WinRunner Custom Functions

This is snapshot (with some information removed) of WinRunner custom functions for real test automation project. To deal with dependencies easier, all function are stored in one file. To navigate quickly to necessary function in WinRunner, use Ctrl_L+F8 from function invocation line, or Crtl+F and on function_name to find it in opened script.

If function copied from here doesn't work in your case, download original script file.
Note that I'm working on other projects for long time now and this information could be outdated!

To get index of functions follow:

###########################################################################################
# CREATED BY: Valdis Vitolins
# PURPOSE: Stores public functions for WinRunner scripts
# INITIAL STATE: None
# PARAMETERS: None
#
###############################
##     GLOBAL CONSTANTS      ##
###############################
public const E_ALREADY_LOGGED = 2;    # Return value for ABC_Logon test (because positive, it is interpretted as warning)
public const E_NOT_RESPONDING=-10106;  # additions for undeclared WinRunner constants
public const E_ODBC_ERROR=-10162;    
public const E_ERROR=-1;   
public const E_WARNING=1;    
public const E_HANDLING=13;  
public const DELIMITER="|";        # delimiter for variable lists
public const BATCH_TEST="ABC_!Batch";  # batch file name
public const FUNCTION_TEST="ABC_Function";  # function file name, used to remove unnecessary test invocation steps
public const TEXTBOX_MAX_LENGTH=4095;   # maximal length of textbox value, which is retrieved
public const VARIABLE_MAX_LENGTH=32736; # maximal length of variable
public const MAX_OPENED_WINDOWS=10;
public const ROOT_DIR="WR_Scripts";    # Root directory for WR scripts. It is used to get full path
public const DATA_DIR="Data";      # Subfolder name for tests' data
public const REGRESSION_TESTS="Regression_Tests"; # subfolder for regression tests
public const LOG_DIR="Results";      # Subfolder name for run logs
public const GUI_FILE="ABC_GUI.gui";  # GUI file name

public const DSN_LOCAL="DSN=ABC_WR";  # ODBC datasource name of the ABC.mdb file
public const SES_SES="SessionSession";  # name for run session settings
public const SCRIPT_SES="ScriptsSession";  # name for table of the scripts which should be invoked
public const IN_DATA_SES="InputDataSession";  # name for table of the script input data
public const OUT_DATA_SES="OutputDataSession";  # name for table of the script output data
public const LOG_SES="LogSession";    # name for the log table

public const ORA_DSN="DSN=ABC_ORA";    # ODBC datasource name for ABC Oracle database
public const ORA_SES="OracleSession";  # name for Oracle session

public const AESL_INFO="aesl_info.sql";        # file name for sql query to get Artist AESL info
public const COPY_AESL_INFO="aesl_copy_info.sql";  # file name for sql query to get Copyright AESL info
public const SL_STATUS_A="sl_status_artist.sql";  # file name for sql query to get sl status for Artist Processing
public const SL_STATUS_C="sl_status_copyright.sql";  # file name for sql query to get sl status for Copyright Processing

###############################
##     GLOBAL VARIABLES      ##
###############################
# following variables can be (re)defined using ABC.mdb Session Parameters
public clear_params="No";    # clear/preserve keys in parama[] arry before test execution. Possible values: "Yes"/"No"
public fill_empty="Yes";      # default value for parama["FillEmpty"], which enable/disable outo-generated values for empty script params
public need_check="Yes";      # default value for parama["NeedCheck"], which enable/disable additional ckecking (search/field checking) of added objects
public timeout_time = 20;      # maximal timeout time for set_window(..), web_sync(..), loops and similar constructs, in runtime it can less, set some tens of seconds
public wait_time = 1;        # fixed wait time for wait(..) function, in runtime newer wil be less, set some seconds
public attempts = 3;        # number of attempts for my_set_window
public higlith_objects = OFF;      # higligth objects on check_values set ON/OFF

# following are all other variables
static platform="w2k";          # test execution platworm should be "w2k" or "wxp"
public run_label;            # label for test logs (*.log file name, value for Run field in Log table)
public browser_launch="Internet Explorer";     # browser type (IE, Netscape) and path to executable
public url;                # URL to the application index page
public root_path;            # root directory of the scripts

static windows_list="Windows_list";    # "" = don't count and save windows list, other value - count and save
static windows_list_file="";      # "" = don't use file, other value= store windows list in file
static WindowsBefore[];          # Array where windows list is stored
static NoBefore;             # count of windows list

public already_logged;          # indicates that user is logged in
public username, password;        # login parameters
public batch_mode;            # set ON to provide logs in file and database

static test_no;              # test nuber for batch script
public parama[];             # only parameter for test invocation, it has 2 fixed elements:
                    # parama["FillEmpty"]="Yes"/"No" - enable/disable outo-generated values for empty params
                    # parama["NeedCheck"]="Yes"/"No" - enable/disable additional ckecking (search/field checking) of added objects     
                   
public is_exception;          # variable for triggering of exception handling
                    # it is triggered to E_ERROR/E_OK in check_exception() and to E_OK in exception_handler()

                    # array of windows, which should not be killed by win_restore()
                    # should be exact name or substring (keyword) for name matching
                    # "WinRunner" element is mandatory, else WR will kill himself
public preserve_windows[] = {"WinRunner", "Index Page", "ABC"};  

static test_return;            # test return value

public OS;                # Operating System name
public OS_ver;              # Operating System version
public OS_lang;              # Operating System language

public gui_home;            # full path to GUI map file, it is initialized in start()

public sql_aesl_info;          # sql query to get Artist AESL info
public sql_copy_aesl_info;        # sql query to get Copyright AESL info
public sql_sl_artist;          # sql query to get sl status for Artist Processing
public sql_sl_copyright;        # sql query to get sl status for Copyright Processing

start

