DIRECTORY Args, Buttons, CedarProcess, Commander, CommanderOps, Containers, Controls, CtBasic, CtDispatch, CtFile, CtMap, FileNames, FS, Imager, IO, MessageWindow, Process, Real, Rope, SF, ViewerClasses, ViewerOps; CtPicturesCommandImpl: CEDAR PROGRAM IMPORTS Args, Buttons, CedarProcess, CommanderOps, Containers, Controls, CtBasic, CtDispatch, CtFile, CtMap, FileNames, FS, IO, MessageWindow, Process, Real, Rope, ViewerOps ~ BEGIN ButtonProc: TYPE ~ Buttons.ButtonProc; SampleMap: TYPE ~ CtBasic.SampleMap; SampleMaps: TYPE ~ CtBasic.SampleMaps; RGB: TYPE ~ CtBasic.RGB; CtProc: TYPE ~ CtDispatch.CtProc; Cmap: TYPE ~ CtMap.Cmap; Color: TYPE ~ Imager.Color; ConstantColor: TYPE ~ Imager.ConstantColor; STREAM: TYPE ~ IO.STREAM; ROPE: TYPE ~ Rope.ROPE; Viewer: TYPE ~ ViewerClasses.Viewer; ViewerClassRec: TYPE ~ ViewerClasses.ViewerClassRec; Gallery: TYPE ~ RECORD [aisName, cmap: ROPE ¬ NIL]; GalleryData: TYPE ~ RECORD [ cmd: Commander.Handle ¬ NIL, ctView: CtProc ¬ NIL, image: Viewer ¬ NIL, wDir: ROPE ¬ NIL, parent: Viewer ¬ NIL, maps: SampleMaps, cmap: Cmap ¬ NIL, placementButton: Buttons.Button ¬ NIL, placement: {perAIS, none, center} ¬ perAIS, clearInBetweenButton: Buttons.Button ¬ NIL, clearInBetween: BOOL ¬ FALSE, filenames, currentName: LIST OF Gallery ¬ NIL ]; ctGalleryUsage: ROPE ~ "Ct Gallery {pattern and/or list of ]}."; CtGallery: CtProc ~ { FirstChar: PROC [rope: ROPE, char: CHAR] RETURNS [BOOL] ~ { RETURN[rope.Length[] > 0 AND Rope.Fetch[rope, 0] = char]; }; LastChar: PROC [rope: ROPE, char: CHAR] RETURNS [BOOL] ~ { ropeLength: INT ¬ Rope.Length[rope]; RETURN[ropeLength > 0 AND Rope.Fetch[rope, ropeLength-1] = char]; }; RopeShorten: PROC [rope: ROPE, n: INT] RETURNS [ROPE] ~ { ropeLength: INT ¬ Rope.Length[rope]; IF ropeLength >= n THEN rope ¬ Rope.Substr[rope, 0, ropeLength-n]; RETURN[rope]; }; i: NAT ¬ 1; args: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; g: REF GalleryData ¬ NEW[GalleryData ¬ [cmd: cmd, image: viewer, maps: maps, wDir: wDir]]; affect ¬ [[0, 0], [0, 0]]; WHILE i < args.argc DO IF NOT FirstChar[args[i], '-] THEN { EachName: PROC [fullFName: ROPE] RETURNS [continue: BOOL ¬ TRUE] ~ { Process.CheckForAbort[]; IF CtFile.Parse[fullFName].type = bad THEN IO.PutF1[cmd.out, "Bad argument: %g\n", IO.rope[args[i]]] ELSE g.filenames ¬ CONS[[fullFName], g.filenames]; }; name: ROPE ¬ FS.ExpandName[FileNames.ResolveRelativePath[args[i]]].fullFName; IF Rope.Find[name, "*"] = -1 THEN [] ¬ EachName[name] ELSE FS.EnumerateForNames[name, EachName ! FS.Error => CONTINUE]; } ELSE IF Rope.Equal[args[i], "-cmap", FALSE] AND g.filenames # NIL THEN g.filenames.first.cmap ¬ FileNames.ResolveRelativePath[args[i ¬ i+1]]; i ¬ i+1; ENDLOOP; IF g.filenames = NIL THEN IO.PutRope[cmd.out, "No such files"] ELSE TRUSTED {Process.Detach[FORK MakeGalleryViewer[g]]}; }; MakeGalleryViewer: PROC [g: REF GalleryData] ~ { Reverse: PROC [list: LIST OF Gallery] RETURNS [reverse: LIST OF Gallery] ~ { FOR l: LIST OF Gallery ¬ list, l.rest WHILE l # NIL DO reverse ¬ CONS[l.first, reverse]; ENDLOOP; }; g.filenames ¬ Reverse[g.filenames]; g.parent ¬ Containers.Create[info: [name: "Ct Gallery", openHeight: 73, iconic: TRUE, column: right, scrollable: FALSE], paint: FALSE]; g.cmap ¬ CtMap.Read[]; g.currentName ¬ g.filenames; [] ¬ Buttons.Create[info: [parent: g.parent, name: "\t\t\t\t\t\t\tNEXT PICTURE", wx: 5, wy: 5, ww: 273, wh: 50], proc: Next, clientData: g, paint: TRUE]; g.clearInBetweenButton ¬ Buttons.Create[ info: [parent: g.parent, name: "Clear In Between: Off", wx: 283, wy: 40], proc: ClearInBetween, clientData: g, paint: TRUE]; g.placementButton ¬ Buttons.Create[ info: [parent: g.parent, name: "Placement: Per AIS", wx: 283, wy: 20], proc: PlacementButton, clientData: g, paint: TRUE]; ViewerOps.OpenIcon[g.parent]; g.ctView ¬ CtDispatch.GetCtOp["View"].proc; }; Next: ButtonProc ~ { Blink: PROC [rope: ROPE] ~ { MessageWindow.Append[Rope.Concat["\t\t", rope], TRUE]; MessageWindow.Blink[]; }; g: REF GalleryData ¬ NARROW[clientData]; err: ROPE; IF g.currentName = NIL THEN RETURN; IF g.clearInBetween THEN CtBasic.FillMaps[g.maps]; g.cmd.commandLine ¬ Rope.Cat[g.currentName.first.aisName, " ", SELECT g.placement FROM none => "-noPlace\n", center => "-center\n", ENDCASE => "\n"]; MessageWindow.Append[g.currentName.first.aisName, TRUE]; IF g.currentName = g.filenames THEN MessageWindow.Append[" (. . . first)"]; IF g.currentName.first.cmap = NIL THEN CtMap.Write[g.cmap] ELSE IF NOT CtMap.Load[g.currentName.first.cmap] THEN Blink["Bad color map"]; IF (err ¬ g.ctView[g.image, g.maps, NIL, g.cmd, g.wDir].error) # NIL THEN Blink[err]; IF (g.currentName ¬ g.currentName.rest) = NIL THEN { g.currentName ¬ g.filenames; MessageWindow.Append[" (. . . last)"]; }; }; PlacementButton: ButtonProc ~ { g: REF GalleryData ¬ NARROW[clientData]; new: ROPE ¬ Rope.Concat["Placement: ", SELECT g.placement FROM perAIS => "None", center => "Per AIS", ENDCASE => "Center"]; g.placement ¬ SELECT g.placement FROM perAIS=> none, center=> perAIS, ENDCASE=> center; Buttons.ReLabel[g.placementButton, new]; }; ClearInBetween: ButtonProc ~ { g: REF GalleryData ¬ NARROW[clientData]; new: ROPE ¬ Rope.Concat["Clear In Between: ", IF g.clearInBetween THEN "Off" ELSE "On"]; g.clearInBetween ¬ NOT g.clearInBetween; Buttons.ReLabel[g.clearInBetweenButton, new]; }; MovieData: TYPE ~ REF MovieDataRec; MovieDataRec: TYPE ~ MONITORED RECORD [ cmd: Commander.Handle ¬ NIL, x, y, w, h, nFrames: INTEGER ¬ 0, nRows, nCols: INTEGER ¬ 0, speed, frame: Controls.Control ¬ NIL, outer: Controls.Viewer ¬ NIL, outerData: Controls.OuterData ¬ NIL, maps, frames, save: SampleMaps, now: REAL ¬ 0.0, old, new: INTEGER ¬ 0, pause, pauseSave: BOOL ¬ FALSE, bounce: BOOL ¬ TRUE, forward, forwardSave: BOOL ¬ TRUE ]; ctMovieUsage: ROPE ~ "Ct Movie [-name ] [-clear]."; CtMovie: CtProc ~ { x, y, w, h, nCols, nRows, clear, name: Args.Arg; [x, y, w, h, nCols, nRows, clear, name] ¬ Args.ArgsGet[cmd, "%iiiiii-clear%b-name%s" ! Args.Error => {error ¬ reason; CONTINUE}]; affect ¬ [[0, 0], [0, 0]]; IF error # NIL THEN RETURN ELSE { m: MovieData ¬ NEW[MovieDataRec ¬ [ cmd: cmd, maps: maps, x: x.int, y: y.int, w: w.int, h: h.int, nCols: nCols.int, nRows: nRows.int, nFrames: nCols.int*nRows.int]]; min: SF.Vec ¬ [m.y+m.h*(m.nRows-1)/2, m.x+m.w*(m.nCols-1)/2]; m.save ¬ CtBasic.CopyOfMaps[maps, min.f, min.s, m.w, m.h]; IF name.ok THEN { m.frames ¬ CtFile.ReadFile[name.rope]; IF m.frames.bpp = 0 THEN RETURN[error: "can't open named file."]; } ELSE m.frames ¬ CtBasic.CopyOfMaps[maps, maps.x, maps.y, maps.w, maps.h]; IF m.frames.bpp=0 OR m.frames.w=0 OR m.frames.h=0 THEN RETURN[error: "no image"]; IF clear.ok AND clear.bool THEN CtBasic.FillMaps[maps]; TRUSTED {Process.Detach[FORK MakeMovieViewer[m]]}; }; }; MakeMovieViewer: PROC [m: MovieData] ~ { m.outerData ¬ Controls.OuterViewer[ clientData: m, column: right, name: "Ct Movie", destroyProc: MovieDestroy, controls: LIST[ m.speed ¬ Controls.NewControl["Speed", hSlider, m,, 5.0, 0.1,,,,,,,,,,,, exp], m.frame ¬ Controls.NewControl["Frame", hSlider, m, 0, m.nFrames-1,0, Frame,, 0]], buttons: LIST [ Controls.ClickButton["Forward", Forward, m], Controls.ClickButton["Bounce-On", Bounce, m], Controls.ClickButton["Pause", Pause, m]] ]; [] ¬ CedarProcess.Fork[Movie, m, [background, TRUE]]; }; MovieDestroy: Controls.DestroyProc ~ {NARROW[clientData, MovieData].pause ¬ FALSE}; ShowNFrame: PROC [m: MovieData] ~ { SetNFrame[m]; IF m.new # m.old THEN { min: SF.Vec ¬ [m.y+(m.new/m.nCols)*m.h, (m.new MOD m.nCols)*m.w]; CtBasic.CopyClippedMaps[m.frames, m.maps, [min, [min.s+m.h, min.f+m.w]], m.save.box]; m.old ¬ m.new; IF NOT m.pause THEN Controls.SetSliderDialValue[m.frame, m.new]; }; }; PrintBox: PROC [out: IO.STREAM, name: Rope.ROPE, box: SF.Box] ~ { IO.PutFL[out, "%g: [%g, %g] to [%g, %g]\n", LIST[IO.rope[name], IO.int[box.min.s], IO.int[box.min.f], IO.int[box.max.s], IO.int[box.max.f]]]; }; SetNFrame: PROC [m: MovieData] ~ { IF (m.new ¬ Real.Round[m.now]) IN [0..m.nFrames) THEN RETURN; IF m.bounce THEN { m.forward ¬ NOT m.forward; m.new ¬ IF m.new < 0 THEN 0 ELSE m.nFrames-1; } ELSE { IF m.new >= m.nFrames THEN m.now ¬ m.new ¬ 0; IF m.new < 0 THEN m.now ¬ m.new ¬ m.nFrames-1; }; }; Movie: CedarProcess.ForkableProc ~ { m: MovieData ¬ NARROW[data]; WHILE NOT m.outerData.destroyed DO IF m.pause THEN {Process.Pause[Process.MsecToTicks[150]]; LOOP}; m.now ¬ m.now+(IF m.forward THEN m.speed.value ELSE -m.speed.value); ShowNFrame[m]; ENDLOOP; CtBasic.CopyMaps[m.save, m.maps]; }; Frame: Controls.ControlProc ~ { m: MovieData ~ NARROW[control.clientData]; IF control.mouse.state = down AND NOT m.pause THEN { m.pauseSave ¬ FALSE; m.pause ¬ TRUE; PauseStyle[m]; }; m.now ¬ control.value; ShowNFrame[m]; IF control.mouse.state = up AND NOT m.pauseSave THEN { m.pause ¬ FALSE; PauseStyle[m]; }; }; Pause: Controls.ClickProc ~ { m: MovieData ~ NARROW[clientData]; m.pause ¬ m.pauseSave ¬ NOT m.pause; PauseStyle[m]; }; PauseStyle: PROC [m: MovieData] ~ { Controls.ButtonStyle[ m.outerData, "Pause", IF m.pause THEN $WhiteOnBlack ELSE $BlackOnWhite]; }; Bounce: Controls.ClickProc ~ { m: MovieData ~ NARROW[clientData]; Controls.ButtonToggle[m.outerData, m.bounce ¬ NOT m.bounce, "Bounce-On", "Bounce-Off"]; IF m.bounce THEN m.forwardSave ¬ m.forward ELSE m.forward ¬ m.forwardSave; }; Forward: Controls.ClickProc ~ { m: MovieData ~ NARROW[clientData]; m.forward ¬ m.forwardSave ¬ NOT m.forward; Controls.ButtonToggle[m.outerData, m.forward, "Forward", "Reverse"]; }; CtDispatch.RegisterCtOp["Movie and Gallery:", NIL, NIL]; CtDispatch.RegisterCtOp["Gallery", CtGallery, ctGalleryUsage]; CtDispatch.RegisterCtOp["Movie", CtMovie, ctMovieUsage]; END. θ CtPicturesCommandImpl.mesa Copyright Σ 1985, 1992 by Xerox Corporation. All rights reserved. Bloomenthal, December 10, 1992 11:39 pm PST Heckbert, June 23, 1988 8:42:17 pm PDT Types Gallery Command Movie Command Start Code Κ •NewlineDelimiter –"cedarcode" style™™Jšœ Οeœ6™BJ™+Jšœ#Οk™&—J˜Jšž œΝ˜ΦJ˜šΠlnœžœž˜$Jšžœ¦˜­—J˜Jšœž˜headšΟl™Jšœ žœ˜'Jšœ žœ˜%Jšœ žœ˜'Jšžœžœ žœ˜Jšœ žœ˜#Jšœ žœ˜Jšœ žœ˜Jšœžœ˜+Jšžœžœžœžœ˜Jšžœžœžœ˜Jšœ žœ˜&Jšœžœ ˜4—š ™š œ žœžœžœžœ˜6J˜—šœžœžœ˜Jšœžœ˜"Jšœžœ˜Jšœžœ˜Jšœ žœžœ˜Jšœžœ˜J˜Jšœžœ˜Jšœ$žœ˜(J˜/Jšœ(žœ˜,Jšœžœžœ˜ Jšœžœžœ ž˜-J˜J˜—šœžœC˜WJ˜—šΠbn œ ˜š Οn œžœžœžœžœžœ˜;Jšžœžœ˜9J˜—š ’œžœžœžœžœžœ˜:Jšœ žœ˜$Jšžœžœ(˜AJ˜—š ‘ œžœžœžœžœžœ˜9Jšœ žœ˜$Jšžœžœ+˜BJšžœ˜ J˜—Jšœžœ˜ J˜Jšžœžœ˜2—J˜—Jšœžœžœ>˜Mšžœ˜Jšžœ˜Jšžœžœ$žœ žœ˜A—J˜—š žœžœžœžœž˜AJšžœG˜K——J˜Jšžœ˜—šžœž˜Jšžœžœ"˜)Jšžœžœžœ˜9—J˜J˜—š’œžœžœ˜0š’œžœžœžœ žœ žœžœ ˜Lš žœžœžœžœžœž˜6Jšœ žœ˜!Jšžœ˜—J˜—J˜#šœPžœ˜UJšœžœ žœ˜1—J˜J˜Jšœ£œ£œ £œ£œ£œ£œ£œ£œ£œ£œ£œ£œ'žœ˜™˜(J˜IJšœ,žœ˜2—˜#J˜FJšœ-žœ˜3—J˜J˜+J˜J˜—š’œ˜š’œžœžœ˜Jšœ0žœ˜6J˜J˜—Jšœžœžœ ˜(Jšœžœ˜ Jšžœžœžœžœ˜#Jšžœžœ˜2˜>Jš ž£œ £ž£œ£œ£œ%žœ ˜V—Jšœ2žœ˜8Jšžœžœ*˜Mšžœž˜!Jšžœ˜Jšžœžœžœ&žœ˜M—Jšžœ£œ£œ£œ£žœ£œ£œ£ž£ž£œ ˜Ušžœ(žœžœ˜4J˜J˜(J˜—J˜J˜—š‘œ˜Jšœžœžœ ˜(šœžœžœ ž˜>Jšœ'žœ˜<—Jšœ £œ£ž£œ £ž£œ£œ£œ£œ£žœ£œ˜WJ˜(J˜J˜—š‘œ˜Jšœžœžœ ˜(Jš œžœ%žœžœžœ˜XJšœžœ˜(J˜-J˜——š  ™ Jšœ žœžœ˜$šœžœž œžœ˜'Jšœžœ˜"Jšœžœ˜"Jšœžœ˜Jšœ%žœ˜)Jšœžœ˜#Jšœ$žœ˜(J˜!Jšœ žœ˜Jšœžœ˜Jšœžœžœ˜!Jšœ žœžœ˜Jšœžœž˜"J˜J˜—šœžœA˜SJ˜—š‘œ ˜J˜0˜VJšœžœ˜*—J˜šžœ ž˜Jšžœž˜ šžœ˜šœžœ˜#Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜J˜#Jšœ˜—Jšœžœ£œ˜=Jšœ!£œ £œ£œ˜:šžœ˜ šžœ˜J˜&Jšžœžœžœ"˜AJ˜—JšžœE˜I—Jšž£œ£ž£œ £ž£œ £ž£žœ£œ£œ˜QJšžœ žœ žœ˜7Jšžœžœ˜2J˜—J˜J˜——š’œžœ˜(˜#J˜J˜J˜J˜šœ žœ˜J˜NJ˜Q—šœ žœ˜J˜,J˜-J˜(—J˜—Jšœ.žœ˜5J˜J˜—š’ œžœ žœ˜SJ˜—š’ œžœ˜#J˜ šžœžœ˜Jšœžœ(žœ˜AJšœU˜UJ˜Jšžœžœ žœ-˜@J˜—J˜J˜—š ’œžœžœžœ žœžœ ˜AJšžœ*žœžœ žœžœžœžœ˜J˜J˜—š’ œžœ˜"Jšžœžœžœžœ˜=šžœ ˜ šžœ˜Jšœ žœ ˜Jšœžœ žœžœ ˜-J˜—šžœ˜Jšžœžœ˜-Jšžœ žœ˜.J˜——J˜J˜—š’œ˜$Jšœžœ˜šžœžœž˜"Jšžœ žœ+žœ˜@Jšœžœ žœžœ˜DJ˜Jšžœ˜—J˜!J˜J˜—š’œ˜Jšœžœ˜*šžœžœžœ žœ˜4Jšœžœ˜Jšœ žœ˜J˜J˜—J˜J˜šžœžœžœ žœ˜6Jšœ žœ˜J˜J˜—J˜J˜—š‘œ˜Jšœžœ ˜"Jšœžœ ˜$J˜J˜J˜—š’ œžœ˜#˜Jšœžœ žœžœ˜H—J˜J˜—š‘œ˜Jšœžœ ˜"Jšœ.žœ&˜WJšžœ žœžœ˜JJ˜J˜—š‘œ˜Jšœžœ ˜"Jšœžœ ˜*J˜DJ˜——š  ™ Jšœ.žœžœ˜:J˜AJ˜=J˜—Jšžœ˜J˜J˜J˜—…—&z3f