[Oberon] Finding an object by name

Felix Friedrich friedrich at gsf.de
Fri Aug 20 10:53:16 CEST 2004


Hi Edgar,
I had a similar problem some time ago, which I treated with a more or 
less (well, more more) dirty solution. I remember that I have thought 
about it quite a long time and did not find a better solution than using 
the Documents.HistoryHook. As far as I remember, there is no way to 
(portably) traverse all viewers/frames in the display space (without 
using Display.Broadcast which in your case does not make sense).
Anyway, you will have a problem with uniqueness of what you are 
searching in the global space, but if you can guarantee only one 
instance of your object and a unique name ...
I needed identification of a frame by a name (even closed frames). 
You'll have to check if the frame is still alive, you can do it with the 
procedure Alive (using an artificial temporary handler .. dirty dirty) 
down below.
Note that the code is of course not thread safe, maybe one could adjust 
it to be with objects.
The code does probably not compile, I have just put it together from 
some pieces, you'll have to adapt it to your problem.

The procedures Traverse and Test do NOT solve the problem, "Test" only 
finds the context's Viewer Track, that is you cannot traverse the whole 
display space, I added it to make the problem more transparent: The 
Viewers Tracks are not accessible from outside Viewers.Mod, that's  why 
you'll probably have to use the Documents.historyHook approach.

Felix.


MODULE Test;

IMPORT Types, Objects, Display,Gadgets,  Out, aM:= antsMessages;

TYPE
	hist = POINTER TO histDesc;
	histDesc = RECORD
		D: Documents.Document;
		next: hist;
		name: ARRAY 128 OF CHAR
	END;
	
VAR
	oldhh: PROCEDURE (VAR D: Documents.Document);
	dhist: hist;
	history: hist; (* for ReplaceDoc *)
	foundFrame: BOOLEAN;

PROCEDURE Traverse(obj: Objects.Object);
VAR this: Objects.Object;   t: Types.Type;

BEGIN
	IF (obj= NIL) OR (~(obj IS Display.Frame)) THEN RETURN END;
		this := obj;
		REPEAT
				t := Types.TypeOf(this);
				Out.String(t.name); Out.Ln;
				Traverse(this(Display.Frame).dsc);
				this := this(Display.Frame).next;
		UNTIL (this=NIL) OR (this=obj) OR (~(this IS Display.Frame)); 	
END Traverse;

PROCEDURE Test*;
VAR obj,last: Objects.Object;  t: Types.Type;
BEGIN
	obj := Gadgets.context;
	WHILE(obj#NIL) & (obj IS Display.Frame) DO last := obj; obj := obj.dlink;
	END;
	Traverse(last);
END Test;

PROCEDURE HistoryHook (VAR D: Documents.Document);
	VAR h: hist;
BEGIN
	IF D # NIL THEN
		NEW(h);   h.D := D;   COPY(D.name, h.name);   h.next := dhist;   dhist 
:= h;
	END;
	IF oldhh # NIL THEN oldhh(D) END
END HistoryHook;

PROCEDURE FindDoc(history: hist; VAR name: ARRAY OF CHAR): 
Documents.Document;
VAR lookup: hist;  name1,name2: ARRAY 256 OF CHAR;
BEGIN
	antsPortability.FileDirRelFileName(name,name1);
	lookup := history;
	WHILE(lookup # NIL) DO
		(* here you have to insert Gadgets.Find(....) *)
		antsPortability.FileDirRelFileName(lookup.name,name2);
		IF antsPortability.FileDirSameName(name1,name2) THEN 	 
aM.dS("antsToolbox.FindDoc, found."); RETURN lookup.D END;
		lookup := lookup.next;
	END;
	RETURN NIL;
END FindDoc;

PROCEDURE TempHandle (obj: Objects.Object;    VAR msg: Objects.ObjMsg);
BEGIN
	WITH msg: Display.DisplayMsg DO
		foundFrame := TRUE;
	ELSE
	END
END TempHandle;

PROCEDURE Alive* (f: Display.Frame): BOOLEAN;
VAR
		msg: Display.DisplayMsg;    orighandle: Objects.Handler;
BEGIN
	orighandle := f.handle;
	f.handle := TempHandle; foundFrame := FALSE;
	msg.F := f;    msg.device := Display.screen;    msg.id := Display.full; 
    msg.res := - 1;
	Display.Broadcast(msg);
	f.handle := orighandle;
	RETURN foundFrame;
END Alive;

BEGIN
	(* oldhh := Documents.historyHook; *)
	Documents.historyHook := HistoryHook;
END Test.

Test.Test





More information about the Oberon mailing list