/* html.c - display code for html
This file contains the code for displaying HTML documents, scrolling them
and dealing with hypertext jumps by recognising which buttons are clicked.
*/
/*
Janne Saarela
janne.saarela@hut.fi
28.7.1995
The SEQTEXT element in the PaintStream has the additional
attribute, emph, of width of two bytes.
The handling of different emph attributes is not finalized.
I tried using < and > symbols from the adobe symbol font
but they do not seem to work properly. OVERHAT, OVERDOT,
OVERDDOT and OVERTILDE are to be implemented.
*/
#include
#include
#include
#include "www.h"
#include "tools.h"
#include "forms.h"
#include "style.h"
extern Display *display;
extern int screen;
extern Window win;
extern GC disp_gc, gc_fill;
extern Cursor hourglass;
extern int UsePaper;
extern Context *context;
extern int ExposeCount;
extern int debug; /* controls display of errors */
/*extern int document; */ /* HTML_DOCUMENT or TEXT_DOCUMENT */
extern int busy;
extern int OpenURL;
extern int IsIndex;
extern int FindStr;
extern char *FindNextStr;
extern int SaveFile;
extern int sbar_width;
extern int statusHeight;
extern int ToolBarHeight;
extern unsigned long windowColor;
extern unsigned int win_width, win_height, tileWidth, tileHeight;
extern unsigned long textColor, labelColor, windowTopShadow,
strikeColor, windowBottomShadow, windowShadow, windowColor;
extern unsigned long stdcmap[128]; /* 2/3/2 color maps for gifs etc */
extern unsigned long greymap[16]; /* for mixing with unsaturated colors */
extern int depth;
extern Form *forms;
Byte color_text_ix, color_background_ix;
/*
The current top line is displayed at the top of the window,the pixel
offset is the number of pixels from the start of the document.
*/
extern char *buffer; /* the start of the document buffer */
extern long PixelOffset; /* the pixel offset to top of window */
extern int hdrlen; /* MIME header length at start of buffer */
extern long buf_height;
extern long lineHeight;
extern long chDescent;
extern int buf_width;
extern int PixelIndent;
extern int chStrike;
extern int spWidth; /* width of space char */
extern int chWidth; /* width of average char */
extern Doc *CurrentDoc;
extern XFontStruct *pFontInfo;
extern XFontStruct *Fonts[FONTS];
extern int LineSpacing[FONTS], BaseLine[FONTS], StrikeLine[FONTS];
extern int LineThickness[FONTS];
extern int ListIndent1, ListIndent2;
extern char *LastBufPtr, *StartOfLine, *StartOfWord; /* in HTML document */
extern char *bufptr; /* parse position in the HTML buffer */
extern Byte *TopObject; /* first visible object in window */
extern Byte *paint; /* holds the sequence of paint commands */
extern int paintbufsize; /* size of buffer, not its contents */
extern int paintlen; /* where to add next entry */
extern Field *focus;
extern int font; /* index into Fonts[] array */
int preformatted;
XRectangle displayRect; /* clipping limits for painting html */
long IdOffset; /* offset for targetId */
char *targetptr; /* for toggling view between HTML/TEXT views */
char *targetId; /* for locating named Id during ParseHTML() */
/* globals associated with detecting which object is under the mouse */
char *anchor_start, *anchor_end;
Byte *clicked_element;
int img_dx, img_dy;
/* the background frame structure specifies:
a) where to start painting in this frame
b) where this frame ends in paint buffer
c) tree of nested frames which all
intersect the top of the window
*/
Frame background;
/* copy line from str to LineBuf, skipping initial spaces and SGML */
char *CopyLine(char *str, unsigned int len)
{
int c, n, k;
char *p;
static char buf[1024];
if (len == 0)
return "";
p = buf;
while (len-- > 0)
{
c = *str;
if (c == '\0')
break;
while (c == '<' && ((n = str[1]) == '!' || n == '?' || n == '/' || isalpha(n)))
{
/* howcome 28/8/95: added code from Michael Van Biesbrouck
to handle comments */
if (strncmp(str+1, "!--", 3) == 0){
str = FindEndComment( str + 2 );
if (*str) str++;
} else {
while (*str++ != '>');
}
c = *str;
}
if (c == '&' && (isalnum(str[1]) || str[1] == '#')) /* howcome 25/11/94: isalpha -> isalnum */
{
n = entity(str + 1, &k);
if (n)
{
/* TokenValue = n; */
str += k;
*p++ = n;
continue;
}
}
if (preformatted)
{
if (c == '\t')
{
n = 8 - (p - buf)%8;
if (n > 0)
++len;
while (n-- > 0)
{
*p++ = ' ';
--len;
}
}
else
*p++ = c;
++str;
continue;
}
if (IsWhite(c))
{
do
c = *++str;
while (IsWhite(c));
*p++ = c = ' ';
continue;
}
*p++ = c;
++str;
}
*p = '\0';
return buf;
}
void PrintFrameData(int depth, Frame *frame)
{
int i;
while (frame)
{
for (i = 0; i < depth; ++i)
printf(" ");
printf("x = %d, y = %ld; w = %d, h = %ld size = %d, info at %d\n",
frame->indent, frame->offset, frame->width, frame->height, frame->length, frame->info);
PrintFrameData(depth+1, frame->child);
frame = frame->next;
}
}
void PrintFrame(Frame *frame)
{
PrintFrameData(1, frame);
}
void PrintObject(unsigned char *p)
{
int tag, emph, fnt, x1, yi, len, width;
unsigned int c1, c2;
long offset, str;
char *s;
BG_Style *bg_style;
tag = *p++;
if ((tag & 0xF) == STRING)
{
c1 = *p++; c2 = *p++; emph = c1 | c2<<8;
fnt = *p++;
#ifdef STYLE_COLOR
color_text_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
bg_style=(BG_Style *)GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
if(bg_style)
color_background_ix = (bg_style->flag & S_BACKGROUND_COLOR) ? rgb2ix(0, bg_style->r, bg_style->g, bg_style->b,0) : 255; /* GRR */
else
color_background_ix = 255;
#endif
yi = *p++ - 128;
c1 = *p++; c2 = *p++; x1 = (c1 | c2<<8); /* here */
c1 = *p++; c2 = *p++; len = c1 | c2<<8;
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
str = (long) GetPointer(&p);
p += POINTERSIZE;
preformatted = (tag & PRE_TEXT);
s = CopyLine((char *)str, len);
printf("string: \"%s\"\n", s);
}
else
{
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
printf("tag = %d, offset = %ld\n", tag, offset);
}
}
void OpenDoc(char *name)
{
/* janet 21/07/95: not used: char *p, *q; */
/* janet 21/07/95: not used: long wh, target; */
OpenURL = 0;
FindNextStr = 0;
/* XDefineCursor(display, win, hourglass);*/
/* XFlush(display);*/
if (name) /* attempt to get new document */
{
/* note current status string */
SaveStatusString();
/* quit Open, SaveAs or Find if active */
OpenURL = SaveFile = FindStr = 0;
libGetDocument(name, strlen(name), NULL, TRUE, FALSE, TRUE, FALSE, FALSE);
}
}
void PostDoc(char *name, char *post)
{
OpenURL = 0;
FindNextStr = 0;
/* XDefineCursor(display, win, hourglass);*/
/* XFlush(display);*/
if (name && post) /* attempt to get new document */
{
/* note current status string */
SaveStatusString();
/* quit Open, SaveAs or Find if active */
OpenURL = SaveFile = FindStr = 0;
libPostDocument(name, strlen(name), post, strlen(post));
}
}
void ReloadDoc(char *name)
{
/* janet 21/07/95: not used: char *p, *q; */
/* janet 21/07/95; not used: long wh, target; */
OpenURL = 0;
FindNextStr = 0;
/* XDefineCursor(display, win, hourglass);*/
/* XFlush(display);*/
if (name) /* attempt to get new document */
{
/* note current status string */
SaveStatusString();
/* quit Open, SaveAs or Find if active */
OpenURL = SaveFile = FindStr = 0;
/* free style sheets */
if (CurrentDoc->style != context->style) {
FreeStyleSheet(CurrentDoc->style);
CurrentDoc->style = NULL;
} else {
FreeStyleSheet(CurrentDoc->style);
CurrentDoc->style = NULL;
context->style = StyleGetInit();
}
Free(CurrentDoc->head_style);
Free(CurrentDoc->link_style);
libGetDocument(name, strlen(name), NULL, TRUE, FALSE, FALSE, TRUE, FALSE);
}
}
/* find title text as defined by title text */
#define MAXTITLE 128
char *TitleText(char *buf)
{
return "Dummy Title";
}
/*
The global unsigned (char *)TopObject points to
the paint stream and is adjusted to the first object
that appears at the top of the window for an offset
of h pixels from the start of the document.
This involves a search thru the paint stream, and
relies on the objects being ordered wrt increasing
pixel offset from the start of the document.
The paint stream is organised as a sequence of nested
frames, intermingled with text lines.
The procedure returns the pixel difference between
the desired position and the current position.
*/
Frame *FrameForward(Frame *frame, long top);
Frame *FrameBackward(Frame *frame, long top);
long DeltaHTMLPosition(long h)
{
long delta; /* janet 21/07/95; not used: offset, TopOffset */
/* janet 21/07/95; not used: Byte *p, *q; */
/* janet 21/07/95; not used: int tag, c1, c2, k; */
/* janet 21/09/95: not used: Frame *frame; */
if (h > PixelOffset) /* search forwards */
FrameForward(&background, h);
else if (h == 0) /* shortcut to start */
{
FreeFrames(background.child);
background.child = NULL;
background.top = paint + FRAMESTLEN;
}
else /* search backwards */
FrameBackward(&background, h);
delta = h - PixelOffset;
PixelOffset = h;
return delta;
}
/*
Move forwards thru frame, adjusting frame->top to last text line
before top. The routine iterates thru peer frames and recurses
thru decendent frames. The frame (and its descendents) are removed
from the peer list if it (and therefore they) finish before top.
This is implemented by returning the frame if it is needed otherwise
returning NULL
Question: what happens when top is the bottom of the buffer?
can this ever occur in practice, e.g. with a null file?
*/
Frame *FrameForward(Frame *frame, long top)
{
long offset, height;
unsigned int c1, c2;
unsigned int width, length, len;
int tag, indent, style, border;
unsigned char *p, *p2, *obj;
Frame *peer, *child, *last;
#ifdef STYLE_COLOR_BORDER
Byte cb_ix;
#endif
if (!frame)
return NULL;
/* move down each of peer frames */
peer = FrameForward(frame->next, top);
/* Does this frame and its descendants end before top ? */
if (frame->offset + frame->height <= top)
{
if (frame == &background) /* should never occur in practice! */
{
FreeFrames(background.child);
background.child = NULL;
background.top = paint + paintlen;
return &background; /* never has peers ! */
}
/* remove self and any descendents BUT not our peers! */
frame->next = NULL; /* unlink from list before freeing */
FreeFrames(frame);
frame = NULL;
return peer;
}
frame->next = peer;
frame->child = FrameForward(frame->child, top);
/* find last child in list to avoid inserting
new children in reverse order */
for (last = frame->child; last; last = last->next)
{
if (last->next == NULL)
break;
}
/* now move frame->top down until we reach top and insert
any new children at end of frame->child list */
p = frame->top;
p2 = paint + frame->info + FRAMESTLEN + frame->length;
while (p < p2)
{
obj = p;
tag = *p++;
/* if frame intersects top then create frame structure
and find paint position within it (and its children)
then insert it in front of frame->child list */
if (tag == BEGIN_FRAME)
{
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
if (offset > top)
{
frame->top = obj;
break;
}
/* otherwise pickup frame header params */
c1 = *p++; c2 = *p++; indent = c1 | c2<<8;
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
c1 = *p++; c2 = *p++; height = c1 | c2<<8;
c1 = *p++; c2 = *p++; height |= (c1 | c2<<8) << 16;
style = *p++; border = *p++;
#ifdef STYLE_COLOR_BORDER
cb_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
#endif
c1 = *p++; c2 = *p++; length = c1 | c2<<8;
if (offset + height > top)
{
child = (Frame *)malloc(sizeof(Frame));
child->next = NULL;
child->child = NULL;
child->offset = offset;
child->indent = indent;
child->width = width;
child->height = height;
child->info = obj - paint;
child->top = p; /* == obj + FRAMESTLEN */
child->length = length;
child->style = style;
child->border = border;
child->box_list = NULL;
#ifdef STYLE_COLOR_BORDER
child->cb_ix = cb_ix;
#else
child->cb_ix = 0;
#endif
FrameForward(child, top);
/* and insert new child in same order
as it appears in paint buffer */
if (last)
last->next = child;
else
frame->child = child;
last = child;
}
p += length+2; /* to skip over frame's contents */
continue;
}
/* the END_FRAME is only used when scrolling backwards */
if (tag == END_FRAME)
{
p += FRAMENDLEN - 1;
continue;
}
/* safety net for garbled paint structure */
if (tag != TEXTLINE)
{
fprintf(stderr, "Unexpected internal tag (1) %d\n", tag);
Exit(1);
}
/* stop if textline overlaps top or starts after it */
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
if (offset >= top)
{
frame->top = obj;
break;
}
p += 4; /* skip over baseline, indent */
c1 = *p++; c2 = *p++; height = c1 | c2<<8;
if (offset + height > top)
{
frame->top = obj;
break;
}
/* skip elements in text line to reach next object */
while ((tag = *p++) != '\0')
{
switch (tag & 0xF)
{
case RULE:
p += RULEFLEN - 1;
break;
case LINE:
p += LINEFLEN - 1;
break;
case BULLET:
p += BULLETFLEN - 1;
break;
case STRING:
p += STRINGFLEN - 1;
break;
case SEQTEXT:
++p; ++p; /* skip over emph */
++p; /* skip over font */
#ifdef STYLE_COLOR
++p; /* skip over color */
#endif
#ifdef STYLE_BACKGROUND
p+=POINTERSIZE; /* skip over background --Spif 18-Oct-95 */
#endif
++p; ++p; /* skip over x position */
++p; ++p; /* skip over y position */
len = *p++;
p += len;
break;
case IMAGE:
p += IMAGEFLEN - 1;
break;
case INPUT:
p += INPUTFLEN - 1;
break;
default:
fprintf(stderr, "Unexpected internal tag (2) %d\n", tag);
/* Exit(1); */
}
}
++p; ++p; /* skip over textline size param */
}
return frame;
}
/*
Move backwards thru frame, adjusting frame->top to last text line
before top. The routine iterates thru peer frames and recurses
thru decendent frames. The frame (and its descendents) are removed
from the peer list if it (and therefore they) start at or after top.
This is implemented by returning the frame if it is needed otherwise
returning NULL
*/
Frame *FrameBackward(Frame *frame, long top)
{
long offset, height;
unsigned int c1, c2;
unsigned int width, length, size; /* janet 21/07/95: not used: len */
int tag, indent, style, border, k, known;
unsigned char *p, *p1, *p2, *obj;
Frame *peer, *child;
#ifdef STYLE_COLOR_BORDER
Byte cb_ix;
#endif
if (!frame)
return NULL;
/* if this frame starts after top then remove from peer list */
if (frame->offset >= top)
{
if (frame == &background)
{
FreeFrames(background.child);
background.child = NULL;
background.top = paint + paintlen;
return &background; /* never has peers ! */
}
peer = frame->next;
frame->next = NULL; /* unlink from list before freeing */
FreeFrames(frame);
frame = NULL;
return FrameBackward(peer, top);
}
/* move backwards through peer frames */
frame->next = FrameBackward(frame->next, top);
/* move backwards through current children */
frame->child = FrameBackward(frame->child, top);
/* now move frame->top back until we reach top and insert
any new children in front of frame->child list */
p = TopObject = frame->top;
p2 = paint + frame->info + FRAMESTLEN;
while (p > p2)
{
/* pop field size into k */
c2 = *--p; c1 = *--p; k = c1 | c2<<8;
p -= k; /* p points to start of previous object */
obj = p;
tag = *p++;
if (tag == BEGIN_FRAME)
{
--p;
continue;
}
/* if frame intersects top then create frame structure
unless it already is one of my children and find
paint position within it (and its children)
then insert it in front of frame->child list */
if (tag == END_FRAME)
{
c1 = *p++; c2 = *p++; length = c1 | c2<<8;
c1 = *p++; c2 = *p++; size = c1 | c2<<8;
p = obj - (int)length; /* kludge for bug in HP92453-01 A.09.19 HP C Compiler */
/* p now points to BEGIN_FRAME tag */
if (*p != BEGIN_FRAME)
{
fprintf(stderr, "FrameBackward: Unexpected internal tag %d when BEGIN_FRAME was expected\n", tag);
Exit(1);
}
p1 = p;
/* check if frame is one of my children, and hence already done */
for (known = 0, child = frame->child; child; child = child->next)
{
if (child->info == p - paint)
{
known = 1;
break;
}
}
if (known)
{
p = obj;
continue;
}
++p; /* skip over frame tag */
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
if (offset >= top)
{
p = obj;
continue;
}
/* otherwise pickup frame header params */
c1 = *p++; c2 = *p++; indent = c1 | c2<<8;
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
c1 = *p++; c2 = *p++; height = c1 | c2<<8;
c1 = *p++; c2 = *p++; height |= (c1 | c2<<8) << 16;
style = *p++; border = *p++;
#ifdef STYLE_COLOR_BORDER
cb_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
#endif
c1 = *p++; c2 = *p++; length = c1 | c2<<8;
child = (Frame *)malloc(sizeof(Frame));
child->next = NULL;
child->child = NULL;
child->offset = offset;
child->indent = indent;
child->width = width;
child->height = height;
child->info = p1 - paint;
child->top = p + length;
child->length = length;
child->style = style;
child->border = border;
child->box_list = NULL;
#ifdef STYLE_COLOR_BORDER
child->cb_ix = cb_ix;
#else
child->cb_ix = 0;
#endif
child = FrameBackward(child, top);
/* and insert new child in front of current children */
child->next = frame->child;
frame->child = child;
p = obj;
continue;
}
/* safety net for garbled paint structure */
if (tag != TEXTLINE)
{
fprintf(stderr, "FrameBackward: Unexpected internal tag: %d when TEXTLINE was expected\n", tag);
Exit(1);
}
/* stop if textline overlaps top or starts before it */
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
p = obj;
if (offset < top)
break;
}
frame->top = p;
return frame;
}
void DrawHButtonUp(int x, int y, int w, int h)
{
--x; ++y; ++w; /* adjust drawing position */
XSetForeground(display, disp_gc, windowTopShadow);
XFillRectangle(display, win, disp_gc, x, y, w, 1);
XFillRectangle(display, win, disp_gc, x, y, 1, h-1);
XSetForeground(display, disp_gc, windowBottomShadow);
XFillRectangle(display, win, disp_gc, x+1, y+h-1, w-1, 1);
XFillRectangle(display, win, disp_gc, x+w-1, y+1, 1, h-2);
XSetForeground(display, disp_gc, textColor);
}
void DrawHButtonDown(int x, int y, int w, int h)
{
--x; ++y; ++w; /* adjust drawing position */
XSetForeground(display, disp_gc, windowBottomShadow);
XFillRectangle(display, win, disp_gc, x, y, w, 1);
XFillRectangle(display, win, disp_gc, x, y, 1, h-1);
XSetForeground(display, disp_gc, windowTopShadow);
XFillRectangle(display, win, disp_gc, x+1, y+h-1, w-1, 1);
XFillRectangle(display, win, disp_gc, x+w-1, y+1, 1, h-2);
XSetForeground(display, disp_gc, textColor);
}
/* Find which object if any is under the mouse at screen coords px, py
event is one of BUTTONUP, BUTTONDOWN, MOVEUP, MOVEDOWN */
Byte *WhichFrameObject(int event, int indent, int x, int y, Byte *p1, Byte *p2,
int *type, char **start, char **end, int *dx, int *dy)
{
char *s;
Byte *p, *q;
unsigned int tag, len, emph;
unsigned int c1, c2;
int fnt, x1, y1, xi, yb, yi, y2, width, height; /* janet 21/07/95: not used: action, active */
int style, border, length;
long offset, str;
BG_Style *bg_style;
#ifdef STYLE_COLOR_BORDER
Byte cb_ix;
#endif
int i; /* for debug only */
/* x += PixelIndent; */ /* howcome: applied patch from dsr 18/11/94 */
for (p = p1; p < p2;)
{
tag = *p++;
if (tag == BEGIN_FRAME)
{
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
/* we are done if frame starts after bottom of window */
y1 = WinTop + (offset - PixelOffset);
if (y1 >= WinBottom)
break;
/* otherwise pickup frame header params */
c1 = *p++; c2 = *p++; x1 = c1 | c2<<8;
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
c1 = *p++; c2 = *p++; height = c1 | c2<<8;
c1 = *p++; c2 = *p++; height |= (c1 | c2<<8) << 16;
style = *p++; border = *p++;
#ifdef STYLE_COLOR_BORDER
cb_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
#endif
c1 = *p++; c2 = *p++; length = c1 | c2<<8;
/* call self to find target object in this frame */
q = WhichFrameObject(event, x1, x /* - x1 */, y, p, p + length, /* howcome 25/1/95 */
type, start, end, dx, dy);
if (q)
return q;
p += length+2; /* to skip over frame's contents */
continue;
}
if (tag == END_FRAME)
{
p += FRAMENDLEN - 1;
continue;
}
if (tag != TEXTLINE)
{
fprintf(stderr, "Unexpected internal tag (4) %d\n", tag);
Exit(1);
}
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
/* y1 points to top of line */
y1 = WinTop + (offset - PixelOffset);
if (y1 > (int) WinBottom)
break;
c1 = *p++; c2 = *p++; yb = y1 + (c1 | c2<<8);
c1 = *p++; c2 = *p++; xi = indent + (c1 | c2<<8);
c1 = *p++; c2 = *p++; height = (c1 | c2<<8);
while ((tag = *p++) != '\0')
{
switch (tag & 0xF)
{
case RULE:
p += RULEFLEN - 1;
break;
case LINE:
p += LINEFLEN - 1;
break;
case BULLET:
p += BULLETFLEN - 1;
break;
case STRING:
c1 = *p++; c2 = *p++; emph = c1 | c2<<8;
fnt = *p++;
#ifdef STYLE_COLOR
color_text_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
bg_style=(BG_Style *)GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
if (bg_style)
color_background_ix = (bg_style->flag & S_BACKGROUND_COLOR) ? rgb2ix(0, bg_style->r, bg_style->g, bg_style->b,0) : 255; /* GRR */
else
color_background_ix = 255;
#endif
yi = *p++ - 128;
c1 = *p++; c2 = *p++; x1 = xi + (c1 | c2<<8); /* here */
c1 = *p++; c2 = *p++; len = c1 | c2<<8;
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
p += POINTERSIZE;
str = (long)GetPointer(&p); /* only reference */
height = LineSpacing[fnt];
y2 = yb - yi - ASCENT(fnt) - 1;
if ((emph & EMPH_ANCHOR) && x1 <= x && y2 <= y &&
x < x1 + width && y < y2 + height)
{
s = (char *)str;
while (s > buffer)
{
--s;
if (s[0] == '<' && TOLOWER(s[1]) == 'a' && s[2] <= ' ')
break;
}
*start = s; /* used in next stage */
s = (char *)str;
while (strncasecmp(s, "", 4) != 0)
{
if (*s == '\0')
break;
++s;
}
*end = s; /* used in next stage */
*dx = *dy = -1;
*type = TAG_ANCHOR;
/* return pointer to start of anchor object */
return p - STRINGFLEN;
}
break;
case SEQTEXT:
p++; p++; /* skip over emph */
p++; /* skip over font */ /* janet: what about putting *p += 3 here? */
#ifdef STYLE_COLOR
++p; /* skip over color */ /* janet p += 2 */
#endif
#ifdef STYLE_BACKGROUND
p+=POINTERSIZE; /* skip over the background --Spif 18-Oct-95 */
#endif
++p; ++p; /* skip over x position */
++p; ++p; /* skip over y position */ /* janet: p += 4 */
len = *p++;
p += len;
break;
case IMAGE:
c1 = *p++; c2 = *p++; y2 = yb - (c1 | c2<<8); /* delta */
c1 = *p++; c2 = *p++; x1 = xi + (c1 | c2<<8); /* here */
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
c1 = *p++; c2 = *p++; height = c1 | c2<<8;
if (x1 <= x && y2 <= y && x < x1 + width && y < y2 + height)
{
p += POINTERSIZE; /* past pixmap */
str = (long) GetPointer(&p);
#ifdef STYLE_BACKGROUND
GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
#endif
if (tag & EMPH_ANCHOR)
{
*dx = *dy = -1;
if ((tag & EMPH_INPUT) == EMPH_INPUT) /* --Spif image input */
{ /* can be removed, as INPUT is ANCHOR || ISMAP... */
*dx = x - x1;
*dy = y - y2;
}
else
{
if (tag & ISMAP)
{
*dx = x - x1;
*dy = y - y2;
};
};
s = (char *)str;
if ((tag & EMPH_INPUT) == EMPH_INPUT) /* --Spif 10-Oct-95 */
{
while (s > buffer) /* find input...*/
{
--s;
if ( strncasecmp(s, "')
{
if (*s == '\0')
break;
s++;
}
*end = s;
*type = TAG_INPUT; /* ?? */
return p - IMAGEFLEN;
}
else
{
while (s > buffer) /* find anchor... must also find an input...*/
{
--s;
if (s[0] == '<' && TOLOWER(s[1]) == 'a' && s[2] <= ' ')
break;
}
*start = s; /* used in next stage */
s = (char *)str;
while (strncasecmp(s, "", 4) != 0)
{
if (*s == '\0')
break;
++s;
}
*end = s; /* used in next stage */
*type = TAG_ANCHOR;
return p - IMAGEFLEN;
}
}
else
{
if (tag & ISMAP)
{
*dx = x - x1;
*dy = y - y2;
*start = (char *)str;
*end = (char *)str;
*type = TAG_IMG;
return p - IMAGEFLEN;
}
}
}
else
{
p += 2 * POINTERSIZE; /* past pixmap and buf pointer */
#ifdef STYLE_BACKGROUND
p += POINTERSIZE;
#endif
}
break;
case INPUT: /* --Spif only text... */
ClipToWindow();
str = (long) GetPointer(&p);
#ifdef STYLE_BACKGROUND
GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
#endif
if (ClickedInField(disp_gc, xi, yb, (Field *)str, x, y, event))
{
s = ((Field *)str)->name; /* updating *start --Spif 14-Oct-95 */
while (s > buffer)
{
if ( strncasecmp(s, "') s++;
*end = s;
*type = TAG_INPUT;
return (p - INPUTFLEN);
};
break;
default:
fprintf(stderr, "Unexpected internal tag (5) %d\n", tag);
Exit(1);
}
}
++p; ++p; /* skip final frame length field */ /* janet: p += 2? , and: is this ever used? */
}
return NULL;
}
/* find which hypertext button contains given point */
Byte *WhichObj(Frame *frame, int event, int x, int y,
int *type, char **start, char **end, int *dx, int *dy)
{
Byte *p, *q;
Frame *peer;
if (frame->child)
{
p = WhichObj(frame->child, event, x, y, type, start, end, dx, dy);
if (p)
return p;
}
for (peer = frame->next; peer; peer = peer->next)
{
p = WhichObj(peer, event, x, y, type, start, end, dx, dy);
if (p)
return p;
}
p = frame->top;
q = paint + frame->info + FRAMESTLEN + frame->length;
x += PixelIndent; /* howcome: applied patch from dsr 18/11/94 */
return WhichFrameObject(event, frame->indent, x, y, p, q, type, start, end, dx, dy);
}
/* find which hypertext button contains given point */
Byte *WhichObject(int event, int x, int y,
int *type, char **start, char **end, int *dx, int *dy)
{
if (focus && focus->type == OPTIONLIST &&
focus->flags & CHECKED &&
ClickedInDropDown(disp_gc, focus, -1, event, x, y))
{
*type = TAG_SELECT;
*start = *end = focus->name;
return paint + focus->object;
}
return WhichObj(&background, event, x, y, type, start, end, dx, dy);
}
/* drawn anchors in designated state */
void DrawFrameAnchor(int up, int indent, Byte *start, Byte *end)
{
char *s;
Byte *p;
unsigned int tag, len, emph;
unsigned int c1, c2;
int fnt, x1, y1, xi, y2, yi, yb, width, height; /* janet 21/07/95: not used: action*/
int style, border, length;
long offset, str;
BG_Style *bg_style;
#ifdef STYLE_COLOR_BORDER
Byte cb_ix;
#endif
displayRect.x = WinLeft;
displayRect.y = WinTop;
displayRect.width = WinWidth;
displayRect.height = WinHeight;
XSetClipRectangles(display, disp_gc, 0, 0, &displayRect, 1, Unsorted);
for (p = start; p < end;)
{
tag = *p++;
if (tag == BEGIN_FRAME)
{
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
/* we are done if frame starts after bottom of window */
y1 = WinTop + (offset - PixelOffset);
if (y1 >= WinBottom)
break;
/* otherwise pickup frame header params */
c1 = *p++; c2 = *p++; x1 = c1 | c2<<8;
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
c1 = *p++; c2 = *p++; height = c1 | c2<<8;
c1 = *p++; c2 = *p++; height |= (c1 | c2<<8) << 16;
style = *p++; border = *p++;
#ifdef STYLE_COLOR_BORDER
cb_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
bg_style = (BG_Style *)GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
#endif
c1 = *p++; c2 = *p++; length = c1 | c2<<8;
/* call self to draw anchors in this frame */
DrawFrameAnchor(up, x1, p, p + length);
p += length+2; /* to skip over frame's contents */
continue;
}
if (tag == END_FRAME)
{
p += FRAMENDLEN - 1;
continue;
}
if (tag != TEXTLINE)
{
fprintf(stderr, "Unexpected internal tag (6) %d\n", tag);
Exit(1);
}
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
/* y1 points to top of line */
y1 = WinTop + (offset - PixelOffset);
if (y1 > (int) WinBottom)
break;
c1 = *p++; c2 = *p++; yb = y1 + (c1 | c2<<8);
c1 = *p++; c2 = *p++; xi = (c1 | c2<<8) - PixelIndent;
c1 = *p++; c2 = *p++; height = (c1 | c2<<8);
xi += indent;
while ((tag = *p++) != '\0')
{
switch (tag & 0xF)
{
case RULE:
p += RULEFLEN - 1;
break;
case LINE:
p += LINEFLEN - 1;
break;
case BULLET:
p += BULLETFLEN - 1;
break;
case STRING:
c1 = *p++; c2 = *p++; emph = c1 | c2<<8;
fnt = *p++;
#ifdef STYLE_COLOR
color_text_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
bg_style=(BG_Style *)GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
if(bg_style)
color_background_ix = (bg_style->flag & S_BACKGROUND_COLOR) ? rgb2ix(0, bg_style->r, bg_style->g, bg_style->b,0) : 255; /* GRR */
else
color_background_ix = 255;
#endif
yi = *p++ - 128;
c1 = *p++; c2 = *p++; x1 = xi + (c1 | c2<<8); /* here */
c1 = *p++; c2 = *p++; len = c1 | c2<<8;
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
str = (long)GetPointer(&p);
p += POINTERSIZE; /* skip the reference pointer */
#ifdef STYLE_COLOR
font = fnt;
SetColor(disp_gc, color_text_ix, color_background_ix);
SetFont(disp_gc, font);
#else
if (font != fnt)
{
font = fnt;
SetFont(disp_gc, font);
}
#endif
height = LineSpacing[font];
y2 = yb - yi - ASCENT(font) - 1;
if (emph & EMPH_ANCHOR)
{
s = (char *)str;
if (anchor_start <= s && s <= anchor_end)
{
if (up)
DrawHButtonUp(x1, y2, width, height);
else
DrawHButtonDown(x1, y2, width, height);
}
}
break;
case SEQTEXT:
p++; p++; /* skip over emph */
p++; /* skip over font */ /* janet: what about putting *p += 3 here? */
#ifdef STYLE_COLOR
++p; /* skip over color */ /* janet p += 2 */
#endif
#ifdef STYLE_BACKGROUND
p+=POINTERSIZE; /* skip over background */
#endif
++p; ++p; /* skip over x position */
++p; ++p; /* skip over y position */ /* janet: p += 4 */
len = *p++;
p += len;
break;
case IMAGE:
c1 = *p++; c2 = *p++; y2 = yb - (c1 | c2<<8);
c1 = *p++; c2 = *p++; x1 = xi + (c1 | c2<<8); /* here */
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
c1 = *p++; c2 = *p++; height = c1 | c2<<8;
p += POINTERSIZE; /* past pixmap id */
s = (char *)GetPointer(&p);
#ifdef STYLE_BACKGROUND
p += POINTERSIZE; /* skip background */
#endif
if (tag & ISMAP && anchor_start == s)
{
x1 -= PixelIndent;
if (up)
{
DrawOutSet(win, disp_gc, x1, y2, width, height);
XSetForeground(display, disp_gc, textColor);
DrawHButtonDown(x1+4, y2+2, width-7, height-6);
}
else
{
DrawInSet(win, disp_gc, x1, y2, width, height);
XSetForeground(display, disp_gc, textColor);
DrawHButtonUp(x1+4, y2+2, width-7, height-6);
}
width -= 8;
height -= 8;
x1 += 4;
y2 += 4;
}
break;
case INPUT:
/* --Spif 13-Oct-95 take care of this...it may be the cause of crashes */
p += INPUTFLEN - 1;
break;
default:
fprintf(stderr, "Unexpected internal tag (7) %d\n", tag);
Exit(1);
}
}
++p; ++p; /* skip final frame length field */
}
XFlush(display);
}
void DrawAnchor(Frame *frame, int state)
{
Byte *start, *end;
Frame *peer;
if (frame->child)
DrawAnchor(frame->child, state);
for (peer = frame->next; peer; peer = peer->next)
DrawAnchor(peer, state);
start = frame->top;
end = paint + frame->info + FRAMESTLEN + frame->length;
DrawFrameAnchor(state, frame->indent, start, end);
}
/* find topmost object's pointer to the html buffer */
char *TopStrSelf(Byte *start, Byte *end)
{
Byte *p;
char *s;
unsigned int tag, len, emph, fnt;
unsigned int c1, c2;
int style, border, length, x1, y1, xi, yb, yi, width, height; /* janet 21/07/95: not used: action, y2 */
long offset, str;
#ifdef STYLE_COLOR_BORDER
Byte cb_ix;
#endif
for (p = start; p < end;)
{
tag = *p++;
if (tag == BEGIN_FRAME)
{
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
c1 = *p++; c2 = *p++; x1 = c1 | c2<<8;
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
c1 = *p++; c2 = *p++; height = c1 | c2<<8;
c1 = *p++; c2 = *p++; height |= (c1 | c2<<8) << 16;
style = *p++; border = *p++;
#ifdef STYLE_COLOR_BORDER
cb_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
#endif
c1 = *p++; c2 = *p++; length = c1 | c2<<8;
if ((s = TopStrSelf(p, p + length)))
return s;
p += length+2; /* to skip over frame's contents */
continue;
}
if (tag == END_FRAME)
{
p += FRAMENDLEN - 1;
continue;
}
if (tag != TEXTLINE)
{
fprintf(stderr, "Unexpected internal tag (8) %d\n", tag);
Exit(1);
}
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
/* y1 points to top of line */
y1 = WinTop + (offset - PixelOffset);
if (y1 > (int) WinBottom)
break;
c1 = *p++; c2 = *p++; yb = y1 + (c1 | c2<<8);
c1 = *p++; c2 = *p++; xi = (c1 | c2<<8);
c1 = *p++; c2 = *p++; height = (c1 | c2<<8);
while ((tag = *p++) != '\0')
{
switch (tag & 0xF)
{
case RULE:
p += RULEFLEN - 1;
break;
case LINE:
p += LINEFLEN - 1;
break;
case BULLET:
p += BULLETFLEN - 1;
break;
case STRING:
c1 = *p++; c2 = *p++; emph = c1 | c2<<8;
fnt = *p++;
#ifdef STYLE_COLOR
p++; /* skip over color */
#endif
#ifdef STYLE_BACKGROUND
p+=POINTERSIZE; /* --Spif 20-Oct-95 skip over style background */
#endif
yi = *p++ - 128;
c1 = *p++; c2 = *p++; x1 = xi + (c1 | c2<<8); /* here */
c1 = *p++; c2 = *p++; len = c1 | c2<<8;
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
p += POINTERSIZE;
str = (long)GetPointer(&p);
return (char *)str; /* return (char *)GetPointer(&p); ??? */
case SEQTEXT:
++p; ++p; /* skip over emph */
++p; /* skip over font */
#ifdef STYLE_COLOR
++p; /* skip over color */
#endif
#ifdef STYLE_BACKGROUND
p+=POINTERSIZE; /* skip over background -_Spif 20-Oct-95 */
#endif
++p; ++p; /* skip over x position */
++p; ++p; /* skip over y position */
len = *p++;
p += len;
break;
case IMAGE:
p += IMAGEFLEN - 1;
break;
case INPUT:
p += INPUTFLEN - 1;
break;
default:
fprintf(stderr, "Unexpected internal tag (9) %d\n", tag);
Exit(1);
}
}
++p; ++p; /* skip final frame length field */ /* janet: p += 2? , and: is this ever used? */
}
return NULL;
}
char *TopStr(Frame *frame)
{
Frame *peer;
char *s;
Byte *start, *end;
if (frame->child && (s = TopStr(frame->child)))
return s;
for (peer = frame->next; peer; peer = peer->next)
if ((s = TopStr(peer)))
return s;
start = frame->top;
end = paint + frame->info + FRAMESTLEN + frame->length;
return TopStrSelf(start, end);
}
void ClipToWindow(void)
{
displayRect.x = WinLeft;
displayRect.y = WinTop;
displayRect.width = WinWidth;
displayRect.height = WinHeight;
XSetClipRectangles(display, disp_gc, 0, 0, &displayRect, 1, Unsorted);
/* XSetClipRectangles(display, gc_fill, 0, 0, &displayRect, 1, Unsorted); -- tracking */
}
void DrawBorder(int border, int x, int y, unsigned int w, unsigned int h, Byte cb_ix)
{
#ifdef STYLE_COLOR_BORDER
if (cb_ix < 128) {
XSetForeground(display, disp_gc, stdcmap[cb_ix]);
} else if (cb_ix < 144) {
XSetForeground(display, disp_gc, greymap[cb_ix & 0xf]);
}
#endif
XFillRectangle(display, win, disp_gc, x, y, w, 1);
XFillRectangle(display, win, disp_gc, x+w, y, 1, h);
XFillRectangle(display, win, disp_gc, x, y+h, w, 1);
XFillRectangle(display, win, disp_gc, x, y, 1, h);
}
void FreeBox(box_link *box_list)
{
box_link *current_link;
box_link *next_link;
if(!box_list)
return;
current_link = box_list;
next_link = box_list->next;
while(next_link)
{
Free(current_link->box);
Free(current_link);
current_link = next_link;
next_link = next_link->next;
}
Free(current_link->box);
Free(current_link);
}
/* free frame structures except for background frame */
void FreeFrames(Frame *frame)
{
/* janet 21/07/95 Frame *peer; */
if (frame)
{
/*
patch from Kai.Arstila@Helsinki.FI replaces
FreeFrames(frame->child);
for (peer = frame->next; peer; peer = peer->next)
FreeFrames(peer);
Free(frame);
with:
*/
if(frame->child)
{
FreeFrames(frame->child);
frame->child = NULL;
}
if(frame->next)
{
FreeFrames(frame->next);
frame->next = NULL;
}
FreeBox(frame->box_list);
Free(frame);
/* end replacement */
}
}
void PaintSelf(Frame *frame, int y, unsigned int h);
void PaintPeers(Frame *frame, int y, unsigned int h);
void PaintFrame(Window w,unsigned char *p, unsigned char *p_end, int x, int y, unsigned int h);
void DisplayHTML(int x, int y, unsigned int w, unsigned int h)
{
long count = 0;
BG_Style *bg_style;
unsigned char *p;
GC gc_bg;
XGCValues values;
unsigned int valuemask;
XRectangle frameRect;
if (UsePaper)
XSetTSOrigin(display, gc_fill,
-PixelIndent % tileHeight, -(int)(PixelOffset % tileHeight));
/* make absolutely certain we don't overwrite the scrollbar */
if (w > WinWidth)
w = WinWidth;
if (y < WinTop)
{
h -= (WinTop - y);
y = WinTop;
if (h <= 0)
return;
}
/* make absolutely certain we don't overwrite the status bar */
if (y + h > WinBottom)
{
h = WinBottom - y;
if (h <= 0)
return;
}
/* the text must be clipped to avoid running over into adjacent
regions, i.e. the scrollbar at the rhs */
displayRect.x = x;
displayRect.y = y;
displayRect.width = w;
displayRect.height = h;
XSetClipRectangles(display, disp_gc, 0, 0, &displayRect, 1, Unsorted);
XSetClipRectangles(display, gc_fill, 0, 0, &displayRect, 1, Unsorted);
/* howcome 25/4/95 */
FormatElementStart(TAG_HTML, NULL, 0);
#ifdef STYLE_BACKGROUND
p = paint + 15; /* --Spif 25-Oct-95 offset to style_bckng pointer */
bg_style=(BG_Style *)GetPointer(&p);
if(bg_style)
{
if(bg_style->flag & S_BACKGROUND_COLOR) /* background color */
{
/* if(!((bg_style->image) && (bg_style->flag & S_BACKGROUND_X_REPEAT) && (bg_style->flag & S_BACKGROUND_Y_REPEAT)))
*/{
XSetForeground(display, disp_gc, rgb2color(0, bg_style->r, bg_style->g, bg_style->b,0));
XFillRectangle(display, win, disp_gc, x,y,w,h);
}
}
else
XFillRectangle(display, win, gc_fill, x,y,w,h);
if(bg_style->flag & S_BACKGROUND_IMAGE) /* background image */
{
if(bg_style->image)
{
gc_bg = XCreateGC(display, win,0,NULL);
XCopyGC(display,gc_fill,0xFFFF,gc_bg);
valuemask = GCTile|GCFillStyle|GCTileStipXOrigin|GCTileStipYOrigin;
values.fill_style = FillTiled;
values.tile = bg_style->image->pixmap;
if(bg_style->flag & S_BACKGROUND_ORIGIN)
{
if(bg_style->flag & S_BACKGROUND_FIXED)
{
values.ts_x_origin = bg_style->x_pos*(WinWidth-bg_style->image->width)/100;
values.ts_y_origin = bg_style->y_pos*(WinHeight-bg_style->image->height)/100 + WinTop;
}
else
{
values.ts_x_origin = bg_style->x_pos*(WinWidth-bg_style->image->width)/100 -PixelIndent;
values.ts_y_origin = bg_style->y_pos*(WinHeight-bg_style->image->height)/100 + WinTop - PixelOffset;
};
}
else
{
if(bg_style->flag & S_BACKGROUND_FIXED)
{
values.ts_x_origin = 0;
values.ts_y_origin = WinTop;
}
else
{
values.ts_x_origin = -PixelIndent;
values.ts_y_origin = WinTop - PixelOffset;
}
}
XChangeGC(display, gc_bg, valuemask, &values);
if(bg_style->flag & S_BACKGROUND_Y_REPEAT)
{
frameRect.y = WinTop;
frameRect.height = WinHeight;
}
else
{
frameRect.y = values.ts_y_origin;
frameRect.height = bg_style->image->height;
}
if(bg_style->flag & S_BACKGROUND_X_REPEAT)
{
frameRect.x = WinLeft;
frameRect.width = WinWidth;
}
else
{
frameRect.x = values.ts_x_origin;
frameRect.width = bg_style->image->width;
}
XSetClipRectangles(display, gc_bg, 0, 0,&frameRect, 1, Unsorted);
XFillRectangle(display, win, gc_bg, x, y, w, h);
XFreeGC(display, gc_bg);
}
else
if(!(bg_style->flag & (S_BACKGROUND_COLOR))) /* use paper if no pixmap and color */
XFillRectangle(display, win, gc_fill, x, y, w, h);
}
if(!(bg_style->flag & (S_BACKGROUND_COLOR |S_BACKGROUND_IMAGE)))
XFillRectangle(display, win, gc_fill, x, y, w, h);
} else
XFillRectangle(display, win, gc_fill, x, y, w, h);
#else
count = StyleGet(S_BACKGROUND);
if (count == 255) { /* i.e. is the background transparent? */
XFillRectangle(display, win, gc_fill, x, y, w, h);
} else {
XSetForeground(display, disp_gc, ix2color(count));
XSetFillStyle(display, disp_gc, FillSolid);
XFillRectangle(display, win, disp_gc, x, y, w, h);
}
#endif
FormatElementEnd();
/* and paint all frames intersecting top of window */
PaintSelf(&background, y, h);
if (focus && focus->type == OPTIONLIST && focus->flags & CHECKED)
PaintDropDown(disp_gc, focus, -1);
}
/* paint children then self - first called for background frame */
void PaintSelf(Frame *frame, int y, unsigned int h)
{
long y1;
unsigned char *p1, *p2;
/* Test that this frame is at least partly visible */
y1 = PixelOffset + y - WinTop; /* pixel offset for screen coord y */
if (frame->offset < y1 + h && frame->offset + frame->height > y1)
{
if (frame->child)
PaintPeers(frame->child, y, h);
if (frame->border)
{
DrawBorder(frame->border, frame->indent-PixelIndent,
WinTop + (frame->offset - PixelOffset),
frame->width, frame->height, frame->cb_ix);
}
if (TAG_TRACE)
#if defined PRINTF_HAS_PFORMAT
fprintf(stderr,"html.c: PaintSelf p1 = frame->top = %p, info = %d, lenght = %d\n",
#else
fprintf(stderr,"html.c: PaintSelf p1 = frame->top = %lx, info = %d, lenght = %d\n",
#endif /* PRINTF_HAS_PFORMAT */
frame->top, frame->info, frame->length);
p1 = frame->top;
p2 = paint + frame->info + FRAMESTLEN + frame->length;
PaintFrame(win,p1, p2, frame->indent, y, h);
}
}
/* paint list of peer frames */
void PaintPeers(Frame *frame, int y, unsigned int h)
{
while (frame)
{
PaintSelf(frame, y, h);
frame = frame->next;
}
}
/*
p, p_end point to paint buffer while x,y,w,h define region to paint
This routine recursively calls itself to paint nested frames when
it comes across the BEGIN_FRAME tag. Note that the border for the
current frame is already drawn - and saves having to pass the
relevant params to this routine.
*/
void PaintFrame(Window w,unsigned char *p, unsigned char *p_end, int x, int y, unsigned int h)
{
char *s;
unsigned int tag, len, width;
unsigned int c1, c2;
int fnt, fnt_size, x1, y1, x2, y2, xi, yb, yi, depth, tmp; /* janet 21/07/95: not used: action, active */
unsigned int emph;
int style, border, length;
long offset, height, str;
BG_Style *bg_style;
#ifdef STYLE_COLOR_BORDER
Byte cb_ix;
#endif
GC gc_bg = NULL;
XGCValues values;
unsigned int valuemask;
Pixmap bg_pixmap = (Pixmap)NULL;
XRectangle frameRect,bgRect;
int dirtyscroll;
dirtyscroll=0;
displayRect.x = WinLeft;
displayRect.y = WinTop;
displayRect.width = WinWidth;
displayRect.height = WinHeight;
if (TAG_TRACE)
#if defined PRINTF_HAS_PFORMAT
fprintf(stderr,"html.c: PaintFrame %p\n",p);
#else
fprintf(stderr,"html.c: PaintFrame %lx\n",p);
#endif /* PRINTF_HAS_PFORMAT */
while (p < p_end)
{
if (p >= paint + paintlen)
{
fprintf(stderr, "Panic: ran off end of paint buffer!\n");
Exit(1);
}
if (TAG_TRACE && VERBOSE_TRACE)
#if defined PRINTF_HAS_PFORMAT
fprintf(stderr,"PaintFrame: tag %d read from %p, p_end = %p\n",*p, p, p_end);
#else
fprintf(stderr,"PaintFrame: tag %d read from %lx, p_end = %lx\n",*p, p, p_end);
#endif /* PRINTF_HAS_PFORMAT */
tag = *p++;
if (tag == BEGIN_FRAME)
{
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
/* we are done if frame starts after bottom of window */
y1 = WinTop + (offset - PixelOffset);
/*
if (y1 >= y + (int)h)
break;
*/
/* otherwise pickup frame header params */
c1 = *p++; c2 = *p++; x1 = c1 | c2<<8;
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
c1 = *p++; c2 = *p++; height = c1 | c2<<8;
c1 = *p++; c2 = *p++; height |= (c1 | c2<<8) << 16;
style = *p++; border = *p++;
#ifdef STYLE_COLOR_BORDER
cb_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
bg_style=(BG_Style *)GetPointer(&p);
if(bg_style)
{
if(bg_style->flag & S_BACKGROUND_COLOR) /* background color */
{
XSetForeground(display, disp_gc, rgb2color(0, bg_style->r, bg_style->g, bg_style->b,0));
if(bg_style->flag & S_BACKGROUND_IMAGE)
{
if(!((bg_style->image) && (bg_style->flag & S_BACKGROUND_X_REPEAT) && (bg_style->flag & S_BACKGROUND_Y_REPEAT)))
XFillRectangle(display, w, disp_gc,x1-PixelIndent, y1 , width, height);
}
else
XFillRectangle(display, w, disp_gc,x1-PixelIndent, y1 , width, height);
}
if(bg_style->flag & S_BACKGROUND_IMAGE) /* bacground image */
{
if(bg_style->image)
{
dirtyscroll = 1;
frameRect.x = x1;
frameRect.y = y1;
frameRect.width = (frameRect.x+width < WinLeft+WinWidth) ? width : width+x-frameRect.x;
frameRect.height = (frameRect.y+height < WinTop+WinHeight) ? height : height+y-frameRect.y;
bg_pixmap = XCreatePixmap(display, RootWindow(display, screen),WinWidth+WinLeft,WinHeight+WinTop,DefaultDepth(display,screen));
gc_bg = XCreateGC(display, w,0,NULL);
XCopyGC(display,gc_fill,0xFFFF,gc_bg);
valuemask = GCTile|GCFillStyle|GCGraphicsExposures|GCTileStipXOrigin|GCTileStipYOrigin;
values.tile = bg_style->image->pixmap;
values.fill_style = FillTiled;
values.graphics_exposures = FALSE;
if(bg_style->flag & S_BACKGROUND_ORIGIN)
{
if(bg_style->flag & S_BACKGROUND_FIXED)
{
values.ts_x_origin = bg_style->x_pos*(WinWidth-bg_style->image->width)/100;
values.ts_y_origin = bg_style->y_pos*(WinHeight-bg_style->image->height)/100 + WinTop;
}
else
{
values.ts_x_origin = bg_style->x_pos*(WinWidth-bg_style->image->width)/100 -PixelIndent;
values.ts_y_origin = bg_style->y_pos*(WinHeight-bg_style->image->height)/100 + WinTop - PixelOffset;
};
}
else
{
if(bg_style->flag & S_BACKGROUND_FIXED)
{
values.ts_x_origin = 0;
values.ts_y_origin = WinTop;
}
else
{
values.ts_x_origin = -PixelIndent;
values.ts_y_origin = WinTop - PixelOffset;
}
}
XChangeGC(display, gc_bg, valuemask, &values);
XSetClipRectangles(display, disp_gc, 0, 0, &frameRect, 1, Unsorted);
XSetClipRectangles(display, gc_fill, 0, 0, &frameRect, 1, Unsorted);
if(bg_style->flag & S_BACKGROUND_COLOR)
XFillRectangle(display, bg_pixmap, disp_gc,x1-PixelIndent, y1 , width, height);
else
XFillRectangle(display, bg_pixmap, gc_fill,x1-PixelIndent, y1 , width, height);
if(bg_style->flag & S_BACKGROUND_Y_REPEAT)
{
bgRect.y = WinTop;
bgRect.height = WinHeight;
}
else
{
bgRect.y = values.ts_y_origin;
bgRect.height = bg_style->image->height;
}
if(bg_style->flag & S_BACKGROUND_X_REPEAT)
{
bgRect.x = WinLeft;
bgRect.width = WinWidth;
}
else
{
bgRect.x = values.ts_x_origin;
bgRect.width = bg_style->image->width;
}
XSetClipRectangles(display, gc_bg, 0, 0,&bgRect, 1, Unsorted);
XFillRectangle(display, bg_pixmap, gc_bg, x1-PixelIndent, y1 , width, height);
XSetClipRectangles(display, gc_bg, 0, 0, &frameRect, 1, Unsorted);
}
else
if(!(bg_style->flag & (S_BACKGROUND_COLOR))) /* use paper if no pixmap and color */
XFillRectangle(display, w, gc_fill, x1-PixelIndent, y1 , width, height);
}
if(!(bg_style->flag & (S_BACKGROUND_COLOR |S_BACKGROUND_IMAGE)))
XFillRectangle(display, w, gc_fill,x1-PixelIndent, y1 , width, height);
};
#endif
c1 = *p++; c2 = *p++; length = c1 | c2<<8;
/* printf("BEGIN_FRAME %xh (x1 %d, y1 %d, width %d, height %d, length %d\n",(p-12),x1,y1,width,height,length);
*/
/* call self to paint this frame */
if(dirtyscroll && bg_style)
{
PaintFrame(bg_pixmap, p, p + length, x1, y, h);
}
else
PaintFrame(w, p, p + length, x1, y, h);
p += length+2; /* to skip over frame's contents */
if(dirtyscroll && bg_style)
{
XCopyGC(display,gc_fill,0xFFFF,gc_bg);
valuemask = GCGraphicsExposures;
valuemask |= GCTile|GCFillStyle;
values.tile = bg_style->image->pixmap;
values.fill_style = FillTiled;
values.graphics_exposures = 0;
XChangeGC(display, gc_bg, valuemask, &values);
XSetClipRectangles(display, disp_gc, 0, 0, &displayRect, 1, Unsorted);
XSetClipRectangles(display, gc_fill, 0, 0, &displayRect, 1, Unsorted);
XSetClipRectangles(display, gc_bg, 0, 0, &displayRect, 1, Unsorted);
XCopyArea(display,bg_pixmap,w,gc_bg,frameRect.x,frameRect.y,frameRect.width,frameRect.height,frameRect.x,frameRect.y);
XFreePixmap(display,bg_pixmap);
XFreeGC(display, gc_bg);
};
if (border)
DrawBorder(border, x+x1-PixelIndent, y1, width, height, 0 /* cb_ix */);
continue;
}
/* skip end of frame marker */
if (tag == END_FRAME)
{
p += FRAMENDLEN - 1; /* skip start/size params */
continue;
}
if (tag != TEXTLINE)
{
printf("Unexpected Internal Tag %d at %X\n",tag,(p-1));
tag = *p++;
}
c1 = *p++; c2 = *p++; offset = c1 | c2<<8;
c1 = *p++; c2 = *p++; offset |= (c1 | c2<<8) << 16;
/* we are done if TextLine starts after bottom of window */
y1 = WinTop + (offset - PixelOffset);
/*
if (y1 >= y + (int)h)
break;
*/
c1 = *p++; c2 = *p++; yb = y1 + (c1 | c2<<8);
c1 = *p++; c2 = *p++; xi = x + (c1 | c2<<8);
c1 = *p++; c2 = *p++; height = (c1 | c2<<8);
while ((tag = *p++) != '\0')
{
switch (tag & 0xF)
{
case RULE:
c1 = *p++; c2 = *p++; x1 = xi + (c1 | c2<<8);
c1 = *p++; c2 = *p++; x2 = c1 | c2<<8;
c1 = *p++; c2 = *p++; yi = c1 | c2<<8;
if (tag & HLINE)
x2 += x1;
#ifdef STYLE_COLOR
color_text_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
#endif
/* if (tag & GROOVE)*/
if (color_text_ix == 255)
{
XSetForeground(display, disp_gc, windowBottomShadow);
XFillRectangle(display, w, disp_gc, x1-PixelIndent, yb-yi, x2-x1, 1);
XSetForeground(display, disp_gc, windowTopShadow);
XFillRectangle(display, w, disp_gc, x1-PixelIndent, yb+1-yi, x2-x1, 1);
XSetForeground(display, disp_gc, textColor);
}
else {
XSetForeground(display, disp_gc, ix2color(color_text_ix)); /* howcome 22/5/95 */
XFillRectangle(display, w, disp_gc, x1-PixelIndent, yb-yi, x2-x1, 1);
}
break;
case LINE:
c1 = *p++; c2 = *p++; x1 = xi + (c1 | c2<<8);
c1 = *p++; c2 = *p++; x2 = xi + (c1 | c2<<8);
c1 = *p++; c2 = *p++; y1 = c1 | c2<<8;
c1 = *p++; c2 = *p++; y2 = c1 | c2<<8;
#ifdef STYLE_COLOR
color_text_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
GetPointer(&p);
#endif
XSetForeground(display, disp_gc, ix2color(color_text_ix));
XDrawLine(display, win, disp_gc, x1-PixelIndent, yb-y1, x2, yb-y2);
break;
case BULLET:
c1 = *p++; c2 = *p++; x1 = xi + (c1 | c2<<8);
c1 = *p++; c2 = *p++; depth = (c1 | c2<<8);
fnt = *p++; /* howcome 25/4/95 */
fnt_size = *p++;
#ifdef STYLE_COLOR
color_text_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
bg_style=(BG_Style *)GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
if(bg_style)
color_background_ix = (bg_style->flag & S_BACKGROUND_COLOR ) ? rgb2ix(0, bg_style->r, bg_style->g, bg_style->b,0) : 255;
else
color_background_ix = 255;
#endif
SetColor(disp_gc, color_text_ix, color_background_ix);
if (depth > 0)
XFillRectangle(display, w, disp_gc, x1 - PixelIndent, yb - LineSpacing[fnt]*3/8, LineSpacing[fnt]/4, 2);
else
{
XFillRectangle(display, w, disp_gc, x1 - PixelIndent, yb - LineSpacing[fnt]*3/8, LineSpacing[fnt]/5, LineSpacing[fnt]/5);
}
break;
case STRING:
c1 = *p++; c2 = *p++; emph = c1 | c2<<8;
fnt = *p++;
#ifdef STYLE_COLOR
color_text_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
bg_style=(BG_Style *)GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
if (bg_style)
{
if(!bg_style->image)
color_background_ix = (bg_style->flag & S_BACKGROUND_COLOR) ? rgb2ix(0, bg_style->r, bg_style->g, bg_style->b,0) : 255;
else
color_background_ix = 255;
}
else
color_background_ix = 255;
#endif
yi = *p++ - 128;
c1 = *p++; c2 = *p++; x1 = xi + (c1 | c2<<8); /* here */
c1 = *p++; c2 = *p++; len = c1 | c2<<8;
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
str = (long) GetPointer(&p);
p += POINTERSIZE; /* skip ref */
/* printf("howcome reading %x\n", str); */
preformatted = (tag & PRE_TEXT);
s = CopyLine((char *)str, len);
#ifdef STYLE_COLOR
font = fnt;
SetColor(disp_gc, color_text_ix, color_background_ix);
SetFont(disp_gc, font);
#else
if (font != fnt)
{
font = fnt;
SetFont(disp_gc, font);
}
#endif
if (emph & EMPH_HIGHLIGHT)
{
XSetForeground(display,disp_gc, labelColor);
XDrawString(display, w, disp_gc, x1-PixelIndent, yb-yi, s, len);
XSetForeground(display,disp_gc, textColor);
}
else {
#ifdef STYLE_COLOR
if (color_background_ix == 255)
#endif
XDrawString(display, w, disp_gc, x1-PixelIndent, yb-yi, s, len);
#ifdef STYLE_COLOR
else
XDrawImageString(display, w, disp_gc, x1-PixelIndent, yb-yi, s, len);
#endif
}
if (emph & EMPH_ANCHOR)
{
y2 = yb - yi - ASCENT(font) - 1;
DrawHButtonUp(x1-PixelIndent, y2, width, LineSpacing[fnt]);
}
if (emph & EMPH_UNDERLINE)
{
y2 = yb - yi + DESCENT(font);
XFillRectangle(display, w, disp_gc, x1+1-PixelIndent, y2 - LineThickness[font], width-2, LineThickness[font]);
}
if (emph & EMPH_STRIKE)
{
y2 = yb - yi - ASCENT(font)/3;
XSetForeground(display,disp_gc, strikeColor);
XFillRectangle(display, w, disp_gc, x1-PixelIndent, y2 - LineThickness[font], width, LineThickness[font]);
XSetForeground(display,disp_gc, textColor);
}
break;
case SEQTEXT:
c1 = *p++; c2 = *p++; emph = (c1 | c2<<8);
fnt = *p++;
#ifdef STYLE_COLOR
color_text_ix = *p++;
#endif
#ifdef STYLE_BACKGROUND
bg_style=(BG_Style *)GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
if (bg_style)
color_background_ix = (bg_style->flag & S_BACKGROUND_COLOR) ? rgb2ix(0, bg_style->r, bg_style->g, bg_style->b,0) : 255;
else
color_background_ix = 255;
#endif
c1 = *p++; c2 = *p++; x1 = xi + (c1 | c2<<8); /* here */
c1 = *p++; c2 = *p++; yi = (c1 | c2<<8); /* y offset */
len = *p++;
width = XTextWidth(Fonts[fnt], (char *)p, len);
#ifdef STYLE_COLOR
font = fnt;
SetColor(disp_gc, color_text_ix, color_background_ix);
SetFont(disp_gc, font);
if (color_background_ix == 255)
XDrawString(display, w, disp_gc,
x1-PixelIndent, yb-yi, (char *)p, len);
else
XDrawImageString(display, w, disp_gc,
x1-PixelIndent, yb-yi,
(char *)p, len);
#else
if (font != fnt)
{
font = fnt;
SetFont(disp_gc, font);
}
XDrawString(display, w, disp_gc, x1-PixelIndent,
yb-yi, (char *)p, len);
#endif
/* different emphasis used in maths */
/* under effects */
if (emph & EMPH_UNDERLINE)
{
y2 = yb - yi + DESCENT(font);
XFillRectangle(display, w, disp_gc,
x1+1-PixelIndent,
y2 - LineThickness[font], width-2,
LineThickness[font]);
}
if (emph & EMPH_UNDERLARR)
{
y2 = yb - yi + DESCENT(font);
XFillRectangle(display, w, disp_gc,
x1+1-PixelIndent,
y2 - LineThickness[font], width,
LineThickness[font]);
SetFont(disp_gc, IDX_SUBSYMFONT);
tmp = 60;
XDrawString(display, w, disp_gc,
x1-PixelIndent, y2+3,
(char *)&tmp, 1);
SetFont(disp_gc, font);
}
if (emph & EMPH_UNDERRARR)
{
y2 = yb - yi + DESCENT(font);
XFillRectangle(display, w, disp_gc,
x1+1-PixelIndent,
y2 - LineThickness[font], width,
LineThickness[font]);
SetFont(disp_gc, IDX_SUBSYMFONT);
tmp = 62;
XDrawString(display, w, disp_gc,
x1-PixelIndent+width-4, y2+3,
(char *)&tmp, 1);
SetFont(disp_gc, font);
}
if (emph & EMPH_UNDERHAT)
{
}
if (emph & EMPH_UNDERTILDE)
{
}
/* OVER effects */
if (emph & EMPH_OVERLINE)
{
y2 = yb - yi + DESCENT(font)/2 - ASCENT(font);
XFillRectangle(display, w, disp_gc,
x1+1-PixelIndent,
y2 - LineThickness[font], width-2,
LineThickness[font]);
}
if (emph & EMPH_OVERLARR)
{
y2 = yb - yi + DESCENT(font)/2 - ASCENT(font);
XFillRectangle(display, w, disp_gc,
x1+1-PixelIndent,
y2 - LineThickness[font], width-2,
LineThickness[font]);
SetFont(disp_gc, IDX_SUBSYMFONT);
tmp = 60;
XDrawString(display, w, disp_gc,
x1-PixelIndent, y2+3,
(char *)&tmp, 1);
SetFont(disp_gc, font);
}
if (emph & EMPH_OVERRARR)
{
y2 = yb - yi + DESCENT(font)/2 - ASCENT(font);
XFillRectangle(display, w, disp_gc,
x1-PixelIndent, y2, width, 1);
SetFont(disp_gc, IDX_SUBSYMFONT);
tmp = 62;
XDrawString(display, w, disp_gc,
x1-PixelIndent+width-4, y2+3,
(char *)&tmp, 1);
SetFont(disp_gc, font);
}
if (emph & EMPH_OVERHAT)
{
}
if (emph & EMPH_OVERDOT)
{
}
if (emph & EMPH_OVERDDOT)
{
}
if (emph & EMPH_OVERTILDE)
{
}
p += len;
break;
case IMAGE:
c1 = *p++; c2 = *p++; y2 = yb - (c1 | c2<<8);
c1 = *p++; c2 = *p++; x1 = xi + (c1 | c2<<8); /* here */
c1 = *p++; c2 = *p++; width = c1 | c2<<8;
c1 = *p++; c2 = *p++; height = c1 | c2<<8;
str = (long)GetPointer(&p);
p += POINTERSIZE; /* skip past buffer pointer */
#ifdef STYLE_BACKGROUND
GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
#endif
if (y2 > y + (int)h)
break;
if (y2 + height < y)
continue;
x1 -= PixelIndent;
if (tag & (ISMAP | EMPH_ANCHOR))
{
DrawOutSet(w, disp_gc, x1, y2, width, height);
XSetForeground(display, disp_gc, textColor);
DrawHButtonDown(x1+4, y2+2, width-7, height-6);
width -= 8;
height -= 8;
x1 += 4;
y2 += 4;
}
if (str) {
XCopyArea(display, (Pixmap)str, w, disp_gc, 0, 0, width, height, x1, y2);
} else if (!(tag & (ISMAP | EMPH_ANCHOR))){
XPoint points[3];
points[0].x = x1;
points[0].y = y2 + IMG_INDICATOR;
points[1].x = x1;
points[1].y = y2;
points[2].x = x1 + IMG_INDICATOR;
points[2].y = y2;
XDrawLines(display, w, disp_gc, points, 3, CoordModeOrigin);
points[0].x = x1 + width - IMG_INDICATOR;
points[0].y = y2;
points[1].x = x1 + width;
points[1].y = y2;
points[2].x = x1 + width;
points[2].y = y2 + IMG_INDICATOR;
XDrawLines(display, w, disp_gc, points, 3, CoordModeOrigin);
points[0].x = x1 + width;
points[0].y = y2 + height - IMG_INDICATOR;
points[1].x = x1 + width;
points[1].y = y2 + height;
points[2].x = x1 + width - IMG_INDICATOR;
points[2].y = y2 + height;
XDrawLines(display, w, disp_gc, points, 3, CoordModeOrigin);
points[0].x = x1 + IMG_INDICATOR ;
points[0].y = y2 + height;
points[1].x = x1;
points[1].y = y2 + height;
points[2].x = x1;
points[2].y = y2 + height - IMG_INDICATOR;
XDrawLines(display, w, disp_gc, points, 3, CoordModeOrigin);
}
break;
case INPUT:
str = (long)GetPointer(&p);
#ifdef STYLE_BACKGROUND
GetPointer(&p); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
#endif
PaintField(disp_gc, xi, yb, (Field *)str);
break;
}
}
++p; ++p; /* skip size param to start of next object */
}
if (TAG_TRACE && VERBOSE_TRACE)
#if defined PRINTF_HAS_PFORMAT
fprintf(stderr,"PaintFrame: after while p = %p, p_end = %p\n", p, p_end);
#else
fprintf(stderr,"PaintFrame: after while p = %lx, p_end = %lx\n", p, p_end);
#endif /* PRINTF_HAS_PFORMAT */
}
/* search for anchor point in document */
/* search index for given keywords */
void SearchIndex(char *keywords)
{
#if 0
char *p, *q;
/* janet 21/07/95: not used: int where; */
p = SearchRef(keywords);
if (*p) /* attempt to get new document */
{
/* XDefineCursor(display, win, hourglass);*/
/* XFlush(display);*/
q = libGetDocument(p, NULL, REMOTE); /* howcome */
if (q && *q)
{
CurrentDoc.offset = PixelOffset;
PushDoc(CurrentDoc.offset);
SetBanner(BANNER);
SetCurrent();
NewBuffer(q);
if (IsIndex)
ClearStatus();
SetStatusString(NULL); /* to refresh screen */
}
DisplayScrollBar();
DisplayDoc(WinLeft, WinTop, WinWidth, WinHeight);
XUndefineCursor(display, win);
XFlush(display);
}
#endif
}
int WindowButtonDown(int x, int y)
{
int tag, dx, dy;
/* the window should only be cliackable for certain content_types and modes */
if (!DocHTML(CurrentDoc))
return VOID;
if (CurrentDoc->show_raw)
return VOID;
anchor_start = anchor_end = 0;
tag = 0;
clicked_element = WhichObject(BUTTONDOWN, x, y, &tag, &anchor_start, &anchor_end, &dx, &dy);
if (tag == TAG_ANCHOR || tag == TAG_IMG) /* redraw anchor if type=image or src= */
{
DrawAnchor(&background, 0);
return WINDOW;
}
if (tag == TAG_INPUT || TAG_SELECT)
/* toggle checked here ??? --SPif 13-oct-95 */
return WINDOW;
Beep();
return VOID;
}
/* --Spif must do this right (11-Oct-95) */
void www_encode(char *raw)
{
int i,rlen;
char *encoded,*j;
rlen=strlen(raw);
encoded=(char *)malloc(3*rlen+1); /* max size = size*3 */
j=encoded;
for(i=0;i'9'))){
*j++ = '%';
sprintf(j,"%X",*(raw+i));
j+=2;
} else if ((*(raw+i) > 'z') || ((*(raw+i)<'a')&&(*(raw+i)>'Z'))){
*j++ = '%';
sprintf(j,"%X",*(raw+i));
j+=2;
} else
*j++=*(raw+i);
};
*j=0;
strcpy(raw,encoded); /* short term hack... must return the pointer */
}
void WindowButtonUp(int shifted, int px, int py)
{
Byte *object;
char *start, *end, *href, *name, *link, *value, buf[16], *action;
int tag, hreflen, namelen, align, ismap, dx, dy, width, height;
int type, vlen, flags, size, method, alen, nlen;
Image *image = NULL;
Form *form = NULL;
/* the window should only be cliackable for certain content_types and modes */
if (!DocHTML(CurrentDoc))
return;
if (CurrentDoc->show_raw)
return;
if (anchor_start && anchor_end)
DrawAnchor(&background, 1);
tag=UNKNOWN; /* -- avoid any pb with this --Spif 16-Oct-95 */
object = WhichObject(BUTTONUP, px, py, &tag, &start, &end, &dx, &dy);
if ((tag == TAG_ANCHOR || tag == TAG_IMG) &&
start == anchor_start && end == anchor_end)
{
if (tag == TAG_IMG)
{
bufptr = anchor_start+5;
ParseImageAttrs(&href, &hreflen, &align, &ismap, &width, &height);
sprintf(buf, "?%d,%d", dx, dy);
link = (char *)malloc(hreflen+strlen(buf)+1);
memcpy(link, href, hreflen);
link[hreflen] = '\0';
strcat(link, buf);
}
else /* tag == TAG_ANCHOR */
{
int class_len;
char *class = NULL;
bufptr = anchor_start+3;
ParseAnchorAttrs(&href, &hreflen, &name, &namelen, &class, &class_len);
if (dx >= 0 && dy >= 0)
{
sprintf(buf, "?%d,%d", dx, dy);
link = (char *)malloc(hreflen+strlen(buf)+1);
memcpy(link, href, hreflen);
link[hreflen] = '\0';
strcat(link, buf);
}
else
{
link = (char *)malloc(hreflen+1);
memcpy(link, href, hreflen);
link[hreflen] = '\0';
}
}
/*
if (shifted)
{
if (CloneSelf())
OpenDoc(link);
}
else */
OpenDoc(link);
Free(link);
}
else
{
if (tag == TAG_INPUT) /* --Spif FORM 10-Oct-95 */
{
bufptr = start + 7 ;
ParseInputAttrs(&type, &name, &nlen, &value, &vlen, &size, &flags, &image);
/* backtrack to find the previous */
for(;(strncasecmp(bufptr, "