MODULE HostCmds;
(**
project = "BlackBox"
organization = "www.oberon.ch"
contributors = "Oberon microsystems"
version = "System/Rsrc/About"
copyright = "System/Rsrc/About"
license = "Docu/BB-License"
changes = ""
issues = ""
**)
IMPORT
Kernel, Ports, Printers, Files,
Stores, Views, Controllers, Dialog, Printing,
Converters, Sequencers, Documents, Windows,
StdDialog, StdCmds,
HostFiles, HostWindows, HostDialog, HostClipboard;
CONST
(* hints *)
impAll = 0; (* can import all file types *)
expDoc = 1; (* imported view should be stored as document *)
VAR quit*: BOOLEAN;
(** File menu **)
PROCEDURE Open*;
(** open an existing document or view **)
VAR loc: Files.Locator; name: Files.Name; v: Views.View;
s: Stores.Store; done: BOOLEAN; w: Windows.Window; conv: Converters.Converter;
BEGIN
HostDialog.GetIntSpec(loc, name, conv);
IF loc # NIL THEN
w := Windows.dir.First();
WHILE (w # NIL) & ((w.loc = NIL) OR (w.name = "") OR (w.loc.res = 77) OR
~Files.dir.SameFile(loc, name, w.loc, w.name) OR (w.conv # conv)) DO
w := Windows.dir.Next(w)
END;
IF w # NIL THEN s := w.doc
ELSE
Converters.Import(loc, name, conv, s);
IF s # NIL THEN StdDialog.RecalcView(s(Views.View)) END
END;
IF s # NIL THEN
v := s(Views.View);
IF (conv # NIL) & (expDoc IN conv.opts) THEN conv := NIL END;
Views.Open(v, loc, name, conv)
ELSE Dialog.ShowParamMsg("#System:FailedToOpen", name, "", "")
END
END
END Open;
PROCEDURE OpenCopyOf*;
VAR loc: Files.Locator; name: Files.Name; conv: Converters.Converter; v: Views.View;
BEGIN
v := Views.Old(TRUE, loc, name, conv);
IF v # NIL THEN
IF v.context # NIL THEN
v := Views.CopyOf(v.context(Documents.Context).ThisDoc(), Views.deep);
Stores.InitDomain(v)
ELSE v := Views.CopyOf(v, Views.deep)
END;
Views.Open(v, NIL, "", conv)
END
END OpenCopyOf;
PROCEDURE SaveWindow (w: Windows.Window; rename: BOOLEAN);
VAR title: Views.Title; loc: Files.Locator; name: Files.Name; v: Views.View;
conv: Converters.Converter; stat: BOOLEAN; i: INTEGER;
BEGIN
IF (w # NIL) & (rename OR ~(Windows.neverDirty IN w.flags)) THEN
v := w.doc.OriginalView();
loc := w.loc; name := w.name$; conv := w.conv;
IF name = "" THEN Dialog.MapString("#System:untitled", name) END;
IF (loc = NIL) OR (loc.res = 77) OR (conv # NIL) & (conv.exp = "") THEN rename := TRUE END;
IF rename THEN HostDialog.GetExtSpec(v, loc, name, conv) END;
IF loc # NIL THEN
Dialog.ShowStatus("#Host:Saving");
Converters.Export(loc, name, conv, v);
IF loc.res = 0 THEN
IF w.seq.Dirty() THEN
w.seq.BeginModification(Sequencers.notUndoable, NIL);
w.seq.EndModification(Sequencers.notUndoable, NIL); (* clear sequencer *)
w.seq.SetDirty(FALSE)
END;
IF rename THEN
i := 0;
WHILE (i < LEN(title) - 1) & (name[i] # 0X) DO title[i] := name[i]; INC(i) END;
title[i] := 0X;
w.SetTitle(title); w.SetSpec(loc, name, conv)
END;
Dialog.ShowStatus("#Host:Saved")
ELSE
Dialog.ShowStatus("#Host:Failed")
END
END;
IF ~quit THEN Kernel.Cleanup END
END
END SaveWindow;
PROCEDURE Save*;
(** save document shown in target window under old name **)
VAR w: Windows.Window;
BEGIN
w := Windows.dir.Focus(Controllers.targetPath);
SaveWindow(w, FALSE)
END Save;
PROCEDURE SaveAs*;
(** save document shown in target window under new name **)
VAR w: Windows.Window;
BEGIN
w := Windows.dir.Focus(Controllers.targetPath);
SaveWindow(w, TRUE)
END SaveAs;
PROCEDURE SaveCopyAs*;
(** save copy of document shown in target window under new name **)
VAR w: Windows.Window; loc: Files.Locator; name: Files.Name; v: Views.View;
conv: Converters.Converter;
BEGIN
w := Windows.dir.Focus(Controllers.targetPath);
IF (w # NIL) THEN
v := w.doc.OriginalView();
loc := w.loc; name := w.name$; conv := w.conv;
IF name = "" THEN Dialog.MapString("#System:untitled", name) END;
HostDialog.GetExtSpec(v, loc, name, conv);
IF loc # NIL THEN
Dialog.ShowStatus("#Host:Saving");
Converters.Export(loc, name, conv, v);
IF loc.res = 0 THEN Dialog.ShowStatus("#Host:Saved")
ELSE Dialog.ShowStatus("#Host:Failed")
END
END;
IF ~quit THEN Kernel.Cleanup END
END
END SaveCopyAs;
PROCEDURE CloseWindow (w: Windows.Window);
VAR res: INTEGER; msg: Sequencers.CloseMsg;
BEGIN
IF w # NIL THEN
IF ~w.sub THEN
msg.sticky := FALSE; w.seq.Notify(msg);
IF ~msg.sticky THEN
IF w.seq.Dirty() & ~(Windows.neverDirty IN w.flags) THEN
HostDialog.CloseDialog(w, quit, res);
IF res = HostDialog.save THEN
SaveWindow(w, FALSE); (* if saving is canceled, document remains dirty *)
IF w.seq.Dirty() THEN quit := FALSE
ELSE Windows.dir.Close(w)
END
ELSIF res = HostDialog.cancel THEN quit := FALSE
ELSE Windows.dir.Close(w)
END
ELSE Windows.dir.Close(w)
END
ELSE quit := FALSE
END
ELSE Windows.dir.Close(w)
END;
IF ~quit THEN Kernel.Cleanup END
END
END CloseWindow;
PROCEDURE Close*;
(** close top window **)
BEGIN
CloseWindow(Windows.dir.First())
END Close;
(*
PROCEDURE PageSetup*;
(** ask user for page size, margins and decoration of the front window's document **)
VAR win: Windows.Window; d: Documents.Document;
w, h, l, t, r, b,dl, dt, dr, db: LONGINT; decorate: BOOLEAN; s: Stores.Operation;
BEGIN
win := Windows.dir.Focus(Controllers.targetPath);
IF win # NIL THEN
d := win.doc;
d.PollPage(w, h, l, t, r, b, decorate);
HostDialog.PageSetup(w, h, l, t, r, b, decorate);
IF w > 0 THEN
IF Windows.noResize IN win.flags THEN
d.PollRect(dl, dt, dr, db);
r := l + (dr - dl); b := t + (db - dt)
END;
d.SetPage(w, h, l, t, r, b, decorate)
END
END
END PageSetup;
*)
PROCEDURE HasSel (w: Windows.Window): BOOLEAN;
VAR ops: Controllers.PollOpsMsg;
BEGIN
ops.type := ""; ops.singleton := NIL; ops.selectable := FALSE; ops.valid := {};
w.ForwardCtrlMsg(ops);
RETURN ops.singleton # NIL
END HasSel;
PROCEDURE PrintSel (w: Windows.Window; from, to, copies: INTEGER);
VAR wt, title: Views.Title; i: INTEGER; edit: Controllers.EditMsg;
BEGIN
edit.op := Controllers.copy; edit.view := NIL;
edit.clipboard := FALSE; w.ForwardCtrlMsg(edit);
ASSERT(edit.view # NIL, 100);
w.GetTitle(wt); title := "[";
i := 1; WHILE (wt[i - 1] # 0X) & (i < LEN(title)) DO title[i] := wt[i - 1]; INC(i) END;
IF i >= LEN(title) - 1 THEN i := LEN(title) - 2 END;
title[i] := "]"; title[i + 1] := 0X;
Printing.PrintView(edit.view, (*edit.w, edit.h,*) Printing.NewDefaultPar(title))
END PrintSel;
PROCEDURE PrintDoc (w: Windows.Window; from, to, copies: INTEGER);
VAR pw, ph, l, t, r, b: INTEGER; decorate: BOOLEAN;
msg: Controllers.ScrollMsg; page: Printing.PageInfo; header, footer: Printing.Banner;
BEGIN
w.doc.PollPage(pw, ph, l, t, r, b, decorate);
page.first := 1; page.from := from; page.to := to; page.alternate := FALSE;
w.GetTitle(page.title);
IF decorate THEN
header.gap := 5 * Ports.mm; header.right := "&d&;&p";
ELSE
header.gap := 0; header.right := "";
END;
footer.gap := 0; footer.right := "";
Printing.PrintView(w.doc, Printing.NewPar(page, header, footer, copies));
(*
msg.focus := FALSE; msg.vertical := TRUE;
msg.op := Controllers.gotoPos; msg.pos := 0;
msg.done := FALSE; w.ForwardCtrlMsg(msg);
Views.UpdateRoot(w.frame, w.frame.l, w.frame.t, w.frame.r, w.frame.b, Views.rebuildFrames)
*)
END PrintDoc;
PROCEDURE PrintThis (w: Windows.Window; from, to, copies: INTEGER; selection: BOOLEAN);
BEGIN
IF copies > 0 THEN
IF selection THEN
PrintSel(w, from, to, copies)
ELSE
PrintDoc(w, from, to, copies)
END
END
END PrintThis;
(*
PROCEDURE PrintSelection*;
(** print the front window's selection **)
VAR win: Windows.Window; pr: Printers.Printer;
from, to, copies: INTEGER; selection, hasSel: BOOLEAN;
BEGIN
win := Windows.dir.Focus(Controllers.path);
IF win # NIL THEN
hasSel := HasSel(win); selection := hasSel;
HostDialog.PrintDialog(hasSel, pr, from, to, copies, selection);
PrintThis(pr, win, from, to, copies, selection)
END
END PrintSelection;
*)
PROCEDURE Print*;
(** print the front window's document **)
VAR win: Windows.Window;
from, to, copies: INTEGER; selection: BOOLEAN;
BEGIN
IF Printers.dir.Available() THEN
win := Windows.dir.Focus(Controllers.targetPath);
IF win # NIL THEN
WHILE win.sub DO win := win.link END;
selection := FALSE;
HostDialog.PrintDialog(HasSel(win), from, to, copies, selection);
PrintThis(win, from, to, copies, selection)
END;
Kernel.Cleanup
END
END Print;
PROCEDURE Quit*;
(** stop if all windows can be closed **)
VAR w: Windows.Window;
BEGIN
quit := TRUE;
w := Windows.dir.First();
WHILE (w # NIL) & (HostWindows.inPlace IN w.flags) DO w := Windows.dir.Next(w) END;
WHILE (w # NIL) & quit DO
CloseWindow(w);
w := Windows.dir.First();
WHILE (w # NIL) & (HostWindows.inPlace IN w.flags) DO w := Windows.dir.Next(w) END
END
END Quit;
PROCEDURE SaveAll*;
VAR w: Windows.Window; res: INTEGER;
BEGIN
quit := FALSE;
w := Windows.dir.First();
WHILE (w # NIL) & (HostWindows.inPlace IN w.flags) DO w := Windows.dir.Next(w) END;
res := HostDialog.save;
WHILE (w # NIL) & (res # HostDialog.cancel) DO
IF ~w.sub & w.seq.Dirty() & ~(Windows.neverDirty IN w.flags) THEN
HostDialog.CloseDialog(w, FALSE, res);
IF res = HostDialog.save THEN
SaveWindow(w, FALSE) (* if saving is canceled, document remains dirty *)
END;
Kernel.Cleanup
END;
w := Windows.dir.Next(w)
END
END SaveAll;
(** Edit menu **)
PROCEDURE Cut*;
(** move the focus document's selection into the clipboard **)
VAR msg: Controllers.EditMsg;
BEGIN
msg.op := Controllers.cut;
msg.clipboard := TRUE;
msg.view := NIL; msg.w := Views.undefined; msg.h := Views.undefined;
Controllers.Forward(msg);
IF msg.view # NIL THEN HostClipboard.Register(msg.view, msg.w, msg.h, msg.isSingle) END
END Cut;
PROCEDURE Copy*;
(** move a copy of the focus document's selection into the clipboard **)
VAR msg: Controllers.EditMsg;
BEGIN
msg.op := Controllers.copy;
msg.clipboard := TRUE;
msg.view := NIL; msg.w := Views.undefined; msg.h := Views.undefined;
Controllers.Forward(msg);
IF msg.view # NIL THEN HostClipboard.Register(msg.view, msg.w, msg.h, msg.isSingle) END
END Copy;
PROCEDURE Paste*;
(** let focus document insert a copy of the clipboard's contents **)
VAR ops: Controllers.PollOpsMsg; msg: Controllers.EditMsg;
BEGIN
HostClipboard.cloneAttributes := TRUE;
HostClipboard.isText := TRUE;
Controllers.PollOps(ops);
HostClipboard.isText := ops.type = "TextViews.View";
IF Controllers.paste IN ops.valid THEN
msg.clipboard := TRUE;
HostClipboard.GetClipView(ops.pasteType, msg.view, msg.w, msg.h, msg.isSingle);
IF msg.view # NIL THEN
msg.op := Controllers.paste; Controllers.Forward(msg)
END
END;
HostClipboard.cloneAttributes := FALSE;
HostClipboard.isText := TRUE;
END Paste;
PROCEDURE PasteObject*;
(** let focus document insert a copy of the clipboard's contents **)
VAR ops: Controllers.PollOpsMsg; v: Views.View; w, h: INTEGER; s: BOOLEAN;
BEGIN
HostClipboard.cloneAttributes := FALSE;
Controllers.PollOps(ops);
IF Controllers.paste IN ops.valid THEN
HostClipboard.GetClipView(ops.pasteType, v, w, h, s);
IF v # NIL THEN
Controllers.PasteView(v, w, h, TRUE)
END
END
END PasteObject;
PROCEDURE PasteToWindow*;
VAR v: Views.View; w, h: INTEGER; d: Documents.Document; s: BOOLEAN;
BEGIN
HostClipboard.cloneAttributes := FALSE;
HostClipboard.GetClipView("", v, w, h, s);
IF v # NIL THEN
d := Documents.dir.New(v, w, h);
Views.OpenView(d)
END
END PasteToWindow;
PROCEDURE OpenDoc* (file: ARRAY OF CHAR);
VAR w: Windows.Window;
BEGIN
w := Windows.dir.Focus(FALSE);
IF (w.loc # NIL) & (w.loc IS HostFiles.Locator) & (w.loc(HostFiles.Locator).path # "") THEN
StdCmds.OpenDoc(w.loc(HostFiles.Locator).path + "\" + file)
ELSE
StdCmds.OpenDoc(file)
END
END OpenDoc;
(* Guards *)
PROCEDURE SaveGuard* (VAR par: Dialog.Par);
VAR w: Windows.Window;
BEGIN
w := Windows.dir.Focus(Controllers.targetPath);
IF (w = NIL) OR (Windows.neverDirty IN w.flags) OR ~w.seq.Dirty() THEN par.disabled := TRUE END
END SaveGuard;
PROCEDURE PrintGuard* (VAR par: Dialog.Par);
VAR w: Windows.Window;
BEGIN
w := Windows.dir.Focus(Controllers.targetPath);
IF (w = NIL) OR ~Printers.dir.Available() THEN par.disabled := TRUE END
END PrintGuard;
PROCEDURE PrinterGuard* (VAR par: Dialog.Par);
BEGIN
IF ~Printers.dir.Available() THEN par.disabled := TRUE END
END PrinterGuard;
PROCEDURE CutGuard* (VAR par: Dialog.Par);
VAR ops: Controllers.PollOpsMsg;
BEGIN
Controllers.PollOps(ops);
IF ~(Controllers.cut IN ops.valid) THEN par.disabled := TRUE END
END CutGuard;
PROCEDURE CopyGuard* (VAR par: Dialog.Par);
VAR ops: Controllers.PollOpsMsg;
BEGIN
Controllers.PollOps(ops);
IF ~(Controllers.copy IN ops.valid) THEN par.disabled := TRUE END
END CopyGuard;
PROCEDURE PasteGuard* (VAR par: Dialog.Par);
VAR ops: Controllers.PollOpsMsg;
BEGIN
Controllers.PollOps(ops);
IF ~(Controllers.paste IN ops.valid)
OR ~HostClipboard.ConvertibleTo(ops.pasteType) THEN par.disabled := TRUE END
END PasteGuard;
PROCEDURE PasteObjectGuard* (VAR par: Dialog.Par);
VAR ops: Controllers.PollOpsMsg;
BEGIN
Controllers.PollOps(ops);
IF ~(Controllers.paste IN ops.valid)
OR ~HostClipboard.ConvertibleTo("") THEN par.disabled := TRUE END
END PasteObjectGuard;
PROCEDURE PasteToWindowGuard* (VAR par: Dialog.Par);
BEGIN
IF ~HostClipboard.ConvertibleTo("") THEN par.disabled := TRUE END
END PasteToWindowGuard;
BEGIN
quit := FALSE
END HostCmds.