aboutsummaryrefslogtreecommitdiff
path: root/src/hyper/extent1.c
diff options
context:
space:
mode:
authordos-reis <gdr@axiomatics.org>2008-03-07 15:19:01 +0000
committerdos-reis <gdr@axiomatics.org>2008-03-07 15:19:01 +0000
commit8531f4c74274b8aa99168d220738227557a9c418 (patch)
treec50b77870e432317be8f99c248e1339f74b51661 /src/hyper/extent1.c
parent33949ff2e6e5b5abe8d22c5604f42a6c9371079a (diff)
downloadopen-axiom-8531f4c74274b8aa99168d220738227557a9c418.tar.gz
* hyper/: De-pamphletize.
Diffstat (limited to 'src/hyper/extent1.c')
-rw-r--r--src/hyper/extent1.c1371
1 files changed, 1371 insertions, 0 deletions
diff --git a/src/hyper/extent1.c b/src/hyper/extent1.c
new file mode 100644
index 00000000..a18dbfd8
--- /dev/null
+++ b/src/hyper/extent1.c
@@ -0,0 +1,1371 @@
+/*
+ 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.
+*/
+
+/******************************************************************************
+ *
+ * extent1.h: HyperDoc extent computation routines
+ *
+ * Copyright The Numerical Algorithms Group Limited 1991, 1992, 1993.
+ *
+ ****************************************************************************/
+#define _EXTENT1_C
+#include "axiom-c-macros.h"
+#include "useproto.h"
+#include "debug.h"
+
+
+#include "extent.h"
+#include "hyper.h"
+#include "group.h"
+#include "titlebar.h"
+#include "scrollbar.h"
+
+#include "all_hyper_proto.H1"
+
+
+/*
+ * Now we declare all the values which are shared among the extent routines
+ * and the showing routines
+ */
+
+int noop_count;
+
+TextNode *link_node = NULL;
+TextNode *paste_node = NULL;
+TextNode *spad_node = NULL;
+TextNode *if_node = NULL;
+
+
+short int gExtentRegion;
+
+
+short int gInDesc;
+short int gInLine; /* true iff there have been words printed */
+short int gInItem; /* true iff we are in a \item */
+short int gInAxiomCommand; /* true iff we are in a \spadcommand */
+short int gInTable;
+
+/* Variables for the formatting state */
+
+int right_margin_space;
+int right_margin;
+int indent;
+int item_indent;
+int text_x;
+int text_y;
+int y_off;
+int scroll_bot;
+int need_scroll_up_button;
+int need_scroll_down_button;
+int item_space;
+int present_line_height;
+int past_line_height;
+int line_height; /* space between lines */
+int normal_text_height; /* space between lines */
+int space_width; /* the maximum width of a character */
+int word_off_height; /* the diff between text height and */
+
+TextNode *gLineNode;
+
+/*
+ * Computes the extent of the input string or box
+ */
+
+static void
+compute_input_extent(TextNode * node)
+{
+ InputItem *item;
+ int t_width;
+ int num_lines;
+
+ /* search the symbol table for the proper entry */
+
+ item = node->link->reference.string;
+ num_lines = item->num_lines;
+
+ /*
+ * Once we have gotten this far, we should just be able to calculate the
+ * width using the normal font
+ */
+
+ t_width = (item->size + 1) * gInputFont->max_bounds.width + 10;
+
+ if (gInLine)
+ text_x += inter_word_space;
+
+ if (text_x + t_width > right_margin) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->x = text_x;
+
+ /* now figure out the height of the current window */
+
+ node->height = line_height * (num_lines);
+ node->y = text_y - line_height + node->height - 1;
+ if (node->height > present_line_height)
+ present_line_height = plh(node->height);
+ node->width = t_width;
+ gInLine = 1;
+ text_x += t_width;
+}
+
+static void
+compute_punctuation_extent(TextNode * node)
+{
+ int twidth;
+ int nextwidth;
+ int incwidth;
+
+ node->height = normal_text_height;
+ node->width = strlen(node->data.text);
+ incwidth = twidth = XTextWidth(gTopOfGroupStack->cur_font, node->data.text,
+ node->width);
+
+ /* always check to see if there was some space in front of us */
+
+ if (gInLine && (node->space & FRONTSPACE))
+ twidth += inter_word_space;
+
+ /*
+ * now calcualte the width of the next one if it needs to be considered
+ */
+
+ if (!(node->space & BACKSPACE))
+ nextwidth = total_width(node->next, Endtokens);
+ else
+ nextwidth = 0;
+
+ if ((!(node->space & BACKSPACE)) &&
+ (text_x + twidth + nextwidth > right_margin) && gInLine) {
+ start_newline(present_line_height, node);
+ if (gInAxiomCommand) {
+ text_x = indent + spadcom_indent;
+ }
+ else
+ text_x = indent;
+ }
+
+ if (node->space & FRONTSPACE)
+ text_x += inter_word_space;
+
+ node->x = text_x;
+
+ /*
+ * Now try to see if we should leave space after myself. Always leave
+ * space when there is space
+ */
+
+ if (node->space & BACKSPACE) {
+ switch (node->data.text[0]) {
+ case '.':
+ case '?':
+ case '!':
+ text_x += term_punct_space;
+ break;
+ }
+ }
+
+ text_x += incwidth;
+ node->y = text_y - word_off_height;
+ gInLine = 1;
+}
+
+static void
+compute_word_extent(TextNode * node)
+{
+ int twidth;
+ int nextwidth;
+ int incwidth;
+
+ node->height = normal_text_height;
+ node->width = strlen(node->data.text);
+ incwidth = twidth = XTextWidth(gTopOfGroupStack->cur_font, node->data.text,
+ node->width);
+
+ /*
+ * Now if we should drop some space in front of me, then add it to twidth
+ */
+
+ if (gInLine && node->space)
+ twidth += inter_word_space;
+
+ /*
+ * Now what we should do is find all the things after us that have no
+ * space in front and add there width on.
+ */
+
+ nextwidth = total_width(node->next, Endtokens);
+
+
+ /*
+ * Should we start a new line?
+ */
+
+ if (text_x + twidth + nextwidth > right_margin && gInLine) {
+ start_newline(present_line_height, node);
+ if (gInAxiomCommand) {
+ text_x = indent + spadcom_indent;
+ }
+ else
+ text_x = indent;
+ }
+
+ /*
+ * Now see if we am on the beginning of a line, and if not add some space
+ * if we need to
+ */
+
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+
+ node->x = text_x;
+ node->y = text_y - word_off_height;
+ text_x += incwidth;
+ gInLine = 1;
+}
+
+static void
+compute_verbatim_extent(TextNode *node)
+{
+ node->height = normal_text_height;
+ node->width = strlen(node->data.text);
+
+ node->x = text_x;
+ node->y = text_y - word_off_height;
+ gInLine = 1;
+ return;
+}
+
+static void
+compute_spadsrctxt_extent(TextNode *node)
+{
+ node->height = normal_text_height;
+ node->width = strlen(node->data.text);
+
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->x = text_x;
+ node->y = text_y - word_off_height;
+ gInLine = 1;
+ return;
+}
+
+static void
+compute_dash_extent(TextNode *node)
+{
+ int num_dashes;
+ int twidth;
+ int nextwidth;
+
+ node->height = normal_text_height;
+
+ 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 (gInLine && node->space)
+ twidth += inter_word_space;
+
+ /*
+ * Now what we should do is find all the things after us that have no
+ * space in front and add there width on.
+ */
+
+ nextwidth = total_width(node->next, Endtokens);
+
+ /*
+ * Should we start a new line?
+ */
+
+ if (text_x + twidth + nextwidth > right_margin) {
+ start_newline(present_line_height, node);
+ if (gInAxiomCommand) {
+ text_x = indent + spadcom_indent;
+ }
+ else
+ text_x = indent;
+ }
+
+ /*
+ * Now see if we am on the beginning of a line, and if not add some space
+ * if we need to
+ */
+
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+
+ node->x = text_x;
+ if (num_dashes > 1)
+ node->y = text_y - dash_y;
+ else
+ node->y = text_y - word_off_height;
+ text_x += node->width;
+ gInLine = 1;
+ return;
+}
+
+void
+compute_text_extent(TextNode *node)
+{
+ for (; node != NULL; node = node->next) {
+ switch (node->type) {
+ case Endpastebutton:
+ endpastebutton_extent(node);
+ break;
+ case Paste:
+ compute_paste_extent(node);
+ break;
+ case Endpaste:
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ break;
+ case Pastebutton:
+ compute_pastebutton_extent(node);
+ break;
+ case Ifcond:
+ compute_ifcond_extent(node);
+ break;
+ case Fi:
+ break;
+ case Endif:
+ if (if_node == NULL) {
+ return;
+ }
+ else
+ endif_extent(node);
+ break;
+ case Endcenter:
+ start_newline(present_line_height, node->next);
+ pop_group_stack();
+ text_x = indent;
+ break;
+ case Pound:
+ case Macro:
+ /* check to see if we had space in front of me, if so add it */
+
+ if (node->space && gInLine)
+ text_x += inter_word_space;
+ break;
+ case Punctuation:
+ compute_punctuation_extent(node);
+ break;
+ case Endmath:
+ break;
+ case Endverbatim:
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ break;
+ case Spadsrctxt:
+ compute_spadsrctxt_extent(node);
+ break;
+ case Math:
+ compute_word_extent(node);
+ break;
+ case Verbatim:
+ compute_verbatim_extent(node);
+ break;
+ case WindowId:
+ case Word:
+ case Lsquarebrace:
+ case Rsquarebrace:
+ compute_word_extent(node);
+ break;
+ case Dash:
+ compute_dash_extent(node);
+ break;
+ case HSpace:
+ node->height = line_height;
+ node->x = text_x;
+ node->y = text_y;
+ if (gInLine) {
+ text_x +=
+ (node->data.node != NULL ? atoi(node->data.node->data.text) : 1);
+ }
+ break;
+ case VSpace:
+ node->height = line_height;
+ node->x = text_x;
+ node->y = text_y + present_line_height;;
+ text_y +=
+ (node->data.node != NULL ? atoi(node->data.node->data.text) : 1) +
+ present_line_height;
+ past_line_height = (node->data.node != NULL ?
+ atoi(node->data.node->data.text) : 1)
+ + present_line_height;
+
+ present_line_height = line_height;
+ break;
+ case Space:
+ node->height = line_height;
+ node->x = text_x;
+ node->y = text_y;
+ text_x += (gTopOfGroupStack->cur_font->max_bounds.width) *
+ (node->data.node != NULL ? atoi(node->data.node->data.text) : 1);
+ break;
+ case Tab:
+ node->height = line_height;
+ text_x = indent + (gTopOfGroupStack->cur_font->max_bounds.width) *
+ (node->data.node != NULL ? atoi(node->data.node->data.text) : 1);
+ gInLine = 0;
+ break;
+ case Par:
+ node->height = line_height;
+ if (gInItem)
+ text_x = indent;
+ else
+ text_x = indent + paragraph_space;
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ }
+ break;
+ case Newline:
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ break;
+ case Horizontalline:
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->height = line_height;
+ gInLine = 0;
+ node->y = text_y - line_height / 2;
+ node->x = text_x;
+ start_newline(present_line_height, node);
+ break;
+ case Center:
+ compute_center_extent(node);
+ break;
+ case Box:
+ compute_box_extent(node);
+ break;
+ case Mbox:
+ compute_mbox_extent(node);
+ break;
+ case Beginitems:
+ case Begintitems:
+ compute_begin_items_extent(node);
+ break;
+ case Enditems:
+ case Endtitems:
+ pop_item_stack();
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ }
+ text_x = indent;
+ break;
+ case Titem:
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ }
+ text_x = indent - item_space;
+ break;
+ case Item:
+ compute_item_extent(node);
+ break;
+ case Mitem:
+ compute_mitem_extent(node);
+ break;
+ case Upbutton:
+ case Returnbutton:
+ case Memolink:
+ case Downlink:
+ case Link:
+ case Windowlink:
+ compute_button_extent(node);
+ break;
+ case Unixlink:
+ case Lisplink:
+ case Lispwindowlink:
+ case Spadcall:
+ case Spadcallquit:
+ case Qspadcall:
+ case Qspadcallquit:
+ case LispDownLink:
+ case LispMemoLink:
+ case Lispcommand:
+ case Lispcommandquit:
+ case Spadlink:
+ case Spaddownlink:
+ case Spadmemolink:
+ case Unixcommand:
+ compute_button_extent(node);
+ break;
+ case Endbutton:
+ endbutton_extent(node);
+ break;
+ case Endlink:
+ if (link_node == NULL)
+ return;
+ else
+ endbutton_extent(node);
+ break;
+ case Spadsrc:
+ compute_spadsrc_extent(node);
+ break;
+ case Spadcommand:
+ case Spadgraph:
+ compute_spadcommand_extent(node);
+ break;
+ case Endspadsrc:
+ end_spadsrc_extent(node);
+ break;
+ case Endspadcommand:
+ end_spadcommand_extent(node);
+ break;
+ case Indent:
+ indent = left_margin +
+ atoi(node->data.node->data.text) *
+ (gTopOfGroupStack->cur_font->max_bounds.width);
+ if (!gInLine)
+ text_x = indent;
+ break;
+ case Indentrel:
+ indent += atoi(node->data.node->data.text) *
+ (gTopOfGroupStack->cur_font->max_bounds.width);
+ if (!gInLine)
+ text_x = indent;
+ break;
+ case Group:
+ push_group_stack();
+ node->y = text_y;
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ break;
+ case Endgroup:
+ pop_group_stack();
+ break;
+ case Tableitem:
+ push_group_stack();
+ node->y = text_y;
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ break;
+ case Endtableitem:
+ pop_group_stack();
+ return;
+ case Controlbitmap:
+ case Inputbitmap:
+ if (node->width == -1)
+ insert_bitmap_file(node);
+ compute_image_extent(node);
+ break;
+ case Inputpixmap:
+ if (node->width == -1)
+ insert_pixmap_file(node);
+ compute_image_extent(node);
+ break;
+ case Table:
+ compute_table_extent(&node);
+ break;
+ case BoldFace:
+ compute_bf_extent(node);
+ break;
+ case Emphasize:
+ compute_em_extent(node);
+ break;
+ case It:
+ compute_it_extent(node);
+ break;
+ case Rm:
+ case Sl:
+ case Tt:
+ compute_rm_extent(node);
+ break;
+ case Inputstring:
+ compute_input_extent(node);
+ break;
+ case SimpleBox:
+ case Radiobox:
+ compute_ir_extent(node);
+ break;
+ case Endbox:
+ text_x += box_width;
+ break;
+ case Endmacro:
+ case Endparameter:
+ break;
+ case Description:
+ bf_top_group();
+ break;
+ case Enddescription:
+ pop_group_stack();
+ if (gInDesc)
+ return;
+ break;
+ case Endscrolling:
+
+ /*
+ * What we should do here is if we am in the middle of a line, we
+ * should end it here an now.
+ */
+
+ if (gInLine)
+ start_newline(present_line_height, node);
+ break;
+ case Noop:
+ noop_count++;
+ break;
+ case Endinputbox:
+ case Endheader:
+ case Endtitle:
+ case Endfooter:
+ case Rbrace:
+ case Free:
+ case Bound:
+ case Beep:
+ case 0:
+ break;
+ default:
+ fprintf(stderr, "Compute_text_extent: Unknown node type %d\n",
+ node->type);
+ break;
+ }
+ }
+}
+
+static void
+compute_begin_items_extent(TextNode * node)
+{
+ int store_x, store_y, lh;
+
+ /*
+ * This routine pushes the current item_stack, and then tries to set the
+ * item_indent, and the indent level. It checks for an optional argument
+ * to begin{items} and if found uses its width.
+ */
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ }
+ store_x = text_x, store_y = text_y, lh = present_line_height;
+ text_x = indent;
+ push_item_stack();
+ gInItem++;
+ item_indent = indent;
+ if (node->data.node != NULL) {
+ /* we have a desc */
+ gInDesc = 1;
+ compute_text_extent(node->data.node);
+ gInDesc = 0;
+ item_space = text_width(node->data.node, Enddescription);
+ text_x = store_x;
+ text_y = store_y;
+ present_line_height = lh;
+ indent = item_indent + item_space;
+ }
+ else
+ indent = item_indent + 30;
+ gInLine = 0;
+}
+
+static void
+compute_item_extent(TextNode * node)
+{
+ if (gInLine)
+ start_newline(present_line_height, node);
+ text_x = item_indent;
+}
+
+static void
+compute_mitem_extent(TextNode *node)
+{
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ }
+ text_x = item_indent;
+}
+
+static void
+endif_extent(TextNode *node)
+{
+ /*
+ * This node has the responsibilty for updating text_x and text_y so that
+ * they are the maxaimum width of teh else and then statements
+ */
+
+ text_x = if_node->x;
+ text_y = if_node->y;
+ if_node = NULL;
+}
+
+static void
+compute_ifcond_extent(TextNode *node)
+{
+ TextNode *condnode = node->data.ifnode->cond;
+ TextNode *tln = gLineNode;
+ int store_x = text_x, store_y = text_y, lh = present_line_height;
+ int then_x, then_y;
+
+ /*
+ * This routine checks the value of the condition and swaps in the else
+ * or the then depending
+ */
+
+ /*
+ * we have to compute the maximum width and height of the rest of the
+ * text and stuff
+ */
+ push_group_stack();
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ compute_text_extent(node->data.ifnode->thennode);
+ then_x = text_x;
+ then_y = text_y;
+ text_x = store_x;
+ text_y = store_y;
+ present_line_height = lh;
+ gLineNode = tln;
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ compute_text_extent(node->data.ifnode->elsenode);
+ /* Now choose the best one that is biggest and put it into ifnode */
+ if (then_y > text_y) {
+ node->y = then_y;
+ node->x = then_x;
+ }
+ else if (text_y > then_y) {
+ node->y = text_y;
+ node->x = text_x;
+ }
+ else if (text_x > then_x) {
+ node->y = text_y;
+ node->x = text_x;
+ }
+ else {
+ node->y = then_y;
+ node->x = then_x;
+ }
+ /* restore everything */
+ text_x = store_x;
+ text_y = store_y;
+ present_line_height = lh;
+ gLineNode = tln;
+ node->width = 0;
+
+ if_node = node;
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ if (check_condition(condnode)) {
+ node->next = node->data.ifnode->thennode;
+ }
+ else {
+ node->next = node->data.ifnode->elsenode;
+ }
+ pop_group_stack();
+}
+
+static void
+compute_center_extent(TextNode * node)
+{
+ if (gInLine)
+ start_newline(present_line_height, node);
+
+ center_top_group();
+
+ if (gLineNode)
+ text_x = indent;
+ else {
+ fprintf(stderr, "(HyperDoc) Internal error: unexpected state in compute_center_extent.\n");
+ exit(-1);
+ }
+}
+
+static void
+compute_bf_extent(TextNode *node)
+{
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ node->x = text_x;
+ node->y = text_y;
+ bf_top_group();
+}
+
+static void
+compute_em_extent(TextNode *node)
+{
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ node->x = text_x;
+ node->y = text_y;
+ if (gTopOfGroupStack->cur_font == gEmFont)
+ rm_top_group();
+ else
+ em_top_group();
+}
+
+static void
+compute_it_extent(TextNode *node)
+{
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ node->x = text_x;
+ node->y = text_y;
+}
+
+static void
+compute_rm_extent(TextNode *node)
+{
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ node->x = text_x;
+ node->y = text_y;
+ rm_top_group();
+}
+
+static void
+compute_button_extent(TextNode *node)
+{
+ int twidth;
+ /*int store_x = text_x;*/
+ /*int store_y = text_y;*/
+ /*int lh = present_line_height;*/
+
+ push_active_group();
+
+ /* First see if we should leave a little space in front of myself * */
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+
+ twidth = text_width(node->next, Endbutton);
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ if (text_x + twidth > right_margin && gInLine) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->x = text_x;
+ node->y = text_y;
+ link_node = node;
+}
+
+static void
+endbutton_extent(TextNode *node)
+{
+ int temp;
+ int height;
+ int twidth;
+ int y;
+ int maxx;
+
+ maxx = max_x(link_node, Endbutton);
+ link_node->width = twidth = text_width(link_node->next, Endbutton);
+ height = link_node->y;
+ temp = text_height(link_node->next, Endbutton);
+ link_node->height = temp - link_node->y + line_height;
+
+ if (gInLine)
+ y = text_y;
+ else
+ y = text_y - past_line_height;
+ if (y > height) {
+ link_node->y = temp; /* height + link_node->height -
+ * normal_text_height; */
+ link_node->width = maxx - indent;
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ }
+ else {
+ link_node->width = twidth;
+ link_node->y = text_y + link_node->height - line_height;
+ }
+ pop_group_stack();
+ link_node = NULL;
+}
+
+static void
+compute_pastebutton_extent(TextNode *node)
+{
+ int twidth;
+
+ push_active_group();
+
+ /*
+ First see if we should leave a little space in front of myself * */
+
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+
+ twidth = text_width(node->next, Endpastebutton);
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ if (text_x + twidth > right_margin && gInLine) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->x = text_x;
+ node->y = text_y;
+ paste_node = node;
+ return;
+}
+
+static void
+endpastebutton_extent(TextNode *node)
+{
+ int temp;
+ int height;
+ int twidth;
+
+ paste_node->width = twidth = text_width(paste_node->next, Endpastebutton);
+ height = paste_node->y;
+ temp = text_height(paste_node->next, Endpastebutton);
+ paste_node->height = temp - paste_node->y + line_height;
+ if (text_y > height) {
+ paste_node->y = temp;
+ paste_node->width = right_margin - indent;
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ }
+ else {
+ paste_node->width = twidth;
+ paste_node->y = text_y + paste_node->height - line_height;
+ }
+ pop_group_stack();
+ paste_node = NULL;
+ gInLine = 1;
+}
+
+static void
+compute_paste_extent(TextNode *node)
+{
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->x = text_x;
+ node->y = text_y;
+ node->height = line_height;
+}
+
+/* Compute the text extent of a spadcommand node */
+
+static void
+compute_spadcommand_extent(TextNode *node)
+{
+ /*
+ * From now on if there is an example which will take over a line, then
+ * it will start and end with a newline
+ */
+
+ /*int height;*/
+ int t_width;
+ /*int store_x = text_x;*/
+ /*int store_y = text_y;*/
+ /*int lh = present_line_height;*/
+
+ gInAxiomCommand = 1;
+
+ push_spad_group();
+
+ /* Check to see if we should space in front of myself */
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+ t_width = text_width(node->next, Endspadcommand);
+ if (gInLine && ((text_x + t_width) > right_margin)) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->x = text_x;
+ node->y = text_y;
+ spad_node = node;
+
+}
+
+static void
+compute_spadsrc_extent(TextNode *node)
+{
+ /*
+ * From now on if there is an example which will take over a line, then
+ * it will start and end with a newline
+ */
+
+ /*int store_x = text_x;*/
+ /*int store_y = text_y;*/
+ /*int lh = present_line_height;*/
+
+ gInAxiomCommand = 1;
+
+ push_spad_group();
+
+ if (gInLine) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->x = text_x;
+ node->y = text_y;
+ spad_node = node;
+
+}
+
+static void
+end_spadcommand_extent(TextNode *node)
+{
+ int temp;
+ int height;
+ int twidth;
+ int maxx;
+ /*int y = (gInLine) ? (text_y) : (text_y - past_line_height);*/
+
+ maxx = max_x(spad_node, Endspadcommand);
+ twidth = spad_node->width = text_width(spad_node->next, Endspadcommand);
+ height = spad_node->y;
+ temp = text_height(spad_node->next, Endspadcommand);
+
+ spad_node->height = temp - height + line_height;
+ if (text_y > height && gInLine) {
+ spad_node->y = temp;
+ spad_node->width = maxx - indent;
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ else {
+ spad_node->width = twidth;
+ spad_node->y = text_y - line_height + spad_node->height;
+ }
+ pop_group_stack();
+ gInAxiomCommand = 0;
+ spad_node = NULL;
+}
+
+static void
+end_spadsrc_extent(TextNode *node)
+{
+ int temp;
+ int height;
+ int twidth;
+ int maxx;
+ int y = (gInLine) ? (text_y) : (text_y - past_line_height);
+
+ maxx = max_x(spad_node, Endspadsrc);
+
+ twidth = spad_node->width = text_width(spad_node->next, Endspadsrc);
+ height = spad_node->y;
+ temp = text_height(spad_node->next, Endspadsrc);
+ spad_node->height = temp - height + line_height;
+ if (y > height && gInLine) {
+ spad_node->y = temp;
+ spad_node->width = maxx - indent;
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ else {
+ spad_node->width = twidth;
+ spad_node->y = text_y - line_height + spad_node->height;
+ }
+ pop_group_stack();
+ gInAxiomCommand = 0;
+ spad_node = NULL;
+}
+
+static void
+compute_mbox_extent(TextNode *node)
+{
+
+ node->width = text_width(node->next, Endmbox);
+ if (node->space)
+ text_x += inter_word_space;
+ if (text_x + node->width > right_margin) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->x = text_x;
+ node->y = text_y;
+}
+
+static void
+compute_box_extent(TextNode *node)
+{
+ int t_width;
+
+ /*
+ * First thing we do is see if we need to skip some space in front of the
+ * word
+ */
+
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+
+ /* Calculate the actual width of the box */
+
+ t_width = text_width(node->next, Endbox) + 2 * box_width;
+
+ if (text_x + t_width > right_margin) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->x = text_x;
+ text_x = text_x + box_width;
+ node->y = text_y - 2;
+ node->width = t_width;
+ node->height = line_height - 2;
+ gInLine = 1;
+}
+
+static void
+compute_ir_extent(TextNode *node)
+{
+ int t_width;
+
+ /*
+ * First thing we do is see if we need to skip some space in front of the
+ * word
+ */
+
+ if (gInLine && node->space)
+ text_x += inter_word_space;
+
+ /* Calculate the actual width of the box */
+
+ t_width = node->width;
+
+ if (text_x + t_width > right_margin) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->x = text_x;
+ if (node->height > line_height) {
+ node->height = present_line_height = plh(node->height + inter_line_space);
+ node->y = text_y + node->height - normal_text_height;
+ }
+ else {
+ node->y = text_y - line_height + node->height;
+ }
+ gInLine = 1;
+ text_x += node->width;
+}
+
+/* read a bitmap file into memory */
+
+static void
+compute_image_extent(TextNode *node)
+{
+ if (text_x + node->width > right_margin) {
+ start_newline(present_line_height, node);
+ text_x = indent;
+ }
+ node->x = text_x;
+ if (node->height > line_height) {
+ present_line_height = plh(node->height + inter_line_space);
+ node->y = text_y + node->height - line_height;
+ }
+ else {
+ node->y = text_y - line_height + node->height;
+ }
+ text_x += node->width;
+ gInLine = 1;
+}
+
+/*
+ * compute the coordinates of the entries in a table
+ */
+
+static void
+compute_table_extent(TextNode **node)
+{
+ int num_cols, num_lines;
+ int max_width = 0, node_width, col_width;
+ int x, y, num_entries = 0,/* n=0, */ screen_width, table_top;
+ TextNode *front = *node;
+ TextNode *tn;
+
+ gInTable = 1;
+ front->x = text_x;
+ front->y = text_y;
+ for (tn = front->next; tn->type != Endtable; num_entries++, tn = tn->next) {
+ /* Now we need to scan the table group by group */
+ node_width = text_width(tn->next, Endtableitem);
+ if (node_width > max_width)
+ max_width = node_width;
+ /* Get to the beginning og the next group */
+ for (; tn->type != Endtableitem; tn = tn->next);
+ }
+ col_width = max_width + min_inter_column_space;
+ screen_width = gWindow->width - right_margin_space - indent;
+ num_cols = screen_width / col_width;
+ if (num_cols == 0)
+ num_cols = 1;
+ num_lines = num_entries / num_cols;
+ if (num_entries % num_cols != 0)
+ ++num_lines;
+ if (gInLine) {
+ start_newline(present_line_height, *node);
+ }
+ table_top = text_y;
+ num_cols = num_entries / num_lines;
+ if (num_entries % num_lines != 0)
+ ++num_cols;
+ col_width = screen_width / num_cols;
+ for (tn = front->next, x = 0; x < num_cols; x++)
+ for (y = 0; y < num_lines && tn->type != Endtable; y++) {
+ if (num_cols == 1 && y > 0)
+ text_y += line_height;
+ else
+ text_y = table_top + y * line_height;
+ text_x = indent + x * col_width;
+ gInLine = 0;
+ compute_text_extent(tn->next);
+ for (; tn->type != Endtableitem; tn = tn->next);
+ tn = tn->next;
+ }
+ front->height = num_lines * line_height;
+ front->width = screen_width;
+ text_x = indent;
+ if (num_cols == 1)
+ text_y += line_height;
+ else
+ text_y = table_top + front->height;
+ *node = tn;
+ gInLine = 0;
+}
+
+void
+compute_title_extent(HyperDocPage *page)
+{
+ right_margin_space = non_scroll_right_margin_space;
+ page->title->height = twheight + gWindow->border_width;
+ page->title->x = gWindow->border_width + 2 * twwidth + (int) gWindow->border_width / 2;
+ gLineNode = page->title->next;
+ init_title_extents(page);
+ text_y = top_margin + line_height;
+ compute_text_extent(page->title->next);
+ page->title->height = max(text_height(page->title->next, Endtitle),
+ twheight);
+}
+
+void
+compute_header_extent(HyperDocPage *page)
+{
+
+ /*
+ * Hopefully we will soon be able to actually compute the needed height
+ * for the header here
+ */
+
+ int ty; /* UNUSED */
+
+ gExtentRegion = Header;
+ right_margin_space = non_scroll_right_margin_space;
+ init_extents();
+ ty = text_y = 3 * top_margin + line_height + max(page->title->height, twheight);
+ gLineNode = page->header->next;
+ compute_text_extent(page->header->next);
+ page->header->height = text_height(page->header->next, Endheader);
+ if (page->header->height) {
+ page->header->height += 1 / 2 * line_height;
+ page->top_scroll_margin = (gInLine) ? text_y : text_y - past_line_height;
+ if (!(page->page_flags & NOLINES))
+ page->top_scroll_margin += (int) line_height / 2;
+ page->top_scroll_margin += gWindow->border_width + 2 * top_margin;
+ }
+ else {
+ page->top_scroll_margin = page->title->height + gWindow->border_width +
+ 2 * scroll_top_margin;
+ }
+}
+
+void
+compute_footer_extent(HyperDocPage * page)
+{
+ if (page->footer) {
+ gExtentRegion = Footer;
+ right_margin_space = non_scroll_right_margin_space;
+ init_extents();
+ present_line_height = line_height;
+ text_y = line_height;
+ gLineNode = page->footer->next;
+ compute_text_extent(page->footer->next);
+ page->footer->height = text_height(page->footer->next, Endfooter);
+ if (page->footer->height) {
+ if ((!page->page_flags & NOLINES))
+ page->footer->height += (int) line_height / 2;
+ page->bot_scroll_margin = gWindow->height -
+ page->footer->height - bottom_margin
+ - gWindow->border_width + top_margin;
+ }
+ else
+ page->bot_scroll_margin = gWindow->height;
+ }
+}
+
+void
+compute_scrolling_extent(HyperDocPage *page)
+{
+ /* Check to see if there is a scrolling region */
+
+ if (!page->scrolling) {
+ return;
+ }
+ noop_count = 0;
+
+ /* If there is then compute all the proper locations */
+ gExtentRegion = Scrolling;
+ right_margin_space = non_scroll_right_margin_space + gScrollbarWidth;
+ init_extents();
+ text_y = line_height;
+ gLineNode = page->scrolling->next;
+ compute_text_extent(page->scrolling->next);
+
+ /*
+ * the following is an attempt to fix the bug where one cannot scroll
+ * down to a bitmap that is opened at the bottom of a page.
+ */
+
+ /*
+ * TTT trial if(!gInLine)
+ */
+ if (0) {
+ text_y = text_y - past_line_height;
+ }
+ else if (present_line_height > line_height)
+ text_y = text_y + present_line_height - line_height;
+ page->scrolling->height = text_y;
+
+}