This is Distributor.m in view mode; [Download] [Up]
// // Distributor.m // LGDCommunicationKit Examples, Release 1.0 (prerelease) // // Copyright (c) 1993, Looking Glass Design, Inc. // All rights reserved. // // Project Manager: Paul Girone // Original Author: Mike Gobbi // Creation Date: June 10, 1993 // $Revision: 1.3 $ // #import "Distributor.h" #import <appkit/Application.h> #import <appkit/ButtonCell.h> #import <appkit/Matrix.h> #import <appkit/Menu.h> #import <assert.h> #import <errno.h> #import <lgd/commkit/LGDAppSerialPort.h> #import <libc.h> #import <pwd.h> #import <signal.h> #import "TextExtensions.h" #define POPUP_STRING(button) [button title] static id port; void hangup(void) { // close the connection if ([port isOpen]) { [port close]; } // unlock the device if ([port isLocked]) { [port unlock]; } } void cleanup(void) { // ensure that we are hung up, then die hangup(); exit(1); } @implementation Distributor // Status - displayStatus:sender { NXRunAlertPanel(NULL, "%s\ndevice %s (fd %d) is %s and %s, errno=%d", NULL, NULL, NULL, [serialPort statusString], [serialPort device], [serialPort _fileDescriptor], [serialPort isLocked] ? "locked" : "unlocked", [serialPort isOpen] ? "open" : "closed", errno); return self; } // Communication - send:sender { int result; char buffer[20]; // either treat field as integer... if ([byteSwitch state]) { result = [serialPort sendCharacter:[inputField intValue]]; sprintf(buffer, "<%d>", [inputField intValue]); [outgoingField appendString:buffer addNewline:YES]; // ...or else treat field as string } else { result = [serialPort sendString:[inputField stringValue] withTrailer:"\r"]; [outgoingField appendString:[inputField stringValue] addNewline:YES]; } // check for errors if (result<0) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } // tidy up the GUI [outgoingField scrollSelToVisible]; [inputField selectText:self]; return self; } - poll:sender { char buffer[80]; int count; int character; // either display input as integers... if ([byteSwitch state]) { for (count=[serialPort getCharacter:&character]; count > 0; count=[serialPort getCharacter:&character]) { assert(character!=EOF); sprintf(buffer, "<%d>", character); [incomingField appendString:buffer addNewline:YES]; [incomingField scrollSelToVisible]; } // ... or else display as a string } else { for (count=[serialPort getString:buffer max:80 termChars:"\n\r"]; count > 0; count=[serialPort getString:buffer max:80 termChars:"\n\r"]) { [incomingField appendString:buffer addNewline:NO]; [incomingField scrollSelToVisible]; } } // check for errors if (count!=0) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; // don't keep trying if we had an error if ([serialPort action]){ [autoPollSwitch performClick:self]; } } // tidy up the GUI // we want to use a delayed call because in auto-polling // the continual flicker as multiple lines are polled looks // bad. The 1/2 second delay will ensure that no reselection // takes place during multiple-poll operations. [inputField perform:@selector(selectText:) with:self afterDelay:0.5 cancelPrevious:YES]; return self; } - peek:sender { BOOL flag; // determine whether there is any data flag = [serialPort dataAvailable]; // notify the user if ([serialPort status]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; // or display error message } else { NXRunAlertPanel(NULL, "There is %s data ready to be read", NULL, NULL, NULL, flag ? "new" : "no"); } return self; } - clearTextFields:sender { [[incomingField setText:""] selectText:self]; [[outgoingField setText:""] selectText:self]; [inputField selectText:self]; return self; } // Buffers - flushInput:sender { if (![serialPort flushInput]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } return self; } - flushOutput:sender { if (![serialPort flushOutput]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } return self; } - flushAll:sender { if (![serialPort flush]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } return self; } // Settings - takeCRModFrom:sender { id cell = [sender isKindOf:[Cell class]] ? sender : [sender selectedCell]; [serialPort setCRMassage:[cell state]]; if ([serialPort status]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } return self; } - takeDuplexFrom:sender { id cell = [sender isKindOf:[Cell class]] ? sender : [sender selectedCell]; // confirm that this rather foolish course of action // is in fact desired. if ([cell state] && NXRunAlertPanel("Feedback warning", "If your modem is set to echo, then setting the " "port to echo will result in the next character " "you send bouncing back and forth forever, and " "you will have to send this process a HUP signal " "to regain control.", "Cancel", "Ok", NULL)) { // turn off switch if the user changed their mind [cell perform:@selector(setState:) with:(id)(int)NO afterDelay:0 cancelPrevious:YES]; [window perform:@selector(display) with:nil afterDelay:0 cancelPrevious:YES]; return self; } // if they really do want to, then do it [serialPort setDuplex:[cell state] ? LGD_SP_FULLDUPLEX : LGD_SP_HALFDUPLEX]; if ([serialPort status]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } return self; } - takeAutoPollFrom:sender { id cell = [sender isKindOf:[Cell class]] ? sender : [sender selectedCell]; // we set the target in awakeFromNib, so we need only // set the action here [serialPort setAction:[cell state] ? @selector(poll:) : NULL]; return self; } - takeModeFrom:sender { id cell = [sender isKindOf:[Cell class]] ? sender : [sender selectedCell]; if (![serialPort isOpen]) { return self; } [serialPort setMode:[cell tag]]; if ([serialPort status]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } return self; } // Signals - raiseDTR:sender { [serialPort raiseDTR]; if ([serialPort status]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } return self; } - lowerDTR:sender { [serialPort lowerDTR]; if ([serialPort status]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } return self; } - raiseBRK:sender { [serialPort raiseBreak]; if ([serialPort status]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } return self; } - lowerBRK:sender { [serialPort lowerBreak]; if ([serialPort status]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } return self; } // Application delegate methods - appDidInit:anApplication { char *username; int signals[] = { SIGINT, SIGQUIT, SIGBUS, SIGSEGV, SIGTERM, 0 }; int i; // set ourself up to die nicely no matter what happens // (well, almost whatever. We can't catch KILL) port = serialPort; signal(SIGHUP, (void*)hangup); for (i=0; signals[i]; i++) { signal(signals[i], (void *)cleanup); } // check uid username = getpwuid(geteuid())->pw_name; if (strcmp(username, "root") && strcmp(username, "uucp")) { NXRunAlertPanel("Process Owner", "WARNING: %s. %s", NULL, NULL, NULL, "Not running as root or uucp", "Permission errors are likely"); } return self; } - appWillTerminate:anApplication { // try the orderly shutdown first if ([serialPort isOpen] && ![serialPort unlockAndClose]) { NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, [serialPort statusString]); [serialPort clearStatus]; } // freeing the serial port is the best way to ensure that // it is disconnected properly if the orderly shutdown failed [serialPort free]; return self; } // SerialPort delegate methods - serialPortWillOpen:aPort { const char *device = POPUP_STRING(devicePopup); [aPort setDevice:device]; return self; } - serialPortDidOpen:aPort { [self takeModeFrom:modeMatrix]; [self takeCRModFrom:CRModSwitch]; [self takeDuplexFrom:duplexSwitch]; [sendButton setEnabled:YES]; [pollButton setEnabled:YES]; [peekButton setEnabled:YES]; [devicePopup setEnabled:NO]; [inputField selectText:self]; return self; } - serialPortDidClose:aPort { [sendButton setEnabled:NO]; [pollButton setEnabled:NO]; [peekButton setEnabled:NO]; [devicePopup setEnabled:YES]; return self; } // Archiving - awakeFromNib { [sendButton setEnabled:NO]; [pollButton setEnabled:NO]; [peekButton setEnabled:NO]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.