#ifndef lint
static char *SCCSid = "%W%	(NCSA)	%G%";
#endif

/*
 *
 *      Virtual Screen Kernel Macintosh Real Screen Interface
 *                          (rsmac.c)
 *
 *   National Center for Supercomputing Applications
 *      by Gaige B. Paulsen
 *
 *    This file contains the macintosh real screen calls for the NCSA
 *  Virtual Screen Kernel.
 *
 *      RSbell(w)                   - Ring window w's bell
 *      RScursoff(w)                - Turn the cursor off in w
 *      RScurson(w,x,y)             - Turn the cursor on in w at x,y
 *      RSdraw(w,x,y,a,len,ptr)     - Draw @x,y in w string@ptr for length len
 *      RSdelchars(w,x,y,n)         - Delete n chars in w from x,y
 *      RSdellines(w,t,b,n)         - Delete n lines in region t->b in w
 *      RSerase(w,x1,y1,x2,y2)      - Erase from x1,y1 to x2,y2 in w
 *      RSinitall()                 - Initialize the world if necessary
 *      RSinslines(w,t,b,n)         - Insert n lines in region t->b in w
 *      RSinsstring(w,x,y,a,len,ptr)- Insert len chars @x,y in w attrib a
 *      RSsendstring(w,ptr,len)     - Send string @ptr length len from window w
 *		RSbufinfo( w, total,current)- Tells you the total/current lines in buffer
 *		RSdrawsep( w, y1,draw)		- Tells you to draw the line at y1 (0 is erase)
 *		RSmargininfo( w, total, current)	- Tells you total/current columns in VS
 *
 *
 *  Macintosh only Routines:
 *	NI	RSregnconv( *)				- Convert region to rect coords
 *  NI  RSsetwind(w)                - Set the port and vars to window w
 *  NI  RSsetattr(a)                - Set font/text style to a
 *	NI	RSsetConst(w)
 *	ML	RSattach(w,wind)			- Attach the RS (w) to window wind
 *	ML	RSdetach(w)				- Ready window for go-away
 *	ML	RSselect(w,pt,shift)		- Handle selection RS (w) point (pt) and (shift) if held down
 *	ML	RSzoom(window,code,shifted)	- Zoom Box handling
 *	ML	RSsize( window, where)		- Resize handling
 *	IN	RSgetwindow(w)				- Get the WindowPtr for RS (w)
 *	IN	RSfindvwind(wind)			- Find the (RS/VS) # of wind
 *	IN	RSfindscroll( control, n)	- Find which VS the control is in and which control it is
 *  	RSupdate(wind)				- Handle updates on WIND, return 0 if not an RS
 *		RSactivate(w)				- Handle activate events 
 *		RSdeactivate(w)				- Handle deactivate events 
 *		RSGetTextSel(w,table)		- Returns handle to text selection of window w, table->tabs
 *		RSchangefont(w,fnum,fsiz,r)	- Set (w) to font fnum, size fsiz, resize window if (r)
 *		RSgetfont(w, &fnum, &fsiz)	- Get the font size and number into fnum and fsiz
 *		RSnewwindow( wDims, sb, wid, lines
 *			name,wrap,fnum,fsiz,
 *			showit, goaway)			- Returns VS # of newly created text window -
 *									  wDims (dimension),sb(scrollback),wid(width 80/132),
 *                                    lines (# of lines, 24 <> 66),
 *									  name(window), wrap(0/1),fnum,fsiz, showit(vis),goaway(0,1)
 *		RSkillwindow( w)			- Destroys, deallocates, kills window (w)
 *		RSclick(window,where,shift,
 *				option)				- Handle clicks in window (returns false if not RS window)
 *		RShide(w)					- Hide RS (w)
 *		RSshow(w)					- Show RS (w)
 *		RScprompt(w, FilterProc)	- Prompt for colors...FilterProc is for Modal Dialog
 *		RSsetcolor(w,n,r,g,b)		- Set one of the 4 colors of RS (w) to R,G,B
 *		RSgetcolor(w,n,r,g,b)		- Get one of the 4 colors of RS (w) into R,G,B
 *		RSmouseintext(w,myPoint)	- Returns true if Mouse is in text part of current RS window
 *		RSskip(w,on)				- Activate/deactivate drawing in an RS
 *		
 *		IN - Informational
 *		ML - Mid Level
 *		NI - Necessary Internal
 *		   - Suggested calls
 *
 *      Version Date    Notes
 *      ------- ------  ---------------------------------------------------
 *      0.01    861102  Initial coding -GBP
 *      0.25    861106  Added code from screen.c -GBP
 *      0.50    861113  First compiled edition -GBP
 *		2.1		871130	NCSA Telnet 2.1 -GBP
 *		2.2 	880715	NCSA Telnet 2.2 -GBP
 */


#define __ALLNU__
#include <Events.h>
#include <Controls.h>
#include <OSUtils.h>
#include <Dialogs.h>
#include <Quickdraw.h>
#include <Palette.h>
#include <Windows.h>
#include <Menus.h>
#include <Fonts.h>
#include <Memory.h>
#include <stdio.h>
#include <string.h>

typedef
	Rect *RectPtr;

#include "whatami.h"
#include "configrec.h"
#include "maclook.h"
#include "user.h"
#include "vskeys.h"
#include "vsdata.h"
#include "vsinterf.h"

#ifdef MPW
#include "mpw.h"
#include <Picker.h>
#endif

#define NCSA_TELNET

#ifdef NCSA_TELNET
#include "wind.h"
#endif

/*
*  Capable of shifting the text to the right some # of pixels
*/
#define CVO 0
#define CHO -3

#define Fheight RSlocal[w].fheight
#define	Fascent	RSlocal[w].fascent
#define Fwidth RSlocal[w].fwidth
#define	FONT RSlocal[w].fnum
#define FSIZE RSlocal[w].fsiz
#define Fright RSlocal[w].width
#define MAXWINDOWWIDTH (width)*Fwidth+16-CHO
#define MAXWINDOWHEIGHT (lines)*Fheight+16

#define BLOCKCURSOR				0	/* BYU 2.4.11 */
#define UNDERSCORECURSOR		1	/* BYU 2.4.11 */
#define VERTICALCURSOR			2	/* BYU 2.4.11 */

#define Edit		2		/*  Edit Menu's Position */
#define EDcopy		4		/* Edit Menu: Copy */
#define EDcopyt		7		/* Edit Menu: Copy Table */

#define	Fil			1		/*	File Menu's Position */
#define FLprint		12		/* File Menu: Print Selection */
extern MenuHandle myMenus[];


#define putln(x)

extern unsigned char tempspot[];

extern short		/* BYU 2.4.11 - From event.c */
	cursorBlink,	/* BYU 2.4.11 - 0 = noblink, 1 = blink */
	cursorType;		/* BYU 2.4.11 - 0 = block, 1 = underscore, 2 = vertical line */
extern int HasColor;			/* BYU */
extern int VSIcursorvisible();	/* BYU 2.4.12 */
extern int VSvalids();			/* BYU 2.4.12 */

struct RSdata {
	Rect		textrect;	/* Where the text is in the window */
	Rect		cursor;		/* Cursor rectangle */
	GrafPtr		window;		/* Window pointer */
	PaletteHandle	pal;	/* My Palette */
	char		cursorstate,/* BYU 2.4.11 - 0 is invisible, 1 is visible */
				selected;	/* BYU 2.4.11 - text is selected */
	long		last,
				anchor;
	int			topline,
				leftmarg;	/* leftmost visible column position */
	int			rheight,	/* Real window dimensions */
							/* adjusted to not include CHO boundary - TK 12/88 */
				rwidth;
	int			height,
				width;		/* Window Dimensions rounded to the nearest character */
	char		color[6];	/* color scheme for this machine's sessions */
	RGBColor	RGBs[4];	/* RGB Colors for window */
	ControlHandle
		left,		/* The CH for the left margin */
		scroll;		/* The CH for the scroll bar */
	int
		min,		/* Minimum vertical scrollbar value (number of lines in screen buffer and scrollback) */
		max,		/* Maximum vertical scrollbar value */
		current,	/* current vertical scrollbar value */
		lmin,		/* Minimum horizontal scrollbar value (always 0) */
		lmax,		/* Maximum horizontal scrollbar value (number of columns not visible) */
		lcurrent;	/* current horizontal scrollbar value (leftmost visible column) */
	int
		fascent,	/* Font Ascent */
		fnum,		/* Font ID */
		fsiz,		/* Font Size */
		fheight,	/* Font Height/character */
		fwidth,		/* Font Width /character */
		monospaced;	/* Font is monospaced */
	int
		skip;		/* TRUE if we are skipping the output */

	};

typedef struct RSdata RSdata;

extern int scrn,numwindows;
#ifdef NCSA_TELNET
extern WindRec *screens;
#endif NCSA_TELNET
pascal void ScrollProc();

CTabHandle RSctab;
int MaxRS;
long blinktime;					/* BYU 2.4.11 */
RSdata *RSlocal, *RScurrent;
Rect	noConst,
		screenRect,
		RScur;				/* cursor rectangle */
RgnHandle RSuRgn;            /* update region */
int RSw=-1,         /* last window used */
    RSa=0;          /* last attrib used */
int RScolor=1;		/* true if try to use color stuff */
int RScolors[]=
	{ 33,			/* black */
	  30,			/* white */
	  205,			/* red */
	  341,			/* green */
	  409,			/* blue */
	  273,			/* cyan */
	  137,			/* magenta */
	  69			/* yellow */
	  };

void RSinitall
  (
	int max /* max nr windows to allow */
  )
  /* initializes handling of terminal windows. */
  {
    int i;
	extern SysEnvRec theWorld;

	MaxRS = max;
	RSlocal = (RSdata *) NewPtr(MaxRS * sizeof(RSdata));
    for (i = 0; i < MaxRS; RSlocal[i++].window = 0L)
	  {
		RScurrent = RSlocal + i;
		RScurrent->color[0] = 0;			/* Foreground */
		RScurrent->color[1] = 1;			/* Background */
		RScurrent->color[2] = 2;			/* Blink Fore */
		RScurrent->color[3] = 3;			/* Blink Back */
		RScurrent->cursor.top = 0;
		RScurrent->cursor.bottom = 0;
		RScurrent->cursor.left = 0;
		RScurrent->cursor.right = 0;
	  }
    RSuRgn = NewRgn();
    RScur.left = 0;
    RScur.top = 0;
    RScur.bottom = 0;
    RScur.right = 0;
    RSctab = (CTabHandle) NewHandle((long) (sizeof(ColorTable) + 8 * sizeof(CSpecArray)));
	RScolor = theWorld.hasColorQD;
  } /* RSinitall */

int RSTextSelected(int w) {		/* BYU 2.4.11 */
  return(RSlocal[w].selected);	/* BYU 2.4.11 */
}								/* BYU 2.4.11 */

void RSsetConst
  (
	int w
  )
  /* sets "noConst" global to a zero-based rectangle equal in size
	to the specified terminal window. */
  {
	SetRect(&noConst, 0, 0, RSlocal[w].width, RSlocal[w].height);
  } /* RSsetConst */

/****************************************************************************/
/*  Given a window record number, do a SetPort() to the window associated with
*   that window record.
*/
int RSsetwind
  (
	int w
  )
  {
	if ((w < 0) || (w > MaxRS))
		return(-3);
    if (RSw != w)								/* if last window used is different */
	  {
        if (RSlocal[w].window == 0L)
			return(-4);
		RScurrent = RSlocal + w;
        RSw = w;
		RSa = -1; /* attributes will need setting */
		SetPort(RScurrent->window);
		return(1);
	  }
    SetPort(RScurrent->window);
	return(0);
  } /* RSsetwind */

void RSbell
  (
	int w
  )
  /* gives an audible signal associated with the specified window. */
  {
    RSsetwind(w);
	if (FrontWindow() != RScurrent->window)
	  {
	  /* beep and temporarily invert the window contents, so
		the user sees which window is beeping */
	    InvertRect(&RScurrent->window->portRect);
	    SysBeep(8);
	    InvertRect(&RScurrent->window->portRect);
	  }
	else
	  /* window is frontmost--just beep */
		SysBeep(8);
  } /* RSbell */

void RScursblink						/* BYU 2.4.11 */
  (										/* BYU 2.4.11 */
    int w								/* BYU 2.4.11 */
  )										/* BYU 2.4.11 */
  /* Blinks the cursor */				/* BYU 2.4.11 */
  {										/* BYU 2.4.11 */
	GrafPtr oldwindow;					/* BYU 2.4.11 */
	long now = TickCount();				/* BYU 2.4.11 */
	if (now > blinktime) {				/* BYU 2.4.11 */
		if (VSvalids(w) != 0)			/* BYU 2.4.12 */
			return;						/* BYU 2.4.12 */
		if (!VSIcursorvisible())		/* BYU 2.4.12 */
			return;						/* BYU 2.4.12 - cursor isn't visible */
		GetPort(&oldwindow);			/* BYU 2.4.11 */
		blinktime = now + 40;			/* BYU 2.4.11 */
		RSlocal[w].cursorstate ^= 1; 	/* BYU 2.4.11 */
		SetPort(RSlocal[w].window);		/* BYU 2.4.11 */
		InvertRect(&RSlocal[w].cursor);	/* BYU 2.4.11 */
		SetPort(oldwindow);				/* BYU 2.4.11 */
	}									/* BYU 2.4.11 */
  } /* RScursblink */					/* BYU 2.4.11 */

void RScursblinkon						/* BYU 2.4.18 */
  (										/* BYU 2.4.18 */
    int w								/* BYU 2.4.18 */
  )										/* BYU 2.4.18 */
  /* Blinks the cursor */				/* BYU 2.4.18 */
  {										/* BYU 2.4.18 */
  	if (!RSlocal[w].cursorstate) {		/* BYU 2.4.18 */
		GrafPtr oldwindow;				/* BYU 2.4.18 */
		GetPort(&oldwindow);			/* BYU 2.4.18 */
		RSlocal[w].cursorstate = 1; 	/* BYU 2.4.18 */
		SetPort(RSlocal[w].window);		/* BYU 2.4.18 */
		InvertRect(&RSlocal[w].cursor);	/* BYU 2.4.18 */
		SetPort(oldwindow);				/* BYU 2.4.18 */
	}									/* BYU 2.4.18 */
  } /* RScursblink */					/* BYU 2.4.18 */

void RScursblinkoff						/* BYU 2.4.11 */
  (										/* BYU 2.4.11 */
    int w								/* BYU 2.4.11 */
  )										/* BYU 2.4.11 */
  /* Blinks the cursor */				/* BYU 2.4.11 */
  {										/* BYU 2.4.11 */
  	if (RSlocal[w].cursorstate) {		/* BYU 2.4.11 */
		GrafPtr oldwindow;				/* BYU 2.4.11 */
		GetPort(&oldwindow);			/* BYU 2.4.11 */
		RSlocal[w].cursorstate = 0; 	/* BYU 2.4.11 */
		SetPort(RSlocal[w].window);		/* BYU 2.4.11 */
		InvertRect(&RSlocal[w].cursor);	/* BYU 2.4.11 */
		SetPort(oldwindow);				/* BYU 2.4.11 */
	}									/* BYU 2.4.11 */
  } /* RScursblink */					/* BYU 2.4.11 */

void RScursoff
  (
	int w
  )
  /* hides the text cursor for the specified window. Assumes it
	is currently being shown. */
  {
	if (RSlocal[w].skip || !RSlocal[w].cursorstate)		/* BYU 2.4.11 */
		return;
    RSsetwind(w);
    RScurrent->cursorstate = 0;							/* BYU 2.4.11 */
	InvertRect(&RScurrent->cursor);
  } /* RScursoff */

void RScurson
  (
	int w,
	int x,
	int y
  )
  /* displays the text cursor for the specified window, at the
	specified position. Assumes it isn't currently being shown. */
  {
	if (RSlocal[w].skip || RSlocal[w].cursorstate)		/* BYU 2.4.11 */
		return;
    RSsetwind(w);

    RScurrent->cursor.left = x * RScurrent->fwidth;			/* BYU 2.4.11 */
    RScurrent->cursor.top  = y * RScurrent->fheight;		/* BYU 2.4.11 */

	switch (cursorType) {											/* BYU 2.4.11 */
		case UNDERSCORECURSOR:										/* BYU 2.4.11 */
    		RScurrent->cursor.top  += RScurrent->fheight;			/* BYU 2.4.11 */
    		RScurrent->cursor.right  = RScurrent->cursor.left + RScurrent->fwidth;	/* BYU 2.4.11 */
    		RScurrent->cursor.bottom = RScurrent->cursor.top + 1;	/* BYU 2.4.11 */
			break;
		case VERTICALCURSOR:										/* BYU 2.4.11 */
    		RScurrent->cursor.left += 2;							/* BYU 2.4.11 */
    		RScurrent->cursor.right  = RScurrent->cursor.left + 1;	/* BYU 2.4.11 */
    		RScurrent->cursor.bottom = RScurrent->cursor.top + RScurrent->fheight;	/* BYU 2.4.11 */
			break;
		case BLOCKCURSOR:											/* BYU 2.4.11 */
		default:													/* BYU 2.4.11 */
    		RScurrent->cursor.right  = RScurrent->cursor.left + RScurrent->fwidth;	/* BYU 2.4.11 */
    		RScurrent->cursor.bottom = RScurrent->cursor.top + RScurrent->fheight;	/* BYU 2.4.11 */
			break;
    }

	if (!cursorBlink) {									/* BYU 2.4.11 */
    	RScurrent->cursorstate = 1;						/* BYU 2.4.11 */
    	InvertRect(&RScurrent->cursor);					/* BYU 2.4.11 */
	}													/* BYU 2.4.11 */
  } /* RScurson */

void RSTextFont(myfnum,myfsiz,myface) 	/* BYU */
int myfnum,myfsiz,myface; 				/* BYU */
{										/* BYU */
	if ((myfnum == monaco) && 			/* BYU - If Monaco, size 9, and bold, then */
		(myfsiz == 9) &&				/* BYU */
		(myface & bold))	{			/* BYU */
		TextFont(75);					/* BYU - use NCSA's Monaco. */
	} else {							/* BYU */
		TextFont(myfnum);				/* BYU */
	}									/* BYU */
}										/* BYU */

void RSsetattr
  (
	int a
  )
  /* sets the text attributes for drawing into the current window. */
  {
    if (VSisgrph(a))
        TextFont(74); /* use "NCSA VT" font for special graphics */
	else
#if 1													/* BYU */
		RSTextFont(RScurrent->fnum,RScurrent->fsiz,a); 	/* BYU - use user-selected text font */
#else
		TextFont(RScurrent->fnum); /* use user-selected text font */
#endif
	TextSize(RScurrent->fsiz);

/* Jim@BYU - bold system fonts don't work (they overwrite the scroll bars), 
         but NCSA's 9 point Monaco bold works okay. */

    TextFace((a & outline) >> 1); 	/* Jim@BYU - do outline as underline setting */


#if 0									/* BYU - experimental */
#if 1									/* BYU */
	if ((RScurrent->fnum == monaco) && 	/* BYU */
		(RScurrent->fsiz == 9))			/* BYU */
    	TextFace((a & outline) >> 1); 	/* BYU - do outline as underline setting */
	else								/* BYU */
    	TextFace((a & outline) >> 1);	/* BYU - bold + outline as underline settings */
#else
    TextFace((a & bold) + (a & outline) /2); /* BYU - bold + outline as underline settings */
#endif
#endif



  /* set up reverse video setting */
	if (RScolor)
	  {
		if (VSisrev(a))
			TextMode(notSrcCopy);
		else
			TextMode(srcCopy);
	  }
	else
	  {
		if (VSisrev(a))
		  {
        	BackPat(qd.black);	/* Reverses current attributes regard */
        	PenPat(qd.white);	/* less of the color, etc.... */
          }
		else
		  {
        	BackPat(qd.white);
        	PenPat(qd.black);
          } /* if */
	  } /* if */
  /* use colors to stand in for blink setting */
	if (VSisblnk(a))
	  {
		if (RScolor)
		  {
			PmForeColor(2);
			PmBackColor(3);
		  }
		else
		  {
			ForeColor((long) RScolors[RScurrent->color[2]]);	/* Blink foreground */
			BackColor((long) RScolors[RScurrent->color[3]]);	/* Blink Background */
		  } /* if */
	  }
	else
	  {
		if (RScolor)
		  {
			PmForeColor(0);
			PmBackColor(1);
		  }
		else
		  {
			ForeColor((long) RScolors[RScurrent->color[0]]);	/* normal foreground */
			BackColor((long) RScolors[RScurrent->color[1]]);	/* normal Background */
		  } /* if */
	  } /* if */
    RSa = a;
  } /* RSsetattr */

void HiliteMode(void)
  /* enables use of highlighting in place of simple color inversion
	for next QuickDraw operation. */
  {
	char *p = (char *) 0x938; /* pointer to HiliteMode low-memory global */
	*p = *p & 0x7f; /* clear the HiliteBit */
  } /* HiliteMode */

