Text Selection 99% complete, replaceSelection added
[wmaker-crm.git] / WINGs / testtext.c
blob76b0acee53d4da79709ac82ee2dde16aadbd7118
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 WMRulerMargins margins;
83 //WMBag *aligns; // for tables...
84 /* the following are "nested"
85 i.e.: <b><b><i></b><b></i>
86 1 2 1 1 2 0 get it? */
87 short i;
88 short b;
89 short u;
90 short fmargin;
91 short bmargin;
92 short first:1;
93 short type:1;
94 WMAlignment align:2;
95 short ul:3; /* how "nested"... up to 8 levels deep */
96 short comment:1; /* ignore text till --> */
97 short RESERVED:10;
98 } CFMT;
99 CFMT cfmt;
103 #if 0
104 getArg(char *t, short type, void *arg)
106 short d=0;
107 while(*(++t) && !d) {
108 if(type==0) {
109 if(*t>='0' && *t<='9') {
110 sscanf(t, "%d", arg);
111 while(*t&& (*t<'0' || *t>'9'))
112 t++;
113 d=1;
118 #endif
120 void parseToken(WMText *tPtr, char *token, short tk)
122 short mode=0; /* 0 starts, 1 closes */
123 void *tb= NULL;
124 int prepend = WMGetTextInsertType(tPtr);
126 while(*token && isspace(*(token))) token++;
127 if(*token == '/') {
128 token++;
129 mode = 1;
130 while(isspace(*(token))) token++;
133 if(strlen(token)==1) {
134 /* nice and fast for small tokens... no need for too much brain
135 power here */
136 switch(TOLOWER(*token)) {
137 case 'i':
138 if(!mode) {
139 cfmt.cfont = WMGetFontItalic(scr, cfmt.cfont);
140 WMPutInBag(cfmt.fonts, (void *)cfmt.cfont);
141 } else { /*dun wanna remove the baseFont eh? */
142 int count = WMGetBagItemCount(cfmt.fonts);
143 if(count>1)
144 WMDeleteFromBag(cfmt.fonts, count-1);
145 cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts,
146 WMGetBagItemCount(cfmt.fonts)-1);
147 } break;
148 case 'b':
149 if(!mode) {
150 cfmt.cfont = WMGetFontBold(scr, cfmt.cfont);
151 WMPutInBag(cfmt.fonts, (void *)cfmt.cfont);
152 } else { /*dun wanna remove the baseFont eh? */
153 int count = WMGetBagItemCount(cfmt.fonts);
154 if(count>1)
155 WMDeleteFromBag(cfmt.fonts, count-1);
156 cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts,
157 WMGetBagItemCount(cfmt.fonts)-1);
158 } break;
159 case 'p':
160 cfmt.first = True;
161 tb = WMCreateTextBlockWithText(NULL, cfmt.cfont,
162 cfmt.ccolor, cfmt.first, 0);
163 WMSetTextBlockProperties(tb, cfmt.first, False, (cfmt.u?1:0), 0, cfmt.margins);
164 //WMAppendTextBlock(tPtr, tb);
165 cfmt.first = False;
166 break;
167 case 'u': cfmt.u = !mode; break;
169 } else { /* the <HTML> tag is, as far as I'm concerned, useless */
170 if(mystrcasecmp(token, "br")) {
171 cfmt.first = True;
173 else if(mystrcasecmp(token, "ul")) {
174 if(mode) {
175 if(cfmt.ul>1) cfmt.ul--;
176 } else cfmt.ul++;
177 if(cfmt.ul) {
178 cfmt.bmargin = cfmt.ul*30;
179 cfmt.fmargin = cfmt.bmargin-10;
180 } else cfmt.fmargin = cfmt.bmargin = 0;
181 } else if(mystrcasecmp(token, "li")) {
182 cfmt.first = True;
183 //change margins... create a new margin....
184 //(cfmt.fmargin, cfmt.bmargin,
185 } else if(mystrcasecmp(token, "align"))
186 ;//printf("align");
187 else if(mystrcasecmp(token, "img")) {
188 if(!mode) {
189 char *mark=NULL;
190 WMPixmap *pixmap;
191 token+=3;
192 while(isspace(*(token))) token++;
193 do {
194 switch(TOLOWER(*token)) {
195 case 's':
196 if(TOLOWER(*(1+token)) == 'r' && TOLOWER(*(2+token)) == 'c') {
197 mark = strchr(token, '=');
198 if(mark) {
199 char img[256], *iptr;
200 token = mark+1;
201 if(!token) return;
202 sscanf(token, "%s", img);
203 iptr = img;
204 if(*img == '\"') { img[strlen(img)-1] = 0; iptr++;}
205 pixmap = WMCreatePixmapFromFile(scr, iptr);
206 if(pixmap) {
207 tb = WMCreateTextBlockWithPixmap(pixmap,
208 iptr, cfmt.ccolor, cfmt.first, 0);
209 WMSetTextBlockProperties(tb, cfmt.first,
210 False, (cfmt.u?1:0), 0, cfmt.margins);
211 WMAppendTextBlock(tPtr, tb);
212 cfmt.first = False;
214 printf("[%s]\n", iptr);
215 } } break; } } while(*(token++));
217 } else if(mystrcasecmp(token, "font")) {
218 #if 0
219 if(mode) {
220 cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts,
221 WMGetBagItemCount(cfmt.fonts)-1);
222 } else
223 (WMColor *)WMGetFromBag(cfmt.colors,
224 WMGetBagItemCount(cfmt.colors)-1),
225 #endif
227 else if(mystrcasecmp(token, "center")) {
228 printf("center\n");
229 if(mode) cfmt.align = WALeft;
230 else cfmt.align = WACenter;
231 cfmt.first = True;
232 //change margins...
239 //printf("parse token (%s)[%s]\n", mode?"close":"open", token);
240 #if 0
241 i=0;
242 //while(*token && !isspace(*(token))) token++;
243 //printf("A:%d a:%d z%d Z%d\n", '1', 'a', 'Z', 'z');
244 do {
245 if(!mm) {
246 if(c>=65 && c<=122) { major[i++] = c;
247 } else if(c==' ' || c=='='){ major[i] = 0; i=0; mm=1;
248 printf("\nmajor: [%s]", major);}
249 } else {
250 if(c!=' ') {
251 minor[i++] = c;
252 } else { minor[i] = 0; i=0; printf(" minor: [%s] ", minor);}
254 }while((c = *(++token)));
255 #endif
258 //printf("parse token (%s)[%s]\n", mode?"close":"open", token);
261 void HTMLParser(WMWidget *w, void *clientData)
263 static short init=1; /* have we been here at least once before? */
264 char *stream = (char *) clientData;
265 WMText *tPtr = (WMText *)w;
266 void *tb = NULL;
267 char c;
268 #define MAX_TOKEN_SIZE 255
269 char token[MAX_TOKEN_SIZE+1];
270 #define MAX_TEXT_SIZE 1023
271 char text[MAX_TEXT_SIZE+1];
272 short mode=0;
273 short tk=0, textlen=0;
274 short wasspace=0;
276 if(!tPtr || !stream)
277 return;
279 cfmt.type = WMGetTextInsertType(tPtr);
280 if(1||init) {
281 cfmt.fonts = WMCreateBag(4); /* there sould always be at least 1 font... */
282 cfmt.cfont = WMGetTextDefaultFont(tPtr);
283 WMPutInBag(cfmt.fonts, (void *)cfmt.cfont);
284 cfmt.colors = WMCreateBag(4);
285 cfmt.ccolor = WMBlackColor(scr);
286 WMPutInBag(cfmt.colors, (void *)cfmt.ccolor);
287 cfmt.i = cfmt.b = cfmt.u = cfmt.ul = 0;
288 cfmt.align = WALeft;
289 cfmt.fmargin = cfmt.bmargin = 0;
290 init = 0;
293 #if 0
294 if(strlen(stream) == 1 && stream[0] == '\n') {
295 /* sometimes if the text entered is a single char AND is a newline,
296 the user prolly typed it */
297 cfmt.para = (cfmt.actions.createParagraph) (cfmt.fmargin, cfmt.bmargin,
298 WMWidgetWidth(tPtr)-30, NULL, 0, cfmt.align);
299 (cfmt.actions.insertParagraph) (tPtr, cfmt.para, cfmt.type);
300 return;
302 #endif
308 while( (c=*(stream++))) {
309 //printf("%c", c);
310 if(c == '\n' || c =='\t')
311 //c = ' '; //continue;
312 continue;
313 if(c == ' ') {
314 if(wasspace)
315 continue;
316 wasspace = 1;
317 }else wasspace = 0;
319 if(c == '<' && !mode) {
320 mode=1;
321 if(textlen>0) {
322 text[textlen] = 0;
323 tb = WMCreateTextBlockWithText(text, cfmt.cfont,
324 cfmt.ccolor, cfmt.first, textlen);
325 WMSetTextBlockProperties(tb, cfmt.first, False, (cfmt.u?1:0), 0, cfmt.margins);
326 WMAppendTextBlock(tPtr, tb);
327 cfmt.first = False;
328 //printf("%s\n", text);
330 textlen = 0;
331 } else if(c == '>' && mode) {
332 token[tk] = 0;
333 if(tk>0) parseToken(tPtr, token, tk);
334 mode=0;
335 tk=0;
336 } else {
337 if(mode) {
338 if(tk < MAX_TOKEN_SIZE) token[tk++] = c;
339 } else if(textlen < MAX_TEXT_SIZE) text[textlen++] = c;
343 if(tk>0) { token[tk] = 0; parseToken(tPtr, token, tk);}
344 if(textlen>0) {
345 text[textlen] = 0;
346 //printf("%s\n", text);
347 tb = WMCreateTextBlockWithText(text,
348 (WMFont *)WMGetFromBag(cfmt.fonts,
349 WMGetBagItemCount(cfmt.fonts)-1),
350 (WMColor *)WMGetFromBag(cfmt.colors,
351 WMGetBagItemCount(cfmt.colors)-1),
352 cfmt.first, textlen);
353 WMSetTextBlockProperties(tb, cfmt.first, False, (cfmt.u?1:0), 0, cfmt.margins);
354 WMAppendTextBlock(tPtr, tb);
355 cfmt.first = False;
361 /* ================= the driver ================== */
363 Display *dpy;
365 static void
366 buttonPressCB(WMWidget *w, void *client)
368 WMText *tPtr = (WMText *)client;
369 WMAppendTextStream(tPtr, NULL);
370 XBell(dpy, 0);
371 WMAppendTextStream(tPtr,
372 "<p><b>You</b> just <i>had</i> to press that button, didn't you? "
373 "Well, this sort of thing is bound to happen when you go about "
374 " pressing buttons :-)"
375 "<p><p>Cheers, <p><p><u>Nwanua</u>");
376 WMRefreshText(tPtr, 0, 0);
380 main(int argc, char **argv)
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 WMSetTextHasRuler(text, True);
406 //WMSetTextHasHorizontalScroller(text, True);
407 WMResizeWidget(text, 480, 280);
408 WMMoveWidget(text, 10, 10);
409 WMSetTextRelief(text, WRSunken);
410 WMSetTextHasVerticalScroller(text, True);
411 WMSetTextUsesMonoFont(text, !True);
412 WMSetTextParser(text, HTMLParser);
413 #if 0
414 WMShowTextRuler(text, True);
415 WMSetTextUseFixedPitchFont(text, False);
416 WMSetTextHasRuler(text, True);
417 WMSetTextHasVerticalScroller(text, True);
418 //WMSetTextHasHorizontalScroller(text, True);
419 WMFreezeText(text);
420 #endif
422 //margins = WMGetTextRulerMargins(text);
425 #if 1
428 WMAppendTextStream(text,
429 "README: <p> <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 WMResizeWidget(te, 140, 120);
476 WMSetTextParser(te, HTMLParser);
477 WMSetTextRelief(te, WRFlat);
478 // WMSetTextBackgroundColor(te, WMCreateNamedColor(scr, "Red", False));
479 WMSetTextDefaultFont(te, WMSystemFontOfSize(scr, 10));
480 WMAppendTextStream(te, "into which you can easily embed other "
481 "<i><b>WINGs</b></i> objects (such as this text object), "
482 " as well as pixmaps <img src=upbtn.xpm> (thus) "
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, True);
488 WMSetTextHasHorizontalScroller(te, True);
489 WMRefreshText(te, 0, 0);
493 WMText *te = WMCreateText(text);
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;