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

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "xp.h"
  20. #include "layout.h"
  21. #include "pa_parse.h"
  22.  
  23. static LO_Element *lo_duplicate_element(MWContext *context, lo_DocState *state,
  24.                     int32 block_watch, LO_Element *eptr);
  25.          
  26. #ifdef XP_WIN16
  27. #define SIZE_LIMIT 32000
  28. #endif
  29.  
  30.  
  31. static LO_Element *
  32. lo_line_to_element(lo_DocState *state, int32 line)
  33. {
  34.     LO_Element *eptr;
  35.     LO_Element **line_array;
  36. #ifdef XP_WIN16
  37.         intn a_size;
  38.         intn a_indx;
  39.         intn a_line;
  40.         XP_Block *larray_array;
  41. #endif /* XP_WIN16 */
  42.  
  43.     if (line >= (state->line_num - 1))
  44.     {
  45.         return(NULL);
  46.     }
  47.  
  48. #ifdef XP_WIN16
  49.         a_size = SIZE_LIMIT / sizeof(LO_Element *);
  50.         a_indx = (intn)(line / a_size);
  51.         a_line = (intn)(line - (a_indx * a_size));
  52.  
  53.         XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array);
  54.         state->line_array = larray_array[a_indx];
  55.         XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array);
  56.         eptr = line_array[a_line];
  57.  
  58.         XP_UNLOCK_BLOCK(state->line_array);
  59.         XP_UNLOCK_BLOCK(state->larray_array);
  60. #else
  61.         XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array);
  62.         eptr = line_array[line];
  63.         XP_UNLOCK_BLOCK(state->line_array);
  64. #endif /* XP_WIN16 */
  65.  
  66.     return(eptr);
  67. }
  68.  
  69.  
  70. static void
  71. lo_set_element_to_line(lo_DocState *state, LO_Element *eptr, int32 line)
  72. {
  73.     LO_Element **line_array;
  74. #ifdef XP_WIN16
  75.         intn a_size;
  76.         intn a_indx;
  77.         intn a_line;
  78.         XP_Block *larray_array;
  79. #endif /* XP_WIN16 */
  80.  
  81.     if (line >= (state->line_num - 1))
  82.     {
  83.         return;
  84.     }
  85.  
  86. #ifdef XP_WIN16
  87.         a_size = SIZE_LIMIT / sizeof(LO_Element *);
  88.         a_indx = (intn)(line / a_size);
  89.         a_line = (intn)(line - (a_indx * a_size));
  90.  
  91.         XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array);
  92.         state->line_array = larray_array[a_indx];
  93.         XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array);
  94.     line_array[a_line] = eptr;
  95.  
  96.         XP_UNLOCK_BLOCK(state->line_array);
  97.         XP_UNLOCK_BLOCK(state->larray_array);
  98. #else
  99.         XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array);
  100.     line_array[line] = eptr;
  101.         XP_UNLOCK_BLOCK(state->line_array);
  102. #endif /* XP_WIN16 */
  103. }
  104.  
  105. static void
  106. lo_duplicate_cell(MWContext *context, lo_DocState *state, int32 block_watch,
  107.         LO_CellStruct *old_cell, LO_CellStruct *new_cell)
  108. {
  109.     LO_Element *list_ptr;
  110.     LO_Element *tail_ptr;
  111.     LO_Element *eptr;
  112.  
  113.     /*
  114.      * Duplicate the cells normal list of elements.
  115.      */
  116.     list_ptr = NULL;
  117.     eptr = old_cell->cell_list;
  118.     if (eptr != NULL)
  119.     {
  120.         list_ptr = lo_duplicate_element(context, state,
  121.                     block_watch, eptr);
  122.         eptr = eptr->lo_any.next;
  123.     }
  124.     tail_ptr = list_ptr;
  125.     while (eptr != NULL)
  126.     {
  127.         tail_ptr->lo_any.next = lo_duplicate_element(context, state,
  128.                             block_watch, eptr);
  129.         tail_ptr = tail_ptr->lo_any.next;
  130.         eptr = eptr->lo_any.next;
  131.     }
  132.     if (tail_ptr != NULL)
  133.     {
  134.         tail_ptr->lo_any.next = NULL;
  135.     }
  136.     new_cell->cell_list = list_ptr;
  137.     new_cell->cell_list_end = tail_ptr;
  138.  
  139.     /*
  140.      * Duplicate the cells floating list of elements.
  141.      */
  142.     list_ptr = NULL;
  143.     eptr = old_cell->cell_float_list;
  144.     if (eptr != NULL)
  145.     {
  146.         list_ptr = lo_duplicate_element(context, state,
  147.                         block_watch, eptr);
  148.         eptr = eptr->lo_any.next;
  149.     }
  150.     tail_ptr = list_ptr;
  151.     while (eptr != NULL)
  152.     {
  153.         tail_ptr->lo_any.next = lo_duplicate_element(context, state,
  154.                         block_watch, eptr);
  155.         tail_ptr = tail_ptr->lo_any.next;
  156.         eptr = eptr->lo_any.next;
  157.     }
  158.     if (tail_ptr != NULL)
  159.     {
  160.         tail_ptr->lo_any.next = NULL;
  161.     }
  162.     new_cell->cell_float_list = list_ptr;
  163. }
  164.  
  165.  
  166. static LO_Element *
  167. lo_duplicate_element(MWContext *context, lo_DocState *state,
  168.             int32 block_watch, LO_Element *eptr)
  169. {
  170.     LO_Element *ret_eptr;
  171.  
  172.     if (eptr == NULL)
  173.     {
  174.         return(NULL);
  175.     }
  176.  
  177.     ret_eptr = lo_NewElement(context, state, eptr->type, NULL, 0);
  178.     if (ret_eptr == NULL)
  179.     {
  180.         return(NULL);
  181.     }
  182.  
  183.     switch(eptr->type)
  184.     {
  185.         case LO_TEXT:
  186.             XP_BCOPY((char *)eptr, (char *)(ret_eptr),
  187.                 sizeof(LO_TextStruct));
  188.             break;
  189.         case LO_LINEFEED:
  190.             XP_BCOPY((char *)eptr, (char *)(ret_eptr),
  191.                 sizeof(LO_LinefeedStruct));
  192.             break;
  193.         case LO_HRULE:
  194.             XP_BCOPY((char *)eptr, (char *)(ret_eptr),
  195.                 sizeof(LO_HorizRuleStruct));
  196.             break;
  197.         case LO_IMAGE:
  198.             XP_BCOPY((char *)eptr, (char *)(ret_eptr),
  199.                 sizeof(LO_ImageStruct));
  200. #ifndef M12N            /* XXXM12N  */
  201.             (void)IL_ReplaceImage(context,
  202.                 (LO_ImageStruct *)ret_eptr,
  203.                 (LO_ImageStruct *)eptr);
  204. #else
  205.             ((LO_ImageStruct *)ret_eptr)->image_req =
  206.                 ((LO_ImageStruct *)eptr)->image_req;
  207. #endif /* M12N */
  208.             FE_ShiftImage(context, (LO_ImageStruct *)ret_eptr);
  209.             break;
  210.         case LO_BULLET:
  211.             XP_BCOPY((char *)eptr, (char *)(ret_eptr),
  212.                 sizeof(LO_BulletStruct));
  213.             break;
  214.         case LO_FORM_ELE:
  215.             XP_BCOPY((char *)eptr, (char *)(ret_eptr),
  216.                 sizeof(LO_FormElementStruct));
  217.             break;
  218.         case LO_SUBDOC:
  219.             XP_BCOPY((char *)eptr, (char *)(ret_eptr),
  220.                 sizeof(LO_SubDocStruct));
  221.             break;
  222.         case LO_TABLE:
  223.             XP_BCOPY((char *)eptr, (char *)(ret_eptr),
  224.                 sizeof(LO_TableStruct));
  225.             break;
  226.         case LO_CELL:
  227.             XP_BCOPY((char *)eptr, (char *)(ret_eptr),
  228.                 sizeof(LO_CellStruct));
  229.             lo_duplicate_cell(context, state, block_watch,
  230.                 (LO_CellStruct *)eptr,
  231.                 (LO_CellStruct *)ret_eptr);
  232.             break;
  233.         case LO_EMBED:
  234.             XP_BCOPY((char *)eptr, (char *)(ret_eptr),
  235.                 sizeof(LO_EmbedStruct));
  236.             break;
  237. #ifdef JAVA
  238.         case LO_JAVA:
  239.             XP_BCOPY((char *)eptr, (char *)(ret_eptr),
  240.                 sizeof(LO_JavaAppStruct));
  241.             break;
  242. #endif
  243.         case LO_NONE:
  244.         case LO_UNKNOWN:
  245.             ret_eptr = NULL;
  246.             break;
  247.     }
  248.  
  249.     /*
  250.      * If we have duplicated the blocking element, set its
  251.      * new pointer into state.
  252.      */
  253.     if ((ret_eptr != NULL)&&(block_watch != -1))
  254.     {
  255.         if (ret_eptr->lo_any.ele_id == block_watch)
  256.         {
  257.             state->top_state->layout_blocking_element = 
  258.                 ret_eptr;
  259.             block_watch = -1;
  260.         }
  261.     }
  262.  
  263.     return(ret_eptr);
  264. }
  265.  
  266.  
  267. void
  268. lo_ClipLines(MWContext *context, lo_DocState *state, int32 line)
  269. {
  270.     int32 i;
  271.     int32 dy;
  272.     int32 block_watch;
  273.     LO_Element *start_clipping;
  274.     LO_Element *end_clipping;
  275.     LO_Element *eptr;
  276.     LO_Element *end_ptr;
  277.     LO_Element *end_last_line;
  278.     LO_Element *float_list;
  279.     LO_Element *float_ptr;
  280.  
  281. #ifdef MEMORY_ARENAS    
  282.     lo_arena *old_first_arena;
  283.     lo_arena *old_current_arena;
  284.  
  285.     /*
  286.      * Save off the current memory arena, and make a new one.
  287.      */
  288.     old_first_arena = state->top_state->first_arena;
  289.     old_current_arena = state->top_state->current_arena;
  290.     state->top_state->first_arena = NULL;
  291.     state->top_state->current_arena = NULL;
  292.     lo_InitializeMemoryArena(state->top_state);
  293.     if (state->top_state->first_arena == NULL)
  294.     {
  295.         state->top_state->out_of_memory = TRUE;
  296.         state->top_state->first_arena = old_first_arena;
  297.         state->top_state->current_arena = old_current_arena;
  298.         return;
  299.     }
  300.  
  301.  
  302. #endif /* MEMORY_ARENAS */
  303.     
  304.     /*
  305.      * Clear the selection (if any).
  306.      */
  307.     LO_HighlightSelection(context, FALSE);
  308.     state->selection_start = NULL;
  309.     state->selection_start_pos = 0;
  310.     state->selection_end = NULL;
  311.     state->selection_end_pos = 0;
  312.  
  313.     /*
  314.      * If there is a blocked element that changes, watch it and reset
  315.      * it properly.
  316.      */
  317.     block_watch = -1;
  318.     if (state->top_state->layout_blocking_element != NULL)
  319.     {
  320.         block_watch =
  321.             state->top_state->layout_blocking_element->lo_any.ele_id;
  322.     }
  323.  
  324.     dy = 0;
  325.  
  326.     /*
  327.      * Delete all elements in the lines being clipped off.
  328.      */
  329.     start_clipping = lo_line_to_element(state, 0);
  330.     end_clipping = lo_line_to_element(state, line);
  331.     if ((end_clipping != NULL)&&(start_clipping != NULL))
  332.     {
  333.         dy = end_clipping->lo_any.y - start_clipping->lo_any.y;
  334.     }
  335.     while ((start_clipping != NULL)&&(start_clipping != end_clipping))
  336.     {
  337.         lo_ScrapeElement(context, start_clipping);
  338.         start_clipping = start_clipping->lo_any.next;
  339.     }
  340.  
  341.     /*
  342.      * Loop through all the lines after the clipped line.
  343.      */
  344.     end_last_line = NULL;
  345.     for (i=0; i < (state->line_num - line - 1); i++)
  346.     {
  347.         LO_Element *line_start;
  348.         LO_Element *lptr;
  349.  
  350.         /*
  351.          * Find the start of this line, and the start of
  352.          * the next line.
  353.          */
  354.         eptr = lo_line_to_element(state, (line + i));
  355.         end_ptr = lo_line_to_element(state, (line + 1 + i));
  356.         if (eptr != NULL)
  357.         {
  358.             line_start = lo_duplicate_element(context, state,
  359.                         block_watch, eptr);
  360.             lptr = line_start;
  361.             eptr = eptr->lo_any.next;
  362.         }
  363.         else
  364.         {
  365.             line_start = NULL;
  366.             lptr = NULL;
  367.         }
  368.  
  369.         /*
  370.          * Set the start of this new line into the line array.
  371.          */
  372.         lo_set_element_to_line(state, line_start, i);
  373.  
  374.         /*
  375.          * Copy all the elements in the line.
  376.          */
  377.         while (eptr != end_ptr)
  378.         {
  379.             lptr->lo_any.y -= dy;
  380.             if (lptr->type == LO_CELL)
  381.             {
  382.                 lo_ShiftCell((LO_CellStruct *)lptr, 0, -dy);
  383.             }
  384.             else if (lptr->type == LO_IMAGE)
  385.             {
  386.                 FE_ShiftImage(context, (LO_ImageStruct *)lptr);
  387.             }
  388.  
  389.             lptr->lo_any.next = lo_duplicate_element(context, state,
  390.                             block_watch, eptr);
  391.             if (lptr->lo_any.next == NULL)
  392.             {
  393.                 break;
  394.             }
  395.             lptr->lo_any.next->lo_any.prev = lptr;
  396.             lptr = lptr->lo_any.next;
  397.             eptr = eptr->lo_any.next;
  398.         }
  399.         if (lptr != NULL)
  400.         {
  401.             lptr->lo_any.y -= dy;
  402.             if (lptr->type == LO_CELL)
  403.             {
  404.                 lo_ShiftCell((LO_CellStruct *)lptr, 0, -dy);
  405.             }
  406.             else if (lptr->type == LO_IMAGE)
  407.             {
  408.                 FE_ShiftImage(context, (LO_ImageStruct *)lptr);
  409.             }
  410.             lptr->lo_any.next = NULL;
  411.         }
  412.  
  413.         /*
  414.          * Link the beginning of the line we just copied to
  415.          * the end of the last line.
  416.          */
  417.         line_start->lo_any.prev = end_last_line;
  418.         if (end_last_line != NULL)
  419.         {
  420.             end_last_line->lo_any.next = line_start;
  421.         }
  422.         end_last_line = lptr;
  423.         lptr->lo_any.next = NULL;
  424.     }
  425.  
  426.     /*
  427.      * Clear the extra slots at the end.
  428.      */
  429.     for (i = (state->line_num - line - 1); i < (state->line_num - 1); i++)
  430.     {
  431.         lo_set_element_to_line(state, NULL, i);
  432.     }
  433.  
  434.     float_list = NULL;
  435.     float_ptr = NULL;
  436.     eptr = state->float_list;
  437.     while (eptr != NULL)
  438.     {
  439.         /*
  440.          * Floating elements that move up off the top are deleted.
  441.          */
  442.         if ((eptr->lo_any.y - dy) < 0)
  443.         {
  444.             lo_ScrapeElement(context, eptr);
  445.             eptr = eptr->lo_any.next;
  446.             continue;
  447.         }
  448.  
  449.         if (float_list == NULL)
  450.         {
  451.             float_list = lo_duplicate_element(context, state,
  452.                     block_watch, eptr);
  453.             float_ptr = float_list;
  454.         }
  455.         else
  456.         {
  457.             float_ptr->lo_any.next = lo_duplicate_element(context,
  458.                         state, block_watch, eptr);
  459.             float_ptr = float_ptr->lo_any.next;
  460.         }
  461.         float_ptr->lo_any.y -= dy;
  462.         if (float_ptr->type == LO_CELL)
  463.         {
  464.             lo_ShiftCell((LO_CellStruct *)float_ptr, 0, -dy);
  465.         }
  466.         else if (float_ptr->type == LO_IMAGE)
  467.         {
  468.             FE_ShiftImage(context, (LO_ImageStruct *)float_ptr);
  469.         }
  470.  
  471.         eptr = eptr->lo_any.next;
  472.     }
  473.     if (float_ptr != NULL)
  474.     {
  475.         float_ptr->lo_any.next = NULL;
  476.     }
  477.  
  478.     /*
  479.      * If there are blocked tags, one of them may be holded
  480.      * a partially fetched blocked image element, duplicate it.
  481.      */
  482.     if (state->top_state->tags != NULL)
  483.     {
  484.         PA_Tag *tag_ptr;
  485.  
  486.         tag_ptr = state->top_state->tags;
  487.         while (tag_ptr != NULL)
  488.         {
  489.             if ((tag_ptr->type == P_IMAGE)&&
  490.                 (tag_ptr->lo_data != NULL))
  491.             {
  492.                 LO_Element *new_eptr;
  493.                 LO_Element *eptr;
  494.  
  495.                 eptr = (LO_Element *)tag_ptr->lo_data;
  496.                 new_eptr = lo_duplicate_element(context, state,
  497.                                                 block_watch, eptr);
  498.                 tag_ptr->lo_data = (void *)new_eptr;
  499.             }
  500.             tag_ptr = tag_ptr->next;
  501.         }
  502.     }
  503.  
  504.     state->line_num -= line;
  505.     state->y -= dy;
  506.     state->end_last_line = end_last_line;
  507.     state->float_list = float_list;
  508.     state->current_ele = NULL;
  509.  
  510.     lo_ShiftMarginsUp(context, state, dy);
  511.  
  512.     /*
  513.      * If we had a blocking element that didn't get duplicated, we don't
  514.      * know what happened to it.
  515.      */
  516.     if (block_watch != -1)
  517.     {
  518.         state->top_state->layout_blocking_element = NULL;
  519.     }
  520.  
  521. #ifdef MEMORY_ARENAS    
  522.     (void)lo_FreeMemoryArena(old_first_arena);
  523. #endif /* MEMORY_ARENAS    */
  524.  
  525. }
  526.  
  527.