先日の投稿「画面レコードを構造体で操作する」で5250画面に入力履歴の機能を付けました。10履歴固定で行ったので、今回は動的配列を使って可変でやった場合のサンプルです。
動的記憶域を使う場合は、RPGの命令とBIFを使うか、APIを使うパターンがあります。
今回は命令とBIFを使ったパターンで、前者はデフォルトヒープが使用され、活動化グループに依存します。後者は、ユーザー自身が任意でヒープを作るパターンで、初期サイズや拡張サイズなどをコントロールする事が出来ます。
静的配列と動的配列の2つのプログラムをDSPPGMで確認すると静的記憶域のサイズが若干小さくなってます。
●静的配列
USR400A.rpgle
H****************************************************************
H*-------------------------------*
H*----<<日付・著作権 >>-----*
H*-------------------------------*
H DATEDIT(*YMD)
H COPYRIGHT('(C) CHUBU SYSTEM CO,.LTD 1996 - ')
H*-------------------------------*
H*----<<コンパイル条件 >>-----*
H*-------------------------------*
H DFTACTGRP(*NO) ACTGRP(*NEW)
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(8192)
D BASED(GHST@)
D*
D DUPE S N
D*
D IX S 4S 0 INZ
D HSTNOW S 4S 0 INZ
D*
D NOW S 4S 0 INZ
D ARYMAX S 4S 0 INZ
D EXTEND C 10
D SIZE S 9B 0 INZ
C*-------------------------------*
C*----<<メインルーチン >>-----*
C*-------------------------------*
/FREE
//画面履歴の配列を記憶域に割り振る
ARYMAX += EXTEND ;
SIZE = %SIZE(GHST) * ARYMAX ;
GHST@ = %ALLOC(SIZE) ;
FOR IX = 1 TO ARYMAX ;
CLEAR GHST(IX) ;
ENDFOR ;
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 NOW ;
IF GCUR = GHST(IX) ;
DUPE = *ON ;
GMEMSG = '履歴'
+ %CHAR( NOW -IX + 1 )
+ '回前と同じ内容' ;
LEAVE ;
ENDIF ;
ENDFOR ;
ENDSR ;
//画面内容保存
BEGSR @SAVE ;
NOW += 1 ;
//配列を拡張
IF NOW > ARYMAX ;
ARYMAX += EXTEND ;
SIZE = %SIZE(GHST) * ARYMAX ;
GHST@ = %REALLOC(GHST@ : SIZE) ;
//要素を初期化
FOR IX = NOW TO ARYMAX ;
CLEAR GHST(IX) ;
ENDFOR ;
ENDIF ;
EVAL-CORR GHST( NOW ) = GCUR ;
CLEAR GCUR ;
GMEMSG = '入力内容を保存しました' ;
HSTNOW = *ZERO ;
ENDSR ;
//履歴を取得
BEGSR @GETHST ;
HSTNOW += 1 ;
IF HSTNOW > NOW ;
HSTNOW = 1 ;
ENDIF ;
EVAL-CORR GCUR = GHST( NOW - HSTNOW + 1 ) ;
GMEMSG = '履歴'
+ %CHAR( HSTNOW )
+ '回前の履歴' ;
ENDSR ;
//終了
BEGSR @END ;
//配列の記憶域解放
DEALLOC GHST@ ;
*INLR = *ON ;
RETURN ;
ENDSR ;
/END-FREE