/* 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, " 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, "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, "