/*
** Structures and typedefs used by the HTML widget
** $Revision: 1.3 $
**
** Copyright (C) 1997-2000 D. Richard Hipp
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Library General Public License for more details.
** 
** You should have received a copy of the GNU Library General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA  02111-1307, USA.
**
** Author contact information:
**   drh@acm.org
**   http://www.hwaci.com/drh/
*/

/*
** Debug must be turned on for testing to work.
*/
#define DEBUG 1

/*
** Sanity checking macros.
*/
#ifdef DEBUG
#define HtmlAssert(X) \
  if(!(X)){ \
    fprintf(stderr,"Assertion failed on line %d of %s\n",__LINE__,__FILE__); \
  }
#define HtmlCantHappen \
  fprintf(stderr,"Can't happen on line %d of %s\n",__LINE__,__FILE__);
#else
#define HtmlAssert(X)
#define HtmlCantHappen
#endif

/*
** The TRACE macro is used to print internal information about the
** HTML layout engine during testing and debugging.  The amount of
** information printed is governed by a global variable named
** HtmlTraceMask.  If bits in the first argument to the TRACE macro
** match any bits in HtmlTraceMask variable, then the trace message
** is printed.
**
** All of this is completely disabled, of course, if the DEBUG macro
** is not defined.
*/
#ifdef DEBUG
# define TRACE_INDENT  printf("%*s",HtmlDepth-3,"")
# define TRACE(Flag, Args) \
    if( (Flag)&HtmlTraceMask ){ \
       TRACE_INDENT; printf Args; fflush(stdout); \
    }
# define TRACE_PUSH(Flag)  if( (Flag)&HtmlTraceMask ){ HtmlDepth+=3; }
# define TRACE_POP(Flag)   if( (Flag)&HtmlTraceMask ){ HtmlDepth-=3; }
#else
# define TRACE_INDENT
# define TRACE(Flag, Args)
# define TRACE_PUSH(Flag)
# define TRACE_POP(Flag)
#endif

/*
** Bitmasks for the HtmlTraceMask global variable
*/
#define HtmlTrace_Table1       0x00000001
#define HtmlTrace_Table2       0x00000002
#define HtmlTrace_Table3       0x00000004
#define HtmlTrace_Table4       0x00000008
#define HtmlTrace_Table5       0x00000010
#define HtmlTrace_Table6       0x00000020
#define HtmlTrace_GetLine      0x00000100
#define HtmlTrace_GetLine2     0x00000200
#define HtmlTrace_FixLine      0x00000400
#define HtmlTrace_BreakMarkup  0x00001000
#define HtmlTrace_Style        0x00002000
#define HtmlTrace_Input1       0x00004000


/*
** Macros to allocate and free memory.
*/
#define HtmlAlloc(A)      ((void*)Tcl_Alloc(A))
#define HtmlFree(A)       Tcl_Free((char*)(A))
#define HtmlRealloc(A,B)  ((void*)Tcl_Realloc((A),(B)))

/*
** Various data types.  This code is designed to run on a modern
** cached architecture where the CPU runs a lot faster than the
** memory bus.  Hence we try to pack as much data into as small a space
** as possible so that it is more likely to fit in cache.  The
** extra CPU instruction or two needed to unpack the data is not
** normally an issue since we expect the speed of the memory bus 
** to be the limiting factor.
*/
typedef unsigned char  Html_u8;      /* 8-bit unsigned integer */
typedef short          Html_16;      /* 16-bit signed integer */
typedef unsigned short Html_u16;     /* 16-bit unsigned integer */
typedef int            Html_32;      /* 32-bit signed integer */

/*
** An instance of the following structure is used to record style
** information on each Html element.
*/
struct HtmlStyle {
  unsigned int font    : 6;      /* Font to use for display */
  unsigned int color   : 4;      /* Foreground color */
  signed int subscript : 4;      /* Positive for <sup>, negative for <sub> */
  unsigned int align   : 2;      /* Horizontal alignment */
  unsigned int bgcolor : 4;      /* Background color */
  unsigned int flags   : 12;     /* the STY_ flags below */
}

/*
** We allow 8 different font families:  Normal, Bold, Italic and 
** Bold-Italic in either variable or constant width.
** Within each family there can be up to 7 font sizes from 1
** (the smallest) up to 7 (the largest).  Hence, the widget can use
** a maximum of 56 fonts.  The ".font" field of the style is an integer
** between 0 and 55 which indicates which font to use.
*/
#define N_FONT_FAMILY     8
#define N_FONT_SIZE       7
#define N_FONT            (N_FONT_FAMILY*N_FONT_SIZE)
#define NormalFont(X)     (X)
#define BoldFont(X)       ((X)+N_FONT_SIZE)
#define ItalicFont(X)     ((X)+2*N_FONT_SIZE)
#define CWFont(X)         ((X)+4*N_FONT_SIZE)
#define FontSize(X)       ((X)%N_FONT_SIZE)
#define FontFamily(X)     (((X)/N_FONT_SIZE)*N_FONT_SIZE)
#define FONT_Any           -1
#define FONT_Default      3
#define FontSwitch(Size, Bold, Italic, Cw) \
                          ((Size)+(Bold+(Italic)*2+(Cw)*4)*N_FONT_SIZE)

