home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-01 | 29.8 KB | 1,188 lines |
- // **************************************************************************
- // Copyright 1996 David Allison
- //
- // VV VV IIIIII SSSSS TTTTTT AA
- // VV VV II SS TT AA AA
- // VV VV II SSSS TT AA AA
- // VV VV II SS TT AAAAAAAA
- // VV IIIIII SSSS TT AA AA
- //
- // MULTI-THREADED C++ WIMP CLASS LIBRARY
- // for RISC OS
- // **************************************************************************
- //
- // P U B L I C D O M A I N L I C E N C E
- // -------------------------------------------
- //
- // This library is copyright. You may not sell the library for
- // profit, but you may sell products which use it providing
- // those products are presented as executable code and are not
- // libraries themselves. The library is supplied without any
- // warranty and the copyright owner cannot be held responsible for
- // damage resulting from failure of any part of this library.
- //
- // See the User Manual for details of the licence.
- //
- // *************************************************************************
-
- //
- // window objects
- //
-
- #include "Vista:task.h"
- #include "Vista:window.h"
- #include <stdlib.h>
- #include <kernel.h>
- #include <swis.h>
- #include <string.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <math.h>
-
- Object::Object (Window *w, char *name, int priority, char *menu)
- {
- window = w ;
- if (menu == NULL)
- default_menu = NULL ;
- else
- {
- default_menu = w->task->find_menu (menu) ;
- if (default_menu == NULL)
- throw ("Unknown menu") ;
- }
- next = NULL ;
- prev = NULL ;
- this->priority = priority ;
- strncpy (this->name, name, 32) ;
- w->add_object (this) ;
- }
-
- Object::~Object ()
- {
- window->remove_object (this) ;
- }
-
- void Object::redraw (int x0, int y0, int x1, int y1)
- {
- }
-
- void Object::update (int x0, int y0, int x1, int y1)
- {
- }
-
- int Object::compare (int x, int y)
- {
- x = window->xtowindow(x) ; // x in window coords
- y = window->ytowindow(y) ; // y in window coords
- return x <= this->x1 && x >= this->x0 && y <= this->y1 && y >= this->y0 ;
- }
-
- //
- // move to alternative window coords
- //
-
- void Object::move (int x0, int y0, int x1, int y1)
- {
- this->x0 = x0 ;
- this->y0 = y0 ;
- this->x1 = x1 ;
- this->y1 = y1 ;
- }
-
- void Object::move (int dx, int dy)
- {
- this->x0 += dx ;
- this->y0 += dy ;
- this->x1 += dx ;
- this->y1 += dy ;
- }
-
- void Object::drag (int mx, int my, int buttons)
- {
- window->task->register_object_drag (this, 1) ;
- window->do_drag (5, x0 + window->x0 - window->scx, y0 + window->y1 - window->scy,
- x1 + window->x0 - window->scx, y1 + window->y1 - window->scy) ;
- }
-
- void Object::click (int mx, int my, int button)
- {
- }
-
- void Object::double_click (int mx, int my, int button)
- {
- }
-
- void Object::end_drag (int x0, int y0, int x1, int y1, int id)
- {
- int oldx0 = this->x0 ;
- int oldy0 = this->y0 ;
- int oldx1 = this->x1 ;
- int oldy1 = this->y1 ;
- move (window->xtowindow (x0), window->ytowindow(y0),
- window->xtowindow (x1), window->ytowindow(y1)) ;
- window->do_redraw (oldx0, oldy0, oldx1, oldy1) ;
- window->do_redraw(this->x0, this->y0, this->x1, this->y1) ;
- }
-
- void Object::key (int x, int y, int height, int index, int code)
- {
- }
-
- void Object::select()
- {
- selected = 1 ;
- }
-
- void Object::unselect()
- {
- selected = 0 ;
- }
-
- void Object::pointer (int entering)
- {
- }
-
- void Object::mode_change()
- {
- }
-
- Menu *Object::display_menu (int x, int y, int button, int icon)
- {
- if (default_menu == NULL)
- {
- char *menu_name = get_menu(x, y, button, icon) ;
- if (menu_name == NULL)
- return NULL ;
- Menu *m = window->task->find_menu (menu_name) ;
- if (m != NULL)
- {
- m->open (x - 40, y) ;
- return m ;
- }
- return NULL ; // no menu
- }
- else
- {
- pre_menu (default_menu, x, y, button, icon) ;
- default_menu->open (x - 40, y) ;
- return default_menu ;
- }
- }
-
- //
- // give user a chance to change the menu before display
- //
-
- void Object::pre_menu (Menu *m, int x, int y, int button, int icon)
- {
- }
-
- //
- // this window doesn't have a default menu, ask the user to provide one
- //
-
-
- char *Object::get_menu (int x, int y, int button, int icon)
- {
- return NULL ;
- }
-
-
- void Object::menu (MenuItem item[])
- {
- }
-
-
- char *Object::help (int mx, int my, int buttons)
- {
- return NULL ;
- }
-
- static void move(int x, int y)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- r.r[0] = 4 ;
- r.r[1] = x ;
- r.r[2] = y ;
- if ((e = _kernel_swi (OS_Plot, &r, &r)) != NULL)
- throw (e) ;
- }
-
- static void draw_char (char ch)
- {
- _kernel_swi_regs r ;
- _kernel_swi (OS_WriteI+ch, &r, &r) ;
- }
-
- static void set_colour (int colour)
- {
- _kernel_swi_regs r ;
- r.r[0] = 18 ;
- _kernel_swi (OS_WriteC, &r, &r) ;
- r.r[0] = 0 ;
- _kernel_swi (OS_WriteC, &r, &r) ;
- r.r[0] = colour ;
- _kernel_swi (OS_WriteC, &r, &r) ;
- }
-
-
- //
- // icon object
- //
-
- IconObject::IconObject (Window *w, char *name, Icon *icon, int priority, char *menu)
- : Object (w, name, priority, menu)
- {
- this->icon = icon ;
- }
-
- IconObject::~IconObject ()
- {
- }
-
- void IconObject::redraw (int x0, int y0, int x1, int y1)
- {
- Box box ;
- icon->read_position (box) ;
- if (x0 <= box.x1 && x1 >= box.x0 && y0 <= box.y1 && y1 >= box.y0)
- icon->plot() ;
- }
-
-
- //
- // a sprite object
- //
-
- RawSpriteObject::RawSpriteObject (Window *w, char *name, char *sprite, void *area, int x, int y, int priority, char *menu)
- : Object (w, name, priority, menu)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- x0 = x ;
- y0 = y ;
- this->sprite = sprite ;
- this->area = area ;
- r.r[0] = 40 + 0x100 ; // read sprite info
- r.r[1] = (int)area ;
- r.r[2] = (int)sprite ;
- if ((e = _kernel_swi (OS_SpriteOp, &r, &r)) != NULL)
- throw (e) ;
- x1 = x0 + r.r[3] ;
- y1 = y0 + r.r[4] ;
- }
-
- RawSpriteObject::RawSpriteObject (Window *w, char *name, char *sprite, int x, int y, int priority, char *menu)
- : Object (w, name, priority, menu)
- {
- x0 = x ;
- y0 = y ;
- this->sprite = sprite ;
- this->area = 0 ;
- init() ;
- }
-
- void RawSpriteObject::init()
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- r.r[0] = 40 + (area == NULL ? 0 : 256) ; // read sprite info
- r.r[2] = (int)sprite ;
- if ((e = _kernel_swi (area == NULL ? Wimp_SpriteOp : OS_SpriteOp, &r, &r)) != NULL)
- throw (e) ;
- int xsize = r.r[3] ;
- int ysize = r.r[4] ;
- mode = r.r[6] ;
- xsize <<= window->task->xeigfactor ;
- ysize <<= window->task->yeigfactor ;
- x1 = x0 + xsize ;
- y1 = y0 + ysize ;
-
- // set up scale factors
-
- scale_factors[0] = 1 ;
- scale_factors[1] = 1 ;
- scale_factors[2] = 1 ;
- scale_factors[3] = 1 ;
-
- #if 0
- if (area == NULL)
- {
- if ((e = _kernel_swi (Wimp_BaseOfSprites, &r, &r)) != NULL)
- throw (e) ;
- r.r[0] = r.r[1] ;
- }
- else
- r.r[0] = (int)area ;
- #endif
- r.r[0] = mode ;
- r.r[1] = 3 ; // NColour (see PRM 1-710)
- if ((e = _kernel_swi (OS_ReadModeVariable,&r,&r)) != NULL)
- throw (e) ;
- pixel_trans = new char [256] ;
- if (r.r[2] < 63) // < 256 colours
- {
- unsigned int palette[20] ;
- r.r[1] = (int)palette ;
- if ((e = _kernel_swi (Wimp_ReadPalette,&r,&r)) != NULL)
- throw (e) ;
- unsigned int i,p,col ;
- for (i = 0 ; i < 15 ; i++)
- {
- p = palette[i] ;
- col = p ;
- col |= (p & 0xf0000000) >> 4 ;
- col |= (p & 0x00f00000) >> 4 ;
- col |= (p & 0x0000f000) >> 4 ;
- palette[i] = p & 0xffffff00 ;
- }
- r.r[0] = mode ;
- r.r[1] = 0 ;
- r.r[2] = -1 ;
- r.r[3] = (int)palette ;
- r.r[4] = (int)pixel_trans ;
- r.r[5] = 0 ;
- if ((e = _kernel_swi (ColourTrans_GenerateTable, &r, &r)) != NULL)
- throw (e) ;
- }
- else
- {
- r.r[0] = mode ;
- r.r[1] = -1 ;
- r.r[2] = -1 ;
- r.r[3] = -1 ;
- // r.r[4] = 0 ; // read buffer size
- // if ((e = _kernel_swi (ColourTrans_SelectTable, &r, &r)) != NULL)
- // throw (e) ;
- // pixel_trans = new char [r.r[4]] ;
- r.r[4] = (int) pixel_trans ;
- if ((e = _kernel_swi (ColourTrans_SelectTable, &r, &r)) != NULL)
- throw (e) ;
- }
- }
-
-
- RawSpriteObject::~RawSpriteObject ()
- {
- }
-
- void RawSpriteObject::redraw (int x0, int y0, int x1, int y1)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- int sx, sy ;
- int swi ;
- if (x0 <= this->x1 && x1 >= this->x0 && y0 <= this->y1 && y1 >= this->y0)
- {
- sx = window->xtoscreen(this->x0) ; // screen x
- sy = window->ytoscreen(this->y0) ; // screen y
- // ::move (sx, sy) ;
- r.r[0] = 52 + (area == NULL ? 0 : 256) ; // put sprite scaled
- r.r[1] = (int)area ;
- r.r[2] = (int)sprite ;
- r.r[3] = sx ;
- r.r[4] = sy ;
- r.r[5] = 8 ; // just put on screen
- r.r[6] = 0 ; // (int)scale_factors ;
- r.r[7] = (int)pixel_trans ;
- swi = ((area == NULL) ? Wimp_SpriteOp : OS_SpriteOp) ;
- if ((e = _kernel_swi (swi, &r, &r)) != NULL)
- throw (e) ;
- }
- }
-
-
- //
- // a text object
- //
-
- #if 0
- TextObject::TextObject (Window *w, char *name, char *text, int length, int x, int y, char *menu)
- : Object (w, name, priority, menu)
- {
- lines = NULL ;
- num_lines = 0 ;
- max_lines = 0 ;
- max_length = 0 ;
- this->text = (char*)malloc (length) ;
- if (this->text == NULL)
- throw ("Out of memory") ;
- memcpy (this->text, text, length) ;
- char *p = this->text ;
- char *ch = p ;
- int len ;
- for (;;)
- {
- while (length > 0 && *ch != '\n') length--,ch++ ; // skip to newline
- len = ch - p ;
- insert_line (p, len) ;
- p = ++ch ; // skip newline
- length-- ; // one byte less
- if (length <= 0)
- break ;
- }
- x0 = x ;
- y1 = y ;
- x1 = x0 + max_length ;
- y0 = y1 - num_lines * 32 ;
- }
- #endif
-
- TextObject::TextObject (Window *w, char *name, char *text, int x, int y, int priority, char *menu)
- : Object (w, name, priority, menu)
- {
- lines = NULL ;
- num_lines = 0 ;
- max_lines = 0 ;
- max_length = 0 ;
- int length = strlen (text) ;
- this->text = (char*)malloc (length+1) ;
- if (this->text == NULL)
- throw ("Out of memory") ;
- strcpy (this->text, text) ;
- char *p = this->text ;
- char *ch = p ;
- int len ;
- for (;;)
- {
- while (length > 0 && *ch != '\n') length--,ch++ ; // skip to newline
- len = ch - p ;
- insert_line (p, len) ;
- p = ++ch ; // skip newline
- length-- ; // one byte less
- if (length <= 0)
- break ;
- }
- x0 = x ;
- y1 = y ;
- x1 = x0 + max_length ;
- y0 = y1 - num_lines * 32 ;
- }
-
- TextObject::TextObject (Window *w, char *name, int x, int y, int priority, char *menu)
- : Object (w, name, priority, menu)
- {
- lines = NULL ;
- text = NULL ;
- num_lines = 0 ;
- max_lines = 0 ;
- max_length = 0 ;
- x0 = x ;
- y1 = y ;
- }
-
-
- TextObject::~TextObject()
- {
- if (text == NULL) // not initialised with text
- {
- for (int i = 0 ; i < num_lines ; i++)
- if (lines[i].text != NULL)
- free (lines[i].text) ;
- }
- else
- free (text) ;
- if (lines != NULL)
- free (lines) ;
- }
-
-
-
- void TextObject::redraw (int x0, int y0, int x1, int y1)
- {
- #if 1
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- int sx, sy ; // screen x and y coords
- int dx, dy ; // delta x and y
- int startx, starty ; // line and char positions in text
- int endx, endy, len ;
- if (lines == NULL) // no text?
- return ;
- if (x0 <= this->x1 && x1 >= this->x0 && y0 <= this->y1 && y1 >= this->y0)
- {
- dy = this->y1 - y1 ; // calculate difference in y coords
- dx = x0 - this->x0 ; // calc diff in X coords
- if (dy < 0) // above text?
- starty = 0 ; // start at line 0
- else
- starty = dy / 32 ; // start at first line in box
- if (dx < 0) // left of text?
- startx = 0 ; // start at char 0
- else
- startx = dx / 16 ; // start at first char in box
- dy = y1 - y0 ; // get difference in y coords
- dx = x1 - x0 ; // and x coords
- endy = (dy / 32) + starty + 1; // set end line count
- len = (dx / 16) + startx + 1; // set length count
- if (endy >= num_lines) // more than number of lines?
- endy = num_lines ;
- else
- endy++ ;
- sx = window->xtoscreen(this->x0) ; // screen x
- sy = window->ytoscreen(this->y1) ; // screen y
- line *l ;
- int i, j ;
- for (i = starty ; i < endy ; i++) // for each line
- {
- ::move (sx + startx * 16, sy - i * 32) ; // move to screen coord
- l = &lines[i] ;
- if (len >= l->length)
- endx = l->length ;
- else
- endx = len + 1;
- for (j = startx ; j < endx ; j++) // for each char
- {
- char ch = l->text[j] ;
- switch (ch)
- {
- case TextObject_Colour:
- {
- int colour = l->text[++j] ;
- set_colour (colour) ;
- break ;
- }
- default:
- draw_char (ch) ; // draw it
- break ;
- }
- }
- }
- }
- #endif
- }
-
-
-
- void TextObject::insert_line (char *text, int length)
- {
- if (num_lines == max_lines)
- {
- if (lines == NULL)
- lines = (line*)malloc (sizeof (line) * 10) ;
- else
- lines = (line*)realloc (lines, sizeof (line) * (max_lines + 10)) ;
- if (lines == NULL)
- throw ("Out of memory") ;
- max_lines += 10 ;
- }
- int i = num_lines++ ;
- lines[i].text = text ;
- lines[i].length = length ;
- int len = length * 16 ;
- if (len > max_length)
- max_length = len ;
- }
-
-
- void TextObject::insert_line (char *text)
- {
- if (num_lines == max_lines)
- {
- if (lines == NULL)
- lines = (line*)malloc (sizeof (line) * 10) ;
- else
- lines = (line*)realloc (lines, sizeof (line) * (max_lines + 10)) ;
- if (lines == NULL)
- throw ("Out of memory") ;
- max_lines += 10 ;
- }
- int i = num_lines++ ;
- char *p ;
- int len = strlen (text) ;
- p = malloc (len+1) ;
- if (p == NULL)
- throw ("Out of memory") ;
- strcpy (p, text) ;
- lines[i].text = p ;
- lines[i].length = len ;
- len *= 16 ;
- if (len > max_length)
- max_length = len ;
- x1 = x0 + max_length ;
- y0 = y1 - num_lines * 32 ;
- }
-
-
-
- //
- // a line
- //
-
- LineObject::LineObject (Window *w, char *name, int x1, int y1, int x2, int y2, int priority, int thickness)
- : Object (w, name, priority, NULL)
- {
- this->x0 = x1 ;
- this->y0 = y1 ;
- this->x1 = x2 ;
- this->y1 = y2 ;
- this->thickness = thickness ;
- if (thickness > 1)
- {
- double theta ; // angle from x axis
- double delta ; // angle to perpendicular
- const double ninety = 3.14159265 / 2 ;
- if (x1 == x2)
- theta = ninety ; // prevent division by zero
- else
- theta = atan ((y2 - y1)/(x2 - x1)) ;
- delta = ninety - theta ;
- dx = thickness * cos (delta) ; // delta x
- dy = thickness * sin (delta) ; // delta y
- }
- }
-
- LineObject::~LineObject ()
- {
- }
-
- void LineObject::redraw (int x0, int y0, int x1, int y1)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- int sx, sy ; // start screen x and y coords
- int ex, ey ; // end screen coords
- if (x0 <= this->x1 + dx && x1 >= this->x0 && y0 <= this->y1 && y1 >= this->y0 - dy)
- {
- sx = window->xtoscreen(this->x0) ; // screen x
- sy = window->ytoscreen(this->y0) ; // screen y
- ex = window->xtoscreen(this->x1) ; // screen x
- ey = window->ytoscreen(this->y1) ; // screen y
-
- if (thickness <= 1)
- {
- ::move (sx, sy) ; // move to screen coord
- r.r[0] = 5 ;
- r.r[1] = ex ;
- r.r[2] = ey ;
- _kernel_swi (OS_Plot, &r, &r) ;
- }
- else
- {
- ::move (sx, sy) ;
- ::move (sx + dx, sy - dy) ;
- r.r[0] = 0x55 ;
- r.r[1] = ex ;
- r.r[2] = ey ;
- _kernel_swi (OS_Plot, &r, &r) ;
- r.r[0] = 0x55 ;
- r.r[1] = ex + dx ;
- r.r[2] = ey - dy ;
- _kernel_swi (OS_Plot, &r, &r) ;
- }
- }
- }
-
-
- //
- // a font object
- //
-
- FontObject::FontObject (Window *w, char *name, int fhandle, int x0, int y1, int width, int priority, char *menu)
- : Object (w,name,priority, menu)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- text = NULL ;
- text_length = 0 ;
- max_length = 0 ;
- this->x0 = x0 ;
- this->y1 = y1 ;
- this->x1 = x0 + width ;
- lines = NULL ;
- last_line = NULL ;
- font_handle = fhandle ;
- indent = 0 ;
- }
-
- FontObject::~FontObject ()
- {
- line *l, *nextl ;
- for (l = lines ; l != NULL ; l = nextl)
- {
- nextl = l->next ;
- delete l ;
- }
- free (text) ;
- }
-
- //
- // finish off the font object by working out the set of lines
- //
-
- void FontObject::finish()
- {
- char *ch = text ; // current char
- struct
- {
- int axs, ays ;
- int axl, ayl ;
- int split_char ; // split character
- int x0, y0 ; // x,y of bottom left
- int x1,y1 ; // x,y of top right
- } coord_block ;
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- int cy = FONT_BORDER ;
- int xmax, ymax ;
- r.r[1] = x1 - x0 ;
- r.r[2] = 1000 ;
- if ((e = _kernel_swi (Font_Converttopoints, &r, &r)) != NULL)
- throw (e) ;
- xmax = r.r[1] - FONT_BORDER ;
- ymax = 0 ;
- int fhandle = font_handle ;
- int indent = this->indent ;
- int w ;
-
- while (*ch != 0)
- {
- coord_block.axs = coord_block.ays = 0 ;
- coord_block.axl = coord_block.ayl = 0 ;
- coord_block.split_char = ' ' ;
-
- r.r[0] = fhandle ;
- r.r[1] = (int)ch ;
- r.r[2] = 0x40120 ; // return bounding box, use R5, R0
- r.r[3] = xmax - indent;
- r.r[4] = ymax ;
- r.r[5] = (int)&coord_block ;
- r.r[7] = 0 ;
- if ((e = _kernel_swi (Font_ScanString, &r, &r)) != NULL)
- throw (e) ;
- line *l = new line ;
- l->next = NULL ;
- l->start = ch ;
- l->length = r.r[1] - (int)ch ;
- l->height = coord_block.y1 /*- coord_block.y0 */ ;
- l->y = cy + l->height ; // positive
- cy = l->y + FONT_LINE_GAP ;
- if (lines == NULL)
- lines = last_line = l ;
- else
- {
- last_line->next = l ;
- last_line = l ;
- }
- ch = (char*)r.r[1] ;
- r.r[1] = r.r[3] + indent ;
- l->width = r.r[1] ; // assign line width
- r.r[2] = 0 ;
- if ((e = _kernel_swi (Font_ConverttoOS, &r, &r)) != NULL)
- throw (e) ;
- end_width = r.r[1] ; // width in OS units
- if (*ch == ' ')
- ch++ ;
- if ((e = _kernel_swi (Font_FutureFont, &r, &r)) != NULL)
- throw (e) ;
- fhandle = r.r[0] ;
- indent = 0 ; // no more indent
- }
- r.r[1] = 0 ;
- r.r[2] = cy + FONT_BORDER ;
- if ((e = _kernel_swi (Font_ConverttoOS, &r, &r)) != NULL)
- throw (e) ;
- y0 = y1 - r.r[2] ;
- if (lines == last_line) // only one line?
- x1 = x0 + end_width ; // set width to width of only line
- }
-
- void FontObject::set_indent (int units)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- end_width = units ; // in case of 0 size object
- r.r[1] = units ;
- r.r[2] = 0 ;
- if ((e = _kernel_swi (Font_Converttopoints, &r, &r)) != NULL)
- throw (e) ;
- indent = r.r[1] ; // in millipoints
- }
-
-
- void FontObject::redraw (int x0, int y0, int x1, int y1)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- line *l ;
- int sx ; // start screen x coord
- int ey ; // end screen y coord
- int px, py ;
- int fhandle = font_handle ;
- int indent = this->indent ;
- if (x0 <= this->x1 && x1 >= this->x0 && y0 <= this->y1 && y1 >= this->y0)
- {
- sx = window->xtoscreen(this->x0) ; // screen x
- ey = window->ytoscreen(this->y1) ; // screen y
- r.r[1] = sx ;
- r.r[2] = ey ;
- if ((e = _kernel_swi (Font_Converttopoints, &r, &r)) != NULL)
- throw (e) ;
- px = r.r[1] ; // x in millipoints
- py = r.r[2] ; // y in millipoints
- for (l = lines ; l != NULL ; l = l->next)
- {
- r.r[0] = fhandle ;
- r.r[1] = (int)l->start ;
- r.r[2] = 0x180 ; // use R7, R0
- r.r[3] = px + indent ;
- r.r[4] = py - l->y ;
- r.r[7] = l->length ;
- if ((e = _kernel_swi (Font_Paint, &r, &r)) != NULL)
- throw (e) ;
- if ((e = _kernel_swi (Font_FutureFont, &r, &r)) != NULL)
- throw (e) ;
- fhandle = r.r[0] ;
- indent = 0 ; // no more indent
- }
- }
- }
-
-
- void FontObject::check_buffer(int length)
- {
- while (text_length + length > max_length)
- {
- if (text == NULL)
- {
- text = (char*)malloc (FONT_BLOCKING_FACTOR) ;
- max_length = FONT_BLOCKING_FACTOR ;
- }
- else
- {
- text = (char*)realloc (text, max_length * 2) ;
- max_length *= 2 ;
- }
- if (text == NULL)
- throw ("Out of memory") ;
- }
- }
-
-
-
- void FontObject::add_text (char *t)
- {
- int length = strlen (t) + 1 ; // allow for 0
- check_buffer (length) ;
- memcpy (&text[text_length], t, length) ;
- text_length += length - 1 ; // remove 0
- }
-
-
- void FontObject::set_colour (int r, int g, int b, int R, int G, int B, int max)
- {
- check_buffer (8) ;
- char *ch = &text[text_length] ;
- *ch++ = 19 ;
- *ch++ = r ;
- *ch++ = g ;
- *ch++ = b ;
- *ch++ = R ;
- *ch++ = G ;
- *ch++ = B ;
- *ch = max ;
- text_length += 8 ;
- }
-
- void FontObject::begin_underline()
- {
- check_buffer (3) ;
- char *ch = &text[text_length] ;
- *ch++ = 25 ;
- *ch++ = 210 ;
- *ch = 20 ;
- text_length += 3 ;
- }
-
- void FontObject::end_underline()
- {
- check_buffer (3) ;
- char *ch = &text[text_length] ;
- *ch++ = 25 ;
- *ch++ = 210 ;
- *ch = 0 ;
- text_length += 3 ;
- }
-
- void FontObject::set_font (int handle)
- {
- check_buffer(2) ;
- char *ch = &text[text_length] ;
- *ch++ = 26 ;
- *ch = handle ;
- text_length += 2 ;
- }
-
- int FontObject::width()
- {
- return end_width ;
- }
-
- int FontObject::compare (int x, int y)
- {
- // quick check first
- int x1 = x + (window->scx - window->x0) ; // x in window coords
- int y1 = y + (window->scy - window->y1) ; // y in window coords
- if (x1 > this->x1 || x1 < this->x0 || y1 > this->y1 || y1 < this->y0)
- return 0 ;
- // now try for more accuracy
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- line *l ;
- int sx ; // start screen x coord
- int ey ; // end screen y coord
- int px, py ;
- int indent = this->indent ;
- // first convert position into millipoints
- r.r[1] = x ;
- r.r[2] = y ;
- if ((e = _kernel_swi (Font_Converttopoints, &r, &r)) != NULL)
- throw (e) ;
- x = r.r[1] ;
- y = r.r[2] ;
- // get the screen position of object in os units
- sx = window->x0 + this->x0 - window->scx ; // screen x
- ey = window->y1 + this->y1 - window->scy ; // screen y
- r.r[1] = sx ;
- r.r[2] = ey ;
- if ((e = _kernel_swi (Font_Converttopoints, &r, &r)) != NULL)
- throw (e) ;
- px = r.r[1] ; // sx in millipoints
- py = r.r[2] ; // ey in millipoints
- // now go thru the lines looking for a match
- for (l = lines ; l != NULL ; l = l->next)
- {
- if (y > py) // gone past possible line?
- return 0 ;
- if (y >= (py - l->y) &&
- x <= (px + indent + l->width) &&
- x >= (px + indent))
- return 1 ;
- indent = 0 ;
- }
- return 0 ;
- }
-
-
- //
- // Draw object (uses DrawFile module)
- //
-
-
- DrawObject::DrawObject (Window *w, char *name, char *data, int length, int x, int y, int priority, char *menu)
- : Object (w, name, priority, menu)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- this->data = data ;
- data_length = length ;
- dealloc_data = false ;
- max_length = length ;
- init (x,y) ;
- }
-
- DrawObject::DrawObject (Window *w, char *name, char *filename, int x, int y, int priority, char *menu)
- : Object (w, name, priority, menu)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- r.r[0] = 17 ;
- r.r[1] = (int)filename ;
- if ((e = _kernel_swi (OS_File, &r, &r)) != NULL) // read file length
- throw (e) ;
- data_length = r.r[4] ;
- data = malloc (data_length) ;
- if (data == NULL)
- throw ("Out of memory") ;
- r.r[0] = 12 ;
- r.r[1] = (int)filename ;
- r.r[2] = (int)data ;
- r.r[3] = 0 ;
- if ((e = _kernel_swi (OS_File, &r, &r)) != NULL) // load the file
- throw (e) ;
- dealloc_data = true ;
- max_length = data_length ;
- init(x,y) ;
- }
-
-
-
- DrawObject::DrawObject(Window *w, char *name, int priority, char *menu)
- : Object (w, name, priority, menu)
- {
- data = NULL ;
- max_length = data_length = 0 ;
- dealloc_data = true ;
- }
-
-
- //
- // Note that the x and y passed to this are the window coords for the top left of
- // the diagram. This conflicts with the drawfile SWIs as they use the
- // bottom left as the origin. It is necessary to translate the diagram
- // down by its height to get it to the correct position
- //
-
- void DrawObject::init(int x, int y) // x and y are in window coords
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- matrix[0] = 1<<16 ;
- matrix[1] = 0 ;
- matrix[2] = 0 ;
- matrix[3] = 1 << 16 ;
- matrix[4] = 256*(window->x0 + x - window->scx) ; // convert to screen coords
- matrix[5] = 256*(window->y1 + y - window->scy) ;
- r.r[0] = 0 ;
- r.r[1] = (int)data ;
- r.r[2] = data_length ;
- r.r[3] = (int)matrix ;
- int buffer[4] ;
- r.r[4] = (int)buffer ;
- if ((e = _kernel_swi (DrawFile_BBox, &r, &r)) != NULL)
- throw (e) ;
- xoffset = buffer[0] - 256*(window->x0 + x - window->scx) ;
- yoffset = buffer[1] - 256*(window->y1 + y - window->scy) ;
- int height = (buffer[3] - buffer[1]) / 256 ; // height in OS units
- int width = (buffer[2] - buffer[0]) / 256 ; // width in OS units
- x0 = x ;
- y1 = y ;
- x1 = x + width ;
- y0 = y - height ;
- }
-
-
- DrawObject::~DrawObject()
- {
- if (dealloc_data)
- free(data) ;
- }
-
- void DrawObject::redraw (int x0, int y0, int x1, int y1)
- {
- if (x0 <= this->x1 && x1 >= this->x0 && y0 <= this->y1 && y1 >= this->y0)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- r.r[0] = 0 ;
- r.r[1] = (int)data ;
- r.r[2] = data_length ;
- matrix[4] = 256*window->xtoscreen(this->x0) - xoffset ;
- matrix[5] = 256*window->ytoscreen(this->y0) - yoffset ;
- r.r[3] = (int)matrix ;
- int clip[4] ;
- clip[0] = window->xtoscreen(x0) ;
- clip[1] = window->ytoscreen(y0) ;
- clip[2] = window->xtoscreen(x1) ;
- clip[3] = window->ytoscreen(y1) ;
- r.r[4] = (int)clip ;
- if ((e = _kernel_swi (DrawFile_Render, &r, &r)) != NULL)
- throw (e) ;
- }
- }
-
-
- void DrawObject::make_header (int width, int height)
- {
- check_space (40) ;
- int *p = (int*)&data[data_length] ;
- strncpy ((char*)p, "Draw", 4) ;
- p++ ;
- *p++ = 201 ;
- *p++ = 0 ;
- strncpy ((char*)p, "Vista ",12) ;
- p += 3 ;
- *p++ = 0 ;
- *p++ = 0 ;
- *p++ = width ;
- *p++ = height ;
- data_length = 40 ;
- }
-
- void DrawObject::insert_word (int word)
- {
- check_space (sizeof(int)) ;
- int *p = (int*)&data[data_length] ;
- *p = word ;
- data_length += sizeof(int) ;
- }
-
- void DrawObject::insert_string (char *str)
- {
- int length = strlen (str) ;
- check_space (length + 1) ;
- memcpy (&data[data_length], str, length + 1) ;
- data_length += length + 1 ;
- }
-
- void DrawObject::insert_data (void *s, int length)
- {
- check_space (length) ;
- memcpy (&data[data_length], s, length) ;
- data_length += length ;
- }
-
- void DrawObject::insert_byte (char c)
- {
- check_space (1) ;
- char *p = &data[data_length] ;
- *p = c ;
- data_length++ ;
- }
-
- void DrawObject::align()
- {
- check_space (sizeof (int)) ;
- data_length = (data_length + 3) & ~3 ;
- }
-
- void DrawObject::check_space (int length)
- {
- if (data_length + length > max_length)
- {
- if (length < DRAW_BLOCKING_FACTOR)
- length = DRAW_BLOCKING_FACTOR ;
- else
- length += DRAW_BLOCKING_FACTOR ;
- if (data == NULL)
- data = (char*)malloc (length) ;
- else
- data = (char*)realloc (data, max_length + length) ;
- if (data == NULL)
- throw ("Out of memory") ;
- max_length += length ;
- }
- }
-
- SpriteObject::SpriteObject (Window *w, char *name, char *sprite, int x, int y, int priority, char *menu)
- : DrawObject (w, name, priority, menu)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- void *addr = w->task->find_sprite (sprite) ;
- if (addr == NULL)
- throw ("No such sprite") ;
- int length = *((int*)addr) ;
- length = (length + 3) & ~3 ; // align the length
- r.r[0] = 40 ; // read sprite info
- r.r[2] = (int)sprite ;
- if ((e = _kernel_swi (Wimp_SpriteOp, &r, &r)) != NULL)
- throw (e) ;
- int width = (r.r[3] << w->task->xeigfactor) * 256 ;
- int height = (r.r[4] << w->task->yeigfactor) * 256 ;
- make_header (width, height) ;
- insert_word (5) ; // sprite object
- insert_word (24 + length) ; // object length
- insert_word (0) ;
- insert_word (0) ;
- insert_word (width) ;
- insert_word (height) ;
- insert_data (addr, length) ;
- init (x,y) ;
- }
-
- SpriteObject::~SpriteObject()
- {
- }
-
-