home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1990 / 12 / gaspar.asc < prev    next >
Text File  |  1990-11-15  |  17KB  |  570 lines

  1. _THE MACINTOSH COMMUNICATIONS TOOLBOX_
  2. by Don Gaspar
  3.  
  4. [LISTING ONE]
  5.  
  6. /* Cheap Com  by Don Gaspar */
  7. /* Requires MPW C and the Comm Toolbox. The complete program, including */
  8. /* the resource file, header file, and make, are available electronically. */
  9. /* These are the standard Mac includes for all managers */
  10.  
  11. #include <values.h>
  12. #include <types.h>
  13. #include <Resources.h>
  14. #include <QuickDraw.h>
  15. #include <fonts.h>
  16. #include <events.h>
  17. #include <windows.h>
  18. #include <menus.h>
  19. #include <textedit.h>
  20. #include <dialogs.h>
  21. #include <Controls.h>
  22. #include <desk.h>
  23. #include <toolutils.h>
  24. #include <memory.h>
  25. #include <Lists.h>
  26. #include <SegLoad.h>
  27. #include <Files.h>
  28. #include <Packages.h>
  29. #include <OSEvents.h>
  30. #include <OSUtils.h>
  31. #include <DiskInit.h>
  32. #include <Traps.h>
  33. #include <String.h>
  34. #include <Strings.h>
  35.  
  36. #include <CRMIntf.h>  // Communications Resource Manager stuff
  37. #include <CMIntf.h>   // Connection Manager stuff
  38. #include <FTIntf.h>   // File Transfer Manager stuff
  39. #include <TMIntf.h>   // Terminal Manager stuff
  40. #include <CTBUtils.h> // Communications Toolbox Utility stuff
  41.  
  42. #include "CommTypes.h"     // communications types, etc.
  43. #include "CheapComm.h"     // constants, forward declarations, etc.
  44.  
  45. /*  global variables */
  46. Boolean      gHasWaitNextEvent;    // does user's machine have WaitNextEvent?
  47. Boolean      gInBackground;    // are we in the background?
  48. Boolean      gStopped;        // are we stopped?
  49.     
  50. TermHandle   gTerm;           // handle to terminal record
  51. ConnHandle   gConn;          // handle to connection record
  52. FTHandle     gFT;          // handle to file transfer record
  53.  
  54. Ptr         gBuffer;        // global connection buffer
  55. long        gFTSearchRefNum;
  56. Boolean     gStartFT;        // are we doing a file transfer?
  57. Boolean     gWasFT;          // was a file transfer in progress?
  58.  
  59. short        gDummy;
  60. Handle        gCache;         // buffer for last terminal line received/sent
  61. TEHandle    gTE;        // buffer for terminal emulator
  62. ControlHandle gScrollHHandle, gScrollVHandle; 
  63.  
  64. #pragma segment Main
  65. /*    Sends data out via choosen connection */
  66. pascal long    TermSendProc(thePtr, theSize, refCon, flags)
  67.     Ptr    thePtr;
  68.     long    theSize;
  69.     long    refCon;
  70.     short    flags;
  71. {
  72.     CMErr    theErr;
  73.     long    termSendProc = 0L;
  74.     if (gConn != nil) {
  75.              theErr = CMWrite(gConn,thePtr,&theSize,cmData,false,nil,0,flags);
  76.         if (theErr == noErr)
  77.             termSendProc = theSize;
  78.     }
  79.     return(termSendProc);
  80. }
  81. #pragma segment Main
  82. /*  Gets the data from the connection tool and sends it to the terminal tool */
  83. pascal void TermRecvProc()
  84. {
  85.     CMErr        theErr;
  86.     CMStatFlags    status;
  87.     CMBufferSizes    sizes;
  88.     short        flags;
  89.     if (gConn != nil && gTerm != nil) {
  90.         theErr = CMStatus(gConn, sizes, &status);
  91.         if (theErr == noErr) {
  92. if ((status & (cmStatusOpen+cmStatusDataAvail)) != 0 && sizes[cmDataIn] != 0) {
  93.                 if (sizes[cmDataIn] > kBufferSize)
  94.                     sizes[cmDataIn] = kBufferSize;
  95. theErr=CMRead(gConn, gBuffer, &sizes[cmDataIn], cmData, false, nil, 0, &flags);
  96.         if (theErr  == noErr)    // give it to terminal emulation buffer
  97.         sizes[cmDataIn] = TMStream(gTerm, gBuffer, sizes[cmDataIn], flags);
  98.        }
  99.     }
  100.     else
  101.     ;              // Connection Manager will handle this 
  102.     }
  103. }
  104. #pragma segment Main
  105. /* Gets the connection environments for FT or Term tool */
  106. pascal OSErr    ToolGetConnEnvirons(refCon, theEnvirons)
  107.     long    refCon;
  108.     ConnEnvironRec    *theEnvirons;
  109. {
  110.     OSErr    toolGetConnEnvirons = envNotPresent;
  111.     if(gConn != nil)
  112.         toolGetConnEnvirons = CMGetConnEnvirons(gConn,theEnvirons);
  113.     return(toolGetConnEnvirons);
  114. }
  115. #pragma segment Main
  116. /* Sends data during a file transfer */
  117. pascal long    FTSendProc(thePtr, theSize, refCon, channel, flags)
  118.     Ptr       thePtr;
  119.     long       theSize;
  120.     long       refCon;
  121.     CMChannel  channel;
  122.     short       flags;
  123. {
  124.     CMErr    theErr;
  125.     long    ftSendProc = 0L;
  126.     if (gConn != nil) {
  127.       theErr = CMWrite(gConn, thePtr,& theSize, channel, false, nil, 0, flags);
  128.         if(theErr == noErr)
  129.             ftSendProc = theSize;
  130.     }
  131.     return(ftSendProc);
  132. }
  133. #pragma segment Main
  134. /* Gets the data during a data transfer */
  135. pascal long    FTReceiveProc(thePtr, theSize, refCon, channel, flags)
  136.     Ptr       thePtr;
  137.     long       theSize;
  138.     long       refCon;
  139.     CMChannel  channel;
  140.     short       *flags;
  141. {
  142.     CMErr       theErr;
  143.     long       ftReceiveProc = 0L;
  144.      if (gConn != nil) {
  145.        theErr = CMRead(gConn, thePtr, &theSize, channel, false, nil, 0, flags);
  146.         if (theErr == noErr)
  147.             ftReceiveProc = theSize;
  148.     }
  149.     return(ftReceiveProc);
  150. }
  151. #pragma segment Main
  152. /* Sets file transfer flag if an autoreceive string was found */
  153. pascal void AutoRecCallBack(theConn, data, refNum)
  154.     ConnHandle     theConn;
  155.     Ptr           data;
  156.     long           refNum;
  157. {
  158.     if (gFTSearchRefNum == refNum)
  159.         gStartFT = true;
  160. }
  161. #pragma segment Main
  162. /* Checks if file transfer has autoreceive string; adds a search to find it */
  163. void AddFTSearch()
  164. {
  165.     Str255    tempStr;
  166.     if (gFT != nil && gConn != nil) {
  167.         //tempStr = (*gFT)->autoRec;
  168.     if ((*gFT)->autoRec[0] != 0) {
  169.      gFTSearchRefNum = CMAddSearch(gConn,(*gFT)->autoRec, cmSearchSevenBit,
  170.                 (ProcPtr)AutoRecCallBack);
  171.             if (gFTSearchRefNum == -1) {
  172.                      AlertUser("Couldn't add stream search\0", false);
  173.                 gFTSearchRefNum = 0;
  174.             }
  175.         }
  176.     }
  177. }
  178. #pragma segment Main
  179. /* Initiates a file transfer send from menu command */
  180. void DoSend()
  181. {
  182.     SFReply     theReply;
  183.     Point        where;
  184.     short        numTypes;
  185.     SFTypeList    typeList;
  186.     FTErr        anyErr;
  187.     if(gFT != nil) {
  188.         SetPt(&where,100,100);
  189.         
  190.         if(((**gFT).attributes & ftTextOnly) != 0) {
  191.             typeList[0] = 'TEXT';
  192.             numTypes = 1;
  193.         }
  194.         else
  195.             numTypes = -1;
  196.     sfgetfile(&where, "File to send", nil, numTypes, typeList, nil, &theReply);
  197.         if(theReply.good) {
  198.             anyErr = FTStart(gFT, ftTransmitting, &theReply);
  199.             if(anyErr != noErr)  
  200.                 ;  // file transfer tool will alert user
  201.         }
  202.     }
  203. }
  204. #pragma segment Main
  205. /* Initiates a file transfer receive from menu */
  206. void DoReceive()
  207. {
  208.     SFReply   theReply;
  209.     OSErr       anyErr;
  210.     
  211.     if (gFT != nil) {
  212.         theReply.vRefNum = 0;
  213.         //theReply.fName = '';
  214.         gStartFT = false;
  215.         if (gConn != nil ) {
  216.             if ((**gFT).autoRec != "\0" && gFTSearchRefNum != 0) {
  217.                 CMRemoveSearch(gConn, gFTSearchRefNum);
  218.                 gFTSearchRefNum = 0;
  219.             }
  220.         }
  221.         anyErr = FTStart(gFT, ftReceiving, &theReply);
  222.         if(anyErr != noErr)
  223.             ;  // file transfer tool will alert user
  224.     }
  225. }
  226. #pragma segment Main
  227. /* Initiates a connection */
  228. void OpenConnection()
  229. {
  230.     CMErr        theErr;
  231.     CMBufferSizes    sizes;
  232.     CMStatFlags    status;
  233.     if(gConn != nil) {
  234.         theErr = CMStatus(gConn, sizes, &status);
  235.         if(theErr == noErr) 
  236.             if((status & (cmStatusOpen + cmStatusOpening)) == 0)
  237.                 theErr =CMOpen(gConn, false, nil, -1);
  238.             if (theErr != noErr)
  239.              ;  // connection tool will tell user if there's an errror
  240.     }
  241. }
  242. #pragma segment Main
  243. /* Cancels connection */
  244. void CloseConnection()
  245. {
  246.     CMErr        theErr;
  247.     CMBufferSizes    sizes;
  248.     CMStatFlags    status;
  249.     if (gConn != nil) {
  250.         theErr = CMStatus(gConn, sizes, &status);
  251.         if(theErr == noErr)
  252.             if ((status & (cmStatusOpen+cmStatusOpening)) != 0)
  253.                 theErr = CMClose(gConn, false, nil ,0, true);
  254.         if (theErr != noErr)
  255.             ; // connection tool will handle error
  256.     }
  257. }
  258. #pragma segment Main
  259. /* tries to get default tool proc ID, otherwise gets first one it can find */
  260. short    FindToolID(toolClass)
  261.     OSType    toolClass;
  262. {
  263.     Str255    toolName;
  264.     OSErr    anyErr;
  265.     short    procID = -1;
  266.     if (toolClass == classTM) {
  267.         StuffHex(&toolName,kDefaultTermTool);
  268.         procID = TMGetProcID(toolName);
  269.         if(procID == -1) {
  270.             anyErr = CRMGetIndToolName(toolClass,1, toolName);
  271.             if (anyErr == noErr)
  272.                 procID = TMGetProcID(toolName);
  273.         }
  274.     }
  275.     else if (toolClass == classCM) {
  276.         StuffHex(&toolName,kDefaultConnTool);
  277.         procID = CMGetProcID(toolName);
  278.         if(procID == -1) {
  279.             anyErr = CRMGetIndToolName(toolClass,1, toolName);
  280.             if (anyErr == noErr)
  281.                 procID = CMGetProcID(toolName);
  282.         }
  283.     }
  284.     else if (toolClass == classFT) {
  285.         StuffHex(&toolName,kDefaultFTTool);
  286.         procID = FTGetProcID(toolName);
  287.         if(procID == -1) {
  288.             anyErr = CRMGetIndToolName(toolClass,1, toolName);
  289.             if (anyErr == noErr)
  290.                 procID = FTGetProcID(toolName);
  291.         }
  292.     }
  293.     return(procID);
  294. }
  295. #pragma segment Main
  296. /* this is click loop for terminal emulation to track */
  297. pascal Boolean clikLoop(refcon)
  298.     long    refcon;
  299. {
  300.     return(true);
  301. }
  302. #pragma segment Initialize
  303. /* this function sets up CommToolbox for what we need;
  304.     it should resemble most other Macinotosh toolbox calls    */
  305. void InitCommTB()
  306. {
  307.     (void)InitCTBUtilities();    //    Comm Toolbox Utilities
  308.     (void)InitCRM();        //    Communications Resource Manager
  309.     //    initialize the Terminal Manager
  310.     if (InitTM() == tmNoTools)            //    Did we fail?
  311.         AlertUser("No terminal tools found\0", true);
  312.     //    Initialize the Connection Manager
  313.     if(InitCM()== cmNoTools)            //    failure?
  314.         AlertUser("No connection tools found\0", true);
  315.     //    Initialize the File Transfer Manager
  316.     if(InitFT() == ftNoTools)                // failure?
  317.         AlertUser("No file transfer tools found\0",false);
  318.     gTerm = nil;                     // initialize our globals
  319.     gConn = nil;
  320.     gFT = nil;
  321.     gCache = nil;
  322.     gFTSearchRefNum = 0;
  323. }
  324. #pragma segment Main
  325. /*    this will cache all data coming in through serial port */
  326. pascal long cacheProc(refCon, theTermData)
  327.     long        refCon;
  328.     TermDataBlock    *theTermData;
  329. {
  330.     long        sizeCached;
  331.     TermEnvironRec    theEnvirons;
  332.     theEnvirons.version = curTermEnvRecVers;
  333.     theEnvirons.termType = tmTextTerminal;
  334.     (void)TMGetTermEnvirons(gTerm, &theEnvirons);
  335.     if (theTermData->theData == nil) 
  336.         return(-1);
  337.     if(gCache != nil)    //    is it valid?
  338.             DisposHandle(gCache);    
  339.     HLock((Handle)theTermData->theData);
  340.     gCache = theTermData->theData;
  341.     if(HandToHand(&gCache)) {
  342.             DisposHandle(gCache);
  343.             sizeCached = -1;
  344.         }
  345.         else {
  346.             sizeCached = GetHandleSize(gCache);
  347.         }
  348.     HUnlock((Handle)theTermData->theData);
  349.     if(theTermData->flags == tmTextTerminal && sizeCached >0L) {
  350.         /*HandAndHand(gCache, (**gTE).hText);
  351.         (**gTE).teLength += 80;
  352.         (**gTE).nLines += 1;*/
  353.         ((Ptr)*gCache,80L,gTE);
  354.         //(**gTE).viewRect.top -= (**gTE).lineHeight;
  355.         //(**gTE).destRect.top -= (**gTE).lineHeight;
  356.         //TECalText(gTE);
  357.         //TEScroll(0,-(**gTE).lineHeight,gTE);
  358.     }    
  359.     return(tmNoErr);
  360. }
  361. #pragma segment Main
  362. /* gets window and create session */
  363. Boolean DoNewWindow()
  364. {
  365.     WindowPtr    window;
  366.     Rect        theRect;
  367.     short        procID;
  368.     CMBufferSizes    sizes;
  369.     Rect        tempRect;
  370.     short        index;
  371.     Rect        r;
  372.     window = GetNewWindow(rWindow, nil, (WindowPtr)-1);
  373.     SetPort(window);
  374.     /* no cache, breakproc, or clikloop */
  375.     gTerm = TMNew(&theRect,&theRect, tmSaveBeforeClear + tmAutoScroll,
  376.          procID, window, (ProcPtr)TermSendProc,(ProcPtr)cacheProc,nil,
  377.         /*(ProcPtr)clikLoop*/nil, (ProcPtr)ToolGetConnEnvirons,0,0);
  378.     SetRect(&r,theRect.left,-theRect.bottom,theRect.right,theRect.top);
  379.     gTE = TENew(&r,&r);
  380.    (**gTE).txSize = 9;
  381.    (**gTE).txFont = monaco;
  382.    (**gTE).viewRect.bottom = (((**gTE).viewRect.bottom - (**gTE).viewRect.top)/
  383.    (**gTE).lineHeight)*(**gTE).lineHeight + (**gTE).viewRect.top;
  384.     TEAutoView(true,gTE);
  385.    /* custom configure with personal settings -- store as a file later */
  386.     (void)TMSetConfig(gTerm, "Scroll Smooth\0");
  387.     if(gTerm == nil)
  388.         AlertUser("Can't create a terminal tool\0", true);
  389.     HLock((Handle)gTerm);
  390.     /* connection tool */
  391.     procID = FindToolID(classCM);
  392.     if(procID == -1)
  393.         AlertUser("No connection tools found/0", true);
  394.       sizes[cmDataIn] = kBufferSize*10;  // data channel; large incoming buffer
  395.       sizes[cmDataOut] = kBufferSize;
  396.       sizes[cmCntlIn] = 0;
  397.       sizes[cmCntlOut] = 0;
  398.       sizes[cmAttnIn] = 0;
  399.       sizes[cmAttnOut] = 0;
  400.     gConn = CMNew(procID, cmData, sizes, 0,0);
  401.         (void)CMSetConfig(gConn,"Baud 9600, Bits 7, StopBits 1, Parity Even, 
  402.                       ModemType Other, PhoneNumber \0429,1800-346-0145\042\0");
  403.     if(gConn == nil)
  404.         AlertUser("Can't create a connection tool/0", true);
  405.     HLock((Handle)gConn);
  406. /* allocate space for reads/writes using number returned by connection tool */
  407.     gBuffer = NewPtrClear(sizes[cmDataIn]);
  408.     if(MemError() != noErr)
  409.         AlertUser("Out of memory\0", true);
  410.     /* file transfer tool */
  411.     procID = FindToolID(classFT);
  412.     if(procID == -1)
  413.         AlertUser("No file transfer tools found\0", false);
  414.     /* no read/write proc -- tool has its own */
  415.     gFT = FTNew(procID, 0 ,(ProcPtr)FTSendProc, (ProcPtr)FTReceiveProc, 
  416.         nil, nil, (ProcPtr)ToolGetConnEnvirons, window, 0L,0L);
  417.     if(gFT == nil)
  418.         AlertUser("Can't create a file transfer tool\0", true);
  419.     HLock((Handle)gFT);
  420.     gWasFT = false;
  421.     gStartFT = false;
  422.     gFTSearchRefNum = 0;
  423.     AddFTSearch();
  424.     return(true);
  425. }
  426. #pragma segment Main
  427. /* Updates the window */
  428. void DoUpdate(window)
  429.     WindowPtr    window;
  430. {
  431.     RgnHandle    savedClip;
  432.     GrafPtr     savedPort;
  433.     
  434.     if (IsAppWindow(window)) {
  435.         GetPort(&savedPort);
  436.         SetPort(window);
  437.         /* clip to the window content */
  438.         savedClip = NewRgn();
  439.         GetClip(savedClip);
  440.         ClipRect(&window->portRect);
  441.         DrawControls(window);
  442.         DrawGrowIcon(window);
  443.         BeginUpdate(window);
  444.             if(gTerm != nil )
  445.                  TMUpdate(gTerm, window->visRgn);
  446.             if(gTE != nil)
  447.                 TEUpdate(&window->portRect,gTE);
  448.         EndUpdate(window);
  449.         SetClip(savedClip);
  450.         DisposeRgn(savedClip);
  451.         SetPort(savedPort);
  452.     }
  453. }
  454. #pragma segment Main
  455. /* suspends/resumes terminal window */
  456. void DoResume(becomingActive)
  457.     Boolean becomingActive;
  458. {
  459.     WindowPtr    theWindow;
  460.     GrafPtr     savedPort;
  461.     GetPort(&savedPort);
  462.     theWindow = FrontWindow();
  463.     while (theWindow!= nil) {
  464.         if (IsAppWindow(theWindow)) {
  465.             SetPort(theWindow);
  466.             if(gTerm != nil)
  467.                 TMResume(gTerm, becomingActive);
  468.             if(gConn != nil)
  469.                 CMResume(gConn, becomingActive);
  470.             if(gFT != nil)
  471.                 FTResume(gFT, becomingActive);
  472.         }
  473.         theWindow = (WindowPtr)(((WindowPeek) theWindow)->nextWindow);
  474.     }
  475.     SetPort(savedPort);
  476. }
  477. #pragma segment Main
  478. /* (de)activates window */
  479. void DoActivate(window, becomingActive)
  480.     WindowPtr    window;
  481.     Boolean         becomingActive;
  482. {    
  483.     if (IsAppWindow(window)) {    // does window belong to us?
  484.         SetPort(window);    // set current port
  485.         if(gConn != nil)    // do we have a valid connection?
  486.             CMActivate(gConn, becomingActive);// activate it
  487.         if(gTerm != nil)    // do we have a terminal?
  488.             TMActivate(gTerm, becomingActive); // activate it
  489.         if(gFT != nil)        // do we have a valid file transfer?
  490.             FTActivate(gFT, becomingActive);// activate it
  491.     }
  492. }
  493. #pragma segment Main
  494. /* tries to pass event to a tool if window is a tool window; 
  495.                                            handles event if appropriate */
  496. Boolean DoToolEvent(event, window)
  497.     EventRecord    *event;
  498.     WindowPtr    window;
  499. {
  500.     Boolean     doToolEvent;
  501.     if (window != nil && !IsAppWindow(window)) { //    is window valid?
  502.         doToolEvent = true;
  503.         /* copies of commtb record must be in refCon field of
  504.             window for changing the settings    */
  505.            if(gFT != nil && gFT == (FTHandle)GetWRefCon(window))
  506.              FTEvent(gFT,event); // handle file transfer manager event 
  507.            else if(gConn != nil && gConn == (ConnHandle)GetWRefCon(window))
  508.              CMEvent(gConn,event); // handle connection manager event
  509.            else if(gTerm != nil && gTerm == (TermHandle)GetWRefCon(window))
  510.              TMEvent(gTerm,event); // handle terminal manager event
  511.            else
  512.             doToolEvent = false;
  513.     }
  514.     else
  515.         doToolEvent = false;
  516.     return(doToolEvent);
  517. }
  518. #pragma segment Main
  519. /* idles all communications tools; this was taken from the Surfer pascal
  520.     example provided from Apple -- you can get it from APDA.*/
  521. void DoIdle()
  522. {
  523.     WindowPtr   theWindow;
  524.     Boolean     doFT, doTM;
  525.     GrafPtr     savedPort;
  526.     GetPort(&savedPort);
  527.     theWindow = FrontWindow();
  528.     while (theWindow != nil) {
  529.         if (IsAppWindow(theWindow)) {
  530.             SetPort(theWindow);
  531.             //TEIdle(gTE);
  532.             if(gConn != nil)
  533.                 CMIdle(gConn);
  534.             doFT = false;
  535.             doTM = true;
  536.             if (gFT != nil ) {
  537.                 if (((**gFT).flags  & ftIsFTMode) != 0) {
  538.                     doFT = true;
  539.                     gWasFT = true;
  540.                               if(((**gFT).attributes & ftSameCircuit) != 0)
  541.                         doTM = false;
  542.                 }
  543.                 else {
  544.                     if (gWasFT) {
  545.                         gWasFT = false;
  546.                           if(((**gFT).flags & ftSucc) == 0)
  547.                             ;
  548.                         AddFTSearch();
  549.                     }
  550.                     if(gStartFT)
  551.                         DoReceive();
  552.                 }
  553.                 if (doFT)
  554.                     FTExec(gFT);
  555.             } /* if gFT != nil  */
  556.             if(gTerm != nil) {
  557.                 if (doTM) {
  558.                     TMIdle(gTerm);
  559.                     TermRecvProc();
  560.                 }    
  561.             }/* gTerm != nil */
  562.         }
  563.         theWindow = (WindowPtr)(((WindowPeek)theWindow)->nextWindow);
  564.     }
  565.     SetPort(savedPort);
  566. }
  567.  
  568.  
  569.  
  570.