Skip to main content
© Atomic Flash

 "Today is the first day of the rest of your life."

                GEM PROGRAMMING - AN IDIOTS GUIDE
            For the Assembler programmer (and others)
                   by Ciaran 'Ringpull' Wills

                             Part 3

 The  last  two parts of this tutorial where quite heavy  on  the
theory but now that the fundamentals have been covered it's  time
to start playing around and seeing just what can actually be done
with  GEM.  This instalment of the tutorial will examine a  small
program  which  utilises pull-down menus as well as  the  already
covered topics of dialogue boxes and alert boxes.
 First  of  all  I would like introduce the program  we  will  be
studying.  It is dedicated to Michael,  Amy and June,  who  spent
most  of  an afternoon trying to place 8 queens on  a  chessboard
without any of the queens threatening each other. I was trying to
think of an interesting example program for this tutorial at  the
time (No boring address books, thank you) so I decided that a GEM
based  solution  for  the 8 queens problem would  do  the  trick.
Anyone who has used the LISP or Prolog languages will surely have
come  across this problem as an example program  before.  Have  a
play around with the program and then load up the source code and
we'll start looking at how it uses GEM.
 First  of all you'll notice a large number of equates.  This  is
mainly due to having the object IDs for all of the 64 squares  on
the chessboard. There are five object trees used and the first is
the pull-down menu.
 As  menus are a new topic I will pause here to explain how  they
are  created  and  used.  Creating menus without  the  aid  of  a
resource construction kit is certainly not a good idea so I  will
not touch on that.  Using a menu is essentially very simple:  You
display the menu at the top of the screen using the menu_bar  AES
call and then make an evnt_mesag call. The evnt_mesag call is one
of  the family of evnt_ calls which wait for a type of  event  to
happen, hence the name.  evnt_mesag waits for a menu selection or
a window operation,  but since we arn't using any windows it only
reports menu selections.
 Back  to  the  program.  The start of the  code  itself  is  the
ubiquitous  GEM header which as always sets up our own stack  and
releases all the unused memory to the operating system.  Then  we
branch  to the initialisation routine which loads and  sorts  out
the resource file.
 The  initialisation  routine starts by executing  the  appl_init
call  which should be made by all GEM programs before  any  other
AES  calls.  Notice  that I have placed the address  of  the  AES
parameter  block (aespb) in register a0.  This means  that  every
time  we  want  to refer to the aespb we can use  a0  instead  of
wasting 4 bytes by giving the full address again.
 Next we load the resource file using the rsc_load call. The only
data  required by this call is a pointer to a  string  containing
the filename. If the call fails then the first word of the intout
array  will  be zero.  Since the resource file contains  all  the
object  descriptions we need there is no point in carrying on  if
the file is not loaded,  so if the call fails we inform the  user
through  an  alert  box and quit.  We must remember  to  make  an
appl_exit call before we quit and the quit routine does this.
 Once the resource file is loaded successfully we execute a  loop
which  find  the addresses in memory of the newly  loaded  object
trees.  This is done using the rsc_gaddr call and since the trees
are  numbered  from zero we can use a  simple  counter.  All  the
addresses  are stored in variables starting at menuaddr  (as  the
menu is the first tree).
 Now  the  menu  bar is placed at the top of the  screen  by  the
menu_bar call.  All this call requires is the address of the menu
tree in the addrin array.
 The  initialisation routine now sets the initial  conditions  of
the options dialogue box,  zeroing the first byte of the editable
text string in the options box. This is necessary due to a bug in
GEM  which  places  the  cursor at the  right-hand  side  of  the
editable  text  field so the user has to clear the  field  before
entering  anything.   Zeroing the first byte of the  text  string
fixes this.
 Since  two of the dialogue boxes have a counter which shows  the
number  of  solutions found it is convenient  to  redirect  these
objects  so  they  both point to a string  which  can  be  easily
manipulated rather than us having to delve into the resource data
every  time  we  want to change the value  in  the  counter.  The
address of our counter is placed at the 12th byte of the object's
description.  Since these objects are just simple strings  rather
than editable or other text objects,  the address in the object's
description points to the string rather than a ted_info block.
 Finally  we change the mouse into an arrow with  the  graf_mouse
call.  This  is necessary as the desktop turns the mouse  into  a
'busy bee' when a program is run.
 Now that the initialisation routine is through, we fall into the
main  loop of the program.  This waits for the user to  select  a
menu  option  and  then acts on it.  This  is  done  through  the
evnt_mesag call. This call waits for either a window operation or
a  menu selection.  Since we don't have any windows open it  only
returns menu selections. The evnt_mesag call requires the address
of  a  16  byte buffer to be used for returning  details  of  the
event.  The first word of the buffer indicates the type of  event
which occurred.  The only one that concerns us at the moment is a
menu  selection which is type 10.  The fourth word of the  buffer
will contain the ID of the menu item selected.
 Handling   the   About...    and   Quit   options   is    fairly
straightforward.  The solve routine is the one that displays  the
dialogue  box  which lets the user view the solutions  one  at  a
time.
 Before  continuing I will briefly explain how the  two  routines
