Files
sibo-playground/code/SIBOSDK/hwdemo/remind.c
2026-07-06 18:01:36 +01:00

876 lines
31 KiB
C

/*
REMIND.C
Written by DavidW
Started on 6/12/91
Resource file version 1/11/92
*/
#include <p_std.h> /* basic Psion header file */
#include <p_object.h> /* defines object oriented functions */
#include <p_gen.h> /* defines E_GEN_ error values, etc */
#include <p_file.h> /* defines E_FILE_ error values, etc */
#include <p_date.h> /* defines date and time functions */
#include <rscfile.xg> /* defines C_RSCFILE and related constants */
#include <wlib.h> /* defines all Window Server library functions */
#include <hwif.h> /* 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,&times,&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 (tent<cent-3)
tent=cent-3; /* cursor was off bottom of screen */
else if (tent>cent)
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+4<nent) /* check if more entries off screen bottom */
bflags|=W_BORD_BOT_ON;
else
bflags|=W_BORD_BOT_OFF;
if (bflags!=lastbflags) /* check if border needs to be redrawn */
gBorder(lastbflags=bflags);
}
LOCAL_C VOID MainLoop(VOID)
{ /* central event processing loop */
INT ret;
WMSG_KEY key; /* to receive keypress */
WORD keystat; /* status word for keypress */
WORD keyactive; /* active word for keypress */
keyactive=FALSE; /* no keyboard read queued */
FOREVER
{
CheckBorderArrows(); /* update border arrow display if changed */
if (keyactive)
wFlush(); /* flush Window Server function buffer */
else
{ /* queue a read for another keypress */
uGetKeyA(&keystat,&key);
keyactive=TRUE;
}
p_iowait(); /* wait for event */
if (keystat==E_FILE_PENDING)
{ /* alarm event must have occurred */
HandleAlarmEvent();
continue;
}
keyactive=FALSE; /* keypress must have been received */
if (key.keycode&W_EVENT_KEY)
{
if (key.keycode==CONS_EVENT_FOREGROUND)
{ /* check whether system time format changed */
UpdateTimeFormat();
Display();
}
}
else if (key.keycode&W_SPECIAL_KEY) /* Psion key pressed */
TryExecuteCommand(key.keycode&(~W_SPECIAL_KEY));
else
{
switch (key.keycode)
{
case W_KEY_MENU:
if (key.modifiers&W_CTRL_MODIFIER)
{ /* toggle status window visibility */
SetGmode(G_TRMODE_CLR);
gBorder(lastbflags&~(W_BORD_TOP_OFF|W_BORD_BOT_OFF));
SetGmode(G_TRMODE_SET);
ToggleStatusWindow();
}
else
{ /* display menu bar */
ret=uPresentMenus();
if (ret>0)
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-1)
MakeHighlight(cent+1);
break;
case W_KEY_PAGE_UP:
if (key.modifiers&W_CTRL_MODIFIER)
MakeHighlight(0);
else if (!tent)
MakeHighlight(0);
else
ScrollPageBy(-tent);
break;
case W_KEY_PAGE_DOWN:
if (key.modifiers&W_CTRL_MODIFIER)
MakeHighlight(nent-1);
else if (tent+4>=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 */
}