First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / utils / xorgcfg / help.c
blobcd5c2c2f4404f17b79d664eeca6a8425985bcdde
1 /*
2 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
22 * Except as contained in this notice, the name of Conectiva Linux shall
23 * not be used in advertising or otherwise to promote the sale, use or other
24 * dealings in this Software without prior written authorization from
25 * Conectiva Linux.
27 * Author: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
31 #include <X11/IntrinsicP.h>
32 #include <X11/StringDefs.h>
33 #include <X11/Shell.h>
34 #include <X11/Xaw/AsciiText.h>
35 #include <X11/Xaw/Command.h>
36 #include <X11/Xaw/Form.h>
37 #include <X11/Xaw/Paned.h>
39 #include <X11/Xaw/Text.h>
40 #include <X11/Xaw/TextSinkP.h>
41 #include <X11/Xaw/TextSrcP.h>
42 #include <X11/Xmu/SysUtil.h>
43 #include <X11/Xmu/Xmu.h>
44 #include <stdlib.h> /* for bsearch() */
45 #include <ctype.h>
46 #include "help.h"
47 #include "options.h"
50 * Prototypes
52 static void CloseCallback(Widget, XtPointer, XtPointer);
53 static void StartHelp(void);
54 void Html_ModeStart(Widget);
57 * Initialization
59 static Widget shell, text;
60 static Bool popped_up = False;
63 * Implementation
65 void
66 Help(char *topic)
68 Widget source;
69 char *str = NULL;
70 Bool error = False;
71 static char *def_text = "<h2>Help Error</h2>"
72 "No help available for the topic <b>%s</b>.";
73 XtResource resource = {
74 NULL, "HelpMessage", XtRString, sizeof(char*),
75 0, XtRString, NULL
78 StartHelp();
79 source = XawTextGetSource(text);
80 XawTextSourceClearEntities(source, 0,
81 XawTextSourceScan(source, 0, XawstAll,
82 XawsdRight, 1, True));
83 if (topic != NULL) {
84 resource.resource_name = topic;
85 XtGetApplicationResources(shell, (XtPointer)&str,
86 &resource, 1, NULL, 0);
88 if (str == NULL) {
89 int len;
91 error = True;
92 if (topic == NULL)
93 topic = "(null argument)";
94 str = XtMalloc(len = strlen(topic) + strlen(def_text) + 1);
95 XmuSnprintf(str, len, def_text, topic);
97 XtVaSetValues(text, XtNstring, str, NULL);
98 if (error)
99 XtFree(str);
101 Html_ModeStart(source);
102 _XawTextBuildLineTable((TextWidget)text,
103 XawTextTopPosition(text), True);
104 XawTextDisplay(text);
105 if (popped_up == False) {
106 popped_up = True;
107 XtPopup(shell, XtGrabNone);
108 XtSetKeyboardFocus(shell, text);
112 static void
113 StartHelp(void)
115 static XtResource resource = {
116 "properties", "Properties", XtRString, sizeof(char*),
117 0, XtRString, NULL
120 if (shell == NULL) {
121 Widget pane, commands, close;
122 char *props;
123 XawTextPropertyList *propl;
125 shell = XtCreatePopupShell("help", transientShellWidgetClass,
126 toplevel, NULL, 0);
127 pane = XtCreateManagedWidget("pane", panedWidgetClass,
128 shell, NULL, 0);
129 text = XtVaCreateManagedWidget("text", asciiTextWidgetClass,
130 pane, XtNeditType, XawtextRead, NULL);
131 commands = XtCreateManagedWidget("commands", formWidgetClass, pane,
132 NULL, 0);
133 close = XtCreateManagedWidget("close", commandWidgetClass,
134 commands, NULL, 0);
135 XtAddCallback(close, XtNcallback, CloseCallback, NULL);
136 XtRealizeWidget(shell);
137 XSetWMProtocols(DPY, XtWindow(shell), &wm_delete_window, 1);
138 XtGetApplicationResources(text, (XtPointer)&props,
139 &resource, 1, NULL, 0);
140 propl = XawTextSinkConvertPropertyList("html", props,
141 toplevel->core.screen,
142 toplevel->core.colormap,
143 toplevel->core.depth);
144 XtVaSetValues(XawTextGetSink(text), XawNtextProperties, propl, NULL);
148 /*ARGSUSED*/
149 static void
150 CloseCallback(Widget w, XtPointer user_data, XtPointer call_data)
152 XtPopdown(shell);
153 popped_up = False;
156 /*ARGSUSED*/
157 void
158 HelpCancelAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
160 CloseCallback(w, NULL, NULL);
164 /* bellow is a modified version of the html-mode.c I wrote for xedit
165 * (at least) temporarily dead.
169 * Copyright (c) 1999 by The XFree86 Project, Inc.
171 * Permission is hereby granted, free of charge, to any person obtaining a
172 * copy of this software and associated documentation files (the "Software"),
173 * to deal in the Software without restriction, including without limitation
174 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
175 * and/or sell copies of the Software, and to permit persons to whom the
176 * Software is furnished to do so, subject to the following conditions:
178 * The above copyright notice and this permission notice shall be included in
179 * all copies or substantial portions of the Software.
181 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
182 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
183 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
184 * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
185 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
186 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
187 * SOFTWARE.
189 * Except as contained in this notice, the name of the XFree86 Project shall
190 * not be used in advertising or otherwise to promote the sale, use or other
191 * dealings in this Software without prior written authorization from the
192 * XFree86 Project.
194 * Author: Paulo César Pereira de Andrade
197 #define Html_Peek(parser) ((parser)->next)
200 * Types
202 typedef struct _Html_Parser Html_Parser;
203 typedef struct _Html_Item Html_Item;
205 typedef struct _Html_TagInfo {
206 char *name;
207 unsigned int entity : 1; /* it changes the type of the text */
208 unsigned int nest : 1; /* does not close tags automatically */
209 unsigned int end : 1; /* need a close markup */
210 unsigned int adnl : 1; /* add newline before/after tag contents */
211 unsigned int para : 1; /* changes the paragraph formatting */
212 unsigned long mask; /* enforce use of attributes of this tag-info */
213 unsigned long xlfd_mask;
214 void (*parse_args)(Html_Parser*, Html_Item*);
215 XawTextProperty *override;
216 XrmQuark ident;
217 } Html_TagInfo;
219 struct _Html_Item {
220 XrmQuark ident;
221 XawTextPosition start, end;
222 Html_TagInfo *info;
224 XawTextProperty *combine;
225 Bool override;
226 int li;
228 XtPointer replace;
230 Html_Item *parent, *child, *next;
233 struct _Html_Parser {
234 Widget source;
235 XawTextBlock block, replace;
236 XawTextPosition position, offset, start, end, last;
237 XrmQuark quark;
238 int i, ch, next;
239 Html_Item *item, *head;
240 XmuScanline *mask;
241 int space, pre, adnl, list, desc, column;
242 Bool spc;
243 XawTextBlock *entity;
245 Pixel alink;
248 typedef struct _Html_SourceInfo Html_SourceInfo;
249 struct _Html_SourceInfo {
250 Widget source;
251 XawTextBlock block;
252 XawTextPosition last;
253 Html_SourceInfo *next;
257 * Proptotypes
259 void Html_ModeEnd(Widget);
260 static void Html_ModeInit(void);
261 static void Html_ParseCallback(Widget, XtPointer, XtPointer);
262 static Html_TagInfo *Html_GetInfo(char*);
263 static int Html_Get(Html_Parser*);
264 static int Html_Parse1(Html_Parser*);
265 static int Html_Parse2(Html_Parser*);
266 static void Html_ParseTag(Html_Parser*);
267 static void Html_Commit(Html_Parser*);
268 static void Html_AddEntities(Html_Parser*, Html_Item*);
270 static int Html_Put(Html_Parser*, int);
271 static void Html_Puts(Html_Parser*, char*);
272 static int Html_Format1(Html_Parser*);
273 static int Html_Format2(Html_Parser*);
274 static int Html_Format3(Html_Parser*);
275 static void Html_FormatTag(Html_Parser*);
277 static void Html_AArgs(Html_Parser*, Html_Item*);
278 static void Html_FontArgs(Html_Parser*, Html_Item*);
281 * Initialization
283 static XrmQuark
284 Qbr,
285 Qdefault,
286 Qdd,
287 Qdl,
288 Qdt,
289 Qentity,
290 Qetag,
291 Qhide,
292 Qli,
293 Qol,
295 Qpre,
296 Qspace,
297 Qtag,
298 Qul;
300 static Html_TagInfo tag_info[] = {
301 {"a", 1, 0, 1, 0, 0,
302 0, 0,
303 Html_AArgs},
304 {"address", 1, 0, 1, 0, 0,
305 0, XAW_TPROP_SLANT,
307 {"b", 1, 0, 1, 0, 0,
308 0, XAW_TPROP_WEIGHT,
310 {"blockquote", 0, 1, 1, 1, 1,
311 0, 0,
313 {"body", 0, 0, 1, 0, 0,
314 0, 0,
316 {"br", 0, 0, 0, 0, 0,
318 {"code", 1, 0, 1, 0, 0,
319 0, XAW_TPROP_FAMILY | XAW_TPROP_PIXELSIZE,
321 {"dd", 0, 1, 1, 0, 1,
322 0, 0},
323 {"dl", 0, 1, 1, 0, 0,
324 0, 0,
326 {"dt", 0, 0, 1, 0, 0,
327 0, 0},
328 {"em", 1, 0, 1, 0, 0,
329 0, XAW_TPROP_SLANT,
331 {"font", 1, 1, 1, 0, 0,
332 0, 0,
333 Html_FontArgs},
334 {"h1", 1, 0, 1, 1, 0,
335 0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
337 {"h2", 1, 0, 1, 1, 0,
338 0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
340 {"h3", 1, 0, 1, 1, 0,
341 0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
343 {"h4", 1, 0, 1, 1, 0,
344 0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
346 {"h5", 1, 0, 1, 1, 0,
347 0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
349 {"h6", 1, 0, 1, 1, 0,
350 0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
352 {"head", 0, 0, 1, 0, 0,
353 0, 0,
355 {"html", 0, 0, 1, 0, 0,
356 0, 0,
358 {"i", 1, 0, 1, 0, 0,
359 0, XAW_TPROP_SLANT,
361 {"kbd", 1, 0, 1, 0, 0,
362 0, XAW_TPROP_FAMILY | XAW_TPROP_PIXELSIZE,
364 {"li", 0, 0, 0, 0, 0,
365 0, 0},
366 {"ol", 0, 1, 1, 0, 1,
367 0, 0,
369 {"p", 0, 0, 0, 1, 0,
371 {"pre", 1, 0, 1, 1, 0,
372 0, XAW_TPROP_FAMILY | XAW_TPROP_PIXELSIZE,
374 {"samp", 1, 0, 1, 0, 0,
375 0, XAW_TPROP_FAMILY | XAW_TPROP_PIXELSIZE,
377 {"strong", 1, 0, 1, 0, 0,
378 0, XAW_TPROP_WEIGHT,
380 {"tt", 1, 0, 1, 0, 0,
381 0, XAW_TPROP_FAMILY | XAW_TPROP_PIXELSIZE,
383 {"ul", 0, 1, 1, 0, 1,
384 0, 0,
388 static char *pnl = "<p>\n", *nlpnl = "\n<p>\n";
389 static Html_SourceInfo *source_info;
392 * Implementation
394 static char *
395 Html_GetText(Widget src, XawTextPosition position)
397 char *result, *tempResult;
398 XawTextPosition offset = 0;
399 XawTextBlock text;
401 tempResult = result = XtMalloc((unsigned)(position + 1));
403 while (offset < position) {
404 offset = XawTextSourceRead(src, offset, &text, position - offset);
405 if (!text.length)
406 break;
407 memcpy(tempResult, text.ptr, (unsigned)text.length);
408 tempResult += text.length;
411 *tempResult = '\0';
413 return (result);
416 void
417 Html_ModeStart(Widget src)
419 Html_Parser *parser = XtNew(Html_Parser);
420 Html_Item *next, *item;
421 XColor color, exact;
422 Html_SourceInfo *info = XtNew(Html_SourceInfo);
424 if (XAllocNamedColor(XtDisplay(toplevel), toplevel->core.colormap,
425 "blue", &color, &exact))
426 parser->alink = color.pixel;
427 else
428 parser->alink = 0L;
430 XtVaSetValues(src, XtNeditType, XawtextEdit, NULL);
432 Html_ModeInit();
434 /* initialize parser state */
435 parser->source = src;
436 parser->position = XawTextSourceRead(parser->source, 0,
437 &parser->block, 4096);
438 parser->replace.ptr = NULL;
439 parser->replace.firstPos = 0;
440 parser->replace.length = 0;
441 parser->replace.format = FMT8BIT;
442 parser->offset = -1;
443 parser->quark = NULLQUARK;
444 parser->i = 0;
445 parser->i = parser->ch = parser->next = 0;
446 parser->last = XawTextSourceScan(src, 0, XawstAll, XawsdRight, 1, 1);
447 if (parser->block.length == 0)
448 parser->ch = parser->next = EOF;
449 else
450 (void)Html_Get(parser);
451 parser->pre = 0;
452 parser->adnl = 1;
453 parser->list = parser->desc = parser->column = 0;
454 parser->spc = True;
456 info->source = src;
457 info->block.ptr = Html_GetText(src, parser->last);
458 info->block.length = parser->last;
459 info->block.format = FMT8BIT;
460 info->block.firstPos = 0;
461 info->next = NULL;
462 if (source_info == NULL)
463 source_info = info;
464 else {
465 Html_SourceInfo *tmp = source_info;
467 while (tmp->next)
468 tmp = tmp->next;
469 tmp->next = info;
472 while (Html_Format1(parser) != EOF)
474 XawTextSourceReplace(parser->source, 0, parser->last, &parser->replace);
475 XtFree(parser->replace.ptr);
477 /* re-initialize parser state */
478 parser->position = XawTextSourceRead(parser->source, 0,
479 &parser->block, 4096);
480 parser->offset = -1;
481 parser->quark = NULLQUARK;
482 parser->i = parser->ch = parser->next = 0;
483 parser->last = XawTextSourceScan(src, 0, XawstAll, XawsdRight, 1, 1);
484 info->last = parser->last;
485 if (parser->block.length == 0)
486 parser->ch = parser->next = EOF;
487 else
488 (void)Html_Get(parser);
489 parser->adnl = 1;
490 parser->list = parser->desc = parser->column = 0;
491 parser->spc = True;
492 parser->head = parser->item = NULL;
494 parser->mask = XmuNewScanline(0, 0, 0);
496 /* build html structure information */
497 while (Html_Parse1(parser) != EOF)
500 /* create top level entity mask */
501 (void)XmuScanlineNot(parser->mask, 0, parser->last);
503 item = parser->item;
504 while (item) {
505 next = item->next;
506 Html_AddEntities(parser, item);
507 if (item->combine)
508 XtFree((XtPointer)item->combine);
509 XtFree((XtPointer)item);
510 item = next;
512 XmuDestroyScanline(parser->mask);
514 XtVaSetValues(src, XtNeditType, XawtextRead, NULL);
516 XtFree((XtPointer)parser);
518 /* add callbacks for interactive changes */
519 XtAddCallback(src, XtNpropertyCallback, Html_ParseCallback, NULL);
522 void
523 Html_ModeEnd(Widget src)
525 Html_SourceInfo *info, *pinfo;
527 XtRemoveCallback(src, XtNpropertyCallback, Html_ParseCallback, NULL);
528 for (pinfo = info = source_info; info; pinfo = info, info = info->next)
529 if (info->source == src)
530 break;
532 if (info == NULL)
533 return;
535 XawTextSourceClearEntities(src, 0, info->last);
536 XtVaSetValues(src, XtNeditType, XawtextEdit, NULL);
537 XawTextSourceReplace(src, 0, info->last, &info->block);
538 XtVaSetValues(src, XtNeditType, XawtextRead, NULL);
540 if (info == source_info)
541 source_info = source_info->next;
542 else
543 pinfo->next = info->next;
544 XtFree(info->block.ptr);
545 XtFree((XtPointer)info);
548 static void
549 Html_ParseCallback(Widget w, XtPointer client_data, XtPointer call_data)
553 static int
554 bcmp_tag_info(_Xconst void *left, _Xconst void *right)
556 return (strcmp((char*)left, ((Html_TagInfo*)right)->name));
559 static Html_TagInfo *
560 Html_GetInfo(char *name)
562 return (bsearch(name, tag_info, sizeof(tag_info) / sizeof(tag_info[0]),
563 sizeof(Html_TagInfo), bcmp_tag_info));
566 static int
567 Html_Get(Html_Parser *parser)
569 if (parser->ch == EOF)
570 return (EOF);
571 if (parser->i >= parser->block.length) {
572 parser->i = 0;
573 parser->position = XawTextSourceRead(parser->source, parser->position,
574 &parser->block, 4096);
576 parser->ch = parser->next;
577 if (parser->block.length == 0)
578 parser->next = EOF;
579 else
580 parser->next = (unsigned char)parser->block.ptr[parser->i++];
581 parser->offset++;
583 return (parser->ch);
586 static void
587 Html_ModeInit(void)
589 static int initialized;
590 int i;
592 if (initialized)
593 return;
595 Qbr = XrmPermStringToQuark("br");
596 Qdd = XrmPermStringToQuark("dd");
597 Qdefault = XrmPermStringToQuark("default");
598 Qdl = XrmPermStringToQuark("dl");
599 Qdt = XrmPermStringToQuark("dt");
600 Qentity = XrmPermStringToQuark("entity");
601 Qetag = XrmPermStringToQuark("/tag");
602 Qhide = XrmPermStringToQuark("hide");
603 Qli = XrmPermStringToQuark("li");
604 Qol = XrmPermStringToQuark("ol");
605 Qp = XrmPermStringToQuark("p");
606 Qpre = XrmPermStringToQuark("pre");
607 Qspace = XrmPermStringToQuark("space");
608 Qtag = XrmPermStringToQuark("tag");
609 Qul = XrmPermStringToQuark("ul");
611 for (i = 0; i < sizeof(tag_info) / sizeof(tag_info[0]); i++)
612 tag_info[i].ident = XrmPermStringToQuark(tag_info[i].name);
614 initialized = True;
617 /************************************************************************/
618 /* PARSE */
619 /************************************************************************/
620 static void
621 Html_AddEntities(Html_Parser *parser, Html_Item *item)
623 Html_Item *parent, *next, *child = item->child;
624 XmuSegment segment, *ent;
625 XmuScanline *mask = XmuNewScanline(0, 0, 0);
626 XawTextProperty *tprop, *property = NULL;
627 Widget sink;
628 Bool changed = False;
630 /* combine properties */
631 if (item->info &&
632 (item->info->entity ||
633 (item->parent && item->parent->ident != item->parent->info->ident))) {
634 sink = XawTextGetSink(text);
635 parent = item->parent;
636 property = XawTextSinkCopyProperty(sink, item->ident);
637 property->mask = item->info->mask;
638 property->xlfd_mask = item->info->xlfd_mask;
639 if (parent) {
640 (void)XawTextSinkCombineProperty(sink, property,
641 XawTextSinkGetProperty(sink, parent->ident), False);
642 if (item->combine && parent->combine)
643 (void)XawTextSinkCombineProperty(sink, item->combine,
644 parent->combine,
645 item->override);
647 if (item->combine)
648 XawTextSinkCombineProperty(sink, property, item->combine, True);
649 tprop = property;
650 property = XawTextSinkAddProperty(sink, property);
651 XtFree((XtPointer)tprop);
652 if (property && item->ident != property->identifier) {
653 item->ident = property->identifier;
654 changed = True;
658 if (item->end < 0) {
659 if (item->next)
660 item->end = item->next->start;
661 else if (item->parent)
662 item->end = item->parent->end;
663 else
664 item->end = parser->last;
667 while (child) {
668 next = child->next;
669 segment.x1 = child->start;
670 segment.x2 = child->end;
671 (void)XmuScanlineOrSegment(mask, &segment);
672 Html_AddEntities(parser, child);
673 if (child->combine)
674 XtFree((XtPointer)child->combine);
675 XtFree((XtPointer)child);
676 child = next;
679 /* build entity mask */
680 (void)XmuScanlineNot(mask, item->start, item->end);
681 (void)XmuScanlineAnd(mask, parser->mask);
683 /* add entities */
684 if (item->info && changed) {
685 for (ent = mask->segment; ent; ent = ent->next)
686 (void)XawTextSourceAddEntity(parser->source, 0, 0, NULL, ent->x1,
687 ent->x2 - ent->x1, item->ident);
689 else if (item->info == NULL)
690 (void)XawTextSourceAddEntity(parser->source, 0,
691 XAW_TENTF_READ | XAW_TENTF_REPLACE,
692 item->replace, item->start,
693 item->end - item->start,
694 item->parent->ident);
696 /* set mask for parent entities */
697 (void)XmuScanlineOr(parser->mask, mask);
698 XmuDestroyScanline(mask);
700 #if 0
701 if (item->info && item->info->para) {
702 XawTextSourceSetParagraph(parser->source, item->start, item->end,
703 40, /* arbitrary value, for testing */
704 0, 0);
706 #endif
709 static void
710 Html_Commit(Html_Parser *parser)
712 XawTextPosition position;
713 int length;
715 position = parser->start;
716 length = parser->end - parser->start;
717 if (position < 0) {
718 length += position;
719 position = 0;
721 if (position + length > parser->last + 1)
722 length -= (position + length) - parser->last + 1;
724 if (parser->quark != Qdefault && parser->quark != NULLQUARK && length > 0) {
725 XmuSegment segment;
726 Html_Item *head = parser->head;
727 XrmQuark quark = parser->quark;
729 parser->quark = Qdefault;
731 if (quark == Qli && head &&
732 (head->info->ident == Qol || head->info->ident == Qul)) {
733 if (parser->head == NULL || head->info->ident != Qol)
734 XawTextSourceAddEntity(parser->source, 0, /*XAW_TENT_BULLET,*/
735 XAW_TENTF_HIDE, NULL,
736 position, length, Qli);
737 else
738 XawTextSourceAddEntity(parser->source, 0, /*XAW_TENT_LITEM,*/
739 XAW_TENTF_HIDE,
740 (XtPointer)(long)head->li++,
741 position, length, Qli);
743 else if (quark == Qhide)
744 XawTextSourceAddEntity(parser->source, 0, XAW_TENTF_HIDE, NULL,
745 position, length, quark);
746 else if (quark == Qentity) {
747 if (head && head->end == -1) {
748 Html_Item *item, *it;
750 item = XtNew(Html_Item);
751 item->ident = Qentity;
752 item->start = position;
753 item->end = position + length;
754 item->info = NULL;
755 item->combine = NULL;
756 item->override = False;
757 item->replace = (XtPointer)parser->entity;
758 item->child = item->next = NULL;
760 it = head->child;
762 item->parent = head;
763 if (it == NULL)
764 head->child = item;
765 else {
766 while (it->next)
767 it = it->next;
768 it->next = item;
771 return;
773 XawTextSourceAddEntity(parser->source, 0,
774 XAW_TENTF_READ | XAW_TENTF_REPLACE,
775 (XtPointer)parser->entity,
776 position, length, Qentity);
779 segment.x1 = position;
780 segment.x2 = position + length;
781 (void)XmuScanlineOrSegment(parser->mask, &segment);
785 static void
786 Html_ParseTag(Html_Parser *parser)
788 int ch, sz;
789 char buf[32];
790 Html_TagInfo *info;
791 Html_Item *item = NULL;
792 XawTextPosition offset = parser->offset - 1;
794 switch (Html_Peek(parser)) {
795 case '!':
796 (void)Html_Get(parser); /* eat `!' */
797 if (Html_Peek(parser) == '-') {
798 /* comment */
799 (void)Html_Get(parser); /* eat `-' */
800 if (Html_Peek(parser) == '-') {
801 int count = 0;
803 (void)Html_Get(parser);
804 while ((ch = Html_Peek(parser)) != EOF) {
805 if (ch == '>' && count >= 2)
806 break;
807 else if (ch == '-')
808 ++count;
809 else
810 count = 0;
811 (void)Html_Get(parser);
815 break;
816 case '?':
817 break;
818 case '/':
819 (void)Html_Get(parser); /* eat `/' */
820 sz = 0;
821 while (isalnum(Html_Peek(parser)) &&
822 ((sz + 1) < sizeof(buf)))
823 buf[sz++] = tolower(Html_Get(parser));
824 buf[sz] = '\0';
825 if ((info = Html_GetInfo(buf)) != NULL) {
826 if (parser->head) {
827 Html_Item *it = parser->head;
829 while (it) {
830 if (it->info == info)
831 break;
832 it = it->parent;
835 if (it) {
836 if (it == parser->head)
837 parser->head->end = offset;
838 else {
839 it->end = offset;
840 do {
841 parser->head->end = offset;
842 parser->head = parser->head->parent;
843 } while (parser->head != it);
845 if (parser->head->parent)
846 parser->head = parser->head->parent;
847 else
848 parser->head = parser->item;
852 break;
853 default:
854 sz = 0;
855 while (isalnum(Html_Peek(parser)) &&
856 ((sz + 1) < sizeof(buf)))
857 buf[sz++] = tolower(Html_Get(parser));
858 buf[sz] = '\0';
859 if ((info = Html_GetInfo(buf)) != NULL) {
860 if (info->end == False) {
861 if (info->ident == Qli)
862 parser->quark = Qli;
863 if (!info->para)
864 break; /* no more processing required */
866 item = XtNew(Html_Item);
867 item->info = info;
868 item->ident = item->info->ident;
869 item->combine = NULL;
870 item->override = False;
871 item->start = item->end = -1;
872 if (info->ident == Qol)
873 item->li = 1;
874 else
875 item->li = 0;
876 item->parent = item->child = item->next = NULL;
877 if (parser->item == NULL)
878 parser->item = parser->head = item;
879 else if (parser->head->end == -1) {
880 if (parser->head->info != item->info || info->nest) {
881 Html_Item *it = parser->head;
883 /* first, see if we need to close a long list of tags */
884 if (info->ident == Qdd) {
885 if (parser->head &&
886 parser->head->info->ident == Qdt) {
887 parser->head->end = offset;
888 parser->head = parser->head->parent;
891 else if (info->ident == Qdt) {
892 if (parser->head &&
893 parser->head->info->ident == Qdd) {
894 parser->head->end = offset;
895 parser->head = parser->head->parent;
898 else if (!info->nest) {
899 while (it) {
900 if (it->info == info || it->info->end)
901 break;
902 it = it->parent;
904 if (it) {
905 /* close the items */
906 while (parser->head != it) {
907 if (parser->head->info->ident == Qpre)
908 --parser->pre;
909 parser->head->end = offset;
910 parser->head = parser->head->parent;
915 /* add child item */
916 it = parser->head->child;
918 item->parent = parser->head;
919 if (it == NULL)
920 parser->head->child = item;
921 else {
922 while (it->next)
923 it = it->next;
924 it->next = item;
926 parser->head = item;
928 else {
929 /* close the `head' item and start a new one */
930 Html_Item *it;
932 parser->head->end = offset;
933 if (parser->head->parent)
934 parser->head = parser->head->parent;
935 else
936 parser->head = parser->item;
938 if ((it = parser->head->child) != NULL) {
939 item->parent = parser->head;
940 while (it->next)
941 it = it->next;
942 it->next = item;
943 parser->head = item;
945 else {
946 parser->head->child = item;
947 parser->head = item;
951 else {
952 /* this is not common, but handle it */
953 Html_Item *it = parser->item;
955 while (it->next)
956 it = it->next;
957 it->next = item;
958 parser->head = item;
960 if (info->parse_args)
961 (info->parse_args)(parser, item);
963 break;
966 /* skip anything not processed */
967 while ((ch = Html_Peek(parser)) != '>' && ch != EOF)
968 (void)Html_Get(parser);
969 if (item && item->start == -1)
970 item->start = parser->offset + 1;
973 /* tags */
974 static int
975 Html_Parse2(Html_Parser *parser)
977 int ch;
979 for (;;) {
980 if ((ch = Html_Get(parser)) == '<') {
981 parser->end = parser->offset - 1;
982 Html_Commit(parser);
983 parser->quark = Qhide;
984 parser->start = parser->end;
986 Html_ParseTag(parser);
988 (void)Html_Get(parser); /* eat `>' */
989 parser->end = parser->offset;
990 Html_Commit(parser);
992 else
993 return (ch);
995 /*NOTREACHED*/
998 /* entities */
999 static int
1000 Html_Parse1(Html_Parser *parser)
1002 static XawTextBlock *entities[256];
1003 static char chars[256];
1004 int ch;
1006 for (;;) {
1007 if ((ch = Html_Parse2(parser)) == EOF)
1008 return (EOF);
1010 if (ch == '&') {
1011 unsigned char idx = '?';
1012 char buf[32];
1013 int sz = 0;
1015 /* the string comparisons need a big optmization! */
1016 parser->end = parser->offset - 1;
1017 Html_Commit(parser);
1018 parser->start = parser->end;
1019 while ((ch = Html_Peek(parser)) != ';'
1020 && ch != EOF && !isspace(ch)) {
1021 ch = Html_Get(parser);
1022 if (sz + 1 < sizeof(buf))
1023 buf[sz++] = ch;
1025 buf[sz] = '\0';
1026 if (ch == ';')
1027 (void)Html_Get(parser);
1028 if (sz == 0)
1029 idx = '&';
1030 else if (strcasecmp(buf, "lt") == 0)
1031 idx = '<';
1032 else if (strcasecmp(buf, "gt") == 0)
1033 idx = '>';
1034 else if (strcasecmp(buf, "nbsp") == 0)
1035 idx = ' ';
1036 else if (strcasecmp(buf, "amp") == 0)
1037 idx = '&';
1038 else if (strcasecmp(buf, "quot") == 0)
1039 idx = '"';
1040 else if (*buf == '#') {
1041 if (sz == 1)
1042 idx = '#';
1043 else {
1044 char *tmp;
1046 idx = strtol(buf + 1, &tmp, 10);
1047 if (*tmp)
1048 idx = '?';
1051 else if (strcmp(buf + 1, "acute") == 0) {
1052 switch (*buf) {
1053 case 'a': idx = 0xe1; break; case 'e': idx = 0xe9; break;
1054 case 'i': idx = 0xed; break; case 'o': idx = 0xf3; break;
1055 case 'u': idx = 0xfa; break; case 'A': idx = 0xc1; break;
1056 case 'E': idx = 0xc9; break; case 'I': idx = 0xcd; break;
1057 case 'O': idx = 0xd3; break; case 'U': idx = 0xda; break;
1058 case 'y': idx = 0xfd; break; case 'Y': idx = 0xdd; break;
1061 else if (strcmp(buf + 1, "grave") == 0) {
1062 switch (*buf) {
1063 case 'a': idx = 0xe0; break; case 'e': idx = 0xe8; break;
1064 case 'i': idx = 0xec; break; case 'o': idx = 0xf2; break;
1065 case 'u': idx = 0xf9; break; case 'A': idx = 0xc0; break;
1066 case 'E': idx = 0xc8; break; case 'I': idx = 0xcc; break;
1067 case 'O': idx = 0xd2; break; case 'U': idx = 0xd9; break;
1070 else if (strcmp(buf + 1, "tilde") == 0) {
1071 switch (*buf) {
1072 case 'a': idx = 0xe3; break; case 'o': idx = 0xf5; break;
1073 case 'n': idx = 0xf1; break; case 'A': idx = 0xc3; break;
1074 case 'O': idx = 0xd5; break; case 'N': idx = 0xd1; break;
1077 else if (strcmp(buf + 1, "circ") == 0) {
1078 switch (*buf) {
1079 case 'a': idx = 0xe2; break; case 'e': idx = 0xea; break;
1080 case 'i': idx = 0xee; break; case 'o': idx = 0xf4; break;
1081 case 'u': idx = 0xfb; break; case 'A': idx = 0xc2; break;
1082 case 'E': idx = 0xca; break; case 'I': idx = 0xce; break;
1083 case 'O': idx = 0xd4; break; case 'U': idx = 0xdb; break;
1086 else if (strcmp(buf + 1, "uml") == 0) {
1087 switch (*buf) {
1088 case 'a': idx = 0xe4; break; case 'e': idx = 0xeb; break;
1089 case 'i': idx = 0xef; break; case 'o': idx = 0xf6; break;
1090 case 'u': idx = 0xfc; break; case 'A': idx = 0xc4; break;
1091 case 'E': idx = 0xcb; break; case 'I': idx = 0xfc; break;
1092 case 'O': idx = 0xd6; break; case 'U': idx = 0xdc; break;
1093 case 'y': idx = 0xff; break;
1096 else if (strcmp(buf + 1, "cedil") == 0) {
1097 switch (*buf) {
1098 case 'c': idx = 0xe7; break; case 'C': idx = 0xc7; break;
1101 else if (strcmp(buf + 1, "slash") == 0) {
1102 switch (*buf) {
1103 case 'o': idx = 0xf8; break; case 'O': idx = 0xd8; break;
1106 else if (strcmp(buf + 1, "ring") == 0) {
1107 switch (*buf) {
1108 case 'a': idx = 0xe5; break; case 'A': idx = 0xc5; break;
1111 else if (strcasecmp(buf, "iexcl") == 0)
1112 idx = 0xa1;
1113 else if (strcasecmp(buf, "cent") == 0)
1114 idx = 0xa2;
1115 else if (strcasecmp(buf, "pound") == 0)
1116 idx = 0xa3;
1117 else if (strcasecmp(buf, "curren") == 0)
1118 idx = 0xa4;
1119 else if (strcasecmp(buf, "yen") == 0)
1120 idx = 0xa5;
1121 else if (strcasecmp(buf, "brvbar") == 0)
1122 idx = 0xa6;
1123 else if (strcasecmp(buf, "sect") == 0)
1124 idx = 0xa7;
1125 else if (strcasecmp(buf, "uml") == 0)
1126 idx = 0xa8;
1127 else if (strcasecmp(buf, "copy") == 0)
1128 idx = 0xa9;
1129 else if (strcasecmp(buf, "ordf") == 0)
1130 idx = 0xaa;
1131 else if (strcasecmp(buf, "laquo") == 0)
1132 idx = 0xab;
1133 else if (strcasecmp(buf, "not") == 0)
1134 idx = 0xac;
1135 else if (strcasecmp(buf, "shy") == 0)
1136 idx = 0xad;
1137 else if (strcasecmp(buf, "reg") == 0)
1138 idx = 0xae;
1139 else if (strcasecmp(buf, "macr") == 0)
1140 idx = 0xaf;
1141 else if (strcasecmp(buf, "deg") == 0)
1142 idx = 0xb0;
1143 else if (strcasecmp(buf, "plusmn") == 0)
1144 idx = 0xb1;
1145 else if (strcasecmp(buf, "sup2") == 0)
1146 idx = 0xb2;
1147 else if (strcasecmp(buf, "sup3") == 0)
1148 idx = 0xb3;
1149 else if (strcasecmp(buf, "acute") == 0)
1150 idx = 0xb4;
1151 else if (strcasecmp(buf, "micro") == 0)
1152 idx = 0xb5;
1153 else if (strcasecmp(buf, "para") == 0)
1154 idx = 0xb6;
1155 else if (strcasecmp(buf, "middot") == 0)
1156 idx = 0xb7;
1157 else if (strcasecmp(buf, "cedil") == 0)
1158 idx = 0xb8;
1159 else if (strcasecmp(buf, "supl") == 0)
1160 idx = 0xb9;
1161 else if (strcasecmp(buf, "ordm") == 0)
1162 idx = 0xba;
1163 else if (strcasecmp(buf, "raquo") == 0)
1164 idx = 0xbb;
1165 else if (strcasecmp(buf, "frac14") == 0)
1166 idx = 0xbc;
1167 else if (strcasecmp(buf, "frac12") == 0)
1168 idx = 0xbd;
1169 else if (strcasecmp(buf, "frac34") == 0)
1170 idx = 0xbe;
1171 else if (strcasecmp(buf, "iquest") == 0)
1172 idx = 0xbf;
1173 else if (strcasecmp(buf, "AElig") == 0)
1174 idx = 0xc6;
1175 else if (strcasecmp(buf, "ETH") == 0)
1176 idx = 0xd0;
1177 else if (strcasecmp(buf, "THORN") == 0)
1178 idx = 0xde;
1179 else if (strcasecmp(buf, "szlig") == 0)
1180 idx = 0xdf;
1181 else if (strcasecmp(buf, "aelig") == 0)
1182 idx = 0xe6;
1183 else if (strcasecmp(buf, "eth") == 0)
1184 idx = 0xf0;
1185 else if (strcasecmp(buf, "thorn") == 0)
1186 idx = 0xfe;
1188 parser->quark = Qentity;
1189 if (entities[idx] == NULL) {
1190 entities[idx] = XtNew(XawTextBlock);
1191 entities[idx]->firstPos = 0;
1192 entities[idx]->length = 1;
1193 entities[idx]->ptr = chars + idx;
1194 entities[idx]->format = FMT8BIT;
1195 chars[idx] = idx;
1197 parser->entity = entities[idx];
1198 parser->end = parser->offset;
1199 Html_Commit(parser);
1200 parser->start = parser->end;
1203 /*NOTREACHED*/
1206 /************************************************************************/
1207 /* FORMAT */
1208 /************************************************************************/
1209 static int
1210 Html_Put(Html_Parser *parser, int ch)
1212 if (ch != '\r') {
1213 if (parser->replace.length % 4096 == 0)
1214 parser->replace.ptr = XtRealloc(parser->replace.ptr,
1215 parser->replace.length + 4096);
1216 parser->replace.ptr[parser->replace.length++] = ch;
1219 return (ch);
1222 static void
1223 Html_Puts(Html_Parser *parser, char *str)
1225 int len = strlen(str);
1227 if (parser->replace.length % 4096 == 0 ||
1228 parser->replace.length + len > parser->replace.length +
1229 (4096 - (parser->replace.length % 4096)))
1230 parser->replace.ptr = XtRealloc(parser->replace.ptr,
1231 parser->replace.length + 4096);
1232 memcpy(parser->replace.ptr + parser->replace.length, str, len);
1233 parser->replace.length += len;
1236 static void
1237 Html_FormatTag(Html_Parser *parser)
1239 int ch = 0, sz = 0;
1240 char buf[32];
1241 Html_TagInfo *info = NULL;
1243 switch (Html_Peek(parser)) {
1244 case '!':
1245 Html_Put(parser, '<');
1246 Html_Put(parser, Html_Get(parser)); /* eat `!' */
1247 if (Html_Peek(parser) == '-') {
1248 /* comment */
1249 Html_Put(parser, Html_Get(parser)); /* eat `-' */
1250 if (Html_Peek(parser) == '-') {
1251 int count = 0;
1253 Html_Put(parser, Html_Get(parser));
1254 while ((ch = Html_Peek(parser)) != EOF) {
1255 if (ch == '>' && count >= 2)
1256 break;
1257 else if (ch == '-')
1258 ++count;
1259 else
1260 count = 0;
1261 Html_Put(parser, Html_Get(parser));
1263 (void)Html_Get(parser); /* eat `>' */
1264 Html_Put(parser, '>');
1265 return;
1268 break;
1269 case '?':
1270 Html_Put(parser, '<');
1271 break;
1272 case '/':
1273 (void)Html_Get(parser); /* eat `/' */
1274 while (isalnum(Html_Peek(parser)) &&
1275 ((sz + 1) < sizeof(buf)))
1276 buf[sz++] = ch = tolower(Html_Get(parser));
1277 buf[sz] = '\0';
1278 if ((info = Html_GetInfo(buf)) != NULL && info->adnl) {
1279 if (info->ident == Qpre && parser->pre) {
1280 if (--parser->pre == 0)
1281 parser->column = 0;
1283 parser->quark = Qetag;
1284 parser->spc = True;
1285 if (info->ident == Qp) {
1286 while ((ch = Html_Peek(parser) != '>' && ch != EOF))
1287 (void)Html_Get(parser);
1288 (void)Html_Get(parser); /* eat '>' */
1289 return;
1292 else if (info) {
1293 if (info->ident == Qol || info->ident == Qul) {
1294 if (parser->list && --parser->list == 0 &&
1295 parser->desc == 0) {
1296 parser->quark = Qetag;
1297 Html_Put(parser, '\n');
1298 ++parser->adnl;
1299 parser->column = 0;
1302 else if (info->ident == Qdl) {
1303 if (parser->desc && --parser->desc == 0 &&
1304 parser->list == 0) {
1305 parser->quark = Qetag;
1306 Html_Put(parser, '\n');
1307 ++parser->adnl;
1308 parser->column = 0;
1312 Html_Puts(parser, "</");
1313 Html_Puts(parser, buf);
1314 break;
1315 default:
1316 while (isalnum(Html_Peek(parser)) &&
1317 ((sz + 1) < sizeof(buf)))
1318 buf[sz++] = tolower(Html_Get(parser));
1319 buf[sz] = '\0';
1320 if ((info = Html_GetInfo(buf)) != NULL && info->adnl) {
1321 if (info->ident == Qpre)
1322 ++parser->pre;
1323 if (parser->quark != Qtag) {
1324 if (parser->adnl < 2) {
1325 Html_Puts(parser, parser->adnl ? pnl : nlpnl);
1326 parser->adnl = 2;
1327 parser->spc = True;
1328 parser->column = 0;
1331 parser->quark = Qtag;
1332 if (info->ident == Qp) {
1333 while ((ch = Html_Peek(parser) != '>' && ch != EOF))
1334 (void)Html_Get(parser);
1335 (void)Html_Get(parser); /* eat '>' */
1336 return;
1339 else if (info) {
1340 if (info->ident == Qol || info->ident == Qul) {
1341 if (++parser->list == 1 && !parser->desc) {
1342 if (parser->adnl < 2) {
1343 Html_Puts(parser, parser->adnl ? pnl : nlpnl);
1344 parser->adnl = 2;
1345 parser->column = 0;
1348 else if (parser->adnl == 0) {
1349 Html_Put(parser, '\n');
1350 parser->adnl = 1;
1351 parser->column = 0;
1353 parser->spc = True;
1355 else if (info->ident == Qli) {
1356 if (parser->adnl == 0) {
1357 Html_Put(parser, '\n');
1358 parser->adnl = 1;
1359 parser->column = 0;
1363 else if (info->ident == Qdl) {
1364 if (++parser->desc == 1 && !parser->list) {
1365 if (parser->adnl < 2) {
1366 Html_Puts(parser, parser->adnl ? pnl : nlpnl);
1367 parser->adnl = 2;
1368 parser->column = 0;
1371 else if (parser->adnl == 0) {
1372 Html_Put(parser, '\n');
1373 parser->adnl = 1;
1374 parser->column = 0;
1376 parser->spc = True;
1378 else if (info->ident == Qdd) {
1379 if (parser->desc == 0) {
1380 if (parser->adnl < 2) {
1381 Html_Puts(parser, parser->adnl ? pnl : nlpnl);
1382 parser->adnl = 2;
1383 parser->column = 0;
1386 else if (parser->adnl == 0) {
1387 Html_Put(parser, '\n');
1388 parser->adnl = 1;
1389 parser->column = 0;
1391 parser->spc = True;
1393 else if (info->ident == Qdt) {
1394 if (parser->adnl == 0) {
1395 Html_Put(parser, '\n');
1396 parser->adnl = 1;
1397 parser->spc = True;
1398 parser->column = 0;
1402 Html_Put(parser, '<');
1403 Html_Puts(parser, buf);
1404 break;
1407 sz = 0;
1408 while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
1409 if (isspace(ch)) {
1410 (void)Html_Get(parser);
1411 ++sz;
1412 continue;
1414 else if (sz) {
1415 Html_Put(parser, ' ');
1416 sz = 0;
1418 Html_Put(parser, Html_Get(parser));
1420 Html_Put(parser, Html_Get(parser)); /* eat `>' */
1421 if (info && info->ident == Qbr) {
1422 ++parser->adnl;
1423 parser->spc = True;
1424 Html_Put(parser, '\n');
1425 parser->quark = info->ident;
1426 parser->column = 0;
1430 /* tags */
1431 static int
1432 Html_Format3(Html_Parser *parser)
1434 int ch;
1436 for (;;) {
1437 if ((ch = Html_Get(parser)) == '<') {
1438 if (parser->quark == Qspace && parser->spc == False) {
1439 Html_Put(parser, ' ');
1440 parser->spc = True;
1443 /* parser->quark = Qhide;*/
1444 Html_FormatTag(parser);
1446 else
1447 return (ch);
1449 /*NOTREACHED*/
1452 /* entities */
1453 static int
1454 Html_Format2(Html_Parser *parser)
1456 int ch;
1458 for (ch = Html_Format3(parser); ch == '&'; ch = Html_Format3(parser)) {
1459 Html_Put(parser, '&');
1460 while ((ch = Html_Peek(parser)) != ';') {
1461 if (isspace(ch) || ch == EOF)
1462 break;
1463 Html_Put(parser, Html_Get(parser));
1465 if (ch != EOF)
1466 Html_Put(parser, Html_Get(parser));
1467 else
1468 break;
1469 if (parser->pre)
1470 ++parser->column;
1473 return (ch);
1476 /* spaces */
1477 static int
1478 Html_Format1(Html_Parser *parser)
1480 int ch;
1482 for (;;) {
1483 if ((ch = Html_Format2(parser)) == EOF)
1484 return (ch);
1486 if (parser->quark == Qetag) {
1487 if (parser->adnl < 2) {
1488 Html_Puts(parser, parser->adnl ? pnl : nlpnl);
1489 parser->adnl = 2;
1490 parser->spc = True;
1493 else if (parser->quark == Qspace && parser->spc == False) {
1494 Html_Put(parser, ' ');
1495 parser->spc = True;
1498 if (!parser->pre && isspace(ch))
1499 parser->quark = Qspace;
1500 else {
1501 if (parser->pre) {
1502 if (parser->spc) {
1503 /* did not yet see any non space character */
1504 if (isspace(ch)) {
1505 if (ch == '\n') {
1506 parser->column = 0;
1507 parser->spc = False;
1508 parser->adnl = 1;
1510 else if (ch == '\t')
1511 parser->column += 8 - (parser->column % 8);
1512 else
1513 ++parser->column;
1514 continue;
1516 else {
1517 int column = parser->column;
1519 while (column-- > 0)
1520 Html_Put(parser, ' ');
1521 parser->spc = False;
1522 parser->adnl = 0;
1525 else if (ch == '\n') {
1526 ++parser->adnl;
1527 parser->column = 0;
1529 else if (ch == '\t') {
1530 int column = parser->column + (8 - (parser->column % 8));
1532 parser->adnl = 0;
1533 while (parser->column < column) {
1534 Html_Put(parser, ' ');
1535 ++parser->column;
1537 continue;
1539 else {
1540 parser->adnl = 0;
1541 ++parser->column;
1544 else
1545 parser->adnl = 0;
1546 Html_Put(parser, ch);
1547 parser->quark = Qdefault;
1548 parser->spc = False;
1553 /************************************************************************/
1554 /* ARGUMENTS */
1555 /************************************************************************/
1556 static void
1557 Html_AArgs(Html_Parser *parser, Html_Item *item)
1559 int ch, sz;
1560 char buf[32];
1562 /*CONSTCOND*/
1563 while (True) {
1564 sz = 0;
1565 while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
1566 if (isalnum(ch))
1567 break;
1568 else
1569 (void)Html_Get(parser);
1572 if (ch == '>' || ch == EOF)
1573 return;
1574 buf[sz++] = tolower(Html_Get(parser));
1575 while ((ch = Html_Peek(parser)) != '>' && ch != EOF)
1576 if (isalnum(ch))
1577 buf[sz++] = tolower(Html_Get(parser));
1578 else
1579 break;
1580 buf[sz] = '\0';
1581 if (strcmp(buf, "href") == 0) {
1582 item->combine = XawTextSinkCopyProperty(XawTextGetSink(text),
1583 item->info->ident);
1584 item->override = True;
1585 item->combine->xlfd_mask = 0L;
1586 item->combine->mask = XAW_TPROP_UNDERLINE | XAW_TPROP_FOREGROUND;
1587 item->combine->foreground = parser->alink;
1588 return;
1590 while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
1591 if (isspace(ch))
1592 break;
1593 else
1594 (void)Html_Get(parser);
1599 static void
1600 Html_FontArgs(Html_Parser *parser, Html_Item *item)
1602 int ch, sz;
1603 char name[32], value[256], xlfd[128];
1605 item->combine = XawTextSinkCopyProperty(XawTextGetSink(text),
1606 Qdefault);
1607 item->override = True;
1608 item->combine->mask = item->combine->xlfd_mask = 0L;
1610 /*CONSTCOND*/
1611 while (True) {
1612 /* skip white spaces */
1613 while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
1614 if (isalnum(ch))
1615 break;
1616 else
1617 (void)Html_Get(parser);
1620 if (ch == '>' || ch == EOF)
1621 return;
1623 /* read option name */
1624 sz = 0;
1625 name[sz++] = tolower(Html_Get(parser));
1626 while ((ch = Html_Peek(parser)) != '>' && ch != EOF)
1627 if (isalnum(ch) && (sz + 1 < sizeof(name)))
1628 name[sz++] = tolower(Html_Get(parser));
1629 else
1630 break;
1631 name[sz] = '\0';
1633 if (ch != '=')
1634 continue;
1635 (void)Html_Get(parser); /* skip `=' */
1636 if (Html_Peek(parser) == '"')
1637 (void)Html_Get(parser);
1639 sz = 0;
1640 while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
1641 if (!isspace(ch) && (sz + 1 < sizeof(value)))
1642 value[sz++] = Html_Get(parser);
1643 else
1644 break;
1646 value[sz] = '\0';
1647 if (sz > 0 && value[sz - 1] == '"')
1648 value[--sz] = '\0';
1650 if (strcmp(name, "color") == 0) {
1651 XColor color, exact;
1653 if (XAllocNamedColor(XtDisplay(toplevel), toplevel->core.colormap,
1654 value, &color, &exact)) {
1655 item->combine->mask |= XAW_TPROP_FOREGROUND;
1656 item->combine->foreground = color.pixel;
1659 else if (strcmp(name, "face") == 0) {
1660 int count = 0;
1661 char *ptr, *family, **font_list;
1663 ptr = value;
1664 do {
1665 family = ptr;
1666 ptr = strchr(ptr, ',');
1667 if (ptr)
1668 *ptr++ = '\0';
1669 XmuSnprintf(xlfd, sizeof(xlfd), "-*-%s-*-*-*-*-*-*-*-*-*-*-*-*",
1670 family);
1671 font_list = XListFonts(XtDisplay(toplevel), xlfd, 1, &count);
1672 if (font_list)
1673 XFreeFontNames(font_list);
1674 if (count)
1675 break;
1676 } while (ptr);
1677 if (count) {
1678 item->combine->xlfd_mask |= XAW_TPROP_FAMILY;
1679 item->combine->family = XrmStringToQuark(family);
1682 else if (strcmp(name, "size") == 0) {
1683 int size, sign = 0;
1685 if (isalnum(*value)) {
1686 size = atoi(value);
1687 sign = 0;
1689 else {
1690 char *str = XrmQuarkToString(item->combine->pixel_size);
1692 size = str ? atoi(str) : 12;
1693 if (*value == '+') {
1694 size += atoi(value + 1);
1695 sign = 1;
1697 else if (*value == '-') {
1698 size -= atoi(value + 1);
1699 sign = -1;
1703 if (item->combine->xlfd != NULLQUARK) {
1704 int count, ucount, dcount, usize, dsize;
1705 char **current, **result, **up, **down;
1707 current = result = up = down = NULL;
1708 /* try to load an appropriate font */
1709 XmuSnprintf(value, sizeof(value),
1710 "-*-%s-%s-%s-*--%%d-*-*-*-*-*-%s-%s",
1711 XrmQuarkToString(item->combine->family),
1712 XrmQuarkToString(item->combine->weight),
1713 XrmQuarkToString(item->combine->slant),
1714 XrmQuarkToString(item->combine->registry),
1715 XrmQuarkToString(item->combine->encoding));
1716 XmuSnprintf(xlfd, sizeof(xlfd), value,
1717 atoi(XrmQuarkToString(item->combine->pixel_size)));
1718 current = XListFonts(XtDisplay(toplevel), xlfd, 1, &count);
1719 if (count) {
1720 ucount = dcount = usize = dsize = 0;
1722 XmuSnprintf(xlfd, sizeof(xlfd), value, size);
1723 result = XListFonts(XtDisplay(toplevel), xlfd, 1, &count);
1724 if (count == 0 || strstr(*result, "-0-")) {
1725 if (sign <= 0) {
1726 sz = dsize = size;
1727 while (dcount == 0 && --sz > size - 8 && sz > 1) {
1728 XmuSnprintf(xlfd, sizeof(xlfd), value, sz);
1729 down = XListFonts(XtDisplay(toplevel), xlfd,
1730 1, &dcount);
1731 if (dcount && strstr(*down, "-0-") != NULL) {
1732 XFreeFontNames(down);
1733 down = NULL;
1734 dcount = 0;
1737 if (dcount)
1738 dsize = sz;
1740 if (sign >= 0) {
1741 sz = usize = size;
1742 while (ucount == 0 && ++sz < size + 8) {
1743 XmuSnprintf(xlfd, sizeof(xlfd), value, sz);
1744 up = XListFonts(XtDisplay(toplevel), xlfd,
1745 1, &ucount);
1746 if (ucount && strstr(*up, "-0-") != NULL) {
1747 XFreeFontNames(up);
1748 up = NULL;
1749 ucount = 0;
1752 if (ucount)
1753 usize = sz;
1755 if (ucount && dcount)
1756 size = size - dsize < usize - size ? dsize : usize;
1757 else if (ucount)
1758 size = usize;
1759 else if (dcount)
1760 size = dsize;
1762 if (current)
1763 XFreeFontNames(current);
1764 if (result)
1765 XFreeFontNames(result);
1766 if (up)
1767 XFreeFontNames(up);
1768 if (down)
1769 XFreeFontNames(down);
1773 XmuSnprintf(value, sizeof(value), "%d", size);
1774 item->combine->xlfd_mask |= XAW_TPROP_PIXELSIZE;
1775 item->combine->pixel_size = XrmStringToQuark(value);
1778 while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
1779 if (isspace(ch))
1780 break;
1781 else
1782 (void)Html_Get(parser);