chiark / gitweb /
Imported Upstream version 1.0.0
[e16] / src / tclass.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2004-2008 Kim Woelders
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies of the Software, its documentation and marketing & publicity
14  * materials, and acknowledgment shall be given in the documentation, materials
15  * and software packages that this Software was used.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include "E.h"
25 #include "conf.h"
26 #include "e16-ecore_list.h"
27 #include "emodule.h"
28 #include "iclass.h"
29 #include "tclass.h"
30 #include "xwin.h"
31
32 #define ENABLE_DESTROY 0        /* Broken */
33
34 static Ecore_List  *tclass_list = NULL;
35
36 static TextClass   *TextclassGetFallback(void);
37
38 static char        *
39 TextstateFontLookup(const char *name)
40 {
41    const char         *font;
42
43    if (*name == '*')
44      {
45         font = FontLookup(name + 1);
46         if (font)
47            name = font;
48      }
49    return Estrdup(name);
50 }
51
52 static TextState   *
53 TextstateCreate(const char *font)
54 {
55    TextState          *ts;
56
57    ts = ECALLOC(TextState, 1);
58    if (!ts)
59       return NULL;
60
61    ts->style.mode = MODE_WRAP_CHAR;
62    ts->style.orientation = FONT_TO_RIGHT;
63
64    if (font)
65      {
66         ts->fontname = TextstateFontLookup(font);
67         ts->style.mode = MODE_VERBATIM;
68      }
69
70    return ts;
71 }
72
73 #if ENABLE_DESTROY
74 static void
75 TextStateDestroy(TextState * ts)
76 {
77    if (!ts)
78       return;
79
80    Efree(ts->fontname);
81    if (ts->ops)
82       ts->ops->Destroy(ts);
83
84    Efree(ts);
85 }
86 #endif
87
88 static TextClass   *
89 TextclassCreate(const char *name)
90 {
91    TextClass          *tc;
92
93    tc = ECALLOC(TextClass, 1);
94    if (!tc)
95       return NULL;
96
97    if (!tclass_list)
98       tclass_list = ecore_list_new();
99    ecore_list_prepend(tclass_list, tc);
100
101    tc->name = Estrdup(name);
102    tc->justification = 512;
103
104    return tc;
105 }
106
107 #if ENABLE_DESTROY
108 static void
109 TextclassDestroy(TextClass * tc)
110 {
111    if (tc->ref_count > 0)
112      {
113         DialogOK("TextClass Error!", _("%u references remain\n"),
114                  tc->ref_count);
115         return;
116      }
117    Efree(tc->name);
118    TextStateDestroy(tc->norm.normal);
119    TextStateDestroy(tc->norm.hilited);
120    TextStateDestroy(tc->norm.clicked);
121    TextStateDestroy(tc->norm.disabled);
122    TextStateDestroy(tc->active.normal);
123    TextStateDestroy(tc->active.hilited);
124    TextStateDestroy(tc->active.clicked);
125    TextStateDestroy(tc->active.disabled);
126    TextStateDestroy(tc->sticky.normal);
127    TextStateDestroy(tc->sticky.hilited);
128    TextStateDestroy(tc->sticky.clicked);
129    TextStateDestroy(tc->sticky.disabled);
130    TextStateDestroy(tc->sticky_active.normal);
131    TextStateDestroy(tc->sticky_active.hilited);
132    TextStateDestroy(tc->sticky_active.clicked);
133    TextStateDestroy(tc->sticky_active.disabled);
134
135    Efree(tc);
136 }
137 #endif /* ENABLE_DESTROY */
138
139 TextClass          *
140 TextclassAlloc(const char *name, int fallback)
141 {
142    TextClass          *tc;
143
144    if (!name || !name[0])
145       return NULL;
146
147    tc = TextclassFind(name, fallback);
148    if (tc)
149       tc->ref_count++;
150
151    return tc;
152 }
153
154 void
155 TextclassFree(TextClass * tc)
156 {
157    if (tc)
158       tc->ref_count--;
159 }
160
161 int
162 TextclassGetJustification(TextClass * tc)
163 {
164    return tc->justification;
165 }
166
167 void
168 TextclassSetJustification(TextClass * tc, int just)
169 {
170    tc->justification = just;
171 }
172
173 static void
174 TextclassPopulate(TextClass * tclass)
175 {
176    if (!tclass)
177       return;
178
179    if (!tclass->norm.normal)
180       return;
181
182    if (!tclass->norm.hilited)
183       tclass->norm.hilited = tclass->norm.normal;
184    if (!tclass->norm.clicked)
185       tclass->norm.clicked = tclass->norm.normal;
186    if (!tclass->norm.disabled)
187       tclass->norm.disabled = tclass->norm.normal;
188
189    if (!tclass->active.normal)
190       tclass->active.normal = tclass->norm.normal;
191    if (!tclass->active.hilited)
192       tclass->active.hilited = tclass->active.normal;
193    if (!tclass->active.clicked)
194       tclass->active.clicked = tclass->active.normal;
195    if (!tclass->active.disabled)
196       tclass->active.disabled = tclass->active.normal;
197
198    if (!tclass->sticky.normal)
199       tclass->sticky.normal = tclass->norm.normal;
200    if (!tclass->sticky.hilited)
201       tclass->sticky.hilited = tclass->sticky.normal;
202    if (!tclass->sticky.clicked)
203       tclass->sticky.clicked = tclass->sticky.normal;
204    if (!tclass->sticky.disabled)
205       tclass->sticky.disabled = tclass->sticky.normal;
206
207    if (!tclass->sticky_active.normal)
208       tclass->sticky_active.normal = tclass->norm.normal;
209    if (!tclass->sticky_active.hilited)
210       tclass->sticky_active.hilited = tclass->sticky_active.normal;
211    if (!tclass->sticky_active.clicked)
212       tclass->sticky_active.clicked = tclass->sticky_active.normal;
213    if (!tclass->sticky_active.disabled)
214       tclass->sticky_active.disabled = tclass->sticky_active.normal;
215 }
216
217 static int
218 _TextclassMatchName(const void *data, const void *match)
219 {
220    return strcmp(((const TextClass *)data)->name, (const char *)match);
221 }
222
223 TextClass          *
224 TextclassFind(const char *name, int fallback)
225 {
226    TextClass          *tc = NULL;
227
228    if (name)
229       tc = (TextClass *) ecore_list_find(tclass_list, _TextclassMatchName,
230                                          name);
231    if (tc || !fallback)
232       return tc;
233
234 #if 0
235    Eprintf("%s: Get fallback (%s)\n", __func__, name);
236 #endif
237    return TextclassGetFallback();
238 }
239
240 int
241 TextclassConfigLoad(FILE * fs)
242 {
243    int                 err = 0;
244    char                s[FILEPATH_LEN_MAX];
245    char                s2[FILEPATH_LEN_MAX];
246    int                 i1, r, g, b;
247    TextClass          *tc = NULL;
248    TextState          *ts = NULL;
249
250    while (GetLine(s, sizeof(s), fs))
251      {
252         i1 = ConfigParseline1(s, s2, NULL, NULL);
253         switch (i1)
254           {
255           case CONFIG_CLOSE:
256              TextclassPopulate(tc);
257              goto done;
258           case CONFIG_CLASSNAME:
259              if (TextclassFind(s2, 0))
260                {
261                   SkipTillEnd(fs);
262                   goto done;
263                }
264              tc = TextclassCreate(s2);
265              break;
266           case TEXT_ORIENTATION:
267              if (ts)
268                 ts->style.orientation = atoi(s2);
269              break;
270           case TEXT_JUSTIFICATION:
271              if (tc)
272                 tc->justification = atoi(s2);
273              break;
274           case CONFIG_DESKTOP:
275           case ICLASS_NORMAL:
276              if (tc)
277                 tc->norm.normal = ts = TextstateCreate(s2);
278              break;
279           case ICLASS_CLICKED:
280              if (tc)
281                 tc->norm.clicked = ts = TextstateCreate(s2);
282              break;
283           case ICLASS_HILITED:
284              if (tc)
285                 tc->norm.hilited = ts = TextstateCreate(s2);
286              break;
287           case ICLASS_DISABLED:
288              if (tc)
289                 tc->norm.disabled = ts = TextstateCreate(s2);
290              break;
291           case ICLASS_STICKY_NORMAL:
292              if (tc)
293                 tc->sticky.normal = ts = TextstateCreate(s2);
294              break;
295           case ICLASS_STICKY_CLICKED:
296              if (tc)
297                 tc->sticky.clicked = ts = TextstateCreate(s2);
298              break;
299           case ICLASS_STICKY_HILITED:
300              if (tc)
301                 tc->sticky.hilited = ts = TextstateCreate(s2);
302              break;
303           case ICLASS_STICKY_DISABLED:
304              if (tc)
305                 tc->sticky.disabled = ts = TextstateCreate(s2);
306              break;
307           case ICLASS_ACTIVE_NORMAL:
308              if (tc)
309                 tc->active.normal = ts = TextstateCreate(s2);
310              break;
311           case ICLASS_ACTIVE_CLICKED:
312              if (tc)
313                 tc->active.clicked = ts = TextstateCreate(s2);
314              break;
315           case ICLASS_ACTIVE_HILITED:
316              if (tc)
317                 tc->active.hilited = ts = TextstateCreate(s2);
318              break;
319           case ICLASS_ACTIVE_DISABLED:
320              if (tc)
321                 tc->active.disabled = ts = TextstateCreate(s2);
322              break;
323           case ICLASS_STICKY_ACTIVE_NORMAL:
324              if (tc)
325                 tc->sticky_active.normal = ts = TextstateCreate(s2);
326              break;
327           case ICLASS_STICKY_ACTIVE_CLICKED:
328              if (tc)
329                 tc->sticky_active.clicked = ts = TextstateCreate(s2);
330              break;
331           case ICLASS_STICKY_ACTIVE_HILITED:
332              if (tc)
333                 tc->sticky_active.hilited = ts = TextstateCreate(s2);
334              break;
335           case ICLASS_STICKY_ACTIVE_DISABLED:
336              if (tc)
337                 tc->sticky_active.disabled = ts = TextstateCreate(s2);
338              break;
339           case TEXT_MODE:
340              if (ts)
341                 ts->style.mode = atoi(s2);
342              break;
343           case TEXT_EFFECT:
344              if (ts)
345                 ts->style.effect = atoi(s2);
346              break;
347           case TEXT_FG_COL:
348              if (ts)
349                {
350                   r = g = b = 0;
351                   sscanf(s, "%*s %i %i %i", &r, &g, &b);
352                   SET_COLOR(&ts->fg_col, r, g, b);
353                }
354              break;
355           case TEXT_BG_COL:
356              if (ts)
357                {
358                   r = g = b = 0;
359                   sscanf(s, "%*s %i %i %i", &r, &g, &b);
360                   SET_COLOR(&ts->bg_col, r, g, b);
361                }
362              break;
363           default:
364              ConfigParseError("TextClass", s);
365              break;
366           }
367      }
368    err = -1;
369
370  done:
371    return err;
372 }
373
374 static TextClass   *
375 TextclassGetFallback(void)
376 {
377    TextClass          *tc;
378
379    tc = TextclassFind("__fb_tc", 0);
380    if (tc)
381       return tc;
382
383    /* Create fallback textclass */
384    tc = TextclassCreate("__fb_tc");
385    if (!tc)
386       return tc;
387
388    tc->norm.normal =
389       TextstateCreate("-*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*");
390    SET_COLOR(&(tc->norm.normal->fg_col), 0, 0, 0);
391    TextclassPopulate(tc);
392
393    return tc;
394 }
395
396 /*
397  * Textclass Module
398  */
399
400 static void
401 TextclassIpc(const char *params)
402 {
403    char                param1[1024];
404    char                param2[1024];
405    int                 l;
406    const char         *p;
407    TextClass          *tc;
408
409    if (!params)
410      {
411         IpcPrintf("Please specify...\n");
412         return;
413      }
414
415    p = params;
416    l = 0;
417    param1[0] = param2[0] = '\0';
418    sscanf(p, "%1000s %1000s %n", param1, param2, &l);
419    p += l;
420
421    if (!strncmp(param1, "list", 2))
422      {
423         ECORE_LIST_FOR_EACH(tclass_list, tc) IpcPrintf("%s\n", tc->name);
424         return;
425      }
426
427    if (!param1[0])
428      {
429         IpcPrintf("TextClass not specified\n");
430         return;
431      }
432
433    if (!strcmp(param2, "create"))
434      {
435         /* Not implemented */
436         return;
437      }
438
439    tc = TextclassFind(param1, 0);
440    if (!tc)
441      {
442         IpcPrintf("TextClass not found: %s\n", param1);
443         return;
444      }
445
446    if (!strcmp(param2, "delete"))
447      {
448 #if ENABLE_DESTROY
449         TextclassDestroy(tc);
450 #endif
451      }
452    else if (!strcmp(param2, "modify"))
453      {
454         /* Not implemented */
455      }
456    else if (!strcmp(param2, "apply"))
457      {
458         Window              xwin;
459         Win                 win;
460         char                state[20];
461         int                 x, y, st;
462
463         /* 3:xwin 4:x 5:y 6:state 7-:txt */
464         xwin = None;
465         x = y = 0;
466         state[0] = '\0';
467         l = 0;
468         sscanf(p, "%lx %d %d %16s %n", &xwin, &x, &y, state, &l);
469         p += l;
470
471         if (!strcmp(state, "normal"))
472            st = STATE_NORMAL;
473         else if (!strcmp(state, "hilited"))
474            st = STATE_HILITED;
475         else if (!strcmp(state, "clicked"))
476            st = STATE_CLICKED;
477         else if (!strcmp(state, "disabled"))
478            st = STATE_DISABLED;
479         else
480            st = STATE_NORMAL;
481
482         if (l == 0)
483            return;
484
485         win = ECreateWinFromXwin(xwin);
486         if (!win)
487            return;
488
489         TextDraw(tc, win, None, 0, 0, st, p, x, y, 99999, 99999, 17, 0);
490         EDestroyWin(win);
491      }
492    else if (!strcmp(param2, "query_size"))
493      {
494         int                 w, h;
495
496         /* 3-:txt */
497
498         if (l == 0)
499            return;
500
501         w = h = 0;
502         TextSize(tc, 0, 0, STATE_NORMAL, p, &w, &h, 17);
503         IpcPrintf("%i %i\n", w, h);
504      }
505    else if (!strcmp(param2, "query"))
506      {
507         IpcPrintf("TextClass %s found\n", tc->name);
508      }
509    else if (!strcmp(param2, "ref_count"))
510      {
511         IpcPrintf("%u references remain\n", tc->ref_count);
512      }
513    else
514      {
515         IpcPrintf("Error: unknown operation specified\n");
516      }
517 }
518
519 static const IpcItem TextclassIpcArray[] = {
520    {
521     TextclassIpc,
522     "textclass", "tc",
523     "List textclasses, apply a textclass",
524     NULL}
525    ,
526 };
527 #define N_IPC_FUNCS (sizeof(TextclassIpcArray)/sizeof(IpcItem))
528
529 /*
530  * Module descriptor
531  */
532 extern const EModule ModTextclass;
533 const EModule       ModTextclass = {
534    "textclass", "tc",
535    NULL,
536    {N_IPC_FUNCS, TextclassIpcArray}
537    ,
538    {0, NULL}
539 };