home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1990
/
12
/
gaspar.asc
< prev
next >
Wrap
Text File
|
1990-11-15
|
17KB
|
570 lines
_THE MACINTOSH COMMUNICATIONS TOOLBOX_
by Don Gaspar
[LISTING ONE]
/* Cheap Com by Don Gaspar */
/* Requires MPW C and the Comm Toolbox. The complete program, including */
/* the resource file, header file, and make, are available electronically. */
/* These are the standard Mac includes for all managers */
#include <values.h>
#include <types.h>
#include <Resources.h>
#include <QuickDraw.h>
#include <fonts.h>
#include <events.h>
#include <windows.h>
#include <menus.h>
#include <textedit.h>
#include <dialogs.h>
#include <Controls.h>
#include <desk.h>
#include <toolutils.h>
#include <memory.h>
#include <Lists.h>
#include <SegLoad.h>
#include <Files.h>
#include <Packages.h>
#include <OSEvents.h>
#include <OSUtils.h>
#include <DiskInit.h>
#include <Traps.h>
#include <String.h>
#include <Strings.h>
#include <CRMIntf.h> // Communications Resource Manager stuff
#include <CMIntf.h> // Connection Manager stuff
#include <FTIntf.h> // File Transfer Manager stuff
#include <TMIntf.h> // Terminal Manager stuff
#include <CTBUtils.h> // Communications Toolbox Utility stuff
#include "CommTypes.h" // communications types, etc.
#include "CheapComm.h" // constants, forward declarations, etc.
/* global variables */
Boolean gHasWaitNextEvent; // does user's machine have WaitNextEvent?
Boolean gInBackground; // are we in the background?
Boolean gStopped; // are we stopped?
TermHandle gTerm; // handle to terminal record
ConnHandle gConn; // handle to connection record
FTHandle gFT; // handle to file transfer record
Ptr gBuffer; // global connection buffer
long gFTSearchRefNum;
Boolean gStartFT; // are we doing a file transfer?
Boolean gWasFT; // was a file transfer in progress?
short gDummy;
Handle gCache; // buffer for last terminal line received/sent
TEHandle gTE; // buffer for terminal emulator
ControlHandle gScrollHHandle, gScrollVHandle;
#pragma segment Main
/* Sends data out via choosen connection */
pascal long TermSendProc(thePtr, theSize, refCon, flags)
Ptr thePtr;
long theSize;
long refCon;
short flags;
{
CMErr theErr;
long termSendProc = 0L;
if (gConn != nil) {
theErr = CMWrite(gConn,thePtr,&theSize,cmData,false,nil,0,flags);
if (theErr == noErr)
termSendProc = theSize;
}
return(termSendProc);
}
#pragma segment Main
/* Gets the data from the connection tool and sends it to the terminal tool */
pascal void TermRecvProc()
{
CMErr theErr;
CMStatFlags status;
CMBufferSizes sizes;
short flags;
if (gConn != nil && gTerm != nil) {
theErr = CMStatus(gConn, sizes, &status);
if (theErr == noErr) {
if ((status & (cmStatusOpen+cmStatusDataAvail)) != 0 && sizes[cmDataIn] != 0) {
if (sizes[cmDataIn] > kBufferSize)
sizes[cmDataIn] = kBufferSize;
theErr=CMRead(gConn, gBuffer, &sizes[cmDataIn], cmData, false, nil, 0, &flags);
if (theErr == noErr) // give it to terminal emulation buffer
sizes[cmDataIn] = TMStream(gTerm, gBuffer, sizes[cmDataIn], flags);
}
}
else
; // Connection Manager will handle this
}
}
#pragma segment Main
/* Gets the connection environments for FT or Term tool */
pascal OSErr ToolGetConnEnvirons(refCon, theEnvirons)
long refCon;
ConnEnvironRec *theEnvirons;
{
OSErr toolGetConnEnvirons = envNotPresent;
if(gConn != nil)
toolGetConnEnvirons = CMGetConnEnvirons(gConn,theEnvirons);
return(toolGetConnEnvirons);
}
#pragma segment Main
/* Sends data during a file transfer */
pascal long FTSendProc(thePtr, theSize, refCon, channel, flags)
Ptr thePtr;
long theSize;
long refCon;
CMChannel channel;
short flags;
{
CMErr theErr;
long ftSendProc = 0L;
if (gConn != nil) {
theErr = CMWrite(gConn, thePtr,& theSize, channel, false, nil, 0, flags);
if(theErr == noErr)
ftSendProc = theSize;
}
return(ftSendProc);
}
#pragma segment Main
/* Gets the data during a data transfer */
pascal long FTReceiveProc(thePtr, theSize, refCon, channel, flags)
Ptr thePtr;
long theSize;
long refCon;
CMChannel channel;
short *flags;
{
CMErr theErr;
long ftReceiveProc = 0L;
if (gConn != nil) {
theErr = CMRead(gConn, thePtr, &theSize, channel, false, nil, 0, flags);
if (theErr == noErr)
ftReceiveProc = theSize;
}
return(ftReceiveProc);
}
#pragma segment Main
/* Sets file transfer flag if an autoreceive string was found */
pascal void AutoRecCallBack(theConn, data, refNum)
ConnHandle theConn;
Ptr data;
long refNum;
{
if (gFTSearchRefNum == refNum)
gStartFT = true;
}
#pragma segment Main
/* Checks if file transfer has autoreceive string; adds a search to find it */
void AddFTSearch()
{
Str255 tempStr;
if (gFT != nil && gConn != nil) {
//tempStr = (*gFT)->autoRec;
if ((*gFT)->autoRec[0] != 0) {
gFTSearchRefNum = CMAddSearch(gConn,(*gFT)->autoRec, cmSearchSevenBit,
(ProcPtr)AutoRecCallBack);
if (gFTSearchRefNum == -1) {
AlertUser("Couldn't add stream search\0", false);
gFTSearchRefNum = 0;
}
}
}
}
#pragma segment Main
/* Initiates a file transfer send from menu command */
void DoSend()
{
SFReply theReply;
Point where;
short numTypes;
SFTypeList typeList;
FTErr anyErr;
if(gFT != nil) {
SetPt(&where,100,100);
if(((**gFT).attributes & ftTextOnly) != 0) {
typeList[0] = 'TEXT';
numTypes = 1;
}
else
numTypes = -1;
sfgetfile(&where, "File to send", nil, numTypes, typeList, nil, &theReply);
if(theReply.good) {
anyErr = FTStart(gFT, ftTransmitting, &theReply);
if(anyErr != noErr)
; // file transfer tool will alert user
}
}
}
#pragma segment Main
/* Initiates a file transfer receive from menu */
void DoReceive()
{
SFReply theReply;
OSErr anyErr;
if (gFT != nil) {
theReply.vRefNum = 0;
//theReply.fName = '';
gStartFT = false;
if (gConn != nil ) {
if ((**gFT).autoRec != "\0" && gFTSearchRefNum != 0) {
CMRemoveSearch(gConn, gFTSearchRefNum);
gFTSearchRefNum = 0;
}
}
anyErr = FTStart(gFT, ftReceiving, &theReply);
if(anyErr != noErr)
; // file transfer tool will alert user
}
}
#pragma segment Main
/* Initiates a connection */
void OpenConnection()
{
CMErr theErr;
CMBufferSizes sizes;
CMStatFlags status;
if(gConn != nil) {
theErr = CMStatus(gConn, sizes, &status);
if(theErr == noErr)
if((status & (cmStatusOpen + cmStatusOpening)) == 0)
theErr =CMOpen(gConn, false, nil, -1);
if (theErr != noErr)
; // connection tool will tell user if there's an errror
}
}
#pragma segment Main
/* Cancels connection */
void CloseConnection()
{
CMErr theErr;
CMBufferSizes sizes;
CMStatFlags status;
if (gConn != nil) {
theErr = CMStatus(gConn, sizes, &status);
if(theErr == noErr)
if ((status & (cmStatusOpen+cmStatusOpening)) != 0)
theErr = CMClose(gConn, false, nil ,0, true);
if (theErr != noErr)
; // connection tool will handle error
}
}
#pragma segment Main
/* tries to get default tool proc ID, otherwise gets first one it can find */
short FindToolID(toolClass)
OSType toolClass;
{
Str255 toolName;
OSErr anyErr;
short procID = -1;
if (toolClass == classTM) {
StuffHex(&toolName,kDefaultTermTool);
procID = TMGetProcID(toolName);
if(procID == -1) {
anyErr = CRMGetIndToolName(toolClass,1, toolName);
if (anyErr == noErr)
procID = TMGetProcID(toolName);
}
}
else if (toolClass == classCM) {
StuffHex(&toolName,kDefaultConnTool);
procID = CMGetProcID(toolName);
if(procID == -1) {
anyErr = CRMGetIndToolName(toolClass,1, toolName);
if (anyErr == noErr)
procID = CMGetProcID(toolName);
}
}
else if (toolClass == classFT) {
StuffHex(&toolName,kDefaultFTTool);
procID = FTGetProcID(toolName);
if(procID == -1) {
anyErr = CRMGetIndToolName(toolClass,1, toolName);
if (anyErr == noErr)
procID = FTGetProcID(toolName);
}
}
return(procID);
}
#pragma segment Main
/* this is click loop for terminal emulation to track */
pascal Boolean clikLoop(refcon)
long refcon;
{
return(true);
}
#pragma segment Initialize
/* this function sets up CommToolbox for what we need;
it should resemble most other Macinotosh toolbox calls */
void InitCommTB()
{
(void)InitCTBUtilities(); // Comm Toolbox Utilities
(void)InitCRM(); // Communications Resource Manager
// initialize the Terminal Manager
if (InitTM() == tmNoTools) // Did we fail?
AlertUser("No terminal tools found\0", true);
// Initialize the Connection Manager
if(InitCM()== cmNoTools) // failure?
AlertUser("No connection tools found\0", true);
// Initialize the File Transfer Manager
if(InitFT() == ftNoTools) // failure?
AlertUser("No file transfer tools found\0",false);
gTerm = nil; // initialize our globals
gConn = nil;
gFT = nil;
gCache = nil;
gFTSearchRefNum = 0;
}
#pragma segment Main
/* this will cache all data coming in through serial port */
pascal long cacheProc(refCon, theTermData)
long refCon;
TermDataBlock *theTermData;
{
long sizeCached;
TermEnvironRec theEnvirons;
theEnvirons.version = curTermEnvRecVers;
theEnvirons.termType = tmTextTerminal;
(void)TMGetTermEnvirons(gTerm, &theEnvirons);
if (theTermData->theData == nil)
return(-1);
if(gCache != nil) // is it valid?
DisposHandle(gCache);
HLock((Handle)theTermData->theData);
gCache = theTermData->theData;
if(HandToHand(&gCache)) {
DisposHandle(gCache);
sizeCached = -1;
}
else {
sizeCached = GetHandleSize(gCache);
}
HUnlock((Handle)theTermData->theData);
if(theTermData->flags == tmTextTerminal && sizeCached >0L) {
/*HandAndHand(gCache, (**gTE).hText);
(**gTE).teLength += 80;
(**gTE).nLines += 1;*/
((Ptr)*gCache,80L,gTE);
//(**gTE).viewRect.top -= (**gTE).lineHeight;
//(**gTE).destRect.top -= (**gTE).lineHeight;
//TECalText(gTE);
//TEScroll(0,-(**gTE).lineHeight,gTE);
}
return(tmNoErr);
}
#pragma segment Main
/* gets window and create session */
Boolean DoNewWindow()
{
WindowPtr window;
Rect theRect;
short procID;
CMBufferSizes sizes;
Rect tempRect;
short index;
Rect r;
window = GetNewWindow(rWindow, nil, (WindowPtr)-1);
SetPort(window);
/* no cache, breakproc, or clikloop */
gTerm = TMNew(&theRect,&theRect, tmSaveBeforeClear + tmAutoScroll,
procID, window, (ProcPtr)TermSendProc,(ProcPtr)cacheProc,nil,
/*(ProcPtr)clikLoop*/nil, (ProcPtr)ToolGetConnEnvirons,0,0);
SetRect(&r,theRect.left,-theRect.bottom,theRect.right,theRect.top);
gTE = TENew(&r,&r);
(**gTE).txSize = 9;
(**gTE).txFont = monaco;
(**gTE).viewRect.bottom = (((**gTE).viewRect.bottom - (**gTE).viewRect.top)/
(**gTE).lineHeight)*(**gTE).lineHeight + (**gTE).viewRect.top;
TEAutoView(true,gTE);
/* custom configure with personal settings -- store as a file later */
(void)TMSetConfig(gTerm, "Scroll Smooth\0");
if(gTerm == nil)
AlertUser("Can't create a terminal tool\0", true);
HLock((Handle)gTerm);
/* connection tool */
procID = FindToolID(classCM);
if(procID == -1)
AlertUser("No connection tools found/0", true);
sizes[cmDataIn] = kBufferSize*10; // data channel; large incoming buffer
sizes[cmDataOut] = kBufferSize;
sizes[cmCntlIn] = 0;
sizes[cmCntlOut] = 0;
sizes[cmAttnIn] = 0;
sizes[cmAttnOut] = 0;
gConn = CMNew(procID, cmData, sizes, 0,0);
(void)CMSetConfig(gConn,"Baud 9600, Bits 7, StopBits 1, Parity Even,
ModemType Other, PhoneNumber \0429,1800-346-0145\042\0");
if(gConn == nil)
AlertUser("Can't create a connection tool/0", true);
HLock((Handle)gConn);
/* allocate space for reads/writes using number returned by connection tool */
gBuffer = NewPtrClear(sizes[cmDataIn]);
if(MemError() != noErr)
AlertUser("Out of memory\0", true);
/* file transfer tool */
procID = FindToolID(classFT);
if(procID == -1)
AlertUser("No file transfer tools found\0", false);
/* no read/write proc -- tool has its own */
gFT = FTNew(procID, 0 ,(ProcPtr)FTSendProc, (ProcPtr)FTReceiveProc,
nil, nil, (ProcPtr)ToolGetConnEnvirons, window, 0L,0L);
if(gFT == nil)
AlertUser("Can't create a file transfer tool\0", true);
HLock((Handle)gFT);
gWasFT = false;
gStartFT = false;
gFTSearchRefNum = 0;
AddFTSearch();
return(true);
}
#pragma segment Main
/* Updates the window */
void DoUpdate(window)
WindowPtr window;
{
RgnHandle savedClip;
GrafPtr savedPort;
if (IsAppWindow(window)) {
GetPort(&savedPort);
SetPort(window);
/* clip to the window content */
savedClip = NewRgn();
GetClip(savedClip);
ClipRect(&window->portRect);
DrawControls(window);
DrawGrowIcon(window);
BeginUpdate(window);
if(gTerm != nil )
TMUpdate(gTerm, window->visRgn);
if(gTE != nil)
TEUpdate(&window->portRect,gTE);
EndUpdate(window);
SetClip(savedClip);
DisposeRgn(savedClip);
SetPort(savedPort);
}
}
#pragma segment Main
/* suspends/resumes terminal window */
void DoResume(becomingActive)
Boolean becomingActive;
{
WindowPtr theWindow;
GrafPtr savedPort;
GetPort(&savedPort);
theWindow = FrontWindow();
while (theWindow!= nil) {
if (IsAppWindow(theWindow)) {
SetPort(theWindow);
if(gTerm != nil)
TMResume(gTerm, becomingActive);
if(gConn != nil)
CMResume(gConn, becomingActive);
if(gFT != nil)
FTResume(gFT, becomingActive);
}
theWindow = (WindowPtr)(((WindowPeek) theWindow)->nextWindow);
}
SetPort(savedPort);
}
#pragma segment Main
/* (de)activates window */
void DoActivate(window, becomingActive)
WindowPtr window;
Boolean becomingActive;
{
if (IsAppWindow(window)) { // does window belong to us?
SetPort(window); // set current port
if(gConn != nil) // do we have a valid connection?
CMActivate(gConn, becomingActive);// activate it
if(gTerm != nil) // do we have a terminal?
TMActivate(gTerm, becomingActive); // activate it
if(gFT != nil) // do we have a valid file transfer?
FTActivate(gFT, becomingActive);// activate it
}
}
#pragma segment Main
/* tries to pass event to a tool if window is a tool window;
handles event if appropriate */
Boolean DoToolEvent(event, window)
EventRecord *event;
WindowPtr window;
{
Boolean doToolEvent;
if (window != nil && !IsAppWindow(window)) { // is window valid?
doToolEvent = true;
/* copies of commtb record must be in refCon field of
window for changing the settings */
if(gFT != nil && gFT == (FTHandle)GetWRefCon(window))
FTEvent(gFT,event); // handle file transfer manager event
else if(gConn != nil && gConn == (ConnHandle)GetWRefCon(window))
CMEvent(gConn,event); // handle connection manager event
else if(gTerm != nil && gTerm == (TermHandle)GetWRefCon(window))
TMEvent(gTerm,event); // handle terminal manager event
else
doToolEvent = false;
}
else
doToolEvent = false;
return(doToolEvent);
}
#pragma segment Main
/* idles all communications tools; this was taken from the Surfer pascal
example provided from Apple -- you can get it from APDA.*/
void DoIdle()
{
WindowPtr theWindow;
Boolean doFT, doTM;
GrafPtr savedPort;
GetPort(&savedPort);
theWindow = FrontWindow();
while (theWindow != nil) {
if (IsAppWindow(theWindow)) {
SetPort(theWindow);
//TEIdle(gTE);
if(gConn != nil)
CMIdle(gConn);
doFT = false;
doTM = true;
if (gFT != nil ) {
if (((**gFT).flags & ftIsFTMode) != 0) {
doFT = true;
gWasFT = true;
if(((**gFT).attributes & ftSameCircuit) != 0)
doTM = false;
}
else {
if (gWasFT) {
gWasFT = false;
if(((**gFT).flags & ftSucc) == 0)
;
AddFTSearch();
}
if(gStartFT)
DoReceive();
}
if (doFT)
FTExec(gFT);
} /* if gFT != nil */
if(gTerm != nil) {
if (doTM) {
TMIdle(gTerm);
TermRecvProc();
}
}/* gTerm != nil */
}
theWindow = (WindowPtr)(((WindowPeek)theWindow)->nextWindow);
}
SetPort(savedPort);
}