Our Little GEM Mark Wherry takes the first step on a guided tour of the unknown... One thing that all Atari programmers will eventually have to face is GEM. The Graphics Environment Manager provides support for four modules, the AES, the VDI, the BIOS and GEMDOS. In these articles we will be focusing upon the AES and the VDI. The Application Environment Services handles windows, icons, resource files, dialogues, alert boxes, file selectors, menus and graphical based inputs (eg. moving a window). When we talk about AES replacements, the above are the operations that are rewritten. If you're interested in how the AES is written, why not take a look at the source code for XaAES or oAESis. The VDI (Virtual Device Interface) provides a set of graphics functions that are independent of physical hardware and enable you to create a virtual workstation, in which you can define and output graphics to a device. The popular utility NVDI (New Virtual Device Interface) replaces the original VDI with faster, superior code that is a dramatic improvement. If you are an NVDI user (and if not why not?!), you don't have to worry about compatibility because, the way NVDI is accessed by GEM is exactly the same as the real VDI. For these articles, I'm going to use the high-level language 'C'; for many reasons. I like 'C' (!), it's popular and ideally suited to the task. In my opinion GEM programming is more difficult in something like GFA Basic! However, Pascal or Modula-2 programmers shouldn't have too much difficulty in adapting the listings. The first thing we must do at the start of our program is to initialise the AES and the VDI. Remember also, to include the relevant header files, eg. and . For the AES, simply include the statement: ap_id=appl_init(); where ap_id is an integer that will contain an identifier given to your application by the AES. To initialise the VDI is slightly more complicated. We start by using the graf_handle function, which returns an id number for the screen which is being used by the AES. This is known as the physical handle: vhandle=graf_handle(&char_height,&char_width,&cell_height,&cell_width); The shorts char_height and char_width return the height and width of each character, while cell_width and cell_height return the size of the rectangular box it occupies. Usually this information isn't needed, so we can call the function like this: vhandle=graf_handle(&junk,&junk,&junk,&junk); As you know, most GEM programs work happily in any resolution, but, this is only because of a special function, called v_opnvwk (open virtual screen workstation). This automatically finds out the size of the screen and how many colours can be displayed on it. v_opnvwk uses arrays of integers which are usually called work_in, and work_out, and should be defined at the start of your program as: int work_in[11]={1,1,1,1,1,1,1,1,1,1,1,2}; int work_out[57]; We will look at what these numbers mean later on, but if you're desperate, try looking in your compiler's manual. But finally, we call v_opnvwk like this: v_opnvwk(work_in,&vhandle,work_out); Now that wasn't so bad, was it? Well, now for something really clever, let's define a window. For this, the following identifiers will need to be defined as follows: int whandle; int wx,wy,ww,wh; short gx,gy,gw,gh; char *title; First of all, we need to create a new window in the AES, this will not appear on screen just yet though. To do this we use the wind_create function, which returns a handle. This handle has nothing to do with the physical (VDI) handle (or even a GEMDOS handle). The returned window handle uniquely identifies our window from any other currently managed by the AES: whandle=wind_create(PROPERTIES,wx,wy,ww,wh); PROPERTIES can include any of the following: NAME, title bar with title. CLOSE, a close box. FULL, a full box. MOVE, the window can be moved. INFO, an information line below the title bar. SIZE, a sizer box. UPARROW, an up arrow. DNARROW, a down arrow. VSLIDE, a vertical slider. LFARROW, a left arrow. RTARROW, a right arrow. HSLIDE, a horizontal slider. So, for example, to define a moveable window with a titlebar and closer, you would do this: whandle=wind_create(NAME|CLOSE|MOVE,wx,wy,ww,wh); If you haven't already guessed, the integers wx,wy,ww and wh define the x and y coordinates, and the width and height of the window. It's good practice to do this as oppose to using values directly, as you will only get tangled up later! Before we finally open the window we must first set the title for our window, and this is achieved by the wind_set command: wind_set(whandle,WF_NAME,ADDR(title),0,0); WF_NAME is the request sent to the wind_set function. There are many other requests you can send to wind_set to set other window parameters which we will cover later. The title address character pointer must be split into the high and low words. Don't worry about this though, you can simply use the ADDR macro as shown. After all this, we can finally open the window like this: wind_open(whandle,wx,wy,ww,wh); .....and that's all there is to it! And that's how to put a window on the screen. There is however one thing that might surprise you when you run this program, and that's what we'll look at next time, see you then. A complete listing is on the reader disk (hopefully), if you run into any problems.