<> <> <> <> <> <<>> DIRECTORY Commander, IO, PFS, Rope, SystemNames, UnixSpawnTCP, Xl, XTk, XTkWidgets; ScannerTool: CEDAR PROGRAM IMPORTS Commander, IO, PFS, Rope, SystemNames, UnixSpawnTCP, Xl, XTk, XTkWidgets ~ BEGIN InstanceRec: TYPE = RECORD [ lock: Xl.TQ, filenameWidget: XTk.Widget ¬ NIL, log: IO.STREAM ¬ NIL, s: REF UnixSpawnTCP.SpawnData ¬ NIL, resolution: INT ¬ 300 ]; Scan: <> XTkWidgets.ButtonHitProcType = { i: REF InstanceRec ~ NARROW[registerData]; fileName: Rope.ROPE ¬ XTkWidgets.GetText[i.filenameWidget]; command: Rope.ROPE; IF i.s#NIL THEN { IO.PutRope[i.log, "\nwait..."]; RETURN; }; command ¬ IO.PutFR["/tmp/ScannerTool-scan-page -r %g %g", IO.int[i.resolution], IO.int[i.resolution]]; command ¬ Rope.Concat[command, " | /tmp/ScannerTool-rotate90 -90"]; command ¬ Rope.Cat[command, " | /tmp/ScannerTool-writeip > ", fileName, "\n"]; BEGIN --debugging IO.PutRope[i.log, "\n"]; IO.PutRope[i.log, command]; END; IO.PutRope[i.log, "\nSTART "]; i.s ¬ UnixSpawnTCP.Spawn[command: command, out: i.log, clientData: i, finish: Finish]; IF i.s = NIL THEN { IO.PutRope[i.log, "can't connect to streams"]; GOTO Oops; }; UnixSpawnTCP.Close[i.s]; EXITS Oops => {}; }; Stop: <> XTkWidgets.ButtonHitProcType = { i: REF InstanceRec ~ NARROW[registerData]; s: REF UnixSpawnTCP.SpawnData ¬ i.s; IF s#NIL THEN { UnixSpawnTCP.Kill[s]; IO.PutRope[i.log, "\nSTOPPED"]; i.s ¬ NIL; } ELSE { IO.PutRope[i.log, "\nnothing to stop..."]; }; }; Finish: UnixSpawnTCP.FinishProc = { i: REF InstanceRec ~ NARROW[clientData]; Protected: PROC = { IO.PutRope[i.log, " END "]; i.s ¬ NIL; }; Xl.CallWithLock[i.lock, Protected]; }; ResolutionHit: XTkWidgets.ButtonHitProcType = { i: REF InstanceRec ~ NARROW[registerData]; i.resolution ¬ NARROW[callData, REF INT]­; }; X11ScannerWidgetCommand: Commander.CommandProc ~ { Ruler: PROC [w, h: INT ¬ -1] RETURNS [ruler: XTk.Widget] = { RETURN [ XTkWidgets.CreateRuler[widgetSpec: [geometry: [size: [w, h]]]] ]; }; lock: Xl.TQ ¬ Xl.CreateTQ[]; i: REF InstanceRec ¬ NEW[InstanceRec ¬ [lock: lock]]; resolutionWidget: XTk.Widget ~ XTkWidgets.CreateChoices[ choices: LIST [ ["300", NEW[INT ¬ 300]], ["200", NEW[INT ¬ 200]], ["150", NEW[INT ¬ 150]], ["100", NEW[INT ¬ 100]], ["75", NEW[INT ¬ 75]] ], hitProc: ResolutionHit, registerData: i ]; label: XTk.Widget ~ XTkWidgets.CreateLabel[[], " resolution:"]; doitWidget: XTk.Widget ~ XTkWidgets.CreateButton[[], "DOIT", [], Scan, i, i, lock]; killWidget: XTk.Widget ~ XTkWidgets.CreateButton[[], "STOP ", [], Stop, i, i, lock]; topControlsContainer: XTk.Widget ~ XTkWidgets.CreateXStack[[], LIST[doitWidget, killWidget, label, resolutionWidget]]; filenameWidget: XTk.Widget ¬ i.filenameWidget ¬ XTkWidgets.CreateLabeledField[label: "filename>", init: "/tmp/slate.ip"]; logWidget: XTk.Widget ~ XTkWidgets.CreateStreamWidget[widgetSpec: [geometry: XTk.G[-1, 50]]]; yContainer: XTk.Widget ~ XTkWidgets.CreateYStack[[], LIST[topControlsContainer, filenameWidget, Ruler[h: 1], logWidget]]; shell: XTkWidgets.Widget ¬ XTkWidgets.CreateShell[child: yContainer, windowHeader: Rope.Concat["Scanner on ", SystemNames.MachineName[]], standardMigration: TRUE]; i.log ¬ XTkWidgets.CreateStream[logWidget]; XTkWidgets.RealizeShell[shell]; }; MakeLocalCopies: PROC[] = { Copy: PROC [from, to: Rope.ROPE] = { Confirm: PFS.NameConfirmProc = {RETURN [TRUE]}; PFS.Copy[from: PFS.PathFromRope[from], to: PFS.PathFromRope[to], confirmProc: Confirm]; }; <> <> <> <> <> Copy["/Cedar/ScannerTool/sun4/scan-page", "/tmp/ScannerTool-scan-page"]; Copy["/Cedar/ScannerTool/sun4/writeip", "/tmp/ScannerTool-writeip"]; Copy["/Cedar/ScannerTool/sun4/rotate90", "/tmp/ScannerTool-rotate90"]; }; MakeLocalCopies[]; Commander.Register["ScannerTool", X11ScannerWidgetCommand, "Create a scanner widget"]; END.