//////////////////////////////////////////////////////////////////////// // PalmJointMain.c // // main file for PalmJoint // // This wizard-generated code is based on code adapted from the // stationery files distributed as part of the Palm OS SDK 4.0. // // Copyright (c) 1999-2000 Palm, Inc. or its subsidiaries. // All rights reserved. //////////////////////////////////////////////////////////////////////// // Includes #include #include #include "PalmJoint.h" #include "PalmJointRsc.h" //////////////////////////////////////////////////////////////////////// // Global variables // g_prefs // cache for application preferences during program execution PalmJointPreferenceType g_prefs; // MainFormHandleEventThunk // holds callback thunk for main form event handler static _CW_CallbackThunk MainFormHandleEventThunk; static const int JointWidth = 45; static const int JointHeight = 160; static BitmapType *JointBitmap = NULL; static WinHandle JointWindow = NULL; static int JointFramesPerSecond = 10; static int JointTicksPerSecond = 30; static int JointLastFrameTime = 0; static int JointHere = 1; static int JointLit = 0; static float JointFatness = 0.7; static float JointTaper = 0.3; static float JointLeft = 1.0; static float JointCherry = 0.0; static float JointLightCherry = 0.02; static float JointMaxCherry = 0.15; static float JointAsh = 0.0; static float JointRoach = 0.2; static float JointBurnRate = 0.05; static float JointSlowRate = 0.01; static float JointMaxAsh = 0.15; static float JointWavePower = 0.1; static float JointPuffPower = 0.18; static float JointTokePower = 0.3; static int JointPuffing = 0; static int JointToking = 0; static int JointStubbing = 0; static int JointPassing = 0; static int JointAshing = 0; static int JointWaving = 0; static int JointSetup = 0; static unsigned char JointProfile[JointHeight]; IndexedColorType JointPaperColor; IndexedColorType JointCherryColor; IndexedColorType JointAshColor; //////////////////////////////////////////////////////////////////////// // Internal Constants // Define the minimum OS version we support #define ourMinVersion sysMakeROMVersion(3,0,0,sysROMStageDevelopment,0) #define kPalmOS10Version sysMakeROMVersion(1,0,0,sysROMStageRelease,0) //////////////////////////////////////////////////////////////////////// // Prototypes float sqrt( float value); static void *MyGetObjectPtr( FormPtr frm, int objectID); static void DrawJoint(); //////////////////////////////////////////////////////////////////////// // Utilities float sqrt( float value) { //return value; const float tol = // 0.000005; // relative error tolerance 0.01; // relative error tolerance float old_app, new_app; if (value <= tol) { return 0.0; } // if old_app = value; // take value as first approximation new_app = (old_app + (value / old_app)) / 2.0; while (1) { float f = (new_app - old_app) / new_app; if (f < 0.0) { f = -f; } // if if (f <= tol) { break; } // if old_app = new_app; new_app = (old_app + (value / old_app)) / 2.0; } // while return new_app; } static void *MyGetObjectPtr( FormPtr frm, int objectID) { return (FrmGetObjectPtr( frm, FrmGetObjectIndex( frm, objectID))); } //////////////////////////////////////////////////////////////////////// // Internal Functions static void MainFormInit(FormType * /*frmP*/) { } static Boolean MainFormDoCommand(UInt16 command) { Boolean handled = false; FormType * frmP; switch (command) { case OptionsAboutPalmJoint: // Clear the menu status from the display MenuEraseStatus(0); // Display the About Box. frmP = FrmInitForm (AboutForm); FrmDoDialog (frmP); FrmDeleteForm (frmP); handled = true; break; } return handled; } static void DrawJoint() { FormType *frm = FrmGetActiveForm(); // FormGadgetType *gad = // (FormGadgetType *)MyGetObjectPtr( // frm, // MainTrayGadget); RectangleType r2; r2.topLeft.x = 0; r2.topLeft.y = 0; r2.extent.x = JointWidth; r2.extent.y = JointHeight; WinHandle lastWin = WinGetDrawWindow(); WinSetDrawWindow( JointWindow); WinEraseRectangle( &r2, 0); if (JointWaving) { JointWaving = 0; if (JointLit) { JointCherry += (JointWavePower / (float)JointFramesPerSecond); } // if } // if if (JointPuffing) { JointPuffing = 0; if (JointLit) { JointCherry += (JointPuffPower / (float)JointFramesPerSecond); } else { if ((JointLeft - (JointAsh + JointCherry)) > JointRoach) { JointLit = 1; JointCherry = JointLightCherry; } // if } // if } // if if (JointToking) { JointToking = 0; if (JointLit) { JointCherry += (JointTokePower / (float)JointFramesPerSecond); } else { JointLeft = 1.0; JointCherry = 0.0; JointAsh = 0.0; JointLit = 0; } // if } // if if (JointAsh >= JointMaxAsh) { JointAshing = 1; } // if if (JointStubbing) { JointStubbing = 0; if (JointLit) { float stub = JointCherry / 2.0; JointAsh += stub; JointCherry -= stub; JointAshing = 1; // JointLit = 0; } // if } // if if (JointAshing) { JointAshing = 0; if (JointAsh > 0.0) { JointLeft -= JointAsh; JointAsh = 0.0; } // if } // if if (JointCherry >= JointMaxCherry) { JointCherry = JointMaxCherry; } // if if (JointLit) { float todo = (JointCherry * JointBurnRate) / ((float)JointFramesPerSecond); float slow = JointSlowRate / ((float)JointFramesPerSecond); JointAsh += (todo + slow); JointCherry -= slow; } // if if (JointCherry <= 0.0) { JointCherry = 0.0; JointLit = 0; } // if if ((JointLeft - (JointAsh + JointCherry)) <= JointRoach) { JointAsh += JointCherry; JointCherry = 0.0; JointLit = 0; } // if if (!JointLit) { JointToking = 0; JointWaving = 0; JointPuffing = 0; } // if if (JointPassing) { JointPassing--; } // if int y; int centerx = JointWidth / 2; int gap = 2; int topy = gap; int bottomy = JointHeight - gap; int dheight = bottomy - topy; int dwidth = (int)((float)JointWidth * JointFatness); if (!JointSetup) { JointSetup = 1; for (y = 0; y < dheight; y++) { float p = (float)y / ((float)(dheight - 1)); float pp = (1.0 - p); if (pp < 0.0) { pp = 0.0; } // if float q = JointFatness; if (p < JointTaper) { float r = p / JointTaper; r = sqrt(r); q = r * JointFatness; } else if (pp < JointTaper) { float r = pp / JointTaper; r = sqrt(r); q = r * JointFatness; } // if int fat = (int)(0.5 * q * dwidth); JointProfile[y] = fat; } // for y } // if WinPushDrawState(); for (y = 0; y < dheight; y++) { int fat = JointProfile[y]; int left = centerx - fat; int right = centerx + fat; float p = (float)y / ((float)(dheight - 1)); if (p < JointLeft) { float r = JointLeft - p; IndexedColorType color; if (r < JointAsh) { color = JointAshColor; } else if (r < (JointAsh + JointCherry)) { color = JointCherryColor; } else { color = JointPaperColor; } // if WinSetForeColor( color); WinDrawLine( left, y + topy, right, y + topy); } // if } // for y WinPopDrawState(); WinSetDrawWindow( lastWin); RectangleType r; r.topLeft.x = 160 - JointWidth; r.topLeft.y = 0; r.extent.x = JointWidth; r.extent.y = 160; WinDrawBitmap( JointBitmap, r.topLeft.x, r.topLeft.y); } static Boolean MainFormHandleEvent(EventType * eventP) { Boolean handled = false; FormType *frmP = FrmGetActiveForm(); switch (eventP->eType) { case menuEvent: return MainFormDoCommand(eventP->data.menu.itemID); case frmOpenEvent: MainFormInit(frmP); FrmDrawForm(frmP); DrawJoint(); handled = true; break; case frmUpdateEvent: // To do any custom drawing here, first call // FrmDrawForm(), then do your drawing, and // then set handled to true. FrmDrawForm(frmP); DrawJoint(); handled = true; break; default: break; } return handled; } static Boolean AppHandleEvent(EventType * eventP) { UInt16 formId; FormType *frmP; if (eventP->eType == frmLoadEvent) { // Load the form resource. formId = eventP->data.frmLoad.formID; frmP = FrmInitForm(formId); FrmSetActiveForm(frmP); // 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(frmP, (FormEventHandlerType *)&MainFormHandleEventThunk); break; default: break; } return true; } return false; } static void AppEventLoop(void) { UInt16 error; EventType event; JointTicksPerSecond = SysTicksPerSecond(); JointTicksPerSecond = 30; do { // change timeout if you need periodic nilEvents int ticksPerFrame = JointTicksPerSecond / JointFramesPerSecond; int now = TimGetTicks(); int elapsed = now - JointLastFrameTime; int togo = ticksPerFrame - elapsed; // if (togo <= 0) { DrawJoint(); JointLastFrameTime = now; togo = ticksPerFrame; // } // if togo = 1; EvtGetEvent(&event, togo); int ignoreSysEvent = 0; switch (event.eType) { case keyDownEvent: { int ch = event.data.keyDown.chr; switch (ch) { case vchrHard1: case vchrHard2: case vchrHard3: case vchrHard4: case vchrPageUp: case vchrPageDown: case vchrMenu: case vchrCalc: case vchrFind: case vchrPalmMin: // silkscreened clock button case vchrKeyboardAlpha: // silkscreened alpha keyboard button case vchrKeyboardNumeric: // silkscreened numeric keyboard button case vchrRonamatic: // magic stroke gesture { ignoreSysEvent = 1; switch (ch) { case vchrPageDown: { JointToking += JointFramesPerSecond; break; } // case case vchrPageUp: { JointPuffing += JointFramesPerSecond; break; } // case case vchrHard1: { JointStubbing += JointFramesPerSecond; break; } // case case vchrHard2: { JointPassing = JointFramesPerSecond; break; } // case case vchrHard3: { JointAshing = JointFramesPerSecond / 5; break; } // case case vchrHard4: { JointWaving = JointFramesPerSecond; break; } // case } // switch break; } // case #if 0 case vchrLaunch: { if (event.tapCount > 1) { event.tapCount--; } else { ignoreSysEvent = 1; } // if break; } // case #endif default: { break; } // case } // switch break; } // case default: { break; } // case } // switch if (ignoreSysEvent || (! SysHandleEvent(&event))) { if (! MenuHandleEvent(0, &event, &error)) { if (! AppHandleEvent(&event)) { FrmDispatchEvent(&event); } } } } while (event.eType != appStopEvent); } static Err AppStart(void) { UInt16 prefsSize; // Read the saved preferences / saved-state information. prefsSize = sizeof(PalmJointPreferenceType); if (PrefGetAppPreferences( appFileCreator, appPrefID, &g_prefs, &prefsSize, true) != noPreferenceFound) { // FIXME: setup g_prefs with default values } // Setup main form event handler callback thunk (needed for "expanded" mode) _CW_GenerateCallbackThunk(MainFormHandleEvent, &MainFormHandleEventThunk); UInt16 err; JointWindow = WinCreateOffscreenWindow( JointWidth, JointHeight, genericFormat, &err); if ((err != 0) || (!JointWindow)) { return 1; } // if JointBitmap = WinGetBitmap( JointWindow); if (JointBitmap == NULL) { return 1; } // if RGBColorType color; color.r = 120; color.g = 120; color.b = 120; JointPaperColor = WinRGBToIndex( &color); color.r = 255; color.g = 20; color.b = 20; JointCherryColor = WinRGBToIndex( &color); color.r = 20; color.g = 20; color.b = 20; JointAshColor = WinRGBToIndex( &color); return errNone; } static void AppStop(void) { if (JointWindow != NULL) { WinDeleteWindow( JointWindow, 0); JointWindow = NULL; JointBitmap = NULL; } // if #if 0 if (JointBitmap != NULL) { BmpDelete( JointBitmap); JointBitmap = NULL; } // if #endif // Write the saved preferences / saved-state information. This // data will be saved during a HotSync backup. PrefSetAppPreferences( appFileCreator, appPrefID, appPrefVersionNum, &g_prefs, sizeof(PalmJointPreferenceType), true); // Close all the open forms. FrmCloseAllForms(); } // all code from here to end of file should use no global variables #pragma warn_a5_access on static Err RomVersionCompatible(UInt32 requiredVersion, UInt16 launchFlags) { UInt32 romVersion; // See if we're on in minimum required version of the ROM or later. FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion); if (romVersion < requiredVersion) { if ((launchFlags & (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) == (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) { FrmAlert (RomIncompatibleAlert); // Palm OS 1.0 will continuously relaunch this app unless // we switch to another safe one. if (romVersion <= kPalmOS10Version) { AppLaunchWithCommand( sysFileCDefaultApp, sysAppLaunchCmdNormalLaunch, NULL); } } return sysErrRomIncompatible; } return errNone; } static UInt32 PalmJointPalmMain( UInt16 cmd, MemPtr /*cmdPBP*/, UInt16 launchFlags) { Err error; error = RomVersionCompatible (ourMinVersion, launchFlags); if (error) return (error); switch (cmd) { case sysAppLaunchCmdNormalLaunch: error = AppStart(); if (error) return error; // start application by opening the main form // and then entering the main event loop FrmGotoForm(MainForm); AppEventLoop(); AppStop(); break; default: break; } return errNone; } UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) { return PalmJointPalmMain(cmd, cmdPBP, launchFlags); } // turn a5 warning off to prevent it being set off by C++ // static initializer code generation #pragma warn_a5_access reset ////////////////////////////////////////////////////////////////////////