WMSetTextSeelctionFont/Color
[wmaker-crm.git] / WINGs / testtext.c
blob083f359e7e615494b358637da69d67b2936591f8
1 #include "WINGs.h"
2 #include <stdio.h>
5 WMScreen *scr;
7 void
8 wAbort()
10 exit(0);
14 void Close(WMWidget *self, void *client)
16 exit(0);
19 extern WMFont * WMGetFontPlain(WMScreen *scrPtr, WMFont *font);
21 extern WMFont * WMGetFontBold(WMScreen *scrPtr, WMFont *font);
23 extern WMFont * WMGetFontItalic(WMScreen *scrPtr, WMFont *font);
25 extern WMFont * WMGetFontOfSize(WMScreen *scrPtr, WMFont *font, int size);
30 /* =============== a rudimentary HTML parser ======================= */
32 /* due to the WMSetTextParser stuff, it should not
33 be too hard to add parsers. like dis :-] */
37 * A hack to speed up caseless_equal. Thanks to Quincey Koziol for
38 * developing it for the "chimera" folks so I could use it 7 years later ;-)
39 * Constraint: nothing but '\0' may map to 0
41 unsigned char map_table[256] =
43 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
44 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
45 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
46 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
47 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
48 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92,
49 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
50 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
51 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
52 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
53 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
54 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
55 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
56 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
57 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
58 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
59 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
60 248, 249, 250, 251, 252, 253, 254, 255};
62 #define TOLOWER(x) (map_table[(int)x])
63 static int
64 mystrcasecmp(const unsigned char *s1, const unsigned char *s2)
66 if (!*s1 || !*s2) return 0;
67 while (*s2 != '\0') {
68 if (TOLOWER (*s1) != TOLOWER (*s2)) /* true if *s1 == 0 ! */
69 return 0;
70 s1++;
71 s2++;
73 return (*s1=='\0' ||!isalnum(*s1))?1:0;
77 typedef struct _currentFormat {
78 WMBag *fonts;
79 WMBag *colors;
80 WMColor *ccolor;
81 WMFont *cfont;
82 //WMBag *aligns; // for tables...
83 /* the following are "nested"
84 i.e.: <b><b><i></b><b></i>
85 1 2 1 1 2 0 get it? */
86 short i;
87 short b;
88 short u;
89 short fmargin;
90 short bmargin;
91 WMAlignment align:2;
92 short type:1;
93 short ul:3; /* how "nested"... up to 8 levels deep */
94 short comment:1; /* ignore text till --> */
95 short RESERVED:10;
96 } CFMT;
97 CFMT cfmt;
101 #if 0
102 getArg(char *t, short type, void *arg)
104 short d=0;
105 while(*(++t) && !d) {
106 if(type==0) {
107 if(*t>='0' && *t<='9') {
108 sscanf(t, "%d", arg);
109 while(*t&& (*t<'0' || *t>'9'))
110 t++;
111 d=1;
116 #endif
118 void parseToken(WMText *tPtr, char *token, short tk)
120 short mode=0; /* 0 starts, 1 closes */
121 int first = True;
122 void *tb= NULL;
123 int prepend = WMGetTextInsertType(tPtr);
125 while(*token && isspace(*(token))) token++;
126 if(*token == '/') {
127 token++;
128 mode = 1;
129 while(isspace(*(token))) token++;
132 if(strlen(token)==1) {
133 /* nice and fast for small tokens... no need for too much brain
134 power here */
135 switch(TOLOWER(*token)) {
136 case 'i':
137 if(!mode) {
138 cfmt.cfont = WMGetFontItalic(scr, cfmt.cfont);
139 WMPutInBag(cfmt.fonts, (void *)cfmt.cfont);
140 } else { /*dun wanna remove the baseFont eh? */
141 int count = WMGetBagItemCount(cfmt.fonts);
142 if(count>1)
143 WMDeleteFromBag(cfmt.fonts, count-1);
144 cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts,
145 WMGetBagItemCount(cfmt.fonts)-1);
146 } break;
147 case 'b':
148 if(!mode) {
149 cfmt.cfont = WMGetFontBold(scr, cfmt.cfont);
150 WMPutInBag(cfmt.fonts, (void *)cfmt.cfont);
151 } else { /*dun wanna remove the baseFont eh? */
152 int count = WMGetBagItemCount(cfmt.fonts);
153 if(count>1)
154 WMDeleteFromBag(cfmt.fonts, count-1);
155 cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts,
156 WMGetBagItemCount(cfmt.fonts)-1);
157 } break;
158 case 'p':
159 first = True;
160 tb = WMCreateTextBlockWithText(NULL, cfmt.cfont,
161 cfmt.ccolor, first, 0);
162 WMSetTextBlockProperties(tb, first, False, (cfmt.u?1:0), 0, 0);
163 WMAppendTextBlock(tPtr, tb);
164 break;
165 case 'u': cfmt.u = !mode; break;
167 } else { /* the <HTML> tag is, as far as I'm concerned, useless */
168 if(mystrcasecmp(token, "br")) {
169 first = True;
171 else if(mystrcasecmp(token, "ul")) {
172 if(mode) {
173 if(cfmt.ul>1) cfmt.ul--;
174 } else cfmt.ul++;
175 if(cfmt.ul) {
176 cfmt.bmargin = cfmt.ul*30;
177 cfmt.fmargin = cfmt.bmargin-10;
178 } else cfmt.fmargin = cfmt.bmargin = 0;
179 } else if(mystrcasecmp(token, "li")) {
180 first = True;
181 //change margins... create a new margin....
182 //(cfmt.fmargin, cfmt.bmargin,
183 } else if(mystrcasecmp(token, "align"))
184 ;//printf("align");
185 else if(mystrcasecmp(token, "img")) {
186 if(!mode) {
187 char *mark=NULL;
188 WMPixmap *pixmap;
189 WMLabel *l;
190 token+=3;
191 while(isspace(*(token))) token++;
192 do {
193 switch(TOLOWER(*token)) {
194 case 's':
195 if(TOLOWER(*(1+token)) == 'r' && TOLOWER(*(2+token)) == 'c') {
196 mark = strchr(token, '=');
197 if(mark) {
198 char img[256], *iptr;
199 token = mark+1;
200 if(!token) return;
201 sscanf(token, "%s", img);
202 iptr = img;
203 if(*img == '\"') { img[strlen(img)-1] = 0; iptr++;}
204 pixmap = WMCreatePixmapFromFile(scr, iptr);
205 if(pixmap) {
206 l = WMCreateLabel(tPtr);
207 WMResizeWidget(l, 48, 48);
208 WMSetLabelRelief(l, WRFlat);
209 WMSetLabelImagePosition(l, WIPImageOnly);
210 WMSetLabelImage(l, pixmap);
211 tb = WMCreateTextBlockWithObject(l,
212 iptr, cfmt.ccolor, first, 0);
213 WMSetTextBlockProperties(tb, first,
214 False, (cfmt.u?1:0), 0, 0);
215 WMAppendTextBlock(tPtr, tb);
217 printf("[%s]\n", iptr);
218 } } break; } } while(*(token++));
220 } else if(mystrcasecmp(token, "font")) {
221 #if 0
222 if(mode) {
223 cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts,
224 WMGetBagItemCount(cfmt.fonts)-1);
225 } else
226 (WMColor *)WMGetFromBag(cfmt.colors,
227 WMGetBagItemCount(cfmt.colors)-1),
228 #endif
230 else if(mystrcasecmp(token, "center")) {
231 printf("center\n");
232 if(mode) cfmt.align = WALeft;
233 else cfmt.align = WACenter;
234 first = True;
235 //change margins...
242 //printf("parse token (%s)[%s]\n", mode?"close":"open", token);
243 #if 0
244 i=0;
245 //while(*token && !isspace(*(token))) token++;
246 //printf("A:%d a:%d z%d Z%d\n", '1', 'a', 'Z', 'z');
247 do {
248 if(!mm) {
249 if(c>=65 && c<=122) { major[i++] = c;
250 } else if(c==' ' || c=='='){ major[i] = 0; i=0; mm=1;
251 printf("\nmajor: [%s]", major);}
252 } else {
253 if(c!=' ') {
254 minor[i++] = c;
255 } else { minor[i] = 0; i=0; printf(" minor: [%s] ", minor);}
257 }while((c = *(++token)));
258 #endif
261 //printf("parse token (%s)[%s]\n", mode?"close":"open", token);
264 void HTMLParser(WMWidget *w, void *clientData)
266 static short init=1; /* have we been here at least once before? */
267 char *stream = (char *) clientData;
268 WMText *tPtr = (WMText *)w;
269 void *tb = NULL;
270 char c;
271 #define MAX_TOKEN_SIZE 255
272 char token[MAX_TOKEN_SIZE+1];
273 #define MAX_TEXT_SIZE 1023
274 char text[MAX_TEXT_SIZE+1];
275 short mode=0;
276 short tk=0, textlen=0;
277 short wasspace=0;
278 int first = False;
280 if(!tPtr || !stream)
281 return;
283 cfmt.type = WMGetTextInsertType(tPtr);
284 if(1||init) {
285 cfmt.fonts = WMCreateBag(4); /* there sould always be at least 1 font... */
286 cfmt.cfont = WMGetTextDefaultFont(tPtr);
287 WMPutInBag(cfmt.fonts, (void *)cfmt.cfont);
288 cfmt.colors = WMCreateBag(4);
289 cfmt.ccolor = WMBlackColor(scr);
290 WMPutInBag(cfmt.colors, (void *)cfmt.ccolor);
291 cfmt.i = cfmt.b = cfmt.u = cfmt.ul = 0;
292 cfmt.align = WALeft;
293 cfmt.fmargin = cfmt.bmargin = 0;
294 init = 0;
297 #if 0
298 if(strlen(stream) == 1 && stream[0] == '\n') {
299 /* sometimes if the text entered is a single char AND is a newline,
300 the user prolly typed it */
301 cfmt.para = (cfmt.actions.createParagraph) (cfmt.fmargin, cfmt.bmargin,
302 WMWidgetWidth(tPtr)-30, NULL, 0, cfmt.align);
303 (cfmt.actions.insertParagraph) (tPtr, cfmt.para, cfmt.type);
304 return;
306 #endif
312 while( (c=*(stream++))) {
313 //printf("%c", c);
314 if(c == '\n' || c =='\t')
315 //c = ' '; //continue;
316 continue;
317 if(c == ' ') {
318 if(wasspace)
319 continue;
320 wasspace = 1;
321 }else wasspace = 0;
323 if(c == '<' && !mode) {
324 mode=1;
325 if(textlen>0) {
326 text[textlen] = 0;
327 tb = WMCreateTextBlockWithText(text, cfmt.cfont,
328 cfmt.ccolor, first, textlen);
329 WMSetTextBlockProperties(tb, first, False, (cfmt.u?1:0), 0, 0);
330 WMAppendTextBlock(tPtr, tb);
331 //printf("%s\n", text);
333 textlen = 0;
334 } else if(c == '>' && mode) {
335 token[tk] = 0;
336 if(tk>0) parseToken(tPtr, token, tk);
337 mode=0;
338 tk=0;
339 } else {
340 if(mode) {
341 if(tk < MAX_TOKEN_SIZE) token[tk++] = c;
342 } else if(textlen < MAX_TEXT_SIZE) text[textlen++] = c;
346 if(tk>0) { token[tk] = 0; parseToken(tPtr, token, tk);}
347 if(textlen>0) {
348 text[textlen] = 0;
349 //printf("%s\n", text);
350 tb = WMCreateTextBlockWithText(text,
351 (WMFont *)WMGetFromBag(cfmt.fonts,
352 WMGetBagItemCount(cfmt.fonts)-1),
353 (WMColor *)WMGetFromBag(cfmt.colors,
354 WMGetBagItemCount(cfmt.colors)-1),
355 first, textlen);
356 WMSetTextBlockProperties(tb, first, False, (cfmt.u?1:0), 0, 0);
357 WMAppendTextBlock(tPtr, tb);
363 /* ================= the driver ================== */
365 static void
366 buttonPressCB(WMWidget *w, void *client)
368 WMText *tPtr = (WMText *)client;
369 WMAppendTextStream(tPtr, NULL);
370 WMAppendTextStream(tPtr,
371 "<p><b>You</b> just <i>had</i> to press that button, didn't you? "
372 "Well, this sort of thing is bound to happen when you go about "
373 " pressing buttons :-)"
374 "<p><p>Cheers, <p><p><u>Nwanua</u>");
375 WMRefreshText(tPtr, 0, 0);
379 main(int argc, char **argv)
381 Display *dpy;
382 WMWidget *win;
383 WMText *text;
384 WMRulerMargins margins;
385 void *tb = NULL;
387 printf("copy and paste this string: \n
388 here is some <b> bold <i>italic <u>underlined</u> </i> </b> text :-) \n");
390 WMInitializeApplication("WMText", &argc, argv);
391 dpy = XOpenDisplay(NULL);
392 if(!dpy) { printf("no display? *sniff* :~( "); exit(1);}
394 scr = WMCreateSimpleApplicationScreen(dpy);
396 win = WMCreateWindow(scr, "WMText Test");
397 WMRealizeWidget(win);
398 WMResizeWidget(win, 500, 300);
399 //WMResizeWidget(win, 900, 600);
400 WMSetWindowTitle(win,"WMText Test");
401 WMSetWindowCloseAction(win, Close, NULL);
403 text = WMCreateText(win);
404 WMRealizeWidget(text);
405 //WMSetTextHasHorizontalScroller(text, True);
406 WMResizeWidget(text, 480, 280);
407 WMMoveWidget(text, 10, 10);
408 WMSetTextRelief(text, WRSunken);
409 WMSetTextHasVerticalScroller(text, True);
410 WMSetTextUseMonoFont(text, !True);
411 WMSetTextParser(text, HTMLParser);
412 #if 0
413 WMSetTextUseFixedPitchFont(text, False);
414 WMSetTextHasRuler(text, True);
415 WMShowTextRuler(text, True);
416 WMSetTextHasVerticalScroller(text, True);
417 //WMSetTextHasHorizontalScroller(text, True);
418 WMSetTextEditable(text, True);
419 WMFreezeText(text);
420 #endif
422 //margins = WMGetTextRulerMargins(text);
425 #if 1
428 WMAppendTextStream(text,
429 "<p><img src=logo.xpm></i> \
430 <b><i>WINGs</b></i> is a <i>small</i> widget set with \
431 a <u>very</u> nice look and feel. Its API is <i>inspired</i> \
432 and its implementation borrows some ideas from interesting places.\
433 <p><p>
434 The library is limited and its design is a little sloppy, \
435 so it's not intended to build large or complex applications, just
436 <i>small</i> and complex ones. <b>:-)</b>\
437 <p><p> Apart from the usual buttons and labels, it has some \
438 interesting widgets like this list widget: ");
441 WMList *list = WMCreateList(text);
442 char t[20];
443 int i;
445 WMResizeWidget(list, 60, 60);
446 for (i=0; i<7; i++) {
447 sprintf(t, "Item %i", i);
448 WMAddListItem(list, t);
451 tb = WMCreateTextBlockWithObject(list, "{a list object or somesuch}",
452 WMBlackColor(scr), False, 0);
453 WMAppendTextBlock(text, tb);
458 WMAppendTextStream(text, " a colour well such as this one: ");
460 WMColorWell *well;
461 well = WMCreateColorWell(text);
462 WMResizeWidget(well, 60, 40);
463 WMSetColorWellColor(well,
464 WMCreateRGBColor(scr, 0, 0, 0x8888, True));
465 tb = WMCreateTextBlockWithObject(well, "{a button object}",
466 WMBlackColor(scr), False, 0);
467 WMAppendTextBlock(text, tb);
470 WMAppendTextStream(text,
471 ", as well as a text widget: ");
474 WMText *te = WMCreateText(text);
475 WMRealizeWidget(te);
476 WMResizeWidget(te, 120, 90);
477 WMSetTextParser(te, HTMLParser);
478 WMSetTextRelief(te, WRFlat);
479 // WMSetTextBackgroundColor(te, WMCreateNamedColor(scr, "Red", False));
480 WMSetTextDefaultFont(te, WMSystemFontOfSize(scr, 10));
481 WMAppendTextStream(te, "into which you can easily embed other "
482 "<i><b>WINGs</b></i> objects (such as this one), "
483 " without breaking a sweat (type in here)");
484 tb = WMCreateTextBlockWithObject(te, "{a text object}",
485 WMBlackColor(scr), False, 0);
486 WMAppendTextBlock(text, tb);
487 WMSetTextHasVerticalScroller(te, False);
488 WMRefreshText(te, 0, 0);
492 WMText *te = WMCreateText(text);
493 WMRealizeWidget(te);
494 WMResizeWidget(te, 120, 90);
495 WMSetTextParser(te, HTMLParser);
496 WMSetTextRelief(te, WRFlat);
497 // WMSetTextBackgroundColor(te, WMCreateNamedColor(scr, "Red", False));
498 WMSetTextDefaultFont(te, WMSystemFontOfSize(scr, 10));
499 WMAppendTextStream(te, "I always wanted to be able to have "
500 "a <i>multi-column</i> text editor in Unix for my reports, "
501 " now all I have to do is wait for <u>someone</u> to code it :-P");
502 tb = WMCreateTextBlockWithObject(te, "{a text object}",
503 WMBlackColor(scr), False, 0);
504 WMAppendTextBlock(text, tb);
505 WMSetTextHasVerticalScroller(te, False);
506 WMRefreshText(te, 0, 0);
513 WMAppendTextStream(text,
514 " .<p><p> Not bad eh? \
515 <p><p> Since <i><b>WINGs</b></i> is \
516 written in C and is sort of \
517 low-level, it is \
518 small and faster than say, Motif or even Athena (just you try
519 embedding and clicking on buttons");
522 WMButton *b = WMCreateCommandButton(text);
523 WMSetButtonText(b, "like me");
524 WMSetButtonAction(b, buttonPressCB, text);
525 WMResizeWidget(b, 60, 15);
526 tb = WMCreateTextBlockWithObject(b, "{a button object}",
527 WMBlackColor(scr), False, 0);
528 WMAppendTextBlock(text, tb);
531 WMAppendTextStream(text,
532 " with those other tool-kits :-). <p><p>Knowing Xlib will help you to \
533 workaround some of its limitations, although you'll probably be able to \
534 write something like a trivial tic-tac-toe game ");
537 WMTextField *t = WMCreateTextField(text);
538 WMInsertTextFieldText(t, "or an interesting text editor", 0);
539 WMResizeWidget(t, 160, 20);
540 WMSetTextFieldBordered(t, True);
541 WMSetTextFieldBeveled(t, True);
542 tb = WMCreateTextBlockWithObject(t, "{a textfield object}",
543 WMGrayColor(scr), False, 0);
544 WMAppendTextBlock(text, tb);
548 WMAppendTextStream(text, " without knowing much Xlib. "
549 "<p><p>(BTW, don't <i>press</i> that button that is <u>screeming</u>"
550 " to be pressed!");
551 #endif
555 // WMThawText(text);
556 WMRefreshText(text, 0, 0);
559 WMAddNotificationObserver(NotificationObserver, win,
560 WMViewSizeDidChangeNotification, WMWidgetView(win));
562 WMSetViewNotifySizeChanges(WMWidgetView(win), True);
563 WMMapSubwidgets(win);
564 WMMapWidget(win);
566 WMScreenMainLoop(scr);
567 return 0;