MAB Title

        From: Deckard
          To: BluPhoenyx (comp.sys.apple2)
        Date: oct 2 2007
Last updated: may 17 2008


Introduction

<waiting for Mike's introduction txt>

...
My main purpose was to get the thing released and hope some enterprising souls would create something new. The II's could really use some new software.
I've had a program in the back of my mind which I've wanted to write for some time and have been looking for the system I want to write it in. I'm not sure if MAB (or the GS version) is it yet but it has a lot of possibilities.
...




Maintenant, vous n'avez plus d'excuses pour écrire des programmes BASIC qui rament...

High Speed BASIC


MAB is a now a FREEWARE

Mike Thomas aka BluPhoenyx nous apprend qu'il a obtenu la reclassification en freeware de Micol Advanced Basic, les versions 8 bits et GS.

Voici le message de l'ancien éditeur l'attestant:

From: "benarnold" <benarnold_at_estrellafilms_dot_ca>
To: <bluphoenyx@**********.com>
Subject: Micol Advanced Basic

Date: Fri, 11 Apr 2008 07:34:26 -0400


Dear Mr. Thomas:
 
    I would be most happy to release Micol BASIC (8 bit) and Micol Advanced BASIC (16 bit) as freeware but I would like to retain the copyright.
Unfortunately, I can't help by supplying manuals or software. I'm no longer in the computer business and do all my work on a PC 
nowadays (I burnt out my Apple II GS years ago).
People have to understand I can not supply technical help and have no responsibility for their use of the software.
Please let me know what you need from me.
 
    A few years ago I helped a gentleman do what you wish to do. What became of that I have no idea.
You might try investigating if there is already a freeware version of my product.
 
    I appreciate the gesture sending the stamped return envelope, but you need to know US stamps work only in the US and territories (I'm in Canada).
 
    Thank you for your enquiry, and good luck with what you are doing.
My primary goal was never the money but rather to provide people with a useful programming tool.
It's a shame Apple decided to discontinue the Apple ][ line.
 
    Sincerely;
    Stephen Brunier
    (former) president
    Micol System (now defunct)


From the Editor


MAB 8 bits : documentation, image disks and screens

==> Documentation complète de mon original acheté auprès de l'éditeur canadien au début des années 90.

MAB version 4.5 pour ordinateur Apple II 8 bits est composé d'une doc reliée prévue pour la version 4.0 et un fichier complémentaire spécial 4.5 présent sur une diskette.

Quelques scans de mes achats: le soft de base et les extensions (utilitaires et programmes pour avoir un look "desktop" dans les applications programmées).
Par contre il me manque leur assembleur maison: le System M2000. Si vous avez ça j'aimerai bien regarder à quoi ça ressemble...

J'ai mis sur cette page des exemples de sources pour donner une idée du style de programmation possible.


Scan
Scan

Scan
Scan

Scan
Scan
Scan
Scan

Scan
Scan
Scan


PDF
Format A4 (10 MBytes)
Download Manual for MAB 4.0
PDF
193 kb
Download Support docs for MAB
800k
ProDOS 8
Download MAB 4.5 800k disk
dsk
ProDOS 8
Download MAB 4.5 Master 140k disk (front)
dsk
ProDOS 8
Download MAB 4.5 Master 140k disk (back)
dsk
ProDOS 8
Download MAB 4.5 Desktop Contruction Set 140k disk (front)
dsk
ProDOS 8
Download MAB 4.5 Desktop Contruction Set 140k disk (back)
dsk
ProDOS 8
Download MAB 4.5 Utilities 140k disk (front)
dsk
ProDOS 8
Download MAB 4.5 Utilities 140k disk (back)


MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen
MAB screen


Welcome MAB


MAB GS (16 bits)

Docs and image disks are available at Mark Percival's web site.
Click on the Apple IIGS picture to open a new window with this content: GS



Version GS


Sommaire


Lien Contenu
Voir Main disk : info doc.
Voir Source: Disk Utility.
Voir Source: Draw Shape.
Voir Source: Font.
Voir Source: Indenter.
Voir Source: Mouse Alias.
Voir Desktop Construction Set.
Voir Source: ASCII.
Voir Source: Calculator.
Voir Source: Filer.
Voir Source: Info.


Main disk : info doc.


                                                      15 September, 1992


      Supplemental information to Micol Advanced BASIC e/c, Version 4.5


    You will find the Micol Program Launcher, file MICOL.LAUNCHER, in the
folder LAUNCHER.  If the Micol Program Launcer had been contained under the
volume directory, it would have executed rather then placing you within the
Advanced BASIC programming environment.

-------------------------------------------------------------------------------

                           Random Number Seed Change

  In versions of Micol Advanced BASIC e/c prior to Version 4.01, the random
number seen was located at locations $C9 and $CA.  This location has now been
changed to locations $4E and $4F (78 and 79 decimal).

  It was necessary to change these locations because the real random number
generator could cause a crash if used in conjunction with a GET, INPUT or
INKEY command.

  If you were reseeding either the integer random number generator, or the
real random number generator by POKEing values into $C7 and/or $C8, you will
have to modify this code.

-------------------------------------------------------------------------------

                         Powerful New Micol Debugger


     Version 4.5 has added a very powerful debugging tool which should be a
great assistance to you in your program development.

     Under Applesoft, it was possible to interrupt a program during its
execution and display the values selected variables have.  This is now
possible under Micol Advanced BASIC.  You may then continue the program's
execution, and interrupt the program's execution as many times as you wish.



                           Displaying Variable Data


    If, during the program's execution, you press <CTRL> C, the program
executes a STOP or END or you press <CTRL> @ (hold down the CONTROL key, the
SHIFT key and press the digit 2), the program will halt and enter the Shell.
You may then interrogate the program to determine the values set by the
program's execution.  You have the following commands to accomplish this:


  PRINT <Variable name>

     PRINT is used to display the variable's value.  A space must separate the
PRINT from the actual variable name.  Any type variable may be printed,
including boolean.  If the variable is an array, include the '(' immediately
after the actual variable name (without a space inbetween).  As in Applesoft,
a question mark (?) may be used as a substitute for PRINT (again with a space
following the ?).


  Example:

    PRINT Real
    PRINT Integer%
    PRINT String$
    ? Boolean!
    PRINT Real_Array(
    ? Integer_Array%
    ? String_Array$(
    ? Boolean_Array(


    Arrays will be displayed from the beginning of the array to the end.
The element numbers will be displayed first followed by the data.  Once
a screen is full, the display will halt waiting for a key to be pressed.
Press <CTRL> C to stop the display, any other key will continue.  Arrays of
any number of dimensions (up to 14) may be displayed.

  You may also see the values of local variables, but you must make use of
the LOCAL command to do this.


  LOCAL <FUNC or PROC Name>

  LOCAL is used to tell the debugger that you are looking for a variable
in the specified Function or Procedure.  Once set, this will cause PRINT
to first search the variable as a Global variable.  If not found, it will
search for the variable as a local (local to the stipulated subroutine)
variable.  If the subroutine cannot be found, an error message will be
printed and the system set to look for Global variables.

  Example:

    LOCAL Dec_To_Hex
    PRINT Local_Variable
    PRINT Global_Variable

    When a local variable's data is printed, the debugger states that the
variable is local and then prints the data.  If the variable is global, no such
message is printed.



  Restrictions

  The following restrictions to the use of PRINT and LOCAL apply:

  1.  You must have just compiled the program. This places the symbol table
into memory for the debugger to access.  Your program has no need for the
Symbol Table during execution, but the debugger uses it to determine the
appropriate addresses.

  2.  Strings may not be in High buffer.  The compiler informs you after
compilation where the strings are stored.  If the compiler says that string
buffer is in High Memory, do not use these commands.  This is because the
strings will overwrite the Symbol Table if the strings are in High Buffer.

  3.  You may not enter the Editor to look at the program and then continue.
Make use of the Shell LIST command instead.



                    Program Continuation after Interruption


    Once you have seen the variables' values, you may wish to continue
execution of your program.  As in Applesoft, the CONT command will perform
this function.


  CONT

  If the program's execution was interrupted with a <CTRL> @ or STOP, you
may cause the program to continue execution with the CONT command.  The
previous screen will be restored, and the program will continue execution
as if there was no interruption.

    You may have to press the <CTRL> @ key longer than you would a <CTRL> C
key as the system checks more frequently for <CTRL> C. As with <CTRL> C, GET
treats <CTRL> @ as any other input.  If there are frequent uses of INKEY in
your program, <CTRL> @ may need to be held down even longer than usual.

     You may want to see the data in variables at selected times.  Simply
place the STOP command at appropriate locations in your program.  When the
program halts it will inform you at which line.  You can then interrogate
the variables and then CONT the program.

    If you attempted to continue a program that was terminated with other than
the <CTRL> @ or STOP, the CONT command will be ignored.


  Restrictions on CONT:

  1.  The object file name (the executing code) must have the same name
(with the appropriate .BIN extension) as the source code.  If you use
<OPTION> K from the editor to compile the program, or compile from the
Shell without compiling to an alternate object file name (don't use the
comma in the COMPILE command), you should be okay.  This is the case because
the object file must be loaded each time you issue the CONT command (the Shell
resides in the same location as the object code).

  2.  The program may have neither the OPTIMIZ (or NOLINE) nor NOT_C compiler
option.  These compiler options turn off the <CTRL> @ ability, without which
will not be able to CONTinue your program.

  3.  No files may have been open.  These files were closed when you
interrupted your program, and you will probably receive an error when you
CONT the program.

  4.  No graphics may be used.  All graphics were turned off when the program
was interrupted.


  As you might imagine, a great deal of thought and effort was made in order
to implement these commands.  Make this effort worth while by making good use
of these commands.

PLEASE INFORM ME IF YOU SHOULD ENCOUNTER ANY BUGS. THANK YOU.

-------------------------------------------------------------------------------

                         Output to Screen and Printer

    Once you have turned the printer on with a PRTON, it is still possible
to send messages to the screen as well as the printer.

    If you stipulate a PRINT with a relative file number of 9 (as if you were
writting to a file you had opened with a 9), all output within this statement
will be directed to the screen and the PRTON will be ignored.  Do not attempt
to open a file with 9 as this is unnecessary and will be treated as an error.

Example:

  PRTON
  PRINT "This text will go to the printer."
  PRINT (9) "This text will go to the screen."
  PRINT "This text will go to the printer again"


IMPORTANT Zero Page Modification:

    In order to support this command, we had to move CH (previous zero page
location of 36) and CV (previous zero page location of 37) to locations
$EB (235) and $EC (236) respectively.  These locations determine the current
horizontal and vertical cursor positions and had to be moved because the ROM
routine which sends output to the printer also makes use of these locations.
We're sorry about this change, but it was unavoidable.  Any program which used
these locations will have to be modified before being compiled under version
4.5.


-------------------------------------------------------------------------------

              Passsing a Parameter to a Machine Language Routine


    The LINK command now accepts an optional parameter enclosed within
square brackets.  This parameter may be a variable of type: Integer (or Integer
Literal), Real, String, Integer array, Real array, or String array.

    When your machine language routine is entered, the X register will contain
the least significant byte (LSB) of the parameter's address and the Y register
will contain the most significant byte (MSB) of the parameter's address (the
same as the address in the symbol table).  If the variable is a single
dimensioned array (you must include the left parenthesis in your code to
inform the compiler you are passing an array), these registers will contain
the address of element zero of the array, otherwise the actual address of the
variable will be passed.

     The calculation of the array address assumes you are passing a one
dimentional array.  Although any array may be passed, one dimentional arrays
simplify the access of each element greatly (each element is sequential with
a one dimentional array, but not with multiple dimensioned arrays).

Example:

    DIM Integer_Array% (100)
    FOR Ctr% = 0 TO 100
         Integer_Array% (Ctr%) = (Ctr% * 2) + 1
    NEXT Ctr%
    LINK "MLFILE.B" [Integer_Array% ( ]
{ Rest of code }

  The linked in machine code will reside in Main memory where your program
code resides, while the data you need to access resides in Auxiliary memory.
This means you cannot directly access the data from your binary code as any
attempt to bank switch Auxiliary memory for reading will crash the computer.
However, it is not difficult to move the data from Auxiliary memory to Main
memory using the built in (ROM) AUXMOVE routine.  The following code
demonstrates how to do this.

    Note that an additional move will be necessary if you are accessing string
data (be certain to check if string buffer is in High memory (the Compiler
will inform you at the end of compilation) as this will require an additional
move and more care (be certain to restore the Bank switching to its original
setting if doing this).

;
;**********************************************************
; This routine demonstrates the use of the LINK command   *
; when passing an integer array.  The values must be      *
; moved from Auxiliary memory, were data resides, to      *
; Main memory where the code resides.  Apple's  AUXMOVE   *
; ROM routine is used to make the move.  AUXMOVE is       *
; described in your Apple IIe or Apple IIc reference      *
; manual.                                                 *
;                                                         *
; The Micol Macro assembler was used to create this code, *
; your assembler may be somewhat different.               *
;**********************************************************
;
INT           EQU $A0             Safe Zero Page loction
COUT1         EQU $FDF0           Monitor character output routine
PRBYTE        EQU $FDDA           Monitor Hexadecimal data output
              TYP 6               Make a Binary file
              ORG $1000           This address will be relocated by the Linker
              STX INT             Address of integer array passed after the link
              STY INT+1
              STX $3C             Source address of data (array address)
              STY $3D
              CLC
              LDA $3C
              ADC #202            Move 202 bytes, Array was DIMed at 100
              STA $3E
              LDA $3D
              ADC #0
              STA $3F
              LDA BUFFER_ADDR+1   Relative address of internal buffer
              STA $42
              LDA BUFFER_ADDR+2
              STA $43
              CLC                 Move from Auxiliary memory to Main memory
              JSR $C311           AUXMOVE address, will actually move data
              LDY #0
LABEL         LDA BUFFER+1,Y      Print the data to screen
              JSR PRBYTE
              LDA BUFFER,Y
              JSR PRBYTE
              LDA #$8D
              JSR COUT1
              INY
              INY
              CPY #203
              BCC LABBK
              JMP END             Skip buffer to return to MAB program
BUFFER_ADDR   LDA BUFFER          Necessary only for relative address of BUFFER
              WOR $FFFF           Tell linker data area follows
BUFFER        RES $100            Buffer to which data will be moved
END           NOP                 Dummy statement for END label

-------------------------------------------------------------------------------

                           The Micol Advanced Utilities

     You only need to read this section if you have purchased the Micol
Advanced Utilities from us.  Otherwise, you may skip this section.

    The Micol Advanced Utilities are standard Micol Utilities described in
Part Two, Chapter One of the manual. These utilities are called: INFO, FILER,
CALCULATOR, ASCII, and FONT.

    If you only has a single drive, you must do the following to use the
utilities.  After you have booted the Micol Advanced BASIC disk, replace the
system disk with the ulilities' disk. Then enter the name of the utility you
wish to execute. Please note that the volume name of the Micol system disk
(initially MICOL.ADV.BASIC) and the utilities' disk must be identical or the
system will not know where to look when you enter the name of the utility.

    If you have a 3.5 inch disk drive, or a hard drive, copy the files in the
UTILITY folder of the Micol Advanced Utilities disk to the UTILITY folder
where Micol Advanced BASIC resides.

    The first utility you probably will wish to execute is INFO, which
describes all the utilities except FONT, which has its own internal help.

     The Micol Advanced BASIC source code to these files are on the reverse
side of the Utilities' disk within folder SOURCE.  Each source file, and its
repective utility, has the same file name, so you won't get confused.

-------------------------------------------------------------------------------


Retour au sommaire
hr docs


Source: Disk Utility.


PROGRAM Disk_Utility
@ NOT_C
@ NOGOTO
INT (A-R): STR (S-Z)
DATA 30, "A,a",35, "Alter filename"
DATA 30, "C,c",35, "Display catalog"
DATA 30, "D,d",35, "Delete file"
DATA 30, "K,k",35, "Copy file"
DATA 30, "L,l",35, "Lock file"
DATA 30, "M,m",35, "Make directory file"
DATA 30, "O,o",35, "Display online volumes"
DATA 30, "P,p",35, "Display or set default prefix"
DATA 30, "Q,q",35, "Quit disk utility"
DATA 30, "R,r", 35, "Read text file"
DATA 30, "U,u", 35, "Unlock FILE"
DIM Text_Buffer (1000)

FUNC Get_Key [Column]
  Allowed$ = "ACDFKLMOPQRUacdfklmopqru"
  HTAB (Column)
  REPEAT
    GET Char$
  UNTIL INDEX (Char$, Allowed$) > 0
  Number = ASC (Char$)
ENDFUNC [Number]

{ Request the file name
  if the inputted string is on line, delete it,
  and if an empty input, give error message. }

PROC Delete_File [ Column ]
  HTAB (Column)
  INPUT "Delete which file ? ";File_Name$
  IF LEN (File_Name$) > 0 THEN BEGIN
    IF FILE (File_Name$) THEN BEGIN
      DELETE File_Name$
    ELSE BEGIN
      PRINT TAB (Column); File_name$;" not found"
      GOSUB Hit_Key [Column]
    ENDIF
  ENDIF
ENDPROC

{ Request the file name from the user,
  If the file exists, read the file
  into a text buffer, then display
  the file one line at a time. }

PROC Read_Text_File [ Lines, Column, ADDRESS File_Name$ ]
  HTAB (Column)
  INPUT "Read which text file ";File_Name$
  Lines = 0
  IF FILE (File_Name$) THEN BEGIN
    ROPEN (8) File_Name$
    FOR Ctr = 1 TO 1000 UNTIL EOF (8)
      INPUT (8) Text_Buffer (Ctr)
      IF NOT EOF (8) THEN Lines = Ctr
    NEXT Ctr
    CLOSE (8)
    FOR Ctr = 1 TO Lines
      PRINT Ctr, Text_Buffer (Ctr)
    NEXT Ctr
  ELSE BEGIN
    PRINT TAB (Column); File_Name$;" not found"
    GOSUB Hit_Key [Column]
    PRINT
  ENDIF
ENDPROC

{ List all commands available to the user }

PROC Help_Screen [ Column ]
  HOME
  PRINT "Time ";TIME$;
  HTAB (20)
  INVERSE
  PRINT "Micol Advanced BASIC Disk Utility Commands";
  NORMAL
  HTAB (65)
  PRINT "Date ";DATE$
  VTAB (8)
  RESTORE
  FOR Ctr = 1 TO 11
    READ Column
    HTAB (Column)
    READ String$
    PRINT String$;
    READ Column
    HTAB (Column)
    READ String$
    PRINT String$
  NEXT Ctr
  PRINT
ENDPROC

{ Copy one file to a request file name,
  If original file doesn't exist, give error message,
  If second file already exists, give error message
  else do the copy. }

PROC Copy_File [ Column ]
  HTAB (Column)
  INPUT "Copy Which file ? ";File_Name$
  IF FILE (File_Name$) THEN BEGIN
    PRINT TAB (Column);"Copy ";File_Name$;" to which file ? ";
    INPUT "";File2$
    IF NOT FILE (FILE2$) THEN BEGIN
      COPY File_Name$ TO File2$
    ELSE BEGIN
      PRINT TAB (Column);"Cannot copy, ";File2$;" exists"
      GOSUB Hit_Key [ Column ]
    ENDIF
  ELSE BEGIN
    PRINT TAB (Column); File_Name$;" not found"
    GOSUB Hit_Key [ Column ]
  ENDIF
ENDPROC

PROC Rename_File [Column]
  HTAB (Column)
  INPUT "Old name of file ? ";File_Name$
  HTAB (Column)
  INPUT "New name of file ? ";File2$
  IF FILE (File_Name$) THEN BEGIN
    RENAME File_Name$ TO File2$
  ELSE BEGIN
    PRINT TAB (Column);File_Name$; "not found"
    GOSUB Hit_Key [Column]
  ENDIF
ENDPROC

{ Request prefix name, if empty, display prefix
  else set prefix to that requested   }

PROC Display_Prefix [ Column ]
  HTAB (Column)
  INPUT "Input volume name ";Vol_Name
  HTAB (Column)
  PREFIX Vol_Name
ENDPROC

{ Print a message, then delay
  until any key is pressed }

PROC Hit_Key [ Column ]
  PRINT:PRINT TAB (Column);
  INVERSE
  PRINT "Hit any key to continue";
  GET A$
  NORMAL:PRINT
ENDPROC

{ Start of main loop
  Execution begins at this point.
  This is the main body of the program. }

Quit_Flag! = FALSE
Error_fLAG! = FALSE
Text_fILE$ = ""
READ Column
ONERR GOTO Error_Trap

ROUTINE Error_Trap
  IF Error_fLAG! THEN BEGIN     { Don't execute unless error }
    HTAB (Column): INVERSE
    PRINT "Disk utility error"
    NORMAL:PRINT:PRINT
    GOSUB Hit_kEY [ Column ]
  ENDIF

{ Main loop, all control comes and goes
  through this REPEAT loop.  }

Error_Flag! = TRUE  { Allow the error trap to execute now }
REPEAT
  GOSUB Help_Screen [Column]
  Key = FN Get_Key [Column]
  CASE_OF Key

    DO 65, 97     { A,a for alter file name }
      GOSUB Rename_File [ Column ]
    ENDDO

    DO 67, 99      { C,c for catalog }
      HTAB (Column)
      INPUT "Take directory of which volume ? ";Vol_Name
      Old_Prefix$ = PREFIX$
      IF LEN (Vol_Name) > 0 THEN BEGIN
        IF FILE (Vol_Name) THEN BEGIN
          IF PEEK (48881) = 15 { DIR file? } THEN BEGIN
            PREFIX Vol_Name
            HOME
            String$ = CAT$ { Skip Directory name, we already have it }
            PRINT "Directory of ";Vol_Name
            PRINT
            PRINT " Filename"; \
            TAB (20);"Typ";TAB (26);"Size"; \
            TAB (36);"Created"; TAB (47);"Time"; \
            TAB (55);"Modified"; TAB (66);"Time"; \
            TAB (74);"EOF"
            PRINT
            REPEAT
              String$ = CAT$
              IF PEEK (48881) > 0 THEN\
              BEGIN
                CR$ = CHR$ (13)
                CR = INDEX (CR$,String$)
                First$ = LEFT$ (String$, CR)
                String$ = MID$ (String$, CR + 1)
                PRINT First$
                PRINT
              ENDIF
              PRINT String$
            UNTIL PEEK (48881) <> 0
          ELSE PRINT Vol_Name;" not a directory file"
        ELSE PRINT TAB (Column); Vol_Name;" not found"
      ELSE BEGIN     { Empty string input, default directory }
        HOME
        String$ = CAT$ {Skip Directory name, we already have it }
        PRINT "Directory of ";PREFIX$
        PRINT
        PRINT " Filename"; \
        TAB (20);"Typ";TAB (26);"Size"; \
        TAB (36);"Created"; TAB (47);"Time"; \
        TAB (55);"Modified"; TAB (66);"Time"; \
        TAB (74);"EOF"
        PRINT
        REPEAT
          String$ = CAT$
          IF PEEK (48881) > 0 THEN\
          BEGIN
            CR$ = CHR$ (13)
            CR = INDEX (CR$,String$)
            First$ = LEFT$ (String$, CR)
            String$ = MID$ (String$, CR + 1)
            PRINT First$
            PRINT
          ENDIF
          PRINT String$
        UNTIL PEEK (48881) <> 0
      ENDIF
      PREFIX Old_Prefix$
      GOSUB Hit_Key [Column]
    ENDDO

    DO 68, 100     { D, d for delete file }
      GOSUB Delete_File [ Column ]
    ENDDO

   DO 75, 107     { K,k for copy }
     GOSUB Copy_File [ Column ]
   ENDDO

    DO 76, 108     { L, l for lock }
      HTAB (Column)
      INPUT "Lock which file ";File_Name$
      IF FILE (File_Name$) THEN BEGIN
        LOCK File_Name$
      ELSE BEGIN
        PRINT TAB (Column); File_Name$;" not found"
      ENDIF
    ENDDO

    DO 77, 109     { M,m make directory }
      HTAB (Column)
      INPUT "Create which directory file ? ";File_Name$
      IF LEN (File_Name$) > 0 THEN BEGIN
        CREATE File_Name$
      ENDIF
    ENDDO

    DO 79, 111     { O, o for online }
      String = ONLINE$
      HTAB (Column)
      FOR Ctr = 1 TO LEN (String)
        Char$ = MID$ (String, Ctr, 1)
        IF ASC (Char$) = 13 THEN BEGIN
          PRINT
          HTAB (Column)
        ELSE PRINT Char$;
      NEXT Ctr
      GOSUB Hit_Key [ Column ]
    ENDDO

    DO 80, 112     { P, p for PREFIX }
      GOSUB Display_Prefix [ Column ]
      GOSUB Hit_Key [ Column ]
    ENDDO

    DO 81, 113     { Q,q for quit disk utility }
      REPEAT
        PRINT TAB (Column); "Quit, certain (Y/N) ? ";
        GET Key$:PRINT Key$
      UNTIL INDEX (Key$, "YyNn") > 0
      IF INDEX (Key$,"Yy") > 0 THEN BEGIN
        Quit_Flag! = TRUE
      ENDIF
    ENDDO

    DO 82, 114     { R, r for read text file }
      GOSUB Read_Text_File [ Lines, Column, Text_File$ ]
      INVERSE
      PRINT "End of ";Text_File$
      NORMAL: PRINT: PRINT
      GOSUB Hit_Key [ Column ]
    ENDDO

    DO 85, 117     { U,u for unlock file }
      INPUT "Unlock which file ";File_Name$
      IF FILE (File_Name$) THEN BEGIN
        UNLOCK File_Name$
      ELSE BEGIN
        PRINT TAB (Column); File_Name$;" not found"
        GOSUB Hit_KEY [ Column ]
      ENDIF
    ENDDO
  ENDCASE
UNTIL Quit_Flag!
END


Retour au sommaire
hr docs


Source: Draw Shape.


PROGRAM Draw_Example
@ OPTIMIZ
  PROC Draw_Shape [No_Of_Sides, Radius, X_Offset, Y_Offset ,\
                   Distortion, Rotation]
    Flag! = TRUE
    Step_Size = 6.28 / No_Of_Sides
    Limit = 6.28 + Step_Size
    FOR Degree_Step = 0 to Limit STEP Step_Size
      X_Cord = Radius * COS (Degree_Step + Rotation)
      Y_Cord = Radius * SIN (Degree_Step + Rotation)
      X_Step = Distortion * X_Cord + X_Offset
      Y_Step = Y_Offset - Y_Cord
      IF Flag! THEN BEGIN
        HPLOT X_Step, Y_Step
        Flag! = FALSE
      ELSE BEGIN
        Note% = RND (100) + 100
        MUSIC (Note% , 5)
        HPLOT TO X_Step, Y_STEP
      ENDIF
    NEXT Degree_Step
    HCOLOR = 0
    HPLOT 0,180
    String$ = "This object has " + STR$ (No_Of_Sides) + " Side"
    IF No_Of_Sides > 1 THEN String$ = String$ + "s"
    DRAWSTR (String$)
  ENDPROC

  REPEAT
    Color_Counter% = 0
    HOME
    REPEAT
      PRINT "Double high resolution of super double high resolution(D/S)? ";
      GET Response$
      PRINT Response$
    UNTIL INDEX (Response$,"DSds") > 0
    FOR No_Of_Sides = 3 TO 15
      IF Response$ = "D" or Response$ = "d" THEN BEGIN
        Color_Counter% = Color_Counter% + 1
        DHGR2
        HCOLOR = Color_Counter% MOD 15 + 1
        X_Offset = 75
        Y_Offset = 100
        Radius = 90
        Distortion = .5
        Rotation = 0
      ELSE BEGIN
        SDHGR2
        X_Offset = 260
        Y_Offset = 96
        Radius = 90
        Distortion = 2
        Rotation = 0
      ENDIF
      GOSUB Draw_Shape [ No_Of_Sides, Radius, X_Offset, Y_Offset,\
                         Distortion, Rotation]
      DELAY = 100
      TEXT
    NEXT No_Of_Sides
    Response$ = ""
    WHILE INDEX (Response$,"YNyn") = 0
      PRINT "Do another set (Y/N)? ";
      GET Response$
      PRINT Response$
    WEND
  UNTIL INDEX (Response$,"Nn") > 0
END


Retour au sommaire
hr docs


Source: Font.


PROGRAM Letter_Generator
@ LIST    { Show a compiled listing }
@ OPTIMIZ { Save memory, and add some speed }
@ HI_BUF  { Force string buffer into high buffer, away from graphics page }
INT (A-Z)
DIM Positions (8,8), Lines$ (196)
DIM Old_Bytes& (8)

Adr& = PEEK (224) + 256 * PEEK (225)
FOR Ctr& = 0 TO 7
  Old_Bytes& (Ctr&) = PEEK (Ctr& + Adr&)
NEXT Ctr&
Y_Size = 23
X_Size = 54


{ Draw the grid that the user will marks each "picel"
  of the character }

  PROC Draw_Grid
    IF Flag! THEN BEGIN   { Maximize the speed by moving memory }
      POKE 48881,255
      MOV_MEM 16384, 8191 AT 8191
      POKE 48881, 254
      MOV_MEM 24576, 8191 AT 8191
    ELSE BEGIN
      Flag! = TRUE
      FOR Ctr = 0 TO 8    { Draw the horizontal lines }
        HPLOT 0, Ctr * Y_Size
        HPLOT TO X_Size * 7, Ctr * Y_Size
      NEXT Ctr
      FOR Ctr = 0 TO 7    { Draw the vertical lines }
        HPLOT Ctr * X_Size, 0
        HPLOT TO Ctr * X_Size, Y_Size * 8
      NEXT Ctr
      POKE 48881,0          { Save Aux screen in main memory }
      MOV_MEM 8191, 8191 AT 16384
      POKE 48881,254        { Save Main screen in main memory }
      MOV_MEM 8191, 8191 AT 24576
    ENDIF
  ENDPROC

  PROC Help [X_Cord, Y_Cord]
    TEXT
    HOME
    PRINT TAB (35);"Help Screen"
    PRINT
    PRINT TAB (10);"The Micol Character Designer allows you to create a designer letter"
    PRINT TAB (10);"on the screen which will effect the text display on the Super Double"
    PRINT TAB (10);"HIGH Resolution screen when DRAWSTR is invoked.  The letter you"
    PRINT TAB (10);"create will replace the letter usually generated by DRAWSTR.  It"
    PRINT TAB (10);"does this by generating a program which modifies the run time"
    PRINT TAB (10);"library at the start of your program's execution."
    PRINT
    PRINT
    PRINT TAB (10);"After you have designed your character, the Letter Designer will"
    PRINT TAB (10);"prompt you for the character to replace.  This is the character"
    PRINT TAB (10);"used in DRAWSTR which will cause this character to be generated."
    PRINT TAB (10);"After you are finished designing your characters, simply make the"
    PRINT TAB (10);"program generated by the Letter Designer the start of the program"
    PRINT TAB (10);"you wish to write."
    PRINT
    PRINT
    INVERSE
    PRINT TAB (30);"Hit any key to continue ";
    NORMAL
    GET A$
    HOME
    VTAB (5)
    PRINT TAB (10);"When the Micol Character Designer starts up, it prompts you for"
    PRINT TAB (10);"a pathname.  Input any suitable ProDOS 8 pathname.  If this file"
    PRINT TAB (10);"already exists, it asks you if you wish to create a new file."
    PRINT TAB (10);"If this file has letters you have previously designed, and wish"
    PRINT TAB (10);"to retain, specify <N> to the prompt, otherwise specify <Y>."
    PRINT
    PRINT
    PRINT TAB (10);"You may design a maximum of 96 characters."
    PRINT
    PRINT
    INVERSE
    PRINT TAB (30);"Hit any key to continue ";
    NORMAL
    GET A$
    HOME
    VTAB (6)
    PRINT TAB (5);"The following keys perform the following functions:"
    PRINT
    PRINT TAB (10);"<Arrow keys>";TAB (30);"Move cursor in respective direction"
    PRINT TAB (10);"<Space bar>";TAB (30);"Toggle box marked/unmarked"
    PRINT TAB (10);"<A,a>";TAB (30);"Mark all boxes"
    PRINT TAB (10);"<E,e>";TAB (30);"Unmark all boxes"
    PRINT TAB (10);"<Q,q>";TAB (30);"Quit without further modifications"
    PRINT TAB (10);"<S,s>";TAB (30);"Show graphics display of character"
    PRINT TAB (10);"<Return>";TAB (30);"Accept character."
    PRINT
    PRINT
    INVERSE
    PRINT TAB (30);"Hit any key to continue ";
    NORMAL
    GET A$
    PRINT
    SDHGR2
    POKE 48881,255
    MOV_MEM 16384, 8191 AT 8191
    POKE 48881, 254
    MOV_MEM 24576, 8191 AT 8191
    FOR Ctr1 = 1 TO 8
      FOR Ctr2 = 1 TO 7
        IF Positions (Ctr1, Ctr2) = 1 THEN \
          GOSUB Box [Ctr2, Ctr1]
      NEXT Ctr2
    NEXT Ctr1
    GOSUB Show_Letter
    GOSUB Mark_Spot [X_Cord, Y_Cord]
  ENDPROC

{ Draw a small box at the specified location }

  PROC Box [X_Cord, Y_Cord]
    HPLOT    X_Cord * X_Size - 40, Y_Cord * Y_Size - 15
    HPLOT TO X_Cord * X_Size - 25, Y_CORD * Y_Size - 15
    HPLOT TO X_Cord * X_Size - 25, Y_Cord * Y_Size - 7
    HPLOT TO X_Cord * X_Size - 40, Y_Cord * Y_size - 7
    HPLOT TO X_Cord * X_Size - 40, Y_Cord * Y_Size - 15
  ENDPROC

{ Make a cross at the specified co-ordiantes }

  PROC Mark_Spot [X_Cord, Y_Cord]
    HPLOT X_Cord * X_Size - 32, Y_Cord * Y_Size - 10
    HPLOT TO X_Cord * X_Size - 32, Y_Cord * Y_Size - 14
    HPLOT X_Cord * X_Size - 27, Y_Cord * Y_Size - 12
    HPLOT TO X_Cord * X_Size - 37, Y_Cord * Y_Size - 12
  ENDPROC

{ Show what the actual letter will look like on the screen }

  PROC Show_Letter
    FOR Y_Cord = 1 TO 8
      Accum = 0
      Binary_Pos = 1
      FOR X_Cord = 1 TO 7
        Accum = Accum + Binary_Pos * Positions (Y_Cord, X_Cord)
        Binary_Pos = Binary_Pos * 2
      NEXT X_Cord
      POKE 8524 + (Y_Cord - 1) * 1024, Accum
    NEXT Y_Cord
  ENDPROC

{  Initialize the position buffer, set the double high
   resolution screen, position the cursor, allow the user
   to mark or unmark a position }

  PROC Make_Letter [ADDRESS Quit_Flag!]
    FOR Ctr1 = 1 TO 8
      FOR Ctr2 = 1 TO 7
        Positions (Ctr1, Ctr2) = 0
      NEXT Ctr2
    NEXT Ctr1
    SDHGR2
    GOSUB Draw_Grid
    X_Cord = 1
    Y_Cord = 1
    GOSUB Mark_Spot [X_Cord, Y_Cord]
    REPEAT
      GET Key$
      Key = ASC (Key$)
      CASE_OF Key

        DO 8              { Left arrow }
          ERASE
          GOSUB Mark_Spot [X_Cord, Y_Cord]
          ERASE
          IF X_Cord > 1 THEN BEGIN
            X_Cord = X_Cord - 1
          ELSE BEGIN
            X_Cord = 7
            IF Y_Cord > 1 THEN BEGIN
              Y_Cord = Y_Cord - 1
            ELSE BEGIN
              Y_Cord = 7
            ENDIF
          ENDIF
          GOSUB Mark_Spot [X_Cord, Y_Cord]
        ENDDO

        DO 10             { Down arrow }
          ERASE
          GOSUB Mark_Spot [X_Cord, Y_Cord]
          ERASE
          IF Y_Cord < 8 THEN BEGIN
            Y_Cord = Y_Cord + 1
            GOSUB Mark_Spot [X_Cord, Y_Cord]
          ELSE BEGIN
            Y_Cord = 1
            IF X_Cord < 7 THEN BEGIN
              X_Cord = X_Cord + 1
            ELSE BEGIN
              X_Cord = 1
            ENDIF
          ENDIF
          GOSUB Mark_Spot [X_Cord, Y_Cord]
        ENDDO

        DO 11             { Up arrow }
          ERASE
          GOSUB Mark_Spot [X_Cord, Y_Cord]
          ERASE
          IF Y_Cord > 1 THEN BEGIN
            Y_Cord = Y_Cord - 1
          ELSE BEGIN
            Y_Cord = 8
            IF X_Cord > 1 THEN BEGIN
              X_Cord = X_Cord - 1
            ELSE BEGIN
              X_Cord = 7
            ENDIF
          ENDIF
          GOSUB Mark_Spot [X_Cord, Y_Cord]
        ENDDO

        DO 21             { Right arrow }
          ERASE
          GOSUB Mark_Spot [X_Cord, Y_Cord]
          ERASE
          IF X_Cord < 7 THEN BEGIN
            X_Cord = X_Cord + 1
          ELSE BEGIN
            X_Cord = 1
            IF Y_Cord < 8  THEN BEGIN
              Y_Cord = Y_Cord + 1
            ELSE BEGIN
              Y_Cord = 1
            ENDIF
          ENDIF
          GOSUB Mark_Spot [X_Cord, Y_Cord]
        ENDDO

        DO "A", "a"     { Mark all positions as a dot }
          TEXT
          SDHGR2
          POKE 48881,255
          MOV_MEM 16384, 8191 AT 8191
          POKE 48881, 254
          MOV_MEM 24576, 8191 AT 8191
          FOR Ctr1 = 1 TO 8
            FOR Ctr2 = 1 TO 7
              Positions (Ctr1, Ctr2) = 1
              GOSUB Box [Ctr2, Ctr1]
            NEXT Ctr2
          NEXT Ctr1
          GOSUB Show_Letter
          GOSUB Mark_Spot [X_Cord, Y_Cord]
        ENDDO

        DO "Q","q"        { Quit the designer }
          Quit_Flag! = TRUE
        ENDDO

        DO "E", "e"       { Erase all dots }
          FOR Ctr1 = 1 TO 8
            FOR Ctr2 = 1 TO 8
              Positions (Ctr1, Ctr2) = 0
            NEXT Ctr2
          NEXT Ctr1
          TEXT
          SDHGR2
          POKE 48881,255
          MOV_MEM 16384, 8191 AT 8191
          POKE 48881, 254
          MOV_MEM 24576, 8191 AT 8191
          GOSUB Show_Letter
          GOSUB Mark_Spot [X_Cord, Y_Cord]
        ENDDO

        DO "?"
          GOSUB Help [X_Cord, Y_Cord]
        ENDDO

        DO " "              { Space bar will toggle marker }
          IF Positions (Y_Cord, X_Cord) = 0 THEN BEGIN
            Positions (Y_Cord, X_Cord) = 1
            GOSUB Box [X_Cord, Y_Cord]
          ELSE BEGIN
            Positions (Y_Cord, X_Cord) = 0
            ERASE
            GOSUB Box [X_Cord, Y_Cord]
            ERASE
            GOSUB Mark_Spot [X_Cord, Y_Cord]
          ENDIF
          GOSUB Show_Letter
        ENDDO

        DO "S", "s"
          TEXT
          SDHGR2
          HPLOT 240,10
          DRAWSTR ("Character Display")
          FOR Y = 1 TO 8
            Accum = 0
            Binary_Pos = 1
            FOR X = 1 TO 7
              Accum = Accum + Binary_Pos * Positions (Y, X)
              Binary_Pos = Binary_Pos * 2
            NEXT X
            POKE Adr& + (Y - 1), Accum
          NEXT Y
          HPLOT 70,90
          DRAWSTR ("   A B C D E F G H I J K L M N O P Q R S T U V W X Y Z   ")
          FOR Ctr& = 0 TO 7
            POKE Adr& + Ctr&, Old_Bytes& (Ctr&)
          NEXT Ctr&
          HPLOT 190,180
          DRAWSTR ("Hit any key to continue")
          GET A$
          TEXT
          SDHGR2
          POKE 48881,255
          MOV_MEM 16384, 8191 AT 8191
          POKE 48881, 254
          MOV_MEM 24576, 8191 AT 8191
          FOR Ctr1 = 1 TO 8
            FOR Ctr2 = 1 TO 7
              IF Positions (Ctr1, Ctr2) = 1 THEN \
                GOSUB Box [Ctr2, Ctr1]
            NEXT Ctr2
          NEXT Ctr1
          GOSUB Show_Letter
          GOSUB Mark_Spot [X_Cord, Y_Cord]
        ENDDO
      ENDCASE
    UNTIL Key = 13 OR Quit_Flag!
    TEXT
  ENDPROC

  HOME
  Num_Of_Letters = 0
  Quit_Flag! = FALSE
  Response$ = "Y"
  PRINT "Press <?> for help after grid is drawn"
  PRINT
  INPUT "Create program as what file name ? ";FileName$
  Prog_Name$ = ""
  FOR Ctr = 1 TO LEN (FileName$)
    Char$ = MID$ (FileName$, Ctr,1)
    IF Char$ = "/" THEN BEGIN
      Prog_Name$ = ""
    ELSE BEGIN
      Prog_Name$ = Prog_Name$ + Char$
    ENDIF
  NEXT Ctr
  IF Prog_Name$ = "" THEN Prog_Name$ = "No_Name"
  IF FILE (FileName$) THEN BEGIN  { If file exists, keep old info? }
    REPEAT
      PRINT FileName$;" already exists, start a new file(Y/N) ";
      GET Response$
      PRINT Response$
      Response$ = UPPER$ (Response$)
    UNTIL INDEX (Response$, "YN") > 0
    IF Response$ = "Y" THEN BEGIN
      WOPEN (1) FileName$
      PRINT (1) "PROGRAM ";Prog_Name$
      PRINT (1) "@ LIST"
      CLOSE (1)
    ELSE BEGIN      { Keep old letter info in file }
      ROPEN (1) FileName$
      INPUT (1) Prog_Name$
      INPUT (1) Line_2$
      Total_Lines = 0
      Flag! = FALSE
      REPEAT
        INPUT (1) Lines$
        IF NOT EOF (1) THEN BEGIN
          IF INDEX ("DATA ",Lines$) = 1 THEN BEGIN
            Total_Lines = Total_Lines + 1
            Lines$ (Total_Lines) = Lines$
            IF Total_Lines MOD 2 = 1 THEN \
              Num_Of_Letters = Num_Of_Letters + 1
          ELSE Flag! = TRUE
        ELSE Flag! = TRUE
      UNTIL Flag!
      CLOSE (1)
      WOPEN (1) FileName$
      PRINT (1) Prog_Name$
      PRINT (1) Line_2$
      FOR Ctr = 1 TO Total_Lines
        PRINT (1) Lines$ (Ctr)
      NEXT Ctr
      CLOSE (1)
    ENDIF
  ELSE BEGIN      { No file under this name, start a new one }
    WOPEN (1) FileName$
    PRINT (1) "PROGRAM ";Prog_Name$
    PRINT (1) "@ LIST"
    CLOSE (1)
  ENDIF
  REPEAT
    Num_Of_Letters = Num_Of_Letters + 1
    IF Num_Of_Letters < 97 { Max. of 96 characters } THEN BEGIN
      GOSUB Make_Letter [Quit_Flag!]
      IF NOT Quit_Flag! THEN BEGIN
        REPEAT
          HOME
          VTAB (10)
          INPUT "Which character will be replaced<Char><CR>>? ";Char$
        UNTIL LEN (Char$) = 1 AND ASC (Char$) > 31
        ROPEN (1) FileName$
        APPEND (1)
        PRINT (1) "DATA "; CHR$ (34);Char$;CHR$ (34)
        PRINT (1) "DATA ";
        FOR Y_Cord = 1 TO 8
          Accum = 0
          Num = 1
          FOR X_Cord = 1 TO 8
            Accum = Accum +  Num * Positions (Y_Cord, X_Cord)
            Num = Num * 2
          NEXT X_Cord
          PRINT (1) Accum;
          IF Y_Cord < 8 THEN \
            PRINT (1) ",";
        NEXT Y_Cord
        PRINT (1) ""
        CLOSE (1)
        IF Num_Of_Letters < 96 THEN BEGIN
          REPEAT
            VTAB (10)
            PRINT TAB (1);"Do another letter(Y/N) ? ";CHR$ (29);
            GET Response$
            PRINT Response$
            Response$ = UPPER$ (Response$)
          UNTIL INDEX (Response$, "YN") > 0
        ELSE Response$ = "N"
      ENDIF           { Quit_Flag! }
    ELSE Response$ = "N"
  UNTIL Response$ = "N" OR Quit_Flag!
  ROPEN  (1) FileName$
  APPEND (1)
  PRINT  (1) "PROC New_Character"
  PRINT  (1) "  Adr& = PEEK (224) + 256 * PEEK (225)"
  PRINT  (1) "  FOR Ctr1% = 1 TO ";Num_Of_Letters
  PRINT  (1) "    READ Letter$"
  PRINT  (1) "    Letter& = ASC (Letter$) - 32"
  PRINT  (1) "    Font_Addr& = Adr& + Letter& * 8"
  PRINT  (1) "    FOR Ctr2% = Font_Addr& TO Font_Addr& + 7"
  PRINT  (1) "      READ Number%"
  PRINT  (1) "      POKE Ctr2%, Number%"
  PRINT  (1) "    NEXT Ctr2%"
  PRINT  (1) "  NEXT Ctr1%"
  PRINT  (1) "ENDPROC"
  PRINT  (1) "GOSUB New_Character"
  CLOSE  (1)
  HOME
END


Retour au sommaire
hr docs


Source: Indenter.


PROGRAM Aligner
@ LIST
@ HI_BUF
@ IO_BUFS = 2
@ OPTIMIZ
INT (A-Z)
DATA "REPEAT","WHILE ","BEGIN","FOR "
DATA "PROC ","FUNC ","CASE_OF ","DO "
DATA "NEXT ","ENDIF","UNTIL ","WEND"
DATA "ENDPROC","ENDFUNC","ENDDO","ENDCASE"
DATA "ELSE "
DIM Push$ (8), Pull$ (9)
  Ok_Flag! = FALSE
  Indent = 2
  Quote$ = CHR$ (34)
  FOR Ctr = 1 TO 8
    READ Push$ (Ctr)
  NEXT Ctr
  FOR Ctr = 1 TO 9
    READ Pull$ (Ctr)
  NEXT Ctr
  HOME
  Program_Name$ = ""
  Flag! = FALSE
  FOR Ctr = 640 to 720 UNTIL Flag!
    Number = PEEK (Ctr)
    IF Number > 0 THEN BEGIN
      Program_Name$ = Program_Name$ + CHR$ (Number)
    ELSE BEGIN
      Flag! = TRUE
    ENDIF
  NEXT Ctr
  IF FILE (Program_Name$) THEN BEGIN
    IF PEEK (48881) = 4 { TXT file } THEN BEGIN
      Ok_Flag! = TRUE
      REPEAT
        INPUT "Write formatted file as which file ";Format_Name$
      UNTIL Format_Name$ <> Program_Name$
      REPEAT
        PRINT "How many spaces in each indentation(1-9)? ";
        GET Indent_Const$
        PRINT Indent_Const$
      UNTIL INDEX (Indent_Const$,"123456789") > 0
      Indent_Const = VAL (Indent_Const$)
      ROPEN (8) Program_Name$
      WOPEN (2) Format_Name$
      INPUT (8) Line$           { Do the program line }
      PRINT (2) Line$
      PRINT Line$
      REPEAT
        INPUT (8) Line$
        IF NOT EOF (8) THEN BEGIN
          IF LEN (Line$) > 1 THEN BEGIN
            Flag! = FALSE
            Len_Line = LEN (Line$)
            FOR Ctr = 1 TO Len_Line UNTIL Flag!   { Strip away leading spaces first }
              IF ASC (Line$) = 32 THEN BEGIN
                IF LEN (Line$) > 1 THEN BEGIN
                  Line$ = MID$ (Line$, 2)
                ELSE BEGIN
                  Line$ = " "
                  Flag! = TRUE
                ENDIF
              ELSE BEGIN
                Flag! = TRUE
              ENDIF
            NEXT Ctr
            IF LEFT$ (Line$,1) = "{" THEN BEGIN
              PRINT (2) Line$
              PRINT Line$
              WHILE INDEX ("}", Line$) = 0 AND NOT EOF (8)
                INPUT (8) Line$       { Skip comments }
                IF NOT EOF (8) THEN BEGIN
                  PRINT (2) Line$
                  PRINT Line$
                ENDIF
              WEND
              IF NOT EOF (8) THEN BEGIN
                INPUT (8) Line$
                Flag! = FALSE
                Len_Line = LEN (Line$)
                FOR Ctr = 1 TO Len_Line UNTIL Flag!   { Strip away leading spaces first }
                  IF ASC (Line$) = 32 THEN BEGIN
                    IF LEN (Line$) > 1 THEN BEGIN
                      Line$ = MID$ (Line$, 2)
                    ELSE BEGIN
                      Line$ = ""
                      Flag! = TRUE
                    ENDIF
                  ELSE BEGIN
                    Flag! = TRUE
                  ENDIF
                NEXT Ctr
              ELSE BEGIN          { Force a line if comment at end }
                Line$ = "END"
              ENDIF
            ENDIF
          ENDIF
          IF LEN (Line$) > 1 THEN BEGIN
            Push_Flag! = FALSE
            Pull_Flag! = FALSE
            IF INDEX ("DATA ",Line$) <> 1 AND \
               INDEX ("@", Line$) <> 1 THEN BEGIN
              FOR Ctr = 1 TO 9 UNTIL Pull_Flag!     { Find word that closes loop or conditional }
                IF INDEX (Pull$ (Ctr), Line$) > 0 THEN BEGIN
                  IF INDEX ("FOR ",Line$) <> 1 THEN Pull_Flag! = TRUE
                  IF INDEX ("ELSE ",Line$ ) > 0 THEN BEGIN
                    IF INDEX (" BEGIN", Line$) > 0 OR RIGHT$ (Line$,1) = "\" THEN BEGIN
                      Pull_Flag! = FALSE
                    ELSE BEGIN      { No  BEGIN in string }
                      IF INDEX ("IF ",Line$) > 0 THEN BEGIN
                        IF INDEX ("THEN ",Line$) > 0 THEN BEGIN
                          Pull_Flag! = FALSE
                        ENDIF
                      ENDIF
                    ENDIF
                  ENDIF
                ENDIF
              NEXT Ctr
              IF Pull_Flag! THEN BEGIN
                Indent = Indent - Indent_Const
                IF Indent < Indent_Const THEN Indent = Indent_Const
                FOR Ctr = 1 TO Indent
                  Line$ = " " + Line$     { Put in correct number of spaces }
                NEXT Ctr
              ELSE BEGIN        { IF Pull_Flag! is false }
                FOR Ctr = 1 TO 8 UNTIL Push_Flag!  {Find word that opens loop or contitional }
                  IF INDEX (Push$ (Ctr), Line$) > 0 THEN Push_Flag! = TRUE
                NEXT Ctr
                IF Push_Flag! THEN BEGIN
                  FOR Ctr = 1 TO Indent
                    Line$ = " " + Line$     { Put in correct number of spaces }
                  NEXT Ctr
                  IF INDEX ("ELSE ",Line$) > 0 THEN BEGIN
                    IF INDEX ("BEGIN",Line$) > 0 THEN BEGIN
                      Line$ = MID$ (Line$, Indent_Const + 1)
                    ELSE BEGIN
                      Indent = Indent + Indent_Const
                    ENDIF { BEGIN Test }
                  ELSE BEGIN
                    Indent = Indent + Indent_Const
                  ENDIF { ELSE test }
                ENDIF   { Pull_Flag test }
              ENDIF     { Push_Flag! test }
            ENDIF       { Not a DATA statement }
            IF (NOT Pull_Flag!) AND (NOT Push_Flag!) THEN BEGIN
              FOR Ctr = 1 TO Indent
                Line$ = " " + Line$     { Put in correct number of spaces }
              NEXT Ctr
            ENDIF       { Flags test }
          ENDIF         { LEN (Line$) > 1 }
          PRINT (2) Line$
          PRINT Line$
        ENDIF
      UNTIL EOF (8)
      CLOSE (8)
      CLOSE (2)
    ENDIF
  ENDIF
  IF NOT Ok_Flag! THEN BEGIN
    PRINT Program_Name$;" not found, or not of type TXT."
    REPEAT
      PRINT "Do you wish instructions(Y/N)? ";
      GET Response$
      PRINT Response$
    UNTIL INDEX (Response$,"YNyn") > 0
    IF INDEX (Response$,"Yy") > 0 THEN BEGIN
      HOME
      PRINT TAB (27);"Micol program formatter instructions"
      VTAB (5)
      PRINT "     This utility is designed to format your Micol Advanced BASIC source"
      PRINT "file in order to reflect the program flow as described in the manual."
      PRINT
      PRINT "     The required parameter to this utility is the source path name of the"
      PRINT "Micol Advanced BASIC program which needs to be formatted.  If this path is"
      PRINT "currently on line, and of type TXT, you will then be prompted for a pathname"
      PRINT "to which the formatted file will be written.  If the path names are identical,"
      PRINT "you will be prompted again."
      PRINT
      PRINT "     The next prompt will be how many spaces the formatter should indent"
      PRINT "each line.  Two spaces are the recommended number.  After entering"
      PRINT "this value (Maximum of 9 spaces), the formatted file will be generated.  As"
      PRINT "this file is written to disk, it will also be displayed to the screen."
      PRINT
      INVERSE
      PRINT TAB (6);"Be very careful!  This formatter is not as sophisticated as the compiler's"
      PRINT "parser and will not always format a file properly.  Be certain to review this"
      PRINT "formatted file before replacing it with the original."
      NORMAL
      PRINT
      PRINT
      INVERSE
      PRINT TAB (30);"Hit any key to continue";
      GET A$
      NORMAL
      HOME
      VTAB (4)
      PRINT "     There are certain rules, described in the manual, you must observe before"
      PRINT "your program can be properly formatted with this utility.  These rules are:"
      PRINT
      PRINT
      PRINT TAB (10);"1.  Only one statement may be on a line."
      PRINT
      PRINT TAB (10);"2.  As no conversion is made, all reserved words must be in"
      PRINT TAB (10);"    upper case."
      PRINT
      PRINT TAB (10);"3.  Variables must be in lower case with only the first letter"
      PRINT TAB (10);"    potentially in upper case.  This is to avoid possible matches"
      PRINT TAB (10);"    of reserved words within the variable which may affect the"
      PRINT TAB (10);"    indenting."
      PRINT
      PRINT TAB (10);"4.  Comments or quotes should not contain reserved words in upper"
      PRINT TAB (10);"    case.  This file, for example, cannot be used with this"
      PRINT TAB (10);"    formatter because of this violation."
      PRINT
    ENDIF
  ENDIF
  END


Retour au sommaire
hr docs


Source: Mouse Alias.


PROGRAM Show_Mouse_Alias
@ LIST
ALIAS "Home cursor"     = "1"
ALIAS "Position cursor" = "2"
ALIAS "Read Mouse"      = "3"
ALIAS "Change cursor"   = "4"
ALIAS "Cursor off"      = "5"
ALIAS "Cursor on"       = "6"
ALIAS "Fast Mouse"      = "7"
ALIAS "Slow Mouse"      = "8"
ALIAS "Clamp X"         = "9"
ALIAS "Clamp Y"         = "10"
ALIAS "Mouse control"   = "Array (0)"
ALIAS "X Co-ordinate"   = "Array (1)"
ALIAS "Y Co-ordinate"   = "Array (2)"
ALIAS "Activate Mouse"  = "MOUSE (Array()"
ALIAS "Button pressed"  = "Array (5) = 1"
INT (A-Z)
DIM Array (10)
  HOME
  FOR Ctr = 1 TO 2000
    PRINT CHR$((Ctr MOD 96) + 32);
  NEXT Ctr
  ~Mouse control = ~Read Mouse
  ~Activate Mouse
  IF PEEK (48881) = 0 THEN BEGIN
    ~Mouse control = ~Home cursor
    ~Activate Mouse
    DELAY = 300
    REPEAT
      ~Mouse control = ~Read Mouse
      ~Activate Mouse
    UNTIL ~Button pressed
    ~Mouse control= ~Position cursor
    ~X Co-ordinate = 20
    ~Y Co-ordinate = 10
    ~Activate Mouse
    DELAY = 300
    REPEAT
      ~Mouse control = ~Read Mouse
      ~Activate Mouse
    UNTIL ~Button pressed
    ~Mouse control = ~Change cursor
    ~X Co-ordinate = 67    { Time delay cursor }
    ~Activate Mouse
    DELAY = 300
    REPEAT
      ~Mouse control = ~Read Mouse
      ~Activate Mouse
    UNTIL ~Button pressed
    DELAY = 300
    ~Mouse control = ~Change cursor
    ~X Co-ordinate = 66
    ~Activate Mouse
    REPEAT
      ~Mouse control = ~Read Mouse
      ~Activate Mouse
    UNTIL ~Button pressed
    ~Mouse control= ~Cursor off
    ~Activate Mouse
    DELAY = 300
    REPEAT
      ~Mouse control = ~Read Mouse
      ~Activate Mouse
    UNTIL ~Button pressed
    DELAY = 300
    ~Mouse control = ~Cursor on
    ~Activate Mouse
    REPEAT
      ~Mouse control = ~Read Mouse
      ~Activate Mouse
    UNTIL ~Button pressed
    DELAY = 300
    ~Mouse control = ~Fast Mouse
    ~Activate Mouse
    REPEAT
      ~Mouse control = ~Read Mouse
      ~Activate Mouse
    UNTIL ~Button pressed
    DELAY = 300
    ~Mouse control = ~Slow Mouse
    ~Activate Mouse
    REPEAT
      ~Mouse control = ~Read Mouse
      ~Activate Mouse
    UNTIL ~Button pressed
    DELAY = 300
    ~Mouse control = ~Clamp X
    ~X Co-ordinate = 30
    ~Y Co-ordinate = 50
    ~Activate Mouse
    ~Mouse control = ~Clamp Y
    ~X Co-ordinate = 12
    ~Y Co-ordinate = 17
    ~Activate Mouse
    REPEAT
      ~Mouse control = ~Read Mouse
      ~Activate Mouse
    UNTIL ~Button pressed
    DELAY = 300
    ~Mouse control = ~Clamp X
    ~X Co-ordinate = 1
    ~Y Co-ordinate = 80
    ~Activate Mouse
    ~Mouse control = ~Clamp Y
    ~X Co-ordinate = 1
    ~Y Co-ordinate = 24
    ~Activate Mouse
    REPEAT
      ~Mouse control = ~Read Mouse
      ~Activate Mouse
    UNTIL ~Button pressed
  ELSE BEGIN
    HOME
    PRINT "No mouse card detected"
  ENDIF
END


Retour au sommaire
hr docs


Desktop Construction Set.



                         Window and Desktop Manager
                       For Micol Advanced BASIC IIe/c
 
                      Updated for DeskTop Manager V2.0
                       Updated for Window Manager V2.0
 
 
      The Micol Window Manager is a set of ROUTINEs and PROCEDUREs which any
 Micol Advanced BASIC IIe/c programmer can use to add and remove text
 "windows".  These windows can be placed anywhere on the 80-column screen,
 without destroying the contents of the area of the screen over which the
 "window" is placed.  When the window is removed, the area of the screen
 over which the window was placed is restored to how it looked before the
 window covered it.  This releases a vast array of possibilities to the
 programmer, including pop-up context sensitive help screens, a Finder-like
 program launcher, an Appleworks-type interface, and more.  You'll need to
 be fairly familiar with Micol Advanced BASIC before you'll be able to
 really use this.

     
      The DeskTop Manager uses the Window Manager to simulate a simple Apple
 Human User Interface DeskTop Metaphor; ie. windows, pull down menus and
 buttons.  The Desktop Manager can be used in your own programs to add a
 desktop interface to your programs, making your programs easier to use and
 more professional looking.

 
      For those of you not familiar with Micol Advanced BASIC, or other
 structured languages, this file will give you a chance to see for yourself
 the many advantages of a structured language, and the advantages of Micol
 Advanced BASIC in particular.  Modularization, better use of memory, local
 and global variables, and no line numbers are all used in these programs,
 and this will give you a chance to see how they operate to make your job
 easier, and your programs better.

 
      The Window and Desktop manager programs are written using Micol
 Advanced BASIC.  You build your own programs using these files and
 "templates".  The templates provide the functions required to do the
 housekeeping associated with window/desktop maintenance, and the code you
 add makes up the actual functionality of the program.

 
      The templates use the INCLUDE command to "bring in" a number of
 support files at compile time.  Except in a few cases, you will rarely need
 to load or modify these files.  However, the compiler MUST be able to find
 these files at the active PREFIX at compile time.  These files are:

 
 If you are using the Window Manager or the Desktop Manager:

      Window.Globals
      Window.Routines
      Window.DIMS
      Window.Procs


                                     [1]



 If you are using the Desktop Manager:

      Desktop.procs
      Deskt.routines
      Desktop.DIMS
      Desktop.Globals

 If you are using the Viewer:

      Viewer.DIMS
      Viewer.Procs
      Viewer.Routines

 
      The next sections will describe how to use the Window Manager and the
 Desktop Manager.

 
 
                             The Window Manager

 
      The Window Manager consists of a set of ROUTINEs, FUNCtions and
 PROCedures which save and restore screens to and from the computer's
 memory.  Also supplied is a template which you can use to build your own
 programs which use the Window Manager.


      The theory of operation is rather simple... every time we add a new
 window, we grab the section of the screen which the window will be
 covering, and stash it in memory somewhere out of the way for safe storage.
 We also save related information, such as the cursor's current location and
 the current screen margins.  And we repeat this for each new window added.
 Later, when we want to remove a window, we 'pop' it off by simply restoring
 the saved screen image and related information.  Since the screen image was
 saved before the window was drawn on the screen, poof! the window
 disappears as the old screen is re-drawn.  Pretty simple, huh?


      The only really small complication is that the text screen, as we see
 it, is actually sitting in two different areas of memory.  Every even
 column is stored in 'Main Memory', and every odd column is stored in
 'Auxiliary Memory'.  Auxiliary memory is the alternative area of memory
 which is virtually impossible to access from Applesoft, since accessing it
 means "switching out" the area of memory where Applesoft sits.  However,
 with Micol Advanced BASIC, we don't have that problem.  With the MOV_MEM
 command, we can easily grab anything from the auxiliary memory, and move it
 anywhere we want.  If this is confusing you, don't worry, it's not really
 required that you understand this.


      This Window manager is also "smart" in the sense that it only saves
 the area of the screen that is under the new window we are about to add.
 We could make our job much easier by just saving the whole screen, but the
 whole screen uses almost 2k of memory, and that means every time we added a
 new window, we would eat up 2k of program space (of course, every time we
 popped a window, we gain that space back).  That means that even with only
 5 small windows open on the screen, you would be using 10k of valuable
 memory.  This may not mean much, since Micol Advanced BASIC IIe/c gives you
 72k of memory, but on an Apple II it doesn't pay to take the easy way out


                                     [2]


 at the expense of memory.  By saving only the area covered by the new
 window, we can fit two to three times as many saved windows in the same
 amount of memory.


      The Window Manager is separated into a few files which are INCLUDEd
 into one large file.  This helps to keep your source code smaller and
 relevant (you don't see all the window ROUTINEs, etc in your source code).
 Here's a break down of each file:

 
      1)   Window.MGR: This is the main program which INCLUDEs the others.
 Use the program as a 'template' to build your own programs in.

      2)   Window.globals:  This file contains all the global variables and
 their starting values.  Do not use any of the variables in this file for
 other purposes, unless you are damn sure of what you're doing.

      3)   Window.PROCs: This contains PROCedures which the window manager
 uses.  All of the variables in these PROCedures are local (except for those
 in Window.globals).  Be careful not to accidentally make a global variable
 with the same name as one of the variables used in these PROCedures.

      4)   Window.ROUTINEs: These are ROUTINEs which the window manager
 uses.  None of these ROUTINEs use any variables.  Since ROUTINEs are
 quicker to call than PROCedures, we made these ROUTINEs (rather than
 PROCedures) to make them a bit quicker, and since there was no danger of
 accidentally messing with any of your program's variables.

 
      First a little window terminology.  The "title bar" is the bar at the
 top of the window which contains a name for the window.  On the left side
 of the title bar, you'll see a little square, which is the "close box".
 The close box is where a user with a mouse will click when they want to
 "close" the window, and generally has the same result as pressing ESC.  The
 close box is drawn on the window, but isn't used by the window manager.
 The mouse is only supported by the Desktop manager.  The topmost window
 will always be "active", which is where all the action will take place,
 such as printing.  The active window will have a solid title bar.  Non-
 active windows will have a "dimmed" title bar, which is not solid.  (Hard
 to describe, but you'll understand when you run the demo).

 
      Ok, now here's a short summary of how to use the window manager, and
 how it works (its flow of control):

 
      1)   Add a new window: To do this, just do a GOSUB Add_Window, passing
 it a title for the window, and the top, left, bottom and right screen
 margins in that order.

      If you want, pass a null string ("") as the Title, and there will be
 no title for the window in the window's title bar.  Alternatively, pass a
 "@" for the title, and no title bar at all will be drawn.  This is useful
 for special types of windows, as we'll see later in the DeskTop manager.

      2)   Add_Window calls a PROCedure which saves the current screen's
 information and "dims" the title bar of the currently active window.  It
 then calls a PROCedure which checks the screen margins you passed it
 Add_Window insure they are legal, and then sets some variables to these
 values for future reference.  Next, it calls the Save_Screen PROCedure.


                                     [3]



      3)   Save_Screen is the heart of the system, it is what actually grabs
 the screen information and stashes it for later.  It figures out how many
 bytes wide your window is, and how many rows down it is.  It divides the
 amount of bytes across by two because every second byte is stored in
 auxiliary memory, which means if your window is 80 bytes across, 40 bytes
 will be in main memory, and 40 will be in auxiliary memory.  Next, it goes
 down each row of the screen area to be saved, determines the memory address
 for that line, and then transfers the appropriate number of bytes to the
 "safe area" buffer, first from Main Memory, and then from Aux Memory.  This
 is repeated for each line.

      The buffer to which the lines are moved resides at the very "top" of
 program space in main memory, directly below some library routines.  The
 starting address is stored in the global variable "start%" which you will
 find in the "window.globals" file.  This variable may need to be changed if
 the library grows, however, you will be informed of this in the supplement
 notes on any new releases of the compiler, and unless you recompile your
 programs with the new version, you will not need to change older programs.
 Anyway, as Save_Window moves bytes into this buffer, it increases a
 variable called "used%" which basically tells Save_Screen how many bytes
 have been used, and where the new destination for transferring bytes is
 (basically, at Start% - Used%).

      WARNING:  Your programs build up from the bottom of program space, and
 the windows build down from the top of program space.  If you have a large
 program, and then save many large windows, your window space could run into
 your program space, destroying your program!  There is only one method to
 detect this.  In the "Window.globals" file, you will find a variable called
 "Top_of_prog".  You can set this variable to the topmost memory location
 used by your program, and the window manager will ensure that your program
 is not overwritten by saved screens (an error will be generated instead).
 The problem with this method is that during development, the length of your
 program will be constantly changing.  Make sure you set this variable to be
 GREATER than the "top of your program".  If you don't want any protection,
 you can set this variable to be equal to 0.  To set the variable, compile
 your program, and watch for the information displayed after compilation.
 The first line of the information will contain the number of bytes
 generated.  Then, load the file "WINDOW.GLOBALS" into your editor, and
 change the value of "Top_of_prog" to reflect this number, plus whatever
 LOMEM is set to.  LOMEM defaults to $900, so unless you change it (see the
 LOMEM compiler option), you would set the variable to $900 + (NUMBER OF
 BYTES COMPILER GENERATES).

      4)   Once Save_Screen has done its thing, control is returned to
 Add_Window, which then calls a ROUTINE to reset the window margins to the
 maximum (so that it may draw anywhere on the screen, uninhibited).  Then it
 draws your new window, and calls a ROUTINE to set the margins to the values
 you supplied for your new window, does a HOME, and presto!  You've got your
 own window with which to do what you like.

      5)   Do whatever you want.  The window will act like a miniature
 version of the screen.  However, be aware that VTAB and HTAB still act
 globally on the whole screen, not relative to the top left corner of your
 window.

      6)   Add more windows if you want.  The process repeats from Step #1,
 using more memory.

      7)   If you want to remove a window, call Pop_Window.  This PROCedure
 basically does exactly what Save_Window does, except in reverse.  First, it


                                     [4]


 figures out the number of bytes across for the current window, and halves
 it as before.  Then, it transfers the memory back TO the screen FROM the
 buffer, and SUBTRACTS the number of bytes moved from Used%.  In doing so,
 it restores the image of the screen from before the new window was added,
 effectively erasing the most current window.  Next, Set_Window is called to
 restore the screen margins of the previous (and now current) window, and
 finally the menu bar (if it exists) of the now current window is
 highlighted to show it is active.

      8)   Again, add more windows, or pop them, as you please.  Your only
 restrictions are:

      a)   The amount of memory you use, as mentioned above, and;
      b)   The Window Manager is currently set up to handle only 20 windows
 at once.  This can easily be changed by increasing the value of the DIM
 statements in the Window.DIMS file.  Increasing these will take memory away
 from your variable space, so try to keep them within reason.

 
    That should give you a pretty good idea of how the Window Manager works...
 if you're still unclear about anything, take a look at the source code.
 It's really easy to follow.

 
    Notes on the Window Manager:  The window manager contains a ROUTINE called
 Quick_Window.  Doing a GOSUB Quick_Window will give you a medium sized
 window in the centre of the screen.  This is handy for many things,
 especially debugging.  For instance, using quickwindow, you can get a
 window on the screen, print a few variables, wait for a keypress and then
 pop the window, and continue with your program.  This allows you to 'peek'
 at the values of variables without disrupting the normal display of your
 program.

 
 How to USE the Window Manager:
 
      Use the file Window.MGR as the main template for your program.  Fill
 in the blanks where appropriate, to add your own PROCs, ROUTINEs, etc.
 There are 8 PROCedures, FUNCtions, and ROUTINEs which you can call to
 handle housekeeping tasks.  They are:
 
 1) Add a window
 
 GOSUB Add_Window [ Name$, Top%, Left%, Bottom%, Right% ]

 
       Use this call to add a window to the screen,
 having the name you specify and the margins you specify.  Note, the left
 margin must be an ODD number, and the right margin must be an EVEN number.
 If you pass Add_Window a Name$ of "@", the window will not have any title
 bar.

 Example:
 
 GOSUB Add_Window ["Hello World",5,7,15,60 ]
 
      This will create a window in the middle of the screen, with the title
 "Hello World" in the menu bar.  The cursor will be placed in the top left
 hand corner of the new window.

 


                                     [5]


 2) Remove topmost window
 
 GOSUB Pop_Window
 
      Use this call to remove the most recent window added (the top window).
 There are no parameters for this call.

 Example:
 
 GOSUB Pop_Window
 
 
 3) Quickly add a window without having to specify size:
 
 GOSUB Quick_Window
 
      Use this call, as mentioned above, to put a window on the screen.
 Useful when you want a window, but don't want to be bothered with its name
 and location.

 Example:
 
 GOSUB Quick_Window

 
 4) Close all Windows
 
      GOSUB Close_All
 
 Use this call to close all open windows, if any.  Example:
 
 GOSUB Close_All

 
 5) Print a string variable centred in a window.
 
 GOSUB Centre [ String$ ]

 
      Use this PROCedure to print a string centred in the currently active
 window.  You only need pass it either a literal string (as in the example
 below), or the name of a string variable (as in the example above).  This
 is useful, since you will often want to centre something in a window, and
 you don't always want to have to calculate the window's dimensions.
 
 Example:
 
 GOSUB Centre [ "This will be centred" ]

 
 6) Format and Print a text string.
 
 Text$ = "whatever......" (up to 255 characters)
 GOSUB FPrint (or GOSUB FPrintx)
 
      Often you will want to print information in a window, but avoid having
 it "wrap-around" the sides of the window, breaking up words in the middle.
 The print formatter will print a text string, inserting a RETURN on each
 line as close to the right hand margin, without having any words wrapping
 around.  This adds a very professional look to your program.



                                     [6]


      To use the print formatter, first assign what you would like printed
 to the global variable Text$.  Then use GOSUB to call FPRINT.  There is a
 variant on FPrint, called FPrintx that you can also use.  FPrintx is
 essentially the exact same as FPrint, except it leaves the cursor positions
 immediately after the last word printed, rather than on the beginning of
 the next line.  Here's an example:
 
      Text$ = "1"
      GOSUB FPrint
      Text$ = "2"
      GOSUB FPrint
 
      This will print:
 
      1
      2
 
      Here's a different example:
 
      Text$ = "1"
      GOSUB Fprintx
      Text$ = "2"
      GOSUB Fprintx
 
      This will print
 
      12
 
      and will leave the cursor positions immediately after the "2"
                             The Desktop Manager

 
      The Desktop Manager uses the window manager to simulate a "desktop
 metaphor", based on Apple's Human Interface Guidelines.  The desktop
 manager lets you write programs with a professional pull-down-menu
 interface.  The Desktop manager also integrates full mouse control into the
 user interface.
 
      First some desktop terminology.  The bar across the top of the screen
 from which menus are pulled down is called the "Menu Bar".  The individual
 items in the menu which can be selected are called "menu items" (pretty
 creative, eh?).  The little squares which you can click on for an action
 (such as the square in the top left hand corner of a window) are called
 "buttons".  The one in the top left hand corner of a window is called the
 "close button", because when you move the mouse cursor over it, and click
 on it, it will close the window.  Because not all users have a mouse, every
 button will have an associated "hot-key".  The hot-keys are displayed next
 to a button, and tell the users what key to press to get the same action as
 clicking on the button with the mouse.  Hot-keys are always a combination
 of holding down the Open-Apple key and pressing a regular key.  Sometimes
 it is necessary to prohibit access to a certain menu item or an entire
 menu.  When we do this, we say we "dim" the menu or menu bar.  This is from
 the Macintosh, where it is possible to actually display these menus and
 menu items dimmer on the screen than the other items, in order to indicate
 that they are not valid choices.  On the text screen of the Apple II, it is
 impossible to display dimmed text, so instead we display a "**" in front of
 the menu or menu item to indicated it has been dimmed.  Menus and menu
 items which have a "**" in front of them are not valid choices, and the
 menuing system will not allow you to choose them.
 
      Using the desktop manager is not easy to program.  It requires a whole


                                     [7]


 new style of programming, a new way of thinking through the logic of your
 program.  Traditional programs have a "straight-through" flow approach,
 where execution of the program flows downwards through a program, and
 progresses from beginning to end, with the user's input modifying the
 outcome.  Desktop programs use an "event loop", which is a central part of
 the program which looks for keyboard/mouse activity and reacts to it by
 calling certain ROUTINEs and PROCedures.  A programmer has very little
 control over the flow of the program... the user drives it.  You must
 design your programs with this fact in mind that you may never know where
 it's headed next.  As more of how the desktop manager is explained, you
 will begin to understand this better.
 
      Using the desktop manager also means supporting the mouse.  Supporting
 the mouse has some very specific requirements.  The reasons for these
 requirements are rather technical, but basically have to do with how the
 mouse driver saves and restores the characters which the mouse cursor
 covers as it moves around the screen.  There are two aliases "~Mouse ON"
 and "~Mouse OFF", which you can use to turn the mouse cursor on and off.
 YOU MUST ALWAYS TURN THE MOUSE CURSOR OFF WHEN YOU USE PRINT TO PRINT TO
 THE SCREEN.  IMMEDIATELY AFTER PRINTING, YOU MUST ALWAYS TURN THE MOUSE
 CURSOR BACK ON.  If you use ANY of the Window Manager or Desktop Manager
 functions (such as GOSUB FPrint to print formatted output to the screen),
 these requirements are taken care of for you.  You only need to shut the
 mouse cursor off yourself if you use a PRINT statement.  This may sound
 like a large task, but you'll discover that you won't be using a raw PRINT
 statement too often, but you'll be using the Window and Desktop manager
 functions instead.
 
      You'll build your programs around the DT.MGR template.  The desktop
 manager template also uses files from the window manager.  You'll need all
 the Desktop Manager and Window manager files available on the disk to which
 the prefix is set when you compile your programs.  Customizing the template
 isn't too difficult.  You'll find it commented to tell you where to add
 your own routines, etc.  The difficult part is to design a program which
 can operate successfully under the desktop environment.  Here are a few
 things which you should consider:
 
      1) The heart of the system is something called the Event Loop.  The
 event loop allows  the user to choose menus and items, as well as enter
 keyboard commands.  Your program should be calling the event loop procedure
 constantly and consistently.  (More info about how to actually call it will
 come later).  If you are processing or waiting for input, you should
 include frequent calls to the event loop.
 
      2) The event loop acts independently.  For instance, let's assume your
 program is doing some work, but frequently calling the event loop, as
 required.  While the program is executing the event loop, let's say the
 user moves the mouse and selects an item from one of the menus.  Every item
 in the menus has an associated ROUTINE or PROCEDURE which the event loop
 knows about.  When the user chooses an item, the event loop AUTOMATICALLY
 transfers control of the program to the ROUTINE or PROCEDURE which has been
 specified to handle that menu item.  Therefore, your program could be in
 the middle of executing one routine, when suddenly execution is transferred
 to a different routine.  Can your program handle this?
 
      3) To make matters even more complicated, let's say the user chooses
 the item in the menu which your program is ALREADY running.  Since Micol
 Advanced BASIC supports recursion, program execution will be transferred to
 the top of the same PROCEDURE or ROUTINE which you are already running.
 Can your PROCEDURE or ROUTINE handle this?  If so, it is what is known as
 "re-entrant", and you are probably a very good programmer.  Most ROUTINEs


                                     [8]


 and PROCEDUREs are not re-entrant.  Imagine what would happen if your
 ROUTINE or PROCEDURE called itself.  If it would work OK, then it is re-
 entrant.  Luckily, there is a way to dim menu items so that they cannot be
 selected.  We suggest that the first thing you do in your ROUTINEs and
 PROCEDUREs which are invoked by menu items is to DIM THE MENU ITEM(s) WHICH
 CAN INVOKE IT to prevent it from being called again, unless the particular
 ROUTINE or PROCEDURE is re-entrant.
 
   The DeskTop manager has essentially twelve main functions.  These functions
 will be explained in depth a little later, but here's a list of what they
 are:
 
 1)   Add a menu.
 2)   Remove the last menu added.
 3)   Dim a menu.
 4)   Undim a menu.
 5)   Add an item to any menu.
 6)   Dim an item in a menu.
 7)   Undim an item in a menu.
 8)   Add a "Desktop Window"
 9)   Remove a "Desktop Window"
 10)  Add a button onto the screen
 11)  special INPUT routines for the desktop environment
 12)  The Event Loop
 
   Included on the disk the file "Mouse.Demo", this is a demo system which
 shows how to use the Desktop Manager.
 
 Here's how the demo system works:
 
      1)   The system starts up and calls the ROUTINE Draw_Desktop, which
 draws the desktop using a MOV_MEM to copy the lines, so it draws it
 quickly.

      2)   Next it calls the ROUTINE Set_Up_Menus, which installs some demo
 menus so you can see how the system works.

      3)   Set_Up_Menus shows you how to add menus and menu items.  To add a
 menu, use the FUNCtion Add_Menu.  It will add a menu with the name you pass
 to it, and will return a menu ID number.  Use this menu ID # to access that
 menu later.  To add an item to a menu, use the FUNCtion Add_Item.  Just
 pass it the menu ID # of the menu you want to add the item to, and the item
 name.  It will return an unique item ID # for the item, and you will use
 this ID # later to identify the item you just added.  Using Add_Menu to
 create a menu with a title "@", it will appear as a closed-apple symbol in
 the menu bar.  Using Add_Item to create a menu item called "-" will put a
 'separator' in the menu... a line of dashes to break the menu up into
 smaller parts.

      Here's a short description of the variables used by Add_Menu:
     
      Menus% : Contains the total number of menus.     
      Menu_Position%(Menu#) : Stores the position across
 the menu bar for each menu.

      Next_pos% : Temporary storage for Menu_Position%

      Menu_Item_Name$ (Menu#,Item#) : This string array
 holds the name of menus and menu items.  Menu names are stored under
 Menu#0, with Item# being the menu numbers.  Therefore Menu_Item_Name$ (0,2)
 is the name of the second menu, and Menu_Item_Name$ (2,1) is the name of


                                     [9]


 the first menu item in the second menu.

      Menu_Bar_Items% (Menu#) : This integer array holds the number of items
 in each menu.  Menu_Bar_Items%(0) contains the total number of menus.

      Menu_Number% : a global variable containing the most recently accessed
 menu.

      Add_Menu also calls the ROUTINE Write_Menu_Bar_Entry, a short ROUTINE
 which writes the menu's name in the menu bar, according the Menu_Position%
 of the most recently accessed menu (Menu_Number%).

      The PROCedure Add_Item uses basically the same variables as Add_Menu,
 except it also uses Item_Identifier%, which basically = (100 * the menu #)
 + the item #, to make it unique.
 

      4)   The program then calls Intro which draws a single window on the
 screen and welcomes the user.  Then, the flow of control passes to the
 ROUTINE Event_Loop.  Event_Loop calls a function which checks to see if
 there are any events to report, such as a keypress, or a menu item being
 chosen.

      Get_Event checks to see if the Closed-Apple key has been pressed, or
 if the user has clicked the mouse on  the menu bar.  If the answer is YES
 to either of these situations, then Get_Event calls the FUNCtion Chooser,
 which lets the user chose a menu item, and returns the item ID# of the user
 chooses.  If a 0 is returned by the FUNCtion, then the user pressed ESC in
 the chooser and did not choose any item.

      5)   The chooser highlights a menu name in the menu bar across the top
 of the screen.  The user can press the left or right arrow to switch to the
 next menu in the respective direction, or ESC to exit.  If the user presses
 the down arrow or RETURN key, the menu pops down, and the a menu bar
 appears, allowing the user to choose an item in the menu.

      Here's where that trick of placing a "@" as a window title mentioned
 earlier comes in handy.  These menus which pop down are really just windows
 without any title bar.

      While in the menu, the user can press ESC to exit back one level to
 choose a new menu, or the up and down arrows to choose between the items.
 The left and right arrows will take the user to the next left or right
 menu, respectively, and it will automatically pop down.  If the user
 presses return on an item, the chooser closes the menu and exits, returning
 the unique item ID # of the item the user has chosen.

      6)   The Chooser exits back to the Event_Loop, returning the item
 identifier of the item chosen.  The Event_Loop then decides what to do
 based on this number, and then resumes the event loop, by calling the
 appropriate PROCedure or ROUTINE, as determined by its jump table.
      Whatever ROUTINE or PROCEDURE is invoked by Event_Loop will call
 event_loop periodically to get any user input.  Go back to Step 4.
 
   The best way to understand the DeskTop Manager is to play with it.  Try
 adding your own menus, or build your own program around it.  Experiment.

 Using the DeskTop Manager
 
   Here are the calls you can make to the Desktop Manager, and what you need
 to pass them:


                                     [10]


 
 1) Add a Menu to the Menu Bar
 
      FUNC Add_Menu [ Menu_Name$, Child! ]
 
      Use this FUNCtion to add a new menu onto the screen.  Menu_Name$ is
 the name of the menu as you want it to appear in the menu bar.  If you pass
 "@" as the name of the menu, you'll get an Apple symbol.

      The Boolean variable Child! is used to indicate whether this menu
 "belongs" to the active window.  Let's say we add a window on the screen
 which contains the word "HELLO", and we add a menu which contains an item
 which calls a ROUTINE which will clear (HOME) the window and print the word
 "Goodbye".  That's no problem.  Ok, so we have our window with the word
 "HELLO" on the screen, and the user goes into the menu, and selects this
 item, the window clears, and then the word "goodbye" appears.  That works
 fine.  However, what if the user did not go into that menu immediately, but
 instead selected a different item, such as "HELP", which calls up a new
 window.  Now the help window is on the screen, and presumably contains the
 some information helping the user.  The user then goes back into the menu
 system and selects the menu item which clears the window and prints
 "goodbye".  Instead of clearing the window with the word "HELLO", it (of
 course), clears the ACTIVE window, which is the help window.  The ROUTINE
 which this item calls ASSUMES that the "HELLO" window is active.  Because
 this menu is dependant on a particular window being active, we call it a
 "child" of this window.  What setting Child! to TRUE does is AUTOMATICALLY
 dims this menu when a new window is added, so none of the menu items in
 this menu can be activated out of the context of the window for which they
 are intended.  Some menus, such as the Apple menu in the example are
 designed so that they can be accessed anytime.  An example of a child menu
 is the Face Control menu in the demo.  When you choose the face demo, a new
 menu is added called "Face Control", which can change the face from happy
 to sad.  However, the items in the menu are intended to be used only when
 the face window is the active window.  By declaring this menu as a child,
 when a new window is added, the menu is automatically dimmed.

      Add_Menu will return a number which you will later use to identify
 that menu, so you'll want to assign it to a meaningful variable.  This
 number is known as an "identifier", since we'll use  it later to tell other
 ROUTINEs and PROCedures that it is this menu in specific which we are
 referring to.  Each menu will have a unique identifier.
     
 Example:
 
      File_Menu_Number%= FN Add_Menu [ "File Menu", FALSE ]
 
      This will add a new menu to the menu bar, which will appear as "File
 Menu".  This menu is not a child of the active window, and will not
 automatically be dimmed when a new window is added.
 
 2) Delete the last menu added.
 
      ROUTINE Delete_Menu
 
      Use this ROUTINE to delete the LAST, or most recently added, menu.
 The menu name will disappear from the menu bar.
 
 Example:
 
      GOSUB Delete_Menu
 


                                     [11]


 3) Dim a menu.
 
      ROUTINE Dim_Menu
 
      Use this routine to dim a menu item so that no items on it can be
 chosen.  This is useful if all the menu items in a menu cannot be used in
 certain situations.  Dimming the menu shuts off access to all the items
 within it.
      To use this routine, you must first set the global variable
 Menu_Number% to the identifier of the menu which we want to dim.  For
 example let's say we want to dim the File Menu, which we created above in
 example 1).
 
      Menu_Number% = File_Menu_Number%
      GOSUB Dim_Menu
 
      The File Menu menu bar item will now have a "**" on each side of it,
 to indicate it has been dimmed.
 
 
 4) Undim an a menu.
 
      Of course, we also need to be able to undim a menu to allow it to be
 chosen again, when its contents become valid options.  The method used is
 the exact same as to dim a menu.  Here's an example to undim the menu we
 created in example 1) and dimmed in example 3).
 
      Menu_Number% = File_Menu_Number%
      GOSUB Undim_Menu
 
      The "**" from around the File Menu menu bar item will be removed, and
 items within that menu will now be able to be chosen.
 
 
 5)   Add an item (or choice) to a menu
 
      FUNC Add_Item [ Menu Number%, Item Name$ ]
 
      Use this FUNCtion to add menu items to a menu.  Add the menu items in
 the order in which you would like them to appear in the menu.  Pass it the
 menu identifier for the menu which you are adding the item to, and the name
 of the item to add.
      If you use a "-" for the item name, it will place a "separating" line
 into the menu bar.

      Do not use a "*" in a menu item name.  A "*" is used to denote a
 dimmed menu item (not selectable) and you may confuse the user by using
 this symbol in another way.
      This function will return a unique item Identifier which you will use
 later to reference this menu item, similar to the way menus are identified.
 
 Example:
     
      Quit_Item% = FN [File_Menu_Number%,"Quit"]
 
      This will add an item to the File Menu, which will appear as "Quit".
 
 
 6) Dim an item in a menu.
 
      PROC Dim_Item [ Item ID Number% ]


                                     [12]


 
      Use this PROCedure to dim a menu item, making it unselectable by the
 user.  The item will be denoted as being dimmed in the menu because it will
 have an "*" before and after it's name.  The menu bar will automatically
 skip over it, not allowing the user to select it.  Be sure not to dim an
 item which has already been dimmed.  If you do, BAD THINGS happen.
 
 Example:
 
      GOSUB Dim_Item [ Quit_Item% ]
 
      This will dim the "Quit" item we added in the above example.
 
 7) Undim a menu item.
 
      PROC Undim_Item [ Item ID Number% ]
 
      Use this to undim a previously dimmed item.  Do not use this on an
 item which is not dimmed, or BAD THINGS will happen.
 
 Example:
 
      GOSUB Undim_Item [ Quit_Item% ]
 
      This will undim the "Quit" item dimmed in the above example.
 
 9) Add a DeskTop window
 
      PROC Add_DT_Window [Title$,Top_Col%,Left_Row%,Bot_Row%,Right_Col%]
 
      This is essentially the same as the Add_Window call in the Window
 Manager, but it includes support for the mouse, plus child menus (described
 in part 1).  NEVER CALL Add_Window FROM A DESKTOP PROGRAM, ONLY USE
 Add_DT_Window!
 
 10) Remove a Desktop Window
 
      PROC Pop_DT_Window

      As in the case above, this PROCedure performs essentially the same
 function as the Pop_Window call in the Window Manager, but it includes
 support for the mouse and child menus.  NEVER CALL Pop_Window FROM A
 DESKTOP PROGRAM, ONLY USE Pop_DT_Window!
 
 11) Add a button
 
      FUNC Add_Button [ Draw!, X%, Y%, Equiv$ ]
 
      Buttons are useful ways to allow users to respond to questions, or to
 pick certain options.  The Add_Button function informs the mouse and event
 loop routines that you are adding a button onto the screen.  Then the event
 loop routines will take over and inform you if the button has been
 activated, either by a keypress or by the user placing the mouse cursor
 over the button location and pressing the mouse button.  The FUNCtion
 returns a unique identifier, similar to menus and menu items, which you
 will use later to identify the button.

      The button also contains a routine to draw a standard button on the
 screen at the current cursor location.  If you pass the function a TRUE for
 the Draw! variable, a button will be drawn.



                                     [13]


      The X% and Y% locations can be specified to place a button on the
 screen a specific location.  Note that if Draw! is set to TRUE, the current
 cursor location will be used for X% and Y%, regardless of what is contained
 in the variables passed.  Otherwise, Add_Button will create an "invisible"
 button at the location on the screen you specify with X% and Y%.  This
 allows you to make custom buttons by drawing something on the screen that a
 user can click on.

      The Equiv$ variable contains the keyboard equivalent for clicking on
 the button, or the "hot-key".  Since not all users have a mouse, you should
 almost always specify a hot-key.  Simply pass a single letter, which will
 become the hotkey.
 
 Example:
 
      Yes_Button% = FN Add_Button [ TRUE, 0, 0, "Y" ]
      Text$ = " Yes - Save the file!"
      GOSUB FPrint
 
      This will draw a button at the current cursor location, and also place
 the information beside it indicating the hot-key for it.  Then it will
 print a message after the button indicating its purpose.  Note that we
 passed zeros for X% and Y% because we used the Draw! feature so their
 values are not important.  The result (assume the @ is an Open-Apple
 symbol, and the # is a box symbol) will look like this:
     
      # (@Y) Yes - Save the file!
 
      Buttons are only active while the current window (at the time the
 buttons are added) is active.  If you add more windows, then all the
 current buttons will become "non-active", until the new windows are removed
 and the window to which the buttons were added is active again.  When the
 window to which the buttons were added is removed, all the buttons for that
 window are lost.
 12) User Input Routines
 
      PROC DT_INPUT [ String_Var$, Max_Length% ]
      PROC Default_INPUT [ String_Var$, Max_Length%, Default$ ]
      PROC Get_Line [ String_Var$, Max_Length%, EmptyOK!,Hide!,DoCR!]
 
      These three PROCedures are designed to be used where you would
 normally use an input statement.  A NORMAL INPUT STATEMENT CANNOT BE USED
 WITHIN THE DESKTOP MANAGER!  The reasons for this are technical, and
 related to the mouse.  However, you will find these PROCedures far more
 useful than INPUT ever was.  The first two PROCedures call the third
 procedure, which is the main input routine.  Since the third PROCedure has
 so many parameters, the first two PROCedures were provided for convenience,
 since they just call the third PROCedure with certain defaults set.  These
 input routines are recursive... up to ten may be open at once.  To increase
 this limit, modify the DIMs found in DESKTOP.DIMS.
 
      The first PROCedure is the standard INPUT that you'll use while using
 the desktop.  Pass it a string variable, into which the input will be
 placed.  Max_Length% is an integer specifying the maximum length the input
 can be.  The DT_Input will not allow the user to type any more than this
 maximum length.  The user will not be allowed to press return unless he/she
 has entered something (an empty result is not permitted).
 
 Example:
 
      GOSUB DT_Input [A$, 5]


                                     [14]


 
      This will allow the user to enter up to 5 letters, and will return the
 result in A$
 
      The second PROCedure, Default_Input, is intended for times when you
 have a default input string to be used if the user does not enter anything.
 The first two parameters are the same as above, the third parameter is the
 default.
 
 Example:
 
      GOSUB Default_Input [ A$, 5, "HELLO" ]
 
      The user will be allowed to type up to 5 characters.  If the user
 presses return without entering anything, the word "HELLO" will be printed
 (to indicate it was used as a default) and the result (either what the user
 entered, or the default) will be returned in the parameter A$.
 
      The third PROCedure is by far the most complicated and flexible.  The
 first two parameters are as above.  The third parameter, EmptyOK!,
 indicates whether the user is permitted to press return without entering
 anything (and hence returning an empty string).  The fourth parameter,
 Hide!, indicates if the input routine should hide what is being typed,
 printing a "#" instead of the characters typed.  This is useful for
 entering passwords.  The last parameter, DoCR!, indicates whether the
 cursor should be put to the beginning of the next line when return is
 pressed, or left at the end of the current line.
 
      There is also a global variable used in all three cases called
 HotKeys!.  If this variable is set to TRUE, and the Maximum_Length% is only
 one character, the user will not be required to hit return after typing the
 single character.  The user should be able to set this variable according
 to their preference (some users love hotkeys, others hate them).  This
 "hotkeys" is not to be confused with the hot-keys assigned to buttons.
 
 
 13)  The Event Loop
 
      ROUTINE Event_Loop
 
      As mentioned earlier, this routine is the heart of your program.
 Contained in the DT.MGR file, it is one of the few parts of the manager
 which you must modify yourself.
 
      Your programs will call this routine anytime they are waiting for
 input.  This routine allows the user to select menu items, or to press
 keys.
 
      When the program returns from the even loop call, the global variable
 Event% may contain a value.  There are four possibilities of what this
 value may be.  Your program must be prepared to deal with each possibility:
 
      1) IF Event% > 1 AND Event% < 255 THEN Event% contains the ASCII value
 of a keypress.  This means that the user has pressed a key (other than the
 ones used for manipulating menus).  If your program is waiting for a
 keypress, then you now have one (NOTE: Never use a GET statement, since
 GOSUB Event_Loop essentially handles keypresses).  If you are not waiting
 for a keypress, then you might as well ignore it.
 
      2) IF Event% = ~CLOSE THEN the user has pushed ESC or clicked on the
 current window's close box.  This is your cue to finish up or abort


                                     [15]


 whatever you're doing, and close/pop the active window.
 
      3) If Event% is not either of the above, then it is probably a "button
 identifier".  By comparing Event% with the button identifiers returned by
 the Add_Button function, you can determine which button was clicked on (or
 equivalent hot-key was pressed) and take appropriate action.
 
      The event loop itself must be modified... you must add a "jump table"
 to it, so that it knows what to do when certain menu items are chosen.  In
 the template, you'll find a line in the event_loop which reads:
 
      {ADD YOUR JUMP TABLE HERE!}
 
      This, as you probably guessed, is where your jump table goes.  Your
 jump table consists of a series of IF... THEN statements, one for each menu
 item used in your program.  Remember the menu item (the "Quit" item) we
 added above?  We need to make a jump table entry to tell the event manager
 what to do when the user picks this item:

      IF Event% = Quit_Item_Number% THEN GOSUB My_Quit_Routine
 
      That's it... and you'll need similar entries for each and every menu
 item.  Of course, you don't have to use a ROUTINE, you could GOSUB a
 PROCedure too.  This pretty well covers the DeskTop manager.  The BEST way
 to understand it is to look at the MOUSE.DEMO file included on the disk.



                             THE VIEWER/CHOOSER
 
 
      The viewer/chooser is an addition to the Desktop manager.  The viewer
 is a vertically scrolling window which allows you to view information which
 is `longer' than the screen.  The chooser is also a vertically scrolling
 window which, through use of a scrolling light bar, allows you to select an
 item from a list.  Both of these routines are fully recursive, meaning that
 multiple windows of each can be open at any time.  Beware, however, that
 these routines are quite memory hungry.
      Also included is a file viewer.  The file viewer will automatically
 load a text file into a viewer window, formatting the text so it appears
 properly according to the width of the window.
 
 
                             The Viewer/Chooser Files
 
      There are three files which make must be included in your main program
 to access the viewer and chooser.  They are VIEWER (the main PROCedures),
 VIEWER.DIMS (DIM statements) and VIEWER.GLOBALS (global variable
 declarations).
      Viewer/Chooser also creates some temporary files when more than one
 viewer or chooser window is open at once.  These files are automatically
 deleted by the system as the windows are closed.  However, this introduces
 a limitation of the viewer/chooser: no disk swaps can occur when using the
 viewer/chooser, unless under very controlled circumstances.  Specifically,
 if you need to change disks, the user cannot be allowed to open or close
 viewer/chooser windows.  This essentially means locking out all user
 activity (such as keyboard, mouse and menu access) until the original disk
 is swapped back in.  Perhaps in a later release we can overcome this
 limitation, but for now this rule stands.
      You'll find the necessary INCLUDES required to use the viewer/chooser
 already in the DESKTOP.MGR program, but commented out using the brace


                                     [16]


 brackets ( { like this } ).  If you want to use the viewer/chooser, merely
 remove the brace brackets.
 
      In the VIEWER.DIMS file, you'll find two arrays.  The first array is
 Scroll_Buffer$, and it is DIMed to 800 elements by default.  This controls
 the number of lines which can be in the viewer or chooser at any one time.
 Increasing this number will allow for more lines, but will consume more
 memory (string arrays can use gobs of memory).  Reducing this number will
 free up more variable space for other uses, but may result in problems if
 you need to view more lines than allowed by the DIM.

      The second array is Save_Lines%, and it is DIMed to 20 elements by
 default.  This controls the number of chooser/viewer windows which may be
 open at once.

      In the VIEWER.GLOBALS file, you'll find three variables which control
 some of the internal workings of the viewer/chooser.  The first is
 Scroll_Buffer_Max%.  This variable must be set to the exact same number of
 lines as the array Scroll_Buffer$ is DIMed to in the VIEWER.DIMS file.  The
 default value for Scroll_Buffer_Max% is 800 to match the default for the
 Scroll_Buffer$ DIM.  You must modify this variable if you modify the
 Scroll_Buffer$ DIM statement.

      The second and third variables, Scroll_Buffer_Level% and Reload! are
 used for managing the viewer and chooser windows.  NEVER USE THESE VARIABLE
 NAMES IN YOUR PROGRAMS.  DO NOT MODIFY THESE VARIABLES.  Modifying these
 variables will cause BAD THINGS to happen.
 
      The VIEWER file contains the heart of the viewer/chooser.  In this
 file are two PROCedure and one FUNCtion which you can call directly, and a
 few support PROCedures which you'll never need to call.
 
      We'll just deal with these in the order they appear in the file:
 
 PROC DISPLAY_FILE [Filename$, Fast!]
 
      This PROCedure will automatically read a file from disk, change the
 current window to a viewer window, and load the file into the view window,
 formatting it as it reads the file.  This is probably the most useful part
 of the entire viewer/chooser.  Using this, you can keep a library of
 information on disk, such as help files or descriptions, and load them into
 viewer windows as needed.  You can write the files using an ordinary word
 processor, as long as they are saved as ASCII files.

      There are two very unique features of this PROCedure: auto-formatting
 and background-updating.  Auto-formatting will process the text in the file
 as it is loaded into the scroll window to ensure that words are not
 `broken' as they wrap around the right margin of the window.  Essentially,
 it performs a real-time word wrap, filling in the lines word by word and
 automatically going the next line if it finds that the next word is too
 long for the current line.  This allows a text file to be stored in normal
 paragraph style format, without regard to the size of the window it will be
 placed in.  Because of this, when you create files to be viewed using
 DISPLAY_FILE, only a put CR [also known as RETURN, ENTER and CHR$(13)] at
 the end of your paragraphs, not at the end of each line.  This will allows
 for the greatest flexibility.  Auto-update is the second unique feature.
 What auto-update does is let you start viewing and scrolling through the
 file in the view window as it is being read from disk.  This means that the
 user does not need to wait for the whole file to be read from disk before
 he/she can start reading it.  As the file is read from disk, the scroll bar
 on the side of the viewer window is automatically updated.  Note that the


                                     [17]


 scroll bar is a "proportional scroll bar", which means it reflects not only
 the users position within the document being viewed, but also the size of
 the window of information relative to the entire document.  What this means
 is that if the scroll bar is half the length of the window, then what the
 user sees in the window is half of the file.  If the scroll bar is quite
 small, then what the user sees in the window represents only a small part
 of the overall document.  Even Windows 3.0 on that `other' computer doesn't
 have this feature yet.  Mac users are just getting it now for the first
 time with System Disk 7.0.  Apple IIgs users have had it for quite a while
 already.  Now Apple IIe/c users have it too.
 
      There are two parameters for DISPLAY_FILE, namely Filename$ and Fast!.
 No explanation is needed for the first parameter.  The second parameter
 allows you to speed up the viewer in certain situations where you know that
 there are no lines longer than 256 characters in the file you want to read.
 If this is the case, pass a TRUE to the Fast! parameter.  Using this
 feature on a file which contains lines longer than 256 lines [this means
 more than 256 characters before a CR/Enter/Return/CHR$(13)] will cause a
 fatal error.
 
      You must already have a window open when you call DISPLAY_FILE.  The
 currently open window will be used as the viewer window.  Here's an example
 of using display file:
 
      GOSUB Add_Dt_Window [ "File: A.FILE", 5, 10, 20, 70 ]
      GOSUB Display_File [ "A.FILE", FALSE ]
      GOSUB Close_DT_Window  { Now we're finished with the window }
 
      That's all that is required to view a file on disk.
 
 PROC Viewer [ Number_of_lines%, New!, Return!, ADDRESS Cancel! ]
 
      The viewer is what does the work of displaying and scrolling the
 information within your window.  As with the DISPLAY_FILE, you must already
 have opened the window you want to use.  Whatever the most current window
 is will be automatically converted to a scroll window.
      Here's a quick overview of the parameters that Viewer uses:
 Number_of_Lines% tells the viewer how many lines are in the scroll buffer.
 New! must be used whenever a new scroll window is opened.  Return! controls
 the background-updating feature.  Cancel! is a global variable which will
 tell the calling PROCedure/ROUTINE that the user has closed the viewer
 window (required to tell the routine doing background-updating to stop and
 close its files).
      Here's step by step instructions on how to use the viewer (auto-
 updating will be explained afterwards):
 
      1) Use Add_DT_Window to add the window you want to use as your scroll
 window.
      2) GOSUB Viewer [ 0, TRUE, TRUE, Cancel! ]
         This tells the viewer to prepare itself for a new scroll window.
 This involves writing information about the currently open scroll window
 (if any) to disk and initializing internal variables.  It also draws the
 scroll bar on the open window.
      3) Load your information into the array Scroll_Buffer$.  Each line in
 Scroll_Buffer$ will be a line in the scroll window.  Therefore, be sure
 that the strings in Scroll_Buffer$ are shorter than the width of the scroll
 window.  In other words, if the window you are using as your scroll window
 is only 15 characters wide, don't do this:
 
      Scroll_Buffer$(x) = "Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
 because that line is too wide for your window.  Also be sure not to exceed


                                     [18]


 the maximum number of scroll lines by checking the global variable
 Scroll_Buffer_Max%.
      4) GOSUB Viewer [ Number of lines, FALSE, FALSE, Cancel! ]
      5) Reset the Close! variable by making it FALSE.
 
      Those five steps are all you need.  Here's an example that will draw a
 scroll window containing as many lines as we can fit, with each line
 numbered:
 
      GOSUB Add_DT_Window ["Lines",4,3,20,76]
      GOSUB Draw_Scroll_Window [0, TRUE, TRUE, Cancel! ]
      FOR Loop% = 1 TO Scroll_Buffer_Max%
           Scroll_Buffer$ (Loop%) = "This is Line #"+STR$(Loop%)
      NEXT Loop%
      Return! = FALSE  { background-updating off }
      Cancel! = FALSE  { Doesn't really matter }
      New! = FALSE     { only use once for each window.. we did so above}
      GOSUB Viewer [ Loop%, New!, Return!, Cancel! ]
      Close! = FALSE  { Cancel will set close... we must reset it }
      GOSUB Pop_DT_Window  { We're finished with our window }
 
      This program segment will result in a scroll window with about 800
 lines (by default) containing "This is line #1" and so on.  The only
 problem with this is that we must wait for the loop to completely fill the
 array before we have a chance to look at it.  Using background updating, we
 can view the scroll window while more information is being loaded into it.
 Background updating works basically the same way as above, except that
 control from the step four back to step three until complete.  When the
 RETURN! parameter is true, the Viewer will execute for a short time,
 allowing the user to use the scroll keys to view the scroll buffer.  Then,
 the viewer will pass control back to the calling routine, which will spend
 a short time loading more information  into the buffer and then passing
 control back to the viewer.  This continuous until there is no more
 information to load into the buffer, at which time the viewer should be
 called with Return! set to FALSE.  The best way to show this is by
 modifying the above example to work with auto-updating:
 
 
      GOSUB Add_DT_Window ["Lines",4,3,20,76]   { same as above }
      GOSUB Draw_Scroll_Window [0, TRUE, TRUE, Cancel! ]   {same as above}
 
      Return! = FALSE  { background-updating ON }
      Cancel! = FALSE  { initialize this }
      New! = FALSE     { we only use this once.. above }
     
      FOR Loop% = 1 TO Scroll_Buffer_Max% UNTIL Cancel!
           Scroll_Buffer$ (Loop%) = "This is Line #"+STR$(Loop%)
           GOSUB Viewer [ Loop%, New!, Return!, Cancel! ]
      NEXT Loop%
     
      IF NOT Cancel!
           Return! = FALSE  { background-updating off }
           Cancel! = FALSE  { Doesn't really matter }
           New! = FALSE  
           GOSUB Viewer [ Loop%, New!, Return!, Cancel! ]  {same as above}
      ENDIF
     
      Close! = FALSE  { Cancel will set close... we must reset it }
      GOSUB Pop_DT_Window  { We're finished with our window }
 
      This program segment is essentially the same as above, except that now


                                     [19]


 we are calling the viewer from within the loop.  The viewer executes for a
 short time and then passes control back.  The only other difference is that
 we must be able to abort out of the loop if the user closes the viewer box
 while we have passed control to it.  This is achieved by using the Cancel!
 global variable.
 
      When using the viewer, there is built-in help that tells the user what
 they can do.  Basically, pressing OPEN-APPLE along with a number from 1 to
 0 (along the top of the keyboard) will jump to that relative position in
 the buffer.  For example, OPEN-APPLE-5 will jump to the middle of the
 scroll buffer.  OPEN-APPLE-UP ARROW and OPEN-APPLE-DOWN ARROW will jump to
 the very top or bottom of the scroll buffer, respectively.  Pressing the up
 or down arrow keys or clicking on those buttons in the side bar will cause
 the scroll buffer to scroll one line.
 
 
 FUNC Chooser [ Number_of_Lines%, New! ]
 
      The chooser allows you to display a long list of items in a scroll
 window and have the user pick an item.  It is similar to the Viewer,
 however it is a function and does not support background-updating.
 
      To use the chooser, you use the exact same steps as the viewer:
 
      1) Add a new window
      2) Dummy_Variable% = FN Chooser [ 0, TRUE ]  { to initialize it }
      3) Load your choices into your array
      4) Choice% = FN Chooser [ Number of choices, FALSE ]
 
      This will cause a scroll window to appear which lists the lines in
 scroll buffer.  The same rules regarding line widths apply.  There will be
 a lightbar which the user can scroll down by using the arrow keys (or using
 the mouse and clicking on the arrow buttons in the scroll bar).  Pressing
 space will toggle the lightbar on and off, allowing for faster scrolling
 (when the light bar is off).  When the user presses enter, the line number
 which the light bar was on will be returned by the function.  If a 0 is
 returned, the user closed the chooser window without picking anything.
 Here's an example based on the example we used for the viewer:
 
      GOSUB Add_DT_Window ["Lines",4,3,20,76]
      GOSUB Draw_Scroll_Window [0, TRUE, TRUE, Cancel! ]
      FOR Loop% = 1 TO Scroll_Buffer_Max%
           Scroll_Buffer$ (Loop%) = "This is Line #"+STR$(Loop%)
      NEXT Loop%
      New! = FALSE     { only use once for each window.. we did so above}
      Choice% = FN Chooser [ Loop%, New! ]
      Close! = FALSE  { Cancel will set close... we must reset it }
      GOSUB Pop_DT_Window  { We're finished with our window }
 
      The variable Choice% now contains the line number which the user was
 on when he/she pressed enter.  To see the actual line:
 
      PRINT Scroll_Buffer$ (Choice%)
 
 And that's all you need to know about the Viewer/Chooser.  Again, if you
 have questions, your first resource should be the MOUSE.DEMO program on
 your distribution disk.  Otherwise, you can contact me by:
 
 Phone:   (416) 731 - 1544   { Note: East cost time }
 
 EMAIL (GENIE):    MICOL.SYSTEM


                                     [20]


       (Proline):  ronl@pro-micol
       (Internet): ronl@pro-micol.cts.com
 
 Paper Mail:   Ron Lewin
               Micol Systems
               9 Lynch Road
               Willowdale, ON
               CANADA    M2J 2V6


Retour au sommaire
hr docs


Source: ASCII.


PROGRAM Ascii
@ LIST
@ OPTIMIZ
INT (A-R): STR (S-Z)

{ Print a message, then delay
 until any key is pressed }

  PROC Hit_Key [ Column ]
    PRINT TAB (Column);
    INVERSE
    PRINT "Hit any key to continue";
    REPEAT
      INKEY A$
    UNTIL A$ <> ""
   NORMAL
   PRINT
 ENDPROC


  PROC Do_Ascii_Chart [Kolumn%]
     HOME
     PRINT TAB (22);"The Micol Advanced Utilities ASCII Chart"
     VTAB (3)
     First% = 0
     Last% = 127
     FOR Counter = 1 TO 2
        FOR Ctr = First% TO Last%
           Kol% = (((Ctr) MOD 8) * 10) + 1
           IF Ctr < 32 THEN BEGIN
              INVERSE
              PRINT TAB (Kol%);CHR$ (Ctr + 64);
              NORMAL
              PRINT TAB (Kol% + 5); Ctr;TAB (Kol% + 8);"|";
           ELSE BEGIN
              PRINT TAB (Kol%); CHR$ (Ctr); TAB (Kol% + 5); Ctr; TAB (Kol% + 8);"|";
           ENDIF
           IF ((Ctr + 1) MOD 8) = 0 THEN BEGIN
              PRINT
              IF Counter = 1 THEN MS_TEXT
              FOR Ctr1 = 1 TO 78
                 PRINT "L";     { Make a straight line in the center }
              NEXT Ctr1
              IF Counter = 1 THEN MS_TEXT
              PRINT
           ENDIF
           IF (Counter = 1) THEN BEGIN
              IF Ctr = 79 THEN BEGIN
                 PRINT
                 GOSUB Hit_Key [Kolumn%]
                 HOME
              ENDIF
           ENDIF
        NEXT Ctr
        IF Counter = 1 THEN BEGIN
           First% = 64
           Last% = 95
           PRINT TAB (31);"MouseText ASCII Chart"
           PRINT
           MS_TEXT
        ENDIF
     NEXT Counter
     MS_TEXT
     GOSUB Hit_Key [Kolumn%]
  ENDPROC

  GOSUB Do_Ascii_Chart [30]
END


Retour au sommaire
hr docs


Source: Calculator.


PROGRAM Micol_Calculator
  @ LIST      { Show compilation }
  @ OPTIMIZ   { Save memory, and speed up calculator }
  @ NOT_C     { Disallow <Control> C to terminate }
  INT (A-R): STR (S-Z)

{ Define Micol Software Calculator function display }

  DATA "Sin","Cos","Tan", "MC"
  DATA "ArcSin","ArcCos","ArcTan", "MR"
  DATA "N!","1/N","Sqrt","M-"
  DATA "Sqr","Cube Root","Cube","M+"
  DATA "LOG","LN ", "e ^ N","Erase"
  DATA "Clear","Degrees", "Hex OFF","OFF"

{ Define only array }

  DIM Functions$ (6,4)

  FOR Ktr1 = 1 TO 6   { Read calculator functions display }
   FOR Ktr2 = 1 TO 4
    READ Functions$ (Ktr1,Ktr2)
   NEXT Ktr2
  NEXT Ktr1

{ Declare all global variables at top of calculator }

  Sum& = 0                        { Initial value is zero }
  Left_Side$ = ""
  Right_Side$ = ""
  Temp_Right$ = ""
  Calc_Error! = FALSE
  Hex_Flag! = FALSE               { Assume decimal mode }
  Right_Display% = 55             { Right most numeric display }
  Quit_Flag! = FALSE              { Initialize the main calculator loop }
  Prevous_Op$ = ""
  Op_Flag! = FALSE
  Memory& = 0                     { Memory is initially empty }
  Spaces$ = "                          "
  Degree_Convert& = 57.2957795    { Convert between degrees and radians }
  Row% = 1
  Column% = 1
  Max_Chars% = 8                  { When decimal display, allow 8 character input }
  Top_Choice% = 1


{ Start of procedures for the calculator }

{ Place the calculated value within the display window,
  clear the window first, then place at the proper position
  within the window }

  PROC Out_Put [String$]
   IF LEN (String$) = 0 THEN String$ = "0"
   VTAB (8)
   PRINT TAB (29);Spaces$;
   IF NOT Hex_Flag! THEN BEGIN
    IF INDEX (".", String$) > 0 THEN BEGIN { Remove redundent zeroes? }
     IF INDEX ("E", String$) = 0 THEN BEGIN
      FOR Ctr% = LEN (String$) TO 1 STEP -1
       IF RIGHT$ (String$, 1) = "0" THEN \
        String$ = LEFT$ (String$, LEN (String$) -1)
      NEXT Ctr%
      IF LEN (String$) > 8 THEN BEGIN   { Set 8 digit accuracy }
       Zeroes$ = "0000000000"
       IF INDEX (".", String$) < 6 THEN BEGIN
        IF LEN (String$) > 10 THEN BEGIN
         String$ = LEFT$ (String$, 10)
        ENDIF
       ENDIF
       No_Of_Zeroes% = LEN (String$) - INDEX (".", String$) - 1
       IF No_Of_Zeroes% > 0 THEN BEGIN
        Accuracy$ = "." + LEFT$ (Zeroes$, No_Of_Zeroes%) + "5"
        Number& = VAL (String$) + VAL (Accuracy$)
        String$ = STR$ (Number&)
        String$ = LEFT$ (String$, LEN (String$) - 1)
        FOR Ctr% = LEN (String$) TO 1 STEP -1
         IF RIGHT$ (String$, 1) = "0" THEN \
          String$ = LEFT$ (String$, LEN (String$) -1)
        NEXT Ctr%
       ENDIF
      ENDIF
      IF RIGHT$ (String$, 1) = "." THEN \
       String$ = LEFT$ (String$, LEN (String$) - 1)
     ENDIF
    ENDIF
   ENDIF
   GOSUB Dec_2_Hex [String$]
   VTAB (8)
   PRINT TAB (Right_Display% - LEN (String$));String$
  ENDPROC  { Out_Put }

{ Convert the current result from decimal to hexadecimal }

  PROC Dec_2_Hex [ADDRESS Number$]
   IF Hex_Flag! THEN BEGIN
    Minus_Flag! = FALSE
    String$ = ""
    Number& = VAL (Number$)
    Number& = INT (Number&)
    IF Number& < 0 THEN BEGIN
     Minus_Flag! = TRUE
     Number& = ABS (Number&)
    ENDIF
    IF Number& < 4.294967296E9 THEN BEGIN { $100000000 }
     Hex_Place& = 268435456         { $10000000 }
     Flag! = FALSE
     FOR Ctr% = 1 TO 8
      Temp& = INT (Number& / Hex_Place&)
      IF Temp& > 9 THEN Num& = Temp& + 7 ELSE Num& = Temp&
      IF Num& > .5 THEN { Allow Trailing zeroes } Flag! = TRUE
      IF Flag! THEN BEGIN
       String$ = String$ + CHR$ (Num& + 48)
       Number& = Number& - (Temp& * Hex_Place&)
      ENDIF
      Hex_Place& = Hex_Place& / 16
     NEXT Ctr%
     IF String$ = "" THEN BEGIN
      Number$ = "0"
     ELSE BEGIN
      IF Minus_Flag! THEN String$ = "-" + String$
      Number$ = String$
     ENDIF
    ELSE BEGIN    { An error has happened }
     BELL
     VTAB (8)
     PRINT TAB (29);Spaces$;TAB (29);"Hex err, hit key";
     Left_Side$ = ""
     Right_Side$ = ""
     Temp_Right$ = ""
     Op_Flag! = FALSE
     REPEAT       { Input character control loop }
      INKEY Response$
     UNTIL Response$ <> ""
     GOSUB Out_Put [Right_Side$]
    ENDIF
   ENDIF
  ENDPROC  { Dec_To_Hex }

{ Convert the current result from hexadecimal to decimal }

  PROC Hex_To_Dec [ADDRESS String$]
   IF Hex_Flag! THEN BEGIN
    Sum& = 0
    Hex_Place& = 1
    FOR Ctr% = LEN (String$) TO 1 STEP -1
     Char$ = MID$ (String$, Ctr%, 1)
     Temp% = ASC (Char$) - 48
     IF Temp% > 9 THEN Temp% = Temp% - 7
     Sum& = Sum& + Temp% * Hex_Place&
     Hex_Place& = Hex_Place& * 16
    NEXT Ctr%
    String$ = STR$ (Sum&)
   ENDIF
  ENDPROC  { Hex_To_Dec }

{ Display the contents of the memory on top of the calculator }

  PROC Out_Memory [Mem&]
   String$ = STR$ (Mem&)
   VTAB (5)
   IF INDEX (".", String$) > 0 THEN BEGIN { Redundent zeroes? }
    IF INDEX ("E", String$) = 0 THEN BEGIN
     FOR Ctr% = LEN (String$) TO 1 STEP -1
      IF RIGHT$ (String$, 1) = "0" THEN \
       String$ = LEFT$ (String$, LEN (String$) -1)
     NEXT Ctr%
    ENDIF
   ENDIF
   PRINT TAB (29);Spaces$;TAB (21);"Memory = ";String$
  ENDPROC  { Out_Memory }

{ Display the functions available to the user within the calculator }

  PROC Print_Functions
   VTAB (13)
   FOR Ctr1 = 1 TO 6
    PRINT TAB (20);"|";
    FOR Ctr2 = 1 TO 4
     PRINT TAB (Ctr2 * 10 + 15);Functions$ (Ctr1, Ctr2);
    NEXT Ctr2
    PRINT TAB (62);"|"
   NEXT Ctr1
  ENDPROC  { Print_Functions }

{ High light the current function by placing it in inverse }

  PROC HiLite_Func
   INVERSE
   VTAB (Row% + 12)
   PRINT TAB (Column% * 10 + 15);Functions$ (Row%, Column%)
   NORMAL
  ENDPROC  { HiLite_Func }

{ Mark the current function as no longer selected by turn off the inverse,
 the is done just before the next function selected is placed in inverse }

  PROC UnHiLite_Func
   VTAB (Row% + 12)
   PRINT TAB (Column% * 10 + 15);Functions$ (Row%, Column%)
  ENDPROC  { UnHiLite_Func }


{ Draw the calculator on the screen, don't display the functions yet }

  PROC Show_Screen
   HOME
   VTAB (4)
   PRINT TAB (20);"___________________________________________"
   PRINT TAB (20);"|";TAB (62);"|"
   PRINT TAB (20);"|";TAB (29);"__________________________";TAB (62);"|"
   PRINT TAB (20);"|";TAB (28);"|                          |";TAB (62);"|"
   PRINT TAB (20);"|";TAB (28);"|                          |";TAB (62);"|"
   PRINT TAB (20);"|";TAB (28);"|__________________________|";TAB (62);"|"
   PRINT TAB (20);"|_________________________________________|"
   PRINT TAB (20);"|/\/\/\/\";
   INVERSE
   PRINT "Micol Software Calculator";
   NORMAL
   PRINT "/\/\/\/\|"
   PRINT TAB (20);"|";TAB (62);"|";
   MS_TEXT
   PRINT TAB (21);"LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL"
   MS_TEXT
   PRINT TAB (20);"|";TAB (62);"|"
   PRINT TAB (20);"|";TAB (62);"|"
   VTAB (19)
   PRINT TAB (20);"|";TAB (62);"|"
   PRINT TAB (20);"|    7         8         9        %";TAB (62);"|"
   PRINT TAB (20);"|    4         5         6        -";TAB (62);"|"
   PRINT TAB (20);"|    1         2         3        *";TAB (62);"|"
   PRINT TAB (20);"|    0         .         +/=      /";TAB (62);"|"
   PRINT TAB (20);"|_________________________________________|";TAB (1);
   GOSUB Out_Put ["0"]
   HTAB (1)
  ENDPROC  { Show_Screen }

{ Main control of the calculator function }

  PROC Calculator
   Quit_Flag! = FALSE  { Initialize the main calculator loop }
   Esc_Flag! = FALSE
   REPEAT              { Exit control loop }
    IF Right_Side$ = "0" THEN Right_Side$ = ""
    REPEAT             { Input character control loop }
     INKEY Response$
    UNTIL Response$ <> ""
    Response$ = UPPER$ (Response$)
    Ascii% = ASC (Response$)
    IF Ascii% = Esc THEN Esc_Flag! = TRUE

    CASE_OF Ascii%
     DO ".", "0", "1", "2", "3", "3", "4", \
        "5", "6", "7", "8", "9", "A", \
        "B", "C", "D", "E", "F"
      IF Op_Flag! THEN BEGIN
       VTAB (8)
       PRINT TAB (29);Spaces$;
       Left_Side$ = Right_Side$
       Temp_Right$ = ""
       Op_Flag! = FALSE
      ENDIF
      IF LEN (Temp_Right$) < Max_Chars% THEN BEGIN
       IF Hex_Flag! OR (INDEX (Response$,"ABCDEF") = 0) THEN BEGIN
        Temp_Right$ = Temp_Right$ + Response$
        VTAB (8)
        PRINT TAB (Right_Display% - LEN (Temp_Right$));Temp_Right$
        Right_Side$ = Temp_Right$
        GOSUB Hex_To_Dec [Right_Side$]
       ENDIF
      ENDIF
     ENDDO

     DO 8           { Left arrow }
      GOSUB UnHiLite_Func
      Column% = Column% - 1
      IF Column% < 1 THEN BEGIN
       Column% = 4
       Row% = Row% - 1
       IF Row% < 1 THEN BEGIN
        Row% = 6
       ENDIF
      ENDIF
      GOSUB HiLite_Func
     ENDDO

     DO 10          { Down Arrow }
      GOSUB UnHiLite_Func
      Row% = Row% + 1
      IF Row% > 6 THEN BEGIN
       Row% = 1
       Column% = Column% + 1
       IF Column% > 4 THEN Column% = 1
      ENDIF
      GOSUB HiLite_Func
     ENDDO

     DO 11          { Up arrow }
      GOSUB UnHiLite_Func
      Row% = Row% - 1
      IF Row% < 1 THEN BEGIN
       Row% = 6
       Column% = Column% - 1
       IF Column% < 1 THEN Column% = 4
      ENDIF
      GOSUB HiLite_Func
     ENDDO

     DO 21          { Right arrow }
      GOSUB UnHiLite_Func
      Column% = Column% + 1
      IF Column% > 4 THEN BEGIN
       Column% = 1
       Row% = Row% + 1
       IF Row% > 6 THEN BEGIN
        Row% = 1
       ENDIF
      ENDIF
      GOSUB HiLite_Func
     ENDDO

     DO "*"
      IF LEN (Left_Side$) > 0 THEN BEGIN
       Previous_Op% = ASC (Previous_Op$)
       CASE_OF Previous_Op%
        DO "*"
         Sum& = VAL (Left_Side$) * VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO

        DO "+"
         Sum& = VAL (Left_Side$) + VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO

        DO "-"
         Sum& = VAL (Left_Side$) - VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO

        DO "/"
         Sum& = VAL (Left_Side$) / VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO
       ENDCASE
      ENDIF
      VTAB (8)
      PRINT TAB (29);Response$;
      Op_Flag! = TRUE
      Previous_Op$ = Response$
     ENDDO

     DO "+", "="
      IF LEN (Left_Side$) > 0 THEN BEGIN
       Previous_Op% = ASC (Previous_Op$)
       CASE_OF Previous_Op%
        DO "*"
         Sum& = VAL (Left_Side$) * VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO
        DO "+"
         Sum& = VAL (Left_Side$) + VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO

        DO "-"
         Sum& = VAL (Left_Side$) - VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO

        DO "/"
         Sum& = VAL (Left_Side$) / VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO
       ENDCASE
      ENDIF
      VTAB (8)
      PRINT TAB (29);Response$;
      Op_Flag! = TRUE
      IF Response$ = "+" THEN BEGIN
       Previous_Op$ = "+"
      ELSE BEGIN    { Response is = }
       Left_Side$ = ""
       Temp_Right$ = ""
       Previous_Op$ = ""
      ENDIF
     ENDDO

     DO "%"
      Sum& = VAL (Right_Side$)
      Sum& = Sum& * .01
      Right_Side$ = STR$ (Sum&)
      GOSUB Out_Put [Right_Side$]
     ENDDO

     DO "-"
      IF LEN (Left_Side$) > 0 THEN BEGIN
       Previous_Op% = ASC (Previous_Op$)
       CASE_OF Previous_Op%
        DO "*"
         Sum& = VAL (Left_Side$) * VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO

        DO "+"
         Sum& = VAL (Left_Side$) + VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO

        DO "-"
         Sum& = VAL (Left_Side$) - VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO

        DO "/"
         Sum& = VAL (Left_Side$) / VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO
       ENDCASE
      ENDIF
      Op_Flag! = TRUE
      Previous_Op$ = Response$
      VTAB (8)
      PRINT TAB (29);Response$;
     ENDDO

     DO "/"
      IF LEN (Left_Side$) > 0 THEN BEGIN
       Previous_Op% = ASC (Previous_Op$)
       CASE_OF Previous_Op%
        DO "*"
         Sum& = VAL (Left_Side$) * VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO

        DO "+"
         Sum& = VAL (Left_Side$) + VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO

        DO "-"
         Sum& = VAL (Left_Side$) - VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO

        DO "/"
         Sum& = VAL (Left_Side$) / VAL (Right_Side$)
         Right_Side$ = STR$ (Sum&)
         GOSUB Out_Put [Right_Side$]
        ENDDO
       ENDCASE
      ENDIF
      Op_Flag! = TRUE
      Previous_Op$ = Response$
      VTAB (8)
      PRINT TAB (29);Response$;
     ENDDO

     DO 13          { <CR> Function referenced }
      HTAB (1)
      Temp_Right$ = ""
      Operation% = (Row% - 1) * 4 + Column%
      CASE_OF Operation%
       DO 1  { SIN }
        Op_Flag! = TRUE
        Sum& = VAL (Right_Side$)
        Sum& = SIN (Sum& / Degree_Convert&)  { Convert to radians }
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 2        { COS }
        Op_Flag! = TRUE
        Sum& = VAL (Right_Side$)
        Sum& = COS (Sum& / Degree_Convert&)  { Convert to radians }
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 3        { TAN }
        Op_Flag! = TRUE
        Sum& = VAL (Right_Side$)
        Sum& = TAN (Sum& / Degree_Convert&)  { Convert to radians if necessary}
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 4        { Memory clear }
        Op_Flag! = TRUE
        Memory& = 0
        GOSUB Out_Memory [Memory&]
       ENDDO

       DO 5        { ARC SIN }
        Op_Flag! = TRUE
        Sum& = VAL (Right_Side$)
        Sum& = ATN ( Sum& / SQR (-Sum& * Sum& + 1 ))
        Sum& = Sum& * Degree_Convert&
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 6        { ARC COS }
        Op_Flag! = TRUE
        Sum& = VAL (Right_Side$)
        Sum& = -1 * ATN ( Sum& / SQR (-Sum& * Sum& + 1 )) + 1.57079633
        Sum& = Sum& * Degree_Convert&
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 7        { ARC TAN }
        Op_Flag! = TRUE
        Sum& = VAL (Right_Side$)
        Sum& = ATN ( Sum& ) * Degree_Convert&
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 8        { Memory recall }
        Op_Flag! = TRUE
        Sum& = Memory&
        IF Left_Side$ = "" THEN \
         Left_Side$ = Right_Side$
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 9        { N! }
        Op_Flag! = TRUE
        IF LEN (Right_Side$) = 0 THEN \
         Right_Side$ = "0"
        Sum& = VAL (Right_Side$)
        Sum& = INT (Sum& + .0001)
        IF Sum& < 2 THEN BEGIN
         Sum& = 1
        ELSE BEGIN
         Num& = 1
         FOR Ctr& = 2 TO Sum&
          Num& = Num& * Ctr&
         NEXT Ctr&
         Sum& = Num&
        ENDIF
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 10       { 1 / N }
        Op_Flag! = TRUE
        Sum& = VAL (Right_Side$)
        Sum& = 1.0 / Sum&
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 11       { Sqrt }
        Op_Flag! = TRUE
        Sum& = VAL (Right_Side$)
        Sum& = SQR (Sum&)
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 12       { Memory subtract }
        Op_Flag! = TRUE
        Sum& = VAL (Right_Side$)
        Memory& = Memory& - Sum&
        GOSUB Out_Memory [Memory&]
       ENDDO

       DO 13       { Sqr }
        Op_Flag! = TRUE
        Sum& = VAL (Right_Side$)
        Sum& = Sum& * Sum&
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 14       { Cube Root }
        Sum& = VAL (Right_Side$)
        Sum& = EXP (LOG (Sum&) / 3)
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 15       { Cube }
        Sum& = VAL (Right_Side$)
        Sum& = Sum& * Sum& * Sum&
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 16       { Memory add }
        Op_Flag! = TRUE
        Sum& = VAL (Right_Side$)
        Memory& = Sum& + Memory&
        GOSUB Out_Memory [Memory&]
       ENDDO

       DO 17       { LOG N }
        Sum& = VAL (Right_Side$)
        Sum& = LOG (Sum&) * 0.434294482
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 18       { LN N }
        Sum& = VAL (Right_Side$)
        Sum& = LOG (Sum&)
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 19       { e ^ N }
        Sum& = VAL (Right_Side$)
        Sum& = EXP (Sum&)
        Right_Side$ = STR$ (Sum&)
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 20       { Erase }
        Sum& = 0
        Left_Side$ = ""
        Right_Side$ = ""
        Temp_Right$ = ""
        Op_Flag! = FALSE
        Previous_Op$ = ""
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 21       { Clear }
        Right_Side$ = ""
        Temp_Right$ = ""
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 22       { Degrees }
        IF Degree_Convert& < 2 THEN BEGIN
         Degree_Convert& = 57.2957795
         Functions$ (6,2) = "Degrees"
        ELSE BEGIN
         Degree_Convert& = 1
         Functions$ (6,2) = "Radians"
        ENDIF
        GOSUB Print_Functions
        GOSUB HiLite_Func
       ENDDO

       DO 23       { HEX }
        IF Hex_Flag! THEN BEGIN
         Hex_Flag! = FALSE
         Max_Chars% = 17
         Functions$ (6,3) = "Hex OFF"
        ELSE BEGIN
         Hex_Flag! = TRUE
         Max_Chars% = 17
         Functions$ (6,3) = "Hex ON "
        ENDIF
        GOSUB Print_Functions
        GOSUB HiLite_Func
        GOSUB Out_Put [Right_Side$]
       ENDDO

       DO 24       { Quit Calculator }
        Quit_Flag! = TRUE
       ENDDO
      ENDCASE
     ENDDO
    ENDCASE
   UNTIL Quit_Flag! OR Esc_Flag!
  ENDPROC  { Calculator }

{ First line of executable code }

  ROUTINE Kalculator
  Error_Flag! = FALSE
  GOSUB Show_Screen
  GOSUB Print_Functions
  GOSUB HiLite_Func
  GOSUB Out_Memory [Mem&]
  ONERR GOTO Error_Handle       { Print error message if error }
  ROUTINE Error_Handle
  IF Error_Flag! THEN BEGIN
   Calc_Error! = TRUE
   BELL
   VTAB (8)
   PRINT TAB (29);Spaces$;TAB (29);"Error, hit key";
   Sum& = 0
   Left_Side$ = ""
   Right_Side$ = ""
   Temp_Right$ = ""
   Op_Flag! = FALSE
   REPEAT           { Input character control loop }
    INKEY Response$
   UNTIL Response$ <> ""
   GOSUB Out_Put [Right_Side$]
  ENDIF
{ End of error routine }
  Error_Flag! = TRUE
  GOSUB Calculator
  HOME
  END


Retour au sommaire
hr docs


Source: Filer.


FILER1.TXT:

PROGRAM Micol_Filer
  @ LIST      { Show compilation }
  @ OPTIMIZ   { Save memory, and speed up Filer }
  @ NOT_C     { Disallow <Control> C to terminate }
  INT (A-R): STR (S-Z)

{ Define Micol Media Management display }

  DATA "Copy Files"
  DATA "Delete Files"
  DATA "Verify Files"
  DATA "Show file information"
  DATA "Rename Files"
  DATA "Lock Files"
  DATA "Unlock Files"
  DATA "Read File"
  DATA "Display Online Volumes"
  DATA "Catalog Disk"
  DATA "Set Default Prefix"
  DATA "Create Directory File"
  DATA "Set Catalog Order"
  DATA "File Find"
  DATA "Quit Micol Media Management"

{ Define file display order display }

  DATA "Sequential Order"
  DATA "File Order"
  DATA "Type Order"
  DATA "Date Of Modification Order"
  DATA "Size Order"

{ Define all arrays }

  DIM Help$ (15),Files$ (54), Locked$ (54)
  DIM Temp_Files (54), Order$ (5), Volumes (20)
  DIM Directories$ (100), Values% (100)
  DIM From_Prefixes$ (50), To_Prefixes$ (50)
  DIM Functions$ (6,4), Top_Level$ (6)
  DIM Found_Dirs$ (100), Copy_Files$ (54)
  DIM Sizes& (100)


{ Set the global variables and values for the Filer }

  Last_Entry = 0
  Selection% = 1
  File_Name$ = ""
  Volumes% = 0
  Old_Prefix$ = ""
  Yes_NO_Esc$ = "YN" + CHR$ (27)
  Cat_Order = 1
  Esc = 27
  Esc_Flag! = FALSE
  Copy_Flag! = FALSE
  Select_Flag! = TRUE
  Volume_Info = ""
  Months$ = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"

{ Read DATA strings into arrays for screen displays }

  FOR Ktr = 1 TO 15 { Read Disk Utilities Display }
    READ Help$ (Ktr)
  NEXT Ktr

  FOR Ktr = 1 to 5 { Read Catalog order display }
    READ Order$ (Ktr)
  NEXT Ktr

{ Define the Procedures for the disk utilities }

{ Place all online volumes into the online
 buffer for later manipulation }

  PROC Get_Volumes
    Previous = 1
    Volumes% = 0
    Flag! = FALSE
    CR$ = CHR$ (13)
    String = ONLINE$
    Array_Ctr = 0
    Ctr = 1
    REPEAT
      Last = INDEX (CR$, String, Ctr)
      IF Last > 0 THEN BEGIN
        Temp = MID$ (String, Previous, Last - Previous)
        IF LEN (Temp) > 0 THEN BEGIN
          Array_Ctr = Array_Ctr + 1
          Files$ (Array_Ctr) = Temp
        ENDIF
        Ctr = Ctr + 1
        Previous = Last + 1
        Volumes% = Array_Ctr
      ELSE BEGIN
        Flag! = TRUE
      ENDIF
    UNTIL Flag! OR Ctr > 14
  ENDPROC

{ Place the current catalog into the catalog buffer
 for later manipulation, or display }

  PROC Simple_Get_Cat
    Flag! = FALSE
    Last_Entry = 0
    String$ = CAT$      { Eat the volume name }
    FOR Ctr = 1 TO 1000 { Must read entire catalog } UNTIL Flag!
      String$ = CAT$
      IF PEEK (48881) = 0 THEN BEGIN
        IF Ctr < 55 THEN BEGIN
          Files$ (Ctr) = String$
          Locked$ (Ctr) = LEFT$ (String$,1)
          Last_Entry = Ctr
        ENDIF
      ELSE BEGIN
        Flag! = TRUE
        CR$ = CHR$ (13)
        Position = INDEX (CR$,String$)
        Volume_Info = MID$ (String$, Position + 1)
        IF Position > 2 THEN BEGIN
          Files$ (Ctr) = LEFT$ (String$, Position - 1)
          Locked$ (Ctr) = LEFT$ (String$,1)
          Last_Entry = Ctr
        ENDIF
      ENDIF
    NEXT Ctr
  ENDPROC


{ Place the Directory into the buffer, reorder
 according to user wishes }

  PROC Get_Catalog
    GOSUB Simple_Get_Cat
    CASE_OF Cat_Order

      DO 2         { Sort by file names }
        FOR Ctr = 1 TO Last_Entry
          File_End = INDEX ("  ",Files$ (Ctr))
          File_Name$ = MID$ (Files$ (Ctr), 2, File_End)
          Temp_Files (Ctr) = UPPER$ (File_Name$)
        NEXT Ctr
      ENDDO

      DO 3         { Sort by type }
        FOR Ctr = 1 TO Last_Entry
          Temp_Files (Ctr) = MID$ (Files$ (Ctr), 20, 3)
        NEXT Ctr
      ENDDO

      DO 4         { Sort by date }
        FOR Ctr = 1 TO Last_Entry
          Temp = MID$ (Files$ (Ctr), 36, 9)
          Mon$ = MID$ (Temp, 4, 3)
          Num = INDEX (Mon$, Months$)
          IF Num > 0 THEN BEGIN    { Is there a date? }
            Num = (Num + 3) / 4
            Num$ = STR$ (Num)
            IF LEN (Num$) = 1 THEN Num$ = "0" + Num$
            Temp_Files (Ctr) = MID$ (Temp,7) + Num$ + LEFT$ (Temp, 3)
          ELSE Temp_Files (Ctr) = "None"
        NEXT Ctr
      ENDDO

      DO 5         { Sort by size }
        FOR Ctr = 1 TO Last_Entry
          Temp = MID$ (Files$ (Ctr), 74) { Isolate EOF }
          End_File = INDEX (" ",Temp)
          IF End_File > 1 THEN BEGIN     { Strip end spaces }
            Temp = LEFT$ (Temp, End_File - 1)
          ENDIF
          WHILE LEN (Temp) < 6
            Temp = "0" + Temp
          WEND
          Temp_Files (Ctr) = Temp
        NEXT Ctr
      ENDDO
    ENDCASE

{ Do the actual sort using a Shell sort }

    IF Cat_Order > 1 THEN BEGIN
      Dist = 1
      WHILE Dist < Last_Entry
        Dist = Dist * 3 + 1
      WEND
      WHILE Dist > 1
        Dist = Dist / 3
        Finish = Last_Entry - Dist
        FOR Ctr = 1 TO Finish
          Temp% = - Dist
          FOR Ctr1 = Ctr TO 1 STEP Temp%
            IF Temp_Files (Ctr1) > Temp_Files (Ctr1 + Dist) THEN BEGIN
              File_Name$ = Files$ (Ctr1)
              File_Name1$ = Files$ (Ctr1 + Dist)
              Files$ (Ctr1) = File_Name1$
              Files$ (Ctr1+Dist) = File_Name$
              File_Name$ = Temp_Files (Ctr1)
              File_Name1$ = Temp_Files (Ctr1 + Dist)
              Temp_Files (Ctr1) = File_Name1$
              Temp_Files (Ctr1+Dist) = File_Name$
            ENDIF
          NEXT Ctr1
        NEXT Ctr
      WEND    { Dist > 1 }
    ENDIF     { Cat_Order > 1 }
  ENDPROC     { Get_Catalog }

{ Get a particular file name for use by other routines.
 Do this by displaying volumes or files to the screen
 and having the user select the file by hitting the
 carriage return. If a file is a directory file, open
 that directory and let the user select another file. }

  PROC Get_VolumeName [ Column, ADDRESS Choice ]
    HOME
    GOSUB Get_Volumes
    VTAB (12 - Volumes%)
    Choice = 1
    PRINT TAB (Column );"Select a volume:"
    REPEAT
      FOR Ctr = 1 TO Volumes%
        IF Ctr = Choice THEN INVERSE
        VTAB (Ctr + 14 - Volumes%)
        PRINT TAB (Column);Files$ (Ctr)
        NORMAL
      NEXT Ctr
      VTAB (1)
      REPEAT     { Get the key press from the user }
        INKEY key$
      UNTIL Key$ <> ""
      Ascii = ASC (Key$)
      IF Ascii = 11 THEN BEGIN    { Up arrow }
        IF Choice > 1 THEN BEGIN
          Choice = Choice - 1
        ELSE BEGIN
          Choice = Volumes%
        ENDIF
        VTAB (Choice + 14)
      ELSE IF Ascii = 10 THEN BEGIN  { Down arrow }
        IF Choice < Volumes% THEN BEGIN
          Choice = Choice + 1
        ELSE BEGIN
          Choice = 1
        ENDIF
        VTAB (Choice + 14)
      ENDIF
    UNTIL Ascii = 13 OR Ascii = Esc
    IF Ascii = Esc THEN Esc_Flag! = TRUE
  ENDPROC          { Get_VolumeName }


{ Main file access routine. Display volumes, then display
 directories of the user selected volume, etc. Set the prefix
 to the desired directory, and return the sequential file number }

  PROC Get_FileName [ Top_Line$, Column, ADDRESS Choice, VALUE Space_Flag! ]
    VTAB (1)
    PRINT TAB (1); CHR$ (29); TAB (40 - (LEN (Top_Line$) / 2)); Top_Line$
    POKE 248, 2    { Set second line as top line }
    GOSUB Get_VolumeName [Column, Choice]
    IF NOT Esc_Flag! THEN BEGIN
      Volume = "/" + Files$ (Choice)
      PREFIX Volume
      GOSUB Do_Catalog [ Column, Choice, Space_Flag!]
    ENDIF
  ENDPROC          { Get_FileName }

{ Display a single directory to the screen,
 as display can have a max of 54 entries,
 let user know how many entries are above
 the screen, and how many are below. Allow
 user to access all entries. }

  PROC Do_Catalog [ Column, ADDRESS Choice, VALUE Space_Flag!]
    Flag! = FALSE
    UpArrow! = FALSE
    REPEAT
      HOME
      GOSUB Get_Catalog
      IF NOT Select_Flag! THEN BEGIN
        Flag! = TRUE
        FOR Ctr = 1 TO Last_Entry UNTIL NOT Flag! { Find DIR type entry }
          IF INDEX (" DIR ",Files$ (Ctr)) > 0 THEN Flag! = FALSE
        NEXT Ctr
      ENDIF
      IF NOT Flag! { Found a DIR file? } THEN BEGIN
        First = 1
        IF Last_Entry > 22 THEN BEGIN
          Last = 22
        ELSE BEGIN
          Last = Last_Entry
        ENDIF
        IF Last_Entry > 0 THEN BEGIN
          Choice = 1
          FOR Ctr = First TO Last
            IF Ctr = Choice THEN INVERSE
            VTAB (Ctr - First + 2)
            IF LEFT$ (Files$ (Ctr),1) = "^" { Selected? } THEN BEGIN
              MS_TEXT
              PRINT CHR$ (68);  { MouseText check }
              MS_TEXT
              PRINT MID$ (Files$ (Ctr), 2)
            ELSE PRINT Files$ (Ctr)
            NORMAL
          NEXT Ctr
          REPEAT
            IF Last_Entry > 22 THEN BEGIN
              POKE 248, 1      { Tell how many files not shown }
              INVERSE
              VTAB (1)
              PRINT TAB (1);Last - 22;" "; TAB (5);"more file";
              IF Last - 22 = 1 THEN \
                PRINT " "; \
              ELSE \
                PRINT "s";
              POKE 248, 2
              VTAB (24)
              PRINT TAB (1); Last_Entry - Last;" "; TAB (5);"more file";
              IF Last_Entry - Last = 1 THEN \
                PRINT " "; \
              ELSE \
                PRINT "s";
              HTAB (1)
              NORMAL
            ELSE BEGIN  { Less than one screen full }
              VTAB (1)
              PRINT TAB (1);"      "
            ENDIF
            VTAB (24)
            INVERSE
            PRINT TAB (17);"DIR= ";PREFIX$;CHR$ (29);TAB (1);
            NORMAL
            REPEAT     { Get the key press from the user }
              INKEY key$
            UNTIL Key$ <> ""
            Ascii = ASC (Key$)
            IF Ascii <> Esc THEN BEGIN
              IF Ascii = 11 THEN BEGIN    { Up arrow }
                VTAB (Choice - First + 2)
                PRINT TAB (1);CHR$ (29);
                IF LEFT$ (Files$ (Choice),1) = "^" THEN BEGIN
                  MS_TEXT
                  PRINT CHR$ (68);  { MouseText check }
                  MS_TEXT
                  PRINT MID$ (Files$ (Choice), 2)
                ELSE PRINT Files$ (Choice)
                IF Choice > 1 THEN BEGIN
                  Choice = Choice - 1
                  IF First > 1 THEN BEGIN
                    First = First - 1
                    Last = Last - 1
                  ENDIF
                  IF Choice > 21 THEN BEGIN
                    PRINT CHR$ (23); {Scrool the screen down}
                    VTAB (2)
                    IF LEFT$ (Files$ (Choice -21),1) = "^" THEN BEGIN
                      MS_TEXT
                      PRINT TAB (1);CHR$ (68);  { MouseText check }
                      MS_TEXT
                      PRINT MID$ (Files$ (Choice- 21), 2);CHR$ (29)
                    ELSE PRINT Files$ (Choice - 21);CHR$ (29)
                    VTAB (23)
                    PRINT TAB (1);CHR$ (29);
                    IF LEFT$ (Files$ (Choice),1) = "^" THEN BEGIN
                      MS_TEXT
                      PRINT TAB (1);CHR$ (68);  { MouseText check }
                      MS_TEXT
                      INVERSE
                      PRINT MID$ (Files$ (Choice), 2);CHR$ (29)
                    ELSE INVERSE:PRINT Files$ (Choice);CHR$ (29)
                    NORMAL
                    HTAB (1)
                  ENDIF
                ELSE BEGIN  { Choice was one }
                  Choice = Last_Entry
                  IF Choice > 22 THEN BEGIN
                    HOME
                    First = Choice - 21
                    Last = First + 21
                  ELSE BEGIN
                    First = 1
                    Last = Last_Entry
                  ENDIF
                  FOR Ctr = First TO Last
                    VTAB (Ctr - First + 2)
                    PRINT TAB (1);
                    IF LEFT$ (Files$ (Ctr),1) = "^" THEN BEGIN
                      MS_TEXT
                      PRINT CHR$ (68);  { MouseText check }
                      MS_TEXT
                      IF Ctr = Choice THEN INVERSE
                      PRINT MID$ (Files$ (Ctr), 2);CHR$ (29)
                    ELSE BEGIN
                      IF Ctr = Choice THEN INVERSE
                      PRINT Files$ (Ctr);CHR$ (29)
                    ENDIF
                    NORMAL
                  NEXT Ctr
                ENDIF
              ELSE IF Ascii = 10 THEN BEGIN  { Down arrow }
                VTAB (Choice - First + 2)
                IF LEFT$ (Files$ (Choice),1) = "^" THEN BEGIN
                  MS_TEXT
                  PRINT TAB (1);CHR$ (68);  { MouseText check }
                  MS_TEXT
                  PRINT MID$ (Files$ (Choice), 2);CHR$ (29)
                ELSE PRINT Files$ (Choice);CHR$ (29)
                IF Choice < Last_Entry THEN BEGIN
                  Choice = Choice + 1
                  IF Choice > 22 THEN BEGIN
                    First = First + 1
                    Last = Last + 1
                    PRINT CHR$ (22); { Scrool screen up }
                  ENDIF
                ELSE BEGIN
                  IF First > 1 THEN HOME
                  Choice = 1
                  First = 1
                  IF Last_Entry > 21 THEN BEGIN
                    Last = 22
                  ELSE BEGIN
                    Last = Last_Entry
                  ENDIF
                  FOR Ctr = First TO Last
                    VTAB (Ctr - First + 2)
                    IF LEFT$ (Files$ (Ctr),1) = "^" THEN BEGIN
                      MS_TEXT
                      PRINT TAB (1);CHR$ (68);  { MouseText check }
                      MS_TEXT
                      IF Ctr = Choice THEN INVERSE
                      PRINT MID$ (Files$ (Ctr), 2);CHR$ (29)
                    ELSE BEGIN
                      IF Ctr = Choice THEN INVERSE
                      PRINT Files$ (Ctr);CHR$ (29)
                    ENDIF
                    NORMAL
                  NEXT Ctr
                ENDIF
              ELSE IF Ascii = 8 THEN BEGIN  { Back arrow, previous DIR }
                Pre$ = PREFIX$
                Test_Flag! = FALSE
                Length% = LEN (Pre$)
                FOR Ctr = 1 TO Length% UNTIL Test_Flag!
                  Pre$ = LEFT$ (Pre$, LEN (Pre$) - 1)
                  IF RIGHT$ (Pre$, 1) = "/" THEN
                  Test_Flag! = TRUE
                NEXT Ctr
                IF LEN (Pre$) > 1 THEN BEGIN
                  PREFIX Pre$
                  HOME
                  GOSUB Get_Catalog
                  First = 1
                  IF Last_Entry > 22 THEN BEGIN
                    Last = 22
                  ELSE BEGIN
                    Last = Last_Entry
                  ENDIF
                  IF Last_Entry > 0 THEN BEGIN
                    Choice = 1
                    FOR Ctr = First TO Last
                      VTAB (Ctr - First + 2)
                      IF LEFT$ (Files$ (Ctr),1) = "^" THEN BEGIN
                        MS_TEXT
                        PRINT TAB (1);CHR$ (68);  { MouseText check }
                        MS_TEXT
                        IF Ctr = Choice THEN INVERSE
                        PRINT MID$ (Files$ (Ctr), 2);CHR$ (29)
                      ELSE BEGIN
                        IF Ctr = Choice THEN INVERSE
                        PRINT Files$ (Ctr);CHR$ (29)
                      ENDIF
                      NORMAL
                    NEXT Ctr
                  ENDIF
                ENDIF
              ELSE BEGIN    { '+', '-', ' ' }
                IF Space_Flag! THEN BEGIN  { Make selection }
                  CASE_OF Ascii
                    DO "+"         { Select all entries }
                      VTAB (2)
                      FOR Ctr1 = 1 TO Last_Entry
                        Files$ (Ctr1) = "^" + MID$ (Files$ (Ctr1),2)
                        IF (Ctr1 >= First) AND (Ctr1 <= Last) THEN BEGIN
                          MS_TEXT
                          PRINT CHR$ (68) { MouseText check }
                          MS_TEXT
                        ENDIF
                      NEXT Ctr1
                    ENDDO

                    DO "-"         { Deselect all entries }
                      VTAB (2)
                      FOR Ctr1 = 1 TO Last_Entry
                        Files$ (Ctr1) = Locked$ (Ctr1) + MID$ (Files$ (Ctr1),2)
                        IF (Ctr1 >= First) AND (Ctr1 <= Last) THEN PRINT Locked$ (Ctr1)
                      NEXT Ctr1
                    ENDDO

                    DO " "         { Make one selection }
                      IF LEFT$ (Files$ (Choice),1) = "^" THEN BEGIN
                        Files$ (Choice) = Locked$ (Choice) + MID$ (Files$ (Choice),2)
                      ELSE BEGIN
                        Files$ (Choice) = "^" + MID$ (Files$ (Choice),2)
                      ENDIF
                    ENDDO
                  ENDCASE
                ENDIF
              ENDIF
              INVERSE
              VTAB (Choice - First + 2)
              IF LEFT$ (Files$ (Choice),1) = "^" THEN BEGIN
                MS_TEXT
                PRINT CHR$ (68);  { MouseText check }
                MS_TEXT
                PRINT MID$ (Files$ (Choice), 2)
              ELSE PRINT Files$ (Choice)
              NORMAL
            ELSE Esc_Flag! = TRUE
          UNTIL Ascii = 13 OR Esc_Flag!
          IF Ascii = 13 THEN BEGIN
            IF INDEX (" DIR ",Files$ (Choice)) > 10 THEN BEGIN
              Test_Flag! = FALSE    { Has user made a selection? }
              FOR Ctr = 1 TO Last_Entry UNTIL Test_Flag!
                IF LEFT$ (Files$ (Ctr),1) = "^" THEN \
                Test_Flag! = TRUE
              NEXT Ctr
              IF NOT Test_Flag! THEN BEGIN { No, then does he wish another display? }
                Num = INDEX ("  ",Files$ (Choice))
                Volume = MID$ (Files$ (Choice), 2, Num - 2)
                PREFIX Volume
              ELSE Flag! = TRUE
            ELSE Flag! = TRUE
          ELSE Flag! = TRUE
        ELSE BEGIN
          Flag! = TRUE
          IF NOT Copy_Flag! THEN BEGIN
            VTAB (10)
            PRINT TAB (10);"No files found in ";PREFIX$
            PRINT
            GOSUB Hit_Key [ Column ]
          ENDIF
        ENDIF
      ENDIF        { No DIR files found & choice needed }
    UNTIL Flag! OR Esc_Flag!
    POKE 248, 1    { Restore normal line as top line }
  ENDPROC          { Do_Catalog }

{ Convert the decimal value into a Hexadecimal string }

  PROC Dec_To_Hex [Value% , ADDRESS String]
    Temp% = Value% / 16
    IF Temp% > 9 THEN Temp% = Temp% + 7
    String = CHR$ (Temp% + 48)
    Value% = Value% - (Value% / 16 * 16)
    IF Value% > 9 THEN Value% = Value% + 7
    String = String + CHR$ (Value% + 48)
  ENDPROC          { Dec_To_Hex }
  CHAIN "FILER.2"

FILER2.TXT:

{ Display the top line of the GS/OS management utilities.
  This consists of the time, a title, and the current date. }

  PROC Do_Top_Line
    VTAB (1)
    HTAB (1)
    PRINT "Time ";TIME$;CHR$ (29);
    HTAB (23)
    INVERSE
    PRINT "Micol Media Management Utilities";
    NORMAL
    HTAB (65)
    PRINT "Date ";DATE$
  ENDPROC

{ Print a message, then delay
 until any key is pressed }

  PROC Hit_Key [ Column ]
    PRINT TAB (Column);
    INVERSE
    PRINT "Hit any key to continue";
    REPEAT
      INKEY A$
    UNTIL A$ <> ""
    NORMAL
    PRINT
  ENDPROC

{ List all commands available to the user }

  PROC Help_Screen [ Column ]
    GOSUB Do_Top_Line
    PRINT
    VTAB (7)
    FOR Ctr = 1 TO 15
      IF Ctr = 1 THEN \
        PRINT "Filing commands:";
      IF Ctr = 9 THEN \
        PRINT "Volume commands:";
      HTAB (Column)
      PRINT Help$ (Ctr)
    NEXT Ctr
  ENDPROC

{ Read the file requested by the user.
  Display can be either HEX/Text or pure text
  according to what the user wishes }

  PROC Read_File [ Column ]
    HOME
    PRINT TAB (Column);"Read file:"
    Space_Flag! = TRUE
    GOSUB Get_FileName ["Read-select file: <Space bar>, <CR>, <Esc>", Column, Choice, Space_Flag!]
    IF NOT Esc_Flag! THEN BEGIN
      HOME
      End_File = INDEX ("  ",Files$ (Choice))
      File_Name$ = MID$ (Files$ (Choice), 2, End_File-2)
      Size& = VAL (MID$ (Files$ (Choice), 74))
      PRINT TAB (Column);"Read file: ";File_Name$
      VTAB (4)
      PRINT TAB (10);"Note! Toggle any key to pause display."
      REPEAT
        VTAB (6)
        PRINT TAB (10);"Display file as text(Y<CR>/N) ? ";
        GET Response$
        Response$ = UPPER$ (Response$)
        PRINT Response$
      UNTIL (INDEX (Response$,Yes_No_Esc$) > 0) OR (ASC (Response$) = 13)
      IF ASC (Response$) = Esc THEN Esc_Flag! = TRUE
      IF ASC (Response$) = 13 THEN Response$ = "Y"
      IF NOT Esc_Flag! THEN BEGIN
        REPEAT
          VTAB (7)
          PRINT TAB (10);"What percent to start from beginning (0-99) ?";CHR$ (29);
          Start$ = ""
          REPEAT
            GET A$
            IF INDEX (A$,"0123456789") > 0 THEN BEGIN
              Start$ = Start$ + A$
              PRINT A$;
            ENDIF
          UNTIL (ASC (A$) = Esc) OR (ASC (A$) = 13) OR (LEN (Start$) = 2)
          IF ASC (A$) = Esc THEN BEGIN
            Esc_Flag! = TRUE
          ELSE BEGIN
            Start& = VAL (Start$) / 100
          ENDIF
        UNTIL Start& < 1 OR Esc_Flag!
        IF NOT Esc_Flag! THEN BEGIN
          HOME
          POKE 248,2     { Protect top line for heading }
          Start& = Size& * Start&
          IF Start& < 1 THEN Buffer_8! = TRUE ELSE Buffer_8! = FALSE
          IF Buffer_8! THEN BEGIN
            ROPEN (8) File_Name$
          ELSE BEGIN     { Offset not zero, use slow buffer }
            ROPEN (1) File_Name$
            Increment& = 1
            Temp& = Start&
            IF Temp& > 65535 THEN BEGIN { Max of 65536 byte blocks in SEEK }
              Temp& = Start& / 16
              Increment& = 16
            ENDIF
            SEEK (1) Temp&, Increment&
          ENDIF
          Byte& = INT (Start&)
          VTAB (1)
          PRINT TAB (Column);"Read file: ";File_Name$
          IF Response$ = "N" THEN BEGIN { HEX/Text display }
            REPEAT
              Num = 0
              REPEAT
                Eof_Flag! = FALSE
                IF Buffer_8! THEN BEGIN
                  GET (8) Char$
                  IF EOF (8) THEN Eof_Flag! = TRUE
                ELSE BEGIN
                  GET (1) Char$
                  IF EOF (1) THEN Eof_Flag! = TRUE
                ENDIF
                Byte& = Byte& + 1
                IF NOT Eof_Flag! THEN BEGIN  { Get 15 characters from disk }
                  IF Num < 15 THEN BEGIN
                    Num = Num + 1
                    Number = ASC (Char$)
                    Number = PEEK (48881)
                    Values% (Num) = Number
                  ENDIF
                ENDIF
              UNTIL Eof_Flag! OR Num = 15
              FOR Ctr = 1 TO Num
                GOSUB Dec_To_Hex [Values% (Ctr), Char$]
                PRINT TAB (Ctr * 3 - 2); Char$;
              NEXT Ctr
              HTAB (50)
              FOR Ctr = 1 TO Num
                Ascii% = Values% (Ctr)
                IF Ascii% > 127 THEN Ascii% = Ascii% - 128
                IF Ascii% < 32 THEN BEGIN
                  INVERSE
                  PRINT CHR$ (Ascii% + 64);
                  NORMAL
                  PRINT " ";
                ELSE BEGIN
                  IF Ascii% < 32 THEN BEGIN
                    INVERSE
                    PRINT ".";
                    NORMAL
                    PRINT " ";
                  ELSE PRINT CHR$ (Ascii%);" ";
                ENDIF
              NEXT Ctr
              PRINT
              Temp% = PEEK (236) { Save current horizontal position }
              POKE 248,1
              INVERSE
              VTAB (1)
              PRINT USING "###,###";TAB (1);"Byte ";Byte&;
              NORMAL
              PRINT " ";
              INVERSE
              PRINT USING "###.##";100.0 * (Byte& / Size&); "%"
              NORMAL
              POKE 248,2
              VTAB (Temp%)    { Restore horz position }
              INKEY A$
              IF ASC (A$) = Esc THEN BEGIN
                Esc_Flag! = TRUE
              ELSE IF LEN (A$) > 0 THEN BEGIN
                REPEAT
                  INKEY A$    { User has requested a pause }
                UNTIL LEN (A$) > 0
              ENDIF
            UNTIL Eof_Flag! OR Esc_Flag!
            IF Buffer_8! THEN CLOSE (8) ELSE CLOSE (1)
          ELSE BEGIN    { Text display }
            REPEAT
              Eof_Flag! = FALSE
              IF Buffer_8! THEN BEGIN
                INPUT (8) String$
                IF EOF (8) THEN Eof_Flag! = TRUE
              ELSE BEGIN
                INPUT (1) String$
                IF EOF (1) THEN Eof_Flag! = TRUE
              ENDIF
              Byte& = Byte& + LEN (String$) { Add <CR> } + 1
              PRINT String$
              Temp% = PEEK (236) { Save current horizontal position }
              POKE 248,1
              VTAB (1)
              INVERSE
              PRINT USING "###,###";TAB (1);"Byte ";Byte&;
              NORMAL
              PRINT " ";
              INVERSE
              Increments& = 100 * (Byte& / Size&)
              IF INDEX ("E", STR$ (Increments&)) > 0 THEN Increments& = 0
              PRINT USING "###.##";Increments&; "%"
              NORMAL
              POKE 248,2
              VTAB (Temp%)    { Restore horz position }
              INKEY A$
              IF ASC (A$) = Esc THEN BEGIN
                Esc_Flag! = TRUE
              ELSE IF LEN (A$) > 0 THEN BEGIN
                REPEAT
                  INKEY A$    { User has requested a pause }
                UNTIL LEN (A$) > 0
              ENDIF
            UNTIL Eof_Flag! OR Esc_Flag!
            IF Buffer_8! THEN CLOSE (8) ELSE CLOSE (1)
          ENDIF   { Hex/Text or Text display }
          IF NOT Esc_Flag! THEN BEGIN
            PRINT
            GOSUB Hit_Key [Column]
          ENDIF    { Esc key not pressed }
        ENDIF      { Esc key not pressed }
      ENDIF        { Esc key not pressed }
    ENDIF          { Esc key not pressed }
    POKE 248,1     { Restore normal screen }
  ENDPROC          { End of Read_File }

{ Display the file information to the screen }

  PROC Show_File_Info [Column]
    Space_Flag! = TRUE
    GOSUB Get_FileName ["Show File Info:Select file(s): <Space>, <CR>, <Esc>", Column, Choice, Space_Flag! ]
    IF NOT Esc_Flag! THEN BEGIN
      Num_Of_Files% = 0
      FOR Ctr = 1 TO Last_Entry UNTIL Flag!
        IF LEFT$ (Files$ (Ctr),1) = "^" THEN BEGIN
          Num_Of_Files% = Num_oF_Files% + 1
          End_File% = INDEX ("  ",Files$ (Ctr))
          Temp_Files (Num_Of_Files%) = MID$ (Files$ (Ctr), 2, End_File% - 2)
          Sizes& (Num_Of_Files%) = VAL (MID$ (Files$ (Ctr), 74))
        ENDIF
      NEXT Ctr
      IF Num_Of_Files% > 0 THEN BEGIN
        HOME
        PRINT TAB (Column);"Show File Information:"
        PRINT "File name";TAB (20);"Size(in Bytes)";TAB (40);"File Type";TAB (55);"Aux. Data type"
        PRINT
        POKE 248,4   { Don't scrool top lines }
        FOR Ctr = 1 TO Num_Of_Files%
          FileName$ = Temp_Files (Ctr)
          Size& = Sizes& (Ctr)
          Dummy! = FILE (FileName$)  { Get file information }
          Type% = PEEK (48881)
          Aux_LSB = PEEK (224)
          Aux_MSB = PEEK (225)
          PRINT USING "#,###,###";FileName$;TAB (20);Size&;
          GOSUB Dec_To_Hex [Type%, Type$]
          PRINT TAB (43);"$";Type$;
          GOSUB Dec_To_Hex [Aux_LSB, Aux_LSB$]
          GOSUB Dec_To_Hex [Aux_MSB, Aux_MSB$]
          PRINT TAB (59);"$";Aux_MSB$;Aux_LSB$
        NEXT Ctr
        PRINT
        PRINT TAB (Column);"Volume block usage:"
        PRINT
        Position = INDEX (": ", Volume_Info) + 1
        Sum1% = VAL (MID$ (Volume_Info,Position, Position + 6))
        Position = INDEX (": ", Volume_Info, 2) + 1
        Sum2% = VAL (MID$ (Volume_Info, Position))
        Sum1& = Sum1%
        Sum2& = Sum2%
        PRINT USING "###,###";"Blocks free:";TAB (15);Sum2&
        PRINT USING "###,###";"Blocks used:";TAB (15);Sum1&
        PRINT USING "###,###";"Total blocks:";TAB (15);Sum1& + Sum2&
        PRINT
        GOSUB Hit_Key [Column]
        POKE 248,1 { Restore normal screen }
      ENDIF        { Num_of_Files% > 0 }
    ENDIF          { Esc key pressed }
  ENDPROC          { Compare_Files }

{ Have user specify files, including DIR files, verify
 these files by means of dummy reads and ONERR handling }

  PROC Verify_Files [ Column ]
    File_Errors% = 0
    Space_Flag! = TRUE
    GOSUB Get_FileName ["Verify: Select file(s): <Space bar>, <CR>, <Esc>", Column, Choice, Space_Flag! ]
    IF NOT Esc_Flag! THEN BEGIN
      Num_Of_Dirs% = 0
      Current_Dirs% = 0
      Loop_Flag! = FALSE
      HOME
      PRINT TAB (1);"Verify files:";CHR$ (29);TAB (15);"Prefix= ";PREFIX$;CHR$ (29)
      REPEAT
        FOR Ctr = 1 TO Last_Entry UNTIL Esc_Flag!
          IF LEFT$ (Files$ (Ctr),1) = "^" THEN BEGIN
            End_File% = INDEX ("  ",Files$ (Ctr))
            FileName$ = MID$ (Files$ (Ctr), 2, End_File% - 2)
            Response$ = "Y"
            IF INDEX (" DIR ",Files$ (Ctr)) > 0 THEN BEGIN
              Num_Of_Dirs% = Num_Of_Dirs% + 1
              Directories$ (Num_Of_Dirs%) = PREFIX$ + FileName$
            ENDIF
            VTAB (10)
            PRINT TAB (10);"Verifying ";CHR$ (29);FileName$;" ";
            COPY FileName$ TO "" { Use COPY to verify files }
            IF PEEK (48881) > 0 THEN BEGIN
              File_Errors% = File_Errors% + 1
              INVERSE
              PRINT " BAD"
              NORMAL
              DELAY = 80
            ELSE BEGIN
              PRINT " OKay"
              DELAY = 20
            ENDIF
          ENDIF
          INKEY A$
          IF ASC (A$) = Esc THEN Esc_Flag! = TRUE
        NEXT Ctr
        IF NOT Esc_Flag! THEN BEGIN
          IF Current_Dirs% < Num_Of_Dirs% THEN BEGIN
            Current_Dirs% = Current_Dirs% + 1
            FileName$ = Directories$ (Current_Dirs%)
            PREFIX FileName$
            VTAB (1)
            PRINT TAB (1);"Verify files:";CHR$ (29);TAB (15);"Prefix= ";FileName$;CHR$ (29)
            GOSUB Simple_Get_Cat
            FOR Ctr = 1 TO Last_Entry  { Mark all files as varifyable }
              Files$ (Ctr) = "^" + MID$ (Files$ (Ctr), 2)
            NEXT Ctr
          ELSE Loop_Flag! = TRUE  { Stop loop }
        ENDIF
      UNTIL Loop_Flag! OR Esc_Flag!
      IF NOT Esc_Flag! THEN BEGIN
        VTAB (12)
        IF File_Errors% > 0 THEN BEGIN
          PRINT TAB (10);File_Errors%;" were detected as bad"
        ELSE BEGIN
          PRINT TAB (10);"All files in this check OKAY"
        ENDIF
        PRINT
        GOSUB Hit_Key [Column]
      ENDIF        { Esc key pressed }
    ENDIF          { Esc key pressed }
  ENDPROC          { End of Verify_Files }

{ Delete the files requested by the user, if
 the file name is a DIR file, delete the entire
 directory unless user refuses request }

  PROC Delete_Files [ Column ]
    Space_Flag! = TRUE
    GOSUB Get_FileName ["Delete-Select file(s): <Space bar>, <CR>, <Esc>", Column, Choice, Space_Flag! ]
    IF NOT Esc_Flag! THEN BEGIN
      Num_Of_Dirs% = 0
      Current_Dirs% = 0
      Loop_Flag! = FALSE
      Yes_No_Dir$ = "N"
      Flag! = FALSE
      HOME
      PRINT TAB (Column);"Delete files:"
      FOR Ctr = 1 TO Last_Entry UNTIL Flag! { DIR file to delete ? }
        IF LEFT$ (Files$ (Ctr), 1) = "^" THEN BEGIN
          IF INDEX (" DIR ",Files$ (Ctr)) > 0 THEN BEGIN
            REPEAT
              VTAB (6)
              PRINT TAB (10);"Delete all directories(Y/N) ? ";CHR$ (29);
              GET Yes_No_Dir$
              Yes_No_Dir$ = UPPER$ (Yes_No_Dir$)
              PRINT Yes_No_Dir$
            UNTIL INDEX (Yes_No_Dir$, Yes_No_Esc$) > 0
            Flag! = TRUE  { Stop "FOR" loop }
          ENDIF
        ENDIF
      NEXT Ctr
      IF ASC (Yes_No_Dir$) = Esc THEN Esc_Flag! = TRUE
      IF NOT Esc_Flag! THEN BEGIN
        REPEAT
          FOR Ctr = 1 TO Last_Entry UNTIL Esc_Flag!
            IF LEFT$ (Files$ (Ctr),1) = "^" THEN BEGIN
              End_File% = INDEX ("  ",Files$ (Ctr))
              FileName$ = MID$ (Files$ (Ctr), 2, End_File% - 2)
              Response$ = "Y"
              IF INDEX (" DIR ",Files$ (Ctr)) > 0 THEN BEGIN
                IF Yes_No_Dir$ = "N" THEN BEGIN
                  REPEAT
                    VTAB (11)
                    PRINT TAB (10);FileName$;" is a DIR file, delete it (Y/N) ? ";CHR$ (29);
                    GET Response$
                    Response$ = UPPER$ (Response$)
                    PRINT Response$
                  UNTIL INDEX (Response$, Yes_No_Esc$) > 0
                  VTAB (11)
                  PRINT TAB (10);CHR$ (29)
                  IF ASC (Response$) = Esc THEN Esc_Flag! = TRUE
                  IF Response$ = "Y" THEN BEGIN
                    Num_Of_Dirs% = Num_Of_Dirs% + 1
                    Directories$ (Num_Of_Dirs%) = PREFIX$ + FileName$
                  ENDIF
                ELSE BEGIN  { Delete all DIR files }
                  Num_Of_Dirs% = Num_Of_Dirs% + 1
                  Directories$ (Num_Of_Dirs%) = PREFIX$ + FileName$
                ENDIF
                Response$ = "N"  { Stop delete of DIR file in this loop }
              ENDIF    { DIR or not DIR file }
              IF NOT Esc_Flag! THEN BEGIN
                IF Response$ ="Y" THEN BEGIN
                  VTAB (1)
                  PRINT TAB (1);"Delete files:";CHR$ (29);
                  INVERSE
                  PRINT TAB (15);"Prefix= ";PREFIX$;
                  NORMAL
                  VTAB (10)
                  PRINT TAB (10);"Deleting ";FileName$;CHR$ (29)
                  UNLOCK FileName$
                  DELETE FileName$
                ENDIF { Response is "Y" }
              ENDIF  { Not Esc pressed }
            ENDIF   { End "^" marker found }
            INKEY A$
            IF ASC (A$) = Esc THEN Esc_Flag! = TRUE
          NEXT Ctr
          IF NOT Esc_Flag! THEN BEGIN
            IF Current_Dirs% < Num_Of_Dirs% THEN BEGIN
              Current_Dirs% = Current_Dirs% + 1
              FileName$ = Directories$ (Current_Dirs%)
              PREFIX FileName$
              GOSUB Simple_Get_Cat
              FOR Ctr = 1 TO Last_Entry  { Mark all files as deletable }
                Files$ (Ctr) = "^" + MID$ (Files$ (Ctr), 2)
              NEXT Ctr
            ELSE Loop_Flag! = TRUE  { Stop loop }
          ENDIF          { Esc pressed }
        UNTIL Loop_Flag! OR Esc_Flag!
        IF NOT Esc_Flag! THEN BEGIN { Delete the DIR files here }
          FOR Ctr = Num_Of_Dirs% TO 1 STEP -1
            FileName$ = Directories$ (Ctr)
            VTAB (11)
            PRINT TAB (10); "Deleting directory ";FileName$;CHR$ (29)
            UNLOCK FileName$
            DELETE FileName$
          NEXT Ctr
        ENDIF      { End of Esc pressed }
      ENDIF        { End of Esc pressed }
    ENDIF          { End of Esc pressed }
  ENDPROC          { End of Delete_Files }

{ Rename the selected files }

  PROC Rename_Files [Column]
    Space_Flag! = TRUE
    GOSUB Get_FileName ["Rename-Select file(s): <Space bar>, <CR>, <Esc>", Column, Choice, Space_Flag! ]
    IF NOT Esc_Flag! THEN BEGIN
      HOME
      PRINT TAB (Column);"Rename file(s):"
      VTAB (6)
      FOR Ctr = 1 TO Last_Entry UNTIL Esc_Flag!
        IF LEFT$ (Files$ (Ctr),1) = "^" THEN BEGIN
          End_File = INDEX ("  ",Files$ (Ctr))
          FileName$ = MID$ (Files$ (Ctr), 2, End_File - 2)
          REPEAT
            PRINT TAB (10);"Rename ";FileName$;" as ";
            INPUT " ";New_Name$
            IF LEN (New_Name$) > 0 THEN BEGIN
              IF FILE (New_Name$) THEN BEGIN
                PRINT TAB (10);New_Name$;" already exists, try again"
                PRINT
                Flag! = FALSE
              ELSE BEGIN
                RENAME FileName$ TO New_Name$
                Flag! = TRUE
              ENDIF
            ELSE Esc_Flag! = TRUE
          UNTIL Flag! OR Esc_Flag!
        ENDIF      { Esc pressed }
      NEXT Ctr
    ENDIF          { Esc pressed }
  ENDPROC          { Rename_Files }
  CHAIN "FILER.3"

FILER3.TXT:

{ Copy selected files to a requested directory,
  If original file doesn't exist, give error message,
  If second file already exists, give error message
  else do the copy. }

  PROC Copy_Files [ Column ]
    Space_Flag! = TRUE
    GOSUB Get_FileName ["Copy-Select file(s): <Space bar>, <CR>, <Esc> ", Column, Choice, Space_Flag! ]
    IF NOT Esc_Flag! THEN BEGIN
      From_Prefix$ = PREFIX$ { From files default prefix }
      Num_Of_Files = 0
      Num_Of_Dirs% = 0
      Current_Dirs% = 0
      FOR Ctr = 1 TO Last_Entry  {Transfer copy file names to buffer }
        IF LEFT$ (Files$ (Ctr),1) = "^" THEN BEGIN
          Num_Of_Files = Num_Of_Files + 1
          End_File = INDEX ("  ",Files$ (Ctr))
          Copy_Files$ (Num_oF_Files) = MID$ (Files$ (Ctr), 2, End_File - 2)
          IF INDEX (" DIR ",Files$ (Ctr)) > 0 THEN \
            Values% (Num_Of_Files) = 1 \
          ELSE \
            Values% (Num_Of_Files) = 0
        ENDIF
      NEXT Ctr
      Select_Flag! = FALSE    { If no DIR file, auto select }
      GOSUB Get_FileName ["Copy-select target directory: <CR>, <Esc>", Column, Choice, Space_Flag! ]
      Select_Flag! = TRUE
      IF NOT Esc_Flag! THEN BEGIN
        To_Prefix$ = PREFIX$   { To files default prefix }
        PREFIX From_Prefix$    { From files are default prefix }
        Loop_Flag! = FALSE
        HOME
        PRINT TAB (1);"Copying from:";TAB (15);From_Prefix$;CHR$ (29)
        PRINT "Copying to: ";TAB (15);To_Prefix$;CHR$ (29)
        REPEAT    { Loop necessary if directories found, avoids GOTOs }
          FOR Ctr = 1 TO Num_Of_Files UNTIL Esc_Flag!
            Response$ = "Y"   { Set default response }
            FileName$ = To_Prefix$ + Copy_Files$ (Ctr)
            IF FILE (FileName$) THEN BEGIN  { Does file already exist? }
              IF PEEK (48881) <> 15 THEN BEGIN { Not a DIR file }
                File_Flag! = TRUE
                REPEAT   { Until a filename is acceptable }
                  REPEAT   { Until Y, N or Esc }
                    VTAB (10)
                    PRINT TAB (1);FileName$;" exists ";
                    PRINT ",copy anyway(Y/N) ? ";CHR$ (29);
                    GET Response$
                    Response$ = UPPER$ (Response$)
                    PRINT Response$
                  UNTIL INDEX (Response$,Yes_No_Esc$) > 0
                  IF Response$ = "Y" THEN BEGIN
                    REPEAT
                      VTAB (10)
                      PRINT TAB (1);"Copy ";FileName$;" with another filename(Y/N) ? ";CHR$ (29);
                      GET Answer$
                      Answer$ = UPPER$ (Answer$)
                      PRINT Answer$
                    UNTIL INDEX (Answer$,Yes_No_Esc$) > 0
                    IF Answer$ = "Y" THEN BEGIN
                      VTAB (10)
                      PRINT TAB (1);"Input new file name";CHR$ (29);
                      INPUT " ";FileName$
                      IF ASC (FileName$) <> { "/" } 47 THEN \
                        FileName$ = To_Prefix$ + FileName$
                      File_Flag! = FILE (FileName$)
                    ELSE File_Flag! = FALSE
                  ELSE File_Flag! = FALSE
                UNTIL NOT File_Flag!
              ELSE BEGIN  { Is a DIR file }
                VTAB (10)
                PRINT TAB (1);FileName$;" exists and is a DIR file, cannot copy";CHR$ (29);
                Response$ = "N"
              ENDIF
            ELSE BEGIN  { File doesn't exist }
              IF Values% (Ctr) > 0 THEN BEGIN { Copy the DIR file later }
                Num_Of_Dirs% = Num_Of_Dirs% + 1
                Directories$ (Num_Of_Dirs%) = Copy_Files$ (Ctr)
                From_Prefixes$ (Num_Of_Dirs%) = PREFIX$
                To_Prefixes$ (Num_Of_Dirs%) = FileName$
                CREATE FileName$
                Response$ = "N"  { Stop file copy }
              ENDIF
            ENDIF
            IF Response$ = "Y" THEN BEGIN
              IF FILE (FileName$) THEN UNLOCK FileName$
              Temp = Copy_Files$ (Ctr)  { Get original file }
              VTAB (10)
              PRINT TAB (1);"Copying ";Temp;CHR$ (29)
              COPY Temp TO FileName$
            ENDIF
            INKEY A$
            IF ASC (A$) = Esc THEN Esc_Flag! = TRUE
          NEXT Ctr
          IF NOT Esc_Flag! THEN BEGIN
            IF Current_Dirs% < Num_Of_Dirs% THEN BEGIN
              Current_Dirs% = Current_Dirs% + 1
              Volume$ = Directories$ (Current_Dirs%)
              From_Prefix$ = From_Prefixes$ (Current_Dirs%) + Volume$
              PREFIX From_Prefix$
              To_Prefix$ = To_Prefixes$ (Current_Dirs%) + "/"
              GOSUB Simple_Get_Cat
              HOME
              PRINT TAB (1);"Copying from:";TAB (15);From_Prefix$;CHR$ (29)
              PRINT "Copying to: ";TAB (15);To_Prefix$;CHR$ (29)
              Num_Of_Files = 0
              FOR Ctr = 1 TO Last_Entry  { Transfer copy file names to buffer }
                End_File = INDEX ("  ",Files$ (Ctr))
                IF   INDEX (" $C7 ", { Resource } Files$ (Ctr)) = 0 AND  \
                     INDEX (" $B8 ", { NDA }      FILES$ (Ctr)) = 0 AND  \
                     INDEX (" UTP ",              FILES$ (Ctr)) = 0 AND  \
                     INDEX (" P08 ",FILES$ (Ctr)) = 0 THEN BEGIN
                  Num_Of_Files = Num_Of_Files + 1
                  Copy_Files$ (Num_Of_Files) = MID$ (Files$ (Ctr), 2, End_File - 2)
                  IF INDEX (" DIR ",Files$ (Ctr)) > 0 THEN \
                    Values% (Num_Of_Files) = 1 \
                  ELSE \
                    Values% (Num_Of_Files) = 0
                ELSE BEGIN
                  INVERSE
                  VTAB (12)
                  PRINT TAB (1);MID$ (Files$ (Ctr), 2, End_File - 2);" is an illegal ProDOS 8 file, canot copy";CHR$ (29)
                  NORMAL
                  DELAY = 150
                ENDIF
              NEXT Ctr
            ELSE Loop_Flag! = TRUE { Stop loop }
          ENDIF
        UNTIL Loop_Flag! OR Esc_Flag!
        DELAY = 200
      ENDIF        { Esc not pressed }
    ENDIF          { Esc not pressed }
  ENDPROC          { Copy_Files }

{ Request prefix name, if empty, display prefix
 else set prefix to that requested }

  PROC Set_Prefix [Column]
    Space_Flag! = TRUE
    Old_Prefix$ = PREFIX$
    Select_Flag! = FALSE
    GOSUB Get_FileName ["Set prefix-Select directory: <CR>, <Esc>", Column, Choice, Space_Flag!]
    Select_Flag! = TRUE
    HOME
    VTAB (10)
    PRINT TAB (10);"Previous prefix was ";Old_Prefix$
    PRINT TAB (10);"Default prefix now set as ";PREFIX$
    PRINT
    GOSUB Hit_Key [Column]
  ENDPROC          { Set_Prefix }

{ Lock or unlock the specified file according to the flag sent }

  PROC Lock_Unlock [Column, Lock_Flag!]
    Space_Flag! = TRUE
    IF Lock_Flag! THEN BEGIN
      GOSUB Get_FileName ["Lock-Select file(s): <Space Bar>, <CR>, <Esc>", Column, Choice, Space_Flag! ]
    ELSE BEGIN
      GOSUB Get_FileName ["Unlock-Select file(s): <Space Bar>, <CR>, <Esc>", Column, Choice, Space_Flag! ]
    ENDIF
    IF NOT Esc_Flag! THEN BEGIN
      FOR Ctr = 1 TO Last_Entry
        IF LEFT$ (Files$ (Ctr),1) = "^" THEN BEGIN
          Num = INDEX ("  ",Files$ (Ctr))
          File_Name$ = MID$ (Files$ (Ctr), 2, Num - 2)
          IF Lock_Flag! THEN LOCK File_Name$ ELSE UNLOCK File_Name$
        ENDIF
      NEXT Ctr
    ENDIF
  ENDPROC          { Lock_Unlock }

{ Probaly most useful command.  Search one volume, or all volumes to
  determine if the entry exists.  Allow dates, times to be searched. }
  PROC File_Find [Column]
    HOME
    PRINT TAB (Column);"File Find:"
    Found = 0
    VTAB (10)
    PRINT TAB (10);"Search on which string";
    INPUT " ";Search_String
    IF LEN (Search_String) > 0 THEN BEGIN
      Search_String = UPPER$ (Search_String)
      REPEAT
        PRINT TAB (10);"Search entire system(Y/N) ? ";
        GET Response$:PRINT Response$
        Response$ = UPPER$ (Response$)
      UNTIL INDEX (Response$,Yes_No_Esc$) > 0
      IF ASC (Response$) = Esc THEN Esc_Flag! = TRUE
      IF NOT Esc_Flag! THEN BEGIN
        IF Response$ = "N" THEN BEGIN
          Space_Flag! = FALSE
          GOSUB Get_VolumeName [Column, Choice, Space_Flag!]
          Volumes% = 1
          Volumes (1) = Files$ (Choice)
        ELSE BEGIN
          GOSUB Get_Volumes
          FOR Ctr = 1 TO Volumes%
            Volumes (Ctr) = Files$ (Ctr)
          NEXT Ctr
        ENDIF
        IF NOT Esc_Flag! THEN BEGIN
          HOME
          GOSUB Do_Top_Line
          FOR Volume_Ctr% = 1 TO Volumes% UNTIL Esc_Flag!
            Temp = "/" + Volumes (Volume_Ctr%)
            PREFIX Temp
            Num_Of_Dirs = 0
            Current_Dirs = 0
            Loop_Flag! = FALSE
            REPEAT
              VTAB (1)
              PRINT TAB (6);TIME$
              VTAB (10)
              PRINT TAB (1); "Searching directory ";PREFIX$;CHR$ (29);
              GOSUB Simple_Get_Cat
              Search_Flag! = FALSE
              FOR Cat_Dirs = 1 TO Last_Entry
                Temp = Files$ (Cat_Dirs)
                Temp = UPPER$ (Temp)
                IF INDEX (Search_String, Temp) > 0 THEN BEGIN
                  IF NOT Search_Flag! THEN BEGIN
                    Found = Found + 1
                    Found_Dirs$ (Found) = PREFIX$
                    Search_Flag! = TRUE
                    INVERSE
                    PRINT "FOUND"
                    NORMAL
                    DELAY = 50
                  ENDIF
                ENDIF
                IF INDEX (" DIR ",Files$ (Cat_Dirs)) > 0 THEN BEGIN
                  Num_Of_Dirs = Num_Of_Dirs + 1
                  End_File = INDEX ("  ",Files$ (Cat_Dirs))
                  Volume = MID$ (Files$ (Cat_Dirs), 2, End_File - 2)
                  Volume = PREFIX$ + Volume
                  Directories$ (Num_Of_Dirs) = Volume
                ENDIF
              NEXT Cat_Dirs
              INKEY String
              IF ASC (String) = Esc THEN Esc_Flag! = TRUE
              IF Current_Dirs < Num_Of_Dirs THEN BEGIN
                Current_Dirs = Current_Dirs + 1
                Volume = Directories$ (Current_Dirs)
                PREFIX Volume
              ELSE Loop_Flag! = TRUE
            UNTIL Loop_Flag! OR Esc_Flag!
          NEXT Volume_Ctr%
          PRINT:PRINT
          IF Found > 0 { If some entries were located } THEN BEGIN
            REPEAT
              HOME
              PRINT TAB (10);Search_String;" found in the following directories:"
              PRINT
              FOR Ctr = 1 TO Found  { Display entries found }
                PRINT Ctr;".";TAB (10);Found_Dirs$ (Ctr)
                IF Ctr MOD 20 = 0 THEN \
                  PRINT:GOSUB Hit_Key [Column]
              NEXT Ctr
              PRINT
              REPEAT  { Allow user to specify entry to view }
                PRINT TAB (10);"Which directory, (enter ";LEN (STR$ (Found));" digit(s), <CR> to terminate)? ";
                Cat_Num$ = ""
                FOR Ctr = 1 TO LEN (STR$ (Found))
                  GET A$
                  IF INDEX (A$,"0123456789") > 0 THEN BEGIN
                    Cat_Num$ = Cat_Num$ + A$
                    PRINT A$;
                  ENDIF
                NEXT Ctr
                PRINT
                Temp% = VAL (Cat_Num$)
              UNTIL Temp% <= Found
              IF LEN (Cat_Num$) > 0 THEN BEGIN
                File_Name$ = Found_Dirs$ (Temp%)
                PREFIX File_Name$
                Space_Flag! = FALSE
                Choice = 0
                HOME
                VTAB (1)
                PRINT TAB (1); CHR$ (29); TAB (40 - (LEN (Top_Line$) / 2)); Top_Line$
                POKE 248, 2  { Set second line as top line }
                GOSUB Do_Catalog [Column, Choice, Space_Flag!]
                Esc_Flag! = FALSE
              ENDIF
            UNTIL Temp% > Found OR LEN (Cat_Num$) = 0
          ELSE BEGIN   { Found > 0 }
            PRINT TAB (10);"No entries found"
            PRINT
            GOSUB Hit_Key [Column]
          ENDIF    { Found = 0 }
        ENDIF      { Esc key pressed }
      ENDIF        { Esc key pressed }
    ENDIF          { Empty input }
  ENDPROC          { File_Find }

{ Order the catalog buffer according to the users wishes,
  order may be by: sequential, file name, file type, date, size }

  PROC Set_Cat_Order [ Column ]
    HOME
    GOSUB Do_Top_Line
    VTAB (9)
    PRINT TAB (Column);"Set the order of the catalog display"
    REPEAT
      FOR Ctr = 1 TO 5
        IF Ctr = Cat_Order THEN INVERSE
        VTAB (Ctr + 10)
        HTAB (Column)
        PRINT Order$ (Ctr)
        NORMAL
      NEXT Ctr
      VTAB (1)
      REPEAT
        INKEY key$
        Time_Ctr% = Time_Ctr% + 1
        IF Time_Ctr% > 100 THEN BEGIN
          HTAB (6)
          PRINT TIME$;
          Time_Ctr% = 0
        ENDIF
      UNTIL Key$ <> ""
      Ascii = ASC (Key$)
      IF Ascii = 10 THEN BEGIN  { Down arrow }
        IF Cat_Order = 5 THEN BEGIN
          Cat_Order = 1
        ELSE BEGIN
          Cat_Order = Cat_Order + 1
        ENDIF
      ELSE IF Ascii = 11 THEN BEGIN { Up arrow }
        IF Cat_Order = 1 THEN BEGIN
          Cat_Order = 5
        ELSE BEGIN
          Cat_Order = Cat_Order - 1
        ENDIF
      ENDIF
    UNTIL Ascii = 13 OR Ascii = Esc
  ENDPROC          { Set_Cat_Order }

{ End of Procedures for the disk utilities }

  PROC Do_Top_Row
    VTAB (1)
    HTAB (1)
    PRINT "Time ";TIME$;CHR$ (29);
    HTAB (29)
    INVERSE
    PRINT "The Micol Advanced Utilities";
    NORMAL
    HTAB (65)
    PRINT "Date ";DATE$
  ENDPROC          { Do_Top_Row }

{ Start of main loop of GS/OS utilities.
 Execution of disk utility begins at this point.
 This is the main body of the disk utilities. }

  ROUTINE Disk_Management
  Quit_Flag! = FALSE
  Disk_Error! = FALSE
  Error_Flag! = FALSE
  Text_File$ = ""
  Bottom_Line = 15
  Time_Ctr% = 0
  Column = 30
  ONERR GOTO Error_Trap

  ROUTINE Error_Trap
  IF Error_Flag! THEN BEGIN  { Don't execute unless error }
    Errors% = Errors% + 1
    IF Errors% > 20 THEN BEGIN { Were errors exsessive? }
      IF PEEK (48856) > 0 THEN BEGIN
        PRINT "A Micol Systems error ";PEEK (48856);" has happened"
      ELSE BEGIN
        PRINT "A ProDOS error ";PEEK (48857);" has happened"
      ENDIF
      DELAY = 1000
      POKE 48860,0   { A system error if here, allow normal errors }
      POKE 48861,0
      Errors% = 0
    ENDIF
    CLOSE (8)
    CLOSE (1)
    POKE 248,1
    HOME
    VTAB (10)
    INVERSE
    PRINT TAB (Column);"GS/OS utilities error"
    NORMAL:PRINT:PRINT
    IF NOT FILE (Old_Prefix$) { Was boot disk removed ? } THEN BEGIN
      Temp% = INDEX ("/", Old_Prefix$, 2)
      PRINT "Volume ";LEFT$ (Old_Prefix$, Temp%);" not currently online"
      CR$ = CHR$ (13)
      Old_Prefix$ = ONLINE$ { Set default prefix to first volume on line }
      Temp% = INDEX (CR$, Old_Prefix$) - 1
      IF Temp% < 1 THEN Temp% = LEN (Old_Prefix$)
      Old_Prefix$ = "/" + LEFT$ (Old_Prefix$, Temp%) + "/"
      PRINT "Setting default prefix to ";Old_Prefix$
    ENDIF
    PREFIX Old_Prefix$
    Disk_Error! = TRUE
    Copy_Flag! = FALSE
    PRINT
    GOSUB Hit_Key [ 10 ]
  ENDIF  { Error flag set }

{ Main loop, all control comes and goes
 through this REPEAT loop. }

  Error_Flag! = TRUE { Allow the error trap to execute now }
  ROUTINE Top_Of_Loop
  REPEAT
    HOME
    GOSUB Help_Screen [Column]
    REPEAT
      Esc_Flag! = FALSE
      INVERSE
      VTAB (Selection% + 6)
      PRINT TAB (Column); Help$ (Selection%); TAB (1);
      NORMAL
      VTAB (1)
      REPEAT
        INKEY key$
        Time_Ctr% = Time_Ctr% + 1
        IF Time_Ctr% > 100 THEN BEGIN
          PRINT TAB (6);TIME$;
          Time_Ctr% = 0
        ENDIF
      UNTIL Key$ <> ""
      VTAB (Selection% + 6)
      PRINT TAB (Column);Help$ (Selection%) { Turn off inverse line }
      Ascii = ASC (Key$)
      IF Ascii = Esc THEN Esc_Flag! = TRUE
      IF Ascii = 11 THEN BEGIN    { Up arrow }
        IF Selection% > 1 THEN BEGIN
          Selection% = Selection% - 1
        ELSE BEGIN
          Selection% = Bottom_Line
        ENDIF
      ELSE IF Ascii = 10 THEN BEGIN  { Down arrow }
        IF Selection% < Bottom_Line THEN BEGIN
          Selection% = Selection% + 1
        ELSE BEGIN
          Selection% = 1
        ENDIF
      ENDIF
    UNTIL Ascii = 13 OR Esc_Flag!

    IF NOT Esc_Flag! THEN BEGIN

      CASE_OF Selection%

        DO 1       { Copy files }
          Old_Prefix$ = PREFIX$
          Copy_Flag! = TRUE
          GOSUB Copy_Files [ Column ]
          PREFIX Old_Prefix$
          Copy_Flag! = FALSE
        ENDDO

        DO 2       { Delete files }
          Old_Prefix$ = PREFIX$
          GOSUB Delete_Files [ Column ]
          PREFIX Old_Prefix$
        ENDDO

        DO 3       { Verify Files }
          Old_Prefix$ = PREFIX$
          GOSUB Verify_Files [Column]
          PREFIX Old_Prefix$
        ENDDO

        DO 4       { Show File Information }
          Old_Prefix$ = PREFIX$
          GOSUB Show_File_Info [ Column ]
          PREFIX Old_Prefix$
        ENDDO

        DO 5       { Rename names }
          Old_Prefix$ = PREFIX$
          GOSUB Rename_Files [ Column ]
          PREFIX Old_Prefix$
        ENDDO

        DO 6       { Lock }
          Old_Prefix$ = PREFIX$
          Flag! = TRUE
          GOSUB Lock_Unlock [Column, Flag!]
          PREFIX Old_Prefix$
        ENDDO

        DO 7      { Unlock file }
          Old_Prefix$ = PREFIX$
          Flag! = FALSE
          GOSUB Lock_Unlock [Column, Flag!]
          PREFIX Old_Prefix$
        ENDDO

        DO 8       { Read files }
          Old_Prefix$ = PREFIX$
          GOSUB Read_File [ Column ]
          PREFIX Old_Prefix$
        ENDDO

        DO 9       { Display online volumes }
          GOSUB Get_Volumes
          HOME
          VTAB (12 - Volumes%)
          PRINT TAB (Column ) "The current online Volumes:":PRINT:PRINT
          FOR Ctr = 1 TO Volumes%
            PRINT TAB (Column);Ctr;".";TAB (Column + 4);Files$ (Ctr)
          NEXT Ctr
          PRINT
          GOSUB Hit_Key [ Column ]
        ENDDO

        DO 10       { Display catalog }
          Old_Prefix$ = PREFIX$
          Flag! = FALSE
          GOSUB Get_FileName ["Catalog disk-Select directory: <CR>, <Esc>", Column, Choice, Flag!]
          PREFIX Old_Prefix$
        ENDDO

        DO 11       { PREFIX }
          GOSUB Set_Prefix [Column]
        ENDDO

        DO 12       { Create directory file }
          Old_Prefix$ = PREFIX$
          Space_Flag! = FALSE
          Copy_Flag! = TRUE
          Select_Flag! = FALSE
          GOSUB Get_FileName ["Create-Select directory: <CR>, <Esc>", Column, Choice, Space_Flag! ]
          Select_Flag! = TRUE
          HOME
          VTAB (10)
          PRINT TAB (10);"Name of directory in ";PREFIX$;
          INPUT " ";File_Name$
          CREATE File_Name$
          PREFIX Old_Prefix$
          Copy_Flag! = FALSE
        ENDDO

        DO 13
          GOSUB Set_Cat_Order [ Column ]
        ENDDO

        DO 14      { Find a file in the system }
          Old_Prefix$ = PREFIX$
          GOSUB File_Find [Column]
          PREFIX Old_Prefix$
        ENDDO

        DO 15      { Quit GS/OS utilities }
          Quit_Flag! = TRUE
        ENDDO
      ENDCASE
      Esc_Flag! = FALSE   { Don't stop loop if Esc in disk function }
    ENDIF         { Esc key pressed }
  UNTIL Quit_Flag! OR Esc_Flag!


Retour au sommaire
hr docs


Source: Info.


PROGRAM Help
@ LIST
@ OPTIMIZ
INT (A-R): STR (S-Z)

{ Print a message, then delay
 until any key is pressed }

  PROC Hit_Key [ Column ]
    PRINT TAB (Column);
    INVERSE
    PRINT "Hit any key to continue";
    REPEAT
      INKEY A$
    UNTIL A$ <> ""
    NORMAL
    PRINT
  ENDPROC

  PROC Help_Me
    HOME
    PRINT TAB (35);"HELP SCREEN"
    VTAB (5)
    PRINT TAB (10);"Source files on back of utilities disk under folder SOURCE."
    PRINT
    PRINT TAB (10);"When using the Micol Media Management System (utility FILER),  choose"
    PRINT TAB (10);"a file by means of the <up-arrow>, <down-arrow> keys, select/deselect"
    PRINT TAB (10);"a file with the <Space bar>.  To reference a sub-directory, place the"
    PRINT TAB (10);"cursor over the directory file and hit the <Return> key.  Once even"
    PRINT TAB (10);"one file has been selected, you may not go to a sub-directory.  Use"
    PRINT TAB (10);"the <back-arrow> key to go to a previous directory. To select all"
    PRINT TAB (10);"files in a directory, use the plus (+) symbol.  To deselect all"
    PRINT TAB (10);"choices, use the minus (-) symbol.  The <Return> key hit, when not"
    PRINT TAB (10);"over a DIR type file, or when no items have been selected, will"
    PRINT TAB (10);"complete the selection."
    PRINT
    PRINT TAB (10);"Some commands expect just a single selection.  In this case, if more"
    PRINT TAB (10);"than one file is selected, only the first sequential selection will"
    PRINT TAB (10);"be used."
    PRINT
    GOSUB Hit_key [30]
    HOME
    VTAB (6)
    PRINT TAB (10);"If using the Find File command, seach will try to match any entry"
    PRINT TAB (10);"you give, including dates, file type, etc., exactly as the entry"
    PRINT TAB (10);"appears in the catalog, except the case of the letters is ignored."
    PRINT TAB (10);"As partial matches anywhere within the line will also be made, be"
    PRINT TAB (10);"very careful when deciding for what to search."
    PRINT
    PRINT TAB (10);"Please note, that currently, the system is set to handle a maximum"
    PRINT TAB (10);"of only 54 files.  Any other files in a single directory will be"
    PRINT TAB (10);"ignored."
    PRINT
    PRINT TAB (10);"Use the <Esc> key to terminate a command."
    PRINT
    GOSUB Hit_Key [30]
    HOME
    PRINT TAB (23);"Using the Micol Software Calculator"
    VTAB (5)
    PRINT TAB (10);"When using the Calculator (utility CALCULATOR), the characters shown"
    PRINT TAB (10);"on the lower portion of the display are entered from the keyboard,"
    PRINT TAB (10);"while the functions (just above) are choosen by the arrow keys, and"
    PRINT TAB (10);"are selected by hitting the <Return> key.  Degrees/Radians and"
    PRINT TAB (10);"Hex/Decimal are toggle keys; hitting the <Return> key will"
    PRINT tab (10);"go from one to the other."
    PRINT
    PRINT TAB (10);"All calculations within the calculator are to 9 or 10 places,"
    PRINT TAB (10);"and the display is rounded to 8 places.  However, internally,"
    PRINT TAB (10);"9/10 place accuracy is maintained. As a result of complex"
    PRINT TAB (10);"calculations, round off errors may be internally maintained,"
    PRINT TAB (10);"which may eventually effect the 8 digit display.  No rounding"
    PRINT TAB (10);"within the memory."
    PRINT
    PRINT TAB (10);"Note that unary operators are not allowed and no precedence of"
    PRINT TAB (10);"operations is observed.  Hex values are truncated."
    PRINT
    GOSUB Hit_key [30]
    HOME
    VTAB (10)
    PRINT TAB (10);"The ASCII chart is utility ASCII. It is self contained and requires"
    PRINT TAB (10);"no input from the user."
    PRINT
    PRINT TAB (10);"The custom font designer is utility FONT.  Press a question mark"
    PRINT TAB (10);"from FONT (?) for information on how to use this utility."
    PRINT
    GOSUB Hit_key [30]
    HOME
    INVERSE
    PRINT TAB (27);"Micol's Limitation of Liability"
    NORMAL
    VTAB (9)
    PRINT TAB (10);"While every precaution has been taken to ensure the reliablity"
    PRINT TAB (10);"of the Micol Advanced Utilities, Micol Systems, Inc. cannot be"
    PRINT TAB (10);"held responsible for any loss or damage caused by our software."
    PRINT TAB (10);"Use the Micol Advanced Utilities at your own risk."
    PRINT
    GOSUB Hit_Key [30]
  ENDPROC

  GOSUB Help_Me
  HOME
END


Retour au sommaire