2010-03-08 04:55:21 -06:00
|
|
|
#include "../config.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include "HTMLP.h"
|
|
|
|
#include "HTML.h"
|
|
|
|
#include "list.h"
|
|
|
|
#ifdef VAXC
|
|
|
|
#include <ctype.h>
|
|
|
|
#endif /* VAXC, need for isspace, GEC */
|
|
|
|
|
|
|
|
#define DEFAULT_FIELD_WIDTH 30
|
|
|
|
#define DEFAULT_FIELD_HEIGHT 20
|
|
|
|
|
|
|
|
#define FIELD_BORDER_SPACE 5 /*aesthetic space around element */
|
|
|
|
|
|
|
|
#define FONTHEIGHT(font) (font->max_bounds.ascent + font->max_bounds.descent)
|
|
|
|
|
|
|
|
extern char *ParseMarkTag();
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
extern int htmlwTrace;
|
|
|
|
#endif
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
/* Allocate a TableField and initialize to default values
|
|
|
|
* return 0 on failure
|
2010-03-08 04:55:21 -06:00
|
|
|
*/
|
|
|
|
static TableField *NewTableField()
|
|
|
|
{
|
|
|
|
TableField *tf;
|
|
|
|
|
|
|
|
if (!(tf = (TableField *) malloc(sizeof(TableField)))) {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
tf->alignment = ALIGN_CENTER;
|
|
|
|
tf->colSpan = 1;
|
|
|
|
tf->rowSpan = 1;
|
|
|
|
tf->contVert = False;
|
|
|
|
tf->contHoriz = False;
|
|
|
|
tf->maxWidth = DEFAULT_FIELD_WIDTH;
|
|
|
|
tf->minWidth = DEFAULT_FIELD_WIDTH;
|
2013-03-09 18:59:42 -06:00
|
|
|
tf->maxHeight = DEFAULT_FIELD_HEIGHT;
|
2010-03-08 04:55:21 -06:00
|
|
|
tf->minHeight = DEFAULT_FIELD_HEIGHT;
|
|
|
|
tf->header = False;
|
|
|
|
|
|
|
|
tf->type = F_NONE;
|
|
|
|
tf->text = (char *) 0;
|
|
|
|
tf->font = (XFontStruct *) 0;
|
|
|
|
tf->formattedText = (char **) 0;
|
|
|
|
tf->numLines = 0;
|
|
|
|
|
|
|
|
tf->image = (ImageInfo *) 0;
|
|
|
|
tf->winfo = (WidgetInfo *) 0;
|
|
|
|
|
|
|
|
return(tf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* return a word out of the text */
|
|
|
|
void GetWord(text,retStart,retEnd)
|
|
|
|
char *text; /* text to get a word out of */
|
|
|
|
char **retStart; /* RETURNED: start of word in text */
|
|
|
|
char **retEnd; /* RETURNED: end of word in text */
|
|
|
|
{
|
|
|
|
char *start;
|
|
|
|
char *end;
|
|
|
|
|
|
|
|
if (!text) {
|
|
|
|
*retStart = *retEnd = text;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = text;
|
|
|
|
while ((*start) && isspace(*start)){ /*skip over leading space*/
|
|
|
|
start++;
|
|
|
|
}
|
|
|
|
|
|
|
|
end = start;
|
|
|
|
while((*end) && (!isspace(*end))){ /* find next space */
|
|
|
|
end++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*retStart = start;
|
|
|
|
*retEnd = end;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
/* PourText() this routine pours a text string of a particular font into a
|
|
|
|
rectangular area of specified dimensions. The return value is a list of
|
2010-03-08 04:55:21 -06:00
|
|
|
text lines that will fit within the given width.
|
|
|
|
If a height is specified, then text will be truncated if necessary to fit.
|
2013-03-09 18:59:42 -06:00
|
|
|
If height is 0, then all of the text is in the list.
|
2010-03-08 04:55:21 -06:00
|
|
|
The actual pixel height of the text is returned in variable height.
|
|
|
|
*/
|
|
|
|
int PourText(text,font,width,height,percentVertSpace,formattedText,numberOfLines)
|
|
|
|
char *text; /* assumed that text is already clean and without newlines */
|
|
|
|
XFontStruct *font;
|
|
|
|
int width; /* width of area to pour text */
|
|
|
|
int *height; /* if passed height value is zero, then height is returned */
|
|
|
|
/* if passed height is non zero, then truncate to this height */
|
|
|
|
int percentVertSpace; /* likely hw->html.percent_vert_space */
|
|
|
|
/* needed to compute height of text */
|
|
|
|
char ***formattedText; /* RETURNED: array of text lines */
|
|
|
|
int *numberOfLines; /* RETURNED: number of lines */
|
|
|
|
{
|
|
|
|
int fontHeight;
|
|
|
|
int stringWidth;
|
|
|
|
int builtWidth;
|
|
|
|
char *textPtr;
|
|
|
|
char *wordStart,*wordEnd;
|
|
|
|
int wordWidth; /* in pixels */
|
|
|
|
int wordLength; /* in chars */
|
|
|
|
List textList; /* returned list of text lines */
|
|
|
|
char tmpBuff[5120]; /*ACK!, can't have more than 5k chars on a line in a field*/
|
|
|
|
int spaceWidth; /* width of a space in this font */
|
|
|
|
char **cTextList;
|
|
|
|
int numLines;
|
|
|
|
int y;
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
fprintf(stderr,"PourText: \"%s\" width=%d,height=%d\n",text,width,height);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!text) {
|
|
|
|
*height = 0;
|
|
|
|
*formattedText = (char **) 0;
|
|
|
|
*numberOfLines = 0;
|
|
|
|
return(0);
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
textList = ListCreate();
|
|
|
|
stringWidth = XTextWidth(font,text,strlen(text));
|
|
|
|
if (stringWidth < width) {
|
|
|
|
ListAddEntry(textList,strdup(text));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
builtWidth = 0;
|
|
|
|
textPtr = text;
|
|
|
|
spaceWidth = XTextWidth(font," ",1);
|
|
|
|
*tmpBuff = '\0';
|
|
|
|
while (*textPtr) {
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
printf("textPtr = \"%s\"\n",textPtr);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
GetWord(textPtr,&wordStart,&wordEnd);
|
|
|
|
wordLength = (int) (wordEnd - wordStart);
|
|
|
|
wordWidth = XTextWidth(font,wordStart, wordLength);
|
2013-03-09 18:59:42 -06:00
|
|
|
if ((builtWidth + spaceWidth + wordWidth) < width) {
|
2010-03-08 04:55:21 -06:00
|
|
|
/* then add to line */
|
|
|
|
if (builtWidth) {
|
|
|
|
/* only add space if something on line already*/
|
|
|
|
strcat(tmpBuff, " ");
|
|
|
|
builtWidth += spaceWidth;
|
|
|
|
}
|
|
|
|
strncat(tmpBuff, wordStart, wordLength);
|
|
|
|
builtWidth += wordWidth;
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
else if (wordWidth < width) {
|
2010-03-08 04:55:21 -06:00
|
|
|
/* start new line */
|
|
|
|
ListAddEntry(textList, strdup(tmpBuff));
|
|
|
|
*tmpBuff = '\0';
|
|
|
|
builtWidth = 0;
|
|
|
|
|
|
|
|
/* and add it to the line */
|
|
|
|
strncat(tmpBuff, wordStart, wordLength);
|
|
|
|
builtWidth += wordWidth;
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
else {
|
2010-03-08 04:55:21 -06:00
|
|
|
/* word is too big to fit on a line */
|
|
|
|
/* so break up word */
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* start new line */
|
|
|
|
ListAddEntry(textList, strdup(tmpBuff));
|
|
|
|
*tmpBuff = '\0';
|
|
|
|
builtWidth = 0;
|
|
|
|
|
|
|
|
/* find the max that will fit on a line*/
|
|
|
|
wordWidth = 0;
|
|
|
|
wordLength = 0;
|
|
|
|
wordEnd = wordStart;
|
|
|
|
while ((*wordEnd) && (width > wordWidth)) {
|
|
|
|
wordEnd++;
|
|
|
|
wordLength = (int) (wordEnd - wordStart);
|
2013-03-09 18:59:42 -06:00
|
|
|
wordWidth = XTextWidth(font,wordStart,
|
2010-03-08 04:55:21 -06:00
|
|
|
wordLength);
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
strncat(tmpBuff, wordStart, wordLength);
|
|
|
|
builtWidth += wordWidth;
|
|
|
|
|
|
|
|
}
|
|
|
|
textPtr = wordEnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*tmpBuff) {
|
|
|
|
ListAddEntry(textList, strdup(tmpBuff));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ok, we haven't paid attention to height, so now we are going
|
|
|
|
to remove placed lines that don't fit */
|
|
|
|
|
|
|
|
fontHeight = FONTHEIGHT(font);
|
|
|
|
fontHeight += (fontHeight * (percentVertSpace/100));
|
|
|
|
if (*height) {
|
|
|
|
/* truncate list to specified height */
|
|
|
|
while ((ListCount(textList) * fontHeight) > (*height)) {
|
|
|
|
ListDeleteEntry(textList, ListTail(textList));
|
|
|
|
}
|
|
|
|
*height = ListCount(textList) * fontHeight;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* return the height */
|
|
|
|
*height = ListCount(textList) * fontHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* turn text list into an array */
|
|
|
|
numLines = ListCount(textList);
|
|
|
|
if (!(cTextList = (char **) malloc(sizeof(char *)* numLines))) {
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
fprintf(stderr,"Out of Memory\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
*formattedText = (char **) 0;
|
|
|
|
*numberOfLines = 0;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
for (y = 0; y < numLines; y++) {
|
|
|
|
cTextList[y] = ListHead(textList);
|
|
|
|
(void) ListDeleteEntry(textList,cTextList[y]);
|
|
|
|
}
|
|
|
|
ListDestroy(textList);
|
|
|
|
*formattedText = cTextList;
|
|
|
|
*numberOfLines = numLines;
|
|
|
|
|
|
|
|
return(numLines);
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
} /* PourText() */
|
|
|
|
|
|
|
|
|
|
|
|
/* print out the table to stdout */
|
|
|
|
TableDump(t)
|
|
|
|
TableInfo *t;
|
|
|
|
{
|
|
|
|
register int x,y;
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
|
|
|
|
fprintf(stderr,"Table dump:\n");
|
|
|
|
fprintf(stderr,"Border width is %d\n",t->borders);
|
|
|
|
fprintf(stderr,"numColumns=%d, numRows=%d\n",t->numColumns,t->numRows);
|
|
|
|
fprintf(stderr,"---------------------------------------------------\n");
|
|
|
|
for (y = 0; y < t->numRows; y++ ) {
|
|
|
|
fprintf(stderr,"|");
|
|
|
|
for (x = 0; x < t->numColumns; x++ ) {
|
|
|
|
fprintf(stderr,"colWidth=%d,rowHeight=%d | ",
|
|
|
|
t->table[y * t->numColumns + x].colWidth,
|
|
|
|
t->table[y * t->numColumns + x].rowHeight);
|
|
|
|
}
|
|
|
|
fprintf(stderr,"\n---------------------------------------------------\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fill out uneven rows in table */
|
|
|
|
/* return 0 on out of memory, 1 on suceess */
|
|
|
|
static int TableCleanUp(t,tableList)
|
|
|
|
TableInfo *t;
|
|
|
|
List tableList;
|
|
|
|
{
|
|
|
|
int maxNumCols;
|
|
|
|
int numColsInRow;
|
|
|
|
List rowList;
|
|
|
|
TableField *field;
|
|
|
|
int x,y;
|
|
|
|
|
|
|
|
/* determine number of columns all rows should have */
|
|
|
|
rowList = (List) ListHead(tableList);
|
|
|
|
t->numRows = 0;
|
|
|
|
maxNumCols = 0;
|
|
|
|
while(rowList) {
|
|
|
|
field = (TableField *) ListHead(rowList);
|
|
|
|
numColsInRow = 0;
|
|
|
|
while (field) {
|
|
|
|
numColsInRow++;
|
|
|
|
field = (TableField *) ListNext(rowList);
|
|
|
|
}
|
|
|
|
maxNumCols=(maxNumCols > numColsInRow)?maxNumCols:numColsInRow;
|
|
|
|
t->numRows++;
|
|
|
|
rowList = (List) ListNext(tableList);
|
|
|
|
}
|
|
|
|
|
|
|
|
t->numColumns = maxNumCols;
|
|
|
|
|
|
|
|
|
|
|
|
/* make all rows have correct number of columns */
|
|
|
|
rowList = (List) ListHead(tableList);
|
|
|
|
while(rowList) {
|
|
|
|
numColsInRow = 0;
|
|
|
|
field = (TableField *) ListHead(rowList);
|
|
|
|
numColsInRow = 0;
|
|
|
|
while (field) {
|
|
|
|
numColsInRow++;
|
|
|
|
field = (TableField *) ListNext(rowList);
|
|
|
|
}
|
|
|
|
|
|
|
|
while(numColsInRow < t->numColumns) {
|
|
|
|
/* fill up the table with empty fields */
|
|
|
|
if (!(field = NewTableField())) {
|
|
|
|
return(0); /* out of memory */
|
|
|
|
}
|
|
|
|
ListAddEntry(rowList,field);
|
|
|
|
numColsInRow++;
|
|
|
|
}
|
|
|
|
rowList = (List) ListNext(tableList);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* move 2D link list table to an array for speed */
|
2013-03-09 18:59:42 -06:00
|
|
|
if (!(t->table = (TableField *) malloc(sizeof(TableField)
|
2010-03-08 04:55:21 -06:00
|
|
|
* t->numColumns * t->numRows))) {
|
|
|
|
return(0); /* out of memory */
|
|
|
|
}
|
|
|
|
y=0;
|
|
|
|
rowList = (List) ListHead(tableList);
|
|
|
|
while(rowList) {
|
|
|
|
x = 0;
|
|
|
|
field = (TableField *) ListHead(rowList);
|
|
|
|
while (field) {
|
2013-03-09 18:59:42 -06:00
|
|
|
memcpy(&(t->table[y * t->numColumns + x]), field,
|
2010-03-08 04:55:21 -06:00
|
|
|
sizeof(TableField));
|
|
|
|
x++;
|
|
|
|
field = (TableField *) ListNext(rowList);
|
|
|
|
}
|
|
|
|
y++;
|
|
|
|
rowList = (List) ListNext(tableList);
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
|
|
|
|
return(1);
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* return the number of connected fields */
|
|
|
|
static int TableHowManyConnectedHorizFields(t,xpos,ypos)
|
|
|
|
TableInfo *t;
|
|
|
|
int xpos,ypos;
|
|
|
|
{
|
|
|
|
int count;
|
|
|
|
register int x;
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
for (x = xpos+1; x < t->numColumns; x++) {
|
|
|
|
if (t->table[ypos * t->numColumns + x].contHoriz) {
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return(count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(count);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return the number of connected fields */
|
|
|
|
static int TableHowManyConnectedVertFields(t,xpos,ypos)
|
|
|
|
TableInfo *t;
|
|
|
|
int xpos,ypos;
|
|
|
|
{
|
|
|
|
int count;
|
|
|
|
register int y;
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
for (y = ypos+1; y < t->numRows; y++) {
|
|
|
|
if (t->table[y * t->numColumns + xpos].contVert) {
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return(count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int CalculateMaxWidthOfColumn(t,x)
|
|
|
|
TableInfo *t;
|
|
|
|
int x;
|
|
|
|
{
|
|
|
|
register int y;
|
|
|
|
register int maxWidth=0;
|
|
|
|
register int width;
|
|
|
|
|
|
|
|
for (y=0; y < t->numRows; y++) {
|
|
|
|
width = t->table[y * t->numColumns+x].maxWidth;
|
|
|
|
maxWidth = (maxWidth > width) ? maxWidth : width;
|
|
|
|
}
|
|
|
|
return(maxWidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
TableCalculateDimensions(hw,t,pageWidth)
|
|
|
|
HTMLWidget hw;
|
|
|
|
TableInfo *t;
|
|
|
|
int pageWidth; /* width in pixels of output page */
|
|
|
|
{
|
|
|
|
TableField *field;
|
|
|
|
register int xx,x,y;
|
|
|
|
int sumMaxWidth; /* summation of max widths */
|
|
|
|
int maxWidthOfColumn;
|
|
|
|
int maxHeightOfRow;
|
|
|
|
int sumMinWidth; /* summation of max widths */
|
|
|
|
int maxWidthOfRow;
|
2013-03-09 18:59:42 -06:00
|
|
|
int minWidthOfRow;
|
2010-03-08 04:55:21 -06:00
|
|
|
int numAdjacent;
|
|
|
|
float percentToShrink;
|
|
|
|
int accumulateColWidth;
|
|
|
|
|
|
|
|
|
|
|
|
/* calculate max and min width for each field*/
|
|
|
|
sumMaxWidth = 0;
|
|
|
|
sumMinWidth = 0;
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
|
|
|
maxWidthOfRow = 0;
|
|
|
|
minWidthOfRow = 0;
|
|
|
|
for (x = 0; x < t->numColumns; x++ ) {
|
|
|
|
|
|
|
|
field = &(t->table[y * t->numColumns + x]);
|
|
|
|
if (field->type == F_TEXT) {
|
|
|
|
field->maxWidth = XTextWidth(field->font,
|
|
|
|
field->text,strlen(field->text));
|
|
|
|
field->minHeight = FONTHEIGHT(field->font);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* non text */
|
|
|
|
field->maxWidth = 0;
|
|
|
|
}
|
|
|
|
maxWidthOfRow += field->maxWidth;
|
|
|
|
|
|
|
|
field->minWidth = 0; /* is minWidth needed? set 0 for now*/
|
|
|
|
field->maxHeight = 0;
|
|
|
|
/* if it's needed, set it to width of one char or maybe
|
|
|
|
length of longest word in text */
|
|
|
|
minWidthOfRow += field->minWidth;
|
|
|
|
}
|
|
|
|
/* save the length of the longest and shortest row */
|
2013-03-09 18:59:42 -06:00
|
|
|
sumMaxWidth = (sumMaxWidth > maxWidthOfRow) ?
|
2010-03-08 04:55:21 -06:00
|
|
|
sumMaxWidth : maxWidthOfRow;
|
2013-03-09 18:59:42 -06:00
|
|
|
sumMinWidth = (sumMinWidth > minWidthOfRow) ?
|
2010-03-08 04:55:21 -06:00
|
|
|
sumMinWidth : minWidthOfRow;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* add border spacing to widths */
|
|
|
|
sumMaxWidth += (t->numColumns * 2 * FIELD_BORDER_SPACE);
|
|
|
|
sumMinWidth += (t->numColumns * 2 * FIELD_BORDER_SPACE);
|
|
|
|
|
|
|
|
|
|
|
|
/* divy up max width with adjacent continue Horizontal fields*/
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
|
|
|
for (x = 0; x < t->numColumns; x++) {
|
|
|
|
numAdjacent = TableHowManyConnectedHorizFields(t,x,y);
|
|
|
|
if (numAdjacent) {
|
|
|
|
int xx;
|
|
|
|
for (xx = x; xx < x + numAdjacent; xx++) {
|
|
|
|
t->table[y * t->numColumns+xx].maxWidth
|
|
|
|
= t->table[y*t->numColumns+x].maxWidth
|
|
|
|
/ (numAdjacent+ 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
x += numAdjacent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* divy up min height with adjacent continue Vertical fields */
|
|
|
|
for (x = 0; x < t->numColumns; x++) {
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
|
|
|
numAdjacent = TableHowManyConnectedVertFields(t,x,y);
|
|
|
|
if (numAdjacent) {
|
|
|
|
int yy;
|
|
|
|
for (yy = y; yy < y + numAdjacent; yy++) {
|
|
|
|
t->table[yy * t->numColumns+x].minHeight
|
|
|
|
= t->table[y*t->numColumns+x].minHeight
|
|
|
|
/ (numAdjacent + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
y += numAdjacent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* fit table to page */
|
|
|
|
if (sumMaxWidth < pageWidth ) {
|
|
|
|
/* fits on the page, set all fields to use max width */
|
|
|
|
|
|
|
|
for (x = 0; x < t->numColumns; x++) {
|
|
|
|
/* find widest field in column */
|
|
|
|
maxWidthOfColumn = 0;
|
|
|
|
for (y = 0; y < t->numRows; y++ ) {
|
2013-03-09 18:59:42 -06:00
|
|
|
maxWidthOfColumn =
|
|
|
|
(maxWidthOfColumn >
|
2010-03-08 04:55:21 -06:00
|
|
|
t->table[y * t->numColumns + x].maxWidth)?
|
2013-03-09 18:59:42 -06:00
|
|
|
maxWidthOfColumn :
|
2010-03-08 04:55:21 -06:00
|
|
|
t->table[y * t->numColumns+x].maxWidth;
|
|
|
|
}
|
|
|
|
/* assign uniform width to column */
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
2013-03-09 18:59:42 -06:00
|
|
|
t->table[y*t->numColumns + x].colWidth
|
2010-03-08 04:55:21 -06:00
|
|
|
= maxWidthOfColumn
|
|
|
|
+ 2 * FIELD_BORDER_SPACE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (y=0; y < t->numRows; y++) {
|
|
|
|
/* find highest of minimum heights */
|
|
|
|
maxHeightOfRow = 0;
|
|
|
|
for (x=0; x < t->numColumns; x++) {
|
2013-03-09 18:59:42 -06:00
|
|
|
maxHeightOfRow =
|
|
|
|
(maxHeightOfRow >
|
2010-03-08 04:55:21 -06:00
|
|
|
t->table[y * t->numColumns + x].minHeight)?
|
2013-03-09 18:59:42 -06:00
|
|
|
maxHeightOfRow:
|
2010-03-08 04:55:21 -06:00
|
|
|
t->table[y * t->numColumns+x].minHeight;
|
|
|
|
}
|
|
|
|
/* assign uniform height to row */
|
|
|
|
for (x=0; x < t->numColumns; x++) {
|
|
|
|
t->table[y * t->numColumns + x].rowHeight
|
|
|
|
= maxHeightOfRow
|
|
|
|
+ 2 * FIELD_BORDER_SPACE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* take care of formattedText */
|
|
|
|
for (y=0; y < t->numRows; y++) {
|
|
|
|
for (x=0; x < t->numColumns; x++) {
|
|
|
|
field = &(t->table[y * t->numColumns + x]);
|
|
|
|
field->formattedText =
|
|
|
|
(char **) malloc(sizeof(char *));
|
|
|
|
if (field->text) {
|
|
|
|
field->formattedText[0]= strdup(field->text);
|
|
|
|
field->numLines = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
field->formattedText[0]= (char *) 0;
|
|
|
|
field->numLines = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* will have to squeeze fields downward to fit on page */
|
|
|
|
|
|
|
|
percentToShrink = ((float)pageWidth)/((float)sumMaxWidth);
|
|
|
|
for (x = 0; x < t->numColumns; x++) {
|
|
|
|
/*find max width of this column */
|
|
|
|
/*
|
|
|
|
maxWidthOfColumn = 0;
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
|
|
|
maxWidthOfColumn = (maxWidthOfColumn >
|
|
|
|
t->table[y*t->numColumns+x].maxWidth) ?
|
|
|
|
maxWidthOfColumn :
|
|
|
|
t->table[y*t->numColumns+x].maxWidth;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* format it */
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
|
|
|
field = &(t->table[y*t->numColumns+x]);
|
2013-03-09 18:59:42 -06:00
|
|
|
field->colWidth = (int) (percentToShrink *
|
2010-03-08 04:55:21 -06:00
|
|
|
((float) CalculateMaxWidthOfColumn(t,x)));
|
|
|
|
field->rowHeight = 0;
|
|
|
|
numAdjacent = TableHowManyConnectedHorizFields
|
|
|
|
(t,x,y);
|
|
|
|
/* calculate the width including connected */
|
|
|
|
accumulateColWidth = field->colWidth;
|
|
|
|
for (xx = x+1; xx < x+numAdjacent+1; xx++) {
|
|
|
|
accumulateColWidth += (
|
|
|
|
(percentToShrink *
|
|
|
|
((float) CalculateMaxWidthOfColumn(t,xx))));
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
fprintf(stderr,"About to call PourText\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
PourText(field->text,field->font,
|
|
|
|
accumulateColWidth,
|
|
|
|
&(field->rowHeight),
|
|
|
|
hw->html.percent_vert_space,
|
|
|
|
&(field->formattedText),
|
|
|
|
&(field->numLines));
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
fprintf(stderr,"poured field %d,%d is dims %d,%d: %%shrink=%f\n",
|
|
|
|
x,y,field->colWidth,field->rowHeight,percentToShrink);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* divy up width with adjacent continue Horizontal fields*/
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
|
|
|
for (x = 0; x < t->numColumns; x++) {
|
|
|
|
numAdjacent = TableHowManyConnectedHorizFields(t,x,y);
|
|
|
|
if (numAdjacent) {
|
|
|
|
int xx;
|
|
|
|
for (xx = x; xx < x + numAdjacent; xx++) {
|
|
|
|
t->table[y * t->numColumns+xx].colWidth
|
|
|
|
= t->table[y*t->numColumns+x].colWidth
|
|
|
|
/ (numAdjacent+ 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
x += numAdjacent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* divy up height with adjacent continue Vertical fields */
|
|
|
|
for (x = 0; x < t->numColumns; x++) {
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
|
|
|
numAdjacent = TableHowManyConnectedVertFields(t,x,y);
|
|
|
|
if (numAdjacent) {
|
|
|
|
int yy;
|
|
|
|
for (yy = y; yy < y + numAdjacent; yy++) {
|
|
|
|
t->table[yy * t->numColumns+x].rowHeight
|
|
|
|
= t->table[y*t->numColumns+x].rowHeight
|
|
|
|
/ (numAdjacent + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
y += numAdjacent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* assign uniform height to row*/
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
|
|
|
/* find max height of this row */
|
|
|
|
maxHeightOfRow = 0;
|
|
|
|
for (x = 0; x < t->numColumns; x++) {
|
|
|
|
maxHeightOfRow = (maxHeightOfRow >
|
|
|
|
t->table[y*t->numColumns+x].rowHeight) ?
|
|
|
|
maxHeightOfRow :
|
|
|
|
t->table[y*t->numColumns+x].rowHeight;
|
|
|
|
}
|
|
|
|
/* assign height */
|
|
|
|
for (x = 0; x < t->numColumns; x++) {
|
2013-03-09 18:59:42 -06:00
|
|
|
t->table[y * t->numColumns + x].rowHeight =
|
2010-03-08 04:55:21 -06:00
|
|
|
maxHeightOfRow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* make sure all widths in a column are the same size */
|
|
|
|
for (x = 0; x < t->numColumns; x++) {
|
2013-03-09 18:59:42 -06:00
|
|
|
maxWidthOfColumn = 0;
|
2010-03-08 04:55:21 -06:00
|
|
|
/* find biggest Width for this column */
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
2013-03-09 18:59:42 -06:00
|
|
|
maxWidthOfColumn = (maxWidthOfColumn >
|
2010-03-08 04:55:21 -06:00
|
|
|
t->table[y*t->numColumns+x].colWidth)?
|
|
|
|
maxWidthOfColumn:
|
|
|
|
t->table[y*t->numColumns+x].colWidth;
|
|
|
|
}
|
|
|
|
/* make sure they are all the same */
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
|
|
|
t->table[y*t->numColumns+x].colWidth = maxWidthOfColumn;
|
|
|
|
}
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* calculate table width */
|
|
|
|
t->width = 0;
|
|
|
|
for (x = 0; x < t->numColumns; x++) {
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
fprintf(stderr,"colWidth for %d,0 = %d\n",x,t->table[x].colWidth);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
t->width += t->table[x].colWidth;
|
|
|
|
}
|
|
|
|
/* calculate table height */
|
|
|
|
t->height = 0;
|
|
|
|
for (y = 0; y < t->numRows; y++) {
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
fprintf(stderr,"rowHeight for 0,%d = %d\n",y,t->table[y * t->numColumns].rowHeight);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
t->height += t->table[y * t->numColumns].rowHeight;
|
|
|
|
}
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
|
|
|
|
/*
|
|
|
|
t->bwidth=t->width-t->borders;
|
|
|
|
t->bheight=t->height-t->borders;
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
t->bwidth=t->width;
|
|
|
|
t->bheight=t->height;
|
|
|
|
*/
|
|
|
|
t->width+=(t->borders*2);
|
|
|
|
t->height+=(t->borders*2);
|
|
|
|
|
|
|
|
if (htmlwTrace) {
|
|
|
|
TableDump(t);
|
|
|
|
fprintf(stderr,"TableCalculateDimensions(): table is %d x %d\n",
|
|
|
|
t->width,t->height);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
} /* TableCalculateDimensions() */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* expand colspans and rowspans in table */
|
|
|
|
/* return True if this routine did something */
|
|
|
|
static Boolean TableExpandFields(tableList, rowList, rowCount, columnCount)
|
|
|
|
List tableList;
|
|
|
|
List rowList;
|
|
|
|
int rowCount;
|
|
|
|
int *columnCount;
|
|
|
|
{
|
|
|
|
TableField *field;
|
|
|
|
List previousRow; /* previous to current row */
|
|
|
|
TableField *aboveField; /* field above current field */
|
|
|
|
TableField *fieldToTheLeft; /* field to the left of current field */
|
|
|
|
Boolean expandedSomething;
|
|
|
|
|
|
|
|
expandedSomething = False;
|
|
|
|
/* check for and take care of previous rowspans */
|
|
|
|
if (rowCount > 1) {
|
|
|
|
/* get field above this one */
|
2013-03-09 18:59:42 -06:00
|
|
|
previousRow = (List) ListGetIndexedEntry(tableList,
|
2010-03-08 04:55:21 -06:00
|
|
|
rowCount - 2);/*zero indexed*/
|
|
|
|
aboveField =(TableField *)ListGetIndexedEntry(previousRow,
|
|
|
|
*columnCount);
|
|
|
|
if (aboveField) {
|
|
|
|
/*check if the above expands into this row*/
|
|
|
|
if (aboveField->rowSpan > 1) {
|
|
|
|
if (!(field = NewTableField())) {
|
|
|
|
return(0); /* out of memory */
|
|
|
|
}
|
|
|
|
|
|
|
|
field->rowSpan = aboveField->rowSpan - 1;
|
|
|
|
field->contVert = True;
|
|
|
|
field->contHoriz = aboveField->contHoriz;
|
|
|
|
field->header = aboveField->header;
|
|
|
|
|
|
|
|
ListAddEntry(rowList, field);
|
|
|
|
expandedSomething = True;
|
|
|
|
(*columnCount)++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check for and take care of previous colspans */
|
|
|
|
if (*columnCount) {
|
|
|
|
/* get field above this one */
|
|
|
|
fieldToTheLeft = (TableField *) ListTail(rowList);
|
|
|
|
while(fieldToTheLeft->colSpan > 1) {
|
|
|
|
|
|
|
|
if (!(field = NewTableField())) {
|
|
|
|
return(0); /* out of memory */
|
|
|
|
}
|
|
|
|
|
|
|
|
field->colSpan = fieldToTheLeft->colSpan - 1;
|
|
|
|
field->contHoriz = True;
|
|
|
|
field->header = fieldToTheLeft->header;
|
|
|
|
|
|
|
|
if (fieldToTheLeft->rowSpan > 1) {
|
|
|
|
field->rowSpan = fieldToTheLeft->rowSpan;
|
|
|
|
}
|
|
|
|
|
|
|
|
ListAddEntry(rowList, field);
|
|
|
|
fieldToTheLeft = field;
|
|
|
|
(*columnCount)++;
|
|
|
|
expandedSomething = True;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(expandedSomething);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* set/get attributes for display from mark list for the field*/
|
|
|
|
static void TableFieldSetAttributes(hw,field,mptr)
|
|
|
|
HTMLWidget hw;
|
|
|
|
TableField *field;
|
|
|
|
struct mark_up **mptr;
|
|
|
|
{
|
|
|
|
struct mark_up *m;
|
|
|
|
/*
|
|
|
|
Boolean bold;
|
|
|
|
Boolean italic;
|
|
|
|
Boolean fixed;
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* for right now, only get the text */
|
|
|
|
|
|
|
|
field->font = hw->html.plain_font; /* default font */
|
|
|
|
m = (*mptr)->next;
|
|
|
|
while(m && (m->type != M_TABLE) && (m->type != M_TABLE_ROW) &&
|
|
|
|
(m->type != M_TABLE_DATA) && (m->type != M_TABLE_HEADER)
|
|
|
|
&& (m->type != M_NONE)) {
|
|
|
|
if (!m->is_end) { /* effect is to only use the top on stack */
|
|
|
|
switch(m->type) {
|
|
|
|
case M_ITALIC:
|
|
|
|
case M_VARIABLE:
|
|
|
|
case M_EMPHASIZED:
|
|
|
|
field->font = hw->html.italic_font;
|
|
|
|
break;
|
|
|
|
case M_BOLD:
|
|
|
|
case M_STRONG:
|
|
|
|
case M_ANCHOR:
|
|
|
|
field->font = hw->html.bold_font;
|
|
|
|
break;
|
|
|
|
case M_FIXED:
|
|
|
|
case M_CODE:
|
|
|
|
case M_SAMPLE:
|
|
|
|
case M_KEYBOARD:
|
|
|
|
field->font = hw->html.fixed_font;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m = m->next;
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
if (field->header) {
|
|
|
|
field->font = hw->html.plainbold_font;
|
|
|
|
}
|
|
|
|
if (m->type == M_NONE){ /* text */
|
|
|
|
field->type = F_TEXT;
|
|
|
|
field->text = strdup(m->text);
|
|
|
|
clean_text(field->text);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TableInfo *MakeTable(hw, mptr, x, y)
|
|
|
|
HTMLWidget hw;
|
|
|
|
struct mark_up **mptr;
|
|
|
|
unsigned int x,y;
|
|
|
|
{
|
|
|
|
struct mark_up *m;
|
|
|
|
TableInfo *t;
|
|
|
|
TableField *field;
|
|
|
|
int columnCount;
|
|
|
|
int rowCount;
|
|
|
|
char *val;
|
|
|
|
List rowList; /* current row (List of TableFields)*/
|
|
|
|
List tableList; /* list of Row Lists */
|
|
|
|
char *tptr;
|
|
|
|
|
|
|
|
if (((*mptr)->type != M_TABLE) || ((*mptr)->is_end)) {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
if (!(t = (TableInfo *) malloc(sizeof(TableInfo)))) {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
t->numColumns = 0;
|
|
|
|
t->numRows = 0;
|
|
|
|
t->caption = (char *) 0;
|
|
|
|
|
|
|
|
if (tptr=ParseMarkTag(((*mptr)->start),MT_TABLE,"BORDER")) {
|
|
|
|
t->borders = atoi(tptr);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
t->borders = 0;
|
|
|
|
}
|
|
|
|
tableList = ListCreate();
|
|
|
|
rowList = ListCreate();
|
|
|
|
ListAddEntry(tableList, rowList);
|
|
|
|
columnCount = 0;
|
|
|
|
rowCount=1;
|
|
|
|
m = *mptr;
|
|
|
|
field = (TableField *) 0;
|
|
|
|
while (m && (!((m->type == M_TABLE) && (m->is_end)))) {
|
|
|
|
|
|
|
|
if (m->type == M_CAPTION) {
|
|
|
|
if (ParseMarkTag(m->start,MT_CAPTION,"top")) {
|
|
|
|
t->captionAlignment = ALIGN_TOP;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
t->captionAlignment = ALIGN_BOTTOM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if ((m->type == M_TABLE_ROW)&&(!m->is_end)) {
|
|
|
|
/* expand at end of row */
|
|
|
|
while(TableExpandFields(tableList, rowList,
|
|
|
|
rowCount, &columnCount));
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
/* if: is this the first container <tr> or the
|
2010-03-08 04:55:21 -06:00
|
|
|
separator */
|
|
|
|
if (ListHead(ListHead(tableList))) {
|
|
|
|
rowList = ListCreate();
|
|
|
|
ListAddEntry(tableList,rowList);
|
|
|
|
rowCount++;
|
|
|
|
}
|
|
|
|
columnCount = 0;
|
|
|
|
/* expand cols at beginning of row */
|
|
|
|
TableExpandFields(tableList, rowList,
|
|
|
|
rowCount, &columnCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if ((m->type == M_TABLE_DATA) && (!m->is_end)) {
|
|
|
|
|
|
|
|
while(TableExpandFields(tableList, rowList,
|
|
|
|
rowCount, &columnCount));
|
|
|
|
|
|
|
|
if (!(field = NewTableField())) {
|
|
|
|
return(0); /* out of memory */
|
|
|
|
}
|
|
|
|
field->header = False;
|
|
|
|
|
|
|
|
/* check for colspan & rowspan */
|
|
|
|
|
|
|
|
val = ParseMarkTag(m->start,MT_TABLE_DATA,"colspan");
|
|
|
|
if (val) {
|
|
|
|
field->colSpan = atoi(val);
|
|
|
|
if ((field->colSpan > 100)||(field->colSpan < 1)){
|
|
|
|
field->colSpan = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
val = ParseMarkTag(m->start,MT_TABLE_DATA,"rowspan");
|
|
|
|
if (val) {
|
|
|
|
field->rowSpan = atoi(val);
|
|
|
|
if ((field->rowSpan > 100)||(field->rowSpan < 1)){
|
|
|
|
field->rowSpan = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check for alignment */
|
|
|
|
val = ParseMarkTag(m->start,MT_TABLE_DATA,"align");
|
|
|
|
if (caseless_equal(val,"left")) {
|
|
|
|
field->alignment = ALIGN_LEFT;
|
|
|
|
}
|
|
|
|
else if (caseless_equal(val,"right")) {
|
|
|
|
field->alignment = ALIGN_RIGHT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
field->alignment = ALIGN_CENTER;
|
|
|
|
}
|
|
|
|
TableFieldSetAttributes(hw,field,&m);
|
|
|
|
|
|
|
|
ListAddEntry(rowList, field);
|
|
|
|
columnCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if ((m->type == M_TABLE_HEADER) && (!m->is_end)) {
|
|
|
|
|
|
|
|
while(TableExpandFields(tableList, rowList,
|
|
|
|
rowCount, &columnCount));
|
|
|
|
|
|
|
|
if (!(field = NewTableField())) {
|
|
|
|
return(0); /*out of memory */
|
|
|
|
}
|
|
|
|
field->header = True;
|
|
|
|
|
|
|
|
val = ParseMarkTag(m->start,MT_TABLE_HEADER,"colspan");
|
|
|
|
if (val) {
|
|
|
|
field->colSpan = atoi(val);
|
|
|
|
if ((field->colSpan > 100)||(field->colSpan<1)){
|
|
|
|
field->colSpan = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
val = ParseMarkTag(m->start,MT_TABLE_HEADER,"rowspan");
|
|
|
|
if (val) {
|
|
|
|
field->rowSpan = atoi(val);
|
|
|
|
if ((field->rowSpan > 100) || (field->rowSpan < 1)) {
|
|
|
|
field->rowSpan = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check for alignment */
|
|
|
|
val = ParseMarkTag(m->start,MT_TABLE_HEADER,"align");
|
|
|
|
if (caseless_equal(val,"left")) {
|
|
|
|
field->alignment = ALIGN_LEFT;
|
|
|
|
}
|
|
|
|
else if (caseless_equal(val,"right")) {
|
|
|
|
field->alignment = ALIGN_RIGHT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
field->alignment = ALIGN_CENTER;
|
|
|
|
}
|
|
|
|
TableFieldSetAttributes(hw,field,&m);
|
|
|
|
|
|
|
|
ListAddEntry(rowList, field);
|
|
|
|
columnCount++;
|
|
|
|
}
|
|
|
|
else if (m->type == 0){ /* text */
|
|
|
|
/* taken care of by TableFieldSetAttributes() above*/
|
|
|
|
/* so ignore text now */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m = m->next;
|
|
|
|
}
|
|
|
|
*mptr = m; /* advance mark pointer to end of table */
|
|
|
|
|
|
|
|
/* end of table has been hit, so wrap it up */
|
|
|
|
/* clean up any at end of row */
|
|
|
|
while(TableExpandFields(tableList, rowList, rowCount, &columnCount));
|
|
|
|
/*
|
|
|
|
rowCount++;
|
|
|
|
do {
|
|
|
|
rowList = ListCreate();
|
|
|
|
ListAddEntry(tableList,rowList);
|
|
|
|
rowCount++;
|
|
|
|
}
|
|
|
|
while (TableExpandFields(tableList, ListTail(tableList),
|
|
|
|
ListCount(tableList) - 1, 0));
|
|
|
|
ListDeleteEntry(tableList, rowList);
|
|
|
|
rowCount--;
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!(TableCleanUp(t,tableList))) {
|
|
|
|
return(0); /* out of memory */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free up memory from tableList since TableCleanUp
|
|
|
|
has already copied it into an array for speed. */
|
|
|
|
rowList = (List) ListHead(tableList);
|
|
|
|
while (rowList) {
|
|
|
|
field = (TableField *) ListHead(rowList);
|
|
|
|
while(field) {
|
|
|
|
ListDeleteEntry(rowList,field);
|
|
|
|
free(field);
|
|
|
|
field = (TableField *) ListHead(rowList);
|
|
|
|
}
|
|
|
|
ListDeleteEntry(tableList,rowList);
|
|
|
|
ListDestroy(rowList);
|
|
|
|
rowList = (List) ListHead(tableList);
|
|
|
|
}
|
|
|
|
|
|
|
|
TableCalculateDimensions(hw,t,622);
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
TableDump(t);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return(t);
|
|
|
|
|
|
|
|
} /* MakeTable() */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TableDisplayField(hw,eptr,field,x,y,width,height)
|
|
|
|
HTMLWidget hw;
|
|
|
|
struct ele_rec *eptr;
|
|
|
|
TableField *field;
|
|
|
|
int x,y; /* field origin */
|
|
|
|
int width,height; /* space allowed for displaying */
|
|
|
|
{
|
|
|
|
int stringWidth; /* in pixels */
|
|
|
|
int placeX,placeY;
|
|
|
|
int lineHeight;
|
|
|
|
int baseLine;
|
|
|
|
int yy;
|
|
|
|
|
|
|
|
if (field->type == F_NONE) { /* nothing to display in field */
|
2013-03-09 11:32:44 -06:00
|
|
|
return -1;
|
2010-03-08 04:55:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if (field->type != F_TEXT) { /* routine only does text at this time */
|
2013-03-09 11:32:44 -06:00
|
|
|
return -1;
|
2010-03-08 04:55:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* adjust for aesthetic surounding space */
|
|
|
|
width -= (2 * FIELD_BORDER_SPACE);
|
|
|
|
x += FIELD_BORDER_SPACE;
|
|
|
|
height -= (2 * FIELD_BORDER_SPACE);
|
|
|
|
y += FIELD_BORDER_SPACE;
|
|
|
|
|
|
|
|
|
|
|
|
lineHeight = FONTHEIGHT(field->font);
|
|
|
|
baseLine = field->font->max_bounds.ascent;
|
|
|
|
placeY = y + (height - (lineHeight * field->numLines))/2;
|
|
|
|
for (yy = 0; yy < field->numLines; yy++) {
|
|
|
|
stringWidth = XTextWidth(field->font,field->formattedText[yy],
|
|
|
|
strlen(field->formattedText[yy]));
|
|
|
|
|
|
|
|
switch(field->alignment) {
|
|
|
|
case ALIGN_LEFT:
|
|
|
|
placeX = x;
|
|
|
|
break;
|
|
|
|
case ALIGN_CENTER:
|
|
|
|
placeX = x + (width - stringWidth)/2;
|
|
|
|
break;
|
|
|
|
case ALIGN_RIGHT:
|
|
|
|
placeX = x + width - stringWidth;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*
|
2013-03-09 18:59:42 -06:00
|
|
|
placeY = y + height/2 +
|
|
|
|
(field->font->max_bounds.ascent
|
2010-03-08 04:55:21 -06:00
|
|
|
- field->font->max_bounds.descent)/2;
|
|
|
|
*/
|
|
|
|
|
|
|
|
XSetLineAttributes(XtDisplay(hw),hw->html.drawGC,1,LineSolid,
|
|
|
|
CapNotLast,JoinMiter);
|
|
|
|
XSetBackground(XtDisplay(hw), hw->html.drawGC, eptr->bg);
|
|
|
|
XSetForeground(XtDisplay(hw), hw->html.drawGC, eptr->fg);
|
|
|
|
XSetFont(XtDisplay(hw), hw->html.drawGC, field->font->fid);
|
2022-04-17 09:05:37 -05:00
|
|
|
XmString ttd=XmStringCreateLocalized(field->formattedText[yy]);
|
|
|
|
XmFontList tftd=XmFontListCreate(field->font,XmSTRING_DEFAULT_CHARSET);
|
|
|
|
XmStringDraw(XtDisplay(hw),
|
|
|
|
XtWindow(hw->html.view),
|
|
|
|
tftd,
|
|
|
|
ttd,
|
|
|
|
hw->html.drawGC,
|
|
|
|
placeX,
|
|
|
|
placeY+baseLine,
|
|
|
|
XmStringWidth(tftd,ttd),
|
|
|
|
XmALIGNMENT_BEGINNING,
|
|
|
|
XmSTRING_DIRECTION_L_TO_R,
|
|
|
|
NULL);
|
|
|
|
XmStringFree(ttd);
|
|
|
|
XmFontListFree(tftd);
|
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
|
|
|
|
placeY += lineHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
XSetLineAttributes(XtDisplay(hw),
|
|
|
|
hw->html.drawGC,
|
|
|
|
eptr->table_data->borders,
|
|
|
|
LineSolid,
|
|
|
|
CapNotLast,
|
|
|
|
JoinMiter);
|
|
|
|
|
|
|
|
} /* TableDisplayField() */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Find actual table field dimensions considering colspans & rowspans */
|
|
|
|
static void TableGetExpandedDimensions(t,xpos,ypos,
|
|
|
|
expandWidth,expandHeight)
|
|
|
|
TableInfo *t;
|
|
|
|
int xpos,ypos; /* current field index */
|
|
|
|
int *expandWidth,*expandHeight; /* returned */
|
|
|
|
{
|
|
|
|
int x,y;
|
|
|
|
x = xpos;
|
|
|
|
y = ypos;
|
|
|
|
|
|
|
|
*expandWidth = t->table[y * t->numColumns + x].colWidth;
|
|
|
|
*expandHeight = t->table[y * t->numColumns + x].rowHeight;
|
|
|
|
|
|
|
|
/* do width */
|
|
|
|
x++;
|
|
|
|
if (x < t->numColumns) {
|
|
|
|
/* do width */
|
2013-03-09 18:59:42 -06:00
|
|
|
while ((x < t->numColumns) &&
|
2010-03-08 04:55:21 -06:00
|
|
|
t->table[y * t->numColumns + x].contHoriz) {
|
|
|
|
(*expandWidth) += t->table[y * t->numColumns + x].colWidth;
|
|
|
|
x++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
x = xpos;
|
|
|
|
y++;
|
|
|
|
if (y < t->numRows) {
|
|
|
|
/* do height */
|
2013-03-09 18:59:42 -06:00
|
|
|
while ((y < t->numRows) &&
|
2010-03-08 04:55:21 -06:00
|
|
|
t->table[y * t->numColumns + x].contVert) {
|
|
|
|
(*expandHeight) += t->table[y * t->numColumns+x].rowHeight;
|
|
|
|
y++;
|
|
|
|
}
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* display table */
|
|
|
|
void TableRefresh(hw,eptr)
|
|
|
|
HTMLWidget hw;
|
|
|
|
struct ele_rec *eptr;
|
|
|
|
{
|
|
|
|
int x,y; /* table origin */
|
|
|
|
register int xx,yy;
|
|
|
|
TableField *field;
|
|
|
|
int vertMarker,horizMarker;
|
|
|
|
int colWidth,rowHeight;
|
|
|
|
int expandedWidth,expandedHeight;
|
|
|
|
|
|
|
|
if (eptr->table_data == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
x = eptr->x;
|
|
|
|
y = eptr->y;
|
|
|
|
|
|
|
|
x = x - hw->html.scroll_x;
|
|
|
|
y = y - hw->html.scroll_y;
|
|
|
|
|
|
|
|
XSetLineAttributes(XtDisplay(hw),
|
|
|
|
hw->html.drawGC,
|
|
|
|
eptr->table_data->borders,
|
|
|
|
LineSolid,
|
|
|
|
CapNotLast,
|
|
|
|
JoinMiter);
|
|
|
|
XSetForeground(XtDisplay(hw), hw->html.drawGC, eptr->fg);
|
|
|
|
XSetBackground(XtDisplay(hw), hw->html.drawGC, eptr->bg);
|
|
|
|
|
|
|
|
if (eptr->table_data->borders){
|
|
|
|
/*
|
|
|
|
XDrawRectangle(XtDisplay(hw), XtWindow(hw->html.view),
|
2013-03-09 18:59:42 -06:00
|
|
|
hw->html.drawGC,
|
2010-03-08 04:55:21 -06:00
|
|
|
x+(eptr->table_data->borders/2),y+eptr->table_data->borders,
|
|
|
|
eptr->table_data->bwidth,
|
|
|
|
eptr->table_data->bheight);
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
eptr->table_data->height-1);
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
field = eptr->table_data->table;
|
|
|
|
horizMarker = y+eptr->table_data->borders;
|
|
|
|
for (yy = 0; yy < eptr->table_data->numRows; yy++) {
|
|
|
|
vertMarker = x+(eptr->table_data->borders/2);
|
|
|
|
rowHeight = field->rowHeight;
|
|
|
|
for (xx = 0; xx < eptr->table_data->numColumns; xx++) {
|
|
|
|
colWidth = field->colWidth;
|
|
|
|
|
|
|
|
/* draw field borders */
|
|
|
|
if (eptr->table_data->borders){
|
|
|
|
if (!field->contVert) { /* draw above line */
|
2013-03-09 18:59:42 -06:00
|
|
|
XDrawLine(XtDisplay(hw),
|
2010-03-08 04:55:21 -06:00
|
|
|
XtWindow(hw->html.view),
|
|
|
|
hw->html.drawGC,
|
|
|
|
/*hw->manager.bottom_shadow_GC,*/
|
|
|
|
vertMarker, horizMarker,
|
|
|
|
vertMarker + colWidth, horizMarker);
|
|
|
|
/*
|
2013-03-09 18:59:42 -06:00
|
|
|
XDrawLine(XtDisplay(hw),
|
2010-03-08 04:55:21 -06:00
|
|
|
XtWindow(hw->html.view),
|
|
|
|
hw->manager.top_shadow_GC,
|
|
|
|
vertMarker, horizMarker+1,
|
|
|
|
vertMarker + colWidth, horizMarker+1);
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
if (!field->contHoriz) { /* draw left side*/
|
2013-03-09 18:59:42 -06:00
|
|
|
XDrawLine(XtDisplay(hw),
|
2010-03-08 04:55:21 -06:00
|
|
|
XtWindow(hw->html.view),
|
|
|
|
hw->html.drawGC,
|
|
|
|
vertMarker, horizMarker,
|
|
|
|
vertMarker, horizMarker + rowHeight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TableGetExpandedDimensions(eptr->table_data,
|
|
|
|
xx,yy,&expandedWidth,&expandedHeight);
|
|
|
|
/* fill in field */
|
|
|
|
TableDisplayField(hw,
|
|
|
|
eptr,
|
|
|
|
field,
|
|
|
|
vertMarker,
|
|
|
|
horizMarker,
|
|
|
|
expandedWidth,
|
|
|
|
expandedHeight);
|
|
|
|
|
|
|
|
vertMarker += colWidth;
|
|
|
|
field++;
|
2013-03-09 18:59:42 -06:00
|
|
|
}
|
2010-03-08 04:55:21 -06:00
|
|
|
|
|
|
|
horizMarker += rowHeight;
|
2013-03-09 18:59:42 -06:00
|
|
|
}
|
2010-03-08 04:55:21 -06:00
|
|
|
|
|
|
|
XSetLineAttributes(XtDisplay(hw),
|
|
|
|
hw->html.drawGC,
|
|
|
|
1,
|
|
|
|
LineSolid,
|
|
|
|
CapNotLast,
|
|
|
|
JoinMiter);
|
|
|
|
}
|