com.quinsoft.noa.ZGLOBAL1_Operation.java Source code

Java tutorial

Introduction

Here is the source code for com.quinsoft.noa.ZGLOBAL1_Operation.java

Source

/**
This file is part of the Zeidon Java Object Engine (Zeidon JOE).
    
Zeidon JOE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
Zeidon JOE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.
    
You should have received a copy of the GNU Lesser General Public License
along with Zeidon JOE.  If not, see <http://www.gnu.org/licenses/>.
    
Copyright 2009-2010 QuinSoft
**/

package com.quinsoft.noa;

//import java.io.File;
import java.io.IOException;
//import java.lang.Math;
//import java.text.NumberFormat;
//import java.util.*;
import java.nio.CharBuffer;

//import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.mutable.MutableDouble;
import org.apache.commons.lang3.mutable.MutableInt;

//import com.quinsoft.zeidon.ActivateFlags;
import com.quinsoft.zeidon.CursorPosition;
import com.quinsoft.zeidon.TaskQualification;
import com.quinsoft.zeidon.Task;
import com.quinsoft.zeidon.View;
import com.quinsoft.zeidon.vml.VmlOperation;
import com.quinsoft.zeidon.vml.zVIEW;
//import com.quinsoft.zeidon.utils.JoeUtils;
import com.quinsoft.zeidon.zeidonoperations.ZDRVROPR;
import com.quinsoft.zeidon.zeidonoperations.KZOEP1AA;
import com.quinsoft.zeidon.zeidonoperations.ActiveDirectory;

/**
 * @author QuinSoft
 *
 */

public class ZGLOBAL1_Operation extends VmlOperation {
    private final ZDRVROPR m_ZDRVROPR;
    private final KZOEP1AA m_KZOEP1AA;
    private final ActiveDirectory m_ActiveDirectory;

