PreviousKeyboard Configuration Utility (Keybcf) ScreensNext"

Chapter 8: Mouse Support for Character Interfaces

DOS, Windows and OS/2:
On DOS, Windows and OS/2, in many instances, you can enhance a PC application's interface by detecting the presence of a mouse and then allowing its optional use. COBOL provides both high and low level routines for accessing the mouse. It is now possible to write sophisticated new applications that exploit all of the mouse features. You can also quickly change existing applications to use the mouse if one is present.

UNIX :
Mouse support is not available on UNIX.

The section Adding Mouse Support to Existing Applications presents information on how to incorporate mouse support into an existing application quickly. The section Using Call-by-name Mouse Routines describes how to use all of the mouse features.

8.1 Adding Mouse Support to Existing Applications

Many existing character PC COBOL applications use Adis, the enhanced screen and keyboard management functions of COBOL. If your program contains a Screen Section, uses the ACCEPT/DISPLAY verb extensions that control positioning or highlighting, or calls the x"AF" routine, you are using Adis. See the chapter Adis for information on Adis.

You can enhance such applications by using the mouse to:

With these mouse routines, your application's user interface behaves as in the past without a mouse. However, if a mouse is present, many operations can be simplified or shortened.

You can add each of these functions to an existing application by including a small amount of code. You access the Adis mouse routines by calling the x"AF" routine with specific function codes. These function codes enable you to:

You cannot mix these x"AF" call by number routines with the newer call by name routines in the same application.

A sample program, admouse.cbl , illustrates these routines and techniques. This program is provided in your cobol\demo directory.

8.1.1 Initializing and Terminating the Mouse

Before accessing any of the other mouse functions, you must initialize the mouse. The initialization call tells Adis to load the mouse driver and draw the mouse pointer. When the application has finished with the mouse, it must be terminated. Termination cancels the mouse driver and deletes the mouse pointer.

The following section of code shows how to initialize or terminate the mouse:

 01  use-mouse-function     pic x comp-x value h"40". 
 01  terminate-mouse        pic x comp-x value h"00". 
 01  activate-mouse         pic x comp-x value h"01". 
    ...
     call x"AF" using use-mouse-function
                      activate-mouse

or:

     call x"AF" using use-mouse-function
                      terminate-mouse

where:

h"nn" is a hexadecimal constant, a Micro Focus extension for representing hexadecimal binary values for numeric fields.
h"40" is equivalent to a one-byte comp field with a value of decimal 64.

For more information on named constants, see your Language Reference.

Adis returns a value of 255 in use-mouse-function if the mouse cannot be initialized.

8.1.2 Showing and Hiding the Mouse

You might not want to display the mouse pointer on every screen or menu in your application, so these two functions enable you to show and hide the mouse when appropriate. A good guideline is to show the mouse pointer if the mouse can actually be used to do something at that point.

The following section of code shows you how to enable or disable the mouse:

01  enable-mouse-function  pic x comp-x value h"42". 
01  show-mouse             pic x comp-x value h"01". 
01  hide-mouse             pic x comp-x value h"00". 
    ...
     call x"AF" using enable-mouse-function
                      show-mouse

or:

     call x"AF" using enable-mouse-function
                      hide-mouse

8.1.3 Using the Mouse

Once the mouse pointer is displayed, the user can use it to point at fields on the screen. In its default setting, if the user presses the first button (usually the left button), the cursor is positioned at the start of the field pointed to by the mouse. If the mouse pointer is not over a valid input field, Adis sounds a warning beep. When the mouse pointer is hidden, button presses are ignored.

8.1.4 Creating Point-and-pick Menus

Using the mouse to select items from a menu requires the program to detect that the mouse button was pressed and determine the mouse pointer's location on the screen at that time. Adis looks for button 1 on the mouse; any other button presses are ignored. Button presses are interpreted by Adis as Adis key 27.

By default, Adis keys other than Enter (Adis key 0) do not terminate an ACCEPT statement. You can change this by using the following code:

The following section of code shows how to enable the mouse to terminate an ACCEPT statement:

 01  set-bit-pairs         pic x comp-x value h"01". 
 01  mouse-can-terminate-accept
                           pic x(4) comp-x value h"01321b01".
 01  mouse-cannot-terminate-accept
                           pic x(4) comp-x value h"02321b01". 
     ...
     call x"AF" using set-bit-pairs
                      mouse-can-terminate-accept

or:

    call x"AF" using set-bit-pairs
                     mouse-cannot-terminate-accept

Enabling the mouse button to terminate the ACCEPT statement gives the user a second Enter key. This behavior is not always appropriate in your application's dialog.

To determine that it was the mouse that terminated the ACCEPT statement, you must examine the CRT-STATUS data item referenced in the Special-Names paragraph. The CRT-STATUS data item is defined as:

 01  key-pressed.
     05  key-type        pic x. 
     05  key1            pic x comp-x. 
     05  keyx            redefines key1 pic x. 
     05  key2            pic x comp-x.

If the ACCEPT statement is terminated by the Enter key, the key-type data item has a value of 0. If the mouse terminates the ACCEPT statement, key-type has a value of 2 and key1 has a value of 27.

Example

Example code to interpret the key-type:

     display screen 
     accept screen 
     evaluate key-type also key1 
       when "0" also any 
*         <code to process enter key> 
       when "2" also 27 
*         <code to process mouse button> 
       when "1" also 1 
*         <code to process function key 1> 
            ...
     end-evaluate

If you have determined that the mouse button was pressed, you can query the position of the mouse pointer with another call:

 01  get-mouse-details      pic x comp-x value h"43". 
 01  mouse-details. 
     05  mouse-x            pic 9(4) comp-x. 
     05  mouse-y            pic 9(4) comp-x. 
     05  mouse-status       pic 9(4) comp-x. 
      ...
     call x"AF" using get-mouse-details
                      mouse-details

The mouse coordinates assume the upper left corner of the screen is (0,0). How you translate these coordinates into a menu selection depends on the orientation (horizontal or vertical), the relative position of the menu on screen, and the length of each menu item. The mouse-status field indicates which mouse button was pressed when the last mouse button press occurred.

8.2 Using Call-by-name Mouse Routines

The section Adding Mouse Support to Existing Applications described how you can quickly modify existing applications that contain Adis ACCEPT and DISPLAY statements to use the mouse if one is present. This support enables you to:

However, this support does not enable you to use all of the mouse features. A set of call-by-name mouse routines are available that enable you to access all of the mouse features.

You cannot mix these call by name routines with the older x"AF" call by number routines in the same application.

You cannot use these call-by-name routines where you are using the Micro Focus extensions to the ACCEPT verb. However, they do provide access to several mouse features not possible with the high level routines. These include:

In this section, we look at these new routines and the techniques for using them.

A sample program, rtsmouse.cbl , illustrates these routines and techniques and is provided in your cobol\demo directory. You might want to compile the program and run it with the discussion that follows.

8.2.1 Detecting the Presence of the Mouse and Mouse Buttons

As with the Adis mouse functions, initialization and termination calls are required.

The following section of code shows how initialization and termination calls are carried out:

 01  mouse-handle        pic x(4) comp-x. 
 01  mouse-buttons       pic x(2) comp-x. 
           ...
     call "CBL_INIT_MOUSE" using mouse-handle
                                 mouse-buttons

or:

     call "CBL_TERM_MOUSE" using mouse-handle

The mouse initialization call sets the COBOL special register RETURN-CODE to zero if a mouse is present, and returns both a mouse handle and the number of buttons on the mouse. The mouse handle is a required first parameter of all the other mouse routines. A nonzero value in RETURN-CODE indicates that no mouse was found and that the mouse handle is invalid. Passing an invalid handle to a mouse routine can cause your machine to lock up in some environments.

8.2.2 Controlling the Mouse

The following sections describe the aspects of the mouse's behavior you can control using the CBL_ routines.

8.2.2.1 Enabling and Disabling Use of the Mouse

As a general rule, you want to display the mouse pointer if the user can do something with the mouse on the current screen, for example, click on a button or menu item.

Routines are available both to show and hide the mouse:

     call "CBL_SHOW_MOUSE" using mouse-handle

or:

     call "CBL_HIDE_MOUSE" using mouse-handle

The routine CBL_HIDE_MOUSE is available only when running a full screen session. The routine behaves unpredictably when running a Windowed session.

8.2.2.2 Making the Mouse Pointer Visible or Invisible

You also can make the mouse pointer visible on the portion of the screen where it can be used, but invisible everywhere else.

The following section of code shows how to specify a rectangular area where the mouse is invisible:

 01  hidden-area. 
     05  top-row         pic x(2) comp-x. 
     05  left-col        pic x(2) comp-x. 
     05  bottom-row      pic x(2) comp-x. 
     05  right-col       pic x(2) comp-x. 
        ...
     call "PC_SET_MOUSE_HIDE_AREA" using mouse-handle
                                         hidden-area

8.2.2.3 Mouse Pointer Position

The CBL_SET_MOUSE_POSITION routine enables you to move the mouse pointer to any location on the screen.

The following section of code shows how you would move the mouse to a specific location on the screen:

 01  mouse-position. 
    05  mouse-row       pic x(2) comp-x. 
    05  mouse-col       pic x(2) comp-x. 
       ...
    call "CBL_SET_MOUSE_POSITION" using mouse-handle 
                                        mouse-position

The CBL_GET_MOUSE_POSITION routine enables you to return the location of the mouse pointer.

Unlike the Adis mouse functions, you do not have to wait until a button is pressed to get the mouse pointer's position.

The following section of code shows how to return the mouse's current position:

 01  mouse-position. 
    05  mouse-row       pic x(2) comp-x. 
    05  mouse-col       pic x(2) comp-x. 
       ...
    call "CBL_GET_MOUSE_POSITION" using mouse-handle 
                                        mouse-position

For both routines, the mouse coordinates assume the upper left corner of the screen is (0,0).

8.2.3 The Mouse Event Queue

A mouse event is generated any time the user moves the mouse pointer, or presses or releases a mouse button. Mouse events are asynchronous; that is, they can occur independently and when other actions are being performed. For instance, the user can move the mouse pointer while the program is in the middle of a file update. So that an application does not miss any potentially important mouse events, these events are stored in a queue until you retrieve them. Reading an event from the queue removes it from the queue.

8.2.3.1 Querying the Mouse Event Queue

8.2.3.1.1 Querying the Status of the Mouse Event Queue

The following section of code shows how you can determine how many events are waiting in the mouse event queue:

 01  queued-events       pic x(2) comp-x. 
     ...
     call "CBL_GET_MOUSE_STATUS" using mouse-handle 
                                       queued-events
8.2.3.1.2 Reading a Mouse Event

You can read from the queue in two ways:

Method
Description
Read With Wait Returns the next event from the queue if there is one. If there are no events in the event queue, the application is suspended until a mouse event occurs, and that event is returned.
Read With No Wait Returns the next event from the queue if one is there. If there are no events in the event queue, all zeros are returned in event-data.

The following section of code shows how mouse events are retrieved from the queue:

 01  read-nowait            pic x comp-x value h"00". 
 01  read-wait              pic x comp-x value h"01". 
 01  event-data. 
     05  event-type         pic x(2) comp-x. 
     05  event-time         pic x(4) comp-x. 
     05  event-row          pic x(2) comp-x. 
     05  event-col          pic x(2) comp-x. 

     call "CBL_READ_MOUSE_EVENT" using mouse-handle 
                                       event-data 
                                       read-nowait

or:

     call "CBL_READ_MOUSE_EVENT" using mouse-handle 
                                       event-data 
                                       read-wait 

where:

event-row is the row that the mouse pointer was on when the event started. Remember that the first row is row 0.
event-col is the column that the mouse pointer was on when the event started. Remember that the first column is column 0.
event-time is the elapsed time from some arbitrary but fixed starting time. The event time is useful when you need to know the elapsed time between two mouse events. For instance, you might want to support both single and double clicking on the mouse buttons. If the event time is zero, there was no event (which implies that the Read No-Wait method was used).
event-type contains the type of action that took place.

A different bit is set in this field for each event type. The bit combination identifies which events have occurred. The following table identifies the event actions and their corresponding bit positions. Button 1 is usually the left button on the mouse, and button 2 the right one.

Bit Value Event Action
15-4 16-255 Reserved.
3 8+ Button 3 pressed.
2 4 Button 2 pressed.
1 2 Button 1 pressed.
0 1 Mouse moved.


Since multiple events can occur at one time, you must test for individual bits in event-type. See the section Testing the Value of a Bit for information on how to do this.

8.2.3.2 Testing the Value of a Bit

The following section of code shows how you can use one of the bit manipulation routines provided with COBOL to test a single bit in a byte:

 78  mouse-moved                value 1. 
 78  button1-pressed            value 2. 
 78  button2-pressed            value 4. 
 78  button3-pressed            value 8. 
 01  event-data. 
     05  event-type             pic x(2) comp-x. 
     05  event-time             pic x(4) comp-x. 
     05  event-row              pic x(2) comp-x. 
     05  event-co               pic x(2) comp-x. 
 01  result                     pic x(2) comp-x. 
 01  button1-status             pic x(8). 
         ... 
     call "CBL_READ_MOUSE_EVENT" using mouse-handle 
                                       event-data 
                                       read-nowait
     move button1-pressed to result
     call "CBL_AND" using event-type
                          result by value 2 
     if result = button1-pressed 
         ...

The CBL_AND routine sets result to zero unless the bit tested for (in this case button1-pressed) is set in event-type.

8.2.3.3 Testing for a Mouse Click

After a call to CBL_READ_MOUSE_EVENT, a value of zero in event-type indicates that one or more mouse buttons were released.

To support clicking (the conventional method of indicating a choice with the mouse button, involving pressing the button and then releasing it) you need to save the previous state of each button. The click is not complete until the button is released.

The next section of code shows how to check for pressing and releasing the mouse button:

        ... 
    if result = button1-pressed 
         move "pressed" to button1-status 
     else 
         if button1-status = "pressed" 
             move "released" to button1-status 
         else 
             move space      to button1-status 
         end-if 
     end-if 
        ... 

Since the mouse pointer could have moved after the button was pressed, you should test the mouse pointer position after the click is complete. The following section of code shows how you could do this.

        ... 
     if button1-status = "released" 
         evaluate  event-row also event-col 
           when 24 also 10 thru 14 
               ... 
           when 24 also 18 thru 22 
               ... 
        end-evaluate 
     end-if 
    ... 

8.2.3.4 The Mouse Event Mask

The event mask enables you to specify what kinds of events are queued. This mask has the same bit settings as event-type returned from a call to CBL_READ_MOUSE_EVENT. Setting a bit in the event mask to 0 results in occurrences of the specified event not being stored in the event queue. By default, all events are stored in the event queue.

Setting the Event Mask

The following section of code shows how you could set or examine the event mask:

 01  event-mask       pic x(2) comp-x. 
        ... 
     call "CBL_SET_MOUSE_MASK" using mouse-handle 
                                     event-mask 

or:

     call "CBL_GET_MOUSE_MASK" using mouse-handle 
                                     event-mask

The routine CBL_SET_MOUSE_MASK is available only when running a full screen session. The routine behaves unpredictably when running a Windowed session.

Setting the Value of a Bit

When setting bits in the event mask, you will probably want to change the value of one bit without affecting the other bit settings. The ability to do this is shown in the following code:

 01 source            pic x(2) comp-x. 
       ... 
     move button1-pressed to source 
     call "CBL_OR" using source
                         event-mask by value 2

8.2.4 Changing the Mouse Pointer's Characteristics

The mouse pointer is generated on the screen by performing a couple of low-level bit operations on the character and attribute on the screen with a special mouse pointer mask. This process ensures that the mouse pointer is visible whatever the foreground and background colors happen to be. You can control both the foreground and background colors used, and the character displayed at the mouse pointer position, by manipulating this mask with the following code. The following section of code shows how to control the character displayed at the mouse pointer position:

 01  mouse-ptr-shape. 
     05  char-and-mask   pic x    comp-x. 
     05  attr-and-mask   pic x    comp-x. 
     05  char-xor-mask   pic x    comp-x. 
     05  attr-xor-mask   pic x    comp-x. 
 01  reserved            pic x(10). 
         ... 
     call "PC_SET_MOUSE_SHAPE"   using mouse-handle 
                                       reserved 
                                       mouse-ptr-shape

or:

     call "PC_GET_MOUSE_SHAPE" using mouse-handle 
                                    reserved
                                     mouse-ptr-shape.

8.2.5 References

For more information on mouse calls, see the chapter Low-level Routines for Character Interfaces.


Copyright © 1999 MERANT International Limited. All rights reserved.
This document and the proprietary marks and names used herein are protected by international law.

PreviousKeyboard Configuration Utility (Keybcf) ScreensNext"