diff options
Diffstat (limited to 'carbon/tkMacOSXDebug.c')
-rw-r--r-- | carbon/tkMacOSXDebug.c | 643 |
1 files changed, 643 insertions, 0 deletions
diff --git a/carbon/tkMacOSXDebug.c b/carbon/tkMacOSXDebug.c new file mode 100644 index 0000000..e007a01 --- /dev/null +++ b/carbon/tkMacOSXDebug.c @@ -0,0 +1,643 @@ +/* + * tkMacOSXDebug.c -- + * + * Implementation of Macintosh specific functions for debugging MacOS + * events, regions, etc... + * + * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net> + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * The following terms apply to all files originating from Apple + * Computer, Inc. ("Apple") and associated with the software + * unless explicitly disclaimed in individual files. + * + * + * Apple hereby grants permission to use, copy, modify, + * distribute, and license this software and its documentation + * for any purpose, provided that existing copyright notices are + * retained in all copies and that this notice is included + * verbatim in any distributions. No written agreement, license, + * or royalty fee is required for any of the authorized + * uses. Modifications to this software may be copyrighted by + * their authors and need not follow the licensing terms + * described here, provided that the new terms are clearly + * indicated on the first page of each file where they apply. + * + * + * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE + * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF + * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, + * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND + * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS + * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE + * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE + * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * GOVERNMENT USE: If you are acquiring this software on behalf + * of the U.S. government, the Government shall have only + * "Restricted Rights" in the software and related documentation + * as defined in the Federal Acquisition Regulations (FARs) in + * Clause 52.227.19 (c) (2). If you are acquiring the software + * on behalf of the Department of Defense, the software shall be + * classified as "Commercial Computer Software" and the + * Government shall have only "Restricted Rights" as defined in + * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the + * foregoing, the authors grant the U.S. Government and others + * acting in its behalf permission to use and distribute the + * software in accordance with the terms specified in this + * license. + */ + +#include "tkMacOSXPrivate.h" +#include "tkMacOSXDebug.h" + +#ifdef TK_MAC_DEBUG + +typedef struct { + EventKind kind; + const char * name; +} MyEventName; + +typedef struct { + EventClass c; + MyEventName * names; +} MyEventNameList; + +static MyEventName windowEventNames [] = { + { kEventWindowUpdate,"Update"}, + { kEventWindowDrawContent,"DrawContent"}, + { kEventWindowActivated,"Activated"}, + { kEventWindowDeactivated,"Deactivated"}, + { kEventWindowGetClickActivation,"GetClickActivation"}, + { kEventWindowShowing,"Showing"}, + { kEventWindowHiding,"Hiding"}, + { kEventWindowShown,"Shown"}, + { kEventWindowHidden,"Hidden"}, + { kEventWindowBoundsChanging,"BoundsChanging"}, + { kEventWindowBoundsChanged,"BoundsChanged"}, + { kEventWindowResizeStarted,"ResizeStarted"}, + { kEventWindowResizeCompleted,"ResizeCompleted"}, + { kEventWindowDragStarted,"DragStarted"}, + { kEventWindowDragCompleted,"DragCompleted"}, + { kEventWindowClickDragRgn,"ClickDragRgn"}, + { kEventWindowClickResizeRgn,"ClickResizeRgn"}, + { kEventWindowClickCollapseRgn,"ClickCollapseRgn"}, + { kEventWindowClickCloseRgn,"ClickCloseRgn"}, + { kEventWindowClickZoomRgn,"ClickZoomRgn"}, + { kEventWindowClickContentRgn,"ClickContentRgn"}, + { kEventWindowClickProxyIconRgn,"ClickProxyIconRgn"}, + { kEventWindowCursorChange,"CursorChange" }, + { kEventWindowCollapse,"Collapse"}, + { kEventWindowCollapsed,"Collapsed"}, + { kEventWindowCollapseAll,"CollapseAll"}, + { kEventWindowExpand,"Expand"}, + { kEventWindowExpanded,"Expanded"}, + { kEventWindowExpandAll,"ExpandAll"}, + { kEventWindowCollapse,"Collapse"}, + { kEventWindowClose,"Close"}, + { kEventWindowClosed,"Closed"}, + { kEventWindowCloseAll,"CloseAll"}, + { kEventWindowZoom,"Zoom"}, + { kEventWindowZoomed,"Zoomed"}, + { kEventWindowZoomAll,"ZoomAll"}, + { kEventWindowContextualMenuSelect,"ContextualMenuSelect"}, + { kEventWindowPathSelect,"PathSelect"}, + { kEventWindowGetIdealSize,"GetIdealSize"}, + { kEventWindowGetMinimumSize,"GetMinimumSize"}, + { kEventWindowGetMaximumSize,"GetMaximumSize"}, + { kEventWindowConstrain,"Constrain"}, + { kEventWindowHandleContentClick,"HandleContentClick"}, + { kEventWindowProxyBeginDrag,"ProxyBeginDra}"}, + { kEventWindowProxyEndDrag,"ProxyEndDrag"}, + { kEventWindowFocusAcquired,"FocusAcquired"}, + { kEventWindowFocusRelinquish,"FocusRelinquish"}, + { kEventWindowDrawFrame,"DrawFrame"}, + { kEventWindowDrawPart,"DrawPart"}, + { kEventWindowGetRegion,"GetRegion"}, + { kEventWindowHitTest,"HitTest"}, + { kEventWindowInit,"Init"}, + { kEventWindowDispose,"Dispose"}, + { kEventWindowDragHilite,"DragHilite"}, + { kEventWindowModified,"Modified"}, + { kEventWindowSetupProxyDragImage,"SetupProxyDragImage"}, + { kEventWindowStateChanged,"StateChanged"}, + { kEventWindowMeasureTitle,"MeasureTitle"}, + { kEventWindowDrawGrowBox,"DrawGrowBox"}, + { kEventWindowGetGrowImageRegion,"GetGrowImageRegion"}, + { kEventWindowPaint,"Paint"}, + { 0, NULL }, +}; + +static MyEventName mouseEventNames [] = { + { kEventMouseMoved, "Moved"}, + { kEventMouseUp, "Up"}, + { kEventMouseDown, "Down"}, + { kEventMouseDragged, "Dragged"}, + { kEventMouseWheelMoved, "WheelMoved"}, + { 0, NULL} +}; + +static MyEventName keyboardEventNames [] = { + { kEventRawKeyDown, "Down"}, + { kEventRawKeyRepeat, "Repeat"}, + { kEventRawKeyUp, "Up"}, + { kEventRawKeyModifiersChanged, "ModifiersChanged"}, + { kEventHotKeyPressed, "HotKeyPressed"}, + { kEventHotKeyReleased, "HotKeyReleased"}, + { 0, NULL} +}; + +static MyEventName appEventNames [] = { + { kEventAppActivated, "Activated"}, + { kEventAppDeactivated, "Deactivated"}, + { kEventAppQuit, "Quit"}, + { kEventAppLaunchNotification, "LaunchNotification"}, + { kEventAppLaunched, "Launched"}, + { kEventAppTerminated, "Terminated"}, + { kEventAppFrontSwitched, "FrontSwitched"}, + { 0, NULL} +}; + +static MyEventName menuEventNames [] = { + { kEventMenuBeginTracking, "BeginTracking"}, + { kEventMenuEndTracking, "EndTracking"}, + { kEventMenuChangeTrackingMode, "ChangeTrackingMode"}, + { kEventMenuOpening, "Opening"}, + { kEventMenuClosed, "Closed"}, + { kEventMenuTargetItem, "TargetItem"}, + { kEventMenuMatchKey, "MatchKey"}, + { kEventMenuEnableItems, "EnableItems"}, + { kEventMenuDispose, "Dispose"}, + { 0, NULL } +}; + +static MyEventName controlEventNames [] = { + { kEventControlInitialize, "Initialize" }, + { kEventControlDispose, "Dispose" }, + { kEventControlGetOptimalBounds, "GetOptimalBounds" }, + { kEventControlHit, "Hit" }, + { kEventControlSimulateHit, "SimulateHit" }, + { kEventControlHitTest, "HitTest" }, + { kEventControlDraw, "Draw" }, + { kEventControlApplyBackground, "ApplyBackground" }, + { kEventControlApplyTextColor, "ApplyTextColor" }, + { kEventControlSetFocusPart, "SetFocusPart" }, + { kEventControlGetFocusPart, "GetFocusPart" }, + { kEventControlActivate, "Activate" }, + { kEventControlDeactivate, "Deactivate" }, + { kEventControlSetCursor, "SetCursor" }, + { kEventControlContextualMenuClick, "ContextualMenuClick" }, + { kEventControlClick, "Click" }, + { kEventControlTrack, "Track" }, + { kEventControlGetScrollToHereStartPoint, "GetScrollToHereStartPoint" }, + { kEventControlGetIndicatorDragConstraint, "GetIndicatorDragConstraint" }, + { kEventControlIndicatorMoved, "IndicatorMoved" }, + { kEventControlGhostingFinished, "GhostingFinished" }, + { kEventControlGetActionProcPart, "GetActionProcPart" }, + { kEventControlGetPartRegion, "GetPartRegion" }, + { kEventControlGetPartBounds, "GetPartBounds" }, + { kEventControlSetData, "SetData" }, + { kEventControlGetData, "GetData" }, + { kEventControlValueFieldChanged, "ValueFieldChanged" }, + { kEventControlAddedSubControl, "AddedSubControl" }, + { kEventControlRemovingSubControl, "RemovingSubControl" }, + { kEventControlBoundsChanged, "BoundsChanged" }, + { kEventControlOwningWindowChanged, "OwningWindowChanged" }, + { kEventControlArbitraryMessage, "ArbitraryMessage" }, + { 0, NULL } +}; + +static MyEventName commandEventNames [] = { + { kEventCommandProcess, "Process" }, + { kEventCommandUpdateStatus, "UpdateStatus" }, + { 0, NULL } +}; + +static MyEventNameList eventNameList [] = { + { kEventClassWindow, windowEventNames }, + { kEventClassMouse, mouseEventNames }, + { kEventClassKeyboard, keyboardEventNames }, + { kEventClassApplication, appEventNames }, + { kEventClassMenu, menuEventNames }, + { kEventClassControl, controlEventNames }, + { kEventClassCommand, commandEventNames }, + { 0, NULL} +}; + +#ifdef TK_MACOSXDEBUG_UNUSED +static MyEventName classicEventNames [] = { + { nullEvent,"nullEvent" }, + { mouseDown,"mouseDown" }, + { mouseUp,"mouseUp" }, + { keyDown,"keyDown" }, + { keyUp,"keyUp" }, + { autoKey,"autoKey" }, + { updateEvt,"updateEvt" }, + { diskEvt,"diskEvt" }, + { activateEvt,"activateEvt" }, + { osEvt,"osEvt" }, + { kHighLevelEvent,"kHighLevelEvent" }, + { 0, NULL } +}; +#endif /* TK_MACOSXDEBUG_UNUSED */ + +MODULE_SCOPE char * +TkMacOSXCarbonEventToAscii( + EventRef eventRef) +{ + EventClass eventClass; + EventKind eventKind; + MyEventNameList * list = eventNameList; + MyEventName * names = NULL; + static char str[256]; + char *buf = str; + int *iPtr = (int*)str; + int found = 0; + + eventClass = GetEventClass(eventRef); + eventKind = GetEventKind(eventRef); + + *iPtr = eventClass; + buf[4] = 0; + strcat(buf, " "); + buf += strlen(buf); + while (list->names && (!names) ) { + if (eventClass == list->c) { + names = list -> names; + } else { + list++; + } + } + while (names && names->name) { + if (eventKind == names->kind) { + snprintf(buf, 250, "%-20s", names->name); + break; + } else { + names++; + } + } + if (!found) { + snprintf(buf, 250, "%-20d", eventKind); + } + return str; +} + +#ifdef TK_MACOSXDEBUG_UNUSED +MODULE_SCOPE char * +TkMacOSXCarbonEventKindToAscii( + EventRef eventRef, + char *buf) +{ + EventClass eventClass; + EventKind eventKind; + MyEventNameList *list = eventNameList; + MyEventName *names = NULL; + int found = 0; + + eventClass = GetEventClass(eventRef); + eventKind = GetEventKind(eventRef); + while (list->names && (!names) ) { + if (eventClass == list -> c) { + names = list -> names; + } else { + list++; + } + } + if (names) { + found = 0; + while (names->name && !found) { + if (eventKind == names->kind) { + sprintf(buf,"%s",names->name); + found = 1; + } else { + names++; + } + } + } + if (!found) { + sprintf(buf,"%d", eventKind); + } else { + sprintf(buf,"%d", eventKind); + } + return buf; +} + +MODULE_SCOPE char * +TkMacOSXClassicEventToAscii( + EventRecord *eventPtr, + char *buf) +{ + MyEventName *names = NULL; + int found = 0; + names = classicEventNames; + while (names -> name && !found) { + if (eventPtr->what == names->kind) { + int *iPtr; + char cBuf[8]; + + iPtr = (int *) &cBuf; + *iPtr = eventPtr->message; + cBuf[4] = 0; + sprintf(buf, "%-16s %08x %04x %s", names->name, + (int) eventPtr->message, eventPtr->modifiers, cBuf); + found = 1; + } else { + names++; + } + } + if (!found) { + sprintf(buf,"%-16d %08x %08x, %s", eventPtr->what, + (int) eventPtr->message, eventPtr->modifiers, buf); + } + return buf; +} + +MODULE_SCOPE void +TkMacOSXPrintPoint( + char *tag, + Point *p) +{ + TkMacOSXDbgMsg("%s %4d %4d", tag,p->h,p->v ); +} + +MODULE_SCOPE void +TkMacOSXPrintRect( + char *tag, + Rect *r) +{ + TkMacOSXDbgMsg("%s %4d %4d %4d %4d (%dx%d)", + tag, r->left, r->top, r->right, r->bottom, + r->right - r->left + 1, r->bottom - r->top + 1); +} + +MODULE_SCOPE void +TkMacOSXPrintRegion( + char *tag, + RgnHandle rgn) +{ + Rect r; + + GetRegionBounds(rgn,&r); + TkMacOSXPrintRect(tag,&r); +} + +MODULE_SCOPE void +TkMacOSXPrintWindowTitle( + char *tag, + WindowRef window) +{ + Str255 title; + + GetWTitle(window, title); + title[title[0] + 1] = 0; + TkMacOSXDbgMsg("%s %s", tag, title+1); +} + +typedef struct { + int msg; + char *name; +} MsgName; + +static MsgName msgNames [] = { + { kMenuDrawMsg, "Draw"}, + { kMenuSizeMsg, "Size"}, + { kMenuPopUpMsg, "PopUp"}, + { kMenuCalcItemMsg, "CalcItem" }, + { kMenuThemeSavvyMsg, "ThemeSavvy"}, + { kMenuInitMsg, "Init" }, + { kMenuDisposeMsg, "Dispose" }, + { kMenuFindItemMsg, "FindItem" }, + { kMenuHiliteItemMsg, "HiliteItem" }, + { kMenuDrawItemsMsg, "DrawItems" }, + { -1, NULL } +}; + +MODULE_SCOPE char * +TkMacOSXMenuMessageToAscii( + int msg, + char *s) +{ + MsgName *msgNamePtr; + + for (msgNamePtr=msgNames ; msgNamePtr->name ; msgNamePtr++) { + if (msgNamePtr->msg == msg) { + strcpy(s,msgNamePtr->name); + return s; + } + } + sprintf(s, "unknown : %d", msg); + return s; +} + +static MsgName trackingNames [] = { + { kMouseTrackingMousePressed , "MousePressed " }, + { kMouseTrackingMouseReleased , "MouseReleased " }, + { kMouseTrackingMouseExited , "MouseExited " }, + { kMouseTrackingMouseEntered , "MouseEntered " }, + { kMouseTrackingMouseMoved , "MouseMoved " }, + { kMouseTrackingKeyModifiersChanged, "KeyModifiersChanged" }, + { kMouseTrackingUserCancelled , "UserCancelled " }, + { kMouseTrackingTimedOut , "TimedOut " }, + { -1, NULL } +}; + +MODULE_SCOPE char * +TkMacOSXMouseTrackingResultToAscii( + MouseTrackingResult r, + char *buf) +{ + MsgName *namePtr; + + for (namePtr = trackingNames; namePtr->name; namePtr++) { + if (namePtr->msg == r) { + strcpy(buf, namePtr->name); + return buf; + } + } + sprintf(buf, "Unknown mouse tracking result : %d", r); + return buf; +} +#endif /* TK_MACOSXDEBUG_UNUSED */ + +MODULE_SCOPE void +TkMacOSXDebugFlashRegion( + Drawable d, + HIShapeRef rgn) +{ + TkMacOSXInitNamedDebugSymbol(HIToolbox, int, QDDebugFlashRegion, + CGrafPtr port, RgnHandle region); + CFShow(rgn); + if (d && rgn && QDDebugFlashRegion && !HIShapeIsEmpty(rgn)) { + CGrafPtr port = TkMacOSXGetDrawablePort(d); + + if (port) { + static RgnHandle qdRgn = NULL; + + if (!qdRgn) { + qdRgn = NewRgn(); + } + ChkErr(HIShapeGetAsQDRgn, rgn, qdRgn); + + /* + * Carbon-internal region flashing SPI (c.f. Technote 2124) + */ + + QDDebugFlashRegion(port, qdRgn); + SetEmptyRgn(qdRgn); + } + } +} + +#include <mach-o/dyld.h> +#include <mach-o/nlist.h> + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetNamedDebugSymbol -- + * + * Dynamically acquire address of a named symbol from a loaded dynamic + * library, so that we can use API that may not be available on all OS + * versions. For debugging purposes, if we cannot find the symbol with + * the usual dynamic library APIs, we manually walk the symbol table of + * the loaded library. This allows access to unexported symbols such as + * private_extern internal debugging functions. If module is NULL or the + * empty string, search all loaded libraries (could be very expensive and + * should be avoided). + * + * THIS FUCTION IS ONLY TO BE USED FOR DEBUGGING PURPOSES, IT MAY BREAK + * UNEXPECTEDLY IN THE FUTURE! + * + * Results: + * Address of given symbol or NULL if unavailable. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +MODULE_SCOPE void * +TkMacOSXGetNamedDebugSymbol( + const char *module, + const char *symbol) +{ + void *addr = TkMacOSXGetNamedSymbol(module, symbol); + +#ifndef __LP64__ + if (!addr) { + const struct mach_header *mh = NULL; + uint32_t i, n = _dyld_image_count(); + size_t module_len = 0; + + if (module && *module) { + module_len = strlen(module); + } + for (i = 0; i < n; i++) { + if (module && *module) { + /* Find image with given module name */ + char *name; + const char *path = _dyld_get_image_name(i); + + if (!path) { + continue; + } + name = strrchr(path, '/') + 1; + if (strncmp(name, module, module_len) != 0) { + continue; + } + } + mh = _dyld_get_image_header(i); + if (mh) { + struct load_command *lc; + struct symtab_command *st = NULL; + struct segment_command *sg = NULL; + uint32_t j, m, nsect = 0, txtsectx = 0; + + lc = (struct load_command*)((const char*) mh + + sizeof(struct mach_header)); + m = mh->ncmds; + for (j = 0; j < m; j++) { + /* Find symbol table and index of __text section */ + if (lc->cmd == LC_SEGMENT) { + /* Find last segment before symbol table */ + sg = (struct segment_command*) lc; + if (!txtsectx) { + /* Count total sections until (__TEXT, __text) */ + uint32_t k, ns = sg->nsects; + + if (strcmp(sg->segname, SEG_TEXT) == 0) { + struct section *s = (struct section *)( + (char *)sg + + sizeof(struct segment_command)); + + for(k = 0; k < ns; k++) { + if (strcmp(s->sectname, SECT_TEXT) == 0) { + txtsectx = nsect+k+1; + break; + } + s++; + } + } + nsect += ns; + } + } else if (!st && lc->cmd == LC_SYMTAB) { + st = (struct symtab_command *) lc; + break; + } + lc = (struct load_command *)((char *) lc + lc->cmdsize); + } + if (st && sg && txtsectx) { + intptr_t base, slide = _dyld_get_image_vmaddr_slide(i); + char *strings; + struct nlist *sym; + uint32_t strsize = st->strsize; + int32_t strx; + + /* + * Offset file positions by difference to actual position + * in memory of last segment before symbol table: + */ + + base = (intptr_t) sg->vmaddr + slide - sg->fileoff; + strings = (char *) (base + st->stroff); + sym = (struct nlist *) (base + st->symoff); + m = st->nsyms; + for (j = 0; j < m; j++) { + /* Find symbol with given name in __text section */ + strx = sym->n_un.n_strx; + if ((sym->n_type & N_TYPE) == N_SECT && + sym->n_sect == txtsectx && + strx > 0 && (uint32_t) strx < strsize && + strcmp(strings + strx, symbol) == 0) { + addr = (char*) sym->n_value + slide; + break; + } + sym++; + } + } + } + if (module && *module) { + /* If given a module name, only search corresponding image */ + break; + } + } + } +#endif /* __LP64__ */ + return addr; +} +#endif /* TK_MAC_DEBUG */ + +/* + * Local Variables: + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |