parsehtml.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:164k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /* parsehtml.c - display code for html
  2. ParseHTML() parses the HTML elements and generates a stream of commands for
  3. displaying the document in the Paint buffer. The paint commands specify the
  4. appearence of the document as a sequence of text, lines, and images. Each
  5. command includes the position as a pixel offset from the start of the
  6. document. This makes it easy to scroll efficiently in either direction.
  7. The paint buffer must be freed and recreated if the window is resized.
  8. The model needs to switch to relative offsets to enable the transition
  9. to an wysiwyg editor for html+. Relative values for pixel offsets and
  10. pointers to the html+ source would make it much easier to edit documents
  11. as it would limit revisions to the paint stream to the region changed.
  12. */
  13. /*
  14. Janne Saarela
  15. janne.saarela@hut.fi
  16. 28.7.1995
  17. PrintSeqText() and PutText() now use PushValue() to place
  18. the emph attribute to the PaintStream. The function prototypes
  19. now have emph added as unsigned int.
  20. */
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include "www.h"
  25. #include "tools.h"
  26. #include "style.h"
  27. #define LBUFSIZE 1024
  28. extern Display *display;
  29. extern int screen;
  30. extern Window win;
  31. extern GC disp_gc, gc_fill;
  32. extern Cursor hourglass;
  33. extern int UsePaper;
  34. extern int debug;  /* controls display of errors */
  35. extern int document;  /* HTMLDOCUMENT or TEXTDOCUMENT */
  36. extern int busy;
  37. extern int OpenURL;
  38. extern int IsIndex;
  39. extern int FindStr;
  40. extern char *FindNextStr;
  41. extern int SaveFile;
  42. extern int sbar_width;
  43. extern int statusHeight;
  44. extern int ToolBarHeight;
  45. extern unsigned long windowColor;
  46. extern unsigned int win_width, win_height, tileWidth, tileHeight;
  47. extern BOOL NoStyle;
  48. extern Context *context;
  49. extern unsigned long textColor, labelColor, windowTopShadow,
  50.                      strikeColor, windowBottomShadow, windowShadow, windowColor;
  51. /*
  52.     The current top line is displayed at the top of the window,the pixel
  53.     offset is the number of pixels from the start of the document.
  54. */
  55. extern char *buffer;            /* the start of the document buffer */
  56. extern long PixelOffset;        /* the pixel offset to top of window */
  57. extern int hdrlen;              /* MIME header length at start of buffer */
  58. extern long buf_height;
  59. extern long lineHeight;
  60. extern long chDescent;
  61. extern int buf_width;
  62. extern int PixelIndent;
  63. extern int chStrike;
  64. extern int spWidth;             /* width of space char */
  65. extern int chWidth;             /* width of average char */
  66. /*extern Doc NewDoc, CurrentDoc;*/
  67. extern XFontStruct *pFontInfo;
  68. extern XFontStruct *Fonts[FONTS];
  69. extern int LineSpacing[FONTS], BaseLine[FONTS], StrikeLine[FONTS];
  70. extern int ListIndent1, ListIndent2;
  71. extern Frame background;
  72. extern Image *images, *note_image, *caution_image, *warning_image;
  73. extern Form *forms;
  74. extern Doc *CurrentDoc;
  75. char *bufptr;  /* parse position in the HTML buffer */
  76. char *lastbufptr;  /* keep track of last position to store delta's */
  77. Byte *TopObject;  /* first visible object in window */
  78. Byte *paint; /* holds the sequence of paint commands */
  79. int paintbufsize;     /* size of buffer, not its contents */
  80. int paintlen;         /* where to add next entry */
  81. int paintStartLine;   /* where line starts in the paint stream */
  82. int above;            /* above baseline */
  83. int below;            /* below baseline */
  84. int voffset;          /* if positive then above baseline */
  85. int IdAttributeFlag;  /* signals attribute is ID value */
  86. int error;            /* set by parser */
  87. int prepass;          /* true during table prepass */
  88. int html_width;       /* tracks maximum width */
  89. int min_width, max_width; /* table cell width */
  90. int list_indent;
  91. int damn_table=0; /* to debug table formatter */
  92. extern int preformatted;
  93. extern int font;  /* index into Fonts[] array */
  94. static int EndTag, TagLen;
  95. static int TokenClass, TokenValue, Token;
  96. /* janet: not used: static char *EntityValue; */
  97. unsigned int ui_n;
  98. unsigned long ul_n;
  99. int baseline;       /* from top of line */
  100. long TermTop, TermBottom;
  101. long PixOffset;     /* current offset from start of document */
  102. long PrevOffset;    /* keep track for saving delta's */
  103. long LastLIoffset;  /* kludge for <LI><LI> line spacing */
  104. long ViewOffset;    /* for toggling between HTML/TEXT views */
  105. extern long IdOffset;      /* offset for targetId */
  106. extern char *targetptr;    /* for toggling view between HTML/TEXT views */
  107. extern char *targetId;     /* for locating named Id during ParseHTML() */
  108. int Here, TextLineWidth;
  109. int HTMLInit = 0;
  110. Image *start_figure, *figure;
  111. long figEnd;
  112. Form *form;
  113. int LeftFlowMargin, RightFlowMargin;
  114. int LeftMarginIndent = 0, RightMarginIndent = 0;
  115. long FigureEnd = 0;
  116. int class_len = 0;
  117. char *class = NULL;
  118. /* BOOL initial_cap = FALSE;*/
  119. char *LastBufPtr, *StartOfLine, *StartOfWord; /* in HTML document */
  120. static int LineLen, LineWidth, WordStart, WordWidth;
  121. static char LineBuf[LBUFSIZE]; /* line buffer */
  122. static char *Ones[] = {"i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"};
  123. static char *Tens[] = {"x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"};
  124. static char *Hundreds[] = {"c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"};
  125. char small_caps[256] = {   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 
  126.   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  127.   32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  128.   48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
  129.   64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
  130.   80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
  131.   96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
  132.   80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
  133.  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
  134.  144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
  135.  160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
  136.  176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
  137.  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
  138.  208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
  139.  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
  140.  208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255 }; 
  141. /* push 16 bit value onto paint buffer */
  142. #define PushValue(p, value) ui_n = (unsigned int)value; *p++ = ui_n & 0xFF; *p++ = (ui_n >> 8) & 0xFF
  143. #define Push32(p, value) ul_n = (unsigned long)value; *p++ = ul_n & 0xFF; *p++ = (ul_n >> 8) & 0xFF; *p++ = (ul_n >> 16) & 0xFF; *p++ = (ul_n >> 24) & 0xFF
  144. /* expand paint stream to fit len bytes */
  145. Byte *MakeRoom(int len)
  146. {
  147.     Byte *p;
  148.     if (paintlen > paintbufsize - len)
  149.     {
  150.         paintbufsize = paintbufsize << 1;
  151.         paint = (Byte *)realloc(paint, paintbufsize);
  152.     }
  153.     p = paint + paintlen;
  154.     paintlen += len;
  155.     return p;
  156. }
  157. void PrintBeginFrame(Frame *frame)
  158. {
  159.     Byte *p;
  160.     /* janet: not used:    unsigned int len; */
  161.     long offset;
  162.     if (!prepass)
  163.     {
  164.         p = MakeRoom(FRAMESTLEN);
  165.         frame->info = (p - paint);
  166.         offset = frame->offset;
  167.         *p++ = BEGIN_FRAME;
  168.         PushValue(p, offset & 0xFFFF);
  169.         PushValue(p, (offset >> 16) & 0xFFFF);
  170.         PushValue(p, frame->indent);
  171.         PushValue(p, frame->width);
  172.         PushValue(p, 0);        /* subsequently filled in with height(1) */
  173. PushValue(p, 0);       /* subsequently filled in with height(2) */
  174.         *p++ = frame->style;    /* frame's background style */
  175.         *p++ = frame->border;   /* frame's border style */
  176. #ifdef STYLE_COLOR_BORDER
  177.         *p++ = frame->cb_ix;    /* frame's foreground color index */
  178. #endif
  179. #ifdef STYLE_BACKGROUND
  180. PutPointer(&p,(void *)StyleGet(S_BACKGROUND));
  181. #endif
  182.         PushValue(p, 0);        /* subsequently filled in with length */
  183.     }
  184. }
  185. /* the size field after end of frame contents */
  186. void PrintFrameLength(Frame *frame)
  187. {
  188.     Byte *p;
  189.     unsigned int len;
  190.     if (!prepass)
  191.     {
  192.      /* write the length field in frame's header */
  193.         p = paint + frame->info + FRAMESTLEN - 2 ; /* --Spif 19-Oct-95 grmph !!! position of lenght in the paint stream */
  194.         PushValue(p, frame->length);
  195.      /* write the size field after frame's contents */
  196. p = MakeRoom(2); 
  197.         len = p - paint - frame->info; /* --Spif 19-Oct-95 must see this */
  198. PushValue(p, len); 
  199.     }
  200. }
  201. /* marker for pixel offset to end of frame */
  202. void PrintEndFrame(Frame *parent, Frame *frame)
  203. {
  204.     Byte *p;
  205.     unsigned int len;
  206.     if (!prepass)
  207.     {
  208.         p = MakeRoom(FRAMENDLEN);
  209.         len = p - (paint + frame->info);
  210.         *p++ = END_FRAME;
  211.         PushValue(p, len);
  212.         PushValue(p, FRAMENDLEN-2);
  213.      /* increase width of parent frame if necessary */
  214.         if (parent)
  215.         {
  216.             len = frame->indent + frame->width + 2;
  217.             if (parent->width < len)
  218.                 parent->width = len;
  219.         /* and restore parent frame margins if this frame
  220.            was involved in a text flow indent and is not
  221.            obstructed by a subsequent text flow frame */
  222.             /* howcome 7/10/94: prolonged the "if parent" block */
  223.             if (frame->flow == ALIGN_LEFT)
  224.                 {
  225.                     if (frame->pushcount == parent->leftcount)
  226.                         {
  227.                             parent->leftcount -= 1;
  228.                             parent->leftmargin = frame->oldmargin;
  229.                         }
  230.                 }
  231.             else if (frame->flow == ALIGN_RIGHT)
  232.                 {
  233.                     if (frame->pushcount == parent->rightcount)
  234.                         {
  235.                             parent->rightcount -= 1;
  236.                             parent->rightmargin = frame->oldmargin;
  237.                         }
  238.                 }
  239.             else if (frame->flow == ALIGN_NOTE)
  240.                 {
  241.                     if (frame->pushcount == parent->leftcount)
  242.                         parent->leftcount -= 1;
  243.                 }
  244.         }
  245.     }
  246. }
  247. /* Write end markers for all peer frames and children.
  248.    Note that the lists are flushed in the same order
  249.    that items were pushed onto the list */
  250. void FlushAllFrames(Frame *parent, Frame *frame)
  251. {
  252.     if (frame)
  253.     {
  254.         FlushAllFrames(parent, frame->next);
  255.         FlushAllFrames(frame, frame->child);
  256.         PrintEndFrame(parent, frame);
  257.         FreeFrames(frame);
  258.     }
  259. }
  260. /*
  261.  Write end markers for any frames in peer list which have a
  262.  finishing offset <= PixOffset. For any such frames, all
  263.  descendant frames are flushed first. The process frees
  264.  frames and removes them from the list of peers.
  265.  If frame is the current frame then this procedure
  266.  should be invoked as:
  267.     frame->child = FlushFrames(frame, frame->child);
  268.  This procedure assumes that BeginFrame() pushes
  269.  new frames onto the front of the list of children,
  270.  and guarantees that frames with the same offset are
  271.  flushed to the paint stream in the order they were
  272.  created. This property is needed for display purposes.
  273. */
  274. Frame *FlushFrames(Frame *parent, Frame *frame)
  275. {
  276.     Frame *next;
  277.     if (frame)
  278.     {
  279.         next = FlushFrames(parent, frame->next);
  280.         if (frame->offset <= PixOffset)
  281.         {
  282.          /* first flush frame's children */
  283.             FlushAllFrames(frame, frame->child);
  284.          /* and now the frame itself */
  285.             PrintEndFrame(parent, frame);
  286.             free(frame);
  287.             return next;
  288.         }
  289.         frame->next = next;
  290.     }
  291.     return frame;
  292. }
  293. void FlushPending(Frame *frame)
  294. {
  295.     if (frame && frame->child)
  296.         frame->child = FlushFrames(frame, frame->child);
  297. }
  298. /* 
  299.  The frame is created here, the new frame is returned so that the
  300.  parser can later call EndFrame() at the end of the frame. Any frames
  301.  which end before PixOffset are first flushed.
  302. */
  303. Frame *BeginFrame(Frame *parent, int style, int border, int left, int right, BG_Style *bg)
  304. {
  305.     Frame *frame;
  306.     FlushPending(parent);
  307.  /* create frame and write begin frame marker */
  308.     frame = (Frame *)calloc(1, sizeof(Frame));
  309.     memset(frame, 0, sizeof(Frame));
  310.     frame->offset = PixOffset;
  311.     frame->indent = (parent ?  parent->leftmargin + left : left);
  312.     frame->width = right - left;
  313.     frame->style = style;
  314.     frame->border = border;
  315. #ifdef STYLE_COLOR_BORDER
  316.     frame->cb_ix = (int)bg;
  317. #else
  318.     frame->cb_ix = 0;
  319. #endif
  320.     frame->flow = ALIGN_CENTER; /* implies this is a figure frame */
  321.     frame->next = frame->child = NULL;
  322.     frame->box_list = NULL;
  323.     PrintBeginFrame(frame);
  324.     return frame;
  325. }
  326. /* This writes the frame's height in the frame's header.
  327.    Here we need to push the frame onto the front of the
  328.    list of the parent frame's children so that FlushFrames()
  329.    can write the end frame marker to the paint queue */
  330. void EndFrame(Frame *parent, Frame *frame)
  331. {
  332.     Byte *p;
  333.  /* janet: not used: Frame *next,  *prev; */
  334.  /* update background.height if needed */
  335.     if (PixOffset > background.height)
  336.         background.height = PixOffset;
  337.  /* write height into paint struct for frame */
  338.     frame->height = PixOffset - frame->offset;
  339.     p = paint + frame->info + 9; /* --Spif 19-Oct-95 offset in frame to height(1) and (2) */
  340.     PushValue(p, frame->height & 0xFFFF);
  341.     PushValue(p, (frame->height >> 16) & 0xFFFF);
  342.  /* change frame->offset to end of frame */
  343.     frame->offset = PixOffset;
  344.  /* and now push onto list of children */
  345.     frame->next = parent->child;
  346.     parent->child = frame;
  347. }
  348. int ListCells(Frame *cells)
  349. {
  350.     int n;
  351.     for (n = 0; cells != NULL; ++n)
  352.     {
  353. #if defined PRINTF_HAS_PFORMAT
  354.         printf("address = %p, indent = %d, width = %d, height = %ldn",
  355.             cells, cells->indent, cells->width, cells->height);
  356. #else
  357.         printf("address = %lx, indent = %d, width = %d, height = %ldn",
  358.             cells, cells->indent, cells->width, cells->height);
  359. #endif /* POINTER_IS_64BIT */
  360.         cells = cells ->next;
  361.     }
  362.     return n;
  363. }
  364. /*
  365.  Insert cell at end of list of cells
  366. */
  367. void /* wm 19.Jan.95 */
  368. InsertCell(Frame **cells, Frame *cell)
  369. {
  370.     Frame *frame, *next;
  371.     frame = *cells;
  372.     cell->next = NULL;
  373.     if (frame == NULL)
  374.         *cells = cell;
  375.     else
  376.     {
  377.         for (frame = *cells;;)
  378.         {
  379.             next = frame->next;
  380.             if (next == NULL)
  381.             {
  382.                 frame->next = cell;
  383.                 break;
  384.             }
  385.             frame = next;
  386.         }
  387.     }
  388. }
  389. /*
  390.  This routine adjusts height of all table cells which end
  391.  on this row and then calls EndFrame() to move them to
  392.  the list of frames awaiting PrintEndFrame()
  393. */
  394. void FlushCells(Frame *parent, int row, Frame **cells)
  395. {
  396.     Frame *prev, *frame, *next;
  397.     prev = NULL;
  398.     frame = *cells;
  399.     while (frame)
  400.     {
  401.         if (frame->lastrow <= row)
  402.         {
  403.             next = frame->next;
  404.             if (prev)
  405.                 prev->next = next;
  406.             else
  407.                 *cells = next;
  408.             frame->height = PixOffset - frame->offset;
  409.             frame->next = NULL;
  410.             EndFrame(parent, frame);
  411.             frame = next;
  412.             continue;
  413.         }
  414.         prev = frame;
  415.         frame = frame->next;
  416.     }
  417. }
  418. /* insert TEXTLINE container */
  419. void TextLineFrame(Frame *frame)
  420. {
  421.     Byte *p;
  422.     if (prepass)
  423.     {
  424.         paintStartLine = 0;
  425.         TextLineWidth = 0;
  426.     }
  427.     else
  428.     {
  429.         FlushPending(frame);
  430.         TextLineWidth = 0;
  431.         p = MakeRoom(TXTLINLEN);
  432.         paintStartLine = p - paint;
  433.         *p++ = TEXTLINE;
  434.     
  435.         PushValue(p, PixOffset & 0xFFFF);
  436.         PushValue(p, (PixOffset >> 16) & 0xFFFF);
  437.  /* baseline & indent set at end of line by EndOfLine() */
  438.         *p++ = 0; *p++ = 0;
  439.         *p++ = 0; *p++ = 0;
  440. *p++ = 0; *p++ = 0;
  441.     }
  442. }
  443. /*
  444.     This procedure writes the end of text line element
  445.     and the baseline, line height and indent as appropriate
  446.     for the frame's current margin settings. This handles
  447.     horizontal alignment in the face of changing margins.
  448. */
  449. void EndOfLine(Frame *frame, int align)
  450. {
  451.     unsigned int n, height, w;
  452.     int indent, delta = 0, len;
  453.     Byte *p;
  454.     if (!prepass)
  455. StyleSetFlag(S_LEADING_FLAG,FALSE);
  456.     if (paintStartLine >= 0)
  457.     {
  458.         /* fill in baseline for current line */
  459.         if (!prepass)
  460.         {
  461.     if (frame == &background)
  462.             {
  463. /*                w = background.width - background.rightmargin;*/
  464.                 w = background.width - background.rightmargin - (int)StyleGet(S_MARGIN_RIGHT);  /* howcome 26/2/95 */
  465.                 if (w > WinWidth - 4)
  466.                     w = WinWidth - 4;
  467. /*                w -= background.leftmargin;*/
  468.                 w -= background.leftmargin;
  469.                 if (align == ALIGN_LEFT)
  470.                     delta = 0;
  471.                 else if (align == ALIGN_CENTER)
  472.                     delta = (w - TextLineWidth) / 2;
  473.                 else if (align == ALIGN_RIGHT)
  474.                     delta = w - TextLineWidth;
  475. else if (align == ALIGN_JUSTIFY)
  476.     delta = 0;
  477.             }
  478.             else
  479.             {
  480.                 if (align == ALIGN_LEFT)
  481.                     delta = 0;
  482.                 else if (align == ALIGN_CENTER)
  483.                     delta = (frame->width /* - frame->leftmargin
  484.                                - frame->rightmargin*/ - TextLineWidth) / 2;
  485.                 else if (align == ALIGN_RIGHT)
  486.                     delta = frame->width/* - frame->leftmargin
  487.                                - frame->rightmargin*/ - TextLineWidth;
  488. else if (align == ALIGN_JUSTIFY)
  489.     delta = 0;
  490.     }
  491.             indent = (delta > 0 ? frame->leftmargin + delta : frame->leftmargin);
  492.             height = above + below;
  493.             paint[paintStartLine + 5] = (above & 0xFF);
  494.             paint[paintStartLine + 6] = (above >> 8) & 0xFF;
  495.             paint[paintStartLine + 7] = (indent & 0xFF);
  496.             paint[paintStartLine + 8] = (indent >> 8) & 0xFF;
  497.             paint[paintStartLine + 9] = (height & 0xFF);
  498.             paint[paintStartLine + 10] = (height >> 8) & 0xFF;
  499.     p = MakeRoom(3);
  500.             *p++ = '';  /* push end of elements marker */
  501.             /* and write text line frame length */
  502.             n = p - paint - paintStartLine;
  503.             PushValue(p, n);
  504.         }
  505. if(frame->flow == ALIGN_JUSTIFY) 
  506.       len = LineWidth + frame->leftmargin;
  507.   else
  508.       len = TextLineWidth + frame->leftmargin; 
  509.   
  510.         if (len > frame->width)
  511.                 frame->width = len;
  512.         PixOffset += above + below;
  513.         paintStartLine = -1;
  514.         above = 0;
  515.         below = 0;
  516.         TextLineWidth = 0;
  517. #if 0
  518.         EndFigure();
  519. #endif
  520.     }
  521. #if 0
  522.     if (start_figure)
  523.         PrintFigure(BEGIN_FIG);
  524. #endif
  525. }
  526. /* push horizontal rule onto paint stream */
  527. void PrintRule(Frame *frame, int type, int left, int right, int dy)
  528. {
  529.     Byte *p;
  530.     /* not used:     int x; */
  531.     if (paintStartLine < 0)
  532.         TextLineFrame(frame);
  533.     if (type == HLINE)
  534.     {
  535.         if (!prepass)
  536.         {
  537.             p = MakeRoom(RULEFLEN);
  538.             *p++ = (RULE | type);
  539.             PushValue(p, left);
  540.             PushValue(p, right);
  541.             PushValue(p, dy);
  542. #ifdef STYLE_COLOR
  543.     *p++ = (Byte) StyleGet(S_COLOR);
  544. #endif
  545. #ifdef STYLE_BACKGROUND
  546.     PutPointer(&p,(void *)StyleGet(S_BACKGROUND)); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
  547. #endif
  548.             above = max(above, 2);
  549.             below = max(below, 2);
  550.         }
  551.     }
  552.     else
  553.     {
  554.         if (frame == &background)
  555.         {
  556.             if (background.width - right > WinWidth - right)
  557.                 right += background.width - WinWidth;
  558.         }
  559.         right += frame->rightmargin;
  560.         if (frame->width - right > TextLineWidth)
  561.             TextLineWidth = frame->width - right;
  562. /*
  563.         above = max(above, 3);
  564.         below = max(below, 5);
  565. */
  566.         above = max(above, (int)StyleGet(S_MARGIN_TOP));
  567.         below = max(below, (int)StyleGet(S_MARGIN_BOTTOM));
  568.         if (!prepass)
  569.         {
  570.     p = MakeRoom(RULEFLEN);
  571.             *p++ = (RULE | type);
  572.             PushValue(p, left);
  573.             PushValue(p, (frame->width - right));
  574.             PushValue(p, dy);
  575. #ifdef STYLE_COLOR
  576.     *p++ = (Byte) StyleGet(S_COLOR);
  577. #endif
  578. #ifdef STYLE_BACKGROUND
  579.     PutPointer(&p, (void *)StyleGet(S_BACKGROUND)); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
  580. #endif
  581.         }
  582.     }
  583. }
  584. void PrintLine(Frame *frame, int left, int right, int top, int bottom)  /* staalesc 13/12/95 */
  585. {
  586.     Byte *p;
  587.     if (paintStartLine < 0)
  588.         TextLineFrame(frame);
  589.     if (!prepass)
  590.     {
  591.         p = MakeRoom(LINEFLEN);
  592.         *p++ = (LINE);
  593.         PushValue(p, left);
  594.         PushValue(p, right);
  595.         PushValue(p, top);
  596.         PushValue(p, bottom);
  597. #ifdef STYLE_COLOR
  598.       *p++ = (Byte) StyleGet(S_COLOR);
  599. #endif
  600. #ifdef STYLE_BACKGROUND
  601.       PutPointer(&p, (void *)StyleGet(S_BACKGROUND));
  602. #endif
  603.         above = max(above, 2); /* staalesc: Are these correct??? */
  604.         below = max(below, 2);
  605.     }
  606. }
  607. /* push bullet onto paint stream */
  608. void PrintBullet(Frame *frame, int depth, int font, int size)
  609. {
  610.     Byte *p;
  611.     if (paintStartLine < 0)
  612.         TextLineFrame(frame);
  613.     if (Here + B_SIZE> TextLineWidth)
  614.         TextLineWidth = Here + B_SIZE;
  615.     above = max(above, ASCENT(font));
  616.     below = max(below, DESCENT(font));
  617.     if (!prepass)
  618.     {
  619.         p = MakeRoom(BULLETFLEN);
  620.         *p++ = BULLET;
  621.         PushValue(p, Here);
  622.         PushValue(p, depth);
  623. *p++ = font; /*StyleGet(S_FONT);*/ /* howcome 25/4/95: adding vertical position of bullet item */
  624. *p++ = size; /*StyleGet(S_FONT_SIZE);*/ /* spif 8/1/96: size... */
  625. *p++ = (Byte) StyleGet(S_COLOR);
  626. #ifdef STYLE_BACKGROUND
  627.   PutPointer(&p, (void *)StyleGet(S_BACKGROUND)); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
  628. #endif
  629.     }
  630. }
  631. void WrapImageIfNeeded(Frame *frame, int align,
  632.                        int left, int right, int width, int up, int down)
  633. {
  634.     if (!preformatted)
  635.     {
  636.         if (Here > left && Here + width + 2 > frame->width - frame->rightmargin - right)
  637.         {
  638.             EndOfLine(frame, align);
  639.             Here = left;
  640.             above = up;
  641.             below = down;
  642.         }
  643.         else
  644.         {
  645.             if (up > above)
  646.                 above = up;
  647.             if (down > below)
  648.                 below = down;
  649.         }
  650.     }
  651.     else
  652.     {
  653.         if (up > above)
  654.             above = up;
  655.         if (down > below)
  656.             below = down;
  657.     }
  658. }
  659. void WrapFieldIfNeeded(Field *field, Frame *frame, int align, int left, int right)
  660. {
  661.     if (!preformatted)
  662.     {
  663.         if (Here > left && field->x + field->width > frame->width - frame->rightmargin - right)
  664.         {
  665.             EndOfLine(frame, align);
  666.             Here = left;
  667.             field->x = Here;
  668.             above = field->above;
  669.             below = field->height - above;
  670.         }
  671.         else
  672.         {
  673.             if (above < field->above)
  674.                 above = field->above;
  675.             if (below < field->height - field->above)
  676.                 below = field->height - above;
  677.         }
  678.     }
  679.     else
  680.     {
  681.         if (above < field->above)
  682.             above = field->above;
  683.         if (below < field->height - field->above)
  684.             below = field->height - field->above;
  685.     }
  686. }
  687. /* push text input field */
  688. void PrintInputField(Frame *frame, Field *field)
  689. {
  690.     Byte *p;
  691.     if (paintStartLine < 0)
  692.         TextLineFrame(frame);
  693.     if (field->x + field->width > TextLineWidth)
  694.         TextLineWidth = field->x + field->width;
  695.     if (!prepass)
  696.     {
  697.         p = MakeRoom(INPUTFLEN);
  698.         field->object = p - paint;
  699.         *p++ = INPUT;
  700. PutPointer(&p,(void *)field);
  701. #ifdef STYLE_BACKGROUND
  702. PutPointer(&p, (void *)StyleGet(S_BACKGROUND)); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
  703. #endif
  704.     }
  705. }
  706. /* push normal or preformatted string */
  707. /* emph contains font and emphasis */
  708. void RealPrintString(Frame *frame, unsigned int emph, int font,
  709.                     int delta, char *ref, char *buf, int len, int width, BOOL tight_font, Byte text_color, BG_Style *text_background)
  710. {
  711.     Byte *p;
  712. /*    int indent; */
  713. /*    indent = Here + LeftMarginIndent;*/ /* figures on LHS */
  714. /*    indent = Here + style->margin_left;*/ /* howcome 21/2/95 */
  715.     if (paintStartLine < 0)
  716.         TextLineFrame(frame);
  717.     if (!prepass)
  718.         p = MakeRoom(STRINGFLEN);
  719.     if (Here + width > TextLineWidth)
  720.         TextLineWidth = Here + width;
  721.     /* In the case of a big initial, the descent should be calculated
  722.        specifically for the character in question */
  723.     if (tight_font) {
  724. above = max(above, Fonts[font]->per_char[*buf].ascent);
  725. /*
  726. if (above == 0)
  727.     above = max(above, ASCENT(font));
  728. */
  729. below = max(below, Fonts[font]->per_char[*buf].descent);
  730. /*
  731. if (below == 0)
  732.     below = max(below, DESCENT(font));
  733. */
  734.     } else {
  735. if (!StyleGetFlag(S_LEADING_FLAG))
  736.     above = max(above, ASCENT(font) + (int)StyleGet(S_FONT_LEADING));
  737. else
  738.     above = max(above, ASCENT(font));
  739. below = max(below, DESCENT(font)); /* howcome 28/8/95: is this the right place to add leading? */
  740.     }                                      /* --Spif 13-Nov-95 this was not the right place ;) */
  741.     if (!prepass)
  742.     {
  743.         *p++ = (preformatted ? (STRING | PRE_TEXT) : STRING);
  744. PushValue (p, emph);
  745.         *p++ = font;
  746. if ( StyleGetFlag(S_INDENT_FLAG))
  747. {
  748.     /*   Here += StyleGet(S_INDENT); */
  749.     Here += StyleGetFlag(S_INDENT_FLAG); /* flag carrying a value... hum... --Spif 14-Nov-95 */
  750.     StyleSetFlag(S_INDENT_FLAG,FALSE);
  751. };
  752. if (StyleGetFlag(S_MARGIN_TOP_FLAG)) /* this is the right place for this, but it doesn't work... yet ;) --Spif 16-Jan-96 */
  753. {
  754.     PixOffset += StyleGetFlag(S_MARGIN_TOP_FLAG);
  755.     StyleSetFlag(S_MARGIN_TOP_FLAG, FALSE);
  756. };
  757. #ifdef STYLE_COLOR
  758. *p++ = text_color;
  759. #endif
  760. #ifdef STYLE_BACKGROUND
  761. PutPointer(&p,(void *)text_background); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
  762. #endif
  763.         *p++ = delta + 128;  /* baseline offset 128 is zero, 255 is +127, 0 is -128 */
  764. /*
  765. if (frame->leftcount) {
  766.     PushValue(p, Here - style->margin_left);
  767. } else {
  768. */
  769.     PushValue(p, Here);
  770. /* }*/
  771.         PushValue(p, len);
  772.         PushValue(p, width);
  773. PutPointer(&p, (void *)buf);
  774. PutPointer(&p, (void *)ref);
  775.     }
  776. }
  777. void PrintString(Frame *frame, unsigned int emph, int font,
  778.                     int delta, char *buf, int len, int width, int wrapped)
  779. {
  780.     int i, j, k, fix, index, icw = 0;
  781.     int sc_width,dumpint; /* --Spif 5/10/95 small caps fix */
  782.     int OldTextLineWidth, OldHere; 
  783.     BOOL emph_set = FALSE;
  784.     BOOL ok;
  785.     char dump_char[2];
  786.     fix = (int)StyleGet(S_FONT);
  787.     if ( ((int)StyleGet(S_TEXT_EFFECT) == TEXT_EFFECT_INITIAL_CAP) && (StyleGetFlag(S_INITIAL_FLAG)) ) {
  788. int alt_fix = (int)StyleGet(S_ALT_FONT);
  789. RealPrintString(frame, (emph_set ? 0 : emph), alt_fix, delta, buf, buf, 1, width, 
  790. TRUE, (Byte) StyleGet(S_ALT_COLOR), (BG_Style *)StyleGet(S_ALT_BACKGROUND) );
  791. emph_set = TRUE;
  792. icw = XTextWidth(Fonts[alt_fix], buf, 1);
  793. Here += icw;
  794. StyleSetFlag(S_INITIAL_FLAG, False);
  795. buf++; len--;
  796.     }
  797.     
  798.     StyleSetFlag(S_FONT_LEADING,FALSE);
  799.     if ((int)StyleGet(S_FONT_STYLE) == FONT_STYLE_SMALL_CAPS) {
  800. int sc_fix = (int)StyleGet(S_SMALL_CAPS_FONT);
  801. for(i=k=0; k<len; i++, k++) {
  802.     sc_width=CompoundTextWidth(buf + i, 0, 1,&dumpint) + (int)StyleGet(S_TEXT_SPACING); /* a hack... rename this stuff */
  803.     OldTextLineWidth = TextLineWidth ;    /* --Spif 6-Oct-95 keep this to update TextLineWidth with the right width */     
  804.     OldHere = Here;
  805.     /* we must give the entire width if it is emphasized, to tell the paint stream to display a beeautiful box around
  806.        the text, but the real TextLineWidth must be calculated with the width of only ONE character at a time */
  807.     if (buf[i]=='&') {
  808. for(ok= FALSE,j=i; !ok && j<len; j++)
  809.             ok = ((buf[j]==';') || (buf[j]==' '));  /* ' ' is here for dummy html writers ;) */
  810. index = *dump_char = (char)entity(buf+i+1, &j);
  811. if (index < 0)
  812.     index+=256; 
  813. dump_char[1]=0;
  814.   RealPrintString(frame, (emph_set ? 0 : emph), sc_fix, delta, buf, &small_caps[index], 1, width,  /* how can we capitalize entities? */
  815. FALSE, (Byte) StyleGet(S_COLOR), (BG_Style *)StyleGet(S_BACKGROUND));
  816. emph_set = TRUE;
  817. if(((index + small_caps[index]) % 256))
  818.     Here += XTextWidth(Fonts[sc_fix], dump_char,1) + (int)StyleGet(S_TEXT_SPACING);
  819. else
  820.     Here += XTextWidth(Fonts[fix], dump_char,1) + (int)StyleGet(S_TEXT_SPACING);
  821. i += j -1;
  822.     } else if (islower(buf[i])) {
  823. RealPrintString(frame, (emph_set ? 0 : emph), sc_fix, delta, buf, &small_caps[buf[i]], 1, width,
  824. FALSE, (Byte) StyleGet(S_COLOR), (BG_Style *)StyleGet(S_BACKGROUND));
  825. emph_set = TRUE;
  826.   Here += XTextWidth(Fonts[sc_fix], &small_caps[buf[i]], 1) + (int)StyleGet(S_TEXT_SPACING); 
  827.     } else if (isdigit(buf[i])) {
  828. RealPrintString(frame, (emph_set ? 0 : emph), sc_fix, delta, buf, &small_caps[buf[i]], 1, width, 
  829. FALSE, (Byte) StyleGet(S_COLOR), (BG_Style *)StyleGet(S_BACKGROUND));
  830. emph_set = TRUE;
  831. Here += XTextWidth(Fonts[sc_fix], &small_caps[buf[i]], 1) + (int)StyleGet(S_TEXT_SPACING); 
  832.     } else {
  833. RealPrintString(frame, (emph_set ? 0 : emph), fix, delta, buf, &small_caps[buf[i]], 1, width, 
  834. FALSE, (Byte) StyleGet(S_COLOR), (BG_Style *)StyleGet(S_BACKGROUND));
  835. emph_set = TRUE;
  836. Here += XTextWidth(Fonts[fix], &small_caps[buf[i]], 1) + (int)StyleGet(S_TEXT_SPACING); 
  837.     }
  838.     if( OldHere + sc_width > OldTextLineWidth)  /* -- Spif: 6-Oct-95 small caps fix */ 
  839.         TextLineWidth = OldHere + sc_width;
  840.  };
  841. TextLineWidth -= (int)StyleGet(S_TEXT_SPACING);
  842. Here -= (int)StyleGet(S_TEXT_SPACING);
  843.     } else if(StyleGet(S_TEXT_SPACING))
  844.     {
  845. for(i=k=0; k<len; i++, k++) {
  846.     sc_width=CompoundTextWidth(buf + i, 0, 1,&dumpint) + (int)StyleGet(S_TEXT_SPACING); /* a hack... rename this stuff */
  847.     OldTextLineWidth = TextLineWidth ;  
  848.     OldHere = Here;
  849.     /* we must give the entire width if it is emphasized, to tell the paint stream to display a beautiful box around
  850.        the text, but the real TextLineWidth must be calculated with the width of only ONE character at a time */
  851.     
  852.     if (buf[i]=='&') {
  853. for(ok= FALSE,j=i; !ok && j<len; j++)
  854.     ok = ((buf[j]==';') || (buf[j]==' '));  /* ' ' is here for dummy html writers ;) */
  855. RealPrintString(frame, (emph_set ? 0 : emph), fix, delta, buf, buf + i, 1, width,  /* how can we capitalize entities? */
  856. FALSE, (Byte) StyleGet(S_COLOR), (BG_Style *)StyleGet(S_BACKGROUND));
  857. emph_set = TRUE;
  858. *dump_char = entity(buf+i+1, &j);
  859. dump_char[1]=0;
  860.   Here += XTextWidth(Fonts[fix], dump_char,1) + (int)StyleGet(S_TEXT_SPACING);
  861. i += j -1;
  862.     } 
  863.     else {
  864. RealPrintString(frame, (emph_set ? 0 : emph), fix, delta, buf, buf + i, 1, width, 
  865. FALSE, (Byte) StyleGet(S_COLOR), (BG_Style *)StyleGet(S_BACKGROUND));
  866. emph_set = TRUE;
  867. Here += XTextWidth(Fonts[fix], buf + i, 1) + (int)StyleGet(S_TEXT_SPACING); 
  868.     }
  869.     if( OldHere + sc_width > OldTextLineWidth)
  870.         TextLineWidth = OldHere + sc_width;
  871. };
  872. TextLineWidth -= (int)StyleGet(S_TEXT_SPACING);
  873. Here -= + (int)StyleGet(S_TEXT_SPACING);
  874.     } else {
  875. if(frame->flow != ALIGN_JUSTIFY)
  876.     RealPrintString(frame, (emph_set ? 0 : emph), fix, delta, buf, buf, len, width, 
  877.     FALSE, (Byte) StyleGet(S_COLOR), (BG_Style *)StyleGet(S_BACKGROUND));
  878. else
  879. {
  880.     int nb_space = 0;
  881.     int remaining_space;
  882.     
  883.     
  884.     for(k=0; k<len; k++)
  885. nb_space += (buf[k]==' ')||(buf[k]=='n');
  886.     if(!nb_space || !wrapped){
  887. RealPrintString(frame, (emph_set ? 0 : emph), fix, delta, buf, buf, len, width, 
  888. FALSE, (Byte) StyleGet(S_COLOR), (BG_Style *)StyleGet(S_BACKGROUND));
  889.     }
  890.     else
  891.     {
  892. remaining_space = frame->width - width - Here - StyleGetFlag(S_INDENT_FLAG);
  893. #if 1
  894. /* printf("len %d :nbspace %d : remaining_space %dn", len, nb_space, remaining_space);
  895.  * printf("width %d, frame->width %d, frame->indent %d, Here %dn", width, frame->width, frame->indent, Here);
  896.  */ 
  897. for(i=k=0; k<len; i++, k++) {
  898.     if(buf[i]=='n')
  899. sc_width=XTextWidth(Fonts[fix], " ", 1) + (remaining_space/(nb_space ? nb_space :1));
  900.     else
  901. sc_width=CompoundTextWidth(buf + i, 0, 1,&dumpint) + (*(buf+i)==' ')*(remaining_space/(nb_space ? nb_space :1));
  902.     OldTextLineWidth = TextLineWidth ;  
  903.     OldHere = Here;
  904.     /* we must give the entire width if it is emphasized, to tell the paint stream to display a beeautiful box around
  905.        the text, but the real TextLineWidth must be calculated with the width of only ONE character at a time */
  906.     
  907.     if (buf[i]=='&') {
  908. for(ok= FALSE,j=i; !ok && j<len; j++)
  909.     ok = ((buf[j]==';') || (buf[j]==' '));  /* ' ' is here for dummy html writers ;) */
  910. RealPrintString(frame, (emph_set ? 0 : emph), fix, delta, buf, buf + i, 1, width,  /* how can we capitalize entities? */
  911. FALSE, (Byte) StyleGet(S_COLOR), (BG_Style *)StyleGet(S_BACKGROUND));
  912. emph_set = TRUE;
  913. *dump_char = entity(buf+i+1, &j);
  914. dump_char[1]=0;
  915. Here += XTextWidth(Fonts[fix], dump_char,1);
  916. i += j -1;
  917.     } 
  918.     else {
  919. if(buf[i]=='n')
  920. {
  921.     emph_set = TRUE;
  922.     Here += XTextWidth(Fonts[fix], " ", 1) + (remaining_space/(nb_space ? nb_space :1)); 
  923.     remaining_space -= (remaining_space/(nb_space ? nb_space :1));
  924.     nb_space--;
  925. }
  926. else
  927. {
  928.     RealPrintString(frame, (emph_set ? 0 : emph), fix, delta, buf, buf + i, 1, width, 
  929.     FALSE, (Byte) StyleGet(S_COLOR), (BG_Style *)StyleGet(S_BACKGROUND));
  930.     emph_set = TRUE;
  931.     Here += XTextWidth(Fonts[fix], buf + i, 1) + (*(buf+i)==' ')*(remaining_space/(nb_space ? nb_space :1)); 
  932.     if(*(buf+i)==' ')
  933.     {
  934. remaining_space -= (remaining_space/(nb_space ? nb_space :1));
  935. nb_space--;
  936.     }
  937. }
  938.     }
  939.     if( OldHere + sc_width > OldTextLineWidth)
  940. TextLineWidth = OldHere + sc_width;
  941. }
  942. #else
  943.     RealPrintString(frame, (emph_set ? 0 : emph), fix, delta, buf, buf, len, width, 
  944.     FALSE, (Byte) StyleGet(S_COLOR), (BG_Style *)StyleGet(S_BACKGROUND));
  945. #endif
  946.     }
  947. }
  948. emph_set = TRUE;
  949. Here += (width - icw);
  950.     }
  951. }
  952. int CompoundTextWidth(char *s, int start, int len, int *space_p)
  953. {
  954.     int width = 0, i, k, j, ok;
  955.     int fix = (int)StyleGet(S_FONT);
  956.     char dump_char[2];
  957.     if (((int)StyleGet(S_TEXT_EFFECT) == TEXT_EFFECT_INITIAL_CAP) && (StyleGetFlag(S_INITIAL_FLAG))) {
  958. int alt_fix = (int)StyleGet(S_ALT_FONT);
  959. width += XTextWidth(Fonts[alt_fix], s, 1);
  960. start++; len--;
  961.     }
  962.     if ((int)StyleGet(S_FONT_STYLE) == FONT_STYLE_SMALL_CAPS) {
  963. for(i=k=start; k < (len + start); i++,k++) {
  964.     width += (int)StyleGet(S_TEXT_SPACING);
  965.     if (islower(s[i]))
  966. width += XTextWidth(Fonts[(int)StyleGet(S_SMALL_CAPS_FONT)], &small_caps[s[i]], 1);
  967.     else if (s[i]=='&') {
  968. for(ok= FALSE,j=i; !ok && j<(len+start); j++)
  969.     ok = ((s[j]==';') || (s[j]==' ')); 
  970. *dump_char = entity(s+i+1, &j);
  971. dump_char[1]=0;
  972. i+=j-1;
  973. width += XTextWidth(Fonts[(int)StyleGet(S_SMALL_CAPS_FONT)], dump_char, 1);
  974.     } else if (isdigit(s[i])) {
  975. width += XTextWidth(Fonts[(int)StyleGet(S_SMALL_CAPS_FONT)], s + i, 1);
  976.     } else
  977. width += XTextWidth(Fonts[fix], s + i, 1);
  978. }
  979. *space_p = XTextWidth(Fonts[(int)StyleGet(S_SMALL_CAPS_FONT)], " ", 1) + (int)StyleGet(S_TEXT_SPACING);
  980. return width;
  981.     } else if(StyleGet(S_TEXT_SPACING)) {
  982. for(i=k=start; k < (len + start); i++,k++) {
  983.     width += (int)StyleGet(S_TEXT_SPACING);
  984.     if (s[i]=='&') {
  985. for(ok= FALSE,j=i; !ok && j<(len+start); j++)
  986.     ok = ((s[j]==';') || (s[j]==' ')); 
  987. *dump_char = entity(s+i+1, &j);
  988. dump_char[1]=0;
  989. i+=j-1;
  990. width += XTextWidth(Fonts[fix], dump_char, 1);
  991.     } else
  992. width += XTextWidth(Fonts[fix], s + i, 1);
  993. }
  994. *space_p = XTextWidth(Fonts[fix], " ", 1) + (int)StyleGet(S_TEXT_SPACING); /* WORD_SPACING instead */
  995. return width;
  996.     } else {
  997. *space_p = XTextWidth(Fonts[fix], " ", 1);
  998. return (width + XTextWidth(Fonts[fix], s + start, len));
  999.     }
  1000. }
  1001. /* Push explicit text onto paint stream */
  1002. void PrintSeqText(Frame *frame, unsigned int emph, int font, char *s, int width)
  1003. {
  1004.     Byte *p;
  1005.     int len;
  1006.     if (paintStartLine < 0)
  1007.         TextLineFrame(frame);
  1008.     if (!prepass)
  1009.     {
  1010.         len = strlen(s);
  1011.         p = MakeRoom(SEQTEXTFLEN(len));
  1012.         if (Here + width > TextLineWidth)
  1013.             TextLineWidth = Here + width;
  1014.         above = max(above, ASCENT(font));
  1015.         below = max(below, DESCENT(font));
  1016.         *p++ = SEQTEXT;
  1017. PushValue (p, emph);
  1018.         *p++ = font;
  1019. #ifdef STYLE_COLOR
  1020. *p++ = (Byte) StyleGet(S_COLOR);
  1021. #endif
  1022. #ifdef STYLE_BACKGROUND
  1023.    PutPointer(&p, (void *)StyleGet(S_BACKGROUND)); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
  1024. #endif
  1025.         PushValue(p, Here);
  1026.         PushValue(p, 0);
  1027.         *p++ = len;
  1028.         memcpy(p, s, len);
  1029.     }
  1030. }
  1031. /* for use by html-math parser */
  1032. int TextWidth(int font, char *str, int len, int *up, int *down)
  1033. {
  1034.     *up = Fonts[font]->max_bounds.ascent;
  1035.     *down = Fonts[font]->max_bounds.descent;
  1036.     return XTextWidth(Fonts[font], str, len);
  1037. }
  1038. /* for use by html-math parser */
  1039. void FontSize(int font, int *ascent, int *descent)
  1040. {
  1041.     *ascent = Fonts[font]->max_bounds.ascent;
  1042.     *descent = Fonts[font]->max_bounds.descent;
  1043. }
  1044. box *CreateBox(int x, int y, int width, int height)
  1045. {
  1046.     box *new_box;
  1047.     
  1048.     new_box = (box *)malloc(sizeof(box));
  1049.     
  1050.     if(!new_box)
  1051.     {
  1052. fprintf(stderr, "Ran Out of memory in CreateBox, Exitingn");
  1053. exit(1);
  1054.     }
  1055.     new_box->x      = x;
  1056.     new_box->y      = y;
  1057.     new_box->width  = width;
  1058.     new_box->height = height;
  1059.     
  1060.     return new_box;
  1061. }
  1062. void AddBox(Frame *frame, int x, int y, int width, int height)
  1063. {
  1064.     box_link *new_link;
  1065.     box      *new_box;
  1066.     if(!frame)
  1067. return;
  1068. #if 0
  1069.     printf("Adding Box %d,%d -> %d,%dn", x, y, width, height); 
  1070. #endif
  1071.     new_link = (box_link *)malloc(sizeof(box_link));
  1072.     if(!new_link)
  1073.     {
  1074.      fprintf(stderr, "Ran Out of memory in AddBox, Exitingn");
  1075. exit(1);
  1076.     }
  1077.     new_link->box  = CreateBox(x, y, width, height);
  1078.     new_link->next = frame->box_list; /* we add the box in first position */
  1079.     frame->box_list = new_link;
  1080. }
  1081. box *IsInBox(Frame *frame, int x, int y)
  1082. {
  1083.     box_link *curr_box;
  1084.     box_link *is_in;
  1085.     if(!frame)
  1086. return 0;
  1087.     for(is_in=NULL, curr_box = frame->box_list;!is_in && curr_box; curr_box = curr_box->next)
  1088. if((x >= curr_box->box->x) && (x <= curr_box->box->x + curr_box->box->width)
  1089.    && (y >= curr_box->box->y) && (y <= curr_box->box->y + curr_box->box->height))
  1090.     is_in = curr_box;
  1091.     return (is_in) ? is_in->box : NULL;
  1092. }
  1093. void CopyBoxList(Frame *dest_frame, Frame *frame)
  1094. {
  1095.     box_link *curr_box;
  1096.     if(!(dest_frame && frame))
  1097. return;
  1098.     
  1099.     for(curr_box = frame->box_list;curr_box; curr_box = curr_box->next)
  1100. AddBox(dest_frame, curr_box->box->x, curr_box->box->y, curr_box->box->width, curr_box->box->height);
  1101. }
  1102. int RightMargin(Frame *frame, int right, int voffset)
  1103. {
  1104.     int rightMargin;
  1105.     box *thebox;
  1106.     if (frame == &background)
  1107.     {
  1108.         rightMargin = background.width - background.rightmargin - right;
  1109.         if (rightMargin > WinWidth - 4)
  1110.             rightMargin = WinWidth - 4;
  1111.         rightMargin -= frame->leftmargin;
  1112.     }
  1113.     else
  1114.         rightMargin = frame->width - right /*- frame->leftmargin - frame->rightmargin*/;
  1115.     if(frame)
  1116.     {
  1117. thebox = IsInBox(frame, rightMargin, voffset);
  1118. while(thebox)
  1119. {
  1120.     rightMargin = thebox->x - 1;
  1121.     thebox = IsInBox(frame, rightMargin, voffset);
  1122. }
  1123.     }
  1124.     return rightMargin;
  1125. }
  1126. int LeftMargin(Frame *frame, int left, int voffset)
  1127. {
  1128.     int current_left;
  1129.     box *thebox;
  1130.     current_left = left;
  1131.     if(frame)
  1132.     {
  1133. thebox = IsInBox(frame, current_left, voffset);
  1134. while(thebox)
  1135. {
  1136.     current_left = thebox->x + thebox->width + 1;
  1137.     thebox = IsInBox(frame, current_left, voffset);
  1138. }
  1139.     }
  1140.     return current_left;
  1141. }
  1142. int Width(Frame *frame, int voffset)
  1143. {
  1144.     return frame->width;
  1145. }
  1146. void PutText(Frame *frame, unsigned int emph, int font, char *s, int len, int x, int y)
  1147. {
  1148.     Byte *p;
  1149.     if (paintStartLine < 0)
  1150.         TextLineFrame(frame);
  1151.     if (!prepass)
  1152.     {
  1153.         p = MakeRoom(SEQTEXTFLEN(len));
  1154.         *p++ = SEQTEXT;
  1155. PushValue (p, emph);
  1156.         *p++ = font;
  1157. #ifdef STYLE_COLOR
  1158. *p++ = (Byte) StyleGet(S_COLOR);
  1159. #endif
  1160. #ifdef STYLE_BACKGROUND
  1161.   PutPointer(&p, (void *)StyleGet(S_BACKGROUND)); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
  1162. #endif
  1163. PushValue(p, x);
  1164.         PushValue(p, y);
  1165.         *p++ = len;
  1166.         memcpy(p, s, len);
  1167.     }
  1168. }
  1169. /* buf points to start of element in html source iff ismap is present */
  1170. void PrintImage(Frame *frame, int delta, unsigned int emph,
  1171.                 char *buf, Image *image, unsigned int width, unsigned int height)
  1172. {
  1173.     Byte *p;
  1174.     Pixmap pixmap = 0;
  1175.     if (image)
  1176. pixmap = image->pixmap;
  1177.     if (paintStartLine < 0)
  1178.         TextLineFrame(frame);
  1179.     if (Here + width > TextLineWidth)
  1180.         TextLineWidth = Here + width;
  1181.     if (prepass)  /* just update min/max widths */
  1182.     {
  1183.         if (width > min_width)
  1184.             min_width = width;
  1185.     }
  1186.     else
  1187.     {
  1188.         p = MakeRoom(IMAGEFLEN);
  1189.         *p++ = (IMAGE & 0xF) | (emph & (ISMAP | EMPH_ANCHOR | EMPH_INPUT ));
  1190.         PushValue(p, delta);
  1191.         PushValue(p, Here);
  1192.         PushValue(p, width);
  1193.         PushValue(p, height);
  1194. PutPointer(&p,(void *)pixmap);
  1195. PutPointer(&p, (void *)buf);
  1196. #ifdef STYLE_BACKGROUND
  1197. PutPointer(&p, (void *)StyleGet(S_BACKGROUND)); /* must be set to the structures defined by the style --Spif 18-Oct-95 */
  1198. #endif
  1199.     }
  1200. }
  1201. #define NOBREAK 0
  1202. #define BREAK   1
  1203. /* check if current word forces word wrap and flush line as needed */
  1204. void WrapIfNeeded(Frame *frame, int align, unsigned int emph, int font, int left, int right)
  1205. {
  1206.     int WordLen, space, rightMargin;
  1207.     long line;
  1208.     if (paintStartLine < 0)
  1209.         TextLineFrame(frame);  /* alters the flow margins, if a figure just ended */
  1210.    
  1211. #ifdef OLD
  1212.     if (frame == &background)
  1213.     {
  1214.         rightMargin = background.width - background.rightmargin - right;
  1215.         if (rightMargin > WinWidth - 4)
  1216.             rightMargin = WinWidth - 4;
  1217.         rightMargin -= frame->leftmargin;
  1218.     }
  1219.     else
  1220.         rightMargin = frame->width - right /*- frame->leftmargin - frame->rightmargin*/;
  1221. #else
  1222.     rightMargin = RightMargin(frame, right, PixOffset);
  1223. #endif
  1224.     if(StyleGetFlag(S_INDENT_FLAG))
  1225. rightMargin -= StyleGetFlag(S_INDENT_FLAG);
  1226.     LineBuf[LineLen] = '';  /* debug*/
  1227.     WordLen = LineLen - WordStart;
  1228. /*    WordWidth = XTextWidth(Fonts[font], LineBuf+WordStart, WordLen);*/
  1229.     WordWidth = CompoundTextWidth(LineBuf, WordStart, WordLen, &space);
  1230. /*    space = XTextWidth(Fonts[StyleGet(S_FONT)], " ", 1);*/    /* width of a space char */
  1231. /*    space = XTextWidth(Fonts[font], " ", 1);   */ /* width of a space char */
  1232.     line = LineSpacing[font];                   /* height of a line */
  1233.     if (WordWidth > min_width)      /* for tables */
  1234.         min_width = WordWidth;
  1235.     if (prepass)
  1236.     {
  1237.         TextLineWidth += WordWidth;
  1238.         LineWidth = LineLen = WordStart = 0;
  1239.         StartOfLine = bufptr;
  1240.     }
  1241.     else if (WordStart == 0 && Here + WordWidth > rightMargin)
  1242.     {
  1243.         /* word wider than window */
  1244.         if (left + WordWidth > rightMargin)
  1245.         {
  1246.             if (emph & EMPH_ANCHOR)
  1247.                 WordWidth += 2;
  1248.             PrintString(frame, emph, font, voffset, StartOfLine, WordLen, WordWidth, FALSE);
  1249.             EndOfLine(frame, align);
  1250.     LineWidth = LineLen = WordStart = 0;
  1251.             StartOfLine = bufptr;
  1252.         }
  1253.         else /* wrap to next line */
  1254.         {
  1255.             EndOfLine(frame, align);
  1256.     LineWidth = WordWidth;
  1257.             LineLen = WordLen;
  1258.             WordStart = LineLen;
  1259.             StartOfLine = StartOfWord;
  1260.         }
  1261.         Here = LeftMargin(frame, left, PixOffset);
  1262.     }
  1263.     else if (WordStart > 0 && Here + LineWidth + space + WordWidth > rightMargin)
  1264.     {
  1265.         if (emph & EMPH_ANCHOR)
  1266.             LineWidth += 2;
  1267.         PrintString(frame, emph, font, voffset, StartOfLine, WordStart-1, LineWidth, TRUE);
  1268.         EndOfLine(frame, align);
  1269.         Here = left;
  1270.      /* was memmove(LineBuf, LineBuf+WordStart, WordLen); 
  1271.         but memmove not available for SUNs and
  1272.         memcpy screws up for overlapping copies */
  1273.         {
  1274.             int n;
  1275.             char *p, *q;
  1276.             n = WordLen;
  1277.             p = LineBuf;
  1278.             q = LineBuf+WordStart;
  1279.             while (n-- > 0)
  1280.                 *p++ = *q++;
  1281.         }
  1282.         LineWidth = WordWidth;
  1283.         LineLen = WordLen;
  1284.         WordStart = LineLen;
  1285.         StartOfLine = StartOfWord;
  1286.     }
  1287.     else /* word will fit on end of current line */
  1288.     {
  1289.         if (WordStart > 0)
  1290.             LineWidth += space;
  1291.         if (WordWidth > 0)
  1292.             LineWidth += WordWidth;
  1293.         WordStart = LineLen;
  1294.     }
  1295. }
  1296. void FlushLine(int linebreak, Frame *frame, int align,
  1297.                 unsigned int emph, int font, int left, int right)
  1298. {
  1299.     int WordLen, space; /* janet: not used: delta, rightMargin */
  1300. /*    *StartOfLine = toupper(*StartOfLine);*//* howcome playing 5/5/95 */
  1301.     if (preformatted)
  1302.     {
  1303.         WordLen = LineLen - WordStart;
  1304. /*        LineWidth = XTextWidth(Fonts[font], LineBuf+WordStart, WordLen);*/
  1305.         LineWidth = CompoundTextWidth(LineBuf, WordStart, WordLen, &space);
  1306.     }
  1307.     else if (LineLen > 1 || (LineLen == 1 && LineBuf[0] != ' '))
  1308.         WrapIfNeeded(frame, align, emph, font, left, right);
  1309.     if (LineLen > 0)
  1310.     {
  1311.         if (emph & EMPH_ANCHOR)
  1312.             LineWidth += 2;
  1313.         /* watch out for single space as leading spaces
  1314.            are stripped by CopyLine */
  1315.         if (LineLen > 1 || LineBuf[0] != ' ')
  1316.             PrintString(frame, emph, font, voffset, StartOfLine, LineLen, LineWidth, FALSE);
  1317.         if (linebreak)
  1318.         {
  1319.             EndOfLine(frame, align);
  1320.             Here = left;
  1321.         }
  1322. /*
  1323.         else
  1324.             Here += LineWidth;
  1325. */
  1326.         LineWidth = LineLen = WordStart = 0;
  1327.     }
  1328.     else if (linebreak)
  1329.     {
  1330. /* watch out for empty preformatted lines */
  1331.         if (preformatted && TextLineWidth == 0)
  1332.             PixOffset += ASCENT(font) + DESCENT(font);
  1333.         if (paintStartLine >= 0)  /* was if (Here > left) */
  1334.         {
  1335.             EndOfLine(frame, align);
  1336.             Here = left;
  1337.         }
  1338.     }
  1339.     StartOfLine = StartOfWord = bufptr;
  1340. }
  1341. /* needs to cope with > in quoted text for ' and " */
  1342. void SwallowAttributes(void)
  1343. {
  1344.     int c;
  1345.     while ((c = *bufptr) && c != '>')
  1346.     {
  1347.         ++bufptr;
  1348.     }
  1349.     if (c == '>')
  1350.         ++bufptr;
  1351. }
  1352. /*
  1353.  Return a pointer to the ">" in an end comment (or to "" if there
  1354.  isn't one).  Example:
  1355.     "hiya <!-- <foo>there</foo> -- --whatever-- > there"
  1356.  pass this -^                      return this -^
  1357.  */
  1358. char *FindEndComment( char *ptr )
  1359. {
  1360.     char c, *s;
  1361. for(;;)
  1362. {
  1363. ptr += 2; /* first character after opening "--" */
  1364. if(!((s = strstr(ptr, "--")))) break;
  1365. ptr = s + 1; /* second "-" -- ++ will put us on the next character */
  1366. /* Skip past the optional white space (<= ' ' from GetToken) */
  1367. while((c=*(++ptr)) && c <= ' ');
  1368. if(c == '>')
  1369. {
  1370. return ptr; /* comment terminated correctly */
  1371. }
  1372. if(!strncmp(ptr, "--", 2))
  1373. {
  1374. /* comment is something like "<!--fine-- wrong>" */
  1375. if(s=strchr(ptr,'>')) return s;
  1376. break;
  1377. }
  1378. }
  1379. /* Document ends in unfinished comment -- seek for '0' */
  1380. if(*ptr) while(*(++ptr));
  1381. return ptr;
  1382. }
  1383. /*
  1384.  char *tag points to start of tag string which is terminated
  1385.  by whitespace (including EOF) or a '>' character.
  1386.  return tag code or 0 if unknown.
  1387. */
  1388. int RecogniseTag(void)
  1389. {
  1390.     int c, len;
  1391.     char *s;
  1392.      s = bufptr + 1;
  1393.   
  1394.     /* handle comments correctly -- code by mlvanbie@valeyard.uwaterloo.ca */
  1395.     if (*s == '!' && (*(s+1) == '-') && (*(s+2) == '-'))
  1396.     {
  1397.         bufptr += 4; /* eat "<!--" */
  1398.         EndTag = 0;
  1399.      TagLen = 0;  /* we will be manipulating bufptr directly */
  1400.         TokenClass = EN_UNKNOWN;
  1401. bufptr = FindEndComment( bufptr + 2 );    /* +2: eat "<!" */
  1402. #if 0
  1403.         while ((s = strstr(bufptr, "--")))
  1404.         {
  1405.             bufptr = s + 1; /* stay on second "-" */
  1406.         /* Skip past the optional white space (<= ' ' from GetToken) */
  1407.         while((c=*(++bufptr)) && c <= ' ');
  1408.             if(c == '>')
  1409.             {
  1410.                 return UNKNOWN; /* pretend we have an unknown tag */
  1411.             }
  1412.             bufptr = s + 1; /* handles "<!-- ... --->" (nonoptimal) */
  1413.         }
  1414.         /* Document ends in unfinished comment -- seek for '0' */
  1415.         if(*bufptr) while(*(++bufptr));
  1416. #endif
  1417.         return UNKNOWN; /* unknown tag */
  1418.     }
  1419.     if (*s == '/')
  1420.     {
  1421.         EndTag = 1;
  1422.         ++s;
  1423.     }
  1424.     else
  1425.         EndTag = 0;
  1426.     if ((c = *s) == '!' || c == '?')
  1427.         ++s;
  1428.     else if (c != '>' && !isalpha(c))
  1429.         return PCDATA;
  1430.   /* find end of tag to allow use of strncasecmp */
  1431.     while ((c = *s, isalpha(c)) || isdigit(c))
  1432.         ++s;
  1433.     TagLen = s - bufptr;        /* how far to next char after tag name */
  1434.     len = TagLen - EndTag - 1;  /* number of chars in tag name itself */
  1435.     s -= len;
  1436.     c = TOLOWER(*s);
  1437.     if (isalpha(c))
  1438.     {
  1439.         if (c == 'a')
  1440.         {
  1441.             if (len == 1 && strncasecmp(s, "a", len) == 0)
  1442.             {
  1443.                 TokenClass = EN_TEXT;
  1444.                 return TAG_ANCHOR;
  1445.             }
  1446.             if (len == 3 && strncasecmp(s, "alt", len) == 0)
  1447.             {
  1448.                 TokenClass = EN_BLOCK;
  1449.                 return TAG_ALT;
  1450.             }
  1451.             if (len == 5 && strncasecmp(s, "added", len) == 0)
  1452.             {
  1453.                 TokenClass = EN_TEXT;
  1454.                 return TAG_ADDED;
  1455.             }
  1456.             if (len == 7 && strncasecmp(s, "address", len) == 0)
  1457.             {
  1458.                 TokenClass = EN_BLOCK;
  1459.                 return TAG_ADDRESS;
  1460.             }
  1461.             if (len == 8 && strncasecmp(s, "abstract", len) == 0)
  1462.             {
  1463.                 TokenClass = EN_BLOCK;
  1464.                 return TAG_ABSTRACT;
  1465.             }
  1466.         }
  1467.         else if (c == 'b')
  1468.         {
  1469.             if (len == 1)
  1470.             {
  1471.                 TokenClass = EN_TEXT;
  1472.                 return TAG_BOLD;
  1473.             }
  1474.             if (len == 2 && strncasecmp(s, "br", len) == 0)
  1475.             {
  1476.                 TokenClass = EN_TEXT;
  1477.                 return TAG_BR;
  1478.             }
  1479.             if (len == 4 && strncasecmp(s, "body", len) == 0)
  1480.             {
  1481.                 TokenClass = EN_MAIN;
  1482.                 return TAG_BODY;
  1483.             }
  1484.             if (len == 10 && strncasecmp(s, "blockquote", len) == 0)
  1485.             {
  1486.                 TokenClass = EN_BLOCK;
  1487.                 return TAG_QUOTE;
  1488.             }
  1489.             if (len == 4 && strncasecmp(s, "base", len) == 0)
  1490.             {
  1491.                 TokenClass = EN_SETUP;
  1492.                 return TAG_BASE;
  1493.             }
  1494.         }
  1495.         else if (c == 'c')
  1496.         {
  1497.             if (len == 4)
  1498.             {
  1499.                 if (strncasecmp(s, "code", len) == 0)
  1500.                 {
  1501.                     TokenClass = EN_TEXT;
  1502.                     return TAG_CODE;
  1503.                 }
  1504.                 if (strncasecmp(s, "cite", len) == 0)
  1505.                 {
  1506.                     TokenClass = EN_TEXT;
  1507.                     return TAG_CITE;
  1508.                 }
  1509.             }
  1510.             else if (len == 7 && (strncasecmp(s, "caption", len) == 0))/* howcome 3/2/95: = -> == after hint from P.M.Hounslow@reading.ac.uk */
  1511.             {
  1512.                 TokenClass = EN_BLOCK;
  1513.                 return TAG_CAPTION;
  1514.             }
  1515.         }
  1516.         else if (c == 'd')
  1517.         {
  1518.             if (len == 3 && strncasecmp(s, "dfn", len) == 0)
  1519.             {
  1520.                 TokenClass = EN_TEXT;
  1521.                 return TAG_DFN;
  1522.             }
  1523.     /* howcome 11/8/95: added upport for DIR */
  1524.             if (len == 3 && strncasecmp(s, "dir", len) == 0)
  1525.             {
  1526.                 TokenClass = EN_LIST;
  1527.                 return TAG_UL;
  1528.             }
  1529.             if (len != 2)
  1530.                 return 0;
  1531.             if (strncasecmp(s, "dl", len) == 0)
  1532.             {
  1533.                 TokenClass = EN_LIST;
  1534.                 return TAG_DL;
  1535.             }
  1536.             if (strncasecmp(s, "dt", len) == 0)
  1537.             {
  1538.                 TokenClass = EL_DEFLIST;
  1539.                 return TAG_DT;
  1540.             }
  1541.             if (strncasecmp(s, "dd", len) == 0)
  1542.             {
  1543.                 TokenClass = EL_DEFLIST;
  1544.                 return TAG_DD;
  1545.             }
  1546.         }
  1547.         else if (c == 'e')
  1548.         {
  1549.             if (len == 2 && strncasecmp(s, "em", len) == 0)
  1550.             {
  1551.                 TokenClass = EN_TEXT;
  1552.                 return TAG_EM;
  1553.             }
  1554.         }
  1555.         else if (c == 'f')
  1556.         {
  1557.             if (len == 3 && strncasecmp(s, "fig", len) == 0)
  1558.             {
  1559.                 TokenClass = EN_BLOCK;
  1560.                 return TAG_FIG;
  1561.             }
  1562.     
  1563.     /* --Spif 10/10/95 Form tag must be checked ! */
  1564.     if (len == 4 && strncasecmp(s, "form", len) == 0)
  1565.     {
  1566.         TokenClass = EN_TEXT /*EN_BLOCK*/;
  1567. return TAG_FORM;
  1568.     };
  1569.         }
  1570.         else if (c == 'h')
  1571.         {
  1572.             if (len == 4 && strncasecmp(s, "head", len) == 0)
  1573.             {
  1574.                 TokenClass = EN_SETUP;
  1575.                 return TAG_HEAD;
  1576.             }
  1577.             if (len != 2)
  1578.                 return 0;
  1579.             TokenClass = EN_HEADER;
  1580.             c = TOLOWER(s[1]);
  1581.             switch (c)
  1582.             {
  1583.                 case '1':
  1584.                     return TAG_H1;
  1585.                 case '2':
  1586.                     return TAG_H2;
  1587.                 case '3':
  1588.                     return TAG_H3;
  1589.                 case '4':
  1590.                     return TAG_H4;
  1591.                 case '5':
  1592.                     return TAG_H5;
  1593.                 case '6':
  1594.                     return TAG_H6;
  1595.                 case 'r':
  1596.                     TokenClass = EN_BLOCK;
  1597.                     return TAG_HR;
  1598.             }
  1599.         }
  1600.         else if (c == 'i')
  1601.         {
  1602.             if (len == 1)
  1603.             {
  1604.                 TokenClass = EN_TEXT;
  1605.                 return TAG_ITALIC;
  1606.             }
  1607.             if (len == 3 && strncasecmp(s, "img", len) == 0)
  1608.             {
  1609.                 TokenClass = EN_TEXT;
  1610.                 return TAG_IMG;
  1611.             }
  1612.             if (len == 5 && strncasecmp(s, "input", len) == 0)
  1613.             {
  1614.                 TokenClass = EN_TEXT;
  1615.                 return TAG_INPUT;
  1616.             }
  1617.             if (len == 7 && strncasecmp(s, "isindex", len) == 0)
  1618.             {
  1619.                 TokenClass = EN_SETUP;
  1620.                 return TAG_ISINDEX;
  1621.             }
  1622.         }
  1623.         else if (c == 'k')
  1624.         {
  1625.             if (len == 3 && strncasecmp(s, "kbd", len) == 0)
  1626.             {
  1627.                 TokenClass = EN_TEXT;
  1628.                 return TAG_KBD;
  1629.             }
  1630.         }
  1631.         else if (c == 'l')
  1632.         {
  1633.             if (len == 2 && strncasecmp(s, "li", len) == 0)
  1634.             {
  1635.                 TokenClass = EN_LIST;
  1636.                 return TAG_LI;
  1637.             }
  1638.             if (len == 4 && strncasecmp(s, "link", len) == 0)
  1639.             {
  1640.                 TokenClass = EN_SETUP;
  1641.                 return TAG_LINK;
  1642.             }
  1643.         }
  1644.         else if (c == 'm')
  1645.         {
  1646.             if (len == 4 && strncasecmp(s, "math", len) == 0)
  1647.             {
  1648.                 TokenClass = EN_TEXT;
  1649.                 return TAG_MATH;
  1650.             }
  1651.             if (len == 6 && strncasecmp(s, "margin", len) == 0)
  1652.             {
  1653.                 TokenClass = EN_TEXT;
  1654.                 return TAG_MARGIN;
  1655.             }
  1656.     /* howcome 11/8/95: added MENU to be compatible with HTML2 */
  1657.             if (len == 4 && strncasecmp(s, "menu", len) == 0)
  1658.             {
  1659.                 TokenClass = EN_LIST;
  1660.                 return TAG_UL;
  1661.             }
  1662.         }
  1663.         else if (c == 'n')
  1664.         {
  1665.             if (len == 4 && strncasecmp(s, "note", len) == 0)
  1666.             {
  1667.                 TokenClass = EN_BLOCK;
  1668.                 return TAG_NOTE;
  1669.             }
  1670.         }
  1671.         else if (c == 'o')
  1672.         {
  1673.             if (len == 2 && strncasecmp(s, "ol", len) == 0)
  1674.             {
  1675.                 TokenClass = EN_LIST;
  1676.                 return TAG_OL;
  1677.             }
  1678.             if (len == 6 && strncasecmp(s, "option", len) == 0)
  1679.             {
  1680.                 TokenClass = EN_TEXT;  /* kludge for error recovery */
  1681.                 return TAG_OPTION;
  1682.             }
  1683.         }
  1684.         else if (c == 'p')
  1685.         {
  1686.             if (len == 1)
  1687.             {
  1688.                 TokenClass = EN_BLOCK;
  1689.                 return TAG_P;
  1690.             }
  1691.             if (len == 3 && strncasecmp(s, "pre", len) == 0)
  1692.             {
  1693.                 TokenClass = EN_BLOCK;
  1694.                 return TAG_PRE;
  1695.             }
  1696.         }
  1697.         else if (c == 'q')
  1698.         {
  1699.             if (len == 1)
  1700.             {
  1701.                 TokenClass = EN_TEXT;
  1702.                 return TAG_Q;
  1703.             }
  1704.             if (len == 5 && strncasecmp(s, "quote", len) == 0)
  1705.             {
  1706.                 TokenClass = EN_BLOCK;
  1707.                 return TAG_QUOTE;
  1708.             }
  1709.         }
  1710.         else if (c == 'r')
  1711.         {
  1712.             if (len == 7 && strncasecmp(s, "removed", len) == 0)
  1713.             {
  1714.                 TokenClass = EN_TEXT;
  1715.                 return TAG_REMOVED;
  1716.             }
  1717.         }
  1718.         else if (c == 's')
  1719.         {
  1720.             if (len == 1)
  1721.             {
  1722.                 TokenClass = EN_TEXT;
  1723.                 return TAG_STRIKE;
  1724.             }
  1725.             if (len == 3 && strncasecmp(s, "sup", len) == 0)
  1726.             {
  1727.                 TokenClass = EN_TEXT;
  1728.                 return TAG_SUP;
  1729.             }
  1730.             if (len == 3 && strncasecmp(s, "sub", len) == 0)
  1731.             {
  1732.                 TokenClass = EN_TEXT;
  1733.                 return TAG_SUB;
  1734.             }
  1735.             if (len == 4 && strncasecmp(s, "samp", len) == 0)
  1736.             {
  1737.                 TokenClass = EN_TEXT;
  1738.                 return TAG_SAMP;
  1739.             }
  1740.             if (len == 5 && strncasecmp(s, "small", len) == 0)
  1741.             {
  1742.                 TokenClass = EN_TEXT;
  1743.                 return TAG_SMALL;
  1744.             }
  1745.             if (len == 6 && strncasecmp(s, "strong", len) == 0)
  1746.             {
  1747.                 TokenClass = EN_TEXT;
  1748.                 return TAG_STRONG;
  1749.             }
  1750.             if (len == 6 && strncasecmp(s, "select", len) == 0)
  1751.             {
  1752.                 TokenClass = EN_TEXT;
  1753.                 return TAG_SELECT;
  1754.             }
  1755.             if (len == 6 && strncasecmp(s, "strike", len) == 0)
  1756.             {
  1757.                 TokenClass = EN_TEXT;
  1758.                 return TAG_STRIKE;
  1759.             }
  1760.     /* howcome 26/2/95 */
  1761.             if (len == 5 && strncasecmp(s, "style", len) == 0)
  1762.             {
  1763.                 TokenClass = EN_SETUP;
  1764.                 return TAG_STYLE;
  1765.             }
  1766.         }
  1767.         else if (c == 't')
  1768.         {
  1769.             if (len == 5 && strncasecmp(s, "title", len) == 0)
  1770.             {
  1771.                 TokenClass = EN_SETUP;
  1772.                 return TAG_TITLE;
  1773.             }
  1774.             if (len == 2 && strncasecmp(s, "tt", len) == 0)
  1775.             {
  1776.                 TokenClass = EN_TEXT;
  1777.                 return TAG_TT;
  1778.             }
  1779.             if (len == 2 && strncasecmp(s, "tr", len) == 0)
  1780.             {
  1781.                 TokenClass = EN_TABLE;
  1782.                 return TAG_TR;
  1783.             }
  1784.             if (len == 2 && strncasecmp(s, "th", len) == 0)
  1785.             {
  1786.                 TokenClass = EN_TABLE;
  1787.                 return TAG_TH;
  1788.             }
  1789.             if (len == 2 && strncasecmp(s, "td", len) == 0)
  1790.             {
  1791.                 TokenClass = EN_TABLE;
  1792.                 return TAG_TD;
  1793.             }
  1794.             if (len == 5 && strncasecmp(s, "table", len) == 0)
  1795.             {
  1796.                 TokenClass = EN_BLOCK;
  1797.                 return TAG_TABLE;
  1798.             }
  1799.             if (len == 8 && strncasecmp(s, "textarea", len) == 0)
  1800.             {
  1801.                 TokenClass = EN_TEXT;
  1802.                 return TAG_TEXTAREA;
  1803.             }
  1804.         }
  1805.         else if (c == 'u')
  1806.         {
  1807.             if (len == 1)
  1808.             {
  1809.                 TokenClass = EN_TEXT;
  1810.                 return TAG_UNDERLINE;
  1811.             }
  1812.             if (len == 2 && strncasecmp(s, "ul", len) == 0)
  1813.             {
  1814.                 TokenClass = EN_LIST;
  1815.                 return TAG_UL;
  1816.             }
  1817.         }
  1818.         else if (c == 'v')
  1819.         {
  1820.             if (len == 3 && strncasecmp(s, "var", len) == 0)
  1821.             {
  1822.                 TokenClass = EN_TEXT;
  1823.                 return TAG_VAR;
  1824.             }
  1825.         }
  1826.         else if (c == 'x')
  1827.         {
  1828.             if (len == 3 && strncasecmp(s, "xmp", len) == 0)
  1829.             {
  1830.                 TokenClass = EN_BLOCK;
  1831.                 return TAG_PRE;
  1832.             }
  1833.         }
  1834.     }
  1835.     TokenClass = EN_UNKNOWN;
  1836.     return UNKNOWN; /* unknown tag */
  1837. }
  1838. void UnGetToken(void)
  1839. {
  1840.     bufptr = LastBufPtr;
  1841. }
  1842. /*
  1843.    The token type is returned in the global token.
  1844.    Characters are returned in TokenValue while TokenClass
  1845.    is used to return a class value e.g. EN_SETUP or EN_BLOCK.
  1846.    Entity definitions are pointed to by EntityValue.
  1847.    The bufptr is moved past the token, except at the end
  1848.    of the buffer - as a safety precaution.
  1849. */
  1850. int GetToken(void)
  1851. {
  1852.     int c, k, n;
  1853.     LastBufPtr = bufptr;
  1854.     c = *(unsigned char *)bufptr;
  1855.     TokenValue = c;
  1856.     if (bufptr <= targetptr)
  1857.         ViewOffset = PixOffset;
  1858.     if (c == '<' && (Token = RecogniseTag()) != PCDATA)
  1859.     {
  1860.         bufptr += TagLen;   /* to first char after tag name */
  1861.         return Token;
  1862.     }
  1863.     TokenClass = EN_TEXT;
  1864.     EndTag = 0;
  1865.     if (c == '&' && (isalpha(bufptr[1]) || bufptr[1] == '#'))
  1866.     {
  1867.         n = entity(bufptr + 1, &k);
  1868.         if (n)
  1869.         {
  1870.             bufptr += k;
  1871.             TokenValue = n;
  1872.             Token = PCDATA;
  1873.             return Token;
  1874.         }
  1875.     }
  1876.     if (c <= ' ')
  1877.     {
  1878.         if (c == '')
  1879.         {
  1880.             Token = ENDDATA;
  1881.             TokenClass = EN_UNKNOWN;
  1882.             return Token;
  1883.         }
  1884.         
  1885.         ++bufptr;
  1886.         Token = WHITESPACE;
  1887.         return Token;
  1888.     }
  1889.     ++bufptr;
  1890.     Token = PCDATA;
  1891.     return Token;
  1892. }
  1893. /* void ParseAnchorAttrs(char **href, int *hreflen, char **name, int *namelen, char **class_p, int *class_len_p);*/
  1894. /* get token, skipping white space and unknown tokens */
  1895. int SkipSpace(void)
  1896. {
  1897.     for (;;)
  1898.     {
  1899.         while (GetToken() == WHITESPACE);
  1900.         if (Token == UNKNOWN)
  1901.         {
  1902.             SwallowAttributes();
  1903.             continue;
  1904.         }
  1905.         break;
  1906.     }
  1907.     return Token;
  1908. }
  1909. /* assumes bufptr points to start of attribute */
  1910. char *ParseAttribute(int *len)
  1911. {
  1912.     int c;
  1913.     char *attr;
  1914.     *len = 0;
  1915.     attr = bufptr;
  1916.     IdAttributeFlag = 0;
  1917.     for (;;)
  1918.     {
  1919.         c = *bufptr;
  1920.         if (c == '>' || c == '')
  1921.             return attr;
  1922.         if (c == '=' || IsWhite(c))
  1923.             break;
  1924.         ++(*len);
  1925.         ++bufptr;
  1926.     }
  1927.     if (*len == 2 && strncasecmp(attr, "id", 2) ==0)
  1928.         IdAttributeFlag = 1;
  1929.     return attr;
  1930. }
  1931. /* values start with "=" or " = " etc. */
  1932. char *ParseValue(int *len)
  1933. {
  1934.     int c, delim;
  1935.     char *value;
  1936.     *len = 0;
  1937.     while (c = *bufptr, IsWhite(c))
  1938.         ++bufptr;
  1939.     if (c != '=')
  1940.         return 0;
  1941.     ++bufptr;   /* past the = sign */
  1942.     while (c = *bufptr, IsWhite(c))
  1943.         ++bufptr;
  1944.     if (c == '"' || c == ''')
  1945.     {
  1946.         delim = c;
  1947.         ++bufptr;
  1948.     }
  1949.     else
  1950.         delim = 0;
  1951.     value = bufptr;
  1952.     for (;;)
  1953.     {
  1954.         c = *bufptr;
  1955.         if (c == '')
  1956.     if(delim)
  1957. return 0;  /* a big and dirty hack --Spif 27-Oct-95 */
  1958.     else
  1959. break;
  1960.         if (delim)
  1961.         {
  1962.             if (c == delim)
  1963.             {
  1964.                 ++bufptr;
  1965.                 break;
  1966.             }
  1967.         }
  1968.         else if (c == '>' || IsWhite(c))
  1969.             break;
  1970.         ++(*len);
  1971.         ++bufptr;
  1972.     }
  1973.     if (IdAttributeFlag && value && targetId)
  1974.     {
  1975.         if (strlen(targetId) == *len &&
  1976.             strncasecmp(value, targetId, *len) == 0)
  1977.         {
  1978.             IdOffset = PixOffset;
  1979.         }
  1980.     }
  1981.     IdAttributeFlag = 0;
  1982.     return value;
  1983. }
  1984. /*
  1985.    HREF attribute defines original document URL and is added by
  1986.    the browser when making a local copy of a document so that
  1987.    relative references can be deferenced to their original links
  1988. */
  1989. void ParseBase(Frame *frame)
  1990. {
  1991.     char *href, *name;
  1992.     int hreflen, namelen;
  1993.     ParseAnchorAttrs(&href, &hreflen, &name, &namelen, &class, &class_len);
  1994.     if(href)
  1995. CurrentDoc->base = strndup(href, hreflen);
  1996. }
  1997. void ParseLink(Frame *frame)
  1998. {
  1999.     char *href=NULL, *rel=NULL;
  2000.     int hreflen = 0, rellen = 0;
  2001.     int c, n, m;
  2002.     char *attr, *value;
  2003.     for (;;)
  2004.     {
  2005.         c = *bufptr++;
  2006.         if (c == '')
  2007.             break;
  2008.         if (c == '>')
  2009.             break;
  2010.         if (IsWhite(c))
  2011.             continue;
  2012.         --bufptr;
  2013.         attr = ParseAttribute(&n);
  2014.         value = ParseValue(&m);
  2015.         if (n == 4 && strncasecmp(attr, "href", n) == 0)
  2016.         {
  2017.             href = value;
  2018.             hreflen = m;
  2019.             continue;
  2020.         }
  2021.         if (n == 3 && strncasecmp(attr, "rel", n) == 0)
  2022.         {
  2023.             rel = value;
  2024.             rellen = m;
  2025.             continue;
  2026.         }
  2027.     }
  2028.     if (href && rel) {
  2029. if (!NoStyle && !CurrentDoc->link_style && (strncasecmp(rel, "style", 5) == 0))
  2030.     CurrentDoc->link_style = (char *)StyleLoad(href, hreflen, CurrentDoc->pending_reload); 
  2031. /* (char *) because StyleLoad not declared -> int implied , must add include files */
  2032.     }
  2033. }
  2034. void ParseTitle(int implied, Frame *frame)
  2035. {
  2036.     if (EndTag)
  2037.     {
  2038.         SwallowAttributes();
  2039.         return;
  2040.     }
  2041.     if (!implied)
  2042.         SwallowAttributes();
  2043.     /* skip leading white space - subsequently contigous
  2044.        white space is compressed to a single space */
  2045.     while (GetToken() == WHITESPACE);
  2046.     UnGetToken();
  2047.     LineLen = 0;
  2048.     for (;;)
  2049.     {
  2050.         GetToken();
  2051.         if (Token == TAG_TITLE && EndTag)
  2052.         {
  2053.             SwallowAttributes();
  2054.             break;
  2055.         }
  2056.         if (Token == UNKNOWN)
  2057.         {
  2058.             SwallowAttributes();
  2059.             continue;
  2060.         }
  2061.         if (Token == WHITESPACE)
  2062.         {
  2063.             while (GetToken() == WHITESPACE);
  2064.             UnGetToken();
  2065.             if (LineLen < LBUFSIZE - 1)
  2066.                 LineBuf[LineLen++] = ' ';
  2067.             continue;
  2068.         }
  2069.         if (Token != PCDATA)
  2070.         {
  2071.             UnGetToken();
  2072.             break;
  2073.         }
  2074.         if (LineLen < LBUFSIZE - 1)
  2075.             LineBuf[LineLen++] = TokenValue;
  2076.     }    
  2077.     LineBuf[LineLen] = '';
  2078.     SetBanner(LineBuf);
  2079. }
  2080. /* howcome 26/2/95 */
  2081. void ParseStyle(Frame *frame)
  2082. {
  2083.     if (EndTag)
  2084.     {
  2085.         SwallowAttributes();
  2086.         return;
  2087.     }
  2088.     SwallowAttributes();
  2089.     /* skip leading white space - subsequently contigous
  2090.        white space is compressed to a single space */
  2091.     while (GetToken() == WHITESPACE);
  2092.     UnGetToken();
  2093.     LineLen = 0;
  2094.     for (;;)
  2095.     {
  2096.         GetToken();
  2097.         if (Token == TAG_STYLE && EndTag)
  2098.         {
  2099.             SwallowAttributes();
  2100.             break;
  2101.         }
  2102.         if (Token == UNKNOWN)
  2103.         {
  2104.             SwallowAttributes();
  2105.             continue;
  2106.         }
  2107.         if (LineLen < LBUFSIZE - 1)
  2108.             LineBuf[LineLen++] = TokenValue;
  2109.     }    
  2110.     LineBuf[LineLen] = '';
  2111.     if (!NoStyle && !CurrentDoc->head_style)
  2112. CurrentDoc->head_style = strdup (LineBuf);
  2113. }
  2114. void ParseSetUp(int implied, Frame *frame)
  2115. {
  2116.     if (EndTag)
  2117.     {
  2118.         SwallowAttributes();
  2119.         return;
  2120.     }
  2121.     if (!implied)
  2122.         SwallowAttributes();
  2123.     for (;;)
  2124.     {
  2125.         while (GetToken() == WHITESPACE);
  2126. /*        UnGetToken(); */ /* howcome 10/7/95 part of comment handling */
  2127.         if (Token == TAG_HEAD && EndTag)
  2128.         {
  2129.             SwallowAttributes();
  2130.             break;
  2131.         }
  2132.         if (Token == TAG_TITLE)
  2133.         {
  2134.             UnGetToken();
  2135.     ParseTitle(0, frame);
  2136.             continue;
  2137.         }
  2138.         if (Token == TAG_ISINDEX)
  2139.         {
  2140.             SwallowAttributes();
  2141.             IsIndex = 1;
  2142.             ClearStatus();
  2143.             continue;
  2144.         }
  2145.         if (Token == TAG_BASE)
  2146.         {
  2147.     UnGetToken();
  2148.     ParseBase(frame);
  2149.             continue;
  2150.         }
  2151. /* howcome 26/2/95 */
  2152. if (Token == TAG_STYLE)
  2153. {
  2154.     UnGetToken();
  2155.     ParseStyle(frame);
  2156.     continue;
  2157. }
  2158. /* howcome 25/4/95 */
  2159. if (Token == TAG_LINK)
  2160. {
  2161.     UnGetToken();
  2162.     ParseLink(frame);
  2163.     continue;
  2164. }
  2165.         if (Token == UNKNOWN)
  2166.         {
  2167.             SwallowAttributes();
  2168.             continue;
  2169.         }
  2170.         if (Token == PCDATA || Token == ENTITY)
  2171.         {
  2172.             UnGetToken();
  2173.             break;
  2174.         }
  2175.         if (Token == ENDDATA || TokenClass != EN_SETUP)
  2176.         {
  2177.             UnGetToken();
  2178.             break;
  2179.         }
  2180.     }
  2181. }
  2182. void ParseAnchorAttrs(char **href, int *hreflen, char **name, int *namelen, char **class_p, int *class_len_p)
  2183. {
  2184.     int c, n, m;
  2185.     char *attr, *value;
  2186.     *href = 0;
  2187.     *name = 0;
  2188.     for (;;)
  2189.     {
  2190.         c = *bufptr++;
  2191.         if (c == '')
  2192.             break;
  2193.         if (c == '>')
  2194.             break;
  2195.         if (IsWhite(c))
  2196.             continue;
  2197.         --bufptr;
  2198.         attr = ParseAttribute(&n);
  2199.         value = ParseValue(&m);
  2200.         if (n == 4 && strncasecmp(attr, "href", n) == 0)
  2201.         {
  2202.             *href = value;
  2203.             *hreflen = m;
  2204.             continue;
  2205.         }
  2206.         if (n == 4 && strncasecmp(attr, "name", n) == 0)
  2207.         {
  2208.             *name = value;
  2209.             *namelen = m;
  2210.             continue;
  2211.         }
  2212.         if (n == 5 && strncasecmp(attr, "class", n) == 0)
  2213.         {
  2214.     if (STYLE_TRACE) {
  2215. char *s = strndup(attr, n);
  2216. fprintf(stderr,"style_class %sn",s);
  2217. Free(s);
  2218.     }
  2219.     *class_p = value;
  2220.     *class_len_p = m;
  2221.         }
  2222.     }
  2223.     if (*href == NULL)
  2224. if (TAG_TRACE)
  2225.     fprintf(stderr,"ParseAnchorAttrs: *href == NULL, hreflen = %dn", *hreflen);
  2226. }
  2227. /* howcome30/5/95: addded support for widht and height */
  2228. void ParseImageAttrs(char **href, int *hreflen, int *align, int *ismap, int *width, int *height)
  2229. {
  2230.     int c, n, m;
  2231.     char *attr, *value;
  2232.     *href = NULL;               /* howcome: NULL !! */
  2233.     *align = ALIGN_BOTTOM;
  2234.     *ismap = 0;
  2235.     *width = 0; *height = 0;
  2236.     for (;;)
  2237.     {
  2238.         c = *bufptr++;
  2239.         if (c == '')
  2240.             break;
  2241.         if (c == '>')
  2242.             break;
  2243.         if (IsWhite(c))
  2244.             continue;
  2245.         --bufptr;
  2246.         attr = ParseAttribute(&n);
  2247.         value = ParseValue(&m);
  2248.         if (n == 3 && strncasecmp(attr, "src", n) == 0)
  2249.         {
  2250.             *href = value;
  2251.             *hreflen = m;
  2252.             continue;
  2253.         }
  2254.         if (n == 5 && strncasecmp(attr, "width", n) == 0)
  2255.         {
  2256.     *width = atoi(value);
  2257.             continue;
  2258.         }
  2259.         if (n == 6 && strncasecmp(attr, "height", n) == 0)
  2260.         {
  2261.             *height = atoi(value);
  2262.             continue;
  2263.         }
  2264.         if (n == 5 && strncasecmp(attr, "align", n) == 0)
  2265.         {
  2266.             if (m == 3 && strncasecmp(value, "top", m) == 0)
  2267.                 *align = ALIGN_TOP;
  2268.             else if (m == 6 && strncasecmp(value, "middle", m) == 0)
  2269.                 *align = ALIGN_MIDDLE;
  2270.             else if (m == 6 && strncasecmp(value, "bottom", m) == 0)
  2271.                 *align = ALIGN_BOTTOM;
  2272.             continue;
  2273.         }
  2274.         if (n == 5 && strncasecmp(attr, "ismap", n) == 0)
  2275.             *ismap = 1;
  2276.     }
  2277. }
  2278. void ParseFigureAttrs(char **href, int *hreflen, int *align, int *width, int *height)
  2279. {
  2280.     int c, n, m;
  2281.     char *attr, *value;
  2282.     *href = 0;
  2283.     *align = ALIGN_CENTER;
  2284.     *width = 0; *height = 0;
  2285.     for (;;)
  2286.     {
  2287.         c = *bufptr++;
  2288.         if (c == '')
  2289.             break;
  2290.         if (c == '>')
  2291.             break;
  2292.         if (IsWhite(c))
  2293.             continue;
  2294.         --bufptr;
  2295.         attr = ParseAttribute(&n);
  2296.         value = ParseValue(&m);
  2297.         if (n == 3 && strncasecmp(attr, "src", n) == 0)
  2298.         {
  2299.             *href = value;
  2300.             *hreflen = m;
  2301.             continue;
  2302.         }
  2303.         if (n == 5 && strncasecmp(attr, "width", n) == 0)
  2304.         {
  2305.     *width = atoi(value);
  2306.             continue;
  2307.         }
  2308.         if (n == 6 && strncasecmp(attr, "height", n) == 0)
  2309.         {
  2310.             *height = atoi(value);
  2311.             continue;
  2312.         }
  2313.         if (n == 5 && strncasecmp(attr, "align", n) == 0)
  2314.         {
  2315.             if (m == 4 && strncasecmp(value, "left", m) == 0)
  2316.                 *align = ALIGN_LEFT;
  2317.             else if (m == 6 && strncasecmp(value, "center", m) == 0)
  2318.                 *align = ALIGN_CENTER;
  2319.             else if (m == 5 && strncasecmp(value, "right", m) == 0)
  2320.                 *align = ALIGN_RIGHT;
  2321.             else if (m == 9 && strncasecmp(value, "bleedleft", m) == 0)
  2322.                 *align = ALIGN_BLEEDLEFT;
  2323.             else if (m == 10 && strncasecmp(value, "bleedright", m) == 0)
  2324.                 *align = ALIGN_BLEEDRIGHT;
  2325.             continue;
  2326.         }
  2327.     }
  2328. }
  2329. void /* wm 19.Jan.95 */
  2330. ParseTextAreaAttrs(int *type, char **name, int *nlen,
  2331.                 char **value, int *vlen, int *rows, int *cols, int *flags)
  2332. {
  2333.     int c, n, m; /* janet: not used: checked */
  2334.     char *attr, *attrval;
  2335.     *type = TEXTFIELD;
  2336.     *rows = 4;
  2337.     *cols = 20;
  2338.     *flags = 0;
  2339.     *name = *value = "";
  2340.     *nlen = *vlen = 0;
  2341.     for (;;)
  2342.     {
  2343.         c = *bufptr++;
  2344.         if (c == '')
  2345.             break;
  2346.         if (c == '>')
  2347.             break;
  2348.         if (IsWhite(c))
  2349.             continue;
  2350.         --bufptr;
  2351.         attr = ParseAttribute(&n);
  2352.         attrval = ParseValue(&m);
  2353.         if (n == 4 && strncasecmp(attr, "type", n) == 0)
  2354.         {
  2355.             if (m == 4 && strncasecmp(attrval, "text", m) == 0)
  2356.                 *type = TEXTFIELD;
  2357.             else if (m == 8 && strncasecmp(attrval, "checkbox", m) == 0)
  2358.                 *type = CHECKBOX;
  2359.             else if (m == 5 && strncasecmp(attrval, "radio", m) == 0)
  2360.                 *type = RADIOBUTTON;
  2361.             continue;
  2362.         }
  2363.         if (n == 4 && strncasecmp(attr, "name", n) == 0)
  2364.         {
  2365.             *name = attrval;
  2366.             *nlen = m;
  2367.             continue;
  2368.         }
  2369.         if (n == 5 && strncasecmp(attr, "value", n) == 0)
  2370.         {
  2371.             *value = attrval;
  2372.             *vlen = m;
  2373.             continue;
  2374.         }
  2375.         if (n == 4 && strncasecmp(attr, "rows", n) == 0)
  2376.         {
  2377.             sscanf(attrval, "%d", rows);
  2378.             continue;
  2379.         }
  2380.         if (n == 4 && strncasecmp(attr, "cols", n) == 0)
  2381.         {
  2382.             sscanf(attrval, "%d", cols);
  2383.             continue;
  2384.         }
  2385.         if (n == 5 && strncasecmp(attr, "error", n) == 0)
  2386.         {
  2387.             *flags |= IN_ERROR;
  2388.             continue;
  2389.         }
  2390.         if (n == 8 && strncasecmp(attr, "disabled", n) == 0)
  2391.         {
  2392.             *flags |= DISABLED;
  2393.             continue;
  2394.         }
  2395.         if (n == 7 && strncasecmp(attr, "checked", n) == 0)
  2396.             *flags |= CHECKED;
  2397.     }
  2398. }
  2399. void /* --Spif 11-Oct-95 */
  2400. ParseFormAttrs(int *method, char **action, int *alen)
  2401. {
  2402.     int c, n, m;
  2403.     char *attr, *attrval;
  2404.     
  2405.     *action = NULL;
  2406.     *method = GET; /* implied must add encoded-type.. */
  2407.     for (;;)
  2408.     {
  2409.         c= *bufptr++;
  2410.         if (c == '')
  2411.             break;
  2412.         if (c == '>')
  2413.             break;
  2414.         if (IsWhite(c))
  2415.             continue;
  2416. --bufptr;
  2417.         attr = ParseAttribute(&n);
  2418.         attrval = ParseValue(&m);
  2419. if (n == 6 && strncasecmp(attr, "method", n) == 0)
  2420.         {
  2421.     if ( m == 3 && strncasecmp(attrval, "get", m) ==0)
  2422.         *method = GET;
  2423.     else if ( m == 4 && strncasecmp(attrval, "post", m) ==0)
  2424.         *method = POST;
  2425. }
  2426. if ( n == 6 && strncasecmp(attr, "action", n) == 0)
  2427. {
  2428.   *action = attrval;
  2429.   *alen = m;
  2430.   continue;
  2431. };
  2432.     };
  2433. }
  2434. void /* wm 19.Jan.95 */
  2435. ParseInputAttrs(int *type, char **name, int *nlen,
  2436.                 char **value, int *vlen, int *size, int *flags, Image **image)
  2437. {
  2438.     int c, n, m; /* janet: not used: checked */
  2439.     char *attr, *attrval, *href = NULL;
  2440.     int hreflen = 0; /* --SPif */
  2441.     *type = TEXTFIELD;
  2442.     *size = 20;
  2443.     *flags = 0;
  2444.     *name = *value = "";
  2445.     *nlen = *vlen = 0;
  2446.     hreflen = 0;
  2447.     *image=NULL;
  2448.     for (;;)
  2449.     {
  2450.         c = *bufptr++;
  2451.         if (c == '')
  2452.             break;
  2453.         if (c == '>')
  2454.             break;
  2455.         if (IsWhite(c))
  2456.             continue;
  2457.         --bufptr;
  2458.         attr = ParseAttribute(&n);
  2459.         attrval = ParseValue(&m);
  2460.         if (n == 4 && strncasecmp(attr, "type", n) == 0)
  2461.         {
  2462.             if (m == 4 && strncasecmp(attrval, "text", m) == 0)
  2463.                 *type = TEXTFIELD;
  2464.             else if (m == 8 && strncasecmp(attrval, "checkbox", m) == 0)
  2465.                 *type = CHECKBOX;
  2466.             else if (m == 5 && strncasecmp(attrval, "radio", m) == 0)
  2467.                 *type = RADIOBUTTON;
  2468.             else if (m == 6 && strncasecmp(attrval, "submit", m) == 0)
  2469.                 *type = SUBMITBUTTON;
  2470.             else if (m == 5 && strncasecmp(attrval, "reset", m) == 0)
  2471.                 *type = RESETBUTTON;
  2472.     else if (m == 5 && strncasecmp(attrval, "image", m) ==0)
  2473.         *type = SUBMITBUTTON; /* --Spif image in html2 = Submit */
  2474.     else if (m == 6 && strncasecmp(attrval, "hidden", m) ==0)
  2475.         *type = HIDDEN;
  2476.     else if (m == 6 && strncasecmp(attrval, "passwd", m) ==0)
  2477.         *type = PASSWD;
  2478.             continue;
  2479.         }
  2480.         if (n == 4 && strncasecmp(attr, "name", n) == 0)
  2481.         {
  2482.             *name = attrval;
  2483.             *nlen = m;
  2484.             continue;
  2485.         }
  2486.         if (n == 5 && strncasecmp(attr, "value", n) == 0)
  2487.         {
  2488.             *value = attrval;
  2489.             *vlen = m;
  2490.             continue;
  2491.         }
  2492.         if (n == 4 && strncasecmp(attr, "size", n) == 0)
  2493.         {
  2494.             sscanf(attrval, "%d", size);
  2495.             continue;
  2496.         }
  2497.         if (n == 5 && strncasecmp(attr, "error", n) == 0)
  2498.         {
  2499.             *flags |= IN_ERROR;
  2500.             continue;
  2501.         }
  2502.         if (n == 8 && strncasecmp(attr, "disabled", n) == 0)
  2503.         {
  2504.             *flags |= DISABLED;
  2505.             continue;
  2506.         }
  2507.         if (n == 7 && strncasecmp(attr, "checked", n) == 0)
  2508.             *flags |= CHECKED;
  2509.         if (n == 8 && strncasecmp(attr, "multiple", n) == 0)
  2510.             *flags |= MULTIPLE;
  2511. /* --Spif 9-Oct-1995 */ 
  2512. if (n == 3 && strncasecmp(attr, "src", n) == 0)
  2513.         {
  2514.     href = attrval;
  2515.     hreflen = m;
  2516. };
  2517.     }
  2518.     /* --Spif 9-Oct-1995 */
  2519.     if (hreflen > 0)
  2520.         *image = GetImage(href, hreflen, CurrentDoc->pending_reload);
  2521. }
  2522. void /* wm 19.Jan.95 */
  2523. ParseCellAttrs(int *rowspan, int *colspan, int *align, int *nowrap)
  2524. {
  2525.     int c, n, m;
  2526.     char *attr, *attrval;
  2527.     *rowspan = *colspan = 1;
  2528.     *align = ALIGN_CENTER;
  2529.     *nowrap = 0;
  2530.     for (;;)
  2531.     {
  2532.         c = *bufptr++;
  2533.         if (c == '')
  2534.             break;
  2535.         if (c == '>')
  2536.             break;
  2537.         if (IsWhite(c))
  2538.             continue;
  2539.         --bufptr;
  2540.         attr = ParseAttribute(&n);
  2541.         attrval = ParseValue(&m);
  2542.         if (n == 7 && strncasecmp(attr, "rowspan", n) == 0)
  2543.         {
  2544.             sscanf(attrval, "%d", rowspan);
  2545.             continue;
  2546.         }
  2547.         if (n == 7 && strncasecmp(attr, "colspan", n) == 0)
  2548.         {
  2549.             sscanf(attrval, "%d", colspan);
  2550.             continue;
  2551.         }
  2552.         if (n == 5 && strncasecmp(attr, "align", n) == 0)
  2553.         {
  2554.             if (m == 6 && strncasecmp(attrval, "center", m) == 0)
  2555.                 *align = ALIGN_CENTER;
  2556.             else if (m == 5 && strncasecmp(attrval, "right", m) == 0)
  2557.                 *align = ALIGN_RIGHT;
  2558.             else if (m == 4 && strncasecmp(attrval, "left", m) == 0)
  2559.                 *align = ALIGN_LEFT;
  2560.             continue;
  2561.         }
  2562.         if (n == 6 && strncasecmp(attr, "nowrap", n) == 0)
  2563.             *nowrap = 1;
  2564.     }
  2565. }
  2566. void /* wm 19.Jan.95 */
  2567. ParseTableAttrs(int *border)
  2568. {
  2569.     int c, n, m;
  2570.     char *attr, *attrval;
  2571.     *border = 0;
  2572.     for (;;)
  2573.     {
  2574.         c = *bufptr++;
  2575.         if (c == '')
  2576.             break;
  2577.         if (c == '>')
  2578.             break;
  2579.         if (IsWhite(c))
  2580.             continue;
  2581.         --bufptr;
  2582.         attr = ParseAttribute(&n);
  2583.         attrval = ParseValue(&m);
  2584.         if (n == 6 && strncasecmp(attr, "border", n) == 0)
  2585.         {
  2586.     int bd=1;   /* DJB 17-Jan-96 */
  2587.     
  2588.     if (attrval)
  2589. sscanf(attrval, "%d", &bd);
  2590.     
  2591.     *border = bd ? 1: 0; /* Restrict to 1 and 0 ? */
  2592.             continue;
  2593.         }
  2594.     }
  2595. }
  2596. void 
  2597. ParseClassAttrs(char **class_p, int *class_len_p)
  2598. {
  2599.     int c, n, m;
  2600.     char *attr, *attrval;
  2601.     *class_p = NULL;
  2602.     *class_len_p = 0;
  2603.     for (;;)
  2604.     {
  2605.         c = *bufptr++;
  2606.         if (c == '')
  2607.             break;
  2608.         if (c == '>')
  2609.             break;
  2610.         if (IsWhite(c))
  2611.             continue;
  2612.         --bufptr;
  2613.         attr = ParseAttribute(&n);
  2614.         attrval = ParseValue(&m);
  2615.         if (n == 5 && strncasecmp(attr, "class", n) == 0)
  2616.         {
  2617.     if (STYLE_TRACE) {
  2618. char *s = strndup(attrval, m);
  2619. fprintf(stderr,"style_class %sn",s);
  2620. Free(s);
  2621.     }
  2622.     *class_p = attrval;
  2623.     *class_len_p = m;
  2624.         }
  2625.     }
  2626. }
  2627. void /* wm 19.Jan.95 */
  2628. ParseParaAttrs(int *align, char **class_p, int *class_len_p)
  2629. {
  2630.     int c, n, m;
  2631.     char *attr, *attrval;
  2632.     *class_p = NULL;
  2633.     *class_len_p = 0;
  2634.     for (;;)
  2635.     {
  2636.         c = *bufptr++;
  2637.         if (c == '')
  2638.             break;
  2639.         if (c == '>')
  2640.             break;
  2641.         if (IsWhite(c))
  2642.             continue;
  2643.         --bufptr;
  2644.         attr = ParseAttribute(&n);
  2645.         attrval = ParseValue(&m);
  2646.         if (n == 5 && strncasecmp(attr, "align", n) == 0)
  2647.         {
  2648.             if (m == 6 && strncasecmp(attrval, "center", m) == 0)
  2649.                 *align = ALIGN_CENTER;
  2650.             else if (m == 5 && strncasecmp(attrval, "right", m) == 0)
  2651.                 *align = ALIGN_RIGHT;
  2652.             else if (m == 4 && strncasecmp(attrval, "left", m) == 0)
  2653.                 *align = ALIGN_LEFT;
  2654.     else if (m == 7 && strncasecmp(attrval, "justify", m) == 0)
  2655. *align = ALIGN_JUSTIFY;
  2656.         }
  2657.         if (n == 5 && strncasecmp(attr, "class", n) == 0)
  2658.         {
  2659.     if (STYLE_TRACE) {
  2660. char *s = strndup(attrval, m);
  2661. fprintf(stderr,"style_class %sn",s);
  2662. Free(s);
  2663.     }
  2664.     *class_p = attrval;
  2665.     *class_len_p = m;
  2666.         }
  2667.     }
  2668. }
  2669. #ifdef HTML3_HAS_EXPIRED
  2670. ParseBodyAttrs(char **bg_img, int *bg_len)
  2671. {
  2672.     int c, n, m;
  2673.     char *attr, *attrval;
  2674.     *bg_img = NULL;
  2675.     *bg_len = 0;
  2676.     for (;;)
  2677.     {
  2678.         c = *bufptr++;
  2679.         if (c == '')
  2680.             break;
  2681.         if (c == '>')
  2682.             break;
  2683.         if (IsWhite(c))
  2684.             continue;
  2685.         --bufptr;
  2686.         attr = ParseAttribute(&n);
  2687.         attrval = ParseValue(&m);
  2688.         if (n == 10 && strncasecmp(attr, "background", n) == 0)
  2689.         {          
  2690.     *bg_img = attrval;
  2691.     *bg_len = m;
  2692. }
  2693.     }
  2694. }
  2695. #endif
  2696. Image *ParseNoteAttrs(void)
  2697. {
  2698.     int c, n, m, hreflen;
  2699.     char *attr, *attrval, *href = NULL;
  2700.     Image *image;
  2701.     image = NULL;
  2702.     hreflen = 0;
  2703.     for (;;)
  2704.     {
  2705.         c = *bufptr++;
  2706.         if (c == '')
  2707.             break;
  2708.         if (c == '>')
  2709.             break;
  2710.         if (IsWhite(c))
  2711.             continue;
  2712.         --bufptr;
  2713.         attr = ParseAttribute(&n);
  2714.         attrval = ParseValue(&m);
  2715.         if ((n == 4 && strncasecmp(attr, "role", n) == 0) || (n == 5 && strncasecmp(attr, "class", n) == 0))
  2716.         {
  2717.             if (m == 4 && strncasecmp(attrval, "note", m) == 0)
  2718.                 image = note_image;
  2719.             else if (m == 3 && strncasecmp(attrval, "tip", m) == 0)
  2720.                 image = note_image;
  2721.             else if (m == 7 && strncasecmp(attrval, "caution", m) == 0)
  2722.                 image = caution_image;
  2723.             else if (m == 7 && strncasecmp(attrval, "warning", m) == 0)
  2724.                 image = warning_image;
  2725.         }
  2726.         if (n == 3 && strncasecmp(attr, "src", n) == 0)
  2727.         {
  2728.             href = attrval;
  2729.             hreflen = m;
  2730.         }
  2731.     }
  2732.     if (hreflen > 0)
  2733.         image = GetImage(href, hreflen, CurrentDoc->pending_reload);
  2734.     return image;
  2735. }
  2736. void ParseOption(int implied, Frame *frame, Field *field, int font)
  2737. {
  2738.   /* janet: not used:     int width; */
  2739.     if (EndTag)
  2740.     {
  2741.         SwallowAttributes();
  2742.         return;
  2743.     }
  2744.     if (!implied)
  2745.         SwallowAttributes();
  2746.     LineLen = 0;
  2747.     for (;;)
  2748.     {
  2749.         GetToken();
  2750.         if (Token == TAG_OPTION && EndTag)
  2751.         {
  2752.             SwallowAttributes();
  2753.             break;
  2754.         }
  2755.         if (Token == UNKNOWN)
  2756.         {
  2757.             SwallowAttributes();
  2758.             continue;
  2759.         }
  2760.         /* condense whitespace */
  2761.         if (Token == WHITESPACE)
  2762.         {
  2763.             while (GetToken() == WHITESPACE);
  2764.             UnGetToken();
  2765.             if (LineLen < LBUFSIZE - 1)
  2766.                 LineBuf[LineLen++] = ' ';
  2767.             continue;
  2768.         }
  2769.         if (Token == PCDATA)
  2770.         {
  2771.             if (LineLen < LBUFSIZE - 1)
  2772.                 LineBuf[LineLen++] = TokenValue;
  2773.             continue;
  2774.         }
  2775.      /* unexpected tag so terminate element */
  2776.         UnGetToken();
  2777.         break;
  2778.     }
  2779.     LineBuf[LineLen] = '';
  2780.     if (LineLen > 0)
  2781.         AddOption(field, font, LineBuf, LineLen);
  2782. }