<%  
H TEXT('iceCap: Emulator')
H BNDDIR('ICECAPEML')
/* ---------------------------------------------------------------------------------------- */
/* Copyright [2009] [System & Method Technologies]                                          */
/*                                                                                          */
/* Licensed under the Apache License, Version 2.0 (the "License");                          */
/* you may not use this file except in compliance with the License.                         */ 
/* You may obtain a copy of the License at                                                  */
/*                                                                                          */
/*     http://www.apache.org/licenses/LICENSE-2.0                                           */
/*                                                                                          */
/* Unless required by applicable law or agreed to in writing, software                      */
/* distributed under the License is distributed on an "AS IS" BASIS,                        */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.                 */
/* See the License for the specific language governing permissions and                      */
/* limitations under the License.                                                           */
/* ---------------------------------------------------------------------------------------- */
/*                                                                                          */
/* Project . . . : IceBreak                                                                 */
/* Design  . . . : Niels Liisberg / Bent Ronne / Claus Rytter Larsen                        */
/* Function  . . : Demo program which implements a tiny 5250 emulator i a webpage using     */
/*                 the "IceCap" API which wraps Virtual Terminal IBM API                    */
/*                                                                                          */
/*                 In this sample I use the ExtJS frame work to build the window stuff      */
/*                 but the emulator is justt plain HTML                                     */
/*                                                                                          */
/*                                                                                          */
/* By       Date       Task    Description                                                  */
/* -------- ---------- ------- ------------------------------------------------------------ */
/* NLI      01.09.2009 0000001 New program                                                  */
/* ---------------------------------------------------------------------------------------- */
/include qasphdr,iceCapEml
/include qasphdr,iceUtils
/include qasphdr,xmlparser
/include qasphdr,ilob

/* pointer and variables for xml documents */
d pCfg            s               *
d pEml            s               *
d pPanel          s               *
d pChild          s               *
d pElem           s               *
d pFields         s               *

d child           s            256    varying 

/* pointer and variables for virtuel terminal */
d pVts            s               *   inz(*null)
d vts             ds                  likeds(vtsDS) based(pvts)                                
d vtLogon         ds                  likeds(vtLogonDS)

d cfgXMLHive      s            128    varying
d cfgXML          s            128    varying
d emlXMLHive      s            128    varying
d emlXML          s            128    varying
d cfgXMLDoc       s            256    varying 
d emlXMLDoc       s            256    varying 

d prevCfgXMLHive  s            128    varying
d prevCfgXML      s            128    varying
d prevEmlXMLHive  s            128    varying
d prevEmlXML      s            128    varying

d config          ds                  likeds(emlConfigDS)
d optTxt          ds                  likeds(emlSearchValDS)
d optFld          ds                  likeds(emlSearchValDS)
d sflEnd          ds                  likeds(emlSflEndValDS)
d moreOpt         ds                  likeds(emlSearchValDS)
d moreKey         ds                  likeds(emlSearchValDS)
d panelSel        ds                  likeds(emlPanelSelDS)
d eml             ds                  likeds(emlEmulatorDS)
d options         ds                  likeds(emlSflOptDS)
d columns         ds                  likeds(emlSflColDS)
d keys            ds                  likeds(emlKeysDS)

d panelType       s             10    varying
d optTxtLin       s             10i 0
d optFldLin       s             10i 0
d sflEndLin       s             10i 0
d dtaStrLin       s             10i 0
d dtaEndLin       s             10i 0
d l               s             10i 0
d line            s            256
d prevLine        s            256
d hex00           c                   x'00'
d hex40           c                   x'40'
d hex20           c                   x'20'
d id              s             12    varying
d title           s            256    varying

d i               s             10i 0
d j               s             10i 0
d p               s             10i 0

/free  
// ------------------------------------------------------------------------------------
// Initialize
// ------------------------------------------------------------------------------------
  monitor;
    exsr main;
  on-error;
    // close all virtual terminal
    emlCloseAllSession();
  endmon;
  
  return;
