ETHZ_Logo RAMSES_Logo_Right   RAMSES   RAMSES_Logo_Left Systems Ecology  
Start    search button      Modules:   A-Z   Function   Layer        QuickRefs:   DM   AuxLib   AuxLibE   SciLib   EasyMW   MW   ISIS   RMSLib

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.

  Contact RAMSES@env.ethz.ch Last updated: 25-Jul-2011 [Top of page]