void RSinvText
  (
	int w, 
	Point curr,
	Point last,
	RectPtr constrain /* don't highlight anything outside this rectangle */
  )
  /* highlights the text from curr to last inclusive. */
  {
	Rect temp, temp2;
	Point lb, ub;

	RSsetwind(w);
  /* normalize coordinates with respect to visible area of virtual screen */
	curr.v -= RScurrent->topline;
	curr.h -= RScurrent->leftmarg;
	last.v -= RScurrent->topline;
	last.h -= RScurrent->leftmarg;

	if (curr.v == last.v)
	  {
	  /* highlighted text all on one line */
		if (curr.h < last.h) /* get bounds the right way round */
		  {
			ub = curr;
			lb = last;
		  }
		else
		  {
			ub = last;
			lb = curr;
		  } /* if */
		SetRect /* set up rectangle bounding area to be highlighted */
		  (
			&temp,
			(ub.h + 1) * RScurrent->fwidth,
			ub.v * RScurrent->fheight,
			(lb.h + 1) * RScurrent->fwidth,
			(lb.v + 1) * RScurrent->fheight
		  );
		SectRect(&temp, constrain, &temp2); /* clip to constraint rectangle */
		HiliteMode();
		InvertRect(&temp2);
	  }
	else
	  {
	  /* highlighting across more than one line */
		if (curr.v < last.v)
			ub = curr;
		else
			ub = last;
		if (curr.v > last.v)
			lb = curr;
		else
			lb = last;
		SetRect /* bounds of first (possibly partial) line to be highlighted */
		  (
			&temp,
			(ub.h + 1) * RScurrent->fwidth,
			ub.v * RScurrent->fheight,
			RScurrent->width,
			(ub.v + 1) * RScurrent->fheight
		  );
		SectRect(&temp, constrain, &temp2); /* clip to constraint rectangle */
		HiliteMode();
		InvertRect(&temp2);
		SetRect /* bounds of last (possibly partial) line to be highlighted */
		  (
			&temp,
			0,
			lb.v * RScurrent->fheight,
			(lb.h + 1) * RScurrent->fwidth,
			(lb.v + 1) * RScurrent->fheight
		  );
		SectRect(&temp, constrain, &temp2); /* clip to constraint rectangle */
		HiliteMode();
		InvertRect(&temp2);
		if (lb.v - ub.v > 1) /* highlight extends across more than two lines */
		  {
		  /* highlight complete in-between lines */
			SetRect
			  (
				&temp,
				0,
				(ub.v + 1) * RScurrent->fheight,
				RScurrent->width,
				lb.v * RScurrent->fheight
			  );
			SectRect(&temp, constrain, &temp2); /* clip to constraint rectangle */
			HiliteMode();
			InvertRect(&temp2);
		  } /* if */
	  } /* if */
  } /* RSinvText */

void RSdraw
  (
	int w, /* window number */
	int x, /* starting column */
	int y, /* line on which to draw */
	int a, /* text attributes */
	int len, /* length of text to draw */
	char *ptr /* pointer to text */
  )
  /* draws a piece of text (assumed to fit on a single line) in a window,
	using the specified attributes. If any part of the text falls
	within the current selection, it will be highlighted. */
  {
    Rect rect;
	static char temp[128];
	int ys;
	static int theLen;

	if (RSlocal[w].skip)
		return;
    RSsetwind(w);
    RSsetattr(0);
    SetRect /* set up rectangle bounding text being drawn */
	  (
		&rect,
		x * RScurrent->fwidth,
		y * RScurrent->fheight,
		(x + len) * RScurrent->fwidth,
		(y + 1) * RScurrent->fheight
	  );
    if (RSa != a)
		RSsetattr(a);
	if (x <= 0)			/* BYU 2.4.12 - Without this, 1 pixel column of reverse */
	  rect.left = -3;	/* BYU 2.4.12 - video text does not clear at left margin */
#ifdef OLDM
	if (!RScolor)
#endif OLDM
	    EraseRect(&rect);
	if (x <= 0)			/* BYU 2.4.12 - Okay, just putting it back the way it was */
	  rect.left = 0;	/* BYU 2.4.12 */
	ys = y * RScurrent->fheight + RScurrent->fascent;
	    MoveTo(x * RScurrent->fwidth, ys);
	strncpy(temp,ptr,len);
	temp[len]=0;
	theLen = StringWidth(temp);
	
#ifdef NEWTXT
	    DrawText(ptr, 0, len);
		
#else
	if (RScurrent->monospaced)
	    DrawText(ptr, 0, len);
	else
		while (len--)
		  {
		  /* draw the characters one at a time to defeat the proportional spacing */
			DrawChar(*ptr++);
			MoveTo((++x) * RScurrent->fwidth, ys);  /*good version */
/*			MoveTo((++x) * CharWidth(*(ptr-1)), ys); */
		  } /* while */
#endif
	if (RScurrent->selected)
		RSinvText(w, *(Point *) &RScurrent->anchor,
			*(Point *) &RScurrent->last, &rect);
  } /* RSdraw */

void RSdelcols
  (
	int w,
	int n /* number of columns to scroll */
  )
  /* scrolls the entire visible display of a virtual screen the
	specified number of columns to the left, blanking out
	the newly-revealed area. */
  {
    Rect rect;

	if (RSlocal[w].skip)
		return;
    RSsetwind(w);
    SetRect /* bounds of entire text area, for scrolling */
	  (
		&rect,
		0,
		0,
		RScurrent->width,
		RScurrent->height
	  );
    ScrollRect(&rect, -n * RScurrent->fwidth, 0, RSuRgn);
    InvalRgn(RSuRgn);
    ValidRect(&rect); /* any necessary redrawing in newly-revealed area will be done by caller */
    SetRect /* bounds of newly-revealed area */
	  (
		&rect,
		RScurrent->width - (n * RScurrent->fwidth),
		0,
		RScurrent->width,
		RScurrent->height
	  );
	if (RScurrent->selected)
	  /* highlight any newly-revealed part of the current selection */
		RSinvText(w, *(Point *) &RScurrent->anchor,
			*(Point *) &RScurrent->last, &rect);
  } /* RSdelcols */

void RSdelchars
  (
	int w, /* affected window */
	int x, /* column to delete from */
	int y, /* line on which to do deletion */
	int n /* number of characters to delete */
  )
  /* deletes the specified number of characters from the specified
	position to the right, moving the remainder of the line to the
	left. */
  {
    Rect rect;

	if (RSlocal[w].skip)
		return;
    RSsetwind(w);
    RSsetattr(0); /* avoid funny pen modes */
    SetRect /* bounds of area from starting column to end of line */
	  (
		&rect,
		x * RScurrent->fwidth,
		y * RScurrent->fheight,
		RScurrent->width,
		(y + 1) * RScurrent->fheight
	  );
	if ((x + n) * RScurrent->fwidth > RScurrent->width)
	  /* deleting to end of line */
		EraseRect(&rect);
	else
	  {
	  /* scroll remainder of line to the left */
    	ScrollRect(&rect, - RScurrent->fwidth * n, 0, RSuRgn);
    	InvalRgn(RSuRgn);
   		ValidRect(&rect); /* leave newly-revealed area blank */
		if (RScurrent->selected)
		  {
		  /* highlight any part of selection which lies in newly-blanked area */
			HLock((Handle) RSuRgn);
			RSinvText(w, *(Point *) &RScurrent->anchor, *(Point *) &RScurrent->last, &((*RSuRgn)->rgnBBox));
			HUnlock((Handle) RSuRgn);
		  } /* if */
	  } /* if */
  } /* RSdelchars */

void RSdellines
  (
	int w, /* affected window */
	int t, /* top line of affected region */
	int b, /* bottom line of affected region */
	int n, /* number of lines to delete */
	int scrolled
	  /*
		-ve => cancel current selection, if any;
		+ve => selection has moved up one line;
		0 => don't touch selection
	  */
  )
  /* deletes lines at the top of the specified region of a window,
	inserting new blank lines at the bottom, and scrolling up the
	stuff in between. */
  {
    Rect rect;

	if (RSlocal[w].skip)
		return;
    RSsetwind(w);
	RSsetConst(w);
    RSsetattr(0); /* avoid funny pen modes */
	if (scrolled)
	  {
		if (RScurrent->selected && scrolled < 0)
		  {
		  /* unhighlight and cancel current selection */
			RSinvText(w, *(Point *) &RScurrent->anchor, *(Point *) &RScurrent->last, &noConst);
			RScurrent->selected = 0;
		  }
		else
		  {
			RScurrent->last -= 65536;		/* Subtract one from each of the */
			RScurrent->anchor -= 65536;		/* Selection components */
		  } /* if */
	  } /* if */

    rect.left = -1;							/* BYU 2.4.12 - necessary */
    rect.right = RScurrent->width;
    rect.top = t * RScurrent->fheight;
    rect.bottom = (b + 1) * RScurrent->fheight;
  /* adjust the update region to track the scrolled window contents */
	OffsetRgn(((WindowPeek) RScurrent->window)->updateRgn,
		0, - RScurrent->fheight * n);
    ScrollRect(&rect, 0, - RScurrent->fheight * n, RSuRgn);
    RSsetattr(VSIw->attrib); /* restore mode for text drawing */
    InvalRgn(RSuRgn);
  /* validate the area containing the newly-inserted blank lines. */
  /* any necessary redrawing in newly-revealed area will be done by caller */
	SetRect
	  (
		&rect,
		0,
		(b - n + 1) * RScurrent->fheight - 1,
		Fright,
		(b + 1) * RScurrent->fheight + 1
	  );
    ValidRect(&rect);
  } /* RSdellines */

void RSerase
  (
	int w, /* affected window */
	int x1, /* left column */
	int y1, /* top line */
	int x2, /* right column */
	int y2 /* bottom line */
  )
  /* erases a rectangular portion of the screen display, preserving
	the selection highlight. */
  {
    Rect rect;

	if (RSlocal[w].skip)
		return;
    RSsetwind(w);
    RSsetattr(0); /* avoid funny pen modes */
    SetRect
	  (
		&rect,
		x1 * RScurrent->fwidth,
		y1 * RScurrent->fheight,
		(x2 + 1) * RScurrent->fwidth - 1,
		(y2 + 1) * RScurrent->fheight + 1
	  );
	if (rect.left <= 0)						/* little buffer strip on left */
		rect.left = CHO;
	if (rect.right >= RScurrent->width - 1)
		rect.right = RScurrent->rwidth - 2;	/* clear to edge of window, including edge strip */
	if (rect.bottom >= RScurrent->height - 2)
		rect.bottom = RScurrent->rheight + 1;	/* clear to bottom edge also */
    EraseRect(&rect);
	if (RScurrent->selected)
	  /* highlight any part of the selection within the cleared area */
		RSinvText(w, *(Point *) &RScurrent->anchor, *(Point *) &RScurrent->last, &rect);
  } /* RSerase */

