 {
 ***********************************************************************
 Web CGI script example.
 ***********************************************************************
 Next text uses by @Help command. Do not remove it.
 ***********************************************************************
[@Help]
|StdIn Command list: "@cmd=arg" or "@cmd arg"
|******************************************************
| @DebugEcho=n   - Switch HTTP debug echo page On/Off.
| @Start=n       - Set Start button state
| @Frequency=n   - Set Frequency of sin wave
| @Amplitude=n   - Set Amplitude of sin wave
| @Noise=n       - Set Noise     of sin wave
| @Browse n      - Call HTML browser to explore site n.
| @HTTP_REQUEST_ACCEPTED=sender,reqtime,request,reply
|                - HTTP request, see &WebSrv @Help
|******************************************************
|Example of HTTP request:
|******************************************************
|   QUERY.COUNT=1
|   QUERY.ITEM0=action=echo
|   COOKIE.COUNT=2
|   COOKIE.ITEM0=RemoteUserName=fhJW7Y1eSfmCNvuGEe2w9eiQC0C/85woHa+uirM8qlM
|   COOKIE.ITEM1=RemotePassword=GXY0lxYhBnDAYD5w77TaASAf6F+//gI50OXam/QBVoM
|   CONTENT.COUNT=2
|   CONTENT.ITEM0=RemoteUserName=root
|   CONTENT.ITEM1=RemotePassword=123
|   GATEWAY_INTERFACE=CGI/1.1
|   REQUEST_METHOD=GET
|   QUERY_STRING=action=echo
|   CONTENT=RemoteUserName=root&RemotePassword=123
|   CONTENT_LENGTH=26
|   CONTENT_TYPE=application/x-www-form-urlencoded
|   SERVER_NAME=RITLABS S.R.L.
|   SERVER_PORT=23816
|   SERVER_PROTOCOL=HTTP/1.1
|   SERVER_SOFTWARE=TinyWeb/1.93
|   REMOTE_HOST=localhost
|   REMOTE_ADDR=127.0.0.1
|   SCRIPT_NAME=/cgi-bin/websrv.cgi
|   PATH_INFO=/websrv.cgi
|   PATH_TRANSLATED=D:\DAQ32\DEMO_WEB4DAQ\websrv.cgi
|   WEBSRV.NAME=&WEBSRV
|   WEBSRV.SITE=http://main/
|   WEBSRV.ROOT=D:\DAQ32\DEMO_WEB4DAQ
|   WEBSRV.PORT=80
|   WEBSRV.INDEX=D:\DAQ32\DEMO_WEB4DAQ\INDEX.HTM
|******************************************************
[]
 }
program WebCgi;
const
 {------------------------------}{ Declare uses program constants:  }
 {$I _con_StdLibrary}            { Include all Standard constants,  }
 {------------------------------}{ And add User defined constants:  }

 FacilityName = 'Web4Daq';       { Name of this facility            }
 WavesPeriod  = 200;             { Poll period to update sin wave   }
 FetchPeriod  = 1000;            { AJAX refresh period, ms          }
 PlotTimeOut  = 3000;            { Timeout to make Plot, ms         }
 ViewRefresh  = 3;               { Refresh period for View page,sec }
 { Important note: All Web pages uses CSS style sheet default.css.  }
 { Call WEB_CopyCssLibrary('alex') to ensure this style available.  }
 { This style include some special CSS classes to set styles easy.  }
 { For example, <span class="big bold red">Use style easy.</span>   }
 DefaultCss   = '/Utility/StyleSheet/alex/default.css';

var
 {------------------------------}{ Declare uses program variables:  }
 {$I _var_StdLibrary}            { Include all Standard variables,  }
 {------------------------------}{ And add User defined variables:  }

 DebugEcho    : Boolean;         { FOR DEBUGGING ONLY               }
 winConsole   : String;          { Console window name              }
 tagStart     : Integer;         { Start button                     }
 tagFreq      : Integer;         { Frequency value                  }
 tagAmpl      : Integer;         { Amplitude value                  }
 tagNoise     : Integer;         { Noise value                      }
 fetchScript  : Integer;         { Text of [fetchDataScript.js]     }
 HostName     : String;          { Computer name                    }

 {------------------------------}{ Declare procedures & functions:  }
 {$I _fun_StdLibrary}            { Include all Standard functions,  }
 {------------------------------}{ And add User defined functions:  }

 {
 Show nice header "Name: Comment", also show computer name, access and date.
 Note that named tags #HeaderHostInfo #HeaderHostDate, #HeaderAccess uses by
 Java Script, see ViewPage. Uses "alex" style sheet to format text.
 }
 procedure WEB_ShowHeader(Name,Comment:String; Access:Integer; Time:String);
 begin
  WEB_Reply('<table cellspacing=0 class="stdborder" width="100%">');
  WEB_Reply('<tr>');
  WEB_Reply('<td class="stdborder nomargin nopadding">');
  WEB_Reply('<h1 class="nomargin"><span class="red">&nbsp;'+Name+'</span>: '+Comment+'</h1>');
  WEB_Reply('</td>');
  WEB_Reply('<td class="stdborder nomargin nopadding" style="border-right: none;" width=40>');
  WEB_Reply('<img src="/Utility/StyleSheet/alex/computer.gif" alt="Сервер" border=0 width=32 height=32>');
  WEB_Reply('</td>');
  WEB_Reply('<td class="stdborder nomargin nopadding small" style="border-left: none;" width=190>');
  WEB_Reply('<span class="blue italic" id="HeaderHostInfo">'+HostName+'</span><br>');
  if Length(Time)>0
  then WEB_Reply('<span class="blue italic" id="HeaderHostDate">'+Time+'</span>')
  else WEB_Reply('<span class="blue italic" id="HeaderHostDate">'+GetDateTime(mSecNow)+'</span>');
  if Access>=0 then
  WEB_Reply('<span class="blue italic" id="HeaderAccess">'+ExtractWord(Access+1,acc_DenyList)+'</span>');
  WEB_Reply('</td>');
  WEB_Reply('</tr>');
  WEB_Reply('</table>');
 end;
 {
 Show nice foot note, also show computer name, access and date.
 Note that named tags #FootNoteHostInfo #FootNoteHostDate, #FootNoteAccess
 uses by Java Script, see ViewPage. Uses "alex" style sheet to format text.
 }
 procedure WEB_ShowFootNote(Access:Integer; Time:String);
 begin
  WEB_Reply('<table cellspacing=0 class="stdborder" width="100%">');
  WEB_Reply('<tr>');
  WEB_Reply('<td class="stdborder nomargin nopadding small italic">');
  WEB_Reply('&nbsp;<b>'+FacilityName+'</b> = Демонстрационный пример Web сервера для CRW-DAQ.<br>');
  WEB_Reply('&nbsp;2012,РФ,Саров,(83130)-28817,'
           +'<a href="mailto:kouriakine@mail.ru">kouriakine@mail.ru</a>,'
           +'<a href="mailto:yvinogra@mail.ru">yvinogra@mail.ru</a>.');
  WEB_Reply('</td>');
  WEB_Reply('<td class="stdborder nomargin nopadding" style="border-right: none;" width=40>');
  WEB_Reply('<img src="/Utility/StyleSheet/alex/computer.gif" alt="Сервер" border=0 width=32 height=32>');
  WEB_Reply('</td>');
  WEB_Reply('<td class="stdborder nomargin nopadding small" style="border-left: none;" width=190>');
  WEB_Reply('<span class="blue italic" id="FootNoteHostInfo">'+HostName+'</span><br>');
  if Length(Time)>0
  then WEB_Reply('<span class="blue italic" id="FootNoteHostDate">'+Time+'</span>')
  else WEB_Reply('<span class="blue italic" id="FootNoteHostDate">'+GetDateTime(mSecNow)+'</span>');
  if Access>=0 then
  WEB_Reply('<span class="blue italic" id="FootNoteAccess">'+ExtractWord(Access+1,acc_DenyList)+'</span>');
  WEB_Reply('</td>');
  WEB_Reply('</tr>');
  WEB_Reply('</table>');
 end;
 {
 Show warning if Java Script is disabled.
 }
 procedure WEB_NoJsWarning;
 begin
  WEB_Reply('<noscript>');
  WEB_Reply('<table border="0"><tr><td><img src="/Utility/StyleSheet/alex/exclamation.gif"></td>');
  WEB_Reply('<td style="padding-left:10px;"><span class="green italic">'
           +'У Вашего Web - обозрвателя отключен Java Script!</span><br>');
  WEB_Reply('<span class="gray italic">Для ускорения работы рекомендуется его включить!</span>');
  WEB_Reply('</td></tr></table>');
  WEB_Reply('</noscript>');
 end;
 {
 Show host date-time and remote operator name (from cookies).
 Also mark date-time as #MainHostDate to use in JavaScript.
 }
 procedure WEB_ShowTimeAndOperator;
 var s:String;
 begin
  s:='';
  WEB_Reply('<p>');
  if WEB_GetCookieItem('RemoteOperator',s) then s:=Trim(WEB_DecryptCookie(s)) else s:='';
  if Length(s)>0 then s:=', <b>Оператор:</b> '+s+'.';
  WEB_Reply('<b>Время:</b> <span id="MainHostDate">'+WEB.DateTime+'</span>'+s);
  WEB_Reply('<p>');
  s:='';
 end;
 {
 HTML page to show error.
 }
 procedure WEB_ErrorPage(Msg:String);
 var t:Integer;
 begin
  WEB_Reply('<html lang=ru>');
  WEB_Reply('<head>');
  WEB_MetaRefresh(-1,'');
  WEB_LinkStyleSheet(DefaultCss);
  WEB_MetaSetCookie('RemoteUserName','');
  WEB_MetaSetCookie('RemotePassword','');
  WEB_Reply('<title>'+FacilityName+': Error page</title>');
  WEB_Reply('</head>');
  WEB_Reply('<body>');
  WEB_ShowHeader(FacilityName,'Ошибка!',-1,'');
  t:=StringToText(Msg);
  WEB_ReplyText(t);
  bNul(text_Free(t));
  WEB_ShowFootNote(-1,WEB.DateTime);
  WEB_Reply('</body>');
  WEB_Reply('</html>');
  WEB_ReplyEnd;
 end;
 {
 HTML page to show Access Denied page.
 }
 procedure WEB_AccessDeniedPage;
 begin
  WEB_ErrorPage('<p><span class="big bold red">Доступ к сайту <span class="big">'
               +FacilityName+'</span> закрыт.</span><br>'+CRLF
               +'<p><span class="big bold">Надо пройти <a class="big" href="'+Web.ScriptName
               +'?action=login&timestamp='+Str(mSecNow-JavaTimeBase)+'">авторизацию</a>.</span><p>'+CRLF
               +'<img src="/utility/stylesheet/alex/blocked.gif" height="150">'+CRLF
               +'<img src="/utility/stylesheet/alex/animate-watchdog.gif" height="150">'+CRLF
               +'<img src="/utility/stylesheet/alex/access_denied.gif" height="150">'+CRLF
               +'<p>');
 end;
 {
 HTML page to see HTTP echo in DebugEcho mode, for tests only.
 }
 procedure WEB_EchoPage;
 begin
  WEB_Reply('<html lang=ru>');
  WEB_Reply('<head>');
  WEB_MetaRefresh(-1,'');
  WEB_LinkStyleSheet(DefaultCss);
  WEB_Reply('<title>'+FacilityName+': Echo page</title>');
  WEB_Reply('</head>');
  WEB_Reply('<body>');
  WEB_ShowHeader(FacilityName,'HTTP echo',-1,'');
  WEB_Reply('<pre style="margin-left: 20px;">');
  WEB_ReplyTextEscape(WEB.Request);
  WEB_Reply('</pre>');
  WEB_ShowFootNote(-1,WEB.DateTime);
  WEB_Reply('</body>');
  WEB_Reply('</html>');
  WEB_ReplyEnd;
 end;
 {
 HTTP page to make Login.
 On first entry user fill a form with user name and password and send it to server.
 When this data received, server set cookies with encrypted user name and password.
 After that client use cookies with encripted user name & password to get access.
 }
 procedure WEB_LoginPage;
 var i,Access:Integer; b:Boolean; s:String;
 begin
  s:='';
  WEB_Reply('<html lang=ru>');
  WEB_Reply('<head>');
  WEB_MetaRefresh(-1,'');
  WEB_LinkStyleSheet(DefaultCss);
  WEB_Reply('<title>'+FacilityName+': Login page</title>');
  {
  If data posted from HTML form, get user&password from content, then set cookies.
  Otherwise, get user&password from cookies.
  }
  if WEB_FormDataPosted then begin
   {If user sent Login form, save encrypted username&password in cookies for future}
   if WEB_GetContentItem('RemoteUserName',WEB.UserName)
   then WEB_MetaSetCookie('RemoteUserName',WEB_EncryptCookie(RightPad(WEB.UserName,32,' ')));
   if WEB_GetContentItem('RemotePassword',WEB.Password)
   then WEB_MetaSetCookie('RemotePassword',WEB_EncryptCookie(RightPad(WEB.Password,32,' ')));
   if WEB_GetContentItem('RemoteOperator',s)
   then WEB_MetaSetCookie('RemoteOperator',WEB_EncryptCookie(s));
   {check access, get username&password from content}
   Access:=WebAccessGranted(0);
  end else begin
   {check access, get username&password from cookies}
   Access:=WebAccessGranted(1);
  end;
  WEB_Reply('</head>');
  WEB_Reply('<body>');
  WEB_ShowHeader(FacilityName,'Авторизация',Access,'');
  if Access>acc_Deny then begin
   WEB_Reply('<p><span class="big bold">Вам предоставлен уровень доступа <span class="big red bold">'
            +ExtractWord(Access,acc_List)+'</span>.</span>');
   WEB_Reply('<p><span class="big bold">Теперь Вы можете <a class="big" href="'
            +WEB.ScriptName+'?action=home&timestamp='+Str(mSecNow-JavaTimeBase)
            +'">войти</a> на сайт <span class="big red">'+FacilityName+'</span>.</span>');
   WEB_Reply('<p>');
   if FileExists(DaqFileRef('..\Utility\StyleSheet\alex\secret_agent.gif','')) then
   if FileExists(DaqFileRef('..\Utility\StyleSheet\alex\animate-applause1.gif','')) then
   if FileExists(DaqFileRef('..\Utility\StyleSheet\alex\animate-applause2.gif','')) then begin
    WEB_Reply('<span style="padding-left:100px;">');
    WEB_Reply('<img src="/utility/stylesheet/alex/animate-applause1.gif" height="100">');
    WEB_Reply('<img src="/utility/stylesheet/alex/secret_agent.gif" height="300">');
    WEB_Reply('<img src="/utility/stylesheet/alex/animate-applause2.gif" height="100">');
    WEB_Reply('</span>');
   end;
   WEB_Reply('<p>');
  end else begin
   WEB_Reply('<form action="'+WEB.ScriptName+'?action=login" method="post">');
   WEB_Reply('<table border=0>');
   WEB_Reply('<tr valign=top>');
   WEB_Reply('<td>');
   WEB_Reply('<span class="big bold blue">Стой кто идет!</span><br><br>');
   WEB_Reply('<span class="bigger bold">Ваше звание:</span>');
   WEB_Reply('<select class="Login bold mono" name="RemoteUserName">');
   WEB_Reply('<option          value="guest"> Рядовой (guest) </option>');
   WEB_Reply('<option selected value="user">  Капитан (user)  </option>');
   WEB_Reply('<option          value="root">  Генерал (root)  </option>');
   WEB_Reply('</select>');
   WEB_Reply('<p>');
   WEB_Reply('<span class="bigger bold">Ввод пароля:</span>');
   WEB_Reply('<input class="Login bold mono" type="Password" name="RemotePassword"><br>');
   WEB_Reply('<p>');
   WEB_Reply('<span class="bigger bold">Ваше Ф.И.О.:</span>');
   WEB_Reply('<input class="Login bold mono" type="Text" name="RemoteOperator"><br>');
   WEB_Reply('<p>');
   WEB_Reply('<input class="big bold mono" type="Submit" value="&nbsp;Подтвердить&nbsp;">');
   WEB_Reply('<input class="big bold mono" type="Reset"  value="&nbsp;Очистить&nbsp;">');
   WEB_Reply('<br>');
   WEB_Reply('<br>');
   WEB_Reply('<pre>');
   WEB_Reply('<hr class="nomargin">Примечание:');
   WEB_Reply('Рядовой пользователь (<span class="red">guest</span>) может войти без');
   WEB_Reply('пароля, но будет иметь ограниченные права.');
   WEB_Reply('<hr class="nomargin">');
   WEB_Reply('</pre>');
   WEB_Reply('</td>');
   WEB_Reply('<td>');
   WEB_Reply('<span class="big bold red">Говори пароль!</span><br>');
   WEB_Reply('<img src="/Utility/StyleSheet/alex/policeman.gif" alt="Введите пароль!">');
   WEB_Reply('</td>');
   WEB_Reply('</tr>');
   WEB_Reply('</table>');
   WEB_Reply('</form>');
   WEB_Reply('В данном примере:');
   WEB_Reply('<ul>');
   WEB_Reply('<li><span class="red">UserName=root, Password=123</span> для Генерала.');
   WEB_Reply('<li><span class="red">UserName=user, Password=321</span> для Капитана.');
   WEB_Reply('<li><span class="red">UserName=guest, No Password</span> для Рядового.');
   WEB_Reply('</ul>');
  end;
  WEB_Reply('<p>');
  WEB_ShowFootNote(Access,WEB.DateTime);
  WEB_Reply('</body>');
  WEB_Reply('</html>');
  WEB_ReplyEnd;
  s:='';
 end;
 {
 HTML page to select content.
 }
 procedure WEB_HomePage;
 var Access:Integer; b:Boolean;
 begin
  Access:=WebAccessGranted(1);
  if Access>=acc_Guest then begin
   WEB_Reply('<html lang=ru>');
   WEB_Reply('<head>');
   WEB_MetaRefresh(-1,'');
   WEB_LinkStyleSheet(DefaultCss);
   WEB_Reply('<title>'+FacilityName+': Home page</title>');
   WEB_Reply('</head>');
   WEB_Reply('<body>');
   WEB_ShowHeader(FacilityName,'Главное меню',Access,'');
   WEB_ShowTimeAndOperator;
   WEB_Reply('<table class="big noborder center">');
   WEB_Reply('<tr>');
   WEB_Reply('<td>');
   WEB_Reply('<img src="/Utility/StyleSheet/alex/officiant.gif" alt="Главное меню" border=0>&nbsp;');
   WEB_Reply('</td>');
   WEB_Reply('<td valign=center>');
   WEB_Reply('<span class="big bold red">Каждый<br>выбирает<br>по себе:</span>');
   WEB_Reply('</td>');
   WEB_Reply('</tr>');
   WEB_Reply('</table>');
   WEB_Reply('<p>');
   WEB_Reply('<ol>');
   WEB_Reply('<li>');
   WEB_Reply('<a class="big bold" href="'+WEB.ScriptName+'?Action=Echo'
            +'&timestamp='+Str(mSecNow-JavaTimeBase)+'" target="_blank">');
   WEB_Reply('HTTP echo.');
   WEB_Reply('</a>');
   WEB_Reply('<br>');
   WEB_Reply('<span class="small italic">');
   WEB_Reply('Позволяет посмотреть содержимое HTTP-запроса (в качестве примера).<br>');
   WEB_Reply('Эта функция разрешена всем.<br>');
   WEB_Reply('</span>');
   WEB_Reply('<p>');
   WEB_Reply('<li>');
   WEB_Reply('<a class="big bold" href="'+WEB.ScriptName+'?Action=View'
            +'&timestamp='+Str(mSecNow-JavaTimeBase)+'" target="_blank">');
   WEB_Reply('Просмотр таблицы данных');
   WEB_Reply('</a>');
   WEB_Reply('<br>');
   WEB_Reply('<span class="small italic">');
   WEB_Reply('Отображает текущее состояние переменных в виде таблицы.<br>');
   WEB_Reply('Эта функция разрешена при уровне доступа не ниже <span class="red bold">guest</span>.<br>');
   WEB_Reply('</span>');
   WEB_Reply('<p>');
   WEB_Reply('<li>');
   WEB_Reply('<a class="big bold" href="'+WEB.ScriptName+'?Action=Plot'
            +'&timestamp='+Str(msecnow-JavaTimeBase)+'" target="_blank">');
   WEB_Reply('Просмотр графика данных');
   WEB_Reply('</a>');
   WEB_Reply('<br>');
   WEB_Reply('<span class="small italic">');
   WEB_Reply('Отображает график с данными.<br>');
   WEB_Reply('Эта функция разрешена при уровне доступа не ниже <span class="red bold">user</span>.<br>');
   WEB_Reply('</span>');
   WEB_Reply('<p>');
   WEB_Reply('<li>');
   WEB_Reply('<a class="big bold" href="'+WEB.ScriptName+'?Action=Edit'
            +'&timestamp='+Str(msecnow-JavaTimeBase)+'" target="_blank">');
   WEB_Reply('Редактирование параметров.');
   WEB_Reply('</a>');
   WEB_Reply('<br>');
   WEB_Reply('<span class="small italic">');
   WEB_Reply('Редактирование параметров.<br>');
   WEB_Reply('Эта функция разрешена при уровне доступа не ниже <span class="red bold">root</span>.<br>');
   WEB_Reply('</span>');
   WEB_Reply('<p>');
   WEB_Reply('</ol>');
   WEB_Reply('<p>');
   WEB_ShowFootNote(Access,WEB.DateTime);
   WEB_NoJsWarning;
   WEB_Reply('</body>');
   WEB_Reply('</html>');
   WEB_ReplyEnd;
  end else WEB_AccessDeniedPage;
 end;
 {
 HTML page to view current state.
 }
 procedure WEB_ViewPage;
 var Access,i:Integer; b:Boolean;
  {
  Add a row with 2 columns to table.
  Also set id="Name" for JavaScript $("#Name") reference!
  }
  procedure AddTableRow2(id,Col1,Col2:String);
  begin
   WEB_Reply('<tr>');
   WEB_Reply('<td class="stdborder big bold">'+Col1+'</td>');
   WEB_Reply('<td class="stdborder big" id="'+id+'">'+Col2+'</td>');
   WEB_Reply('</tr>');
  end;
 begin
  Access:=WebAccessGranted(1);
  if Access>=acc_Guest then begin
   WEB_Reply('<html>');
   WEB_Reply('<head>');
   WEB_MetaRefresh(-1,'');
   WEB_LinkStyleSheet(DefaultCss);
   WEB_Reply('<title>'+FacilityName+': View page</title>');
   WEB_Reply('<noscript>');
   WEB_MetaRefresh(ViewRefresh,''); // If JavaScript disabled, setup page refresh.
   WEB_Reply('</noscript>');
   WEB_AddJavaScript('/Utility/JavaScript/flot/jquery.min.js');
   WEB_Reply('</head>');
   WEB_Reply('<body>');
   WEB_ShowHeader(FacilityName,'Таблица SIN',Access,'');
   WEB_ShowTimeAndOperator;
   WEB_Reply('<table class="stdborder mono" cellspacing="5" cellpadding="5">');
   AddTableRow2('SinStart', 'Start',      ExtractWord(iGetTag(tagStart)+1,'Off,On'));
   AddTableRow2('SinTime',  'Time,[min]', StrFix(time,1,3));
   AddTableRow2('SinVal1',  'SIN1 value', StrFix(CrvY(RefAo(0),CrvLen(RefAo(0))),1,3));
   AddTableRow2('SinVal2',  'SIN2 value', StrFix(CrvY(RefAo(1),CrvLen(RefAo(0))),1,3));
   AddTableRow2('SinFreq',  'Frequency',  Str(rGetTag(tagFreq)));
   AddTableRow2('SinAmpl',  'Amplitude',  Str(rGetTag(tagAmpl)));
   AddTableRow2('SinNoise', 'Noise',      Str(rGetTag(tagNoise)));
   WEB_Reply('</table>');
   WEB_Reply('<p>');
   WEB_ShowFootNote(Access,WEB.DateTime);
   {
   Show warning if JavaScript disabled. Create HTML tag #AjaxStatus to display AJAX status.
   Then write JavaScript. A part of the script generated by DaqPascal, to setup parameters.
   Main text of JavaScript is embedded in [fetchDataScript.js] section inside the comments.
   Note that JavaScript also use named HTML tags by using $("#NameId").Text(..),so be sure
   that HTML tags use the same names ( id="..." ) as JavaScript.
   }
   WEB_NoJsWarning;
   WEB_Reply('<span style="color: blue; background-color: yellow; '
            +'font-weight: bold; font-size: 24pt;" id="AjaxStatus"></span>');
   WEB_Reply('<script id="fetchDataScript" language="javascript" type="text/javascript">');
   WEB_Reply(' var fetchPeriod='+Str(FetchPeriod)+';');   // Setup fetchPeriod parameter for script.
   WEB_Reply(' var WebScriptName="'+WEB.ScriptName+'";'); // Setup WebScriptName parameter etc.
   WEB_ReplyText(fetchScript);                            // Add JavaScript from [fetchDataScript.js].
   WEB_Reply('</script>');
   WEB_Reply('</body>');
   WEB_Reply('</html>');
   WEB_ReplyEnd;
  end else WEB_AccessDeniedPage;
 end;

(*
 ******************************************************************************
 **************** Embedded JavaScript to fetch data via AJAX ******************
  This script embedded to DaqPascal program by using comments and sections [].
  Use WEB_ReadJsFromPas(text_New,'[fetchDataScript.js]'); to read this script.
  Use WEB_ReplyText() to add the script to WEB reply to send script to client.
  Note that some uses variables (fetchPeriod, WebScriptName) we have to setup
  in DaqPascal program, to transfer a parameters from DaqPascal to JavaScript.
 ******************************************************************************
[fetchDataScript.js]
 $(function () {
  var ajaxWatchdog=0;
  function onDataReceived(data,status) {
   $("#MainHostDate").text(data.HostDate);
   $("#HeaderAccess").text(data.AccessId);
   $("#HeaderHostInfo").text(data.HostInfo);
   $("#HeaderHostDate").text(data.HostDate);
   $("#FootNoteAccess").text(data.AccessId);
   $("#FootNoteHostInfo").text(data.HostInfo);
   $("#FootNoteHostDate").text(data.HostTime);
   if(data.SinData.length>=7){
    $("#SinStart").text(data.SinData[0]);
    $("#SinTime").text(data.SinData[1]);
    $("#SinVal1").text(data.SinData[2]);
    $("#SinVal2").text(data.SinData[3]);
    $("#SinFreq").text(data.SinData[4]);
    $("#SinAmpl").text(data.SinData[5]);
    $("#SinNoise").text(data.SinData[6]);
   }
   $("#AjaxStatus").text("");
   ajaxWatchdog=0;
  }
  function onFetchError(xhr,status,error) {
   $("#AjaxStatus").text("СБОЙ СВЯЗИ: "+status+" ("+xhr.status+").");
  }
  function fetchData(){
   var Factor=1;
   if(ajaxWatchdog>10) Factor=Math.ceil(Math.log(ajaxWatchdog));
   $.ajax({ url: WebScriptName+"?Action=Fetch&Time="+(new Date().getTime()),
    method: 'GET', dataType: 'json', success: onDataReceived, error: onFetchError
   });
   setTimeout(fetchData,fetchPeriod*Factor);
  };
  setTimeout(fetchData,fetchPeriod);
  function fetchWatchdog(){
   ajaxWatchdog=ajaxWatchdog+1;
   if(ajaxWatchdog>fetchPeriod/1000*10){
    $("#AjaxStatus").text("СВЯЗЬ ПОТЕРЯНА. Прошло "+ajaxWatchdog+" сек."); 
   }
   setTimeout(fetchWatchdog,1000);
  };
  setTimeout(fetchWatchdog,1000);
 });
[]
 ******************************************************************************
 ********************** End of embedded JavaScript section ********************
 ******************************************************************************
*)

 (*
 HTML page to fetch current data via JSON (Java Script Object Notation) format.
 See http://ru.wikipedia.org/wiki/JSON for details.
 Example of FetchPage output:
  {
   "SinData": [ "On", "477.855", "-1.602", "1.133", 1, 2, 0.1 ], 
   "HostTime": "2012.03.16-19:21:42", "HostDate": "2012.03.16-19:21:43", 
   "HostInfo": "AKURYAKI-XP", "AccessId": "Guest" 
  }
 *)
 procedure WEB_FetchPage;
 var Access,Start:Integer; sin1,sin2,freq,ampl,nois:Real;
 begin
  Access:=WebAccessGranted(1);
  if Access>=acc_Guest then begin
   {
   Extract data to send
   }
   start:=iGetTag(tagStart);
   sin1:=crvGetLastY(RefAo(0));
   sin2:=crvGetLastY(RefAo(1));
   freq:=rGetTag(tagFreq);
   ampl:=rGetTag(tagAmpl);
   nois:=rGetTag(tagNoise);
   {
   Create JSON answer:
   }
   JSON_BeginPage;                                         //  {
   JSON_AddKey('SinData');                                 //  "SinData":
   JSON_BeginArray;                                        //  [ 
   JSON_AddStr(ExtractWord(start+1,'Off,On'),_Comma);      //  "On",
   JSON_AddStr(StrFix(time,1,3),_Comma);                   //  "477.855",
   JSON_AddStr(StrFix(sin1,1,3),_Comma);                   //  "-1.602",
   JSON_AddStr(StrFix(sin2,1,3),_Comma);                   //  "1.133",
   JSON_AddNum(freq,_Comma);                               //  1,
   JSON_AddNum(ampl,_Comma);                               //  2,
   JSON_AddNum(nois,_Space);                               //  0.1
   JSON_EndArray(_Comma);                                  //  ],
   JSON_Flush;                                             //  New line, for nice view
   JSON_AddKeyStr('HostTime',GetDateTime(mSecNow),_Comma); //  "HostTime": "2012.03.16-19:21:42",
   JSON_AddKeyStr('HostDate',WEB.DateTime,_Comma);         //  "HostDate": "2012.03.16-19:21:43",
   JSON_AddKeyStr('HostInfo',HostName,_Comma);             //  "HostInfo": "AKURYAKI-XP",
   JSON_AddKeyStr('AccessId',ExtractWord(Access+1,acc_DenyList),_Space); // "AccessId": "Guest"
   JSON_EndPage;                                           //  }
  end else begin
   JSON_BeginPage;
   JSON_AddKey('SinData'); JSON_BeginArray; JSON_EndArray(_Comma); // Empty array
   JSON_AddKeyStr('HostTime',GetDateTime(mSecNow),_Comma);
   JSON_AddKeyStr('HostDate',WEB.DateTime,_Comma);
   JSON_AddKeyStr('HostInfo',HostName,_Comma);
   JSON_AddKeyStr('AccessId',ExtractWord(Access+1,acc_DenyList),_Space);
   JSON_EndPage;
  end;
 end;