/*
** Macros for manipulating the fontValid bitmap of an HtmlWidget structure.
*/
#define FontIsValid(H,I)     (((H)->fontValid[(I)>>3] & (1<<((I)&3)))!=0)
#define FontSetValid(H,I)    ((H)->fontValid[(I)>>3] |= (1<<((I)&3)))
#define FontClearValid(H,I)  ((H)->fontValid[(I)>>3] &= ~(1<<((I)&3)))

/*
** Information about available colors.
**
** The widget will use at most N_COLOR colors.  4 of these colors
** are predefined.  The rest are user selectable by options to
** various markups. (Ex:  <font color=red>)
**
** All colors are stored in the apColor[] array of the main widget
** structure.  The ".color" field of the HtmlStyle is an integer
** between 0 and N_COLOR-1 which indicates which of these colors 
** to use.
*/
#define N_COLOR             16      /* Total number of colors */
#define COLOR_Normal         0      /* Index for normal color (black) */
#define COLOR_Unvisited      1      /* Index for unvisited hyperlinks */
#define COLOR_Visited        2      /* Color for visited hyperlinks */
#define COLOR_Selection      3      /* Background color for the selection */
#define COLOR_Background     4      /* Default background color */
#define N_PREDEFINED_COLOR   5      /* Number of predefined colors */

/*
** The "align" field of the style determines how text is justified
** horizontally.  ALIGN_None means that the alignment is not specified.
** (It should probably default to ALIGN_Left in this case.)
*/
#define ALIGN_Left   1
#define ALIGN_Right  2
#define ALIGN_Center 3
#define ALIGN_None   0

/*
** Possible value of the "flags" field of HtmlStyle are shown below.
**
**  STY_Preformatted       If set, the current text occurred within
**                         <pre>..</pre>
**
**  STY_StrikeThru         Draw a solid line thru the middle of this text.
**
**  STY_Underline          This text should drawn with an underline.
**
**  STY_NoBreak            This text occurs within <nobr>..</nobr>
**
**  STY_Anchor             This text occurs within <a href=X>..</a>.
**
**  STY_DT                 This text occurs within <dt>..</dt>.                 
**
**  STY_Invisible          This text should not appear in the main HTML
**                         window.  (For example, it might be within 
**                         <title>..</title> or <marquee>..</marquee>.)
*/
#define STY_Preformatted    0x001
#define STY_StrikeThru      0x002
#define STY_Underline       0x004
#define STY_NoBreak         0x008
#define STY_Anchor          0x010
#define STY_DT              0x020
#define STY_Invisible       0x040
#define STY_FontMask        (STY_StrikeThru|STY_Underline)

/*
** The first thing done with input HTML text is to parse it into
** HtmlElements.  All sizing and layout is done using these elements,
** so this is a very important structure.
**
** Elements are designed so that the common ones (Text and Space)
** require as little storage as possible, in order to increase
** the chance of memory cache hits.  (Turns out I didn't do a
** very good job of this.  This widget is a pig for memory.  But
** the speed is good, so I'm not going to change it right now...)
**
** Some elements require more memory than Text and Space (ex: <IMG>).
** An HtmlElement is therefore represented as a union of many other 
** structures all of different sizes.  That way we can have a pointer 
** to a generic element without having to worry about how big that 
** element is.  The ".base.type" field (which is found in all elements) 
** will tell us what type of element we are dealing with.
**
** NOTE:  This trick will only work on compilers that align all elements
** of a union to the lowest memory address in that union.  This is true
** for every C compiler I've ever seen, but isn't guarenteed for ANSI-C.
*/
union HtmlElement {
  HtmlElement *pNext;
  HtmlBaseElement base;
  HtmlTextElement text;
  HtmlSpaceElement space;
  HtmlMarkupElement markup;
  HtmlCell cell;
  HtmlTable table;
  HtmlRef ref;
  HtmlLi li;
  HtmlListStart list;
  HtmlImageMarkup image;
  HtmlInput input;
  HtmlForm form;
  HtmlHr hr;
  HtmlAnchor anchor;
  HtmlScript script;
  HtmlBlock block;
};

/*
** Every element contains at least this much information:
*/
struct HtmlBaseElement {
  HtmlElement *pNext;         /* Next input token in a list of them all */
  HtmlElement *pPrev;         /* Previous token in a list of them all */
  HtmlStyle style;            /* The rendering style for this token */
  Html_u8 type;               /* The token type. */
  Html_u8 flags;              /* The HTML_ flags below */
  Html_16 count;              /* Various uses, depending on "type" */
};

/*
** Bitmasks for the "flags" field of the HtmlBaseElement
*/
#define HTML_Visible   0x01     /* This element produces "ink" */
#define HTML_NewLine   0x02     /* type==Html_Space and ends with newline */
#define HTML_Selected  0x04     /* Some or all of this Html_Block is selected */
                                /* Used by Html_Block elements only. */

/*
** Each text element holds additional information as show here.  Notice
** that extra space is allocated so that zText[] will be large enough
** to hold the complete text of the element.  X and y coordinates are
** relative to the virtual canvas.  The y coordinate refers to the
** baseline.
*/
struct HtmlTextElement {
  HtmlBaseElement base;       /* All the base information */
  Html_32 y;                  /* y coordinate where text should be rendered */
  Html_16 x;                  /* x coordinate where text should be rendered */
  Html_16 w;                  /* width of this token in pixels */
  Html_u8 ascent;             /* height above the baseline */
  Html_u8 descent;            /* depth below the baseline */
  Html_u8 spaceWidth;         /* Width of one space in the current font */
  char zText[1];              /* Text for this element.  Null terminated */
};

/*
** Each space element is represented like this:
*/
struct HtmlSpaceElement {
  HtmlBaseElement base;       /* All the base information */
  Html_16 w;                  /* Width of a single space in current font */
  Html_u8 ascent;             /* height above the baseline */
  Html_u8 descent;            /* depth below the baseline */
};

/*
** Most markup uses this structure.  Some markup extends this structure
** with additional information, but most use it as a base, at the very
** least. 
**
** If the markup doesn't have arguments (the "count" field of
** HtmlBaseElement is 0) then the extra "argv" field of this structure
** is not allocated and should not be used.
*/
struct HtmlMarkupElement {
  HtmlBaseElement base;
  char **argv;
};

/* Each <td> or <th> markup is represented by an instance of the 
** following structure.
**
** Drawing for a cell is a sunken 3D border with the border width given
** by the borderWidth field in the associated <table> structure.
*/
struct HtmlCell {
  HtmlMarkupElement markup;
  Html_16 rowspan;          /* Number of rows spanned by this cell */
  Html_16 colspan;          /* Number of columns spanned by this cell */
  Html_16 x;                /* X coordinate of left edge of border */
  Html_16 w;                /* Width of the border */
  Html_32 y;                /* Y coordinate of top of border indentation */
  Html_32 h;                /* Height of the border */
  HtmlElement *pTable;      /* Pointer back to the <table> */
  HtmlElement *pEnd;        /* Element that ends this cell */
};

/*
** The maximum number of columns allowed in a table.  Any columns beyond
** this number are ignored.
*/
#define HTML_MAX_COLUMNS 40

/*
** This structure is used for each <table> element.
**
** In the minW[] and maxW[] arrays, the [0] element is the overall
** minimum and maximum width, including cell padding, spacing and 
** the "hspace".  All other elements are the minimum and maximum 
** width for the contents of individual cells without any spacing or
** padding.
*/
struct HtmlTable {
  HtmlMarkupElement markup;
  Html_u8 borderWidth;           /* Width of the border */
  Html_u8 nCol;                  /* Number of columns */
  Html_u16 nRow;                 /* Number of rows */
  Html_32 y;                     /* top edge of table border */
  Html_32 h;                     /* height of the table border */
  Html_16 x;                     /* left edge of table border */
  Html_16 w;                     /* width of the table border */
  int minW[HTML_MAX_COLUMNS+1];  /* minimum width of each column */
  int maxW[HTML_MAX_COLUMNS+1];  /* maximum width of each column */
};

/* This structure is used for </table>, </td>, <tr>, </tr> 
** and </th> elements.  It points back to the <table> element 
** that began the table.  It is also used by </a> to point back
** to the original <a>.  I'll probably think of other uses before
** all is said and done...
*/
struct HtmlRef {
  HtmlMarkupElement markup;
  HtmlElement *pOther;         /* Pointer to some other Html element */
};

/*
** An instance of the following structure is used to represent
** each <LI> markup.
*/
struct HtmlLi {
  HtmlMarkupElement markup;
  Html_u8 type;     /* What type of list is this? */
  Html_u8 ascent;   /* height above the baseline */
  Html_u8 descent;  /* depth below the baseline */
  Html_16 cnt;      /* Value for this element (if inside <OL>) */
  Html_16 x;        /* X coordinate of the bullet */
  Html_32 y;        /* Y coordinate of the bullet */
};

/*
** The .type field of an HtmlLi or HtmlListStart structure can take on 
** any of the following values to indicate what type of bullet to draw.
** The value in HtmlLi will take precedence over the value in HtmlListStart
** if the two values differ.
*/
#define LI_TYPE_Undefined 0     /* If in HtmlLi, use the HtmlListStart value */
#define LI_TYPE_Bullet1   1     /* A solid circle */
#define LI_TYPE_Bullet2   2     /* A hollow circle */
#define LI_TYPE_Bullet3   3     /* A hollow square */
#define LI_TYPE_Enum_1    4     /* Arabic numbers */
#define LI_TYPE_Enum_A    5     /* A, B, C, ... */
#define LI_TYPE_Enum_a    6     /* a, b, c, ... */
#define LI_TYPE_Enum_I    7     /* Capitalized roman numerals */
#define LI_TYPE_Enum_i    8     /* Lower-case roman numerals */

