Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

VMS Cobol - how can you determine current Cursor Line

SOLVED
Go to solution
davidbn123
Occasional Advisor

VMS Cobol - how can you determine current Cursor Line

Wondering if any one knows if you can determine the terminal line number you were on when you enter the Run command from DCL.

$ RUN TEST_PROG

I know the calls to GETDVI to obtain the actual device details about how many lines the device has but I can't find what to call to get the current line number. Just to add, I'm not a whizz with SMG. If anyone knows a simple call (or sequence of calls) that will give me this then that would be perfect. However, I do not want to end up controlling all the screen input/output by SMG. I see there is the SMG$CURSOR system service but seems like I then need to first call SMG$CREATE_VIRTUAL_DISPLAY. I'm not sure what all these virtual displays and pasteboards etc really are but I take it that this call is actually going to create some sort of window. I don't want that - I just want the line number and then I can stick to simple COBOL DISPLAY and ACCEPT statements and specify the line numbers.

Grateful for any assistance.

7 REPLIES
Hoff
Honored Contributor
Solution

Re: VMS Cobol - how can you determine current Cursor Line

SMG is not applicable here, save possibly as a dictionary for control sequences.  SMG manages the screen — sending and receiving control sequences — and you're not looking for that here.  You're looking to query the terminal.

COBOL is also not applicable here, save as a way to make this effort that much harder, given the added glue code needed around calling system services from that language.

You'll need to query the terminal directly.   In short, you'll send a sequence such as a DSR directly, and receive back the cursor position (CPR).   ESC [ 6 n gets you ESC [ Pl ; Pc R.   This involves opening an I/O channel to the terminal, and processing the sequences, likely via what's known as an extended read. 

There are some DCL examples here, and some doc pointers here (including using SMG to retrieve control sequences), and links to C examples of $qio extended read calls here, and some COBOL system service calls here and here

Hein van den Heuvel
Honored Contributor

Re: VMS Cobol - how can you determine current Cursor Line

It is not entirely clear to me what you are trying to accomplish. Just knowing the current line seems futile. WHY should the program care??

To twist an overused idiom: It is where it is. Just keep on reading/printing from that position without trying to position explicity.

If you need specific position, then just take full control and to heck with this notion of trying to accomodate where it is.

I can see how one might want to know the screen size, and those anre attributes you can get from GETDVI as you indicate. It can readily be called from Cobol as LIB$GETDVI, and more efficiently but more work (assign channel) as SYS$GETDVI..

FInally, you can ask the terminal where the cursos is with a reporting escape sequence (below). That's fine with a low level function like sys$qiow or lib$output, but to send it from Cobol is desctructive best I recall. Just asking changes the position with new-lines. And 'with no advancing' causes activating the extended terminal io which changes the cursor (again, best I recall).

Anyway, hope this helps some,

Hein

http://www.cse.psu.edu/~kxc104/class/cmpen472/11f/hw/hw7/vt100ansi.htm

Query Cursor Position	<ESC>[6n
  • Requests a Report Cursor Position response from the device.

 

Report Cursor Position	<ESC>[{ROW};{COLUMN}R
  • Generated by the device in response to a Query Cursor Position request; reports current cursor position.

 

 

abrsvc
Respected Contributor

Re: VMS Cobol - how can you determine current Cursor Line

e you may be able to determine the "current" position.  Unless you know how you got there, the info may not be what you expect.  Once a terminal has reached the "bottom" line, it will scroll.  That means that any call to request the cursur position will indicate line 24 (for example) and remain at that number.  While the horizontal position may change, the verticle one likely won't.

If you really need to know where the cursur is, I suspect you will also need to tell the system where to place data on the screen as well.  This really means that you need to keep track of all output both line and character position.

As mentioned earlier, there are easier ways to do this.  For example FMS is probably easier as the "terminal" can be defined as a form where you fill in certain fields directly without having to know the screen positioning at all from the program.

In order to properly address your inquiry, you need to supply more information about the environment of the program as well as what you are trying to accomplish.  I suspect that you are asking the wrong question.  Describe things a bit more and maybe we can determine the question you are really asking.

 

Dan

davidbn123
Occasional Advisor

Re: VMS Cobol - how can you determine current Cursor Line

Thanks all so far. I think you all have a better knowledge though of these Escape sequences. I have read your replies and also the system documentation but I just don't understand where these Terminal reports go to. I also haven't succeeded in generating one. Are they going to some DCL symbol that I need to translate.

The basic problem I am trying to solve is this (it relates to a query I posted quite some time ago). I have a cobol program that is an interactive program. I want it to run in two modes. Mode one is in screen mode where I display a full screen (that part is fine, I display from line 1 down to end of screen). The other mode is line mode. A similar example of the line mode is when you go into a standard VMS utility like SQL. You type in SQL and then what happens is that the prompt SQL> is displayed on the next line and you enter your commands. The problem in Alpha and Integrity is that when you have an ACCEPT statement with a PROTECTED clause (needed for the screen mode, and actually I want it anyway for the line mode) is that when you do not specify the line number the cursor position jumps back to the top of the screen. I can't allow that. At the moment, since I can't solve this problem neatly what I am having to do is erase the screen display and start displaying from line 1. It's just about acceptable but does not look great.

 

Hein van den Heuvel
Honored Contributor

Re: VMS Cobol - how can you determine current Cursor Line

Those cursor positioning response come back to the caller who has to post a read to get the bytes.

A complication is that depending on terminal setting the escape sequence itself is a terminator, and not data.

In that case you need a special (QIO) read to look into the terminator

And if the whole sequence is NOT a terminator, but perhaps the escape is, then the data is sort of lingering until a 'newline' is pushed, or a timeout is reached or the program again use a special, but different QIO to read a character at a time, or the read-ahead buffer. 

So you are caught between a rock and a hard-place. best advice is to PUNT!

That jump to the top-left of the screen is Cobol doing the initiallization when the first, any, extend ACCEPT or DISPLAY functions is seen such as the 'PROTECTED'

So either live with that and blindly position to line '99' or stop using anay advanced read/write. Just sstick to plain ACCEPT and DISPLAY and all will be well.

Hope this helps some,

Hein

 

 

davidbn123
Occasional Advisor

Re: VMS Cobol - how can you determine current Cursor Line

Thanks very much everyone - I will keep this open a little longer and see if any more ideas come back.

JRBrady
Occasional Advisor

Re: VMS Cobol - how can you determine current Cursor Line

Hello, thanks to the excellent OpenVMS system services it's very easy to query a VT-class terminal and determine the cursor position (among other things) from COBOL, or any other supported language.

The secret is to assign SYS$INPUT and SYS$OUTPUT to I/O channels and use SYS$QIOW to send and receive the terminal escape sequences, then deassign the channels when finished. With the proper settings, TTDRIVER does all the work of capturing the terminal's response escape sequence for easy reference.

Here's an example screen shot and the quick-and-dirty COBOL program that works all the magic. Enjoy!

CURPOS_SNIPPET.jpg

       Identification Division.
       Program-ID. CURPOS.
       Author. Jason Brady.

       Environment Division.
       Configuration Section.
       Source-Computer. AXP.
       Object-Computer. AXP.

       Data Division.
       Working-Storage Section.

       01  General-Variables.
           03 Input-Channel-Name               Pic X(9).
           03 Output-Channel-Name              Pic X(10).
           03 Input-Channel-Num                Pic 9(9)  Comp.
           03 Output-Channel-Num               Pic 9(9)  Comp.
           03 Status-Code                      Pic S9(9) Comp.
           03 Longword-Display                 Pic S9(9) Display
              Sign Leading Separate.

       01  QIO-Variables.
           03 QIO-Buffer                       Pic X(16).
           03 QIO-MBX                          Pic S9(9) Comp.
           03 QIO-Chars                        Pic S9(9) Comp.
           03 QIO-Channel                      Pic 9(9)  Comp.
           03 QIO-Func                         Pic S9(9) Comp.
           03 QIO-Timeout                      Pic S9(9) Comp.
           03 QIO-Terminator-Mask              Pic X(16) Value
              X'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'.

       01  QIO-Terminator-Block.
           03 Termin-Size                      Pic S9(4) Comp.
           03 Filler                           Pic S9(4) Comp.
           03 Pointer Value Reference QIO-Terminator-Mask.

       01  IO-Status-Block.
           03 IOSB-Receive.
              05 IOSB-Recv-Status              Pic S9(4) Comp.
              05 IOSB-Recv-Offset              Pic S9(4) Comp.
              05 IOSB-Recv-Term                Pic S9(4) Comp.
              05 IOSB-Recv-Term-Size           Pic S9(4) Comp.
           03 IOSB-Write Redefines IOSB-Receive.
              05 IOSB-Write-Status             Pic S9(4) Comp.
              05 IOSB-Write-Count              Pic S9(4) Comp.
              05 IOSB-Write-Resv               Pic S9(9) Comp.

       01  Switches-And-Indicators.
           03 Call-Failure-Switch              Pic X.
              88 Call-Failure      Value 'Y'.

       01  Constants-And-Literals.
           03 Clear-Screen-Code.
              05 Filler                        Pic X Value X'1B'.
              05 Filler                        Pic X(3) Value '[2J'.
           03 Home-Cursor-Code.
              05 Filler                        Pic X Value X'1B'.
              05 Filler                        Pic X(5) Value '[1;1H'.
           03 Set-Cursor-Position-Code.
              05 Filler                        Pic X Value X'1B'.
              05 Filler                        Pic X(7) Value '[12;13H'.
           03 Req-Cursor-Position-Code.
              05 Filler                        Pic X Value X'1B'.
              05 Filler                        Pic X(3) Value '[6n'.
           03 Return-Key-Code                  Pic X Value X'0D'.
           03 Linefeed-Key-Code                Pic X Value X'0A'.

       01  System-Constants.
           03 SS$_NORMAL                       Pic S9(9) Comp Value
              External SS$_NORMAL.
           03 IO$_READVBLK                     Pic S9(9) Comp Value
              External IO$_READVBLK.
           03 IO$_WRITEVBLK                    Pic S9(9) Comp Value
              External IO$_WRITEVBLK.
           03 IO$M_NOECHO                      Pic S9(9) Comp Value
              External IO$M_NOECHO.
           03 IO$M_NOFILTR                     Pic S9(9) Comp Value
              External IO$M_NOFILTR.
           03 IO$M_NOFORMAT                    Pic S9(9) Comp Value
              External IO$M_NOFORMAT.
           03 IO$M_ESCAPE                      Pic S9(9) Comp Value
              External IO$M_ESCAPE.
           03 IO$M_TIMED                       Pic S9(9) Comp Value
              External IO$M_TIMED.

      ******************************************************************
      * Main Routine                                                   *
      ******************************************************************
       Procedure Division.

       Main-Routine.

           Perform Initialization-Tasks

           Display Clear-Screen-Code Home-Cursor-Code

           Display 'CURPOS.COB - Obtain Cursor Row and Column'
           Display '  We move cursor to row 12, column 13 then'
           Display '  ask the terminal for the location.'
           Display Set-Cursor-Position-Code 'X' With No Advancing

           Perform Assign-IO-Channels
           Perform Request-Cursor-Position
           Perform Receive-Cursor-Position

           Display ' <== Cursor row ' QIO-Buffer(3:2) ' column ' 
                   QIO-Buffer(6:2)
           Display ''

           Perform Deassign-IO-Channels
           Perform Exit-Program
           .

       Exit-Program.

           If Call-Failure-Switch = 'Y'
              Display 'Program error occurred'
           End-If

           Stop Run
           .

      ******************************************************************
      * Initialization                                                 *
      ******************************************************************
       Initialization-Tasks.

           Initialize General-Variables
                      QIO-Variables
                      IO-Status-Block
                      Switches-And-Indicators
           .

      ******************************************************************
      * Assign I/O Channels                                            *
      ******************************************************************
       Assign-IO-Channels.

           Move 'SYS$INPUT'  To Input-Channel-Name
           Move 'SYS$OUTPUT' To Output-Channel-Name

           Call 'SYS$ASSIGN' Using By Descriptor Input-Channel-Name
                                   By Reference Input-Channel-Num
                                   Omitted
                                   Omitted
                                   Omitted
                            Giving Status-Code

           If Status-Code Is Not Equal To SS$_NORMAL
              Display 'Error: Unable to assign input I/O channel'
               Set Call-Failure To True
              Perform Exit-Program
           End-If

           Call 'SYS$ASSIGN' Using By Descriptor Output-Channel-Name
                                   By Reference Output-Channel-Num
                                   Omitted
                                   Omitted
                                   Omitted
                            Giving Status-Code

           If Status-Code Is Not Equal To SS$_NORMAL
              Display 'Error: Unable to assign output I/O channel'
              Set Call-Failure To True
              Perform Exit-Program
           End-If
           .

      ******************************************************************
      * Deassign I/O Channels                                          *
      ******************************************************************
       Deassign-IO-Channels.

           Call 'SYS$DASSGN' Using By Reference Input-Channel-Num
                            Giving Status-Code
           Call 'SYS$DASSGN' Using By Reference Output-Channel-Num
                            Giving Status-Code
           .

      ******************************************************************
      * Request Cursor Position                                        *
      * Output buffer contents to the I/O channel assigned to          *
      * SYS$OUTPUT.                                                    *
      ******************************************************************
       Request-Cursor-Position.

           Move Output-Channel-Num to QIO-Channel
           Compute QIO-Func = IO$_WRITEVBLK + IO$M_NOFORMAT
           Move Req-Cursor-Position-Code to QIO-Buffer
           Move Function Length (Req-Cursor-Position-Code) to QIO-Chars

           Call 'SYS$QIOW' Using Omitted
                                 By Value QIO-Channel
                                 By Value QIO-Func
                                 By Reference IO-Status-Block
                                 Omitted
                                 Omitted
                                 By Reference QIO-Buffer
                                 By Value QIO-Chars
                                 Omitted
                                 Omitted
                                 Omitted
                                 Omitted
                          Giving Status-Code

           If Status-Code Is Not Equal To SS$_NORMAL
              Display 'Error: Write call to SYS$QIOW failed (status).'
              Call 'LIB$STOP' Using By Value Status-Code
              Set Call-Failure to True
              Perform Exit-Program 
           End-If
           .

      ******************************************************************
      * Receive Cursor Position                                        *
      * Inputs a character or ESC sequence from the I/O channel        *
      * assigned to SYS$INPUT. It relies on TTDRIVER to treat all      *
      * characters as a terminator using a terminator mask with the    *
      * exception of ESC sequences, which it parses and stores in the  *
      * input buffer. No trapping is done for OpenVMS reserved control *
      * keys Ctrl-C,Q,S,T,Y. These will return an error.               *
      ******************************************************************
       Receive-Cursor-Position.

           Move Input-Channel-Num to QIO-Channel
           Compute QIO-Func = IO$_READVBLK + IO$M_NOECHO +
                              IO$M_NOFILTR + IO$M_ESCAPE
           Move Spaces To QIO-Buffer
           Move Function Length (QIO-Buffer) To QIO-Chars
           Move Function Length (QIO-Terminator-Mask) to Termin-Size

           Call 'SYS$QIOW' Using Omitted
                                 By Value QIO-Channel
                                 By Value QIO-Func
                                 By Reference IO-Status-Block
                                 Omitted
                                 Omitted
                                 By Reference QIO-Buffer
                                 By Value QIO-Chars
                                 Omitted
                                 By Reference QIO-Terminator-Block
                                 Omitted
                                 Omitted
                          Giving Status-Code

           If Status-Code Is Not Equal To SS$_NORMAL
              Display 'Error: Read call to SYS$QIOW failed (status).'
              Call 'LIB$STOP' Using By Value Status-Code
              Set Call-Failure to True
              Perform Exit-Program 
           End-If
           .