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 */
|