/*
** An instance of this structure is used for <UL> or <OL>
** markup.
*/
struct HtmlListStart {
  HtmlMarkupElement markup;
  Html_u8 type;            /* One of the LI_TYPE_ defines above */
  Html_u8 compact;         /* True if the COMPACT flag is present */
  Html_u16 cnt;            /* Next value for <OL> */
  Html_u16 width;          /* How much space to allow for indentation */
  HtmlElement *pPrev;      /* Next higher level list, or NULL */
};

/*
** Information about each image on the HTML widget is held in an
** instance of the following structure.  A pointer to this structure
** is the clientData for the image change callback.  All image structures
** are held on a list attached to the main widget structure.
**
** This structure is NOT an element.  The <IMG> element is represented
** by an HtmlImageMarkup structure below.  There is one HtmlImageMarkup
** for each <IMG> in the source HTML.  There is one of these structures
** for each unique image loaded.  (If two <IMG> specify the same image,
** there are still two HtmlImageMarkup structures but only one
** HtmlImage structure that is shared between them.)
*/
struct HtmlImage {
  HtmlWidget *htmlPtr;     /* The owner of this image */
  Tk_Image image;          /* The Tk image token */
  Html_32 w;               /* Requested width of this image (0 if none) */
  Html_32 h;               /* Requested height of this image (0 if none) */
  char *zUrl;              /* The URL for this image. */
  char *zWidth, *zHeight;  /* Width and height in the <img> markup. */
  HtmlImage *pNext;        /* Next image on the list */
  HtmlElement *pList;      /* List of all <IMG> markups that use this 
                           ** same image */
};

/* Each <img> markup is represented by an instance of the 
** following structure.
**
** If pImage==0, then we use the alternative text in zAlt.
*/
struct HtmlImageMarkup {
  HtmlMarkupElement markup;
  Html_u8 align;          /* Alignment.  See IMAGE_ALIGN_ defines below */
  Html_u8 textAscent;     /* Ascent of text font in force at the <IMG> */
  Html_u8 textDescent;    /* Descent of text font in force at the <IMG> */
  Html_u8 redrawNeeded;   /* Need to redraw this image because the image
                          ** content changed. */
  Html_16 h;              /* Actual height of the image */
  Html_16 w;              /* Actual width of the image */
  Html_16 ascent;         /* How far image extends above "y" */
  Html_16 descent;        /* How far image extends below "y" */
  Html_16 x;              /* X coordinate of left edge of the image */
  Html_32 y;              /* Y coordinate of image baseline */
  char *zAlt;             /* Alternative text */
  HtmlImage *pImage;      /* Corresponding HtmlImage structure */
  HtmlElement *pNext;     /* Next markup using the same HtmlImage structure */
};

/*
** Allowed alignments for images.  These represent the allowed arguments
** to the "align=" field of the <IMG> markup.
*/
#define IMAGE_ALIGN_Bottom        0
#define IMAGE_ALIGN_Middle        1
#define IMAGE_ALIGN_Top           2
#define IMAGE_ALIGN_TextTop       3
#define IMAGE_ALIGN_AbsMiddle     4
#define IMAGE_ALIGN_AbsBottom     5
#define IMAGE_ALIGN_Left          6
#define IMAGE_ALIGN_Right         7

/*
** All kinds of form markup, including <INPUT>, <TEXTAREA> and <SELECT>
** are represented by instances of the following structure.
**
** (later...)  We also use this for the <APPLET> markup.  That way,
** the window we create for an <APPLET> responds to the HtmlMapControls()
** and HtmlUnmapControls() function calls.  For an <APPLET>, the
** pForm field is NULL.  (Later still...) <EMBED> works just like
** <APPLET> so it uses this structure too.
*/
struct HtmlInput {
  HtmlMarkupElement markup;
  HtmlElement *pForm;      /* The <FORM> to which this belongs */
  HtmlElement *pNext;      /* Next element in a list of all input elements */
  Tk_Window tkwin;         /* The window that implements this control */
  HtmlWidget *htmlPtr;     /* The whole widget.  Needed by geometry callbacks */
  HtmlElement *pEnd;       /* End tag for <TEXTAREA>, etc. */
  Html_32  y;              /* Baseline for this input element */
  Html_u16 x;              /* Left edge */
  Html_u16 w, h;           /* Width and height of this control */
  Html_u8 padLeft;         /* Extra padding on left side of the control */
  Html_u8 align;           /* One of the IMAGE_ALIGN_xxx  types */
  Html_u8 textAscent;      /* Ascent for the current font */
  Html_u8 textDescent;     /* descent for the current font */
  Html_u8 type;            /* What type of input is this? */
  Html_u8 sized;           /* True if this input has been sized already */
  Html_u16 cnt;            /* Used to derive widget name. 0 if no widget */
};

/*
** An input control can be one of the following types.  See the
** comment about <APPLET> on the HtmlInput structure insight into
** INPUT_TYPE_Applet.
*/
#define INPUT_TYPE_Unknown      0
#define INPUT_TYPE_Checkbox     1
#define INPUT_TYPE_File         2
#define INPUT_TYPE_Hidden       3
#define INPUT_TYPE_Image        4
#define INPUT_TYPE_Password     5
#define INPUT_TYPE_Radio        6
#define INPUT_TYPE_Reset        7
#define INPUT_TYPE_Select       8
#define INPUT_TYPE_Submit       9
#define INPUT_TYPE_Text        10
#define INPUT_TYPE_TextArea    11
#define INPUT_TYPE_Applet      12

