[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