// ------------------------------------------------------------------------------------
// Main
// ------------------------------------------------------------------------------------
begsr main;
  // retrieve input parameter
  clear eml;
  eml.func     = qrystr('func');
  eml.tabid    = qrystrNum('tabid');
  eml.closeApp = qrystr('close');
  eml.xScale   = num(qrystr('xScale'):'.');
  eml.yScale   = num(qrystr('yScale'):'.');
  cfgXMLHive   = qrystr('configHive');
  cfgXML       = qrystr('config');
  emlXMLHive   = qrystr('emulatorHive');
  emlXML       = qrystr('emulator');
  
	if qrystr('user') <> '';
    eml.userID   = qrystr('user');
    eml.password = qrystr('password');
  else;  
    eml.userID   = sesgetvar('sys.usr.login.ID');
    eml.password = sesgetvar('sys.usr.password');
  endif;  

  eml.ccsid = sesGetVarNum('sys.usr.ccsid');

  // load config xml
  if pCfg = *NULL or cfgXMLHive <> prevCfgXMLHive or cfgXML <> prevCfgXML;
    prevCfgXMLHive = cfgXMLHive;
    prevCfgXML     = cfgXML;
    exsr loadCfgXml;
  endif;  

  // Logon and goto IceCap Commany Entry
  eml.deviceName = '';
  pVts = emlStart(config:eml);
  if pVts = *NULL;
    return;
  endif;

  // move form values and set focus field to the virtual terminal
  // - and return key pressed, ENTER, F1, F2, etc.  
  panelType = emlGetPanelType(pVts:optTxt:*on:optFld:*on:sflEnd:*off);
  eml.keyPressed = emlSetFieldValue(pVts:config:panelType);
  
  // fire 5250 key event
  vtPressFormKey(pVts: eml.keyPressed);

  // Check for Error after request to the virtual terminal
  if emlError(pVts);
    return;
  endif;
	
	// If a break out program was registeret, the run it to grarnish the panel attribue types 
	emlRunBreakOut(pVts:config.breakOutLib:config.breakOutPgm);

  // if return to staring point 'IceCap Command Entry' or 'Sign on' 
  // close virtual terminal and set response to 'close'  
  if emlCheckAtStartingPoint(pVts:eml);
    return;
  endif;

// output the screen buffer from the IceCap API. Do some simple formating based on the attribute ( nothing fancy, just a "pre" tag)
  exsr buildResponse;

endsr;
// ------------------------------------------------------------------------------------
// build Response
// ------------------------------------------------------------------------------------
begsr buildResponse;
  SetContentType('text/html; charset=windows-1252');
  
  eml.emulator = 'simple';

  // write log
  eml.msg = '';
  emlWriteLog(config:eml:title);

// write json response
  setTrim(TRIM_BOTH);
  setEncodingType('*JSON');
  
  exsr getHints;
  
// build JSON response
  eml.msg = vts.errMsg; 
  if eml.emulator = 'simple';
    emlBuildSimpleJSON(pVts:eml:config);	
  else;
    emlBuildAdvancedJSON(pVts:eml:config:sflEnd:pPanel);	
  endif;
endsr;
// ------------------------------------------------------------------------------------
// get Hints for this screen, stored in XML document
// ------------------------------------------------------------------------------------
begsr getHints;
  // load emulator xml
  if pEml = *NULL or emlXMLHive <> prevEmlXMLHive or emlXML <> prevEmlXML;
    prevEmlXMLHive = emlXMLHive;
    prevEmlXML     = emlXML;
    exsr loadEmlXml;
  endif;  

  // try to find panel in emulator XML, if not found build hints
  title = vtWinTitle(pVts);
  if config.useHints = 'yes';
    pPanel = emlFindPanel(pVts:pEml:title);
    if pPanel = *NULL;
      panelType = emlGetPanelType(pVts:optTxt:*on:optFld:*on:sflEnd:*on);
      if panelType = 'grid';
        exsr hints2XML;
      endif;
    endif;
  else;
    pPanel = *NULL;
  endif;
  
  if pPanel = *NULL;
    eml.emulator = 'simple';
  else;
    eml.emulator = 'advanced';
  endif;
