1 /*
2 * tixUtils.c --
3 *
4 * This file contains some utility functions for Tix, such as the
5 * subcommand handling functions and option handling functions.
6 *
7 * Copyright (c) 1993-1999 Ioi Kim Lam.
8 * Copyright (c) 2000-2001 Tix Project Group.
9 *
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 *
13 * $Id: tixUtils.c,v 1.13 2008/02/28 04:29:17 hobbs Exp $
14 */
15
16 #include <tcl.h>
17 #include <tixPort.h>
18 #include <tixInt.h>
19
20 /*
21 * Forward declarations for procedures defined later in this file:
22 */
23
24 static int ReliefParseProc(ClientData clientData,
25 Tcl_Interp *interp, Tk_Window tkwin, CONST84 char *value,
26 char *widRec, int offset);
27 static char * ReliefPrintProc(ClientData clientData,
28 Tk_Window tkwin, char *widRec, int offset,
29 Tix_FreeProc **freeProcPtr);
30
31 #define WRONG_ARGC 1
32 #define NO_MATCH 2
33
34
35 /*----------------------------------------------------------------------
36 * Tix_HandleSubCmds --
37 *
38 * This function makes it easier to write major-minor style TCL
39 * commands. It matches the minor command (sub-command) names
40 * with names defined in the cmdInfo structure and call the
41 * appropriate sub-command functions for you. This function will
42 * automatically generate error messages when the user calls an
43 * invalid sub-command or calls a sub-command with incorrect
44 * number of arguments.
45 *
46 *----------------------------------------------------------------------
47 */
48
Tix_HandleSubCmds(cmdInfo,subCmdInfo,clientData,interp,argc,argv)49 int Tix_HandleSubCmds(cmdInfo, subCmdInfo, clientData, interp, argc, argv)
50 Tix_CmdInfo * cmdInfo;
51 Tix_SubCmdInfo * subCmdInfo;
52 ClientData clientData; /* Main window associated with
53 * interpreter. */
54 Tcl_Interp *interp; /* Current interpreter. */
55 int argc; /* Number of arguments. */
56 CONST84 char **argv; /* Argument strings. */
57 {
58
59 int i;
60 int error = NO_MATCH;
61 unsigned int len;
62 Tix_SubCmdInfo * s;
63
64 /*
65 * First check if the number of arguments to the major command
66 * is correct
67 */
68 argc -= 1;
69 if (argc < cmdInfo->minargc ||
70 (cmdInfo->maxargc != TIX_VAR_ARGS && argc > cmdInfo->maxargc)) {
71
72 Tcl_AppendResult(interp, "wrong # args: should be \"",
73 argv[0], " ", cmdInfo->info, "\".", (char *) NULL);
74
75 return TCL_ERROR;
76 }
77
78 /*
79 * Now try to match the subcommands with argv[1]
80 */
81 argc -= 1;
82 len = strlen(argv[1]);
83
84 for (i = 0, s = subCmdInfo; i < cmdInfo->numSubCmds; i++, s++) {
85 if (s->name == TIX_DEFAULT_SUBCMD) {
86 if (s->checkArgvProc) {
87 if (!((*s->checkArgvProc)(clientData, interp, argc+1, argv+1))) {
88 /* Some improper argv in the arguments of the default
89 * subcommand
90 */
91 break;
92 }
93 }
94 return (*s->proc)(clientData, interp, argc+1, argv+1);
95 }
96
97 if (s->namelen == TIX_DEFAULT_LEN) {
98 s->namelen = strlen(s->name);
99 }
100 if (s->name[0] == argv[1][0] && strncmp(argv[1],s->name,len)==0) {
101 if (argc < s->minargc) {
102 error = WRONG_ARGC;
103 break;
104 }
105
106 if (s->maxargc != TIX_VAR_ARGS &&
107 argc > s->maxargc) {
108 error = WRONG_ARGC;
109 break;
110 }
111
112 /*
113 * Here we have a matched argc and command name --> go for it!
114 */
115 return (*s->proc)(clientData, interp, argc, argv+2);
116 }
117 }
118
119 if (error == WRONG_ARGC) {
120 /*
121 * got a match but incorrect number of arguments
122 */
123 Tcl_AppendResult(interp, "wrong # args: should be \"",
124 argv[0], " ", argv[1], " ", s->info, "\"", (char *) NULL);
125 } else {
126 int max;
127
128 /*
129 * no match: let print out all the options
130 */
131 Tcl_AppendResult(interp, "unknown option \"",
132 argv[1], "\".", (char *) NULL);
133
134 if (cmdInfo->numSubCmds == 0) {
135 max = 0;
136 } else {
137 if (subCmdInfo[cmdInfo->numSubCmds-1].name == TIX_DEFAULT_SUBCMD) {
138 max = cmdInfo->numSubCmds-1;
139 } else {
140 max = cmdInfo->numSubCmds;
141 }
142 }
143
144 if (max == 0) {
145 Tcl_AppendResult(interp,
146 " This command does not take any options.",
147 (char *) NULL);
148 } else if (max == 1) {
149 Tcl_AppendResult(interp,
150 " Must be ", subCmdInfo->name, ".", (char *)NULL);
151 } else {
152 Tcl_AppendResult(interp, " Must be ", (char *) NULL);
153
154 for (i = 0, s = subCmdInfo; i < max; i++, s++) {
155 if (i == max-1) {
156 Tcl_AppendResult(interp,"or ",s->name, ".", (char *) NULL);
157 } else if (i == max-2) {
158 Tcl_AppendResult(interp, s->name, " ", (char *) NULL);
159 } else {
160 Tcl_AppendResult(interp, s->name, ", ", (char *) NULL);
161 }
162 }
163 }
164 }
165 return TCL_ERROR;
166 }
167
168 /*----------------------------------------------------------------------
169 * Tix_Exit --
170 *
171 * Call the "exit" tcl command so that things can be cleaned up
172 * before calling the unix exit(2);
173 *
174 *----------------------------------------------------------------------
175 */
Tix_Exit(interp,code)176 void Tix_Exit(interp, code)
177 Tcl_Interp* interp;
178 int code;
179 {
180 const char *str;
181 if (code != 0 && interp && ((str = Tcl_GetStringResult(interp)) != NULL)) {
182 fprintf(stderr, "%s\n", str);
183 fprintf(stderr, "%s\n",
184 Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY));
185 }
186
187 if (interp) {
188 Tcl_EvalEx(interp, "exit", -1, TCL_GLOBAL_ONLY);
189 }
190 exit(code);
191 }
192
193 /*----------------------------------------------------------------------
194 * Tix_CreateCommands --
195 *
196 *
197 * Creates a list of commands stored in the array "commands"
198 *----------------------------------------------------------------------
199 */
200
201 static int initialized = 0;
202
Tix_CreateCommands(interp,commands,clientData,deleteProc)203 void Tix_CreateCommands(interp, commands, clientData, deleteProc)
204 Tcl_Interp *interp;
205 Tix_TclCmd *commands;
206 ClientData clientData;
207 Tcl_CmdDeleteProc *deleteProc;
208 {
209 Tix_TclCmd * cmdPtr;
210
211 if (!initialized) {
212 Tcl_CmdInfo cmdInfo;
213
214 initialized = 1;
215 if (!Tcl_GetCommandInfo(interp,"image", (Tcl_CmdInfo *) &cmdInfo)) {
216 Tcl_Panic("cannot find the \"image\" command");
217 } else if (cmdInfo.isNativeObjectProc == 1) {
218 initialized = 2; /* we use objects */
219 }
220 }
221 for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
222 Tcl_CreateCommand(interp, cmdPtr->name,
223 cmdPtr->cmdProc, clientData, deleteProc);
224 }
225 }
226
227 /*
228 *----------------------------------------------------------------------
229 * Tix_GetAnchorGC --
230 *
231 * Get the GC for drawing the anchor dotted lines around anchor
232 * elements.
233 *
234 * Results:
235 * Returns a GC that can be passed to Tix_DrawAnchorLines for
236 * drawing an anchor line for the given background color.
237 *
238 * Side effects:
239 * None.
240 *----------------------------------------------------------------------
241 */
242
243 GC
Tix_GetAnchorGC(tkwin,bgColor)244 Tix_GetAnchorGC(tkwin, bgColor)
245 Tk_Window tkwin;
246 XColor *bgColor;
247 {
248 XGCValues gcValues;
249 XColor valueKey;
250 XColor * anchorColor;
251 int r, g, b;
252 int max;
253
254 /*
255 * Get the best color to draw the dotted lines on the given background
256 * color.
257 */
258
259 r = bgColor->red;
260 g = bgColor->green;
261 b = bgColor->blue;
262
263 r = (65535 - r) & 0xffff;
264 g = (65535 - g) & 0xffff;
265 b = (65535 - b) & 0xffff;
266
267 max = r;
268 if (max < g) {
269 max = g;
270 }
271 if (max < b) {
272 max = b;
273 }
274
275 max = max / 256;
276 if (max > 96) {
277 /*
278 * scale color up
279 */
280
281 r = (r * 255) / max;
282 g = (g * 255) / max;
283 b = (b * 255) / max;
284 } else {
285 /*
286 * scale color down
287 */
288 int min = r;
289 if (min > g) {
290 min = g;
291 }
292 if (min > b) {
293 min = b;
294 }
295 r = r - min;
296 g = g - min;
297 b = b - min;
298 }
299
300 valueKey.red = r;
301 valueKey.green = g;
302 valueKey.blue = b;
303
304 anchorColor = Tk_GetColorByValue(tkwin, &valueKey);
305
306 gcValues.foreground = anchorColor->pixel;
307 gcValues.graphics_exposures = False;
308 gcValues.subwindow_mode = IncludeInferiors;
309
310 return Tk_GetGC(tkwin, GCForeground|GCGraphicsExposures|GCSubwindowMode,
311 &gcValues);
312 }
313
314 /*
315 *----------------------------------------------------------------------
316 * Tix_DrawAnchorLines --
317 *
318 * Draw dotted anchor lines around anchor elements. The exact
319 * behavior is defined in the platform-specific
320 * TixpDrawAnchorLines function.
321 *
322 * Results:
323 * None.
324 *
325 * Side effects:
326 * None.
327 *----------------------------------------------------------------------
328 */
329
330 void
Tix_DrawAnchorLines(display,drawable,gc,x,y,w,h)331 Tix_DrawAnchorLines(display, drawable, gc, x, y, w, h)
332 Display *display;
333 Drawable drawable;
334 GC gc;
335 int x;
336 int y;
337 int w;
338 int h;
339 {
340 TixpDrawAnchorLines(display, drawable, gc, x, y, w, h);
341 }
342
343 /*----------------------------------------------------------------------
344 * Tix_CreateSubWindow --
345 *
346 * Creates a subwindow for a widget (usually used to draw headers,
347 * e.g, HList and Grid widgets)
348 *----------------------------------------------------------------------
349 */
350
351 Tk_Window
Tix_CreateSubWindow(interp,tkwin,subPath)352 Tix_CreateSubWindow(interp, tkwin, subPath)
353 Tcl_Interp * interp;
354 Tk_Window tkwin;
355 CONST84 char * subPath;
356 {
357 Tcl_DString dString;
358 Tk_Window subwin;
359
360 Tcl_DStringInit(&dString);
361 Tcl_DStringAppend(&dString, Tk_PathName(tkwin),
362 (int) strlen(Tk_PathName(tkwin)));
363 Tcl_DStringAppend(&dString, ".tixsw:", 7);
364 Tcl_DStringAppend(&dString, subPath, (int) strlen(subPath));
365
366 subwin = Tk_CreateWindowFromPath(interp, tkwin, dString.string,
367 (char *) NULL);
368
369 Tcl_DStringFree(&dString);
370
371 return subwin;
372 }
373 static int
ErrorProc(clientData,errorEventPtr)374 ErrorProc(clientData, errorEventPtr)
375 ClientData clientData;
376 XErrorEvent *errorEventPtr; /* unused */
377 {
378 int * badAllocPtr = (int*) clientData;
379
380 * badAllocPtr = 1;
381 return 0; /* return 0 means error has been
382 * handled properly */
383 }
384
385 /*
386 *----------------------------------------------------------------------
387 * Tix_GetRenderBuffer --
388 *
389 * Returns a drawable for rendering a widget. If there is
390 * sufficient graphics resource, a pixmap is returned so that
391 * double-buffering can be done. However, if resource is
392 * insufficient, then the windowId is returned. In the second
393 * case happens, the caller of this function has two choices: (1)
394 * draw to the window directly (which may lead to flickering on
395 * the screen) or (2) try to allocate smaller pixmaps.
396 *
397 * Results:
398 * An allocated pixmap of the same depth as the window, or the
399 * window itself.
400 *
401 * Side effects:
402 * A pixmap may be allocated. The caller should call
403 * Tk_FreePixmap() to free the pixmap returned by this function.
404 *
405 *----------------------------------------------------------------------
406 */
407
408 /*
409 * Uncomment this if you want to use single-buffer mode drawing to
410 * debug paintings.
411 */
412
413 /* #define PAINT_DEBUG 1 */
414
415 Drawable
Tix_GetRenderBuffer(display,windowId,width,height,depth)416 Tix_GetRenderBuffer(display, windowId, width, height, depth)
417 Display *display; /* Display of the windowId */
418 Window windowId; /* Window to draw into */
419 int width; /* width of the drawing region */
420 int height; /* height of the drawing region */
421 int depth; /* Depth of the window. TODO remove this arg*/
422 {
423 #ifdef PAINT_DEBUG
424 return windowId;
425 #else
426 Tk_ErrorHandler handler;
427 Pixmap pixmap;
428 int badAlloc = 0;
429
430 handler= Tk_CreateErrorHandler(display, BadAlloc,
431 -1, -1, (Tk_ErrorProc *) ErrorProc, (ClientData) &badAlloc);
432 pixmap = Tk_GetPixmap(display, windowId, width, height, depth);
433
434 #if !defined(__WIN32__) && !defined(MAC_TCL) && !defined(MAC_OSX_TK) /* UNIX */
435 /*
436 * This XSync call is necessary because X may delay the delivery of the
437 * error message. This will make our graphics a bit slower, though,
438 * especially over slow lines
439 */
440 XSync(display, 0);
441 #endif
442 /* If ErrorProc() is eevr called, it is called before XSync returns */
443
444 Tk_DeleteErrorHandler(handler);
445
446 if (!badAlloc) {
447 return pixmap;
448 } else {
449 return windowId;
450 }
451 #endif
452 }
453
454 /*
455 *----------------------------------------------------------------------
456 *
457 * Tix_GlobalVarEval --
458 *
459 * Given a variable number of string arguments, concatenate them
460 * all together and execute the result as a Tcl command in the global
461 * scope.
462 *
463 * Results:
464 * A standard Tcl return result. An error message or other
465 * result may be left in the interp's result.
466 *
467 * Side effects:
468 * Depends on what was done by the command.
469 *
470 *----------------------------------------------------------------------
471 */
472 /* VARARGS2 */ /* ARGSUSED */
473 int
TCL_VARARGS_DEF(Tcl_Interp *,arg1)474 Tix_GlobalVarEval TCL_VARARGS_DEF(Tcl_Interp *,arg1)
475 {
476 va_list argList;
477 Tcl_DString buf;
478 char *string;
479 Tcl_Interp *interp;
480 int result;
481
482 /*
483 * Copy the strings one after the other into a single larger
484 * string. Use stack-allocated space for small commands, but if
485 * the command gets too large than call ckalloc to create the
486 * space.
487 */
488
489 interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
490 Tcl_DStringInit(&buf);
491 while (1) {
492 string = va_arg(argList, char *);
493 if (string == NULL) {
494 break;
495 }
496 Tcl_DStringAppend(&buf, string, -1);
497 }
498 va_end(argList);
499
500 result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf),
501 Tcl_DStringLength(&buf), TCL_GLOBAL_ONLY);
502 Tcl_DStringFree(&buf);
503 return result;
504 }
505
506 /*----------------------------------------------------------------------
507 * TixGetHashTable --
508 *
509 * This functions makes it possible to keep one hash table per
510 * interpreter. This way, Tix classes can be used in multiple
511 * interpreters.
512 *
513 *----------------------------------------------------------------------
514 */
515
516 static void DeleteHashTableProc _ANSI_ARGS_((ClientData clientData,
517 Tcl_Interp * interp));
518 static void
DeleteHashTableProc(clientData,interp)519 DeleteHashTableProc(clientData, interp)
520 ClientData clientData;
521 Tcl_Interp * interp;
522 {
523 Tcl_HashTable * htPtr = (Tcl_HashTable *)clientData;
524 Tcl_HashSearch hashSearch;
525 Tcl_HashEntry * hashPtr;
526
527 for (hashPtr = Tcl_FirstHashEntry(htPtr, &hashSearch);
528 hashPtr;
529 hashPtr = Tcl_NextHashEntry(&hashSearch)) {
530 Tcl_DeleteHashEntry(hashPtr);
531 }
532
533 Tcl_DeleteHashTable(htPtr);
534 ckfree((char*)htPtr);
535 }
536
537 /*
538 *----------------------------------------------------------------------
539 * TixGetHashTable() --
540 *
541 * Returns a named hashtable to be used for the given
542 * interpreter. Creates the hashtable if it doesn't exist yet. It
543 * uses Tcl_GetAssocData to make sure that the hashtable is not
544 * shared by different interpreters.
545 *
546 * Results:
547 * Pointer to the hashtable.
548 *
549 * Side effects:
550 * The hashtable is created if it doesn't exist yet.
551 *
552 *----------------------------------------------------------------------
553 */
554
555 Tcl_HashTable *
TixGetHashTable(interp,name,deleteProc,keyType)556 TixGetHashTable(interp, name, deleteProc, keyType)
557 Tcl_Interp * interp;
558 char * name;
559 Tcl_InterpDeleteProc *deleteProc;
560 int keyType;
561 {
562 Tcl_HashTable * htPtr;
563
564 htPtr = (Tcl_HashTable*)Tcl_GetAssocData(interp, name, NULL);
565
566 if (htPtr == NULL) {
567 htPtr = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));
568 Tcl_InitHashTable(htPtr, keyType);
569 Tcl_SetAssocData(interp, name, NULL, (ClientData)htPtr);
570
571 if (deleteProc) {
572 Tcl_CallWhenDeleted(interp, deleteProc, (ClientData)htPtr);
573 } else {
574 Tcl_CallWhenDeleted(interp, DeleteHashTableProc,
575 (ClientData)htPtr);
576 }
577 }
578
579 return htPtr;
580 }
581
582 /*----------------------------------------------------------------------
583 *
584 * The Tix Customed Config Options
585 *
586 *----------------------------------------------------------------------
587 */
588
589 /*----------------------------------------------------------------------
590 * ReliefParseProc --
591 *
592 * Parse the text string and store the Tix_Relief information
593 * inside the widget record.
594 *----------------------------------------------------------------------
595 */
596 static int
ReliefParseProc(clientData,interp,tkwin,value,widRec,offset)597 ReliefParseProc(clientData, interp, tkwin, value, widRec,offset)
598 ClientData clientData;
599 Tcl_Interp *interp;
600 Tk_Window tkwin;
601 CONST84 char *value;
602 char *widRec; /* Must point to a valid Tix_DItem struct */
603 int offset;
604 {
605 Tix_Relief * ptr = (Tix_Relief *)(widRec + offset);
606 Tix_Relief newVal;
607
608 if (value != NULL) {
609 size_t len = strlen(value);
610
611 if (strncmp(value, "raised", len) == 0) {
612 newVal = TIX_RELIEF_RAISED;
613 } else if (strncmp(value, "flat", len) == 0) {
614 newVal = TIX_RELIEF_FLAT;
615 } else if (strncmp(value, "sunken", len) == 0) {
616 newVal = TIX_RELIEF_SUNKEN;
617 } else if (strncmp(value, "groove", len) == 0) {
618 newVal = TIX_RELIEF_GROOVE;
619 } else if (strncmp(value, "ridge", len) == 0) {
620 newVal = TIX_RELIEF_RIDGE;
621 } else if (strncmp(value, "solid", len) == 0) {
622 newVal = TIX_RELIEF_SOLID;
623 } else {
624 goto error;
625 }
626 } else {
627 value = "";
628 goto error;
629 }
630
631 *ptr = newVal;
632 return TCL_OK;
633
634 error:
635 Tcl_AppendResult(interp, "bad relief type \"", value,
636 "\": must be flat, groove, raised, ridge, solid or sunken", NULL);
637 return TCL_ERROR;
638 }
639
640 static char *
ReliefPrintProc(clientData,tkwin,widRec,offset,freeProcPtr)641 ReliefPrintProc(clientData, tkwin, widRec,offset, freeProcPtr)
642 ClientData clientData;
643 Tk_Window tkwin;
644 char *widRec;
645 int offset;
646 Tix_FreeProc **freeProcPtr;
647 {
648 Tix_Relief *ptr = (Tix_Relief*)(widRec+offset);
649
650 switch (*ptr) {
651 case TIX_RELIEF_RAISED:
652 return "raised";
653 case TIX_RELIEF_FLAT:
654 return "flat";
655 case TIX_RELIEF_SUNKEN:
656 return "sunken";
657 case TIX_RELIEF_GROOVE:
658 return "groove";
659 case TIX_RELIEF_RIDGE:
660 return "ridge";
661 case TIX_RELIEF_SOLID:
662 return "solid";
663 default:
664 return "unknown";
665 }
666 }
667 /*
668 * The global data structures to use in widget configSpecs arrays
669 *
670 * These are declared in <tix.h>
671 */
672
673 Tk_CustomOption tixConfigRelief = {
674 ReliefParseProc, ReliefPrintProc, 0,
675 };
676
677 /* Tix_SetRcFileName --
678 *
679 * Sets a user-specific startup file in a way that's compatible with
680 * different versions of Tclsh
681 */
Tix_SetRcFileName(interp,rcFileName)682 void Tix_SetRcFileName(interp, rcFileName)
683 Tcl_Interp * interp;
684 CONST84 char * rcFileName;
685 {
686 /*
687 * Starting from TCL 7.5, the symbol tcl_rcFileName is no longer
688 * exported by libtcl.a. Instead, this variable must be set using
689 * a TCL global variable
690 */
691 Tcl_SetVar(interp, "tcl_rcFileName", rcFileName, TCL_GLOBAL_ONLY);
692 }
693
694 /*
695 * The TkComputeTextGeometry function is no longer supported in Tk 8.0+
696 */
697
698 /*
699 *----------------------------------------------------------------------
700 *
701 * TixComputeTextGeometry --
702 *
703 * This procedure computes the amount of screen space needed to
704 * display a multi-line string of text.
705 *
706 * Results:
707 * There is no return value. The dimensions of the screen area
708 * needed to display the text are returned in *widthPtr, and *heightPtr.
709 *
710 * Side effects:
711 * None.
712 *
713 *----------------------------------------------------------------------
714 */
715
716 void
TixComputeTextGeometry(font,string,numChars,wrapLength,widthPtr,heightPtr)717 TixComputeTextGeometry(font, string, numChars, wrapLength,
718 widthPtr, heightPtr)
719 TixFont font; /* Font that will be used to display text. */
720 CONST84 char *string; /* String whose dimensions are to be
721 * computed. */
722 int numChars; /* Number of characters to consider from
723 * string. -1 means the entire size of
724 * the text string */
725 int wrapLength; /* Longest permissible line length, in
726 * pixels. <= 0 means no automatic wrapping:
727 * just let lines get as long as needed. */
728 int *widthPtr; /* Store width of string here. */
729 int *heightPtr; /* Store height of string here. */
730 {
731 Tk_TextLayout textLayout;
732
733 /*
734 * The justification itself doesn't affect the geometry (size) of
735 * the text string. We pass TK_JUSTIFY_LEFT.
736 */
737
738 textLayout = Tk_ComputeTextLayout(font,
739 string, numChars, wrapLength, TK_JUSTIFY_LEFT, 0,
740 widthPtr, heightPtr);
741 Tk_FreeTextLayout(textLayout);
742 }
743
744 /*
745 *----------------------------------------------------------------------
746 *
747 * TixDisplayText --
748 *
749 * Display a text string on one or more lines.
750 *
751 * Results:
752 * None.
753 *
754 * Side effects:
755 * The text given by "string" gets displayed at the given location
756 * in the given drawable with the given font etc.
757 *
758 *----------------------------------------------------------------------
759 */
760
761 void
TixDisplayText(display,drawable,font,string,numChars,x,y,length,justify,underline,gc)762 TixDisplayText(display, drawable, font, string, numChars, x, y,
763 length, justify, underline, gc)
764 Display *display; /* X display to use for drawing text. */
765 Drawable drawable; /* Window or pixmap in which to draw the
766 * text. */
767 TixFont font; /* Font that determines geometry of text
768 * (should be same as font in gc). */
769 CONST84 char *string; /* String to display; may contain embedded
770 * newlines. */
771 int numChars; /* Number of characters to use from string. */
772 int x, y; /* Pixel coordinates within drawable of
773 * upper left corner of display area. */
774 int length; /* Line length in pixels; used to compute
775 * word wrap points and also for
776 * justification. Must be > 0. */
777 Tk_Justify justify; /* How to justify lines. */
778 int underline; /* Index of character to underline, or < 0
779 * for no underlining. */
780 GC gc; /* Graphics context to use for drawing text. */
781 {
782 Tk_TextLayout textLayout;
783 int dummyx, dummyy;
784
785 textLayout = Tk_ComputeTextLayout(font,
786 string, numChars, length, justify, 0,
787 &dummyx, &dummyy);
788
789 Tk_DrawTextLayout(display, drawable, gc, textLayout,
790 x, y, 0, -1);
791 Tk_UnderlineTextLayout(display, drawable, gc,
792 textLayout, x, y, underline);
793
794 Tk_FreeTextLayout(textLayout);
795 }
796
797 /*
798 *----------------------------------------------------------------------
799 * Tix_ZAlloc --
800 *
801 * Allocate the memory block with ckalloc and zeros it.
802 *
803 * Results:
804 * Same as ckalloc() except the new memory block is filled with
805 * zero. Returns NULL if memory allocation fails.
806 *
807 * Side effects:
808 * None.
809 *----------------------------------------------------------------------
810 */
811
Tix_ZAlloc(nbytes)812 char * Tix_ZAlloc(nbytes)
813 unsigned int nbytes; /* size of memory block to alloc, in
814 * number of bytes.*/
815 {
816 char * ptr = (char*)ckalloc(nbytes);
817 if (ptr) {
818 memset(ptr, 0, nbytes);
819 }
820 return ptr;
821 }
822