/*
** There can be multiple <FORM> entries on a single HTML page.
** Each one must be given a unique number for identification purposes,
** and so we can generate unique state variable names for radiobuttons,
** checkbuttons, and entry boxes.
*/
struct HtmlForm {
  HtmlMarkupElement markup;
  Html_u16 id;             /* Unique number assigned to this form */
};

/*
** Information used by a <HR> markup
*/
struct HtmlHr {
  HtmlMarkupElement markup;
  Html_32  y;              /* Baseline for this input element */
  Html_u16 x;              /* Left edge */
  Html_u16 w, h;           /* Width and height of this control */
  Html_u8 is3D;            /* Is it drawn 3D? */
};

/*
** Information used by a <A> markup
*/
struct HtmlAnchor {
  HtmlMarkupElement markup;
  Html_32  y;              /* Top edge for this element */
};

/*
** Information about the <SCRIPT> markup.  The parser treats <SCRIPT>
** specially.  All text between <SCRIPT> and </SCRIPT> is captured and
** is pointed to by the zScript field of this structure.
**
** Note that zScript is not null-terminated.   Instead, zScript just
** points to a spot in the zText field of the HtmlWidget structure.
** The nScript field determines how long the script is.
*/
struct HtmlScript {
  HtmlMarkupElement markup;
  char *zScript;           /* Complete text of this script */
  int nScript;             /* Number of characters of text */
}

/*
** A block is a single unit of display information.  This can be
** one or more text elements, or the border of table, or an
** image, etc.
**
** Blocks are used to improve display speed and to improve the
** speed of linear searchs through the token list.  A single
** block will typically contain enough information to display
** a dozen or more Text and Space elements all with a single
** call to Tk_DrawChars().  The blocks are linked together on
** their own list, so we can search them much faster then elements
** (since there are fewer of them.)
**
** Of course, you can construct pathological HTML that has as
** many Blocks as it has normal tokens.  But you haven't lost
** anything.  Using blocks just speeds things up in the common
** case.
**
** Much of the information needed for display is held in the
** original HtmlElement structures.  "base.pNext" points to the first
** structure in the list which can be used to find the "style"
** "x" and "y".
**
** If n==0, then "base.pNext" might point to a special HtmlElement that
** defines some other kind of drawing, like <LI> or <IMG> or <INPUT>.
*/
struct HtmlBlock {
  HtmlBaseElement base;      /* Superclass.  Must be first */
  char *z;                   /* Space to hold text when n>0 */
  int top, bottom;           /* Extremes of y coordinates */
  Html_u16 left, right;      /* Left and right boundry of this object */
  Html_u16 n;                /* Number of characters in z[] */
  HtmlBlock *pPrev, *pNext;  /* Linked list of all Blocks */
};

/*
** Linux doesn't have a stricmp() function.
*/
#ifndef HAVE_STRICMP
# define stricmp strcasecmp
# define strnicmp strncasecmp
#endif

/*
** A stack of these structures is used to keep track of nested font and
** style changes.  This allows us to easily revert to the previous style
** when we encounter and end-tag like </em> or </h3>.
**
** This stack is used to keep track of the current style while walking
** the list of elements.  After all elements have been assigned a style,
** the information in this stack is no longer used.
*/
struct HtmlStyleStack {
  HtmlStyleStack *pNext;   /* Next style on the stack */
  int type;                /* A markup that ends this style. Ex: Html_EndEM */
  HtmlStyle style;         /* The currently active style. */
}

/*
** A stack of the following structures is used to remember the
** left and right margins within a layout context.
*/
struct HtmlMargin {
  int indent;          /* Size of the current margin */
  int bottom;          /* Y value at which this margin expires */
  int tag;             /* Markup that will cancel this margin */
  HtmlMargin *pNext;   /* Previous margin */
};

/*
** How much space (in pixels) used for a single level of indentation due
** to a <UL> or <DL> or <BLOCKQUOTE>, etc.
*/
#define HTML_INDENT 36

/*
** A layout context holds all state information used by the layout
** engine.
*/
struct HtmlLayoutContext {
  HtmlWidget *htmlPtr;          /* The html widget undergoing layout */
  HtmlElement *pStart;          /* Start of elements to layout */
  HtmlElement *pEnd;            /* Stop when reaching this element */
  int headRoom;                 /* Extra space wanted above this line */
  int top;                      /* Absolute top of drawing area */
  int bottom;                   /* Bottom of previous line */
  int left, right;              /* Left and right extremes of drawing area */
  int pageWidth;                /* Width of the layout field, including
                                ** the margins */
  int maxX, maxY;               /* Maximum X and Y values of paint */
  HtmlMargin *leftMargin;       /* Stack of left margins */
  HtmlMargin *rightMargin;      /* Stack of right margins */
};

