1786 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1786 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
						|
 * copy of this software and associated documentation files (the "Software"),
 | 
						|
 * to deal in the Software without restriction, including without limitation
 | 
						|
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
						|
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
						|
 * Software is furnished to do so, subject to the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice shall be included in
 | 
						|
 * all copies or substantial portions of the Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | 
						|
 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
						|
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 | 
						|
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
						|
 * SOFTWARE.
 | 
						|
 *
 | 
						|
 * Except as contained in this notice, the name of Conectiva Linux shall
 | 
						|
 * not be used in advertising or otherwise to promote the sale, use or other
 | 
						|
 * dealings in this Software without prior written authorization from
 | 
						|
 * Conectiva Linux.
 | 
						|
 *
 | 
						|
 * Author: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <X11/IntrinsicP.h>
 | 
						|
#include <X11/StringDefs.h>
 | 
						|
#include <X11/Shell.h>
 | 
						|
#include <X11/Xaw/AsciiText.h>
 | 
						|
#include <X11/Xaw/Command.h>
 | 
						|
#include <X11/Xaw/Form.h>
 | 
						|
#include <X11/Xaw/Paned.h>
 | 
						|
 | 
						|
#include <X11/Xaw/Text.h>
 | 
						|
#include <X11/Xaw/TextSinkP.h>
 | 
						|
#include <X11/Xaw/TextSrcP.h>
 | 
						|
#include <X11/Xmu/SysUtil.h>
 | 
						|
#include <X11/Xmu/Xmu.h>
 | 
						|
#include <stdlib.h>		/* for bsearch() */
 | 
						|
#include <ctype.h>
 | 
						|
#include "help.h"
 | 
						|
#include "options.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * Prototypes
 | 
						|
 */
 | 
						|
static void CloseCallback(Widget, XtPointer, XtPointer);
 | 
						|
static void StartHelp(void);
 | 
						|
void Html_ModeStart(Widget);
 | 
						|
 | 
						|
/*
 | 
						|
 * Initialization
 | 
						|
 */
 | 
						|
static Widget shell, text;
 | 
						|
static Bool popped_up = False;
 | 
						|
 | 
						|
/*
 | 
						|
 * Implementation
 | 
						|
 */
 | 
						|
void
 | 
						|
