home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / education / a / biology1 / !Biology1 / c / TextIcon < prev    next >
Text File  |  1991-12-02  |  11KB  |  346 lines

  1. /* TextIcon */
  2. /* To display & maintain an icon containing text */
  3.  
  4. /* We maintain a list of windows
  5.  * Each with a list of icons
  6.  * each comprising the icon no, position, & pointer to text.
  7.  */
  8.  
  9. #include <stdlib.h>
  10. #include <string.h>
  11.  
  12. #include "kernel.h"
  13. #include "os.h"
  14. #include "wimp.h"
  15.  
  16. #include "texticon.h"
  17. #include "utils.h"
  18.  
  19.  
  20. #define XOS_Plot   0x020045
  21. #define XOS_WriteN 0x020046
  22. #define XOS_WriteI 0x020100
  23.  
  24.  
  25. static int  udg_base       = 128;
  26. static int  no_udgs        = 0;
  27. static char (*udg_defn)[8] = NULL;
  28.  
  29. static os_error out_of_memory = {0, "Out of memory"};
  30. /* Program error if the following occurs */
  31. static os_error out_of_range  = {0, "Out of range"};
  32.  
  33. struct iconlist
  34.   { struct iconlist *next;
  35.     wimp_i handle;
  36.     char *text;
  37.     int  flags;
  38.   };
  39.  
  40. struct windlist
  41.   { struct windlist *next;
  42.     wimp_w w;
  43.     struct iconlist *i;
  44.   };
  45.  
  46. static struct windlist *list = NULL;
  47.  
  48.  
  49. os_error *texticon_create_icon (wimp_icreate *defn, wimp_i *result)
  50.   { struct windlist  *wnd_ptr;
  51.     struct iconlist  *ic_ptr;
  52.     wimp_icreate     icreate;
  53.     os_error         *err;
  54.  
  55.     memcpy (&icreate, defn, sizeof (wimp_icreate));
  56.  
  57. /* Find window */
  58.     ll_find (wnd_ptr, list, w, icreate.w);
  59.  
  60.     if (wnd_ptr == NULL)
  61.       { wnd_ptr = malloc (sizeof (struct windlist));
  62.         if (wnd_ptr == NULL)
  63.             return (&out_of_memory);           
  64.         (wnd_ptr)->next = list;
  65.         (wnd_ptr)->w    = icreate.w;
  66.         (wnd_ptr)->i    = NULL;
  67.         list = wnd_ptr;
  68.       }
  69.  
  70.     ic_ptr = malloc (sizeof (struct iconlist));
  71.     if (ic_ptr == NULL)
  72.         return (&out_of_memory);
  73.  
  74. /* Remember flags */
  75.     ic_ptr->flags = icreate.i.flags;
  76.  
  77. /* Modify defn */
  78.     icreate.i.flags &= ~ wimp_IFILLED;
  79.  
  80.     if (icreate.i.flags & wimp_ITEXT)
  81.       { if (icreate.i.flags & wimp_INDIRECT)
  82.           { ic_ptr->text = malloc (icreate.i.data.indirecttext.bufflen);
  83.             if (ic_ptr->text == NULL)
  84.                 return (&out_of_memory);
  85.             strcpy (ic_ptr->text, icreate.i.data.indirecttext.buffer);
  86.           }
  87.         else
  88.           { ic_ptr->text = malloc (12);
  89.             if (ic_ptr->text == NULL)
  90.                 return (&out_of_memory);
  91.             strcpy (ic_ptr->text, icreate.i.data.text);
  92.           }
  93.         icreate.i.flags |= wimp_IREDRAW;
  94.         icreate.i.flags &= ~0x140;    /* cancel wimp_IFONT | wimp_INDIRECT*/
  95.         icreate.i.data.text[0] = '\0';
  96.       }
  97.     else
  98.       { ic_ptr->text = NULL;
  99.       }
  100.  
  101. /* Create it */
  102.     err = wimp_create_icon (&icreate, result);
  103.     if (err)
  104.       { if (ic_ptr->text)
  105.             free (ic_ptr->text);
  106.         free (ic_ptr);
  107.         return (err);
  108.       }
  109.     ic_ptr->handle = *result;
  110.     ic_ptr->next = wnd_ptr->i;
  111.     wnd_ptr->i = ic_ptr;
  112.  
  113.     return (NULL);
  114.   }
  115.  
  116. os_error *texticon_delete_wind (wimp_w wnd)
  117.   { struct windlist  *wnd_p;
  118.     struct iconlist  *ic_ptr, *next_icon;
  119.  
  120.     ll_find (wnd_p, list, w, wnd);
  121.  
  122.     if (wnd_p != NULL)  /* Free all it's icons */
  123.       { next_icon = wnd_p->i;
  124.         while (next_icon != NULL)
  125.           { ic_ptr = next_icon;
  126.             next_icon = ic_ptr->next;
  127.             if (ic_ptr->text)
  128.                 free (ic_ptr->text);
  129.             free (ic_ptr);
  130.           }
  131. /* Now window has no icons, unlink it */
  132.         ll_unlink (struct windlist, wnd_p, list);
  133.       }
  134. /* That's done our housekeeping, now delete the window */
  135.  
  136.      return (wimp_delete_wind (wnd));
  137.   }
  138.  
  139.  
  140. os_error *texticon_delete_icon (wimp_w wnd, wimp_i ic, BOOL force_redraw)
  141.   { struct windlist  *wnd_p;
  142.     struct iconlist  *ic_p;
  143.     wimp_icon        result;
  144.     wimp_redrawstr   r;
  145.     os_error         *res_err;
  146.  
  147.     ll_find (wnd_p, list, w, wnd);
  148.  
  149.     if (wnd_p != NULL)
  150.       { 
  151.         ll_find (ic_p, wnd_p->i, handle, ic);
  152.  
  153.         if (ic_p != NULL)
  154.           { if (ic_p->text)
  155.                 free (ic_p->text);
  156.  
  157.             ll_unlink (struct iconlist, ic_p, wnd_p->i);
  158.           }
  159. /* Now if window has no icons, unlink it */
  160.         if (wnd_p->i == NULL)
  161.             ll_unlink (struct windlist, wnd_p, list);
  162.       }
  163. /* That's done our housekeeping, now delete the icon */
  164.     wimp_get_icon_info (wnd, ic, &result);
  165.     r.w = wnd;
  166.     memcpy (&r.box, &result.box, sizeof (wimp_box));
  167.     wimp_delete_icon (wnd, ic);
  168.     if (force_redraw)                    
  169.       { wimp_force_redraw (&r);
  170.       }
  171.      return (res_err);
  172.   }
  173.  
  174. void texticon_del_all_icons (wimp_w wnd)
  175.   { struct windlist  *wnd_p;
  176.     struct iconlist  *ic_ptr, *next_icon;
  177.  
  178.     ll_find (wnd_p, list, w, wnd);
  179.     if (wnd_p != NULL)
  180.       { next_icon = wnd_p->i;
  181.         while (next_icon != NULL)
  182.           { ic_ptr = next_icon;
  183.             next_icon = ic_ptr->next;
  184.             texticon_delete_icon (wnd, ic_ptr->handle, FALSE);
  185.           }
  186.       }
  187.   }
  188.  
  189. void texticon_redraw (wimp_redrawstr *r)
  190.   { int  work_origin_x, work_origin_y;
  191.     int  clip_x0, clip_y0, clip_x1, clip_y1;
  192.     int  curr_defined = -1;
  193.     int  hoffset, voffset;
  194.     int  line, llen, l;
  195.     char *str, *line_end;
  196.     char gcol[3] = {18, 0};
  197.     char draw_udg[11] = {23, 128, 0, 0, 0, 0, 0, 0, 0, 0, 128};
  198.     char old_defn[10] = {23, 128, 0, 0, 0, 0, 0, 0, 0, 0};
  199.  
  200.     wimp_icon        ic_info;
  201.     struct windlist  *wnd_ptr;
  202.     struct iconlist  *ic_ptr;
  203.    
  204. /* Find window */
  205.     ll_find (wnd_ptr, list, w, r->w);
  206.  
  207.     if (wnd_ptr != NULL)
  208.       { work_origin_x = r->box.x0 - r->scx;
  209.         work_origin_y = r->box.y1 - r->scy;
  210.         clip_x0 = r->g.x0 - work_origin_x;
  211.         clip_y0 = r->g.y0 - work_origin_y;
  212.         clip_x1 = r->g.x1 - work_origin_x;
  213.         clip_y1 = r->g.y1 - work_origin_y;
  214.  
  215.         /* Read old udg defn */
  216.         os_word (10, old_defn+1);
  217.  
  218.         for (ic_ptr = wnd_ptr->i; ic_ptr; ic_ptr = ic_ptr->next)
  219.           { wimp_get_icon_info (r->w, ic_ptr->handle, &ic_info);
  220.  
  221.             if (ic_info.box.x0 < clip_x1 &&
  222.                 ic_info.box.y0 < clip_y1 &&
  223.                 ic_info.box.x1 > clip_x0 &&
  224.                 ic_info.box.y1 > clip_y0)
  225.               {
  226.                 if (ic_ptr->flags & wimp_IFILLED)
  227.                   {
  228.                     char rect [12] = {25,4, 0,0, 0,0,  25, 96+5, 0,0, 0,0};
  229.                     int x0 = work_origin_x + ic_info.box.x0;
  230.                     int x1 = work_origin_x + ic_info.box.x1 - 1;
  231.                     int y0 = work_origin_y + ic_info.box.y0;
  232.                     int y1 = work_origin_y + ic_info.box.y1 - 1;
  233.  
  234. #define rectcoord(value, offset) rect [offset] = value & 0xff; \
  235.                                  rect [offset+1] = value >> 8
  236.  
  237.                     rectcoord (x0, 2);
  238.                     rectcoord (y0, 4);
  239.                     rectcoord (x1, 8);
  240.                     rectcoord (y1, 10);
  241.  
  242.                     gcol[2] = ((ic_info.flags >> 28) & 0x0F);
  243.                     os_swi2 (XOS_WriteN, (int) gcol, 3);
  244.  
  245.                     os_swi2 (XOS_WriteN, (int) rect, 12);
  246.                   }
  247.  
  248.                 if (ic_info.flags & wimp_ITEXT)
  249.                   {
  250. /* COLOURS MAY NEED translating */
  251.                     gcol[2] = ((ic_info.flags >> 24) & 0x0F);
  252.                     os_swi2 (XOS_WriteN, (int) gcol, 3);
  253.     /* Set vertical offset */
  254.                     if (ic_info.flags & wimp_IVCENTRE)
  255.                       { for (str = ic_ptr->text, line=0; str; line++)
  256.                           { str = strchr (str, '\n');
  257.                             if (str)
  258.                                 str++;   /* Put us past the newline */
  259.                             if (str && *str == '\0')
  260.                                 str = NULL;  /* Ignore an empty last line */
  261.                           }
  262.                         voffset = (ic_info.box.y1 - ic_info.box.y0)/2 -
  263.                                       20 * line + 4;
  264.     /* NB ABOVE ASSUMES CHARACTERS 32 OS UNITS DEEP & spaced at 40 */
  265.                       }
  266.                     else
  267.                         voffset = 8;
  268.  
  269.     /* Write the lines */
  270.                     for (str = ic_ptr->text, line=0; *str; line++)
  271.                       { /* Position cursor */
  272.                         if (ic_info.flags & wimp_IHCENTRE)
  273.                           { line_end = strchr (str, '\n');
  274.                             if (line_end == NULL)
  275.                                 llen = strlen (str);
  276.                             else
  277.                                 llen = line_end - str;
  278.                             hoffset = (ic_info.box.x1 - ic_info.box.x0)/2 -
  279.                                       8 * llen;
  280.     /* NB ABOVE ASSUMES CHARACTERS 16 OS UNITS WIDE */
  281.                           }
  282.                         else
  283.                             hoffset = 8;
  284.                         os_swi3 (XOS_Plot, 4,
  285.                                  work_origin_x + ic_info.box.x0 + hoffset,
  286.                                  work_origin_y + ic_info.box.y1 - voffset
  287.                                                - 40 * line);
  288.     /* Now print the line */
  289.                         while (*str && *str != '\n')
  290.                           { /* Count block to write */
  291.                             l=0;
  292.                             while (str[l] && str[l]!='\n' &&
  293.                               (str[l] < udg_base || str[l] >= udg_base+no_udgs))
  294.                                 l++;
  295.                             os_swi2 (XOS_WriteN, (int) str, l);
  296.                             str += l;
  297.     /* If we've stopped for a udg, print it */
  298.                             if (*str == curr_defined)
  299.                               { os_swi0 (XOS_WriteI + 128);
  300.                                 str++;
  301.                               }
  302.                             else if (*str>=udg_base && *str<udg_base+no_udgs)
  303.                               { memcpy (draw_udg+2, udg_defn[*str-udg_base], 8);
  304.                                 os_swi2 (XOS_WriteN, (int) draw_udg, 11);
  305.                                 curr_defined = *str++;
  306.                               }
  307.                           } /* while */
  308.                         if (*str == '\n')
  309.                             str++;
  310.                       } /* for */
  311.                   }
  312.               }
  313.           }
  314.         /* Write back old udg defn */
  315.         if (curr_defined != -1)
  316.             os_swi2 (XOS_WriteN, (int) old_defn, 10);
  317.       }
  318.   }
  319.  
  320. os_error *texticon_register_udgs (int base, int no)
  321.   { udg_base = base;
  322.     no_udgs = no;
  323.     if (udg_defn)
  324.         free (udg_defn);
  325.     if (no > 0)
  326.       { udg_defn = malloc (no * 8);
  327.         if (udg_defn == NULL)
  328.           { no_udgs = 0;
  329.             return (&out_of_memory);
  330.           }
  331.         memset (udg_defn, 0xAA, no*8);  /* Reset defns so noticable */
  332.       }
  333.     else
  334.         udg_defn = NULL;
  335.     return (NULL);
  336.   }
  337.  
  338. os_error *texticon_define_udg (int udg_no, char defn[8])
  339.   {
  340.     if (udg_no < 0 || udg_no >= no_udgs)
  341.         return (&out_of_range);
  342.  
  343.     memcpy (udg_defn[udg_no], defn, 8);
  344.     return (NULL);
  345.   }
  346.