summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--doc/cursors.n8
-rw-r--r--tests/cursor.test57
-rw-r--r--unix/tkUnixCursor.c387
-rw-r--r--win/rc/cursor9a.curbin0 -> 326 bytes
-rw-r--r--win/rc/tk_base.rc4
6 files changed, 403 insertions, 72 deletions
diff --git a/ChangeLog b/ChangeLog
index 9de8803..38923b7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2006-12-16 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * doc/cursors.n: Mention "none" in supported
+ cursor list. Fix comment that incorrectly
+ claims that the Win32 "no" cursor hides
+ the cursor.
+ * tests/cursor.test: Test "none" cursor.
+ * unix/tkUnixCursor.c (CreateCursorFromTableOrFile,
+ TkGetCursorByName): Define a table of Tk cursors
+ that is searched in addition to the X cursor
+ table. A Tk cursor is loaded from a data string
+ and works with the same options as the built
+ in X cursors. This code makes it possible to
+ use "none" as a cursor name under Unix.
+ * win/rc/cursor9a.cur: Added none Win32 cursor.
+ * win/rc/tk_base.rc: Define a built-in Win32
+ cursor named "none".
+ [Patch 1615427]
+
2006-12-14 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/ttkButton.c, generic/ttk/ttkElements.c,
diff --git a/doc/cursors.n b/doc/cursors.n
index 0855f5f..fba41bb 100644
--- a/doc/cursors.n
+++ b/doc/cursors.n
@@ -2,7 +2,7 @@
'\" Copyright (c) 1998-2000 by Scriptics Corporation.
'\" All rights reserved.
'\"
-'\" RCS: @(#) $Id: cursors.n,v 1.3 2002/11/15 15:35:55 dkf Exp $
+'\" RCS: @(#) $Id: cursors.n,v 1.4 2006/12/17 00:43:06 mdejong Exp $
'\"
'\"
.so man.macros
@@ -62,6 +62,7 @@ lr_angle
man
middlebutton
mouse
+none
pencil
pirate
plus
@@ -96,6 +97,8 @@ umbrella
ur_angle
watch
xterm
+
+The \fBnone\fR cursor can be specified to eliminate the cursor.
.CE
.SH "PORTABILITY ISSUES"
@@ -111,6 +114,7 @@ crosshair
fleur
ibeam
icon
+none
sb_h_double_arrow
sb_v_double_arrow
watch
@@ -128,7 +132,6 @@ size_we
uparrow
wait
.CE
-The \fBno\fR cursor can be specified to eliminate the cursor.
.RE
.TP
@@ -140,6 +143,7 @@ arrow
cross
crosshair
ibeam
+none
plus
watch
xterm
diff --git a/tests/cursor.test b/tests/cursor.test
index ebe58e1..d5dabcf 100644
--- a/tests/cursor.test
+++ b/tests/cursor.test
@@ -6,7 +6,7 @@
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
#
-# RCS: @(#) $Id: cursor.test,v 1.15 2004/12/07 10:07:59 dkf Exp $
+# RCS: @(#) $Id: cursor.test,v 1.16 2006/12/17 00:43:06 mdejong Exp $
package require tcltest 2.1
eval tcltest::configure $argv
@@ -228,6 +228,61 @@ foreach {testName cursor} {
} -result {}
}
+# Test cursor named "none", it is not defined in
+# the X cursor table. It is defined in a Tk specific
+# table of named cursors and should be available on
+# all platforms.
+
+test cursor-6.80 {} -setup {
+ button .b -text CButton
+} -body {
+ .b configure -cursor none
+ .b cget -cursor
+} -cleanup {
+ destroy .b
+} -result none
+
+test cursor-6.81 {} -setup {
+ button .b -text CButton
+} -body {
+ .b configure -cursor none
+ .b configure -cursor {}
+ .b cget -cursor
+} -cleanup {
+ destroy .b
+} -result {}
+
+test cursor-6.82 {} -setup {
+ button .b -text CButton
+} -body {
+ .b configure -cursor none
+ .b configure -cursor {}
+ .b configure -cursor none
+ .b cget -cursor
+} -cleanup {
+ destroy .b
+} -result none
+
+test cursor-6.83 {} -setup {
+ button .b -text CButton
+} -body {
+ # Setting fg and bg does nothing for the none cursor
+ # because it displays no fg or bg pixels.
+ set results [list]
+ .b configure -cursor none
+ lappend results [.b cget -cursor]
+ .b configure -cursor {none blue}
+ lappend results [.b cget -cursor]
+ .b configure -cursor {none blue green}
+ lappend results [.b cget -cursor]
+ .b configure -cursor {}
+ lappend results [.b cget -cursor]
+ set results
+} -cleanup {
+ destroy .b
+ unset results
+} -result {none {none blue} {none blue green} {}}
+
# -------------------------------------------------------------------------
# Check the Windows specific cursors
diff --git a/unix/tkUnixCursor.c b/unix/tkUnixCursor.c
index 858025c..e3873a7 100644
--- a/unix/tkUnixCursor.c
+++ b/unix/tkUnixCursor.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUnixCursor.c,v 1.7 2005/10/21 01:51:45 dkf Exp $
+ * RCS: @(#) $Id: tkUnixCursor.c,v 1.8 2006/12/17 00:43:06 mdejong Exp $
*/
#include "tkPort.h"
@@ -116,12 +116,89 @@ static struct CursorName {
};
/*
+ * The table below is used to map from a cursor name to the data
+ * that defines the cursor. This table is used for cursors defined
+ * by Tk that don't exist in the X cursor table.
+ */
+
+#define CURSOR_NONE_DATA \
+"#define none_width 1
+ #define none_height 1
+ #define none_x_hot 0
+ #define none_y_hot 0
+ static unsigned char none_bits[] = {
+ 0x00};"
+
+
+/* Define test cursor to check that mask
+ * fg and bg color settings are working.
+ *
+ * . configure -cursor {center_ptr green red}
+ *
+ * . configure -cursor {@myarrow.xbm myarrow-mask.xbm green red}
+ *
+ * . configure -cursor {myarrow green red}
+ */
+
+/*#define DEFINE_MYARROW_CURSOR*/
+
+
+#ifdef DEFINE_MYARROW_CURSOR
+
+#define CURSOR_MYARROW_DATA \
+"#define myarrow_width 16
+#define myarrow_height 16
+#define myarrow_x_hot 7
+#define myarrow_y_hot 0
+static unsigned char myarrow_bits[] = {
+ 0x7f, 0xff, 0xbf, 0xfe, 0xdf, 0xfd, 0xef, 0xfb, 0xf7, 0xf7, 0xfb, 0xef,
+ 0xfd, 0xdf, 0xfe, 0xbf, 0x80, 0x00, 0xbf, 0xfe, 0xbf, 0xfe, 0xbf, 0xfe,
+ 0xbf, 0xfe, 0xbf, 0xfe, 0xbf, 0xfe, 0x3f, 0xfe};"
+
+#define CURSOR_MYARROW_MASK \
+"#define myarrow-mask_width 16
+#define myarrow-mask_height 16
+#define myarrow-mask_x_hot 7
+#define myarrow-mask_y_hot 0
+static unsigned char myarrow-mask_bits[] = {
+ 0x80, 0x00, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f, 0xfc, 0x1f,
+ 0xfe, 0x3f, 0xff, 0x7f, 0xff, 0xff, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,
+ 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01};"
+
+#endif /* DEFINE_MYARROW_CURSOR */
+
+
+static struct TkCursorName {
+ char *name;
+ char *data;
+ char *mask;
+} tkCursorNames[] = {
+
+ {"none", CURSOR_NONE_DATA, NULL},
+
+#ifdef DEFINE_MYARROW_CURSOR
+ {"myarrow", CURSOR_MYARROW_DATA, CURSOR_MYARROW_MASK},
+#endif /* DEFINE_MYARROW_CURSOR */
+
+ {NULL, NULL, NULL}
+};
+
+/*
* Font to use for cursors:
*/
#ifndef CURSORFONT
#define CURSORFONT "cursor"
#endif
+
+MODULE_SCOPE Cursor CreateCursorFromTableOrFile(
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ int argc,
+ CONST char **argv,
+ struct TkCursorName *tkCursorPtr);
+
+
/*
*----------------------------------------------------------------------
@@ -152,9 +229,9 @@ TkGetCursorByName(
Cursor cursor = None;
int argc;
CONST char **argv = NULL;
- Pixmap source = None;
- Pixmap mask = None;
Display *display = Tk_Display(tkwin);
+ int inTkTable = 0;
+ struct TkCursorName* tkCursorPtr = NULL;
if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) {
return NULL;
@@ -162,7 +239,28 @@ TkGetCursorByName(
if (argc == 0) {
goto badString;
}
+
+ /*
+ * Check Tk specific table of cursor names. The
+ * cursor names don't overlap with cursors defined
+ * in the X table so search order does not matter.
+ */
+
if (argv[0][0] != '@') {
+ for ( tkCursorPtr = tkCursorNames; ; tkCursorPtr++) {
+ if (tkCursorPtr->name == NULL) {
+ tkCursorPtr = NULL;
+ break;
+ }
+ if ((tkCursorPtr->name[0] == argv[0][0]) &&
+ (strcmp(tkCursorPtr->name, argv[0]) == 0)) {
+ inTkTable = 1;
+ break;
+ }
+ }
+ }
+
+ if ((argv[0][0] != '@') && !inTkTable) {
XColor fg, bg;
unsigned int maskIndex;
register struct CursorName *namePtr;
@@ -188,6 +286,7 @@ TkGetCursorByName(
break;
}
}
+
maskIndex = namePtr->shape + 1;
if (argc == 1) {
fg.red = fg.green = fg.blue = 0;
@@ -220,15 +319,11 @@ TkGetCursorByName(
dispPtr->cursorFont, namePtr->shape, maskIndex,
&fg, &bg);
} else {
- int width, height, maskWidth, maskHeight;
- int xHot, yHot, dummy1, dummy2;
- XColor fg, bg;
-
/*
* Prevent file system access in safe interpreters.
*/
- if (Tcl_IsSafe(interp)) {
+ if (!inTkTable && Tcl_IsSafe(interp)) {
Tcl_AppendResult(interp, "can't get cursor from a file in",
" a safe interpreter", NULL);
cursorPtr = NULL;
@@ -236,65 +331,22 @@ TkGetCursorByName(
}
/*
- * The cursor is to be created by reading bitmap files. There should
- * be either two elements in the list (source, color) or four (source
- * mask fg bg).
+ * If the cursor is to be created from bitmap files, then there
+ * should be either two elements in the list (source, color)
+ * or four (source mask fg bg). A cursor defined in the Tk
+ * table accepts the same arguments as an X cursor.
*/
- if ((argc != 2) && (argc != 4)) {
+ if (inTkTable && (argc != 1) && (argc != 2) && (argc != 3)) {
goto badString;
}
- if (TkReadBitmapFile(display,
- RootWindowOfScreen(Tk_Screen(tkwin)), &argv[0][1],
- (unsigned int *) &width, (unsigned int *) &height,
- &source, &xHot, &yHot) != BitmapSuccess) {
- Tcl_AppendResult(interp, "cleanup reading bitmap file \"",
- &argv[0][1], "\"", NULL);
- goto cleanup;
- }
- if ((xHot < 0) || (yHot < 0) || (xHot >= width) || (yHot >= height)) {
- Tcl_AppendResult(interp, "bad hot spot in bitmap file \"",
- &argv[0][1], "\"", NULL);
- goto cleanup;
- }
- if (argc == 2) {
- if (XParseColor(display, Tk_Colormap(tkwin), argv[1], &fg) == 0) {
- Tcl_AppendResult(interp, "invalid color name \"",
- argv[1], "\"", NULL);
- goto cleanup;
- }
- cursor = XCreatePixmapCursor(display, source, source,
- &fg, &fg, (unsigned) xHot, (unsigned) yHot);
- } else {
- if (TkReadBitmapFile(display,
- RootWindowOfScreen(Tk_Screen(tkwin)), argv[1],
- (unsigned int *) &maskWidth, (unsigned int *) &maskHeight,
- &mask, &dummy1, &dummy2) != BitmapSuccess) {
- Tcl_AppendResult(interp, "cleanup reading bitmap file \"",
- argv[1], "\"", NULL);
- goto cleanup;
- }
- if ((maskWidth != width) && (maskHeight != height)) {
- Tcl_SetResult(interp,
- "source and mask bitmaps have different sizes",
- TCL_STATIC);
- goto cleanup;
- }
- if (XParseColor(display, Tk_Colormap(tkwin), argv[2],
- &fg) == 0) {
- Tcl_AppendResult(interp, "invalid color name \"", argv[2],
- "\"", NULL);
- goto cleanup;
- }
- if (XParseColor(display, Tk_Colormap(tkwin), argv[3],
- &bg) == 0) {
- Tcl_AppendResult(interp, "invalid color name \"", argv[3],
- "\"", NULL);
- goto cleanup;
- }
- cursor = XCreatePixmapCursor(display, source, mask,
- &fg, &bg, (unsigned) xHot, (unsigned) yHot);
+
+ if (!inTkTable && (argc != 2) && (argc != 4)) {
+ goto badString;
}
+
+ cursor = CreateCursorFromTableOrFile(interp, tkwin,
+ argc, argv, tkCursorPtr);
}
if (cursor != None) {
@@ -307,12 +359,6 @@ TkGetCursorByName(
if (argv != NULL) {
ckfree((char *) argv);
}
- if (source != None) {
- Tk_FreePixmap(display, source);
- }
- if (mask != None) {
- Tk_FreePixmap(display, mask);
- }
return (TkCursor *) cursorPtr;
badString:
@@ -322,6 +368,211 @@ TkGetCursorByName(
Tcl_AppendResult(interp, "bad cursor spec \"", string, "\"", NULL);
return NULL;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateCursorFromTableOrFile --
+ *
+ * Create a cursor defined in a file or the Tk static cursor table.
+ * A cursor defined in a file starts with the '@' character. This
+ * method assumes that the number of arguments in argv has been
+ * validated already.
+ *
+ * Results:
+ * Returns a new cursor, or None on error.
+ *
+ * Side effects:
+ * Allocates a new X cursor.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Cursor
+CreateCursorFromTableOrFile(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tk_Window tkwin, /* Window in which cursor will be used. */
+ int argc,
+ CONST char **argv, /* Cursor spec parsed into elements. */
+ struct TkCursorName *tkCursorPtr) /* Non-NULL when cursor is defined in Tk table */
+{
+ Cursor cursor = None;
+
+ int width, height, maskWidth, maskHeight;
+ int xHot = -1, yHot = -1;
+ int dummy1, dummy2;
+ XColor fg, bg;
+ CONST char *fgColor;
+ CONST char *bgColor;
+ int inTkTable = (tkCursorPtr != NULL);
+
+ Display *display = Tk_Display(tkwin);
+ Drawable drawable = RootWindowOfScreen(Tk_Screen(tkwin));
+
+ Pixmap source = None;
+ Pixmap mask = None;
+
+ /*
+ * A cursor defined in a file accepts either 2 or 4 arguments.
+ *
+ * {srcfile fg}
+ * {srcfile maskfile fg bg}
+ *
+ * A cursor defined in the Tk table accepts 1, 2, or 3 arguments.
+ *
+ * {tkcursorname}
+ * {tkcursorname fg}
+ * {tkcursorname fg bg}
+ */
+
+ if (inTkTable) {
+ /* This logic is like TkReadBitmapFile() */
+ char *data;
+
+ data = TkGetBitmapData(
+ /* interp */ NULL,
+ /* string */ tkCursorPtr->data,
+ /* filename */ NULL,
+ &width, &height,
+ &xHot, &yHot);
+ if (data == NULL) {
+ Tcl_AppendResult(interp, "error reading bitmap data for \"",
+ argv[0], "\"", NULL);
+ goto cleanup;
+ }
+
+ source = XCreateBitmapFromData(display, drawable,
+ data, width, height);
+
+ ckfree(data);
+ } else {
+ if (TkReadBitmapFile(display, drawable,
+ &argv[0][1],
+ (unsigned int *) &width, (unsigned int *) &height,
+ &source, &xHot, &yHot) != BitmapSuccess) {
+ Tcl_AppendResult(interp, "cleanup reading bitmap file \"",
+ &argv[0][1], "\"", NULL);
+ goto cleanup;
+ }
+ }
+
+ if ((xHot < 0) || (yHot < 0) || (xHot >= width) || (yHot >= height)) {
+ if (inTkTable) {
+ Tcl_AppendResult(interp, "bad hot spot in bitmap data for \"",
+ argv[0], "\"", NULL);
+ } else {
+ Tcl_AppendResult(interp, "bad hot spot in bitmap file \"",
+ &argv[0][1], "\"", NULL);
+ }
+ goto cleanup;
+ }
+
+ /*
+ * Parse color names from optional fg and bg arguments
+ */
+
+ if (argc == 1) {
+ fg.red = fg.green = fg.blue = 0;
+ bg.red = bg.green = bg.blue = 65535;
+ } else if (argc == 2) {
+ fgColor = argv[1];
+ if (XParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) {
+ Tcl_AppendResult(interp, "invalid color name \"",
+ fgColor, "\"", NULL);
+ goto cleanup;
+ }
+ if (inTkTable) {
+ bg.red = bg.green = bg.blue = 0;
+ } else {
+ bg = fg;
+ }
+ } else {
+ /* 3 or 4 arguments */
+ if (inTkTable) {
+ fgColor = argv[1];
+ bgColor = argv[2];
+ } else {
+ fgColor = argv[2];
+ bgColor = argv[3];
+ }
+ if (XParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) {
+ Tcl_AppendResult(interp, "invalid color name \"",
+ fgColor, "\"", NULL);
+ goto cleanup;
+ }
+ if (XParseColor(display, Tk_Colormap(tkwin), bgColor, &bg) == 0) {
+ Tcl_AppendResult(interp, "invalid color name \"",
+ bgColor, "\"", NULL);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * If there is no mask data, then create the cursor now.
+ */
+
+ if ((!inTkTable && (argc == 2)) || (tkCursorPtr->mask == NULL)) {
+ cursor = XCreatePixmapCursor(display, source, source,
+ &fg, &fg, (unsigned) xHot, (unsigned) yHot);
+ goto cleanup;
+ }
+
+ /*
+ * Parse bitmap mask data and create cursor with fg and bg colors.
+ */
+
+ if (inTkTable) {
+ /* This logic is like TkReadBitmapFile() */
+ char *data;
+
+ data = TkGetBitmapData(
+ /* interp */ NULL,
+ /* string */ tkCursorPtr->mask,
+ /* filename */ NULL,
+ &maskWidth, &maskHeight,
+ &dummy1, &dummy2);
+ if (data == NULL) {
+ Tcl_AppendResult(interp, "error reading bitmap mask data for \"",
+ argv[0], "\"", NULL);
+ goto cleanup;
+ }
+
+ mask = XCreateBitmapFromData(display, drawable,
+ data, maskWidth, maskHeight);
+
+ ckfree(data);
+ } else {
+ if (TkReadBitmapFile(display,
+ drawable,
+ argv[1],
+ (unsigned int *) &maskWidth, (unsigned int *) &maskHeight,
+ &mask,
+ &dummy1, &dummy2) != BitmapSuccess) {
+ Tcl_AppendResult(interp, "cleanup reading bitmap file \"",
+ argv[1], "\"", NULL);
+ goto cleanup;
+ }
+ }
+
+ if ((maskWidth != width) && (maskHeight != height)) {
+ Tcl_SetResult(interp,
+ "source and mask bitmaps have different sizes",
+ TCL_STATIC);
+ goto cleanup;
+ }
+
+ cursor = XCreatePixmapCursor(display, source, mask,
+ &fg, &bg, (unsigned) xHot, (unsigned) yHot);
+
+ cleanup:
+ if (source != None) {
+ Tk_FreePixmap(display, source);
+ }
+ if (mask != None) {
+ Tk_FreePixmap(display, mask);
+ }
+ return cursor;
+}
/*
*----------------------------------------------------------------------
diff --git a/win/rc/cursor9a.cur b/win/rc/cursor9a.cur
new file mode 100644
index 0000000..048f06b
--- /dev/null
+++ b/win/rc/cursor9a.cur
Binary files differ
diff --git a/win/rc/tk_base.rc b/win/rc/tk_base.rc
index 456a5aa..1f5fe28 100644
--- a/win/rc/tk_base.rc
+++ b/win/rc/tk_base.rc
@@ -1,4 +1,4 @@
-// RCS: @(#) $Id: tk_base.rc,v 1.4 2006/12/12 23:38:22 mdejong Exp $
+// RCS: @(#) $Id: tk_base.rc,v 1.5 2006/12/17 00:43:06 mdejong Exp $
//
// Base resources needed by Tk whether it's a DLL or a static library.
//
@@ -137,3 +137,5 @@ umbrella CURSOR DISCARDABLE "cursor92.cur"
ur_angle CURSOR DISCARDABLE "cursor94.cur"
watch CURSOR DISCARDABLE "cursor96.cur"
xterm CURSOR DISCARDABLE "cursor98.cur"
+none CURSOR DISCARDABLE "cursor9a.cur"
+