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
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
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() */
52 static void CloseCallback(Widget
, XtPointer
, XtPointer
);
53 static void StartHelp(void);
54 void Html_ModeStart(Widget
);
59 static Widget shell
, text
;
60 static Bool popped_up
= 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*),
79 source
= XawTextGetSource(text
);
80 XawTextSourceClearEntities(source
, 0,
81 XawTextSourceScan(source
, 0, XawstAll
,
82 XawsdRight
, 1, True
));
84 resource
.resource_name
= topic
;
85 XtGetApplicationResources(shell
, (XtPointer
)&str
,
86 &resource
, 1, NULL
, 0);
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
);
101 Html_ModeStart(source
);
102 _XawTextBuildLineTable((TextWidget
)text
,
103 XawTextTopPosition(text
), True
);
104 XawTextDisplay(text
);
105 if (popped_up
== False
) {
107 XtPopup(shell
, XtGrabNone
);
108 XtSetKeyboardFocus(shell
, text
);
115 static XtResource resource
= {
116 "properties", "Properties", XtRString
, sizeof(char*),
121 Widget pane
, commands
, close
;
123 XawTextPropertyList
*propl
;
125 shell
= XtCreatePopupShell("help", transientShellWidgetClass
,
127 pane
= XtCreateManagedWidget("pane", panedWidgetClass
,
129 text
= XtVaCreateManagedWidget("text", asciiTextWidgetClass
,
130 pane
, XtNeditType
, XawtextRead
, NULL
);
131 commands
= XtCreateManagedWidget("commands", formWidgetClass
, pane
,
133 close
= XtCreateManagedWidget("close", commandWidgetClass
,
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
);
150 CloseCallback(Widget w
, XtPointer user_data
, XtPointer call_data
)
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
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
194 * Author: Paulo César Pereira de Andrade
197 #define Html_Peek(parser) ((parser)->next)
202 typedef struct _Html_Parser Html_Parser
;
203 typedef struct _Html_Item Html_Item
;
205 typedef struct _Html_TagInfo
{
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
;
221 XawTextPosition start
, end
;
224 XawTextProperty
*combine
;
230 Html_Item
*parent
, *child
, *next
;
233 struct _Html_Parser
{
235 XawTextBlock block
, replace
;
236 XawTextPosition position
, offset
, start
, end
, last
;
239 Html_Item
*item
, *head
;
241 int space
, pre
, adnl
, list
, desc
, column
;
243 XawTextBlock
*entity
;
248 typedef struct _Html_SourceInfo Html_SourceInfo
;
249 struct _Html_SourceInfo
{
252 XawTextPosition last
;
253 Html_SourceInfo
*next
;
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
*);
300 static Html_TagInfo tag_info
[] = {
304 {"address", 1, 0, 1, 0, 0,
310 {"blockquote", 0, 1, 1, 1, 1,
313 {"body", 0, 0, 1, 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,
323 {"dl", 0, 1, 1, 0, 0,
326 {"dt", 0, 0, 1, 0, 0,
328 {"em", 1, 0, 1, 0, 0,
331 {"font", 1, 1, 1, 0, 0,
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,
355 {"html", 0, 0, 1, 0, 0,
361 {"kbd", 1, 0, 1, 0, 0,
362 0, XAW_TPROP_FAMILY
| XAW_TPROP_PIXELSIZE
,
364 {"li", 0, 0, 0, 0, 0,
366 {"ol", 0, 1, 1, 0, 1,
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,
380 {"tt", 1, 0, 1, 0, 0,
381 0, XAW_TPROP_FAMILY
| XAW_TPROP_PIXELSIZE
,
383 {"ul", 0, 1, 1, 0, 1,
388 static char *pnl
= "<p>\n", *nlpnl
= "\n<p>\n";
389 static Html_SourceInfo
*source_info
;
395 Html_GetText(Widget src
, XawTextPosition position
)
397 char *result
, *tempResult
;
398 XawTextPosition offset
= 0;
401 tempResult
= result
= XtMalloc((unsigned)(position
+ 1));
403 while (offset
< position
) {
404 offset
= XawTextSourceRead(src
, offset
, &text
, position
- offset
);
407 memcpy(tempResult
, text
.ptr
, (unsigned)text
.length
);
408 tempResult
+= text
.length
;
417 Html_ModeStart(Widget src
)
419 Html_Parser
*parser
= XtNew(Html_Parser
);
420 Html_Item
*next
, *item
;
422 Html_SourceInfo
*info
= XtNew(Html_SourceInfo
);
424 if (XAllocNamedColor(XtDisplay(toplevel
), toplevel
->core
.colormap
,
425 "blue", &color
, &exact
))
426 parser
->alink
= color
.pixel
;
430 XtVaSetValues(src
, XtNeditType
, XawtextEdit
, NULL
);
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
;
443 parser
->quark
= NULLQUARK
;
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
;
450 (void)Html_Get(parser
);
453 parser
->list
= parser
->desc
= parser
->column
= 0;
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;
462 if (source_info
== NULL
)
465 Html_SourceInfo
*tmp
= source_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);
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
;
488 (void)Html_Get(parser
);
490 parser
->list
= parser
->desc
= parser
->column
= 0;
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
);
506 Html_AddEntities(parser
, item
);
508 XtFree((XtPointer
)item
->combine
);
509 XtFree((XtPointer
)item
);
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
);
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
)
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
;
543 pinfo
->next
= info
->next
;
544 XtFree(info
->block
.ptr
);
545 XtFree((XtPointer
)info
);
549 Html_ParseCallback(Widget w
, XtPointer client_data
, XtPointer call_data
)
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
));
567 Html_Get(Html_Parser
*parser
)
569 if (parser
->ch
== EOF
)
571 if (parser
->i
>= parser
->block
.length
) {
573 parser
->position
= XawTextSourceRead(parser
->source
, parser
->position
,
574 &parser
->block
, 4096);
576 parser
->ch
= parser
->next
;
577 if (parser
->block
.length
== 0)
580 parser
->next
= (unsigned char)parser
->block
.ptr
[parser
->i
++];
589 static int initialized
;
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
);
617 /************************************************************************/
619 /************************************************************************/
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
;
628 Bool changed
= False
;
630 /* combine properties */
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
;
640 (void)XawTextSinkCombineProperty(sink
, property
,
641 XawTextSinkGetProperty(sink
, parent
->ident
), False
);
642 if (item
->combine
&& parent
->combine
)
643 (void)XawTextSinkCombineProperty(sink
, item
->combine
,
648 XawTextSinkCombineProperty(sink
, property
, item
->combine
, True
);
650 property
= XawTextSinkAddProperty(sink
, property
);
651 XtFree((XtPointer
)tprop
);
652 if (property
&& item
->ident
!= property
->identifier
) {
653 item
->ident
= property
->identifier
;
660 item
->end
= item
->next
->start
;
661 else if (item
->parent
)
662 item
->end
= item
->parent
->end
;
664 item
->end
= parser
->last
;
669 segment
.x1
= child
->start
;
670 segment
.x2
= child
->end
;
671 (void)XmuScanlineOrSegment(mask
, &segment
);
672 Html_AddEntities(parser
, child
);
674 XtFree((XtPointer
)child
->combine
);
675 XtFree((XtPointer
)child
);
679 /* build entity mask */
680 (void)XmuScanlineNot(mask
, item
->start
, item
->end
);
681 (void)XmuScanlineAnd(mask
, parser
->mask
);
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
);
701 if (item
->info
&& item
->info
->para
) {
702 XawTextSourceSetParagraph(parser
->source
, item
->start
, item
->end
,
703 40, /* arbitrary value, for testing */
710 Html_Commit(Html_Parser
*parser
)
712 XawTextPosition position
;
715 position
= parser
->start
;
716 length
= parser
->end
- parser
->start
;
721 if (position
+ length
> parser
->last
+ 1)
722 length
-= (position
+ length
) - parser
->last
+ 1;
724 if (parser
->quark
!= Qdefault
&& parser
->quark
!= NULLQUARK
&& length
> 0) {
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
);
738 XawTextSourceAddEntity(parser
->source
, 0, /*XAW_TENT_LITEM,*/
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
;
755 item
->combine
= NULL
;
756 item
->override
= False
;
757 item
->replace
= (XtPointer
)parser
->entity
;
758 item
->child
= item
->next
= NULL
;
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
);
786 Html_ParseTag(Html_Parser
*parser
)
791 Html_Item
*item
= NULL
;
792 XawTextPosition offset
= parser
->offset
- 1;
794 switch (Html_Peek(parser
)) {
796 (void)Html_Get(parser
); /* eat `!' */
797 if (Html_Peek(parser
) == '-') {
799 (void)Html_Get(parser
); /* eat `-' */
800 if (Html_Peek(parser
) == '-') {
803 (void)Html_Get(parser
);
804 while ((ch
= Html_Peek(parser
)) != EOF
) {
805 if (ch
== '>' && count
>= 2)
811 (void)Html_Get(parser
);
819 (void)Html_Get(parser
); /* eat `/' */
821 while (isalnum(Html_Peek(parser
)) &&
822 ((sz
+ 1) < sizeof(buf
)))
823 buf
[sz
++] = tolower(Html_Get(parser
));
825 if ((info
= Html_GetInfo(buf
)) != NULL
) {
827 Html_Item
*it
= parser
->head
;
830 if (it
->info
== info
)
836 if (it
== parser
->head
)
837 parser
->head
->end
= offset
;
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
;
848 parser
->head
= parser
->item
;
855 while (isalnum(Html_Peek(parser
)) &&
856 ((sz
+ 1) < sizeof(buf
)))
857 buf
[sz
++] = tolower(Html_Get(parser
));
859 if ((info
= Html_GetInfo(buf
)) != NULL
) {
860 if (info
->end
== False
) {
861 if (info
->ident
== Qli
)
864 break; /* no more processing required */
866 item
= XtNew(Html_Item
);
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
)
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
) {
886 parser
->head
->info
->ident
== Qdt
) {
887 parser
->head
->end
= offset
;
888 parser
->head
= parser
->head
->parent
;
891 else if (info
->ident
== Qdt
) {
893 parser
->head
->info
->ident
== Qdd
) {
894 parser
->head
->end
= offset
;
895 parser
->head
= parser
->head
->parent
;
898 else if (!info
->nest
) {
900 if (it
->info
== info
|| it
->info
->end
)
905 /* close the items */
906 while (parser
->head
!= it
) {
907 if (parser
->head
->info
->ident
== Qpre
)
909 parser
->head
->end
= offset
;
910 parser
->head
= parser
->head
->parent
;
916 it
= parser
->head
->child
;
918 item
->parent
= parser
->head
;
920 parser
->head
->child
= item
;
929 /* close the `head' item and start a new one */
932 parser
->head
->end
= offset
;
933 if (parser
->head
->parent
)
934 parser
->head
= parser
->head
->parent
;
936 parser
->head
= parser
->item
;
938 if ((it
= parser
->head
->child
) != NULL
) {
939 item
->parent
= parser
->head
;
946 parser
->head
->child
= item
;
952 /* this is not common, but handle it */
953 Html_Item
*it
= parser
->item
;
960 if (info
->parse_args
)
961 (info
->parse_args
)(parser
, item
);
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;
975 Html_Parse2(Html_Parser
*parser
)
980 if ((ch
= Html_Get(parser
)) == '<') {
981 parser
->end
= parser
->offset
- 1;
983 parser
->quark
= Qhide
;
984 parser
->start
= parser
->end
;
986 Html_ParseTag(parser
);
988 (void)Html_Get(parser
); /* eat `>' */
989 parser
->end
= parser
->offset
;
1000 Html_Parse1(Html_Parser
*parser
)
1002 static XawTextBlock
*entities
[256];
1003 static char chars
[256];
1007 if ((ch
= Html_Parse2(parser
)) == EOF
)
1011 unsigned char idx
= '?';
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
))
1027 (void)Html_Get(parser
);
1030 else if (strcasecmp(buf
, "lt") == 0)
1032 else if (strcasecmp(buf
, "gt") == 0)
1034 else if (strcasecmp(buf
, "nbsp") == 0)
1036 else if (strcasecmp(buf
, "amp") == 0)
1038 else if (strcasecmp(buf
, "quot") == 0)
1040 else if (*buf
== '#') {
1046 idx
= strtol(buf
+ 1, &tmp
, 10);
1051 else if (strcmp(buf
+ 1, "acute") == 0) {
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) {
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) {
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) {
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) {
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) {
1098 case 'c': idx
= 0xe7; break; case 'C': idx
= 0xc7; break;
1101 else if (strcmp(buf
+ 1, "slash") == 0) {
1103 case 'o': idx
= 0xf8; break; case 'O': idx
= 0xd8; break;
1106 else if (strcmp(buf
+ 1, "ring") == 0) {
1108 case 'a': idx
= 0xe5; break; case 'A': idx
= 0xc5; break;
1111 else if (strcasecmp(buf
, "iexcl") == 0)
1113 else if (strcasecmp(buf
, "cent") == 0)
1115 else if (strcasecmp(buf
, "pound") == 0)
1117 else if (strcasecmp(buf
, "curren") == 0)
1119 else if (strcasecmp(buf
, "yen") == 0)
1121 else if (strcasecmp(buf
, "brvbar") == 0)
1123 else if (strcasecmp(buf
, "sect") == 0)
1125 else if (strcasecmp(buf
, "uml") == 0)
1127 else if (strcasecmp(buf
, "copy") == 0)
1129 else if (strcasecmp(buf
, "ordf") == 0)
1131 else if (strcasecmp(buf
, "laquo") == 0)
1133 else if (strcasecmp(buf
, "not") == 0)
1135 else if (strcasecmp(buf
, "shy") == 0)
1137 else if (strcasecmp(buf
, "reg") == 0)
1139 else if (strcasecmp(buf
, "macr") == 0)
1141 else if (strcasecmp(buf
, "deg") == 0)
1143 else if (strcasecmp(buf
, "plusmn") == 0)
1145 else if (strcasecmp(buf
, "sup2") == 0)
1147 else if (strcasecmp(buf
, "sup3") == 0)
1149 else if (strcasecmp(buf
, "acute") == 0)
1151 else if (strcasecmp(buf
, "micro") == 0)
1153 else if (strcasecmp(buf
, "para") == 0)
1155 else if (strcasecmp(buf
, "middot") == 0)
1157 else if (strcasecmp(buf
, "cedil") == 0)
1159 else if (strcasecmp(buf
, "supl") == 0)
1161 else if (strcasecmp(buf
, "ordm") == 0)
1163 else if (strcasecmp(buf
, "raquo") == 0)
1165 else if (strcasecmp(buf
, "frac14") == 0)
1167 else if (strcasecmp(buf
, "frac12") == 0)
1169 else if (strcasecmp(buf
, "frac34") == 0)
1171 else if (strcasecmp(buf
, "iquest") == 0)
1173 else if (strcasecmp(buf
, "AElig") == 0)
1175 else if (strcasecmp(buf
, "ETH") == 0)
1177 else if (strcasecmp(buf
, "THORN") == 0)
1179 else if (strcasecmp(buf
, "szlig") == 0)
1181 else if (strcasecmp(buf
, "aelig") == 0)
1183 else if (strcasecmp(buf
, "eth") == 0)
1185 else if (strcasecmp(buf
, "thorn") == 0)
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
;
1197 parser
->entity
= entities
[idx
];
1198 parser
->end
= parser
->offset
;
1199 Html_Commit(parser
);
1200 parser
->start
= parser
->end
;
1206 /************************************************************************/
1208 /************************************************************************/
1210 Html_Put(Html_Parser
*parser
, int ch
)
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
;
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
;
1237 Html_FormatTag(Html_Parser
*parser
)
1241 Html_TagInfo
*info
= NULL
;
1243 switch (Html_Peek(parser
)) {
1245 Html_Put(parser
, '<');
1246 Html_Put(parser
, Html_Get(parser
)); /* eat `!' */
1247 if (Html_Peek(parser
) == '-') {
1249 Html_Put(parser
, Html_Get(parser
)); /* eat `-' */
1250 if (Html_Peek(parser
) == '-') {
1253 Html_Put(parser
, Html_Get(parser
));
1254 while ((ch
= Html_Peek(parser
)) != EOF
) {
1255 if (ch
== '>' && count
>= 2)
1261 Html_Put(parser
, Html_Get(parser
));
1263 (void)Html_Get(parser
); /* eat `>' */
1264 Html_Put(parser
, '>');
1270 Html_Put(parser
, '<');
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
));
1278 if ((info
= Html_GetInfo(buf
)) != NULL
&& info
->adnl
) {
1279 if (info
->ident
== Qpre
&& parser
->pre
) {
1280 if (--parser
->pre
== 0)
1283 parser
->quark
= Qetag
;
1285 if (info
->ident
== Qp
) {
1286 while ((ch
= Html_Peek(parser
) != '>' && ch
!= EOF
))
1287 (void)Html_Get(parser
);
1288 (void)Html_Get(parser
); /* eat '>' */
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');
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');
1312 Html_Puts(parser
, "</");
1313 Html_Puts(parser
, buf
);
1316 while (isalnum(Html_Peek(parser
)) &&
1317 ((sz
+ 1) < sizeof(buf
)))
1318 buf
[sz
++] = tolower(Html_Get(parser
));
1320 if ((info
= Html_GetInfo(buf
)) != NULL
&& info
->adnl
) {
1321 if (info
->ident
== Qpre
)
1323 if (parser
->quark
!= Qtag
) {
1324 if (parser
->adnl
< 2) {
1325 Html_Puts(parser
, parser
->adnl
? pnl
: nlpnl
);
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 '>' */
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
);
1348 else if (parser
->adnl
== 0) {
1349 Html_Put(parser
, '\n');
1355 else if (info
->ident
== Qli
) {
1356 if (parser
->adnl
== 0) {
1357 Html_Put(parser
, '\n');
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
);
1371 else if (parser
->adnl
== 0) {
1372 Html_Put(parser
, '\n');
1378 else if (info
->ident
== Qdd
) {
1379 if (parser
->desc
== 0) {
1380 if (parser
->adnl
< 2) {
1381 Html_Puts(parser
, parser
->adnl
? pnl
: nlpnl
);
1386 else if (parser
->adnl
== 0) {
1387 Html_Put(parser
, '\n');
1393 else if (info
->ident
== Qdt
) {
1394 if (parser
->adnl
== 0) {
1395 Html_Put(parser
, '\n');
1402 Html_Put(parser
, '<');
1403 Html_Puts(parser
, buf
);
1408 while ((ch
= Html_Peek(parser
)) != '>' && ch
!= EOF
) {
1410 (void)Html_Get(parser
);
1415 Html_Put(parser
, ' ');
1418 Html_Put(parser
, Html_Get(parser
));
1420 Html_Put(parser
, Html_Get(parser
)); /* eat `>' */
1421 if (info
&& info
->ident
== Qbr
) {
1424 Html_Put(parser
, '\n');
1425 parser
->quark
= info
->ident
;
1432 Html_Format3(Html_Parser
*parser
)
1437 if ((ch
= Html_Get(parser
)) == '<') {
1438 if (parser
->quark
== Qspace
&& parser
->spc
== False
) {
1439 Html_Put(parser
, ' ');
1443 /* parser->quark = Qhide;*/
1444 Html_FormatTag(parser
);
1454 Html_Format2(Html_Parser
*parser
)
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
)
1463 Html_Put(parser
, Html_Get(parser
));
1466 Html_Put(parser
, Html_Get(parser
));
1478 Html_Format1(Html_Parser
*parser
)
1483 if ((ch
= Html_Format2(parser
)) == EOF
)
1486 if (parser
->quark
== Qetag
) {
1487 if (parser
->adnl
< 2) {
1488 Html_Puts(parser
, parser
->adnl
? pnl
: nlpnl
);
1493 else if (parser
->quark
== Qspace
&& parser
->spc
== False
) {
1494 Html_Put(parser
, ' ');
1498 if (!parser
->pre
&& isspace(ch
))
1499 parser
->quark
= Qspace
;
1503 /* did not yet see any non space character */
1507 parser
->spc
= False
;
1510 else if (ch
== '\t')
1511 parser
->column
+= 8 - (parser
->column
% 8);
1517 int column
= parser
->column
;
1519 while (column
-- > 0)
1520 Html_Put(parser
, ' ');
1521 parser
->spc
= False
;
1525 else if (ch
== '\n') {
1529 else if (ch
== '\t') {
1530 int column
= parser
->column
+ (8 - (parser
->column
% 8));
1533 while (parser
->column
< column
) {
1534 Html_Put(parser
, ' ');
1546 Html_Put(parser
, ch
);
1547 parser
->quark
= Qdefault
;
1548 parser
->spc
= False
;
1553 /************************************************************************/
1555 /************************************************************************/
1557 Html_AArgs(Html_Parser
*parser
, Html_Item
*item
)
1565 while ((ch
= Html_Peek(parser
)) != '>' && ch
!= EOF
) {
1569 (void)Html_Get(parser
);
1572 if (ch
== '>' || ch
== EOF
)
1574 buf
[sz
++] = tolower(Html_Get(parser
));
1575 while ((ch
= Html_Peek(parser
)) != '>' && ch
!= EOF
)
1577 buf
[sz
++] = tolower(Html_Get(parser
));
1581 if (strcmp(buf
, "href") == 0) {
1582 item
->combine
= XawTextSinkCopyProperty(XawTextGetSink(text
),
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
;
1590 while ((ch
= Html_Peek(parser
)) != '>' && ch
!= EOF
) {
1594 (void)Html_Get(parser
);
1600 Html_FontArgs(Html_Parser
*parser
, Html_Item
*item
)
1603 char name
[32], value
[256], xlfd
[128];
1605 item
->combine
= XawTextSinkCopyProperty(XawTextGetSink(text
),
1607 item
->override
= True
;
1608 item
->combine
->mask
= item
->combine
->xlfd_mask
= 0L;
1612 /* skip white spaces */
1613 while ((ch
= Html_Peek(parser
)) != '>' && ch
!= EOF
) {
1617 (void)Html_Get(parser
);
1620 if (ch
== '>' || ch
== EOF
)
1623 /* read option name */
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
));
1635 (void)Html_Get(parser
); /* skip `=' */
1636 if (Html_Peek(parser
) == '"')
1637 (void)Html_Get(parser
);
1640 while ((ch
= Html_Peek(parser
)) != '>' && ch
!= EOF
) {
1641 if (!isspace(ch
) && (sz
+ 1 < sizeof(value
)))
1642 value
[sz
++] = Html_Get(parser
);
1647 if (sz
> 0 && value
[sz
- 1] == '"')
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) {
1661 char *ptr
, *family
, **font_list
;
1666 ptr
= strchr(ptr
, ',');
1669 XmuSnprintf(xlfd
, sizeof(xlfd
), "-*-%s-*-*-*-*-*-*-*-*-*-*-*-*",
1671 font_list
= XListFonts(XtDisplay(toplevel
), xlfd
, 1, &count
);
1673 XFreeFontNames(font_list
);
1678 item
->combine
->xlfd_mask
|= XAW_TPROP_FAMILY
;
1679 item
->combine
->family
= XrmStringToQuark(family
);
1682 else if (strcmp(name
, "size") == 0) {
1685 if (isalnum(*value
)) {
1690 char *str
= XrmQuarkToString(item
->combine
->pixel_size
);
1692 size
= str
? atoi(str
) : 12;
1693 if (*value
== '+') {
1694 size
+= atoi(value
+ 1);
1697 else if (*value
== '-') {
1698 size
-= atoi(value
+ 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
);
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-")) {
1727 while (dcount
== 0 && --sz
> size
- 8 && sz
> 1) {
1728 XmuSnprintf(xlfd
, sizeof(xlfd
), value
, sz
);
1729 down
= XListFonts(XtDisplay(toplevel
), xlfd
,
1731 if (dcount
&& strstr(*down
, "-0-") != NULL
) {
1732 XFreeFontNames(down
);
1742 while (ucount
== 0 && ++sz
< size
+ 8) {
1743 XmuSnprintf(xlfd
, sizeof(xlfd
), value
, sz
);
1744 up
= XListFonts(XtDisplay(toplevel
), xlfd
,
1746 if (ucount
&& strstr(*up
, "-0-") != NULL
) {
1755 if (ucount
&& dcount
)
1756 size
= size
- dsize
< usize
- size
? dsize
: usize
;
1763 XFreeFontNames(current
);
1765 XFreeFontNames(result
);
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
) {
1782 (void)Html_Get(parser
);