Help(char *topic)
 | 
						|
{
 | 
						|
    Widget source;
 | 
						|
    char *str = NULL;
 | 
						|
    Bool error = False;
 | 
						|
    static char *def_text = "<h2>Help Error</h2>"
 | 
						|
			    "No help available for the topic <b>%s</b>.";
 | 
						|
    XtResource resource = {
 | 
						|
	NULL, "HelpMessage", XtRString, sizeof(char*),
 | 
						|
	0, XtRString, NULL
 | 
						|
    };
 | 
						|
 | 
						|
    StartHelp();
 | 
						|
    source = XawTextGetSource(text);
 | 
						|
    XawTextSourceClearEntities(source, 0,
 | 
						|
			       XawTextSourceScan(source, 0, XawstAll,
 | 
						|
						 XawsdRight, 1, True));
 | 
						|
    if (topic != NULL) {
 | 
						|
	resource.resource_name = topic;
 | 
						|
	XtGetApplicationResources(shell, (XtPointer)&str,
 | 
						|
				  &resource, 1, NULL, 0);
 | 
						|
    }
 | 
						|
    if (str == NULL) {
 | 
						|
	int len;
 | 
						|
 | 
						|
	error = True;
 | 
						|
	if (topic == NULL)
 | 
						|
	    topic = "(null argument)";
 | 
						|
	str = XtMalloc(len  = strlen(topic) + strlen(def_text) + 1);
 | 
						|
	XmuSnprintf(str, len, def_text, topic);
 | 
						|
    }
 | 
						|
    XtVaSetValues(text, XtNstring, str, NULL);
 | 
						|
    if (error)
 | 
						|
	XtFree(str);
 | 
						|
 | 
						|
    Html_ModeStart(source);
 | 
						|
    _XawTextBuildLineTable((TextWidget)text,
 | 
						|
			       XawTextTopPosition(text), True);
 | 
						|
    XawTextDisplay(text);
 | 
						|
    if (popped_up == False) {
 | 
						|
	popped_up = True;
 | 
						|
	XtPopup(shell, XtGrabNone);
 | 
						|
	XtSetKeyboardFocus(shell, text);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
StartHelp(void)
 | 
						|
{
 | 
						|
    static XtResource resource = {
 | 
						|
	"properties", "Properties", XtRString, sizeof(char*),
 | 
						|
	0, XtRString, NULL
 | 
						|
    };
 | 
						|
 | 
						|
    if (shell == NULL) {
 | 
						|
	Widget pane, commands, close;
 | 
						|
	char *props;
 | 
						|
	XawTextPropertyList *propl;
 | 
						|
 | 
						|
	shell = XtCreatePopupShell("help", transientShellWidgetClass,
 | 
						|
				   toplevel, NULL, 0);
 | 
						|
	pane = XtCreateManagedWidget("pane", panedWidgetClass,
 | 
						|
				     shell, NULL, 0);
 | 
						|
	text = XtVaCreateManagedWidget("text", asciiTextWidgetClass,
 | 
						|
				       pane, XtNeditType, XawtextRead, NULL);
 | 
						|
	commands = XtCreateManagedWidget("commands", formWidgetClass, pane,
 | 
						|
					 NULL, 0);
 | 
						|
	close = XtCreateManagedWidget("close", commandWidgetClass,
 | 
						|
				      commands, NULL, 0);
 | 
						|
	XtAddCallback(close, XtNcallback, CloseCallback, NULL);
 | 
						|
	XtRealizeWidget(shell);
 | 
						|
	XSetWMProtocols(DPY, XtWindow(shell), &wm_delete_window, 1);
 | 
						|
	XtGetApplicationResources(text, (XtPointer)&props,
 | 
						|
				  &resource, 1, NULL, 0);
 | 
						|
	propl = XawTextSinkConvertPropertyList("html", props,
 | 
						|
					       toplevel->core.screen,
 | 
						|
					       toplevel->core.colormap,
 | 
						|
					       toplevel->core.depth);
 | 
						|
	XtVaSetValues(XawTextGetSink(text), XawNtextProperties, propl, NULL);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*ARGSUSED*/
 | 
						|
static void
 | 
						|
CloseCallback(Widget w, XtPointer user_data, XtPointer call_data)
 | 
						|
{
 | 
						|
    XtPopdown(shell);
 | 
						|
    popped_up = False;
 | 
						|
}
 | 
						|
 | 
						|
/*ARGSUSED*/
 | 
						|
void
 | 
						|
HelpCancelAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
 | 
						|
{
 | 
						|
    CloseCallback(w, NULL, NULL);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* bellow is a modified version of the html-mode.c I wrote for xedit
 | 
						|
 * (at least) temporarily dead.
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * Copyright (c) 1999 by The XFree86 Project, Inc.
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
						|
 * copy of this software and associated documentation files (the "Software"),
 | 
						|
 * to deal in the Software without restriction, including without limitation
 | 
						|
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
						|
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
						|
 * Software is furnished to do so, subject to the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice shall be included in
 | 
						|
 * all copies or substantial portions of the Software.
 | 
						|
 *  
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | 
						|
 * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
						|
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 | 
						|
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
						|
 * SOFTWARE.
 | 
						|
 *
 | 
						|
 * Except as contained in this notice, the name of the XFree86 Project shall
 | 
						|
 * not be used in advertising or otherwise to promote the sale, use or other
 | 
						|
 * dealings in this Software without prior written authorization from the
 | 
						|
 * XFree86 Project.
 | 
						|
 *
 | 
						|
 * Author: Paulo César Pereira de Andrade
 | 
						|
 */
 | 
						|
 | 
						|
#define Html_Peek(parser)	((parser)->next)
 | 
						|
 | 
						|
/*
 | 
						|
 * Types
 | 
						|
 */
 | 
						|
typedef struct _Html_Parser Html_Parser;
 | 
						|
typedef struct _Html_Item Html_Item;
 | 
						|
 | 
						|
typedef struct _Html_TagInfo {
 | 
						|
    char *name;
 | 
						|
    unsigned int entity	: 1;	/* it changes the type of the text */
 | 
						|
    unsigned int nest	: 1;	/* does not close tags automatically */
 | 
						|
    unsigned int end	: 1;	/* need a close markup */
 | 
						|
    unsigned int adnl	: 1;	/* add newline before/after tag contents */
 | 
						|
    unsigned int para	: 1;	/* changes the paragraph formatting */
 | 
						|
    unsigned long mask;	/* enforce use of attributes of this tag-info */
 | 
						|
    unsigned long xlfd_mask;
 | 
						|
    void (*parse_args)(Html_Parser*, Html_Item*);
 | 
						|
    XawTextProperty *override;
 | 
						|
    XrmQuark ident;
 | 
						|
} Html_TagInfo;
 | 
						|
 | 
						|
struct _Html_Item {
 | 
						|
    XrmQuark ident;
 | 
						|
    XawTextPosition start, end;
 | 
						|
    Html_TagInfo *info;
 | 
						|
 | 
						|
    XawTextProperty *combine;
 | 
						|
    Bool override;
 | 
						|
    int li;
 | 
						|
 | 
						|
    XtPointer replace;
 | 
						|
 | 
						|
    Html_Item *parent, *child, *next;
 | 
						|
};
 | 
						|
 | 
						|
struct _Html_Parser {
 | 
						|
    Widget source;
 | 
						|
    XawTextBlock block, replace;
 | 
						|
    XawTextPosition position, offset, start, end, last;
 | 
						|
    XrmQuark quark;
 | 
						|
    int i, ch, next;
 | 
						|
    Html_Item *item, *head;
 | 
						|
    XmuScanline *mask;
 | 
						|
    int space, pre, adnl, list, desc, column;
 | 
						|
    Bool spc;
 | 
						|
    XawTextBlock *entity;
 | 
						|
 | 
						|
    Pixel alink;
 | 
						|
};
 | 
						|
 | 
						|
typedef struct _Html_SourceInfo Html_SourceInfo;
 | 
						|
struct _Html_SourceInfo {
 | 
						|
    Widget source;
 | 
						|
    XawTextBlock block;
 | 
						|
    XawTextPosition last;
 | 
						|
    Html_SourceInfo *next;
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
 * Proptotypes
 | 
						|
 */
 | 
						|
void Html_ModeEnd(Widget);
 | 
						|
static void Html_ModeInit(void);
 | 
						|
static void Html_ParseCallback(Widget, XtPointer, XtPointer);
 | 
						|
static Html_TagInfo *Html_GetInfo(char*);
 | 
						|
static int Html_Get(Html_Parser*);
 | 
						|
static int Html_Parse1(Html_Parser*);
 | 
						|
static int Html_Parse2(Html_Parser*);
 | 
						|
static void Html_ParseTag(Html_Parser*);
 | 
						|
static void Html_Commit(Html_Parser*);
 | 
						|
static void Html_AddEntities(Html_Parser*, Html_Item*);
 | 
						|
 | 
						|
static int Html_Put(Html_Parser*, int);
 | 
						|
static void Html_Puts(Html_Parser*, char*);
 | 
						|
static int Html_Format1(Html_Parser*);
 | 
						|
static int Html_Format2(Html_Parser*);
 | 
						|
static int Html_Format3(Html_Parser*);
 | 
						|
static void Html_FormatTag(Html_Parser*);
 | 
						|
 | 
						|
static void Html_AArgs(Html_Parser*, Html_Item*);
 | 
						|
static void Html_FontArgs(Html_Parser*, Html_Item*);
 | 
						|
 | 
						|
/*
 | 
						|
 * Initialization
 | 
						|
 */
 | 
						|
static XrmQuark
 | 
						|
	Qbr,
 | 
						|
	Qdefault,
 | 
						|
	Qdd,
 | 
						|
	Qdl,
 | 
						|
	Qdt,
 | 
						|
	Qentity,
 | 
						|
	Qetag,
 | 
						|
	Qhide,
 | 
						|
	Qli,
 | 
						|
	Qol,
 | 
						|
	Qp,
 | 
						|
	Qpre,
 | 
						|
	Qspace,
 | 
						|
	Qtag,
 | 
						|
	Qul;
 | 
						|
 | 
						|
static Html_TagInfo tag_info[] = {
 | 
						|
    {"a",	1, 0, 1, 0, 0,
 | 
						|
     0, 0,
 | 
						|
     Html_AArgs},
 | 
						|
    {"address",	1, 0, 1, 0, 0,
 | 
						|
     0, XAW_TPROP_SLANT,
 | 
						|
     },
 | 
						|
    {"b",	1, 0, 1, 0, 0,
 | 
						|
     0, XAW_TPROP_WEIGHT,
 | 
						|
     },
 | 
						|
    {"blockquote", 0, 1, 1, 1, 1,
 | 
						|
     0, 0,
 | 
						|
     },
 | 
						|
    {"body",	0, 0, 1, 0, 0,
 | 
						|
     0, 0,
 | 
						|
     },
 | 
						|
    {"br",	0, 0, 0, 0, 0,
 | 
						|
     },
 | 
						|
    {"code",	1, 0, 1, 0, 0,
 | 
						|
     0, XAW_TPROP_FAMILY | XAW_TPROP_PIXELSIZE,
 | 
						|
     },
 | 
						|
    {"dd",	0, 1, 1, 0, 1,
 | 
						|
     0, 0},
 | 
						|
    {"dl",	0, 1, 1, 0, 0,
 | 
						|
     0, 0,
 | 
						|
     },
 | 
						|
    {"dt",	0, 0, 1, 0, 0,
 | 
						|
     0, 0},
 | 
						|
    {"em",	1, 0, 1, 0, 0,
 | 
						|
     0, XAW_TPROP_SLANT,
 | 
						|
     },
 | 
						|
    {"font",	1, 1, 1, 0, 0,
 | 
						|
     0, 0,
 | 
						|
     Html_FontArgs},
 | 
						|
    {"h1",	1, 0, 1, 1, 0,
 | 
						|
     0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
 | 
						|
     },
 | 
						|
    {"h2",	1, 0, 1, 1, 0,
 | 
						|
     0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
 | 
						|
     },
 | 
						|
    {"h3",	1, 0, 1, 1, 0,
 | 
						|
     0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
 | 
						|
     },
 | 
						|
    {"h4",	1, 0, 1, 1, 0,
 | 
						|
     0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
 | 
						|
     },
 | 
						|
    {"h5",	1, 0, 1, 1, 0,
 | 
						|
     0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
 | 
						|
     },
 | 
						|
    {"h6",	1, 0, 1, 1, 0,
 | 
						|
     0, XAW_TPROP_WEIGHT | XAW_TPROP_PIXELSIZE,
 | 
						|
     },
 | 
						|
    {"head",	0, 0, 1, 0, 0,
 | 
						|
     0, 0,
 | 
						|
     },
 | 
						|
    {"html",	0, 0, 1, 0, 0,
 | 
						|
     0, 0,
 | 
						|
     },
 | 
						|
    {"i",	1, 0, 1, 0, 0,
 | 
						|
     0, XAW_TPROP_SLANT,
 | 
						|
     },
 | 
						|
    {"kbd",	1, 0, 1, 0, 0,
 | 
						|
     0, XAW_TPROP_FAMILY | XAW_TPROP_PIXELSIZE,
 | 
						|
     },
 | 
						|
    {"li",	0, 0, 0, 0, 0,
 | 
						|
     0, 0},
 | 
						|
    {"ol",	0, 1, 1, 0, 1,
 | 
						|
     0, 0,
 | 
						|
     },
 | 
						|
    {"p",	0, 0, 0, 1, 0,
 | 
						|
     },
 | 
						|
    {"pre",	1, 0, 1, 1, 0,
 | 
						|
     0, XAW_TPROP_FAMILY | XAW_TPROP_PIXELSIZE,
 | 
						|
     },
 | 
						|
    {"samp",	1, 0, 1, 0, 0,
 | 
						|
     0, XAW_TPROP_FAMILY | XAW_TPROP_PIXELSIZE,
 | 
						|
     },
 | 
						|
    {"strong",	1, 0, 1, 0, 0,
 | 
						|
     0, XAW_TPROP_WEIGHT,
 | 
						|
     },
 | 
						|
    {"tt",	1, 0, 1, 0, 0,
 | 
						|
     0, XAW_TPROP_FAMILY | XAW_TPROP_PIXELSIZE,
 | 
						|
     },
 | 
						|
    {"ul",	0, 1, 1, 0, 1,
 | 
						|
     0, 0,
 | 
						|
     },
 | 
						|
};
 | 
						|
 | 
						|
static char *pnl = "<p>\n", *nlpnl = "\n<p>\n";
 | 
						|
static Html_SourceInfo *source_info;
 | 
						|
 | 
						|
/*
 | 
						|
 * Implementation
 | 
						|
 */
 | 
						|
static char *
 | 
						|
Html_GetText(Widget src, XawTextPosition position)
 | 
						|
{
 | 
						|
    char *result, *tempResult;
 | 
						|
    XawTextPosition offset = 0;
 | 
						|
    XawTextBlock text;
 | 
						|
 | 
						|
    tempResult = result = XtMalloc((unsigned)(position + 1));
 | 
						|
 | 
						|
    while (offset < position) {
 | 
						|
	offset = XawTextSourceRead(src, offset, &text, position - offset);
 | 
						|
	if (!text.length)
 | 
						|
	    break;
 | 
						|
	memcpy(tempResult, text.ptr, (unsigned)text.length);
 | 
						|
	tempResult += text.length;
 | 
						|
    }
 | 
						|
 | 
						|
    *tempResult = '\0';
 | 
						|
 | 
						|
    return (result);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
Html_ModeStart(Widget src)
 | 
						|
{
 | 
						|
    Html_Parser *parser = XtNew(Html_Parser);
 | 
						|
    Html_Item *next, *item;
 | 
						|
    XColor color, exact;
 | 
						|
    Html_SourceInfo *info = XtNew(Html_SourceInfo);
 | 
						|
 | 
						|
    if (XAllocNamedColor(XtDisplay(toplevel), toplevel->core.colormap,
 | 
						|
			 "blue", &color, &exact))
 | 
						|
	parser->alink = color.pixel;
 | 
						|
    else
 | 
						|
	parser->alink = 0L;
 | 
						|
 | 
						|
    XtVaSetValues(src, XtNeditType, XawtextEdit, NULL);
 | 
						|
 | 
						|
    Html_ModeInit();
 | 
						|
 | 
						|
    /* initialize parser state */
 | 
						|
    parser->source = src;
 | 
						|
    parser->position = XawTextSourceRead(parser->source, 0,
 | 
						|
					 &parser->block, 4096);
 | 
						|
    parser->replace.ptr = NULL;
 | 
						|
    parser->replace.firstPos = 0;
 | 
						|
    parser->replace.length = 0;
 | 
						|
    parser->replace.format = FMT8BIT;
 | 
						|
    parser->offset = -1;
 | 
						|
    parser->quark = NULLQUARK;
 | 
						|
    parser->i = 0;
 | 
						|
    parser->i = parser->ch = parser->next = 0;
 | 
						|
    parser->last = XawTextSourceScan(src, 0, XawstAll, XawsdRight, 1, 1);
 | 
						|
    if (parser->block.length == 0)
 | 
						|
	parser->ch = parser->next = EOF;
 | 
						|
    else
 | 
						|
	(void)Html_Get(parser);
 | 
						|
    parser->pre = 0;
 | 
						|
    parser->adnl = 1;
 | 
						|
    parser->list = parser->desc = parser->column = 0;
 | 
						|
    parser->spc = True;
 | 
						|
 | 
						|
    info->source = src;
 | 
						|
    info->block.ptr = Html_GetText(src, parser->last);
 | 
						|
    info->block.length = parser->last;
 | 
						|
    info->block.format = FMT8BIT;
 | 
						|
    info->block.firstPos = 0;
 | 
						|
    info->next = NULL;
 | 
						|
    if (source_info == NULL)
 | 
						|
	source_info = info;
 | 
						|
    else {
 | 
						|
	Html_SourceInfo *tmp = source_info;
 | 
						|
 | 
						|
	while (tmp->next)
 | 
						|
	    tmp = tmp->next;
 | 
						|
	tmp->next = info;
 | 
						|
    }
 | 
						|
 | 
						|
    while (Html_Format1(parser) != EOF)
 | 
						|
	;
 | 
						|
    XawTextSourceReplace(parser->source, 0, parser->last, &parser->replace);
 | 
						|
    XtFree(parser->replace.ptr);
 | 
						|
 | 
						|
    /* re-initialize parser state */
 | 
						|
    parser->position = XawTextSourceRead(parser->source, 0,
 | 
						|
					 &parser->block, 4096);
 | 
						|
    parser->offset = -1;
 | 
						|
    parser->quark = NULLQUARK;
 | 
						|
    parser->i = parser->ch = parser->next = 0;
 | 
						|
    parser->last = XawTextSourceScan(src, 0, XawstAll, XawsdRight, 1, 1);
 | 
						|
    info->last = parser->last;
 | 
						|
    if (parser->block.length == 0)
 | 
						|
	parser->ch = parser->next = EOF;
 | 
						|
    else
 | 
						|
	(void)Html_Get(parser);
 | 
						|
    parser->adnl = 1;
 | 
						|
    parser->list = parser->desc = parser->column = 0;
 | 
						|
    parser->spc = True;
 | 
						|
    parser->head = parser->item = NULL;
 | 
						|
 | 
						|
    parser->mask = XmuNewScanline(0, 0, 0);
 | 
						|
 | 
						|
    /* build html structure information */
 | 
						|
    while (Html_Parse1(parser) != EOF)
 | 
						|
	;
 | 
						|
 | 
						|
    /* create top level entity mask */
 | 
						|
    (void)XmuScanlineNot(parser->mask, 0, parser->last);
 | 
						|
 | 
						|
    item = parser->item;
 | 
						|
    while (item) {
 | 
						|
	next = item->next;
 | 
						|
	Html_AddEntities(parser, item);
 | 
						|
	if (item->combine)
 | 
						|
	    XtFree((XtPointer)item->combine);
 | 
						|
	XtFree((XtPointer)item);
 | 
						|
	item = next;
 | 
						|
    }
 | 
						|
    XmuDestroyScanline(parser->mask);
 | 
						|
 | 
						|
    XtVaSetValues(src, XtNeditType, XawtextRead, NULL);
 | 
						|
 | 
						|
    XtFree((XtPointer)parser);
 | 
						|
 | 
						|
    /* add callbacks for interactive changes */
 | 
						|
    XtAddCallback(src, XtNpropertyCallback, Html_ParseCallback, NULL);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
Html_ModeEnd(Widget src)
 | 
						|
{
 | 
						|
    Html_SourceInfo *info, *pinfo;
 | 
						|
 | 
						|
    XtRemoveCallback(src, XtNpropertyCallback, Html_ParseCallback, NULL);
 | 
						|
    for (pinfo = info = source_info; info; pinfo = info, info = info->next)
 | 
						|
	if (info->source == src)
 | 
						|
	    break;
 | 
						|
 | 
						|
    if (info == NULL)
 | 
						|
	return;
 | 
						|
 | 
						|
    XawTextSourceClearEntities(src, 0, info->last);
 | 
						|
    XtVaSetValues(src, XtNeditType, XawtextEdit, NULL);
 | 
						|
    XawTextSourceReplace(src, 0, info->last, &info->block);
 | 
						|
    XtVaSetValues(src, XtNeditType, XawtextRead, NULL);
 | 
						|
 | 
						|
    if (info == source_info)
 | 
						|
	source_info = source_info->next;
 | 
						|
    else
 | 
						|
	pinfo->next = info->next;
 | 
						|
    XtFree(info->block.ptr);
 | 
						|
    XtFree((XtPointer)info);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
Html_ParseCallback(Widget w, XtPointer client_data, XtPointer call_data)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
bcmp_tag_info(_Xconst void *left, _Xconst void *right)
 | 
						|
{
 | 
						|
    return (strcmp((char*)left, ((Html_TagInfo*)right)->name));
 | 
						|
}
 | 
						|
 | 
						|
static Html_TagInfo *
 | 
						|
Html_GetInfo(char *name)
 | 
						|
{
 | 
						|
    return (bsearch(name, tag_info, sizeof(tag_info) / sizeof(tag_info[0]),
 | 
						|
		    sizeof(Html_TagInfo), bcmp_tag_info));
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
Html_Get(Html_Parser *parser)
 | 
						|
{
 | 
						|
    if (parser->ch == EOF)
 | 
						|
	return (EOF);
 | 
						|
    if (parser->i >= parser->block.length) {
 | 
						|
	parser->i = 0;
 | 
						|
	parser->position = XawTextSourceRead(parser->source, parser->position,
 | 
						|
					     &parser->block, 4096);
 | 
						|
    }
 | 
						|
    parser->ch = parser->next;
 | 
						|
    if (parser->block.length == 0)
 | 
						|
	parser->next = EOF;
 | 
						|
    else
 | 
						|
	parser->next = (unsigned char)parser->block.ptr[parser->i++];
 | 
						|
    parser->offset++;
 | 
						|
 | 
						|
    return (parser->ch);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
Html_ModeInit(void)
 | 
						|
{
 | 
						|
    static int initialized;
 | 
						|
    int i;
 | 
						|
 | 
						|
    if (initialized)
 | 
						|
	return;
 | 
						|
 | 
						|
    Qbr			= XrmPermStringToQuark("br");
 | 
						|
    Qdd			= XrmPermStringToQuark("dd");
 | 
						|
    Qdefault		= XrmPermStringToQuark("default");
 | 
						|
    Qdl			= XrmPermStringToQuark("dl");
 | 
						|
    Qdt			= XrmPermStringToQuark("dt");
 | 
						|
    Qentity		= XrmPermStringToQuark("entity");
 | 
						|
    Qetag		= XrmPermStringToQuark("/tag");
 | 
						|
    Qhide		= XrmPermStringToQuark("hide");
 | 
						|
    Qli			= XrmPermStringToQuark("li");
 | 
						|
    Qol			= XrmPermStringToQuark("ol");
 | 
						|
    Qp			= XrmPermStringToQuark("p");
 | 
						|
    Qpre		= XrmPermStringToQuark("pre");
 | 
						|
    Qspace		= XrmPermStringToQuark("space");
 | 
						|
    Qtag		= XrmPermStringToQuark("tag");
 | 
						|
    Qul			= XrmPermStringToQuark("ul");
 | 
						|
 | 
						|
    for (i = 0; i < sizeof(tag_info) / sizeof(tag_info[0]); i++)
 | 
						|
	tag_info[i].ident = XrmPermStringToQuark(tag_info[i].name);
 | 
						|
 | 
						|
    initialized = True;
 | 
						|
}
 | 
						|
 | 
						|
/************************************************************************/
 | 
						|
/* PARSE								*/
 | 
						|
/************************************************************************/
 | 
						|
static void
 | 
						|
Html_AddEntities(Html_Parser *parser, Html_Item *item)
 | 
						|
{
 | 
						|
    Html_Item *parent, *next, *child = item->child;
 | 
						|
    XmuSegment segment, *ent;
 | 
						|
    XmuScanline *mask = XmuNewScanline(0, 0, 0);
 | 
						|
    XawTextProperty *tprop, *property = NULL;
 | 
						|
    Widget sink;
 | 
						|
    Bool changed = False;
 | 
						|
 | 
						|
    /* combine properties */
 | 
						|
    if (item->info &&
 | 
						|
	(item->info->entity ||
 | 
						|
	 (item->parent && item->parent->ident != item->parent->info->ident))) {
 | 
						|
	sink = XawTextGetSink(text);
 | 
						|
	parent = item->parent;
 | 
						|
	property = XawTextSinkCopyProperty(sink, item->ident);
 | 
						|
	property->mask = item->info->mask;
 | 
						|
	property->xlfd_mask = item->info->xlfd_mask;
 | 
						|
	if (parent) {
 | 
						|
	    (void)XawTextSinkCombineProperty(sink, property,
 | 
						|
			XawTextSinkGetProperty(sink, parent->ident), False);
 | 
						|
	    if (item->combine && parent->combine)
 | 
						|
		(void)XawTextSinkCombineProperty(sink, item->combine,
 | 
						|
					 	 parent->combine,
 | 
						|
						 item->override);
 | 
						|
	}
 | 
						|
	if (item->combine)
 | 
						|
	    XawTextSinkCombineProperty(sink, property, item->combine, True);
 | 
						|
	tprop = property;
 | 
						|
	property = XawTextSinkAddProperty(sink, property);
 | 
						|
	XtFree((XtPointer)tprop);
 | 
						|
	if (property && item->ident != property->identifier) {
 | 
						|
	    item->ident = property->identifier;
 | 
						|
	    changed = True;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (item->end < 0) {
 | 
						|
	if (item->next)
 | 
						|
	    item->end = item->next->start;
 | 
						|
	else if (item->parent)
 | 
						|
	    item->end = item->parent->end;
 | 
						|
	else
 | 
						|
	    item->end = parser->last;
 | 
						|
    }
 | 
						|
 | 
						|
    while (child) {
 | 
						|
	next = child->next;
 | 
						|
	segment.x1 = child->start;
 | 
						|
	segment.x2 = child->end;
 | 
						|
	(void)XmuScanlineOrSegment(mask, &segment);
 | 
						|
	Html_AddEntities(parser, child);
 | 
						|
	if (child->combine)
 | 
						|
	    XtFree((XtPointer)child->combine);
 | 
						|
	XtFree((XtPointer)child);
 | 
						|
	child = next;
 | 
						|
    }
 | 
						|
 | 
						|
    /* build entity mask */
 | 
						|
    (void)XmuScanlineNot(mask, item->start, item->end);
 | 
						|
    (void)XmuScanlineAnd(mask, parser->mask);
 | 
						|
 | 
						|
    /* add entities */
 | 
						|
    if (item->info && changed) {
 | 
						|
	for (ent = mask->segment; ent; ent = ent->next)
 | 
						|
	    (void)XawTextSourceAddEntity(parser->source, 0, 0, NULL, ent->x1,
 | 
						|
					 ent->x2 - ent->x1, item->ident);
 | 
						|
    }
 | 
						|
    else if (item->info == NULL)
 | 
						|
	(void)XawTextSourceAddEntity(parser->source, 0,
 | 
						|
				     XAW_TENTF_READ | XAW_TENTF_REPLACE,
 | 
						|
				     item->replace, item->start,
 | 
						|
				     item->end - item->start,
 | 
						|
				     item->parent->ident);
 | 
						|
 | 
						|
    /* set mask for parent entities */
 | 
						|
    (void)XmuScanlineOr(parser->mask, mask);
 | 
						|
    XmuDestroyScanline(mask);
 | 
						|
 | 
						|
#if 0
 | 
						|
    if (item->info && item->info->para) {
 | 
						|
	XawTextSourceSetParagraph(parser->source, item->start, item->end,
 | 
						|
				  40,	/* arbitrary value, for testing */
 | 
						|
				  0, 0);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
Html_Commit(Html_Parser *parser)
 | 
						|
{
 | 
						|
    XawTextPosition position;
 | 
						|
    int length;
 | 
						|
 | 
						|
    position = parser->start;
 | 
						|
    length = parser->end - parser->start;
 | 
						|
    if (position < 0) {
 | 
						|
	length += position;
 | 
						|
	position = 0;
 | 
						|
    }
 | 
						|
    if (position + length > parser->last + 1)
 | 
						|
	length -= (position + length) - parser->last + 1;
 | 
						|
 | 
						|
    if (parser->quark != Qdefault && parser->quark != NULLQUARK && length > 0) {
 | 
						|
	XmuSegment segment;
 | 
						|
	Html_Item *head = parser->head;
 | 
						|
	XrmQuark quark = parser->quark;
 | 
						|
 | 
						|
	parser->quark = Qdefault;
 | 
						|
 | 
						|
	if (quark == Qli && head &&
 | 
						|
	    (head->info->ident == Qol || head->info->ident == Qul)) {
 | 
						|
	    if (parser->head == NULL || head->info->ident != Qol)
 | 
						|
		XawTextSourceAddEntity(parser->source, 0, /*XAW_TENT_BULLET,*/
 | 
						|
				       XAW_TENTF_HIDE, NULL,
 | 
						|
				       position, length, Qli);
 | 
						|
	    else
 | 
						|
		XawTextSourceAddEntity(parser->source, 0, /*XAW_TENT_LITEM,*/
 | 
						|
				       XAW_TENTF_HIDE,
 | 
						|
				       (XtPointer)(long)head->li++,
 | 
						|
				       position, length, Qli);
 | 
						|
	}
 | 
						|
	else if (quark == Qhide)
 | 
						|
	    XawTextSourceAddEntity(parser->source, 0, XAW_TENTF_HIDE, NULL,
 | 
						|
				   position, length, quark);
 | 
						|
	else if (quark == Qentity) {
 | 
						|
	    if (head && head->end == -1) {
 | 
						|
		Html_Item *item, *it;
 | 
						|
 | 
						|
		item = XtNew(Html_Item);
 | 
						|
		item->ident = Qentity;
 | 
						|
		item->start = position;
 | 
						|
		item->end = position + length;
 | 
						|
		item->info = NULL;
 | 
						|
		item->combine = NULL;
 | 
						|
		item->override = False;
 | 
						|
		item->replace = (XtPointer)parser->entity;
 | 
						|
		item->child = item->next = NULL;
 | 
						|
 | 
						|
		it = head->child;
 | 
						|
 | 
						|
		item->parent = head;
 | 
						|
		if (it == NULL)
 | 
						|
		    head->child = item;
 | 
						|
		else {
 | 
						|
		    while (it->next)
 | 
						|
			it = it->next;
 | 
						|
		    it->next = item;
 | 
						|
		}
 | 
						|
 | 
						|
		return;
 | 
						|
	    }
 | 
						|
	    XawTextSourceAddEntity(parser->source, 0,
 | 
						|
				   XAW_TENTF_READ | XAW_TENTF_REPLACE,
 | 
						|
				   (XtPointer)parser->entity,
 | 
						|
				   position, length, Qentity);
 | 
						|
	}
 | 
						|
 | 
						|
	segment.x1 = position;
 | 
						|
	segment.x2 = position + length;
 | 
						|
	(void)XmuScanlineOrSegment(parser->mask, &segment);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
Html_ParseTag(Html_Parser *parser)
 | 
						|
{
 | 
						|
    int ch, sz;
 | 
						|
    char buf[32];
 | 
						|
    Html_TagInfo *info;
 | 
						|
    Html_Item *item = NULL;
 | 
						|
    XawTextPosition offset = parser->offset - 1;
 | 
						|
 | 
						|
    switch (Html_Peek(parser)) {
 | 
						|
	case '!':
 | 
						|
	    (void)Html_Get(parser);			/* eat `!' */
 | 
						|
	    if (Html_Peek(parser) == '-') {
 | 
						|
		/* comment */
 | 
						|
		(void)Html_Get(parser);			/* eat `-' */
 | 
						|
		if (Html_Peek(parser) == '-') {
 | 
						|
		    int count = 0;
 | 
						|
 | 
						|
		    (void)Html_Get(parser);
 | 
						|
		    while ((ch = Html_Peek(parser)) != EOF) {
 | 
						|
			if (ch == '>' && count >= 2)
 | 
						|
			    break;
 | 
						|
			else if (ch == '-')
 | 
						|
			    ++count;
 | 
						|
			else
 | 
						|
			    count = 0;
 | 
						|
			(void)Html_Get(parser);
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    break;
 | 
						|
	case '?':
 | 
						|
	    break;
 | 
						|
	case '/':
 | 
						|
	    (void)Html_Get(parser);			/* eat `/' */
 | 
						|
	    sz = 0;
 | 
						|
	    while (isalnum(Html_Peek(parser)) &&
 | 
						|
		   ((sz + 1) < sizeof(buf)))
 | 
						|
		buf[sz++] = tolower(Html_Get(parser));
 | 
						|
	    buf[sz] = '\0';
 | 
						|
	    if ((info = Html_GetInfo(buf)) != NULL) {
 | 
						|
		if (parser->head) {
 | 
						|
		    Html_Item *it = parser->head;
 | 
						|
 | 
						|
		    while (it) {
 | 
						|
			if (it->info == info)
 | 
						|
			    break;
 | 
						|
			it = it->parent;
 | 
						|
		    }
 | 
						|
 | 
						|
		    if (it) {
 | 
						|
			if (it == parser->head)
 | 
						|
			    parser->head->end = offset;
 | 
						|
			else {
 | 
						|
			    it->end = offset;
 | 
						|
			    do {
 | 
						|
				parser->head->end = offset;
 | 
						|
				parser->head = parser->head->parent;
 | 
						|
			    } while (parser->head != it);
 | 
						|
			}
 | 
						|
			if (parser->head->parent)
 | 
						|
			    parser->head = parser->head->parent;
 | 
						|
			else
 | 
						|
			    parser->head = parser->item;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    break;
 | 
						|
	default:
 | 
						|
	    sz = 0;
 | 
						|
	    while (isalnum(Html_Peek(parser)) &&
 | 
						|
		   ((sz + 1) < sizeof(buf)))
 | 
						|
		buf[sz++] = tolower(Html_Get(parser));
 | 
						|
	    buf[sz] = '\0';
 | 
						|
	    if ((info = Html_GetInfo(buf)) != NULL) {
 | 
						|
		if (info->end == False) {
 | 
						|
		    if (info->ident == Qli)
 | 
						|
			parser->quark = Qli;
 | 
						|
		    if (!info->para)
 | 
						|
			break;	/* no more processing required */
 | 
						|
		}
 | 
						|
		item = XtNew(Html_Item);
 | 
						|
		item->info = info;
 | 
						|
		item->ident = item->info->ident;
 | 
						|
		item->combine = NULL;
 | 
						|
		item->override = False;
 | 
						|
		item->start = item->end = -1;
 | 
						|
		if (info->ident == Qol)
 | 
						|
		    item->li = 1;
 | 
						|
		else
 | 
						|
		    item->li = 0;
 | 
						|
		item->parent = item->child = item->next = NULL;
 | 
						|
		if (parser->item == NULL)
 | 
						|
		    parser->item = parser->head = item;
 | 
						|
		else if (parser->head->end == -1) {
 | 
						|
		    if (parser->head->info != item->info || info->nest) {
 | 
						|
			Html_Item *it = parser->head;
 | 
						|
 | 
						|
			/* first, see if we need to close a long list of tags */
 | 
						|
			if (info->ident == Qdd) {
 | 
						|
			    if (parser->head &&
 | 
						|
				parser->head->info->ident == Qdt) {
 | 
						|
				parser->head->end = offset;
 | 
						|
				parser->head = parser->head->parent;
 | 
						|
			    }
 | 
						|
			}
 | 
						|
			else if (info->ident == Qdt) {
 | 
						|
			    if (parser->head &&
 | 
						|
				parser->head->info->ident == Qdd) {
 | 
						|
				parser->head->end = offset;
 | 
						|
				parser->head = parser->head->parent;
 | 
						|
			    }
 | 
						|
			}
 | 
						|
			else if (!info->nest) {
 | 
						|
			    while (it) {
 | 
						|
				if (it->info == info || it->info->end)
 | 
						|
				    break;
 | 
						|
				it = it->parent;
 | 
						|
			    }
 | 
						|
			    if (it) {
 | 
						|
				/* close the items */
 | 
						|
				 while (parser->head != it) {
 | 
						|
				    if (parser->head->info->ident == Qpre)
 | 
						|
					--parser->pre;
 | 
						|
				    parser->head->end = offset;
 | 
						|
				    parser->head = parser->head->parent;
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			}
 | 
						|
 | 
						|
			/* add child item */
 | 
						|
			it = parser->head->child;
 | 
						|
 | 
						|
			item->parent = parser->head;
 | 
						|
			if (it == NULL)
 | 
						|
			    parser->head->child = item;
 | 
						|
			else {
 | 
						|
			    while (it->next)
 | 
						|
				it = it->next;
 | 
						|
			    it->next = item;
 | 
						|
			}
 | 
						|
			parser->head = item;
 | 
						|
		    }
 | 
						|
		    else {
 | 
						|
			/* close the `head' item and start a new one */
 | 
						|
			Html_Item *it;
 | 
						|
 | 
						|
			parser->head->end = offset;
 | 
						|
			if (parser->head->parent)
 | 
						|
			    parser->head = parser->head->parent;
 | 
						|
			else
 | 
						|
			    parser->head = parser->item;
 | 
						|
 | 
						|
			if ((it = parser->head->child) != NULL) {
 | 
						|
			    item->parent = parser->head;
 | 
						|
			    while (it->next)
 | 
						|
				it = it->next;
 | 
						|
			    it->next = item;
 | 
						|
			    parser->head = item;
 | 
						|
			}
 | 
						|
			else {
 | 
						|
			    parser->head->child = item;
 | 
						|
			    parser->head = item;
 | 
						|
			}
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		else {
 | 
						|
		    /* this is not common, but handle it */
 | 
						|
		    Html_Item *it = parser->item;
 | 
						|
 | 
						|
		    while (it->next)
 | 
						|
			it = it->next;
 | 
						|
		    it->next = item;
 | 
						|
		    parser->head = item;
 | 
						|
		}
 | 
						|
		if (info->parse_args)
 | 
						|
		    (info->parse_args)(parser, item);
 | 
						|
	    }
 | 
						|
	    break;
 | 
						|
    }
 | 
						|
 | 
						|
    /* skip anything not processed */
 | 
						|
    while ((ch = Html_Peek(parser)) != '>' && ch != EOF)
 | 
						|
	(void)Html_Get(parser);
 | 
						|
    if (item && item->start == -1)
 | 
						|
	item->start = parser->offset + 1;
 | 
						|
}
 | 
						|
 | 
						|
/* tags */
 | 
						|
static int
 | 
						|
Html_Parse2(Html_Parser *parser)
 | 
						|
{
 | 
						|
    int ch;
 | 
						|
 | 
						|
    for (;;) {
 | 
						|
	if ((ch = Html_Get(parser)) == '<') {
 | 
						|
	    parser->end = parser->offset - 1;
 | 
						|
	    Html_Commit(parser);
 | 
						|
	    parser->quark = Qhide;
 | 
						|
	    parser->start = parser->end;
 | 
						|
 | 
						|
	    Html_ParseTag(parser);
 | 
						|
 | 
						|
	    (void)Html_Get(parser);	/* eat `>' */
 | 
						|
	    parser->end = parser->offset;
 | 
						|
	    Html_Commit(parser);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    return (ch);
 | 
						|
    }
 | 
						|
    /*NOTREACHED*/
 | 
						|
}
 | 
						|
 | 
						|
/* entities */
 | 
						|
static int
 | 
						|
Html_Parse1(Html_Parser *parser)
 | 
						|
{
 | 
						|
    static XawTextBlock *entities[256];
 | 
						|
    static char chars[256];
 | 
						|
    int ch;
 | 
						|
 | 
						|
    for (;;) {
 | 
						|
	if ((ch = Html_Parse2(parser)) == EOF)
 | 
						|
	    return (EOF);
 | 
						|
 | 
						|
	if (ch == '&') {
 | 
						|
	    unsigned char idx = '?';
 | 
						|
	    char buf[32];
 | 
						|
	    int sz = 0;
 | 
						|
 | 
						|
	    /* the string comparisons need a big optmization! */
 | 
						|
	    parser->end = parser->offset - 1;
 | 
						|
	    Html_Commit(parser);
 | 
						|
	    parser->start = parser->end;
 | 
						|
	    while ((ch = Html_Peek(parser)) != ';'
 | 
						|
		   && ch != EOF && !isspace(ch)) {
 | 
						|
		ch = Html_Get(parser);
 | 
						|
		if (sz + 1 < sizeof(buf))
 | 
						|
		    buf[sz++] = ch;
 | 
						|
	    }
 | 
						|
	    buf[sz] = '\0';
 | 
						|
	    if (ch == ';')
 | 
						|
		(void)Html_Get(parser);
 | 
						|
	    if (sz == 0)
 | 
						|
		idx = '&';
 | 
						|
	    else if (strcasecmp(buf, "lt") == 0)
 | 
						|
		idx = '<';
 | 
						|
	    else if (strcasecmp(buf, "gt") == 0)
 | 
						|
		idx = '>';
 | 
						|
	    else if (strcasecmp(buf, "nbsp") == 0)
 | 
						|
		idx = ' ';
 | 
						|
	    else if (strcasecmp(buf, "amp") == 0)
 | 
						|
		idx = '&';
 | 
						|
	    else if (strcasecmp(buf, "quot") == 0)
 | 
						|
		idx = '"';
 | 
						|
	    else if (*buf == '#') {
 | 
						|
		if (sz == 1)
 | 
						|
		    idx = '#';
 | 
						|
		else {
 | 
						|
		    char *tmp;
 | 
						|
 | 
						|
		    idx = strtol(buf + 1, &tmp, 10);
 | 
						|
		    if (*tmp)
 | 
						|
			idx = '?';
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (strcmp(buf + 1, "acute") == 0) {
 | 
						|
		switch (*buf) {
 | 
						|
		    case 'a': idx = 0xe1; break;	case 'e': idx = 0xe9; break;
 | 
						|
		    case 'i': idx = 0xed; break;	case 'o': idx = 0xf3; break;
 | 
						|
		    case 'u': idx = 0xfa; break;	case 'A': idx = 0xc1; break;
 | 
						|
		    case 'E': idx = 0xc9; break;	case 'I': idx = 0xcd; break;
 | 
						|
		    case 'O': idx = 0xd3; break;	case 'U': idx = 0xda; break;
 | 
						|
		    case 'y': idx = 0xfd; break;	case 'Y': idx = 0xdd; break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (strcmp(buf + 1, "grave") == 0) {
 | 
						|
		switch (*buf) {
 | 
						|
		    case 'a': idx = 0xe0; break;	case 'e': idx = 0xe8; break;
 | 
						|
		    case 'i': idx = 0xec; break;	case 'o': idx = 0xf2; break;
 | 
						|
		    case 'u': idx = 0xf9; break;	case 'A': idx = 0xc0; break;
 | 
						|
		    case 'E': idx = 0xc8; break;	case 'I': idx = 0xcc; break;
 | 
						|
		    case 'O': idx = 0xd2; break;	case 'U': idx = 0xd9; break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (strcmp(buf + 1, "tilde") == 0) {
 | 
						|
		switch (*buf) {
 | 
						|
		    case 'a': idx = 0xe3; break;	case 'o': idx = 0xf5; break;
 | 
						|
		    case 'n': idx = 0xf1; break;	case 'A': idx = 0xc3; break;
 | 
						|
		    case 'O': idx = 0xd5; break;	case 'N': idx = 0xd1; break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (strcmp(buf + 1, "circ") == 0) {
 | 
						|
		switch (*buf) {
 | 
						|
		    case 'a': idx = 0xe2; break;	case 'e': idx = 0xea; break;
 | 
						|
		    case 'i': idx = 0xee; break;	case 'o': idx = 0xf4; break;
 | 
						|
		    case 'u': idx = 0xfb; break;	case 'A': idx = 0xc2; break;
 | 
						|
		    case 'E': idx = 0xca; break;	case 'I': idx = 0xce; break;
 | 
						|
		    case 'O': idx = 0xd4; break;	case 'U': idx = 0xdb; break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (strcmp(buf + 1, "uml") == 0) {
 | 
						|
		switch (*buf) {
 | 
						|
		    case 'a': idx = 0xe4; break;	case 'e': idx = 0xeb; break;
 | 
						|
		    case 'i': idx = 0xef; break;	case 'o': idx = 0xf6; break;
 | 
						|
		    case 'u': idx = 0xfc; break;	case 'A': idx = 0xc4; break;
 | 
						|
		    case 'E': idx = 0xcb; break;	case 'I': idx = 0xfc; break;
 | 
						|
		    case 'O': idx = 0xd6; break;	case 'U': idx = 0xdc; break;
 | 
						|
		    case 'y': idx = 0xff; break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (strcmp(buf + 1, "cedil") == 0) {
 | 
						|
		switch (*buf) {
 | 
						|
		    case 'c': idx = 0xe7; break;	case 'C': idx = 0xc7; break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (strcmp(buf + 1, "slash") == 0) {
 | 
						|
		switch (*buf) {
 | 
						|
		    case 'o': idx = 0xf8; break;	case 'O': idx = 0xd8; break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (strcmp(buf + 1, "ring") == 0) {
 | 
						|
		switch (*buf) {
 | 
						|
		    case 'a': idx = 0xe5; break;	case 'A': idx = 0xc5; break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (strcasecmp(buf, "iexcl") == 0)
 | 
						|
		idx = 0xa1;
 | 
						|
	    else if (strcasecmp(buf, "cent") == 0)
 | 
						|
		idx = 0xa2;
 | 
						|
	    else if (strcasecmp(buf, "pound") == 0)
 | 
						|
		idx = 0xa3;
 | 
						|
	    else if (strcasecmp(buf, "curren") == 0)
 | 
						|
		idx = 0xa4;
 | 
						|
	    else if (strcasecmp(buf, "yen") == 0)
 | 
						|
		idx = 0xa5;
 | 
						|
	    else if (strcasecmp(buf, "brvbar") == 0)
 | 
						|
		idx = 0xa6;
 | 
						|
	    else if (strcasecmp(buf, "sect") == 0)
 | 
						|
		idx = 0xa7;
 | 
						|
	    else if (strcasecmp(buf, "uml") == 0)
 | 
						|
		idx = 0xa8;
 | 
						|
	    else if (strcasecmp(buf, "copy") == 0)
 | 
						|
		idx = 0xa9;
 | 
						|
	    else if (strcasecmp(buf, "ordf") == 0)
 | 
						|
		idx = 0xaa;
 | 
						|
	    else if (strcasecmp(buf, "laquo") == 0)
 | 
						|
		idx = 0xab;
 | 
						|
	    else if (strcasecmp(buf, "not") == 0)
 | 
						|
		idx = 0xac;
 | 
						|
	    else if (strcasecmp(buf, "shy") == 0)
 | 
						|
		idx = 0xad;
 | 
						|
	    else if (strcasecmp(buf, "reg") == 0)
 | 
						|
		idx = 0xae;
 | 
						|
	    else if (strcasecmp(buf, "macr") == 0)
 | 
						|
		idx = 0xaf;
 | 
						|
	    else if (strcasecmp(buf, "deg") == 0)
 | 
						|
		idx = 0xb0;
 | 
						|
	    else if (strcasecmp(buf, "plusmn") == 0)
 | 
						|
		idx = 0xb1;
 | 
						|
	    else if (strcasecmp(buf, "sup2") == 0)
 | 
						|
		idx = 0xb2;
 | 
						|
	    else if (strcasecmp(buf, "sup3") == 0)
 | 
						|
		idx = 0xb3;
 | 
						|
	    else if (strcasecmp(buf, "acute") == 0)
 | 
						|
		idx = 0xb4;
 | 
						|
	    else if (strcasecmp(buf, "micro") == 0)
 | 
						|
		idx = 0xb5;
 | 
						|
	    else if (strcasecmp(buf, "para") == 0)
 | 
						|
		idx = 0xb6;
 | 
						|
	    else if (strcasecmp(buf, "middot") == 0)
 | 
						|
		idx = 0xb7;
 | 
						|
	    else if (strcasecmp(buf, "cedil") == 0)
 | 
						|
		idx = 0xb8;
 | 
						|
	    else if (strcasecmp(buf, "supl") == 0)
 | 
						|
		idx = 0xb9;
 | 
						|
	    else if (strcasecmp(buf, "ordm") == 0)
 | 
						|
		idx = 0xba;
 | 
						|
	    else if (strcasecmp(buf, "raquo") == 0)
 | 
						|
		idx = 0xbb;
 | 
						|
	    else if (strcasecmp(buf, "frac14") == 0)
 | 
						|
		idx = 0xbc;
 | 
						|
	    else if (strcasecmp(buf, "frac12") == 0)
 | 
						|
		idx = 0xbd;
 | 
						|
	    else if (strcasecmp(buf, "frac34") == 0)
 | 
						|
		idx = 0xbe;
 | 
						|
	    else if (strcasecmp(buf, "iquest") == 0)
 | 
						|
		idx = 0xbf;
 | 
						|
	    else if (strcasecmp(buf, "AElig") == 0)
 | 
						|
		idx = 0xc6;
 | 
						|
	    else if (strcasecmp(buf, "ETH") == 0)
 | 
						|
		idx = 0xd0;
 | 
						|
	    else if (strcasecmp(buf, "THORN") == 0)
 | 
						|
		idx = 0xde;
 | 
						|
	    else if (strcasecmp(buf, "szlig") == 0)
 | 
						|
		idx = 0xdf;
 | 
						|
	    else if (strcasecmp(buf, "aelig") == 0)
 | 
						|
		idx = 0xe6;
 | 
						|
	    else if (strcasecmp(buf, "eth") == 0)
 | 
						|
		idx = 0xf0;
 | 
						|
	    else if (strcasecmp(buf, "thorn") == 0)
 | 
						|
		idx = 0xfe;
 | 
						|
 | 
						|
	    parser->quark = Qentity;
 | 
						|
	    if (entities[idx] == NULL) {
 | 
						|
		entities[idx] = XtNew(XawTextBlock);
 | 
						|
		entities[idx]->firstPos = 0;
 | 
						|
		entities[idx]->length = 1;
 | 
						|
		entities[idx]->ptr = chars + idx;
 | 
						|
		entities[idx]->format = FMT8BIT;
 | 
						|
		chars[idx] = idx;
 | 
						|
	    }
 | 
						|
	    parser->entity = entities[idx];
 | 
						|
	    parser->end = parser->offset;
 | 
						|
	    Html_Commit(parser);
 | 
						|
	    parser->start = parser->end;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    /*NOTREACHED*/
 | 
						|
}
 | 
						|
 | 
						|
/************************************************************************/
 | 
						|
/* FORMAT								*/
 | 
						|
/************************************************************************/
 | 
						|
static int
 | 
						|
Html_Put(Html_Parser *parser, int ch)
 | 
						|
{
 | 
						|
    if (ch != '\r') {
 | 
						|
	if (parser->replace.length % 4096 == 0)
 | 
						|
	    parser->replace.ptr = XtRealloc(parser->replace.ptr,
 | 
						|
					    parser->replace.length + 4096);
 | 
						|
	parser->replace.ptr[parser->replace.length++] = ch;
 | 
						|
    }
 | 
						|
 | 
						|
    return (ch);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
Html_Puts(Html_Parser *parser, char *str)
 | 
						|
{
 | 
						|
    int len = strlen(str);
 | 
						|
 | 
						|
    if (parser->replace.length % 4096 == 0 ||
 | 
						|
	parser->replace.length + len > parser->replace.length +
 | 
						|
	(4096 - (parser->replace.length % 4096)))
 | 
						|
	parser->replace.ptr = XtRealloc(parser->replace.ptr,
 | 
						|
					parser->replace.length + 4096);
 | 
						|
    memcpy(parser->replace.ptr + parser->replace.length, str, len);
 | 
						|
    parser->replace.length += len;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
Html_FormatTag(Html_Parser *parser)
 | 
						|
{
 | 
						|
    int ch = 0, sz = 0;
 | 
						|
    char buf[32];
 | 
						|
    Html_TagInfo *info = NULL;
 | 
						|
 | 
						|
    switch (Html_Peek(parser)) {
 | 
						|
	case '!':
 | 
						|
	    Html_Put(parser, '<');
 | 
						|
	    Html_Put(parser, Html_Get(parser));		/* eat `!' */
 | 
						|
	    if (Html_Peek(parser) == '-') {
 | 
						|
		/* comment */
 | 
						|
		Html_Put(parser, Html_Get(parser));	/* eat `-' */
 | 
						|
		if (Html_Peek(parser) == '-') {
 | 
						|
		    int count = 0;
 | 
						|
 | 
						|
		    Html_Put(parser, Html_Get(parser));
 | 
						|
		    while ((ch = Html_Peek(parser)) != EOF) {
 | 
						|
			if (ch == '>' && count >= 2)
 | 
						|
			    break;
 | 
						|
			else if (ch == '-')
 | 
						|
			    ++count;
 | 
						|
			else
 | 
						|
			    count = 0;
 | 
						|
			Html_Put(parser, Html_Get(parser));
 | 
						|
		    }
 | 
						|
		    (void)Html_Get(parser);		/* eat `>' */
 | 
						|
		    Html_Put(parser, '>');
 | 
						|
		    return;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    break;
 | 
						|
	case '?':
 | 
						|
	    Html_Put(parser, '<');
 | 
						|
	    break;
 | 
						|
	case '/':
 | 
						|
	    (void)Html_Get(parser);			/* eat `/' */
 | 
						|
	    while (isalnum(Html_Peek(parser)) &&
 | 
						|
		   ((sz + 1) < sizeof(buf)))
 | 
						|
		buf[sz++] = ch = tolower(Html_Get(parser));
 | 
						|
	    buf[sz] = '\0';
 | 
						|
	    if ((info = Html_GetInfo(buf)) != NULL && info->adnl) {
 | 
						|
		if (info->ident == Qpre && parser->pre) {
 | 
						|
		    if (--parser->pre == 0)
 | 
						|
			parser->column = 0;
 | 
						|
		}
 | 
						|
		parser->quark = Qetag;
 | 
						|
		parser->spc = True;
 | 
						|
		if (info->ident == Qp) {
 | 
						|
		    while ((ch = Html_Peek(parser) != '>' && ch != EOF))
 | 
						|
			(void)Html_Get(parser);
 | 
						|
		    (void)Html_Get(parser);		/* eat '>' */
 | 
						|
		    return;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (info) {
 | 
						|
		if (info->ident == Qol || info->ident == Qul) {
 | 
						|
		    if (parser->list && --parser->list == 0 &&
 | 
						|
			parser->desc == 0) {
 | 
						|
			parser->quark = Qetag;
 | 
						|
			Html_Put(parser, '\n');
 | 
						|
			++parser->adnl;
 | 
						|
			parser->column = 0;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		else if (info->ident == Qdl) {
 | 
						|
		    if (parser->desc && --parser->desc == 0 &&
 | 
						|
			parser->list == 0) {
 | 
						|
			parser->quark = Qetag;
 | 
						|
			Html_Put(parser, '\n');
 | 
						|
			++parser->adnl;
 | 
						|
			parser->column = 0;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    Html_Puts(parser, "</");
 | 
						|
	    Html_Puts(parser, buf);
 | 
						|
	    break;
 | 
						|
	default:
 | 
						|
	    while (isalnum(Html_Peek(parser)) &&
 | 
						|
		   ((sz + 1) < sizeof(buf)))
 | 
						|
		buf[sz++] = tolower(Html_Get(parser));
 | 
						|
	    buf[sz] = '\0';
 | 
						|
	    if ((info = Html_GetInfo(buf)) != NULL && info->adnl) {
 | 
						|
		if (info->ident == Qpre)
 | 
						|
		    ++parser->pre;
 | 
						|
		if (parser->quark != Qtag) {
 | 
						|
		    if (parser->adnl < 2) {
 | 
						|
			Html_Puts(parser, parser->adnl ? pnl : nlpnl);
 | 
						|
			parser->adnl = 2;
 | 
						|
			parser->spc = True;
 | 
						|
			parser->column = 0;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		parser->quark = Qtag;
 | 
						|
		if (info->ident == Qp) {
 | 
						|
		    while ((ch = Html_Peek(parser) != '>' && ch != EOF))
 | 
						|
			(void)Html_Get(parser);
 | 
						|
		    (void)Html_Get(parser);		/* eat '>' */
 | 
						|
		    return;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (info) {
 | 
						|
		if (info->ident == Qol || info->ident == Qul) {
 | 
						|
		    if (++parser->list == 1 && !parser->desc) {
 | 
						|
			if (parser->adnl < 2) {
 | 
						|
			    Html_Puts(parser, parser->adnl ? pnl : nlpnl);
 | 
						|
			    parser->adnl = 2;
 | 
						|
			    parser->column = 0;
 | 
						|
			}
 | 
						|
		    }
 | 
						|
		    else if (parser->adnl == 0) {
 | 
						|
			Html_Put(parser, '\n');
 | 
						|
			parser->adnl = 1;
 | 
						|
			parser->column = 0;
 | 
						|
		    }
 | 
						|
		    parser->spc = True;
 | 
						|
		}
 | 
						|
		else if (info->ident == Qli) {
 | 
						|
		    if (parser->adnl == 0) {
 | 
						|
			Html_Put(parser, '\n');
 | 
						|
			parser->adnl = 1;
 | 
						|
			parser->column = 0;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
 | 
						|
		else if (info->ident == Qdl) {
 | 
						|
		    if (++parser->desc == 1 && !parser->list) {
 | 
						|
			if (parser->adnl < 2) {
 | 
						|
			    Html_Puts(parser, parser->adnl ? pnl : nlpnl);
 | 
						|
			    parser->adnl = 2;
 | 
						|
			    parser->column = 0;
 | 
						|
			}
 | 
						|
		    }
 | 
						|
		    else if (parser->adnl == 0) {
 | 
						|
			Html_Put(parser, '\n');
 | 
						|
			parser->adnl = 1;
 | 
						|
			parser->column = 0;
 | 
						|
		    }
 | 
						|
		    parser->spc = True;
 | 
						|
		}
 | 
						|
		else if (info->ident == Qdd) {
 | 
						|
		    if (parser->desc == 0) {
 | 
						|
			if (parser->adnl < 2) {
 | 
						|
			    Html_Puts(parser, parser->adnl ? pnl : nlpnl);
 | 
						|
			    parser->adnl = 2;
 | 
						|
			    parser->column = 0;
 | 
						|
			}
 | 
						|
		    }
 | 
						|
		    else if (parser->adnl == 0) {
 | 
						|
			Html_Put(parser, '\n');
 | 
						|
			parser->adnl = 1;
 | 
						|
			parser->column = 0;
 | 
						|
		    }
 | 
						|
		    parser->spc = True;
 | 
						|
		}
 | 
						|
		else if (info->ident == Qdt) {
 | 
						|
		    if (parser->adnl == 0) {
 | 
						|
			Html_Put(parser, '\n');
 | 
						|
			parser->adnl = 1;
 | 
						|
			parser->spc = True;
 | 
						|
			parser->column = 0;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    Html_Put(parser, '<');
 | 
						|
	    Html_Puts(parser, buf);
 | 
						|
	    break;
 | 
						|
    }
 | 
						|
 | 
						|
    sz = 0;
 | 
						|
    while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
 | 
						|
	if (isspace(ch)) {
 | 
						|
	    (void)Html_Get(parser);
 | 
						|
	    ++sz;
 | 
						|
	    continue;
 | 
						|
	}
 | 
						|
	else if (sz) {
 | 
						|
	    Html_Put(parser, ' ');
 | 
						|
	    sz = 0;
 | 
						|
	}
 | 
						|
	Html_Put(parser, Html_Get(parser));
 | 
						|
    }
 | 
						|
    Html_Put(parser, Html_Get(parser));			/* eat `>' */
 | 
						|
    if (info && info->ident == Qbr) {
 | 
						|
	++parser->adnl;
 | 
						|
	parser->spc = True;
 | 
						|
	Html_Put(parser, '\n');
 | 
						|
	parser->quark = info->ident;
 | 
						|
	parser->column = 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* tags */
 | 
						|
static int
 | 
						|
Html_Format3(Html_Parser *parser)
 | 
						|
{
 | 
						|
    int ch;
 | 
						|
 | 
						|
    for (;;) {
 | 
						|
	if ((ch = Html_Get(parser)) == '<') {
 | 
						|
	    if (parser->quark == Qspace && parser->spc == False) {
 | 
						|
		Html_Put(parser, ' ');
 | 
						|
		parser->spc = True;
 | 
						|
	    }
 | 
						|
 | 
						|
/*	    parser->quark = Qhide;*/
 | 
						|
	    Html_FormatTag(parser);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    return (ch);
 | 
						|
    }
 | 
						|
    /*NOTREACHED*/
 | 
						|
}
 | 
						|
 | 
						|
/* entities */
 | 
						|
static int
 | 
						|
Html_Format2(Html_Parser *parser)
 | 
						|
{
 | 
						|
    int ch;
 | 
						|
 | 
						|
    for (ch = Html_Format3(parser); ch == '&'; ch = Html_Format3(parser)) {
 | 
						|
	Html_Put(parser, '&');
 | 
						|
	while ((ch = Html_Peek(parser)) != ';') {
 | 
						|
	    if (isspace(ch) || ch == EOF)
 | 
						|
		break;
 | 
						|
	    Html_Put(parser, Html_Get(parser));
 | 
						|
	}
 | 
						|
	if (ch != EOF)
 | 
						|
	    Html_Put(parser, Html_Get(parser));
 | 
						|
	else
 | 
						|
	    break;
 | 
						|
	if (parser->pre)
 | 
						|
	    ++parser->column;
 | 
						|
    }
 | 
						|
 | 
						|
    return (ch);
 | 
						|
}
 | 
						|
 | 
						|
/* spaces */
 | 
						|
static int
 | 
						|
Html_Format1(Html_Parser *parser)
 | 
						|
{
 | 
						|
    int ch;
 | 
						|
 | 
						|
    for (;;) {
 | 
						|
	if ((ch = Html_Format2(parser)) == EOF)
 | 
						|
	    return (ch);
 | 
						|
 | 
						|
	if (parser->quark == Qetag) {
 | 
						|
	    if (parser->adnl < 2) {
 | 
						|
		Html_Puts(parser, parser->adnl ? pnl : nlpnl);
 | 
						|
		parser->adnl = 2;
 | 
						|
		parser->spc = True;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else if (parser->quark == Qspace && parser->spc == False) {
 | 
						|
	    Html_Put(parser, ' ');
 | 
						|
	    parser->spc = True;
 | 
						|
	}
 | 
						|
 | 
						|
	if (!parser->pre && isspace(ch))
 | 
						|
	    parser->quark = Qspace;
 | 
						|
	else {
 | 
						|
	    if (parser->pre) {
 | 
						|
		if (parser->spc) {
 | 
						|
		    /* did not yet see any non space character */
 | 
						|
		    if (isspace(ch)) {
 | 
						|
			if (ch == '\n') {
 | 
						|
			    parser->column = 0;
 | 
						|
			    parser->spc = False;
 | 
						|
			    parser->adnl = 1;
 | 
						|
			}
 | 
						|
			else if (ch == '\t')
 | 
						|
			    parser->column += 8 - (parser->column % 8);
 | 
						|
			else
 | 
						|
			    ++parser->column;
 | 
						|
			continue;
 | 
						|
		    }
 | 
						|
		    else {
 | 
						|
			int column = parser->column;
 | 
						|
 | 
						|
			while (column-- > 0)
 | 
						|
			    Html_Put(parser, ' ');
 | 
						|
			parser->spc = False;
 | 
						|
			parser->adnl = 0;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		else if (ch == '\n') {
 | 
						|
		    ++parser->adnl;
 | 
						|
		    parser->column = 0;
 | 
						|
		}
 | 
						|
		else if (ch == '\t') {
 | 
						|
		    int column = parser->column + (8 - (parser->column % 8));
 | 
						|
 | 
						|
		    parser->adnl = 0;
 | 
						|
		    while (parser->column < column) {
 | 
						|
			Html_Put(parser, ' ');
 | 
						|
			++parser->column;
 | 
						|
		    }
 | 
						|
		    continue;
 | 
						|
		}
 | 
						|
		else {
 | 
						|
		    parser->adnl = 0;
 | 
						|
		    ++parser->column;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
		parser->adnl = 0;
 | 
						|
	    Html_Put(parser, ch);
 | 
						|
	    parser->quark = Qdefault;
 | 
						|
	    parser->spc = False;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/************************************************************************/
 | 
						|
/* ARGUMENTS								*/
 | 
						|
/************************************************************************/
 | 
						|
static void
 | 
						|
Html_AArgs(Html_Parser *parser, Html_Item *item)
 | 
						|
{
 | 
						|
    int ch, sz;
 | 
						|
    char buf[32];
 | 
						|
 | 
						|
    /*CONSTCOND*/
 | 
						|
    while (True) {
 | 
						|
	sz = 0;
 | 
						|
	while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
 | 
						|
	    if (isalnum(ch))
 | 
						|
		break;
 | 
						|
	    else
 | 
						|
		(void)Html_Get(parser);
 | 
						|
	}
 | 
						|
 | 
						|
	if (ch == '>' || ch == EOF)
 | 
						|
	    return;
 | 
						|
	buf[sz++] = tolower(Html_Get(parser));
 | 
						|
	while ((ch = Html_Peek(parser)) != '>' && ch != EOF)
 | 
						|
	    if (isalnum(ch))
 | 
						|
		buf[sz++] = tolower(Html_Get(parser));
 | 
						|
	    else
 | 
						|
		break;
 | 
						|
	buf[sz] = '\0';
 | 
						|
	if (strcmp(buf, "href") == 0) {
 | 
						|
	    item->combine = XawTextSinkCopyProperty(XawTextGetSink(text),
 | 
						|
						    item->info->ident);
 | 
						|
	    item->override = True;
 | 
						|
	    item->combine->xlfd_mask = 0L;
 | 
						|
	    item->combine->mask = XAW_TPROP_UNDERLINE | XAW_TPROP_FOREGROUND;
 | 
						|
	    item->combine->foreground = parser->alink;
 | 
						|
	    return;
 | 
						|
	}
 | 
						|
	while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
 | 
						|
	    if (isspace(ch))
 | 
						|
		break;
 | 
						|
	    else
 | 
						|
		(void)Html_Get(parser);
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
Html_FontArgs(Html_Parser *parser, Html_Item *item)
 | 
						|
{
 | 
						|
    int ch, sz;
 | 
						|
    char name[32], value[256], xlfd[128];
 | 
						|
 | 
						|
    item->combine = XawTextSinkCopyProperty(XawTextGetSink(text),
 | 
						|
					    Qdefault);
 | 
						|
    item->override = True;
 | 
						|
    item->combine->mask = item->combine->xlfd_mask = 0L;
 | 
						|
 | 
						|
    /*CONSTCOND*/
 | 
						|
    while (True) {
 | 
						|
	/* skip white spaces */
 | 
						|
	while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
 | 
						|
	    if (isalnum(ch))
 | 
						|
		break;
 | 
						|
	    else
 | 
						|
		(void)Html_Get(parser);
 | 
						|
	}
 | 
						|
 | 
						|
	if (ch == '>' || ch == EOF)
 | 
						|
	    return;
 | 
						|
 | 
						|
	/* read option name */
 | 
						|
	sz = 0;
 | 
						|
	name[sz++] = tolower(Html_Get(parser));
 | 
						|
	while ((ch = Html_Peek(parser)) != '>' && ch != EOF)
 | 
						|
	    if (isalnum(ch) && (sz + 1 < sizeof(name)))
 | 
						|
		name[sz++] = tolower(Html_Get(parser));
 | 
						|
	    else
 | 
						|
		break;
 | 
						|
	name[sz] = '\0';
 | 
						|
 | 
						|
	if (ch != '=')
 | 
						|
	    continue;
 | 
						|
	(void)Html_Get(parser);	/* skip `=' */
 | 
						|
	if (Html_Peek(parser) == '"')
 | 
						|
	    (void)Html_Get(parser);
 | 
						|
 | 
						|
	sz = 0;
 | 
						|
	while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
 | 
						|
	    if (!isspace(ch) && (sz + 1 < sizeof(value)))
 | 
						|
		value[sz++] = Html_Get(parser);
 | 
						|
	    else
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	value[sz] = '\0';
 | 
						|
	if (sz > 0 && value[sz - 1] == '"')
 | 
						|
	    value[--sz] = '\0';
 | 
						|
 | 
						|
	if (strcmp(name, "color") == 0) {
 | 
						|
	    XColor  color, exact;
 | 
						|
 | 
						|
	    if (XAllocNamedColor(XtDisplay(toplevel), toplevel->core.colormap,
 | 
						|
				 value, &color, &exact)) {
 | 
						|
		item->combine->mask |= XAW_TPROP_FOREGROUND;
 | 
						|
		item->combine->foreground = color.pixel;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else if (strcmp(name, "face") == 0) {
 | 
						|
	    int count = 0;
 | 
						|
	    char *ptr, *family, **font_list;
 | 
						|
 | 
						|
	    ptr = value;
 | 
						|
	    do {
 | 
						|
		family = ptr;
 | 
						|
		ptr = strchr(ptr, ',');
 | 
						|
		if (ptr)
 | 
						|
		    *ptr++ = '\0';
 | 
						|
		XmuSnprintf(xlfd, sizeof(xlfd), "-*-%s-*-*-*-*-*-*-*-*-*-*-*-*",
 | 
						|
			    family);
 | 
						|
		font_list = XListFonts(XtDisplay(toplevel), xlfd, 1, &count);
 | 
						|
		if (font_list)
 | 
						|
		    XFreeFontNames(font_list);
 | 
						|
		if (count)
 | 
						|
		    break;
 | 
						|
	    } while (ptr);
 | 
						|
	    if (count) {
 | 
						|
		item->combine->xlfd_mask |= XAW_TPROP_FAMILY;
 | 
						|
		item->combine->family = XrmStringToQuark(family);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else if (strcmp(name, "size") == 0) {
 | 
						|
	    int size, sign = 0;
 | 
						|
 | 
						|
	    if (isalnum(*value)) {
 | 
						|
		size = atoi(value);
 | 
						|
		sign = 0;
 | 
						|
	    }
 | 
						|
	    else {
 | 
						|
		char *str = XrmQuarkToString(item->combine->pixel_size);
 | 
						|
 | 
						|
		size = str ? atoi(str) : 12;
 | 
						|
		if (*value == '+') {
 | 
						|
		    size += atoi(value + 1);
 | 
						|
		    sign = 1;
 | 
						|
		}
 | 
						|
		else if (*value == '-') {
 | 
						|
		    size -= atoi(value + 1);
 | 
						|
		    sign = -1;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 | 
						|
	    if (item->combine->xlfd != NULLQUARK) {
 | 
						|
		int count, ucount, dcount, usize, dsize;
 | 
						|
		char **current, **result, **up, **down;
 | 
						|
 | 
						|
		current = result = up = down = NULL;
 | 
						|
		/* try to load an appropriate font */
 | 
						|
		XmuSnprintf(value, sizeof(value),
 | 
						|
			    "-*-%s-%s-%s-*--%%d-*-*-*-*-*-%s-%s",
 | 
						|
			    XrmQuarkToString(item->combine->family),
 | 
						|
			    XrmQuarkToString(item->combine->weight),
 | 
						|
			    XrmQuarkToString(item->combine->slant),
 | 
						|
			    XrmQuarkToString(item->combine->registry),
 | 
						|
			    XrmQuarkToString(item->combine->encoding));
 | 
						|
		XmuSnprintf(xlfd, sizeof(xlfd), value,
 | 
						|
			    atoi(XrmQuarkToString(item->combine->pixel_size)));
 | 
						|
		current = XListFonts(XtDisplay(toplevel), xlfd, 1, &count);
 | 
						|
		if (count) {
 | 
						|
		    ucount = dcount = usize = dsize = 0;
 | 
						|
 | 
						|
		    XmuSnprintf(xlfd, sizeof(xlfd), value, size);
 | 
						|
		    result = XListFonts(XtDisplay(toplevel), xlfd, 1, &count);
 | 
						|
		    if (count == 0 || strstr(*result, "-0-")) {
 | 
						|
			if (sign <= 0) {
 | 
						|
			    sz = dsize = size;
 | 
						|
			    while (dcount == 0 && --sz > size - 8 && sz > 1) {
 | 
						|
				XmuSnprintf(xlfd, sizeof(xlfd), value, sz);
 | 
						|
				down = XListFonts(XtDisplay(toplevel), xlfd,
 | 
						|
						  1, &dcount);
 | 
						|
				if (dcount && strstr(*down, "-0-") != NULL) {
 | 
						|
				    XFreeFontNames(down);
 | 
						|
				    down = NULL;
 | 
						|
				    dcount = 0;
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			    if (dcount)
 | 
						|
				dsize = sz;
 | 
						|
			}
 | 
						|
			if (sign >= 0) {
 | 
						|
			    sz = usize = size;
 | 
						|
			    while (ucount == 0 && ++sz < size + 8) {
 | 
						|
				XmuSnprintf(xlfd, sizeof(xlfd), value, sz);
 | 
						|
				up = XListFonts(XtDisplay(toplevel), xlfd,
 | 
						|
						1, &ucount);
 | 
						|
				if (ucount && strstr(*up, "-0-") != NULL) {
 | 
						|
				    XFreeFontNames(up);
 | 
						|
				    up = NULL;
 | 
						|
				    ucount = 0;
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			    if (ucount)
 | 
						|
				usize = sz;
 | 
						|
			}
 | 
						|
			if (ucount && dcount)
 | 
						|
			    size = size - dsize < usize - size ? dsize : usize;
 | 
						|
			else if (ucount)
 | 
						|
			    size = usize;
 | 
						|
			else if (dcount)
 | 
						|
			    size = dsize;
 | 
						|
		    }
 | 
						|
		    if (current)
 | 
						|
			XFreeFontNames(current);
 | 
						|
		    if (result)
 | 
						|
			XFreeFontNames(result);
 | 
						|
		    if (up)
 | 
						|
			XFreeFontNames(up);
 | 
						|
		    if (down)
 | 
						|
			XFreeFontNames(down);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 | 
						|
	    XmuSnprintf(value, sizeof(value), "%d", size);
 | 
						|
	    item->combine->xlfd_mask |= XAW_TPROP_PIXELSIZE;
 | 
						|
	    item->combine->pixel_size = XrmStringToQuark(value);
 | 
						|
	}
 | 
						|
 | 
						|
	while ((ch = Html_Peek(parser)) != '>' && ch != EOF) {
 | 
						|
	    if (isspace(ch))
 | 
						|
		break;
 | 
						|
	    else
 | 
						|
		(void)Html_Get(parser);
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 |