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

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19.  
  20. #include "xp.h"
  21. /*
  22.  * Mocha layout interface.
  23.  */
  24. #include "lo_ele.h"
  25. #include "layout.h"
  26. #include "laylayer.h"
  27. #include "pa_parse.h"
  28. #include "libevent.h"
  29. #ifdef JAVA
  30. #include "jsjava.h"
  31. #endif
  32. #include "layers.h"
  33.  
  34. PRIVATE
  35. lo_TopState *
  36. lo_GetTopState(MWContext *context)
  37. {
  38.     int32 doc_id;
  39.     lo_TopState *top_state;
  40.  
  41.     if (!context)
  42.         return NULL ;
  43.  
  44.     doc_id = XP_DOCID(context);
  45.     top_state = lo_FetchTopState(doc_id);
  46.     if (top_state != NULL && top_state->doc_state == NULL)
  47.         return NULL;
  48.     return top_state;
  49. }
  50.  
  51. lo_TopState *
  52. lo_GetMochaTopState(MWContext *context)
  53. {
  54.     lo_TopState *top_state;
  55.  
  56.     top_state = lo_GetTopState(context);
  57.     if (top_state == NULL)
  58.         return NULL;
  59.     return top_state;
  60. }
  61.  
  62. lo_FormData *
  63. LO_GetFormDataByID(MWContext *context, int32 layer_id, intn form_id)
  64. {
  65.     lo_TopState *top_state;
  66.     lo_FormData *form;
  67.     lo_DocLists *doc_lists;
  68.  
  69.     top_state = lo_GetTopState(context);
  70.     if (top_state == NULL)
  71.         return NULL;
  72.  
  73.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  74.     if (!doc_lists)
  75.         return NULL;
  76.     
  77.     for (form = doc_lists->form_list; form != NULL; form = form->next) {
  78.         if (form->id == form_id)
  79.             return form;
  80.     }
  81.     return NULL;
  82. }
  83.  
  84. /*
  85.  * This can only safely be called while holding the JS_Lock
  86.  */
  87. uint
  88. LO_EnumerateForms(MWContext *context, int32 layer_id)
  89. {
  90.     lo_TopState *top_state;
  91.     lo_FormData *form;
  92.     lo_DocLists *doc_lists;
  93.  
  94.     top_state = lo_GetMochaTopState(context);
  95.     if (top_state == NULL)
  96.         return 0;
  97.  
  98.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  99.     if (!doc_lists)
  100.         return 0;
  101.  
  102.     /* Try to reflect all forms in case someone is enumerating. */
  103.     for (form = doc_lists->form_list; form != NULL; form = form->next) {
  104.         if (form->mocha_object == NULL)
  105.         LM_ReflectForm(context, form, NULL, layer_id, 0);
  106.     }
  107.     return doc_lists->current_form_num;
  108. }
  109.  
  110. /*
  111.  * Note that index is zero-based from the first form, and if in the second
  112.  * form, is one more than the index of the last element in the first form.
  113.  * So we subtract form's first element index before subscripting.
  114.  */
  115. LO_FormElementStruct *
  116. LO_GetFormElementByIndex(lo_FormData *form, int32 index)
  117. {
  118.     LO_Element **ele_list;
  119.     LO_FormElementStruct *form_element;
  120.  
  121.     if (form->form_elements == NULL)
  122.         return NULL;
  123.     PA_LOCK(ele_list, LO_Element **, form->form_elements);
  124.     form_element = (LO_FormElementStruct *)ele_list[0];
  125.     index -= form_element->element_index;
  126.     if ((uint32)index < (uint32)form->form_ele_cnt)
  127.         form_element = (LO_FormElementStruct *)ele_list[index];
  128.     else
  129.         form_element = NULL;
  130.     PA_UNLOCK(form->form_elements);
  131.     if (form_element == NULL || form_element->element_data == NULL)
  132.         return NULL;
  133.     return form_element;
  134. }
  135.  
  136.  
  137. /*
  138.  * This can only safely be called while holding the JS_Lock
  139.  */
  140. uint
  141. LO_EnumerateFormElements(MWContext *context, lo_FormData *form)
  142. {
  143.     LO_Element **ele_list;
  144.     LO_FormElementStruct *form_element;
  145.     uint i;
  146.  
  147.     /* Try to reflect all elements in case someone is enumerating. */
  148.     PA_LOCK(ele_list, LO_Element **, form->form_elements);
  149.     for (i = 0; i < (uint)form->form_ele_cnt; i++) {
  150.         form_element = (LO_FormElementStruct *)ele_list[i];
  151.         if (form_element->mocha_object == NULL)
  152.         LM_ReflectFormElement(context, form_element->layer_id,
  153.               form->id, form_element->element_index, NULL);
  154.     }
  155.     PA_UNLOCK(form->form_elements);
  156.     return form->form_ele_cnt;
  157. }
  158.  
  159. void
  160. lo_BeginReflectForm(MWContext *context, lo_DocState *doc_state, PA_Tag *tag,
  161.                     lo_FormData *form)
  162. {
  163.     int32 layer_id;
  164.     
  165.     if(!PA_HasMocha(tag))
  166.         return;
  167.  
  168.     layer_id = lo_CurrentLayerId(doc_state);
  169.     ET_ReflectObject(context, (void *) form, tag, layer_id, 
  170.                      form->id, LM_FORMS);
  171.     ET_SetActiveForm(context, form);
  172.  
  173. }
  174.  
  175. LO_ImageStruct *
  176. LO_GetImageByIndex(MWContext *context, int32 layer_id, intn index)
  177. {
  178.     lo_TopState *top_state;
  179.     LO_ImageStruct *image;
  180.     lo_DocLists *doc_lists;
  181.     
  182.     top_state = lo_GetTopState(context);
  183.     if (top_state == NULL)
  184.         return NULL;
  185.  
  186.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  187.     if (!doc_lists)
  188.         return NULL;
  189.     
  190.     for (image = doc_lists->image_list; image != NULL;
  191.          image = image->next_image) {
  192.         if (image && image->seq_num == index)
  193.             return image;
  194.     }
  195.     return NULL;
  196. }
  197.  
  198. uint
  199. LO_EnumerateImages(MWContext *context, int32 layer_id)
  200. {
  201.     lo_TopState *top_state;
  202.     uint image_num;
  203.     LO_ImageStruct *img;
  204.     lo_DocLists *doc_lists;
  205.  
  206.     top_state = lo_GetMochaTopState(context);
  207.     if (top_state == NULL)
  208.         return 0;
  209.  
  210.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  211.     if (!doc_lists)
  212.         return 0;
  213.  
  214.     /* 
  215.      * Try to reflect all images in case someone is enumerating.
  216.      * If its already on the image_list then it already has a valid
  217.      *   seq_num
  218.      */
  219.     image_num = 0;
  220.     for (img = doc_lists->image_list; img; img = img->next_image) {
  221.     if (img->mocha_object == NULL)
  222.         LM_ReflectImage(context, img, NULL, layer_id, img->seq_num);
  223.     image_num++;
  224.     }
  225.     return image_num;
  226. }
  227.  
  228. void
  229. lo_EndReflectForm(MWContext *context, lo_FormData *form_data)
  230. {
  231.     ET_SetActiveForm(context, NULL);
  232. }
  233.  
  234. void
  235. lo_ReflectImage(MWContext *context, lo_DocState *doc_state, PA_Tag *tag,
  236.                 LO_ImageStruct *image, Bool blocked, int32 layer_id)
  237. {
  238.     lo_DocLists *doc_lists;
  239.  
  240.     /* Reflect only IMG tags, not form INPUT tags of TYPE=IMAGE */
  241.     if (tag->type != P_IMAGE && tag->type != P_NEW_IMAGE)
  242.         return;
  243.  
  244.     /* Has this image already been reflected ? */
  245.     if ((image->image_attr->attrmask & LO_ATTR_ON_IMAGE_LIST)) {
  246.         if (! blocked) {
  247.         /* Flush any image events that were sent when the image
  248.                was blocked */
  249.             ET_SendImageEvent(context, image, LM_IMGUNBLOCK);
  250.         }
  251.         return;
  252.     } else {
  253.     /* Add image to global list of images for this document. */
  254.         doc_lists = lo_GetDocListsById(doc_state, layer_id);
  255.         if (!doc_lists)
  256.             return;
  257.  
  258.         image->image_attr->attrmask |= LO_ATTR_ON_IMAGE_LIST;
  259.         image->seq_num = doc_lists->image_list_count++;
  260.         /*
  261.          * If we're in table relayout, we replace the old image
  262.          * in the image list. Note that we also look to see if 
  263.          * the corresponding mocha object has already been allocated.
  264.          * If so, we copy it. If not, it will be set when the 
  265.          * the JS thread gets around to it (the mocha reflection
  266.          * code gets the image by index, so it will get the right
  267.          * one.
  268.          */
  269.         if (doc_state->in_relayout) {
  270.             LO_ImageStruct *cur_image, *prev_image;
  271.             prev_image = NULL;
  272.             
  273.             for (cur_image = doc_lists->image_list; cur_image != NULL;
  274.                  prev_image=cur_image, cur_image=cur_image->next_image) {
  275.                 if (cur_image->seq_num == image->seq_num) {
  276.                     /* Copy over the mocha object (it might not exist) */
  277.                     image->mocha_object = cur_image->mocha_object;
  278.                     
  279.                     /* Replace the old image with the new one */
  280.                     image->next_image = cur_image->next_image;
  281.                     if (prev_image == NULL)
  282.                         doc_lists->image_list = image;
  283.                     else
  284.                         prev_image->next_image = image;
  285.                     if (doc_lists->last_image == cur_image)
  286.                         doc_lists->last_image = image;
  287.                     /* Note that the old image is recycled by the table code */
  288.                     break;
  289.                 }
  290.             }
  291.             return;
  292.         }
  293.         /* Add it to the end of the list */
  294.         else {
  295.             if (doc_lists->last_image)
  296.                 doc_lists->last_image->next_image = image;
  297.             else
  298.                 doc_lists->image_list = image;
  299.             doc_lists->last_image = image;
  300.         }
  301.     }
  302.  
  303.     /* The image is reflected into a Javascript object lazily:
  304.        Immediate reflection only occurs if there are Javascript-only
  305.        attributes in the IMG tag */
  306.     if(!PA_HasMocha(tag))
  307.         return;
  308.  
  309.     ET_ReflectObject(context, (LO_Element *) image, tag, layer_id,
  310.                      image->seq_num, LM_IMAGES);
  311.  
  312.     /* Since the image is unblocked, there is no need to buffer
  313.        any JavaScript image events.  Deliver them as they're generated. */
  314.     if (! blocked)
  315.         ET_SendImageEvent(context, image, LM_IMGUNBLOCK);
  316.  
  317. }
  318.  
  319. void
  320. lo_ReflectFormElement(MWContext *context, lo_DocState *doc_state, PA_Tag *tag,
  321.                       LO_FormElementStruct *form_element)
  322. {
  323.     lo_DocLists *doc_lists;
  324.  
  325.     /* Don't reflect form elements twice, it makes arrays out of them! */
  326.     if (doc_state->in_relayout)
  327.         return;
  328.  
  329.     /* don't do squat if we don't have any mocha */
  330.     if (!PA_HasMocha(tag))
  331.         return;
  332.  
  333.     doc_lists = lo_GetDocListsById(doc_state, form_element->layer_id);
  334.     if (!doc_lists)
  335.         return;
  336.     
  337.     /* reflect the form element */
  338.     ET_ReflectFormElement(context, doc_lists->form_list, form_element, tag);
  339.  
  340. }
  341.  
  342. void
  343. lo_ReflectNamedAnchor(MWContext *context, lo_DocState *doc_state, PA_Tag *tag,
  344.                       lo_NameList *name_rec, int32 layer_id)
  345. {
  346.     lo_DocLists *doc_lists;
  347.  
  348.     if (!doc_state->in_relayout) {
  349.         doc_lists = lo_GetDocListsById(doc_state, layer_id);
  350.         if (!doc_lists)
  351.             return;
  352.         name_rec->index = doc_lists->anchor_count++;
  353.  
  354.         if(!PA_HasMocha(tag))
  355.             return;
  356.  
  357.         ET_ReflectObject(context, (void *) name_rec, tag, 
  358.                          layer_id, name_rec->index, LM_NAMEDANCHORS);
  359.  
  360.     }
  361. }
  362.  
  363.  
  364. lo_NameList *
  365. LO_GetNamedAnchorByIndex(MWContext *context, int32 layer_id, uint index)
  366. {
  367.     lo_TopState *top_state;
  368.     lo_NameList *name_rec, *nptr;
  369.     lo_DocLists *doc_lists;
  370.     
  371.     top_state = lo_GetTopState(context);
  372.     if (top_state == NULL)
  373.         return NULL;
  374.  
  375.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  376.     if (!doc_lists)
  377.         return NULL;
  378.  
  379.     /* The list is not guaranteed to be in reverse-source order when nested
  380.        tables are involved, so search for matching index instead. */
  381.     name_rec = NULL;
  382.     for (nptr = doc_lists->name_list; nptr != NULL; nptr = nptr->next) {
  383.         if (nptr->index == index) {
  384.             name_rec = nptr;
  385.             break;
  386.         }
  387.     }
  388.     return name_rec;
  389. }
  390.  
  391. uint
  392. LO_EnumerateNamedAnchors(MWContext *context, int32 layer_id)
  393. {
  394.     lo_TopState *top_state;
  395.     lo_NameList *name_rec;
  396.     uint count;
  397.     lo_DocLists *doc_lists;
  398.  
  399.     top_state = lo_GetTopState(context);
  400.     if (top_state == NULL)
  401.         return 0;
  402.  
  403.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  404.     if (!doc_lists)
  405.         return 0;
  406.  
  407.     count = 0;
  408.     for (name_rec = doc_lists->name_list; name_rec != NULL;
  409.          name_rec = name_rec->next) {
  410.         if (name_rec->mocha_object == NULL)
  411.         LM_ReflectNamedAnchor(context, (void *) name_rec, NULL, 
  412.                   layer_id, name_rec->index);
  413.         count++;
  414.     }
  415.     return count;
  416. }
  417.  
  418. void
  419. lo_ReflectLink(MWContext *context, lo_DocState *doc_state, PA_Tag *tag,
  420.                LO_AnchorData *anchor_data, int32 layer_id, uint index)
  421. {
  422.     /* if this tag has any mocha, reflect it now */
  423.     if(!PA_HasMocha(tag))
  424.         return;
  425.  
  426.     ET_ReflectObject(context, anchor_data, tag, layer_id, index, LM_LINKS);
  427. }
  428.  
  429. LO_AnchorData *
  430. LO_GetLinkByIndex(MWContext *context, int32 layer_id, uint index)
  431. {
  432.     lo_TopState *top_state;
  433.     LO_AnchorData **anchor_array;
  434.     LO_AnchorData *anchor_data;
  435.     lo_DocLists *doc_lists;
  436.  
  437.     top_state = lo_GetTopState(context);
  438.     if (top_state == NULL)
  439.         return NULL;
  440.  
  441.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  442.     if (!doc_lists)
  443.         return NULL;
  444.     
  445.     if (index >= (uint)doc_lists->url_list_len)
  446.         return NULL;
  447.  
  448.     XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, doc_lists->url_list);
  449.     anchor_data = anchor_array[index];
  450.     XP_UNLOCK_BLOCK(doc_lists->url_list);
  451.     return anchor_data;
  452. }
  453.  
  454. uint
  455. LO_EnumerateLinks(MWContext *context, int32 layer_id)
  456. {
  457.     lo_TopState *top_state;
  458.     uint count, index;
  459.     LO_AnchorData **anchor_array;
  460.     LO_AnchorData *anchor_data;
  461.     lo_DocLists *doc_lists;
  462.  
  463.     top_state = lo_GetMochaTopState(context);
  464.     if (top_state == NULL)
  465.         return 0;
  466.  
  467.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  468.     if (!doc_lists)
  469.         return 0;
  470.     
  471.     /* Try to reflect all links in case someone is enumerating. */
  472.     count = (uint)doc_lists->url_list_len;
  473.     XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, doc_lists->url_list);
  474.     for (index = 0; index < count; index++) {
  475.         anchor_data = anchor_array[index];
  476.         if (anchor_data->mocha_object == NULL)
  477.         LM_ReflectLink(context, anchor_data, NULL, layer_id, index);
  478.     }
  479.     XP_UNLOCK_BLOCK(doc_lists->url_list);
  480.     return count;
  481. }
  482.  
  483. #ifdef JAVA
  484. LO_JavaAppStruct *
  485. LO_GetAppletByIndex(MWContext *context, int32 layer_id, uint index)
  486. {
  487.     lo_TopState *top_state;
  488.     LO_JavaAppStruct *applet;
  489.     int i, count;
  490.     lo_DocLists *doc_lists;
  491.  
  492.     /* XXX */
  493.     if (!JSJ_IsEnabled())
  494.         return NULL;
  495.  
  496.     top_state = lo_GetTopState(context);
  497.     if (top_state == NULL)
  498.         return NULL;
  499.  
  500.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  501.     if (!doc_lists)
  502.         return NULL;
  503.  
  504.     /* count 'em */
  505.     count = 0;
  506.     applet = doc_lists->applet_list;
  507.     while (applet) {
  508.         applet = applet->nextApplet;
  509.         count++;
  510.     }
  511.  
  512.     /* reverse order... */
  513.     applet = doc_lists->applet_list;
  514.     for (i = count-1; i >= 0; i--) {
  515.         if ((uint)i == index)
  516.             return applet;
  517.         applet = applet->nextApplet;
  518.     }
  519.     return NULL;
  520. }
  521.  
  522. uint
  523. LO_EnumerateApplets(MWContext *context, int32 layer_id)
  524. {
  525.     lo_TopState *top_state;
  526.     int count, index;
  527.     LO_JavaAppStruct *applet;
  528.     lo_DocLists *doc_lists;
  529.  
  530.     /* XXX */
  531.     if (!JSJ_IsEnabled())
  532.         return 0;
  533.  
  534.     top_state = lo_GetMochaTopState(context);
  535.     if (top_state == NULL)
  536.         return 0;
  537.  
  538.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  539.     if (!doc_lists)
  540.         return 0;
  541.  
  542.     /* count 'em */
  543.     count = 0;
  544.     applet = doc_lists->applet_list;
  545.     while (applet) {
  546.         applet = applet->nextApplet;
  547.         count++;
  548.     }
  549.  
  550.     /* reflect all applets in reverse order */
  551.     applet = doc_lists->applet_list;
  552.     for (index = count-1; index >= 0; index--) {
  553.         if (applet->mocha_object == NULL)
  554.         LM_ReflectApplet(context, (void *) applet, NULL, layer_id, index);
  555.         applet = applet->nextApplet;
  556.     }
  557.  
  558.     return count;
  559. }
  560.  
  561. LO_EmbedStruct *
  562. LO_GetEmbedByIndex(MWContext *context, int32 layer_id, uint index)
  563. {
  564.     lo_TopState *top_state;
  565.     LO_EmbedStruct *embed;
  566.     int i, count;
  567.     lo_DocLists *doc_lists;
  568.  
  569.     /* XXX */
  570.     if (!JSJ_IsEnabled())
  571.         return NULL;
  572.  
  573.     top_state = lo_GetTopState(context);
  574.     if (top_state == NULL)
  575.         return NULL;
  576.  
  577.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  578.     if (!doc_lists)
  579.         return NULL;
  580.  
  581.     /* count 'em */
  582.     count = 0;
  583.     embed = doc_lists->embed_list;
  584.     while (embed) {
  585.         embed = embed->nextEmbed;
  586.         count++;
  587.     }
  588.  
  589.     /* reverse order... */
  590.     embed = doc_lists->embed_list;
  591.     for (i = count-1; i >= 0; i--) {
  592.         if ((uint)i == index)
  593.             return embed;
  594.         embed = embed->nextEmbed;
  595.     }
  596.     return NULL;
  597. }
  598.  
  599. uint
  600. LO_EnumerateEmbeds(MWContext *context, int32 layer_id)
  601. {
  602.     lo_TopState *top_state;
  603.     int count, index;
  604.     LO_EmbedStruct *embed;
  605.     lo_DocLists *doc_lists;
  606.  
  607.     /* XXX */
  608.     if (!JSJ_IsEnabled())
  609.         return 0;
  610.  
  611.     top_state = lo_GetMochaTopState(context);
  612.     if (top_state == NULL)
  613.         return 0;
  614.  
  615.     doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id);
  616.     if (!doc_lists)
  617.         return 0;
  618.  
  619.     /* count 'em */
  620.     count = 0;
  621.     embed = doc_lists->embed_list;
  622.     while (embed) {
  623.         embed = embed->nextEmbed;
  624.         count++;
  625.     }
  626.  
  627.     /* reflect all embeds in reverse order */
  628.     embed = doc_lists->embed_list;
  629.     for (index = count-1; index >= 0; index--) {
  630.     if (embed->mocha_object == NULL)
  631.             LM_ReflectEmbed(context, (void *) embed, NULL, layer_id, index);
  632.         embed = embed->nextEmbed;
  633.     }
  634.  
  635.     return count;
  636. }
  637. #endif /* JAVA */
  638.  
  639.  
  640. /* XXX lo_DocState should use a colors[LO_NCOLORS] array to shrink code here
  641.        and in layout.c.
  642.  */
  643. void
  644. LO_GetDocumentColor(MWContext *context, int type, LO_Color *color)
  645. {
  646.     lo_TopState *top_state;
  647.     lo_DocState *doc_state;
  648.  
  649.     top_state = lo_GetTopState(context);
  650.     if (top_state == NULL)
  651.         return;
  652.     doc_state = top_state->doc_state;
  653.  
  654.     switch (type) {
  655.       case LO_COLOR_BG:
  656.         *color = doc_state->text_bg;
  657.         break;
  658.       case LO_COLOR_FG:
  659.         *color = doc_state->text_fg;
  660.         break;
  661.       case LO_COLOR_LINK:
  662.         *color = doc_state->anchor_color;
  663.         break;
  664.       case LO_COLOR_VLINK:
  665.         *color = doc_state->visited_anchor_color;
  666.         break;
  667.       case LO_COLOR_ALINK:
  668.         *color = doc_state->active_anchor_color;
  669.         break;
  670.       default:
  671.         break;
  672.     }
  673. }
  674.  
  675. void
  676. LO_SetDocumentColor(MWContext *context, int type, LO_Color *color)
  677. {
  678.     lo_TopState *top_state;
  679.     lo_DocState *doc_state;
  680.  
  681.     top_state = lo_GetTopState(context);
  682.     if (top_state == NULL)
  683.         return;
  684.     doc_state = top_state->doc_state;
  685.     if (color == NULL)
  686.         color = &lo_master_colors[type];
  687.  
  688.     switch (type) {
  689.       case LO_COLOR_BG:
  690.         doc_state->text_bg = *color;
  691.         top_state->doc_specified_bg = TRUE;
  692.         LO_SetDocBgColor(context, color);
  693.         break;
  694.       case LO_COLOR_FG:
  695.         lo_ChangeBodyTextFGColor(context, doc_state, color);
  696.         break;
  697.       case LO_COLOR_LINK:
  698.         doc_state->anchor_color = *color;
  699.         break;
  700.       case LO_COLOR_VLINK:
  701.         doc_state->visited_anchor_color = *color;
  702.         break;
  703.       case LO_COLOR_ALINK:
  704.         doc_state->active_anchor_color = *color;
  705.         break;
  706.       default:;
  707.     }
  708. }
  709.  
  710. XP_Bool
  711. lo_ProcessContextEventHandlers(MWContext *context, lo_DocState *doc_state,
  712.                                PA_Tag *tag)
  713. {
  714.     PA_Block onload, onunload, onfocus, onblur, onhelp, onmouseover, onmouseout,
  715.     ondragdrop, onmove, onresize, id;
  716.     lo_TopState *top_state;
  717.     char *all = 0;
  718.     XP_Bool ret;
  719.  
  720.     ret = FALSE;
  721.     onload = lo_FetchParamValue(context, tag, PARAM_ONLOAD);
  722.     onunload = lo_FetchParamValue(context, tag, PARAM_ONUNLOAD);
  723.     onfocus = lo_FetchParamValue(context, tag, PARAM_ONFOCUS);
  724.     onblur = lo_FetchParamValue(context, tag, PARAM_ONBLUR);
  725.     onhelp = lo_FetchParamValue(context, tag, PARAM_ONHELP);
  726.     onmouseover = lo_FetchParamValue(context, tag, PARAM_ONMOUSEOVER);
  727.     onmouseout = lo_FetchParamValue(context, tag, PARAM_ONMOUSEOUT);
  728.     ondragdrop = lo_FetchParamValue(context, tag, PARAM_ONDRAGDROP);
  729.     onmove = lo_FetchParamValue(context, tag, PARAM_ONMOVE);
  730.     onresize = lo_FetchParamValue(context, tag, PARAM_ONRESIZE);
  731.  
  732.     if (onload == NULL && onunload == NULL && onfocus == NULL && onblur == NULL
  733.         && onhelp == NULL && onmouseover == NULL && onmouseout == NULL && ondragdrop == NULL
  734.     && onmove == NULL && onresize == NULL)
  735.     {
  736.         return ret;
  737.     }
  738.  
  739.     ret = TRUE;
  740.  
  741.     id = lo_FetchParamValue(context, tag, PARAM_ID);
  742.     all = NULL;
  743.     StrAllocCopy(all, (char *) tag->data);
  744.  
  745.     top_state = doc_state->top_state;
  746.  
  747.     /* 
  748.      * If we're in a layer, pass along the tag to the layer reflection 
  749.      * function so that the event handlers get attached to the layer.
  750.      */
  751.     if (lo_InsideLayer(doc_state)) {
  752.         int32 cur_layer_id = lo_CurrentLayerId(doc_state);
  753.         CL_Layer *layer = LO_GetLayerFromId(context, cur_layer_id);
  754.         CL_Layer *parent = CL_GetLayerParent(layer);
  755.         int32 parent_layer_id = LO_GetIdFromLayer(context, parent);
  756.         
  757.         ET_ReflectObject(context, NULL, tag, parent_layer_id, cur_layer_id, 
  758.                          LM_LAYERS);
  759.     }
  760.     else {
  761.         ET_ReflectWindow(context, onload, onunload, onfocus, onblur, onhelp, onmouseover,
  762.              onmouseout, ondragdrop, onmove, onresize, 
  763.                          id, all, tag->type != P_GRID, tag->newline_count);
  764.  
  765.         if (onload != NULL && tag->type == P_BODY)
  766.             top_state->mocha_has_onload = TRUE;
  767.         
  768.         if (onunload != NULL && tag->type == P_BODY)
  769.             top_state->mocha_has_onunload = TRUE;
  770.     
  771.         if (tag->type == P_GRID) {
  772.             top_state->savedData.OnUnload = onunload;
  773.             top_state->savedData.OnFocus = onfocus;
  774.             top_state->savedData.OnBlur = onblur;
  775.             top_state->savedData.OnLoad = onload;
  776.             top_state->savedData.OnHelp = onhelp;
  777.             top_state->savedData.OnMouseOver = onmouseover;
  778.             top_state->savedData.OnMouseOut = onmouseout;
  779.             top_state->savedData.OnDragDrop = ondragdrop;
  780.             top_state->savedData.OnMove = onmove;
  781.             top_state->savedData.OnResize = onresize;
  782.         }
  783.     }
  784.     return ret;
  785. }
  786.  
  787. void
  788. lo_RestoreContextEventHandlers(MWContext *context, lo_DocState *doc_state,
  789.                                PA_Tag *tag, SHIST_SavedData *saved_data)
  790. {
  791.     PA_Block onload, onunload, onfocus, onblur, onhelp, onmouseover, onmouseout, ondragdrop,
  792.     onmove, onresize;
  793.     lo_TopState *top_state;
  794.  
  795.     onload = saved_data->OnLoad;
  796.     onunload = saved_data->OnUnload;
  797.     onfocus = saved_data->OnFocus;
  798.     onblur = saved_data->OnBlur;
  799.     onhelp = saved_data->OnHelp;
  800.     onmouseover = saved_data->OnMouseOver;
  801.     onmouseout = saved_data->OnMouseOut;
  802.     ondragdrop = saved_data->OnDragDrop;
  803.     onmove = saved_data->OnMove;
  804.     onresize = saved_data->OnResize;
  805.     if (onload == NULL && onunload == NULL && onfocus == NULL && onblur == NULL
  806.         && onhelp == NULL && onmouseover == NULL && onmouseout == NULL && ondragdrop == NULL
  807.     && onmove == NULL && onresize == NULL)
  808.         return;
  809.  
  810.     top_state = doc_state->top_state;
  811.  
  812.     /* XXX - could these be signed? */
  813.     ET_ReflectWindow(context, onload, onunload, onfocus, onblur, onhelp, onmouseover,
  814.              onmouseout, ondragdrop, onmove, onresize, 
  815.                      NULL, NULL, FALSE, tag->newline_count);
  816.  
  817.     if (onload != NULL && tag->type == P_BODY)
  818.         top_state->mocha_has_onload = TRUE;
  819.  
  820.     if (onunload != NULL && tag->type == P_BODY)
  821.         top_state->mocha_has_onunload = TRUE;
  822.  
  823.     top_state->savedData.OnUnload = onunload;
  824.     top_state->savedData.OnFocus = onfocus;
  825.     top_state->savedData.OnBlur = onblur;
  826.     top_state->savedData.OnLoad = onload;
  827.     top_state->savedData.OnHelp = onhelp;
  828.     top_state->savedData.OnMouseOver = onmouseover;
  829.     top_state->savedData.OnMouseOut = onmouseout;
  830.     top_state->savedData.OnDragDrop = ondragdrop;
  831.     top_state->savedData.OnMove = onmove;
  832.     top_state->savedData.OnResize = onresize;
  833.  
  834. }
  835.  
  836.