    //public ZGLOBAL1_Operation( TaskQualification taskQual )
    public ZGLOBAL1_Operation(View view) {
        super(view);
        m_ZDRVROPR = new ZDRVROPR(view);
        m_KZOEP1AA = new KZOEP1AA(view);
        m_ActiveDirectory = new ActiveDirectory();
        //private final KZOEP1AA m_KZOEP1AA;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // .Function Name: >>>SetAttributeFromCurrentDateTime
    //
    // .Description: Set an Attribute to Current Date Time
    //
    // .Return Value: int
    //    (Same as SetAttributeFromString() )
    //
    // .Parameter:
    //    Data type       Name        (I/O/U) Description
    //    View            View          (I)   View for Attribute
    //    String          entityName    (I)   Name of Entity
    //    String          attributeName (I)   Name of Attribute
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    // .Detail description
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    public int SetAttributeFromCurrentDateTime(View View, String entityName, String attributeName) {
        String stringTimeStamp = null;
        int rc;

        stringTimeStamp = m_KZOEP1AA.SysGetDateTime(stringTimeStamp);
        rc = SetAttributeFromString(View, entityName, attributeName, stringTimeStamp);
        return rc;
    }

    /*
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // .Function Name: >>>DecimalSumOf
    //
    // .Description: Compute the sum of a double attribute over all
    //               instances of an entity
    //
    // .Return Value: BigDecimal - sum
    //
    // .Parameter:
    //    Datatype        Name            (I/O/U) Description
    //    View            View              (I)   View for Entity
    //    String          entityName        (I)   Name of Entity
    //    String          attributeName     (I)   Name of Attribute
    //    String          stringParentName  (I)   Name of Parent Entity
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    // .Detail description
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    */
    public Double DecimalSumOf(View vSum, String entityName, String attributeName, String stringParentName) {
        Double decimalSum;
        Double decimalValue = null;
        int RESULT;

        decimalSum = 0.0;

        RESULT = SetCursorFirstEntity(vSum, entityName, stringParentName);
        while (RESULT > zCURSOR_UNCHANGED) {
            decimalSum += GetDecimalFromAttribute(decimalValue, vSum, entityName, attributeName);
            RESULT = SetCursorNextEntity(vSum, entityName, stringParentName);
        }

        return decimalSum;
    }

    // Sets the cursor to the latest entity based on a date/time stamp
    // attribute.  The attribute passed should be a date/time stamp, but
    // could be any attribute with ascending collating sequence.
    public int SetCursorLatestEntity(View view, String entityName, String attributeName) {
        OrderEntityForView(view, entityName, attributeName);
        SetCursorLastEntity(view, entityName, "");
        return 0;
    }

    public int GetIntFromAttrByContext(MutableInt lValue, View view, String stringEntity, String stringAttribute,
            String stringContext) {
        int lValueInt = 0;

        lValueInt = GetVariableFromAttribute(lValueInt, 0, zTYPE_INTEGER, 0, view, stringEntity, stringAttribute,
                stringContext, 0);

        lValue.setValue(lValueInt);
        return lValue.intValue();
    }

    public int GetStrFromAttrByContext(StringBuilder sbValue, int lOrigLth, View view, String stringEntity,
            String stringAttribute, String stringContext) {
        MutableInt k = new MutableInt(0);
        int lLth;
        // String  string;

        // If the Context value is null, use the default Context.
        if (lOrigLth < 10000)
            lLth = lOrigLth;
        else
            lLth = 10000;

        if (stringContext == null)
            GetVariableFromAttribute(sbValue, k, zTYPE_STRING, lLth, view, stringEntity, stringAttribute, "",
                    zUSE_DEFAULT_CONTEXT);
        else
            GetVariableFromAttribute(sbValue, k, zTYPE_STRING, lLth, view, stringEntity, stringAttribute,
                    stringContext, 0);

        return k.intValue();
    }

    public int SetAttrFromIntByContext(View view, String stringEntity, String stringAttribute, int lValue,
            String stringContext) {
        int rc;

        rc = SetAttributeFromVariable(view, stringEntity, stringAttribute, lValue, zTYPE_INTEGER, 0, stringContext,
                0);
        return rc;
    }

    public int AddToAttrFromIntByContext(View view, String stringEntity, String stringAttribute, int lValue,
            String stringContext) {
        int rc;

        rc = AddToAttributeFromVariable(view, stringEntity, stringAttribute, lValue, zTYPE_INTEGER, 0,
                stringContext);
        return rc;
    }

    /*
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // .Function name: >>>GetEnvVariable
    //
    // .Description: Get an environment variable
    //
    // .Return value: int
    //    0 - OK
    //    else Error
    //
    // .Parameter:
    //    Data type,      Name             (I/O/U) Description
    //    String          stringReturnWert   (O)   value of the env var (returned)
    //    String          stringVariableName (I)   name of the env var
    //    int             nMaxReturnLth      (I)   max. length of stringReturnWert
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    */
    public String GetEnvVariable(String stringReturnValue, String stringVariableName, int nMaxReturnLth) {
        stringReturnValue = m_KZOEP1AA.SysGetEnvVar(stringReturnValue, stringVariableName, nMaxReturnLth);
        return stringReturnValue;
    }

    /*
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // .Function Name: >>>StrToInt
    //
    // .Description: Convert an String to an Integer
    //
    // .Return Value: int
    //    (Integer Value of String )
    //
    // .Parameter:
    //    Data type,      Name,       (I/O/U) Description
    //    String          stringStr         (I)   String to convert
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    // .Detail description
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    */
    public int StrToInt(String string) {
        return Integer.parseInt(string);
    }

    /*
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // .Function Name: >>>StrToDecimal
    //
    // .Description: Convert an String to a Decimal
    //
    // .Return Value: BigDecimal
    //             0 - OK
    //             else: invalid string
    //
    // .Parameter:
    //    Data type,      Name,       (I/O/U) Description
    //    String          stringStr         (I)   String to convert
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    // .Detail description
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    */
    public Double StrToDecimal(String stringStr) {
        if (stringStr == null)
            return 0.0;

        if (stringStr.equals(""))
            return 0.0;

        return Double.valueOf(stringStr);
    }

    /*
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // .Function Name: >>>CodeToChar
    //
    // .Description: Returns the Char for the given code
    //
    // .Return Value: zVOID
    //
    // .Parameter:
    //    Data type,      Name,       (I/O/U) Description
    //    String          stringStr     (O)   String, which contains the char
    //    int             sCode         (I)   Code for Char
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    // .Detail description
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    */
    public String CodeToChar(String stringStr, int sCode) {
        char[] arrayChar = new char[2];

        arrayChar[0] = (char) (sCode & 0x00ff);
        arrayChar[1] = (char) 0;
        arrayChar[2] = 'x'; // testing to ensure array bounds checking occurs at run time
        return stringStr = arrayChar.toString();
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // .Function Name: >>>CharToCode
    //
    // .Description: Returns the code of the first char in string
    //
    // .Return Value: int - code for char
    //
    // .Parameter:
    //    Data type,      Name,       (I/O/U) Description
    //    String          stringStr         (I)   String with char on first pos
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    // .Detail description
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    public int CharToCode(String stringStr) {
        int nCode = 0;

        nCode = (int) stringStr.charAt(0);
        return nCode;
    }

    public MutableInt GetDateAttributeDifferenceInDays(MutableInt lDays, View srcView, String srcEntityName,
            String srcAttributeName, View tgtView, String tgtEntityName, String tgtAttributeName) {
        DateTimeRecord SourceDate = null;
        DateTimeRecord TargetDate = null;
        String stringSourceDate = null;
        String stringTargetDate = null;
        int lDaysTmp;

        // read the attributes
        stringSourceDate = GetStringFromAttribute(stringSourceDate, srcView, srcEntityName, srcAttributeName);
        stringTargetDate = GetStringFromAttribute(stringTargetDate, tgtView, tgtEntityName, tgtAttributeName);

        UfStringToDateTime(stringSourceDate, SourceDate);
        UfStringToDateTime(stringTargetDate, TargetDate);

        // subtract the values
        lDaysTmp = lDays.intValue();
        lDaysTmp = UfDateTimeDiff(lDaysTmp, TargetDate, SourceDate, zDT_DAY);

        lDays.setValue(lDaysTmp);

        return lDays;
    }

    public int GetEntityNameFromStructure(String stringInternalEntityStructure, StringBuilder returnEntityName) {
        returnEntityName.setLength(0);
        returnEntityName.append(stringInternalEntityStructure);
        return 0;
    }

    public String GetEntityNameFromStructure(String stringInternalEntityStructure, String returnEntityName) {
        // returnEntityName = stringInternalEntityStructure;
        // return returnEntityName;
        return stringInternalEntityStructure;
    }

    public int AddWorkingDaysToDate(View tgtView, String tgtEntityName, String tgtAttributeName, int lWorkingDays) {
        int lRegularDays;
        int lRemainder;
        int nRC;

        // Convert Working Days to Regular Days and add them to a Date Attribute.
        // To determine regular days, we will take working daYS and
        // simply multiply by 7/5, using remainder and not fraction.
        // Thus 8 working days is divided by 5 to get 1 with remainder 3.
        // We multiply the 1 by 7 and add the 3 to get 10.
        lRegularDays = lWorkingDays / 5;
        lRemainder = lWorkingDays - (lRegularDays * 5);
        lRegularDays = (lRegularDays * 7) + lRemainder;

        nRC = AddToAttributeFromVariable(tgtView, tgtEntityName, tgtAttributeName, lRegularDays, zTYPE_INTEGER, 0,
                "Day");
        return nRC;
    }

    public int CompareAttributeByShortString(View view, String entityName, String attributeName,
            String compareValue)

    {
        String stringTempString = null;
        int nLth = 0;
        int nRC;

        stringTempString = GetVariableFromAttribute(stringTempString, nLth, zTYPE_STRING, 254, view, entityName,
                attributeName, "", 0);

        // nLth = stringStringValue.length( );
        nRC = stringTempString.compareTo(compareValue);
        return nRC;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: ActivateWorkObjectFromFile
    //
    // Activate a work object from a file
    //
    public int ActivateWorkObjectFromFile(zVIEW vWorkView, String stringFileName, String stringLOD_Name,
            View ViewToWindow) throws IOException {
        int file;
        int nRC;

        // First make sure the file exists. If not, return an error code.
        file = m_KZOEP1AA.SysOpenFile(ViewToWindow, stringFileName, COREFILE_READ);
        if (file == -1)
            return -1;

        m_KZOEP1AA.SysCloseFile(ViewToWindow, file, 0);

        // Next Activate the OI from the file just created.
        nRC = ActivateOI_FromFile(vWorkView, stringLOD_Name, ViewToWindow, stringFileName, zSINGLE);
        return nRC;

    } // ActivateWorkObjectFromFile

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AddDaysToDate
    //
    // Add Days To a Date Attribute
    //
    public int // TODO
            AddDaysToDate(View view, String entityName, String attributeName, int days) {
        int nRC;

        nRC = AddToAttributeFromVariable(view, entityName, attributeName, days, zTYPE_INTEGER, 0, "Day");
        return nRC;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AddMonthsToDate
    //
    // Add Months To a Date Attribute
    //
    public int // TODO
            AddMonthsToDate(View view, String entityName, String attributeName, int months) // Days or Months?
    {
        int nRC;

        nRC = AddToAttributeFromVariable(view, entityName, attributeName, months, zTYPE_INTEGER, 0, "Month");
        return nRC;
    } // AddDaysToDate

    /**  these do not seem to be used in Zencas ... good thing because of the global buffer usage.
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: ReadLineToLongPointer
    //
    // Read a line passing the pointer back as a LONG
    //
    public int
    ReadLineIntoGlobalBuffer( View  ViewToWindow, int hFile )
    {
       int nRC;
        
       nRC = SysReadLine( ViewToWindow, lpBufferArea, hFile );
        
       return nRC;
        
    } // ReadLineToLongPointer
        
    public int
    SetAttributeFromTabField( View   mCustO,
                          String lpEntityName,
                          String lpAttributeName,
                          int    lFieldPosition )
    {
       StringBuffer sb;
       String lpNext;
       int    k;
       int    nRC;
        
       // Position on field based on Field position, assuming fields are delineated by tabs.
       sb = lpBufferArea;
        
       for ( k = lFieldPosition; k > 1; k-- )
       {
      for ( lpNext = sb; *lpNext != '\t'; lpNext++ )
      {
        ;
      }
        
      sb = lpNext + 1;
       }
        
       // Find next tab to change to string end.
       for ( lpNext = sb; *lpNext != '\t'; lpNext++ )
       {
      ;
       }
        
       *lpNext = 0;
        
       // Set the Attribute value.
       nRC = SetAttributeFromString( mCustO, lpEntityName, lpAttributeName, sb );
        
       // Set string end back to tab.
       *lpNext = '\t';
        
       return nRC;
    }
    **/

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: SeparateName
    //
    // Separate a name into first and last names
    //
    public int SeparateName(String fullName, StringBuilder firstName, StringBuilder lastName) {
        // String lpNext;
        int k = 0;
        int nLth = fullName.length();

        String s = fullName.trim(); // remove whitespace from beginning and end of FullName

        // Eliminate any "Mr." or "Ms." characters in front of the name and then point to first non-blank.
        if (s.charAt(k) == 'M' && (s.charAt(k + 1) == 'r' || s.charAt(k + 1) == 's') && s.charAt(k + 2) == '.') {
            k = 3;
            while (s.charAt(k) == ' ')
                k++;
        }

        // put original string into an array of chars
        //
        // char[] charArray = new char[ nLth + 1 ];  // we are eliminating characters, so this should be plenty of room
        int j = 0;
        int nLastBegin = 0;
        // int nFirstEnd = 0;
        while (k <= nLth) {
            if (nLastBegin == 0) {
                if (s.charAt(k) == ' ' || s.charAt(k) == '\t') {
                    // nFirstEnd = k;
                    firstName.insert(j++, '\0'); // terminate first name
                    nLastBegin = k + 1;

                    // Skip to next non-blank or end of string.
                    while (s.charAt(nLastBegin) == ' ' || s.charAt(nLastBegin) == '\t')
                        nLastBegin++;

                    j = 0; // process last name
                    while (nLastBegin <= nLth)
                        lastName.insert(j++, s.charAt(nLastBegin++));

                    break; // out of outer while loop
                } else {
                    firstName.insert(j++, s.charAt(k++)); // process the First Name (all chars to the first blank)
                }
            }
        }

        return 0;
    } // SeparateName

    /** fortunately these next two methods are not used anywhere
       ////////////////////////////////////////////////////////////////////////////////////////////////////
       //
       //  Method Name: GetViewFromBlobAttribute
       //
       // Get a view from a blob attribute
       //
       public int
       GetViewFromBlobAttribute( View  pvRetrievedView,
                       View  vOI_View,
                       String stringOI_EntityName,
                       String stringOI_AttributeName )
       {
          int nRC;
          int lLth;
        
          lLth = sizeof( vOI_View );
          nRC = GetBlobFromAttribute( pvRetrievedView, lLth, vOI_View, stringOI_EntityName, stringOI_AttributeName );
        
          return 0;
       } // GetViewFromBlobAttribute
        
       ////////////////////////////////////////////////////////////////////////////////////////////////////
       //
       //  Method Name: SetBlobAttributeFromView
       //
       // Set a blob attribute from a view.
       //
       public int
       SetBlobAttributeFromView( View  vOI_View,
                          String stringOI_EntityName,
                          String stringOI_AttributeName,
                          View   ViewToSet )
       {
          int nRC;
        
          nRC = SetAttributeFromBlob( vOI_View, stringOI_EntityName, stringOI_AttributeName,
                               ViewToSet, sizeof( ViewToSet ) );
        
          return nRC;
       } // SetBlobAttributeFromView
    **/

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AddressFormatToMultiLine
    //
    // can be used for display or labels
    //
    public int AddressFormatToMultiLine(String stringMultiLineAddress, String stringLine1, String stringLine2,
            String stringLine3, String stringCity, String stringState, String stringPostalCode) {
        String stringFirstPart = null;

        if (stringLine1.isEmpty() == false)
            stringFirstPart = zsprintf(stringFirstPart, "%s\n", stringLine1);

        if (stringLine2.isEmpty() == false)
            stringFirstPart = zsprintf(stringFirstPart, "%s%s\n", stringFirstPart, stringLine2);

        if (stringLine3.isEmpty() == false)
            stringFirstPart = zsprintf(stringFirstPart, "%s%s\n", stringFirstPart, stringLine3);

        stringMultiLineAddress = zsprintf(stringMultiLineAddress, "%s\n%s, %s %s", stringFirstPart, stringCity,
                stringState, stringPostalCode);
        return 0;
    } // AddressFormatToMultiLine

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: dAdressLabel
    //
    // multiline address (without name)
    //
    public String fnAdressLabelText(View vAnyObject, // BASED ON LOD "any object with entity that has address attributes"
            String stringInternalEntityStructure, String stringInternalAttribStructure, String stringReturnText) {
        String entityName = null;
        String stringAttribName = null;
        String stringMultiLineAddress = null;
        StringBuilder sb = new StringBuilder("");
        String stringAttn = null;
        String stringCity = null;
        String stringState = null;
        String stringZipCode = null;
        String stringZipCodeFormatted = null;
        String stringCountry = null;
        StringBuilder stringSep = null; // set to /r/n or "; "

        zstrcpy(entityName, stringInternalEntityStructure);
        zstrcpy(stringAttribName, stringInternalAttribStructure);
        if (ZeidonStringCompare(stringAttribName, 1, 5, "dLine", 1, 5, 33) == 0)
            zstrcpy(stringSep, "; ");
        else
            zstrcpy(stringSep, "\r\n");

        stringMultiLineAddress = "";
        stringAttn = "";
        sb.setCharAt(0, '\0');

        if (IsValidAttribute("AttentionLine1", stringInternalEntityStructure) == 0)
            GetStringFromAttribute(sb, vAnyObject, entityName, "AttentionLine1");

        if (sb.length() != 0) {
            stringAttn = zsprintf(stringAttn, "Attn:  %s%s", sb, stringSep);
            sb.setCharAt(0, '\0');
        }

        if (IsValidAttribute("AttentionLine2", stringInternalEntityStructure) == 0)
            GetStringFromAttribute(sb, vAnyObject, entityName, "AttentionLine2");

        if (sb.length() != 0) {
            stringAttn = zsprintf(stringAttn, "%s         %s%s", stringAttn, sb, stringSep);
            sb.setCharAt(0, '\0');
        }

        if (stringAttn.length() != 0)
            ZeidonStringCopy(stringMultiLineAddress, 1, 0, stringAttn, 1, 0, 2000);

        if (IsValidAttribute("Line1", stringInternalEntityStructure) == 0)
            GetStringFromAttribute(sb, vAnyObject, entityName, "Line1");

        if (sb.length() != 0)
            zsprintf(stringMultiLineAddress, "%s%s%s", stringMultiLineAddress, sb, stringSep);

        if (IsValidAttribute("Line2", stringInternalEntityStructure) == 0)
            GetStringFromAttribute(sb, vAnyObject, entityName, "Line2");
        else
            sb.setCharAt(0, '\0');

        if (sb.length() != 0)
            stringMultiLineAddress = zsprintf(stringMultiLineAddress, "%s%s%s", stringMultiLineAddress, sb,
                    stringSep);

        if (IsValidAttribute("Line3", stringInternalEntityStructure) == 0)
            GetStringFromAttribute(sb, vAnyObject, entityName, "Line3");
        else
            sb.setCharAt(0, '\0');

        if (sb.length() != 0)
            stringMultiLineAddress = zsprintf(stringMultiLineAddress, "%s%s%s", stringMultiLineAddress, sb,
                    stringSep);

        stringCity = GetStringFromAttribute(stringCity, vAnyObject, entityName, "City");
        //GetStringFromAttribute( stringState, vAnyObject, entityName, "State" );
        stringState = GetVariableFromAttribute(stringState, 0, zTYPE_STRING, 120, vAnyObject, entityName,
                "StateProvince", "State", 0);
        if (stringState.length() == 0) {
            if (IsValidAttribute("InternationalRegion", stringInternalEntityStructure) == 0)
                stringState = GetVariableFromAttribute(stringState, 0, zTYPE_STRING, 120, vAnyObject, entityName,
                        "InternationalRegion", "", 0);
        }

        // For ZipCodes larger than five characters, we want to format them with a
        // dash, if they don't already have a dash.
        stringZipCode = GetVariableFromAttribute(stringZipCode, 0, zTYPE_STRING, 11, vAnyObject, entityName,
                "PostalCode", "", 0);
        if (stringZipCode.length() > 5 && stringZipCode.charAt(5) != '-')
            stringZipCodeFormatted = stringZipCode.substring(0, 4) + "-" + stringZipCode.substring(5, -1);
        else
            stringZipCodeFormatted = stringZipCode;

        stringCountry = "";
        if (IsValidAttribute("Country", stringInternalEntityStructure) == 0)
            GetStrFromAttrByContext(sb, 50, vAnyObject, entityName, "Country", "Country");

        if (sb.equals("US") == true)
            stringCountry = "";
        else
            stringCountry = sb.toString();

        if (stringCity.length() != 0)
            stringMultiLineAddress = zsprintf(stringMultiLineAddress, "%s%s, %s %s %s", stringMultiLineAddress,
                    stringCity, stringState, stringZipCodeFormatted, stringCountry);
        else
            stringMultiLineAddress = zsprintf(stringMultiLineAddress, "%s%s %s %s", stringMultiLineAddress,
                    stringState, stringZipCodeFormatted, stringCountry);

        stringReturnText = ZeidonStringCopy(stringReturnText, 1, 0, stringMultiLineAddress, 1, 0, 255);

        return stringReturnText;
    } // fnAdressLabelText

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: dAdressLabel
    //
    // multiline address (without name)
    //
    public int /* DERIVED ATTRIBUTE */
            dAdressLabel(View vAnyObject, // BASED ON LOD "any object with entity that has address attributes"
                    String stringInternalEntityStructure, String stringInternalAttribStructure, int nGetOrSetFlag) {
        String stringMultiLineAddress = null;
        String entityName = null;

        entityName = zstrcpy(entityName, stringInternalEntityStructure);
        if (CheckExistenceOfEntity(vAnyObject, entityName) != 0) {
            return 0;
        }

        stringMultiLineAddress = fnAdressLabelText(vAnyObject, stringInternalEntityStructure,
                stringInternalAttribStructure, stringMultiLineAddress);

        StoreStringInRecord(vAnyObject, stringInternalEntityStructure, stringInternalAttribStructure,
                stringMultiLineAddress);

        return 0;
    } // dAdressLabel

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: dAdressLabel
    //
    // multiline address (with name)
    //
    public int /* DERIVED ATTRIBUTE */
            dAdressLabelFull(View vAnyObject, // BASED ON LOD "any object with entity that has address attributes"
                    String stringInternalEntityStructure, String stringInternalAttribStructure, int nGetOrSetFlag) {
        String entityName = null;
        String stringMultiLineAddress;
        String string = null;
        String stringCompanyName;

        entityName = zstrcpy(entityName, stringInternalEntityStructure);
        if (CheckExistenceOfEntity(vAnyObject, entityName) != 0) {
            return 0;
        }

        stringMultiLineAddress = "";
        stringCompanyName = "";
        if (IsValidAttribute("CompanyName", stringInternalEntityStructure) == 0)
            stringCompanyName = GetStringFromAttribute(stringCompanyName, vAnyObject, entityName, "CompanyName");

        if (stringCompanyName.length() != 0)
            stringMultiLineAddress = zsprintf(stringMultiLineAddress, "%s\r\n", stringCompanyName);

        string = fnAdressLabelText(vAnyObject, stringInternalEntityStructure, stringInternalAttribStructure,
                string);

        stringMultiLineAddress = ZeidonStringConcat(stringMultiLineAddress, 1, 0, string, 1, 0, 2000);

        StoreStringInRecord(vAnyObject, stringInternalEntityStructure, stringInternalAttribStructure,
                stringMultiLineAddress);

        return 0;
    } // dAdressLabelFull

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: PersonName_LastFirstMiddle
    //
    // Person's name formatted Last Name first
    //
    public int /* DERIVED ATTRIBUTE */
            PersonName_LastFirstMiddle(View vAnyObject, // BASED ON LOD "any object with entity that has "NAME" attributes"
                    String stringInternalEntityStructure, String stringInternalAttribStructure, int nGetOrSetFlag) {
        String stringLastFirstMiddle;
        String entityName = null;
        String string;

        entityName = zstrcpy(entityName, stringInternalEntityStructure);
        stringLastFirstMiddle = "";
        string = "";

        // Last Name
        if (IsValidAttribute("LastName", stringInternalEntityStructure) == 0)
            stringLastFirstMiddle = GetStringFromAttribute(stringLastFirstMiddle, vAnyObject, entityName,
                    "LastName");

        // First Name
        if (IsValidAttribute("FirstName", stringInternalEntityStructure) == 0)
            string = GetStringFromAttribute(string, vAnyObject, entityName, "FirstName");

        if (string.length() != 0) {
            stringLastFirstMiddle = ZeidonStringConcat(stringLastFirstMiddle, 1, 0, ", ", 1, 0, 101);
            stringLastFirstMiddle = ZeidonStringConcat(stringLastFirstMiddle, 1, 0, string, 1, 0, 101);
            string = "";
        }

        // Middle Name
        if (IsValidAttribute("MiddleName", stringInternalEntityStructure) == 0)
            string = GetStringFromAttribute(string, vAnyObject, entityName, "MiddleName");

        if (string.length() != 0) {
            stringLastFirstMiddle = ZeidonStringConcat(stringLastFirstMiddle, 1, 0, " ", 1, 0, 101);
            stringLastFirstMiddle = ZeidonStringConcat(stringLastFirstMiddle, 1, 0, string, 1, 0, 101);
            if (string.length() == 1)
                stringLastFirstMiddle = ZeidonStringConcat(stringLastFirstMiddle, 1, 0, ".", 1, 0, 101);

            string = "";
        }

        // Suffix
        if (IsValidAttribute("Suffix", stringInternalEntityStructure) == 0)
            string = GetStringFromAttribute(string, vAnyObject, entityName, "Suffix");

        if (zstrlen(string) != 0) {
            stringLastFirstMiddle = ZeidonStringConcat(stringLastFirstMiddle, 1, 0, " ", 1, 0, 101);
            stringLastFirstMiddle = ZeidonStringConcat(stringLastFirstMiddle, 1, 0, string, 1, 0, 101);
            string = "";
        }

        StoreStringInRecord(vAnyObject, stringInternalEntityStructure, stringInternalAttribStructure,
                stringLastFirstMiddle);

        return 0;
    } // dAdressLabel

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: PersonName_FirstMiddleLast
    //
    // Person's name formatted Last Name last
    //
    public int /* DERIVED ATTRIBUTE */
            PersonName_FirstMiddleLast(View vAnyObject, // BASED ON LOD "any object with entity that has "NAME" attributes"
                    String stringInternalEntityStructure, String stringInternalAttribStructure, int nGetOrSetFlag) {
        StringBuilder stringReturnName = new StringBuilder();
        String entityName = null;
        StringBuilder string = new StringBuilder();

        entityName = zstrcpy(entityName, stringInternalEntityStructure);
        stringReturnName.append("");
        string.append("");

        // Last Name
        if (IsValidAttribute("FirstName", stringInternalEntityStructure) == 0)
            GetStringFromAttribute(stringReturnName, vAnyObject, entityName, "FirstName");

        // Middle Name
        if (IsValidAttribute("MiddleName", stringInternalEntityStructure) == 0)
            GetStringFromAttribute(string, vAnyObject, entityName, "MiddleName");
        if (zstrlen(string) != 0) {
            ZeidonStringConcat(stringReturnName, 1, 0, " ", 1, 0, 101);
            ZeidonStringConcat(stringReturnName, 1, 0, string, 1, 0, 101);
            if (zstrlen(string) == 1)
                ZeidonStringConcat(stringReturnName, 1, 0, ".", 1, 0, 101);

            string.append("");
        }

        // Last Name
        if (IsValidAttribute("LastName", stringInternalEntityStructure) == 0)
            GetStringFromAttribute(string, vAnyObject, entityName, "LastName");

        if (zstrlen(string) != 0) {
            ZeidonStringConcat(stringReturnName, 1, 0, " ", 1, 0, 101);
            ZeidonStringConcat(stringReturnName, 1, 0, string, 1, 0, 101);
            string.append("");
        }

        // Suffix
        if (IsValidAttribute("Suffix", stringInternalEntityStructure) == 0)
            GetStringFromAttribute(string, vAnyObject, entityName, "Suffix");

        if (zstrlen(string) != 0) {
            ZeidonStringConcat(stringReturnName, 1, 0, " ", 1, 0, 101);
            ZeidonStringConcat(stringReturnName, 1, 0, string, 1, 0, 101);
            string.append("");
        }

        StoreStringInRecord(vAnyObject, stringInternalEntityStructure, stringInternalAttribStructure,
                stringReturnName.toString());

        return 0;
    } // dAdressLabel

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: zTrim
    //
    // trim whitespace from front and back
    //
    // Remove whitespace at the beginning and end of a string.
    //
    public int zTrim(StringBuilder stringStringInOut) {
        String s = stringStringInOut.toString().trim();
        stringStringInOut.replace(0, -1, s);
        return 0;
    } // zTrim

    public String zTrim(String stringStringInOut) {
        return stringStringInOut.trim();
    } // zTrim

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: SetDecimalPrecisionRounded
    //
    public Double SetDecimalPrecisionRounded(Double pdDecimalValue, int ulNumberOfDecimals) {
        StringBuilder sb = new StringBuilder(ulNumberOfDecimals > 0 ? ulNumberOfDecimals + 5 : 25);

        SysConvertDecimalToString(pdDecimalValue, sb, (int) ulNumberOfDecimals);
        MutableDouble d = new MutableDouble(pdDecimalValue);
        SysConvertStringToDecimal(sb.toString(), d);
        return d.toDouble();

    } // SetDecimalPrecisionRounded

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: RemoveLeadingBlanksFromAttrib
    //
    public int RemoveLeadingBlanksFromAttrib(View view, String stringEntity, String stringAttribute) {
        StringBuilder sb = new StringBuilder(256);
        MutableInt i = new MutableInt(0);
        int k;

        // Remove any leading blanks from the attribute.

        GetVariableFromAttribute(sb, i, zTYPE_STRING, 253, view, stringEntity, stringAttribute, "", 0);
        if (sb.charAt(0) == ' ') {
            k = 1;

            while (sb.charAt(k) == ' ')
                k++;

            SetAttributeFromString(view, stringEntity, stringAttribute, sb.substring(k));
        }

        return 0;

    } // RemoveLeadingBlanksFromAttrib

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: RemoveLeadingZerosFromAttrib
    //
    public int RemoveLeadingZerosFromAttrib(View view, String stringEntity, String stringAttribute) {
        StringBuilder sb = new StringBuilder(256);
        MutableInt i = new MutableInt(0);
        int k;

        // Remove any leading zeros from the attribute.

        GetVariableFromAttribute(sb, i, zTYPE_STRING, 253, view, stringEntity, stringAttribute, "", 0);
        if (sb.charAt(0) == '0') {
            k = 1;

            while (sb.charAt(k) == '0')
                k++;

            SetAttributeFromString(view, stringEntity, stringAttribute, sb.substring(k));
        }

        return 0;

    } // RemoveLeadingZerosFromAttrib

    /** doesn't seem to be used in Zencas (that's a good thing).
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: GetButtonHeaderName
    //
    // this can only be used inside the button action for the new list box
    //
    public String
    GetButtonHeaderName( View   ViewToWindow,
                     String stringButtonHeaderName )
    {
        
       zstrcpy( stringButtonHeaderName, ( (String) GetActionParameters( ViewToWindow ) ) );
       //stringButtonHeaderName = (String) GetActionParameters( ViewToWindow );
        
       return 0;
        
    } // GetButtonHeaderName
        
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: GetWindowsUserName
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public String
    GetWindowsUserName( String stringUserName,
                    int ulMaxLengthOfName )
    {
       int lth;
        
       lth = ulMaxLengthOfName;
        
       if ( GetUserName( stringUserName, lth ) == 0 )
      stringUserName = "";
        
       return stringUserName;
    } // GetWindowsUserName
        
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: CallObjectOperation
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int
    CallObjectOperation( View   returnView,
                     View   ViewToWindow,
                     String stringObject,
                     String stringOperationName )
    {
       String stringOperation;
       String stringPrefix;
       zFARPROC_DYNOBJ lpfnDynRoutine;
       int  nRC = -1;
       LPLIBRARY hLibrary;
        
       hLibrary = 0;
        
       zstrcpy( stringPrefix, "o" );
       zstrcat( stringPrefix, stringObject );
       zstrcat( stringPrefix, "_" );
        
       zstrcpy( stringOperation, stringPrefix );
       zstrcat( stringOperation, stringOperationName );
        
       lpfnDynRoutine = (zFARPROC_DYNOBJ)
      GetOperationDynamicCallAddress( ViewToWindow, &hLibrary,
                                      "LODOPS_R", stringOperation, "Reports" );
       if ( lpfnDynRoutine )
       {
      nRC = (*lpfnDynRoutine)( returnView, (View ) ViewToWindow );
       }
        
       return nRC;
        
    } // CallObjectOperation
        
    // FindItemByName - enumerates the subkeys of a given key and the associated
    //    values.
    // hKey - key whose subkeys and values are to be enumerated
        
    public String
    FindItemByName( HKEY    hKey,
                String  stringValueName,
                DWORD   dwReturnType,
                String  stringReturnData,
                DWORD   dwMaxReturnLth )
    {
       char     stringKey;
       char     stringClass = "";           // buffer for class name
       DWORD    dwClassName = MAX_PATH;     // length of class string
       DWORD    dwSubKeys;                  // number of subkeys
       DWORD    dwMaxSubKey;                // longest subkey size
       DWORD    dwMaxClass;                 // longest class string
       DWORD    dwValues;                   // number of values for key
       DWORD    dwMaxValue;                 // longest value name
       DWORD    dwMaxValueData;             // longest value data
       DWORD    dwSecurityDescriptor;       // size of security descriptor
       DWORD    dwType;
       FILETIME ftLastWriteTime;            // last write time
        
       DWORD k, j;
       DWORD dwRC;
       int lRC;
       zBOOL bFound = FALSE;
        
       char  stringValue;
       DWORD dwValue = MAX_PATH;
       char  stringBuff;
        
       // Get the class name and the value count.
       RegQueryInfoKey( hKey,                  // key handle
                    stringClass,           // buffer for class name
                    dwClassName,          // length of class string
                    null,                  // reserved
                    &dwSubKeys,            // number of subkeys
                    &dwMaxSubKey,          // longest subkey size
                    &dwMaxClass,           // longest class string
                    &dwValues,             // number of values for this key
                    &dwMaxValue,           // longest value name
                    &dwMaxValueData,       // longest value data
                    &dwSecurityDescriptor, // security descriptor
                    &ftLastWriteTime );    // last write time
        
       // Enumerate the child keys, looping until RegEnumKey fails. Then
       // get the name of each child key and copy it into the list box.
       SetCursor( LoadCursor( null, IDC_WAIT ) );
       for ( k = 0, dwRC = ERROR_SUCCESS; dwRC == ERROR_SUCCESS; k++ )
       {
      dwRC = RegEnumKey( hKey, k, stringKey, MAX_PATH );
      //if ( dwRC == (DWORD) ERROR_SUCCESS )
      //{
      //   TraceLineS( "IDE_CLASS?: ", stringKey );
      //}
       }
        
       SetCursor( LoadCursor( null, IDC_ARROW ) );
        
       // Enumerate the key values.
       SetCursor( LoadCursor( null, IDC_WAIT ) );
        
       if ( dwValues )
       {
      for ( j = 0, dwRC = ERROR_SUCCESS; j < dwValues; j++ )
      {
         dwValue = MAX_PATH;
         stringValue = "";
         dwRC = RegEnumValue( hKey, j, stringValue,
                              &dwValue,
                              null,
                              &dwType, // &dwType,
                              null,    // &bData,
                              null );  // &bcData
        
         if ( dwRC != (DWORD) ERROR_SUCCESS &&
              dwRC != ERROR_INSUFFICIENT_BUFFER )
         {
            wsprintf( stringBuff,
                      "Line:%d 0 based index = %d, dwRC = %d, "
                      "ValueLen = %d",
                      __LINE__, j, dwRC, dwValue );
            //TraceLineS( "Debug", stringBuff );
         }
        
         stringBuff = "";
        
         if ( dwType == dwReturnType && zstrcmp( stringValueName, stringValue ) == 0 )
         {
            bFound = TRUE;
        
            lRC = RegQueryValueEx( hKey,               // handle to key
                                   stringValue,
                                   0,                  // reserved must be null
                                   &dwType,            // value type
                                   (LPBYTE) stringReturnData, // data buffer
                                   &dwMaxReturnLth );  // data buffer size
            if ( zstrlen( stringValue ) == 0 )
               zstrcpy( stringValue, "(Default)" );
        
            //TraceLineS( "Found Key ===> ", stringValue );
            break;
         }
        
         // Add each value to a list box.
         if ( zstrlen( stringValue ) == 0 )
            zstrcpy( stringValue, "(Default)" );
        
         wsprintf( stringBuff, "%d) %s ", j, stringValue );
         // TraceLineS( "???:  ", stringBuff );
      }
       }
        
       SetCursor( LoadCursor( null, IDC_ARROW ) );
       return bFound );
    }
        
    public String
    GetRegistryImagingValue( String stringValueName,
                         String stringCLSID_ID,
                         DWORD   dwReturnType,
                         String  stringReturnData,
                         DWORD   dwMaxReturnLth )
    {
       HKEY  hConnect;
       HKEY  hClassesRoot;
       HKEY  hSoftware;
       HKEY  hKeyClasses;
       HKEY  hKeyCLSID;
       HKEY  hKeyID;
       HKEY  hKeyLocalServer;
       int nRC = -1;
        
       *stringReturnData = 0;  // initialize
        
       int lRC = RegConnectRegistry( null, HKEY_LOCAL_MACHINE, &hConnect );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegConnectRegistry", " failed"  );
      return nRC;
       }
        
       // open the local key
       lRC = RegOpenKeyEx( HKEY_LOCAL_MACHINE, 0, 0, KEY_READ, &hClassesRoot );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx HKEY_LOCAL_MACHINE", " failed"  );
      return nRC;
       }
        
       lRC = RegOpenKeyEx( hClassesRoot, "Software", 0, KEY_READ, &hSoftware );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx hSoftware", " failed"  );
      return nRC;
       }
        
       // get thr CLSID here
       lRC = RegOpenKeyEx( hSoftware, "Classes", 0, KEY_READ, &hKeyClasses );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx Classes", " failed"  );
      return nRC;
       }
        
       // get thr CLSID here
       lRC = RegOpenKeyEx( hKeyClasses, "CLSID", 0, KEY_READ, &hKeyCLSID );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx CLSID", " failed"  );
      return nRC;
       }
        
       // get thr CLSID here
       lRC = RegOpenKeyEx( hKeyCLSID, stringCLSID_ID, 0, KEY_READ, &hKeyID );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx hKeyID", " failed"  );
      return nRC;
       }
        
       lRC = RegOpenKeyEx( hKeyID, "LocalServer32", 0, KEY_READ, &hKeyLocalServer );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx hKeyLocalServer", " failed"  );
      return nRC;
       }
        
       nRC = FindItemByName( hKeyLocalServer, stringValueName, dwReturnType,
                         stringReturnData, dwMaxReturnLth );
       return nRC;
    }
        
    public String
    GetRegistryImagingPrintValue( String stringValueName,
                              String stringCLSID_ID,
                              DWORD   dwReturnType,
                              String  stringReturnData,
                              DWORD   dwMaxReturnLth )
    {
       HKEY  hConnect;
       HKEY  hClassesRoot;
       HKEY  hSoftware;
       HKEY  hKeyShell;
       HKEY  hKeyClasses;
       HKEY  hKeyPrint;
       HKEY  hKeyCommand;
       HKEY  hKeyTif;
       int nRC = -1;
        
       *stringReturnData = 0;  // initialize
        
       int lRC = RegConnectRegistry( null, HKEY_LOCAL_MACHINE, &hConnect );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegConnectRegistry", " failed"  );
      return nRC;
       }
        
       // open the local key
       lRC = RegOpenKeyEx( HKEY_LOCAL_MACHINE, 0, 0, KEY_READ, &hClassesRoot );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx HKEY_LOCAL_MACHINE", " failed"  );
      return nRC;
       }
        
       lRC = RegOpenKeyEx( hClassesRoot, "Software", 0, KEY_READ, &hSoftware );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx hSoftware", " failed"  );
      return nRC;
       }
        
       // get thr CLSID here
       lRC = RegOpenKeyEx( hSoftware, "Classes", 0, KEY_READ, &hKeyClasses );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx Classes", " failed"  );
      return nRC;
       }
        
       // get the TIF.Document here
       lRC = RegOpenKeyEx( hKeyClasses, "TIFImage.Document", 0, KEY_READ, &hKeyTif );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx TIF.Docuement", " failed"  );
      return nRC;
       }
        
       // get the shell here
       lRC = RegOpenKeyEx( hKeyTif, "shell", 0, KEY_READ, &hKeyShell );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx shell", " failed"  );
      return nRC;
       }
        
       // get the print key here
       lRC = RegOpenKeyEx( hKeyShell, "print", 0, KEY_READ, &hKeyPrint );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx print:", ":failed"  );
      return nRC;
       }
        
       lRC = RegOpenKeyEx( hKeyPrint, "command", 0, KEY_READ, &hKeyCommand );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx command ", " failed"  );
      return nRC;
       }
        
       nRC = FindItemByName( hKeyCommand, stringValueName, dwReturnType,
                         stringReturnData, dwMaxReturnLth );
        
       TraceLineS( stringValueName, stringReturnData );
        
       return nRC;
    }
        
    public String
    GetRegistryImagingViewValue( String stringValueName,
                             String stringCLSID_ID,
                             DWORD   dwReturnType,
                             String  stringReturnData,
                             DWORD   dwMaxReturnLth )
    {
       HKEY  hConnect;
       HKEY  hClassesRoot;
       HKEY  hSoftware;
       HKEY  hKeyShell;
       HKEY  hKeyClasses;
       HKEY  hKeyPrint;
       HKEY  hKeyCommand;
       HKEY  hKeyTif;
       int nRC = -1;
        
       *stringReturnData = 0;  // initialize
        
       int lRC = RegConnectRegistry( null, HKEY_LOCAL_MACHINE, &hConnect );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegConnectRegistry", " failed"  );
      return nRC;
       }
        
       // open the local key
       lRC = RegOpenKeyEx( HKEY_LOCAL_MACHINE, 0, 0, KEY_READ, &hClassesRoot );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx HKEY_LOCAL_MACHINE", " failed"  );
      return nRC;
       }
        
       lRC = RegOpenKeyEx( hClassesRoot, "Software", 0, KEY_READ, &hSoftware );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx hSoftware", " failed"  );
      return nRC;
       }
       // get thr CLSID here
       lRC = RegOpenKeyEx( hSoftware, "Classes", 0, KEY_READ, &hKeyClasses );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx Classes", " failed"  );
      return nRC;
       }
       // get the TIF.Document here
       lRC = RegOpenKeyEx( hKeyClasses, "TIFImage.Document", 0, KEY_READ, &hKeyTif );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx TIF.Docuement", " failed"  );
      return nRC;
       }
       // get the shell here
       lRC = RegOpenKeyEx( hKeyTif, "shell", 0, KEY_READ, &hKeyShell );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx shell", " failed"  );
      return nRC;
       }
       // get the print key here
       lRC = RegOpenKeyEx( hKeyShell, "open", 0, KEY_READ, &hKeyPrint );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx open:", ":failed"  );
      return nRC;
       }
       lRC = RegOpenKeyEx( hKeyPrint, "command", 0, KEY_READ, &hKeyCommand );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx command ", " failed"  );
      return nRC;
       }
        
       nRC = FindItemByName( hKeyCommand, stringValueName, dwReturnType,
                         stringReturnData, dwMaxReturnLth );
       TraceLineS( stringValueName, stringReturnData );
        
       return nRC;
    }
        
    public String
    GetRegistryHTMLViewValue( String stringValueName,
                          String stringCLSID_ID,
                          DWORD   dwReturnType,
                          String  stringReturnData,
                          DWORD   dwMaxReturnLth )
    {
       HKEY  hConnect;
       HKEY  hClassesRoot;
       HKEY  hSoftware;
       HKEY  hKeyShell;
       HKEY  hKeyClasses;
       HKEY  hKeyPrint;
       HKEY  hKeyCommand;
       HKEY  hKeyHtml;
       int nRC = -1;
        
       *stringReturnData = 0;  // initialize
        
       int lRC = RegConnectRegistry( null, HKEY_LOCAL_MACHINE, &hConnect );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegConnectRegistry", " failed"  );
      return nRC;
       }
        
       // open the local key
       lRC = RegOpenKeyEx( HKEY_LOCAL_MACHINE, 0, 0, KEY_READ, &hClassesRoot );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx HKEY_LOCAL_MACHINE", " failed"  );
      return nRC;
       }
        
       lRC = RegOpenKeyEx( hClassesRoot, "Software", 0, KEY_READ, &hSoftware );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx hSoftware", " failed"  );
      return nRC;
       }
       // get thr CLSID here
       lRC = RegOpenKeyEx( hSoftware, "Classes", 0, KEY_READ, &hKeyClasses );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx Classes", " failed"  );
      return nRC;
       }
       // get the hKeyHtml here
       lRC = RegOpenKeyEx( hKeyClasses, "htmlfile", 0, KEY_READ, &hKeyHtml );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx htmlfile", " failed"  );
      return nRC;
       }
       // get the shell here
       lRC = RegOpenKeyEx( hKeyHtml, "shell", 0, KEY_READ, &hKeyShell );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx shell", " failed"  );
      return nRC;
       }
       // get the print key here
       lRC = RegOpenKeyEx( hKeyShell, "open", 0, KEY_READ, &hKeyPrint );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx open:", ":failed"  );
      return nRC;
       }
       lRC = RegOpenKeyEx( hKeyPrint, "command", 0, KEY_READ, &hKeyCommand );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx command ", " failed"  );
      return nRC;
       }
        
       nRC = FindItemByName( hKeyCommand, stringValueName, dwReturnType,
                         stringReturnData, dwMaxReturnLth );
       TraceLineS( stringValueName, stringReturnData );
        
       return nRC;
    }
        
    public String
    GetRegistryGeneralValue( String stringValueName,
                         String  stringFileType,
                         String stringCLSID_ID,
                         DWORD   dwReturnType,
                         String  stringReturnData,
                         DWORD   dwMaxReturnLth )
    {
       HKEY  hConnect;
       HKEY  hClassesRoot;
       HKEY  hSoftware;
       HKEY  hKeyShell;
       HKEY  hKeyClasses;
       HKEY  hKeyPrint;
       HKEY  hKeyCommand;
       HKEY  hKeyHtml;
       int nRC = -1;
        
       *stringReturnData = 0;  // initialize
        
       int lRC = RegConnectRegistry( null, HKEY_LOCAL_MACHINE, &hConnect );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegConnectRegistry", " failed"  );
      return nRC;
       }
        
       // open the local key
       lRC = RegOpenKeyEx( HKEY_LOCAL_MACHINE, 0, 0, KEY_READ, &hClassesRoot );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx HKEY_LOCAL_MACHINE", " failed"  );
      return nRC;
       }
        
       lRC = RegOpenKeyEx( hClassesRoot, "Software", 0, KEY_READ, &hSoftware );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx hSoftware", " failed"  );
      return nRC;
       }
       // get thr CLSID here
       lRC = RegOpenKeyEx( hSoftware, "Classes", 0, KEY_READ, &hKeyClasses );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx Classes", " failed"  );
      return nRC;
       }
       // get the hKeyHtml here
       lRC = RegOpenKeyEx( hKeyClasses, stringFileType, 0, KEY_READ, &hKeyHtml );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx stringFileType", " failed"  );
      return nRC;
       }
       // get the shell here
       lRC = RegOpenKeyEx( hKeyHtml, "shell", 0, KEY_READ, &hKeyShell );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx shell", " failed"  );
      return nRC;
       }
       // get the print key here
       lRC = RegOpenKeyEx( hKeyShell, "open", 0, KEY_READ, &hKeyPrint );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx open:", ":failed"  );
      return nRC;
       }
       lRC = RegOpenKeyEx( hKeyPrint, "command", 0, KEY_READ, &hKeyCommand );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx command ", " failed"  );
      return nRC;
       }
        
       nRC = FindItemByName( hKeyCommand, stringValueName, dwReturnType,
                         stringReturnData, dwMaxReturnLth );
       TraceLineS( stringValueName, stringReturnData );
        
       return nRC;
    }
        
    public String
    GetRegistryPrintValue( String stringValueName,
                       String  stringFileType,
                       String stringCLSID_ID,
                       DWORD   dwReturnType,
                       String  stringReturnData,
                       DWORD   dwMaxReturnLth )
    {
       HKEY  hConnect;
       HKEY  hClassesRoot;
       HKEY  hSoftware;
       HKEY  hKeyShell;
       HKEY  hKeyClasses;
       HKEY  hKeyPrint;
       HKEY  hKeyCommand;
       HKEY  hKeyHtml;
       int nRC = -1;
        
       *stringReturnData = 0;  // initialize
        
       int lRC = RegConnectRegistry( null, HKEY_LOCAL_MACHINE, &hConnect );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegConnectRegistry", " failed"  );
      return nRC;
       }
        
       // open the local key
       lRC = RegOpenKeyEx( HKEY_LOCAL_MACHINE, 0, 0, KEY_READ, &hClassesRoot );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx HKEY_LOCAL_MACHINE", " failed"  );
      return nRC;
       }
        
       lRC = RegOpenKeyEx( hClassesRoot, "Software", 0, KEY_READ, &hSoftware );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx hSoftware", " failed"  );
      return nRC;
       }
        
       // get thr CLSID here
       lRC = RegOpenKeyEx( hSoftware, "Classes", 0, KEY_READ, &hKeyClasses );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx Classes", " failed"  );
      return nRC;
       }
        
       // get the hKeyHtml here
       lRC = RegOpenKeyEx( hKeyClasses, stringFileType, 0, KEY_READ, &hKeyHtml );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx stringFileType", " failed"  );
      return nRC;
       }
        
       // get the shell here
       lRC = RegOpenKeyEx( hKeyHtml, "shell", 0, KEY_READ, &hKeyShell );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx shell", " failed"  );
      return nRC;
       }
        
       // get the print key here
       lRC = RegOpenKeyEx( hKeyShell, "print", 0, KEY_READ, &hKeyPrint );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx print:", ":failed"  );
      return nRC;
       }
        
       lRC = RegOpenKeyEx( hKeyPrint, "command", 0, KEY_READ, &hKeyCommand );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx print command ", " failed"  );
      return nRC;
       }
        
       nRC = FindItemByName( hKeyCommand, stringValueName, dwReturnType,
                         stringReturnData, dwMaxReturnLth );
       TraceLineS( stringValueName, stringReturnData );
        
       return nRC;
    }
        
    public String
    GetRegistryCLSID( String  stringReturnData, String stringClassName )
    {
       HKEY  hConnect;
       HKEY  hClassesRoot;
       HKEY  hCLSID;
       HKEY  hKeyCLSID;
       DWORD dwReturnTypeCLSID = REG_SZ;
       DWORD dwMaxReturnCLSIDLth = 128;
       int nRC = -1;
        
       int lRC = RegConnectRegistry( null, HKEY_LOCAL_MACHINE, &hConnect );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegConnectRegistry", " failed"  );
      return nRC;
       }
        
       // open the local key
       lRC = RegOpenKeyEx( HKEY_CLASSES_ROOT, 0, 0, KEY_READ, &hClassesRoot );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx HKEY_CLASSES_ROOT", " failed"  );
      return nRC;
       }
        
       lRC = RegOpenKeyEx( hClassesRoot, stringClassName, 0, KEY_READ, &hCLSID );
       if ( lRC != ERROR_SUCCESS )
       {
        
      TraceLineS( "RegOpenKeyEx Failed for: ", stringClassName  );
      return nRC;
       }
        
       // get thr CLSID here
       lRC = RegOpenKeyEx( hCLSID, "CLSID", 0, KEY_READ, &hKeyCLSID );
       if ( lRC != ERROR_SUCCESS )
       {
      TraceLineS( "RegOpenKeyEx CLSID", " failed"  );
      return nRC;
       }
        
       // get the CLSID Value
       nRC = FindItemByName( hKeyCLSID, "", dwReturnTypeCLSID, stringReturnData, dwMaxReturnCLSIDLth );
       TraceLineS( "CLSID ReturnValue", stringReturnData );
       return 0;
    }
        
    public String
    GetImagingPath( View  vSubtask, int lFlag, String stringTarget )
    {
       char   stringReturn;
       char   stringCLSID;
       int nRC = FALSE;
        
       stringReturn = "";  // initially empty
       if ( lFlag == 1 )   //open for edit
       {
      GetRegistryCLSID( stringCLSID, "TIFImage.Document" );
      GetRegistryImagingValue( "", stringCLSID, REG_SZ, stringReturn, sizeof( stringReturn ) );
       }
        
       if ( lFlag == 2 ) //open for print
       {
      GetRegistryCLSID( stringCLSID, "TIFImage.Document" );
      nRC = GetRegistryImagingPrintValue( "", stringCLSID, REG_EXPAND_SZ, stringReturn, sizeof( stringReturn ) );
      if ( nRC == FALSE )
      {
         nRC = GetRegistryImagingPrintValue( "", stringCLSID, REG_SZ, stringReturn, sizeof( stringReturn ) );
      }
       }
       // zstrcpy( stringTarget, stringReturn );
       if ( lFlag == 3 ) //open for view
       {
      GetRegistryCLSID( stringCLSID, "TIFImage.Document" );
      nRC = GetRegistryImagingViewValue( "", stringCLSID, REG_EXPAND_SZ, stringReturn, sizeof( stringReturn ) );
      if ( nRC == FALSE )
      {
         nRC = GetRegistryImagingViewValue( "", stringCLSID, REG_SZ, stringReturn, sizeof( stringReturn ) );
      }
       }
        
       zstrcpy( stringTarget, stringReturn );
       return 0;
    }
        
    public String
    GetHTMLPath( View  vSubtask, int lFlag, String stringTarget )
    {
       char   stringReturn;
       char   stringCLSID;
       int nRC = FALSE;
        
       stringReturn[0] = 0;
       lFlag = 3; // set flag to 3 as that is all we currently support
       if ( lFlag == 3 ) //open for view
       {
      GetRegistryCLSID( stringCLSID, "htmlfile" );
      nRC = GetRegistryHTMLViewValue( "", stringCLSID, REG_SZ, stringReturn, sizeof( stringReturn ) );
      TraceLineS( "Flag 3 stringCLSID !", stringCLSID ) ;
      TraceLineS( "Flag 3 Return !", stringReturn ) ;
      if ( nRC == FALSE )
      {
         // for win98 in case we are not in win2K
         nRC = GetRegistryHTMLViewValue( "", stringCLSID, REG_EXPAND_SZ, stringReturn, sizeof( stringReturn ) );
         TraceLineS( "Flag 3C stringCLSID !", stringCLSID ) ;
         TraceLineS( "Flag 3C Return !", stringReturn ) ;
      }
       }
         TraceLineS( "RIGHT BEFORE STRCopy:", stringReturn ) ;
       zstrcpy( stringTarget, stringReturn );
         TraceLineS( "RIGHT AFTER STRCopy", "") ;
       return 0;
    }
     **/

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: FindStringInAttribute
    //
    //    Find a string within a string attribute. Not case sensitive.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int FindStringInAttribute(String stringSearchString, View view, String entityName,
            String attributeName) {
        String stringAttributeValue = null;
        String stringFoundValue;

        // Look for a match on the string stringSearchString within the attribute.
        // Return 0 if found.
        // Return -1 if not found.
        stringAttributeValue = GetStringFromAttribute(stringAttributeValue, view, entityName, attributeName);
        stringFoundValue = zstrstr(stringAttributeValue, stringSearchString);
        if (stringFoundValue == null)
            return -1; // the string was not found
        else
            return 0; // the string was found

    } // FindStringInAttribute

    public int ConvertExternalValueOfAttribute(StringBuilder lpReturnedString, String srcString, View lpView,
            String entityName, String attributeName) {
        // TODO - Convert code from "C"
        return (0);
    }

    /**
       public String
       GetGeneralPath( View  vSubtask, int lFlag, String stringFileType, String stringTarget )
       {
          char   stringReturn;
          char   stringCLSID;
          int nRC = FALSE;
        
          stringReturn = "";
          lFlag = 3; // set flag to 3 as that is all we currently support
          if ( lFlag == 3 ) //open for view
          {
      GetRegistryCLSID( stringCLSID, stringFileType );
      // nRC = GetRegistryHTMLViewValue( "", stringCLSID, REG_SZ, stringReturn, sizeof( stringReturn ) );
      nRC = GetRegistryGeneralValue( "", "rtffile", stringCLSID, REG_SZ, stringReturn, sizeof( stringReturn ) );
        
      TraceLineS( "Flag 3 stringCLSID !", stringCLSID ) ;
      TraceLineS( "Flag 3 Return !", stringReturn ) ;
      if ( nRC == FALSE )
      {
         // for win98 in case we are not in win2K
         nRC = GetRegistryGeneralValue( "", "rtffile", stringCLSID, REG_EXPAND_SZ,
                                        stringReturn, sizeof( stringReturn ) );
         TraceLineS( "Flag 3C stringCLSID !", stringCLSID ) ;
         TraceLineS( "Flag 3C Return !", stringReturn ) ;
      }
          }
        
          TraceLineS( "RIGHT BEFORE STRCopy:", stringReturn ) ;
          stringTarget = zstrcpy( stringTarget, stringReturn );
          TraceLineS( "RIGHT AFTER STRCopy", "" ) ;
          return stringTarget;
       }
        
       ////////////////////////////////////////////////////////////////////////////////////////////////////
       //
       //  Method Name: ConvertExternalValueOfAttribute
       //
       //    Convert an external value for an attribute to its internal value.
       //
       ////////////////////////////////////////////////////////////////////////////////////////////////////
       public int
       ConvertExternalValueOfAttribute( String lpReturnedString,
                                 String srcString,
                                 View   lpView,
                                 String entityName,
                                 String attributeName )
       {
          zVIEW  wXferO;
          zVIEW  vDynamicT;
          zVIEW  vQualObject;
          zVIEW  zqFrameOrig;
          zVIEW  zqFrame;
          LPVIEWENTITY lpViewEntity;
          LPVIEWATTRIB lpViewAttrib;
          LPDOMAIN     lpDomain;
          String  DataType;
          String  Msg;
          String  SavedTableName;
          String  stringYearIndicator;
          int  lInternalTableValue;
          int nLth;
          int nRC;
        
          GetViewByName( wXferO, "wXferO", lpView, zLEVEL_TASK );
          lpReturnedString = "";
          lpViewEntity = String MiGetViewEntityForView( lpView, entityName );
          if ( lpViewEntity == 0 )
      return -16;
        
          // Position on attribute.
    #ifdef VIEWENTITY_OD
          lpViewAttrib = String zGETPTR( lpViewEntity->hFirstOD_Attrib );
          nRC = 1;
          while ( lpViewAttrib > 0 && nRC > 0 )
          {
      if ( zstrcmp( lpViewAttrib->stringName, attributeName ) == 0 )
         nRC = 0;
        
      if ( nRC > 0 )
         lpViewAttrib = String zGETPTR( lpViewAttrib->hNextOD_Attrib );
          }
    #else
          lpViewAttrib = String zGETPTR( lpViewEntity->hFirstViewAttrib );
          nRC = 1;
          while ( lpViewAttrib > 0 && nRC > 0 )
          {
      if ( zstrcmp( lpViewAttrib->stringName, attributeName ) == 0 )
         nRC = 0;
        
      if ( nRC > 0 )
         lpViewAttrib = String zGETPTR( lpViewAttrib->hNextViewAttrib );
          }
    // #endif
          if ( nRC > 0 )
          {
      MessageSend( lpView, "", "Data Conversion",
                   "The attribute specified was not found.",
                   zMSGQ_OBJECT_CONSTRAINT_ERROR, 0 );
      return -1;
          }
        
          // If input is null, simply return because output has already been set to null.
          if ( *srcString == 0 )
      return 0;
        
          nLth = zstrlen( srcString );
        
          // Process depending on whether or not the Domain is a Table.
          lpDomain = (LPDOMAIN) zGETPTR( lpViewAttrib->hDomain );
          if ( lpDomain->cDomainType == 'T' )
          {
      if ( *(lpDomain->stringDomainOper) == 0 )
      {
         // The domain is a static table so convert the value through the table interface.
         if ( lpDomain->cType == zTYPE_INTEGER )
         {
            nRC = TableEntryExtToInt( &lInternalTableValue, lpView, lpDomain, 0, srcString );
            zltoa( lInternalTableValue, lpReturnedString );
         }
         else
            nRC = TableEntryExtToInt( lpReturnedString, lpView, lpDomain, 0, srcString );  // Internal value is STRING.
         if ( nRC < 0 )
         {
            zstrcpy( Msg, "Invalid input value for attribute, " );
            zstrcat( Msg, attributeName );
            zstrcat( Msg, "." );
            MessageSend( lpView, "", "Data Conversion",
                         Msg,
                         zMSGQ_OBJECT_CONSTRAINT_ERROR, 0 );
            return -1;
         }
      }
      else
      {
         if ( zstrcmp( lpDomain->stringName, "FAISIR_DynamicTableSingle" ) == 0 )
         {
            // Get Year Indicator value as GeneralParameter in zqFrame object.
            // If we get to this section of code, we must have come from zqFrame and the lpView is actually
            // the zqFrame view.
            // (This is very similar to the code in DomainC.)
            GetViewByName( zqFrameOrig, "zqFrame", lpView, zLEVEL_TASK );
            CreateViewFromView( zqFrame, zqFrameOrig );
            nRC = SetCursorFirstEntityByString( zqFrame, "GeneralParameter", "AttributeName", "YearIndicator", "" );
            if ( nRC < zCURSOR_SET )
               *stringYearIndicator = 0;
            else
               GetStringFromAttribute( stringYearIndicator, zqFrame, "GeneralParameter", "Value" );
            if ( *stringYearIndicator == 0 )
            {
               MessageSend( lpView, "", "Data Validation",
                            "A YearIndicator value must be specified as a General Parameter in the Query.",
                            zMSGQ_DOMAIN_ERROR, 0 );
               return zCALL_ERROR;
            }
        
            zstrcpy( SavedTableName, "X_" );
            zstrcat( SavedTableName, lpDomain->stringName );
            zstrcat( SavedTableName, stringYearIndicator );    // Build the concatenated name.
        
            // Either get existing view or activate new one.
            nRC = GetViewByName( vDynamicT, SavedTableName, lpView, zLEVEL_TASK );
            if ( nRC < 0 )
            {
               // Set up Qualification object for YearIndicator.
               SfActivateSysEmptyOI( vQualObject, "KZDBHQUA", lpView, zMULTIPLE );
               CreateEntity( vQualObject, "EntitySpec", zPOS_AFTER );
               SetAttributeFromString( vQualObject, "EntitySpec", "EntityName", "FAISIRDomain" );
               CreateEntity( vQualObject, "QualAttrib", zPOS_AFTER );
               SetAttributeFromString( vQualObject, "QualAttrib", "EntityName", "FAISIRDomain" );
               SetAttributeFromString( vQualObject, "QualAttrib", "AttributeName", "YearIndicator" );
               SetAttributeFromString( vQualObject, "QualAttrib", "Value", stringYearIndicator );
               SetAttributeFromString( vQualObject, "QualAttrib", "Oper", "=" );
        
               // Activate the Domains for the YearIndicator.
               nRC = ActivateObjectInstance( vDynamicT, "mFAISIRD", zqFrame, vQualObject, zMULTIPLE );
               DropView( vQualObject );
               if ( nRC < 0 )
               {
                  MessageSend( lpView, "", "Data Validation",
                               "A YearIndicator value must be specified as a General Parameter in the Query.",
                               zMSGQ_DOMAIN_ERROR, 0 );
                  return zCALL_ERROR;
               }
        
               SetNameForView( vDynamicT, SavedTableName, 0, zLEVEL_APPLICATION );
               CreateViewFromViewForTask( &vDynamicT, vDynamicT, 0 );
               SetNameForView( vDynamicT, SavedTableName, lpView, zLEVEL_TASK );
            }
        
            // Position on correct table entry.
            nRC = SetCursorFirstEntityByString( vDynamicT, "FAISIRDomain", "Name", attributeName, "" );
            if ( nRC >= zCURSOR_SET )
               nRC = SetCursorFirstEntityByString( vDynamicT, "FAISIRDomainValue", "ExternalDescription", srcString, "" );
            if ( nRC < 0 )
            {
               zstrcpy( Msg, "Invalid input value for attribute, " );
               zstrcat( Msg, attributeName );
               zstrcat( Msg, "." );
               MessageSend( lpView, "", "Data Conversion",
                            Msg,
                            zMSGQ_OBJECT_CONSTRAINT_ERROR, 0 );
               return -1;
            }
        
            GetStringFromAttribute( lpReturnedString, vDynamicT, "FAISIRDomainValue", "InternalStringValue" );
        
            DropView( zqFrame );
         }
         else
         {
            // The domain is a regular dynamic table so use the object in memory or activate it.
            zstrcpy( SavedTableName, "X_" );
            zstrcat( SavedTableName, lpDomain->stringName );
            nRC = GetViewByName( vDynamicT, SavedTableName, lpView, zLEVEL_TASK );
            if ( nRC < 0 )
               nRC = GetViewByName( vDynamicT, SavedTableName, lpView, zLEVEL_APPLICATION );
        
            if ( nRC < 0 )
            {
               // The table wasn't in memory, so call the dynamic table routine to load it.
               // Note that we will call the routine with an invalid request type, which will load
               // the table but not take action.
               SfActivateSysEmptyOI( &vQualObject, "KZDBHQUA", lpView, zMULTIPLE );
               CreateEntity( vQualObject, "EntitySpec", zPOS_AFTER );
               SetAttributeFromString( vQualObject, "EntitySpec", "EntityName", "Domain" );
               CreateEntity( vQualObject, "QualAttrib", zPOS_AFTER );
               SetAttributeFromString( vQualObject, "QualAttrib", "EntityName", "Domain" );
               SetAttributeFromString( vQualObject, "QualAttrib", "AttributeName", "Name" );
               SetAttributeFromString( vQualObject, "QualAttrib", "Value", lpDomain->stringName );
               SetAttributeFromString( vQualObject, "QualAttrib", "Oper", "=" );
               nRC = ActivateObjectInstance( &vDynamicT, "DOMAINT", lpView,
                                             vQualObject, zSINGLE | zLEVEL_APPLICATION );
               SetNameForView( vDynamicT, SavedTableName, lpView, zLEVEL_APPLICATION );
            }
        
            // Locate the entry in the table by external value and return the internal value.
            nRC = SetCursorFirstEntityByString( vDynamicT, "DomainValue",
                                                "ExternalDescription",
                                                srcString, 0 );
            if ( nRC < 0 )
            {
               zstrcpy( Msg, "Invalid input value for attribute, " );
               zstrcat( Msg, attributeName );
               zstrcat( Msg, "." );
               MessageSend( lpView, "", "Data Conversion",
                            Msg,
                            zMSGQ_OBJECT_CONSTRAINT_ERROR, 0 );
               return -1;
            }
        
            GetStringFromAttribute( lpReturnedString, vDynamicT, "DomainValue", "InternalStringValue" );
         }
      }
          }
          else
          {
      // If Domain Type is not Table, use data type for conversion through wXferO attribute.
      DataType = lpDomain->cType;
      if ( DataType == 'L' )
      {
         nRC = SetAttributeFromVariable( wXferO, "Root", "WorkInteger",
                                        srcString, zTYPE_STRING,
                                        nLth, 0, zUSE_DEFAULT_CONTEXT );
         if ( nRC >= 0 )
            GetStringFromAttribute( lpReturnedString, wXferO, "Root", "WorkInteger" );
         else
            return -1;
      }
      else
      if ( DataType == 'T' )
      {
         nRC = SetAttributeFromVariable( wXferO, "Root", "WorkDate",
                                         srcString, zTYPE_STRING,
                                         nLth, "M/D/YYYY", 0 );
         if ( nRC >= 0 )
            GetStringFromAttribute( lpReturnedString, wXferO, "Root", "WorkDate" );
         else
            return -1;
      }
      else
      if ( DataType == 'D' )
      {
         nRC = SetAttributeFromVariable( wXferO, "Root", "WorkDate",
                                         srcString, zTYPE_STRING,
                                         nLth, "M/D/YYYY", 0 );
         if ( nRC >= 0 )
            GetStringFromAttribute( lpReturnedString, wXferO, "Root", "WorkDate" );
         else
            return -1;
      }
      else
      if ( DataType == 'M' )
      {
         nRC = SetAttributeFromVariable( wXferO, "Root", "WorkDecimal",
                                         srcString, zTYPE_STRING,
                                         nLth, 0, zUSE_DEFAULT_CONTEXT );
         if ( nRC >= 0 )
            GetStringFromAttribute( lpReturnedString, wXferO, "Root", "WorkDecimal" );
         else
            return -1;
      }
      else
         zstrcpy( lpReturnedString, srcString );
          }
        
          return 0;
       } // ConvertExternalValueOfAttribute
    **/

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AddSpacesToString
    //
    //    Insert spaces within a Zeidon string name where capital letters exist.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public String AddSpacesToString(String stringZeidonName) {
        StringBuilder sb = new StringBuilder(stringZeidonName);
        int k;

        for (k = 1; k < sb.length(); k++) {
            if (sb.charAt(k) >= 'A' && sb.charAt(k) <= 'Z') {
                sb.insert(k, ' ');
                k++;
            }
        }

        return sb.toString();

    } // AddSpacesToString

    /**
       ////////////////////////////////////////////////////////////////////////////////////////////////////
       //
       //  Method Name: GetDataTypeForAttribute
       //
       //    Return the Data Type for an attribute
       //
       ////////////////////////////////////////////////////////////////////////////////////////////////////
       public int
       GetDataTypeForAttribute( String stringDataType,
                         View   lpView,
                         String entityName,
                         String attributeName )
       {
          LPVIEWENTITY lpViewEntity;
          LPVIEWATTRIB lpViewAttrib;
          int nRC;
        
          lpViewEntity = String zGETPTR( MiGetViewEntityForView( lpView, entityName ) );
          if ( lpViewEntity == 0 )
      return -16;
        
          // Position on attribute.
       #ifdef VIEWENTITY_OD
          lpViewAttrib = String zGETPTR( lpViewEntity->hFirstOD_Attrib );
          nRC = 1;
          while ( lpViewAttrib > 0 && nRC > 0 )
          {
      if ( zstrcmp( lpViewAttrib->stringName, attributeName ) == 0 )
         nRC = 0;
        
      if ( nRC > 0 )
         lpViewAttrib = String zGETPTR( lpViewAttrib->hNextOD_Attrib );
          }
       #else
          lpViewAttrib = String zGETPTR( lpViewEntity->hFirstViewAttrib );
          nRC = 1;
          while ( lpViewAttrib > 0 && nRC > 0 )
          {
      if ( zstrcmp( lpViewAttrib->stringName, attributeName ) == 0 )
         nRC = 0;
        
      if ( nRC > 0 )
         lpViewAttrib = String zGETPTR( lpViewAttrib->hNextViewAttrib );
          }
       #endif
          if ( nRC > 0 )
          {
      MessageSend( lpView, "", "GetDataTypeForAttribute",
                   "The attribute specified was not found.",
                   zMSGQ_OBJECT_CONSTRAINT_ERROR, 0 );
      return -1;
          }
        
          // Set single character datatype followed by a string terminator.
          *stringDataType = lpViewAttrib->hDomain->cType;
          *(stringDataType + 1) = 0;
        
          return 0;
       } // GetDataTypeForAttribute
    **/

    //
    int ParseOutEntityAttribute(String entityDotAttribute, StringBuilder entityName, StringBuilder attributeName) {
        int k;
        int lSkipLth;

        // Initialize entityName and attributeName.
        entityName.replace(0, -1, entityDotAttribute);
        attributeName.delete(0, -1);
        // entityDotAttribute is pointing to the first character of the entity name on entry to this routine.
        // Parse out Entity Name

        for (k = 0; k < entityName.length(); k++) {
            char ch = entityName.charAt(k);
            if (ch == '.' || ch == ']' || ch == '}') {
                entityName.setCharAt(k, '\0');
                if (ch == '}')
                    return -2;

                if (ch != ']') // there is an attribute, so keep going
                {
                    int j = 0;
                    k++;

                    // Parse out Attribute Name
                    ch = entityDotAttribute.charAt(k);
                    while (ch != ']' && ch != '}') {
                        if (ch == '}')
                            return -2;

                        attributeName.setCharAt(j, ch);
                        j++;
                        k++;
                        ch = entityDotAttribute.charAt(k);
                    }

                    attributeName.setCharAt(k, '\0');
                }
            }
        }

        lSkipLth = k + 1; // TODO not sure this translation to java is exactly right for SkipLth
        return lSkipLth;
    }

    int ConvertCharacterString(StringBuilder sbTarget, StringBuilder sbSource, StringBuilder sbOrigMemory,
            int nFileType) // 1-Text   2-HTML
    {
        char ch;
        int lTabCount;
        int i; // index to sbTarget
        int j; // index to sbSource
        int k;

        // This code checks for "carriage return/line feed" combinations in the
        // text and inserts the correct \par and \tab strings in the target text.
        // pchTarget = *sbTarget;

        // First, determine if the start of the text is preceded by tab characters and if so, count them.
        lTabCount = 0;

        /** TODO - figure this out and implement java version
        String pchBack = sbOrigMemory - 5;
        while ( zstrncmp( sbOrigMemory, "\\tab", 4 ) == 0 )
        {
           lTabCount++;
           pchBack = pchBack - 5;
        }
         **/

        // Copy the characters, inserting \par and \tab strings as necessary for new lines.
        for (i = 0, j = 0; (ch = sbSource.charAt(j)) != '\0'; j++) {
            // Search for carriage return/line feed and insert \par and \tab strings.
            if (ch == 13 && sbSource.charAt(j + 1) == 10) {
                // Copy carriage control and line feed characters.
                sbTarget.setCharAt(i++, sbSource.charAt(j++));
                sbTarget.setCharAt(i++, sbSource.charAt(j++));

                // Insert \par and \tab characters.
                if (nFileType == 1) {
                    i = zstrcpy(sbTarget, i, "\\par ");
                } else {
                    i = zstrcpy(sbTarget, i, "<br />");
                }

                for (k = 0; k < lTabCount; k++) {
                    i = zstrcpy(sbTarget, i, "\\tab ");
                }
            } else {
                sbTarget.setCharAt(i++, sbSource.charAt(j++));
            }
        }

        sbTarget.setCharAt(i++, '\0');

        return (0);
    }

    /**
       int
       CopyWithInsertMemoryArea( zVIEW   vResultSet,
                          StringBuilder sbTemplateMemory,
                          int     nTemplateMemoryPosition,
                          String  stringInnerLoopEntityName,
                          String  pchEmbeddedImages,
                          int     nFileType )  // 1-Text   2-HTML
       {
          StringBuilder sbLoopEntityName;
          StringBuilder sbEntityName;
          StringBuilder sbAttributeName;
          StringBuilder sbVariableBuffer;
          int    nTemplateMemoryLth;
          int    lRBracketPos;
          int    lSkipLth;
          int    k;
          int    nRC;
        
          nTemplateMemoryLth = sbTemplateMemory.length( );
          for ( k = nTemplateMemoryPosition; k < nTemplateMemoryLth; k++ )
          {
      if ( sbTemplateMemory.charAt( k ) == '[' )
      {
         lRBracketPos = zstrchr( sbTemplateMemory, ']' );
         if ( lRBracketPos >= 0 )
         {
         sbTemplateMemory.setCharAt( lRBracketPos, '\0' );
            if ( (zstrchr( sbTemplateMemory, '<' )) >= 0 || (zstrchr( sbTemplateMemory, '>' )) >= 0 || (zstrchr( sbTemplateMemory, '/' )) >= 0 )
            {
               sbTemplateMemory.setCharAt( lRBracketPos, ']' );
               lRBracketPos = 0;
            }
            else
            {
               sbTemplateMemory.setCharAt( lRBracketPos, ']' );
            }
         }
        
         if ( lRBracketPos >= 0 && sbTemplateMemory.charAt( k + 1 ) == 'Z' && sbTemplateMemory.charAt( k + 2 ) == ':' )  // "[Z:"
         {
            if ( sbTemplateMemory.charAt( k + 3 ) == '#' )  // "[Z:#"
            {
               if ( sbTemplateMemory.charAt( k + 4 ) == 'C' )  // "[Z:#C"
               {
                  // Just set the cursor to the next entity.
                 k += 6;
                 nTemplateMemoryPosition = k;
                  SetCursorNextEntity( vResultSet, stringInnerLoopEntityName, "" );
               }
               else
               {
                  if ( sbTemplateMemory.charAt( k + 4 ) == 'S' && sbTemplateMemory.charAt( k + 5 ) == ':' )  // "[Z:#S:"
                  {
                     // Parse out the Loop Entity name.
                   k += 6;
                   lSkipLth = ParseOutEntityAttribute( sbTemplateMemory.substring( k ), sbLoopEntityName, sbAttributeName );
                     if ( lSkipLth < 0 )
                        return lSkipLth;
        
                     k += lSkipLth;
                     nTemplateMemoryPosition = k;
        
                     // Identify the beginning and end of the data area to be repeated in variables:
                     //   pchMemoryLoopStartArea and pchMemoryLoopEndArea.
                     while ( sbTemplateMemory.charAt( k ) != ']' && nTemplateMemoryPosition < nTemplateMemoryLth )
                     {
                      nTemplateMemoryPosition++;
                     }
        
                     nTemplateMemoryPosition++;
        
                     while ( zstrncmp( sbTemplateMemory, nTemplateMemoryPosition, "[Z:#E]", 6 ) != 0 && nTemplateMemoryPosition < nTemplateMemoryLth )
                     {
                      nTemplateMemoryPosition++;
                     }
        
                     nTemplateMemoryLth = sbTemplateMemory.length( );
        
                     // Process the looping on the specified Entity Name.
                     nRC = SetCursorFirstEntity( vResultSet, sbLoopEntityName.toString( ), "" );
                     while ( nRC >= zCURSOR_SET )
                     {
                        // Perform the normal mapping code here.
                        nRC = CopyWithInsertMemoryArea( vResultSet, sbTemplateMemory, nTemplateMemoryPosition,
                                                        sbLoopEntityName.toString( ), pchEmbeddedImages, nFileType );
        
                        if ( nRC < 0 )
                           return( nRC );
        
                        nRC = SetCursorNextEntity( vResultSet, sbLoopEntityName.toString( ), "" );
                     }
        
                     // Skip repeating area and the [Z:#E] characters ending the loop.
                     k += 6;
                     nTemplateMemoryPosition = k;
                  }
                  else
                  {
                     // The else condition is ignored as an error.
                     while ( sbTemplateMemory.charAt( k ) != ']' && k < nTemplateMemoryLth )
                     {
                      k++;
                     }
        
                     k++;
                     nTemplateMemoryPosition = k;
                  }
               }
            }
            else
            {
               // Get the Entity and Attribute Names.
               // We save original memory position in pchOrigMemory so the
               // subroutine can search for preceding tab characters.
               k += 3;
               lSkipLth = ParseOutEntityAttribute( sbTemplateMemory.substring( k ), sbEntityName, sbAttributeName );
               if ( lSkipLth < 0 )
                  return lSkipLth;
        
               k += lSkipLth;
               nTemplateMemoryPosition = k;
        
               // Get the data from the object.
               if ( CheckExistenceOfEntity( vResultSet, sbEntityName.toString( ) ) >= zCURSOR_SET )
               {
                  if ( zstrcmp( sbAttributeName.toString( ), "StudentAccountNotClearedText" ) == 0 )
                     zstrcpy( sbVariableBuffer, "Stop" );    // DonC ???
        
                  GetStringFromAttributeByContext( sbVariableBuffer, vResultSet,
                                                sbEntityName.toString( ), sbAttributeName.toString( ), "", 1000 );
                  if ( sbVariableBuffer != null )
                  {
                     ConvertCharacterString( pchMemoryNew, sbVariableBuffer, pchOrigMemory, nFileType );
                  }
               }
            }
         }
         else
         {
            // Just copy the character
            *pchMemoryNew = *sbTemplateMemory;
            sbTemplateMemory++;
            pchMemoryNew++;
         }
      }
      else
      // <IMG SRC="cid:message-root.1.d:\10c\a\tz\image1.gif" ALT="image1.gif">
      if ( pchEmbeddedImages && sbTemplateMemory[ 0 ] == '<' &&
           zstrnicmp( sbTemplateMemory.substring( 1 ), "IMG SRC=", 8 ) == 0 &&
           zstrncmp( sbTemplateMemory.substring( 10 ), "cid:message-root.", 17 ) == 0 )
      {
         zstrncpy( pchMemoryNew, sbTemplateMemory, 27 );
         pchMemoryNew += 27;
         sbTemplateMemory += 27;
         while ( sbTemplateMemory.charAt( k ) != '\0' &&
                 sbTemplateMemory.charAt( k ) != '.' &&
                 sbTemplateMemory.charAt( k ) != '"' )
         {
            // Just copy the character
            *pchMemoryNew = *sbTemplateMemory;
            sbTemplateMemory++;
            pchMemoryNew++;
         }
        
         if ( sbTemplateMemory.charAt( k ) == '.' )
         {
            sbTemplateMemory++;  // skip past '.'
            lSkipLth = zstrlen( pchEmbeddedImages );
            if ( lSkipLth > 0 )
               pchEmbeddedImages[ lSkipLth++ ] = ';';
        
            while ( sbTemplateMemory.charAt( k ) != '\0' && sbTemplateMemory.charAt( k ) != '"' )
            {
               pchEmbeddedImages[ lSkipLth++ ] = *sbTemplateMemory;
               sbTemplateMemory++;
            }
        
            pchEmbeddedImages[ lSkipLth ] = 0;
         }
        
         // Finally copy the terminating quote.
         *pchMemoryNew = *sbTemplateMemory;
         sbTemplateMemory++;
         pchMemoryNew++;
      }
      else
      {
         // Just copy the character.
         *pchMemoryNew = *sbTemplateMemory;
         sbTemplateMemory++;
         pchMemoryNew++;
      }
          }
        
          if ( pchMemoryNew - pchStartMemoryNew > lTotalOutputSize )
          {
      MessageBox( 0, "CopyWithInsertMemoryArea Overwrite Buffer",
                  "Memory Overwrite", MB_OK );
          }
        
          *sbMemoryNew = pchMemoryNew;
          return 0;
       }
    **/

    int ReadFileDataIntoMemory(View vResultSet, String stringDocumentFile, long hDocumentMemory,
            StringBuilder sbDocumentData) throws IOException {
        int hDocumentFile;
        int lDocumentLth;

        hDocumentMemory = 0;
        sbDocumentData.setLength(0);
        lDocumentLth = 0;

        hDocumentFile = m_KZOEP1AA.SysOpenFile(vResultSet, stringDocumentFile, COREFILE_READ);
        if (hDocumentFile < 0) {
            // IssueError( vResultSet, 0, 0, "Can't open Document file." );
            return -1;
        }

        lDocumentLth = m_KZOEP1AA.SysGetFileSize(vResultSet, hDocumentFile);

        // Exit if the document file is empty.
        if (lDocumentLth == 0) {
            m_KZOEP1AA.SysCloseFile(vResultSet, hDocumentFile, 0);
            return 0;
        }

        // hDocumentMemory = SysAllocMemory( sbDocumentData.toString( ), lDocumentLth, 0, zCOREMEM_ALLOC, 0 );  TODO  This is all wrong ... recode correctly in Java when needed
        // DrAllocTaskMemory( ppvDocumentData, lDocumentLth );
        // TraceLine( "ReadFileDataIntoMemory: 0x%x   Size: %d",
        //            (int) *ppvDocumentData, lDocumentLth );

        // **ppvDocumentData = 0;
        m_KZOEP1AA.SysReadFile(vResultSet, hDocumentFile, sbDocumentData, lDocumentLth);
        m_KZOEP1AA.SysCloseFile(vResultSet, hDocumentFile, 0);

        if (sbDocumentData == null) {
            // SysFreeMemory( hDocumentMemory  );
            // DrFreeTaskMemory( *ppvDocumentData );
            // phDocumentMemory = 0;
            sbDocumentData = null;
            lDocumentLth = 0;
            IssueError(vResultSet, 0, 0, "Read Error on Document file");
            return -1;
        }

        return lDocumentLth;
    }

    public int ParseBooleanExpression(View zqFrame) {
        //zPCHAR pchValue;
        //zPCHAR pchNext;
        String szBooleanExpression = null;
        StringBuilder sbBooleanExpression = null;
        String szConditionValue = null;

        // Parse the Boolean Expression and create each component value as an entity Component.

        GetStringFromAttributeByContext(sbBooleanExpression, zqFrame, "BooleanExpression", "TextValue", "", 254);
        /*
              // Skip to first nonblank.
              for ( pchNext = szBooleanExpression;
         *pchNext == ' ' && *pchNext != 0;
         pchNext++ )
              {
              }
            
              // Loop through all parameters.
              while ( *pchNext != 0 )
              {
                 // Find next parameter
                 if ( *pchNext == ')' || *pchNext == '(' )
                 {
         pchValue = szConditionValue;
         *pchValue = *pchNext;
         pchValue++;
         *pchValue = 0;
         if ( *pchNext == ')' )
            pchNext++;    // We need to do the skip here for close paren
                 }
                 else
                 {
        for ( pchValue = szConditionValue;
              *pchNext != ' ' && *pchNext != 0 && *pchNext != ')';
              pchNext++ )
         {
            *pchValue = *pchNext;
            pchValue++;
         }
            
         *pchValue = 0;
            
                 }
            
                 CreateEntity( zqFrame, "Component", zPOS_AFTER );
                 SetAttributeFromString( zqFrame, "Component", "Value", szConditionValue );
            
                 if ( *pchNext != 0 && *pchNext != ')' )
         pchNext++;
            
                 // Skip to next nonblank.
                 while ( *pchNext == ' ' && *pchNext != 0 )
         pchNext++;
              }
        */
        return 0;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: MergeSingleRS_EntryWithTemplate
    //
    //    Insert OI variable data in Template
    //
    //    lFlags  0 - No Attachment / Mime Type Text
    //            1 - Has Attachment
    //            2 - Mime Type HTML
    //           16 - Prompt if there are any recipients that do not have
    //                an email address specified
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int MergeSingleRS_EntryWithTemplate(View vResultSet, String TemplateFileName, String OutputFileName,
            String stringEmbeddedImages, StringBuilder stringReturnedMergedText, int lMaxReturnedLth, int nFileType)
            throws IOException // 1-Text   2-HTML
    {
        /**
              long  hFileTo;
              StringBuilder sbTemplateMemory = new StringBuilder( );
           // String stringMemoryEndOrig = null;
           // String stringMemoryEndNew;
              int  nTemplateMemoryPosition;
              int  hTemplateMemoryUnused = 0;
              int  selMemoryNew;
              int  lTemplateLth;
              int  lTotalOutputSize;
              int  lLthNew = 0;
              int  ulRC;
              int  nRC;
              int  nLth;
            
              // Get memory for output file.
              // The size of the new memory will add 8000 bytes of variable data to the
              // template size to account for merged data.
              lTemplateLth = ReadFileDataIntoMemory( vResultSet, TemplateFileName,
                                          hTemplateMemoryUnused, sbTemplateMemory );
            
              // Exit if the template file is empty or if there is an error opening it.
              if ( lTemplateLth <= 0 )
              {
                 MessageSend( vResultSet, "", "Template File Merge",
                   "The Template File could not be opened.\nCheck that the file name specified is valid.",
                   zMSGQ_OBJECT_CONSTRAINT_ERROR, 0 );
                 return null;
              }
            
           // stringMemoryEndOrig = cbMemoryStartOrig + lTemplateLth;  TODO  This is all wrong ... recode correctly in Java when needed
              lTotalOutputSize = lTemplateLth + 8000;
           // selMemoryNew = SysAllocMemory( sbMemoryStartNew, lTotalOutputSize, 0, zCOREMEM_ALLOC, 0 );
           // StringBuilder sbMemoryStartNew = new StringBuilder( lTotalOutputSize );
           // DrAllocTaskMemory( (zCOREMEM) &stringMemoryStartNew, lTotalOutputSize );
           // TraceLine( "MergeSingleRS_EntryWithTemplate: 0x%x   Size: %d",
           //            (int) stringMemoryStartNew, lTotalOutputSize );
            
              // Perform the normal mapping code here.
              nTemplateMemoryPosition = 0;
              stringEmbeddedImages = "";
              nRC = CopyWithInsertMemoryArea( vResultSet,
                              sbTemplateMemory,
                                   nTemplateMemoryPosition, "",
                                   stringEmbeddedImages,
                                   nFileType );
           // SysFreeMemory( hTemplateMemoryUnused );
           // DrFreeTaskMemory( stringMemoryStartOrig );
              if ( nRC < 0 )
              {
                 MessageSend( vResultSet, "", "Template File Merge",
                   "A Merge error occurred.\nCheck the Template file for invalid data or recreate the file.",
                   zMSGQ_OBJECT_CONSTRAINT_ERROR, 0 );
                 return null;;
              }
            
              // End file.
              stringMemoryEndNew = nTemplateMemoryPosition;
              stringMemoryEndNew = "";
           // stringMemoryEndNew++;  TODO  This is all wrong ... recode correctly in Java when needed
            
              // Write the merged resulting data in memory out to the file.
           // lLthNew = (int) (stringMemoryEndNew - stringMemoryStartNew);  TODO  This is all wrong ... recode correctly in Java when needed
              hFileTo = SysOpenFile( vResultSet, OutputFileName, COREFILE_WRITE );
              if ( hFileTo < 0 )
              {
                 SysFreeMemory( selMemoryNew );
              // DrFreeTaskMemory( stringMemoryStartNew );
                 MessageSend( vResultSet, "", "Template File Merge",
                   "The Output File could not be opened.\nCheck that the file directory specified is valid.",
                   zMSGQ_OBJECT_CONSTRAINT_ERROR, 0 );;
                 return -1;
              }
            
           // WriteFile( hFileTo, stringMemoryStartNew, lLthNew, ulRC, 0 );  TODO  This is all wrong ... recode correctly in Java when needed
              SysCloseFile( vResultSet, hFileTo, 0 );
            
              // Returned the Merged text.
              if ( lMaxReturnedLth < lLthNew )
                 nLth = lMaxReturnedLth;
              else
                 nLth = lLthNew;
            
           // zstrncpy( pReturnedMergedText, stringMemoryStartNew, nLth );  TODO  This is all wrong ... recode correctly in Java when needed
            
              SysFreeMemory( selMemoryNew );
           // DrFreeTaskMemory( stringMemoryStartNew );
        **/
        return 0;

    } // MergeSingleRS_EntryWithTemplate

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: InsertOI_DataIntoTemplate
    //
    //    Insert OI variable data in Template
    //
    //    lFlags  0 - No Attachment / Mime Type Text
    //            1 - Has Attachment
    //            2 - Mime Type HTML
    //           16 - Prompt if recipient(s) does not have email address
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////
    public int InsertOI_DataIntoEmailTemplate(View ViewToWindow, View vResultSet, String stringSMTPServer,
            String stringEMailUserName, String stringEMailPassword, String stringSenderEMailAddress,
            String stringSubjectLine, String stringAttachmentFileName, String stringTemplateFileName,
            String stringAltFileName, String stringRootEntityName, int lFlags) throws IOException {
        String stringEmbeddedImages; // should be WAY more than enough
        String stringRecipientEMailAddress = null;
        int nHasAttachment;
        int nMimeType;
        int lConnection;
        // int  hFileTo;
        @SuppressWarnings("unused")
        String stringMemory;
        String stringMemoryNew;
        String stringMemoryNewHold = null;
        String stringMemoryStartEmailBody;
        StringBuilder sbMemoryStartOld = new StringBuilder(256);
        @SuppressWarnings("unused")
        String stringMemoryEndOld;
        String stringMemoryStartArea = null;
        String stringMemoryEndArea = null;
        long selMemory = 0;
        long selMemoryNew;
        int lTemplateLth;

        String stringAltMemory;
        String stringAltMemoryNew;
        String stringAltMemoryNewHold = null;
        @SuppressWarnings("unused")
        String stringAltMemoryStartEmailBody;
        StringBuilder sbAltMemoryStartOld = new StringBuilder(256);
        @SuppressWarnings("unused")
        String stringAltMemoryEndOld;
        String stringAltMemoryStartArea = null;
        String stringAltMemoryEndArea = null;
        long selAltMemory = 0;
        long selAltMemoryNew = 0;
        long lAltTemplateLth;
        long lAltTotalOutputSize = 0;
        @SuppressWarnings("unused")
        int lAltLthNew;

        int lSelectedCount;
        int lCurrentCount;
        int lTotalOutputSize;
        @SuppressWarnings("unused")
        int lLthNew;
        boolean bNoEmailAddress = false;
        // zULONG ulRC;
        int nRC;

        if ((lFlags & 0x00000001) != 0)
            nHasAttachment = 1; // has attachment
        else
            nHasAttachment = 0; // no attachment

        if ((lFlags & 0x00000002) != 0)
            nMimeType = 2; // HTML
        else
            nMimeType = 1; // Text

        // The size of the new memory will add 8000 bytes of variable data to the
        // template size.
        lSelectedCount = 0;
        nRC = SetCursorFirstEntity(vResultSet, stringRootEntityName, "");
        while (nRC > zCURSOR_UNCHANGED) {
            nRC = GetSelectStateOfEntity(vResultSet, stringRootEntityName);
            if (nRC == 1) {
                stringRecipientEMailAddress = GetStringFromAttribute(stringRecipientEMailAddress, vResultSet,
                        "Person", "eMailAddress");
                if (stringRecipientEMailAddress.isEmpty() == false)
                    lSelectedCount++;
                else {
                    String lastName = null;
                    String firstName = null;
                    String middleName = null;

                    if (bNoEmailAddress == false) {
                        bNoEmailAddress = true;
                        TraceLineS("EMail NOT sent Subject: ", stringSubjectLine);
                    }

                    lastName = GetStringFromAttribute(lastName, vResultSet, "Person", "LastName");
                    firstName = GetStringFromAttribute(firstName, vResultSet, "Person", "FirstName");
                    middleName = GetStringFromAttribute(middleName, vResultSet, "Person", "MiddleName");
                    stringRecipientEMailAddress = lastName + ", " + firstName + " " + middleName;
                    TraceLineS("  No EMail address for: ", stringRecipientEMailAddress);
                }
            }

            nRC = SetCursorNextEntity(vResultSet, stringRootEntityName, "");
        }

        if (bNoEmailAddress && (lFlags & 0x00000010) != 0) {
            if (OperatorPrompt(vResultSet, "EMail not sent to recipient(s)",
                    "See Zeidon Trace for list ... Continue?", TRUE, zBUTTONS_YESNO, zRESPONSE_NO,
                    0) == zRESPONSE_NO) {
                return 0;
            }
        }

        // We'll just exit here if nothing was selected.
        if (lSelectedCount == 0)
            return 0;

        lTemplateLth = ReadFileDataIntoMemory(vResultSet, stringTemplateFileName, selMemory, sbMemoryStartOld);

        // Exit if the template file is empty or if there is an error opening it.
        if (lTemplateLth <= 0) {
            IssueError(vResultSet, 0, 0, "Can't open Template file.");
            return 0;
        }

        lAltTemplateLth = 0;
        if (nMimeType == 2) // HTML
        {
            if (stringAltFileName != null && stringAltFileName.isEmpty() == false) {
                //? lAltTemplateLth = ReadFileDataIntoMemory( vResultSet, stringAltFileName, selAltMemory, sbAltMemoryStartOld );
            }

            // Exit if the alt template file is empty or if there is an error opening it.
            if (lAltTemplateLth > 0) {
                lAltTotalOutputSize = lAltTemplateLth + 8000;
                //?   selAltMemoryNew = SysAllocMemory( stringAltMemoryNewHold, lAltTotalOutputSize, 0, zCOREMEM_ALLOC, 0 );
            } else {
                // IssueError( vResultSet, 0, 0, "Can't open Alt Template file." );
                // return 0;
            }
        }

        lTotalOutputSize = lTemplateLth + 8000;
        //? selMemoryNew = SysAllocMemory( stringMemoryNewHold, lTotalOutputSize, 0, zCOREMEM_ALLOC, 0 );

        // DrAllocTaskMemory( (zCOREMEM) &stringMemoryNewHold, lTotalOutputSize );
        // TraceLine( "InsertOI_DataIntoEmailTemplate: 0x%x   Size: %d",
        //            (int) stringMemoryNewHold, lTotalOutputSize );

        lConnection = m_ZDRVROPR.CreateSeeConnection(stringSMTPServer, stringSenderEMailAddress,
                stringEMailUserName, stringEMailPassword);

        // For each selected item, map the repeatable data in the template to the output buffer.
        lCurrentCount = 0;
        nRC = SetCursorFirstEntity(vResultSet, stringRootEntityName, "");
        while (nRC > zCURSOR_UNCHANGED) {
            nRC = GetSelectStateOfEntity(vResultSet, stringRootEntityName);
            if (nRC == 1) {
                GetStringFromAttribute(stringRecipientEMailAddress, vResultSet, "Person", "eMailAddress");
                if (stringRecipientEMailAddress.isEmpty() == false) {
                    if (lAltTemplateLth > 0) {
                        stringAltMemoryNew = stringAltMemoryNewHold;
                        lCurrentCount++;
                        stringAltMemoryEndOld = sbAltMemoryStartOld.subSequence(lTemplateLth, -1).toString();

                        // Initialize Output values.
                        stringAltMemoryStartEmailBody = stringAltMemoryNew;
                        lAltLthNew = 0;

                        // Copy the first brace that starts the file.
                        // stringAltMemory = cbAltMemoryStartOld.toString( );  TODO  This is all wrong ... recode correctly in Java when needed
                        // stringAltMemoryNew = stringAltMemory;
                        // stringAltMemory++;
                        // stringAltMemoryNew++;

                        // Set the start of repeatable area (one per document copy) as
                        // second character in Template file.
                        // stringAltMemoryStartArea = stringAltMemory;

                        // Set the end of repeatable area as one character before the last
                        // character in Template file.
                        // stringAltMemoryEndArea = stringAltMemoryEndOld - 1;
                        stringAltMemory = stringAltMemoryStartArea;

                        // Perform the normal mapping code here.
                        //? nRC = CopyWithInsertMemoryArea( vResultSet, stringAltMemoryStartArea, stringAltMemoryEndArea,
                        //?                                 stringAltMemoryNew, "", stringAltMemoryNewHold,
                        //?                                 lAltTotalOutputSize, "", 1 );
                        if (nRC < 0)
                            return nRC;

                        // Finally copy the closing brace to the output file.
                        stringAltMemoryNew = stringAltMemoryEndArea;
                        // stringAltMemory++;  TODO  This is all wrong ... recode correctly in Java when needed
                        // stringAltMemoryNew++;

                        // lAltLthNew = (int) (stringAltMemoryNew - stringAltMemoryStartEmailBody);
                    } else
                        stringAltMemory = "";

                    stringMemoryNew = stringMemoryNewHold;
                    lCurrentCount++;
                    // stringMemoryEndOld = cbMemoryStartOld + lTemplateLth;  TODO  This is all wrong ... recode correctly in Java when needed

                    // Initialize Output values.
                    stringMemoryStartEmailBody = stringMemoryNew;
                    lLthNew = 0;

                    // Copy the first brace that starts the file.
                    //  stringMemory = cbMemoryStartOld;  TODO  This is all wrong ... recode correctly in Java when needed
                    //  stringMemoryNew = stringMemory;
                    //  stringMemory++;
                    //  stringMemoryNew++;

                    // Set the start of repeatable area (one per document copy) as
                    // second character in Template file.
                    //  stringMemoryStartArea = stringMemory;

                    // Set the end of repeatable area as one character before the last
                    // character in Template file.
                    //  stringMemoryEndArea = stringMemoryEndOld - 1;
                    stringMemory = stringMemoryStartArea;

                    // Perform the normal mapping code here.
                    stringEmbeddedImages = "";
                    //? nRC = CopyWithInsertMemoryArea( vResultSet, stringMemoryStartArea, stringMemoryEndArea,
                    //?                                 stringMemoryNew, "", stringMemoryNewHold,
                    //?                                 lTotalOutputSize, stringEmbeddedImages, nMimeType );
                    if (nRC < 0)
                        return nRC;

                    // Finally copy the closing brace to the output file.
                    // stringMemoryNew = stringMemoryEndArea;  TODO  This is all wrong ... recode correctly in Java when needed
                    // stringMemory++;
                    // stringMemoryNew++;

                    // lLthNew = (int) (stringMemoryNew - stringMemoryStartEmailBody);  TODO  This is all wrong ... recode correctly in Java when needed

                    m_ZDRVROPR.CreateSeeMessage(lConnection, stringSMTPServer, stringSenderEMailAddress,
                            stringRecipientEMailAddress, "", "", stringSubjectLine, nMimeType,
                            stringMemoryStartEmailBody, stringAltMemory, stringEmbeddedImages, nHasAttachment,
                            stringAttachmentFileName, stringEMailUserName, stringEMailPassword);

                    // SysOpenFile( stringAttachmentFileName, COREFILE_DELETE );
                }
            }

            nRC = SetCursorNextEntity(vResultSet, stringRootEntityName, "");
        }

        m_ZDRVROPR.CloseSeeConnection(lConnection);
        //? SysFreeMemory( selMemory );
        //? SysFreeMemory( selMemoryNew );
        if (lAltTemplateLth != 0) {
            //? SysFreeMemory( selAltMemory );
            //? SysFreeMemory( selAltMemoryNew );
        }

        // DrFreeTaskMemory( stringMemoryStartOld );
        // DrFreeTaskMemory( stringMemoryNewHold );

        return 0;

    } // InsertOI_DataIntoEmailTemplate

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: InsertOI_DataIntoTemplateFile
    //
    //    Insert OI variable data in Template File
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int InsertOI_DataIntoTemplateFile(View ViewToWindow, View vResultSet, String stringOutputFileName,
            String stringTemplateFileName, String stringAltFileName, String stringRootEntityName)
            throws IOException {
        int hFileTo;
        @SuppressWarnings("unused")
        String stringMemory;
        String stringMemoryNew = null;
        @SuppressWarnings("unused")
        String stringMemoryStartNew;
        StringBuilder sbMemoryStartOld = new StringBuilder();
        @SuppressWarnings("unused")
        String stringMemoryEndOld;
        String stringMemoryStartArea = null;
        String stringMemoryEndArea = null;
        long selMemory = 0;
        int selMemoryNew;
        int lTemplateLth;
        int lSelectedCount;
        int lCurrentCount;
        int lTotalOutputSize;
        @SuppressWarnings("unused")
        int lLthNew;
        int nRC;

        // The size of the new memory will try to allow for the number of select
        // copies to be made of the input template.  It will thus add 50000 bytes
        // of variable data to the template size and multiply that by the number
        // of items selected.
        lSelectedCount = 0;
        nRC = SetCursorFirstEntity(vResultSet, stringRootEntityName, "");
        while (nRC > zCURSOR_UNCHANGED) {
            nRC = GetSelectStateOfEntity(vResultSet, stringRootEntityName);
            if (nRC == 1)
                lSelectedCount++;

            nRC = SetCursorNextEntity(vResultSet, stringRootEntityName, "");
        }

        // We'll just exit here if nothing was selected.
        if (lSelectedCount == 0)
            return 0;

        lTemplateLth = ReadFileDataIntoMemory(vResultSet, stringTemplateFileName, selMemory, sbMemoryStartOld);

        // Exit if the template file is empty or if there is an error opening it.
        if (lTemplateLth <= 0) {
            IssueError(vResultSet, 0, 0, "Can't open Template file.");
            return 0;
        }

        lTotalOutputSize = (lTemplateLth + 50000) * lSelectedCount;
        //? selMemoryNew = SysAllocMemory( stringMemoryNew, lTotalOutputSize, 0, zCOREMEM_ALLOC, 0 );
        // DrAllocTaskMemory( (zCOREMEM) &stringMemoryNew, lTotalOutputSize );
        // TraceLine( "InsertOI_DataIntoTemplateFile: 0x%x   Size: %d",
        //            (int) stringMemoryNew, lTotalOutputSize );

        stringMemoryEndOld = sbMemoryStartOld.subSequence(lTemplateLth, -1).toString();

        // Initialize Output values.
        stringMemoryStartNew = stringMemoryNew;
        lLthNew = 0;

        // Copy the first brace that starts the file.
        // stringMemory = cbMemoryStartOld.toString( );  TODO  This is all wrong ... recode correctly in Java when needed
        //  stringMemoryNew = stringMemory;
        // stringMemory++;
        // stringMemoryNew++;

        // Set the start of repeatable area (one per document copy) as second character in
        // Template file.
        // stringMemoryStartArea = stringMemory;

        // Set the end of repeatable area as one character before the last character in Template file.
        // stringMemoryEndArea = stringMemoryEndOld - 1;

        // For each selected item, map the repeatable data in the template to the output buffer.
        nRC = SetCursorFirstEntity(vResultSet, stringRootEntityName, "");
        lCurrentCount = 0;
        while (nRC > zCURSOR_UNCHANGED) {
            nRC = GetSelectStateOfEntity(vResultSet, stringRootEntityName);
            if (nRC == 1) {
                // If this is any page but the first, add in the page break
                // characters.
                lCurrentCount++;
                if (lCurrentCount > 1) {
                    // TODO  what's the problem with this line??? zstrcpy( stringMemoryNew, "\x0D\x0A\\par \\page \\hich\\af0\\dbch\\af28\\loch\\f0 " );
                    stringMemoryNew = stringMemoryNew + 41;
                }

                stringMemory = stringMemoryStartArea;
                // Perform the normal mapping code here.
                //? nRC = CopyWithInsertMemoryArea( vResultSet, stringMemoryStartArea, stringMemoryEndArea,
                //?                                 stringMemoryNew, "", stringMemoryNew, lTotalOutputSize, "",    // no embedded images
                //?                                 1 );  // Text
                if (nRC < 0)
                    return nRC;
            }

            nRC = SetCursorNextEntity(vResultSet, stringRootEntityName, "");
        }

        // Finally copy the closing brace to the output file.
        // stringMemoryNew = stringMemoryEndArea;  TODO  This is all wrong ... recode correctly in Java when needed
        //  stringMemory++;
        // stringMemoryNew++;

        // lLthNew = (int) (stringMemoryNew - stringMemoryStartNew);
        //? SysFreeMemory( selMemory );
        // DrFreeTaskMemory( stringMemoryStartOld );
        hFileTo = m_KZOEP1AA.SysOpenFile(ViewToWindow, stringOutputFileName, COREFILE_WRITE);
        if (hFileTo < 0) {
            //? SysFreeMemory( selMemoryNew );
            // DrFreeTaskMemory( stringMemoryNew );
            IssueError(vResultSet, 0, 0, "Write Open Error");
            return -1;
        }

        // WriteFile( hFileTo, stringMemoryStartNew, lLthNew, ulRC, 0 );  TODO  This is all wrong ... recode correctly in Java when needed
        m_KZOEP1AA.SysCloseFile(ViewToWindow, hFileTo, 0);
        //? SysFreeMemory( selMemoryNew );
        // DrFreeTaskMemory( stringMemoryNew );

        return 0;

    } // InsertOI_DataIntoTemplateFile

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: ReadLine5000
    //
    //    Read a line into a 5000 character string
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int ReadLine5000(View ViewToWindow, StringBuilder sbLineBuffer, int FileHandle) throws IOException {
        int nRC = 0;

        nRC = m_KZOEP1AA.SysReadLine(ViewToWindow, sbLineBuffer, FileHandle);
        if (sbLineBuffer.length() == 0)
            return 0;

        if (sbLineBuffer.length() > 5000) {
            TraceLineS("////////////* > 5000", "//////////*");
            sbLineBuffer.setCharAt(5000, '\0');
        }

        //return sbLineBuffer.toString( );
        return nRC;

    } // ReadLine5000

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: ConvertLineToEntity
    //
    //    Convert data in a comma or tab delimited record to attribute values in an entity.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int ConvertLineToEntity(View vTarget, View vXOD, String stringRecord, String stringDelimiterType,
            int lMaxRecordLth) {
        /** TODO
              String  cDelimiter;
              String  stringDataValue;
              String  entityName;
              String  attributeName;
              String  stringTab;
              String  stringDate;
              String  stringDataValue;
              String  stringRecordEnd;
              int nRC;
            
              zstrcpy( stringTab, "x09" );
              if ( stringDelimiterType.charAt( 0 ) == 'T' )
                 cDelimiter = stringTab[ 1 ];
              else
                 cDelimiter = stringTab[ 1 ];
            
              stringRecordEnd = stringRecord + lMaxRecordLth;
              GetStringFromAttribute( entityName, vXOD, "ENTITY", "NAME" );
            
              // Loop for each Attribute in the Entity, parsing the record string and setting the Attribute.
              nRC = SetCursorFirstEntity( vXOD, "ATTRIB", 0 );
              while ( nRC >= zCURSOR_SET && stringRecord < stringRecordEnd )
              {
                 GetStringFromAttribute( attributeName, vXOD, "ATTRIB", "NAME" );
                 stringDataValue = stringDataValue;
                 stringDataValue = "";
                 while ( *stringRecord != 9 && stringRecord < stringRecordEnd )
                 {
         *stringDataValue = *stringRecord;
         stringRecord++;
         stringDataValue++;
                 }
            
                 *stringDataValue = 0;
                 stringRecord++;
            
                 if ( CompareAttributeToString( vXOD, "ATTRIB", "TYPE", "T" ) == 0 &&
           zstrlen( stringDataValue ) <= 8 )
                 {
         // Attribute is Date, so convert properly.
         if ( zstrlen( stringDataValue ) == 7 )
         {
            zstrcpy( stringDate, "0" );
            zstrcat( stringDate, stringDataValue );
         }
         else
            zstrcpy( stringDate, stringDataValue );
         // A value of "0" is really null.
         if ( zstrcmp( stringDate, "0" ) == 0 )
            stringDate = "";
            
         SetAttrFromStrByContext( vTarget, entityName, attributeName, stringDate, "MMDDYYYY" );
                 }
                 else
         // Attribute is treated as simple Text.
         SetAttributeFromString( vTarget, entityName, attributeName, stringDataValue );
            
                 nRC = SetCursorNextEntity( vXOD, "ATTRIB", "" );
              }
        **/
        return 0;
    } // ConvertLineToEntity

    public int SetAttrFromStrByContext(View view, String entityName, String attributeName, String value,
            String context) {
        int RESULT = 0;
        view.cursor(entityName).setAttribute(attributeName, value, context);
        RESULT = 0;
        return RESULT;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: GetCurrentApplicationName
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int GetCurrentApplicationName(StringBuilder stringReturnedString, int lMaxLength, View ViewToWindow) {
        // LPAPP  stringApp;

        return SfGetApplicationForSubtask(stringReturnedString, ViewToWindow);
    }

    // GetCurrentApplicationName

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: DBQualEntityByString
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int DBQualEntityByString(View vQualObject, String entityName, String attributeName, String operationName,
            String value, int bExists) {
        if (entityName.length() == 0)
            entityName = null;

        if (attributeName.length() == 0)
            attributeName = null;

        if (operationName.length() == 0)
            operationName = null;

        if (value.length() == 0)
            value = null;

        // add qualification
        CreateEntity(vQualObject, "QualAttrib", zPOS_AFTER);
        SetAttributeFromString(vQualObject, "QualAttrib", "EntityName", entityName);
        if (bExists == TRUE) {
            SetAttributeFromString(vQualObject, "QualAttrib", "Oper", "EXISTS");
            CreateEntity(vQualObject, "SubQualAttrib", zPOS_AFTER);
            SetAttributeFromString(vQualObject, "SubQualAttrib", "EntityName", entityName);
            SetAttributeFromString(vQualObject, "SubQualAttrib", "AttributeName", attributeName);
            SetAttributeFromString(vQualObject, "SubQualAttrib", "Value", value);
            SetAttributeFromString(vQualObject, "SubQualAttrib", "Oper", operationName);
        } else {
            SetAttributeFromString(vQualObject, "QualAttrib", "AttributeName", attributeName);
            SetAttributeFromString(vQualObject, "QualAttrib", "Value", value);
            SetAttributeFromString(vQualObject, "QualAttrib", "Oper", operationName);
        }

        return 0;
    } // DBQualEntityByString

    /**  TODO when we get some time
       ////////////////////////////////////////////////////////////////////////////////////////////////////
       //
       //  Method Name: ParseBooleanExpression
       //
       ////////////////////////////////////////////////////////////////////////////////////////////////////
       public int
       ParseBooleanExpression( View   zqFrame )
       {
          String  stringValue;
          String  stringNext;
          String  stringBooleanExpression;
          String  stringConditionValue;
        
          // Parse the Boolean Expression and create each component value as an entity Component.
        
          stringBooleanExpression = GetStringFromAttributeByContext( stringBooleanExpression,
                                                              zqFrame, "BooleanExpression",
                                                              "TextValue", "", 254 );
        
          // Skip to first nonblank.
          for ( stringNext = stringBooleanExpression;
         *stringNext == ' ' && *stringNext != 0;
         stringNext++ )
          {
          }
        
          // Loop through all parameters.
          while ( *stringNext != 0 )
          {
      // Find next parameter
      if ( *stringNext == ')' || *stringNext == '(' )
      {
         stringValue = stringConditionValue;
         *stringValue = *stringNext;
         stringValue++;
         *stringValue = 0;
         if ( *stringNext == ')' )
            stringNext++;    // We need to do the skip here for close paren
      }
      else
      {
        for ( stringValue = stringConditionValue;
              *stringNext != ' ' && *stringNext != 0 && *stringNext != ')';
              stringNext++ )
         {
            *stringValue = *stringNext;
            stringValue++;
         }
        
         *stringValue = 0;
      }
        
      CreateEntity( zqFrame, "Component", zPOS_AFTER );
      SetAttributeFromString( zqFrame, "Component", "Value", stringConditionValue );
        
      if ( *stringNext != 0 && *stringNext != ')' )
         stringNext++;
        
      // Skip to next nonblank.
      while ( *stringNext == ' ' && *stringNext != 0 )
         stringNext++;
          }
        
          return 0;
       } // ParseBooleanExpression
    **/

    /**
       ////////////////////////////////////////////////////////////////////////////////////////////////////
       //
       //  Method Name: WinShellExecute
       //
       ////////////////////////////////////////////////////////////////////////////////////////////////////
       public int
       WinShellExecute( View   vSubtask,
                 String stringFileOrExeName,
                 String stringFileOpenCommand,
                 String stringExeParams )
       {
          //HWND hWnd;
          int hWnd;
          int lControlReturn;
          int hInstance;
        
          GetWindowHandle( hWnd, lControlReturn, vSubtask, "" );
          //GetWindowHandle( PTR UNSIGNED int, // Window Return
          //                PTR UNSIGNED int,  // ControlReturn
          //                View,      // Subtask
          //                String );  // CtrlTag
        
          if ( stringFileOpenCommand != null && stringFileOpenCommand.isEmpty( ) == false )
      TraceLineS( "WinShellExecute FileOpenCommand: ", stringFileOpenCommand );
        
          if ( stringFileOrExeName != null && stringFileOrExeName.isEmpty( ) == false  )
      TraceLineS( "WinShellExecute FileOrExeName: ", stringFileOrExeName );
        
          if ( stringExeParams != null && stringExeParams.isEmpty( ) == false )
      TraceLineS( "WinShellExecute ExeParams: ", stringExeParams );
        
          hInstance = (zULONG) ShellExecute( (HWND) hWnd, stringFileOpenCommand,
                                      stringFileOrExeName, stringExeParams,
                                      null, SW_SHOWNORMAL );
          if ( hInstance > 32 )
          {
      TraceLineI( "WinShellExecute Success - Result: ", hInstance );
      return 0;
          }
          else
          {
      TraceLineI( "WinShellExecute Failed Result: ", hInstance );
      return hInstance;
          }
        
    return 0;
       } // WinShellExecute
    **/

    public String GetRTFPath(View vSubtask, int lFlag, String stringTarget) {
        String stringReturn;
        String stringCLSID = null;
        @SuppressWarnings("unused")
        int nRC = FALSE;

        stringReturn = "";
        if (lFlag == 2) // open for print
        {
            stringCLSID = GetRegistryCLSID(stringCLSID, "rtffile");
            stringReturn = GetRegistryPrintValue("", "rtffile", stringCLSID, REG_SZ, stringReturn, 0);

            TraceLineS("RTF-Print-Flag 3 stringCLSID !", stringCLSID);
            TraceLineS("RTF-Print-Flag 3 Return !", stringReturn);
            if (stringReturn == null) {
                stringReturn = GetRegistryPrintValue("", "rtffile", stringCLSID, REG_SZ, stringReturn, 0);
                TraceLineS("RTF-Print-Flag 3 stringCLSID [win98]!", stringCLSID);
                TraceLineS("RTF-Print-Flag 3 Return [win98]!", stringReturn);
            }
        }

        if (lFlag == 3) // open for view
        {
            GetRegistryCLSID(stringCLSID, "rtffile");
            stringReturn = GetRegistryGeneralValue("", "rtffile", stringCLSID, REG_SZ, stringReturn, 0);

            TraceLineS("RTF-Flag 3 stringCLSID !", stringCLSID);
            TraceLineS("RTF-Flag 3 Return !", stringReturn);
            if (stringReturn == null) {
                // for win98 in case we are not in win2K
                stringReturn = GetRegistryGeneralValue("", "rtffile", stringCLSID, REG_EXPAND_SZ, stringReturn, 0);
                TraceLineS("RTF-Flag 3C stringCLSID [win98]!", stringCLSID);
                TraceLineS("RTF-Flag 3C Return [win98]!", stringReturn);
            }
        }

        zstrcpy(stringTarget, stringReturn);
        return stringTarget;
    }

    public int StartEmailClientForListReus(View vResult, String entityName, String attributeName,
            String contextName, String stringScope, int bUseOnlySelectedEntities, int bUseParentSelectedEntities,
            String stringSubject, String stringCopyTo, // comma separated list
            String stringBlindCopy, // comma separated list
            String stringBody, String stringAttachment, String stringEmailClient, int lFlags,
            String stringBlindCopyFlag) // reserved
    {
        String stringParentEntity = null;
        String s = null;
        int lEntityCnt;
        int ulAttributeLth = 0;
        int lTotalSize;
        int lLth = 0;
        int lRC;

        if (bUseParentSelectedEntities != 0)
            stringParentEntity = MiGetParentEntityNameForView(stringParentEntity, vResult, entityName);

        lEntityCnt = CountEntitiesForView(vResult, entityName);
        ulAttributeLth = GetAttributeDisplayLength(ulAttributeLth, vResult, entityName, attributeName, contextName);
        lTotalSize = lEntityCnt * (int) ulAttributeLth; // a starting point
        CharBuffer cbMemory = CharBuffer.allocate(lTotalSize + 1);
        // DrAllocTaskMemory( cbMemory, lTotalSize + 1 );

        // For each entity, append the specified data to the list.
        // lRC = SetCursorFirstEntity( vResult, entityName, stringScope );
        lRC = SetEntityCursor(vResult, entityName, "", zPOS_FIRST, "", "", "", 0, stringScope, "");

        while (lRC > zCURSOR_UNCHANGED) {
            if (bUseOnlySelectedEntities == 0
                    || ((bUseOnlySelectedEntities != 0) && GetSelectStateOfEntity(vResult, entityName) != 0)
                    || ((bUseParentSelectedEntities != 0)
                            && GetSelectStateOfEntity(vResult, stringParentEntity) != 0)) {
                s = GetVariableFromAttribute(s, 0, zTYPE_STRING, lTotalSize - lLth - 1, vResult, entityName,
                        attributeName, contextName,
                        contextName != null && contextName.isEmpty() == false ? 0 : zUSE_DEFAULT_CONTEXT);
                lLth = zstrcpy(cbMemory, lLth, s);
                while (lLth > 0 && cbMemory.charAt(lLth - 1) == ' ') {
                    lLth--;
                    cbMemory.put(lLth, '\0');
                }
            }

            // lRC = SetCursorNextEntity( vResult, entityName, stringScope );
            lRC = SetEntityCursor(vResult, entityName, "", zPOS_NEXT, "", "", "", 0, stringScope, "");
            if (lRC > zCURSOR_UNCHANGED) {
                // lLth = zstrlen( stringMemory );
                if (lTotalSize - lLth < (int) ulAttributeLth) {
                    s = cbMemory.toString();

                    lEntityCnt *= 2;
                    lTotalSize = lEntityCnt * (int) ulAttributeLth;
                    cbMemory = CharBuffer.allocate(lTotalSize + 1);
                    zstrcpy(cbMemory, 0, s);
                }

                if (lLth > 0 && cbMemory.charAt(lLth - 1) != ',') {
                    cbMemory.put(lLth++, ',');
                    cbMemory.put(lLth, '\0');
                }
            }
        }

        if (stringBlindCopyFlag.charAt(0) == 'Y') {
            // Email Addresses are to be put in Blind Copy parameter.
            TraceLineS("Blind Copies: ", cbMemory.toString());
            lRC = m_ZDRVROPR.StartEmailClient(stringBlindCopy, // Regular send parameter
                    stringSubject, stringCopyTo, // comma separated list
                    cbMemory.toString(), // Blind Copy parameter
                    stringBody, stringAttachment, "", lFlags); // reserved
        } else {
            // Email Addresses are to be put in regular Send parameter.
            TraceLineS("Regular Copies: ", cbMemory.toString());
            lRC = m_ZDRVROPR.StartEmailClient(cbMemory.toString(), // comma separated list
                    stringSubject, stringCopyTo, // comma separated list
                    stringBlindCopy, // comma separated list
                    stringBody, stringAttachment, stringEmailClient, lFlags); // reserved
        }

        // DrFreeTaskMemory( (String) cbMemory );
        return lRC;
    }

    public int StartEmailClientForList(View vResult, String entityName, String attributeName, String contextName,
            String stringScope, int bUseOnlySelectedEntities, int bUseParentSelectedEntities, String stringSubject,
            String stringCopyTo, // comma separated list
            String stringBlindCopy, // comma separated list
            String stringBody, String stringAttachment, String stringEmailClient, int lFlags) // reserved
    {
        int lRC;

        // Call reusable routine.
        lRC = StartEmailClientForListReus(vResult, entityName, attributeName, contextName, stringScope,
                bUseOnlySelectedEntities, bUseParentSelectedEntities, stringSubject, stringCopyTo, stringBlindCopy,
                stringBody, stringAttachment, stringEmailClient, lFlags, "");
        return lRC;
    }

    public int StartEmailClientForList(View vResult, String entityName, String attributeName, String contextName,
            int nScope, int bUseOnlySelectedEntities, int bUseParentSelectedEntities, String stringSubject,
            String stringCopyTo, // comma separated list
            String stringBlindCopy, // comma separated list
            String stringBody, String stringAttachment, String stringEmailClient, int lFlags) // reserved
    {
        int lRC;

        // Call reusable routine.
        lRC = StartEmailClientForListReus(vResult, entityName, attributeName, contextName, "",
                bUseOnlySelectedEntities, bUseParentSelectedEntities, stringSubject, stringCopyTo, stringBlindCopy,
                stringBody, stringAttachment, stringEmailClient, lFlags, "");
        return lRC;
    }

    public int StartBlindEmailClientForList(View vResult, String entityName, String attributeName,
            String contextName, String stringScope, int bUseOnlySelectedEntities, int bUseParentSelectedEntities,
            String stringSubject, String stringCopyTo, // comma separated list
            String stringBlindCopy, // comma separated list
            String stringBody, String stringAttachment, String stringEmailClient, int lFlags) // reserved
    {
        zVIEW mUser = null;
        String stringBlindEmailAddress = null;
        int lRC;

        // Get the Target Email Address from mUser, unless a BlindCopy is passed.
        if (stringBlindCopy == null) {
            stringBlindEmailAddress = "";
            GetViewByName(mUser, "mUser", vResult, zLEVEL_APPLICATION);
            lRC = CheckExistenceOfEntity(mUser, "Employee");
            if (lRC >= 0)
                GetStringFromAttribute(stringBlindEmailAddress, mUser, "Employee", "eMailAddress");
            if (stringBlindEmailAddress.isEmpty()) {
                lRC = CheckExistenceOfEntity(mUser, "Student");
                if (lRC >= 0)
                    stringBlindEmailAddress = GetStringFromAttribute(stringBlindEmailAddress, mUser, "Student",
                            "eMailAddress");

                if (stringBlindEmailAddress.isEmpty()) {
                    stringBlindEmailAddress = GetStringFromAttribute(stringBlindEmailAddress, mUser, "Person",
                            "eMailAddress");
                }
            }
        } else
            stringBlindEmailAddress = zstrcpy(stringBlindEmailAddress, stringBlindCopy);

        // Call reusable routine.
        lRC = StartEmailClientForListReus(vResult, entityName, attributeName, contextName, stringScope,
                bUseOnlySelectedEntities, bUseParentSelectedEntities, stringSubject, stringCopyTo,
                stringBlindEmailAddress, stringBody, stringAttachment, stringEmailClient, lFlags, "Y");
        return lRC;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: StartEmailClientWithFiles
    //
    //    Start Email Client passing in file names for body and attachment
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int StartEmailClientWithFiles(View AnyView, String stringEmailAddress, String stringSubjectLine,
            String stringCopyToEmailAddress, String stringBlindCopyEmailAddress, String stringBodyFileName,
            String stringAttachmentFileName, String stringEmailClientOverride, int ulFlags) throws IOException {
        // Read the data from the Body and Attachment files into memory and call StartEmailClient
        // with those values.
        StringBuilder sbBodyMemoryStart = new StringBuilder();
        StringBuilder sbAttachmentMemoryStart = new StringBuilder();
        long hBodyMemory = 0;
        long hAttachmentMemory = 0;
        int lFileLth = 0;

        // Read the Body into memory.
        hBodyMemory = ReadFileDataIntoMemory(AnyView, stringBodyFileName, hBodyMemory, sbBodyMemoryStart);
        // Exit if the file is empty or if there is an error opening it.
        if (hBodyMemory == -1) {
            IssueError(AnyView, 0, 0, "Can't open Email file.");
            return -1;
        }

        // If there is an attachment file, also read it into memory.
        // Then call StartEmailClientWithFiles with or without an attachment.
        if (stringAttachmentFileName.isEmpty() == false) {
            hAttachmentMemory = ReadFileDataIntoMemory(AnyView, stringAttachmentFileName, hAttachmentMemory,
                    sbAttachmentMemoryStart);
            // Exit if the file is empty or if there is an error opening it.
            if (lFileLth <= 0)
                return -1;

            m_ZDRVROPR.StartEmailClient(stringEmailAddress, stringSubjectLine, stringCopyToEmailAddress,
                    stringBlindCopyEmailAddress, sbBodyMemoryStart.toString(), sbAttachmentMemoryStart.toString(),
                    stringEmailClientOverride, 0);
            //? SysFreeMemory( hAttachmentMemory );
            // DrFreeTaskMemory( stringAttachmentMemoryStart );
        } else {
            m_ZDRVROPR.StartEmailClient(stringEmailAddress, stringSubjectLine, stringCopyToEmailAddress,
                    stringBlindCopyEmailAddress, sbBodyMemoryStart.toString(), "", stringEmailClientOverride, 0);
        }

        //? SysFreeMemory( hBodyMemory );
        // DrFreeTaskMemory( stringBodyMemoryStart );
        return 0;
    }

    // StartEmailClientWithFiles

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: IsEmailAddressValid
    //
    //    Validates an email address
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    boolean IsEmailAddressValid(String stringEmailAddress) {
        // TODO return ValidateEmailAddressFormat( stringEmailAddress ) ? true : false;
        return true;

        /** #if 0
            
           // Contains at least one character preceding the "@"
           // Contains a "@" following the preceding character(s)
           // Contains at least one character following the "@", followed
           // by a dot (.), followed by either a two character or three
           // character string (a two character country code or the standard
           // three character US code, such as com, edu etc)
            
           String stringAt;
           String stringDot;
           String string;
            
           if ( zstrchr( stringEmailAddress, ' ' )  ||
        zstrchr( stringEmailAddress, '\t' ) ||
        zstrchr( stringEmailAddress, '\n' ) ||
        zstrchr( stringEmailAddress, '\r' ) )
           {
              return FALSE );
           }
            
           stringAt = zstrchr( stringEmailAddress, '@' );
           if ( stringAt )
           {
              stringDot = zstrchr( stringAt, '.' );
              stringAt = zstrchr( stringAt + 1, '@' );
              if ( stringAt == 0 && stringDot )
              {
         stringDot = zstrrchr( stringDot, '.' );
         if ( stringDot[ 1 ] && stringDot &&
              ((stringDot[ 3 ] == 0) ||
               (stringDot[ 3 ] && stringDot == 0)) )
         {
            string = (String) stringEmailAddress;
            while ( *string )
            {
               if ( *string > (char) 127 )
                  return FALSE );
            
               string++;
            }
            
            return TRUE );
         }
              }
           }
            
           return FALSE );
            
        #endif **/
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: SendEmailForFiles
    //
    //    Start Email Client passing in file names for body and attachment
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int SendEmailForFiles(View ViewToWindow, View ResultSet, String stringSmtpServer,
            String stringRecipientEMailAddress, String stringSenderEMailAddress, String stringEMailUserName,
            String stringEMailPassword, String stringSubjectLine, String stringBodyFileName,
            String stringAltTextFileName, String stringEmbeddedImages, String stringAttachmentFileName,
            int nMimeType, // 1-Text, 2-HTML
            int lConnection) {
        // String stringBodyMemoryStart;
        CharBuffer cbAtBodyFileName = CharBuffer.allocate(256);
        CharBuffer cbAtAltTextFileName = CharBuffer.allocate(256);
        // int  selBodyMemory;
        // int  lFileLth;
        zVIEW zqMDocOLST = null;
        zVIEW wXferO = null;
        int nRC;

        // TraceLine( "SendEmailForFiles Server: %s   Sender: %s   Recipient: %s"
        //            "   Subject: %s   Mime Type: %d"
        //            "   User: %s   Password %s",
        //            stringSmtpServer, stringSenderEMailAddress, stringRecipientEMailAddress,
        //            stringSubjectLine, nMimeType, stringEMailUserName, stringEMailPassword );

        // First make sure the email address is valid. If not exit with return code of 2.
        if (IsEmailAddressValid(stringRecipientEMailAddress) == false)
            return 2;

        GetViewByName(zqMDocOLST, "zqMDocOLST", ResultSet, zLEVEL_TASK);
        GetViewByName(wXferO, "wXferO", ViewToWindow, zLEVEL_TASK);

        if (stringBodyFileName != null) {
            if (stringBodyFileName.isEmpty() == false && stringBodyFileName.charAt(0) != '@') {
                cbAtBodyFileName.put(0, '@');
                zstrcpy(cbAtBodyFileName, 1, stringBodyFileName);
            } else
                zstrcpy(cbAtBodyFileName, 0, stringBodyFileName);
        } else
            cbAtBodyFileName.put(0, '\0');

        if (stringAltTextFileName != null) {
            if (stringAltTextFileName.isEmpty() == false && stringAltTextFileName.charAt(0) != '@') {
                cbAtAltTextFileName.put(0, '@');
                zstrcpy(cbAtAltTextFileName, 1, stringAltTextFileName);
            } else
                zstrcpy(cbAtAltTextFileName, 0, stringAltTextFileName);
        } else
            cbAtAltTextFileName.put(0, '\0');

        // Read the data from the Body and Attachment files into memory and call
        // StartEmailClient with those values.

        // Read the Body into memory.
        // lFileLth = ReadFileDataIntoMemory( ResultSet, stringBodyFileName,
        //                                    &selBodyMemory, &stringBodyMemoryStart );

        // Exit if the file is empty or if there is an error opening it.
        // if ( lFileLth <= 0 )
        // {
        // The memory allocated to hold the body has been freed.
        //    IssueError( ResultSet, 0, 0, "Can't open Email file." );
        //    return -1;
        // }

        if (stringSubjectLine == null || stringSubjectLine.isEmpty())
            stringSubjectLine = " ";

        // TraceLine( "SendEmailForFiles2 Server: %s   Sender: %s   Recipient: %s"
        //            "   Subject: %s   Mime Type: %d"
        //            "   User: %s   Password %s",
        //            stringSmtpServer, stringSenderEMailAddress, stringRecipientEMailAddress,
        //            stringSubjectLine, nMimeType, stringEMailUserName, stringEMailPassword );

        // If there is an attachment file, also read it into memory.
        // Then call CreateSeeMessage with or without an attachment.
        if (stringAttachmentFileName.isEmpty() == false) {
            nRC = m_ZDRVROPR.CreateSeeMessage(lConnection, stringSmtpServer, stringSenderEMailAddress,
                    stringRecipientEMailAddress, "", "", stringSubjectLine, nMimeType, cbAtBodyFileName.toString(),
                    cbAtAltTextFileName.toString(), stringEmbeddedImages, 1, // has attachment
                    stringAttachmentFileName, stringEMailUserName, stringEMailPassword);
        } else {
            nRC = m_ZDRVROPR.CreateSeeMessage(lConnection, stringSmtpServer, stringSenderEMailAddress,
                    stringRecipientEMailAddress, "", "", stringSubjectLine, nMimeType, cbAtBodyFileName.toString(),
                    cbAtAltTextFileName.toString(), stringEmbeddedImages, 0, // no attachment
                    "", // blank attachment file name
                    stringEMailUserName, stringEMailPassword);
        }

        // SysFreeMemory( selBodyMemory );
        // DrFreeTaskMemory( stringBodyMemoryStart );

        return nRC;

    } // StartEmailClientWithFiles

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: SendEmailForFilesWithCC
    //
    //    Same function as SendEmailForFiles, except it supports CC and BCC copies.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int SendEmailForFilesWithCC(View ViewToWindow, View ResultSet, String stringSmtpServer,
            String stringRecipientEMailAddress, String stringSenderEMailAddress, String stringCC_EMailAddresses,
            String stringBCC_EMailAddresses, String stringEMailUserName, String stringEMailPassword,
            String stringSubjectLine, String stringBodyFileName, String stringAltTextFileName,
            String stringEmbeddedImages, String stringAttachmentFileName, int nMimeType, // 1-Text, 2-HTML
            int lConnection) {
        // String stringBodyMemoryStart;
        CharBuffer cbAtBodyFileName = CharBuffer.allocate(256);
        CharBuffer cbAtAltTextFileName = CharBuffer.allocate(256);
        // int  selBodyMemory;
        // int  lFileLth;
        zVIEW zqMDocOLST = null;
        zVIEW wXferO = null;
        int nRC;

        // TraceLine( "SendEmailForFiles Server: %s   Sender: %s   Recipient: %s"
        //            "   Subject: %s   Mime Type: %d"
        //            "   User: %s   Password %s",
        //            stringSmtpServer, stringSenderEMailAddress, stringRecipientEMailAddress,
        //            stringSubjectLine, nMimeType, stringEMailUserName, stringEMailPassword );

        // First make sure the email address is valid. If not exit with return code of 2.
        if (IsEmailAddressValid(stringRecipientEMailAddress) == false)
            return 2;

        GetViewByName(zqMDocOLST, "zqMDocOLST", ResultSet, zLEVEL_TASK);
        GetViewByName(wXferO, "wXferO", ViewToWindow, zLEVEL_TASK);

        if (stringBodyFileName != null) {
            if (stringBodyFileName.isEmpty() == false && stringBodyFileName.charAt(0) != '@') {
                cbAtBodyFileName.put(0, '@');
                zstrcpy(cbAtBodyFileName, 1, stringBodyFileName);
            } else
                zstrcpy(cbAtBodyFileName, 0, stringBodyFileName);
        } else
            cbAtBodyFileName.put(0, '\0');

        if (stringAltTextFileName != null) {
            if (stringAltTextFileName.isEmpty() == false && stringAltTextFileName.charAt(0) != '@') {
                cbAtAltTextFileName.put(0, '@');
                zstrcpy(cbAtAltTextFileName, 1, stringAltTextFileName);
            } else
                zstrcpy(cbAtAltTextFileName, 0, stringAltTextFileName);
        } else
            cbAtAltTextFileName.put(0, '\0');

        // Read the data from the Body and Attachment files into memory and call
        // StartEmailClient with those values.

        // Read the Body into memory.
        // lFileLth = ReadFileDataIntoMemory( ResultSet, stringBodyFileName,
        //                                    &selBodyMemory, &stringBodyMemoryStart );

        // Exit if the file is empty or if there is an error opening it.
        // if ( lFileLth <= 0 )
        // {
        // The memory allocated to hold the body has been freed.
        //    IssueError( ResultSet, 0, 0, "Can't open Email file." );
        //    return -1;
        // }

        if (stringSubjectLine == null || stringSubjectLine.isEmpty())
            stringSubjectLine = " ";

        // TraceLine( "SendEmailForFiles2 Server: %s   Sender: %s   Recipient: %s"
        //            "   Subject: %s   Mime Type: %d"
        //            "   User: %s   Password %s",
        //            stringSmtpServer, stringSenderEMailAddress, stringRecipientEMailAddress,
        //            stringSubjectLine, nMimeType, stringEMailUserName, stringEMailPassword );

        // If there is an attachment file, also read it into memory.
        // Then call CreateSeeMessage with or without an attachment.
        if (stringAttachmentFileName != null && stringAttachmentFileName.isEmpty() == false) {
            nRC = m_ZDRVROPR.CreateSeeMessage(lConnection, stringSmtpServer, stringSenderEMailAddress,
                    stringRecipientEMailAddress, stringCC_EMailAddresses, stringBCC_EMailAddresses,
                    stringSubjectLine, nMimeType, cbAtBodyFileName.toString(), cbAtAltTextFileName.toString(),
                    stringEmbeddedImages, 1, // has attachment
                    stringAttachmentFileName, stringEMailUserName, stringEMailPassword);
        } else {
            nRC = m_ZDRVROPR.CreateSeeMessage(lConnection, stringSmtpServer, stringSenderEMailAddress,
                    stringRecipientEMailAddress, stringCC_EMailAddresses, stringBCC_EMailAddresses,
                    stringSubjectLine, nMimeType, cbAtBodyFileName.toString(), cbAtAltTextFileName.toString(),
                    stringEmbeddedImages, 0, // no attachment
                    "", // blank attachment file name
                    stringEMailUserName, stringEMailPassword);
        }

        // SysFreeMemory( selBodyMemory );
        // DrFreeTaskMemory( stringBodyMemoryStart );

        return nRC;

    } // StartEmailClientWithFiles

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: ReturnSuffixOfFileName
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public String ReturnSuffixOfFileName(String stringReturnedSuffix, String stringFileName) {
        int nPosition;

        nPosition = zstrrchr(stringFileName, '.'); // find last period
        if (nPosition >= 0) // if we found the last period ...
        {
            stringReturnedSuffix = stringFileName.substring(nPosition + 1); // ... we have our ext!
            stringReturnedSuffix = stringReturnedSuffix.toLowerCase();
        } else
            stringReturnedSuffix = ""; // initialize to empty extension

        return stringReturnedSuffix;

    } // ReturnSuffixOfFileName

    /////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: SubSectionShowHideDisableTabs
    //
    /////////////////////////////////////////////////////////////////////////////
    public int SubSectionShowHideDisableTabs(View mUser, View vSubtask, String stringTabTag) {
        return 0; // TODO fnSubSectionShowHideDisableTabs( mUser, vSubtask, stringTabTag );
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: WL_QC
    //
    //  PURPOSE:    This routine Converts an instance of a special character in
    //              a buffer and then writes out the buffer. The character to
    //              be translated is stringTransChar and any instance of it is
    //              converted to a double quote.
    //
    //  PARAMETERS: lFile - File handle
    //              stringBuffer - the string to be converted.
    //              stringTransChar - The character to be converted to a quote.
    //              nAddBlankLineCnt - Number of blank lines to append.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int WL_QC(int lFile, String stringInput, String stringTransChar, int nBlankLineCnt) throws IOException {
        View taskView = null; // TODO ??? = GetDefaultViewForActiveTask( );

        stringInput = stringInput.replaceAll(stringTransChar, "\"");
        m_KZOEP1AA.SysWriteLine(taskView, lFile, stringInput);
        while (nBlankLineCnt-- > 0)
            m_KZOEP1AA.SysWriteLine(taskView, lFile, "");

        return 0;
    }

    /////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////

    public int FixLegacyReportDate(View wXferO, View vLegacyTranscript, String stringEntity, String stringAttribute,
            String searchString) {
        String stringBlob = null;
        String stringDate = null;
        MutableInt ulBlobLth = new MutableInt(0);
        int lSearchLth = zstrlen(searchString);

        if (lSearchLth != 0) {
            stringDate = GetStringFromAttributeByContext(stringDate, wXferO, "Root", "dCurrentDate", "MonthDDYYYY",
                    64);
            // lLth = stringDate.length( );
            stringBlob = GetAddrForAttribute(stringBlob, vLegacyTranscript, stringEntity, stringAttribute);
            GetAttributeLength(ulBlobLth, vLegacyTranscript, stringEntity, stringAttribute);
            stringBlob = stringBlob.replaceAll(searchString, stringDate);

            // this could never have worked since the fixed date is not set/returned!!!  dks 2010.04.07
            return ulBlobLth.intValue();
        }

        return zCALL_ERROR;
    }

    /////////////////////////////////////////////////////////////////////////////
    //
    //  Return number of entities written.
    //
    /////////////////////////////////////////////////////////////////////////////
    public int CreateBlobsFromLegacyTranscript(View vSubtask, String stringObjectName,
            String stringLegacyAttributeName, String stringLegacyTranscriptFileSpec) {
        // TODO
        return 0; // fnCreateBlobsFromLegacyTranscript( vSubtask, stringObjectName,
                  //                                    stringLegacyAttributeName, stringLegacyTranscriptFileSpec );
    }

    int AddAttributeToCSV(CharBuffer cb, int nLth, View lLibPers, String entityName, String attributeName,
            boolean bNumeric) {
        String s = null;

        cb.put(0, '"'); // opening quote

        // if ( bNumeric )
        // {
        s = GetStringFromAttribute(s, lLibPers, entityName, attributeName);
        nLth = zstrcpy(cb, 1, s);
        // }
        // else
        // {
        //    String stringAttrib;
        //
        //    GetAddrForAttribute( &stringAttrib, lLibPers, entityName, stringAttribute );
        //    zstrcpy( stringBuffer, stringAttrib );
        // }

        s = cb.toString();
        if (s.indexOf('"', 1) > 0) {
            s = s.replace("\"", "\"\" "); // double any quotes ...
            s = s.substring(1); // except the first one
        }

        s += "\","; // terminating quote plus comma
        nLth = zstrcpy(cb, 0, s);
        return nLth;
    }

    int WriteCSV_RecordFromEntity(View lLibPers, String entityName, int lFile) throws IOException {
        CharBuffer charBuffer = CharBuffer.allocate(32000);
        int nLth;

        charBuffer.put(0, '"');
        charBuffer.put(1, entityName.charAt(0)); // S E P (Student Employee Prospect)
        charBuffer.put(2, '"');
        charBuffer.put(3, ',');
        nLth = 4;

        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, entityName, "Status", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "CampusID", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "ID", true);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "LastName", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "FirstName", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "MiddleName", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "Suffix", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "PreferedFirstName", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "Gender", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "MaritalStatus", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "HomePhone", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "WorkPhone", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "Extension", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "eMailAddress", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Person", "DateOfBirth", false);
        if (CheckExistenceOfEntity(lLibPers, "Address") == 0) {
            nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Address", "Line1", false);
            nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Address", "City", false);
            nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Address", "StateProvince", false);
            nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Address", "PostalCode", false);
            nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "Address", "Country", false);
        } else {
            charBuffer.put(nLth++, ',');
            charBuffer.put(nLth++, ',');
            charBuffer.put(nLth++, ',');
            charBuffer.put(nLth++, ',');
            charBuffer.put(nLth++, ',');
        }

        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, entityName, "ID", false);
        nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, entityName, "eMailAddress", false);
        if (entityName.charAt(0) == 'S') {
            nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, entityName, "CurrentLevel", false);
            nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, "AdministrativeDivision", "Name", false);
            nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, entityName, "ClearingHouseGradDate", false);
        } else if (entityName.charAt(0) == 'P') {
            nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, entityName, "ExpectedEntryTerm", false);
            nLth += AddAttributeToCSV(charBuffer, nLth, lLibPers, entityName, "ExpectedEntryYear", false);
        }

        if (nLth > 0 && charBuffer.get(nLth - 1) == ',')
            charBuffer.put(nLth - 1, '\0'); // drop terminating ',' and null terminate
        else
            charBuffer.put(nLth++, '\0'); // ensure null termination

        m_KZOEP1AA.SysWriteLine(lLibPers, lFile, charBuffer.toString());
        return nLth;
    }

    /////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: WriteLibraryOLCN
    //
    /////////////////////////////////////////////////////////////////////////////
    public int WriteLibraryOLCN(View lLibPers, int lFile) throws IOException {
        int lCnt = 0;
        int nRC;

        nRC = SetCursorFirstEntity(lLibPers, "Person", "");
        while (nRC >= zCURSOR_SET) {
            if (CheckExistenceOfEntity(lLibPers, "Student") == 0) {
                WriteCSV_RecordFromEntity(lLibPers, "Student", lFile);
                lCnt++;
            } else if (CheckExistenceOfEntity(lLibPers, "Employee") == 0) {
                WriteCSV_RecordFromEntity(lLibPers, "Employee", lFile);
                lCnt++;
            } else if (CheckExistenceOfEntity(lLibPers, "Prospect") == 0) {
                WriteCSV_RecordFromEntity(lLibPers, "Prospect", lFile);
                lCnt++;
            }

            nRC = SetCursorNextEntity(lLibPers, "Person", "");
        }

        return lCnt;
    }

    /**
       int
       TraceLastError( DWORD dwError )
       {
          String lpMsgBuf;
          String stringBuffer;
          zULONG ulLth = sizeof( stringBuffer );
        
          FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
                  FORMAT_MESSAGE_IGNORE_INSERTS, null, dwError,
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                  lpMsgBuf, 0, null );
        
          if ( lpMsgBuf && lpMsgBuf )
          {
      TraceLineI( "Win32 Error Message: ", dwError );
      TraceLineS( "Win32 Error Message: ", (String) lpMsgBuf );
          }
        
          // Free the buffer.
          LocalFree( lpMsgBuf );
        
          InternetGetLastResponseInfo( dwError, stringBuffer, ulLth );
          if ( ulLth > 0 )
      TraceLineS( "Internet error: ", stringBuffer );
        
          return 0;
       }
        
       public int
       FTPSendFile( View   vSubtask,
             String stringServerAddress,
             String stringUserName,
             String stringPassword,
             String stringLocalFileName,
             String stringServerFileName,
             int  lControl )
       {
          int    nRC         = 0;
          HINTERNET hConnection = 0;
          HINTERNET hFtp        = 0;
        
          hConnection = InternetOpen( "ftp", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0,
                               INTERNET_FLAG_ASYNC );
          do  // purist's goto
          {
          if ( hConnection == 0 )
          {
      DWORD dwError = GetLastError();
      TraceLineS( "*ERROR*", "" );
      TraceLastError( dwError );
      TraceLineS( "Server Address   = ", stringServerAddress );
      TraceLineS( "User Name        = ", stringUserName );
      TraceLineS( "Local File Name  = ", stringLocalFileName );
      TraceLineS( "Server File Name = ", stringServerFileName );
      MessageSend ( vSubtask,
                    "AD0450",
                    "FTP",
                    "Error creating an internet connection.",
                    zMSGQ_OBJECT_CONSTRAINT_ERROR, 0 );
      break;
          }
        
          hFtp = InternetConnect( hConnection, stringServerAddress, INTERNET_DEFAULT_FTP_PORT,
                           stringUserName, stringPassword, INTERNET_SERVICE_FTP, 0, 0 );
          if ( hFtp == 0 )
          {
      DWORD dwError = GetLastError();
      TraceLineS( "*ERROR*", "" );
      TraceLastError( dwError );
      TraceLineS( "Server Address   = ", stringServerAddress );
      TraceLineS( "User Name        = ", stringUserName );
      MessageSend ( vSubtask,
                    "AD0451",
                    "FTP",
                    "Error connecting to ftp server.",
                    zMSGQ_OBJECT_CONSTRAINT_ERROR, 0 );
      break;
          }
        
          if ( !FtpPutFile( hFtp, stringLocalFileName, stringServerFileName,
                     FTP_TRANSFER_TYPE_BINARY, 0 ) )
          {
      DWORD dwError = GetLastError();
      TraceLineS( "*ERROR*", "" );
      TraceLastError( dwError );
      TraceLineS( "Server Address   = ", stringServerAddress );
      TraceLineS( "User Name        = ", stringUserName );
      TraceLineS( "Local File Name  = ", stringLocalFileName );
      TraceLineS( "Server File Name = ", stringServerFileName );
      MessageSend ( vSubtask,
                    "AD0452",
                    "FTP",
                    "Error sending file to the server.",
                    zMSGQ_OBJECT_CONSTRAINT_ERROR, 0 );
      break;
          }
          // If we get here then everything's ok, so set return value.
          nRC = 1;
        
          }  while ( false );  // end of purist's goto
        
          if ( hConnection != 0 )
      InternetCloseHandle( hConnection );
        
          if ( hFtp != 0 )
      InternetCloseHandle( hFtp );
        
          return nRC;
       }
    **/

    //////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //Method Name: ConvertISIR_NumberToAttribute
    //
    //////////////////////////////////////////////////////////////////////////////////////////////////
    public int ConvertISIR_NumberToAttribute(View tgtView, String tgtEntityName, String tgtAttributeName,
            String stringISIR_Value) {
        String stringValue;
        String stringMsg;
        char charSign;
        char charLastCharacter = 0;
        char charLastDigit = 0;
        int lValue;
        int nLth;
        @SuppressWarnings("unused")
        int nRC;

        // Convert stringISIR_Value from a signed string to the attribute passed into the operation.
        if (stringISIR_Value == null || stringISIR_Value.isEmpty())
            SetAttributeFromString(tgtView, tgtEntityName, tgtAttributeName, "");
        else {
            nLth = stringISIR_Value.length();
            stringValue = stringISIR_Value;
            if (stringValue.compareTo("N/A") == 0)
                stringValue = null; // A value of N/A is converted to null.
            else
                charLastCharacter = stringISIR_Value.charAt(nLth - 1);

            if (stringValue == null) {
                // The value is null, so set result to null.
                SetAttributeFromString(tgtView, tgtEntityName, tgtAttributeName, "");
            } else {
                if (charLastCharacter >= '0' && charLastCharacter <= '9')
                    charSign = '\0';
                else {
                    charSign = charLastCharacter;

                    // Convert last character to digit.
                    switch (charLastCharacter) {
                    case '}':
                    case '{':
                        charLastDigit = '0';
                        break;

                    case 'A':
                    case 'J':
                        charLastDigit = '1';
                        break;

                    case 'B':
                    case 'K':
                        charLastDigit = '2';
                        break;

                    case 'C':
                    case 'L':
                        charLastDigit = '3';
                        break;

                    case 'D':
                    case 'M':
                        charLastDigit = '4';
                        break;

                    case 'E':
                    case 'N':
                        charLastDigit = '5';
                        break;

                    case 'F':
                    case 'O':
                        charLastDigit = '6';
                        break;

                    case 'G':
                    case 'P':
                        charLastDigit = '7';
                        break;

                    case 'H':
                    case 'Q':
                        charLastDigit = '8';
                        break;

                    case 'I':
                    case 'R':
                        charLastDigit = '9';
                        break;

                    default:
                        stringMsg = "Unexpected Sign for the following data and attribute:   Entity Name: "
                                + tgtEntityName + zNEW_LINE + "   Attribute Name: " + tgtAttributeName + zNEW_LINE
                                + "   Data Value: " + stringISIR_Value;
                        IssueError(tgtView, 0, 0, stringMsg);
                    }

                    stringValue = stringValue.substring(0, nLth - 2) + charLastDigit;
                }

                lValue = StrToInt(stringValue);

                if (charSign == '}' || (charSign >= 'J' && charSign <= 'Z'))
                    lValue = -lValue;

                nRC = SetAttributeFromInteger(tgtView, tgtEntityName, tgtAttributeName, lValue);
            }
        }

        return 0;
    }

    // ConvertISIR_NumberToAttribute

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: SetEntityCursorByInteger
    //    Does a SetEntityCursor for an Integer, since the regular SetEntityCursor doesn't work for
    //    an integeri in VML.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int SetEntityCursorByInteger(View view, String entityName, String attributeName, int cursorPosition,
            int lIntegerSearchValue, String stringScopingEntityName) {
        int nRC;

        nRC = SetEntityCursor(view, entityName, attributeName, cursorPosition, lIntegerSearchValue, "", "", 0,
                stringScopingEntityName, "");
        return nRC;
    } // SetEntityCursorByInteger

    public int PositionOnEntityByZID(View vLDD, String pchZID) {
        String pchDot;
        int nDot1;
        int nDot2;
        int nRC;

        if (pchZID == null || pchZID.isEmpty())
            return 0;

        nDot1 = zstrchr(pchZID, '.');
        if (nDot1 >= 0)
            pchDot = pchZID.substring(0, nDot1 - 1);
        else
            pchDot = pchZID;

        nRC = SetCursorFirstEntityByString(vLDD, "MasterLabelContent", "ID", pchDot, "");
        if (nRC == zCURSOR_SET) {
            if (nDot1 < 0)
                return 1; // found MasterLabelContent

            nDot1++;
            nDot2 = zstrchr(pchZID, nDot1, '.');
            if (nDot2 >= 0)
                pchDot = pchZID.substring(nDot1, nDot2 - 1);
            else
                pchDot = pchZID.substring(nDot1);

            nRC = SetCursorFirstEntityByString(vLDD, "MasterLabelSection", "ID", pchDot, "");
            if (nRC == zCURSOR_SET) {
                if (nDot2 < 0)
                    return 2; // found MasterLabelSection

                pchDot = pchZID.substring(nDot2 + 1);
                nRC = SetCursorFirstEntityByString(vLDD, "MasterLabelParagraph", "ID", pchDot, "");
                if (nRC == zCURSOR_SET)
                    return 3; // found MasterLabelParagraph
            }
        }

        return -1; // did not find proper entity
    }

    /////////////////////////////////////////////////////////////////////////////
    //
    // OPERATION: DetermineNextVersion
    //
    // Determine the next available version.  If the current version is 1.2 and
    // version 1.3 exists, the next available version is 1.2.1, otherwise, the
    // next available version is 1.3.
    //
    // Algorithm:  Match dots and sub-versions.  If second runs out of dots or
    //      has a greater corresponding sub-version, simply increment the final
    //      sub-version of the first version as the new version.  Otherwise, keep
    //      adding the second's sub-version on to the end if the first and, if
    //      necessary, add a new sub-version.
    //
    /////////////////////////////////////////////////////////////////////////////
    public String DetermineNextVersion(String pchVersionNew, View vListVersionIn, String cpcListVersionEntity,
            String cpcListVersionAttribute) {
        // "SubregLabelContent", "Version", mSubProd, "SubregLabelContent", "Version" )
        zVIEW vListVersion = null;
        String pch;
        String pchDot1;
        String pchDot2;
        String pchDotNext1;
        String pchDotNext2;
        String szVersion = null;
        String szVersionNext = null;
        int lVersion = 0;
        int lVersionNext = 0;
        int nDot1 = 0;
        int nDot2 = 0;
        int nDotNext2 = 0;
        int nDotCnt = 0;
        int nDotCntNext = 0;
        int nRC;

        CreateViewFromView(vListVersion, vListVersionIn);
        szVersion = GetStringFromAttribute(szVersion, vListVersion, cpcListVersionEntity, cpcListVersionAttribute);
        nRC = SetCursorNextEntity(vListVersion, cpcListVersionEntity, "");
        if (nRC == zCURSOR_SET)
            szVersionNext = GetStringFromAttribute(szVersionNext, vListVersion, cpcListVersionEntity,
                    cpcListVersionAttribute);
        else
            szVersionNext = "";

        /* test stuff
        zstrcpy( szVersion, "1.2" );
        zstrcpy( szVersionNext, "1.3" );
        zstrcpy( szVersion, "1.2" );
        zstrcpy( szVersionNext, "1.2.1" );
        zstrcpy( szVersion, "1.2" );
        zstrcpy( szVersionNext, "2" );
        zstrcpy( szVersion, "1" );
        zstrcpy( szVersionNext, "" );
        end of test stuff */

        // Count the number of Dots and compare the sub-versions in the two versions and determine
        // where the versions quit matching up.
        pchDot1 = szVersion;
        pchDotNext1 = szVersionNext;
        do {
            nDot2 = zstrchr(pchDot1, '.');
            nDotNext2 = zstrchr(pchDotNext1, '.');
            if (nDot2 >= 0) // still more versions for first
            {
                nDotCnt++;
                pch = pchDot1.substring(0, nDot2 - 1);
                lVersion = zatol(pch);
                pchDot1 = pchDot1.substring(0, nDot2 + 1);
            } else {
                lVersion = zatol(pchDot1);
                pchDot1 = null;
            }

            if (nDotNext2 >= 0) // still more versions for second
            {
                nDotCntNext++;
                pch = pchDotNext1.substring(0, nDotNext2 - 1);
                lVersionNext = zatol(pch);
                pchDotNext1 = pchDotNext1.substring(0, nDotNext2 + 1);
            } else {
                lVersionNext = zatol(pchDotNext1);
                pchDotNext1 = null;
            }

            if ((lVersionNext > lVersion + 1) || (lVersionNext > lVersion && pchDot1 != null && pchDotNext1 == null)
                    || (lVersionNext == 0)) {
                // Simply increment final sub-version of the first version.
                pchVersionNew = zstrcpy(pchVersionNew, szVersion);
                nDot1 = zstrrchr(pchVersionNew, '.');
                if (nDot1 >= 0)
                    pchDot1 = pchVersionNew.substring(nDot1 + 1);
                else
                    pchDot1 = pchVersionNew;

                lVersion = zatol(pchDot1);
                lVersion++;
                pchDot1 = zltoa(lVersion, pchDot1); // now pchVersionNew contains the next version
                break; // we are done ... get out of loop
            }

            if (pchDot1 == null || pchDotNext1 == null) {
                pchVersionNew = zstrcpy(pchVersionNew, szVersion);
                if (pchDotNext1 != null) // something in second version
                {
                    lVersionNext = zatol(pchDotNext1);
                    pchVersionNew += '.';
                    pchVersionNew += zltoa(lVersionNext - 1, pchVersionNew); // now pchVersionNew contains the next version
                } else {
                    // On the last version for both ... just extend the next version
                    pchVersionNew = zstrcat(pchVersionNew, ".5");
                }

                break; // we are done ... get out of loop
            }

        } while (pchDot1 != null);

        DropView(vListVersion);
        return pchVersionNew;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: CheckForTableAttribute
    //    Check if an attribute has a table domain
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int CheckForTableAttribute(View lpView, String entityName, String attributeName,
            String stringObjectName) {
        zVIEW vXOD = null;
        zVIEW vXDM = null;
        StringBuilder sbFileName = new StringBuilder(0);
        String stringDomainName = null;
        String stringDomainType = null;
        int cursorPosition;
        int nRC;

        // Check if the attribute passed has a table domain.
        // A 0 indicates it does.
        // A 1 indicates it does not.

        // If necessary, activate the XOD for the requested object.
        nRC = GetViewByName(vXOD, "FindTableXOD", lpView, zLEVEL_TASK);
        if (nRC < 0) {
            GetApplDirectoryFromView(sbFileName, lpView, zAPPL_DIR_OBJECT, 300);
            zstrcat(sbFileName, stringObjectName);
            zstrcat(sbFileName, ".XOD");
            // 536870912 is ACTIVATE_SYSTEM in the following activate statement.
            ActivateOI_FromFile(vXOD, "TZZOXODO", lpView, sbFileName.toString(), zACTIVATE_ROOTONLY_MULTIPLE); // zACTIVATE_SYSTEM 536870912 );
            SetNameForView(vXOD, "FindTableXOD", lpView, zLEVEL_TASK);
        }

        // Position on correct entity and attribute (using recursive set cursor on entity) and
        // retrieve Domain Name.
        ResetView(vXOD);
        cursorPosition = zPOS_FIRST; // TODO to get by an error zQUAL_STRING + zPOS_FIRST + zRECURS;
        SetEntityCursor(vXOD, "ENTITY", "NAME", cursorPosition, entityName, "", "", 0, "OBJECT", "");

        SetCursorFirstEntityByString(vXOD, "ATTRIB", "NAME", attributeName, "");
        GetStringFromAttribute(stringDomainName, vXOD, "ATTRIB", "DOMAIN");
        //TraceLineS( "Domain Name: ", stringDomainName );

        // If necessary, activate the XDM containing all Domain data.
        nRC = GetViewByName(vXDM, "FindTableXDM", lpView, zLEVEL_TASK);
        if (nRC < 0) {
            GetApplDirectoryFromView(sbFileName, lpView, zAPPL_DIR_OBJECT, 300);
            zstrcat(sbFileName, "zeidon.xdm");
            ActivateOI_FromFile(vXDM, "TZDMXGPO", lpView, sbFileName.toString(), zACTIVATE_ROOTONLY_MULTIPLE); // zACTIVATE_SYSTEM 536870912 );
            SetNameForView(vXDM, "FindTableXDM", lpView, zLEVEL_TASK);
        }

        // Position on the correct Domain and retrieve the Domain Type, which is "T" for Table Domains.
        SetCursorFirstEntityByString(vXDM, "Domain", "Name", stringDomainName, "");
        stringDomainType = GetStringFromAttribute(stringDomainType, vXDM, "Domain", "DomainType");

        // Set return code base on whether or not the Domain is a Table.
        if (stringDomainType.charAt(0) == 'T')
            return 0;
        else
            return 1;

    } // CheckForTableAttribute

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AD_AuthenticateUserPassword
    //    Authenticate User Name and Password against Active Directory.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AD_AddUserPassword
    //    Add Active Directory User and Password
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int AD_AddUserPassword(String stringServerName, String stringServerPort, String stringOrganization,
            String stringUserName, String stringUserPassword) {
        return m_ActiveDirectory.ActiveDirectoryAddUser(stringServerName, stringServerPort, stringOrganization,
                stringUserName, stringUserPassword);

    } // AD_AddUserPassword

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AD_RemoveUserPassword
    //    Remove Active Directory User with Password
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int AD_RemoveUserPassword(String stringServerName, String stringServerPort, String stringOrganization,
            String stringUserName) {
        return m_ActiveDirectory.ActiveDirectoryRemoveUser(stringServerName, stringServerPort, stringOrganization,
                stringUserName);

    } // AD_RemoveUserPassword

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AD_ChangeUserPassword
    //    Change the user password through Active Directory
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int AD_ChangePassword(String stringAD_Pathname, String stringAD_LoginUserName,
            String stringAD_LoginPassword, String stringAD_UserName, String stringAD_OldPassword,
            String stringAD_NewPassword) {
        return m_ActiveDirectory.ActiveDirectoryChangePassword(stringAD_Pathname, stringAD_LoginUserName,
                stringAD_LoginPassword, stringAD_UserName, stringAD_OldPassword, stringAD_NewPassword);

    } // AD_ChangeUserPassword

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AD_SetPassword
    //    Set password in  Active Directory
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int AD_SetPassword(String stringAD_Pathname, String stringAD_LoginUserName,
            String stringAD_LoginPassword, String stringAD_UserName, String stringAD_Password) {
        return m_ActiveDirectory.ActiveDirectorySetPassword(stringAD_Pathname, stringAD_LoginUserName,
                stringAD_LoginPassword, stringAD_UserName, stringAD_Password);
    }

    // AD_SetPassword

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AD_AddNewUser
    //    Add a new user to Active Directory
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int AD_AddNewUser(String stringAD_Pathname, String stringAD_LoginUserName, String stringAD_LoginPassword,
            String stringAD_NewUserName, String stringAD_NewUserPassword) {
        return m_ActiveDirectory.ActiveDirectoryAddUser(stringAD_Pathname, stringAD_LoginUserName,
                stringAD_LoginPassword, stringAD_NewUserName, stringAD_NewUserPassword);

    } // AD_AddNewUser

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AD_GetUserProperty
    //    Get the value of an Active Directory property for the user.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int AD_GetUserProperty(String stringAD_Pathname, String stringAD_UserName, String stringAD_Password,
            String stringAD_Property, StringBuilder stringReturnProperty) {
        return m_ActiveDirectory.ActiveDirectoryGetProperty(stringAD_Pathname, stringAD_UserName, stringAD_Password,
                stringAD_Property, stringReturnProperty);

    } // AD_GetUserProperty

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: ValidateAndSetState
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int ValidateAndSetState(View view, String entityName, String attributeName, String stringStateString) {
        StringBuilder sbTableValue = new StringBuilder();
        MutableInt Pointer = null;
        int lFoundFlag = 0;
        int nRC;

        nRC = GetFirstTableEntryForAttribute(sbTableValue, view, entityName, attributeName, "", Pointer);
        while (lFoundFlag == 0 && nRC >= 0) {
            TraceLineS("//* Domain Value: ", sbTableValue.toString());
            if (zstrcmp(stringStateString, sbTableValue.toString()) == 0)
                lFoundFlag = 1;

            nRC = GetNextTableEntryForAttribute(sbTableValue, view, entityName, attributeName, "", Pointer);
        }

        if (lFoundFlag == 0)
            return -1; // String was NOT found.
        else {
            // String WAS found.
            SetAttributeFromString(view, entityName, attributeName, stringStateString);
            return 0;
        }

    } // ValidateAndSetState

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: SetStringUpperLowerCase
    //    Set characters in a string to a combination of upper and lower case, with the 1st character
    //    of each "word" in the string to be in upper case and the remainder in lower case.  Eliminate
    //    leading and trailing whitespace and multiple consecutive whitespace characters.  Also check
    //    for Roman Numeral suffix and upper case as necessary.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int SetStringUpperLowerCase(StringBuilder sbName) {
        String string;
        boolean bSuffix = false;
        int nBlankFound = 0;
        @SuppressWarnings("unused")
        int nLth;
        int k;
        int j;

        // Eliminate leading and trailing blanks.
        string = sbName.toString();
        string = string.trim();

        // Force first character to be upper case
        StringBuffer sb = new StringBuffer(string.toLowerCase()); // force string to lower case
        sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));

        for (k = 1; k < sb.length(); k++) {
            // Eliminate multiple consecutive blanks.
            if (sb.charAt(k) == ' ') {
                j = k;
                while (sb.charAt(j + 1) == ' ')
                    j++;

                if (j > k)
                    sb.delete(k + 1, j);
            } else
            // if ( sb.charAt( k ) != ' ' )
            {
                if (sb.charAt(k - 1) == ' ') {
                    nBlankFound++;
                    char ch = Character.toUpperCase(sb.charAt(k));
                    sb.setCharAt(k, ch);

                    if (ch == 'I' || ch == 'V')
                        bSuffix = true;
                    else
                        bSuffix = false;
                } else {
                    if (nBlankFound > 1 && bSuffix) // checking for II or III or IV or V or VI or VII or VIII
                    {
                        if ((sb.charAt(k) == 'i' || sb.charAt(k) == 'v') && (sb.charAt(k + 1) == '\0'
                                || sb.charAt(k + 1) == 'i' || sb.charAt(k + 1) == 'v')) {
                            sb.setCharAt(k, Character.toUpperCase(sb.charAt(k)));
                        } else
                            bSuffix = false;
                    } else {
                        bSuffix = false; // can't start with suffix
                    }
                }
            }
        }

        zstrcpy(sbName, sb.toString());
        return sbName.length();

    } // SetStringUpperLowerCase

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: SetAttributeFromUC_String
    //    Set Attribute from String, converting string to upper case.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int SetAttributeFromUC_String(View tgtView, String tgtEntityName, String tgtAttributeName,
            String srcString) {

        // Convert srcString to upper case and store it in the attribute.
        SetAttributeFromString(tgtView, tgtEntityName, tgtAttributeName, srcString.toUpperCase());

        return 0;
    } // SetAttributeFromUC_String

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: SetAttributeFromUC_Attribute
    //    Set Attribute from Attribute, converting the source string to upper case in the process.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int SetAttributeFromUC_Attribute(View tgtView, String tgtEntityName, String tgtAttributeName,
            View srcView, String srcEntityName, String srcAttributeName) {
        String srcString = null;

        // Convert source attribute value to upper case and store it in the target attribute.
        // zToUpper prototype is in TZVMLIP.H
        srcString = GetStringFromAttribute(srcString, srcView, srcEntityName, srcAttributeName);
        SetAttributeFromString(tgtView, tgtEntityName, tgtAttributeName, srcString.toUpperCase());

        return 0;
    } // SetAttributeFromUC_Attribute

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Method Name: AD_SetUserProperty
    //    Set an AD property for a user
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public int AD_SetUserProperty(String stringAD_Pathname, String stringAD_AdminName,
            String stringAD_AdminPassword, String stringAD_UserName, String stringAD_PropertyName,
            String stringAD_PropertyValue) {
        int nRC;

        nRC = m_ActiveDirectory.ActiveDirectorySetProperty(stringAD_Pathname, stringAD_AdminName,
                stringAD_AdminPassword, stringAD_UserName, stringAD_PropertyName, stringAD_PropertyValue);
        return nRC;

    } // AD_SetUserProperty

    /////////////////////////////////////////////////////////////////////////////
    //
    //OPERATION: InsertUsageWordsIntoString
    //
    /////////////////////////////////////////////////////////////////////////////
    public int InsertUsageWordsIntoString(View view, StringBuilder sbString, // original data and return data
            int lMaxLth, String szUsageType, String szUsageKeyword, String szUsageEntityName,
            String szSeparatorCharacters) {
        /****
          zVIEW  viewT;
          String  szCurrentType[ 2 ];
          String  szCurrentName[ 51 ];
          String pchFromString;
          String pchToString;
          String pchToStringHold;
          int    lMemHandle;
          int    nUsageKeywordLth;
          int    nSeparatorCharsLth;
          int    nNameLth;
          int    nCount;
          int    nRC;
            
          // Insert Usage text into a position in szStringArea that is identified by a Usage Keyword.
          // The entries inserted will be separated by one or more characters as identified by the variable szSeparatorCharacters.
          // After determining the position of the insertion, we will loop through Usage entries, formatting each entry as we go.
          // Which entries we insert depend on the UsageType as follows:
          // A - Insert all Usage entries.
          // C - Insert only Claim Usage entries.
          // S - Insert only Surface Usage entries.
          // T - Insert only Application Type Usage entries.
          // U - Insert only Area of Use Usage entries.
            
          // Copy all characters up to the point of the keyword. If there is no keyword match, we simply copy all characters.
          // If we get a match on the keyword, insert the characters and finish copying the rest of the text.
            
          lMemHandle = SysAllocMemory( &pchToString, lMaxLth, 0, zCOREMEM_ALLOC, 0 );
          pchToStringHold = pchToString;
          nSeparatorCharsLth = zstrlen( szSeparatorCharacters );
          nUsageKeywordLth = zstrlen( szUsageKeyword );
          pchFromString = pchString;
          while ( *pchFromString )
          {
             // Compare the keyword to the characters in the string.
             if ( zstrncmp( pchFromString, szUsageKeyword, nUsageKeywordLth ) == 0 )
             {
         // There was a keyword match ... insert Usage entries.
         nCount = 0;
         nRC = SetCursorFirstEntity( view, szUsageEntityName, "" );
         while ( nRC >= zCURSOR_SET )
         {
            GetVariableFromAttribute( szCurrentType, 0, zTYPE_STRING, 2, view, szUsageEntityName, "Type", 0, 0 );
            GetVariableFromAttribute( szCurrentName, 0, zTYPE_STRING, 51, view, szUsageEntityName, "Name", 0, 0 );
            
            // Insert this entry, if the Usage entry is the same Type or "All" is requested.
            if ( szUsageType[ 0 ] == 'A' || szUsageType[ 0 ] == szCurrentType[ 0 ] )
            {
               nNameLth = zstrlen( szCurrentName );
               // For any entry but the first or last, copy the separator characters.
               // For the first entry, don't add any characters at all.
               // For the last entry, add the characters "and".
               nCount++;
               CreateViewFromView( &viewT, view );
               if ( szUsageType[ 0 ] == 'A' )
                  nRC = SetCursorNextEntity( viewT, szUsageEntityName, "" );
               else
                  nRC = SetCursorNextEntityByString( viewT, szUsageEntityName, "Type", szUsageType, "" );
            
               DropView( viewT );
               if ( nRC < zCURSOR_SET )
               {
                  zstrcpy( pchToString, " and " );
                  pchToString += 5;
               }
               else
               {
                  if ( nCount > 1 )
                  {
                     zstrcpy( pchToString, szSeparatorCharacters );
                     pchToString += nSeparatorCharsLth;
                  }
               }
            
               zstrcpy( pchToString, szCurrentName );
               nNameLth = zstrlen( szCurrentName );
               pchToString += nNameLth;
            }
            
            nRC = SetCursorNextEntity( view, szUsageEntityName, "" );
         }
            
         pchFromString = pchFromString + nUsageKeywordLth;    // skip past keyword
             }
             else
             {
         // There was no keyword match, simply copy the character.
         *pchToString = *pchFromString;
         pchToString++;
         pchFromString++;
             }
          }
            
          zstrcpy( pchString, pchToStringHold );  // copy data back into original string
          SysFreeMemory( lMemHandle  );
        ****/

        return 0;

    } // InsertUsageWordsIntoString

    /////////////////////////////////////////////////////////////////////////////
    //
    // OPERATION: SeparateNumberedStatement
    //
    // Separate a numbered statement into the number and the rest of the
    // statement. A return code of -1 means the text didn't start with a number.
    /////////////////////////////////////////////////////////////////////////////
    public int SeparateNumberedStatement(String pchOriginalStatement, int lMaxLth, String pchNumberedText) {
        String pchRemainingText;
        int lMemHandle;
        int nCount;
        /***
            // Separate a numbered statement into the number and the rest of the statement.
            // A return code of -1 means the text didn't start with a number.
            
            lMemHandle = SysAllocMemory( &pchRemainingText, lMaxLth, 0, zCOREMEM_ALLOC, 0 );
            pchRemainingText[ 0 ] = 0;
            if ( isdigit( *pchOriginalStatement ))
            {
               // The first character is a digit, so separate the non-blank chars from the rest.
            
               // First separate numbered text.
               nCount = 0;
               while ( *pchOriginalStatement != ' ' && *pchOriginalStatement != 0 )
               {
          // Make sure text doesn't go over 5 characters.
          nCount++;
          if ( nCount > 5 )
          {
             SysFreeMemory( lMemHandle  );
             return( -2 );
          }
            
          *pchNumberedText = *pchOriginalStatement;
          pchNumberedText++;
          pchOriginalStatement++;
               }
            
               *pchNumberedText = 0;
            
               // Skip next nonblank text.
               while ( *pchOriginalStatement == ' ' && *pchOriginalStatement != 0 )
          pchOriginalStatement++;
            
               // Copy rest of text.
               zstrcpy( pchRemainingText, pchOriginalStatement );
            }
            else
            {
               // The first character is not a digit, so return with RC -1.
               SysFreeMemory( lMemHandle  );
               return( -1 );
            }
            
            zstrcpy( pchOriginalStatement, pchRemainingText );  // copy data back into original string
            SysFreeMemory( lMemHandle  );
        ***/

        return (0);

    } // SeparateNumberedStatement

    public int WinShellExecute(View viewToWindow, String szTempString_0, String string, String string2) {
        // TODO Auto-generated method stub
        return 0;
    }

    public String GetImagingPath(View viewToWindow, int i, String szPathName) {
        // TODO Auto-generated method stub
        return null;
    }

    public int FTPSendFile(View viewToSubtask, String szURL, String szLoginName, String szPassword,
            String szFullFileName, String szTargetFileName, int i) {
        // TODO Auto-generated method stub
        return 0;
    }

    /*************************************************************************************************
    **    
    **    OPERATION: CopyFileToPDF
    **    Copy a file to a pdf file.
    **    
    *************************************************************************************************/
    public int CopyFileToPDF(View vMapObject, String szFileToCopy, String szPDFName) {
        zVIEW vKZXMLPGO = null;
        String szCommandLine = null;
        String szPathFileName = null;
        String szFileName = null;

        zstrcpy(szCommandLine, "copypdf.bat \"");
        zstrcat(szCommandLine, szFileToCopy);
        zstrcat(szCommandLine, "\"");

        // KJS 01/05/11 - When we move to java I don't think we will be able to do this anymore.
        // Need to keep JODConverter in mind:http://stackoverflow.com/questions/586411/is-there-a-free-way-to-convert-rtf-to-pdf

        //system( szCommandLine );
        try {
            Runtime.getRuntime().exec(szCommandLine);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // KJS 02/20/2009 - We would like our pdfs to be created in a separate directory.
        // Use PDF_PathFileName to get this.  Currently I have this set as /zencas/pdf/ but
        // I know Aadit would like to put these in a totally different directory not under
        // zencas.  Might need to change something because I had a hard time getting a file
        // to open when PDF_PathFileName was something like "C:\Program Files...".
        StringBuilder sb_szPathName;
        sb_szPathName = new StringBuilder(200);
        //SysReadZeidonIni( -1, "[App.Zencas]", "WebDirectory", sb_szDirectoryName );
        m_KZOEP1AA.SysReadZeidonIni(-1, "Workstation", "PDF_PathFileName", sb_szPathName);
        szPathFileName = sb_szPathName.toString();

        /*
        nZRetCode = GetWorkstationApplicationValues( vMapObject, "PDF_PathFileName",
           szPathFileName, 32, &lFontSize, &lWork, &lWork, &lWork, &lWork, &lWork,
           &lWork, &lWork, &lWork, &lWork );
        */

        zstrcpy(szFileName, szPathFileName);
        zstrcat(szFileName, szPDFName);
        //szFileName += szPathFileName;
        //szFileName += ;

        // We set the report name in KZXMLPGO so that
        // we can retrieve this name in FindOpenFile (kzoejava.c) when trying to
        // open the file in the jsp files.
        GetViewByName(vKZXMLPGO, "KZXMLPGO", vMapObject, zLEVEL_TASK);
        SetAttributeFromString(vKZXMLPGO, "Session", "PrintFileName", szFileName);
        //pchReportName );
        SetAttributeFromString(vKZXMLPGO, "Session", "PrintFileType", "pdf");
        return (0);
    } // CopyFileToPDF
}