home *** CD-ROM | disk | FTP | other *** search
- /* (C) 1993 Stuart Cheshire <cheshire@cs.stanford.edu>
-
- This sample code can be used to obtain a list of AppleTalk Zones on the
- network. It uses an efficient sorting algorithm to sort a large number
- zone names into alphabetical order in an acceptable length of time.
- I'm making this public because a shocking number of programs, like MacTCP,
- Shiva Net Manager, Spectre Supreme etc. are unable to do this. The Stanford
- network has over 200 zones, and on a Mac SE it takes *over a minute* just
- to open the MacTCP Control Panel!
-
- MAX_ZONES is set to 1000 by default, which should be enough for most networks.
-
- You should create a List Manager list, and then call getzonelist to fill it.
-
- eg.
- static Rect initial_list = { 0,0,0,1 };
- static Point list_cell_size = { 0,0 };
-
- GetDItem(modaldialog, zonelist_item, &di_type, &di_handle, &di_box);
- // Read useritem bounds from DITL
- di_box.right -= 15; // Make room for the vertical scroll bar
- zonelist = LNew(&di_box, &initial_list, list_cell_size, 0, modaldialog,
- TRUE, FALSE, FALSE, TRUE); // Create the list
-
-
- LDoDraw(FALSE, zonelist); // Turn off list drawing
- num_appletalk_zones = getzonelist(zonelist, mydomain.c);
- // Get the list of zones
- pt.h = pt.v = 0;
- LSearch(&myzone.c[1], myzone.c[0], NULL, &pt, zonelist);
- LSetSelect(TRUE, pt, zonelist); // select home zone as default
- LAutoScroll(zonelist); // scroll it into view
- LDoDraw(TRUE, zonelist); // and turn on list drawing again.
-
-
- Tab stops are four spaces
-
- /*****************************************************************************/
-
- #include <AppleTalk.h>
- #include <Packages.h>
-
- #include "StuTypes.h"
- #include "StuAppleTalk.h"
-
- /*****************************************************************************/
-
- #define atpMaxData 578 // size of buffer for zone names
- #define kZIPSocket 6 // the Zone Information Protocol socket
- #define kATPTimeOutVal 3 // re-try ATP SendRequest every 3 seconds
- #define kATPRetryCount 5 // for five times
- #define kGZLCall 0x08000000 // GetZoneList indicator
- #define kGMZCall 0x07000000 // GetMyZone indicator
- #define kZoneCount 0x0000FFFF // mask to count zones in buffer
- #define kNoMoreZones 0xFF000000 // mask to see if more zones to come
-
- #define xCall 246
- #define zipGetLocalZones 5
- #define zipGetZoneList 6
- #define zipGetMyZone 7
-
- typedef struct
- {
- QElemPtr qLink;
- short qType;
- short ioTrap;
- Ptr ioCmdAddr;
- ProcPtr ioCompletion;
- OSErr ioResult;
- StringPtr ioNamePtr;
- short ioVRefNum;
- short ioRefNum;
- short csCode;
- short xppSubCode;
- u_char xppTimeOut;
- u_char xppRetry;
- short filler;
- Ptr zipBuffPtr;
- short zipNumZones;
- short zipLastFlag;
- short zipInfoField[35];
- } xCallParam;
-
- /*****************************************************************************\
-
- These global variables hold the zone names, the heap of pointers used to
- sort them, and the counter which says how many zones there are on the heap.
-
- The code could be made more elegant (and re-entrant) if the routines were
- wrapped up into a "ZoneList" C++ object, and the globals could then be made
- private class member variables.
- */
-
- #define MAX_ZONES 1000
- typedef struct { u_char c[34]; } ZONE_NAME;
- local ZONE_NAME *zone_array, **zone_heap;
- local short num_zones;
-
- /*****************************************************************************\
-
- These two routines are used to sort the zone list into alphabetical order
- */
-
- local void ZL_addtoheap(int place, ZONE_NAME *new)
- {
- int parent = (place-1)>>1;
- zone_heap[place]=new;
- while (place>0 && IUCompString(zone_heap[parent]->c, zone_heap[place]->c)>0)
- {
- ZONE_NAME *temp = zone_heap[place ];
- zone_heap[place ] = zone_heap[parent];
- zone_heap[parent] = temp;
- place=parent;
- parent=(place-1)>>1;
- }
- }
-
- local ZONE_NAME *ZL_removefromheap(int last)// last is index of last item on heap
- {
- ZONE_NAME *top = zone_heap[0]; // extract top element
- int gap = 0; // top is now empty
- int left = 1;
- int right = 2;
- while(left<=last) // move gap to bottom
- {
- if(right>last || IUCompString(zone_heap[right]->c, zone_heap[left]->c)>0)
- { zone_heap[gap]=zone_heap[left ]; gap=left; }
- else{ zone_heap[gap]=zone_heap[right]; gap=right; }
- left = (gap<<1)+1;
- right = left + 1;
- }
- if(last != gap) ZL_addtoheap(gap, zone_heap[last]); // fill gap
- return(top); // and heap is now one element smaller
- }
-
- /*****************************************************************************\
-
- This routine (the old method) is used if AppleTalk Phase Two is not available
- */
-
- local void BuildZoneListPhase1(u_char *myzone)
- {
- ATPParamBlock pb;
- BDSElement dBDS;
- u_char datapacket[atpMaxData];
- short i;
-
- dBDS.buffSize = atpMaxData;
- dBDS.buffPtr = (Ptr)datapacket;
-
- pb.ATPatpFlags = 0;
- pb.ATPreqLength = 0;
- pb.ATPreqPointer = NULL;
- pb.ATPbdsPointer = (Ptr) &dBDS;
- pb.ATPnumOfBuffs = 1;
- pb.ATPtimeOutVal = kATPTimeOutVal;
- pb.ATPretryCount = kATPRetryCount;
-
- pb.ATPaddrBlock.aNet = ABusVars->sysNetNum;
- pb.ATPaddrBlock.aNode = GetBridgeAddress();
- pb.ATPaddrBlock.aSocket = kZIPSocket;
-
- if (!pb.ATPaddrBlock.aNode) return; // no bridge -- no zones
-
- do {
- u_char *ptr = datapacket;
- pb.ATPuserData = kGZLCall + num_zones + 1;
- PSendRequest(&pb, false);
- i = dBDS.userBytes & kZoneCount;
- while(--i >= 0)
- {
- int count = 1 + *ptr;
- u_char *dest = zone_array[num_zones].c;
- while (count-- > 0) *dest++ = *ptr++;
- ZL_addtoheap(num_zones, &zone_array[num_zones]);
- num_zones++;
- }
- } until(dBDS.userBytes & kNoMoreZones);
-
- pb.ATPuserData = kGMZCall;
- datapacket[0] = 0;
- if (PSendRequest(&pb, false) == noErr && datapacket[0] && datapacket[0]<32)
- for (i=0; i<=datapacket[0]; i++) myzone[i] = datapacket[i];
- }
-
- /*****************************************************************************\
-
- This routine (the new method) should be used in almost all cases these days
- */
-
- local void BuildZoneListPhase2(u_char *myzone)
- {
- short XPPRefNum;
- xCallParam xpb;
- u_char datapacket[atpMaxData];
-
- if (OpenDriver("\p.XPP", &XPPRefNum)) return;
-
- xpb.zipInfoField[0] = 0;
- xpb.zipInfoField[1] = 0;
- xpb.zipLastFlag = FALSE;
- xpb.ioRefNum = XPPRefNum;
- xpb.csCode = xCall;
- xpb.xppSubCode = zipGetZoneList;
- xpb.xppTimeOut = kATPTimeOutVal;
- xpb.xppRetry = kATPRetryCount;
- xpb.zipBuffPtr = (Ptr)datapacket;
-
- while (!xpb.zipLastFlag && PBControl((ParmBlkPtr)&xpb, FALSE) == noErr)
- {
- u_char *ptr = datapacket;
- short i = xpb.zipNumZones;
- while(--i >= 0)
- {
- int namelength = 1 + *ptr;
- u_char *dest = zone_array[num_zones].c;
- while (namelength-- > 0) *dest++ = *ptr++;
- ZL_addtoheap(num_zones, &zone_array[num_zones]);
- num_zones++;
- }
- }
-
- xpb.zipInfoField[0] = 0;
- xpb.zipInfoField[1] = 0;
- xpb.xppSubCode = zipGetMyZone;
- xpb.zipBuffPtr = (Ptr)myzone;
- PBControl((ParmBlkPtr)&xpb, FALSE);
- // Mustn't close XPP driver (see IM V 532)
- }
-
- /*****************************************************************************\
-
- This routine fills the given ListHandle with the list of zone names,
- in alphabetical order, and also puts the name of the 'home' zone for
- this Machintosh in the string pointed to by myzone. The return value
- is the number of zone names put into the ListHandle.
- */
-
- short getzonelist(ListHandle zonelist, u_char *myzone)
- {
- myzone[0] = num_zones = 0;
- zone_array = (ZONE_NAME *) NewPtr(MAX_ZONES * sizeof(ZONE_NAME ));
- zone_heap = (ZONE_NAME **) NewPtr(MAX_ZONES * sizeof(ZONE_NAME *));
-
- if (zone_array && zone_heap)
- {
- short i;
- SysEnvRec sysenvirons;
- SysEnvirons(1, &sysenvirons);
- if (sysenvirons.atDrvrVersNum < 53) BuildZoneListPhase1(myzone);
- else BuildZoneListPhase2(myzone);
-
- i = num_zones;
- while (--i>=0)
- {
- Point pt = { 0, 0 };
- ZONE_NAME *name = ZL_removefromheap(i);
- pt.v = (*zonelist)->dataBounds.bottom;
- LAddRow(1, pt.v, zonelist);
- LSetCell(&name->c[1], name->c[0], pt, zonelist);
- }
- }
-
- if (zone_array) DisposPtr((Ptr)zone_array);
- if (zone_heap ) DisposPtr((Ptr)zone_heap);
-
- return(num_zones);
- }
-