RPG Ref

(click to open)

Quick Page Table of Contents

Scanning…

ezwindow System i RPG ezwindow API Ref

Getting Started

Compile

There are two components to the RPG ezwindow API:

  • /QOpenSys/usr/bin/ezwindow - PASE binary/program that handles X GUI
  • QSYS/XGUI10 - *SRVPGM interface to the ezwindow binary/program
    • Note: included build program BLDX10 creates XGUI10 in QSYS

To ezwindow enable your RPG program include the RPG API prototype interface:

     H AlwNull(*UsrCtl)
      /copy xgui10_h

and compile with XGUI10 BNDSRVPGM (ezsimpr program this example):

     CRTRPGMOD MODULE(FREEWARE/ezsimpr) +
               SRCFILE(FREEWARE/QRPGLESRC) +
               DBGVIEW(*LIST) ALWNULL(*YES)
     CRTPGM PGM(FREEWARE/ezsimpr) +
            BNDSRVPGM(QSYS/XGUI10) +
            ACTGRP(*NEW)

Note: The demos provided assume all the source code is in FREEWARE library, but you may copy the header file and RPG source wherever you would like.

Run

ssh -X my400 (or latest ssh -Y my400 if you see "bad atom", or graphics problems)
--or--
>ssh -X myuserid@myi5.xxx.org (if your PC is not same user name)
> echo $DISPLAY
> qsh
> cd /qsys.lib/freeware.lib
> EZGUIR.PGM&

--  or --
5250 emulator with DISPLAY env var set to ssh -X (see echo above)

-- or --
icon on PC though Putty, etc

There are always at least two jobs running on the System i for any RPG ezwindow GUI program:

  • Job 1: your RPG GUI program bound to XGUI10
    • This process is pure ILE with no PASE trappings, therefore it can be debugged with any traditional debugger you normally use. This process does need any special attributes (no threads, etc.), but the DISPLAY environment variable must be set so that X GUI will know where to place the window.
    • Each window in the RPG application is modal, which means a child window requires the user to complete interaction before they can return to operating the parent window. The modal ezwindow default allows your traditional single threaded RPG application to run the same way it does under traditional 5250 applications.
  • Job 2-N: ezwindow - PASE program handling all X GUI specific work for a particular window
    • This process is spawned by the XGUI10 SRVPGM. The PASE ezwindow program started in the spawned child handles all GUI work plus communications with the client PC and your RPG program. There will be one additional PASE ezwindow job started for each separate window in the application using the ezWinOpen() API. The ezWinClose() API will dismiss the window and end the ezwindow process. You can think of the ezwindow child job as similar to the role played by DB2 QSQSRVR jobs that run on behalf of DB2 interface to a program, except the mission of the PASE ezwindow job is GUI.
      • Note: To avoid ezwindow process start/stop performance problems, there is a ezwindow :start tag hide=yes option that will allow the window to be dismissed from view but keep the ezwindow process active for reuse on any frequently accessed child window..
        • Use ezWinUpd(wid:’Window hide=yes’) in place of ezWinClose(wid) on any :start hide=yes window definition to enable the process/window reuse, but don’t forget to use ezWinClose(wid) at job/application end.
  • “Thin” Client:
    • If you are a Linux user (like me), use standard ssh -X my400 (ssh -Y if you see bad atom).
    • If you are a Windows user you have two choices:
      • Download a X render product (see Client Pgms). If you install a product with ssh (recommended), use standard ssh -X my400 (ssh -Y if you see bad atom).
      • Setup VNC client and server (see 5799PTLPRPQ). Or see VNC server from Open Source Binaries, RPM package wwwinstall GetVnc. Note: The VNC option will not perform as well as ssh -X with a render product..
    • Note: if you are using encrypted communications from your Linux, Windows or Mac PC ssh -X/-Y my400 (recommended), the DISPLAY variable will be set automatically to a localhost:xx.0 when you initiate the conversation, assuming you enabled X11Forwarding yes on the System i server (see SSHSetup). To see the DISPLAY setting in the ssh session type echo $DISPLAY. You may set the DISPLAY environment variable in any ILE process that wants to run X/ezwindows and the window will pop up on the PC client that started ssh -X/-Y my400. Remember the DISPLAY environment variable must be set before your RPG program calls ezWinOpen() or the RPG job will appear to just hang (actually the window is all dressed up, but has nowhere to go for keyboard/mouse communication).

Debug

You can use any standard debugger to debug your ILE RPG program. The only trick is to make sure that the DISPLAY environment variable is set before your RPG application calls the ezWinOpen() API that spawns the PASE ezwindow binary handling all the X GUI communications with your PC client. In the case of the System GUI Debugger simply set ADDENVVAR ENVVAR(DISPLAY) VALUE(‘localhost:xx.0′) in the Initialization command: prompt and you are off debugging a ezwindow graphical application.

Note: Do not check Debug PASE as this will have no effect on the debug session because the job running your RPG program is pure ILE with no PASE. As far as I know traditional ILE debuggers have never been taught to follow spawned child processes like UNIX debuggers, so if you really need to debug the PASE ezwindow binary job you will have to attach to the running ezwindow job with a new debugger session (may the force be with you).

Simple program

Window screen shot

Click Samples for more examples.

Window definition

# :tags must start at begin line
# to be correctly read by ezwindow    
# -------- Window definition -------
:start my_window title=GetBio exit_buttons=no \
typechk_rc=0 fg=Black bg=LightSteelBlue hide=yes
:ltr frame=yes
:text_entry_group input_fg=SlateBlue input_bg=LightGrey \
enter=exit(0)
Name:\length=40
Age: \length=2
:eltr
:ltr
:hot_button name=" Ok      "  rc=0 fg=ivory bg=DarkSlateBlue
:hot_button name=" Cancel  "  rc=4 fg=ivory bg=DarkSlateBlue
:eltr
:text id=msg fg=IndianRed lines=3
:stop

RPG program

     H AlwNull(*UsrCtl)
      /copy xgui10_h
     d wid             s             10i 0 inz(0)
     D rc              s             10i 0
     D def1            s               *
     D defonly         s               *
     D fields          s               *   dim(1000)
     D fieldsDim       c                   1000
     D upd             s             60a   inz(*blanks)
     D name            s             60a   inz(*blanks)
     D age             s             60a   inz(*blanks)

      /free
       def1=ezWinLFM('freeware/qddssrc(ezsimp)'); // read window defs (EBCDIC)
       defonly=ezWinDef(def1:'my_window');        // parse single def
       wid=ezWinOpen(defonly);                    // Display window
       if (wid<0);
         *inlr = *on;                             // Open error; terminate
       endif;
       upd='msg text=" "';                        // Init msg blanks
       dou upd = *blanks;
         rc=ezWinUpdGetDim(wid:upd:
              %addr(fields):fieldsDim);           // Upd/Get user input
         if (rc=4);
           leave;                                 // Cancel button clicked
         endif;
         upd=*BLANKS;
         name=%trim(%str(fields(1)));             // copy results string #1
         age=%trim(%str(fields(2)));              // copy results string #2
         dealloc fields(1);                       // free result storage #1
         dealloc fields(2);                       // free result storage #2
         if (name=*BLANKS);                       // Error. ring bell
           upd='msg text="Please enter your name"; Window bell=yes';
         else;                                    // All OK, display data
           upd='msg text="Data is '+%trim(name)+' '+%trim(age)+'";';
         endif;
       enddo;

       dealloc defonly;
       dealloc def1;
       ezWinClose(wid);

       *inlr = *on;
      /end-free

The ILE RPG Interface

Single include/copy FREEWARE/QRPGLESRC(xgui10_h)

     H AlwNull(*UsrCtl)
      /copy xgui10_h

and compile with XGUI10 BNDSRVPGM (ezsimpr program this example):

     CRTRPGMOD MODULE(FREEWARE/ezsimpr) +
               SRCFILE(FREEWARE/QRPGLESRC) +
               DBGVIEW(*LIST) ALWNULL(*YES)
     CRTPGM PGM(FREEWARE/ezsimpr) +
            BNDSRVPGM(QSYS/XGUI10) +
            ACTGRP(*NEW)

Constants

     ***********************************************************************
     **  C O N S T A N T S
     ***********************************************************************
     D ezLF            c                   x'25'
     D ezNULL          c                   x'00'
  • ezLF - line feed that will translate to ASCII line feed x’0A’
  • ezNULL - null terminated string marker

*string vs. varying

The RPG interface supports both options(*string: *trim) and varying interfaces. The *string interfaces will correctly null terminate strings passed to the XGUI10 SRVPGM from a variety RPG character data structures. The varying interfaces requires the RPG programmer to make sure the string is null terminated before passing the data through the interface, the receiving XGUI10 SRVPGM will ignore the first 2 bytes of length information of a varying data type.

Create window defs