/*
** With 28 different fonts and 16 colors, we could in principle have
** as many as 448 different GCs.  But in practice, a single page of
** HTML will typically have much less than this.  So we won't try to
** keep all GCs on hand.  Instead, We'll keep around the most recently
** used GCs and allocate new ones as necessary.
**
** The following structure is used to build a cache of GCs in the
** main widget structure.
*/
#define N_CACHE_GC 16
struct GcCache {
  GC gc;                /* The graphics context */
  Html_u8 font;         /* Font used for this context */
  Html_u8 color;        /* Color used for this context */
  Html_u8 index;        /* Index used for LRU replacement */
};

/*
** An HtmlIndex is a reference to a particular character within a
** particular Text or Space token.  
*/
struct HtmlIndex {
  HtmlElement *p;      /* The token containing the character */
  int i;               /* Index of the character */
};

/*
** A single instance of the following structure (together with various
** other structures to which this structure points) contains complete 
** state information for a single HTML widget.  The clientData for
** the widget command is a pointer to this structure.
**
** The HTML widget is really a mega-widget.  It consists of two nested
** windows.  The outer window (tkwin) contains the focus highlight border,
** the 3D border and the padding between the border and the text.  All
** text that results from the HTML is drawn into the clipping window
** (clipwin).  The clipping window is a child of the main
** window and has the name "x".  We have to use a clipping window so
** that subwindows required by <FORM> will be clipped properly and won't
** overlap with the borders.
**
** Two primary coordinate systems are used in this widget.
**
**   Window coordinates      In this system, (0,0) is the upper left-hand
**                           corner of the clipping window.  This coordinates
**                           apply only to objects which is visible on screen.
**
**   Virtual canvas          The virtual canvas is an imaginary canvas holding
**                           the entire document.  Typically, part of the
**                           virtual canvas will show thru the clipping 
**                           window to become visible.  The mapping from
**                           window to virtual canvas coordinates is
**                           governed by the "xOffset" and "yOffset" fields
**                           of the widget structure.
**
** 
*/
struct HtmlWidget {
  Tk_Window tkwin;              /* The main window for this widget */
  Tk_Window clipwin;            /* The clipping window in which all text is
                                ** rendered. */
  char *zClipwin;               /* Name of the clipping window. */
  Display *display;             /* The X11 Server that contains tkwin */
  Tcl_Interp *interp;           /* The interpreter in which the widget lives */
  char *zCmdName;               /* Name of the command */
  HtmlElement *pFirst;          /* First HTML token on a list of them all */
  HtmlElement *pLast;           /* Last HTML token on the list */
  int nToken;                   /* Number of HTML tokens on the list.
                                 * Html_Block tokens don't count. */
  HtmlElement *lastSized;       /* Last HTML element that has been sized */
  HtmlElement *nextPlaced;      /* Next HTML element that needs to be 
                                 * positioned on canvas. */
  HtmlBlock *firstBlock;        /* List of all HtmlBlock tokens */
  HtmlBlock *lastBlock;         /* Last HtmlBlock in the list */
  HtmlElement *firstInput;      /* First <INPUT> element */
  HtmlElement *lastInput;       /* Last <INPUT> element */
  int nInput;                   /* The number of <INPUT> elements */
  int nForm;                    /* The number of <FORM> elements */
  int varId;                    /* Used to construct a unique name for a
                                ** global array used by <INPUT> elements */

  /*
   * Information about the selected region of text
   */
  HtmlIndex selBegin;           /* Start of the selection */
  HtmlIndex selEnd;             /* End of the selection */
  HtmlBlock *pSelStartBlock;    /* Block in which selection starts */
  Html_16 selStartIndex;        /* Index in pSelStartBlock of first selected
                                 * character */
  Html_16 selEndIndex;          /* Index of last selecte char in pSelEndBlock */
  HtmlBlock *pSelEndBlock;      /* Block in which selection ends */

  /*
   * Information about the insertion cursor 
   */
  int insOnTime;                /* How long the cursor states one (millisec) */
  int insOffTime;               /* How long it is off (milliseconds) */
  int insStatus;                /* Is it visible? */
  Tcl_TimerToken insTimer;      /* Timer used to flash the insertion cursor */
  HtmlIndex ins;                /* The insertion cursor position */
  HtmlBlock *pInsBlock;         /* The HtmlBlock containing the cursor */
  int insIndex;                 /* Index in pInsBlock of the cursor */

  /*
   * The following fields hold state information used by
   * the tokenizer.
   */
  char *zText;                  /* Complete text of the unparsed HTML */
  int nText;                    /* Number of characters in zText */
  int nAlloc;                   /* Space allocated for zText */
  int nComplete;                /* How much of zText has actually been
                                 * converted into tokens */
  int iCol;                     /* The column in which zText[nComplete]
                                 * occurs.  Used to resolve tabs in input */
  int iPlaintext;               /* If not zero, this is the token type that
                                 * caused us to go into plaintext mode.  One
                                 * of Html_PLAINTEXT, Html_LISTING or
                                 * Html_XMP */
  HtmlScript *pScript;            /* <SCRIPT> currently being parsed */
  char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that
                                 * is used to process tokens of the given 
                                 * type */
  /*
   * These fields hold state information used by the HtmlAddStyle routine.
   * We have to store this state information here since HtmlAddStyle
   * operates incrementally.  This information must be carried from
   * one incremental execution to the next.
   */
  HtmlStyleStack *styleStack;   /* The style stack */
  int paraAlignment;            /* Justification associated with <p> */
  int rowAlignment;             /* Justification associated with <tr> */
  int anchorFlags;              /* Style flags associated with <A>...</A> */
  int inDt;                     /* Style flags associated with <DT>...</DT> */
  int inTr;                     /* True if within <tr>..</tr> */
  int inTd;                     /* True if within <td>..</td> or <th>..</th> */
  HtmlElement *anchorStart;     /* Most recent <a href=...> */
  HtmlElement *formStart;       /* Most recent <form> */
  HtmlElement *formElemStart;   /* Most recent <textarea> or <select> */
  HtmlElement *innerList;       /* The inner most <OL> or <UL> */

