02
Sat, Nov
2 New Articles

Reduce Indicator Usage

RPG
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

As IBM continues to enhance RPG to allow reducing the use of indicators, RPG developers should also be looking for ways to decrease the use of indicators. Using display attribute fields is one way.

One common use of indicators is to conditionally set the display attributes of fields on display files--for example, highlighting or reverse imaging the field, or setting the field's color.

Setting the display attributes on a field is done using the COLOR and DSPATR field-level keywords. Different display attributes are usually set with conditioning indicators. However, there is a way to set these attributes without using indicators--by coding a special form of DSPATR and defining attribute fields.

An attribute field is a one-character field defined in the display file DDS. It is a program-to-system field (specified with a usage of "P"). The RPG application loads an attribute byte into this field, which controls the display attributes of the display field linked to the attribute field.

A display field is linked to an attribute field by using the DSPATR keyword: The format is DSPATR(&ATTRFLD), where ATTRFLD is the name of the attribute field. A field can have only one attribute field, although any number of fields can share a single attribute field; thus, one attribute field can be used to set the same attributes for more than one field simultaneously.

Attribute Bytes

An attribute byte is a special one-byte value that controls the color and effect of a display field. By "effect," I mean highlighting, underlining, and reverse imaging. These values are expressed in hexadecimal format--for example, x'20' (for normal attribute).

IBM's documentation for the DSPATR keyword gives a list of 30 attribute byte values: Some establish a color (such as x'38' for pink), some establish an effect (x'24' for underscore), and some establish a combination (x'3C' for pink and underscore). These 30 attribute byte values are used for input-capable fields. There is another set of 30 values for use with non-input-capable fields. That is a total of 60 values.

To set display attributes for a field, we simply load the desired attribute byte value into the field's linked attribute field:

ATTRFLD = x'24';

And then we write the screen format.

Attribute Value Bit Manipulation

It's easier, and recommended, to define a named constant for each attribute byte value. It is also a good idea to put these named constants into a copybook. We can define a named constant for each of the 60 values. However, we don't necessarily need to define that many named constants.

These attribute values were not arbitrarily chosen. Each bit of an attribute value has a certain function:

  • The high order bit (bit 0 in RPG-ese) is the Protected Attribute bit. It is on for a protected field, off for an input-capable field.
  • Bits 1 and 2 are always 0 and 1, respectively.
  • Bits 3 and 4 determine the color (00=green, 01=red, 10=turquoise, 11=pink).
  • Bit 5, if on, underscores the field.
  • Bit 6, if on, highlights the field.
  • Bit 7, if on, reverse images the field. Setting on bits 5, 6, and 7 at the same time results in the non-display attribute.

We can then use bit manipulation to derive any of the 60 attributes we want. Now, we would only need a minimum of eight named constants:

  • One constant for each of the four color attributes
  • One constant for each of the three effect attributes
  • One constant for the protect attribute

We derive the attribute value by assigning the named constant to the attribute field:

ATTRFLD = atrPNK;

To combine color with an effect and/or the protect attribute, use the %bitor built-in function (BIF). As an example, to set an attribute field to pink with reverse image, you would use the statement:

ATTRFLD = %bitor(atrPNK:atrRI);

Or, prior to V5R2:

C                   eval       ATTRFLD = x'00'
C                   biton      atrPNK         ATTRFLD
C                   biton      atrRI          ATTRFLD

To determine if a certain attribute is on in an attribute field, use the %bitand BIF. For any named constant atrXX, the format would be this:

if %bitand(ATTRFLD:atrXX) = atrXX;

For example, to check to see if the reverse image attribute is on:

if %bitand(ATTRFLD:atrRI) = atrRI;

or

C                   testb      atrRI          ATTRFLD     99    
C*** 99 is in the EQ indicator spot, positions 75..76
C                   if         *in99

To check for a combination, use %bitor wherever atrXX is (or use an and clause).

I mentioned that we would need only eight named constants, but for the sake of a program's readability and ease of maintenance, I suggest a couple more:

  • Named constants for white, yellow and blue. These are actually highlighting colors, derived by turning on highlighting with the following colors: green, which highlights to white; turquoise, which highlights to yellow; and pink, which highlights to blue.
  • A named constant for the non-display attribute.

Example: Calendar Date Prompt Window

To best see attribute fields in action, I present this example (which you may download and use).

This program is a date prompt window. When called, it presents a calendar, from which the user may select a date to pass back to the caller, either by double-clicking on the desired day, or by putting the cursor on the desired day and pressing Enter.

http://www.mcpressonline.com/articles/images/2002/Tip%20-%20Attribute%20FieldsV700.png

As you can see in the figure above, the days in the calendar have various attributes. Workdays are green. Weekends and holidays are pink. Today's date is reversed imaged.

The program has three parameters:

  • A one-digit numeric field that returns either zero (if the user exits the prompt without selecting a day) or a number representing the day of the week of the user's selected day (1=Monday...7=Sunday).
  • An *ISO date field that contains the user's selected date. (Careful! If the user exits without selecting a date, this will contain the system date.)
  • An optional one-character field (defined in the program as an indicator field) that contains '1' if the selected date is a workday, '0' otherwise.

Display File Source (PMTCALD)

In order for this program to work properly and for the calendar to be displayed properly, we need to set up 42 fields--one for each day of the month, keeping in mind that a month could span six calendar week rows (as May 2004 does). Also, keep in mind that the first of the month could start on any of the seven days of the week.

The goal is to differentiate between workdays (which may include weekend days) and non-workdays, including holidays. Non-workdays will be pink. To accomplish changing the attribute to pink using indicators, we would need to use 42 separate indicators, one for each day field. To also reverse image today's day, we would need another 42 separate indicators.

By using attribute fields, we will use no indicators:

     A*%%TS  SD  20030923  143255  DECKERSLEY  REL-V5R2M0  5722-WDS
     A*%%EC
     A                                      DSPSIZ(24 80 *DS3)
     A          R SCRN1
     A*%%TS  SD  20030923  143255  DECKERSLEY  REL-V5R2M0  5722-WDS
     A                                      WINDOW(*DFT 12 40)
     A                                      WDWBORDER((*COLOR WHT)- 

                                             (*DSPATR RI)-
     A                                       (*CHAR '        '))
     A                                      RTNCSRLOC(&CSRREC &CSRFLD)
     A                                      MOUBTN(*ULD E03)
     A            CSRREC        10A  H
     A            CSRFLD        10A  H
     A            CSRROW         3S 0H
     A            CSRCOL         3S 0H
1    A            A01            1A  P
     A            A02            1A  P
     A            A03            1A  P
     A            A04            1A  P
     A            A05            1A  P
     A            A06            1A  P
     A            A07            1A  P
     A            A08            1A  P
     A            A09            1A  P
     A            A10            1A  P
     A            A11            1A  P
     A            A12            1A  P
     A            A13            1A  P
     A            A14            1A  P
     A            A15            1A  P
     A            A16            1A  P
     A            A17            1A  P
     A            A18            1A  P
     A            A19            1A  P
     A            A20            1A  P
     A            A21            1A  P
     A            A22            1A  P
     A            A23            1A  P
     A            A24            1A  P
     A            A25            1A  P
     A            A26            1A  P
     A            A27            1A  P
     A            A28            1A  P
     A            A29            1A  P
     A            A30            1A  P
     A            A31            1A  P
     A            A32            1A  P
     A            A33            1A  P
     A            A34            1A  P
     A            A35            1A  P
     A            A36            1A  P
     A            A37            1A  P
     A            A38            1A  P
     A            A39            1A  P
     A            A40            1A  P
     A            A41            1A  P
     A            A42            1A  P
     A            S1MONTH        2Y 0B  1  2EDTCDE(Z)
     A            PBMONTH        2Y 0B  1  6PSHBTNFLD((*GUTTER 2))
     A                                      PSHBTNCHC(1 '-' CF07)
     A                                      PSHBTNCHC(2 '+' CF08)
     A            S1MONTHN       9A  O  1 15
     A            S1YEAR         4Y 0B  1 25EDTCDE(Z)
     A            PBYEAR         2Y 0B  1 31PSHBTNFLD((*GUTTER 2))
     A                                      PSHBTNCHC(1 '-' CF19)
     A                                      PSHBTNCHC(2 '+' CF20)
     A                                  3  2'Su'
     A                                      DSPATR(UL)
     A                                      DSPATR(HI)
     A                                  3  8'Mo'
     A                                      DSPATR(UL)
     A                                      DSPATR(HI)
     A                                  3 14'Tu'
     A                                      DSPATR(UL)
     A                                      DSPATR(HI)
     A                                  3 20'We'
     A                                      DSPATR(UL)
     A                                      DSPATR(HI)
     A                                  3 26'Th'
     A                                      DSPATR(UL)
     A                                      DSPATR(HI)
     A                                  3 32'Fr'
     A                                      DSPATR(UL)
     A                                      DSPATR(HI)
     A                                  3 38'Sa'
     A                                      DSPATR(UL)
     A                                      DSPATR(HI)
2    A            D01            2Y 0O  4  2EDTCDE(Z)
     A                                      DSPATR(&A01)
     A            D02            2Y 0O  4  8EDTCDE(Z)
     A                                      DSPATR(&A02)
     A            D03            2Y 0O  4 14EDTCDE(Z)
     A                                      DSPATR(&A03)
     A            D04            2Y 0O  4 20EDTCDE(Z)
     A                                      DSPATR(&A04)
     A            D05            2Y 0O  4 26EDTCDE(Z)
     A                                      DSPATR(&A05)
     A            D06            2Y 0O  4 32EDTCDE(Z)
     A                                      DSPATR(&A06)
     A            D07            2Y 0O  4 38EDTCDE(Z)
     A                                      DSPATR(&A07)
     A            D08            2Y 0O  5  2EDTCDE(Z)
     A                                      DSPATR(&A08)
     A            D09            2Y 0O  5  8EDTCDE(Z)
     A                                      DSPATR(&A09)
     A            D10            2Y 0O  5 14EDTCDE(Z)
     A                                      DSPATR(&A10)
     A            D11            2Y 0O  5 20EDTCDE(Z)
     A                                      DSPATR(&A11)
     A            D12            2Y 0O  5 26EDTCDE(Z)
     A                                      DSPATR(&A12)
     A            D13            2Y 0O  5 32EDTCDE(Z)
     A                                      DSPATR(&A13)
     A            D14            2Y 0O  5 38EDTCDE(Z)
     A                                      DSPATR(&A14)
     A            D15            2Y 0O  6  2EDTCDE(Z)
     A                                      DSPATR(&A15)
     A            D16            2Y 0O  6  8EDTCDE(Z)
     A                                      DSPATR(&A16)
     A            D17            2Y 0O  6 14EDTCDE(Z)
     A                                      DSPATR(&A17)
     A            D18            2Y 0O  6 20EDTCDE(Z)
     A                                      DSPATR(&A18)
     A            D19            2Y 0O  6 26EDTCDE(Z)
     A                                      DSPATR(&A19)
     A            D20            2Y 0O  6 32EDTCDE(Z)
     A                                      DSPATR(&A20)
     A            D21            2Y 0O  6 38EDTCDE(Z)
     A                                      DSPATR(&A21)
     A            D22            2Y 0O  7  2EDTCDE(Z)
     A                                      DSPATR(&A22)
     A            D23            2Y 0O  7  8EDTCDE(Z)
     A                                      DSPATR(&A23)
     A            D24            2Y 0O  7 14EDTCDE(Z)
     A                                      DSPATR(&A24)
     A            D25            2Y 0O  7 20EDTCDE(Z)
     A                                      DSPATR(&A25)
     A            D26            2Y 0O  7 26EDTCDE(Z)
     A                                      DSPATR(&A26)
     A            D27            2Y 0O  7 32EDTCDE(Z)
     A                                      DSPATR(&A27)
     A            D28            2Y 0O  7 38EDTCDE(Z)
     A                                      DSPATR(&A28)
     A            D29            2Y 0O  8  2EDTCDE(Z)
     A                                      DSPATR(&A29)
     A            D30            2Y 0O  8  8EDTCDE(Z)
     A                                      DSPATR(&A30)
     A            D31            2Y 0O  8 14EDTCDE(Z)
     A                                      DSPATR(&A31)
     A            D32            2Y 0O  8 20EDTCDE(Z)
     A                                      DSPATR(&A32)
     A            D33            2Y 0O  8 26EDTCDE(Z)
     A                                      DSPATR(&A33)
     A            D34            2Y 0O  8 32EDTCDE(Z)
     A                                      DSPATR(&A34)
     A            D35            2Y 0O  8 38EDTCDE(Z)
     A                                      DSPATR(&A35)
     A            D36            2Y 0O  9  2EDTCDE(Z)
     A                                      DSPATR(&A36)
     A            D37            2Y 0O  9  8EDTCDE(Z)
     A                                      DSPATR(&A37)
     A            D38            2Y 0O  9 14EDTCDE(Z)
     A                                      DSPATR(&A38)
     A            D39            2Y 0O  9 20EDTCDE(Z)
     A                                      DSPATR(&A39)
     A            D40            2Y 0O  9 26EDTCDE(Z)
     A                                      DSPATR(&A40)
     A            D41            2Y 0O  9 32EDTCDE(Z)
     A                                      DSPATR(&A41)
     A            D42            2Y 0O  9 38EDTCDE(Z)
     A                                      DSPATR(&A42)
     A            PBCMDKEY       2Y 0B 11  2PSHBTNFLD((*GUTTER 2))
     A                                      PSHBTNCHC(1 'Today' CF10)
     A                                      PSHBTNCHC(2 'ThsMth' CF05)
     A                                      PSHBTNCHC(3 'Back' CA12)
     A          R ASSUME                    ASSUME
     A                                  1  2' '

Display File Notes

Note that the code above shows a bolded 1 and 2 in the left margin:

  1. These are the attribute fields. Notice their length, data type, and usage; they are one-character program-to-system fields.
  2. These are the day fields that will display on the screen. Look at the DSPATR keyword. This is where the field is linked to the corresponding attribute field.

RPG Source (PMTCAL)

      **********************************************************************
      * Program........: PMTCAL                                            *
      * Programmer.....: Doug Eckersley                                    *
      * Date...........: 09/2003                                           *
      *                                                                    *
      * Description....: Date Prompter                                     *
      *                                                                    *
      *====================================================================*
      * Modification Log                                                   *
      *                                                                    *
      * Date       Req  Who      Description                               *
      * ---------- ---- -------- ----------------------------------------- *
      *                                                                    *
      **********************************************************************
     H dftactgrp(*no) option(*nodebugio) datfmt(*iso)

     FPMTCALD   CF   E             WORKSTN INFDS(ScreenInfo)

     D*=====================================================================
     D* Parms
     D*=====================================================================
     D outRes          S              1S 0
     D outDate         S               D
     D outWD           S               N
     D*=====================================================================
     D* Constants
     D*=====================================================================
     D*=====================================================================
     D* Program Status Data Structure
     D*=====================================================================
1    D***/copy DSDS
     D                SDS
     D #Proc             *PROC
     D #Status           *STATUS
     D #PStatus                       5S 0
     D #LineNbr                       8A
     D #Routine          *ROUTINE
     D #Parms            *PARMS
     D #Exception                     7A
     D   #ExcTyp                      3A   OVERLAY(#Exception)
     D   #ExcNbr                      4A   OVERLAY(#Exception:4)
     D #MsgWork               51     80A
     D #Lib                   81     90A
     D #MsgData               91    170A
     D #File                 175    184A
     D #JobName              244    253A
     D #User                 254    263A
     D #JobNbr               264    269S 0
     D #ProcProg             334    343A
     D #ProcMod              344    353A
     D #LineNbr2             354    355I 0
     D*---------------------------------------------------------------
     D* Other Useful Stuff
     D*---------------------------------------------------------------
     D TRUE            C                   *ON
     D FALSE           C                   *OFF
     D*---------------------------------------------------------------
     D OK              S               N
     D Once            S               N   INZ(*ON)
     D Forever         S               N   INZ(*OFF)
     D*---------------------------------------------------------------
 1   D***/end-copy
     D
     D*=====================================================================
     D* Screen Work Area
     D*=====================================================================
     D***/copy DSCREEN
     D CurrScreen      S              2S 0 inz(1)
     D
     D ScreenInfo      DS
     D   CmdKey              369    369A
     D
     D***          Command Keys
     D F3              C                   X'33'
     D F5              C                   X'35'
     D F7              C                   X'37'
     D F8              C                   X'38'
     D F10             C                   X'3A'
     D F12             C                   X'3C'
     D F19             C                   X'B7'
     D F20             C                   X'B8'
     D