The ezwindow binary is very particular about line feed markers at the end of the window definition lines (same sort of obsession that compilers have about semi-colons). To aid the programmer with this small “quirk”, a few string data modifiers have been added to the API for your convenience.

  • ezWinLFM - read EBCDIC window definitions from a lib/file(mbr) text file and transform the record data into free format lines with line feeds and null terminator. The examples use FREEWARE/QDDSSRC(MYDEFS), where QDDSSRC was created with reclen=92.
  • ezWinRec - transform a large string of fixed length window definition(s) lines (array) into free format lines with line feeds and null terminator.
  • ezWinTok - transform a tokenized string into free format lines with line feeds and null terminator. The classic example is a large string of window definition(s) that is using a semi-colon as a terminator, which will be transformed into lines with line feeds and null terminator.
  • ezWinDef - chop a single window definition :start to :stop, from multiple window definition(s) provided by the ezWinLFM, ezWinRec, or ezWinTok APIs. This function also replaces “:start label” with required “:start *”, so that the ezwindow binary will work with your definition.

ezWinLFM - read lib/file(mbr)

Header prototype:

     ** ezWinLFM reads window definition(s) library/file(mbr) 
     **   text files. and then transforms fixed record length 
     **   window definition(s) into variable length null 
     **   terminated string with required LF at the 
     **   end of each line.
     **   There may be multiple :start label / :stop
     **   window definitions in the data records.
     **   To subset a single :start / :stop definition
     **   with correct ezwindow format use ezWinDef
     **   on the buffer reurned from this function.
     **   *** The caller must free the returned buffer. ***
     ** Parameters:
     **   file    - file name              (ezWinLFMV varying)
     ** returns (NULL=bad, !NULL=window definitions)
     **
     ** Example FREEWARE/QDDSSRC(DEMOSAMP):
     **   :start main1 title="DEMO0001"                     
     **   :text id=EZmsg lines=3 fg=SteelBlue bell=no 
     **   :stop
     **   :start main2 title="DEMO0002"                     
     **   :text id=EZmsg lines=3 fg=SteelBlue bell=no
     **   :stop
     ** Routine returns:
     **    ':start main1 title="DEMO0001"'+ezLF
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no'+ezLF 
     **   +':stop'+ezLF
     **    ':start main2 title="DEMO0002"'+ezLF
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no'+ezLF
     **   +':stop'+ezLF+ezNULL
     DezWinLFM...
     D                 PR              *   EXTPROC('ezWinLFM')
     D file                            *   VALUE options(*string: *trim)
     DezWinLFMV...
     D                 PR              *   EXTPROC('ezWinLFMV')
     D file                            *   VALUE

ezWinRec - fixed string

Header prototype:

     ** ezWinRec transforms fixed record length window definition(s)
     **   into variable length null terminated string with
     **   required LF at the end of each line.
     **   There may be multiple :start label / :stop
     **   window definitions in the data records.
     **   To subset a single :start / :stop definition
     **   with correct ezwindow format use ezWinDef
     **   on the buffer reurned from this function.
     **   *** The caller must free the returned buffer. ***
     ** Parameters:
     **   def     - array fixed len string (ezWinRecV varying)
     **   line_sz - record len each line
     **   max_sz  - max bytes passed (line_sz*records)
     ** returns (NULL=bad, !NULL=window definitions)
     **
     ** Example def string:
     **    ':start main1 title="DEMO0001"                     '
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no       ' 
     **   +':stop                                             '
     **   +':start main2 title="DEMO0002"                     '
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no       ' 
     **   +':stop                                             '
     ** Routine returns:
     **    ':start main1 title="DEMO0001"'+ezLF
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no'+ezLF 
     **   +':stop'+ezLF
     **   +':start main2 title="DEMO0002"'+ezLF
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no'+ezLF 
     **   +':stop'+ezLF+ezNULL
     DezWinRec...
     D                 PR              *   EXTPROC('ezWinRec')
     D def                             *   VALUE options(*string: *trim)
     D line_sz                       10u 0 VALUE
     D max_sz                        10u 0 VALUE
     DezWinRecV...
     D                 PR              *   EXTPROC('ezWinRecV')
     D def                             *   VALUE
     D line_sz                       10u 0 VALUE
     D max_sz                        10u 0 VALUE

ezWinTok - tokenized string

