Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Talker.c
#include <Stdio.h> |
#include <Memory.h> |
#include <Types.h> |
#include <CursorCtl.h> |
#include <AppleTalk.h> |
#include <Packages.h> |
#include <Events.h> |
#include <SysEqu.h> |
#include <Desk.h> |
#include <Devices.h> |
#include <Errors.h> |
#include <Fonts.h> |
#include <Menus.h> |
#include <ToolUtils.h> |
#include <Events.h> |
#include <Resources.h> |
#include <OSEvents.h> |
#include <Scrap.h> |
/* |
© Copyright 1991 Apple Computer, By Ricardo Batista |
This is a quick and dirty application to chat over the network using |
Written by Ricardo Batista. 1/31/91 |
*/ |
#define appleMenu 128 |
#define fileMenu 129 |
#define editMenu 130 |
#define setupMenu 131 |
#define quitItem 1 |
#define undoItem 1 |
#define cutItem 3 |
#define copyItem 4 |
#define pasteItem 5 |
#define clearItem 6 |
#define configureItem 1 |
#define okItem 1 |
#define cancelItem 2 |
#define MAXADDRBLOCKS 100 |
#define LOOKUPBUFSIZE 20000 |
pascal void InitDDPListener(ATDDPRec *ddp); |
pascal void DDPListener(void); |
void DoAbout(void); |
void NewMessage(void); |
void SetMenus(void); |
void AnalizeKeys(void); |
Boolean Working(void); |
Boolean DoCommand(long mResult); |
Boolean HandleMouseDowns(void); |
void Configure(void); |
void ShowStatus(void); |
void CleanUp(void); |
void AdjustTextScrollBar(); |
void Message(char *mess); |
short DoDDP(char *st); |
short DoRegName(void); |
void CleanTalk(void); |
Boolean Setup(void); |
void Names(void); |
short myNBPExtract(char *buffer,int howMany,int which,EntityName *Name,AddrBlock *Addr); |
char ourName[60]; |
EventRecord myEvent; |
Boolean commandK, shiftK, optionK; |
Boolean inFront; |
short err; |
MenuHandle myMenu[5]; |
WindowPtr textWindow = 0L; |
TEHandle textTE = 0L; |
ControlHandle textScrollBar = 0L; |
WindowRecord wRec; |
short mpp = 0, socket = 0; |
NamesTableEntry *NTPtr = 0L; |
MPPParamBlock p; |
ATDDPRec ddp; |
char buffer[1000]; |
AddrBlock *users; |
void main() |
{ |
short err, len; |
char *copyright = {"© 1991 Apple Computer, Inc. By Ricardo Batista"}; |
char st[256]; |
if (!Setup()) |
return; |
err = OpenDriver("\p.MPP",&mpp); |
if (err) { |
Message("\pAppleTalk is not available"); |
return; |
} |
err = DoRegName(); |
Names(); |
BlockMove("\pEntering the network...",st,30L); |
len = ourName[0]; |
BlockMove(&ourName[1], &st[st[0] + 1], (long) len); |
st[0] += len; |
err = DoDDP(st); |
if (err) |
Message("\pError writing to network."); |
while (Working()) |
; |
BlockMove("\pLeaving the network...",st,30L); |
len = ourName[0]; |
BlockMove(&ourName[1], &st[st[0] + 1], (long) len); |
st[0] += len; |
err = DoDDP(st); |
CleanTalk(); |
} |
Boolean Setup(void) |
{ |
short counter; |
Rect box, bounds; |
for (counter = 0; counter < 10; counter++) |
MoreMasters(); |
InitGraf(&qd.thePort); |
InitFonts(); |
InitWindows(); |
TEInit(); |
InitMenus(); |
InitDialogs(0L); |
DrawMenuBar(); |
FlushEvents(everyEvent,0L); |
InitCursor(); |
MaxApplZone(); |
SetCursor(*GetCursor(watchCursor)); |
InitAllPacks(); |
SetMenus(); |
box.top = 40; |
box.left = 10; |
box.right = 500; |
box.bottom = 300; |
textWindow = NewWindow((Ptr) &wRec,&box,"\pNeighborhood Watch by Ricardo Batista",1,documentProc, |
(WindowPtr) -1L,0,0L); |
if (!textWindow) |
return(false); |
SetPort(textWindow); |
TextSize(9); |
TextFont(1); |
box = textWindow->portRect; |
box.left = 5; |
box.bottom -= 16; |
box.right -= 16; |
bounds.top = box.top; |
bounds.left = 5; |
bounds.right = box.right; |
bounds.bottom = 2000; |
textTE = TENew(&bounds,&box); |
if (!textTE) |
return(false); |
box = textWindow->portRect; |
box.top--; |
box.right -= 15; |
bounds.top = box.top; |
bounds.left = box.right; |
bounds.right = bounds.left + 16; |
bounds.bottom = box.bottom - 14; |
textScrollBar = NewControl(textWindow,&bounds,"\p",1,1,1,1,scrollBarProc,(long) textTE); |
BeginUpdate(textWindow); |
EndUpdate(textWindow); |
DrawGrowIcon(textWindow); |
TEActivate(textTE); |
AdjustTextScrollBar(); |
inFront = true; |
ddp.abResult = 1; |
ddp.ddpActCount = 0; |
ddp.ddpReqCount = 586; |
ddp.ddpDataPtr = buffer; |
users = (AddrBlock*) NewPtrClear(sizeof(AddrBlock) * MAXADDRBLOCKS); |
return(true); |
} |
void CleanTalk() |
{ |
if (socket && NTPtr) { |
p.NBPntQElPtr = (Ptr) &(NTPtr->nt.entityData[0]); |
err = PRemoveName(&p,false); |
DisposPtr((Ptr) NTPtr); |
p.DDPsocket = (unsigned char) socket; |
err = PCloseSkt(&p,false); |
if (err) |
Message("\pCould not close socket."); |
} |
if (textWindow) |
CloseWindow(textWindow); |
if (textTE) |
TEDispose(textTE); |
} |
void SetMenus() |
{ |
char appleStr[2]; |
appleStr[0] = 1; |
appleStr[1] = 0x14; |
myMenu[appleMenu - 128] = NewMenu(appleMenu,appleStr); |
myMenu[fileMenu - 128] = NewMenu(fileMenu,"\pFile"); |
myMenu[editMenu - 128] = NewMenu(editMenu,"\pEdit"); |
myMenu[setupMenu - 128] = NewMenu(setupMenu,"\pTalk"); |
AppendMenu(myMenu[appleMenu - 128],"\pAbout Neighborhood Watch...;(-"); |
AddResMenu(myMenu[appleMenu - 128],'DRVR'); |
AppendMenu(myMenu[fileMenu - 128],"\pQuit/Q"); |
AppendMenu(myMenu[editMenu - 128],"\pUndo;(-;Cut/X;Copy/C;Paste/V;Clear"); |
AppendMenu(myMenu[setupMenu - 128],"\pSend A Message/M"); |
InsertMenu(myMenu[appleMenu - 128],0); |
InsertMenu(myMenu[fileMenu - 128],0); |
InsertMenu(myMenu[editMenu - 128],0); |
InsertMenu(myMenu[setupMenu - 128],0); |
DrawMenuBar(); |
} |
short DoRegName() |
{ |
EntityName name; |
short err, len; |
short index; |
StringHandle H; |
H = GetString(-16096); |
if (H) { |
LoadResource((Handle) H); |
HLock((Handle) H); |
BlockMove((Ptr) *H, ourName, 40L); |
HUnlock((Handle) H); |
ReleaseResource((Handle) H); |
} |
else { |
ourName[0] = 1; |
ourName[1] = '?'; |
} |
p.MPPioCompletion = 0L; |
p.MPPioRefNum = mpp; |
p.DDPsocket = 0; |
p.DDPlistener = (Ptr) StripAddress((Ptr) (ProcPtr) DDPListener); |
err = POpenSkt(&p,true); |
while (p.MPPioResult == 1) |
; |
if (err) { |
Message("\pCould not open AppleTalk socket !!!"); |
return(err); |
} |
socket = p.DDPsocket; |
name.zoneStr[0] = 1; |
name.zoneStr[1] = '*'; |
BlockMove("\pNeighborhood Watch",name.typeStr, 20L); |
len = sizeof(NamesTableEntry); |
NTPtr = (NamesTableEntry*) NewPtrClear(len); |
if (!NTPtr) |
return(MemErr); |
NTPtr->nt.nteAddress.aSocket = socket; |
p.NBPinterval = 3; |
p.NBPcount = 3; |
p.NBPverifyFlag = true; |
p.NBPntQElPtr = (Ptr) NTPtr; |
BlockMove(ourName,&(NTPtr->nt.entityData[0]),33L); |
index = ourName[0] + 1; |
BlockMove(name.typeStr,&(NTPtr->nt.entityData[index]),33L); |
index += name.typeStr[0] + 1; |
BlockMove(name.zoneStr,&(NTPtr->nt.entityData[index]),33L); |
err = PRegisterName(&p,true); |
while (p.MPPioResult == 1) |
; |
err = p.MPPioResult; |
while (err == nbpDuplicate) { |
ourName[0]++; |
ourName[ourName[0]] = '1'; |
BlockMove(ourName,&(NTPtr->nt.entityData[0]),33L); |
index = ourName[0] + 1; |
BlockMove(name.typeStr,&(NTPtr->nt.entityData[index]),33L); |
index += name.typeStr[0] + 1; |
BlockMove(name.zoneStr,&(NTPtr->nt.entityData[index]),33L); |
err = PRegisterName(&p,true); |
while (p.MPPioResult == 1) |
; |
err = p.MPPioResult; |
} |
if (err) |
Message("\pCould not register name in network."); |
InitDDPListener(&ddp); |
return(noErr); |
} |
// I tried making network wide broadcasts, but seems like the FX didn't like opening static sockets, |
// there was no problem with the SE30 and Portable, but the FX was a problem... |
short DoDDP(char *st) |
{ |
MPPParamBlock p; |
short err = 0; |
WDSElement wds[4]; |
unsigned char header[20]; |
register short counter; |
wds[2].entryLength = 0; |
wds[2].entryPtr = 0L; |
wds[3].entryLength = 0; |
wds[3].entryPtr = 0L; |
wds[1].entryPtr = st; |
wds[1].entryLength = st[0] + 1; |
p.MPPioResult = 1; |
p.MPPioCompletion = 0L; |
p.MPPioRefNum = mpp; |
p.DDPchecksumFlag = false; |
p.DDPsocket = socket; |
p.DDPwdsPointer = (Ptr) wds; |
wds[0].entryPtr = &header[1]; |
wds[0].entryLength = 16; |
header[16] = 44; // Type; |
for (counter = 0; counter < MAXADDRBLOCKS;) { |
BlockMove((Ptr) &(users[counter].aNet),&header[8],2L); |
header[14] = users[counter].aSocket; // Socket; |
header[12] = users[counter].aNode; // Node |
err = PWriteDDP(&p,true); |
while (p.MPPioResult == 1) |
; |
counter++; |
if (users[counter].aNet == 0) |
counter = MAXADDRBLOCKS + 1; |
} |
if (!err) |
err = p.MPPioResult; |
return(err); |
} |
void UpdateTextWindow() |
{ |
GrafPtr savePort; |
Rect box; |
GetPort(&savePort); |
SetPort(textWindow); |
BeginUpdate(textWindow); |
box = textWindow->portRect; |
TEUpdate(&box,textTE); |
EndUpdate(textWindow); |
DrawGrowIcon(textWindow); |
SetPort(savePort); |
} |
void AnalizeKeys() |
{ |
if (myEvent.modifiers & cmdKey) |
commandK = true; |
else |
commandK = false; |
if (myEvent.modifiers & shiftKey) |
shiftK = true; |
else |
shiftK = false; |
if (myEvent.modifiers & optionKey) |
optionK = true; |
else |
optionK = false; |
} |
Boolean Working() |
{ |
register char theChar; |
register Boolean event; |
WindowPtr w; |
GrafPtr savePort; |
Rect box; |
Point mouse; |
short lines; |
register long counter; |
if (ddp.abResult == 0) { |
Message(buffer); |
ddp.abResult = 1; |
for (counter = 0; counter < MAXADDRBLOCKS; counter++) { |
if ((users[counter].aNet == 0) && (users[counter].aNode == 0)) { |
users[counter] = ddp.ddpAddress; |
counter = MAXADDRBLOCKS + 1; |
Message("\pA new user has been recorded."); |
} |
else { |
if ((ddp.ddpAddress.aNet == users[counter].aNet) && |
(ddp.ddpAddress.aNode == users[counter].aNode)) |
counter = MAXADDRBLOCKS + 1; |
} |
} |
} |
event = GetNextEvent(everyEvent,&myEvent); |
AnalizeKeys(); |
w = FrontWindow(); |
if ((w == textWindow) && inFront && textTE) { |
GetPort(&savePort); |
SetPort(textWindow); |
TEIdle(textTE); |
box = w->portRect; |
GetMouse(&mouse); |
box.right -= 16; |
box.bottom -= 16; |
if (PtInRect(mouse,&box)) |
SetCursor(*(GetCursor(iBeamCursor))); |
else |
InitCursor(); |
SetPort(savePort); |
} |
if (event) { |
switch (myEvent.what) { |
case app4Evt: |
if (myEvent.modifiers & 128) |
inFront = true; |
else |
inFront = false; |
break; |
case activateEvt: |
w = (WindowPtr) myEvent.message; |
if (myEvent.modifiers & activeFlag) { |
if (w == textWindow) |
TEActivate(textTE); |
} |
else { |
if (w == textWindow) |
TEDeactivate(textTE); |
} |
break; |
case keyDown: |
case autoKey: |
theChar = myEvent.message & charCodeMask; |
if (commandK) { |
if (!DoCommand(MenuKey(theChar))) |
return(false); |
} |
else { |
w = FrontWindow(); |
if (w == textWindow) { |
lines = (**textTE).nLines; |
TEKey(theChar,textTE); |
if (lines != (**textTE).nLines) |
AdjustTextScrollBar(); |
} |
} |
break; |
case updateEvt: |
w = (WindowPtr) myEvent.message; |
if (w == textWindow) |
UpdateTextWindow(); |
break; |
case mouseDown: |
if (!HandleMouseDowns()) |
return(false); |
break; |
default: |
break; |
} |
} |
return(true); |
} |
pascal void CtlAction(theControl, part) |
ControlHandle theControl; |
short part; |
{ |
TEHandle TE; |
short newValue, value, v, max; |
TE = (TEHandle) GetCRefCon(theControl); |
max = GetCtlMax(theControl); |
v = (**TE).lineHeight; |
newValue = value = GetCtlValue(theControl); |
if (part == inPageUp) { |
newValue -= 12; |
if (newValue < 1) |
newValue = 1; |
SetCtlValue(theControl,newValue); |
} |
if (part == inPageDown) { |
newValue += 12; |
if (newValue > max) |
newValue = max; |
SetCtlValue(theControl,newValue); |
} |
if (part == inUpButton) { |
newValue--; |
if (newValue < 1) |
newValue = 1; |
SetCtlValue(theControl,newValue); |
} |
if (part == inDownButton) { |
newValue++; |
if (newValue > max) |
newValue = max; |
SetCtlValue(theControl,newValue); |
} |
if (value != newValue) |
TEScroll(0,(value - newValue) * v,TE); |
} |
void HandleMouseInText() |
{ |
short where; |
ControlHandle whichControl; |
short value, oldValue; |
short v; |
Rect box; |
SetPort(textWindow); |
GlobalToLocal(&myEvent.where); |
where = FindControl(myEvent.where,textWindow,&whichControl); |
switch (where) { |
case inUpButton: |
case inDownButton: |
case inPageUp: |
case inPageDown: |
TrackControl(whichControl,myEvent.where,(ProcPtr) CtlAction); |
break; |
case inThumb: |
v = (**(textTE)).lineHeight; |
oldValue = GetCtlValue(whichControl); |
if (TrackControl(whichControl,myEvent.where,0L)) { |
value = GetCtlValue(whichControl); |
if (value != oldValue) { |
TEScroll(0,(oldValue - value) * v,textTE); |
} |
} |
break; |
case 0: |
box = (**(textTE)).viewRect; |
if (PtInRect(myEvent.where,&box)) |
TEClick(myEvent.where,shiftK,textTE); |
break; |
default: |
break; |
} |
} |
void AdjustTextScrollBar() |
{ |
short lines; |
short v; |
short top, bottom; |
lines = (**textTE).nLines; |
v = (**textTE).lineHeight; |
top = (**textTE).viewRect.top; |
bottom = (**textTE).viewRect.bottom; |
bottom -= top + 10; |
lines -= bottom / v; |
if (lines < 1) |
lines = 1; |
if (lines > 1) |
lines++; |
SetCtlMax(textScrollBar,lines); |
if (lines > 1) |
HiliteControl(textScrollBar,0); |
else |
HiliteControl(textScrollBar,255); |
} |
Boolean DoCommand(mResult) |
long mResult; |
{ |
register short theItem; |
char st[250]; |
theItem = LoWord(mResult); |
switch (HiWord(mResult)) { |
case appleMenu: |
GetItem(myMenu[0],theItem,st); |
if (theItem > 2) |
OpenDeskAcc(st); |
else |
DoAbout(); |
break; |
case fileMenu: |
switch (theItem) { |
case quitItem: |
return(false); |
break; |
default: |
break; |
} |
break; |
case editMenu: |
if (!SystemEdit(theItem -1)) { |
switch (theItem) { |
case undoItem: |
break; |
case cutItem: |
if (textTE) { |
TECut(textTE); |
AdjustTextScrollBar(); |
} |
ZeroScrap(); |
TEToScrap(); |
break; |
case copyItem: |
if (textTE) |
TECopy(textTE); |
ZeroScrap(); |
TEToScrap(); |
break; |
case pasteItem: |
TEFromScrap(); |
if (textTE) { |
TEPaste(textTE); |
AdjustTextScrollBar(); |
} |
break; |
case clearItem: |
if (textTE) { |
TEDelete(textTE); |
AdjustTextScrollBar(); |
} |
break; |
default: |
break; |
} |
} |
break; |
case setupMenu: |
if (theItem == configureItem) |
NewMessage(); |
break; |
default: |
break; |
} |
HiliteMenu(0); |
return(true); |
} |
Boolean HandleMouseDowns() |
{ |
WindowPtr whichWindow; |
Rect box; |
long new; |
short v, h; |
switch (FindWindow(myEvent.where,&whichWindow)) { |
case inSysWindow: |
SystemClick(&myEvent,whichWindow); |
break; |
case inMenuBar: |
return(DoCommand(MenuSelect(myEvent.where))); |
break; |
case inGrow: |
SetRect(&box,160,100,600,600); |
new = GrowWindow(whichWindow,myEvent.where,&box); |
if (new) { |
v = HiWord(new); |
h = LoWord(new); |
SetPort(whichWindow); |
SizeWindow(whichWindow,h,v,true); |
EraseRect(&(whichWindow->portRect)); |
InvalRect(&(whichWindow->portRect)); |
if (whichWindow == textWindow) { |
MoveControl(textScrollBar,h - 15,0); |
SizeControl(textScrollBar,16,v - 15); |
HLock((Handle) textTE); |
(**textTE).viewRect.right = h - 15; |
(**textTE).viewRect.bottom = v - 15; |
(**textTE).destRect.right = h - 15; |
HUnlock((Handle) textTE); |
TECalText(textTE); |
AdjustTextScrollBar(); |
} |
} |
break; |
case inGoAway: |
if (!TrackGoAway(whichWindow,myEvent.where)) |
break; |
break; |
case inDrag: |
if (commandK || (FrontWindow() == whichWindow)) |
DragWindow(whichWindow,myEvent.where,&qd.screenBits.bounds); |
else { |
SelectWindow(whichWindow); |
SetPort(whichWindow); |
} |
break; |
case inContent: |
if (whichWindow != FrontWindow()) { |
SelectWindow(whichWindow); |
SetPort(whichWindow); |
} |
else { |
if (whichWindow == textWindow) |
HandleMouseInText(); |
} |
break; |
default: |
break; |
} |
return(true); |
} |
void NewMessage(void) |
{ |
short err; |
char st[256], mess[256]; |
GrafPtr savePort; |
DialogPtr aDialog; |
short item; |
Handle H; |
Rect box; |
DialogRecord d; |
mess[0] = 0; |
BlockMove(ourName, st, 40L); |
st[0]++; |
st[st[0]] = ':'; |
st[0]++; |
st[st[0]] = 'Ê'; |
GetPort(&savePort); |
aDialog = GetNewDialog(128, (Ptr) &d, (WindowPtr) -1L); |
if (aDialog) { |
SetPort(aDialog); |
GetDItem(aDialog, okItem, &item, &H, &box); |
PenSize(3,3); |
InsetRect(&box, -5, -5); |
FrameRoundRect(&box, 16, 16); |
PenNormal(); |
item = 0; |
while ((item != okItem) && (item != cancelItem)) |
ModalDialog(0L, &item); |
if (item == okItem) { |
GetDItem(aDialog, 3, &item, &H, &box); |
GetIText(H, mess); |
item = okItem; |
} |
CloseDialog(aDialog); |
} |
SetPort(savePort); |
if (item == okItem) { |
BlockMove(&mess[1], &st[st[0] + 1], (long) ((short) mess[0])); |
st[0] += mess[0]; |
err = DoDDP(st); |
if (err) |
Message("\pError sending packet. Destination not found."); |
} |
} |
void DoAbout() |
{ |
Message("\pThis is a quick and dirty application by Ricardo Batista."); |
Message("\pAnyone in the network with this same application is able to"); |
Message("\preceive messages by others using this application."); |
Message("\p© Copyright 1991 Apple Computer, Inc. All Rights Reserved."); |
Message("\p"); |
} |
void Message(char *mess) |
{ |
long len; |
GrafPtr savePort; |
char st[40]; |
unsigned long t; |
GetDateTime(&t); |
GetPort(&savePort); |
SetPort(textWindow); |
IUTimeString((long) t, true,st); |
while (st[0] < 14) { |
st[0]++; |
st[st[0]] = ' '; |
} |
len = st[0]; |
TEInsert(&st[1],len,textTE); |
IUDateString((long) t, shortDate ,st); |
while (st[0] < 14) { |
st[0]++; |
st[st[0]] = ' '; |
} |
len = st[0]; |
TEInsert(&st[1],len,textTE); |
len = mess[0]; |
TEInsert(&mess[1],len,textTE); |
TEKey(13,textTE); |
TECalText(textTE); |
AdjustTextScrollBar(); |
SetPort(savePort); |
} |
void Names() |
{ |
EntityName name; |
short err, counter; |
Handle buffer = 0L; |
short found; |
MPPParamBlock p; |
char Entity[110]; |
p.MPPioCompletion = 0L; |
p.MPPioRefNum = mpp; |
buffer = NewHandle(LOOKUPBUFSIZE); |
if (!buffer) { |
return; |
} |
Message("\pFindind Neighbors..."); |
HLock(buffer); |
BlockMove("\pNeighborhood Watch",name.typeStr, 20L); |
name.objStr[0] = 1; |
name.objStr[1] = '='; |
name.zoneStr[0] = 1; |
name.zoneStr[1] = '*'; |
BlockMove(name.objStr,Entity,33L); |
counter = Entity[0] + 1; |
BlockMove(name.typeStr,&Entity[counter],33L); |
counter += name.typeStr[0] + 1; |
BlockMove(name.zoneStr,&Entity[counter],33L); |
p.NBPinterval = 5; |
p.NBPcount = 4; |
p.NBPentityPtr = Entity; |
p.NBPretBuffPtr = *buffer; |
p.NBPretBuffSize = LOOKUPBUFSIZE; |
p.NBPmaxToGet = LOOKUPBUFSIZE / 110; |
p.NBPnumGotten = 0; |
err = PLookupName(&p,false); |
err = p.MPPioResult; |
if (!err) { |
found = p.NBPnumGotten; |
for (counter = 0; counter < found; counter++) |
err = myNBPExtract(*buffer,found,counter + 1,&name, &(users[counter])); |
Message(name.objStr); |
} |
if (buffer) |
DisposHandle(buffer); |
buffer = 0L; |
} |
short myNBPExtract(char *buffer,int howMany,int which,EntityName *Name,AddrBlock *Addr) |
{ |
char *p; |
register int index = 1, nameCounter = 0; |
p = buffer; |
while ((index < which) && (index < howMany)) { |
p += 5; /* skip addr and enumerator */ |
p += (*p) + 1; /* skip name */ |
p += (*p) + 1; /* skip type */ |
p += (*p) + 1; /* skip zone */ |
index++; |
} |
BlockMove(p,(Ptr) Addr,4L); |
p += 5; |
BlockMove(p,Name->objStr,33L); |
p += (*p) + 1; |
BlockMove(p,Name->typeStr,33L); |
p += (*p) + 1; |
BlockMove(p,Name->zoneStr,33L); |
return(0); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14