Article View: mod.mac.sources
Article #50MakeWrite Source (part 2 of 3)
From: 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 ---
Technical Details
Message-ID:
<2457@felix.UUCP>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!water!watnot!watmath!clyde!rutgers!ames!ucbcad!ucbvax!decvax!decwrl!pyramid!oliveb!felix!macintoshReferences:
<2455@felix.UUCP>Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: arc1-ca.pugleaf.net!utzoo!utgpu!water!watnot!watmath!clyde!rutgers!ames!ucbcad!ucbvax!decvax!decwrl!pyramid!oliveb!felix!macintosh From: macintosh@felix.UUCP Newsgroups: mod.mac.sources Subject: MakeWrite Source (part 2 of 3) Message-ID: <2457@felix.UUCP> Date: Sat, 21-Mar-87 14:00:06 EST Article-I.D.: felix.2457 Posted: Sat Mar 21 14:00:06 1987 Date-Received: Mon, 23-Mar-87 00:30:57 EST References: <2455@felix.UUCP> Sender: root@felix.UUCP Reply-To: dubois@uwmacc.UUCP (Paul DuBois) Organization: UWisconsin-Madison Academic Comp Center Lines: 2483 Approved: bytebug@felix.UUCP (Roger L. Long)