tkMacOSXCursor.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:12k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * tkMacOSXCursor.c --
  3.  *
  4.  * This file contains Macintosh specific cursor related routines.
  5.  *
  6.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  7.  * Copyright 2001, Apple Computer, Inc.
  8.  * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * RCS: @(#) $Id: tkMacOSXCursor.c,v 1.4.2.6 2007/06/29 03:22:01 das Exp $
  14.  */
  15. #include "tkMacOSXPrivate.h"
  16. /*
  17.  * There are three different ways to set the cursor on the Mac.
  18.  * The default theme cursors (listed in cursorNames below),
  19.  * color resource cursors, & normal cursors.
  20.  */
  21. #define NONE -1 /* Hidden cursor */
  22. #define THEME 0 /* Theme cursors */
  23. #define ANIMATED 1 /* Animated theme cursors */
  24. #define COLOR 2 /* Cursors of type crsr. */
  25. #define NORMAL 3 /* Cursors of type CURS. */
  26. /*
  27.  * The following data structure contains the system specific data
  28.  * necessary to control Windows cursors.
  29.  */
  30. typedef struct {
  31.     TkCursor info; /* Generic cursor info used by tkCursor.c */
  32.     Handle macCursor; /* Resource containing Macintosh cursor.
  33.  * For theme cursors, this is -1. */
  34.     int type; /* Type of Mac cursor: for theme cursors
  35.  * this is the theme cursor constant,
  36.  * otherwise one of crsr or CURS */
  37.     int count; /* For animating cursors, the count for the
  38.  * cursor. */
  39. } TkMacOSXCursor;
  40. /*
  41.  * The table below is used to map from the name of a predefined cursor
  42.  * to its resource identifier.
  43.  */
  44. struct CursorName {
  45.     const char *name;
  46.     int id;
  47. };
  48. static struct CursorName noneCursorName = {"none", 0};
  49. static struct CursorName themeCursorNames[] = {
  50.     {"arrow", kThemeArrowCursor},
  51.     {"copyarrow", kThemeCopyArrowCursor},
  52.     {"aliasarrow", kThemeAliasArrowCursor},
  53.     {"contextualmenuarrow", kThemeContextualMenuArrowCursor},
  54.     {"ibeam", kThemeIBeamCursor},
  55.     {"text", kThemeIBeamCursor},
  56.     {"xterm", kThemeIBeamCursor},
  57.     {"cross", kThemeCrossCursor},
  58.     {"crosshair", kThemeCrossCursor},
  59.     {"cross-hair", kThemeCrossCursor},
  60.     {"plus", kThemePlusCursor},
  61.     {"closedhand", kThemeClosedHandCursor},
  62.     {"openhand", kThemeOpenHandCursor},
  63.     {"pointinghand", kThemePointingHandCursor},
  64.     {"resizeleft", kThemeResizeLeftCursor},
  65.     {"resizeright", kThemeResizeRightCursor},
  66.     {"resizeleftright", kThemeResizeLeftRightCursor},
  67.     {"resizeup", kThemeResizeUpCursor},
  68.     {"resizedown", kThemeResizeDownCursor},
  69.     {"resizeupdown", kThemeResizeUpDownCursor},
  70.     {"notallowed", kThemeNotAllowedCursor},
  71.     {"poof", kThemePoofCursor},
  72.     {NULL, 0}
  73. };
  74. static struct CursorName animatedThemeCursorNames[] = {
  75.     {"watch", kThemeWatchCursor},
  76.     {"countinguphand", kThemeCountingUpHandCursor},
  77.     {"countingdownhand", kThemeCountingDownHandCursor},
  78.     {"countingupanddownhand", kThemeCountingUpAndDownHandCursor},
  79.     {"spinning", kThemeSpinningCursor},
  80.     {NULL, 0}
  81. };
  82. /*
  83.  * Declarations of static variables used in this file.
  84.  */
  85. static TkMacOSXCursor * gCurrentCursor = NULL; /* A pointer to the current
  86.  * cursor. */
  87. static int gResizeOverride = false; /* A boolean indicating whether
  88.  * we should use the resize
  89.  * cursor during installations. */
  90. static int gTkOwnsCursor = true; /* A boolean indicating whether
  91.  * Tk owns the cursor. If not (for
  92.  * instance, in the case where a Tk
  93.  * window is embedded in another app's
  94.  * window, and the cursor is out of
  95.  * the tk window, we will not attempt
  96.  * to adjust the cursor */
  97. /*
  98.  * Declarations of procedures local to this file
  99.  */
  100. static void FindCursorByName(TkMacOSXCursor *macCursorPtr, const char *string);
  101. /*
  102.  *----------------------------------------------------------------------
  103.  *
  104.  * FindCursorByName --
  105.  *
  106.  * Retrieve a system cursor by name, and fill the macCursorPtr
  107.  * structure. If the cursor cannot be found, the macCursor field
  108.  * will be NULL. The function first attempts to load a color
  109.  * cursor. If that fails it will attempt to load a black & white
  110.  * cursor.
  111.  *
  112.  * Results:
  113.  * Fills the macCursorPtr record.
  114.  *
  115.  * Side effects:
  116.  * None
  117.  *
  118.  *----------------------------------------------------------------------
  119.  */
  120. void
  121. FindCursorByName(
  122.     TkMacOSXCursor *macCursorPtr,
  123.     const char *string)
  124. {
  125.     Handle resource;
  126.     Str255 curName;
  127.     int destWrote, inCurLen;
  128.     Tcl_Encoding encoding;
  129.     inCurLen = strlen(string);
  130.     if (inCurLen > 255) {
  131. return;
  132.     }
  133.     /*
  134.      * macRoman is the encoding that the resource fork uses.
  135.      */
  136.     encoding = Tcl_GetEncoding(NULL, "macRoman");
  137.     Tcl_UtfToExternal(NULL, encoding, string, inCurLen, 0, NULL,
  138.     (char *) &curName[1], 255, NULL, &destWrote, NULL);
  139.     curName[0] = destWrote;
  140.     Tcl_FreeEncoding(encoding);
  141.     resource = GetNamedResource('crsr', curName);
  142.     if (resource) {
  143. short id;
  144. Str255 theName;
  145. ResType theType;
  146. GetResInfo(resource, &id, &theType, theName);
  147. macCursorPtr->macCursor = (Handle) GetCCursor(id);
  148. macCursorPtr->type = COLOR;
  149.     } else {
  150. macCursorPtr->macCursor = GetNamedResource('CURS', curName);
  151. macCursorPtr->type = NORMAL;
  152.     }
  153. }
  154. /*
  155.  *----------------------------------------------------------------------
  156.  *
  157.  * TkGetCursorByName --
  158.  *
  159.  * Retrieve a system cursor by name.
  160.  *
  161.  * Results:
  162.  * Returns a new cursor, or NULL on errors.
  163.  *
  164.  * Side effects:
  165.  * Allocates a new cursor.
  166.  *
  167.  *----------------------------------------------------------------------
  168.  */
  169. TkCursor *
  170. TkGetCursorByName(
  171.     Tcl_Interp *interp, /* Interpreter to use for error reporting. */
  172.     Tk_Window tkwin, /* Window in which cursor will be used. */
  173.     Tk_Uid string) /* Description of cursor. See manual entry
  174.  * for details on legal syntax. */
  175. {
  176.     struct CursorName *namePtr;
  177.     TkMacOSXCursor *macCursorPtr;
  178.     int count = -1;
  179.     macCursorPtr = (TkMacOSXCursor *) ckalloc(sizeof(TkMacOSXCursor));
  180.     macCursorPtr->info.cursor = (Tk_Cursor) macCursorPtr;
  181.     /*
  182.      * To find a cursor we must first determine if it is one of the
  183.      * builtin cursors or the standard arrow cursor. Otherwise, we
  184.      * attempt to load the cursor as a named Mac resource.
  185.      */
  186.     if (strcmp(noneCursorName.name, string) == 0) {
  187. namePtr = &noneCursorName;
  188. macCursorPtr->type = NONE;
  189.     } else {
  190. for (namePtr = themeCursorNames; namePtr->name != NULL; namePtr++) {
  191.     if (strcmp(namePtr->name, string) == 0) {
  192. macCursorPtr->type = THEME;
  193. break;
  194.     }
  195. }
  196.     }
  197.     if (namePtr->name == NULL) {
  198. for (namePtr = animatedThemeCursorNames;
  199. namePtr->name != NULL; namePtr++) {
  200.     int namelen = strlen (namePtr->name);
  201.     if (strncmp(namePtr->name, string, namelen) == 0) {
  202. const char *numPtr = string + namelen;
  203. if (*numPtr) {
  204.     int result = Tcl_GetInt(NULL, numPtr, &count);
  205.     if (result != TCL_OK) {
  206. continue;
  207.     }
  208. }
  209. macCursorPtr->type = ANIMATED;
  210. break;
  211.     }
  212. }
  213.     }
  214.     if (namePtr->name != NULL) {
  215. macCursorPtr->macCursor = (Handle) namePtr;
  216. macCursorPtr->count = count;
  217.     } else {
  218. FindCursorByName(macCursorPtr, string);
  219. if (macCursorPtr->macCursor == NULL) {
  220.     const char **argv;
  221.     int argc;
  222.     /*
  223.      * The user may be trying to specify an XCursor with fore
  224.      * & back colors. We don't want this to be an error, so pick
  225.      * off the first word, and try again.
  226.      */
  227.     if (Tcl_SplitList(interp, string, &argc, &argv) == TCL_OK ) {
  228. if (argc > 1) {
  229.     FindCursorByName(macCursorPtr, argv[0]);
  230. }
  231. ckfree((char *) argv);
  232.     }
  233. }
  234.     }
  235.     if (macCursorPtr->macCursor == NULL) {
  236. ckfree((char *)macCursorPtr);
  237. Tcl_AppendResult(interp, "bad cursor spec "", string, """, NULL);
  238. return NULL;
  239.     } else {
  240. return (TkCursor *) macCursorPtr;
  241.     }
  242. }
  243. /*
  244.  *----------------------------------------------------------------------
  245.  *
  246.  * TkCreateCursorFromData --
  247.  *
  248.  * Creates a cursor from the source and mask bits.
  249.  *
  250.  * Results:
  251.  * Returns a new cursor, or NULL on errors.
  252.  *
  253.  * Side effects:
  254.  * Allocates a new cursor.
  255.  *
  256.  *----------------------------------------------------------------------
  257.  */
  258. TkCursor *
  259. TkCreateCursorFromData(
  260.     Tk_Window tkwin, /* Window in which cursor will be used. */
  261.     CONST char *source, /* Bitmap data for cursor shape. */
  262.     CONST char *mask, /* Bitmap data for cursor mask. */
  263.     int width, int height, /* Dimensions of cursor. */
  264.     int xHot, int yHot, /* Location of hot-spot in cursor. */
  265.     XColor fgColor, /* Foreground color for cursor. */
  266.     XColor bgColor) /* Background color for cursor. */
  267. {
  268.     return NULL;
  269. }
  270. /*
  271.  *----------------------------------------------------------------------
  272.  *
  273.  * TkpFreeCursor --
  274.  *
  275.  * This procedure is called to release a cursor allocated by
  276.  * TkGetCursorByName.
  277.  *
  278.  * Results:
  279.  * None.
  280.  *
  281.  * Side effects:
  282.  * The cursor data structure is deallocated.
  283.  *
  284.  *----------------------------------------------------------------------
  285.  */
  286. void
  287. TkpFreeCursor(
  288.     TkCursor *cursorPtr)
  289. {
  290.     TkMacOSXCursor *macCursorPtr = (TkMacOSXCursor *) cursorPtr;
  291.     switch (macCursorPtr->type) {
  292. case COLOR:
  293.     DisposeCCursor((CCrsrHandle) macCursorPtr->macCursor);
  294.     break;
  295. case NORMAL:
  296.     ReleaseResource(macCursorPtr->macCursor);
  297.     break;
  298.     }
  299.     if (macCursorPtr == gCurrentCursor) {
  300. gCurrentCursor = NULL;
  301.     }
  302. }
  303. /*
  304.  *----------------------------------------------------------------------
  305.  *
  306.  * TkMacOSXInstallCursor --
  307.  *
  308.  * Installs either the current cursor as defined by TkpSetCursor
  309.  * or a resize cursor as the cursor the Macintosh should currently
  310.  * display.
  311.  *
  312.  * Results:
  313.  * None.
  314.  *
  315.  * Side effects:
  316.  * Changes the Macintosh mouse cursor.
  317.  *
  318.  *----------------------------------------------------------------------
  319.  */
  320. void
  321. TkMacOSXInstallCursor(
  322.     int resizeOverride)
  323. {
  324.     TkMacOSXCursor *macCursorPtr = gCurrentCursor;
  325.     CCrsrHandle ccursor;
  326.     CursHandle cursor;
  327.     static unsigned int cursorStep = 0;
  328.     static int cursorHidden = 0;
  329.     int cursorNone = 0;
  330.     gResizeOverride = resizeOverride;
  331.     if (resizeOverride) {
  332. cursor = (CursHandle) GetNamedResource('CURS', "presize");
  333. if (cursor) {
  334.     SetCursor(*cursor);
  335. } else {
  336.     TkMacOSXDbgMsg("Resize cursor failed: %d", ResError());
  337. }
  338.     } else if (macCursorPtr == NULL) {
  339. SetThemeCursor(kThemeArrowCursor);
  340.     } else {
  341. struct CursorName *namePtr;
  342. switch (macCursorPtr->type) {
  343.     case NONE:
  344. if (!cursorHidden) {
  345.     cursorHidden = 1;
  346.     HideCursor();
  347. }
  348. cursorNone = 1;
  349. break;
  350.     case THEME:
  351. namePtr = (struct CursorName *) macCursorPtr->macCursor;
  352. SetThemeCursor(
  353. namePtr->id);
  354. break;
  355.     case ANIMATED:
  356. namePtr = (struct CursorName *) macCursorPtr->macCursor;
  357. if (macCursorPtr->count == -1) {
  358.     SetAnimatedThemeCursor(namePtr->id, cursorStep++);
  359. } else {
  360.     SetAnimatedThemeCursor(namePtr->id, macCursorPtr->count);
  361. }
  362. break;
  363.     case COLOR:
  364. ccursor = (CCrsrHandle) macCursorPtr->macCursor;
  365. SetCCursor(ccursor);
  366. break;
  367.     case NORMAL:
  368. cursor = (CursHandle) macCursorPtr->macCursor;
  369. SetCursor(*cursor);
  370. break;
  371. }
  372.     }
  373.     if (cursorHidden && !cursorNone) {
  374. cursorHidden = 0;
  375. ShowCursor();
  376.     }
  377. }
  378. /*
  379.  *----------------------------------------------------------------------
  380.  *
  381.  * TkpSetCursor --
  382.  *
  383.  * Set the current cursor and install it.
  384.  *
  385.  * Results:
  386.  * None.
  387.  *
  388.  * Side effects:
  389.  * Changes the current cursor.
  390.  *
  391.  *----------------------------------------------------------------------
  392.  */
  393. void
  394. TkpSetCursor(
  395.     TkpCursor cursor)
  396. {
  397.     int cursorChanged = 1;
  398.     if (!gTkOwnsCursor) {
  399. return;
  400.     }
  401.     if (cursor == None) {
  402. /*
  403.  * This is a little tricky. We can't really tell whether
  404.  * gCurrentCursor is NULL because it was NULL last time around
  405.  * or because we just freed the current cursor. So if the input
  406.  * cursor is NULL, we always need to reset it, we can't trust the
  407.  * cursorChanged logic.
  408.  */
  409. gCurrentCursor = NULL;
  410.     } else {
  411. if (gCurrentCursor == (TkMacOSXCursor *) cursor) {
  412.     cursorChanged = 0;
  413. }
  414. gCurrentCursor = (TkMacOSXCursor *) cursor;
  415.     }
  416.     if (Tk_MacOSXIsAppInFront() && cursorChanged) {
  417. TkMacOSXInstallCursor(gResizeOverride);
  418.     }
  419. }
  420. /*
  421.  *----------------------------------------------------------------------
  422.  *
  423.  * Tk_MacOSXTkOwnsCursor --
  424.  *
  425.  * Sets whether Tk has the right to adjust the cursor.
  426.  *
  427.  * Results:
  428.  * None.
  429.  *
  430.  * Side effects:
  431.  * May keep Tk from changing the cursor.
  432.  *
  433.  *----------------------------------------------------------------------
  434.  */
  435. void
  436. Tk_MacOSXTkOwnsCursor(
  437.     int tkOwnsIt)
  438. {
  439.     gTkOwnsCursor = tkOwnsIt;
  440. }