Listing of Source ../source/GOF/GofListContMarkIdentifier.java
package se.entra.phantom.server;

import java.util.Vector;
import java.util.StringTokenizer;

/**
 * This class identifies AS/400 subfile continuation mark.
 * @author J. Bergström
 */
public class GofListContMarkIdentifier extends GofControlIdentifierAdapter
{
  // ------------------
  // INSTANCE VARIABLES
  // ------------------

  /**
   * A list over strings identifying list continuation marks.
   */
  private Vector<String> listContMarks;

  /**
   * The last possible line for a list. This will be the line on which the 
   * continuation mark is placed on.
   */
  private int lastListLine;

  /**
   * The column on the host screen from which to start searching for the 
   * continuation mark. Defaults to 0 (zero).
   */
  private int contMarkStartXpos = 0;

  // ----------------
  // INSTANCE METHODS
  // ----------------

  /**
   * Loads setting for the control from the server ini-file.
   * <p>
   * This class needs to settings from the configuration file. The first setting, 
   * called listcontmark, is used to specify the texts that are valid continuation 
   * marks. A typcal example would be like the one below:
   * <pre>
   *    listcontmark=+,More,MORE
   * </pre>
   * <p>
   * The second setting, called <code>listcontpos</code>, is used to specify from 
   * which column to start search for the continuation mark. This can either be the 
   * real column, or a column relative to the right side. In the later case it is 
   * specified as a negative value.
   * <pre>
   *    listcontpos=-13
   * </pre>
   * In this example the search for the continuation mark would only be done in the 
   * last 13 columns.
   * @param confFile The server ini file.
   * @param subsection The name of the GOF subsection that we are currently loading settings from.
   */
  @Override
  public void getControlSettings( IniFile confFile, String subsection )
  {
    String setting;
    setting = confFile.getData( subsection, "listcontmark" );
    listContMarks = parseIdentifiers( setting );

    setting = confFile.getData( subsection, "listcontpos" );
    if( setting != null )
    {
      try
      {
        contMarkStartXpos = Integer.valueOf( setting ).intValue( );
      }
      catch( NumberFormatException e )
      {
      }
    }
  }

  /**
   * Tries to find a list continuation mark in the area's <code>GofHostFields</code>.
   * <P>
   * A list continuation mark is mark used by the AS/400 as mark at the end of subfile
   * that is displayed to inform the user if there are more list pages in the subfile.
   * Typical list continuation marks are:
   * <pre>
   *   +      (plus sign, created with the Display File option *PLUS)
   *   More   (created with the Display File option *MORE)
   *   Bottom (created with the Display File option *MORE)
   * </pre>
   * If a continuation mark is found, a flag is set to mark this, and the line on which
   * the mark was found is saved as the last line for the list.
   * <P>
   * If a continuation mark has been found, the search will be terminated.
   * @param gofRuntime        The GuiOnTheFlyRuntime instance.
   * @param areaIdentifier    The areaIdentifier in which the entry fields should be identified..
   * @param phantomHostScreen The Phantom host screen corresponding to the host screen.
   * @param hostScreen        The host screen that we are trying to build a GOF panel for.
   * @param newPanel          The newly created Gui-on-the-fly runtime panel.
   */
  @Override
  public void identifyCtrls( GuiOnTheFlyRuntime gofRuntime,
                             GofHostAreaIdentifier areaIdentifier, 
                             PhantomHostScreen phantomHostScreen, 
                             HostScreen hostScreen,
                             PhantomPanelData templPanel, 
                             PhantomPanelData newPanel,
                             int offsetX,
                             int offsetY )
  {
    this.templPanel = templPanel;

    Vector<GofHostField> gofHostFields = areaIdentifier.getAreasGofHostFields( );

    String listContMark = "";

    int hostScreenWidth = hostScreen.getWidth( );
    int cmX;
    if( contMarkStartXpos < 0 )
      cmX = hostScreenWidth + contMarkStartXpos;
    else
      cmX = contMarkStartXpos;

    int s2 = listContMarks.size( );
    lastListLine = 0;

    boolean hasContMark = false;
    for( int i = 0, s = gofHostFields.size( ); i < s; i++ )
    {
      GofHostField gofHostField = gofHostFields.elementAt( i );
      int x = gofHostField.getX( );
      if( gofHostField.isEmpty( ) == false && 
          gofHostField.hasBeenProcessed == false && 
          x >= cmX )
      {
        String text = gofHostField.getText( );
        for( int j = 0; j < s2; j++ )
        {
          String cTxt = listContMarks.elementAt( j );
          String subt = text.substring( text.length( ) -1 );
          if( cTxt.equals( text ) || cTxt.equals( subt ) )
          {
            hasContMark = true;
            listContMark = cTxt;
            lastListLine = gofHostField.getY( );
            gofHostField.hasBeenProcessed = true;
            break;
          }
          else
          {
            int tl = text.length( );
            int cl = cTxt.length( );
            if( tl > cl )
            {
              String sTxt = text.substring( tl - cl );
              if( sTxt.equals( cTxt ) )
              {
                hasContMark = true;
                listContMark = cTxt;
                lastListLine = gofHostField.getY( );
                gofHostField.setText( text.substring( 0, text.length( ) - cTxt.length( ) ) );
                break;
              }
            }
          }
        }

        if( hasContMark == true )
        {
          gofRuntime.setAttribute( "hasListCont", new Boolean( true ) );
          gofRuntime.setAttribute( "lastListLine", new Integer( lastListLine ) );
          gofRuntime.setAttribute( "listContMark", listContMark );
          break;
        }
      }
    }
  }

  /**
   * Parses a value that holds comma separated String items into Vector.
   * @param identifiers The value to parse.
   * @return A Vector containing the items.
   */
  private Vector<String> parseIdentifiers( String identifiers )
  {
    if( identifiers == null || identifiers.isEmpty() )
      return null;

    Vector<String> items = new Vector<String>( );
    StringTokenizer st = new StringTokenizer( identifiers, ", " );
    while( st.hasMoreTokens( ) )
    {
      String item = st.nextToken( );
      if( item != null && !item.equals( "" ) )
        items.addElement( item );
    }
    return items;
  }
}