  /*
   * These fields are used to hold the state of the layout engine.
   * Because the layout is incremental, this state must be held for
   * the life of the widget.
   */
  HtmlLayoutContext layoutContext;

  /*
   * Information used when displaying the widget:
   */
  Tk_3DBorder border;		/* Background color */
  int borderWidth;		/* Width of the border. */
  int relief;			/* 3-D effect: TK_RELIEF_RAISED, etc. */
  int highlightWidth;		/* Width in pixels of highlight to draw
				 * around widget when it has the focus.
				 * <= 0 means don't draw a highlight. */
  XColor *highlightBgColorPtr;  /* Color for drawing traversal highlight
				 * area when highlight is off. */
  XColor *highlightColorPtr;	/* Color for drawing traversal highlight. */
  int inset;			/* Total width of highlight and 3-D border */
  Tk_Font aFont[N_FONT];	/* Information about all screen fonts */
  char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0
                                 * if aFont[N] needs to be reallocated before
                                 * being used. */
  XColor *apColor[N_COLOR];     /* Information about all colors */
  int colorUsed;                /* bit N is 1 if color N is in use.  Only
                                ** applies to colors that aren't predefined */
  int iDark[N_COLOR];           /* Dark 3D shadow of color K is iDark[K] */
  int iLight[N_COLOR];          /* Light 3D shadow of color K is iLight[K] */
  XColor *fgColor;              /* Color of normal text. apColor[0] */
  XColor *newLinkColor;         /* Color of unvisitied links. apColor[1] */
  XColor *oldLinkColor;         /* Color of visitied links. apColor[2] */
  XColor *selectionColor;       /* Background color for selections */
  GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */
  int lastGC;                   /* Index of recently used GC */
  HtmlImage *imageList;         /* A list of all images */
  int width, height;		/* User-requested size of the usable drawing
                                 * area, in pixels.   Borders and padding
                                 * make the actual window a little larger */
  int realWidth, realHeight;    /* The actual physical size of tkwin as
                                 * reported in the most recent ConfigureNotify
                                 * event. */
  int padx, pady;               /* Separation between the edge of the window
                                 * and rendered HTML.  */
  int underlineLinks;           /* TRUE if we should underline hyperlinks */

  /* Information about the selection
  */
  int exportSelection;          /* True if the selection is automatically
                                 * exported to the clipboard */

  /* Callback commands.  The HTML parser will invoke callbacks from time
  ** to time to find out information it needs to complete formatting of
  ** the document.  The following fields define the callback commands.
  */
  char *zIsVisited;             /* Command to tell if a hyperlink has already
                                ** been visited */
  char *zGetImage;              /* Command to get an image from a URL */
  char *zFrameCommand;          /* Command for handling <frameset> markup */
  char *zAppletCommand;         /* Command to process applets */
  char *zResolverCommand;       /* Command to resolve URIs */
  char *zFormCommand;           /* When user presses Submit */
  char *zHyperlinkCommand;      /* Invoked when a hyperlink is clicked */
  char *zFontCommand;           /* Invoked to find font names */
  char *zScriptCommand;         /* Invoked for each <SCRIPT> markup */

   /*
    * Miscellaneous information:
    */
  int tableRelief;              /* 3d effects on <TABLE> */
  int ruleRelief;               /* 3d effects on <HR> */
  char *zBase;                  /* The base URI */
  char *zBaseHref;              /* zBase as modified by <BASE HREF=..> markup */
  Tk_Cursor cursor;		/* Current cursor for window, or None. */
  char *takeFocus;		/* Value of -takefocus option;  not used in
				 * the C code, but used by keyboard traversal
				 * scripts.  Malloc'ed, but may be NULL. */
  char *yScrollCmd;		/* Command prefix for communicating with
				 * vertical scrollbar.  NULL means no command
				 * to issue.  Malloc'ed. */
  char *xScrollCmd;		/* Command prefix for communicating with
				 * horizontal scrollbar.  NULL means no command
				 * to issue.  Malloc'ed. */
  int xOffset, yOffset;         /* Current scroll position.  These form the
                                 * coordinate in the virtual canvas that
                                 * corresponds to (0,0) on the physical screen
                                 * in window tkwin */
  int maxX, maxY;               /* Maximum extent of any "paint" that appears
                                 * on the virtual canvas.  Used to compute 
                                 * scrollbar positions. */
  int dirtyLeft, dirtyTop;      /* Top left corner of region to redraw.  These
                                 * are physical screen coordinates relative to
                                 * clipwin, not tkwin. */
  int dirtyRight, dirtyBottom;  /* Bottom right corner of region to redraw */
  int locked;                   /* Number of locks on this structure. Don't
                                ** delete until it reaches zero. */
  int flags;			/* Various flags;  see below for
				 * definitions. */
}

