diff options
Diffstat (limited to 'src/hyper/extent2.c')
-rw-r--r-- | src/hyper/extent2.c | 929 |
1 files changed, 929 insertions, 0 deletions
diff --git a/src/hyper/extent2.c b/src/hyper/extent2.c new file mode 100644 index 00000000..5a7a6848 --- /dev/null +++ b/src/hyper/extent2.c @@ -0,0 +1,929 @@ +/* + Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd. + All rights reserved. + Copyright (C) 2007-2008, Gabriel Dos Reis. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + - Neither the name of The Numerical Algorithms Group Ltd. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/****************************************************************************** + * + * extent2.h: HyperDoc extent computation routines + * + * Copyright The Numerical Algorithms Group Limited 1991, 1992, 1993. + * + ****************************************************************************/ +#define _EXTENT2_C +#include "axiom-c-macros.h" +#include "useproto.h" +#include "debug.h" + + +#include "extent.h" +#include "group.h" +#include "titlebar.h" + +#include "all_hyper_proto.H1" +#include "pixmap.H1" + + +static int cur_height = 0; +static int max_x_value = 0; + +/* + * start_newline updates the current header node, and also allocates if needed + * memory for the next Line Header. It also assigns the first TextNode on the + * line to the structure, because this is the last time I will be able to do + * this + */ + +void +start_newline(int distance, TextNode * node) +{ + if (gLineNode != NULL) { + if (gTopOfGroupStack->center) + center_nodes(gLineNode, node); + gLineNode = node; + } + text_y += distance; + past_line_height = distance; + present_line_height = line_height; + gInLine = 0; +} + +/* + * center_nodes goes through and centers all the text between the two + * given nodes. + */ + +static void +center_nodes(TextNode * begin_node, TextNode * end_node) +{ + int begin_x, end_x, wmid_x, offset, mid_x; + TextNode *node; + + end_x = text_x; + begin_x = x_value(begin_node); + mid_x = (int) (end_x + begin_x) / 2; + wmid_x = (int) (right_margin + indent) / 2; + + if (mid_x > wmid_x) + offset = 0; + else + offset = wmid_x - mid_x; + + for (node = begin_node; node != end_node; node = node->next) + if (node->x > 0) + node->x += offset; +} + +static int +punctuation_width(TextNode * node) +{ + int twidth, width = strlen(node->data.text); + + twidth = XTextWidth(gTopOfGroupStack->cur_font, node->data.text, width); + + /* check to see if there was some space in front */ + + if (gInLine && (node->space & FRONTSPACE)) + twidth += inter_word_space; + +# if 0 + if (node->space & BACKSPACE) { + switch (node->data.text[0]) { + case '.': + case '?': + case '!': + twidth += term_punct_space; + break; + } + } +#endif + + return twidth; +} + +static int +input_string_width(TextNode * node) +{ + InputItem *item; + int t_width; + + /** search the symbol table for the proper entry **/ + + item = node->link->reference.string; + + /** Once I have gotten this far, I should just be able to calculate + the width using the normal font **/ + + t_width = (item->size + 1) * gInputFont->max_bounds.width + 10; + return t_width; + +} + +static int +word_width(TextNode * node) +{ + int twidth, len = strlen(node->data.text); + + twidth = XTextWidth(gTopOfGroupStack->cur_font, node->data.text, len); + if (node->space & FRONTSPACE) + twidth += inter_word_space; + + return twidth; +} + +static int +verbatim_width(TextNode * node) +{ + int twidth, len = strlen(node->data.text); + + twidth = XTextWidth(gTopOfGroupStack->cur_font, node->data.text, len); + if (node->space) + twidth += inter_word_space; + + return twidth; +} + +static int +width_of_dash(TextNode * node) +{ + int num_dashes, twidth; + + num_dashes = strlen(node->data.text); + if (num_dashes > 1) + twidth = node->width = num_dashes * dash_width; + else + twidth = node->width = XTextWidth(gTopOfGroupStack->cur_font, + node->data.text, 1); + if (node->space) + twidth += inter_word_space; + return twidth; +} + +/* + * return the gWindow->width in pixels of the given text node, when + * displayed + */ + +int +text_width(TextNode * node, int Ender) +{ + int twidth = 0, num_words; + + for (num_words = 0; node != NULL; num_words++, node = node->next) { + if (Ender == Endtokens) { + if (node->type == Endtokens) + return twidth; + } + else if (node->type == Ender) + return twidth; + + switch (node->type) { + case Macro: + case Pound: + if (node->space && gInLine) + twidth += inter_word_space; + break; + case Punctuation: + twidth += punctuation_width(node); + break; + case Dash: + if (gInLine && node->space) + twidth += inter_word_space; + twidth += width_of_dash(node); + break; + case Verbatim: + case Spadsrctxt: + twidth += verbatim_width(node); + break; + case Lsquarebrace: + case Rsquarebrace: + case Word: + twidth += word_width(node); + break; + case Box: + twidth += 2 * box_space; + break; + case Link: + case Downlink: + case Memolink: + case Windowlink: + case LispMemoLink: + case Lispwindowlink: + case Lisplink: + case Unixlink: + case Spadcall: + case Spadcallquit: + case Qspadcall: + case Qspadcallquit: + case LispDownLink: + case Lispcommand: + case Lispcommandquit: + case Spadlink: + case Spaddownlink: + case Spadmemolink: + case Unixcommand: + case Upbutton: + case Returnbutton: + case Description: + push_active_group(); + break; + case Endbutton: + case Endspadcommand: + case Enddescription: + pop_group_stack(); + break; + case Endlink: + pop_group_stack(); + break; + case Inputstring: + twidth += input_string_width(node); + break; + case SimpleBox: + case Radiobox: + twidth += node->width + ((node->space) ? inter_word_space : 0); + break; + case Spadcommand: + case Spadgraph: + push_spad_group(); + break; + case VSpace: + break; + case HSpace: + twidth += + (node->data.node != NULL ? atoi(node->data.node->data.text) : 1); + break; + case Space: + twidth += (gTopOfGroupStack->cur_font->max_bounds.width) * + (node->data.node != NULL ? atoi(node->data.node->data.text) : 1); + break; + case Tab: + twidth = (gTopOfGroupStack->cur_font->max_bounds.width) * + (node->data.node != NULL ? atoi(node->data.node->data.text) : 1); + break; + case Table: + twidth = gWindow->width - left_margin - right_margin_space; + break; + case Tableitem: + case Group: + twidth += (node->space) ? inter_word_space : 0; + push_group_stack(); + break; + case BoldFace: + if (node->space) + twidth += inter_word_space; + bf_top_group(); + break; + case Emphasize: + if (node->space) + twidth += inter_word_space; + if (gTopOfGroupStack->cur_font == gRmFont) + em_top_group(); + else + rm_top_group(); + break; + case It: + if (node->space) + twidth += inter_word_space; + em_top_group(); + break; + case Rm: + case Sl: + case Tt: + if (node->space) + twidth += inter_word_space; + rm_top_group(); + break; + case Endgroup: + pop_group_stack(); + break; + case Controlbitmap: + case Inputbitmap: + if (node->width == -1) + insert_bitmap_file(node); + twidth += node->width; + break; + case Inputpixmap: + if (node->width == -1) + insert_pixmap_file(node); + twidth += node->width; + break; + case Mbox: + case Indent: + case Endmacro: + case Free: + case Bound: + case Beep: + case Item: + case Titem: + case Beginitems: + case Noop: + case Endinputbox: + case Fi: + case Ifcond: + case Endif: + case Begintitems: + case Enditems: + case Endtitems: + case Endtableitem: + case Endtable: + case Endparameter: + case Endbox: + case Endheader: + case Endfooter: + case Endscrolling: + case Endverbatim: + case Endspadsrc: + break; + case Newline: + /* WOw, I guess I should ertunr a really big number */ + twidth += gWindow->width; + break; + default: + + /* + * fprintf(stderr, "Unknown nodetype %d in text_width\n", + * node->type); + */ + break; + } + } + return twidth; +} + +/* + * total_width traces through the nodes, until it finds a blank space. It is + * used by compute_word_extent, and compute_punctuation extent to determine + * How far we go before we actually see white space. + */ + +int +total_width(TextNode * node, int Ender) +{ + int twidth = 0; + + for (; (node != NULL); node = node->next) { + if (Ender == Endtokens) { + if (node->type >= Endtokens) + return twidth; + } + else if (node->type == Ender) + return twidth; + + /* + * The first thing we check for is to see if there was space in front + * of the current node, if so we are done + */ + + if (node->space) + return twidth; + + /*** Else depending on the node type ***/ + + switch (node->type) { + case Noop: + case Endinputbox: + case Pound: + case Ifcond: + case Fi: + case Endif: + break; + case Rsquarebrace: + case Punctuation: + case Word: + case Dash: + twidth += XTextWidth(gTopOfGroupStack->cur_font, node->data.text, + strlen(node->data.text)); + break; + case Box: + case Link: + case Downlink: + case Memolink: + case Windowlink: + case LispMemoLink: + case Lispwindowlink: + case Lisplink: + case Unixlink: + case Spadcall: + case Spadcallquit: + case Qspadcall: + case Qspadcallquit: + case LispDownLink: + case Lispcommand: + case Lispcommandquit: + case Spadlink: + case Spaddownlink: + case Spadmemolink: + case Unixcommand: + case Inputstring: + case SimpleBox: + case Radiobox: + case Upbutton: + case Returnbutton: + case Spadcommand: + case Spadgraph: + case VSpace: + case HSpace: + case Space: + case Table: + case Group: + case Controlbitmap: + case Inputbitmap: + case Inputpixmap: + case Free: + case Beep: + case Bound: + case Lsquarebrace: + case BoldFace: + case Emphasize: + case It: + case Rm: + case Sl: + case Tt: + case Newline: + case Verbatim: + case Spadsrctxt: + return twidth; + default: + break; + } + } + return twidth; +} + +/* + * init_extents initialize some text size variables + */ + +void +init_extents(void) +{ + present_line_height = line_height; + gInLine = 0; + gInItem = 0; + gInAxiomCommand = 0; + item_indent = 0; + gInDesc = 0; + indent = left_margin; + text_x = indent; + gTopOfGroupStack->cur_font = gRmFont; + gTopOfGroupStack->cur_color = gRmColor; + right_margin = gWindow->width - right_margin_space; + clear_item_stack(); +} + +/* + * init_title_extents initialize some title text size variables + */ + +void +init_title_extents(HyperDocPage * page) +{ + present_line_height = line_height; + gInLine = 0; + gInAxiomCommand = 0; + item_indent = 0; + gInDesc = 0; + indent = left_margin + page->title->x; + text_x = indent; + gTopOfGroupStack->cur_font = gRmFont; + gTopOfGroupStack->cur_color = gRmColor; + right_margin = gWindow->width - right_margin_space - gWindow->border_width - + 2 * twwidth; + clear_item_stack(); +} + +/* + * init_text initialize some text size variables + */ + +void +init_text(void) +{ + normal_text_height = gRmFont->ascent + gRmFont->descent; + line_height = gRmFont->ascent + gRmFont->descent + inter_line_space; + word_off_height = line_height - normal_text_height; + space_width = gRmFont->max_bounds.width; +} + +/* + * text_height returns the height of a piece of formatted text in pixels + */ + +int +text_height(TextNode * node, int Ender) +{ + cur_height = 0; + return text_height1(node, Ender); +} + +/* + * text_height1 is the recursive part of text_height + */ + +static int +text_height1(TextNode * node, int Ender) +{ + for (; node != NULL; node = node->next) { + if (Ender == Endtokens) { + if (node->type > -Endtokens) + return cur_height; + } + else if (node->type == Ender) + return cur_height; + switch (node->type) { + case Center: + case Downlink: + case Link: + case Spadcommand: + case Spadgraph: + case Upbutton: + case Returnbutton: + case Windowlink: + case Memolink: + case Lispwindowlink: + case Lisplink: + case Unixlink: + case Spadcall: + case Spadcallquit: + case Qspadcall: + case Qspadcallquit: + case LispDownLink: + case LispMemoLink: + case Lispcommand: + case Lispcommandquit: + case Spadlink: + case Spaddownlink: + case Spadmemolink: + case Unixcommand: + case SimpleBox: + case Radiobox: + case Group: + case Box: + case Controlbitmap: + case Inputbitmap: + case Inputpixmap: + case Horizontalline: + case Punctuation: + case Lsquarebrace: + case Rsquarebrace: + case Word: + case Verbatim: + case Math: + case Spadsrctxt: + case Dash: + case Inputstring: + cur_height = max(node->y, cur_height); + break; + case Mbox: + case Macro: + case Pound: + case Emphasize: + case BoldFace: + case It: + case Rm: + case Sl: + case Tt: + case Endparameter: + case Description: + case Enddescription: + case Noop: + case Fi: + case Ifcond: + case Endif: + case Endinputbox: + case Tab: + case Newline: + case Space: + case VSpace: + case HSpace: + case Beginitems: + case Begintitems: + case Endtitems: + case Titem: + case Enditems: + case Endtable: + case Endtableitem: + case Item: + case Par: + case Beep: + case Free: + case Bound: + case Endgroup: + case Endcenter: + case Endbutton: + case Endmacro: + case Tableitem: + case Endlink: + case Endspadcommand: + case Indent: + case Indentrel: + case Endbox: + case Endmbox: + case Table: + case Endverbatim: + case Endmath: + case Spadsrc: + case Endspadsrc: + break; + case Beginscroll: + case Endscroll: + break; + case Endscrolling: + return cur_height; + default: + + /* + * fprintf(stderr, "Text_height1: Unknown Node Type %d\n", + * node->type); + */ + break; + } + } + return cur_height; +} + +/* + * max_x returns the height of a piece of formatted text in pixels + */ + +int +max_x(TextNode * node, int Ender) +{ + max_x_value = 0; + for (; node != NULL; node = node->next) { + if (Ender == Endtokens) { + if (node->type >= Endtokens) + return max_x_value; + } + else if (node->type == Ender) + return max_x_value; + switch (node->type) { + case Lsquarebrace: + case Rsquarebrace: + case Word: + max_x_value = max(max_x_value, node->x + word_width(node)); + break; + case Verbatim: + case Spadsrctxt: + max_x_value = max(max_x_value, node->x + verbatim_width(node)); + break; + case Punctuation: + max_x_value = max(max_x_value, node->x + punctuation_width(node)); + break; + case Dash: + max_x_value = max(max_x_value, node->x + width_of_dash(node)); + break; + case HSpace: + max_x_value = max(max_x_value, node->x + + (node->data.node != NULL ? atoi(node->data.node->data.text) : 1)); + break; + case Space: + max_x_value = max(max_x_value, node->x + + (gTopOfGroupStack->cur_font->max_bounds.width) * + (node->data.node != NULL ? atoi(node->data.node->data.text) : 1)); + break; + case Group: + push_group_stack(); + break; + case BoldFace: + bf_top_group(); + break; + case Emphasize: + if (gTopOfGroupStack->cur_font == gRmFont) + em_top_group(); + else + rm_top_group(); + break; + case It: + em_top_group(); + break; + case Rm: + case Sl: + case Tt: + rm_top_group(); + break; + case Endgroup: + pop_group_stack(); + break; + case Controlbitmap: + case Inputbitmap: + if (node->width == -1) + insert_bitmap_file(node); + max_x_value = max(max_x_value, node->x + node->width); + break; + case Inputpixmap: + if (node->width == -1) + insert_pixmap_file(node); + max_x_value = max(max_x_value, node->y + node->width); + break; + default: + break; + } + } + return cur_height; +} + +static int +x_value(TextNode * node) +{ + for (; node != NULL; node = node->next) { + switch (node->type) { + case Controlbitmap: + case Inputbitmap: + case Inputpixmap: + case Lsquarebrace: + case Rsquarebrace: + case Word: + case Verbatim: + case Spadsrctxt: + case Dash: + case Punctuation: + case VSpace: + case HSpace: + case Horizontalline: + case Box: + case Downlink: + case Link: + case Lispwindowlink: + case Lisplink: + case Unixlink: + case Spadcall: + case Spadcallquit: + case Qspadcall: + case Qspadcallquit: + case LispDownLink: + case LispMemoLink: + case Lispcommand: + case Lispcommandquit: + case Spadlink: + case Spaddownlink: + case Spadmemolink: + case Spadcommand: + case Spadgraph: + case Unixcommand: + case Space: + case SimpleBox: + case Radiobox: + return node->x; + default: +#ifdef DEBUG + fprintf(stderr, "X_value did not know x value of type %d\n", node->type); +#endif + return x_value(node->next); + } + } + return 0; +} + +/* + * trailing_space computes the length of the trailing spaces of a node + */ + +int +trailing_space(TextNode * node) +{ + int space = 0; + + for (; node->type < Endtokens; node = node->next); + if (node->type == Space) + space += inter_word_space * + (node->data.node != NULL ? atoi(node->data.node->data.text) : 1); + return space; +} + +/* + * insert_bitmap_file reads a bitmap file into memory + */ + +void +insert_bitmap_file(TextNode * node) +{ + char *filename = node->data.text; + int bm_width, bm_height; + XImage *im; + ImageStruct *image; + + if (*filename == ' ') + filename++; + if (node->image.pm == 0) { + if ( + ((image = (ImageStruct *) hash_find(&gImageHashTable, filename)) == NULL) + || (getenv("HTCACHE"))) { + + /* + * read the bitmap if not already in memory or if the environment + * variable HTCACHE is set (NAG addition). + */ + + im = HTReadBitmapFile(gXDisplay, gXScreenNumber, filename, + &bm_width, &bm_height); + + /** now add the image to the gImageHashTable **/ + image = (ImageStruct *) halloc(sizeof(ImageStruct), "ImageStruct"); + image->image.xi = im; + image->width = image->image.xi->width; + image->height = image->image.xi->height; + image->filename = (char *) halloc(sizeof(char) * strlen(filename) +1,"Image Filename"); + /* strcpy(image->filename, filename); */ + sprintf(image->filename, "%s", filename); + hash_insert(&gImageHashTable, (char *)image, image->filename); + } + node->width = image->width; + node->height = image->height; + node->image.xi = image->image.xi; + } +} + +/* + * insert_pixmap_file reads a pixmap file into memory + */ + +void +insert_pixmap_file(TextNode * node) +{ + char *filename = node->data.text; + int bm_width, bm_height, ret_val; + XImage *xi; + ImageStruct *image; + + if (*filename == ' ') + filename++; + if (node->image.xi == 0) { + if ((image = (ImageStruct *) hash_find(&gImageHashTable, filename)) == NULL) { + ret_val = read_pixmap_file(gXDisplay, gXScreenNumber, filename, &xi, + &bm_width, &bm_height); + switch (ret_val) { + case(-1): + gSwitch_to_mono = 1; + return; + case BitmapFileInvalid: + fprintf(stderr, "File %s contains invalid bitmap data\n", filename); + return; + case BitmapOpenFailed: + fprintf(stderr, "couldn't open bitmap file %s\n", filename); + return; + case BitmapNoMemory: + fprintf(stderr, "not enough memory to store bitmap\n"); + return; + } + image = (ImageStruct *) halloc(sizeof(ImageStruct), "ImageStruct"); + image->width = bm_width; + image->height = bm_height; + image->filename = (char *) halloc(sizeof(char) * strlen(filename) +1, + "insert_pixmap--filename"); + /* strcpy(image->filename, filename); */ + sprintf(image->filename, "%s", filename); + image->image.xi = xi; + hash_insert(&gImageHashTable, (char *)image, image->filename); + } + node->width = image->width; + node->height = plh(image->height + inter_line_space); + node->image.xi = image->image.xi; + } +} + +/* + * plh calculates the closet value of line_height > height + */ + +int +plh(int height) +{ + int rheight = height; + + if (gExtentRegion == Scrolling) { + for (rheight = line_height; rheight < height; rheight += line_height) + ; + } + return rheight; +} |