🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: mod.mac.sources
Article #49

MakeWrite Source (part 1 of 3)

#49
From: 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 ---
Technical Details
Message-ID: <2455@felix.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!water!watnot!watmath!clyde!rutgers!lll-lcc!pyramid!oliveb!felix!macintosh

Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: arc1-ca.pugleaf.net!utzoo!utgpu!water!watnot!watmath!clyde!rutgers!lll-lcc!pyramid!oliveb!felix!macintosh
From: macintosh@felix.UUCP
Newsgroups: mod.mac.sources
Subject: MakeWrite Source (part 1 of 3)
Message-ID: <2455@felix.UUCP>
Date: Sat, 21-Mar-87 02:31:24 EST
Article-I.D.: felix.2455
Posted: Sat Mar 21 02:31:24 1987
Date-Received: Mon, 23-Mar-87 00:29:39 EST
Sender: macintosh@felix.UUCP
Reply-To: dubois@uwmacc.UUCP (Paul DuBois)
Organization: UWisconsin-Madison Academic Comp Center
Lines: 2162
Approved: bytebug@felix.UUCP (Roger L. Long)