1 |
/* $Header$ */ |
2 |
|
3 |
/* |
4 |
* tkUtil.c -- |
5 |
* |
6 |
* This file contains miscellaneous utility procedures that |
7 |
* are used by the rest of Tk, such as a procedure for drawing |
8 |
* a focus highlight. |
9 |
* |
10 |
* Copyright (c) 1994 The Regents of the University of California. |
11 |
* Copyright (c) 1994-1997 Sun Microsystems, Inc. |
12 |
* |
13 |
* See the file "license.terms" for information on usage and redistribution |
14 |
* of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
15 |
* |
16 |
* RCS: @(#) $Id: tkutil.c,v 1.1.1.1 2001/06/13 05:11:37 dtashley Exp $ |
17 |
*/ |
18 |
|
19 |
#include "tkInt.h" |
20 |
#include "tkPort.h" |
21 |
|
22 |
/* |
23 |
* The structure below defines the implementation of the "statekey" |
24 |
* Tcl object, used for quickly finding a mapping in a TkStateMap. |
25 |
*/ |
26 |
|
27 |
static Tcl_ObjType stateKeyType = { |
28 |
"statekey", /* name */ |
29 |
(Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */ |
30 |
(Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */ |
31 |
(Tcl_UpdateStringProc *) NULL, /* updateStringProc */ |
32 |
(Tcl_SetFromAnyProc *) NULL /* setFromAnyProc */ |
33 |
}; |
34 |
|
35 |
|
36 |
/* |
37 |
*-------------------------------------------------------------- |
38 |
* |
39 |
* TkStateParseProc -- |
40 |
* |
41 |
* This procedure is invoked during option processing to handle |
42 |
* the "-state" and "-default" options. |
43 |
* |
44 |
* Results: |
45 |
* A standard Tcl return value. |
46 |
* |
47 |
* Side effects: |
48 |
* The state for a given item gets replaced by the state |
49 |
* indicated in the value argument. |
50 |
* |
51 |
*-------------------------------------------------------------- |
52 |
*/ |
53 |
|
54 |
int |
55 |
TkStateParseProc(clientData, interp, tkwin, value, widgRec, offset) |
56 |
ClientData clientData; /* some flags.*/ |
57 |
Tcl_Interp *interp; /* Used for reporting errors. */ |
58 |
Tk_Window tkwin; /* Window containing canvas widget. */ |
59 |
CONST char *value; /* Value of option. */ |
60 |
char *widgRec; /* Pointer to record for item. */ |
61 |
int offset; /* Offset into item. */ |
62 |
{ |
63 |
int c; |
64 |
int flags = (int)clientData; |
65 |
size_t length; |
66 |
|
67 |
register Tk_State *statePtr = (Tk_State *) (widgRec + offset); |
68 |
|
69 |
if(value == NULL || *value == 0) { |
70 |
*statePtr = TK_STATE_NULL; |
71 |
return TCL_OK; |
72 |
} |
73 |
|
74 |
c = value[0]; |
75 |
length = strlen(value); |
76 |
|
77 |
if ((c == 'n') && (strncmp(value, "normal", length) == 0)) { |
78 |
*statePtr = TK_STATE_NORMAL; |
79 |
return TCL_OK; |
80 |
} |
81 |
if ((c == 'd') && (strncmp(value, "disabled", length) == 0)) { |
82 |
*statePtr = TK_STATE_DISABLED; |
83 |
return TCL_OK; |
84 |
} |
85 |
if ((c == 'a') && (flags&1) && (strncmp(value, "active", length) == 0)) { |
86 |
*statePtr = TK_STATE_ACTIVE; |
87 |
return TCL_OK; |
88 |
} |
89 |
if ((c == 'h') && (flags&2) && (strncmp(value, "hidden", length) == 0)) { |
90 |
*statePtr = TK_STATE_HIDDEN; |
91 |
return TCL_OK; |
92 |
} |
93 |
|
94 |
Tcl_AppendResult(interp, "bad ", (flags&4)?"-default" : "state", |
95 |
" value \"", value, "\": must be normal", |
96 |
(char *) NULL); |
97 |
if (flags&1) { |
98 |
Tcl_AppendResult(interp, ", active",(char *) NULL); |
99 |
} |
100 |
if (flags&2) { |
101 |
Tcl_AppendResult(interp, ", hidden",(char *) NULL); |
102 |
} |
103 |
if (flags&3) { |
104 |
Tcl_AppendResult(interp, ",",(char *) NULL); |
105 |
} |
106 |
Tcl_AppendResult(interp, " or disabled",(char *) NULL); |
107 |
*statePtr = TK_STATE_NORMAL; |
108 |
return TCL_ERROR; |
109 |
} |
110 |
|
111 |
/* |
112 |
*-------------------------------------------------------------- |
113 |
* |
114 |
* TkStatePrintProc -- |
115 |
* |
116 |
* This procedure is invoked by the Tk configuration code |
117 |
* to produce a printable string for the "-state" |
118 |
* configuration option. |
119 |
* |
120 |
* Results: |
121 |
* The return value is a string describing the state for |
122 |
* the item referred to by "widgRec". In addition, *freeProcPtr |
123 |
* is filled in with the address of a procedure to call to free |
124 |
* the result string when it's no longer needed (or NULL to |
125 |
* indicate that the string doesn't need to be freed). |
126 |
* |
127 |
* Side effects: |
128 |
* None. |
129 |
* |
130 |
*-------------------------------------------------------------- |
131 |
*/ |
132 |
|
133 |
char * |
134 |
TkStatePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) |
135 |
ClientData clientData; /* Ignored. */ |
136 |
Tk_Window tkwin; /* Window containing canvas widget. */ |
137 |
char *widgRec; /* Pointer to record for item. */ |
138 |
int offset; /* Offset into item. */ |
139 |
Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with |
140 |
* information about how to reclaim |
141 |
* storage for return string. */ |
142 |
{ |
143 |
register Tk_State *statePtr = (Tk_State *) (widgRec + offset); |
144 |
|
145 |
if (*statePtr==TK_STATE_NORMAL) { |
146 |
return "normal"; |
147 |
} else if (*statePtr==TK_STATE_DISABLED) { |
148 |
return "disabled"; |
149 |
} else if (*statePtr==TK_STATE_HIDDEN) { |
150 |
return "hidden"; |
151 |
} else if (*statePtr==TK_STATE_ACTIVE) { |
152 |
return "active"; |
153 |
} else { |
154 |
return ""; |
155 |
} |
156 |
} |
157 |
|
158 |
/* |
159 |
*-------------------------------------------------------------- |
160 |
* |
161 |
* TkOrientParseProc -- |
162 |
* |
163 |
* This procedure is invoked during option processing to handle |
164 |
* the "-orient" option. |
165 |
* |
166 |
* Results: |
167 |
* A standard Tcl return value. |
168 |
* |
169 |
* Side effects: |
170 |
* The orientation for a given item gets replaced by the orientation |
171 |
* indicated in the value argument. |
172 |
* |
173 |
*-------------------------------------------------------------- |
174 |
*/ |
175 |
|
176 |
int |
177 |
TkOrientParseProc(clientData, interp, tkwin, value, widgRec, offset) |
178 |
ClientData clientData; /* some flags.*/ |
179 |
Tcl_Interp *interp; /* Used for reporting errors. */ |
180 |
Tk_Window tkwin; /* Window containing canvas widget. */ |
181 |
CONST char *value; /* Value of option. */ |
182 |
char *widgRec; /* Pointer to record for item. */ |
183 |
int offset; /* Offset into item. */ |
184 |
{ |
185 |
int c; |
186 |
size_t length; |
187 |
|
188 |
register int *orientPtr = (int *) (widgRec + offset); |
189 |
|
190 |
if(value == NULL || *value == 0) { |
191 |
*orientPtr = 0; |
192 |
return TCL_OK; |
193 |
} |
194 |
|
195 |
c = value[0]; |
196 |
length = strlen(value); |
197 |
|
198 |
if ((c == 'h') && (strncmp(value, "horizontal", length) == 0)) { |
199 |
*orientPtr = 0; |
200 |
return TCL_OK; |
201 |
} |
202 |
if ((c == 'v') && (strncmp(value, "vertical", length) == 0)) { |
203 |
*orientPtr = 1; |
204 |
return TCL_OK; |
205 |
} |
206 |
Tcl_AppendResult(interp, "bad orientation \"", value, |
207 |
"\": must be vertical or horizontal", |
208 |
(char *) NULL); |
209 |
*orientPtr = 0; |
210 |
return TCL_ERROR; |
211 |
} |
212 |
|
213 |
/* |
214 |
*-------------------------------------------------------------- |
215 |
* |
216 |
* TkOrientPrintProc -- |
217 |
* |
218 |
* This procedure is invoked by the Tk configuration code |
219 |
* to produce a printable string for the "-orient" |
220 |
* configuration option. |
221 |
* |
222 |
* Results: |
223 |
* The return value is a string describing the orientation for |
224 |
* the item referred to by "widgRec". In addition, *freeProcPtr |
225 |
* is filled in with the address of a procedure to call to free |
226 |
* the result string when it's no longer needed (or NULL to |
227 |
* indicate that the string doesn't need to be freed). |
228 |
* |
229 |
* Side effects: |
230 |
* None. |
231 |
* |
232 |
*-------------------------------------------------------------- |
233 |
*/ |
234 |
|
235 |
char * |
236 |
TkOrientPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) |
237 |
ClientData clientData; /* Ignored. */ |
238 |
Tk_Window tkwin; /* Window containing canvas widget. */ |
239 |
char *widgRec; /* Pointer to record for item. */ |
240 |
int offset; /* Offset into item. */ |
241 |
Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with |
242 |
* information about how to reclaim |
243 |
* storage for return string. */ |
244 |
{ |
245 |
register int *statePtr = (int *) (widgRec + offset); |
246 |
|
247 |
if (*statePtr) { |
248 |
return "vertical"; |
249 |
} else { |
250 |
return "horizontal"; |
251 |
} |
252 |
} |
253 |
|
254 |
/* |
255 |
*---------------------------------------------------------------------- |
256 |
* |
257 |
* TkOffsetParseProc -- |
258 |
* |
259 |
* Converts the offset of a stipple or tile into the Tk_TSOffset structure. |
260 |
* |
261 |
*---------------------------------------------------------------------- |
262 |
*/ |
263 |
|
264 |
int |
265 |
TkOffsetParseProc(clientData, interp, tkwin, value, widgRec, offset) |
266 |
ClientData clientData; /* not used */ |
267 |
Tcl_Interp *interp; /* Interpreter to send results back to */ |
268 |
Tk_Window tkwin; /* Window on same display as tile */ |
269 |
CONST char *value; /* Name of image */ |
270 |
char *widgRec; /* Widget structure record */ |
271 |
int offset; /* Offset of tile in record */ |
272 |
{ |
273 |
Tk_TSOffset *offsetPtr = (Tk_TSOffset *)(widgRec + offset); |
274 |
Tk_TSOffset tsoffset; |
275 |
CONST char *q, *p; |
276 |
int result; |
277 |
|
278 |
if ((value == NULL) || (*value == 0)) { |
279 |
tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE; |
280 |
goto goodTSOffset; |
281 |
} |
282 |
tsoffset.flags = 0; |
283 |
p = value; |
284 |
|
285 |
switch(value[0]) { |
286 |
case '#': |
287 |
if (((int)clientData) & TK_OFFSET_RELATIVE) { |
288 |
tsoffset.flags = TK_OFFSET_RELATIVE; |
289 |
p++; break; |
290 |
} |
291 |
goto badTSOffset; |
292 |
case 'e': |
293 |
switch(value[1]) { |
294 |
case '\0': |
295 |
tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_MIDDLE; |
296 |
goto goodTSOffset; |
297 |
case 'n': |
298 |
if (value[2]!='d' || value[3]!='\0') {goto badTSOffset;} |
299 |
tsoffset.flags = INT_MAX; |
300 |
goto goodTSOffset; |
301 |
} |
302 |
case 'w': |
303 |
if (value[1] != '\0') {goto badTSOffset;} |
304 |
tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_MIDDLE; |
305 |
goto goodTSOffset; |
306 |
case 'n': |
307 |
if ((value[1] != '\0') && (value[2] != '\0')) { |
308 |
goto badTSOffset; |
309 |
} |
310 |
switch(value[1]) { |
311 |
case '\0': tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_TOP; |
312 |
goto goodTSOffset; |
313 |
case 'w': tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_TOP; |
314 |
goto goodTSOffset; |
315 |
case 'e': tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_TOP; |
316 |
goto goodTSOffset; |
317 |
} |
318 |
goto badTSOffset; |
319 |
case 's': |
320 |
if ((value[1] != '\0') && (value[2] != '\0')) { |
321 |
goto badTSOffset; |
322 |
} |
323 |
switch(value[1]) { |
324 |
case '\0': tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_BOTTOM; |
325 |
goto goodTSOffset; |
326 |
case 'w': tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_BOTTOM; |
327 |
goto goodTSOffset; |
328 |
case 'e': tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_BOTTOM; |
329 |
goto goodTSOffset; |
330 |
} |
331 |
goto badTSOffset; |
332 |
case 'c': |
333 |
if (strncmp(value, "center", strlen(value)) != 0) { |
334 |
goto badTSOffset; |
335 |
} |
336 |
tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE; |
337 |
goto goodTSOffset; |
338 |
} |
339 |
if ((q = strchr(p,',')) == NULL) { |
340 |
if (((int)clientData) & TK_OFFSET_INDEX) { |
341 |
if (Tcl_GetInt(interp, (char *) p, &tsoffset.flags) != TCL_OK) { |
342 |
Tcl_ResetResult(interp); |
343 |
goto badTSOffset; |
344 |
} |
345 |
tsoffset.flags |= TK_OFFSET_INDEX; |
346 |
goto goodTSOffset; |
347 |
} |
348 |
goto badTSOffset; |
349 |
} |
350 |
*((char *) q) = 0; |
351 |
result = Tk_GetPixels(interp, tkwin, (char *) p, &tsoffset.xoffset); |
352 |
*((char *) q) = ','; |
353 |
if (result != TCL_OK) { |
354 |
return TCL_ERROR; |
355 |
} |
356 |
if (Tk_GetPixels(interp, tkwin, (char *) q+1, &tsoffset.yoffset) != TCL_OK) { |
357 |
return TCL_ERROR; |
358 |
} |
359 |
|
360 |
|
361 |
goodTSOffset: |
362 |
/* below is a hack to allow the stipple/tile offset to be stored |
363 |
* in the internal tile structure. Most of the times, offsetPtr |
364 |
* is a pointer to an already existing tile structure. However |
365 |
* if this structure is not already created, we must do it |
366 |
* with Tk_GetTile()!!!!; |
367 |
*/ |
368 |
|
369 |
memcpy(offsetPtr,&tsoffset, sizeof(Tk_TSOffset)); |
370 |
return TCL_OK; |
371 |
|
372 |
badTSOffset: |
373 |
Tcl_AppendResult(interp, "bad offset \"", value, |
374 |
"\": expected \"x,y\"", (char *) NULL); |
375 |
if (((int) clientData) & TK_OFFSET_RELATIVE) { |
376 |
Tcl_AppendResult(interp, ", \"#x,y\"", (char *) NULL); |
377 |
} |
378 |
if (((int) clientData) & TK_OFFSET_INDEX) { |
379 |
Tcl_AppendResult(interp, ", <index>", (char *) NULL); |
380 |
} |
381 |
Tcl_AppendResult(interp, ", n, ne, e, se, s, sw, w, nw, or center", |
382 |
(char *) NULL); |
383 |
return TCL_ERROR; |
384 |
} |
385 |
|
386 |
/* |
387 |
*---------------------------------------------------------------------- |
388 |
* |
389 |
* TkOffsetPrintProc -- |
390 |
* |
391 |
* Returns the offset of the tile. |
392 |
* |
393 |
* Results: |
394 |
* The offset of the tile is returned. |
395 |
* |
396 |
*---------------------------------------------------------------------- |
397 |
*/ |
398 |
|
399 |
char * |
400 |
TkOffsetPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) |
401 |
ClientData clientData; /* not used */ |
402 |
Tk_Window tkwin; /* not used */ |
403 |
char *widgRec; /* Widget structure record */ |
404 |
int offset; /* Offset of tile in record */ |
405 |
Tcl_FreeProc **freeProcPtr; /* not used */ |
406 |
{ |
407 |
Tk_TSOffset *offsetPtr = (Tk_TSOffset *)(widgRec + offset); |
408 |
char *p, *q; |
409 |
|
410 |
if ((offsetPtr->flags) & TK_OFFSET_INDEX) { |
411 |
if ((offsetPtr->flags) >= INT_MAX) { |
412 |
return "end"; |
413 |
} |
414 |
p = (char *) ckalloc(32); |
415 |
sprintf(p, "%d",(offsetPtr->flags & (~TK_OFFSET_INDEX))); |
416 |
*freeProcPtr = TCL_DYNAMIC; |
417 |
return p; |
418 |
} |
419 |
if ((offsetPtr->flags) & TK_OFFSET_TOP) { |
420 |
if ((offsetPtr->flags) & TK_OFFSET_LEFT) { |
421 |
return "nw"; |
422 |
} else if ((offsetPtr->flags) & TK_OFFSET_CENTER) { |
423 |
return "n"; |
424 |
} else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) { |
425 |
return "ne"; |
426 |
} |
427 |
} else if ((offsetPtr->flags) & TK_OFFSET_MIDDLE) { |
428 |
if ((offsetPtr->flags) & TK_OFFSET_LEFT) { |
429 |
return "w"; |
430 |
} else if ((offsetPtr->flags) & TK_OFFSET_CENTER) { |
431 |
return "center"; |
432 |
} else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) { |
433 |
return "e"; |
434 |
} |
435 |
} else if ((offsetPtr->flags) & TK_OFFSET_BOTTOM) { |
436 |
if ((offsetPtr->flags) & TK_OFFSET_LEFT) { |
437 |
return "sw"; |
438 |
} else if ((offsetPtr->flags) & TK_OFFSET_CENTER) { |
439 |
return "s"; |
440 |
} else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) { |
441 |
return "se"; |
442 |
} |
443 |
} |
444 |
q = p = (char *) ckalloc(32); |
445 |
if ((offsetPtr->flags) & TK_OFFSET_RELATIVE) { |
446 |
*q++ = '#'; |
447 |
} |
448 |
sprintf(q, "%d,%d",offsetPtr->xoffset, offsetPtr->yoffset); |
449 |
*freeProcPtr = TCL_DYNAMIC; |
450 |
return p; |
451 |
} |
452 |
|
453 |
|
454 |
/* |
455 |
*---------------------------------------------------------------------- |
456 |
* |
457 |
* TkPixelParseProc -- |
458 |
* |
459 |
* Converts the name of an image into a tile. |
460 |
* |
461 |
*---------------------------------------------------------------------- |
462 |
*/ |
463 |
|
464 |
int |
465 |
TkPixelParseProc(clientData, interp, tkwin, value, widgRec, offset) |
466 |
ClientData clientData; /* if non-NULL, negative values are |
467 |
* allowed as well */ |
468 |
Tcl_Interp *interp; /* Interpreter to send results back to */ |
469 |
Tk_Window tkwin; /* Window on same display as tile */ |
470 |
CONST char *value; /* Name of image */ |
471 |
char *widgRec; /* Widget structure record */ |
472 |
int offset; /* Offset of tile in record */ |
473 |
{ |
474 |
double *doublePtr = (double *)(widgRec + offset); |
475 |
int result; |
476 |
|
477 |
result = TkGetDoublePixels(interp, tkwin, value, doublePtr); |
478 |
|
479 |
if ((result == TCL_OK) && (clientData == NULL) && (*doublePtr < 0.0)) { |
480 |
Tcl_AppendResult(interp, "bad screen distance \"", value, |
481 |
"\"", (char *) NULL); |
482 |
return TCL_ERROR; |
483 |
} |
484 |
return result; |
485 |
} |
486 |
|
487 |
/* |
488 |
*---------------------------------------------------------------------- |
489 |
* |
490 |
* TkPixelPrintProc -- |
491 |
* |
492 |
* Returns the name of the tile. |
493 |
* |
494 |
* Results: |
495 |
* The name of the tile is returned. |
496 |
* |
497 |
*---------------------------------------------------------------------- |
498 |
*/ |
499 |
|
500 |
char * |
501 |
TkPixelPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) |
502 |
ClientData clientData; /* not used */ |
503 |
Tk_Window tkwin; /* not used */ |
504 |
char *widgRec; /* Widget structure record */ |
505 |
int offset; /* Offset of tile in record */ |
506 |
Tcl_FreeProc **freeProcPtr; /* not used */ |
507 |
{ |
508 |
double *doublePtr = (double *)(widgRec + offset); |
509 |
char *p; |
510 |
|
511 |
p = (char *) ckalloc(24); |
512 |
Tcl_PrintDouble((Tcl_Interp *) NULL, *doublePtr, p); |
513 |
*freeProcPtr = TCL_DYNAMIC; |
514 |
return p; |
515 |
} |
516 |
|
517 |
/* |
518 |
*---------------------------------------------------------------------- |
519 |
* |
520 |
* TkDrawInsetFocusHighlight -- |
521 |
* |
522 |
* This procedure draws a rectangular ring around the outside of |
523 |
* a widget to indicate that it has received the input focus. It |
524 |
* takes an additional padding argument that specifies how much |
525 |
* padding is present outside th widget. |
526 |
* |
527 |
* Results: |
528 |
* None. |
529 |
* |
530 |
* Side effects: |
531 |
* A rectangle "width" pixels wide is drawn in "drawable", |
532 |
* corresponding to the outer area of "tkwin". |
533 |
* |
534 |
*---------------------------------------------------------------------- |
535 |
*/ |
536 |
|
537 |
void |
538 |
TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, padding) |
539 |
Tk_Window tkwin; /* Window whose focus highlight ring is |
540 |
* to be drawn. */ |
541 |
GC gc; /* Graphics context to use for drawing |
542 |
* the highlight ring. */ |
543 |
int width; /* Width of the highlight ring, in pixels. */ |
544 |
Drawable drawable; /* Where to draw the ring (typically a |
545 |
* pixmap for double buffering). */ |
546 |
int padding; /* Width of padding outside of widget. */ |
547 |
{ |
548 |
XRectangle rects[4]; |
549 |
|
550 |
rects[0].x = padding; |
551 |
rects[0].y = padding; |
552 |
rects[0].width = Tk_Width(tkwin) - (2 * padding); |
553 |
rects[0].height = width; |
554 |
rects[1].x = padding; |
555 |
rects[1].y = Tk_Height(tkwin) - width - padding; |
556 |
rects[1].width = Tk_Width(tkwin) - (2 * padding); |
557 |
rects[1].height = width; |
558 |
rects[2].x = padding; |
559 |
rects[2].y = width + padding; |
560 |
rects[2].width = width; |
561 |
rects[2].height = Tk_Height(tkwin) - 2*width - 2*padding; |
562 |
rects[3].x = Tk_Width(tkwin) - width - padding; |
563 |
rects[3].y = rects[2].y; |
564 |
rects[3].width = width; |
565 |
rects[3].height = rects[2].height; |
566 |
XFillRectangles(Tk_Display(tkwin), drawable, gc, rects, 4); |
567 |
} |
568 |
|
569 |
/* |
570 |
*---------------------------------------------------------------------- |
571 |
* |
572 |
* Tk_DrawFocusHighlight -- |
573 |
* |
574 |
* This procedure draws a rectangular ring around the outside of |
575 |
* a widget to indicate that it has received the input focus. |
576 |
* |
577 |
* This function is now deprecated. Use TkpDrawHighlightBorder instead, |
578 |
* since this function does not handle drawing the Focus ring properly |
579 |
* on the Macintosh - you need to know the background GC as well |
580 |
* as the foreground since the Mac focus ring separated from the widget |
581 |
* by a 1 pixel border. |
582 |
* |
583 |
* Results: |
584 |
* None. |
585 |
* |
586 |
* Side effects: |
587 |
* A rectangle "width" pixels wide is drawn in "drawable", |
588 |
* corresponding to the outer area of "tkwin". |
589 |
* |
590 |
*---------------------------------------------------------------------- |
591 |
*/ |
592 |
|
593 |
void |
594 |
Tk_DrawFocusHighlight(tkwin, gc, width, drawable) |
595 |
Tk_Window tkwin; /* Window whose focus highlight ring is |
596 |
* to be drawn. */ |
597 |
GC gc; /* Graphics context to use for drawing |
598 |
* the highlight ring. */ |
599 |
int width; /* Width of the highlight ring, in pixels. */ |
600 |
Drawable drawable; /* Where to draw the ring (typically a |
601 |
* pixmap for double buffering). */ |
602 |
{ |
603 |
TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, 0); |
604 |
} |
605 |
|
606 |
/* |
607 |
*---------------------------------------------------------------------- |
608 |
* |
609 |
* Tk_GetScrollInfo -- |
610 |
* |
611 |
* This procedure is invoked to parse "xview" and "yview" |
612 |
* scrolling commands for widgets using the new scrolling |
613 |
* command syntax ("moveto" or "scroll" options). |
614 |
* |
615 |
* Results: |
616 |
* The return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES, |
617 |
* TK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether |
618 |
* the command was successfully parsed and what form the command |
619 |
* took. If TK_SCROLL_MOVETO, *dblPtr is filled in with the |
620 |
* desired position; if TK_SCROLL_PAGES or TK_SCROLL_UNITS, |
621 |
* *intPtr is filled in with the number of lines to move (may be |
622 |
* negative); if TK_SCROLL_ERROR, the interp's result contains an |
623 |
* error message. |
624 |
* |
625 |
* Side effects: |
626 |
* None. |
627 |
* |
628 |
*---------------------------------------------------------------------- |
629 |
*/ |
630 |
|
631 |
int |
632 |
Tk_GetScrollInfo(interp, argc, argv, dblPtr, intPtr) |
633 |
Tcl_Interp *interp; /* Used for error reporting. */ |
634 |
int argc; /* # arguments for command. */ |
635 |
char **argv; /* Arguments for command. */ |
636 |
double *dblPtr; /* Filled in with argument "moveto" |
637 |
* option, if any. */ |
638 |
int *intPtr; /* Filled in with number of pages |
639 |
* or lines to scroll, if any. */ |
640 |
{ |
641 |
int c; |
642 |
size_t length; |
643 |
|
644 |
length = strlen(argv[2]); |
645 |
c = argv[2][0]; |
646 |
if ((c == 'm') && (strncmp(argv[2], "moveto", length) == 0)) { |
647 |
if (argc != 4) { |
648 |
Tcl_AppendResult(interp, "wrong # args: should be \"", |
649 |
argv[0], " ", argv[1], " moveto fraction\"", |
650 |
(char *) NULL); |
651 |
return TK_SCROLL_ERROR; |
652 |
} |
653 |
if (Tcl_GetDouble(interp, argv[3], dblPtr) != TCL_OK) { |
654 |
return TK_SCROLL_ERROR; |
655 |
} |
656 |
return TK_SCROLL_MOVETO; |
657 |
} else if ((c == 's') |
658 |
&& (strncmp(argv[2], "scroll", length) == 0)) { |
659 |
if (argc != 5) { |
660 |
Tcl_AppendResult(interp, "wrong # args: should be \"", |
661 |
argv[0], " ", argv[1], " scroll number units|pages\"", |
662 |
(char *) NULL); |
663 |
return TK_SCROLL_ERROR; |
664 |
} |
665 |
if (Tcl_GetInt(interp, argv[3], intPtr) != TCL_OK) { |
666 |
return TK_SCROLL_ERROR; |
667 |
} |
668 |
length = strlen(argv[4]); |
669 |
c = argv[4][0]; |
670 |
if ((c == 'p') && (strncmp(argv[4], "pages", length) == 0)) { |
671 |
return TK_SCROLL_PAGES; |
672 |
} else if ((c == 'u') |
673 |
&& (strncmp(argv[4], "units", length) == 0)) { |
674 |
return TK_SCROLL_UNITS; |
675 |
} else { |
676 |
Tcl_AppendResult(interp, "bad argument \"", argv[4], |
677 |
"\": must be units or pages", (char *) NULL); |
678 |
return TK_SCROLL_ERROR; |
679 |
} |
680 |
} |
681 |
Tcl_AppendResult(interp, "unknown option \"", argv[2], |
682 |
"\": must be moveto or scroll", (char *) NULL); |
683 |
return TK_SCROLL_ERROR; |
684 |
} |
685 |
|
686 |
/* |
687 |
*---------------------------------------------------------------------- |
688 |
* |
689 |
* Tk_GetScrollInfoObj -- |
690 |
* |
691 |
* This procedure is invoked to parse "xview" and "yview" |
692 |
* scrolling commands for widgets using the new scrolling |
693 |
* command syntax ("moveto" or "scroll" options). |
694 |
* |
695 |
* Results: |
696 |
* The return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES, |
697 |
* TK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether |
698 |
* the command was successfully parsed and what form the command |
699 |
* took. If TK_SCROLL_MOVETO, *dblPtr is filled in with the |
700 |
* desired position; if TK_SCROLL_PAGES or TK_SCROLL_UNITS, |
701 |
* *intPtr is filled in with the number of lines to move (may be |
702 |
* negative); if TK_SCROLL_ERROR, the interp's result contains an |
703 |
* error message. |
704 |
* |
705 |
* Side effects: |
706 |
* None. |
707 |
* |
708 |
*---------------------------------------------------------------------- |
709 |
*/ |
710 |
|
711 |
int |
712 |
Tk_GetScrollInfoObj(interp, objc, objv, dblPtr, intPtr) |
713 |
Tcl_Interp *interp; /* Used for error reporting. */ |
714 |
int objc; /* # arguments for command. */ |
715 |
Tcl_Obj *CONST objv[]; /* Arguments for command. */ |
716 |
double *dblPtr; /* Filled in with argument "moveto" |
717 |
* option, if any. */ |
718 |
int *intPtr; /* Filled in with number of pages |
719 |
* or lines to scroll, if any. */ |
720 |
{ |
721 |
int c; |
722 |
size_t length; |
723 |
char *arg2, *arg4; |
724 |
|
725 |
arg2 = Tcl_GetString(objv[2]); |
726 |
length = strlen(arg2); |
727 |
c = arg2[0]; |
728 |
if ((c == 'm') && (strncmp(arg2, "moveto", length) == 0)) { |
729 |
if (objc != 4) { |
730 |
Tcl_WrongNumArgs(interp, 2, objv, "moveto fraction"); |
731 |
return TK_SCROLL_ERROR; |
732 |
} |
733 |
if (Tcl_GetDoubleFromObj(interp, objv[3], dblPtr) != TCL_OK) { |
734 |
return TK_SCROLL_ERROR; |
735 |
} |
736 |
return TK_SCROLL_MOVETO; |
737 |
} else if ((c == 's') |
738 |
&& (strncmp(arg2, "scroll", length) == 0)) { |
739 |
if (objc != 5) { |
740 |
Tcl_WrongNumArgs(interp, 2, objv, "scroll number units|pages"); |
741 |
return TK_SCROLL_ERROR; |
742 |
} |
743 |
if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) { |
744 |
return TK_SCROLL_ERROR; |
745 |
} |
746 |
arg4 = Tcl_GetString(objv[4]); |
747 |
length = (strlen(arg4)); |
748 |
c = arg4[0]; |
749 |
if ((c == 'p') && (strncmp(arg4, "pages", length) == 0)) { |
750 |
return TK_SCROLL_PAGES; |
751 |
} else if ((c == 'u') |
752 |
&& (strncmp(arg4, "units", length) == 0)) { |
753 |
return TK_SCROLL_UNITS; |
754 |
} else { |
755 |
Tcl_AppendResult(interp, "bad argument \"", arg4, |
756 |
"\": must be units or pages", (char *) NULL); |
757 |
return TK_SCROLL_ERROR; |
758 |
} |
759 |
} |
760 |
Tcl_AppendResult(interp, "unknown option \"", arg2, |
761 |
"\": must be moveto or scroll", (char *) NULL); |
762 |
return TK_SCROLL_ERROR; |
763 |
} |
764 |
|
765 |
/* |
766 |
*--------------------------------------------------------------------------- |
767 |
* |
768 |
* TkComputeAnchor -- |
769 |
* |
770 |
* Determine where to place a rectangle so that it will be properly |
771 |
* anchored with respect to the given window. Used by widgets |
772 |
* to align a box of text inside a window. When anchoring with |
773 |
* respect to one of the sides, the rectangle be placed inside of |
774 |
* the internal border of the window. |
775 |
* |
776 |
* Results: |
777 |
* *xPtr and *yPtr set to the upper-left corner of the rectangle |
778 |
* anchored in the window. |
779 |
* |
780 |
* Side effects: |
781 |
* None. |
782 |
* |
783 |
*--------------------------------------------------------------------------- |
784 |
*/ |
785 |
void |
786 |
TkComputeAnchor(anchor, tkwin, padX, padY, innerWidth, innerHeight, xPtr, yPtr) |
787 |
Tk_Anchor anchor; /* Desired anchor. */ |
788 |
Tk_Window tkwin; /* Anchored with respect to this window. */ |
789 |
int padX, padY; /* Use this extra padding inside window, in |
790 |
* addition to the internal border. */ |
791 |
int innerWidth, innerHeight;/* Size of rectangle to anchor in window. */ |
792 |
int *xPtr, *yPtr; /* Returns upper-left corner of anchored |
793 |
* rectangle. */ |
794 |
{ |
795 |
switch (anchor) { |
796 |
case TK_ANCHOR_NW: |
797 |
case TK_ANCHOR_W: |
798 |
case TK_ANCHOR_SW: |
799 |
*xPtr = Tk_InternalBorderWidth(tkwin) + padX; |
800 |
break; |
801 |
|
802 |
case TK_ANCHOR_N: |
803 |
case TK_ANCHOR_CENTER: |
804 |
case TK_ANCHOR_S: |
805 |
*xPtr = (Tk_Width(tkwin) - innerWidth) / 2; |
806 |
break; |
807 |
|
808 |
default: |
809 |
*xPtr = Tk_Width(tkwin) - (Tk_InternalBorderWidth(tkwin) + padX) |
810 |
- innerWidth; |
811 |
break; |
812 |
} |
813 |
|
814 |
switch (anchor) { |
815 |
case TK_ANCHOR_NW: |
816 |
case TK_ANCHOR_N: |
817 |
case TK_ANCHOR_NE: |
818 |
*yPtr = Tk_InternalBorderWidth(tkwin) + padY; |
819 |
break; |
820 |
|
821 |
case TK_ANCHOR_W: |
822 |
case TK_ANCHOR_CENTER: |
823 |
case TK_ANCHOR_E: |
824 |
*yPtr = (Tk_Height(tkwin) - innerHeight) / 2; |
825 |
break; |
826 |
|
827 |
default: |
828 |
*yPtr = Tk_Height(tkwin) - Tk_InternalBorderWidth(tkwin) - padY |
829 |
- innerHeight; |
830 |
break; |
831 |
} |
832 |
} |
833 |
|
834 |
/* |
835 |
*--------------------------------------------------------------------------- |
836 |
* |
837 |
* TkFindStateString -- |
838 |
* |
839 |
* Given a lookup table, map a number to a string in the table. |
840 |
* |
841 |
* Results: |
842 |
* If numKey was equal to the numeric key of one of the elements |
843 |
* in the table, returns the string key of that element. |
844 |
* Returns NULL if numKey was not equal to any of the numeric keys |
845 |
* in the table. |
846 |
* |
847 |
* Side effects. |
848 |
* None. |
849 |
* |
850 |
*--------------------------------------------------------------------------- |
851 |
*/ |
852 |
|
853 |
char * |
854 |
TkFindStateString(mapPtr, numKey) |
855 |
CONST TkStateMap *mapPtr; /* The state table. */ |
856 |
int numKey; /* The key to try to find in the table. */ |
857 |
{ |
858 |
for ( ; mapPtr->strKey != NULL; mapPtr++) { |
859 |
if (numKey == mapPtr->numKey) { |
860 |
return mapPtr->strKey; |
861 |
} |
862 |
} |
863 |
return NULL; |
864 |
} |
865 |
|
866 |
/* |
867 |
*--------------------------------------------------------------------------- |
868 |
* |
869 |
* TkFindStateNum -- |
870 |
* |
871 |
* Given a lookup table, map a string to a number in the table. |
872 |
* |
873 |
* Results: |
874 |
* If strKey was equal to the string keys of one of the elements |
875 |
* in the table, returns the numeric key of that element. |
876 |
* Returns the numKey associated with the last element (the NULL |
877 |
* string one) in the table if strKey was not equal to any of the |
878 |
* string keys in the table. In that case, an error message is |
879 |
* also left in the interp's result (if interp is not NULL). |
880 |
* |
881 |
* Side effects. |
882 |
* None. |
883 |
* |
884 |
*--------------------------------------------------------------------------- |
885 |
*/ |
886 |
|
887 |
int |
888 |
TkFindStateNum(interp, option, mapPtr, strKey) |
889 |
Tcl_Interp *interp; /* Interp for error reporting. */ |
890 |
CONST char *option; /* String to use when constructing error. */ |
891 |
CONST TkStateMap *mapPtr; /* Lookup table. */ |
892 |
CONST char *strKey; /* String to try to find in lookup table. */ |
893 |
{ |
894 |
CONST TkStateMap *mPtr; |
895 |
|
896 |
for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) { |
897 |
if (strcmp(strKey, mPtr->strKey) == 0) { |
898 |
return mPtr->numKey; |
899 |
} |
900 |
} |
901 |
if (interp != NULL) { |
902 |
mPtr = mapPtr; |
903 |
Tcl_AppendResult(interp, "bad ", option, " value \"", strKey, |
904 |
"\": must be ", mPtr->strKey, (char *) NULL); |
905 |
for (mPtr++; mPtr->strKey != NULL; mPtr++) { |
906 |
Tcl_AppendResult(interp, |
907 |
((mPtr[1].strKey != NULL) ? ", " : ", or "), |
908 |
mPtr->strKey, (char *) NULL); |
909 |
} |
910 |
} |
911 |
return mPtr->numKey; |
912 |
} |
913 |
|
914 |
int |
915 |
TkFindStateNumObj(interp, optionPtr, mapPtr, keyPtr) |
916 |
Tcl_Interp *interp; /* Interp for error reporting. */ |
917 |
Tcl_Obj *optionPtr; /* String to use when constructing error. */ |
918 |
CONST TkStateMap *mapPtr; /* Lookup table. */ |
919 |
Tcl_Obj *keyPtr; /* String key to find in lookup table. */ |
920 |
{ |
921 |
CONST TkStateMap *mPtr; |
922 |
CONST char *key; |
923 |
CONST Tcl_ObjType *typePtr; |
924 |
|
925 |
if ((keyPtr->typePtr == &stateKeyType) |
926 |
&& (keyPtr->internalRep.twoPtrValue.ptr1 == (VOID *) mapPtr)) { |
927 |
return (int) keyPtr->internalRep.twoPtrValue.ptr2; |
928 |
} |
929 |
|
930 |
key = Tcl_GetStringFromObj(keyPtr, NULL); |
931 |
for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) { |
932 |
if (strcmp(key, mPtr->strKey) == 0) { |
933 |
typePtr = keyPtr->typePtr; |
934 |
if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { |
935 |
(*typePtr->freeIntRepProc)(keyPtr); |
936 |
} |
937 |
keyPtr->internalRep.twoPtrValue.ptr1 = (VOID *) mapPtr; |
938 |
keyPtr->internalRep.twoPtrValue.ptr2 = (VOID *) mPtr->numKey; |
939 |
keyPtr->typePtr = &stateKeyType; |
940 |
return mPtr->numKey; |
941 |
} |
942 |
} |
943 |
if (interp != NULL) { |
944 |
mPtr = mapPtr; |
945 |
Tcl_AppendResult(interp, "bad ", |
946 |
Tcl_GetStringFromObj(optionPtr, NULL), " value \"", key, |
947 |
"\": must be ", mPtr->strKey, (char *) NULL); |
948 |
for (mPtr++; mPtr->strKey != NULL; mPtr++) { |
949 |
Tcl_AppendResult(interp, |
950 |
((mPtr[1].strKey != NULL) ? ", " : ", or "), |
951 |
mPtr->strKey, (char *) NULL); |
952 |
} |
953 |
} |
954 |
return mPtr->numKey; |
955 |
} |
956 |
|
957 |
/* End of tkutil.c */ |