Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: 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) [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 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 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 ---