Thread View: mod.mac.sources
3 messages
3 total messages
Started by macintosh
Sat, 21 Mar 1987 07:31
MakeWrite Source (part 1 of 3)
Author: 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 ---
MakeWrite Source (part 2 of 3)
Author: macintosh
Date: Sat, 21 Mar 1987 19:00
Date: Sat, 21 Mar 1987 19:00
2483 lines
57060 bytes
57060 bytes
[MakeWrite Source - part 2 of 3]
---
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# MW/MWFontOps.c
# MW/MWGen.c
# MW/MWIO.c
# MW/MWMSpecOps.c
# MW/MWMain.c
# MW/MWMapOps.c
# MW/MWMapWind.c
sed 's/^X//' << 'SHAR_EOF' > MW/MWFontOps.c
X# include "MakeWrite.h"
X# define applFont 1
X
X
X/*
X Query user whether to replace the current font list with the
X selected font, or just add them to the list. Return false if
X Cancel clicked. If Replace clicked, then warn user that the
X map will be destroyed (if it has been changed) and return false
X if he declines. Otherwise return true.
X
X If Replace is selected, then the map and the font list are
X cleared as well as setting some state variables. The map is
X really modified by clearing it, but that was ok'd by user, so is
X now considered clean (unmodified) - just like after New Map.
X*/
X
Xstatic Boolean ReplaceOrAdd ()
X{
Xtypedef enum /* alert button numbers */
X{
X cancel = 1,
X add,
X replace
X};
Xregister Integer i;
X
X i = Alert (replaceAlrtNum, nil);
X DoUpdates ();
X
X if (i == cancel)
X return (false);
X
X if (i == replace)
X {
X if (!DestroyWarn ())
X return (false);
X ClobberMap ();
X ClearMapName ();
X ResetFontList ();
X mapModified = false;
X undoOp = noUndo;
X }
X return (true);
X}
X
X
X/*
X Add the names of the FONT resources in the open resource files
X to the font list (or replace the list with those fonts).
X
X Not all FONT resources have a name, so check it first. This could
X equally well be done by using only those FONT resources corresponding
X to a point size of zero (bits 0-6 of the resource id equal to zero).
X*/
X
XResourceFonts (ask)
XBoolean ask;
X{
XHandle h;
Xregister Integer i;
XInteger fNum, nFonts;
XInteger resId;
XResType resType;
XStr255 resName;
X
X if (ask)
X {
X if (ReplaceOrAdd () == false)
X return;
X }
X
X nFonts = CountResources ('FONT');
X SetResLoad (false);
X for (i = 1; i <= nFonts; ++i)
X {
X h = GetIndResource ('FONT', i);
X GetResInfo (h, &resId, &resType, &resName);
X if (resName[0] != 0) /* not all font resources have names! */
X {
X GetFNum (resName, &fNum);
X if (!SetFontSpec (fNum, resName))
X break;
X }
X }
X SetResLoad (true);
X SyncFontSpecs ();
X}
X
X
X/*
X Add the fonts contained in the STR# whose id is fontStrNum
X to the font list (or replace the list with those fonts).
X*/
X
XStrFonts (ask)
XBoolean ask;
X{
XHandle h;
Xregister Integer i, j, len;
XInteger nStrings;
XStr255 s;
XLongint fNum;
X
X if (ask)
X {
X if (ReplaceOrAdd () == false)
X return;
X }
X
X h = GetResource ('STR#', fontStrNum);
X nStrings = * (Integer *) *h;
X
X for (i = 0; i < nStrings; ++i)
X {
X GetIndString (s, fontStrNum, i + 1);
X if (s[1] == '#')
X continue; /* comment - ignore */
X len = s[0];
X j = 1;
X while (j <= len && s[j] != '/')
X ++j;
X if (j > len) /* error */
X {
X NumToString ((Longint) fontStrNum, s);
X Message3 ("\pA font list resource (STR# ", s,
X "\p) is messed up.");
X break;
X }
X s[0] = j - 1; /* length of numeric part */
X StringToNum (s, &fNum);
X s[j] = len - j;
X if (!SetFontSpec ((Integer) fNum, &s[j]))
X break;
X }
X ReleaseResource (h);
X SyncFontSpecs ();
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWGen.c
X# include "MWMaca.h"
X# include "MWFileStuff.h"
X
X
X/*
X Prototype for data of empty paragraph
X*/
X
Xtypedef struct EmptyParaData6
X{
X Integer pTextLen;
X Integer pFmtLen;
X Format pFormat;
X} EmptyParaData6;
X
X
XEmptyParaData6 emptyParaData =
X{
X 0, /* text length = 0 (no text) */
X 6, /* format data length (1 format) */
X { 0, 12, 0, 1} /* format: pos 0, size 12, style */
X /* plain, application font */
X};
X
X
XUPrintRec uPrintRec; /* not initialized - doesn't matter? */
X
X
XRuler stdRuler =
X{
X 10, /* left margin */
X 480, /* right margin */
X leftJust, /* justification */
X 10, /* number of tabs */
X 0, /* line spacing = single */
X 10, /* indentation of first line */
X { 40, 80, 120, 160, 200, /* tab values */
X 240, 280, 320, 360, 400 }, /* tab values */
X { 0, 0, 0, 0 } /* four bytes fill */
X};
X
X
X
XGlobals6 globals =
X{
X 6, /* MacWrite 4.5 = version 6 */
X 0, /* main doc para count - fill in later */
X 2, /* header para count */
X /* (one ruler + 1 empty text para) */
X 2, /* footer para count */
X /* (one ruler + 1 empty text para) */
X 0, /* title page flag */
X 0, /* unused */
X 0, /* scrap not displayed */
X 0, /* footer not displayed */
X 0, /* header not displayed */
X 0, /* rulers displayed */
X -1, /* active document: -1 tells MacWrite */
X /* to recalc display information */
X 1, /* starting page = 1 */
X 0L, /* free list position - fill in later */
X 8, /* free list length */
X 8, /* # bytes allocated for list */
X { 0, 0, 0, 0, 0, 0, 0, /* unused */
X 0, 0, 0, 0, 0, 0, 0 } /* unused */
X};
X
X
XWindows6 windowVars =
X{
X { 1, 0 }, /* start of selection (para 1, char 0) */
X { 1, 0 }, /* end of selection (para 1, char 0) */
X 0, /* vertical offset */
X 0, /* first paragraph to redraw */
X 0L, /* position of information array */
X /* (filled in later) */
X 0, /* length of information array */
X /* (filled in later) */
X 0L, /* position of line height array */
X /* (filled in later) */
X 0, /* length of line height array */
X /* (filled in later) */
X { -14, 30 }, /* page icon position */
X { -14, 236 }, /* date icon position */
X { -14, 442 }, /* time icon position */
X { -1, -1, -1, -1 }, /* four bytes fill */
X -1, /* redraw ovals (icons) */
X 0, /* don't redraw rulers */
X { -1, -1 }, /* face active when saved */
X /* (-1 = "has never been set") */
X -1 /* font active when saved */
X /* (-1 = "has never been set") */
X};
X
X
XParaInfo6 rulerParaInfo;
XParaInfo6 nullTextParaInfo;
X
X
XBoolean SetParaInfo (p, height, status, dataPos, dataLen, comFormats)
Xregister ParaInfo6 *p;
XInteger height;
XByte status;
XLongint dataPos;
XInteger dataLen;
XInteger comFormats;
X{
X
X# ifdef debug
X DisplayString ("\p{SetParaInfo}");
X# endif
X
X p->paraHeight = height;
X p->paraPos = 0;
X p->paraHandle = nil;
X p->paraStOff.paraOffset = dataPos; /* this first */
X p->paraStOff.paraStatus = status; /* *then* this! */
X p->paraLen = dataLen;
X p->paraFmts = comFormats;
X
X return (true);
X}
X
X
X/*
X Write file prelude, using prototype structures.
X Global variables
X Universal print record
X Footer document variables
X Header document variables
X Main document varables
X
X Some of these will be patched in the postlude.
X
X Also write as much of the invariant file contents as possible:
X Footer document contents (1 ruler + 1 empty text paragraph)
X Header document contents (1 ruler + 1 empty text paragraph)
X Initial ruler of main document
X*/
X
XBoolean WritePrelude (f)
Xregister Integer f;
X{
X
X return (FileWrite (f, &globals, (Longint) sizeof (Globals6))
X && FileWrite (f, &uPrintRec, (Longint) sizeof (UPrintRec))
X && FileWrite (f, &windowVars, (Longint) sizeof (Windows6))
X && FileWrite (f, &windowVars, (Longint) sizeof (Windows6))
X && FileWrite (f, &windowVars, (Longint) sizeof (Windows6))
X && ZeroPad (f, 6)
X && FileWrite (f, &stdRuler, (Longint) sizeof (Ruler))
X && FileWrite (f, &emptyParaData, (Longint) sizeof (EmptyParaData6))
X && FileWrite (f, &stdRuler, (Longint) sizeof (Ruler))
X && FileWrite (f, &emptyParaData, (Longint) sizeof (EmptyParaData6))
X && FileWrite (f, &stdRuler, (Longint) sizeof (Ruler))
X );
X}
X
X
X/*
X Write line height array, one entry for each paragraph. First
X para is always a ruler - write a zero word. Other paras are
X faked by writing information that there's one line in the para
X of height 16 (12-point height). MacWrite will fix when it reads
X the file.
X
X paraCount assumed >= 2.
X*/
X
XBoolean WriteLineHeights (f, paraCount)
XInteger f;
XInteger paraCount;
X{
X
X if (!WriteInteger (f, 0))
X return (false);
X
X while (--paraCount > 0)
X {
X if (!WriteLongint (f, 0x00011010))
X return (false);
X }
X
X return (true);
X}
X
X
X/*
X Write line height and paragraph info positions and lengths
X*/
X
XBoolean WriteArrayInfo (f, seek, piPos, piLen, lhPos, lhLen)
XInteger f;
XLongint seek;
XLongint piPos;
XInteger piLen;
XLongint lhPos;
XInteger lhLen;
X{
X
X FileSeek (f, seek);
X return (WriteLongint (f, piPos) && WriteInteger (f, piLen)
X && WriteLongint (f, lhPos) && WriteInteger (f, lhLen));
X}
X
X
X/*
X Paragraph data are all written now. The line height and paragraph
X info arrays must now be written, as well as an empty free list.
X Save the positions of these arrays, as they must be patched into
X the window variables.
X
X The paraCount and paraInfo are for the text paragraphs only.
X When the main document paragraph count and paragraph information
X are length are patched into the globals, increment to take
X into account the initial ruler (written during prelude).
X*/
X
XBoolean WritePostlude (f, paraCount, paraInfo)
Xregister Integer f;
XInteger paraCount;
XPIAHandle paraInfo;
X{
XLongint fLHPos, fPIPos; /* footer line height, para info array pos */
XLongint hLHPos, hPIPos; /* header line height, para info array pos */
XLongint mLHPos, mPIPos; /* main line height, para info array pos */
XInteger paraInfoLen; /* length of main para info array */
XInteger defInfoLen; /* length of header, footer pi array */
XInteger defLHLen; /* length of header, footer line height array */
XInteger mainLHLen; /* length of main line height array */
XLongint freeListPos; /* free list pos */
XBoolean result;
X
X/*
X Set up prototype ruler paragraph and null text paragraph
X information array elements. The position field must be filled
X in on a per-window basis.
X*/
X
X SetParaInfo (&rulerParaInfo, 0, 0, (Longint) 0x130, 34, 0);
X SetParaInfo (&nullTextParaInfo, 16, 0, (Longint) 0x152, 10, 0);
X
X/*
X For footer
X*/
X
X fLHPos = FilePos (f);
X if (!WriteLineHeights (f, 2))
X return (false);
X
X fPIPos = FilePos (f);
X if (!FileWrite (f, &rulerParaInfo, (Longint) sizeof (ParaInfo6))
X || !FileWrite (f, &nullTextParaInfo, (Longint) sizeof (ParaInfo6)))
X return (false);
X
X/*
X For header
X*/
X
X hLHPos = FilePos (f);
X if (!WriteLineHeights (f, 2))
X return (false);
X
X rulerParaInfo.paraStOff.paraOffset += sizeof (Ruler) + sizeof (EmptyParaData6);
X nullTextParaInfo.paraStOff.paraOffset += sizeof (Ruler) + sizeof (EmptyParaData6);
X
X hPIPos = FilePos (f);
X
X if (!FileWrite (f, &rulerParaInfo, (Longint) sizeof (ParaInfo6))
X || !FileWrite (f, &nullTextParaInfo, (Longint) sizeof (ParaInfo6)))
X return (false);
X
X/*
X For main
X*/
X
X mLHPos = FilePos (f);
X if (!WriteLineHeights (f, paraCount + 1))
X return (false);
X
X rulerParaInfo.paraStOff.paraOffset += sizeof (Ruler) + sizeof (EmptyParaData6);
X
X mPIPos = FilePos (f);
X
X if (!FileWrite (f, &rulerParaInfo, (Longint) sizeof (ParaInfo6)))
X return (false);
X
X paraInfoLen = paraCount * sizeof (ParaInfo6);
X HLock (paraInfo);
X result = FileWrite (f, *paraInfo, (Longint) paraInfoLen);
X HUnlock (paraInfo);
X if (!result)
X return (false);
X
X/*
X Write free list. It's at the end of the file, so set the
X file EOF here, too.
X*/
X
X freeListPos = FilePos (f);
X if (!WriteLongint (f, freeListPos + 8) || !WriteLongint (f, 0L))
X return (false);
X
X (void) SetEOF (f, FilePos (f));
X
X/*
X Now patch globals and window variables:
X main doc para count (increment to account for ruler)
X free list position
X line height and para info array positions (and para info array
X length for main document)
X*/
X
X FileSeek (f, 2L);
X ++paraCount;
X paraInfoLen += sizeof (ParaInfo6);
X if (!WriteInteger (f, paraCount))
X return (false);
X FileSeek (f, 18L);
X if (!WriteLongint (f, freeListPos))
X return (false);
X
X defInfoLen = 2 * sizeof (ParaInfo6);
X defLHLen = 3 * sizeof (Integer);
X mainLHLen = sizeof (Integer) + (paraCount-1) * sizeof (Longint);
X if (!WriteArrayInfo (f, 172L, fPIPos, defInfoLen, fLHPos, defLHLen)
X || !WriteArrayInfo (f, 218L, hPIPos, defInfoLen, hLHPos, defLHLen)
X || !WriteArrayInfo (f, 264L, mPIPos, paraInfoLen, mLHPos, mainLHLen))
X return (false);
X
X return (true);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWIO.c
X/*
X MakeWrite File I/O Routines.
X*/
X
X
X# include "MakeWrite.h"
X# include "MWFileStuff.h"
X# include "MWMaca.h"
X# include <StdFilePkg.h>
X
X
Xstatic SFReply inFile;
Xstatic SFReply outFile;
Xstatic Str255 fName; /* map name and volume reference number */
Xstatic Integer vRefNum;
X
X
X/*
X Clear the current file name, and reset the title of the map
X window. Obviously, the first call to this must occur
X after the map window is initialized.
X*/
X
XClearMapName ()
X{
X CopyString ("\pUntitled", fName);
X SetMapName (fName);
X}
X
X
XSetMapName (name)
XStringPtr name;
X{
XStr255 s;
X
X CopyString ("\pMap Name: ", s);
X AppendString (name, s);
X SetWTitle (mapWind, s);
X}
X
X
X/*
X Check a ConvSpec to see that it makes sense
X*/
X
Xstatic Boolean CheckMSpec (m)
XMapSpec *m;
X{
XInteger errCnt = 0;
X
X if (FontIndex (m->font) < 0)
X {
X ErrWindMsge ("\pUnknown font number: ", m->font);
X ++errCnt;
X }
X if (SizeIndex ((Integer) m->size) < 0)
X {
X ErrWindMsge ("\pUnknown size: ", (Integer) m->size);
X ++errCnt;
X }
X
X return (errCnt == 0);
X}
X
X
X/*
X Read paragraph style variables
X*/
X
Xstatic Boolean ReadParaStyle (f, version)
XInteger f;
XInteger version;
X{
X if (version == 1)
X {
X InitParaStyle (); /* use defaults */
X return (true);
X }
X return (FileRead (f, ¶Style, (Longint) sizeof (ParaStyle))
X && ReadString (f, paraMark)
X && ReadString (f, pageMark)
X && ReadString (f, periodStr)
X && ReadString (f, quoteStr));
X}
X
X
X/*
X Read one map specification from a file. First read the MapSpec
X structure, being careful not to clobber the mark string handle.
X Then read the string that gets put into the handle (first the
X length byte, then the rest of the string).
X*/
X
Xstatic Boolean ReadMSpec (f, m)
Xregister Integer f;
Xregister MapSpec *m;
X{
XStringHandle hStr;
XBoolean ok;
X
X hStr = m->mark; /* save since clobbered by next read */
X ok = FileRead (f, m, (Longint) sizeof (MapSpec));
X m->mark = hStr;
X if (ok)
X {
X HLock (hStr);
X ok = ReadString (f, *hStr);
X HUnlock (hStr);
X }
X return (ok);
X}
X
X
X/*
X Read map specifications from a file. Duplicate or illegal
X specifications are not added.
X
X Assumes file is open and all mappings already cleared (for Open) or
X not (for Append). If setParaInfo is true (Open), paragraph style
X info is set. If it's false (Append), it's not set.
X
X Does not set undo variables or map-changed variables.
X*/
X
Xstatic ReadMap (f, setParaInfo)
XInteger f;
XBoolean setParaInfo;
X{
XMapSpec mSpec;
XInteger badCnt = 0;
XInteger ver;
XInteger i, nLines;
XStr255 str;
XBoolean ok;
X
X InitMSpec (&mSpec);
X ErrWindInit (inFile.fName);
X if (!ReadInteger (f, &ver))
X {
X Message1 ("\pCan't read map file.");
X }
X else if (ver != mapVersion && ver != 1)
X {
X NumToString ((Longint) ver, str);
X Message2 ("\pUnknown map file version: ", str);
X }
X else if (ReadInteger (f, &nLines))
X {
X ok = true;
X for (i = 0; i < nLines; ++i)
X {
X ok = false;
X if (!ReadMSpec (f, &mSpec))
X break;
X ok = true;
X
X/*
X Need to check legality here, since the file may have been
X created using the fonts from a font list other than the current
X one.
X*/
X
X if (CheckMSpec (&mSpec) == false)
X {
X ++badCnt;
X continue; /* its bad - don't use it */
X }
X
X if (StatMSpec (&mSpec))
X {
X ++badCnt;
X continue; /* already exists - don't use dups */
X }
X
X if (InsertMapping (&mSpec, mapList->nLines) == false)
X break;
X }
X if (ok && setParaInfo)
X (void) ReadParaStyle (f, ver);
X }
X
X TermMSpec (&mSpec);
X
X (void) FSClose (f);
X ScrollToLine (mapList, 0); /* force scroll to top */
X SelectMapping (noLine); /* but leave unselected */
X
X if (badCnt)
X {
X NumToString ((Longint) badCnt, str);
X Message2 (str, "\p illegal or duplicate specifications were found and ignored");
X }
X}
X
X
X/*
X Open a map. Clobber the current map first, set the map name
X afterward.
X*/
X
XBoolean OpenMap ()
X{
XInteger f;
X
X if (GetInputFile ("\pOpen", mwType, &inFile)
X && OpenInputFile (&inFile, &f))
X {
X ClobberMap ();
X ReadMap (f, true);
X CopyString (inFile.fName, fName);
X vRefNum = inFile.vRefNum;
X SetMapName (fName);
X return (true);
X }
X return (false);
X}
X
X
X/*
X Add a map to the current map. Doesn't set map name afterward.
X*/
X
XBoolean AddMap ()
X{
XInteger f;
X
X if (GetInputFile ("\pAdd", mwType, &inFile)
X && OpenInputFile (&inFile, &f))
X {
X ReadMap (f, false);
X return (true);
X }
X return (false);
X}
X
X
X/*
X Save map to file. askForName is true if should ask for name,
X otherwise use current name. If name is "Untitled", ask for a name
X anyway. Sets the current name if it wasn't already set.
X
X The file is deleted if not written properly.
X*/
X
XBoolean SaveMap (askForName)
XBoolean askForName;
X{
XInteger f;
Xregister Integer i;
XOSErr result;
XLongint pos;
XBoolean ok = false;
XStringHandle hStr;
X
X if (GetOutputFile (askForName, fName, vRefNum, &outFile) == false)
X return (false);
X if (OpenOutputFile (&outFile, mwCreator, mwType, &f) == false)
X return (false);
X
X if (WriteInteger (f, (Integer) mapVersion)
X && WriteInteger (f, (Integer) mapList->nLines))
X {
X ok = true;
X for (i = 0; i < mapList->nLines; ++i)
X {
X ok = FileWrite (f, &mapSpec[i], (Longint) sizeof (MapSpec));
X if (!ok)
X break;
X hStr = mapSpec[i].mark;
X HLock (hStr);
X ok = WriteString (f, *hStr);
X HUnlock (hStr);
X if (!ok)
X break;
X }
X if (ok)
X {
X ok = FileWrite (f, ¶Style, (Longint) sizeof (ParaStyle))
X && WriteString (f, paraMark)
X && WriteString (f, pageMark)
X && WriteString (f, periodStr)
X && WriteString (f, quoteStr);
X }
X }
X
X (void) GetFPos (f, &pos);
X (void) SetEOF (f, pos);
X (void) FSClose (f);
X (void) FlushVol (f, outFile.vRefNum);
X
X if (!ok)
X {
X Message1 ("\pCould not write map");
X (void) FSDelete (outFile.fName, outFile.vRefNum);
X return (false);
X }
X
X CopyString (outFile.fName, fName); /* set map name */
X vRefNum = outFile.vRefNum;
X SetMapName (fName);
X return (true);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMSpecOps.c
X# include "MWMapInfo.h"
X
X
X/*
X Initialize a MapSpec by allocating a mark string for it.
X*/
X
XInitMSpec (mSpec)
XMapSpec *mSpec;
X{
X mSpec->mark = (StringHandle) NewHandle ((Size) maxMarkLen + 1);
X}
X
X
X/*
X Terminate a MapSpec by tossing its mark string. The procedure
X name is somewhat of a misnomer since it doesn't actually dispose
X of the MapSpec itself.
X*/
X
XTermMSpec (mSpec)
XMapSpec *mSpec;
X{
X DisposHandle (mSpec->mark);
X}
X
X
X/*
X Copy one init'ed MapSpec to another. The most difficult part
X is making sure the mark string gets copied correctly.
X*/
X
XCopyMSpec (srcMSpec, dstMSpec)
Xregister MapSpec *srcMSpec, *dstMSpec;
X{
Xregister StringHandle srcStr, dstStr;
X
X dstStr = dstMSpec->mark; /* save, since next line clobbers it */
X *dstMSpec = *srcMSpec;
X dstMSpec->mark = dstStr; /* fix this field and copy the handle */
X srcStr = srcMSpec->mark;
X HLock (srcStr);
X HLock (dstStr);
X CopyString (*srcStr, *dstStr);
X HUnlock (srcStr);
X HUnlock (dstStr);
X /*SetHandleSize (dstStr, (Size) 0);
X HandAndHand (srcMSpec->mark, dstStr);*/
X}
X
X
X/*
X Zero the contents of an init'ed MapSpec.
X*/
X
X
XClearMSpec (mSpec)
Xregister MapSpec *mSpec;
X{
X mSpec->font = sameFont;
X mSpec->size = sameSize;
X mSpec->style = sameStyle;
X (*mSpec->mark)[0] = 0;
X mSpec->selStart = 0;
X mSpec->selEnd = 0;
X}
X
X
X/*
X Compare two markers for equality.
X*/
X
XCompareMark (s1, s2)
XStringHandle s1, s2;
X{
XInteger result;
X
X HLock (s1);
X HLock (s2);
X result = CompareString (*s1, *s2);
X HUnlock (s1);
X HUnlock (s2);
X return (result);
X}
X
X
X/*
X Compare two map specifications.
X Return:
X 0 m1 = m2
X < 0 m1 < m2
X > 0 m1 > m2
X
X Mark sorts before font, which sorts before size, which sorts
X before style.
X
X For all of font, size and style, the "same" selection is greater,
X so that generic selections sort to the end of the list. Font
X comparisons are otherwise based on the name of the font, rather
X than its number. A string compare is avoided by keeping the
X fonts in alphabetic order in the font information structures.
X
X Note that the style comparison does not use the manifest constants
X defined for each style value, and so would break if style coding
X changed!
X*/
X
XCompareMSpec (m1, m2)
Xregister MapSpec *m1, *m2;
X{
Xregister Integer i;
Xregister Integer s1, s2;
X
X if ((i = CompareMark (m1->mark, m2->mark)) != 0)
X return (i);
X
X if (m1->font != m2->font)
X {
X if (m1->font == sameFont)
X return (1);
X if (m2->font == sameFont)
X return (-1);
X return (FontIndex (m1->font) - FontIndex (m2->font));
X }
X
X if ((i = m1->size - m2->size) != 0)
X {
X if (m1->size == sameSize)
X return (1);
X if (m2->size == sameSize)
X return (-1);
X return (i);
X }
X
X s1 = m1->style;
X s2 = m2->style;
X if (s1 - s2 != 0)
X {
X if (s1 == sameStyle)
X return (1);
X if (s2 == sameStyle)
X return (-1);
X for (i = 0; i < 7; ++i)
X {
X if (s1 == 0)
X {
X if (s2 != 0)
X return (-1);
X }
X else if (s2 == 0)
X {
X return (1);
X }
X else if (s1 & 1)
X {
X if (!(s2 & 1))
X return (-1);
X }
X else if (s2 & 1)
X return (1);
X s1 >>= 1;
X s2 >>= 1;
X }
X }
X return (0); /* equal */
X}
X
X
X/*
X Convert map specs to map text. Do this by converting input specs
X and output specs.
X*/
X
XMSpecToMStr (mSpec, mStr)
Xregister MapSpec *mSpec;
Xregister MapStr *mStr;
X{
X HLock (mSpec->mark);
X CopyString (*mSpec->mark, mStr->markStr);
X HUnlock (mSpec->mark);
X FontToStr (mSpec->font, mStr->fontStr);
X SizeToStr (mSpec->size, mStr->sizeStr);
X StyleToStr (mSpec->style, mStr->styleStr);
X}
X
X
X/*
X Convert font number to font name. The font *must* be legal.
X*/
X
XFontToStr (font, str)
Xregister Integer font;
Xregister StringPtr str;
X{
X FontName (FontIndex (font), str);
X}
X
X
X/*
X Convert size value to string.
X*/
X
XSizeToStr (size, str)
Xregister Integer size;
Xregister StringPtr str;
X{
X if (size == sameSize) /* no size specified, use default */
X CopyString ("\pSame", str);
X else
X NumToString ((Longint) size, str);
X}
X
X
X/*
X Convert style value to string. If the style has only one attribute
X bit set, use the attribute name, otherwise use abbreviated form with
X one letter for each attribute.
X*/
X
Xstatic StringPtr styleStr[7] =
X{
X (StringPtr) "\pBold",
X (StringPtr) "\pItalic",
X (StringPtr) "\pUnder",
X (StringPtr) "\pOutline",
X (StringPtr) "\pShadow",
X (StringPtr) "\pHigh",
X (StringPtr) "\pLow"
X};
X
X
XStyleToStr (style, str)
Xregister Integer style;
Xregister StringPtr str;
X{
Xregister Integer i, style2;
X
X if (style == sameStyle) /* no style specified, use default */
X CopyString ("\pSame", str);
X else if (style == 0) /* no bits set = plain text */
X CopyString ("\pPlain", str);
X else
X {
X style2 = style;
X for (i = 0; i < 7; ++i)
X {
X if ((style2 & 1))
X {
X if (style2 != 1)
X break; /* more than 1 bit set */
X CopyString (styleStr[i], str);
X return;
X }
X style2 >>= 1;
X }
X i = 0;
X if (style & styleBold)
X str[++i] = 'B';
X if (style & styleItalic)
X str[++i] = 'I';
X if (style & styleUnder)
X str[++i] = 'U';
X if (style & styleOutline)
X str[++i] = 'O';
X if (style & styleShadow)
X str[++i] = 'S';
X if (style & styleSuper)
X str[++i] = 'H';
X if (style & styleSub)
X str[++i] = 'L';
X str[0] = i;
X }
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMain.c
X# include "MakeWrite.h"
X
X
X/*
X Offsets of each field in the map and font lists. There is one
X extra value, which is actually the offset of the right edge of
X the last field. These offsets are relative to the text area.
X*/
X
X
X# define mapFields 4 /* number of fields in mapping */
X
X
Xstatic Integer mapOffsets[mapFields + 1] =
X{
X 0,
X 100,
X 217,
X 257,
X 313
X};
X
X
Xstatic LineList mapStruct =
X{
X nil, /* port - filled in later */
X nil, /* control - filled in later */
X { 150, 124, 246, 436 }, /* text display rect, t, l, b, r */
X 0, /* max lines (set by InitList) */
X 6, /* max visible lines */
X 0, /* top visible line */
X 16, /* line height */
X 0, /* number of lines */
X noLine, /* current line */
X false, /* no hiliting */
X mapFields, /* number of fields/line */
X mapOffsets, /* field offsets */
X nil /* line array (set by InitList) */
X};
X
X
X
XWindowPtr mapWind;
X
XListPtr mapList = &mapStruct;
XMapSpec mapSpec[maxMappings];
X
XBoolean mapModified = false;
X
XInteger undoOp = noUndo;
XInteger undoVal;
XInteger undoPos;
XInteger undoFieldType;
XMapSpec undoMSpec;
XBoolean undoCPMarker;
X
XBoolean havePasteMSpec = false; /* for setting Paste menu item */
X
XBoolean cpMarker = false; /* whether cut/paste applies to marker */
X
X
X/*
X Paragraph style control
X
X Default is "every line a paragraph", ignore command-only lines
X*/
X
XParaStyle paraStyle;
X
XStr255 paraMark; /* paragraph marker string */
XStr255 pageMark; /* page break marker string */
XStr255 periodStr; /* sentence "periods" (terminators) */
XStr255 quoteStr; /* quotes to ignore after periods */
X
X# ifdef debug
XBoolean debugOut = false; /* controls debugging output during format */
X# endif
X
X
Xmain ()
X{
X SkelInit ();
X InitParaStyle ();
X SetupMenus ();
X MapSetup ();
X SkelMain ();
X SkelClobber ();
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMapOps.c
X# include "MakeWrite.h"
X
X
X/*
X Check whether a MapSpec already exists in the map
X*/
X
XBoolean StatMSpec (mSpec)
XMapSpec *mSpec;
X{
Xregister Integer i;
X
X for (i = 0; i < mapList->nLines; ++i)
X {
X if (CompareMSpec (mSpec, &mapSpec[i]) == 0)
X return (true);
X }
X return (false);
X}
X
X
X
X/*
X Insert the text of all the fields for the given map list line.
X
X This routines relies implicitly on the ordering of fields
X within a map line.
X*/
X
Xstatic SetMapFields (hLine, mStr)
Xregister LineHandle hLine;
Xregister MapStr *mStr;
X{
Xregister FieldHandle hField;
X
X hField = hLine;
X SetFieldStr (hField, mStr->markStr);
X hField = NextField (hField);
X SetFieldStr (hField, mStr->fontStr);
X hField = NextField (hField);
X SetFieldStr (hField, mStr->sizeStr);
X hField = NextField (hField);
X SetFieldStr (hField, mStr->styleStr);
X}
X
X
X/*
X Select a mapping
X*/
X
XSelectMapping (lineNo)
Xregister Integer lineNo;
X{
X SelectLine (mapList, lineNo);
X if (lineNo != noLine)
X ScrollToLine (mapList, lineNo);
X SetSelectors (lineNo);
X}
X
X
X/*
X Insert a new mapping, making it mapping n. This takes care
X of both the specification array, and the list of text representations
X of the mappings.
X
X Note that there's no explicit count of mappings. Use the count
X in the LineList corresponding to the mapping array is used.
X*/
X
XBoolean InsertMapping (mSpec, n)
XMapSpec *mSpec;
XInteger n;
X{
XMapStr mStr;
Xregister LineHandle hLine;
Xregister Integer i, nLines;
XStr255 s;
X
X if (mapList->nLines < mapList->maxLines)
X {
X
X/*
X Convert mapping specification into string form and put the strings
X into a new line to be inserted into the line list.
X
X Then make room for the new mapping in spec array and insert it.
X*/
X
X nLines = mapList->nLines; /* save; InsertLine changes it */
X MSpecToMStr (mSpec, &mStr); /* convert specs to strings */
X hLine = NewLine (mapList->nFields);
X SetMapFields (hLine, &mStr);
X if (InsertLine (mapList, hLine, n) == false)
X {
X DisposeLine (hLine);
X }
X else
X {
X/*
X Move specs around to make room, then add the new one
X in the empty slot.
X*/
X for (i = nLines; i > n; --i)
X {
X CopyMSpec (&mapSpec[i-1], &mapSpec[i]);
X }
X CopyMSpec (mSpec, &mapSpec[n]);
X /*mapSpec[n].selStart = 0;
X mapSpec[n].selEnd = 32767;*/
X SelectMapping (n);
X /*SetCPMarker (true);*/
X return (true);
X }
X }
X NumToString ((Longint) mapList->maxLines, s);
X Message3 ("\pMap is full (", s, "\p lines). Can't add anything to it.");
X return (false);
X}
X
X
X/*
X Add a new, blank, mapping to the end of the list.
X This should be different - the handle should be copied in InsertMapping.
X*/
X
XNewMapping ()
X{
XMapSpec mSpec;
X
X InitMSpec (&mSpec);
X ClearMSpec (&mSpec);
X (void) InsertMapping (&mSpec, mapList->nLines);
X TermMSpec (&mSpec);
X}
X
X
X/*
X Duplicate the currently selected mapping and add right after the
X selection.
X*/
X
XDupMapping (n)
X{
X (void) InsertMapping (&mapSpec[n], n+1);
X}
X
X
X/*
X Replace the currently selected mapping with the given one.
X (It's assumed that there *is* one selected.)
X*/
X
XPasteMapping (mSpec, n)
XMapSpec *mSpec;
XInteger n;
X{
XMapStr mStr;
Xregister Integer curLine;
X
X curLine = mapList->curLine;
X CopyMSpec (mSpec, &mapSpec[curLine]);
X MSpecToMStr (mSpec, &mStr);
X SetMapFields (ListLine (mapList, curLine), &mStr);
X DrawLine (mapList, curLine);
X SetSelectors (curLine); /* set selection controls */
X}
X
X
X/*
X Clobber the n'th mapping.
X*/
X
XDeleteMapping (n)
Xregister Integer n;
X{
Xregister Integer i;
X
X for (i = n; i < mapList->nLines; ++i)
X {
X CopyMSpec (&mapSpec[i+1], &mapSpec[i]); /* copy specs */
X }
X DeleteLine (mapList, n);
X SelectMapping (noLine);
X ScrollToLine (mapList, n);
X}
X
X
X/*
X Clobber entire map.
X*/
X
XClobberMap ()
X{
X SelectMapping (noLine);
X ResetList (mapList);
X InitParaStyle ();
X}
X
X
X
X/*
X Sort the map specifications on the input format values. Make
X sure to keep track of the current spec and redraw the text
X and controls properly when done.
X*/
X
XSortMap ()
X{
Xregister Integer i, j, curLine;
Xregister LineHandle tmpLine;
XMapSpec tmpSpec;
X
X InitMSpec (&tmpSpec);
X curLine = mapList->curLine;
X for (i = 0; i < mapList->nLines - 1; ++i)
X {
X for (j = i; j < mapList->nLines; ++j)
X {
X if (CompareMSpec (&mapSpec[i], &mapSpec[j]) > 0)
X {
X CopyMSpec (&mapSpec[i], &tmpSpec);
X CopyMSpec (&mapSpec[j], &mapSpec[i]);
X CopyMSpec (&tmpSpec, &mapSpec[j]);
X tmpLine = ListLine (mapList, i);
X ListLine (mapList, i) = ListLine (mapList, j);
X ListLine (mapList, j) = tmpLine;
X if (curLine == i)
X curLine = j;
X else if (curLine == j)
X curLine = i;
X }
X }
X }
X DrawListText (mapList);
X SelectMapping (curLine);
X TermMSpec (&tmpSpec);
X}
X
X
X/*
X Eliminate duplicates in the map. The loops must explicitly
X test mapList->nLines, not a variable set equal to that before
X the loops, since DeleteMapping causes mapList->nLines to change.
X*/
X
XSquishMap ()
X{
Xregister Integer i, j;
X
X for (i = 0; i < mapList->nLines; ++i)
X {
X j = i + 1;
X while (j < mapList->nLines)
X {
X if (CompareMSpec (&mapSpec[i], &mapSpec[j]) == 0)
X DeleteMapping (j);
X else
X ++j;
X }
X }
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMapWind.c
X# include <TextEdit.h>
X# include "MakeWrite.h"
X
X
X# define tab '\t'
X# define shiftKey 0x0200
X# define applFont 1
X
X
X/*
X Local data for creating controls
X*/
X
X
X/*
X maxSize = number of point-size selection radio buttons
X maxStyle = number of style selection check boxes
X maxCP = number of edit menu cut/paste indicator controls
X maxCtrl = sum of above three
X maxFonts = maximum number of fonts allowed in scrollable list
X*/
X
X# define maxSize 7
X# define maxStyle 9
X# define maxCP 2
X# define maxCtrl (maxSize+maxStyle+maxCP)
X# define maxFonts 102
X
X
Xtypedef enum /* control types, by function */
X{
X sizeType, /* size radio button */
X styleType, /* style check box */
X cpType /* edit menu check box */
X};
X
X
Xtypedef struct CtrlInfo
X{
X Str255 cTitle; /* initial control title */
X Integer ch, cv; /* location of upper left corner */
X} CtrlInfo;
X
X
Xstatic CtrlInfo ctrlInfo[maxCtrl] =
X{
X { "\pSame", 181, 20 },
X { "\p9", 172, 40 },
X { "\p10", 172, 60 },
X { "\p12", 172, 80 },
X { "\p14", 217, 40 },
X { "\p18", 217, 60 },
X { "\p24", 217, 80 },
X { "\pSame", 312, 20 },
X { "\pPlain", 265, 40 },
X { "\pBold", 265, 60 },
X { "\pItalic", 265, 80 },
X { "\pUnderline", 265, 100 },
X { "\pOutline", 355, 40 },
X { "\pShadow", 355, 60 },
X { "\pSuperscript", 355, 80 },
X { "\pSubscript", 355, 100 },
X { "\pMarker", 9, 210 },
X { "\pMap Lines", 9, 230 }
X};
X
X
Xstatic ControlHandle sizeCtrl[maxSize];
Xstatic ControlHandle styleCtrl[maxStyle];
Xstatic ControlHandle cpCtrl[maxCP];
X
X
X
X/*
X Standard MacWrite point sizes, plus the "same size" selection.
X The order of these corresponds to the size radio buttons.
X*/
X
Xstatic Integer sizeInfo[maxSize] = { sameSize, 9, 10, 12, 14, 18, 24 };
X
X
X/*
X Masks for manipulating style selections. The order of these
X corresponds to the style check boxes.
X*/
X
X
Xstatic Integer styleMask[maxStyle] =
X{
X sameStyle,
X 0, /* plain; special-cased */
X styleBold,
X styleItalic,
X styleUnder,
X styleOutline,
X styleShadow,
X styleSuper,
X styleSub
X};
X
X
X/*
X Standard font specifications
X*/
X
X
Xtypedef struct
X{
X Integer fontNum;
X StringHandle fontName;
X} FontSpec;
X
X
Xstatic FontSpec fontSpecs[maxFonts];
Xstatic Integer nFontSpecs;
X
X
Xstatic Integer fontOffsets[2] = { 0, 137 };
X
X
Xstatic LineList fontStruct =
X{
X nil, /* port - filled in later */
X nil, /* control - filled in later */
X { 20, 5, 116, 141 }, /* text display rect, t, l, b, r */
X 0, /* max lines */
X 6, /* max visible lines */
X 0, /* top visible line */
X 16, /* line height */
X 0, /* number of lines */
X noLine, /* current line */
X false, /* no hiliting */
X 1, /* number of fields/line */
X fontOffsets, /* field offsets */
X nil /* line array */
X};
X
X
Xstatic ListPtr fontList = &fontStruct;
X
Xstatic MapSpec *curMSpec;
Xstatic Integer curMSpecNo;
X
Xstatic TEHandle markTE;
X
X
X/* ---------------------------------------------------------------- */
X/* General Control Operations */
X/* ---------------------------------------------------------------- */
X
X
X
X/*
X Set a control value, but only when it changes, to avoid
X unnecessary redrawing (ugly, since gobs of them are usually
X changed together).
X
X Use for check boxes and radio buttons only, not scroll bars!
X*/
X
Xstatic SetControl (ctrl, value)
XControlHandle ctrl;
XBoolean value;
X{
X if (GetCtlValue (ctrl) != value)
X SetCtlValue (ctrl, value);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Font List Operations */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Add a font to the spec list. Return false if there's overrun.
X*/
X
XBoolean SetFontSpec (fNum, fName)
XInteger fNum;
XStringPtr fName;
X{
Xregister StringHandle h;
XStr255 s;
Xregister Integer i, result;
X
X for (i = 0; i < nFontSpecs; ++i) /* see if already there */
X {
X h = fontSpecs[i].fontName;
X HLock (h);
X result = CompareString (*h, fName);
X HUnlock (h);
X if (result == 0) /* font name's a duplicate */
X return (true); /* but that's ok */
X }
X
X if (nFontSpecs >= fontList->maxLines) /* will list be too full? */
X {
X NumToString ((Longint) maxFonts - 2, s);
X Message3 ("\pSorry, I am such a brain-damaged program that I only allow ",
X s, "\p fonts!");
X return (false);
X }
X
X h = (StringHandle) NewHandle ((Longint) (fName[0] + 1));
X HLock (h);
X CopyString (fName, *h);
X HUnlock (h);
X fontSpecs[nFontSpecs].fontName = h;
X fontSpecs[nFontSpecs++].fontNum = fNum;
X return (true);
X}
X
X
X/*
X Set up to construct a new font list. Note that the other
X selector controls must have been initialized by this point.
X*/
X
XResetFontList ()
X{
Xregister Integer i;
X
X for (i = 0; i < fontList->nLines; ++i)
X DisposHandle (fontSpecs[i].fontName);
X nFontSpecs = 0;
X ResetList (fontList);
X SetFontSpec (sameFont, "\pSame");
X SetFontSpec (applFont, "\pApplication");
X}
X
X
X/*
X Sync information in fontSpec to fontList by constructing the LineList
X elements.
X*/
X
XSyncFontSpecs ()
X{
Xregister Integer i, j;
XInteger tmp;
Xregister FontSpec *f1, *f2;
XStringHandle h1, h2;
XLineHandle hField;
X
X/*
X Sort font names, except for "Same" and "Application", which
X stay at the front of the list.
X*/
X
X for (i = 2; i < nFontSpecs - 1; ++i)
X {
X for (j = i + 1; j < nFontSpecs; ++j)
X {
X f1 = &fontSpecs[i];
X f2 = &fontSpecs[j];
X h1 = f1->fontName;
X h2 = f2->fontName;
X HLock (h1);
X HLock (h2);
X if (CompareString (*h1, *h2) > 0)
X {
X f1->fontName = h2;
X f2->fontName = h1;
X tmp = f1->fontNum;
X f1->fontNum = f2->fontNum;
X f2->fontNum = tmp;
X }
X HUnlock (h1);
X HUnlock (h2);
X }
X }
X
X/*
X Add names to fontList
X*/
X
X ResetList (fontList);
X for (i = 0; i < nFontSpecs; ++i)
X {
X h1 = fontSpecs[i].fontName;
X HLock (h1);
X hField = NewLine (1);
X SetFieldStr (hField, *h1);
X HUnlock (h1);
X (void) InsertLine (fontList, hField, i);
X }
X SelectLine (fontList, 0);
X ScrollToLine (fontList, 0); /* force scroll to top */
X}
X
X
X/*
X Given a font number, find its index in the stdFontSpecs
X array. Return -1 if it's not there.
X*/
X
XFontIndex (fontNum)
XInteger fontNum;
X{
Xregister Integer i;
X
X for (i = 0; i < fontList->nLines; ++i)
X {
X if (fontNum == fontSpecs[i].fontNum)
X return (i);
X }
X return (-1);
X}
X
X
X/*
X Return a font name corresponding to the given index
X*/
X
XFontName (fontIndex, str)
XInteger fontIndex;
XStringPtr str;
X{
XStringHandle hStr;
X
X hStr = fontSpecs[fontIndex].fontName;
X HLock (hStr);
X CopyString (*hStr, str);
X HUnlock (hStr);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Size Control Operations */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Given a point size, find its index in the sizeInfo
X array. (Return -1 if it's not there.)
X*/
X
XSizeIndex (size)
XInteger size;
X{
Xregister Integer i;
X
X for (i = 0; i < maxSize; ++i)
X {
X if (size == sizeInfo[i])
X return (i);
X }
X return (-1);
X}
X
X
Xstatic SetSizeCtrls ()
X{
Xregister Integer i;
X
X for (i = 0; i < maxSize; ++i)
X SetControl (sizeCtrl[i], sizeInfo[i] == curMSpec->size);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Style Control Operations */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Set the style controls based on the current value of theStyle.
X
X The sameStyle bit and the attributes bits cause the corresponding
X boxes to be checked if they are set. If the style is zero, it's
X plain.
X*/
X
Xstatic SetStyleCtrls ()
X{
Xregister Integer i;
Xregister Boolean same;
Xregister Integer theStyle;
X
X theStyle = curMSpec->style;
X same = ((theStyle & sameStyle) != 0);
X SetControl (styleCtrl[0], same);
X
X if (same)
X {
X for (i = 1; i < maxStyle; ++i)
X SetControl (styleCtrl[i], false);
X }
X else if (theStyle == 0) /* plain */
X {
X SetControl (styleCtrl[1], true);
X for (i = 2; i < maxStyle; ++i)
X SetControl (styleCtrl[i], false);
X }
X else /* not plain */
X {
X SetControl (styleCtrl[1], false);
X for (i = 2; i < maxStyle; ++i)
X SetControl (styleCtrl[i], (theStyle & styleMask[i]) != 0);
X }
X}
X
X
X/*
X Determine style value. The argument is an index into the control
X array not a style value itself. Style controls interact in
X wretched complexity.
X
X If same is toggled on, all the other style boxes are toggled off.
X If it's toggled off, plain is toggled on.
X
X If plain is toggled on, all the other style boxes are toggled off.
X If it's toggled off, same is toggled on.
X
X The other style boxes correspond to style attributes. If any of
X them are toggled on, then same and plain are toggle off if
X they were on. If all the attributes are toggled off, plain is
X toggled on. Superscript and subscript are mutually exclusive,
X so that if one of them is toggled on, the other is toggled off.
X*/
X
Xstatic NewStyleValue (i)
Xregister Integer i;
X{
Xregister Integer curValue;
Xregister Integer theStyle;
X
X curValue = GetCtlValue (styleCtrl[i]); /* current value - new value */
X /* will be opposite */
X theStyle = curMSpec->style;
X
X if (i == 0) /* "same" box clicked */
X {
X if (curValue) /* currently same, turn off (implies plain) */
X theStyle = 0;
X else
X theStyle = styleMask[0]; /* currently off, turn on */
X }
X else if (i == 1) /* plain box clicked */
X {
X if (curValue) /* currently plain, turn off (implies same) */
X theStyle = styleMask[0];
X else
X theStyle = 0; /* currently off, turn on */
X }
X else
X {
X /*
X Flip box value.
X Can't have superscript and subscript at the same time.
X */
X if (curValue) /* currently on, turn off */
X theStyle &= ~styleMask[i];
X else /* currently off, turn on (turn same off) */
X {
X theStyle |= styleMask[i];
X theStyle &= ~styleMask[0];
X }
X
X if (i == 7) /* superscript. if turning on, turn off sub */
X {
X if (curValue == 0)
X theStyle &= ~styleMask[8];
X }
X if (i == 8) /* subscript. if turning on, turn off super */
X {
X if (curValue == 0)
X theStyle &= ~styleMask[7];
X }
X }
X return (theStyle);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Edit Menu Cut/Paste Control Operations */
X/* ---------------------------------------------------------------- */
X
X
Xstatic SetCPCtrls ()
X{
X SetControl (cpCtrl[0], cpMarker);
X SetControl (cpCtrl[1], !cpMarker);
X}
X
X
XSetCPMarker (useMarker)
XBoolean useMarker;
X{
X cpMarker = useMarker;
X SetCPCtrls ();
X}
X
X
XBlankCPCtrls ()
X{
X SetControl (cpCtrl[0], false);
X SetControl (cpCtrl[1], false);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Marker Operations */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Sync the marker edit text to a mapSpec
X*/
X
XMSpecToMark (m)
XMapSpec *m;
X{
XStringHandle s;
XRect r;
X
X s = m->mark;
X HLock (s);
X TESetSelect (0L, 32767L, markTE);
X TEDelete (markTE);
X TEInsert (*s + 1, (Longint) (*s)[0], markTE); /* replace text */
X HUnlock (s);
X TESetSelect ((Longint) m->selStart, (Longint) m->selEnd, markTE);
X}
X
X
X/*
X Sync current mapSpec to the marker edit text
X*/
X
Xstatic MarkToMSpec ()
X{
XStringHandle hStr;
XHandle h;
XInteger len;
X
X curMSpec->selStart = (**markTE).selStart;
X curMSpec->selEnd = (**markTE).selEnd;
X h = TEGetText (markTE);
X len = (**markTE).teLength;
X if (len > maxMarkLen)
X len = maxMarkLen; /* truncate length if necessary */
X hStr = curMSpec->mark;
X HLock (h);
X HLock (hStr);
X BlockMove (*h, *hStr + 1, (Longint) len);
X (*hStr)[0] = len;
X HUnlock (h);
X PasteField (mapList, mapList->curLine, markField, *hStr);
X HUnlock (hStr);
X}
X
X
Xtypedef enum /* relevant Edit menu item numbers */
X{
X cut = 3,
X copy,
X paste,
X clear
X};
X
X
XMarkerUndoSetup ()
X{
X CopyMSpec (curMSpec, &undoMSpec);
X undoOp = undoMarkerOp;
X undoPos = mapList->curLine;
X undoCPMarker = cpMarker;
X}
X
X
XBoolean EditMarker (item)
XInteger item;
X{
X if (!cpMarker)
X return (false);
X
X switch (item)
X {
X
X case cut:
X MarkerUndoSetup ();
X TECut (markTE);
X (void) ZeroScrap ();
X (void) TEToScrap ();
X break;
X
X case copy:
X TECopy (markTE);
X (void) ZeroScrap ();
X (void) TEToScrap ();
X break;
X
X case paste:
X if (curMSpec == nil) /* ignore if no line selected */
X return (false);
X MarkerUndoSetup ();
X (void) TEFromScrap ();
X TEPaste (markTE);
X break;
X
X case clear:
X MarkerUndoSetup ();
X (void) TEDelete (markTE);
X break;
X
X default:
X return (false); /* all others handled by general */
X /* edit menu handler */
X
X }
X
X MarkToMSpec (curMSpec); /* sync map with change in mark */
X if (item != copy)
X mapModified = true;
X FixMenus ();
X return (true);
X}
X
X
X/* ---------------------------------------------------------------- */
X
X
X/*
X Set a field in the currently selected line. Don't call this if
X no line is selected, or if the field already has the same value.
X*/
X
XSetMapFieldValue (fieldType, value)
XInteger fieldType;
XInteger value;
X{
XStr255 s;
X
X switch (fieldType)
X {
X
X case fontField:
X undoVal = curMSpec->font;
X FontToStr (value, s);
X curMSpec->font = value;
X SelectLine (fontList, FontIndex (value));
X break;
X
X case sizeField:
X undoVal = curMSpec->size;
X SizeToStr (value, s);
X curMSpec->size = value;
X SetSizeCtrls ();
X break;
X
X case styleField:
X undoVal = curMSpec->style;
X StyleToStr (value, s);
X curMSpec->style = value;
X SetStyleCtrls ();
X break;
X }
X
X PasteField (mapList, mapList->curLine, fieldType, s);
X mapModified = true;
X undoOp = undoFieldChg;
X undoFieldType = fieldType;
X}
X
X
X/*
X Set the selection controls and font list to reflect currently
X selected conversion specification. Also sets current MapSpec
X pointer.
X*/
X
XSetSelectors (lineNo)
XInteger lineNo;
X{
Xregister Integer i;
X
X if (lineNo == noLine) /* no map line selected */
X {
X
X curMSpec = nil;
X curMSpecNo = noLine;
X
X ListActivate (fontList, false);
X
X for (i = 0; i < maxSize; ++i)
X SetControl (sizeCtrl[i], false);
X
X for (i = 0; i < maxStyle; ++i)
X SetControl (styleCtrl[i], false);
X
X TESetSelect (0L, 32767L, markTE);
X TEDelete (markTE);
X TEDeactivate (markTE);
X
X return;
X }
X
X curMSpec = &mapSpec[curMSpecNo = lineNo];
X
X SelectLine (fontList, FontIndex (curMSpec->font));
X ListActivate (fontList, true);
X ScrollToLine (fontList, fontList->curLine);
X SetSizeCtrls ();
X SetStyleCtrls ();
X MSpecToMark (curMSpec);
X TEActivate (markTE);
X /*SetCPCtrls ();*/
X}
X
X
X/*
X Map window mouse handler.
X
X First test the scroll bars, and return if one was hit; they
X require no further action.
X
X Then check for hit in map list. If a new line was selected, set
X the selectors to the values, and disable undo.
X
X Then, if a line is currently selected, check the selection controls.
X If one is hit, change the values in the current line and reset the
X controls properly - but only if the current values *change*.
X*/
X
Xstatic Mouse (pt, t, mods)
XPoint pt;
XLongint t;
XInteger mods;
X{
XControlHandle ctrl;
XInteger index;
XInteger type;
XLongint refCon;
XInteger newVal;
XBoolean newIO;
XInteger curLine;
XRect r;
X
X if (ListTestScroll (mapList, pt) || ListTestScroll (fontList, pt))
X return;
X
X curLine = mapList->curLine; /* current line */
X if (ListTestText (mapList, pt))
X {
X if (curLine != mapList->curLine) /* different now? */
X {
X undoOp = noUndo;
X if ((curLine = mapList->curLine) != noLine)
X {
X mapSpec[curLine].selStart = 0;
X mapSpec[curLine].selEnd = 32767;
X }
X /*SetCPMarker (true);*/
X SetSelectors (curLine);
X FixMenus ();
X }
X return;
X }
X
X if (curMSpec == nil)
X return; /* no current line - controls irrelevant */
X
X if (ListTestText (fontList, pt))
X {
X if (fontList->curLine == noLine)
X SelectLine (fontList, fontList->nLines - 1);
X newVal = fontSpecs[fontList->curLine].fontNum;
X if (curMSpec->font != newVal)
X {
X SetMapFieldValue (fontField, newVal);
X FixMenus ();
X }
X return;
X }
X
X/*
X Check the edittext box
X*/
X
X r = (**markTE).viewRect;
X InsetRect (&r, -3, -3);
X if (PtInRect (pt, &r))
X {
X undoOp = noUndo;
X SetCPMarker (true);
X TEClick (pt, (mods & shiftKey) != 0, markTE);
X curMSpec->selStart = (**markTE).selStart;
X curMSpec->selEnd = (**markTE).selEnd;
X FixMenus ();
X return;
X }
X
X
X/*
X Don't need to check control type returned from FindControl - at
X this point, it can't be anything but inCheckBox. The control type
X and index is coded in the reference constant (see MakeControl).
X*/
X
X if (FindControl (pt, mapWind, &ctrl))
X {
X if (TrackControl (ctrl, pt, nil) == inCheckBox)
X {
X refCon = GetCRefCon (ctrl);
X index = refCon & 0x00ff;
X type = (refCon & 0xff00) >> 8;
X
X switch (type)
X {
X
X case sizeType:
X newVal = sizeInfo[index];
X if (newVal != curMSpec->size)
X SetMapFieldValue (sizeField, newVal);
X break;
X
X case styleType:
X newVal = NewStyleValue (index);
X if (newVal != curMSpec->style)
X SetMapFieldValue (styleField, newVal);
X break;
X
X case cpType:
X SetCPMarker (index == 0);
X undoOp = noUndo;
X break;
X
X }
X
X FixMenus ();
X }
X return;
X }
X}
X
X
X/*
X Process key click in window for mark string. On the first key
X after any other operation, save the current mark string state
X for undo. And on every key click, save the selection range. This
X is so the range can be saved properly if the window is inactivated
X and later activated, or if another line is selected and then this
X line is reselected.
X*/
X
Xstatic Key (c, mods)
Xchar c;
XInteger mods;
X{
XHandle h;
XStringHandle s;
XInteger len;
X
X if (curMSpec == nil)
X return;
X
X switch (c)
X {
X
X case tab:
X case enter:
X case cr:
X undoOp = noUndo;
X if (mods & shiftKey)
X {
X if (--curMSpecNo < 0)
X curMSpecNo = mapList->nLines - 1;
X }
X else
X {
X if (++curMSpecNo >= mapList->nLines)
X curMSpecNo = 0;
X }
X SelectMapping (curMSpecNo);
X break;
X
X default:
X if (undoOp != undoTyping) /* first char typed */
X {
X MarkerUndoSetup ();
X undoOp = undoTyping;
X }
X
X TEKey (c, markTE);
X MarkToMSpec (curMSpec);
X SetCPMarker (true);
X mapModified = true;
X FixMenus ();
X
X }
X}
X
X
Xstatic Update (resized)
XBoolean resized;
X{
Xregister Integer i;
XRect r;
X
X MoveTo (65, 14);
X DrawString ("\pFont");
X MoveTo (180, 14);
X DrawString ("\pPoint Size");
X MoveTo (322, 14);
X DrawString ("\pStyle");
X MoveTo (30, 145);
X DrawString ("\pMarker");
X MoveTo (4, 190);
X DrawString ("\pCut & Paste Ops");
X MoveTo (4, 206);
X DrawString ("\pAffect:");
X MoveTo (212, 143);
X DrawString ("\pFormat Specifications");
X DrawControls (mapWind);
X r = (**markTE).viewRect;
X EraseRect (&r);
X TEUpdate (&r, markTE);
X InsetRect (&r, -3, -3);
X FrameRect (&r);
X DrawListFrame (fontList);
X DrawListFrame (mapList);
X DrawListText (fontList);
X DrawListText (mapList);
X}
X
X
X/*
X When the window is activated, do appropriate map list and font list
X line and scroll bar hiliting, and set size and style controls to
X current values.
X
X When the window is deactivated, all hiliting is turned off, the
X scroll bars are unhilited and the size and style controls go blank.
X
X Note that SetSelectrs takes care of setting font list line and scroll
X bar hiliting; it doesn't have to be done here. It also activates
X or deactivates the text field properly.
X*/
X
Xstatic Activate (active)
XBoolean active;
X{
X if (active)
X {
X DoUpdates ();
X ListActivate (mapList, true);
X SetSelectors (mapList->curLine);
X }
X else
X {
X SetSelectors (noLine);
X ListActivate (mapList, false);
X }
X FixMenus ();
X}
X
X
Xstatic Clobber ()
X{
X HideWindow (mapWind);
X TEDispose (markTE);
X /*DisposeList (mapList);
X DisposeList (fontList);*/
X DisposeWindow (mapWind);
X}
X
X
Xstatic Idle ()
X{
X TEIdle (markTE);
X}
X
X
X/*
X Create controls. These are created in the same order as the specs
X in the ctrlInfo array.
X*/
X
Xstatic ControlHandle MakeControl (proc, type, index)
XInteger proc;
XInteger type;
XInteger index;
X{
Xstatic Integer i = 0; /* used to step through ctrlInfo array */
Xregister CtrlInfo *cInfo;
XRect r;
XStringPtr title;
Xregister Integer h, v;
XControlHandle ctrl;
X
X cInfo = &ctrlInfo[i++];
X title = cInfo->cTitle;
X h = cInfo->ch;
X v = cInfo->cv;
X SetRect (&r, h, v, h + StringWidth (title) + 20, v + 20);
X ctrl = NewControl (mapWind,
X &r,
X title,
X true,
X 0, 0, 1,
X proc,
X (Longint) (type << 8 | index));
X return (ctrl);
X}
X
X
XMapSetup ()
X{
Xregister Integer i;
XRect r;
X
X SetRect (&r, 24, 60, 480, 311);
X mapWind = NewWindow (nil, &r, "\p", false, noGrowDocProc,
X -1L, false, 0L);
X SkelWindow (mapWind,
X Mouse,
X Key,
X Update,
X Activate,
X nil,
X Clobber,
X Idle,
X true);
X
X TextFont (0); /* do this so StringWidth calculations */
X TextSize (0); /* for controls will be accurate */
X
X for (i = 0; i < maxSize; ++i)
X sizeCtrl[i] = MakeControl (radioButProc, sizeType, i);
X
X for (i = 0; i < maxStyle; ++i)
X styleCtrl[i] = MakeControl (checkBoxProc, styleType, i);
X
X for (i = 0; i < maxCP; ++i)
X cpCtrl[i] = MakeControl (radioButProc, cpType, i);
X
X SetRect (&r, 7, 152, 107, 168);
X markTE = TENew (&r, &r);
X (void) ZeroScrap ();
X
X InitList (fontList, maxFonts); /* initialize empty list */
X InitList (mapList, maxMappings);
X for (i = 0; i < maxMappings; ++i)
X InitMSpec (&mapSpec[i]);
X
X/*
X Add default set of fonts: ImageWriter fonts and LaserWriter fonts.
X Reset the list and add the two sets without asking whether to add to
X or replace the current list, since there's not really any current
X list.
X*/
X
X ResetFontList ();
X StrFonts (false);
X
X ClearMapName ();
X ShowWindow (mapWind);
X}
SHAR_EOF
exit
--- end of part 2 ---
MakeWrite Source (part 3 of 3)
Author: macintosh
Date: Sun, 22 Mar 1987 07:00
Date: Sun, 22 Mar 1987 07:00
1947 lines
44377 bytes
44377 bytes
[MakeWrite Source - part 3 of 3]
---
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# MW/MWMenu.c
# MW/MWMisc.c
# MW/MWParaDlog.c
# MW/MWTextToWrite.c
# MW/MWWindMisc.c
sed 's/^X//' << 'SHAR_EOF' > MW/MWMenu.c
X# include "MakeWrite.h"
X# include <MenuMgr.h>
X
X
X
Xtypedef enum /* File menu item numbers */
X{
X newMap = 1,
X openMap,
X appendMap,
X saveMap,
X saveMapAs,
X close,
X /* --- */
X makeWrite = 8,
X /* --- */
X quit = 10
X};
X
X
Xtypedef enum /* Edit menu item numbers */
X{
X undo = 1,
X /* --- */
X cut = 3,
X copy,
X paste,
X clear,
X /* --- */
X new = 8,
X duplicate,
X /* --- */
X sort = 11,
X squish
X};
X
X
Xtypedef enum /* Special menu items */
X{
X stdFontList = 1,
X systemFontList,
X /* --- */
X pgraphStyle = 4,
X /* --- */
X conflicts = 6,
X /* --- */
X getInfo = 8,
X /* --- */
X debugOption = 10
X};
X
X
Xstatic MenuHandle fileMenu;
Xstatic MenuHandle editMenu;
Xstatic MenuHandle specialMenu;
X
Xstatic MapSpec clipMSpec; /* clipboard specification */
X
X
X/*
X Enable or disable menu or menu items, according to the string.
X First char of string is for entire menu, following chars are
X for successive items. '0' disables, '1' enables.
X
X Return true if the status of the menu itself changed
X value, i.e., if the menu bar now needs redrawing.
X*/
X
XBoolean SetMenuStatus (m, s)
XMenuHandle m;
XStringPtr s;
X{
Xregister Integer i;
XInteger menuState;
X
X menuState = ((**m).enableFlags & 1); /* current state of menu */
X for (i = 1; i <= s[0]; ++i)
X {
X if (s[i] == '0')
X DisableItem (m, i - 1);
X else
X EnableItem (m, i - 1);
X }
X return (menuState != ((**m).enableFlags & 1));
X}
X
X
X/*
X Fix up menus to match window states. There will always be some
X window.
X
X Note the handling of strings. Those that may change need to be
X CopyString'ed into the string, otherwise the string constant
X itself will be changed.
X
X This routine is stupid about setting cut&paste types of items.
X*/
X
XFixMenus ()
X{
XWindowPtr frontWind;
XInteger theKind;
XInteger nLines;
XInteger curLine;
XBoolean drawBar = false;
XStr255 eString;
Xregister StringPtr fStr,
X eStr = eString, /* initial setting, may change */
X oStr;
X
X curLine = mapList->curLine;
X nLines = mapList->nLines;
X frontWind = FrontWindow ();
X theKind = ((WindowPeek) frontWind)->windowKind;
X
X if (frontWind == mapWind)
X {
X fStr = (StringPtr) "\p11111100101";
X oStr = (StringPtr) "\p11101010101";
X CopyString ("\p1101111011011", eStr); /* points to eString */
X
X if (undoOp == noUndo)
X eStr[undo + 1] = '0';
X
X if (curLine == noLine)
X {
X cpMarker = false; /* no line - *can't* apply to marker */
X eStr[cut + 1] = '0';
X eStr[copy + 1] = '0';
X eStr[clear + 1] = '0';
X eStr[duplicate + 1] = '0';
X if (havePasteMSpec == false)
X eStr[paste + 1] = '0';
X }
X else if (cpMarker == false) /* line but c/p applies to map */
X {
X if (havePasteMSpec == false)
X eStr[paste + 1] = '0';
X }
X
X if (nLines < 2)
X {
X eStr[sort + 1] = '0';
X eStr[squish + 1] = '0';
X }
X else if (nLines >= mapList->maxLines)
X {
X if (cpMarker == false && curLine == noLine)
X eStr[paste + 1] = '0';
X eStr[new + 1] = '0';
X eStr[duplicate + 1] = '0';
X }
X
X/*
X now figure out how to set the cut/paste indicators. They're
X blank if there's no current line and can't paste. Else set
X according to the current state of indicator flag.
X*/
X
X if (curLine == noLine && eStr[paste+1] == '0')
X BlankCPCtrls ();
X else
X SetCPMarker (cpMarker);
X }
X else
X {
X
X/*
X Settings for File and Special menus are same for DA's and display
X windows
X*/
X fStr = (StringPtr) "\p10000010001";
X oStr = (StringPtr) "\p10001000101";
X
X if (theKind < 0) /* DA in front */
X eStr = (StringPtr) "\p1101111000000";
X else /* some display window in front */
X eStr = (StringPtr) "\p0";
X
X BlankCPCtrls ();
X }
X
X drawBar = SetMenuStatus (fileMenu, fStr);
X drawBar |= SetMenuStatus (editMenu, eStr);
X drawBar |= SetMenuStatus (specialMenu, oStr);
X
X if (drawBar)
X DrawMenuBar ();
X}
X
X
X/*
X Handle "About MakeWrite..." selection from Apple menu.
X*/
X
XDoAbout ()
X{
X (void) Alert (aboutAlrtNum, nil);
X}
X
X
X/*
X Process selection from File menu
X*/
X
XDoFileMenu (item)
XInteger item;
X{
XWindowPeek theWind;
XInteger theKind;
X
X switch (item)
X {
X
X case newMap:
X if (DiscardChanges ())
X {
X ClobberMap ();
X ClearMapName ();
X undoOp = noUndo;
X mapModified = false;
X }
X break;
X
X case openMap:
X if (DiscardChanges ())
X {
X if (OpenMap ())
X {
X undoOp = noUndo;
X mapModified = false;
X }
X }
X break;
X
X case appendMap:
X if (AddMap ())
X {
X undoOp = noUndo;
X mapModified = true;
X }
X break;
X
X case saveMap:
X if (SaveMap (false))
X mapModified = false;
X break;
X
X case saveMapAs:
X if (SaveMap (true))
X mapModified = false;
X break;
X
X case close:
X theWind = (WindowPeek) FrontWindow ();
X theKind = theWind->windowKind;
X if (theKind < 0) /* DA being closed */
X CloseDeskAcc (theKind);
X else /* Display window - just hide */
X HideWindow (theWind); /* it. Activation proc will */
X break; /* dispose of it */
X
X case makeWrite:
X TextToWrite ();
X break;
X
X case quit:
X if (DiscardChanges ())
X SkelWhoa ();
X break;
X }
X FixMenus ();
X}
X
X
XDoUndo ()
X{
XMapSpec tempSpec;
XStringHandle hStr;
XStr255 tempStr;
XInteger selStart, selEnd;
XBoolean tmpCPMarker;
X
X tmpCPMarker = cpMarker;
X cpMarker = undoCPMarker;
X undoCPMarker = tmpCPMarker;
X
X InitMSpec (&tempSpec);
X switch (undoOp)
X {
X
X case undoInsert:
X undoOp = undoDelete;
X CopyMSpec (&mapSpec[undoPos], &undoMSpec);
X DeleteMapping (undoPos);
X break;
X
X case undoDelete:
X undoOp = undoInsert;
X InsertMapping (&undoMSpec, undoPos);
X break;
X
X case undoPaste:
X CopyMSpec (&mapSpec[undoPos], &tempSpec);
X PasteMapping (&undoMSpec, undoPos);
X CopyMSpec (&tempSpec, &undoMSpec);
X break;
X
X case undoFieldChg:
X SetMapFieldValue (undoFieldType, undoVal);
X break;
X
X case undoTyping:
X case undoMarkerOp:
X undoOp = undoMarkerOp;
X CopyMSpec (&mapSpec[undoPos], &tempSpec);
X CopyMSpec (&undoMSpec, &mapSpec[undoPos]);
X CopyMSpec (&tempSpec, &undoMSpec);
X
X hStr = mapSpec[undoPos].mark;
X HLock (hStr);
X PasteField (mapList, undoPos, markField, *hStr);
X HUnlock (hStr);
X SetSelectors (undoPos);
X break;
X
X }
X TermMSpec (&tempSpec);
X}
X
X
X/*
X Process selection from Edit menu
X*/
X
XDoEditMenu (item)
XInteger item;
X{
Xregister Integer curLine;
X
X if (SystemEdit (item - 1))
X return;
X
X if (EditMarker (item))
X return; /* it was a marker edit operation */
X
X curLine = mapList->curLine;
X switch (item)
X {
X
X case undo:
X DoUndo ();
X break;
X
X case cut:
X undoCPMarker = cpMarker;
X CopyMSpec (&mapSpec[curLine], &clipMSpec);
X CopyMSpec (&clipMSpec, &undoMSpec);
X undoOp = undoDelete;
X undoPos = curLine;
X havePasteMSpec = true;
X DeleteMapping (curLine);
X break;
X
X case copy:
X CopyMSpec (&mapSpec[curLine], &clipMSpec);
X havePasteMSpec = true;
X break;
X
X case paste:
X undoCPMarker = cpMarker;
X if (curLine != noLine)
X {
X CopyMSpec (&mapSpec[curLine], &undoMSpec);
X undoOp = undoPaste;
X undoPos = curLine;
X PasteMapping (&clipMSpec, curLine);
X }
X else /* no selection; */
X { /* add at end */
X undoOp = undoInsert;
X undoPos = mapList->nLines;
X if (InsertMapping (&clipMSpec, mapList->nLines) == false)
X undoOp = noUndo;
X }
X break;
X
X case clear:
X undoCPMarker = cpMarker;
X CopyMSpec (&mapSpec[curLine], &undoMSpec);
X undoOp = undoDelete;
X undoPos = curLine;
X DeleteMapping (curLine);
X break;
X
X case new:
X undoCPMarker = cpMarker;
X NewMapping ();
X /*SetCPMarker (true);*/
X undoOp = undoInsert;
X break;
X
X case duplicate:
X undoCPMarker = cpMarker;
X DupMapping (curLine); /* changes mapList->curLine */
X SetCPMarker (true);
X undoOp = undoInsert;
X undoPos = mapList->curLine;
X break;
X
X case sort:
X SortMap ();
X undoOp = noUndo; /* can't undo this */
X break;
X
X case squish:
X SquishMap ();
X undoOp = noUndo; /* can't undo this */
X break;
X
X }
X
X if (item != copy)
X mapModified = true;
X FixMenus ();
X}
X
X
XDoSpecialMenu (item)
XInteger item;
X{
X switch (item)
X {
X
X case stdFontList:
X StrFonts (true);
X SetSelectors (mapList->curLine);
X break;
X
X case systemFontList:
X ResourceFonts (true);
X SetSelectors (mapList->curLine);
X break;
X
X case pgraphStyle:
X DoParaDialog ();
X break;
X
X case conflicts:
X FindConflicts ();
X break;
X
X case getInfo:
X HelpWindow ();
X break;
X
X# ifdef debug
X case debugOption:
X debugOut = !debugOut;
X CheckItem (specialMenu, debugOption, debugOut);
X break;
X# endif
X
X }
X FixMenus ();
X}
X
X
X/*
X Menu initialization.
X*/
X
XSetupMenus ()
X{
X SkelApple ("\pAbout MakeWrite...", DoAbout);
X
X fileMenu = GetMenu (fileMenuNum);
X SkelMenu (fileMenu, DoFileMenu, nil);
X
X editMenu = GetMenu (editMenuNum);
X SkelMenu (editMenu, DoEditMenu, nil);
X
X specialMenu = GetMenu (specialMenuNum);
X# ifdef debug
X AppendMenu (specialMenu, "\p(-;Debug Output");
X# endif
X SkelMenu (specialMenu, DoSpecialMenu, nil);
X
X InitMSpec (&undoMSpec);
X InitMSpec (&clipMSpec);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWMisc.c
X# include "MakeWrite.h"
X# include <EventMgr.h>
X
X
X/* ---------------------------------------------------------------- */
X/* String Operations */
X/* ---------------------------------------------------------------- */
X
X/*
X Copy src to dst
X*/
X
XCopyString (src, dst)
XStringPtr src, dst;
X{
X BlockMove (src, dst, (Longint) (src[0] + 1));
X}
X
X
X/*
X Append src to dst
X*/
X
XAppendString (src, dst)
XStringPtr src, dst;
X{
X BlockMove (&src[1], dst + dst[0] + 1, (Longint) src[0]);
X dst[0] += src[0];
X}
X
X
X/*
X Compare two strings.
X Return:
X 0 s1 = s2
X < 0 s1 < s2
X > 0 s1 > s2
X*/
X
XCompareString (s1, s2)
Xregister StringPtr s1, s2;
X{
Xregister Integer i, len, diff;
X
X len = s1[0];
X if (len > s2[0])
X len = s2[0];
X for (i = 1; i <= len; ++i)
X {
X if ((diff = s1[i] - s2[i]) != 0)
X return (diff);
X }
X return (s1[0] - s2[0]);
X}
X
X
XBoolean InString (s, c)
XStringPtr s;
Xchar c;
X{
Xregister Integer i, len;
X
X for (len = s[0], i = 1; i <= len; ++i)
X {
X if (s[i] == c)
X return (true);
X }
X return (false);
X}
X
X/* ---------------------------------------------------------------- */
X/* Event Operations */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Return true if there's a mouse-down event pending (also flush the
X event so that it's not used in some way other than as a signal.
X*/
X
XBoolean MouseClick ()
X{
XEventRecord theEvent;
X
X if (EventAvail (mDownMask, &theEvent))
X {
X FlushEvents (mDownMask, 0);
X return (true);
X }
X return (false);
X}
X
X
Xstatic Integer eventTypes;
X
X
X/*
X Make sure any events of proper type are processed before
X proceeding.
X*/
X
XCheckEvents ()
X{
XEventRecord event;
X
X if (!EventAvail (eventTypes, &event))
X SkelWhoa ();
X}
X
X
XDoEvents (doTypes) /* can be called recursively */
XInteger doTypes;
X{
XInteger types;
XInteger mask;
XProcPtr bkGnd;
X
X SkelGetBackground (&bkGnd); /* get current background proc */
X SkelGetEventMask (&mask); /* and event mask */
X types = eventTypes; /* and processing types */
X
X SkelBackground (CheckEvents); /* install new background & mask */
X SkelEventMask (doTypes);
X eventTypes = doTypes;
X
X SkelMain (); /* handle updates only */
X
X SkelBackground (bkGnd); /* restore old background & mask */
X SkelEventMask (mask);
X eventTypes = types;
X}
X
X
XDoUpdates ()
X{
X DoEvents (updateMask);
X}
X
X
X/*
X Make a window the front window and update it before proceeding.
X*/
X
XMakeFrontWind (w)
XWindowPtr w;
X{
X HiliteMenu (0);
X SelectWindow (w);
X ShowWindow (w);
X DoEvents (updateMask + activMask);
X SetPort (w);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Memory Operations */
X/* ---------------------------------------------------------------- */
X
X
XBoolean ExpandHandle (h, delta)
XHandle h;
XSize delta;
X{
XSize newSize;
X
X newSize = GetHandleSize (h) + delta;
X SetHandleSize (h, newSize);
X return (GetHandleSize (h) == newSize);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Miscellaneous */
X/* ---------------------------------------------------------------- */
X
X
XBoolean DiscardChanges ()
X{
XBoolean result;
X
X if (!mapModified)
X return (true);
X ParamText ("\pDiscard changes to current map?", "\p", "\p", "\p");
X result = (Alert (questAlrtNum, nil) == 2); /* 2 is "OK" */
X DoUpdates ();
X return (result);
X}
X
X
X
XBoolean DestroyWarn ()
X{
XBoolean result;
X
X if (mapList->nLines == 0) /* if nothing there, don't bother, */
X { /* unless map has changed, then ask */
X if (mapModified) /* different question */
X return (DiscardChanges ());
X return (true);
X }
X ParamText ("\pThis operation destroys the current map.",
X "\p Do you wish to proceed?", "\p", "\p");
X result = (Alert (questAlrtNum, nil) == 2); /* 2 is "OK" */
X DoUpdates ();
X return (result);
X}
X
X
X/*
X Display a message in a generic alert.
X*/
X
XMessage (s1, s2, s3, s4)
XStringPtr s1, s2, s3, s4;
X{
X ParamText (s1, s2, s3, s4);
X (void) Alert (msgeAlrtNum, nil);
X DoUpdates ();
X}
X
X
XMessage1 (s1)
XStringPtr s1;
X{
X Message (s1, "\p", "\p", "\p");
X}
X
X
XMessage2 (s1, s2)
XStringPtr s1, s2;
X{
X Message (s1, s2, "\p", "\p");
X}
X
X
XMessage3 (s1, s2, s3)
XStringPtr s1, s2, s3;
X{
X Message (s1, s2, s3, "\p");
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWParaDlog.c
X/*
X Paragraph style dialog
X*/
X
X
X# include <DialogMgr.h>
X# include <EventMgr.h>
X# include <ToolboxUtil.h>
X# include "MakeWrite.h"
X
X
Xtypedef enum /* paragraph style dialog item numbers */
X{
X paraOK = 1,
X paraCancel,
X paraEach,
X paraBlank,
X paraSmart,
X paraMText,
X paraPText,
X paraQText,
X paraLine1,
X paraLine2
X};
X
X
X/*
X Initialize paragraph style to default: blank lines and lines
X beginning with whitespace initiate paragraphs, line joining
X is smart, there's no explicit paragraph or page break marker.
X*/
X
X
Xstatic ParaStyle defStyle = { false, true, true };
Xstatic Str255 defPeriodStr = "\p.!?";
Xstatic Str255 defQuoteStr = { 5, '"', '\'', 0xd3, 0xd5, ')' };
X
X
X/*
X Set the contents of a string using the contents of the 'STR '
X resource whose id is passed as strResId.
X*/
X
Xstatic ResSetString (strResId, str)
XInteger strResId;
XStringPtr str;
X{
XStringHandle hStr;
X
X hStr = GetString (strResId);
X HLock (hStr);
X if ((*hStr)[0] > maxMarkLen)
X (*hStr)[0] = maxMarkLen;
X CopyString (*hStr, str);
X HUnlock (hStr);
X ReleaseResource (hStr);
X}
X
X
XInitParaStyle ()
X{
X paraStyle = defStyle;
X paraMark[0] = 0;
X pageMark[0] = 0;
X ResSetString (periodStrNum, periodStr);
X ResSetString (quoteStrNum, quoteStr);
X}
X
X
Xstatic pascal void DoLine (dlog, item)
XDialogPtr dlog;
XInteger item;
X{
XHandle itemHandle;
XInteger itemType;
XRect itemRect;
X
X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X FrameRect (&itemRect);
X}
X
X
Xstatic Boolean GetDCtl (dlog, item)
XDialogPtr dlog;
XInteger item;
X{
XHandle itemHandle;
XInteger itemType;
XRect itemRect;
X
X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X return (GetCtlValue (itemHandle));
X}
X
X
Xstatic SetDCtl (dlog, item, value)
XDialogPtr dlog;
XInteger item;
XBoolean value;
X{
XHandle itemHandle;
XInteger itemType;
XRect itemRect;
X
X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X SetCtlValue (itemHandle, (Integer) value);
X}
X
X
Xstatic GetDText (dlog, item, str)
XDialogPtr dlog;
XInteger item;
XStringPtr str;
X{
XHandle itemHandle;
XInteger itemType;
XRect itemRect;
XStr255 s;
X
X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X GetIText (itemHandle, s);
X if (s[0] > maxMarkLen)
X s[0] = maxMarkLen;
X CopyString (s, str);
X}
X
X
Xstatic SetDText (dlog, item, str)
XDialogPtr dlog;
XInteger item;
XStr255 str;
X{
XHandle itemHandle;
XInteger itemType;
XRect itemRect;
X
X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X SetIText (itemHandle, str);
X SelIText (dlog, item, 0, 32767);
X}
X
X
X/*
X Get the text of an item, and return true if it's different than
X the current value
X*/
X
Xstatic Boolean CheckDText (dlog, item, str)
XDialogPtr dlog;
XInteger item;
XStr255 str;
X{
XStr255 tmpStr;
XBoolean changed;
X
X GetDText (dlog, item, tmpStr);
X changed = (CompareString (str, tmpStr) != 0);
X CopyString (tmpStr, str);
X return (changed);
X}
X
X
Xstatic SetDProc (dlog, item, p)
XDialogPtr dlog;
XInteger item;
XProcPtr p;
X{
XHandle itemHandle;
XInteger itemType;
XRect itemRect;
X
X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
X SetDItem (dlog, item, itemType, p, &itemRect);
X}
X
X
Xstatic SetParaCheck (theDialog, each, blank, smart)
XDialogPtr theDialog;
XBoolean each, blank, smart;
X{
X SetDCtl (theDialog, paraEach, each);
X SetDCtl (theDialog, paraBlank, blank);
X SetDCtl (theDialog, paraSmart, smart);
X}
X
X
X
XDoParaDialog ()
X{
Xregister DialogPtr theDialog;
XInteger itemHit = 0;
XBoolean loop = true;
Xregister Boolean curEach, curBlank, curSmart;
XBoolean changed;
XStr255 s;
X
X theDialog = GetNewDialog (paraDlogNum, nil, -1L);
X SetParaCheck (theDialog, curEach = paraStyle.pEachLine,
X curBlank = paraStyle.pBlankLine,
X curSmart = paraStyle.pSmartJoin);
X SetDText (theDialog, paraPText, periodStr);
X SetDText (theDialog, paraQText, quoteStr);
X SetDText (theDialog, paraMText, paraMark);
X SetDProc (theDialog, paraLine1, DoLine);
X SetDProc (theDialog, paraLine2, DoLine);
X ShowWindow (theDialog);
X
X while (loop)
X {
X ModalDialog (nil, &itemHit);
X switch (itemHit)
X {
X
X/*
X If smart join is selected but there aren't any sentence terminators,
X put up an alert and don't quit.
X*/
X case paraOK:
X GetDText (theDialog, paraPText, s);
X if (curSmart && s[0] == 0)
X {
X (void) Alert (noPeriodAlrtNum, nil);
X continue;
X }
X
X changed = (paraStyle.pEachLine != curEach);
X paraStyle.pEachLine = curEach;
X
X changed |= (paraStyle.pBlankLine != curBlank);
X paraStyle.pBlankLine = curBlank;
X
X changed |= (paraStyle.pSmartJoin != curSmart);
X paraStyle.pSmartJoin = curSmart;
X
X changed |= CheckDText (theDialog, paraMText, paraMark);
X changed |= CheckDText (theDialog, paraPText, periodStr);
X changed |= CheckDText (theDialog, paraQText, quoteStr);
X
X if (changed)
X mapModified = true;
X loop = false;
X break;
X
X case paraCancel:
X loop = false;
X break;
X
X case paraEach:
X curEach = !curEach;
X if (curEach)
X curBlank = false;
X break;
X
X case paraBlank:
X curBlank = !curBlank;
X if (curBlank)
X curEach = false;
X break;
X
X case paraSmart:
X curSmart = !curSmart;
X break;
X
X }
X SetParaCheck (theDialog, curEach, curBlank, curSmart);
X }
X DisposDialog (theDialog);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWTextToWrite.c
X/*
X Convert text file to MacWrite document, using formatting
X specifications contained in current map.
X
X Possibly add:
X Text compression
X*/
X
X
X# include "MakeWrite.h"
X# include "MWMaca.h"
X# include "MWFileStuff.h"
X# include <StdFilePkg.h>
X
X
X# define applFont 1
X
X# define maxTBufSize 1024 /* text file input buffer size */
X# define maxCBufSize 4000 /* MacWrite limit on chars in paragraph */
X
X/*
X MacWrite's maximum main doc text para count is something over
X 2000. I choose 2000 as a reasonable limit.
X*/
X
X# define maxMWParas 2000
X
X
X/*
X Vars for text file streaming
X*/
X
Xstatic Integer fText; /* input text file reference number */
Xstatic char tFileBuf[maxTBufSize]; /* file buffer */
Xstatic Longint tFileSize; /* file size */
Xstatic Longint tFileRead; /* # chars read */
Xstatic Longint tFileLeft; /* # chars still to read */
Xstatic Longint tBufSize; /* number of chars currently in buffer */
Xstatic Integer tBufPos; /* current text buffer position */
Xstatic Integer percent; /* percent of input read so far */
X
X
X/*
X fWord - output MacWrite file reference number
X pushBack - text file input pushback queue
X outBuf - output paragraph buffer
X outChars - number of chars into current output paragraph so far
X blankCount - number of blanks to put out for line joining
X fmtCount - number of formats in the current paragraph so far
X fmtBuf - format information storage array
X maxFormats - number of formats the format array handle can hold
X before needing expansion
X needFormat - true if need to generate a format when the next output
X char is added to current paragraph
X paraInfo - paragraph information storage array
X maxParas - number of elements paraInfo can hold before needing expansion
X paraCount - current number of paragraphs (doesn't count initial ruler)
X
X font, size, style - current format
X*/
X
Xstatic Integer fWord;
Xstatic Str255 pushBack;
Xstatic char outBuf[maxCBufSize];
Xstatic Integer outChars;
Xstatic Integer blankCount;
X
Xstatic FAHandle fmtBuf;
Xstatic Integer fmtCount;
Xstatic Integer maxFormats;
Xstatic Boolean needFormat;
X
Xstatic PIAHandle paraInfo;
Xstatic Integer maxParas;
Xstatic Integer paraCount;
X
Xstatic Integer font;
Xstatic Integer size;
Xstatic Integer style;
X
X
X/*
X Initialize text streaming variables
X*/
X
Xstatic InitTextStream (f)
XInteger f;
X{
X (void) GetEOF (f, &tFileSize); /* set up streaming variables */
X tFileLeft = tFileSize;
X tFileRead = 0;
X tBufSize = 0;
X tBufPos = 0;
X percent = -1;
X}
X
X
X/*
X Get next char from text file. This has to take account of the
X state of the pushback stack. File is read from disk a block
X at a time and dribbled out to avoid making a file system call
X for every character.
X
X Return false on end of file or file read error.
X*/
X
Xstatic Boolean ReadTextChar (c)
Xregister char *c;
X{
XInteger newPercent;
X
X if (pushBack[0] > 0) /* pushback stack not empty */
X {
X *c = pushBack[pushBack[0]--]; /* return top char */
X return (true);
X }
X
X if (tBufPos >= tBufSize) /* need to read in a new block */
X {
X tBufSize = tFileLeft;
X if (tBufSize == 0) /* end of file */
X return (false);
X if (tBufSize > maxTBufSize) /* don't read more than a block */
X tBufSize = maxTBufSize;
X tFileLeft -= maxTBufSize;
X if (tFileLeft < 0)
X tFileLeft = 0;
X
X if (!FileRead (fText, tFileBuf, (Longint) tBufSize))
X return (false); /* read error */
X tBufPos = 0;
X }
X *c = tFileBuf[tBufPos++];
X
X# ifdef debug
X DisplayChar (*c);
X# endif
X
X newPercent = (++tFileRead * 100) / tFileSize;
X if (newPercent != percent)
X {
X percent = newPercent;
X SetMeterPercent (percent);
X }
X return (true);
X}
X
X
X/*
X FIgure out how many blanks need to be added to the output buffer
X if another line is joined on. Default is one. If smart join is
X on, then two spaces if something like a period is at the end now.
X Remember to account for spaces that may already be on the end. If
X a tab is found at the end, then throw hands up in disgust, because
X who knows how wide it is?
X*/
X
Xstatic SetBlankCount ()
X{
Xregister Integer i, endBlanks, needBlanks = 1;
Xregister char c;
X
X i = outChars;
X while (i > 0) /* count up spaces on end currently */
X {
X if ((c = outBuf[i-1]) == '\t')
X {
X blankCount = 0;
X return; /* tab found - give up */
X }
X if (c != ' ')
X break;
X --i;
X }
X endBlanks = outChars - i;
X
X if (paraStyle.pSmartJoin) /* smart join - try to be intelligent */
X {
X while (i > 0)
X {
X c = outBuf[i-1];
X if (InString (quoteStr, c)) /* quote char - ignore */
X --i;
X else /* not quote char - is it period char? */
X {
X if (InString (periodStr, c))
X needBlanks = 2; /* yes - need two chars */
X break;
X }
X }
X }
X
X if (i == 0) /* empty buffer - nothing needed */
X needBlanks = 0;
X
X needBlanks -= endBlanks; /* account for those already there */
X if (needBlanks < 0)
X needBlanks = 0;
X blankCount = needBlanks;
X}
X
X
X/*
X Push saved text back onto the pushback stack
X*/
X
Xstatic PushSavedText (s)
XStringPtr s;
X{
X while (s[0] > 0)
X {
X pushBack[++pushBack[0]] = s[s[0]--];
X }
X}
X
X
Xstatic Boolean NewFormat ()
X{
Xregister Format *f;
X
X# ifdef debug
X DisplayString ("\p {NewFormat}");
X# endif
X
X if (fmtCount >= maxFormats) /* need to make format array bigger */
X {
X if (!ExpandHandle (fmtBuf, 1024L))
X {
X Message1 ("\pOut of memory, can't continue (NewFormat)");
X return (false);
X }
X maxFormats = GetHandleSize (fmtBuf) / sizeof (Format);
X }
X
X f = &((**fmtBuf)[fmtCount++]);
X f->fmtPos = outChars; /* starting pos of format */
X f->fmtFont = font; /* current font */
X f->fmtSize = size; /* current size */
X f->fmtStyle = style; /* current style */
X return (true);
X}
X
X
Xstatic Boolean AddChar (c)
Xchar c;
X{
XStr255 s;
X
X if (needFormat)
X {
X needFormat = false;
X if (!NewFormat ())
X return (false); /* couldn't get memory for format */
X }
X if (outChars >= maxCBufSize)
X {
X NumToString ((Longint) maxCBufSize, s);
X Message ("\pParagraph contains more than ", s,
X "\p chars (MacWrite limit exceeded).",
X "\p Check your Paragraph Style settings.");
X return (false);
X }
X outBuf[outChars++] = c;
X return (true);
X}
X
X
Xstatic ChangeCurFormat (m)
Xregister MapSpec *m;
X{
XStr255 infoStr;
X
X if (m->font != sameFont && m->font != font)
X {
X font = m->font;
X needFormat = true;
X }
X if (m->size != sameSize && m->size != size)
X {
X size = m->size;
X needFormat = true;
X }
X if (m->style != sameStyle && m->style != style)
X {
X style = m->style;
X needFormat = true;
X }
X
X# ifdef debug
X if (needFormat)
X {
X DisplayChar ('{');
X FontToStr (font, infoStr);
X DisplayString (infoStr);
X DisplayChar ('/');
X DisplayInt (size);
X DisplayChar ('/');
X StyleToStr (style, infoStr);
X DisplayString (infoStr);
X DisplayString ("\p} ");
X }
X# endif
X}
X
X
X/*
X Write stored paragraph contents to disk:
X number bytes of text (word)
X the text
X zero pad if necessary to align to word boundary
X number bytes of format information
X the format information
X
X Construct a new element in the paragraph information array
X as well, and reset the paragraph state vars.
X
X The data position pointer in the para info element is set
X to the current file position, since that's where the data
X will be written.
X*/
X
Xstatic Boolean FlushPara ()
X{
XInteger fmtLen, dataLen;
XBoolean result;
XStr255 s;
X
X# ifdef debug
X DisplayString ("\p{FlushPara}");
X# endif
X
X if (paraCount >= maxMWParas)
X {
X NumToString ((Longint) maxMWParas, s);
X Message3 ("\pYour document contains more than ",
X s, "\p paragraphs. Split the input file and try again.");
X return (false);
X }
X
X if (paraCount >= maxParas) /* need to make para info array bigger */
X {
X if (!ExpandHandle (paraInfo, 1024L))
X {
X Message1 ("\pOut of memory, can't continue (FlushPara)");
X return (false);
X }
X maxParas = GetHandleSize (paraInfo) / sizeof (ParaInfo6);
X }
X
X fmtLen = fmtCount * sizeof (Format);
X dataLen = sizeof (Integer) /* word for length of text */
X + ((outChars + 1) & ~1) /* text ( + pad if necessary) */
X + sizeof (Integer) /* word for length of formats */
X + fmtLen; /* formats */
X HLock (paraInfo);
X SetParaInfo (&((**paraInfo)[paraCount++]),
X 16, 0, FilePos (fWord), dataLen, 0);
X HUnlock (paraInfo);
X HLock (fmtBuf);
X result =
X WriteInteger (fWord, outChars)
X && FileWrite (fWord, outBuf, (Longint) outChars)
X && ZeroPad (fWord, 0)
X && WriteInteger (fWord, fmtLen)
X && FileWrite (fWord, *fmtBuf, (Longint) fmtLen);
X HUnlock (fmtBuf);
X outChars = 0; /* reset para state vars */
X fmtCount = 0;
X needFormat = true;
X blankCount = 0; /* don't need blanks for line joining now */
X return (result);
X}
X
X
X/*
X Flush current paragraph, if there's any text in it
X*/
X
Xstatic Boolean DoBreak ()
X{
X return (outChars == 0 || (AddChar (cr) && FlushPara ()));
X}
X
X
X/*
X Flush current paragraph, regardless of whether there's anything
X in it or not.
X*/
X
Xstatic Boolean DoSpace ()
X{
X return (AddChar (cr) && FlushPara ());
X}
X
X
X/*
X FormatText - convert text file to MacWrite file
X
X Winner of 1987 "Ugliest Function" award. That goes for the
X comments, too. They've been revised so often, even I barely
X understand them, so good luck.
X
X saveQueue is the text that's been matched partially. It's saved
X for writing to output in case no match is found: the text is
X put back on the pushback stack, the first char is written out
X and a match is sought starting with the next char.
X
X The biggest headache about this thing is getting it to work properly
X with all legal combinations of paragraph style settings.
X
X "Each line a paragraph" is never on if blank line paragraphing is
X on, and vice-versa. Use of a paragraph marker is compatible with
X all options.
X
X Input lines containing only imbedded commands are always ignored
X for paragraphing purposes - that is, they're not treated as blank
X lines.
X*/
X
Xstatic Boolean FormatText ()
X{
Xchar c; /* input char */
XStr255 saveQueue; /* input save queue */
XInteger index; /* command index */
Xregister Integer inLineChars; /* # chars from current line added to */
X /* output (for blank line and beginning */
X /* of line detection) */
XBoolean cmdsInLine; /* whether commands were found in line */
XBoolean xNeedFormat;
X
X if (!WritePrelude (fWord))
X return (false);
X
X font = applFont;
X size = 12;
X style = 0; /* plain */
X
X InitMarkStates (); /* clear match info */
X pushBack[0] = 0; /* and file queues */
X saveQueue[0] = 0;
X inLineChars = 0; /* no chars added from current line */
X blankCount = 0; /* no blanks needed for line joining yet */
X cmdsInLine = false; /* no commands in line yet */
X paraCount = 0; /* no paragraphs yet */
X outChars = 0; /* no chars in current paragraph */
X fmtCount = 0; /* no formats yet, either */
X needFormat = true; /* generate format on next char written */
X
X while (ReadTextChar (&c)) /* while not eof on text file */
X {
X saveQueue[++saveQueue[0]] = c;
X switch (index = CheckMarkers (c))
X {
X
X case -2: /* no match */
X/*
X Push back saved text, read first char and add to current
X paragraph. If the paragraph is done, flush it to disk, and
X start looking for a new marker.
X
X Note what happens on cr. It is read, saved, fails to match, and
X is pushed back. If there are other chars before it in pushback,
X they'll be reprocessed (except first of them, which is added to
X para). Eventually, the cr becomes first thing in pushback. It is
X read, saved, fails to match, and is pushed back, Then it's read
X again, and causes para flushing according to para style rules.
X
X Carriage return check is here only. Cr never matches any marker
X char, since it can't be typed into one. Therefore it's not possible
X to get any other return value from CheckMarkers when c == cr.
X*/
X
X PushSavedText (saveQueue);
X InitMarkStates ();
X (void) ReadTextChar (&c);
X
X/*
X If the character is not a carriage return, then it is simply
X added to the current paragraph. The exception occur if this is
X the first char of the line:
X
X (i) If the character is whitespace at the beginning of the line,
X then the line begins a new paragraph, so flush the previous
X paragraph, if there's anything there.
X
X (ii) Dribble out any blanks needed to take care of any line
X joining that might be going on. Delay putting out any format
X change that might be pending until right before the char following
X the blanks - it's safe to do this because a format must have
X already been written for there to be any need to join with spaces.
X*/
X
X if (c != cr)
X {
X if (inLineChars == 0) /* if start of line... */
X {
X if (c == ' ' || c == '\t')
X {
X if (!DoBreak ())
X return (false);
X }
X else
X {
X xNeedFormat = needFormat;
X needFormat = false;
X while (blankCount > 0)
X {
X if (!AddChar (' '))
X return (false);
X --blankCount;
X }
X needFormat = xNeedFormat;
X }
X }
X if (!AddChar (c))
X return (false);
X ++inLineChars;
X }
X
X/*
X Char is cr. If line only contained commands, ignore it.
X Else if every line begins a paragraph, flush it. Else if
X line is blank and blank lines begin paragraphs. Else it's just
X the end of the current line and it will be joined to the text of
X the next line unless the paragraph gets flushed first - so figure
X out how many spaces to put out before the next line is written.
X The writing happens when we actually get a line to be joined, not
X here, so that spaces don't get tacked onto lines that may not need
X them.
X*/
X
X else
X {
X if (!(cmdsInLine && inLineChars == 0))
X {
X if (paraStyle.pEachLine) /* always force line */
X {
X if (!DoSpace ())
X return (false);
X }
X else if (inLineChars == 0) /* if blank line */
X {
X if (paraStyle.pBlankLine) /* and they are paras */
X {
X if (!DoBreak () || !DoSpace ())
X return (false);
X }
X else /* ignore the line, but set blank count */
X {
X SetBlankCount ();
X }
X }
X else
X {
X SetBlankCount ();
X }
X }
X inLineChars = 0;
X cmdsInLine = false;
X }
X break;
X
X case -1: /* match, but not entirely yet */
X break; /* just keep looking */
X
X default: /* found complete match */
X/*
X Since the text matched a marker, it either appears in the
X output as a format change or signals the beginning of a
X paragraph. In either case, it doesn't appear in the output
X as literal text, so can toss the save queue.
X
X If it's a format, process the format spec, setting the flag
X indicating that a new format will be needed on the next char
X written out (but only if the format actually *changes*).
X
X If it's a para marker, flush the current paragraph.
X*/
X cmdsInLine = true;
X
X if (index == paraMarkIdx)
X {
X if (!DoSpace ())
X return (false);
X }
X else if (index == pageMarkIdx)
X {
X /* not implemented */
X# ifdef debug
X DisplayString ("\p{Page break not implemented}");
X# endif
X }
X else
X ChangeCurFormat (&mapSpec[index]);
X
X saveQueue[0] = 0; /* toss pushback */
X InitMarkStates (); /* start looking for new marker */
X break;
X
X }
X }
X
X/*
X It's the end of the file, but we might have been left in the middle
X of matching a mark, so return saved text to the pushback queue and
X write it out. Note that if we *were* in the middle of mark testing,
X then this is not the beginning of a line and no spaces need to be
X dribbled.
X*/
X
X PushSavedText (saveQueue);
X while (ReadTextChar (&c))
X {
X if (!AddChar (c))
X return (false);
X }
X
X/*
X There must be at least one text paragraph. If there aren't any
X make sure one is generated. If nothing at all has been formatted,
X there won't even be any formats generated, so force one. Then
X flush the paragraph.
X
X If there already were paragraphs, then see whether unflushed
X characters are being held and flush if so.
X*/
X
X if (paraCount == 0)
X {
X if (fmtCount == 0)
X {
X if (!NewFormat ())
X return (false);
X }
X if (!FlushPara ())
X return (false);
X }
X else if (outChars != 0)
X {
X if (!FlushPara ())
X return (false);
X }
X
X if (!WritePostlude (fWord, paraCount, paraInfo))
X return (false);
X
X return (true);
X}
X
X
XTextToWrite ()
X{
XSFReply inFile;
XSFReply outFile;
XBoolean result;
X
X if (FindEmptyMark ())
X return;
X
X if (!GetInputFile ("\pOpen", 'TEXT', &inFile))
X return;
X CopyString (inFile.fName, outFile.fName); /* make default output name */
X AppendString ("\p.mw", outFile.fName);
X if (!GetOutputFile (true, outFile.fName, 0, &outFile))
X return;
X
X if (!OpenInputFile (&inFile, &fText))
X return;
X
X InitTextStream (fText);
X
X if (!OpenOutputFile (&outFile, 'MACA', 'WORD', &fWord))
X {
X (void) FSClose (fText);
X return;
X }
X
X MeterBegin ();
X MeterPos (5, 0);
X MeterString ("\pFormatting: ");
X MeterString (inFile.fName);
X MeterPos (64, 1);
X MeterString ("\pTo: ");
X MeterString (outFile.fName);
X StartMeterPercentInfo ();
X
X/*
X Fire up a debug output window if that option is true. If it's
X false, then not executing DisplayWindow results in all output calls
X being ignored. Not as quick as testing them all, but easier.
X (None of it will be true if compilation has all this stuff turned
X off, anyway.)
X*/
X
X# ifdef debug
X if (debugOut)
X DisplayWindow (outFile.fName, true);
X DisplayString ("\pInput file size ");
X DisplayLong (tFileSize);
X DisplayLn ();
X# endif
X
X fmtBuf = (FAHandle) NewHandle (0L); /* get format array buffer */
X maxFormats = 0;
X paraInfo = (PIAHandle) NewHandle (0L); /* get para info array buffer */
X maxParas = 0;
X
X result = FormatText ();
X (void) FSClose (fText);
X (void) FSClose (fWord);
X (void) FlushVol (fWord, outFile.vRefNum);
X if (result == false)
X FSDelete (outFile.fName, outFile.vRefNum);
X
X DisposHandle (fmtBuf);
X DisposHandle (paraInfo);
X MeterEnd ();
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > MW/MWWindMisc.c
X# include "MakeWrite.h"
X
X
XWindowPtr NewDWindow ();
X
Xstatic WindowPtr meterWind = nil;
Xstatic WindowPtr helpWind = nil;
Xstatic Integer errCount;
Xstatic Str255 errWindName;
Xstatic Integer hPercent;
X
X/* ---------------------------------------------------------------- */
X/* General Display Window Routines */
X/* ---------------------------------------------------------------- */
X
X
Xstatic DWindActivate (active)
XBoolean active;
X{
XWindowPeek w;
X
X if (!active) /* deactivated - was it closed? */
X {
X GetPort (&w);
X if (w->visible == 0)
X {
X SkelRmveWind (w); /* yes - remove it */
X if ((WindowPtr) w == helpWind)
X helpWind = nil;
X }
X }
X FixMenus ();
X}
X
X
X/*
X Build a display window. NewDWindow makes it the current output
X window for display output. The window comes up in front unless
X the meter is present, in which case it comes up under the meter.
X*/
X
XDisplayWindow (title, visible)
XStringPtr title;
XBoolean visible;
X{
Xregister WindowPtr w;
XRect r;
Xstatic Integer i = 0;
Xregister Integer h, v;
X
X if (meterWind != nil && i < 1)
X i = 1;
X h = i * 23 + 5;
X v = h + 65;
X SetRect (&r, h, v, h + 350, v + 200);
X SetDWindowNotify (nil, DWindActivate);
X w = NewDWindow (&r, title, visible, -1L, true, 0L);
X if (visible)
X MakeFrontWind (w);
X if (++i == 4)
X i = 0;
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Meter Window Routines */
X/* ---------------------------------------------------------------- */
X
X
XMeterPos (h, lineNo)
XInteger h, lineNo;
X{
X SetPort (meterWind);
X MoveTo (h, (Integer) (lineNo * 16 + 14));
X}
X
X
XMeterString (s)
XStringPtr s;
X{
X SetPort (meterWind);
X DrawString (s);
X}
X
X
XMeterInt (i)
XInteger i;
X{
XStr255 s;
X
X NumToString ((Integer) i, s);
X MeterString (s);
X}
X
X
XStartMeterPercentInfo ()
X{
XPenState p;
X
X MeterString ("\p ");
X GetPenState (&p);
X hPercent = p.pnLoc.h;
X}
X
X
XSetMeterPercent (i)
XInteger i;
X{
X MeterPos (hPercent, 1);
X MeterInt (i);
X MeterString ("\p%");
X}
X
X
Xstatic MeterClobber ()
X{
X DisposeWindow (meterWind);
X meterWind = nil;
X}
X
X
XMeterBegin ()
X{
XRect r;
X
X SetRect (&r, 80, 29, 420, 65);
X meterWind = NewWindow (nil, &r, "\p", true, dBoxProc, -1L, false, 0L);
X SkelWindow (meterWind, nil, nil, nil, nil, nil, MeterClobber, nil, false);
X TextFont (0);
X TextSize (0);
X TextMode (srcCopy);
X MakeFrontWind (meterWind);
X}
X
X
XMeterEnd ()
X{
X SkelRmveWind (meterWind);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Error Window Routines */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Initialize an error window. This just clears the error count
X and sets the name that will be given the window if an error
X occurs. The window doesn't actually appear unless the error
X message routine is called.
X*/
X
XErrWindInit (fName)
XStringPtr fName;
X{
X errCount = 0;
X CopyString (fName, errWindName);
X}
X
X
XErrWindMsge (thing, value)
XStringPtr thing;
XInteger value;
X{
X if (errCount++ == 0) /* first error */
X {
X DisplayWindow (errWindName, true);
X }
X DisplayString (thing);
X DisplayInt (value);
X DisplayLn ();
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Help Window Routine */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Create help window, unless it already exists - in which case
X simply pull it to the front.
X*/
X
X
XHelpWindow ()
X{
XRect r;
Xregister Handle h;
X
X if (helpWind == nil)
X {
X SetRect (&r, 40, 50, 450, 280);
X SetDWindowNotify (nil, DWindActivate);
X helpWind = NewDWindow (&r, "\pInformation Window", false, -1L, true, 0L);
X
X h = GetResource ('TEXT', helpTextNum); /* read help text */
X HLock (h); /* lock it and write to window */
X DisplayText (*h, GetHandleSize (h));
X HUnlock (h);
X ReleaseResource (h); /* done with it, so goodbye */
X SetDWindowPos (helpWind, 0); /* scroll back to top */
X SetDWindow (nil); /* no more output to this window */
X }
X MakeFrontWind (helpWind);
X}
SHAR_EOF
exit
--- end of part 3 ---
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads