14 void Close(WMWidget
*self
, void *client
)
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])
64 mystrcasecmp(const unsigned char *s1
, const unsigned char *s2
)
66 if (!*s1
|| !*s2
) return 0;
68 if (TOLOWER (*s1
) != TOLOWER (*s2
)) /* true if *s1 == 0 ! */
73 return (*s1
=='\0' ||!isalnum(*s1
))?1:0;
77 typedef struct _currentFormat
{
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? */
93 short ul
:3; /* how "nested"... up to 8 levels deep */
94 short comment
:1; /* ignore text till --> */
102 getArg(char *t
, short type
, void *arg
)
105 while(*(++t
) && !d
) {
107 if(*t
>='0' && *t
<='9') {
108 sscanf(t
, "%d", arg
);
109 while(*t
&& (*t
<'0' || *t
>'9'))
118 void parseToken(WMText
*tPtr
, char *token
, short tk
)
120 short mode
=0; /* 0 starts, 1 closes */
123 int prepend
= WMGetTextInsertType(tPtr
);
125 while(*token
&& isspace(*(token
))) token
++;
129 while(isspace(*(token
))) token
++;
132 if(strlen(token
)==1) {
133 /* nice and fast for small tokens... no need for too much brain
135 switch(TOLOWER(*token
)) {
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
);
143 WMDeleteFromBag(cfmt
.fonts
, count
-1);
144 cfmt
.cfont
= (WMFont
*)WMGetFromBag(cfmt
.fonts
,
145 WMGetBagItemCount(cfmt
.fonts
)-1);
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
);
154 WMDeleteFromBag(cfmt
.fonts
, count
-1);
155 cfmt
.cfont
= (WMFont
*)WMGetFromBag(cfmt
.fonts
,
156 WMGetBagItemCount(cfmt
.fonts
)-1);
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
);
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")) {
171 else if(mystrcasecmp(token
, "ul")) {
173 if(cfmt
.ul
>1) 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")) {
181 //change margins... create a new margin....
182 //(cfmt.fmargin, cfmt.bmargin,
183 } else if(mystrcasecmp(token
, "align"))
185 else if(mystrcasecmp(token
, "img")) {
191 while(isspace(*(token
))) token
++;
193 switch(TOLOWER(*token
)) {
195 if(TOLOWER(*(1+token
)) == 'r' && TOLOWER(*(2+token
)) == 'c') {
196 mark
= strchr(token
, '=');
198 char img
[256], *iptr
;
201 sscanf(token
, "%s", img
);
203 if(*img
== '\"') { img
[strlen(img
)-1] = 0; iptr
++;}
204 pixmap
= WMCreatePixmapFromFile(scr
, iptr
);
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")) {
223 cfmt
.cfont
= (WMFont
*)WMGetFromBag(cfmt
.fonts
,
224 WMGetBagItemCount(cfmt
.fonts
)-1);
226 (WMColor
*)WMGetFromBag(cfmt
.colors
,
227 WMGetBagItemCount(cfmt
.colors
)-1),
230 else if(mystrcasecmp(token
, "center")) {
232 if(mode
) cfmt
.align
= WALeft
;
233 else cfmt
.align
= WACenter
;
242 //printf("parse token (%s)[%s]\n", mode?"close":"open", token);
245 //while(*token && !isspace(*(token))) token++;
246 //printf("A:%d a:%d z%d Z%d\n", '1', 'a', 'Z', 'z');
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
);}
255 } else { minor
[i
] = 0; i
=0; printf(" minor: [%s] ", minor
);}
257 }while((c
= *(++token
)));
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
;
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];
276 short tk
=0, textlen
=0;
283 cfmt
.type
= WMGetTextInsertType(tPtr
);
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;
293 cfmt
.fmargin
= cfmt
.bmargin
= 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
);
312 while( (c
=*(stream
++))) {
314 if(c
== '\n' || c
=='\t')
315 //c = ' '; //continue;
323 if(c
== '<' && !mode
) {
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);
334 } else if(c
== '>' && mode
) {
336 if(tk
>0) parseToken(tPtr
, token
, tk
);
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
);}
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),
356 WMSetTextBlockProperties(tb
, first
, False
, (cfmt
.u
?1:0), 0, 0);
357 WMAppendTextBlock(tPtr
, tb
);
363 /* ================= the driver ================== */
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
)
384 WMRulerMargins margins
;
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
);
413 WMSetTextUseFixedPitchFont(text
, False
);
414 WMSetTextHasRuler(text
, True
);
415 WMShowTextRuler(text
, True
);
416 WMSetTextHasVerticalScroller(text
, True
);
417 //WMSetTextHasHorizontalScroller(text, True);
418 WMSetTextEditable(text
, True
);
422 //margins = WMGetTextRulerMargins(text);
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.\
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
);
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: ");
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
);
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
);
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 \
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>"
556 WMRefreshText(text
, 0, 0);
559 WMAddNotificationObserver(NotificationObserver, win,
560 WMViewSizeDidChangeNotification, WMWidgetView(win));
562 WMSetViewNotifySizeChanges(WMWidgetView(win
), True
);
563 WMMapSubwidgets(win
);
566 WMScreenMainLoop(scr
);