/* REMIND.C Written by DavidW Started on 6/12/91 Resource file version 1/11/92 */ #include /* basic Psion header file */ #include /* defines object oriented functions */ #include /* defines E_GEN_ error values, etc */ #include /* defines E_FILE_ error values, etc */ #include /* defines date and time functions */ #include /* defines C_RSCFILE and related constants */ #include /* defines all Window Server library functions */ #include /* defines all Hwif Library functions */ #include "remind.rh" /* definitions common to remind.rss & remind.c */ #include "remind.rsg" /* GENERATED resource file header */ GLREF_D VOID *DatCommandPtr; /* where run from */ GLDEF_D TEXT ** _cmds; /* for menu commands */ GLDEF_D H_MENU_DATA * _mdata; /* for menu titles */ LOCAL_C VOID *rcb; /* resource file object handle */ LOCAL_D UINT MainWid; /* ID of main window */ typedef struct { ULONG sdate; /* date when reminder due */ UBYTE ref; /* TRUE iff this is the reminder queued to ALM: */ UBYTE tlen; /* length of text message */ TEXT *pb; /* the text message itself (another alloc cell) */ } ENTRY; /* represents one reminder */ LOCAL_D ENTRY table[500]; /* handle up to 500 reminders */ LOCAL_D UWORD nent=0; /* number of entries */ LOCAL_D INT cent=0; /* entry at cursor */ LOCAL_D INT tent=0; /* entry at top of screen */ LOCAL_D ENTRY clipent; /* entry in clipboard */ LOCAL_D UWORD show_statwin=FALSE; /* is Status Window showing */ LOCAL_D UWORD ScreenWidth; /* width of remaining screen */ LOCAL_D UWORD lastbflags=W_BORD_CORNER_4; /* which kind of Border flags */ LOCAL_D VOID *ttH; /* handle of Time Text object */ LOCAL_D VOID *aH; /* handle of channel to ALM: alarm device */ LOCAL_D WORD almstat; /* status word for ALM: services */ LOCAL_D WORD almactive; /* active word for ALM: services */ LOCAL_D UWORD PrintRec; /* which entry is being printed */ LOCAL_D UWORD PrintState; /* which part of entry is being printed */ LOCAL_D TEXT PrintBuf[48]; /* holds text about to be printed */ LOCAL_C VOID LoadStr(INT rid,TEXT *pb) { /* load resource into given buffer (assumed long enough) */ while (p_entersend4(rcb,O_RS_READ_BUF,rid,pb)<0) hRequestReplacePack(rcb,DatCommandPtr); } LOCAL_C TEXT *str(INT rid) { /* load specified resource into scratch buffer and return address */ LOCAL_D TEXT scratch[50]; /* static "scratch" buffer */ LoadStr(rid,&scratch[0]); return(&scratch[0]); } LOCAL_C INT cmp(INT r,VOID *pent) { /* comparison function used in binary searching */ return(table[r].sdate>(*(ULONG *)pent)? -1: 1); } LOCAL_C INT LocateEntry(ULONG *psdate) { /* find entry at (or nearest after) given date */ INT dir; /* direction to nearest hit (as given by p_bsrch) */ INT ret; /* nearest hit (as given by p_bsrch) */ dir=p_bsrch(nent,cmp,&ret,psdate); if (dir>0) ret++; return(ret); } LOCAL_C ENTRY *LocateRef(VOID) { /* find the entry that was queued to ALM: */ ENTRY *pent; pent=(&table[0]); while (!pent->ref) pent++; return(pent); } LOCAL_C VOID RequeueAlarm(VOID) { /* recalculate the next alarm due, and queue it (if any) */ ULONG sdate; /* current time and date */ INT entno; /* no of entry to queue */ ENTRY *pent; /* entry to queue */ ULONG times[2]; /* needed for service to ALM: */ TEXT buf[66]; /* needed for service to ALM: */ if (almactive) { /* cancel any alarm currently queued */ p_iow2(aH,P_FCANCEL); p_waitstat(&almstat); almactive=FALSE; LocateRef()->ref=FALSE; } if (!nent) return; /* no entries hence none to queue */ sdate=p_date(); entno=LocateEntry(&sdate); if (entno>=nent) return; /* no entries with dates in the future */ pent=(&table[entno]); *p_bcpy(&buf[0],pent->pb,pent->tlen)=0; /* copy the text */ pent->ref=TRUE; /* mark this entry as the one queued */ times[0]=pent->sdate; /* fill in the time the alarm is due */ times[1]=pent->sdate; /* and the time to DISPLAY */ p_ioc5(aH,P_FWRITE,&almstat,×,&buf); almactive=TRUE; /* set active word TRUE */ } LOCAL_C VOID UpdateTimeFormat(VOID) { /* Update time-text object's record of time format */ hTTSetFormat(ttH,H_TIME_FORMAT_NO_SECONDS|H_TIME_FORMAT_SUFFIX| H_TIME_FORMAT_DAY_NAME|H_TIME_FORMAT_MONTH_NAME); } LOCAL_C INT SdateToBuf(TEXT *pb,ULONG *psdate) { /* convert time and date to text, as per system preferences */ hTTSetTime(ttH,H_TIME_SET_SDATE,psdate); return(hTTSenseString(ttH,H_TIME_SENSE_BOTH,pb)); } LOCAL_C VOID SetGmode(INT gmode) { /* set Gmode of current graphics context */ G_GC gc; gc.gmode=gmode; gSetGC(0,G_GC_MASK_GMODE,&gc); } LOCAL_C VOID SetBold(INT flag) { /* prepare to print in bold (if flag TRUE) or non-bold */ G_GC gc; gc.font=WS_FONT_BASE+flag; gSetGC(0,G_GC_MASK_FONT,&gc); } LOCAL_C VOID GetCursorBox(INT i,P_RECT *pbox) { /* where should the cursor be drawn */ pbox->tl.x=4; pbox->br.x=10; pbox->tl.y=4+i*18; pbox->br.y=pbox->tl.y+9; } LOCAL_C VOID DrawCursor(INT i) { /* draw the cursor (character octal 34) */ P_RECT box; GetCursorBox(i,&box); gPrintBoxText(&box,8,G_TEXT_ALIGN_LEFT,0,"\034",1); } LOCAL_C VOID EraseCursor(INT i) { /* remove the cursor (from the specified row) */ P_RECT box; GetCursorBox(i,&box); gClrRect(&box,G_TRMODE_CLR); /* clear all pixels in the rectangle */ } LOCAL_C VOID LineToScreen(INT y,INT xoff,TEXT *pb,INT tlen) { /* print the given line of text on the screen */ P_RECT box; box.tl.x=4; box.tl.y=4+y*9; box.br.x=ScreenWidth-4; box.br.y=box.tl.y+9; gPrintBoxText(&box,8,G_TEXT_ALIGN_LEFT,xoff,pb,tlen); } LOCAL_C VOID ClearLine(INT y) { /* clear all text from the given line */ LineToScreen(y,0,NULL,0); } LOCAL_C VOID DrawLine(INT i) { /* draw the two lines of text for the specified entry */ INT len; INT entno; ENTRY *pent; TEXT buf[48]; entno=i+tent; /* offset by no. of first on-screen entry */ if (entno>=nent) { /* no entry for this position - hence clear */ ClearLine(i*2); ClearLine(i*2+1); } else { pent=(&table[entno]); SetBold(TRUE); /* draw the date and time in bold */ len=SdateToBuf(&buf[0],&pent->sdate); LineToScreen(i*2,10,&buf[0],len); SetBold(FALSE); /* draw the text (and any cursor) in non-bold */ if (entno==cent) DrawCursor(i); LineToScreen(i*2+1,22,pent->pb,pent->tlen); } } LOCAL_C VOID Display(VOID) { /* draw all four entry slots on the screen */ INT i; if (!nent) { /* no entries set - so display text to this effect */ SetBold(TRUE); LineToScreen(0,10,str(STR_NO_REMINDERS_SET),16); ClearLine(1); /* clear the line under the message */ return; } for (i=0; i<4; i++) DrawLine(i); } LOCAL_C INT ResizeWidth(UWORD width) { /* try to change the width of the main display region */ INT ret; W_WINDATA wd; wd.extent.tl.x=wd.extent.tl.y=0; wd.extent.width=width; wd.extent.height=80; wSetWindow(MainWid,W_WIN_EXTENT,&wd); ret=uErrorValue(wCheckPoint()); /* check whether successful */ if (!ret) ScreenWidth=width; /* only record new value if successful */ return(ret); } LOCAL_C INT ToggleStatusWindow(VOID) { /* attempt to toggle the visibility of the status window */ if (show_statwin) { /* status window is currently showing */ if (ResizeWidth(240)) return(-1); wsDisable(); /* remove status window */ } else { /* status window not currently showing */ if (ResizeWidth(189)) return(-1); wsEnable(); /* display status window */ } show_statwin^=TRUE; gBorder(lastbflags); /* redraw the border */ Display(); /* redraw the main display */ return(0); } LOCAL_C VOID EnsureGoodTent(VOID) { /* find good value for tent - top entry on screen */ if (nent<5) tent=0; /* show ALL entries if less than five in total */ else if (tentcent) tent=cent; /* cursor was off top of screen */ } LOCAL_C VOID AppendEntry(ENTRY *pent) { /* add the given entry */ INT tomove; if (!nent) cent=0; else { /* find where to insert the entry */ cent=LocateEntry(&pent->sdate); /* uses binary search */ tomove=nent-cent; /* how many entries to "move along */ p_bcpy(&table[cent+1],&table[cent],tomove*sizeof(ENTRY)); } nent++; /* increment count of number of entries */ table[cent]=(*pent); /* copy the entry details into the table */ EnsureGoodTent(); /* check whether need to scroll */ Display(); /* redraw the main display */ RequeueAlarm(); /* ensure correct alarm is queued */ } LOCAL_C VOID DoDeleteEntry(VOID) { /* delete the current entry */ INT tomove; /* how many records to "move back" */ p_free(table[cent].pb); /* free alloc cell holding the text */ nent--; /* decrement total count of entries */ tomove=nent-cent; /* now fill up the gap in the table */ p_bcpy(&table[cent],&table[cent+1],tomove*sizeof(ENTRY)); } LOCAL_C VOID CleanEntry(ENTRY *pent) { /* prepare a blank entry */ p_bfil(pent,sizeof(ENTRY),0); pent->sdate=p_date()+3600; /* seed to one hour in the future */ } LOCAL_C INT EditEntry(ENTRY *pent) { /* allow the user to edit an entry */ P_DAYSEC ds; H_DI_DATE date; H_DI_TIME time; TEXT buf[66]; H_DI_SEDIT sed; if (uOpenDialog(str(STR_REMINDER))) /* title line of dialog */ return(-1); p_bcpy(&buf[1],pent->pb,buf[0]=pent->tlen); sed.str=(&buf[0]); /* prepare to edit the text of the reminder */ sed.len=64; /* maximum allowed length */ sed.width=25; /* width of "viewing" region */ if (uAddDialogItem(H_DIALOG_SEDIT,str(STR_MESSAGE),&sed)) return(-1); p_sttods(&pent->sdate,&ds); /* crack into "time" and "date" */ time.value=(&ds.sec); /* prepare to edit the time of the reminder */ time.low=0; time.high=P_NSECDAY-1; time.type=0; if (uAddDialogItem(H_DIALOG_TIME,str(STR_TIME),&time)) return(-1); date.value=(&ds.day); /* prepare to edit the date of the reminder */ date.low=H_FIRST_SYS_DAY; date.high=H_LAST_SYS_DAY; if (uAddDialogItem(H_DIALOG_DATE,str(STR_DATE),&date)) return(-1); if (uRunDialog()<=0) return(-1); /* user cancelled (or insufficient memory) */ p_dstost(&ds,&pent->sdate); /* reconstitute system time */ pent->pb=p_realloc(pent->pb,buf[0]); /* check text alloc cell length */ if (!pent->pb) { /* no memory left to grow the text alloc cell */ uErrorValue(E_GEN_NOMEMORY); return(-1); } pent->tlen=buf[0]; p_bcpy(pent->pb,&buf[1],buf[0]); return(0); /* signal successful edit */ } LOCAL_C VOID AddEntry(VOID) { /* the user wants to add an entry */ ENTRY ent; CleanEntry(&ent); /* prepare a "clean" initial starting point */ if (EditEntry(&ent)) /* allow the user to edit it */ return; AppendEntry(&ent); /* insert the entry */ } LOCAL_C VOID InfoMsg(INT rid) { /* present info message with text with given resource id */ wInfoMsg(str(rid)); } LOCAL_C VOID UpdateEntry(VOID) { /* the user wants to update the current entry */ ENTRY *pent; ENTRY ent; if (!nent) { /* no current entry to update */ InfoMsg(STR_NO_ENTRY_UPDATE); return; } pent=(&table[cent]); /* find the current entry */ if (EditEntry(pent)) /* allow the user to edit it */ return; ent=(*pent); pent->pb=0; DoDeleteEntry(); /* delete the existing entry... */ AppendEntry(&ent); /* ... and re-insert it with the new contents */ } LOCAL_C VOID DeleteEntry(VOID) { /* the user wants to delete the current entry */ TEXT ny[4]; /* for the characters 'n' then 'y' */ TEXT yes[10]; /* for the string "yes" */ TEXT no[10]; /* for the string "no" */ if (!nent) { /* no entry to delete */ InfoMsg(STR_NO_ENTRY_DELETE); return; } if (uOpenDialog(str(STR_DELETE_REMINDER))) /* title of dialog */ return; LoadStr(STR_NY,&ny[0]); /* find the text for the existing language */ LoadStr(STR_NO,&no[0]); LoadStr(STR_YES,&yes[0]); if (uAddButtonList(&no[0],-ny[0],&yes[0],ny[1],NULL)) /* no-yes buttons */ return; if (uRunDialog()!=ny[1]) /* check if user pressed 'y' button */ return; DoDeleteEntry(); /* delete the entry */ if (cent==nent && nent) /* change the cursor position */ cent=nent-1; EnsureGoodTent(); /* check whether need to scroll display */ Display(); /* redraw main display area */ RequeueAlarm(); /* recalculate which alarm to queue */ } LOCAL_C INT TakeCopy(ENTRY *targ,ENTRY *src) { /* copy specified entry */ targ->pb=p_alloc(src->tlen); /* prepare an alloc cell for the text */ if (!targ->pb) { uErrorValue(E_GEN_NOMEMORY); return(-1); } p_bcpy(targ->pb,src->pb,src->tlen); /* copy the text */ p_bcpy(targ,src,sizeof(ENTRY)-sizeof(TEXT *)); /* copy everything else */ return(0); } LOCAL_C VOID CopyEntry(VOID) { /* the user wants to copy the current entry */ ENTRY new; if (!nent) { /* no current entry to copy */ InfoMsg(STR_NO_ENTRY_COPY); return; } if (TakeCopy(&new,&table[cent])) return; /* no memory to make copy */ p_free(clipent.pb); /* free any existing clipboard text */ clipent=new; InfoMsg(STR_REMINDER_COPIED); /* signal success to user */ } LOCAL_C VOID InsertEntry(VOID) { /* the user wants to insert the clipboard contents */ ENTRY new; if (!clipent.pb) { /* the clipboard contents are empty */ InfoMsg(STR_NO_ENTRY_INSERT); return; } if (TakeCopy(&new,&clipent)) return; /* no memory for new entry */ AppendEntry(&new); /* insert the entry */ } LOCAL_C VOID ExitIfConfirmed(VOID) { /* the user wants to exit - request confirmation */ H_DI_TEXT txt; TEXT cancel[10]; /* for the text "cancel" */ TEXT exit[10]; /* for the text "exit" */ if (nent) { /* only need confirmation if there are entries */ if (uOpenDialog(str(STR_WARNING))) /* dialog title */ return; txt.str=str(LSTR_DELETE_ALL); /* lbc text from resource file */ txt.type=H_DTEXT_ALIGN_CENTRE; /* centre alignment */ if (uAddDialogItem(H_DIALOG_TEXT,0,&txt)) return; LoadStr(STR_CANCEL,&cancel[0]); /* load correct language text */ LoadStr(STR_EXIT,&exit[0]); if (uAddButtonList(&cancel[0],W_KEY_ESCAPE, &exit[0],W_KEY_RETURN,NULL)) return; if (uRunDialog()!=W_KEY_RETURN) return; /* the user failed to confirm */ } p_exit(0); /* exit cleanly */ } LOCAL_C INT PrintLine(H_PRINT *pr) { /* print next line of data */ ENTRY *pent; pent=(&table[PrintRec]); /* which entry to print */ switch (PrintState++) { case 0: /* need to print the date and time */ pr->blen=SdateToBuf(&PrintBuf[0],&pent->sdate); pr->buf=(&PrintBuf[0]); pr->style|=H_PRINT_STY_BOLD; /* print date and time in bold */ break; case 1: /* need to print the text */ pr->buf=pent->pb; pr->blen=pent->tlen; break; case 2: /* gap between entries */ pr->blen=0; PrintState=0; PrintRec++; return(PrintRec!=nent); /* return FALSE if no more to print */ } pr->flags|=H_PRINT_KEEP;/* keep different parts of entry on same page */ return(TRUE); /* return TRUE since printing not yet finished */ } LOCAL_C VOID PrintAll(VOID) { /* the user wants to print the reminders */ if (!nent) { /* no entries to print */ InfoMsg(STR_NOTHING_PRINT); return; } PrintRec=0; /* initialise print state variables */ PrintState=0; hPrint(PrintLine); /* specify call-back function */ } LOCAL_C VOID ManageCommand(INT index) { /* switch on command index to appropriate function */ switch (index) { case ITEMS_BEFORE_EDIT: InsertEntry(); break; case ITEMS_BEFORE_EDIT+1: CopyEntry(); break; case ITEMS_BEFORE_EDIT+2: UpdateEntry(); break; case ITEMS_BEFORE_EDIT+3: AddEntry(); break; case ITEMS_BEFORE_EDIT+4: DeleteEntry(); break; case ITEMS_BEFORE_SPECIAL: PrintAll(); break; case ITEMS_BEFORE_SPECIAL+1: hPrintSetupDialog(); break; case ITEMS_BEFORE_SPECIAL+2: ExitIfConfirmed(); break; } } LOCAL_C VOID TryExecuteCommand(INT keycode) { /* try to find command to execute matching accelerator passed */ keycode=uLocateCommand(keycode); /* look up accelerator table */ if (keycode>=0) /* found - keycode converted to index */ ManageCommand(keycode); } LOCAL_C VOID DoScroll(INT dely) { /* scroll the display vertically by given amount */ P_POINT offset; /* offset to scroll */ P_RECT src; /* source region for scroll */ offset.x=0; offset.y=dely*18; /* each entry is two lines each 9 pixels high */ src.tl.x=4; src.br.x=ScreenWidth-4; if (dely>0) { /* scrolling down - so exclude bottom from source */ src.tl.y=4; src.br.y=4+(4-dely)*18; } else { /* scrolling up - so exclude top from source */ src.tl.y=4-dely*18; src.br.y=4+4*18; } wScrollRect(MainWid,&src,&offset); } LOCAL_C VOID MakeHighlight(INT newcent) { /* change the cursor position as specified, with smooth scrolling */ INT toscroll; /* amount of scroll needed (if any) */ if (!nent) return; /* no entries - hence nothing to do */ if (newcent==cent) return; /* cursor already at specified position */ EraseCursor(cent-tent); /* remove existing cursor */ toscroll=tent-newcent; if (toscroll>0) { /* new cursor position off top of screen */ tent-=toscroll; /* adjust record of entry at top of screen */ if (toscroll<4) DoScroll(toscroll); /* only actually scroll if less than 4 */ else toscroll=4; /* toscroll now holds number of lines to redraw */ while (toscroll) DrawLine(--toscroll); /* redraw lines not scrolled */ } else { toscroll=-3-toscroll; if (toscroll>0) { /* new cursor position off bottom of screen */ tent+=toscroll; /* adjust record of entry at top of screen */ if (toscroll<4) DoScroll(-toscroll); else toscroll=4; while (toscroll) DrawLine(4-toscroll--); /* redraw lines not scrolled */ } } cent=newcent; DrawCursor(cent-tent); /* draw the cursor back in */ } LOCAL_C VOID ScrollPageBy(INT delta) { /* implementation of PgUp / PgDn */ if (!nent) return; /* no entries to display */ if (delta<(-3)) delta=(-3); /* scroll at most three records */ else if (delta>3) delta=3; tent+=delta; cent+=delta; Display(); } LOCAL_C VOID HandleAlarmEvent(VOID) { /* an alarm has expired (or time has been put back) */ ENTRY *pent; /* the alarm that was queued */ INT expired; /* whether alarm really did expire */ pent=LocateRef(); expired=(pent->sdate<=p_date()); /* find if alarm time has elapsed */ almactive=FALSE; pent->ref=FALSE; RequeueAlarm(); /* find which is next alarm to queue */ if (expired) { uForceToFront(); /* come into foreground */ MakeHighlight(pent-(&table[0])); /* highlight the elapsed alarm */ UpdateEntry(); /* allow user to edit the reminder */ } } LOCAL_C VOID CheckBorderArrows(VOID) { /* see if border needs redisplaying (on account of "scroll arrows") */ INT bflags; /* the flags that ought to be displayed */ if (!nent) return; /* no entries */ if (tent) /* check if more entries off screen top */ bflags=W_BORD_CORNER_4|W_BORD_TOP_ON; else bflags=W_BORD_CORNER_4|W_BORD_TOP_OFF; if (tent+40) TryExecuteCommand(ret); } break; case W_KEY_DELETE_LEFT: DeleteEntry(); /* user wants to delete entry */ break; case W_KEY_RETURN: if (!nent || key.modifiers&W_SHIFT_MODIFIER) AddEntry(); /* user wants to add entry */ else UpdateEntry(); /* user wants to update entry */ break; case W_KEY_UP: if (cent) MakeHighlight(cent-1); break; case W_KEY_DOWN: if (cent=nent) MakeHighlight(nent-1); else ScrollPageBy(nent-tent-4); break; } } } } LOCAL_C VOID CreateGC(VOID) { /* attempt to create default graphics context on main window */ INT hgc; /* graphics context handle (if successful) */ hgc=gCreateGC0(MainWid); if (hgc<0) p_exit(hgc); } LOCAL_C VOID *InitRcb(VOID) { /* create and initialise resource file object */ INT ret; VOID *rcb; /* resource file object handle */ rcb=p_new(1,C_RSCFILE); ret=p_entersend3(rcb,O_RS_INIT,DatCommandPtr); /* pass file name */ if (ret<0) /* no resource file found */ p_exit(ret); /* fatal (programmer) error */ return(rcb); } LOCAL_C H_MENU_DATA *LoadMenuTitles(VOID *rcb,INT rid) { /* load menu titles from specified resource file */ H_MENU_DATA *pmdata,*pi; /* for created alloc cell */ TEXT *titles; /* for loaded alloc cell */ WORD count; /* how many menus */ INT ret; ret=p_entersend4(rcb,O_RS_READ,rid,&titles); if (ret<0) return(NULL); /* couldn't access resource file */ count=(*(WORD *)titles); /* first WORD gives count of menus */ pmdata=p_alloc((count+1)*sizeof(H_MENU_DATA)); if (!pmdata) { /* no memory to alloc H_MENU_DATA array */ p_free(titles); /* clean up partially constructed data */ return(NULL); } pi=pmdata; /* prepare to walk through H_MENU_DATA array */ titles+=2; /* skip over leading WORD count */ while (count--) /* for each menu */ { pi->title=titles; /* store pointer to title text */ titles+=p_slen(titles)+1; /* skip the text and terminating zero */ pi->nlines=(*titles++); /* store the number of lines */ pi++; /* increment to next H_MENU_DATA element */ } pi->title=0; /* place NULL at end of array */ return(pmdata); /* return pointer to created struct */ } LOCAL_C TEXT **LoadMenuCommands(VOID *rcb,INT rid) { /* load menu commands from specified resource file */ TEXT **pcmds,**pi; /* for created alloc cell */ TEXT *cmds; /* for loaded alloc cell */ WORD count; /* how many commands */ INT ret; ret=p_entersend4(rcb,O_RS_READ,rid,&cmds); if (ret<0) return(NULL); /* couldn't access resource file */ count=(*(WORD *)cmds); /* first WORD gives count of commands */ pcmds=p_alloc((count+1)*sizeof(TEXT *)); if (!pcmds) { /* no memory to allow TEXT * array */ p_free(cmds); /* clean up partially constructed data */ return(NULL); } pi=pcmds; /* prepare to walk through TEXT * array */ cmds+=2; /* skip over leading WORD count */ while (count--) /* for each menu command */ { *pi++=cmds; /* store pointer to command details */ cmds+=p_slen(cmds)+1; /* skip the text and terminating zero */ } *pi=0; /* place NULL at end of array */ return(pcmds); /* return pointer to created struct */ } LOCAL_C VOID LoadMenus(VOID) { /* load all menu data */ rcb=InitRcb(); /* create and initialise resource file object */ _cmds=LoadMenuCommands(rcb,REMIND_CMDS); /* load commands */ _mdata=LoadMenuTitles(rcb,REMIND_MENUS); /* load menu titles */ if (!_cmds || !_mdata) /* test if either load failed */ p_exit(E_GEN_START); /* report fatal initialisation error */ } LOCAL_C VOID SpecificInit(VOID) { /* application initialisation specific to Remind */ uEscape(FALSE); /* disable Psion-Esc */ LoadMenus(); /* load all menu data */ MainWid=uFindMainWid(); /* find id of main display window */ CreateGC(); /* create default graphics context */ p_open(&aH,"ALM:",-1); /* open channel to ALM: device */ ttH=hTTOpen(); /* open channel to time-text object */ hTTSetAbbreviations(ttH,3,3); /* set abbreviations to use */ UpdateTimeFormat(); /* check current system time format */ hCrackCommandLine(); /* crack incoming command line */ if (ToggleStatusWindow()) /* attempt to display status window */ p_exit(0); } GLDEF_C VOID main(VOID) { /* the main() for all Hwif programs */ uCommonInit(); /* initialisation common to all Hwif programs */ SpecificInit(); /* initialisation specific to Remind */ MainLoop(); /* the central event processing loop */ }