DEFINITION MODULE DMOpSys;
(*******************************************************************
Module DMOpSys ('Dialog Machine' DM_V3.0)
Copyright (c) 1990-2006 by Andreas Fischlin, Olivier Roth and
ETH Zurich.
Purpose Provides operating system and/or platform dependent
procedures such as directory management. You risk to
introduce platform dependencies if you use this module.
Remarks Enables in particular the sub-launching of Modula-2
subprograms or any Macintosh applications, e.g. an
editor, from within a Modula-2 program.
Typically this module is used to access the
operating system to perform these tasks and is
used from within a shell (see e.g. the RAMSES shell,
Fischlin, 1990). In this context arises also the
needs to have some of the other utilities readily
available, e.g. to find out about the location and
other properties of files and applications etc.
Note that this implementation has been made with
and for the underlying MacMETH compiler and linking
loader (Wirth et al., 1988). Especially the latter
deserves special mentioning, since it does perform
a dynamic-linking loading, features which are
especially supported by this module in various
ways.
Hints for the usage of the exported routines:
The separate module DMFileNames serves for typical
path and filename operations.
Whenever a path parameter is required it may be
used to denote a directory. E.g. 'HD:M2:Work:'
denotes the folder 'Work' within the folder 'M2'
within the volume with name 'HD', a hard disk.
In case you wish to use the MacMETH compiler from
within a Modula-2 program linked as a stand-alone
application, you should call procedure
EmulateMacMETHCopyProtection at least once during
application start up; otherwise be warned that the
compiler will refuse to work.
Calling Modula-2 programs allows to profit from the
very efficient dynamic-linking loader capability of
the MacMETH language implementation.
Note that normally any Modula-2 program module can be
called as a subprogram by any other Modula-2 program.
For instance the compiler or debugger are just such
subprograms. Note that subprograms form a stack
(LIFO-queue (Last in, First out)).
As long as these subprograms are 'Dialog Machine'
programs all elements on this stack, not just the top
of the stack, remain visible to all others, in
particular also to the user. A 'Dialog Machine' menu
or window belongs always (together with its content
etc.) to a particular (sub)program level. The
maximum level of programs supported is exported by
constant DMSystem.maxLevel.
References
Fischlin, A. 1990. Interactive Simulation of
Environmental Systems on Working Stations.
In, Möller, D. (ed.), Proc. 4. Ebernburger
Gespräche, 4.-9. April 1990, Münster a. Stein/
Ebernburg, BRD, Vieweg Verlag. In prep.
Wirth, N., Gutknecht, J., Heiz, W., Schär, H.,
Seiler, H. & Vetterli, C. 1988: MacMETH. A fast
Modula-2 language system for the Apple Macintosh.
User Manual. 2nd ed. Institut für Informatik ETH
Zürich, Switzerland, 100pp
This module belongs to the 'Dialog Machine'.
Programming
o Design
Andreas Fischlin 06/09/1990
o Implementation
Andreas Fischlin 06/09/1990
Olivier Roth 23/05/1991
ETH Zurich
Systems Ecology
CHN E 35.1
Universitaetstrasse 16
8092 Zurich
SWITZERLAND
URLs:
<mailto:RAMSES@env.ethz.ch>
<http://www.sysecol.ethz.ch>
<http://www.sysecol.ethz.ch/SimSoftware/RAMSES>
Last revision of definition: 21/04/2010 AF
*******************************************************************)
CONST
noError = 0;
notDone = -2;
VAR
profileFName: ARRAY [0..127] OF CHAR; (* read only, normally = 'User.Profile' *)
(***************************************)
(*##### Results of operations #####*)
(***************************************)
PROCEDURE GetLastResultCode(): INTEGER;
(*
Returns result code obtained from the last call to an internal
system routine. If noError is returned, this means that no error
was detected during the last operation. Otherwise a code >=
notDone will be returned. See module DMLanguage for the
interpretation of result codes. For any code not defined in there
you have to refer to the platform specific information. Macintosh:
Inside Macintosh, Volumes I-VI, Addison Wesley Publishing Company,
Inc., Reading a.o., 1986-1991. IBM PC: Windows. Unix: System
calls or routine specific error codes.
*)
(*************************)
(*##### Volumes #####*)
(*************************)
PROCEDURE EjectDisk( volName: ARRAY OF CHAR; VAR done: BOOLEAN );
(*
Flushes and ejects the volume volName. 'done' returns the success
of the operation. The success depends on the actual hardware and
the platform.
*)
PROCEDURE GetStartupVolName(VAR volName: ARRAY OF CHAR);
(*
Returns the name of the startup volume, i.e. the disk or disk
partition from which the system has been booted. This function is
of minor interest for Unix systems where the startup volume is the
known root '/'. However, under OS X (Macintosh platform) this
function returns the actual name of the startup volume. This
routine is available on all platforms.
*)
(*****************************)
(*##### Directories #####*)
(*****************************)
TYPE
DirectoryProc = PROCEDURE (INTEGER, ARRAY OF CHAR, BOOLEAN, VAR BOOLEAN);
(*
Meaning of arguments:
nr - position number of the file (starts with 1)
dirOrFileName - name of item found in directory (without preceeding paths)
isDir - tells wether item is directory
exit - return TRUE unless you wish to abort the processing
See procedure DoForAllFilesInDirectory
*)
PROCEDURE CurWorkDirectory(VAR path: ARRAY OF CHAR);
(*
Returns the path of the current working directory. This routine is
available on all platforms. Note, path contains at the end a
platform specific path separator.
*)
PROCEDURE CreateDir( path, dirN: ARRAY OF CHAR; VAR done: BOOLEAN );
PROCEDURE DeleteDir( path, dirN: ARRAY OF CHAR; VAR done: BOOLEAN );
(*
Creates/Deletes the directory specified by path and dirN, the
success of operation is returned in done (Note, a non empty
directory cannot be deleted). This routine is available on all
platforms.
*)
PROCEDURE RenameDir( path, oldDirN, newDirN: ARRAY OF CHAR;
VAR done: BOOLEAN );
(*
Rename the directory specified by path and oldDirN to path and
newDirN, the success of operation is returned in done. This
routine is available on all platforms.
*)
PROCEDURE DirInfo( path, dirN: ARRAY OF CHAR;
VAR dirExists, containsFiles : BOOLEAN );
(*
Returns if the directory specified by path and dirN exists and if
it contains any other directories or files. HINT: DirInfo works
also if path contains already the name of the wanted directory at
the end, given you pass for dirN the empty string. This routine is
available on all platforms.
*)
PROCEDURE DoForAllFilesInDirectory(path: ARRAY OF CHAR; dp: DirectoryProc);
(*
Executes dp for all files or directories residing in the
directory specified by path. The first argument is the
position number of the file (starts with 1), the 2nd argument
of dp is the name of the file (contains no path) or if it is a
directory the name of the directory (without any preceeding
volume or mother directory names), the 3rd argument indicates
whether the item encountered is a directory or not, the 4th
argument is interpreted by DoForAllFilesInDirectory upon
returning from dp as a signal to exit the loop (the parameter
is in/out and is reset before each call to FALSE). The
following sample program excerpt, which lists all files
contained in the directory 'HD:MyWork', exemplifies a typical
usage of DoForAllFilesInDirectory:
...
PROCEDURE ListDir(nr: INTEGER; dirOrFileName: ARRAY OF CHAR; isDir: BOOLEAN;
VAR exit: BOOLEAN);
BEGIN
IF nr=1 THEN
WriteString("The directory contains following files: ");
END(*IF*);
IF NOT isDir THEN WriteLn; WriteString(dirOrFileName) END;
exit := FALSE;
END ListDir;
...
DoForAllFilesInDirectory("HD:MyWork:",ListDir);
...
This routine is available on all platforms.
*)
(***********************)
(*##### Files #####*)
(***********************)
PROCEDURE GetFileDialog(prompt, fileTypes: ARRAY OF CHAR;
VAR path,fileName: ARRAY OF CHAR): BOOLEAN;
(*
Let the user specify a file's location and name by standard open
file dialog box. Only files of particular types, listed in
fileTypes (each type characterized by exactly 4 characters) will be
shown and offered for selection. Up to 4 file types may be
specified by separating them with '|' (e.g. "TEXT|PICT|APPL|Mine").
This routine does nothing and returns FALSE if the 'Dialog Machine'
is currently running in the so-called batch mode (see DMMaster
routine DialogMachineIsInBatchMode). The implementation may be
platform dependent.
*)
PROCEDURE GetApplication (prompt: ARRAY OF CHAR;
VAR path, applName: ARRAY OF CHAR): BOOLEAN;
(*
Let the user specify an application's location and name by standard
open file dialog box (equivalent to
GetFileDialog('APPL',path,fileName)). This routine does nothing
and returns FALSE if the 'Dialog Machine' is currently running in
the so-called batch mode (see DMMaster routine
DialogMachineIsInBatchMode). The implementation may be platform
dependent.
*)
CONST
inexistent = -1;
notOpen = 0;
readOnly = 1;
alreadyWrite = 2;
PROCEDURE CurrentFileUse (path,fileName: ARRAY OF CHAR): INTEGER;
(*
Returns how the file denoted by path and name fileName is currently
used by other programs or applications. If the operation could not
be performed or the file does not exist, notDone respectively
inexistent is returned. If it is currently closed, notOpen is
returned. If the file is currently opened by an application which
has the permission to read only from the file (no write
permission), then readOnly is returned. If the file is currently
opened by an application which has a writing permission,
alreadyWrite is returned. For instance, routine CurrentFileUse
will return alreadyWrite, in all cases when the routines
GetExistingFile, CreateNewFile, or Lookup from DMFiles have been
used to open the file. If DMFiles.ReadOnlyLookup has been used to
open a file, CurrentFileUse returns readOnly.
The result of this routine may be platform dependent.
NOTE: The values returned by CurrentFileUse are globally valid for
all currently running programs regardless wether it is the 'Dialog
Machine' or any other program which accesses the file. In
particular, this is also true for the application, which calls
CurrentFileUse. If you wish specifically to learn about wether a
file is used by the "Dialog Machine" itself, it is better to use
routines from module DMFiles.
Note that on the Macintosh normally only a single application has
the permission to write to a file (unless shared access should be
in use). Hence, any program should avoid to write to a file which
is currently already open for writing.
*)
PROCEDURE GetFileTypeAndCreator (path,fn: ARRAY OF CHAR;
VAR type,creator: ARRAY OF CHAR);
(*
Returns the file's type and creator (both strings must be exactly 4
characters long) given it exists on volume/directory path and has
the name fn. This routine returns the file extension in the string
'type' if run on a non-Macintosh platform or run under Mac OSX.
*)
PROCEDURE SetFileTypeAndCreator (path,fn: ARRAY OF CHAR;
type,creator: ARRAY OF CHAR);
(*
This routine does nothing if run on a non-Macintosh platform or
run under Mac OSX.
*)
PROCEDURE HasCustomIcon (path,fn: ARRAY OF CHAR): BOOLEAN;
PROCEDURE SetCustomIconFlag (path,fn: ARRAY OF CHAR; cif: BOOLEAN);
(*
Investigate wether the custom icon flag is set or set it to cif.
This routine does nothing if run on a non-Macintosh platform or run
under Mac OSX.
*)
PROCEDURE GetFileDates (path,fn: ARRAY OF CHAR;
VAR creationDate,modificationDate: LONGINT);
(*
Returns the file's creation and last modificaton date given it
exists on volume/directory path and has the name fn. The older the
file the smaller the returned long integer values, since they
correspond to the number of seconds elapsed since 1st January 1904.
Convert the long integer values with routine InterpreteSeconds from
module DMClock. This routine is available on all platforms but its
result may be platform dependent.
*)
PROCEDURE SetFileDates (path,fn: ARRAY OF CHAR;
creationDate,modificationDate: LONGINT);
(*
Sets the file's creation and last modificaton date given it exists
on volume/directory path and has the name fn. This routine is
available on all platforms but its result may be platform
dependent.
*)
PROCEDURE NowSeconds (): LONGINT;
(*
Returns current date and time from the computer's internal clock.
If needed convert the returned long integer value with routine
DMClock.InterpreteSeconds. This routine is available on all
platforms.
*)
PROCEDURE TouchFileDate (path,fn: ARRAY OF CHAR);
(*
Force the file's last modificaton date to be that of the current
date and time from the computer's internal clock, given the file
exists on volume/directory path and has the name fn. This
routine is available on all platforms.
*)
PROCEDURE CopyResourceFork (sourcePath,sourceFn, destPath, destFn: ARRAY OF CHAR;
VAR done: BOOLEAN);
(*
Copies the whole resource fork from file source to the file dest.
WARNING: If the file dest should already have a resource fork, the
resources from that file will be completely lost without any
warning or a chance for user interaction. If destFn is an existing
file without a resource fork, CopyResourceFork adds first a
resource fork and then copies all resources from source to dest.
If destFn can't be found that file will be created (creator & type
for ResEdit) and the resources are added. done returns the success
of the overall copying process. Note: In case of creation of a new
dest, neither the creation nor modification dates of the source
file are retained; use SetFileDates to force also the copying of
these dates. This routine is only available on the Macintosh. It
does nothing on all other platforms.
*)
PROCEDURE CopyDataFork (sourcePath,sourceFn, destPath, destFn: ARRAY OF CHAR;
VAR done: BOOLEAN);
(*
Copies the whole data fork from file source to the file dest.
WARNING: If file dest should already have a data fork, all data
from that file will be completely lost without any warning or a
chance for user interaction. If destFn is an existing file without
a data fork, CopyResourceFork adds first a data fork and then
copies all data from source to dest. If destFn can't be found that
file will be created (creator & type of sourceFn) and the data are
added. done returns the success of the overall copying process.
Note: In case of creation of a new dest, neither the creation nor
modification dates of the source file are retained; use
SetFileDates to force also the copying of these dates. This
routine is available on all platforms.
*)
(************************************************)
(*##### Start Up and Document handling #####*)
(************************************************)
PROCEDURE GetNameOfRunningApplication (VAR name: ARRAY OF CHAR);
(*
Returns the name of the currently running application. If you
need the path to the folder where it is running, use procedure
CurWorkDirectory.
The implementation of this routine is platform dependent.
Note, on the Macintosh the running application is NOT the subprogram
you may be executing, while you are making use of the dynamic
linking loader provided by MacMETH or RAMSES. For the MacOS the
running application is only the application the MacOS knows about.
Typically this is the MacMETH or RAMSES Shell. Only if you link
your 'Dialog Machine' program as a double-clickable stand-alone
application, will this routine return the name of your 'Dialog
Machine' program.
*)
TYPE
InitDocuHandlingProc = PROCEDURE ( INTEGER );
DocuHandler = PROCEDURE ( INTEGER, ARRAY OF CHAR, ARRAY OF CHAR, VAR BOOLEAN );
PROCEDURE InstallInitDocuOpening (idhp: InitDocuHandlingProc);
PROCEDURE InstallInitDocuPrinting (idhp: InitDocuHandlingProc);
PROCEDURE InstallOpenDocuHandler (dh: DocuHandler);
PROCEDURE InstallPrintDocuHandler (dh: DocuHandler);
(*
Above handlers support the opening respectively printing of document
files bundled with a 'Dialog Machine' program at start up time or
under Windows or MacOS 7 (or later) while the 'Dialog Machine'
program is already running. Typically when double clicking a
document belonging to a 'Dialog Machine' program, the opening
handlers will be executed as installed by above procedures.
Depending whether the user has requested the printing or just the
opening of the documents, either the printing or the opening handlers
are called accordingly.
At the begin of the sequence the initialization procedure
(InitDocuHandlingProc) is called by the 'Dialog Machine'; hereby the
integer parameter nrDocs, i.e. the number of documents to be
processed, is passed to the installed initialization procedure.
Afterwards the 'Dialog Machine' loops from 1 to nrDocs by calling
for each document the installed handler (DocuHandler). First an
index for the document (range [1..nrDocs]) is passed, then the file
name (a full path and file name, which can be directly used as an
argument for DMFiles.Lookup), the type (e.g. 'TEXT' or 'TXT'), and
the flag continue set to the value TRUE. In case the installed
handler procedure decides to exit the loop, it may set the flag
continue to FALSE, and the 'Dialog Machine' will terminate the loop.
In case that the user has issued a printing request, the Dialog
Machine program will be quit immediately after having printed the
last document.
The implementation of this routine is platform dependent.
*)
(***************************************)
(*##### Using Non-DM Programs #####*)
(***************************************)
PROCEDURE SubLaunch (path, prog: ARRAY OF CHAR);
(*
May be used to launch any other application. This includes
also applications which are not 'Dialog Machine' programs.
On a Macintosh make sure if you launch a native OS X
application (Carbon or Cocoa application) to specify the
prog parameter properly by adding the extension '.app'. In
the Finder the extension '.app' of such applications is
normally not visible. The implementation is platform
dependent.
*)
PROCEDURE Transfer (path, prog: ARRAY OF CHAR);
(*
May be used for transferring (quit current program and
launch prog) to any other application. This includes also
applications which are not 'Dialog Machine' programs. On a
Macintosh make sure if you launch a native OS X application
(Carbon or Cocoa application) to specify the prog parameter
properly by adding the extension '.app'. In the Finder the
extension '.app' of such applications is normally not
visible. The implementation is platform dependent.
*)
PROCEDURE ExecuteForResult (command: ARRAY OF CHAR; VAR result: ARRAY OF CHAR);
(*
Executes a command on the host operating system. It
returns the result in the string 'result'. E.g. on Unix
the command "/bin/ls -l" will return in 'result' the
standard output of the executed command. Use
GetLastResultCode to learn about the success. In case of
failure 'result' is the empty string. IMPORTANT NOTE:
There is no warranty for the success of this routine; it is
highly NON-PORTABLE! IMPLEMENTATION RESTRICTIONS: Works
under Unix in a limited way, i.e. commands have either to
be programs in the working directory or need to be passed
to this routine with absolute paths. Arguments containing
blanks need to be double quoted. Any other quoting fails.
*)
PROCEDURE IsForegroundProgram(): BOOLEAN;
(*
Returns whether the calling program is currently in the foreground
and receives the user's attention with the highest priority. The
implementation may be platform dependent.
*)
PROCEDURE BringProgramToForeground;
(*
Brings the calling program to the foreground where it receives the
user's attention with the highest priority. The implementation may
be platform dependent.
*)
PROCEDURE PutProgramIntoBackground;
(*
Puts the calling program into the background. There it
receives the user's attention no longer with the highest
priority. The implementation may be platform dependent.
*)
PROCEDURE QuitDialogMachineInBackground;
(*
Similar to DMMaster.AbortDialogMachine but manages to quit
the running 'Dialog Machine' program while it is in the
background. The implementation may be platform dependent.
*)
(*************************************************)
(*##### Inter Application Communication #####*)
(*************************************************)
(* Functions available only on Macintosh under System 7.0 or later *)
TYPE
MessageResponder = PROCEDURE (ARRAY OF CHAR, ARRAY OF CHAR, INTEGER);
PROCEDURE SetMessageResponder( mr: MessageResponder);
PROCEDURE GetMessageResponder(VAR mr: MessageResponder);
(*
Simple basic mechanism to respond to messages from other programs
under MacOS System 7 (or later). Given the 'Dialog Machine' receives
a message from an other application where the message class is 'DMEv'
('Dialog Machine' Event) or 'MnCh' (Menu Choice), the 'Dialog
Machine' will respond to this message in the manner tabulated below.
Otherwise the the 'Dialog Machine' ignores the event and passes it on
to the Apple Event Manager.
Event class Action taken
i.e. value of by DM
field message
in EventRecord
------------------------------------------------------------------
'MnCh' While responding to an event of this class the
'Dialog Machine' interprets the eventID
(EventRecord.where) to execute a menu command
within the receiving DM program. The eventID
is interpreted as follows: high word contains
the menuID (All following menus numbered
consecutively starting at the Apple menu with
number 128), the low word denotes the menu item
or command number (starting at the topmost
command with the number 1). Note that
hierarchical submenus matter. E.g. if the
first menu right to the Apple menu with ID 129
has a hierarchical menu, the second menu next
to the first will have ID 131 and not 130,
since the hierarchical menu gets ID 130. Using
ResEdit to learn about the menu IDs may be
helpful if the DM program uses predefined menus
(resource type MENU). Commands are numbered
from 1. Note that separators count fully as if
they would be a menu command and that the
status of a menu command does not matter. If a
menu command is currently disabled, a 'MnCh'
event for that command will simply have no
effect.
'DMEv' While responding to an event of this class the
'Dialog Machine' calls the currently installed
responder by passing it the eventClass
(EventRecord.message) as the first, the eventID
(EventRecord.where) as the second and the
EventRecord.modifiers as the third argument.
any other value Event is ignored by the receiving DM program
The implementation of this routine is highly platform dependent.
*)
PROCEDURE SignalMessageToApplication(creatorOfAppl,
eventClass,
eventID: ARRAY OF CHAR;
msgVal: INTEGER;
VAR resultCode: INTEGER);
(*
Simple basic mechanism to send a message to another program under
MacOS System 7 (or later, i.e. including OS X). Signals a message to
the application running on the local machine, i.e. not through the
network, which is identified via the creatorOfAppl, e.g. 'MSWD' for
Microsoft Word or 'MEDT' for MEdit editor. All other input
parameters must be interpreted by the receiving application and are
used in the following way when constructing the event record
before sending it:
parameter is assigned E.g. Possible meaning
to EventRecord and action
field taken by receiving
application
------------------------------------------------------------------
eventClass message 'MnCh' use eventID as if
the user has chosen
a menu command
eventID where 'quit' causes another
program to be
quit
msgVal modifiers 3 An additional
integer to be sent
to the receiver
(possibly ignored)
Note that calling SignalMessageToApplication with the eventClass =
'MnCh' leads to the following interpretation of the parameters:
eventID denotes the menu and command IDs. E.g. the menuID of the
Apple menu is 129, thus pass '129' as the actual parameter value for
argument eventID. You may find out about menu IDs by using ResEdit
and opening the receiving applications resources of type 'MENU'.
msgVal denotes the menu item, e.g. 1. Note that separators or
submenu items count like normal items and that the top item in a menu
is item 1. Example:
SignalMessageToApplication('RAMS','MnCh', '129', 1, res);
This will cause the RAMSES Shell (has the creator 'RAMS') to execute
the 1st menu command in the menu with ID = 129, i.e. the about
command 'About RAMSES Shell...' in the Apple menu.
Both actual arguments eventClass and eventID should
always contain exactly 4 characters. Otherwise blanks will be
appended or only the first 4 characters will be recognized.
The only reporting on success which is available is the
resultCode ( no error = 0; for other codes see Inside Macintosh
Vol. VI p. 5-31, values returned by PostHighLevelEvent). The
postingOptions is always only = receiverIDisSignature (see also
Inside Macintosh Vol. VI p. 5-30), hence no receipt can be
requested.
Note that Apple core events are implemented in any 'Dialog Machine'
program by default. Most applications are capable to respond to
these events in the wanted manner. According to Inside Macintosh VI
6-106 Apple core events are specified as follows:
parameter is assigned E.g. Possible meaning
to EventRecord and action
field taken by receiving
application
------------------------------------------------------------------
eventClass message 'aevt' is Apple core event
eventID where 'oapp' open application
= kAEOpenApplication
eventID where 'odoc' open document
= kAEOpenDocuments
eventID where 'pdoc' print document
= kAEPrintDocuments
eventID where 'quit' quit application
= kAEQuitApplication
msgVal modifiers 0 ignored or pointer
to document list
IMPORTANT IMPLEMENTATION INFORMATION:
------------------------------------
On the Macintosh platform the data are internally stored in the
following data structure, the so-called EventRecord before a message
is sent to another application:
TYPE
EventRecord = RECORD
what: Integer; {event code}
message: LongInt; {event message}
when: LongInt; {ticks since startup}
where: Point; {mouse location}
modifiers: Integer; {modifier flags}
END;
Point = RECORD v,h: INTEGER; END;
For event class 'MnCh' the actual menu choice needs to be stored in
field where: The menuID is stored in where.v, the number of the menu
item (command) in where.h. This is exactly the format in which a
Macintosh applications expect to find the selection of any ordinary
menu choice, i.e. one made by the user. If a 'Dialog Machine'
program receives such an EventRecord via an Apple Event, the effect
is the same as if you would call DMMenus.ExecuteCommand(Menu(menuID),
Command(itemNo)). It is for your convenience only, that you may call
SignalMessageToApplication by passing the menuID and the menu item
number as two separate arguments. As a consequence you can't send
any modifiers. Note also, the event class 'MnCh' is not generally
recognized by Macintosh applications. Only all 'Dialog Machine'
programs recognize this event class.
The use of the fields what and when are reserved for internal use.
The implementation of this routine is highly platform dependent.
*)
(**************************************)
(*##### User event emulation #####*)
(**************************************)
(* Use these procedures to emulate a 'Dialog Machine' user event
received by the running 'Dialog Machine' program *)
PROCEDURE EmulateKeyPress(ch: CHAR; modifier: BITSET);
(*
Emulates the user event keyboard pressed (see module DMKeyChars for
a description of modifiers or see Inside Macintosh Toolbox Event
manager). The implementation of this routine is platform
dependent.
*)
PROCEDURE EmulateMenuSelection(aliasChar: CHAR);
(*
Emulates the user event menu selection via a keyboard
equivalent. Implementation restriction: Only menus which have
an alias char installed can be selected by this mechanism.
The implementation of this routine is platform dependent.
*)
PROCEDURE EmulateMouseDown(x,y: INTEGER; modif: BITSET);
(*
Emulates the user event mouse click at background coordinates x,y
and with modifiers modif (see module DMKeyChars for a description
of modifiers or see Inside Macintosh Toolbox Event manager).
*)
(*************************************)
(*##### Machine environment #####*)
(*************************************)
(* The following routines have no effect on platforms, which don't
support these functions for an ordinary user. For instance under Unix
you require super user privileges to reboot (RestartMachine) or to shut
the machine down (TurnMachineOff). *)
PROCEDURE TurnMachineOff;
(* terminates any running program and turns the power off *)
PROCEDURE RestartMachine;
(* terminates any running program and reboots *)
(**************************************)
(*##### Modula-2 environment #####*)
(**************************************)
(* -----------------------------------------------------------------
The following routines are of relevance on platforms where a dynamic
linking-loader is available. Cyrrently this is the case only for
MacMETH on the Macintosh. On other platforms, program levels remain
always the same and the use of the following routines makes little
sense.
----------------------------------------------------------------- *)
TYPE
ProgStatus = (regular, moduleNotFound, fileNotFound, illegalKey,
readError, badSyntax, noMemory, alreadyLoaded,
killed, tooManyPrograms, continue,
noApplication);
(* Note: in current implementation matches also type
DMLinkLoader.ProgStatus from MacMETH*)
PROCEDURE SetNewPaths;
(*
Reads a new path definition from the text file with the name
profileFName (is normally 'User.Profile') and updates all
'Dialog Machine' file acessing routines (DMFiles, DMSubLaunch,
compiler, linker, editor) such that those paths become
accessible.
*)
PROCEDURE CallDMSubProg (prog: ARRAY OF CHAR; leaveLoaded: BOOLEAN;
VAR st: ProgStatus);
(*
Calls (i.e. sublaunches) a Modula-2 (sub)program by using the
dynamic linking loader; i.e. only those modules are loaded
which are not already in memory. The program level increases
automatically, so that the whole module environment can be
released upon returning from this procedure and the program
level is set back to what it was before the call.
In case that leaveLoaded = TRUE the memory block holding the
program will not be actually released but can be reused for any
subsequent calls to this procedure without having to get the
program from disk again. Note that in the latter case the
initializing bodies of the modules are still rexecuted as if
the (sub)program would have been loaded anew. (NOTE:
Implementation restriction: The names of the module and the
file in which its code is stored must exactly match, even the
extension 'OBM' is disallowed. Otherwise there will an error
occur, i.e. the status alreadyLoaded is returned when
returning from the second call to this procedure).
(Sub)Programs are located following a search strategy which
uses a path definition which must be given in the text file
with the name profileFName (User.Profile). The latter file
must reside in the same folder as the starting application
(usually the shell or any other linked stand-alone application
made with the 'Dialog Machine'). Path definitions must follow
this syntax given in EBNF (start symbol is PathDefinition):
PathDefinition = 'PATH' path { ',' path }.
path = [VolName] { ':' FolderName | ':' } ':'.
VolName = String.
FolderName = String.
String = char { char }.
(Remark: all characters (including ' ') are allowed except
':', however it is recommended to avoid also the use of ','
and '.' in folder names due to some not well understood
Macintosh operating system idiosynchrasies sometimes causing
program crashes at start-up, sometimes not).
Ex.:
PATH
HD:M2:Work:, :DMLib:, :RAMSESLib:,
:Work:MyProject:,
Another Disk:M2:Work:Another Project:,
::Utilities:
Remark to the semantics of relative paths defintions: A
path definition starting with ':' signifies a relative
path, i.e. a path which starts at the folder in which the
file with name profileFName (User.Profile) resides. If
one uses absolute paths, they must not start with ':' and
then always indicate a full path starting with the volume
name. In the example given the last path using the
folder Utilities is preceeded by the construct '::' is
located relative to the start-up folder in which the file
with name profileFName (User.Profile) resides on a level
above (father/mother level).
Path definitions can be changed anytime during program
execution but must then be reentered into the system by
calling routine DMSubLaunch.SetNewPaths.
*)
PROCEDURE CallM2SubProg (prog: ARRAY OF CHAR; leaveLoaded: BOOLEAN;
VAR st: ProgStatus);
(*
Same as CallDMSubProg but is called with a slightly different
level management, i.e. the program is called on the level just
above the current subprogram level. Hence this procedure is
should only be called from the System.TopDMLevel(). It is the
subprogram mechanism used by the underlying MacMETH system and
is reserved to special purposes. Typically this procedure is
never used unless a MacMETH compiler, editor or linker shall be
called.
*)
PROCEDURE IncludeLibModules (prog: ARRAY OF CHAR; VAR st: ProgStatus);
(*
Same as CallM2SubProg but the program level is not incremented and
remains the same. As a consequence you should not call with
this technique program modules (you would not return from it
anymore) but only library modules since you return from this
procedure only if it just executes the bodies of library
modules. Neither is it possible to set the flag leaveLoaded,
since it is always interpreted as beeing the same as the
including program. Finally it is neither possible to release
the used memory unless the whole currnet program level is left.
*)
PROCEDURE UnLoadM2Progs;
(*
Releases all memory occupied by Modula-2 (sub)programs previously
called with leaveLoaded = TRUE.
*)
PROCEDURE EmulateMacMETHCopyProtection;
(*
Emulates the MacMETH copy protection, so that the compiler can
be freely executed, e.g. via CallM2SubProg, from anywhere.
Note that without calling EmulateMacMETHCopyProtection the
MacMETH compilers will refuse to work properly.
*)
PROCEDURE SetCompilerFileTypes(creator,
sbmType, obmType, rfmType: ARRAY OF CHAR);
PROCEDURE GetCompilerFileTypes(VAR creator,
sbmType, obmType, rfmType: ARRAY OF CHAR);
(*
Allows to control the creator and the corresponding Macintosh
file type used by the MacMETH compiler. During compilation it
may create symbol files (SBM file), object code files (OBM
file), and debugger information holding reference files (RFM
file). Note that the file type used depends solely on the
file's name, i.e. each file ending with the extension '.SBM' is
treated as a symbol file etc. Initial defaults are
SetCompilerFileTypes('RAMS','MSYM','MOBJ','MREF');
Note: In accordance with Macintosh file system rules, all
strings must be exactly 4 characters long. Note: the defaults
are restored upon termination of the environment of this module.
*)
(**********************************)
(*##### Program Abortion #####*)
(**********************************)
PROCEDURE AbortM2Prog (st: ProgStatus);
(*
Aborts the currently running program level without executing any
remaining portions of its code except for the installed termination
procedures (see DMSystem.InstallTermProc). The program status on
which to terminate is given by st. On the Unix platform this
routine corresponds to typing Control^C. The implementation of this
routine is platform dependent.
*)
END DMOpSys.