<> <> <> <> <> <> <> <> <> <<>> <> <<>> DIRECTORY Ascii, NodeStyle, NodeStyleExtra, NodeStyleObject, TextLooks, NameSymbolTable, Real, SafeStorage, TJaMOps, TJaMBasic; NodeStyleTabsImpl: CEDAR PROGRAM IMPORTS Ascii, TJaMOps, NodeStyle, NodeStyleExtra, NodeStyleObject, Real EXPORTS NodeStyle, NodeStyleExtra = BEGIN OPEN R:Real, NodeStyle, NodeStyleExtra, NodeStyleObject; <> <<>> RulesTabCount: PUBLIC PROC [stop: RulesTabStop] RETURNS [count: INTEGER] = { RETURN [stop.array.length/2] }; RulesTabInfo: PUBLIC PROC [stop: RulesTabStop, num: INTEGER] RETURNS [weight, vshift: REAL] = TRUSTED { <> ObjectToReal: PROC [ob: TJaMBasic.Object] RETURNS [Real] = TRUSTED { WITH ob:ob SELECT FROM integer => RETURN[ob.ivalue]; real => RETURN[ob.rvalue]; ENDCASE => ERROR }; weight _ ObjectToReal[TJaMOps.AGet[stop.array, num*2]]; vshift _ ObjectToReal[TJaMOps.AGet[stop.array, num*2+1]] }; RulesTabInfoI: PUBLIC PROC [stop: RulesTabStop, num: INTEGER] RETURNS [weight, vshift: INTEGER] = TRUSTED { ObjectToInteger: PROC [ob: TJaMBasic.Object] RETURNS [INTEGER] = TRUSTED { WITH ob:ob SELECT FROM integer => RETURN[ob.ivalue]; real => RETURN[R.RoundI[ob.rvalue]]; ENDCASE => ERROR }; weight _ ObjectToInteger[TJaMOps.AGet[stop.array, num*2]]; vshift _ ObjectToInteger[TJaMOps.AGet[stop.array, num*2+1]] }; <> <<>> GetTabRealCode: PROC [ref: Ref, stop: TabStop, which: TabRealParam, value: Real] RETURNS [code: RealCode] = { code _ EnterReal[value ! realTableOverflow => { code _ overflow; ref.dataList _ NEW[DataEntry _ [ ref.dataList, tab[stop, which, value, IntegerValue[value]]]]; CONTINUE }] }; GetTabOverflow: PUBLIC PROC [ref: Ref, stop: TabStop, which: TabRealParam] RETURNS [value: Real] = { FOR x: DataList _ ref.dataList, x.next UNTIL x=NIL DO xx: REF DataEntry.tab = NARROW[x]; IF xx.tabStop=stop AND xx.which=which THEN RETURN [xx.value]; ENDLOOP; ERROR -- failed to find it on the data list -- }; GetTabIntOverflow: PUBLIC PROC [ref: Ref, stop: TabStop, which: TabRealParam] RETURNS [value: INTEGER] = { FOR x: DataList _ ref.dataList, x.next UNTIL x=NIL DO xx: REF DataEntry.tab = NARROW[x]; IF xx.tabStop=stop AND xx.which=which THEN RETURN [xx.valueI]; ENDLOOP; ERROR -- failed to find it on the data list -- }; <> <<>> RelativeTabStopsOp: PUBLIC PROC [frame: Frame] = { ref: Ref _ StyleForFrame[frame]; name: Name; ok: BOOL; [name, ok] _ TryToPopName[frame]; IF ~ok THEN { -- restore name to stack and return default PushText[frame,"illegal value for tabStops: should be fixed or relative"L]; StyleError[frame,1] }; SELECT name FROM fixed => ref.fixedTabs _ TRUE; relative => ref.fixedTabs _ FALSE; ENDCASE => { -- restore name to stack and return default PushName[frame, name]; PushText[frame,"illegal value for tabStops: should be fixed or relative"L]; StyleError[frame,2] }}; DefaultTabStopsOp: PUBLIC PROC [frame: Frame] = { ref: Ref _ StyleForFrame[frame]; tabStop: TabStop _ TabSpec[ref, frame]; tabStop.loc _ GetTabRealCode[ref, tabStop, loc, PopReal[frame]]; ref.defaultTabStops _ tabStop }; <<>> <> <<>> TabStopOp: PUBLIC PROC [frame: Frame] = { ref: Ref _ StyleForFrame[frame]; tabStop: TabStop _ TabSpec[ref, frame]; loc: Real; tabStop.loc _ GetTabRealCode[ref, tabStop, loc, PopReal[frame]]; <> <> loc _ GetTabLoc[tabStop, ref]; ref.numTabStops _ ref.numTabStops+1; IF ref.tabStops = NIL OR GetTabLoc[ref.tabStops.first, ref] <= loc THEN ref.tabStops _ CONS[tabStop, ref.tabStops] ELSE { -- copy list up to first with smaller loc old: LIST OF TabStop _ ref.tabStops; new: LIST OF TabStop _ CONS[old.first, NIL]; ref.tabStops _ new; FOR lst: LIST OF TabStop _ old.rest, lst.rest DO IF lst=NIL OR GetTabLoc[lst.first, ref] <= loc THEN { -- insert here new.rest _ CONS[tabStop, lst]; EXIT }; new.rest _ CONS[lst.first, NIL]; new _ new.rest; ENDLOOP }}; TabSpec: PROC [ref: Ref, frame: Frame] RETURNS [tabStop: TabStop] = { -- parse tab specs looks: TextLooks.Looks _ TabLooksSpec[frame]; breakIfPast: BOOL _ TabPastSpec[frame]; tabStop _ TabPattern[ref, frame]; tabStop.looks _ looks; tabStop.breakIfPast _ breakIfPast; TabAlign[tabStop, frame] }; TabLooksSpec: PROC [frame: Frame] RETURNS [lks: TextLooks.Looks] = TRUSTED { name: Name; ok: BOOL; SetLookBit: PROC [look: CHAR] RETURNS [quit: BOOL] = TRUSTED { look _ Ascii.Lower[look]; IF look IN ['a..'z] THEN lks[look] _ TRUE; RETURN [FALSE] }; lks _ TextLooks.noLooks; [name, ok] _ TryToPopName[frame]; IF ~ok THEN RETURN; IF name # looks THEN { PushName[frame, name]; RETURN }; TJaMOps.StringForAll[TJaMOps.PopString[frame.opstk], SetLookBit]; }; TabPastSpec: PROC [frame: Frame] RETURNS [break: BOOL] = { name: Name; ok: BOOL; [name, ok] _ TryToPopName[frame]; IF ~ok THEN RETURN; SELECT name FROM breakIfPast => break _ TRUE; spaceIfPast => break _ FALSE; ENDCASE => { -- restore name to stack and return default PushName[frame, name]; break _ FALSE }}; TabPattern: PROC [ref: Ref, frame: Frame] RETURNS [tabStop: TabStop] = { name: Name; ok: BOOL; [name, ok] _ TryToPopName[frame]; IF ~ok THEN { tabStop _ NEW[blank TabStopRec]; RETURN }; SELECT name FROM blank => tabStop _ NEW[blank TabStopRec]; leaders => { leaderChar: BOOL _ FALSE; string: string TJaMBasic.Object; value: Real; SetLeaderChar: PROC [c: CHAR] RETURNS [quit: BOOL] = { IF leaderChar THEN { PushText[frame,"Cannot specify more than one character for tab leaders"L]; StyleError[frame,1] }; leaderChar _ TRUE; ldrStop.char _ c }; ldrStop: LeaderTabStop _ NEW[leaders TabStopRec]; tabStop _ ldrStop; [name, ok] _ TryToPopName[frame]; IF ~ok THEN ldrStop.congruent _ TRUE ELSE SELECT name FROM centered => ldrStop.congruent _ FALSE; congruent => ldrStop.congruent _ TRUE; ENDCASE => { PushName[frame,name]; PushText[frame,"is not legal as value for tab leaders: congruent or centered"L]; StyleError[frame,2] }; [value, ok] _ TryToPopReal[frame]; ldrStop.spacing _ GetTabRealCode[ref, tabStop, spacing, IF ok THEN value ELSE 0.0]; [string, ok] _ TryToPopString[frame]; IF ok THEN TRUSTED {TJaMOps.StringForAll[string, SetLeaderChar]} ELSE { PushText[frame,"Must specify character for leaders"L]; StyleError[frame,1] }}; rule => { ruleStop: RuleTabStop _ NEW[rule TabStopRec]; tabStop _ ruleStop; ruleStop.vshift _ GetTabRealCode[ref, tabStop, vshift, PopReal[frame]]; ruleStop.weight _ GetTabRealCode[ref, tabStop, weight, PopReal[frame]] }; rules => { rulesStop: RulesTabStop _ NEW[rules TabStopRec]; tabStop _ rulesStop; TRUSTED {rulesStop.array _ TJaMOps.PopArray[frame.opstk] }}; ENDCASE => { <> PushName[frame, name]; tabStop _ NEW[blank TabStopRec] }}; MissingChar: PROC [frame: Frame] = { PushText[frame,"Cannot specify more than one character for tab alignment"L]; StyleError[frame,1] }; TabAlign: PROC [tabStop: TabStop, frame: Frame] = { name: Name; ok: BOOL; [name, ok] _ TryToPopName[frame]; IF ~ok THEN { tabStop.alignment _ FlushLeft; RETURN }; SELECT name FROM flushLeft => tabStop.alignment _ FlushLeft; flushRight => tabStop.alignment _ FlushRight; centered => tabStop.alignment _ Centered; aligned => { alignmentChar: BOOL _ FALSE; string: string TJaMBasic.Object; SetAlignmentChar: PROC [c: CHAR] RETURNS [quit: BOOL] = { IF alignmentChar THEN { PushText[frame,"Cannot specify more than one character for tab alignment"L]; StyleError[frame,1] }; alignmentChar _ TRUE; tabStop.alignmentChar _ c }; tabStop.alignment _ Character; [string, ok] _ TryToPopString[frame]; IF ok THEN TRUSTED {TJaMOps.StringForAll[string, SetAlignmentChar]} ELSE { PushText[frame,"Must specify character for tab alignment"L]; StyleError[frame,1] }}; ENDCASE => { PushName[frame, name]; tabStop.alignment _ FlushLeft }}; END...