home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / layout / laydisp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  21.3 KB  |  815 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. #include "xp.h"
  20. #include "layout.h"
  21. #include "laylayer.h"
  22. #include "libi18n.h"
  23. #include "xlate.h"
  24. #include "layers.h"
  25.  
  26. #define IL_CLIENT               /* XXXM12N Defined by Image Library clients */
  27. #include "libimg.h"             /* Image Library public API. */
  28.  
  29. #ifdef PROFILE
  30. #pragma profile on
  31. #endif
  32.  
  33. #ifdef XP_MAC
  34. # ifdef XP_TRACE
  35. #  undef XP_TRACE
  36. # endif
  37. # define XP_TRACE(X)
  38. #else
  39. #ifndef XP_TRACE
  40. # define XP_TRACE(X) fprintf X
  41. #endif
  42. #endif /* XP_MAC */
  43.  
  44.  
  45. /* 
  46.  * BUGBUG LAYERS: This is a hack that is currently being used for selection
  47.  * but might be useful elsewhere. Essentially, for extending the selected
  48.  * text, we know exactly how much we want to draw (using FE_DisplaySubtext).
  49.  * Rather than ask for a synchronous refresh of the area and relying on
  50.  * LO_RefreshArea to do the correct drawing (actually, it can't do the
  51.  * correct drawing since it doesn't draw sub-strings), we temporarily replace
  52.  * the painter_func for the layer in question to one that just does the
  53.  * required drawing. We still do a synchronous refresh, but the temporary
  54.  * painter_func is called instead of the one that calls LO_RefreshArea.
  55.  */
  56. typedef struct LO_SelectionHackStruct {
  57.   MWContext *context;
  58.   LO_TextStruct *text;
  59.   int32 start_pos;
  60.   int32 end_pos;
  61.   Bool need_bg;
  62. } LO_SelectionHackStruct;
  63.  
  64. static void
  65. lo_selection_hack_painter_func(void *drawable, 
  66.                                CL_Layer *layer, 
  67.                                FE_Region update_region)
  68. {
  69.     LO_SelectionHackStruct *hack = (LO_SelectionHackStruct *)CL_GetLayerClientData(layer);
  70.  
  71.     FE_SetDrawable(hack->context, drawable);
  72.     
  73.     /* For layers, we don't ever need to clear the background */
  74.     FE_DisplaySubtext(hack->context, FE_VIEW,
  75.                       hack->text, hack->start_pos, hack->end_pos,
  76.                       FALSE);
  77.  
  78.     FE_SetDrawable(hack->context, NULL);
  79. }
  80.  
  81. static void
  82. lo_NormalizeStartAndEndOfSelection(LO_TextStruct *text, int32 *start,
  83.     int32 *end)
  84. {
  85.     int32 p1, p2;
  86.     char *string;
  87.     int n;
  88.     int16 charset;
  89.  
  90.     if (text->ele_attrmask & LO_ELE_SELECTED)
  91.     {
  92.         if (text->sel_start < 0)
  93.         {
  94.             p1 = 0;
  95.         }
  96.         else
  97.         {
  98.             p1 = text->sel_start;
  99.         }
  100.  
  101.         if (text->sel_end < 0)
  102.         {
  103.             p2 = text->text_len - 1;
  104.         }
  105.         else
  106.         {
  107.             p2 = text->sel_end;
  108.         }
  109.  
  110.         PA_LOCK(string, char *, text->text);
  111.  
  112.         /*
  113.          * find beginning of first character
  114.          */
  115.         charset = text->text_attr->charset;
  116.         switch (n = INTL_NthByteOfChar(charset, string, (int)(p1+1)))
  117.         {
  118.         case 0:
  119.         case 1:
  120.             break;
  121.         default:
  122.             p1 -= (n - 1);
  123.             if (p1 < 0)
  124.             {
  125.                 p1 = 0;
  126.             }
  127.             break;
  128.         }
  129.         if (text->sel_start >= 0)
  130.         {
  131.             text->sel_start = p1;
  132.         }
  133.  
  134.         /*
  135.          * find end of last character
  136.          */
  137.         switch (n = INTL_NthByteOfChar(charset, string, (int)(p2+1)))
  138.         {
  139.         case 0:
  140.             break;
  141.         default:
  142.             p2 -= (n - 1);
  143.             if (p2 < 0)
  144.             {
  145.                 p2 = 0;
  146.             }
  147.             /* fall through */
  148.         case 1:
  149.             p2 += INTL_IsLeadByte(charset, string[p2]);
  150.             if (p2 > text->text_len - 1)
  151.             {
  152.                 p2 = text->text_len - 1;
  153.             }
  154.             break;
  155.         }
  156.         if (text->sel_end >= 0)
  157.         {
  158.             text->sel_end = p2;
  159.         }
  160.  
  161.         *start = p1;
  162.         *end = p2;
  163.  
  164.         PA_UNLOCK(text->text);
  165.     }
  166. }
  167.  
  168. #ifdef DEBUG
  169. void
  170. LO_DUMP_RECT(XP_Rect *rect)
  171. {
  172.     XP_TRACE(("Compositing rectangle: [%3d,%3d]  %d x %d\n", rect->left, rect->top,
  173.               rect->right - rect->left, rect->bottom - rect->top));
  174. }
  175. #endif
  176.  
  177. /* 
  178.  * BUGBUG LAYERS: Since we know that lo_DisplaySubtext is only done 
  179.  * for selection, we generate a synchronous composite. This might 
  180.  * not be the right thing to do: maybe we should have an additional
  181.  * argument to the LO_Display routines
  182.  */
  183. void
  184. lo_DisplaySubtext(MWContext *context, LO_TextStruct *text,
  185.                   int32 start_pos, int32 end_pos, Bool need_bg,
  186.                   CL_Layer *sel_layer)
  187. {
  188.     lo_NormalizeStartAndEndOfSelection(text, &start_pos, &end_pos);
  189.     /* If we have to draw, go through the compositor */
  190.     if (context->compositor) {
  191.         XP_Rect rect;
  192.     CL_Layer *layer;
  193.         int32 x_offset, y_offset;
  194.  
  195.         if (!sel_layer)
  196.             layer = CL_FindLayer(context->compositor, LO_BODY_LAYER_NAME);
  197.         else
  198.             layer = sel_layer;
  199.  
  200.         FE_GetTextFrame(context, text, start_pos, end_pos, &rect);
  201.         lo_GetLayerXYShift(layer, &x_offset, &y_offset);
  202.         XP_OffsetRect(&rect, -x_offset, -y_offset);
  203.       
  204.         CL_UpdateLayerRect(context->compositor, layer, &rect, PR_FALSE);
  205.  
  206.         return;
  207.   }                                                      
  208.   else
  209.     /* For layers, we don't ever need to clear the background */
  210.     FE_DisplaySubtext(context, FE_VIEW, text, start_pos, end_pos,
  211.         FALSE);
  212. }
  213.  
  214.  
  215. void
  216. lo_DisplayText(MWContext *context,
  217.     LO_TextStruct *text, Bool need_bg)
  218. {
  219.     int32 p1, p2;
  220.     LO_TextAttr tmp_attr;
  221.     LO_TextAttr *hold_attr;
  222.  
  223.     /* Blinking text elements are placed in a separate layer */
  224.     if (context->compositor && text->text_attr->attrmask & LO_ATTR_BLINK)
  225.     {
  226.         if (! (text->ele_attrmask & LO_ELE_DRAWN))
  227.         {
  228.                /* XXX - If the BLINK is in a layer, we need to create the
  229.                blink layer as a child of that layer, not as a child of
  230.                the _BODY layer. */
  231.             CL_Layer *body_layer =
  232.                 CL_FindLayer(context->compositor, LO_BODY_LAYER_NAME);
  233.             lo_CreateBlinkLayer(context, text, body_layer);
  234.             text->ele_attrmask |= LO_ELE_DRAWN;
  235.         }
  236.  
  237.         /* All blink text drawing is handled by the blink layer's
  238.            painter function.  Don't do any drawing here. */
  239.         return;
  240.     }
  241.  
  242.     if (text->ele_attrmask & LO_ELE_SELECTED)
  243.     {
  244.         lo_NormalizeStartAndEndOfSelection(text, &p1, &p2);
  245.  
  246.         if (p1 > 0)
  247.         {
  248.           /* For layers we don't ever need to clear the background */
  249.             FE_DisplaySubtext(context, FE_VIEW, text,
  250.                 0, (p1 - 1), FALSE);
  251.         }
  252.  
  253.         lo_CopyTextAttr(text->text_attr, &tmp_attr);
  254.         tmp_attr.fg.red = text->text_attr->bg.red;
  255.         tmp_attr.fg.green = text->text_attr->bg.green;
  256.         tmp_attr.fg.blue = text->text_attr->bg.blue;
  257.         tmp_attr.bg.red = text->text_attr->fg.red;
  258.         tmp_attr.bg.green = text->text_attr->fg.green;
  259.         tmp_attr.bg.blue = text->text_attr->fg.blue;
  260.  
  261.         /* lo_CopyTextAttr doesn't copy the FE_Data. In
  262.          * this case, however, we need to copy the FE_Data
  263.          * because otherwise the front end will
  264.          * synthesize a new copy. This assumes that
  265.          * the FE_Data doesn't care about font color.
  266.          */
  267.         tmp_attr.FE_Data = text->text_attr->FE_Data;
  268.  
  269.         hold_attr = text->text_attr;
  270.         text->text_attr = &tmp_attr;
  271.           /* For layers we don't ever need to clear the background */
  272.         FE_DisplaySubtext(context, FE_VIEW, text, p1, p2,
  273.             FALSE);
  274.         text->text_attr = hold_attr;
  275.  
  276.         if (p2 < (text->text_len - 1))
  277.         {
  278.           /* For layers we don't ever need to clear the background */
  279.             FE_DisplaySubtext(context, FE_VIEW, text,
  280.                 (p2 + 1), (text->text_len - 1),
  281.                 FALSE);
  282.         }
  283.     }
  284.     else
  285.     {
  286.       /* For layers we don't ever need to clear the background */
  287.       FE_DisplayText(context, FE_VIEW, text, FALSE);
  288.     }
  289. }
  290.  
  291.  
  292. void
  293. lo_DisplayEmbed(MWContext *context, LO_EmbedStruct *embed)
  294. {
  295.     CL_Layer *layer;
  296.  
  297.     if (! context->compositor) {
  298.         FE_DisplayEmbed(context, FE_VIEW, embed);
  299.         return;
  300.     }
  301.  
  302.     /* Don't ever display hidden embeds */
  303.     if (embed->ele_attrmask & LO_ELE_HIDDEN)
  304.         return;
  305.  
  306.     layer = embed->layer;
  307.     XP_ASSERT(layer);
  308.     if (! layer)                /* Paranoia */
  309.         return;
  310.  
  311.         if (!(embed->ele_attrmask & LO_ELE_DRAWN)) {
  312.             /* Move layer to new position */
  313.             CL_MoveLayer(layer,
  314.                          embed->x + embed->x_offset,
  315.                          embed->y + embed->y_offset);
  316.             CL_SetLayerHidden(layer, PR_FALSE);
  317.             embed->ele_attrmask |= LO_ELE_DRAWN;
  318.         }
  319. }
  320.  
  321. #ifdef JAVA
  322. void
  323. lo_DisplayJavaApp(MWContext *context, LO_JavaAppStruct *java_app)
  324. {
  325.     CL_Layer *layer;
  326.  
  327.     if (! context->compositor) {
  328.         FE_DisplayJavaApp(context, FE_VIEW, java_app);
  329.         return;
  330.     }
  331.  
  332.     layer = java_app->layer;
  333.     XP_ASSERT(layer);
  334.     if (! layer)                /* Paranoia */
  335.         return;
  336.  
  337.         if (!(java_app->ele_attrmask & LO_ELE_DRAWN)) {
  338.             /* Move layer to new position */
  339.             CL_MoveLayer(layer,
  340.                          java_app->x + java_app->x_offset,
  341.                          java_app->y + java_app->y_offset);
  342.             
  343.             /* Now that layer is layed out to its final position, 
  344.                we can display it */
  345.             CL_SetLayerHidden(layer, PR_FALSE);
  346.             java_app->ele_attrmask |= LO_ELE_DRAWN;
  347.         }
  348. }
  349. #endif
  350.  
  351. /* Make the image layer visible and draw the image border.  Should only be called
  352.    if there is a compositor. */
  353. static void
  354. lo_DisplayImage(MWContext *context, LO_ImageStruct *image)
  355. {
  356.     int bw = image->border_width;
  357.  
  358.     XP_ASSERT(context->compositor);
  359.     
  360.     /* Allow the compositor to start drawing the image layer. */
  361.     lo_ActivateImageLayer(context, image);
  362.  
  363.     /* The image border, if present, draws in the parent of the image layer. */
  364.     if (bw) {
  365.         int x = image->x + image->x_offset + bw;
  366.         int y = image->y + image->y_offset + bw;
  367.  
  368.         FE_DisplayBorder(context, FE_VIEW, x - bw, y - bw,
  369.                          image->width + 2 * bw, image->height + 2 * bw, bw,
  370.                          &image->text_attr->fg, LO_SOLID);
  371.     }
  372. }
  373.  
  374. void
  375. lo_DisplayImageWithoutCompositor(MWContext *context, LO_ImageStruct *image)
  376. {
  377.     int bw = image->border_width;
  378.     int x = image->x + image->x_offset + bw;
  379.     int y = image->y + image->y_offset + bw;
  380.     int width = image->width;
  381.     int height = image->height;
  382.  
  383.     /* This routine should only be called in the absence of a compositor. */
  384.     XP_ASSERT(!context->compositor);
  385.     
  386.     /* Handle the TextFE. */
  387.     if (context->type == MWContextText) {
  388.         XL_DisplayTextImage(context, FE_VIEW, image);
  389.         return;
  390.     }
  391.  
  392.     if (image->is_icon) {
  393.         IL_DisplayIcon(context->img_cx, image->icon_number, x, y);
  394.     }
  395.     else {
  396.         int cnv_x = context->convertPixX;
  397.         int cnv_y = context->convertPixY;
  398.  
  399.         IL_DisplaySubImage(image->image_req, x/cnv_x, y/cnv_y, 0, 0,
  400.                            width/cnv_x, height/cnv_y);
  401.     }
  402.  
  403.     if (bw)
  404.         FE_DisplayBorder(context, FE_VIEW, x - bw, y - bw, width + 2 * bw,
  405.                          height + 2 * bw, bw, &image->text_attr->fg, LO_SOLID);
  406. }
  407.  
  408. void
  409. lo_DisplaySubImageWithoutCompositor(MWContext *context, LO_ImageStruct *image,
  410.                                     int32 x, int32 y, uint32 width, uint32 height)
  411. {
  412.     int bw = image->border_width;
  413.     int x_pos = image->x + image->x_offset + bw;
  414.     int y_pos = image->y + image->y_offset + bw;
  415.     int sub_x, sub_y, sub_w, sub_h;
  416.             
  417.     /* This routine should only be called in the absence of a compositor. */
  418.     XP_ASSERT(!context->compositor);
  419.     
  420.     /* Handle the TextFE. */
  421.     if (context->type == MWContextText) {
  422.         XL_DisplayTextImage(context, FE_VIEW, image);
  423.         return;
  424.     }
  425.  
  426.     if (x < x_pos) {
  427.         sub_x = x_pos;
  428.         sub_w = width + x - x_pos;
  429.     }
  430.     else {
  431.         sub_x = x;
  432.         sub_w = width;
  433.     }
  434.  
  435.     if (y < y_pos) {
  436.         sub_y = y_pos;
  437.         sub_h = height + y - y_pos;
  438.     }
  439.     else {
  440.         sub_y = y;
  441.         sub_h = height;
  442.     }
  443.  
  444.     if (x + width > x_pos + image->width)
  445.         sub_w += (x_pos + image->width - x - width);
  446.             
  447.     if (y + height > y_pos + image->height)
  448.         sub_h += (y_pos + image->height - y - height);            
  449.  
  450.     if (sub_w > 0 && sub_h > 0) {
  451.         if (image->is_icon) {
  452.                 IL_DisplayIcon(context->img_cx, image->icon_number,
  453.                                x_pos, y_pos);
  454.         }
  455.         else {
  456.                 int cnv_x = context->convertPixX;
  457.                 int cnv_y = context->convertPixY;
  458.                 
  459.                 IL_DisplaySubImage(image->image_req, x_pos/cnv_x, y_pos/cnv_y,
  460.                                (sub_x - x_pos)/cnv_x, (sub_y - y_pos)/cnv_y,
  461.                                sub_w/cnv_x, sub_h/cnv_y);
  462.         }        
  463.     }
  464.  
  465.     if (bw)
  466.         FE_DisplayBorder(context, FE_VIEW, x - bw, y - bw, width + 2 * bw,
  467.                          height + 2 * bw, bw, &image->text_attr->fg,
  468.                          LO_SOLID);
  469. }
  470.  
  471. /* Should only be called in the absence of a compositor. */
  472. void
  473. lo_ClipImage(MWContext *context, LO_ImageStruct *image,
  474.     int32 x, int32 y, uint32 width, uint32 height)
  475. {
  476.     int32 sub_x, sub_y;
  477.     uint32 sub_w, sub_h;
  478.  
  479.     /*
  480.      * If the two don't overlap, do nothing.
  481.      */
  482.     if (((int32)(image->x + image->x_offset + image->width +
  483.                  2*image->border_width) < x)||
  484.         ((int32)(x + width) < (int32)(image->x + image->x_offset))||
  485.         ((int32)(image->y + image->y_offset + image->height +
  486.               2*image->border_width) < y)||
  487.         ((int32)(y + height) < (int32)(image->y + image->y_offset)))
  488.     {
  489.         return;
  490.     }
  491.  
  492.     if ((image->x + image->x_offset) >= x)
  493.     {
  494.         sub_x = image->x + image->x_offset;
  495.     }
  496.     else
  497.     {
  498.         sub_x = x;
  499.     }
  500.  
  501.     if ((int32)(image->x + image->x_offset + image->width + 2*image->border_width)
  502.         <= (int32)(x + width))
  503.     {
  504.         sub_w = image->x + image->x_offset + image->width +
  505.         2*image->border_width - sub_x;
  506.     }
  507.     else
  508.     {
  509.         sub_w = x + width - sub_x;
  510.     }
  511.  
  512.     if ((image->y + image->y_offset) >= y)
  513.     {
  514.         sub_y = image->y + image->y_offset;
  515.     }
  516.     else
  517.     {
  518.         sub_y = y;
  519.     }
  520.  
  521.     if ((int32)(image->y + image->y_offset + image->height + 2*image->border_width)
  522.         <= (int32)(y + height))
  523.     {
  524.         sub_h = image->y + image->y_offset + image->height +
  525.         2*image->border_width - sub_y;
  526.     }
  527.     else
  528.     {
  529.         sub_h = y + height - sub_y;
  530.     }
  531.  
  532.     if (((int32)sub_w >= (int32)(image->width - 2))&&
  533.         ((int32)sub_h >= (int32)(image->height - 2)))
  534.     {
  535.         lo_DisplayImageWithoutCompositor(context, (LO_ImageStruct *)image);
  536.     }
  537.     else
  538.     {
  539.         lo_DisplaySubImageWithoutCompositor(context, (LO_ImageStruct *)image,
  540.         sub_x, sub_y, sub_w, sub_h);
  541.     }
  542. }
  543.  
  544.  
  545. void
  546. lo_DisplayEdge(MWContext *context, LO_EdgeStruct *edge)
  547. {
  548.     if (edge->visible != FALSE)
  549.     {
  550.         FE_DisplayEdge(context, FE_VIEW, edge);
  551.     }
  552. }
  553.  
  554.  
  555. void
  556. lo_DisplayTable(MWContext *context, LO_TableStruct *table)
  557. {
  558.     FE_DisplayTable(context, FE_VIEW, table);
  559. }
  560.  
  561.  
  562. void
  563. lo_DisplaySubDoc(MWContext *context, LO_SubDocStruct *subdoc)
  564. {
  565.     FE_DisplaySubDoc(context, FE_VIEW, subdoc);
  566. }
  567.  
  568.  
  569. void
  570. lo_DisplayCell(MWContext *context, LO_CellStruct *cell)
  571. {
  572.     /* If this cell is empty, bail */
  573.     if (cell->cell_list == NULL && cell->cell_float_list == NULL)
  574.         return;
  575.  
  576.     if (context->compositor && cell->cell_bg_layer)
  577.             CL_SetLayerHidden(cell->cell_bg_layer, PR_FALSE);
  578.         
  579.     FE_DisplayCell(context, FE_VIEW, cell);
  580. }
  581.  
  582. void
  583. lo_DisplayLineFeed(MWContext *context,
  584.     LO_LinefeedStruct *lfeed, Bool need_bg)
  585. {
  586.     LO_TextAttr tmp_attr;
  587.     LO_TextAttr *hold_attr;
  588.  
  589.     if (lfeed->ele_attrmask & LO_ELE_SELECTED)
  590.     {
  591.         lo_CopyTextAttr(lfeed->text_attr, &tmp_attr);
  592.         tmp_attr.fg.red = lfeed->text_attr->bg.red;
  593.         tmp_attr.fg.green = lfeed->text_attr->bg.green;
  594.         tmp_attr.fg.blue = lfeed->text_attr->bg.blue;
  595.         tmp_attr.bg.red = lfeed->text_attr->fg.red;
  596.         tmp_attr.bg.green = lfeed->text_attr->fg.green;
  597.         tmp_attr.bg.blue = lfeed->text_attr->fg.blue;
  598.         hold_attr = lfeed->text_attr;
  599.         lfeed->text_attr = &tmp_attr;
  600.         FE_DisplayLineFeed(context, FE_VIEW, lfeed, (XP_Bool)need_bg);
  601.         lfeed->text_attr = hold_attr;
  602.     }
  603.     else
  604.     {
  605.         FE_DisplayLineFeed(context, FE_VIEW, lfeed, (XP_Bool)need_bg);
  606.     }
  607. }
  608.  
  609.  
  610. void
  611. lo_DisplayHR(MWContext *context, LO_HorizRuleStruct *hrule)
  612. {
  613.     FE_DisplayHR(context, FE_VIEW, hrule);
  614. }
  615.  
  616.  
  617. void
  618. lo_DisplayBullet(MWContext *context, LO_BulletStruct *bullet)
  619. {
  620.     FE_DisplayBullet(context, FE_VIEW, bullet);
  621. }
  622.  
  623. void
  624. lo_DisplayFormElement(MWContext *context, LO_FormElementStruct *form_element)
  625. {
  626.     CL_Layer *layer;
  627.  
  628.     if (! context->compositor) {
  629.         FE_DisplayFormElement(context, FE_VIEW, form_element);
  630.         return;
  631.     }
  632.  
  633.     layer = form_element->layer;
  634.     XP_ASSERT(layer);
  635.     if (! layer)                /* Paranoia */
  636.         return;
  637.  
  638.         if (!(form_element->ele_attrmask & LO_ELE_DRAWN)) {
  639.             /* Move layer to new position */
  640.             CL_MoveLayer(layer,
  641.                          form_element->x + form_element->x_offset +
  642.              form_element->border_horiz_space,
  643.                          form_element->y + form_element->y_offset +
  644.              form_element->border_vert_space);
  645.             CL_SetLayerHidden(layer, PR_FALSE);
  646.             form_element->ele_attrmask |= LO_ELE_DRAWN;
  647.         }
  648. }
  649.  
  650. void
  651. lo_DisplayElement(MWContext *context, LO_Element *tptr,
  652.                   int32 base_x, int32 base_y,
  653.                   int32 x, int32 y,
  654.                   uint32 width, uint32 height)
  655. {
  656.     LO_Any *any = &tptr->lo_any;
  657.     XP_Rect bbox;
  658.     
  659.     lo_GetElementBbox(tptr, &bbox);
  660.     XP_OffsetRect(&bbox, base_x, base_y);
  661.  
  662.     if (bbox.top >= (int32)(y + height))
  663.         return;
  664.  
  665.     if (bbox.bottom <= y )
  666.         return;
  667.  
  668.     if (bbox.left >= (int32)(x + width))
  669.         return;
  670.  
  671.     if (bbox.right <= x )
  672.         return;
  673.  
  674.     /* Temporarily translate to new coordinate system */
  675.     any->x += base_x;
  676.     any->y += base_y;
  677.  
  678.     switch (tptr->type)
  679.     {
  680.     case LO_TEXT:
  681.         if (tptr->lo_text.text != NULL)
  682.             lo_DisplayText(context, (LO_TextStruct *)tptr, FALSE);
  683.         break;
  684.  
  685.     case LO_LINEFEED:
  686.         lo_DisplayLineFeed(context, (LO_LinefeedStruct *)tptr, FALSE);
  687.         break;
  688.  
  689.     case LO_HRULE:
  690.         lo_DisplayHR(context, (LO_HorizRuleStruct *)tptr);
  691.         break;
  692.  
  693.     case LO_FORM_ELE:
  694.         lo_DisplayFormElement(context, (LO_FormElementStruct *)tptr);
  695.         break;
  696.  
  697.     case LO_BULLET:
  698.         lo_DisplayBullet(context, (LO_BulletStruct *)tptr);
  699.         break;
  700.  
  701.     case LO_IMAGE:
  702.         if (context->compositor) {
  703.             /* Allow the compositor to start drawing the image. */
  704.             lo_DisplayImage(context, (LO_ImageStruct *)tptr);
  705.         }
  706.         else {
  707.             /* There is no compositor, so draw the image directly, with the
  708.                appropriate clip. */
  709.             lo_ClipImage(context,
  710.                          (LO_ImageStruct *)tptr,
  711.                          (x + base_x),
  712.                          (y + base_y), width, height);
  713.         }
  714.         break;
  715.  
  716.     case LO_TABLE:
  717.         lo_DisplayTable(context, (LO_TableStruct *)tptr);
  718.         break;
  719.  
  720.     case LO_EMBED:
  721.         lo_DisplayEmbed(context, (LO_EmbedStruct *)tptr);
  722.         break;
  723.  
  724. #ifdef JAVA
  725.     case LO_JAVA:
  726.         lo_DisplayJavaApp(context, (LO_JavaAppStruct *)tptr);
  727.         break;
  728. #endif
  729.  
  730.     case LO_EDGE:
  731.         lo_DisplayEdge(context, (LO_EdgeStruct *)tptr);
  732.         break;
  733.  
  734.     case LO_CELL:
  735.         /* If this cell is a container for an inflow layer (and
  736.            therefore not a table cell), don't descend into the cell
  737.            because the layer's painter function will handle its
  738.            display. */
  739.         if (((LO_CellStruct*)tptr)->cell_inflow_layer)
  740.             break;
  741.  
  742.         /* cmanske: Order changed - display cell contents FIRST
  743.          * so selection feedback near cell border is not wiped out
  744.          * TODO: This doesn't work for images, which are display
  745.          *  asynchronously. Need to add "observer" to image display
  746.         */
  747.         lo_DisplayCellContents(context, (LO_CellStruct *)tptr,
  748.                                base_x, base_y, x, y, width, height);
  749.         lo_DisplayCell(context, (LO_CellStruct *)tptr);
  750.         break;
  751.  
  752.     case LO_SUBDOC:
  753.     {
  754.         LO_SubDocStruct *subdoc;
  755.         int32 new_x, new_y;
  756.         uint32 new_width, new_height;
  757.         lo_DocState *sub_state;
  758.  
  759.         subdoc = (LO_SubDocStruct *)tptr;
  760.         sub_state = (lo_DocState *)subdoc->state;
  761.  
  762.         if (sub_state == NULL)
  763.         {
  764.             break;
  765.         }
  766.  
  767.         lo_DisplaySubDoc(context, subdoc);
  768.  
  769.         new_x = subdoc->x;
  770.         new_y = subdoc->y;
  771.         new_width = subdoc->x_offset + subdoc->width;
  772.         new_height = subdoc->y_offset + subdoc->height;
  773.  
  774.         new_x = new_x - subdoc->x;
  775.         new_y = new_y - subdoc->y;
  776.         sub_state->base_x = subdoc->x +
  777.             subdoc->x_offset + subdoc->border_width;
  778.         sub_state->base_y = subdoc->y +
  779.             subdoc->y_offset + subdoc->border_width;
  780.         lo_RefreshDocumentArea(context, sub_state,
  781.                                new_x, new_y, new_width, new_height);
  782.     }
  783.     break;
  784.  
  785.     case LO_PARAGRAPH:
  786.     case LO_CENTER:
  787.     case LO_MULTICOLUMN:
  788.     case LO_LIST:
  789.     case LO_DESCTITLE:
  790.     case LO_DESCTEXT:
  791.     case LO_BLOCKQUOTE:
  792.     case LO_HEADING:
  793.     case LO_SPAN:
  794.       /* all non-display, doc-state mutating elements. */
  795.       break;
  796.     case LO_TEXTBLOCK:
  797.       break;
  798.     case LO_FLOAT:
  799.     case LO_LAYER:
  800.       break;
  801.     default:
  802.         XP_TRACE(("lo_DisplayElement(%p) skip element type = %d\n", tptr, tptr->type));
  803.         break;
  804.     }
  805.  
  806.     /* Restore original element's coordinates */
  807.     any->x -= base_x;
  808.     any->y -= base_y;
  809. }
  810.  
  811. #ifdef PROFILE
  812. #pragma profile off
  813. #endif
  814.  
  815.