home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 1
/
ARM_CLUB_CD.iso
/
contents
/
education
/
a
/
biology1
/
!Biology1
/
c
/
TextIcon
< prev
next >
Wrap
Text File
|
1991-12-02
|
11KB
|
346 lines
/* TextIcon */
/* To display & maintain an icon containing text */
/* We maintain a list of windows
* Each with a list of icons
* each comprising the icon no, position, & pointer to text.
*/
#include <stdlib.h>
#include <string.h>
#include "kernel.h"
#include "os.h"
#include "wimp.h"
#include "texticon.h"
#include "utils.h"
#define XOS_Plot 0x020045
#define XOS_WriteN 0x020046
#define XOS_WriteI 0x020100
static int udg_base = 128;
static int no_udgs = 0;
static char (*udg_defn)[8] = NULL;
static os_error out_of_memory = {0, "Out of memory"};
/* Program error if the following occurs */
static os_error out_of_range = {0, "Out of range"};
struct iconlist
{ struct iconlist *next;
wimp_i handle;
char *text;
int flags;
};
struct windlist
{ struct windlist *next;
wimp_w w;
struct iconlist *i;
};
static struct windlist *list = NULL;
os_error *texticon_create_icon (wimp_icreate *defn, wimp_i *result)
{ struct windlist *wnd_ptr;
struct iconlist *ic_ptr;
wimp_icreate icreate;
os_error *err;
memcpy (&icreate, defn, sizeof (wimp_icreate));
/* Find window */
ll_find (wnd_ptr, list, w, icreate.w);
if (wnd_ptr == NULL)
{ wnd_ptr = malloc (sizeof (struct windlist));
if (wnd_ptr == NULL)
return (&out_of_memory);
(wnd_ptr)->next = list;
(wnd_ptr)->w = icreate.w;
(wnd_ptr)->i = NULL;
list = wnd_ptr;
}
ic_ptr = malloc (sizeof (struct iconlist));
if (ic_ptr == NULL)
return (&out_of_memory);
/* Remember flags */
ic_ptr->flags = icreate.i.flags;
/* Modify defn */
icreate.i.flags &= ~ wimp_IFILLED;
if (icreate.i.flags & wimp_ITEXT)
{ if (icreate.i.flags & wimp_INDIRECT)
{ ic_ptr->text = malloc (icreate.i.data.indirecttext.bufflen);
if (ic_ptr->text == NULL)
return (&out_of_memory);
strcpy (ic_ptr->text, icreate.i.data.indirecttext.buffer);
}
else
{ ic_ptr->text = malloc (12);
if (ic_ptr->text == NULL)
return (&out_of_memory);
strcpy (ic_ptr->text, icreate.i.data.text);
}
icreate.i.flags |= wimp_IREDRAW;
icreate.i.flags &= ~0x140; /* cancel wimp_IFONT | wimp_INDIRECT*/
icreate.i.data.text[0] = '\0';
}
else
{ ic_ptr->text = NULL;
}
/* Create it */
err = wimp_create_icon (&icreate, result);
if (err)
{ if (ic_ptr->text)
free (ic_ptr->text);
free (ic_ptr);
return (err);
}
ic_ptr->handle = *result;
ic_ptr->next = wnd_ptr->i;
wnd_ptr->i = ic_ptr;
return (NULL);
}
os_error *texticon_delete_wind (wimp_w wnd)
{ struct windlist *wnd_p;
struct iconlist *ic_ptr, *next_icon;
ll_find (wnd_p, list, w, wnd);
if (wnd_p != NULL) /* Free all it's icons */
{ next_icon = wnd_p->i;
while (next_icon != NULL)
{ ic_ptr = next_icon;
next_icon = ic_ptr->next;
if (ic_ptr->text)
free (ic_ptr->text);
free (ic_ptr);
}
/* Now window has no icons, unlink it */
ll_unlink (struct windlist, wnd_p, list);
}
/* That's done our housekeeping, now delete the window */
return (wimp_delete_wind (wnd));
}
os_error *texticon_delete_icon (wimp_w wnd, wimp_i ic, BOOL force_redraw)
{ struct windlist *wnd_p;
struct iconlist *ic_p;
wimp_icon result;
wimp_redrawstr r;
os_error *res_err;
ll_find (wnd_p, list, w, wnd);
if (wnd_p != NULL)
{
ll_find (ic_p, wnd_p->i, handle, ic);
if (ic_p != NULL)
{ if (ic_p->text)
free (ic_p->text);
ll_unlink (struct iconlist, ic_p, wnd_p->i);
}
/* Now if window has no icons, unlink it */
if (wnd_p->i == NULL)
ll_unlink (struct windlist, wnd_p, list);
}
/* That's done our housekeeping, now delete the icon */
wimp_get_icon_info (wnd, ic, &result);
r.w = wnd;
memcpy (&r.box, &result.box, sizeof (wimp_box));
wimp_delete_icon (wnd, ic);
if (force_redraw)
{ wimp_force_redraw (&r);
}
return (res_err);
}
void texticon_del_all_icons (wimp_w wnd)
{ struct windlist *wnd_p;
struct iconlist *ic_ptr, *next_icon;
ll_find (wnd_p, list, w, wnd);
if (wnd_p != NULL)
{ next_icon = wnd_p->i;
while (next_icon != NULL)
{ ic_ptr = next_icon;
next_icon = ic_ptr->next;
texticon_delete_icon (wnd, ic_ptr->handle, FALSE);
}
}
}
void texticon_redraw (wimp_redrawstr *r)
{ int work_origin_x, work_origin_y;
int clip_x0, clip_y0, clip_x1, clip_y1;
int curr_defined = -1;
int hoffset, voffset;
int line, llen, l;
char *str, *line_end;
char gcol[3] = {18, 0};
char draw_udg[11] = {23, 128, 0, 0, 0, 0, 0, 0, 0, 0, 128};
char old_defn[10] = {23, 128, 0, 0, 0, 0, 0, 0, 0, 0};
wimp_icon ic_info;
struct windlist *wnd_ptr;
struct iconlist *ic_ptr;
/* Find window */
ll_find (wnd_ptr, list, w, r->w);
if (wnd_ptr != NULL)
{ work_origin_x = r->box.x0 - r->scx;
work_origin_y = r->box.y1 - r->scy;
clip_x0 = r->g.x0 - work_origin_x;
clip_y0 = r->g.y0 - work_origin_y;
clip_x1 = r->g.x1 - work_origin_x;
clip_y1 = r->g.y1 - work_origin_y;
/* Read old udg defn */
os_word (10, old_defn+1);
for (ic_ptr = wnd_ptr->i; ic_ptr; ic_ptr = ic_ptr->next)
{ wimp_get_icon_info (r->w, ic_ptr->handle, &ic_info);
if (ic_info.box.x0 < clip_x1 &&
ic_info.box.y0 < clip_y1 &&
ic_info.box.x1 > clip_x0 &&
ic_info.box.y1 > clip_y0)
{
if (ic_ptr->flags & wimp_IFILLED)
{
char rect [12] = {25,4, 0,0, 0,0, 25, 96+5, 0,0, 0,0};
int x0 = work_origin_x + ic_info.box.x0;
int x1 = work_origin_x + ic_info.box.x1 - 1;
int y0 = work_origin_y + ic_info.box.y0;
int y1 = work_origin_y + ic_info.box.y1 - 1;
#define rectcoord(value, offset) rect [offset] = value & 0xff; \
rect [offset+1] = value >> 8
rectcoord (x0, 2);
rectcoord (y0, 4);
rectcoord (x1, 8);
rectcoord (y1, 10);
gcol[2] = ((ic_info.flags >> 28) & 0x0F);
os_swi2 (XOS_WriteN, (int) gcol, 3);
os_swi2 (XOS_WriteN, (int) rect, 12);
}
if (ic_info.flags & wimp_ITEXT)
{
/* COLOURS MAY NEED translating */
gcol[2] = ((ic_info.flags >> 24) & 0x0F);
os_swi2 (XOS_WriteN, (int) gcol, 3);
/* Set vertical offset */
if (ic_info.flags & wimp_IVCENTRE)
{ for (str = ic_ptr->text, line=0; str; line++)
{ str = strchr (str, '\n');
if (str)
str++; /* Put us past the newline */
if (str && *str == '\0')
str = NULL; /* Ignore an empty last line */
}
voffset = (ic_info.box.y1 - ic_info.box.y0)/2 -
20 * line + 4;
/* NB ABOVE ASSUMES CHARACTERS 32 OS UNITS DEEP & spaced at 40 */
}
else
voffset = 8;
/* Write the lines */
for (str = ic_ptr->text, line=0; *str; line++)
{ /* Position cursor */
if (ic_info.flags & wimp_IHCENTRE)
{ line_end = strchr (str, '\n');
if (line_end == NULL)
llen = strlen (str);
else
llen = line_end - str;
hoffset = (ic_info.box.x1 - ic_info.box.x0)/2 -
8 * llen;
/* NB ABOVE ASSUMES CHARACTERS 16 OS UNITS WIDE */
}
else
hoffset = 8;
os_swi3 (XOS_Plot, 4,
work_origin_x + ic_info.box.x0 + hoffset,
work_origin_y + ic_info.box.y1 - voffset
- 40 * line);
/* Now print the line */
while (*str && *str != '\n')
{ /* Count block to write */
l=0;
while (str[l] && str[l]!='\n' &&
(str[l] < udg_base || str[l] >= udg_base+no_udgs))
l++;
os_swi2 (XOS_WriteN, (int) str, l);
str += l;
/* If we've stopped for a udg, print it */
if (*str == curr_defined)
{ os_swi0 (XOS_WriteI + 128);
str++;
}
else if (*str>=udg_base && *str<udg_base+no_udgs)
{ memcpy (draw_udg+2, udg_defn[*str-udg_base], 8);
os_swi2 (XOS_WriteN, (int) draw_udg, 11);
curr_defined = *str++;
}
} /* while */
if (*str == '\n')
str++;
} /* for */
}
}
}
/* Write back old udg defn */
if (curr_defined != -1)
os_swi2 (XOS_WriteN, (int) old_defn, 10);
}
}
os_error *texticon_register_udgs (int base, int no)
{ udg_base = base;
no_udgs = no;
if (udg_defn)
free (udg_defn);
if (no > 0)
{ udg_defn = malloc (no * 8);
if (udg_defn == NULL)
{ no_udgs = 0;
return (&out_of_memory);
}
memset (udg_defn, 0xAA, no*8); /* Reset defns so noticable */
}
else
udg_defn = NULL;
return (NULL);
}
os_error *texticon_define_udg (int udg_no, char defn[8])
{
if (udg_no < 0 || udg_no >= no_udgs)
return (&out_of_range);
memcpy (udg_defn[udg_no], defn, 8);
return (NULL);
}