Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libtk/generic/tkConfig.c
1810 views
1
/*
2
* tkConfig.c --
3
*
4
* This file contains the Tk_ConfigureWidget procedure.
5
*
6
* Copyright (c) 1990-1994 The Regents of the University of California.
7
* Copyright (c) 1994-1995 Sun Microsystems, Inc.
8
*
9
* See the file "license.terms" for information on usage and redistribution
10
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
*
12
* SCCS: @(#) tkConfig.c 1.52 96/02/15 18:52:39
13
*/
14
15
#include "tkInt.h"
16
17
/*
18
* Values for "flags" field of Tk_ConfigSpec structures. Be sure
19
* to coordinate these values with those defined in tk.h
20
* (TK_CONFIG_COLOR_ONLY, etc.). There must not be overlap!
21
*
22
* INIT - Non-zero means (char *) things have been
23
* converted to Tk_Uid's.
24
*/
25
26
#define INIT 0x20
27
28
/*
29
* Forward declarations for procedures defined later in this file:
30
*/
31
32
static int DoConfig _ANSI_ARGS_((Tcl_Interp *interp,
33
Tk_Window tkwin, Tk_ConfigSpec *specPtr,
34
Tk_Uid value, int valueIsUid, char *widgRec));
35
static Tk_ConfigSpec * FindConfigSpec _ANSI_ARGS_((Tcl_Interp *interp,
36
Tk_ConfigSpec *specs, char *argvName,
37
int needFlags, int hateFlags));
38
static char * FormatConfigInfo _ANSI_ARGS_((Tcl_Interp *interp,
39
Tk_Window tkwin, Tk_ConfigSpec *specPtr,
40
char *widgRec));
41
static char * FormatConfigValue _ANSI_ARGS_((Tcl_Interp *interp,
42
Tk_Window tkwin, Tk_ConfigSpec *specPtr,
43
char *widgRec, char *buffer,
44
Tcl_FreeProc **freeProcPtr));
45
46
/*
47
*--------------------------------------------------------------
48
*
49
* Tk_ConfigureWidget --
50
*
51
* Process command-line options and database options to
52
* fill in fields of a widget record with resources and
53
* other parameters.
54
*
55
* Results:
56
* A standard Tcl return value. In case of an error,
57
* interp->result will hold an error message.
58
*
59
* Side effects:
60
* The fields of widgRec get filled in with information
61
* from argc/argv and the option database. Old information
62
* in widgRec's fields gets recycled.
63
*
64
*--------------------------------------------------------------
65
*/
66
67
int
68
Tk_ConfigureWidget(interp, tkwin, specs, argc, argv, widgRec, flags)
69
Tcl_Interp *interp; /* Interpreter for error reporting. */
70
Tk_Window tkwin; /* Window containing widget (needed to
71
* set up X resources). */
72
Tk_ConfigSpec *specs; /* Describes legal options. */
73
int argc; /* Number of elements in argv. */
74
char **argv; /* Command-line options. */
75
char *widgRec; /* Record whose fields are to be
76
* modified. Values must be properly
77
* initialized. */
78
int flags; /* Used to specify additional flags
79
* that must be present in config specs
80
* for them to be considered. Also,
81
* may have TK_CONFIG_ARGV_ONLY set. */
82
{
83
register Tk_ConfigSpec *specPtr;
84
Tk_Uid value; /* Value of option from database. */
85
int needFlags; /* Specs must contain this set of flags
86
* or else they are not considered. */
87
int hateFlags; /* If a spec contains any bits here, it's
88
* not considered. */
89
90
needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
91
if (Tk_Depth(tkwin) <= 1) {
92
hateFlags = TK_CONFIG_COLOR_ONLY;
93
} else {
94
hateFlags = TK_CONFIG_MONO_ONLY;
95
}
96
97
/*
98
* Pass one: scan through all the option specs, replacing strings
99
* with Tk_Uids (if this hasn't been done already) and clearing
100
* the TK_CONFIG_OPTION_SPECIFIED flags.
101
*/
102
103
for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
104
if (!(specPtr->specFlags & INIT) && (specPtr->argvName != NULL)) {
105
if (specPtr->dbName != NULL) {
106
specPtr->dbName = Tk_GetUid(specPtr->dbName);
107
}
108
if (specPtr->dbClass != NULL) {
109
specPtr->dbClass = Tk_GetUid(specPtr->dbClass);
110
}
111
if (specPtr->defValue != NULL) {
112
specPtr->defValue = Tk_GetUid(specPtr->defValue);
113
}
114
}
115
specPtr->specFlags = (specPtr->specFlags & ~TK_CONFIG_OPTION_SPECIFIED)
116
| INIT;
117
}
118
119
/*
120
* Pass two: scan through all of the arguments, processing those
121
* that match entries in the specs.
122
*/
123
124
for ( ; argc > 0; argc -= 2, argv += 2) {
125
specPtr = FindConfigSpec(interp, specs, *argv, needFlags, hateFlags);
126
if (specPtr == NULL) {
127
return TCL_ERROR;
128
}
129
130
/*
131
* Process the entry.
132
*/
133
134
if (argc < 2) {
135
Tcl_AppendResult(interp, "value for \"", *argv,
136
"\" missing", (char *) NULL);
137
return TCL_ERROR;
138
}
139
if (DoConfig(interp, tkwin, specPtr, argv[1], 0, widgRec) != TCL_OK) {
140
char msg[100];
141
142
sprintf(msg, "\n (processing \"%.40s\" option)",
143
specPtr->argvName);
144
Tcl_AddErrorInfo(interp, msg);
145
return TCL_ERROR;
146
}
147
specPtr->specFlags |= TK_CONFIG_OPTION_SPECIFIED;
148
}
149
150
/*
151
* Pass three: scan through all of the specs again; if no
152
* command-line argument matched a spec, then check for info
153
* in the option database. If there was nothing in the
154
* database, then use the default.
155
*/
156
157
if (!(flags & TK_CONFIG_ARGV_ONLY)) {
158
for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
159
if ((specPtr->specFlags & TK_CONFIG_OPTION_SPECIFIED)
160
|| (specPtr->argvName == NULL)
161
|| (specPtr->type == TK_CONFIG_SYNONYM)) {
162
continue;
163
}
164
if (((specPtr->specFlags & needFlags) != needFlags)
165
|| (specPtr->specFlags & hateFlags)) {
166
continue;
167
}
168
value = NULL;
169
if (specPtr->dbName != NULL) {
170
value = Tk_GetOption(tkwin, specPtr->dbName, specPtr->dbClass);
171
}
172
if (value != NULL) {
173
if (DoConfig(interp, tkwin, specPtr, value, 1, widgRec) !=
174
TCL_OK) {
175
char msg[200];
176
177
sprintf(msg, "\n (%s \"%.50s\" in widget \"%.50s\")",
178
"database entry for",
179
specPtr->dbName, Tk_PathName(tkwin));
180
Tcl_AddErrorInfo(interp, msg);
181
return TCL_ERROR;
182
}
183
} else {
184
value = specPtr->defValue;
185
if ((value != NULL) && !(specPtr->specFlags
186
& TK_CONFIG_DONT_SET_DEFAULT)) {
187
if (DoConfig(interp, tkwin, specPtr, value, 1, widgRec) !=
188
TCL_OK) {
189
char msg[200];
190
191
sprintf(msg,
192
"\n (%s \"%.50s\" in widget \"%.50s\")",
193
"default value for",
194
specPtr->dbName, Tk_PathName(tkwin));
195
Tcl_AddErrorInfo(interp, msg);
196
return TCL_ERROR;
197
}
198
}
199
}
200
}
201
}
202
203
return TCL_OK;
204
}
205
206
/*
207
*--------------------------------------------------------------
208
*
209
* FindConfigSpec --
210
*
211
* Search through a table of configuration specs, looking for
212
* one that matches a given argvName.
213
*
214
* Results:
215
* The return value is a pointer to the matching entry, or NULL
216
* if nothing matched. In that case an error message is left
217
* in interp->result.
218
*
219
* Side effects:
220
* None.
221
*
222
*--------------------------------------------------------------
223
*/
224
225
static Tk_ConfigSpec *
226
FindConfigSpec(interp, specs, argvName, needFlags, hateFlags)
227
Tcl_Interp *interp; /* Used for reporting errors. */
228
Tk_ConfigSpec *specs; /* Pointer to table of configuration
229
* specifications for a widget. */
230
char *argvName; /* Name (suitable for use in a "config"
231
* command) identifying particular option. */
232
int needFlags; /* Flags that must be present in matching
233
* entry. */
234
int hateFlags; /* Flags that must NOT be present in
235
* matching entry. */
236
{
237
register Tk_ConfigSpec *specPtr;
238
register char c; /* First character of current argument. */
239
Tk_ConfigSpec *matchPtr; /* Matching spec, or NULL. */
240
size_t length;
241
242
c = argvName[1];
243
length = strlen(argvName);
244
matchPtr = NULL;
245
for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
246
if (specPtr->argvName == NULL) {
247
continue;
248
}
249
if ((specPtr->argvName[1] != c)
250
|| (strncmp(specPtr->argvName, argvName, length) != 0)) {
251
continue;
252
}
253
if (((specPtr->specFlags & needFlags) != needFlags)
254
|| (specPtr->specFlags & hateFlags)) {
255
continue;
256
}
257
if (specPtr->argvName[length] == 0) {
258
matchPtr = specPtr;
259
goto gotMatch;
260
}
261
if (matchPtr != NULL) {
262
Tcl_AppendResult(interp, "ambiguous option \"", argvName,
263
"\"", (char *) NULL);
264
return (Tk_ConfigSpec *) NULL;
265
}
266
matchPtr = specPtr;
267
}
268
269
if (matchPtr == NULL) {
270
Tcl_AppendResult(interp, "unknown option \"", argvName,
271
"\"", (char *) NULL);
272
return (Tk_ConfigSpec *) NULL;
273
}
274
275
/*
276
* Found a matching entry. If it's a synonym, then find the
277
* entry that it's a synonym for.
278
*/
279
280
gotMatch:
281
specPtr = matchPtr;
282
if (specPtr->type == TK_CONFIG_SYNONYM) {
283
for (specPtr = specs; ; specPtr++) {
284
if (specPtr->type == TK_CONFIG_END) {
285
Tcl_AppendResult(interp,
286
"couldn't find synonym for option \"",
287
argvName, "\"", (char *) NULL);
288
return (Tk_ConfigSpec *) NULL;
289
}
290
if ((specPtr->dbName == matchPtr->dbName)
291
&& (specPtr->type != TK_CONFIG_SYNONYM)
292
&& ((specPtr->specFlags & needFlags) == needFlags)
293
&& !(specPtr->specFlags & hateFlags)) {
294
break;
295
}
296
}
297
}
298
return specPtr;
299
}
300
301
/*
302
*--------------------------------------------------------------
303
*
304
* DoConfig --
305
*
306
* This procedure applies a single configuration option
307
* to a widget record.
308
*
309
* Results:
310
* A standard Tcl return value.
311
*
312
* Side effects:
313
* WidgRec is modified as indicated by specPtr and value.
314
* The old value is recycled, if that is appropriate for
315
* the value type.
316
*
317
*--------------------------------------------------------------
318
*/
319
320
static int
321
DoConfig(interp, tkwin, specPtr, value, valueIsUid, widgRec)
322
Tcl_Interp *interp; /* Interpreter for error reporting. */
323
Tk_Window tkwin; /* Window containing widget (needed to
324
* set up X resources). */
325
Tk_ConfigSpec *specPtr; /* Specifier to apply. */
326
char *value; /* Value to use to fill in widgRec. */
327
int valueIsUid; /* Non-zero means value is a Tk_Uid;
328
* zero means it's an ordinary string. */
329
char *widgRec; /* Record whose fields are to be
330
* modified. Values must be properly
331
* initialized. */
332
{
333
char *ptr;
334
Tk_Uid uid;
335
int nullValue;
336
337
nullValue = 0;
338
if ((*value == 0) && (specPtr->specFlags & TK_CONFIG_NULL_OK)) {
339
nullValue = 1;
340
}
341
342
do {
343
ptr = widgRec + specPtr->offset;
344
switch (specPtr->type) {
345
case TK_CONFIG_BOOLEAN:
346
if (Tcl_GetBoolean(interp, value, (int *) ptr) != TCL_OK) {
347
return TCL_ERROR;
348
}
349
break;
350
case TK_CONFIG_INT:
351
if (Tcl_GetInt(interp, value, (int *) ptr) != TCL_OK) {
352
return TCL_ERROR;
353
}
354
break;
355
case TK_CONFIG_DOUBLE:
356
if (Tcl_GetDouble(interp, value, (double *) ptr) != TCL_OK) {
357
return TCL_ERROR;
358
}
359
break;
360
case TK_CONFIG_STRING: {
361
char *old, *new;
362
363
if (nullValue) {
364
new = NULL;
365
} else {
366
new = (char *) ckalloc((unsigned) (strlen(value) + 1));
367
strcpy(new, value);
368
}
369
old = *((char **) ptr);
370
if (old != NULL) {
371
ckfree(old);
372
}
373
*((char **) ptr) = new;
374
break;
375
}
376
case TK_CONFIG_UID:
377
if (nullValue) {
378
*((Tk_Uid *) ptr) = NULL;
379
} else {
380
uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
381
*((Tk_Uid *) ptr) = uid;
382
}
383
break;
384
case TK_CONFIG_COLOR: {
385
XColor *newPtr, *oldPtr;
386
387
if (nullValue) {
388
newPtr = NULL;
389
} else {
390
uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
391
newPtr = Tk_GetColor(interp, tkwin, uid);
392
if (newPtr == NULL) {
393
return TCL_ERROR;
394
}
395
}
396
oldPtr = *((XColor **) ptr);
397
if (oldPtr != NULL) {
398
Tk_FreeColor(oldPtr);
399
}
400
*((XColor **) ptr) = newPtr;
401
break;
402
}
403
case TK_CONFIG_FONT: {
404
XFontStruct *newPtr, *oldPtr;
405
406
if (nullValue) {
407
newPtr = NULL;
408
} else {
409
uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
410
newPtr = Tk_GetFontStruct(interp, tkwin, uid);
411
if (newPtr == NULL) {
412
return TCL_ERROR;
413
}
414
}
415
oldPtr = *((XFontStruct **) ptr);
416
if (oldPtr != NULL) {
417
Tk_FreeFontStruct(oldPtr);
418
}
419
*((XFontStruct **) ptr) = newPtr;
420
break;
421
}
422
case TK_CONFIG_BITMAP: {
423
Pixmap new, old;
424
425
if (nullValue) {
426
new = None;
427
} else {
428
uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
429
new = Tk_GetBitmap(interp, tkwin, uid);
430
if (new == None) {
431
return TCL_ERROR;
432
}
433
}
434
old = *((Pixmap *) ptr);
435
if (old != None) {
436
Tk_FreeBitmap(Tk_Display(tkwin), old);
437
}
438
*((Pixmap *) ptr) = new;
439
break;
440
}
441
case TK_CONFIG_BORDER: {
442
Tk_3DBorder new, old;
443
444
if (nullValue) {
445
new = NULL;
446
} else {
447
uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
448
new = Tk_Get3DBorder(interp, tkwin, uid);
449
if (new == NULL) {
450
return TCL_ERROR;
451
}
452
}
453
old = *((Tk_3DBorder *) ptr);
454
if (old != NULL) {
455
Tk_Free3DBorder(old);
456
}
457
*((Tk_3DBorder *) ptr) = new;
458
break;
459
}
460
case TK_CONFIG_RELIEF:
461
uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
462
if (Tk_GetRelief(interp, uid, (int *) ptr) != TCL_OK) {
463
return TCL_ERROR;
464
}
465
break;
466
case TK_CONFIG_CURSOR:
467
case TK_CONFIG_ACTIVE_CURSOR: {
468
Tk_Cursor new, old;
469
470
if (nullValue) {
471
new = None;
472
} else {
473
uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
474
new = Tk_GetCursor(interp, tkwin, uid);
475
if (new == None) {
476
return TCL_ERROR;
477
}
478
}
479
old = *((Tk_Cursor *) ptr);
480
if (old != None) {
481
Tk_FreeCursor(Tk_Display(tkwin), old);
482
}
483
*((Tk_Cursor *) ptr) = new;
484
if (specPtr->type == TK_CONFIG_ACTIVE_CURSOR) {
485
Tk_DefineCursor(tkwin, new);
486
}
487
break;
488
}
489
case TK_CONFIG_JUSTIFY:
490
uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
491
if (Tk_GetJustify(interp, uid, (Tk_Justify *) ptr) != TCL_OK) {
492
return TCL_ERROR;
493
}
494
break;
495
case TK_CONFIG_ANCHOR:
496
uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
497
if (Tk_GetAnchor(interp, uid, (Tk_Anchor *) ptr) != TCL_OK) {
498
return TCL_ERROR;
499
}
500
break;
501
case TK_CONFIG_CAP_STYLE:
502
uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
503
if (Tk_GetCapStyle(interp, uid, (int *) ptr) != TCL_OK) {
504
return TCL_ERROR;
505
}
506
break;
507
case TK_CONFIG_JOIN_STYLE:
508
uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
509
if (Tk_GetJoinStyle(interp, uid, (int *) ptr) != TCL_OK) {
510
return TCL_ERROR;
511
}
512
break;
513
case TK_CONFIG_PIXELS:
514
if (Tk_GetPixels(interp, tkwin, value, (int *) ptr)
515
!= TCL_OK) {
516
return TCL_ERROR;
517
}
518
break;
519
case TK_CONFIG_MM:
520
if (Tk_GetScreenMM(interp, tkwin, value, (double *) ptr)
521
!= TCL_OK) {
522
return TCL_ERROR;
523
}
524
break;
525
case TK_CONFIG_WINDOW: {
526
Tk_Window tkwin2;
527
528
if (nullValue) {
529
tkwin2 = NULL;
530
} else {
531
tkwin2 = Tk_NameToWindow(interp, value, tkwin);
532
if (tkwin2 == NULL) {
533
return TCL_ERROR;
534
}
535
}
536
*((Tk_Window *) ptr) = tkwin2;
537
break;
538
}
539
case TK_CONFIG_CUSTOM:
540
if ((*specPtr->customPtr->parseProc)(
541
specPtr->customPtr->clientData, interp, tkwin,
542
value, widgRec, specPtr->offset) != TCL_OK) {
543
return TCL_ERROR;
544
}
545
break;
546
default: {
547
sprintf(interp->result, "bad config table: unknown type %d",
548
specPtr->type);
549
return TCL_ERROR;
550
}
551
}
552
specPtr++;
553
} while ((specPtr->argvName == NULL) && (specPtr->type != TK_CONFIG_END));
554
return TCL_OK;
555
}
556
557
/*
558
*--------------------------------------------------------------
559
*
560
* Tk_ConfigureInfo --
561
*
562
* Return information about the configuration options
563
* for a window, and their current values.
564
*
565
* Results:
566
* Always returns TCL_OK. Interp->result will be modified
567
* hold a description of either a single configuration option
568
* available for "widgRec" via "specs", or all the configuration
569
* options available. In the "all" case, the result will
570
* available for "widgRec" via "specs". The result will
571
* be a list, each of whose entries describes one option.
572
* Each entry will itself be a list containing the option's
573
* name for use on command lines, database name, database
574
* class, default value, and current value (empty string
575
* if none). For options that are synonyms, the list will
576
* contain only two values: name and synonym name. If the
577
* "name" argument is non-NULL, then the only information
578
* returned is that for the named argument (i.e. the corresponding
579
* entry in the overall list is returned).
580
*
581
* Side effects:
582
* None.
583
*
584
*--------------------------------------------------------------
585
*/
586
587
int
588
Tk_ConfigureInfo(interp, tkwin, specs, widgRec, argvName, flags)
589
Tcl_Interp *interp; /* Interpreter for error reporting. */
590
Tk_Window tkwin; /* Window corresponding to widgRec. */
591
Tk_ConfigSpec *specs; /* Describes legal options. */
592
char *widgRec; /* Record whose fields contain current
593
* values for options. */
594
char *argvName; /* If non-NULL, indicates a single option
595
* whose info is to be returned. Otherwise
596
* info is returned for all options. */
597
int flags; /* Used to specify additional flags
598
* that must be present in config specs
599
* for them to be considered. */
600
{
601
register Tk_ConfigSpec *specPtr;
602
int needFlags, hateFlags;
603
char *list;
604
char *leader = "{";
605
606
needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
607
if (Tk_Depth(tkwin) <= 1) {
608
hateFlags = TK_CONFIG_COLOR_ONLY;
609
} else {
610
hateFlags = TK_CONFIG_MONO_ONLY;
611
}
612
613
/*
614
* If information is only wanted for a single configuration
615
* spec, then handle that one spec specially.
616
*/
617
618
Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
619
if (argvName != NULL) {
620
specPtr = FindConfigSpec(interp, specs, argvName, needFlags,
621
hateFlags);
622
if (specPtr == NULL) {
623
return TCL_ERROR;
624
}
625
interp->result = FormatConfigInfo(interp, tkwin, specPtr, widgRec);
626
interp->freeProc = TCL_DYNAMIC;
627
return TCL_OK;
628
}
629
630
/*
631
* Loop through all the specs, creating a big list with all
632
* their information.
633
*/
634
635
for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
636
if ((argvName != NULL) && (specPtr->argvName != argvName)) {
637
continue;
638
}
639
if (((specPtr->specFlags & needFlags) != needFlags)
640
|| (specPtr->specFlags & hateFlags)) {
641
continue;
642
}
643
if (specPtr->argvName == NULL) {
644
continue;
645
}
646
list = FormatConfigInfo(interp, tkwin, specPtr, widgRec);
647
Tcl_AppendResult(interp, leader, list, "}", (char *) NULL);
648
ckfree(list);
649
leader = " {";
650
}
651
return TCL_OK;
652
}
653
654
/*
655
*--------------------------------------------------------------
656
*
657
* FormatConfigInfo --
658
*
659
* Create a valid Tcl list holding the configuration information
660
* for a single configuration option.
661
*
662
* Results:
663
* A Tcl list, dynamically allocated. The caller is expected to
664
* arrange for this list to be freed eventually.
665
*
666
* Side effects:
667
* Memory is allocated.
668
*
669
*--------------------------------------------------------------
670
*/
671
672
static char *
673
FormatConfigInfo(interp, tkwin, specPtr, widgRec)
674
Tcl_Interp *interp; /* Interpreter to use for things
675
* like floating-point precision. */
676
Tk_Window tkwin; /* Window corresponding to widget. */
677
register Tk_ConfigSpec *specPtr; /* Pointer to information describing
678
* option. */
679
char *widgRec; /* Pointer to record holding current
680
* values of info for widget. */
681
{
682
char *argv[6], *result;
683
char buffer[200];
684
Tcl_FreeProc *freeProc = (Tcl_FreeProc *) NULL;
685
686
argv[0] = specPtr->argvName;
687
argv[1] = specPtr->dbName;
688
argv[2] = specPtr->dbClass;
689
argv[3] = specPtr->defValue;
690
if (specPtr->type == TK_CONFIG_SYNONYM) {
691
return Tcl_Merge(2, argv);
692
}
693
argv[4] = FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer,
694
&freeProc);
695
if (argv[1] == NULL) {
696
argv[1] = "";
697
}
698
if (argv[2] == NULL) {
699
argv[2] = "";
700
}
701
if (argv[3] == NULL) {
702
argv[3] = "";
703
}
704
if (argv[4] == NULL) {
705
argv[4] = "";
706
}
707
result = Tcl_Merge(5, argv);
708
if (freeProc != NULL) {
709
if ((freeProc == TCL_DYNAMIC) || (freeProc == (Tcl_FreeProc *) free)) {
710
ckfree(argv[4]);
711
} else {
712
(*freeProc)(argv[4]);
713
}
714
}
715
return result;
716
}
717
718
/*
719
*----------------------------------------------------------------------
720
*
721
* FormatConfigValue --
722
*
723
* This procedure formats the current value of a configuration
724
* option.
725
*
726
* Results:
727
* The return value is the formatted value of the option given
728
* by specPtr and widgRec. If the value is static, so that it
729
* need not be freed, *freeProcPtr will be set to NULL; otherwise
730
* *freeProcPtr will be set to the address of a procedure to
731
* free the result, and the caller must invoke this procedure
732
* when it is finished with the result.
733
*
734
* Side effects:
735
* None.
736
*
737
*----------------------------------------------------------------------
738
*/
739
740
static char *
741
FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer, freeProcPtr)
742
Tcl_Interp *interp; /* Interpreter for use in real conversions. */
743
Tk_Window tkwin; /* Window corresponding to widget. */
744
Tk_ConfigSpec *specPtr; /* Pointer to information describing option.
745
* Must not point to a synonym option. */
746
char *widgRec; /* Pointer to record holding current
747
* values of info for widget. */
748
char *buffer; /* Static buffer to use for small values.
749
* Must have at least 200 bytes of storage. */
750
Tcl_FreeProc **freeProcPtr; /* Pointer to word to fill in with address
751
* of procedure to free the result, or NULL
752
* if result is static. */
753
{
754
char *ptr, *result;
755
756
*freeProcPtr = NULL;
757
ptr = widgRec + specPtr->offset;
758
result = "";
759
switch (specPtr->type) {
760
case TK_CONFIG_BOOLEAN:
761
if (*((int *) ptr) == 0) {
762
result = "0";
763
} else {
764
result = "1";
765
}
766
break;
767
case TK_CONFIG_INT:
768
sprintf(buffer, "%d", *((int *) ptr));
769
result = buffer;
770
break;
771
case TK_CONFIG_DOUBLE:
772
Tcl_PrintDouble(interp, *((double *) ptr), buffer);
773
result = buffer;
774
break;
775
case TK_CONFIG_STRING:
776
result = (*(char **) ptr);
777
if (result == NULL) {
778
result = "";
779
}
780
break;
781
case TK_CONFIG_UID: {
782
Tk_Uid uid = *((Tk_Uid *) ptr);
783
if (uid != NULL) {
784
result = uid;
785
}
786
break;
787
}
788
case TK_CONFIG_COLOR: {
789
XColor *colorPtr = *((XColor **) ptr);
790
if (colorPtr != NULL) {
791
result = Tk_NameOfColor(colorPtr);
792
}
793
break;
794
}
795
case TK_CONFIG_FONT: {
796
XFontStruct *fontStructPtr = *((XFontStruct **) ptr);
797
if (fontStructPtr != NULL) {
798
result = Tk_NameOfFontStruct(fontStructPtr);
799
}
800
break;
801
}
802
case TK_CONFIG_BITMAP: {
803
Pixmap pixmap = *((Pixmap *) ptr);
804
if (pixmap != None) {
805
result = Tk_NameOfBitmap(Tk_Display(tkwin), pixmap);
806
}
807
break;
808
}
809
case TK_CONFIG_BORDER: {
810
Tk_3DBorder border = *((Tk_3DBorder *) ptr);
811
if (border != NULL) {
812
result = Tk_NameOf3DBorder(border);
813
}
814
break;
815
}
816
case TK_CONFIG_RELIEF:
817
result = Tk_NameOfRelief(*((int *) ptr));
818
break;
819
case TK_CONFIG_CURSOR:
820
case TK_CONFIG_ACTIVE_CURSOR: {
821
Tk_Cursor cursor = *((Tk_Cursor *) ptr);
822
if (cursor != None) {
823
result = Tk_NameOfCursor(Tk_Display(tkwin), cursor);
824
}
825
break;
826
}
827
case TK_CONFIG_JUSTIFY:
828
result = Tk_NameOfJustify(*((Tk_Justify *) ptr));
829
break;
830
case TK_CONFIG_ANCHOR:
831
result = Tk_NameOfAnchor(*((Tk_Anchor *) ptr));
832
break;
833
case TK_CONFIG_CAP_STYLE:
834
result = Tk_NameOfCapStyle(*((int *) ptr));
835
break;
836
case TK_CONFIG_JOIN_STYLE:
837
result = Tk_NameOfJoinStyle(*((int *) ptr));
838
break;
839
case TK_CONFIG_PIXELS:
840
sprintf(buffer, "%d", *((int *) ptr));
841
result = buffer;
842
break;
843
case TK_CONFIG_MM:
844
Tcl_PrintDouble(interp, *((double *) ptr), buffer);
845
result = buffer;
846
break;
847
case TK_CONFIG_WINDOW: {
848
Tk_Window tkwin;
849
850
tkwin = *((Tk_Window *) ptr);
851
if (tkwin != NULL) {
852
result = Tk_PathName(tkwin);
853
}
854
break;
855
}
856
case TK_CONFIG_CUSTOM:
857
result = (*specPtr->customPtr->printProc)(
858
specPtr->customPtr->clientData, tkwin, widgRec,
859
specPtr->offset, freeProcPtr);
860
break;
861
default:
862
result = "?? unknown type ??";
863
}
864
return result;
865
}
866
867
/*
868
*----------------------------------------------------------------------
869
*
870
* Tk_ConfigureValue --
871
*
872
* This procedure returns the current value of a configuration
873
* option for a widget.
874
*
875
* Results:
876
* The return value is a standard Tcl completion code (TCL_OK or
877
* TCL_ERROR). Interp->result will be set to hold either the value
878
* of the option given by argvName (if TCL_OK is returned) or
879
* an error message (if TCL_ERROR is returned).
880
*
881
* Side effects:
882
* None.
883
*
884
*----------------------------------------------------------------------
885
*/
886
887
int
888
Tk_ConfigureValue(interp, tkwin, specs, widgRec, argvName, flags)
889
Tcl_Interp *interp; /* Interpreter for error reporting. */
890
Tk_Window tkwin; /* Window corresponding to widgRec. */
891
Tk_ConfigSpec *specs; /* Describes legal options. */
892
char *widgRec; /* Record whose fields contain current
893
* values for options. */
894
char *argvName; /* Gives the command-line name for the
895
* option whose value is to be returned. */
896
int flags; /* Used to specify additional flags
897
* that must be present in config specs
898
* for them to be considered. */
899
{
900
Tk_ConfigSpec *specPtr;
901
int needFlags, hateFlags;
902
903
needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
904
if (Tk_Depth(tkwin) <= 1) {
905
hateFlags = TK_CONFIG_COLOR_ONLY;
906
} else {
907
hateFlags = TK_CONFIG_MONO_ONLY;
908
}
909
specPtr = FindConfigSpec(interp, specs, argvName, needFlags, hateFlags);
910
if (specPtr == NULL) {
911
return TCL_ERROR;
912
}
913
interp->result = FormatConfigValue(interp, tkwin, specPtr, widgRec,
914
interp->result, &interp->freeProc);
915
return TCL_OK;
916
}
917
918
/*
919
*----------------------------------------------------------------------
920
*
921
* Tk_FreeOptions --
922
*
923
* Free up all resources associated with configuration options.
924
*
925
* Results:
926
* None.
927
*
928
* Side effects:
929
* Any resource in widgRec that is controlled by a configuration
930
* option (e.g. a Tk_3DBorder or XColor) is freed in the appropriate
931
* fashion.
932
*
933
*----------------------------------------------------------------------
934
*/
935
936
/* ARGSUSED */
937
void
938
Tk_FreeOptions(specs, widgRec, display, needFlags)
939
Tk_ConfigSpec *specs; /* Describes legal options. */
940
char *widgRec; /* Record whose fields contain current
941
* values for options. */
942
Display *display; /* X display; needed for freeing some
943
* resources. */
944
int needFlags; /* Used to specify additional flags
945
* that must be present in config specs
946
* for them to be considered. */
947
{
948
register Tk_ConfigSpec *specPtr;
949
char *ptr;
950
951
for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
952
if ((specPtr->specFlags & needFlags) != needFlags) {
953
continue;
954
}
955
ptr = widgRec + specPtr->offset;
956
switch (specPtr->type) {
957
case TK_CONFIG_STRING:
958
if (*((char **) ptr) != NULL) {
959
ckfree(*((char **) ptr));
960
*((char **) ptr) = NULL;
961
}
962
break;
963
case TK_CONFIG_COLOR:
964
if (*((XColor **) ptr) != NULL) {
965
Tk_FreeColor(*((XColor **) ptr));
966
*((XColor **) ptr) = NULL;
967
}
968
break;
969
case TK_CONFIG_FONT:
970
if (*((XFontStruct **) ptr) != NULL) {
971
Tk_FreeFontStruct(*((XFontStruct **) ptr));
972
*((XFontStruct **) ptr) = NULL;
973
}
974
break;
975
case TK_CONFIG_BITMAP:
976
if (*((Pixmap *) ptr) != None) {
977
Tk_FreeBitmap(display, *((Pixmap *) ptr));
978
*((Pixmap *) ptr) = None;
979
}
980
break;
981
case TK_CONFIG_BORDER:
982
if (*((Tk_3DBorder *) ptr) != NULL) {
983
Tk_Free3DBorder(*((Tk_3DBorder *) ptr));
984
*((Tk_3DBorder *) ptr) = NULL;
985
}
986
break;
987
case TK_CONFIG_CURSOR:
988
case TK_CONFIG_ACTIVE_CURSOR:
989
if (*((Tk_Cursor *) ptr) != None) {
990
Tk_FreeCursor(display, *((Tk_Cursor *) ptr));
991
*((Tk_Cursor *) ptr) = None;
992
}
993
}
994
}
995
}
996
997