Sample Event Loop
/* Sample C Code of a Database Event Loop */
/* NOTE: The following code is not complete and provided for purposes of learning about the event loop. For experimentation, and as a typing aid, this portion of this file appears in
\SOURCE as DBEVENT.C */
/****************************************************************************
*************************************************************************
***************************************************************************
***************************************************************************/
/*****************************************************************************
******************************************************************************
*
* Global Data
*
****************************************************************************** ******************************************************************************
/
EVENT app_event; /* System manager event struct */
LHAPIBLOCK CapData; /* LHAPI application data block */
/*----------------------------------------------------------------------
* far ptrs to be managed by sysmgr in event that memory moves. They must
* be registered with the sysmgr during initialization. The first
* MAX_CARD_WNDS are used to handle local titles for card windows, while the
* remainder are for database engine, note, multiline edit in general filter,
* and other miscellaneous uses that involve allocating memory block.
*----------------------------------------------------------------------*/
char far *CardWndTitlePtrs[MAX_CARD_WNDS + 27]; /* sysmgr farptrs */
/*----------------------------------------------------------------------
* Multitudinous other data declarations specific to your program would
* normally appear here, but are excluded from this example.
*----------------------------------------------------------------------*/
/***************************************************************************** ******************************************************************************
*
* Main entry point and event loop.
*
* Main contains init calls, event loop, error check, and uninit calls.
* This event loop is the ONLY one in the entire application.
* ****************************************************************************** *****************************************************************************/
void main(int argc, char *argv[])
{
*/
Initialize();
/*-----------------------------------------------------------
* loop repeatedly for events until Done goes TRUE.
*-----------------------------------------------------------*/
eventloopstart:
while (!IndexBlock.Done) {
/*----------------------------------------------------------------------
* if there is stuff that could be lost from buffered disk i/o, send it
* on through before asking for keystroke.
*----------------------------------------------------------------------*/
if (Db.flags & DB_SHOULDFLUSH) { /* protect against warmstart */
if (DB_FlushFile(&Db) == DB_CLOSE)
SetError(ERR_WRITE);
}
/*----------------------------------------------------------------------
* Create error dlg if any errors reported during last event (or init).
* if db is closed and nofilewnd (DummyWnd) has not yet been launched,
* do it before creating error dlg. If no errors, cruise on by.
*----------------------------------------------------------------------*/
if (err = GetError()) { /* report errors if any */
SendMsg(&ErrorDlg,CREATE,CREATE_FOCUS,0);
}
/*----------------------------------------------------------------------
* Get an event (a keystroke or null(timer) event are the usuals.
*----------------------------------------------------------------------*/
maction:
app_event.do_event = DO_EVENT;
m_action (&app_event); /* Grab system manager event */
if (DB_CardChanged(&Db)<0)
goto restart;
switch (app_event.kind) { /* Branch on SysMgr event */
case E_KEY: /* users, the source of all troubles */
if (GetFocus())
SendFocusMsg(KEYSTROKE, app_event.data, app_event.scan);
else
goto restart;
break;
case E_REFRESH: /* redraw after sysmgr mucks up screen */
SendAllMsg(DRAW, DRAW_ALL, 0);
break;
case E_ACTIV: /* reactivate on rtn from other app */
HourglassOn(-1,-1);
if (DB_Reactivate(&Db) != DB_OK) { /* some file badness, restart app */
restart:
RestartApp(MyAppsHotKey);
m_fini(); /* but just in case, */
return; /* bail out cuz windows can't be operated */
}
ReactivateLHAPI(&CapData); /* things are OK, Hello LHAPI */
SyncLHAPIKeyState();
break;
case E_DEACT: /* switch to another app */
DB_Deactivate(&Db);
DeactivateLHAPI();
goto maction;
break;
case E_TERM: /* enforced bailout */
IndexBlock.Done = TRUE;
break;
case E_NONE:
SendMsg(GetFocus(), NULLEVENT, app_event.shifts, app_event.scan);
HandleClock(); /* show ticking clock (if enabled) */
break;
} /* end of switch on event type */
} /* end of event loop */
/*-----------------------------------------------------------
* Proof that miracles exist: no reboot this time.
*-----------------------------------------------------------*/
HourglassOn(-1,-1);
CloseDbFile(&Db); /* close current database */
m_fini(); /* Tell System Manager goodbye */
}
/***************************************************************************** ******************************************************************************
*
* Initialize CAP, SysMgr, Database, and data structures
*
****************************************************************************** ******************************************************************************
/
void Initialize(void)
{
int i, size, err = 0;
char *titleptr;
char *bufptr;
char *pstuffptr;
/*----------------------------------------------------------------------
* Greet all the important local personalities
*----------------------------------------------------------------------*/
m_init_app(SYSTEM_MANAGER_VERSION); /* Hello SysMgr */
InitializeLHAPI(&CapData); /* Hello LHAPI */
/*----------------------------------------------------------------------
* setup far internal far pointers to be maintained by sysmgr. Initialize
* the first block for use by card window titles.
*----------------------------------------------------------------------*/
HourglassOn(-1,-1);
titleptr = CardWndTitles;
m_reg_far(&CardWndTitlePtrs, countof(CardWndTitlePtrs), 4);
for (i=0; i<MAX_CARD_WNDS; i++) {
CardWndTitlePtrs[i] = titleptr;
titleptr += DB_FIELDNAMELENGTH + 1;
CardWindow[i].Title = &CardWndTitlePtrs[i];
}
MultiBuffer = FilterBuffer;
EscBuffer = FileSpace;
LineStarts = Scratch2;
/*----------------------------------------------------------------------
* Set fonts, map in the resource file and init resource ptrs.
*----------------------------------------------------------------------*/
RegisterFont(FONT_NORMAL); /* be as normal as possible */
SetMenuFont(FONT_NORMAL);
SetDefaultFont(FONT_NORMAL);
map_resource_file("CDBAPP.RI"); /* map in resourced msgs */
Init_Db_Strings(); /* create access to those msgs */
/*-----------------------------------------------------------
* App specific initialization
*
* Must set EnvFileName, DfltDataFileName, ResourceFileName,
* DfltSmartClipName1/2, DfltCategory.
*-----------------------------------------------------------*/
InitAppPhone();
/*----------------------------------------------------------------------
* register the name of the application
* with the system manager for use in case low memory prompting is
* needed.
*----------------------------------------------------------------------*/
m_reg_app_name(*IndexBlock.AppName); /* register appname */
/*----------------------------------------------------------------------
* Init file dlgs, empty index window, and no-file window.
*----------------------------------------------------------------------*/
InitializeFileDialogs(); /* Hello File Dialogs */
*BackupFileName = 0; /* No 2nd chance if loadfile fails */
SendMsg(&TopWnd,CREATE,CREATE_FOCUS,0); /* Create main application window */
SendMsg(&DummyWnd, CREATE, CREATE_FOCUS, 0);
HourglassOn(-1,-1); /* put hourglass up again now that windows up */
/*----------------------------------------------------------------------
* Get name of current data file from environment file, use default file
* name if no environment file exists.
*----------------------------------------------------------------------*/
if (_dos_open(EnvFileName, O_RDWR, &EnvHandle))
lstrcpy(FileSpec, DfltDataFileName);
else {
_dos_lseek(EnvHandle, 0, SEEK_SET);
_dos_read(EnvHandle, FileSpec, sizeof(Db.filename), &size);
/*----------------------------------------------------------------------
* get printer setup information. dflts are already in place if read fails
*----------------------------------------------------------------------*/
i = sizeof(INDEXPRINTBLOCK);
bufptr = Record;
_dos_read(EnvHandle, bufptr, i, &size); /* read print setup info */
if (size == i) {
pstuffptr = (char *)&PStuff;
for (;i;i--) *(pstuffptr++) = *(bufptr++);
}
close:
_dos_close(EnvHandle);
}
/*----------------------------------------------------------------------
* init the db engine
*----------------------------------------------------------------------*/
err = DB_Init();
if (err || GetError()) {
SetError(ERR_DBINIT);
HourglassOff();
return;
}
/*----------------------------------------------------------------------
* if file is not default and does not exist, create no file state
* instead
*----------------------------------------------------------------------*/
if ((lstrcmp(FileSpec, DfltDataFileName)) && (!(Exists(FileSpec)))) {
SetError(ERR_OPEN);
HourglassOff();
return;
}
/*----------------------------------------------------------------------
* open up the datafile
*----------------------------------------------------------------------*/
LoadFileShell(NULL);
}
/***************************************************************************** ******************************************************************************
*
* Launches app; closes current app and launches again - last ditch
* recovery system when datafile deleted underneath.
*
****************************************************************************** ******************************************************************************/
int RestartApp(int HotKey)
{
struct task far *TCB = m_get_TCB();
int i;
for (i=0; i<TASKCOUNT; i++, TCB++)
if (HotKey==TCB->t_hotkey) goto launch;
return -1;
launch:
app_event.e_launch_task = i; /* Index of the app we want */
app_event.e_launch_type = LT_CLOSE_THEN_LAUNCH; /* Close us out first */
app_event.do_event = DO_LAUNCH;
m_action(&app_event); /* Launch our app */
return 1;
}