]> www.wagner.pp.ru Git - oss/ck.git/blob - ckGet.c
Ck console graphics toolkit
[oss/ck.git] / ckGet.c
1 /* 
2  * ckGet.c --
3  *
4  *      This file contains a number of "Ck_GetXXX" procedures, which
5  *      parse text strings into useful forms for Ck.
6  *
7  * Copyright (c) 1990-1994 The Regents of the University of California.
8  * Copyright (c) 1994-1995 Sun Microsystems, Inc.
9  * Copyright (c) 1995 Christian Werner
10  *
11  * See the file "license.terms" for information on usage and redistribution
12  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13  */
14
15 #include "ckPort.h"
16 #include "ck.h"
17
18 typedef struct {
19     short fg, bg;
20 } CPair;
21
22 static CPair *cPairs = NULL;
23 static int numPairs, newPair;
24
25 /*
26  * The hash table below is used to keep track of all the Ck_Uids created
27  * so far.
28  */
29
30 static Tcl_HashTable uidTable;
31 static int initialized = 0;
32
33 static struct {
34     char *name;
35     int value;
36 } ctab[] = {
37     { "black", COLOR_BLACK },
38     { "blue", COLOR_BLUE },
39     { "cyan", COLOR_CYAN },
40     { "green", COLOR_GREEN },
41     { "magenta", COLOR_MAGENTA },
42     { "red", COLOR_RED },
43     { "white", COLOR_WHITE },
44     { "yellow", COLOR_YELLOW }
45 };
46
47 static struct {
48     char *name;
49     int value;
50 } atab[] = {
51     { "blink", A_BLINK },
52     { "bold", A_BOLD },
53     { "dim", A_DIM },
54     { "normal", A_NORMAL },
55     { "reverse", A_REVERSE },
56     { "standout", A_STANDOUT },
57     { "underline", A_UNDERLINE }
58 };
59 \f
60 /*
61  *----------------------------------------------------------------------
62  *
63  * Ck_GetUid --
64  *
65  *      Given a string, this procedure returns a unique identifier
66  *      for the string.
67  *
68  * Results:
69  *      This procedure returns a Ck_Uid corresponding to the "string"
70  *      argument.  The Ck_Uid has a string value identical to string
71  *      (strcmp will return 0), but it's guaranteed that any other
72  *      calls to this procedure with a string equal to "string" will
73  *      return exactly the same result (i.e. can compare Ck_Uid
74  *      *values* directly, without having to call strcmp on what they
75  *      point to).
76  *
77  * Side effects:
78  *      New information may be entered into the identifier table.
79  *
80  *----------------------------------------------------------------------
81  */
82
83 Ck_Uid
84 Ck_GetUid(string)
85     char *string;               /* String to convert. */
86 {
87     int dummy;
88
89     if (!initialized) {
90         Tcl_InitHashTable(&uidTable, TCL_STRING_KEYS);
91         initialized = 1;
92     }
93     return (Ck_Uid) Tcl_GetHashKey(&uidTable,
94             Tcl_CreateHashEntry(&uidTable, string, &dummy));
95 }
96 \f
97 /*
98  *------------------------------------------------------------------------
99  *
100  * Ck_GetColor --
101  *
102  *      Given a color specification, return curses color value.
103  *
104  * Results:
105  *      TCL_OK if color found, curses color in *colorPtr.
106  *      TCL_ERROR if color not found; interp->result contains an
107  *      error message.
108  *
109  * Side effects:
110  *      None.
111  *
112  *------------------------------------------------------------------------
113  */
114
115 int
116 Ck_GetColor(interp, name, colorPtr)
117     Tcl_Interp *interp;
118     char *name;
119     int *colorPtr;
120 {
121     int i, len;
122
123     len = strlen(name);
124     if (len > 0)
125         for (i = 0; i < sizeof (ctab) / sizeof (ctab[0]); i++)
126             if (strncmp(name, ctab[i].name, len) == 0) {
127                 if (colorPtr != NULL)
128                     *colorPtr = ctab[i].value;
129                 return TCL_OK;
130             }
131     Tcl_AppendResult(interp, "bad color \"", name, "\"", (char *) NULL);
132     return TCL_ERROR;
133 }
134 \f
135 /*
136  *------------------------------------------------------------------------
137  *
138  * Ck_NameOfColor --
139  *
140  *      Given a curses color, return its name.
141  *
142  * Results:
143  *      String: name of color, or NULL if no valid color.
144  *
145  * Side effects:
146  *      None.
147  *
148  *------------------------------------------------------------------------
149  */
150
151 char *
152 Ck_NameOfColor(color)
153     int color;          /* Curses color to get name for */
154 {
155     int i;
156
157     for (i = 0; i < sizeof (ctab) / sizeof (ctab[0]); i++)
158         if (ctab[i].value == color)
159             return ctab[i].name;
160     return NULL;
161 }
162 \f
163 /*
164  *------------------------------------------------------------------------
165  *
166  * Ck_GetAttr --
167  *
168  *      Given an attribute specification, return attribute value.
169  *
170  * Results:
171  *      TCL_OK if color found, curses color in *colorPtr.
172  *      TCL_ERROR if color not found; interp->result contains an
173  *      error message.
174  *
175  * Side effects:
176  *      None.
177  *
178  *------------------------------------------------------------------------
179  */
180
181 int
182 Ck_GetAttr(interp, name, attrPtr)
183     Tcl_Interp *interp;
184     char *name;
185     int *attrPtr;
186 {
187     int i, k, len, largc;
188     char **largv;
189
190     if (Tcl_SplitList(interp, name, &largc, &largv) != TCL_OK)
191         return TCL_ERROR;
192     if (attrPtr != NULL)
193         *attrPtr = A_NORMAL;
194     if (largc > 1 || (largc == 1 && largv[0][0] != '\0')) {
195         for (i = 0; i < largc; i++) {
196             len = strlen(largv[i]);
197             if (len > 0) {
198                 for (k = 0; k < sizeof (atab) / sizeof (atab[0]); k++)
199                     if (strncmp(largv[i], atab[k].name, len) == 0) {
200                         if (attrPtr != NULL)
201                             *attrPtr |= atab[k].value;
202                         break;
203                     }
204                 if (k >= sizeof (atab) / sizeof (atab[0])) {
205                     Tcl_AppendResult(interp, "bad attribute \"",
206                         name, "\"", (char *) NULL);
207                     ckfree((char *) largv);
208                     return TCL_ERROR;
209                 }
210             }
211         }
212     }
213     ckfree((char *) largv);
214     return TCL_OK;
215 }
216 \f
217 /*
218  *------------------------------------------------------------------------
219  *
220  * Ck_NameOfAttr --
221  *
222  *      Given an attribute value, return its textual specification.
223  *
224  * Results:
225  *      interp->result contains result or message.
226  *
227  * Side effects:
228  *      None.
229  *
230  *------------------------------------------------------------------------
231  */
232
233 char *
234 Ck_NameOfAttr(attr)
235     int attr;
236 {
237     int i;
238     char *result;
239     Tcl_DString list;
240
241     Tcl_DStringInit(&list);
242     if (attr == -1 || attr == A_NORMAL)
243         Tcl_DStringAppendElement(&list, "normal");
244     else {
245         for (i = 0; i < sizeof (atab) / sizeof (atab[0]); i++)
246             if (attr & atab[i].value)
247                 Tcl_DStringAppendElement(&list, atab[i].name);
248     }
249     result = ckalloc(Tcl_DStringLength(&list) + 1);
250     strcpy(result, Tcl_DStringValue(&list));
251     Tcl_DStringFree(&list);
252     return result;
253 }
254 /*
255  *------------------------------------------------------------------------
256  *
257  * Ck_GetColorPair --
258  *
259  *      Given background/foreground curses colors, a color pair
260  *      is allocated and returned.
261  *
262  * Results:
263  *      TCL_OK if color found, curses color in *colorPtr.
264  *      TCL_ERROR if color not found; interp->result contains an
265  *      error message.
266  *
267  * Side effects:
268  *      None.
269  *
270  *------------------------------------------------------------------------
271  */
272
273 int
274 Ck_GetPair(winPtr, fg, bg)
275     CkWindow *winPtr;
276     int fg, bg;
277 {
278     int i;
279
280     if (!(winPtr->mainPtr->flags & CK_HAS_COLOR))
281         return COLOR_PAIR(0);
282     if (cPairs == NULL) {
283         cPairs = (CPair *) ckalloc(sizeof (CPair) * (COLOR_PAIRS + 2));
284         numPairs = 0;
285         newPair = 1;
286     }
287     for (i = 1; i < numPairs; i++)
288         if (cPairs[i].fg == fg && cPairs[i].bg == bg)
289             return COLOR_PAIR(i);
290     i = newPair;
291     cPairs[i].fg = fg;
292     cPairs[i].bg = bg;
293     init_pair((short) i, (short) fg, (short) bg);
294     if (++newPair >= COLOR_PAIRS)
295         newPair = 1;
296     else
297         numPairs = newPair;
298     return COLOR_PAIR(i);
299 }
300 \f
301 /*
302  *--------------------------------------------------------------
303  *
304  * Ck_GetAnchor --
305  *
306  *      Given a string, return the corresponding Ck_Anchor.
307  *
308  * Results:
309  *      The return value is a standard Tcl return result.  If
310  *      TCL_OK is returned, then everything went well and the
311  *      position is stored at *anchorPtr;  otherwise TCL_ERROR
312  *      is returned and an error message is left in
313  *      interp->result.
314  *
315  * Side effects:
316  *      None.
317  *
318  *--------------------------------------------------------------
319  */
320
321 int
322 Ck_GetAnchor(interp, string, anchorPtr)
323     Tcl_Interp *interp;         /* Use this for error reporting. */
324     char *string;               /* String describing a direction. */
325     Ck_Anchor *anchorPtr;       /* Where to store Ck_Anchor corresponding
326                                  * to string. */
327 {
328     switch (string[0]) {
329         case 'n':
330             if (string[1] == 0) {
331                 *anchorPtr = CK_ANCHOR_N;
332                 return TCL_OK;
333             } else if ((string[1] == 'e') && (string[2] == 0)) {
334                 *anchorPtr = CK_ANCHOR_NE;
335                 return TCL_OK;
336             } else if ((string[1] == 'w') && (string[2] == 0)) {
337                 *anchorPtr = CK_ANCHOR_NW;
338                 return TCL_OK;
339             }
340             goto error;
341         case 's':
342             if (string[1] == 0) {
343                 *anchorPtr = CK_ANCHOR_S;
344                 return TCL_OK;
345             } else if ((string[1] == 'e') && (string[2] == 0)) {
346                 *anchorPtr = CK_ANCHOR_SE;
347                 return TCL_OK;
348             } else if ((string[1] == 'w') && (string[2] == 0)) {
349                 *anchorPtr = CK_ANCHOR_SW;
350                 return TCL_OK;
351             } else {
352                 goto error;
353             }
354         case 'e':
355             if (string[1] == 0) {
356                 *anchorPtr = CK_ANCHOR_E;
357                 return TCL_OK;
358             }
359             goto error;
360         case 'w':
361             if (string[1] == 0) {
362                 *anchorPtr = CK_ANCHOR_W;
363                 return TCL_OK;
364             }
365             goto error;
366         case 'c':
367             if (strncmp(string, "center", strlen(string)) == 0) {
368                 *anchorPtr = CK_ANCHOR_CENTER;
369                 return TCL_OK;
370             }
371             goto error;
372     }
373
374     error:
375     Tcl_AppendResult(interp, "bad anchor position \"", string,
376             "\": must be n, ne, e, se, s, sw, w, nw, or center",
377             (char *) NULL);
378     return TCL_ERROR;
379 }
380 \f
381 /*
382  *--------------------------------------------------------------
383  *
384  * Ck_NameOfAnchor --
385  *
386  *      Given a Ck_Anchor, return the string that corresponds
387  *      to it.
388  *
389  * Results:
390  *      None.
391  *
392  * Side effects:
393  *      None.
394  *
395  *--------------------------------------------------------------
396  */
397
398 char *
399 Ck_NameOfAnchor(anchor)
400     Ck_Anchor anchor;           /* Anchor for which identifying string
401                                  * is desired. */
402 {
403     switch (anchor) {
404         case CK_ANCHOR_N: return "n";
405         case CK_ANCHOR_NE: return "ne";
406         case CK_ANCHOR_E: return "e";
407         case CK_ANCHOR_SE: return "se";
408         case CK_ANCHOR_S: return "s";
409         case CK_ANCHOR_SW: return "sw";
410         case CK_ANCHOR_W: return "w";
411         case CK_ANCHOR_NW: return "nw";
412         case CK_ANCHOR_CENTER: return "center";
413     }
414     return "unknown anchor position";
415 }
416 \f
417 /*
418  *--------------------------------------------------------------
419  *
420  * Ck_GetJustify --
421  *
422  *      Given a string, return the corresponding Ck_Justify.
423  *
424  * Results:
425  *      The return value is a standard Tcl return result.  If
426  *      TCL_OK is returned, then everything went well and the
427  *      justification is stored at *justifyPtr;  otherwise
428  *      TCL_ERROR is returned and an error message is left in
429  *      interp->result.
430  *
431  * Side effects:
432  *      None.
433  *
434  *--------------------------------------------------------------
435  */
436
437 int
438 Ck_GetJustify(interp, string, justifyPtr)
439     Tcl_Interp *interp;         /* Use this for error reporting. */
440     char *string;               /* String describing a justification style. */
441     Ck_Justify *justifyPtr;     /* Where to store Ck_Justify corresponding
442                                  * to string. */
443 {
444     int c, length;
445
446     c = string[0];
447     length = strlen(string);
448
449     if ((c == 'l') && (strncmp(string, "left", length) == 0)) {
450         *justifyPtr = CK_JUSTIFY_LEFT;
451         return TCL_OK;
452     }
453     if ((c == 'r') && (strncmp(string, "right", length) == 0)) {
454         *justifyPtr = CK_JUSTIFY_RIGHT;
455         return TCL_OK;
456     }
457     if ((c == 'c') && (strncmp(string, "center", length) == 0)) {
458         *justifyPtr = CK_JUSTIFY_CENTER;
459         return TCL_OK;
460     }
461     if ((c == 'f') && (strncmp(string, "fill", length) == 0)) {
462         *justifyPtr = CK_JUSTIFY_FILL;
463         return TCL_OK;
464     }
465
466     Tcl_AppendResult(interp, "bad justification \"", string,
467             "\": must be left, right, center, or fill",
468             (char *) NULL);
469     return TCL_ERROR;
470 }
471 \f
472 /*
473  *--------------------------------------------------------------
474  *
475  * Ck_NameOfJustify --
476  *
477  *      Given a Ck_Justify, return the string that corresponds
478  *      to it.
479  *
480  * Results:
481  *      None.
482  *
483  * Side effects:
484  *      None.
485  *
486  *--------------------------------------------------------------
487  */
488
489 char *
490 Ck_NameOfJustify(justify)
491     Ck_Justify justify;         /* Justification style for which
492                                  * identifying string is desired. */
493 {
494     switch (justify) {
495         case CK_JUSTIFY_LEFT: return "left";
496         case CK_JUSTIFY_RIGHT: return "right";
497         case CK_JUSTIFY_CENTER: return "center";
498         case CK_JUSTIFY_FILL: return "fill";
499     }
500     return "unknown justification style";
501 }
502 \f
503 /*
504  *--------------------------------------------------------------
505  *
506  * Ck_GetCoord --
507  *
508  *      Given a string, return the coordinate that corresponds
509  *      to it.
510  *
511  * Results:
512  *      None.
513  *
514  * Side effects:
515  *      None.
516  *
517  *--------------------------------------------------------------
518  */
519
520 int
521 Ck_GetCoord(interp, winPtr, string, intPtr)
522     Tcl_Interp *interp;        /* Use this for error reporting. */
523     CkWindow *winPtr;          /* Window (not used). */
524     char *string;              /* String to convert. */
525     int *intPtr;               /* Place to store converted result. */
526 {
527     int value;
528
529     if (Tcl_GetInt(interp, string, &value) != TCL_OK)
530         return TCL_ERROR;
531     if (value < 0) {
532         Tcl_AppendResult(interp, "coordinate may not be negative",
533             (char *) NULL);
534         return TCL_ERROR;
535     }
536     *intPtr = value;
537     return TCL_OK;
538 }