home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / layout / laylayer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  87.4 KB  |  2,850 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.  
  21. #include "xp.h"
  22. #include "pa_tags.h"
  23. #include "layout.h"
  24. #include "laylayer.h"
  25. #include "layers.h"
  26. #include "libmocha.h"
  27. #include "libevent.h"
  28. #include "prefapi.h"
  29.  
  30. #define IL_CLIENT               /* XXXM12N Defined by Image Library clients */
  31. #include "libimg.h"             /* Image Library public API. */
  32. #include "il_icons.h"           /* Image icon enumeration. */
  33.  
  34. /* Z-order for internal layers within a group layer */
  35. #define Z_CONTENT_LAYERS          -1  /* HTML blocks, images, blinking text, windowless plugins */
  36. #define Z_CELL_BACKGROUND_LAYER   -2  /* Table cell backgrounds */
  37. #define Z_BACKGROUND_LAYER        -3  /* Layer/document backgrounds */
  38.  
  39.  
  40. #ifdef PROFILE
  41. #pragma profile on
  42. #endif
  43.  
  44. extern Bool UserOverride;
  45.  
  46. static MWContext*
  47. lo_get_layer_context(CL_Layer* layer)
  48. {
  49.     lo_AnyLayerClosure *closure = (lo_AnyLayerClosure *)CL_GetLayerClientData(layer);
  50.     return closure->context;
  51. }
  52.  
  53. static lo_TopState*
  54. lo_get_layer_top_state(CL_Layer * layer)
  55. {
  56.     MWContext *context = lo_get_layer_context(layer);
  57.     if (! context)              /* Paranoia */
  58.         return NULL;
  59.  
  60.     return lo_FetchTopState(XP_DOCID(context));
  61. }
  62.  
  63. /**********************
  64.  *
  65.  * BLINK tag-related layering code
  66.  *
  67.  **********************/
  68.  
  69. #define LO_BLINK_RATE 750
  70.  
  71.  
  72. static void
  73. lo_blink_destroy_func(CL_Layer *layer)
  74. {
  75.     CL_RemoveLayerFromGroup(CL_GetLayerCompositor(layer), 
  76.                             layer, LO_BLINK_GROUP_NAME);
  77.     XP_DELETE(CL_GetLayerClientData(layer));
  78. }
  79.  
  80. static void
  81. lo_blink_painter_func(CL_Drawable *drawable, 
  82.                       CL_Layer *layer, 
  83.                       FE_Region update_region)
  84. {
  85.     lo_BlinkLayerClosure *closure;
  86.     int32 layer_x_offset, layer_y_offset;
  87.     LO_TextStruct *text;
  88.     closure = (lo_BlinkLayerClosure *)CL_GetLayerClientData(layer);
  89.     text = closure->text;
  90.  
  91.     /* Temporarily change the text element's position to be layer relative */
  92.     layer_x_offset = CL_GetLayerXOffset(layer);
  93.     layer_y_offset = CL_GetLayerYOffset(layer);
  94.  
  95.     text->x -= layer_x_offset;
  96.     text->y -= layer_y_offset;
  97.     
  98.     FE_SetDrawable(closure->context, drawable);
  99.  
  100.     /* Temporarily turn off the blink attribute so that this text
  101.        will be drawn. */
  102.     text->text_attr->attrmask &= ~LO_ATTR_BLINK;
  103.  
  104.     /* Draw the text element associated with this layer */
  105.     lo_DisplayText(closure->context, text, FALSE);
  106.  
  107.     /* Restore blink attribute */
  108.     text->text_attr->attrmask |= LO_ATTR_BLINK;
  109.  
  110.     text->x += layer_x_offset;
  111.     text->y += layer_y_offset;
  112.  
  113.     FE_SetDrawable(closure->context, NULL);
  114. }
  115.  
  116. static void
  117. lo_blink_callback(void *closure)
  118. {
  119.     MWContext *context = (MWContext *)closure;
  120.  
  121.     if (context->blink_hidden == FALSE) {
  122.         CL_HideLayerGroup(context->compositor, LO_BLINK_GROUP_NAME);
  123.         context->blink_hidden = TRUE;
  124.     }
  125.     else {
  126.         CL_UnhideLayerGroup(context->compositor, LO_BLINK_GROUP_NAME);
  127.         context->blink_hidden = FALSE;
  128.     }
  129.  
  130.     /* Set the next timeout */
  131.     context->blink_timeout = FE_SetTimeout(lo_blink_callback,
  132.                                            (void *)context,
  133.                                            LO_BLINK_RATE);
  134. }
  135.  
  136. void
  137. lo_CreateBlinkLayer (MWContext *context, LO_TextStruct *text,
  138.                      CL_Layer *parent)
  139. {
  140.     CL_Layer *blink_layer;
  141.     lo_BlinkLayerClosure *closure;
  142.     XP_Rect bbox;
  143.     CL_LayerVTable vtable;
  144.     int32 layer_x_offset, layer_y_offset;
  145.     
  146.     /* The layer is the size of the text element */
  147.     bbox.left   = 0;
  148.     bbox.top    = 0;
  149.     bbox.right  = text->width;
  150.     bbox.bottom = text->height;
  151.  
  152.     layer_x_offset = text->x + text->x_offset;
  153.     layer_y_offset = text->y + text->y_offset;
  154.  
  155.     /* Create the client_data */
  156.     closure = XP_NEW_ZAP(lo_BlinkLayerClosure);
  157.     closure->type = LO_BLINK_LAYER;
  158.     closure->context = context;
  159.     closure->text = text;
  160.     
  161.     XP_BZERO(&vtable, sizeof(CL_LayerVTable));    
  162.     vtable.painter_func = (CL_PainterFunc)lo_blink_painter_func;
  163.     vtable.destroy_func = (CL_DestroyFunc)lo_blink_destroy_func;
  164.     
  165.     blink_layer = CL_NewLayer(NULL, layer_x_offset, layer_y_offset,
  166.                               &bbox, &vtable,
  167.                               CL_NO_FLAGS | CL_DONT_ENUMERATE, (void *)closure);
  168.  
  169.     CL_InsertChildByZ(parent, blink_layer, Z_CONTENT_LAYERS);
  170.     CL_AddLayerToGroup(context->compositor, blink_layer, LO_BLINK_GROUP_NAME);
  171.  
  172.     /* If noone has setup the callback yet, start it up */
  173.     if (context->blink_timeout == NULL) {
  174.         context->blink_hidden = FALSE;
  175.         context->blink_timeout = FE_SetTimeout(lo_blink_callback,
  176.                                                (void *)context,
  177.                                                LO_BLINK_RATE);
  178.     }
  179. }
  180.  
  181. /* Update the bounding box of a blink layer to its current text element position. */
  182. static PRBool
  183. lo_blink_update_func(CL_Layer *blink_layer, void *dummy)
  184. {
  185.     lo_BlinkLayerClosure *closure;
  186.     LO_TextStruct *text;
  187.  
  188.     closure = ((lo_BlinkLayerClosure *)CL_GetLayerClientData(blink_layer));
  189.     text = closure->text;
  190.     
  191.     CL_MoveLayer(blink_layer, text->x + text->x_offset, text->y + text->y_offset);
  192.     return PR_TRUE;
  193. }
  194.  
  195. void
  196. lo_UpdateBlinkLayers(MWContext *context)
  197. {
  198.     CL_ForEachLayerInGroup(context->compositor, LO_BLINK_GROUP_NAME,
  199.                            lo_blink_update_func, NULL);
  200. }
  201.  
  202. void
  203. lo_DestroyBlinkers(MWContext *context)
  204. {
  205.     if (context->blink_timeout) {
  206.         FE_ClearTimeout(context->blink_timeout);
  207.         context->blink_timeout = NULL;
  208.     }
  209. }
  210.  
  211. /**********************
  212.  *
  213.  * HTML and background layer code
  214.  *
  215.  **********************/
  216.  
  217. static void
  218. lo_html_destroy_func(CL_Layer *layer)
  219. {
  220.     lo_AnyLayerClosure *closure;
  221.     lo_TopState *top_state = NULL;
  222.  
  223.     closure = (lo_AnyLayerClosure *)CL_GetLayerClientData(layer);
  224.     top_state = lo_FetchTopState(XP_DOCID(closure->context));
  225.     
  226.     XP_DELETE(closure);
  227.  
  228.     if (top_state && top_state->doc_state && 
  229.             top_state->doc_state->selection_layer == layer)
  230.     top_state->doc_state->selection_layer = NULL;
  231. }
  232.  
  233. static void
  234. lo_html_block_destroy_func(CL_Layer *layer)
  235. {
  236.     lo_GroupLayerClosure *closure;
  237.     lo_LayerDocState *layer_state;
  238.     JSObject *obj;
  239.     lo_TopState *top_state = NULL;
  240.     int32 layer_id;
  241.     
  242.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  243.  
  244.     top_state = lo_get_layer_top_state(layer);
  245.  
  246.     layer_state = closure->layer_state;
  247.     if (!layer_state)            /* Paranoia */
  248.         goto done;
  249.     obj = layer_state->mocha_object;
  250.     if (obj) {
  251.         layer_state->mocha_object = NULL;
  252.         ET_DestroyLayer(closure->context, obj);
  253.     }
  254.     layer_id = layer_state->id;
  255.  
  256.     if (top_state->layers[layer_id] == layer_state)
  257.         top_state->layers[layer_id] = NULL;
  258.  
  259.     /* 
  260.      * Don't get rid of the layer associated with this layer_state,
  261.      * since the entire layer tree will be dealt with separately.
  262.      */
  263.     layer_state->layer = NULL;
  264.  
  265.     /* 
  266.      * If this layer corresponds to an inflow layer, its cell
  267.      * will be recycled with the rest of the document.
  268.      */
  269.     if (layer_state->cell && layer_state->cell->cell_inflow_layer)
  270.         layer_state->cell = NULL;
  271.     lo_DeleteLayerState(closure->context, top_state->doc_state, layer_state);
  272.  
  273.   done:
  274.     XP_DELETE(closure);
  275.  
  276.     if (top_state && top_state->doc_state && 
  277.             top_state->doc_state->selection_layer == layer)
  278.     top_state->doc_state->selection_layer = NULL;
  279.  
  280. }
  281.  
  282. typedef struct html_event_closure {
  283.     CL_Layer    *layer;
  284.     CL_Event    *event;
  285. } html_event_closure;
  286.  
  287. static void
  288. lo_html_event_callback(MWContext * pContext, LO_Element * pEle, int32 event,
  289.                      void * pObj, ETEventStatus status)
  290. {
  291.     html_event_closure *event_closure = (html_event_closure *)pObj;
  292.  
  293.     if (status == EVENT_PANIC){
  294.     if (event_closure->event->fe_event)
  295.         XP_FREE(event_closure->event->fe_event);
  296.     XP_FREE(event_closure->event);
  297.     XP_FREE(event_closure);
  298.     return;
  299.     }
  300.  
  301.     if (status == EVENT_OK){
  302.         FE_HandleLayerEvent(pContext, event_closure->layer, 
  303.                             event_closure->event);
  304.     }
  305.  
  306.     if (event_closure->event->fe_event)
  307.     XP_FREE(event_closure->event->fe_event);
  308.     XP_FREE(event_closure->event);
  309.     XP_FREE(event_closure);
  310.     return;
  311. }
  312.  
  313. #define LEFT_BUTTON_DRAG 1
  314. #define RIGHT_BUTTON_DRAG 2
  315.  
  316. static PRBool
  317. lo_html_event_handler_func(CL_Layer *layer,
  318.                            CL_Event *event)
  319. {
  320.     html_event_closure *event_closure;
  321.     JSEvent *jsevent, *jskd_event;
  322.     LO_Element *pElement;
  323.     uint32 event_capture_bit = 0;
  324.     MWContext *context;
  325.     int32 client_x_pos, client_y_pos, layer_id;
  326.     LO_AnchorData *anchor = NULL;
  327.  
  328.     lo_AnyLayerClosure *closure = (lo_AnyLayerClosure *)CL_GetLayerClientData(layer);
  329.  
  330.     if (EDT_IS_EDITOR(closure->context))
  331.     return FE_HandleLayerEvent(closure->context, layer, event);
  332.  
  333.     event_capture_bit |= closure->context->event_bit;
  334.  
  335.     if (closure->context->is_grid_cell) {
  336.         context = closure->context;
  337.     while (context->grid_parent) {
  338.         context = context->grid_parent;
  339.         event_capture_bit |= context->event_bit;
  340.     }
  341.     }
  342.  
  343.     layer_id = (LO_GetLayerType(layer) == LO_GROUP_LAYER) ?
  344.         LO_GetIdFromLayer(closure->context, layer) : LO_DOCUMENT_LAYER_ID;
  345.  
  346.     if ((event->type != CL_EVENT_MOUSE_ENTER) &&
  347.         (event->type != CL_EVENT_MOUSE_LEAVE) &&
  348.         (event->type != CL_EVENT_KEY_FOCUS_GAINED) &&
  349.         (event->type != CL_EVENT_KEY_FOCUS_LOST)) 
  350.         pElement = LO_XYToElement(closure->context, event->x, event->y, 
  351.                       layer);
  352.     else {
  353.         pElement = NULL;
  354.  
  355.     /* These events shouldn't be going to the document. */
  356.     if (layer_id == LO_DOCUMENT_LAYER_ID)    {
  357.         return FE_HandleLayerEvent(closure->context, layer, event);
  358.     }
  359.     }
  360.  
  361.     if (pElement && pElement->type == LO_FORM_ELE) {
  362.     if ((event->x - pElement->lo_form.x - pElement->lo_form.x_offset > pElement->lo_form.width) ||
  363.         (event->x - pElement->lo_form.x - pElement->lo_form.x_offset < 0) ||
  364.         (event->y - pElement->lo_form.y - pElement->lo_form.y_offset > pElement->lo_form.height) ||
  365.         (event->y - pElement->lo_form.y - pElement->lo_form.y_offset < 0)) {
  366.         pElement = NULL;
  367.     }
  368.     }
  369.     
  370.     FE_GetWindowOffset(closure->context, &client_x_pos, &client_y_pos);
  371.  
  372.     jsevent = XP_NEW_ZAP(JSEvent);
  373.     switch (event->type) 
  374.     {
  375.     case CL_EVENT_MOUSE_BUTTON_DOWN:
  376.     if (pElement) {
  377.         if (pElement->type == LO_TEXT)
  378.         anchor = pElement->lo_text.anchor_href;
  379.         if (pElement->type == LO_IMAGE)    {
  380.             anchor = pElement->lo_image.anchor_href;
  381.         }
  382.         
  383.         if (anchor && !(event_capture_bit & EVENT_MOUSEDOWN) 
  384.                 && anchor->event_handler_present != TRUE) {
  385.         XP_FREE(jsevent);
  386.         return FE_HandleLayerEvent(closure->context, layer, event);
  387.         }
  388.     }
  389. #ifdef XP_MAC
  390.     /* the mac sets the data to the number of clicks instead of
  391.        sending a multiclick event */
  392.     if (event->data > 1)
  393.         jsevent->type = EVENT_DBLCLICK;
  394.     else    
  395. #endif /* XP_MAC */
  396.         jsevent->type = EVENT_MOUSEDOWN;
  397.     if (closure->context->js_drag_enabled) {
  398.         CL_GrabMouseEvents(closure->context->compositor, layer);
  399.         if (event->which == 1)
  400.         closure->context->js_dragging |= LEFT_BUTTON_DRAG;
  401.         if (event->which == 3)
  402.         closure->context->js_dragging |= RIGHT_BUTTON_DRAG;
  403.     }
  404.     break;
  405.     case CL_EVENT_MOUSE_BUTTON_UP:
  406.     if (pElement) {
  407.         if (pElement->type == LO_TEXT)
  408.         anchor = pElement->lo_text.anchor_href;
  409.         if (pElement->type == LO_IMAGE)
  410.         anchor = pElement->lo_image.anchor_href;
  411.         
  412.         if (anchor && !(event_capture_bit & EVENT_MOUSEUP) 
  413.                 && anchor->event_handler_present != TRUE) {
  414.         XP_FREE(jsevent);
  415.         return FE_HandleLayerEvent(closure->context, layer, event);
  416.         }
  417.     }
  418.         jsevent->type = EVENT_MOUSEUP;
  419.     if (closure->context->js_dragging) {
  420.         CL_GrabMouseEvents(closure->context->compositor, NULL);
  421.         if (event->which == 1)
  422.         closure->context->js_dragging &= ~LEFT_BUTTON_DRAG;
  423.         if (event->which == 3)
  424.         closure->context->js_dragging &= ~RIGHT_BUTTON_DRAG;
  425.     }
  426.     break;
  427.     case CL_EVENT_MOUSE_BUTTON_MULTI_CLICK:
  428.         jsevent->type = EVENT_DBLCLICK;
  429.     break;
  430.     case CL_EVENT_KEY_DOWN:
  431.     if (!event->data) {
  432.  
  433.         /* Key events are handled a little strangely.  The initial hitting of the
  434.          * key triggers two events, a KEYDOWN event and a KEYPRESS event.  Any
  435.          * key repetition is accomplished through additional KEYPRESS events.  So
  436.          * if this is our first time through, we need to create and send an 
  437.          * additional event.  However, since the main program triggers off of the
  438.          * KEYPRESS only we don't need a callback and closure.
  439.          */
  440.         jskd_event = XP_NEW_ZAP(JSEvent);
  441.         jskd_event->type = EVENT_KEYDOWN;
  442.         jskd_event->x = event->x;
  443.         jskd_event->y = event->y;
  444.         jskd_event->docx = event->x + CL_GetLayerXOrigin(layer);
  445.         jskd_event->docy = event->y + CL_GetLayerYOrigin(layer);
  446.         jskd_event->screenx = jskd_event->docx + client_x_pos 
  447.                 - CL_GetCompositorXOffset(closure->context->compositor);
  448.         jskd_event->screeny = jskd_event->docy + client_y_pos 
  449.                 - CL_GetCompositorXOffset(closure->context->compositor);
  450.         jskd_event->which = event->which;
  451.         jskd_event->modifiers = event->modifiers;
  452.         jskd_event->layer_id = layer_id;
  453.         
  454.         ET_SendEvent(closure->context, pElement, jskd_event, 0, 0);
  455.     }   
  456.         jsevent->type = EVENT_KEYPRESS;
  457.     break;
  458.     case CL_EVENT_KEY_UP:
  459.         jsevent->type = EVENT_KEYUP;
  460.     break;
  461.     case CL_EVENT_MOUSE_ENTER:
  462.         jsevent->type = EVENT_MOUSEOVER;
  463.     break;
  464.     case CL_EVENT_MOUSE_LEAVE:
  465.         jsevent->type = EVENT_MOUSEOUT;
  466.     break;
  467.     case CL_EVENT_MOUSE_MOVE:
  468.     if (event_capture_bit & EVENT_MOUSEMOVE || 
  469.             closure->context->js_dragging==TRUE)
  470.             jsevent->type = EVENT_MOUSEMOVE;
  471.     break;
  472.     case CL_EVENT_KEY_FOCUS_GAINED:
  473.         jsevent->type = EVENT_FOCUS;
  474.         break;
  475.     case CL_EVENT_KEY_FOCUS_LOST:
  476.         jsevent->type = EVENT_BLUR;
  477.         break;
  478.     default:
  479.     XP_FREE(jsevent);
  480.     return FE_HandleLayerEvent(closure->context, layer, event);
  481.     }
  482.     
  483.     if (!jsevent->type) {
  484.     XP_FREE(jsevent);
  485.     return FE_HandleLayerEvent(closure->context, layer, event);
  486.     }
  487.  
  488.     jsevent->x = event->x;
  489.     jsevent->y = event->y;
  490.     jsevent->docx = event->x + CL_GetLayerXOrigin(layer);
  491.     jsevent->docy = event->y + CL_GetLayerYOrigin(layer);
  492.     jsevent->screenx = jsevent->docx + client_x_pos 
  493.         - CL_GetCompositorXOffset(closure->context->compositor);
  494.     jsevent->screeny = jsevent->docy + client_y_pos 
  495.         - CL_GetCompositorYOffset(closure->context->compositor);
  496.     jsevent->which = event->which;
  497.     jsevent->modifiers = event->modifiers;
  498.     jsevent->layer_id = layer_id;
  499.     
  500.     /* This probably isn't the best place for these but I don't want to 
  501.      * put the setting of all of these at the top of the function because
  502.      * of possible early returns and since this is part of the event loop 
  503.      * I'm trying to be stingy with cycles.
  504.      */
  505.     if (jsevent->type == EVENT_FOCUS || jsevent->type == EVENT_BLUR) {
  506.     jsevent->docx = 0;
  507.     jsevent->docy = 0;
  508.     jsevent->screenx = 0;
  509.     jsevent->screeny = 0;
  510.     jsevent->which = 0;
  511.     }
  512.     if (jsevent->type == EVENT_MOUSEOVER || jsevent->type == EVENT_MOUSEOUT) {
  513.     jsevent->which = 0;
  514.     }
  515.     
  516.     event_closure = XP_NEW_ZAP(html_event_closure);
  517.     event_closure->layer = layer;
  518.     event_closure->event = XP_NEW_ZAP(CL_Event);
  519.     XP_MEMCPY(event_closure->event, event, sizeof(CL_Event));
  520.     if (event->fe_event) {
  521.     event_closure->event->fe_event = XP_ALLOC(event->fe_event_size);
  522.     XP_MEMCPY(event_closure->event->fe_event, event->fe_event, event->fe_event_size);
  523.     }
  524.  
  525.     ET_SendEvent(closure->context, pElement, jsevent, lo_html_event_callback, event_closure);
  526.  
  527.     return PR_TRUE;
  528. }
  529.  
  530. static PRBool
  531. lo_html_inflow_layer_event_handler_func(CL_Layer *layer,
  532.                                         CL_Event *event)
  533. {
  534. /* XXX - Doesn't work yet */
  535. #if 0
  536.     lo_LayerClosure *closure = (lo_LayerClosure *)CL_GetLayerClientData(layer);
  537.     CL_Layer *parent = CL_GetLayerParent(layer);
  538.     int32 x_offset = closure->u.block_closure.x_offset;
  539.     int32 y_offset = closure->u.block_closure.y_offset;
  540.     event->x += x_offset;
  541.     event->y += y_offset;
  542.     if (lo_html_event_handler_func(parent, event))
  543.         return PR_TRUE;
  544.     event->x += x_offset;
  545.     event->y += y_offset;
  546. #endif
  547.     return PR_FALSE;
  548. }
  549.  
  550. static PRBool
  551. lo_is_document_layer(CL_Layer * layer)
  552. {
  553.     lo_TopState *top_state = lo_get_layer_top_state(layer);
  554.     return (PRBool)(top_state->doc_layer == layer);
  555. }
  556.  
  557. /* Callback that tells the front-end to expand the scrollable extent
  558.    of the document to encompass the _DOCUMENT layer. */
  559. static void
  560. doc_bbox_changed_func(CL_Layer *layer, XP_Rect *new_bbox)
  561. {
  562.     lo_GroupLayerClosure *closure;
  563.     lo_TopState *top_state = lo_get_layer_top_state(layer);
  564.     lo_LayerDocState *layer_state = top_state->layers[LO_DOCUMENT_LAYER_ID];
  565.  
  566.     int32 width  = new_bbox->right - new_bbox->left;
  567.     int32 height = new_bbox->bottom - new_bbox->top;
  568.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  569.  
  570.     XP_ASSERT(layer_state->id == LO_DOCUMENT_LAYER_ID);
  571.  
  572.     if (layer_state->overrideScrollWidth)
  573.         width = layer_state->contentWidth;
  574.     else
  575.         layer_state->contentWidth = width;
  576.  
  577.     if (layer_state->overrideScrollHeight)
  578.         height = layer_state->contentHeight;
  579.     else
  580.         layer_state->contentHeight = height;
  581.     
  582.     FE_SetDocDimension(closure->context, FE_VIEW, width, height);
  583. }
  584.  
  585. /* Expand a bbox to contain a given layer.
  586.    (Callback for CL_ForEachChildOfLayer(), below.) */
  587. static PRBool
  588. expand_bbox(CL_Layer *layer, void *closure)
  589. {
  590.     XP_Rect layer_bbox;
  591.     XP_Rect *enclosing_bbox = closure;
  592.  
  593.     CL_GetLayerBboxAbsolute(layer, &layer_bbox);
  594.  
  595.     /* Expand the enclosing bbox to encompass the layer. */
  596.     XP_RectsBbox(&layer_bbox, enclosing_bbox, enclosing_bbox);
  597.     return PR_TRUE;
  598. }
  599.  
  600. /* The _BODY layer is treated specially in that if it shrinks, it may
  601.    cause the document to shrink as well.  At the moment, the only case
  602.    in which that happens is when editing a document. */
  603. static void
  604. body_bbox_changed_func(CL_Layer *layer, XP_Rect *new_bbox)
  605. {
  606.     XP_Rect bbox = {0, 0, 0, 0};
  607.     CL_Layer *doc_layer = CL_GetLayerParent(layer);
  608.  
  609.     /* Set the bbox of the document to be the rectangle that encloses
  610.        the BODY layer and all its siblings. */
  611.     CL_ForEachChildOfLayer(doc_layer, expand_bbox, &bbox);
  612.     CL_SetLayerBbox(doc_layer, &bbox);
  613. }
  614.  
  615. lo_LayerDocState *
  616. lo_GetLayerState(CL_Layer *layer)
  617. {
  618.     lo_GroupLayerClosure *closure;
  619.     lo_TopState *top_state;
  620.  
  621.     XP_ASSERT(layer);
  622.     if (! layer)
  623.         return NULL;
  624.         
  625.     top_state = lo_get_layer_top_state(layer);
  626.  
  627.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  628. /*    XP_ASSERT(closure->type == LO_GROUP_LAYER); */
  629.     /* Hack for document layer and body layers, necessary for event handling */
  630.     if ((top_state->body_layer == layer) || 
  631.         (top_state->doc_layer == layer) || 
  632.         (closure->type != LO_GROUP_LAYER))
  633.         return top_state->layers[LO_DOCUMENT_LAYER_ID];
  634.  
  635.     return closure->layer_state;
  636.  
  637. }
  638.  
  639. PRBool
  640. lo_InsideLayer(lo_DocState *state)
  641. {
  642.     int32 layer_id = lo_CurrentLayerId(state);
  643.     if (layer_id != LO_DOCUMENT_LAYER_ID)
  644.         return PR_TRUE;
  645.     return PR_FALSE;
  646. }
  647.  
  648. PRBool
  649. lo_InsideInflowLayer(lo_DocState *state)
  650. {
  651.     lo_LayerDocState *layer_state;
  652.     lo_GroupLayerClosure *closure;
  653.     
  654.     layer_state = lo_CurrentLayerState(state);
  655.     
  656.     if (layer_state->id == LO_DOCUMENT_LAYER_ID)
  657.         return PR_FALSE;
  658.     
  659.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer_state->layer);
  660.     XP_ASSERT(closure->type == LO_GROUP_LAYER);
  661.     if (closure->type != LO_GROUP_LAYER)
  662.         return PR_FALSE;
  663.         
  664.     return closure->is_inflow;
  665. }
  666.  
  667. /* Get XY needed to convert from layer coordinates to layout coordinates */
  668. void
  669. lo_GetLayerXYShift(CL_Layer *layer, int32 *xp, int32 *yp)
  670. {
  671.     lo_GroupLayerClosure *closure;
  672.  
  673.     *xp = 0;
  674.     *yp = 0;
  675.     XP_ASSERT(layer);
  676.     if (! layer)
  677.         return;
  678.         
  679.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  680.     if (closure->type != LO_GROUP_LAYER)
  681.         return;
  682.     
  683.     *xp = closure->x_offset;
  684.     *yp = closure->y_offset;
  685. }
  686.  
  687. void
  688. LO_MoveLayer(CL_Layer *layer, int32 x, int32 y)
  689. {
  690.     CL_Layer *parent_layer;
  691.     lo_GroupLayerClosure *closure, *parent_closure;
  692.     int32 x_offset, y_offset;
  693.  
  694.     XP_ASSERT(layer);
  695.     if (! layer)
  696.         return;
  697.         
  698.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  699.     XP_ASSERT(closure->type == LO_GROUP_LAYER);
  700.     parent_layer = CL_GetLayerParent(layer);
  701.     x_offset = closure->x_offset;
  702.     y_offset = closure->y_offset;
  703.  
  704.     /* Handle special case of inflow layer nested in another inflow layer. */
  705.     if (closure->is_inflow && parent_layer) {
  706.         parent_closure = CL_GetLayerClientData(parent_layer);
  707.         x_offset -= parent_closure->x_offset;
  708.         y_offset -= parent_closure->y_offset;
  709.     }
  710.  
  711.     CL_MoveLayer(layer, x + x_offset, y + y_offset);
  712. }
  713.  
  714. void
  715. LO_SetLayerBbox(CL_Layer *layer, XP_Rect *bbox)
  716. {
  717.     lo_LayerDocState *layer_state = lo_GetLayerState(layer);
  718.     XP_Rect resultBbox;
  719.     XP_IntersectRect(&layer_state->viewRect, bbox, &resultBbox);
  720.     CL_SetLayerBbox(layer, &resultBbox);
  721. }
  722.  
  723. int32
  724. LO_GetLayerXOffset(CL_Layer *layer)
  725. {
  726.     CL_Layer *parent_layer;
  727.     lo_GroupLayerClosure *closure, *parent_closure;
  728.     int32 x_offset;
  729.  
  730.     XP_ASSERT(layer);
  731.     if (! layer)
  732.         return 0;
  733.         
  734.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  735.     XP_ASSERT(closure->type == LO_GROUP_LAYER);
  736.     parent_layer = CL_GetLayerParent(layer);
  737.     x_offset = closure->x_offset;
  738.  
  739.     /* Handle special case of inflow layer nested in another inflow layer. */
  740.     if (closure->is_inflow && parent_layer) {
  741.         parent_closure = CL_GetLayerClientData(parent_layer);
  742.         x_offset -= parent_closure->x_offset;
  743.     }
  744.  
  745.     return CL_GetLayerXOffset(layer) - x_offset;
  746. }
  747.     
  748. int32
  749. LO_GetLayerYOffset(CL_Layer *layer)
  750. {
  751.     CL_Layer *parent_layer;
  752.     lo_GroupLayerClosure *closure, *parent_closure;
  753.     int32 y_offset = 0;
  754.  
  755.     XP_ASSERT(layer);
  756.     if (! layer)
  757.         return 0;
  758.         
  759.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  760.     XP_ASSERT(closure->type == LO_GROUP_LAYER);
  761.     parent_layer = CL_GetLayerParent(layer);
  762.     y_offset = closure->y_offset;
  763.  
  764.     /* Handle special case of inflow layer nested in another inflow layer. */
  765.     if (closure->is_inflow && parent_layer) {
  766.         parent_closure = CL_GetLayerClientData(parent_layer);
  767.         y_offset -= parent_closure->y_offset;
  768.     }
  769.  
  770.     return CL_GetLayerYOffset(layer) - y_offset;
  771. }
  772.  
  773. int32
  774. LO_GetLayerScrollWidth(CL_Layer *layer)
  775. {
  776.     lo_LayerDocState *layer_state;
  777.     XP_ASSERT(layer);
  778.     if (!layer)
  779.         return -1;
  780.     
  781.     layer_state = lo_GetLayerState(layer);
  782.     XP_ASSERT(layer_state);
  783.     if (!layer_state)
  784.         return -1;
  785.     return layer_state->contentWidth;
  786. }
  787.  
  788. int32
  789. LO_GetLayerScrollHeight(CL_Layer *layer)
  790. {
  791.     lo_LayerDocState *layer_state;
  792.     XP_ASSERT(layer);
  793.     if (!layer)
  794.         return -1;
  795.  
  796.     layer_state = lo_GetLayerState(layer);
  797.     XP_ASSERT(layer_state);
  798.     if (!layer_state)
  799.         return -1;
  800.     return layer_state->contentHeight;
  801. }
  802.  
  803. void
  804. LO_SetLayerScrollWidth(CL_Layer *layer, uint32 width)
  805. {
  806.     uint32 height;
  807.     lo_LayerDocState *layer_state;
  808.     XP_ASSERT(layer);
  809.     if (!layer)
  810.         return;
  811.  
  812.     /* The document layer is special.  It's the only one with a
  813.        mutable scroll width and height.*/
  814.     if (!lo_is_document_layer(layer))
  815.         return;
  816.     
  817.     layer_state = lo_GetLayerState(layer);
  818.     layer_state->contentWidth = width;
  819.     layer_state->overrideScrollWidth = PR_TRUE;
  820.     height = layer_state->contentHeight;
  821.     LO_SetDocumentDimensions(lo_get_layer_context(layer), width, height);
  822. }
  823.  
  824. void
  825. LO_SetLayerScrollHeight(CL_Layer *layer, uint32 height)
  826. {
  827.     uint32 width;
  828.     lo_LayerDocState *layer_state;
  829.     XP_ASSERT(layer);
  830.     if (!layer)
  831.         return;
  832.  
  833.     /* The document layer is special.  It's the only one with a
  834.        mutable scroll width and height.*/
  835.     if (!lo_is_document_layer(layer))
  836.         return;
  837.     
  838.     layer_state = lo_GetLayerState(layer);
  839.     layer_state->contentHeight = height;
  840.     layer_state->overrideScrollHeight = PR_TRUE;
  841.     width = layer_state->contentWidth;
  842.     LO_SetDocumentDimensions(lo_get_layer_context(layer), width, height);
  843. }
  844.  
  845. int32
  846. LO_GetLayerWrapWidth(CL_Layer *layer)
  847. {
  848.     lo_GroupLayerClosure *closure;
  849.  
  850.     XP_ASSERT(layer);
  851.     if (! layer)
  852.         return 0;
  853.         
  854.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  855.     XP_ASSERT(closure->type == LO_GROUP_LAYER);
  856.  
  857.     return closure->wrap_width;
  858. }
  859.  
  860. extern void
  861. lo_SetLayerClipExpansionPolicy(CL_Layer *layer, int policy)
  862. {
  863.     lo_GroupLayerClosure *closure;
  864.  
  865.     XP_ASSERT(layer);
  866.     if (! layer)
  867.         return;
  868.         
  869.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  870.     XP_ASSERT(closure->type == LO_GROUP_LAYER);
  871.  
  872.     closure->clip_expansion_policy = policy;
  873. }
  874.  
  875. extern int
  876. lo_GetLayerClipExpansionPolicy(CL_Layer *layer)
  877. {
  878.     lo_GroupLayerClosure *closure;
  879.  
  880.     XP_ASSERT(layer);
  881.     if (! layer)
  882.         return 0;
  883.         
  884.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  885.     XP_ASSERT(closure->type == LO_GROUP_LAYER);
  886.  
  887.     return closure->clip_expansion_policy;
  888. }
  889.  
  890. typedef struct lo_BlockRectStruct
  891. {
  892.     lo_HTMLBlockClosure *closure;
  893.     CL_Layer *layer;
  894. } lo_BlockRectStruct;
  895.  
  896. /* Called for each rectangle in the update region */
  897. static void
  898. lo_block_rect_func(void *closure,
  899.                    XP_Rect *rect)
  900. {
  901.     lo_BlockRectStruct *block_struct = (lo_BlockRectStruct *)closure;
  902.     lo_HTMLBlockClosure *myclosure = block_struct->closure;
  903.     
  904.     /* Intersect the layer to be drawn with the layer's bbox */
  905.     CL_WindowToLayerRect(CL_GetLayerCompositor(block_struct->layer),
  906.                          block_struct->layer, rect);
  907.                       
  908.     lo_DisplayCellContents(myclosure->context,
  909.                myclosure->layer_state->cell, 
  910.                -myclosure->x_offset, 
  911.                -myclosure->y_offset, 
  912.                rect->left, rect->top,
  913.                (rect->right - rect->left),
  914.                (rect->bottom - rect->top));
  915. }
  916.  
  917. /* painter_func for block layers */
  918. static void
  919. lo_block_painter_func(CL_Drawable *drawable, 
  920.                       CL_Layer *layer, 
  921.                       FE_Region update_region)
  922. {
  923.     lo_BlockRectStruct block_struct;
  924.     
  925.     block_struct.closure = (lo_HTMLBlockClosure *)CL_GetLayerClientData(layer);
  926.     block_struct.layer = layer;
  927.     
  928.     FE_SetDrawable(block_struct.closure->context, drawable);
  929.  
  930.     CL_ForEachRectCoveringRegion(update_region, 
  931.                  (FE_RectInRegionFunc)lo_block_rect_func,
  932.                  (void *)&block_struct);
  933.  
  934.     FE_SetDrawable(block_struct.closure->context, NULL);
  935. }
  936.  
  937.  
  938. /* Called for each rectangle in the update region */
  939. static void
  940. lo_body_rect_func(void *closure,
  941.                   XP_Rect *rect)
  942. {
  943.     lo_HTMLBodyClosure *myclosure = (lo_HTMLBodyClosure *)closure;
  944.     
  945.     CL_WindowToLayerRect(myclosure->context->compositor, 
  946.                          myclosure->layer,
  947.                          rect);
  948.     LO_RefreshArea(myclosure->context,
  949.                    rect->left, rect->top,
  950.                    (rect->right - rect->left),
  951.                    (rect->bottom - rect->top));
  952. }
  953.  
  954. /* painter_func for HTML document layers */
  955. static void
  956. lo_body_painter_func(CL_Drawable *drawable, 
  957.                      CL_Layer *layer, 
  958.                      FE_Region update_region)
  959. {
  960.     lo_HTMLBodyClosure *closure;
  961.     
  962.     closure = (lo_HTMLBodyClosure *)CL_GetLayerClientData(layer);
  963.     FE_SetDrawable(closure->context, drawable);
  964.  
  965.     CL_ForEachRectCoveringRegion(update_region, 
  966.                                  (FE_RectInRegionFunc)lo_body_rect_func,
  967.                                  (void *)closure);
  968.  
  969.     FE_SetDrawable(closure->context, NULL);
  970. }
  971.  
  972. /* 
  973.  * Create an grouping layer and make it the parent of the content
  974.  * and background layers specified.
  975.  */
  976. static CL_Layer *
  977. lo_CreateGroupLayer(MWContext *context, char *name,
  978.                     int32 x_offset, int32 y_offset,
  979.                     Bool enumerate_for_javascript,
  980.                     Bool clip_children, CL_Layer *content,
  981.                     lo_LayerDocState *layer_state,
  982.  
  983.                     CL_BboxChangedFunc bbox_changed_func,
  984.                     CL_EventHandlerFunc event_handler_func,
  985.  
  986.                     CL_DestroyFunc destroy_func)
  987.  
  988. {
  989.     CL_Layer *layer;
  990.     CL_LayerVTable vtable;
  991.     lo_GroupLayerClosure *closure;
  992.  
  993.     uint32 flags = 
  994.         CL_HIDDEN |
  995.         (CL_DONT_ENUMERATE * (enumerate_for_javascript == FALSE)) |
  996.         (CL_CLIP_CHILD_LAYERS * clip_children);
  997.  
  998.     /* Bbox values don't matter since they will be changed afterwards. */
  999.     XP_Rect bbox = {0,0,0,0};
  1000.  
  1001.     XP_BZERO(&vtable, sizeof(CL_LayerVTable));
  1002.     vtable.destroy_func = destroy_func;
  1003.  
  1004.     vtable.bbox_changed_func = bbox_changed_func;
  1005.     vtable.event_handler_func = event_handler_func;
  1006.  
  1007.     closure = XP_NEW_ZAP(lo_GroupLayerClosure);
  1008.     closure->type = LO_GROUP_LAYER;
  1009.     closure->context = context;    
  1010.     closure->content_layer = content;
  1011.     closure->x_offset = x_offset;
  1012.     closure->y_offset = y_offset;
  1013.     closure->layer_state = layer_state;
  1014.  
  1015.  
  1016.     /* Initially, layer created at [0,0] and moved to final position later. */
  1017.     layer = CL_NewLayer(name, 0, 0, &bbox, &vtable,
  1018.                         flags, (void *)closure);
  1019.  
  1020.     if (content)
  1021.         CL_InsertChildByZ(layer, content, Z_CONTENT_LAYERS);
  1022.     
  1023.     return layer;
  1024. }
  1025.  
  1026. /* Create the _CONTENT child of a block layer */
  1027. PRIVATE
  1028. CL_Layer *
  1029. lo_CreateBlockContentLayer(MWContext *context,
  1030.                            PRBool is_inflow,
  1031.                            int32 x_offset,
  1032.                            int32 y_offset,
  1033.                            lo_LayerDocState *layer_state,
  1034.                            lo_DocState *state)
  1035. {
  1036.     CL_Layer *layer;
  1037.     lo_HTMLBlockClosure *closure;
  1038.     CL_LayerVTable vtable;
  1039.  
  1040.     /* Bbox values don't matter since CL_DONT_CLIP_SELF flag is set */
  1041.     XP_Rect bbox = {0,0,0,0};
  1042.     
  1043.     uint32 flags = CL_DONT_ENUMERATE | CL_DONT_CLIP_SELF;
  1044.  
  1045.     closure = XP_NEW_ZAP(lo_HTMLBlockClosure);
  1046.     closure->type = LO_HTML_BLOCK_LAYER;
  1047.     closure->context = context;
  1048.     closure->layer_state = layer_state;
  1049.     closure->state = state;
  1050.     closure->is_inflow = is_inflow;
  1051.     closure->x_offset = x_offset;
  1052.     closure->y_offset = y_offset;
  1053.     
  1054.     XP_BZERO(&vtable, sizeof(CL_LayerVTable));    
  1055.     vtable.painter_func = (CL_PainterFunc)lo_block_painter_func;
  1056.     vtable.destroy_func = (CL_DestroyFunc)lo_html_destroy_func;
  1057.     
  1058.     layer = CL_NewLayer(LO_CONTENT_LAYER_NAME, 0, 0, &bbox, &vtable,
  1059.                         flags, (void *)closure);
  1060.     
  1061.     return layer;
  1062. }
  1063.  
  1064. typedef struct lo_BackgroundRectStruct
  1065. {
  1066.     lo_BackgroundLayerClosure *closure;
  1067.     CL_Layer *layer;
  1068. } lo_BackgroundRectStruct;
  1069.  
  1070. /* Called for each rectangle in the update region */
  1071. static void
  1072. lo_background_rect_func(void *inclosure,
  1073.                         XP_Rect *rect)
  1074. {
  1075.     LO_ImageStruct *backdrop;
  1076.  
  1077.     LO_Color * bg;
  1078.     PRBool is_transparent_backdrop, is_complete;
  1079.     lo_TileMode tile_mode;
  1080.     PRBool fully_tiled;         /* PR_TRUE, if tiled in both X and Y */
  1081.  
  1082.     XP_Rect doc_rect;
  1083.     lo_BackgroundLayerClosure *closure = ((lo_BackgroundRectStruct *)inclosure)->closure;
  1084.     CL_Layer *layer = ((lo_BackgroundRectStruct *)inclosure)->layer;
  1085.     CL_Compositor *compositor = CL_GetLayerCompositor(layer);
  1086.     MWContext * context = closure->context;
  1087.     static LO_Color white_color = {0xFF, 0xFF, 0xFF};
  1088.  
  1089.     XP_CopyRect(rect, &doc_rect);
  1090.     CL_WindowToDocumentRect(compositor, &doc_rect);
  1091.  
  1092.     backdrop = closure->backdrop_image;
  1093.     bg = closure->bg_color;
  1094.     tile_mode = closure->tile_mode;
  1095.  
  1096.     /* Erase with solid color if required. */
  1097.     fully_tiled = (PRBool)(tile_mode == LO_TILE_BOTH);
  1098.     is_complete = (PRBool)(backdrop && 
  1099.         ((backdrop->image_status == IL_IMAGE_COMPLETE) || 
  1100.          (backdrop->image_status == IL_FRAME_COMPLETE)));
  1101.     is_transparent_backdrop = (PRBool)(backdrop && (!is_complete ||
  1102.                                            backdrop->is_transparent));
  1103.  
  1104.     /*
  1105.      * For printing never draw backdrop images. Also, only draw the
  1106.      * backgrounds of table cells in their actual color (everything
  1107.      * else will be drawn with white.
  1108.      */
  1109.  
  1110.     if ((context->type == MWContextPrint) || 
  1111.         (context->type == MWContextPostScript)) {
  1112. #ifdef XP_MAC
  1113.         /* the Mac does print background images, if requested */
  1114.         XP_Bool backgroundPref;
  1115.         if (PREF_GetBoolPref("browser.mac.print_background", &backgroundPref) != PREF_OK || !backgroundPref)
  1116.             backdrop = NULL;
  1117. #elif defined(XP_WIN32)
  1118.         XP_Bool backgroundPref = FALSE;
  1119.         PREF_GetBoolPref("browser.print_background",&backgroundPref);
  1120.         if (!backgroundPref)
  1121.             backdrop = NULL;
  1122.  
  1123. #else
  1124.         backdrop = NULL;
  1125. #endif
  1126. #ifndef XP_WIN32
  1127.         if (closure->bg_type != BG_CELL) 
  1128.             bg = &white_color;
  1129. #else
  1130.         if (!backgroundPref) {
  1131.             if (closure->bg_type != BG_CELL) 
  1132.                 bg = &white_color;
  1133.         }
  1134. #endif
  1135.     }
  1136.  
  1137.     if (bg && (!backdrop || is_transparent_backdrop || !fully_tiled))
  1138.         FE_EraseBackground(closure->context,
  1139.                            FE_VIEW,
  1140.                            doc_rect.left,
  1141.                            doc_rect.top,
  1142.                            doc_rect.right - doc_rect.left,
  1143.                            doc_rect.bottom - doc_rect.top,
  1144.                            bg);
  1145.  
  1146.     /* Paint the backdrop image if there is one. */
  1147.     if (backdrop && !backdrop->is_icon && is_complete) {
  1148.         XP_Rect tile_area = CL_MAX_RECT;
  1149.  
  1150.         /* Convert to layer coordinates */
  1151.         CL_WindowToLayerRect(compositor, layer, rect);
  1152.  
  1153.         /* Constrain tiling area based on tiling mode */
  1154.         if ((int)tile_mode & LO_TILE_HORIZ)
  1155.             tile_area.bottom = backdrop->height;
  1156.         if ((int)tile_mode & LO_TILE_VERT)
  1157.             tile_area.right = backdrop->width;
  1158.  
  1159.         XP_IntersectRect(rect, &tile_area, rect);
  1160.  
  1161.         /* Note: if the compositor is ever used with contexts which have a
  1162.            scale factor other than unity, then all length arguments should
  1163.            be divided by the appropriate context scaling factor i.e.
  1164.            convertPixX, convertPixY.  The FE callback is responsible for
  1165.            context specific scaling. */
  1166.         IL_DisplaySubImage(backdrop->image_req, 0, 0,
  1167.                            rect->left / context->convertPixX,
  1168.                            rect->top / context->convertPixY,
  1169.                            (rect->right - rect->left) / context->convertPixX,
  1170.                            (rect->bottom - rect->top) / context->convertPixY);
  1171.     }
  1172. }
  1173.  
  1174. /* painter_func for a background layer */
  1175. static void
  1176. lo_background_painter_func(CL_Drawable *drawable, 
  1177.                            CL_Layer *layer, 
  1178.                            FE_Region update_region)
  1179. {
  1180.     lo_BackgroundRectStruct bgrect;
  1181.     lo_BackgroundLayerClosure *closure;
  1182.     closure = (lo_BackgroundLayerClosure *)CL_GetLayerClientData(layer);
  1183.     
  1184.     bgrect.closure = closure;
  1185.     bgrect.layer = layer;
  1186.  
  1187. #ifdef XP_MAC
  1188.     /* If we're a grid parent, then we don't want to draw our background */
  1189.     if (closure->context->grid_children && !XP_ListIsEmpty(closure->context->grid_children))
  1190.         return;
  1191. #endif /* XP_MAC */
  1192.  
  1193.     /* 
  1194.      * For Windows and X, we draw the backgrounds of grid parents
  1195.      * since clipping of child windows is done by the windowing system.
  1196.      */
  1197.     
  1198.     FE_SetDrawable(closure->context, drawable);
  1199.  
  1200.     /* XXX - temporary, because Exceed X server has bugs with its
  1201.        offscreen tiling of clipped areas. */
  1202.     /* NOTE -- this causes a significant performance hit on other
  1203.      * Unix platforms.  Is there no other way around this Exceed bug?
  1204.      */
  1205. #ifdef XP_UNIX
  1206.     FE_ForEachRectInRegion(update_region, 
  1207.                (FE_RectInRegionFunc)lo_background_rect_func,
  1208.                (void *)&bgrect);
  1209. #else
  1210.     CL_ForEachRectCoveringRegion(update_region, 
  1211.                  (FE_RectInRegionFunc)lo_background_rect_func,
  1212.                  (void *)&bgrect);
  1213. #endif
  1214.  
  1215.     FE_SetDrawable(closure->context, NULL);
  1216. }
  1217.  
  1218. static void
  1219. lo_background_destroy_func(CL_Layer *layer)
  1220. {
  1221.     LO_Color *bg_color;
  1222.     LO_ImageStruct *backdrop;
  1223.     lo_BackgroundLayerClosure *closure;
  1224.     closure = (lo_BackgroundLayerClosure *)CL_GetLayerClientData(layer);
  1225.     
  1226.     XP_ASSERT(closure->type == LO_HTML_BACKGROUND_LAYER);
  1227.  
  1228.     bg_color = closure->bg_color;
  1229.     if (bg_color)
  1230.         XP_FREE(bg_color);
  1231.  
  1232.     backdrop = closure->backdrop_image;
  1233.     if (backdrop) {
  1234.         if (backdrop->image_req)
  1235.             IL_DestroyImage(backdrop->image_req);
  1236.         if (backdrop->image_url)
  1237.             XP_FREE(backdrop->image_url);
  1238.         XP_FREE(backdrop->image_attr);
  1239.         XP_FREE(backdrop);
  1240.     }
  1241.  
  1242.     XP_DELETE(closure);
  1243. }
  1244.  
  1245. /* Creates a HTML background layer to be a child of a layer group */
  1246. PRIVATE
  1247. CL_Layer *
  1248. lo_CreateBackgroundLayer(MWContext *context, PRBool is_document_backdrop)
  1249. {
  1250.     CL_Layer *layer;
  1251.     XP_Rect bbox = {0, 0, 0, 0};
  1252.  
  1253.     CL_LayerVTable vtable;
  1254.     lo_BackgroundLayerClosure *closure;
  1255.     
  1256.     uint32 flags = CL_DONT_ENUMERATE | CL_DONT_CLIP_SELF;
  1257.  
  1258.     XP_BZERO(&vtable, sizeof(CL_LayerVTable));
  1259.     vtable.painter_func = lo_background_painter_func;
  1260.     vtable.destroy_func = lo_background_destroy_func;
  1261.     if (is_document_backdrop)
  1262.         vtable.event_handler_func = lo_html_event_handler_func;
  1263.  
  1264.     closure = XP_NEW_ZAP(lo_BackgroundLayerClosure);
  1265.     closure->type = LO_HTML_BACKGROUND_LAYER;
  1266.     closure->context = context;
  1267.     closure->bg_type = is_document_backdrop ? BG_DOCUMENT : BG_LAYER;
  1268.     closure->tile_mode = LO_TILE_BOTH; /* Default tiling mode */
  1269.     
  1270.     layer = CL_NewLayer(LO_BACKGROUND_LAYER_NAME, 0, 0, &bbox, &vtable,
  1271.                         flags, (void *)closure);
  1272.  
  1273.     return layer;
  1274. }
  1275.  
  1276. /* Retrieve the background sub-layer for a layer group.
  1277.    If the <create> argument is TRUE, build the background layer
  1278.    if it doesn't exist. */
  1279. PRIVATE
  1280. CL_Layer *
  1281. lo_get_group_background(CL_Layer *layer, PRBool create)
  1282. {
  1283.     lo_GroupLayerClosure *closure;
  1284.     MWContext *context;
  1285.     CL_Layer *background_layer;
  1286.  
  1287.     if (! layer)
  1288.         return NULL;
  1289.         
  1290.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  1291.     context = closure->context;
  1292.  
  1293.     XP_ASSERT(closure->type == LO_GROUP_LAYER);
  1294.     if (closure->type != LO_GROUP_LAYER)
  1295.         return NULL;
  1296.  
  1297.     background_layer = closure->background_layer;
  1298.     if (!background_layer && create) {
  1299.         PRBool is_document_backdrop = lo_is_document_layer(layer);
  1300.         background_layer = lo_CreateBackgroundLayer(context, 
  1301.                                                     is_document_backdrop);
  1302.  
  1303.         if (! background_layer) /* OOM */
  1304.             return NULL;
  1305.         CL_InsertChildByZ(layer, background_layer, Z_BACKGROUND_LAYER);
  1306.         closure->background_layer = background_layer;
  1307.     }
  1308.     return background_layer;
  1309. }
  1310.  
  1311. static void
  1312. lo_set_background_layer_bgcolor(CL_Layer *background_layer, LO_Color *new_bg_color)
  1313. {
  1314.     lo_BackgroundLayerClosure *closure;
  1315.     LO_Color *bg_color, *old_bg_color;
  1316.     LO_ImageStruct *backdrop;
  1317.     
  1318.     closure = (lo_BackgroundLayerClosure *)CL_GetLayerClientData(background_layer);
  1319.  
  1320.     bg_color = NULL;
  1321.     if (new_bg_color) {
  1322.         bg_color = XP_NEW_ZAP(LO_Color);
  1323.         if (!bg_color)
  1324.             return;
  1325.         *bg_color = *new_bg_color;
  1326.     }
  1327.     
  1328.     old_bg_color = closure->bg_color;
  1329.     if (old_bg_color)
  1330.         XP_FREE(old_bg_color);
  1331.     closure->bg_color = bg_color;
  1332.     backdrop = closure->backdrop_image;
  1333.  
  1334.     /* Make layer opaque if solid color or backdrop has no transparent areas */
  1335.     CL_ChangeLayerFlag(background_layer, CL_OPAQUE, 
  1336.                        (PRBool)(new_bg_color || (backdrop && !backdrop->is_transparent)));
  1337.  
  1338.     /* We can optimize drawing on top of this layer if it's a uniform color */
  1339.     if (!backdrop)
  1340.         CL_SetLayerUniformColor(background_layer, (CL_Color*)bg_color);
  1341.  
  1342.     /* Redraw the entire layer to reflect its new color. */
  1343.     {
  1344.         MWContext *context = closure->context;
  1345.         PRBool is_document_backdrop = (PRBool)(closure->bg_type == BG_DOCUMENT);
  1346.         XP_Rect rect = CL_MAX_RECT;
  1347.  
  1348.         if (is_document_backdrop) {
  1349.             XP_ASSERT(bg_color);
  1350.             if (bg_color) {
  1351.                 /* Prevent default doc color from overriding JS-supplied color */
  1352.                 lo_TopState *top_state = lo_get_layer_top_state(background_layer);
  1353.                 if (top_state)  /* Paranoia */
  1354.                     top_state->doc_specified_bg = TRUE;
  1355.                 FE_SetBackgroundColor(context,
  1356.                                       bg_color->red, bg_color->green, bg_color->blue);
  1357.             }
  1358.         }
  1359.         
  1360.         CL_UpdateLayerRect(context->compositor, background_layer, &rect, PR_FALSE);
  1361.     }
  1362. }
  1363.  
  1364. /* Set the background color for a layer group to the given RGB color.
  1365.    If <new_bg_color> is NULL, make the layer transparent. */
  1366. void
  1367. LO_SetLayerBgColor(CL_Layer *layer, LO_Color *new_bg_color)
  1368. {
  1369.     CL_Layer *background_layer;
  1370.  
  1371.     background_layer = lo_get_group_background(layer, PR_TRUE);
  1372.     if (!background_layer)
  1373.         return;
  1374.     
  1375.     lo_set_background_layer_bgcolor(background_layer, new_bg_color);
  1376. }
  1377.  
  1378. /* Retrieve a layer group's solid background color.
  1379.    Returned LO_Color structure must not be free'd or modified. */
  1380. LO_Color *
  1381. LO_GetLayerBgColor(CL_Layer *layer)
  1382. {
  1383.     lo_BackgroundLayerClosure *closure;
  1384.     CL_Layer *background_layer;
  1385.  
  1386.     background_layer = lo_get_group_background(layer, PR_FALSE);
  1387.     if (!background_layer)
  1388.         return NULL;
  1389.     
  1390.     closure = (lo_BackgroundLayerClosure *)CL_GetLayerClientData(background_layer);
  1391.     return closure->bg_color;
  1392. }
  1393.  
  1394. static LO_ImageStruct *
  1395. lo_get_background_layer_image(CL_Layer *background_layer, PRBool create)
  1396. {
  1397.     lo_BackgroundLayerClosure *closure;
  1398.     LO_ImageStruct *backdrop;
  1399.     
  1400.     closure = (lo_BackgroundLayerClosure *)CL_GetLayerClientData(background_layer);
  1401.     backdrop = closure->backdrop_image;
  1402.  
  1403.     /* Create the layout image structure if it doesn't exist. */
  1404.     if (! backdrop && create) {
  1405.         LO_ImageAttr *image_attr;
  1406.         PRBool is_cell_backdrop = (PRBool)(closure->bg_type == BG_CELL);
  1407.         PRBool is_layer_backdrop = (PRBool)(closure->bg_type == BG_LAYER);
  1408.  
  1409.         backdrop = XP_NEW_ZAP(LO_ImageStruct);
  1410.         if (!backdrop)
  1411.             return NULL;
  1412.  
  1413.         image_attr = XP_NEW(LO_ImageAttr);
  1414.         if (!image_attr) {
  1415.             XP_FREE(backdrop);
  1416.             return NULL;
  1417.         }
  1418.  
  1419.         /* Fake layout ID, guaranteed not to match any real layout element */
  1420.         backdrop->ele_id = -1;
  1421.         backdrop->type = LO_IMAGE;
  1422.  
  1423.         backdrop->image_attr = image_attr;
  1424.         backdrop->image_attr->attrmask = LO_ATTR_BACKDROP;
  1425.         if (is_layer_backdrop)
  1426.             backdrop->image_attr->attrmask |= LO_ATTR_LAYER_BACKDROP;
  1427.         else if (is_cell_backdrop)
  1428.             backdrop->image_attr->attrmask |= LO_ATTR_CELL_BACKDROP;
  1429.         
  1430.         backdrop->layer = background_layer;
  1431.         closure->backdrop_image = backdrop;
  1432.     }
  1433.  
  1434.     return backdrop;
  1435. }
  1436.  
  1437. /* Retrieve the LO_ImageStruct corresponding to a layer's backdrop,
  1438.    creating it if necessary. */
  1439. LO_ImageStruct *
  1440. LO_GetLayerBackdropImage(CL_Layer *layer)
  1441. {
  1442.     CL_Layer *background_layer;
  1443.     
  1444.     background_layer = lo_get_group_background(layer, PR_TRUE);
  1445.     if (!background_layer)
  1446.         return NULL;
  1447.     return lo_get_background_layer_image(background_layer, PR_TRUE);
  1448. }
  1449.  
  1450. void
  1451. LO_SetImageURL(MWContext *context,
  1452.                IL_GroupContext *img_cx,
  1453.                LO_ImageStruct *image,
  1454.                const char *url,
  1455.                NET_ReloadMethod reload_policy)
  1456. {
  1457.     PRBool replace = PR_FALSE; /* True if we are replacing an
  1458.                                    existing image. */
  1459.     XP_ObserverList image_obs_list;
  1460.     CL_Layer *image_layer = image->layer;
  1461.  
  1462.     /* Clear out the resources of any previous backdrop image. */
  1463.     if (image->image_url)
  1464.         XP_FREE(image->image_url);
  1465.     image->image_url = NULL;
  1466.     if (image->image_req) {
  1467.         replace = PR_TRUE;
  1468.         IL_DestroyImage(image->image_req);
  1469.         image->image_req = NULL;
  1470.     }
  1471.     image->is_icon = FALSE;
  1472.     image->image_status = IL_START_URL;
  1473.  
  1474.     /* If there is a backdrop url to load, start loading the image. */
  1475.     if (url) {
  1476.         image->image_url = (PA_Block)XP_STRDUP(url);
  1477.         if (!image->image_url)
  1478.             return;
  1479.         
  1480.         image_obs_list = lo_NewImageObserverList(context, image);
  1481.         if (!image_obs_list)
  1482.             return;
  1483.  
  1484.         
  1485.         if (image_layer) {
  1486.             /* Is this a backdrop image ? */
  1487.             if (LO_GetLayerType(image_layer) == LO_HTML_BACKGROUND_LAYER) {
  1488.             
  1489.             /* Backdrop images are never scaled. */
  1490.             image->width = image->height = 0;
  1491.  
  1492.             /* We can't optimize drawing on top of a solid-colored
  1493.                background now that we have an image backdrop. */
  1494.             CL_SetLayerUniformColor(image_layer, NULL);
  1495.             }
  1496.             
  1497.             /* If we are replacing an existing image, then make the layer
  1498.                 transparent to minimize flicker as the new image comes in. */
  1499.             if (replace) {
  1500.                 CL_ChangeLayerFlag(image_layer, CL_OPAQUE, PR_FALSE);
  1501.                 CL_ChangeLayerFlag(image_layer, CL_PREFER_DRAW_OFFSCREEN,
  1502.                                    PR_TRUE);
  1503.             }
  1504.         }
  1505.  
  1506.         /* Initiate the loading of this image. */
  1507.         lo_GetImage(context, img_cx, image, image_obs_list, reload_policy);
  1508.     } else if (image_layer) {
  1509.         XP_Rect rect = CL_MAX_RECT;
  1510.         LO_LayerType layer_type = LO_GetLayerType(image_layer);
  1511.  
  1512.         /* No backdrop image.  Make the background layer transparent,
  1513.            unless the layer consists of a solid color. */
  1514.         if (layer_type == LO_HTML_BACKGROUND_LAYER) {
  1515.             lo_BackgroundLayerClosure *closure =
  1516.                 (lo_BackgroundLayerClosure *)CL_GetLayerClientData(image_layer);
  1517.  
  1518.             CL_ChangeLayerFlag(image_layer, CL_OPAQUE, 
  1519.                                (PRBool)(closure->bg_color != NULL));
  1520.  
  1521.             /* Now, either the backdrop is a solid color or it's
  1522.                completely transparent. */
  1523.             CL_SetLayerUniformColor(image_layer, (CL_Color*)closure->bg_color);
  1524.         }
  1525.  
  1526.         /* If there is no URL, refresh the layer because it is
  1527.            now transparent. */
  1528.         CL_UpdateLayerRect(context->compositor, image_layer, &rect, PR_FALSE);
  1529.     }
  1530. }
  1531.     
  1532. /* set the tile mode of a backdrop image.  SetLayerBackdropURL must
  1533.  * be called before this function.
  1534.  */
  1535. void
  1536. lo_SetLayerBackdropTileMode(CL_Layer *layer, lo_TileMode tile_mode)
  1537. {
  1538.     lo_BackgroundLayerClosure *closure;
  1539.     CL_Layer *background_layer = lo_get_group_background(layer, PR_FALSE);
  1540.     if (!background_layer)
  1541.         return;
  1542.     closure = (lo_BackgroundLayerClosure *)CL_GetLayerClientData(background_layer);
  1543.     closure->tile_mode = tile_mode;
  1544. }
  1545.  
  1546. /* Set the backdrop URL for a layer group.
  1547.    If <url> is NULL or empty string, then clear the backdrop. */
  1548. void
  1549. LO_SetLayerBackdropURL(CL_Layer *layer, const char *url)
  1550. {
  1551.     LO_ImageStruct *image = LO_GetLayerBackdropImage(layer);
  1552.     MWContext *context = lo_get_layer_context(layer);
  1553.     lo_TopState *top_state = lo_get_layer_top_state(layer);
  1554.     IL_GroupContext *img_cx = context->img_cx;
  1555.  
  1556.     if (url && *url) {
  1557.         url = NET_MakeAbsoluteURL(top_state->base_url, (char*)url);
  1558.         LO_SetImageURL(context, img_cx, image, url, top_state->force_reload);
  1559.     } else
  1560.         LO_SetImageURL(context, img_cx, image, NULL, top_state->force_reload);
  1561. }
  1562.  
  1563. /* Get the backdrop URL for a layer group.  Return NULL if their is no
  1564.    backdrop URL. */
  1565. const char *
  1566. LO_GetLayerBackdropURL(CL_Layer *layer)
  1567. {
  1568.     CL_Layer *background_layer;
  1569.     LO_ImageStruct *backdrop;
  1570.     
  1571.     background_layer = lo_get_group_background(layer, PR_FALSE);
  1572.     if (!background_layer)
  1573.         return NULL;
  1574.     backdrop = lo_get_background_layer_image(background_layer, PR_FALSE);
  1575.     if (!backdrop)
  1576.         return NULL;
  1577.     
  1578.     return (const char *)backdrop->image_url;
  1579. }
  1580.  
  1581. void
  1582. lo_OffsetInflowLayer(CL_Layer *layer, int32 dx, int32 dy)
  1583. {
  1584.     lo_GroupLayerClosure *closure;
  1585.     lo_HTMLBlockClosure *content_closure;
  1586.     CL_Layer *content_layer;
  1587.  
  1588.     CL_OffsetLayer(layer, dx, dy);
  1589.  
  1590.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  1591.     content_layer = closure->content_layer;
  1592.     if (content_layer) {
  1593.         content_closure = 
  1594.             (lo_HTMLBlockClosure *)CL_GetLayerClientData(content_layer);
  1595.         content_closure->x_offset += dx;
  1596.         content_closure->y_offset += dy;
  1597.     }
  1598.     
  1599.     closure->x_offset += dx;
  1600.     closure->y_offset += dy;
  1601. }
  1602.  
  1603. LO_CellStruct *
  1604. lo_GetCellFromLayer(MWContext *context, CL_Layer *layer)
  1605. {
  1606.     lo_GroupLayerClosure *closure;
  1607.  
  1608.     if (!layer)                 /* Paranoia */
  1609.         return NULL;
  1610.     
  1611.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
  1612.     if (closure->type != LO_GROUP_LAYER)
  1613.         return NULL;
  1614.     if (!closure->layer_state)  /* This must be the BODY layer */
  1615.         return NULL;
  1616.     return closure->layer_state->cell;
  1617. }
  1618.  
  1619.  
  1620. /**********************
  1621.  *
  1622.  * Cell background layering code
  1623.  *
  1624.  **********************/
  1625.  
  1626. static void
  1627. lo_cellbg_destroy_func(CL_Layer *layer)
  1628. {
  1629.     lo_BackgroundLayerClosure *closure;
  1630.     closure = (lo_BackgroundLayerClosure *)CL_GetLayerClientData(layer);
  1631.     /* 
  1632.      * NULL out the corresponding cell's pointer to this layer so that
  1633.      * there won't be double destruction. We assume that if the cell
  1634.      * is destroyed first, it will also destroy this layer.
  1635.      */
  1636.     if (closure->cell)
  1637.         closure->cell->cell_bg_layer = NULL;
  1638.     lo_background_destroy_func(layer);
  1639. }
  1640.  
  1641. /* Cell backgrounds are almost identical to regular backgrounds,
  1642.  * except that they are of finite size and they don't do any event
  1643.  * handling.
  1644.  */
  1645. CL_Layer *
  1646. lo_CreateCellBackgroundLayer(MWContext *context, LO_CellStruct *cell,
  1647.                              CL_Layer *parent_layer)
  1648. {
  1649.     CL_Layer *cellbg_layer;
  1650.     XP_Rect bbox;
  1651.     lo_BackgroundLayerClosure *closure;    
  1652.     CL_LayerVTable vtable;
  1653.     int32 layer_x_offset, layer_y_offset;
  1654.     int32 parent_x_shift, parent_y_shift;
  1655.  
  1656.         
  1657.  
  1658.     /* The layer is the size of the cell */
  1659.     bbox.left   = 0;
  1660.     bbox.top    = 0;
  1661.     bbox.right  = cell->width;
  1662.     bbox.bottom = cell->height;
  1663.  
  1664.     lo_GetLayerXYShift(parent_layer, &parent_x_shift, &parent_y_shift);
  1665.  
  1666.     layer_x_offset = cell->x + cell->x_offset - parent_x_shift;
  1667.     layer_y_offset = cell->y + cell->y_offset - parent_y_shift;
  1668.     
  1669.     /* Create the client_data */
  1670.     closure = XP_NEW_ZAP(lo_BackgroundLayerClosure);
  1671.     closure->type = LO_HTML_BACKGROUND_LAYER;
  1672.     closure->context = context; 
  1673.     closure->bg_type = BG_CELL;
  1674.     closure->tile_mode = cell->backdrop.tile_mode;
  1675.     closure->cell = cell;
  1676.    
  1677.     XP_BZERO(&vtable, sizeof(CL_LayerVTable));    
  1678.     vtable.painter_func = lo_background_painter_func;
  1679.     vtable.destroy_func = lo_cellbg_destroy_func;
  1680.  
  1681.     cellbg_layer = CL_NewLayer(NULL, layer_x_offset, layer_y_offset,
  1682.                                &bbox, &vtable,
  1683.                                CL_HIDDEN | CL_DONT_ENUMERATE, 
  1684.                                (void *)closure);
  1685.  
  1686.     if (!cellbg_layer)
  1687.         return NULL;
  1688.  
  1689.     CL_InsertChildByZ(parent_layer, cellbg_layer, Z_CELL_BACKGROUND_LAYER);
  1690.  
  1691.     /* Start loading tiled cell backdrop image, if present */
  1692.     if (cell->backdrop.url && *cell->backdrop.url) {
  1693.         LO_ImageStruct *image;
  1694.  
  1695.         image = lo_get_background_layer_image(cellbg_layer, PR_TRUE);
  1696.         if (image) {
  1697.             lo_TopState *top_state = lo_get_layer_top_state(parent_layer);
  1698.             char *url = NET_MakeAbsoluteURL(top_state->base_url, cell->backdrop.url);
  1699.             if (url) {
  1700.                 XP_FREE(cell->backdrop.url);
  1701.                 cell->backdrop.url = url;
  1702.                 /* Note: In the case of nested tables with background
  1703.                 images, the image request is destroyed before the table
  1704.                 relayout and will not exist in the cache. Changing reload
  1705.                 policy if it is NET_CACHE_ONLY_RELOAD to NET_DONT_RELOAD
  1706.                 allows loading the image again from a file if it has 
  1707.                 been removed from the cache.
  1708.  
  1709.                 Trying to use the trash list would cause memory leaks
  1710.                 as the trash list removes items from the mem arena. Allocating
  1711.                 the image_request by taking it from the arena (instead of
  1712.                 explicitly allocating it) could cause problems in
  1713.                 the editor code.
  1714.                 */    
  1715.                 LO_SetImageURL(context, context->img_cx, image, url,
  1716.                        ((top_state->force_reload == NET_CACHE_ONLY_RELOAD)?
  1717.                                     NET_DONT_RELOAD : top_state->force_reload));
  1718.                 XP_FREE(url);
  1719.             }
  1720.         }
  1721.     }
  1722.  
  1723.     /* Set cell background color, if the cell isn't transparent. */
  1724.     if (cell->backdrop.bg_color) {
  1725.     if (UserOverride)
  1726.         lo_set_background_layer_bgcolor(cellbg_layer, &lo_master_colors[LO_COLOR_BG]);
  1727.     else
  1728.             lo_set_background_layer_bgcolor(cellbg_layer, cell->backdrop.bg_color);
  1729.     }
  1730.  
  1731.     return cellbg_layer;
  1732. }
  1733.  
  1734. /* Create a block layer - a layer created by a HTML <LAYER> tag */
  1735. CL_Layer *
  1736. lo_CreateBlockLayer(MWContext *context, 
  1737.                     char *name,
  1738.                     PRBool is_inflow,
  1739.                     int32 x_offset, int32 y_offset,
  1740.                     int32 wrap_width,
  1741.                     lo_LayerDocState *layer_state,
  1742.                     lo_DocState *state)
  1743. {
  1744.     CL_Layer *content_layer, *block_layer;
  1745.     lo_GroupLayerClosure *closure;
  1746.     
  1747.     content_layer = lo_CreateBlockContentLayer(context, is_inflow,
  1748.                                                x_offset, y_offset, 
  1749.                                                layer_state, state);
  1750.  
  1751.     if (! content_layer)
  1752.         return NULL;
  1753.  
  1754.     block_layer = lo_CreateGroupLayer(context, name,
  1755.                                       x_offset, y_offset,
  1756.                                       TRUE, TRUE, content_layer,
  1757.                                       layer_state,
  1758.  
  1759.                                       NULL, 
  1760.                                       is_inflow ? 
  1761.                                       lo_html_inflow_layer_event_handler_func :
  1762.                                       lo_html_event_handler_func,
  1763.  
  1764.                                       lo_html_block_destroy_func);
  1765.  
  1766.  
  1767.     if (! block_layer) {
  1768.         CL_DestroyLayer(content_layer);
  1769.         return NULL;
  1770.     }
  1771.  
  1772.     closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(block_layer);
  1773.     closure->wrap_width = wrap_width;
  1774.     closure->is_inflow = is_inflow;
  1775.     
  1776.     return block_layer;
  1777. }
  1778.  
  1779.  
  1780. /* Create the _CONTENT child of the _BODY layer */
  1781. static CL_Layer *
  1782. lo_CreateBodyContentLayer(MWContext *context)
  1783. {
  1784.     CL_Layer *layer;
  1785.     XP_Rect bbox;
  1786.     CL_LayerVTable vtable;
  1787.     lo_HTMLBodyClosure *closure;
  1788.  
  1789.     uint32 flags = CL_DONT_ENUMERATE | CL_DONT_CLIP_SELF;
  1790.  
  1791.     bbox.left = 0;
  1792.     bbox.top = 0;
  1793.     bbox.right = 0;
  1794.     bbox.bottom = 0;
  1795.     
  1796.     XP_BZERO(&vtable, sizeof(CL_LayerVTable));
  1797.     vtable.painter_func = lo_body_painter_func;
  1798.     vtable.destroy_func = lo_html_destroy_func;
  1799.  
  1800.     closure = XP_NEW_ZAP(lo_HTMLBodyClosure);
  1801.     closure->type = LO_HTML_BODY_LAYER;
  1802.     closure->context = context;
  1803.  
  1804.     layer = CL_NewLayer(LO_CONTENT_LAYER_NAME, 0, 0, &bbox, &vtable,
  1805.                         flags, (void *)closure);
  1806.     closure->layer = layer;
  1807.  
  1808.     return layer;
  1809. }
  1810.  
  1811.  
  1812. /* 
  1813.  * Creates the HTML body layer
  1814.  */
  1815. static CL_Layer *
  1816. lo_CreateHTMLBodyLayer(MWContext *context)
  1817. {
  1818.     CL_Layer *content_layer, *body_layer;
  1819.  
  1820.     /* First create the _CONTENT part of the _BODY layer */
  1821.     content_layer = lo_CreateBodyContentLayer(context);
  1822.     
  1823.     /* 
  1824.      * Now create the abstract _BODY layer. The _CONTENT layer
  1825.      * is a child of this layer, but there's no background.
  1826.      */
  1827.     body_layer = lo_CreateGroupLayer(context, LO_BODY_LAYER_NAME, 
  1828.                                      0, 0,
  1829.                                      FALSE, TRUE, content_layer,
  1830.                                      NULL,
  1831.  
  1832.                                      body_bbox_changed_func,
  1833.                                      lo_html_event_handler_func,
  1834.  
  1835.                                      lo_html_destroy_func);
  1836.  
  1837.     CL_ChangeLayerFlag(body_layer, CL_HIDDEN, PR_FALSE);
  1838.     return body_layer;
  1839. }
  1840.  
  1841. void
  1842. LO_SetDocumentDimensions(MWContext *context, int32 width, int32 height)
  1843. {
  1844.     XP_Rect bbox;
  1845.     int32 current_width, current_height;
  1846.     
  1847.     lo_TopState *top_state = lo_FetchTopState(XP_DOCID(context));
  1848.     if (!top_state)
  1849.         return;
  1850.  
  1851.     /* If layering is enabled, set the size of the _BODY layer.  That
  1852.        will enlarge/shrink the _DOCUMENT layer as necessary, and call
  1853.        FE_SetDocDimension if the document layer changes size. */
  1854.     if (context->compositor) {
  1855.         bbox.left = bbox.top = 0;
  1856.         bbox.right = width;
  1857.         bbox.bottom = height;
  1858.         CL_SetLayerBbox(top_state->body_layer, &bbox);
  1859.  
  1860.         /* The document layer is always at least as large as the body
  1861.            layer, so if the body expands beyond the document's size,
  1862.            tell the FE about it immediately, rather than waiting for
  1863.            it to occur as a callback from the timing-driven composite
  1864.            cycle.  That avoids race conditions in which
  1865.            FE_SetDocPosition() is called before FE_SetDocDimension()
  1866.            has specified a sufficiently large document to encompass
  1867.            the new document position. */
  1868.         current_width = LO_GetLayerScrollWidth(top_state->doc_layer);
  1869.         current_height = LO_GetLayerScrollHeight(top_state->doc_layer);
  1870.  
  1871.         if ((width > current_width) || (height > current_height) || (width == 0) || (height == 0))
  1872.             doc_bbox_changed_func(top_state->doc_layer, &bbox);
  1873.     } else {
  1874.         FE_SetDocDimension(context, FE_VIEW, width, height);
  1875.     }
  1876. }
  1877.  
  1878. /* Creates the _DOCUMENT, _BODY and _BACKGROUND layers and 
  1879.    adds them to the layer tree */
  1880. void
  1881. lo_CreateDefaultLayers(MWContext *context,
  1882.                        CL_Layer **doc_layer,
  1883.                        CL_Layer **body_layer)
  1884. {
  1885.     *doc_layer = NULL;
  1886.     
  1887.     *body_layer = lo_CreateHTMLBodyLayer(context);
  1888.     if (!*body_layer)
  1889.         return;
  1890.     
  1891.     *doc_layer = lo_CreateGroupLayer(context, LO_DOCUMENT_LAYER_NAME,
  1892.                                      0, 0, FALSE, FALSE,
  1893.                                      *body_layer,
  1894.                                      NULL,
  1895.  
  1896.                                      doc_bbox_changed_func, NULL,
  1897.  
  1898.                                      lo_html_destroy_func);
  1899.  
  1900.  
  1901.     if (!*doc_layer)
  1902.         return;
  1903.  
  1904.     CL_ChangeLayerFlag(*doc_layer, CL_HIDDEN, PR_FALSE);
  1905.     if (context->compositor)
  1906.         CL_SetCompositorRoot(context->compositor, *doc_layer);        
  1907. }
  1908.  
  1909. /* Attaches the new layer into the layer structure */
  1910. void
  1911. lo_AttachHTMLLayer(MWContext *context, CL_Layer *layer, CL_Layer *parent,
  1912.                    char *above, char *below, int32 z_order)
  1913. {
  1914.     CL_Layer *sibling;
  1915.     CL_LayerPosition pos;
  1916.  
  1917.     if (parent != NULL)
  1918.     {
  1919.     if (z_order >= 0)
  1920.     {
  1921.         CL_InsertChildByZ(parent, layer, z_order);
  1922.     }
  1923.     else
  1924.     {
  1925.         sibling = NULL;
  1926.         if (above != NULL)
  1927.         {
  1928.         pos = CL_BELOW;
  1929.         sibling = CL_GetLayerChildByName(parent, above);
  1930.         }
  1931.         if ((sibling == NULL)&&(below != NULL))
  1932.         {
  1933.         pos = CL_ABOVE;
  1934.         sibling = CL_GetLayerChildByName(parent, below);
  1935.         }
  1936.         if (sibling == NULL)
  1937.         {
  1938.         pos = CL_ABOVE;
  1939.         }
  1940.         CL_InsertChild(parent, layer, sibling, pos);
  1941.     }
  1942.     }
  1943. }
  1944.  
  1945. /* Destroy all HTML-created layers */
  1946. void
  1947. lo_DestroyLayers(MWContext *context)
  1948. {
  1949.     CL_DestroyLayerTree(CL_GetCompositorRoot(context->compositor));
  1950.     CL_SetCompositorRoot(context->compositor, NULL);
  1951. }
  1952.  
  1953. LO_LayerType
  1954. LO_GetLayerType(CL_Layer *layer)
  1955. {
  1956.     lo_AnyLayerClosure *closure = (lo_AnyLayerClosure *)CL_GetLayerClientData(layer);
  1957.     
  1958.     return closure->type;
  1959. }
  1960.  
  1961. /* Push a layer onto the document's layer stack */
  1962. void
  1963. lo_PushLayerState(lo_TopState *top_state, lo_LayerDocState *layer_state)
  1964. {
  1965.     lo_LayerStack *lptr;
  1966.  
  1967.     lptr = XP_NEW(lo_LayerStack);
  1968.     if (lptr == NULL)
  1969.     {
  1970.     return;
  1971.     }
  1972.     lptr->layer_state = layer_state;
  1973.     lptr->next = top_state->layer_stack;
  1974.     top_state->layer_stack = lptr;
  1975. }
  1976.  
  1977. /* Pop a layer off the document's layer stack */
  1978. lo_LayerDocState *
  1979. lo_PopLayerState(lo_DocState *state)
  1980. {
  1981.     lo_LayerStack *lptr;
  1982.     lo_LayerDocState *layer_state;
  1983.     lo_TopState *top_state = state->top_state;
  1984.     
  1985.     if (top_state->layer_stack == NULL)
  1986.         return NULL;
  1987.     
  1988.     lptr = top_state->layer_stack;
  1989.     layer_state = lptr->layer_state;
  1990.     top_state->layer_stack = lptr->next;
  1991.     
  1992.     XP_DELETE(lptr);
  1993.     
  1994.     return layer_state;
  1995. }
  1996.  
  1997. /* Look at the top layer on the document's layer stack, without popping it */
  1998. lo_LayerDocState *
  1999. lo_CurrentLayerState(lo_DocState *state)
  2000. {
  2001.     lo_LayerDocState *layer_state;
  2002.     lo_TopState *top_state = state->top_state;
  2003.     if (top_state->layer_stack == NULL)
  2004.         return NULL;
  2005.     layer_state = top_state->layer_stack->layer_state;
  2006.     return layer_state;
  2007. }
  2008.  
  2009. int32
  2010. lo_CurrentLayerId(lo_DocState *state)
  2011. {
  2012.     lo_LayerDocState *layer_state = lo_CurrentLayerState(state);
  2013.     return layer_state->id;
  2014. }
  2015.  
  2016. CL_Layer *
  2017. lo_CurrentLayer(lo_DocState *state)
  2018. {
  2019.     lo_LayerDocState *layer_state = lo_CurrentLayerState(state);
  2020.     return layer_state->layer;
  2021. }
  2022.  
  2023. void
  2024. lo_DeleteLayerStack(lo_DocState *state)
  2025. {
  2026.     lo_LayerStack *lptr;
  2027.     lo_LayerStack *prev;
  2028.     lo_TopState *top_state = state->top_state;
  2029.  
  2030.     lptr = top_state->layer_stack;
  2031.     while (lptr != NULL) {
  2032.         prev = lptr;
  2033.         lptr = lptr->next;
  2034.         XP_DELETE(prev);
  2035.     }
  2036.     top_state->layer_stack = NULL;
  2037. }
  2038.  
  2039. /**********************
  2040.  *
  2041.  * Embedded object layering code
  2042.  *
  2043.  **********************/
  2044.  
  2045.  
  2046. /* Redraw an embedded object window because its position or visibility may
  2047.    have been altered. */
  2048. static void
  2049. lo_update_embedded_object_window(CL_Layer *layer)
  2050.     int32 x_save, y_save;
  2051.     LO_Any *any;
  2052.     MWContext *context;
  2053.     lo_EmbeddedObjectClosure *closure;
  2054.     LO_Element *tptr;
  2055.     XP_Rect rect;
  2056.     CL_Compositor *compositor = CL_GetLayerCompositor(layer);
  2057.  
  2058.     closure = (lo_EmbeddedObjectClosure *)CL_GetLayerClientData(layer);
  2059.     XP_ASSERT(closure);
  2060.     if (! closure)
  2061.         return;
  2062.  
  2063.     /* If embedded object is not (yet) a window.  There's
  2064.        nothing to do. */
  2065.     if (!closure->is_windowed)
  2066.         return;
  2067.  
  2068.     context = closure->context;
  2069.  
  2070.     tptr = closure->element;
  2071.     any = &tptr->lo_any;
  2072.     XP_ASSERT(any);
  2073.  
  2074.     /* Convert layer-relative coordinates for element to document
  2075.        coordinates, since that's what the FE uses. */
  2076.     rect.top = rect.left = rect.right = rect.bottom = 0;
  2077.     CL_LayerToWindowRect(compositor, layer, &rect);
  2078.     CL_WindowToDocumentRect(compositor, &rect);
  2079.     
  2080.     /* Save old, layer-relative coordinates */
  2081.     x_save = any->x;
  2082.     y_save = any->y;
  2083.  
  2084.     /* Temporarily shift element to document coordinates */
  2085.     any->x = rect.left - any->x_offset;
  2086.     any->y = rect.top - any->y_offset;
  2087.  
  2088.     /* Call the platform-specific display code. */
  2089.     switch (tptr->type) {
  2090.     case LO_FORM_ELE:
  2091.         any->x -= tptr->lo_form.border_horiz_space;
  2092.         any->y -= tptr->lo_form.border_vert_space;
  2093.     FE_DisplayFormElement(context, FE_VIEW, &tptr->lo_form);
  2094.     break;
  2095.     case LO_EMBED:
  2096.     FE_DisplayEmbed(context, FE_VIEW, &tptr->lo_embed);
  2097.     break;
  2098. #ifdef JAVA
  2099.     case LO_JAVA:
  2100.     FE_DisplayJavaApp(context, FE_VIEW, &tptr->lo_java);
  2101.     break;
  2102. #endif
  2103.     default:
  2104.     XP_ASSERT(0);
  2105.     }
  2106.  
  2107.     /* Restore layer-relative coordinates */
  2108.     any->x = x_save;
  2109.     any->y = y_save;
  2110. }
  2111.  
  2112. #ifdef XP_UNIX
  2113.  
  2114. /* Same as FE_DisplayFormElement, except coordinates converted
  2115.    from layer-relative to document-relative to satisfy FE
  2116.    expectations. */
  2117. void
  2118. LO_DisplayFormElement(LO_FormElementStruct *form)
  2119. {
  2120.    XP_ASSERT(form->layer);
  2121.    if (!form->layer)
  2122.         return;
  2123.    lo_update_embedded_object_window(form->layer);
  2124. }
  2125.  
  2126. #endif /* XP_UNIX */
  2127.  
  2128. static void
  2129. lo_window_layer_visibility_changed(CL_Layer *layer,
  2130.                    PRBool visible)
  2131. {
  2132.     lo_EmbeddedObjectClosure *closure;
  2133.     LO_Element *tptr;
  2134.  
  2135.     closure = (lo_EmbeddedObjectClosure *)CL_GetLayerClientData(layer);
  2136.     XP_ASSERT(closure);
  2137.  
  2138.     tptr = closure->element;
  2139.     XP_ASSERT(tptr);
  2140.  
  2141.     switch (tptr->type) {
  2142.     case LO_FORM_ELE:
  2143.     tptr->lo_form.ele_attrmask &= ~LO_ELE_INVISIBLE;
  2144.     tptr->lo_form.ele_attrmask |= LO_ELE_INVISIBLE * !visible;
  2145.     break;
  2146.     case LO_EMBED:
  2147.     tptr->lo_embed.ele_attrmask &= ~LO_ELE_INVISIBLE;
  2148.     tptr->lo_embed.ele_attrmask |= LO_ELE_INVISIBLE * !visible;
  2149.     break;
  2150. #ifdef JAVA
  2151.     case LO_JAVA:
  2152.     tptr->lo_java.ele_attrmask &= ~LO_ELE_INVISIBLE;
  2153.     tptr->lo_java.ele_attrmask |= LO_ELE_INVISIBLE * !visible;
  2154.     break;
  2155. #endif
  2156.     default:
  2157.     XP_ASSERT(0);
  2158.     return;
  2159.     }
  2160.  
  2161.     lo_update_embedded_object_window(layer);
  2162. }
  2163.  
  2164. static void
  2165. lo_window_layer_position_changed(CL_Layer *layer,
  2166.                  int32 x_offset, int32 y_offset)
  2167.     lo_update_embedded_object_window(layer);
  2168. }
  2169.  
  2170. /* Only set if we're a print context */
  2171. static void
  2172. lo_embedded_object_painter_func(CL_Drawable *drawable, 
  2173.                                 CL_Layer *layer, 
  2174.                                 FE_Region update_region)
  2175. {
  2176.     lo_EmbeddedObjectClosure *closure = 
  2177.         (lo_EmbeddedObjectClosure *)CL_GetLayerClientData(layer);
  2178.     
  2179.     FE_SetDrawable(closure->context, drawable);
  2180.  
  2181.     lo_update_embedded_object_window(layer);
  2182.  
  2183.     FE_SetDrawable(closure->context, NULL);
  2184. }
  2185.  
  2186. /* Create a child layer to contain an embedded object, e.g. a plugin,
  2187.    applet or form widget. The child layer may be created as a "cutout"
  2188.    layer if the embedded object is a window, to prevent the compositor
  2189.    from overdrawing the window's contents. */
  2190. CL_Layer *
  2191. lo_CreateEmbeddedObjectLayer(MWContext *context,
  2192.                              lo_DocState *state, LO_Element *tptr)
  2193. {
  2194.     PRBool is_window;
  2195.     LO_Any *any = &tptr->lo_any;
  2196.     CL_Layer *layer, *parent_layer, *doc_layer;
  2197.     char *name;
  2198.     XP_Rect bbox;
  2199.     lo_EmbeddedObjectClosure *closure;
  2200.     CL_LayerVTable vtable;
  2201.     int vspace, hspace;
  2202.     int32 layer_x_offset, layer_y_offset;
  2203.  
  2204.     /* Layer is initially hidden, until lo_DisplayWhatever is called. */
  2205.     uint32 flags = CL_DONT_ENUMERATE | CL_HIDDEN;
  2206.  
  2207.     if (! context->compositor)
  2208.         return NULL;
  2209.  
  2210.     /* These types of elements aren't truly layers (they're embedded
  2211.        windows), so we can't hide them directly through the layer API.
  2212.        We need to set a flag so that the FE knows not to draw the
  2213.        window initially. */
  2214.     switch (tptr->type) {
  2215.     case LO_FORM_ELE:
  2216.     name = "_FORM_ELEMENT";
  2217.     tptr->lo_form.ele_attrmask  |= LO_ELE_INVISIBLE;
  2218.     vspace = tptr->lo_form.border_vert_space;
  2219.     hspace = tptr->lo_form.border_horiz_space;
  2220.     is_window = PR_TRUE;
  2221.     break;
  2222.     case LO_EMBED:
  2223.     name = "_PLUGIN";
  2224.     tptr->lo_embed.ele_attrmask |= LO_ELE_INVISIBLE;
  2225.     /* We don't commit to the type of a plugin layer until
  2226.        it's known whether or not the plugin is windowless. */
  2227.     vspace = tptr->lo_embed.border_vert_space;
  2228.     hspace = tptr->lo_embed.border_horiz_space;
  2229.     is_window = PR_FALSE;
  2230. #ifdef SHACK
  2231.     if (XP_STRNCASECMP (tptr->lo_embed.value_list[0], "builtin/", 8) == 0) {
  2232.         is_window = PR_TRUE;
  2233.     }
  2234. #endif /* SHACK */
  2235.     break;
  2236. #ifdef JAVA
  2237.     case LO_JAVA:
  2238.     name = "_JAVA_APPLET";
  2239.     tptr->lo_java.ele_attrmask  |= LO_ELE_INVISIBLE;
  2240.     vspace = tptr->lo_java.border_vert_space;
  2241.     hspace = tptr->lo_java.border_horiz_space;
  2242.     is_window = PR_TRUE;
  2243.     break;
  2244. #endif
  2245.     default:
  2246.     XP_ASSERT(0);
  2247.     return NULL;
  2248.     }
  2249.  
  2250.     /* The layer is the size of the layout element.
  2251.      (For a plugin, this may not *really* reflect the size of the element,
  2252.      but it will get resized later.) */
  2253.     layer_x_offset = any->x + any->x_offset + hspace;
  2254.     layer_y_offset = any->y + any->y_offset + vspace;
  2255.  
  2256.     bbox.left   = 0;
  2257.     bbox.top    = 0;
  2258.     bbox.right  = any->width  - 2 * hspace;
  2259.     bbox.bottom = any->height - 2 * vspace;
  2260.     
  2261.     closure = XP_NEW_ZAP(lo_EmbeddedObjectClosure);
  2262.     closure->type = LO_EMBEDDED_OBJECT_LAYER;
  2263.  
  2264.     closure->context = context;
  2265.     closure->element = tptr;
  2266.  
  2267.     XP_BZERO(&vtable, sizeof(CL_LayerVTable));    
  2268.  
  2269.     if (is_window) {
  2270.         if (context->type != MWContextPrint)
  2271.             flags |= CL_CUTOUT;
  2272.         closure->is_windowed = PR_TRUE;
  2273.     }
  2274.  
  2275.     vtable.visibility_changed_func = lo_window_layer_visibility_changed;
  2276.     vtable.position_changed_func = lo_window_layer_position_changed;
  2277.     vtable.destroy_func = (CL_DestroyFunc)lo_html_destroy_func;
  2278.     if (context->type == MWContextPrint)
  2279.         vtable.painter_func = (CL_PainterFunc)lo_embedded_object_painter_func;
  2280.  
  2281.     layer = CL_NewLayer(name, layer_x_offset, layer_y_offset,
  2282.                         &bbox, &vtable, flags, (void *)closure);
  2283.  
  2284.     /*
  2285.      * XXX I don't really like this. For embeds that
  2286.      * are part of the _BASE layer, we need to special case
  2287.      * the parent layer of the embed layer, since
  2288.      * the _DOCUMENT layer (and not the _BASE layer) is on
  2289.      * the layer stack.
  2290.      * This code exists for cell bg creation, too.
  2291.      */
  2292.     doc_layer = CL_GetCompositorRoot(context->compositor);
  2293.     parent_layer = lo_CurrentLayer(state);
  2294.     if (parent_layer == doc_layer) {
  2295.         lo_TopState *top_state = lo_get_layer_top_state(layer);
  2296.         parent_layer = top_state->body_layer;
  2297.     }
  2298.  
  2299.     XP_ASSERT(parent_layer);
  2300.  
  2301.     if (parent_layer)
  2302.           CL_InsertChildByZ(parent_layer, layer, Z_CONTENT_LAYERS);
  2303.  
  2304.     return layer;
  2305. }
  2306.  
  2307. /**********************
  2308.  *
  2309.  * Java Applet layer code
  2310.  *
  2311.  **********************/
  2312. #ifdef JAVA
  2313.  
  2314. #include "java.h"
  2315.  
  2316. static void
  2317. lo_java_painter_func(CL_Drawable *drawable, CL_Layer *layer, FE_Region update_region)
  2318. {
  2319.     lo_EmbeddedObjectClosure *closure;
  2320.     LO_JavaAppStruct *javaData;
  2321.     
  2322.     closure = (lo_EmbeddedObjectClosure *)CL_GetLayerClientData(layer);
  2323.     javaData = (LO_JavaAppStruct*)closure->element;
  2324.     
  2325.     FE_SetDrawable(closure->context, drawable);
  2326.     FE_DrawJavaApp(closure->context, FE_VIEW, javaData);
  2327.     FE_SetDrawable(closure->context, NULL);
  2328. }
  2329.  
  2330. static PRBool
  2331. lo_java_event_handler_func(CL_Layer *layer, CL_Event *event)
  2332. {
  2333.     NAppletEvent evt;
  2334.     lo_EmbeddedObjectClosure *closure =
  2335.                                 (lo_EmbeddedObjectClosure *)CL_GetLayerClientData(layer);
  2336.  
  2337.     evt.id = 0;
  2338.     evt.data = (void*)event;
  2339.     return LJ_HandleEvent(closure->context, 
  2340.                             (LO_JavaAppStruct*)closure->element, 
  2341.                             (void*)&evt);
  2342. }
  2343.  
  2344.  
  2345. /* Modify the way in which a plugin's layer draws depending on whether
  2346.    or not it is a windowless plugin. */
  2347. void
  2348. LO_SetJavaAppTransparent(LO_JavaAppStruct *javaData)
  2349. {
  2350.     XP_Rect bbox;
  2351.     CL_LayerVTable vtable;
  2352.     lo_EmbeddedObjectClosure *closure;
  2353.     CL_Layer *layer = javaData->layer;
  2354.     XP_ASSERT(layer);
  2355.     if (! layer)
  2356.     return;
  2357.     
  2358.     closure = (lo_EmbeddedObjectClosure *)CL_GetLayerClientData(layer);
  2359.     XP_ASSERT(closure->type == LO_EMBEDDED_OBJECT_LAYER);
  2360.     closure->is_windowed = PR_FALSE;
  2361.  
  2362.     XP_BZERO(&vtable, sizeof(CL_LayerVTable));    
  2363.     vtable.destroy_func = (CL_DestroyFunc)lo_html_destroy_func;
  2364.  
  2365.     /* Windowless plugin */
  2366.     vtable.painter_func = lo_java_painter_func;
  2367.     vtable.event_handler_func = lo_java_event_handler_func;
  2368.  
  2369.     CL_SetLayerVTable(layer, &vtable);
  2370.     CL_ChangeLayerFlag(layer, CL_CUTOUT, PR_FALSE);
  2371.  
  2372.     /* At this point, the size of the plugin is known. */
  2373.     bbox.left = 0;
  2374.     bbox.top = 0;
  2375.     bbox.right = javaData->width;
  2376.     bbox.bottom = javaData->height;
  2377.     CL_SetLayerBbox(layer, &bbox);
  2378. }
  2379.  
  2380. #endif
  2381.  
  2382. /**********************
  2383.  *
  2384.  * Plugin layer code
  2385.  *
  2386.  **********************/
  2387.  
  2388. static void
  2389. lo_embed_painter_func(CL_Drawable *drawable, CL_Layer *layer, 
  2390.                       FE_Region update_region)
  2391. {
  2392.     lo_EmbeddedObjectClosure *closure;
  2393.     LO_EmbedStruct *embed;
  2394.     
  2395.     closure = (lo_EmbeddedObjectClosure *)CL_GetLayerClientData(layer);
  2396.     embed = (LO_EmbedStruct*)closure->element;
  2397.     
  2398.     FE_SetDrawable(closure->context, drawable);
  2399.     FE_DisplayEmbed(closure->context, FE_VIEW, embed);
  2400.     FE_SetDrawable(closure->context, NULL);
  2401. }
  2402.  
  2403. static PRBool
  2404. lo_windowless_embed_event_handler_func(CL_Layer *layer, CL_Event *event)
  2405. {
  2406.     lo_EmbeddedObjectClosure *closure =
  2407.         (lo_EmbeddedObjectClosure *)CL_GetLayerClientData(layer);
  2408.  
  2409.     return FE_HandleEmbedEvent(closure->context, 
  2410.                                (LO_EmbedStruct*)closure->element, 
  2411.                                event);
  2412. }
  2413.  
  2414.  
  2415. /* Modify the way in which a plugin's layer draws depending on whether
  2416.    or not it is a windowless plugin. */
  2417. void
  2418. LO_SetEmbedType(LO_EmbedStruct *embed, PRBool is_windowed)
  2419. {
  2420.     XP_Rect bbox;
  2421.     CL_LayerVTable vtable;
  2422.     lo_EmbeddedObjectClosure *closure;
  2423.     CL_Layer *layer = embed->layer;
  2424.     XP_ASSERT(layer);
  2425.     if (! layer)
  2426.     return;
  2427.     
  2428.     closure = (lo_EmbeddedObjectClosure *)CL_GetLayerClientData(layer);
  2429.     XP_ASSERT(closure->type == LO_EMBEDDED_OBJECT_LAYER);
  2430.     closure->is_windowed = is_windowed;
  2431.  
  2432.     XP_BZERO(&vtable, sizeof(CL_LayerVTable));    
  2433.     vtable.destroy_func = (CL_DestroyFunc)lo_html_destroy_func;
  2434.     if (is_windowed) {
  2435.     /* Windowed plugin */
  2436.     vtable.visibility_changed_func = lo_window_layer_visibility_changed;
  2437.     vtable.position_changed_func = lo_window_layer_position_changed;
  2438.     if (closure->context->type == MWContextPrint)
  2439.         vtable.painter_func = (CL_PainterFunc)lo_embedded_object_painter_func;
  2440.     } else {
  2441.     /* Windowless plugin */
  2442.     vtable.painter_func = lo_embed_painter_func;
  2443.     vtable.event_handler_func = lo_windowless_embed_event_handler_func;
  2444.     CL_ChangeLayerFlag(layer, CL_PREFER_DRAW_OFFSCREEN,
  2445.                        (PRBool)((CL_GetLayerFlags(layer) & CL_OPAQUE) == 0));
  2446.    }
  2447.     CL_SetLayerVTable(layer, &vtable);
  2448.     if (closure->context->type != MWContextPrint)
  2449.         CL_ChangeLayerFlag(layer, CL_CUTOUT, is_windowed);
  2450.  
  2451.     /* At this point, the size of the plugin is known. */
  2452.     bbox.left = 0;
  2453.     bbox.top = 0;
  2454.     bbox.right = embed->width;
  2455.     bbox.bottom = embed->height;
  2456.     CL_SetLayerBbox(layer, &bbox);
  2457.  
  2458.     if (is_windowed && !CL_GetLayerHidden(layer))
  2459.         lo_update_embedded_object_window(layer);
  2460. }
  2461.  
  2462.  
  2463. /**********************
  2464.  *
  2465.  * Image layering code
  2466.  *
  2467.  **********************/
  2468.  
  2469. #define ICON_X_OFFSET 4
  2470. #define ICON_Y_OFFSET 4
  2471.  
  2472. typedef struct lo_ImageRectStruct
  2473. {
  2474.     lo_ImageLayerClosure *closure;
  2475.     CL_Layer *layer;
  2476. } lo_ImageRectStruct;
  2477.  
  2478.  
  2479. /* Create a text element to be used to display ALT text. */
  2480. static LO_TextStruct *
  2481. lo_AltTextElement(MWContext *context)
  2482. {
  2483.     lo_TopState *top_state;
  2484.     lo_DocState *state;
  2485.     LO_TextStruct *text;
  2486.  
  2487.     /*
  2488.      * Get the unique document ID, and retrieve this
  2489.      * documents layout state.
  2490.      */
  2491.     top_state = lo_FetchTopState(XP_DOCID(context));
  2492.     if ((top_state == NULL) || (top_state->doc_state == NULL)) {
  2493.         return NULL;
  2494.     }
  2495.     state = lo_CurrentSubState(top_state->doc_state);
  2496.  
  2497.     text = XP_NEW_ZAP(LO_TextStruct);
  2498.     if (!text)
  2499.         return NULL;
  2500.     text->text_attr = XP_NEW_ZAP(LO_TextAttr);
  2501.     if (!text->text_attr)
  2502.         return NULL;
  2503.  
  2504.     lo_SetDefaultFontAttr(state, text->text_attr, context);
  2505.  
  2506.     return text;
  2507. }
  2508.  
  2509. /* Draw an icon, ALT text and a temporary border. */
  2510. static void
  2511. lo_ImageDelayed(MWContext *context, LO_ImageStruct *image, int icon_number, int x, int y)
  2512. {
  2513.     int icon_width, icon_height;
  2514.     int x_offset, y_offset;
  2515.     PRBool drew_icon = PR_FALSE;
  2516.     LO_Color color;
  2517.     LO_TextStruct *text;
  2518.     IL_GroupContext *img_cx;
  2519.     
  2520.     /* Offsets for drawing the icon and ALT text. */
  2521.     x_offset = ICON_X_OFFSET;
  2522.     y_offset = ICON_Y_OFFSET;
  2523.     
  2524.     /* Draw the delayed icon. */
  2525.     img_cx = context->img_cx;
  2526.     IL_GetIconDimensions(img_cx, icon_number, &icon_width, &icon_height);
  2527.     if (x_offset + icon_width <= image->width &&
  2528.         y_offset + icon_height <= image->height) {
  2529.         IL_DisplayIcon(img_cx, icon_number, x + x_offset, y + y_offset);
  2530.         drew_icon = PR_TRUE;
  2531.     }
  2532.     
  2533.     /* Draw the ALT text. */
  2534.     if (image->alt) {
  2535.         text = lo_AltTextElement(context);
  2536.         if (text) {
  2537.             XP_Rect frame;
  2538.             int total_width, total_height, text_width, text_height;
  2539.             LO_TextInfo text_info;
  2540.  
  2541.             text->text = image->alt;
  2542.             text->text_len = image->alt_len;
  2543.              FE_GetTextInfo(context, text, &text_info);
  2544.  
  2545.             text->width = text_info.max_width;
  2546.             text->height = text_info.ascent + text_info.descent;
  2547.              if (drew_icon) {
  2548.                 int h_space = 3;
  2549.  
  2550.                 x_offset += icon_width + h_space;
  2551.                 y_offset += (icon_height - text->height) / 2;
  2552.             }
  2553.             text->x = x + x_offset;
  2554.             text->y = y + y_offset;
  2555.  
  2556.             FE_GetTextFrame(context, text, 0, text->text_len - 1, &frame);
  2557.  
  2558.             text_width = frame.right - frame.left;
  2559.             text_height = frame.bottom - frame.top;
  2560.  
  2561.             if (text_width && text_height) {
  2562.                 total_width = text_width + x_offset;
  2563.                 total_height = text_height + y_offset;
  2564.  
  2565.                 if (total_width <= image->width &&
  2566.                     total_height <= image->height)
  2567.                     FE_DisplayText(context, FE_VIEW, text, FALSE);
  2568.             }
  2569.  
  2570.             /* Free the ALT text element. */
  2571.             XP_FREE(text->text_attr);
  2572.             XP_FREE(text);
  2573.         }
  2574.     }
  2575.  
  2576.     /* Draw a temporary border within the bounds of the image.  We only do this
  2577.        if a border has not already been specified for the image. */
  2578.     if (!image->border_width) {
  2579.         color.red = color.green = color.blue = 0;
  2580.         FE_DisplayBorder(context, FE_VIEW, x, y, image->width, image->height,
  2581.                          1, &color, LO_BEVEL);
  2582.     }
  2583. }
  2584.  
  2585.  
  2586. /* Called for each rectangle in the update region */
  2587. static void
  2588. lo_image_rect_func(void *inclosure,
  2589.                    XP_Rect *rect)
  2590. {
  2591.     lo_ImageLayerClosure *closure = ((lo_ImageRectStruct *)inclosure)->closure;
  2592.     MWContext *context = closure->context;
  2593.     CL_Layer *layer = ((lo_ImageRectStruct *)inclosure)->layer;
  2594.     LO_ImageStruct *image = closure->image;
  2595.     int32 layer_x_origin, layer_y_origin;
  2596.     XP_Rect bbox = {0, 0, 0, 0};
  2597.     CL_Compositor *compositor = CL_GetLayerCompositor(layer);
  2598.  
  2599.     CL_WindowToDocumentRect(CL_GetLayerCompositor(layer), rect);
  2600.  
  2601.     /* Convert layer origin to document coordinates */
  2602.     CL_LayerToWindowRect(compositor, layer, &bbox);
  2603.     CL_WindowToDocumentRect(compositor, &bbox);
  2604.     layer_x_origin = bbox.left;
  2605.     layer_y_origin = bbox.top;
  2606.  
  2607.     /* Draw the image or icon. */
  2608.     if (image->is_icon) {
  2609.         char *image_url;
  2610.  
  2611.         PA_LOCK(image_url, char *, image->image_url);
  2612.         /* Determine whether the icon was explicitly requested by URL
  2613.            (in which case only the icon is drawn) or whether it needs
  2614.            to be drawn as a placeholder (along with the ALT text and
  2615.            placeholder border) as a result of a failed image request. */
  2616.         if (image_url &&
  2617.             (*image_url == 'i'              ||
  2618.              !XP_STRNCMP(image_url, "/mc-", 4)  ||
  2619.              !XP_STRNCMP(image_url, "/ns-", 4))) {
  2620.             IL_DisplayIcon(closure->context->img_cx, image->icon_number, 0, 0);
  2621.         }
  2622.         else {
  2623.             lo_ImageDelayed(closure->context, image, image->icon_number, 0, 0);
  2624.         }
  2625.         PA_UNLOCK(image->image_url);
  2626.     }
  2627.     else {
  2628.         /* Note: if the compositor is ever used with contexts which have a
  2629.            scale factor other than unity, then all length arguments should
  2630.            be divided by the appropriate context scaling factor i.e.
  2631.            convertPixX, convertPixY.  The FE callback is responsible for
  2632.            context specific scaling. */
  2633.        IL_DisplaySubImage(image->image_req, 0, 0,
  2634.                           (rect->left - layer_x_origin) / context->convertPixX,
  2635.                           (rect->top - layer_y_origin) / context->convertPixY,
  2636.                           (rect->right - rect->left) / context->convertPixX,
  2637.                           (rect->bottom - rect->top) / context->convertPixY);
  2638.     }
  2639. }
  2640.  
  2641. /* painter_func for an image layer */
  2642. static void
  2643. lo_image_painter_func(CL_Drawable *drawable, 
  2644.                       CL_Layer *layer, 
  2645.                       FE_Region update_region)
  2646. {
  2647.     lo_ImageLayerClosure *closure = (lo_ImageLayerClosure *)CL_GetLayerClientData(layer);
  2648.     lo_ImageRectStruct image_rect;
  2649.     LO_ImageStruct *image = closure->image;
  2650.     int32 save_x, save_y, save_y_offset, save_bw;
  2651.     int16 save_x_offset;
  2652.     
  2653.     image_rect.closure = closure;
  2654.     image_rect.layer = layer;
  2655.  
  2656.     FE_SetDrawable(closure->context, drawable);
  2657.  
  2658.     /* XXX - temporary, because Exceed X server has bugs with its
  2659.        offscreen tiling of clipped areas. */
  2660.     /* NOTE -- this may cause a significant performance hit on other
  2661.      * Unix platforms.  Is there no other way around this Exceed bug?
  2662.      */
  2663. #ifdef XP_UNIX
  2664.     FE_ForEachRectInRegion(update_region, 
  2665.                (FE_RectInRegionFunc)lo_image_rect_func,
  2666.                (void *)&image_rect);
  2667. #else
  2668.     CL_ForEachRectCoveringRegion(update_region, 
  2669.                  (FE_RectInRegionFunc)lo_image_rect_func,
  2670.                  (void *)&image_rect);
  2671. #endif
  2672.  
  2673.     /* Draw selection feedback. */
  2674.     save_x = image->x;
  2675.     save_y = image->y;
  2676.     save_x_offset = image->x_offset;
  2677.     save_y_offset = image->y_offset;
  2678.     save_bw = image->border_width;
  2679.     image->x = image->y = image->y_offset = image->border_width = 0;
  2680.     image->x_offset = 0;
  2681.     
  2682.     FE_DisplayFeedback(closure->context, FE_VIEW, (LO_Element*)image);
  2683.  
  2684.     image->x = save_x;
  2685.     image->y = save_y;
  2686.     image->x_offset = save_x_offset;
  2687.     image->y_offset = save_y_offset;
  2688.     image->border_width = save_bw;
  2689.  
  2690.     FE_SetDrawable(closure->context, NULL);
  2691. }
  2692.  
  2693. static void
  2694. lo_image_destroy_func(CL_Layer *layer)
  2695. {
  2696.     lo_ImageLayerClosure *closure = (lo_ImageLayerClosure *)CL_GetLayerClientData(layer);
  2697.  
  2698.     closure->image->layer = NULL;
  2699.     
  2700.     XP_DELETE(closure);
  2701. }
  2702.  
  2703. /* Create the image layer */
  2704. CL_Layer *
  2705. lo_CreateImageLayer(MWContext *context, LO_ImageStruct *image,
  2706.                     CL_Layer *parent)
  2707. {
  2708.     CL_Layer *layer;
  2709.     XP_Rect bbox = {0, 0, 0, 0};
  2710.     CL_LayerVTable vtable;
  2711.     lo_ImageLayerClosure *closure;
  2712.     int32 layer_x_offset, layer_y_offset;
  2713.     int bw = image->border_width;
  2714.     char *name, *str;
  2715.  
  2716.     uint32 flags = CL_OPAQUE | CL_DONT_ENUMERATE | CL_HIDDEN;
  2717.  
  2718.     layer_x_offset = image->x + image->x_offset + bw;
  2719.     layer_y_offset = image->y + image->y_offset + bw;
  2720.     
  2721.     XP_BZERO(&vtable, sizeof(CL_LayerVTable));
  2722.     vtable.painter_func = lo_image_painter_func;
  2723.     vtable.destroy_func = lo_image_destroy_func;
  2724.  
  2725.     closure = XP_NEW_ZAP(lo_ImageLayerClosure);
  2726.     closure->type = LO_IMAGE_LAYER;
  2727.     closure->context = context;
  2728.  
  2729.     PA_LOCK(str, char *, image->image_url);
  2730.     name = str;
  2731.  
  2732.     PA_UNLOCK(image->image_url);
  2733.  
  2734.     layer = CL_NewLayer(name, layer_x_offset, layer_y_offset, &bbox,
  2735.                         &vtable, flags, (void *)closure);
  2736.  
  2737.     /* Insert the image layer the _CONTENT layer. */
  2738.     if (parent)
  2739.         CL_InsertChildByZ(parent, layer, Z_CONTENT_LAYERS);
  2740.  
  2741.     closure->image = image;
  2742.  
  2743.     return layer;
  2744. }
  2745.  
  2746. /* Activate an image layer, allowing the compositor to start making calls to
  2747.    display the image.  This routine should be called only after the layout
  2748.    position of an image has been finalized, and it should only be called if
  2749.    the compositor exists. */
  2750. void
  2751. lo_ActivateImageLayer(MWContext *context, LO_ImageStruct *image)
  2752. {
  2753.     PRBool suppress_mode, is_mocha_image, draw_delayed_icon;
  2754.      int x, y;
  2755.     CL_Layer *layer;
  2756.     char *image_url;
  2757.     
  2758.     XP_ASSERT(context->compositor);
  2759.     layer = image->layer;
  2760.     XP_ASSERT(layer);
  2761.     if (! layer)                /* Paranoia */
  2762.         return;
  2763.  
  2764.     /* Determine the feedback suppression mode for non-icon, non-backdrop
  2765.        images. */
  2766.     switch (image->suppress_mode) {
  2767.     case LO_SUPPRESS_UNDEFINED:
  2768.         suppress_mode = (PRBool)image->is_transparent;
  2769.         break;
  2770.         
  2771.     case LO_SUPPRESS:
  2772.         suppress_mode = PR_TRUE;
  2773.         break;
  2774.         
  2775.     case LO_DONT_SUPPRESS:
  2776.         suppress_mode = PR_FALSE;
  2777.         break;
  2778.         
  2779.     default:
  2780.         break;
  2781.     }
  2782.  
  2783.     /* Don't draw delayed icon for JavaScript-generated images. */
  2784.     PA_LOCK(image_url, char *, image->image_url);
  2785.     if (NET_URL_Type(image_url) == MOCHA_TYPE_URL)
  2786.         is_mocha_image = PR_TRUE;
  2787.     else
  2788.         is_mocha_image = PR_FALSE;
  2789.     PA_UNLOCK(image->image_url);
  2790.  
  2791.     /* Determine whether to draw the delayed icon, ALT text and a 
  2792.        temporary border as the image is loading. */
  2793.     draw_delayed_icon = (PRBool)(!suppress_mode && !image->is_icon &&
  2794.         !is_mocha_image && image->image_attr &&
  2795.         !(image->image_attr->attrmask & LO_ATTR_BACKDROP) &&
  2796.         (image->image_status != IL_FRAME_COMPLETE) &&
  2797.         (image->image_status != IL_IMAGE_COMPLETE));
  2798.  
  2799.     if (!(image->ele_attrmask & LO_ELE_DRAWN)) {
  2800.         /* Determine the new position of the layer. */
  2801.         x = image->x + image->x_offset + image->border_width;
  2802.         y = image->y + image->y_offset + image->border_width;
  2803.  
  2804.         /* Move layer to new position and unhide it. */
  2805.         CL_MoveLayer(layer,    x, y);
  2806.         CL_SetLayerHidden(layer, PR_FALSE);
  2807.         image->ele_attrmask |= LO_ELE_DRAWN;
  2808.  
  2809.         /* In order to increase the perceived speed of image loading,
  2810.            non-backdrop, non-icon images have the delayed icon, ALT text
  2811.            and a temporary border drawn in their place before they come in. */
  2812.         if (draw_delayed_icon)
  2813.             lo_ImageDelayed(context, image, IL_IMAGE_DELAYED, x, y);
  2814.     }
  2815.     else {
  2816.         /* In order to increase the perceived speed of image loading,
  2817.            non-backdrop, non-icon images have the delayed icon, ALT text
  2818.            and a temporary border drawn in their place before they come in. */
  2819.         XP_Rect *valid_rect = &image->valid_rect;
  2820.         int valid_width, valid_height;
  2821.  
  2822.         valid_width = valid_rect->right - valid_rect->left;
  2823.         valid_height = valid_rect->bottom - valid_rect->top;
  2824.  
  2825.         /* Get the offset of the image layer relative to its parent layer. */
  2826.         x = CL_GetLayerXOffset(image->layer);
  2827.         y = CL_GetLayerYOffset(image->layer);
  2828.  
  2829.         if (draw_delayed_icon && !valid_width && !valid_height)
  2830.             lo_ImageDelayed(context, image, IL_IMAGE_DELAYED, x, y);
  2831.     }
  2832. }
  2833.  
  2834. #ifdef DEBUG
  2835. /* Utility function for debugging */
  2836. MWContext *
  2837. LO_CompositorToContext(CL_Compositor *compositor)
  2838. {
  2839.     CL_Layer *doc_layer = CL_GetCompositorRoot(compositor);
  2840.     lo_GroupLayerClosure *closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(doc_layer);
  2841.     return closure->context;
  2842. }
  2843. #endif /* DEBUG */
  2844.  
  2845. #ifdef PROFILE
  2846. #pragma profile off
  2847. #endif
  2848.