/****************************************************************************** * * Copyright (c) 1999-2004 PalmSource, Inc. All rights reserved. * * File: GcFonts.c * * Release: Palm OS 6.0.1 * *****************************************************************************/ #include #include "AppResources.h" /*********************************************************************** * * Internal Structures * ***********************************************************************/ // Holds current transform values for the three types we support in the app. typedef struct TransformType { fcoord_t minimum; fcoord_t maximum; fcoord_t value; fcoord_t step; } TransformType; // Transformation types enum { kTransTypeSize = 0, kTransTypeShear, kTransTypeRotate }; // Flag to redraw entire form instead of single object #define kDrawFormID (-1) // Structure to hold our font family names (or styles) typedef struct ListItemsType { uint16_t uwNumItems; // number of items in array FontFamily *pItems; // array of FontFamily/FontStyle items // (essentially char[64]) } ListItemsType; /*********************************************************************** * * Global variables * ***********************************************************************/ // Holds current value and range for three transformation properties TransformType gTransType[3] = { // min, max, value, step { 3.0f, 100.0f, 42.0f, 1.0f }, // Size { -10.0f, 10.0f, 0.0f, 0.05f }, // Shear (x) { 0.0f, 6.283185f, 0.0f, 0.05f }, // Rotate (radians) }; DmOpenRef gAppResDB; // Pointer to database holding our form and other resources. ListItemsType gFontNames; ListItemsType gFontStyles; GcFontHandle gFontHandle; uint16_t gCurrentNameIndex; uint16_t gCurrentStyleIndex; // Enables automatic form object repositioning when the DIA changes FormLayoutType gMainFormLayout[] = { { sizeof(FormLayoutType), MainCanvasGadget, 0, frmFollowAllSides }, { sizeof(FormLayoutType), MainTextLabel, 0, frmFollowBottom }, { sizeof(FormLayoutType), MainSampleField, 0, frmFollowBottom }, { sizeof(FormLayoutType), frmLayoutGraffitiShiftID, 0, frmFollowBottom }, { 0,0,0,0 } // Last item must be all zeros }; /*********************************************************************** * Internal Functions ***********************************************************************/ /*********************************************************************** * * FUNCTION: PrvGetObjectPtr * * DESCRIPTION: Returns a pointer to an object's data on the specified form. * * PARAMETERS: -> pForm: Pointer to form * -> uwObjectID: ID of desired object * * RETURNED: Pointer to object, or NULL if no form specified. * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void * PrvGetObjectPtr(FormType *pForm, uint16_t uwObjectID) { uint16_t uwObjIndex; if (pForm == NULL) return NULL; uwObjIndex = FrmGetObjectIndex(pForm, uwObjectID); return FrmGetObjectPtr(pForm, uwObjIndex); } /****************************************************************************** * * FUNCTION: PrvInvalidateObject * * DESCRIPTION: Invalidates window or form object rectangle to trigger * an update event by the system. * * PARAMETERS: -> uwFormID: The ID of the form * -> wObjectID: The ID of the object to invalidate. If * wObjectID is kDrawFormID, invalidate whole form. * * RETURNED: Nothing * * REVISION HISTORY: * 6/2/03 jbp Initial version * ******************************************************************************/ static void PrvInvalidateObject(uint16_t uwFormID, int16_t wObjectID) { WinHandle hWindow; FormType * pForm; if ((pForm = FrmGetFormPtr(uwFormID)) == NULL) return; if ((hWindow = FrmGetWindowHandle(pForm)) == NULL) return; if (wObjectID == kDrawFormID) // Force update of entire window. WinInvalidateWindow(hWindow); else { RectangleType rect; FrmGetObjectBounds(pForm, FrmGetObjectIndex(pForm, (uint16_t)wObjectID), &rect); WinInvalidateRect(FrmGetWindowHandle(pForm), &rect); } } /*********************************************************************** * * FUNCTION: DisplayAboutDialog * * DESCRIPTION: Display the About box dialog. * * PARAMETERS: None * * RETURNED: Nothing * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void DisplayAboutDialog(void) { FormType *pForm; pForm = FrmInitForm(gAppResDB, AboutForm); FrmDoDialog(pForm); FrmDeleteForm(pForm); } /*********************************************************************** * * FUNCTION: BuildFamilyArray * * DESCRIPTION: Create an array of font families installed on device. * * PARAMETERS: None * * RETURNED: Index of first family in the list * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static uint16_t BuildFamilyArray(void) { int32_t numFamilies = GcCountFontFamilies(); int32_t i; FontFamily family; FontStyle style; status_t err; int16_t which = 0; // Initialize the data structure for our font families. gFontNames.uwNumItems = (uint16_t)numFamilies; if (numFamilies > 0) { gFontNames.pItems = (FontFamily *)MemPtrNew(sizeof(FontFamily) * numFamilies); MemSet(gFontNames.pItems, sizeof(FontFamily) * numFamilies, 0); } for (i = 0; i < numFamilies; i++) { // Get the next family name. err = GcGetFontFamily(i, &family); if (err == errNone) StrCopy(gFontNames.pItems[i], family); } // Set initial font if (gFontHandle) GcReleaseFont(gFontHandle); gFontHandle = GcCreateFont("palmos-plain"); // Get the family name and find it in the names list. GcGetFontFamilyAndStyle(gFontHandle, &family, &style); for (i = 0; i < numFamilies; i++) { if (StrCompare(gFontNames.pItems[i], family) == 0) { which = (int16_t)i; break; } } return which; } /*********************************************************************** * * FUNCTION: BuildStyleArray * * DESCRIPTION: Create an array of styles for the specified font family. * * PARAMETERS: -> family: Pointer to name of font family * * RETURNED: Index of current style * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static int16_t BuildStyleArray(const char* family) { int32_t numStyles; int32_t i; FontStyle currentStyle; FontFamily currentFamily; int16_t which = 0; // Free existing pointer if it exists. if (gFontStyles.uwNumItems > 0 && gFontStyles.pItems) MemPtrFree(gFontStyles.pItems); numStyles = GcCountFontStyles(family); gFontStyles.uwNumItems = (uint16_t)numStyles; // Allocate space for an array of styles (strings). gFontStyles.pItems = (FontFamily *)MemPtrNew(numStyles * sizeof(FontStyle)); for (i = 0; i < numStyles; i++) { FontStyle style; status_t err = GcGetFontStyle(family, i, &style); if (err == errNone) StrCopy(gFontStyles.pItems[i], style); } // Get the family name and find it in the names list. GcGetFontFamilyAndStyle(gFontHandle, ¤tFamily, ¤tStyle); for (i = 0; i < numStyles; i++) { if (StrCompare(gFontStyles.pItems[i], currentStyle) == 0) { which = (int16_t)i; break; } } return which; } /*********************************************************************** * * FUNCTION: LimitProperty * * DESCRIPTION: Ensure value is within property min/max limits. * * PARAMETERS: -> tt: Index of property to check * -> val: Value to validate * * RETURNED: Value, within property limits * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static fcoord_t LimitProperty(int32_t tt, fcoord_t val) { if (val < gTransType[tt].minimum) return gTransType[tt].minimum; if (val > gTransType[tt].maximum) return gTransType[tt].maximum; return val; } /*********************************************************************** * * FUNCTION: MainFormUpdateStylePopup * * DESCRIPTION: Update the Style popup trigger and list when user * chooses a different font family. * * PARAMETERS: None * * RETURNED: Nothing * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void MainFormUpdateStylePopup(void) { FormType *pForm; ListType *pList; ControlType *pTrigger; pForm = FrmGetActiveForm(); pList = PrvGetObjectPtr(pForm, MainFaceList); LstSetListChoices(pList, NULL, gFontStyles.uwNumItems); LstSetHeight(pList, gFontStyles.uwNumItems); LstSetSelection(pList, gCurrentStyleIndex); pTrigger = PrvGetObjectPtr(pForm, MainFacePopTrigger); CtlSetLabel(pTrigger, gFontStyles.pItems[gCurrentStyleIndex]); } /*********************************************************************** * * FUNCTION: MainFormDrawFontStyleItem * * DESCRIPTION: Callback routine to draw items in the font style popup * * PARAMETERS: -> itemNum: Index of list item to draw * -> pRect: Pointer to bounds where we can draw * -> pItemsText: unused (will be NULL) * -> pList: Pointer to ListType structure * * RETURNED: Nothing * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void MainFormDrawFontStyleItem(int16_t itemNum, RectangleType *pRect, char **itemsText, struct ListType *listP) { uint16_t itemTextLen; char *pStr; // Truncate the item with an ellipsis if it doesn't fit in the list width. // Get the item text length pStr = (char *)gFontStyles.pItems[itemNum]; itemTextLen = StrLen(pStr); WinDrawTruncChars(pStr, itemTextLen, pRect->topLeft.x, pRect->topLeft.y, pRect->extent.x); } /*********************************************************************** * * FUNCTION: MainFormDrawFontFamilyItem * * DESCRIPTION: Callback routine to draw items in the font family popup * * PARAMETERS: -> itemNum: Index of list item to draw * -> pRect: Pointer to bounds where we can draw * -> pItemsText: unused (will be NULL) * -> pList: Pointer to ListType structure * * RETURNED: Nothing * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void MainFormDrawFontFamilyItem(int16_t itemNum, RectangleType *pRect, char **pItemsText, struct ListType *pList) { uint16_t itemTextLen; char *pStr; // Truncate the item with an ellipsis if it doesn't fit in the list width. // Get the item text length pStr = (char *)gFontNames.pItems[itemNum]; itemTextLen = StrLen(pStr); WinDrawTruncChars(pStr, itemTextLen, pRect->topLeft.x, pRect->topLeft.y, pRect->extent.x); } /*********************************************************************** * * FUNCTION: MainFormSetAmountSlider * * DESCRIPTION: Called when user chooses a different Transform Type push * button. Set the slider values for the transform. * * PARAMETERS: -> pForm: Pointer to main form's data * -> uwPushBtnID: ID of pushed button :-) * * RETURNED: Nothing * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void MainFormSetAmountSlider(FormType* pForm, uint16_t uwPushBtnID) { ControlType *pSlider = PrvGetObjectPtr(pForm, MainAmountFeedbackSliderControl); uint16_t tt = uwPushBtnID - MainSizePushButton; // transform type = 0..2 fcoord_t range; uint16_t ctlMin, ctlMax, ctlPage, ctlValue; range = gTransType[tt].maximum - gTransType[tt].minimum; // The minimum is always 0. Scale the other values accordingly. ctlMin = 0; ctlMax = (uint16_t)((range / gTransType[tt].step) + 0.5f); ctlPage = (uint16_t)((ctlMax * (gTransType[tt].step * 10.0 / range)) + 0.5f); ctlValue = (uint16_t)((ctlMax * ((gTransType[tt].value - gTransType[tt].minimum) / range)) + 0.5f); // Set the values - the OS will take care of updating the slider's appearance. CtlSetSliderValues(pSlider, &ctlMin, &ctlMax, &ctlPage, &ctlValue); } /*********************************************************************** * * FUNCTION: MainFormDrawCanvas * * DESCRIPTION: Called by gadget handler when gadget needs to be redrawn. * * PARAMETERS: -> pRect: Pointer to gadget's bounding rectangle * * RETURNED: nothing * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void MainFormDrawCanvas(RectangleType *pRect) { FormType *pForm = FrmGetActiveForm(); FieldType *field = PrvGetObjectPtr(pForm, MainSampleField); char *pText = FldGetTextPtr(field); RectangleType bounds = *pRect; GcHandle gc; fcoord_t y, x; FAbsRectType fontR; // Save the draw state (we'll restore it when we are done drawing). WinPushDrawState(); // Set the window's coordinate system to native coordinates. Although you could // do the drawing in standard coords, the GcFontSize() call returns // native coordinates, so this way we don't have to do very much scaling. WinSetCoordinateSystem(kCoordinatesNative); // We do need to scale the canvas bounds rectangle to native, however. WinScaleRectangle(&bounds); // Get the graphics context (don't forget to release when done). gc = GcGetCurrentContext(); // Although we have set the window's coordinate system to native, we // still need to set the graphic context coordinates as well. GcSetCoordinateSystem(gc, kCoordinatesNative); // Set clipping region to the canvas area. GcBeginClip(gc, false); GcRectI(gc, bounds.topLeft.x, bounds.topLeft.y, bounds.topLeft.x + bounds.extent.x, bounds.topLeft.y + bounds.extent.y); GcPaint(gc); GcEndClip(gc); // Clear canvas by painting white. GcSetColor(gc, 255, 255, 255, 255); GcPaint(gc); // Turn on antialiasing to make the text look better GcSetAntialiasing(gc, kNormalAntialiasing); // Set font size, style, and color GcSetFont(gc, gFontHandle); GcSetFontSize(gFontHandle, gTransType[kTransTypeSize].value); GcSetFontStyle(gFontHandle, gFontStyles.pItems[gCurrentStyleIndex]); GcSetColor(gc, 255, 0, 128, 255); // Reddish - maybe we'll add a picker later // Find the center of the canvas and move the origin there. We'll be rotating // the canvas around that point. y = (fcoord_t)(bounds.topLeft.y + (bounds.extent.y / 2)); x = (fcoord_t)(bounds.topLeft.x + (bounds.extent.x / 2)); GcTranslate(gc, x, y); // Apply our effects GcShear(gc, gTransType[kTransTypeShear].value, 0.0f); GcRotate(gc, gTransType[kTransTypeRotate].value); // Get the height and width of the font, so we can draw the text // centered on the canvas's midpoint. GcFontStringBounds(gFontHandle, pText, StrLen(pText), &fontR); // Draw the text to complete the path GcDrawTextAt(gc, -((fontR.right - fontR.left) / 2), ((fontR.bottom - fontR.top) /2), pText, StrLen(pText)); // Release the context... GcReleaseContext(gc); // ...and restore our window's draw state. WinPopDrawState(); } /*********************************************************************** * * FUNCTION: MainFormGadgetHandler * * DESCRIPTION: Called by OS to handle events for gadget (update, penDown, etc.). * * PARAMETERS: -> Standard gadget handler callback function parameters. * * RETURNED: 'true' if no additional processing of event is required. * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static Boolean MainFormGadgetHandler(struct FormGadgetTypeInCallback *gadgetP, uint16_t cmd, void *paramP) { // We only care about update events - our signal to redraw the canvas. if (cmd == formGadgetDrawCmd && gFontHandle) { MainFormDrawCanvas(&gadgetP->rect); return true; } return false; } /*********************************************************************** * * FUNCTION: MainFormCloseEvent * * DESCRIPTION: Clean up allocated memory here before we close (we * allocated memory in MainFormOpenEvent(). * * PARAMETERS: void * * RETURNED: Nothing * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void MainFormCloseEvent(void) { // Free allocated memory if (gFontStyles.pItems) MemPtrFree(gFontStyles.pItems); if (gFontNames.pItems) MemPtrFree(gFontNames.pItems); } /*********************************************************************** * * FUNCTION: MainFormOpenEvent * * DESCRIPTION: Initializes objects on the main form. Do not do any * drawing: when everything is set up, invalidate the * form to force the initial drawing. * NOTE: we allocate two handles here that must be * freed when we leave the form. * * PARAMETERS: None * * RETURNED: Nothing * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void MainFormOpenEvent(void) { FormType *pForm = FrmGetFormPtr(MainForm); ListType *pList; ControlType *pTrigger, *pPushButton; FieldType *pField; const char *text = "PalmSource"; // Build array of font names (for popup list) and return selected font. gCurrentNameIndex = BuildFamilyArray(); // Set font family popup list and trigger. pList = PrvGetObjectPtr(pForm, MainFamilyList); LstSetDrawFunction(pList, MainFormDrawFontFamilyItem); LstSetListChoices(pList, NULL, gFontNames.uwNumItems); LstSetHeight(pList, gFontNames.uwNumItems); LstSetSelection(pList, gCurrentNameIndex); pTrigger = PrvGetObjectPtr(pForm, MainFamilyPopTrigger); CtlSetLabel(pTrigger, gFontNames.pItems[gCurrentNameIndex]); // Set up the font style list and trigger. gCurrentStyleIndex = BuildStyleArray(gFontNames.pItems[gCurrentNameIndex]); pList = PrvGetObjectPtr(pForm, MainFaceList); LstSetDrawFunction(pList, MainFormDrawFontStyleItem); MainFormUpdateStylePopup(); // Set the initial value for the push buttons pPushButton = PrvGetObjectPtr(pForm, MainSizePushButton); CtlSetValue(pPushButton, true); // Set up the slider MainFormSetAmountSlider(pForm, MainSizePushButton); // Set the handler function for events in our canvas (gadget). The only events // we care about are update events, so we can draw the canvas. FrmSetGadgetHandler(pForm, FrmGetObjectIndex(pForm, MainCanvasGadget), MainFormGadgetHandler); // Set the starting text. pField = PrvGetObjectPtr(pForm, MainSampleField); FldInsert(pField, text, StrLen(text)); // Put insertion point in text field. FrmSetFocus(pForm, FrmGetObjectIndex(pForm, MainSampleField)); // Invalidate whole window - OS will draw during next update event. PrvInvalidateObject(MainForm, kDrawFormID); } /*********************************************************************** * * FUNCTION: MainFormMenuEvent * * DESCRIPTION: Process user's menu selections. * * PARAMETERS: -> uwMenuCmdID: ID of selected menu item * * RETURNED: 'true' if item is selected * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static Boolean MainFormMenuEvent(uint16_t uwMenuCmdID) { Boolean fHandled = false; switch (uwMenuCmdID) { case MainOptionsAboutGcFonts: DisplayAboutDialog(); fHandled = true; break; } return fHandled; } /*********************************************************************** * * FUNCTION: MainFormKeydownEvent * * DESCRIPTION: Update the canvas when user edits the input text * * PARAMETERS: -> pEvent: Pointer to event's data * * RETURNED: 'true' if we update the display; 'false' otherwise * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static Boolean MainFormKeydownEvent(EventType *pEvent) { // Ignore all virtual keys if (EvtKeydownIsVirtual(pEvent)) return false; // Force redraw of canvas. PrvInvalidateObject(MainForm, MainCanvasGadget); return true; } /*********************************************************************** * * FUNCTION: MainFormCtlSelectEvent * * DESCRIPTION: If the user taps on the Size, Shear, or Rotate pushbutton, * set the values of the slider and redraw it. * * PARAMETERS: -> pEvent: Pointer to event's data * * RETURNED: 'true' if a button was pushed. * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static Boolean MainFormCtlSelectEvent(EventType *pEvent) { Boolean fHandled = false; switch (pEvent->data.ctlSelect.controlID ) { case MainSizePushButton: case MainShearPushButton: case MainAnglePushButton: MainFormSetAmountSlider(FrmGetActiveForm(), pEvent->data.ctlSelect.controlID); fHandled = true; break; } return fHandled; } /*********************************************************************** * * FUNCTION: MainFormCtlRepeatEvent * * DESCRIPTION: Process user's adjustment of the value slider control. * * PARAMETERS: -> pEvent: Pointer to event's data * * RETURNED: Nothing (the caller must return 'false' so sytem can * process the next ctlRepeatEvent * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void MainFormCtlRepeatEvent(EventType *pEvent) { // We only have one slider control if (pEvent->data.ctlRepeat.controlID == MainAmountFeedbackSliderControl) { uint16_t value = pEvent->data.ctlRepeat.value; uint16_t pbIndex; uint16_t tt; FormType *pForm = FrmGetActiveForm(); uint16_t minVal, maxVal; fcoord_t range; ControlType *pSlider; pbIndex = FrmGetControlGroupSelection(pForm, MainGroupID); tt = FrmGetObjectId(pForm, pbIndex) - MainSizePushButton; pSlider = PrvGetObjectPtr(pForm, MainAmountFeedbackSliderControl); CtlGetSliderValues(pSlider, &minVal, &maxVal, NULL, NULL); range = gTransType[tt].maximum - gTransType[tt].minimum; gTransType[tt].value = LimitProperty(tt, gTransType[tt].minimum + (range * value) / (maxVal - minVal)); PrvInvalidateObject(MainForm, MainCanvasGadget); } } /*********************************************************************** * * FUNCTION: MainFormPopSelectEvent * * DESCRIPTION: Process user selection of popup list item. * * PARAMETERS: -> pEvent: Pointer to event's data * * RETURNED: Return 'true' if user chooses a list item, since we * are setting the popup trigger's text ourselves. * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static Boolean MainFormPopSelectEvent(EventType *pEvent) { Boolean fHandled = false; char *pSelText; // Get the index of the selected item from the event data structure switch (pEvent->data.popSelect.controlID ) { case MainFamilyPopTrigger: // Update the trigger text, since we are overriding the default behavior. gCurrentNameIndex = pEvent->data.popSelect.selection; pSelText = gFontNames.pItems[gCurrentNameIndex]; CtlSetLabel(pEvent->data.popSelect.controlP, pSelText); // Set new font handle, update the Style popup, and update canvas // TODO: factor following code if (gFontHandle) GcReleaseFont(gFontHandle); gFontHandle = GcCreateFont(pSelText); GcSetFontSize(gFontHandle, gTransType[kTransTypeSize].value); GcSetFontStyle(gFontHandle, gFontStyles.pItems[gCurrentStyleIndex]); gCurrentStyleIndex = BuildStyleArray(pSelText); MainFormUpdateStylePopup(); // Force an update of the canvas to reflect user's choice. PrvInvalidateObject(MainForm, MainCanvasGadget); fHandled = true; break; case MainFacePopTrigger: gCurrentStyleIndex = pEvent->data.popSelect.selection; pSelText = gFontStyles.pItems[gCurrentNameIndex]; CtlSetLabel(pEvent->data.popSelect.controlP, pSelText); MainFormUpdateStylePopup(); GcSetFontStyle(gFontHandle, gFontStyles.pItems[gCurrentStyleIndex]); // Force an update of the canvas to reflect user's choice. PrvInvalidateObject(MainForm, MainCanvasGadget); fHandled = true; break; } return fHandled; } /*********************************************************************** * * FUNCTION: MainFormHandleEvent * * DESCRIPTION: Handles events for this form. * * PARAMETERS: -> pEvent: Pointer to received EventType structure * * RETURNED: Return 'true' to prevent system from calling default * event handler. * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static Boolean MainFormHandleEvent(EventType* pEvent) { Boolean fHandled = false; switch (pEvent->eType) { case frmOpenEvent: MainFormOpenEvent(); fHandled = true; break; case frmCloseEvent: MainFormCloseEvent(); break; case ctlSelectEvent: fHandled = MainFormCtlSelectEvent(pEvent); break; case popSelectEvent: fHandled = MainFormPopSelectEvent(pEvent); break; case ctlRepeatEvent: MainFormCtlRepeatEvent(pEvent); break; case keyDownEvent: MainFormKeydownEvent(pEvent); break; case menuEvent: fHandled = MainFormMenuEvent(pEvent->data.menu.itemID); break; default: break; } return fHandled; } /*********************************************************************** * * FUNCTION: AppHandleEvent * * DESCRIPTION: Loads form resources, makes form active, and registers * the form's event handler function. * * PARAMETERS: -> pEvent: Pointer to EventType structure * * RETURNED: Return 'true' if you don't want system to call the default * event handler for the event. * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static Boolean AppHandleEvent(EventType* pEvent) { uint16_t formId; FormType *pForm; if (pEvent->eType == frmLoadEvent) { // Load the form resource. formId = pEvent->data.frmLoad.formID; // OS6NEW: FrmInitForm() needs app res db ptr as first argument pForm = FrmInitForm(gAppResDB, formId); FrmSetActiveForm(pForm); // Set the event handler for the form. The handler of the currently // active form is called by FrmHandleEvent each time is receives an // event. switch (formId) { case MainForm: FrmSetEventHandler(pForm, MainFormHandleEvent); FrmInitLayout(pForm, gMainFormLayout); break; default: ErrFatalDisplay("Invalid Form Load Event"); break; } return true; } return false; } /*********************************************************************** * * FUNCTION: AppStart * * DESCRIPTION: Set up app's state, init globals, etc. * * PARAMETERS: None * * RETURNED: 0 (errNone) if no problems. * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static status_t AppStart(void) { return errNone; } /*********************************************************************** * * FUNCTION: AppStop * * DESCRIPTION: Clean up and save application state before closing. * * PARAMETERS: None * * RETURNED: Nothing * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void AppStop(void) { // Close all the open forms. FrmCloseAllForms(); } /*********************************************************************** * * FUNCTION: AppEventLoop * * DESCRIPTION: Processes all events for the application. * * PARAMETERS: None * * RETURNED: Nothing * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ static void AppEventLoop(void) { status_t error; EventType event; do { EvtGetEvent(&event, evtWaitForever); if (SysHandleEvent(&event)) continue; // OS6NEW: error codes are now status_t, not status_t (32 bit) if (MenuHandleEvent(0, &event, &error)) continue; if (AppHandleEvent(&event)) continue; FrmDispatchEvent(&event); } while (event.eType != appStopEvent); } /*********************************************************************** * * FUNCTION: PilotMain * * DESCRIPTION: Main entry point for the application. * * PARAMETERS: -> launchCode: Launch code specifying why app's entry * point was called. * <-> pParams: Pointer to a data structure associated * with the launch code. * -> launchFlags: Provides information about app conditions at launch * ( e.g., is app the active application). * RETURNED: Result of launch. If no errors, return 0 * * REVISION HISTORY: * 6/2/03 jbp Initial version * ***********************************************************************/ uint32_t PilotMain(uint16_t launchCode, MemPtr pParams, uint16_t launchFlags) { // OS6NEW: New error type status_t error = errNone; // OS6NEW: Get app resource database ref - needed for Form Mgr calls, resources, etc. if ((error = SysGetModuleDatabase(SysGetRefNum(), NULL, &gAppResDB)) < errNone) return error; // Handle launch code switch (launchCode) { case sysAppLaunchCmdNormalLaunch: // Perform app initialization. error = AppStart(); if (error) return error; // OS6NEW: FrmGotoForm() now requires app db ref argument FrmGotoForm(gAppResDB, MainForm); // Handle events until user switches to another app. AppEventLoop(); // Clean up before exit. AppStop(); break; default: break; } return errNone; }