TranslateCedarFilesImpl.mesa
Copyright Ó 1991, 1992 by Xerox Corporation. All rights reserved.
Willie-s, June 30, 1992 6:27 pm PDT
Michael Plass, March 9, 1992 4:23 pm PST
Doug Wyatt, June 29, 1992 12:08 pm PDT
DIRECTORY
Atom USING [GetPName],
BasicTime USING [Now, Unpack, Update],
Char,
Commander,
CommanderOps,
EditSpan,
IO,
NodeProps,
NodeStyleOps,
PFS,
PFSNames,
Rope,
TextEdit,
TextEditBogus,
TextNode,
TiogaIO USING [FromFile, ToStream],
UserProfile USING [Line];
TranslateCedarFilesImpl: CEDAR PROGRAM
IMPORTS Atom, BasicTime, Char, Commander, CommanderOps, EditSpan, IO, NodeProps, NodeStyleOps, PFS, PFSNames, Rope, TextEdit, TextEditBogus, TextNode, TiogaIO, UserProfile
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
Node: TYPE ~ TextNode.Ref;
CommentPrefix: PROC [rope: ROPE, start: INT] RETURNS [prefixLength: INT] ~ {
IF (rope.Run[start, "--"] = 2) OR (rope.Run[start, "//"] = 2) THEN
RETURN [2]
ELSE IF rope.Run[start, ";"] = 1 THEN
RETURN [rope.SkipOver[start, ";"] - start]
ELSE
RETURN [0];
};
SkipOverBackward: PROC [s: ROPE, pos: INT ¬ Rope.MaxLen, skip: ROPE] RETURNS [INT] ~ {
Like Rope.SkipOver, but backwards. Returns the highest position N in s such that s[N] is NOT in the skip string and N <= pos. If no such character occurs in s, then return -1.
skipText: Rope.Text = skip.Flatten[];
skiplen: NAT ~ skipText.Size[];
slen: INT ~ s.Size[];
start: INT ~ MIN[slen-1, pos];
IF start < 0 OR s.IsEmpty[] THEN RETURN [-1];
IF skiplen=0 THEN RETURN[start];
FOR n: INT ¬ start, n - 1 WHILE n>=0 DO
c: CHAR ~ s.Fetch[n];
FOR i: NAT IN [0..skiplen) DO
IF c = skipText[i] THEN EXIT;
REPEAT
FINISHED => RETURN [n];
ENDLOOP;
ENDLOOP;
RETURN [-1];
};
EnumerateInitialCommentLines: PROC [root: Node,
proc: PROC [text: ROPE, node: Node, start, length: INT] RETURNS [continue, redo: BOOL]]
RETURNS [finalNode: Node ¬ NIL, finalIndex: INT ¬ 0] ~ {
Calls proc on the text and location of each line of comments at the beginning of the given document until proc returns FALSE. Returns the location of the last comment line found. In all cases, the ``line'' is not considered to include any initial comment characters (e.g., "--" or ";"), leading or trailing whitespace, or the terminating newline character if any.
contents: ROPE;
index: INT ¬ 0;
node: Node ¬ TextNode.StepForward[root];
continue, redo: BOOL;
contents ¬ TextEditBogus.GetRope[node];
DO
GetTrimmedLine: PROC [begin: INT] RETURNS [start, length: INT] ~ {
end: INT;
index ¬ contents.SkipTo[begin, "\l\r"] + 1; -- set up for next line
start ¬ contents.SkipOver[begin, " \t"];
end ¬ SkipOverBackward[contents, index - 2, " \t"];
RETURN [start, MAX[0, end - start + 1]];
};
prefixLength, start, length: INT;
IF (prefixLength ¬ CommentPrefix[contents, index]) > 0 OR TextEdit.GetComment[node] THEN {
savedIndex: INT ~ index;
[start, length] ¬ GetTrimmedLine[index + prefixLength];
IF length > 0 OR prefixLength > 0 THEN { -- don't count truly empty comments
finalNode ¬ node; -- remember this one in case it's the last one
finalIndex ¬ savedIndex;
};
}
ELSE
EXIT;
[continue, redo] ¬ proc[contents.Substr[start, length], node, start, length];
IF NOT continue THEN EXIT;
IF redo THEN { -- node has been changed, start again
node ¬ TextNode.StepForward[root];
contents ¬ TextEditBogus.GetRope[node];
LOOP;
};
IF index >= contents.Length[] THEN { -- on to the next node
node ¬ TextNode.StepForward[node];
index ¬ 0;
IF node = NIL THEN EXIT;
contents ¬ TextEditBogus.GetRope[node];
};
ENDLOOP;
};
UpdateCopyrightNotice: PROC[root: Node, short, hasNodes, alreadyChanged: BOOL]
RETURNS[changed: BOOL ¬ FALSE, funnyCopyRight: BOOL ¬ FALSE] ~ {
secondCopyright, shortFound: BOOL ¬ FALSE;
shortCopyrightNode: Node;
EachComment: PROC [text: ROPE, node: Node, start, length: INT]
RETURNS [continue, redo: BOOL] ~ {
The copyright line is assumed to have the format
Copyright <symbol> <year>, <year>, ..., <year> <some other text>
We fix up the <symbol> to be a true copyright symbol and add the current year to the end of the list if it's not already present.
index, foundYear, lastDigitPos: INT ¬ 0;
thisLooks: TextEdit.Looks ~ IF hasNodes THEN eLooks ELSE TextEdit.noLooks;
doneWithLine: BOOL ¬ FALSE;
IF NOT Rope.IsPrefix["Copyright ", text] THEN RETURN [TRUE, FALSE];
IF shortFound THEN {
secondCopyright ¬ TRUE;
funnyCopyRight ¬ NOT Rope.Equal[text, fullCopyright];
RETURN[FALSE, FALSE];
};
shortCopyrightNode ¬ node;
IF text.Run[9, " c "] = 3 THEN {  -- replace obsolete math font symbol
[] ¬ TextEdit.ReplaceByRope[root: root, dest: node, rope: " Ó ", start: start + 9, len: 3, looks: thisLooks];
changed ¬ TRUE;
}
ELSE IF text.Run[pos1: 9, s2: " (C) ", case: FALSE] = 5 THEN {
  -- replace legally useless "(C)" symbol
[] ¬ TextEdit.ReplaceByRope[root: root, dest: node, rope: " Ó ", start: start + 9, len: 5, looks: thisLooks];
changed ¬ TRUE;
RETURN[TRUE, TRUE]; -- need new copy of text to work with
}
ELSE IF hasNodes THEN {
looks: TextEdit.Looks ~ TextEdit.FetchLooks[node, start + 10];
IF NOT looks['e] THEN {
TextEdit.ChangeLooks[root: root, text: node, add: eLooks, start: start + 10, len: 1];
changed ¬ TRUE;
};
};
index ¬ text.SkipTo[0, " \t"]; -- skip "Copyright" and the <symbol>
index ¬ text.SkipOver[index, " \t"];
index ¬ text.SkipTo[index, " \t"];
index ¬ text.SkipOver[index, " \t"];
lastDigitPos ¬ index-2; -- for malformed Copyright's, put year after symbol
WHILE index < length DO
ch: CHAR ~ text.Fetch[index];
SELECT TRUE FROM
ch IN ['0..'9] => {
lastDigitPos ¬ index;
index ¬ index + 1;
IF foundYear < 1000 THEN
foundYear ¬ foundYear * 10 + (ch - '0)
ELSE
foundYear ¬ -1;
};
foundYear = thisYear => { doneWithLine ¬ TRUE; EXIT };
( ch = ', ) OR ( ch = ' ) OR ( ch = '\t ) => {
foundYear ¬ 0;
index ¬ text.SkipOver[index + 1, ", \t"];
};
ENDCASE => {
IF changed OR alreadyChanged THEN {
[] ¬ TextEdit.ReplaceByRope[root: root, dest: node, rope: yearRope, start: start + lastDigitPos + 1, len: 0];
changed ¬ TRUE;
};
doneWithLine ¬ TRUE;
EXIT;
};
IF doneWithLine THEN EXIT;
ENDLOOP;
shortFound ¬ TRUE;
RETURN[TRUE, FALSE];
};
CopyrightLines: PROC[node: Node] ~ { -- We must add at least one new copyright line.
rope: ROPE ~ TextEditBogus.GetRope[node];
prefixLength: INT ~ CommentPrefix[rope, 0];
prefix: ROPE ~ rope.Substr[len: prefixLength];
index: INT ~ rope.SkipTo[skip: "\l\r"];
Add: PROC[node: Node, fullLine: ROPE, where: EditSpan.Place, isComment, short: BOOL] ~ {
child: Node ~ EditSpan.InsertTextNode[root: root, old: node, where: where];
[] ¬ TextEdit.ReplaceByRope[root: root, dest: child, rope: fullLine];
IF isComment THEN TextEdit.PutComment[child, TRUE];
IF short AND hasNodes THEN TextEdit.ChangeLooks[root: root, text: child, add: eLooks, start: 10, len: 1];
IF node # root AND where # $before THEN
TextEdit.PutFormat[node: child, format: IF short THEN TextEdit.GetFormat[node] ELSE $finepoint];
};
IF NOT TextEdit.GetComment[node] AND prefixLength = 0 THEN { -- no initial comment
IF NOT shortFound THEN Add[node, shortCopyright, $before, TRUE, TRUE];
node ¬ TextNode.StepForward[node];
IF NOT short THEN Add[node, fullCopyright, $after, TRUE, FALSE];
}
ELSE IF index < rope.Length[] THEN { -- first comment ends with a newline
Add the line as the second line of the document, copying the comment characters and EOL character of the first line.
newline: CHAR ~ rope.Fetch[index];
resultLen: INT ¬ 0;
fullLine: ROPE;
IF NOT shortFound THEN {
fullLine ¬ IF prefixLength = 0 THEN shortCopyright.Concat[Rope.FromChar[newline]]
ELSE IO.PutFR["%g %g%g", [rope[prefix]], [rope[shortCopyright]], [character[newline]]];
resultLen ¬ TextEdit.ReplaceByRope[root: root, dest: node, rope: fullLine, start: index+1, len: 0].resultLen;
};
IF NOT short THEN {  -- add rest of fullCopyright
fullLine ¬ IF prefixLength = 0 THEN fullCopyright.Concat[Rope.FromChar[newline]]
ELSE IO.PutFR["%g %g%g", [rope[prefix]], [rope[fullCopyright]], [character[newline]]];
[] ¬ TextEdit.ReplaceByRope[root: root, dest: node, rope: fullLine, start: index+resultLen+1, len: 0];
};
}
ELSE IF prefixLength = 0 THEN {
IF NOT shortFound THEN {
Add[node, shortCopyright, $child, TRUE, TRUE];
IF NOT short THEN Add[TextNode.StepForward[node], fullCopyright, $after, TRUE, FALSE];
}
ELSE Add[node, fullCopyright, $after, TRUE, FALSE];
}
ELSE {
IF NOT shortFound THEN Add[node, IO.PutFR["%g %g", [rope[prefix]], [rope[shortCopyright]]], $after, TextEdit.GetComment[node], TRUE];
IF NOT short THEN Add[TextNode.StepForward[node], IO.PutFR["%g %g", [rope[prefix]], [rope[fullCopyright]]], $after, TextEdit.GetComment[node], FALSE];
};
};
[] ¬ EnumerateInitialCommentLines[root, EachComment];
IF shortFound AND ( short OR secondCopyright ) THEN RETURN;
IF NOT shortFound THEN CopyrightLines[TextNode.StepForward[root]]
ELSE CopyrightLines[shortCopyrightNode];
changed ¬ TRUE;
};
CheckProperties: PROC[root: TextNode.Ref, isTioga: BOOL, isDoc: BOOL ¬ FALSE] RETURNS[changed: BOOL ¬ FALSE, oldStyleDef: BOOL ¬ FALSE] = {
IF root.hasStyleDef
THEN oldStyleDef ¬ TRUE -- has $StyleDef property, don't clobber it
ELSE {
currentStyle: ROPE ~ Atom.GetPName[NodeStyleOps.StyleNameForNode[root]];
wantedStyle: ROPE ~ IF isTioga THEN "cedardoc" ELSE "cedarcode";
IF NOT Rope.Equal[currentStyle, wantedStyle, FALSE] THEN {
TextEdit.ChangeStyle[root, wantedStyle];
changed ¬ TRUE;
};
};
IF isDoc THEN {
put LastEdited $Mark property on initial comment nodes of doc files
lastEdited: ROPE ~ "LastEdited";
FOR node: Node ¬ TextNode.StepForward[root], TextNode.StepForward[node]
WHILE (node#NIL AND TextEdit.GetComment[node]) DO
WITH NodeProps.GetProp[node, $Mark] SELECT FROM
rope: ROPE => IF Rope.Equal[rope, lastEdited] THEN LOOP;
ENDCASE;
NodeProps.PutProp[node, $Mark, lastEdited];
changed ¬ TRUE;
ENDLOOP;
};
IF isTioga THEN {
check for obsolete $Postfix property
DKW: What was the intent of this???
prop: REF ¬ NodeProps.GetProp[root, $Postfix];
IF prop # NIL THEN {
NodeProps.RemProp[root, $Postfix];
changed ¬ TRUE;
};
};
};
CheckForEmptyNodes: PROC[root: TextNode.Ref, out: IO.STREAM, file: ROPE]
RETURNS[changed: BOOL ¬ FALSE] = {
make special check for mesa files, looking for empty nodes at beginning
nonEmptySeen, nonEmptyComment: BOOL ¬ FALSE;
atBeginning: BOOL ¬ TRUE;
this: TextNode.Ref ¬ TextNode.StepForward[root];
AddNameAsNode: PROC = {
add file name as first node of file
child: Node ¬ EditSpan.InsertTextNode[root: root, old: TextNode.StepForward[root], where: $before];
[] ¬ TextEdit.ReplaceByRope[root: root, dest: child, rope: file];
TextEdit.PutComment[child, TRUE];
add a blank node after name
child ¬ EditSpan.InsertTextNode[root: root, old: TextNode.StepForward[root], where: $after];
TextEdit.PutComment[child, TRUE];
out.PutF1["\t$$ %g has no non-empty comment nodes at the beginning\n", [rope[file]] ];
out.PutRope["\t\t$$\tadding file name as inital node\n" ];
changed ¬ TRUE;
};
UNTIL this = NIL DO
thisLevel: INT;
commentPrefixLen: INT ¬ CommentPrefix[this.rope, 0];
IF ( Rope.Size[this.rope] = 0 ) AND atBeginning THEN {
span: TextNode.Span ~ TextNode.MakeNodeSpan[this, this];
this ¬ TextNode.StepForward[this];
EditSpan.Delete[root, span, NIL, FALSE];
changed ¬ TRUE;
LOOP;
};
IF ( commentPrefixLen = 0 ) AND ( NOT TextEdit.GetComment[this] ) THEN {
IF atBeginning OR ( nonEmptySeen AND NOT nonEmptyComment ) THEN AddNameAsNode[];
RETURN;
};
check for nesting level; only the first node should be at level 1
nonEmptySeen ¬ nonEmptySeen OR ( Rope.Size[this.rope] # 0 );
IF nonEmptySeen AND TextEdit.GetComment[this] THEN nonEmptyComment ¬ TRUE;
thisLevel ¬ TextNode.Level[this];
IF atBeginning THEN {
IF thisLevel # 1 THEN {
[] ¬ EditSpan.ChangeNesting[root, TextNode.MakeNodeSpan[this, this], -thisLevel+1];
changed ¬ TRUE;
};
atBeginning ¬ FALSE;
this ¬ TextNode.StepForward[this];
LOOP;
};
IF thisLevel = 1 THEN {
[] ¬ EditSpan.ChangeNesting[root, TextNode.MakeNodeSpan[this, this], +1];
changed ¬ TRUE;
LOOP;
};
this ¬ TextNode.StepForward[this];
ENDLOOP;
};
ChangeCharCodes: PROC[root: TextNode.Ref, hasNodes: BOOL]
RETURNS[changed: BOOL ¬ FALSE] = {
called only for .mesa files
make all the non-comment nodes have format $code if they don't already have a format
inQuotes: BOOL ¬ FALSE;
FOR each: TextNode.Ref ¬ TextNode.StepForward[root], TextNode.StepForward[each] UNTIL each = NIL DO
size: INT;
index: INT ¬ 0;
IF TextEdit.GetComment[each] THEN LOOP;
IF hasNodes AND ( TextEdit.GetFormat[each] = NIL ) THEN {
TextEdit.PutFormat[each, $code];
changed ¬ TRUE;
};
size ¬ Rope.Size[each.rope];
WHILE index < size DO
xchar: Char.XCHAR ¬ TextEdit.FetchChar[each, index];
IF ( Char.Set[xchar] = 0 ) THEN {
char: CHAR ~ Char.Narrow[xchar];
SELECT TRUE FROM
inQuotes =>
SELECT char FROM
'\\ => index ¬ index + 1; --skip one char;
'" => inQuotes ¬ FALSE;
ENDCASE => NULL;
( char = '" ) => inQuotes ¬ NOT inQuotes;
we play fast and loose with single quotes here - we only skip the very next char and ignore the fact of quoted chars like '\030, knowing it won't be one of the special chars we are looking for; we assume legal cedar syntax
( char = '' ) => {
index ¬ index + 1; --skip one char (and maybe two)
IF index >= size THEN EXIT; -- ' was last char in rope (comment)
xchar ¬ TextEdit.FetchChar[each, index];
IF ( Char.Set[xchar] = 0 ) AND ( Char.Narrow[xchar] = '\\ )
THEN index ¬ index + 1;
};
( char = '← ) => {
[] ¬ TextEdit.ReplaceByRope[root: root, dest: each, rope: "¬", start: index, len: 1];
TextEdit.ChangeLooks[root: root, text: each, remove: kLooks, start: index, len: 1];
changed ¬ TRUE;
};
( char = '^ ) => {
[] ¬ TextEdit.ReplaceByRope[root: root, dest: each, rope: "­", start: index, len: 1];
TextEdit.ChangeLooks[root: root, text: each, remove: kLooks, start: index, len: 1];
changed ¬ TRUE;
};
( char = '\030 ) => {
[] ¬ TextEdit.ReplaceByRope[root: root, dest: each, rope: "\045", charSet: 357B, start: index, len: 1];
changed ¬ TRUE;
};
ENDCASE => NULL;
};
index ¬ index + 1;
ENDLOOP;
ENDLOOP;
};
ChangeNewLinesToLF: PROC[root: TextNode.Ref] = {
NodeProps.PutProp[n: root, name: $NewlineDelimiter, value: Rope.Flatten["\l"]];
root.comment ¬ TRUE;
FOR each: TextNode.Ref ¬ TextNode.StepForward[root], TextNode.StepForward[each] UNTIL each = NIL DO
size: INT ~ Rope.Size[each.rope];
FOR index: INT ¬ Rope.SkipTo[s: each.rope, pos: 0, skip: "\l\r"], Rope.SkipTo[s: each.rope, pos: index+1, skip: "\l\r"] UNTIL index = size DO
IF Char.Set[TextEdit.FetchChar[each, index]] = 0 THEN
[] ¬ TextEdit.ReplaceByRope[root: root, dest: each, rope: "\l", start: index, len: 1];
ENDLOOP;
ENDLOOP;
};
scriptPrefix: ROPE ~ "#!";
scriptPrefixLen: INT ~ scriptPrefix.Length[];
IsScript: PROC[root: TextNode.Ref] RETURNS[isScript: BOOL ¬ FALSE] = {
this: ROPE ¬ TextNode.StepForward[root].rope;
IF this.Length[] < scriptPrefixLen THEN RETURN;
RETURN[ ( this.Fetch[0] = '# ) AND ( this.Fetch[1] = '! ) ];
};
DoOneFile: PROC[out: IO.STREAM, file: ROPE, short, isTioga, isMesa: BOOL] = {
root: TextNode.Ref;
changed, funnySecondCopyright: BOOL ¬ FALSE;
ref: REF;
hasNodes, oldStyleDef: BOOL ¬ FALSE;
root ¬ TiogaIO.FromFile[PFS.PathFromRope[file] ! PFS.Error => {
out.PutF1["** Couldn't open %g\n", [rope[file]] ];
CONTINUE;
} ].root;
IF root = NIL THEN RETURN;
IF NOT short AND IsScript[root] THEN {
out.PutF1["\t\t~ %g is a shell script\n", [rope[file]] ];
RETURN
};
hasNodes ¬ ( TextNode.StepForward[TextNode.StepForward[root]] # NIL );
SELECT TRUE FROM
Rope.Match["*.df", file, FALSE] => NULL;
isTioga => {
this: BOOL;
[this, oldStyleDef] ¬ CheckProperties[root: root, isTioga: TRUE,
isDoc: Rope.Match["*Doc.tioga", file, FALSE]];
changed ¬ changed OR this;
};
ENDCASE => {
this: BOOL ¬ CheckProperties[root: root, isTioga: FALSE].changed;
changed ¬ changed OR this;
this ¬ CheckForEmptyNodes[root, out, file];
changed ¬ changed OR this;
IF isMesa THEN {
this ¬ ChangeCharCodes[root, hasNodes];
changed ¬ changed OR this;
};
};
IF oldStyleDef THEN
out.PutF1["\t\t*==> %g has StyleDef property\n", [rope[file]] ];
ref ¬ NodeProps.GetProp[root, $NewlineDelimiter]; -- does it have $NewlineDelimiter?
IF ref = NIL THEN { ChangeNewLinesToLF[root]; changed ¬ TRUE }
ELSE {
rp: ROPE ¬ NARROW[ref];
IF rp.Equal["\r"] THEN { ChangeNewLinesToLF[root]; changed ¬ TRUE };
};
don't do the copyright stuff for tioga files - that will be dealt with by hand
IF NOT isTioga THEN {
this: BOOL;
for now, just use short copyright notice
[this, funnySecondCopyright] ¬ UpdateCopyrightNotice[root, TRUE, hasNodes, changed];
changed ¬ changed OR this;
};
IF funnySecondCopyright THEN
out.PutF1["\t\t*** %g has a funny secondCopyright notice\n", [rope[file]] ];
IF changed THEN {
set date of new file one minute later than its "source"; one minute allows one to see the time difference with Unix's ls
of: PFS.OpenFile;
filePath: PFS.PATH ~ PFS.PathFromRope[file];
fileType: PFS.FileType;
uid: PFS.UniqueID;
stream: IO.STREAM;
[ , , uid, , , fileType] ¬ PFS.FileInfo[filePath];
uid.egmt.gmt ¬ BasicTime.Update[uid.egmt.gmt, 60];
of ¬ PFS.Open[name: filePath, access: $create, wantedUniqueID: uid, fileType: fileType];
stream ¬ PFS.StreamFromOpenFile[of, $create];
[] ¬ TiogaIO.ToStream[stream, root];
IO.Close[stream];
IF isTioga THEN out.PutF1["\t=> %g has been updated\n", [rope[file]] ]
ELSE out.PutF1["\t%g has been updated\n", [rope[file]] ];
}
ELSE {
IF isTioga THEN out.PutF1["\t\t=> %g did not change\n", [rope[file]] ]
ELSE out.PutF1["\t\t& %g did not change\n", [rope[file]] ];
};
};
FixupCedarFileCmd: Commander.CommandProc = {
arg: ROPE ¬ CommanderOps.NextArgument[cmd];
ignoreExtn: BOOL ¬ Rope.Equal[arg, "-d", FALSE];
fileBase: ROPE ¬ IF ignoreExtn THEN CommanderOps.NextArgument[cmd] ELSE arg;
fileExtn: ROPE ~ CommanderOps.NextArgument[cmd];
file: ROPE ¬ Rope.Concat[fileBase, fileExtn];
IF file = NIL THEN RETURN;
DoFixup[cmd.out, fileExtn, file, ignoreExtn];
};
FixupCedarFile: Commander.CommandProc = {
ignoreExtn: BOOL ¬ FALSE;
FOR arg: ROPE ¬ CommanderOps.NextArgument[cmd], CommanderOps.NextArgument[cmd] UNTIL arg = NIL DO
short, fileExtn: ROPE;
pos: INT;
IF Rope.Equal[arg, "-d", FALSE] THEN { ignoreExtn ¬ TRUE; LOOP };
IF Rope.Equal[arg, "-~d", FALSE] THEN { ignoreExtn ¬ FALSE; LOOP };
short ¬ PFSNames.ComponentRope[PFSNames.ShortName[PFS.PathFromRope[arg]]];
pos ¬ short.Find["."];
IF pos # -1 THEN { fileExtn ¬ short.Substr[pos] }; -- include . in extn
IF pos = -1 THEN { fileBase ¬ file }
ELSE {
fileExtn ¬ short.Substr[pos]; -- include . in extn
fileBase ¬ file.Substr[0, file.Length[]-(short.Length[] - pos)];
};
DoFixup[cmd.out, fileExtn, arg, ignoreExtn];
ENDLOOP;
};
DoFixup: PROC[out: IO.STREAM, fileExtn, file: ROPE, ignoreExtn: BOOL] = {
short, isTioga, isMesa: BOOL ¬ FALSE;
doIt: BOOL ¬ TRUE;
IF NOT ignoreExtn THEN
SELECT TRUE FROM
Rope.Equal[".mesa", fileExtn] => isMesa ¬ TRUE;
Rope.Equal[".meta", fileExtn] => isMesa ¬ TRUE;
Rope.Equal[".tioga", fileExtn] => isTioga ¬ TRUE;
Rope.Equal[".config", fileExtn] => NULL;
Rope.Equal[".abbreviations", fileExtn] => NULL;
Rope.Equal[".command", fileExtn] => NULL;
Rope.Equal[".cm", fileExtn] => NULL;
Rope.Equal[".df", fileExtn] => NULL;
Rope.Equal[".require", fileExtn] => NULL;
ENDCASE => { doIt ¬ FALSE; short ¬ TRUE };
IF doIt THEN DoOneFile[out, file, short, isTioga, isMesa]
ELSE
out.PutF1["\t\t\t# skipping %g\n", [rope[file]] ];
};
eLooks: TextEdit.Looks ¬ TextEdit.noLooks;
kLooks: TextEdit.Looks ¬ TextEdit.noLooks;
thisYear: INT ~ BasicTime.Unpack[BasicTime.Now[]].year;
yearRope: ROPE ~ IO.PutFR1[", %g", [integer[thisYear]]];
shortCopyright: ROPE;
fullCopyright: ROPE ~
"Copyright protection claimed includes all forms and matters of copyrightable material and information now allowed by statutory or judicial law or hereinafter granted, including without limitation, material generated from the software programs which are displayed on the screen such as icons, screen display looks, character bitmaps, etc.";
InitVals: PROC = {
holder: ROPE ~ UserProfile.Line["Tioga.CopyrightHolder", "Xerox Corporation"];
shortCopyright ¬ IO.PutFR["Copyright Ó %g by %g. All rights reserved.", [integer[thisYear]], [rope[holder]]];
eLooks['e] ¬ TRUE;
kLooks['k] ¬ TRUE;
};
Commander.Register["FixupCedarFileCmd", FixupCedarFileCmd, "Usage: FixupCedarFileCmd {-d} base .extension"];
Commander.Register["FixupCedarFile", FixupCedarFile, "Usage: FixupCedarFile {-d} base.extension"];
InitVals[];
END.