/* ** Structures and typedefs used by the HTML widget ** $Revision$ ** ** 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))*/ void* HtmlAlloc(size_t); #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 , negative for */ 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: ) ** ** 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 **
..
** ** 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 .. ** ** STY_Anchor This text occurs within ... ** ** STY_DT This text occurs within
..
. ** ** STY_Invisible This text should not appear in the main HTML ** window. (For example, it might be within ** .. or ...) */ #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: ). ** 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 or 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 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
*/ 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
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
, , , ** and elements. It points back to the element ** that began the table. It is also used by to point back ** to the original . 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
  • 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
      ) */ 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
        or
          ** 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
            */ 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 element is represented ** by an HtmlImageMarkup structure below. There is one HtmlImageMarkup ** for each in the source HTML. There is one of these structures ** for each unique image loaded. (If two 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 markup. */ HtmlImage *pNext; /* Next image on the list */ HtmlElement *pList; /* List of all markups that use this ** same image */ }; /* Each 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 */ Html_u8 textDescent; /* Descent of text font in force at the */ 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 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 ,