📄 quiklist.c
字号:
/********************************************************************* FILE: QuikList.c** DESCRIPTION: The QuikList project module. This version of QuikList (1) * shows you how to implement a list with multi-character* Graffiti lookup. The list data is stored in a string array.** VERSION: 1.0**********************************************************************/#include <PalmOS.h>#include <TxtGlue.h>#include "QuikList.h"#include "QuikListRsc.h"#include "Utils.h"#include "UtilsRsc.h"/*********************************************************************** * FUNCTION: StartGraffitiLookup * * DESCRIPTION: Initiate a record lookup using a user-entered keystroke, * The lookup uses a two-part timing mechanism: one setting * for the EvtGetEvent timeout value, and a secondary counter. * * RETURNED: Nothing. * *SIDE EFFECT: sets three global variables: * gFindStr (the lookup string), the EvtGetEvent timeout setting, * and the lookup counter. ***********************************************************************/static void StartGraffitiLookup( Char chr // ( in ) The next char to put in the lookup string.){ Int32 gFindStrLen = StrLen ( gFindStr ); // Turn on lookup indicator so user knows a lookup is taking place FrmShowObject ( FrmGetActiveForm (), FrmGetObjectIndex ( FrmGetActiveForm (), MainLookupIndicatorLabel )); // Set up the lookup string gFindStr [ gFindStrLen ] = chr; gFindStr [ gFindStrLen + 1 ] = NULL; // Arm (rearm) the nilEvent timer and its counter. We need a value > 1 in// gNilEventCnt because nilEvents may appear for reasons other than// the timer. gEventTimeout = LOOKUP_TIMER_CNT; gNilEventCnt = NIL_EVENT_CNT;}/*********************************************************************** * FUNCTION: StopGrafftiLookup * * DESCRIPTION: Check to see if there's an active Graffiti lookup going on. * If so, check for termination. This gets called every * LOOKUP_TIMER_CNT ticks until gNilEventCnt is zero. * * RETURNED: Nothing. ***********************************************************************/static void StopGrafftiLookup( void){ gNilEventCnt--; if ( gNilEventCnt == 0 ) {// Hide the lookup indicator, clear the lookup string, and // turn off nilEvent generation. FrmHideObject ( FrmGetActiveForm (), FrmGetObjectIndex ( FrmGetActiveForm (), MainLookupIndicatorLabel )); gFindStr [ 0 ] = NULL; gEventTimeout = evtWaitForever; }}/*********************************************************************** * FUNCTION: CompareNameAndFindString * * DESCRIPTION: The binary search callback function. Compare two strings * for equality. The second string parameter is actually * a pointer to a string, so we have to fetch it indirectly. * * RETURNED: 0 if they match, non-zero otherwise. ***********************************************************************/static Int16 CompareNameAndFindString( void const * gFindStr, // ( in ) The string we're looking for void const * name, // ( in ) The item to check for a match Int32 /* other */ // unused){ Char** listNameP = ( Char ** ) name; UInt16 gFindStrLen = ( UInt16 ) StrLen ( gFindStr ); return ( TxtCaselessCompare ( gFindStr, gFindStrLen, NULL, * listNameP, gFindStrLen, NULL ));}#pragma mark ----------------/*********************************************************************** * FUNCTION: MainFormDrawList ** DESCRIPTION: Draw the main form list. In between each line,* check for a new incoming keystroke. If there is one, do* another Graffiti lookup. * * RETURNED: nothing ***********************************************************************/static void MainFormDrawList( void){#define NUM_REDRAWS 1 UInt16 i, j; Coord x, y; EventType event;// Erase the list's rectangle WinEraseRectangle ( &gListBounds, 0 ); for ( i = 0; i < VIS_ITEMS; i++ ) { // Check for keystroke in middle of list redraw.// If there is one, do a lookup to see if there is a new list location// match. If so, stop redrawing until the next redraw kicks in.// StopRedraw is set in ProcessKeystroke. if ( ! gStopDrawing ) { if ( EvtSysEventAvail ( false )) { EvtGetEvent ( &event, 0 ); SysHandleEvent ( &event ); if ( event.eType == keyDownEvent ) { Boolean handled = MainFormProcessKeystroke ( ( UInt8 ) event.data.keyDown.chr, true ); if ( gStopDrawing ) return; } }// No event available, keep drawing the current list x = ( Coord ) ( gListBounds.topLeft.x + 2 ); y = ( Coord ) ( gListBounds.topLeft.y + ( i * FONT_HEIGHT )); // Draw more than once to slow things down for testing for ( j = 0; j < NUM_REDRAWS; j++ ) WinDrawChars ( gNames [ gTopItem + i ], StrLen ( gNames [ gTopItem + i ]), x, y ); } }}/*********************************************************************** * FUNCTION: FitToListBoundaries * * DESCRIPTION: Check an incoming list position to make sure it* it fits within the legal boundaries for the list. * * RETURNED: A valid list position ***********************************************************************/static Int16 FitToListBoundaries( Int16 topItem // ( in ) the list item to check){ Int16 result = topItem; if ( result < 0 ) result = 0; if ( result > LIST_SIZE - VIS_ITEMS ) result = LIST_SIZE - VIS_ITEMS; return ( result );}/*********************************************************************** * FUNCTION: MainFormProcessKeystroke * * DESCRIPTION: Process a keystroke event for the Main form. That typically means * to see if there is a record that starts with a specific string. * * RETURNED: A boolean set to True if the keystroke was handled. It also set * the global gStopDrawing ***********************************************************************/static Boolean MainFormProcessKeystroke( UInt8 chr, // ( in ) keystroke to process Boolean drawing // ( in ) Currently drawing a list?){ Boolean handled = false;// First, check for scroll up/down buttons if ( chr == vchrPageUp ) { if ( gTopItem != 0 ) { gTopItem = FitToListBoundaries ( gTopItem - VIS_ITEMS + 1 ); MainFormDrawList (); } handled = true; } else if ( chr == vchrPageDown ) { if ( gTopItem != LIST_SIZE - VIS_ITEMS ) { gTopItem = FitToListBoundaries ( gTopItem + VIS_ITEMS - 1 ); MainFormDrawList (); } handled = true; } else // If it's a valid char, start Graffiti lookup if ( TxtGlueCharIsPrint ( chr )) { Int32 recLoc = -1; handled = true;// Only do the lookup if there's room in the lookup string if ( StrLen ( gFindStr ) < MAX_MATCH_CHAR ) { StartGraffitiLookup (( Char ) chr ); // Lookup started, check for a record that starts with the string if ( SysBinarySearch ( gNames, LIST_SIZE, sizeof ( Char* ), CompareNameAndFindString, gFindStr, 0, &recLoc, true )) { // Found a record, redraw the list so the matched record is the topmost// visible item. If this is a redraw for a multi-char match (if drawing == true),// this redraw takes place before the previous list drawing completes. gTopItem = FitToListBoundaries (( Int16 ) recLoc ); MainFormDrawList (); // If a previous list is being drawn, stop it. If not, enable drawing// in case a multi-char match previously disabled drawing. gStopDrawing = drawing; } } } return handled;}#pragma mark ----------------/*********************************************************************** * FUNCTION: MainFormInit * * DESCRIPTION: This routine initializes the main form. It should be used to * execute code that must be done _before_ the form is * drawn using FrmDrawForm. * * RETURNED: nothing ***********************************************************************/static void MainFormInit( FormPtr frmP // ( in ) Pointer to the main form){ if ( frmP != NULL ) { RctSetRectangle ( &gListBounds, TOP_LEFT_X, TOP_LEFT_Y, EXTENT_X, EXTENT_Y ); }}/*********************************************************************** * FUNCTION: MainFormDraw * * DESCRIPTION: This routine draws the non-form contents of the main form. * * RETURNED: nothing ***********************************************************************/static void MainFormDraw( FormPtr frmP // ( in ) Pointer to the main form.){ if ( frmP != NULL ) { WinDrawRectangleFrame ( simpleFrame, &gListBounds ); MainFormDrawList (); }}/*********************************************************************** * FUNCTION: MainFormDone * * DESCRIPTION: This routine cleans up after the main form. * * RETURNED: nothing ***********************************************************************/static void MainFormDone( FormPtr frmP // ( in ) Pointer to the main form){ if ( frmP != NULL ) { FrmEraseForm ( frmP ); FrmDeleteForm ( frmP ); }}/*********************************************************************** * FUNCTION: MainFormDoMenuCommand * * DESCRIPTION: This routine handles menu commands. * * RETURNED: true if command event handled ***********************************************************************/static Boolean MainFormDoMenuCommand( UInt16 command // ( in ) The ID of menu command to do){ Boolean handled = false; FormPtr frmP; switch ( command ) { case MainOptionsAboutQuikList: MenuEraseStatus ( 0 ); frmP = FrmInitForm ( AboutForm ); FrmDoDialog ( frmP ); FrmDeleteForm ( frmP ); handled = true; break; } return handled;}/*********************************************************************** * FUNCTION: MainFormHandleEvent * * DESCRIPTION: This routine is the event handler for the main form. * * RETURNED: true if the event is handled. ***********************************************************************/static Boolean MainFormHandleEvent( EventPtr eventP // ( in ) Pointer to the event to handle){ Boolean handled = false; FormPtr frmP = FrmGetActiveForm (); switch ( eventP->eType ) {// Form events case frmOpenEvent: MainFormInit ( frmP ); // ***** WARNING - falls thru to next case ***** case frmUpdateEvent: FrmDrawForm ( frmP ); MainFormDraw ( frmP ); handled = true; break; case frmCloseEvent: MainFormDone ( frmP ); handled = true; break; // Menu events case menuEvent: handled = MainFormDoMenuCommand ( eventP->data.menu.itemID ); break; // Keystroke events case keyDownEvent: handled = MainFormProcessKeystroke (( UInt8 ) eventP->data.keyDown.chr, false ); break; } return handled;}#pragma mark ----------------/*********************************************************************** * FUNCTION: AppHandleEvent * * DESCRIPTION: Loads a form's resources and set its event handler. * * RETURNED: true if the event is handled. ***********************************************************************/static Boolean AppHandleEvent( EventPtr eventP // ( in ) Pointer to the event to handle){ Boolean handled = false; if ( eventP->eType == frmLoadEvent ) { // Form load event--initialize the form and make it the active form. UInt16 formId = eventP->data.frmLoad.formID; FormPtr frmP = FrmInitForm ( formId ); if ( frmP ) { FrmSetActiveForm ( frmP );// Set the event handler for the form. switch ( formId ) { case MainForm: FrmSetEventHandler ( frmP, MainFormHandleEvent ); handled = true; break; // Set other cases as needed } } } return handled;}/*********************************************************************** * FUNCTION: AppEventLoop * * DESCRIPTION: The main event loop for the application. * * RETURNED: nothing ***********************************************************************/static void AppEventLoop( void){ UInt16 error; EventType event; do { // Get the next event EvtGetEvent ( &event, gEventTimeout );// Check the starndard default handlers if (! SysHandleEvent ( &event)) if (! MenuHandleEvent ( 0, &event, &error )) if (! AppHandleEvent ( &event )) // Nobody wanted the event. Check for a nil event to turn off Graffiti lookup timing if ( event.eType == nilEvent && gNilEventCnt > 0 && FrmGetActiveFormID () == MainForm) { StopGrafftiLookup ( ); }// None of the above, take the default handler FrmDispatchEvent ( &event ); } while ( event.eType != appStopEvent );}/*********************************************************************** * FUNCTION: AppStart * * DESCRIPTION: Do whatever is necessary to get started, like read the app preferences. * * RETURNED: Err value or 0 if nothing went wrong ***********************************************************************/static UInt32 AppStart // ( out ) zero or an error code( void){ return 0; // Return an error code if necessary. }/*********************************************************************** * FUNCTION: AppStop * * DESCRIPTION: Do whatever you need to do, like save the preferences. * * RETURNED: nothing ***********************************************************************/static void AppStop( void){ FrmCloseAllForms ();}#pragma mark ----------------/*********************************************************************** * FUNCTION: PilotMain * * DESCRIPTION: The application main entry point. * * RETURNED: 0 if launch & execution are successful, non-zero otherwise. ***********************************************************************/ UInt32 PilotMain( UInt16 cmd, // ( in ) The launch code MemPtr /* cmdPBP*/, // ( in ) Pointer to the launch code structure UInt16 launchFlags // ( in ) Extra launch info){ UInt32 error = 0;// Check the ROM version for compatibility. error = RomVersionCompatible ( MIN_ROM_VERSION, launchFlags); if ( error == 0 ){// ROM OK, check for the various launch codes as needed. switch (cmd) { case sysAppLaunchCmdNormalLaunch: error = AppStart (); if ( error == 0 ) { FrmGotoForm ( MainForm ); AppEventLoop (); AppStop (); } break; } } return error;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -