<> <> <> <> <> DIRECTORY Basics, Buttons, CD, CDCommandOps, CDColors, CDIO, CDSequencer, CMos, Commander, Containers, Convert, Imager, ImagerColor, ImagerColorMap, ImagerDitherContext, ImagerTerminal, InterminalBackdoor, Icons, Labels, MessageWindow, PopUpSelection, Process, Real, Rope, Sliders, Terminal, TerminalIO, UserProfile, ViewerOps, ViewerClasses, ViewerPrivate, WindowManager; CMosA8BitColors: CEDAR PROGRAM IMPORTS Basics, Buttons, CDCommandOps, CDColors, CDIO, CDSequencer, CMos, Commander, Containers, Convert, Icons, ImagerColor, ImagerColorMap, ImagerDitherContext, ImagerTerminal, InterminalBackdoor, Labels, MessageWindow, PopUpSelection, Process, Real, Rope, Sliders, Terminal, TerminalIO, UserProfile, ViewerOps, ViewerPrivate, WindowManager = BEGIN <<>> terminal: Terminal.Virtual _ InterminalBackdoor.terminal; <<>> <<--**color device**************************************>> useMapEntries: ImagerDitherContext.MapEntries _ NIL; ContextCreator: ViewerPrivate.ContextCreatorProc = BEGIN context: Imager.Context; SELECT screen FROM bw => context _ ImagerTerminal.BWContext[vt: terminal, pixelUnits: TRUE]; color => { context _ ImagerTerminal.ColorContext[vt: terminal, pixelUnits: TRUE]; IF useMapEntries#NIL THEN ImagerDitherContext.SetDitherMap[context, useMapEntries]; <<--experimenting showed that the following line was necessary....>> [] _ Terminal.SetColorCursorPresentation[terminal, onesAreWhite]; } ENDCASE => ERROR; RETURN [context] END; ForceColors: PROC [mapEntries: ImagerDitherContext.MapEntries] = BEGIN useMapEntries _ mapEntries; ImagerColorMap.LoadEntries[vt: terminal, mapEntries: mapEntries, gamma: 1, shared: FALSE]; <> <> <> [] _ Terminal.SetColorCursorPresentation[terminal, onesAreWhite]; [] _ ViewerPrivate.SetCreator[ContextCreator]; END; CallMenu: Buttons.ButtonProc = BEGIN p: CDSequencer.CommandProc _ CDSequencer.FetchCommand[$ColorDisplayMenuC, technology].proc; IF p#NIL THEN p[NIL]; END; <<--**end color device**************************************>> ColorRec: TYPE = RECORD[r, g, b, w: REAL _ 0, name: Rope.ROPE _ NIL]; <<--w is a wight; The color of an intersection (i.e. green1 over blue) is the >> <<--weighted sum of the rgb of each color.>> ColorDescRep: TYPE = ARRAY [0..numberOfColors) OF ColorRec; <<--index 0 is supposed to be background>> Exception: TYPE = RECORD [x: CARDINAL, c: ColorRec, replace: BOOL _ TRUE]; <<--XXXXXXXXXXXXXXXX TECHNOLOGY XXXXXXXXXXXXXXXX>> technology: CD.Technology _ CMos.cmos; technologyName: Rope.ROPE _ technology.name; numberOfColors: INT = 9; --background, normal colors and extra colors numberOfNormalColors: INT = 7; --without background and extra colors cDefaults: REF ColorDescRep _ NEW[ColorDescRep _ [ [0.49, 0.62, 0.62, 0.05, "Sub"], --background [0, 1, 0, 1, "pD"], [0, 1, 0, 1, "nD"], [0.5, 0.5, 1, 0.5, "m1"], [0.7, 0.4, 0.7, 0.4, "m2"], [1, 0.2, 0, 1, "pol"], [0.8, 0.8, 0.5, 0.15, "nW"], [0.60, 0.70, 0.75, 0.15, "pW"], [1, 0.95, 0.0, 0.9, "Xx"] --channel hack ]]; channelX: INT _ 8; SetupSpecials: PROC [] = BEGIN cc: ColorRec _ currentColor[8]; --channel hack x: INT _ channelX+1; specials1 _ LIST[ [x: 1+16, c: [cc.r, cc.g, -cc.b, x*cc.w-1], replace: FALSE], --yellow on transistor [x: 2+16, c: [cc.r, cc.g, -cc.b, x*cc.w-1], replace: FALSE], --yellow on transistor [x: 32+64, c: [1, 1, 1, 1], replace: TRUE], --hack white error message [x: 1+32, c: [1, 1, 1, 1], replace: TRUE], --hack white error message [x: 2+64, c: [1, 1, 1, 1], replace: TRUE], --hack white error message [x: 127, c: [0, 0, 0, 1], replace: TRUE] --black for cuts ]; specials2 _ LIST[ [x: 2, c: [1, 1, 1, 1], replace: TRUE], --pdiff without well [x: 1+2, c: [0.8, 0.8, 0.8, 1], replace: TRUE] --light grey for inverted white ]; specials3 _ LIST[ [x: 245, c: [0, 0, 1, 1]], --get all nice colors back for other users [x: 247, c: [0, 1, 0, 1]], [x: 249, c: [0, 1, 1, 1]], [x: 250, c: [1, 0, 1, 1]], [x: 251, c: [1, 1, 0, 1]], [x: 252, c: [1, 1, 1, 1]], --white as opposite to 1+2 [x: 254, c: [1, 0, 0, 1]], IF whiteOutLine THEN Exception[x: 255, c: [1, 1, 1, 1]] ELSE Exception[x: 255, c: [0, 0, 0, 1]] --all bits set ]; END; Init8Patterns: Buttons.ButtonProc = <<--all parameter are discarded >> BEGIN nDiffColor: CARDINAL = 1; pDiffColor: CARDINAL = 2; met1Color: CARDINAL = 4; met2Color: CARDINAL = 8; polyColor: CARDINAL = 16; nWellColor: CARDINAL = 32; pWellColor: CARDINAL = 64; black: CARDINAL = 127; Checker8: PROC[col1, col2: CARDINAL] RETURNS[REF CDColors.Brick] = BEGIN RETURN[NEW[CDColors.Brick _ [col1*256+col2, col2*256+col1, col1*256+col2, col2*256+col1]]] END; DefineDimmer8: PROC[lev: CD.Layer, color: CARDINAL] = BEGIN CDColors.DefineColor[lev, Checker8[color, 0], bit8, pushedOut]; END; Full8: PROC[color: CARDINAL] RETURNS [b: REF CDColors.Brick] = BEGIN RETURN[Checker8[color, color]] END; CDColors.DefineColor[CMos.ndif, Full8[nDiffColor], bit8]; CDColors.DefineColor[CMos.pdif, Full8[pDiffColor], bit8]; CDColors.DefineColor[CMos.met, Full8[met1Color], bit8]; CDColors.DefineColor[CMos.met2, Full8[met2Color], bit8]; CDColors.DefineColor[CMos.pol, Full8[polyColor], bit8]; CDColors.DefineColor[CMos.nwell, Full8[nWellColor], bit8]; CDColors.DefineColor[CMos.pwell, Full8[pWellColor], bit8]; CDColors.DefineColor[CMos.cut, Full8[black], bit8]; CDColors.DefineColor[CMos.cut2, Checker8[black, met1Color], bit8]; CDColors.DefineColor[CMos.bur, Checker8[black, 0], bit8]; CDColors.DefineColor[CMos.nwellCont, Checker8[pDiffColor, met1Color], bit8]; CDColors.DefineColor[CMos.pwellCont, Checker8[nDiffColor, met1Color], bit8]; CDColors.DefineColor[CMos.ovg, Checker8[met1Color, met2Color], bit8]; CDColors.DefineColor[CMos.imp, NEW[CDColors.Brick_[14, 14, 0, 0]], bit8]; CDColors.DefineColor[CD.backgroundLayer, NEW[CDColors.Brick _ [8, 0, 256*8, 0]], bit8]; CDColors.DefineColor[CD.errorLayer, NEW[CDColors.Brick _ [255, 0, 0, 0]], bit8]; CDColors.DefineColor[CD.shadeLayer, NEW[CDColors.Brick_[0, 255,0 , 255]], bit8]; DefineDimmer8[CMos.ndif, nDiffColor]; DefineDimmer8[CMos.pdif, pDiffColor]; DefineDimmer8[CMos.met, met1Color]; DefineDimmer8[CMos.met2, met2Color]; DefineDimmer8[CMos.pol, polyColor]; DefineDimmer8[CMos.nwell, nWellColor]; DefineDimmer8[CMos.cut, black]; DefineDimmer8[CMos.cut2, black]; <<-- no change for bur, nwelCont, pwelCont, and ovgc for this background>> END; HackContextColors: PROC [] = BEGIN SetFilter[CMos.ndif, 1]; SetFilter[CMos.pdif, 2]; SetFilter[CMos.met, 3]; SetFilter[CMos.met2, 4]; SetFilter[CMos.pol, 5]; SetFilter[CMos.nwell, 6]; SetFilter[CMos.pwell, 7]; END; <<>> <<--XXXXX end technology XXXXXXXXXXXXXXXXXXXXX>> whiteOutLine: BOOL; currentColor: REF ColorDescRep = NEW[ColorDescRep]; curLayer: INT _ 1; prevLayer: INT _ 1; -- to deselect the previous layer button <<>> CoefSlider: TYPE = RECORD [ value: Labels.Label _ NIL, select: Buttons.Button _ NIL, bar: Sliders.Slider _ NIL ]; ColorSlider: TYPE = RECORD [ value: Labels.Label _ NIL, bar: Sliders.Slider _ NIL ]; Handle: TYPE = REF AdjustColorRec; AdjustColorRec: TYPE = RECORD [ outer: Containers.Container _ NIL, coefLayer: ARRAY [0..numberOfColors) OF CoefSlider, potarColor: ARRAY [0..3) OF ColorSlider, height: CARDINAL _ 0 -- height measured from the top of the container ]; DataForSpecialProc: TYPE = REF DataForSpecialProcRec; DataForSpecialProcRec: TYPE = RECORD [ my: Handle, layer: CARDINAL ]; caption: Rope.ROPE = Rope.Concat[technologyName, " 8 bit color editor"]; ColorModeIs8: PROC [] RETURNS [BOOL] = INLINE BEGIN RETURN [terminal.hasColorDisplay AND ~terminal.GetColorMode[].full AND terminal.GetColorMode[].bitsPerPixelChannelA=8]; END; Check8BitMode: PROC [] RETURNS [ok: BOOL] = BEGIN ok _ ColorModeIs8[]; IF ~ok THEN TRUSTED{Process.Detach[FORK TerminalIO.PutRope["Put the display in 8 bit per pixel mode first\n"]]}; END; UpdateWeightSlider: Sliders.SliderProc = BEGIN datac: DataForSpecialProc _ NARROW[clientData]; my: Handle _ datac.my; layer: CARDINAL _ datac.layer; IF ~ColorModeIs8[] THEN RETURN; currentColor[layer].w _ value; ComputeColors[]; Labels.Set[my.coefLayer[layer].value, Convert.RopeFromInt[Real.Fix[value*100]]]; END; UpdateColorSlider: Sliders.SliderProc = BEGIN data: DataForSpecialProc _ NARROW[clientData]; my: Handle _ data.my; layer: CARDINAL _ data.layer; IF ~ColorModeIs8[] THEN RETURN; Labels.Set[my.potarColor[layer].value, Convert.RopeFromInt[Real.Fix[value*100]]]; SELECT layer FROM 0 => currentColor[curLayer-1].r _ value; 1 => currentColor[curLayer-1].g _ value; 2 => currentColor[curLayer-1].b _ value; ENDCASE => ERROR; ComputeColors[]; END; ResetButton: Buttons.ButtonProc = BEGIN Init8Patterns[parent: parent, clientData: clientData]; ResetMapButton[parent: parent, clientData: clientData]; END; XSelection: Buttons.ButtonProc = BEGIN whiteOutLine _ ~whiteOutLine; ComputeColors[]; END; ResetAndCreateButton: Buttons.ButtonProc = BEGIN viewer: ViewerClasses.Viewer _ ViewerOps.FindViewer[caption]; IF viewer=NIL THEN { IF mouseButton=yellow THEN CallMenu[NIL] ELSE { IF Terminal.LegalColorMode[terminal, [FALSE, 8, 0]] AND ~ColorModeIs8[] THEN { pos: WindowManager.ScreenPos _ left; IF Rope.Equal["right", UserProfile.Token[key: "ColorDisplay.Side"], FALSE] THEN pos _ right; WindowManager.StartColorViewers[screenPos: pos, bitsPerPixel: 8]; }; ResetButton[parent: parent]; IF mouseButton=blue THEN CreateAnInstance[]; } } ELSE { <<--we do only open the viewer, >> <<--because resetting can not reset already painted sliders... >> IF viewer.iconic THEN ViewerOps.OpenIcon[viewer] ELSE MessageWindow.Append["use the color editor tool", TRUE]; }; END; ResetMapButton: Buttons.ButtonProc = <<--Resets color map;>> <<--does not touch patterns>> BEGIN UpdateAllSliders: PROC [my: Handle] = BEGIN w: Sliders.NormalizedSliderValue; IF my=NIL OR my.outer=NIL OR my.outer.destroyed THEN RETURN; FOR layer: INT IN [0..numberOfColors) DO w _ currentColor[layer].w; Sliders.SetContents[my.coefLayer[layer].bar, 0]; Sliders.SetContents[my.coefLayer[layer].bar, w]; Labels.Set[my.coefLayer[layer].value, Convert.RopeFromInt[Real.Fix[currentColor[layer].w*100]]]; ENDLOOP; ButtonProcLayerInternal[0, my]; END; <<>> <<--ResetMapButton>> IF Check8BitMode[] THEN { ReadProfileColors[]; ComputeColors[]; IF clientData#NIL THEN UpdateAllSliders[NARROW[clientData, Handle]]; }; END; ButtonProcLayer: Buttons.ButtonProc = BEGIN data: DataForSpecialProc _ NARROW[clientData]; IF Check8BitMode[] THEN { ButtonProcLayerInternal[data.layer, data.my]; } END; ButtonProcLayerInternal: PROC[layer: CARDINAL, my: Handle] = BEGIN SetPotar: PROC[layer: CARDINAL, my: Handle] = BEGIN Sliders.SetContents[my.potarColor[0].bar, currentColor[layer].r]; Sliders.SetContents[my.potarColor[1].bar, currentColor[layer].g]; Sliders.SetContents[my.potarColor[2].bar, currentColor[layer].b]; Labels.Set[my.potarColor[0].value, Convert.RopeFromInt[Real.Fix[currentColor[layer].r*100]]]; Labels.Set[my.potarColor[1].value, Convert.RopeFromInt[Real.Fix[currentColor[layer].g*100]]]; Labels.Set[my.potarColor[2].value, Convert.RopeFromInt[Real.Fix[currentColor[layer].b*100]]]; END; <<>> <<-- ButtonProcLayerInternal>> curLayer _ layer+1; SetPotar[layer, my]; Buttons.SetDisplayStyle[my.coefLayer[prevLayer-1].select, $BlackOnWhite]; Buttons.SetDisplayStyle[my.coefLayer[curLayer-1].select, $WhiteOnBlack]; prevLayer _ curLayer; END; CreateAnInstance: PROC[] = <<--create an icon of the tool;>> <<--does not change any color setup at initialization of the tool>> BEGIN nameColorSlider: ARRAY [0..3) OF Rope.ROPE _ ["R", "G", "B"]; coefX: CARDINAL = 10; coefDX: CARDINAL = 25; coefDeltaX: CARDINAL = coefDX+4; coefSelectY: CARDINAL = 3; coefSelectDY: CARDINAL = 15; coefValueY: CARDINAL = coefSelectY+coefSelectDY+3; coefValueDY: CARDINAL = 15; coefBarY: CARDINAL = coefValueY+coefValueDY; firstButtonY: CARDINAL = 3; buttonX: CARDINAL = coefX+numberOfColors*coefDeltaX+8; buttonDX: CARDINAL = 80; firstSliderY: CARDINAL = 6; sliderDY: CARDINAL = 22; interSliderY: CARDINAL = 6; labelX: CARDINAL = buttonX+buttonDX+10; -- R, G, B labelDX: CARDINAL = 14; label2X: CARDINAL = labelX+labelDX; -- number label2DX: CARDINAL = 30; sliderX: CARDINAL = label2X+label2DX; my: Handle = NEW[AdjustColorRec]; buttonWy: CARDINAL _ firstButtonY; NextButton: PROC [name: Rope.ROPE, proc: Buttons.ButtonProc] = BEGIN buttonDY: CARDINAL = 15; interButtonY: CARDINAL = 2; [] _ Buttons.Create[ info: [name: name, wx: buttonX, wy: buttonWy, wh: buttonDY, ww: buttonDX, parent: my.outer, border: TRUE], proc: proc, clientData: my, fork: TRUE ]; buttonWy _ buttonWy+buttonDY+interButtonY; END; IF ~ColorModeIs8[] THEN TerminalIO.PutRope["The 8 bit color tool works only after setting the display in 8 bit mode\n"]; IF ViewerOps.FindViewer[caption]#NIL THEN { TerminalIO.PutRope[caption]; TerminalIO.PutRope[" viewer already exits\n"]; RETURN }; my.outer _ Containers.Create[[ name: caption, iconic: TRUE, icon: Icons.NewIconFromFile[CDIO.GetWorkingDirectory[NIL].Cat["Chipndale.icons"], 2], column: left, scrollable: FALSE ]]; my.height _ firstSliderY+3*(sliderDY+interSliderY); <<-- create sliders for weights>> FOR curLayer: INT IN [0..numberOfColors) DO wInit: REAL _ currentColor[curLayer].w; my.coefLayer[curLayer].select _ Buttons.Create[ info: [ name: cDefaults[curLayer].name, iconic: TRUE, wx: coefX+curLayer*coefDeltaX, wy: coefSelectY, wh: coefSelectDY, ww: coefDX, parent: my.outer, border: TRUE], proc: ButtonProcLayer, clientData: NEW[DataForSpecialProcRec _ [my: my, layer: curLayer]] ]; my.coefLayer[curLayer].value _ Labels.Create[ [ name: Convert.RopeFromInt[Real.Fix[wInit*100]], -- initial contents iconic: TRUE, wx: coefX+curLayer*coefDeltaX, wy: coefValueY, wh: coefValueDY, ww: coefDX, parent: my.outer, border: TRUE ]]; my.coefLayer[curLayer].bar _ Sliders.Create[ info: [ name: cDefaults[curLayer].name, iconic: TRUE, parent: my.outer, wx: coefX+curLayer*coefDeltaX, wy: coefBarY, wh: -5, --guardY ww: coefDX, border: TRUE], sliderProc: UpdateWeightSlider, orientation: vertical, value: wInit, clientData: NEW[DataForSpecialProcRec _ [my: my, layer: curLayer] ]]; Containers.ChildYBound[my.outer, my.coefLayer[curLayer].bar]; ENDLOOP; <<>> <<-- create command buttons>> NextButton["reset all", ResetButton]; NextButton["reset map", ResetMapButton]; NextButton["reset pattern", Init8Patterns]; NextButton["X Selection", XSelection]; NextButton["Menu", CallMenu]; <<>> <<-- create sliders for rgb colors>> FOR iColor: CARDINAL IN [0..3) DO cInit: REAL _ SELECT iColor FROM 0 => currentColor[curLayer-1].r, 1 => currentColor[curLayer-1].g, 2 => currentColor[curLayer-1].b, ENDCASE => ERROR; [] _ Labels.Create[ info: [name: nameColorSlider[iColor], parent: my.outer, wx: labelX, wy: firstSliderY+iColor*(sliderDY+interSliderY), ww: labelDX, wh: sliderDY, border: TRUE ]]; my.potarColor[iColor].bar _ Sliders.Create[ info: [parent: my.outer, wx: sliderX, wy: firstSliderY+iColor*(sliderDY+interSliderY), ww: 10, wh: sliderDY], sliderProc: UpdateColorSlider, orientation: horizontal, value: cInit, clientData: NEW[DataForSpecialProcRec _ [my: my, layer: iColor]] ]; Containers.ChildXBound[my.outer, my.potarColor[iColor].bar]; my.potarColor[iColor].value _ Labels.Create[[ name: Convert.RopeFromInt[Real.Fix[cInit*100]], -- initial contents wx: label2X, wy: firstSliderY+iColor*(sliderDY+interSliderY), ww: label2DX, wh: sliderDY, parent: my.outer, border: TRUE ]]; ENDLOOP; ViewerOps.SetOpenHeight[my.outer, my.height]; -- hint our desired height ViewerOps.PaintViewer[my.outer, all]; -- reflect above change Buttons.SetDisplayStyle[my.coefLayer[0].select, $WhiteOnBlack]; END; SaturationComm: CDSequencer.CommandProc = BEGIN sat: CARDINAL _ 1; IF Check8BitMode[] THEN { list: LIST OF Rope.ROPE _ LIST["from profile"]; FOR i: INT DECREASING IN [0..numberOfColors) DO list _ CONS[cDefaults[i].name, list] ENDLOOP; curLayer _ PopUpSelection.Request[header: "Layers", choice: list]; IF curLayer=0 THEN RETURN[]; IF curLayer<=numberOfColors THEN { sat _ PopUpSelection.Request[ header: "Values", choice: LIST["Invisible", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Saturated"] ]; IF sat = 0 THEN RETURN[]; currentColor[curLayer-1].w _ Real.Float[sat-1]/10; } ELSE ReadProfileColors[]; ComputeColors[]; }; END; specials1: LIST OF Exception _ NIL; --specials in the range of stipples [use for any comb] specials2: LIST OF Exception _ NIL; --specials in the range of stipples [use for exact comb] specials3: LIST OF Exception _ NIL; --specials to be considered later ComputeColors: PROC[] = <<--takes a color setting (weights and rgb values) and sets up the device>> BEGIN ComposeColor: PROC[c1, wc2: ColorRec] RETURNS [c: ColorRec] = <<--c1 not weighted; wc2 weighted>> INLINE BEGIN w: REAL _ wc2.w; c _ [c1.r+w*wc2.r, c1.g+w*wc2.g, c1.b+w*wc2.b, c1.w+w] END; SetMap: PROC[index: CARDINAL, color: ColorRec] = BEGIN RtoC: PROC [r: REAL] RETURNS [c: [0..256)] = INLINE { c _ MAX[MIN[Real.Round[r*255], 255], 0] }; mapEntrie: ImagerColorMap.MapEntry _ [index, RtoC[color.r], RtoC[color.g], RtoC[color.b]]; mapEntries _ CONS[mapEntrie, mapEntries]; END; mapEntries: LIST OF ImagerColorMap.MapEntry _ NIL; c: ColorRec; bits: CARDINAL _ numberOfNormalColors; power: CARDINAL _ Basics.BITSHIFT[1, bits]; IF ~ColorModeIs8[] THEN RETURN; SetupSpecials[]; <<--colors in the range of layers>> FOR i: CARDINAL IN [0..power) DO c _ [0, 0, 0, 0]; <<--bit loop>> FOR bit: CARDINAL IN [0..bits) DO IF Basics.BITAND[i, Basics.BITSHIFT[1, bit]]#0 THEN { c _ ComposeColor[c, currentColor[bit+1]]; }; ENDLOOP; <<--check exception loops>> FOR list: LIST OF Exception _ specials1, list.rest WHILE list#NIL DO IF Basics.BITAND[i, list.first.x]=list.first.x THEN { IF list.first.replace THEN c _ list.first.c ELSE c _ ComposeColor[c, list.first.c]; }; ENDLOOP; FOR list: LIST OF Exception _ specials2, list.rest WHILE list#NIL DO IF i=list.first.x THEN { IF list.first.replace THEN c _ list.first.c ELSE c _ ComposeColor[c, list.first.c]; }; ENDLOOP; <<--assign color>> IF c.w<0.2 THEN c _ ComposeColor[c, currentColor[0]]; IF c.w=0 THEN c _ currentColor[0] ELSE c _ [c.r/c.w, c.g/c.w, c.b/c.w, 0]; SetMap[i, c]; ENDLOOP; <<--include further colors from exception loop>> FOR list: LIST OF Exception _ specials3, list.rest WHILE list#NIL DO IF list.first.x>=power THEN SetMap[list.first.x, list.first.c]; ENDLOOP; ForceColors[mapEntries: mapEntries]; HackContextColors[]; END; SetFilter: PROC [layer: CD.Layer, i: INT] = { CDColors.DefineIColor[layer: layer, col: ImagerColor.ColorFromRGB[[R: currentColor[i].r, G: currentColor[i].g, B: currentColor[i].b]], display: bit8 ]; }; ReadProfileColors: PUBLIC PROC [] = BEGIN DefaultColor: PROC [def: ColorRec] RETURNS [c: ColorRec] = BEGIN r: Rope.ROPE _ Rope.Cat["ChipNDale.", technologyName, ".", def.name]; c.w _ Real.Float[UserProfile.Number[key: r.Concat[".w"], default: Real.Round[def.w*100]]]/100; c.r _ Real.Float[UserProfile.Number[key: r.Concat[".r"], default: Real.Round[def.r*100]]]/100; c.g _ Real.Float[UserProfile.Number[key: r.Concat[".g"], default: Real.Round[def.g*100]]]/100; c.b _ Real.Float[UserProfile.Number[key: r.Concat[".b"], default: Real.Round[def.b*100]]]/100; END; FOR i: INT IN [0..numberOfColors) DO currentColor[i] _ DefaultColor[cDefaults[i]]; ENDLOOP; whiteOutLine _ UserProfile.Boolean[ key: Rope.Cat["ChipNDale." , technologyName, ".WhiteOutline"], default: TRUE ]; END; ColorCommand: Commander.CommandProc = BEGIN CreateAnInstance[]; END; ColorComm: PROC [comm: CDSequencer.Command] = BEGIN CreateAnInstance[]; END; Init8Patterns[NIL]; ReadProfileColors[]; IF UserProfile.Boolean[Rope.Cat["ChipNDale.", technologyName, ".StartColorMap8"], ~Rope.Equal[technologyName, "chipnsil", FALSE]] THEN ComputeColors[]; CDSequencer.ImplementCommand[$SaturationComm, SaturationComm, technology, doQueue]; CDSequencer.ImplementCommand[$ColorTool, ColorComm, technology, dontQueue]; CDCommandOps.RegisterWithMenu[menu: $DisplayMenu, entry: Rope.Concat[technologyName, " 8 bit tool"], key: $ColorTooltech, tech: technology, queue: dontQueue]; [] _ Buttons.Create[ info: [name: Rope.Concat[technologyName, " colors"]], proc: ResetAndCreateButton ]; Commander.Register[ key: Rope.Cat["CD", technologyName, "ColorRec"], proc: ColorCommand, doc: Rope.Concat[technologyName, " 8 bit color tool"] ]; ERROR --not yet converted to cedar 7 END.