void RSinslines
  (
	int w, /* affected window */
	int t, /* where to insert blank lines */
	int b, /* bottom of area to scroll */
	int n, /* number of lines to insert */
	int scrolled /* -ve <=> cancel current selection, if any */
  )
  /* inserts blank lines at the top of the given area of the display,
	scrolling the rest of it down. */
  {
    Rect rect;

	if (RSlocal[w].skip)
		return;
    RSsetwind(w);
	RSsetConst(w);
    RSsetattr(0); /* avoid funny pen modes */
	if (RScurrent->selected && (scrolled < 0))
	  {
	  /* unhighlight and cancel selection */
		RSinvText(w, *(Point *) &RScurrent->anchor,
			*(Point *) &RScurrent->last, &noConst);
		RScurrent->selected = 0;
	  } /* if */
	rect.left = -1;						/* BYU 2.4.12 - necessary */
    rect.right = RScurrent->width;
    rect.top = t * RScurrent->fheight;
    rect.bottom = (b + 1) * RScurrent->fheight;
  /* adjust the update region to track the scrolled window contents */
	OffsetRgn(((WindowPeek) RScurrent->window)->updateRgn,
		0, RScurrent->fheight * n);
    ScrollRect(&rect, 0, RScurrent->fheight * n, RSuRgn);
    InvalRgn(RSuRgn);
  /* newly-inserted area is already blank -- validate it to avoid redrawing. */
  /* any necessary redrawing will be done by caller */
	SetRect(&rect, 0, t * RScurrent->fheight - 1,
		RScurrent->width, (t + n) * RScurrent->fheight + 1);
    ValidRect(&rect);
  } /* RSinslines */

void RSinscols
  (
	int w,
	int n /* number of columns to insert */
  )
  /* inserts blank columns at the left side of the text display in
	the specified window, scrolling its current contents to the right.
	Maintains the selection highlight, but doesn't move the selection.
	Doesn't even unhighlight text which moves out of the selection area. */
  {
    Rect rect;

	if (RSlocal[w].skip)
		return;
    RSsetwind(w);
    SetRect /* bounds of entire text area */
	  (
		&rect,
		0,
		0,
		RScurrent->width,
		RScurrent->height
	  );
    ScrollRect(&rect, n * RScurrent->fwidth, 0, RSuRgn);
    InvalRgn(RSuRgn);
    ValidRect(&rect); /* any necessary redrawing in newly-revealed area will be done by caller */
    SetRect /* bounds of newly-inserted blank area */
	  (
		&rect,
		0,
		0,
		(n + 1) * RScurrent->fwidth - 1,
		RScurrent->height
	  );
	if (RScurrent->selected)
	  /* highlight any part of the selection in the newly-blanked area */
		RSinvText(w, *(Point *) &RScurrent->anchor, *(Point *) &RScurrent->last, &rect);
  } /* RSinscols */

void RSinsstring
  (
	int w, /* affected window */
	int x, /* starting column at which to insert */
	int y, /* line on which to insert */
	int a, /* attributes for inserted text */
	int len, /* length of inserted text */
	char *ptr /* pointer to inserted text */
  )
  /* inserts a string of characters at the specified position, scrolling
	the rest of the line to the right. Highlights any part of the newly-
	inserted text lying within the current selection. */
  {
    Rect rect;

	if (RSlocal[w].skip)
		return;
    RSsetwind(w);
    SetRect /* bounds of part of line from specified position to end of line */
	  (
		&rect,
		x * RScurrent->fwidth,
		y * RScurrent->fheight,
		RScurrent->width,
		(y + 1) * RScurrent->fheight
	  );
    ScrollRect(&rect, len * RScurrent->fwidth, 0, RSuRgn); /* scroll remainder of line to the right */
    if (RSa != a)
		RSsetattr(a);
    InvalRgn(RSuRgn);
    ValidRect(&rect); /* any necessary redrawing in newly-revealed area will be done by caller */
    SetRect /* bounds area to contain inserted string */
	  (
		&rect,
		x * RScurrent->fwidth,
		y * RScurrent->fheight,
		(x + len) * RScurrent->fwidth,
		(y + 1) * RScurrent->fheight
	  );
    EraseRect(&rect); /* erase area to appropriate background */
    MoveTo
	  (
		x * RScurrent->fwidth,
		y * RScurrent->fheight + RScurrent->fascent
	  );
    DrawText(ptr, 0, len);
	if (RScurrent->selected)
	  /* highlight any part of selection covering the newly-inserted text */
		RSinvText(w, *(Point *) &RScurrent->anchor,
			*(Point *) &RScurrent->last, &rect);
  } /* RSinsstring */

void RSsendstring
  (
	int w, /* which terminal window */
	char *ptr, /* pointer to data */
	int len /* length of data */
  )
  /* sends some data to the host along the connection associated
	with the specified window. */
  {
#ifdef NCSA_TELNET
	int temp;

	temp = findbyVS(w);
	if (temp < 0)
		return;
/*	if (!screens[scrn].lmflag)	*/
		netwrite(screens[temp].port, ptr, len);
		netpush(screens[temp].port);				/* BYU 2.4.18 - for Diab systems? */
/*	else 
		{
		sprintf(screens[scrn].kbbuf,"%s",ptr);
		screens[scrn].kblen += len;
		if (screens[scrn].echo) parse(&screens[scrn],ptr,len);
		}*/
		
#else
	while (len--)
		putu(*ptr++);
#endif
  } /* RSsendstring */

void RSmargininfo
  (
	int w,
	int total, /* number of invisible character positions (screen width less visible width) */
	int current /* leftmost visible character position */
  )
  /* updates the horizontal scroll bar and associated variables
	to reflect the current view of the virtual screen within the
	specified window. */
  {
	RSlocal[w].leftmarg = current;			/* Adjust local vars */
	if (RSlocal[w].lcurrent != current)
		SetCtlValue(RSlocal[w].left, (RSlocal[w].lcurrent = current));
	if (RSlocal[w].lmax != total)
		SetCtlMax(RSlocal[w].left, (RSlocal[w].lmax = total));
  } /* RSmargininfo */

void RSbufinfo
  (
	int w, /* affected window */
	int total, /* number of lines of scrollback */
	int current, /* current topmost visible line */
	int bottom /* current bottommost visible line */
  )
  /* readjusts the vertical scroll bar and associated variables
	to reflect the current view of the virtual screen within the
	specified window. */
  {
	RSdata *RSthis;
	int newmax;

	RSthis = RSlocal + w;
	RSthis->topline = current;			/* Adjust local vars */
	if (RSthis->min != -total)
	  {
		SetCtlMin(RSthis->scroll, (RSthis->min = -total));
		SetCtlValue(RSthis->scroll, (RSthis->current = current));
	  } /* if */
	if (RSthis->current != current)
		SetCtlValue(RSthis->scroll, (RSthis->current = current));
	newmax = (VSgetlines(w) - 1) - (bottom - current);
	if (RSthis->max != newmax)
	  {
		SetCtlMax(RSthis->scroll, (RSthis->max = newmax));
		SetCtlValue(RSthis->scroll, (RSthis->current = current));
	  } /* if */
  } /* RSbufinfo */

GrafPtr RSgetwindow
  (
	int w
  )
  /* returns a pointer to the Mac window structure for the
	specified terminal window. */
  {
    return(RSlocal[w].window);
  } /* RSgetwindow */

void RSattach
  (
	int w,
	GrafPtr wind
  )
  /* attaches the specified window to a virtual screen, for
	use for displaying that screen. */
  {
    RSlocal[w].window = wind;
    RSlocal[w].selected = 0;
	RScurrent->cursorstate = 0;	/* BYU 2.4.11 - cursor off */
    SetPort(wind);
#if 1								/* BYU */
    RSTextFont(FONT,FSIZE,0);			/* BYU */
#else
    TextFont(FONT);
#endif

    TextSize(FSIZE);
	if (!RScolor)
		TextMode(srcXor);			/* Xor mode*/
	else
		TextMode(srcCopy);
	RSw = -1;	/* make sure we don't write in wrong place */
  } /* RSattach */

void RSdetach
  (
	int w
  )
  /* detaches the window for the specified virtual screen. */
  {
    RSlocal[w].window = 0L;
	RSw = -1;	/* make sure we don't write in wrong place */
  } /* RSdetach */

int RSfindvwind
  (
	GrafPtr wind
  )
  /* returns the number of the virtual screen associated with
	the specified window, or -4 if not found. */
  {
    int
		i = 0;
    while ((RSlocal[i].window != wind) && (i < MaxRS))
		i++;
    if ((RSlocal[i].window == 0L) || (i >= MaxRS))
		return(-4);
	else
		return(i);
  } /* RSfindvwind */

int RSfindscroll				/* Find screen index by control*/
  (
	ControlHandle control,
	int *n
  )
  /* finds the window to which the given scroll bar belongs.
	Returns the window number in *n if found, and a function
	result of 1 for a vertical scroll bar, 2 for a horizontal
	one, or -1 if the window wasn't found. */
  {
  /* look for a vertical scroll bar */
	*n = 0;
	while ((*n < MaxRS) && (control != RSlocal[*n].scroll))
		(*n)++;
	if (*n < MaxRS)
		return (1); /* found it */
  /* look for a horizontal scroll bar */
	*n = 0;
	while ((*n < MaxRS) && (control != RSlocal[*n].left))
		(*n)++;
	if (*n < MaxRS)
		return (2); /* found it */
	return(-1); /* not found */
  } /* RSfindscroll */