##############################################################################
# FUNCTION:start
# PURPOSE: Environment setup and startup statements for functional test
# INPUT PARAMS: all optional: username_tmp, password_tmp, url_tmp, if logon==ON - not log into ABC instance
# RETURN VALUE: E_OK on success, otherwise - Error code
# COMMENTS: this function is used for functional scripts to prepare all environment with only one code line:
# if (start() != E_OK) treturn E_GENERAL_ERROR;  
# ABC!_Batch uses start(..,logon=OFF), because it need to show session parameters before logging into instance
##############################################################################
public function start(in username_tmp, in password_tmp, in url_tmp, in logon) {
  auto retval,wrbatch, row_number,test_name,arr[],i,j,session_run_label,ses_id,ses_param,ses_param_val;
  auto schema;                  # Oracle db schema name
 
  GUI_unload_all();                # loads common GUI mapping file
  GUI_close_all();

  set_GUI_map_configuration();          # Set WR GUI map configuration.      
 
  wrbatch=getvar("batch");            # get WinRunner batch mode (Tools-General Options...-Run-Run in batch mode) settings
  if(logon=="") logon=ON;              # set as default to log on ABC instance
 
  root_path = getvar("curr_dir");          # get current test directory
  root_path=substr(root_path,1,index(root_path,ROOT_DIR)-1)&ROOT_DIR;
  gui_home = root_path"\"DATA_DIR"\"GUI_FILE;  #initialize full path to GUI map file
 
  retval = GUI_load(gui_home);
  if (retval < E_OK) {              # check for GUI file load status
    my_tl_step("REQUIRED PARAMS", E_ERROR, "GUI mapping file 'ABC_GUI.gui' couldn't NOT be loaded");
    if (wrbatch=="off")
      MessageBoxA(0,"GUI Mapping file for Tests could not be loaded!nTesting cannot be continued!nn" & err_expl(retval),"GUI Map file",48);
    return E_NOT_FOUND;
  }

  retval=my_db_connect (SES_SES,DSN_LOCAL);    # open session for session table
  if (retval!=E_OK && wrbatch=="off") {      # check for ODBC data source success
    my_tl_step("REQUIRED PARAMS", E_ERROR, "The ODBC '"substr(DSN_LOCAL,5)"' data cource is not setnTesting cannot be continued!");
    MessageBoxA(0,"The ODBC '"substr(DSN_LOCAL,5)"' data cource is not setnTesting cannot be continued!nnClose MS Access database, and open it AFTER WinRunner to avoid ODBC sharing violation error.","ODBC data source",48);
    return E_NOT_FOUND;
  }  
   
  my_db_execute_query (SES_SES,"SELECT * FROM "qryUseSession"",row_number);
  if (row_number!=1) {              # check for Session settings success
    my_tl_step("REQUIRED PARAMS", E_ERROR, "The Session is not set properly. Set exactly ONE 'Use'='Yes' row in Session table!");
    if (wrbatch=="off") MessageBoxA(0,"The Session is not set properly. nTesting cannot be continued!nnSet exactly ONE 'Use'='Yes' row in Session table!","Session row",48);
    return E_NOT_FOUND;
  }
  if (username_tmp=="") username = db_get_field_value(SES_SES,"#0","Username");   # get session parameters from passed parameter
    else username=username_tmp;                          # or database
  if (password_tmp=="") password = db_get_field_value(SES_SES,"#0","Password");
    else password=password_tmp;
  if (url_tmp=="") url = db_get_field_value(SES_SES,"#0","URL");
    else url=url_tmp;  
  session_run_label = db_get_field_value(SES_SES,"#0","RunLabel");  # get runlabel from Session table
  if (run_label=="") {                        # set run label, from database
    if (session_run_label!="") run_label=session_run_label;
    else run_label=date_from_WRsecs("YYYY-MM-DD_HH-NN");      # or generate new, if is empty
  }

  schema = db_get_field_value(SES_SES,"#0","Schema");          # open connection to Oracle db
  if(schema != "") my_db_connect(ORA_SES, ORA_DSN";UID="schema";PWD="schema, 30);
    else my_tl_step ("REQUIRED PARAMS", E_WARNING, "Database schema is not set");
   
  ses_id = db_get_field_value(SES_SES,"#0","ID");
  my_db_execute_query (SES_SES,"SELECT * FROM "qryUseSessionParameter"",row_number);
  for (i=0;i<row_number;i++) {
    ses_param = db_get_field_value(SES_SES,"#"i,"Parameter");
    ses_param_val = db_get_field_value(SES_SES,"#"i,"Value");
    if(ascii(ses_param_val)>57)            # if value is string assign as string
      eval(ses_param" = ""ses_param_val"";");
    else eval(ses_param" = "ses_param_val";");    # else assign value as numeric
  }

  sql_aesl_info = file_read(root_path"\"DATA_DIR"\"AESL_INFO);    # initialize sql queries strings
  sql_copy_aesl_info = file_read(root_path"\"DATA_DIR"\"COPY_AESL_INFO);
  sql_sl_artist = file_read(root_path"\"DATA_DIR"\"SL_STATUS_A);
  sql_sl_copyright = file_read(root_path"\"DATA_DIR"\"SL_STATUS_C);

                                    # if not set, and WR is in dialog mode
  if ((username=="" || password=="") && wrbatch=="off")         # ask for username and password
    retval = create_password_dialog("Cybrarian Account Name: ","Account Password:",username,password);

  if(url=="" && wrbatch=="off")
    url=create_input_dialog ("Please enter instance URL.");  # ask for URL
 
  if (username=="" || password=="" || url=="") {          # exit, if parameters are't set
    my_tl_step ("REQUIRED PARAMS", E_ERROR, "Some of required parameters are missing.nUsername:'"username"'nPassword:'"password"'nURL:'"url"'");
    return E_GENERAL_ERROR;
  }
 
  my_db_connect (LOG_SES,DSN_LOCAL,30);        # create ODBC session for logging
   
  is_exception=E_OK;                                # reset is_exception !!!
  if (logon==ON) already_logged = ABC_Logon(username,password);  # If not said opposite, Log On to ABC Instance
                   
  test_name=get_test_name();              # get invoked test name
  my_tl_step(arr[i],0,"STARTED");            # and log start

  if (already_logged > E_OK || already_logged=="") return E_OK;   # return E_OK (not warnings)
  else return already_logged;              # or error
}

start_batch

##############################################################################
# FUNCTION:start_batch
# PURPOSE: Environment setup and startup statements for batch test uses start() and does additional jobs for only batch tests
# INPUT PARAMS: none
# RETURN VALUE: E_OK on success, otherwise - Error code
##############################################################################
public function start_batch() {
  auto row_number;
  if (start("","","",OFF)!= E_OK) return E_GENERAL_ERROR;  # Invoke common initialization, but don't log on
  db_connect (SCRIPT_SES,DSN_LOCAL,30);      # open session for script tables
  db_execute_query (SCRIPT_SES,"SELECT * FROM qryUseScript;",row_number);
                          # MS Acces query is used, because ORDER BY statement in WR/ODBC (can investigate if will have time)
  test_no=0;                    # set test starting number
}

ABC_Logon

#############################################################################
# FUNCTION:ABC_Logon
# PURPOSE: Logs on to ABC instance
# INPUT PARAMS: optional username_tmp and password_tmp
# RETURN VALUE: E_OK on success, otherwise - Error code
# COMMENTS: usually this function is invoked by start(), exception is ABC!_Batch or some customized script
##############################################################################
public function ABC_Logon(in username_tmp, in password_tmp) {
  auto retval, start_time, cwin, logon_window;
  get_sys_var();                    # get Operating System name
   
  if (username_tmp=="") username_tmp=username;
  if (password_tmp=="") password_tmp=password;
  cwin=get_mainwin_desc("ABC");          # get winow description from expected title
  if (cwin!="" && win_exists("ABC")==E_OK) return E_ALREADY_LOGGED;  # and it has ABC frame window (already logged on), return OK

  start_time=get_time();                
  while (win_exists("Index")!=E_OK){          # try to open Index window
    if(get_time()>(start_time+timeout_time)) {    # handle timeout
      my_tl_step("ABC_Logon", E_WARNING, "Timeout reached for Index window");
      return E_NOT_RESPONDING;
    }
    if (win_exists("Browser Main Window")==E_OK) win_close ("Browser Main Window"); # close previous window
    web_browser_invoke(1,url);            # and open browser with given URL again
    wait(wait_time);
    web_sync(timeout_time);
    web_refresh("Index");              # force WR to reload frame (necessary, if window exists already)
  }
  win_close_dialogs();                 # close all unexpected dialogs
  start_time=get_time();                
  while (cwin==""){    # try while ABC broser window doesn't appear
    if(get_time()>(start_time+timeout_time)) {    # handle timeout
      my_tl_step("ABC_Logon", E_WARNING, "Timeout reached for ABC window");
      return E_NOT_RESPONDING;
    }
    my_set_window("Index",10);              # Set Index window
    web_sync(timeout_time);
    web_link_click("Start");            # click on Start link
    wait(wait_time);
    web_sync(timeout_time);
   
    if(OS == "Windows 2000")             # workaround for different win names in Win XP and Win 2000
      logon_window="wLogon_2000";
    if(OS == "Windows XP")
      logon_window="wLogon_XP";  
         
    if (win_exists(logon_window)==E_OK) {      # if Index window wasn't closed, but application was - logon screen doesn't appear
      my_set_window (logon_window, 10);
   
      edit_set ("User Name", username_tmp);
      edit_set("Password", password_tmp);
      button_set ("Save this password in your password list", ON);
      button_press ("OK");
    }
    if(check_exception()!=E_OK) exception_handler(E_ERROR,"ABC_Logon");  # if exception is happened, handle it
    cwin=get_mainwin_desc("ABC");          # get winow description from expected title
  }
  start_time=get_time();                # Checks if logon is succesful
  while (TRUE) {
    if(get_time()>(start_time+timeout_time)) {    # handle timeout
      my_tl_step("ABC_Logon", E_WARNING, "While timeout reached");
      return E_NOT_RESPONDING;
    }
 
    if (win_exists("ABC",30)==E_OK)  {        # checks using main HTML frame Ok - succesful
      wait(wait_time);
      my_set_window("ABC",30);          # set ABC window and
      web_sync(timeout_time);                # wait for HTML code completition
      web_refresh("Index");            # force WR to reload frame (necessary, if window exists already)
      return E_OK;                # return E_OK
    }
    else {                      # if login is unsuccessful
      if (batch_mode == OFF) {          # show message  
          retval = MessageBoxA(0,"Logging seems to be unsuccessful. Will you try to wait more?nnHINT: You can do manual login now and press "Retry" afterwards.","LOGIN failure",53);
        if (retval == 2)               
          return E_GENERAL_ERROR;       # on Cancel Return error
      }
      else return E_ERROR;               
    }
  }
}

finish

#############################################################################
# FUNCTION:finish
# PURPOSE: Environment cleanup and ending statements for each test
# INPUT PARAMS: none
# RETURN VALUE: none
##############################################################################
public function finish() {
  auto test_name,arr[],i,cwin;
  if (already_logged != E_ALREADY_LOGGED) {     # log out only, if was logged off before
    if(win_exists("ABC")==E_OK) {
      my_set_window ("ABC",10);
      web_link_click("bLogout");
    }  
  }
#   these lines aren't necessary because windows are handled by win_restore()  
#  cwin=get_mainwin_desc("Index");          # get the Index page
#  if(cwin!="") win_close (cwin);          # if was found, close it

   test_name=get_test_name();            # get invoked test name
   my_tl_step(test_name,0,"FINISHED");        # and log finish
}

finish_batch

#############################################################################
# FUNCTION:finish_batch
# PURPOSE: Environment cleanup and ending statements for batch test
# INPUT PARAMS: none
# RETURN VALUE: none
##############################################################################
public function finish_batch() {    
  db_disconnect (SCRIPT_SES);            # disconnect sript and data ODBC sessions
  db_disconnect (IN_DATA_SES);
  db_disconnect (OUT_DATA_SES);
  finish();                    # call usual finish procedure
  db_disconnect (LOG_SES);            # finally close logging ODBC session
  db_disconnect (ORA_SES);            # finally close Oracle ODBC session  
}

get_next_test

#############################################################################
# FUNCTION:get_next_test
# PURPOSE: read next test and data table from UseScript table
# INPUT PARAMS: none
# RETURN VALUE: none
##############################################################################
public function get_next_test(out test_name, out data_table, out test_case, out order_data_set) {
  auto row_content;
  db_get_row(SCRIPT_SES,test_no,row_content);
  test_name = db_get_field_value(SCRIPT_SES,"#"test_no,"Script");
  data_table = db_get_field_value(SCRIPT_SES,"#"test_no,"DataTable");
  test_case = db_get_field_value(SCRIPT_SES,"#"test_no,"TestCase");
  order_data_set = db_get_field_value(SCRIPT_SES,"#"test_no,"OrderDataSet");
  test_no++;
  if (test_name!="") return E_OK;
  else return E_NOT_FOUND;
}

test_process

#############################################################################
# FUNCTION:test_process
# PURPOSE: invokes test calls and manages its execution
# INPUT PARAM:   test_name - mandatory name of invoked test
#        table_name - mandatory name of the input data table
# RETURN VALUE: Returns E_OK or error code
##############################################################################
public function test_process(in script_name, in table_name, in test_case, in order_data_set) {
  auto i, log_text, cwin, row_number, row_content, header_count, header_content,res;
  script_name=substr(script_name,1,index(script_name,"(")-1);
  test_return="";
  if (NoBefore=="") win_save(windows_list_file);          # if windows list is empty, save windows
 
  res=file_open (root_path"\"REGRESSION_TESTS"\"script_name"\script", FO_MODE_READ); # check that file exists
  if(res!=E_OK) {
    my_tl_step("test_process", E_WARNING,script_name" isn't found and invoked");  # if not, log and exit
    return E_ERROR;  
  }
  file_close(root_path"\"REGRESSION_TESTS"\"script_name"\script");  # else close file and continue
 
  if (table_name!="") {                      # if data table name was passed
    my_db_connect (IN_DATA_SES,DSN_LOCAL,30);           # get its data
    res=my_db_execute_query (IN_DATA_SES,"SELECT * FROM "table_name" WHERE (Use =Yes AND TestCase = '"test_case"' AND OrderDataSet ='"order_data_set"');",row_number);
    if (row_number==0) {
      my_tl_step("test_process", E_WARNING, script_name" - no data in table '"table_name"' for data set '"test_case"' and OrderDataSet ='"order_data_set"'. Script isn't invoked");
      return E_WARNING;
    }
    db_get_headers (IN_DATA_SES, header_count, header_content);  
  }
  else row_number=1;                        # else execute script only once
 
  for (i=0;i<row_number;i++) {
    parama["NeedCheck"]=need_check;                # (re)initialize default checking option
    parama["FillEmpty"]=fill_empty;                # (re)initialize default auto-filling option
    parama["Error"]="";                      # clear Error value
    my_tl_step("test_process", E_OK, script_name" is invoked");    # write to log
    if (table_name!="") {                    # if data table name was passed
      db_get_row(IN_DATA_SES,i,row_content);          # get data
      to_array(parama, header_content, row_content, "t",clear_params);
      my_tl_step("test_process", E_OK, "Parameters:"replace_ASCII(row_content,9,59));
    }
    if (parama["Error"]!="") parama["NeedCheck"]="No";      # disable checking of added values for negative test
    already_logged = ABC_Logon(username,password);        # Log On to ABC Instance (avoids logoff after each test execution)
    eval ("test_return=call_close ""script_name"" (parama);");  # invoke test with parameter
   
    win_close_dialogs();                  # close unnecesarry dialogs
    win_restore(windows_list_file);              # restore winows after completed test
       
    log_text=script_name" finished";                # prepare log statement
    if (test_return<E_OK && test_return!="") log_text=log_text&" UNSUCCESFULLY";
    if (test_return==E_OK) log_text=log_text&" SUCCESFULLY";
 
    my_tl_step("test_process", test_return, log_text);        # write to the log
  }
  cwin=get_mainwin_desc("ABC");          # get winow description from expected title
  if (cwin!="" && win_exists("ABC")) return E_OK;
  else return test_return;
}
##############################################################################
#######################       U T I L I T I E S        #######################
##############################################################################

date_from_WRsecs

#############################################################################
# FUNCTION:date_from_WRsecs
# PURPOSE: Use this function, if seconds is in get_time() format (as diff_date returns)
#       else use date_from_WRtime()
# INPUT PARAMS: format (for example "dd-mmm-yyyy")
#               time (get_time format: seconds since 1-1-1970)
# RETURN VALUE: Returns normalized time string ("5-Dec-1998" for params above)
##############################################################################
public function date_from_WRsecs(in format, in seconds)
{
  auto time;
 
  if (seconds == "")
    seconds = get_time();
  time=time_str(seconds);
  return date_from_WRtime(format,time);  
}

date_from_str

#############################################################################
# FUNCTION:date_from_str
# PURPOSE: Pass date as string, and get as Unix seconds (get_time() format), or as formatted string in other format.
# To run function Set: WinRunner Settings-General Options-Miscellaneous-Enable date operations
#
# INPUT PARAMS: date mandatory - input date (i.e. 19.12.2003 12:45:56)
#               inFormat - optional date format if other than defaulf (i.e. mm/dd/yy) default is "DD.MM.YYYY HH:NN:SS"
#        outFormat - optional, if return value should be returned as other format (i.e. mm/dd/yy)
# RETURN VALUE: Returns integer as get_time() or formated string as date
##############################################################################
public function date_from_str(in date, in inFormat, in outFormat) {
  auto y,m,d,h,n,s,i,period,days,secs,formata[],formati,datea[],value;
  if (inFormat=="") inFormat="DD.MM.YYYY HH:NN:SS";    # if format not set, use latvian
  formati=split(inFormat,formata," _/-:;");        # split in parts format
  split(date,datea," _/-:;");              # split in parts date value
  for (i=1;i<=formati;i++) {                # for each format part
    period=toupper(formata[i]);              # get current period
    if (period=="Y" ||  period=="YY" || period=="YYY" || period=="YYYY") y=sprintf("%.0d",datea[i]);  # set year
    if (period=="M" ||  period=="MM") m=sprintf("%.0d",datea[i]);                    # set short month
    if (period=="MMM" || period=="MMMM") {                        # set long month
      value=datea[i];
      if(value=="Jan" || value=="January" || value=="Janvāris") m=1;
      if(value=="Feb" || value=="February" || value=="Februāris") m=2;
      if(value=="Mar" || value=="March" || value=="Marts") m=3;
      if(value=="Apr" || value=="April" || value=="Aprīlis") m=4;
      if(value=="May" || value=="May" || value=="Mai" || value=="Maijs") m=5;
      if(value=="Jun" || value=="June" || value=="Jūn" || value=="Jūnijs") m=6;
      if(value=="Jul" || value=="July" || value=="Jūl" || value=="Jūlijs") m=7;
      if(value=="Aug" || value=="August" || value=="Augusts") m=8;
      if(value=="Sep" || value=="September" || value=="Septembris") m=9;
      if(value=="Oct" || value=="October" || value=="Okt" || value=="Oktobris") m=10;
      if(value=="Nov" || value=="November" || value=="Novembris") m=11;
      if(value=="Dec" || value=="December" || value=="Decembris") m=12;
    }
    if (period=="D" ||  period=="DD") d=sprintf("%.0d",datea[i]);            # set day
    if (period=="H" || period=="HH") h=sprintf("%.0d",datea[i]);            # set hours
    if (period=="N" || period=="NN") n=sprintf("%.0d",datea[i]);            # set minutes
    if (period=="S" || period=="SS") s=sprintf("%.0d",datea[i]);            # set seconds
    if (period=="T" || period=="TT") {                          # if, AM, PM exists
      h=h%12;                                      # round hours to <=12
      if (datea[i]=="PM") h=h+12;                            # add 12, for PM
    }      
  }
  if (y==0) y=2000;                    # format year arround 2000
  if (y>0 && y<30) y=y+2000;
  if (y>=30 && y<2000) y=y+1900;
 
  if (m>12) {
    m=12;                         # format month
    my_tl_step("date_from_str",2,"Months '"m"' was more than 12, changed to 1");
  }
  if (((m==4 || m==6 || m==9 || m==11) && d>30) || (m==2 && d>29) || m>31) {
    d=1;
    my_tl_step("date_from_str",2,"Date '"d"' for month '"m"' was more than allowed, changed to 1");
  }
 
  days=date_string_to_Julian (m"/"d"/"y)-2440587.5;    # get Julian days and substract 1970.01.01 (includig midday)
  secs=days*86400+h*3600+n*60+s-12*3600;          # count seconds from 1970.01.01 (remove midday time back)
  if (secs<0) {
    secs=0;
    my_tl_step("date_from_str",2,"Date in seconds was negative , changed to 01.01.1970 00:00:00 GMT");
  }
  if(outFormat=="") return secs;             # return seconds from 1970.01.01
  else return date_from_WRsecs(outFormat,secs);    # or format according output format string
}

date_from_WRtime

#############################################################################
# FUNCTION:date_from_WRtime
# PURPOSE: Pass format string and [optional] time string (as WinRunner time_str)
#          and get formatted time string on return
#
# INPUT PARAMS: format (for example "dd-mmm-yyyy"
#               time (time_str format: "Thu Dec 05, 1998, 22:00:00"
#
# RETURN VALUE: Returns normalized time string ("5-Dec-1998" for params above)
##############################################################################
public function date_from_WRtime(in format, in time) {
  auto current_element, current_symbol;
  auto nCikls;
  auto result,start_time;
  auto date, year, monthstr, fullmonth, monthnum, day, fullday, isAmPm, hours;
  auto elements[];
 
  if (time == "")
    time=time_str();
  year=substr(time,21,4);
  day=substr(time,9,2);
  monthstr=substr(time,5,3);
  switch (monthstr) {                        # get all notations of month for passed date
    case "Jan":monthnum="01";fullmonth="January";break;
    case "Feb":monthnum="02";fullmonth="February";break;
    case "Mar":monthnum="03";fullmonth="March";break;
    case "Apr":monthnum="04";fullmonth="April";break;
    case "May":monthnum="05";fullmonth="May";break;
    case "Jun":monthnum="06";fullmonth="June";break;
    case "Jul":monthnum="07";fullmonth="July";break;
    case "Aug":monthnum="08";fullmonth="August";break;
    case "Sep":monthnum="09";fullmonth="September";break;
    case "Oct":monthnum="10";fullmonth="October";break;
    case "Nov":monthnum="11";fullmonth="November";break;
    case "Dec":monthnum="12";fullmonth="December";break;
  }  
  switch (substr(time,1,3)) {                    # get all notations of weekday for passed date
    case "Mon":fullday="Monday";break;
    case "Tue":fullday="Tuesday";break;
    case "Wed":fullday="Wednesday";break;
    case "Thu":fullday="Thursday";break;
    case "Fri":fullday="Friday";break;
    case "Sat":fullday="Saturday";break;
    case "Sun":fullday="Sunday";break;
  }

  isAmPm=FALSE;
  current_element = -1;
  current_symbol = "";
  for (nCikls=1; nCikls<=length(format); nCikls++) {        # split format to elements
    if (current_symbol != substr(format,nCikls,1))        # if format characters changes
      current_element++;                      # make new element
    elements[current_element] = elements[current_element] & substr(format,nCikls,1);
    if(index(toupper(elements[current_element]),"T")>0) isAmPm=TRUE;  # mark, that AM/PM symbol required
    current_symbol = substr(format,nCikls,1);
  }

  for(current_element = 0;elements[current_element] != "";current_element++){    # for each element in format
    switch (elements[current_element]) {
      case "dddd":result=result&fullday;break;
      case "ddd":result=result&substr(time,1,3);break;
      case "dd":result=result&sprintf("%.0d",day);break;
      case "d":result=result&substr(day,2,1);break;
      case "DD":result=result&day;break;
      case "D":result=result&sprintf("%.0d",day);break;
      case "mmmm":result=result&fullmonth;break;
      case "mmm":result=result&monthstr;break;
      case "MMM":result=result&monthstr;break;      
      case "mm":result=result&sprintf("%.0d",monthnum);break;
      case "m":result=result&sprintf("%.0d",substr(monthnum,2,1));break;
      case "MM":result=result&sprintf("%2s",monthnum);break;
      case "M":result=result&sprintf("%.0d",monthnum);break;
      case "yyyy":result=result&year;break;
      case "yyy":result=result&substr(year,2,3);break;      
      case "YYYY":result=result&year;break;      
      case "yy":result=result&sprintf("%.0d",substr(year,3,2));break;
      case "y":result=result&sprintf("%.0d",substr(year,4,1));break;
      case "YYY":result=result&substr(year,2,3);break;
      case "YY":result=result&substr(year,3,2);break;
      case "Y":result=result&sprintf("%.0d",substr(year,4,1));break;
      case "hh":
        if (isAmPm==FALSE) result=result&sprintf("%.0d",substr(time,12,2));  # if AM/PM not required, add hours as is        
        else {                                # else
          hours=sprintf("%.0d",substr(time,12,2));            # get actual hours    
          if(hours<12) isAmPm="AM";                    # count AM/PM flag
          else isAmPm="PM";
          hours=hours%12;                          # set hours to 12 cycle
          if (hours==0) hours=12;                      # set 0 hours to 12
          result=result&sprintf("%.0d",hours);
        }
        break;
      case "h":
        result=result&sprintf("%.0d",substr(time,13,1));break;
      case "HH":                                # if AM/PM not required, add hours as is  
        if (isAmPm==FALSE) result=result&sprintf("%0.2d",substr(time,12,2));          
        else {
          hours=sprintf("%.0d",substr(time,12,2));
          if(hours<12) isAmPm="AM";
          else isAmPm="PM";
          hours=hours%12;
          if (hours==0) hours=12;
          result=result&sprintf("%0.2d",hours);
        }
        break;
      case "H":
        result=result&sprintf("%.0d",substr(time,13,1));break;        
      case "nn":result=result&sprintf("%.0d",substr(time,15,2));break;
      case "n":result=result&sprintf("%.0d",substr(time,16,1));break;
      case "NN":result=result&substr(time,15,2);break;
      case "N":result=result&sprintf("%.0d",substr(time,16,1));break;
      case "ss":result=result&sprintf("%.0d",substr(time,18,2));break;
      case "s":result=result&sprintf("%.0d",substr(time,19,1));break;
      case "SS":result=result&substr(time,18,2);break;
      case "S":result=result&sprintf("%.0d",substr(time,19,1));break;
      case "TT":result=result&isAmPm;break;
      case "tt":result=result&tolower(isAmPm);break;
      default:result=result&elements[current_element];break;
    }
  }
return result;
}

date_diff

#############################################################################
# FUNCTION:date_diff
# PURPOSE: desired difference in time and get back it in get_time format
# INPUT PARAMS: format: string, indicating alteration unit ("m" for month), shift: shift number, optional from_zero, if shift is not necessary from from current date
# RETURN VALUE: seconds (get_time() format)
##############################################################################
public function date_diff(in format, in shift, in from_zero) {
    auto seconds;
    if (from_zero=="") seconds = get_time();
    else seconds=0;
    switch (toupper(format)) {
        case "D":seconds=seconds+(shift*24*3600);break;
        case "W":seconds=seconds+(shift*7*24*3600);break;
        case "M":seconds=seconds+(shift*30*24*3600);break;
        case "Y":seconds=seconds+(shift*365*24*3600);break;
        case "H":seconds=seconds+(shift*3600);break;
        case "N":seconds=seconds+(shift*60);break;
        case "S":seconds=seconds+(shift);break;
        default:break;
    }
    return seconds;
}

date_shift

#############################################################################
# FUNCTION:date_shift
# PURPOSE: returns date shifted by assigned period from passed date
# INPUT PARAMS: date as sring, which format is described in format, shift +/- integer, shift factor specified as one of D/W/M/Y/H/N/S
# RETURN VALUE: date is returned in the same format as passed date
##############################################################################

public function date_shift(in date, in format, in shift, in shift_format) {
    auto cdate,ndate;
    cdate = date_from_str(date, format);
    ndate=cdate+date_diff(shift_format, shift, ON);
    return date_from_WRsecs(format, ndate);
}

get_test_name

#############################################################################
# FUNCTION:get_test_name
# PURPOSE: return name of the functional test, which is currently running
# INPUT PARAMS: none
# RETURN VALUE: name of the functional test
##############################################################################
public function get_test_name() {
  auto depth,i,j,testname,testnamea[];
  depth=call_chain_get_depth();
  for(i=depth-1;i>=0;i--) {              # go trough call chain from the last one
    call_chain_get_attr("testname",i,testname);
    if (index(testname,FUNCTION_TEST)==0 && index(testname,BATCH_TEST)==0) { # if it isn't ABC_Functions and ABC_!Batch
      j=split(testname,testnamea,"\");      # split test full path in parts
      testname=testnamea[j];            # and get only test name from full path
      break;
    }
  }
  return testname;
}

list_check_presence

#############################################################################
# FUNCTION:list_check_presence
# PURPOSE: Check if item presents in check list or not
# INPUT PARAMS: list name, item name (in list), exact_match (ON/OFF,by default=OFF)
# INITIAL STATE: Window (Frame) must be active (focus ON) within list reside
# RETURN VALUE: returns E_OK if exact match, value - if similar, E_NOT_FOUND - if not found
##############################################################################
public function list_check_presence(in passed_list_name, in passed_item_name, in exact_match) {
  auto ItemCount, ItemContents, _nFuncCycle, i;
  if (passed_item_name=="") return E_NOT_FOUND;              # do not check for empty string
  if (exact_match!=ON) exact_match=OFF;                  # by default search for similar match
  list_get_info(passed_list_name,"count",ItemCount);            # Count of Items in List to ItemCount
  for (_nFuncCycle=0; _nFuncCycle<ItemCount; _nFuncCycle++) {        # at 1st, try to find exact match
    list_get_item(passed_list_name, _nFuncCycle, ItemContents);     # Get list item value (one by one)
    if (ItemContents == passed_item_name) {
      return E_OK;
    }
  }
  if (exact_match==OFF) {                          # if exact match is off , search for similar match                       
    for (_nFuncCycle=0; _nFuncCycle<ItemCount; _nFuncCycle++) {
      list_get_item(passed_list_name, _nFuncCycle, ItemContents);   # Get similar value in list, using 1st character
      if (index(ItemContents,substr(passed_item_name,1,1))==1)
          return ItemContents;
      }
  }  
  return E_NOT_FOUND;
}

list_check_substr

#############################################################################
# FUNCTION:list_check_substr
# PURPOSE: Check if list contains passed string as part of any record, or not
# INPUT PARAMS: list name, item name (in list)
# INITIAL STATE: Window (Frame) must be active (focus ON) within list reside
# RETURN VALUE: returns E_OK if some of records contain passed string, E_NOT_FOUND - if not found
##############################################################################
public function list_check_substr(in passed_list_name, in passed_item_name) {
  auto ItemCount, ItemContents, _nFuncCycle, i;
  list_get_info(passed_list_name,"count",ItemCount);            # Count of Items in List to ItemCount
  for (_nFuncCycle=0; _nFuncCycle<ItemCount; _nFuncCycle++) {
    list_get_item(passed_list_name, _nFuncCycle, ItemContents);     # Gets list item value (one by one)
    if (index(ItemContents,passed_item_name)!=0) {
      return E_OK;
    }
  }
  return E_NOT_FOUND;
}

excel_read

#############################################################################
# FUNCTION:excel_read
# PURPOSE: Reads value from Excel file
#
# INPUT PARAMS: excel file name (simple: without path and extension)
#               variable name - name of variable from what get the value
#               [row] - return value from ROW. Rows are numbered from 1 (variable name in 0.)
#        [separator] - if specified, values are red till to end and are separated with separator
# RETURN VALUE: Value or error explanation (string)
##############################################################################
public function excel_read(in excel_name, in variable_name, in row, in separator) {
  auto retval, cDataFile,row_count, cur_val, cur_row, start_time;
  cDataFile = excel_name & ".xls";
  if(index(cDataFile,"\")==0) cDataFile=root_path"\"LOG_DIR"\"cDataFile; # if full file name is not passed, set to LOG_DIR
  ddt_close_all_tables();
  retval = ddt_open(cDataFile,DDT_MODE_READ);
  if(retval == E_FILE_OK) {                  # if file is open
    if (row=="" || row==0) row=1;                # sets default row to 1st (not 0 which is variable name)
    cur_row=row;                        # set row counter
    ddt_get_row_count (cDataFile, row_count);          # checks, count of existing rows
    if (row>row_count) {                    # if passed row doesn't fit in existing rows
      my_tl_step("Read from " & excel_name & ".xls", 2 , variable_name & "(" & row & ") is out of existing rows");
      retval="";
      return retval;                    # log and exit
    }
    retval = ddt_val_by_row (cDataFile, row, variable_name); # else
    if (separator!="") {                    # if several values are expected
      start_time=get_time();
      while(TRUE) {                          # get all of them
         if(get_time()>start_time+60) {
          my_tl_step("excel_read",2,"While timeout reached");
          break;
        }
        cur_row++;
        cur_val = ddt_val_by_row (cDataFile, cur_row, variable_name);
        if (cur_val!="") retval = retval & separator & cur_val;  # and append to retval
        else break;
      }
    }

    if (retval!="") my_tl_step("Read from "excel_name".xls", 0 , variable_name"("row"-"cur_row")='"retval"'");
    else my_tl_step("Read from "excel_name".xls", 2 , variable_name"("row"-"cur_row") not found or cells are empty");    

    ddt_close(cDataFile);
     return retval;    
  }
  else {                              # on file open error logs and returns error code
    my_tl_step("Read from " & excel_name & ".xls", 1 , "Error:" & err_expl(retval));  
     return retval;
  }
}

excel_write

#############################################################################
# FUNCTION:excel_write
# PURPOSE: Writes value to Excel file
# INPUT PARAMS: excel file name (simple: without path and extension)
#               variable name - name of variable where to write value
#               variable value - value to be written
#               [row] - write value to ROW. Rows are numbered from 1 (variable name in 0.)
#        [separator] - If several variables ar passed as delimited string,
#        separator passes delimiter. If separator is string, each character is used as possible separator value
# RETURN VALUE: Value or error explanation (string)
##############################################################################
public function excel_write(in excel_name, in variable_name, in variable_value, in row, in separator) {
  auto retval, cDataFile, val_count=0, i=0, row_count=0;  # counter of values, counter, count of existing rows
  auto val_arr[];
  val_count = split (variable_value, val_arr, separator);    # split passed value to separate values, if necessarry
  cDataFile = excel_name & ".xls";
  if(index(cDataFile,"\")==0) cDataFile=root_path"\"LOG_DIR"\"cDataFile; # if full file name is not passed, set to LOG_DIR  
  ddt_close_all_tables();
  retval = ddt_open(cDataFile,DDT_MODE_READWRITE);
  if (retval == E_FILE_OK) {                  # if file is openened successfully
    if (row=="" || row==0) row=1;              
    else {                          # ir passed row >1,  
      ddt_get_row_count (cDataFile, row_count);      # checks, count of existing rows
      if (row_count==0) {                  # if file is empty
        ddt_set_val (cDataFile, variable_name, " ");  # create variable column with empty value
      }
    }
    if (row<=row_count) ddt_set_row (cDataFile, row);    # if passed row fits in existing rows, set it
    else {  
      ddt_set_row (cDataFile, row_count);        # else add necessarry number of rows
      for(i=row_count+1;i<=row;i++) {
        retval = ddt_set_val_by_row (cDataFile, i, variable_name, " ");
        ddt_set_row (cDataFile, i);          # set active row according to passed value
      }
    }
    for (i=0;i<val_count;i++) {                # adds necessarry number of values in row
      ddt_set_row (cDataFile, row+i);
      retval = ddt_set_val_by_row (cDataFile, row+i, variable_name, val_arr[i+1]);
      my_tl_step("Write to " & excel_name & ".xls", 0 , variable_name & "(" & row+i &  ")='" &  val_arr[i+1] & "'");
    }
    ddt_save(cDataFile);                  # save and close file
    ddt_close(cDataFile);
     return retval;      
  }
  else {
    my_tl_step("Write to " & excel_name & ".xls", 1 , "Error:" & err_expl(retval));
     return retval;
  }
}

excel_clear_values

#############################################################################
# FUNCTION:excel_clear_values
# PURPOSE: clear all values for variable in Excel file
# INPUT PARAMS: excel file name (simple: without path and extension)
#               variable name - name of variable where to write value
# RETURN VALUE: Value or error explanation (string)
##############################################################################
public function excel_clear_values(in excel_name, in variable_name) {
  auto retval, cDataFile, val_count=0, i=0,j=0,cur_val, row_count=0;  # counter of values, counter, count of existing rows
  cDataFile = excel_name & ".xls";
  if(index(cDataFile,"\")==0) cDataFile=root_path"\"LOG_DIR"\"cDataFile; # if full file name is not passed, set to LOG_DIR
  ddt_close_all_tables();
  retval = ddt_open(cDataFile,DDT_MODE_READWRITE);
  if (retval == E_FILE_OK) {                # if file is openened successfully
    if (ddt_is_parameter (cDataFile, variable_name)==E_NOT_PARAMETER) {
      my_tl_step("excel_clear_values "excel_name".xls", 2 ,"There is no variable '"variable_name"' in file");      
      ddt_close(cDataFile);
      return retval;
    }
    ddt_get_row_count (cDataFile, row_count);        # checks, count of existing rows
    if (row_count<=0) {                    # if no rows
      my_tl_step("excel_clear_values "excel_name".xls", 2 ,"Values for '"variable_name"' are not declared");
      ddt_close(cDataFile);
      return retval;
    }
    else {  
      for(i=1;i<=row_count;i++) {
        cur_val = ddt_val_by_row (cDataFile, i, variable_name);
        if (cur_val!="") {
          retval = ddt_set_val_by_row (cDataFile, i, variable_name, "");
          j++;
        }
      }
      if(j==0)
        my_tl_step("excel_clear_values "excel_name".xls", 2 ,"Values for '"variable_name"' are not declared");
      else
        my_tl_step("excel_clear_values "excel_name".xls", 0 , "Deleted "j" values for '"variable_name"'");
      ddt_save(cDataFile);                  # save and close file
      ddt_close(cDataFile);
       return retval;
    }      
  }
  else {
    my_tl_step("excel_clear_values " & excel_name & ".xls", 1 , "Error:" & err_expl(retval));
     return retval;
  }
}

err_expl

 
#############################################################################
# FUNCTION:err_expl
# PURPOSE: Pass in the error code you want to check and the function
# will return a string explaining what the error code means.
# INPUT PARAM:code - the error code you wantto check.
# RETURN VALUE:Returns a string of the error code passed as the arguement.
##############################################################################
public function err_expl (in code) {
switch(code) {
  case 0 : return ("E_OK or E_FILE_OK Operation successful.");
  case E_ERROR: return ("E_ERROR ABC Framework Error");
  case E_ALREADY_LOGGED: return ("E_ALREADY_LOGGED Already logged to the ABC instance");
  case E_NOT_RESPONDING: return ("E_NOT_RESPONDING Timeout");
  case E_WARNING: return ("E_WARNING ABC Framework Warning");
  case E_HANDLING: return ("E_HANDLING In exception handling call chain");    
  case -10001: return ("E_GENERAL_ERROR General error occurred.");
  case -10002: return ("E_NOT_FOUND Window or object not found.");
  case -10003: return ("E_NOT_UNIQUE More than one window or object responds to the physical description.");
  case -10004: return ("E_ILLEGAL_OPERATION Operation invalid for object.(See note.)");
  case -10005: return ("E_OUT_OF_RANGE Parameter is out of range.");
  case -10006: return ("E_ILLEGAL_PARAMETER Specified value for one or more parameters is invalid.");
  case -10007: return ("E_FILE_OPEN Cannot open file. File may already be open.");
  case -10011: return ("E_NOT_IN_MAPPING Cannot find window or object in the GUI map.");
  case -10012: return ("E_EXIST Object already exists");
  case -10018: return ("E_OPERATION_NOT_PERFORMED Cannot perform requested operation.");
  case -10019: return ("E_FUNCTION_NOT_LOADED Specified function is not currently loaded. In the case of a handler function, the exception is undefined.");
  case -10024: return ("E_NO_FONT No font was loaded.");
  case -10025: return ("E_SYNTAX Syntax error in TSL statement.");
  case -10026: return ("E_NO_SVC Called function does not exist.");
  case -10028: return ("E_FUNCTION_NOT_IMPLEMENTED Called function could not be implemented.");
  case -10029: return ("E_ATTR_IN_DESC Specified property is used in the object's physical description in the GUI map.");
  case -10030: return ("E_NO_LABEL Label property is not used in the window's physical description in the GUI map.");
  case -10032: return ("E_FILE_NOT_OPEN File is not open.");
  case -10033: return ("E_FILE_NOT_FOUND File is not found.");
  case -10034: return ("E_FILE_LINE_TRUNC File line is truncated.");
  case -10035: return ("E_FILE_EOF End of file.");
  case -10036: return ("E_FILE_NOT_READ_MODE Cannot read file because file is not in read mode. ");
  case -10037: return ("E_FILE_READ_MODE Cannot write to file because file is in read mode.");
  case -10038: return ("E_BAD_PATH Incorrect path.");
  case -10039: return ("E_ACCESS_DENIED Access is denied.");
  case -10040: return ("E_DISK_FULL Disk is full.");
  case -10041: return ("E_SHARING_VIOLATION Sharing violation.");
  case -10042: return ("E_FILE_ERROR General file error.");
  case -10044: return ("E_NOT_PARAMETER Parameter is invalid.");
  case -10101: return ("E_NOT_DISPLAYED Window or object is not displayed.");
  case -10102: return ("E_DISABLED Window or object is disabled. ");
  case -10103: return ("E_IMPROPER_CLASS Operation cannot be performed on this object class.");
  case -10104: return ("E_ILLEGAL_KEY Key or mouse button name is illegal.");
  case -10105: return ("E_ITEM_NOT_FOUND Item in list or menu not found.");
  case -10107: return ("E_OBJECT_SYNTAX Illegal syntax used.");
  case -10112: return ("E_ILLEGAL_NUM_OF_PARAMS Number of parameters does not match those for the command.");
  case -10114: return ("E_AUT_DISCONNECTED The application under test was disconnected.");
  case -10115: return ("E_ATTR_NOT_SUPPORTED Property function is not supported.");
  case -10116: return ("E_MISMATCH Verification mismatch found.");
  case -10117: return ("E_ITEM_NOT_UNIQUE More than one item in list or menu has this name.");
  case -10118: return ("E_TEXT_TOO_LONG Text to be inserted exceeds maximum number of characters. The string will be truncated to the appropriate length.");
  case -10119: return ("E_DIFF GUI checkpoint mismatch found.");
  case -10120: return ("E_CMP_FAILED Comparison failed.");
  case -10121: return ("E_CAPT_FAILED Capture failed.");
  case -10122: return ("E_WRONG_OBJ_FAILED Object in checklist is not the object in the command.");
  case -10123: return ("E_SET_WIN Window setting parameters missing.");
  case -10124: return ("E_BITMAP_TIMEOUT The wait_bitmap operation exceeded specified wait time.");
  case -10125: return ("E_BAD_CHECK_NAME Syntax error in requested check.");
  case -10126: return ("E_OBJ_CAPT_FAILED Capture failed for specified object.");
  case -10127: return ("E_UNEXP_WIN Window in checklist is not the window in the command.");
  case -10128: return ("E_CAPT_FUNC_NOT_FOUND Capture function not defined.");
  case -10129: return ("E_CMP_FUNC_NOT_FOUND Compare function not defined.");
  case -10130: return ("E_TSL_ERR Syntax error detected.");
  case -10131: return ("E_TOOLKIT_MISMATCH Incorrect toolkit detected.");
  case -10132: return ("E_RECT_COVERED Desired rectangle is hidden.");
  case -10133: return ("E_RECT_OUT Desired rectangle does not appear on screen.");
  case -10134: return ("E_AREA_COVERED Desired area is hidden.");
  case -10135: return ("E_AREA_OUT Desired area does not appear on screen.");
  case -10136: return ("E_STR_NOT_FOUND Text string not located.");
  case -10137: return ("E_WAIT_INFO_TIMEOUT The wait_info operation exceeded specified wait time.");
  case -10138: return ("E_SYNC_FAILED Synchronization failed.");
  case -10139: return ("E_DIFF_SIZE Expected and actual bitmaps are different sizes.");
  case -10141: return ("E_DROP_WITHOUT_DRAG Drop operation is performed without a drag operation preceding it.");
  case -10142: return ("E_VIR_OBJ Function not supported for virtual objects.");
  case -10143: return ("E_MISSING_ATTR Lack of x-, y-, height, or width coordinates in the description of the virtual object.");
  case -10144: return ("E_EDIT_SET_FAILED The edit_set operation failed.");
  case -10106: return ("E_NOT_RESPONDING Application did not respond within the specified timeout.");
  case -10162: return ("E_ODBC_ERROR There is an error in ODBC connection or SQL operation.");
  default: return ("Not a standard error code. ("code")");
  }
}

tbl_find_text

#############################################################################
# FUNCTION:tbl_find_text
# PURPOSE: Finds a text in a html_table and returns row and column where the text resides.
# INPUT PARAM: table_name - name of table or description
#              text_to_find - string to find in table
#              row - variable to store found row number
#              col - variable to store found col number
#              startrow - optional parameter to avoid first rows in table
# RETURN VALUE:Returns E_OK if success, otherwise E_NOT_FOUND.
##############################################################################
public function tbl_find_text(in table_name, in text_to_find, out row, inout col, in startrow, in exact_match) {
  auto rows_count, cols_count, cell_value, cell_value_len, nCol, nRow;
  if (exact_match=="") exact_match=OFF;
  tbl_get_rows_count(table_name,rows_count); # Gets Rows count in table
  tbl_get_cols_count(table_name,cols_count); # Gets Column count in table
 
  if (startrow == "" || startrow>rows_count)
    startrow = 1;

  for (nRow=startrow; nRow<=rows_count; nRow++) {   # Goes through all cells within table
    if (col == "" || col == 0) {
      for (nCol=1; nCol<=cols_count; nCol++) {
        tbl_get_cell_value(table_name,nRow,nCol,cell_value);
        if (cell_value==text_to_find || (exact_match==OFF && (index(cell_value,text_to_find)>0 || text_to_find==""))) { # If required string is within found one
          row = nRow; # Return Row and Column by passed variables
          col = nCol;
          return E_OK;
        }    
      }
    } else {
      tbl_get_cell_value(table_name,nRow,col,cell_value);
      if (cell_value==text_to_find || (exact_match==OFF && (index(cell_value,text_to_find)>0 || text_to_find==""))) { # If required string is within found one
        row = nRow; # Return Row and Column by passed variables
        return E_OK;
      }
    }
  }
  row = "";
  col = "";
  return E_NOT_FOUND;
}

tbl_get_value

#############################################################################
# FUNCTION:tbl_get_value
# PURPOSE: Finds a row in a html_table according to passed value and returns contents (value) of another column in the found row.
# INPUT PARAM: table_name - name of table or description
#              text_to_find - string to find in table
#              retvalue - variable to store found value
#              [out_col] - column where function should harvest for ret. value
#                        if omitted: next col after in_col
#              [in_col] - column where function should search for passed string
#                        if omitted: calls tbl_find_text get from entire table search
# RETURN VALUE:Returns E_OK if success, otherwise E_NOT_FOUND.
##############################################################################
public function tbl_get_value(in table_name, in text_to_find, out retvalue, in out_col, in in_col) {
  auto rows_count, cols_count, in_row, nCycle, cell_value, child_object;
  if (in_col  == "") {
    if (tbl_find_text(table_name,text_to_find,in_row,in_col)!=E_OK)
      return E_NOT_FOUND;
  } else {
    tbl_get_rows_count(table_name,rows_count);
    for (nCycle=1;nCycle<=rows_count;nCycle++) {
      web_obj_get_text(table_name,"#"&nCycle,"#"&in_col,cell_value,"","",1);
#      tbl_get_cell_data(table_name,"#"&nCycle,"#"&in_col,cell_value);
      if (index(cell_value,text_to_find)>0) {
        in_row = nCycle;
        break;
      }
    }
  }
  if (out_col == "") {
    tbl_get_cols_count(table_name,cols_count);
    if (cols_count<=in_col) {
      return E_NOT_FOUND;
    } else {
      out_col = in_col + 1;
    }
  }

  web_obj_get_child_item(table_name, "#"in_row, "#"out_col, "html_edit", 0, child_object);
  if (child_object != "") {
    obj_get_info(child_object,"value",retvalue);
    return E_OK;
  }
  web_obj_get_child_item(table_name, "#"in_row, "#"out_col, "html_combobox", 0, child_object);
  if (child_object != "") {
    obj_get_info(child_object,"value",retvalue);
    return E_OK;
  }
  web_obj_get_child_item(table_name, "#"in_row, "#"out_col, "html_listbox", 0, child_object);
  if (child_object != "") {
    obj_get_info(child_object,"value",retvalue);
    return E_OK;
  }
  tbl_get_cell_data(table_name,"#"in_row, "#"out_col, retvalue);
  return E_OK;
}

tbl_get_cell_value

#############################################################################
# FUNCTION:tbl_get_cell_value
# PURPOSE: Returns textual value from cell. Works better than TSL tbl_get_cell_data ()
# INPUT PARAM: in table_name, in row (int), in col(int), out retvalue
# RETURN VALUE: Returns E_OK
##############################################################################
public function tbl_get_cell_value(in table_name, in row, in col, out retvalue) {
  auto child_object, rows_count, cols_count,list_num;
  tbl_get_rows_count(table_name,rows_count);    # check count of rows
  if (row>rows_count) {
    my_tl_step("tbl_get_cell_value" ,2,"Passed row '"row"' is out of count '"rows_count"'");
    return E_NOT_FOUND;
  }
  tbl_get_cols_count(table_name,cols_count);    # check count of columns
  if (col>cols_count) {
    my_tl_step("tbl_get_cell_value" ,2,"Passed column '"col"' is out of count '"cols_count"'");
    return E_NOT_FOUND;
  }  
 
  web_obj_get_child_item(table_name, "#"row, "#"col, "html_edit", 0, child_object);  # try to get from html_edit
  if (child_object != "") {
    obj_get_info(child_object,"value",retvalue);
    return E_OK;
  }
  web_obj_get_child_item(table_name, "#"row, "#"col, "html_combobox", 0, child_object);  # try to get from html_combobox
  if (child_object != "") {
#    list_get_selected (child_object, retvalue, list_num);
    obj_get_info(child_object,"value",retvalue);
    return E_OK;
  }
  web_obj_get_child_item(table_name, "#"row, "#"col, "html_listbox", 0, child_object);  # try to get from html_listbox
  if (child_object != "") {
    obj_get_info(child_object,"value",retvalue);
    return E_OK;
  }
  tbl_get_cell_data(table_name,"#"row, "#"col, retvalue);      # try to get from table cell as text
  return E_OK;
}

tbl_set_cell_value

#############################################################################
# FUNCTION:tbl_set_cell_value
# PURPOSE: sets value for child control in a table cell, processes: html_edit,html_combobox,html_listbox,html_check_button and html_radio_button
# INPUT PARAM: in table_name, in row, in col, in data
# RETURN VALUE: E_OK or E_ERROR
##############################################################################
public function tbl_set_cell_value(in table_name, in row, in col, in data) {
  auto child_object,msw_class;
  web_obj_get_child_item(table_name, "#"row, "#"col, "html_edit", 0, child_object);
  if (child_object=="") web_obj_get_child_item(table_name, "#"row, "#"col, "html_combobox", 0, child_object);
  if (child_object=="") web_obj_get_child_item(table_name, "#"row, "#"col, "html_listbox", 0, child_object);
  if (child_object=="") web_obj_get_child_item(table_name, "#"row, "#"col, "html_check_button", 0, child_object);
  if (child_object=="") web_obj_get_child_item(table_name, "#"row, "#"col, "html_radio_button", 0, child_object);
  if (child_object=="") {
    my_tl_step("tbl_set_value", E_ERROR, "Couldn't get child element for table '"table_name"'(row:'"row"', col:'"col"')");
    return E_ERROR;
  }
  msw_class=substr(child_object,index(child_object,"MSW_class: ")+12,9);
  switch(msw_class) {
    case "html_edit":        # set data using obj_type(), because it is more generic than edit_set()
      replace(data, "\,",-,+,>,<", "\\,\",\-,\+,\>,\<", ","); # ecranize specialsymbols for obj_type
      obj_type(child_object,"<T100><kCtrl_L-a><T100><kDel_E>");  # delete data, if there was something before  
      obj_type(child_object,data);
      break;
    case "html_comb":              
      select_combo(child_object,data);  
      break;
    case "html_list":            
      select_combo(child_object,data);  
      break;
    case "html_chec":    
      button_set(child_object, data);  
      break;
    case "html_radi":    
      button_set(child_object, data);  
      break;    
  }
  return E_OK;
}

tbl_check_cell_val

##########################################################################################
# FUNCTION:tbl_check_cell_val
# PURPOSE: checks that the given cell in the given table contains the given text  
# INPUT PARAMS: tablename, row, col, rightvalue
# RETURN VALUE: E_OK - if it is so, E_WARNING if the value differs, some other error if
#               the table or cell not found (see tbl_get_cell_value).
##########################################################################################
function tbl_check_cell_val(in table_name, in row, in col, in rightvalue) {
  auto r, retvalue;
  r = tbl_get_cell_value(table_name, row, col, retvalue);
  if (r != E_OK) {
    return r;
  }
  if (trim(retvalue) != trim(rightvalue)) {
    return E_WARNING;
  }
  return E_OK;
}

obj_get_desc_by_name

#############################################################################
# FUNCTION:obj_get_desc_by_name
# PURPOSE: Finds a physical description of object even it is not in the GUI mapping file
# INPUT PARAM: obj_name - exact name of object
#              obj_class - MSW_class of object (html_table, html_checkbox)
#              order_type - only can be "index" || "location"
# RETURN VALUE:Returns description or empty string.
##############################################################################
public function obj_get_desc_by_name(in obj_name, in obj_class, in order_type, in match_criteria)
{
  auto obj_description, found_name, nCikls;
 
  for (nCikls=1; nCikls<99; nCikls++) {        # checks up to 99 objects - can be changed
     
    # Generate description of next object
    obj_$description = "{class: object,MSW_class: " & obj_class & "," & order_type & ": " & nCikls & "}";;

    if (obj_exists(obj_description)==E_OK) { # Is object exists at all ?
      web_obj_get_info(obj_description, "name", found_name);  # check for name of found object
      if ((match_criteria=="" || match_criteria=="=") && found_name==obj_name) # If names are equal...
        return obj_description;  # return the description, we are interested
      if (match_criteria=="like" && index(found_name,obj_name)>0) # If names are similar
        return obj_description;  # return the description, we are interested
    }
    else return ""; #<--- If last object was chcked in the frame/window
  }
}

win_save

########################################################################################################
# FUNCTION:win_save
# PURPOSE: count windows before running test and (optionally) save list of existing windows in excel file
# INPUT PARAMS: uses global variable windows_list
#        optional excel_file - file, where windows list will be stored, if not passed, uses array
#        verbose - optional parameter for verbose mode
# RETURN VALUE: E_OK on success, otherwise - Error code
#########################################################################################################
public function win_save (in excel_file, in verbose) {
  auto rc,i,WindowsBeforeList;
  if(windows_list!="") {                        # if function is enabled
    NoBefore=0;
    invoke_application("taskmgr", "", "", SW_SHOW);          # open task manager
    rc=win_exists("wTMInnerFrame", 2);
    if(rc==E_OK) {  
      my_set_window ("wWindowsTaskManager", 10);
      tab_select_item ("tab", "Applications");          # set to task list
      my_set_window ("wTMInnerFrame", 20);
      list_get_items_count("SysListView32", NoBefore);      # get No of windows before
      for(i=0; i<NoBefore; i++) {
        list_get_item("SysListView32", i, WindowsBefore[i]);        # get current window ain write to array
        WindowsBeforeList=WindowsBeforeList & WindowsBefore[i];        # add window name to list
        if (i<NoBefore-1) WindowsBeforeList=WindowsBeforeList & DELIMITER;  # add delimiter only if not last value
      }
      my_set_window ("wWindowsTaskManager", 8);                  # close task manager
      win_min ("wWindowsTaskManager");
      if (excel_file!="") {                          # if file name is passed
        excel_clear_values(excel_file, windows_list);            # clear previous windows list, if exist
        excel_write(excel_file, windows_list,WindowsBeforeList,1,DELIMITER);  # and write current values
        my_tl_step("win_save",0, "Windows list stored in file '"excel_file"'"); # log
      }      
      else {                                  # if file name isn't passed
        my_tl_step("win_save",0, "Windows list stored in array 'WindowsBefore'");  
         if(verbose!="") {                          # if in verbose mode
          for(i=0;i<NoBefore;i++)
             my_tl_step("win_save", 0, "Array value["i"]='"WindowsBefore[i]"'");  # log
        }
      }
      my_tl_step("win_save", 0, "Finished succesfully");        # log
      return rc;
    }
    else {
      my_tl_step("win_save", 1, err_expl(rc));          # can't open task manager
      return rc;
    }
  }
  else {
    my_tl_step("win_save", 0, "Function is disabled");        # function is disabled
    return E_OK;
  }
}  

win_restore

########################################################################################################
# FUNCTION:win_restore
# PURPOSE: count windows after running test and delete unexpected. For previous list use global array, or excel file
# INPUT PARAMS: uses global variable windows_list
#        optional excel_file - file, where windows list was stored, if not passed, uses array
#        verbose - optional parameter for verbose mode
# RETURN VALUE: E_OK on success, otherwise - Error code
#########################################################################################################
public function win_restore(in excel_file, in verbose) {
  auto i,j,WindowsBeforeList,NoAfter,WindowName,WindowExisted,start_time;
  if(windows_list=="") {                          # if function is enabled  
    my_tl_step("Restore_windows", 0, "Function is disabled");      # function is disabled
    return E_OK;
  }    
  if (excel_file!="") {                        # if file name is passed
    for(i=0;i<NoBefore;i++) delete WindowsBefore[i];        # clear array and read values from file
    WindowsBeforeList=excel_read(excel_file, windows_list,1,DELIMITER);  
    NoBefore=split(WindowsBeforeList,WindowsBefore,DELIMITER);
    for(i=0;i<NoBefore;i++) WindowsBefore[i]=WindowsBefore[i+1];  # because split starts with 1 not 0, move elements left
    delete WindowsBefore[NoBefore];                  # delete last element which was duplicaded
    my_tl_step("win_restore", 0, "Windows list loaded from file '"excel_file".xls'");
  }
  else                                 # file name not passed, use array values
    my_tl_step("win_restore", 0, "Windows list loaded from array 'WindowsBefore'");
 
  if (NoBefore=="") {                          # if 'WindowsBefore' is empty exit
    my_tl_step("win_restore", E_WARNING, "Array 'WindowsBefore' is empty. Exiting");  # log windows list
    return E_OPERATION_NOT_PERFORMED;
  }
  if(verbose!="") {                           # if in verbose node
    for(i=0;i<NoBefore;i++)
      my_tl_step("win_restore", 0, "Array value["i"]='"WindowsBefore[i]"'");  # log windows list
  }
             
  invoke_application("taskmgr", "", "", SW_SHOW);            # open task manager
  if(win_exists("{class: window, label: "Windows Task Manager: taskmgr.exe - Application Error"}")==E_OK) {   # if opens with errors
    start_time=get_time();
    while(win_exists("{class: window, label: "Windows Task Manager: taskmgr.exe - Application Error"}", 1)==E_OK)  { # close all error boxes
      if (get_time()>(start_time+timeout_time)) {
        my_tl_step("win_restore",2,"While timeout reached");
        return E_NOT_RESPONDING;
      }
      my_set_window("{class: window, label: "Windows Task Manager: taskmgr.exe - Application Error"}", 1);
      type("<kReturn>");
      invoke_application("taskmgr", "", "", SW_SHOW);
    }
  }
  if(win_exists("wTMInnerFrame", 2)==E_OK) {              # if task manager is ready
    my_set_window ("wTMInnerFrame", 10);
    list_get_items_count("SysListView32", NoAfter);          # count windows after running test
    if(NoAfter > NoBefore) {                    # if windows are more than before start
      for(i=0; i<NoAfter; i++) {                  # check all current windows
        my_set_window ("wTMInnerFrame", 3);
        list_get_item("SysListView32", i, WindowName);      # get one
       
        if(window_preserve(WindowName)==E_OK)          # if widow should be preserved
          continue;                      # go to next

        WindowExisted = FALSE;                  # reset value
        for(j=0;j<NoBefore;j++) {                # check to all windows list, what was before        
          if(WindowName == WindowsBefore[j])  {        # if found
            WindowExisted = TRUE;              # mark that existed before
            break;
          }
        }
        if(WindowExisted == FALSE) {              # if window didn't exist before
          my_set_window ("wTMInnerFrame", 10);        # kill it
          list_select_item ("SysListView32", WindowName);
          button_press ("pbEndTask");
          #Check if some confirmation window appears
          if(win_exists("wTMConfirmation", 1)==E_OK) {
            my_set_window("wTMConfirmation");
            button_press ("pbYes");
            wait(wait_time);
          }
          if(win_exists("wEndProgram", 1)==E_OK) {
            my_set_window("wEndProgram", 1);
            button_press("pbEndNow");
            wait(wait_time);
          }
          i--;                        #Shifting up
          my_set_window ("wTMInnerFrame", 3);  
          list_get_items_count("SysListView32", NoAfter);
          my_tl_step("win_restore", E_WARNING, "Unexpected window '"WindowName"' killed");  # log            
          if(NoAfter == NoBefore)
            break;
        }
      }
    }
    my_set_window ("wWindowsTaskManager", 8);              # minimize task manager
    win_min ("wWindowsTaskManager");
    my_tl_step("win_restore", 0, "Finished succesfully");        # log
  }
}  

window_preserve

########################################################################################################
# FUNCTION:window_preserve
# PURPOSE: check, if window shown in TaskManeger should be preserved from killing
# INPUT PARAMS: window_name - name of the window
# RETURN VALUE: E_OK if window is in preserve_windows array (and should be preserved), else E_NOT_FOUND
#########################################################################################################
public function window_preserve(in window_name) {
  auto i;
  for (i in preserve_windows) {
    if (index(window_name,preserve_windows[i])!=0)
      return E_OK;
  }
  return E_NOT_FOUND;
}

select_referenced_item

##################################################################################################
# FUNCTION:select_referenced_item
# PURPOSE: next generation of function to select referenced value using search form
# INPUT PARAMS: required link_button, which should be pressed to open dialog window,
#        values - delimited list of values, if value is for combobox, it should have prefix "combo" e.g. "Val|comboVal2"        
#        first_window, second_window - windows whis should be set before and after Search operation
#        list_table -name of table in which results are show
#        options - "DontCommit/DontSearch"
# RETURN VALUE: name of the selected item
###################################################################################################
public function select_referenced_item (in link_button, in values, in first_window, in second_window, in list_table, in options) {
  auto count, valuesa[],i,j,row,col,cellvalue,start_time,link,commit,search,selected;
  if (first_window=="") first_window="wSearch2";
  if (second_window=="") second_window=first_window;
  if (list_table=="") list_table="tList";
  if (index(options,"DontCommit")==0) commit=ON;
  if (index(options,"DontSearch")==0) search=ON;
                                  # *** OPEN *** search window
  if (link_button!="") navigate(link_button,"ABC",first_window);  # click button in ABC window, set 1st window (e.g. html_name Search* or PopupDialog*)
  else my_set_window(first_window);
 
  if(search==ON) {                        # *** SEARCH *** for value
    count=split(values,valuesa,DELIMITER);                    
    j=0;                          
    for (i=1;i<=count;i++) {          # fill text/combo boxes with search criteria
      if (index(valuesa[i],"combo")==1) {
        if(obj_exists("{class: list,MSW_class: html_combobox,html_name: "!.*",location: "j"}")==E_OK) {
          select_combo("{class: list,MSW_class: html_combobox,html_name: "!.*",location: "j"}",valuesa[i]);
          j++;
        }
      }
      else
        if(obj_exists("{class: edit,MSW_class: html_edit,html_name: "!.*", location: "i-1"}")==E_OK)
          my_edit_set("{class: edit,MSW_class: html_edit,html_name: "!.*", location: "i-1"}", valuesa[i]);
      if (valuesa[i]!="" && cellvalue=="") cellvalue=valuesa[i];    # set first non-empty string as necessary value
    }
    if(obj_exists("bSearch")==E_OK)
      navigate("bSearch",first_window,second_window,wait_time);  # click on search using navigate, but including window changes
    row=0;
    start_time=get_time();                
    do {        # try while "Current request is being processed.  Please wait until done and try again" disappear
      if(get_time()>(start_time+timeout_time)) {
        my_tl_step("select_referenced_item", E_WARNING, "Timeout reached to get '"list_table"' table.");
        break;
      }
      wait(wait_time);
      web_sync(timeout_time);
      web_refresh(second_window);
    } while (obj_exists(list_table)!=E_OK && obj_exists("tNoRecords")!=E_OK);
    if(obj_exists(list_table)==E_OK) tbl_get_rows_count (list_table, row);
 
    if(row==0) {
      my_tl_step("select_referenced_item", E_WARNING, "Couldn't get rows for table '"list_table"'. Trying search with empty criteria for 1st field");
      my_edit_set("{class: edit,MSW_class: html_edit,html_name: "!.*", location: 0}","");
      navigate("bSearch",second_window);
      start_time=get_time();                
      do {        # try while "Current request is being processed.  Please wait until done and try again" disappear
        if(get_time()>(start_time+timeout_time)) {
          my_tl_step("select_referenced_item", E_WARNING, "Timeout reached to get '"list_table"' table.");
          break;
        }
        wait(wait_time);
        web_sync(timeout_time);
        web_refresh(second_window);
      } while (obj_exists(list_table)!=E_OK && obj_exists("tNoRecords")!=E_OK);
      if(obj_exists(list_table)==E_OK) tbl_get_rows_count (list_table, row);
 
      if(row==0) {
        my_tl_step("select_referenced_item", E_WARNING, "Couldn't get rows for table '"list_table"'. Trying search with * for 1st field");
        my_edit_set("{class: edit,MSW_class: html_edit,html_name: "!.*", location: 0}","*");
        navigate("bSearch",second_window);
        start_time=get_time();                
        do {        # try while "Current request is being processed.  Please wait until done and try again" disappear
          if(get_time()>(start_time+timeout_time)) {
            my_tl_step("select_referenced_item", E_WARNING, "Timeout reached to get '"list_table"' table.");
            break;
          }
          wait(wait_time);
          web_sync(timeout_time);
          web_refresh(second_window);
        } while (obj_exists(list_table)!=E_OK && obj_exists("tNoRecords")!=E_OK);
        if(obj_exists(list_table)==E_OK) tbl_get_rows_count (list_table, row);
        if(row==0) {
          my_tl_step("select_referenced_item", E_WARNING, "Couldn't get any record for '"list_table"' table in '"second_window"' window");
          return E_ERROR;
        }
       }
    }                            
    if (row>1) {                      # if more than one record was found, goto last page
      if(obj_exists("bShowLastPage")==E_OK)        # using Show Last Page button
        navigate("bShowLastPage",second_window);    
      if(obj_exists("ResultList")==E_OK) {        # or Result List combobox
        select_combo("ResultList","",-1);
        web_sync(timeout_time);
      }
      start_time=get_time();                
        do {        # try while "Current request is being processed.  Please wait until done and try again" disappear
          if(get_time()>(start_time+timeout_time)) {
            my_tl_step("select_referenced_item", E_WARNING, "Timeout reached to get '"list_table"' table.");
            break;
          }
          wait(wait_time);
          web_sync(timeout_time);
          web_refresh(second_window);
        } while (obj_exists(list_table)!=E_OK);
    }
  }                                  # *** GET VALUE *** for item selection
 
  if (cellvalue!="" && tbl_find_text(list_table, cellvalue, row, col,1,ON)==E_OK)    # search for exact match, starting from the 1st row
    tbl_get_cell_value(list_table, row, col, cellvalue);      # get coordinates for cell of necessary item
  else {                                # or get value of the last row
    tbl_get_rows_count (list_table, row);              # get number of the last row
    tbl_get_cols_count (list_table, col);              # and count of columns
    i=0;
    do {                              # and search non-empty value for cells in last row
      i++;
      tbl_get_cell_value(list_table, row, i, cellvalue);
    } while (cellvalue=="" && i<=col);  
  }
  cellvalue=substr(cellvalue,index(cellvalue," ")+1);          # get last word only, drop "http://.." and other mess
  web_obj_get_child_item(list_table,row,i,"html_text_link",0,link);  # get link for selected cell
                              
  selected=OFF;                            # *** SELECT *** item in different ways
  if (link!="") {
    navigate(link,second_window,"ABC");
    return cellvalue;                        # by clicking on hyperlink, window is closed
  }
  if(obj_exists("{class: object,MSW_class: html_text_link,html_name: ""cellvalue""}")==E_OK) {
    navigate("{class: object,MSW_class: html_text_link,html_name: ""cellvalue"",location: 0}",second_window,"ABC"); # location is necessary, if equal links appear
    return cellvalue;                        # by clicking on hyperlink, window is closed
  }
  if(obj_exists("{class: push_button, MSW_class: html_push_button, html_name: Select, location: "row-1"}")==E_OK) {
    navigate("{class: push_button, MSW_class: html_push_button, html_name: Select, location: "row-1"}",second_window,"ABC");
    return cellvalue;                        # by clicking "Select" buton, window also is closed, go back to "ABC"   
  }

  if (obj_exists("{class: check_button,MSW_class: html_check_button,html_name: "!.*.control_pde_system_column",part_value: false,location: "row-1"}")==E_OK) {  
    button_set("{class: check_button,MSW_class: html_check_button,html_name: "!.*.control_pde_system_column",part_value: false,location: "row-1"}",ON);
    selected=ON;
  }
                                    # check button, needs to be commited later    
  if(obj_exists("{class: object,MSW_class: html_general_element,html_name: ""cellvalue"",tag_name: SPAN, location: 0}")==E_OK) {
    navigate("{class: object,MSW_class: html_general_element,html_name: ""cellvalue"",tag_name: SPAN, location: 0}",second_window);
    selected=ON;
  }
                                    # another check button, also needs to be commited later    
  if (obj_exists("{class: radio_button, MSW_class: html_radio_button, html_name: "!.*.control_pde_system_column", location: "row-1"}")==E_OK) {
    button_set("{class: radio_button, MSW_class: html_radio_button, html_name: "!.*.control_pde_system_column", location: "row-1"}",ON);
    selected=ON;
  }                                  # if last row of table wasn't found but 0. check_button exists, select it
  if (selected==OFF && obj_exists("{class: check_button, MSW_class: html_check_button, location: 0}")==E_OK) { # if none of objects was selected (e.g. wrong table name was passed) try to select 1st record in last table
    button_set("{class: check_button, MSW_class: html_check_button, location: 0}",ON);
    my_tl_step("select_referenced_item", E_WARNING, "0. check_button was selected. Probably '"list_table"' is wrong table name");
    selected=ON;
  }                                  # if last row of table wasn't found but 0. radio_button exists, select it
  if(selected==OFF && obj_exists("{class: radio_button, MSW_class: html_radio_button, location: 0}")==E_OK) {  # using radio button
    button_set("{class: radio_button, MSW_class: html_radio_button, location: 0}",ON);
    my_tl_step("select_referenced_item", E_WARNING, "0. radio_button was selected. Probably '"list_table"' is wrong table name");
    selected=ON;
  }
  if (selected==OFF && obj_exists(list_table)==E_OK) {
    tbl_set_selected_cell (list_table,1,1);    
    my_tl_step("select_referenced_item", E_WARNING, "Cell (1,1) of table '"list_table"' was selected");
    selected=ON;
  }
                                    # if still none of selection was applied, put warning in log  
  if (selected==OFF) my_tl_step("select_referenced_item", E_WARNING, "None of records was selected. Probably '"list_table"' is wrong table name");
                                   
                                    # *** COMMIT *** operation in different ways
  if(commit==ON) {                                    
    if (obj_exists("bSelect")==E_OK) navigate("bSelect",second_window,"ABC");   # Select button
    if (obj_exists("bOk")==E_OK) navigate("bOk",second_window,"ABC");      # Ok button
  }
 
  return cellvalue;
}

select_referenced_project

##################################################################################################
# FUNCTION:select_referenced_project
# PURPOSE: select referenced project using its specific approach  
# INPUT PARAMS: required element, optional  projectname (default - "*") and projectdate (default - current date)
# RETURN VALUE: name of the selected project
###################################################################################################
public function select_referenced_project(in element, in projectname, in projectdate) {
  auto i,rows,retvalue;
  if (projectdate=="") projectdate=date_from_WRsecs("MM/DD/YYYY");
  if (projectname=="") projectname="*";
  navigate(element,"ABC", "Edit Project History");
  i=0;
  while(obj_exists("{class: push_button,MSW_class: html_push_button,html_name: "...",location: "i"}")==E_OK)
    i++;
  navigate("bAddNewProject","Edit Project History","wSearchResults");

  navigate("{class: push_button,MSW_class: html_push_button,html_name: "...",location: "i"}","wSearchResults");
  my_edit_set("{class: edit,MSW_class: html_edit,html_name: "!.*", location: 0}",projectname);
  navigate("bSearch","wSearchResults");
  rows=0;
  if (obj_exists("tProjects")==E_OK) tbl_get_rows_count("tProjects",rows);
  if(rows==0) {
    my_tl_step("select_referenced_project",E_WARNING,"Project '"projectname"' was not found, trying to search any");
    my_edit_set("{class: edit,MSW_class: html_edit,html_name: "!.*", location: 0}","*");
    navigate("bSearch","wSearchResults");
    rows=0;
    if (obj_exists("tProjects")==E_OK) tbl_get_rows_count("tProjects",rows);
    if(rows==0) {
      my_tl_step("select_referenced_project",E_ERROR,"Couldn't find any Project. Exiting.");
      my_set_window("ABC");    
      return E_ERROR;
    }
  }
  tbl_get_cell_value("tProjects", rows, 1, retvalue);
  retvalue=substr(retvalue,index(retvalue," ")+1);          # get last word only, drop "http://.." and other mess

  navigate("{class: object, MSW_class: html_general_element, html_name: ""retvalue"", tag_name: TD, location: 0}","wSearchResults");
  navigate("bOk","wSearchResults");
  my_edit_set("{class: edit,MSW_class: html_edit,html_name: edit,location: "i"}","01/01/2005");
  navigate("bOK","wSearchResults","ABC");
  return retvalue;
}

select_combo

#############################################################################
# FUNCTION:select_combo
# PURPOSE: Selects passed item in combo box or other if not found, or if shifted
# INPUT PARAMS: <combo_name>, [item_name] - if not passed, select 1st record (#0), [shift=0] - shift from selected item +forward, -backward, goes trough list recurrently,[shift_allways]
# RETURN VALUE: selected item name, or E_GENERAL_ERROR on error
# SAMPLES:
#      get exact item: select_combo("combo_name","item_name")
#       get 1st item: select_combo("combo_name"),
#      get last record: select_combo("combo_name","",-1)
#      get another value: select_combo("combo_name","item_name",1)
##############################################################################
public function select_combo(in combo_name, in item_name, in shift, in shift_allways) {
  auto count=0,cur_no=0,list_item=0,found, curr_win;
  if(shift=="") shift=0;
  if(shift_allways=="") shift_allways=ON;
  if(combo_name=="") {
    my_tl_step("select_combo",1,"No combo name passed to function");
    return E_GENERAL_ERROR;
  }
  curr_win = GUI_get_window();                    # get current window
  if(obj_exists(combo_name)!=E_OK) {
    my_tl_step("select_combo",1,"Combo '"curr_win":"combo_name"' isn't found");
    return E_GENERAL_ERROR;
  }  
  if(higlith_objects==ON) obj_highlight(combo_name,1);                
  list_get_info(combo_name,"count",count);              # counts all returned values
  if (item_name!="" && count>0) {
    found=check_list_presence(combo_name, item_name);          
    if (found!=E_NOT_FOUND) {                    # if similar value exists in list
      if(found==E_OK) found=item_name;              # set finding result to exact value
      else                             # or
        my_tl_step("select_combo", 2 , "'"found"' is selected in place of '"item_name"' from '"combo_name"'");  # log warning
      list_select_item_byval(combo_name,found);          # select it, using safe selection (only by value)
      web_sync(timeout_time);    #mihailb for stability
#      list_get_selected (combo_name,list_item,cur_no);      # get record number and value
    list_get_info(combo_name,"value",list_item);            # get record number and value (could be multiple records)
    list_get_item_num (combo_name, list_item, cur_no );  
    }
  }                                  # if shift is passed/necessary
  if (item_name=="" || (shift!=0 && (shift_allways==ON || found==E_NOT_FOUND))) {  
    if(count>1) {                            # if there is more than one choice
      shift=shift+cur_no;                        # recalculate shift from selected record
      if(shift<0)                            # if result is negative
         list_select_item (combo_name, "#" & (count+(shift%count)));  # count recurrently backward
      else                              # if result is positive
        list_select_item (combo_name, "#" & (shift%count));      # count recurrently forward
    }
    else list_select_item (combo_name, "#0");
#    list_get_selected (combo_name,list_item,cur_no);          # get record number and value
    list_get_info(combo_name,"value",list_item);            # get record number and value (could be multiple records)
    list_get_item_num (combo_name, list_item, cur_no );  
    my_tl_step("select_combo", 2 , "#" cur_no" record '"list_item"' is selected from '"combo_name"'");  
  }
  return list_item;                            # return selected value
}

list_select_item_byval

#############################################################################
# FUNCTION:list_select_item_byval
# PURPOSE: Allow selecting items by values strating with "#", in difference to list_select_item() which treats it as item/record number
# INPUT PARAMS: list_name - name or description of the combo box, item_name - item value  
# RETURN VALUE: selected item, or E_NOT_FOUND on error
# SAMPLES: list_select_item_byval("combo_name","#123") will celect record with value "#123", not 123. record of the combobox
##############################################################################
public function list_select_item_byval(in list_name, in item_name) {
  auto i,item_count,item_content;
  list_get_info(list_name,"count",item_count);          # Count of Items in List to ItemCount
  for (i=0; i<item_count; i++) {                # review all items
    list_get_item(list_name, i, item_content);         
    if (item_content == item_name) {            # if math was found
      list_select_item(list_name, "#"i);          # select it
      return item_content;
    }
  }
  return E_NOT_FOUND;
}

get_mainwin_desc

#############################################################################
# FUNCTION:get_mainwin_desc
# PURPOSE: Finds a physical description of browser_main_window by partial/suspected label
# INPUT PARAM: label_substring - expected label of browser_main_window
# RETURN VALUE: Returns description or empty string.
##############################################################################
public function get_mainwin_desc(in label_substring, inout i) {
  auto value;
  for (i=0;i<MAX_OPENED_WINDOWS;i++) {
    if (win_exists("{class: window,MSW_class: browser_main_window,NSTitle: "Browser Main Window",location: "&i&"}") == 0) {
      win_get_info("{class: window,MSW_class: browser_main_window,NSTitle: "Browser Main Window",location: "&i&"}","label",value);
      # Check if window label starts with passed      
      if (index(value,label_substring)>0) {
        return "{class: window,MSW_class: browser_main_window,NSTitle: "Browser Main Window",location: "&i&"}";
      }
    } else return;
  }
}

win_get_property

#############################################################################
# FUNCTION:win_get_property
# PURPOSE: Returns value of window property e.g. Label,Width,Height,Enabled,Focused,etc. see WR help for window property
# it is better than win_get_info, because it doesn't require out parameter
# INPUT PARAM: window - window name or description, property_name
# RETURN VALUE: Returns value of the property or error code
##############################################################################
public function win_get_property(in window, in property_name) {
  auto property_val, val;
  val=win_get_info(window,property_name, property_val);
  if (val==E_OK) return property_val;
  else return val;
}

trim

#############################################################################
# FUNCTION:trim
# PURPOSE: drops spaces from string
# INPUT PARAM:   str - input string
# RETURN VALUE: string without spaces
##############################################################################
public function trim(in str) {
  auto len,ret,start,end;
  len=length (str);
  for(start=1;start<=len;start++)
    if(substr(str,start,1)!=" ")
      break;
  for(end=len;end>1;end--)
    if(substr(str,end,1)!=" ")
      break;
  return substr(str,start,len-start-(len-end)+1);
}

file_read

##############################################################################################
# FUNCTION:file_read
# PURPOSE: Read value from file and return it content to value
# INPUT PARAMS: mandatory file_name. If only file name is passed, current directory is appened.
# RETURN VALUE: value
##############################################################################################
public function file_read (in file_name,in dont_warn) {
  auto test_path, value, line, depth, i;
  if(index(file_name,"\")==0) file_name=root_path"\"LOG_DIR"\"file_name; # if full file name is not passed, set to LOG_DIR
  file_open(file_name,FO_MODE_READ);
  while(file_getline(file_name,line)==E_OK) {
    if((length(value)+length(line)+2)>VARIABLE_MAX_LENGTH) {
      if(dont_warn=="") my_tl_step("file_read",2,"Maximum of string ("VARIABLE_MAX_LENGTH") is retrieved!");
      break;
    }
    value=value&line&"rn";
  }
  value=substr(value,1,length(value)-2);        # remove last "rn"
  file_close(file_name);
  return value;
}

file_append

#############################################################################
# FUNCTION:file_append
# PURPOSE: appends specified string as new line to specified file
# INPUT PARAM:   name - file name
#        value - string what should append
# RETURN VALUE: no
##############################################################################
public function file_append(in file_name, in value) {
  auto test_path, depth, i;
  if(index(file_name,"\")==0) file_name=root_path"\"LOG_DIR"\"file_name; # if full file name is not passed, set to LOG_DIR
  file_open(file_name,FO_MODE_APPEND);            # open file in append mode
  if(substr(value,length(value)-1,2)!="rn") value=value&"rn";   # add next line, if necessarry
  file_printf(file_name,"%s",value);              # write string
  file_close(file_name);                    # close file
}

file_write

#############################################################################
# FUNCTION:file_write
# PURPOSE: writes specified string in the specified file
# INPUT PARAM:   file_name - file name without txt extension, value - string what should written
# RETURN VALUE: no
##############################################################################
public function file_write(in file_name, in value) {
  auto test_path, depth, i;
  if(index(file_name,"\")==0) file_name=root_path"\"LOG_DIR"\"file_name; # if full file name is not passed, set to LOG_DIR  
  file_open(file_name,FO_MODE_WRITE);              # open file in append mode
  file_printf(file_name,"%s",value);              # write string
  file_close(file_name);                    # close file
}

screen_shoot

##################################################################################################
# FUNCTION:screen_shoot
# PURPOSE: save screenshoot in passed file name, or generates unique filene in format "yymmddhhnn"
# INPUT PARAMS: file_name (without file extension)
#
# RETURN VALUE: E_OK on success, otherwise - Error code
###################################################################################################
public function screen_shoot(in file_name) {
  auto i;
  if (file_name=="") file_name=date_from_WRsecs("YYMMDDHHNNSS");
  if(index(file_name,"\")==0) file_name=root_path"\"LOG_DIR"\"file_name; # if full file name is not passed, set to LOG_DIR
   
  type("<kCtrl_L-kPrSc>");                  # copy screen to clipboard
  i=0;
  while (win_exists("{class: window, label: "!.*Paint", MSW_class: MSPaintApp, location: "i"}")==E_OK)
    i++;                        # count existing Paintbrush windows
  GUI_buf_set_desc_attr(gui_home, "Paint", "", "location",i);  # set location to new one
  invoke_application("mspaint", "", "", SW_SHOW);      # start MS paint
  wait(wait_time);
 
  if (win_exists("Paint")==E_OK) {  
    set_window ("Paint", 30);                # Paintbrush window
    obj_type ("Edit","<kCtrl_L-v>");            # paste content
    if(win_exists("Paint_1",1)==E_OK) {            # if window for resizing file appear
      set_window("Paint_1");
      button_press ("Yes");                # confirm it
    }
 
    set_window("Paint");
    menu_select_item ("File;Save Ctrl+S");          # open save dialog
    set_window ("Save As", 5);
    edit_set ("File name", file_name);
    if (list_check_presence("Save as type:", "JPEG")!=E_NOT_FOUND)
      select_combo("Save as type:", "JPEG (*.JPG;*.JPEG;*.JPE;*.JFIF)");
    else  select_combo("Save as type:", "24");
 
    button_press ("Save");                  # press Save button
    if(win_exists("Paint_1",1)==E_OK) {            # if window about loss of color appears
      set_window("Paint_1");
      button_press ("Yes");                # confirm it
    }
    if(win_exists("Save As_1")==E_OK) {           # if window about  existing file appears
      set_window("Save As_1");
      button_press ("Yes");                # confirm it
    }    
    win_close ("Paint");                  # close    
    my_tl_step ("screen_shoot",E_WARNING,"Screen shoot stored inthe file '"file_name"'");
  }    
  return E_OK;
}

save_html_source

##################################################################################################
# FUNCTION:save_html_source
# PURPOSE: save html source of the window (html frame) in file
# INPUT PARAMS: optional file_name and curr_window (current window)
# RETURN VALUE: E_OK on success, otherwise - Error code
###################################################################################################
public function save_html_source(in file_name, in curr_win) {
  auto x,y,width,height,i;
  if (file_name=="") file_name="Source"&date_from_WRsecs("YYMMDDHHNNSS");
  if(index(file_name,"\")==0) file_name=root_path"\"LOG_DIR"\"file_name; # if full file name is not passed, set to LOG_DIR
  file_name="""file_name".htm"";
  if(curr_win=="") curr_win = GUI_get_window();      # get current window
  if (win_exists(curr_win)!=E_OK) {
       my_tl_step("save_html_source",E_WARNING,"Curren window '"curr_win"' doesn't exist and could not be handled");
       return E_ERROR;
    }
  win_get_info(curr_win,"X",x);              # get coordinates of the window
  win_get_info(curr_win,"Y",y);
  win_get_info(curr_win,"Width",width);          # right click on center
  win_get_info(curr_win,"Height",height);
  move_locator_abs(x+int(width/2), y+int(height/2));
  i=0;
  while (win_exists("{class: window, label: "!.*.Notepad.*", location: "i"}")==E_OK)
    i++;                        # count existing Notepad windows

  GUI_buf_set_desc_attr(gui_home, "Notepad", "", "location",i); # set location to new one
    mtype ("<T300><kRight>-<T100><kRight>+");        # and choose "view Source"
    move_locator_rel(40, 210);                
    mtype ("<T300><kLeft>-<T100><kLeft>+");
    wait(wait_time);
  if (win_exists("Notepad")==E_OK) {    
    set_window("Notepad",30);
    menu_select_item("File;Save As...");
    set_window ("Save As", 5);
    edit_set ("File name", file_name);
    select_combo("Save as type:", "All Files");      
    button_press ("Save");                # press Save button
    wait(wait_time);
    if(win_exists("Save As_1")==E_OK) {         # if window about  existing file appears
      set_window("Save As_1");
      button_press ("Yes");              # confirm overwrite
    }    
    wait(wait_time);  
    win_close ("Notepad");                # close    
    my_tl_step("save_html_source",E_WARNING,"HTML source is saved in the file '"file_name"'");
  }
  else my_tl_step("save_html_source",E_WARNING,"Couldn't save HTML source in file");
  return E_OK;
}

check_error

#############################################################################
# FUNCTION:check_error
# PURPOSE: check for application error messages
# INPUT PARAM: no
# RETURN VALUE: E_OK or E_ERROR
##############################################################################
public function check_error(in expected_error) {
  auto i,url,color,bgcolor,text,error,id;
  my_set_window("ABC",10);
  i=0;
  error="";
  while (obj_exists("{class: object,MSW_class: html_text_link,html_name:"!.*",location:"i"}")==E_OK) {
        # check for error using keyword in url or background color
    web_obj_get_info("{class: object,MSW_class: html_text_link,html_name:"!.*",location:"i"}","url",url);  
    web_obj_get_info("{class: object,MSW_class: html_text_link,html_name:"!.*",location:"i"}","current_bgcolor",bgcolor);
    web_obj_get_info("{class: object,MSW_class: html_text_link,html_name:"!.*",location:"i"}","color",color);      
    web_obj_get_info("{class: object,MSW_class: html_text_link,html_name:"!.*",location:"i"}","html_id",id);    
    if (index(url,"#error")>0 || color=="#ff0000" || bgcolor=="#ff0000" || index(id,"error")>0) {
      web_obj_get_info("{class: object,MSW_class: html_text_link,html_name:"!.*",location:"i"}","text",text);
      error=error&text&".";
    }
    i++;
  }
  if (error!="") {          # if runtime error appeared
    switch (expected_error) {              
      case "":
        my_tl_step("check_error",E_ERROR,"Following error(s) appeared:'"error"'");
        error=E_ERROR;
        break;
      case "No":
        my_tl_step("check_error",E_ERROR,"Following error(s) appeared:'"error"'");
        error=E_ERROR;
        break;
      case "Yes":
        my_tl_step("check_error",E_OK,"Expected error(s) '"error"' appeared");
        error=E_OK;
        break;
      default:
        if (index(error,expected_error)>0) {
          my_tl_step("check_error",E_OK,"Expected error '"expected_error"' appeared in '"error"'");
          error=E_OK;
        }
        else {
          my_tl_step("check_error",E_WARNING,"Other error '"error"' appeared in in place of expected error '"expected_error"'");
          error=E_WARNING;
        }
    }  
  }
  else {             # if runtime error didn't appear          
    switch (expected_error) {    
      case "":      # if wasn't expected, return E_OK
        error=E_OK;
        break;
      case "No":
        error=E_OK;
        break;
      case "Yes":      # if was expected, return E_ERROR
        my_tl_step("check_error",E_ERROR,"Expected error '"error"' didn't appear");
        error=E_ERROR;
        break;
      default:
        my_tl_step("check_error",E_ERROR,"Expected error '"expected_error"' didn't appear");
        error=E_ERROR;
    }  
  }
  return error;  # return error code  
}

check_exception

#############################################################################
# FUNCTION:check_exception
# PURPOSE: check for application exception window
# INPUT PARAM: no
# RETURN VALUE: E_OK, E_ERROR, E_HANDLING
##############################################################################
public function check_exception() {
  extern is_exception;
  auto cwin;
  if (is_exception!=E_HANDLING) {          # if not in exception handling chain already  
    cwin=get_mainwin_desc("Error report");    # catch for application exception
    if (cwin!="") {
      my_tl_step("check_exception",E_ERROR,"Application failed with exception");
      is_exception=E_ERROR;          # trigger is_exception to E_ERROR, if exception was occured
    }
    else is_exception=E_OK;            # or E_OK, if not
  }
  return is_exception;
}

exception_handler

#############################################################################
# FUNCTION:exception_handler
# PURPOSE: handle application exceptions. Clear environment, write to test log and exit from fuctional script
# INPUT PARAM:   optional rc - error code
#        optional func - function what generated error
#        uses global parameter batch_mode
# RETURN VALUE: none
##############################################################################
public function exception_handler(in rc, in func) {
  extern is_exception;
  auto depth,testname,line_no,ftype,ffunction,str,i,j,subtest[],cwin,test_chain,cdate;
  is_exception=E_HANDLING;
  depth=call_chain_get_depth();
  test_chain=0;
  str="Function:'"func"' Error:'"rc"'"err_expl(rc);
  str=str&";Call depth:"depth";Call chain:";
  for(i=depth-1;i>=0;i--) {                            # go trough call chain
    call_chain_get_attr("testname",i,testname);
    if (index(testname,FUNCTION_TEST)==0) j=split(testname,subtest,"\");    # if get actual test split test path in parts
    call_chain_get_attr("line_no",i,line_no);                  # format call chain string
    call_chain_get_attr("type",i,ftype);
    str=str&"'"testname"':"line_no;    
    if(ftype=="function") {                            # if call is from function,
      call_chain_get_attr("function",i,ffunction);    
      str=str&":"ffunction;                          # append function name
    }
    else test_chain++;  
    if (i>0) str=str&"->";
  }
  my_tl_step("exception_handler",E_WARNING,str);                  # add to log (and) log file

  cwin=get_mainwin_desc("Error report");            # handle application exception, if exists
  if (cwin!="") set_window("Apache Tomcat - Error report");      

  if (batch_mode==ON) {                  # if in batch_mode
    cdate=date_from_WRtime("YYYY-MM-DD_HH-NN-SS");
    save_html_source(root_path"\"LOG_DIR"\"cdate"_"subtest[j]"_src");  # save html source of the current window
    screen_shoot(root_path"\"LOG_DIR"\"cdate"_"subtest[j]"_exc");    # and take screen shoot
  }

  for (i=MAX_OPENED_WINDOWS; i>=0;i--) {            # close all Browser Main Windows, starting from last one
    if(win_exists("{class: window,MSW_class: browser_main_window,NSTitle: "Browser Main Window",location: "i"}")==E_OK)
      win_close("{class: window,MSW_class: browser_main_window,NSTitle: "Browser Main Window",location: "i"}");
  }
 
  if(test_chain>1) {      # if test call chain > 1 can, run texit (else it breaks WR)
    if (getvar("batch")!="on") {                          # if WinRunner Settings-General Options-Run in batch mode is off
      if (MessageBoxA(0,"StopTest invoked.nContinue current test?","Attention!",4)==6) {  # open dialog box, if answer is Yes
        my_tl_step("exception_handler",E_WARNING,"Texit cancelled");
        return E_GENERAL_ERROR;                          #  simply exit, test will try to run further
      }
    }
    my_tl_step("exception_handler",E_WARNING,"Texit was executed");          # else texit is evaluated
    eval("texit (E_GENERAL_ERROR);");            # run texit
  }
  is_exception=E_OK;                      # allow to handle new exception
}

my_set_window

#############################################################################
# FUNCTION:my_set_window
# PURPOSE: Smarter operating with my_set_window. In case of failure, call exception handler
# INPUT PARAM:   window - window name, optional time - additional timeout
# RETURN VALUE: E_OK or error code
##############################################################################
public function my_set_window(in window, in time) {
  extern is_exception;
  auto rc, i;
  time=timeout_time;                # ignore all other settings and use global constant for timeout

  if(check_exception()==E_ERROR) {        # to avoid recursive invocation of exception_handler()
    exception_handler(E_ERROR,"my_set_window");  # invoke only if E_ERROR (in further invocation chain it returns E_OK/E_HANDLING)
    return E_ERROR;
  }                 
  for(i=1;i<=attempts;i++) {
    rc=set_window(window,time);          # !!! change back this line after global replacement !!!
    if (rc==E_OK) break;  
  }
 
  if (i>1) my_tl_step ("my_set_window",E_WARNING,"'"window"' was invoked unsuccesfully "i-1" times!");

          # if window was not found and run in batch_mode,  and not in exception handling chain already
  if (i>attempts && batch_mode==ON && is_exception!=E_HANDLING) {    
    my_tl_step("my_set_window",E_WARNING,"my_set_window was unsuccesfull, exception_handler is invoked");
    exception_handler(rc, "my_set_window");   # resume as exception
  }  
  return rc;
}

my_edit_set

#############################################################################
# FUNCTION:my_edit_set
# PURPOSE: Smarter operating with edit_set. In case of failure log is generated
# INPUT PARAM:   edit_name, control name or description, value - which should be set
# RETURN VALUE: E_OK or error code
##############################################################################
public function my_edit_set(in edit_name, in value) {
  auto count=0,cur_no=0,list_item=0,found, curr_win;
  if(edit_name=="") {
    my_tl_step("my_edit_set",E_WARNING,"No edit name passed to function");
    return E_NOT_FOUND;
  }
  curr_win = GUI_get_window();                    # get current window
  if(obj_exists(edit_name)!=E_OK) {
    my_tl_step("my_edit_set",E_WARNING,"Editbox '"curr_win":"edit_name"' isn't found");
    return E_NOT_FOUND;
  }
  if(higlith_objects==ON) obj_highlight(edit_name,1);
  edit_set(edit_name, value);
  return E_OK;
}

my_db_connect

#############################################################################
# FUNCTION:my_db_connect
# PURPOSE: Smarter operating with error handling
# INPUT PARAM:   required session_name, odbc_source_name, optional timeout
# RETURN VALUE: E_OK or error code
##############################################################################
public function my_db_connect(in session_name, in odbc_source_name,in timeout) {
  auto retval;
  if (timeout=="") timeout = timeout_time;
  retval=db_connect(session_name,odbc_source_name,timeout);      # open session for session table
  if (retval!=E_OK) tl_step("db_connect",retval,"session: '"session_name"' ODBC source: '"odbc_source_name"' Error:'"err_expl(retval)"'");  # check for success and log
  return retval;
}  

my_db_execute_query

#############################################################################
# FUNCTION:my_db_execute_query
# PURPOSE: Smarter operating with error handling
# INPUT PARAM:   required in: session_name, sql_statement, required out: row_number
# RETURN VALUE: E_OK or error code
##############################################################################
public function my_db_execute_query(in session_name, in sql_statement,out row_number) {
  auto retval;
  retval=db_execute_query (session_name,sql_statement,row_number);    # execute SQL statement
  if (retval!=E_OK) tl_step("db_execute_query",retval,"session: '"session_name"' SQL: '"sql_statement"' Error:'"err_expl(retval)"'");  # check for success and log
  return retval;
}

my_tl_step

#############################################################################
# FUNCTION:my_tl_step
# PURPOSE: Write to test WR log and if batch_mode==ON, also into file and database
# INPUT PARAM:   mandatory step_name, status, description
# RETURN VALUE: none
##############################################################################
public function my_tl_step(in step_name, in status, in step_description) {
  auto retval, value,now,time,test_name,test_namea[],last,i, row_number;
  test_name=get_test_name();
  tl_step(step_name,status,step_description);  # log into standard WR log !!! change bach this line after global replacement !!!
                        # log into database  
  if (batch_mode==ON) {
    now=date_from_WRsecs("YYYY-MM-DD HH:NN:SS");
    time=date_from_WRsecs("HH:NN:SS");
    value=status"t"step_description"t"step_name"t"test_name"t"now;
    file_append(root_path&"\"&LOG_DIR&"\"&run_label&".log",value);
    replace(run_label,"'","''");      # replace ' to '' for SQL statement
    replace(status,"'","''");
    replace(test_name,"'","''");
    replace(step_name,"'","''");
    replace(step_description,"'","''");
    my_db_execute_query(LOG_SES, "INSERT INTO [-Log](RunLabel,Status,Test,Step,Info,CTime) VALUES('"run_label"','"status"','"test_name"','"step_name"','"step_description"','"time"');",row_number);
  }
}

replace

##############################################################################################
# FUNCTION:replace
# PURPOSE: Replace substring from (delimited list of values) with to (delimited list of values) in string str
# INPUT PARAMS: mandatory str (string), from (what), to (to replace), delim(delimiter)
# RETURN VALUE: string
##############################################################################################
public function replace(inout str, in from, in to, in delim) {
  auto pos,end,search_from, froma[], toa[], fromi, toi,i;
  if (delim=="") delim=DELIMITER;          # set delimiter
  fromi=split(from,froma,delim);        # split from.. values  
  toi=split(to,toa,delim);          # slot to.. values
  for(i=1;i<=fromi || i<=toi;i++) {      # for each value
    search_from=1;              # to avoid recursive replacement, set position for index() function
    do {
      pos=index(substr(str,search_from),froma[i]);    # get next occurence
      if (pos>0) {                    # if found
        end=pos+length(froma[i])+search_from-1;      # get position of replacement end
        str=substr(str,1,pos+search_from-2) & toa[i] & substr(str,end);   # replace string part before_replacement:replace_to:after_replacement
        search_from=pos+length(toa[i])+search_from-1;  # set next position for index()
      }
    }
    while(pos>0);              # while found to replace
  }
  return E_OK;
}

get_part

##############################################################################################
# FUNCTION:get_part
# PURPOSE: Return one of values in delimited list
# INPUT PARAMS: mandatory str (delimited list), optional from, to, delimiter
# if from==-1, last value is retrieved, if from>0 and to==-1, values from 'from' to last are retrieved
# RETURN VALUE: string
##############################################################################################
public function get_part(in str, in from,in to, in delim) {
  auto stri, stra[],i,value;
  if (delim=="") delim=DELIMITER;      # set delimiter to default
  if (from=="") from=1;          # if not passed, set from to default
  if (to=="") to=from;          # if to not passed, set to one value
  stri=split(str,stra,delim);        # split values
  if(from>0 && to>0) {          # if range is specified
    for (i=from;i<=to && i<=stri;i++) value=value&stra[i]&delim;  # get requested part
    value=substr(value,1,length(value)-1);
  }
  if(from==-1 && to==-1) value=stra[stri];  # get last value specified, get it
  if(from>0 && to==-1) {          # if range from from to end is specified
    for (i=from;i<=stri;i++) value=value&stra[i]&delim; # get from 'from' to last value
    value=substr(value,1,length(value)-1);
  }
  return   value;         # return delimited values, remove last delimiter
}  

win_close_dialogs

##############################################################################################
# FUNCTION:win_close_dialogs
# PURPOSE: Check for unexpected browser and Win dialogs, ad close it
# INPUT PARAMS: none
# RETURN VALUE: E_OK or counter of handled windows, or E_NOT_RESPONDING
##############################################################################################
public function win_close_dialogs() {
  auto start_time, is_window, awin, no, handled, label;
  awin=get_mainwin_desc("ABC");  # get winow description from expected title
  handled=0;        # counter of times for handled windows
  no++;  
  start_time=get_time();  # mark current time for timeout controlling
  do {          # do at least once   
    is_window=FALSE;  # reset handled windows
    if(get_time()>(start_time+timeout_time)) {  # break and log on timeout
      my_tl_step("win_close_dialogs", 2, "Timeout reached to kill unexpected dialog window. Exception handler is invoked.");
      exception_handler(E_ERROR, "win_close_dialogs"); # resume as exception
    }
    ####### handle html_frame(s) before, which need specific actions, because after simple closing it can appear again ##
    if(win_exists("Save Confirmation")==E_OK) {  # class: window, MSW_class: html_frame, html_name: "Save confirmation"
      is_window=TRUE;
      set_window("Save Confirmation");
      if(obj_exists("bOK")==E_OK) button_press("bOK");
      if(obj_exists("bYes")==E_OK) button_press("bYes");
      if(obj_exists("bNo")==E_OK) button_press("bNo");
      if(obj_exists("bCancel")==E_OK) button_press("bCancel");
      my_tl_step("win_close_dialogs",E_WARNING,"Unexpected 'Save Confirmation' window was handled");
      handled++;
    }
    # don't need handling of search (e.g. wPopupDialog, wSearchResults) and similar html_frame windows,
    # because they will be simply closed by browser_main_window

    ###### handle javascript windows ##
    if(win_exists("MicrosoftInternetExplorer")==E_OK) { # label: "!Microsoft Internet Explorer.*"
      is_window=TRUE;
      set_window("MicrosoftInternetExplorer");
      if(obj_exists("bOK")==E_OK) button_press("bOK");
      if(obj_exists("bDontSend")==E_OK) button_press("bDontSend");
      if(win_exists("MicrosoftInternetExplorer")==E_OK) win_close("MicrosoftInternetExplorer"); # if window still exist, try to simply close it
      my_tl_step("win_close_dialogs",E_WARNING,"Unexpected 'MicrosoftInternetExplorer' window was handled");
      handled++;
    }  

    ####### now try to close other unexpected windows which can recognized by specific pattern ##      
    if(win_exists("Messenger Service")==E_OK) { # browser dialogs (security, proxy server etc. warnings), class: window, label: "Messenger Service",  MSW_class: "#32770"
      is_window=TRUE;
      set_window("Messenger Service");
      button_press("OK");
      if(win_exists("Messenger Service")==E_OK) win_close("Messenger Service"); # if window still exist, try to simply close it
      my_tl_step("win_close_dialogs",E_WARNING,"Unexpected 'Messenger Service' window was handled");
      handled++;
    }            
    if(win_exists("wLogon_2000")==E_OK) {    # class: window, label: "Enter Network Password"
      is_window=TRUE;
      set_window("wLogon_2000");
      if(obj_exists("OK")==E_OK) button_press("OK");
      my_tl_step("win_close_dialogs",E_WARNING,"Unexpected 'wLogon_2000' window was handled");
      handled++;
    }
    if(win_exists("wLogon_XP")==E_OK) {      # class: window, label: "!Connect to.*"
      is_window=TRUE;
      set_window("wLogon_XP");
      if(obj_exists("OK")==E_OK) button_press("OK");
      my_tl_step("win_close_dialogs",E_WARNING,"Unexpected 'wLogon_XP' window was handled");
      handled++;
    }
    if(win_exists("Unexpected Dialog")==E_OK) { # dialog windows:  class: window, MSW_class: "Internet Explorer_TridentDlgFrame"
      is_window=TRUE;
      win_close("Unexpected Dialog");

      my_tl_step("win_close_dialogs",E_WARNING,"Unexpected 'Unexpected Dialog' window was handled");
      handled++;
    }
   
    ###### now try to close unnecessary browser_main_window(s)  ##
    # class: window, MSW_class: browser_main_window, NSTitle: "Browser Main Window", location: no  
    if (win_exists("{class: window, MSW_class: browser_main_window, NSTitle: "Browser Main Window", location: "no"}")==E_OK) {
      win_get_info("{class: window, MSW_class: browser_main_window, NSTitle: "Browser Main Window", location: "no"}","label",label);  # get its label
      if(index(label,"Index Page")!=1) {  # and don't close Index window
        is_window=TRUE;
        win_close("{class: window, MSW_class: browser_main_window, NSTitle: "Browser Main Window", location: "no"}");
        my_tl_step("win_close_dialogs",E_WARNING,"Unexpected 'browser_main_window:"no"' window was handled");
        handled++;
      }
    }
    if(is_window==TRUE) wait(wait_time);  # if some window was closed, wait
  } while (is_window==TRUE);           # continue while any window was handled
  if (handled==0) return E_OK;
  else return handled;
}

chr

##############################################################################################
# FUNCTION:chr
# PURPOSE: Returns the character representation of the ASCII code
# INPUT PARAMS: ASCIICode - An integer value
# RETURN VALUE: Character
##############################################################################################
function chr (in ASCIICode) {
  return(sprintf("%c", ASCIICode));
}

replace_ASCII

##############################################################################################
# FUNCTION:replace_ASCII
# PURPOSE: replace one character in string to other, given by ASCII code
# usually spaces are converted to non-breaking spaces, e.g. replace_ASCII(passed_item_name,32,160);
# INPUT PARAMS: str - given str, from - code of old character, to - code of new  
# RETURN VALUE: string with replaced characters
##############################################################################################
public function replace_ASCII(in str, in from, in to) {
  auto tmp,i;
  for(i=1;i<=length(str);i++) {
    if(substr(str,i,1)==chr(from)) tmp=tmp&chr(to);
    else tmp=tmp&substr(str,i,1);
  }
  return tmp;
}

list_get_copy

##############################################################################################
# FUNCTION:list_get_copy
# PURPOSE: create copy of GUI list in WR array to improve checking performance
# INPUT PARAMS: passed_list_name from which copy is created, array[] where list values are stored (array is 0 based!)
# RETURN VALUE: count of values in list
##############################################################################################
public function list_get_copy(in passed_list_name,inout array[]) {
  auto i,ItemCount,ItemContents;
  for (i in array) delete array[i];                  # clear passed array
  list_get_info(passed_list_name,"count",ItemCount);          # count of Items in List to ItemCount
  for (i=0; i<ItemCount; i++) {
    list_get_item(passed_list_name, i, ItemContents);         # Gets list item value (one by one)
    array[i]=ItemContents;
  }
  return i-1;                              # return count
}

arr_find_text

##############################################################################################
# FUNCTION:arr_find_text
# PURPOSE: chech if passed value exists in array or not
# INPUT PARAMS: mandatory: array[], passed_item_name, optional: row, column - place where value is found (address is 0 based!)   
# RETURN VALUE: E_OK if found, else E_NOT_FOUND
##############################################################################################
public function arr_find_text(inout array[], in passed_item_name, inout row, inout col) {
  auto i;                          # counter
  for (i in array) {                    # for each element in array
    if (array[i]==passed_item_name) {          # if found value
      row=get_part(i, 1, 1,chr(28));          # calculate row and column from i
      col=get_part(i, 2, 2,chr(28));
      return E_OK;                  
    }
  }
  return E_NOT_FOUND;                    # if not found
}

tbl_get_copy

##############################################################################################
# FUNCTION:tbl_get_copy
# PURPOSE: create copy of GUI table in WR array to improve checking performance
# INPUT PARAMS: table_name, array[], row ("" means all rows), column ("" means all columns)
# RETURN VALUE: array (0 based!), count of rows, count of columns; E_OK
##############################################################################################
public function tbl_get_copy(in table_name,inout array[],inout row, inout column) {
  auto row_to, column_to, i, j, value;
  if (row=="") {
    row=1;
    tbl_get_rows_count(table_name,row_to);         # get row count in table
  }
  else row_to=row;
  if (column=="") {
    column=1;
    tbl_get_cols_count(table_name,column_to);       # get column count in table
  }
  else column_to=column;
 
  for (i in array) delete array[i];            # clear passed array  
 
  for (i=0;i<=(row_to-row);i++) {              # get values for each cell in passed row range
    for (j=0;j<=(column_to-column);j++) {        # and column range
      tbl_get_cell_value(table_name,i+row,j+column,value);
      array[i,j]=value;
    }
  }
  row=i;                          # set count of rows in array
  column=j;                        # set count of columns in array
  return E_OK;
}

get_message

##############################################################################################
# FUNCTION:get_message
# PURPOSE: Looks for JavaScript message and returns String it contains
# INPUT PARAMS: strRealMessage - on return will contain Message body of MessageBox
#               [optional] strButton = Button to push ("OK", "Cancel", "Yes", "No", "Abort", "Retry")
#                          If not passed - will click default in this order: OK, Yes, Cancel  
# RETURN VALUE: Success = E_OK, failure = E_NOT_FOUND
#               !!! Do not forget to invoke my_set_window() after usage of this function !!!
##############################################################################################
public function get_message(inout strRealMessage, in strButton) {
  auto strMessageContents, nElementsSplitted, arrSplitMsg[], i;

  if (win_exists("MicrosoftInternetExplorer")==E_OK) {
    my_set_window ("MicrosoftInternetExplorer");
    win_get_text("MicrosoftInternetExplorer",strMessageContents);
    nElementsSplitted = split(strMessageContents, arrSplitMsg, "rn");
    strRealMessage = "";
    for (i=2;i<=nElementsSplitted;i++) {
      if (substr(arrSplitMsg[i],1,2) != "OK" && substr(arrSplitMsg[i],1,5) != "Retry" && substr(arrSplitMsg[i],1,5) != "Abort" && substr(arrSplitMsg[i],1,6) != "Cancel" && substr(arrSplitMsg[i],1,3) != "Yes" && substr(arrSplitMsg[i],1,2) != "No")
        strRealMessage = strRealMessage & arrSplitMsg[i];
      else
        break;
    }
    if (strButton!="") {
      if(obj_exists(strButton) != E_OK)
        button_press (strButton);
      else {
        my_tl_step("Wrong MessageBox button passed", 1, "Message '"strRealMessage"' doesn't contain button '"strButton"'");
        return E_NOT_FOUND;
      }
    }    
    if (strButton == "") {
      if (obj_exists("bOK") == E_OK) button_press ("bOK");
      if (obj_exists("bYes") == E_OK) button_press ("bYes");
      if (obj_exists("bCancel") == E_OK) button_press ("bCancel");
    }
    return E_OK;
  }
  strRealMessage = "Window or object not found";
  return E_NOT_FOUND;
}

get_obj_desc

##########################################################################################
# FUNCTION:get_obj_desc
# PURPOSE: Returns [almost] any objects physical description by it's name
#
# INPUT PARAMS: strObjectName   - [mandatory] logical name of the object (like "personName")
#               nLocation       - location number (if numeruous objects are on page with the same names)
#               object_type     - will return it's type (like "html_combobox")
#               obj_description - will contain object's physical description
#               
# RETURN VALUE: On Success: E_OK + variables will contain values, On failure: E_NOT_FOUND + empty variables
##########################################################################################
public function get_obj_desc(in strObjectName, inout nLocation, out object_type, out obj_description) {
  auto descr_ending, i, current_window, gui_file;

  if (strObjectName == "")
    return E_NOT_FOUND;
 
  #--- First let's try to find object in GUI mapping file
  current_window = GUI_get_window();
  if (current_window != "") {
    if (GUI_map_get_desc(current_window, strObjectName, obj_description, gui_file) == E_OK) {
      GUI_desc_get_attr(obj_description,"MSW_class",object_type);
      GUI_desc_get_attr(obj_description,"location",nLocation);
      return E_OK;
    }
  }

  #--- Not in GUI: Continue to concatenate known pieces
  if (nLocation == "")
    descr_ending = "};";
  else
    descr_ending = ",location: "&nLocation&"};";

  #--- First attempt to find initial name
  obj_$description = "{html_name: "" & strObjectName & """ & descr_ending;;
  if (obj_exists(obj_description)!=E_OK && nLocation=="") {
    #--- Unsuccessfull - just find first object if numeruous on page (location)
    for(i=0;i<50;i++) {
      obj_$description = "{html_name: "" & strObjectName & "",location: "&i&"}";;
      if (obj_exists(obj_description) == E_OK) {
        nLocation = i
        descr_ending = ",location: "&nLocation&"};";
        break;
      }
    }
    if (i>=50) {
      obj_$description = "";;
      return E_NOT_FOUND;
    }
  }
 
  if (obj_exists(obj_description) == E_OK) {
    web_obj_get_info(obj_description, "class", object_type);  # check for name of found object
    switch (object_type) {
    case "html_edit":
      obj_$description = "{class: edit,MSW_class: html_edit,html_name: "" & strObjectName & """ & descr_ending;;
      break;
    case "html_combobox":
      obj_$description = "{class: list,MSW_class: html_combobox,html_name: "" & strObjectName & """ & descr_ending;;
      break;
    case "html_listbox":
      obj_$description = "{class: list,MSW_class: html_listbox,html_name: "" & strObjectName & """ & descr_ending;;
      break;
    case "html_radio_button":
      obj_$description = "{class: radio_button,MSW_class: html_radio_button,html_name: "" & strObjectName & """ & descr_ending;;
      break;
    case "html_push_button":
      obj_$description = "{class: push_button,MSW_class: html_push_button,html_name: "" & strObjectName & """ & descr_ending;;
      break;
    case "html_check_button":
      obj_$description = "{class: check_button,MSW_class: html_check_button,html_name: "" & strObjectName & """ & descr_ending;;
      break;
    case "html_table":
      obj_$description = "{class: object,MSW_class: html_table,html_name: "" & strObjectName & """ & descr_ending;;
      break;
    case "html_text_link":
      obj_$description = "{class: object,MSW_class: html_text_link,html_name: "" & strObjectName & """ & descr_ending;;
      break;
    case "html_rect":
      obj_$description = "{class: object,MSW_class: html_rect,html_name: "" & strObjectName & """ & descr_ending;;
      break;
    default:
      obj_$description = "{MSW_class: "&object_type&",html_name: "" & strObjectName & """ & descr_ending;;
      break;
    }
    return E_OK;
  } else {
    obj_$description = "";;
    return E_NOT_FOUND;
  }
}

navigate(in commands)

##########################################################################################
# FUNCTION:navigate(in commands)
# PURPOSE: Navigates to the necesssary window by clicking on passed elements
# INPUT PARAMS: mandatory: commands - list of delimited elements, which can be "clicked", optional: cwindow - name of current window, de.="ABC",
# nextwindow - name of window, after clicking, def.=cwindow, halt_on_failure - invoke exception_handler() on failure or not, def.=OFF      
# RETURN VALUE: E_OK or E_NOT_RESPONDING
##########################################################################################
public function navigate(in commands, in cwindow, in nextwindow,in halt_on_failure) {
  auto acommand[],i,count,start_time,start_time1,width,height,control_type,ctype_res,is_window,cwin,status,message;
  if (cwindow=="") cwindow="ABC";
  if (nextwindow=="") nextwindow=cwindow;
  if(halt_on_failure=="") halt_on_failure=OFF;      
  count=split(commands,acommand,DELIMITER);
  for (i=1;i<=count;i++) {                # do for each passed command
    start_time=get_time();                # get time for timeout checking
    # don't close unnecesary windows before any activity. It can cause problems after search dialogs
    do {                        # try to find necessary object
      if(get_time()>(start_time+timeout_time)) {
        my_tl_step("navigate", E_WARNING, "Timeout reached to get '"acommand[i]"' button/link.");
        if(halt_on_failure==ON) {          # if should handle as exception
          my_tl_step("navigate", E_WARNING, "Exception handler is invoked");
          exception_handler(E_ERROR, "navigate"); # resume as exception
        }
        else return E_NOT_RESPONDING;        # or simple return error
      }
      my_set_window(cwindow,timeout_time);      # set window to 1st window
      web_sync(timeout_time);
    } while (obj_exists(acommand[i])!=E_OK);      # while necessary object appears
    start_time=get_time();                
                              ### Try navigate here ###
    do {      # try while "Current request is being processed.  Please wait until done and try again" disappears
      my_set_window(cwindow,timeout_time);    # set focus to 1st window again (is lost after checking status and dialogs)
      is_window=FALSE;                # reset handled windows
      if(get_time()>(start_time+timeout_time)) {
        my_tl_step("navigate", E_WARNING, "Timeout reached to click on '"acommand[i]"' button/link");
        if(halt_on_failure==ON) {          # if should handle as exception
          my_tl_step("navigate", E_WARNING, "Exception handler is invoked");
          exception_handler(E_ERROR, "navigate"); # resume as exception
        }
        else return E_NOT_RESPONDING;        # or simple return error
      }

      obj_get_info(acommand[i],"Width",width);    # get center of the current object
      obj_get_info(acommand[i],"Height",height);
      width=int(width/2);
      height=int(height/2);  

      ctype_res = GUI_buf_get_desc_attr(gui_home, "ABC", acommand[i], "MSW_class", control_type);              
      if (ctype_res == E_OK && control_type == "html_text_link")
        web_link_click(acommand[i]);         # click on the current link
      else                       # click on current link/button
        web_event(acommand[i], "click", width, height); # web_event is more comprehensive than special "click.." functions
     
      if(get_message(message)==E_OK) {        # handle JSript messages before ("Current request is being processed.." and local validation messages)
        my_tl_step("navigate", E_WARNING, "'"message"' message appeared and was closed after clicking '"acommand[i]"'");
        wait(wait_time);
        is_window=TRUE;                  # register handling of unexpected window
      }
      if (cwindow=="ABC" && nextwindow == "ABC") {    # *** if navigation is in ABC window ***
        if(win_close_dialogs()>0) {            # close unnecesary dialogs
          is_window=TRUE;                # register handling of unexpected window
          my_set_window("ABC");            # ang go back to sarting window        
        }
        cwin=get_mainwin_desc("ABC");  # get winow description from expected title
        my_set_window(cwin);                # activate it,  
        start_time1=get_time();                # initialize start time for 'Done' seeking loop
        do {    
          if(get_time()>(start_time1+timeout_time)) {
            my_tl_step("navigate", E_WARNING, "Timeout reached to get status bar 'Done'");
            break;
          }
          statusbar_get_text ("{class: statusbar}",0,status);   # and check for "Done " in status bar
        } while (index(status,"Done")==0);
      }    
    } while (is_window==TRUE);          # try while unexpected windows apear
  }
  web_sync(timeout_time);              # check, that previous windows is ready
  my_set_window(nextwindow,timeout_time);      # check finally for 2nd window
  web_sync(timeout_time);              # wait for 2nd windows completition
  wait(1);                    # wait 1 sec after "window is ready"
  web_refresh(nextwindow);            # force WR to reload content (DHTML and other cases which WR can not catch smoothly)
  return E_OK;
}

check_navigate

##########################################################################################
# FUNCTION:check_navigate
# PURPOSE: Check and log more info and errors than simple navigate() by clicking on butoons and links
# INPUT PARAMS: mandatory: commands  - list of delimited elements, which can be "clicked", global_status - total statusofeach subsequental navigation step
# RETURN VALUE: E_OK, inout status is changed to warning or error, if werent error alredy
##########################################################################################
public function check_navigate(in commands, inout global_status) {
  auto status,error_status,status_string,acommand[],count,i;
  count=split(commands,acommand,DELIMITER);
  for (i=1;i<=count;i++) {
    status=navigate(acommand[i]);        # navigate and get stratus for current step
    error_status=check_error();          # check for error message
    if(status>=E_OK)              # if total status is not error already
      if(error_status!=E_OK) status=error_status;  # set status to error status, if error occured

    if(status==E_OK) status_string="SUCCESSFULLY";  # prepare status string for step
    if(status>E_OK) status_string="with WARNING";
    if(status<E_OK) status_string="with ERROR";

    my_tl_step("check_navigate",status,"Click on '"acommand[i]"' completed "status_string);
    if(global_status>=E_OK)                 
      if(status!=E_OK) global_status=status;    # change status to eror or warning, from current navigation step
  }
  return E_OK;
}

to_array

##########################################################################################
# FUNCTION:to_array
# PURPOSE: returns arry, created from delimited lists
# INPUT PARAMS: inout arr, delimited string of fields, delimited string of values, delimiter, clear values "Yes/No"
# RETURN VALUE: no
##########################################################################################
public function to_array(inout arr[], in fields, in values, in delim, in clear) {
  auto i, fieldsi, valuesi, fieldsa[], valuesa[];
  if (clear=="") clear="Yes";
  if (delim=="") delim=DELIMITER;
  if(clear=="Yes") {
    for (i in arr) delete arr[i];
  }
  split(fields,fieldsa,delim);        # split values
  split(values,valuesa,delim);        
  for (i in fieldsa)
    arr[fieldsa[i]]=valuesa[i];   
}

get_sys_var

##########################################################################################
# FUNCTION:get_sys_var
# PURPOSE: get system information and initialize appropriate variables
# INPUT PARAMS: no
# RETURN VALUE: changes global variables OS, OS_ver, OS_lang (Operating System name, version and language)
##########################################################################################
public function get_sys_var() {
  GUI_get_name(OS, OS_ver);
  OS_lang = get_lang();
}

check_values

##########################################################################################
# FUNCTION:check_values
# PURPOSE: compare control (edit/list/combo box) and passed value  
# INPUT PARAMS: control - logical name or full description of control, value - value which should be checked
# RETURN VALUE: E_OK if values are equal, control's value if they differs, or E_ERROR, if control was not found
##########################################################################################
public function check_values(in control, in value) {
  extern gui_home;
  auto depth,testname, testnamea[],i,j,start,curr_win,desc,msw_class,retvalue,retno;
  testname=get_test_name();              # get current functional test
  curr_win = GUI_get_window();            # get current window
  if (obj_exists(control)!=E_OK) {
    my_tl_step(testname": check_values",E_ERROR,"Control '"curr_win":"control"' was not found");
    return E_ERROR;                  # return error if control was not found
  }
  if(higlith_objects==ON) obj_highlight(control,1);    # highlight object, if required
  start=index(control,"MSW_class: ");          # get control's class from full description
  if(start>0) {
    msw_class=substr(control,start+11);        # get msw_class start
    msw_class=substr(msw_class,1,index(msw_class,",")-1); # cut its end
    replace (msw_class,""","");          # and remove quotation marks, if exist
  }
  else {                        # or from logical name
    GUI_map_get_desc(curr_win, control, desc, gui_home);
    GUI_desc_get_attr(desc, "MSW_class", msw_class);
  }
  switch(msw_class) {
    case "html_edit":                # get data from control
      edit_get_text(control,retvalue);
      break;
    case "html_combobox":              
      list_get_info(control,"value",retvalue);  # this works for disabled combo boxes also
      break;
    case "html_listbox":            
      list_get_selected(control,retvalue,retno);  
      break;
    case "html_radio_button":    
      button_get_info (control, "enabled", retvalue);  
      break;
    case "html_check_button":    
      button_get_state (control, retvalue);  
      break;      
    default:
      my_tl_step(testname": check_values",E_ERROR,"No appropriate type for control '"curr_win":"control"' was found");
      return E_ERROR;                # return error if control was not found
  }
  if(retvalue!=value)                  # compare values, log warning, if differ
    my_tl_step(testname": check_values",E_WARNING,"Value for control '"curr_win":"control"' is changed. Typed value:'"value"', stored:'"retvalue"'");
  else retvalue=E_OK;                 # return E_OK if walues are equal

  return retvalue;

check_from_table

##########################################################################################
# FUNCTION:check_from_table
# PURPOSE: set checkbox ON/OFF in table against required value  
# INPUT PARAMS: tablename, itemname which should be find, optional column, where to find value, optional on_off=ON/OFF state for checkbox, ON/OFF exact_match for search
# RETURN VALUE: selitem - value for the selected checkbox
##########################################################################################
public function check_from_table(in tablename, in itemname, in column, in on_off, in exact_match) {
  auto row, check_button, selitem, tcolumn;
  if (on_off=="") on_off=ON;
  if (exact_match=="") exact_match=ON;
  tcolumn=column;
  if (tbl_find_text(tablename, itemname, row, tcolumn,"",exact_match)!=E_OK) {
    tbl_get_rows_count(tablename,row);
    tcolumn=column;
  }
  tbl_get_cell_value(tablename, row, tcolumn, selitem);
  if (selitem!=itemname)
    my_tl_step("check_from_table",E_WARNING,"'"itemname"' was not found. In place the '"selitem"' is checked");
  web_obj_get_child_item(tablename, row, 1, "html_check_button", 0, check_button);
  button_set(check_button, on_off);
  return selitem;
}

analog_prepare_lastrow

##########################################################################################
# FUNCTION:analog_prepare_lastrow
# PURPOSE: prepare fieldinfo[] array for using with analog_edit_set(); calculates x,y coords for all fields IN THE LAST row of the table    
# INPUT PARAMS: tablename - where all fields are placed, fieldinfo[] -2D array with elements, each element should have "rowfactor" and "colshift" keys,opt: skip_rows
# RETURN VALUE: E_OK
##########################################################################################
public function analog_prepare_lastrow(in tablename, inout fieldinfo[], in skip_rows) {
  auto rows_count,i,fieldname,rowfactor,colshift,lastel,location;
  if (skip_rows == "") skip_rows = 0;
  tbl_get_rows_count(tablename, rows_count);
  rows_count=rows_count-skip_rows;             # discount skipped rows
  analog_prepare_row(tablename, fieldinfo, rows_count);  # prepare elements
  return E_OK;
}

analog_prepare_row

##########################################################################################
# FUNCTION:analog_prepare_row
# PURPOSE: prepare x and y coords for elements which are in passed row of the table. Elements are calculated using GUI file and by their location    
# INPUT PARAMS: req: tablename, fieldinfo[] -2D array with elements, each element should have "rowfactor" and "colshift" keys , opt: row_no
# RETURN VALUE: E_OK
##########################################################################################
public function analog_prepare_row(in tablename, inout fieldinfo[], in row_no) {
  auto fieldlist[],location,i,fieldname,rowfactor,colshift;
  if (row_no == "") tbl_get_rows_count(tablename, row_no);
  row_no--;            # discount number of rows, because number of elelemts is zero based
  for (i in fieldinfo) {      # create temporary list of fields
    fieldname=substr(i,1,index(i,chr(28))-1); # get name of the first element as fieldname
    fieldlist[fieldname];    # simply overwrite not unique elements
  }
  for (fieldname in fieldlist) {
    rowfactor = fieldinfo[fieldname, "rowfactor"];
    colshift  = fieldinfo[fieldname, "colshift"];
    location=rowfactor*row_no+colshift;
    analog_set_coords(fieldname, location, fieldinfo);
  }
  return E_OK;
}

analog_prepare_elements

##########################################################################################
# FUNCTION:analog_prepare_elements
# PURPOSE: set x and y coords for elements in the passed array. Can use either logical name, or physical description of the object
# INPUT PARAMS: fieldinfo[] -2D array with elements, element can has optional "location" key, element should be from GUI file or physical location
# RETURN VALUE: E_OK, array keys [fieldname][x] and [fieldname][y] [fieldname][msw_class] are added in the fieldinfo[]  
##########################################################################################
public function analog_prepare_elements(inout fieldinfo[]) {
  auto location,fieldlist[], fieldname, i;
  for (i in fieldinfo) {      # create temporary list of fields
    fieldname=substr(i,1,index(i,chr(28))-1); # get name of the first element as fieldname
    fieldlist[fieldname];    # simply overwrite not unique elements
  }  
  for (fieldname in fieldlist) {
    if(fieldinfo[fieldname, "location"]!="") location=fieldinfo[fieldname, "location"];  # get location, if is set in fieldinfo[]  
    else location=0;
    analog_set_coords(fieldname, location, fieldinfo); # get coordinates and store in passed array
  }  
  return E_OK;
}

analog_prepare_row_elements

##########################################################################################
# FUNCTION:analog_prepare_row_elements
# PURPOSE: set set x and y coords for several elements in tables's last (or other, if passed) row. Function doesn't use .gui file     
# INPUT PARAMS:  tablename, fieldinfo[] - 2D array with elements and their properties, element should contain "column" attribute for each element
# RETURN VALUE: E_OK, array keys [fieldname][x] and [fieldname][y] [fieldname][msw_class] are added in the fieldinfo[]  
##########################################################################################
public function analog_prepare_row_elements(in tablename, inout fieldinfo[], in row) {
  auto fieldlist[],i,fieldname,col,msw_class,control;
  if (obj_exists(tablename)!=E_OK) {
    my_tl_step("analog_prepare_row_elements",E_ERROR,"Table '"tablename"' doesn't exist");
    return E_ERROR;
  }
  if (row == "") tbl_get_rows_count(tablename, row);
  for (i in fieldinfo) {      # create temporary list of fields
    fieldname=substr(i,1,index(i,chr(28))-1); # get name of the first element as fieldname
    fieldlist[fieldname];    # simply overwrite not unique elements
  }  
 
  for (fieldname in fieldlist) {          # for all elements in fieldinfo
    col=fieldinfo[fieldname, "column"];      # get number of element's col in table
    if(fieldinfo[fieldname, "msw_class"]!="") {
      msw_class=fieldinfo[fieldname, "msw_class"];
      web_obj_get_child_item(tablename, "#"row, "#"col, msw_class, 0, control);  # try to get from html_edit
    }
    else {
      web_obj_get_child_item(tablename, "#"row, "#"col, "html_edit", 0, control); # try to get several types,html_edit,
      if (control == "")  web_obj_get_child_item(tablename, "#"row, "#"col, "html_combobox", 0, control);  # html_combobox
      if (control == "")  web_obj_get_child_item(tablename, "#"row, "#"col, "html_listbox", 0, control);    # html_listbox
    }
    if (control == "") {
      my_tl_step("analog_prepare_row_elements",E_WARNING,"Couldn't find any element:'"fieldname"' in table:'"tablename"'("row","col").");
      continue;
    }
    analog_set_coords(control,0,fieldinfo,fieldname);  # get and store corrdinates in the fieldinfo[] array
  }
  return E_OK;
}

analog_set_coords

##########################################################################################
# FUNCTION:analog_set_coords
# PURPOSE: set x and y coords for ONE mentioned control in passed array. Can use either logical name, or physical description of the object   
# INPUT PARAMS: control - logical name (location), or physical description, fieldinfo - 2D array of the element's properties in form [control][property]=value
# RETURN VALUE: E_OK, array keys [control][x] and [control][y] [control][msw_class] are added in passed array  
##########################################################################################
public function analog_set_coords(in control, in location, inout fieldinfo[], in logical_name) {
  auto i,x0,x,y0,y,width,height,curr_win,start,msw_class,desc,item_no,item_val,item_count;

  if (logical_name=="") logical_name=control;    # use element physical description if logical name is not passed

  curr_win = GUI_get_window();  
  win_get_info(curr_win,"X",x0);            # get coordinates of the window
  win_get_info(curr_win,"Y",y0);

  start=index(control,"MSW_class: ");          # get control's class from full description
  if(start>0) {
    msw_class=substr(control,start+11);            # get line form start
    msw_class=substr(msw_class,1,index(msw_class,",")-1);   # cat end finish
    replace (msw_class,""","");              # and remove "s
    if(location>0) my_tl_step("analog_set_coords",E_WARNING,"Location ("location") for the the element with physical description ("control") is passed, which is not supported");
  }
  else {                        # or from logical name
    GUI_map_get_desc(curr_win, control, desc, gui_home);
    GUI_desc_get_attr(desc, "MSW_class", msw_class);
    if (location!="")
      GUI_buf_set_desc_attr(gui_home, "ABC", control, "location", location); # set location attribute, if it is passed
  }
 
  obj_get_info(control,"X",x);      # get coordinates and size of the GUI control  
  obj_get_info(control,"Width",width);
  obj_get_info(control,"Height",height);
  obj_get_info(control,"Y",y);

  x=x+int(width/2)+x0;          # calculate coordinates of the control center
  y=y+int(height/2)+y0;
  fieldinfo[logical_name,"x"] = x;          # and store in array
  fieldinfo[logical_name,"y"] = y;
  fieldinfo[logical_name, "msw_class"] = msw_class;   # set msw_class info in the array

  if(msw_class=="html_combobox" || msw_class=="html_listbox") {  # if control is listbox, prepare value list for it ir array            
    item_no = 0;
    item_count = 0;
    while (list_get_item(control, item_no, item_val) == E_OK) {
      item_count++;
      fieldinfo[logical_name, "list_item" item_no] = item_val;
      item_no++;
    }
    fieldinfo[logical_name, "list_item_count"] = item_count;  
  }
  if(higlith_objects==ON) obj_highlight(control,1);
  return E_OK;
}

analog_click_on_text

##########################################################################################
# FUNCTION:analog_click_on_text
# PURPOSE: find text (i.e. link) in frame and click on it in analog mode     
# INPUT PARAMS: req: text which should be found, opt: frame (ABC), location (1-based), shitx, shifty
# RETURN VALUE: E_OK or E_NOT_FOUND
##########################################################################################
public function analog_click_on_text(in text, in frame, in location,in shiftx, in shifty) {
  auto x0,y0,coord[],res;
  if(frame=="") frame="ABC";
  if (shiftx=="") shiftx=0;
  if (shifty=="") shifty=0;
  if (location=="") location=1;          # location is 1 based
  win_get_info(frame,"X",x0);            # get coordinates of the window
  win_get_info(frame,"Y",y0);
  res = web_find_text (frame,text,coord,"","",location,TRUE); # get coordinates of link
  if(res==E_OK) {                  # if was found
    move_locator_abs(x0+int(coord[0]+(coord[2]-coord[0])/2)+shiftx,y0+int(coord[1]+(coord[3]-coord[1])/2)+shifty);
    mtype("<T100><kLeft>-<T100><kLeft>+");    # and click on it in analog mode
    wait(1);
    web_sync(10);
  }
  return res;
}

analog_type

##########################################################################################
# FUNCTION:analog_type
# PURPOSE: click (and type something, if necessary) on some grapgical element in analog mode, use this function if analog_edit_set() is too complex     
# INPUT PARAMS: required: element_name - logical name of the GUI element, fieldinfo[] - array of properties, optional: text which should be typed
# RETURN VALUE: E_OK  
##########################################################################################
public function analog_type(in element_name, in text, inout fieldinfo[]) {
  move_locator_abs(fieldinfo[element_name,"x"],fieldinfo[element_name,"y"]);
  mtype ("<T100><kLeft>-<T100><kLeft>+");
  if(text!="") type(text);
  return E_OK;
}

analog_navigate

##########################################################################################
# FUNCTION:analog_navigate
# PURPOSE: navigate to necessary screen using analog mode     
# INPUT PARAMS: commands - delimited list of the GUI elements, fieldinfo[] - array of the element properties (x an y coords)
# RETURN VALUE: E_OK  
##########################################################################################
public function analog_navigate(in commands, inout fieldinfo[]) {
  auto acommand[],i,count;
  count=split(commands,acommand,DELIMITER);
  for (i=1;i<=count;i++) {                # do for each passed command
    analog_type(acommand[i], "", fieldinfo); # click on the current link
    wait(3*wait_time);
  }
  return E_OK;
}

analog_edit_set

##########################################################################################
# FUNCTION:analog_edit_set
# PURPOSE: write the given text into the given textbox using analog functions     
# INPUT PARAMS: required: fieldname, text, field1info, optional: press_enter(ON), overwrite(OFF), translate_text(ON)
# RETURN VALUE: E_OK or E_ERROR
##########################################################################################
public function analog_edit_set(in fieldname, in text, inout fieldinfo[], in press_enter,in overwrite, in translate_text) {
  auto text1, item_count, item_no, i, list_itm_txt, command;
  text1 = text;
  if(press_enter== "") press_enter = ON;
  if(overwrite== "") overwrite = OFF;
  if(translate_text=="") translate_text = ON;

  if (fieldinfo[fieldname, "msw_class"] == "") {        # if elements isn't prepared, exit with warning
    my_tl_step("analog_edit_set",E_ERROR,"'msw_class' key was not found for fieldinfo["fieldname"]");
    return E_ERROR;
  }

  if (fieldinfo[fieldname, "msw_class"] != "html_edit")
    my_tl_step("analog_edit_set",E_WARNING,"'msw_class' key for fieldinfo["fieldname"] is not 'html_edit'. Use analog_select_combo() or analog_type() instead.");

# delete following 5 lines when migration of analog functions will be completed.    
  if (fieldinfo[fieldname, "msw_class"] == "html_combobox" || fieldinfo[fieldname, "msw_class"] == "html_listbox") {
#    my_tl_step("analog_edit_set",E_WARNING,"Wraped analog_select_combo() is invoked.");
    analog_select_combo(fieldname, text, fieldinfo);
    return E_WARNING;
  }

  if(translate_text==ON) replace(text1, "\,",-,+,>,<", "\\,\",\-,\+,\>,\<", ",");
  move_locator_abs(fieldinfo[fieldname, "x"], fieldinfo[fieldname, "y"]);
  mtype ("<T100><kLeft>-<T100><kLeft>+");
  if(overwrite) type("<T100><kCtrl_L-a><T100><kDel_E>");  #double click doesn't work for several words (number 12.12 also is separated as two words)
  type(text1);
  if (press_enter) type("<kReturn>");    # add Enter, if necessary
  return E_OK;
}

analog_select_combo

##########################################################################################
# FUNCTION:analog_select_combo
# PURPOSE: write the given text into the given field (textbox or combobox) using analogous functions     
# INPUT PARAMS: required: fieldname, text, field1info, optional: press_enter, exact_match, overwrite, shift, translate_text (ON/OFF)
# RETURN VALUE: selected value or E_ERROR
##########################################################################################
public function analog_select_combo(in fieldname, in text, inout fieldinfo[], in exact_match, in shift) {
  auto item_count, item_no, i, list_itm_txt, command;
  if(exact_match=="") exact_match = OFF;

  if (fieldinfo[fieldname, "msw_class"] == "") {        # if elements isn't prepared, exit with warning
    my_tl_step("analog_select_combo",E_ERROR,"'msw_class' key was not found for fieldinfo["fieldname"]");
    return E_ERROR;
  }
  if (fieldinfo[fieldname, "msw_class"] != "html_combobox" && fieldinfo[fieldname, "msw_class"] != "html_listbox") {
    my_tl_step("analog_select_combo",E_ERROR,"'msw_class' key for fieldinfo["fieldname"] is not either 'html_combobox' nor 'html_listbox'");
    return E_ERROR;
  }
  move_locator_abs(fieldinfo[fieldname, "x"], fieldinfo[fieldname, "y"]);
  mtype ("<T100><kLeft>-<T100><kLeft>+");

  item_count = fieldinfo[fieldname, "list_item_count"];
  item_no = -1;
  for (i=0; i<item_count; i++) {
    list_itm_txt = fieldinfo[fieldname, "list_item"i];
    if (list_itm_txt==text || (exact_match==OFF && (index(list_itm_txt,text)>0) || text=="")) {
      if(exact_match==OFF && text!="") {              # for partial match of non empty string,
        while (index(fieldinfo[fieldname, "list_item"i],text)>0) i++;
        i--;
        list_itm_txt = fieldinfo[fieldname, "list_item"i];     # get the last of appropriate records      }
      }
      item_no = i;
      break;
    }
  }
  if (item_no < 0 && exact_match==OFF && text!=""){              # if passed text is not found
    list_itm_txt=fieldinfo[fieldname, "list_item"1];
    my_tl_step("analog_select_combo", E_WARNING, "Value '"text"' cannot be found in the listbox '"fieldname"'. 2nd record '"list_itm_txt"' is selected");
    item_no=1;
  }
  if(shift!="" && shift!=0) {
    if(shift==-1) item_no=item_count;
    else item_no=item_no+int(shift%item_count);
    if (item_no==0) item_no=1;                        # don't allow selection of 0. record if no-zero shift is passed
    my_tl_step("analog_select_combo", E_OK, "'"item_no"' record '"fieldinfo[fieldname, "list_item"item_no]"' in listbox '"fieldname"' is selected");
  }
  type("<kHome_E>");              # due to default value, selection can be not at the top row
  for (i=0; i<item_no; i++) command=command&"<kDown_E>";
  command=command&"<kReturn>";
  type(command);
  return fieldinfo[fieldname, "list_item"item_no];
}

tbl_get_row_with_values

##########################################################################################
# FUNCTION:tbl_get_row_with_values
# PURPOSE: find row with passed values in columns
# INPUT PARAMS: req: table, delimited string of values and columns, opt: exact_match (ON/OFF), delim  
# RETURN VALUE: row or E_NOT_FOUND
##########################################################################################
public function tbl_get_row_with_values(in table, in values, in columns,in exact_match, in delim) {
  static valuesa[];
  static columnsa[];
  auto rows,row,i,j,count,row_prev;
  if (exact_match!=ON) exact_match=OFF;            # by default search for similar match
  if (delim=="") delim=DELIMITER;
 
  count=split(values,valuesa,delim);
  split(columns,columnsa,delim);
  tbl_get_rows_count(table,rows);
  row=1;
  i=1;
  while(i<=count) {                      # searh for all passed values
    row_prev=row;                      # remember row for which some value was found
    tbl_find_text(table, valuesa[i], row, columnsa[i], row, exact_match); # search next value
    if(row=="") return E_NOT_FOUND;              # if one value was not found, exit (don't need to check more)
    else {
      if(row_prev==row) i++;                # if one value was found, check if next value matches the same row
      else i=1;                      # else start finding the first value again
    }
  }
  return row;
}

tbl_check_row_with_values

##########################################################################################
# FUNCTION:tbl_check_row_with_values
# PURPOSE: check that table has row with required values
# INPUT PARAMS: req: table, delimited string of values and columns, opt: exact_match (ON/OFF)
# RETURN VALUE: E_OK or E_ERROR;
##########################################################################################
public function tbl_check_row_with_values(in table, in values, in columns,in exact_match) {
  auto depth,i,j,testname,row,testnamea[];
  if(exact_match=="") exact_match=OFF;
  testname=get_test_name();                    # get current functional test
  row=tbl_get_row_with_values(table,values,columns,exact_match);   # find row with values
  if(row>0)                            # and log
    my_tl_step(testname, E_OK, "The newly added record '"values"' was found in row:'"row"'");
  else {
    my_tl_step(testname, E_ERROR, "The newly added record '"values"' was not found");
    return E_ERROR;
  }
  return E_OK;
}

analog_scroll_obj

##########################################################################################
# FUNCTION:analog_scroll_obj
# PURPOSE: scroll content of the object in necessary direction
# INPUT PARAMS: theobject - object to scroll, opt: where (right/down), to (down/up/right/left), shift (10)
# RETURN VALUE: E_OK
##########################################################################################
public function analog_scroll_obj(in theobject, in where, in to, in shift) {
  auto x0,y0,x,y,w,h,xstart,xend,ystart,yend;
  if(where=="") where="right";
  if(to=="") to="down";
  if(shift=="") shift=10;

  my_set_window("ABC");
  win_get_info("ABC","X",x0);      # get coordinates of the window
  win_get_info("ABC","Y",y0);
 
  obj_get_info (theobject,"X",x);    # get coordinates of the object
  obj_get_info (theobject,"Y",y);
  obj_get_info (theobject,"Width",w);
  obj_get_info (theobject,"Height",h);

  x=x+x0;                # get starting coordinates of the object
  y=y+y0;  

  if(where=="right") {
    xstart=x+w-shift;
    xend=xstart;
    ystart=y+int(h/2);
    if(to=="up") yend=y;
    if(to=="down") yend=y+h;
  }
  if(where=="down") {
    ystart=y+h-shift;
    yend=ystart;
    xstart=x+int(w/2);
    if(to=="left") xend=x;
    if(to=="right") xend=x+w;
  }

  move_locator_abs(xstart, ystart);
  mtype ("<T10><kLeft>-<T200><kLeft>+");    # click on scrollbar center, to get slider there
  mtype ("<T10><kLeft>-");          # move slider to the necessary direction
  move_locator_abs(xend, yend);
  mtype ("<T10><kLeft>+");
  wait(1);                  # wait for screen to be ready
  return E_OK;
}

need_check

##########################################################################################
# FUNCTION:need_check
# PURPOSE: return value of parama["NeedCheck"], in case if it is empty, return  default: NEED_CHECK   
# INPUT PARAMS: no
# RETURN VALUE: "Yes"/"No"
##########################################################################################
public function need_check() {
  switch(parama["NeedCheck"]) {
    case "Yes": return "Yes";
    case "No": return "No";
    default: return need_check;
  }  
}

fill_empty

##########################################################################################
# FUNCTION:fill_empty
# PURPOSE: return value of parama["FillEmpty"], in case if it is empty, return  default: FILL_EMPTY   
# INPUT PARAMS: no
# RETURN VALUE: "Yes"/"No"
##########################################################################################
public function fill_empty() {
  switch(parama["FillEmpty"]) {
    case "Yes": return "Yes";
    case "No": return "No";
    default: return fill_empty;
  }  
}

arr_max_idx

##########################################################################################
# FUNCTION:arr_max_idx
# PURPOSE:  Returns the maximum index in the given array
# INPUT PARAMS: anarray[] - the array
# RETURN VALUE: the max. index
##########################################################################################
public function arr_max_idx(inout anarray[]) {
  auto i, maxidx;
  maxidx = -1;
  for (i in anarray) {
    if (i>maxidx) maxidx = i;
  }
  return maxidx;
}

parse_number

##########################################################################################
# FUNCTION:parse_number
# PURPOSE:  Analyzes the given string and returns the number contained there. Scientific form (e.g. 1e-5) is NOT supported!       
# INPUT PARAMS: in astring - the given string, out number
# RETURN VALUE: E_OK if astring is a number and E_ERROR, if - not.  
##########################################################################################
public function parse_number(in astring, out number) {
  auto s, l, i, neg, num, ch, pos, dot_num, was_dot, div;

  s = trim(astring);
  neg = FALSE;
  if (substr(s, 1, 1) == "-") {
    neg = TRUE;
    s = substr(s, 2);
  }
  else if (substr(s, 1, 1) == "+") {
    neg = FALSE;
    s = substr(s, 2);
  }
 
  l = length(s);
  num = 0;
  was_dot = FALSE;
  dot_num = 0;
  div = 1;
  for (i=1; i<= l; i++) {
    ch = substr(s, i, 1);
    pos = index("0123456789,.", ch);
    if (pos == 0) return E_ERROR; # Not a number

    pos = pos - 1;
    if (pos == 10) continue;    # comma

    if (pos == 11) {   # dot
      if (was_dot == TRUE)
        return E_ERROR; # TWO dots - NOT a number
      was_dot = TRUE;
      continue;
    }
    if (was_dot == TRUE) {
      dot_num = 10* dot_num + pos;
      div = div * 10;
    }
    else num = 10 * num + pos;
  }
 
  if (dot_num > 0) num = num + (dot_num / div);
  number = num;
  return E_OK; # Number
}

int_rand

##########################################################################################
# FUNCTION:int_rand
# PURPOSE:  return random integer
# INPUT PARAMS: range(1) - boundary of numbers, start - start point (0 if range 1, else 1)
# RETURN VALUE: start<=return<=range+start
##########################################################################################
public function int_rand(in range, in start) {
  if (range=="") range=1;
  if(range==1 && start=="") start=0;
  if(range>1 && start=="") start=1;
  return int(rand()*range+start+0.5);
}

equal_as_numbers

##########################################################################################
# FUNCTION:equal_as_numbers
# PURPOSE:  Compares two give strings as numbers       
# INPUT PARAMS: left, right - values to compare
# RETURN VALUE: TRUE if equal, FALSE if not equal
##########################################################################################
public function equal_as_numbers(in left, in right) {
  auto l, r, s;

  if (parse_number(left, l) != E_OK) {
    my_tl_step("equal_as_numbers()", E_WARNING, "parameter 1 ("left") is not a number");
    return FALSE;
  }
  if (parse_number(right, r) != E_OK) {
    my_tl_step("equal_as_numbers()", E_WARNING, "parameter 2 ("right") is not a number");
    return FALSE;
  }
  s = l - r;

  if (s < 0) s = -s;
  if (s < 1e-7) return TRUE;   # Equal

  return FALSE;         # Not equal
}

set_GUI_map_configuration

##########################################################################################
# FUNCTION:set_GUI_map_configuration
# PURPOSE: To minimize WR setup work, set WR GUI map by code. This could also set by user interface under Tools-GUI Map Configuration.
# all GUI map settings, which are different from WR default (after installation), should be set there   
# INPUT PARAMS: none
# RETURN VALUE: E_OK
##########################################################################################
public function set_GUI_map_configuration() {
  # only lines which are different form default are included here
  # Usually it is better to change default numbering by location (on screen) to numbering by index (apearance in HTML code) for objects
  # we don't do it for ..boxes, because for workspace objects are sorted after code generation (so indexes aren't ordered)

  set_record_attr("html_frame", "class html_name MSW_class", "html_id frame_id", "index");        # here index is used
 
  # add custom html_table class as specialized object
  set_class_map("html_table", "object");      
  set_record_attr("html_table", "class html_name", "html_id attached_text MSW_id MSW_class", "index");   # here index is used
  set_record_method("html_table", RM_RECORD);    # and recording method (context sensitive)
 
  set_record_attr("html_check_button", "class MSW_class html_name part_value", "html_id", "location");
  set_record_attr("html_combobox", "class MSW_class html_name", "html_id", "location");
  set_record_attr("html_edit", "class MSW_class html_name", "html_id", "location");
  set_record_attr("html_listbox", "class MSW_class html_name", "html_id", "location");
  set_record_attr("html_push_button", "class MSW_class html_name", "html_id", "location");
  set_record_attr("html_radio_button", "class MSW_class html_name part_value", "html_id", "location");  


#  set_class_map("html_text_link", "object");
  set_record_attr("html_text_link", "class MSW_class html_name", "attached_text html_id label", "location");
  set_record_method("html_text_link", RM_RECORD);
 
  return E_OK;  
}

Created by Valdis Vītoliņš on 2008-11-23 08:26
Last modified by Valdis Vītoliņš on 2021-04-13 14:29
 
Xwiki Powered
Creative Commons Attribution 3.0 Unported License