画面レコードを構造体で操作する

#画面レコードを構造体（ＤＳ）で操作する
以前、V5R4のIBMiを使っていた当時、**EVAL-CORR**って素敵な命令が追加された時に、ふと「画面レコードをLIKEREC」出来て、入力した値を保存だとか比較出来たら良いなぁーって思ってた。
で、V7R2にしてからRPGの解説書見ると、V6R1でもう出来る様になっているじゃないの。
RPGってさ、地味ーに進歩しているのよね。最近じゃフリーフォームのRPGを「**FFのRPG**」とか呼んじゃうらしく、これじゃもう**ゲーム**としか誰もが思わなくなるんじゃないの？

画面レコードをＤＳで扱える前は、画面の情報を退避したり一次保存しようとすると、結構しんどかった。

- 鬼の様に変数を定義する
- 鬼の様に画面の保護フィールドを定義する
- MOVEL,MOVE,Z-ADDをフィールド単位に行う

でも、画面レコードをＤＳで扱えると、多くの保存領域が、欲しくてもDIMで配列数を増やす、LIKERECだから、フィールド名は元の画面フィールドのまま、転送はEVAL-CORRでめちゃ簡単。
今までは、画面でＤＢのレコードを呼び出して更新処理をする前に、内容変更がされてない場合は、更新したくないなんてケースは、フィールドを全部チェックしなけりゃならなかった。（※外部記述前提です。内部記述だったら一発比較でＯＫなんて人は知りません）
それもＤＳ同士の比較だけで済むからすごく簡単。
簡単に出来る様になった事をあげると…

+ LIKEREC等で画面レコードを選択できる（コレ事態は以前も出来たかも）
+ DSだから配列にも出来る
+ EXFMTでレコードの後にDS指定できる。（READ、CHAINとかと同じ感じ）
+ DSだからDS同士の比較も出来る。

簡単な画面を作ってみた、入力履歴の呼出と、入力履歴の中に全く同じ内容が居たらエラーになるだけの画面。これだけだけど、項目が馬鹿みたいにある画面だと凄く有用だと思う。

最近のRPG追加機能の事、書こうと思ったけど、こっちの方が業務役立ちそうなので、これにしちゃいました。

![2015-11-27_202618.png](https://qiita-image-store.s3.amazonaws.com/0/100029/e1bd567a-00d2-03e0-aa25-2066fb4f92af.png)

```RPG:USR400FM.DSPF
     A*********************************************************************
     A                                      CHGINPDFT
     A                                      CF03(03)
     A                                      PRINT
     A                                      INDARA
     A*
     A          R GAMEN1
     A                                      OVERLAY PROTECT
     A                                      CF09(09)
     A*
     A                                  1 10'<USR400>'
     A                                  1 22'＊＊　入力履歴呼出+
     A                                      　＊＊'
     A                                      COLOR(WHT)
     A*
     A                                  3  2'-------------------+
     A                                       --------------------+
     A                                       --------------------+
     A                                       -------------------'
     A                                      DSPATR(HI)
     A*
     A                                  4  2'項目１'
     A            GIFLD1         7Y 0B  4 12DSPATR(UL) COLOR(YLW)
     A                                      EDTCDE(4)
     A*
     A                                  6  2'項目２'
     A            GIFLD2        32O  B  6 12DSPATR(UL) COLOR(YLW)
     A*
     A                                  8  2'項目３'
     A            GIFLD3        32O  B  8 12DSPATR(UL) COLOR(YLW)
     A*
     A                                  9  2'-------------------+
     A                                       --------------------+
     A                                       --------------------+
     A                                       -------------------'
     A                                      DSPATR(HI)
     A*
     A          R GAMMSG
     A                                      OVERLAY PROTECT
     A            GMEMSG        60O  O 23  2
     A                                      COLOR(RED)
     A                                 24  2'F3:終了F9:履歴'
```

```RPG:USR400.RPGLE
     H****************************************************************
     H*-------------------------------*
     H*----<<日付・著作権    >>-----*
     H*-------------------------------*
     H DATEDIT(*YMD)
     H COPYRIGHT('(C) USHIDAY - ')
     H*-------------------------------*
     H*----<<コンパイル条件  >>-----*
     H*-------------------------------*
     H DFTACTGRP(*NO)
     F*----<<ファイル定義   >>-----*
     FUSR400FM  CF   E             WORKSTN INDDS(INDICATORS)
     D*-----<<画面フィールド定義>>-----*
     D INDICATORS      DS
     D  KEY@END                        N   OVERLAY(INDICATORS:03)
     D  KEY@HST                        N   OVERLAY(INDICATORS:09)
     D*----<<変数定義 >>-----*
     D*現在の画面レコード
     D GCUR            DS                  LIKEREC(GAMEN1 :*ALL)
     D                                     INZ
     D*画面レコードの履歴
     D GHST            DS                  LIKEREC(GAMEN1 :*ALL)
     D                                     DIM(10)
     D                                     INZ
     D*
     D DUPE            S               N
     D*
     D IX              S              2S 0 INZ
     D*
     D IX2             S              2S 0 INZ(%ELEM(GHST))
     C*-------------------------------*
     C*----<<メインルーチン  >>-----*
     C*-------------------------------*
      /FREE

           DOW 1 = 1        ;
              WRITE GAMMSG      ;
              EXFMT GAMEN1 GCUR ;
              IF KEY@END       ;          //終了
                 LEAVE         ;
              ENDIF            ;
              IF KEY@HST       ;          //履歴取得
                 EXSR  @GETHST ;
                 ITER          ;
              ENDIF            ;

              EXSR  @CHK    ;             //入力チェック
              IF DUPE          ;          //エラー
                 ITER          ;
              ENDIF            ;

              EXSR  @SAVE   ;             //登録
           ENDDO            ;

           EXSR  @END    ;

           //入力チェック
           BEGSR  @CHK      ;
              DUPE = *OFF   ;
              //全く同じ内容があったらエラー
              FOR  IX = 1 TO %ELEM(GHST) ;
                IF GCUR = GHST(IX)   ;
                    DUPE = *ON    ;
                    GMEMSG = '履歴'
                           + %CHAR( ( %ELEM(GHST) + 1 - IX ))
                           + '回前と同じ内容' ;
                    LEAVE   ;
                ENDIF            ;
              ENDFOR           ;
           ENDSR            ;

           //画面内容保存
           BEGSR  @SAVE     ;
             //履歴をずらす
              FOR  IX = 1 TO %ELEM(GHST) -1 ;
                  EVAL-CORR GHST(IX) = GHST(IX+1)   ;
              ENDFOR           ;
              EVAL-CORR GHST( %ELEM(GHST) ) = GCUR  ;
              CLEAR GCUR ;
              GMEMSG = '入力内容を保存しました' ;
              IX2  = %ELEM(GHST) ;
           ENDSR            ;

           //履歴を取得
           BEGSR  @GETHST   ;
              IF  IX2 <= *ZERO ;
                  IX2  = %ELEM(GHST) ;
              ENDIF ;
              EVAL-CORR GCUR = GHST( IX2 )  ;
              GMEMSG = '履歴'
                         + %CHAR( ( %ELEM(GHST) + 1 - IX2 ))
                         + '回前の履歴' ;
              IX2 -= 1 ;
           ENDSR            ;

           //終了
           BEGSR  @END      ;
             *INLR = *ON    ;
              RETURN        ;
           ENDSR            ;

      /END-FREE
```