home *** CD-ROM | disk | FTP | other *** search
- /*
-
- This software is open source pursuant to the "BSD License."
-
- Copyright (c) 2000, Josh Goldfoot
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- * Neither the name of Goldfoot Biochemical nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- DAMAGE.
-
- */
-
- /* Code version 1.0 */
-
- #include <Pilot.h>
- #include <SysEvtMgr.h>
- #include <ExgMgr.h>
- #include <NewFloatMgr.h>
- #include "FreeCurrencyRsc.h"
-
- // Internal Structures
-
- enum field_type { Unit1Qty, Unit2Qty, Unit1Put, Unit2Put, Unit1Name, Unit2Name,
- blank };
- struct myPreferenceType
- {
- Long prefversion;
- char pUnit1Name[80];
- char pUnit2Name[80];
- double pUnit1Qty, pUnit2Qty, pUnit1Put, pUnit2Put;
- UInt current_record_index;
- } ;
-
- struct StarterAppInfoType
- {
- Byte replaceme;
- } ;
-
- class cRecord
- {
- public:
- cRecord();
- cRecord(const CharPtr unit1name, const CharPtr unit2name, double unit1qty, double unit2qty);
- ~cRecord();
- Byte version;
- char unit_1_name[80];
- char unit_2_name[80];
- double unit_1_qty;
- double unit_2_qty;
- };
-
- // Constants
-
- const unsigned long appFileCreator = 'fCUR';
- const unsigned short appVersionNum = 0x01;
- const unsigned short appPrefID = 0x00;
- const unsigned short appPrefVersionNum = 0x01;
- const unsigned long version30 = 0x03000000;
- const CharPtr currency_DB_name = "CurrencyDatabase-fCUR";
- const ULong currency_DB_type = 'crdb';
-
- // Globals
-
- myPreferenceType prefs;
- DmOpenRef gDB;
- CharPtr popup_label;
-
- // Function prototypes
-
- void print_names();
- double ascii2double(CharPtr s);
- Short double2ascii(const double x, CharPtr s);
- Short do_conversion(field_type which_changed);
- void record2fields();
- Boolean handle_keydown_event(EventPtr eventP);
- FieldPtr set_field_text_from_handle(Word field_id, VoidHand text_handle);
- FieldPtr set_field_text_from_string(Word field_id, CharPtr string_pointer);
- void clear_field_text(Word field_id);
- CharPtr get_field_text(Word field_id);
- Boolean handle_button_event(EventPtr eventP);
- void swap_fields(Word field1, Word field2);
- void flip_values();
- void populate_new_database();
- UInt add_record_to_database(const CharPtr unit1name, const CharPtr unit2name, double unit1qty,
- double unit2qty, UInt actual_index);
- void get_record_name(UInt item_num, CharPtr list_entry);
- void currency_list_draw_function(UInt item_num, RectanglePtr bounds, CharPtr* pUnused);
- Boolean select_new_currency(Int16 selection);
- void do_save_command();
- void do_new_command();
- void do_delete_command();
- void do_restore_to_original_command();
- void create_new_database();
- void beam_send();
- void beam_receive(ExgSocketPtr socket_pointer, Boolean app_active);
- void goto_item(GoToParamsPtr goToParams, Boolean launchingApp);
- void search_find(FindParamsPtr findParams);
-
-
- /***********************************************************************
- *
- * FUNCTION: RomVersionCompatible
- *
- * DESCRIPTION: This routine checks that a ROM version is meet your
- * minimum requirement.
- *
- * PARAMETERS: requiredVersion - minimum rom version required
- * (see sysFtrNumROMVersion in SystemMgr.h
- * for format)
- * launchFlags - flags that indicate if the application
- * UI is initialized.
- *
- * RETURNED: error code or zero if rom is compatible
- *
- * REVISION HISTORY:
- *
- ***********************************************************************/
- static Err RomVersionCompatible(DWord requiredVersion, Word launchFlags)
- {
- DWord 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);
-
- // Pilot 1.0 will continuously relaunch this app unless we switch to
- // another safe one.
- if (romVersion < version30)
- {
- // Err err;
-
- AppLaunchWithCommand(sysFileCDefaultApp, sysAppLaunchCmdNormalLaunch, NULL);
- }
- }
-
- return (sysErrRomIncompatible);
- }
-
- return (0);
- }
-
-
- /***********************************************************************
- *
- * FUNCTION: GetObjectPtr
- *
- * DESCRIPTION: This routine returns a pointer to an object in the current
- * form.
- *
- * PARAMETERS: formId - id of the form to display
- *
- * RETURNED: VoidPtr
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
- static VoidPtr GetObjectPtr(Word objectID)
- {
- FormPtr frmP;
-
- frmP = FrmGetActiveForm();
-
- return (FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, objectID)));
- }
-
-
- /***********************************************************************
- *
- * FUNCTION: MainFormInit
- *
- * DESCRIPTION: This routine initializes the MainForm form.
- *
- * PARAMETERS: frm - pointer to the MainForm form.
- *
- * RETURNED: nothing
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
- static void MainFormInit(FormPtr frmP)
- {
-
-
- ListPtr currency_list_ptr = (ListPtr) FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, MainCurrenciesList));
-
- LstSetListChoices( currency_list_ptr, NULL, DmNumRecords (gDB) );
- LstSetDrawFunction(currency_list_ptr, currency_list_draw_function);
- LstSetSelection(currency_list_ptr, 0);
-
-
- CharPtr buf = (CharPtr) MemPtrNew(128);
-
- if (prefs.current_record_index == -1)
- select_new_currency(0);
- else {
- set_field_text_from_string(MainUnit1NameField, prefs.pUnit1Name);
- set_field_text_from_string(MainUnit2NameField, prefs.pUnit2Name);
- double2ascii(prefs.pUnit1Qty, buf);
- set_field_text_from_string(MainUnit1QtyField, buf);
- double2ascii(prefs.pUnit2Qty, buf);
- set_field_text_from_string(MainUnit2QtyField, buf);
- double2ascii(prefs.pUnit1Put, buf);
- set_field_text_from_string(MainUnit1PutField, buf);
- double2ascii(prefs.pUnit2Put, buf);
- set_field_text_from_string(MainUnit2PutField, buf);
-
- get_record_name(prefs.current_record_index, popup_label);
- CtlSetLabel (ControlPtr(GetObjectPtr(MainCurrenciesPopTrigger)), popup_label);
-
- }
-
- MemPtrFree( (VoidPtr) buf);
- print_names();
- }
-
-
- /***********************************************************************
- *
- * FUNCTION: MainFormDoCommand
- *
- * DESCRIPTION: This routine performs the menu command specified.
- *
- * PARAMETERS: command - menu item id
- *
- * RETURNED: nothing
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
- static Boolean MainFormDoCommand(Word command)
- {
- Boolean handled = false;
-
- FormPtr frmP = FrmGetActiveForm();
- Word active_field_id = FrmGetObjectId(frmP, FrmGetFocus(FrmGetActiveForm()));
- FieldPtr active_field = (FieldPtr) GetObjectPtr(active_field_id);
-
- switch (command)
- {
- case MainOptionsAboutFreeCurrency:
- FrmAlert(AboutAlert);
- handled = true;
- break;
-
- case EditUndo:
- handled = true;
- if (active_field)
- FldUndo(active_field);
- break;
-
- case EditGraffitiHelp:
- SysGraffitiReferenceDialog(referenceDefault);
- handled = true;
- break;
-
- case EditKeyboard:
- SysKeyboardDialog (kbdDefault);
- handled = true;
- break;
-
- case EditCopy:
- if (active_field)
- FldCopy(active_field);
- break;
-
- case EditCut:
- if (active_field)
- FldCut(active_field);
- break;
-
- case EditPaste:
- if (active_field)
- FldPaste(active_field);
- break;
-
- case CurrencyNew:
- do_new_command();
- handled = true;
- break;
-
- case CurrencySave:
- do_save_command();
- handled = true;
- break;
-
- case CurrencyDelete:
- do_delete_command();
- handled = true;
- break;
-
- case CurrencyBeam:
- beam_send();
- handled = true;
- break;
-
- case CurrencyRestoretooriginal:
- do_restore_to_original_command();
- handled = true;
- break;
-
- }
- return handled;
- }
-
-
- /***********************************************************************
- *
- * FUNCTION: MainFormHandleEvent
- *
- * DESCRIPTION: This routine is the event handler for the
- * "MainForm" of this application.
- *
- * PARAMETERS: eventP - a pointer to an EventType structure
- *
- * RETURNED: true if the event has handle and should not be passed
- * to a higher level handler.
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
- static Boolean MainFormHandleEvent(EventPtr eventP)
- {
- Boolean handled = false;
- FormPtr frmP = FrmGetActiveForm();
-
-
- switch (eventP->eType)
- {
- case menuEvent:
- return MainFormDoCommand(eventP->data.menu.itemID);
-
- case frmOpenEvent:
- frmP = FrmGetActiveForm();
- MainFormInit( frmP);
- FrmDrawForm ( frmP);
- handled = true;
- break;
-
-
- case keyDownEvent:
- handled = handle_keydown_event(eventP);
- break;
-
- case popSelectEvent:
- handled = false;
- if (eventP->data.popSelect.controlID == MainCurrenciesPopTrigger)
- handled = select_new_currency(eventP->data.popSelect.selection);
- break;
-
-
- case ctlSelectEvent:
- handled = handle_button_event(eventP);
- break;
-
- case frmGotoEvent:
- prefs.current_record_index = eventP->data.frmGoto.recordNum;
- select_new_currency(prefs.current_record_index);
- if (eventP->data.frmGoto.matchFieldNum) {
- FieldPtr selectedField = FieldPtr(GetObjectPtr(eventP->data.frmGoto.matchFieldNum));
- FldSetScrollPosition(selectedField, eventP->data.frmGoto.matchPos);
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, eventP->data.frmGoto.matchFieldNum));
- FldSetSelection(selectedField, eventP->data.frmGoto.matchPos, eventP->data.frmGoto.matchPos + eventP->data.frmGoto.matchLen);
-
- }
- handled = true;
- break;
-
-
- default:
- break;
-
- }
-
- return handled;
- }
-
- /***********************************************************************
- *
- * FUNCTION: AppHandleEvent
- *
- * DESCRIPTION: This routine loads form resources and set the event
- * handler for the form loaded.
- *
- * PARAMETERS: event - a pointer to an EventType structure
- *
- * RETURNED: true if the event has handle and should not be passed
- * to a higher level handler.
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
- static Boolean AppHandleEvent( EventPtr eventP)
- {
- Word formId;
- FormPtr 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, MainFormHandleEvent);
- }
- break;
-
- default:
- // ErrFatalDisplay("Invalid Form Load Event");
- break;
-
- }
- return true;
- }
-
- return false;
- }
-
-
- /***********************************************************************
- *
- * FUNCTION: AppEventLoop
- *
- * DESCRIPTION: This routine is the event loop for the application.
- *
- * PARAMETERS: nothing
- *
- * RETURNED: nothing
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
- static void AppEventLoop(void)
- {
- Word error;
- EventType event;
-
-
- do {
- EvtGetEvent(&event, evtWaitForever);
-
-
- if (! SysHandleEvent(&event))
- if (! MenuHandleEvent(0, &event, &error))
- if (! AppHandleEvent(&event))
- FrmDispatchEvent(&event);
- //if (event.eType == keyDownEvent)
- // handle_keydown_event(&event);
-
- } while (event.eType != appStopEvent);
- }
-
-
- /***********************************************************************
- *
- * FUNCTION: AppStart
- *
- * DESCRIPTION: Get the current application's preferences.
- *
- * PARAMETERS: nothing
- *
- * RETURNED: Err value 0 if nothing went wrong
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
- static Err AppStart(void)
- {
-
- Word prefsSize;
-
- // Read the saved preferences / saved-state information.
- prefsSize = sizeof(myPreferenceType);
- if (PrefGetAppPreferences(appFileCreator, appPrefID, &prefs, &prefsSize, true) ==
- noPreferenceFound)
- {
- MemSet( VoidPtr(&prefs), prefsSize, 0);
- prefs.prefversion = 1;
- StrCopy(prefs.pUnit1Name, "xNew");
- StrCopy(prefs.pUnit2Name, "xNew");
- prefs.pUnit1Qty = 1;
- prefs.pUnit2Qty = 1;
- prefs.pUnit1Put = 0;
- prefs.pUnit2Put = 0;
- prefs.current_record_index = -1;
-
- }
-
- gDB = DmOpenDatabaseByTypeCreator(currency_DB_type, appFileCreator, dmModeReadWrite);
- if (! gDB) {
- create_new_database();
- }
-
- popup_label = (CharPtr) MemPtrNew(128);
-
-
- return 0;
- }
-
-
- /***********************************************************************
- *
- * FUNCTION: AppStop
- *
- * DESCRIPTION: Save the current state of the application.
- *
- * PARAMETERS: nothing
- *
- * RETURNED: nothing
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
- static void AppStop(void)
- {
-
-
- StrCopy(prefs.pUnit1Name, get_field_text(MainUnit1NameField));
- StrCopy(prefs.pUnit2Name, get_field_text(MainUnit2NameField));
- prefs.pUnit1Qty = ascii2double(get_field_text(MainUnit1QtyField));
- prefs.pUnit2Qty = ascii2double(get_field_text(MainUnit2QtyField));
- prefs.pUnit1Put = ascii2double(get_field_text(MainUnit1PutField));
- prefs.pUnit2Put = ascii2double(get_field_text(MainUnit2PutField));
-
- MemPtrFree( (VoidPtr) popup_label);
-
- // Write the saved preferences / saved-state information. This data
- // will be backed up during a HotSync.
- PrefSetAppPreferences (appFileCreator, appPrefID, appPrefVersionNum,
- &prefs, sizeof (prefs), true);
-
- if (gDB != NULL)
- DmCloseDatabase(gDB);
-
- }
-
-
-
- /***********************************************************************
- *
- * FUNCTION: FreeCurrencyPilotMain
- *
- * DESCRIPTION: This is the main entry point for the application.
- * PARAMETERS: cmd - word value specifying the launch code.
- * cmdPB - pointer to a structure that is associated with the launch code.
- * launchFlags - word value providing extra information about the launch.
- *
- * RETURNED: Result of launch
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
- static DWord FreeCurrencyPilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
- {
- Err error;
- Boolean app_active;
-
-
- error = RomVersionCompatible (version30, launchFlags);
- if (error) return (error);
-
-
- switch (cmd)
- {
- case sysAppLaunchCmdNormalLaunch:
- error = AppStart();
- if (error)
- return error;
-
- FrmGotoForm(MainForm);
- AppEventLoop();
- AppStop();
- break;
-
- case sysAppLaunchCmdSyncNotify:
- // Use this if I have more than one data type, but I don't...
- break;
-
-
- case sysAppLaunchCmdExgReceiveData:
- app_active = (launchFlags & sysAppLaunchFlagSubCall);
- beam_receive(ExgSocketPtr(cmdPBP), app_active);
- break;
-
- case sysAppLaunchCmdSaveData:
- // Do nothing; we don't need to save data
- break;
-
- case sysAppLaunchCmdGoTo:
- Boolean launched = launchFlags & sysAppLaunchFlagNewGlobals;
- if (launched) {
- error = AppStart();
- if (! error) {
- goto_item((GoToParamsPtr) cmdPBP, launched);
- AppEventLoop();
- AppStop();
- }
- } else
- goto_item((GoToParamsPtr) cmdPBP, launched);
- break;
-
- case sysAppLaunchCmdFind:
- search_find((FindParamsPtr)cmdPBP);
-
- default:
- break;
-
- }
-
- return 0;
- }
-
-
- /***********************************************************************
- *
- * FUNCTION: PilotMain
- *
- * DESCRIPTION: This is the main entry point for the application.
- *
- * PARAMETERS: cmd - word value specifying the launch code.
- * cmdPB - pointer to a structure that is associated with the launch code.
- * launchFlags - word value providing extra information about the launch.
- * RETURNED: Result of launch
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
- DWord PilotMain( Word cmd, Ptr cmdPBP, Word launchFlags)
- {
- return FreeCurrencyPilotMain(cmd, cmdPBP, launchFlags);
- }
-
-
- // print_names: Gets the names of the currencies, and prints them
- // in the lower part of the form.
- void print_names()
- {
- CharPtr cpUnit1Name = get_field_text(MainUnit1NameField);
- CharPtr cpUnit2Name = get_field_text(MainUnit2NameField);
- RectangleType r;
- RctSetRectangle(&r, 104, 75, 56, 50);
- WinEraseRectangle(&r, 0);
- WinDrawChars(cpUnit1Name, StrLen(cpUnit1Name), 104, 80);
- WinDrawChars(cpUnit2Name, StrLen(cpUnit2Name), 104, 112);
- }
-
- // ascii2double: Given a string containing a number (s), return a double
- // representing the value of the string.
- double ascii2double(CharPtr s)
- {
- char thousand_separator, decimal_separator;
-
- if (s != NULL) {
- if (StrLen(s) > 0) {
- LocGetNumberSeparators ((NumberFormatType) PrefGetPreference(prefNumberFormat),
- &thousand_separator, &decimal_separator);
- StrDelocalizeNumber (s, thousand_separator, decimal_separator);
-
- FlpCompDouble theCompdouble;
- theCompdouble.fd = FlpAToF(s);
- double result = theCompdouble.d;
- return result;
- } else
- return 0;
- } else
- return 0;
- }
-
- // double2ascii: given a double and a pointer to a string buffer,
- // put an ASCII representation of the double into the buffer, using normal
- // (i.e. non-scientific) notation, rounding to hundredths.
-
- Short double2ascii(const double x, CharPtr s)
- {
- char temp[80];
- char thousand_separator, decimal_separator;
-
- if (s == NULL)
- return 0;
-
- // Use the OS to convert the double to ASCII.
- FlpCompDouble theCompdouble;
- theCompdouble.d = x;
- if (FlpFToA( theCompdouble.fd, s)) {
- StrCopy(s, "Overflow");
- return StrLen(s);
- }
-
- // De-localize the number string so that it uses U.S. conventions
- LocGetNumberSeparators ((NumberFormatType) PrefGetPreference(prefNumberFormat),
- &thousand_separator, &decimal_separator);
- StrDelocalizeNumber (s, thousand_separator, decimal_separator);
-
-
-
- // FlpFToA leaves us with a number in scientific notation, in the form:
- // [-]x.yyyyyyyye[-]zz. We must convert this to normal notation.
-
- // Locate the "e" towards the end of the string, and extract the exponent.
- Short string_length = StrLen(s);
- Short e_position = string_length - 3;
- if (s[e_position] == '-')
- e_position--;
- Long exponent = StrAToI( & s[e_position + 1] );
-
-
- // Wipe out the "e[-]zz" at the end of the string
- Short i = e_position;
- while (s[i] != 0) {
- s[i] = 0;
- i++;
- }
- string_length = e_position;
-
-
- // Find the decimal point.
- // Because we have delocalized, it is OK to assume it is a "."
- Short decimal_position = 1;
- if (s[decimal_position] != '.')
- decimal_position++;
-
- if (exponent != 0) {
- // Delete the decimal point, moving all other numbers forward one.
- for (i = decimal_position; i < string_length - 1; i++)
- s[i] = s[i + 1];
- string_length--;
- }
-
- if (exponent < 0) {
- // If exponent is negative, add zeros to the front.
- StrCopy(temp, "0.0000000000000000000000000000000");
- temp[1 - exponent] = 0;
- StrCat(temp, s);
- StrCopy(s, temp);
- string_length += 1 - exponent;
- } else if (exponent > 0) {
- // If exponent is positive, insert decimal point into the string at the proper point.
- decimal_position += exponent;
- for (i = string_length; i > decimal_position; i--)
- s[i] = s[i - 1];
- s[decimal_position] = '.';
- string_length++;
- }
-
- // Remove trailing zeroes.
- i = string_length - 1;
- while ((s[i] == '0') && (i > 0)) {
- s[i--] = 0;
- string_length--;
- }
-
- // If there is a thousandths place (or more), round to hundredths.
- // (This is good to do both because we are dealing with currencies and because the Palm's
- // floating point accuracy isn't too good).
- if (string_length - decimal_position > 3) {
- if (s[decimal_position + 3] > '4')
- s[decimal_position + 2]++;
- for (i = decimal_position + 3; i < string_length; i++)
- s[i] = 0;
- }
-
- // Remove trailing garbage, if any
- while (((s[string_length - 1] < '0') || (s[string_length - 1] > '9'))
- && (string_length > 0))
- s[--string_length] = 0;
-
- // Re-localize the number, and return the length.
- LocGetNumberSeparators ((NumberFormatType) PrefGetPreference(prefNumberFormat),
- &thousand_separator, &decimal_separator);
- StrLocalizeNumber (s, thousand_separator, decimal_separator);
-
- // Recalculate string length in case it was changed during localization.
- return StrLen(s);
- }
-
- // do_conversion: the main currency conversion routine. "which_changed"
- // tells the routine which of the fields the user has changed. Based on that,
- // the routine decides which field to recalculate, and does so.
- Short do_conversion(field_type which_changed)
- {
- // Get the text of all the fields.
- CharPtr cpUnit1Qty = get_field_text(MainUnit1QtyField);
- CharPtr cpUnit2Qty = get_field_text(MainUnit2QtyField);
- if ((StrLen(cpUnit1Qty) == 0) || (StrLen(cpUnit2Qty) == 0))
- return 0;
-
- double dUnit1Qty, dUnit1Put, dUnit2Qty, dUnit2Put;
-
- // Convert from strings to floating point numbers for calculating.
- dUnit1Qty = ascii2double(cpUnit1Qty);
- dUnit2Qty = ascii2double(cpUnit2Qty);
- dUnit1Put = ascii2double(get_field_text(MainUnit1PutField));
- dUnit2Put = ascii2double(get_field_text(MainUnit2PutField));
-
- char buf[255];
-
- // If either of the main unit quantities are zero, quit to avoid division
- // by zero errors.
- if ((dUnit1Qty == 0) || (dUnit2Qty == 0)) {
- clear_field_text(MainUnit1PutField);
- clear_field_text(MainUnit2PutField);
- return 0;
- }
-
- // Do the calculation. Note that if the "quantity" fields change, only
- // unit 2 put gets changed.
-
- if (which_changed != Unit2Put) {
- dUnit2Put = dUnit1Put * dUnit2Qty / dUnit1Qty;
- double2ascii(dUnit2Put, buf);
- set_field_text_from_string(MainUnit2PutField, buf);
- }
-
- if (which_changed != Unit1Put) {
- dUnit1Put = dUnit2Put * dUnit1Qty / dUnit2Qty;
- double2ascii(dUnit1Put, buf);
- set_field_text_from_string(MainUnit1PutField, buf);
- }
-
-
- return 0;
- }
-
-
-
- // handle_keydown_event: called after the user enters a character.
- Boolean handle_keydown_event(EventPtr eventP)
- {
- FormPtr frmP = FrmGetActiveForm();
- Word active_field_id = FrmGetObjectId(frmP, FrmGetFocus(FrmGetActiveForm()));
- FldHandleEvent ( FieldPtr(FrmGetObjectPtr(frmP,
- FrmGetObjectIndex(frmP, active_field_id))), eventP);
-
- switch ( active_field_id ) {
- case MainUnit1QtyField:
- do_conversion(Unit1Qty);
- break;
- case MainUnit2QtyField:
- do_conversion(Unit2Qty);
- break;
- case MainUnit1PutField:
- do_conversion(Unit1Put);
- break;
- case MainUnit2PutField:
- do_conversion(Unit2Put);
- break;
- case MainUnit1NameField:
- print_names();
- break;
- case MainUnit2NameField:
- print_names();
- break;
- default:
- break;
- }
-
- return true;
- }
-
-
- FieldPtr set_field_text_from_handle(Word field_id, VoidHand text_handle)
- {
- VoidHand old_text_handle;
- FormPtr frm = FrmGetActiveForm();
- FieldPtr field_pointer;
-
- field_pointer = FieldPtr(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, field_id)));
- ErrNonFatalDisplayIf(!field_pointer, "missing field");
- old_text_handle = (VoidHand) FldGetTextHandle(field_pointer);
-
- FldSetTextHandle(field_pointer, (Handle) text_handle);
- FldDrawField(field_pointer);
-
- if (old_text_handle)
- MemHandleFree(old_text_handle);
-
- return field_pointer;
- }
-
- FieldPtr set_field_text_from_string(Word field_id, CharPtr string_pointer)
- {
- VoidHand text_handle;
- text_handle = MemHandleNew(StrLen(string_pointer) + 1);
- if (!text_handle)
- return NULL;
- StrCopy(CharPtr(MemHandleLock(text_handle)), string_pointer);
- MemHandleUnlock(text_handle);
- return set_field_text_from_handle(field_id, text_handle);
- }
-
- void clear_field_text(Word field_id)
- {
- set_field_text_from_handle(field_id, NULL);
- }
-
- CharPtr get_field_text(Word field_id)
- {
- FormPtr frmP = FrmGetActiveForm();
- return FldGetTextPtr(FieldPtr(FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, field_id))));
- }
-
- Boolean handle_button_event(EventPtr eventP)
- {
- Boolean handled = false;
-
- switch (eventP->data.ctlSelect.controlID) {
- case MainSaveButton:
- handled = true;
- do_save_command();
- break;
- case MainNewButton:
- handled = true;
- do_new_command();
- break;
- case MainDeleteButton:
- handled = true;
- do_delete_command();
- break;
- default:
- handled = false;
- break;
-
- }
-
- return handled;
- }
-
- void do_save_command()
- {
- char question[200] = "Really save over \"";
- char record_name[80];
- get_record_name(prefs.current_record_index, record_name);
- StrCat(question, record_name);
- StrCat(question, "?\"");
-
- Word button_tapped = FrmCustomAlert (QueryAlert, question, NULL, NULL);
- if (button_tapped == QueryNo)
- return;
-
- cRecord my_record(get_field_text(MainUnit1NameField),
- get_field_text(MainUnit2NameField),
- ascii2double(get_field_text(MainUnit1QtyField)),
- ascii2double(get_field_text(MainUnit2QtyField)) );
-
- VoidHand record_handle = DmGetRecord( gDB, prefs.current_record_index );
- if (! record_handle)
- return;
-
- VoidPtr record_pointer = MemHandleLock( record_handle );
- UInt the_size = sizeof(cRecord);
- DmWrite( record_pointer, 0, &my_record, the_size );
- MemHandleUnlock( record_handle );
- DmReleaseRecord( gDB, prefs.current_record_index, true);
- get_record_name(prefs.current_record_index, popup_label);
- CtlSetLabel (ControlPtr(GetObjectPtr(MainCurrenciesPopTrigger)), popup_label);
-
-
- }
-
- void do_new_command()
- {
- UInt new_index = add_record_to_database("USA Dollar", "Foreign", 1, 3, prefs.current_record_index);
- LstSetListChoices( ListPtr(GetObjectPtr(MainCurrenciesList)),
- NULL, DmNumRecords (gDB) );
- select_new_currency(new_index);
- }
-
- void do_delete_command()
- {
- if (DmNumRecords(gDB) == 1) {
- FrmCustomAlert(InfoAlert, "Sorry, that's your last record.", NULL, NULL);
- return;
- }
-
- char question[200] = "Really delete \"";
- char record_name[80];
- get_record_name(prefs.current_record_index, record_name);
- StrCat(question, record_name);
- StrCat(question, "?\"");
-
- Word button_tapped = FrmCustomAlert (QueryAlert, question, NULL, NULL);
- if (button_tapped == QueryNo)
- return;
-
- Err myErr = DmRemoveRecord (gDB, prefs.current_record_index);
- if (prefs.current_record_index > 0) {
- prefs.current_record_index--;
- }
- LstSetListChoices( ListPtr(GetObjectPtr(MainCurrenciesList)),
- NULL, DmNumRecords (gDB) );
- select_new_currency(prefs.current_record_index);
-
- }
-
- void do_restore_to_original_command()
- {
-
- Word button_tapped = FrmCustomAlert (QueryAlert, "Really delete ALL records and replace them with a default set?", NULL, NULL);
- if (button_tapped == QueryNo)
- return;
-
- UInt num_records = DmNumRecords(gDB);
- while (num_records > 0) {
- DmRemoveRecord (gDB, 0);
- num_records--;
- }
- populate_new_database();
- LstSetListChoices( ListPtr(GetObjectPtr(MainCurrenciesList)),
- NULL, DmNumRecords (gDB) );
- select_new_currency(0);
- }
-
-
- cRecord::cRecord()
- {
- version = 1;
- StrCopy(unit_1_name, "");
- StrCopy(unit_2_name, "");
- unit_1_qty = 1;
- unit_2_qty = 1;
- }
-
- cRecord::cRecord(const CharPtr unit1name, const CharPtr unit2name, double unit1qty, double unit2qty)
- {
- version = 1;
- StrCopy(unit_1_name, unit1name);
- StrCopy(unit_2_name, unit2name);
- unit_1_qty = unit1qty;
- unit_2_qty = unit2qty;
- }
-
- cRecord::~cRecord()
- {
-
- }
-
-
- UInt add_record_to_database(const CharPtr unit1name, const CharPtr unit2name, double unit1qty,
- double unit2qty, UInt actual_index)
- {
- cRecord my_record(unit1name, unit2name, unit1qty, unit2qty);
- ULong record_size = sizeof(cRecord);
- VoidHand record_handle = DmNewHandle( gDB, record_size );
- if (! record_handle)
- return -1;
- VoidPtr record_pointer = MemHandleLock( record_handle );
- DmWrite( record_pointer, 0, &my_record, record_size );
- MemHandleUnlock( record_handle );
- DmAttachRecord( gDB, &actual_index, (char **) record_handle, NULL );
- return actual_index;
- }
-
- void populate_new_database()
- {
- // Defaults to major USA trading partners
- // Country abbreviations are taken from ISO 3166 for consistency
-
- add_record_to_database("USA Dollar", "CAN Dollar", 1, 1.48, dmMaxRecordIndex);
- add_record_to_database("USA Dollar", "CHN Yuan", 1, 8.28, dmMaxRecordIndex);
- add_record_to_database("USA Dollar", "DEU Mark", 1, 2.30, dmMaxRecordIndex);
- add_record_to_database("USA Dollar", "Euro", 1, 1.17, dmMaxRecordIndex);
- add_record_to_database("USA Dollar", "FRA Franc", 1, 7.70, dmMaxRecordIndex);
- add_record_to_database("USA Dollar", "GBR Pound", 1.41, 1, dmMaxRecordIndex);
- add_record_to_database("USA Dollar", "ITA Lira", 1, 2273.68, dmMaxRecordIndex);
- add_record_to_database("USA Dollar", "JPN Yen", 1, 107.27, dmMaxRecordIndex);
- add_record_to_database("USA Dollar", "KOR Won", 1, 1119, dmMaxRecordIndex);
- add_record_to_database("USA Dollar", "MEX Peso", 1, 9.36, dmMaxRecordIndex);
- add_record_to_database("USA Dollar", "NLD Guilder", 1, 1.74, dmMaxRecordIndex);
- add_record_to_database("USA Dollar", "TWN Dollar", 1, 31.19, dmMaxRecordIndex);
- }
-
- // Given a database index (zero-based), return in list_entry the "name" of that
- // record, e.g. "USA Dollar/FRA Franc"
- void get_record_name(UInt item_num, CharPtr list_entry)
- {
- if (list_entry == NULL)
- return;
-
- if (! gDB) {
- StrCopy(list_entry, "Error!");
- return;
- }
-
- VoidHand record_handle = DmQueryRecord (gDB, item_num);
- if (! record_handle)
- return;
- VoidPtr record_pointer = MemHandleLock( record_handle );
- cRecord* the_record = (cRecord*) record_pointer;
- StrCopy(list_entry, the_record->unit_1_name);
- StrCat(list_entry, "/");
- StrCat(list_entry, the_record->unit_2_name);
- MemHandleUnlock(record_handle);
- }
-
- // The draw function called by the OS to draw each entry in the list function.
- // The best way I know of to implement a dynamic list.
- void currency_list_draw_function(UInt item_num, RectanglePtr bounds, CharPtr* pUnused)
- {
- FormPtr pForm = FrmGetActiveForm();
- CharPtr list_entry = (CharPtr) MemPtrNew(256);
-
- get_record_name(item_num, list_entry);
-
- WinDrawChars(list_entry, StrLen(list_entry), bounds->topLeft.x, bounds->topLeft.y);
- MemPtrFree( (VoidPtr) list_entry);
- }
-
- // select_new_currency: called when the user picks a new currency, or when the
- // app otherwise has to move to a new currency. Updates the displays.
- Boolean select_new_currency(Int16 selection)
- {
- if (! gDB)
- return false;
-
- VoidHand record_handle = DmQueryRecord (gDB, selection);
- if (! record_handle)
- return true;
- VoidPtr record_pointer = MemHandleLock( record_handle );
- cRecord* the_record = (cRecord*) record_pointer;
-
- CharPtr buf = (CharPtr) MemPtrNew(128);
-
- set_field_text_from_string(MainUnit1NameField, the_record->unit_1_name);
- set_field_text_from_string(MainUnit2NameField, the_record->unit_2_name);
- double2ascii(the_record->unit_1_qty, buf);
- set_field_text_from_string(MainUnit1QtyField, buf);
- double2ascii(the_record->unit_2_qty, buf);
- set_field_text_from_string(MainUnit2QtyField, buf);
- StrCopy(buf, "0");
- set_field_text_from_string(MainUnit1PutField, buf);
- set_field_text_from_string(MainUnit2PutField, buf);
-
- MemHandleUnlock(record_handle);
-
- print_names();
- prefs.current_record_index = selection;
- get_record_name(selection, popup_label);
- CtlSetLabel (ControlPtr(GetObjectPtr(MainCurrenciesPopTrigger)), popup_label);
-
- MemPtrFree( (VoidPtr) buf);
-
- return true;
- }
-
- void create_new_database()
- {
- Err err = DmCreateDatabase(0, currency_DB_name, appFileCreator, currency_DB_type, false);
- if (err) return;
- gDB = DmOpenDatabaseByTypeCreator(currency_DB_type, appFileCreator, dmModeReadWrite);
- if (! gDB) return;
- populate_new_database();
- }
-
- // Beam the current currency record to another Palm device.
- void beam_send()
- {
- ExgSocketPtr socket_pointer = (ExgSocketPtr) MemPtrNew(sizeof(ExgSocketType));
- Err error;
-
- MemSet(socket_pointer, sizeof(ExgSocketType), 0);
-
- // Fill in the fields to describe this entry
- socket_pointer->description = (CharPtr) MemPtrNew(120);
- get_record_name(prefs.current_record_index, socket_pointer->description);
- socket_pointer->name = "currency.cur";
- socket_pointer->target = appFileCreator;
-
- // Begin the beam
- error = ExgPut (socket_pointer);
-
- // Load the record, and call ExgSend repeatedly (if need be) to send it
- if (! error) {
- VoidHand record_handle = DmQueryRecord( gDB, prefs.current_record_index );
- if (record_handle) {
- VoidPtr record_pointer = MemHandleLock( record_handle );
- ULong record_size = MemPtrSize(record_pointer);
- VoidPtr local_copy_ptr = MemPtrNew( record_size );
- MemMove( local_copy_ptr, record_pointer, record_size );
- MemHandleUnlock( record_handle );
- cRecord* buf = (cRecord*) local_copy_ptr;
- ULong amount_sent;
- while (record_size) {
- amount_sent = ExgSend(socket_pointer, local_copy_ptr, record_size, &error);
- if (error)
- break;
- buf += amount_sent;
- record_size -= amount_sent;
- }
- MemPtrFree(local_copy_ptr);
- }
- }
-
- // Disconnect to free the port and internal memory structures
- ExgDisconnect(socket_pointer, error);
-
- MemPtrFree( (VoidPtr) socket_pointer->description);
- MemPtrFree( (VoidPtr) socket_pointer);
-
- }
-
- // Receive a currency record from another Palm device.
- void beam_receive(ExgSocketPtr socket_pointer, Boolean app_active)
- {
- UInt record_index;
- DmOpenRef* local_db;
-
- // Because this could be called when we are not the active application, do not
- // assume that globals like gDB are available.
- if (app_active)
- local_db = &gDB;
- else {
- local_db = (DmOpenRef*) MemPtrNew(sizeof(DmOpenRef));
- *local_db = DmOpenDatabaseByTypeCreator(currency_DB_type, appFileCreator, dmModeReadWrite);
- if (! *local_db)
- return;
- }
-
- // Call ExgAccept, then call ExgReceive to get the new record.
- Err error = 0;
- if ( ! ExgAccept (socket_pointer)) {
- VoidPtr buf = MemPtrNew(sizeof(cRecord));
- ULong record_size = ExgReceive(socket_pointer, buf, sizeof(cRecord), &error);
- if ((! error) && (buf != NULL)) {
- // Add the record to our database
- VoidHand record_handle = DmNewHandle( *local_db, record_size );
- if (!record_handle)
- return;
- VoidPtr record_pointer = MemHandleLock( record_handle );
- DmWrite( record_pointer, 0, buf, record_size );
- MemHandleUnlock( record_handle );
- record_index = 0;
- DmAttachRecord( *local_db, &record_index, (char **) record_handle, NULL );
- }
- if (buf != NULL)
- MemPtrFree(buf);
- }
- error = ExgDisconnect(socket_pointer, error);
-
- // Set the "goto" params so that the OS will send us a "goto" event to take us to the
- // newly-received record.
- if (! error) {
- DmRecordInfo(*local_db, record_index, NULL, &socket_pointer->goToParams.uniqueID,
- NULL);
- DmOpenDatabaseInfo(*local_db, &socket_pointer->goToParams.dbID, NULL, NULL,
- &socket_pointer->goToParams.dbCardNo, NULL);
- socket_pointer->goToParams.recordNum = record_index;
- socket_pointer->goToCreator = appFileCreator;
- }
-
- if (! app_active) {
- DmCloseDatabase( *local_db );
- MemPtrFree( (VoidPtr) local_db);
- }
-
- }
-
-
- void goto_item(GoToParamsPtr goToParams, Boolean launchingApp)
- {
- EventType event;
- UInt recordNum = goToParams->recordNum;
-
- if (! launchingApp) {
- ULong uniqueID;
-
- DmRecordInfo(gDB, recordNum, NULL, &uniqueID, NULL);
- DmFindRecordByID(gDB, uniqueID, &recordNum);
- }
-
- FrmGotoForm(MainForm);
-
- MemSet (&event, 0, sizeof(EventType));
-
- event.eType = frmGotoEvent;
- event.data.frmGoto.formID = MainForm;
- event.data.frmGoto.recordNum = recordNum;
- event.data.frmGoto.matchPos = goToParams->matchPos;
- event.data.frmGoto.matchLen = goToParams->searchStrLen;
- event.data.frmGoto.matchFieldNum = goToParams->matchFieldNum;
- event.data.frmGoto.matchCustom = goToParams->matchCustom;
-
- EvtAddEventToQueue(&event);
- }
-
-
- // search_find: Handles the "Find" open application message.
- // searches the database for the find string, and sends self
- // a goto event if it finds it.
- void search_find(FindParamsPtr find_params)
- {
- Boolean done, truncate;
- CharPtr unit1_qty_str, unit2_qty_str, scratch_string;
- DmOpenRef local_db;
- DmSearchStateType search_state;
- Err error;
- LocalID database_id;
- RectangleType r;
- SWord string_length, pixel_width;
- UInt card_number, field_number, record_number;
- VoidHand record_handle;
- VoidPtr record;
- Word pos;
-
-
- find_params->more = false;
- card_number = 0;
- error = DmGetNextDatabaseByTypeCreator(true, &search_state, currency_DB_type, appFileCreator, true,
- &card_number, &database_id);
- if (error)
- return;
- local_db = DmOpenDatabase(card_number, database_id, find_params->dbAccesMode);
- if (! local_db)
- return;
-
- // Display the heading line.
- scratch_string = (CharPtr) MemPtrNew(128);
- unit1_qty_str = (CharPtr) MemPtrNew(128);
- unit2_qty_str = (CharPtr) MemPtrNew(128);
- StrCopy(scratch_string, "Currency");
- done = FindDrawHeader(find_params, scratch_string);
-
- if (done)
- find_params->more = true;
- else {
- record_number = find_params->recordNum;
- cRecord* record_ptr;
-
- while (true) {
- Boolean match = false;
-
- if ( (record_number % 10 == 0) && EvtSysEventAvail(true)) {
- find_params->more = true;
- break;
- }
-
- record_handle = DmQueryNextInCategory(local_db, &record_number, dmAllCategories);
- if (! record_handle)
- break;
-
- record = MemHandleLock(record_handle);
- record_ptr = (cRecord*) record;
- double2ascii(record_ptr->unit_1_qty, unit1_qty_str);
- double2ascii(record_ptr->unit_2_qty, unit2_qty_str);
-
- if ((match = FindStrInStr((CharPtr) record_ptr->unit_1_name, find_params->strToFind, &pos)) != false)
- field_number = MainUnit1NameField;
- else if ((match = FindStrInStr((CharPtr) record_ptr->unit_2_name, find_params->strToFind, &pos)) != false)
- field_number = MainUnit2NameField;
- else if ((match = FindStrInStr(unit1_qty_str, find_params->strToFind, &pos)) != false)
- field_number = MainUnit1QtyField;
- else if ((match = FindStrInStr( unit2_qty_str, find_params->strToFind, &pos)) != false)
- field_number = MainUnit2QtyField;
-
- if (match) {
- done = FindSaveMatch(find_params, record_number, pos, field_number, 0,
- card_number, database_id);
- if (done)
- break;
-
- StrCopy(scratch_string, record_ptr->unit_1_name);
- StrCat(scratch_string, "/");
- StrCat(scratch_string, record_ptr->unit_2_name);
- FindGetLineBounds(find_params, &r);
- string_length = StrLen(scratch_string);
- pixel_width = r.extent.x;
- FntCharsInWidth(scratch_string, &pixel_width, &string_length, &truncate);
- WinDrawChars(scratch_string, string_length, r.topLeft.x, r.topLeft.y);
-
- find_params->lineNumber++;
- }
- MemHandleUnlock(record_handle);
- if (done)
- break;
- record_number++;
- }
- }
- DmCloseDatabase(local_db);
- MemPtrFree(scratch_string);
- MemPtrFree( (VoidPtr) unit1_qty_str);
- MemPtrFree( (VoidPtr) unit2_qty_str);
-
- }
-