home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-01 | 35.2 KB | 1,323 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.
- //
- // *************************************************************************
-
-
-
- //
- // c.task
- //
-
- #include "Vista:task.h"
- #include <kernel.h>
- #include <swis.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <setjmp.h>
-
-
-
- ControlThread::ControlThread(Task *t, int event, int *buf)
- : Thread ("control")
- {
- task = t ;
- next = NULL ;
- init (event, buf) ;
- }
-
- ControlThread::~ControlThread()
- {
- }
-
- void ControlThread::init(int event, int *buf)
- {
- this->event = event ;
- memcpy (this->buf, buf, sizeof (this->buf)) ;
- }
-
- void ControlThread::run()
- {
- int caught = 0 ;
- Window *w ;
- _kernel_oserror err ;
- _kernel_oserror *e ;
- _kernel_swi_regs r ;
- int adjust_hit ; // adjust was hit on menu
- Object *object ;
- #ifdef __EASY_C
- try
- #endif
- {
- switch (event)
- {
- case Task::ENULL:
- break ;
- case Task::EREDRAW: /* this is handled as a special case */
- #if 0
- w = task->find_window (buf[0]) ;
- if (w == NULL)
- break ;
- w->redraw() ;
- #endif
- break ;
- case Task::EOPEN:
- w = task->find_window (buf[0]) ;
- if (w == NULL)
- break ;
- w->open(buf[1],buf[2],buf[3],buf[4], buf[5], buf[6], buf[7]) ;
- break ;
- case Task::ECLOSE:
- w = task->find_window (buf[0]) ;
- if (w == NULL)
- break ;
- w->close() ;
- break ;
- case Task::EPTRLEAVE:
- case Task::EPTRENTER:
- w = task->find_window (buf[0]) ;
- if (w == NULL)
- break ;
- w->pointer (event == Task::EPTRENTER) ;
- break ;
- case Task::EBUT:
- if (buf[3] >= 0) // in a window?
- {
- w = task->find_window (buf[3]) ; // find the window
- if (w == NULL)
- break ;
- if (buf[2] & Task::BMID) // menu button?
- {
- Icon *icon ;
- bool found = false ;
- if (buf[4] != -1 && (icon = w->find_icon(buf[4])) != NULL) // find icon
- {
- task->current_menu = icon->display_menu (buf[0], buf[1], buf[2], buf[4]) ;
- if (task->current_menu != NULL)
- {
- found = true ;
- task->current_menu_icon = icon ;
- }
- }
- if (!found && (object = w->find_object (buf[0], buf[1])) != NULL) // find object
- {
- task->current_menu = object->display_menu (buf[0], buf[1], buf[2], buf[4]) ;
- if (task->current_menu != NULL)
- {
- found = true ;
- task->current_menu_object = object ;
- }
- }
- if (!found)
- {
- task->current_menu = w->display_menu (buf[0], buf[1], buf[2], buf[4]) ;
- task->current_menu_window = w ;
- }
- }
- else
- {
- if (buf[4] != -1) // on an icon?
- {
- Icon *icon ;
- if ((icon = w->find_icon(buf[4])) != NULL) // find it
- {
- icon->click (buf[0], buf[1], buf[2], buf[4]) ; // say clicked
- break ;
- }
- }
- if ((object = w->find_object (buf[0], buf[1])) != NULL)
- {
- if (buf[2] & (4 * 16 + 16))
- object->drag (buf[0], buf[1], buf[2]) ;
- else if (buf[2] & (4 + 1))
- object->double_click (buf[0], buf[1], buf[2]) ;
- else
- object->click (buf[0], buf[1], buf[2]) ;
- }
- else
- w->click(buf[0], buf[1], buf[2], buf[4]) ; // tell window
- }
- }
- else if (buf[3] == -2) // icon bar
- {
- task->current_menu_window = NULL ; // no window
- task->current_menu_icon = NULL ; // no icon
- task->current_menu_object = NULL ; // no object
- if (buf[2] & Task::BMID)
- {
- if (task->iconbar_menu != NULL)
- {
- task->current_menu = task->iconbar_menu ;
- task->pre_menu (task->iconbar_menu) ; // any user modifications
- task->iconbar_menu->iconbar_adjust (buf[0], buf[1]) ;
- task->iconbar_menu->open(buf[0] - 48, buf[1]) ;
- }
- else
- {
- char *menu_name = task->get_iconbar_menu (buf[4]) ;
- if (menu_name != NULL)
- {
- task->current_menu = task->menus->find (menu_name) ;
- task->current_menu->iconbar_adjust (buf[0], buf[1]) ;
- task->current_menu->open (buf[0] - 48, buf[1]) ;
- }
- }
- }
- else
- task->click (buf[0], buf[1], buf[2], buf[4]) ;
- }
- break ;
- case Task::EUSERDRAG:
- if (task->dragging_sprite)
- {
- _kernel_swi (DragASprite_Stop, &r, &r) ;
- task->dragging_sprite = false ;
- }
- if (task->object_dragger != NULL)
- {
- task->object_dragger->end_drag (buf[0], buf[1], buf[2], buf[3], task->object_dragger_id) ;
- task->object_dragger = NULL ;
- }
- if (task->dragger != NULL)
- {
- task->dragger->drag(buf[0], buf[1], buf[2], buf[3],task->dragger_id) ;
- task->dragger = NULL ;
- }
- break ;
- case Task::EKEY:
- w = task->find_window (buf[0]) ;
- if (w == NULL)
- break ;
- if (buf[1] != -1) // pressed in an icon?
- {
- Icon *icon ;
- if ((icon = w->find_icon(buf[1])) != NULL) // find it
- {
- icon->key (buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]) ; // say key pressed
- break ;
- }
- }
- if ((object = w->find_object (buf[0], buf[1])) != NULL)
- object->key (buf[2], buf[3], buf[4], buf[5], buf[6]) ;
- else
- w->key (buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]) ;
- break ;
- case Task::EMENU:
- {
- int pointer_info[5] ;
- r.r[1] = (int)pointer_info ;
- if ((e = _kernel_swi (Wimp_GetPointerInfo, &r, &r)) != NULL)
- throw (e) ;
- adjust_hit = pointer_info[2] & 1 ;
- if (!task->current_menu->invalid_selection(buf))
- {
- MenuItem *items = task->current_menu->selection (buf) ;
- if (task->current_menu_icon != NULL)
- task->current_menu_icon->menu (items) ;
- else if (task->current_menu_object != NULL)
- task->current_menu_object->menu (items) ;
- else if (task->current_menu_window != NULL)
- task->current_menu_window->menu (items) ;
- else
- task->menu (items) ;
- }
- if (adjust_hit)
- task->current_menu->open (0,0) ;
- break ;
- }
- case Task::ESCROLL:
- w = task->find_window (buf[0]) ;
- if (w == NULL)
- break ;
- w->scroll (buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]) ;
- break ;
- case Task::ELOSECARET:
- case Task::EGAINCARET:
- w = task->find_window (buf[0]) ;
- if (w == NULL)
- break ;
- w->caret (r.r[0] == Task::EGAINCARET, buf[1], buf[2], buf[3], buf[4], buf[5]) ;
- break ;
- case Task::EPOLLNONZERO:
- task->poll_word_non_zero ((int *)buf[0], buf[1]) ;
- break ;
- case Task::ESEND:
- case Task::ESENDWANTACK:
- switch (buf[4])
- {
- case Task::Message_Quit: // quit message
- task->exit() ;
- break ;
-
- case Task::Message_ModeChange: // mode change message
- {
- int iblock[3] ;
- int oblock[2] ;
-
- for (w = task->windows ; w != NULL ; w = w->next) // tell windows
- w->mode_change() ;
- r.r[0] = 0 ; // see PRM 3-416
- r.r[1] = (int)"" ;
- r.r[2] = 0x10 ;
- r.r[3] = -1 ;
- r.r[4] = -1 ;
- if ((e = _kernel_swi (Font_Paint, &r, &r)) != NULL)
- throw (e) ;
- r.r[0] = (int)iblock ;
- r.r[1] = (int)oblock ;
- iblock[0] = 4 ;
- iblock[1] = 5 ;
- iblock[2] = -1 ;
- if ((e = _kernel_swi (OS_ReadVduVariables, &r, &r)) != NULL)
- throw (e) ;
- task->xeigfactor = oblock[0] ;
- task->yeigfactor = oblock[1] ;
- break ;
- }
-
- case Task::Message_MenuWarning: // menu warning
- {
- MenuItem *items = task->current_menu->selection (buf+8) ;
- if (task->current_menu_icon != NULL)
- task->current_menu_icon->menu (items) ;
- else if (task->current_menu_object != NULL)
- task->current_menu_object->menu (items) ;
- else if (task->current_menu_window != NULL)
- task->current_menu_window->menu (items) ;
- else
- task->menu (items) ;
- break ;
- }
-
- case Task::Message_HelpRequest:
- {
- char *help_reply = NULL ;
- w = task->find_window (buf[8]) ;
- if (w != NULL)
- {
- if (buf[9] != -1) // pressed in an icon?
- {
- Icon *icon ;
- if ((icon = w->find_icon(buf[9])) != NULL) // find it
- help_reply = icon->help (buf[5], buf[6], buf[7]) ;
- }
- if (help_reply == NULL && (object = w->find_object (buf[5], buf[6])) != NULL)
- help_reply = object->help (buf[5], buf[6], buf[7]) ;
- if (help_reply == NULL)
- help_reply = w->help (buf[5], buf[6], buf[7], buf[9]) ;
- }
- if (help_reply == NULL)
- help_reply = task->help (buf[5],buf[6],buf[7],buf[8],buf[9]) ;
- if (help_reply != NULL)
- {
- int len = strlen (help_reply) + 1 ; // allow of 0 at end
- int my_ref ;
- task->send_message (Task::ESEND, Task::Message_HelpReply, buf[1], my_ref, buf[2], len, help_reply) ;
- }
- break ;
- }
-
- default:
- {
- Task::receiver *r = task->find_receiver (buf[4], buf[3]) ;
- if (r != NULL)
- r->channel->receive (buf[4], buf[1], buf[2], buf[3], buf[0] - 20, &buf[5]) ;
- break;
- }
- }
- break ;
- case Task::EACK:
- break ;
- }
- }
- #ifdef __EASY_C
- catch (TaskError t)
- {
- err.errnum = 0 ;
- strcpy (err.errmess, task->lookup(t.buf)) ;
- r.r[0] = (int)&err ;
- r.r[1] = 0 ;
- r.r[2] = (int)task->program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- if (t.fatal)
- task->exit(t.fatal) ;
- }
-
- catch (_kernel_oserror *e)
- {
- r.r[0] = (int)e ;
- r.r[1] = 0 ;
- r.r[2] = (int)task->program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- }
- catch (char *s)
- {
- err.errnum = 0 ;
- strcpy (err.errmess, task->lookup(s)) ;
- r.r[0] = (int)&err ;
- r.r[1] = 0 ;
- r.r[2] = (int)task->program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- }
- #endif
- task->delete_deferred (this) ;
- }
-
-
- DebugWin::DebugWin (Task *t)
- : Window (t,"debug")
- {
- text = NULL ;
- Window::Info *inf = info() ;
- min_height = inf->extent.y1 - inf->extent.y0 ;
- }
-
- DebugWin::~DebugWin()
- {
- if (text != NULL)
- delete text ;
- }
-
- void DebugWin::print (char *format...)
- {
- char buffer[1024] ;
- va_list arg ;
- va_start (arg,format) ;
- vsprintf (buffer,format,arg) ;
- if (text == NULL)
- text = new TextObject (this, "text", buffer, 8, -8) ;
- else
- text->insert_line (buffer) ;
- int height = text->height() + 16 ;
- if (height > min_height)
- set_height (height) ;
- Window::State *s = state() ;
- do_open (s->box.x0, s->box.y0, s->box.x1, s->box.y1, 0, ((s->box.y1 - s->box.y0)/2) - height) ;
- do_redraw() ;
- }
-
- static char *signals[] = {
- "Abort",
- "Floating point exception",
- "Illegal instruction",
- "Interrupt",
- "Segmentation fault",
- "Terminate",
- "Stack overflow"
- } ;
- static char *application ;
-
- void signal_handler(int sig)
- {
- thread_disable_ints() ;
- thread_stop_ticker(ThreadManager::current_manager) ;
- // raise(sig) ;
- ::print ("%s has received signal \"%s\" and must exit immediately",application,signals[sig]) ;
- exit(1) ;
- }
-
- Task *main_task ;
-
- void dprintf (char *format...)
- {
- if (main_task->debug == NULL)
- return ;
- char buf[1024] ;
- va_list arg ;
- va_start (arg,format) ;
- vsprintf (buf,format,arg) ;
- main_task->debug->print (buf) ;
- }
-
- Task::Task (char *taskname, char *applname, char *spritename, char *icon_menu, int priority, int position, int wimp_version, int *message_list)
- {
- char buffer[256] ;
- _kernel_swi_regs r ;
- _kernel_osfile_block b ;
- _kernel_oserror *err ;
- char resources[256] ;
-
- #ifdef __EASY_C
- try
- #endif
- {
- init(taskname, applname, icon_menu, wimp_version, message_list) ;
-
- //
- // create icon on iconbar
- //
-
- strcpy (icon_name, spritename) ;
- IconData icon_data ;
- icon_data.indirectsprite.name = icon_name ;
- icon_data.indirectsprite.spritearea = spr_area ;
- icon_data.indirectsprite.nameisname = 1 ;
-
- iconbar_icon = new Icon (priority, position, 0, 0, 70, 76,
- (Icon::iconflags)(Icon::ISPRITE + Icon::INDIRECT + Icon::IHCENTRE + (Icon::IBTYPE * 3)),
- &icon_data) ;
- icon_handle = iconbar_icon->handle ;
- }
- #ifdef __EASY_C
- catch (TaskError t)
- {
- _kernel_oserror err ;
- err.errnum = 0 ;
- strcpy (err.errmess, t.buf) ;
- _kernel_raise_error (&err) ;
- if (t.fatal)
- exit(t.fatal) ;
- }
-
- catch (_kernel_oserror *e)
- {
- _kernel_swi_regs r ;
- r.r[0] = (int)e ;
- r.r[1] = 0 ;
- r.r[2] = (int)program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- exit (1) ;
- }
-
- catch (char *s)
- {
- _kernel_oserror err ;
- _kernel_swi_regs r ;
- err.errnum = 0 ;
- strcpy (err.errmess, lookup(s)) ;
- r.r[0] = (int)&err ;
- r.r[1] = 0 ;
- r.r[2] = (int)program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- exit (1) ;
- }
- #endif
- }
-
- //
- // create a task without an icon on the icon bar
- //
-
- Task::Task (char *taskname, char *applname, int wimp_version, int *message_list)
- {
- char buffer[256] ;
- _kernel_swi_regs r ;
- _kernel_osfile_block b ;
- _kernel_oserror *err ;
- char resources[256] ;
-
- #ifdef __EASY_C
- try
- #endif
- {
- init(taskname, applname, NULL, wimp_version, message_list) ;
- }
- #ifdef __EASY_C
- catch (TaskError t)
- {
- _kernel_oserror err ;
- err.errnum = 0 ;
- strcpy (err.errmess, t.buf) ;
- _kernel_raise_error (&err) ;
- if (t.fatal)
- exit(t.fatal) ;
- }
-
- catch (_kernel_oserror *e)
- {
- _kernel_swi_regs r ;
- r.r[0] = (int)e ;
- r.r[1] = 0 ;
- r.r[2] = (int)program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- exit (1) ;
- }
-
- catch (char *s)
- {
- _kernel_oserror err ;
- _kernel_swi_regs r ;
- err.errnum = 0 ;
- strcpy (err.errmess, lookup(s)) ;
- r.r[0] = (int)&err ;
- r.r[1] = 0 ;
- r.r[2] = (int)program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- exit (1) ;
- }
- #endif
- }
-
-
- Task::Task (char *taskname, char *applname, Icon *iconbar, char *icon_menu, int priority, int position, int wimp_version, int *message_list)
- {
- char buffer[256] ;
- _kernel_swi_regs r ;
- _kernel_osfile_block b ;
- _kernel_oserror *err ;
- char resources[256] ;
-
- #ifdef __EASY_C
- try
- #endif
- {
- init(taskname, applname, icon_menu, wimp_version, message_list) ;
- iconbar_icon = iconbar ;
- icon_handle = iconbar->handle ;
- }
- #ifdef __EASY_C
- catch (TaskError t)
- {
- _kernel_oserror err ;
- err.errnum = 0 ;
- strcpy (err.errmess, t.buf) ;
- _kernel_raise_error (&err) ;
- if (t.fatal)
- exit(t.fatal) ;
- }
-
- catch (_kernel_oserror *e)
- {
- _kernel_swi_regs r ;
- r.r[0] = (int)e ;
- r.r[1] = 0 ;
- r.r[2] = (int)program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- exit (1) ;
- }
-
- catch (char *s)
- {
- _kernel_oserror err ;
- _kernel_swi_regs r ;
- err.errnum = 0 ;
- strcpy (err.errmess, lookup(s)) ;
- r.r[0] = (int)&err ;
- r.r[1] = 0 ;
- r.r[2] = (int)program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- exit (1) ;
- }
- #endif
- }
-
- void Task::init(char *taskname, char *applname, char *iconmenu, int wimp_version, int *message_list)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- int iblock[3] ;
- int oblock[2] ;
- char buffer[256] ;
- _kernel_osfile_block b ;
- char resources[256] ;
-
- dragger = NULL ; // no dragger yet
- object_dragger = NULL ; // no dragger yet
- waiting = 0 ;
- receivers = NULL ;
- last_receiver = NULL ;
- windows = NULL ;
- last_window = NULL ;
- poll_mask = 1 ; // no null events by default
- r.r[0] = (int)iblock ;
- r.r[1] = (int)oblock ;
- iblock[0] = 4 ;
- iblock[1] = 5 ;
- iblock[2] = -1 ;
- if ((e = _kernel_swi (OS_ReadVduVariables, &r, &r)) != NULL)
- throw (e) ;
- xeigfactor = oblock[0] ;
- yeigfactor = oblock[1] ;
- open_fonts = NULL ;
- num_open_fonts = max_open_fonts = 0 ;
- control_threads = NULL ;
- deferred_deletions = NULL ;
-
- main_task = this ;
- FILE *fp ;
- sprintf (resources, "<%s$Dir>.Resources.Country", applname) ;
- if ((fp = fopen (resources, "r")) == NULL)
- #ifdef __EASY_C
- throw TaskError (1,"Unable to open resources country file %s",resources) ;
- #else
- {
- char str[256] ;
- sprintf (str,"Unable to open resources country file %s",resources) ;
- __throw (str) ;
- }
- #endif
- if (fscanf (fp,"%s",country) != 1)
- throw ("Unable to read country name") ;
- fclose (fp) ;
- program = applname ;
- application = applname ;
- //
- // read and initialise sprites
- //
-
- sprintf (buffer,"<%s$Dir>.!Sprites",applname) ;
- spr_area = (sprite_area*)1 ;
- int er = _kernel_osfile (5, buffer, &b) ;
- if (er == 1)
- {
- spr_area = (sprite_area*)new char[b.start+4] ;
- spr_area->size = b.start+4 ;
- spr_area->number = 0 ;
- spr_area->sproff = 16 ;
- spr_area->freeoff = 16 ;
- r.r[0] = 10 + 256 ;
- r.r[1] = (int)spr_area ;
- r.r[2] = (int)buffer ;
- if ((e = _kernel_swi (OS_SpriteOp, &r, &r)) != NULL)
- throw (e) ;
- }
-
- //
- // initialise the wimp task
- //
-
- r.r[0] = wimp_version ;
- r.r[1] = 'T' +
- ('A' << 8) +
- ('S' << 16) +
- ('K' << 24);
- r.r[2] = (int) taskname;
- r.r[3] = (int) message_list ;
- if ((e = _kernel_swi (Wimp_Initialise, &r, &r)) != NULL)
- throw (e) ;
- handle = r.r[1] ;
-
- //
- // read in the messages from the resources file
- //
-
- sprintf (buffer,"<%s$Dir>.Resources.%s.Messages",applname, country) ;
- messages = new MsgTrans (buffer) ;
-
-
- //
- // read in the templates
- //
- sprintf (buffer,"<%s$Dir>.Resources.%s.Templates",applname, country) ;
- templates = new Template (this,buffer) ;
-
-
- //
- // read in all the menus from the resources file
- //
-
- sprintf (buffer,"<%s$Dir>.Resources.%s.Menus",applname, country) ;
- menus = new MenuSet (this, buffer) ;
-
- if (iconmenu != NULL)
- {
- iconbar_menu = menus->find (iconmenu) ;
- if (iconbar_menu == NULL)
- throw ("No such menu") ;
- }
- else
- iconbar_menu = NULL ;
-
- if (find_template ("debug") != NULL)
- debug = new DebugWin (this) ;
- else
- debug = NULL ;
-
- // allocate the thread manager
-
- thread_manager = new ThreadManager ;
-
- // initialise the thread package
-
- thread_init(thread_manager) ;
-
-
- // trap signals to make them stop the threads
-
- signal (SIGABRT, signal_handler) ;
- signal (SIGILL, signal_handler) ;
- signal (SIGINT, signal_handler) ;
- signal (SIGSEGV, signal_handler) ;
- signal (SIGSTAK, signal_handler) ;
- signal (SIGTERM, signal_handler) ;
- }
-
-
- Task::~Task()
- {
- Window *w, *nw ;
-
- for (w = windows ; w != NULL ; w = nw)
- {
- nw = w->next ;
- delete w ;
- }
- for (int i = 0 ; i < max_open_fonts ; i++)
- if (open_fonts[i] != -1)
- close_font (open_fonts[i]) ;
- }
-
- //
- // spawn a new task, returning the task handle for it
- //
-
- int Task::spawn (char *command...)
- {
- va_list arg ;
- char buf[1024] ;
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- thread_manager->stop_threads() ;
- va_start (arg, command) ;
- vsprintf (buf, command, arg) ;
- r.r[0] = (int)buf ;
- if ((e = _kernel_swi (Wimp_StartTask, &r, &r)) != NULL)
- {
- thread_manager->resume_threads() ;
- throw (e) ;
- }
- thread_manager->resume_threads() ;
- return r.r[0] ;
- }
-
-
- //
- // add a window to the start of the task windows list
- //
-
- void Task::add_window (Window *w)
- {
- if (windows == NULL)
- windows = last_window = w ;
- else
- {
- last_window->next = w ;
- w->prev = last_window ;
- last_window = w ;
- }
- }
-
- void Task::remove_window (Window *w)
- {
- if (w->prev == NULL)
- windows = w->next ;
- else
- w->prev->next = w->next ;
- if (w->next == NULL)
- last_window = w->prev ;
- else
- w->next->prev = w->prev ;
- }
-
- //
- // remove a window and put it on the deleted queue to be really deleted (destructor called)
- // when thread finishes. The window will actually be removed from the task when the
- // destructor is called
- //
-
-
- void Task::delete_window (Window *w)
- {
- delete_deferred(w) ;
- }
-
- void Task::delete_deferred (DeferredDelete *d)
- {
- d->next = deferred_deletions ;
- deferred_deletions = d ;
- }
-
-
- Window *Task::find_window (int handle)
- {
- Window *w, *w1 ;
-
- for (w = windows ; w != NULL ; w = w->next)
- if ((w1 = w->find_window (handle)) != NULL)
- return w1 ;
-
- // no such window
- return NULL ;
- }
-
- Task::receiver *Task::find_receiver (int message, int your_ref)
- {
- receiver *r ;
- for (r = last_receiver ; r != NULL ; r = r->prev) // search backwards
- if (message == r->message && r->channel->accept (your_ref))
- return r ;
- return NULL ;
- }
-
- void Task::run()
- {
- #ifdef __EASY_C
- try
- #endif
- {
- _kernel_oserror *e ;
- _kernel_swi_regs r ;
- int buf[256/sizeof(int)] ; // event buffer
- DeferredDelete *next ;
-
- running = 1 ;
- threads_running = 0 ;
- // debug->print ("running task, poll_mask = %d",poll_mask) ;
- while (running)
- {
- r.r[0] = thread_manager->num_running_threads == 0 ? poll_mask : poll_mask & ~(1 << ENULL);
- r.r[1] = (int)buf ;
- if ((e = _kernel_swi (Wimp_Poll, &r, &r)) != NULL)
- throw (e) ;
- if (r.r[0] == EREDRAW)
- {
- Window *w ;
- w = find_window(buf[0]) ;
- if (w != NULL)
- w->redraw() ;
- continue ;
- }
- if (r.r[0] != ENULL)
- {
- last_event = (Task::events)r.r[0] ;
- memcpy (last_event_data, buf, sizeof buf) ;
- }
- if (thread_manager->num_running_threads > 0 || r.r[0] != ENULL) // any threads to run
- {
- threads_running = 1 ;
- if (r.r[0] != ENULL) // need to process event?
- {
- // if (r.r[0] != EREDRAW)
- // debug->print ("spawning control thread for event %d",r.r[0]) ;
- spawn_control_thread(r.r[0], buf) ; // process the event in a thread
- }
- thread_manager->run (5) ; // run all threads
- // if (r.r[0] != EREDRAW && r.r[0] != ENULL)
- // debug->print ("end of run, event = %d",r.r[0]) ;
- threads_running = 0 ;
- }
- while (deferred_deletions != NULL)
- {
- next = deferred_deletions->next ;
- delete deferred_deletions ; // has virtual destructor, so real object will be deleted
- deferred_deletions = next ;
- }
- }
- }
- #ifdef __EASY_C
- catch (TaskError t)
- {
- _kernel_oserror err ;
- _kernel_swi_regs r ;
- err.errnum = 0 ;
- strcpy (err.errmess, lookup(t.buf)) ;
- r.r[0] = (int)&err ;
- r.r[1] = 0 ;
- r.r[2] = (int)program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- if (t.fatal)
- exit(t.fatal) ;
- }
-
- catch (_kernel_oserror *e)
- {
- _kernel_swi_regs r ;
- r.r[0] = (int)e ;
- r.r[1] = 0 ;
- r.r[2] = (int)program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- exit (1) ;
- }
- catch (char *s)
- {
- _kernel_oserror err ;
- _kernel_swi_regs r ;
- err.errnum = 0 ;
- strcpy (err.errmess, lookup(s)) ;
- r.r[0] = (int)&err ;
- r.r[1] = 0 ;
- r.r[2] = (int)program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- exit (1) ;
- }
- #endif
- }
-
-
- void Task::send_message (events event, int action, int &task, int &my_ref, int your_ref, int data_length, void *data, int icon)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- int block [256/sizeof(int)] ;
- r.r[0] = (int)event ;
- r.r[1] = (int)block ;
- r.r[2] = task ;
- r.r[3] = icon ;
- if (data_length < 0 || data_length > (256-20))
- throw ("Illegal message length") ;
- block[0] = ((data_length + 3) & ~3) + 20 ;
- block[3] = your_ref ;
- block[4] = action ;
- memcpy (&block[5], data, data_length) ;
- if ((e = _kernel_swi (Wimp_SendMessage, &r, &r)) != NULL)
- throw (e) ;
- my_ref = block[2] ;
- }
-
- void Task::sleep (ThreadResource *thread, int pri)
- {
- thread_manager->sleep (thread,pri) ;
- }
-
- void Task::sleep (int time)
- {
- thread_manager->sleep (time) ;
- }
-
- void Task::yield ()
- {
- thread_manager->yield () ;
- }
-
-
- void Task::exit (int status)
- {
- thread_manager->exit() ;
- _kernel_swi_regs r ;
- r.r[0] = handle ;
- r.r[1] = 'T' +
- ('A' << 8) +
- ('S' << 16) +
- ('K' << 24);
- _kernel_swi (Wimp_CloseDown, &r, &r) ;
- ::exit(status) ;
- }
-
- void Task::print (char *format,...)
- {
- va_list arg ;
- _kernel_oserror err ;
- _kernel_swi_regs r ;
- err.errnum = 0 ;
- va_start (arg,format) ;
- vsprintf (err.errmess, format, arg) ;
- r.r[0] = (int)&err ;
- r.r[1] = 0 ;
- r.r[2] = (int)program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- }
-
- //
- // icon bar click
- //
-
- void Task::click (int x, int y, int buttons, int icon)
- {
- }
-
- char *Task::get_iconbar_menu(int icon)
- {
- return NULL ;
- }
-
- void Task::pre_menu(Menu *menu)
- {
- }
-
-
- void Task::menu (MenuItem items[])
- {
- }
-
-
- void Task::register_drag (Window *dragger, int id, bool dragging_sprite)
- {
- if (this->dragger != NULL)
- throw ("Already dragging") ;
- this->dragger = dragger ;
- this->dragging_sprite = dragging_sprite ;
- dragger_id = id ;
- }
-
- void Task::register_object_drag (Object *dragger, int id, bool dragging_sprite)
- {
- if (this->object_dragger != NULL)
- throw ("Already dragging an object") ;
- this->dragging_sprite = dragging_sprite ;
- this->object_dragger = dragger ;
- object_dragger_id = id ;
- }
-
-
- //
- // add a receiver to the end of the receiver queue
- //
-
- void Task::add_receiver (Channel *channel, int message)
- {
- receiver *r ;
- r = new receiver (channel, message) ;
- if (receivers == NULL)
- receivers = last_receiver = r ;
- else
- {
- last_receiver->next = r ;
- r->prev = last_receiver ;
- last_receiver = r ;
- }
- }
-
- void Task::remove_receiver (Channel *channel, int message)
- {
- for (receiver *r = receivers ; r != NULL ; r = r->next)
- if (r->channel == channel && r->message == message)
- {
- if (r->prev == NULL)
- receivers = r->next ;
- else
- r->prev->next = r->next ;
- if (r->next == NULL)
- last_receiver = r->prev ;
- else
- r->next->prev = r->prev ;
- delete r ;
- }
- }
-
- int Task::open_font (char *name, int xsize, int ysize)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- r.r[1] = (int)name ;
- r.r[2] = xsize * 16 ;
- r.r[3] = ysize * 16 ;
- r.r[4] = 0 ;
- r.r[5] = 0 ;
- if ((e = _kernel_swi (Font_FindFont, &r, &r)) != NULL)
- throw (e) ;
- int font_handle = r.r[0] ;
- if (num_open_fonts == max_open_fonts)
- {
- if (open_fonts == NULL)
- open_fonts = (int*)malloc (sizeof (int) * 10) ;
- else
- open_fonts = (int*)realloc (open_fonts, (max_open_fonts + 10) * sizeof (int)) ;
- if (open_fonts == NULL)
- throw ("Out of memory") ;
- for (int i = 0 ; i < 10 ; i++)
- open_fonts[max_open_fonts+i] = -1 ;
- max_open_fonts += 10 ;
- }
- for (int i = 0 ; i < max_open_fonts ; i++)
- if (open_fonts[i] == -1)
- {
- open_fonts[i] = font_handle ;
- num_open_fonts++ ;
- break ;
- }
- return font_handle ;
- }
-
- void Task::close_font (int handle)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- r.r[0] = handle ;
- if ((e = _kernel_swi (Font_LoseFont, &r, &r)) != NULL)
- throw (e) ;
- for (int i = 0 ; i < max_open_fonts ; i++)
- if (open_fonts[i] == handle)
- {
- open_fonts[i] = -1 ;
- num_open_fonts-- ;
- return ;
- }
- throw ("Font handle not found in task memory") ;
- }
-
- //
- // spawn a new control thread
- //
-
- void Task::spawn_control_thread(int event, int *buf)
- {
- ControlThread *t ;
- t = new ControlThread (this, event, buf) ;
- if (event == EREDRAW || event == ESENDWANTACK) // redraw request?
- t->setpriority(40) ;
- else
- t->setpriority(60) ;
- t->start() ;
- }
-
-
-
- void Task::enter_critical()
- {
- thread_disable_ints() ;
- }
-
- void Task::exit_critical()
- {
- thread_enable_ints() ;
- }
-
- void *Task::find_sprite (char *name)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- if ((e = _kernel_swi (Wimp_BaseOfSprites, &r, &r)) != NULL)
- throw (e) ;
- int ram = r.r[1] ;
- int p ;
- int num_sprites ;
- int i ;
- p = ram + *((int*)(ram + 8)) ; // get address of first sprite
- num_sprites = ram + *((int*)(ram + 4)) ;
- for (i = 0 ; i < num_sprites ; i++)
- {
- if (strncmp ((char*)(p + 4), name, 12) == 0)
- return (void*)p ;
- p += *(int*)p ;
- }
- return NULL ;
- }
-
-
- void Task::poll_word_non_zero (int *poll_word, int contents)
- {
- }
-
- void Task::set_menu (Menu *menu, Icon *icon)
- {
- current_menu = menu ;
- current_menu_icon = icon ;
- }
-
- void Task::set_menu (Menu *menu, Object *object)
- {
- current_menu = menu ;
- current_menu_object = object ;
- }
-
- void Task::set_menu (Menu *menu, Window *window)
- {
- current_menu = menu ;
- current_menu_window = window ;
- }
-
- char *Task::help (int mx, int my, int buttons, int window, int icon)
- {
- return NULL ;
- }
-
- void Task::show_threads()
- {
- thread_manager->show_threads() ;
- }
- //
- // TaskError class. Used to carry exceptions to a catch handler for errors
- //
-
-
- TaskError::TaskError (int f, char *format...)
- {
- va_list arg ;
- va_start (arg,format) ;
- vsprintf (buf, format, arg) ;
- fatal = f ;
- }
-
- void print (char *format,...)
- {
- va_list arg ;
- _kernel_oserror err ;
- _kernel_swi_regs r ;
- err.errnum = 0 ;
- va_start (arg,format) ;
- vsprintf (err.errmess, format, arg) ;
- r.r[0] = (int)&err ;
- r.r[1] = 0 ;
- r.r[2] = (int)"Wimp Program" ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- }
-
- #ifndef __EASY_C
-
- // this is defined because of a 'sorry not implemented' error from cfront.
-
- char *Task::lookup (char *token)
- {
- char *s ;
- if ((s = messages->lookup(token)) != NULL)
- return s ;
- return token ;
- }
-
-
- void __throw (_kernel_oserror *e)
- {
- _kernel_swi_regs r ;
- r.r[0] = (int)e ;
- r.r[1] = 0 ;
- r.r[2] = (int)main_task->program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- main_task->exit(1) ;
- }
-
- void __throw (char *s)
- {
- _kernel_oserror err ;
- _kernel_swi_regs r ;
- err.errnum = 0 ;
- strcpy (err.errmess, s) ;
- r.r[0] = (int)&err ;
- r.r[1] = 0 ;
- r.r[2] = (int)main_task->program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- main_task->exit (1) ;
- }
-
- void werr (int fatal, char *format...)
- {
- _kernel_oserror err ;
- _kernel_swi_regs r ;
- va_list arg ;
- va_start (arg, format) ;
- vsprintf (err.errmess,format,arg) ;
- err.errnum = 0 ;
- r.r[0] = (int)&err ;
- r.r[1] = 0 ;
- r.r[2] = (int)main_task->program ;
- _kernel_swi (Wimp_ReportError, &r, &r) ;
- if (fatal)
- main_task->exit (1) ;
- }
-
- #endif
-