Article View: mod.mac.sources
Article #49MakeWrite Source (part 1 of 3)
From: macintosh
Date: Sat, 21 Mar 1987 07:31
Date: Sat, 21 Mar 1987 07:31
2162 lines
53088 bytes
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!macintoshShow 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)