(start  and  nextpos) which produce the actual solutions  to  the
problem  work.  The start routine resets the  routine's  internal
variables  and finds the first solution.  Each time  the  nextpos
routine is called it returns the next solution until there are no
more solutions,  in which case it returns a non-zero in  register
d0.  Both  the routines return the solution in the 8  word  array
curpos.  Each  word  of the array indicates the position  of  the
queen  in that row (There must be one and only one queen on  each
row).  Also,  none of the numbers will be the same, as that would
mean two queens on the same column.
 The solve routine starts by finding the first solution.  It then
calls  the plotgrid routine which sets the selected flags of  the
objects  in the dialogue box so that it shows where the 8  queens
are positioned. If we look at the plotgrid routine we can se that
it  is  a  loop,  executed 8 times,  which finds the  ID  of  the
corresponding  square on the grid from the look-up  table  called
grid. The object ID is multiplied by 24 to get the offset for the
descriptor for this object.  The value of d1 (1) is placed in the
address generated when this offset, the tree address and 10 bytes
offset  for  the  object status field  are  added  together.  The
cleargrid  routine works in the same way and even uses  the  same
code but it clears the squares which where selected earlier.
 Next  stop is the counter routine which takes the current  value
of  the  counter  (count,  which is incremented  by  the  nextpos
routine) and creates a 4 byte ASCII string (terminated in a zero)
which is returned in d0.  This string is then placed at countstr,
to which the string pointers in the object trees where redirected
to earlier. Next the form_center and form_dial calls required for
displaying  a dialogue box are made.  We now enter a  loop  which
displays the dialogue box,  executes a form_do call,  clears  the
grid  again,   finds  the  next  solution,   calls  plotgrid   in
preparation for displaying the next solution, updates the counter
string and then loops back to display the box.  Provision is made
to leave the loop either when the user selects the 'Done'  button
or when all the solutions have been found.  When this happens the
dialogue box is tidied and the menu returned to normal.   Control
is  then returned back to the main loop to wit for  another  menu
selection.
 The solve all routine also finds all the solutions but this time
they  are sent to an output device (printer or file) rather  than
the screen.  The routines open, output and close take care of the
output  and  their names explain what they do.  Open  and  output
return  a  negative  value in d0 in the case  of  an  error.  The
dialogue  box is handled as before except that there is  no  need
for a form_do call as the box requires no user interaction.  This
time the routine is stopped by running out of solutions or by  an
output  error,  not by the user.  It ends by closing  the  output
channel  (close),  removing the dialogue box from the screen  and
returning the menu bar to normal.
 The final piece of GEM programming which we will look at in this
program  is the handling of the options dialogue  box.  This  box
contains  two pairs of radio buttons and an editable text  string
as  well  as the OK and Cancel buttons.  The  radio  buttons  are
contained in boxes so that GEM knows which buttons are  connected
to each other.  I have left the boxes visible but you may  render
them invisible by giving their outlines a width of zero.
 The  dialogue box is handled in the usual way but when the  user
is  finished it must do one of two things.  If the OK button  was
clicked  then  the  routine must look at the new  status  of  the
buttons  in  the  box and set  the  programs  internal  variables
according  to  their  new state,  or if  the  cancel  button  was
clicked,  it must return the buttons in the box to their previous
state.
 The  internal variables are two words at printeropt and  a  text
string containing the filename.  The first word is the status  of
the  status of the file button and the second word is the  status
of  the  serial  button.  From these to values  the  program  can
workout  what  form  of output is  required.  This  routine  also
requires the copying of strings to get the filename. This is done
by  simply moveing the string a byte at a time until a zero  byte
is  encountered,  indicating the end of the string.  The  routine
ends  as  usual  by returning the menu bar  to  normal  with  the
menu_tnormal call and returning to the main loop.
 And that concludes our look at this program. Feel free to change
the  program  in any way you please and perhaps try  making  some
pull-down  menus of your own.  Since the menu items  are  objects
like  any  other objects they can be changed by  you  program  in
almost  any way you choose.  It is often desirable to change  the
text  of a menu entry or to set the checked (bit 2 of the  status
word) or disabled (bit 3 of the status word) to place a tick next
to an item or to have it 'grayed out'.  You can also try changing
other attributes such as colours.
 Next time we will take a first look at GEM windows, which are an
important part of all but the smallest GEM applications.  See you
then!

 Please  check out the FEATURES.ZIP archive for a  folder  called
"GEM" which will contain some sample code. 

Disclaimer
The text of the articles is identical to the originals like they appeared in old ST NEWS issues. Please take into consideration that the author(s) was (were) a lot younger and less responsible back then. So bad jokes, bad English, youthful arrogance, insults, bravura, over-crediting and tastelessness should be taken with at least a grain of salt. Any contact and/or payment information, as well as deadlines/release dates of any kind should be regarded as outdated. Due to the fact that these pages are not actually contained in an Atari executable here, references to scroll texts, featured demo screens and hidden articles may also be irrelevant.