//(*
 {
 HTML page to plot curves. GnuPlot version.
 Also show how to set axis ranges by using forms.
 }
 procedure WEB_PlotPage;
 var Access,Refresh,Crv1,Crv2:Integer;
     x1,y1,x2,y2,t1,w1,t2,w2,ms:Real; s,Title,Units,sx1,sx2,sy1,sy2:String;
 begin
  s:=''; Title:=''; Units:=''; sx1:=''; sy1:=''; sx2:=''; sy2:='';
  Access:=WebAccessGranted(1);
  if Access>=acc_User then begin
   Crv1:=RefAo(0);
   Crv2:=RefAo(1);
   Title:='График '+CrvName(Crv1)+','+CrvName(Crv2);
   Units:='Усл.ед.';
   sx1:='xmax-10';
   sy1:='ymin-0.1*(ymax-ymin)';
   sx2:='xmax';
   sy2:='ymax+0.1*(ymax-ymin)';
   if WEB_FormDataPosted then begin
    if WEB_GetContentItem('x1',s) then sx1:=s;
    if WEB_GetContentItem('y1',s) then sy1:=s;
    if WEB_GetContentItem('x2',s) then sx2:=s;
    if GetStringVar(WEB.ContentItems,'y2',s) then sy2:=s;
    Refresh:=1;
   end else begin
    if WEB_GetCookieItem('x1',s) then sx1:=s;
    if WEB_GetCookieItem('y1',s) then sy1:=s;
    if WEB_GetCookieItem('x2',s) then sx2:=s;
    if WEB_GetCookieItem('y2',s) then sy2:=s;
    Refresh:=10;
   end;
   x1:=+MaxReal; y1:=+MaxReal;
   x2:=-MaxReal; y2:=-MaxReal;
   if GetCrvRange(Crv1,t1,w1,t2,w2)>0 then begin
    x1:=Min(x1,t1); y1:=Min(y1,w1);
    x2:=Max(x2,t2); y2:=Max(y2,w2);
   end;
   if GetCrvRange(Crv2,t1,w1,t2,w2)>0 then begin
    x1:=Min(x1,t1); y1:=Min(y1,w1);
    x2:=Max(x2,t2); y2:=Max(y2,w2);
   end;
   if (x1<x2) and (y1<y2) then begin
    bNul(evar('xmin',x1));
    bNul(evar('ymin',y1));
    bNul(evar('xmax',x2));
    bNul(evar('ymax',y2));
    x1:=TimeBase+TimeUnits*eval(sx1);
    y1:=eval(sy1);
    x2:=TimeBase+TimeUnits*eval(sx2);
    y2:=eval(sy2);
   end else begin
    x1:=0;
    y1:=0;
    x2:=1;
    y2:=1;
   end;
   WEB_Reply('<html lang=ru>');
   WEB_Reply('<head>');
   WEB_MetaRefresh(Refresh,'');
   WEB_LinkStyleSheet(DefaultCss);
   if WEB_FormDataPosted then begin
    WEB_MetaSetCookie('x1',sx1);
    WEB_MetaSetCookie('y1',sy1);
    WEB_MetaSetCookie('x2',sx2);
    WEB_MetaSetCookie('y2',sy2);
   end;
   WEB_Reply('<title>'+FacilityName+': Plot page</title>');
   WEB_Reply('</head>');
   WEB_Reply('<body>');
   WEB_ShowHeader(FacilityName,'График SIN',Access,'');
   WEB_ShowTimeAndOperator;
   ms:=msecnow;
   if FileErase(DaqFileRef('..\Bitmaps\web_plot.gif','')) and
     (PlotSend('@Clear'+CRLF
              +'@HomeDir ..\Temp'+CRLF
              +'@TimeOut '+Str(PlotTimeOut)+CRLF
              +'@DoneMsg '+DevName+' @PlotSrv-Done ..\Bitmaps\web_plot.gif'+CRLF
              +'@FailMsg '+DevName+' @PlotSrv-Fail ..\Bitmaps\web_plot.gif'+CRLF
              +'@> set encoding koi8r; set output "web_plot.gif"'+CRLF
              +'@> set terminal gif small size 700,350'+CRLF
              +'@> set title "'+Win2Koi(Title)+'" font "luconk,10"'+CRLF
              +'@> set xlabel "'+Win2Koi('Время календарное')+'" font "luconk,10"'+CRLF
              +'@> set ylabel "'+Win2Koi(Units)+'" font "luconk,8"'+CRLF
              +'@> set xdata time; set timefmt "%Y.%m.%d-%H:%M:%S"'+CRLF
              +'@> set format x "%d.%m\n%H:%M";'+CRLF
              +'@> set xrange [ "'+GetDateTime(x1)+'":"'+GetDateTime(x2)+'" ]'+CRLF
              +'@> set yrange [ "'+Str(y1)+'":"'+Str(y2)+'" ]'+CRLF
              +'@> set grid; set key left top;'+CRLF
              +'@> plot "web_plot.dat" index 0 using 1:2 with lp lw 2 lc 12 pt 0 ti "'+CrvName(Crv1)+'",\'+CRLF
              +'@>      "web_plot.dat" index 1 using 1:2 with lp lw 2 lc 3  pt 0 ti "'+CrvName(Crv2)+'"'+CRLF
              +'@CurveList '+CrvName(Crv1)+CRLF
              +'@CurveList '+CrvName(Crv2)+CRLF
              +'@XTime=Default'+CRLF
              +'@! move /y web_plot.gif ..\Bitmaps\web_plot.gif'+CRLF
              +'@run web_plot.job web_plot.dat web_plot.bat'+CRLF)>0)
   then begin
    while (msecnow-ms<PlotTimeOut) and not FileExists(DaqFileRef('..\Bitmaps\web_plot.gif','')) do begin
     bNul(Wdt_Reset(True)>0);
     bNul(Sleep(1));
    end;
   end;
   if not FileExists(DaqFileRef('..\Bitmaps\web_plot.gif','')) then
   bNul(FileCopy(Url_Packed(DaqFileRef('..\Bitmaps\web_none.gif',''))+' '
                +Url_Packed(DaqFileRef('..\Bitmaps\web_plot.gif',''))));
   WEB_Reply('<img src="/Bitmaps/web_plot.gif" border="1" width="700" alt="SIN plot">');
   WEB_Reply(StrFix(msecnow-ms,1,0)+' ms');
   WEB_Reply('<br>');
   WEB_Reply('<form action="'+WEB.ScriptName+'?'+WEB.QueryString+'" method="post">');
   WEB_Reply('<p>');
   WEB_Reply('<table class="noborder" width="800">');
   WEB_Reply('<tr>');
   WEB_Reply('<td>');
   WEB_Reply('<span class="big bold">Пределы по оси X:</span><br>');
   WEB_Reply('<b>x1=</b><input class="bold mono" type="text" name="x1" value="'+sx1+'"> минут<br>');
   WEB_Reply('<b>x2=</b><input class="bold mono" type="text" name="x2" value="'+sx2+'"> минут<br>');
   WEB_Reply('</td>');
   WEB_Reply('<td>');
   WEB_Reply('<span class="big bold">Пределы по оси Y:</span><br>');
   WEB_Reply('<b>y1=</b><input class="bold mono" type="text" name="y1" value="'+sy1+'"> '+Units+'<br>');
   WEB_Reply('<b>y2=</b><input class="bold mono" type="text" name="y2" value="'+sy2+'"> '+Units+'<br>');
   WEB_Reply('</td>');
   WEB_Reply('<td>');
   WEB_Reply('<input class="big bold mono" type="Submit" value="Задать"><br>');
   WEB_Reply('<input class="big bold mono" type="Reset"  value="Отмена">');
   WEB_Reply('</td>');
   WEB_Reply('</tr>');
   WEB_Reply('</table>');
   WEB_Reply('<p class="small">');
   WEB_Reply('<b>Примечание:</b> При указании пределов используйте формулы и');
   WEB_Reply('переменные xmin, ymin, xmax, ymax (диапазон данных).<br>');
   WEB_Reply('Примеры формул: <b>x1=</b><i>xmax-1</i>, <b>x2=</b><i>xmax</i>,'
            +' <b>y1=</b><i>ymin-10</i>, <b>y2=</b><i>ymax+10</i><br>');
   WEB_Reply('</form>');
   WEB_Reply('<p>');
   WEB_ShowFootNote(Access,WEB.DateTime);
   WEB_Reply('</body>');
   WEB_Reply('</html>');
   WEB_ReplyEnd;
  end else WEB_AccessDeniedPage;
  s:=''; Title:=''; Units:=''; sx1:=''; sy1:=''; sx2:=''; sy2:='';
 end;
//*)
(*
 {
 HTML page to plot curves. Simple version.
 }
 procedure WEB_PlotPage;
 var Access:Integer; ms:real; s:String;
 begin
  s:='';
  Access:=WebAccessGranted(1);
  if Access>=acc_User then begin
   WEB_Reply('<html>');
   WEB_Reply('<head>');
   WEB_MetaRefresh(10,'');
   WEB_LinkStyleSheet(DefaultCss);
   WEB_Reply('<title>'+FacilityName+': Plot page</title>');
   WEB_Reply('</head>');
   WEB_Reply('<body>');
   WEB_ShowHeader(FacilityName,'График SIN',Access,'');
   WEB_ShowTimeAndOperator;
   s:='..\Bitmaps\web_plot.bmp';
   bNul(FileErase(DaqFileRef(s,'.bmp')));
   bNul(WinDraw('SIN_PLOT|SaveBmp=4bit,'+s+'|Range=x1,ymin*1.2,x2,ymax*1.2'));
   ms:=msecnow;
   while (msecnow-ms<PlotTimeOut) and not FileExists(DaqFileRef(s,'.bmp')) do begin
    bNul(Wdt_Reset(True)>0);
    bNul(Sleep(1));
   end;
   WEB_Reply('<img src="/Bitmaps/web_plot.bmp" border="1" alt="SIN_PLOT window">');
   WEB_Reply(StrFix(msecnow-ms,1,0)+' ms');
   WEB_Reply('<br>');
   WEB_Reply('<p>');
   WEB_ShowFootNote(Access,WEB.DateTime);
   WEB_Reply('</body>');
   WEB_Reply('</html>');
   WEB_ReplyEnd;
  end else WEB_AccessDeniedPage;
  s:='';
 end;
*)
 {
 HTML page to edit parameters.
 }
 procedure WEB_EditPage;
 var i,Access:Integer; b:Boolean; s:String;
 begin
  s:='';
  Access:=WebAccessGranted(1);
  if Access>=acc_Root then begin
   if IsSameText(WEB.RequestMethod,'Post') then begin
    if WEB_GetContentItem('Start',s)     then UpdateTag(tagStart,s,0,1);
    if WEB_GetContentItem('Frequency',s) then UpdateTag(tagFreq,s,0,_PlusInf);
    if WEB_GetContentItem('Amplitude',s) then UpdateTag(tagAmpl,s,0,_PlusInf);
    if WEB_GetContentItem('Noise',s)     then UpdateTag(tagNoise,s,0,_PlusInf);
   end;
   WEB_Reply('<html>');
   WEB_Reply('<head>');
   WEB_MetaRefresh(-1,'');
   WEB_LinkStyleSheet(DefaultCss);
   WEB_Reply('<title>'+FacilityName+': Edit page</title>');
   WEB_Reply('</head>');
   WEB_Reply('<body>');
   WEB_ShowHeader(FacilityName,'Редактор SIN',Access,'');
   WEB_ShowTimeAndOperator;
   WEB_Reply('<span class="big bold mono">Отредактируте параметры SIN:</span>');
   WEB_Reply('<form action="'+WEB.ScriptName+'?action=edit" method="post">');
   WEB_Reply('<span class="bigger bold mono pre">State:    </span>');
   WEB_Reply('<select name="Start" class="mono">');
   if iGetTag(tagStart)=0 then begin
    WEB_Reply('<option selected value="0">OFF (stopped)</option>');
    WEB_Reply('<option          value="1">ON (started)</option>');
   end else begin
    WEB_Reply('<option          value="0">OFF (stopped)</option>');
    WEB_Reply('<option selected value="1">ON (started)</option>');
   end;
   WEB_Reply('</select><br>');
   WEB_Reply('<span class="bigger bold mono pre">Frequency:</span>');
   WEB_Reply('<input type="text" name="Frequency" value="'+Str(rGetTag(tagFreq))+'" class="mono"><br>');
   WEB_Reply('<span class="bigger bold mono pre">Amplitude:</span>');
   WEB_Reply('<input type="text" name="Amplitude" value="'+Str(rGetTag(tagAmpl))+'" class="mono"><br>');
   WEB_Reply('<span class="bigger bold mono pre">Noise:    </span>');
   WEB_Reply('<input type="text" name="Noise" value="'+Str(rGetTag(tagNoise))+'" class="mono"><br>');
   WEB_Reply('<p>');
   WEB_Reply('<input type="Submit" value="Accept" class="bigger bold mono">');
   WEB_Reply('<input type="Reset"  value="Discard" class="bigger bold mono">');
   WEB_Reply('</form>');
   WEB_Reply('<p>');
   WEB_ShowFootNote(Access,WEB.DateTime);
   WEB_Reply('</body>');
   WEB_Reply('</html>');
   WEB_ReplyEnd;
  end else WEB_AccessDeniedPage;
  s:='';
 end;
 {
 General procedure to process HTTP request.
 All HTTP request data is already located in WEB record when Processing called.
 User should add HTML page via WEB_Reply(...) and call WEB_ReplyEnd in the end.
 }
 procedure WEB_Processing;
 begin
  if not WEB_IsRequestMethod('Get,Post')
  then WEB_ErrorPage('Bad RequestMethod='+WEB.RequestMethod) else
  if WEB_IsQueryItem('Action','Login') then WEB_LoginPage else
  if WEB_IsQueryItem('Action','Home')  then WEB_HomePage  else
  if WEB_IsQueryItem('Action','Fetch') then WEB_FetchPage else
  if WEB_IsQueryItem('Action','View')  then WEB_ViewPage  else
  if WEB_IsQueryItem('Action','Edit')  then WEB_EditPage  else
  if WEB_IsQueryItem('Action','Plot')  then WEB_PlotPage  else
  if WEB_IsQueryItem('Action','Echo')  then WEB_EchoPage  else
  WEB_ErrorPage('<p><span class="big bold red">Запрошенная функция не существует.</span><br>'
               +'<p><span class="big bold">Вам надо пройти <a class="big" href="'
               +Web.ScriptName+'?action=login&timestamp='+Str(msecnow-JavaTimeBase)+'">авторизацию</a>.</span><p>');
 end;
 {
 Handle @HTTP_REQUEST_ACCEPTED=ArgList message.
 ArgList is Sender,RequestTime,RequestText,ReplyText.
 Client should analyse RequestText, and put HTML page
 to ReplyText. Last line of ReplyText should be dump(0).
 }
 procedure WEB_HandleRequest(Msg:String);
 var Status:Integer;
 begin
  Status:=WEB_CheckRequest(Msg);
  if Status=HTTP_REQUEST_OK then begin
   if DebugEcho then WEB_EchoPage else WEB_Processing;
  end else
  if Status=HTTP_REQUEST_BAD then WEB_ErrorPage('Invalid HTTP request.');
  WEB_Clear;
 end;
 {
 Clear user application strings...
 }
 procedure ClearApplication;
 begin
  HostName:='';
  winConsole:='';
 end;
 {
 User application Initialization...
 }
 procedure InitApplication;
 begin
  {
  Initialize variables...
  }
  DebugEcho:=False;
  HostName:=ParamStr('ComputerName');
  StdIn_SetTimeouts(0,MaxInt,MaxInt,0);  
  StdIn_SetScripts('@StartupScript','@FinallyScript');
  {
  Initialize tags...
  }
  InitTag(tagStart, 'sin_start', 1);
  InitTag(tagFreq,  'sin_freq',  2);
  InitTag(tagAmpl,  'sin_ampl',  2);
  InitTag(tagNoise, 'sin_noise', 2);
  {
  Draw control window...
  }
  bNul(WinDraw('SIN_CTRL|Top=317|Left=167|Width=400|Height=290'));
  bNul(WinSelect('SIN_CTRL'));
  {
  Copy uses JavaScript library (flot) from Resource to local Utility site.
  Copy uses StyleSheet library (alex) from Resource to local Utility site.
  This libraries are strongly required for WebCgi, so we must copy it.
  }
  WEB_CopyJsLibrary('flot');  // ~~\Resource\Tools\JavaScript\flot  ->  ..\Utility\JavaScript\flot
  WEB_CopyCssLibrary('alex'); // ~~\Resource\Tools\StyleSheet\alex  ->  ..\Utility\StyleSheet\alex
  {
  Read JavaScript from embedded section [fetchDataScript.js].
  This JavaScript used by ViewPage, FetchPage to apply AJAX data transfer.
  }
  fetchScript:=WEB_ReadJsFromPas(text_New,'[fetchDataScript.js]');
 end;
 {
 User application Finalization...
 }
 procedure FreeApplication;
 begin
  WEB_KillJsLibrary('flot');     // Delete local copy ..\Utility\JavaScript\flot
  WEB_KillCssLibrary('alex');    // Delete local copy ..\Utility\StyleSheet\alex 
  bNul(text_Free(fetchScript));  // Free JavaScript text
 end;
 {
 User application Polling...
 }
 procedure PollApplication;
 var s:String; x,y:Real;
 begin
  s:='';
  {
  Generate sin and cos waves periodically.
  }
  if SysTimer_Pulse(WavesPeriod)>0 then
  if igettag(tagStart)>0 then begin
   x:=time;
   y:=rGetTag(tagAmpl)*sin(2*pi*x*rGetTag(tagFreq))+rGetTag(tagNoise)*Random(-1,1);
   bNul(putao(0,x,y));
   y:=rGetTag(tagAmpl)*cos(2*pi*x*rGetTag(tagFreq))+rGetTag(tagNoise)*Random(-1,1);
   bNul(putao(1,x,y));
  end;
  {
  Edit tags...
  }
  if editstate=1 then begin
   if CheckEditTag(tagFreq,s)  then bNul(DevMsg(DevName+' @Frequency='+s+CRLF)>0);
   if CheckEditTag(tagAmpl,s)  then bNul(DevMsg(DevName+' @Amplitude='+s+CRLF)>0);
   if CheckEditTag(tagNoise,s) then bNul(DevMsg(DevName+' @Noise='+s+CRLF)>0);
  end;
  if editstate=1 then begin
   Trouble('Unknown tag edition!');
   s:=edit('');
  end;
  if iand(editstate,9)<>0 then begin
   Trouble('Dialog error detected!');
   s:=edit('');
  end;
  {
  Actions on sensor click...
  }
  if clickbutton=1 then begin
   if IsSameText(clicksensor,'SIN_BROWSE') then begin
    bNul(DevMsg(DevName+' @Browse'+CRLF)>0);
    bNul(Voice(snd_Click));
   end;
   if IsSameText(clicksensor,'SIN_START') then begin
    bNul(DevMsg(DevName+' @Start='+Str(Ord(iGetTag(tagStart)=0))+CRLF)>0);
    bNul(Voice(snd_Click));
   end;
   if IsSameText(clicksensor,'SIN_FREQ') then begin
    StartEditTag(tagFreq,'Sin frequency');
    bNul(Voice(snd_Click));
   end;
   if IsSameText(clicksensor,'SIN_AMPL') then begin
    StartEditTag(tagAmpl,'Sin amplitude');
    bNul(Voice(snd_Click));
   end;
   if IsSameText(clicksensor,'SIN_NOISE') then begin
    StartEditTag(tagNoise,'Sin noise');
    bNul(Voice(snd_Click));
   end;
   if IsSameText(clicksensor,'SIN_WAVE1')
   or IsSameText(clicksensor,'SIN_WAVE2') then begin
    bNul(WinDraw('SIN_PLOT|Top=317|Left=167|Width=600|Height=400'));
    bNul(WinSelect('SIN_PLOT'));
    bNul(Voice(snd_Click));
   end;
  end;
  s:='';
 end;
 {
 Process data coming from standard input...
 }
 procedure StdIn_Processor(var Data:String);
 var cmd,arg:String;
 begin
  if iAnd(DebugFlags,dfViewImp)<>0 then ViewImp('CON: '+Data);
  {
  "@cmd=arg" or "@cmd args" commands:
  }
  cmd:='';
  arg:='';
  if GotCommand(Data,cmd,arg) then begin
   {
   Example: @HTTP_REQUEST_ACCEPTED=&WEBSRV,63295844422438,1049397,1049374
   }
   if IsSameText(cmd,HTTP_REQUEST_ACCEPTED_CMD) then begin
    WEB_HandleRequest(Data);
    Data:='';
   end else
   {
   Example: @PlotSrv-Done ..\Bitmaps\web_plot.gif
   Message coming after success WEB_PlotPage
   }
   if IsSameText(cmd,'@PlotSrv-Done') then begin
    Success(Data);
    Data:='';
   end else
   {
   Example: @PlotSrv-Fail ..\Bitmaps\web_plot.gif
   Message coming after failed WEB_PlotPage
   }
   if IsSameText(cmd,'@PlotSrv-Fail') then begin
    Trouble(Data);
    Data:='';
   end else
   {
   Example: @Browse http://localhost/
   }
   if IsSameText(cmd,'@Browse') then begin
    rNul(DevMsg('&WebSrv @Browse '+arg+CRLF));
    Data:='';
   end else
   {
   Example: @Start 1
   }
   if IsSameText(cmd,'@Start') then begin
    if not IsNan(rVal(arg)) then bNul(iSetTag(tagStart,Ord(rVal(arg)>0)));
    Success(cmd+'='+Str(iGetTag(tagStart)));
    Data:='';
   end else
   {
   Example: @Frequency 3.14
   }
   if IsSameText(cmd,'@Frequency') then begin
    if not IsNan(rVal(arg)) then bNul(rSetTag(tagFreq,rVal(arg)));
    Success(cmd+'='+Str(rGetTag(tagFreq)));
    Data:='';
   end else
   {
   Example: @Amplitude 2.5
   }
   if IsSameText(cmd,'@Amplitude') then begin
    if not IsNan(rVal(arg)) then bNul(rSetTag(tagAmpl,rVal(arg)));
    Success(cmd+'='+Str(rGetTag(tagAmpl)));
    Data:='';
   end else
   {
   Example: @Noise 0.1
   }
   if IsSameText(cmd,'@Noise') then begin
    if not IsNan(rVal(arg)) then bNul(rSetTag(tagNoise,rVal(arg)));
    Success(cmd+'='+Str(rGetTag(tagNoise)));
    Data:='';
   end else
   {
   Handle other commands by default handler
   }
   StdIn_DefaultHandler(Data,cmd,arg);
  end;
  Data:='';
  cmd:='';
  arg:='';
 end;

{***************************************************}
{***************************************************}
{***                                             ***}
{***  MMM    MMM        AAA   IIII   NNN    NN   ***}
{***  MMMM  MMMM       AAAA    II    NNNN   NN   ***}
{***  MM MMMM MM      AA AA    II    NN NN  NN   ***}
{***  MM  MM  MM     AA  AA    II    NN  NN NN   ***}
{***  MM      MM    AAAAAAA    II    NN   NNNN   ***}
{***  MM      MM   AA    AA   IIII   NN    NNN   ***}
{***                                             ***}
{***************************************************}
{$I _std_main}{*** Please never change this code ***}
{***************************************************}
