This post will cover the start of adding a UIM interface to the C Project. The UIM interface adds a CUA compliant interface to the project which is important when you later add the LookSoftware interface over the 5250 screens we are developing.
We have a stock method which we tend to use for the UIM processing, the following code is built upon this base code.
We have created a new header file called UIMHDR.c, this header file contains the includes which are specific to the UIM. Here is the header file.
#include <quidspp.h> /* Display Panel */
#include <quicloa.h> /* close application */
#include <quiputv.h> /* put variable */
#include <quiaddle.h> /* add a list entry */
#include <quiopnda.h> /* open display application */
#include <euialcl.h> /* listopt exit */
#define HELPFULL_NO “NO”
#define CLOSEOPT_NORMAL “M”
#define REDISPLAY_NO “N”
#define EXTEND_NO “N”
#define APPSCOPE_CALLER -1
#define EXITPARM_STR 0
#define EXITPROG_BUFLEN 20
We also added some chnages to the COMMON header file as seen below
#include <stdio.h> /* Standard Input/Output */
#include <stdlib.h> /* Standard Library */
#include <recio.h> /* Record IO */
#include <qusec.h> /* Error Code structs */
/* External File declaration and structure declaration & defines. */
#pragma mapinc("usrf","*LIBL/USERS(USRREC)","both","","","DATA_F")
#include "usrf"
typedef DATA_F_USRREC_both_t USRREC;
#define _USR_REC sizeof(USRREC)
#define _CPYRGHT "Copyright @ Shield Advanced Solutions Ltd 1997-2010"
/* structure for error code passed to API's */
typedef struct EC_x {
Qus_EC_t EC;
char Exception_Data[48];
} EC_t;
The main change is to add the QUSEC.H file and define a structure we will use for capturing errors returned from the PI calls.
We will only use certain API’s for this exercise so as we develop the project further we will add more includes and defines in this file if they are specific to UIM programs.
There is nothing really special about the content so the comments should be enough.
Next we built the panel group based on the information we already have. The basic process will be to display a list of entries which just show the First and Last name of the users we have in the DB file. We will provide a list option(5) to display all of the data stored about the user.
.*******************************************************************
.*
.* Part name: DSPUSRPNL
.*
.* Author name..: Chris Hird
.* Date created : January 2010
.*
.* Function…..: Display the list of users
.*
.* Date Author Revision
.*
.* @Copyright Shield Advanced Solutions Ltd. Canada
.*
.*******************************************************************
.* (1)
NLGRP HLPSHELF=list
DFTMSGF=hlpmsgf.
:COPYR.
(c) Copyright Shield Advanced Solutions (Canada) Inc. 2010
.* Import all help from panel group SDRHLP ——
:IMPORT NAME=’*’ PNLGRP=usrhlp.
.*(2)
.* ——————————————————————-
.* Variable classes
.*
:CLASS NAME=chr10cls BASETYPE=’CHAR 10′.
:ECLASS.
:CLASS NAME=chr15cls BASETYPE=’CHAR 15′.
:ECLASS.
:CLASS NAME=chr20cls BASETYPE=’CHAR 20′.
:ECLASS.
:CLASS NAME=chr25cls BASETYPE=’CHAR 25′.
:ECLASS.
:CLASS NAME=chr35cls BASETYPE=’CHAR 35′.
:ECLASS.
:CLASS NAME=actcls BASETYPE=’ACTION’.
:ECLASS.
:CLASS NAME=exitcl BASETYPE=’CHAR 20′.
:ECLASS.
:CLASS NAME=chr255cls BASETYPE=’CHAR 255′.
:ECLASS.
.* ——————————————————————-
.*(3)
:VAR NAME=fname CLASS=chr20cls.
:VAR NAME=lname CLASS=chr20cls.
:VAR NAME=addr1 CLASS=chr25cls.
:VAR NAME=addr2 CLASS=chr25cls.
:VAR NAME=city CLASS=chr15cls.
:VAR NAME=state CLASS=chr15cls.
:VAR NAME=zip CLASS=chr10cls.
:VAR NAME=cntry CLASS=chr15cls.
:VAR NAME=telnum CLASS=chr15cls.
:VAR NAME=email CLASS=chr35cls.
:VAR NAME=opt CLASS=actcls.
:VAR NAME=csrvar CLASS=chr10cls.
:VAR NAME=exitpgm CLASS=exitcl.
:VAR NAME=parms CLASS=chr255cls.
.* ——————————————————————-
.*(4)
:VARRCD NAME=usrdet
VARS=’lname fname addr1 addr2 city state zip cntry telnum email’.
:VARRCD NAME=cursor
VARS=’csrvar’.
:VARRCD NAME=exitprog
VARS=’exitpgm’.
.* ——————————————————————-
.*(5)
:LISTDEF NAME=usrlist
VARS=’opt lname fname addr1 addr2 city state zip cntry telnum email’.
.* ——————————————————————-
.*(6)
.* — File panel’s keys ——
:KEYL NAME=usrkeys HELP=fkeys.
:KEYI KEY=F1 HELP=helpf1
ACTION=HELP.
:KEYI KEY=F3 HELP=helpf3
ACTION=’EXIT SET’
VARUPD=NO.
F3=Exit
:KEYI KEY=F12 HELP=helpf12
ACTION=’CANCEL SET’
VARUPD=NO.
F12=Cancel
:KEYI KEY=F21 HELP=helpf21
ACTION=’CMDLINE’
PRIORITY=40.
F21=Command Line
:KEYI KEY=ENTER HELP=enter
ACTION=ENTER.
:KEYI KEY=HELP HELP=help
ACTION=HELP.
:KEYI KEY=PAGEDOWN HELP=pagedown
ACTION=PAGEDOWN.
:KEYI KEY=PAGEUP HELP=pageup
ACTION=PAGEUP.
:KEYI KEY=PRINT HELP=print
ACTION=PRINT.
:EKEYL.
.* ——————————————————————-
.*(7)
ANEL NAME=USRPNL HELP=’usrpnl/’
KEYL=usrkeys
CSRVAR=csrvar
ENTER=’RETURN 500′
TOPSEP=SYSNAM.
Work with Users
.* — File list area ————-
:LIST DEPTH=’*’ LISTDEF=usrlist
ACTOR=UIM
MAXHEAD=4
PARMS=parms
SCROLL=YES
BOTSEP=SPACE.
:TOPINST.
Type options, press Enter.
.* List options ——————
.*(8)
:LISTACT OPTION=5
HELP=’usrpnl/dspdet’
ENTER=’CALL exitpgm’
USREXIT=’CALL exitpgm’.
5=Display Detail
.* Columns and headings ———-
:LISTCOL VAR=opt HELP=’usrpnl/opt’
USAGE=INOUT
MAXWIDTH=3.
Opt
:LISTCOL VAR=lname HELP=’usrpnl/lname’
USAGE=OUT
MAXWIDTH=20.
Last Name
:LISTCOL VAR=fname HELP=’usrpnl/fname’
USAGE=OUT
MAXWIDTH=20.
First Name
:LISTCOL VAR=addr1 HELP=’usrpnl/addr1′
USAGE=OUT
MAXWIDTH=25.
Address
:LISTCOL VAR=addr2 HELP=’usrpnl/addr2′
USAGE=OUT
MAXWIDTH=25.
Address
:LISTCOL VAR=city HELP=’usrpnl/city’
USAGE=OUT
MAXWIDTH=15.
City
:LISTCOL VAR=state HELP=’usrpnl/state’
USAGE=OUT
MAXWIDTH=15.
State
:LISTCOL VAR=zip HELP=’usrpnl/zip’
USAGE=OUT
MAXWIDTH=10.
ZipCode
:LISTCOL VAR=cntry HELP=’usrpnl/cntry’
USAGE=OUT
MAXWIDTH=15.
Country
:LISTCOL VAR=telnum HELP=’usrpnl/telnum’
USAGE=OUT
MAXWIDTH=15.
Telephone
:LISTCOL VAR=email HELP=’usrpnl/email’
USAGE=OUT
MAXWIDTH=35.
Email
.*(9)
:LISTVIEW COLS=’opt lname fname’.
:ELIST.
:EPANEL.
.* ——————————————————————-
.*(10)
ANEL NAME=DETPNL
HELP=’usrpnl/dets’
KEYL=usrkeys
ENTER=’RETURN 500′
TOPSEP=SYSNAM.
User Details
.*
.* — Data area ————-
ATA DEPTH=’*’
SCROLL=YES
LAYOUT=1
BOTSEP=SPACE.
.*
ATACOL WIDTH=25.
ATACOL WIDTH=’*’.
.*
ATAI VAR=fname
HELP=’usrpnl/fname’
USAGE=OUT.
First Name
ATAI VAR=lname
HELP=’usrpnl/lname’
USAGE=OUT.
Last Name
ATAI VAR=addr1
HELP=’usrpnl/addr1′
USAGE=OUT.
Address
ATAI VAR=addr2
HELP=’usrpnl/addr2′
USAGE=OUT.
Address
ATAI VAR=city
HELP=’usrpnl/city’
USAGE=OUT.
City
ATAI VAR=state
HELP=’usrpnl/state’
USAGE=OUT.
State
ATAI VAR=zip
HELP=’usrpnl/zip’
USAGE=OUT.
Zip Code
ATAI VAR=cntry
HELP=’usrpnl/cntry’
USAGE=OUT.
Country
ATAI VAR=telnum
HELP=’usrpnl/telnum’
USAGE=OUT.
Telephone
ATAI VAR=email
HELP=’usrpnl/email’
USAGE=OUT.
Email
:EDATA.
:EPANEL.
:EPNLGRP.
Here are the notes, the numbers are shown in the code above as .*(??) so if you are wondering about where each note corresponds to just look for the identifier. .* denotes a comment in UIM and is for the entire line that follows the .*.
1. First we will add the help information, copyright information and message file. We have not created any of these objects yet.
2. Next we have to create the variable classes we will use. This just defines a class based on the base class ie char10cls is based on char 10 etc. We will add different classes as we progress so it is important to understand what each class is used for.
3. We then create the variables based on the classes we have defined. These classes are not objects as you would see in object oriented programming. They have no methods etc.
4. Once we have the variables we define the variable records, this is how we pass structures between the C program and the panel group.
5. List definitions simply state what variables make up a list entry (record) in this instance they are the same as the variable records we pass in.
6. We have to define the function keys we will want to be used. Any key not defined will not be accepted by the panel group.
7. The first panel we create is for the list of records we will pass in. You can see the links to the list definition.
8. These are the options we will show to the user and are the only ones UIM will respond to. If you enter a different one it will not error but simply return without changing the screen at all.
9. You can see how we have defined every element to the list columns but we have only said display the fname(First Name) lname(Last Name) variable in the list view. We want the list entries to be complete so when you select option 5 to display the entry we dont have to go back to the file to get additional data.
10. This is the detail panel where all of the data is shown for individually selected records.
The following is the code to read the data from the file and display it through the panel group.
/******************************************************************************/
/* Program: DSPUSRNL */
/* Program Description : Display a List of Users */
/* */
/* */
/* Purpose : C Programming Project (Using a panel Group) */
/* Files : */
/* */
/* Author: C Hird */
/* */
/* */
/* Copyright Shield Advanced Solutions Limited 2010 */
/******************************************************************************/
#include /* UIM Includes */
#include /* Common header */
#pragma comment(copyright,_CPYRGHT)
#define PNLGRP “DSPUSRPNL *LIBL ”
#define ILEPGMLIB “DSPUSRPNL *LIBL ”
#define EXITPROG “EXITPROG ”
/* 1 */
extern void UIMExit(Qui_ALC_t *);
extern void AppWrkUsrLst(void);
void ProcessListOption(Qui_ALC_t *);
int load_entries(char *);
/* 2 */
int main(int argc,char *argv[]) {
int CallType;
char **tmp_ptr;
Qui_ALC_t *call_lopt;
/* 3 */
if(argc == 1) {
AppWrkUsrLst();
}
else {
tmp_ptr = argv;
call_lopt = (Qui_ALC_t *) tmp_ptr[1];
UIMExit(call_lopt);
}
return 0;
}
/* 4 */
void AppWrkUsrLst(void) {
int Function_Requested,
*Func_Req = &Function_Requested;
char applHandle[8];
char varBuffer[130];
char tmp[2];
EC_t Error_Code = {0};
Error_Code.EC.Bytes_Provided = sizeof(Error_Code);
QUIOPNDA(applHandle,
PNLGRP,
APPSCOPE_CALLER,
EXITPARM_STR,
HELPFULL_NO,
&Error_Code);
if(Error_Code.EC.Bytes_Available > 0) {
printf(“Error Code received %.7s\n”,Error_Code.EC.Exception_Id);
exit(-1);
}
memset(varBuffer,’ ‘,EXITPROG_BUFLEN);
memcpy(varBuffer,ILEPGMLIB,20);
QUIPUTV(applHandle,
varBuffer,
EXITPROG_BUFLEN,
“EXITPROG “,
&Error_Code);
if(Error_Code.EC.Bytes_Available > 0) {
printf(“Error Code received %.7s\n”,Error_Code.EC.Exception_Id);
exit(-1);
}
/* set up the display data here */
if(load_entries(applHandle) == 0) {
QUIDSPP(applHandle,
Func_Req,
“USRPNL “,
REDISPLAY_NO,
&Error_Code);
if(Error_Code.EC.Bytes_Available > 0) {
printf(“Error Code received %.7s\n”,Error_Code.EC.Exception_Id);
exit(-1);
}
}
QUICLOA(applHandle,
CLOSEOPT_NORMAL,
&Error_Code);
if(Error_Code.EC.Bytes_Available > 0) {
printf(“Error Code received %.7s\n”,Error_Code.EC.Exception_Id);
exit(-1);
}
exit(0);
}
/* 5 */
void UIMExit(Qui_ALC_t *uimExitStr) {
Qui_ALC_t *listOptAction;
int CallType;
CallType = uimExitStr->CallType;
switch(CallType) {
case 1: {
break;
}
case 2: {
break;
}
case 3: {
listOptAction = (Qui_ALC_t *) uimExitStr;
ProcessListOption(listOptAction);
break;
}
case 4: {
break;
}
case 5: {
break;
}
case 6: {
break;
}
case 7: {
break;
}
case 8: {
break;
}
}
return;
}
/* 6 */
void ProcessListOption(Qui_ALC_t *listOptAction) {
Qui_ALC_t listOpt; /* Structure for List Option */
char ListEntryHandle[4]; /* handle to list entry */
int functionRequested, /* Function requested by user */
*funcReq = &functionRequested; /* Pointer to function requested */
EC_t Error_Code = {0}; /* Error Code struct */
listOpt = *listOptAction;
Error_Code.EC.Bytes_Provided = sizeof(Error_Code);
/* display the content */
if(listOpt.ListOption == 5) {
QUIDSPP(listOpt.ApplHandle,
funcReq,
“DETPNL “,
REDISPLAY_NO,
&Error_Code);
if(Error_Code.EC.Bytes_Available > 0) {
printf(“Error Code received %.7s\n”,Error_Code.EC.Exception_Id);
return;
}
return;
}
return;
}
/* 7 */
int load_entries(char *applHandle ) {
_RFILE *fp; /* file Ptr */
_RIOFB_T *fdbk; /* Feed back Ptr */
USRREC UsrRec; /* File struct */
EC_t Error_Code = {0}; /* Error_Code Struct */
Error_Code.EC.Bytes_Provided = sizeof(Error_Code);
if((fp =_Ropen(“USERS”,”rr”)) == NULL) {
printf(“filed to open the file\n”);
return -1;
}
fdbk = _Rreadf(fp,&UsrRec,_USR_REC,__DFT);
if(fdbk->num_bytes == EOF) {
printf(“No Records in the file\n”);
_Rclose(fp);
return -1;
}
do {
/* add the list entries */
QUIADDLE(applHandle,
&UsrRec,
_USR_REC,
“USRDET “,
“USRLIST “,
“NEXT”,
” “,
&Error_Code);
if(Error_Code.EC.Bytes_Available > 0) {
_Rclose(fp);
return -1;
}
fdbk = _Rreadn(fp,&UsrRec,_USR_REC,__DFT);
}while(fdbk->num_bytes == _USR_REC);
_Rclose(fp);
return 0;
}
The program has a dual purpose it will load up the panel group when first called and also acts as the exit program for the panel group. You could create multiple exit programs for individual actions but we feel this way keeps things faily simple.
1. We define the functions to be used in the program
2. This is the entry point of the program.
3. We check the number of arguments passed to the program, if its 1 we know this is the first time the program is called so call the AppWrkUsrLst function.
4. This function sets up the panel group and loads the relevant data for the list.
5. If there is more than 1 parameter passed on the call to the program this function is called. We use this function to decide what request has been made from the panel group. We are only coding up for a list option request at this time so we simply break if any others are called and the program exits normally.
6. If the request is for a list option this function is called, we check for the right option(5) and if it is we display the detail panel which shows the detail. All of the data is available in the list entry so we load up the variable pool when the list entry is selected.
7. This is the function which loads the list entries to the panel. You can see it is the same program as we had before but instead of writing out to STDOUT (printf) we are adding list entries before returning.
Once you have this code compiled in the CPROJPGM library, add CPROJDTA and CPROJPGM to the library list in a 5250 session and call DSPUSRPNL program you should get a screen which looks like the following.

Display Users
Thats all there is to it. Any problems or questions let us know.
Chris….