// $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 , and elements. // It points back to the
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
, ,
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... class TGHtmlRef : public TGHtmlMarkupElement { public: TGHtmlRef(int type, int argc, int arglen[], char *argv[]); ~TGHtmlRef() override; public: TGHtmlElement *fPOther; // Pointer to some other Html element TImage *fBgImage; // A background for the entire row }; // An instance of the following class is used to represent // each
  • markup. class TGHtmlLi : public TGHtmlMarkupElement { public: TGHtmlLi(int type, int argc, int arglen[], char *argv[]); public: Html_u8_t fLtype; // What type of list is this? Html_u8_t fAscent; // height above the baseline Html_u8_t fDescent; // depth below the baseline Html_16_t fCnt; // Value for this element (if inside
      ) Html_16_t fX; // X coordinate of the bullet Html_32_t fY; // Y coordinate of the bullet }; // The ltype field of an TGHtmlLi or TGHtmlListStart object can take on // any of the following values to indicate what type of bullet to draw. // The value in TGHtmlLi will take precedence over the value in // TGHtmlListStart if the two values differ. #define LI_TYPE_Undefined 0 // If in TGHtmlLi, use the TGHtmlListStart 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 class is used for
        or
          markup. class TGHtmlListStart : public TGHtmlMarkupElement { public: TGHtmlListStart(int type, int argc, int arglen[], char *argv[]); public: Html_u8_t fLtype; // One of the LI_TYPE_ defines above Html_u8_t fCompact; // True if the COMPACT flag is present Html_u16_t fCnt; // Next value for
            Html_u16_t fWidth; // How much space to allow for indentation TGHtmlListStart *fLPrev; // Next higher level list, or NULL }; #define HTML_MAP_RECT 1 #define HTML_MAP_CIRCLE 2 #define HTML_MAP_POLY 3 class TGHtmlMapArea : public TGHtmlMarkupElement { public: TGHtmlMapArea(int type, int argc, int arglen[], char *argv[]); public: int fMType; int *fCoords; int fNum; }; //---------------------------------------------------------------------- // Structure to chain extension data onto. struct SHtmlExtensions_t { void *fExts; int fTyp; int fFlags; SHtmlExtensions_t *fNext; }; //---------------------------------------------------------------------- // Information about each image on the HTML widget is held in an instance // of the following class. All images are held on a list attached to the // main widget object. // // This class is NOT an element. The element is represented by an // TGHtmlImageMarkup object below. There is one TGHtmlImageMarkup for each // in the source HTML. There is one of these objects for each unique // image loaded. (If two specify the same image, there are still two // TGHtmlImageMarkup objects but only one TGHtmlImage object that is shared // between them.) class TGHtml; class TGHtmlImageMarkup; class TGHtmlImage : public TObject { private: TGHtmlImage(const TGHtmlImage&) = delete; TGHtmlImage &operator=(const TGHtmlImage&) = delete; public: TGHtmlImage(TGHtml *htm, const char *url, const char *width, const char *height); ~TGHtmlImage() override; public: TGHtml *fHtml; // The owner of this image TImage *fImage; // The image token Html_32_t fW; // Requested width of this image (0 if none) Html_32_t fH; // Requested height of this image (0 if none) char *fZUrl; // The URL for this image. char *fZWidth, *fZHeight; // Width and height in the markup. TGHtmlImage *fPNext; // Next image on the list TGHtmlImageMarkup *fPList; // List of all markups that use this // same image TTimer *fTimer; // for animations }; // Each markup is represented by an instance of the following // class. // // If pImage == 0, then we use the alternative text in zAlt. class TGHtmlImageMarkup : public TGHtmlMarkupElement { public: TGHtmlImageMarkup(int type, int argc, int arglen[], char *argv[]); public: Html_u8_t fAlign; // Alignment. See IMAGE_ALIGN_ defines below Html_u8_t fTextAscent; // Ascent of text font in force at the Html_u8_t fTextDescent; // Descent of text font in force at the Html_u8_t fRedrawNeeded; // Need to redraw this image because the image // content changed. Html_16_t fH; // Actual height of the image Html_16_t fW; // Actual width of the image Html_16_t fAscent; // How far image extends above "y" Html_16_t fDescent; // How far image extends below "y" Html_16_t fX; // X coordinate of left edge of the image Html_32_t fY; // Y coordinate of image baseline const char *fZAlt; // Alternative text TGHtmlImage *fPImage; // Corresponding TGHtmlImage object TGHtmlElement *fPMap; // usemap TGHtmlImageMarkup *fINext; // Next markup using the same TGHtmlImage object }; // 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 ,