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 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? */
95 short ul
:3; /* how "nested"... up to 8 levels deep */
96 short comment
:1; /* ignore text till --> */
104 getArg(char *t
, short type
, void *arg
)
107 while(*(++t
) && !d
) {
109 if(*t
>='0' && *t
<='9') {
110 sscanf(t
, "%d", arg
);
111 while(*t
&& (*t
<'0' || *t
>'9'))
120 void parseToken(WMText
*tPtr
, char *token
, short tk
)
122 short mode
=0; /* 0 starts, 1 closes */
124 int prepend
= WMGetTextInsertType(tPtr
);
126 while(*token
&& isspace(*(token
))) token
++;
130 while(isspace(*(token
))) token
++;
133 if(strlen(token
)==1) {
134 /* nice and fast for small tokens... no need for too much brain
136 switch(TOLOWER(*token
)) {
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
);
144 WMDeleteFromBag(cfmt
.fonts
, count
-1);
145 cfmt
.cfont
= (WMFont
*)WMGetFromBag(cfmt
.fonts
,
146 WMGetBagItemCount(cfmt
.fonts
)-1);
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
);
155 WMDeleteFromBag(cfmt
.fonts
, count
-1);
156 cfmt
.cfont
= (WMFont
*)WMGetFromBag(cfmt
.fonts
,
157 WMGetBagItemCount(cfmt
.fonts
)-1);
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);
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")) {
173 else if(mystrcasecmp(token
, "ul")) {
175 if(cfmt
.ul
>1) 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")) {
183 //change margins... create a new margin....
184 //(cfmt.fmargin, cfmt.bmargin,
185 } else if(mystrcasecmp(token
, "align"))
187 else if(mystrcasecmp(token
, "img")) {
192 while(isspace(*(token
))) token
++;
194 switch(TOLOWER(*token
)) {
196 if(TOLOWER(*(1+token
)) == 'r' && TOLOWER(*(2+token
)) == 'c') {
197 mark
= strchr(token
, '=');
199 char img
[256], *iptr
;
202 sscanf(token
, "%s", img
);
204 if(*img
== '\"') { img
[strlen(img
)-1] = 0; iptr
++;}
205 pixmap
= WMCreatePixmapFromFile(scr
, iptr
);
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
);
214 printf("[%s]\n", iptr
);
215 } } break; } } while(*(token
++));
217 } else if(mystrcasecmp(token
, "font")) {
220 cfmt
.cfont
= (WMFont
*)WMGetFromBag(cfmt
.fonts
,
221 WMGetBagItemCount(cfmt
.fonts
)-1);
223 (WMColor
*)WMGetFromBag(cfmt
.colors
,
224 WMGetBagItemCount(cfmt
.colors
)-1),
227 else if(mystrcasecmp(token
, "center")) {
229 if(mode
) cfmt
.align
= WALeft
;
230 else cfmt
.align
= WACenter
;
239 //printf("parse token (%s)[%s]\n", mode?"close":"open", token);
242 //while(*token && !isspace(*(token))) token++;
243 //printf("A:%d a:%d z%d Z%d\n", '1', 'a', 'Z', 'z');
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
);}
252 } else { minor
[i
] = 0; i
=0; printf(" minor: [%s] ", minor
);}
254 }while((c
= *(++token
)));
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
;
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];
273 short tk
=0, textlen
=0;
279 cfmt
.type
= WMGetTextInsertType(tPtr
);
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;
289 cfmt
.fmargin
= cfmt
.bmargin
= 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
);
308 while( (c
=*(stream
++))) {
310 if(c
== '\n' || c
=='\t')
311 //c = ' '; //continue;
319 if(c
== '<' && !mode
) {
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
);
328 //printf("%s\n", text);
331 } else if(c
== '>' && mode
) {
333 if(tk
>0) parseToken(tPtr
, token
, tk
);
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
);}
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
);
361 /* ================= the driver ================== */
366 buttonPressCB(WMWidget
*w
, void *client
)
368 WMText
*tPtr
= (WMText
*)client
;
369 WMAppendTextStream(tPtr
, NULL
);
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
)
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 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
);
414 WMShowTextRuler(text
, True
);
415 WMSetTextUseFixedPitchFont(text
, False
);
416 WMSetTextHasRuler(text
, True
);
417 WMSetTextHasVerticalScroller(text
, True
);
418 //WMSetTextHasHorizontalScroller(text, True);
422 //margins = WMGetTextRulerMargins(text);
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.\
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
);
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 \
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
);