Program ANLCMMON;
    {    Version 1.01  10/7/92 ANL Electron Microscopy Center      }
    { A revision of the CMonitor program from Phillips for control }
    { of CM microscopes.  Include files have been put in a unit,   }
    { (CM.TPU), and a number of units from Technojocks Turbo       }
    { Toolkit have been used.  TTT is available from TechnoJock    }
    { Software Inc., PO Box 820927, Huston, Texas 77282-0827.      }
    { I am presently using version 5.5 of Turbo Pascal and any     }
    { units provided are compiled under that version.  If you use  }
    { a different version you will need the source to recompile    }
    { the various units. S. Ockers,                                }

Uses CM,CRT,Printer,FastTTT5, DOS, WinTTT5, KeyTTT5, MenuTTT5, MiscTTT5,
     DirTTT5,ReadTTT5   ;

{ (C)  1988 Copyright PHILIPS EXPORT B.V., All Rights Reserved  }

TYPE Stig_Choice_Type = (C2,Obj,Dif);
     Str3 = String[3];
     Str70 = String[70];

CONST
  Algn_Filename : StrScreen = 'ALIGNMNT.ALG';
  Stig_Filename : StrScreen = 'STIGMATR.STG';
  Mode_Filename : StrScreen = 'MODE.MOD';
  Log_Filename  : StrScreen = 'LOG.LOG';
  AllSet_Filename : StrScreen = 'ALLSETXX.ALL';

  Stig_Choice   : Stig_Choice_Type = Obj;
  Replace       : boolean          = False;
  Logging       : boolean          = False;
  Update        : boolean          = True;
  Port2         : boolean          = True;


var
  M,S,R,L,C : menu_record;
  Choice,choice2, Retcode : integer;
  Ch : char;
  tempfile : StrScreen;
  errcode : Integer;

  PROCEDURE Show_FileReadError(filename:StrScreen);
    BEGIN
      TempMessageBox(20,13,yellow,red,1,'Cannot read file '+filename);
    END;  { Show_FileReadError }

  PROCEDURE Show_FileWriteError(filename:StrScreen);
    BEGIN
      TempMessageBox(20,13,yellow,red,1,'Cannot write to file '+filename);
    END;  { Show_FileWriteError }

  PROCEDURE Show_CommunicationError;
    BEGIN
      TempMessageBox(20,13,yellow,red,1,'Communication with microscope failed');
    END;  { Show_CommunicationError }

{ ************************ The Remote Control Functions ******************* }

  procedure GetAlignment;
  { Get the alignments from the microscope and put them into the file
    with the name <Algn_Filename>. The data are preceeded by the string
    'CMONITOR-ALIGNMENT'. }
    type  Check_String_Type = String[18];
          Alignment_Set_Type = record
                                 Check_String : Check_String_Type;
                                 Alignments   : AlignmentsType;
                               end;
    var
      Alignment_Set : Alignment_Set_Type;
      AlignmentsFile: File of Alignment_Set_Type;
      ok : boolean;
    begin
      if GetAlignments(Alignment_Set.Alignments) then begin
{$I-}
        assign(Alignmentsfile,Algn_Filename );
        ok := (IOResult=0);
        if ok then begin
          rewrite(Alignmentsfile);
          ok := (IOResult = 0);
          if ok then begin
            Alignment_Set.Check_String := 'CMONITOR-ALIGNMENT';
            write(Alignmentsfile, Alignment_Set);
            ok := (IOResult = 0);
          end
        end;
        close(Alignmentsfile);
{$I+}
        if not ok then
          Show_FilewriteError(Algn_Filename);
      end
      else
        Show_CommunicationError;
    end;


{.cp13}
  procedure SetAlignment;
  { Retrieve the alignments into the microscope out of the file
    with the name <Algn_Filename>. It is checked whether the data
    are preceeded by the string 'CMONITOR-ALIGNMENT'. }
    type  Check_String_Type = String[18];
          Alignment_Set_Type = record
                                 Check_String : Check_String_Type;
                                 Alignments   : AlignmentsType;
                               end;
    var
      Alignment_Set : Alignment_Set_Type;
      AlignmentsFile: File of Alignment_Set_Type;
      ok : boolean;
{.cp15}
    begin
{$I-}
      assign(Alignmentsfile,Algn_Filename );
      ok := (IOResult = 0);
      if ok then begin
        reset(Alignmentsfile);
        ok := (IOResult = 0);
        if ok then begin
          read(Alignmentsfile,Alignment_Set);
          ok := (IOResult = 0) and
                (Alignment_Set.Check_String = 'CMONITOR-ALIGNMENT');
        end
      end;
      close(Alignmentsfile);
{$I+}
{.cp18}
      { The following commands make sure that the retrieved settings
        get active }
      if ok then begin
        ok := Pushbutton(29,0);                          { ALGN OFF }
      if ok then
        ok := SetAlignments(Alignment_Set.Alignments);
      if ok then
        ok := Pushbutton(63,1);                          { WBL ON }
      if ok then
        ok := Pushbutton(03,1);                          { D   ON }
      if ok then
        ok := Pushbutton(63,0);                          { WBL OFF }
      if ok then
        ok := Pushbutton(03,0);                          { D   OFF }
      if ok then
        ok := InstrumentMode(08);                        { TEM }
      if not ok then
        Show_CommunicationError
      end
      else
        Show_FileReadError(Algn_Filename);
    end;

{.cp13}
  procedure Get_Stigmator;
  { Get the stigmator settings from the microscope and put them into the file
    with the name <Stig_Filename>. The data are preceeded by the string
    'CMONITOR-STIGMATOR'. }
    type  Check_String_Type = String[18];
          Stigmator_Set_Type = record
                                 Check_String : Check_String_Type;
                                 StigRec      : StigType;
                               end;
    var
      Stigmator_Set : Stigmator_Set_Type;
      StigFile      : File of Stigmator_Set_Type;
      ok : boolean;
{.cp16}
    begin
      if GetStigmator(Stigmator_Set.StigRec) then begin
{$I-}
        assign(Stigfile,Stig_Filename );
        ok := (IOResult = 0);
        if ok then begin
          rewrite(Stigfile);
          ok := (IOResult = 0);
          if ok then begin
            Stigmator_Set.Check_String := 'CMONITOR-STIGMATOR';
            write(Stigfile, Stigmator_Set);
            ok := (IOResult = 0);
          end
        end;
        close(Stigfile);
{$I+}
{.cp6}
        if not ok then
          Show_FilewriteError(Stig_Filename);
      end
      else
        Show_CommunicationError
    end;

{.cp14}
  procedure Set_Stigmator;
  { Retrieve the stigmator settings into the microscope out of the file
    with the name <Stig_Filename>. It is checked whether the data
    are preceeded by the string 'CMONITOR-STIGMATOR'. }
    type  Check_String_Type = String[18];
          Stigmator_Set_Type = record
                                 Check_String : Check_String_Type;
                                 StigRec      : StigType;
                               end;
    var
      Stigmator_Set : Stigmator_Set_Type;
      StigFile      : File of Stigmator_Set_Type;
      ok : boolean;
      StigNr : integer;
{.cp15}
    begin
{$I-}
      assign(Stigfile,Stig_Filename );
      ok := (IOResult =0);
      if ok then begin
        reset(Stigfile);
        ok := (IOResult =0);
        if ok then begin
          read(Stigfile,Stigmator_Set);
          ok := (IOResult =0) and
                (Stigmator_Set.Check_String = 'CMONITOR-STIGMATOR');
        end;
      end;
      close(Stigfile);
{$I+}
{.cp8}
      StigNr := Ord(Stig_Choice);
      if ok then begin
        if not SetStigmator(Stigmator_Set.StigRec,StigNr) then
          Show_CommunicationError
      end
      else
        Show_FileReadError(Stig_Filename);
    end;

{.cp13}
  procedure Get_Mode;
  { Get the mode descriptors from the microscope and put them into the file
    with the name <Mode_Filename>. The data are preceeded by the string
    'CMONITOR-MODE'. }
    type  Check_String_Type = String[13];
          Mode_Set_Type = record
                            Check_String : Check_String_Type;
                            ModeRec      : ModeType;
                           end;
    var
      Mode_Set      : Mode_Set_Type;
      ModeFile      : File of Mode_Set_Type;
      ok : boolean;
{.cp16}
    begin
    if GetMode(Mode_Set.ModeRec) then begin
{$I-}
      assign(Modefile,Mode_Filename );
      ok := (IOResult = 0);
      if ok then begin
        rewrite(Modefile);
        ok := (IOResult = 0);
        if ok then begin
          Mode_Set.Check_String := 'CMONITOR-MODE';
          write(Modefile,Mode_Set);
          ok := (IOResult = 0);
        end
      end;
      close(Modefile);
{$I+}
{.cp6}
      if not ok then
        Show_FilewriteError(Mode_Filename);
    end
    else
      Show_CommunicationError;
    end;

{.cp13}
  procedure Set_Mode;
  { Retrieve the mode descriptors into the microscope out of the file
    with the name <Mode_Filename>. It is checked whether the data
    are preceeded by the string 'CMONITOR-MODE'. }
    type  Check_String_Type = String[13];
          Mode_Set_Type = record
                            Check_String : String[13];
                            ModeRec      : ModeType;
                           end;
    var
      Mode_Set      : Mode_Set_Type;
      ModeFile      : File of Mode_Set_Type;
      ok : boolean;
{.cp15}
    begin
{$I-}
      assign(Modefile,Mode_Filename );
      ok := (IOResult =0);
      if ok then begin
        reset(Modefile);
        ok := (IOResult =0);
        if ok then begin
          read(Modefile, Mode_Set);
          ok := (IOResult =0) and
                (Mode_Set.Check_String = 'CMONITOR-MODE');
        end
      end;
      close(modefile);
{$I+}
{.cp7}
      if ok then begin
        if not SetMode(Mode_Set.ModeRec) then
          Show_CommunicationError
      end
      else
        Show_FileReadError(Mode_Filename);
    end;

{.cp17}
  PROCEDURE GetAllSettings;     { store all settings to disk }
  VAR
      alignfnsav,stigfnsav,modefnsav : StrScreen;
      lenfn : Byte;
  BEGIN
      alignfnsav := Algn_Filename;
      stigfnsav := Stig_Filename;
      modefnsav := Mode_Filename;
      lenfn := Length(AllSet_Filename);
      Algn_Filename:=Copy(AllSet_Filename,1,lenfn-6)+'AL'
                           +Copy(AllSet_Filename,lenfn-3,4);
      GetAlignment;
      Stig_Filename:=Copy(AllSet_Filename,1,lenfn-6)+'ST'
                           +Copy(AllSet_Filename,lenfn-3,4);
      Get_Stigmator;
      Mode_Filename:=Copy(AllSet_Filename,1,lenfn-6)+'MO'
                           +Copy(AllSet_Filename,lenfn-3,4);
      Get_Mode;
      Algn_Filename := alignfnsav;
      Stig_Filename := stigfnsav;
      Mode_Filename := modefnsav;
  END;  { GetAllSettings }

  PROCEDURE SetAllSettings;    { recall all settings from disk }
  VAR stigsav : stig_choice_type;
      alignfnsav,stigfnsav,modefnsav : StrScreen;
      lenfn : Byte;
  BEGIN
      stigsav := Stig_Choice;
      alignfnsav := Algn_Filename;
      stigfnsav := Stig_Filename;
      modefnsav := Mode_Filename;
      lenfn := Length(AllSet_Filename);
      Algn_Filename:=Copy(AllSet_Filename,1,lenfn-6)+'AL'
                           +Copy(AllSet_Filename,lenfn-3,4);
      SetAlignment;
      Stig_Choice := C2;
      Stig_Filename:=Copy(AllSet_Filename,1,lenfn-6)+'ST'
                           +Copy(AllSet_Filename,lenfn-3,4);
      Set_Stigmator;
      Stig_Choice := Dif;
      Set_Stigmator;
      Stig_Choice := Obj;
      Set_Stigmator;
      Mode_Filename:=Copy(AllSet_Filename,1,lenfn-6)+'MO'
                           +Copy(AllSet_Filename,lenfn-3,4);
      Set_Mode;
      Stig_Choice := stigsav;
      Algn_Filename := alignfnsav;
      Stig_Filename := stigfnsav;
      Mode_Filename := modefnsav;
  END;  { SetAllSettings }

  { ***************** Topic Sensitive Help ************************** }

  Procedure Display_Help_Text(L1,L2,L3:string);
  {}
  const
      X1 = 1;
      Y1 = 15;
      X2 = 40;
      Y2 = 21;
      F1  = white;
      F2  = yellow;
      B  = blue;
  begin
      MkWin(X1,Y1,X2,Y2,F1,B,1);
      WriteBetween(X1,X2,Y1,yellow,B,' H E L P ');
      WriteBetween(X1,X2,Y1+2,F2,B,L1);
      WriteBetween(X1,X2,Y1+3,F1,B,L2);
      WriteBetween(X1,X2,Y1+4,F1,B,L3);
      WriteBetween(X1,X2,Y2,F1,B,' press any key ... ');
      DelayKey(10000);   {wait 10 seconds or user presses key}
      Rmwin;
  end; {of proc Display_Help_Text}

{$F+}
  Procedure MTopic_Sensitive_Help(var Ch:char; Choice:integer; var Ecode:integer);
  {this procedure is Hooked into the menu}
  begin
      If Ch = #187 then   {F1}
      begin
          case Choice of
          1 :Display_Help_Text(
             'Store Settings',
             'This option stores microscope',
             'parameters to a disk file.'
             );
          2 :Display_Help_Text(
             'Recall Settings',
             'Select this option to retrieve ',
             'microscope parameters from disk.'
             );
          3 :Display_Help_Text(
             'Directory',
             'This option provides a directory ',
             'display to see what files exist.'
             );
          4 :Display_Help_Text(
             'Logging',
             'Use to turn logging on or off, choose',
             'type of logging and print logfile.'
             );
          5 :Display_Help_Text(
             'Microscope Parameters',
             'This option provides a screen of lens',
             'currents and vacuum information.'
             );
          6 :Display_Help_Text(
             'Communications',
             'Use to change baud rate',
             'or communications port.'
             );
          7 :Display_Help_Text(
             'Blank the Screen',
             'Use for darkness. Pressing any',
             'key will return the menu.'
             );
          8 :Display_Help_Text(
             'QUIT',
             'If you don''t know what quit',
             'means why are you at ANL?'
             );
          end;  {Case}
      end;
  end; {of proc MTopic_Sensitive_Help}
{$F-}
{$F+}
  Procedure STopic_Sensitive_Help(var Ch:char; Choice:integer; var Ecode:integer);
  {this procedure is Hooked into the menu}
  begin
      If Ch = #187 then   {F1}
      begin
          case Choice of
          1 :Display_Help_Text(
             'Alignment Settings',
             'Stores microscope alignment',
             'parameters to a disk file.'
             );
          2 :Display_Help_Text(
             'Stigmator Settings',
             'Stores all stigmator',
             'parameters to a disk file.'
             );
          3 :Display_Help_Text(
             'Mode Settings',
             'Stores microscope mode',
             'parameters to a disk file.'
             );
          4 :Display_Help_Text(
             'Everything above',
             'Stores alignment, mode and all',
             'stigmator parameters to disk.'
             );
          5 :Display_Help_Text(
             'Back to main menu',
             'A way out if you',
             'don''t want to do anything.'
             );
          end;  {Case}
      end;
  end; {of proc STopic_Sensitive_Help}
{$F-}
{$F+}
  Procedure RTopic_Sensitive_Help(var Ch:char; Choice:integer; var Ecode:integer);
  {this procedure is Hooked into the menu}
  begin
      If Ch = #187 then   {F1}
      begin
          case Choice of
          1 :Display_Help_Text(
             'Alignment Settings',
             'Recalls microscope alignment',
             'parameters from a disk file.'
             );
          2 :Display_Help_Text(
             'Condensor Stigmator',
             'Recalls condensor stigmator',
             'parameters from a disk file.'
             );
          3 :Display_Help_Text(
             'Objective Stigmator',
             'Recalls objective stigmator',
             'parameters from a disk file.'
             );
          4 :Display_Help_Text(
             'Diffraction Stigmator',
             'Recalls diffraction stigmator',
             'parameters from a disk file.'
             );
          5 :Display_Help_Text(
             'Mode Settings',
             'Recalls microscope mode',
             'parameters from a disk file.'
             );
          6 :Display_Help_Text(
             'Everything above',
             'Recalls alignment, mode and all',
             'stigmator parameters from disk.'
             );
          7 :Display_Help_Text(
             'Back to main menu',
             'A way out if you',
             'don''t want to do anything.'
             );
          end;  {Case}
      end;
  end; {of proc RTopic_Sensitive_Help}
{$F-}
{$F+}
  Procedure LTopic_Sensitive_Help(var Ch:char; Choice:integer; var Ecode:integer);
  {this procedure is Hooked into the menu}
  begin
      If Ch = #187 then   {F1}
      begin
          case Choice of
          1 :Display_Help_Text(
             'Activate Logging',
             'Log info will be sent from',
             'microscope to disk files.'
             );
          2 :Display_Help_Text(
             'Deactivate Logging',
             'Logging will be turnd OFF,',
             '(data from microscope not saved).'
             );
          3 :Display_Help_Text(
             'Printer Logging',
             'Output of Print Log',
             'is sent to printer.'
             );
          4 :Display_Help_Text(
             'Log to Screen',
             'Output of Print Log',
             'is sent to screen.'
             );
          5 :Display_Help_Text(
             'Back to Main Menu',
             'A way out if you',
             'change your mind.'
             );
        end; { Case }
      end;   { If }
  end; {of proc LTopic_Sensitive_Help}
{$F-}
{$F+}
  Procedure CTopic_Sensitive_Help(var Ch:char; Choice:integer; var Ecode:integer);
  {this procedure is Hooked into the menu}
  begin
      If Ch = #187 then   {F1}
      begin
          case Choice of
          1 :Display_Help_Text(
             'First Port',
             'Change serial communications',
             'port to use COM1.'
             );
          2 :Display_Help_Text(
             'Second Port',
             'Change serial communications',
             'port to use COM2.'
             );
          3 :Display_Help_Text(
             'Choose Baud Rate',
             'Use to set baud rate of',
             'computer output port.'
             );
          4 :Display_Help_Text(
             'Are you there?',
             'Determine if communication',
             'with microscope is possible.'
             );
          5 :Display_Help_Text(
             'Back to Main Menu',
             'A way out if you',
             'change your mind.'
             );
        end; { Case }
      end;   { If }
  end; {of proc CTopic_Sensitive_Help}
{$F-}

  { ******************  Menu Definitions ****************************** }

Procedure Define_M;          { The Main Menu }
begin
    Menu_Set(M);
    With M do
    begin
        Heading1 := 'Microscope Control Program';
        Heading2 := 'Main Menu';
        Topic[1]  := '  Store Settings';
        Topic[2]  := '  Recall Settings';
        Topic[3]  := '  Directory';
        Topic[4]  := '  Logging';
        Topic[5]  := '  Microscope Parameters';
        Topic[6]  := '  Communications';
        Topic[7]  := '  Blank the Screen';
        Topic[8]  := '  Quit';
        TotalPicks := 8;
        PicksPerLine := 1;
        AddPrefix := 4;
        TopleftXY[1] := 5;
        TopLeftXY[2] := 5;
        BoxType := 5;
        Margins := 4;
        Colors[1] := white;
        Colors[2] := blue;
        Colors[3] := lightgray;
        Colors[4] := red;
        Colors[5] := cyan;
        AllowEsc := true;
        Hook := MTopic_Sensitive_Help;
    end;
end;

Procedure Define_S;            { The Store Settings Menu }
begin
    Menu_Set(S);
    With S do
    begin
        Heading1 := 'Store Settings';
        Heading2 := 'Select One :';
        Topic[1]  := '  Alignment Settings';
        Topic[2]  := '  Stigmator Settings';
        Topic[3]  := '  Mode Settings';
        Topic[4]  := '  Everything Above';
        Topic[5]  := '  Back to Main Menu';
        TotalPicks := 5;
        PicksPerLine := 1;
        AddPrefix := 4;
        TopleftXY[1] := 4;
        TopLeftXY[2] := 5;
        BoxType := 5;
        Margins := 2;
        Colors[1] := white;
        Colors[2] := blue;
        Colors[3] := lightgray;
        Colors[4] := red;
        Colors[5] := cyan;
        AllowEsc := true;
        Hook := STopic_Sensitive_Help;
    end;
end;

Procedure Define_R;            { The Recall Settings Menu }
begin
    Menu_Set(R);
    With R do
    begin
        Heading1 := 'Recall Settings';
        Heading2 := 'Select One :';
        Topic[1]  := '  Alignment Settings';
        Topic[2]  := '  Condensor Stigmator';
        Topic[3]  := '  Objective Stigmator';
        Topic[4]  := '  Diffraction Stigmator';
        Topic[5]  := '  Mode Settings';
        Topic[6]  := '  Everything Above';
        Topic[7]  := '  Back to Main Menu';
        TotalPicks := 7;
        PicksPerLine := 1;
        AddPrefix := 4;
        TopleftXY[1] := 5;
        TopLeftXY[2] := 5;
        BoxType := 5;
        Margins := 2;
        Colors[1] := white;
        Colors[2] := blue;
        Colors[3] := lightgray;
        Colors[4] := red;
        Colors[5] := cyan;
        AllowEsc := true;
        Hook := RTopic_Sensitive_Help;
    end;
end;

Procedure Define_L;         { The Logging Menu }
begin
    Menu_Set(L);
    With L do
    begin
        Heading1 := 'Logging Menu';
        Heading2 := 'Select One :';
        Topic[1]  := '  Activate Logging';
        Topic[2]  := '  Deactivate Logging';
        Topic[3]  := '  Print Log (printer)';
        Topic[4]  := '  Logfile to screen';
        Topic[5]  := '  Back to Main Menu';
        TotalPicks := 5;
        PicksPerLine := 1;
        AddPrefix := 4;
        TopleftXY[1] := 5;
        TopLeftXY[2] := 5;
        BoxType := 5;
        Margins := 3;
        Colors[1] := white;
        Colors[2] := blue;
        Colors[3] := lightgray;
        Colors[4] := red;
        Colors[5] := cyan;
        AllowEsc := true;
        Hook := LTopic_Sensitive_Help;
    end;
end;

Procedure Define_C;         { The Communications Menu }
begin
    Menu_Set(C);
    With C do
    begin
        Heading1 := 'Communication Menu';
        Heading2 := 'Select One :';
        Topic[1]  := '  First Port (COM1)';
        Topic[2]  := '  Second Port (COM2)';
        Topic[3]  := '  Choose Baud ';
        Topic[4]  := '  Are you there?';
        Topic[5]  := '  Back to Main Menu';
        TotalPicks := 5;
        PicksPerLine := 1;
        AddPrefix := 4;
        TopleftXY[1] := 5;
        TopLeftXY[2] := 5;
        BoxType := 5;
        Margins := 3;
        Colors[1] := white;
        Colors[2] := blue;
        Colors[3] := lightgray;
        Colors[4] := red;
        Colors[5] := cyan;
        AllowEsc := true;
        Hook := CTopic_Sensitive_Help;
    end;
end;

  { ********************  Screen Displays  ***************************** }

    PROCEDURE WhatsHappening(msg:Str70;line:byte);
      VAR l,x1,x2 : Byte;
      BEGIN
        l := Length(msg);
        x1:=(76-l) DIV 2;
        x2:=x1+l+4;
        FBox(x1,Pred(line),x2,Succ(line),white,blue,1);
        WriteCenter(line,white,blue,msg);
        Delay(2000);  { 2 seconds to read message }
      END;  { WhatsHappening }

  PROCEDURE DisplayDefaults;
    BEGIN
      Fbox(39,2,76,14,white,blue,2);
      WriteBetween(39,76,3,white,blue,Date);
      PlainWrite(42,4,'Defaults:');
      PlainWrite(44,5,'Alignment File:'+Algn_Filename);
      PlainWrite(44,6,'Stigmator File:'+Stig_Filename);
      PlainWrite(44,7,'Mode      File:'+Mode_Filename);
      PlainWrite(44,8,'All_Set   File:'+AllSet_Filename);
      PlainWrite(44,9,'Log       File:'+Log_Filename);
      IF Port2 THEN
        WriteBetween(39,76,11,white,blue,'COM2 Used')
      ELSE
        WriteBetween(39,76,11,white,blue,'COM1 Used');
      IF logging THEN
        WriteBetween(39,76,12,white,blue,'Logging is ON')
      ELSE
        WriteBetween(39,76,12,white,blue,'Logging is OFF');
      IF NOT Replace AND logging THEN
        WriteBetween(39,76,13,white,blue,'Data APPENDED to Log');
      IF Replace AND logging THEN
        WriteBetween(39,76,13,white,blue,'Data will REPLACE Log File');
    END;

  PROCEDURE Ask_Filename(prompt:StrScreen;nbr:Byte;VAR fname:StrScreen;sufx:Str3);
    CONST notallowed : Set of Char = [#0..#32,#34,#42..#44,#46,#47,
                                       #58..#63,#91..#93];
    VAR valid,nospace : Boolean;
        j : Byte;
    BEGIN
      IF nbr=8 THEN
        fname:=Copy(fname,1,Length(fname)-4)
      ELSE
        fname:=Copy(fname,1,Length(fname)-6);
      MkWin(20,16,60,21,white,blue,1);
      WriteAt(22,18,white,blue,'Enter Filename for '+prompt+ ':');
      WriteAt(48,19,white,blue,'XX.'+sufx);
      WriteAt(30,17,black,cyan,' Press Esc to cancel. ');
      WriteAt(26,20,black,cyan,' F2 = Select Using Directory. ');
      REPEAT
        valid := TRUE; nospace := TRUE;
        Read_String_Upper(42,19,nbr,'',0,fname);
        IF R_Char = #27 THEN Exit;
        IF R_Char =#188 THEN BEGIN
          fname := File_Name(Display_Directory('*.'+sufx,errcode));
          IF sufx = 'ALL' THEN
             fname := Copy(fname,1,Length(fname)-2)+'XX';
          fname := fname + '.'+ sufx;
          IF errcode<>0 THEN R_Char := #27;
          Exit;
        END;  { If }
        IF NOT (fname[1] IN [#65..#90]) THEN
          BEGIN
            Beep;
            TempMessageBox(30,14,Black,yellow,1,'Must begin with a letter!')
          END;  { IF }
        FOR j:=1 TO Length(fname) DO
          BEGIN
            IF fname[j] IN notallowed THEN valid := FALSE;
            IF fname[j] = #32 then nospace := FALSE;
          END;  { for j }
        IF NOT valid THEN  BEGIN
            Beep;
            IF NOT nospace THEN
              TempMessageBox(30,14,Black,yellow,1,'Can''t use spaces!')
            ELSE
              TempMessageBox(30,14,Black,yellow,1,'Invalid Character!');
          END;  { if not valid }
      UNTIL (fname[1] IN [#65..#90]) AND valid;
      IF nbr=8 THEN
        fname:=fname +'.'+sufx
      ELSE
        fname:=fname +'XX.'+sufx;
      RmWin;
    END;  { Ask_Filename }

  PROCEDURE DrawBackground;
    BEGIN
      Fillscreen(1,1,80,22,white,blue,chr(177));
      ClearText(1,23,80,25,white,blue);
      WriteCenter(24,yellow,blue,'ANL Electron Microscopy Center');
      WriteAT(11,3,yellow,blue,' Press F1 for help ');
    END;  { DrawBackground }

  PROCEDURE Credits;
    BEGIN
      Fillscreen(1,1,80,25,black,cyan,chr(177));
      Box(1,1,80,25,white,cyan,2);
      WriteCenter(3,white,cyan,' ANLCMMON ');
      WriteCenter(4,white,cyan,' CM Microscope Remote Control Program ');
      WriteCenter(5,white,cyan,' Version 1.0 ');
      WriteCenter(8,yellow,cyan,' Original (C) 1988 Copyright PHILIPS EXPORT B.V. ');
      WriteCenter(9,yellow,cyan,' All Rights Reserved ');
      WriteCenter(12,white,cyan,' Modifed by S. Ockers 9/92 ');
      WriteCenter(13,white,cyan,' Electron Microscopy Center ');
      WriteCenter(14,white,cyan,' Argonne National Laboratory ');
      WriteCenter(15,white,cyan,' 9700 S. Cass Ave. ');
      WriteCenter(16,white,cyan,' Argonne, IL 60439 ');
      WriteCenter(19,yellow,cyan,' Copies and updates available from: ');
      WriteCenter(20,yellow,cyan,' EMMPDL@ANLEMC.BITNET ');
      WriteCenter(23,black,cyan,' Press any key for Main Menu ');
      Ch := GetKey;
    END;  { Credits }

  {************************* LOGGING ROUTINES ****************************}

  PROCEDURE StartAppLog;    { Start logging in the append mode }
    BEGIN
      IF StartDisplInfo(Log_filename,TRUE) then
        BEGIN
           logging := TRUE;
           replace := FALSE;
           WhatsHappening('Append Logging is now ON',20);
        END
      ELSE
           Show_CommunicationError;
    END;  { Start AppLog }

  PROCEDURE StartRepLog;  { Start logging in the replace mode }
    BEGIN
      IF StartDisplInfo(Log_filename,FALSE) then
        BEGIN
           logging := TRUE;
           replace := TRUE;
           WhatsHappening('Replace Logging is now ON',20);
        END
      ELSE
           Show_CommunicationError;
    END;  { Start RepLog }

  PROCEDURE Print_Log(Log_Filename:StrScreen);
  { Prints the contents of file  on line printer }
    var ok        : boolean;
        IO_File   : Text;
    begin
{$I-}
      Assign(IO_File,Log_Filename);
      ok := (IOResult = 0);
      if ok then begin
        Reset(IO_File);
        ok := (IOResult=0);
      end;
      if ok then
        While not EOF(IO_File) do begin
          Read(IO_File,ch);
          Write(LST,ch)
        end;
      ok := ok and (IOResult = 0);
      if ok then
        Close(IO_File);
{$I+}
      if not ok then
        Show_FileReadError(log_Filename);
    end;

  PROCEDURE Screen_Log(Log_Filename:StrScreen);
  { Prints the contents of file on screen }
    var ok        : boolean;
        IO_File   : Text;
        cnt       : Byte;
        ch        : Char;
    begin
      ClrScr;
{$I-}
      Assign(IO_File,Log_Filename);
      ok := (IOResult = 0);
      if ok then begin
        Reset(IO_File);
        ok := (IOResult=0);
      end;
      if ok then
        cnt := 0;
        While not EOF(IO_File) do begin
          Read(IO_File,ch);
          IF ch = #10 THEN Inc(cnt);
          IF cnt = 18 THEN BEGIN
             cnt := 0; ch := ReadKey;
          END;  { IF cnt }
          Write(output,ch)
        end;
        ch := ReadKey;
      ok := ok and (IOResult = 0);
      if ok then
        Close(IO_File);
{$I+}
      if not ok then
        Show_FileReadError(log_Filename);
    end;

   PROCEDURE PrntrLogOut;      { Checks if everything O.K. to print Log }
     VAR tempfile : Strscreen;
         sel : Boolean;
     BEGIN
       IF logging THEN
         BEGIN
          FBox(20,13,60,18,yellow,red,2);
          WriteAt(25,14,yellow,red,'Must stop logging before printing');
          Read_YN(29,16,'Wish to stop logging?',1,sel);
          IF sel = TRUE THEN
            BEGIN
              IF StopDisplInfo THEN
                BEGIN
                    Logging := FALSE;
                    WhatsHappening('Logging is now OFF',20);
                  END
                ELSE
                Show_CommunicationError;
            END  { If sel = True }
            ELSE
              Exit;
         END;  { If logging }
       IF NOT Logging THEN
         BEGIN
           tempfile := Display_Directory('*.LOG',errcode);
           IF errcode = 0 THEN
             BEGIN
               tempfile := File_Name(tempfile)+'.LOG';
               IF NOT Printer_Ready THEN
                 TempMessageBox(28,15,yellow,red,2,'   Check the Printer!   ')
               ELSE
                 Print_Log(tempfile);
             END;  { If errcode }
           END;  { If Not Logging }
    END;  { PrntrLogout }

   PROCEDURE ScrnLogOut;        { Checks if everything O.K. for Screen Log }
     VAR tempfile : Strscreen;
         sel      : Boolean;
     BEGIN
       IF Logging THEN
         BEGIN
          FBox(20,13,60,18,yellow,red,2);
          WriteAt(25,14,yellow,red,'Must stop logging before printing');
          Read_YN(29,16,'Wish to stop logging?',1,sel);
          IF sel = TRUE THEN
            BEGIN
              IF StopDisplInfo THEN
                BEGIN
                    Logging := FALSE;
                    WhatsHappening('Logging is now OFF',20);
                  END
                ELSE
                Show_CommunicationError;
            END  { If sel = True }
            ELSE
              Exit;
         END;  { If logging }
         IF NOT Logging THEN
         BEGIN
           tempfile := Display_Directory('*.LOG',errcode);
           IF errcode = 0 THEN
             BEGIN
               tempfile := File_Name(tempfile)+'.LOG';
               Screen_Log(tempfile);
             END;  { If errcode }
           END;  { Else }
    END;  { ScreenLogout }

  PROCEDURE LogOptions;
    VAR i : Integer;
        sel : Boolean;
    BEGIN
      choice2 := 1;
      WriteCenter(21,yellow,blue,' Press Esc to return to Main Menu ');
      DisplayMenu(L,true,choice2,Retcode);
      CASE choice2 OF
        1 : IF NOT Logging THEN
              BEGIN
                Mkwin(15,13,65,23,white,blue,1);
                WriteCenter(15,white,blue,'Information from the microscope');
                WriteCenter(16,white,blue,'may be appended to a file on');
                WriteCenter(17,white,blue,'disk or may replace that file');
                WriteCenter(18,white,blue,'each time a new set of data is');
                WriteCenter(19,white,blue,'available.');
                Read_YN(22,21,'Do you wish to append data (Y/N)? ',0,sel);
                Rmwin;
                IF R_Char = #27 THEN Exit;
                IF sel = TRUE THEN
                   BEGIN
                     Ask_Filename('Append Logging',8,Log_Filename,'LOG');
                     IF R_Char = #27 THEN Exit ELSE StartAppLog;
                   END;
                IF sel = FALSE THEN
                   BEGIN
                     Ask_Filename('Replace Logging',8,Log_Filename,'LOG');
                     IF R_Char = #27 THEN Exit ELSE StartRepLog;
                   END;
              END;
        2 : IF Logging THEN
              IF StopDisplInfo THEN
                BEGIN
                  Logging := FALSE;
                  WhatsHappening('Logging is now OFF',20);
                END
              ELSE
                Show_CommunicationError;
        3 : PrntrLogOut;               { Log to Printer }
        4 : ScrnLogOut;                { Log to Screen }
      END;    { Case }
      if Port2 then i := 2 else i := 1;
      if (not IOCtl(9600,i)) or
          (not OpenRemoteCM) or (not EquipmentAvailable) then
                Show_CommunicationError;
    END;  { SelectOptions }

  PROCEDURE ChooseBaud;
    VAR choice : Byte;
        i,rate : Integer;
        ratestr : String[4];
    BEGIN
      rate := 9600;
      MkWin(15,17,70,19,white,blue,1);
      Read_Select(22,18,'Baud Rate:  ','9600 4800 2400 1200 600 300 150',choice);
      RmWin;
      CASE choice OF
        1 : BEGIN rate := 9600; ratestr := '9600'; END;
        2 : BEGIN rate := 4800; ratestr := '4800'; END;
        3 : BEGIN rate := 2400; ratestr := '2400'; END;
        4 : BEGIN rate := 1200; ratestr := '1200'; END;
        5 : BEGIN rate := 600; ratestr := '600'; END;
        6 : BEGIN rate := 300; ratestr := '300'; END;
        7 : BEGIN rate := 150; ratestr := '150'; END;
      END;  { Case }
      IF Port2 THEN i := 2 ELSE i := 1;
      IF (NOT IOCtl(rate,i)) OR
          (NOT OpenRemoteCM) OR (NOT EquipmentAvailable) THEN
                Show_CommunicationError
      ELSE TempMessageBox(30,16,white,blue,1,'Baud Rate is '+ratestr);

    END;

  PROCEDURE IsThere;
    BEGIN
      IF EquipmentAvailable THEN
        TempMessageBox(26,16,white,blue,1,' Microscope is Available ')
      ELSE
        TempMessageBox(24,16,yellow,red,1,
                                      ' Microscope is NOT Available ');
    END;

  PROCEDURE ComOptions;
    VAR i : Integer;
    BEGIN
      choice2 := 1;
      WriteCenter(21,yellow,blue,' Press Esc to return to Main Menu ');
      DisplayMenu(C,true,choice2,Retcode);
      CASE choice2 OF
        1 : BEGIN
              Port2 := FALSE;                         { Switch to COM1 }
              WhatsHappening('Switching to COM1',20);
            END;
        2 : BEGIN
              Port2 := TRUE;                          { Switch to COM2 }
              WhatsHappening('Switching to COM2',20);
            END;
        3 : ChooseBaud;
        4 : IsThere;
      END;    { Case }
      if Port2 then i := 2 else i := 1;
      if (not IOCtl(9600,i)) or
          (not OpenRemoteCM) or (not EquipmentAvailable) then
                Show_CommunicationError;
    END;  { SelectOptions }

    PROCEDURE Paramscreen;    { Parameters from scope put on screen }
      TYPE onedata = RECORD
             x,y  : Byte;  { leftmost coords }
             strg : String[9];  { title }
             valu : Real;
           END; { onedata }

      CONST scrd : ARRAY[1..32] OF onedata =
         ( ( x:3;y:7;strg:'  C1:';valu:0.00 ),
           ( x:3;y:9;strg:'  C2:';valu:0.00 ),
           ( x:3;y:11;strg:'TWIN:';valu:0.00 ),
           ( x:3;y:13;strg:' OBJ:';valu:0.00 ),
           ( x:3;y:15;strg:' DIF:';valu:0.00 ),
           ( x:3;y:17;strg:' INT:';valu:0.00 ),
           ( x:3;y:19;strg:'  P1:';valu:0.00 ),
           ( x:3;y:21;strg:'  P2:';valu:0.00 ),
           ( x:44;y:7;strg:'Gun UX:';valu:0.00 ),
           ( x:44;y:8;strg:'Gun UY:';valu:0.00 ),
           ( x:44;y:9;strg:'Gun LX:';valu:0.00 ),
           ( x:44;y:10;strg:'Gun LY:';valu:0.00 ),
           ( x:44;y:11;strg:' BD_UX:';valu:0.00 ),
           ( x:44;y:12;strg:' BD-UY:';valu:0.00 ),
           ( x:44;y:13;strg:' BD-LX:';valu:0.00 ),
           ( x:44;y:14;strg:' BD-LY:';valu:0.00 ),
           ( x:44;y:15;strg:' ID-UX:';valu:0.00 ),
           ( x:44;y:16;strg:' ID-UY:';valu:0.00 ),
           ( x:44;y:17;strg:' ID-LX:';valu:0.00 ),
           ( x:44;y:18;strg:' ID-LY:';valu:0.00 ),
           ( x:23;y:7;strg:' C2-X:';valu:0.00 ),
           ( x:23;y:9;strg:' C2-Y:';valu:0.00 ),
           ( x:23;y:11;strg:' OB-X:';valu:0.00 ),
           ( x:23;y:13;strg:' OB-Y:';valu:0.00 ),
           ( x:23;y:15;strg:'DIF-X:';valu:0.00 ),
           ( x:23;y:17;strg:'DIF-Y:';valu:0.00 ),
           ( x:69;y:8;strg:'';valu:0.00 ),
           ( x:69;y:11;strg:'';valu:0.00 ),
           ( x:69;y:14;strg:'';valu:0.00 ),
           ( x:69;y:17;strg:'';valu:0.00 ),
           ( x:23;y:23;strg:'Emission:';valu:0.00 ),
           ( x:23;y:24;strg:'  Screen:';valu:0.00 )
            );
            curmax = 60000.0;
            maxtime : Byte = 60;
      VAR  c : CurrentType;
           p : PressureType;
           iscreen,iemission : Real;
           j,timer : Byte;
           ch : Char;
      BEGIN
        timer := maxtime;
        REPEAT
         Clrscr;  FBox(20,15,60,17,white,blue,2);
         WriteCenter(16,white,blue,'Getting Microscope Parameters');
         IF NOT CurrentReadout(c) THEN Show_CommunicationError;
         IF NOT PressureReadout(p) THEN Show_CommunicationError;
         IF NOT ScreenCurrent(iscreen) THEN Show_CommunicationError;
         IF NOT EmissionCurrent(iemission) THEN Show_CommunicationError;
         FOR j:=1 TO 26 DO
           BEGIN
             IF Abs(c[j])>curmax THEN c[j] := 0;
             scrd[j].valu := c[j];
           END;
         FOR j:=27 TO 30 DO
           BEGIN
             IF Abs(p[j-26])>curmax THEN p[j-26] := 0;
             scrd[j].valu := p[j-26];
           END;
         IF Abs(iemission)>curmax THEN iemission :=  0.00;
         IF Abs(iscreen)>curmax THEN iscreen :=  0.00;
         scrd[31].valu := iemission; scrd[32].valu := iscreen;
         TextBackground(BLACK); TextColor(WHITE); ClrScr;
         WriteCenter(2,white,cyan,' Microscope Parameters ');
         WriteAt(7,4,white,blue,' LENSES ');
         Box(1,5,19,23,white,blue,2);
         WriteAt(47,4,white,blue,' DEF COILS ');
         Box(42,5,60,20,white,blue,2);
         WriteAt(26,4,white,blue,' STIGMATORS ');
         Box(21,5,40,19,white,blue,2);
         WriteAt(67,4,white,blue,' VACUUM ');
         Box(62,5,80,19,white,blue,2);
         WriteAt(66,7,white,black,'Buffer Vac');
         WriteAt(68,10,white,black,'Prevac');
         WriteAt(65,13,white,black,'Proj Chamber');
         WriteAt(68,16,white,black,'Column');
         Box(21,22,42,25,white,blue,2);
         WriteAt(23,21,white,blue,' OTHER CURRENTS ');
         Fbox(45,21,80,25,white,blue,2);
         WriteAt(48,22,yellow,blue,' Space - Update ');
         WriteAt(47,23,yellow,blue,' B,Esc - Main Menu ');
         WriteAt(46,24,yellow,blue,' F2 - Set Auto Update ');
         FOR j:=1 TO 32 DO
           BEGIN
             GotoXY(scrd[j].x,scrd[j].y);
             CASE j OF
              1..26 :  Write(scrd[j].strg+' ',scrd[j].valu:8:2);
              27..30 : Write(scrd[j].strg+' ',scrd[j].valu:4:0);
              31,32  : Write(scrd[j].strg+' ',scrd[j].valu:8);
             END;  { Case }
           END;  { For j }
         IF maxtime <> 0 THEN
           BEGIN
             WriteAT(67,22,white,blue,' Update in: ');
             WriteAT(72,23,white,blue,' Sec ');
             TextBackground(Blue);
             REPEAT
               GotoXY(69,23); Write(timer:3);
               Delay(1000); Dec(timer);
             UNTIL Keypressed OR (timer=0);
             timer := maxtime;  TextBackground(Black);
             IF KeyPressed THEN ch := GetKey;
           END  { If maxtime <> 0 }
           ELSE
             ch := GetKey;
           IF ch = #188 THEN
             BEGIN
               ClrScr;
               Fbox(20,8,60,19,white,blue,2);
               WriteCenter(10,white,blue,' Automatic Update Setting ');
               WriteCenter(11,white,blue,' A timer can be set to automatically ');
               WriteCenter(12,white,blue,' update parameters from the microscope ');
               WriteCenter(13,white,blue,' at intervals of 1 to 255 seconds. If ');
               WriteCenter(14,white,blue,' set to 0, only a keypress will ');
               WriteCenter(15,white,blue,' update the screen. ');
               Read_Byte(30,17,3,' Update Time (0-255): ',0,maxtime,0,255);
               timer := maxtime;  ch := #0;
             END;
        UNTIL (ch = #27) OR (UpCase(ch) = #66);
      END;  { Paramscreen }

{ ********************** Main Program **************************** }

BEGIN
    Define_M; Define_S; Define_R; Define_L; Define_C;
    WITH RTTT DO
      BEGIN
        FCol := WHITE;
        BCol := BLUE;
        PFCol := WHITE;
        PBCol := BLUE;
        HiFCol := WHITE;
        HiBCol := BLUE;
        RightJustify := TRUE;
        BegCursor := TRUE;
        EraseDefault := TRUE;
        End_Chars := [#13,#188,#27];
      END;  { With }
    WITH DTTT DO
      BEGIN
        AllowInput := FALSE;
      END;
    IF OpenRemoteCM THEN
        IF NOT IOCtl(9600,2) THEN Show_CommunicationError;
    IF NOT EquipmentAvailable THEN
          Show_CommunicationError;
    Choice := 1;
    OffCursor;
    Credits;
    REPEAT
      DrawBackground;
      DisplayDefaults;
      DisplayMenu(M,true,Choice,Retcode);
      CASE Choice OF
        1 : BEGIN                                       { Store Settings }
               choice2 := 1;
               WriteCenter(21,yellow,blue,' Press Esc to return to Main Menu ');
               DisplayMenu(S,true,choice2,Retcode);         { Store Menu }
               IF Retcode=1 THEN choice2 := 0;  { no action - return }
               CASE choice2 OF
                1 : BEGIN                                   { STORE ALGN }
                      Ask_Filename('Alignments',8,Algn_Filename,'ALG');
                      IF R_Char <> #27 THEN
                        BEGIN
                          WhatsHappening('Storing Microscope Alignments to Disk',20);
                          GetAlignment;
                        END;  { If }
                    END;
                2 : BEGIN                                  { STORE STIG }
                      Ask_Filename('C2 Sigmator',8,Stig_Filename,'STG');
                      IF R_Char <> #27 THEN
                        BEGIN
                          WhatsHappening('Storing Stigmator Settings to Disk',20);
                          Get_Stigmator;
                        END;  { If }
                    END;
                3 : BEGIN                                 { STORE MODE }
                      Ask_Filename('Mode',8,Mode_Filename,'MOD');
                      IF R_Char <> #27 THEN
                        BEGIN
                          WhatsHappening('Storing Mode Settings to Disk',20);
                          Get_Mode;
                        END;  { If }
                    END;
                4 : BEGIN                                 { STORE All }
                      Ask_Filename('All Settings',6,AllSet_Filename,'ALL');
                      IF R_Char <> #27 THEN
                        BEGIN
                          WhatsHappening('Storing All Settings to Disk',20);
                          GetAllSettings;
                        END;  { If }
                    END;

               END;  { Case choice 2 }

            END;
        2 : BEGIN                                  { Recall Settings }
               choice2 := 1;
               WriteCenter(21,yellow,blue,' Press Esc to return to Main Menu ');
               DisplayMenu(R,true,choice2,Retcode);
               IF Retcode=1 THEN choice2 := 0;  { no action - return }
               CASE choice2 OF
                1 : BEGIN                               { RECALL ALGN }
                      Ask_Filename('Alignments: ',8,Algn_Filename,'ALG');
                      IF R_Char <> #27 THEN
                        BEGIN
                          WhatsHappening('Getting Algnment Settings Into Microscope From Disk',20);
                          SetAlignment;
                        END;  { If }
                    END;
                2 : BEGIN                                { RECALL C2 }
                      Ask_Filename('C2 Sigmator',8,Stig_Filename,'STG');
                      Stig_Choice := C2;
                      IF R_Char <> #27 THEN
                        BEGIN
                          WhatsHappening('Getting C2 Stigmator Settings Into Microscope From Disk',20);
                          Set_Stigmator;
                        END;  { If }
                    END;
                3 : BEGIN                              { RECALL OBJ }
                      Ask_Filename('Obj Sigmator',8,Stig_Filename,'STG');
                      Stig_Choice := Obj;
                      IF R_Char <> #27 THEN
                        BEGIN
                          WhatsHappening('Getting OBJ Stigmator Settings Into Microscope From Disk',20);
                          Set_Stigmator;
                        END;  { If }
                    END;
                4 : BEGIN                             { RECALL DIF }
                      Ask_Filename('Dif Sigmator',8,Stig_Filename,'STG');
                      Stig_Choice := Dif;
                      IF R_Char <> #27 THEN
                        BEGIN
                          WhatsHappening('Getting DIF Stigmator Settings Into Microscope From Disk',20);
                          Set_Stigmator;
                        END;  { If }
                    END;
                5 : BEGIN                           { RECALL MODE }
                      Ask_Filename('Mode',8,Mode_Filename,'MOD');
                      IF R_Char <> #27 THEN
                        BEGIN
                          WhatsHappening('Getting Mode Settings Into Microscope From Disk',20);
                          Set_Mode;
                        END;  { If }
                    END;
                6 : BEGIN                           { RECALL All }
                      Ask_Filename('All Settings',6,AllSet_Filename,'ALL');
                      IF R_Char <> #27 THEN
                        BEGIN
                          WhatsHappening('Getting All Settings Into Microscope From Disk',20);
                          SetAllSettings;
                        END;  { If }
                    END;
               END;  { Case choice 2 }
           END;
        3 : BEGIN
              WriteCenter(21,yellow,blue,' Press Esc to return to Main Menu ');
              tempfile := Display_Directory('\*.*',errcode); { Directory }
            END;
        4 : LogOptions;                                      { Logging }
        5 : Paramscreen;                       { Microscope Parameters }
        6 : ComOptions;                                { Communication }
        7 : BEGIN TextBackground(black);            { Blank the Screen }
            Clrscr; ch := ReadKey; END;
      END    { Case }
    UNTIL Choice = 8;                                           { Quit }
    Reset_StartUp_Mode;
    Clrscr;
    IF logging THEN logging := StopDisplInfo; { Stop Logging before quit }
end.


