From: CS_PAUL@GSBVAX.uchicago.edu (Paul Ford 312/702-0335)
Subject: re: Mapping Prev/Next page in 4GL table field
Organization: National Radio Astronomy Observatory
Date: Fri, 4 Sep 1992 20:52:30 GMT

Bruce Momjian writes:

>I have found that the frs key mapping for next/prev page within a table
>field does not work if the table field is not display only.
>
>		set_forms frs (	map(frskey20) = 'pf25',
>				map(frskey21) = 'pf26');
>
>This works only if the field is dislay-only.

Do you have column activations? I'm guessing that you do.

In which case it's not the frskey remapping that's doing it. Tablefield
scrolling doesn't work on tablefields with column activations.

I've been bugged by this problem too and noted with some interest that
it was addressed in a recent INQUIRE_INGRES newsletter (Spring, 1992,
Vol.1  No 4.).  The article was "Scrolling in a Tablefield with Column
Activations" by Rosalind Holland who works in Tech Support. The article
is Expert Note #US-17004, I guess you can use INGRES Advisor to get at
it.

The article says this behavior is due to the fact that activation takes
precedence over scrolling.  This reasoning seems incomplete, since FRS
manages to convert scrolldown and scrollup into one-row tablefield
motions.  Be that as it may, here's how to fix it.

Each column activation for the table in question needs to call a special
procedure in place of a RESUME NEXT, when triggered by a scrolldown or a
scrollup (frs command codes 10 and 11).

Something like this:

field 'table.column' =
{

    /* activation stuff ... */

    inquire_forms frs ( frscommand = command ) ;
    if ( frscommand = 10 or frscommand = 11 ) then
        callproc frs_scroll_page( 'my_form', 'my_table', frscommand ) ;
        RESUME ;
    else
        RESUME NEXT ;
    endif ;
}

Your note has rekindled my interest in this problem.  I've reexamined
the 4GL code outlined in INQUIRE_INGRES and rewritten (and slightly
improved, my version even handles 1-row tablefields :-) it in C so that
I can stick it in one of our tool libraries.  The procedure is attached
below.  It takes three arguments:

        char * form_name
        char * tablefield_name
        int    frscommand_code

all optional. To omit the names, pass either the NULL pointer or empty
string, to omit the command code, pass a 0.  If ommitted the current FRS
values are used.

The INQUIRE_INGRES 4GL procedure required a fourth argument, the dataset
record number, but the C procedure doesn't need it since a 3GL
procedure, unlike a 4GL procedure, can do GETROW(_RECORD) to compute it.

The procedure could be written to take no arguments, but that limits it
to the current form and current field and the current FRS command.
Taking arguments with defaults adds flexibility, the procedure can be
used for  tablefields other than the current one, or after other FRS
commands than just scrollup and scrolldown.

By the way, I've compiled and tested this routine and it works, so far
as I can tell.

Paul Ford
--------------------------------------------------------------------------
GSB Computing Services                  312.702.0335
University of Chicago                   cs_paul@gsbvax.uchicago.edu
1101 E. 58th Street
Chicago IL 60637
--------------------------------------------------------------------------

  --------------------------------<cut here>---------------------------------

/* ----------------------------<scroll_page.sc>----------------------------- */

exec sql INCLUDE SQLCA ;
#include <stdio.h>               /* for NULL */

void frs_scroll_page( const char * this_form
                    , const char * this_tablefield
                    , int frscommand )
{

/* This is a C comment, but declares the function arguments to ESQL. */
#if 1==0
    exec sql begin declare section ;
    char * this_form ;
    char * this_tablefield ;
    int frscommand ;
    exec sql end declare section ;
#endif

#define SCROLLUP   10
#define SCROLLDOWN 11

exec sql BEGIN DECLARE SECTION ;
    int  is_table ;
    int  record ;
    int  rowno ;
    int  maxrow ;
    int  datarows ;
    int  new_record ;
exec sql END DECLARE SECTION ;

char current_form[24+1] ;
char current_tablefield[24+1] ;

/* Compute current values for missing arguments. */

    if ( frscommand <= 0 )
        exec frs inquire_frs frs ( :frscommand = command ) ;

    if ( NULL == this_form || 0==strlen(this_form) )
    {
        this_form = current_form ;
        exec frs inquire_frs form ( :this_form = name ) ;
    }

    if ( NULL == this_tablefield || 0==strlen(this_tablefield) )
    {
        this_tablefield = current_tablefield ;
        exec frs inquire_frs field :this_form ( :this_tablefield = name ) ;
    }

/* Make sure the command is scrollup or down and that we've got a tablefield.
If not, bail out. */

    if ( SCROLLUP != frscommand && SCROLLDOWN != frscommand )
    {
        return ;
    }
    exec frs inquire_frs field :this_form
                               ( :is_table  = table(:this_tablefield) ) ;

    if ( 0 == is_table )
    {
        return ;
    }

/* Get current column, visible row information (current and max), and dataset
record information (current and max). */

    exec frs inquire_frs table :this_form
                               ( :maxrow   = maxrow(:this_tablefield)
                               , :rowno    = rowno(:this_tablefield)
                               , :datarows = datarows(:this_tablefield)
                               ) ;

    exec frs getrow :this_form :this_tablefield ( :record = _RECORD ) ;

/* For SCROLLUP the last visible row will become the first.  For
SCROLLDOWN the first visible row will become the last.  */

    if ( SCROLLUP == frscommand )
    {
        new_record = record + ( maxrow - rowno ) /* last visible record */
                            + maxrow             /* last on next screen*/
                            - 1 ;                /* 1 row overlap */
    }
    else
    {
        new_record = record - ( rowno - 1 )     /* first visible record */
                            - maxrow            /* first on prior screen */
                            + 1 ;               /* 1 row overlap */
    }

/* Handle edge effects and 1-row tablefields. */

    if ( new_record == record )
    {
        if ( SCROLLUP == frscommand ) ++new_record ;
        else                          --new_record ;
    }
    if ( new_record < 1 ) new_record = 1 ;
    if ( new_record > datarows ) new_record = datarows ;

    exec frs SCROLL :this_form :this_tablefield TO :new_record ;
    return ;

} /* end frs_scroll_page */

Newsgroups: comp.databases.ingres,comp.databases.informix,comp.databases,comp.databases.oracle