home *** CD-ROM | disk | FTP | other *** search
- /*
- GetTLE - Main.c - The main file for GetTLE
- Copyright ⌐2000 Andreas Schneider
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- // With thanks to Neil Rhodes and Julie McKeehan for
- // their invaluable book
- // 'Palm Programming: the Developer's Guide'
-
- #include <PalmOS.h> // all the system headers needed, except...
- #include <NetMgr.h> // .. this one
- #include "GetTLERsc.h" // application resource defines
- #include "debug.h" // Allow debug output to go to a file/memo
- #include "URLsMemo.h" // Allow a list of URLs to be saved as a memo
- #include "PSatDB.h" // handles the PocketSat database
- #include "http.h" // the HTTP connection to the webserver
- #include "alerts.h" // the popup alerts
- #include "Util.h" // Some convenience functions
- #include "Progress.h" // Progress indicator
-
- // We need some global variables for the socket routines
- // The socket routines are macros that use them when expanded
-
- extern UInt16 AppNetRefnum;
- extern Int32 AppNetTimeout;
- Err errno;
-
- #define version20 0x02000000 // PalmOS 2.0 version number - we insist on it
-
- #define CreatorID 'GTLE' // registered exclusively to us
- #define PrefID 0 // the docs says'usually 0', so that's what we use
- #define Version 1 // is returned by PrefGetAppReferences()
-
- // Make sure these are not smaller than the Max Characters
- // of the appropriate text entry fields
- #define MAX_URL_LEN 120
-
- typedef struct
- {
- Char URL[MAX_URL_LEN+1]; // allow for trailing \0
- Boolean debugging_enabled;
- }
- PreferencesType;
-
- static PreferencesType Prefs={0}; // our preferences
-
- // Stuff we do when the application starts
- static Boolean StartApplication(void)
- {
- Int16 result=0;
- UInt16 pref_size=0;
-
- // first we initialize the Memopad debugging
- InitDebugMessages();
- // let's see if there is a save preference for the TLE location
- pref_size=sizeof(Prefs);
- result=PrefGetAppPreferences(CreatorID,PrefID,&Prefs,&pref_size,true);
- if (result==noPreferenceFound)
- {
- // if there is no saved preference we use a default site
- StrCopy(Prefs.URL,"www.celestrak.com/NORAD/elements/stations.txt");
- Prefs.debugging_enabled=false;
- }
- if (Prefs.debugging_enabled)
- {
- StartDebugMessages();
- }
- // first read a list of sites and build up the popup list
- ReadURLsMemo();
- // if we debug to Memopad log some information
- LogMessage("URL: %s\n",Prefs.URL);
- // Now open the PocketSat database
- OpenPSatDB();
- return false;
- }
-
- // Make sure that the operating system version is ok
- static Err RomVersionCompatible (UInt32 requiredVersion, UInt16 launchFlags)
- {
- UInt32 romVersion;
-
- // Check that we have the minimum required version of the OS or later
- FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
- if (romVersion < requiredVersion)
- {
- // If the program was started from the launcher display a message
- // If the program was started any other way be quiet
- if ((launchFlags & (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) ==
- (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp))
- {
- FrmAlert (RomIncompatibleAlert);
- // OS 1.0 will continuously relaunch this app unless we switch to
- // another safe one. The sysFileCDefaultApp is considered "safe".
- if (romVersion < 0x02000000)
- {
- AppLaunchWithCommand(sysFileCDefaultApp, sysAppLaunchCmdNormalLaunch, NULL);
- }
- }
- // wrong version - return error code
- return (sysErrRomIncompatible);
- }
- // everything is ok
- return 0;
- }
-
- // Called before the application stops
- static void StopApplication(void)
- {
- // clean up:
- // close the PocketSat database
- ClosePSatDB();
- // and write the debug messages to the memo
- WriteDebugMessages();
- return;
- }
-
- static void ListDrawFunction(Int16 item_number, RectanglePtr bounds,Char **data)
- {
- Char ellipse[]="...";
- Char *text=SiteNames[item_number];
- Int16 x=bounds->topLeft.x;
- Int16 y=bounds->topLeft.y;
- Int16 width=bounds->extent.x;
- Int16 half_width=width/2;
- Int16 draw_width=width;
- Int16 text_len=StrLen(text);
- Int16 chars_to_draw=text_len;
- Int16 pixels=0;
- UInt16 pos=0;
- UInt16 left=0;
- UInt16 right=0;
-
- // first find out if the site name fits the width
- pixels=FntCharsWidth(text,text_len);
- if (pixels<width)
- {
- // the easy case the whole string fits - draw it
- WinDrawChars(text,chars_to_draw,x,y);
- }
- else
- {
- // doesn't find completely use ellipse in the middle
- // adjust width for the '...'
- width-=FntCharsWidth(ellipse,StrLen(ellipse));
- // use up to half the remaining width for the text on the left
- half_width=width/2;
- // how many characters from the left make up just under half the width?
- left=1; // We want at least one
- // add characters until we'd exceed half the remaining width
- for (pos=1;pos<text_len && FntCharsWidth(text,pos+1)<=half_width;pos++)
- {
- left++; // one more character that fits
- }
- // for the text on the right we can now use all the remaining pixels
- // I reuse the half_width variable - it's roughly half the width anyway
- half_width=width-FntCharsWidth(text,pos); // Pos, not Pos+1, because of the Pos++ above
- // how many characters from the right make up just under the remaining space
- right=1; // at least one
- // add characters until we'd exceed the remaining space
- for (pos=text_len-2;pos>=0 && FntCharsWidth(text+pos,text_len-pos)<=half_width;pos--)
- {
- right++;
- }
- // First we draw 'Left' characters from the left
- WinDrawChars(text,left,x,y);
- // adjust x
- x+=FntCharsWidth(text,left);
- // draw the ellipse
- WinDrawChars(ellipse,StrLen(ellipse),x,y);
- // adjust x again
- x+=FntCharsWidth(ellipse,StrLen(ellipse));
- // now draw the stuff on the right
- WinDrawChars(text+(text_len-right),right,x,y);
- }
- return;
- }
-
- // Initialize the main form
- static void MainViewInit(void)
- {
- FormPtr frm;
- ListPtr list;
-
- // Get a pointer to the main form.
- frm = FrmGetActiveForm();
- list=FrmGetObjectPtr(frm,FrmGetObjectIndex(frm,GetTLEMainSitesList));
- // set the text in the entry fields to the right values
- SetFieldTextFromString(GetTLEMainURLField,Prefs.URL);
- // now take care of the list
- LstSetListChoices(list,NULL,NumSites);
- LstSetDrawFunction(list,ListDrawFunction);
- // Clear the progress indicator
- ClearProgress();
- // Draw the form.
- FrmEraseForm(frm);
- FrmDrawForm(frm);
- return;
- }
-
- // returns (locked) text in a field object
- static char *GetLockedPtr(UInt16 objectID)
- {
- FormPtr frm = FrmGetActiveForm();
- FieldPtr fld = FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, objectID));
- MemHandle h = FldGetTextHandle(fld);
-
- if (h)
- return MemHandleLock(h);
- else
- return 0;
- }
-
- // The main form got an event
- static Boolean MainViewHandleEvent(EventPtr event)
- {
- Boolean handled;
- UInt16 interfaceError;
- Err error;
- UInt16 PrefLen=0;
- Char *URL;
- UInt16 TLEs=0;
- Char Message[64];
- FormPtr Form;
-
- // initially we haven't handled the event
- handled = false;
- // now we look at the event type
- switch (event->eType)
- {
- case ctlSelectEvent: // A control button was pressed and released.
- if (event->data.ctlEnter.controlID == GetTLEMainSendButton)
- {
- // This was the 'Get' button -
- if (SysLibFind( "Net.lib", &AppNetRefnum) == 0)
- {
- LogMessage("Found NetLib\n");
- // lock the two text fields containing hostname and filename
- URL = GetLockedPtr(GetTLEMainURLField);
- // Make sure we actually were able to lock the fields
- if (!URL)
- {
- MyErrorFunc("Missing URL", NULL);
- }
- else
- {
- LogMessage("Opening NetLib\n");
- error = NetLibOpen(AppNetRefnum, &interfaceError);
- if (interfaceError != 0)
- {
- MyErrorFunc("NetLibOpen: interface error", NULL);
- NetLibClose(AppNetRefnum, true);
- }
- else if (error == 0 || error == netErrAlreadyOpen)
- {
- AppNetTimeout=SysTicksPerSecond()*10;
- LogMessage("Will request doc now\n");
- ClearProgress();
- TLEs=RequestDocument(URL);
- ClearProgress();
- StrIToA(Message,TLEs);
- StrCat(Message," TLE sets received.");
- MyStatusFunc(Message);
- LogMessage("%s\n",Message);
- if (TLEs>0)
- {
- // that url worked - make it our preference
- // first copy the stuff to the Prefs
- StrCopy(Prefs.URL,URL);
- PrefLen=sizeof(Prefs);
- PrefSetAppPreferences(CreatorID,PrefID,Version,&Prefs,PrefLen,true);
- LogMessage("saved preferences %i bytes:\n",PrefLen);
- LogMessage("http://%s",Prefs.URL);
- }
- else
- {
- LogMessage("Receive failed: %i\n",errno);
- }
- NetLibClose(AppNetRefnum, false);
- }
- else
- {
- MyErrorFunc("netLibOpen error", NULL);
- }
- }
- if (URL)
- {
- MemPtrUnlock(URL);
- }
- }
- else
- {
- MyErrorFunc("Can't SysLibFind", NULL);
- }
- // Whatever the outcome - we have handled the event
- handled = true;
- }
- else
- {
- // No other controls for this application
- }
- break;
- case frmOpenEvent:
- // When the form gets opened we have to draw it
- FrmDrawForm(FrmGetActiveForm());
- // MainViewInit() sets the text fields with hostname and
- // filename to the default or preferences values
- MainViewInit();
- handled = true;
- break;
- case popSelectEvent:
- SetFieldTextFromString(GetTLEMainURLField,SiteUrls[event->data.popSelect.selection]);
- handled = true;
- break;
- case menuEvent:
- switch (event->data.menu.itemID)
- {
- case MainOptionsAboutGetTLE:
- MenuEraseStatus(0); // Clear the menu status from the display.
- Form = FrmInitForm (AboutForm);
- FrmDoDialog (Form); // Display the About Box.
- FrmDeleteForm (Form);
- handled = true;
- break;
- case MainOptionsClearDatabase:
- MenuEraseStatus(0);
- ClearPSatDB();
- break;
- case MainOptionsStartStopLogging:
- {
- Prefs.debugging_enabled=!Prefs.debugging_enabled;
- if (Prefs.debugging_enabled)
- {
- StartDebugMessages();
- MyStatusFunc("Now logging to Memo Pad");
- }
- else
- {
- StopDebugMessages();
- MyStatusFunc("Stopped logging to Memo Pad");
- }
- // this changes our preferences - save them
- PrefLen=sizeof(Prefs);
- PrefSetAppPreferences(CreatorID,PrefID,Version,&Prefs,PrefLen,true);
- LogMessage("saved preferences %i bytes:\n",PrefLen);
- }
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- return(handled);
- }
-
- // Event handler for the application
- static Boolean ApplicationHandleEvent(EventPtr event)
- {
- FormPtr frm;
- UInt16 formId;
- Boolean handled = false;
-
- if (event->eType == frmLoadEvent)
- {
- // Load the form resource specified in the event then activate the form.
- formId = event->data.frmLoad.formID;
- frm = FrmInitForm(formId);
- FrmSetActiveForm(frm);
- // tell the form about its event handler
- switch (formId)
- {
- case GetTLEMainForm:
- FrmSetEventHandler(frm, MainViewHandleEvent);
- break;
- default:
- break;
- }
- handled = true;
- }
- return handled;
- }
-
- // Standard stuff in here
- static void EventLoop(void)
- {
- EventType event;
- UInt16 error;
-
- do
- {
- EvtGetEvent(&event, evtWaitForever);
- if (! SysHandleEvent(&event))
- {
- if (! MenuHandleEvent(0, &event, &error))
- {
- if (! ApplicationHandleEvent(&event))
- {
- FrmDispatchEvent(&event);
- }
- }
- }
- }
- while (event.eType != appStopEvent);
- return;
- }
- // Standard stuff in here too
-
- UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
- {
- UInt16 error;
-
- // Check the OS version
- error = RomVersionCompatible (version20, launchFlags);
- if (error)
- {
- return error;
- }
- // how was the application lauched?
- if (cmd == sysAppLaunchCmdNormalLaunch)
- {
- // normal launch is the only way we do support
- // try to initialize the application
- if (!StartApplication())
- {
- // Now show the main form
- FrmGotoForm(GetTLEMainForm);
- // and start the event loop
- EventLoop();
- // the event loop only quits for an appStopEvent
- // so we try to stop the application
- StopApplication();
- }
- }
- // and that's the end of our program
- return 0;
- }
-