DIRECTORY Feedback, FileNames, FS, GGBasicTypes, GGControlPanelTypes, GGFileIn, GGFileOps, GGInterfaceTypes, GGModelTypes, GGScene, GGState, GGUserInput, GGWindow, GList, IO, Match, MatchGrep, MatchViewer, Rope, ViewerOps; MatchGrepImpl: CEDAR PROGRAM IMPORTS Feedback, FileNames, FS, GGFileIn, GGFileOps, GGScene, GGState, GGWindow, GList, IO, Match, MatchViewer, Rope, ViewerOps EXPORTS GGInterfaceTypes, MatchGrep = BEGIN ControlsObj: PUBLIC TYPE = GGControlPanelTypes.ControlsObj; GGData: TYPE = GGInterfaceTypes.GGData; Point: TYPE = GGBasicTypes.Point; Scene: TYPE = GGModelTypes.Scene; fileList: LIST OF Rope.ROPE _ NIL; lastSpawned: GGData _ NIL; Grep: PUBLIC GGUserInput.UserInputProc = { GrepIt[ggData, event, FALSE]; }; GrepListOnly: PUBLIC GGUserInput.UserInputProc = { GrepIt[ggData, event, TRUE]; }; GrepIt: PROC [ggData: GGData, event: LIST OF REF ANY, listOnly: BOOL _ FALSE] = { FillFileList: FS.NameProc = { fileList _ CONS[fullFName, fileList]; RETURN[TRUE];}; matchData: MatchViewer.MatchData _ MatchViewer.GetMatchData[]; grepData: GGData _ MatchViewer.GetGrepData[]; patRope: Rope.ROPE _ NARROW[event.rest.first]; patStream: IO.STREAM _ IO.RIS[patRope]; IF IO.SkipWhitespace[patStream]=Rope.Length[patRope] THEN MatchViewer.ErrorFeedback["Must select a filename pattern"] ELSE { fileList _ NIL; -- clear out global file list UNTIL IO.EndOf[patStream] DO nextPat: Rope.ROPE _ IO.GetTokenRope[patStream, IO.IDProc].token; thisPat: Rope.ROPE _ FileNames.ResolveRelativePath[nextPat]; FS.EnumerateForNames[thisPat, FillFileList, grepData.currentWDir ! FS.Error => { msg: Rope.ROPE _ IO.PutFR["Invalid filename pattern: %g", IO.rope[thisPat]]; MatchViewer.ErrorFeedback[msg]; GOTO Abort; };]; ENDLOOP; IF fileList = NIL THEN MatchViewer.ErrorFeedback["No files match the pattern"] ELSE { aMatch: BOOL _ FALSE; fileList _ NARROW[GList.DReverse[fileList]]; -- back in order of enumeration FOR files: LIST OF Rope.ROPE _ fileList, files.rest UNTIL files = NIL DO fileList _ files.rest; IF GrepFile[files.first, TRUE] THEN { aMatch _ TRUE; IF listOnly THEN IO.PutF[matchData.commander.out, "\n%g matched.", IO.rope[files.first]] ELSE { SpawnViewer[grepData, files.first]; RETURN; -- Expects user to invoke NextFile for more files }; }; ENDLOOP; MatchViewer.ErrorFeedback[IF aMatch THEN "No more matches." ELSE "No matches."]; IF listOnly THEN IO.PutRope[matchData.commander.out, "\n"]; }; }; EXITS Abort => Feedback.Blink[MatchViewer.GetToData[].router, $Error]; }; GrepFile: PROC [fullFName: Rope.ROPE, verbose: BOOL _ TRUE] RETURNS [found: BOOL _ FALSE] = { grepData: GGData _ MatchViewer.GetGrepData[]; fullName: Rope.ROPE; success, versionSpecified: BOOL _ FALSE; [fullName, success, versionSpecified] _ GGFileOps.GetGargoyleFileName["GrepFile", fullFName, NIL, grepData.router, FALSE]; IF NOT success THEN { mesg: Rope.ROPE _ IO.PutFR["Couldn't load %g.\n", IO.rope[fullName]]; IF verbose THEN MatchViewer.ErrorFeedback[mesg]; RETURN[FALSE]; } ELSE { matchData: MatchViewer.MatchData _ MatchViewer.GetMatchData[]; f: FS.STREAM; IF verbose THEN Feedback.PutF[grepData.router, oneLiner, $Feedback, "Finding %g.", IO.rope[fullName]]; f _ FS.StreamOpen[fullName, $read ! FS.Error, IO.Error => { msgRope: Rope.ROPE _ IO.PutFR["Could not find: %g", [rope[fullName]]]; Feedback.Append[grepData.router, oneLiner, $Error, msgRope]; GOTO Abort; };]; grepData.scene _ GGScene.CreateScene[]; -- give GGData a new clean slate/scene [] _ GGFileIn.FileinSceneOnly[f, grepData.scene, FALSE, grepData.camera]; f.Close[]; IF verbose THEN Feedback.PutF[grepData.router, begin, $Feedback, "Searching %g ... ", IO.rope[fullName]]; matchData.theirData _ NIL; -- force a reset of search lists success _ Match.Search[grepData, LIST[$MatchSearch, $SearchFromTop], FALSE]; IF verbose THEN Feedback.PutF[grepData.router, end, $Feedback, IF success THEN "It matched!!!" ELSE "No match"]; RETURN[success]; }; EXITS Abort => { Feedback.Blink[MatchViewer.GetToData[].router, $Error]; RETURN[FALSE]; }; }; NextFile: PUBLIC GGUserInput.UserInputProc = { grepData: GGData _ MatchViewer.GetGrepData[]; IF fileList = NIL THEN MatchViewer.ErrorFeedback["No more file matches."] ELSE { FOR files: LIST OF Rope.ROPE _ fileList, files.rest UNTIL files = NIL DO fileList _ files.rest; IF GrepFile[files.first, TRUE] THEN { SpawnViewer[grepData, files.first]; RETURN; }; ENDLOOP; MatchViewer.ErrorFeedback["No more file matches."]; }; }; SpawnViewer: PROC [ggData: GGData, fileName: Rope.ROPE] = { f: FS.STREAM _ FS.StreamOpen[fileName, $read ! FS.Error, IO.Error => { msgRope: Rope.ROPE _ IO.PutFR["Could not find: %g", [rope[fileName]]]; Feedback.Append[ggData.router, oneLiner, $Error, msgRope]; GOTO Abort; };]; IF lastSpawned = NIL OR lastSpawned.controls.topper.destroyed OR lastSpawned.controls.topper.newVersion THEN { -- we create a gargoyle viewer lastSpawned _ GGWindow.CreateWindow[ggData.scene, TRUE, FALSE, ggData.currentWDir]; [] _ GGFileIn.FileinOptionsOnly[f, lastSpawned, FALSE]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, ggData: lastSpawned, remake: triggerBag, edited: FALSE, okToSkipCapture: FALSE]; ViewerOps.OpenIcon[lastSpawned.controls.topper]; MatchViewer.CenterSel[NIL, lastSpawned]; -- this may not happen, since OpenIcon is async. } ELSE { -- we use the old unedited viewer lastSpawned.scene _ ggData.scene; [] _ GGFileIn.FileinOptionsOnly[f, lastSpawned, FALSE]; MatchViewer.CenterSel[NIL, lastSpawned]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, ggData: lastSpawned, remake: triggerBag, edited: FALSE, okToSkipCapture: FALSE]; }; lastSpawned.controls.topper.file _ FileNames.StripVersionNumber[fileName]; lastSpawned.controls.topper.label _ FileNames.GetShortName[path: fileName]; lastSpawned.controls.topper.name _ fileName; GGState.ChangeIcon[lastSpawned, $clean]; -- will also repaint the label EXITS Abort => ERROR; -- we've already opened fileName prior to this, so something's screwy }; END. :MatchGrep.mesa Contents: Implements the file searching routines of the MatchTool. Copyright Σ 1987 by Xerox Corporation. All rights reserved. Kurlander, September 6, 1987 5:18:03 pm PDT Pier, September 25, 1989 5:21:29 pm PDT Bier, April 8, 1991 10:34 pm PDT Spreitze, May 7, 1990 12:01 pm PDT The interactive grep (compared to GrepListOnly). Invokes a gargoyle viewer on the matched scene file. Greps for graphical matches, only printing out their names in the invoker commander when there's a hit. Returns true if there is a match between the MatchTool From viewer and the gargoyle scene file described by fullFName. Now do search Creates a gargoyle viewer, stuffs the scene from ggData into that Gargoyle viewer, and loads the various scene state info (from fileName) Now change the viewer file, label, and name Κy˜Icode™šΟnœ:™BK™˜>K˜-Kšœžœžœ˜.Kš œ žœžœžœžœ ˜'Kšžœžœ0žœ<˜ušžœ˜Kšœ žœΟc˜-šžœžœžœ˜Kšœžœžœžœ˜AKšœžœ*˜<šžœAžœ ˜PKšœ žœžœ'žœ˜LKšœ˜Kšžœ˜ Kšœ˜—Kšžœ˜—Kšžœ žœžœ8˜Nšžœ˜Kšœžœžœ˜Kšœ žœŸ˜Lš žœžœžœžœžœ žœž˜HKšœ˜šžœžœžœ˜%Kšœ žœ˜Kšžœ žœžœ0žœ˜Xšžœ˜Kšœ#˜#KšžœŸ1˜9K˜—K˜—Kšžœ˜—Kšœžœžœžœ˜PKšžœ žœžœ(˜;K˜—K˜—šž˜Kšœ@˜@—K˜K˜—šœžœžœ žœžœžœ ž œ˜]K™vK˜-Kšœžœ˜Kšœž ˜(Kšœ]žœžœ˜zšžœžœ žœ˜Kšœ žœžœžœ˜EKšžœ žœ!˜0Kšžœžœ˜K˜—šžœ˜Kšœ>˜>Kšœžœžœ˜ Kšžœ žœDžœ˜fšœžœžœžœ ˜;Kšœžœžœ/˜FKšœ<˜