Спасибо за советы. Пока сделал так:
Код:
MODULE TmpOpenForm;
IMPORT Files, Views, FormViews, FormModels, Containers, Controls, StdDialog, Dialog, Windows, Properties, StdLog;
(*
1.2[3]4 -> 1.2[fix]4
1.2(3)4 -> 1.2(fix)4
*)
PROCEDURE Fix (VAR s: Dialog.String; IN fix: ARRAY OF CHAR);
VAR new: Dialog.String;
i (* s reader *), j (* new writer *), k (* fix reader *): INTEGER;
c: CHAR;
BEGIN
i := 0;
WHILE (i < LEN(s)) & (s[i] # 0X) & (s[i] # '.') DO new[i] := s[i]; INC(i) END;
IF (i < LEN(s)) & (s[i] = '.') THEN
new[i] := '.'; INC(i);
WHILE (i < LEN(s)) & (s[i] # 0X) & ~((s[i] = '[') OR (s[i] = '(')) DO new[i] := s[i]; INC(i) END;
IF (i < LEN(s)) & ((s[i] = '[') OR (s[i] = '(')) THEN
new[i] := s[i]; j := i + 1;
IF s[i] = '[' THEN
c := ']'
ELSE (* '(' *)
c := ')'
END;
WHILE (i < LEN(s)) & (s[i] # 0X) & (s[i] # c) DO INC(i) END;
IF (i < LEN(s)) & (s[i] = c) THEN
INC(i);
k := 0;
WHILE (k < LEN(fix)) & (fix[k] # 0X) DO
new[j] := fix[k]; (* TRAP on new[j] bound overflow OK *)
INC(j);
INC(k)
END;
new[j] := c; INC(j); (* TRAP on new[j] bound overflow OK *)
WHILE (i < LEN(s)) & (s[i] # 0X) DO
new[j] := s[i]; (* TRAP on new[j] bound overflow OK *)
INC(j);
INC(i)
END;
new[j] := 0X; (* TRAP on new[j] bound overflow OK *)
StdLog.String(s); StdLog.String(" -> ");
s := new;
StdLog.String(s); StdLog.Ln
END
END
END
END Fix;
(* сделано как в UnicodeConv.ControlsControl *)
PROCEDURE ControlsControl (src: Controls.Control; IN fix: ARRAY OF CHAR): Controls.Control;
VAR
res: Controls.Control;
plist : Properties.Property;
p : Controls.Prop;
poll : Properties.PollMsg;
set : Properties.SetMsg;
BEGIN
res := Views.CopyOf(src, Views.deep)(Controls.Control);
Views.HandlePropMsg(src, poll);
plist := poll.prop;
WHILE (plist # NIL) & ~(plist IS Controls.Prop) DO
plist := plist.next
END;
IF plist # NIL THEN
p := plist(Controls.Prop);
p.known := {Controls.link,Controls.guard,Controls.notifier};
p.valid := {Controls.link,Controls.guard,Controls.notifier};
Fix(p.link, fix);
Fix(p.guard, fix);
Fix(p.notifier, fix);
set.old := NIL; set.prop := p;
Views.HandlePropMsg(res, set)
END;
RETURN res
END ControlsControl;
(* сделано как в UnicodeConv.ConvertThisView *)
PROCEDURE ConvertThisView (src: Views.View; IN fix: ARRAY OF CHAR): Views.View;
VAR dst: Views.View;
BEGIN
WITH src: Controls.Control DO
dst := ControlsControl(src, fix)
ELSE
dst := NIL
END;
RETURN dst
END ConvertThisView;
(* сделано как в UnicodeConv.FormViewsView *)
PROCEDURE FormViewsView (src: FormViews.View; IN fix: ARRAY OF CHAR): FormViews.View;
VAR
res: FormViews.View; m: FormModels.Model; c: Containers.Controller;
v, v1, cv: Views.View;
BEGIN
res := Views.CopyOf(src, Views.deep)(FormViews.View);
m := res.ThisModel(); c := res.ThisController();
c.GetFirstView(Containers.any, v);
WHILE v # NIL DO
v1 := v; c.GetNextView(Containers.any, v1); (* след-й надо брать до замены *)
cv := ConvertThisView(v, fix); IF cv # NIL THEN m.ReplaceView(v, cv) END;
v := v1
END;
RETURN res
END FormViewsView;
PROCEDURE GetForm (IN masterDir, masterName: ARRAY OF CHAR; IN fix: ARRAY OF CHAR): FormViews.View;
VAR v: FormViews.View;
BEGIN
v := Views.OldView(Files.dir.This(masterDir), masterName$)(FormViews.View);
ASSERT(v # NIL);
RETURN FormViewsView(v, fix)
END GetForm;
(* сделано как в StdApi.ThisMask *)
PROCEDURE Mask (v: Views.View);
VAR c: Containers.Controller;
BEGIN
IF v # NIL THEN
WITH v: Containers.View DO
c := v.ThisController();
IF c # NIL THEN
c.SetOpts(c.opts - {Containers.noFocus} + {Containers.noCaret, Containers.noSelection})
ELSE Dialog.ShowMsg("#System:NotEditable")
END
ELSE Dialog.ShowMsg("#System:ContainerExpected")
END
END
END Mask;
(* сделано как в StdApi.OpenAuxDialog *)
PROCEDURE OpenAuxDialog* (IN masterDir, masterName: ARRAY OF CHAR; IN fix: ARRAY OF CHAR; IN title: ARRAY OF CHAR);
VAR t0: Views.Title; done: BOOLEAN;
v: Views.View;
BEGIN
Dialog.MapString(title, t0);
Windows.SelectByTitle(NIL, {Windows.isAux}, t0, done);
IF ~done THEN
v := GetForm(masterDir, masterName, fix);
Mask(v);
StdDialog.Open(v, title, NIL, "", NIL, FALSE, TRUE, TRUE, FALSE, TRUE)
END
END OpenAuxDialog;
(* сделано как в StdApi.OpenToolDialog *)
PROCEDURE OpenToolDialog* (IN masterDir, masterName: ARRAY OF CHAR; IN fix: ARRAY OF CHAR; IN title: ARRAY OF CHAR);
VAR t0: Views.Title; done: BOOLEAN;
v: Views.View;
BEGIN
Dialog.MapString(title, t0);
Windows.SelectByTitle(NIL, {Windows.isTool}, t0, done);
IF ~done THEN
v := GetForm(masterDir, masterName, fix);
Mask(v);
IF v # NIL THEN
StdDialog.Open(v, title, NIL, "", NIL, TRUE, FALSE, TRUE, FALSE, TRUE)
END
END
END OpenToolDialog;
PROCEDURE Test*;
BEGIN
OpenAuxDialog("Tmp/Rsrc", "X1", "0", "Form X1 1 aux");
OpenAuxDialog("Tmp/Rsrc", "X1", "1", "Form X1 2 aux");
OpenToolDialog("Tmp/Rsrc", "X1", "1", "Form X1 2 tool")
END Test;
END TmpOpenForm.
(!)TmpOpenForm.Test
Все отображения (Views), размещаемые на форме, должны быть Control-ами, потому что иначе к ним будет неудобно привязываться. Если какой-нибудь график надо выводить, то его тоже надо оборачивать в Control.