home *** CD-ROM | disk | FTP | other *** search
- /*
- * Object to peck on a remote network weather service.
- *
- * Michael Hawley
- * MIT Media Laboratory
- * 20 Ames Street
- * Cambridge, MA 02139
- * mike@media-lab.mit.edu
- * Copyright (c) 1991 MIT Media Laboratory
- * Burn before reading! This means you!!
- *
- * Please forward any comments/revisions.
- * Keep in mind that this was a one-day knock off;
- * much of the complexity is due to the fact that
- * we have to parse a telnet conversation that was
- * never intended for such.
- */
-
- #import "Storm.h"
- #import "Process.h"
- #import <appkit/Form.h>
- #import <appkit/Font.h>
- #import <appkit/Text.h>
- #import <appkit/TextField.h>
- #import <appkit/Button.h>
- #import <appkit/PopUpList.h>
- #import <appkit/ScrollView.h>
- #import <appkit/Matrix.h>
- #import <appkit/NXBrowser.h>
- #import <appkit/Speaker.h>
- #import <appkit/Listener.h>
- #import "MyMenuCell.h"
- #import "Defaults.h"
- #import "License.h"
-
- @implementation Storm
-
- static int blank(char *s){
- while (*s && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')) s++;
- return *s? 0 : 1;
- }
-
- int StormDebug = 1;
- id _status;
- extern int Verbose;
-
- char *
- path(char *s)
- /*
- * if 's' is in [NXArgv[0]], return [NXArgv[0]]/s.
- * (for looking up internal commands and files in .../Opener.app/...).
- */
- {
- char t[1024], *q, *r;
- static char p[1024];
- extern char **NXArgv;
- *t = '\0';
- sscanf(s,"%s",t);
- if (!*t || *t=='(') return s;
- r = s + strlen(t);
- strcpy(p,*NXArgv);
- if (q=rindex(p,'/'))
- strcpy(q+1,t);
- else
- strcpy(p,t);
- if (access(p,0)==0){
- strcpy(p+strlen(p),r);
- return p;
- }
- return s;
- }
-
- static void say(s, a,b,c,d) id s; char *a,*b,*c,*d; {
- char p[1024];
- sprintf(p,a,b,c,d);
- [s setStringValue:p];
- [s display];
- NXPing();
- }
-
- void message(a,b,c,d) char *a,*b,*c,*d; {
- char p[1024];
- sprintf(p,a,b,c,d);
- [_status setStringValue:p];
- [_status display];
- NXPing();
- }
-
- static int eq(char *a, char *b){ return strncmp(a,b,strlen(b))==0; }
- static int eqtail(char *s, char *t){ /* true if t appears at end of s */
- int tn = strlen(t), sn = strlen(s);
- if (tn > sn) return 0;
- return strcmp(s+(sn-tn), t)==0;
- }
- static int streq(char *a, char *b){ return strcmp(a,b)==0; }
- static char *strindex(char *s, char *t){
- int n = strlen(t);
- if (s) while (*s)
- if (!strncmp(s, t, n))
- return s;
- else
- s++;
- return (char *)0;
- }
- static int match(char *a, char *b){
- return eq(a,b) || strindex(a,b) || strindex(b,a);
- }
- static char *stripnl(char *s){
- char *p;
- for (p=s;*p;p++) if (*p == '\n' || *p == '\r') *p = '\0';
- return s;
- }
-
- id _P;
-
- static void put(P, fmt, a, b, c, d) id P; char *fmt, *a, *b, *c, *d; {
- char p[1024];
- sprintf(p,fmt,a,b,c,d);
- if (Verbose) printf("+ %s\n",p);
- [P puts:p];
- }
-
- void Put(fmt, a, b, c, d) char *fmt, *a, *b, *c, *d; {
- char p[1024];
- sprintf(p,fmt,a,b,c,d);
- if (Verbose) printf("+ %s\n",p);
- if (_P) [_P puts:p];
- }
-
-
- static char *
- get(P, s, n) id P; char *s; int n; {
- [P gets:s:n];
- if (*s && Verbose) printf("> %s",s);
- return *s? s : (char *)0;
- }
-
- char *
- pgets(s,n) char *s; int n; {
- [_P gets:s:n];
- return *s? s : (char *)0;
- }
-
- static char *
- flush(P,s) id P; char *s; {
- static char t[1024];
- while (get(P,t,sizeof t))
- if (strindex(t,s)) return t;
- sleep(1);
- while (get(P,t,sizeof t))
- if (strindex(t,s)) return t;
- return (char *)0;
- }
-
- char *
- Flush(s) char *s; {
- static char t[1024];
- if (_P) return;
- while (get(_P,t,sizeof t))
- if (strindex(t,s)) return t;
- sleep(1);
- while (get(_P,t,sizeof t))
- if (strindex(t,s)) return t;
- return (char *)0;
- }
-
- - enable:(BOOL)b {
- [attachB setIcon:b? "plug" : "unplug"];
- return self;
- }
-
- static id _text, _scroll;
-
- - initMatrix {
- // from the nib file, we have the help text; keep a pointer to it.
- _text = helpText = [scrollView docView];
- [_text setDelegate:self];
- [_text setMarginLeft:6.0 right:6.0 top:0.0 bottom:0.0];
- [_text notifyAncestorWhenFrameChanged:YES];
- return self;
- }
-
- - setScrollView:anObject {
- _scroll = scrollView = anObject;
- [self initMatrix];
- return self;
- }
-
- extern char DefaultFont[];
- extern char DefaultFontSize[];
- static id fid = (id)0;
- static int canconvert = 0;
- double atof();
-
- - textWillConvert:textObject fromFont:from toFont:to {
- if (canconvert && strcmp(DefaultFont,[from name])==0 &&
- atof(DefaultFontSize) == [from pointSize]){
- strcpy(DefaultFont,[to name]);
- sprintf(DefaultFontSize,"%f",[to pointSize]);
- fid = to;
- writeDefaults();
- }
- return to;
- }
-
- void
- setText(s) char *s; {
- static NXPoint origin = {0.0,0.0};
- id w = [_scroll window];
-
- if (!fid){
- fid = [Font newFont:DefaultFont size:atof(DefaultFontSize)];
- }
- canconvert=0;
- [w disableFlushWindow];
- [_text setText:s];
- [_text setSel:0:999999];
- [_text setSelGray:0.0];
- [_text setSelFont:fid];
- [_text selectNull];
- [_text scrollPoint:&origin];
- [_scroll display];
- [[w reenableFlushWindow] flushWindow];
- NXPing();
- canconvert=1;
- }
-
- void openFile(char *s){ /* open 's' in workspace */
- int ok = 0;
- id p = [NXApp appSpeaker];
- char t[512];
-
- sprintf(t,"\nThe file\n %s\nwill open in the workspace.",s);
- setText(t);
- [p setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
- [p openFile:s ok:&ok];
- if (!ok) sprintf(t,"\nCouldn't open: %s",s), setText(t);
- }
-
- isRTF(s) char *s; {
- int f = open(s,0);
- if (f > 0){
- char t[128];
- int n = read(f,t,sizeof(t));
- close(f);
- if (n <= 0) return 0;
- return strncmp(t,"{\\rtf",5)==0;
- } else
- return 0;
- }
-
- void
- setFile(s) char *s; {
- char *p = path(s);
- NXStream *f = NXMapFile(p,NX_READONLY);
- static NXPoint origin = {0.0,0.0};
- id w = [_scroll window];
-
- canconvert=0;
- if (!f) return ;
- [w disableFlushWindow];
-
- if (isRTF(p)){
- [_text setMonoFont:NO];
- [_text readRichText:f];
- } else {
- [_text readText:f];
- [_text setSel:0:999999];
- [_text setSelGray:0.0];
- if (!fid)
- fid = [Font newFont:DefaultFont size:atof(DefaultFontSize)];
- [_text setSelFont:fid];
- [_text selectNull];
- canconvert=1;
- }
- NXCloseMemory(f,NX_FREEBUFFER);
- [_text scrollPoint:&origin];
- [_scroll display];
- [[w reenableFlushWindow] flushWindow];
- }
-
- - showHelp:sender {
- setFile("info");
- return self;
- }
-
- #define Case break; case
-
- static char *prompt = "archie>";
-
- squishRtn(char *s){
- char *p = s;
-
- while (*p = *s++)
- if (*p != '\r') ++p;
- }
-
- static char *
- getLine(char *s, char *t){ /* read ...\n from s into t; return new s */
- char *p = t;
- *t = '\0';
- squishRtn(s);
- while (*s && *s != '\n') *p++ = *s++;
- if (*s == '\n') *p++ = *s++;
- *p++ = '\0';
- if (*t == '\0') return (char *)0;
- if (Verbose) printf("- %s",t);
- return s;
- }
-
- - processOutput:(char *)s {
- static char prev[8192]="";
- char t[1024], *p=prev;
-
- strcat(prev,s); s = t;
- while ((p=getLine(p,s)) &&
- (index(s,'\n') || strcmp(s+strlen(s)-2,": ")==0 ||
- strcmp(s+strlen(s)-1,":")==0))
- execState(0,s);
- strcpy(prev,blank(s)?s:"");
- return self;
- }
-
- static id me;
-
- Command(s) char *s; {
- if (!_P) {
- substr(s,"$Site",Site);
- _P = [Process new:s delegate:me];
- }
- }
-
- - click:sender {
- id c = [[browser matrixInColumn:[browser lastColumn]] selectedCell];
- if ([c isLeaf])
- [c click:self];
- return self;
- }
-
- - click2:sender {
- return self;
- }
-
- ensurelogin(){
- [me ensurelogin];
- return _P? 1 : 0;
- }
-
- - ensurelogin {
- //if (!_P) [self login:self];
- return self;
- }
-
- - login:sender {
- if (_P) [_P free]; P = _P = (id)0;
- _status = status;
- [self setFetch];
- ReadState(path("menus"));
- [browser setDelegate:self];
- [browser setCellPrototype:[[MyMenuCell alloc] init]];
- [browser loadColumnZero];
- [browser setAction:@selector(click:)];
- [browser setDoubleAction:@selector(click2:)];
- [browser setTarget:self];
- [attachB setIcon:"plug"];
- runState("");
- return self;
- }
-
- void
- logout(){
- [me logout:me];
- }
-
- - logout:sender {
- if (P && _P) setState("Detach"), runState("");
- if (P) [P terminate:self];
- _P = P = (id)0;
- [self enable:NO];
- [attachB setIcon:"unplug"];
- message("not connected.");
- return self;
- }
-
- extern int sleep();
-
- - attach:sender {
- if (eq((char *)[sender icon],"unplug")){
- [self login:sender];
- } else {
- [self logout:sender];
- }
- return self;
- }
-
- /*
- * the buttons and commands to run at startup time.
- */
- id Fetch[NumFetch];
-
- int FetchSelected = -1;
-
- - setFetch {
- int i;
- Fetch[0] = fetch1;
- Fetch[1] = fetch2;
- Fetch[2] = fetch3;
- for (i=0;i<NumFetch;i++) [self setFetchText:i:FetchText[i]];
- return self;
- }
-
- - setFetchText:(int)i:(char *)s {
- [Fetch[i] setStringValue:s];
- strcpy(FetchText[i],s);
- [Fetch[i] display];
- return self;
- }
-
- - setFetchText:(char *)s {
- if (FetchSelected >= 0)
- [self setFetchText:FetchSelected:s];
- return self;
- }
-
- void
- setFetchText(s) char *s; {
- [me setFetchText:s];
- }
-
- - setFetch:(int)i:(int)state {
- [Fetch[i] setBackgroundGray:state?1.0:.666];
- if (state) [self setFetchText:i:""];
- else [Fetch[i] display];
- return self;
- }
-
- - hitRadio:sender {
- int i;
- int n = [sender selectedRow], state = [[sender selectedCell] state];
- [self setFetch:n:state];
- FetchSelected = state? n : -1;
- for (i=0; i<NumFetch; i++){
- if (i != n || !state){
- [[sender cellAt:i:0] setState:0];
- [self setFetch:i:0];
- }
- }
- [sender display];
- return self;
- }
-
- fetchReports() {
- int i;
- char buf[80000], *p = buf;
- while (pgets(buf,1024) && !strindex(buf,curMenuLast())) ;
- *buf = '\0';
- for (i=0;i<NumFetch;i++){
- if (!blank(FetchText[i])){
- message("%s. . .",FetchText[i]);
- fetchReport(FetchText[i],p);
- if (p[0]){
- p += strlen(p);
- if (i < (NumFetch-1))
- strcpy(p,"\n===============================\n");
- p += strlen(p);
- }
- }
- }
- squishRtn(buf);
- squishwhite(buf);
- if (*buf) setText(buf);
- message("connected!");
- }
-
- - setSite:thing {
- openDefaults();
- site = thing;
- [site setTitle:Site];
- return self;
- }
-
- - hitSite:sender {
- char *s = (char *)[[sender selectedCell] title];
- strcpy(Site,s);
- writeDefaults();
- return self;
- }
-
- /*
- * telnet:
- */
- #import <appkit/Pasteboard.h>
- #import <appkit/Speaker.h>
- #import <appkit/Listener.h>
- - copyString:(char *)s {
- id p = [Pasteboard new];
- [p declareTypes:&NXAsciiPboard num:1 owner:self];
- [p writeType:NXAsciiPboard data:s length:strlen(s)];
- return self;
- }
-
- - launchTerminal:(char *)program {
- id p = [NXApp appSpeaker];
- port_t t = NXPortFromName("Terminal",NULL);
- int ok;
- if (t==PORT_NULL) return self;
- [p setSendPort:t];
- [self copyString:program];
- (void)[p msgPaste:&ok];
- return self;
- }
-
- - telnet:sender {
- char p[1024];
- sprintf(p,"telnet %s 3000\n",Site);
- [self launchTerminal:p];
- return self;
- }
-
- - sendComments:sender {
- return self;
- }
-
- #import <appkit/PrintInfo.h>
-
- - print:sender {
- static int p = 0;
- if (!p){
- p++;
- [[NXApp printInfo] setScalingFactor:.9];
- }
- return [_text printPSCode:sender];
- }
-
- - pageLayout:sender {
- return [NXApp runPageLayout:sender];
- }
-
- + new {
- me = self = [[Storm alloc] init];
- return self;
- }
-
- - free {
- [self logout:self];
- return [super free];
- }
-
-
- - appDidInit:sender {
- openDefaults();
- if (FirstUse()) [license show:self];
- [attachB performClick:sender];
- return self;
- }
-
- - appWillTerminate:sender {
- [self logout:self];
- System("/bin/rm -rf /tmp/W_maps /tmp/W_scratch &");
- writeDefaults();
- return self;
- }
-
- - (int)browser:sender fillMatrix:matrix inColumn:(int)column {
- char *s = "Main";
- if (column>0){
- id c;
- c = [[browser matrixInColumn:[browser lastColumn]] selectedCell];
- s = [c get];
- }
- setMenu(s);
- return numItem(s);
- }
-
- - browser:sender loadCell:c atRow:(int)row inColumn:(int)column {
- [c setStringValueNoCopy:curMenuItem(row)];
- return self;
- }
-
- - browserDidScroll:sender {
- static int pc = -1;
- int c = [browser firstVisibleColumn];
- ensurelogin();
- if (pc == c) return self;
- pc = c;
- if (c == 0) Put("m\n"), Flush("Change scroll"), setMenu("Main");
- else
- [[[browser matrixInColumn:0] selectedCell] click:self];
- return self;
- }
-
-
- @end
-