void RSregnconv
  (
	RgnHandle regn,
	int *x1, /* left (output) */
	int *y1, /* top (output) */
	int *x2, /* right (output) */
	int *y2, /* bottom (output) */
	int fh, /* font character height */
	int fw /* font character width */
  )
  /* converts the bounding box of the specified QuickDraw region
	into units of character positions (using the specified character
	height and width) and returns the results in *x1, *y1, *x2 and *y2. */
  {
    HLock((Handle) regn);
    *y1 = ((*regn)->rgnBBox.top) / fh;
    *y2 = (((*regn)->rgnBBox.bottom) + fh - 1) / fh;
    *x1 = ((*regn)->rgnBBox.left) / fw;
    *x2 = (((*regn)->rgnBBox.right) + fw - 1) / fw;
    HUnlock((Handle) regn);
	if (*x1 < 0)
		*x1 = 0;
	if (*y1 < 0)
		*y1 = 0;
	if (*x2 < 0)
		*x2 = 0;
	if (*y2 < 0)
		*y2 = 0;
#ifdef WHONEEDSIT
    if (*x1> VSIw->maxwidth)
		*x1 = VSIw->maxwidth;
    if (*x2 > VSIw->maxwidth)
		*x2 = VSIw->maxwidth;
    if (*y1 > VSIw->lines)
		*y1 = VSIw->lines;
    if (*y2 > VSIw->lines)
		*y2 = VSIw->lines;
#endif WHONEEDSIT
  } /* RSregnconv */

int RSupdate
  (
	GrafPtr wind
  )
  /* does updating for the specified window, if it's one of mine.
	Returns zero iff it is. */
  {
    int w, x1, x2, y1, y2;

    w = RSfindvwind(wind);
    if (RSsetwind(w) < 0)
		return(-1); /* not one of mine */
    BeginUpdate(wind);
	RSregnconv /* find bounds of text area needing updating */
	  (
		wind->visRgn,
		&x1, &y1, &x2, &y2,
		RScurrent->fheight, RScurrent->fwidth
	  );
	VSredraw(w, x1, y1, x2, y2); /* draw that text */
  /* We must reset, less we risk looking UGLY as sin... */
	BackPat(qd.white);
	PenPat(qd.black);
	if (RScolor)
	  {
		PmForeColor(0);
		PmBackColor(1);
	  }
	else
	  {
		ForeColor((long) RScolors[ RScurrent->color[0]]);		/* normal foreground */
		BackColor((long) RScolors[ RScurrent->color[1]]);		/* normal Background */
	  } /* if */
    RSa = -1;
	PenMode(patOr);
	DrawGrowIcon(wind);
	PenMode(patCopy);
	DrawControls(wind);
    EndUpdate(wind);
	return(0);
  } /* RSupdate */

#ifdef FASTERCOMMENTED

RSupdprint(wind)
	WindowPeek wind;
  /* debugging routine: displays bounds (in character units) of
	update region of specified window. */
  {
	int x, y, z, w;
	char tbuf[50];

	RSregnconv(wind->updateRgn, &x, &y, &z, &w);
	sprintf(tbuf, "RSregnconv: %d,%d,%d,%d", x, y, z, w);
	putln(tbuf);
  } /* RSupdprint */

#endif

long getlocalmouse(wind)
	GrafPtr wind;
  /* returns the current mouse position in coordinates local
	to the specified window. Leaves the current grafPort set
	to that window. */
  {
	Point temp;

	SetPort(wind);
	GetMouse(&temp);
	return(*((long *) &temp));
  } /* getlocalmouse */

#define	Fwidthhalf	Fwidth/2

long normalize(in, w)
	Point in;
	int  w;
  /* converts in from a pixel position in local coordinates to
	a character cell position within the virtual screen corresponding
	to the specified window. Constrains the position to lie within
	the currently-visible region of the screen, autoscrolling the
	screen if necessary. */
  {
	if (in.v <0)
	  {
		in.v = 0;
		VSscrolback(w, 1);
	  } /* if */
	if (in.v > RSlocal[w].height)
	  {
		in.v = RSlocal[w].height;
		VSscrolforward(w, 1);
	  } /* if */
	in.v = in.v / Fheight;

	if (in.h < 0)
	  {
		in.h = -1;
		VSscrolleft(w, 1);
	  } /* if */
	if (in.h > RSlocal[w].width)
	  {
		in.h = RSlocal[w].width;
		VSscrolright(w, 1);
	  } /* if */
  /* in.h = (in.h + Fwidthhalf) / Fwidth - 1; */
  /* the MPW C 3.0 compiler has a bug in its register allocation */
  /* which keeps the above line from working. So, replace it with this: */
	in.h = in.h + Fwidthhalf;
	in.h = in.h / Fwidth - 1;
  /* note the bug has been fixed in the 3.1 compiler. */
  /* convert to virtual screen coordinates */
	in.v += RSlocal[w].topline;
	in.h += RSlocal[w].leftmarg;
	return(*((long *) &in));
  } /* normalize */

void RSselect
  (
	int w,
	long *pt, /* mouse-down position in local coordinates */
	short shift /* shift key is down (extend existing selection) or not */
  )
  /* called on a mouse-down in the text display area of the
	active window. Creates or extends the highlighted selection
	within that window, autoscrolling as appropriate if the user
	drags outside the currently visible part of the display. */
  {
	GrafPtr tempwndo;
	long curr;

	RSsetConst(w);
	tempwndo = RSlocal[w].window;
	if (RSlocal[w].selected)
	  {
		if (!shift)
		  {
		  /* unhighlight current selection */
			RSinvText(w, *(Point *) &RSlocal[ w].anchor,
				*(Point *) &RSlocal[w].last, &noConst);
		  /* start new selection */
			curr = RSlocal[w].last = RSlocal[w].anchor = normalize(*pt, w);
			RSlocal[w].selected = 1;
		  } /* if */
	  }
	else
	  {
	  /* start new selection */
		curr = RSlocal[w].anchor = RSlocal[w].last = normalize(*pt, w);
		RSlocal[w].selected = 1;
	  }
	while (StillDown())
	  {
	  /* wait for mouse position to change */
		while
		  (((curr = normalize(getlocalmouse(tempwndo), w)) == RSlocal[w].last)
			&& StillDown());

	  /* toggle highlight state of text between current and last mouse positions */
		RSinvText(w, *(Point *) &curr, *(Point *) &RSlocal[w].last, &noConst);
		RSlocal[w].last = curr;
	  } /* while */

	if  ( RSlocal[w].anchor == curr || RSlocal[w].anchor == RSlocal[w].last )
		{
		RSlocal[w].selected = 0; /* null selection */
		DisableItem(myMenus[Fil],FLprint);
		DisableItem(myMenus[Edit],EDcopy);
		DisableItem(myMenus[Edit],EDcopyt);
		}

	if (RSlocal[w].selected)	  
		{
		EnableItem(myMenus[Fil],FLprint);
		EnableItem(myMenus[Edit],EDcopy);
		EnableItem(myMenus[Edit],EDcopyt);
		}
  } /* RSselect */

void RSactivate
  (
	int w
  )
  /* handles an activate event for the specified window. */
  {
	RSsetConst(w);
  /* display the grow icon */
	DrawGrowIcon(RSlocal[w].window);
  /* and activate the scroll bars */
	if (RSlocal[w].scroll != 0L)
		HiliteControl(RSlocal[w].scroll, 0);
	if (RSlocal[w].left != 0L)
		HiliteControl(RSlocal[w].left, 0);
  } /* RSactivate */

void RSdeactivate
  (
	int w
  )
  /* handles a deactivate event for the specified window. */
  {
	RSsetConst(w);
  /* update the appearance of the grow icon */
	DrawGrowIcon(RSlocal[w].window); 
  /* and deactivate the scroll bars */
	if (RSlocal[w].scroll != 0L)
		HiliteControl(RSlocal[w].scroll, 255);
	if (RSlocal[w].left != 0L)
		HiliteControl(RSlocal[w].left, 255);
  } /* RSdeactivate */

char **RSGetTextSel
  (
	int w, /* window to look at */
	int table /* nonzero for "table" mode, i e
		replace this many (or more) spaces with a single tab. */
  )
  /* returns the contents of the current selection as a handle,
	or nil if there is no selection. */
  {
	char **charh, *charp;
	int maxwid;
	long realsiz, VSgettext();
	char tempc[100];
	Point Anchor,Last;

	putln("In the routine");
	if (!RSlocal[w].selected)
		return(0L);	/* No Selection */
	maxwid = VSmaxwidth(w);
	Anchor = *((Point *) &RSlocal[w].anchor);
	Last = *((Point *) &RSlocal[w].last);
	realsiz = Anchor.v - Last.v;
	if (realsiz < 0)
		realsiz = - realsiz;
	realsiz ++;								/* lines 2,3 selected can be 2 lines */
	realsiz *= (maxwid + 2);
	sprintf(tempc, "Size of block=%d", realsiz);
	putln(tempc);
	charh = NewHandle(realsiz);
	if (charh == 0L)
		return((char **) -1L);				/* Boo Boo return */
	HLock(charh);
	charp = *charh;
	realsiz = VSgettext(w, Anchor.h, Anchor.v, Last.h, Last.v,
		charp, realsiz, "\015", table);
	putln("unlocking");
	HUnlock(charh);
	SetHandleSize(charh, realsiz);
	sprintf(tempc, "Size of clip=%d", realsiz);
	putln(tempc);
	return(charh);
  }  /* RSGetTextSel */

void RSsetsize
  (
	int w,
	int v,
	int h
  )
  /* saves the new size settings for a window, and repositions
	the scroll bars accordingly. */
  {
	RSlocal[w].height = ((v - 16 + CVO) / Fheight) * Fheight;
	RSlocal[w].width = ((h - 16 + CHO) / Fwidth) * Fwidth;
	RSlocal[w].rheight = v - 16;
	RSlocal[w].rwidth = h - 16;

/*
*  Get rid of the scroll bars which were in the old size.
*  Hiding them causes the region to be updated later.
*/
	if (RSlocal[w].scroll != NULL )
		HideControl(RSlocal[w].scroll);
	if (RSlocal[w].left != NULL ) 
		HideControl(RSlocal[w].left);

	DrawGrowIcon(RSlocal[w].window);			/* Draw in the necessary bugger */

  /* move the scroll bars to their new positions and sizes,
	and redisplay them */	
	if (RSlocal[w].scroll != NULL )
	  {
		SizeControl(RSlocal[w].scroll, 16, (v - 13));
		MoveControl(RSlocal[w].scroll, (h - 15) + CHO, -1 + CVO);
		ShowControl(RSlocal[w].scroll);
	  } /* if */
	if (RSlocal[w].left != NULL )
	  {
		SizeControl(RSlocal[w].left, (h - 13), 16);
		MoveControl(RSlocal[w].left, -1 + CHO,  (v - 15) + CVO);
		ShowControl(RSlocal[w].left);
	  } /* if */
	SetRect(&RSlocal[w].textrect, 0, 0, RSlocal[w].rwidth, RSlocal[w].rheight);
  } /* RSsetsize */

void RSdrawsep
  (
	int w,
	int y1,
	int draw /* 1 to draw the line, 0 to erase the existing line */
  )
  /* draws a dotted line separating the screen contents from the
	scrollback area. This is currently conditionally compiled to
	be a no-op. */
  {
#ifdef SEPLINE
    RSsetwind(w);
	PenPat(gray);
	if (draw)
		PenMode(srcCopy);
	else
		PenMode(srcXor);
	MoveTo(0, y1 * RScurrent->fheight);
	Line(RSlocal[w].width-1, 0);
	PenMode(srcOr);
	RSsetattr(0);
#else
#pragma unused(w, y1, draw)
#endif SEPLINE
  } /* RSdrawsep */

void RSfontmetrics
  (
	void
  )
  /* calculates various metrics for drawing text with selected font
	and size in current grafport into *RScurrent. */
  {
	FontInfo finforec;
	GrafPtr myGP;
 
	GetPort(&myGP); 
	GetFontInfo(&finforec);
	RScurrent->fascent = finforec.ascent;
	RScurrent->fheight = finforec.ascent + finforec.descent + finforec.leading /* +1 */;
	RScurrent->monospaced = (CharWidth('W') == CharWidth('i'));   
/*	RScurrent->monospaced = (CharWidth('W') == CharWidth('i') == CharWidth(' '));  */

	if (RScurrent->monospaced)
		RScurrent->fwidth = CharWidth('W'); 
	else 
		RScurrent->fwidth = finforec.widMax;
  }

void RSchangefont
  (
	int w,
	int fnum, /* new font ID or -1 for no change */
	int fsiz, /* new font size or 0 for no change */
	int resizwind /* should I resize window to keep same number of visible lines & cols */
  )
  {
	Rect pRect;
	int x1, x2, y1, y2, width, lines;
	int srw,srh;
	WStateData *wstate;
	WindowPeek wpeek;

    RSsetwind(w);
	srw = RScurrent->rwidth;
	srh = RScurrent->rheight;

	if (fnum != -1)
	  {
#if 1								/* thanx to Jim@BYU */
		RSTextFont(fnum,fsiz,0);	/* thanx to Jim@BYU */
#else
		TextFont(fnum);
#endif
		RScurrent->fnum = fnum;
	  } /* if */
	if (fsiz)
	  {
		TextSize(fsiz);
		RScurrent->fsiz = fsiz;
	  } /* if */
	RSfontmetrics();

	width = VSmaxwidth(w) + 1;
	lines = VSgetlines(w);
	if (!resizwind)
	  {
	  /* round window size to new character cell dimensions */
		RScurrent->height =
			((RScurrent->rheight) / RScurrent->fheight) * RScurrent->fheight;
		RScurrent->width =
			((RScurrent->rwidth + CHO) / RScurrent->fwidth ) * RScurrent->fwidth
				- CHO;
	  }
	else
	  {
	  /* resize window to preserve its dimensions in character cell units */
		VSgetrgn(w, &x1, &y1, &x2, &y2);
		RScurrent->rwidth =
			RScurrent->width = (x2 - x1 + 1) * RScurrent->fwidth - CHO;
		RScurrent->rheight =
			RScurrent->height= (y2 - y1 + 1) * RScurrent->fheight;
	  } /* if */

	if (RScurrent->rwidth > MAXWINDOWWIDTH - 16 - CHO)
	 	 RScurrent->rwidth = MAXWINDOWWIDTH - 16 - CHO;
	if (RScurrent->rheight > MAXWINDOWHEIGHT - 16)
	 	 RScurrent->rheight = MAXWINDOWHEIGHT - 16;
	
	SizeWindow
	  (
		RScurrent->window,
		RScurrent->rwidth + 16, RScurrent->rheight+16,
		FALSE
	  ); /*  TRUE if done right */
	RSsetsize(w, RScurrent->rheight + 16, RScurrent->rwidth + 16);

	wpeek = (WindowPeek) RScurrent->window;

	HLock(wpeek->dataHandle);
	wstate = (WStateData *) *wpeek->dataHandle;

	movmem(&wstate->stdState, &pRect, 8);
	pRect.right = pRect.left + MAXWINDOWWIDTH;
	if (pRect.right > screenRect.right)
		pRect.right = screenRect.right;
	pRect.bottom = pRect.top + MAXWINDOWHEIGHT;
	movmem(&pRect, &wstate->stdState, 8);

	VSgetrgn(w, &x1, &y1, &x2, &y2);
	VSsetrgn(w, x1, y1,
		(int) (x1 + (RScurrent->rwidth ) / RScurrent->fwidth - 1),
		(int) (y1 + (RScurrent->rheight) / RScurrent->fheight - 1));
	VSgetrgn(w, &x1, &y1, &x2, &y2);		/* Get new region */
	
	DrawGrowIcon(RScurrent->window);
	VSredraw(w, 0, 0, x2 - x1 + 1, y2 - y1 + 1); /* redraw newly-revealed area, if any */
	ValidRect(&RScurrent->window->portRect); /* no need to do it again */
	DrawControls(RScurrent->window);
  } /* RSchangefont */

int RSgetfont
  (
	int w, /* which window */
	int *pfnum, /* where to return font ID */
	int *pfsiz /* where to return font size */
  )
  /* returns the current font ID and size setting for the specified window. */
  {
/*
*  Bug fix.  RSsetwind's error conditions are all < 0.  There is a success condition == 1.
*  TK 12/17/88
*/
    if (0 > RSsetwind(w))
		return -1;
	*pfnum = RScurrent->fnum;
	*pfsiz = RScurrent->fsiz;
	return(0);
  } /* RSgetfont */

int RSnewwindow
  (
	RectPtr wDims, /* window bounds in pixels */
	int scrollback, /* number of lines to save off top */
	int width, /* number of characters per text line (80 or 132) */
	int lines, /* number of text lines */
	char *name, /* window name */
	int wrapon, /* autowrap on by default */
	int fnum, /* ID of font to use initially */
	int fsiz, /* size of font to use initially */
	int showit, /* window initially visible or not */
	int goaway, /* NCSA 2.5 */
	int forcesave		/* NCSA 2.5: force screen save */
  )
  /* creates a virtual screen and a window to display it in. */
  {
	GrafPort gp; /* temp port for getting text parameters */
	int w;

	Rect pRect;
	int wheight, wwidth;
	long VSwhereis();
	WStateData *wstate;
	WindowPeek wpeek;

  /* create the virtual screen */
	w = VSnewscreen(scrollback, (scrollback != 0), /* NCSA 2.5 */
		width,1, forcesave);	/* NCSA 2.5 */
	if (w < 0)
	  {
		putln("Couldn't open Virtual Screen");
		return(-1);
	  }
	RScurrent = RSlocal + w;

	RScurrent->fnum = fnum;
	RScurrent->fsiz = fsiz;

	OpenPort(&gp);
#if 1							/* thanx to Jim@BYU */
	RSTextFont(fnum,fsiz,0);	/* thanx to Jim@BYU */
#else
	TextFont(fnum);
#endif
	TextSize(fsiz);
	RSfontmetrics();
	ClosePort(&gp);

	if ((wDims->right - wDims->left) > MAXWINDOWWIDTH)
		wDims->right = wDims->left + MAXWINDOWWIDTH;
	if ((wDims->bottom - wDims->top) > MAXWINDOWHEIGHT)
		wDims->bottom = wDims->top + MAXWINDOWHEIGHT;
	wwidth = wDims->right - wDims->left;
	wheight = wDims->bottom - wDims->top;

  /* create the window */
	if (!RScolor)
		RScurrent->window = newwindow(0L, wDims, name, showit?TRUE:FALSE, 8,
			(WindowPtr) -1L,goaway?TRUE:FALSE, (long)w);
	else
	  {
		RScurrent->window = newcwindow(0L, wDims, name, showit?TRUE:FALSE, 8,
			(WindowPtr) -1L, goaway?TRUE:FALSE, (long)w);
					/* the screen is not there until we can see it..... */
		HLock((Handle) RSctab);
		(*RSctab)->ctSize = 4;
		RScurrent->RGBs[0].red  =(*RSctab)->ctTable[0].rgb.red		=     0;
		RScurrent->RGBs[0].green=(*RSctab)->ctTable[0].rgb.green	=     0;
		RScurrent->RGBs[0].blue =(*RSctab)->ctTable[0].rgb.blue		=     0;
		RScurrent->RGBs[1].red  =(*RSctab)->ctTable[1].rgb.red		= 65535;
		RScurrent->RGBs[1].green=(*RSctab)->ctTable[1].rgb.green	= 65535;
		RScurrent->RGBs[1].blue =(*RSctab)->ctTable[1].rgb.blue		= 65535;
		RScurrent->RGBs[2].red  =(*RSctab)->ctTable[2].rgb.red		=     0;
		RScurrent->RGBs[2].green=(*RSctab)->ctTable[2].rgb.green	= 61183;
		RScurrent->RGBs[2].blue =(*RSctab)->ctTable[2].rgb.blue		= 11060;
		RScurrent->RGBs[3].red  =(*RSctab)->ctTable[3].rgb.red		= 61183;
		RScurrent->RGBs[3].green=(*RSctab)->ctTable[3].rgb.green	=  2079;
		RScurrent->RGBs[3].blue =(*RSctab)->ctTable[3].rgb.blue		=  4938;
		HUnlock((Handle) RSctab);

		RScurrent->pal = NewPalette(4, RSctab, pmCourteous, 0);
		SetPalette(RScurrent->window, RScurrent->pal, TRUE);
	  } /* if */

	if (RScurrent->window == 0L)
	  {
		printf("Couldn't open Real Window");
		return(-2);
	  }

	SetPort(RScurrent->window);
	SetOrigin(CHO, CVO);			/* Cheap way to correct left margin problem */

	wpeek = (WindowPeek) RScurrent->window;

	HLock(wpeek->dataHandle);
	wstate = (WStateData *) *wpeek->dataHandle;

	movmem(wDims, &wstate->userState, 8);
	pRect.top = wDims->top;
	pRect.left = wDims->left;
	pRect.right = pRect.left + MAXWINDOWWIDTH;
	if (pRect.right > screenRect.right)
		pRect.right = screenRect.right;

	pRect.bottom = pRect.top + MAXWINDOWHEIGHT;
	movmem(&pRect, &wstate->stdState, 8);

  /* create scroll bars for window */
	pRect.top = -1 + CVO;
	pRect.bottom = wheight - 14 + CVO;
	pRect.left = wwidth - 15 + CHO;
	pRect.right = wwidth + CHO;
	RScurrent->scroll = newcontrol(RScurrent->window, &pRect, "", FALSE,
		0, 0, 0, 16, 1L);
	if (RScurrent->scroll == 0L)
	  {
		printf("Couldn't Make Vertical Scroll Bar");
		return(-3);
	  }

	pRect.top = wheight - 15 + CVO;
	pRect.bottom = wheight + CVO;
	pRect.left = -1 + CHO;
	pRect.right = wwidth - 14 + CHO;
	RScurrent->left = newcontrol(RScurrent->window, &pRect, "", FALSE,
		0, 0, 0, 16, 1L);
	if (RScurrent->left == 0L)
	  {
		printf("Couldn't Make Horizontal Scroll Bar");
		return(-3);
	  }

	RScurrent->skip = 0; /* not skipping output initially */
	RScurrent->max = 0; /* scroll bar settings will be properly initialized by subsequent call to VSsetrgn */
	RScurrent->min = 0;
	RScurrent->current = 0;
	RScurrent->lmax = 0;
	RScurrent->lmin = 0;
	RScurrent->lcurrent = 0;
	RScurrent->selected = 0; /* no selection initially */
	RScurrent->cursorstate = 0;	/* BYU 2.4.11 - cursor off initially */

	RSsetsize(w, wheight, wwidth);
	VSsetlines(w, lines);
	VSsetrgn(w, 0, 0, ((wwidth - 16 + CHO) / Fwidth -1),
		((wheight - 16 + CVO) / Fheight - 1));

#if 1								/* thankx to Jim@BYU */
	RSTextFont(RScurrent->fnum,0);	/* thankx to Jim@BYU */
#else
	TextFont(RScurrent->fnum);
#endif
	TextSize(RScurrent->fsiz);				/* 9 point*/
	if (!RScolor)
		TextMode(srcXor);			/* Xor mode*/
	else
		TextMode(srcCopy);

	if (wrapon)
	  /* turn on autowrap */
		VSwrite(w, "\033[?7h",5);

	return(w);
  } /* RSnewwindow */

