A replacement for DISPL

There are a number of shortcomings using DISPL, such as the message to display can be maximum 52 characters.

Further, you have to press [ENTER] for each line (which might be what you need in some situations). There is a method to circumvent these short comings, and that is what this article is about.

Messages written to screen. User has to press [ENTER] for each line.

In stead of using DISPL, you can use two C functions to display messages and to get input from the user.

To display a message on the screen, you use the C function ‘puts’ (put string). It writes out a string on the screen (to standard out to be precise). To write a message containing a numeric or date field, you must convert the number/date to character, e.g. by using the %Char() BIF.

One huge advantage of using ‘puts’ is, that on the terminal screen, you can press [F6] to print everything that has been written to the screen.

The declaration for ‘puts’ is quite simple:

Dcl-PR PutS Int(10:0) ExtProc('puts');
   oString Pointer Options(*String) Value;
End-PR;

You can now display a message simply by passing the message to PutS:

PutS('Hello world');

To get input from the user, you use the C function ‘gets’ (get string). It returns a string. The declaration for ‘gets’ is:

Dcl-PR GetS Pointer ExtProc('gets');
   Buffer Char(1024);
End-PR;

‘gets’ returns a zero terminated string. To get a useful character field you can either use %Scan() to locate the x’00’ character or you can simply define a pointer to the character field that ‘gets’ returns, and then use the %Str() BIF to get the characters. The example below shows how to do that.

**Free
Ctl-Opt BndDir('QC2LE');
Dcl-PR PutS Int(10:0) ExtProc('puts');
   oString Pointer Options(*String) Value;
End-PR;

Dcl-PR GetS Pointer ExtProc('gets');
   Buffer Char(1024);
End-PR;

Dcl-S InputString Char(1024);
Dcl-S pInputString Pointer Inz(%Addr(InputString));
Dcl-S OutputString VarChar(1024);

PutS('Hello world. How are you?');
If GetS(InputString) = *Null;
   // An error occurred
   PutS('Something went wrong when getting input.');
EndIf;

// Get all characters up to, not including the x'00' char. 

OutputString = %Str(pInputString);
PutS('You wrote: ' + OutputString);

*InLr = *On;
Return;

You could, of cause, wrap ‘gets’ in a procedure to make it very simple to use:

Dcl-Proc GetInput;

   Dcl-PI GetInput Char(1024);
   End-PI;

   // Local work fields.
   Dcl-S InputString Char(1024);
   Dcl-S pInputString Pointer Inz(%Addr(InputString));
   Dcl-S OutputString VarChar(1024);

   If GetS(InputString) = *Null;
      // An error occurred
      PutS('Something went wrong when getting input.');
   Else;
      // Get all characters up to, not including the x'00' char.
      OutputString = %Str(pInputString);
   EndIf;

   Return OutputString;
 End-Proc;

Now the example program looks like this:

**Free
Ctl-Opt BndDir('QC2LE');

Dcl-PR PutS Int(10:0) ExtProc('puts');
   oString Pointer Options(*String) Value;
End-PR;

Dcl-PR GetS Pointer ExtProc('gets');
   Buffer Char(1024);
End-PR;

Dcl-Pr GetInput Char(1024);
End-Pr;

Dcl-S TempString VarChar(1024);

PutS('Hello world. How are you?');
TempString = GetInput();

PutS('You wrote: ' + TempString);

*InLr = *On;
Return;

Dcl-Proc GetInput;
   Dcl-PI GetInput Char(1024);
   End-PI;
   // Local work fields.
   Dcl-S InputString Char(1024);
   Dcl-S pInputString Pointer Inz(%Addr(InputString));
   Dcl-S OutputString VarChar(1024);

   If GetS(InputString) = *Null;
      // An error occurred
      PutS('Something went wrong when getting input.');
   Else;
      // Get all characters up to, not including the x'00' char.
      OutputString = %Str(pInputString);
   EndIf;

   Return OutputString;
End-Proc;

Agreed, that using ‘puts’ and ‘gets’ requires more lines of code than DISPL does. However, if you put the declarations and the ‘GetInput’ procedure in your toolbox, they will be one-liners in your program code 😉