mirror of
https://github.com/cc65/cc65.git
synced 2024-10-31 20:06:11 +00:00
1665 lines
69 KiB
Plaintext
1665 lines
69 KiB
Plaintext
<!doctype linuxdoc system>
|
|
|
|
<article>
|
|
<title>GEOSLib docs
|
|
<author><url url="mailto:ytm@elysium.pl" name="Maciej Witkowiak">
|
|
|
|
<abstract>
|
|
This is the documentation of cc65's GEOSLib, but information contained here may be also
|
|
useful for writing GEOS applications in general.
|
|
</abstract>
|
|
|
|
<!-- Table of contents -->
|
|
<toc>
|
|
|
|
<!-- Begin the document -->
|
|
|
|
<sect>Introduction
|
|
<p>
|
|
As we all know that the best computers in the world are the C64 and C128. They have their GUI too -
|
|
the excellent GEOS. GEOS seems very difficult and cryptic for many people, from programmer's point
|
|
of view. That's not true. The designers of GEOS created a flexible and powerful system, which
|
|
is easy to use and program.
|
|
<p>
|
|
Coding GEOS in C? That's something new. It is possible now - with Ulrich von Bassewitz's cc65
|
|
package and my GEOSLib you are able to create GEOS applications in no time.
|
|
<p>
|
|
GEOSLib supports a subset of the standard cc65 libraries. Whenever possible native Kernal functions
|
|
are used (e.g. <tt/memset/ is an alias for <tt/FillRam/), however not all are supported. E.g.
|
|
string functions like <tt/strcmp/, <tt/strcpy/ are doubled with native <tt/CmpString/,
|
|
<tt/CopyString/ because the latter can handle only 256 byte strings. Keep this in mind when
|
|
you write your program. If you don't need long strings simply use functions from the Kernal,
|
|
the resulting code will be smaller.
|
|
<p>
|
|
<tt/dio/ - direct disk access is available, but you might have problems with devices other
|
|
than 1541, 1571 or 1581. RAM drives emulating these should work.
|
|
<p>
|
|
<tt/conio/ - simple console input-output is available for command line applications.
|
|
This implementation assumes that one character does fit in 8x8 cell, so output with
|
|
default BSW font, which is has 9 points, might be a bit messy. There is no color support in
|
|
GEOS 2.0 so color functions are disabled. Both 40 and 80 column modes are supported
|
|
and automatically detected.
|
|
<p>
|
|
<tt/tgi/ - TGI driver for GEOS that supports both 40 and 80 column modes but mode can not be
|
|
changed between <tt/tgi_init/ and <tt/tgi_done/.
|
|
<p>
|
|
<tt/joy/ - JOY driver for GEOS that supports only joystick, not current pointing device.
|
|
<p>
|
|
It is safe to use these standard includes and their contents:
|
|
<tt/assert.h, conio.h, dio.h, errno.h, em.h, geos.h, joystick.h, modload.h, mouse.h, stdlib.h, string.h, tgi.h, time.h/
|
|
<p>
|
|
For <tt/time.h/ functions <tt/clock()/ and <tt/clock_gettime()/ note that the resolution is one second.
|
|
<p>
|
|
Functions from the headers above are either standard C library functions or cc65-specific, in
|
|
either case they are not GEOS specific and so they are not described here.
|
|
<p>
|
|
I am an assembler programmer and GEOSLib was designed in such way that cc65 could emit the best
|
|
available code (well, the best as for machine :-). Many of the <tt/void foo (void)/ functions are
|
|
just raw calls to the Kernal (assembled just as <tt/jsr _foo/), look in <tt/gsym.h/, where you
|
|
can find many definitions of standard GEOS locations. Access to these addresses is optimized by
|
|
cc65 to simple <tt/lda/ and <tt/sta/. Don't be afraid to use C syntax.
|
|
|
|
<sect1>Requirements
|
|
<p>
|
|
You don't need a C64 or C128 for development. The only hardware requirement is a PC capable of
|
|
running cc65. You do however need C64 or C128 emulator and GEOS disk images (.d64) to test your
|
|
programs.
|
|
|
|
The software needed:
|
|
<itemize>
|
|
<item><em/cc65/ Excellent package containing a C crosscompiler, a crossassembler and a linker, you
|
|
can get it from: <url url="https://cc65.github.io/">.
|
|
<item><em/VICE/ This is a portable C64, C128 and few other Commodore computers emulator, you
|
|
can obtain it from: <url url="http://vice-emu.sourceforge.net/">.
|
|
The VICE package contains the <em/c1541/ program that is able
|
|
to convert/unconvert GEOS files to disk images.
|
|
<item><em/The Star Commander/ This tool is only for DOS. You will need it for transferring
|
|
object files from a PC to a 1541. There's also one important ability of this
|
|
tool - it automatically un-converts .cvt files into GEOS native format on
|
|
disk image files. Check out: <url url="http://sta.c64.org/sc.html">.
|
|
<item><em/opencbm/ A package that allows for communication directly with a 1541 and
|
|
other Commodore IEC bus drives. It can be a replacement for Star Commander if
|
|
you only want to transfer files to a disk and unconvert using GEOS program for
|
|
this purpose. Check out: <url url="https://spiro.trikaliotis.net/opencbm">.
|
|
</itemize>
|
|
<p>
|
|
VICE and cc65 are portable - they run on variety of platforms - DOS, Win32 and UNIX. GEOSLib only
|
|
needs cc65.
|
|
<p>
|
|
<em/Update:/ starting from v2.5.0 GEOSLib is a part of the cc65 package as its GEOS support library.
|
|
|
|
<sect1>Legal
|
|
<p>
|
|
I want to thank Uz for his cc65 package, Alexander Boyce for his excellent GEOS Programmer's
|
|
Reference Guide and BSW for GEOS.
|
|
<p>
|
|
GEOSLib is covered by the same license as cc65. You can find the whole text
|
|
among documentation. I would really appreciate if you would like to send me
|
|
your comments, suggestions, questions, changes, bug reports etc. I will also
|
|
appreciate if you will just give me a sign that you are using GEOSLib - not
|
|
especially something big and important, mail me even if you are just playing
|
|
with it.
|
|
<p>
|
|
You can send postcards with hellos to:
|
|
<p>
|
|
Maciej Witkowiak, ul. Slowackiego 6/57, 77-400 ZLOTOW
|
|
<p>
|
|
POLAND
|
|
<p>
|
|
e-mail: <tt/ytm@elysium.pl/
|
|
|
|
<sect>What do you have and what to do with it?
|
|
<p>
|
|
This chapter describes some rules you ought to obey, and how to use GEOSLib.
|
|
|
|
<sect1>Usage
|
|
<p>
|
|
Apart from this file, which merely describes only standard GEOS library
|
|
functions, you should read the <tt/grc65/ (GEOS resource compiler) documentation.
|
|
There is information about necessary resource files (each GEOS application
|
|
needs at least one) and the build process - what should be done and in what
|
|
order. Please also read the cc65 documentation on how to compile C, assembler
|
|
and link everything together.
|
|
<p>
|
|
All in all, you just need to place
|
|
<tscreen><verb>
|
|
#include <geos.h>
|
|
</verb></tscreen>
|
|
at the top of your source.
|
|
<p>
|
|
As a general rule read the sources of the example programs and read the headers.
|
|
These are the most reliable sources of knowledge ;-). You will also find there
|
|
many C macros representing various arguments passed to the functions. Please use
|
|
them. You will find your sources easier to understand, and it will be easier
|
|
to find bugs.
|
|
<p>
|
|
All types used in GEOSLib are <tt/unsigned/.
|
|
<p>
|
|
Screen coordinates are given in pixels unless stated differently.
|
|
|
|
<sect1>Notes on style
|
|
<p>
|
|
Contrary to a typical GEOS assembly program which has a main function called after loading that
|
|
setups the screen, menus, icons etc. exiting from the <tt/main/ function in C is equivalent to
|
|
calling <tt/exit()/. These two are the only safe methods of terminating applications. DO NOT
|
|
USE <tt/EnterDeskTop/! Your data may be lost as library destructors and functions registered
|
|
with <tt/atexit/ are not called.
|
|
<p>
|
|
For GEOS GUI applications the recommended program structure is to have everything initialized
|
|
in the <tt/main/ function and at the end of it a call to the <tt/MainLoop()/ function. WARNING! This
|
|
function never returns, any code between <tt/MainLoop();/ and the end of <tt/main/ will not
|
|
be executed. You have to call <tt/exit()/ explicitly somewhere in your code (e.g. in a menu
|
|
handler or via DialogBox action).
|
|
<p>
|
|
Whenever possible use definitions from <tt/gsym.h/. The resulting code is translated by cc65 into
|
|
series of <tt/lda/ and <tt/sta/, so you can't do it better :-).
|
|
<p>
|
|
Don't hesitate to use library functions. Everything was written with size and speed in mind. In
|
|
fact many calls are just redirections to the GEOS Kernal which results in a simple <tt/jsr/.
|
|
<p>
|
|
The <tt/main/ function receives the standard <tt/argc/ and <tt/argv/ parameters. There are
|
|
always either 1 or 3 parameters. The DOS application name is always set as <tt/argv[0]/.
|
|
If present, <tt/argv[1]/ and <tt/argv[2]/ will be set to the data filename and data diskname (it only
|
|
works if the user double-clicks on a data file associated with your application). Note that it is up
|
|
to your application to determine which of the available (up to four) disk drives has the disk
|
|
with given diskname inside. If this fails your program should ask to insert the proper disk into
|
|
one of available drives.
|
|
<p>
|
|
You might wonder why I have chosen a sometimes weird order of arguments in functions. I just
|
|
wanted to avoid unnecessary pushing and popping of arguments from the stack because cc65 can pass a single
|
|
<tt/unsigned int/ through CPU registers.
|
|
<p>
|
|
Do not try to compile in strict ANSI mode. The library uses cc65 extensions which are not available in
|
|
ANSI.
|
|
<p>
|
|
It is possible to use dynamically loaded modules, three such modules are provided:
|
|
A GEOS TGI driver, a GEOS EMD driver (for VDC extended memory) and a GEOS JOY driver.
|
|
Just make sure that their filenames appear UPPERCASE in DeskTop. There are no more special
|
|
recommendations, read the cc65 documentation about modules and the demo programs source code.
|
|
|
|
<sect>Library Functions
|
|
<p>
|
|
Functions here are sorted more or less in the way they appear in the header files. This way I am able
|
|
to keep functions covering similar tasks near each other. All function names are identical to those
|
|
from the <tt/geosSym/ file provided with the GeoProgrammer package. Only my extensions to <tt/geosSym/
|
|
are covered by new names, but I tried to keep them in the naming convention.
|
|
|
|
<sect1>Graphics
|
|
<p>
|
|
This section covers the drawing package of GEOS along with text output routines.
|
|
|
|
<sect2>SetNewMode
|
|
<p>
|
|
<tt/void SetNewMode (void)/
|
|
<p>
|
|
This function is intended for use by GEOS 128 only, and will exhibit undefined behavior on the
|
|
C64. It will toggle between the 40 column screen mode and the 80 column screen mode. Many C128 GEOS
|
|
programs implement a "Switch 40/80" submenu option under the <tt/geos/ menu.
|
|
|
|
<sect2>SetPattern
|
|
<p>
|
|
<tt/void SetPattern (char pattern)/
|
|
<p>
|
|
This function sets the current pattern to the given. There are 32 different patterns in GEOS. You can
|
|
see them together in the filling box in GeoPaint.
|
|
|
|
<sect2>GraphicsString
|
|
<p>
|
|
<tt/void GraphicsString (char *myGString)/
|
|
<p>
|
|
One of the more powerfull routines of GEOS. This function calls other graphic functions depending
|
|
on the given command string. See the structures chapter for a more detailed description.
|
|
|
|
<sect2>Rectangle functions
|
|
<p>
|
|
Parameters to those functions are grouped in the <tt/struct window drawWindow/. To speed up things and
|
|
reduce overhead this structure is bound to zero page locations, where all rectangle functions
|
|
expect their parameters. You can modify the data directly (e.g. <tt/drawWindow.top=10/) or via the
|
|
<tt/InitDrawWindow/ function. Contents of <tt/drawWindow/ are guaranteed not to change when only
|
|
using graphics functions. In other cases you should keep your data in separate <tt/struct window/
|
|
and use <tt/InitDrawWindow/ before the first call to one of the rectangle functions.
|
|
|
|
<sect3>InitDrawWindow
|
|
<p>
|
|
<tt/void InitDrawWindow (struct window *myWindow)/
|
|
<p>
|
|
This function only copies the contents of <tt/myWindow/ into the system area of <tt/drawWindow/. Use it
|
|
if for some reason you have to keep your window data out of the zero page space.
|
|
|
|
<sect3>Rectangle
|
|
<p>
|
|
<tt/void Rectangle (void)/
|
|
<p>
|
|
This draws on screen a rectangle filled with the current pattern.
|
|
|
|
<sect3>FrameRectangle
|
|
<p>
|
|
<tt/void FrameRectangle (char pattern)/
|
|
<p>
|
|
This one draws a frame with the given bit pattern (not a pattern from the GEOS palette).
|
|
|
|
<sect3>InvertRectangle
|
|
<p>
|
|
<tt/void InvertRectangle (void)/
|
|
<p>
|
|
Just as the name says...
|
|
|
|
<sect3>ImprintRectangle and RecoverRectangle
|
|
<p>
|
|
<tt/void ImprintRectangle (void)/
|
|
<p>
|
|
<tt/void RecoverRectangle (void)/
|
|
<p>
|
|
These two functions are for copying parts of the screen to (<tt/Imprint/) and from (<tt/Recover/) the
|
|
backbuffer of the screen. For example when drawing a new menu box GEOS first uses
|
|
<tt/ImprintRectangle/ to save the area under the box, and restores it by <tt/RecoverRectangle/ upon
|
|
destroying the menu.
|
|
|
|
<sect2>Line Functions
|
|
<p>
|
|
The GEOS drawing package is optimized so there are different functions for drawing vertical and
|
|
horizontal lines.
|
|
|
|
<sect3>HorizontalLine
|
|
<p>
|
|
<tt/void HorizontalLine (char pattern, char y, unsigned xStart, unsigned xEnd)/
|
|
<p>
|
|
This function draws a horizontal line using the given pattern. Note that <tt/pattern/ is not a pattern
|
|
number as set in <tt/SetPattern/ but a true bit pattern.
|
|
|
|
<sect3>InvertLine
|
|
<p>
|
|
<tt/void InvertLine (char y, unsigned xStart, unsigned xEnd)/
|
|
<p>
|
|
There is only a horizontal version.
|
|
|
|
<sect3>RecoverLine
|
|
<p>
|
|
<tt/void RecoverLine (char y, unsigned xStart, unsigned xEnd)/
|
|
<p>
|
|
This function recovers a single line. It is utilized by <tt/RecoverRectangle/. See its description
|
|
for more details.
|
|
|
|
<sect3>VerticalLine
|
|
<p>
|
|
<tt/void VerticalLine (char pattern, char yStart, char yEnd, unsigned x)/
|
|
<p>
|
|
This function draws a vertical line using the given pattern. Note that <tt/pattern/ is not a pattern
|
|
number as set in <tt/SetPattern/ but a true bit pattern.
|
|
|
|
<sect3>DrawLine
|
|
<p>
|
|
<tt/void DrawLine (char mode, struct window *myWindow)/
|
|
<p>
|
|
The <tt/top/ parameters of <tt/struct window/ describe the starting point of the line, while
|
|
<tt/bottom/ ones are for the ending point. If <tt/mode/ is <tt/DRAW_DRAW/ then the current pattern from
|
|
<tt/SetPattern/ is used for drawing. If <tt/mode/ is <tt/DRAW_ERASE/ then the line is erased from the
|
|
screen. If <tt/mode/ is <tt/DRAW_COPY/ then the line is copied from/to back/frontbuffer, according to
|
|
the <tt/dispBufferOn/ setting.
|
|
|
|
<sect2>Point Functions
|
|
<p>
|
|
The parameters to these two functions are passed by a pointer to an own <tt/struct pixel/ filled with
|
|
proper values.
|
|
|
|
<sect3>DrawPoint
|
|
<p>
|
|
<tt/void DrawPoint (char mode, struct pixel *myPixel)/
|
|
<p>
|
|
Depending on <tt/mode/ (see <tt/DrawLine/) draws/erases/copies a single point
|
|
on the screen.
|
|
|
|
<sect3>TestPoint
|
|
<p>
|
|
<tt/char TestPoint (struct pixel *myPixel)/
|
|
<p>
|
|
This function tests if the given pixel is set and returns <tt/true/ (non-zero) or <tt/false/ (zero).
|
|
|
|
<sect2>Character and string output
|
|
|
|
<sect3>PutChar
|
|
<p>
|
|
<tt/void PutChar (char character, char y, unsigned x)/
|
|
<p>
|
|
This function outputs a single character using the current style and font to the screen.
|
|
|
|
<sect3>PutString
|
|
<p>
|
|
<tt/void PutString (char *myString, char y, unsigned x)/
|
|
<p>
|
|
Same as <tt/PutChar/ except the fact that you can output a whole <tt/NULL/-terminated string.
|
|
See <tt/ggraph.h/ for the list of tokens that you can also place in the string - like <tt/CBOLDON/ or
|
|
<tt/COUTLINEON/.
|
|
|
|
<sect3>PutDecimal
|
|
<p>
|
|
<tt/void PutDecimal (char parameter, unsigned value, char y, unsigned x)/
|
|
<p>
|
|
This function converts <tt/value/ to its decimal representation and outputs it to the screen.
|
|
The <tt/parameter/ is the field width in pixels (range 1-31) and the mode bits. Depending on them
|
|
the string can be filled with zeroes (the string is always 5 characters long) or not and left or right
|
|
justified to the given pixel. See <tt/ggraph.h/ for predefined values for <tt/parameter/.
|
|
|
|
<sect2>Font Handling
|
|
|
|
<sect3>GetCharWidth
|
|
<p>
|
|
<tt/char GetCharWidth (char character)/
|
|
<p>
|
|
This function returns the real width (in pixels) of the given character with the current font. It can be used
|
|
for counting the length of a string on the screen, allowing for indentation or justification.
|
|
|
|
<sect3>LoadCharSet
|
|
<p>
|
|
<tt/void LoadCharSet (struct fontdesc *myFont)/
|
|
<p>
|
|
This function forces GEOS to use the given font. <tt/myFont/ should be casted from a
|
|
pointer to the start of the area where a record from a font file (VLIR structure) was loaded.
|
|
|
|
<sect3>UseSystemFont
|
|
<p>
|
|
<tt/void UseSystemFont (void)/
|
|
<p>
|
|
This function forces GEOS to use the built-in BSW font.
|
|
|
|
<sect2>Bitmap handling
|
|
<p>
|
|
I'm not quite sure how these functions are working (except <tt/BitmapUp/) so you should
|
|
probably look into the library sources and compare it with your knowledge. Please let me know
|
|
if something is wrong or broken.
|
|
|
|
<sect3>BitmapUp
|
|
<p>
|
|
<tt/void BitmapUp (struct iconpic *myPic)/
|
|
<p>
|
|
This function unpacks the bitmap and places it on the screen - just as you set it in the
|
|
<tt/struct iconpic/ pointer which you pass. See <tt/gstruct.h/ for a description of this
|
|
structure. Note that you can only use packed GEOS bitmaps - a simple Photo Scrap is in this format.
|
|
|
|
<sect3>BitmapClip
|
|
<p>
|
|
<tt/void BitmapClip (char skipLeft, char skipRight, unsigned skipTop, struct iconpic *myPic)/
|
|
<p>
|
|
This function acts similar to <tt/BitmapUp/ but you can also define which parts of the bitmap are
|
|
to be drawn - you give the number of columns (8-pixel) to skip on the right and left of the bitmap,
|
|
and the number of rows to skip from the top if it.
|
|
|
|
<sect3>BitOtherClip
|
|
<p>
|
|
<tt/void BitOtherClip (void *proc1, void *proc2, char skipLeft, char skip Right, unsigned skipTop,
|
|
struct iconpic *myPic)/
|
|
<p>
|
|
Similar to the previous one with some extension. <tt/proc1/ is called before reading a byte (it
|
|
returns in .A the next value), and <tt/proc2/ is called every time the parser reads a byte which is
|
|
not a piece of a pattern (byte of code greater than 219). Both procedures should be written
|
|
separately in assembler and declared as <tt/__fastcall__/ returning char.
|
|
|
|
<sect1>Menus and Icons
|
|
<p>
|
|
Here you will find information about functions related with menus and icons.
|
|
|
|
<sect2>Menus
|
|
<p>
|
|
Menus are essential for a GUI. GEOS can handle only one menu at a time, but each menu can call
|
|
another one, which results in a submenu tree. There can be up to 8 menu levels, each one with up
|
|
to 32 items.
|
|
<p>
|
|
Menus are initialized with <tt/DoMenu/ and then the Kernal takes care of everything. Your code
|
|
(called from an event handler) should be a function without parameters, returning void. You should
|
|
use <tt/DoPreviousMenu/ or <tt/GotoFirstMenu/ at least once in its code to have the screen clean.
|
|
|
|
<sect3>DoMenu
|
|
<p>
|
|
<tt/void DoMenu (struct menu *myMenu)/
|
|
<p>
|
|
This function initializes the GEOS menu processor and exits. See <tt/DoMenu structure/ for more
|
|
information about it. Know that many GEOS applications just initialize the screen, menu and
|
|
exit to the main Kernal loop, this proves the power of <tt/DoMenu/.
|
|
|
|
<sect3>ReDoMenu
|
|
<p>
|
|
<tt/void ReDoMenu (void)/
|
|
<p>
|
|
This simply redraws the menu at the lowest level. It works like calling <tt/DoMenu/ again with
|
|
the same parameters.
|
|
|
|
<sect3>RecoverMenu
|
|
<p>
|
|
<tt/void RecoverMenu (void)/
|
|
<p>
|
|
This function erases the current menu from the screen. It doesn't change the menu level.
|
|
|
|
<sect3>RecoverAllMenus
|
|
<p>
|
|
<tt/void RecoverAllMenus (void)/
|
|
<p>
|
|
This calls <tt/RecoverMenu/ and erases all menus from the screen. Then the menu level is
|
|
set to 0 (topmost).
|
|
|
|
<sect3>DoPreviousMenu
|
|
<p>
|
|
<tt/void DoPreviousMenu (void)/
|
|
<p>
|
|
This functions causes the menu processor to go back one menu level. You should use it in menu
|
|
handler code to have the screen clean.
|
|
|
|
<sect3>GotoFirstMenu
|
|
<p>
|
|
<tt/void GotoFirstMenu (void)/
|
|
<p>
|
|
This one jumps back to the topmost menu. If there is only a menu and one submenu it works the
|
|
same as <tt/DoPreviousMenu/.
|
|
|
|
<sect2>Icon Functions
|
|
<p>
|
|
Icons are working similar to menus except the fact that there is only one level. Icons are
|
|
defined as a screen area filled with a bitmap, but if you would setup icons and erase the
|
|
screen they would still be active and clicking in the place where formerly an icon was would cause
|
|
an effect. Similarly if you would setup icons and then turn them off with <tt/ClearMouseMode/
|
|
the bitmap would still be on the screen but clicking on it would not cause any action.
|
|
There is only one, but powerful icon function.
|
|
|
|
<sect3>DoIcons
|
|
<p>
|
|
<tt/void DoIcons (struct icontab *myIconTab)/
|
|
<p>
|
|
This function initializes all icons that are present on the screen at once. For more information
|
|
look at the <tt/Icons/ chapter in this manual.
|
|
|
|
<sect1>DialogBoxes
|
|
<p>
|
|
This chapter covers the most powerful GEOS user interface function - <tt/DoDlgBox/.
|
|
|
|
<sect2>GEOS standard
|
|
|
|
<sect3>DoDlgBox
|
|
<p>
|
|
<tt/char DoDlgBox (char *dialogString)/
|
|
<p>
|
|
This function returns one byte. It can be the value of one of six standard icons (see <tt/gdlgbox.h/)
|
|
or whatever the closing routine passes. Register <tt/r0L/ also contains this value.
|
|
<p>
|
|
Read the structures chapter for the specs of the <tt/dialogString/.
|
|
|
|
<sect3>RstrFrmDialogue
|
|
<p>
|
|
<tt/char RstrFrmDialogue/
|
|
<p>
|
|
This function is called from within DoDlgBox event. It immediately closes the DialogBox and returns
|
|
the owner ID (or whatever caller has in the .A register).
|
|
|
|
<sect2>GEOSLib extensions
|
|
<p>
|
|
To simplify the usage of DoDlgBox from C I wrote some helper functions - wrappers for DoDlgBox,
|
|
with predefined data. In one word - these are standard DialogBoxes you can see in almost every
|
|
GEOS application.
|
|
|
|
<sect3>DlgBoxYesNo, DlgBoxOkCancel, DlgBoxOk
|
|
<p>
|
|
<tt/char DlgBoxYesNo (char *line1, char *line2)/
|
|
<p>
|
|
<tt/char DlgBoxOkCancel (char *line1, char *line2)/
|
|
<p>
|
|
<tt/void DlgBoxOk (char *line1, char *line2)/
|
|
<p>
|
|
These function show two lines of text in a standard-sized DialogBox. You can read the code of the
|
|
pressed icon from the return value. E.g. for <tt/DlgBoxYesNo/ it can only be <tt/YES/ or <tt/NO/.
|
|
You can pass an empty string or NULL to get a blank line.
|
|
|
|
<sect3>DlgBoxGetString
|
|
<p>
|
|
<tt/char DlgBoxGetString (char *string, char strlen, char *line1, char *line2)/
|
|
<p>
|
|
This function prompts the user to enter a string of at most <tt/strlen/ characters. It is returned
|
|
in <tt/string/. The two given lines of text are shown above the input line. Please remember
|
|
that there is also a <tt/CANCEL/ icon in the DialogBox and you should test if user confirmed his
|
|
input or gave up. The <tt/string/ is also shown so you can place a default input there or remember
|
|
to place <tt/NULL/ at start.
|
|
|
|
<sect3>DlgBoxFileSelect
|
|
<p>
|
|
<tt/char DlgBoxFileSelect (char *class, char filetype, char *filename)/
|
|
<p>
|
|
This routine is the standard file selector. It can return <tt/OPEN/, <tt/CANCEL/ or disk error
|
|
on reading the directory or opening the disk.
|
|
There is also a <tt/DISK/ icon shown, but it is handled internally. You pass as input parameters
|
|
<tt/filetype/ and a pointer to a string containing the first part of a file's class. If this string is
|
|
empty (<tt/NULL/ at the start), then all files with given filetype will be shown.
|
|
<p>
|
|
At present this file selector handles only first 16 files of given type and supports only one
|
|
(current) drive.
|
|
|
|
<sect3>MessageBox
|
|
<p>
|
|
<tt/char MessageBox (char mode, const char *format, ...)/
|
|
<p>
|
|
This function is a more general one. It works very much like <tt/printf/ in a
|
|
box. The only difference is the <tt/mode/ parameter which allows for placing
|
|
default icons (see <tt/gdlgbox.h/ for list of possible <tt/MB_/ values).
|
|
Any too wide text will be clipped to the size of the default window. If <tt/mode/
|
|
is invalid or equal to <tt/MB_EMPTY/ then the window will be closed
|
|
after a click. Otherwise the user must choose an icon.
|
|
<p>
|
|
Note: Use it if you really need (or if you use it in many places) as
|
|
it adds quite amount of code to your program.
|
|
<p>
|
|
Note: the formatted text <em/cannot exceed/ 255 bytes in length, there is no check
|
|
for that.
|
|
|
|
<sect1>Mouse, Sprites and Cursors
|
|
<p>
|
|
You will find here functions related to sprite and mouse drawing and handling.
|
|
|
|
<sect2>Mouse related functions
|
|
<p>
|
|
These cover the mouse - as a general pointing device, but expect users to utilize as different devices
|
|
as a digital or analog joystick, a mouse, a lightpen or a koalapad (whatever it is).
|
|
|
|
<sect3>StartMouseMode
|
|
<p>
|
|
<tt/void StartMouseMode (void)/
|
|
<p>
|
|
This function initializes the mouse vectors - <tt/mouseVector/ and <tt/mouseFaultVec/, and then
|
|
calls <tt/MouseUp/.
|
|
|
|
<sect3>ClearMouseMode
|
|
<p>
|
|
<tt/void ClearMouseMode (void)/
|
|
<p>
|
|
This function disables all mouse activities - icons and menus stop to respond to mouse events,
|
|
but they are not cleared from the screen.
|
|
|
|
<sect3>MouseUp and MouseOff
|
|
<p>
|
|
<tt/void MouseUp (void)/
|
|
<p>
|
|
<tt/void MouseOff (void)/
|
|
<p>
|
|
The first function turns the mouse pointer on. It appears on the next IRQ. The second one does
|
|
the opposite - it turns off the pointer, but its position is still updated by the input driver.
|
|
|
|
<sect3>IsMseInRegion
|
|
<p>
|
|
<tt/char IsMseInRegion (struct window *myWindow)/
|
|
<p>
|
|
This function tests if the mouse pointer is actually in the given range of the screen. See <tt/gsprite.h/ for
|
|
a description of the bits in the return values - they describe the position in detail.
|
|
|
|
<sect2>Sprites
|
|
<p>
|
|
You are free to use any of the eight sprites, but keep in mind that sprite 0 is actually the mouse
|
|
pointer and sprite 1 can be overwritten when using a text prompt. You don't have to worry about
|
|
40/80 column issues because GEOS128 has a pretty good sprite emulator for the VDC.
|
|
|
|
<sect3>DrawSprite
|
|
<p>
|
|
<tt/void DrawSprite (char sprite, char *mySprite)/
|
|
<p>
|
|
This function initializes the sprite data. <tt/mySprite/ is a 63-byte table with bitmap data, which
|
|
is copied to the system sprite area (at <tt/sprpic/ - see <tt/gsym.h/). Hardware sprite registers are
|
|
not initialized and the sprite is not yet visible.
|
|
|
|
<sect3>PosSprite
|
|
<p>
|
|
<tt/void PosSprite (char sprite, struct pixel *myPixel)/
|
|
<p>
|
|
This function positions the sprite on the screen. The given coordinates are screen ones - they are
|
|
converted to sprite coordinates by GEOS. Due to this you cannot use this function to position your
|
|
sprite off the left or top to the screen.
|
|
|
|
<sect3>EnablSprite and DisablSprite
|
|
<p>
|
|
<tt/void EnablSprite (char sprite)/
|
|
<p>
|
|
<tt/void DisablSprite (char sprite)/
|
|
<p>
|
|
These two functions are responsible for making the sprite visible or not.
|
|
|
|
<sect2>Cursors and Console
|
|
|
|
<sect3>InitTextPrompt
|
|
<p>
|
|
<tt/void InitTextPrompt (char height)/
|
|
<p>
|
|
This function initializes sprite 1 for a text prompt with given <tt/height/. This parameter can be in
|
|
range 1-48.
|
|
|
|
<sect3>PromptOn and PromptOff
|
|
<p>
|
|
<tt/void PromptOn (struct pixel *myPixel)/
|
|
<p>
|
|
<tt/void PromptOff (void)/
|
|
<p>
|
|
The first function places a text prompt in given place and enables blinking.
|
|
The second one is pretty self-explanatory.
|
|
|
|
<sect3>GetNextChar
|
|
<p>
|
|
<tt/char GetNextChar (void)/
|
|
<p>
|
|
This function gets the next character from the keyboard queue. If the queue is empty it returns
|
|
<tt/NULL/, otherwise you receive the true ASCII code of a character or the value of a special (function)
|
|
key. See <tt/gsprite.h/ for the list of them.
|
|
|
|
<sect1>Disk
|
|
<p>
|
|
This chapter covers rather low-level disk routines. You should use them with care, because
|
|
you may easily corrupt data on disks. Also remember that contemporary GEOS supports many various
|
|
devices and sticking to 1541 track layout (e.g. expecting the directory on track 18) might be
|
|
dangerous.
|
|
<p>
|
|
For some purposes you might consider using the <tt/dio.h/ interface to disk access. It is native.
|
|
<p>
|
|
All GEOS disk functions return an error code in the X register. In some cases this is returned by the
|
|
GEOSLib function (if its type is <tt/char/), but in all cases the last error is saved in the <tt/__oserror/
|
|
location. If it is nonzero - an error occured. See <tt/gdisk.h/ for the list of possible errorcodes.
|
|
You need to include <tt/errno.h/ to get <tt/__oserror/, together with the standard <tt/errno/. The
|
|
latter gives less verbose, but still usable information and can be used with <tt/strerror/.
|
|
Probably you will get more information using <tt/_stroserror/ in a similar way.
|
|
<p>
|
|
For passing parameters use almost always a pointer to your data e.g. <tt/ReadBuff (&myTrSe)/.
|
|
|
|
<sect2>Buffer functions
|
|
<p>
|
|
These functions take a single data sector (256 bytes) to read or write on the disk.
|
|
|
|
<sect3>ReadBuff and Writebuff
|
|
<p>
|
|
<tt/char ReadBuff (struct tr_se *myTrSe)/
|
|
<p>
|
|
<tt/char WriteBuff (struct tr_se *myTrSe)/
|
|
<p>
|
|
These functions read and write a sector placed at <tt/diskBlkBuf/.
|
|
|
|
<sect3>GetBlock and ReadBlock
|
|
<p>
|
|
<tt/char GetBlock (struct tr_se *myTrSe, char *buffer)/
|
|
<p>
|
|
<tt/char ReadBlock (struct tr_se *myTrSe, char *buffer)/
|
|
<p>
|
|
These two functions read a single block directly to the 256 byte array placed at <tt/buffer/.
|
|
The difference between them is that <tt/GetBlock/ initializes TurboDos in the drive if it was not
|
|
enabled. <tt/ReadBlock/ assumes that it is already enabled thus being slightly faster.
|
|
|
|
<sect3>PutBlock, WriteBlock, VerWriteBlock
|
|
<p>
|
|
<tt/char PutBlock (struct tr_se *myTrSe, char *buffer)/
|
|
<p>
|
|
<tt/char WriteBlock (struct tr_se *myTrSe, char *buffer)/
|
|
<p>
|
|
<tt/char VerWriteBlock (struct tr_se *myTrSe, char *buffer)/
|
|
<p>
|
|
Similar to previous but needed for writing the disk. <tt/VerWriteBlock/ verifies the data after
|
|
writing. In case of an error five tries are attempted before an error code is returned.
|
|
|
|
<sect2>Directory header
|
|
<p>
|
|
The functions described here operate on <tt/curDirHeader/ where the current disk header is stored.
|
|
On larger (than 1541) capacity drives the second part of the directory header is in <tt/dir2Head/.
|
|
|
|
<sect3>GetPtrCurDkNm
|
|
<p>
|
|
<tt/void GetPtrCurDkNm (char *diskName)/
|
|
<p>
|
|
This function fills the given character string with the name of current disk. It is converted to C
|
|
standard - the string is terminated with <tt/NULL/ character instead of code 160 as in Commodore DOS.
|
|
Note that the passed pointer must point to an array of at least 17 bytes.
|
|
|
|
<sect3>GetDirHead and PutDirHead
|
|
<p>
|
|
<tt/char GetDirHead (void)/
|
|
<p>
|
|
<tt/char PutDirHead (void)/
|
|
<p>
|
|
These functions read and write the directory header. You should use <tt/GetDirHead/ before
|
|
using any functions described below, and you should use <tt/PutDirHead/ to save the changes on the
|
|
disk. Otherwise they will be lost. Operating area is the <tt/curDirHead/.
|
|
|
|
<sect3>CalcBlksFree
|
|
<p>
|
|
<tt/unsigned CalcBlksFree (void)/
|
|
<p>
|
|
This function returns the number of free blocks on the current disk. It is counted using data in
|
|
<tt/curDirHead/ so you must initialize the disk before calling it.
|
|
|
|
<sect3>ChkDskGEOS
|
|
<p>
|
|
<tt/char ChkDskGEOS (void)/
|
|
<p>
|
|
This functions checks <tt/curDirHead/ for the GEOS Format identifier. It returns either true or false,
|
|
and also sets <tt/isGEOS/ properly. You must initialize the disk before using this.
|
|
|
|
<sect3>SetGEOSDisk
|
|
<p>
|
|
<tt/char SetGEOSDisk (void)/
|
|
<p>
|
|
This function initializes disk for use with GEOS. It sets the indicator in directory header and
|
|
allocates a sector for the directory of border files. You don't need to initialize the disk before
|
|
using.
|
|
|
|
<sect3>FindBAMBit
|
|
<p>
|
|
<tt/char FindBAMBit (struct tr_se *myTrSe)/
|
|
<p>
|
|
This function returns the bit value from the BAM (Block Allocation Map) for the given sector. The bit is
|
|
set if the sector is free to use. The returned value is always zero if the sector is already allocated.
|
|
In fact, this function could be used in a following way:
|
|
<tscreen><verb>
|
|
#define BlockInUse FindBAMBit
|
|
...
|
|
if (!BlockInUse(&myTrSe)) {
|
|
... block not allocated ...
|
|
}
|
|
</verb></tscreen>
|
|
<p>
|
|
Anyway, I feel that this function is too low-level.
|
|
|
|
<sect3>BlkAlloc and NxtBlkAlloc
|
|
<p>
|
|
<tt/char BlkAlloc (struct tr_se output[&rsqb, unsigned length)/
|
|
<p>
|
|
<tt/char NxtBlkAlloc (struct tr_se *myTrSe, struct tr_se output[&rsqb, unsigned length)/
|
|
<p>
|
|
Both functions allocate enough disk sectors to fit <tt/length/ bytes in them. You
|
|
find the output in <tt/output/ which is a table of <tt/struct tr_se/. The last entry will have the
|
|
track equal to 0 and sector equal to 255. The simplest way of using them is to use
|
|
predefined space in the GEOS data space and pass <tt/fileTrScTab/, which is a predefined table.
|
|
<p>
|
|
The difference between those two is that <tt/NextBlkAlloc/ starts allocating from the given sector,
|
|
and <tt/BlkAlloc/ starts from the first nonused sector.
|
|
<p>
|
|
You need to use <tt/PutDirHead/ later to save any changes in BAM.
|
|
|
|
<sect3>FreeBlock
|
|
<p>
|
|
<tt/char FreeBlock (struct tr_se *myTrSe)/
|
|
<p>
|
|
Simply deallocates a block in the BAM. You need to update the BAM with <tt/PutDirHead/.
|
|
|
|
<sect3>SetNextFree
|
|
<p>
|
|
<tt/struct tr_se SetNextFree (struct tr_se *myTrSe)/
|
|
<p>
|
|
This function finds the first free sector starting from given track and sector and allocates it.
|
|
It might return the same argument if the given block is not allocated. I wanted it to be type
|
|
clean, but this made the usage a bit tricky. To assign a value to your own <tt/struct tr_se/ you have to
|
|
cast both variables to <tt/unsigned/. E.g.
|
|
<tscreen><verb>
|
|
struct tr_se myTrSe;
|
|
...
|
|
(unsigned)myTrSe=(unsigned)SetNextFree(&otherTrSe);
|
|
</verb></tscreen>
|
|
<p>
|
|
In this example <tt/otherTrSe/ can be replaced by <tt/myTrSe/.
|
|
<p>
|
|
Note: you <em/must/ use casting to have the correct values.
|
|
|
|
<sect2>Low-level disk IO
|
|
<p>
|
|
Functions described here are more usable in Kernal or drivers code, less common in applications,
|
|
but who knows, maybe someone will need them.
|
|
|
|
<sect3>EnterTurbo, ExitTurbo, PurgeTurbo
|
|
<p>
|
|
<tt/void EnterTurbo (void)/
|
|
<p>
|
|
<tt/void ExitTurbo (void)/
|
|
<p>
|
|
<tt/void PurgeTurbo (void)/
|
|
<p>
|
|
These functions are the interface to the GEOS TurboDos feature which makes slow Commodore drives a bit
|
|
more usable. <tt/EnterTurbo/ enables TurboDos unless it is already enabled. If not, then you will
|
|
have to wait a bit to transfer the TurboDos code into disk drive RAM. <tt/ExitTurbo/ disables TurboDos.
|
|
This is useful for sending some DOS commands to a drive e.g. for formatting. Note that before any
|
|
interaction with the Kernal in ROM you have to call <tt/InitForIO/. You don't have to worry about speed.
|
|
<tt/EnterTurbo/ will only enable TurboDos (no code transfer) if TurboDos was disabled with
|
|
<tt/ExitTurbo/. <tt/PurgeTurbo/ acts differently from <tt/ExitTurbo/ - it not only disables TurboDos,
|
|
but also removes it from drive RAM (not quite true, but it works like that). After using
|
|
<tt/PurgeTurbo/ the next call to <tt/EnterTurbo/ will reload drive RAM.
|
|
|
|
<sect3>ChangeDiskDevice
|
|
<p>
|
|
<tt/char ChangeDiskDevice (char newDevice)/
|
|
<p>
|
|
This function changes the device number of the current device (in fact drives only) to the given one. It is
|
|
usable for swapping drives. There's no check if the given <tt/newDevice/ already exist, so if you want
|
|
to change the logical number of drive 8 to 9 and you already have a drive number 9 then GEOS will probably
|
|
hang on disk access. Use safe, large numbers. Note that the safe IEC range is 8-30.
|
|
|
|
<sect2>Disk Initialization
|
|
<p>
|
|
GEOS has two functions for initialization ('logging in' as they say on CP/M) of a disk.
|
|
<sect3>OpenDisk
|
|
<p>
|
|
<tt/char OpenDisk (void)/
|
|
<p>
|
|
This function initializes everything for a new disk. It loads and enables TurboDos if needed.
|
|
Then the disk is initialized with <tt/NewDisk/. Next, <tt/GetDirHead/ initializes <tt/curDirHead/.
|
|
Disk names are compared and if they differ then the disk cache on REU is cleared. Finally the format is
|
|
checked with <tt/ChkDkGEOS/ and the disk name is updated in the internal tables.
|
|
|
|
<sect3>NewDisk
|
|
<p>
|
|
<tt/char NewDisk (void)/
|
|
<p>
|
|
This function is similar to the DOS command I. It clears the REU cache and enables TurboDos if needed.
|
|
|
|
<sect1>Files
|
|
<p>
|
|
This section covers the GEOS file interface.
|
|
|
|
<sect2>Directory handling
|
|
<p>
|
|
The functions described here are common for SEQ and VLIR structures.
|
|
|
|
<sect3>Get1stDirEntry and GetNxtDirEntry
|
|
<p>
|
|
<tt/struct filehandle *Get1stDirEntry (void)/
|
|
<p>
|
|
<tt/struct filehandle *GetNxtDirEntry (void)/
|
|
<p>
|
|
These two functions are best suited for scanning the whole directory for particular files. Note that
|
|
the returned filehandles describe all file slots in the directory - even those with deleted files.
|
|
The return value can be obtained by casting both sides to <tt/unsigned/ - as in the <tt/SetNextFree/
|
|
function or read directly after a call to those two functions from <tt/r5/. The current sector number
|
|
is in <tt/r1/ and the sector data itself is in <tt/diskBlkBuf/.
|
|
|
|
<sect3>FindFile
|
|
<p>
|
|
<tt/char FindFile (char *fName)/
|
|
<p>
|
|
This function scans the whole directory for the given filename. It returns either 0 (success) or 5
|
|
(FILE_NOT_FOUND, defined in <tt/gdisk.h/) or any other fatal disk read error. After a successful
|
|
<tt/FindFile/ you will have <tt/struct filehandle/ at <tt/dirEntryBuf/ filled with the file's data and
|
|
other registers set as described in <tt/GetNxtDirEntry/.
|
|
|
|
<sect3>FindFTypes
|
|
<p>
|
|
<tt/char FindFTypes (char *buffer, char fType, char fMaxNum, char *classTxt)/
|
|
<p>
|
|
This function scans the directory and fills a table at <tt/buffer/ with <tt/char [17]/ entries.
|
|
<tt/fType/ is the GEOS type of the searched files and <tt/classTxt/ is a string for the Class field in the file
|
|
header. Class matches if the given string is equal or shorter than that found in the file's header block.
|
|
If you want just to find all files with the given GEOS type you should pass an empty string or <tt/NULL/ as
|
|
<tt/classTxt/. Be warned that for searching <tt/NON_GEOS/ files you must pass <tt/NULL/ as <tt/classTxt/.
|
|
<tt/fMaxNum/ is the maximal number of files to find, thus the <tt/buffer/ must provide an area of size
|
|
equal to <tt/17 * fMaxNum/. This function returns the number of found files, ranging from 0 to number
|
|
passed as <tt/fMaxNum/. The return value can be also restored from <tt/r7H/.
|
|
|
|
<sect3>DeleteFile
|
|
<p>
|
|
<tt/char DeleteFile (char *fName)/
|
|
<p>
|
|
This function deletes a file by its name. It works for SEQ and VLIR files.
|
|
|
|
<sect3>RenameFile
|
|
<p>
|
|
<tt/char RenameFile (char *oldName, char *newName)/
|
|
<p>
|
|
I think it is obvious...
|
|
|
|
<sect3>GetFHdrInfo
|
|
<p>
|
|
<tt/char GetFHdrInfo (struct filehandle *myFile)/
|
|
<p>
|
|
This function loads the file header into the <tt/fileHeader/ buffer. Using after e.g. <tt/FindFile/
|
|
you can pass the address of <tt/dirEntryBuf/.
|
|
|
|
<sect2>Common and SEQ structure
|
|
<p>
|
|
Functions described here are common for SEQ and VLIR structures because the arguments passed are the
|
|
starting track and sector which may point either to the start of a chain for VLIR or the data for SEQ.
|
|
|
|
<sect3>GetFile
|
|
<p>
|
|
<tt/char __fastcall__ GetFile(char flag, const char *fname, const char *loadaddr, const char *datadname, const char *datafname)/
|
|
<p>
|
|
This routine loads and runs a given file <tt/fname/. The file must be one of following types:
|
|
<tt/SYSTEM, DESK_ACC, APPLICATION, APPL_DATA, PRINTER,/ or <tt/INPUT_DEVICE/. The execution
|
|
address is taken from the file header. If it is zero, then the file is only loaded. Only the first chain
|
|
from VLIR files is loaded. If <tt/flag/ has bit 0 set then the load address is taken from <tt/loadaddr/
|
|
and not from the file header. In this case <tt/APPLICATION/ files will be only loaded, not executed.
|
|
This does not apply to <tt/DESK_ACC/. If either bit 6 or 7 of <tt/flag/ are set, then 16 bytes from
|
|
<tt/datadname/ are copied to <tt/dataDiskName/ and 16 bytes from <tt/datafname/ go to <tt/dataFileName/
|
|
thus becoming parameters for the new application. Pass <tt/NULL/ for any unused parameter.
|
|
|
|
<sect3>ReadFile
|
|
<p>
|
|
<tt/char ReadFile (struct tr_se *myTrSe, char *buffer, unsigned fLength)/
|
|
<p>
|
|
This function reads at most <tt/fLength/ bytes into <tt/buffer/ from chained sectors starting at
|
|
<tt/myTrSe/.
|
|
|
|
<sect3>ReadByte
|
|
<p>
|
|
<tt/char ReadByte (void)/
|
|
<p>
|
|
This function returns the next byte from a file. Before the first call to it you must load <tt/r5/
|
|
with <tt/NULL/, <tt/r4/ with the sector buffer address and <tt/r1/ with the track and sector of the
|
|
first block of a file.
|
|
Remember to not modify <tt/r1/, <tt/r4/ and <tt/r5/. These registers must be preserved between
|
|
calls to <tt/ReadByte/.
|
|
<p>
|
|
The returned value is valid only if there was no error. The end of file is marked as <tt/BFR_OVERFLOW/
|
|
in <tt/__oserror/, this is set when trying to read one byte after the end of file, in this case the
|
|
returned value is invalid.
|
|
|
|
<sect3>SaveFile
|
|
<p>
|
|
<tt/char SaveFile (char skip, struct fileheader *myHeader)/
|
|
<p>
|
|
<tt/SaveFile/ will take care of everything needed to create a GEOS file, no matter if VLIR of SEQ
|
|
structure. All you need to do is to place the data in the proper place and prepare a header which will
|
|
contain all information about a file. The <tt/skip/ parameter says how many directory pages you
|
|
want to skip before searching for a free slot for the directory entry. In most cases you will put
|
|
<tt/0/ there.
|
|
<p>
|
|
You have to declare a <tt/struct fileheader/ and fill it with proper values. There is only one
|
|
difference - the first two bytes which are a link to a nonexistent next sector are replaced by a
|
|
pointer to the DOS filename of the file.
|
|
<p>
|
|
When saving sequential files the two most important fields in <tt/struct fileheader/ are <tt/fileheader.load_address/
|
|
and <tt/fileheader.end_address/.
|
|
|
|
<sect3>FreeFile
|
|
<p>
|
|
<tt/char FreeFile (struct tr_se myTable[])/
|
|
<p>
|
|
This function deallocates all sectors contained in the passed table.
|
|
|
|
<sect3>FollowChain
|
|
<p>
|
|
<tt/char FollowChain(struct tr_se *myTrSe, char *buffer)/
|
|
<p>
|
|
This function fills a <tt/struct tr_se/ table at <tt/buffer/ with the sector numbers for a chain of
|
|
sectors starting with <tt/myTrSe/. You can pass such data (<tt/buffer/) to e.g. <tt/FreeFile/.
|
|
|
|
<sect2>VLIR structure
|
|
<p>
|
|
Here is information about VLIR files (later called RecordFiles) and functions.
|
|
<p>
|
|
A VLIR structure file consists of up to 127 SEQ-like files called records. Each record is like one
|
|
SEQ structure file. Records are grouped together, described by a common name - the VLIR file name and
|
|
an own number. Each record pointed to by its number is described by the starting track and sector numbers.
|
|
VLIR structures allow records to be empty (<tt/tr_se/ of such record is equal to <tt/{NULL,$ff}/),
|
|
or even non-exist (<tt/{NULL,NULL}/). Any other numbers represent the starting track and sector of
|
|
a particular file.
|
|
<p>
|
|
In GEOS there can be only one file opened at a time. Upon opening a VLIR file some information
|
|
about it is copied into memory. You can retrieve the records table at <tt/fileTrScTab/ (table of
|
|
128 <tt/struct tr_se/) and from <tt/VLIRInfo/ (<tt/struct VLIR_info/.
|
|
E.g. the size of whole VLIR file can be retrieved by reading <tt/VLIRInfo.fileSize/.
|
|
|
|
<sect3>OpenRecordFile
|
|
<p>
|
|
<tt/char OpenRecordFile (char *fName)/
|
|
<p>
|
|
This function finds and opens a given file. An error is returned if the file is not found or if it is not
|
|
in VLIR format. Information in <tt/VLIRInfo/ is initialized. VLIR track and sector table is
|
|
loaded at <tt/fileTrScTab/ and will be valid until a call to <tt/CloseRecordFile/ so don't modify it.
|
|
You should call <tt/PointRecord/ before trying to do something with the file.
|
|
|
|
<sect3>CloseRecordFile
|
|
<p>
|
|
<tt/char CloseRecordFile (void)/
|
|
<p>
|
|
This function calls <tt/UpdateRecordFile/ and clears internal GEOS variables.
|
|
|
|
<sect3>UpdateRecordFile
|
|
<p>
|
|
<tt/char UpdateRecordFile (void)/
|
|
<p>
|
|
This function will check the <tt/VLIRInfo.fileWritten/ flag and if it is set, then <tt/curDirHead/ is
|
|
updated along with size and date stamps in the directory entry.
|
|
|
|
<sect3>PointRecord
|
|
<p>
|
|
<tt/char PointRecord (char recordNumber)/
|
|
<p>
|
|
This function will setup internal variables (and <tt/VLIRInfo.curRecord/) and return the track and
|
|
sector of the given record in <tt/r1/. Note that the data may not be valid (if the record is non-existing
|
|
you will get 0,0 and if it is empty - 255,0).
|
|
|
|
<sect3>NextRecord and PreviousRecord
|
|
<p>
|
|
<tt/char NextRecord (void)/
|
|
<p>
|
|
<tt/char PreviousRecord (void)/
|
|
<p>
|
|
These two work like <tt/PointRecord/. Names are self-explanatory.
|
|
|
|
<sect3>AppendRecord
|
|
<p>
|
|
<tt/char AppendRecord (void)/
|
|
<p>
|
|
This function will append an empty record (pair of 255,0) to the current VLIR track and sector
|
|
table. It will also set <tt/VLIRInfo.curRecord/ to its number.
|
|
|
|
<sect3>DeleteRecord
|
|
<p>
|
|
<tt/char DeleteRecord (void)/
|
|
<p>
|
|
This function will remove the current record from the table, and move all current+1 records one place
|
|
back (in the table). Note that there's no BAM update and you must call <tt/UpdateRecordFile/ to
|
|
commit changes.
|
|
|
|
<sect3>InsertRecord
|
|
<p>
|
|
<tt/char InsertRecord (void)/
|
|
<p>
|
|
This function will insert an empty record in place of <tt/VLIRInfo.curRecord/ and move all following
|
|
records in the table one place forward (contents of <tt/VLIRInfo.curRecord/ after a call to <tt/InsertRecord/
|
|
can be found in <tt/VLIRInfo.curRecord + 1/).
|
|
|
|
<sect3>ReadRecord and WriteRecord
|
|
<p>
|
|
<tt/char ReadRecord (char *buffer, unsigned fLength)/
|
|
<p>
|
|
<tt/char WriteRecord (char *buffer, unsigned fLength)/
|
|
<p>
|
|
This function will load or save at most <tt/fLength/ bytes from the currently pointed record into or from
|
|
<tt/buffer/.
|
|
|
|
<sect1>Memory and Strings
|
|
<p>
|
|
The functions covered in this section are common for the whole C world - copying memory parts and
|
|
strings is one of the main computer tasks. GEOS also has an interface to do this. These functions
|
|
are replacements for those like <tt/memset, memcpy, strcpy/ etc. from standard libraries.
|
|
If you are dealing with short strings (up to 255 characters) you should use these functions
|
|
instead of standard ones, e.g. <tt/CopyString/ instead of <tt/strcpy/. It will work faster.
|
|
<p>
|
|
However some of them have slightly different calling conventions (order of arguments to be specific),
|
|
so please check their syntax here before a direct replacement.
|
|
<p>
|
|
Please note that the memory areas described here as <em/strings/ are up to 255 characters (without
|
|
counting the terminating <tt/NULL/), and <em/regions/ can cover the whole 64K of memory.
|
|
|
|
<sect2>CopyString
|
|
<p>
|
|
<tt/void CopyString (char *dest, char *src)/
|
|
<p>
|
|
This function copies the string from <tt/src/ to <tt/dest/, until it reaches <tt/NULL/. The <tt/NULL/
|
|
is also copied.
|
|
|
|
<sect2>CmpString
|
|
<p>
|
|
<tt/char CmpString (char *s1, char *s2)/
|
|
<p>
|
|
This function compares the strings <tt/s1/ to <tt/s2/ for equality - this is case sensitive, and both
|
|
strings have to have the same length. It returns either <tt/true/ (non-zero) or <tt/false/ (zero).
|
|
|
|
<sect2>CopyFString and CmpFString
|
|
<p>
|
|
<tt/void CopyFString (char length, char *dest, char *src)/
|
|
<p>
|
|
<tt/char CmpFString (char length, char *s1, char *s2)/
|
|
<p>
|
|
These two are similar to <tt/CopyString/ and <tt/CmpString/ except the fact, that you provide
|
|
the length of the copied or compared strings. The strings can also contain several <tt/NULL/
|
|
characters - they are not treated as delimiters.
|
|
|
|
<sect2>CRC
|
|
<p>
|
|
<tt/unsigned CRC (char *src, unsigned length)/
|
|
<p>
|
|
This function calculates the CRC checksum for the given memory range. I don't know if it is
|
|
compatible with standard CRC routines.
|
|
|
|
<sect2>FillRam and ClearRam
|
|
<p>
|
|
<tt/void *FillRam (char *dest, char value, unsigned length)/
|
|
<p>
|
|
<tt/void *ClearRam (char *dest, unsigned length)/
|
|
<p>
|
|
Both functions are filling the given memory range. <tt/ClearRam/ fills with <tt/0s/, while
|
|
<tt/FillRam/ uses the given <tt/value/. Be warned that these functions destroy <tt/r0, r1 and
|
|
r2L/ registers. The functions are aliases for <tt/memset/ and <tt/bzero/, respectively.
|
|
|
|
<sect2>MoveData
|
|
<p>
|
|
<tt/void *MoveData (char *dest, char *src, unsigned length)/
|
|
<p>
|
|
This functions copies one memory region to another. There are checks for an overlap and the
|
|
non-destructive method is chosen. Be warned that this function destroys contents of the
|
|
<tt/r0, r1 and r2/ registers. This function is an alias for <tt/memcpy/.
|
|
|
|
<sect2>InitRam
|
|
<p>
|
|
<tt/void InitRam (char *table)/
|
|
<p>
|
|
This function allows to initialize multiple memory locations with single bytes or strings.
|
|
This is done with a <tt/table/ where everything is defined. See the structures chapter for a description of
|
|
<tt/InitRam's/ command string.
|
|
|
|
<sect2>StashRAM, FetchRAM, SwapRAM, and VerifyRAM
|
|
<p>
|
|
<tt/void StashRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/
|
|
<p>
|
|
<tt/void FetchRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/
|
|
<p>
|
|
<tt/void SwapRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/
|
|
<p>
|
|
<tt/ char VerifyRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/
|
|
<p>
|
|
These functions are the interface to a REU - Ram Expansion Unit. I think that they are self-explanatory.
|
|
You can check for REU presence by taking the value of <tt/ramExpSize/. You have to do it before
|
|
using any of these functions.
|
|
|
|
<sect1>Processes and Multitasking
|
|
<p>
|
|
Weird? Not at all. GEOS has some limited multitasking ability. You can set up a chain of functions
|
|
called in specified intervals and you can put the main program to sleep without disturbing other
|
|
tasks and making the user interface unresponsive.
|
|
|
|
<sect2>InitProcesses
|
|
<p>
|
|
<tt/void InitProcesses (char number, struct process *processTab)/
|
|
<p>
|
|
This is the main initialization routine. After calling it processes are set up, but not
|
|
enabled. The parameters for <tt/InitProcesses/ are:
|
|
<itemize>
|
|
<item><tt/number/ - number of processes
|
|
<item><tt/processTab/ - a table of <tt/struct process/, with size equal to <tt/number/
|
|
</itemize>
|
|
<p>
|
|
A single task is described by an entry in <tt/processTab/, it contains two values - a <tt/pointer/ to
|
|
the task function and a number of <tt/jiffies/ which describe the delay between calls to task. On PAL
|
|
systems there are 50 jiffies per second, while on NTSC there are 60.
|
|
<p>
|
|
The maximum number of tasks is 20. Be warned that GEOS doesn't check if parameters are valid and
|
|
if <tt/processTab/ would be too large it would overwrite existing data in GEOS space.
|
|
<p>
|
|
There's one important thing - the last entry in <tt/processTab/ has to be <tt/NULL,NULL/, so the
|
|
maximum size of <tt/processTab/ is equal to 21.
|
|
<p>
|
|
See the description of <tt/process/ structure for a more detailed discussion on this.
|
|
|
|
<sect2>RestartProcess and EnableProcess
|
|
<p>
|
|
<tt/void RestartProcess (char processNumber)/
|
|
<p>
|
|
<tt/void EnableProcess (char processNumber)/
|
|
<p>
|
|
These two functions start the task counter. <tt/RestartProcess/ should be called for each process
|
|
after <tt/InitProcesses/, because it resets all flags and counters and it starts the counters.
|
|
<p>
|
|
<tt/RestartProcess/ enables the counters and sets their initial value to that given in <tt/processTab/.
|
|
<p>
|
|
<tt/EnableProcess/ forces the given process to execute by simulating the timer expiring.
|
|
|
|
<sect2>BlockProcess and UnblockProcess
|
|
<p>
|
|
<tt/void BlockProcess (char processNumber)/
|
|
<p>
|
|
<tt/void UnblockProcess (char processNumber)/
|
|
<p>
|
|
<tt/BlockProcess/ disables the execution of the given process, but this does not disable the timers.
|
|
It means that if you call <tt/UnblockProcess/ before the timer runs out, the process will be executed.
|
|
<p>
|
|
<tt/UnblockProcess/ does the opposite.
|
|
|
|
<sect2>FreezeProcess and UnfreezeProcess
|
|
<p>
|
|
<tt/void FreezeProcess (char processNumber)/
|
|
<p>
|
|
<tt/void UnfreezeProcess (char processNumber)/
|
|
<p>
|
|
<tt/FreezeProcess/ disables timer for given process. <tt/UnfreezeProcess/ does the opposite.
|
|
This is not equal to <tt/RestartProcess/ as timers are not reloaded with initial value.
|
|
|
|
<sect2>Sleep
|
|
<p>
|
|
<tt/void Sleep (unsigned jiffies)/
|
|
<p>
|
|
This function is a multitasking sleep - the program is halted, but it doesn't block other functions
|
|
e.g. callbacks from menus and icons.
|
|
The only argument here is the number of jiffies to wait until the app will wake up. It depends on the
|
|
video mode (PAL or NTSC) how many jiffies there are per second (50 or 60, respectively).
|
|
If you don't want to worry about it and need only full second resolution, call the standard
|
|
<tt/sleep/ function from <tt/unistd.h/.
|
|
|
|
<sect1>System Functions
|
|
|
|
<sect2>FirstInit
|
|
<p>
|
|
<tt/void FirstInit (void)/
|
|
<p>
|
|
This function initializes some GEOS variables and mouse parameters. This is called on GEOS boot
|
|
up. You shouldn't use this unless you know what you are doing.
|
|
|
|
<sect2>InitForIO and DoneWithIO
|
|
<p>
|
|
<tt/void InitForIO (void)/
|
|
<p>
|
|
<tt/void DoneWithIO (void)/
|
|
<p>
|
|
These functions are called by some disk routines. You should call them only if you want to
|
|
do something with IO registers or call one of the Kernal ROM routines. Note that this is rather an
|
|
expensive way of turning off IRQs and enabling IO.
|
|
|
|
<sect2>MainLoop
|
|
<p>
|
|
<tt/void MainLoop (void)/
|
|
<p>
|
|
Returns control to the system. Any code between call to <tt/MainLoop/ and the end of current
|
|
function will never be executed. When in <tt/MainLoop/ the system waits for your action - using
|
|
icons, keyboard or menus to force some specific action from the program. You have to define
|
|
proper handlers before that.
|
|
|
|
<sect2>EnterDeskTop
|
|
<p>
|
|
<tt/void EnterDeskTop (void)/
|
|
<p>
|
|
This is an alias for <tt/exit(0)/ so you will never burn yourself. Anyway, you should not
|
|
use it. Always use <tt/exit()/ instead. Library destructors and functions registered with
|
|
<tt/atexit()/ are called.
|
|
|
|
<sect2>ToBASIC
|
|
<p>
|
|
<tt/void ToBASIC (void)/
|
|
<p>
|
|
This one is another way of terminating an application - forcing GEOS to shutdown and exit to BASIC.
|
|
I was considering whether to include it or not, but maybe someone will need it - which I doubt.
|
|
<p>
|
|
<em/WARNING:/ library destructors and functions registered with <tt/atexit()/ will not be called
|
|
so it is quite unsafe way to terminate your program.
|
|
|
|
<sect2>Panic
|
|
<p>
|
|
<tt/void Panic (void)/
|
|
<p>
|
|
This calls system's <tt/Panic/ handler - it shows a dialog box with the message
|
|
<tscreen><verb>
|
|
System error at:xxxx
|
|
</verb></tscreen>
|
|
where <tt/xxxx/ is last known execution address (caller). By default this is bound to the <tt/BRK/
|
|
instruction, but it might be usable in debugging as kind of <tt/assert/. (Note that <tt/assert/
|
|
is available as a separate function and will give you more information than that).
|
|
<p>
|
|
The system is halted after a call to <tt/Panic/ which means that library destructors will not be
|
|
called and some data may be lost (no wonder you're panicking).
|
|
|
|
<sect2>CallRoutine
|
|
<p>
|
|
<tt/void CallRoutine (void *myFunct)/
|
|
<p>
|
|
This is a system caller routine. You need to provide a pointer to a function and it will be immediately
|
|
called, unless the pointer is equal to <tt/NULL/. This is the main functionality of this function -
|
|
you don't need to check if the pointer is valid.
|
|
|
|
<sect2>GetSerialNumber
|
|
<p>
|
|
<tt/unsigned GetSerialNumber (void)/
|
|
<p>
|
|
This function returns the serial number of the system. It might be used for copy-protection.
|
|
However, please remember that Free Software is a true power and you are using it right now.
|
|
|
|
<sect2>GetRandom
|
|
<p>
|
|
<tt/char GetRandom (void)/
|
|
<p>
|
|
This function returns a random number. It can be also read from <tt/random/ e.g.
|
|
<tscreen><verb>
|
|
a=random;
|
|
</verb></tscreen>
|
|
but by calling this function you are sure that the results will be always different.
|
|
<tt/random/ is updated once a frame (50Hz PAL) and on every call to <tt/GetRandom/.
|
|
<p>
|
|
Note that this is not the same as the <tt/rand/ function from the standard library. <tt/GetRandom/
|
|
will give you unpredictable results (if IRQs occur between calls to it) while
|
|
<tt/rand/ conforms to the standard and for a given seed (<tt/srand/) always returns with the
|
|
same sequence of values.
|
|
|
|
<sect2>SetDevice
|
|
<p>
|
|
<tt/void SetDevice (char device)/
|
|
<p>
|
|
This function sets the current device to the given. It might be used together with <tt/InitForIO/,
|
|
<tt/DoneWithIO/ and some Kernal routines. Unless the new device is a disk drive this only sets
|
|
new value in <tt/curDevice/, in the other case new disk driver is loaded from REU or internal RAM.
|
|
|
|
<sect2>get_ostype
|
|
<p>
|
|
<tt/char get_ostype (void)/
|
|
<p>
|
|
This function returns the GEOS Kernal version combined (by logical OR) with the machine type. Read
|
|
<tt/gsys.h/ for definitions of the returned values.
|
|
|
|
<sect2>get_tv
|
|
<p>
|
|
<tt/char get_tv (void)/
|
|
<p>
|
|
This function returns the PAL/NTSC flag combined (by logical OR) with the 40/80 columns flag. This is
|
|
not the best way to check if the screen has 40 or 80 columns since a PAL/NTSC check is always
|
|
performed and it can take as long as a full raster frame. If you just want to know if the
|
|
screen has 40 or 80 columns use the expression <tt/graphMode & 0x80/ which returns <tt/0/ for
|
|
40 columns and <tt/0x80/ for 80 columns. Remember that this value can be changed during
|
|
runtime. It is unclear if this will work for GEOS 64 so you probably do not want to test
|
|
anything if not running under GEOS128. Use <tt/get_ostype/ to check it. Read <tt/gsys.h/ for
|
|
definitions of the returned values.
|
|
|
|
<sect>Library Structures
|
|
<p>
|
|
To simplify usage and optimize passing parameters to functions I have declared several structures
|
|
which describe the most common objects. Some of these structures are bound to static addresses in
|
|
the GEOS data space (<tt/$8000-$8fff/), so you can use their fields directly in an optimized way.
|
|
Please see <tt/gsym.h/ to find them. All structures are defined in <tt/gstruct.h/ and you may
|
|
find also some comments there.
|
|
|
|
<sect1>Graphics Structures
|
|
|
|
<sect2>pixel
|
|
<p>
|
|
A simple structure describing a point on the screen.
|
|
|
|
<sect2>fontdesc
|
|
<p>
|
|
This structure describes a font in one pointsize. There is the current font - <tt/struct fontdesc/
|
|
bound to <tt/curFontDesc/. You can also force GEOS to use your own fonts by calling
|
|
<tt/LoadCharSet/. You just need to open a VLIR font file and load one record - one pointsize -
|
|
somewhere. At the start of this area you already have all data for <tt/fontdesc/ so you can
|
|
pass a pointer to the load address of that pointsize to <tt/LoadCharSet/. (Note that although
|
|
it has 'Load' in the name, that function loads only GEOS internal data structures, not data
|
|
from disk).
|
|
|
|
<sect2>window
|
|
<p>
|
|
This widely used structure holds the description of a region of the screen. It describes the top-left and
|
|
bottom-right corners of a window.
|
|
|
|
<sect2>iconpic
|
|
<p>
|
|
Maybe the name isn't the best - it has nothing with <tt/DoIcons/ but with bitmap functions -
|
|
<tt/BitmapUp/ for example. This structure holds the parameters needed to properly decode and show
|
|
a bitmap on the screen. The bitmap has to be encoded - if you have some non-GEOS bitmaps simply
|
|
convert them to Photo Scraps - this is the format used by all GEOS bitmap functions - <tt/DoIcons/
|
|
too.
|
|
|
|
<sect1>Icons
|
|
<p>
|
|
These structures describe click boxes (icons) that can be placed on screen or in a dialog box.
|
|
|
|
<sect2>icondef
|
|
<p>
|
|
This is the definition of a single click box. Please see <tt/gstruct.h/ for a description of its fields.
|
|
|
|
<sect2>icontab
|
|
<p>
|
|
This is the toplevel description of icons to be placed and enabled on the screen. This structure
|
|
has the following fields:
|
|
<itemize>
|
|
<item><tt/char number/ - total number of icons declared here
|
|
<item><tt/struct pixel mousepos/ - after finishing <tt/DoIcons/ the mouse pointer will be placed in
|
|
this point allowing you to have a hint for the user what the default action is
|
|
<item><tt/struct icondef tab[&rsqb/ - this table of size equal to <tt/icontab.number/ contains
|
|
descriptions for all icons
|
|
</itemize>
|
|
|
|
<sect1>File and Disk
|
|
|
|
<sect2>tr_se
|
|
<p>
|
|
This simple structure holds the track and sector number of something. Do not expect the track to be
|
|
in range 1-35, as GEOS can support many various and weird devices. For example my C128 256K
|
|
expansion is utilized as RAMDisk with a layout of 4 tracks of 128 sectors each. However assuming that
|
|
a track number equal to 0 is illegal might be wise.
|
|
|
|
<sect2>f_date
|
|
<p>
|
|
This is a placeholder for a file datestamp. This structure is also present in <tt/struct filehandle/.
|
|
GEOS is not Y2K compliant, so if the current file has in <tt/filehandle.date.year/ a value less than 86
|
|
you can safely assume that it is e.g. 2004 and not 1904.
|
|
|
|
<sect2>filehandle
|
|
<p>
|
|
This is the main file descriptor. It is either an entry in the directory (returned from file functions)
|
|
or its copy in <tt/dirEntryBuf/. This is optimized so you can safely get to the file's year e.g.
|
|
by testing <tt/dirEntryBuf.date.year/ - it will be compiled to simple <tt/LDA, STA/.
|
|
|
|
<sect2>fileheader
|
|
<p>
|
|
This structure holds the fileheader description. You can load a file's header into the <tt/fileHeader/
|
|
fixed area using <tt/GetFHdrInfo/. (note that <tt/fileHeader/ is a place in memory while
|
|
<tt/fileheader/ is a structure).
|
|
You will also need your own fileheader for <tt/SaveFile/.
|
|
|
|
<sect1>System Structures
|
|
|
|
<sect2>s_date
|
|
<p>
|
|
This structure is defined only for <tt/system_date/. It is slightly different from <tt/f_date/
|
|
so I prepared this one. You can e.g. get or set the current time using <tt/system_date.s_hour/ and
|
|
<tt/system_date.s_minute/. Accesses to these will be optimized to simple <tt/LDA/ and <tt/STA/
|
|
pair.
|
|
|
|
<sect2>process
|
|
<p>
|
|
You should declare a table of that type to prepare data for <tt/InitProcesses/. The maximum number
|
|
of processes is 20, and the last entry has to be equal to <tt/{NULL,NULL}/, so this table may hold
|
|
only 21 entries. The first member of this structure (<tt/pointer/) holds the pointer to the called
|
|
function (void returning void), you will probably have to cast that pointer into <tt/unsigned int/.
|
|
The second field <tt/jiffies/ holds the amount of time between calls to that function.
|
|
On PAL systems there are 50 jiffies per second, while NTSC have 60 of them.
|
|
|
|
<sect1>A few things in detail...
|
|
<p>
|
|
GEOSLib uses cc65 non-ANSI extensions to easily initialize data in memory. This is done with a
|
|
kind of array of unspecified length and unspecified type. Here is how it works:
|
|
<tscreen><verb>
|
|
void example = {
|
|
(char)3, (unsigned)3, (char)0 };
|
|
</verb></tscreen>
|
|
Which will be compiled to following string of bytes:
|
|
<tscreen><verb>
|
|
_example:
|
|
.byte 3
|
|
.word 3
|
|
.byte 0
|
|
</verb></tscreen>
|
|
As you see this way it is possible to define data of any type in any order. You must remember to
|
|
cast each member to proper type.
|
|
|
|
<sect2>DoMenu structure
|
|
<p>
|
|
<tt/DoMenu/ is responsible for everything concerned with menu processing. Many, many GEOS programs
|
|
are just initializing the screen and menu and returning to <tt/MainLoop/. In GEOSLib it is the same as
|
|
returning from <tt/main/ function without using <tt/exit(0)/.
|
|
<p>
|
|
A menu is described by two types of data - menu descriptors and menu items. A descriptor contains
|
|
information about the following menu items, and items contain names of entries and either
|
|
pointers to functions to execute or, in case of nested menus, pointers to submenu descriptors.
|
|
Note that submenu descriptor can be top-level descriptor, there's no difference in structure,
|
|
just in the content.
|
|
<p>
|
|
Here is how a single descriptor looks like:
|
|
<tscreen><verb>
|
|
void myMenu = {
|
|
(char)top, (char)bottom, // this is the size of the menubox
|
|
(unsigned)left, (unsigned)right, // counting all items in the current descriptor
|
|
(char)number_of_items | type_of_menu, // number of following items ORed with
|
|
// type of this menu, it can be either
|
|
// HORIZONTAL or VERTICAL if you will have also bit 6 set then menu won't be closed
|
|
// after moving mouse pointer outside the menubox. You can have at most 31 items.
|
|
</verb></tscreen>
|
|
This is followed by <tt/number_of_items/ of following item description.
|
|
<tscreen><verb>
|
|
...
|
|
"menuitemname", (char)item_type, (unsigned)pointer,
|
|
"nextitemname", (char)item_type, (unsigned)pointer,
|
|
...
|
|
"lastitemname", (char)item_type, (unsigned)pointer };
|
|
// Note that there isn't ending <tt/NULL/ or something like that.
|
|
</verb></tscreen>
|
|
<tt/pointer/ is a pointer to something, what it points for depends from <tt/item_type/. This one
|
|
can have following values:
|
|
<p>
|
|
<tt/MENU_ACTION/ - a function pointed by <tt/pointer/ will be called after clicking on the menu item
|
|
<p>
|
|
<tt/SUB_MENU/ - <tt/pointer/ points to next menu descriptor - a submenu
|
|
<p>
|
|
Both of them can be ORed with <tt/DYN_SUB_MENU/ and then the <tt/pointer/ points to a function
|
|
which will return in <tt/r0/ the needed pointer (to function to execute or a submenu).
|
|
<p>
|
|
For creating nested menus (you can have at most 8 levels of submenus) you need to declare such
|
|
a structure for each submenu and top level menu.
|
|
|
|
<sect2>DoDlgBox command string
|
|
<p>
|
|
<tt/DoDlgBox/ is together with <tt/DoMenu/ one of the most powerful routines in GEOS. It is
|
|
responsible for creating dialog boxes, that is windows which task is to interact with the user.
|
|
The format of the command string is following:
|
|
<tscreen><verb>
|
|
(window size and position)
|
|
(commands and parameters)
|
|
NULL
|
|
</verb></tscreen>
|
|
There is a custom type defined for the command string: <tt/dlgBoxStr/.
|
|
|
|
<sect3>Size and position
|
|
<p>
|
|
The first element can be specified in two ways - by using the default size and position or specifying
|
|
your own. The first case results in
|
|
<tscreen><verb>
|
|
const dlgBoxStr example = {
|
|
DB_DEFPOS (pattern_of_shadow),
|
|
... // commands
|
|
DB_END };
|
|
</verb></tscreen>
|
|
And the own size and position would be:
|
|
<tscreen><verb>
|
|
const dlgBoxStr example = {
|
|
DB_SETPOS (pattern, top, bottom, left, right)
|
|
... // commands
|
|
DB_END };
|
|
</verb></tscreen>
|
|
|
|
<sect3>Commands
|
|
<p>
|
|
The next element of the <tt/DoDlgBox/ command string are the commands themselves. The first six commands are
|
|
default icons and the number of the selected icon will be returned from window processor. The icons are
|
|
<tt/OK, CANCEL, YES, NO, OPEN/, and <tt/DISK/. You can use predefined macros for using them, e.g.:
|
|
<tscreen><verb>
|
|
...
|
|
DB_ICON(OK, DBI_X_0, DBI_Y_0),
|
|
...
|
|
</verb></tscreen>
|
|
Note that the position is counted from top left corner of window, not entire screen and that the 'x'
|
|
position is counted in cards (8-pixel) and not in pixels. This is also true for all following commands.
|
|
<tt/DBI_X_0/ and <tt/DBI_Y_0/ are predefined (see <tt/gdlgbox.h/ for more), the default positions
|
|
which will cause icons to appear on a default window exactly where you would expect them.
|
|
<p>
|
|
<tt/DB_TXTSTR (x, y, text)/ will cause to show the given text in the window.
|
|
<p>
|
|
<tt/DB_VARSTR (x, y, ptr)/ works as above, but here you are passing a pointer to a zero page location
|
|
where the address of the text is stored. This is useful for information windows where only the text content
|
|
is variable. Consider following:
|
|
<tscreen><verb>
|
|
char text = "foo";
|
|
...
|
|
r15=(unsigned)text; // in code just before call to DoDlgBox
|
|
...
|
|
DB_VARSTR (TXT_LN_X, TXT_LN_1_Y, &r15),
|
|
...
|
|
</verb></tscreen>
|
|
will cause the word ''foo'' to appear in the window, but you may store the pointer to any text in
|
|
<tt/r15/ (in this case) before the call to DoDlgBox.
|
|
<p>
|
|
<tt/DB_GETSTR(x, y, ptr, length)/ - will add a input-from-keyboard feature. <tt/ptr/ works as in the
|
|
previous example and points to the location where the text is to be stored. Note that the contents of this
|
|
location will be shown upon creating the window. <tt/length/ is the maximum number of characters to input.
|
|
<p>
|
|
<tt/DB_SYSOPV(ptr)/ - this sets <tt/otherPressVec/ to the given pointer. It is called on every keypress.
|
|
<p>
|
|
<tt/DB_GRPHSTR(ptr)/ - the data for this command is a pointer for <tt/GraphicsString/ commands.
|
|
<p>
|
|
<tt/DB_GETFILES(x, y)/ - for a standard window you should pass 4 for both x and y. This function
|
|
draws a file selection box and searches the current drive for files. Before the call to <tt/DoDlgBox/ you
|
|
must load <tt/r7L/ with the GEOS filetype of searched files and <tt/r10/ with the class text. In <tt/r5/
|
|
you have to load a pointer to a <tt/char[17]/ where the selected filename will be copied. It works
|
|
like <tt/FindFTypes/ but is limited to first 16 files.
|
|
<p>
|
|
<tt/DB_OPVEC(ptr)/ - this sets a new pointer for the button press function, if you pass
|
|
<tt/RstrFrmDialogue/ here you will cause the window to close after pressing mouse button.
|
|
<p>
|
|
<tt/DB_USRICON(x, y, ptr)/ - places a single user icon (click box) on the window, <tt/ptr/ points at a
|
|
<tt/struct icondef/ but fields <tt/x/ and <tt/y/ are not used here. You can have at most 8 click
|
|
boxes in a window, this is an internal limit of the GEOS Kernal.
|
|
<p>
|
|
<tt/DB_USRROUT(ptr)/ - this command causes to immediately call the user routine pointed by <tt/ptr/.
|
|
|
|
<sect2>GraphicsString command string
|
|
<p>
|
|
<tt/GraphicsString/ is a very powerful routine to initialize the whole screen at once. There are
|
|
predefined macros for all commands, names are self-explanatory, see them in <tt/ggraph.h/. The last
|
|
command has to be <tt/GSTR_END/. There is a custom type defined for the command string: <tt/graphicStr/.
|
|
<p>
|
|
Here is an example for clearing the screen:
|
|
<tscreen><verb>
|
|
const graphicStr example = {
|
|
MOVEPENTO(0,0),
|
|
NEWPATTERN(0),
|
|
RECTANGLETO(319,199)
|
|
GSTR_END };
|
|
</verb></tscreen>
|
|
|
|
<sect2>InitRam table
|
|
<p>
|
|
This type of data is used to initialize one or more bytes in different locations at once. The format is
|
|
the following:
|
|
<tscreen><verb>
|
|
void example = {
|
|
(unsigned)address_to_store_values_at,
|
|
(char)number_of_bytes_that_follow,
|
|
(char)data,(char)data (...)
|
|
// more such definitions
|
|
(unsigned)NULL // address of 0 ends the table
|
|
};
|
|
</verb></tscreen>
|
|
|
|
<sect2>Intercepting system vectors
|
|
<p>
|
|
It is possible to intercept events and hook into the GEOS Kernal using vectors. Here is a little example:
|
|
<tscreen><verb>
|
|
void_func oldVector;
|
|
|
|
void NewVectorHandler(void) {
|
|
// do something and at the end call the old vector routine
|
|
oldVector();
|
|
}
|
|
|
|
void hook_into_system(void) {
|
|
oldVector = mouseVector;
|
|
mouseVector = NewVectorHandler;
|
|
}
|
|
|
|
void remove_hook(void) {
|
|
mouseVector = oldVector;
|
|
}
|
|
</verb></tscreen>
|
|
<p>
|
|
In your <tt/main/ function you should call <tt/hook_into_system()/ but <em/after/ all calls to the GEOS
|
|
Kernal (like <tt/DoMenu/, <tt/DoIcons/, etc.) - right before passing control to the <tt/MainLoop()/.
|
|
Be warned that vectors are most likely to be changed by the GEOS Kernal also via other functions (like
|
|
<tt/GotoFirstMenu/, <tt/DoDlgBox/ and its derivatives etc.). It depends on what Kernal functions
|
|
you use and which vectors you altered. Unfortunately there is no exact list for GEOS 2.0, a complete
|
|
list for GEOS 1.x can be found in A. Boyce's Programmers' Reference Guide mentioned before. Most of the
|
|
information contained there should be still valid for GEOS 2.0. When calling a function that restores
|
|
the vector you should add a <tt/hook_into_system()/ call right after it.
|
|
<p>
|
|
It is critical to restore old vector values before exiting the program. If you have more than one
|
|
place where you call <tt/exit()/ then it might be worth to register <tt/remove_hook/ function to
|
|
be called upon exiting with <tt/atexit(&remove_hook);/ call. This way you will ensure that
|
|
such destructor will be always called.
|
|
<p>
|
|
That little example above intercepts <tt/mouseVector/. The <tt/NewVectorHandler/ function will be
|
|
called every time the mouse button changes status. Other important vectors you should know about
|
|
are:
|
|
<itemize>
|
|
<item><tt/appMain/ - this is called from within the <tt/MainLoop/ system loop
|
|
<item><tt/keyVector/ - called whenever a keypress occurs
|
|
<item><tt/intTopVector/ - called at the start of the IRQ routine
|
|
<item><tt/intBotVector/ - called at the end of the IRQ routine
|
|
</itemize>
|
|
|
|
</article>
|