This is Servers.m in view mode; [Download] [Up]
/*--------------------------------------------------------------------------- Servers.m -- Copyright (c) 1991 Rex Pruess This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or send electronic mail to the the author. Servers manages the Nameservers window. It build the scrollView of servers based on data it receives from the default Nameserver. Rex Pruess <Rex-Pruess@uiowa.edu> $Header: /rpruess/apps/Ph/qiServers.subproj/RCS/Servers.m,v 3.0 93/06/26 07:49:04 rpruess Exp $ ----------------------------------------------------------------------------- $Log: Servers.m,v $ Revision 3.0 93/06/26 07:49:04 rpruess Brought Ph code up to NeXTSTEP 3.0 specifications. Also, fixed bug for those sites with ns-servers entries which do not have a Site field without a corresponding Server field. Now, I assign "unknown" to the Server field so that there is at least a value associated with that field. Revision 2.3 92/04/27 14:00:25 rpruess Fixed a bug that caused Ph to crash for remote help. The bug was obscure. If the Nameserver did not maintain a site name for the default Nameserver, then Ph would crash. This should not happen anymore. Revision 2.2 91/12/15 15:55:58 rpruess Renames the startTimer/stopTimer methods so they are unique within the Ph group of files. This change wasn't really needed except to help clarify which methods belonged to which object files. Revision 2.1 91/12/10 16:20:13 rpruess Added code to support the "hide" preference options. This code was added prior to sending the first production release to the archive sites. Revision 2.0 91/11/19 08:26:28 rpruess Revision 2.0 is the initial production release of Ph. -----------------------------------------------------------------------------*/ #define MAXSECS 1.0 /* Max # of seconds before alert panel */ #define MINSERVERSHEIGHT 115.0 #define MINSERVERSWIDTH 150.0 #define TIMERSECS 0.2 /* Animator wakeup interval */ /* Application class header files */ #import "Servers.h" #import "Qi.h" #import "QiManager.h" #import "Site.h" #import "../PhShare.h" #import "../info.h" #import "../query.h" /* Qi Server header file (Qi return codes) */ #import "QiReplies.h" @implementation Servers /*--------------------------------------------------------------------------- Load the Servers.nib file, initialize variables, create the Servers matrix, and set up the ScrollView. -----------------------------------------------------------------------------*/ - init { NXSize cSize; NXRect mRect; self = [super init]; [NXApp loadNibSection:"Servers.nib" owner:self withNames:NO]; [serversWindow setMiniwindowIcon:"app"]; [NXHelpPanel attachHelpFile:"Commands/Menus/Main/ServersWindow.rtfd" markerName:NULL to:serversWindow]; qiManager = nil; queryManager = nil; serversMenuCell = nil; curSite = 0; hasServers = NO; serversAnimator = [[Animator alloc] initChronon:TIMERSECS adaptation:0.0 target:self action:@selector (serversTimeCheck) autoStart:NO eventMask:0]; siteList = [[List alloc] init]; /*** Create the Servers matrix. This matrix will hold the site names of all the NameServers. */ mRect.origin.x = 0; mRect.origin.y = 0; [serversScrollView getContentSize:&mRect.size]; serversMatrix= [[Matrix alloc] initFrame:&mRect mode:NX_RADIOMODE cellClass:[SelectionCell class] numRows:0 numCols:1]; [serversMatrix setAutosizing:NX_WIDTHSIZABLE]; [serversMatrix setAutosizeCells:YES]; [serversMatrix setTarget:self]; [serversMatrix setAction:@selector(singleClick)]; [serversMatrix setDoubleAction:@selector(doubleClick)]; [serversMatrix getCellSize:&cSize]; cSize.width = mRect.size.width; [serversMatrix setCellSize:&cSize]; [[serversScrollView setDocView:serversMatrix] free]; [serversScrollView setDocCursor:NXArrow]; return self; } /*--------------------------------------------------------------------------- Set ID of objects we need later on. -----------------------------------------------------------------------------*/ - initIDs:aMenuCell queryManager:aQueryManager qiManager:aQiManager { serversMenuCell = aMenuCell; queryManager = aQueryManager; qiManager = aQiManager; return self; } /*--------------------------------------------------------------------------- Build the serversMatrix based on the site names which were retrieved earlier from the default Nameserver. -----------------------------------------------------------------------------*/ - buildMatrix { int i; int nServers; nServers = [siteList count]; /*** Add each Nameserver site to the serversMatrix. */ for (i = 0; i < nServers; i++) { [serversMatrix addRow]; [[serversMatrix cellAt:i:0] setStringValue:[[siteList objectAt:i] site]]; } [serversMatrix sizeToCells]; [serversMatrix display]; /*** We finally have the name of the site for the default server. Select the default server in the Servers matrix so it is selected & visible when the Servers window is brought forward. */ for (i = 0; i < nServers; i++) { if (strcmp (defaultServer, [[siteList objectAt:i] server]) == 0) { [serversMatrix selectCellAt:i:0]; [serversMatrix scrollCellToVisible:i:0]; [serversTextField setStringValue:defaultServer]; [domainTextField setStringValue:[[siteList objectAt:i] domain]]; break; } } /*** Enable the Servers menu item. */ [serversMenuCell setEnabled:YES]; return self; } /*--------------------------------------------------------------------------- Save the defaultServer object for later use. Start the timer and wait for the earlier "fields" command to finish. When the "fields" are back, the timer will stop, & the query ns-servers" command will be issued to generate the entire list of Nameservers. -----------------------------------------------------------------------------*/ - fetchServers:(const char *)aServer { defaultServer = malloc (strlen (aServer) + 1); strcpy (defaultServer, aServer); if ((defaultQi = [qiManager open:defaultServer]) == nil) return self; [self startServersTimer:self]; return self; } /*--------------------------------------------------------------------------- Update the Servers & Domain text fields to reflect the newly selected entry. -----------------------------------------------------------------------------*/ - singleClick { id aCell; int i; aCell = [serversMatrix selectedCell]; for (i = 0; i < [siteList count]; i++) { if (strcmp ([aCell stringValue], [[siteList objectAt:i] site]) == 0) { [serversTextField setStringValue:[[siteList objectAt:i] server]]; [domainTextField setStringValue:[[siteList objectAt:i] domain]]; break; } } return self; } /*--------------------------------------------------------------------------- User has doubleClicked a Server. Must bring it to life. -----------------------------------------------------------------------------*/ - doubleClick { [queryManager startQuery:[serversTextField stringValue]]; return self; } /*--------------------------------------------------------------------------- Display the Servers window. -----------------------------------------------------------------------------*/ - showServersWindow:sender { [serversWindow makeKeyAndOrderFront:self]; return self; } /*--------------------------------------------------------------------------- Don't let the Servers window be too small. -----------------------------------------------------------------------------*/ - windowWillResize:sender toSize:(NXSize *) frameSize { if (frameSize -> width < MINSERVERSWIDTH) frameSize -> width = MINSERVERSWIDTH; if (frameSize -> height < MINSERVERSHEIGHT) frameSize -> height = MINSERVERSHEIGHT; return self; } /*--------------------------------------------------------------------------- This method is set to be Qi's delegate. It processes one line of Qi output at a time. This output is the result of the "ns-servers" inquiry. Upon end of output, it is responsible for telling Qi to stop and for lanuching a Query window for the default server. -----------------------------------------------------------------------------*/ - qiOutput:(char *)aBuf { int len; int theCode; char *theData; id theSite; theCode = atoi (aBuf); if (theCode == LR_NUMRET) return self; if (theCode >= LR_OK) { /* Tell the Qi object to stop watching FD */ [self qiOutputIsDone:self]; return self; } if (theCode == -LR_OK || theCode == -LR_AINFO || theCode == -LR_ABSENT || theCode == -LR_ISCRYPT) { len = strlen (aBuf) - 1; if (aBuf[len] == '\n') aBuf[len] = '\0'; /*** Insert new sites alphabetically in the list. */ theData = strstr (aBuf, "site:"); if (theData != NULL) { theData += strlen ("site:"); theSite = [[Site alloc] init]; [theSite setSite:theData]; [theSite setServer:"unkown"]; for (curSite = 0; curSite < [siteList count]; curSite++) { if (strcmp (theData, [[siteList objectAt:curSite] site]) < 0) break; } [siteList insertObject:theSite at:curSite]; return self; } /*** Assign "server" & "domain" lines to the curSite object. */ theData = strstr (aBuf, "server:"); if (theData != NULL) { theData += strlen ("server:"); [[siteList objectAt:curSite] setServer:theData]; return self; } theData = strstr (aBuf, "domain:"); if (theData != NULL) { theData += strlen ("domain:"); [[siteList objectAt:curSite] setDomain:theData]; return self; } } return self; } /*--------------------------------------------------------------------------- The "ns-servers" output has been received. -----------------------------------------------------------------------------*/ - qiOutputIsDone:sender { id theSite; hasServers = YES; [defaultQi stopFd:self]; /*** Insist that the default server be in the siteList. This should not happen, provided the Ph administrator maintains the default server in the "ns-servers" entry. If we must add it in, then we don't bother to insert it alphabetically (we tack it to the front). */ if ([self getSiteName:defaultServer] == NULL) { theSite = [[Site alloc] init]; [theSite setSite:defaultServer]; [theSite setServer:defaultServer]; [siteList insertObject:theSite at:0]; } /*** Build the Servers matrix. */ [self buildMatrix]; /*** If the user has requested not to see the default Query window, then simply return. */ if (strcmp (NXGetDefaultValue ([NXApp appName], HIDEQUERY), "YES") == 0) return self; /*** If Ph was auto-launched & the user has requested it to hide, then simply return. The default Query session will be started when the user first unhides Ph. */ if (strcmp (NXGetDefaultValue ([NXApp appName], "NXAutoLaunch"), "YES") == 0 && strcmp (NXGetDefaultValue ([NXApp appName], HIDELAUNCH), "YES") == 0) return self; /*** Start the default Query session. */ [queryManager startQuery:defaultServer]; return self; } /*--------------------------------------------------------------------------- The animator is responsible for periodically invoking this method. This code checks to see if the Qi object has been initialized. Qi objects need to get "fields" data so there is some delay before they come to life. -----------------------------------------------------------------------------*/ - serversTimeCheck { if ([defaultQi hasQiFields] == YES) { [self stopServersTimer:self]; [defaultQi qiSend:"query ns-servers type=serverlist return text\n" delegate:self]; } return self; } /*--------------------------------------------------------------------------- Wait for the Qi object to initialize. -----------------------------------------------------------------------------*/ - startServersTimer:sender { [serversAnimator startEntry]; return self; } /*--------------------------------------------------------------------------- The Qi object has initialized itself or we've given up on it. The timer is only needed once so free it after its been stopped. -----------------------------------------------------------------------------*/ - stopServersTimer:sender { [serversAnimator stopEntry]; [serversAnimator free]; return self; } /*--------------------------------------------------------------------------- Add a new server/site. This method is invoked via the Speaker/Listener code. If another app requests a connection with a server that we don't know about, we honor the request anyway. -----------------------------------------------------------------------------*/ - addServerSite:(const char *)aServer site:(const char *)aSite { int ind; int nServers; id theSite; /*** If we already have an entry for this server, then skip the new request. */ if ([self getSiteName:aServer] != NULL) return self; /*** Find the alphabetical position for the new entry. */ nServers = [siteList count]; for (ind = 0; ind < nServers; ind++) { if (strcmp (aSite, [[siteList objectAt:ind] site]) < 0) break; } /*** Create the new site & insert it into siteList. */ theSite = [[Site alloc] init]; [theSite setServer:aServer]; [theSite setSite:aSite]; [siteList insertObject:theSite at:ind]; /*** Add it to the end of the Servers matrix too. */ [serversMatrix insertRowAt:ind]; [[serversMatrix cellAt:ind :0] setStringValue:aSite]; [serversMatrix sizeToCells]; [serversMatrix display]; return self; } /*--------------------------------------------------------------------------- Return the domain name for the specified server. -----------------------------------------------------------------------------*/ - (const char *)getDomainName:(const char *)aServer { int i; int nSites; nSites = [siteList count]; for (i = 0; i < nSites; i++) { if (strcmp (aServer, [[siteList objectAt:i] server]) == 0) return [[siteList objectAt:i] domain]; } return NULL; } /*--------------------------------------------------------------------------- Return the server name for the specified site. -----------------------------------------------------------------------------*/ - (const char *)getServerName:(const char *)aSite { int i; int nSites; if (aSite == NULL) return NULL; nSites = [siteList count]; for (i = 0; i < nSites; i++) { if (strcmp (aSite, [[siteList objectAt:i] site]) == 0) return [[siteList objectAt:i] server]; } return NULL; } /*--------------------------------------------------------------------------- Return the site name for the specified server. -----------------------------------------------------------------------------*/ - (const char *)getSiteName:(const char *)aServer { int i; int nSites; if (aServer == NULL) return NULL; nSites = [siteList count]; for (i = 0; i < nSites; i++) { if (strcmp (aServer, [[siteList objectAt:i] server]) == 0) return [[siteList objectAt:i] site]; } return NULL; } /*--------------------------------------------------------------------------- Return a tab-separated list of the server names and the site names. This method is for the Speaker/Listener support. Some other application may need to know what sites/servers Ph knows about. -----------------------------------------------------------------------------*/ - getServersAndSites:(char **)serverNames sites:(char **)siteNames { int i; int nSites; int serverLen; int siteLen; serverLen = 1; /* Need one byte for the trailing '\0' */ siteLen = 1; /*** Make a pass through all the site objects and figure out the malloc sizes. */ nSites = [siteList count]; for (i = 0; i < nSites; i++) { serverLen += strlen ([[siteList objectAt:i] server]) + 1; siteLen += strlen ([[siteList objectAt:i] site]) + 1; } /*** Create the variables exactly as big as we need them. */ *serverNames = malloc (serverLen); *siteNames = malloc (siteLen); *serverNames[0] = '\0'; *siteNames[0] = '\0'; /*** Build the server & site strings. */ for (i = 0; i < nSites; i++) { strcat (*serverNames, [[siteList objectAt:i] server]); strcat (*serverNames, "\t"); strcat (*siteNames, [[siteList objectAt:i] site]); strcat (*siteNames, "\t"); } return self; } /*--------------------------------------------------------------------------- Return flag indicating whether or not we have received the server names. -----------------------------------------------------------------------------*/ - (BOOL)hasServers { return hasServers; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.