/*****
* format.c : XmHTML formatting routines: translates parsed HTML to info
* required for displaying a HTML page.
*
* This file Version $Revision: 1.13 $
*
* Creation date: Tue Nov 26 17:03:09 GMT+0100 1996
* Last modification: $Date: 1999/07/29 01:26:28 $
* By: $Author: sopwith $
* Current State: $State: Exp $
*
* Author: newt
* (C)Copyright 1995-1996 Ripley Software Development
* All Rights Reserved
*
* This file is part of the XmHTML TWidget Library.
*
* 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.
*
*****/
/*****
* ChangeLog
* $Log: format.c,v $
* Revision 1.13 1999/07/29 01:26:28 sopwith
*
*
* Fix all warnings.
*
* Revision 1.12 1999/06/02 01:00:39 unammx
*
* 1999-06-01 Akira Higuchi
*
* * libgnomeui/gnome-canvas-text.c:
* * libgnomeui/gnome-icon-item.c:
* * libgnomeui/gnome-less.c: Replace some gdk_font_load() calls with
* gdk_fontset_load. Use a more open fontset rule to load the fonts.
*
* 1999-06-01 Akira Higuchi
*
* * gtk-xmhtml/XmHTMLP.h: Add three members lbearing, rbearing,
* and width. These members are computed in allocFont().
*
* * gtk-xmhtml/toolkit.h: Remove Toolkit_XFont() macro.
*
* * gtk-xmhtml/XmHTML.c:
* * gtk-xmhtml/fonts.c:
* * gtk-xmhtml/format.c:
* * gtk-xmhtml/gtk-xmhtml.c:
* * gtk-xmhtml/layout.c:
* * gtk-xmhtml/paint.c: Add fontset support. We use gdk_fontset_load()
* instead of gdk_font_load() iff a fontset is supplied for label
* widgets.
*
* * gtk-xmhtml/test.c: Add gtk_set_locale() call before gtk_init().
*
* Revision 1.11 1998/06/23 18:45:55 unammx
* James Henstridge's signal fixes to GtkXmHTML
*
* Revision 1.10 1998/02/12 03:08:39 unammx
* Merge to Koen's XmHTML 1.1.2 + following fixes:
*
* Wed Feb 11 20:27:19 1998 Miguel de Icaza
*
* * gtk-forms.c (freeForm): gtk_destroy_widget is no longer needed
* with the refcounting changes.
*
* * gtk-xmhtml.c (gtk_xmhtml_remove): Only god knows why I was
* adding the just removed widget.
*
* Revision 1.9 1998/01/14 05:49:51 unammx
* Tue Jan 13 22:04:43 1998 Federico Mena
*
* * gtk-xmhtml.c (gtk_xmhtml_new): The widget starts up frozen and
* thaws itself when it is realized. This fixes all of the problems
* regarding realization, gc creation, and window background setting.
*
* (Federico and Miguel)
*
* Revision 1.8 1998/01/14 04:11:52 unammx
* Tue Jan 13 22:04:43 1998 Federico Mena
*
* * Lots of changes all over the place to fix colors. Things are
* *almost* working right now. I think I'm only missing setting the
* window backgrounds appropriately. Several things were done:
*
* - Motif's color and gc fields from Core and XmManager were
* replicated inside the GtkXmHTML widget structure.
*
* - Macros were created in toolkit.h to use these fields.
*
* - Instead of the old kludgy set_{fore,back}ground_internal
* functions, we now set the window background directly.
* This does not work perfectly; I'll look into it.
*
* - I created a shade_color() function in colors.c (ok, ok,
* I stole it from gtkstyle.c) which mimics XmGetColors()
* -- it calculates shaded colors for the 3D look.
*
* I hope to fix the remaining problems with window backgrounds real
* soon now.
*
* Revision 1.7 1998/01/09 06:10:23 unammx
* Fixed (?) background colors of the HTML widget. I'm not 100% sure I did it
* the right way, but it seems to work.
*
* - Federico
*
* Revision 1.6 1997/12/29 22:16:25 unammx
* This version does:
*
* - Sync with Koen to version Beta 1.1.2c of the XmHTML widget.
* Includes various table fixes.
*
* - Callbacks are now properly checked for the Gtk edition (ie,
* signals).
*
* Revision 1.5 1997/12/27 20:58:17 unammx
* More access functions to the widget internals. I missed these
* yesterday (ie, those that did not require SetValues validation
* now have an explicit routine to change the values).
*
* Frame support depends on the client of the widget, we should catch
* that signal and do something with it, I have not figured out exacly
* how it works, but example_2 in the XmHTML-1.1.1 distribution has an
* example of this working.
*
* Miguel.
*
* Revision 1.4 1997/12/25 01:34:11 unammx
* Good news for the day:
*
* I have upgraded our XmHTML sources to XmHTML 1.1.1.
*
* This basically means that we got table support :-)
*
* Still left to do:
*
* - Set/Get gtk interface for all of the toys in the widget.
* - Frame support is broken, dunno why.
* - Form support (ie adding widgets to it)
*
* Miguel.
*
* Revision 1.3 1997/12/13 01:49:15 unammx
* your daily dose of ported XmHTML code, non functional as usual -mig
*
* Revision 1.2 1997/12/11 21:20:21 unammx
* Step 2: more gtk/xmhtml code, still non-working - mig
*
* Revision 1.1 1997/11/28 03:38:56 gnomecvs
* Work in progress port of XmHTML; No, it does not compile, don't even try -mig
*
* Revision 1.17 1997/10/23 00:24:56 newt
* XmHTML Beta 1.1.0 release
*
* Revision 1.16 1997/08/31 17:34:24 newt
* renamed _rec structures to Rec.
*
* Revision 1.15 1997/08/30 00:55:24 newt
* Completed support.
* Bugfix in _XmHTMLInitializeFontSizeLists, the default font is now properly
* changed.
* Made the font loading routines again robuster.
* ParseBodyTags now always attempts to load a body image.
* Made XmHTMLGetURLType a bit stricter.
*
* Revision 1.14 1997/08/01 13:00:21 newt
* Bugfixes in font switching (.........) now
* properly handler. Enhanced form support.
*
* Revision 1.13 1997/05/28 01:46:35 newt
* Added support for the XmNbodyImage resource: it's now used but only if no
* bgcolor resource has been set.
*
* Revision 1.12 1997/04/29 14:26:18 newt
* HTML forms changes
*
* Revision 1.11 1997/04/03 05:34:25 newt
* _XmHTMLLoadBodyImage added.
* Placed a large number of warnings between a #ifdef PEDANTIC/#endif
*
* Revision 1.10 1997/03/28 07:12:43 newt
* Fixed buffer overrun in TexToPre.
* Fixed font resolution: x and y resolution are now always equal.
* XmHTML now ignores the ending body tag.
*
* Revision 1.9 1997/03/20 08:10:04 newt
* Split font cache in a true cache and a font stack.
* Added stack checks when document has been formatted.
*
* Revision 1.8 1997/03/11 19:52:17 newt
* added ImageToWord
*
* Revision 1.7 1997/03/04 00:59:26 newt
* ?
*
* Revision 1.6 1997/03/02 23:17:46 newt
* Way too many changes. Most important: font loading/switching scheme; anchor
* treatment; image/imagemap treatment
*
* Revision 1.5 1997/02/11 02:08:44 newt
* Way to many. Anchor treatment has been changed completely.
* Bugfixes in anchor parsing. Potential buffer overruns eliminated.
*
* Revision 1.4 1997/02/04 02:56:49 newt
* Bugfix in LoadQueryFont.
* Added code to deal with the basefont element.
* Changed the font element handling.
*
* Revision 1.3 1997/01/09 06:55:39 newt
* expanded copyright marker
*
* Revision 1.2 1997/01/09 06:44:42 newt
* lots of changes: linebreaking and changes related to changed XmHTMLWord
*
* Revision 1.1 1996/12/19 02:17:10 newt
* Initial Revision
*
*****/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include /* isspace, tolower */
/* Local includes */
#include "XmHTMLP.h"
#include "XmHTMLfuncs.h"
/*** External Function Prototype Declarations ***/
/*** Public Variable Declarations ***/
/*** Private Datatype Declarations ****/
#define MAX_NESTED_LISTS 26 /* maximum no of nested lists */
#define IDENT_SPACES 3 /* length of each indent, in no of spaces */
typedef struct{
String name;
Marker type; /* Marker is an enumeration type defined in XmHTMLP.h */
}listMarkers;
/* for nesting of ordered and unordered lists */
typedef struct{
Boolean isindex; /* propagate index numbers? */
int level; /* item number */
htmlEnum type; /* ol or ul, used for custom markers */
Marker marker; /* marker to use */
}listStack;
/* for nesting of colors */
typedef struct colorRec{
unsigned long color;
struct colorRec *next;
}colorStack;
typedef struct fontRec{
int size;
XmHTMLfont *font; /* ptr to cached font */
struct fontRec *next;
}fontStack;
/* for nesting of alignments */
typedef struct alignRec{
Alignment align;
struct alignRec *next;
}alignStack;
/*** Private Function Prototype Declarations ****/
/****
* Formatting routines
*****/
/* Created a new element for the formatted element table */
static XmHTMLObjectTableElement NewTableElement(XmHTMLObject *data);
/* Insert and element into the formatted element table */
static void InsertTableElement(XmHTMLWidget html,
XmHTMLObjectTableElement element, Boolean is_anchor);
/* Release the formatted element table */
static void FreeObjectTable(XmHTMLObjectTable *list);
/* Free the given list of tables */
static void freeTables(XmHTMLTable *table);
/* Initialize the formatted element table */
static void InitObjectTable(XmHTMLObjectTable *list, XmHTMLAnchor *anchors);
/* push/pop a font on font stack */
static void PushFont(XmHTMLfont *font, int size);
static XmHTMLfont *PopFont(int *size);
/* copy given text into an internal buffer */
static String CopyText(XmHTMLWidget html, String text, Boolean formatted,
Byte *text_data, Boolean expand_escapes);
/* collapse all consecutive whitespace into a single space */
static void CollapseWhiteSpace(String text);
/* Split raw text into an array of words */
static XmHTMLWord* TextToWords(String text, int *num_words, Dimension *height,
XmHTMLfont *font, Byte line_data, Byte text_data,
XmHTMLObjectTableElement owner);
/* Split an image into an array of words ;-) */
static XmHTMLWord *ImageToWord(XmHTMLWidget html, String attributes,
int *num_words, Dimension *height, XmHTMLObjectTableElement owner,
Boolean formatted);
static XmHTMLWord *allocFormWord(XmHTMLForm *form, Dimension *width,
Dimension *height, XmHTMLObjectTableElement owner, Boolean formatted);
static XmHTMLWord *InputToWord(XmHTMLWidget html, String attributes,
int *num_words, Dimension *width, Dimension *height,
XmHTMLObjectTableElement owner, Boolean formatted);
static XmHTMLWord *SelectToWord(XmHTMLWidget html, XmHTMLObject *start,
int *num_words, Dimension *width, Dimension *height,
XmHTMLObjectTableElement owner, Boolean formatted);
static XmHTMLWord *TextAreaToWord(XmHTMLWidget html, XmHTMLObject *start,
int *num_words, Dimension *width, Dimension *height,
XmHTMLObjectTableElement owner, Boolean formatted);
static XmHTMLWord *BreakToWord(Dimension *height, XmHTMLfont *font,
int linefeed, XmHTMLObjectTableElement owner);
static XmHTMLWord *MakeDummyWord(Dimension *height, XmHTMLfont *font,
Byte line_data, XmHTMLObjectTableElement owner);
/* Split raw text into a chunk of preformatted lines */
static XmHTMLWord *TextToPre(String text, int *num_words, XmHTMLfont *font,
Byte line_data, XmHTMLObjectTableElement owner);
/* Insert a horizontal tab */
static XmHTMLWord* SetTab(int size, Dimension *height, XmHTMLfont *font,
XmHTMLObjectTableElement owner);
/* Initialize a bullet (a real bullet or some number) */
static void FillBullet(XmHTMLWidget html, XmHTMLObjectTableElement owner);
/* get properties of a table element */
static TableProperties *tableCheckProperties(XmHTMLWidget html,
String attributes, TableProperties *parent, Alignment halign, Pixel bg);
/* open a new table */
static XmHTMLTable *tableOpen(XmHTMLWidget html, XmHTMLTable *parent,
XmHTMLObjectTableElement start, XmHTMLObject *obj, Alignment *halign,
Pixel *bg);
/* close the current table */
static XmHTMLTable *tableClose(XmHTMLWidget html, XmHTMLTable *parent,
XmHTMLObjectTableElement end);
/* open a caption in the current table */
static void tableOpenCaption(XmHTMLWidget html, XmHTMLTable *parent,
XmHTMLObjectTableElement start, XmHTMLObject *obj,
Pixel *bg);
/* close the current caption */
static void tableCloseCaption(XmHTMLWidget html, XmHTMLTable *parent,
XmHTMLObjectTableElement end);
/* open a row in the current table */
static void tableOpenRow(XmHTMLWidget html, XmHTMLTable *parent,
XmHTMLObjectTableElement start, XmHTMLObject *obj, Alignment *halign,
Pixel *bg);
/* close the current row */
static void tableCloseRow(XmHTMLWidget html, XmHTMLTable *parent,
XmHTMLObjectTableElement end);
/* open a cell in the current row */
static void tableOpenCell(XmHTMLWidget html, XmHTMLTable *parent,
XmHTMLObjectTableElement start, XmHTMLObject *obj, Alignment *halign,
Pixel *bg);
/* close the current cell in the current row */
static void tableCloseCell(XmHTMLWidget html, XmHTMLTable *parent,
XmHTMLObjectTableElement end);
/* Parse body tags and update the TWidget */
static void ParseBodyTags(XmHTMLWidget html, XmHTMLObject *data);
/* Check whether a linefeed is required or not */
static int CheckLineFeed(int this, Boolean force);
/* push/pop a color on the color stack */
static void PushFGColor(Pixel color);
static void PushBGColor(Pixel color);
static Pixel PopFGColor(void);
static Pixel PopBGColor(void);
/* push/pop an alignment on/from the alignment stack */
static void PushAlignment(Alignment align);
static Alignment PopAlignment(void);
/* split the given anchor spec into a href, target and other stuff */
static void parseHref(String text, XmHTMLAnchor *anchor);
/*** Private Variable Declarations ***/
/* Element data bits */
#define ELE_ANCHOR (1<<1)
#define ELE_ANCHOR_TARGET (1<<2)
#define ELE_ANCHOR_VISITED (1<<3)
#define ELE_ANCHOR_INTERN (1<<4)
#define ELE_UNDERLINE (1<<5)
#define ELE_UNDERLINE_TEXT (1<<6)
#define ELE_STRIKEOUT (1<<7)
#define ELE_STRIKEOUT_TEXT (1<<8)
/* Private formatted element table data */
static struct{
unsigned long num_elements;
unsigned long num_anchors;
XmHTMLObjectTableElement head;
XmHTMLObjectTableElement current;
XmHTMLAnchor *anchor_head;
XmHTMLAnchor *anchor_current;
}list_data;
/* color and alignment stacks */
static colorStack fg_color_base, *fg_color_stack;
static colorStack bg_color_base, *bg_color_stack;
static alignStack align_base, *align_stack;
static fontStack font_base, *font_stack;
/* Marker information for HTML lists, ordered list. */
#define OL_ARRAYSIZE 5
static listMarkers ol_markers[OL_ARRAYSIZE] = {
{"1", XmMARKER_ARABIC},
{"a", XmMARKER_ALPHA_LOWER},
{"A", XmMARKER_ALPHA_UPPER},
{"i", XmMARKER_ROMAN_LOWER},
{"I", XmMARKER_ROMAN_UPPER},
};
/* Unordered list. */
#define UL_ARRAYSIZE 3
static listMarkers ul_markers[UL_ARRAYSIZE] = {
{"disc", XmMARKER_DISC},
{"square", XmMARKER_SQUARE},
{"circle", XmMARKER_CIRCLE},
};
#ifdef DEBUG
static int allocated;
#endif
/*****
* Name: NewTableElement
* Return Type: XmHTMLObjectTableElement
* Description: creates a ObjectTableElement and fills it.
* In:
* data: raw data for this element.
* Returns:
* the newly created element.
*****/
static XmHTMLObjectTableElement
NewTableElement(XmHTMLObject *data)
{
static XmHTMLObjectTableElement element = NULL;
element = (XmHTMLObjectTableElement)malloc(sizeof(XmHTMLObjectTable));
/* initialise to zero */
(void)memset(element, 0, sizeof(XmHTMLObjectTable));
/* fill in appropriate fields */
element->object = data;
#ifdef DEBUG
allocated++;
#endif
return(element);
}
/*****
* Name: InsertTableElement
* Return Type: void
* Description: inserts a given formatted element in the list of elements.
* In:
* w: XmHTMLWidget to which this element belongs.
* element: element to add
* is_anchor: true if this element is an anchor.
* Returns:
* nothing.
*****/
static void
InsertTableElement(XmHTMLWidget html, XmHTMLObjectTableElement element,
Boolean is_anchor)
{
/* attach prev and next ptrs to the appropriate places */
element->prev = list_data.current;
list_data.current->next = element;
list_data.current = element;
/* increment element counter */
list_data.num_elements++;
#ifdef DEBUG
if(is_anchor)
list_data.num_anchors++;
#endif
}
/*****
* Name: parseHref
* Return Type: void
* Description: returns the url specification found in the given anchor.
* In:
* text: full anchor spec.
* href: url found in given anchor. Filled upon return.
* target: any target attribute found. Filled upon return.
* extra: any additional attributes found. Filled upon return.
* Returns:
* nothing.
*****/
static void
parseHref(String text, XmHTMLAnchor *anchor)
{
if(text == NULL ||
(anchor->href = _XmHTMLTagGetValue(text, "href")) == NULL)
{
/* allocate empty href field so later strcmps won't explode */
anchor->href = (char *)malloc(1);
anchor->href[0] = '\0'; /* fix 02/03/97-05, kdh */
/*
* Could be a named anchor with a target spec. Rather impossible but
* allow for it anyway (I can imagine this to be true for a
* split-screen display).
*/
if(text == NULL)
return;
}
/* Check if there is a target specification */
anchor->target= _XmHTMLTagGetValue(text, "target");
/* Also check for rel, rev and title */
anchor->rel = _XmHTMLTagGetValue(text, "rel");
anchor->rev = _XmHTMLTagGetValue(text, "rev");
anchor->title = _XmHTMLTagGetValue(text, "title");
}
/*****
* Name: FreeObjectTable
* Return Type: void
* Description: releases all memory occupied by the formatted list of elements.
* In:
* list: previous list to be released.
* Returns:
* nothing.
* Note:
* Images are freed in XmHTML.c, which calls XmHTMLFreeAllImages to do the
* job.
*****/
static void
FreeObjectTable(XmHTMLObjectTable *list)
{
XmHTMLObjectTableElement temp;
#ifdef DEBUG
int i = 0, j = 0;
#endif
/* free all parsed objects */
while(list != NULL)
{
temp = list->next;
if(list->text) /* space occupied by text to display */
free(list->text);
/* free list of words. Can't be done above,
doesn't have this! */
if(list->n_words)
{
/*
* only the first word contains a valid ptr, all others point to
* some char in this buffer, so freeing them *will* cause a
* segmentation fault eventually.
*/
free(list->words[0].word);
/* Free raw word data */
free(list->words);
}
free(list);
list = temp;
#ifdef DEBUG
i++;
#endif
}
_XmHTMLDebug(2, ("format.c: FreeObjectTable End, freed %i elements and "
"%i anchors.\n", i, j));
}
/*****
* Name: freeTables
* Return Type: void
* Description: frees all data allocated for HTML table support.
* In:
* table: list of tables to be freed.
* Returns:
* nothing.
*****/
static void
freeTables(XmHTMLTable *table)
{
XmHTMLTable *tab, *tmp = table;
TableRow *row;
int i, j, k;
while(table)
{
tmp = table->next;
/*****
* Free all child tables (first table in the childs array is the
* table itself)
*****/
for(i = 0; i < table->nchilds; i++)
{
tab = &table->childs[i];
/* free all rows */
for(j = 0; j < tab->nrows; j++)
{
row = &tab->rows[j];
/* free all cells in this row */
for(k = 0; k < row->ncells; k++)
{
free(row->cells[k].properties);
}
free(row->cells);
free(row->properties);
}
free(tab->rows);
free(tab->properties);
}
free(table->childs);
free(table);
table = tmp;
}
}
/*****
* Name: FreeAnchors
* Return Type: void
* Description: frees the memory occupied by the anchor data
* In:
* anchors: list of anchors to be freed
* Returns:
* nothing.
*****/
static void
FreeAnchors(XmHTMLAnchor *anchors)
{
XmHTMLAnchor *tmp;
int i = 0;
while(anchors)
{
tmp = anchors->next;
/* href field is always allocated */
free(anchors->href);
if(anchors->target)
free(anchors->target);
if(anchors->rel)
free(anchors->rel);
if(anchors->rev)
free(anchors->rev);
if(anchors->title)
free(anchors->title);
if(anchors->name) /* fix 07/09/97-01, kdh */
free(anchors->name);
if(anchors->events)
free(anchors->events);
free(anchors);
anchors = NULL;
anchors = tmp;
i++;
}
_XmHTMLDebug(2, ("format.c: FreeAnchors, freed %i XmHTMLAnchor objects\n",
i));
}
/*****
* Name: InitObjectTable
* Return Type: void
* Description: initializes the list of formatted elements.
* In:
* list: previous list to be released.
* Returns:
* nothing
* Note:
* The list head is a dummy element and is never used. It is done to gain
* some performance (a test on an empty head is not required now in the
* InsertTableElement routine).
*****/
static void
InitObjectTable(XmHTMLObjectTable *list, XmHTMLAnchor *anchors)
{
if(list != NULL)
{
FreeObjectTable(list);
list = NULL;
}
if(anchors != NULL)
{
FreeAnchors(anchors);
anchors = NULL;
}
if(list_data.head)
free(list_data.head);
list_data.head = NewTableElement(NULL);
list_data.current = list_data.head;
list_data.anchor_head = (XmHTMLAnchor*)NULL;
list_data.anchor_current = (XmHTMLAnchor*)NULL;
list_data.num_elements = 1;
list_data.num_anchors = 0;
}
/*****
* Name: CollapseWhiteSpace
* Return Type: void
* Description: collapses whitespace in the given text
* In:
* text: text for which multiple whitespace has to be collapsed.
* Returns:
* nothing, but text is updated when this function returns.
*****/
static void
CollapseWhiteSpace(String text)
{
register char *outPtr = text;
/*
* We only collapse valid text and text that contains more than whitespace
* only. This should never be true since CopyText will filter these
* things out. It's just here for sanity.
*/
if(*text == '\0' || !strlen(text))
return;
_XmHTMLDebug(2, ("format.c: CollapseWhiteSpace, text in is:\n%s\n", text));
/*
* Now collapse each occurance of multiple whitespaces.
* This may produce different results on different systems since
* isspace() might not produce the same on each and every platform.
*/
while(True)
{
switch(*text)
{
case '\f':
case '\n':
case '\r':
case '\t':
case '\v':
*text = ' '; /* replace by a single space */
/* fall through */
case ' ':
/* skip past first space */
*(outPtr++) = *(text++);
/* collapse every space following */
while(*text != '\0' && isspace(*text))
*text++ = '\0';
break;
default:
*(outPtr++) = *(text++);
break;
}
if(*text == 0)
{
*outPtr = '\0';
return;
}
}
}
/*****
* Name: TextToWords
* Return Type: XmHTMLWord*
* Description: splits the given text into an array of words.
* In:
* text: text to split
* num_words: number of words in the given text. Filled upon return;
* font: font to use for this text.
* Returns:
* an array of words. When allocation fails, this routine exits.
*****/
static XmHTMLWord*
TextToWords(String text, int *num_words, Dimension *height, XmHTMLfont *font,
Byte line_data, Byte text_data, XmHTMLObjectTableElement owner)
{
int n_words, len, i;
char *start;
static XmHTMLWord *words;
static char *raw;
register int j;
register char *chPtr;
/* sanity check */
if(text == NULL)
{
*height = *num_words = 0;
return(NULL);
}
_XmHTMLFullDebug(2, ("format.c: TextToWords, text in is:\n%s\n", text));
/* compute how many words we have */
n_words = 0;
for(chPtr = text; *chPtr != '\0'; chPtr++)
if(*chPtr == ' ')
n_words++;
/* also pick up the last word */
n_words++;
/* copy text */
raw = strdup(text);
/* allocate memory for all words */
words = (XmHTMLWord*)calloc(n_words, sizeof(XmHTMLWord));
/* Split the text in words and fill in the appropriate fields */
*height = font->height;
chPtr = start = raw;
for(i = 0, j = 0, len = 0; ; chPtr++, len++, j++)
{
/* also pick up the last word! */
if(*chPtr == ' ' || *chPtr == '\0')
{
if(*chPtr)
{
chPtr++; /* nuke the space */
raw[j++] = '\0';
}
/* fill in required fields */
words[i].self = &words[i];
words[i].word = start;
words[i].len = len;
words[i].height = *height;
words[i].width = Toolkit_Text_Width(font->xfont, words[i].word, len);
words[i].owner = owner;
words[i].font = font;
words[i].spacing = TEXT_SPACE_LEAD | TEXT_SPACE_TRAIL;
words[i].type = OBJ_TEXT;
words[i].line_data = line_data;
_XmHTMLFullDebug(2, ("format.c: TextToWords, word is %s, len is "
"%i, width is %i, height is %i\n", words[i].word, words[i].len,
words[i].width, words[i].height));
start = chPtr;
i++;
len = 0;
}
if(*chPtr == '\0')
break;
}
/*
* when there is more than one word in this block, the first word
* _always_ has a trailing space.
* Likewise, the last word always has a leading space.
*/
if(n_words > 1)
{
/* unset nospace bit */
Byte spacing = text_data & ~TEXT_SPACE_NONE;
words[0].spacing = spacing | TEXT_SPACE_TRAIL;
words[n_words-1].spacing = spacing | TEXT_SPACE_LEAD;
}
else
words[0].spacing = text_data;
_XmHTMLFullDebug(2, ("format.c: TextToWords counted %i words\n", n_words));
*num_words = i; /* n_words */;
return(words);
}
/*****
* Name: ImageToWord
* Return Type: XmHTMLWord*
* Description: converts an image to a word
* In:
* w: XmHTMLWidget id
* attributes: raw specification
* height: object height, updated upon return
* owner: owning object
* formatted: True when this image is part of a block of text.
* Returns:
* a word representing the image
*****/
static XmHTMLWord*
ImageToWord(XmHTMLWidget html, String attributes, int *num_words,
Dimension *height, XmHTMLObjectTableElement owner, Boolean formatted)
{
static XmHTMLWord *word;
static XmHTMLImage *image;
Dimension width = 0;
*num_words = 0;
/* sanity check */
if(attributes == NULL ||
(image = _XmHTMLNewImage(html, attributes, &width, height)) == NULL)
{
*height = 0;
return(NULL);
}
_XmHTMLFullDebug(2, ("format.c: ImageToWord, image in is: %s\n",
image->url));
word = (XmHTMLWord*)calloc(1, sizeof(XmHTMLWord));
/* required for image anchoring/replace/update */
image->owner = owner;
/* fill in required fields */
word->self = word;
word->word = strdup(image->alt); /* we always have this */
word->len = strlen(image->alt);
word->width = width + 2*image->hspace + 2*image->border;
word->height = *height + 2*image->vspace + 2*image->border;
word->owner = owner;
word->font = font_base.font; /* always use the default font */
/*****
* if image support is disabled, add width of the alt text to the
* image width (either from default image or specified in the doc).
* This is required for proper exposure handling when images are disabled.
*****/
if(!html->html.images_enabled)
word->width += Toolkit_Text_Width(word->font->xfont, word->word, word->len);
/*****
* No spacing if part of a chunk of text
* Fix 07/24/97, kdh
*****/
word->spacing = formatted ? 0 : TEXT_SPACE_LEAD | TEXT_SPACE_TRAIL;
word->type = OBJ_IMG;
word->line_data = NO_LINE; /* no underlining for images */
word->image = image;
_XmHTMLFullDebug(2, ("format.c: TextToWords, word is %s, len is %i, "
"width is %i, height is %i\n", word->word, word->len,
word->width, word->height));
*num_words = 1;
return(word);
}
/*****
* Name: allocFormWord
* Return Type: XmHTMLWord*
* Description: allocates a default XmHTMLWord for use within a HTML form.
* In:
* form: form entry for which this word should be allocated;
* *width: object's width, updated upon return;
* *height: object's height, updated upon return;
* owner: owning object.
* formatted: true when allocating a form component present in
* Returns:
* a newly allocated word.
*****/
static XmHTMLWord*
allocFormWord(XmHTMLForm *form, Dimension *width, Dimension *height,
XmHTMLObjectTableElement owner, Boolean formatted)
{
static XmHTMLWord *word;
/* allocate new entry */
word = (XmHTMLWord*)calloc(1, sizeof(XmHTMLWord));
/* fill in required fields */
word->self = word;
word->word = strdup(form->name); /* we always have this */
word->len = strlen(form->name);
word->height = *height = form->height;
word->width = *width = form->width;
word->owner = owner;
word->font = font_base.font; /* always use default font */
word->spacing = formatted ? 0 : TEXT_SPACE_LEAD | TEXT_SPACE_TRAIL;
word->type = OBJ_FORM;
word->form = form;
return(word);
}
/*****
* Name: InputToWord
* Return Type: XmHTMLWord*
* Description: converts a HTML form element to a word
* In:
* w: XmHTMLWidget id
* attributes: raw form element specification
* width: object width, updated upon return
* height: object height, updated upon return
* owner: owning object
* formatted: true when this form component is placed in a tag.
* Returns:
* a word representing the image
*****/
static XmHTMLWord*
InputToWord(XmHTMLWidget html, String attributes, int *num_words,
Dimension *width, Dimension *height, XmHTMLObjectTableElement owner,
Boolean formatted)
{
static XmHTMLForm *form_entry;
XmHTMLWord *word;
*num_words = 0;
/* sanity check */
if(attributes == NULL ||
(form_entry = _XmHTMLFormAddInput(html, attributes)) == NULL)
return(NULL);
/* save owner, we need it in the paint routines */
form_entry->data = owner;
/* image buttons are treated as anchored images */
if(form_entry->type == FORM_IMAGE)
{
word = ImageToWord(html, attributes, num_words, height, owner,
formatted);
/* remove alt text */
free(word->word);
/* use form member name instead */
word->word = strdup(form_entry->name);
word->len = strlen(form_entry->name);
word->form = form_entry;
_XmHTMLFullDebug(2, ("format.c: InputToWord, word is %s, len is %i, "
"width is %i, height is %i (type = image)\n", word->word,
word->len, word->width, word->height));
return(word);
}
/* allocate new word for this form member */
word = allocFormWord(form_entry, width, height, owner, formatted);
_XmHTMLFullDebug(2, ("format.c: InputToWord, word is %s, len is %i, "
"width is %i, height is %i\n", word->word, word->len,
word->width, word->height));
*num_words = 1;
return(word);
}
/*****
* Name: SelectToWord
* Return Type: XmHTMLWord*
* Description: converts a HTML form to a HTMLWord.
* Also processes any items within this select.
* In:
* html: XmHTMLWidget id;
* start: object at which