DIRECTORY EBEditors, EBLanguage, EBTypes, EmbeddedButtons, EBNullDoc, IO, List, Prop, Rope, SymTab; EBNullDocImpl: CEDAR PROGRAM IMPORTS EBEditors, IO, List, Prop, Rope, SymTab EXPORTS EBNullDoc = BEGIN ActiveDoc: TYPE = EBTypes.ActiveDoc; ActiveButton: TYPE = EBTypes.ActiveButton; Variable: TYPE = EBLanguage.Variable; VariableObj: TYPE = EBLanguage.VariableObj; VariableType: TYPE = EBLanguage.VariableType; VariableTypeObj: TYPE = EBLanguage.VariableTypeObj; ROPE: TYPE = Rope.ROPE; nullActiveDocClass: EBEditors.ActiveDocClass ¬ NEW[EBEditors.ActiveDocClassObj ¬ [ name: $NullDoc, getRef: NullDocGetRef, setRef: NullDocSetRef, mapRef: NullDocMapRef, getDocName: NullDocGetDocName, feedback: NullDocButtonFeedback, -- Feedback is the name of an interface inButton: NullDocInButton ]]; NullDoc: TYPE = REF NullDocObj; NullDocObj: TYPE = RECORD [ instantiated: BOOL _ FALSE, docName: ROPE, buttons: SymTab.Ref -- maps button names to button datas ]; NullButton: TYPE = REF NullButtonObj; NullButtonObj: TYPE = RECORD [ name: ROPE, -- button name firstValue: NameVariablePair, -- built by Create*Button. First variable and value moreValues: LIST OF NameVariablePair, -- built by Add*Variable. More variables and values propList: Prop.PropList -- built by Instantiate from "firstValue" and "moreValues" fields ]; NameVariablePair: TYPE = RECORD [ name: ROPE, variable: EBLanguage.Variable ]; NullDocGetRef: EBEditors.GetRefProc = { nullButton: NullButton _ NARROW[button]; ref ¬ Prop.Get[nullButton.propList, key]; }; NullDocSetRef: EBEditors.SetRefProc = { nullButton: NullButton _ NARROW[button]; nullButton.propList ¬ Prop.Put[nullButton.propList, key, ref]; }; NullDocMapRef: EBEditors.MapRefProc = { ForEachButton: SymTab.EachPairAction = { nullButton: NullButton _ NARROW[val]; quit ¬ mapProc[nullButton, doc]; }; buttons: SymTab.Ref _ NARROW[doc.theDoc, NullDoc].buttons; aborted ¬ SymTab.Pairs[buttons, ForEachButton]; }; NullDocGetDocName: EBEditors.GetDocNameProc ~ { name _ NARROW[doc.theDoc, NullDoc].docName; }; NullDocButtonFeedback: EBEditors.FeedbackProc = { RETURN[NIL]; }; NullDocInButton: EBEditors.InButtonProc = { RETURN[FALSE]; }; Create: PUBLIC PROC [docName: ROPE] RETURNS [doc: ActiveDoc] = { nullDoc: NullDoc _ NEW[NullDocObj _ [FALSE, docName, SymTab.Create[]] ]; doc ¬ EBEditors.CreateActiveDoc[nullDoc, nullActiveDocClass]; }; emptyRope: ROPE = ""; semiRope: ROPE = "; "; prefix: ROPE = "Poppy1\nClass: MultiStateButton\nVariables: ("; -- prefix for every button data suffix: ROPE = ")\n"; Instantiate: PUBLIC PROC [doc: ActiveDoc] = { InstantiateEachButton: EmbeddedButtons.EachButtonProc = { RopeFromNameVariablePair: PROC [nv: NameVariablePair, semiColon: BOOL] RETURNS [r: ROPE] = { SELECT nv.variable.type.class FROM boolean => { r _ IO.PutFR["%g: BOOL = %g%g", [rope[nv.name]], [boolean[NARROW[nv.variable.value, REF BOOL]­]], [rope[IF semiColon THEN semiRope ELSE emptyRope]] ]; }; atom => { r _ IO.PutFR["%g: ATOM = %g%g", [rope[nv.name]], [atom[NARROW[nv.variable.value, ATOM]]], [rope[IF semiColon THEN semiRope ELSE emptyRope]] ]; }; rope => { r _ IO.PutFR["%g: STRING = \"%g\"%g", [rope[nv.name]], [rope[NARROW[nv.variable.value, ROPE]]], [rope[IF semiColon THEN semiRope ELSE emptyRope]] ]; }; integer => { r _ IO.PutFR["%g: INT = %g%g", [rope[nv.name]], [integer[NARROW[nv.variable.value, REF INT]­]], [rope[IF semiColon THEN semiRope ELSE emptyRope]] ]; }; real => { r _ IO.PutFR["%g: REAL = %g%g", [rope[nv.name]], [real[NARROW[nv.variable.value, REF REAL]­]], [rope[IF semiColon THEN semiRope ELSE emptyRope]] ]; }; enumerated => { RopeFromEnumeration: PROC [v: VariableType] RETURNS [e: ROPE] = { e _ "{"; -- open curly bracket FOR n: NAT IN [1.. v.count] DO e _ IO.PutFR["%g%g%g", [rope[e]], WITH v[n-1] SELECT FROM z: ROPE => [rope[Rope.Cat["\"", z, "\""]]], z: ATOM => [atom[z]], z: REF INT => [integer[z­]], z: REF REAL => [real[z­]], z: REF BOOL => [boolean[z­]], ENDCASE => [rope["UnknownEnumType"]], IF n [rope[Rope.Cat["\"", z, "\""]]], z: ATOM => [atom[z]], z: REF INT => [integer[z­]], z: REF REAL => [real[z­]], z: REF BOOL => [boolean[z­]], ENDCASE => [rope["UnknownValueType"]], [rope[IF semiColon THEN semiRope ELSE emptyRope]] ] ]; }; ENDCASE => ERROR; }; bdRope: ROPE; buttonData: REF; nB: NullButton _ NARROW[button]; FOR l: LIST OF NameVariablePair _ nB.moreValues, l.rest UNTIL l=NIL DO bdRope _ Rope.Concat[bdRope, RopeFromNameVariablePair[l.first, l.rest#NIL]]; ENDLOOP; bdRope _ Rope.Concat[RopeFromNameVariablePair[nB.firstValue, nB.moreValues # NIL], bdRope]; bdRope _ Rope.Concat[prefix, bdRope]; -- concat the required prefix for buttonData bdRope _ Rope.Concat[bdRope, suffix]; -- concat the required suffix for buttonData bdRope _ Rope.Cat[bdRope, "Name: ", nB.name]; buttonData ¬ EBEditors.ButtonDataFromRope[rope: bdRope, instantiateNow: FALSE, button: button, doc: doc]; NullDocSetRef[key: $ButtonData, ref: buttonData, button: button, doc: doc, edited: FALSE]; }; aborted: BOOL ¬ TRUE; thisDoc: NullDoc _ NARROW[doc.theDoc]; aborted ¬ NullDocMapRef[doc: doc, mapProc: InstantiateEachButton]; IF NOT aborted THEN thisDoc.instantiated _ TRUE; }; CreateBOOLButton: PUBLIC PROC [doc: ActiveDoc, buttonName: ROPE, initialVarVal: BOOL] RETURNS [ActiveButton] = { button: NullButton; buttons: SymTab.Ref _ NARROW[doc.theDoc, NullDoc].buttons; valRef: REF BOOL _ NEW[BOOL ¬ initialVarVal]; button _ NEW[NullButtonObj ¬ [name: buttonName, firstValue: [name: "Value", variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: boolean]--], value: valRef]]]]]; button.firstValue.variable.type.class ¬ boolean; [] ¬ SymTab.Store[buttons, buttonName, button]; RETURN[button]; }; AddBOOLVariable: PUBLIC PROC [button: ActiveButton, varName: ROPE, varVal: BOOL] = { nvPair: NameVariablePair; nullButton: NullButton _ NARROW[button]; varValRef: REF BOOL _ NEW[BOOL ¬ varVal]; nvPair ¬ [name: varName, variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: boolean]--], value: varValRef]] ]; nvPair.variable.type.class ¬ boolean; nullButton.moreValues ¬ CONS[nvPair, nullButton.moreValues]; }; CreateATOMButton: PUBLIC PROC [doc: ActiveDoc, buttonName: ROPE, initialVarVal: ATOM] RETURNS [ActiveButton] = { button: NullButton; buttons: SymTab.Ref _ NARROW[doc.theDoc, NullDoc].buttons; button _ NEW[NullButtonObj ¬ [name: buttonName, firstValue: [name: "Value", variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: atom]--], value: initialVarVal]]]]]; button.firstValue.variable.type.class ¬ atom; [] ¬ SymTab.Store[buttons, buttonName, button]; RETURN[button]; }; AddATOMVariable: PUBLIC PROC [button: ActiveButton, varName: ROPE, varVal: ATOM] = { nvPair: NameVariablePair; nullButton: NullButton _ NARROW[button]; nvPair ¬ [name: varName, variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: ATOM]--], value: varVal]] ]; nvPair.variable.type.class ¬ atom; nullButton.moreValues ¬ CONS[nvPair, nullButton.moreValues]; }; CreateROPEButton: PUBLIC PROC [doc: ActiveDoc, buttonName: ROPE, initialVarVal: ROPE] RETURNS [ActiveButton] = { button: NullButton; buttons: SymTab.Ref _ NARROW[doc.theDoc, NullDoc].buttons; button _ NEW[NullButtonObj ¬ [name: buttonName, firstValue: [name: "Value", variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: rope]--], value: initialVarVal]]]]]; button.firstValue.variable.type.class ¬ rope; [] ¬ SymTab.Store[buttons, buttonName, button]; RETURN[button]; }; AddROPEVariable: PUBLIC PROC [button: ActiveButton, varName: ROPE, varVal: ROPE] = { nvPair: NameVariablePair; nullButton: NullButton _ NARROW[button]; nvPair ¬ [name: varName, variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: ROPE]--], value: varVal]] ]; nvPair.variable.type.class ¬ rope; nullButton.moreValues ¬ CONS[nvPair, nullButton.moreValues]; }; CreateINTButton: PUBLIC PROC [doc: ActiveDoc, buttonName: ROPE, initialVarVal: INT] RETURNS [ActiveButton] = { button: NullButton; buttons: SymTab.Ref _ NARROW[doc.theDoc, NullDoc].buttons; valRef: REF INT _ NEW[INT ¬ initialVarVal]; button _ NEW[NullButtonObj ¬ [name: buttonName, firstValue: [name: "Value", variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: integer]--], value: valRef]]]]]; button.firstValue.variable.type.class ¬ integer; [] ¬ SymTab.Store[buttons, buttonName, button]; RETURN[button]; }; AddINTVariable: PUBLIC PROC [button: ActiveButton, varName: ROPE, varVal: INT] = { nvPair: NameVariablePair; nullButton: NullButton _ NARROW[button]; varValRef: REF INT _ NEW[INT ¬ varVal]; nvPair ¬ [name: varName, variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: integer]--], value: varValRef]] ]; nvPair.variable.type.class ¬ integer; nullButton.moreValues ¬ CONS[nvPair, nullButton.moreValues]; }; CreateREALButton: PUBLIC PROC [doc: ActiveDoc, buttonName: ROPE, initialVarVal: REAL] RETURNS [ActiveButton] = { button: NullButton; buttons: SymTab.Ref _ NARROW[doc.theDoc, NullDoc].buttons; valRef: REF REAL _ NEW[REAL ¬ initialVarVal]; button _ NEW[NullButtonObj ¬ [name: buttonName, firstValue: [name: "Value", variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: real]--], value: valRef]]]]]; button.firstValue.variable.type.class ¬ real; [] ¬ SymTab.Store[buttons, buttonName, button]; RETURN[button]; }; AddREALVariable: PUBLIC PROC [button: ActiveButton, varName: ROPE, varVal: REAL] = { nvPair: NameVariablePair; nullButton: NullButton _ NARROW[button]; varValRef: REF REAL _ NEW[REAL ¬ varVal]; nvPair ¬ [name: varName, variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: real]--], value: varValRef]] ]; nvPair.variable.type.class ¬ real; nullButton.moreValues ¬ CONS[nvPair, nullButton.moreValues]; }; CreateRopeEnumerationButton: PUBLIC PROC [doc: ActiveDoc, buttonName: ROPE, initialVarVal: ROPE, type: LIST OF ROPE] RETURNS [ActiveButton] = { OPEN List; ptr, anyList: LORA; ptr ¬ anyList ¬ CONS[type.first, NIL]; FOR al: LIST OF ROPE ¬ type.rest, al.rest UNTIL al=NIL DO ptr.rest ¬ CONS[al.first, NIL]; ptr ¬ ptr.rest ENDLOOP; RETURN[CreateEnumeratedButton[doc, buttonName, initialVarVal, anyList]]; }; AddRopeEnumerationVariable: PUBLIC PROC [button: ActiveButton, varName: ROPE, varVal: ROPE, type: LIST OF ROPE] = { OPEN List; ptr, anyList: LORA; ptr ¬ anyList ¬ CONS[type.first, NIL]; FOR al: LIST OF ROPE ¬ type.rest, al.rest UNTIL al=NIL DO ptr.rest ¬ CONS[al.first, NIL]; ptr ¬ ptr.rest ENDLOOP; AddEnumeratedVariable[button, varName, varVal, anyList]; }; CreateEnumeratedButton: PUBLIC PROC [doc: ActiveDoc, buttonName: ROPE, initialVarVal: REF, type: LIST OF REF] RETURNS [ActiveButton] = { count: NAT ¬ 0; button: NullButton; buttons: SymTab.Ref _ NARROW[doc.theDoc, NullDoc].buttons; button _ NEW[NullButtonObj ¬ [name: buttonName, firstValue: [name: "Value", variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[List.Length[type]]-- ¬ [class: enumerated]--], value: initialVarVal]]]]]; button.firstValue.variable.type.class ¬ enumerated; FOR elements: LIST OF REF _ type, elements.rest UNTIL elements = NIL DO button.firstValue.variable.type.enumeration[count] ¬ elements.first; count _ count + 1; ENDLOOP; [] ¬ SymTab.Store[buttons, buttonName, button]; RETURN[button]; }; AddEnumeratedVariable: PUBLIC PROC [button: ActiveButton, varName: ROPE, varVal: REF, type: LIST OF REF] = { count: NAT ¬ 0; nvPair: NameVariablePair; nullButton: NullButton _ NARROW[button]; nvPair ¬ [name: varName, variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[List.Length[type]]-- ¬ [class: ]--], value: varVal]] ]; nvPair.variable.type.class ¬ enumerated; FOR elements: LIST OF REF _ type, elements.rest UNTIL elements = NIL DO nvPair.variable.type.enumeration[count] ¬ elements.first; count _ count + 1; ENDLOOP; nullButton.moreValues ¬ CONS[nvPair, nullButton.moreValues]; }; END. CreateButton: PUBLIC PROC [doc: ActiveDoc, buttonName: ROPE, initialVarVal: ] RETURNS [ActiveButton] = { button: NullButton; buttons: SymTab.Ref _ NARROW[doc.theDoc, NullDoc].buttons; valRef: REF  _ NEW[ ¬ initialVarVal]; button _ NEW[NullButtonObj ¬ [name: buttonName, firstValue: [name: "Value", variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: ]--], value: valRef]]]]]; button.firstValue.variable.type.class ¬ ; button.firstValue.variable.type.enumeration ¬ ; [] ¬ SymTab.Store[buttons, buttonName, button]; RETURN[button]; }; AddVariable: PUBLIC PROC [button: ActiveButton, varName: ROPE, varVal: ] = { nvPair: NameVariablePair; nullButton: NullButton _ NARROW[button]; varValRef: REF  _ NEW[ ¬ varVal]; nvPair ¬ [name: varName, variable: NEW[VariableObj ¬ [type: NEW[VariableTypeObj[0]-- ¬ [class: ]--], value: varValRef]] ]; nvPair.variable.type.class ¬ ; nvPair.variable.type.enumeration ¬ ; nullButton.moreValues ¬ CONS[nvPair, nullButton.moreValues]; }; ­­­­­ Enumerated types in Poppy are more general than in Cedar. Any base type can form an enumerated type. For example: x: {3, 7, 15} = 3; -- INT base type x: {"Hello", "Goodbye"} = "Hello"; -- ROPE base type x: {Foo, Bar} = Foo; -- ATOM base type x: {34.2, 63.6, 12.2} = 63.6; -- REAL base type x: {FALSE, TRUE} = FALSE -- BOOL base type (pretty silly) p EBNullDocImpl.mesa Copyright Σ 1992 by Xerox Corporation. All rights reserved. Kenneth A. Pier, October 1, 1992 11:24 am PDT Bier, September 29, 1992 4:10 pm PDT ActiveDoc Class VariableObj: TYPE = RECORD [ type: VariableType, VariableTypeObj: TYPE = RECORD [ class: {boolean, atom, rope, integer, real, enumerated}, enumeration: SEQUENCE count: NAT OF REF ANY ]; value: REF ]; PROC [key: ATOM, button: ActiveButton, doc: ActiveDoc] RETURNS [ref: REF]; PROC [key: ATOM, button: ActiveButton, doc: ActiveDoc, ref: REF, edited: BOOL]; PROC [doc: ActiveDoc, mapProc: EachButtonProc] RETURNS [aborted: BOOL ¬ FALSE]; EachButtonProc: TYPE = PROC [button: ActiveButton, doc: ActiveDoc] RETURNS [done: BOOL] PROC [key: Key, val: Val] RETURNS [quit: BOOL] PROC [doc: ActiveDoc] RETURNS [name: ROPE]; PROC[button: ActiveButton, doc: ActiveDoc, feedback: REF] RETURNS [REF]; Interface procs EBLanguage interface defines class: {boolean, atom, rope, integer, real, enumerated} EachButtonProc: TYPE = PROC [button: ActiveButton, doc: ActiveDoc] RETURNS [done: BOOL ¬ FALSE]; r is a ROPE of the form: "Name: TYPE = VALUE " or "Name: TYPE = VALUE; " x: {3, 7, 15} = 3; -- INT base type x: {"Hello", "Goodbye"} = "Hello"; -- ROPE base type x: {Foo, Bar} = Foo; -- ATOM base type x: {34.2, 63.6, 12.2} = 63.6; -- REAL base type x: {FALSE, TRUE} = FALSE -- BOOL base type (pretty silly) valRef: REF ATOM _ NEW[ATOM ¬ initialVarVal]; button.firstValue.variable.type.enumeration ¬ ; varValRef: REF ATOM _ NEW[ATOM ¬ varVal]; nvPair.variable.type.enumeration ¬ ; valRef: REF ROPE _ NEW[ROPE ¬ initialVarVal]; button.firstValue.variable.type.enumeration ¬ ; varValRef: REF ROPE _ NEW[ROPE ¬ varVal]; nvPair.variable.type.enumeration ¬ ; button.firstValue.variable.type.enumeration ¬ ; nvPair.variable.type.enumeration ¬ ; button.firstValue.variable.type.enumeration ¬ ; nvPair.variable.type.enumeration ¬ ; CreateRopeEnumerationButton is preferable to CreateEnumeratedButton because it does better type checking and avoids the spurious use of REF TEXT where ROPE is required. See end of this document for explanation of Enumerated type Κ6•NewlineDelimiter ™code™Kšœ Οeœ1™K˜K˜—šŸ œ˜'šžœ+žœ žœžœ™OKš œžœžœ(žœžœ™W—šŸ œ˜(Kšžœžœžœ™.Kšœžœ˜%K˜ Kšœ˜K˜—Jšœžœ˜:K˜/K˜K˜—šŸœ˜/Kšžœžœžœ™+Jšœžœ˜+K˜K˜—šŸœ˜1Kšžœ1žœžœžœ™HKšžœžœ˜ K˜K˜—šŸœ˜+Kšžœžœ˜K˜—K˜™K™TK˜—š Ÿœžœžœ žœžœ˜@Kšœžœžœ˜HK˜=J˜J˜Jšœ žœ˜Jšœ žœ˜Jšœžœ4 ˜_Jšœžœ ˜J˜—šŸ œžœžœ˜-šŸœ$˜9Kš œžœžœ(žœžœžœ™`š Ÿœžœ#žœžœžœ˜\J™Mšžœž˜"˜ Jšœžœ4žœžœžœ žœ žœ žœ˜–J˜—˜ Jš œžœ1žœžœ žœ žœ žœ˜ŽJ˜—˜ Jš œžœ7žœžœ žœ žœ žœ˜”J˜—˜ Jšœžœ3žœžœžœ žœ žœ žœ˜”J˜—˜ Jšœžœ1žœžœžœ žœ žœ žœ˜“J˜—˜J™(J™5J™*J™1J™:blockšŸœžœžœžœ˜AJšœ  ˜šžœžœžœž˜šœžœ˜J˜ šžœžœž˜Jšœžœ$˜+Jšœžœ˜Jšœžœžœ˜Jšœžœžœ˜Jšœžœžœ˜Jšžœ˜%—Jšžœ žœžœ ˜.J˜—Jšžœ˜—Jšœ ˜/J˜—J˜šœžœ˜šžœ˜J˜J˜.J˜šžœžœž˜"Jšœžœ$˜+Jšœžœ˜Jšœžœžœ˜Jšœžœžœ˜Jšœžœžœ˜Jšžœ˜&J˜—Jšœžœ žœ žœ ˜1J˜—J˜—J˜—Jšžœžœ˜—J˜J˜—J˜Jšœžœ˜ Jšœ žœ˜Jšœžœ ˜ š žœžœžœΟb œ žœžœž˜FJšœFžœ˜LJšžœ˜—J˜JšœMžœ ˜[Jšœ& ,˜RJšœ& ,˜RJ˜-JšœHžœ˜iJšœSžœ˜ZKšœ˜—J˜Jšœ žœžœ˜Jšœžœ ˜&J˜BJšžœžœ žœžœ˜0J˜—J™š Ÿœžœžœžœžœžœ˜pJ˜Jšœžœ˜:Jš œžœžœžœžœ˜-Jš œ žœJžœžœ œ˜²J˜0J˜/Kšžœ ˜J˜J˜—š Ÿœžœžœ!žœ žœ˜TJ˜Jšœžœ ˜(Jš œ žœžœžœžœ ˜)Jšœ#žœžœ œ˜J˜%Jšœžœ ˜