home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / layout / layspace.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  16.4 KB  |  800 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19.  
  20. #include "xp.h"
  21. #include "pa_parse.h"
  22. #include "layout.h"
  23.  
  24.  
  25. #define SPACE_WORD    1
  26. #define SPACE_LINE    2
  27. #define SPACE_BLOCK    3
  28.  
  29. static void lo_AppendSpacerElementToLineList( MWContext *context, lo_DocState *state, 
  30.                                              LO_SpacerStruct *spacer );
  31. static void lo_ParseAttributesForBlockSpacer( MWContext *context, lo_DocState *state, 
  32.                                              LO_SpacerStruct *spacer );
  33. static void lo_LayoutBlockSpacer(MWContext *context, lo_DocState *state, 
  34.                                  LO_SpacerStruct *spacer, Bool relayout);
  35.  
  36. void
  37. lo_ProcessSpacerTag(MWContext *context, lo_DocState *state, PA_Tag *tag)
  38. {
  39.     int32 type;
  40.     int32 size;
  41.     PA_Block buff;
  42.     LO_SpacerStruct *spacer;
  43.     
  44.     spacer = (LO_SpacerStruct*)lo_NewElement(context, state, LO_SPACER, NULL, 0);
  45.     XP_ASSERT(spacer);
  46.     if (!spacer) 
  47.     {
  48.         state->top_state->out_of_memory = TRUE;
  49.         return;
  50.     }
  51.  
  52.     type = SPACE_WORD;
  53.     buff = lo_FetchParamValue(context, tag, PARAM_TYPE);
  54.     if (buff != NULL)
  55.     {
  56.         char *type_str;
  57.  
  58.         PA_LOCK(type_str, char *, buff);
  59.         if (pa_TagEqual("line", type_str))
  60.         {
  61.             type = SPACE_LINE;
  62.         }
  63.         else if (pa_TagEqual("vert", type_str))
  64.         {
  65.             type = SPACE_LINE;
  66.         }
  67.         else if (pa_TagEqual("vertical", type_str))
  68.         {
  69.             type = SPACE_LINE;
  70.         }
  71.         else if (pa_TagEqual("block", type_str))
  72.         {
  73.             type = SPACE_BLOCK;
  74.         }
  75.         PA_UNLOCK(buff);
  76.         PA_FREE(buff);
  77.     }
  78.  
  79.     size = 0;
  80.     buff = lo_FetchParamValue(context, tag, PARAM_SIZE);
  81.     if (buff != NULL)
  82.     {
  83.         char *str;
  84.  
  85.         PA_LOCK(str, char *, buff);
  86.         size = XP_ATOI(str);
  87.         PA_UNLOCK(buff);
  88.         PA_FREE(buff);
  89.         if (size < 1)
  90.         {
  91.             size = 0;
  92.         }
  93.     }    
  94.  
  95.     spacer->size = size;
  96.     spacer->type = (int8) type;
  97.     spacer->tag = tag;
  98.  
  99.     lo_AppendSpacerElementToLineList( context, state, spacer );
  100.     lo_LayoutSpacerElement(context, state, spacer, FALSE);
  101.  
  102.     /*
  103.      * Spacers of size 0 do nothing.
  104.      * Unless they are block spacers that use WIDTH and HEIGHT.
  105.      */
  106.     /*
  107.     if ((size == 0)&&(type != SPACE_BLOCK))
  108.     {
  109.         return;
  110.     }
  111.  
  112.     if (type == SPACE_WORD)
  113.     {
  114.         lo_InsertWordBreak(context, state);
  115.         size = FEUNITS_X(size, context);
  116.         state->x += size;
  117.     }
  118.     else if (type == SPACE_LINE)
  119.     {
  120.         lo_SetSoftLineBreakState(context, state, FALSE, 1);
  121.         size = FEUNITS_Y(size, context);
  122.         state->y += size;
  123.     }
  124.     else if (type == SPACE_BLOCK)
  125.     {
  126.         lo_format_block_spacer(context, state, tag);
  127.     }
  128.     */
  129. }
  130.  
  131. static void lo_AppendSpacerElementToLineList( MWContext *context, lo_DocState *state, LO_SpacerStruct *spacer )
  132. {
  133.     spacer->lo_any.type = LO_SPACER;
  134.     spacer->lo_any.x = state->x;
  135.     spacer->lo_any.y = state->y;
  136.     spacer->lo_any.x_offset = 0;
  137.     spacer->lo_any.y_offset = 0;
  138.     spacer->lo_any.width = 0;
  139.     spacer->lo_any.height = 0;
  140.     spacer->lo_any.line_height = 0;
  141.     spacer->lo_any.ele_id = NEXT_ELEMENT;
  142.     
  143.     lo_AppendToLineList(context, state, (LO_Element*)spacer, 0);
  144. }
  145.  
  146.  
  147. void lo_LayoutSpacerElement(MWContext *context, lo_DocState *state, LO_SpacerStruct *spacer, Bool relayout)
  148. {
  149.     int32 size = spacer->size;
  150.     int8 type = spacer->type;
  151.  
  152.     /*
  153.      * Spacers of size 0 do nothing.
  154.      * Unless they are block spacers that use WIDTH and HEIGHT.
  155.      */
  156.     if ((size == 0)&&(type != SPACE_BLOCK))
  157.     {
  158.         return;
  159.     }
  160.  
  161.     if (type == SPACE_WORD)
  162.     {
  163.         if (!relayout)
  164.             lo_InsertWordBreak(context, state);
  165.  
  166.         size = FEUNITS_X(size, context);
  167.         state->x += size;
  168.     }
  169.     else if (type == SPACE_LINE)
  170.     {
  171.         /* lo_SetSoftLineBreakState(context, state, FALSE, 1); */
  172.         lo_SetLineBreakState(context, state, FALSE, LO_LINEFEED_BREAK_SOFT, 1, relayout);
  173.         size = FEUNITS_Y(size, context);
  174.         state->y += size;
  175.     }
  176.     else if (type == SPACE_BLOCK)
  177.     {
  178.         if (!relayout)
  179.         {
  180.             lo_ParseAttributesForBlockSpacer(context, state, spacer);
  181.         }
  182.         
  183.         lo_LayoutBlockSpacer(context, state, spacer, relayout);
  184.     }
  185.  
  186.     if (!relayout)
  187.     {
  188.         /* We do not want to keep a pointer to the tag around for relayout
  189.            because we have all the information we need in the LO_SPACER
  190.            layout element */
  191.         spacer->tag = NULL;
  192.     }
  193. }
  194.  
  195.  
  196. static void lo_ParseAttributesForBlockSpacer( MWContext *context, lo_DocState *state, LO_SpacerStruct *spacer )
  197. {
  198.     Bool floating;
  199.     int32 alignment;
  200.     int32 val;
  201.     PA_Block buff;
  202.     PA_Tag *tag = spacer->tag;
  203.     char *str;
  204.  
  205.     alignment = LO_ALIGN_BASELINE;
  206.     floating = FALSE;
  207.  
  208.     /*
  209.      * Check for an align parameter
  210.      */
  211.     buff = lo_FetchParamValue(context, tag, PARAM_ALIGN);
  212.     if (buff != NULL)
  213.     {
  214.         PA_LOCK(str, char *, buff);
  215.         alignment = lo_EvalAlignParam(str, &floating);
  216.         PA_UNLOCK(buff);
  217.         PA_FREE(buff);
  218.     }
  219.     spacer->alignment = alignment;
  220.     spacer->floating = floating;    
  221.  
  222.     /*
  223.      * Get the width parameter, in absolute or percentage.
  224.      * If percentage, make it absolute.
  225.      */
  226.     buff = lo_FetchParamValue(context, tag, PARAM_WIDTH);
  227.     if (buff != NULL)
  228.     {
  229.         Bool is_percent;
  230.  
  231.         PA_LOCK(str, char *, buff);
  232.         val = lo_ValueOrPercent(str, &is_percent);
  233.         if (is_percent != FALSE)
  234.         {
  235.             spacer->is_percent_width = TRUE;
  236.             spacer->width = val;            
  237.         }
  238.         else
  239.         {
  240.             spacer->is_percent_width = FALSE;
  241.             val = FEUNITS_X(val, context);
  242.             if (val < 1)
  243.             {
  244.                 val = 1;
  245.             }
  246.             spacer->width = val;
  247.         }        
  248.         PA_UNLOCK(buff);
  249.         PA_FREE(buff);
  250.     }
  251.  
  252.     /*
  253.      * Get the height parameter, in absolute or percentage.
  254.      * If percentage, make it absolute.
  255.      */
  256.     buff = lo_FetchParamValue(context, tag, PARAM_HEIGHT);
  257.     if (buff != NULL)
  258.     {
  259.         Bool is_percent;
  260.  
  261.         PA_LOCK(str, char *, buff);
  262.         val = lo_ValueOrPercent(str, &is_percent);
  263.         if (is_percent != FALSE)
  264.         {
  265.             spacer->is_percent_height = TRUE;
  266.             spacer->height = val;
  267.         }
  268.         else
  269.         {
  270.             spacer->is_percent_height = FALSE;
  271.             val = FEUNITS_Y(val, context);
  272.             if (val < 1)
  273.             {
  274.                 val = 1;
  275.             }
  276.             spacer->height = val;
  277.         }
  278.         PA_UNLOCK(buff);
  279.         PA_FREE(buff);
  280.     }
  281. }
  282.  
  283. static void lo_LayoutBlockSpacer(MWContext *context, lo_DocState *state, LO_SpacerStruct *spacer, Bool relayout)
  284. {
  285.     int32 width = 0;
  286.     int32 height = 0;
  287.     int32 doc_width;
  288.     int32 alignment = spacer->alignment;
  289.     Bool floating = spacer->floating;
  290.     Bool line_break;
  291.     char *str;
  292.     int32 x, y;
  293.     int16 x_offset;
  294.     int32 y_offset;
  295.     int32 baseline_inc, line_inc;    
  296.     LO_TextStruct tmp_text;
  297.     LO_TextInfo text_info;
  298.     LO_Element *eptr;
  299.     PA_Block buff;
  300.  
  301.     x = state->x;
  302.     y = state->y;    
  303.     doc_width = state->right_margin - state->left_margin;
  304.     
  305.     if (spacer->is_percent_width)
  306.     {
  307.         int32 val;
  308.         
  309.         if (state->allow_percent_width == FALSE)
  310.         {
  311.             val = 0;
  312.         }
  313.         else
  314.         {
  315.             val = spacer->width;
  316.             val = doc_width * val / 100;
  317.             if (val < 1)
  318.             {
  319.                 val = 1;
  320.             }
  321.         }
  322.  
  323.         width = val;
  324.     }
  325.     else
  326.     {
  327.         width = spacer->width;
  328.     }
  329.  
  330.     if (spacer->is_percent_height)
  331.     {
  332.         int32 val;
  333.  
  334.         if (state->allow_percent_height == FALSE)
  335.         {
  336.             val = 0;
  337.         }
  338.         else
  339.         {
  340.             val = state->win_height * val / 100;
  341.             if (val < 1)
  342.             {
  343.                 val = 1;
  344.             }
  345.         }
  346.         height = val;
  347.     }
  348.     else
  349.     {
  350.         height = spacer->height;
  351.     }
  352.  
  353.  
  354.     /*
  355.      * All this work is to get the text_info filled in for the current
  356.      * font in the font stack. Yuck, there must be a better way.
  357.      */
  358.     memset (&tmp_text, 0, sizeof (tmp_text));
  359.     buff = PA_ALLOC(1);
  360.     if (buff == NULL)
  361.     {
  362.         state->top_state->out_of_memory = TRUE;
  363.         return;
  364.     }
  365.     PA_LOCK(str, char *, buff);
  366.     str[0] = ' ';
  367.     PA_UNLOCK(buff);
  368.     tmp_text.text = buff;
  369.     tmp_text.text_len = 1;
  370.     tmp_text.text_attr = state->font_stack->text_attr;
  371.     FE_GetTextInfo(context, &tmp_text, &text_info);
  372.     PA_FREE(buff);
  373.  
  374.     /*
  375.      * If both dimentions are bogus, no spacer.
  376.      * If only one dimension bogus, then make it 1.
  377.      */
  378.     if ((width < 1)&&(height < 1))
  379.     {
  380.         return;
  381.     }
  382.     else if (width < 1)
  383.     {
  384.         width = 1;
  385.     }
  386.     else if (height < 1)
  387.     {
  388.         height = 1;
  389.     }
  390.  
  391.  
  392.     /*
  393.      * SEVERE FLOW BREAK!  This may be a floating image,
  394.      * which means at this point we go do something completely
  395.      * different.
  396.      */
  397.     if (floating != FALSE)
  398.     {
  399.         if (alignment == LO_ALIGN_RIGHT)
  400.         {
  401.             if (state->right_margin_stack == NULL)
  402.             {
  403.                 x = state->right_margin - width;
  404.             }
  405.             else
  406.             {
  407.                 x = state->right_margin_stack->margin - width;
  408.             }
  409.             if (x < 0)
  410.             {
  411.                 x = 0;
  412.             }
  413.         }
  414.         else
  415.         {
  416.             x = state->left_margin;
  417.         }
  418.  
  419.         y = -1;
  420.  
  421.         lo_AddMarginStack(state, x, y,
  422.             width, height, 0, 0, 0, alignment);
  423.  
  424.         if (state->at_begin_line != FALSE)
  425.         {
  426.             lo_FindLineMargins(context, state, !relayout);
  427.             state->x = state->left_margin;
  428.         }
  429.  
  430.         return;
  431.     }
  432.  
  433.     /*
  434.      * Will this spacer make the line too wide.
  435.      */
  436.     if ((state->x + width) > state->right_margin)
  437.     {
  438.         line_break = TRUE;
  439.     }
  440.     else
  441.     {
  442.         line_break = FALSE;
  443.     }
  444.  
  445.     /*
  446.      * if we are at the beginning of the line.  There is
  447.      * no point in breaking, we are just too wide.
  448.      * Also don't break in unmapped preformatted text.
  449.      * Also can't break inside a NOBR section.
  450.      */
  451.     if ((state->at_begin_line != FALSE)||
  452.         (state->preformatted == PRE_TEXT_YES)||
  453.         (state->breakable == FALSE))
  454.     {
  455.         line_break = FALSE;
  456.     }
  457.  
  458.     /*
  459.      * break on the spacer if we have
  460.      * a break.
  461.      */
  462.     if (line_break != FALSE)
  463.     {
  464.         if (!relayout)
  465.             lo_SoftLineBreak(context, state, TRUE);
  466.         else
  467.             lo_rl_AddSoftBreakAndFlushLine(context, state);
  468.  
  469.         x = state->x;
  470.         y = state->y;
  471.     }
  472.  
  473.     /*
  474.      * Figure out how to align this spacer.
  475.      * baseline_inc is how much to increase the baseline
  476.      * of previous element of this line.  line_inc is how
  477.      * much to increase the line height below the baseline.
  478.      */
  479.     baseline_inc = 0;
  480.     line_inc = 0;
  481.     x_offset = 0;
  482.     y_offset = 0;
  483.  
  484.     lo_CalcAlignOffsets(state, &text_info, alignment,
  485.         width, height,
  486.         &x_offset, &y_offset, &line_inc, &baseline_inc);
  487.  
  488.     width += x_offset;
  489.     height += y_offset;
  490.  
  491.     /*
  492.      * Change the rest of the line the way lo_AppendToLineList()
  493.      * would if we were adding a real element.
  494.      */
  495.     eptr = state->line_list;
  496.         if (eptr != NULL)
  497.         {
  498.                 while (eptr->lo_any.next != NULL)
  499.                 {
  500.                         eptr->lo_any.y_offset += baseline_inc;
  501.                         eptr = eptr->lo_any.next;
  502.                 }
  503.                 eptr->lo_any.y_offset += baseline_inc;
  504.         }
  505.  
  506.     state->baseline += (intn) baseline_inc;
  507.     state->line_height += (intn) (baseline_inc + line_inc);
  508.  
  509.     /*
  510.      * Clean up state
  511.      */
  512.     state->x = state->x + width;
  513.     state->linefeed_state = 0;
  514.     state->at_begin_line = FALSE;
  515.     state->trailing_space = FALSE;
  516.     state->cur_ele_type = LO_NONE;
  517. }
  518.  
  519. #if 0
  520. void
  521. lo_format_block_spacer(MWContext *context, lo_DocState *state, PA_Tag *tag, Bool relayout)
  522. {
  523.     Bool line_break;
  524.     Bool floating;
  525.     int32 baseline_inc, line_inc;
  526.     int32 alignment;
  527.     int16 x_offset;
  528.     int32 y_offset;
  529.     int32 x, y;
  530.     int32 width, height;
  531.     int32 doc_width;
  532.     int32 val;
  533.     PA_Block buff;
  534.     char *str;
  535.     LO_TextStruct tmp_text;
  536.     LO_TextInfo text_info;
  537.     LO_Element *eptr;
  538.  
  539.     x = state->x;
  540.     y = state->y;
  541.     width = 0;
  542.     height = 0;
  543.     alignment = LO_ALIGN_BASELINE;
  544.     floating = FALSE;
  545.  
  546.     /*
  547.      * Check for an align parameter
  548.      */
  549.     buff = lo_FetchParamValue(context, tag, PARAM_ALIGN);
  550.     if (buff != NULL)
  551.     {
  552.  
  553.         PA_LOCK(str, char *, buff);
  554.         alignment = lo_EvalAlignParam(str, &floating);
  555.         PA_UNLOCK(buff);
  556.         PA_FREE(buff);
  557.     }
  558.  
  559.     doc_width = state->right_margin - state->left_margin;
  560.  
  561.     /*
  562.      * Get the width parameter, in absolute or percentage.
  563.      * If percentage, make it absolute.
  564.      */
  565.     buff = lo_FetchParamValue(context, tag, PARAM_WIDTH);
  566.     if (buff != NULL)
  567.     {
  568.         Bool is_percent;
  569.  
  570.         PA_LOCK(str, char *, buff);
  571.         val = lo_ValueOrPercent(str, &is_percent);
  572.         if (is_percent != FALSE)
  573.         {
  574.             if (state->allow_percent_width == FALSE)
  575.             {
  576.                 val = 0;
  577.             }
  578.             else
  579.             {
  580.                 val = doc_width * val / 100;
  581.                 if (val < 1)
  582.                 {
  583.                     val = 1;
  584.                 }
  585.             }
  586.         }
  587.         else
  588.         {
  589.             val = FEUNITS_X(val, context);
  590.             if (val < 1)
  591.             {
  592.                 val = 1;
  593.             }
  594.         }
  595.         width = val;
  596.         PA_UNLOCK(buff);
  597.         PA_FREE(buff);
  598.     }
  599.  
  600.     /*
  601.      * Get the height parameter, in absolute or percentage.
  602.      * If percentage, make it absolute.
  603.      */
  604.     buff = lo_FetchParamValue(context, tag, PARAM_HEIGHT);
  605.     if (buff != NULL)
  606.     {
  607.         Bool is_percent;
  608.  
  609.         PA_LOCK(str, char *, buff);
  610.         val = lo_ValueOrPercent(str, &is_percent);
  611.         if (is_percent != FALSE)
  612.         {
  613.             if (state->allow_percent_height == FALSE)
  614.             {
  615.                 val = 0;
  616.             }
  617.             else
  618.             {
  619.                 val = state->win_height * val / 100;
  620.                 if (val < 1)
  621.                 {
  622.                     val = 1;
  623.                 }
  624.             }
  625.         }
  626.         else
  627.         {
  628.             val = FEUNITS_Y(val, context);
  629.             if (val < 1)
  630.             {
  631.                 val = 1;
  632.             }
  633.         }
  634.         height = val;
  635.         PA_UNLOCK(buff);
  636.         PA_FREE(buff);
  637.     }
  638.  
  639.     /*
  640.          * All this work is to get the text_info filled in for the current
  641.          * font in the font stack. Yuck, there must be a better way.
  642.          */
  643.     memset (&tmp_text, 0, sizeof (tmp_text));
  644.     buff = PA_ALLOC(1);
  645.     if (buff == NULL)
  646.     {
  647.         state->top_state->out_of_memory = TRUE;
  648.         return;
  649.     }
  650.     PA_LOCK(str, char *, buff);
  651.     str[0] = ' ';
  652.     PA_UNLOCK(buff);
  653.     tmp_text.text = buff;
  654.     tmp_text.text_len = 1;
  655.     tmp_text.text_attr = state->font_stack->text_attr;
  656.     FE_GetTextInfo(context, &tmp_text, &text_info);
  657.     PA_FREE(buff);
  658.  
  659.     /*
  660.      * If both dimentions are bogus, no spacer.
  661.      * If only one dimension bogus, then make it 1.
  662.      */
  663.     if ((width < 1)&&(height < 1))
  664.     {
  665.         return;
  666.     }
  667.     else if (width < 1)
  668.     {
  669.         width = 1;
  670.     }
  671.     else if (height < 1)
  672.     {
  673.         height = 1;
  674.     }
  675.  
  676.  
  677.     /*
  678.      * SEVERE FLOW BREAK!  This may be a floating image,
  679.      * which means at this point we go do something completely
  680.      * different.
  681.      */
  682.     if (floating != FALSE)
  683.     {
  684.         if (alignment == LO_ALIGN_RIGHT)
  685.         {
  686.             if (state->right_margin_stack == NULL)
  687.             {
  688.                 x = state->right_margin - width;
  689.             }
  690.             else
  691.             {
  692.                 x = state->right_margin_stack->margin - width;
  693.             }
  694.             if (x < 0)
  695.             {
  696.                 x = 0;
  697.             }
  698.         }
  699.         else
  700.         {
  701.             x = state->left_margin;
  702.         }
  703.  
  704.         y = -1;
  705.  
  706.         lo_AddMarginStack(state, x, y,
  707.             width, height, 0, 0, 0, alignment);
  708.  
  709.         if (state->at_begin_line != FALSE)
  710.         {
  711.             lo_FindLineMargins(context, state, TRUE);
  712.             state->x = state->left_margin;
  713.         }
  714.  
  715.         return;
  716.     }
  717.  
  718.     /*
  719.      * Will this spacer make the line too wide.
  720.      */
  721.     if ((state->x + width) > state->right_margin)
  722.     {
  723.         line_break = TRUE;
  724.     }
  725.     else
  726.     {
  727.         line_break = FALSE;
  728.     }
  729.  
  730.     /*
  731.      * if we are at the beginning of the line.  There is
  732.      * no point in breaking, we are just too wide.
  733.      * Also don't break in unmapped preformatted text.
  734.      * Also can't break inside a NOBR section.
  735.      */
  736.     if ((state->at_begin_line != FALSE)||
  737.         (state->preformatted == PRE_TEXT_YES)||
  738.         (state->breakable == FALSE))
  739.     {
  740.         line_break = FALSE;
  741.     }
  742.  
  743.     /*
  744.      * break on the spacer if we have
  745.      * a break.
  746.      */
  747.     if (line_break != FALSE)
  748.     {
  749.         lo_SoftLineBreak(context, state, TRUE);
  750.         x = state->x;
  751.         y = state->y;
  752.     }
  753.  
  754.     /*
  755.      * Figure out how to align this spacer.
  756.      * baseline_inc is how much to increase the baseline
  757.      * of previous element of this line.  line_inc is how
  758.      * much to increase the line height below the baseline.
  759.      */
  760.     baseline_inc = 0;
  761.     line_inc = 0;
  762.     x_offset = 0;
  763.     y_offset = 0;
  764.  
  765.     lo_CalcAlignOffsets(state, &text_info, alignment,
  766.         width, height,
  767.         &x_offset, &y_offset, &line_inc, &baseline_inc);
  768.  
  769.     width += x_offset;
  770.     height += y_offset;
  771.  
  772.     /*
  773.      * Change the rest of the line the way lo_AppendToLineList()
  774.      * would if we were adding a real element.
  775.      */
  776.     eptr = state->line_list;
  777.         if (eptr != NULL)
  778.         {
  779.                 while (eptr->lo_any.next != NULL)
  780.                 {
  781.                         eptr->lo_any.y_offset += baseline_inc;
  782.                         eptr = eptr->lo_any.next;
  783.                 }
  784.                 eptr->lo_any.y_offset += baseline_inc;
  785.         }
  786.  
  787.     state->baseline += (intn) baseline_inc;
  788.     state->line_height += (intn) (baseline_inc + line_inc);
  789.  
  790.     /*
  791.      * Clean up state
  792.      */
  793.     state->x = state->x + width;
  794.     state->linefeed_state = 0;
  795.     state->at_begin_line = FALSE;
  796.     state->trailing_space = FALSE;
  797.     state->cur_ele_type = LO_NONE;
  798. }
  799. #endif
  800.