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