void RSkillwindow
  (
	int w
  )
  /* closes a terminal window. */
  {
	VSdetach(w);		/* Detach the virtual screen */
	KillControls(RSlocal[w].window);  /* Get rid of those little slidy things */
	DisposeWindow(RSlocal[w].window);	/* Get rid of the actual window */
	RSdetach(w);		/* Detach from the table */
  }

void RSzoom
  (
	GrafPtr window, /* window to zoom */
	int code, /* inZoomIn or inZoomOut */
	int shifted /* bring to front or not */
  )
  /* called after a click in the zoom box, to zoom a terminal window. */
  {
	int w;
	int h, v, x1, x2, y1, y2;

	SetPort(window);
  /* EraseRect(&window->portRect); */
	ZoomWindow(window, code, shifted);
    EraseRect(&window->portRect);			/* BYU 2.4.15 */

  /* get new window size */
	h = window->portRect.right - window->portRect.left;
	v = window->portRect.bottom - window->portRect.top;

	w = RSfindvwind(window); /* which window is it, anyway */
	RSsetsize(w, v, h); /* save new size settings and update scroll bars */
  /* update the visible region of the virtual screen */
	VSgetrgn(w, &x1, &y1, &x2, &y2);
	VSsetrgn(w, x1, y1, (x1 + (h - 16 + CHO) / Fwidth -1),
		(y1 + (v - 16 + CVO) / Fheight - 1));
	VSgetrgn(w, &x1, &y1, &x2, &y2);		/* Get new region */
  /* refresh the part which has been revealed, if any */
	VSredraw(w, 0, 0, x2 - x1 + 1, y2 - y1 + 1); 
  /* window contents are now completely valid */
	ValidRect(&window->portRect);
  } /* RSzoom */

/*
*  This routine is called when the user presses the grow icon, or when the size of
*  the window needs to be adjusted (where==NULL, modifiers==0).
*  It limits the size of the window to a legal range.
*/

void RSsize
  (
	GrafPtr window,
	long *where,
	int modifiers
  )
  {
	Rect SizRect;
	long size;
	int w, width, lines;
	int tw, h, v, x1, x2, y1, y2, th;

	if ((w = RSfindvwind(window)) < 0)
		return;
	if (modifiers & cmdKey)
		return ;		/* don't allow command-grow */
	
	SetPort(window);

	width = VSmaxwidth(w) + 1;
	lines = VSgetlines(w);
	tw = MAXWINDOWWIDTH; /* don't allow window to be wider than virtual screen */
#ifdef LIMIT_WIDTH
	if (tw > screenRect.right)
		tw = screenRect.right - window->portRect.left - CHO;
#endif	LIMIT_WIDTH
	if (modifiers & optionKey)
	  /* changing size of virtual screen */
		th = screenRect.bottom;
	else
	  /* don't allow window to be taller than virtual screen */
		th = MAXWINDOWHEIGHT + 1;
	SetRect(&SizRect, 48, 48, tw + 1, th);
	
	if (where)
	  {							/* grow icon actions */
		size = growwindow(window, (Point *) where, &SizRect);
		if (size != 0L)
		  {
			SizeWindow(window, size & 0xffff, (size >> 16) & 0xffff, FALSE);
			h = window->portRect.right - window->portRect.left;
			v = window->portRect.bottom - window->portRect.top;
		  }
		else
			return;							/* user skipped growing */
	  }
	else
	  {									/* just resize the window */
		h = window->portRect.right - window->portRect.left;	/* same width */
		v = (Fheight) * VSgetlines(w) + 16;					/* new height */
		SizeWindow(window, h, v, FALSE);					/* change it */
	  } /* if */
	RSsetsize(w, v, h); /* save new size settings and update scroll bars */
  /* update the visible region of the virtual screen */
	VSgetrgn(w, &x1, &y1, &x2, &y2);
	VSsetrgn(w, x1, y1, (x1 + (h - 16 + CHO) / Fwidth - 1),
		(y1 + (v - 16) / Fheight - 1));
	VSgetrgn(w, &x1, &y1, &x2, &y2);		/* Get new region */
	if (modifiers & optionKey)
		VSsetlines(w, y2 - y1 + 1); /* change height of virtual screen */
  /* refresh the part which has been revealed, if any */
	VSredraw(w, 0, 0, x2 - x1 + 1, y2 - y1 + 1);
  /* window contents are now completely valid */
	ValidRect(&window->portRect);
	return;
  } /* RSsize */

int RSclick
  (
	GrafPtr window, /* which window */
	long *where, /* position in global coordinates */
	int shifted, /* shift key was down */
	int optioned /* option key was down */
  )
  /* handles a click in a terminal window. */
  {
	ControlHandle ctrlh;
	int w, part, part2, x1, x2, y1, y2;

	w = RSfindvwind(window);
	if (w < 0)
		return -1; /* what the heck is going on here?? */
	SetPort(window);
	GlobalToLocal((Point *) where);
	part = findcontrol((Point *) where, window, &ctrlh);
	if (part != 0)
		switch (part)
		  {
			case inThumb:
				part2 = trackcontrol(ctrlh, (Point *) where, 0L);
				if (part2 == inThumb)
				  {
					part = GetCtlValue(ctrlh);
					if (ctrlh == RSlocal[w].scroll)
					  {
					  /* scroll visible region vertically */
						VSgetrgn(w, &x1, &y1, &x2, &y2);
						VSsetrgn(w, x1, part, x2, part + (y2 - y1));
					  }
					else
					  { /* ctrlh must be .left */
					  /* scroll visible region horizontally */
						VSgetrgn(w, &x1, &y1, &x2, &y2);
						VSsetrgn(w, part, y1, part + (x2 - x1), y2);
					  } /* if */
				  } /* if */
				break;
			case inUpButton:
			case inDownButton:
			case inPageUp:
			case inPageDown:
				part2 = trackcontrol(ctrlh, (Point *) where, (ProcPtr) ScrollProc);
	/*			InvalRect(&(**RSlocal->scroll).contrlRect); */  /* cheap fix */
				break;
			default:
				break;
		  } /* switch */
	else
	  {
		if (optioned) 
		  {
		  /* send host the appropriate sequences to move the cursor
			to the specified position */
			Point x;
			(*(long *) &x) = normalize(*where, w);
			VSpossend(w, x.h, x.v, screens[scrn].echo);
		  }
		else
			RSselect(w, where, shifted);
	  } /* if */
	return
		0;
  } /* RSclick */

pascal void ScrollProc(control, part)
	short part;
	ControlHandle control;
  /* scroll-tracking routine which does continuous scrolling of visible
	 region. */
  {
	int w, kind, x1, y2, x2, y1;

	kind = RSfindscroll(control, &w);
	VSgetrgn(w, &x1, &y1, &x2, &y2);

	if (kind == 2)
	  { /* horizontal scroll bar */
		switch (part)
		  {
			case inUpButton:							/* Up is left */
				VSscrolleft(w, 1);
				break;
			case inDownButton:							/* Down is right */
				VSscrolright(w, 1);
				break;
			case inPageUp:
				VSscrolleft(w, x2 - x1); /* scroll a whole windowful */
				break;
			case inPageDown:
				VSscrolright(w, x2 - x1); /* scroll a whole windowful */
				break;
			default:
				break;
		  } /* switch */
	  }
	else if (kind == 1)
	  { /* vertical scroll bar */
		switch (part)
		  {
			case inUpButton:
				VSscrolback(w, 1);
				break;
			case inDownButton:
				VSscrolforward(w, 1);
				break;
			case inPageUp:
				VSscrolback(w, y2 - y1); /* scroll a whole windowful */
				break;
			case inPageDown:
				VSscrolforward(w, y2 - y1); /* scroll a whole windowful */
				break;
			default:
				break;
		  } /* switch */
	  } /* if */
  } /* ScrollProc */

void RShide
  (
	int w
  )
  /* hides a terminal window. */
  {
    if (RSsetwind(w) < 0)
		return;
	HideWindow(RScurrent->window);
  } /* RShide */

void RSshow
  (
	int w
  )
  /* reveals a hidden terminal window. */
  {
    if (RSsetwind(w) < 0)
		return;
	ShowWindow(RScurrent->window);
  } /* RSshow */


#ifdef NCSA_TELNET
/* color selection dialog */

/* globals for communicating with handlers for dialog user items */
int
	RScpromptnum = 0, /* number of window for which settings are being displayed/changed */
	RScfontsize = 0; /* currently-chosen font size */
Str255
	RScfontname; /* currently-chosen font name */

#ifdef PROMPTFONT
/* code to include font selection in color selection dialog */

pascal void RSdrawsize(wind, item)
	GrafPtr wind;
	int item;
  /* handler for a dialog user item--frames the item with a shadowed
	border and displays the currently-chosen font size within it. */
  {
	short itemType;
	Rect ibox;
	char **itemh;
	RGBColor rgb;
	char temp[50];

	GetDItem(wind, item, &itemType, &itemh, &ibox);

	EraseRect(&ibox);
	MoveTo(ibox.left, ibox.top + 12);
	sprintf(temp, "%d", RScfontsize);
	drawstring(temp);
	FrameRect(&ibox);
	MoveTo(ibox.right, ibox.top + 1);
	LineTo(ibox.right, ibox.bottom);
	LineTo(ibox.left, ibox.bottom);
  } /* RSdrawsize */

pascal void RSdrawfont(wind, item)
	GrafPtr wind;
	int item;
  /* handler for a dialog user item--frames the item with a shadowed
	border and draws the name of the currently-chosen font within it. */
  {
	int itemType;
	Rect ibox;
	char **itemh;
	RGBColor rgb;

	GetDItem(wind, item, &itemType, &itemh, &ibox);

	EraseRect(&ibox);
	MoveTo(ibox.left, ibox.top + 12);
	drawstring(&RScfontname);
	FrameRect(&ibox);
	MoveTo(ibox.right, ibox.top+1);
	LineTo(ibox.right, ibox.bottom);
	LineTo(ibox.left, ibox.bottom);
  } /* RSdrawfont */

#endif PROMPTFONT

pascal void RScboxdraw(wind, item)
	GrafPtr wind;
	short item;
  /* handler for a dialog user item--draws a box around the item. */
  {
	short itemType;
	Rect ibox;
	char **itemh;

	GetDItem(wind, item, &itemType, &itemh, &ibox);
	InsetRect(&ibox, -2, -2);
	FrameRect(&ibox);
  } /* RScboxdraw */

pascal void RScdraw(wind, item)
	GrafPtr wind;
	short item;
  /* handler for a dialog user item representing one of the
	currently-chosen colors. Fills in the item rectangle with
	the color. */
  {
	short itemType;
	Rect ibox;
	char **itemh;
	RGBColor rgb;

	GetDItem(wind, item, &itemType, &itemh, &ibox);
	GetForeColor(&rgb);
	RGBForeColor(&RSlocal[RScpromptnum].RGBs[item - 3]); /* color corresponding to item */
	PaintRect(&ibox);
	RGBForeColor(&rgb); /* restore previous foreground color */
  } /* RScdraw */

int RScprompt
  (
	int w,
	int (*FilterProc)()
  )
  /* puts up the dialog that lets the user examine and change the color
	settings for the specified window. */
  {
	short
		itemType;
	short
		item, x;
	long
		sresult = 1,
		fresult = 1;

	static char
		*cprompt = "\pChoose a color:";

	Rect ibox;
	char **itemh;
	RGBColor rgb2;
	DialogPtr dlog;
	Point pt;
#ifdef PROMPTFONT
	short size, num;
	long result;
	char sizetemp[10];
	Rect sizebox, fontbox, fnambox, snambox;
	MenuHandle fontMH, sizeMH;
#endif PROMPTFONT

	pt.h = 0;
	pt.v = 0;

	RScpromptnum = w;

#ifdef PROMPTFONT
  /* get name of currently-chosen font */
	RScfontsize = RSlocal[w].fsiz;
	getfontname(RSlocal[w].fnum, &RScfontname);
#endif PROMPTFONT

  /* open the selection dialog */
	dlog = GetNewDialog(1001, (Ptr) 0L, (WindowPtr) -1L);
	SetPort(dlog);

#ifdef PROMPTFONT
  /* create the pop-up menus for choosing font and size */
	fontMH = newmenu(63, "\PFontPopUp");
	AddResMenu(fontMH, 'FONT');
	sizeMH = newmenu(64, "\PSizePopUp");
	appendmenu(sizeMH, "\P7;9;10;12;18;24;36");
	InsertMenu(fontMH, -1);
	InsertMenu(sizeMH, -1);
#endif PROMPTFONT

	GetDItem(dlog, 3, &itemType, &itemh, &ibox);
	SetDItem(dlog, 3, itemType, (Handle) RScdraw, &ibox);

	GetDItem(dlog, 4, &itemType, &itemh, &ibox);
	SetDItem(dlog, 4, itemType, (Handle) RScdraw, &ibox);

	GetDItem(dlog, 5, &itemType, &itemh, &ibox);
	SetDItem(dlog, 5, itemType, (Handle) RScdraw, &ibox);

	GetDItem(dlog, 6, &itemType, &itemh, &ibox);
	SetDItem(dlog, 6, itemType, (Handle) RScdraw, &ibox);

	GetDItem(dlog, 11, &itemType, &itemh, &ibox);
	SetDItem(dlog, 11, itemType, (Handle) RScboxdraw, &ibox);

	GetDItem(dlog, 12, &itemType, &itemh, &ibox);
	SetDItem(dlog, 12, itemType, (Handle) RScboxdraw, &ibox);

	GetDItem(dlog, 13, &itemType, &itemh, &ibox);
	SetDItem(dlog, 13, itemType, (Handle) RScboxdraw, &ibox);

	GetDItem(dlog, 14, &itemType, &itemh, &ibox);
	SetDItem(dlog, 14, itemType, (Handle) RScboxdraw, &ibox);

#ifdef PROMPTFONT
	GetDItem(dlog, 11, &itemType, &itemh, &fnambox);

	GetDItem(dlog, 12, &itemType, &itemh, &fontbox);
	SetDItem(dlog, 12, itemType, (Handle) RSdrawfont, &fontbox);
	LocalToGlobal(&fontbox); /* for positioning pop-up menu */

	GetDItem(dlog, 13, &itemType, &itemh, &snambox);

	GetDItem(dlog, 14, &itemType, &itemh, &sizebox);
	SetDItem(dlog, 14, itemType, (Handle) RSdrawsize, &sizebox);
	LocalToGlobal(&sizebox); /* for positioning pop-up menu */
#endif PROMPTFONT

	item = 0;
	while (item !=1 && item !=2)
	  {
		ModalDialog((ModalFilterProcPtr) FilterProc, &item);
		switch (item)
		  {
			case 3:
				x = GetColor(pt, cprompt, &RSlocal[w].RGBs[0], &rgb2);
				if (x)
					RSlocal[w].RGBs[0] = rgb2;
				break;

			case 4:
				x = GetColor(pt, cprompt, &RSlocal[w].RGBs[1], &rgb2);
				if (x)
					RSlocal[w].RGBs[1] = rgb2;
				break;

			case 5:
				x = GetColor(pt, cprompt, &RSlocal[w].RGBs[2], &rgb2);
				if (x)
					RSlocal[w].RGBs[2] = rgb2;
				break;

			case 6:
				x = GetColor(pt, cprompt, &RSlocal[w].RGBs[3], &rgb2);
				if (x)
					RSlocal[w].RGBs[3] = rgb2;
				break;

#ifdef PROMPTFONT
			case 12:
				InvertRect(&fnambox);
				result = PopUpMenuSelect(fontMH, fontbox.top, fontbox.left, (short) fresult);
				result = result & 0xffff;
				InvertRect(&fnambox);

				if (result > 0)
				  {
					getitem(fontMH, (short) result, &RScfontname);
					RSdrawfont(dlog, 12);
					fresult = result;
				  } /* if */
				break;
			case 14:
				InvertRect(&snambox);
				result = PopUpMenuSelect(sizeMH, sizebox.top, sizebox.left, (short) sresult);
				result = result & 0xffff;
				InvertRect(&snambox);

				if (result > 0)
				  {
					getitem(sizeMH, (short) result, &sizetemp);
					sscanf(sizetemp, "%d", &RScfontsize);
					RSdrawsize(dlog, 14);
					sresult = result;
				  } /* if */
				break;
#endif PROMPTFONT
		  } /* switch */
	  } /* while */

	DisposDialog(dlog);

  /* force redrawing of entire window contents */
	SetPort(RSlocal[w].window);
	InvalRect(&RSlocal[w].window->portRect);

	if (item == 2)
		return (-1);
	else
		for (x = 0; x < 4; x++)
			SetEntryColor(RSlocal[w].pal, x, &RSlocal[w].RGBs[x]);
  /* do something if it changes */;

#ifdef PROMPTFONT
	getfnum(&RScfontname, &num);
	size = RScfontsize;
	DeleteMenu(fontMH);
	DeleteMenu(sizeMH);

	RSchangefont(w, num, size, 1);
#endif PROMPTFONT

	return(0);
  } /* RScprompt */

int RSsetcolor
  (
	int w, /* window number */
	int n, /* color entry number */
	unsigned int r, /* components of new color */
	unsigned int g,
	unsigned int b
  )
  /* sets a new value for the specified color entry of a terminal window. */
  {
    if ( !HasColor || (RSsetwind(w) < 0))		/* from Jim@BYU */
		return(-1);
	RScurrent->RGBs[n].red = r;
	RScurrent->RGBs[n].green = g;
	RScurrent->RGBs[n].blue = b;
	if (RScolor)
	  {
	  /* only take account of the color settings on a color-capable machine */
		SetEntryColor(RScurrent->pal, n, &RScurrent->RGBs[n]);
		SetPort(RScurrent->window);
		InvalRect(&RScurrent->window->portRect);
	  } /* if */
	return(0);
  } /* RSsetcolor */

void RSgetcolor
  (
	int w, /* window number */
	int n, /* color entry number */
	unsigned int *r, /* where to return components of color */
	unsigned int *g,
	unsigned int *b
  )
  /* gets the current value for the specified color entry of a terminal window. */
  {
	*r = RSlocal[w].RGBs[n].red;
	*g = RSlocal[w].RGBs[n].green;
	*b = RSlocal[w].RGBs[n].blue;
  } /* RSgetcolor */

int RSmouseintext				/* Point is in global coords */
  (
	int w,
	long myPoint
  )
  /* is myPoint within the text-display area of the specified window. */
  {
	return
		ptinrect((Point *) &myPoint, &RSlocal[w].textrect); 
  } /* RSmouseintext */

void RSskip
  (
	int w,
	int on
  )
  /* sets the "skip" flag for the specified window (whether ignore
	screen updates until further notice). */
  {
	RSlocal[w].skip = on;
  } /* RSskip */

/**********************************************************************************/
/*  Make sure at least this much memory is available before allocating more memory
*   for me.  Returns true or false whether that much is available.
*/
int RSokmem
  (
	int amount
  )
  {
	char *p;
	
	if (NULL == (p = NewPtr(amount)))
		return(0);
	DisposPtr(p);
	return(1);
  } /* RSokmem */

#endif NCSA_TELNET