Header prototype:

     ** ezWinTok transforms variable length window definition(s)
     **   with caller provided tokenizer 
     **   into variable length null terminated string with
     **   required LF at the end of each line.
     **   There may be multiple :start label / :stop
     **   window definitions in the data records.
     **   To subset a single :start / :stop definition
     **   with correct ezwindow format use ezWinDef
     **   on the buffer reurned from this function.
     **   *** The caller must free the returned buffer. ***
     ** Parameters:
     **   def     - variable len null term string (ezWinTokV varying)
     **   token   - character end-of-line token   (ezWinTokV varying)
     ** returns (NULL=bad, !NULL=window definitions)
     **
     ** Example def string:
     **    ':start main1 title="DEMO0001";'
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no;' 
     **   +':stop;'
     **   +':start main2 title="DEMO0002";'
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no;' 
     **   +':stop;'
     ** Routine returns:
     **    ':start main1 title="DEMO0001"'+ezLF
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no'+ezLF 
     **   +':stop'+ezLF
     **   +':start main2 title="DEMO0002"'+ezLF
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no'+ezLF 
     **   +':stop'+ezLF+ezNULL
     DezWinTok...
     D                 PR              *   EXTPROC('ezWinTok')
     D def                             *   VALUE options(*string: *trim)
     D token                          1A   VALUE
     DezWinTokV...
     D                 PR              *   EXTPROC('ezWinTokV')
     D def                             *   VALUE
     D token                          1A   VALUE

ezWinDef - chop :start to :stop

Header prototype:

     ** ezWinDef finds :start label to :stop and returns a new buffer
     **   of this definition only. The routine replaces ':start label'
     **   to ':start *' required by ezwindows in the new buffer.
     **   *** The caller must free the returned buffer. ***
     ** Parameters:
     **   def     - window file definition (ezWinDefV varying)
     **   label   - window start label     (ezWinDefV varying)
     **             Note: label only the :start tag
     **                   is managed by the rountine.
     **                   :start tag must have only one
     **                   space before label.
     ** returns (NULL=bad, !NULL=window definition)
     **
     ** Example def string (from ezWinLFM, ezWinRec, etc.):
     **    ':start main1 title="DEMO0001"'+ezLF
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no'+ezLF 
     **   +':stop'+ezLF
     **    ':start main2 title="DEMO0002"'+ezLF
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no'+ezLF 
     **   +':stop'+ezLF+ezNULL
     ** Routine returns (assuming label was 'main2'):
     **    ':start *     title="DEMO0002"'+ezLF
     **   +':text id=EZmsg lines=3 fg=SteelBlue bell=no'+ezLF 
     **   +':stop'+ezLF+ezNULL
     DezWinDef...
     D                 PR              *   EXTPROC('ezWinDef')
     D def                             *   VALUE options(*string: *trim)
     D label                           *   VALUE options(*string: *trim)
     DezWinDefV...
     D                 PR              *   EXTPROC('ezWinDefV')
     D def                             *   VALUE
     D label                           *   VALUE

Process/Window control

There are only two ezwindow control APIs, ezWinOpen and EzWinClose.

  • ezWinOpen - will open a window and start a PASE process to handle the GUI.
  • ezWinClose - will close a window and end the PASE process.
    • Note: To avoid excessive PASE process start/stop, use window hiding instead of ezWinClose (see User Guide for details).

ezWinOpen - open ezwindow def

Header prototype:

     ** ezWinOpen accepts a (single) null-terminated string that holds
     **   window definition parameters, and returns the (non-negative)
     **   window identifier needed to manage the window.  The result
     **   is -1 (with errno set) for any error
     ** Parameters:
     **   parms   - window file definition (ezWinOpenV varying)
     ** returns (-1=bad, !-1=window id)
     DezWinOpen...
     D                 PR            10i 0 EXTPROC('ezWinOpen')
     D parms                           *   VALUE options(*string: *trim)
     DezWinOpenV...
     D                 PR            10i 0 EXTPROC('ezWinOpenV')
     D parms                           *   VALUE

ezWinClose - close window

Header prototype:

     ** ezWinClose closes a window previously opened by ezWinOpen,
     **   freeing all resources for the window (ending the server process)
     ** Parameters:
     **   wid     - window id from ezWinOpen
     ** returns (NA)
     DezWinClose...
     D                 PR                  EXTPROC('ezWinClose')
     D wid                           10i 0 VALUE

Recommended array interface

The simplest APIs to update or get information for an ezwindow process are:

  • ezWinGetDim - this API will get an array of PTRs to null terminated strings that match one-for-one the number of output capable GUI widgets. The SRVPGM handles all socket communications and creates the separate strings, so you do not have to perform complex parsing.
  • ezWinUpdGetDim - this API first sends all accumulated changes in a string to the ezwindow process to update the window (immediately), then performs exactly the same get array of PTRS to null terminated strings described in ezWinGetDim.

ezWinGetDim - get array

ezWinUpdGetDim - update/get

