Version 3 Technical Highlights - Input.Char

Published ByDateVersionKnowledge LevelKeywords
Sprezzatura Ltd01 OCT 19923.0+EXPERTINPUT.CHAR, MOUSE, VIDEO.RW, BORDER.UP, INRECT

The central system routine for keyboard input has been modified to be "mouse aware". It now returns additional codes permitting the user to know where the mouse was when a button was clicked, and what status line button has been pressed. Thus there are now five functions of Input.Char, 1 - to handle background processing/@Priority.Int etc. 2 - To return a pressed key. 3 - To provide the mouse position when a button is clicked. 4 - To identify the status line cell that has been clicked on. 5 - To permit clicking on the top screen line to display the menu. As 1 and 2 have not changed they will not be dealt with here.

Input.Char now accepts a second additional parameter MousePosFlag. If this is set to true, then if a mouse button is clicked (regardless of which mouse button) a string of length four characters will be returned in the first parameter having the format Char(0) : Char(0) : Char(X) : Char(Y) where X and Y are the ascii values representing the X and Y position of the mouse respectively. Thus if the cursor was at 65, 10, the string returned would be Char(0) : Char(0) : Char(65) : Char(10).

To display custom "mouseable" buttons on the status line requires a knowledge of status record structures. All status line images are stored in the SYSTEXT table with a row key of Name*Status where Name is the name of the status line image and Status is the literal "Status", e.g. WINDOW*STATUS. In release 3.0 this record has five fields, each field being a dynamic array having a structure as follows

<1>Normally the name of the status line (Name above), although can be different if required.
<2>The information to display in each cell, value mark delimited.
<3>Format information for the dynamic section of cell 3.
<4>Reserved for compiled status line image.
<5>Array of start positions and lengths for active "mouseable" areas of the status line. This is a multivalue for each "mouseable" section of the status line. Each multivalue has two subvalues. The first being the start position of the area (note the relative position not the absolute position, thus the first character is 1 not 0), and the second being the length. Thus to define a hot spot with 1 at the first character of the status line, a hot spot width 10 in the middle of the status line, and a hot spot width one at the far right of the status line, field 5 would contain 1ü1ý35ü10ý80ü1
  • Note that it is the job of the programmer to ensure that hot areas correspond to screen literals.

As many "hot areas" can be defined as are required by the application.

When a "hot area" is clicked on, Input.Char returns a string indicating which numbered hot area has been selected. This has a similar structure to the X/Y information but is only three bytes long, in this case Char(0) : Char(0) : Char(X) where X is the position in the "hot area" array. It is then the job of the programmer to act upon this information.

Note that due to the way in which this has been implemented (hot areas are not associated with code and commands, rather they just tell the calling program which area has been chosen) it is not possible to alter functionality of existing status lines. Hot area locations and legends may be changed, but choosing hot area 4 in a window will always display "Options " regardless of the legend/position. For reference there are 6 hot areas defined for the Window status line, as follows

1Browse previous
2Browse
3Browse next
4Options
5Softkeys
6Save

The following code shows the use of INPUT.CHAR in its modified form along with INRECT to provide a "Radio Button" window which takes as input a field mark delimited set of button names and displays a small window allowing the user to mouse to each button to toggle the button status, or tab and use the space bar to toggle status. Note that in the real world this would be rewritten using VSpace but space considerations preclude that here. Whilst it would be possible to achieve a similar result using hooks in the window processor this is shown as 3GL code merely to illustrate the use of the new routines and return values.

  Function Radio_Window(ButtonLabels)
  /*
    Author      AMcA, CC
    Date        Sept 92
    Purpose     To display a field mark delimited set of prompts with a
                corresponding radio button for each prompt. These may be
                toggled using mouse and/or tab/spacebar and will return a
                dynamic array of results when <Save> is moused, or an empty
                array if Esc or the close button are pressed.
  */
    Declare Function Min, Max, Esc.To.Attr, InRect
    Declare Subroutine Msg,Video.RW,Border.Up,Input.Char,Delay
    $Insert SysInclude, Logical
    Equ Escape$  to \1B\
    Equ Tab$     to \09\
    Equ BackTab$ to \000F\
    GoSub SetUp
    GoSub DisplayScreen
    GoSub ProcessMouse
  Return ResultArray

  SetUp:
    Colour4 = \1B\:'C1O'
    Colour1 = Esc.To.Attr(Colour4)
    ButtonCtr = Count(ButtonLabels, @Fm) + (ButtonLabels#"")
    ResultArray = str(0:@fm,ButtonCtr)
    ResultArray[-1,1] = ''
    Rectangles = ''
    MaxWidth = 6 ; Pos = 0 ; Mark = 0 ; Screen = ""
    Ptr = 2 ; Depth = ButtonCtr * 2
    Ypos = Int((@CrtHigh-(Depth+3))/2)
    ScreenTop = Ypos - 2
    OldYpos = Ypos
    Loop
     Remove NextLabel From ButtonLabels At Pos Setting Mark
     MaxWidth = Max(MaxWidth, Len(NextLabel))
     Screen := @(2, Ypos) : NextLabel
     Ypos += 2
    While Mark
    Repeat
    For X = 1 To ButtonCtr
     Screen := @(4 + MaxWidth, OldYpos) : "[ ]"
     ThisBox = Char(5 + MaxWidth) : Char(OldYpos)
     Rectangles := ThisBox:ThisBox
     OldYpos += 2
    Next
    BottomLine = '<Save>'
    Screen := @(2, Ypos) : BottomLine
    Rectangles := Char(3):Char(Ypos):Char(6):Char(Ypos)
    Rectangles :=Char(3):Char(ScreenTop):Char(3):Char(ScreenTop)
    OldYpos += 2
  Return

  DisplayScreen:
    Video.RW(1,ScreenTop,7+MaxWidth,OldYpos,'R', Image)
    Video.RW(1,ScreenTop,7+MaxWidth,OldYpos,'C',' ':Colour1)
    Border.Up(1,Screentop,7+MaxWidth,OldYpos,1,Colour4)
    Print @(2,ScreenTop):'[':@fm:']'
    Print Colour4:Screen
    CurrentButton = 1
    Print @(5 + MaxWidth, ScreenTop +2):
  Return

  ProcessMouse:
    ExitSet = False$
    Loop Until ExitSet
     Input.Char(Chr,True$)
     Begin Case
       Case Len(Chr) = 4
       * A Mouse Button was pressed - a slight delay is in order here !
          Delay(0.25)
          MouseX = Seq(Chr[3,1])
          MouseY = Seq(Chr[4,1])
          * Now see if the mouse press was somewhere we need to act on
          Rectangle = InRect(MouseX, MouseY, Rectangles, '')
  Begin Case
           Case Rectangle = ButtonCtr + 2
              * Border "Cancel" icon.
              ExitSet = True$
              Resultarray = ''
           Case Rectangle = ButtonCtr + 1
              * <Save> icon.
              ExitSet = True$
           Case Rectangle > 0
              If ResultArray<Rectangle> Then
                 ResultArray<Rectangle> = 0 ; Choice = ' '
              End Else
                 ResultArray<Rectangle> = 1 ; Choice = @fm
              End
              Print @(5+MaxWidth,ScreenTop+(Rectangle*2)):Choice
              Print @(5+MaxWidth,ScreenTop+(CurrentButton*2)):
          End Case
       Case Chr = Tab$
          CurrentButton += 1
          If CurrentButton > ButtonCtr then CurrentButton = 1
          Print @(5 + MaxWidth, ScreenTop + (CurrentButton*2)):
       Case Chr = BackTab$
          CurrentButton -= 1
          If CurrentButton < 1 then CurrentButton = ButtonCtr
          Print @(5 + MaxWidth, ScreenTop + (CurrentButton*2)):
       Case Chr = ' '
          If ResultArray<CurrentButton> then
           Choice = ' ' ; ResultArray<CurrentButton> = 0
          End Else
           Choice = @fm ; ResultArray<CurrentButton> = 1
          End
          Print @(5+MaxWidth,ScreenTop+(CurrentButton*2)):Choice
          Print @(5 + MaxWidth, ScreenTop + (CurrentButton*2)):
       Case Chr = Escape$
          ExitSet = True$ ; ResultArray = ''
     End Case
    Repeat
    Video.RW(1,ScreenTop,7+MaxWidth,OldYpos,'W',Image)
  Return

(Volume 4, Issue 5, Pages 7-10)

  • tips/revmedia/v4i5a3.txt
  • Last modified: 2024/06/19 20:20
  • by 127.0.0.1