endsr;
// ------------------------------------------------------------------------------------
// build Hints
// ------------------------------------------------------------------------------------
begsr hints2XML;
// find line number for search values
  optTxtLin = 
    emlFindLineNo4SearchValue(pVts:optTxt:1:vts.winHeight);
  optFldLin = 
    emlFindLineNo4SearchValue(pVts:optFld:optTxtLin+1:vts.winHeight);
  sflEndLin = 
    emlFindLineNo4SflEndValue(pVts:sflEnd:optFldLin+1:vts.winHeight);
  if optFldLin = 0;
    optFldLin = vts.winHeight;
  endif;

  dtaStrLin = 0;
  dtaEndLin = 0;

  // get keys
  clear keys;
  i = -1;
  keys.strLin = 99;
  keys.endLin = 0;
  dow i <> keys.nbr;
    i = keys.nbr;
    keys = emlGetKeys(pVts:keys:21:vts.winHeight);
    if config.moreKeysKey <> '';
      if %lookup(config.moreKeysKey:keys.aId) = 0;
        i = keys.nbr;
      else;
        vtPressFormKey(pVts:config.moreKeysKey);
      endif;
    endif;
  enddo;

  // get options and start/end lineno for option text and data  
  clear options;
  if panelType = 'grid';
    dtaStrLin = optFldLin + 1; // TODO, if data not start right after option field text line
    dtaEndLin = sflEndLin - 1; // TODO, if data not end right before subfile end text line
    if optTxtLin > 0;
      // get options
      i = -1;
      dow i <> options.nbr;
        i = options.nbr;
        options = emlGetOptions(pVts:options:optTxtLin:optFldLin);
        if config.moreOptKey <> '';
          if %lookup(config.moreOptKey:keys.aId) = 0;
            i = options.nbr;
          else;
            vtPressFormKey(pVts:config.moreOptKey);
          endif;
        endif;
      enddo;
    endif;
    // get subfile columns
    columns = emlGetSubfileColumns(pVts:optFldLin:dtaStrLin:dtaEndLin);

    // add column header to panel selection
    for i = columns.strLin to columns.endLin;
      panelSel.nbr = panelSel.nbr + 1;
      panelSel.aLin(panelSel.nbr) = i;
      panelSel.aCol(panelSel.nbr) = 1;
      panelSel.aLen(panelSel.nbr) = vts.winWidth;
    endfor;
  endif;
  
  // save panel title and id
  pPanel = emlSavePanelId(pVts:pEml:title);
      
  // save panel selection
  emlSavePanelSelection(pVts:pPanel:panelSel);

  // start building fields
  pFields = xml_elementAdd(pPanel:XML_LAST_CHILD:'fields':'');  
  
  prevLine = '';
  for l = 1 to vts.winHeight;
    select;
    when l = dtaStrLin;
      emlSaveGrid2XML(pFields
                     :columns
                     :options
                     :optFldLin
                     :dtaStrLin
                     :dtaEndLin
                     :sflEndLin);
    when l >= dtaStrLin and l <= dtaEndLin;           // ignore subfile lines
    when l >= options.strLin and l <= options.endLin; // ignore option text lines
    when l >= columns.strLin and l <= columns.endLin; // ignore column text lines
    when l >= keys.strLin and l <= keys.endLin;       // ignore key lines
    other;                                            // save fields;
      if vts.winWidth = 80;
        line = vts.scn80x24(l);
      else;
        line = vts.scn132x27(l);
      endif;
      if line <> ' ';
        // get attribute from previous line
        if %subst(line:1:1) > hex40;
          if %subst(prevLine:vts.winWidth:1) < hex40 and
             %subst(prevLine:vts.winWidth:1) > hex20;
            line = %subst(prevLine:vts.winWidth:1) + line;
          else;
            line = hex20 + line;
          endif;
        endif;
        emlSaveFieldsFromLine2XML(pVts:eml:pFields:config:l:line);
      endif;
      prevLine = line;
    endsl;
  endfor;

  // save message line
  if config.messageLine > 0;  
    emlSaveMsgLin2XML(pFields:config.messageLine);  
  endif;    
  
  // save keys to xml
  emlSaveKeys2XML(pPanel:keys);  

  pElem = xml_locate(pEml:'/icecap');  
  xml_writeStmf(pElem:%trim(emlXMLDoc):1252);
  
  exsr loadEmlXml;
  
  pPanel = emlFindPanel(pVts:pEml:title);
endsr;
// ------------------------------------------------------------------------------------
// Load emulator XML file
// ------------------------------------------------------------------------------------
begsr loadEmlXml;
  // close, if already 'open'
  if pEml <> *NULL;
    xml_close(pEml);  
  endif;

  emlXMLDoc = emlBuildXMLPath(emlXMLHive:emlXML);

  pEml = Xml_ParseFile(
            emlXMLDoc
             :'syntax=LOOSE'
          );
  if Xml_Error(pEml);
    pEml = sesGetILOB('emlXMLDoc');  
    ILOB_Clear(pEml);

    SetResponseObject(pEml);   
    SetContentType('text/xml; charset=windows-1252');
    %>
    <?xml version="1.0" encoding="windows-1252"?>
    <icecap>
      <panels>
      </panels>
    </icecap>  
    <%
    ILOB_SaveToBinaryStream(pEml: emlXMLDoc);

    SetResponseObject(*NULL);   

    pEml = Xml_ParseFile(
              emlXMLDoc
               :'syntax=LOOSE'
            );
  endif;
endsr;
// ------------------------------------------------------------------------------------
// build and save XML document
// ------------------------------------------------------------------------------------
begsr loadCfgXml;
  clear config;
  clear optTxt;
  clear optFld;
  clear sflEnd;
  clear moreOpt;
  clear moreKey;
  
  cfgXMLDoc = emlBuildXMLPath(cfgXMLHive:cfgXML);
            
  pCfg  = Xml_ParseFile(
            cfgXMLDoc
             :'syntax=LOOSE'
          );
  if not Xml_Error(pCfg);
    config   = emlGetConfigValues(pCfg);
    optTxt   = emlGetSearchValues(pCfg:'optionText');
    optFld   = emlGetSearchValues(pCfg:'optionField');
    sflEnd   = emlGetSflEndValues(pCfg:'subfileEndText');
    panelSel = emlGetPanelSelectionValues(pCfg);
  endif;
  XML_Close(pCfg);
endSr;
/end-free