Header prototype:

     ** ezWinUpdGetDim and ezWinGetDim call ezWinUpdGet
     **   to update the window (if needed) and get results into a local buffer,
     **   then parse the buffer to return an array of null-terminated strings.
     **   The function result is the return code value that follows the last
     **   field returned by the server, or -1 (with errno set) for any error
     **   Every returned string is a heap allocation that clients must free().
     **   An error is returned (with no useful results) if the array is too
     **   small for all results fields
     ** Parameters:
     **   wid     - window id from ezWinOpen
     **   updates - pend gui entry change  (ez____V varying)
     **   fields  - output results from window (array ptrs to strings)
     **   fieldsDim - output nbr of results
     ** returns (-1=bad, !-1=return code window)
     DezWinUpdGetDim...
     D                 PR            10i 0 EXTPROC('ezWinUpdGetDim')
     D wid                           10i 0 VALUE
     D updates                         *   VALUE options(*string: *trim)
     D fields                          *   VALUE
     D fieldsDim                     10u 0 VALUE
     DezWinUpdGetDimV...
     D                 PR            10i 0 EXTPROC('ezWinUpdGetDimV')
     D wid                           10i 0 VALUE
     D updates                         *   VALUE
     D fields                          *   VALUE
     D fieldsDim                     10u 0 VALUE
     DezWinGetDim...
     D                 PR            10i 0 EXTPROC('ezWinGetDim')
     D wid                           10i 0 VALUE
     D fields                          *   VALUE
     D fieldsDim                     10u 0 VALUE

Alternative buffer interface

This a raw data buffer of the socket information returned by ezwindow. In the case of ezWinUpd, no data is waited for to be retrieved, only window updates are made (immediately).

ezWinUpd - update window

ezWinGet - get results

ezWinUpdGet - update/get

Header prototype:

     ** ezWinUpdGet, ezWinUpd, and ezWinGet update a window
     **   definition (from a single null-terminated string) and/or return
     **   window input/results.  The function result is the number of bytes
     **   used/returned in results (zero for UpdateWindow or if "results"
     **   is null), or -1 (with errno set) for any error.  Excess results
     **   may be silently truncated if the buffer is too small
     ** Parameters:
     **   wid     - window id from ezWinOpen
     **   updates - pend gui entry change  (ez____V varying)
     **   results - output results from window
     **   resultsMax - output results max length
     ** returns (-1=bad, !-1=nbr bytes returned)
     DezWinUpdGet...
     D                 PR            10i 0 EXTPROC('ezWinUpdGet')
     D wid                           10i 0 VALUE
     D updates                         *   VALUE options(*string: *trim)
     D results                         *   VALUE
     D resultsMax                    10u 0 VALUE
     DezWinUpdGetV...
     D                 PR            10i 0 EXTPROC('ezWinUpdGetV')
     D wid                           10i 0 VALUE
     D updates                         *   VALUE
     D results                         *   VALUE
     D resultsMax                    10u 0 VALUE
     DezWinUpd...
     D                 PR            10i 0 EXTPROC('ezWinUpd')
     D wid                           10i 0 VALUE
     D updates                         *   VALUE options(*string: *trim)
     DezWinUpdV...
     D                 PR            10i 0 EXTPROC('ezWinUpdV')
     D wid                           10i 0 VALUE
     D updates                         *   VALUE
     DezWinGet...
     D                 PR            10i 0 EXTPROC('ezWinGet')
     D wid                           10i 0 VALUE
     D results                         *   VALUE
     D resultsMax                    10u 0 VALUE

ezCommand - QShell command

Header prototype:

     ** ezCommand invokes QShell to run a command string, and returns
     **   any data written by the shell/command to stdout in the results
     **   buffer.  The function result is the number of bytes used/returned
     **   in results, or -1 (with errno set) for any error.  Excess results
     **   are silently truncated if the buffer is too small
     ** Parameters:
     **   cmd     - command to run         (ezCommandV varying)
     **   results - output results from window
     **   resultsMax - output results max length
     **   waitResult - wait for the command to end
     ** returns (-1=bad, !-1=number bytes returned)
     DezCommand        PR            10i 0   EXTPROC('ezCommand')
     D cmd                             *   VALUE options(*string: *trim)
     D results                         *   VALUE
     D resultsMax                    10u 0 VALUE
     D waitResult                    10i 0 VALUE
     DezCommandV       PR            10i 0   EXTPROC('ezCommandV')
     D cmd                             *   VALUE
     D results                         *   VALUE
     D resultsMax                    10u 0 VALUE
     D waitResult                    10i 0 VALUE