home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
clintsrc.sit
/
DAdialog.c
< prev
next >
Wrap
Text File
|
1990-05-04
|
28KB
|
1,232 lines
/*========================================================================
=== DAdialog.c
===
=== Greg Anderson
=== 29 Kerr Hall
=== Social Sciences Computing
=== University of California at Santa Cruz
=== Santa Cruz CA 95062
===
=== (408) 459-2658
=== sirkm@ssyx.ucsc.edu
===
=== Dialog box routines.
===
========================================================================*/
#include <types.h>
#include <osutils.h>
#include <memory.h>
#include <devices.h>
#include <events.h>
#include <quickdraw.h>
#include <fonts.h>
#include <windows.h>
#include <files.h>
#include <errors.h>
#include <toolutils.h>
#include <packages.h>
#include <Limits.h>
#include <Controls.h>
#include <TextEdit.h>
#include <Dialogs.h>
#include <Desk.h>
#include <Scrap.h>
#include <Traps.h>
#include <Lists.h>
#include <Menus.h>
#include <Resources.h>
#include "unixDA.h"
#include "DA.h"
/*----------------------------------------------------------------------
| Draw a shaded rectangle. The shaded part hangs outside the
| rectangle by one pixel below and to the right.
----------------------------------------------------------------------*/
ShadedRect( Rect *theRect )
{
PenNormal();
EraseRect( theRect );
FrameRect( theRect );
MoveTo( theRect->left+2, theRect->bottom );
LineTo( theRect->right, theRect->bottom );
LineTo( theRect->right, theRect->top+2 );
}
/*----------------------------------------------------------------------
| Draw the thick rounded rectangle around the default button
----------------------------------------------------------------------*/
drawDefault(dialog)
DialogPtr dialog;
{
short type;
Handle item;
Rect box;
SetPort(dialog);
GetDItem(dialog, 1, &type, &item, &box);
PenSize(3,3);
InsetRect(&box,-4,-4);
FrameRoundRect(&box,18,18);
}
/*----------------------------------------------------------------------
| Draw the pop-up menu icon
----------------------------------------------------------------------*/
pascal void drawPopIcon(DialogPtr dlog,short whichItem)
{
DCtlPtr dCtl;
Handle item;
short type;
Rect box;
Str255 Pstr;
int x;
dCtl = (DCtlPtr)GetWRefCon(dlog);
GetDItem(dlog,whichItem,&type,&item,&box);
ShadedRect(&box);
GetIndString(Pstr, DA_global->rsrcID, ePopMsg);
x = ( (box.right - box.left) - StringWidth(Pstr) ) / 2;
MoveTo( box.left + x , box.top+12 );
DrawString(Pstr);
}
/*----------------------------------------------------------------------
| Draw the scrolling item list
----------------------------------------------------------------------*/
pascal void drawItemList(DialogPtr dlog,short whichItem)
{
DCtlPtr dCtl;
short type;
Handle item;
Rect box;
dCtl = (DCtlPtr)GetWRefCon(dlog);
GetDItem(dlog,whichItem,&type,&item,&box);
ShadedRect(&box);
LUpdate( ((*DA_iList)->port)->visRgn,DA_iList);
}
/*----------------------------------------------------------------------
| Center the dialog box
----------------------------------------------------------------------*/
centerDialog(param)
DialogPtr param;
{
Rect scrRect;
int w,h,x,y;
w = param->portRect.right - param->portRect.left;
h = param->portRect.bottom - param->portRect.top;
getScreenRect(&scrRect);
x = (scrRect.right/2) - (w/2);
y = ( (scrRect.bottom - 16 - h)/2) + 16;
if( y < 16 ) y = 16;
MoveWindow(param,x,y,false);
}
/*----------------------------------------------------------------------
| Set the item handle of a dialog item (particularly useritems
----------------------------------------------------------------------*/
void setItemHandle(DialogPtr dlog, short whichItem, Handle newItem)
{
short type;
Handle item;
Rect box;
GetDItem(dlog,whichItem,&type,&item,&box);
SetDItem(dlog,whichItem,type,newItem,&box);
}
/*----------------------------------------------------------------------
| Put up an alert with some arbitrary message
----------------------------------------------------------------------*/
void alertMsg( DCtlPtr dCtl, char *msg )
{
Str255 Pmsg;
short itemHit;
C2Pstr(Pmsg,msg);
ParamText(Pmsg, Pmsg, Pmsg, Pmsg);
itemHit = Alert(DA_global->rsrcID, nil);
}
/*----------------------------------------------------------------------
| Display an alert that tells the user an error occurred. The error
| number is used to index an 'STR#' resource so that a relevant
| message can be displayed.
----------------------------------------------------------------------*/
void alertUser2( DCtlPtr dCtl, short error1, short error2 )
{
short itemHit;
Str255 msg1,
msg2;
if( DA_global->flag == NOERRORMAGIC ) return;
/* SetCursor(&qd.arrow); */
InitCursor();
/*
* The type 'Str255' is an array in MPW 3
*/
GetIndString(msg2, DA_global->rsrcID, error2);
GetIndString(msg1, DA_global->rsrcID, error1);
ParamText(msg1, msg2, msg1, msg2);
itemHit = Alert(DA_global->rsrcID, nil);
}
/*----------------------------------------------------------------------
| Like alertUser2, but has only one error message.
----------------------------------------------------------------------*/
void alertUser( DCtlPtr dCtl, short error )
{
alertUser2( dCtl, error, eNulString );
}
/*----------------------------------------------------------------------
| Display the HELP dialog box.
----------------------------------------------------------------------*/
void helpDialog( DCtlPtr dCtl )
{
DialogPtr dlog;
short itemHit;
Str255 Pstr;
/*
* Set up the dialog box
*/
dlog = GetNewDialog(DA_global->rsrcID + 2, nil, (WindowPtr)-1L);
SetWRefCon(dlog,(long)dCtl);
setItemHandle(dlog,9,(Handle)drawPopIcon);
SetPort(dlog);
centerDialog(dlog);
ShowWindow(dlog);
SelectWindow(dlog);
DrawDialog(dlog);
drawDefault(dlog);
do
{
ModalDialog( nil, &itemHit);
if( itemHit == 9 )
doPopup( dCtl, dlog, itemHit, Pstr );
} while( itemHit != 1 );
DisposDialog(dlog);
}
/*----------------------------------------------------------------------
| A short delay used when flashing stuff
----------------------------------------------------------------------*/
shortPause()
{
long ticky;
ticky = TickCount() + 10;
while( ticky > TickCount() );
}
/*----------------------------------------------------------------------
| Momentarily hilite a dialog button
----------------------------------------------------------------------*/
FlashDlogItem( DialogPtr dlog, short itemNum )
{
Handle item;
short itemType;
Rect iRect;
GetDItem(dlog,itemNum,&itemType,&item,&iRect);
InsetRect(&iRect,1,1);
InvertRoundRect( &iRect, 8, 8 );
shortPause();
InvertRoundRect( &iRect, 8, 8 );
}
/*
* A list of events returned by the filter:
*/
#define fUndo 1000
#define fCut 1001
#define fCopy 1002
#define fPaste 1003
#define fClear 1004
#define fSelAll 1005
#define fUpArrow 1010
#define fDownArrow 1011
#define fHome 1012
#define fEnd 1013
#define fPgUp 1014
#define fPgDown 1015
/*----------------------------------------------------------------------
| This filter, when passed to ModalDialog, will allow the user to
| cut, copy and paste by pressing command-X, command-C or command-V,
| respectively.
----------------------------------------------------------------------*/
pascal Boolean cutPasteFilter( DialogPtr dlog, EventRecord *theEvent, short *itemHit )
{
Str255 Pstr;
long num;
char key,
code;
short itemType,
itemNum;
Handle item;
Point mouse;
Rect tRect;
/*
* Adjust the cursor to an iBeam or Arrow as appropriate
*/
GetMouse( &mouse );
itemNum = FindDItem(dlog,mouse) + 1;
itemType = statText;
if( itemNum > 0 )
GetDItem(dlog,itemNum,&itemType,&item,&tRect);
if( itemType == editText )
SetCursor(*GetCursor(iBeamCursor));
else
InitCursor();
/*
* We only wish to filter keyDown events.
*/
if( (theEvent->what == keyDown) || (theEvent->what == autoKey) )
{
key = (theEvent->message & charCodeMask);
code = (theEvent->message & keyCodeMask) >> 8;
if( theEvent->modifiers & optionKey )
{
num = code;
NumToString(num, Pstr);
GetDItem(dlog,11,&itemType,&item,&tRect);
SetIText(item,Pstr);
theEvent->what = nullEvent;
return(false);
}
/*
* If ESCAPE was pressed, forge a command-. and continue
* (Note that CLEAR <code 71> also sends an ESCAPE, which isn't what
* we want)
*/
if( (key == 27) && (code != 71) )
{
theEvent->modifiers |= cmdKey;
key = '.';
}
/*
* If F1, F2, F3 or F4 (undo, cut, copy or paste) are pressed, exit
* with the appropriate result code.
*/
switch( code )
{
case 122:
*itemHit = fUndo;
return(true);
case 120:
*itemHit = fCut;
return(true);
case 99:
*itemHit = fCopy;
return(true);
case 118:
*itemHit = fPaste;
return(true);
case 126:
*itemHit = fUpArrow;
return(true);
case 125:
*itemHit = fDownArrow;
return(true);
case 115:
*itemHit = fHome;
return(true);
case 119:
*itemHit = fEnd;
return(true);
case 116:
*itemHit = fPgUp;
return(true);
case 121:
*itemHit = fPgDown;
return(true);
case 114:
*itemHit = 5;
FlashDlogItem( dlog, 5 );
return(true);
default:
break;
GetDItem(dlog,11,&itemType,&item,&tRect);
NumToString((long)code, Pstr);
SetIText(item,Pstr);
}
/*
* Is the command key down?
*/
if( theEvent->modifiers & cmdKey )
{
switch( key )
{
case 'x': *itemHit = fCut;
return(true);
case 'c': *itemHit = fCopy;
return(true);
case 'v': *itemHit = fPaste;
return(true);
case 'z': *itemHit = fUndo;
return(true);
case 'a': *itemHit = fSelAll;
return(true);
case '.': *itemHit = 2;
FlashDlogItem( dlog, 2 );
return(true);
}
theEvent->what = nullEvent;
return(false);
}
/*
* If CLEAR was pressed, return fClear
*/
if( code == 71 )
{
*itemHit = fClear;
return(true);
}
/*
* If RETURN or ENTER was pressed, exit with itemHit = 1.
*/
if( (key == 13) || (key == 3) )
{
*itemHit = 1;
FlashDlogItem( dlog, 1 );
return(true);
}
/*
* Swallow non-printing characters
*/
if( (key < ' ') && (key != 8) && (key != 9) )
{
theEvent->what = nullEvent;
return(false);
}
}
return(false);
}
/*----------------------------------------------------------------------
| Dialog box Special functions
----------------------------------------------------------------------*/
void specialDlog(DCtlPtr dCtl, DialogPtr dlog, int what)
{
DialogRecord *dp = dlog;
TEHandle te;
Cell selectionCell;
int i;
te = dp->textH;
switch( what )
{
case fCut:
case fCopy:
/*
* If there is no selection, do nothing
*/
if( (*te)->selEnd != (*te)->selStart )
{
HiliteEditMenu();
ZeroScrap();
if(what == fCut)
DlgCut( dlog );
else
DlgCopy( dlog );
if( TEToScrap() != noErr )
SysBeep(0);
shortPause();
HiliteMenu(0);
}
break;
case fPaste:
HiliteEditMenu();
if( TEFromScrap() == noErr )
DlgPaste( dlog );
else
SysBeep(0);
shortPause();
HiliteMenu(0);
break;
case fClear:
if( (*te)->selEnd != (*te)->selStart )
DlgDelete( dlog );
break;
case fSelAll:
TESetSelect(0,kMaxTELength,te);
break;
case fUndo:
break;
case fUpArrow:
case fDownArrow:
case fPgUp:
case fPgDown:
case fHome:
case fEnd:
selectionCell.h = 0; selectionCell.v = 0;
if( LGetSelect(true, &selectionCell, DA_iList) )
{
LSetSelect(false,selectionCell,DA_iList);
i = (*(DA_iList))->dataBounds.bottom;
selectionCell.v += (what == fDownArrow)
- (what == fUpArrow)
- (what == fPgUp) * 10
+ (what == fPgDown) * 10;
if(what == fHome) selectionCell.v = 0;
if(what == fEnd) selectionCell.v = i-1;
if(selectionCell.v < 0) selectionCell.v = 0;
if(selectionCell.v >=i) selectionCell.v = i-1;
}
LSetSelect(true,selectionCell,DA_iList);
LAutoScroll(DA_iList);
break;
}
}
/*----------------------------------------------------------------------
| Put up the 'SelectService' dialog box and wait for the user to
| select the service desired.
|
| Returns 'true' if the user clicks 'Okay' and 'false' if the user
| clicks 'Cancel'.
----------------------------------------------------------------------*/
short selectService( DCtlPtr dCtl, long *inet_addr, char *result )
{
DialogPtr dlog;
Handle tmpHandle,
hostHandle;
Point cSize,
clickAt;
Str255 Pstr,
lastHost,
params;
short itemHit,
lastHit = 0,
itemType,
len;
Cell selectionCell;
Rect tRect,
rView,
dataBounds;
int i;
*result = 0;
HiliteMenu(0);
/*
* Set up the dialog box
*/
dlog = GetNewDialog(DA_global->rsrcID, nil, (WindowPtr)-1L);
SetPort(dlog);
centerDialog(dlog);
SetWRefCon(dlog,(long)dCtl);
setItemHandle(dlog,9,(Handle)drawItemList);
setItemHandle(dlog,12,(Handle)drawPopIcon);
/*
* Get the name of the host and set the editable text field in the dialog
*/
hostHandle = GetResource('STR ',DA_global->rsrcID );
pstrcpy(Pstr,*hostHandle);
GetDItem(dlog,7,&itemType,&tmpHandle,&tRect);
SetIText(tmpHandle,Pstr);
do
{
GetDItem(dlog,7,&itemType,&tmpHandle,&tRect);
GetIText(tmpHandle,&lastHost);
/*
* Set up the item list: rView should be the same size as dialog item #9.
*/
GetDItem(dlog,9,&itemType,&tmpHandle,&rView);
InsetRect(&rView,1,1);
rView.right -= 15;
SetRect(&dataBounds,0,0,1,0);
cSize.h = 0; cSize.v = 0;
DA_iList = LNew(&rView,&dataBounds,cSize,(short)0,dlog,true,false,false,true);
lastHit = 0;
/*
* Now show the dialog box & draw a rectangle around the item list
*/
ShowWindow(dlog);
SelectWindow(dlog);
DrawDialog(dlog);
drawDefault(dlog);
/*
* Find all services offered & add them to the scrolling item list.
*/
SetCursor( *GetCursor( watchCursor) );
setupList(dCtl, dlog, inet_addr);
LUpdate( ((*DA_iList)->port)->visRgn,DA_iList);
InitCursor();
selectionCell.h = 0; selectionCell.v = DA_global->lastService;
LSetSelect(true,selectionCell,DA_iList);
LAutoScroll(DA_iList);
do
{
ModalDialog( (ModalFilterProcPtr)cutPasteFilter, &itemHit);
/* ModalDialog( nil, &itemHit); */
/*
* If itemHit >= 1000, then do special handling stuff
*/
if( itemHit >= 1000 )
specialDlog(dCtl, dlog, itemHit );
/*
* Did user click the question mark button?
*/
if( itemHit == 5 )
{
helpDialog( dCtl );
SelectWindow(dlog);
SetPort(dlog);
DrawDialog(dlog);
drawDefault(dlog);
}
/*
* Did user click the popup menu marker?
*/
if( itemHit == 12 )
{
/*
GetDItem(dlog,12,&itemType,&tmpHandle,&tRect);
tRect.bottom += 160;
tRect.right += 160;
*/
i = doPopup( dCtl, dlog, itemHit, Pstr );
/*
udRegion = NewRgn();
RectRgn(udRegion,&tRect);
UpdtDialog(dlog,udRegion);
drawDefault(dlog);
DisposeRgn(udRegion);
*/
if( i > -1 )
{
GetDItem(dlog,7,&itemType,&tmpHandle,&tRect);
SetIText(tmpHandle,Pstr);
itemHit = -1;
}
}
GetDItem(dlog,7,&itemType,&tmpHandle,&tRect);
GetIText(tmpHandle,&Pstr);
/*
* Did the user change the host name field and then move the
* cursor to the 'Parameters' field?
*/
if( ( (itemHit == 3) || (itemHit == 9) ) && pstrcmp(Pstr,lastHost) )
itemHit = -1;
/*
* Check for a double-click on the item list
*/
if( itemHit == 9 )
{
GetMouse(&clickAt);
if( LClick(clickAt,0,DA_iList) )
{
FlashDlogItem( dlog, 1 );
itemHit = 1;
}
}
/*
* If the host name field was touched & the user hit "Okay",
* re-read the service list
*/
if( (itemHit == 1) && pstrcmp( Pstr, lastHost ) )
itemHit = -1;
/*
* Requested a new item list? Ignore if hostname has not changed
*/
if( itemHit == -1 )
{
if( pstrcmp( Pstr,lastHost ) )
{
DA_global->lastService = 0;
LDispose(DA_iList);
}
else
itemHit = 9999;
}
} while( itemHit > 2 );
} while( itemHit < 0 );
selectionCell.h = 0; selectionCell.v = 0;
if( LGetSelect(true, &selectionCell, DA_iList) )
{
/*
| | Get the selection
*/
DA_global->lastService = selectionCell.v;
len = 79;
LGetCell(result,&len,selectionCell,DA_iList);
result[len++] = '\r';
/*
* If it is ever deemed necessary: insert username here
*/
result[len++] = '\r';
result[len] = 0;
/*
| | Get the text from the 'parameters' field
*/
GetDItem(dlog,3,&itemType,&tmpHandle,&rView);
GetIText(tmpHandle,¶ms);
processParams( (char *)params, result+len );
}
LDispose(DA_iList);
DisposDialog(dlog);
if( itemHit == 2 )
CloseDeskAcc( dCtl->dCtlRefNum );
return( itemHit == 1 );
} /* SelectService */
/*----------------------------------------------------------------------
| Set up the list of services offered.
----------------------------------------------------------------------*/
void setupList(DCtlPtr dCtl, DialogPtr dlog, long *inet_addr)
{
#define SBSIZE 1000
Handle item,
knownHosts,
hostHandle;
Str255 Pstr;
OSErr err = noErr;
short m,
itemType;
Rect tRect;
Cell theCell;
char serviceBuf[SBSIZE+4],
msg[80],
*serv,
*line,
hostName[255],
dot_addr[40];
int i,
j,
tries = 0;
DA_global->flag = NOERRORMAGIC;
/*
* Get the name of the host:
*/
GetDItem(dlog,7,&itemType,&item,&tRect);
GetIText(item,&Pstr);
P2Cstr(hostName,Pstr);
/*
* Set the error message text field to the 'looking up inetadr' message
* and clear the internet address field
*/
GetIndString(Pstr,DA_global->rsrcID, eNoServ-1 );
GetDItem(dlog,11,&itemType,&item,&tRect);
SetIText(item,Pstr);
*Pstr = 0;
GetDItem(dlog,8,&itemType,&item,&tRect);
SetIText(item,Pstr);
/*
* Put the name of the host & its inet address into the
* appropriate dialog fields
*/
C2Pstr(Pstr,hostName);
GetDItem(dlog,7,&itemType,&item,&tRect);
SetIText(item,Pstr);
/*
* Look up the internet address of the host
*/
knownHosts = GetResource('STR#',DA_global->rsrcID+1 );
HLock(knownHosts);
checkHostCache( *knownHosts, hostName, inet_addr );
HUnlock(knownHosts);
if( !(*inet_addr) )
err = NameToAddr(hostName,inet_addr,0L);
myAddrToStr(*inet_addr,dot_addr);
C2Pstr(Pstr,dot_addr);
GetDItem(dlog,8,&itemType,&item,&tRect);
SetIText(item,Pstr);
/*
* Set the error message text field to the 'reading service list' message
*/
GetIndString(Pstr,DA_global->rsrcID, eNoServ+1 );
if( !(*inet_addr) ) *Pstr = 0;
GetDItem(dlog,11,&itemType,&item,&tRect);
SetIText(item,Pstr);
if( !(*inet_addr) ) return;
do
{
i=0;
++tries;
/*
* Ask the superserver for a list of services
*/
getCstr(eList,msg,DA_global);
if( (err = MakeTCPStream( dCtl )) != noErr)
continue;
if( (err = ActiveOpen( dCtl, *inet_addr, 3502 )) != noErr )
{
KillTCPStream( dCtl );
continue;
}
/*
* Send the 'LIST' command & read back the response.
*/
if( (err = SendTCP( dCtl, msg )) == noErr )
err = GetUntilClosed( dCtl, serviceBuf, SBSIZE );
KillTCPStream( dCtl );
LDoDraw(false,DA_iList);
theCell.h = 0;
serv = serviceBuf;
findNextLine(&serv);
findNextLine(&serv);
findNextLine(&serv);
/*
* Add all of the service names to the item list
*/
while(*serv)
{
/*
* Find the next service name
*/
line = serv;
findNextLine(&serv);
while( (*line) && (*line != '\t') ) ++line;
if( *line ) line++;
if( !(*line) ) continue;
/*
* Put it into the list in alphabetical order
*/
for(j=0;j<i;++j)
{
m = 80;
theCell.v = j;
LGetCell(msg,&m,theCell,DA_iList);
msg[m] = 0;
if( cistrcmp(msg,line) > 0 )
break;
}
theCell.v = j;
LAddRow(1,j,DA_iList);
LAddToCell(line,strlen(line),theCell,DA_iList);
++i;
}
LDoDraw(true,DA_iList);
} while( (i==0) && (tries<2) );
/*
* If no services were added, put up an error message
*/
m = getTCPErrorStr(err);
if( (m == eBadOpen) || (err == noErr) )
{
getCstr(eNoServ,msg,DA_global);
strcat(msg,hostName);
C2Pstr(Pstr,msg);
}
else
GetIndString(Pstr, DA_global->rsrcID, m );
if( i ) *Pstr = 0;
GetDItem(dlog,11,&itemType,&item,&tRect);
SetIText(item,Pstr);
/*
* If services are offered here, remember the name of the host
* for use in subsiquent lookups.
*/
if( i )
{
addHostToCache( dCtl, hostName, dot_addr, dlog );
hostHandle = GetResource('STR ',DA_global->rsrcID );
ReallocHandle(hostHandle,lstrlen(hostName)+2);
C2Pstr(*hostHandle,hostName);
ChangedResource(hostHandle);
WriteResource(hostHandle);
}
DA_global->flag = 0;
}
/*----------------------------------------------------------------------
| Search the cache & see if the inet_addr of this host is known
----------------------------------------------------------------------*/
char *checkHostCache( char *walk, char *hostName, long *inet_addr )
{
char c,
*begin;
int i,
starting = 1,
hLen;
hLen = strlen(hostName);
*inet_addr = 0;
/*
* Check if the host is in inet addr cache list
*/
walk += 2;
while( *walk )
{
if( starting )
begin = walk;
++walk;
/*
* Only do a string compare if the target string is the
* right length
*/
if( ((c = walk[hLen]) == '=') || (c == ',') || (c == '.') || (c == '\n') )
{
walk[hLen] = 0;
i = strcmp(walk,hostName);
walk[hLen] = c;
/*
* Did we find a match?
*/
if( !i )
{
if( c == '\n')
--walk;
else
while( (*walk) && (*walk != '=') )
++walk;
if( *walk )
myStrToAddr(walk + 1,inet_addr);
return(begin);
}
}
while( (*walk >= ' ') && (*walk != ',') && (*walk != '=') )
++walk;
starting = (*walk < ' ');
if( starting && *walk ) ++walk;
}
return( nil );
}
/*----------------------------------------------------------------------
| Add a host name & its internet address to the cache
----------------------------------------------------------------------*/
void addHostToCache( DCtlPtr dCtl, char *hostName, char *dotAddr, DialogPtr dlog)
{
Handle knownHosts,
newCache;
unsigned char pLen;
char hostEntry[256],
*walk,
*build,
*inCache;
long inet_addr,
tLen;
short tLines = 0,
*lPeek;
int i,
j = 0,
hLen;
hLen = strlen(hostName);
knownHosts = GetResource('STR#',DA_global->rsrcID+1 );
newCache = NewHandle( GetHandleSize(knownHosts) + 256L );
MoveHHi(newCache);
HLock(newCache);
HLock(knownHosts);
/*
* First we want to know if the host is already in the cache.
*/
inCache = checkHostCache( *knownHosts, dotAddr, &inet_addr );
lPeek = (short *)*newCache;
build = *newCache + 2;
walk = *knownHosts + 2;
strcpy(hostEntry,hostName);
straddc(hostEntry,'=');
strcat(hostEntry,dotAddr);
straddc(hostEntry,'\n');
/*
* Copy the new host name entry into the cache
*/
C2Pstr( build, hostEntry );
tLen = lstrlen(hostEntry)+1;
build += tLen;
/*
* Copy the rest of the old cache to the new cache
*/
while( (*walk) && (tLines < 8) )
{
++j;
pLen = pstrlen(walk) + 1;
if( (StripAddress(walk) == StripAddress(inCache)) )
walk += pLen;
else
{
++tLines;
tLen += pLen;
for(i=0;i<pLen;++i)
*build++ = *walk++;
}
}
*build++ = 0;
*build++ = 0;
*lPeek = tLines + 1;
HUnlock(knownHosts);
ReallocHandle(knownHosts,tLen+2);
HLock(knownHosts);
BlockMove(*newCache,*knownHosts,tLen+2);
ChangedResource(knownHosts);
WriteResource(knownHosts);
DisposHandle(newCache);
}
/*----------------------------------------------------------------------
| Find the next line in the service list buffer
----------------------------------------------------------------------*/
void findNextLine(char **str)
{
while( **str )
{
if( ( (**str) == '\n') || ( (**str) == '\r'))
{
**str = 0;
++(*str);
return;
}
++(*str);
}
}
/*----------------------------------------------------------------------
| Process the parameters list.
|
| On entry, parameters are separated by whitespace (space, tab, cr,
| etc.) in a Pascal string. Single or double quotes may be used to
| imbed whitespace inside a parameter. Single quotes may appear inside
| double-quoted strings, and visa-versa. A backslash may preceed
| special characters (quotes, backslashes) to include them in the
| string.
|
| On exit, parameters are concatinated to a C string & separated by
| newlines..
----------------------------------------------------------------------*/
processParams(char *str, char *new)
{
char c,
quote = 0;
int skipwhite = 1,
backslash = 0,
i = *str;
while(i-- > 0)
{
++str;
c = *str;
if( backslash )
{
*new++ = c;
backslash = 0;
skipwhite = 0;
}
else if( c == '\\')
{
backslash = 1;
}
else if( c <= ' ' )
{
if( !skipwhite )
{
if( quote )
*new++ = ' ';
else
{
*new++ = '\r';
skipwhite = 1;
}
}
}
else if( (c == '"') || (c == '\'') )
{
if( c == quote )
quote = 0;
else
quote = c;
skipwhite = 0;
}
else
{
*new++ = c;
skipwhite = 0;
}
}
*new++ = '\r';
if( !skipwhite ) *new++ = '\r';
*new++ = 0;
}
/*----------------------------------------------------------------------
| Return which rectangle the mouse is in. WholeRect contains the
| coordinates of the entire rectangle; inRect is set to the rectangle
| that bounds the line that the mouse it pointing at.
----------------------------------------------------------------------*/
mouseInRect( Rect *wholeRect, Rect *inRect )
{
Point theMouse;
int i;
GetMouse( &theMouse );
i = PtInRect( theMouse, wholeRect );
*inRect = *wholeRect;
InsetRect(inRect,1,1);
theMouse.v -= wholeRect->top;
theMouse.v /= 16;
inRect->top = wholeRect->top + 1 + theMouse.v * 16;
inRect->bottom = inRect->top+15;
if( !i || (inRect->bottom > wholeRect->bottom) )
{
SetRect( inRect,-1,-1,-1,-1);
return( -1 );
}
return(theMouse.v);
}
/*----------------------------------------------------------------------
| Do the popup menu stuff.
----------------------------------------------------------------------*/
int doPopup( DCtlPtr dCtl, DialogPtr dlog, int popItem, Str255 Pstr)
{
RgnHandle udRegion;
Handle knownHosts,
hList,
item;
Rect lastRect,
inRect,
tRect;
char *walk,
*build,
*hNames[maxInCache+2];
short itemType,
tlines = 0,
ilines = 0;
int i,
hLens[maxInCache+2],
mline;
GetDItem(dlog,popItem,&itemType,&item,&tRect);
tRect.bottom += 160;
tRect.right = tRect.left + 176;
knownHosts = GetResource('STR#',DA_global->rsrcID+1 );
hList = NewHandle( GetHandleSize(knownHosts) + 20L );
if( (knownHosts == nil) || (hList == nil) )
{
SysBeep(0);
return(-1);
}
MoveHHi(hList);
HLock(hList);
HLock( knownHosts );
walk = *knownHosts + 2;
build = *hList;
while( (*walk) && (tlines < maxInCache) )
{
hNames[ilines] = build;
hLens[ilines] = 0;
walk++;
while( (*walk) && (*walk != '=') && (*walk != ',') )
{
*build++ = *walk++;
++hLens[ilines];
}
*build++ = 0;
++ilines;
while( *walk >= ' ' )
++walk;
if( *walk )
{
++walk;
++tlines;
}
}
*build++ = 0;
tRect.bottom = tRect.top + tlines * 16 + 1;
SetRect(&lastRect,-1,-1,-1,-1);
ShadedRect(&tRect);
InsetRect(&tRect,1,1);
for(i=0;i<tlines;++i)
{
MoveTo( tRect.left+8, tRect.top + 10 + i*16 );
DrawText( hNames[i], 0, min(hLens[i],18) );
}
InsetRect(&tRect,-1,-1);
while( StillDown() )
{
mline = mouseInRect( &tRect, &inRect );
if( !EqualRect(&inRect, &lastRect) )
{
InvertRect( &lastRect );
InvertRect( &inRect );
lastRect = inRect;
}
}
/*
* If the mouse was inside the popup menu, build a pascal string
*/
if( mline > -1 )
{
C2Pstr(Pstr,hNames[mline]);
/*
walk = hNames[mline];
build = Pstr + 1;
*Pstr = 0;
while( *walk >= ' ' )
{
*build++ = *walk++;
++(*Pstr);
}
*/
}
HUnlock( knownHosts );
DisposHandle( hList );
InsetRect(&tRect,-2,-2);
EraseRect(&tRect);
/*
* Redraw the portion of the dialog that was covered
*/
udRegion = NewRgn();
RectRgn(udRegion,&tRect);
UpdtDialog(dlog,udRegion);
drawDefault(dlog);
DisposeRgn(udRegion);
return( mline );
}