]> www.wagner.pp.ru Git - oss/ck.git/blob - ckBorder.c
Ck console graphics toolkit
[oss/ck.git] / ckBorder.c
1 /*
2  * ckBorder.c --
3  *
4  *      Manage borders by using alternate character set.
5  *
6  * Copyright (c) 1995 Christian Werner
7  *
8  * See the file "license.terms" for information on usage and redistribution
9  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10  */
11
12 #include "ckPort.h"
13 #include "ck.h"
14
15 /*
16  * Variables used in this module.
17  */
18
19 static Tcl_HashTable gCharTable;          /* Maps gChar names to values. */
20 static int initialized = 0;               /* gCharTable initialized. */
21
22 \f
23 /*
24  *------------------------------------------------------------------------
25  *
26  * Ck_GetGChar --
27  *
28  *      Return curses ACS character given string.
29  *
30  *------------------------------------------------------------------------
31  */
32
33 int
34 Ck_GetGChar(interp, name, gchar)
35     Tcl_Interp *interp;
36     char *name;
37     int *gchar;
38 {
39     Tcl_HashEntry *hPtr;
40
41     if (!initialized) {
42         int new;
43
44         Tcl_InitHashTable(&gCharTable, TCL_STRING_KEYS);
45         hPtr = Tcl_CreateHashEntry(&gCharTable, "ulcorner", &new);
46         Tcl_SetHashValue(hPtr, (ClientData) ACS_ULCORNER);
47         hPtr = Tcl_CreateHashEntry(&gCharTable, "urcorner", &new);
48         Tcl_SetHashValue(hPtr, (ClientData) ACS_URCORNER);
49         hPtr = Tcl_CreateHashEntry(&gCharTable, "llcorner", &new);
50         Tcl_SetHashValue(hPtr, (ClientData) ACS_LLCORNER);
51         hPtr = Tcl_CreateHashEntry(&gCharTable, "lrcorner", &new);
52         Tcl_SetHashValue(hPtr, (ClientData) ACS_LRCORNER);
53         hPtr = Tcl_CreateHashEntry(&gCharTable, "rtee", &new);
54         Tcl_SetHashValue(hPtr, (ClientData) ACS_RTEE);
55         hPtr = Tcl_CreateHashEntry(&gCharTable, "ltee", &new);
56         Tcl_SetHashValue(hPtr, (ClientData) ACS_LTEE);
57         hPtr = Tcl_CreateHashEntry(&gCharTable, "btee", &new);
58         Tcl_SetHashValue(hPtr, (ClientData) ACS_BTEE);
59         hPtr = Tcl_CreateHashEntry(&gCharTable, "ttee", &new);
60         Tcl_SetHashValue(hPtr, (ClientData) ACS_TTEE);
61         hPtr = Tcl_CreateHashEntry(&gCharTable, "hline", &new);
62         Tcl_SetHashValue(hPtr, (ClientData) ACS_HLINE);
63         hPtr = Tcl_CreateHashEntry(&gCharTable, "vline", &new);
64         Tcl_SetHashValue(hPtr, (ClientData) ACS_VLINE);
65         hPtr = Tcl_CreateHashEntry(&gCharTable, "plus", &new);
66         Tcl_SetHashValue(hPtr, (ClientData) ACS_PLUS);
67         hPtr = Tcl_CreateHashEntry(&gCharTable, "s1", &new);
68         Tcl_SetHashValue(hPtr, (ClientData) ACS_S1);
69         hPtr = Tcl_CreateHashEntry(&gCharTable, "s9", &new);
70         Tcl_SetHashValue(hPtr, (ClientData) ACS_S9);
71         hPtr = Tcl_CreateHashEntry(&gCharTable, "diamond", &new);
72         Tcl_SetHashValue(hPtr, (ClientData) ACS_DIAMOND);
73         hPtr = Tcl_CreateHashEntry(&gCharTable, "ckboard", &new);
74         Tcl_SetHashValue(hPtr, (ClientData) ACS_CKBOARD);
75         hPtr = Tcl_CreateHashEntry(&gCharTable, "degree", &new);
76         Tcl_SetHashValue(hPtr, (ClientData) ACS_DEGREE);
77         hPtr = Tcl_CreateHashEntry(&gCharTable, "plminus", &new);
78         Tcl_SetHashValue(hPtr, (ClientData) ACS_PLMINUS);
79         hPtr = Tcl_CreateHashEntry(&gCharTable, "bullet", &new);
80         Tcl_SetHashValue(hPtr, (ClientData) ACS_BULLET);
81         hPtr = Tcl_CreateHashEntry(&gCharTable, "larrow", &new);
82         Tcl_SetHashValue(hPtr, (ClientData) ACS_LARROW);
83         hPtr = Tcl_CreateHashEntry(&gCharTable, "rarrow", &new);
84         Tcl_SetHashValue(hPtr, (ClientData) ACS_RARROW);
85         hPtr = Tcl_CreateHashEntry(&gCharTable, "darrow", &new);
86         Tcl_SetHashValue(hPtr, (ClientData) ACS_DARROW);
87         hPtr = Tcl_CreateHashEntry(&gCharTable, "uarrow", &new);
88         Tcl_SetHashValue(hPtr, (ClientData) ACS_UARROW);
89         hPtr = Tcl_CreateHashEntry(&gCharTable, "board", &new);
90         Tcl_SetHashValue(hPtr, (ClientData) ACS_BOARD);
91         hPtr = Tcl_CreateHashEntry(&gCharTable, "lantern", &new);
92         Tcl_SetHashValue(hPtr, (ClientData) ACS_LANTERN);
93         hPtr = Tcl_CreateHashEntry(&gCharTable, "block", &new);
94         Tcl_SetHashValue(hPtr, (ClientData) ACS_BLOCK);
95
96         initialized = 1;
97     }
98     
99     hPtr = Tcl_FindHashEntry(&gCharTable, name);
100     if (hPtr == NULL) {
101         if (interp != NULL)
102             Tcl_AppendResult(interp,
103                 "bad gchar \"", name, "\"", (char *) NULL);
104         return TCL_ERROR;
105     }
106     if (gchar != NULL)
107         *gchar = (int) Tcl_GetHashValue(hPtr);
108     return TCL_OK;
109 }
110 \f
111 /*
112  *------------------------------------------------------------------------
113  *
114  * Ck_SetGChar --
115  *
116  *      Modify ACS mapping.
117  *
118  *------------------------------------------------------------------------
119  */
120
121 int
122 Ck_SetGChar(interp, name, gchar)
123     Tcl_Interp *interp;
124     char *name;
125     int gchar;
126 {
127     Tcl_HashEntry *hPtr;
128
129     if (!initialized)
130         Ck_GetGChar(interp, "ulcorner", NULL);
131     hPtr = Tcl_FindHashEntry(&gCharTable, name);    
132     if (hPtr == NULL) {
133         Tcl_AppendResult(interp, "bad gchar \"", name, "\"", (char *) NULL);
134         return TCL_ERROR;
135     }
136     Tcl_SetHashValue(hPtr, (ClientData) gchar);
137     return TCL_OK;
138 }
139 \f
140 /*
141  *------------------------------------------------------------------------
142  *
143  * Ck_GetBorder --
144  *
145  *      Create border from string.
146  *
147  *------------------------------------------------------------------------
148  */
149
150 CkBorder *
151 Ck_GetBorder(interp, string)
152     Tcl_Interp *interp;
153     char *string;
154 {
155     int i, largc, bchar[8];
156     char **largv;
157     CkBorder *borderPtr;
158
159     if (Tcl_SplitList(interp, string, &largc, &largv) != TCL_OK)
160         return NULL;
161     if (largc != 1 && largc != 3 && largc != 6 && largc != 8) {
162         ckfree((char *) largv);
163         Tcl_AppendResult(interp, "illegal number of box characters",
164             (char *) NULL);
165         return NULL;
166     }
167     for (i = 0; i < sizeof (bchar) / sizeof (bchar[0]); i++)
168         bchar[i] = ' ';
169     for (i = 0; i < largc; i++) {
170         if (strlen(largv[i]) == 1)
171             bchar[i] = (unsigned char) largv[i][0];
172         else if (Ck_GetGChar(interp, largv[i], &bchar[i]) != TCL_OK) {
173             ckfree((char *) largv);
174             return NULL;
175         }
176     }
177     if (largc == 1) {
178         for (i = 1; i < sizeof (bchar) / sizeof (bchar[0]); i++)
179             bchar[i] = bchar[0];
180     } else if (largc == 3) {
181         bchar[3] = bchar[7] = bchar[2];
182         bchar[2] = bchar[4] = bchar[6] = bchar[0];
183         bchar[5] = bchar[1];
184     } else if (largc == 6) {
185         bchar[6] = bchar[5];
186         bchar[5] = bchar[1];
187         bchar[7] = bchar[3];
188     }
189     ckfree((char *) largv);
190     borderPtr = (CkBorder *) ckalloc(sizeof (CkBorder));
191     memset(borderPtr, 0, sizeof (CkBorder));
192     for (i = 0; i < 8; i++)
193         borderPtr->gchar[i] = bchar[i];
194     borderPtr->name = ckalloc(strlen(string) + 1);
195     strcpy(borderPtr->name, string);    
196     return borderPtr;
197 }
198 \f
199 /*
200  *------------------------------------------------------------------------
201  *
202  * Ck_FreeBorder --
203  *
204  *      Release memory related to border.
205  *
206  *------------------------------------------------------------------------
207  */
208
209 void
210 Ck_FreeBorder(borderPtr)
211     CkBorder *borderPtr;
212 {
213     ckfree(borderPtr->name);
214     ckfree((char *) borderPtr);
215 }
216 \f
217 /*
218  *------------------------------------------------------------------------
219  *
220  * Ck_NameOfBorder --
221  *
222  *      Create border from string.
223  *
224  *------------------------------------------------------------------------
225  */
226
227 char *
228 Ck_NameOfBorder(borderPtr)
229     CkBorder *borderPtr;
230 {
231     return borderPtr->name;
232 }
233 \f
234 /*
235  *------------------------------------------------------------------------
236  *
237  * Ck_DrawBorder --
238  *
239  *      Given window, border and bounding box, draw border.
240  *
241  *------------------------------------------------------------------------
242  */
243
244 void
245 Ck_DrawBorder(winPtr, borderPtr, x, y, width, height)
246     CkWindow *winPtr;
247     CkBorder *borderPtr;
248     int x, y, width, height;
249 {
250     int i, *gchar;
251     WINDOW *w;
252
253     if (winPtr->window == NULL)
254         return;
255     w = winPtr->window;
256     gchar = borderPtr->gchar;
257     if (width < 1 || height < 1)
258         return;
259     if (width == 1) {
260         for (i = y; i < height + y; i++)
261             mvwaddch(w, i, x, gchar[3]);
262         return;
263     }
264     if (height == 1) {
265         for (i = x; i < width + x; i++)
266             mvwaddch(w, y, i, gchar[1]);
267         return;
268     }
269     if (width == 2) {
270         mvwaddch(w, y, x, gchar[0]);
271         mvwaddch(w, y, x + 1, gchar[2]);
272         for (i = y + 1; i < height - 1 + y; i++)
273             mvwaddch(w, i, x, gchar[7]);
274         for (i = y + 1; i < height - 1 + y; i++)
275             mvwaddch(w, i, x + 1, gchar[3]);
276         mvwaddch(w, height - 1 + y, x, gchar[6]);
277         mvwaddch(w, height - 1 + y, x + 1, gchar[4]);
278         return;
279     }
280     if (height == 2) {
281         mvwaddch(w, y, x, gchar[0]);
282         mvwaddch(w, y + 1, x, gchar[6]);
283         for (i = x + 1; i < width - 1 + x; i++)
284             mvwaddch(w, y, i, gchar[1]);
285         for (i = x + 1; i < width - 1 + x; i++)
286             mvwaddch(w, y + 1, i, gchar[5]);
287         mvwaddch(w, y, width - 1 + x, gchar[2]);
288         mvwaddch(w, y + 1, width - 1 + x, gchar[4]);
289         return;
290     }
291     mvwaddch(w, y, x, gchar[0]);
292     for (i = x + 1; i < width - 1 + x; i++)
293         mvwaddch(w, y, i, gchar[1]);
294     mvwaddch(w, y, width - 1 + x, gchar[2]);
295     for (i = y + 1; i < height - 1 + y; i++)
296         mvwaddch(w, i, width - 1 + x, gchar[3]);
297     mvwaddch(w, height - 1 + y, width - 1 + x, gchar[4]);
298     for (i = x + 1; i < width - 1 + x; i++)
299         mvwaddch(w, height - 1 + y, i, gchar[5]);
300     mvwaddch(w, height - 1 + y, x, gchar[6]);
301     for (i = y + 1; i < height - 1 + y; i++)
302         mvwaddch(w, i, x, gchar[7]);
303 }