home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / OLEO130S.ZIP / oleo130s.tar / oleo-1.3 / display.c < prev    next >
C/C++ Source or Header  |  1993-03-27  |  11KB  |  419 lines

  1. /*    Copyright (C) 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7.  
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12.  
  13. You should have received a copy of the GNU General Public License
  14. along with this software; see the file COPYING.  If not, write to
  15. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17.  
  18. #include <stdio.h>
  19. #include "display.h"
  20. #include "lists.h"
  21. #include "cell.h"
  22. #include "io-utils.h"
  23.  
  24. #if __STDC__
  25. struct cell_display *
  26. cell_display_of (struct display *disp, CELLREF r, CELLREF c)
  27. #else
  28. struct cell_display *
  29. cell_display_of (disp, r, c)
  30.      struct display *disp;
  31.      CELLREF r;
  32.      CELLREF c;
  33. #endif
  34. {
  35.   int cols = disp->range.hc - disp->range.lc + 1;
  36.   if (   (r < disp->range.lr)
  37.       || (c < disp->range.lc)
  38.       || (r > disp->range.hr)
  39.       || (c > disp->range.hc))
  40.     return 0;
  41.   r -= disp->range.lr;
  42.   c -= disp->range.lc;
  43.   return disp->cells + r * cols + c;
  44. }
  45.  
  46.  
  47. void 
  48. free_display (disp)
  49.      struct display *disp;
  50. {
  51.   int rows = disp->range.hr - disp->range.lr + 1;
  52.   int cols = disp->range.hc - disp->range.lc + 1;
  53.   struct cell_display *cd = disp->cells;
  54.   int x, y;
  55.   for (y = 0; y < rows; ++y)
  56.     for (x = 0; x < cols; ++x)
  57.       {
  58.     if (cd->unclipped)
  59.       free (cd->unclipped);
  60.     if (cd->clipped)
  61.       free (cd->clipped);
  62.     ++cd;
  63.       }
  64.   free (disp->widths);
  65.   free (disp->heights);
  66.   free (disp->cells);
  67.   free (disp->rowy);
  68.   free (disp->colx);
  69. }
  70.  
  71. void 
  72. damage (disp, cd)
  73.      struct display *disp;
  74.      struct cell_display *cd;
  75. {
  76.   if (cd && !cd->next_damaged)
  77.     {
  78.       cd->next_damaged = disp->damaged;
  79.       disp->damaged = cd;
  80.     }
  81. }
  82.  
  83. #if __STDC__
  84. int
  85. pr_display_cell (struct display *disp, CELLREF r, CELLREF c, CELL *cp)
  86. #else
  87. int
  88. pr_display_cell (disp, r, c, cp)
  89.      struct display *disp;
  90.      CELLREF r;
  91.      CELLREF c;
  92.      CELL *cp;
  93. #endif
  94. {
  95.   int cols = disp->range.hc - disp->range.lc + 1;
  96.   struct cell_display *cd =
  97.   &disp->cells[cols * (r - disp->range.lr) + (c - disp->range.lc)];
  98.   xx_IntRectangle ir = &cd->layout;
  99.   struct font_memo * new_font = 0;
  100.   char * new_unclipped = 0;
  101.   int new_type = 0;
  102.   int new_jst = 0;
  103.  
  104.   if (cp && disp->widths[c - disp->range.lc]
  105.       && disp->heights[r - disp->range.lr])
  106.     {
  107.       new_unclipped = print_cell (cp);
  108.       if (!new_unclipped || *new_unclipped == '\0')
  109.     new_unclipped = 0;
  110.       else
  111.     {
  112.       new_type = GET_TYP (cp);
  113.       new_jst = GET_JST (cp);
  114.       new_font = cp->cell_font;
  115.       if (new_jst == JST_DEF)
  116.         new_jst = default_jst;
  117.     }
  118.     }
  119.  
  120.  
  121.   if (((!new_unclipped && !cd->unclipped)
  122.        || ((new_unclipped && cd->unclipped)
  123.        && !strcmp(cd->unclipped, new_unclipped))) 
  124.       && (cd->font == new_font)
  125.       && (cd->cell_type == new_type)
  126.       && (cd->justification == new_jst))
  127.     return 0;
  128.            
  129.   record_display_damage (disp, xx_IRx (ir), xx_IRy (ir),
  130.              xx_IRw (ir), xx_IRh (ir));
  131.   if (cd->unclipped)
  132.     {
  133.       free (cd->unclipped);
  134.       cd->unclipped = 0;
  135.     }
  136.   if (cd->clipped)
  137.     {
  138.       free (cd->clipped);
  139.       cd->clipped = 0;
  140.     }
  141.   cd->font = new_font;
  142.   cd->cell_type = new_type;
  143.   cd->justification = new_jst;
  144.   if (!cp || !GET_TYP (cp))
  145.     {
  146.       xx_IRinit (&cd->goal, 0, 0, 0, 0);
  147.       xx_IRinit (&cd->clip, 0, 0, 0, 0);
  148.       cd->unclipped = 0;
  149.       return 1;
  150.     }
  151.   cd->unclipped = ck_savestr (new_unclipped);
  152.   cd->clipped = 0;
  153.   disp->metric (cd, disp);
  154.   if (new_type == TYP_INT)
  155.     cd->numeric.integer = cp->c_z.c_l;
  156.   else if (new_type == TYP_FLT)
  157.     cd->numeric.dbl = cp->c_z.c_d;
  158.   else
  159.     {
  160.       cd->clipped = ck_savestr (cd->unclipped);
  161.       cd->clip = cd->goal;
  162.     }
  163.   return 1;
  164. }
  165.  
  166. static void null_metric (cd, disp)
  167.      struct cell_display * cd;
  168.      struct display * disp;
  169. {}
  170.  
  171. static void 
  172. _build_display (disp, range, metric, vdata, scalep)
  173.      struct display *disp;
  174.      struct rng *range;
  175.      cell_display_metric metric;
  176.      void *vdata;
  177.      int scalep;
  178. {
  179.   /* This would be more useful if it handled scrolling. */
  180.   int r, c;
  181.   int rows = range->hr - range->lr + 1;
  182.   int cols = range->hc - range->lc + 1;
  183.   int x, y;
  184.   disp->range = *range;
  185.   disp->widths = (int *) ck_malloc (sizeof (int) * cols);
  186.   disp->heights = (int *) ck_malloc (sizeof (int) * rows);
  187.   disp->rowy = (int *) ck_malloc (sizeof (int) * rows);
  188.   disp->colx = (int *) ck_malloc (sizeof (int) * cols);
  189.   disp->metric = metric ? metric : null_metric;
  190.   disp->vdata = vdata;
  191.   disp->cells = ((struct cell_display *)
  192.          ck_calloc (sizeof (struct cell_display) * rows * cols));
  193.   disp->damaged = (struct cell_display *) disp;
  194.   for (x = 0, r = range->lr; r <= range->hr; ++r)
  195.     {
  196.       disp->rowy[r - range->lr] = x;
  197.       x += disp->heights[r - range->lr] = (scalep ? get_scaled_height : get_height) (r);
  198.     }
  199.   for (y = 0, c = range->lc; c <= range->hc; ++c)
  200.     {
  201.       disp->colx[c - range->lc] = y;
  202.       y += disp->widths[c - range->lc] = (scalep ? get_scaled_width : get_width) (c);
  203.       for (r = range->lr; r <= range->hr; ++r)
  204.     {
  205.       struct cell_display *cd = cell_display_of (disp, r, c);
  206.       cd->r = r;
  207.       cd->c = c;
  208.       pr_display_cell (disp, r, c, find_cell (r, c));
  209.     }
  210.     }
  211. }
  212.  
  213. void 
  214. build_display (disp, range, metric, vdata)
  215.      struct display *disp;
  216.      struct rng *range;
  217.      cell_display_metric metric;
  218.      void *vdata;
  219. {
  220.   _build_display (disp, range, metric, vdata, 1);
  221. }
  222.  
  223. void 
  224. build_unscaled_display (disp, range, metric, vdata)
  225.      struct display *disp;
  226.      struct rng *range;
  227.      cell_display_metric metric;
  228.      void *vdata;
  229. {
  230.   _build_display (disp, range, metric, vdata, 0);
  231. }
  232.  
  233. void 
  234. display_range (rng, disp, x, y, w, h)
  235.      struct rng *rng;
  236.      struct display *disp;
  237.      int x, y, w, h;
  238. {
  239.   int t;
  240.   struct rng *winrng = &disp->range;
  241.   int *rowy = disp->rowy;
  242.   int *heights = disp->heights;
  243.   int *colx = disp->colx;
  244.   int *widths = disp->widths;
  245.   int rows = winrng->hr - winrng->lr + 1;
  246.   int cols = winrng->hc - winrng->lc + 1;
  247.  
  248.   for (t = 0; t < rows - 1; ++t)
  249.     if (rowy[t] + heights[t] - 1 >= y)
  250.       break;
  251.   rng->lr = t + winrng->lr;
  252.  
  253.   while (t < rows - 1)
  254.     {
  255.       if (rowy[t] + heights[t] >= y + h)
  256.     break;
  257.       t++;
  258.     }
  259.   rng->hr = t + winrng->lr;
  260.  
  261.   for (t = 0; t < cols - 1; ++t)
  262.     if (colx[t] + widths[t] - 1 >= x)
  263.       break;
  264.   rng->lc = t + winrng->lc;
  265.  
  266.   while (t < cols - 1)
  267.     {
  268.       if (colx[t] + widths[t] >= x + w)
  269.     break;
  270.       t++;
  271.     }
  272.   rng->hc = t + winrng->lc;
  273. }
  274.  
  275. extern void 
  276. record_display_damage (disp, x, y, w, h)
  277.      struct display *disp;
  278.      int x, y, w, h;
  279. {
  280.   CELLREF r, c;
  281.   struct rng rng;
  282.   display_range (&rng, disp, x, y, w, h);
  283.   for (r = rng.lr; r <= rng.hr && r > 0; ++r)
  284.     for (c = rng.lc; c <= rng.hc && c > 0; ++c)
  285.       damage (disp, cell_display_of (disp, r, c));
  286. }
  287.  
  288.  
  289. void 
  290. layout (disp)
  291.      struct display *disp;
  292. {
  293.   int *widths = disp->widths;
  294.   int *heights = disp->heights;
  295.   int *rowy = disp->rowy;
  296.   int *colx = disp->colx;
  297.   int rows = disp->range.hr - disp->range.lr + 1;
  298.   int cols = disp->range.hc - disp->range.lc + 1;
  299.   int ri, ci;
  300.   struct cell_display *cd;
  301.  
  302.   /* This assigns each non-empty cell's space to itself.  The rest of the */
  303.   /* function allocates the space held by empty cells. */
  304.   for (cd = disp->cells, ri = 0; ri < rows; ++ri)
  305.     for (ci = 0; ci < cols; ++ci, ++cd)
  306.       {
  307.     cd->was_used_by = cd->used_by;
  308.     cd->used_by = cd->unclipped ? cd : 0;
  309.       }
  310.  
  311.   for (ri = 0; ri < rows; ++ri)
  312.     for (ci = 0; ci < cols; ++ci)
  313.       {
  314.     struct cell_display *cd =
  315.     cell_display_of (disp, ri + disp->range.lr, ci + disp->range.lc);
  316.     if (cd->unclipped)
  317.       {
  318.         xx_IntRectangle gr = &cd->goal;
  319.         int xl = xx_IRxl (gr);
  320.         int xh = xx_IRxh (gr);
  321.         int yl = xx_IRyl (gr);
  322.         int rl_answer, rh_answer, cl_answer, ch_answer;
  323.         int rl, rh, cl, ch;
  324.         int rit, cit;
  325.         int xt, yt;
  326.  
  327.         for (cl = ci, xt = colx[cl];
  328.          cl && (xt > xl);
  329.          --cl, xt = colx[cl]);
  330.         for (rl = ri, yt = rowy[rl];
  331.          rl && (yt > yl);
  332.          --rl, yt = rowy[rl]);
  333.         for (ch = ci, xt = colx[ch] + widths[ch];
  334.          (ch < (cols - 1)) && (xt < xh);
  335.          ++ch, xt = colx[ch] + widths[ch]);
  336.         rh = ri;
  337.         /* rl/h & cl/h bound the cells covered by the goal rectangle.
  338.          * Of these, at least ri, ci is unused.  The goal here is to
  339.          * allocate additional cells for use by ri,ci.
  340.          */
  341.         for (rit = ri - 1; rit >= rl; --rit)
  342.           for (cit = cl; ci <= ch; ++cit)
  343.         {
  344.           struct cell_display *cdt = disp->cells + (rit * cols) + cit;
  345.           if (cdt->used_by)
  346.             goto got_rl;
  347.         }
  348.       got_rl:
  349.         ++rit;
  350.         rl_answer = rit;
  351.  
  352.         for (rit = ri + 1; rit <= rh; ++rit)
  353.           for (cit = cl; ci <= ch; ++cit)
  354.         {
  355.           struct cell_display *cdt = disp->cells + (rit * cols) + cit;
  356.           if (cdt->used_by)
  357.             goto got_rh;
  358.         }
  359.       got_rh:
  360.         --rit;
  361.         rh_answer = rit;
  362.  
  363.         for (cit = ci - 1; cit >= cl; --cit)
  364.           for (rit = rl_answer; rit <= rh_answer; ++rit)
  365.         {
  366.           struct cell_display *cdt = disp->cells + (rit * cols) + cit;
  367.           if (cdt->used_by)
  368.             goto got_cl;
  369.         }
  370.       got_cl:
  371.         ++cit;
  372.         cl_answer = cit;
  373.  
  374.         for (cit = ci + 1; cit <= ch; ++cit)
  375.           for (rit = rl_answer; rit <= rh_answer; ++rit)
  376.         {
  377.           struct cell_display *cdt = disp->cells + (rit * cols) + cit;
  378.           if (cdt->used_by)
  379.             goto got_ch;
  380.         }
  381.       got_ch:
  382.         --cit;
  383.         ch_answer = cit;
  384.  
  385.         for (rit = rl_answer; rit <= rh_answer; ++rit)
  386.           for (cit = cl_answer; cit <= ch_answer; ++cit)
  387.         {
  388.           struct cell_display *cdt = disp->cells + (rit * cols) + cit;
  389.           cdt->used_by = cd;
  390.           if (cdt->was_used_by != cdt->used_by)
  391.             {
  392.               damage (disp, cdt);
  393.               damage (disp, cdt->was_used_by);
  394.             }
  395.         }
  396.  
  397.         xx_IRinit (&cd->layout,
  398.                colx[cl_answer], rowy[rl_answer],
  399.                colx[ch_answer] + widths[ch_answer] - colx[cl_answer],
  400.                rowy[rh_answer] + heights[rh_answer] - rowy[rl_answer]);
  401.       }
  402.       }
  403.  
  404.   /* Unused cells are given to themselves. */
  405.   for (cd = disp->cells, ri = 0; ri < rows; ++ri)
  406.     for (ci = 0; ci < cols; ++ci, ++cd)
  407.       if (!cd->used_by)
  408.     {
  409.       cd->used_by = cd;
  410.       if (cd->was_used_by != cd)
  411.         {
  412.           damage (disp, cd);
  413.           damage (disp, cd->was_used_by);
  414.         }
  415.       xx_IRinit (&cd->layout, colx[ci], rowy[ri],
  416.              widths[ci], heights[ri]);
  417.     }
  418. }
  419.