/*
 * Flag bits "flags" field of the Html widget:
 *
 * REDRAW_PENDING         A DoWhenIdle handler has already been queued to 
 *                        call HtmlRedrawCallback() function.
 *
 * GOT_FOCUS              This widget currently has input focus.
 *
 * HSCROLL                Horizontal scrollbar position needs to be
 *                        recomputed.
 *
 * VSCROLL                Vertical scrollbar position needs to be
 *                        recomputed.
 *
 * RELAYOUT               We need to reposition every element on the 
 *                        virtual canvas.  (This happens, for example,
 *                        when the size of the widget changes and we
 *                        need to recompute the line breaks.)
 *
 * RESIZE_ELEMENTS        We need to recompute the size of every element.
 *                        This happens, for example, when the fonts
 *                        change.
 *
 * REDRAW_FOCUS           We need to repaint the focus highlight border.
 *
 * REDRAW_TEXT            Everything in the clipping window needs to be redrawn.
 *
 * REDRAW_BORDER          Everything outside the clipping window needs
 *                        to be redrawn.
 *
 * RESIZE_CLIPWIN         The size and position of the clipping window 
 *                        needs to be adjusted using Tk_MoveResizeWindow().
 *
 * STYLER_RUNNING         There is a call to HtmlAddStyle() in process.
 *                        Used to prevent a recursive call to HtmlAddStyle().
 *
 * INSERT_FLASHING        True if there is a timer callback pending that will
 *                        toggle the state of the insertion cursor.
 *
 * REDRAW_IMAGES          One or more HtmlImageMarkup structures have
 *                        their redrawNeeded flag set.
 */

#define REDRAW_PENDING	     0x000001
#define GOT_FOCUS            0x000002
#define HSCROLL              0x000004
#define VSCROLL              0x000008
#define RELAYOUT             0x000010
#define RESIZE_ELEMENTS      0x000020
#define REDRAW_FOCUS         0x000040
#define REDRAW_TEXT          0x000080
#define REDRAW_BORDER        0x000100
#define EXTEND_LAYOUT        0x000200
#define RESIZE_CLIPWIN       0x000400
#define STYLER_RUNNING       0x000800
#define INSERT_FLASHING      0x001000
#define REDRAW_IMAGES        0x002000

/*
** Macros to set, clear or test bits of the "flags" field.
*/
#define HtmlHasFlag(A,F)      (((A)->flags&(F))==(F))
#define HtmlHasAnyFlag(A,F)   (((A)->flags&(F))!=0)
#define HtmlSetFlag(A,F)      ((A)->flags|=(F))
#define HtmlClearFlag(A,F)    ((A)->flags&=~(F))

/*
** No coordinate is every as big as this number
*/
#define LARGE_NUMBER 100000000

/*
** Default values for configuration options
*/
#define DEF_HTML_BG_COLOR             DEF_FRAME_BG_COLOR
#define DEF_HTML_BG_MONO              DEF_FRAME_BG_MONO
#define DEF_HTML_BORDER_WIDTH         "2"
#define DEF_HTML_CALLBACK             ""
#define DEF_HTML_CURSOR               DEF_FRAME_CURSOR
#define DEF_HTML_EXPORT_SEL           "yes"
#define DEF_HTML_FG                   DEF_BUTTON_FG
#define DEF_HTML_HEIGHT               "400"
#define DEF_HTML_HIGHLIGHT_BG         DEF_BUTTON_HIGHLIGHT_BG
#define DEF_HTML_HIGHLIGHT            DEF_BUTTON_HIGHLIGHT
#define DEF_HTML_HIGHLIGHT_WIDTH      "0"
#define DEF_HTML_INSERT_OFF_TIME      "300"
#define DEF_HTML_INSERT_ON_TIME       "600"
#define DEF_HTML_PADX                 "5"
#define DEF_HTML_PADY                 "5"
#define DEF_HTML_RELIEF               "raised"
#define DEF_HTML_SCROLL_COMMAND       ""
#define DEF_HTML_SELECTION_COLOR      "skyblue"
#define DEF_HTML_TAKE_FOCUS           "0"
#define DEF_HTML_UNVISITED            "blue1"
#define DEF_HTML_VISITED              "blue3"
#define DEF_HTML_WIDTH                "600"

#ifdef NAVIGATOR_TABLES

#define DEF_HTML_TABLE_BORDER             "0"
#define DEF_HTML_TABLE_CELLPADDING        "2"
#define DEF_HTML_TABLE_CELLSPACING        "5"
#define DEF_HTML_TABLE_BORDER_LIGHT_COLOR "gray80"
#define DEF_HTML_TABLE_BORDER_DARK_COLOR  "gray40"

#endif /* NAVIGATOR_TABLES */
