home *** CD-ROM | disk | FTP | other *** search
/ Hand Held Organizer Toolkit / walnutcreekcdrom-handheldorganizertoolkit-march1998.iso / PalmPilot / development / sample_source_code / simpleterm_srcs.txt < prev    next >
C/C++ Source or Header  |  1997-12-30  |  29KB  |  1,177 lines

  1.  
  2.  
  3. /* serial.c - basis of SimpleTerm 0.5, a simple Pilot terminal */
  4. /* 
  5.  
  6.    Feel free to use this code as you wish, no guarantees are given 
  7.    or implied. The code was not designed to be seen by others, it just
  8.    turned out that way! Excuse the mess, it was quick and dirty, but fun!
  9.    
  10.     
  11.    Whilst I'll endeavour to help when I can, I can't promise to reply to all
  12.    email or give detailed explanations of the code. Let me know if anything
  13.    interesting arises - especially that elusive VT100 terminal!
  14.    
  15.    Have fun,
  16.    Iain - isb@pobox.com
  17.    
  18.    Hints
  19.    -----
  20.    
  21.    I never got this to run under the emulator, all my debugging had to be 
  22.    done after loading to the Pilot.
  23.    
  24.    
  25.    Please distribute anything interesting that comes of this, people really seem 
  26.    to appreciate it!
  27.    
  28. */
  29.  
  30.  
  31. /* This code was once... */
  32.  
  33.  
  34.  
  35. /***********************************************************************
  36.  *
  37.  *    Copyright (c) Palm Computing 1995 -- All Rights Reserved
  38.  *
  39.  * PROJECT: Memo Pad Sample Application
  40.  *
  41.  * FILE: MemoPad.c (Phase 1)
  42.  *
  43.  * DESCRIPTION: Sample application to demonstrate the various
  44.  *     features available.
  45.  *
  46.  *    OBJECTIVE: Create an initial main form with a title and an
  47.  *     exit button.
  48.  *
  49.  * REVISION HISTORY:
  50.  *      9/1/95    David        Initial version
  51.  *
  52.  **********************************************************************/
  53.  
  54. #include <Pilot.h>                // all the system toolbox headers
  55. #include <SerialMgr.h>
  56.  
  57. #include "serialRsc.h"        // application resource defines
  58.  
  59.  
  60.  
  61. //Code for Doc database logging
  62.  
  63. typedef    struct trecord0 {
  64.         Word    compression_type;
  65.         Word    spare;
  66.         DWord    story_length;
  67.         Word    num_records;
  68.         Word    reclen;        // normall 0x1000;
  69. } Record0Type;
  70.  
  71. typedef struct
  72.     {
  73.         Int baud;
  74.         Int bits;
  75.         Int parity;
  76.         Int xon;
  77.         Int rts;
  78.         Int version;
  79.     } SimplePreferenceType;
  80.  
  81. SimplePreferenceType prefs;
  82.  
  83. // Application database management defines.
  84. #define JDocAppType        'JDoc'            // P5. type for application. J-DOC
  85. #define JDocDBCreator    'REAd'            // P5. name for application 'DOC'
  86. #define JDocDBType        'TEXt'            // P5. type for application 'DOC'
  87. #define JDocVersionNum    1
  88.  
  89. #define null 0
  90.  
  91. /***********************************************************************
  92.  * Prototypes for internal functions
  93.  **********************************************************************/
  94. static Err StartApplication(void);
  95. static void StopApplication(void);
  96.  
  97. static Boolean MainFormHandleEvent(EventPtr event);
  98. static Boolean SetFormHandleEvent(EventPtr event);
  99. static void SetCurrentMenu(Word rscID);    // P2. set new current menu
  100. static void EventLoop(void);
  101. static Boolean RxData();
  102. static void ClrScreen();
  103. static void SetSerialSettings();
  104. static void OptionsApply();
  105.  
  106. void WriteDB( CharPtr, int);
  107. void CloseDB(void);
  108. Boolean CreateLogDB(CharPtr);
  109. FieldPtr GetFocusObjectPtr (void);
  110.  
  111. extern void YieldTime();
  112.  
  113.  
  114. void YieldTime() {return;}
  115.  
  116. static MenuBarPtr        CurrentMenu = NULL;    // P2. ptr to current menu
  117.  
  118. UInt SerialRef;
  119. static SerSettingsType SerialSettings;
  120. static DmOpenRef        CurrentDB;
  121.  
  122. Int Bits = 8;
  123. Int Parity = 0; //Use 0 for none, 1 for odd and 2 for even!
  124. Int Baud = 19200;
  125. Int Xon = 1;
  126. Int Rts = 1;
  127. Int Version = 5;
  128.  
  129. static char InputStr[80];
  130. char OutputStr[4200] = "";
  131. char newBuff[1001] = "";
  132.  
  133. Handle bufferHandle;
  134. static Boolean portClosed;
  135.  
  136. /***********************************************************************
  137.  *
  138.  * FUNCTION:     StartApplication
  139.  *
  140.  * DESCRIPTION:  This routine sets up the initial state of the application.
  141.  *
  142.  * PARAMETERS:   None.
  143.  *
  144.  * RETURNED:     Nothing.
  145.  *
  146.  ***********************************************************************/
  147. static Err StartApplication(void)
  148. {
  149.     FormPtr    frm;
  150.     ControlPtr closePtr;    
  151.     ControlPtr openPtr;
  152.     ControlPtr sendPtr;        
  153.     FieldPtr opPtr;    
  154.  
  155.     Err error;
  156.     
  157.     //Try to open the serial port...
  158.     error = SysLibFind("Serial Library", &SerialRef);
  159.     if (error)
  160.         ErrDisplay("Error trying to load the serial library");
  161.  
  162.  
  163.     // Initialize and draw the main form.
  164.     frm = FrmInitForm(mainForm);    
  165.     FrmSetActiveForm(frm);
  166.  
  167.     closePtr = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainCloseButton))));
  168.     CtlSetEnabled(closePtr, false);
  169.     sendPtr = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainSendButton))));
  170.     CtlSetEnabled(sendPtr, false);
  171.     openPtr = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainOpenButton))));
  172.     CtlSetEnabled(openPtr, true);
  173.         
  174.     FrmDrawForm(frm);
  175.     SetCurrentMenu(mainMenu);        // P2. set the current menu to the main menu
  176.  
  177.     bufferHandle = MemHandleNew(10);
  178.     portClosed = true;
  179.     
  180.     opPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainOPField))));
  181.     FldSetTextPtr(opPtr, "Welcome to SimpleTerm - V0.5\rConnect the Pilot to a modem via the cradle (with NullModem) or cable, tap 'Online' to connect. Enter AT commands to dial the modem - tap \'Send\' to transmit data. The checkbox toggles whether a Return is sent. To send an Escape type \'esc\', to send a control character (eg.x) type \'ctlx\'\r                    Have fun... isb@pobox.com");
  182.     FldRecalculateField(opPtr, true);
  183.  
  184.     if (PrefGetAppPreferences('Seri', 1, &prefs, sizeof(SimplePreferenceType)) != NULL)
  185.     {
  186.         Baud = prefs.baud;
  187.         Parity = prefs.parity;
  188.         Rts = prefs.rts;
  189.         Xon = prefs.xon;
  190.         Bits = prefs.bits;
  191.     }
  192.     
  193.     CurrentDB = 0;    
  194.     
  195.     return 0;
  196. }
  197.  
  198. static void StopApplication (void)
  199. {
  200.     //ErrDisplay("Stop App called!");
  201.     if (!portClosed)
  202.     {
  203.         SerClose(SerialRef);
  204.     }         
  205.     if ( CurrentDB !=0)
  206.         CloseDB();
  207. }
  208.  
  209.  
  210. /***********************************************************************
  211.  *
  212.  * FUNCTION:    SetCurrentMenu
  213.  *
  214.  * DESCRIPTION: P2. This routine loads the specified menu resource and makes
  215.  *              it the current menu.  
  216.  *
  217.  * PARAMETERS:  rscID  - resource id of the new menu
  218.  *
  219.  * RETURNED:    nothing
  220.  *
  221.  ***********************************************************************/
  222. static void SetCurrentMenu(Word rscID)
  223. {
  224.     // Dispose of an existing current menu.
  225.     if (CurrentMenu)
  226.         MenuDispose(CurrentMenu);
  227.     
  228.     // Set the current menu and remember it.
  229.     CurrentMenu = MenuInit(rscID);
  230. }
  231.  
  232. static Boolean RxData()
  233. {
  234.             FormPtr frm;
  235.             FieldPtr opPtr;    
  236.             ULong numBytes = 0;            
  237.             CharPtr buffer;
  238.             Err error;
  239.             int i, attempt;
  240.             int lineCnt = 0;
  241.             Boolean success;
  242.             Handle textHandle;
  243.                     
  244.             if (portClosed)
  245.                 return false;
  246.                                 
  247.             // Get the text from the send box...
  248.             frm = FrmGetFormPtr(mainForm);
  249.             opPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainOPField))));
  250.                                             
  251.             error = SerReceiveCheck(SerialRef, &numBytes);
  252.             if (error)
  253.             {
  254.                 SerClearErr(SerialRef);                    
  255.                 //ErrNonFatalDisplayIf(true, "Could not read the number of bytes in the receive queue");
  256.                 StrCat(OutputStr, "Error reading number of bytes");
  257.                                             
  258.                 FldSetTextPtr(opPtr, OutputStr);
  259.                 FldRecalculateField(opPtr, true);
  260.                 FldScrollField(opPtr, lineCnt+100, down);
  261.                 return false;
  262.             }
  263.             else
  264.             if (numBytes <= 0)
  265.                     return false;
  266.     
  267.             if (numBytes > 1000)
  268.                 numBytes = 1000;
  269.  
  270.             MemHandleResize(bufferHandle, numBytes+10);
  271.                 
  272.             // Lock down the handle and get a pointer to the memory chunk.
  273.             buffer = MemHandleLock(bufferHandle);
  274.                         
  275.             attempt = 0;
  276.             success = false;                    
  277.  
  278.             StrCopy(buffer, "");
  279.             error = SerReceive(SerialRef, buffer, numBytes, -1);    
  280.             if (error) //failed to get the data
  281.             {
  282.                     //What's the error?
  283.                     if (error == serErrTimeOut)
  284.                     {
  285.                         StrCopy(buffer, "timeout");
  286.                     }
  287.                     else
  288.                     if (error == serErrLineErr)
  289.                     {
  290.                         Boolean x;
  291.                         Boolean y;
  292.                         Word err;
  293.                         
  294.                         // The next line causes the Mac linker to fail, but works
  295.                         // with the 'real' linker
  296.                         err = SerGetStatus(SerialRef, &x, &y);
  297.                         if (err==serLineErrorParity)
  298.                         {
  299.                             StrCopy(buffer, "parity");
  300.                         }
  301.                         else
  302.                         if (err==serLineErrorHWOverrun)
  303.                         {
  304.                             StrCopy(buffer, "HW overrun");
  305.                         }
  306.                         else
  307.                         if (err==serLineErrorFraming)
  308.                         {
  309.                             StrCopy(buffer, "framing");
  310.                         }
  311.                         else
  312.                         if (err==serLineErrorBreak)
  313.                         {
  314.                             StrCopy(buffer, "break");
  315.                         }
  316.                         else
  317.                         if (err==serLineErrorHShake)
  318.                         {
  319.                             StrCopy(buffer, "handshake");
  320.                         }
  321.                         else
  322.                         if (err==serLineErrorSWOverrun)
  323.                         {
  324.                             StrCopy(buffer, "SW overrun");
  325.                         }
  326.                     }
  327.                     
  328.                 SerClearErr(SerialRef);
  329.  
  330.             }
  331.                                 
  332.             buffer[numBytes] = '\0';
  333.             
  334.             for (i=0; i<numBytes; i++)
  335.             {
  336.                 if ((int)(buffer[i]) == 13)
  337.                 {
  338.                     buffer[i]='\r';
  339.                     lineCnt++;
  340.                 }
  341.                 else
  342.                 if ((int)(buffer[i]) == 10)
  343.                 {
  344.                     buffer[i] = '\r';
  345.                     lineCnt++;
  346.                 }
  347.                 /* This is where to trap chars for VT100 etc.
  348.                 else
  349.                 if  ((int)(buffer[i]) == 27)
  350.                 {
  351.                     //buffer[i]=' '; //Can't remember what this char is!
  352.                 }
  353.                 else
  354.                 if  ((int)(buffer[i]) < 32)
  355.                 {
  356.                     //buffer[i]=' ';
  357.                 }
  358.                 */
  359.             }
  360.  
  361.                      
  362.             if ( (StrLen(buffer) + StrLen(OutputStr)) >= 4000)
  363.             {
  364.                 StrCopy(OutputStr, ""); // A bit crap, as it just blasts the array away.
  365.                 FldSetScrollPosition(opPtr, 0);
  366.             }
  367.                                                             
  368.             //Set the OPText field to show the buffer    
  369.             StrCat(OutputStr, buffer);
  370.                                             
  371.             FldSetTextPtr(opPtr, OutputStr);
  372.             FldRecalculateField(opPtr, true);
  373.             FldScrollField(opPtr, lineCnt+100, down);
  374.             
  375.             if ( CurrentDB != 0)
  376.                 WriteDB( buffer, strlen(buffer) );
  377.                     
  378.             // Unlock the new memory chunk.
  379.             MemHandleUnlock(bufferHandle);        
  380.                         
  381.             return true;
  382. }
  383.  
  384. void SetSerialSettings()
  385. {
  386.         Err error;
  387.         
  388.         SerialSettings.baudRate = Baud;
  389.         SerialSettings.flags = 0;
  390.         SerialSettings.ctsTimeout = serDefaultCTSTimeout;
  391.  
  392.         if (Xon == 1)
  393.             SerialSettings.flags =  serSettingsFlagXonXoffM;
  394.  
  395.         if (Bits == 7)
  396.         {
  397.             SerialSettings.flags = serSettingsFlagStopBits1 | serSettingsFlagBitsPerChar7;            
  398.         }
  399.         else
  400.         {
  401.             SerialSettings.flags = (SerialSettings.flags) | serSettingsFlagStopBits1 | serSettingsFlagBitsPerChar8;    
  402.         }
  403.  
  404.         if (Rts == 1)
  405.             SerialSettings.flags = (SerialSettings.flags) | serSettingsFlagCTSAutoM | serSettingsFlagRTSAutoM;    
  406.                  
  407.         if (Parity == 1)
  408.         {
  409.             SerialSettings.flags = (SerialSettings.flags) | serSettingsFlagParityOnM;            
  410.         }
  411.         else
  412.         if (Parity == 2)
  413.         {
  414.             SerialSettings.flags = (SerialSettings.flags) | serSettingsFlagParityOnM | serSettingsFlagParityEvenM;    
  415.         }
  416.         
  417.         error = SerSetSettings(SerialRef, &SerialSettings);
  418.         if (error)
  419.         {
  420.             SerClearErr(SerialRef);
  421.             ErrDisplay("Error when setting serial port values");
  422.         }
  423.         
  424.         prefs.baud = Baud;
  425.         prefs.rts = Rts;
  426.         prefs.xon = Xon;
  427.         prefs.bits = Bits;
  428.         prefs.parity = Parity;
  429.         prefs.version = Version;
  430.         
  431.         PrefSetAppPreferences('Seri', 1, &prefs, sizeof(SimplePreferenceType));
  432.  
  433. }
  434.  
  435.  
  436. /***********************************************************************
  437.  *
  438.  * FUNCTION:        MainFormHandleEvent
  439.  *
  440.  * DESCRIPTION:    Handles processing of events for the ╥main╙ form.
  441.  *
  442.  * PARAMETERS:        event    - the most recent event.
  443.  *
  444.  * RETURNED:        True if the event is handled, false otherwise.
  445.  *
  446.  ***********************************************************************/
  447. static Boolean MainFormHandleEvent(EventPtr event)
  448. {
  449.     Boolean        handled = false;
  450.     Err error;
  451.     
  452.    if (event->eType == ctlSelectEvent)
  453.        {
  454.             
  455.             // P3. If the new button is pressed, go to the edit form.
  456.                 if (event->data.ctlEnter.controlID == mainOpenButton)
  457.                 {
  458.                         FormPtr frm;
  459.                         ControlPtr closePtr;    
  460.                         ControlPtr openPtr;
  461.                         ControlPtr sendPtr;            
  462.         
  463.     
  464.                         if (!portClosed)
  465.                             return false; // Port is already open!
  466.                             
  467.                         error = SerOpen(SerialRef, 0, Baud);
  468.                         // Best do something if there's an error!
  469.                         if (error)
  470.                         {
  471.                             ErrNonFatalDisplayIf( (error == serErrAlreadyOpen), "Another application is using the serial port");
  472.                             ErrNonFatalDisplayIf( (error == memErrNotEnoughSpace), "Not enough memory to open the serial port");
  473.                             ErrNonFatalDisplayIf( (error == serErrBadParam), "The serial port could not be opened");
  474.                             return true;
  475.                         }
  476.                             
  477.                         SetSerialSettings();
  478.                         
  479.                         //Set the open button not usable and close and send usable
  480.                         frm = FrmGetFormPtr(mainForm);
  481.                         closePtr = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainCloseButton))));
  482.                         CtlSetEnabled(closePtr, true);
  483.                         sendPtr = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainSendButton))));
  484.                         CtlSetEnabled(sendPtr, true);
  485.                         openPtr = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainOpenButton))));
  486.                         CtlSetEnabled(openPtr, false);
  487.                         
  488.                         portClosed = false;
  489.                         CreateLogDB("SimpleTerm-log");
  490.  
  491.                         handled = true;
  492.                 }
  493.             else
  494.               if (event->data.ctlEnter.controlID == mainCloseButton)
  495.                 {        
  496.                         FormPtr frm;
  497.                         ControlPtr closePtr;    
  498.                         ControlPtr openPtr;
  499.                         ControlPtr sendPtr;            
  500.  
  501.                         if (portClosed)
  502.                             return false;
  503.  
  504.                         CloseDB();
  505.                                             
  506.                         error = SerClose(SerialRef);
  507.                         if (error)
  508.                         {
  509.                             ErrNonFatalDisplayIf(true, "The serial port could not be closed");
  510.                             return true;
  511.                         }
  512.  
  513.                         frm = FrmGetFormPtr(mainForm);
  514.                         closePtr = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainCloseButton))));
  515.                         CtlSetEnabled(closePtr, false);
  516.                         sendPtr = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainSendButton))));
  517.                         CtlSetEnabled(sendPtr, false);
  518.                         openPtr = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainOpenButton))));
  519.                         CtlSetEnabled(openPtr, true);
  520.                             
  521.                         portClosed = true;
  522.                         handled = true;
  523.                 }
  524.             else
  525.             if (event->data.ctlEnter.controlID == mainSendButton)
  526.                 {        
  527.                     FormPtr frm;
  528.                     FieldPtr ipPtr;
  529.                     ControlPtr ctl;                
  530.     
  531.                     if (portClosed)
  532.                         return false;
  533.     
  534.                     
  535.                     // Get the text from the send box...
  536.                     frm = FrmGetFormPtr(mainForm);
  537.                     ipPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainIPField))));
  538.  
  539.                     if (FldGetTextPtr(ipPtr) != NULL)
  540.                         StrCopy(InputStr, FldGetTextPtr(ipPtr));
  541.                     else
  542.                         return false;
  543.                         
  544.                     if (!StrCaselessCompare("esc", InputStr))
  545.                     {
  546.                         //Send an escape character
  547.                         //Copy char(27) to InputStr
  548.                         StrCopy(InputStr, " ");
  549.                         InputStr[0] = (char)27;
  550.                     }
  551.                     else
  552.                     if (StrLen(InputStr)==4) //It could be ctlx - need to check the first three chars
  553.                     {
  554.                         //Do a check
  555.                         //If the first bit matches, then subtract 96 to make it a CTRL-x
  556.                         //Be wary that this is case sensitive!
  557.                         
  558.                         char temp[5] = "";
  559.                         
  560.                         StrCopy(temp, InputStr);
  561.                         temp[3] = '\0';
  562.                         
  563.                         if (!StrCaselessCompare("ctl", temp))
  564.                         {
  565.                             //We're in business!
  566.                             StrToLower(temp, InputStr);
  567.                             StrCopy(InputStr, " ");
  568.                             InputStr[0] = (char)((Word)temp[3] - 96);
  569.                         }
  570.                         //Not ctl - never mind!                    
  571.                     }
  572.                     
  573.                     error = SerSend(SerialRef, InputStr, StrLen(InputStr));
  574.                     ErrNonFatalDisplayIf( (error!=0), "Handshaking timed out when trying to send data (use CTS/RTS)");
  575.                     if (error)                    
  576.                         SerClearErr(SerialRef);    
  577.                     
  578.                     //Lets see if the user wants a CR appended...
  579.                     ctl = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainCRBox))));
  580.                     if (CtlGetValue (ctl))
  581.                     {
  582.                         error = SerSend(SerialRef, "\n", StrLen("\n"));
  583.                         ErrNonFatalDisplayIf( (error!=0), "Handshaking timed out when trying to send CR character");
  584.                     }
  585.                     
  586.                     //Clear the field
  587.                     if (!error)
  588.                         FldDelete(ipPtr, 0, FldGetTextLength(ipPtr));
  589.                     
  590.                     //Just pause until the send buffer clears...
  591.                     SerSendWait(SerialRef, -1);
  592.                     
  593.                     handled = true;
  594.                                                 
  595.                     RxData(); //Check for anything received                                                                                 
  596.                 }
  597.                 else
  598.                 if (event->data.ctlEnter.controlID == mainClearButton)
  599.                 {        
  600.                     //Clear all the boxes
  601.                     FormPtr frm;
  602.                     FieldPtr opPtr;    
  603.  
  604.                     frm = FrmGetFormPtr(mainForm);
  605.                     opPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainOPField))));
  606.     
  607.                     StrCopy(OutputStr, ""); // A bit crap, as it just blasts the array away.
  608.                                                     
  609.                     FldSetTextPtr(opPtr, OutputStr);
  610.                     FldDrawField(opPtr);
  611.                     FldSetScrollPosition(opPtr, 0);
  612.                     handled = true;
  613.                 }
  614.         }
  615.         else
  616.         if (event->eType == nilEvent)
  617.         {        
  618.                 while (RxData());
  619.                 
  620.                 handled = true;
  621.         }
  622.         else
  623.         if (event->eType == keyDownEvent)
  624.         {
  625.         // Scroll up key presed?
  626.            if (event->data.keyDown.chr == pageUpChr)
  627.             {
  628.                     FormPtr frm;
  629.                     FieldPtr opPtr;    
  630.  
  631.                     // Get the text from the send box...
  632.                     frm = FrmGetFormPtr(mainForm);
  633.                     opPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainOPField))));
  634.                     FldScrollField( opPtr, 1, up);
  635.                     handled = true;
  636.             }
  637.  
  638.         // Scroll down key presed?
  639.         else if (event->data.keyDown.chr == pageDownChr)
  640.             {
  641.                     FormPtr frm;
  642.                     FieldPtr opPtr;    
  643.  
  644.                     // Get the text from the send box...
  645.                     frm = FrmGetFormPtr(mainForm);
  646.                     opPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainOPField))));
  647.                     FldScrollField( opPtr, 1, down);
  648.                     handled = true;
  649.             }
  650.         else if (event->data.keyDown.chr != 0)
  651.             {
  652.  
  653.                 FormPtr frm;
  654.                 FieldPtr ipPtr;
  655.                 // Get the text from the send box...
  656.                 frm = FrmGetFormPtr(mainForm);
  657.                 ipPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainIPField))));
  658.  
  659.                if (GetFocusObjectPtr () != ipPtr)
  660.                {
  661.                     // A cool idea from yamada@mm.rd.nttdata.co.jp (YAMADA Tatsushi)                            
  662.                     StrCopy(InputStr, " ");
  663.                     InputStr[0] =  event->data.keyDown.chr;
  664.                     if ( event->data.keyDown.chr == '\r')
  665.                         InputStr[0] =  '\n';
  666.                     InputStr[1] = 0;
  667.                     error = SerSend(SerialRef, InputStr, StrLen(InputStr));
  668.                     ErrNonFatalDisplayIf( (error!=0), "Handshaking timed out when trying to send data (use CTS/RTS)");
  669.                                 
  670.                     //Just pause until the send buffer clears...
  671.                     SerSendWait(SerialRef, -1);    
  672.                     handled = true;
  673.                     RxData();            
  674.                 }
  675.             }
  676.         }
  677.           else 
  678.           if (event->eType == menuEvent)        // P2. process menu events for this form
  679.         {
  680.             FormPtr frm;
  681.             int i;
  682.             ListPtr listP;
  683.             
  684.             // A menu item was selected.
  685.             // The ╥prefs╙ being the only menu item, display the info form.
  686.         
  687.             // First clear the menu status from the display.
  688.             if (event->data.menu.itemID == settingsCmd)
  689.             {
  690.                 ControlPtr ctl;
  691.                 
  692.                 MenuEraseStatus(CurrentMenu);
  693.                 
  694.                 // Load the info form, then display it.
  695.                 frm = FrmInitForm(setForm);
  696.                 //FrmDoDialog(frm);
  697.                 FrmDrawForm(frm);
  698.                 FrmSetActiveForm(frm);
  699.             
  700.                 ctl = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, setXonBox))));
  701.                 if (Xon == 1)
  702.                     CtlSetValue (ctl, 1);
  703.                 else
  704.                     CtlSetValue (ctl, 0);
  705.  
  706.                 ctl = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, setRtsBox))));
  707.                 if (Rts == 1)
  708.                     CtlSetValue (ctl, 1);
  709.                 else
  710.                     CtlSetValue (ctl, 0);                
  711.                 
  712.                 if (Bits == 7)
  713.                     FrmSetControlGroupSelection(frm, 1, set7);
  714.                 else
  715.                     FrmSetControlGroupSelection(frm, 1, set8);
  716.                 
  717.                 if (Parity == 1)        
  718.                     FrmSetControlGroupSelection(frm, 2, setO);
  719.                 else
  720.                 if (Parity == 2)
  721.                     FrmSetControlGroupSelection(frm, 2, setE);
  722.                 else
  723.                     FrmSetControlGroupSelection(frm, 2, setN);
  724.  
  725.                 if (Baud == 1200)
  726.                     FrmSetControlGroupSelection(frm, 3, setBaud1);
  727.                 else
  728.                 if (Baud == 2400)
  729.                     FrmSetControlGroupSelection(frm, 3, setBaud2);
  730.                 else                
  731.                 if (Baud == 4800)
  732.                     FrmSetControlGroupSelection(frm, 3, setBaud4);
  733.                 else                
  734.                 if (Baud == 9600)
  735.                     FrmSetControlGroupSelection(frm, 3, setBaud9);
  736.                 else
  737.                     FrmSetControlGroupSelection(frm, 3, setBaud19);
  738.  
  739.             }
  740.             else
  741.             {
  742.                 //This is one from the edit menu...
  743.                 if (event->data.menu.itemID == copyCmd)
  744.                 {
  745.                     FormPtr frm;
  746.                     FieldPtr opPtr;
  747.                     Word len;    
  748.  
  749.                     // Copy the output text to the clipboard
  750.                     // The clipboard is only 1k big :^(
  751.                     //Lets go for the top of the screen + 1000 chars
  752.                     
  753.                     frm = FrmGetFormPtr(mainForm);
  754.                     opPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainOPField))));
  755.                     len = FldGetTextLength(opPtr);
  756.                     if (len>1000)
  757.                         len = 1000;
  758.                         
  759.                     FldSetSelection(opPtr, 0, len);
  760.                     FldCopy(opPtr);
  761.                     FldSetSelection(opPtr, 0, 0);
  762.                     
  763.                     handled = true;
  764.                 }
  765.                 else
  766.                 if (event->data.menu.itemID == pasteCmd)
  767.                 {
  768.                     FormPtr frm;
  769.                     FieldPtr ipPtr;    
  770.  
  771.                     // Copy the output text to the clipboard
  772.                     frm = FrmGetFormPtr(mainForm);
  773.                     ipPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainIPField))));
  774.                     FldPaste(ipPtr);
  775.                     
  776.                     handled = true;
  777.                 }
  778.                 else
  779.                 if (event->data.menu.itemID == keybdCmd)
  780.                 {
  781.                     SysKeyboardDialog();
  782.                     handled = true;                    
  783.                 }
  784.                         
  785.                 MenuEraseStatus(CurrentMenu);
  786.             }
  787.             
  788.             handled = true;
  789.         }
  790.  
  791.     return handled;
  792. }
  793.  
  794. static Boolean SetFormHandleEvent(EventPtr event)
  795. {
  796.     Boolean        handled = false;
  797.     Err error;
  798.     FormPtr frm;
  799.  
  800.     //ErrDisplay("Set form Handler came thru top");
  801.  
  802.     if (event->eType == ctlSelectEvent)
  803.     {
  804.         switch (event->data.ctlSelect.controlID)
  805.         {
  806.             case setOK:
  807.             {
  808.                 //OptionsApply ();
  809.                 Byte sel;
  810.                 Word ctl;
  811.                 ListPtr listP;
  812.                 ControlPtr chk;
  813.                 int i=0;  
  814.                         
  815.                 frm = FrmGetFormPtr(setForm);
  816.                 chk = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, setXonBox))));
  817.                 if (CtlGetValue (chk))
  818.                     Xon = 1;
  819.                 else
  820.                     Xon = 0;
  821.  
  822.                 chk = (ControlPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, setRtsBox))));
  823.                 if (CtlGetValue (chk))
  824.                     Rts = 1;
  825.                 else
  826.                     Rts = 0;
  827.                     
  828.                 sel = FrmGetControlGroupSelection(frm, 1);                
  829.                 ctl = FrmGetObjectId (frm, sel);                
  830.                 if (ctl == set7)
  831.                 {
  832.                     //ErrDisplay("7 bits set");
  833.                     Bits = 7;
  834.                 }    
  835.                 else
  836.                     Bits = 8;
  837.                     
  838.                 sel = FrmGetControlGroupSelection(frm, 2);
  839.  
  840.                 if (sel == -1)
  841.                     ErrDisplay("No parity selected");
  842.                     
  843.                 ctl = FrmGetObjectId (frm, sel);
  844.                                 
  845.                 if (ctl == setO)
  846.                 {
  847.                     Parity = 1;
  848.                 }
  849.                 else
  850.                 if (ctl == setE)
  851.                 {
  852.                     Parity = 2;
  853.                 }    
  854.                 else
  855.                     Parity = 0;
  856.                                 
  857.                 sel = FrmGetControlGroupSelection(frm, 3);                
  858.                 ctl = FrmGetObjectId (frm, sel);
  859.                 
  860.                 if (ctl == setBaud1)
  861.                     Baud = 1200;
  862.                 else
  863.                 if (ctl == setBaud2)
  864.                     Baud = 2400;
  865.                 else
  866.                 if (ctl == setBaud4)
  867.                     Baud = 4800;
  868.                 else
  869.                 if (ctl == setBaud9)
  870.                     Baud = 9600;
  871.                 else
  872.                     Baud = 19200;
  873.                     
  874.                 SetSerialSettings();
  875.                 FrmReturnToForm (mainForm);
  876.                 FrmUpdateForm (mainForm, frmRedrawUpdateCode);
  877.                 handled = true;
  878.                 break;
  879.             }
  880.             case setCancel:
  881.                 FrmReturnToForm (mainForm);
  882.                 handled = true;
  883.                 break;                
  884.             }
  885.         }
  886.  
  887.     return handled;
  888. }
  889.  
  890.  
  891. /***********************************************************************
  892.  *
  893.  * FUNCTION:        EventLoop
  894.  *
  895.  * DESCRIPTION:    A simple loop that obtains events from the Event
  896.  *                        Manager and passes them on to various applications and
  897.  *                        system event handlers before passing them on to
  898.  *                        FrmHandleEvent for default processing.
  899.  *
  900.  * PARAMETERS:        None.
  901.  *
  902.  * RETURNED:        Nothing.
  903.  *
  904.  ***********************************************************************/
  905. static void EventLoop(void)
  906. {
  907.     EventType    event;
  908.     Word            error;
  909.     
  910.     do
  911.         {
  912.         // Get the next available event.
  913.         if (portClosed) //ie. we are not listening for serial events
  914.             EvtGetEvent(&event, evtWaitForever);
  915.         else // We are so need to react quickly...
  916.             EvtGetEvent(&event, 1); 
  917.                     
  918.         // Give the system a chance to handle the event.
  919.         if (! SysHandleEvent (&event))
  920.  
  921.             // P2. Give the menu bar a chance to update and handle the event.    
  922.             if (! MenuHandleEvent(CurrentMenu, &event, &error))
  923.  
  924.                 // Give the application a chance to handle the event.
  925.                 if (! MainFormHandleEvent(&event))
  926.  
  927.                     if (! SetFormHandleEvent(&event))
  928.     
  929.                         // Let the form object provide default handling of the event.
  930.                         FrmHandleEvent(FrmGetActiveForm(), &event);
  931.         } 
  932.     while (event.eType != appStopEvent);
  933.                                 // ** SPECIAL NOTE **
  934.                                 // In order for the Emulator to exit
  935.                                 // cleanly when the File|Quit menu option is
  936.                                 // selected, the running application
  937.                                 // must exit.  The emulator will generate an 
  938.                                 // ╥appStopEvent╙ when Quit is selected.
  939. }
  940.  
  941.  
  942.  
  943. static FieldPtr GetFocusObjectPtr (void)
  944. {
  945.     FormPtr frm;
  946.     Word focus;
  947.     FormObjectKind objType;
  948.     
  949.     frm = FrmGetActiveForm ();
  950.     focus = FrmGetFocus (frm);
  951.     if (focus == noFocus)
  952.         return (NULL);
  953.         
  954.     objType = FrmGetObjectType (frm, focus);
  955.     
  956.     if (objType == frmFieldObj)
  957.         return (FrmGetObjectPtr (frm, focus));
  958.     
  959.     else if (objType == frmTableObj)
  960.         return (TblGetCurrentField (FrmGetObjectPtr (frm, focus)));
  961.     
  962.     return (NULL);
  963. }
  964.  
  965. //Again some great code given by yamada@mm.rd.nttdata.co.jp (YAMADA Tatsushi)
  966.  
  967. static int dbID;
  968. static long total_length;
  969. static Word current_record;
  970. static int current_pos;
  971. static CharPtr    current_record_ptr;
  972. static Handle current_record_handle;
  973.  
  974. Boolean CreateLogDB(CharPtr dbname)
  975. {
  976.     LocalID    dbID;            
  977.     Handle h;
  978.     Record0Type rec0;
  979.     VoidPtr p;
  980.     Err error;
  981.     Word recnum;
  982.     
  983.  
  984.     CurrentDB = 0;
  985.     return true;
  986.     
  987.     //Not working yet - will log in 'corrupt' Doc format at present
  988.  
  989.     dbID = DmFindDatabase( 0, dbname);
  990.  
  991.     if (dbID) //Delete and replace the database
  992.         DmDeleteDatabase(0, dbID);
  993.  
  994.     
  995.     error = DmCreateDatabase(0, dbname, JDocDBCreator, JDocDBType, false);
  996.     if (error)
  997.         return false;
  998.  
  999.     dbID =  DmFindDatabase ( 0,dbname);
  1000.     CurrentDB = DmOpenDatabase(0, dbID, dmModeReadWrite);
  1001.  
  1002. //Make header in record 0    
  1003.  
  1004.     rec0.compression_type = 1; // no compression
  1005.     rec0.spare = 0x5555;
  1006.     rec0.num_records = 1;
  1007.     rec0.story_length = total_length = 0;
  1008.     rec0.reclen = 0x1000;
  1009.   
  1010.     recnum = 0;
  1011.     h = DmNewRecord( CurrentDB, &recnum, sizeof( Record0Type));
  1012.     p = (Record0Type *)MemHandleLock(h);
  1013.     DmWrite( p, 0L, &rec0, sizeof( rec0));    
  1014.     MemHandleUnlock( h);
  1015.     DmReleaseRecord( CurrentDB, recnum, true);
  1016.  
  1017.     // Make first record for log
  1018.  
  1019.     current_record = 1;
  1020.     current_record_handle = DmNewRecord( CurrentDB, ¤t_record, 0x1000);
  1021.     current_record_ptr = (CharPtr)MemHandleLock(current_record_handle);
  1022.     current_pos=0;    
  1023.         
  1024.     //WinDrawChars("Log opened",10, 100,148);
  1025.  
  1026.     return true;
  1027. }
  1028.  
  1029. void
  1030. CloseDB(void){
  1031.     Record0Type rec0;
  1032.     Word recnum;
  1033.     Handle h;
  1034.     VoidPtr p;
  1035. // compact and release last record
  1036.  
  1037.     if ( CurrentDB == 0 )
  1038.         return;
  1039.     
  1040.     MemHandleUnlock( current_record_handle);
  1041.     MemHandleResize( current_record_handle, current_pos);
  1042.     DmReleaseRecord( CurrentDB, current_record, true);
  1043.  
  1044.     rec0.compression_type = 1; // no compression
  1045.     rec0.spare = 0x5555;
  1046.     rec0.num_records = current_record;
  1047.     rec0.story_length = total_length;
  1048.     rec0.reclen = 0x1000;
  1049.  
  1050.     recnum = 0;
  1051.     h = DmGetRecord( CurrentDB, recnum);
  1052.     p = (Record0Type *)MemHandleLock(h);
  1053.      DmWrite( p, 0L, &rec0, sizeof( rec0));    
  1054.     MemHandleUnlock( h);
  1055.     DmReleaseRecord( CurrentDB, recnum, true);
  1056.  
  1057.     DmCloseDatabase(CurrentDB);
  1058. //    WinDrawChars("Log closed",10, 100,148);
  1059.  
  1060.     CurrentDB = 0;
  1061. }    
  1062.  
  1063. void
  1064. WriteDB( CharPtr c, int len)
  1065. {
  1066.     int temp_len;
  1067.     int tmp;
  1068.     char buf[16];
  1069.     Record0Type rec0;
  1070.     Word recnum;
  1071.     Handle h;
  1072.     VoidPtr p;
  1073.  
  1074.     if ( CurrentDB == 0 )
  1075.         return;
  1076.     /*
  1077.     buf[0] = '0'+ current_record / 10;
  1078.     buf[1] = '0'+ current_record % 10;
  1079.     buf[2] = ':';
  1080.     tmp = current_pos;
  1081.     buf[3] = '0'+ tmp / 1000; tmp = tmp % 1000;
  1082.     buf[4] = '0'+ tmp / 100; tmp = tmp % 100;
  1083.     buf[5] = '0'+ tmp / 10; tmp = tmp % 10;
  1084.     buf[6] = '0'+ tmp ;
  1085.     WinDrawChars( buf, 7, 100,124);
  1086.     */
  1087.         
  1088.     while (len){
  1089.         if ( current_pos + len <= 0x1000){
  1090.             temp_len = len;
  1091.         } else {
  1092.             temp_len = 0x1000-current_pos;
  1093.         }
  1094.  
  1095.         DmWrite( current_record_ptr , current_pos, c , temp_len);
  1096.         current_pos += temp_len;
  1097.         
  1098.         if ( current_pos >= 0x1000){
  1099.     // release current record;
  1100.             MemHandleUnlock( current_record_handle);
  1101.             DmReleaseRecord( CurrentDB, current_record, true);
  1102.         
  1103.         // make new record
  1104.  
  1105.             current_record++;
  1106.  
  1107.             current_record_handle = DmNewRecord( CurrentDB, ¤t_record, 0x1000);
  1108.             current_record_ptr = (CharPtr)MemHandleLock(current_record_handle);
  1109.             current_pos=0;    
  1110.     
  1111.             rec0.compression_type = 1; // no compression
  1112.             rec0.spare = 0x5555;
  1113.             rec0.num_records = current_record;
  1114.             rec0.story_length = total_length;
  1115.             rec0.reclen = 0x1000;
  1116.  
  1117.             recnum = 0;
  1118.             h = DmGetRecord( CurrentDB, recnum);
  1119.             p = (Record0Type *)MemHandleLock(h);
  1120.              DmWrite( p, 0L, &rec0, sizeof( rec0));    
  1121.             MemHandleUnlock( h);
  1122.             DmReleaseRecord( CurrentDB, recnum, true);
  1123.     
  1124.         }
  1125.         total_length += temp_len;
  1126.         
  1127.         len -= temp_len;
  1128.         c += temp_len;
  1129. /*
  1130.         buf[0] = '0'+ current_record / 10;
  1131.         buf[1] = '0'+ current_record % 10;
  1132.         buf[2] = ':';
  1133.         tmp = current_pos;
  1134.         buf[3] = '0'+ tmp / 1000; tmp = tmp % 1000;
  1135.         buf[4] = '0'+ tmp / 100; tmp = tmp % 100;    
  1136.         buf[5] = '0'+ tmp / 10; tmp = tmp % 10;
  1137.         buf[6] = '0'+ tmp ;
  1138.         //WinDrawChars( buf, 7, 100,136);
  1139. */
  1140.  
  1141.     }
  1142.     
  1143. }
  1144.  
  1145.  
  1146. /***********************************************************************
  1147.  *
  1148.  * FUNCTION:        PilotMain
  1149.  *
  1150.  * DESCRIPTION:    This function is the equivalent of a main() function
  1151.  *                        in standard ╥C╙.  It is called by the Emulator to begin
  1152.  *                        execution of this application.
  1153.  *
  1154.  * PARAMETERS:        cmd - command specifying how to launch the application.
  1155.  *                        cmdPBP - parameter block for the command.
  1156.  *                        launchFlags - flags used to configure the launch.            
  1157.  *
  1158.  * RETURNED:        Any applicable error code.
  1159.  *
  1160.  ***********************************************************************/
  1161. DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
  1162. {
  1163.     Err error;
  1164.  
  1165.     if (cmd == sysAppLaunchCmdNormalLaunch)
  1166.     {
  1167.         // Set up initial form.
  1168.         error = StartApplication();
  1169.         if (error) return error;
  1170.  
  1171.         // Start up the event loop.
  1172.         EventLoop();
  1173.         StopApplication ();
  1174.     }
  1175.     return(0);
  1176. }
  1177.