🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: mod.mac.sources
Article #51

MakeWrite Source (part 3 of 3)

#51
From: macintosh
Date: Sun, 22 Mar 1987 07:00
1947 lines
44377 bytes
[MakeWrite Source - part 3 of 3]

---
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	MW/MWMenu.c
#	MW/MWMisc.c
#	MW/MWParaDlog.c
#	MW/MWTextToWrite.c
#	MW/MWWindMisc.c
sed 's/^X//' << 'SHAR_EOF' > MW/MWMenu.c
X# include	"MakeWrite.h"
X# include	<MenuMgr.h>
X
X
X
Xtypedef enum		/* File menu item numbers */
X{
X	newMap = 1,
X	openMap,
X	appendMap,
X	saveMap,
X	saveMapAs,
X	close,
X	/* --- */
X	makeWrite = 8,
X	/* --- */
X	quit = 10
X};
X
X
Xtypedef enum		/* Edit menu item numbers */
X{
X	undo = 1,
X	/* --- */
X	cut = 3,
X	copy,
X	paste,
X	clear,
X	/* --- */
X	new = 8,
X	duplicate,
X	/* --- */
X	sort = 11,
X	squish
X};
X
X
Xtypedef enum			/* Special menu items */
X{
X	stdFontList = 1,
X	systemFontList,
X	/* --- */
X	pgraphStyle = 4,
X	/* --- */
X	conflicts = 6,
X	/* --- */
X	getInfo = 8,
X	/* --- */
X	debugOption = 10
X};
X
X
Xstatic MenuHandle	fileMenu;
Xstatic MenuHandle	editMenu;
Xstatic MenuHandle	specialMenu;
X
Xstatic MapSpec		clipMSpec;				/* clipboard specification */
X
X
X/*
X	Enable or disable menu or menu items, according to the string.
X	First char of string is for entire menu, following chars are
X	for successive items.  '0' disables, '1' enables.
X
X	Return true if the status of the menu itself changed
X	value, i.e., if the menu bar now needs redrawing.
X*/
X
XBoolean	SetMenuStatus (m, s)
XMenuHandle	m;
XStringPtr	s;
X{
Xregister Integer	i;
XInteger				menuState;
X
X	menuState = ((**m).enableFlags & 1);	/* current state of menu */
X	for (i = 1; i <= s[0]; ++i)
X	{
X		if (s[i] == '0')
X			DisableItem (m, i - 1);
X		else
X			EnableItem (m, i - 1);
X	}
X	return (menuState != ((**m).enableFlags & 1));
X}
X
X
X/*
X	Fix up menus to match window states.  There will always be some
X	window.
X
X	Note the handling of strings.  Those that may change need to be
X	CopyString'ed into the string, otherwise the string constant
X	itself will be changed.
X
X	This routine is stupid about setting cut&paste types of items.
X*/
X
XFixMenus ()
X{
XWindowPtr			frontWind;
XInteger					theKind;
XInteger					nLines;
XInteger					curLine;
XBoolean				drawBar = false;
XStr255				eString;
Xregister StringPtr	fStr,
X					eStr = eString,		/* initial setting, may change */
X					oStr;
X
X	curLine = mapList->curLine;
X	nLines = mapList->nLines;
X	frontWind = FrontWindow ();
X	theKind = ((WindowPeek) frontWind)->windowKind;
X
X	if (frontWind == mapWind)
X	{
X		fStr = (StringPtr) "\p11111100101";
X		oStr = (StringPtr) "\p11101010101";
X		CopyString ("\p1101111011011", eStr);	/* points to eString */
X
X		if (undoOp == noUndo)
X			eStr[undo + 1] = '0';
X
X		if (curLine == noLine)
X		{
X			cpMarker = false;	/* no line - *can't* apply to marker */
X			eStr[cut + 1] = '0';
X			eStr[copy + 1] = '0';
X			eStr[clear + 1] = '0';
X			eStr[duplicate + 1] = '0';
X			if (havePasteMSpec == false)
X				eStr[paste + 1] = '0';
X		}
X		else if (cpMarker == false)	/* line but c/p applies to map */
X		{
X			if (havePasteMSpec == false)
X				eStr[paste + 1] = '0';
X		}
X
X		if (nLines < 2)
X		{
X			eStr[sort + 1] = '0';
X			eStr[squish + 1] = '0';
X		}
X		else if (nLines >= mapList->maxLines)
X		{
X			if (cpMarker == false && curLine == noLine)
X				eStr[paste + 1] = '0';
X			eStr[new + 1] = '0';
X			eStr[duplicate + 1] = '0';
X		}
X
X/*
X	now figure out how to set the cut/paste indicators.  They're
X	blank if there's no current line and can't paste.  Else set
X	according to the current state of indicator flag.
X*/
X
X		if (curLine == noLine && eStr[paste+1] == '0')
X			BlankCPCtrls ();
X		else
X			SetCPMarker (cpMarker);
X	}
X	else
X	{
X
X/*
X	Settings for File and Special menus are same for DA's and display
X	windows
X*/
X		fStr = (StringPtr) "\p10000010001";
X		oStr = (StringPtr) "\p10001000101";
X
X		if (theKind < 0)				/* DA in front */
X			eStr = (StringPtr) "\p1101111000000";
X		else							/* some display window in front */
X			eStr = (StringPtr) "\p0";
X
X		BlankCPCtrls ();
X	}
X
X	drawBar = SetMenuStatus (fileMenu, fStr);
X	drawBar |= SetMenuStatus (editMenu, eStr);
X	drawBar |= SetMenuStatus (specialMenu, oStr);
X
X	if (drawBar)
X		DrawMenuBar ();
X}
X
X
X/*
X	Handle "About MakeWrite..." selection from Apple menu.
X*/
X
XDoAbout ()
X{
X	(void) Alert (aboutAlrtNum, nil);
X}
X
X
X/*
X	Process selection from File menu
X*/
X
XDoFileMenu (item)
XInteger		item;
X{
XWindowPeek	theWind;
XInteger			theKind;
X
X	switch (item)
X	{
X
X	case newMap:
X		if (DiscardChanges ())
X		{
X			ClobberMap ();
X			ClearMapName ();
X			undoOp = noUndo;
X			mapModified = false;
X		}
X		break;
X
X	case openMap:
X		if (DiscardChanges ())
X		{
X			if (OpenMap ())
X			{
X				undoOp = noUndo;
X				mapModified = false;
X			}
X		}
X		break;
X
X	case appendMap:
X		if (AddMap ())
X		{
X			undoOp = noUndo;
X			mapModified = true;
X		}
X		break;
X
X	case saveMap:
X		if (SaveMap (false))
X			mapModified = false;
X		break;
X
X	case saveMapAs:
X		if (SaveMap (true))
X			mapModified = false;
X		break;
X	
X	case close:
X		theWind = (WindowPeek) FrontWindow ();
X		theKind = theWind->windowKind;
X		if (theKind < 0)				/* DA being closed */
X			CloseDeskAcc (theKind);
X		else							/* Display window - just hide */
X			HideWindow (theWind);		/* it.  Activation proc will */
X		break;							/* dispose of it */
X	
X	case makeWrite:
X		TextToWrite ();
X		break;
X	
X	case quit:
X		if (DiscardChanges ())
X			SkelWhoa ();
X		break;
X	}
X	FixMenus ();
X}
X
X
XDoUndo ()
X{
XMapSpec	tempSpec;
XStringHandle	hStr;
XStr255			tempStr;
XInteger				selStart, selEnd;
XBoolean			tmpCPMarker;
X
X	tmpCPMarker = cpMarker;
X	cpMarker = undoCPMarker;
X	undoCPMarker = tmpCPMarker;
X
X	InitMSpec (&tempSpec);
X	switch (undoOp)
X	{
X
X	case undoInsert:
X		undoOp = undoDelete;
X		CopyMSpec (&mapSpec[undoPos], &undoMSpec);
X		DeleteMapping (undoPos);
X		break;
X
X	case undoDelete:
X		undoOp = undoInsert;
X		InsertMapping (&undoMSpec, undoPos);
X		break;
X
X	case undoPaste:
X		CopyMSpec (&mapSpec[undoPos], &tempSpec);
X		PasteMapping (&undoMSpec, undoPos);
X		CopyMSpec (&tempSpec, &undoMSpec);
X		break;
X
X	case undoFieldChg:
X		SetMapFieldValue (undoFieldType, undoVal);
X		break;
X
X	case undoTyping:
X	case undoMarkerOp:
X		undoOp = undoMarkerOp;
X		CopyMSpec (&mapSpec[undoPos], &tempSpec);
X		CopyMSpec (&undoMSpec, &mapSpec[undoPos]);
X		CopyMSpec (&tempSpec, &undoMSpec);
X
X		hStr = mapSpec[undoPos].mark;
X		HLock (hStr);
X		PasteField (mapList, undoPos, markField, *hStr);
X		HUnlock (hStr);
X		SetSelectors (undoPos);
X		break;
X
X	}
X	TermMSpec (&tempSpec);
X}
X
X
X/*
X	Process selection from Edit menu
X*/
X
XDoEditMenu (item)
XInteger		item;
X{
Xregister Integer	curLine;
X
X	if (SystemEdit (item - 1))
X		return;
X
X	if (EditMarker (item))
X		return;					/* it was a marker edit operation */
X
X	curLine = mapList->curLine;
X	switch (item)
X	{
X	
X	case undo:
X		DoUndo ();
X		break;
X	
X	case cut:
X		undoCPMarker = cpMarker;
X		CopyMSpec (&mapSpec[curLine], &clipMSpec);
X		CopyMSpec (&clipMSpec, &undoMSpec);
X		undoOp = undoDelete;
X		undoPos = curLine;
X		havePasteMSpec = true;
X		DeleteMapping (curLine);
X		break;
X	
X	case copy:
X		CopyMSpec (&mapSpec[curLine], &clipMSpec);
X		havePasteMSpec = true;
X		break;
X	
X	case paste:
X		undoCPMarker = cpMarker;
X		if (curLine != noLine)
X		{
X			CopyMSpec (&mapSpec[curLine], &undoMSpec);
X			undoOp = undoPaste;
X			undoPos = curLine;
X			PasteMapping (&clipMSpec, curLine);
X		}
X		else										/* no selection; */
X		{											/* add at end */
X			undoOp = undoInsert;
X			undoPos = mapList->nLines;
X			if (InsertMapping (&clipMSpec, mapList->nLines) == false)
X				undoOp = noUndo;
X		}
X		break;
X	
X	case clear:
X		undoCPMarker = cpMarker;
X		CopyMSpec (&mapSpec[curLine], &undoMSpec);
X		undoOp = undoDelete;
X		undoPos = curLine;
X		DeleteMapping (curLine);
X		break;
X	
X	case new:
X		undoCPMarker = cpMarker;
X		NewMapping ();
X		/*SetCPMarker (true);*/
X		undoOp = undoInsert;
X		break;
X	
X	case duplicate:
X		undoCPMarker = cpMarker;
X		DupMapping (curLine);	/* changes mapList->curLine */
X		SetCPMarker (true);
X		undoOp = undoInsert;
X		undoPos = mapList->curLine;
X		break;
X
X	case sort:
X		SortMap ();
X		undoOp = noUndo;	/* can't undo this */
X		break;
X
X	case squish:
X		SquishMap ();
X		undoOp = noUndo;	/* can't undo this */
X		break;
X
X	}
X
X	if (item != copy)
X		mapModified = true;
X	FixMenus ();
X}
X
X
XDoSpecialMenu (item)
XInteger		item;
X{
X	switch (item)
X	{
X
X	case stdFontList:
X		StrFonts (true);
X		SetSelectors (mapList->curLine);
X		break;
X
X	case systemFontList:
X		ResourceFonts (true);
X		SetSelectors (mapList->curLine);
X		break;
X
X	case pgraphStyle:
X		DoParaDialog ();
X		break;
X
X	case conflicts:
X		FindConflicts ();
X		break;
X
X	case getInfo:
X		HelpWindow ();
X		break;
X
X# ifdef	debug
X	case debugOption:
X		debugOut = !debugOut;
X		CheckItem (specialMenu, debugOption, debugOut);
X		break;
X# endif
X
X	}
X	FixMenus ();
X}
X
X
X/*
X	Menu initialization.
X*/
X
XSetupMenus ()
X{
X	SkelApple ("\pAbout MakeWrite...", DoAbout);
X
X	fileMenu = GetMenu (fileMenuNum);
X	SkelMenu (fileMenu, DoFileMenu, nil);
X
X	editMenu = GetMenu (editMenuNum);
X	SkelMenu (editMenu, DoEditMenu, nil);
X
X	specialMenu = GetMenu (specialMenuNum);
X# ifdef	debug
X	AppendMenu (specialMenu, "\p(-;Debug Output");
X# endif
X	SkelMenu (specialMenu, DoSpecialMenu, nil);
X
X	InitMSpec (&undoMSpec);
X	InitMSpec (&clipMSpec);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMisc.c
X# include	"MakeWrite.h"
X# include	<EventMgr.h>
X
X
X/* ---------------------------------------------------------------- */
X/*							String Operations						*/
X/* ---------------------------------------------------------------- */
X
X/*
X	Copy src to dst
X*/
X
XCopyString (src, dst)
XStringPtr	src, dst;
X{
X	BlockMove (src, dst, (Longint) (src[0] + 1));
X}
X
X
X/*
X	Append src to dst
X*/
X
XAppendString (src, dst)
XStringPtr	src, dst;
X{
X	BlockMove (&src[1], dst + dst[0] + 1, (Longint) src[0]);
X	dst[0] += src[0];
X}
X
X
X/*
X	Compare two strings.
X	Return:
X		0		s1 = s2
X		< 0		s1 < s2
X		> 0		s1 > s2
X*/
X
XCompareString (s1, s2)
Xregister StringPtr	s1, s2;
X{
Xregister Integer	i, len, diff;
X
X	len = s1[0];
X	if (len > s2[0])
X		len = s2[0];
X	for (i = 1; i <= len; ++i)
X	{
X		if ((diff = s1[i] - s2[i]) != 0)
X			return (diff);
X	}
X	return (s1[0] - s2[0]);
X}
X
X
XBoolean InString (s, c)
XStringPtr	s;
Xchar		c;
X{
Xregister Integer	i, len;
X
X	for (len = s[0], i = 1; i <= len; ++i)
X	{
X		if (s[i] == c)
X			return (true);
X	}
X	return (false);
X}
X
X/* ---------------------------------------------------------------- */
X/*							Event Operations						*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Return true if there's a mouse-down event pending (also flush the
X	event so that it's not used in some way other than as a signal.
X*/
X
XBoolean	MouseClick ()
X{
XEventRecord	theEvent;
X
X	if (EventAvail (mDownMask, &theEvent))
X	{
X		FlushEvents (mDownMask, 0);
X		return (true);
X	}
X	return (false);
X}
X
X
Xstatic Integer	eventTypes;
X
X
X/*
X	Make sure any events of proper type are processed before
X	proceeding.
X*/
X
XCheckEvents ()
X{
XEventRecord	event;
X
X	if (!EventAvail (eventTypes, &event))
X		SkelWhoa ();
X}
X
X
XDoEvents (doTypes)	/* can be called recursively */
XInteger		doTypes;
X{
XInteger		types;
XInteger		mask;
XProcPtr	bkGnd;
X
X	SkelGetBackground (&bkGnd);		/* get current background proc */
X	SkelGetEventMask (&mask);		/* and event mask */
X	types = eventTypes;				/* and processing types */
X
X	SkelBackground (CheckEvents);	/* install new background & mask */
X	SkelEventMask (doTypes);
X	eventTypes = doTypes;
X
X	SkelMain ();					/* handle updates only */
X
X	SkelBackground (bkGnd);			/* restore old background & mask */
X	SkelEventMask (mask);
X	eventTypes = types;
X}
X
X
XDoUpdates ()
X{
X	DoEvents (updateMask);
X}
X
X
X/*
X	Make a window the front window and update it before proceeding.
X*/
X
XMakeFrontWind (w)
XWindowPtr	w;
X{
X	HiliteMenu (0);
X	SelectWindow (w);
X	ShowWindow (w);
X	DoEvents (updateMask + activMask);
X	SetPort (w);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*							Memory Operations						*/
X/* ---------------------------------------------------------------- */
X
X
XBoolean ExpandHandle (h, delta)
XHandle	h;
XSize	delta;
X{
XSize	newSize;
X
X	newSize = GetHandleSize (h) + delta;
X	SetHandleSize (h, newSize);
X	return (GetHandleSize (h) == newSize);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*								Miscellaneous						*/
X/* ---------------------------------------------------------------- */
X
X
XBoolean DiscardChanges ()
X{
XBoolean	result;
X
X	if (!mapModified)
X		return (true);
X	ParamText ("\pDiscard changes to current map?", "\p", "\p", "\p");
X	result = (Alert (questAlrtNum, nil) == 2);	/* 2 is "OK" */
X	DoUpdates ();
X	return (result);
X}
X
X
X
XBoolean DestroyWarn ()
X{
XBoolean	result;
X
X	if (mapList->nLines == 0)	/* if nothing there, don't bother, */
X	{							/* unless map has changed, then ask */
X		if (mapModified)		/* different question */
X			return (DiscardChanges ());
X		return (true);
X	}
X	ParamText ("\pThis operation destroys the current map.",
X				"\p Do you wish to proceed?", "\p", "\p");
X	result = (Alert (questAlrtNum, nil) == 2);	/* 2 is "OK" */
X	DoUpdates ();
X	return (result);
X}
X
X
X/*
X	Display a message in a generic alert.
X*/
X
XMessage (s1, s2, s3, s4)
XStringPtr	s1, s2, s3, s4;
X{
X	ParamText (s1, s2, s3, s4);
X	(void) Alert (msgeAlrtNum, nil);
X	DoUpdates ();
X}
X
X
XMessage1 (s1)
XStringPtr	s1;
X{
X	Message (s1, "\p", "\p", "\p");
X}
X
X
XMessage2 (s1, s2)
XStringPtr	s1, s2;
X{
X	Message (s1, s2, "\p", "\p");
X}
X
X
XMessage3 (s1, s2, s3)
XStringPtr	s1, s2, s3;
X{
X	Message (s1, s2, s3, "\p");
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWParaDlog.c
X/*
X	Paragraph style dialog
X*/
X
X
X# include	<DialogMgr.h>
X# include	<EventMgr.h>
X# include	<ToolboxUtil.h>
X# include	"MakeWrite.h"
X
X
Xtypedef enum		/* paragraph style dialog item numbers */
X{
X	paraOK = 1,
X	paraCancel,
X	paraEach,
X	paraBlank,
X	paraSmart,
X	paraMText,
X	paraPText,
X	paraQText,
X	paraLine1,
X	paraLine2
X};
X
X
X/*
X	Initialize paragraph style to default:  blank lines and lines
X	beginning with whitespace initiate paragraphs,  line joining
X	is smart, there's no explicit paragraph or page break marker.
X*/
X
X
Xstatic ParaStyle	defStyle =  { false, true, true };
Xstatic Str255		defPeriodStr = "\p.!?";
Xstatic Str255		defQuoteStr = { 5, '"', '\'', 0xd3, 0xd5, ')' };
X
X
X/*
X	Set the contents of a string using the contents of the 'STR '
X	resource whose id is passed as strResId.
X*/
X
Xstatic ResSetString (strResId, str)
XInteger			strResId;
XStringPtr	str;
X{
XStringHandle	hStr;
X
X	hStr = GetString (strResId);
X	HLock (hStr);
X	if ((*hStr)[0] > maxMarkLen)
X		(*hStr)[0] = maxMarkLen;
X	CopyString (*hStr, str);
X	HUnlock (hStr);
X	ReleaseResource (hStr);
X}
X
X
XInitParaStyle ()
X{
X	paraStyle = defStyle;
X	paraMark[0] = 0;
X	pageMark[0] = 0;
X	ResSetString (periodStrNum, periodStr);
X	ResSetString (quoteStrNum, quoteStr);
X}
X
X
Xstatic pascal void DoLine (dlog, item)
XDialogPtr	dlog;
XInteger			item;
X{
XHandle	itemHandle;
XInteger		itemType;
XRect	itemRect;
X
X	GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X	FrameRect (&itemRect);
X}
X
X
Xstatic Boolean GetDCtl (dlog, item)
XDialogPtr	dlog;
XInteger			item;
X{
XHandle	itemHandle;
XInteger		itemType;
XRect	itemRect;
X
X	GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X	return (GetCtlValue (itemHandle));
X}
X
X
Xstatic SetDCtl (dlog, item, value)
XDialogPtr	dlog;
XInteger			item;
XBoolean		value;
X{
XHandle	itemHandle;
XInteger		itemType;
XRect	itemRect;
X
X	GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X	SetCtlValue (itemHandle, (Integer) value);
X}
X
X
Xstatic GetDText (dlog, item, str)
XDialogPtr	dlog;
XInteger			item;
XStringPtr	str;
X{
XHandle	itemHandle;
XInteger		itemType;
XRect	itemRect;
XStr255	s;
X
X	GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X	GetIText (itemHandle, s);
X	if (s[0] > maxMarkLen)
X		s[0] = maxMarkLen;
X	CopyString (s, str);
X}
X
X
Xstatic SetDText (dlog, item, str)
XDialogPtr	dlog;
XInteger			item;
XStr255		str;
X{
XHandle	itemHandle;
XInteger		itemType;
XRect	itemRect;
X
X	GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X	SetIText (itemHandle, str);
X	SelIText (dlog, item, 0, 32767);
X}
X
X
X/*
X	Get the text of an item, and return true if it's different than
X	the current value
X*/
X
Xstatic Boolean CheckDText (dlog, item, str)
XDialogPtr	dlog;
XInteger			item;
XStr255		str;
X{
XStr255		tmpStr;
XBoolean		changed;
X
X	GetDText (dlog, item, tmpStr);
X	changed = (CompareString (str, tmpStr) != 0);
X	CopyString (tmpStr, str);
X	return (changed);
X}
X
X
Xstatic SetDProc (dlog, item, p)
XDialogPtr	dlog;
XInteger			item;
XProcPtr		p;
X{
XHandle	itemHandle;
XInteger		itemType;
XRect	itemRect;
X
X	GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X	SetDItem (dlog, item, itemType, p, &itemRect);
X}
X
X
Xstatic SetParaCheck (theDialog, each, blank, smart)
XDialogPtr	theDialog;
XBoolean		each, blank, smart;
X{
X	SetDCtl (theDialog, paraEach, each);
X	SetDCtl (theDialog, paraBlank, blank);
X	SetDCtl (theDialog, paraSmart, smart);
X}
X
X
X
XDoParaDialog ()
X{
Xregister DialogPtr	theDialog;
XInteger			itemHit = 0;
XBoolean		loop = true;
Xregister Boolean	curEach, curBlank, curSmart;
XBoolean		changed;
XStr255		s;
X
X	theDialog = GetNewDialog (paraDlogNum, nil, -1L);
X	SetParaCheck (theDialog, curEach = paraStyle.pEachLine,
X							 curBlank = paraStyle.pBlankLine,
X							 curSmart = paraStyle.pSmartJoin);
X	SetDText (theDialog, paraPText, periodStr);
X	SetDText (theDialog, paraQText, quoteStr);
X	SetDText (theDialog, paraMText, paraMark);
X	SetDProc (theDialog, paraLine1, DoLine);
X	SetDProc (theDialog, paraLine2, DoLine);
X	ShowWindow (theDialog);
X
X	while (loop)
X	{
X		ModalDialog (nil, &itemHit);
X		switch (itemHit)
X		{
X
X/*
X	If smart join is selected but there aren't any sentence terminators,
X	put up an alert and don't quit.
X*/
X		case paraOK:
X			GetDText (theDialog, paraPText, s);
X			if (curSmart && s[0] == 0)
X			{
X				(void) Alert (noPeriodAlrtNum, nil);
X				continue;
X			}
X
X			changed = (paraStyle.pEachLine != curEach);
X			paraStyle.pEachLine = curEach;
X
X			changed |= (paraStyle.pBlankLine != curBlank);
X			paraStyle.pBlankLine = curBlank;
X
X			changed |= (paraStyle.pSmartJoin != curSmart);
X			paraStyle.pSmartJoin = curSmart;
X
X			changed |= CheckDText (theDialog, paraMText, paraMark);
X			changed |= CheckDText (theDialog, paraPText, periodStr);
X			changed |= CheckDText (theDialog, paraQText, quoteStr);
X
X			if (changed)
X				mapModified = true;
X			loop = false;
X			break;
X
X		case paraCancel:
X			loop = false;
X			break;
X
X		case paraEach:
X			curEach = !curEach;
X			if (curEach)
X				curBlank = false;
X			break;
X
X		case paraBlank:
X			curBlank = !curBlank;
X			if (curBlank)
X				curEach = false;
X			break;
X
X		case paraSmart:
X			curSmart = !curSmart;
X			break;
X
X		}
X		SetParaCheck (theDialog, curEach, curBlank, curSmart);
X	}
X	DisposDialog (theDialog);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWTextToWrite.c
X/*
X	Convert text file to MacWrite document, using formatting
X	specifications contained in current map.
X
X	Possibly add:
X		Text compression
X*/
X
X
X# include	"MakeWrite.h"
X# include	"MWMaca.h"
X# include	"MWFileStuff.h"
X# include	<StdFilePkg.h>
X
X
X# define	applFont	1
X
X# define	maxTBufSize	1024	/* text file input buffer size */
X# define	maxCBufSize	4000	/* MacWrite limit on chars in paragraph */
X
X/*
X	MacWrite's maximum main doc text para count is something over
X	2000.  I choose 2000 as a reasonable limit.
X*/
X
X# define		maxMWParas	2000
X
X
X/*
X	Vars for text file streaming
X*/
X
Xstatic Integer	fText;					/* input text file reference number */
Xstatic char	tFileBuf[maxTBufSize];	/* file buffer */
Xstatic Longint	tFileSize;				/* file size */
Xstatic Longint	tFileRead;				/* # chars read */
Xstatic Longint	tFileLeft;				/* # chars still to read */
Xstatic Longint	tBufSize;				/* number of chars currently in buffer */
Xstatic Integer	tBufPos;				/* current text buffer position */
Xstatic Integer	percent;				/* percent of input read so far */
X
X
X/*
X	fWord - output MacWrite file reference number
X	pushBack - text file input pushback queue
X	outBuf - output paragraph buffer
X	outChars - number of chars into current output paragraph so far
X	blankCount - number of blanks to put out for line joining
X	fmtCount - number of formats in the current paragraph so far
X	fmtBuf - format information storage array
X	maxFormats - number of formats the format array handle can hold
X		before needing expansion
X	needFormat - true if need to generate a format when the next output
X		char is added to current paragraph
X	paraInfo - paragraph information storage array
X	maxParas - number of elements paraInfo can hold before needing expansion
X	paraCount - current number of paragraphs (doesn't count initial ruler)
X
X	font, size, style - current format
X*/
X
Xstatic Integer	fWord;
Xstatic Str255	pushBack;
Xstatic char		outBuf[maxCBufSize];
Xstatic Integer	outChars;
Xstatic Integer		blankCount;
X
Xstatic FAHandle		fmtBuf;
Xstatic Integer		fmtCount;
Xstatic Integer		maxFormats;
Xstatic Boolean		needFormat;
X
Xstatic PIAHandle	paraInfo;
Xstatic Integer		maxParas;
Xstatic Integer		paraCount;
X
Xstatic Integer		font;
Xstatic Integer		size;
Xstatic Integer		style;
X
X
X/*
X	Initialize text streaming variables
X*/
X
Xstatic InitTextStream (f)
XInteger		f;
X{
X	(void) GetEOF (f, &tFileSize);	/* set up streaming variables */
X	tFileLeft = tFileSize;
X	tFileRead = 0;
X	tBufSize = 0;
X	tBufPos = 0;
X	percent = -1;
X}
X
X
X/*
X	Get next char from text file.  This has to take account of the
X	state of the pushback stack.  File is read from disk a block
X	at a time and dribbled out to avoid making a file system call
X	for every character.
X
X	Return false on end of file or file read error.
X*/
X
Xstatic Boolean ReadTextChar (c)
Xregister char	*c;
X{
XInteger		newPercent;
X
X	if (pushBack[0] > 0)				/* pushback stack not empty */
X	{
X		*c = pushBack[pushBack[0]--];	/* return top char */
X		return (true);
X	}
X
X	if (tBufPos >= tBufSize)	/* need to read in a new block */
X	{
X		tBufSize = tFileLeft;
X		if (tBufSize == 0)				/* end of file */
X			return (false);
X		if (tBufSize > maxTBufSize)		/* don't read more than a block */
X			tBufSize = maxTBufSize;
X		tFileLeft -= maxTBufSize;
X		if (tFileLeft < 0)
X			tFileLeft = 0;
X
X		if (!FileRead (fText, tFileBuf, (Longint) tBufSize))
X			return (false);				/* read error */
X		tBufPos = 0;
X	}
X	*c = tFileBuf[tBufPos++];
X
X# ifdef	debug
X	DisplayChar (*c);
X# endif
X
X	newPercent = (++tFileRead * 100) / tFileSize;
X	if (newPercent != percent)
X	{
X		percent = newPercent;
X		SetMeterPercent (percent);
X	}
X	return (true);
X}
X
X
X/*
X	FIgure out how many blanks need to be added to the output buffer
X	if another line is joined on.  Default is one.  If smart join is
X	on, then two spaces if something like a period is at the end now.
X	Remember to account for spaces that may already be on the end.  If
X	a tab is found at the end, then throw hands up in disgust, because
X	who knows how wide it is?
X*/
X
Xstatic SetBlankCount ()
X{
Xregister Integer	i, endBlanks, needBlanks = 1;
Xregister char	c;
X
X	i = outChars;
X	while (i > 0)	/* count up spaces on end currently */
X	{
X		if ((c = outBuf[i-1]) == '\t')
X		{
X			blankCount = 0;
X			return;					/* tab found - give up */
X		}
X		if (c != ' ')
X			break;
X		--i;
X	}
X	endBlanks = outChars - i;
X
X	if (paraStyle.pSmartJoin)	/* smart join - try to be intelligent */
X	{
X		while (i > 0)
X		{
X			c = outBuf[i-1];
X			if (InString (quoteStr, c))	/* quote char - ignore */
X				--i;
X			else			/* not quote char - is it period char? */
X			{
X				if (InString (periodStr, c))
X					needBlanks = 2;		/* yes - need two chars */
X				break;
X			}
X		}
X	}
X
X	if (i == 0)					/* empty buffer - nothing needed */
X		needBlanks = 0;
X
X	needBlanks -= endBlanks;	/* account for those already there */
X	if (needBlanks < 0)
X		needBlanks = 0;
X	blankCount = needBlanks;
X}
X
X
X/*
X	Push saved text back onto the pushback stack
X*/
X
Xstatic PushSavedText (s)
XStringPtr	s;
X{
X	while (s[0] > 0)
X	{
X		pushBack[++pushBack[0]] = s[s[0]--];
X	}
X}
X
X
Xstatic Boolean NewFormat ()
X{
Xregister Format	*f;
X
X# ifdef	debug
X	DisplayString ("\p {NewFormat}");
X# endif
X
X	if (fmtCount >= maxFormats)	/* need to make format array bigger */
X	{
X		if (!ExpandHandle (fmtBuf, 1024L))
X		{
X			Message1 ("\pOut of memory, can't continue (NewFormat)");
X			return (false);
X		}
X		maxFormats = GetHandleSize (fmtBuf) / sizeof (Format);
X	}
X
X	f = &((**fmtBuf)[fmtCount++]);
X	f->fmtPos = outChars;			/* starting pos of format */
X	f->fmtFont = font;				/* current font */
X	f->fmtSize = size;				/* current size */
X	f->fmtStyle = style;			/* current style */
X	return (true);
X}
X
X
Xstatic Boolean AddChar (c)
Xchar	c;
X{
XStr255	s;
X
X	if (needFormat)
X	{
X		needFormat = false;
X		if (!NewFormat ())
X			return (false);		/* couldn't get memory for format */
X	}
X	if (outChars >= maxCBufSize)
X	{
X		NumToString ((Longint) maxCBufSize, s);
X		Message ("\pParagraph contains more than ", s,
X					"\p chars (MacWrite limit exceeded).",
X					"\p  Check your Paragraph Style settings.");
X		return (false);
X	}
X	outBuf[outChars++] = c;
X	return (true);
X}
X
X
Xstatic ChangeCurFormat (m)
Xregister MapSpec	*m;
X{
XStr255	infoStr;
X
X	if (m->font != sameFont && m->font != font)
X	{
X		font = m->font;
X		needFormat = true;
X	}
X	if (m->size != sameSize && m->size != size)
X	{
X		size = m->size;
X		needFormat = true;
X	}
X	if (m->style != sameStyle && m->style != style)
X	{
X		style = m->style;
X		needFormat = true;
X	}
X
X# ifdef	debug
X	if (needFormat)
X	{
X		DisplayChar ('{');
X		FontToStr (font, infoStr);
X		DisplayString (infoStr);
X		DisplayChar ('/');
X		DisplayInt (size);
X		DisplayChar ('/');
X		StyleToStr (style, infoStr);
X		DisplayString (infoStr);
X		DisplayString ("\p} ");
X	}
X# endif
X}
X
X
X/*
X	Write stored paragraph contents to disk:
X		number bytes of text (word)
X		the text
X		zero pad if necessary to align to word boundary
X		number bytes of format information
X		the format information
X
X	Construct a new element in the paragraph information array
X	as well, and reset the paragraph state vars.
X	
X	The data position pointer in the para info element is set
X	to the current file position, since that's where the data
X	will be written.
X*/
X
Xstatic Boolean FlushPara ()
X{
XInteger	fmtLen, dataLen;
XBoolean	result;
XStr255	s;
X
X# ifdef	debug
X	DisplayString ("\p{FlushPara}");
X# endif
X
X	if (paraCount >= maxMWParas)
X	{
X		NumToString ((Longint) maxMWParas, s);
X		Message3 ("\pYour document contains more than ",
X						s, "\p paragraphs.  Split the input file and try again.");
X		return (false);
X	}
X		
X	if (paraCount >= maxParas)	/* need to make para info array bigger */
X	{
X		if (!ExpandHandle (paraInfo, 1024L))
X		{
X			Message1 ("\pOut of memory, can't continue (FlushPara)");
X			return (false);
X		}
X		maxParas = GetHandleSize (paraInfo) / sizeof (ParaInfo6);
X	}
X
X	fmtLen = fmtCount * sizeof (Format);
X	dataLen = sizeof (Integer)			/* word for length of text */
X			+ ((outChars + 1) & ~1)	/* text ( + pad if necessary) */
X			+ sizeof (Integer)			/* word for length of formats */
X			+ fmtLen;					/* formats */
X	HLock (paraInfo);
X	SetParaInfo (&((**paraInfo)[paraCount++]),
X					16, 0, FilePos (fWord), dataLen, 0);
X	HUnlock (paraInfo);
X	HLock (fmtBuf);
X	result =
X		   WriteInteger (fWord, outChars)
X		&& FileWrite (fWord, outBuf, (Longint) outChars)
X		&& ZeroPad (fWord, 0)
X		&& WriteInteger (fWord, fmtLen)
X		&& FileWrite (fWord, *fmtBuf, (Longint) fmtLen);
X	HUnlock (fmtBuf);
X	outChars = 0;			/* reset para state vars */
X	fmtCount = 0;
X	needFormat = true;
X	blankCount = 0;			/* don't need blanks for line joining now */
X	return (result);
X}
X
X
X/*
X	Flush current paragraph, if there's any text in it
X*/
X
Xstatic Boolean DoBreak ()
X{
X	return (outChars == 0 || (AddChar (cr) && FlushPara ()));
X}
X
X
X/*
X	Flush current paragraph, regardless of whether there's anything
X	in it or not.
X*/
X
Xstatic Boolean DoSpace ()
X{
X	return (AddChar (cr) && FlushPara ());
X}
X
X
X/*
X	FormatText - convert text file to MacWrite file
X
X	Winner of 1987 "Ugliest Function" award.  That goes for the
X	comments, too.  They've been revised so often, even I barely
X	understand them, so good luck.
X
X	saveQueue is the text that's been matched partially.  It's saved
X	for writing to output in case no match is found:  the text is
X	put back on the pushback stack, the first char is written out
X	and a match is sought starting with the next char.
X
X	The biggest headache about this thing is getting it to work properly
X	with all legal combinations of paragraph style settings.
X
X	"Each line a paragraph" is never on if blank line paragraphing is
X	on, and vice-versa.  Use of a paragraph marker is compatible with
X	all options.
X
X	Input lines containing only imbedded commands are always ignored
X	for paragraphing purposes - that is, they're not treated as blank
X	lines.
X*/
X
Xstatic Boolean FormatText ()
X{
Xchar			c;				/* input char */
XStr255			saveQueue;		/* input save queue */
XInteger				index;			/* command index */
Xregister Integer	inLineChars;	/* # chars from current line added to */
X								/* output (for blank line and beginning */
X								/* of line detection) */
XBoolean			cmdsInLine;		/* whether commands were found in line */
XBoolean			xNeedFormat;
X
X	if (!WritePrelude (fWord))
X		return (false);
X
X	font = applFont;
X	size = 12;
X	style = 0;	/* plain */
X
X	InitMarkStates ();				/* clear match info */
X	pushBack[0] = 0;				/* and file queues */
X	saveQueue[0] = 0;
X	inLineChars = 0;			/* no chars added from current line */
X	blankCount = 0;				/* no blanks needed for line joining yet */
X	cmdsInLine = false;			/* no commands in line yet */
X	paraCount = 0;				/* no paragraphs yet */
X	outChars = 0;				/* no chars in current paragraph */
X	fmtCount = 0;				/* no formats yet, either */
X	needFormat = true;			/* generate format on next char written */
X
X	while (ReadTextChar (&c))			/* while not eof on text file */
X	{
X		saveQueue[++saveQueue[0]] = c;
X		switch (index = CheckMarkers (c))
X		{
X
X		case -2:						/* no match */
X/*
X	Push back saved text, read first char and add to current
X	paragraph.  If the paragraph is done, flush it to disk, and
X	start looking for a new marker.
X
X	Note what happens on cr.  It is read, saved, fails to match, and
X	is pushed back.  If there are other chars before it in pushback,
X	they'll be reprocessed (except first of them, which is added to
X	para).  Eventually, the cr becomes first thing in pushback.  It is
X	read, saved, fails to match, and is pushed back,  Then it's read
X	again, and causes para flushing according to para style rules.
X
X	Carriage return check is here only.  Cr never matches any marker
X	char, since it can't be typed into one.  Therefore it's not possible
X	to get any other return value from CheckMarkers when c == cr.
X*/
X
X			PushSavedText (saveQueue);
X			InitMarkStates ();
X			(void) ReadTextChar (&c);
X
X/*
X	If the character is not a carriage return, then it is simply
X	added to the current paragraph.  The exception occur if this is
X	the first char of the line:
X
X	(i) If the character is whitespace at the beginning of the line,
X	then the line begins a new paragraph, so flush the previous
X	paragraph, if there's anything there.
X
X	(ii) Dribble out any blanks needed to take care of any line
X	joining that might be going on.  Delay putting out any format
X	change that might be pending until right before the char following
X	the blanks - it's safe to do this because a format must have
X	already been written for there to be any need to join with spaces.
X*/
X
X			if (c != cr)
X			{
X				if (inLineChars == 0)			/* if start of line... */
X				{
X					if (c == ' ' || c == '\t')
X					{
X						if (!DoBreak ())
X							return (false);
X					}
X					else
X					{
X						xNeedFormat = needFormat;
X						needFormat = false;
X						while (blankCount > 0)
X						{
X							if (!AddChar (' '))
X								return (false);
X							--blankCount;
X						}
X						needFormat = xNeedFormat;
X					}
X				}
X				if (!AddChar (c))
X					return (false);
X				++inLineChars;
X			}
X
X/*
X	Char is cr.  If line only contained commands, ignore it.
X	Else if every line begins a paragraph, flush it.  Else if
X	line is blank and blank lines begin paragraphs.  Else it's just
X	the end of the current line and it will be joined to the text of
X	the next line unless the paragraph gets flushed first - so figure
X	out how many spaces to put out before the next line is written.
X	The writing happens when we actually get a line to be joined, not
X	here, so that spaces don't get tacked onto lines that may not need
X	them.
X*/
X
X			else
X			{
X				if (!(cmdsInLine && inLineChars == 0))
X				{
X					if (paraStyle.pEachLine)		/* always force line */
X					{
X						if (!DoSpace ())
X							return (false);
X					}
X					else if (inLineChars == 0)			/* if blank line */
X					{
X						if (paraStyle.pBlankLine)	/* and they are paras */
X						{
X							if (!DoBreak () || !DoSpace ())
X								return (false);
X						}
X						else	/* ignore the line, but set blank count */
X						{
X							SetBlankCount ();
X						}
X					}
X					else
X					{
X						SetBlankCount ();
X					}
X				}
X				inLineChars = 0;
X				cmdsInLine = false;
X			}
X			break;
X	
X		case -1:						/* match, but not entirely yet */
X			break;						/* just keep looking */
X
X		default:						/* found complete match */
X/*
X	Since the text matched a marker, it either appears in the
X	output as a format change or signals the beginning of a
X	paragraph.  In either case, it doesn't appear in the output
X	as literal text, so can toss the save queue.
X
X	If it's a format, process the format spec, setting the flag
X	indicating that a new format will be needed on the next char
X	written out (but only if the format actually *changes*).
X
X	If it's a para marker, flush the current paragraph.
X*/
X			cmdsInLine = true;
X
X			if (index == paraMarkIdx)
X			{
X				if (!DoSpace ())
X					return (false);
X			}
X			else if (index == pageMarkIdx)
X			{
X				/* not implemented */
X# ifdef	debug
X				DisplayString ("\p{Page break not implemented}");
X# endif
X			}
X			else
X				ChangeCurFormat (&mapSpec[index]);
X
X			saveQueue[0] = 0;		/* toss pushback */
X			InitMarkStates ();		/* start looking for new marker */
X			break;
X		
X		}
X	}
X
X/*
X	It's the end of the file, but we might have been left in the middle
X	of matching a mark, so return saved text to the pushback queue and
X	write it out.  Note that if we *were* in the middle of mark testing,
X	then this is not the beginning of a line and no spaces need to be
X	dribbled.
X*/
X
X	PushSavedText (saveQueue);
X	while (ReadTextChar (&c))
X	{
X		if (!AddChar (c))
X			return (false);
X	}
X
X/*
X	There must be at least one text paragraph.  If there aren't any
X	make sure one is generated.  If nothing at all has been formatted,
X	there won't even be any formats generated, so force one.  Then
X	flush the paragraph.
X
X	If there already were paragraphs, then see whether unflushed
X	characters are being held and flush if so.
X*/
X
X	if (paraCount == 0)
X	{
X		if (fmtCount == 0)
X		{
X			if (!NewFormat ())
X				return (false);
X		}
X		if (!FlushPara ())
X			return (false);
X	}
X	else if (outChars != 0)
X	{
X		if (!FlushPara ())
X			return (false);
X	}
X
X	if (!WritePostlude (fWord, paraCount, paraInfo))
X		return (false);
X
X	return (true);
X}
X
X
XTextToWrite ()
X{
XSFReply	inFile;
XSFReply	outFile;
XBoolean	result;
X
X	if (FindEmptyMark ())
X		return;
X
X	if (!GetInputFile ("\pOpen", 'TEXT', &inFile))
X		return;
X	CopyString (inFile.fName, outFile.fName);	/* make default output name */
X	AppendString ("\p.mw", outFile.fName);
X	if (!GetOutputFile (true, outFile.fName, 0, &outFile))
X		return;
X
X	if (!OpenInputFile (&inFile, &fText))
X		return;
X
X	InitTextStream (fText);
X	
X	if (!OpenOutputFile (&outFile, 'MACA', 'WORD', &fWord))
X	{
X		(void) FSClose (fText);
X		return;
X	}
X
X	MeterBegin ();
X	MeterPos (5, 0);
X	MeterString ("\pFormatting:  ");
X	MeterString (inFile.fName);
X	MeterPos (64, 1);
X	MeterString ("\pTo:  ");
X	MeterString (outFile.fName);
X	StartMeterPercentInfo ();
X
X/*
X	Fire up a debug output window if that option is true.  If it's
X	false, then not executing DisplayWindow results in all output calls
X	being ignored. Not as quick as testing them all, but easier.
X	(None of it will be true if compilation has all this stuff turned
X	off, anyway.)
X*/
X
X# ifdef	debug
X	if (debugOut)
X		DisplayWindow (outFile.fName, true);
X	DisplayString ("\pInput file size ");
X	DisplayLong (tFileSize);
X	DisplayLn ();
X# endif
X
X	fmtBuf = (FAHandle) NewHandle (0L);	/* get format array buffer */
X	maxFormats = 0;
X	paraInfo = (PIAHandle) NewHandle (0L);	/* get para info array buffer */
X	maxParas = 0;
X
X	result =  FormatText ();
X	(void) FSClose (fText);
X	(void) FSClose (fWord);
X	(void) FlushVol (fWord, outFile.vRefNum);
X	if (result == false)
X		FSDelete (outFile.fName, outFile.vRefNum);
X
X	DisposHandle (fmtBuf);
X	DisposHandle (paraInfo);
X	MeterEnd ();
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWWindMisc.c
X# include	"MakeWrite.h"
X
X
XWindowPtr	NewDWindow ();
X
Xstatic WindowPtr	meterWind = nil;
Xstatic WindowPtr	helpWind = nil;
Xstatic Integer			errCount;
Xstatic Str255		errWindName;
Xstatic Integer			hPercent;
X
X/* ---------------------------------------------------------------- */
X/*					General Display Window Routines					*/
X/* ---------------------------------------------------------------- */
X
X
Xstatic DWindActivate (active)
XBoolean	active;
X{
XWindowPeek	w;
X
X	if (!active)	/* deactivated - was it closed? */
X	{
X		GetPort (&w);
X		if (w->visible == 0)
X		{
X			SkelRmveWind (w);	/* yes - remove it */
X			if ((WindowPtr) w == helpWind)
X				helpWind = nil;
X		}
X	}
X	FixMenus ();
X}
X
X
X/*
X	Build a display window.  NewDWindow makes it the current output
X	window for display output.  The window comes up in front unless
X	the meter is present, in which case it comes up under the meter.
X*/
X
XDisplayWindow (title, visible)
XStringPtr	title;
XBoolean		visible;
X{
Xregister WindowPtr	w;
XRect				r;
Xstatic Integer			i = 0;
Xregister Integer		h, v;
X
X	if (meterWind != nil && i < 1)
X		i = 1;
X	h = i * 23 + 5;
X	v = h + 65;
X	SetRect (&r, h, v, h + 350, v + 200);
X	SetDWindowNotify (nil, DWindActivate);
X	w = NewDWindow (&r, title, visible, -1L, true, 0L);
X	if (visible)
X		MakeFrontWind (w);
X	if (++i == 4)
X		i = 0;
X}
X
X
X/* ---------------------------------------------------------------- */
X/*						Meter Window Routines						*/
X/* ---------------------------------------------------------------- */
X
X
XMeterPos (h, lineNo)
XInteger		h, lineNo;
X{
X	SetPort (meterWind);
X	MoveTo (h, (Integer) (lineNo * 16 + 14));
X}
X
X
XMeterString (s)
XStringPtr	s;
X{
X	SetPort (meterWind);
X	DrawString (s);
X}
X
X
XMeterInt (i)
XInteger		i;
X{
XStr255	s;
X
X	NumToString ((Integer) i, s);
X	MeterString (s);
X}
X
X
XStartMeterPercentInfo ()
X{
XPenState	p;
X
X	MeterString ("\p     ");
X	GetPenState (&p);
X	hPercent = p.pnLoc.h;
X}
X
X
XSetMeterPercent (i)
XInteger		i;
X{
X	MeterPos (hPercent, 1);
X	MeterInt (i);
X	MeterString ("\p%");
X}
X
X
Xstatic MeterClobber ()
X{
X	DisposeWindow (meterWind);
X	meterWind = nil;
X}
X
X
XMeterBegin ()
X{
XRect	r;
X
X	SetRect (&r, 80, 29, 420, 65);
X	meterWind = NewWindow (nil, &r, "\p", true, dBoxProc, -1L, false, 0L);
X	SkelWindow (meterWind, nil, nil, nil, nil, nil, MeterClobber, nil, false);
X	TextFont (0);
X	TextSize (0);
X	TextMode (srcCopy);
X	MakeFrontWind (meterWind);
X}
X
X
XMeterEnd ()
X{
X	SkelRmveWind (meterWind);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*						Error Window Routines						*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Initialize an error window.  This just clears the error count
X	and sets the name that will be given the window if an error
X	occurs.  The window doesn't actually appear unless the error
X	message routine is called.
X*/
X
XErrWindInit (fName)
XStringPtr	fName;
X{
X	errCount = 0;
X	CopyString (fName, errWindName);
X}
X
X
XErrWindMsge (thing, value)
XStringPtr	thing;
XInteger			value;
X{
X	if (errCount++ == 0)	/* first error */
X	{
X		DisplayWindow (errWindName, true);
X	}
X	DisplayString (thing);
X	DisplayInt (value);
X	DisplayLn ();
X}
X
X
X/* ---------------------------------------------------------------- */
X/*						Help Window Routine							*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Create help window, unless it already exists - in which case 
X	simply pull it to the front.
X*/
X
X
XHelpWindow ()
X{
XRect			r;
Xregister Handle	h;
X
X	if (helpWind == nil)
X	{
X		SetRect (&r, 40, 50, 450, 280);
X		SetDWindowNotify (nil, DWindActivate);
X		helpWind = NewDWindow (&r, "\pInformation Window", false, -1L, true, 0L);
X	
X		h = GetResource ('TEXT', helpTextNum);	/* read help text */
X		HLock (h);							/* lock it and write to window */
X		DisplayText (*h, GetHandleSize (h));
X		HUnlock (h);
X		ReleaseResource (h);			/* done with it, so goodbye */
X		SetDWindowPos (helpWind, 0);	/* scroll back to top */
X		SetDWindow (nil);				/* no more output to this window */
X	}
X	MakeFrontWind (helpWind);
X}
SHAR_EOF
exit
--- end of part 3 ---
Technical Details
Message-ID: <2458@felix.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!water!watnot!watmath!clyde!rutgers!sri-unix!hplabs!pyramid!oliveb!felix!macintosh
References: <2455@felix.UUCP> <2457@felix.UUCP>

Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: arc1-ca.pugleaf.net!utzoo!utgpu!water!watnot!watmath!clyde!rutgers!sri-unix!hplabs!pyramid!oliveb!felix!macintosh
From: macintosh@felix.UUCP
Newsgroups: mod.mac.sources
Subject: MakeWrite Source (part 3 of 3)
Message-ID: <2458@felix.UUCP>
Date: Sun, 22-Mar-87 02:00:06 EST
Article-I.D.: felix.2458
Posted: Sun Mar 22 02:00:06 1987
Date-Received: Mon, 23-Mar-87 01:58:34 EST
References: <2455@felix.UUCP> <2457@felix.UUCP>
Sender: root@felix.UUCP
Reply-To: dubois@uwmacc.UUCP (Paul DuBois)
Organization: UWisconsin-Madison Academic Comp Center
Lines: 1947
Approved: bytebug@felix.UUCP (Roger L. Long)