aboutsummaryrefslogtreecommitdiff
path: root/generic/tkZinc.c
diff options
context:
space:
mode:
authorlecoanet2000-05-26 08:54:11 +0000
committerlecoanet2000-05-26 08:54:11 +0000
commit826ea7741486256ad279325634737ad2c402fede (patch)
tree698ea0ea7fafcdd004466e1b1088afbd734e4346 /generic/tkZinc.c
parentec163ed41e71f8d3972ad75a850c7c9e2d123d63 (diff)
downloadtkzinc-826ea7741486256ad279325634737ad2c402fede.zip
tkzinc-826ea7741486256ad279325634737ad2c402fede.tar.gz
tkzinc-826ea7741486256ad279325634737ad2c402fede.tar.bz2
tkzinc-826ea7741486256ad279325634737ad2c402fede.tar.xz
Ajout d'options en rapport avec la saisie de texte, focus, selection,
highlight, etc. Ajout des commandes et event handlers pour g�rer la saisie de texte et le focus/selection: cursor, dchars, focus, index, insert, select. Correction des fonctions de recherche de tags/ids afin qu'elles prennent en compte le groupe de d�part. La commande group retourne le topgroup si on lui passe en param�tre le topgroup (le topgroup est son propre groupe).
Diffstat (limited to 'generic/tkZinc.c')
-rw-r--r--generic/tkZinc.c860
1 files changed, 712 insertions, 148 deletions
diff --git a/generic/tkZinc.c b/generic/tkZinc.c
index 8466880..9909b4b 100644
--- a/generic/tkZinc.c
+++ b/generic/tkZinc.c
@@ -59,6 +59,7 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ "
#include <math.h>
#include <sys/time.h>
#include <unistd.h>
+#include <X11/Xatom.h>
typedef struct TagSearch {
@@ -122,18 +123,32 @@ static Tk_ConfigSpec config_specs[] = {
{TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
"2", Tk_Offset(WidgetInfo, border_width), 0},
{TK_CONFIG_BORDER, "-backcolor", "backColor", "BackColor",
- "White", Tk_Offset(WidgetInfo, bg_border), 0},
+ "#c3c3c3", Tk_Offset(WidgetInfo, bg_border), 0},
{TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
"", Tk_Offset(WidgetInfo, cursor), TK_CONFIG_NULL_OK},
{TK_CONFIG_FONT, "-font", "font", "Font",
"-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*",
Tk_Offset(WidgetInfo, font), 0},
- {TK_CONFIG_COLOR, "-forecolor", "foreColor", "ForeColor",
+ {TK_CONFIG_COLOR, "-forecolor", "foreColor", "Foreground",
"Black", Tk_Offset(WidgetInfo, fore_color), 0},
{TK_CONFIG_BOOLEAN, "-fullreshape", "fullReshape", "FullReshape",
"1", Tk_Offset(WidgetInfo, full_reshape), 0},
{TK_CONFIG_PIXELS, "-height", "height", "Height",
- "100", Tk_Offset(WidgetInfo, opt_height), 0},
+ "7c", Tk_Offset(WidgetInfo, opt_height), 0},
+ {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground",
+ "#c3c3c3", Tk_Offset(WidgetInfo, highlight_bg_color), 0},
+ {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ "Black", Tk_Offset(WidgetInfo, highlight_color), 0},
+ {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness",
+ "2", Tk_Offset(WidgetInfo, highlight_width), 0},
+ {TK_CONFIG_COLOR, "-insertbackground", "insertBackground", "Foreground",
+ "Black", Tk_Offset(WidgetInfo, text_info.insert_color), 0},
+ {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime",
+ "300", Tk_Offset(WidgetInfo, insert_off_time), 0},
+ {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime",
+ "600", Tk_Offset(WidgetInfo, insert_on_time), 0},
+ {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
+ "2", Tk_Offset(WidgetInfo, text_info.insert_width), 0},
{TK_CONFIG_BITMAP, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol",
"AtcSymbol19", Tk_Offset(WidgetInfo, map_distance_symbol), TK_CONFIG_NULL_OK},
{TK_CONFIG_FONT, "-maptextfont", "mapTextFont", "MapTextFont",
@@ -147,18 +162,22 @@ static Tk_ConfigSpec config_specs[] = {
"1", Tk_Offset(WidgetInfo, pick_aperture), 0},
{TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
"flat", Tk_Offset(WidgetInfo, relief), 0},
+ {TK_CONFIG_BOOLEAN, "-reshape", "reshape", "Reshape",
+ "1", Tk_Offset(WidgetInfo, reshape), 0},
+ {TK_CONFIG_COLOR, "-selectbackground", "selectBackground", "Foreground",
+ "#a0a0a0", Tk_Offset(WidgetInfo, text_info.sel_color), 0},
{TK_CONFIG_INT, "-speedvectorlength", "speedVectorLength",
"SpeedVectorLength", "3", Tk_Offset(WidgetInfo, speed_vector_length), 0},
- {TK_CONFIG_INT, "-trackmanagedhistorysize", "trackManagedHistorySize",
- "TrackManagedHistorySize", "6", Tk_Offset(WidgetInfo, track_managed_history_size), 0},
- {TK_CONFIG_BOOLEAN, "-trackmanagehistory", "trackManageHistory", "TrackManageHistory",
- "1", Tk_Offset(WidgetInfo, track_manage_history), 0},
- {TK_CONFIG_BOOLEAN, "-reshape", "reshape", "Reshape",
- "1", Tk_Offset(WidgetInfo, reshape), 0},
+ {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ NULL, Tk_Offset(WidgetInfo, take_focus), TK_CONFIG_NULL_OK},
{TK_CONFIG_STRING, "-tile", "tile", "Tile",
"", Tk_Offset(WidgetInfo, tile_name), 0},
+ {TK_CONFIG_BOOLEAN, "-trackmanagehistory", "trackManageHistory", "TrackManageHistory",
+ "1", Tk_Offset(WidgetInfo, track_manage_history), 0},
+ {TK_CONFIG_INT, "-trackmanagedhistorysize", "trackManagedHistorySize",
+ "TrackManagedHistorySize", "6", Tk_Offset(WidgetInfo, track_managed_history_size), 0},
{TK_CONFIG_PIXELS, "-width", "width", "Width",
- "100", Tk_Offset(WidgetInfo, opt_width), 0},
+ "10c", Tk_Offset(WidgetInfo, opt_width), 0},
/*
* Debug options.
*/
@@ -180,27 +199,39 @@ static Tk_ConfigSpec config_specs[] = {
#define CURSOR_SPEC 2
#define FONT_SPEC 3
#define FORE_COLOR_SPEC 4
-#define FULL_RESHAPE 5
+#define FULL_RESHAPE_SPEC 5
#define HEIGHT_SPEC 6
-#define MAP_DISTANCE_SYMBOL_SPEC 7
-#define MAP_TEXT_FONT_SPEC 8
-#define OVERLAP_MANAGER_SPEC 9
-#define PICK_APERTURE_SPEC 10
-#define RELIEF_SPEC 11
-#define SPEED_VECTOR_LENGTH_SPEC 12
-#define MANAGED_HISTORY_SIZE_SPEC 13
-#define MANAGE_HISTORY_SPEC 14
-#define RESHAPE_SPEC 15
-#define TILE_SPEC 16
-#define WIDTH_SPEC 17
-#define BBOXES_SPEC 18
-#define BBOXES_COLOR_SPEC 19
-#define LIGHT_ANGLE_SPEC 20
+#define HIGHLIGHT_BACK_COLOR_SPEC 7
+#define HIGHLIGHT_COLOR_SPEC 8
+#define HIGHLIGHT_THICKNESS_SPEC 9
+#define INSERT_COLOR_SPEC 10
+#define INSERT_OFF_TIME_SPEC 11
+#define INSERT_ON_TIME_SPEC 12
+#define INSERT_WIDTH_SPEC 13
+#define MAP_DISTANCE_SYMBOL_SPEC 14
+#define MAP_TEXT_FONT_SPEC 15
+#define OVERLAP_MANAGER_SPEC 16
+#define PICK_APERTURE_SPEC 17
+#define RELIEF_SPEC 18
+#define RESHAPE_SPEC 19
+#define SELECT_COLOR_SPEC 20
+#define SPEED_VECTOR_LENGTH_SPEC 21
+#define TAKE_FOCUS_SPEC 22
+#define TILE_SPEC 23
+#define MANAGE_HISTORY_SPEC 24
+#define MANAGED_HISTORY_SIZE_SPEC 25
+#define WIDTH_SPEC 26
+#define BBOXES_SPEC 27
+#define BBOXES_COLOR_SPEC 28
+#define LIGHT_ANGLE_SPEC 29
static void CmdDeleted _ANSI_ARGS_((ClientData client_data));
static void Event _ANSI_ARGS_((ClientData client_data, XEvent *eventPtr));
static void Bind _ANSI_ARGS_((ClientData client_data, XEvent *eventPtr));
+static int FetchSelection _ANSI_ARGS_((ClientData clientData, int offset,
+ char *buffer, int maxBytes));
+static void SelectTo _ANSI_ARGS_((Item item, int index));
static int WidgetCmd _ANSI_ARGS_((ClientData client_data,
Tcl_Interp *, int argc, Arg *args));
static int Configure _ANSI_ARGS_((Tcl_Interp *interp, WidgetInfo *wi,
@@ -208,7 +239,9 @@ static int Configure _ANSI_ARGS_((Tcl_Interp *interp, WidgetInfo *wi,
static void Redisplay _ANSI_ARGS_((ClientData client_data));
static void Destroy _ANSI_ARGS_((char *mem_ptr));
static void InitZinc _ANSI_ARGS_((Tcl_Interp *interp));
-
+static void Focus _ANSI_ARGS_((WidgetInfo *wi, ZnBool got_focus));
+
+
/*
*----------------------------------------------------------------------
*
@@ -386,6 +419,28 @@ ZincCmd(ClientData client_data, /* Main window associated with
wi->work_item_list = NULL;
wi->work_pts = ZnListNew(8, sizeof(ZnPoint));
wi->work_xpts = ZnListNew(8, sizeof(XPoint));
+
+ /*
+ * Text management init.
+ */
+ wi->text_info.sel_color = NULL;
+ wi->text_info.sel_item = ZN_NO_ITEM;
+ wi->text_info.sel_first = -1;
+ wi->text_info.sel_last = -1;
+ wi->text_info.anchor_item = ZN_NO_ITEM;
+ wi->text_info.sel_anchor = 0;
+ wi->text_info.insert_color = NULL;
+ wi->text_info.insert_width = 0;
+ wi->text_info.focus_item = ZN_NO_ITEM;
+ wi->text_info.got_focus = False;
+ wi->text_info.cursor_on = False;
+ wi->insert_on_time = 0;
+ wi->insert_off_time = 0;
+ wi->blink_handler = NULL;
+ wi->take_focus = NULL;
+ wi->highlight_width = 0;
+ wi->highlight_color = NULL;
+ wi->highlight_bg_color = NULL;
ITEM_P.InitClipStack(wi);
ITEM_P.InitTransformStack(wi);
@@ -404,6 +459,8 @@ ZincCmd(ClientData client_data, /* Main window associated with
ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
LeaveWindowMask|PointerMotionMask, Bind,
(ClientData) wi);
+ Tk_CreateSelHandler(tkwin, XA_PRIMARY, XA_STRING,
+ FetchSelection, (ClientData) wi, XA_STRING);
if (Configure(interp, wi, argc-2, args+2, 0) != TCL_OK) {
Tk_DestroyWindow(tkwin);
@@ -532,10 +589,10 @@ ZnSearchWithTagOrId(WidgetInfo *wi,
if (uid == all_uid) {
tag_search->current = tag_search->group->head;
tag_search->previous = ZN_NO_ITEM;
- return tag_search->current;
+ return group;
}
- item = tag_search->group->head;
+ item = group;
do {
while (item != ZN_NO_ITEM) {
if (item->tags) {
@@ -576,7 +633,8 @@ ZnSearchWithTagOrId(WidgetInfo *wi,
tag_search->over = True;
ZnListFree(tag_search->item_stack);
- return NULL;
+
+ return ZN_NO_ITEM;
}
static Item
@@ -877,7 +935,7 @@ static ZnBool
IsHeirOf(Item item,
Item group)
{
- while ((item != ZN_NO_ITEM) && (item->parent != group)) {
+ while ((item != ZN_NO_ITEM) && (item != group)) {
item = item->parent;
}
@@ -936,10 +994,10 @@ FindArea(Tcl_Interp *interp,
}
area.corner.x += 1;
area.corner.y += 1;
- area.orig.x -= wi->border_width;
- area.orig.y -= wi->border_width;
- area.corner.x -= wi->border_width;
- area.corner.y -= wi->border_width;
+ area.orig.x -= wi->inset;
+ area.orig.y -= wi->inset;
+ area.corner.x -= wi->inset;
+ area.corner.y -= wi->inset;
/*
* BUG: The starting group should be considered instead of top_group.!!
@@ -1054,8 +1112,8 @@ FindItems(Tcl_Interp *interp,
if (Tcl_GetDouble(interp, args[2], &p.y) == ZN_ERROR) {
return ZN_ERROR;
}
- p.x -= wi->border_width;
- p.y -= wi->border_width;
+ p.x -= wi->inset;
+ p.y -= wi->inset;
if (argc > 3) {
if (Tcl_GetInt(interp, args[3], &halo) == ZN_ERROR) {
return ZN_ERROR;
@@ -1798,13 +1856,13 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
}
}
if (found && !IsEmptyBBox(&bbox)) {
- sprintf(msg, "%g", bbox.orig.x+wi->border_width);
+ sprintf(msg, "%g", bbox.orig.x+wi->inset);
Tcl_AppendElement(interp, msg);
- sprintf(msg, "%g", bbox.orig.y+wi->border_width);
+ sprintf(msg, "%g", bbox.orig.y+wi->inset);
Tcl_AppendElement(interp, msg);
- sprintf(msg, "%g", bbox.corner.x+wi->border_width);
+ sprintf(msg, "%g", bbox.corner.x+wi->inset);
Tcl_AppendElement(interp, msg);
- sprintf(msg, "%g", bbox.corner.y+wi->border_width);
+ sprintf(msg, "%g", bbox.corner.y+wi->inset);
Tcl_AppendElement(interp, msg);
}
}
@@ -2038,9 +2096,10 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
* coords
*/
else if ((c == 'c') && (strncmp(LangString(args[1]), "coords", length) == 0)) {
- if ((argc < 3) && (argc > 6)) {
+ if ((argc < 3) || (argc > 6)) {
Tcl_AppendResult(interp, "wrong # args: should be \"", LangString(args[0]),
- "\" coords tagOrId ?add/remove? ?index? ?coordList?", NULL);
+ "\" coords tagOrId ?add/remove? ?contour? ?index? ?coordList?",
+ NULL);
goto error;
}
if (Coords(wi, argc, args) == ZN_ERROR) {
@@ -2062,6 +2121,70 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
}
/*
+ * cursor
+ */
+ else if ((c == 'c') && (strncmp(LangString(args[1]), "cursor", length) == 0)) {
+ int index;
+ if (argc != 4) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", LangString(args[0]),
+ "\" cursor tagOrId index", NULL);
+ goto error;
+ }
+ num = ZnItemsWithTagOrId(wi, LangString(args[2]), &item, &items);
+ for (i = 0; i < num; i++) {
+ if ((items[i]->class->Cursor == NULL) ||
+ (items[i]->class->Index == NULL)) {
+ continue;
+ }
+ result = (*items[i]->class->Index)(items[i], LangString(args[3]), &index);
+ if (result != ZN_OK) {
+ goto error;
+ }
+
+ (*items[i]->class->Cursor)(items[i], index);
+ if ((items[i] == wi->text_info.focus_item) && wi->text_info.cursor_on) {
+ ITEM.Invalidate(items[i], ZN_COORDS_FLAG);
+ }
+ }
+ }
+
+ /*
+ * dchars
+ */
+ else if ((c == 'd') && (strncmp(LangString(args[1]), "dchars", length) == 0)) {
+ int first, last;
+
+ if ((argc != 4) && (argc != 5)) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", LangString(args[0]),
+ "\" dchars tagOrId first ?last?", NULL);
+ goto error;
+ }
+ num = ZnItemsWithTagOrId(wi, LangString(args[2]), &item, &items);
+ for (i = 0; i < num; i++) {
+ if ((items[i]->class->Index == NULL) ||
+ (items[i]->class->DeleteChars == NULL)) {
+ continue;
+ }
+ result = (*items[i]->class->Index)(items[i], LangString(args[3]), &first);
+ if (result != ZN_OK) {
+ goto error;
+ }
+ if (argc == 5) {
+ result = (*items[i]->class->Index)(items[i], LangString(args[4]), &last);
+ if (result != ZN_OK) {
+ goto error;
+ }
+ }
+ else {
+ last = first;
+ }
+ (*items[i]->class->DeleteChars)(items[i], first, last);
+ }
+ }
+
+ /*
* dtag
*/
else if ((c == 'd') && (strncmp(LangString(args[1]), "dtag", length) == 0)) {
@@ -2140,6 +2263,47 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
}
/*
+ * focus
+ */
+ else if ((c == 'f') && (strncmp(LangString(args[1]), "focus", length) == 0)) {
+ if ((argc != 2) && (argc != 3)) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", LangString(args[0]),
+ "\" focus ?tagOrId?", NULL);
+ goto error;
+ }
+ item = wi->text_info.focus_item;
+ if (argc == 2) {
+ if (item != ZN_NO_ITEM) {
+ sprintf(msg, "%d", item->id);
+ Tcl_SetResult(wi->interp, msg, TCL_VOLATILE);
+ }
+ goto done;
+ }
+ if ((item != ZN_NO_ITEM) && (wi->text_info.got_focus)) {
+ ITEM.Invalidate(item, ZN_COORDS_FLAG);
+ }
+ if (LangString(args[2])[0] == 0) {
+ wi->text_info.focus_item = ZN_NO_ITEM;
+ goto done;
+ }
+ num = ZnItemsWithTagOrId(wi, LangString(args[2]), &item, &items);
+ item = ZN_NO_ITEM;
+ for (i = 0; i < num; i++) {
+ if (items[i]->class->Cursor != NULL) {
+ break;
+ }
+ }
+ if (num == 0) {
+ goto done;
+ }
+ wi->text_info.focus_item = items[i];
+ if (wi->text_info.got_focus) {
+ ITEM.Invalidate(wi->text_info.focus_item, ZN_COORDS_FLAG);
+ }
+ }
+
+ /*
* gettags
*/
else if ((c == 'g') && (strncmp(LangString(args[1]), "gettags", length) == 0)) {
@@ -2181,11 +2345,14 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
}
if (item->parent != ZN_NO_ITEM) {
sprintf(msg, "%d", item->parent->id);
- Tcl_SetResult(interp, msg, TCL_VOLATILE);
}
else {
- Tcl_SetResult(interp, "", TCL_STATIC);
+ /*
+ * Top group is its own parent.
+ */
+ sprintf(msg, "%d", item->id);
}
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
}
/*
@@ -2270,6 +2437,59 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
}
/*
+ * index
+ */
+ else if ((c == 'i') && (strncmp(LangString(args[1]), "index", length) == 0)) {
+ int index;
+
+ if (argc != 4) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", LangString(args[0]),
+ "\" index tagOrId string", NULL);
+ goto error;
+ }
+ num = ZnItemsWithTagOrId(wi, LangString(args[2]), &item, &items);
+ for (i = 0; i < num; i++) {
+ if (items[i]->class->Index != NULL) {
+ result = (*items[i]->class->Index)(items[i], LangString(args[3]), &index);
+ if (result != ZN_OK) {
+ goto error;
+ }
+ sprintf(msg, "%d", index);
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ goto done;
+ }
+ }
+ Tcl_AppendResult(interp, "can't find an indexable item \"",
+ LangString(args[2]), "\"", NULL);
+ goto error;
+ }
+
+ /*
+ * insert
+ */
+ else if ((c == 'i') && (strncmp(LangString(args[1]), "insert", length) == 0)) {
+ int index;
+
+ if (argc != 5) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", LangString(args[0]),
+ "\" insert tagOrId before string", NULL);
+ goto error;
+ }
+ num = ZnItemsWithTagOrId(wi, LangString(args[2]), &item, &items);
+ for (i = 0; i < num; i++) {
+ if ((items[i]->class->Index == NULL) ||
+ (items[i]->class->InsertChars == NULL)) {
+ continue;
+ }
+ result = (*items[i]->class->Index)(items[i], LangString(args[3]), &index);
+ if (result != ZN_OK) {
+ goto error;
+ }
+ (*items[i]->class->InsertChars)(items[i], index, LangString(args[4]));
+ }
+ }
+
+ /*
* itemcget
*/
else if ((c == 'i') && (strncmp(LangString(args[1]), "itemcget", length) == 0)) {
@@ -2327,7 +2547,8 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
int field = -1;
if (argc < 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", LangString(args[0]),
- "\" itemconfigure tagOrId ?field? option value ?option value? ...", NULL);
+ "\" itemconfigure tagOrId ?field? option value ?option value? ...",
+ NULL);
goto error;
}
num = ZnItemsWithTagOrId(wi, LangString(args[2]), &item, &items);
@@ -2441,6 +2662,14 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
}
/*
+ * postscript
+ */
+ else if ((c == 'p') && (strncmp(LangString(args[1]), "postscript", length) == 0)) {
+ Tcl_AppendResult(interp, "Command not yet implemented", NULL);
+ goto error;
+ }
+
+ /*
* raise
*/
else if ((c == 'r') && (strncmp(LangString(args[1]), "raise", length) == 0)) {
@@ -2497,6 +2726,9 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
goto error;
}
for (i = num-1; i >= 0; i--) {
+ if (items[i] == wi->top_group) {
+ continue;
+ }
if (wi->binding_table != NULL) {
/*
* BUG: we can't actually destroy all the item's bindings
@@ -2607,6 +2839,107 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
}
/*
+ * select
+ */
+ else if ((c == 's') && (strncmp(LangString(args[1]), "select", length) == 0)) {
+ int index;
+
+ if (argc < 3) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", LangString(args[0]),
+ "\" select option ?tagOrId? ?arg?", NULL);
+ goto error;
+ }
+ if (argc >= 4) {
+ num = ZnItemsWithTagOrId(wi, LangString(args[3]), &item, &items);
+ if (num == 0) {
+ goto done;
+ }
+ item = ZN_NO_ITEM;
+ for (i = 0; i < num; i++) {
+ if ((items[i]->class->Index != NULL) &&
+ (items[i]->class->Selection != NULL)) {
+ item = items[i];
+ break;
+ }
+ }
+ if (item == ZN_NO_ITEM) {
+ Tcl_AppendResult(interp, "can't find an indexable item \"",
+ LangString(args[3]), "\"", NULL);
+ goto error;
+ }
+ }
+ if (argc == 5) {
+ result = item->class->Index(item, LangString(args[4]), &index);
+ if (result != ZN_OK) {
+ goto error;
+ }
+ }
+ c = LangString(args[2])[0];
+ length = strlen(LangString(args[2]));
+ if ((c == 'a') && (strncmp(LangString(args[2]), "adjust", length) == 0)) {
+ if (argc != 5) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", LangString(args[0]),
+ "\" select adjust tagOrId index", NULL);
+ goto error;
+ }
+ if (wi->text_info.sel_item == item) {
+ if (index < (wi->text_info.sel_first + wi->text_info.sel_last)/2) {
+ wi->text_info.sel_anchor = wi->text_info.sel_last+1;
+ }
+ else {
+ wi->text_info.sel_anchor = wi->text_info.sel_first;
+ }
+ }
+ SelectTo(item, index);
+ }
+ else if ((c == 'c') && (strncmp(LangString(args[2]), "clear", length) == 0)) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", LangString(args[0]),
+ "\" select clear", NULL);
+ goto error;
+ }
+ if (wi->text_info.sel_item != ZN_NO_ITEM) {
+ ITEM.Invalidate(wi->text_info.sel_item, ZN_DRAW_FLAG);
+ wi->text_info.sel_item = ZN_NO_ITEM;
+ }
+ }
+ else if ((c == 'f') && (strncmp(LangString(args[2]), "from", length) == 0)) {
+ if (argc != 5) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", LangString(args[0]),
+ "\" select from tagOrId index", NULL);
+ goto error;
+ }
+ wi->text_info.anchor_item = item;
+ wi->text_info.sel_anchor = index;
+ }
+ else if ((c == 'i') && (strncmp(LangString(args[2]), "item", length) == 0)) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", LangString(args[0]),
+ "\" select item", NULL);
+ goto error;
+ }
+ if (wi->text_info.sel_item != ZN_NO_ITEM) {
+ sprintf(msg, "%d", wi->text_info.sel_item->id);
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ }
+ }
+ else if ((c == 't') && (strncmp(LangString(args[2]), "to", length) == 0)) {
+ if (argc != 5) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", LangString(args[0]),
+ "\" select to tagOrId index", NULL);
+ goto error;
+ }
+ SelectTo(item, index);
+ }
+ }
+
+ /*
* smooth
*/
else if ((c == 's') && (strncmp(LangString(args[1]), "smooth", length) == 0)) {
@@ -2727,8 +3060,8 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
* Need to adjust for the border.
*/
if (argc != 5) {
- p->x -= wi->border_width;
- p->y -= wi->border_width;
+ p->x -= wi->inset;
+ p->y -= wi->inset;
}
ZnTransformPoint(this_one, p, &xp);
/*printf("p->x=%g, p->y=%g, xp.x=%g, xp.y=%g\n", p->x, p->y, xp.x, xp.y);*/
@@ -2905,12 +3238,11 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
"\": must be "
"add, addtag, anchorxy, bbox, becomes, bind, cget, "
"chggroup, clone, configure, contour, coords, currentpart, "
- "dtag, find, fit, gettags, group, hasanchors, "
- "hasfields, hasparts, hastag, itemcget, "
- "itemconfigure, lower, monitor, raise, "
- "remove, rotate, scale, smooth, tapply, tdelete, "
- "transform, translate, "
- "treset, trestore, tsave, type, ", NULL);
+ "cursor, chars, dtag, find, fit, focus, gettags, group, "
+ "hasanchors, hasfields, hasparts, hastag, index, insert, "
+ "itemcget, itemconfigure, lower, monitor, postscript, raise, "
+ "remove, rotate, scale, select, smooth, tapply, tdelete, "
+ "transform, translate, treset, trestore, tsave, type", NULL);
goto error;
}
done:
@@ -3025,7 +3357,9 @@ Configure(Tcl_Interp *interp, /* Used for error reporting. */
* If the changes in geometry are actually performed the code below
* might be a duplicate effort (done in Event).
*/
- if (CONFIG_PROBE(BORDER_WIDTH_SPEC)) {
+ wi->inset = wi->border_width + wi->highlight_width;
+ if (CONFIG_PROBE(BORDER_WIDTH_SPEC) ||
+ CONFIG_PROBE(HIGHLIGHT_THICKNESS_SPEC)) {
bbox.orig.x = bbox.orig.y = 0;
bbox.corner.x = wi->width;
bbox.corner.y = wi->height;
@@ -3046,9 +3380,10 @@ Configure(Tcl_Interp *interp, /* Used for error reporting. */
* Request the new geometry.
*/
if (CONFIG_PROBE(WIDTH_SPEC) || CONFIG_PROBE(HEIGHT_SPEC) ||
- CONFIG_PROBE(BORDER_WIDTH_SPEC) || !wi->realized) {
- Tk_GeometryRequest(wi->win, wi->opt_width + 2*wi->border_width,
- wi->opt_height + 2*wi->border_width);
+ CONFIG_PROBE(BORDER_WIDTH_SPEC) ||
+ CONFIG_PROBE(HIGHLIGHT_THICKNESS_SPEC) || !wi->realized) {
+ Tk_GeometryRequest(wi->win, wi->opt_width + 2*wi->inset,
+ wi->opt_height + 2*wi->inset);
}
if (CONFIG_PROBE(TILE_SPEC)) {
@@ -3090,6 +3425,15 @@ Configure(Tcl_Interp *interp, /* Used for error reporting. */
}
#endif
+ /*
+ * Update the blinking cursor timing if on/off time has changed.
+ */
+ if (wi->text_info.got_focus &&
+ (CONFIG_PROBE(INSERT_ON_TIME_SPEC) ||
+ CONFIG_PROBE(INSERT_OFF_TIME_SPEC))) {
+ Focus(wi, True);
+ }
+
return TCL_OK;
}
@@ -3097,6 +3441,70 @@ Configure(Tcl_Interp *interp, /* Used for error reporting. */
/*
*----------------------------------------------------------------------
*
+ * Focus --
+ *
+ * This procedure is called whenever a zinc gets or loses the
+ * input focus. It's also called whenever the window is
+ * reconfigured while it has the focus.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cursor gets turned on or off.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+Blink(ClientData client_data)
+{
+ WidgetInfo *wi = (WidgetInfo *) client_data;
+
+ if (!wi->text_info.got_focus || (wi->insert_off_time == 0)) {
+ return;
+ }
+ if (wi->text_info.cursor_on) {
+ wi->text_info.cursor_on = 0;
+ wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_off_time,
+ Blink, client_data);
+ }
+ else {
+ wi->text_info.cursor_on = 1;
+ wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_on_time,
+ Blink, client_data);
+ }
+ if (wi->text_info.focus_item != ZN_NO_ITEM) {
+ ITEM.Invalidate(wi->text_info.focus_item, ZN_DRAW_FLAG);
+ }
+}
+
+static void
+Focus(WidgetInfo *wi,
+ ZnBool got_focus)
+{
+ Tcl_DeleteTimerHandler(wi->blink_handler);
+ if (got_focus) {
+ wi->text_info.got_focus = 1;
+ wi->text_info.cursor_on = 1;
+ if (wi->insert_off_time != 0) {
+ wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_off_time,
+ Blink, (ClientData) wi);
+ }
+ }
+ else {
+ wi->text_info.got_focus = 0;
+ wi->text_info.cursor_on = 0;
+ wi->blink_handler = (Tcl_TimerToken) NULL;
+ }
+ if (wi->text_info.focus_item != ZN_NO_ITEM) {
+ ITEM.Invalidate(wi->text_info.focus_item, ZN_COORDS_FLAG);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
* Event --
*
* This procedure is invoked by the Tk dispatcher for various
@@ -3113,17 +3521,17 @@ Configure(Tcl_Interp *interp, /* Used for error reporting. */
*/
static void
Event(ClientData client_data, /* Information about widget. */
- XEvent *event_ptr) /* Information about event. */
+ XEvent *event) /* Information about event. */
{
WidgetInfo *wi = (WidgetInfo *) client_data;
/*printf("=============== DEBUT %s EVENT ==================\n",
- event_ptr->type == MapNotify ? "MAP":
- event_ptr->type == Expose? "EXPOSE" :
- event_ptr->type == ConfigureNotify ? "CONFIGURE" :
- event_ptr->type == DestroyNotify ? "DESTROY" :
+ event->type == MapNotify ? "MAP":
+ event->type == Expose? "EXPOSE" :
+ event->type == ConfigureNotify ? "CONFIGURE" :
+ event->type == DestroyNotify ? "DESTROY" :
"??");*/
- if (event_ptr->type == MapNotify) {
+ if (event->type == MapNotify) {
if (!wi->gc) {
wi->realized = True;
/*
@@ -3156,14 +3564,14 @@ Event(ClientData client_data, /* Information about widget. */
}
}
}
- else if (event_ptr->type == Expose) {
+ else if (event->type == Expose) {
ZnBBox bbox;
ZnDim width, height;
- bbox.orig.x = ((XExposeEvent*) event_ptr)->x - wi->border_width;
- bbox.orig.y = ((XExposeEvent*) event_ptr)->y - wi->border_width;
- width = ((XExposeEvent*) event_ptr)->width;
- height = ((XExposeEvent*) event_ptr)->height;
+ bbox.orig.x = (((XExposeEvent*) event)->x - wi->inset);
+ bbox.orig.y = (((XExposeEvent*) event)->y - wi->inset);
+ width = ((XExposeEvent*) event)->width;
+ height = ((XExposeEvent*) event)->height;
if (bbox.orig.x < 0) {
width += bbox.orig.x;
bbox.orig.x = 0;
@@ -3176,15 +3584,15 @@ Event(ClientData client_data, /* Information about widget. */
bbox.corner.y = bbox.orig.y + height;
/*printf("expose %d %d %d %d\n",
- ((XExposeEvent*) event_ptr)->x, ((XExposeEvent*) event_ptr)->y,
- ((XExposeEvent*) event_ptr)->width, ((XExposeEvent*) event_ptr)->height);*/
+ ((XExposeEvent*) event)->x, ((XExposeEvent*) event)->y,
+ ((XExposeEvent*) event)->width, ((XExposeEvent*) event)->height);*/
/*
* Add the exposed area to the expose region and
* schedule an asynchronous redisplay of the window
* if we are done adding exposed parts.
*/
AddBBoxToBBox(&wi->exposed_area, &bbox);
- if ((((XExposeEvent*) event_ptr)->count == 0) &&
+ if ((((XExposeEvent*) event)->count == 0) &&
!IsEmptyBBox(&wi->exposed_area)) {
ZnNeedRedisplay(wi);
}
@@ -3195,14 +3603,14 @@ Event(ClientData client_data, /* Information about widget. */
* modified as a result of the resize. If the application
* need such change, it can bind a handler on <Configure>.
*/
- else if (event_ptr->type == ConfigureNotify) {
+ else if (event->type == ConfigureNotify) {
ZnDim w, h;
ZnBBox bbox;
- /* w = ((XConfigureEvent*) event_ptr)->width-2*wi->border_width;
- h = ((XConfigureEvent*) event_ptr)->height-2*wi->border_width;*/
- w = Tk_Width(wi->win)-2*wi->border_width;
- h = Tk_Height(wi->win)-2*wi->border_width;
+ /* w = ((XConfigureEvent*) event)->width-2*wi->inset;
+ h = ((XConfigureEvent*) event)->height-2*wi->inset;*/
+ w = Tk_Width(wi->win)-2*wi->inset;
+ h = Tk_Height(wi->win)-2*wi->inset;
if ((wi->width != w) || (wi->height != h)) {
/*printf("reallocating pixmap\n");*/
@@ -3242,7 +3650,7 @@ Event(ClientData client_data, /* Information about widget. */
* Remove the corresponding widget command, unregister any
* pending Redisplay and eventually free the widget's memory.
*/
- else if (event_ptr->type == DestroyNotify) {
+ else if (event->type == DestroyNotify) {
if (wi->win != NULL) {
wi->win = NULL;
wi->realized = False;
@@ -3257,11 +3665,22 @@ Event(ClientData client_data, /* Information about widget. */
}
Tcl_EventuallyFree((ClientData) wi, Destroy);
}
+ else if (event->type == FocusIn) {
+ if (event->xfocus.detail != NotifyInferior) {
+ Focus(wi, True);
+ }
+ }
+ else if (event->type == FocusOut) {
+ if (event->xfocus.detail != NotifyInferior) {
+ Focus(wi, False);
+ }
+ }
+
/*printf("=============== FIN %s EVENT ==================\n",
- event_ptr->type == MapNotify ? "MAP":
- event_ptr->type == Expose? "EXPOSE" :
- event_ptr->type == ConfigureNotify ? "CONFIGURE" :
- event_ptr->type == DestroyNotify ? "DESTROY" :
+ event->type == MapNotify ? "MAP":
+ event->type == Expose? "EXPOSE" :
+ event->type == ConfigureNotify ? "CONFIGURE" :
+ event->type == DestroyNotify ? "DESTROY" :
"??");*/
}
@@ -3277,7 +3696,7 @@ Event(ClientData client_data, /* Information about widget. */
*/
static void
DoEvent(WidgetInfo *wi,
- XEvent *event_ptr)
+ XEvent *event)
{
#define NUM_STATIC 4
ClientData items[NUM_STATIC], *its;
@@ -3286,6 +3705,7 @@ DoEvent(WidgetInfo *wi,
int num, num_tags, i, len, ptr;
ClientData *tag_list = NULL;
Item item;
+ int part;
ZnBool bind_part, bind_item;
#define BIND_ITEM(test) \
@@ -3306,8 +3726,13 @@ DoEvent(WidgetInfo *wi,
}
item = wi->current_item;
- if (item == NULL) {
- /*printf("no current item, leaving\n");*/
+ part = wi->current_part;
+ if ((event->type == KeyPress) || (event->type == KeyRelease)) {
+ item = wi->text_info.focus_item;
+ part = ZN_NO_PART;
+ }
+
+ if ((item == ZN_NO_ITEM) || !item->class->IsSensitive(item, part)) {
return;
}
@@ -3330,12 +3755,12 @@ DoEvent(WidgetInfo *wi,
* any binding related to the item only those pertaining
* to the fields.
*/
- bind_item = (((event_ptr->type != EnterNotify) &&
- (event_ptr->type != LeaveNotify)) ||
+ bind_item = (((event->type != EnterNotify) &&
+ (event->type != LeaveNotify)) ||
(wi->current_item != wi->new_item));
/*printf("type=%s, current=%d, new=%d --> %s\n",
- event_ptr->type==EnterNotify?"Enter":
- event_ptr->type==LeaveNotify?"Leave":"other",
+ event->type==EnterNotify?"Enter":
+ event->type==LeaveNotify?"Leave":"other",
wi->current_item?wi->current_item->id:0,
wi->new_item?wi->new_item->id:0,
bind_item?"bind":"nobind");*/
@@ -3364,7 +3789,7 @@ DoEvent(WidgetInfo *wi,
ptr = 0;
- BIND_ITEM(event_ptr->type != LeaveNotify);
+ BIND_ITEM(event->type != LeaveNotify);
if (bind_part) {
/*
@@ -3387,13 +3812,13 @@ DoEvent(WidgetInfo *wi,
ptr++;
}
- BIND_ITEM(event_ptr->type == LeaveNotify);
+ BIND_ITEM(event->type == LeaveNotify);
/*
* Invoke the binding system.
*/
if (wi->win != NULL) {
- Tk_BindEvent(wi->binding_table, event_ptr, wi->win, num, its);
+ Tk_BindEvent(wi->binding_table, event, wi->win, num, its);
}
if (its != items) {
ZnFree(its);
@@ -3429,7 +3854,7 @@ DoEvent(WidgetInfo *wi,
*/
static void
PickCurrentItem(WidgetInfo *wi,
- XEvent *event_ptr)
+ XEvent *event)
{
int button_down;
int prev_left_grabbed_item;
@@ -3458,28 +3883,28 @@ PickCurrentItem(WidgetInfo *wi,
* Translate MotionNotify events into EnterNotify events, since that's
* what gets reported to item handlers.
*/
- if (event_ptr != &wi->pick_event) {
- if ((event_ptr->type == MotionNotify) || (event_ptr->type == ButtonRelease)) {
+ if (event != &wi->pick_event) {
+ if ((event->type == MotionNotify) || (event->type == ButtonRelease)) {
wi->pick_event.xcrossing.type = EnterNotify;
- wi->pick_event.xcrossing.serial = event_ptr->xmotion.serial;
- wi->pick_event.xcrossing.send_event = event_ptr->xmotion.send_event;
- wi->pick_event.xcrossing.display = event_ptr->xmotion.display;
- wi->pick_event.xcrossing.window = event_ptr->xmotion.window;
- wi->pick_event.xcrossing.root = event_ptr->xmotion.root;
+ wi->pick_event.xcrossing.serial = event->xmotion.serial;
+ wi->pick_event.xcrossing.send_event = event->xmotion.send_event;
+ wi->pick_event.xcrossing.display = event->xmotion.display;
+ wi->pick_event.xcrossing.window = event->xmotion.window;
+ wi->pick_event.xcrossing.root = event->xmotion.root;
wi->pick_event.xcrossing.subwindow = None;
- wi->pick_event.xcrossing.time = event_ptr->xmotion.time;
- wi->pick_event.xcrossing.x = event_ptr->xmotion.x;
- wi->pick_event.xcrossing.y = event_ptr->xmotion.y;
- wi->pick_event.xcrossing.x_root = event_ptr->xmotion.x_root;
- wi->pick_event.xcrossing.y_root = event_ptr->xmotion.y_root;
+ wi->pick_event.xcrossing.time = event->xmotion.time;
+ wi->pick_event.xcrossing.x = event->xmotion.x;
+ wi->pick_event.xcrossing.y = event->xmotion.y;
+ wi->pick_event.xcrossing.x_root = event->xmotion.x_root;
+ wi->pick_event.xcrossing.y_root = event->xmotion.y_root;
wi->pick_event.xcrossing.mode = NotifyNormal;
wi->pick_event.xcrossing.detail = NotifyNonlinear;
- wi->pick_event.xcrossing.same_screen = event_ptr->xmotion.same_screen;
+ wi->pick_event.xcrossing.same_screen = event->xmotion.same_screen;
wi->pick_event.xcrossing.focus = False;
- wi->pick_event.xcrossing.state = event_ptr->xmotion.state;
+ wi->pick_event.xcrossing.state = event->xmotion.state;
}
else {
- wi->pick_event = *event_ptr;
+ wi->pick_event = *event;
}
}
@@ -3501,8 +3926,8 @@ PickCurrentItem(WidgetInfo *wi,
if (wi->pick_event.type != LeaveNotify) {
ZnPoint p;
- p.x = wi->pick_event.xcrossing.x-wi->border_width;
- p.y = wi->pick_event.xcrossing.y-wi->border_width;
+ p.x = wi->pick_event.xcrossing.x-wi->inset;
+ p.y = wi->pick_event.xcrossing.y-wi->inset;
wi->top_group->class->Pick(wi->top_group, &p, NULL, wi->pick_aperture,
&wi->new_item, &wi->new_part);
}
@@ -3636,7 +4061,7 @@ PickCurrentItem(WidgetInfo *wi,
*/
static void
Bind(ClientData client_data, /* Information about widget. */
- XEvent *event_ptr) /* Information about event. */
+ XEvent *event) /* Information about event. */
{
WidgetInfo *wi = (WidgetInfo *) client_data;
@@ -3647,10 +4072,10 @@ Bind(ClientData client_data, /* Information about widget. */
* wi->state. This information is used to defer repicks of
* the current item while buttons are down.
*/
- if ((event_ptr->type == ButtonPress) || (event_ptr->type == ButtonRelease)) {
+ if ((event->type == ButtonPress) || (event->type == ButtonRelease)) {
int mask;
- switch (event_ptr->xbutton.button) {
+ switch (event->xbutton.button) {
case Button1:
mask = Button1Mask;
break;
@@ -3679,17 +4104,17 @@ Bind(ClientData client_data, /* Information about widget. */
* current item).
*/
- if (event_ptr->type == ButtonPress) {
+ if (event->type == ButtonPress) {
/*
* On a button press, first repick the current item using
* the button state before the event, the process the event.
*/
- wi->state = event_ptr->xbutton.state;
- PickCurrentItem(wi, event_ptr);
+ wi->state = event->xbutton.state;
+ PickCurrentItem(wi, event);
wi->state ^= mask;
if ((wi->current_item != ZN_NO_ITEM) &&
wi->current_item->class->IsSensitive(wi->current_item, wi->current_part)) {
- DoEvent(wi, event_ptr);
+ DoEvent(wi, event);
}
}
else {
@@ -3698,32 +4123,28 @@ Bind(ClientData client_data, /* Information about widget. */
* still considered to be down. Then repick the current
* item under the assumption that the button is no longer down.
*/
- wi->state = event_ptr->xbutton.state;
- DoEvent(wi, event_ptr);
- event_ptr->xbutton.state ^= mask;
- wi->state = event_ptr->xbutton.state;
- PickCurrentItem(wi, event_ptr);
- event_ptr->xbutton.state ^= mask;
+ wi->state = event->xbutton.state;
+ DoEvent(wi, event);
+ event->xbutton.state ^= mask;
+ wi->state = event->xbutton.state;
+ PickCurrentItem(wi, event);
+ event->xbutton.state ^= mask;
}
goto done;
}
- else if ((event_ptr->type == EnterNotify) || (event_ptr->type == LeaveNotify)) {
- wi->state = event_ptr->xcrossing.state;
- PickCurrentItem(wi, event_ptr);
+ else if ((event->type == EnterNotify) || (event->type == LeaveNotify)) {
+ wi->state = event->xcrossing.state;
+ PickCurrentItem(wi, event);
goto done;
}
- else if (event_ptr->type == MotionNotify) {
- wi->state = event_ptr->xmotion.state;
- PickCurrentItem(wi, event_ptr);
+ else if (event->type == MotionNotify) {
+ wi->state = event->xmotion.state;
+ PickCurrentItem(wi, event);
}
- /*printf("=event=\n");*/
- if ((wi->current_item != ZN_NO_ITEM) &&
- wi->current_item->class->IsSensitive(wi->current_item, wi->current_part)) {
- DoEvent(wi, event_ptr);
- }
+ DoEvent(wi, event);
done:
Tcl_Release((ClientData) wi);
@@ -3733,6 +4154,136 @@ done:
/*
*----------------------------------------------------------------------
*
+ * LostSelection --
+ *
+ * This procedure is called back by Tk when the selection is
+ * grabbed away from a zinc widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The existing selection is unhighlighted, and the window is
+ * marked as not containing a selection.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+LostSelection(ClientData client_data)
+{
+ WidgetInfo *wi = (WidgetInfo *) client_data;
+
+ if (wi->text_info.sel_item != ZN_NO_ITEM) {
+ ITEM.Invalidate(wi->text_info.sel_item, ZN_DRAW_FLAG);
+ }
+ wi->text_info.sel_item = ZN_NO_ITEM;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SelectTo --
+ *
+ * Modify the selection by moving its un-anchored end. This could
+ * make the selection either larger or smaller.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The selection changes.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+SelectTo(Item item,
+ int index)
+{
+ WidgetInfo *wi = item->wi;
+ int old_first, old_last;
+ Item old_sel_item;
+
+ old_first = wi->text_info.sel_first;
+ old_last = wi->text_info.sel_last;
+ old_sel_item = wi->text_info.sel_item;
+
+ /*
+ * Grab the selection if we don't own it already.
+ */
+ if (wi->text_info.sel_item == ZN_NO_ITEM) {
+ Tk_OwnSelection(wi->win, XA_PRIMARY, LostSelection, (ClientData) wi);
+ }
+ else if (wi->text_info.sel_item != item) {
+ ITEM.Invalidate(wi->text_info.sel_item, ZN_DRAW_FLAG);
+ }
+ wi->text_info.sel_item = item;
+
+ if (wi->text_info.anchor_item != item) {
+ wi->text_info.anchor_item = item;
+ wi->text_info.sel_anchor = index;
+ }
+ if (wi->text_info.sel_anchor <= index) {
+ wi->text_info.sel_first = wi->text_info.sel_anchor;
+ wi->text_info.sel_last = index;
+ }
+ else {
+ wi->text_info.sel_first = index;
+ wi->text_info.sel_last = wi->text_info.sel_anchor;
+ }
+ if ((wi->text_info.sel_first != old_first) ||
+ (wi->text_info.sel_last != old_last) ||
+ (item != old_sel_item)) {
+ ITEM.Invalidate(item, ZN_DRAW_FLAG);
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FetchSelection --
+ *
+ * This procedure is invoked by Tk to return part or all of
+ * the selection, when the selection is in a zinc widget.
+ * This procedure always returns the selection as a STRING.
+ *
+ * Results:
+ * The return value is the number of non-NULL bytes stored
+ * at buffer. Buffer is filled (or partially filled) with a
+ * NULL-terminated string containing part or all of the selection,
+ * as given by offset and maxBytes.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+static int
+FetchSelection( ClientData client_data,
+ int offset, /* Offset within selection of first
+ * character to be returned. */
+ char *buffer, /* Location in which to place selection. */
+ int max_bytes) /* Maximum number of bytes to place
+ * at buffer, not including terminating
+ * NULL character. */
+{
+ WidgetInfo *wi = (WidgetInfo *) client_data;
+
+ if (wi->text_info.sel_item == NULL) {
+ return -1;
+ }
+ if (wi->text_info.sel_item->class->Selection == NULL) {
+ return -1;
+ }
+ return (*wi->text_info.sel_item->class->Selection)(wi->text_info.sel_item, offset,
+ buffer, max_bytes);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
* CmdDeleted --
*
* This procedure is invoked when a widget command is deleted. If
@@ -3803,7 +4354,7 @@ Destroy(char *mem_ptr) /* Info about the widget. */
/*
* Print remaining items.
*/
- printf("Remaining item count: %d\n", wi->num_items);
+ /*printf("Remaining item count: %d\n", wi->num_items);*/
/* Free all items. */
ITEM.DestroyItem(wi->top_group);
@@ -3959,6 +4510,29 @@ Redisplay(ClientData client_data) /* Information about the widget. */
*/
ITEM_P.Repair(wi);
+ /*
+ * Redraw the borders.
+ */
+ if (wi->border_width > 0) {
+ /*printf("win size %d %d\n", Tk_Width(wi->win), Tk_Height(wi->win));*/
+ Tk_Draw3DRectangle(wi->win, ZnWindowId(wi->win), wi->bg_border,
+ wi->highlight_width, wi->highlight_width,
+ Tk_Width(wi->win) - 2*wi->highlight_width,
+ Tk_Height(wi->win) - 2*wi->highlight_width,
+ wi->border_width, wi->relief);
+
+ }
+ if (wi->highlight_width > 0) {
+ GC gc;
+ if (wi->text_info.got_focus) {
+ gc = Tk_GCForColor(wi->highlight_color, Tk_WindowId(wi->win));
+ }
+ else {
+ gc = Tk_GCForColor(wi->highlight_bg_color, Tk_WindowId(wi->win));
+ }
+ Tk_DrawFocusHighlight(wi->win, gc, wi->highlight_width, Tk_WindowId(wi->win));
+ }
+
ResetBBox(&merge);
CopyBBox(&wi->damaged_area, &merge);
AddBBoxToBBox(&merge, &wi->exposed_area);
@@ -3967,19 +4541,9 @@ Redisplay(ClientData client_data) /* Information about the widget. */
/*printf("redisplay %d %d %d %d\n", r.x, r.y, r.width, r.height);*/
XCopyArea(wi->dpy,
wi->draw_buffer, ZnWindowId(wi->win), wi->gc,
- r.x, r.y, r.width, r.height, r.x+wi->border_width, r.y+wi->border_width);
- }
- /*
- * Redraw the borders.
- */
- if (wi->border_width > 0) {
- /*printf("win size %d %d\n", Tk_Width(wi->win), Tk_Height(wi->win));*/
- Tk_Draw3DRectangle(wi->win, ZnWindowId(wi->win),
- wi->bg_border, 0, 0,
- Tk_Width(wi->win), Tk_Height(wi->win),
- wi->border_width, wi->relief);
-
+ r.x, r.y, r.width, r.height, r.x+wi->inset, r.y+wi->inset);
}
+
/*
* Reset the exposed & damaged areas.
*/
@@ -4484,8 +5048,8 @@ MapInfoCmd(ClientData client_data,
line_style, coords[0], coords[1], LangString(args[num_param+4]));
}
else {
- printf("replace text ts %d ls %d %d %d %s\n", text_style,
- line_style, coords[0], coords[1], LangString(args[num_param+4]));
+ /*printf("replace text ts %d ls %d %d %d %s\n", text_style,
+ line_style, coords[0], coords[1], LangString(args[num_param+4]));*/
MapInfoReplaceText(master->map_info, index, NULL, text_style,
line_style, coords[0], coords[1], LangString(args[num_param+4]));
}