home *** CD-ROM | disk | FTP | other *** search
/ PC World 2002 July & August / PCWorld_2002-07-08_cd.bin / Software / Vyzkuste / batterypanel / source / main.c < prev    next >
C/C++ Source or Header  |  2000-10-11  |  29KB  |  1,055 lines

  1. //=============================================================================
  2. // $Id$
  3. //=============================================================================
  4.  
  5. /*
  6. Copyright (C) 2000 Remo Hofer <cocos.nucifera@gmx.net>
  7. For more information see http://www.geocities.com/SiliconValley/Cable/5206/
  8.  
  9. This program is free software; you can redistribute it and/or
  10. modify it under the terms of the GNU General Public License
  11. as published by the Free Software Foundation; either version 2
  12. of the License, or (at your option) any later version.
  13.  
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  22. */
  23.  
  24. // include header
  25.  
  26. #include <PalmOS.h>
  27. #include "callback.h"
  28. #include "rsrc.h"
  29. #include "rsrcfix.h"
  30.  
  31. /*
  32.  *    DEBUG >= 2    Include code for silent errorcheck. Does only interact with 
  33.  *                the user in the case of an error. 
  34.  *    DEBUG >= 4    Include code for silent logging to the emulator log.
  35.  *    DEBUG >= 6    Include code that may interact with (display info to) the 
  36.  *                user without making the program unusable.
  37.  *    DEBUG >= 8    Include code that may make the program almost unuseable.
  38.  */
  39. #define DEBUG 4
  40.  
  41. #define PalmOS20            sysMakeROMVersion(2,0,0,sysROMStageRelease,0)
  42. #define PalmOS30            sysMakeROMVersion(3,0,0,sysROMStageRelease,0)
  43. #define PalmOS31            sysMakeROMVersion(3,1,0,sysROMStageRelease,0)
  44. #define PalmOS32            sysMakeROMVersion(3,2,0,sysROMStageRelease,0)
  45. #define PalmOS33            sysMakeROMVersion(3,3,0,sysROMStageRelease,0)
  46.  
  47. #define Creator                'Bttr'
  48. #define PrefsId                0
  49. #define PrefsVersion        1
  50. #define MinRequiredVersion    PalmOS20
  51. #define RefreshDelay        (SysTicksPerSecond())        /* 1 second */
  52. #define RepeatDelay            (SysTicksPerSecond() / 5)    /* 0.2 seconds */
  53.  
  54. // defaults
  55.  
  56. #define DefaultAlkalineWarn            200
  57. #define DefaultAlkalineCritical        160
  58. #define DefaultLiIonWarn            376
  59. #define DefaultLiIonCritical        371
  60. #define DefaultLiIon1400Warn        364
  61. #define DefaultLiIon1400Critical    200
  62.  
  63. typedef enum {
  64.     initValues,
  65.     redrawForm,
  66.     testValues
  67. } FormUpdateReason;
  68.  
  69. typedef struct {
  70. //    SysBatteryKind    kind;
  71.     UInt16            warn;
  72.     UInt16            critical;
  73.     Boolean            acceptRisk;
  74. } PrefsType;
  75.  
  76. // globals
  77.  
  78. static Boolean                calledFromApp = false;
  79. static SysDBListItemType    *panelIDsP = NULL;    // ptr to panel pick list items
  80.  
  81. static UInt16                oldVoltage, oldWarn, oldCritical, oldTimeout,
  82.                             dialogVoltage, dialogMin, dialogMax;
  83. static UInt8                oldPercent;
  84. static Boolean                oldPlugged;
  85. static SysBatteryKind        oldKind;
  86. static Coord                oldLevel;
  87. static Char                    s[64];
  88. static Char                    decimalPoint[2];
  89. static SysBatteryKind        indexToKind[4] = { 
  90.     sysBatteryKindAlkaline, sysBatteryKindNiCad, 
  91.     sysBatteryKindRechAlk, sysBatteryKindNiMH };
  92. static UInt16                kindToIndex[5] = { 0, 1, 0xFF, 2, 3 };
  93.  
  94. //-----------------------------------------------------------------------------
  95. static UInt32 GetRomVersion(void) {
  96.     UInt32    romVersion;
  97.     
  98.     FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
  99.     return(romVersion);
  100. }
  101.  
  102. //-----------------------------------------------------------------------------
  103. #if DEBUG >= 4
  104. #include <stdarg.h>
  105. #include "gccHostControl.h"
  106.  
  107. void EmulatorLog(Char * format,...) {
  108.     va_list    args;
  109.     UInt32    dummy;
  110.     Char    s[64];
  111.     
  112.     va_start(args, format);
  113.     StrVPrintF(s, format, args);
  114.     va_end(args);
  115.  
  116.     if ((GetRomVersion() >= PalmOS30) && (FtrGet('pose', 0, &dummy) == 0)) {
  117.         HostFPutS(s, HostLogFile());
  118.     }
  119.     
  120. #if DEBUG >= 8
  121.     WinDrawChars(s, StrLen(s), 0, 0);
  122. #endif
  123.  
  124. }
  125. #endif
  126.  
  127. //-----------------------------------------------------------------------------
  128. static void * FormGetObjectPtr(FormType * formP, UInt16 objId) {
  129.         
  130. #if DEBUG >= 4
  131.     EmulatorLog("FormGetObjectPtr");
  132. #endif
  133.  
  134.     return (FrmGetObjectPtr(formP, FrmGetObjectIndex(formP, objId)));
  135. }
  136.  
  137. //-----------------------------------------------------------------------------
  138. static void FormShowObject(FormType * formP, UInt16 objId) {
  139.         
  140. #if DEBUG >= 4
  141.     EmulatorLog("FormShowObject");
  142. #endif
  143.  
  144.     FrmShowObject(formP, FrmGetObjectIndex(formP, objId));
  145. }
  146.  
  147. //-----------------------------------------------------------------------------
  148. static void FormHideObject(FormType * formP, UInt16 objId) {
  149.         
  150. #if DEBUG >= 4
  151.     EmulatorLog("FormHideObject");
  152. #endif
  153.  
  154.     FrmHideObject(formP, FrmGetObjectIndex(formP, objId));
  155. }
  156.  
  157. //-----------------------------------------------------------------------------
  158. static void PanelFreeData(void) {
  159.         
  160. #if DEBUG >= 4
  161.     EmulatorLog("PanelFreeData");
  162. #endif
  163.  
  164.     if (panelIDsP) {
  165.         MemPtrFree(panelIDsP);
  166.         panelIDsP = NULL;
  167.     }
  168. }
  169.             
  170. //-----------------------------------------------------------------------------
  171. static void PanelDone(void) {
  172.     EventType        newEvent;
  173.     
  174. #if DEBUG >= 4
  175.     EmulatorLog("PanelDone");
  176. #endif
  177.  
  178.     // by simply exiting we return to the prior which called us
  179.     MemSet(&newEvent, sizeof(EventType), 0);
  180.     newEvent.eType = appStopEvent;
  181.     EvtAddEventToQueue(&newEvent);
  182. }
  183.  
  184. //-----------------------------------------------------------------------------
  185. static void PanelSelect(UInt16 index) {
  186.       UInt16        currentAppCardNo;
  187.     LocalID        currentAppDBID;
  188.     
  189. #if DEBUG >= 4
  190.     EmulatorLog("PanelSelect");
  191. #endif
  192.  
  193.     if (panelIDsP) {
  194.         
  195.         // Switch to the panel if it isn't this one
  196.         SysCurAppDatabase(¤tAppCardNo, ¤tAppDBID);
  197.  
  198.         if ((panelIDsP[index].dbID != currentAppDBID) ||
  199.           (panelIDsP[index].cardNo != currentAppCardNo)) {
  200.             SysUIAppSwitch(
  201.               panelIDsP[index].cardNo, panelIDsP[index].dbID, 
  202.               sysAppLaunchCmdNormalLaunch, 0);
  203.         }
  204.     }
  205. }
  206.  
  207. //-----------------------------------------------------------------------------
  208. static void PanelDrawItem(Int16 itemNum, RectanglePtr bounds, Char ** dummy) {
  209.     Char * itemText;
  210.     
  211.     CALLBACK_PROLOGUE
  212.     
  213. #if DEBUG >= 4
  214.     EmulatorLog("PanelDrawItem");
  215. #endif
  216.  
  217.     if (panelIDsP) {
  218.         itemText = panelIDsP[itemNum].name;
  219.         WinDrawChars(itemText, StrLen(itemText), 
  220.           bounds->topLeft.x, bounds->topLeft.y);
  221.     }
  222.  
  223.     CALLBACK_EPILOGUE
  224. }
  225.  
  226. //-----------------------------------------------------------------------------
  227. // Create a list of panels available and select the current one.
  228. // panelIDsP is set.
  229. static void PanelInit(Boolean calledFromApp, FormPtr f, 
  230.   UInt16 idPopup, UInt16 idList, UInt16 idLabel, UInt16 idDone) {
  231.  
  232. #if DEBUG >= 4
  233.     EmulatorLog("PanelInit");
  234. #endif
  235.  
  236.     if (calledFromApp) {
  237.         // hide panel popup and show done button
  238.         
  239.         FormShowObject(f, idLabel);
  240.         FormShowObject(f, idDone);
  241.         
  242.     } else {
  243.         // create panel list and show popup trigger
  244.         
  245.         ListPtr        listP;
  246.           UInt16        currentAppCardNo;
  247.         LocalID        currentAppDBID;
  248.         MemHandle    panelIDsH;    // MemHandle to pick list items
  249.         UInt16        panelCount, i;
  250.         PrefActivePanelParamsType prefs;
  251.         
  252.         // create the panel list data
  253.         if (SysCreatePanelList(&panelCount, &panelIDsH)) {
  254.     
  255.             panelIDsP = MemHandleLock(panelIDsH);
  256.     
  257.             listP = FormGetObjectPtr(f, idList);
  258.         
  259.             // Now set the list to hold the number of panels found.  There
  260.             // is no array of text to use.
  261.             LstSetListChoices(listP, NULL, panelCount);
  262.     
  263.             // Now resize the list to the number of panel found
  264.             LstSetHeight(listP, panelCount);
  265.     
  266.             // Because there is no array of text to use, we need a function
  267.             // to interpret the panelIDsP list and draw the list items.
  268.             LstSetDrawFunction(listP, PanelDrawItem);
  269.     
  270.             // Now we should select the item in the list which matches the 
  271.             // current app.
  272.             SysCurAppDatabase(¤tAppCardNo, ¤tAppDBID);
  273.             for (i = 0; i < panelCount; i++) {
  274.                 if (panelIDsP[i].dbID == currentAppDBID &&
  275.                   panelIDsP[i].cardNo == currentAppCardNo) {
  276.                     LstSetSelection(listP, i);
  277.                     CtlSetLabel(
  278.                       FormGetObjectPtr(f, idPopup), 
  279.                       panelIDsP[i].name);
  280.                     break;
  281.                 }
  282.             }
  283.               
  284.             // draw the popup trigger 
  285.             FormShowObject(f, idPopup);
  286.  
  287.             // set this panel as the active one next time the 
  288.             // Prefs app is opened
  289.             prefs.activePanel = Creator;
  290.             AppCallWithCommand(sysFileCPreferences, 
  291.               prefAppLaunchCmdSetActivePanel, &prefs);
  292.         }
  293.     }
  294. }
  295.  
  296. //-----------------------------------------------------------------------------
  297. static UInt16 GlueSysBatteryInfo(Boolean set, UInt16 * warnThresholdP, 
  298.   UInt16 *criticalThresholdP, Int16 *maxTicksP, SysBatteryKind* kindP, 
  299.   Boolean *pluggedIn, UInt8 *percentP) {
  300.     UInt16    result;
  301.  
  302. #if DEBUG >= 4
  303.     EmulatorLog("GlueSysBatteryInfo");
  304. #endif
  305.  
  306.     if (GetRomVersion() >= PalmOS30) {
  307.         return (SysBatteryInfo(set, warnThresholdP, criticalThresholdP, 
  308.           maxTicksP, kindP, pluggedIn, percentP));
  309.     } else {
  310.         result = SysBatteryInfoV20(set, warnThresholdP, criticalThresholdP,
  311.           maxTicksP, kindP, pluggedIn);
  312.         if ((!set) && (percentP != NULL)) {
  313.             // interpolate between 205 and 280
  314.             // values are taken (more or less) from the alkaline table
  315.             // in the PalmOS 3.0 source (ignoring the top and low 10%)
  316.             *percentP = min(((max(result,205)-205) * 100 + (280-205)/2) 
  317.               / (280-205), 100);
  318.         }
  319.         return (result);
  320.     }
  321. }
  322.  
  323. //-----------------------------------------------------------------------------
  324. static void UpdatePopup(FormPtr f, UInt16 popupId, UInt16 listId, 
  325.   UInt16 index) {
  326.  
  327. #if DEBUG >= 4
  328.     EmulatorLog("UpdatePopup");
  329. #endif
  330.  
  331.     CtlSetLabel(
  332.       FormGetObjectPtr(f, popupId), 
  333.       LstGetSelectionText(FormGetObjectPtr(f, listId), index));
  334. }  
  335.      
  336. //-----------------------------------------------------------------------------
  337. void UpdateControl(FormPtr f, UInt16 id, Char * s) {
  338.     ControlType    *ctl;
  339.     Char        *label;
  340.  
  341. #if DEBUG >= 4
  342.     EmulatorLog("UpdateControl");
  343. #endif
  344.  
  345.     ctl = FormGetObjectPtr(f, id),
  346.     label = (Char *) CtlGetLabel(ctl);
  347.     StrCopy(label, s);
  348.     CtlSetLabel(ctl, label);
  349. }
  350. //-----------------------------------------------------------------------------
  351. static void UpdateLabel(FormPtr f, UInt16 id, Char * s) {
  352.  
  353. #if DEBUG >= 4
  354.     EmulatorLog("UpdateLabel");
  355. #endif
  356.  
  357.     FormHideObject(f, id);
  358.     FrmCopyLabel(f, id, s);
  359.     FormShowObject(f, id);
  360. }
  361.  
  362. //-----------------------------------------------------------------------------
  363. static void UpdateButton(FormPtr f, UInt16 id, 
  364.   Boolean enabled, Boolean up) {
  365.     ControlType    *ctl;
  366.     
  367.     ctl = FormGetObjectPtr(f, id);
  368.     if (CtlEnabled(ctl) != enabled) {
  369.         CtlSetEnabled(ctl, enabled);
  370.         if (up) { if (enabled) StrCopy(s, "\001"); else StrCopy(s, "\003"); }
  371.           else { if (enabled) StrCopy(s, "\002"); else StrCopy(s, "\004"); }
  372.         UpdateLabel(f, id, s);
  373.     }
  374. }
  375.  
  376. //-----------------------------------------------------------------------------
  377. static void VoltageToA(Char * s, UInt16 v) {
  378.  
  379. #if DEBUG >= 4
  380.     EmulatorLog("VoltageToA");
  381. #endif
  382.  
  383.     StrPrintF(s, "%u%s%u%u V", v/100, decimalPoint, (v/10)%10, v%10);
  384. }
  385.  
  386. //-----------------------------------------------------------------------------
  387. static void UpdateForm(FormPtr f, FormUpdateReason reason) {
  388.     UInt16                voltage, warn, critical, timeout, index;
  389.     UInt8                percent;
  390.     Boolean                plugged, changeable;
  391.     SysBatteryKind        kind;
  392.     RectangleType        r1, r2, save;
  393.     Coord                full, level, x, y;
  394.     MemHandle            h;
  395.  
  396. #if DEBUG >= 4
  397.     EmulatorLog("UpdateForm");
  398. #endif
  399.  
  400.     // get the data
  401.     voltage = GlueSysBatteryInfo(false, &warn, &critical, 
  402.       &timeout, &kind, &plugged, &percent);
  403.  
  404.     // update the percentage
  405.      if ((oldPercent != percent) || (reason == initValues)) {
  406.         oldPercent = percent;
  407.         StrIToA(s, percent);    // implicit typecast!
  408.         StrCat(s, "%");
  409.         UpdateLabel(f, idPercentLabel, s);
  410.     }
  411.         
  412.     // update graphical battery display, either when the level changed,
  413.     // or when we got an update event
  414.     FrmGetObjectBounds(f, FrmGetObjectIndex(f, idBitmapBounds), &r1);
  415.     full = r1.extent.x;
  416.     level = min(((((full-4)*percent)+50)/100)+1, full-3); // 1 <-> (full-3)
  417.     if (FrmVisible(f) && ((reason == redrawForm) || (oldLevel != level))) {
  418.         oldLevel = level;
  419.         WinGetClip(&save);
  420.         RctCopyRectangle(&r1, &r2);
  421.         x = r1.topLeft.x;
  422.         y = r1.topLeft.y;
  423.         // draw full part of display
  424.         if (level > 0) {
  425.             r1.extent.x = level;
  426.             WinClipRectangle(&r1);
  427.             WinSetClip(&r1);
  428.             h = DmGetResource(bitmapRsc, idFullBitmap);
  429.             WinDrawBitmap(MemHandleLock(h), x, y);
  430.             MemHandleUnlock(h);
  431.             DmReleaseResource(h);
  432.             WinSetClip(&save);
  433.         }
  434.         // draw empty part of display
  435.         r2.topLeft.x = x + level;
  436.         r2.extent.x = full - level;
  437.         if (r2.extent.x > 0) {
  438.             WinClipRectangle(&r2);
  439.             WinSetClip(&r2);
  440.             h = DmGetResource(bitmapRsc, idEmptyBitmap);
  441.             WinDrawBitmap(MemHandleLock(h), x, y);
  442.             MemHandleUnlock(h);
  443.               DmReleaseResource(h);
  444.           }
  445.         WinSetClip(&save);
  446.     }
  447.  
  448.     // update the voltage
  449.     if ((oldVoltage != voltage) || (reason == initValues)) {
  450.         oldVoltage = voltage;
  451.         VoltageToA(s, voltage);
  452.         UpdateLabel(f, idVoltageLabel, s);
  453.     }
  454.     
  455.     // update the battery kind
  456.     if ((oldKind != kind) || (reason == initValues)) {
  457.         oldKind = kind;
  458.         switch (kind) {
  459.           case sysBatteryKindAlkaline:
  460.           case sysBatteryKindNiCad:
  461.           case sysBatteryKindRechAlk:
  462.           case sysBatteryKindNiMH:
  463.             changeable = true;
  464.             index = kindToIndex[kind];
  465.             break;            
  466.           case sysBatteryKindLiIon:
  467.             changeable = false;
  468.             index = idLiIonKindStr;
  469.             break;
  470.           case sysBatteryKindLiIon1400:
  471.             changeable = false;
  472.             index = idLiIon1400KindStr;
  473.             break;
  474.           default:
  475.             changeable = false;
  476.             index = idUnknownKindStr;
  477.             break;
  478.         }        
  479.         if (changeable) {
  480.             FormHideObject(f, idKindLabel);
  481.             UpdatePopup(f, idKindPopup, idKindList, index);
  482.             FormShowObject(f, idKindPopup);
  483.         } else {
  484.             FormHideObject(f, idKindPopup);
  485.             SysCopyStringResource(s, index);
  486.             UpdateLabel(f, idKindLabel, s);
  487.             FormShowObject(f, idKindLabel);
  488.         }
  489.     }
  490.  
  491.     // update plugged in
  492.     if ((oldPlugged != plugged) || (reason == initValues)) {
  493.         oldPlugged = plugged;
  494.         if (plugged) SysCopyStringResource(s, idYesStr);
  495.           else  SysCopyStringResource(s, idNoStr);
  496.         UpdateLabel(f, idPluggedLabel, s);
  497.     }
  498.  
  499.     // update warning threshold
  500.     if ((oldWarn != warn) || (reason == initValues)) {
  501.         oldWarn = warn;
  502.         VoltageToA(s, warn);
  503.         UpdateControl(f, idWarnSelector, s);
  504.     }
  505.  
  506.     // update critical threshold
  507.     if ((oldCritical != critical) || (reason == initValues)) {
  508.         oldCritical = critical;
  509.         VoltageToA(s, critical);
  510.         UpdateControl(f, idCriticalSelector, s);
  511.     }
  512.  
  513.     // update warning timeout
  514.     if ((oldTimeout != timeout) || (reason == initValues)) {
  515.         oldTimeout = timeout;
  516.         StrPrintF(s, "%u s", timeout / SysTicksPerSecond());
  517.         UpdateLabel(f, idTicksLabel, s);
  518.     }
  519.  
  520. }
  521.  
  522. //-----------------------------------------------------------------------------
  523. static Boolean PopupList(UInt16 * value, 
  524.   FormPtr f, UInt16 triggerId, UInt16 listId) {
  525.     Int16    newi, oldi;
  526.     ListPtr    list;
  527.     Coord    x, y;
  528.  
  529. #if DEBUG >= 4
  530.     EmulatorLog("PopupList");
  531. #endif
  532.  
  533.     list = FormGetObjectPtr(f, listId);
  534.     FrmGetObjectPosition(f, FrmGetObjectIndex(f, triggerId), &x, &y);
  535.     LstSetPosition(list, x, y);
  536.     oldi =  *value;
  537.     LstSetSelection(list, oldi);
  538.     newi = LstPopupList(list);
  539.     if ((newi >= 0) && (newi != oldi)) {
  540.         *value = newi;
  541.         UpdatePopup(f, triggerId, listId, *value);
  542.         return (true);
  543.     }
  544.     return (false);
  545. }
  546.  
  547. //-----------------------------------------------------------------------------
  548. // no globals
  549. static void InitPrefs(PrefsType * p) {
  550.     
  551. #if DEBUG >= 4
  552.     EmulatorLog("InitPrefs");
  553. #endif
  554.  
  555. //    p->kind = sysBatteryKindAlkaline;
  556.     p->warn = 0;
  557.     p->critical = 0;
  558.     p->acceptRisk = false;
  559. }
  560.  
  561. //-----------------------------------------------------------------------------
  562. // no globals
  563. static Boolean LoadPrefs(PrefsType * p) {
  564.     UInt16        size;
  565.     UInt16        version;
  566.  
  567. #if DEBUG >= 4
  568.     EmulatorLog("LoadPrefs");
  569. #endif
  570.  
  571.     size = sizeof(PrefsType);
  572.     version = PrefGetAppPreferences(Creator, PrefsId,  p, &size, true);
  573.     if ((version != PrefsVersion) || (size != sizeof(PrefsType))) {
  574.         InitPrefs(p);
  575.         return (false);
  576.     }
  577.     return (true);
  578. }
  579.  
  580. //-----------------------------------------------------------------------------
  581. // no globals
  582. static void SavePrefs(Boolean setRisk, Boolean acceptRisk) {
  583.     PrefsType        p;
  584.     SysBatteryKind    kind, prefkind;
  585.     UInt16            warn;
  586.     UInt16            critical;
  587.  
  588. #if DEBUG >= 4
  589.     EmulatorLog("SavePrefs");
  590. #endif
  591.  
  592.     GlueSysBatteryInfo(false, &warn, &critical, NULL, &kind, NULL, NULL);
  593.  
  594.     LoadPrefs(&p);
  595.     // only write prefs, if something has changed
  596.     if (/*(p.kind != kind) ||*/ (p.warn != warn) || (p.critical != critical) || 
  597.       (setRisk && (p.acceptRisk != acceptRisk))) {
  598. //        p.kind = kind;
  599.         p.warn = warn;
  600.         p.critical = critical;
  601.         if (setRisk) p.acceptRisk = acceptRisk;
  602.         PrefSetAppPreferences(Creator, PrefsId, PrefsVersion, 
  603.           &p, sizeof(PrefsType), true);    
  604.     }
  605.     
  606.     // save the battery kind in the system preferences
  607.     prefkind = (SysBatteryKind) PrefGetPreference(prefSysBatteryKind);
  608.     if (prefkind != kind) {
  609.         PrefSetPreference(prefSysBatteryKind, (SysBatteryKind) kind);
  610.     }
  611.  
  612.     
  613. }
  614.         
  615. //-----------------------------------------------------------------------------
  616. static Boolean WarnUserRisk(void) {
  617.     PrefsType    prefs;
  618.     
  619. #if DEBUG >= 4
  620.     EmulatorLog("WarnUserRisk");
  621. #endif
  622.  
  623.     LoadPrefs(&prefs);
  624.     if (prefs.acceptRisk) return (true);
  625.     if (FrmAlert(idUserRiskAlert) == 0) {
  626.         SavePrefs(true, true);
  627.         return (true);
  628.     }
  629.     return (false);
  630. }
  631.  
  632. //-----------------------------------------------------------------------------
  633. static void UpdateVoltageDialog(FormPtr f) {
  634.  
  635.     StrIToA(s, dialogVoltage / 100);
  636.     UpdateLabel(f, idVoltage100Button, s);
  637.     StrIToA(s, (dialogVoltage / 10) % 10);
  638.     UpdateLabel(f, idVoltage10Button, s);
  639.     StrIToA(s, dialogVoltage % 10);
  640.     UpdateLabel(f, idVoltage1Button, s);
  641. }
  642.  
  643. //-----------------------------------------------------------------------------
  644. static Boolean VoltageDialogHandleEvent(EventPtr event) {
  645.     FormPtr            formPtr;
  646.     Int16            delta, newvalue;
  647.     
  648.     CALLBACK_PROLOGUE
  649.     
  650. #if DEBUG >= 4
  651.     EmulatorLog("VoltageDialogHandleEvent: %u", event->eType);
  652. #endif
  653.  
  654.     formPtr = FrmGetFormPtr(idVoltageForm);
  655.         
  656.     switch (FrmGetObjectId(formPtr,
  657.       FrmGetControlGroupSelection(formPtr, idVoltageGroup))) {
  658.         case idVoltage100Button:
  659.           delta = 100;
  660.          break;
  661.         case idVoltage10Button:
  662.           delta = 10;
  663.           break;
  664.         default:
  665.           delta = 1;
  666.       }
  667.       
  668.       // handle the buton up / down events (but return false)
  669.     if  (event->eType == ctlRepeatEvent) {
  670.         event->data.ctlRepeat.time += RepeatDelay;
  671.         if (event->data.ctlRepeat.controlID == idVoltageDownButton) {
  672.             newvalue = dialogVoltage - delta;
  673.             if (newvalue >= dialogMin) {
  674.                 dialogVoltage = newvalue;
  675.                 UpdateVoltageDialog(formPtr);
  676.             }
  677.         } else if (event->data.ctlRepeat.controlID == idVoltageUpButton) {
  678.             newvalue = dialogVoltage + delta;
  679.             if (newvalue <= dialogMax) {
  680.                 dialogVoltage = newvalue;
  681.                 UpdateVoltageDialog(formPtr);
  682.             }
  683.         }
  684.     }
  685.  
  686.       // enable or disable the up button
  687.       UpdateButton(formPtr, idVoltageUpButton, 
  688.         (dialogVoltage+delta <= dialogMax), true);
  689.       UpdateButton(formPtr, idVoltageDownButton,
  690.         (dialogVoltage >= dialogMin+delta), false);
  691.       
  692.     CALLBACK_EPILOGUE
  693.     return (false);
  694. }
  695.  
  696. //-----------------------------------------------------------------------------
  697. static Boolean VoltageDialog(UInt16 * volts, UInt16 min, UInt16 max,
  698.   UInt16 titleId) {
  699.     FormPtr    formPtr;
  700.  
  701. #if DEBUG >= 4
  702.     EmulatorLog("VoltageDialog");
  703. #endif
  704.  
  705.     dialogVoltage = *volts;
  706.     dialogMin = min;
  707.     dialogMax = max(max, *volts);
  708.     
  709.     formPtr = FrmInitForm(idVoltageForm);
  710.     FrmSetEventHandler(formPtr, VoltageDialogHandleEvent);
  711.     FrmSetControlGroupSelection(formPtr, idVoltageGroup, idVoltage1Button);
  712.     SysCopyStringResource(s, titleId);
  713.     FrmCopyTitle(formPtr, s);
  714.     UpdateLabel(formPtr, idVoltageSeparatorLabel, decimalPoint);
  715.     UpdateVoltageDialog(formPtr);
  716.     
  717.     if (FrmDoDialog(formPtr) == idVoltageOkButton) {
  718.  
  719.         FrmDeleteForm(formPtr);
  720.         if (dialogVoltage != *volts) {
  721.             *volts = dialogVoltage;
  722.             return (true);
  723.         } else {
  724.             return (false);
  725.         }
  726.     }
  727.     
  728.     FrmDeleteForm(formPtr);
  729.     return (false);
  730. }
  731.  
  732. //-----------------------------------------------------------------------------
  733. static Boolean MainFormHandleEvent(EventPtr event) {
  734.     FormPtr            formPtr;
  735.     MemHandle        h;
  736.     SysBatteryKind    kind;
  737.     UInt32            romVersion;
  738.     UInt16            index;
  739.     UInt16            warn, critical, voltage;
  740.     ListPtr            list;
  741.     Boolean            reducedList;
  742.     Boolean            handled = false;
  743.     
  744.     CALLBACK_PROLOGUE
  745.     
  746. #if DEBUG >= 4
  747.     EmulatorLog("MainFormHandleEvent: %u", event->eType);
  748. #endif
  749.  
  750.     formPtr = FrmGetFormPtr(idMainForm);
  751.  
  752.     switch (event->eType) {
  753.  
  754.       case frmOpenEvent:
  755.         // init all form elements
  756.         UpdateForm(formPtr, initValues);
  757.         // setup the version string
  758.           h = DmGetResource(verRsc, idVersion);
  759.         FrmCopyLabel(formPtr, idVersionLabel, MemHandleLock(h));
  760.           MemHandleUnlock(h);
  761.           DmReleaseResource(h);
  762.          // draw the form
  763.         FrmDrawForm(formPtr);
  764.         // update the image display (draw the battery icon)
  765.         UpdateForm(formPtr, redrawForm);
  766.         
  767.         // Now that the form is displayed, generate the panel pick list.
  768.         // By occuring here after everything is displayed the time required
  769.         // isn't noticed by the user.
  770.         PanelInit(calledFromApp, formPtr, idPanelPopup, idPanelList, 
  771.           idPanelLabel, idDoneButton);
  772.         handled = true;
  773.         break;
  774.         
  775.       case frmUpdateEvent:
  776.         FrmDrawForm(formPtr);
  777.         UpdateForm(formPtr, redrawForm);
  778.         handled = true;
  779.         break;
  780.         
  781.       case frmCloseEvent:
  782.         PanelFreeData();
  783.         SavePrefs(false, false);
  784.         // handled = false; // give std form handler a chance to cleanup
  785.         break;
  786.         
  787.       case nilEvent:
  788.         // update all form elements
  789.         UpdateForm(formPtr, testValues);
  790.         // handled = false;
  791.         break;        
  792.         
  793.       case menuEvent:
  794.         switch (event->data.menu.itemID) {
  795.           case idDefaultMenu:
  796.             // reset prefs to defaults
  797.             GlueSysBatteryInfo(false, NULL, NULL, NULL, &kind, NULL, NULL);
  798.             // get the defaults depending of battery kind
  799.             switch (kind) {
  800.               case sysBatteryKindLiIon:
  801.                 warn        = DefaultLiIonWarn;
  802.                 critical    = DefaultLiIonCritical;
  803.                 break;
  804.               case sysBatteryKindLiIon1400:
  805.                 warn        = DefaultLiIon1400Warn;
  806.                 critical    = DefaultLiIon1400Critical;
  807.                 break;
  808.               default:
  809.                 kind        = sysBatteryKindAlkaline;
  810.                 warn        = DefaultAlkalineWarn;
  811.                 critical    = DefaultAlkalineCritical;
  812.                 break;
  813.             }
  814.             // change to default levels
  815.             GlueSysBatteryInfo(true, &warn, &critical, NULL,NULL,NULL,NULL);
  816.             // change to default kind; this may as well reset the levels
  817.             GlueSysBatteryInfo(true, NULL,NULL,NULL, &kind, NULL,NULL);
  818.             // reset the acceptRisk state
  819.             SavePrefs(true, false);
  820.             // update the form
  821.             UpdateForm(formPtr, testValues);
  822.             handled = true;
  823.             break;
  824.           case idThanksMenu:
  825.             // show about form
  826.             FrmHelp(idThanksStr);
  827.             handled = true;
  828.             break;
  829.           case idAboutMenu:
  830.             // show about form
  831.             FrmHelp(idAboutStr);
  832.             handled = true;
  833.             break;
  834.         }
  835.         break;
  836.  
  837.       case ctlSelectEvent:
  838.         // one of the controls (popup/selector trigger) is selected
  839.         switch (event->data.ctlSelect.controlID) {
  840.           case idKindPopup:
  841.             GlueSysBatteryInfo(false, NULL, NULL, NULL, &kind, NULL, NULL);
  842.             index = min(kindToIndex[kind], 3);
  843.             list = FormGetObjectPtr(formPtr, idKindList);
  844.             reducedList = false;
  845.             romVersion = GetRomVersion();
  846.             if (romVersion < PalmOS33) {
  847.                 if ((romVersion < PalmOS32) && (romVersion >= PalmOS31)) {
  848.                     // OS 3.1 with Alkaline, NiCad, and Rech. Alkaline
  849.                     LstSetListChoices(list, list->itemsText, 3);
  850.                     LstSetHeight(list, 3);
  851.                     index = min(kindToIndex[kind], 2);
  852.                     reducedList = true;
  853.                 } else {
  854.                     // old OS (2.0 3.0 3.2) with only Alkaline and NiCad
  855.                     LstSetListChoices(list, list->itemsText, 2);
  856.                     LstSetHeight(list, 2);
  857.                     index = min(kindToIndex[kind], 1);
  858.                     reducedList = true;
  859.                 }
  860.             }
  861.             // new OS (>=3.3) with Alkaline, NiCad, Rech. Alkaline, and NiMH
  862.             if (PopupList(&index, formPtr, idKindPopup, idKindList)) {
  863.                 kind = indexToKind[index];
  864.                 GlueSysBatteryInfo(true, NULL,NULL,NULL, &kind, NULL,NULL);
  865.                 UpdateForm(formPtr, testValues);
  866.             }
  867.             if (reducedList) {
  868.                 // restore the list
  869.                 LstSetListChoices(list, list->itemsText, 4);
  870.                 LstSetHeight(list, 4);
  871.             }
  872.             handled = true;
  873.             break;
  874.           case idWarnSelector:
  875.           case idCriticalSelector:
  876.             if (event->data.ctlSelect.controlID == idCriticalSelector) {
  877.                 voltage = GlueSysBatteryInfo(false, NULL, &warn, 
  878.                   NULL, NULL, NULL, NULL);
  879.                 index = idSetCriticalStr;
  880.             } else {
  881.                 voltage = GlueSysBatteryInfo(false, &warn, 
  882.                   NULL, NULL, NULL, NULL, NULL);
  883.                 index = idSetWarnStr;
  884.             }
  885.             if (WarnUserRisk()) {
  886. //???                if (VoltageDialog(&warn, 0, voltage-2, index)) {
  887.                 if (VoltageDialog(&warn, 0, 1500, index)) {
  888.                     if (event->data.ctlSelect.controlID == idCriticalSelector){
  889.                         GlueSysBatteryInfo(true, NULL, &warn, 
  890.                           NULL, NULL, NULL, NULL);
  891.                     } else {
  892.                         GlueSysBatteryInfo(true, &warn, 
  893.                           NULL, NULL, NULL, NULL, NULL);
  894.                     }
  895.                     UpdateForm(formPtr, testValues);
  896.                 }
  897.             }
  898.             handled = true;
  899.             break;
  900.           case idDoneButton:
  901.             // if calledFromApp this is the way to end the program
  902.             PanelDone();
  903.             handled = true;
  904.             break;
  905.         }
  906.         break;
  907.  
  908.       case popSelectEvent:
  909.         switch (event->data.popSelect.listID) {
  910.           case idPanelList:
  911.             // a new panel has been selected
  912.             PanelSelect(event->data.popSelect.selection);
  913.             handled = true;
  914.             break;
  915.         }
  916.         break;
  917.         
  918.       default:
  919.     }
  920.     
  921.     CALLBACK_EPILOGUE
  922.     return (handled);
  923. }
  924.  
  925. //-----------------------------------------------------------------------------
  926. static Boolean ApplicationHandleEvent(EventPtr event) {
  927.     FormPtr    formPtr;
  928.     
  929. #if DEBUG >= 4
  930.     EmulatorLog("ApplicationHandleEvent");
  931. #endif
  932.  
  933.     if (event->eType == frmLoadEvent) {
  934.  
  935.         // we have only one form!
  936.         // load the form resource and set the event handler
  937.         formPtr = FrmInitForm(event->data.frmLoad.formID);
  938.         FrmSetActiveForm(formPtr);        
  939.         FrmSetEventHandler(formPtr, MainFormHandleEvent);
  940.  
  941.         return (true);
  942.         
  943.     }
  944.             
  945.     return (false);
  946.  
  947. }
  948.  
  949. //-----------------------------------------------------------------------------
  950. UInt32 PilotMain(UInt16 cmd, void * cmdPBP, UInt16 launchFlags) {
  951.     UInt32                updateInterval;
  952.     static EventType    event; // declared static to conserve stack space
  953.     Err                    error;
  954.         
  955. #if DEBUG >= 4
  956.     EmulatorLog("PilotMain: %u", cmd);
  957. #endif
  958.  
  959.     // see if we're on in minimum required version of the ROM or later
  960.     if (GetRomVersion() < MinRequiredVersion) {
  961.         if ((launchFlags & (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp))
  962.           == (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) {
  963.               FrmAlert(idErrOldRomAlert);
  964.         }
  965.         return (sysErrRomIncompatible);
  966.     }
  967.     
  968.     // handle launch codes
  969.     switch (cmd) {
  970.         
  971.       case sysAppLaunchCmdPanelCalledFromApp:
  972.         // we are called directly from an App (not by Prefs)
  973.         calledFromApp = true;
  974.       case sysAppLaunchCmdNormalLaunch:
  975.         // normal call from Prefs (or other panel)
  976.       case sysAppLaunchCmdReturnFromPanel:
  977.         // does this happen if we switch a lot between panels?
  978.         
  979.         // get the decimal delimiter
  980.         switch (PrefGetPreference(prefNumberFormat)) {
  981.           case nfPeriodComma:
  982.           case nfSpaceComma:
  983.           case nfApostropheComma:
  984.             StrCopy(decimalPoint, ",");
  985.             break;
  986.           default:
  987.             StrCopy(decimalPoint, ".");
  988.         }
  989.         // go to the initial form
  990.         FrmGotoForm(idMainForm);
  991.         // go into the event loop
  992.         updateInterval = RefreshDelay;
  993.         do {
  994.             EvtGetEvent(&event, updateInterval);
  995.             if (! SysHandleEvent(&event)) {
  996.                 if (! MenuHandleEvent(NULL, &event, &error)) {
  997.                     if (! ApplicationHandleEvent(&event)) {
  998.                         FrmDispatchEvent(&event);
  999.                     }
  1000.                 }
  1001.             }
  1002.         } while (event.eType != appStopEvent);    
  1003.         // send a frmCloseEvent to active form handlers
  1004.         FrmCloseAllForms();
  1005.         break;
  1006.         
  1007.       case sysAppLaunchCmdSyncNotify:
  1008.         // we are freshly installed by a HotSync
  1009.       case sysAppLaunchCmdSystemReset:
  1010.         // the unit has been reset
  1011.         // so we need to tell the system about our prefs
  1012.         // no globals!
  1013.         {
  1014.             PrefsType        prefs;
  1015.             UInt16            warn, critical;
  1016.             SysBatteryKind    kind, prefkind;
  1017.  
  1018.             // PalmOS 2.0 and 3.0 do not restore the battery kind
  1019.             // from the system prefs.
  1020.             // To be save we also retore them on newer OSes, if needed
  1021.             prefkind = (SysBatteryKind) PrefGetPreference(prefSysBatteryKind);
  1022.             GlueSysBatteryInfo(false, NULL, NULL, NULL, &kind, NULL, NULL);
  1023.             if (prefkind != kind) 
  1024.               GlueSysBatteryInfo(true, NULL, NULL, NULL, &prefkind, NULL, NULL);
  1025.  
  1026.             if (LoadPrefs(&prefs)) {
  1027.                 // prefs have been set
  1028.                 
  1029. //                GlueSysBatteryInfo(false, NULL, NULL, NULL, &kind, NULL, NULL);                
  1030. //                if (prefs.kind != kind) {
  1031. //                    // set the battery kind
  1032. //                    GlueSysBatteryInfo(true, NULL, NULL, NULL, &prefs.kind, 
  1033. //                      NULL, NULL);
  1034. //                }
  1035.                 
  1036.                 if (prefs.acceptRisk) {
  1037.                     // set the warn and critical level
  1038.                     GlueSysBatteryInfo(false, &warn, &critical, 
  1039.                       NULL, NULL, NULL, NULL);
  1040.                     if ((warn != prefs.warn) || (critical != prefs.critical)) {
  1041.                         GlueSysBatteryInfo(true, &prefs.warn, &prefs.critical, 
  1042.                           NULL, NULL, NULL, NULL);
  1043.                     }
  1044.                 }
  1045.             }
  1046.         }
  1047.         break;
  1048.         
  1049.     }
  1050.  
  1051.     return (0);
  1052. }
  1053.  
  1054. //=============================================================================
  1055.