From: Deckard
To: BluPhoenyx
(comp.sys.apple2)
Date: oct 2 2007
Last updated: may 17 2008
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)
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.
-------------------------------------------------------------------------------
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
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
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
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
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
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
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
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
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!
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