2    D***          Attributes
     D atr             S              1A
     D
     D atrNormal       C                   x'20'
     D atrGRN          C                   x'20'
     D atrWHT          C                   x'22'
     D atrRED          C                   x'28'
     D atrTRQ          C                   x'30'
     D atrYLW          C                   x'32'
     D atrPNK          C                   x'38'
     D atrBLU          C                   x'3A'
     D atrND           C                   x'27'
     D
     D atrRI           C                   x'01'
     D atrHI           C                   x'02'
     D atrUL           C                   x'04'
     D
     D atrPR           C                   x'80'
     D*** *** Hi colors (do not use atrHI): WHT, YLW, BLU
     D***/end-copy
     D
     D*IndicNames      DS                  based(InPtr)
     D
     D* User Field Change Control
     D S1              DS
     D   S1MONTH
     D     S1MONTHX                   2A   overlay(S1MONTH)
     D   S1YEAR
     D     S1YEARX                    4A   overlay(S1YEAR)
     D P1              S                   like(S1)
     D
3    D*--- Green
     D aWorkDay        S                   like(atr)
     D*--- Pink, for weekends and holidays
     D aNotWorkDay     S                   like(atr)
     D*=====================================================================
     D* Screen Mapping
     D*=====================================================================
4    D aD              DS
     D   D01
          |
          |
     D   D42
     D   D                                 like(D01) overlay(aD) dim(42)
     D   Da                           2A   overlay(aD) dim(42)
     D
4    D aA              DS
     D   A01
          |
          |
     D   A42
     D   A                                 like(A01) overlay(aA) dim(42)
     D                 DS
     D CSRFLD
     D   CsrDay                       2S 0 overlay(CSRFLD:2)
     D*=====================================================================
     D* Switches
     D*=====================================================================
     D Switches        DS
     D   ErrFound                      N
     D   ChgFound                      N
     D   ForceChg                      N   inz(*off)
     D*=====================================================================
     D* Other Work Areas
     D*=====================================================================
     D SysDate         S               D   inz(*sys)
     D
     D wDate           S               D
     D Dx              S              2S 0
     D Day             S              2S 0
     D
     D MonthN          S              9A   dim(12) ctdata perrcd(1)
     D*=====================================================================
     D* Prototypes
     D*=====================================================================
     D Holiday         S             10A
5    D IsWorkDay       PR                  extpgm('ISWORKDAY')
     D   @Date                         D
     D   @WorkDay                      N
     D***@Holiday                          like(Holiday)
     D*=====================================================================
     D* KLISTS
     D*=====================================================================
     C*****************************************************************
     C*****************************************************************
     C     *entry        plist
     C                   parm                    outRes
     C                   parm                    outDate
     C                   parm                    outWD

      /free
       exsr $inzsr;
       exsr $Main;

       *inlr = *on;

       // ================================================================
       begsr $inzsr;
       // ================================================================
           clear SCRN1;

           exsr $Parms;

6          aWorkDay = %bitor(atrPR:atrNormal);
           aNotWorkDay = %bitor(atrPR:atrPNK);

           exsr $S1Change;
           exsr $S1Edit;

       endsr;

       // ================================================================
       begsr $Parms;
       // ================================================================
           test(e) outDate;
           if (%error)
           or (outDate = *loval);
               outDate = SysDate;
           endif;

           S1MONTH = %subdt(outDate:*m);
           S1YEAR  = %subdt(outDate:*y);

           outRes = *zero;

       endsr;

       // ================================================================
       begsr $Main;
       // ================================================================
           dow CurrScreen > *ZERO;
               select;
               when CurrScreen = 1;
                   exsr $Screen1;
               endsl;
           enddo;

       endsr;

       // ================================================================
       begsr $Screen1;
       //  Main Screen
       // ================================================================
           exsr $S1Show;

           if  (CmdKey = F3)
           or  (CmdKey = F12);
               CurrScreen = *zero;
               leavesr;
           endif;

           if  (CmdKey = F5);
               exsr $ThisMonth;
           endif;

           if  (CmdKey = F10);
               exsr $Today;
               leavesr;
           endif;

           if  (CmdKey = F7);
               exsr $S1DecrMonth;
           endif;

           if  (CmdKey = F8);
               exsr $S1IncrMonth;
           endif;

           if  (CmdKey = F19);
               exsr $S1DecrYear;
           endif;

           if  (CmdKey = F20);
               exsr $S1IncrYear;
           endif;

           exsr $S1Change;
           if ErrFound OR ChgFound;
               exsr $S1Edit;
               leavesr;
           endif;

           exsr $Process;

       endsr;

       // ================================================================
       begsr $S1Show;
       // ================================================================
           exfmt SCRN1;

       endsr;


       // ================================================================
       begsr $ThisMonth;
       // ================================================================
           S1MONTH = %subdt(SysDate:*m);
           S1YEAR  = %subdt(SysDate:*y);
           ForceChg = TRUE;

       endsr;

       // ================================================================
       begsr $Today;
       // ================================================================
           exsr $ThisMonth;
           exsr $S1Load;
           for Dx = 1 to %elem(A);
7              if %bitand(A(Dx):atrRI) = atrRI;
                   leave;
               endif;
           endfor;
           CSRFLD = 'D' + %editc(Dx:'X');
           exsr $Process;

       endsr;

       // ================================================================
       begsr $S1DecrMonth;
       // ================================================================
           S1MONTH -= 1;
           if S1MONTH <= *zero;
               S1MONTH = 12;
               exsr $S1DecrYear;
           endif;

       endsr;

       // ================================================================
       begsr $S1IncrMonth;
       // ================================================================
           S1MONTH += 1;
           if S1MONTH > 12;
               S1MONTH = 1;
               exsr $S1IncrYear;
           endif;

       endsr;

       // ================================================================
       begsr $S1DecrYear;
       // ================================================================
           S1YEAR -= 1;
           if S1YEAR <= *zero;
               S1YEAR = 9999;
           endif;

       endsr;

       // ================================================================
       begsr $S1IncrYear;
       // ================================================================
           if S1YEAR < 9999;
               S1YEAR += 1;
           else;
               S1YEAR = 1;
           endif;

       endsr;

       // ================================================================
       begsr $S1Change;
       // ================================================================
           ChgFound = ForceChg OR (S1 <> P1);
           ForceChg = FALSE;

           P1 = S1;

       endsr;

       // ================================================================
       begsr $S1Edit;
       // ================================================================
           ErrFound = FALSE;
       
           dou Once;
               if S1MONTH <= *zero;
                   exsr $S1DecrMonth;
               endif;
               if S1MONTH > 12;
                   exsr $S1IncrMonth;
               endif;

               if S1YEAR <= *zero;
                   exsr $S1DecrYear;
               endif;

               S1MONTHN = MonthN(S1MONTH);
           enddo;
       // --------------------------------
       
           if NOT ErrFound;
               exsr $S1Load;
           endif;

       endsr;

       // ================================================================
       begsr $S1Load;
       // ================================================================
           D(*) = *zero;
8          A(*) = aWorkDay;

           wDate = %date((S1YEARX+S1MONTHX+'01'):*iso0);
           Dx = %rem(%diff(wDate:d'0001-01-07':*d) : 7);
           Day = *zero;

           dow %subdt(wDate:*m) = S1MONTH;
               Dx  += 1;
               Day += 1;
               D(Dx) = Day;
               IsWorkDay(wDate:OK);
               if  (not OK);
8                  A(Dx) = aNotWorkDay;
               endif;
               if  (wDate = SysDate);
8                  A(Dx) = %bitor(A(Dx):atrRI);
               endif;
               wDate += %days(1);
           enddo;

       endsr;

       // ================================================================
       begsr $Process;
       // ================================================================
           if %subst(CSRFLD:1:1) <> 'D';
               leavesr;
           endif;
           if (D(CsrDay) <= *zero);
               leavesr;
           endif;

           outDate = %date((S1YEARX+S1MONTHX+Da(CsrDay)):*iso0);
           outRes  = %rem(%diff(outDate:d'0001-01-01':*d) : 7) + 1;

           if  (%parms >= 3);
9              outWD = (%bitand(A(CsrDay):aWorkDay) = aWorkDay);
           endif;

           CurrScreen = *zero;

       endsr;

      /end-free

**ctdata MonthN
January
February
March
April
May
June
July
August
September
October
November
December

RPG Program Notes

Again, refer to the bolded numbers in the left column:

  1. The code between D***/copy and D***/end-copy are normally in a copybook.
  2. These are the hexadecimal named constants for the various display attributes. We will create an attribute value by bit manipulation on a color, an effect, and the protect attribute. The color is required, and the effect is optional. The protect attribute is only required for output fields, or input-capable fields you want to protect. There is also a one-character attribute work field defined here.
  3. These are fields that will contain default attribute values. They are defined LIKE the attribute work field. One, aWorkDay, will be used for the workday, and the other, aNotWorkDay, will be used for non-workdays.
  4. The screen day display fields and the corresponding attribute fields are put into an array for easier manipulation. You will need to enter the rest.
  5. You will need to substitute your shop's program to determine if a date is a workday.
  6. Here is where we establish the default attributes. The day display fields are output, so the protect attribute is required. We also establish the appropriate color for each: green (normal) for workdays, pink for non-workdays. These attributes are set using bit manipulation with %bitor.
  7. This subroutine is looking for today among the day fields, by looping through the array of attribute fields. It knows today has been found when the reverse image attribute has been found to be on. %bitand is used to determine if the reverse image attribute is on in the attribute field.
  8. This is where we assign the attribute value to the attribute field. We start by defaulting all the attribute fields to aWorkDay (green). Note that this is a simple assignment. As we loop through, building the calendar, we see if the day is a workday. If it isn't, we assign aNotWorkDay (pink). Again, this is a simple assignment. Also in this loop, if the day is today, we turn on the reverse image effect in the attribute field. %bitor is used, because we are combining reverse image with what is already in the attribute field--protected, green or pink.
  9. This is another check to see if an attribute is on. In this case, we are checking to see if the attribute value in aWorkDay is on.

Other Points to Consider

Attribute fields are ideal for use in subfile records, as there would be no worry about keeping track of attribute indicators, either in the record or in the indicator area.

These same attribute values can be embedded in character fields to allow mixing display attributes (including the non-display attribute) in one field.

In our quest to reduce indicator usage, the use of attribute fields goes a long way toward that goal. They are simple to use, and deriving the attribute values is also simple with bit manipulation. Attribute values are also invaluable when needing to mix attributes in a field, which cannot be done with indicators.

Give them a try.

Doug Eckersley is the iSeries programmer with a premier homebuilder in Columbus. He has been programming on the iSeries for 10 years and has been in the business for 15. He is certified by IBM.

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: