// $Id: TGHtml.h,v 1.1 2007/05/04 17:07:01 brun Exp $
// Author: Valeriy Onuchin 03/05/2007
/*************************************************************************
* Copyright (C) 1995-2021, Rene Brun, Fons Rademakers and Reiner Rohlfs *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
/**************************************************************************
HTML widget for xclass. Based on tkhtml 1.28
Copyright (C) 1997-2000 D. Richard Hipp
Copyright (C) 2002-2003 Hector Peraza.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
**************************************************************************/
#ifndef ROOT_TGHtml
#define ROOT_TGHtml
#include "TGView.h"
#include "TGHtmlTokens.h"
class TGClient;
class TImage;
class TGFont;
class TGIdleHandler;
class THashTable;
class TTimer;
class TGPopupMenu;
//----------------------------------------------------------------------
#define HTML_RELIEF_FLAT 0
#define HTML_RELIEF_SUNKEN 1
#define HTML_RELIEF_RAISED 2
//#define TABLE_TRIM_BLANK 1
// Debug must be turned on for testing to work.
//#define DEBUG
#define CANT_HAPPEN \
fprintf(stderr, \
"Unplanned behavior in the HTML Widget in file %s line %d\n", \
__FILE__, __LINE__)
#define UNTESTED \
fprintf(stderr, \
"Untested code executed in the HTML Widget in file %s line %d\n", \
__FILE__, __LINE__)
// 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
// 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
// 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
extern int HtmlTraceMask;
extern int HtmlDepth;
# 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
//----------------------------------------------------------------------
// 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_t; // 8-bit unsigned integer
typedef short Html_16_t; // 16-bit signed integer
typedef unsigned short Html_u16_t; // 16-bit unsigned integer
typedef int Html_32_t; // 32-bit signed integer
// An instance of the following structure is used to record style
// information on each Html element.
struct SHtmlStyle_t {
unsigned int fFont : 6; // Font to use for display
unsigned int fColor : 6; // Foreground color
signed int fSubscript : 4; // Positive for , negative for
unsigned int fAlign : 2; // Horizontal alignment
unsigned int fBgcolor : 6; // Background color
unsigned int fExpbg : 1; // Set to 1 if bgcolor explicitly set
unsigned int fFlags : 7; // 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.
// HP: we further subdivide the .font field into two 3-bit subfields (size
// and family). That makes easier to manipulate the family field.
#define N_FONT_FAMILY 8
#define N_FONT_SIZE 7
#define N_FONT 71
#define NormalFont(X) (X)
#define BoldFont(X) ((X) | 8)
#define ItalicFont(X) ((X) | 16)
#define CWFont(X) ((X) | 32)
#define FontSize(X) ((X) & 007)
#define FontFamily(X) ((X) & 070)
#define FONT_Any -1
#define FONT_Default 3
#define FontSwitch(Size, Bold, Italic, Cw) \
((Size) | ((Bold+(Italic)*2+(Cw)*4) << 3))
// Macros for manipulating the fontValid bitmap of an TGHtml object.
#define FontIsValid(I) ((fFontValid[(I)>>3] & (1<<((I)&3)))!=0)
#define FontSetValid(I) (fFontValid[(I)>>3] |= (1<<((I)&3)))
#define FontClearValid(I) (fFontValid[(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 object.
// The ".color" field of the SHtmlStyle_t is an integer between 0 and
// N_COLOR-1 which indicates which of these colors to use.
#define N_COLOR 32 // 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 SHtmlStyle_t 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
// TGHtmlElements. All sizing and layout is done using these elements.
// Every element contains at least this much information:
class TGHtmlElement : public TObject {
public:
TGHtmlElement(int etype = 0);
virtual int IsMarkup() const { return (fType > Html_Block); }
virtual const char *MarkupArg(const char * /*tag*/, const char * /*zDefault*/) { return nullptr; }
virtual int GetAlignment(int dflt) { return dflt; }
virtual int GetOrderedListType(int dflt) { return dflt; }
virtual int GetUnorderedListType(int dflt) { return dflt; }
virtual int GetVerticalAlignment(int dflt) { return dflt; }
public:
TGHtmlElement *fPNext; // Next input token in a list of them all
TGHtmlElement *fPPrev; // Previous token in a list of them all
SHtmlStyle_t fStyle; // The rendering style for this token
Html_u8_t fType; // The token type.
Html_u8_t fFlags; // The HTML_ flags below
Html_16_t fCount; // Various uses, depending on "type"
int fElId; // Unique identifier
int fOffs; // Offset within zText
};
// Bitmasks for the "flags" field of the TGHtmlElement
#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 shown 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.
class TGHtmlTextElement : public TGHtmlElement {
private:
TGHtmlTextElement(const TGHtmlTextElement&) = delete;
TGHtmlTextElement &operator=(const TGHtmlTextElement&) = delete;
public:
TGHtmlTextElement(int size);
~TGHtmlTextElement() override;
Html_32_t fY; // y coordinate where text should be rendered
Html_16_t fX; // x coordinate where text should be rendered
Html_16_t fW; // width of this token in pixels
Html_u8_t fAscent; // height above the baseline
Html_u8_t fDescent; // depth below the baseline
Html_u8_t fSpaceWidth; // Width of one space in the current font
char *fZText; // Text for this element. Null terminated
};
// Each space element is represented like this:
class TGHtmlSpaceElement : public TGHtmlElement {
public:
Html_16_t fW; // Width of a single space in current font
Html_u8_t fAscent; // height above the baseline
Html_u8_t fDescent; // depth below the baseline
public:
TGHtmlSpaceElement() : TGHtmlElement(Html_Space), fW(0), fAscent(0), fDescent(0) {}
};
// Most markup uses this class. Some markup extends this class with
// additional information, but most use it as is, at the very least.
//
// If the markup doesn't have arguments (the "count" field of
// TGHtmlElement is 0) then the extra "argv" field of this class
// is not allocated and should not be used.
class TGHtmlMarkupElement : public TGHtmlElement {
public:
TGHtmlMarkupElement(int type, int argc, int arglen[], char *argv[]);
~TGHtmlMarkupElement() override;
const char *MarkupArg(const char *tag, const char *zDefault) override;
int GetAlignment(int dflt) override;
int GetOrderedListType(int dflt) override;
int GetUnorderedListType(int dflt) override;
int GetVerticalAlignment(int dflt) override;
public://protected:
char **fArgv;
};
// The maximum number of columns allowed in a table. Any columns beyond
// this number are ignored.
#define HTML_MAX_COLUMNS 40
// This class 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.
class TGHtmlTable : public TGHtmlMarkupElement {
public:
TGHtmlTable(int type, int argc, int arglen[], char *argv[]);
~TGHtmlTable() override;
public:
Html_u8_t fBorderWidth; // Width of the border
Html_u8_t fNCol; // Number of columns
Html_u16_t fNRow; // Number of rows
Html_32_t fY; // top edge of table border
Html_32_t fH; // height of the table border
Html_16_t fX; // left edge of table border
Html_16_t fW; // width of the table border
int fMinW[HTML_MAX_COLUMNS+1]; // minimum width of each column
int fMaxW[HTML_MAX_COLUMNS+1]; // maximum width of each column
TGHtmlElement *fPEnd; // Pointer to the end tag element
TImage *fBgImage; // A background for the entire table
int fHasbg; // 1 if a table above has bgImage
};
// Each
or
markup is represented by an instance of the
// following class.
//
// Drawing for a cell is a sunken 3D border with the border width given
// by the borderWidth field in the associated
object.
class TGHtmlCell : public TGHtmlMarkupElement {
public:
TGHtmlCell(int type, int argc, int arglen[], char *argv[]);
~TGHtmlCell() override;
public:
Html_16_t fRowspan; // Number of rows spanned by this cell
Html_16_t fColspan; // Number of columns spanned by this cell
Html_16_t fX; // X coordinate of left edge of border
Html_16_t fW; // Width of the border
Html_32_t fY; // Y coordinate of top of border indentation
Html_32_t fH; // Height of the border
TGHtmlTable *fPTable; // Pointer back to the
TGHtmlElement *fPRow; // Pointer back to the
TGHtmlElement *fPEnd; // Element that ends this cell
TImage *fBgImage; // Background for the cell
};
// This class is used for