🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: mod.mac.sources
3 messages
3 total messages Started by macintosh Sat, 21 Mar 1987 07:31
MakeWrite Source (part 1 of 3)
#49
Author: macintosh
Date: Sat, 21 Mar 1987 07:31
2162 lines
53088 bytes
[MakeWrite Source - part 1 of 3]

---
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	MW/ListEdit.h
#	MW/MWFileStuff.h
#	MW/MWMaca.h
#	MW/MWMapInfo.h
#	MW/MachDep.h
#	MW/MakeWrite.h
#	MW/ListEdit.c
#	MW/MWCheckMark.c
#	MW/MWFileStuff.c
sed 's/^X//' << 'SHAR_EOF' > MW/ListEdit.h
X/*
X	ListEdit.h - ListEdit header file
X*/
X
X#ifndef	_ListEdit_
X
X# define	_ListEdit_
X
X
X# ifndef	_MachDep_
X# include	"MachDep.h"
X# endif
X
X
X# ifndef	_ControlMgr_
X# include	<ControlMgr.h>
X# endif
X
X
X# ifndef	nil
X# define	nil		(0L)
X# endif
X
X
X# ifndef	New
X# define	New(x)		(x **) NewHandle ((Size) sizeof (x))
X# endif
X
X
X/*
X	A LineList object consists of the following:
X
X	o	owning port
X	o	scroll bar
X	o	rectangle indicating the text display area
X	o	maximum number of lines
X	o	number of lines visible in text display area
X	o	index of top visible line
X	o	height of each line in the display
X	o	current number of lines
X	o	currently selected line (noLine if none)
X	o	activation state
X	o	number of fields in each line
X	o	array indicating horizontal offset of each field
X	o	array of handles to information for each line.
X
X	Lines are lists of fields.
X	A field consists of a string and a handle to the next field.
X	A LineHandle is equivalent to a FieldHandle because a line is
X	simply a list of fields.
X*/
X
X# define	noLine		(-1)	/* "current line" value of no line selected */
X
X
Xtypedef struct Field
X{
X	Str255			fStr;
X	struct Field	**fNext;
X} Field, **FieldHandle, **LineHandle;
X
X
Xtypedef LineHandle	LineArray[1];
Xtypedef LineArray	**LAHandle;
X
X
Xtypedef struct LineList
X{
X	GrafPtr			port;		/* port                          */
X	ControlHandle	scroll;		/* scroll bar                    */
X	Rect			textRect;	/* text display rectangle        */
X	Integer				maxLines;	/* maximum number of lines       */
X	Integer				visLines;	/* number of visible lines       */
X	Integer				topVisLine;	/* index of top visible line     */
X	Integer				lineHeight;	/* height of each line           */
X	Integer				nLines;		/* number of lines               */
X	Integer				curLine;	/* currently selected line       */
X	Boolean			hilite;		/* whether to hilite             */
X	Integer				nFields;	/* number of fields in each line */
X	Integer				*offset;	/* offsets of each field         */
X	LAHandle		lines;		/* lines in list                 */
X} LineList, *ListPtr;
X
X
X# define	NextField(hField)	((**hField).fNext)
X# define	ListLine(list, line)	((**list->lines)[line])
X
XLineHandle	NewLine ();
XBoolean		InsertLine ();
XBoolean		ListTestScroll ();
XBoolean		ListTestText ();
X
X# endif
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWFileStuff.h
X/*
X	MWFileStuff.h - File operation header file
X*/
X
X
X#ifndef	_MWFileStuff_
X
X# define	_MWFileStuff_
X
X# ifndef	_MacTypes_
X# include	<MacTypes.h>
X# endif
X
X
X# ifndef	_MachDep_
X# include	"MachDep.h"
X# endif
X
X
X# ifndef	nil
X# define	nil		(0L)
X# endif
X
X
X/*
X	Functions returning non-int
X*/
X
XBoolean	GetInputFile ();
XBoolean	OpenInputFile ();
XBoolean	GetOutputFile ();
XBoolean	OpenOutputFile ();
XBoolean	FileRead ();
XBoolean	FileWrite ();
XLongint	FilePos ();
XBoolean	ZeroPad ();
XBoolean ReadString ();
XBoolean WriteString ();
XBoolean ReadInteger ();
XBoolean WriteInteger ();
XBoolean WriteLongint ();
X
X# endif
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMaca.h
X/*
X	MWMaca.h - MacWrite document structures, version 4.5
X	(actually, lots of this is for version 2.2, I was never took it out.)
X
X	The comments below are mostly non-edifying.  A copy of
X	Macintosh Technical Note 12 is a necessity, as it
X	describes document formats in detail.
X
X	One difference is that the "active face" in the window variables
X	is really a point size (high byte) and style (low byte), not just
X	a style.	
X*/
X
X
X# ifndef	_MWMaca_
X# define	_MWMaca_
X
X
X# ifndef	_MacTypes_
X# include	<MacTypes.h>
X# endif
X
X
X# ifndef	_MachDep_
X# include	"MachDep.h"
X# endif
X
X
X# ifndef	nil
X# define	nil		(0L)
X# endif
X
X
X
Xtypedef enum			/* supported versions of MacWrite */
X{
X	version3 = 3,		/* MacWrite 2.2 */
X	version6 = 6		/* MacWrite 4.5 */
X};
X
X
Xtypedef enum			/* document types */
X{
X	mainDoc = 0,
X	headDoc = 1,
X	footDoc = 2
X};
X
X
Xtypedef enum			/* paragraph types */
X{
X	rulerPara = 0,
X	textPara = 1,
X	pictPara = 2
X};
X
X
Xtypedef enum			/* justification types */
X{
X	leftJust = 0,
X	centerJust = 1,
X	rightJust = 2,
X	fillJust = 3
X} Justification;
X
X
X/*
X	Types common to all versions
X*/
X
Xtypedef Byte	ByteBool;		/* byte-size boolean */
Xtypedef Byte	UPrintRec[120];	/* 120-byte universal printing record */
X								/* (anyone know what's in it?) */
X
X
Xtypedef struct Selection
X{
X	Integer		selPara;	/* selection paragraph number */
X	Integer		selPos;		/* selection char position (start or end) */
X} Selection;
X
X
Xtypedef struct ActiveFace
X{
X	Byte		faceSize;	/* point size */
X	Byte		faceStyle;	/* style */
X} ActiveFace;
X
X
Xtypedef struct Format
X{
X	Integer		fmtPos;		/* pos of first char format applies to */
X	Byte		fmtSize;	/* point size */
X	Byte		fmtStyle;	/* style */
X	Integer		fmtFont;	/* font number */
X} Format;
X
Xtypedef Format	FormatArray[1];		/* actually variable length */
Xtypedef FormatArray	**FAHandle;
X
X
Xtypedef struct Ruler
X{
X	Integer			margLeft;	/* left margin */
X	Integer			margRight;	/* right margin */
X	Justification	just;		/* justification */
X	Byte			nTabs;		/* number of tabs */
X	Integer			spacing;	/* line spacing = 1 + (spacing/2) */
X	Integer			indent;		/* indentation of first line */
X	Integer			tab[10];	/* tab values */
X	Byte			fill[4];	/* unused */
X} Ruler;
X
X
X/*
X	MacWrite 2.2 (version number 3) data structures
X*/
X
X
Xtypedef struct Globals3		/* version 2.2 globals */
X{
X	Integer		version;	/* version number (always 3) */
X	Integer		paraOffset;	/* offset to paragraph information */
X	Integer		mainParas;	/* main doc paragraph count */
X	Integer		headParas;	/* header paragraph count */
X	Integer		footParas;	/* footer paragraph count */
X	ByteBool	titlePage;	/* title page flag */
X	Byte		fill[2];	/* unused */
X	ByteBool	showFoot;	/* true if footer displayed */
X	ByteBool	showHead;	/* true if header displayed */
X	ByteBool	showRuler;	/* true if rulers displayed */
X	Integer		activeDoc;	/* active document */
X	Integer		startPage;	/* starting page number */
X} Globals3;
X
X
Xtypedef struct ParaInfo3
X{
X	Integer		paraHeight;	/* height of paragraph (pixels) */
X	Integer		paraPos;	/* position from top of page */
X	Byte		paraPage;	/* page number */
X	Byte		fill[3];	/* unused */
X} ParaInfo3;
X
X
Xtypedef struct Windows3		/* version 2.2 window variables */
X{
X	Selection	selStart;	/* start of selection */
X	Selection	selEnd;		/* end of selection */
X	Integer		vertOffset;	/* vertical offset */
X	Integer		redrawPara;	/* first paragraph to redraw */
X	Point		pageIconPt;	/* page icon position */
X	Point		dateIconPt;	/* date icon position */
X	Point		timeIconPt;	/* time icon position */
X	Byte		fill[4];	/* unused */
X	ByteBool	iconRedraw;	/* true if icons should be redrawn */
X	ByteBool	iconFlag;	/* true if rulers shown when icons last drawn */
X	Integer		activeFont;	/* font active when saved */
X	ActiveFace	activeFace;	/* face active when saved */
X} Windows3;
X
X
Xtypedef struct DocInfo3		/* version 2.2 document information */
X{
X	Globals3	globals3;	/* globals */
X	UPrintRec	uPrintRec;	/* universal printing record */
X	Windows3	mainWind3;	/* main doc window information */
X	Windows3	headWind3;	/* header window information */
X	Windows3	footWind3;	/* footer window information */
X} DocInfo3;
X
X
X/*
X	MacWrite 4.5 (version number 6) data structures
X*/
X
X
Xtypedef struct Globals6		/* version 4.5 globals */
X{
X	Integer		version;	/* version number (always 6) */
X	Integer		mainParas;	/* main doc paragraph count */
X	Integer		headParas;	/* header paragraph count */
X	Integer		footParas;	/* footer paragraph count */
X	ByteBool	titlePage;	/* title page flag */
X	Byte		fill;		/* unused */
X	ByteBool	showScrap;	/* true if scrap displayed */
X	ByteBool	showFoot;	/* true if footer displayed */
X	ByteBool	showHead;	/* true if header displayed */
X	ByteBool	showRuler;	/* true if rulers displayed */
X	Integer		activeDoc;	/* active document */
X	Integer		startPage;	/* starting page number */
X	Longint		freePos;	/* free list position */
X	Integer		freeLen;	/* free list length */
X	Integer		freeAlloc;	/* bytes allocated for free list on disk */
X	Byte		fill2[14];	/* unused */
X} Globals6;
X
X
Xtypedef enum				/* status byte bitmasks */
X{
X	stJustMask = 0x03,		/* justification code */
X	stInUse = 0x04,			/* bit set if paragraph is in use */
X	stCompress = 0x08,		/* bit set if text is compressed */
X	stOnItsWay = 0x10,		/* bit set if disk i/o started, not done */
X	stInMemory = 0x20,		/* bit set if paragraph is in memory */
X	stJustify = 0x40,		/* bit set if just code above used */
X							/* otherwise use ruler */
X	stDirty = 0x80			/* set if paragraph is dirty */
X};
X
X
Xtypedef enum			/* justification codes relating to stJustMask */
X{
X	stJustLeft = 0x00,
X	stJustCenter = 0x01,
X	stJustRight = 0x02,
X	stJustFull = 0x03
X};
X
X
Xtypedef union ParaStOff
X{
X	Byte		paraStatus;	/* paragraph status */
X	Longint		paraOffset;	/* position of paragraph data */
X							/* (low 3 bytes only) */
X} ParaStOff;
X
X
Xtypedef struct ParaInfo6
X{
X	Integer		paraHeight;	/* height of paragraph (pixels) */
X	Integer		paraPos;	/* position from top of page */
X	Longint		paraHandle;	/* handle to paragraph */
X	ParaStOff	paraStOff;	/* data position/status */
X	Integer		paraLen;	/* length of paragraph data */
X	Integer		paraFmts;	/* common formats */
X} ParaInfo6;
X
Xtypedef ParaInfo6	ParaInfoArray6[1];	/* actually variable length */
Xtypedef ParaInfoArray6	**PIAHandle;
X
X
Xtypedef struct Windows6		/* version 4.5 window variables */
X{
X	Selection	selStart;	/* start of selection */
X	Selection	selEnd;		/* end of selection */
X	Integer		vertOffset;	/* vertical offset */
X	Integer		redrawPara;	/* first paragraph to redraw */
X	Longint		infoPos;	/* position of information array */
X	Integer		infoLen;	/* length of information array */
X	Longint		linePos;	/* position of line height array */
X	Integer		lineLen;	/* length of line height array */
X	Point		pageIconPt;	/* page icon position */
X	Point		dateIconPt;	/* date icon position */
X	Point		timeIconPt;	/* time icon position */
X	Byte		fill[4];	/* unused */
X	ByteBool	iconRedraw;	/* true if ovals (icons) should be redrawn */
X	ByteBool	iconFlag;	/* true if rulers shown when ovals last drawn */
X	ActiveFace	activeFace;	/* face active when saved */
X	Integer		activeFont;	/* font active when saved */
X} Windows6;
X
X
Xtypedef struct DocInfo6		/* version 4.5 document information */
X{
X	Globals6	globals6;	/* globals */
X	UPrintRec	uPrintRec;	/* universal printing record */
X	Windows6	footWind6;	/* footer window information */
X	Windows6	headWind6;	/* header window information */
X	Windows6	mainWind6;	/* main doc window information */
X} DocInfo6;
X
X# endif
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMapInfo.h
X/*
X	MapInfo.h - map structures
X*/
X
X#ifndef	_MWMapInfo_
X
X# define	_MWMapInfo_
X
X# ifndef	_MacTypes_
X# include	<MacTypes.h>
X# endif
X
X
X# ifndef	_MachDep_
X# include	"MachDep.h"
X# endif
X
X
X# ifndef	nil
X# define	nil		(0L)
X# endif
X
X
X/*
X	Font chosen is specified by its number in FontMgr.h.  If no font
X	change is specified, use sameFont.
X	Point size is one of 9, 10, 12, 14, 18 or 24, or none.  If no
X	size change is specified, use sameSize.
X*/
X
X# define	sameFont	(-1)
X# define	sameSize	(-1)
X
X
X/*
X	Style word coded as follows:  high bit never used in a legal MacWrite
X	style spec, so it's used to signify "no style change".  If the high
X	bit is set, others can be anything, but are ignored.  If it's clear
X	the others are set according to the style attributes selected.  If
X	no attributes are selected (low 7 bits = 0), that means plain.
X
X	Warning:  these constants are specified for convience in coding,
X	but the values are really hardcoded, since they're sometimes used
X	in non-obvious ways.  See StyleToStr for an example.
X*/
X
Xtypedef enum				/* bits used in style byte */
X{
X							/* 0 = plain */
X	styleBold = 1,			/* boldface */
X	styleItalic = 2,		/* italic */
X	styleUnder = 4,			/* underline */
X	styleOutline = 8,		/* outline */
X	styleShadow = 16,		/* shadow */
X	styleSuper = 32,		/* superscript */
X	styleSub = 64,			/* subscript */
X	sameStyle = 128			/* high bit unused in any legal style, so */
X							/* it's used to signify no style change */
X};
X
X
X/*
X	A map specification consists of the marker string to look for that
X	signals a format change, and the font, size and style combination
X	to be used to effect the change.  It also holds the beginning and
X	end of the selection points for editing the marker.
X*/
X
X# define	maxMarkLen		20	/* max number of chars in a marker */
X
Xtypedef struct
X{
X	StringHandle	mark;		/* marker string */
X	Integer				selStart;	/* selection range in mark string */
X	Integer				selEnd;
X	Integer				font;		/* sameFont if no change specified */
X	Integer				size;		/* sameSize if no change specified */
X	Integer				style;		/* sameStyle if no change specified, */
X								/* 0 if plain, */
X								/* else bits = attributes selected */
X} MapSpec;
X
X
X/*
X	Structure used for holding text representation of
X	map specifications
X*/
X
Xtypedef struct
X{
X	Str255	markStr;
X	Str255	fontStr;
X	Str255	sizeStr;
X	Str255	styleStr;
X} MapStr;
X
X# endif
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MachDep.h
X/*
X	"Machine" dependent stuff.  Integer and Longint should be typedef'd
X	to the compiler's two- and four-byte integer types.  This facilitates
X	conversion to other C compilers.
X*/
X
X
X# ifndef	_MachDep_
X
X# define	_MachDep_
X
Xtypedef short	Integer;			/* 16-bit integer */
Xtypedef long	Longint;			/* 32-bit integer */
X
X# endif
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MakeWrite.h
X# include	"ListEdit.h"
X# include	"MWMapInfo.h"
X
X
X/*
X	# define debug	to enable debug output option
X	# undef  debug	to disable debug output option
X*/
X
X# undef	debug
X
X
X# define	cr		'\r'
X# define	enter	3
X
X
X/*
X	Resource numbers
X*/
X
Xtypedef enum					/* alert/dialog numbers */
X{
X	aboutAlrtNum = 1000,	/* "About FaceLift..." alert */
X	msgeAlrtNum,
X	questAlrtNum,
X	paraDlogNum,
X	conflictAlrtNum,
X	noPeriodAlrtNum,
X	replaceAlrtNum
X};
X
X
Xtypedef enum
X{
X	fileMenuNum = 1000,
X	editMenuNum,
X	specialMenuNum
X};
X
X
Xtypedef enum			/* STR resource numbers */
X{
X	periodStrNum = 1000,	/* default periods list */
X	quoteStrNum				/* default quotes list */
X};
X
X
Xtypedef enum			/* STR# resource numbers */
X{
X	fontStrNum = 1000	/* standard font list */
X};
X
X
X# define	helpTextNum		1000	/* TEXT for help window */
X
X
Xtypedef enum		/* Undo operations */
X{
X	noUndo,			/* = "last op can't be undone" */
X	undoDelete,
X	undoInsert,
X	undoPaste,
X	undoFieldChg,
X	undoTyping,
X	undoMarkerOp
X};
X
X
Xtypedef enum		/* field numbers - don't change */
X{
X	markField = 0,
X	fontField,
X	sizeField,
X	styleField
X};
X
X
X# define	maxMappings	100
X
X# define	extraMarks	2		/* number of special markers */
X
Xtypedef enum					/* special-marker indices */
X{
X	paraMarkIdx = maxMappings,	/* paragraph marker */
X	pageMarkIdx					/* page break marker */
X};
X
X
X/*
X	Paragraph style control
X*/
X
Xtypedef struct
X{
X	Boolean	pEachLine;		/* each line is a paragraph */
X	Boolean	pBlankLine;		/* blank lines are paragraphs */
X	Boolean	pSmartJoin;		/* line-joining smart or not */
X} ParaStyle;
X
X
X# define	mwCreator	'MKWR'	/* map file creator */
X# define	mwType		'MMAP'	/* map file type */
X# define	mapVersion	2		/* current map file structure version */
X
X/*
X	Variable definitions
X*/
X
Xextern WindowPtr	mapWind;
X
Xextern ListPtr	mapList;
Xextern MapSpec	mapSpec[];
X
Xextern Boolean	mapModified;
X
Xextern Integer		undoOp;
Xextern Integer		undoVal;
Xextern Integer		undoPos;
Xextern Integer		undoFieldType;
Xextern MapSpec	undoMSpec;
Xextern Boolean	undoCPMarker;
X
Xextern Boolean	havePasteMSpec;
X
Xextern Boolean	cpMarker;
X
X
Xextern ParaStyle	paraStyle;
Xextern Str255		paraMark;
Xextern Str255		pageMark;
Xextern Str255		periodStr;
Xextern Str255		quoteStr;
X
X# ifdef	debug
Xextern Boolean	debugOut;
X# endif
X
X/*
X	Functions returning non-int
X*/
X
XBoolean SetFontSpec ();
XBoolean	InString ();
XBoolean	InsertMapping ();
XBoolean	EditMarker ();
XBoolean StatMSpec ();
XBoolean	OpenMap ();
XBoolean	AddMap ();
XBoolean	SaveMap ();
XBoolean	MouseClick ();
XBoolean ExpandHandle ();
XBoolean DestroyWarn ();
XBoolean DiscardChanges ();
X
X
XBoolean	WritePrelude ();
XBoolean WritePostlude ();
XBoolean	SetParaInfo ();
X
XBoolean FindEmptyMark ();
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/ListEdit.c
X/*
X	ListEdit.c - LineList manipulations
X
X	The LineList structure is set up to allow an arbitrary number of
X	fields in each line.  Each field contains some text, in string
X	form.  This means that whatever kind of structure underlies the
X	line must be mapped onto the strings externally to the routines
X	in this file.
X
X	All routines that operate on LineList objects assume
X	that there's at least one field in each line.
X*/
X
X# include	"ListEdit.h"
X
X# define	teJustLeft	0
X
X
Xstatic ListPtr	trackList;
Xstatic Integer		trackPart;
X
X
X/* ---------------------------------------------------------------- */
X/*		Line list initialization, line creation and disposal		*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Initialize a line list.  It's assumed that everything that
X	can be statically initialized already has been.  What's done
X	here:
X
X	o	set the port
X	o	create the scroll bar
X	o	get a line list big enough for the given number of lines
X
X	The port must be set before InitList is called, since the control
X	calculations depend on that.
X*/
X
XInitList (theList, maxLines)
Xregister ListPtr	theList;
XInteger					maxLines;
X{
XGrafPtr		curPort;
XRect		r;
XInteger			i;
X
X	theList->lines = (LAHandle) NewHandle (maxLines * sizeof (LineHandle));
X	theList->maxLines = maxLines;
X	theList->hilite = false;
X	r = theList->textRect;
X	r.left = r.right + 1;
X	r.right = r.left + 14;
X	InsetRect (&r, -1, -1);
X	GetPort (&curPort);
X	theList->port = curPort;
X	theList->scroll = NewControl (curPort, &r, "\p", true, 0, 0, 0,
X									scrollBarProc, 0L);
X}
X
X
X/*
X	Create a line for a LineList object.  Must pass the number of
X	fields in a line.  NewLine doesn't know anything about the owner
X	of the line except that.  In particular, it doesn't attach the
X	line to the LineList.
X*/
X
XLineHandle NewLine (nFields)
Xregister Integer		nFields;
X{
Xregister FieldHandle	hField1,
X						hField2 = nil;
X
X	while (nFields-- > 0)
X	{
X		hField1 = New (Field);
X		(**hField1).fStr[0] = 0;
X		(**hField1).fNext = hField2;
X		hField2 = hField1;
X	}
X	return (hField1);
X}
X
X
X/*
X	Dispose of a LineList line.  DisposeLine doesn't know anything
X	about the owner of the line.  In particular, it doesn't detach
X	the line from the LineList.
X
X	The case of theLine = nil is handled w/o special treatment.
X*/
X
XDisposeLine (theList, n)
XListPtr	theList;
XInteger		n;
X{
Xregister FieldHandle	hField1,
X						hField2;
X
X	hField1 = ListLine (theList, n);
X	ListLine (theList, n) = nil;
X	while (hField1 != nil)
X	{
X		hField2 = (**hField1).fNext;
X		DisposHandle (hField1);
X		hField1 = hField2;
X	}
X}
X
X
X/*
X	Set the text of a field
X*/
X
XSetFieldStr (field, str)
Xregister FieldHandle	field;
XStringPtr	str;
X{
X	HLock (field);
X	CopyString (str, (**field).fStr);
X	HUnlock (field);
X}
X
X
X/*
X	Return number of the line in which point is located.  First
X	line is line zero.  This does *not* (and *shouldn't*) check
X	whether the point is actually in the text rectangle.
X*/
X
XFindLine (theList, pt)
Xregister ListPtr	theList;
Xregister Point	pt;
X{
Xregister Integer		i, height;
X
X	height = theList->lineHeight;
X	i = pt.v - theList->textRect.top;
X	if (i < 0)
X		i -= height - 1;		/* so next division works properly */
X	i /= height;
X	return (i + theList->topVisLine);
X}
X
X
X/*
X	Scroll a LineList object absolutely to line n, i.e., so line
X	n is the top visible line.
X	This does not set the current line, since the lists are only
X	scrolled - nothing is actually selected.
X*/
X
XScrollToLine (theList, n)
XListPtr	theList;
Xregister Integer		n;
X{
Xregister Integer		nLines;
Xregister Integer		topLine;
Xregister Integer		bottomLine;
Xregister Integer		visLines;
XInteger		scrollAmt;
XInteger		firstRedraw, redrawCount;
XInteger		scrollFrom;
X
X	nLines = theList->nLines;
X	if (nLines == 0)
X		return;				/* nothing to scroll to */
X
X	topLine = theList->topVisLine;
X	visLines = theList->visLines;
X	bottomLine = topLine + visLines - 1;
X
X/*
X	clip n to range 0..nLines-1
X*/
X	if (n < 0)
X		n = 0;
X	if (n >= nLines)
X		n = nLines - 1;
X	
X/*
X	Determine scroll direction
X*/
X	if (n < topLine)
X		scrollAmt = topLine - n;		/* toward beginning */
X	else if (n > bottomLine)
X		scrollAmt = bottomLine - n;	/* toward end */
X	else
X		scrollAmt = 0;				/* already visible, no scroll */
X
X	if (nLines >= visLines)		/* enough to fill window */
X	{
X		if (nLines - visLines < topLine - scrollAmt)
X			scrollAmt += topLine - (nLines - visLines);
X	}
X
X	if (scrollAmt == 0)
X		return;
X
X/*
X	Figure out if any of the currently visible lines can be reused
X	by ScrollRect'ing them, and how many must be redrawn from scratch.
X	firstRedraw is determined as a number from 0..visLines-1, then
X	converted to an absolute line number.  This is because the value
X	of topLine is volatile; firstRedraw isn't tied to it until it
X	settles down.
X*/
X	if (scrollAmt <= -visLines || scrollAmt >= visLines)
X	{
X		firstRedraw = 0;
X		redrawCount = visLines;
X	}
X	else
X	{
X		if (scrollAmt > 0)
X		{
X			firstRedraw = 0;
X			redrawCount = scrollAmt;
X			scrollFrom = topLine;
X		}
X		else	/* scrollAmt < 0 */
X		{
X			firstRedraw = visLines + scrollAmt;
X			redrawCount = -scrollAmt;
X			scrollFrom = topLine - scrollAmt;
X		}
X/*
X	Don't scrollRect the stuff if not front window - might scroll in
X	background pattern if stuff to be scrolled is under another window.
X*/
X		if (theList->port == FrontWindow ())
X			ScrollListLines (theList, scrollFrom, scrollFrom + scrollAmt);
X		else
X		{
X			firstRedraw = 0;					/* draw from first visible */
X			redrawCount = theList->visLines;	/* and draw all visible */
X		}
X	}
X	theList->topVisLine -= scrollAmt;
X	firstRedraw += theList->topVisLine;
X	DrawListLines (theList, firstRedraw, firstRedraw + redrawCount - 1);
X	ListSetScroll (theList);
X}
X
X
X/*
X	Scroll LineList object up or down n lines.  n < 0 means scroll up
X	(towards beginning).
X*/
X
XListScrollRel (theList, n)
Xregister ListPtr	theList;
Xregister Integer		n;
X{
X	if (n < 0)
X		n += theList->topVisLine;
X	else
X		n += theList->topVisLine + theList->visLines - 1;
X	ScrollToLine (theList, n);
X}
X
X
X/*
X	Set the scroll bar value
X*/
X
XListSetScroll (theList)
XListPtr	theList;
X{
X	SetCtlValue (theList->scroll, theList->topVisLine);
X}
X
X
X/*
X	Set the scroll bar maximum value and highlight appropriately.
X	It unhilited if there aren't enough lines to make the scroll bar
X	necessary, or if the list isn't currently activated.
X*/
X
XListScrollMax (theList)
XListPtr	theList;
X{
XControlHandle	scroll;
Xregister Integer	maxScroll;
X
X	scroll = theList->scroll;
X	maxScroll = theList->nLines - theList->visLines;
X	if (maxScroll <= 0)
X	{
X		maxScroll = 0;
X	}
X	SetCtlMax (scroll, maxScroll);
X	HiliteControl (scroll, maxScroll > 0
X							&& theList->hilite
X							&& theList->port == FrontWindow ()
X							? 0 : 255);
X}
X
X
X/*
X	Select a line in the LineList.  The previous selection is
X	unhighlighted and the new selection is highlighted.
X	Selecting noLine unhilites currently selected line.
X
X	If the list isn't currently activated (hilite = true), just
X	set the curLine field and do nothing.
X
X	Note that InvertLine is smart about ignoring line "noLine" and
X	non-visible lines.
X*/
X
XSelectLine (theList, n)
Xregister ListPtr	theList;
Xregister Integer		n;
X{
Xregister Integer		prevCurLine;
X
X	if (n < 0 || n >= theList->nLines)	/* trim to range */
X		n = noLine;
X
X	prevCurLine = theList->curLine;
X	theList->curLine = n;
X
X	if (theList->hilite && n != prevCurLine)
X	{
X		InvertLine (theList, prevCurLine);	/* turn off previous line */
X		InvertLine (theList, n);			/* turn on new line */
X	}
X}
X
X
X/*
X	ListTestScroll
X	Handle clicks in the scroll bar of a LineList object.  If it returns
X	false, the click was not in the scroll bar, otherwise it was and
X	scrolling has already been handled.
X
X	ListTestText
X	Call this to see if the point was in the text rectangle of a
X	LineList object.  If not, ListTestText returns false.  Otherwise,
X	the line clicked on is highlighted and then the mouse is tracked
X	so that the line the mouse is in is hilited even if the mouse is
X	dragged.  If the mouse is dragged off the top or bottom of the
X	text rectangle, autoscrolling occurs.  If the user clicks or
X	drags below the bottom filled line but still in the text rectangle,
X	the current selection is deselected, but true is still returned.
X*/
X
X
X
Xstatic pascal void TrackScroll (theScroll, partCode)
XControlHandle	theScroll;
XInteger				partCode;
X{
Xregister Integer	lDelta;
X
X    if (partCode == trackPart)			/* still in same part? */
X    {
X        switch (partCode)
X        {
X            case inUpButton: lDelta = -1; break;
X            case inDownButton: lDelta = 1; break;
X            case inPageUp: lDelta = -(trackList->visLines-1); break;
X            case inPageDown: lDelta = trackList->visLines-1; break;
X        }
X		ListScrollRel (trackList, lDelta);
X    }
X}
X
X
X/*
X	Test whether the point lies in theList's scroll bar.  Handle scrolling
X	if so and return true, else return false.
X*/
X
XBoolean ListTestScroll (theList, pt)
XListPtr	theList;
XPoint	pt;
X{
XControlHandle	scrollBar;
XBoolean			result = false;
XInteger				line;
X
X	scrollBar = theList->scroll;
X	if ((trackPart = TestControl (scrollBar, pt)) != 0)
X	{
X		if (trackPart == inThumb)
X		{
X			line = GetCtlValue (scrollBar);
X			if (TrackControl (scrollBar, pt, nil) == inThumb)
X				ListScrollRel (theList, GetCtlValue (scrollBar) - line);
X		}
X		else
X		{
X			trackList = theList;
X			(void) TrackControl (scrollBar, pt, TrackScroll);
X		}
X		result = true;
X	}
X	return (result);
X}
X
X
X/*
X	Test whether the point lies in theList's text rect.  If it does,
X	select the correct line.  Handles autoscrolling when the mouse is
X	dragged outside of the text rectangle.
X*/
X
XBoolean ListTestText (theList, pt)
XListPtr	theList;
XPoint	pt;
X{
XBoolean	result = false;
Xregister Integer		line;
Xregister Integer		topLine;
Xregister Integer		bottomLine;
X
X	if (PtInRect (pt, &theList->textRect))
X	{
X		for (;;)
X		{
X			line = FindLine (theList, pt);
X			topLine = theList->topVisLine;
X			bottomLine = topLine + theList->visLines - 1;
X			if (line < topLine)
X				line = topLine - 1;		/* scroll up one */
X			if (line > bottomLine)
X				line = bottomLine + 1;	/* scroll down one */
X			if (line < 0)
X				line = 0;				/* can only scroll to line zero */
X			if (line > theList->nLines - 1)
X			{
X				if (PtInRect (pt, &theList->textRect))
X					line = noLine;
X				else
X					line = theList->nLines - 1;
X			}
X			SelectLine (theList, line);
X			ScrollToLine (theList, line);
X			if (!StillDown ())
X				break;
X			GetMouse (&pt);
X		}
X		result = true;
X	}
X	return (result);
X}
X
X
X/*
X	Insert a line into a line list at position n.  The line is
X	selected but that doesn't cause it to be scrolled into view.
X	The list is redrawn appropriately, i.e. with hiliting if it's
X	turned on.
X
X	Some intelligence is lacking to handle pathological things, so
X	that, for instance, inserting lines above the top visible line
X	will cause the stuff that's visible to be drawn shoved down a line.
X*/
X
XBoolean InsertLine (theList, theLine, n)
XListPtr		theList;
XLineHandle	theLine;
XInteger			n;
X{
XInteger			i;
XLAHandle	lines;
X
X	SelectLine (theList, noLine);	/* unhilite any previous selection */
X
X	if (n >= theList->maxLines)		/* uh-oh - no more room! */
X	{
X		lines = theList->lines;
X		if (ExpandHandle (lines, 1024L) == false)
X			return (false);			/* can't make room */
X		theList->maxLines = GetHandleSize (lines) / sizeof (LineHandle);
X	}
X
X	for (i = theList->nLines; i > n; --i)	/* make empty slot */
X		ListLine (theList, i) = ListLine (theList, i-1);
X	ListLine (theList, n) = theLine;
X	++theList->nLines;
X	ListScrollMax (theList);
X	DrawListLines (theList, n, n + theList->visLines - 1);
X	/*DrawListLines (theList, n, theList->topVisLine + theList->visLines - 1);*/
X	SelectLine (theList, n);
X	return (true);
X}
X
X
X/*
X	Delete a line from a line list.
X*/
X
XDeleteLine (theList, n)
XListPtr	theList;
XInteger		n;
X{
XInteger		i;
X
X	SelectLine (theList, noLine);		/* unhilite previous selection */
X	DisposeLine (theList, n);			/* toss storage for line */
X	for (i = n; i < theList->nLines - 1; ++i)
X		ListLine (theList, i) = ListLine (theList, i+1);	/* close up gap */
X	--theList->nLines;
X	ListScrollMax (theList);
X	DrawListText (theList);
X	/*ScrollToLine (theList, n);*/
X}
X
X
X/*
X	Paste a new string into one of a line's field.  It's redrawn
X	as well.
X*/
X
XPasteField (theList, lineNo, fieldNo, str)
XListPtr		theList;
XInteger			lineNo;
XInteger			fieldNo;
XStringPtr	str;
X{
XFieldHandle	hField;
XInteger			i = fieldNo;
X
X	hField = ListLine (theList, lineNo);
X	while (i-- > 0)
X		hField = NextField (hField);
X	SetFieldStr (hField, str);
X	DrawField (theList, lineNo, fieldNo);
X}
X
X
X
X/*
X	Paste a line into a line list.  It's redrawn as it's pasted,
X	and if it was the selected line before, is drawn hilited.
X
X	This could all be much smarter (and faster) but I don't care.
X	It works, and the speedup wouldn't be enough to make it worth
X	it.
X*/
X
XPasteLine (theList, theLine, n)
XListPtr		theList;
XLineHandle	theLine;
XInteger			n;
X{
XFieldHandle	hField;
XInteger			i;
X
X	for (i = 0, hField = theLine;
X			hField != nil;
X				hField = NextField (hField), ++i)
X	{
X		HLock (hField);
X		PasteField (theList, n, i, (**hField).fStr);
X		HUnlock (hField);
X	}
X}
X
X
X/*
X	Turn list hiliting on or off.  This also affects the scroll bar.
X*/
X
XListActivate (theList, hilite)
XListPtr	theList;
XBoolean	hilite;
X{
X	if (theList->hilite != hilite)		/* do this only on state change */
X	{
X		theList->hilite = hilite;
X		InvertLine (theList, theList->curLine);
X	}
X	ListScrollMax (theList);
X}
X
X
X/*
X	Toss all the lines of a list and redraw.  This doesn't change
X	the list hiliting state.
X*/
X
XResetList (theList)
XListPtr	theList;
X{
Xregister Integer	i;
X
X	for (i = 0; i < theList->nLines; ++i)
X		DisposeLine (theList, i);
X	theList->nLines = 0;
X	ListScrollMax (theList);
X	ListSetScroll (theList);
X	DrawListText (theList);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*					LineList drawing routines						*/
X/* ---------------------------------------------------------------- */
X
X
X/* ---------------------------------------------------------------- */
X/*	There is some code redundancy among these routines.  The		*/
X/*	redundancy is for the purpose of increasing drawing speed.		*/
X/*	It is necessary to save and restore the port properly.  This	*/
X/*	is only done in the routines where that is really necessary.	*/
X/* ---------------------------------------------------------------- */
X
X
X
X/* ---------------------------------------------------------------- */
X/*					Display area calculations						*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Get the rectangle enclosing the display area for one of the
X	lines.  The line number is an index in the range 0..visLines-1.
X	The left and right boundaries are the same as the general text
X	display rectangle, so only need to adjust top and bottom.
X*/
X
XGetLineRect (r, theList, lineNo)
XRect	*r;
XListPtr	theList;
XInteger		lineNo;
X{
XInteger		height;
X
X	*r = theList->textRect;
X	height = theList->lineHeight;
X	r->top += lineNo * height;
X	r->bottom = r->top + height;
X}
X
X
X/*
X	Get the rectangle enclosing the display area for one of the
X	fields of a line.  The line number is an index in the range
X	0..visLines-1.  The field number is an index in the range
X	0..nFields-1.
X
X	Must offset horizontally to get the absolute window position
X	since the offsets are relative to the text rectangle.
X	Leave one space to account for the separator line to the
X	left of the next field.
X	
X*/
X
XGetFieldRect (r, theList, lineNo, fieldNo)
XRect	*r;
XListPtr	theList;
XInteger		lineNo;
XInteger		fieldNo;
X{
X	GetLineRect (r, theList, lineNo);
X	r->left = theList->offset[fieldNo];
X	r->right = theList->offset[fieldNo + 1] - 1;
X	OffsetRect (r, theList->textRect.left, 0);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*							Drawing routines						*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Scroll the list's text rectangle.  Note that this may not produce
X	the correct effect if the window is not the front window - some
X	of the stuff shifted might not be visible, and when shifted out from
X	under another window, shifts out as the background pattern.
X*/
X
XScrollListLines (theList, from, to)
XListPtr	theList;
XInteger		from, to;
X{
XGrafPtr		curPort;
XRgnHandle	rgn;
X
X	GetPort (&curPort);
X	SetPort (theList->port);
X	rgn = NewRgn ();
X	ScrollRect (&theList->textRect, 0, (to-from) * theList->lineHeight, rgn);
X	DisposeRgn (rgn);
X	SetPort (curPort);
X}
X
X
X/*
X	Check whether a line is currently visible in the list's text
X	rectangle.
X*/
X
XBoolean LineVisible (theList, lineNo)
XListPtr	theList;
XInteger		lineNo;
X{
X	return (lineNo != noLine && lineNo >= theList->topVisLine
X			&& lineNo < theList->topVisLine + theList->visLines);
X}
X
X
X/*
X	Invert a line from a list.  The line number passed is not
X	assumed to be visible.
X
X	This routine will give you trouble if you're not careful!
X*/
X
XInvertLine (theList, lineNo)
XListPtr	theList;
XInteger		lineNo;
X{
XGrafPtr	curPort;
XInteger		i;
XRect	r;
X
X	if (!LineVisible (theList, lineNo))
X			return;
X	GetPort (&curPort);
X	SetPort (theList->port);
X	GetLineRect (&r, theList, lineNo - theList->topVisLine);
X	InvertRect (&r);
X	SetPort (curPort);
X}
X
X
X/*
X	Draw a field from a list.  The line number passed is not assumed to
X	be visible.  If the line doesn't really exist (i.e., lineNo >= nLines)
X	a blank field is drawn.
X*/
X
XDrawField (theList, lineNo, fieldNo)
Xregister ListPtr	theList;
Xregister Integer		lineNo;
XInteger		fieldNo;
X{
XGrafPtr		curPort;
XRect		r;
Xregister FieldHandle	hField;
XBoolean		invert;
XRgnHandle	rgn;
XInteger			textMode;
X
X	if (!LineVisible (theList, lineNo))
X			return;
X
X	GetPort (&curPort);
X	SetPort (theList->port);
X	invert = theList->hilite && (theList->curLine == lineNo);
X	GetFieldRect (&r, theList, lineNo - theList->topVisLine, fieldNo);
X	FillRect (&r, invert ? black : white);
X	if (lineNo < theList->nLines)
X	{
X		hField = ListLine (theList, lineNo);
X		while (fieldNo-- > 0)
X			hField = NextField (hField);
X		rgn = NewRgn ();
X		GetClip (rgn);
X		ClipRect (&r);
X		MoveTo (r.left + 2, r.bottom - 4);
X		textMode = theList->port->txMode;
X		TextMode (invert? srcBic : srcOr);
X		HLock (hField);
X		DrawString ((**hField).fStr);
X		HUnlock (hField);
X		TextMode (textMode);
X		SetClip (rgn);
X		DisposeRgn (rgn);
X	}
X	SetPort (curPort);
X}
X
X
X/*
X	Draw a line from a list.  The line number passed is not assumed to be
X	visible.  If the line doesn't really exist (i.e., lineNo >= nLines)
X	then draw blank fields.
X*/
X
XDrawLine (theList, lineNo)
Xregister ListPtr	theList;
XInteger		lineNo;
X{
XGrafPtr		curPort;
Xregister Integer	i;
Xregister Integer	topLine;
XInteger			top, bottom, left;
XInteger			penMode;
XRect		r;
XFieldHandle	hField;
XBoolean		invert;
X
X	if (!LineVisible (theList, lineNo))
X			return;
X
X	GetPort (&curPort);
X	SetPort (theList->port);
X	topLine = theList->topVisLine;
X	
X	invert = theList->hilite && (lineNo == theList->curLine);
X
X	top = theList->textRect.top + theList->lineHeight * (lineNo - topLine);
X	bottom = top + theList->lineHeight - 1;
X	penMode = theList->port->pnMode;
X	if (invert)
X		PenMode (patBic);
X
X	for (i = 0; i < theList->nFields; ++i)
X	{
X		DrawField (theList, lineNo, i);
X		if (i > 0)
X		{
X			left = theList->textRect.left + theList->offset[i] - 1;
X			MoveTo (left, top);
X			LineTo (left, bottom);
X		}
X	}
X
X	PenMode (penMode);
X	SetPort (curPort);
X}
X
X
XDrawListLines (theList, from, to)
Xregister ListPtr	theList;
Xregister Integer		from, to;
X{
Xregister Integer		i;
X
X	for (i = from;  i <= to; ++i)
X	{
X		DrawLine (theList, i);
X	}
X}
X
X
XDrawListText (theList)
Xregister ListPtr	theList;
X{
X	DrawListLines (theList, theList->topVisLine,
X					theList->topVisLine + theList->visLines - 1);
X}
X
X
XDrawListFrame (theList)
Xregister ListPtr	theList;
X{
XGrafPtr	curPort;
XRect	r;
Xregister Integer		i;
Xregister Integer		offset;
X
X	GetPort (&curPort);
X	SetPort (theList->port);
X	r = theList->textRect;
X	InsetRect (&r, -1, -1);
X	FrameRect (&r);
X	InsetRect (&r, 1, 1);
X
X/*
X	Draw separator lines.  These are drawn one pixel to the left of
X	the field area.
X*/
X
X	for (i = 1; i < theList->nFields; ++i)
X	{
X		offset = r.left + theList->offset[i] - 1;
X		MoveTo (offset, r.top);
X		LineTo (offset, r.bottom);
X	}
X	SetPort (curPort);
X}
X
X
X/*
X	Redraw the list.  Set the control hiliting value to its current
X	value to redraw it.  Draw the text area frame (including field
X	separating bars), then draw all the visible lines.
X*/
X
XDrawList (theList)
Xregister ListPtr	theList;
X{
XControlHandle	scroll;
X
X	scroll = theList->scroll;
X	HiliteControl (scroll, (**scroll).contrlHilite);
X	DrawListFrame (theList);
X	DrawListText (theList);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWCheckMark.c
X# include	"MakeWrite.h"
X
X
X/*
X	markRes holds the result, for each map line, of the current match
X	state.  Element i is true if mark i still matches the input, false
X	if not.
X
X	markRes is big enough to hold one entry for each formatting
X	specification, plus one entry for each special marker.  The special
X	marks must generally be special-cased.
X	
X	Right now there's two special marks - the paragraph indicator
X	mark and the page break.
X
X	markPos is the position in the marks that the current input char is
X	matched against.
X*/
X
X# define	maxMarkers	(maxMappings + extraMarks)
X
X
Xstatic Boolean		markRes[maxMarkers];
Xstatic Integer			markPos;
X
X
X/*
X	Look for marks that are empty.  This is done before any text->write
X	conversion because empty marks are illegal.
X
X	Return false if no empty marks, otherwise true.
X	
X	No check on the paragraph marker:  that's handled by the paragraph
X	style dialog.
X*/
X
XBoolean FindEmptyMark ()
X{
Xregister Integer	i;
X
X	for (i = 0; i < mapList->nLines; ++i)
X	{
X		if ((*mapSpec[i].mark)[0] == 0)
X		{
X			SelectMapping (i);
X			Message1 ("\pCan't have empty format markers");
X			return (true);
X		}
X	}
X	return (false);
X}
X
X
X/*
X	Initialize all the used mark states (every mark eligible) and
X	reset the mark position
X*/
X
XInitMarkStates ()
X{
Xregister Integer	i;
X
X	markPos = 0;
X	for (i = 0; i < mapList->nLines; ++i)
X		markRes[i] = true;
X	for (i = maxMappings; i < maxMarkers; ++i)
X		markRes[i] = true;
X}
X
X
X/*
X	Check current input character against the current mark position
X	of each of the marks that are still in the running for a match.
X	Eliminate those that don't match the char.  For those that do,
X	if the entire mark has been matched, then it's a hit, and the format
X	of the input should be changed to that of the format corresponding
X	to the mark.
X
X	Return -2 if no more marks are in the running, -1 if any marks
X	are still in the running but none have been matched completely,
X	otherwise return the index of the completely matched mark.
X
X	Check format markers first, then paragraph marker (if one is being
X	used).
X*/
X
XCheckMarkers (c)
Xchar	c;
X{
Xregister Integer			i;
Xregister Integer			count = 0;	/* number of matches */
Xregister StringHandle	hStr;
X
X	++markPos;						/* advance to next marker position */
X	for (i = 0; i < mapList->nLines; ++i)
X	{
X		if (markRes[i])				/* if mark still in running */
X		{
X			hStr = mapSpec[i].mark;
X			if (c != (*hStr)[markPos])
X				markRes[i] = false;	/* this one's eliminated now */
X			else
X			{						/* this one still matches -- */
X				++count;			/* has the end been reached? */
X				if (markPos == (*hStr)[0])
X					return (i);		/* yes */
X			}
X		}
X	}
X
X/*
X	Check special marks:  paragraph and page break
X*/
X	if (paraMark[0] > 0 && markRes[paraMarkIdx])
X	{
X	 	if (c != paraMark[markPos])
X	 		markRes[paraMarkIdx] = false;
X	 	else
X		{
X			++count;
X			if (markPos == paraMark[0])
X				return (paraMarkIdx);
X		}
X	}
X
X	if (pageMark[0] > 0 && markRes[pageMarkIdx])
X	{
X	 	if (c != pageMark[markPos])
X	 		markRes[pageMarkIdx] = false;
X	 	else
X		{
X			++count;
X			if (markPos == paraMark[0])
X				return (pageMarkIdx);
X		}
X	}
X
X	return (count > 0 ? -1 : -2);
X}
X
X
X/*
X	Check two markers.  If one is a prefix of the other, put up a
X	warning.  Return false if the user says not to continue.  If the
X	user says to continue, or there's no conflict, return true.
X*/
X
Xstatic Boolean ConflictCheck (s1, s2, type1, type2)
XStringPtr	s1, s2, type1, type2;
X{
Xregister Integer	i, len;
X
X	len = s1[0];
X	if (s2[0] < len)
X		len = s2[0];
X	for (i = 1; i <= len; ++i)
X	{
X		if (s1[i] != s2[i])
X			return (true);		/* not a prefix - continue */
X	}
X	ParamText (type1, s1, type2, s2);
X	return (Alert (conflictAlrtNum, nil) == 1);
X}
X
X
X/*
X	Find conflicts among the set of markers
X*/
X
XFindConflicts ()
X{
Xregister Integer			i, j;
Xregister StringHandle	h1, h2;
Xregister Boolean		loop = true;
X
X	for (i = 0; loop && i < mapList->nLines; ++i)
X	{
X		h1 = mapSpec[i].mark;
X		HLock (h1);
X		for (j = i + 1; loop && j < mapList->nLines; ++j)
X		{
X			h2 = mapSpec[j].mark;
X			HLock (h2);
X			loop = ConflictCheck (*h1, *h2, "\pformat", "\pformat");
X			HUnlock (h2);
X		}
X		if (loop && paraMark[0] > 0)
X			loop = ConflictCheck (*h1, paraMark, "\pformat", "\pparagraph");
X		if (loop && pageMark[0] > 0)
X			loop = ConflictCheck (*h1, pageMark, "\pformat", "\ppage break");
X		if (loop && paraMark[0] > 0 && pageMark[0] > 0)
X			loop = ConflictCheck (paraMark, pageMark, "\pparagraph", "\ppage break");
X		HUnlock (h1);
X	}
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWFileStuff.c
X/*
X	MWFileStuff.c - file routines of general usefulness.
X*/
X
X
X# include	"MWFileStuff.h"
X# include	"MWMaca.h"
X# include	<FileMgr.h>
X# include	<StdFilePkg.h>
X# include	<ToolboxUtil.h>
X
X
X/* ---------------------------------------------------------------- */
X/*					Generic Error Message Routine					*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	If errNo isn't noErr, then print a message.  The message is found
X	in the 'STR ' resource of the same number as the file err.  If
X	no resource is found with that number, use a default message.
X*/
X
XFileErr (errNo)
XOSErr		errNo;
X{
Xregister StringHandle	h;
XStr255					numStr;
XStr255					meaning;
X
X	if (errNo == noErr)
X		return;
X
X	CopyString ("\pNo error message available", meaning);	/* default */
X
X	h = GetString (errNo);
X	if (h != nil && HomeResFile (h) == CurResFile ())
X	{
X		HLock (h);
X		CopyString (*h, meaning);
X		HUnlock (h);
X		ReleaseResource (h);
X	}
X
X	NumToString ((Longint) errNo, numStr);
X	Message ("\pI/O error ", numStr, "\p: ", meaning);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*			Routines to get or open files for input or output		*/
X/* ---------------------------------------------------------------- */
X
X
Xstatic Point	dlogWhere = { 70, 100 };	/* Get/PutFile dlog location */
Xstatic Str255	buttonTitle;				/* "Open" button title */
X
X
X/*
X	GFFilter is a SFGetFile filter to set the name of the "Open"
X	button.
X*/
X
Xtypedef	Ptr	DialogPtr;		/* not right, but... */
X
Xstatic pascal Integer GFFilter (theItem, theDialog)
XInteger			theItem;
XDialogPtr	theDialog;
X{
XInteger		itemNo;
XInteger		itemType;
XHandle	itemHandle;
XRect	r;
X
X	if (theItem == -1)	/* change "Open" button name */
X	{
X		GetDItem (theDialog, 1, &itemType, &itemHandle, &r);
X		SetCTitle (itemHandle, buttonTitle);
X	}
X	return (theItem);
X}
X
X
X/*
X	Get a filename for input.
X*/
X
XBoolean GetInputFile (bTitle, type, inFile)
XStringPtr	bTitle;
XOSType		type;
XSFReply		*inFile;
X{
X	CopyString (bTitle, buttonTitle);	/* set title for "Open" button */
X	SFGetFile (dlogWhere, "\p", nil, 1, &type, GFFilter, inFile);
X	DoUpdates ();
X	return (inFile->good);
X}
X
X
X/*
X	Open a filename for input.
X*/
X
XBoolean OpenInputFile (inFile, f)
XSFReply		*inFile;
XInteger			*f;
X{
XOSErr		result;
X
X	result = FSOpen (inFile->fName, inFile->vRefNum, f);
X	if (result != noErr)
X	{
X		FileErr (result);
X		Message3 ("\pCannot open \"", inFile->fName, "\p\".");
X	}
X	return (result == noErr);
X}
X
X
X/*
X	Get a filename for output.
X	Pass the current name and volume reference, and whether to
X	ask for a name even if one is known.  Return the information
X	in the SFReply record.
X
X	Note: if ask is false and the name isn't "Untitled", the name
X	passed is assumed to be the correct name to use and is returned.
X	This may seem odd, but eliminates making the check every place
X	from which this is called.
X*/
X
XBoolean GetOutputFile (ask, fName, vRefNum, outFile)
XBoolean		ask;
XStringPtr	fName;
XInteger			vRefNum;
XSFReply		*outFile;
X{
X	CopyString (fName, outFile->fName);
X	outFile->vRefNum = vRefNum;
X	if (ask || CompareString ("\pUntitled", fName) == 0)
X	{
X		SFPutFile (dlogWhere, "\pWrite to...", fName, nil, outFile);
X		DoUpdates ();
X		if (!outFile->good)
X			return (false);
X	}
X	return (true);
X}
X
X
X/*
X	Open output file, creating if necessary.  Truncate contents as well.
X*/
X
XBoolean OpenOutputFile (outFile, creator, type, f)
Xregister SFReply		*outFile;
XOSType		creator;
XOSType		type;
XInteger			*f;
X{
XFInfo	fndrInfo;
XOSErr	result;
X
X	if (GetFInfo (outFile->fName, outFile->vRefNum, &fndrInfo) == noErr)
X	{
X		if (fndrInfo.fdCreator != creator || fndrInfo.fdType != type)
X		{
X			Message3 ("\p\"", outFile->fName, "\p\" is not a file of the proper type");
X			return (false);
X		}
X	}
X	else	/* Doesn't exist.  Try to create it. */
X	{
X		result = Create (outFile->fName, outFile->vRefNum, creator, type);
X		if (result != noErr)
X		{
X			FileErr (result);
X			Message3 ("\pCan't create \"", outFile->fName, "\p\"");
X			return (false);
X		}
X		else				/* new file now - set Finder info */
X		{
X			(void) GetFInfo (outFile->fName, outFile->vRefNum, &fndrInfo);
X			fndrInfo.fdFlags &= ~1;		/* clear init'ed bit */
X			fndrInfo.fdLocation.h = 0;
X			fndrInfo.fdLocation.v = 0;
X			fndrInfo.fdFldr = 0;
X			(void) SetFInfo (outFile->fName, outFile->vRefNum, &fndrInfo);
X		}
X	}
X
X	result = FSOpen (outFile->fName, outFile->vRefNum, f);
X	if (result != noErr)
X	{
X		FileErr (result);
X		Message3 ("\pCan't write to \"", outFile->fName, "\p\".");
X	}
X	else
X		(void) SetEOF (*f, 0L);	/* clear contents */
X
X	return (result == noErr);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*					Seek, Read, Write on open files					*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Seek to given position in file
X*/
X
XFileSeek (f, pos)
XInteger		f;
XLongint	pos;
X{
X	(void) SetFPos (f, fsFromStart, pos);
X}
X
X
X/*
X	Return current file position
X*/
X
XLongint FilePos (f)
XInteger		f;
X{
XLongint	pos;
X
X	(void) GetFPos (f, &pos);
X	return (pos);
X}
X
X
X/*
X	Read the given number of bytes from a file.  Return false
X	if fail.  Note that false is returned if something is read, but
X	not the full amount, thus the caller should know exactly how
X	much to read when close to the end of the file.
X*/
X
XBoolean FileRead (f, p, amount)
XInteger		f;
XPtr		p;
XLongint	amount;
X{
XOSErr	result;
XLongint	read;
XBoolean	ok = false;
X
X	read = amount;
X	if ((result = FSRead (f, &read, p)) != noErr && result != eofErr)
X		FileErr (result);
X	else
X		ok = (amount == read);
X	return (ok);
X}
X
X
X/*
X	Write the given number of bytes from a file.  Return false
X	if fail.
X*/
X
XBoolean FileWrite (f, p, amount)
XInteger		f;
XPtr		p;
XLongint	amount;
X{ 
XOSErr	result;
XLongint	written;
XBoolean	ok = false;
X
X	written = amount;
X	if ((result = FSWrite (f, &written, p)) != noErr)
X		FileErr (result);
X	else if (amount != written)
X		Message1 ("\pIncomplete write operation");
X	else
X		ok = true;
X	return (ok);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*						Read, Write on data types					*/
X/* ---------------------------------------------------------------- */
X
X
XBoolean ReadInteger (f, val)
XInteger		f;
XInteger	*val;
X{
X	return (FileRead (f, val, (Longint) sizeof (Integer)));
X}
X
X
XBoolean WriteInteger (f, val)
XInteger		f;
XInteger	val;
X{
X	return (FileWrite (f, &val, (Longint) sizeof (Integer)));
X}
X
X
XBoolean WriteLongint (f, val)
XInteger		f;
XLongint	val;
X{
X	return (FileWrite (f, &val, (Longint) sizeof (Longint)));
X}
X
X
XBoolean WriteString (f, s)
XInteger			f;
XStringPtr	s;
X{
X	return (FileWrite (f, s, (Longint) (s[0] + 1)));
X}
X
X
XBoolean ReadString (f, s)
XInteger			f;
XStringPtr	s;
X{
X	return (FileRead (f, s, 1L) && FileRead (f, s + 1, (Longint) s[0]));
X}
X
X
X/*
X	Write n zero bytes, and make sure the file position ends up on
X	a word boundary (by writing an extra zero byte if necessary).
X	ZeroPad (0) to just align the boundary.
X	Return false if file error.
X*/
X
XBoolean ZeroPad (f, n)
XInteger		f;
XInteger		n;
X{
Xchar	c = 0;
X
X	if ((FilePos (f) + n) % 2 != 0)		/* write enough to align on boundary */
X		++n;
X	while (n-- > 0)
X	{
X		if (!FileWrite (f, &c, 1L))
X			return (false);
X	}
X	return (true);
X}
SHAR_EOF
exit
--- end of part 1 ---
MakeWrite Source (part 2 of 3)
#50
Author: macintosh
Date: Sat, 21 Mar 1987 19:00
2483 lines
57060 bytes
[MakeWrite Source - part 2 of 3]

---
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	MW/MWFontOps.c
#	MW/MWGen.c
#	MW/MWIO.c
#	MW/MWMSpecOps.c
#	MW/MWMain.c
#	MW/MWMapOps.c
#	MW/MWMapWind.c
sed 's/^X//' << 'SHAR_EOF' > MW/MWFontOps.c
X# include	"MakeWrite.h"
X# define	applFont	1
X
X
X/*
X	Query user whether to replace the current font list with the
X	selected font, or just add them to the list.  Return false if
X	Cancel clicked.  If Replace clicked, then warn user that the
X	map will be destroyed (if it has been changed) and return false
X	if he declines.  Otherwise return true.
X	
X	If Replace is selected, then the map and the font list are
X	cleared as well as setting some state variables.  The map is
X	really modified by clearing it, but that was ok'd by user, so is
X	now considered clean (unmodified) - just like after New Map.
X*/
X
Xstatic Boolean ReplaceOrAdd ()
X{
Xtypedef enum	/* alert button numbers */
X{
X	cancel = 1,
X	add,
X	replace
X};
Xregister Integer	i;
X
X	i = Alert (replaceAlrtNum, nil);
X	DoUpdates ();
X
X	if (i == cancel)
X		return (false);
X
X	if (i == replace)
X	{
X		if (!DestroyWarn ())
X			return (false);
X		ClobberMap ();
X		ClearMapName ();
X		ResetFontList ();
X		mapModified = false;
X		undoOp = noUndo;
X	}
X	return (true);
X}
X
X
X/*
X	Add the names of the FONT resources in the open resource files
X	to the font list (or replace the list with those fonts).
X
X	Not all FONT resources have a name, so check it first.  This could
X	equally well be done by using only those FONT resources corresponding
X	to a point size of zero (bits 0-6 of the resource id equal to zero).
X*/
X
XResourceFonts (ask)
XBoolean	ask;
X{
XHandle			h;
Xregister Integer	i;
XInteger				fNum, nFonts;
XInteger				resId;
XResType			resType;
XStr255			resName;
X
X	if (ask)
X	{
X		if (ReplaceOrAdd () == false)
X			return;
X	}
X
X	nFonts = CountResources ('FONT');
X	SetResLoad (false);
X	for (i = 1; i <= nFonts; ++i)
X	{
X		h = GetIndResource ('FONT', i);
X		GetResInfo (h, &resId, &resType, &resName);
X		if (resName[0] != 0)	/* not all font resources have names! */
X		{
X			GetFNum (resName, &fNum);
X			if (!SetFontSpec (fNum, resName))
X				break;
X		}
X	}
X	SetResLoad (true);
X	SyncFontSpecs ();
X}
X
X
X/*
X	Add the fonts contained in the STR# whose id is  fontStrNum
X	to the font list (or replace the list with those fonts).
X*/
X
XStrFonts (ask)
XBoolean	ask;
X{
XHandle			h;
Xregister Integer	i, j, len;
XInteger				nStrings;
XStr255			s;
XLongint			fNum;
X
X	if (ask)
X	{
X		if (ReplaceOrAdd () == false)
X			return;
X	}
X
X	h = GetResource ('STR#', fontStrNum);
X	nStrings = * (Integer *) *h;
X
X	for (i = 0; i < nStrings; ++i)
X	{
X		GetIndString (s, fontStrNum, i + 1);
X		if (s[1] == '#')
X			continue;			/* comment - ignore */
X		len = s[0];
X		j = 1;
X		while (j <= len && s[j] != '/')
X			++j;
X		if (j > len)	/* error */
X		{
X			NumToString ((Longint) fontStrNum, s);
X			Message3 ("\pA font list resource (STR# ", s,
X						"\p) is messed up.");
X			break;
X		}
X		s[0] = j - 1;	/* length of numeric part */
X		StringToNum (s, &fNum);
X		s[j] = len - j;
X		if (!SetFontSpec ((Integer) fNum, &s[j]))
X			break;
X	}
X	ReleaseResource (h);
X	SyncFontSpecs ();
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWGen.c
X# include	"MWMaca.h"
X# include	"MWFileStuff.h"
X
X
X/*
X	Prototype for data of empty paragraph
X*/
X
Xtypedef struct EmptyParaData6
X{
X	Integer	pTextLen;
X	Integer	pFmtLen;
X	Format	pFormat;
X} EmptyParaData6;
X
X
XEmptyParaData6	emptyParaData =
X{
X	0,								/* text length = 0 (no text) */
X	6,								/* format data length (1 format) */
X	{ 0, 12, 0, 1}					/* format: pos 0, size 12, style */
X									/* plain, application font */
X};
X
X
XUPrintRec	uPrintRec;	/* not initialized - doesn't matter? */
X
X
XRuler	stdRuler =
X{
X	10,								/* left margin */
X	480,							/* right margin */
X	leftJust,						/* justification */
X	10,								/* number of tabs */
X	0,								/* line spacing = single */
X	10,								/* indentation of first line */
X	{ 40, 80, 120, 160, 200,		/* tab values */
X	  240, 280, 320, 360, 400 },	/* tab values */
X	{ 0, 0, 0, 0 }					/* four bytes fill */
X};
X
X
X
XGlobals6	globals =
X{
X	6,								/* MacWrite 4.5 = version 6 */
X	0,								/* main doc para count - fill in later */
X	2,								/* header para count */
X									/* (one ruler + 1 empty text para) */
X	2,								/* footer para count */
X									/* (one ruler + 1 empty text para) */
X	0,								/* title page flag */
X	0,								/* unused */
X	0,								/* scrap not displayed */
X	0,								/* footer not displayed */
X	0,								/* header not displayed */
X	0,								/* rulers displayed */
X	-1,								/* active document: -1 tells MacWrite */
X									/* to recalc display information */
X	1,								/* starting page = 1 */
X	0L,								/* free list position - fill in later */
X	8,								/* free list length */
X	8,								/* # bytes allocated for list */
X	{ 0, 0, 0, 0, 0, 0, 0,			/* unused */
X	  0, 0, 0, 0, 0, 0, 0 }			/* unused */
X};
X
X
XWindows6	windowVars =
X{
X	{ 1, 0 },						/* start of selection (para 1, char 0) */
X	{ 1, 0 },						/* end of selection (para 1, char 0) */
X	0,								/* vertical offset */
X	0,								/* first paragraph to redraw */
X	0L,								/* position of information array */
X									/* (filled in later) */
X	0,								/* length of information array */
X									/* (filled in later) */
X	0L,								/* position of line height array */
X									/* (filled in later) */
X	0,								/* length of line height array */
X									/* (filled in later) */
X	{ -14, 30 },					/* page icon position */
X	{ -14, 236 },					/* date icon position */
X	{ -14, 442 },					/* time icon position */
X	{ -1, -1, -1, -1 },				/* four bytes fill */
X	-1,								/* redraw ovals (icons) */
X	0,								/* don't redraw rulers */
X	{ -1, -1 },						/* face active when saved */
X									/* (-1 = "has never been set") */
X	-1								/* font active when saved */
X									/* (-1 = "has never been set") */
X};
X
X
XParaInfo6	rulerParaInfo;
XParaInfo6	nullTextParaInfo;
X
X
XBoolean SetParaInfo (p, height, status, dataPos, dataLen, comFormats)
Xregister ParaInfo6	*p;
XInteger			height;
XByte		status;
XLongint		dataPos;
XInteger			dataLen;
XInteger			comFormats;
X{
X
X# ifdef	debug
X	DisplayString ("\p{SetParaInfo}");
X# endif
X
X	p->paraHeight = height;
X	p->paraPos = 0;
X	p->paraHandle = nil;
X	p->paraStOff.paraOffset = dataPos;		/* this first */
X	p->paraStOff.paraStatus = status;		/* *then* this! */
X	p->paraLen = dataLen;
X	p->paraFmts = comFormats;
X
X	return (true);
X}
X
X
X/*
X	Write file prelude, using prototype structures.
X		Global variables
X		Universal print record
X		Footer document variables
X		Header document variables
X		Main document varables
X
X	Some of these will be patched in the postlude.
X
X	Also write as much of the invariant file contents as possible:
X		Footer document contents (1 ruler + 1 empty text paragraph)
X		Header document contents (1 ruler + 1 empty text paragraph)
X		Initial ruler of main document
X*/
X
XBoolean WritePrelude (f)
Xregister Integer	f;
X{
X
X	return (FileWrite (f, &globals, (Longint) sizeof (Globals6))
X		&& FileWrite (f, &uPrintRec, (Longint) sizeof (UPrintRec))
X		&& FileWrite (f, &windowVars, (Longint) sizeof (Windows6))
X		&& FileWrite (f, &windowVars, (Longint) sizeof (Windows6))
X		&& FileWrite (f, &windowVars, (Longint) sizeof (Windows6))
X		&& ZeroPad (f, 6)
X		&& FileWrite (f, &stdRuler, (Longint) sizeof (Ruler))
X		&& FileWrite (f, &emptyParaData, (Longint) sizeof (EmptyParaData6))
X		&& FileWrite (f, &stdRuler, (Longint) sizeof (Ruler))
X		&& FileWrite (f, &emptyParaData, (Longint) sizeof (EmptyParaData6))
X		&& FileWrite (f, &stdRuler, (Longint) sizeof (Ruler))
X	);
X}
X
X
X/*
X	Write line height array, one entry for each paragraph.  First
X	para is always a ruler - write a zero word.  Other paras are
X	faked by writing information that there's one line in the para
X	of height 16 (12-point height).  MacWrite will fix when it reads
X	the file.
X
X	paraCount assumed >= 2.
X*/
X
XBoolean WriteLineHeights (f, paraCount)
XInteger		f;
XInteger	paraCount;
X{
X
X	if (!WriteInteger (f, 0))
X		return (false);
X
X	while (--paraCount > 0)
X	{
X		if (!WriteLongint (f, 0x00011010))
X			return (false);
X	}
X	
X	return (true);
X}
X
X
X/*
X	Write line height and paragraph info positions and lengths
X*/
X
XBoolean WriteArrayInfo (f, seek, piPos, piLen, lhPos, lhLen)
XInteger		f;
XLongint	seek;
XLongint	piPos;
XInteger	piLen;
XLongint	lhPos;
XInteger	lhLen;
X{
X
X	FileSeek (f, seek);
X	return (WriteLongint (f, piPos) && WriteInteger (f, piLen)
X			&& WriteLongint (f, lhPos) && WriteInteger (f, lhLen));
X}
X
X
X/*
X	Paragraph data are all written now.  The line height and paragraph
X	info arrays must now be written, as well as an empty free list.
X	Save the positions of these arrays, as they must be patched into
X	the window variables.
X
X	The paraCount and paraInfo are for the text paragraphs only.
X	When the main document paragraph count and paragraph information
X	are length are patched into the globals, increment to take
X	into account the initial ruler (written during prelude).
X*/
X
XBoolean WritePostlude (f, paraCount, paraInfo)
Xregister Integer	f;
XInteger		paraCount;
XPIAHandle	paraInfo;
X{
XLongint	fLHPos, fPIPos;		/* footer line height, para info array pos */
XLongint	hLHPos, hPIPos;		/* header line height, para info array pos */
XLongint	mLHPos, mPIPos;		/* main line height, para info array pos */
XInteger	paraInfoLen;		/* length of main para info array */
XInteger	defInfoLen;			/* length of header, footer pi array */
XInteger	defLHLen;			/* length of header, footer line height array */
XInteger	mainLHLen;			/* length of main line height array */
XLongint	freeListPos;		/* free list pos */
XBoolean	result;
X
X/*
X	Set up prototype ruler paragraph and null text paragraph
X	information array elements.  The position field must be filled
X	in on a per-window basis.
X*/
X
X	SetParaInfo (&rulerParaInfo, 0, 0, (Longint) 0x130, 34, 0);
X	SetParaInfo (&nullTextParaInfo, 16, 0, (Longint) 0x152, 10, 0);
X
X/*
X	For footer
X*/
X
X	fLHPos = FilePos (f);
X	if (!WriteLineHeights (f, 2))
X		return (false);
X
X	fPIPos = FilePos (f);
X	if (!FileWrite (f, &rulerParaInfo, (Longint) sizeof (ParaInfo6))
X		|| !FileWrite (f, &nullTextParaInfo, (Longint) sizeof (ParaInfo6)))
X			return (false);
X
X/*
X	For header
X*/
X
X	hLHPos = FilePos (f);
X	if (!WriteLineHeights (f, 2))
X		return (false);
X
X	rulerParaInfo.paraStOff.paraOffset += sizeof (Ruler) + sizeof (EmptyParaData6);
X	nullTextParaInfo.paraStOff.paraOffset += sizeof (Ruler) + sizeof (EmptyParaData6);
X
X	hPIPos = FilePos (f);
X
X	if (!FileWrite (f, &rulerParaInfo, (Longint) sizeof (ParaInfo6))
X		|| !FileWrite (f, &nullTextParaInfo, (Longint) sizeof (ParaInfo6)))
X			return (false);
X
X/*
X	For main
X*/
X
X	mLHPos = FilePos (f);
X	if (!WriteLineHeights (f, paraCount + 1))
X		return (false);
X
X	rulerParaInfo.paraStOff.paraOffset += sizeof (Ruler) + sizeof (EmptyParaData6);
X
X	mPIPos = FilePos (f);
X
X	if (!FileWrite (f, &rulerParaInfo, (Longint) sizeof (ParaInfo6)))
X		return (false);
X
X	paraInfoLen = paraCount * sizeof (ParaInfo6);
X	HLock (paraInfo);
X	result = FileWrite (f, *paraInfo, (Longint) paraInfoLen);
X	HUnlock (paraInfo);
X	if (!result)
X		return (false);
X
X/*
X	Write free list.  It's at the end of the file, so set the
X	file EOF here, too.
X*/
X
X	freeListPos = FilePos (f);
X	if (!WriteLongint (f, freeListPos + 8) || !WriteLongint (f, 0L))
X		return (false);
X
X	(void) SetEOF (f, FilePos (f));
X
X/*
X	Now patch  globals and window variables:
X		main doc para count (increment to account for ruler)
X		free list position
X		line height and para info array positions (and para info array
X		length for main document)
X*/
X
X	FileSeek (f, 2L);
X	++paraCount;
X	paraInfoLen += sizeof (ParaInfo6);
X	if (!WriteInteger (f, paraCount))
X		return (false);
X	FileSeek (f, 18L);
X	if (!WriteLongint (f, freeListPos))
X		return (false);
X
X	defInfoLen = 2 * sizeof (ParaInfo6);
X	defLHLen = 3 * sizeof (Integer);
X	mainLHLen = sizeof (Integer) + (paraCount-1) * sizeof (Longint);
X	if (!WriteArrayInfo (f, 172L, fPIPos, defInfoLen, fLHPos, defLHLen)
X		|| !WriteArrayInfo (f, 218L, hPIPos, defInfoLen, hLHPos, defLHLen)
X		|| !WriteArrayInfo (f, 264L, mPIPos, paraInfoLen, mLHPos, mainLHLen))
X			return (false);
X
X	return (true);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWIO.c
X/*
X	MakeWrite File I/O  Routines.
X*/
X
X
X# include	"MakeWrite.h"
X# include	"MWFileStuff.h"
X# include	"MWMaca.h"
X# include	<StdFilePkg.h>
X
X
Xstatic SFReply	inFile;
Xstatic SFReply	outFile;
Xstatic Str255	fName;		/* map name and volume reference number */
Xstatic Integer		vRefNum;
X
X
X/*
X	Clear the current file name, and reset the title of the map
X	window.  Obviously, the first call to this must occur
X	after the map window is initialized.
X*/
X
XClearMapName ()
X{
X	CopyString ("\pUntitled", fName);
X	SetMapName (fName);
X}
X
X
XSetMapName (name)
XStringPtr	name;
X{
XStr255	s;
X
X	CopyString ("\pMap Name:  ", s);
X	AppendString (name, s);
X	SetWTitle (mapWind, s);
X}
X
X
X/*
X	Check a ConvSpec to see that it makes sense
X*/
X
Xstatic Boolean CheckMSpec (m)
XMapSpec	*m;
X{
XInteger		errCnt = 0;
X
X	if (FontIndex (m->font) < 0)
X	{
X		ErrWindMsge ("\pUnknown font number: ", m->font);
X		++errCnt;
X	}
X	if (SizeIndex ((Integer) m->size) < 0)
X	{
X		ErrWindMsge ("\pUnknown size: ", (Integer) m->size);
X		++errCnt;
X	}
X
X	return (errCnt == 0);
X}
X
X
X/*
X	Read paragraph style variables
X*/
X
Xstatic Boolean ReadParaStyle (f, version)
XInteger		f;
XInteger		version;
X{
X	if (version == 1)
X	{
X		InitParaStyle ();		/* use defaults */
X		return (true);
X	}
X	return (FileRead (f, &paraStyle, (Longint) sizeof (ParaStyle))
X			&& ReadString (f, paraMark)
X			&& ReadString (f, pageMark)
X			&& ReadString (f, periodStr)
X			&& ReadString (f, quoteStr));
X}
X
X
X/*
X	Read one map specification from a file.  First read the MapSpec
X	structure, being careful not to clobber the mark string handle.
X	Then read the string that gets put into the handle (first the
X	length byte, then the rest of the string).
X*/
X
Xstatic Boolean ReadMSpec (f, m)
Xregister Integer		f;
Xregister MapSpec	*m;
X{
XStringHandle	hStr;
XBoolean			ok;
X
X	hStr = m->mark;	/* save since clobbered by next read */
X	ok = FileRead (f, m, (Longint) sizeof (MapSpec));
X	m->mark = hStr;
X	if (ok)
X	{
X		HLock (hStr);
X		ok = ReadString (f, *hStr);
X		HUnlock (hStr);
X	}
X	return (ok);
X}
X
X
X/*
X	Read map specifications from a file.  Duplicate or illegal
X	specifications are not added.
X
X	Assumes file is open and all mappings already cleared (for Open) or
X	not (for Append).  If setParaInfo is true (Open), paragraph style
X	info is set.  If it's false (Append), it's not set.
X
X	Does not set undo variables or map-changed variables.
X*/
X
Xstatic ReadMap (f, setParaInfo)
XInteger		f;
XBoolean	setParaInfo;
X{
XMapSpec	mSpec;
XInteger		badCnt = 0;
XInteger	ver;
XInteger	i, nLines;
XStr255	str;
XBoolean	ok;
X
X	InitMSpec (&mSpec);
X	ErrWindInit (inFile.fName);
X	if (!ReadInteger (f, &ver))
X	{
X		Message1 ("\pCan't read map file.");
X	}
X	else if (ver != mapVersion && ver != 1)
X	{
X		NumToString ((Longint) ver, str);
X		Message2 ("\pUnknown map file version:  ", str);
X	}
X	else if (ReadInteger (f, &nLines))
X	{
X		ok = true;
X		for (i = 0; i < nLines; ++i)
X		{
X			ok = false;
X			if (!ReadMSpec (f, &mSpec))
X				break;
X			ok = true;
X	
X/*
X	Need to check legality here, since the file may have been
X	created using the fonts from a font list other than the current
X	one.
X*/
X	
X			if (CheckMSpec (&mSpec) == false)
X			{
X				++badCnt;
X				continue;			/* its bad - don't use it */
X			}
X	
X			if (StatMSpec (&mSpec))
X			{
X				++badCnt;
X				continue;			/* already exists - don't use dups */
X			}
X	
X			if (InsertMapping (&mSpec, mapList->nLines) == false)
X				break;
X		}
X		if (ok && setParaInfo)
X			(void) ReadParaStyle (f, ver);
X	}
X
X	TermMSpec (&mSpec);
X
X	(void) FSClose (f);
X	ScrollToLine (mapList, 0);		/* force scroll to top */
X	SelectMapping (noLine);			/* but leave unselected */
X
X	if (badCnt)
X	{
X		NumToString ((Longint) badCnt, str);
X		Message2 (str, "\p illegal or duplicate specifications were found and ignored");
X	}
X}
X
X
X/*
X	Open a map.  Clobber the current map first, set the map name
X	afterward.
X*/
X
XBoolean OpenMap ()
X{
XInteger		f;
X
X	if (GetInputFile ("\pOpen", mwType, &inFile)
X		&& OpenInputFile (&inFile, &f))
X	{
X		ClobberMap ();
X		ReadMap (f, true);
X		CopyString (inFile.fName, fName);
X		vRefNum = inFile.vRefNum;
X		SetMapName (fName);
X		return (true);
X	}
X	return (false);
X}
X
X
X/*
X	Add a map to the current map.  Doesn't set map name afterward.
X*/
X
XBoolean AddMap ()
X{
XInteger		f;
X
X	if (GetInputFile ("\pAdd", mwType, &inFile)
X		&& OpenInputFile (&inFile, &f))
X	{
X		ReadMap (f, false);
X		return (true);
X	}
X	return (false);
X}
X
X
X/*
X	Save map to file.  askForName is true if should ask for name,
X	otherwise use current name.  If name is "Untitled", ask for a name
X	anyway.  Sets the current name if it wasn't already set.
X
X	The file is deleted if not written properly.
X*/
X
XBoolean SaveMap (askForName)
XBoolean	askForName;
X{
XInteger				f;
Xregister Integer	i;
XOSErr			result;
XLongint			pos;
XBoolean			ok = false;
XStringHandle	hStr;
X
X	if (GetOutputFile (askForName, fName, vRefNum, &outFile) == false)
X		return (false);
X	if (OpenOutputFile (&outFile, mwCreator, mwType, &f) == false)
X		return (false);
X
X	if (WriteInteger (f, (Integer) mapVersion)
X		&& WriteInteger (f, (Integer) mapList->nLines))
X	{
X		ok = true;
X		for (i = 0; i < mapList->nLines; ++i)
X		{
X			ok = FileWrite (f, &mapSpec[i], (Longint) sizeof (MapSpec));
X			if (!ok)
X				break;
X			hStr = mapSpec[i].mark;
X			HLock (hStr);
X			ok = WriteString (f, *hStr);
X			HUnlock (hStr);
X			if (!ok)
X				break;
X		}
X		if (ok)
X		{
X			ok = FileWrite (f, &paraStyle, (Longint) sizeof (ParaStyle))
X				&& WriteString (f, paraMark)
X				&& WriteString (f, pageMark)
X				&& WriteString (f, periodStr)
X				&& WriteString (f, quoteStr);
X		}
X	}
X
X	(void) GetFPos (f, &pos);
X	(void) SetEOF (f, pos);
X	(void) FSClose (f);
X	(void) FlushVol (f, outFile.vRefNum);
X
X	if (!ok)
X	{
X		Message1 ("\pCould not write map");
X		(void) FSDelete (outFile.fName, outFile.vRefNum);
X		return (false);
X	}
X
X	CopyString (outFile.fName, fName);		/* set map name */
X	vRefNum = outFile.vRefNum;
X	SetMapName (fName);
X	return (true);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMSpecOps.c
X# include	"MWMapInfo.h"
X
X
X/*
X	Initialize a MapSpec by allocating a mark string for it.
X*/
X
XInitMSpec (mSpec)
XMapSpec	*mSpec;
X{
X	mSpec->mark = (StringHandle) NewHandle ((Size) maxMarkLen + 1);
X}
X
X
X/*
X	Terminate a MapSpec by tossing its mark string.  The procedure
X	name is somewhat of a misnomer since it doesn't actually dispose
X	of the MapSpec itself.
X*/
X
XTermMSpec (mSpec)
XMapSpec	*mSpec;
X{
X	DisposHandle (mSpec->mark);
X}
X
X
X/*
X	Copy one init'ed MapSpec to another.  The most difficult part
X	is making sure the mark string gets copied correctly.
X*/
X
XCopyMSpec (srcMSpec, dstMSpec)
Xregister MapSpec	*srcMSpec, *dstMSpec;
X{
Xregister StringHandle	srcStr, dstStr;
X
X	dstStr = dstMSpec->mark;		/* save, since next line clobbers it */
X	*dstMSpec = *srcMSpec;
X	dstMSpec->mark = dstStr;		/* fix this field and copy the handle */
X	srcStr = srcMSpec->mark;
X	HLock (srcStr);
X	HLock (dstStr);
X	CopyString (*srcStr, *dstStr);
X	HUnlock (srcStr);
X	HUnlock (dstStr);
X	/*SetHandleSize (dstStr, (Size) 0);
X	HandAndHand (srcMSpec->mark, dstStr);*/
X}
X
X
X/*
X	Zero the contents of an init'ed MapSpec.
X*/
X
X
XClearMSpec (mSpec)
Xregister MapSpec	*mSpec;
X{
X	mSpec->font = sameFont;
X	mSpec->size = sameSize;
X	mSpec->style = sameStyle;
X	(*mSpec->mark)[0] = 0;
X	mSpec->selStart = 0;
X	mSpec->selEnd = 0;
X}
X
X
X/*
X	Compare two markers for equality.
X*/
X
XCompareMark (s1, s2)
XStringHandle	s1, s2;
X{
XInteger		result;
X
X	HLock (s1);
X	HLock (s2);
X	result = CompareString (*s1, *s2);
X	HUnlock (s1);
X	HUnlock (s2);
X	return (result);
X}
X
X
X/*
X	Compare two map specifications.
X	Return:
X		0		m1 = m2
X		< 0		m1 < m2
X		> 0		m1 > m2
X
X	Mark sorts before font, which sorts before size, which sorts
X	before style.
X
X	For all of font, size and style, the "same" selection is greater,
X	so that generic selections sort to the end of the list.  Font
X	comparisons are otherwise based on the name of the font, rather
X	than its number.   A string compare is avoided by keeping the
X	fonts in alphabetic order in the font information structures.
X
X	Note that the style comparison does not use the manifest constants
X	defined for each style value, and so would break if style coding
X	changed!
X*/
X
XCompareMSpec (m1, m2)
Xregister MapSpec	*m1, *m2;
X{
Xregister Integer	i;
Xregister Integer	s1, s2;
X
X	if ((i = CompareMark (m1->mark, m2->mark)) != 0)
X		return (i);
X
X	if (m1->font != m2->font)
X	{
X		if (m1->font == sameFont)
X			return (1);
X		if (m2->font == sameFont)
X			return (-1);
X		return (FontIndex (m1->font) - FontIndex (m2->font));
X	}
X
X	if ((i = m1->size - m2->size) != 0)
X	{
X		if (m1->size == sameSize)
X			return (1);
X		if (m2->size == sameSize)
X			return (-1);
X		return (i);
X	}
X
X	s1 = m1->style;
X	s2 = m2->style;
X	if (s1 - s2 != 0)
X	{
X		if (s1 == sameStyle)
X			return (1);
X		if (s2 == sameStyle)
X			return (-1);
X		for (i = 0; i < 7; ++i)
X		{
X			if (s1 == 0)
X			{
X				if (s2 != 0)
X					return (-1);
X			}
X			else if (s2 == 0)
X			{
X				return (1);
X			}
X			else if (s1 & 1)
X			{
X				if (!(s2 & 1))
X					return (-1);
X			}
X			else if (s2 & 1)
X				return (1);
X			s1 >>= 1;
X			s2 >>= 1;
X		}
X	}
X	return (0);			/* equal */
X}
X
X
X/*
X	Convert map specs to map text.  Do this by converting input specs
X	and output specs.
X*/
X
XMSpecToMStr (mSpec, mStr)
Xregister MapSpec	*mSpec;
Xregister MapStr		*mStr;
X{
X	HLock (mSpec->mark);
X	CopyString (*mSpec->mark, mStr->markStr);
X	HUnlock (mSpec->mark);
X	FontToStr (mSpec->font, mStr->fontStr);
X	SizeToStr (mSpec->size, mStr->sizeStr);
X	StyleToStr (mSpec->style, mStr->styleStr);
X}
X
X
X/*
X	Convert font number to font name.  The font *must* be legal.
X*/
X
XFontToStr (font, str)
Xregister Integer		font;
Xregister StringPtr	str;
X{
X	FontName (FontIndex (font), str);
X}
X
X
X/*
X	Convert size value to string.
X*/
X
XSizeToStr (size, str)
Xregister Integer		size;
Xregister StringPtr	str;
X{
X	if (size == sameSize)		/* no size specified, use default */
X		CopyString ("\pSame", str);
X	else
X		NumToString ((Longint) size, str);
X}
X
X
X/*
X	Convert style value to string. If the style has only one attribute
X	bit set, use the attribute name, otherwise use abbreviated form with
X	one letter for each attribute.
X*/
X
Xstatic StringPtr	styleStr[7] =
X{
X	(StringPtr) "\pBold",
X	(StringPtr) "\pItalic",
X	(StringPtr) "\pUnder",
X	(StringPtr) "\pOutline",
X	(StringPtr) "\pShadow",
X	(StringPtr) "\pHigh",
X	(StringPtr) "\pLow"
X};
X
X
XStyleToStr (style, str)
Xregister Integer		style;
Xregister StringPtr	str;
X{
Xregister Integer	i, style2;
X
X	if (style == sameStyle)		/* no style specified, use default */
X		CopyString ("\pSame", str);
X	else if (style == 0)			/* no bits set = plain text */
X		CopyString ("\pPlain", str);
X	else
X	{
X		style2 = style;
X		for (i = 0; i < 7; ++i)
X		{
X			if ((style2 & 1))
X			{
X				if (style2 != 1)
X					break;			/* more than 1 bit set */
X				CopyString (styleStr[i], str);
X				return;
X			}
X			style2 >>= 1;
X		}
X		i = 0;
X		if (style & styleBold)
X			str[++i] = 'B';
X		if (style & styleItalic)
X			str[++i] = 'I';
X		if (style & styleUnder)
X			str[++i] = 'U';
X		if (style & styleOutline)
X			str[++i] = 'O';
X		if (style & styleShadow)
X			str[++i] = 'S';
X		if (style & styleSuper)
X			str[++i] = 'H';
X		if (style & styleSub)
X			str[++i] = 'L';
X		str[0] = i;
X	}
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMain.c
X# include	"MakeWrite.h"
X
X
X/*
X	Offsets of each field in the map and font lists.  There is one
X	extra value, which is actually the offset of the right edge of
X	the last field.  These offsets are relative to the text area.
X*/
X
X
X# define	mapFields	4		/* number of fields in mapping */
X
X
Xstatic Integer		mapOffsets[mapFields + 1] =
X{
X	0,
X	100,
X	217,
X	257,
X	313
X};
X
X
Xstatic LineList	mapStruct =
X{
X	nil,						/* port - filled in later        */
X	nil,						/* control - filled in later     */
X	{ 150, 124, 246, 436 },		/* text display rect, t, l, b, r */
X	0,							/* max lines (set by InitList)   */
X	6,							/* max visible lines             */
X	0,							/* top visible line              */
X	16,							/* line height                   */
X	0,							/* number of lines               */
X	noLine,						/* current line                  */
X	false,						/* no hiliting                   */
X	mapFields,					/* number of fields/line         */
X	mapOffsets,					/* field offsets                 */
X	nil							/* line array (set by InitList)  */
X};
X
X
X
XWindowPtr	mapWind;
X
XListPtr		mapList = &mapStruct;
XMapSpec		mapSpec[maxMappings];
X
XBoolean		mapModified = false;
X
XInteger			undoOp = noUndo;
XInteger			undoVal;
XInteger			undoPos;
XInteger			undoFieldType;
XMapSpec		undoMSpec;
XBoolean		undoCPMarker;
X
XBoolean		havePasteMSpec = false;	/* for setting Paste menu item */
X
XBoolean		cpMarker = false;	/* whether cut/paste applies to marker */
X
X
X/*
X	Paragraph style control
X
X	Default is "every line a paragraph", ignore command-only lines
X*/
X
XParaStyle	paraStyle;
X
XStr255	paraMark;	/* paragraph marker string */
XStr255	pageMark;	/* page break marker string */
XStr255	periodStr;	/* sentence "periods" (terminators) */
XStr255	quoteStr;	/* quotes to ignore after periods */
X
X# ifdef	debug
XBoolean	debugOut = false;	/* controls debugging output during format */
X# endif
X
X
Xmain ()
X{
X	SkelInit ();
X	InitParaStyle ();
X	SetupMenus ();
X	MapSetup ();
X	SkelMain ();
X	SkelClobber ();
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMapOps.c
X# include	"MakeWrite.h"
X
X
X/*
X	Check whether a MapSpec already exists in the map
X*/
X
XBoolean StatMSpec (mSpec)
XMapSpec	*mSpec;
X{
Xregister Integer	i;
X
X	for (i = 0; i < mapList->nLines; ++i)
X	{
X		if (CompareMSpec (mSpec, &mapSpec[i]) == 0)
X			return (true);
X	}
X	return (false);
X}
X
X
X
X/*
X	Insert the text of all the fields for the given map list line.
X
X	This routines relies implicitly on the ordering of fields
X	within a map line.
X*/
X
Xstatic SetMapFields (hLine, mStr)
Xregister LineHandle	hLine;
Xregister MapStr		*mStr;
X{
Xregister FieldHandle	hField;
X
X	hField = hLine;
X	SetFieldStr (hField, mStr->markStr);
X	hField = NextField (hField);
X	SetFieldStr (hField, mStr->fontStr);
X	hField = NextField (hField);
X	SetFieldStr (hField, mStr->sizeStr);
X	hField = NextField (hField);
X	SetFieldStr (hField, mStr->styleStr);
X}
X
X
X/*
X	Select a mapping
X*/
X
XSelectMapping (lineNo)
Xregister Integer	lineNo;
X{
X	SelectLine (mapList, lineNo);
X	if (lineNo != noLine)
X		ScrollToLine (mapList, lineNo);
X	SetSelectors (lineNo);
X}
X
X
X/*
X	Insert a new mapping, making it mapping n.  This takes care
X	of both the specification array, and the list of text representations
X	of the mappings.
X
X	Note that there's no explicit count of mappings.  Use the count
X	in the LineList corresponding to the mapping array is used.
X*/
X
XBoolean InsertMapping (mSpec, n)
XMapSpec	*mSpec;
XInteger		n;
X{
XMapStr				mStr;
Xregister LineHandle	hLine;
Xregister Integer		i, nLines;
XStr255				s;
X
X	if (mapList->nLines < mapList->maxLines)
X	{
X
X/*
X	Convert mapping specification into string form and put the strings
X	into a new line to be inserted into the line list.
X
X	Then make room for the new mapping in spec array and insert it.
X*/
X
X		nLines = mapList->nLines;		/* save; InsertLine changes it */
X		MSpecToMStr (mSpec, &mStr);		/* convert specs to strings */
X		hLine = NewLine (mapList->nFields);
X		SetMapFields (hLine, &mStr);
X		if (InsertLine (mapList, hLine, n) == false)
X		{
X			DisposeLine (hLine);
X		}
X		else
X		{
X/*
X	Move specs around to make room, then add the new one
X	in the empty slot.
X*/
X			for (i = nLines; i > n; --i)
X			{
X				CopyMSpec (&mapSpec[i-1], &mapSpec[i]);
X			}
X			CopyMSpec (mSpec, &mapSpec[n]);
X			/*mapSpec[n].selStart = 0;
X			mapSpec[n].selEnd = 32767;*/
X			SelectMapping (n);
X			/*SetCPMarker (true);*/
X			return (true);
X		}
X	}
X	NumToString ((Longint) mapList->maxLines, s);
X	Message3 ("\pMap is full (", s, "\p lines).  Can't add anything to it.");
X	return (false);
X}
X
X
X/*
X	Add a new, blank, mapping to the end of the list.
X	This should be different - the handle should be copied in InsertMapping.
X*/
X
XNewMapping ()
X{
XMapSpec	mSpec;
X
X	InitMSpec (&mSpec);
X	ClearMSpec (&mSpec);
X	(void) InsertMapping (&mSpec, mapList->nLines);
X	TermMSpec (&mSpec);
X}
X
X
X/*
X	Duplicate the currently selected mapping and add right after the
X	selection.
X*/
X
XDupMapping (n)
X{
X	(void) InsertMapping (&mapSpec[n], n+1);
X}
X
X
X/*
X	Replace the currently selected mapping with the given one.
X	(It's assumed that there *is* one selected.)
X*/
X
XPasteMapping (mSpec, n)
XMapSpec	*mSpec;
XInteger		n;
X{
XMapStr			mStr;
Xregister Integer	curLine;
X
X	curLine = mapList->curLine;
X	CopyMSpec (mSpec, &mapSpec[curLine]);
X	MSpecToMStr (mSpec, &mStr);
X	SetMapFields (ListLine (mapList, curLine), &mStr);
X	DrawLine (mapList, curLine);
X	SetSelectors (curLine);				/* set selection controls */
X}
X
X
X/*
X	Clobber the n'th mapping.
X*/
X
XDeleteMapping (n)
Xregister Integer	n;
X{
Xregister Integer	i;
X
X	for (i = n; i < mapList->nLines; ++i)
X	{
X		CopyMSpec (&mapSpec[i+1], &mapSpec[i]);		/* copy specs */
X	}
X	DeleteLine (mapList, n);
X	SelectMapping (noLine);
X	ScrollToLine (mapList, n);
X}
X
X
X/*
X	Clobber entire map.
X*/
X
XClobberMap ()
X{
X	SelectMapping (noLine);
X	ResetList (mapList);
X	InitParaStyle ();
X}
X
X
X
X/*
X	Sort the map specifications on the input format values.  Make
X	sure to keep track of the current spec and redraw the text 
X	and controls properly when done.
X*/
X
XSortMap ()
X{
Xregister Integer		i, j, curLine;
Xregister LineHandle	tmpLine;
XMapSpec				tmpSpec;
X
X	InitMSpec (&tmpSpec);
X	curLine = mapList->curLine;
X	for (i = 0; i < mapList->nLines - 1; ++i)
X	{
X		for (j = i; j < mapList->nLines; ++j)
X		{
X			if (CompareMSpec (&mapSpec[i], &mapSpec[j]) > 0)
X			{
X				CopyMSpec (&mapSpec[i], &tmpSpec);
X				CopyMSpec (&mapSpec[j], &mapSpec[i]);
X				CopyMSpec (&tmpSpec, &mapSpec[j]);
X				tmpLine = ListLine (mapList, i);
X				ListLine (mapList, i) = ListLine (mapList, j);
X				ListLine (mapList, j) = tmpLine;
X				if (curLine == i)
X					curLine = j;
X				else if (curLine == j)
X					curLine = i;
X			}
X		}
X	}
X	DrawListText (mapList);
X	SelectMapping (curLine);
X	TermMSpec (&tmpSpec);
X}
X
X
X/*
X	Eliminate duplicates in the map.  The loops must explicitly
X	test mapList->nLines, not a variable set equal to that before
X	the loops, since DeleteMapping causes mapList->nLines to change.
X*/
X
XSquishMap ()
X{
Xregister Integer	i, j;
X
X	for (i = 0; i < mapList->nLines; ++i)
X	{
X		j = i + 1;
X		while (j < mapList->nLines)
X		{
X			if (CompareMSpec (&mapSpec[i], &mapSpec[j]) == 0)
X				DeleteMapping (j);
X			else
X				++j;
X		}
X	}
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMapWind.c
X# include	<TextEdit.h>
X# include	"MakeWrite.h"
X
X
X# define	tab			'\t'
X# define	shiftKey	0x0200
X# define	applFont	1
X
X
X/*
X	Local data for creating controls
X*/
X
X
X/*
X	maxSize = number of point-size selection radio buttons
X	maxStyle = number of style selection check boxes
X	maxCP = number of edit menu cut/paste indicator controls
X	maxCtrl = sum of above three
X	maxFonts = maximum number of fonts allowed in scrollable list
X*/
X
X# define	maxSize		7
X# define	maxStyle	9
X# define	maxCP		2
X# define	maxCtrl		(maxSize+maxStyle+maxCP)
X# define	maxFonts	102
X
X
Xtypedef enum	/* control types, by function */
X{
X	sizeType,	/* size radio button */
X	styleType,	/* style check box */
X	cpType		/* edit menu check box */
X};
X
X
Xtypedef struct CtrlInfo
X{
X	Str255	cTitle;		/* initial control title */
X	Integer		ch, cv;		/* location of upper left corner */
X} CtrlInfo;
X
X
Xstatic CtrlInfo	ctrlInfo[maxCtrl] =
X{
X	{ "\pSame",				181,	20 },
X	{ "\p9",				172,	40 },
X	{ "\p10",				172,	60 },
X	{ "\p12",				172,	80 },
X	{ "\p14",				217,	40 },
X	{ "\p18",				217,	60 },
X	{ "\p24",				217,	80 },
X	{ "\pSame",				312,	20 },
X	{ "\pPlain",			265,	40 },
X	{ "\pBold",				265,	60 },
X	{ "\pItalic",			265,	80 },
X	{ "\pUnderline",		265,	100 },
X	{ "\pOutline",			355,	40 },
X	{ "\pShadow",			355,	60 },
X	{ "\pSuperscript",		355,	80 },
X	{ "\pSubscript",		355,	100 },
X	{ "\pMarker",			9,		210 },
X	{ "\pMap Lines",		9,		230 }
X};
X
X
Xstatic ControlHandle	sizeCtrl[maxSize];
Xstatic ControlHandle	styleCtrl[maxStyle];
Xstatic ControlHandle	cpCtrl[maxCP];
X
X
X
X/*
X	Standard MacWrite point sizes, plus the "same size" selection.
X	The order of these corresponds to the size radio buttons.
X*/
X
Xstatic Integer		sizeInfo[maxSize] = { sameSize, 9, 10, 12, 14, 18, 24 };
X
X
X/*
X	Masks for manipulating style selections.  The order of these
X	corresponds to the style check boxes.
X*/
X
X
Xstatic Integer		styleMask[maxStyle] =
X{
X	sameStyle,
X	0,				/* plain; special-cased */
X	styleBold,
X	styleItalic,
X	styleUnder,
X	styleOutline,
X	styleShadow,
X	styleSuper,
X	styleSub
X};
X
X
X/*
X	Standard font specifications
X*/
X
X
Xtypedef struct
X{
X	Integer				fontNum;
X	StringHandle	fontName;
X} FontSpec;
X
X
Xstatic FontSpec	fontSpecs[maxFonts];
Xstatic Integer		nFontSpecs;
X
X
Xstatic Integer		fontOffsets[2] = { 0, 137 };
X
X
Xstatic LineList	fontStruct =
X{
X	nil,						/* port - filled in later        */
X	nil,						/* control - filled in later     */
X	{ 20, 5, 116, 141 },		/* text display rect, t, l, b, r */
X	0,							/* max lines                     */
X	6,							/* max visible lines             */
X	0,							/* top visible line              */
X	16,							/* line height                   */
X	0,							/* number of lines               */
X	noLine,						/* current line                  */
X	false,						/* no hiliting                   */
X	1,							/* number of fields/line         */
X	fontOffsets,				/* field offsets                 */
X	nil							/* line array                    */
X};
X
X
Xstatic ListPtr	fontList = &fontStruct;
X
Xstatic MapSpec	*curMSpec;
Xstatic Integer		curMSpecNo;
X
Xstatic TEHandle	markTE;
X
X
X/* ---------------------------------------------------------------- */
X/*					General Control Operations						*/
X/* ---------------------------------------------------------------- */
X
X
X
X/*
X	Set a control value, but only when it changes, to avoid
X	unnecessary redrawing (ugly, since gobs of them are usually
X	changed together).
X
X	Use for check boxes and radio buttons only, not scroll bars!
X*/
X
Xstatic SetControl (ctrl, value)
XControlHandle	ctrl;
XBoolean			value;
X{
X	if (GetCtlValue (ctrl) != value)
X		SetCtlValue (ctrl, value);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*						Font List Operations						*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Add a font to the spec list.  Return false if there's overrun.
X*/
X
XBoolean SetFontSpec (fNum, fName)
XInteger			fNum;
XStringPtr	fName;
X{
Xregister StringHandle	h;
XStr255					s;
Xregister Integer			i, result;
X
X	for (i = 0; i < nFontSpecs; ++i)	/* see if already there */
X	{
X		h = fontSpecs[i].fontName;
X		HLock (h);
X		result = CompareString (*h, fName);
X		HUnlock (h);
X		if (result == 0)		/* font name's a duplicate */
X			return (true);		/* but that's ok */
X	}
X
X	if (nFontSpecs >= fontList->maxLines)	/* will list be too full? */
X	{
X		NumToString ((Longint) maxFonts - 2, s);
X		Message3 ("\pSorry, I am such a brain-damaged program that I only allow ",
X					s, "\p fonts!");
X		return (false);
X	}
X
X	h = (StringHandle) NewHandle ((Longint) (fName[0] + 1));
X	HLock (h);
X	CopyString (fName, *h);
X	HUnlock (h);
X	fontSpecs[nFontSpecs].fontName = h;
X	fontSpecs[nFontSpecs++].fontNum = fNum;
X	return (true);
X}
X
X
X/*
X	Set up to construct a new font list.  Note that the other
X	selector controls must have been initialized by this point.
X*/
X
XResetFontList ()
X{
Xregister Integer	i;
X
X	for (i = 0; i < fontList->nLines; ++i)
X		DisposHandle (fontSpecs[i].fontName);
X	nFontSpecs = 0;
X	ResetList (fontList);
X	SetFontSpec (sameFont, "\pSame");
X	SetFontSpec (applFont, "\pApplication");
X}
X
X
X/*
X	Sync information in fontSpec to fontList by constructing the LineList
X	elements.
X*/
X
XSyncFontSpecs ()
X{
Xregister Integer		i, j;
XInteger					tmp;
Xregister FontSpec	*f1, *f2;
XStringHandle		h1, h2;
XLineHandle			hField;
X
X/*
X	Sort font names, except for "Same" and "Application", which
X	stay at the front of the list.
X*/
X
X	for (i = 2; i < nFontSpecs - 1; ++i)
X	{
X		for (j = i + 1; j < nFontSpecs; ++j)
X		{
X			f1 = &fontSpecs[i];
X			f2 = &fontSpecs[j];
X			h1 = f1->fontName;
X			h2 = f2->fontName;
X			HLock (h1);
X			HLock (h2);
X			if (CompareString (*h1, *h2) > 0)
X			{
X				f1->fontName = h2;
X				f2->fontName = h1;
X				tmp = f1->fontNum;
X				f1->fontNum = f2->fontNum;
X				f2->fontNum = tmp;
X			}
X			HUnlock (h1);
X			HUnlock (h2);
X		}
X	}
X
X/*
X	Add names to fontList
X*/
X
X	ResetList (fontList);
X	for (i = 0; i < nFontSpecs; ++i)
X	{
X		h1 = fontSpecs[i].fontName;
X		HLock (h1);
X		hField = NewLine (1);
X		SetFieldStr (hField, *h1);
X		HUnlock (h1);
X		(void) InsertLine (fontList, hField, i);
X	}
X	SelectLine (fontList, 0);
X	ScrollToLine (fontList, 0);		/* force scroll to top */
X}
X
X
X/*
X	Given a font number, find its index in the stdFontSpecs
X	array.  Return -1 if it's not there.
X*/
X
XFontIndex (fontNum)
XInteger		fontNum;
X{
Xregister Integer		i;
X
X	for (i = 0; i < fontList->nLines; ++i)
X	{
X		if (fontNum == fontSpecs[i].fontNum)
X			return (i);
X	}
X	return (-1);
X}
X
X
X/*
X	Return a font name corresponding to the given index
X*/
X
XFontName (fontIndex, str)
XInteger			fontIndex;
XStringPtr	str;
X{
XStringHandle	hStr;
X
X	hStr = fontSpecs[fontIndex].fontName;
X	HLock (hStr);
X	CopyString (*hStr, str);
X	HUnlock (hStr);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*						Size Control Operations						*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Given a point size, find its index in the sizeInfo
X	array.  (Return -1 if it's not there.)
X*/
X
XSizeIndex (size)
XInteger		size;
X{
Xregister Integer		i;
X
X	for (i = 0; i < maxSize; ++i)
X	{
X		if (size == sizeInfo[i])
X			return (i);
X	}
X	return (-1);
X}
X
X
Xstatic SetSizeCtrls ()
X{
Xregister Integer		i;
X
X	for (i = 0; i < maxSize; ++i)
X		SetControl (sizeCtrl[i], sizeInfo[i] == curMSpec->size);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*						Style Control Operations					*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Set the style controls based on the current value of theStyle.
X
X	The sameStyle bit and the attributes bits cause the corresponding
X	boxes to be checked if they are set.  If the style is zero, it's
X	plain.
X*/
X
Xstatic SetStyleCtrls ()
X{
Xregister Integer		i;
Xregister Boolean	same;
Xregister Integer		theStyle;
X
X	theStyle = curMSpec->style;
X	same = ((theStyle & sameStyle) != 0);
X	SetControl (styleCtrl[0], same);
X
X	if (same)
X	{
X		for (i = 1; i < maxStyle; ++i)
X			SetControl (styleCtrl[i], false);
X	}
X	else if (theStyle == 0)					/* plain */
X	{
X		SetControl (styleCtrl[1], true);
X		for (i = 2; i < maxStyle; ++i)
X			SetControl (styleCtrl[i], false);
X	}
X	else									/* not plain */
X	{
X		SetControl (styleCtrl[1], false);
X		for (i = 2; i < maxStyle; ++i)
X			SetControl (styleCtrl[i], (theStyle & styleMask[i]) != 0);
X	}
X}
X
X
X/*
X	Determine style value.  The argument is an index into the control
X	array not a style value itself.  Style controls interact in
X	wretched complexity.
X
X	If same is toggled on, all the other style boxes are toggled off.
X	If it's toggled off, plain is toggled on.
X
X	If plain is toggled on, all the other style boxes are toggled off.
X	If it's toggled off, same is toggled on.
X
X	The other style boxes correspond to style attributes.  If any of
X	them are toggled on, then same and plain are toggle off if
X	they were on.  If all the attributes are toggled off, plain is
X	toggled on.  Superscript and subscript are mutually exclusive,
X	so that if one of them is toggled on, the other is toggled off.
X*/
X
Xstatic NewStyleValue (i)
Xregister Integer	i;
X{
Xregister Integer	curValue;
Xregister Integer	theStyle;
X
X	curValue = GetCtlValue (styleCtrl[i]);	/* current value - new value */
X											/* will be opposite */
X	theStyle = curMSpec->style;
X
X	if (i == 0)			/* "same" box clicked */
X	{
X		if (curValue)	/*  currently same, turn off (implies plain) */
X			theStyle = 0;
X		else
X			theStyle = styleMask[0];	/* currently off, turn on */
X	}
X	else if (i == 1)	/* plain box clicked */
X	{
X		if (curValue)	/*  currently plain, turn off (implies same) */
X			theStyle = styleMask[0];
X		else
X			theStyle = 0;	/* currently off, turn on */
X	}
X	else
X	{
X	/*
X		Flip box value.
X		Can't have superscript and subscript at the same time.
X	*/
X		if (curValue)	/* currently on, turn off */
X			theStyle &= ~styleMask[i];
X		else			/* currently off, turn on (turn same off) */
X		{
X			theStyle |= styleMask[i];
X			theStyle &= ~styleMask[0];
X		}
X
X		if (i == 7)	/* superscript.  if turning on, turn off sub */
X		{
X			if (curValue == 0)
X				theStyle &= ~styleMask[8];
X		}
X		if (i == 8)	/* subscript.  if turning on, turn off super */
X		{
X			if (curValue == 0)
X				theStyle &= ~styleMask[7];
X		}
X	}
X	return (theStyle);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*				Edit Menu Cut/Paste Control Operations				*/
X/* ---------------------------------------------------------------- */
X
X
Xstatic SetCPCtrls ()
X{
X	SetControl (cpCtrl[0], cpMarker);
X	SetControl (cpCtrl[1], !cpMarker);
X}
X
X
XSetCPMarker (useMarker)
XBoolean	useMarker;
X{
X	cpMarker = useMarker;
X	SetCPCtrls ();
X}
X
X
XBlankCPCtrls ()
X{
X	SetControl (cpCtrl[0], false);
X	SetControl (cpCtrl[1], false);
X}
X
X
X/* ---------------------------------------------------------------- */
X/*							Marker Operations						*/
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Sync the marker edit text to a mapSpec
X*/
X
XMSpecToMark (m)
XMapSpec	*m;
X{
XStringHandle	s;
XRect			r;
X
X	s = m->mark;
X	HLock (s);
X	TESetSelect (0L, 32767L, markTE);
X	TEDelete (markTE);
X	TEInsert (*s + 1, (Longint) (*s)[0], markTE);	/* replace text */
X	HUnlock (s);
X	TESetSelect ((Longint) m->selStart, (Longint) m->selEnd, markTE);
X}
X
X
X/*
X	Sync current mapSpec to the marker edit text
X*/
X
Xstatic MarkToMSpec ()
X{
XStringHandle	hStr;
XHandle			h;
XInteger				len;
X
X	curMSpec->selStart = (**markTE).selStart;
X	curMSpec->selEnd = (**markTE).selEnd;
X	h = TEGetText (markTE);
X	len = (**markTE).teLength;
X	if (len > maxMarkLen)
X		len = maxMarkLen;		/* truncate length if necessary */
X	hStr = curMSpec->mark;
X	HLock (h);
X	HLock (hStr);
X	BlockMove (*h, *hStr + 1, (Longint) len);
X	(*hStr)[0] = len;
X	HUnlock (h);
X	PasteField (mapList, mapList->curLine, markField, *hStr);
X	HUnlock (hStr);
X}
X
X
Xtypedef enum		/* relevant Edit menu item numbers */
X{
X	cut = 3,
X	copy,
X	paste,
X	clear
X};
X
X
XMarkerUndoSetup ()
X{
X	CopyMSpec (curMSpec, &undoMSpec);
X	undoOp = undoMarkerOp;
X	undoPos = mapList->curLine;
X	undoCPMarker = cpMarker;
X}
X
X
XBoolean EditMarker (item)
XInteger		item;
X{
X	if (!cpMarker)
X		return (false);
X
X	switch (item)
X	{
X	
X	case cut:
X		MarkerUndoSetup ();
X		TECut (markTE);
X		(void) ZeroScrap ();
X		(void) TEToScrap ();
X		break;
X	
X	case copy:
X		TECopy (markTE);
X		(void) ZeroScrap ();
X		(void) TEToScrap ();
X		break;
X	
X	case paste:
X		if (curMSpec == nil)	/* ignore if no line selected */
X			return (false);
X		MarkerUndoSetup ();
X		(void) TEFromScrap ();
X		TEPaste (markTE);
X		break;
X	
X	case clear:
X		MarkerUndoSetup ();
X		(void) TEDelete (markTE);
X		break;
X	
X	default:
X		return (false);	/* all others handled by general */
X						/* edit menu handler */
X
X	}
X
X	MarkToMSpec (curMSpec);	/* sync map with change in mark */
X	if (item != copy)
X		mapModified = true;
X	FixMenus ();
X	return (true);
X}
X
X
X/* ---------------------------------------------------------------- */
X
X
X/*
X	Set a field in the currently selected line.  Don't call this if
X	no line is selected, or if the field already has the same value.
X*/
X
XSetMapFieldValue (fieldType, value)
XInteger		fieldType;
XInteger		value;
X{
XStr255		s;
X
X	switch (fieldType)
X	{
X
X	case fontField:
X		undoVal = curMSpec->font;
X		FontToStr (value, s);
X		curMSpec->font = value;
X		SelectLine (fontList, FontIndex (value));
X		break;
X
X	case sizeField:
X		undoVal = curMSpec->size;
X		SizeToStr (value, s);
X		curMSpec->size = value;
X		SetSizeCtrls ();
X		break;
X
X	case styleField:
X		undoVal = curMSpec->style;
X		StyleToStr (value, s);
X		curMSpec->style = value;
X		SetStyleCtrls ();
X		break;
X	}
X
X	PasteField (mapList, mapList->curLine, fieldType, s);
X	mapModified = true;
X	undoOp = undoFieldChg;
X	undoFieldType = fieldType;
X}
X
X
X/*
X	Set the selection controls and font list to reflect currently
X	selected conversion specification.  Also sets current MapSpec
X	pointer.
X*/
X
XSetSelectors (lineNo)
XInteger		lineNo;
X{
Xregister Integer	i;
X
X	if (lineNo == noLine)				/* no map line selected */
X	{
X
X		curMSpec = nil;
X		curMSpecNo = noLine;
X
X		ListActivate (fontList, false);
X	
X		for (i = 0; i < maxSize; ++i)
X			SetControl (sizeCtrl[i], false);
X	
X		for (i = 0; i < maxStyle; ++i)
X			SetControl (styleCtrl[i], false);
X
X		TESetSelect (0L, 32767L, markTE);
X		TEDelete (markTE);
X		TEDeactivate (markTE);
X
X		return;
X	}
X
X	curMSpec = &mapSpec[curMSpecNo = lineNo];
X
X	SelectLine (fontList, FontIndex (curMSpec->font));
X	ListActivate (fontList, true);
X	ScrollToLine (fontList, fontList->curLine);
X	SetSizeCtrls ();
X	SetStyleCtrls ();
X	MSpecToMark (curMSpec);
X	TEActivate (markTE);
X	/*SetCPCtrls ();*/
X}
X
X
X/*
X	Map window mouse handler.
X
X	First test the scroll bars, and return if one was hit; they
X	require no further action.
X
X	Then check for hit in map list.  If a new line was selected, set
X	the selectors to the values, and disable undo.
X
X	Then, if a line is currently selected, check the selection controls.
X	If one is hit, change the values in the current line and reset the
X	controls properly - but only if the current values *change*.
X*/
X
Xstatic Mouse (pt, t, mods)
XPoint	pt;
XLongint	t;
XInteger		mods;
X{
XControlHandle	ctrl;
XInteger				index;
XInteger				type;
XLongint			refCon;
XInteger				newVal;
XBoolean			newIO;
XInteger				curLine;
XRect			r;
X
X	if (ListTestScroll (mapList, pt) || ListTestScroll (fontList, pt))
X		return;
X
X	curLine = mapList->curLine;				/* current line */
X	if (ListTestText (mapList, pt))
X	{
X		if (curLine != mapList->curLine)	/* different now? */
X		{
X			undoOp = noUndo;
X			if ((curLine = mapList->curLine) != noLine)
X			{
X				mapSpec[curLine].selStart = 0;
X				mapSpec[curLine].selEnd = 32767;
X			}
X			/*SetCPMarker (true);*/
X			SetSelectors (curLine);
X			FixMenus ();
X		}
X		return;
X	}
X
X	if (curMSpec == nil)
X		return;				/* no current line - controls irrelevant */
X
X	if (ListTestText (fontList, pt))
X	{
X		if (fontList->curLine == noLine)
X			SelectLine (fontList, fontList->nLines - 1);
X		newVal = fontSpecs[fontList->curLine].fontNum;	
X		if (curMSpec->font != newVal)
X		{
X			SetMapFieldValue (fontField, newVal);
X			FixMenus ();
X		}
X		return;
X	}
X
X/*
X	Check the edittext box
X*/
X
X	r = (**markTE).viewRect;
X	InsetRect (&r, -3, -3);
X	if (PtInRect (pt, &r))
X	{
X		undoOp = noUndo;
X		SetCPMarker (true);
X		TEClick (pt, (mods & shiftKey) != 0, markTE);
X		curMSpec->selStart = (**markTE).selStart;
X		curMSpec->selEnd = (**markTE).selEnd;
X		FixMenus ();
X		return;
X	}
X
X
X/*
X	Don't need to check control type returned from FindControl - at
X	this point, it can't be anything but inCheckBox.  The control type
X	and index is coded in the reference constant (see MakeControl).
X*/
X
X	if (FindControl (pt, mapWind, &ctrl))
X	{
X		if (TrackControl (ctrl, pt, nil) == inCheckBox)
X		{
X			refCon = GetCRefCon (ctrl);
X			index = refCon & 0x00ff;
X			type = (refCon & 0xff00) >> 8;
X
X			switch (type)
X			{
X
X			case sizeType:
X				newVal = sizeInfo[index];
X				if (newVal != curMSpec->size)
X					SetMapFieldValue (sizeField, newVal);
X				break;
X
X			case styleType:
X				newVal = NewStyleValue (index);
X				if (newVal != curMSpec->style)
X					SetMapFieldValue (styleField, newVal);
X				break;
X
X			case cpType:
X				SetCPMarker (index == 0);
X				undoOp = noUndo;
X				break;
X
X			}
X
X			FixMenus ();
X		}
X		return;
X	}
X}
X
X
X/*
X	Process key click in window for mark string.  On the first key
X	after any other operation, save the current mark string state
X	for undo.  And on every key click, save the selection range.  This
X	is so the range can be saved properly if the window is inactivated
X	and later activated, or if another line is selected and then this
X	line is reselected.
X*/
X
Xstatic Key (c, mods)
Xchar	c;
XInteger		mods;
X{
XHandle			h;
XStringHandle	s;
XInteger				len;
X
X	if (curMSpec == nil)
X		return;
X
X	switch (c)
X	{
X	
X	case tab:
X	case enter:
X	case cr:
X		undoOp = noUndo;
X		if (mods & shiftKey)
X		{
X			if (--curMSpecNo < 0)
X				curMSpecNo = mapList->nLines - 1;
X		}
X		else
X		{
X			if (++curMSpecNo >= mapList->nLines)
X				curMSpecNo = 0;
X		}
X		SelectMapping (curMSpecNo);
X		break;
X
X	default:
X		if (undoOp != undoTyping)	/* first char typed */
X		{
X			MarkerUndoSetup ();
X			undoOp = undoTyping;
X		}
X
X		TEKey (c, markTE);
X		MarkToMSpec (curMSpec);
X		SetCPMarker (true);
X		mapModified = true;
X		FixMenus ();
X
X	}
X}
X
X
Xstatic Update (resized)
XBoolean	resized;
X{
Xregister Integer	i;
XRect	r;
X
X	MoveTo (65, 14);
X	DrawString ("\pFont");
X	MoveTo (180, 14);
X	DrawString ("\pPoint Size");
X	MoveTo (322, 14);
X	DrawString ("\pStyle");
X	MoveTo (30, 145);
X	DrawString ("\pMarker");
X	MoveTo (4, 190);
X	DrawString ("\pCut & Paste Ops");
X	MoveTo (4, 206);
X	DrawString ("\pAffect:");
X	MoveTo (212, 143);
X	DrawString ("\pFormat Specifications");
X	DrawControls (mapWind);
X	r = (**markTE).viewRect;
X	EraseRect (&r);
X	TEUpdate (&r, markTE);
X	InsetRect (&r, -3, -3);
X	FrameRect (&r);
X	DrawListFrame (fontList);
X	DrawListFrame (mapList);
X	DrawListText (fontList);
X	DrawListText (mapList);
X}
X
X
X/*
X	When the window is activated, do appropriate map list and font list
X	line and scroll bar hiliting, and set size and style controls to
X	current values.
X
X	When the window is deactivated, all hiliting is turned off, the
X	scroll bars are unhilited and the size and style controls go blank.
X
X	Note that SetSelectrs takes care of setting font list line and scroll
X	bar hiliting; it doesn't have to be done here.  It also activates
X	or deactivates the text field properly.
X*/
X
Xstatic Activate (active)
XBoolean	active;
X{
X	if (active)
X	{
X		DoUpdates ();
X		ListActivate (mapList, true);
X		SetSelectors (mapList->curLine);
X	}
X	else
X	{
X		SetSelectors (noLine);
X		ListActivate (mapList, false);
X	}
X	FixMenus ();
X}
X
X
Xstatic Clobber ()
X{
X	HideWindow (mapWind);
X	TEDispose (markTE);
X	/*DisposeList (mapList);
X	DisposeList (fontList);*/
X	DisposeWindow (mapWind);
X}
X
X
Xstatic Idle ()
X{
X	TEIdle (markTE);
X}
X
X
X/*
X	Create controls.  These are created in the same order as the specs
X	in the ctrlInfo array.
X*/
X
Xstatic ControlHandle MakeControl (proc, type, index)
XInteger				proc;
XInteger				type;
XInteger				index;
X{
Xstatic Integer			i = 0;	/* used to step through ctrlInfo array */
Xregister CtrlInfo	*cInfo;
XRect				r;
XStringPtr			title;
Xregister Integer		h, v;
XControlHandle		ctrl;
X
X	cInfo = &ctrlInfo[i++];
X	title = cInfo->cTitle;
X	h = cInfo->ch;
X	v = cInfo->cv;
X	SetRect (&r, h, v, h + StringWidth (title) + 20, v + 20);
X	ctrl = NewControl (mapWind,
X						&r,
X						title,
X						true,
X						0, 0, 1,
X						proc,
X						(Longint) (type << 8 | index));
X	return (ctrl);
X}
X
X
XMapSetup ()
X{
Xregister Integer	i;
XRect			r;
X
X	SetRect (&r, 24, 60, 480, 311);
X	mapWind = NewWindow (nil, &r, "\p", false, noGrowDocProc,
X							-1L, false, 0L);
X	SkelWindow (mapWind,
X				Mouse,
X				Key,
X				Update,
X				Activate,
X				nil,
X				Clobber,
X				Idle,
X				true);
X
X	TextFont (0);			/* do this so StringWidth calculations */
X	TextSize (0);			/* for controls will be accurate */
X
X	for (i = 0; i < maxSize; ++i)
X		sizeCtrl[i] = MakeControl (radioButProc, sizeType, i);
X
X	for (i = 0; i < maxStyle; ++i)
X		styleCtrl[i] = MakeControl (checkBoxProc, styleType, i);
X
X	for (i = 0; i < maxCP; ++i)
X		cpCtrl[i] = MakeControl (radioButProc, cpType, i);
X
X	SetRect (&r, 7, 152, 107, 168);
X	markTE = TENew (&r, &r);
X	(void) ZeroScrap ();
X
X	InitList (fontList, maxFonts);		/* initialize empty list */
X	InitList (mapList, maxMappings);
X	for (i = 0; i < maxMappings; ++i)
X		InitMSpec (&mapSpec[i]);
X
X/*
X	Add default set of fonts:  ImageWriter fonts and LaserWriter fonts.
X	Reset the list and add the two sets without asking whether to add to
X	or replace the current list, since there's not really any current
X	list.
X*/
X
X	ResetFontList ();
X	StrFonts (false);
X
X	ClearMapName ();
X	ShowWindow (mapWind);
X}
SHAR_EOF
exit
--- end of part 2 ---
MakeWrite Source (part 3 of 3)
#51
Author: 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 ---
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads