source: trunk/kitgen/8.x/blt/generic/bltGrPen.c@ 191

Last change on this file since 191 was 175, checked in by demin, 12 years ago

initial commit

File size: 17.6 KB
Line 
1
2/*
3 * bltGrPen.c --
4 *
5 * This module implements pens for the BLT graph widget.
6 *
7 * Copyright 1996-1998 Lucent Technologies, Inc.
8 *
9 * Permission to use, copy, modify, and distribute this software and
10 * its documentation for any purpose and without fee is hereby
11 * granted, provided that the above copyright notice appear in all
12 * copies and that both that the copyright notice and warranty
13 * disclaimer appear in supporting documentation, and that the names
14 * of Lucent Technologies any of their entities not be used in
15 * advertising or publicity pertaining to distribution of the software
16 * without specific, written prior permission.
17 *
18 * Lucent Technologies disclaims all warranties with regard to this
19 * software, including all implied warranties of merchantability and
20 * fitness. In no event shall Lucent Technologies be liable for any
21 * special, indirect or consequential damages or any damages
22 * whatsoever resulting from loss of use, data or profits, whether in
23 * an action of contract, negligence or other tortuous action, arising
24 * out of or in connection with the use or performance of this
25 * software.
26 */
27
28#include "bltGraph.h"
29#include <X11/Xutil.h>
30
31static Tk_OptionParseProc StringToColor;
32static Tk_OptionPrintProc ColorToString;
33static Tk_OptionParseProc StringToPen;
34static Tk_OptionPrintProc PenToString;
35Tk_CustomOption bltColorOption =
36{
37 StringToColor, ColorToString, (ClientData)0
38};
39Tk_CustomOption bltPenOption =
40{
41 StringToPen, PenToString, (ClientData)0
42};
43Tk_CustomOption bltBarPenOption =
44{
45 StringToPen, PenToString, (ClientData)&bltBarElementUid
46};
47Tk_CustomOption bltLinePenOption =
48{
49 StringToPen, PenToString, (ClientData)&bltLineElementUid
50};
51
52/*
53 *----------------------------------------------------------------------
54
55 * StringToColor --
56 *
57 * Convert the string representation of a color into a XColor pointer.
58 *
59 * Results:
60 * The return value is a standard Tcl result. The color pointer is
61 * written into the widget record.
62 *
63 *----------------------------------------------------------------------
64 */
65/*ARGSUSED*/
66static int
67StringToColor(clientData, interp, tkwin, string, widgRec, offset)
68 ClientData clientData; /* Not used. */
69 Tcl_Interp *interp; /* Interpreter to send results back to */
70 Tk_Window tkwin; /* Not used. */
71 char *string; /* String representing color */
72 char *widgRec; /* Widget record */
73 int offset; /* Offset of color field in record */
74{
75 XColor **colorPtrPtr = (XColor **)(widgRec + offset);
76 XColor *colorPtr;
77 unsigned int length;
78 char c;
79
80 if ((string == NULL) || (*string == '\0')) {
81 *colorPtrPtr = NULL;
82 return TCL_OK;
83 }
84 c = string[0];
85 length = strlen(string);
86
87 if ((c == 'd') && (strncmp(string, "defcolor", length) == 0)) {
88 colorPtr = COLOR_DEFAULT;
89 } else {
90 colorPtr = Tk_GetColor(interp, tkwin, Tk_GetUid(string));
91 if (colorPtr == NULL) {
92 return TCL_ERROR;
93 }
94 }
95 *colorPtrPtr = colorPtr;
96 return TCL_OK;
97}
98
99/*
100 *----------------------------------------------------------------------
101 *
102 * NameOfColor --
103 *
104 * Convert the color option value into a string.
105 *
106 * Results:
107 * The static string representing the color option is returned.
108 *
109 *----------------------------------------------------------------------
110 */
111static char *
112NameOfColor(colorPtr)
113 XColor *colorPtr;
114{
115 if (colorPtr == NULL) {
116 return "";
117 } else if (colorPtr == COLOR_DEFAULT) {
118 return "defcolor";
119 } else {
120 return Tk_NameOfColor(colorPtr);
121 }
122}
123
124/*
125 *----------------------------------------------------------------------
126 *
127 * ColorToString --
128 *
129 * Convert the color value into a string.
130 *
131 * Results:
132 * The string representing the symbol color is returned.
133 *
134 *----------------------------------------------------------------------
135 */
136/*ARGSUSED*/
137static char *
138ColorToString(clientData, tkwin, widgRec, offset, freeProcPtr)
139 ClientData clientData; /* Not used. */
140 Tk_Window tkwin; /* Not used. */
141 char *widgRec; /* Widget information record */
142 int offset; /* Offset of symbol type in record */
143 Tcl_FreeProc **freeProcPtr; /* Not used. */
144{
145 XColor *colorPtr = *(XColor **)(widgRec + offset);
146
147 return NameOfColor(colorPtr);
148}
149
150/*
151 *----------------------------------------------------------------------
152 *
153 * StringToPen --
154 *
155 * Convert the color value into a string.
156 *
157 * Results:
158 * The string representing the symbol color is returned.
159 *
160 *----------------------------------------------------------------------
161 */
162/*ARGSUSED*/
163static int
164StringToPen(clientData, interp, tkwin, string, widgRec, offset)
165 ClientData clientData; /* Not used. */
166 Tcl_Interp *interp; /* Interpreter to send results back to */
167 Tk_Window tkwin; /* Not used. */
168 char *string; /* String representing pen */
169 char *widgRec; /* Widget record */
170 int offset; /* Offset of pen field in record */
171{
172 Blt_Uid classUid = *(Blt_Uid *)clientData; /* Element type. */
173 Pen **penPtrPtr = (Pen **)(widgRec + offset);
174 Pen *penPtr;
175 Graph *graphPtr;
176
177 penPtr = NULL;
178 graphPtr = Blt_GetGraphFromWindowData(tkwin);
179
180 if (classUid == NULL) {
181 classUid = graphPtr->classUid;
182 }
183 if ((string != NULL) && (string[0] != '\0')) {
184 if (Blt_GetPen(graphPtr, string, classUid, &penPtr) != TCL_OK) {
185 return TCL_ERROR;
186 }
187 }
188 /* Release the old pen */
189 if (*penPtrPtr != NULL) {
190 Blt_FreePen(graphPtr, *penPtrPtr);
191 }
192 *penPtrPtr = penPtr;
193 return TCL_OK;
194}
195
196/*
197 *----------------------------------------------------------------------
198 *
199 * PenToString --
200 *
201 * Parse the name of the name.
202 *
203 * Results:
204 * The return value is a standard Tcl result.
205 *
206 *----------------------------------------------------------------------
207 */
208/*ARGSUSED*/
209static char *
210PenToString(clientData, tkwin, widgRec, offset, freeProcPtr)
211 ClientData clientData; /* Not used. */
212 Tk_Window tkwin; /* Not used. */
213 char *widgRec; /* Widget information record */
214 int offset; /* Offset of pen in record */
215 Tcl_FreeProc **freeProcPtr; /* Not used. */
216{
217 Pen *penPtr = *(Pen **)(widgRec + offset);
218
219 return penPtr->name;
220}
221
222
223/*
224 *----------------------------------------------------------------------
225 *
226 * NameToPen --
227 *
228 * Find and return the pen style from a given name.
229 *
230 * Results:
231 * A standard TCL result.
232 *
233 *----------------------------------------------------------------------
234 */
235static Pen *
236NameToPen(graphPtr, name)
237 Graph *graphPtr;
238 char *name;
239{
240 Blt_HashEntry *hPtr;
241 Pen *penPtr;
242
243 hPtr = Blt_FindHashEntry(&(graphPtr->penTable), name);
244 if (hPtr == NULL) {
245 notFound:
246 Tcl_AppendResult(graphPtr->interp, "can't find pen \"", name,
247 "\" in \"", Tk_PathName(graphPtr->tkwin), "\"", (char *)NULL);
248 return NULL;
249 }
250 penPtr = (Pen *)Blt_GetHashValue(hPtr);
251 if (penPtr->flags & PEN_DELETE_PENDING) {
252 goto notFound;
253 }
254 return penPtr;
255}
256
257static void
258DestroyPen(graphPtr, penPtr)
259 Graph *graphPtr;
260 Pen *penPtr;
261{
262 Tk_FreeOptions(penPtr->configSpecs, (char *)penPtr, graphPtr->display, 0);
263 (*penPtr->destroyProc) (graphPtr, penPtr);
264 if ((penPtr->name != NULL) && (penPtr->name[0] != '\0')) {
265 Blt_Free(penPtr->name);
266 }
267 if (penPtr->hashPtr != NULL) {
268 Blt_DeleteHashEntry(&(graphPtr->penTable), penPtr->hashPtr);
269 }
270 Blt_Free(penPtr);
271}
272
273void
274Blt_FreePen(graphPtr, penPtr)
275 Graph *graphPtr;
276 Pen *penPtr;
277{
278 penPtr->refCount--;
279 if ((penPtr->refCount == 0) && (penPtr->flags & PEN_DELETE_PENDING)) {
280 DestroyPen(graphPtr, penPtr);
281 }
282}
283
284Pen *
285Blt_CreatePen(graphPtr, penName, classUid, nOpts, options)
286 Graph *graphPtr;
287 char *penName;
288 Blt_Uid classUid;
289 int nOpts;
290 char **options;
291{
292
293 Pen *penPtr;
294 Blt_HashEntry *hPtr;
295 unsigned int length, configFlags;
296 int isNew;
297 register int i;
298
299 /*
300 * Scan the option list for a "-type" entry. This will indicate
301 * what type of pen we are creating. Otherwise we'll default to the
302 * suggested type. Last -type option wins.
303 */
304 for (i = 0; i < nOpts; i += 2) {
305 length = strlen(options[i]);
306 if ((length > 2) && (strncmp(options[i], "-type", length) == 0)) {
307 char *arg;
308
309 arg = options[i + 1];
310 if (strcmp(arg, "bar") == 0) {
311 classUid = bltBarElementUid;
312 } else if (strcmp(arg, "line") != 0) {
313 classUid = bltLineElementUid;
314 } else if (strcmp(arg, "strip") != 0) {
315 classUid = bltLineElementUid;
316 } else {
317 Tcl_AppendResult(graphPtr->interp, "unknown pen type \"",
318 arg, "\" specified", (char *)NULL);
319 return NULL;
320 }
321 }
322 }
323 if (classUid == bltStripElementUid) {
324 classUid = bltLineElementUid;
325 }
326 hPtr = Blt_CreateHashEntry(&(graphPtr->penTable), penName, &isNew);
327 if (!isNew) {
328 penPtr = (Pen *)Blt_GetHashValue(hPtr);
329 if (!(penPtr->flags & PEN_DELETE_PENDING)) {
330 Tcl_AppendResult(graphPtr->interp, "pen \"", penName,
331 "\" already exists in \"", Tk_PathName(graphPtr->tkwin), "\"",
332 (char *)NULL);
333 return NULL;
334 }
335 if (penPtr->classUid != classUid) {
336 Tcl_AppendResult(graphPtr->interp, "pen \"", penName,
337 "\" in-use: can't change pen type from \"", penPtr->classUid,
338 "\" to \"", classUid, "\"", (char *)NULL);
339 return NULL;
340 }
341 penPtr->flags &= ~PEN_DELETE_PENDING;
342 } else {
343 if (classUid == bltBarElementUid) {
344 penPtr = Blt_BarPen(penName);
345 } else {
346 penPtr = Blt_LinePen(penName);
347 }
348 penPtr->classUid = classUid;
349 penPtr->hashPtr = hPtr;
350 Blt_SetHashValue(hPtr, penPtr);
351 }
352
353 configFlags = (penPtr->flags & (ACTIVE_PEN | NORMAL_PEN));
354 if (Blt_ConfigureWidgetComponent(graphPtr->interp, graphPtr->tkwin,
355 penPtr->name, "Pen", penPtr->configSpecs, nOpts, options,
356 (char *)penPtr, configFlags) != TCL_OK) {
357 if (isNew) {
358 DestroyPen(graphPtr, penPtr);
359 }
360 return NULL;
361 }
362 (*penPtr->configProc) (graphPtr, penPtr);
363 return penPtr;
364}
365
366int
367Blt_GetPen(graphPtr, name, classUid, penPtrPtr)
368 Graph *graphPtr;
369 char *name;
370 Blt_Uid classUid;
371 Pen **penPtrPtr;
372{
373 Pen *penPtr;
374
375 penPtr = NameToPen(graphPtr, name);
376 if (penPtr == NULL) {
377 return TCL_ERROR;
378 }
379 if (classUid == bltStripElementUid) {
380 classUid = bltLineElementUid;
381 }
382 if (penPtr->classUid != classUid) {
383 Tcl_AppendResult(graphPtr->interp, "pen \"", name,
384 "\" is the wrong type (is \"", penPtr->classUid, "\"",
385 ", wanted \"", classUid, "\")", (char *)NULL);
386 return TCL_ERROR;
387 }
388 penPtr->refCount++;
389 *penPtrPtr = penPtr;
390 return TCL_OK;
391}
392
393/*
394 *----------------------------------------------------------------------
395 *
396 * Blt_DestroyPens --
397 *
398 * Release memory and resources allocated for the style.
399 *
400 * Results:
401 * None.
402 *
403 * Side effects:
404 * Everything associated with the pen style is freed up.
405 *
406 *----------------------------------------------------------------------
407 */
408void
409Blt_DestroyPens(graphPtr)
410 Graph *graphPtr;
411{
412 Blt_HashEntry *hPtr;
413 Blt_HashSearch cursor;
414 Pen *penPtr;
415
416 for (hPtr = Blt_FirstHashEntry(&(graphPtr->penTable), &cursor);
417 hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
418 penPtr = (Pen *)Blt_GetHashValue(hPtr);
419 penPtr->hashPtr = NULL;
420 DestroyPen(graphPtr, penPtr);
421 }
422 Blt_DeleteHashTable(&(graphPtr->penTable));
423}
424
425/*
426 * ----------------------------------------------------------------------
427 *
428 * CgetOp --
429 *
430 * Queries axis attributes (font, line width, label, etc).
431 *
432 * Results:
433 * A standard Tcl result. If querying configuration values,
434 * interp->result will contain the results.
435 *
436 * ----------------------------------------------------------------------
437 */
438/* ARGSUSED */
439static int
440CgetOp(interp, graphPtr, argc, argv)
441 Tcl_Interp *interp;
442 Graph *graphPtr;
443 int argc; /* Not used. */
444 char *argv[];
445{
446 Pen *penPtr;
447 unsigned int configFlags;
448
449 penPtr = NameToPen(graphPtr, argv[3]);
450 if (penPtr == NULL) {
451 return TCL_ERROR;
452 }
453 configFlags = (penPtr->flags & (ACTIVE_PEN | NORMAL_PEN));
454 return Tk_ConfigureValue(interp, graphPtr->tkwin, penPtr->configSpecs,
455 (char *)penPtr, argv[4], configFlags);
456}
457
458/*
459 * ----------------------------------------------------------------------
460 *
461 * ConfigureOp --
462 *
463 * Queries or resets pen attributes (font, line width, color, etc).
464 *
465 * Results:
466 * A standard Tcl result. If querying configuration values,
467 * interp->result will contain the results.
468 *
469 * Side Effects:
470 * Pen resources are possibly allocated (GC, font).
471 *
472 * ----------------------------------------------------------------------
473 */
474static int
475ConfigureOp(interp, graphPtr, argc, argv)
476 Tcl_Interp *interp;
477 Graph *graphPtr;
478 int argc;
479 char *argv[];
480{
481 int flags;
482 Pen *penPtr;
483 int nNames, nOpts;
484 int redraw;
485 char **options;
486 register int i;
487
488 /* Figure out where the option value pairs begin */
489 argc -= 3;
490 argv += 3;
491 for (i = 0; i < argc; i++) {
492 if (argv[i][0] == '-') {
493 break;
494 }
495 if (NameToPen(graphPtr, argv[i]) == NULL) {
496 return TCL_ERROR;
497 }
498 }
499 nNames = i; /* Number of pen names specified */
500 nOpts = argc - i; /* Number of options specified */
501 options = argv + i; /* Start of options in argv */
502
503 redraw = 0;
504 for (i = 0; i < nNames; i++) {
505 penPtr = NameToPen(graphPtr, argv[i]);
506 flags = TK_CONFIG_ARGV_ONLY | (penPtr->flags & (ACTIVE_PEN|NORMAL_PEN));
507 if (nOpts == 0) {
508 return Tk_ConfigureInfo(interp, graphPtr->tkwin,
509 penPtr->configSpecs, (char *)penPtr, (char *)NULL, flags);
510 } else if (nOpts == 1) {
511 return Tk_ConfigureInfo(interp, graphPtr->tkwin,
512 penPtr->configSpecs, (char *)penPtr, options[0], flags);
513 }
514 if (Tk_ConfigureWidget(interp, graphPtr->tkwin, penPtr->configSpecs,
515 nOpts, options, (char *)penPtr, flags) != TCL_OK) {
516 break;
517 }
518 (*penPtr->configProc) (graphPtr, penPtr);
519 if (penPtr->refCount > 0) {
520 redraw++;
521 }
522 }
523 if (redraw) {
524 graphPtr->flags |= REDRAW_BACKING_STORE | DRAW_MARGINS;
525 Blt_EventuallyRedrawGraph(graphPtr);
526 }
527 if (i < nNames) {
528 return TCL_ERROR;
529 }
530 return TCL_OK;
531}
532
533/*
534 *----------------------------------------------------------------------
535 *
536 * CreateOp --
537 *
538 * Adds a new penstyle to the graph.
539 *
540 * Results:
541 * A standard Tcl result.
542 *
543 *----------------------------------------------------------------------
544 */
545static int
546CreateOp(interp, graphPtr, argc, argv)
547 Tcl_Interp *interp;
548 Graph *graphPtr;
549 int argc;
550 char **argv;
551{
552 Pen *penPtr;
553
554 penPtr = Blt_CreatePen(graphPtr, argv[3], graphPtr->classUid, argc - 4,
555 argv + 4);
556 if (penPtr == NULL) {
557 return TCL_ERROR;
558 }
559 Tcl_SetResult(interp, penPtr->name, TCL_VOLATILE);
560 return TCL_OK;
561}
562
563/*
564 *--------------------------------------------------------------
565 *
566 * DeleteOp --
567 *
568 * Delete the given pen.
569 *
570 * Results:
571 * Always returns TCL_OK. The interp->result field is
572 * a list of the graph axis limits.
573 *
574 *--------------------------------------------------------------
575 */
576
577/*ARGSUSED*/
578static int
579DeleteOp(interp, graphPtr, argc, argv)
580 Tcl_Interp *interp;
581 Graph *graphPtr;
582 int argc;
583 char **argv;
584{
585 Pen *penPtr;
586 int i;
587
588 for (i = 3; i < argc; i++) {
589 penPtr = NameToPen(graphPtr, argv[i]);
590 if (penPtr == NULL) {
591 return TCL_ERROR;
592 }
593 if (penPtr->flags & PEN_DELETE_PENDING) {
594 Tcl_AppendResult(graphPtr->interp, "can't find pen \"", argv[i],
595 "\" in \"", Tk_PathName(graphPtr->tkwin), "\"", (char *)NULL);
596 return TCL_ERROR;
597 }
598 penPtr->flags |= PEN_DELETE_PENDING;
599 if (penPtr->refCount == 0) {
600 DestroyPen(graphPtr, penPtr);
601 }
602 }
603 return TCL_OK;
604}
605
606/*
607 * ----------------------------------------------------------------------
608 *
609 * NamesOp --
610 *
611 * Return a list of the names of all the axes.
612 *
613 * Results:
614 * Returns a standard Tcl result.
615 *
616 * ----------------------------------------------------------------------
617 */
618/*ARGSUSED*/
619static int
620NamesOp(interp, graphPtr, argc, argv)
621 Tcl_Interp *interp;
622 Graph *graphPtr;
623 int argc;
624 char **argv;
625{
626 Blt_HashSearch cursor;
627 Pen *penPtr;
628 register int i;
629 register Blt_HashEntry *hPtr;
630
631 for (hPtr = Blt_FirstHashEntry(&(graphPtr->penTable), &cursor);
632 hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
633 penPtr = (Pen *)Blt_GetHashValue(hPtr);
634 if (penPtr->flags & PEN_DELETE_PENDING) {
635 continue;
636 }
637 if (argc == 3) {
638 Tcl_AppendElement(interp, penPtr->name);
639 continue;
640 }
641 for (i = 3; i < argc; i++) {
642 if (Tcl_StringMatch(penPtr->name, argv[i])) {
643 Tcl_AppendElement(interp, penPtr->name);
644 break;
645 }
646 }
647 }
648 return TCL_OK;
649}
650
651/*
652 * ----------------------------------------------------------------------
653 *
654 * TypeOp --
655 *
656 * Return the type of pen.
657 *
658 * Results:
659 * Returns a standard Tcl result.
660 *
661 * ----------------------------------------------------------------------
662 */
663/*ARGSUSED*/
664static int
665TypeOp(interp, graphPtr, argc, argv)
666 Tcl_Interp *interp;
667 Graph *graphPtr;
668 int argc;
669 char **argv;
670{
671 Pen *penPtr;
672
673 penPtr = NameToPen(graphPtr, argv[3]);
674 if (penPtr == NULL) {
675 return TCL_ERROR;
676 }
677 Tcl_SetResult(interp, penPtr->classUid, TCL_STATIC);
678 return TCL_OK;
679}
680
681static Blt_OpSpec penOps[] =
682{
683 {"cget", 2, (Blt_Op)CgetOp, 5, 5, "penName option",},
684 {"configure", 2, (Blt_Op)ConfigureOp, 4, 0,
685 "penName ?penName?... ?option value?...",},
686 {"create", 2, (Blt_Op)CreateOp, 4, 0, "penName ?option value?...",},
687 {"delete", 2, (Blt_Op)DeleteOp, 3, 0, "?penName?...",},
688 {"names", 1, (Blt_Op)NamesOp, 3, 0, "?pattern?...",},
689 {"type", 1, (Blt_Op)TypeOp, 4, 4, "penName",},
690};
691static int nPenOps = sizeof(penOps) / sizeof(Blt_OpSpec);
692
693int
694Blt_PenOp(graphPtr, interp, argc, argv)
695 Graph *graphPtr;
696 Tcl_Interp *interp;
697 int argc;
698 char **argv;
699{
700 Blt_Op proc;
701
702 proc = Blt_GetOp(interp, nPenOps, penOps, BLT_OP_ARG2, argc, argv, 0);
703 if (proc == NULL) {
704 return TCL_ERROR;
705 }
706 return (*proc) (interp, graphPtr, argc, argv);
707}
Note: See TracBrowser for help on using the repository browser.