!INCLUDE GW.bas

GW_VER$ = "v1.9"
!' This is the 'GW' include file for RFO-BASIC! for Android.
!' It allows to easily create nice GUIs with Web technologies.
!'
!' Written by Nicolas MOUGIN mougino@free.fr http://mougino.free.fr
!' You can use, modify, and redistribute this file without restriction.
!'
!' Important notes for the programer:
!'      1. You need a theme to render GW apps. Currently available are 9 possible GW themes:
!'      "default" (the default one), "flat-ui", "classic", "ios", "bootstrap", "android-holo", "square-ui",
!'      "metro", and finally the "native-droid-*" family. See the GW_demo > Theme section for more info.
!'
!'      Existence or not of theme files on the device can be checked with GW_THEME_EXISTS().
!'      If not existing, a theme can be downloaded (HTTP) from mougino's server with GW_DOWNLOAD_THEME().
!'      You can handle theme check and download yourself in your GW app, or you can let the lib deal with it.
!'      In this last case, usage of a missing theme will show a download popup. Whether user proceeds to download
!'      or decline, the GW app will in any case exit and have to be restarted by the user to take the new theme
!'      files into account. This can be avoided if you handle theme check + download yourself.
!'      
!'      You can modify the default theme for all your apps by changing this line (in GW.bas below):
!'          BUNDLE.PUT global, "theme", "default" %' <-- change if you want another theme by default
!'
!'      2. GW_LOAD_THEME() must be called before the page creation with GW_NEW_PAGE(), or else the page 
!'      will not inherit the theme. It is also good practice to call GW_UNLOAD_THEME() right after
!'      the GW_RENDER() of the page, in order for the next created page to not inherit inadvertently
!'      the theme of the previous page...
!'
!'      3. All the GW_ADD_* functions can be invoked as is (inline), or be called prefixed with a
!'      variable and the equal sign, in this case the variable will contain a pointer to the newly
!'      created control...  So, either use
!'              GW_ADD_BUTTON (mypage, "Button 1", "www.rfo-basic.com")
!'      or      mybtn = GW_ADD_BUTTON (mypage, "Button 1", "www.rfo-basic.com")
!'      It all depends if you want to change the content of the control after creation thanks to
!'      GW_MODIFY(), or track the behavior of the control with GW_GET_VALUE(), etc.
!'
!'      4. Controls (or page elements: titlebar, panel) need to be CUSTOmized *before* being ADDed
!'      on the page. Call GW_NEW_THEME_CUSTO() + GW_USE_THEME_CUSTO(), or GW_USE_THEME_CUSTO_ONCE()
!'      *before* GW_ADD_CONTROL().
!'
!'      5. The following functions: GW_GET_VALUE() GW_GET_VALUE$() GW_FLIPSWITCH_CHANGED() 
!'      GW_CHECKBOX_CHECKED() GW_RADIO_SELECTED() can either be used after a GW_WAIT_ACTION$(),
!'      to parse and analyze the user interaction with the GW page when the user validates it,
!'      or at any other moment if you want the live state of a control (CHECKBOX, RADIO, SLIDER,
!'      SELECTBOX, all the INPUT* controls...)
!'      If you want to track the change of a control in real-time, use GW_ADD_LISTENER()
!'
!'      6. To create *related* RADIO buttons, where only one among the buttons can be checked, first
!'      create the 'parent' by passing a zero value into the 2nd parameter 'radio_parent':
!'          parent = GW_ADD_RADIO (mypage, 0, "My radio button 1")
!'      and then ADD the following RADIO buttons with the 'parent' variable as 2nd parameter:
!'          child1 = GW_ADD_RADIO (mypage, parent, "My radio button 2")
!'          child2 = GW_ADD_RADIO (mypage, parent, "My radio button 3")   etc.
!'
!'      7. Use the greater than character ">" in your FLIPSWITCH, CHECKBOX and RADIO option labels
!'      in order to select this option by default e.g. GW_ADD_FLIPSWITCH(mypage, "Switch:", "Off", ">On")
!'      By default, FLIPSWITCH have the first option selected, and CHECKBOX and RADIO are unselected.
!'
!'      8. The functions GW_MODIFY() and GW_AMODIFY() ('A' for Array) need to be called *after* the
!'      GW_RENDER() of the page that contains the control to be modified. Because the control does
!'      not exist before rendering the page.
!'
!' Complete list of APIs:
!'      ! --> load a theme before page creation:
!'      theme_name$ = GW_THEME$[1] % ..up to GW_THEME$[9] see list at http://mougino.free.fr/tmp/GW/
!'      test = GW_THEME_EXISTS (theme_name$) % return true|false if full set of theme' files are on device
!'      GW_DOWNLOAD_THEME (theme_name$) % download all theme files to device
!'      GW_LOAD_THEME (theme_name$) % load a theme to be used by all newly created pages
!'      GW_UNLOAD_THEME () % equivalent to GW_LOAD_THEME ("default")
!'
!'      ! --> create a new page:
!'      mypage = GW_NEW_PAGE ()
!'
!'      ! --> transform the page:
!'      GW_USE_FONT (mypage, "localfont.ttf")
!'      GW_CENTER_PAGE_VER (mypage) % to center vertically the page content
!'      GW_SET_TRANSITION (mypage | mypanel | my_dialog_message, transition$)
!'      :CONTROL        :VALUES
!'      :PAGE           :fade|pop|flip|turn|flow|slidefade|slide|slideup|slidedown|none
!'      :PANEL          :push|reveal|overlay
!'      :DIALOG_MESSAGE :idem PAGE
!'
!'      ! --> change layout of controls before adding them:
!'      GW_OPEN_GROUP (mypage) % to visually group checkbox or radio control
!'      GW_CLOSE_GROUP (mypage)
!'      GW_START_CENTER (mypage) % to visually center elements
!'      GW_STOP_CENTER (mypage)
!'
!'      ! --> apply customization to controls:
!'      GW_USE_THEME_CUSTO_ONCE ("param1=value1 param2=value2 ...")
!'      mycusto = GW_NEW_THEME_CUSTO ("param1=value1 param2=value2 ...")
!'      GW_USE_THEME_CUSTO (mycusto)
!'      GW_RESET_THEME_CUSTO ()
!'      :PARAM      :VALUES
!'      :color      :a|b|c|d|e|f|g (depending on theme)
!'      :icon       :see http://demos.jquerymobile.com/1.4.5/icons/#Iconset
!'      :iconpos    :left|right|top|bottom|notext
!'      :inline     :<no value needed>
!'
!'      ! --> add standard controls:
!'      mybar$ = GW_ADD_BAR_LBUTTON$ ("L-Button>ACTION1")
!'      mybar$ += GW_ADD_BAR_TITLE$ ("My titlebar / footbar")
!'      mybar$ += GW_ADD_BAR_RBUTTON$ ("R-Button>ACTION2")
!'      GW_ADD_TITLEBAR (mypage, mybar$)
!'      GW_ADD_FOOTBAR (mypage, mybar$)
!'      GW_ADD_PANEL (mypage, "My panel content")
!'      GW_ADD_DIALOG_MESSAGE (mypage, "Title", "Message", buttons_and_actions$[])
!'      GW_ADD_IMAGE (mypage, "mypicture.png") % use '>' after pic name for hyperlink e.g. "exit.png>BYE"
!'      myicon = GW_ADD_ICON (mypage, ico$, width, height)
!'      GW_ICON$ (myicon)
!'      GW_ADD_LISTVIEW (mypage, values_and_actions$[]) % use '#' for ordered list, use '>' for title/separator
!'      GW_ADD_TABLE (mypage, n_cols, table$[]) % use '>' in the first element to indicate a title line
!'      GW_ADD_VIDEO (mypage, link_to_video$)
!'      GW_ADD_TITLE (mypage, "My section title")
!'      GW_ADD_TEXTBOX (mypage, s_ini$)
!'      GW_ADD_TEXT (mypage, s_ini$)
!'      GW_ADD_LINK (mypage, "My link label", "http://www.mylink.com | USER_ACTION")
!'      GW_ADD_BUTTON (mypage, "My button label", "http://www.mylink.com | USER_ACTION")
!'      GW_SHOW_PANEL$ (mypanel) % use it as a link in GW_ADD_LINK() or GW_ADD_BUTTON()
!'      GW_SHOW_DIALOG_MESSAGE$ (my_dlg_msg) % idem
!'
!'      ! --> add user input controls:
!'      GW_ADD_INPUTLIST (mypage, "Hint message", values_and_actions$[])
!'      GW_ADD_SELECTBOX (mypage, "My selectbox", values$[])
!'      GW_ADD_CHECKBOX (mypage, "My checkbox") % use ">" to check by default
!'      GW_ADD_RADIO (mypage, radio_parent, "My radio button") % use ">" to select by default
!'      GW_ADD_FLIPSWITCH (mypage, "My flip switch", s_opt1$, s_opt2$) % use ">" to select default option
!'      GW_ADD_SLIDER (mypage, "My slider label", n_min, n_max, n_step, n_ini)
!'      GW_ADD_INPUTLINE (mypage, "My input line label", s_ini$)
!'      GW_ADD_INPUTBOX (mypage, "My input box label", s_ini$)
!'      GW_ADD_INPUTDATETIME (mypage, "Input Date and Time", s_ini$)
!'      GW_ADD_INPUTDATE (mypage, "Input Date", s_ini$)
!'      GW_ADD_INPUTTIME (mypage, "Input Time", s_ini$)
!'      GW_ADD_INPUTMONTH (mypage, "Input Month", s_ini$)
!'      GW_ADD_INPUTWEEK (mypage, "Input Week", s_ini$)
!'      GW_ADD_INPUTURL (mypage , "Input URL", s_ini$)
!'      GW_ADD_INPUTEMAIL (mypage, "Input eMail", s_ini$)
!'      GW_ADD_INPUTCOLOR (mypage, "Input Color", s_ini$)
!'      GW_ADD_INPUTNUMBER (mypage, "Input Number", s_ini$)
!'      GW_ADD_INPUTTEL (mypage , "Input Tel", s_ini$)
!'      GW_ADD_INPUTPASSWORD (mypage, "Input Password", s_ini$)
!'      GW_ADD_INPUTFILE (mypage, "Input File", s_ini$)
!'      GW_ADD_SUBMIT (mypage, "My submit button label")
!'
!'      ! --> add advanced stuff (custom control, listener):
!'      GW_INJECT_HTML (mypage, "<some>code</some>") % add custom HTML|CSS|JavaScript code
!'      GW_ADD_LISTENER (mypage, ctl_id, event$, action$) % event$ = "change", "click", "clear"...
!'
!'      ! --> render and interact with the page:
!'      GW_RENDER (mypage)
!'      GW_WAIT_ACTION$ ()
!'      GW_SHOW_DIALOG_MESSAGE (my_dlg_msg) % display the dialog message manually
!'      GW_SHOW_PANEL (my_panel) % display the panel manually
!'      GW_GET_VALUE$ (ctl_id)
!'      GW_GET_VALUE (ctl_id)
!'      ctl_name$ = GW_ID$ (ctl_id)
!'      ctl_id = GW_ID (ctl_name$)
!'      ctl_id = GW_LAST_ID ()
!'      test = GW_CHECKBOX_CHECKED (ctl_id) % to test if a checkbox is checked
!'      test = GW_RADIO_SELECTED (ctl_id) % to test if a radio button is selected
!'      test = GW_FLIPSWITCH_CHANGED (ctl_id, s_opt1$)
!'      GW_MODIFY (ctl_id, key$, "new value")
!'      GW_AMODIFY (ctl_id, key$, new_values$[]) % Array-Modify
!'      :CONTROL (GW_MODIFY)   :KEYS                   :VALUES
!'      :TITLEBAR              :lbutton|title|rbutton  :
!'      :FOOTBAR               :lbutton|title|rbutton  :
!'      :CHECKBOX              :checked                :"0"|"1"
!'      :FLIPSWITCH            :selected               :s_opt1$|s_opt2$
!'      :RADIO                 :selected               :"0"|"1"
!'      :SLIDER                :val|min|max|step       :
!'      :TABLE                 :content                :
!'      :IMAGE                 :content                :
!'      :DIALOG_MESSAGE        :text|title             :
!'      :LINK                  :text|link              :
!'      :BUTTON                :text|link              :
!'      :TITLE                 :text                   :
!'      :TEXTBOX               :text                   :
!'      :TEXT                  :text                   :
!'      :INPUT*                :text                   :
!'      :SUBMIT                :text                   :
!'
!'      :CONTROL (GW_AMODIFY)   :KEYS                  :VALUES 
!'      :LISTVIEW               :content               :array$[]
!'      :TABLE                  :content               :array$[]
!'      :SELECTBOX              :content               :array$[]
!'      :INPUTLIST              :list                  :array$[]
!'      :DIALOG_MESSAGE         :buttons               :array$[]
!'
!'      ! --> other special functions:
!'      GW_LINK$ ("http://mylink.com") % add a final ">" to open link in new tab
!'      GW_DUMP_TO_FILE (mypage, "myfile.html")
!'      GW_DUMP (mypage) %' print page content to console
!'      GW_CODE_HIGHLIGHT$ (raw_code$, black$[], blue$[], red$[])
!'
!'      ! --> functions aliases and shortcuts:
!'      :GW FUNCTION:ALIAS:SHORTCUT
!'      :GW_THEME_EXISTS():GwThemeExists():gwte()
!'      :GW_DOWNLOAD_THEME():GwDownloadTheme():gwdt()
!'      :GW_LOAD_THEME():GwLoadTheme():gwlt()
!'      :GW_UNLOAD_THEME():GwUnloadTheme():gwut()
!'      :GW_NEW_PAGE():GwNewPage():gwnp()
!'      :GW_USE_FONT():GwUseFont():gwuf()
!'      :GW_SET_TRANSITION():GwSetTransition():gwst()
!'      :GW_ADD_DIALOG_MESSAGE():GwAddDialogMessage():gwadm()
!'      :GW_SHOW_DIALOG_MESSAGE$():GwShowDialogMessage$():gwsdm$()
!'      :GW_SHOW_DIALOG_MESSAGE():GwShowDialogMessage():gwsdm()
!'      :GW_ADD_BAR_TITLE$():GwAddBarTitle$():gwabt$()
!'      :GW_ADD_BAR_LBUTTON$():GwAddBaLButton$():gwablb$()
!'      :GW_ADD_BAR_RBUTTON$():GwAddBarRButton$():gwabrb$()
!'      :GW_ADD_TITLEBAR():GwAddTitleBar():gwatib()
!'      :GW_ADD_FOOTBAR():GwAddFootBar():gwafb()
!'      :GW_ADD_PANEL():GwAddPanel():gwap()
!'      :GW_SHOW_PANEL$():GwShowPanel$():gwsp$()
!'      :GW_SHOW_PANEL():GwShowPanel():gwsp()
!'      :GW_START_CENTER():GwStartCenter():gwstac()
!'      :GW_STOP_CENTER():GwStopCenter():gwstoc()
!'      :GW_CENTER_PAGE_VER():GwCenterPageVer():gwcpv()
!'      :GW_OPEN_GROUP():GwOpenGroup():gwog()
!'      :GW_CLOSE_GROUP():GwCloseGroup():gwcg()
!'      :GW_NEW_THEME_CUSTO():GwNewThemeCusto():gwntc()
!'      :GW_USE_THEME_CUSTO():GwUseThemeCusto():gwutc()
!'      :GW_USE_THEME_CUSTO_ONCE():GwUseThemeCustoOnce():gwutco()
!'      :GW_RESET_THEME_CUSTO():GwResetThemeCusto():gwrtc()
!'      :GW_ADD_LISTVIEW():GwAddListView():gwalv()
!'      :GW_ADD_IMAGE():GwAddImage():gwaimg()
!'      :GW_ICON$():GwIcon$():gwico$()
!'      :GW_ADD_ICON():GwAddIcon():gwaico()
!'      :GW_ADD_TABLE():GwAddTable():gwata()
!'      :GW_ADD_VIDEO():GwAddVideo():gwav()
!'      :GW_ADD_BUTTON():GwAddButton():gwab()
!'      :GW_ADD_LINK():GwAddLink():gwalnk()
!'      :GW_ADD_TITLE():GwAddTitle():gwati()
!'      :GW_ADD_TEXT():GwAddText():gwate()
!'      :GW_ADD_TEXTBOX():GwAddTextBox():gwateb()
!'      :GW_ADD_FLIPSWITCH():GwAddFlipSwitch():gwafs()
!'      :GW_ADD_INPUTLIST():GwAddInputList():gwails()
!'      :GW_ADD_SELECTBOX():GwAddSelectBox():gwasb()
!'      :GW_ADD_RADIO():GwAddRadio():gwar()
!'      :GW_ADD_CHECKBOX():GwAddCheckBox():gwac()
!'      :GW_ADD_SLIDER():GwAddSlider():gwasl()
!'      :GW_ADD_INPUTLINE():GwAddInputLine():gwailn()
!'      :GW_ADD_INPUTDATETIME():GwAddInputDateTime():gwaidt()
!'      :GW_ADD_INPUTDATE():GwAddInputDate():gwaid()
!'      :GW_ADD_INPUTTIME():GwAddInputTime():gwaiti()
!'      :GW_ADD_INPUTMONTH():GwAddInputMonth():gwaim()
!'      :GW_ADD_INPUTWEEK():GwAddInputWeek():gwaiw()
!'      :GW_ADD_INPUTURL():GwAddInputUrl():gwaiu()
!'      :GW_ADD_INPUTEMAIL():GwAddInputEmail():gwaie()
!'      :GW_ADD_INPUTCOLOR():GwAddInputColor():gwaic()
!'      :GW_ADD_INPUTNUMBER():GwAddInputNumber():gwain()
!'      :GW_ADD_INPUTTEL():GwAddInputTel():gwaite()
!'      :GW_ADD_INPUTPASSWORD():GwAddInputPassword():gwaip()
!'      :GW_ADD_INPUTFILE():GwAddInputFile():gwaif()
!'      :GW_ADD_INPUTBOX():GwAddInputBox():gwaib()
!'      :GW_ADD_SUBMIT():GwAddSubmit():gwasu()
!'      :GW_RENDER():GwRender():gwr()
!'      :GW_WAIT_ACTION$():GwWaitAction$():gww$()
!'      :GW_GET_VALUE():GwGetValue():gwg()
!'      :GW_GET_VALUE$():GwGetValue$():gwg$()
!'      :GW_CHECKBOX_CHECKED():GwCheckBoxChecked():gwcc()
!'      :GW_RADIO_SELECTED():GwRadioSelected():gwrs()
!'      :GW_FLIPSWITCH_CHANGED():GwFlipSwitchChanged():gwfc()
!'      :GW_MODIFY():GwModify():gwm()
!'      :GW_AMODIFY():GwAModify():gwam()
!'      :GW_ID$():GwId$():gwid$()
!'      :GW_DUMP():GwDump():gwd()
!'      :GW_DUMP_TO_FILE():GwDumpToFile():gwdtf()
!'      :GW_INJECT_HTML():GwInjectHtml():gwih()
!'      :GW_ADD_LISTENER():GwAddListener():gwali()
!'      :GW_ENABLE_LISTENER():GwEnableListener():gwel()
!'      :GW_CODE_HIGHLIGHT$():GwCodeHighlight$():gwch$()
!'
!' TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
!' * fontawesome info msg, warning, GW_ADD_ICON, etc.
!' * native date picker has prehistoric look: GitHub issue #179
!' * cable INPUTFILE
!' * GWbuilder?
!' TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
!'
!' Changelog:
!' [v1.9] 18-DEC-2015
!'      * /!\ Removed the GW_FORCE_MODE() function, now obsolete since the "grey circle" fix in GW lib v1.8
!'      * /!\ Added support for Back key: now it doesn't stop the lib anymore but returns "BACK" in GW_WAIT_ACTION$()
!'      * Added GW_THEME_EXISTS() and GW_DOWNLOAD_THEME() to allow theme files to be downloaded programmatically
!'      * Enhanced low-level handling of missing themes: there is now a popup proposing to automatically download files
!'      * Cleaned-up the "Important notes" in the header of the lib
!' [v1.8] 14-DEC-2015
!'      * Added a script that fix grey circle issue for Android System WebView > 44.0.2403.117
!' [v1.7] 29-NOV-2015
!'      * Added GW_MODIFY() of the "title" and "text" of a DIALOG_MESSAGE
!'      * Added GW_MODIFY() of a "selected" FLIPSWITCH option (s_opt1$ or s_opt2$)
!' [v1.6] 13-JUN-2015
!'      * /!\ Renamed GW_ADD_TITLE$() to GW_ADD_BAR_TITLE$() ; renamed GW_ADD_LEFT_BUTTON$() to GW_ADD_BAR_LBUTTON$() ;
!'        and finally renamed GW_ADD_RIGHT_BUTTON$() to GW_ADD_BAR_RBUTTON$()
!'      * Fixed a bug when GW_MODIFYing a new content with double quotes and/or single quotes in it (esp. in a TABLE)
!'      * Added a new control: GW_ADD_IMAGE() to display an image (with an hyperlink option)
!'      * Added a whole new set of functions for all the GW_ADD_*(page, ...) functions: GW_ADD_*$(...) (1 less parameter)
!'        returns the string result of the function without adding it to the page. E.g. GW_ADD_TEXT(p,t$) -> GW_ADD_TEXT$(t$)
!'      * Added function GW_LAST_ID() (no argument) to get the Id of the last control created with GW_ADD_*$(...)
!'      * Added function GW_ID(ctl_name$) to get the Id of a control known only from its name
!'      * Added function GW_USE_FONT() to make use of a local font (TTF or other)
!'      * Added GW_ENABLE_LISTENER() to enable listener of dynamically created content, typically after a GW_MODIFY/GW_AMODIFY
!'      * Added support of GW_MODIFY for TITLEBARs and FOOTBARs, see the corresponding changeable keys in the cheatsheet
!'      * Improved GW_ADD_TITLEBAR/FOOTBAR/DIALOG_MESSAGE/PANEL: they can be added anytime even after creating some controls
!' [v1.5] 07-MAY-2015
!'      * Fixed creation of *linked* listviews with GW_ADD_LISTVIEW(), the links now work from the start
!'      * Added aliases / shortcuts for all GW functions, shorter and easier to write from mobile device
!' [v1.4] 21-APR-2015
!'      * Added a new control: GW_ADD_LISTVIEW() based on the work from forum user Gyula
!'      * Fixed an Android 5.0 bug when setting GW_SET_TRANSITION() of a page without controls
!' [v1.3] 12-FEB-2015
!'      * Added GW_ADD_FOOTBAR() counterpart of a TITLEBAR but at the bottom of the page
!'      * Added 3 new functions to build a TITLEBAR or FOOTBAR: GW_ADD_LEFT_BUTTON$() GW_ADD_TITLE$() GW_ADD_RIGHT_BUTTON$()
!'      * Added a new control: GW_ADD_ICON() that allows with GW_ICON$() to add custom icons in TITLEBAR or FOOTBAR
!'      * Added function GW_ADD_LISTENER() that triggers an action when a certain event occurs on a control
!'      * Improved GW_GET_VALUE() and GW_GET_VALUE$() to retrieve the live content of a control! (without submit)
!' [v1.2] 15-JAN-2015
!'      * Added new standard control GW_ADD_TABLE() to make tables with (">") or w/o a title line
!'      * Added GW_AMODIFY() (ARRAY-MODIFY) for controls taking an array as a parameter: TABLE, INPUTLIST,
!'        SELECTBOX and DIALOG_MESSAGE
!' [v1.1] 14-JAN-2015
!'      * Added GW_SHOW_DIALOG_MESSAGE() to display a dialog message manually
!'      * Added GW_SHOW_PANEL() to open a panel manually
!'      * Added GW_MODIFY() of the state of a CHECKBOX and of a RADIO button
!'      * Added GW_SET_TRANSITION() to change the transition animation of DIALOG_MESSAGE, PAGE, or PANEL
!'      * Added GW_ADD_INPUTDATETIME() as a workaround for the INPUTTIME bug on Android Lollipop
!'        ( see https://code.google.come/p/chromium/issues/detail?id=434695 )
!' [v1.0] 12-JAN-2015
!'      * Added support of videos! both local or online with GW_ADD_VIDEO()
!'      * Added 2 new user input controls: GW_ADD_INPUTLIST() and GW_ADD_SELECTBOX()
!'      * Added GW_MODIFY() to modify properties of already ADDed controls
!'      * Removed GW_SET_CONTENT(), the functionality of which is now merged (and extended) in GW_MODIFY()
!' [v0.9] 11-JAN-2015
!'      * Added a new page element: GW_ADD_DIALOG_MESSAGE() and its 'trigger' link GW_SHOW_DIALOG_MESSAGE$()
!'      * Added function GW_CENTER_PAGE_VER() to center vertically the page content
!'      * Added GW_PREVENT_LANDSCAPE() and GW_PREVENT_PORTRAIT(), undocumented because HTML.ORIENTATION is prefered
!' [v0.8] 08-JAN-2015
!'      * Fixed the usage of GW_USE_THEME_CUSTO_ONCE() for a first control in the page
!'      * Fixed the possibility to enter a decimal number with GW_ADD_INPUTNUMBER()
!'      * Added 2 functions to be used after GW_WAIT_ACTION$(): GW_CHECKBOX_CHECKED() and GW_RADIO_SELECTED()
!'      * Added GW_LINK$() to embed a link into a string used in a control (TEXTBOX, TEXT, TITLE, etc.)
!'      * Created a GW APis cheat sheet available at http://mougino.free.fr/tmp/GW/cheatsheet.html
!' [v0.7] 06-JAN-2015
!'      * Fixed GW_GET_VALUE() of an empty control, it now returns 0 (zero)
!'      * Added GW_INJECT_HTML() to add custom HTML/CSS/JavaScript code to the page
!'      * Added GW_START_CENTER() and GW_STOP_CENTER() to center elements on the page
!' [v0.6] 04-JAN-2015
!'      * Changed the number of parameters of GW_ADD_INPUTBOX(): n-rows and n-cols are no longer needed
!'      * Fixed the rendering of the "native-droid-*" theme family
!'      * Fixed inline comments highlighting with GW_CODE_HIGHLIGHT$()
!'      * Added GW_OPEN_GROUP() and GW_CLOSE_GROUP() to visually group CHECKBOX or RADIO controls
!'      * Added 11 new user input controls: GW_ADD_INPUTDATE(), GW_ADD_INPUTTIME(), GW_ADD_INPUTMONTH(),
!'        GW_ADD_INPUTWEEK(), GW_ADD_INPUTURL(), GW_ADD_INPUTEMAIL(), GW_ADD_INPUTCOLOR(), GW_ADD_INPUTNUMBER(),
!'        GW_ADD_INPUTTEL(), GW_ADD_INPUTPASSWORD(), GW_ADD_INPUTFILE()
!'      * Added a 'reset' button (X) to the input controls that support it = INPUTLINE and the 11 new controls
!'      * Added the compatibility mode FORCE_MODE(1) for Android devices that otherwise show empty GW pages
!' [v0.5] 31-DEC-2014
!'      * Added full support for the "native-droid-*" theme family, composed of
!'        10 themes: 5 colors blue/green/purple/red/yellow in 2 flavours light/dark (recommended)
!'      * Added full support for the "square-ui" theme (recommended)
!'      * Added limited support for the "android-holo" theme (deprecated, not recommended)
!'      * Added limited support for the "metro" theme (deprecated, not recommended)
!' [v0.4] 30-DEC-2014
!'      * Added 2 new input controls: GW_ADD_CHECKBOX() and GW_ADD_RADIO()
!'      * Fixed and improved the rendering of the themes
!'      * Added full support for the "bootstrap" theme (recommended)
!'      * Added limited support for the "iOS" theme (deprecated, not recommended)
!' [v0.3] 29-DEC-2014
!'      * Added themes and theme-customization! persistent or 1-shot (GW_USE_THEME_CUSTO /.._ONCE)
!'      * Added full support for the "flat-ui" theme (recommended)
!'      * Added limited support for the "classic" jQuery Mobile theme (deprecated, not recommended)
!'      * Added initial selection of FLIPSWITCH second state (s_opt2$) if it begins with ">"
!' [v0.2] 28-DEC-2014
!'      * Renamed the lib to 'GW' (GUI-Web)
!'      * Created GW_demo.bas
!'      * Added 3 new standard controls: GW_ADD_BUTTON() GW_ADD_LINK() and GW_ADD_TEXT()
!'      * Added 3 new input controls: GW_ADD_FLIPSWITCH(), GW_ADD_INPUTLINE() and GW_ADD_INPUTBOX()
!'      * Added a new page element: GW_ADD_PANEL() and its 'trigger' link GW_SHOW_PANEL$()
!'      * Added GW_GET_VALUE() -> returns a number (Vs GW_GET_VALUE$() returns a string)
!'      * Added GW_CODE_HIGHLIGHT$() for syntax highlighting
!'      * Renamed all GW_NEW* control creation functions to GW_ADD_*
!'      * Renamed GW_SET_SECTION_TEXT() to GW_SET_CONTENT()
!'      * GW_GET_VALUE() GW_GET_VALUE$() and GW_SET_CONTENT() now take only 1 param (ctl_id)
!'      * SLIDER control now takes an extra parameter: n_step
!' [v0.1] 24-DEC-2014
!'      * Initial release

HTML.OPEN 0 %' hide status bar, else JQM header is masked (bug)

ARRAY.LOAD GW_THEME$[], "default", "flat-ui", "classic", "ios", ~
  "bootstrap", "android-holo", "square-ui", "metro", "native-droid"

LIST.CREATE s, GW_PGE %' string list pointer of GW pages = #1
LIST.CREATE s, GW_CTL %' string list pointer of GW controls = #2
LIST.CREATE s, GW_THC %' string list pointer of GW theme-customizations = #3
LIST.CREATE n, GW_RAP %' number list pointer of GW radio parents = #4
LIST.CREATE n, GW_TBL %' number list pointer of GW table columns = #5

BUNDLE.CREATE global %' 'global' bundle pointer = #1
BUNDLE.PUT global, "theme", "default" %' <-- change if you want another theme by default
BUNDLE.PUT global, "theme-custo", 0
BUNDLE.PUT global, "theme-custo-token", 0 %' zero token = no customization
BUNDLE.PUT global, "page-transition", "slide" %' fade|pop|flip|turn|flow|slidefade|slide|slideup|slidedown|none
BUNDLE.PUT global, "panel-transition", "push" %' push|reveal|overlay
BUNDLE.PUT global, "dlgmsg-transition", "pop" %' fade|pop|flip|turn|flow|slidefade|slide|slideup|slidedown|none
BUNDLE.PUT global, "theme-1-files", "basic.js, jquery-2.1.1.min.js, jquery.mobile-1.4.5.min.css, jquery.mobile-1.4.5.min.js, styles.css"
BUNDLE.PUT global, "theme-2-files", "flatui/jquery.mobile.flatui.css, flatui/fonts/Flat-UI-Icons-24.ttf, flatui/fonts/Flat-UI-Icons-24.woff, flatui/fonts/lato-black.ttf, flatui/fonts/lato-black.woff, flatui/fonts/lato-bold.ttf, flatui/fonts/lato-bold.woff, flatui/fonts/lato-italic.ttf, flatui/fonts/lato-italic.woff, flatui/fonts/lato-regular.ttf, flatui/fonts/lato-regular.woff, flatui/images/ajax-loader.gif, flatui/images/icons-18-black.png, flatui/images/icons-18-white.png, flatui/images/icons-36-black.png, flatui/images/icons-36-white.png"
BUNDLE.PUT global, "theme-3-files", "basic.js, jquery-2.1.1.min.js, jquery.mobile-1.4.5.min.css, jquery.mobile-1.4.5.min.js, styles.css, theme-classic.css"
BUNDLE.PUT global, "theme-4-files", "ios/ios.css, ios/jquery-1.7.1.min.js, ios/jquery.mobile-1.2.0.min.css, ios/jquery.mobile-1.2.0.min.js, ios/images/ajax-loader.gif, ios/images/arrow_right.png, ios/images/arrow_right@2x.png, ios/images/backButtonSprite.png, ios/images/backButtonSprite@2x.png, ios/images/icons-18-black.png, ios/images/icons-18-white.png, ios/images/icons-36-black.png, ios/images/icons-36-white.png, ios/images/iconSprite.png, ios/images/tabSprite.png, ios/images/tick.png, ios/images/tiling_stripes.gif"
BUNDLE.PUT global, "theme-5-files", "bootstrap/Bootstrap.min.css, bootstrap/images/ajax-loader.gif, bootstrap/images/icons-png/action-black.png, bootstrap/images/icons-png/action-white.png, bootstrap/images/icons-png/alert-black.png, bootstrap/images/icons-png/alert-white.png, bootstrap/images/icons-png/arrow-d-black.png, bootstrap/images/icons-png/arrow-d-l-black.png, bootstrap/images/icons-png/arrow-d-l-white.png, bootstrap/images/icons-png/arrow-d-r-black.png, bootstrap/images/icons-png/arrow-d-r-white.png, bootstrap/images/icons-png/arrow-d-white.png, bootstrap/images/icons-png/arrow-l-black.png, bootstrap/images/icons-png/arrow-l-white.png, bootstrap/images/icons-png/arrow-r-black.png, bootstrap/images/icons-png/arrow-r-white.png, bootstrap/images/icons-png/arrow-u-black.png, bootstrap/images/icons-png/arrow-u-l-black.png, bootstrap/images/icons-png/arrow-u-l-white.png, bootstrap/images/icons-png/arrow-u-r-black.png, bootstrap/images/icons-png/arrow-u-r-white.png, bootstrap/images/icons-png/arrow-u-white.png, bootstrap/images/icons-png/audio-black.png, bootstrap/images/icons-png/audio-white.png, bootstrap/images/icons-png/back-black.png, bootstrap/images/icons-png/back-white.png, bootstrap/images/icons-png/bars-black.png, bootstrap/images/icons-png/bars-white.png, bootstrap/images/icons-png/bullets-black.png, bootstrap/images/icons-png/bullets-white.png, bootstrap/images/icons-png/calendar-black.png, bootstrap/images/icons-png/calendar-white.png, bootstrap/images/icons-png/camera-black.png, bootstrap/images/icons-png/camera-white.png, bootstrap/images/icons-png/carat-d-black.png, bootstrap/images/icons-png/carat-d-white.png, bootstrap/images/icons-png/carat-l-black.png, bootstrap/images/icons-png/carat-l-white.png, bootstrap/images/icons-png/carat-r-black.png, bootstrap/images/icons-png/carat-r-white.png, bootstrap/images/icons-png/carat-u-black.png, bootstrap/images/icons-png/carat-u-white.png, bootstrap/images/icons-png/check-black.png, bootstrap/images/icons-png/check-white.png, bootstrap/images/icons-png/clock-black.png, bootstrap/images/icons-png/clock-white.png, bootstrap/images/icons-png/cloud-black.png, bootstrap/images/icons-png/cloud-white.png, bootstrap/images/icons-png/comment-black.png, bootstrap/images/icons-png/comment-white.png, bootstrap/images/icons-png/delete-black.png, bootstrap/images/icons-png/delete-white.png, bootstrap/images/icons-png/edit-black.png, bootstrap/images/icons-png/edit-white.png, bootstrap/images/icons-png/eye-black.png, bootstrap/images/icons-png/eye-white.png, bootstrap/images/icons-png/forbidden-black.png, bootstrap/images/icons-png/forbidden-white.png, bootstrap/images/icons-png/forward-black.png, bootstrap/images/icons-png/forward-white.png, bootstrap/images/icons-png/gear-black.png, bootstrap/images/icons-png/gear-white.png, bootstrap/images/icons-png/grid-black.png, bootstrap/images/icons-png/grid-white.png, bootstrap/images/icons-png/heart-black.png, bootstrap/images/icons-png/heart-white.png, bootstrap/images/icons-png/home-black.png, bootstrap/images/icons-png/home-white.png, bootstrap/images/icons-png/info-black.png, bootstrap/images/icons-png/info-white.png, bootstrap/images/icons-png/location-black.png, bootstrap/images/icons-png/location-white.png, bootstrap/images/icons-png/lock-black.png, bootstrap/images/icons-png/lock-white.png, bootstrap/images/icons-png/mail-black.png, bootstrap/images/icons-png/mail-white.png, bootstrap/images/icons-png/minus-black.png, bootstrap/images/icons-png/minus-white.png, bootstrap/images/icons-png/navigation-black.png, bootstrap/images/icons-png/navigation-white.png, bootstrap/images/icons-png/phone-black.png, bootstrap/images/icons-png/phone-white.png, bootstrap/images/icons-png/plus-black.png, bootstrap/images/icons-png/plus-white.png, bootstrap/images/icons-png/power-black.png, bootstrap/images/icons-png/power-white.png, bootstrap/images/icons-png/recycle-black.png, bootstrap/images/icons-png/recycle-white.png, bootstrap/images/icons-png/refresh-black.png, bootstrap/images/icons-png/refresh-white.png, bootstrap/images/icons-png/search-black.png, bootstrap/images/icons-png/search-white.png, bootstrap/images/icons-png/shop-black.png, bootstrap/images/icons-png/shop-white.png, bootstrap/images/icons-png/star-black.png, bootstrap/images/icons-png/star-white.png, bootstrap/images/icons-png/tag-black.png, bootstrap/images/icons-png/tag-white.png, bootstrap/images/icons-png/user-black.png, bootstrap/images/icons-png/user-white.png, bootstrap/images/icons-png/video-black.png, bootstrap/images/icons-png/video-white.png"
BUNDLE.PUT global, "theme-6-files", "android-holo/android-holo-light.min.css, android-holo/jquery-1.7.1.min.js, android-holo/jquery.mobile-1.1.0.min.js, android-holo/jquery.mobile.structure-1.1.0.min.css, android-holo/images/ajax-loader.gif, android-holo/images/icons-18-black.png, android-holo/images/icons-18-white.png, android-holo/images/icons-36-black.png, android-holo/images/icons-36-white.png"
BUNDLE.PUT global, "theme-7-files", "squareui/jquery.mobile.squareui.min.css, squareui/fonts/Flat-UI-Icons-24.woff, squareui/fonts/lato-black.woff, squareui/fonts/lato-bold.woff, squareui/fonts/lato-italic.woff, squareui/fonts/lato-regular.woff, squareui/images/ajax-loader.gif, squareui/images/icons-18-black.png, squareui/images/icons-18-white.png, squareui/images/icons-36-black.png, squareui/images/icons-36-white.png"
BUNDLE.PUT global, "theme-8-files", "metro/jquery-1.7.1.min.js, metro/jquery.mobile-1.1.0.min.js, metro/jquery.mobile.metro.theme.css, metro/jquery.mobile.metro.theme.init.js, metro/jquery.mobile.structure-1.1.0.min.css, metro/images/ajax-loader.png, metro/images/checkbox-disabled.png, metro/images/checkbox.png, metro/images/icons-18-black.png, metro/images/icons-18-white.png, metro/images/icons-36-black.png, metro/images/icons-36-white.png, metro/images/radiobtn-disabled.png, metro/images/radiobtn.png, metro/images/wait-indicator.gif"
BUNDLE.PUT global, "theme-9-files", "nativedroid/font-awesome.min.css, nativedroid/fonts.css, nativedroid/jquery-1.9.1.min.js, nativedroid/jquery.mobile-1.4.2.min.css, nativedroid/jquery.mobile-1.4.2.min.js, nativedroid/jquerymobile.nativedroid.color.blue.css, nativedroid/jquerymobile.nativedroid.color.green.css, nativedroid/jquerymobile.nativedroid.color.purple.css, nativedroid/jquerymobile.nativedroid.color.red.css, nativedroid/jquerymobile.nativedroid.color.yellow.css, nativedroid/jquerymobile.nativedroid.css, nativedroid/jquerymobile.nativedroid.dark.css, nativedroid/jquerymobile.nativedroid.light.css, nativedroid/nativedroid.script.js, nativedroid/fonts/fontawesome-webfont.eot, nativedroid/fonts/fontawesome-webfont.svg, nativedroid/fonts/fontawesome-webfont.ttf, nativedroid/fonts/fontawesome-webfont.woff, nativedroid/fonts/FontAwesome.otf"

!'---------------------------------------------------------------------------------------------
!' FUNCTIONS TO BE CALLED BEFORE CREATING A PAGE
!'---------------------------------------------------------------------------------------------
FN.DEF GW_THEME_EXISTS(e$) %' Return true|false depending if theme's full set of files exist on device
  IF e$="default" THEN FN.RTN GW_THEME_FILES_EXIST(1)
  IF e$="flat-ui" THEN FN.RTN GW_THEME_FILES_EXIST(2)
  IF e$="classic" THEN FN.RTN GW_THEME_FILES_EXIST(3)
  IF e$="ios" THEN FN.RTN GW_THEME_FILES_EXIST(4)
  IF e$="bootstrap" THEN FN.RTN GW_THEME_FILES_EXIST(5)
  IF e$="android-holo" THEN FN.RTN GW_THEME_FILES_EXIST(6)
  IF e$="square-ui" THEN FN.RTN GW_THEME_FILES_EXIST(7)
  IF e$="metro" THEN FN.RTN GW_THEME_FILES_EXIST(8)
  IF IS_IN("native-droid", e$)=1 THEN FN.RTN GW_THEME_FILES_EXIST(9)
  FN.RTN 0 %' any other case = illegal theme
FN.END
FN.DEF GwThemeExists(e$) %' alias
  FN.RTN GW_THEME_EXISTS(e$)
FN.END
FN.DEF gwte(e$) %' shortcut
  FN.RTN GW_THEME_EXISTS(e$)
FN.END

FN.DEF GW_DOWNLOAD_THEME(e$) %' Download to device all files for a given theme
  IF e$="default" THEN FN.RTN GW_DOWNLOAD_THEME_FILES(1)
  IF e$="flat-ui" THEN FN.RTN GW_DOWNLOAD_THEME_FILES(2)
  IF e$="classic" THEN FN.RTN GW_DOWNLOAD_THEME_FILES(3)
  IF e$="ios" THEN FN.RTN GW_DOWNLOAD_THEME_FILES(4)
  IF e$="bootstrap" THEN FN.RTN GW_DOWNLOAD_THEME_FILES(5)
  IF e$="android-holo" THEN FN.RTN GW_DOWNLOAD_THEME_FILES(6)
  IF e$="square-ui" THEN FN.RTN GW_DOWNLOAD_THEME_FILES(7)
  IF e$="metro" THEN FN.RTN GW_DOWNLOAD_THEME_FILES(8)
  IF IS_IN("native-droid", e$)=1 THEN FN.RTN GW_DOWNLOAD_THEME_FILES(9)
  FN.RTN 0 %' any other case = illegal theme
FN.END
FN.DEF GwDownloadTheme(e$) %' alias
  FN.RTN GW_DOWNLOAD_THEME(e$)
FN.END
FN.DEF gwdt(e$) %' shortcut
  FN.RTN GW_DOWNLOAD_THEME(e$)
FN.END

FN.DEF GW_LOAD_THEME(e$)
  !' Error-proofing
  r$=LOWER$(e$)
  IF GW_THEME_CSS$(r$)="" THEN %' Throw an error
    (illegal_gw_theme)
  END IF
  !' Change 'theme' property in the global bundle
  BUNDLE.PUT 1, "theme", r$
FN.END
FN.DEF GwLoadTheme(e$) %' alias
  FN.RTN GW_LOAD_THEME(e$)
FN.END
FN.DEF gwlt(e$) %' shortcut
  FN.RTN GW_LOAD_THEME(e$)
FN.END

FN.DEF GW_UNLOAD_THEME()
  !' Reset theme to default
  FN.RTN GW_LOAD_THEME("default")
FN.END
FN.DEF GwUnloadTheme() %' alias
  FN.RTN GW_UNLOAD_THEME()
FN.END
FN.DEF gwut() %' shortcut
  FN.RTN GW_UNLOAD_THEME()
FN.END

FN.DEF GW_THEME_FILES_EXIST(idx) %' (internal) Check existence of #idx theme (full set of files) on the device
  BUNDLE.GET 1, "theme-" + INT$(idx) + "-files", allfiles$
  SPLIT file$[], allfiles$, ","
  ARRAY.LENGTH nfiles, file$[]
  exists = 1
  FOR i=1 TO nfiles
    FILE.EXISTS fe, TRIM$(file$[i])
    exists *= fe
  NEXT
  FN.RTN exists
FN.END

FN.DEF GW_DOWNLOAD_THEME_FILES(idx) %' (internal) Download #idx theme (full set of files) to the device
  BUNDLE.GET 1, "theme-" + INT$(idx) + "-files", allfiles$
  SPLIT file$[], allfiles$, ","
  ARRAY.LENGTH nfiles, file$[]
  FOR i=1 TO nfiles
    f$ = TRIM$(file$[i])
    BYTE.OPEN r, fid, "http://mougino.free.fr/tmp/GW/" + f$
    IF fid<0 THEN FN.RTN 0 %' could not access file on server
    PRINT "Downloading " + f$
    j = IS_IN("/", f$)
    WHILE j %' create subfolder hierarchy for this file, if any
      FILE.MKDIR LEFT$(f$, j)
      j = IS_IN("/", f$, j+1)
    REPEAT
    BYTE.COPY fid, f$
  NEXT
FN.END

FN.DEF GW_CHECK_THEME(theme$) %' (internal) Check existence on the device of main .css file for a theme
  FILE.EXISTS fe, GW_THEME_CSS$(theme$)  %' It's a low level procedure: if theme doesn't exist download will be proposed,
  IF fe THEN FN.RTN 1                    %' then whether it succeeds or fails the app will exit (user has to re-launch it)
  IF IS_IN("native-droid", theme$)=1 THEN theme$="native-droid"
  HTML.CLOSE
  DIALOG.MESSAGE "GW theme missing", ~
    "Theme '"+theme$+"' is missing. " + ~
    "Proceed to download now?", ~
    go, "Yes", "No"
  IF go=1 THEN
    GW_DOWNLOAD_THEME(theme$)
    IF GW_THEME_EXISTS(theme$) THEN
      DIALOG.MESSAGE "Download ok", ~
        "GW theme '"+theme$+"' was correctly downloaded. " + ~
        "Please restart the app to take it into account.", go, "OK"
    ELSE
      DIALOG.MESSAGE "Download error", ~
        "There was a problem downloading GW theme '"+theme$+"' ! " + ~
        "Please try again later. The app will now exit.", go, "OK"
    END IF
  END IF
  EXIT
FN.END

FN.DEF GW_THEME_CSS$(e$) %' (internal) Return path to main .css file for a desired theme
  IF e$="default" THEN FN.RTN "jquery.mobile-1.4.5.min.css"
  IF e$="classic" THEN FN.RTN "theme-classic.css"
  IF e$="flat-ui" THEN FN.RTN "flatui/jquery.mobile.flatui.css"
  IF e$="ios" THEN FN.RTN "ios/ios.css"
  IF e$="bootstrap" THEN FN.RTN "bootstrap/Bootstrap.min.css"
  IF e$="android-holo" THEN FN.RTN "android-holo/android-holo-light.min.css"
  IF e$="square-ui" THEN FN.RTN "squareui/jquery.mobile.squareui.min.css"
  IF e$="metro" THEN FN.RTN "metro/jquery.mobile.metro.theme.css"
  IF IS_IN("native-droid", e$)=1 THEN FN.RTN "nativedroid/jquerymobile.nativedroid.css"
  FN.RTN "" %' any other case = illegal theme
FN.END

!'---------------------------------------------------------------------------------------------
!' FUNCTION TO CREATE A NEW GW PAGE
!'---------------------------------------------------------------------------------------------
FN.DEF GW_NEW_PAGE() %' Return an index to a new GW page
  !' New script to solve grey circle issue for Android System WebView > 44.0.2403.117
  script$="<script>$(document).bind('mobileinit',function(){$.mobile.changePage.defaults.changeHash=false;"
  script$+="$.mobile.hashListeningEnabled=false;$.mobile.pushStateEnabled=false;});</script>"
  !' Check presence of theme CSS and load it
  BUNDLE.GET 1, "theme", theme$
  GW_CHECK_THEME(theme$)
  css$=GW_THEME_CSS$(theme$)
  !' Build beginning of HTML string
  e$ ="<html>"
  e$+="<head>"
  e$+="<meta charset='ISO-8859-2'>"
  e$+="<meta name='viewport' content='width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no'>"
  e$+="<link rel='stylesheet' type='text/css' href='styles.css' />"
  !' The following themes need another CSS to work
  IF theme$="ios" THEN
    e$+="<link rel='stylesheet' href='ios/jquery.mobile-1.2.0.min.css' />"
    e$+="<link rel='stylesheet' href='"+css$+"' />"
    e$+="<script src='ios/jquery-1.7.1.min.js'></script>"
    e$+=script$+"<script src='ios/jquery.mobile-1.2.0.min.js'></script>"
  ELSEIF theme$="android-holo" THEN
    e$+="<link rel='stylesheet' href='"+css$+"' />"
    e$+="<link rel='stylesheet' href='android-holo/jquery.mobile.structure-1.1.0.min.css' />"
    e$+="<script src='android-holo/jquery-1.7.1.min.js'></script>"
    e$+=script$+"<script src='android-holo/jquery.mobile-1.1.0.min.js'></script>"
  ELSEIF theme$="metro" THEN
    e$+="<link rel='stylesheet' href='"+css$+"' />"
    e$+="<link rel='stylesheet' href='metro/jquery.mobile.structure-1.1.0.min.css' />"
    e$+="<script src='metro/jquery-1.7.1.min.js'></script>"
    e$+="<script src='metro/jquery.mobile.metro.theme.init.js'></script>"
    e$+=script$+"<script src='metro/jquery.mobile-1.1.0.min.js'></script>"
  ELSEIF IS_IN("native-droid", theme$)=1 THEN
    e$+="<link rel='stylesheet' href='nativedroid/font-awesome.min.css' />"
    e$+="<link rel='stylesheet' href='nativedroid/jquery.mobile-1.4.2.min.css' />"
    e$+="<link rel='stylesheet' href='"+css$+"' />"
    IF IS_IN("-dark-", theme$) THEN
      e$+="<link rel='stylesheet' href='nativedroid/jquerymobile.nativedroid.dark.css' />"
    ELSE
      e$+="<link rel='stylesheet' href='nativedroid/jquerymobile.nativedroid.light.css' />"
    END IF
    IF IS_IN("-green", theme$) THEN
      e$+="<link rel='stylesheet' href='nativedroid/jquerymobile.nativedroid.color.green.css' />"
    ELSEIF IS_IN("-purple", theme$) THEN
      e$+="<link rel='stylesheet' href='nativedroid/jquerymobile.nativedroid.color.purple.css' />"
    ELSEIF IS_IN("-red", theme$) THEN
      e$+="<link rel='stylesheet' href='nativedroid/jquerymobile.nativedroid.color.red.css' />"
    ELSEIF IS_IN("-yellow", theme$) THEN
      e$+="<link rel='stylesheet' href='nativedroid/jquerymobile.nativedroid.color.yellow.css' />"
    ELSE
      e$+="<link rel='stylesheet' href='nativedroid/jquerymobile.nativedroid.color.blue.css' />"
    END IF
    e$+="<script src='nativedroid/jquery-1.9.1.min.js'></script>"
    e$+=script$+"<script src='nativedroid/jquery.mobile-1.4.2.min.js'></script>"
  ELSEIF theme$<>"default" THEN 
    GW_CHECK_THEME("default")
    e$+="<link rel='stylesheet' href='"+GW_THEME_CSS$("default")+"' />"
  END IF
  !' Embed the correct JQM JavaScript
  IF theme$<>"ios" & theme$<>"android-holo" & theme$<>"metro" & !IS_IN("native-droid", theme$) THEN
    e$+="<link rel='stylesheet' href='"+css$+"' />"
    e$+="<script src='jquery-2.1.1.min.js'></script>"
    e$+=script$+"<script src='jquery.mobile-1.4.5.min.js'></script>"
  END IF
  e$+="<script src='basic.js'></script>"
  e$+="<script>function replace(ctlid, tag){var obj=document.getElementById(ctlid); var regex=new RegExp('<'+obj.tagName,'i'); var newTag=obj.outerHTML.replace(regex,'<'+tag); regex=new RegExp('</'+obj.tagName,'i'); newTag=newTag.replace(regex,'</'+tag); obj.outerHTML=newTag;}</script>"
  e$+="<script>function htc(){$('.ui-table-columntoggle-btn').hide()}</script>" %' hide tables' column-toggle button
  e$+="<style>th{border-bottom:1px solid #d6d6d6;}tr:nth-child(even){background:#e9e9e9;}</style>" %' styling tables
  e$+="</head>"
  e$+="<body onload='htc()'>"
  !' Add the page to the list of GW pages
  LIST.SIZE 1, ls
  ls++
  e$+="<div data-role='page' id='page"+INT$(ls)+"' "+GW_THEME_CUSTO$("page")+">"
  e$+="<div data-role='content' id='content"+INT$(ls)+"' "+GW_THEME_CUSTO$("content")+">"
  LIST.ADD 1, e$
  FN.RTN ls
FN.END
FN.DEF GwNewPage() %' alias
  FN.RTN GW_NEW_PAGE()
FN.END
FN.DEF gwnp() %' shortcut
  FN.RTN GW_NEW_PAGE()
FN.END

!'---------------------------------------------------------------------------------------------
!' FUNCTIONS TO TRANSFORM PAGE - TO BE INSERTED BEFORE CONTENT
!'---------------------------------------------------------------------------------------------
FN.DEF GW_INSERT_BEFORE_CONTENT(idx, ins$) %' (internal) insert element before page content itself
  e$ = GW_PAGE$(idx)
  i = IS_IN("<div data-role='content'", e$)
  IF !i THEN FN.RTN 0
  e$ = LEFT$(e$, i-1) + ins$ + MID$(e$, i)
  LIST.REPLACE 1, idx, e$
FN.END

FN.DEF GW_USE_FONT(idx, fnt$)
  e$ = GW_PAGE$(idx)
  i = IS_IN("</head>", e$)
  IF !i THEN FN.RTN 0
  j=IS_IN("/", fnt$, -1)
  IF j THEN ff$=MID$(fnt$, j+1) ELSE ff$=fnt$
  j=IS_IN(".", ff$)
  IF j THEN ff$=LEFT$(ff$, j-1)
  ins$="<style>@font-face{"
  ins$+=" font-family:'"+ff$+"';"
  ins$+=" src: url('"+fnt$+"');"
  ins$+="} body,.ui-btn{font-family: "+ff$+";}</style>"
  e$ = LEFT$(e$, i-1) + ins$ + MID$(e$, i)
  LIST.REPLACE 1, idx, e$
FN.END
FN.DEF GwUseFont(idx, fnt$) %' alias
  FN.RTN GW_USE_FONT(idx, fnt$)
FN.END
FN.DEF gwuf(idx, fnt$) %' shortcut
  FN.RTN GW_USE_FONT(idx, fnt$)
FN.END

FN.DEF GW_SET_TRANSITION(ctl_id, e$)
  !' Get Unique IDentifier of the control
  ctl$ = GW_ID$(ctl_id)
  IF IS_IN("dlgmsg", ctl$)=1 THEN %' DIALOG_MESSAGE
    BUNDLE.PUT 1, "dlgmsg-transition", e$
  ELSEIF IS_IN("panel", ctl$)=1 THEN %' PANEL
    BUNDLE.PUT 1, "panel-transition", e$
    HTML.LOAD.URL "javascript:$('#"+ctl$+"').panel('option','display','"+e$+"')"
  ELSE %' PAGE
    BUNDLE.PUT 1, "page-transition", e$
    HTML.LOAD.URL "javascript:$.mobile.defaultPageTransition='"+e$+"'"
  END IF
FN.END
FN.DEF GwSetTransition(ctl_id, e$) %' alias
  FN.RTN GW_SET_TRANSITION(ctl_id, e$)
FN.END
FN.DEF gwst(ctl_id, e$) %' shortcut
  FN.RTN GW_SET_TRANSITION(ctl_id, e$)
FN.END

FN.DEF GW_NEW_DM_BTN$(btn_axn$[]) %' (internal) for DIALOG_MESSAGE
  ARRAY.LENGTH al, btn_axn$[]
  FOR i=1 TO al
    k=IS_IN(">", btn_axn$[i])
    IF !k THEN k=LEN(btn_axn$[i])+1
    bt$=WEB$(LEFT$(btn_axn$[i], k-1))
    ax$=GW_FORMAT_LINK$(MID$(btn_axn$[i], k+1))
    e$+="<a class='ui-btn ui-corner-all ui-shadow ui-btn-inline'"
    e$+=" href='"+ax$+"' data-rel='back' onclick='"+ax$+"'>"+bt$+"</a>"
  NEXT
  FN.RTN e$
FN.END

FN.DEF GW_ADD_DIALOG_MESSAGE$(title$, msg$, btn_axn$[])
  !' Create the control
  u$=GW_NEWID$("dlgmsg")
  e$="<div data-role='popup' id='"+u$+"' data-dismissible='false' "+GW_THEME_CUSTO$("dlgmsg")+">"
  IF title$<>"" THEN e$+="<div data-role='header'><h1 id='"+u$+"-title'>"+WEB$(title$)+"</h1></div>"
  e$+="<div role='main' class='ui-content'><h3  id='"+u$+"-text'class='ui-title'>"+WEB$(msg$)+"</h3>"
  e$+="<div id='"+u$+"-buttons' style='margin:0 auto; text-align:center;'>"
  e$+=GW_NEW_DM_BTN$(btn_axn$[])
  e$+="</div><!-- /center -->"
  e$+="</div><!-- /main --></div><!-- /dlgmsg -->"
  !' Add to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddDialogMessage$(title$, msg$, btn_axn$[]) %' alias
  FN.RTN GW_ADD_DIALOG_MESSAGE$(title$, msg$, btn_axn$[])
FN.END
FN.DEF gwadm$(title$, msg$, btn_axn$[]) %' shortcut
  FN.RTN GW_ADD_DIALOG_MESSAGE$(title$, msg$, btn_axn$[])
FN.END

FN.DEF GW_ADD_DIALOG_MESSAGE(idx, title$, msg$, btn_axn$[])
  !' Add to the page before page-content
  GW_INSERT_BEFORE_CONTENT(idx, GW_ADD_DIALOG_MESSAGE$(title$, msg$, btn_axn$[]))
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddDialogMessage(idx, title$, msg$, btn_axn$[]) %' alias
  FN.RTN GW_ADD_DIALOG_MESSAGE(idx, title$, msg$, btn_axn$[])
FN.END
FN.DEF gwadm(idx, title$, msg$, btn_axn$[]) %' shortcut
  FN.RTN GW_ADD_DIALOG_MESSAGE(idx, title$, msg$, btn_axn$[])
FN.END

FN.DEF GW_SHOW_DIALOG_MESSAGE$(ctl_id) %' BUTTON link to display a DIALOG_MESSAGE
  !' Get Unique IDentifier of the control
  FN.RTN "#"+GW_ID$(ctl_id)
FN.END
FN.DEF GwShowDialogMessage$(ctl_id) %' alias
  FN.RTN GW_SHOW_DIALOG_MESSAGE$(ctl_id)
FN.END
FN.DEF gwsdm$(ctl_id) %' shortcut
  FN.RTN GW_SHOW_DIALOG_MESSAGE$(ctl_id)
FN.END

FN.DEF GW_SHOW_DIALOG_MESSAGE(ctl_id) %' manually trigger a DIALOG_MESSAGE
  !' Get Unique IDentifier of the control
  ctl$ = GW_ID$(ctl_id)
  BUNDLE.GET 1, "dlgmsg-transition", dmt$
  HTML.LOAD.URL "javascript:$('#"+ctl$+"').popup('open',{transition:'"+dmt$+"'})"
FN.END
FN.DEF GwShowDialogMessage(ctl_id) %' alias
  FN.RTN GW_SHOW_DIALOG_MESSAGE(ctl_id)
FN.END
FN.DEF gwsdm(ctl_id) %' shortcut
  FN.RTN GW_SHOW_DIALOG_MESSAGE(ctl_id)
FN.END

FN.DEF GW_ADD_BAR_TITLE$(e$) %' for TITLEBAR and FOOTBAR
  FN.RTN "<h1 id='-title'>"+WEB$(e$)+"</h1>"
FN.END
FN.DEF GwAddBarTitle$(e$) %' alias
  FN.RTN GW_ADD_BAR_TITLE$(e$)
FN.END
FN.DEF gwabt$(e$) %' shortcut
  FN.RTN GW_ADD_BAR_TITLE$(e$)
FN.END

FN.DEF GW_ADD_BAR_LBUTTON$(ba$) %' for TITLEBAR and FOOTBAR
  k=IS_IN(">", ba$)
  IF !k THEN k=LEN(ba$)+1
  bt$=WEB$(LEFT$(ba$, k-1))
  ax$=GW_FORMAT_LINK$(MID$(ba$, k+1))
  e$+="<a class='ui-btn-left ui-btn ui-corner-all "
  e$+="ui-shadow ui-btn-inline ui-mini "+GW_THEME_CUSTO$("hfbtn")
  e$+="' id='-lbutton' href='"+ax$+"'>"+bt$+"</a>"
  FN.RTN e$
FN.END
FN.DEF GwAddBarLButton$(ba$) %' alias
  FN.RTN GW_ADD_BAR_LBUTTON$(ba$)
FN.END
FN.DEF gwablb$(ba$) %' shortcut
  FN.RTN GW_ADD_BAR_LBUTTON$(ba$)
FN.END

FN.DEF GW_ADD_BAR_RBUTTON$(ba$) %' for TITLEBAR and FOOTBAR
  k=IS_IN(">", ba$)
  IF !k THEN k=LEN(ba$)+1
  bt$=WEB$(LEFT$(ba$, k-1))
  ax$=GW_FORMAT_LINK$(MID$(ba$, k+1))
  e$+="<a class='ui-btn-right ui-btn ui-corner-all "
  e$+="ui-shadow ui-btn-inline ui-mini "+GW_THEME_CUSTO$("hfbtn")
  e$+="' id='-rbutton' href='"+ax$+"'>"+bt$+"</a>"
  FN.RTN e$
FN.END
FN.DEF GwAddBarRButton$(ba$) %' alias
  FN.RTN GW_ADD_BAR_RBUTTON$(ba$)
FN.END
FN.DEF gwabrb$(ba$) %' shortcut
  FN.RTN GW_ADD_BAR_RBUTTON$(ba$)
FN.END

FN.DEF GW_ADD_TITLEBAR$(title$)
  !' Create the control
  u$=GW_NEWID$("titlebar")
  e$="<div data-role='header' data-position='fixed' data-tap-toggle='false' "+GW_THEME_CUSTO$("titlebar")+">"
  IF LEFT$(title$, 1)="<" THEN
    e$+=REPLACE$(title$,"id='","id='"+u$)
  ELSE
    e$=e$+"<h1 id='"+u$+"-title'>"+WEB$(title$)+"</h1>"
  END IF
  e$+="</div>"
  !' Add to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddTitleBar$(title$) %' alias
  FN.RTN GW_ADD_TITLEBAR$(title$)
FN.END
FN.DEF gwatib$(title$) %' shortcut
  FN.RTN GW_ADD_TITLEBAR$(title$)
FN.END

FN.DEF GW_ADD_TITLEBAR(idx, title$)
  !' Add to the page before page-content
  GW_INSERT_BEFORE_CONTENT(idx, GW_ADD_TITLEBAR$(title$))
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddTitleBar(idx, title$) %' alias
  FN.RTN GW_ADD_TITLEBAR(idx, title$)
FN.END
FN.DEF gwatib(idx, title$) %' shortcut
  FN.RTN GW_ADD_TITLEBAR(idx, title$)
FN.END

FN.DEF GW_ADD_FOOTBAR$(foot$)
  !' Create the control
  u$=GW_NEWID$("footbar")
  e$="<div data-role='footer' data-position='fixed' data-tap-toggle='false' "+GW_THEME_CUSTO$("footbar")+">"
  IF LEFT$(foot$, 1)="<" THEN
    e$+=REPLACE$(foot$,"id='","id='"+u$)
  ELSE
    e$=e$+"<h1 id='"+u$+"-title'>"+WEB$(foot$)+"</h1>"
  END IF
  e$+="</div>"
  !' Add to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddFootBar$(foot$) %' alias
  FN.RTN GW_ADD_FOOTBAR$(foot$)
FN.END
FN.DEF gwafb$(foot$) %' shortcut
  FN.RTN GW_ADD_FOOTBAR$(foot$)
FN.END

FN.DEF GW_ADD_FOOTBAR(idx, foot$)
  !' Add to the page before page-content
  GW_INSERT_BEFORE_CONTENT(idx, GW_ADD_FOOTBAR$(foot$))
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddFootBar(idx, foot$) %' alias
  FN.RTN GW_ADD_FOOTBAR(idx, foot$)
FN.END
FN.DEF gwafb(idx, foot$) %' shortcut
  FN.RTN GW_ADD_FOOTBAR(idx, foot$)
FN.END

FN.DEF GW_ADD_PANEL$(content$)
  !' First format the default text, if any
  IF LEFT$(content$, 1)<>"<" THEN ini$="<p>"+content$+"</p>" ELSE ini$=content$
  !' Create the control
  u$=GW_NEWID$("panel")
  BUNDLE.GET 1, "panel-transition", pnt$
  e$="<div data-role='panel' id='"+u$+"' data-display='"+pnt$+"' "+GW_THEME_CUSTO$("panel")+">"
  e$+=WEB$(ini$)+"</div><!-- /panel -->"
  !' Add to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddPanel$(content$) %' alias
  FN.RTN GW_ADD_PANEL$(content$)
FN.END
FN.DEF gwap$(content$) %' shortcut
  FN.RTN GW_ADD_PANEL$(content$)
FN.END

FN.DEF GW_ADD_PANEL(idx, content$)
  !' Add to the page before page-content
  GW_INSERT_BEFORE_CONTENT(idx, GW_ADD_PANEL$(content$))
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddPanel(idx, content$) %' alias
  FN.RTN GW_ADD_PANEL(idx, content$)
FN.END
FN.DEF gwap(idx, content$) %' shortcut
  FN.RTN GW_ADD_PANEL(idx, content$)
FN.END

FN.DEF GW_SHOW_PANEL$(ctl_id)
  !' Get Unique IDentifier of the control
  ctl$ = GW_ID$(ctl_id)
  FN.RTN "#"+ctl$
FN.END
FN.DEF GwShowPanel$(ctl_id) %' alias
  FN.RTN GW_SHOW_PANEL$(ctl_id)
FN.END
FN.DEF gwsp$(ctl_id) %' shortcut
  FN.RTN GW_SHOW_PANEL$(ctl_id)
FN.END

FN.DEF GW_SHOW_PANEL(ctl_id)
  !' Get Unique IDentifier of the control
  ctl$ = GW_ID$(ctl_id)
  BUNDLE.GET 1, "panel-transition", pt$
  HTML.LOAD.URL "javascript:$('#"+ctl$+"').panel('option','display','"+pt$+"')"
  HTML.LOAD.URL "javascript:$('#"+ctl$+"').panel('open')"
FN.END
FN.DEF GwShowPanel(ctl_id) %' alias
  FN.RTN GW_SHOW_PANEL(ctl_id)
FN.END
FN.DEF gwsp(ctl_id) %' shortcut
  FN.RTN GW_SHOW_PANEL(ctl_id)
FN.END

!'---------------------------------------------------------------------------------------------
!' FUNCTIONS TO VISUALLY CHANGE CONTROLS LAYOUTS BEFORE ADDING THEM
!'---------------------------------------------------------------------------------------------
FN.DEF GW_START_CENTER$()
  FN.RTN "<div style='margin:0 auto; text-align:center;'>"
FN.END
FN.DEF GwStartCenter$() %' alias
  FN.RTN GW_START_CENTER$()
FN.END
FN.DEF gwstac$() %' shortcut
  FN.RTN GW_START_CENTER$()
FN.END

FN.DEF GW_START_CENTER(idx)
  !' Add the center div to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_START_CENTER$()
FN.END
FN.DEF GwStartCenter(idx) %' alias
  FN.RTN GW_START_CENTER(idx)
FN.END
FN.DEF gwstac(idx) %' shortcut
  FN.RTN GW_START_CENTER(idx)
FN.END

FN.DEF GW_STOP_CENTER$()
  FN.RTN "</div><!-- /center -->"
FN.END
FN.DEF GwStopCenter$() %' alias
  FN.RTN GW_STOP_CENTER$()
FN.END
FN.DEF gwstoc$() %' shortcut
  FN.RTN GW_STOP_CENTER$()
FN.END

FN.DEF GW_STOP_CENTER(idx)
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_STOP_CENTER$()
FN.END
FN.DEF GwStopCenter(idx) %' alias
  FN.RTN GW_STOP_CENTER(idx)
FN.END
FN.DEF gwstoc(idx) %' shortcut
  FN.RTN GW_STOP_CENTER(idx)
FN.END

FN.DEF GW_CENTER_PAGE_VER$()
  e$="<script>$(document.body).on('pageshow',function(e,data){"
  e$+="$('#content"+INT$(idx)+"').css('margin-top',("
  e$+="$(window).height()-$('[data-role=header]').height()"
  e$+="-$('[data-role=footer]').height()-$('#content"+INT$(idx)+"').outerHeight()"
  e$+=")/2);});</script>"
  FN.RTN e$
FN.END
FN.DEF GwCenterPageVer$() %' alias
  FN.RTN GW_CENTER_PAGE_VER$()
FN.END
FN.DEF gwcpv$() %' shortcut
  FN.RTN GW_CENTER_PAGE_VER$()
FN.END

FN.DEF GW_CENTER_PAGE_VER(idx)
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_CENTER_PAGE_VER$()
FN.END
FN.DEF GwCenterPageVer(idx) %' alias
  FN.RTN GW_CENTER_PAGE_VER(idx)
FN.END
FN.DEF gwcpv(idx) %' shortcut
  FN.RTN GW_CENTER_PAGE_VER(idx)
FN.END

FN.DEF GW_OPEN_GROUP$() %' for CHECKBOX or RADIO controls
  FN.RTN "<fieldset data-role='controlgroup' "+GW_THEME_CUSTO$("group")+">"
FN.END
FN.DEF GwOpenGroup$() %' alias
  FN.RTN GW_OPEN_GROUP$()
FN.END
FN.DEF gwog$() %' shortcut
  FN.RTN GW_OPEN_GROUP$()
FN.END

FN.DEF GW_OPEN_GROUP(idx) %' for CHECKBOX or RADIO controls
  !' Add the group to the page
  e$ = GW_PAGE$(idx)
  IF !IS_IN("<form ",e$,IS_IN("role='content'",e$)) THEN e$+=GW_OPEN_INPUTFORM$(idx)
  e$+=GW_OPEN_GROUP$()
  LIST.REPLACE 1, idx, e$
FN.END
FN.DEF GwOpenGroup(idx) %' alias
  FN.RTN GW_OPEN_GROUP(idx)
FN.END
FN.DEF gwog(idx) %' shortcut
  FN.RTN GW_OPEN_GROUP(idx)
FN.END

FN.DEF GW_CLOSE_GROUP$()
  FN.RTN "</fieldset>"
FN.END
FN.DEF GwCloseGroup$() %' alias
  FN.RTN GW_CLOSE_GROUP$()
FN.END
FN.DEF gwcg$() %' shortcut
  FN.RTN GW_CLOSE_GROUP$()
FN.END

FN.DEF GW_CLOSE_GROUP(idx)
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_CLOSE_GROUP$()
FN.END
FN.DEF GwCloseGroup(idx) %' alias
  FN.RTN GW_CLOSE_GROUP(idx)
FN.END
FN.DEF gwcg(idx) %' shortcut
  FN.RTN GW_CLOSE_GROUP(idx)
FN.END

!'---------------------------------------------------------------------------------------------
!' FUNCTIONS TO CREATE AND USE THEME-CUSTOMIZATIONS ON CONTROLS
!'---------------------------------------------------------------------------------------------
FN.DEF GW_NEW_THEME_CUSTO(e$)
  !' Add the theme customization to the list + return its index
  LIST.ADD 3, LOWER$(e$)
  LIST.SIZE 3, ls
  FN.RTN ls
FN.END
FN.DEF GwNewThemeCusto(e$) %' alias
  FN.RTN GW_NEW_THEME_CUSTO(e$)
FN.END
FN.DEF gwntc(e$) %' shortcut
  FN.RTN GW_NEW_THEME_CUSTO(e$)
FN.END

FN.DEF GW_USE_THEME_CUSTO(idx)
  !' Change 'theme-custo' properties in the global bundle
  BUNDLE.PUT 1, "theme-custo", idx
  BUNDLE.PUT 1, "theme-custo-token", -1 %' -1 = unlimited tokens = persistent theme customization
FN.END
FN.DEF GwUseThemeCusto(idx) %' alias
  FN.RTN GW_USE_THEME_CUSTO(idx)
FN.END
FN.DEF gwutc(idx) %' shortcut
  FN.RTN GW_USE_THEME_CUSTO(idx)
FN.END

FN.DEF GW_USE_THEME_CUSTO_ONCE(e$)
  !' Add the theme-customization to the list
  idx=GW_NEW_THEME_CUSTO(e$)
  !' Change 'theme-custo' properties in the global bundle
  BUNDLE.PUT 1, "theme-custo", idx
  BUNDLE.PUT 1, "theme-custo-token", 1 %' 1 token = 1-shot theme customization
FN.END
FN.DEF GwUseThemeCustoOnce(e$) %' alias
  FN.RTN GW_USE_THEME_CUSTO_ONCE(e$)
FN.END
FN.DEF gwutco(e$) %' shortcut
  FN.RTN GW_USE_THEME_CUSTO_ONCE(e$)
FN.END

FN.DEF GW_RESET_THEME_CUSTO()
  !' Change 'theme-custo' properties in the global bundle
  BUNDLE.PUT 1, "theme-custo", 0
  BUNDLE.PUT 1, "theme-custo-token", 0 %' zero token = no customization
FN.END
FN.DEF GwResetThemeCusto() %' alias
  FN.RTN GW_RESET_THEME_CUSTO()
FN.END
FN.DEF gwrtc() %' shortcut
  FN.RTN GW_RESET_THEME_CUSTO()
FN.END

FN.DEF GW_THEME_CUSTO$(ctl$) %' (internal) Return a formated theme customization for this control family
  BUNDLE.GET 1, "theme", theme$
  BUNDLE.GET 1, "theme-custo-token", tct
  IF !tct THEN %' No theme customization -> return empty string, except for native-droid = data-theme-b by default
    IF IS_IN("native-droid", theme$)=1 & IS_IN(ctl$, "page|panel|titlebar") THEN FN.RTN "data-theme=b" ELSE FN.RTN ""
  END IF
  BUNDLE.GET 1, "theme-custo", idx
  r$ = GW_THEME$(idx) %' Get the theme-customization string
  !' Format it for the desired control
  IF ctl$="hfbtn" THEN %' button for TITLEBAR or FOOTBAR
    r$=REPLACE$(r$, "icon=", "ui-icon-")
    r$=REPLACE$(r$, "iconpos=", "ui-btn-icon-")
    r$=REPLACE$(r$, "inline", "") %' because inline by default
  ELSEIF ctl$="group" THEN %' group for checkboxes
    r$=REPLACE$(r$, "inline", "data-type='horizontal' data-mini='true'")
  ELSE
    r$=REPLACE$(r$, "color=", "data-theme=")
    r$=REPLACE$(r$, "icon=", "data-icon=")
    r$=REPLACE$(r$, "iconpos=", "data-iconpos=")
    r$=REPLACE$(r$, "inline", "data-inline='true'")
  END IF
  !' Flush use of 1-shot theme customization (GW_USE_THEME_CUSTO_ONCE), for a control! (don't flush for content)
  IF tct=1 & ctl$<>"content" THEN GW_RESET_THEME_CUSTO()
  !' Return the formated string
  FN.RTN r$
FN.END

!'---------------------------------------------------------------------------------------------
!' FUNCTIONS TO ADD STANDARD CONTROLS
!'---------------------------------------------------------------------------------------------
FN.DEF GW_NEW_LV$(txt_axn$[]) %' (internal)
  ARRAY.LENGTH al, txt_axn$[]
  !' Scan listview for links
  FOR i=1 TO al
    IF IS_IN(">", txt_axn$[i])>2 THEN
      linked=1 %' at least 1 'link' value means a 'linked' listview
      F_N.BREAK
    END IF
  NEXT
  !' Create listview elements, 1 by 1
  FOR i=1 TO al
    ar$=txt_axn$[i]
    IF i=1 & IS_IN("#", ar$)=1 THEN ar$=MID$(ar$, 2) %' ignore 'ordered' switch
    k=IS_IN(">", ar$)
    IF k=1 THEN %' divider --> ">Listview title"
      ar$=MID$(ar$, 2)
      IF i=1 & IS_IN("#", ar$)=1 THEN ar$=MID$(ar$, 2) %' ignore 'ordered' switch
      k=IS_IN(">", ar$)
      IF k>0 THEN ar$=LEFT$(ar$, k-1)
      e$+="<li data-role='list-divider'>"+WEB$(ar$)+"</li>"
    ELSE
      IF !k THEN k=LEN(ar$)+1
      m=IS_IN("(", LEFT$(ar$, k-1))
      n=IS_IN(")", LEFT$(ar$, k-1))
      IF m & n & n>m THEN %' count bubble "(n)" --> "label bla bla (12)>action"
        tx$=WEB$(LEFT$(ar$, m-1))
        m+=1
        tx$+="<span class='ui-li-count'>"
        tx$+=WEB$(MID$(ar$, m, n-m))
        tx$+="</span>"
      ELSE %' no count bubble
        tx$=WEB$(LEFT$(ar$, k-1))
      END IF
      e$+="<li>"
      IF linked THEN
        ax$=MID$(ar$, k+1)
        IF ax$="" THEN ax$="#" ELSE ax$ = GW_FORMAT_LINK$(ax$)
        ax$=REPLACE$(ax$, CHR$(34), CHR$(92,34)) %' protect double quotes with a backslash
        e$+="<a href='"+ax$+"'>"
      END IF
      e$+=tx$
      IF linked THEN e$+="</a>"
      e$+="</li>"
    END IF
  NEXT
  FN.RTN e$
FN.END

FN.DEF GW_ADD_LISTVIEW$(txt_axn$[])
  !' Create the control
  IF IS_IN("#", txt_axn$[1])=1 THEN ordered=1 %' first element starting with '#' --> means ordered list
  u$=GW_NEWID$("listview")
  IF ordered THEN e$="<ol " ELSE e$="<ul "
  e$+="id='"+u$+"' data-role='listview' data-inset='true' "+GW_THEME_CUSTO$("listview")+">"
  e$+=REPLACE$(GW_NEW_LV$(txt_axn$[]), CHR$(92,34), CHR$(34)) %' unprotect double quotes
  IF ordered THEN e$=e$+"</ol>" ELSE e$=e$+"</ul>"
  !' Add to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddListView$(txt_axn$[]) %' alias
  FN.RTN GW_ADD_LISTVIEW$(txt_axn$[])
FN.END
FN.DEF gwalv$(txt_axn$[]) %' shortcut
  FN.RTN GW_ADD_LISTVIEW$(txt_axn$[])
FN.END

FN.DEF GW_ADD_LISTVIEW(idx, txt_axn$[])
  !' Add the element to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_LISTVIEW$(txt_axn$[])
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddListView(idx, txt_axn$[]) %' alias
  FN.RTN GW_ADD_LISTVIEW(idx, txt_axn$[])
FN.END
FN.DEF gwalv(idx, txt_axn$[]) %' shortcut
  FN.RTN GW_ADD_LISTVIEW(idx, txt_axn$[])
FN.END

FN.DEF GW_ADD_IMAGE$(img$)
  !' Create the control
  u$=GW_NEWID$("image")
  i=IS_IN(">", img$)
  IF i THEN
    e$="<a href='"+GW_FORMAT_LINK$(MID$(img$, i+1))+"'>"
    e$+="<img id='"+u$+"' src='"+LEFT$(img$, i-1)+"'>"
    e$+="</a>"
  ELSE
    e$="<img id='"+u$+"' src='"+img$+"'>"
  END IF
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddImage$(img$) %' alias
  FN.RTN GW_ADD_IMAGE$(img$)
FN.END
FN.DEF gwaimg$(img$) %' shortcut
  FN.RTN GW_ADD_IMAGE$(img$)
FN.END

FN.DEF GW_ADD_IMAGE(idx, img$)
  !' Add the control to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_IMAGE$(img$)
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddImage(idx, img$) %' alias
  FN.RTN GW_ADD_IMAGE(idx, img$)
FN.END
FN.DEF gwaimg(idx, img$) %' shortcut
  FN.RTN GW_ADD_IMAGE(idx, img$)
FN.END

FN.DEF GW_ICON$(ctl_id)
  GW_USE_THEME_CUSTO_ONCE("ui-btn-icon-notext ui-nodisc-icon icon="+GW_ID$(ctl_id))
  FN.RTN ">#"
FN.END
FN.DEF GwIcon$(ctl_id) %' alias
  FN.RTN GW_ICON$(ctl_id)
FN.END
FN.DEF gwico$(ctl_id) %' shortcut
  FN.RTN GW_ICON$(ctl_id)
FN.END

FN.DEF GW_ADD_ICON(idx, ico$, w, h)
  !' Add the control to the page
  e$ = GW_PAGE$(idx)
  u$=GW_NEWID$("icon")
  e$+="<style>.ui-icon-"+u$+":after{"
  e$+="background-image:url("+ico$+");"
  e$+="background-size:"+INT$(w)+"px "+INT$(h)+"px;}"
  e$+="</style>"
  LIST.REPLACE 1, idx, e$
  !' Add the control to the list of controls + return its index
  LIST.ADD 2, u$
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddIcon(idx, ico$, w, h) %' alias
  FN.RTN GW_ADD_ICON(idx, ico$, w, h)
FN.END
FN.DEF gwaico(idx, ico$, w, h) %' shortcut
  FN.RTN GW_ADD_ICON(idx, ico$, w, h)
FN.END

FN.DEF GW_NEW_TBL$(n_cols, table$[]) %' (internal)
  firstrow=1
  IF LEFT$(table$[1], 1)=">" THEN
    e$="<thead><tr>"
    FOR col=1 TO n_cols
      IF LEFT$(table$[col], 1)=">" THEN t$=MID$(table$[col], 2) ELSE t$=table$[col]
      e$+="<th data-priority='persistent'>"+t$+"</th>"
    NEXT
    e$+="</tr></thead>"
    firstrow=2
  END IF
  e$+="<tbody>"
  ARRAY.LENGTH al, table$[]
  FOR row=firstrow TO al/n_cols
    e$+="<tr>"
    FOR col=1 to n_cols
      i=n_cols*(row-1)+col
      e$+="<td>"+table$[i]+"</td>"
    NEXT
    e$+="</tr>"
  NEXT
  e$+="</tbody>"
  FN.RTN e$
FN.END

FN.DEF GW_ADD_TABLE$(n_cols, table$[])
  !' Create the control
  u$=GW_NEWID$("table")
  e$="<table data-role='table' id='"+u$+"' class='ui-responsive ui-shadow' data-mode='columntoggle'"+GW_THEME_CUSTO$("table")+">"
  e$+=GW_NEW_TBL$(n_cols, table$[])
  e$+="</table>"
  !' Add the table's number of columns to the dedicated list
  LIST.ADD 5, n_cols
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddTable$(n_cols, table$[]) %' alias
  FN.RTN GW_ADD_TABLE$(n_cols, table$[])
FN.END
FN.DEF gwata$(n_cols, table$[]) %' shortcut
  FN.RTN GW_ADD_TABLE$(n_cols, table$[])
FN.END

FN.DEF GW_ADD_TABLE(idx, n_cols, table$[])
  !' Add the control to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_TABLE$(n_cols, table$[])
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddTable(idx, n_cols, table$[]) %' alias
  FN.RTN GW_ADD_TABLE(idx, n_cols, table$[])
FN.END
FN.DEF gwata(idx, n_cols, table$[]) %' shortcut
  FN.RTN GW_ADD_TABLE(idx, n_cols, table$[])
FN.END

FN.DEF GW_ADD_VIDEO$(video$)
  FN.RTN "<video controls width='100%' src='"+video$+"'>"+video$+"</video>"
FN.END
FN.DEF GwAddVideo$(video$) %' alias
  FN.RTN GW_ADD_VIDEO$(video$)
FN.END
FN.DEF gwav$(video$) %' shortcut
  FN.RTN GW_ADD_VIDEO$(video$)
FN.END

FN.DEF GW_ADD_VIDEO(idx, video$)
  !' Add the video to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_VIDEO$(video$)
FN.END
FN.DEF GwAddVideo(idx, video$) %' alias
  FN.RTN GW_ADD_VIDEO(idx, video$)
FN.END
FN.DEF gwav(idx, video$) %' shortcut
  FN.RTN GW_ADD_VIDEO(idx, video$)
FN.END

FN.DEF GW_ADD_GW_LOGO$() %' (internal)
  FN.RTN "<img  alt='GW logo' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAS8AAACJCAMAAABKMk6tAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAADDUExURf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANgxu+kAAABAdFJOUwAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gIOHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+/z9/tAXf2zAAAS00lEQVR42u1dWVviwBKthC0gahREZFEURVRUBGQnqf//q+5DCNJd1Z3O4tw7351+nJFATmo5daq6A/Bv/beX1Sz/A8F8OV/ov1X/4WC4bnaIiDj6h5jJKowwXP8Qi161NR6tf4jpV26A0hpV/qGiXGcLJMsfFn/3S/MnlzUbLOf8qtls1l3XdV236jiO4zj5bCJM9fL8V1hEz0dubZvKjzwtUy8PEXG3Rc3apP+Cj1zmcFWmqt87VH6mg3/L+soasPZO8U07tXmBvf0/Baz0rvqe7xPVZ5oA0MP/S8CuNkpfzAEA+0036AIUvb8HsJGVFYsYotYXW7s644prnALA09+DF75kA9f5UuuLuVc24ncQsQ5Q9v8iwO6zYBF9X+uL1QWfIZeIOAOA178IL2ymhutkFuGLHs8oLhAR8Qqg+jfh5V+khKvjRfoij1fwHwsL4P1vAmyajkWMMdoXWbwK3sHAXeFz82bM1bofjherm8Fy89Hvj0USOGpmvVLVdo2tiS+yeLX2/7GwAATQt+lqPpGf9P6Xiuu8OlILvsji9XkUQevCZx/S/SqBAM+t/x24LlaGvsjhVTjk1IUFIKQMrwiQb/TC9TgM1zhc00Mp/PK5/PoYPuz/tAgAkBds/hYAoL8M/v9evNAiuAaT3b3FePjw8v3So6uREC37EU19kcPrRkjRDeHzjwAPiWLxnJbw2yJAJVOGd5cIruq33hfzb3qF4kezxoUFliCb+WVoJ7uXsG4QKXkh05r+JAlFvfX1vni6jFB0PJEDtqQ/thZJbuUDoFEEaAr/eC5fPd1aJGuX6X2x40cpYJ8oGJhoE35FSgGG6wryOAIJ7G8LrGl2ePXjw9XcRfjiKFoxbEhFxq1ImwC+4t/KxoJLxLqcb1sAZ9nhFVuYLowwpi8iIj7pdMKFJWU1rMJpokf/jLiwpXy7LQA8ZwXXOl27zMgXEXFEBLCBZGBiRvwEeIl9LxWwNgGFECuG5wxD/nNMoUujVil9kZVBBPtZWLJu6EIprpD4CVALCwSxTDvLLuRfpm6XRfuid81d61syMLFxOQa4i3kr9ZClPMqaxwSyCvk7O4N2WYQvrs/Yq3UlpinphnWwl3ETfTG4hFcW+B0i3mQV8l/jtMsmiXxxVlLkDV8yDlHTnkFMTtH5eQQvMvqbfEYh/zqDdlnoi2esPYyUTZWRBI+kGzYA3uIkLhtg/pNeJfQH2YR8z7hDVNSIeoEv8pRfI3jXhD+syT60sKC4iSUUu8ehX8wf/kkmIf8zfbts74uFDzSO9GE4XEsB/pQgUDO+kzEI5ugCiHrAVyYh/yZtuyz0xXNW21FE+nD1JQYhsYClDdDoma273CHahxlRYsDBkys6juOcuK7rus1ms9nsKq84+GS4QCllu0zvi7OIy1dkW3dJBI+zWlL+6InPLr5sSxjzlxGLePAT+aIm0odrItVAYh2DazvW7VUkYVWs4eMXyhbxmdtU7TK9L5q0NltykS0xCK367h41IaoU/qY8++NHze3JF7wkt2Qw893xkvmiZ8JUcp6sxM3RtPUhWM+uQoTVtS2LaBHJTYh3uzLTR55Ht8s+MZkvRkR6PkIMZalPZ6M3wtPJH7foDs7TJIzOtE+ys+WHaeIxjW1CX5yZJRIpwPtlsMTU4qm7fd+MuvYqG6cYS1a2qXnhs/RAEBHxNHG7TO+LBpH+eIZCEMmkecNH1QcvZS5yeg9wLgf4urmBdGVVkAiWq4hnv4ryxSLvi3GGWHqyOUlJzVOF2A85sAy2OcnovKLM6LyyWTjEBUA5UvI0bZeFvnjBK4dejJoUHGJOXb2OHWZt4Y+6AHkP2yC1lR4Jo/tQV8dyz6xHbuwiWbts74sqcccw0nN9D8RtXqblPm8SgtjgFQA6iHOA/E7+rCSZ1FRcS0yljhwpEHGrbpVbXT/SFxWZ0zTSh+uaMC7pwY5YLciTRal5oH0OZOOURI+FIuTX5WLUJXf2kqRdFuGLMSI9Px+9tSEv5XFuQ82drBFf7qGtEuMcGnWnp3Kl/8zJt7HbZRG+mGRccUBqRilyvkcF52WopfmOXGK9EdnWc9gKWbzHHNg7U+mroBXptL4YK9IfWgJE9pMnpl36ROWqruSHDKJBjFOC/y1SusQhCROquKBtl0X5YsxIzxJPxBtyh2PyEYGG+sVDzNvakqiGYzqwzqQ5yQZdOQ0ppa+cdrhb74txIz1PFHFhkYnpS3by9ejBH5SEFsA9MU4pgTAjYeIDWgKUyN35Bc435ol9MX6kPyjdPqnypBg9kz7xLlOE2tFflsTLTYlwSFUZkYVgT55O4I1c2y6L8sU0g+kjgo5sYGJqEpn3yjom++dkerhOaqxdkdkIIJKvOdd9kp14Eu2LqjG2RJGe5z6IddIYWggu9CRbgyNE8xqBX6qxZCYl1fhjtlfpxGmX7X2xpOJlCSM92/dAHNOR/ONdAiI/80vC6IVfIrJoneg60ozNFQnsNIrPYrTLQl+8VPWIkkZ6vu+B6BIfPablt3JFKOD9QOYIZqTawW9LrYp7ObDpjUo0t75J7ovJIz1fPCOOqEd0VNZ4JdkHw9+uqcu31QTwhRgcLTL007V6X+QjfXvRj9GsmNBfN0ZF60NkkmtLknbwmvR1yAB2MBIm7jM5pmcjbjZDSKi6/iLmqFAVEemdMSLOzYNai051uCqHEO/8gUhCA2qcN/RyP2NcEv9YyYMdvGxZ04iDQdOh7RtH+n3q8O9NNwvIJbZfJgYWtj7OSdp6oCL9lBqnvG/nTBE879kt5XQIM69m9uuWBQBQ35pFeufnp01Nj554oY//Atne2khOpVI88/NUJMIuzbjhtqnclrTMaANxIz74VwcAwFV3sb8vAbgd2lykF3jJrm24VUT28iL52UHrQ2KyDVJgT6h+ERjniK8H26SDzWwvlIYw97eVe1Tz+48TAIDmNirSl2RJ/9OMa8jhgPYqgm8TK70NdbTADO+pcco1wyZw8DlBsU/vXlJlEXHsRNSP/qAAAPlHTxvpm9Rnt0YbbuR0QpthOKGVXl+ewQjjklyTbvOkKMUBbTOhlyPsGekQ5o/n2Oqtxbi9tQHAGaojvWLSfGDALByGIEoGtqFaRoVYw5YnCdijuo5fldtMiC/sCJUsme1jpwMAUNWMSywbAADlgcdHeuV+tZnB3IGcv2g7v08mQCZAqPgrT0JxVySyGjapdV6yu8mvWbxw17aiVIrJGQBA8X5LI72uAbeL3iVOBM22XPaVCfEmG9uOCs0pZVCyrnNOCsWVRagNIvo5Hi/ESQUA4EQnVLw6/P2Wv7U1wmNk30Mu9+Vdax+kDtjaVActqfD3inKQXJBwiA/s0CaZUzm6atcCAKurGcrx7rlwVNOqG2gwOjVgvKAl5qgz0m+Ww963oiUSPDHx3+4oM62w25ZaarxCE9ONjuOKJsZGBFq4jDxm7oyRUI5ucAlEFatS3nC0lfmeMbCOWBpIwhdOuCkAZghTvG7XipTDvuRJlWLEZp8Pg2HIOcN6OscU3SFKM5kAvFDL3Pgs6jpjyvCo+r+nsDq8QhNzxjoAnmVN90KzU8bvAQBE7UvtMpL5wcC8AslvLZr7BaIkJzq/LGSQJgl+Xp7yZrbDS0LUnQUAcKOb/treSsW0fa/KqysXAPLPWInX90A8+zGwZ5Ledjm6n+Fd6+DDY3VjlyOy2yuty/Z5OQIvxFmVLxiF/CK3uSq8RPZeAID6iuu76to++07Z3mxPSXAeMAi3NT3+wMDqRx8fUPLF6FrM/mPWhSwAgKZWdx3JkbBNLdLrHHrmUXjR7UKV0IMmVFM+Yzy4rKd0L0e8+IQwrZUFuZ2RHMoKE4GJ6acDdt2DU54/5DiL/K7+oB6Fl7VhPCiAqUHQ/GYyxEI3ZbHPqO4hiHdpid9EE+mLnH0gmNiV1sS+wypygasGrbifbADn/aeNEa/vgf5+s//aJsSoTaTDfQUNakqBo4OAdkXIBJ5wUwCKIcyWpzYxvViNz4WDjX5WQDiBaHUBAK0dmuJ1wpUF1jfiA9lb5DGCAxmGoxmkupe3Fhbx/ik3BUCfQfhT2XLGD5oWOrEacXN18Gn/wQaw7oKf6T/mxSN0IvEiERq3eYAa+iXCDoZA573pxNErZ2DDgEx80FzBbehVDWHm+O2UQdMiP4gsDpdHf++uEfHzBKQjdKLxarHkZ/xGuhLoMn88jq4Z8Byg7OPCIsqEVwBgKORO3YJo7DQm5mr3Bh/lDL9vAziTd5e6eTReVBxY2wBOhTQ15pwx3hoY7BgAHvGatrDf+B3LugMenanGxLSTTkKOnYYsI/dKbCJqvSqKXflU2y4X7E4MVCJ0AYrPQJlDjan4g3awJqH3UWNiGrFa5CR75bW6wNh40S1OwahJmzoPeX5rg9GMg9PK5xmtLfak4aj9x4oRibmrF6slDudfAsC5h/HxYuq3q4CtyJWLzZG1qMHgn18xp+TriqtNIofXFONwTzkAgLOZEV64q3Dcz6TxQfWBGcP8LzkFqRE9eH5oPF4yvswVf9H7j1UnVS1dzUgdqRF63HYlk6NLHeQMQpJKlozej1iI3tiAiMHw3Yg+lCJzZ37B4CcrtpztTaw6NcSrlwgvBodP0kG95XCdmHLgGVHShLMr9NIXm9UVBzDtTYwRqzPEiynhOh+0SqITRT2jDTeBgfUZO+JCjekG8ranMzEqVmeIlx3VCBAHorV1cdBZoAZGcsVIcciw8TunqgrusKoBAFiyWJ0hXgbHttQ4ENS7oShr3zAhjesGzswn2JQnTgzzjFjN4dVPiFfkuUAri5toUx8EFP3Gi43FaEkYc+a7sdOZGLS2EXgNE+IF84i767G5TJ3585Ee/qg4SCXeq5PKU62JHUuDmeJ1q785v8TmMs0Y0GMUXlX+ZKNl3Dlv1RftTexHGswUr5L+dNkP1gS/dQ8+Aq4ZR2tNevI0t6i01WEBAKD4psKrlQKviOPdr9gQ109+Qewojm5yY+OlPq49EAlDsZrg1eR+pOHhRmwhd1wYcyn0Il4VL5OvCZ8FEuy9UE7rvBUAAAovKrzGxoySUDBdx+ABuC5OxLGC2lmYdzrWFLY8kyxVeRSaWG2VNV7aN8Y4XGWq2fev0G1FB2f3H9QT7r5Qn08bmFh+2MkYL80LPcbAOk87ucVubHYKIN5JmBLj8/QmBhnjBeoZxwbvPFGFi2YDyxM/BaDaf2z2wJXDJO8lFV6LFHh1dMbQT8CUNBzlVHGScJodipBTziuFryokeC1T4FVQGXSfk5iVTUJtY+CHuOW4b/NTvjlSfchCYGKZ4qU8SLTCs43o0KysSrv8FID5SZhKljzTmthSlhBS4aU4F3PCk0/fYEOhorjzi1ykjc4gJrRIXYe9lyR43JR4WTyJafKy8djgitdK8uWw/1GC9Eu9q3Tb3WSKF5/QtjZfjZscw2itVeSLPdZ7ClmskulLD1LjVVGkflbtOTW54p3qCbC5/y4TvCDiyAU9XrHq/S9edznnSkqjC7Lv5RzwV0TM7B3YF6vEeA3jfM8N7yOc7Gt4XY4SnSn07wVkthQHYmaNF1NUt9h/NWaWzAtB5qr+ygNkuDr+H8CLPvddTkGVCoZXnHCJgt9pke3byauLP4DXGUfivxSkzIxyc9I26y0ryHblhtGKeFq8iGh1psiaxl0cMoDzoSosnyHr1dA3XZwM8OpShf4hne88UbGjy/78i8zxAmfy23hJRXdbwTm35rLxCSVfrPKaQvrSUDHdMe9Z4CUW3V5eUVW+xbjiRA6I/Eu0XuBXloaKZYKXK3+YVS1uYlyRvLjvUSVK/spSK9WZ4CXUPi57TgsyB3OZRvwF8FMAMV4CE3u1dr+JV1dglnxsnse64kAsEevKjvBvrcrMGK/4h6odRfyuqisW7y0Tp6Jiw/vHzS/ipZipZvCaJHhx9UFF9gqq2Bzv/W9HEf9TKXsX4VcXF/YLBK/nJN1i93haid1j4sVM/dfHVSf/ktwv+OXFbG+TBWo/oY3Pf6zI3mYRaw6dyJ2t0qi78OvreqvHK/F5kN2fftm1alYk3nr4KXlO+FxV/n28yOZ4ADji4l+JI8I+wtyCoisRX9cLR6PPVU3cb/gTSzoxHyB3JCOneCf9S9jE4bsSy/hXfD+Qr8SvTcpG5JkJeB1mILxmmquehq35Hntzg/hXrIXk61IprfyZZfeP8Qqp4Oo03VUnQTcTVqr2TrIc4qjeJ7yCP7d+NkkeSo1xWjLTCAaieWPwk1QuraBjmfNUs79/bh1O9AtvME3o2gfGBQ5ANf8wTuQHa8Qm21D5JelLqyLPw3jvIe6uM7jiNTaUTDxZl7CDu5zq/fEb68/iBXbPC+1rmU3ovLJUTByTxUZ7PVTl2/iaQAYl+BgRIPf1WcjumjwTXye82sWJ8rziOvwXVm2adVz8yFwHPWeVqLkN/1bW6z8S6UJFCmYsoQAAAABJRU5ErkJggg==' />"
FN.END

FN.DEF GW_ADD_GW_LOGO(idx) %' (internal)
  !' Add the image to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_GW_LOGO$()
FN.END

FN.DEF GW_FORMAT_LINK$(link$) %' (internal)
  IF IS_IN("#dlgmsg", link$)=1 THEN
    BUNDLE.GET 1, "dlgmsg-transition", dmt$
    href$=link$+"' data-rel='popup' data-position-to='window' data-transition='"+dmt$
  ELSEIF IS_IN("#panel", link$)=1 THEN
    BUNDLE.GET 1, "panel-transition", pt$
    href$=link$+"' data-display='"+pt$
  ELSEIF LOWER$(LEFT$(link$, 4))="http" | LEFT$(link$,1)="#" THEN
    href$=link$+"' data-ajax='false"
  ELSEIF link$<>"" THEN
    href$="javascript:doDataLink("+CHR$(34)+link$+CHR$(34)+");' data-ajax='false"
  END IF
  FN.RTN href$
FN.END

FN.DEF GW_ADD_BUTTON$(label$, link$)
  !' First treat the link: web hyperlink or user command?
  href$=GW_FORMAT_LINK$(link$)
  !' Create the control
  u$=GW_NEWID$("button")
  e$="<a id='"+u$+"' href='"+href$+"' "+GW_THEME_CUSTO$("button")
  e$+=" data-role='button'>"+WEB$(label$)+"</a>"
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddButton$(label$, link$) %' alias
  FN.RTN GW_ADD_BUTTON$(label$, link$)
FN.END
FN.DEF gwab$(label$, link$) %' shortcut
  FN.RTN GW_ADD_BUTTON$(label$, link$)
FN.END

FN.DEF GW_ADD_BUTTON(idx, label$, link$)
  !' Add the control to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_BUTTON$(label$, link$)
  !' Return the index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddButton(idx, label$, link$) %' alias
  FN.RTN GW_ADD_BUTTON(idx, label$, link$)
FN.END
FN.DEF gwab(idx, label$, link$) %' shortcut
  FN.RTN GW_ADD_BUTTON(idx, label$, link$)
FN.END

FN.DEF GW_ADD_LINK$(label$, link$)
  !' First treat the link: web hyperlink or user command?
  href$=GW_FORMAT_LINK$(link$)
  !' Create the control
  u$=GW_NEWID$("link")
  e$="<a id='"+u$+"' href='"+href$+"' "+GW_THEME_CUSTO$("link") %' v1.6: removed <p></p>
  e$+=">"+WEB$(label$)+"</a>"
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddLink$(label$, link$) %' alias
  FN.RTN GW_ADD_LINK$(label$, link$)
FN.END
FN.DEF gwalnk$(label$, link$) %' shortcut
  FN.RTN GW_ADD_LINK$(label$, link$)
FN.END

FN.DEF GW_ADD_LINK(idx, label$, link$)
  !' Add the control to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_LINK$(label$, link$)
  !' Return the index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddLink(idx, label$, link$) %' alias
  FN.RTN GW_ADD_LINK(idx, label$, link$)
FN.END
FN.DEF gwalnk(idx, label$, link$) %' shortcut
  FN.RTN GW_ADD_LINK(idx, label$, link$)
FN.END

FN.DEF GW_ADD_TITLE$(title$)
  !' Create the control
  u$=GW_NEWID$("title")
  e$="<h3 id='"+u$+"' "+GW_THEME_CUSTO$("title")
  e$+=" class='ui-bar ui-bar-a ui-corner-all'>"+WEB$(title$)+"</h3>"
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddTitle$(title$) %' alias
  FN.RTN GW_ADD_TITLE$(title$)
FN.END
FN.DEF gwati$(title$) %' shortcut
  FN.RTN GW_ADD_TITLE$(title$)
FN.END

FN.DEF GW_ADD_TITLE(idx, title$)
  !' Add the control to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_TITLE$(title$)
  !' Return the index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddTitle(idx, title$) %' alias
  FN.RTN GW_ADD_TITLE(idx, title$)
FN.END
FN.DEF gwati(idx, title$) %' shortcut
  FN.RTN GW_ADD_TITLE(idx, title$)
FN.END

FN.DEF GW_ADD_TEXT$(txt$)
  !' First format the default text, if any
  IF LEFT$(txt$, 1)<>"<" THEN ini$="<p>"+txt$+"</p>" ELSE ini$=txt$
  !' Create the control
  u$=GW_NEWID$("text")
  e$="<div class='ui-body' id='"+u$+"' "+GW_THEME_CUSTO$("text")+">"
  e$+=WEB$(ini$)+"</div><!-- /ui-body -->"
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddText$(txt$) %' alias
  FN.RTN GW_ADD_TEXT$(txt$)
FN.END
FN.DEF gwate$(txt$) %' shortcut
  FN.RTN GW_ADD_TEXT$(txt$)
FN.END

FN.DEF GW_ADD_TEXT(idx, txt$)
  !' Add the control to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_TEXT$(txt$)
  !' Return the index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddText(idx, txt$) %' alias
  FN.RTN GW_ADD_TEXT(idx, txt$)
FN.END
FN.DEF gwate(idx, txt$) %' shortcut
  FN.RTN GW_ADD_TEXT(idx, txt$)
FN.END

FN.DEF GW_ADD_TEXTBOX$(txt$)
  !' First format the default text, if any
  IF LEFT$(txt$, 1)<>"<" THEN ini$="<p>"+txt$+"</p>" ELSE ini$=txt$
  !' Create the control
  u$=GW_NEWID$("textbox")
  e$="<div class='ui-body ui-body-a ui-corner-all' id='"+u$+"' "+GW_THEME_CUSTO$("textbox")+">"
  e$+=WEB$(ini$)+"</div><!-- /ui-body -->"
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddTextBox$(txt$) %' alias
  FN.RTN GW_ADD_TEXTBOX$(txt$)
FN.END
FN.DEF gwateb$(txt$) %' shortcut
  FN.RTN GW_ADD_TEXTBOX$(txt$)
FN.END

FN.DEF GW_ADD_TEXTBOX(idx, txt$)
  !' Add the control to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_TEXTBOX$(txt$)
  !' Return the index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddTextBox(idx, txt$) %' alias
  FN.RTN GW_ADD_TEXTBOX(idx, txt$)
FN.END
FN.DEF gwateb(idx, txt$) %' shortcut
  FN.RTN GW_ADD_TEXTBOX(idx, txt$)
FN.END

FN.DEF GW_ADD_FLIPSWITCH$(label$, s_opt1$, s_opt2$)
  u$=GW_NEWID$("flipswitch")
  !' Add the javascript snippet
  e$="<script type='text/javascript'>"
  e$+="$(document.body).on('change','#"+u$+"',function(e){"
  e$+="doDataLink('"+u$+":'+$('#"+u$+"').val());"
  e$+="});</script>"
  !' Create the control
  e$+="<div data-role='fieldcontain'>"
  e$+="<label for='"+u$+"'>"+WEB$(label$)+"</label>"
  BUNDLE.GET 1, "theme", theme$
  IF theme$="ios" | theme$="android-holo" | theme$="metro" THEN
    e$+="<select name='"+u$+"' id='"+u$+"' data-role='slider' "+GW_THEME_CUSTO$("flipswitch")+">"
  ELSE
    e$+="<select name='"+u$+"' id='"+u$+"' data-role='flipswitch' "+GW_THEME_CUSTO$("flipswitch")+">"
  END IF
  e$+="<option value='"+WEB$(s_opt1$)+"'>"+WEB$(s_opt1$)+"</option>"
  e$+="<option "
  r$=WEB$(s_opt2$)
  IF LEFT$(r$,1)=">" THEN
    e$+="selected "
    r$=MID$(r$,2)
  END IF
  e$+="value='"+r$+"'>"+r$+"</option>"
  e$+="</select>"
  e$+="</div><!-- /fieldcontain -->"
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddFlipSwitch$(label$, s_opt1$, s_opt2$) %' alias
  FN.RTN GW_ADD_FLIPSWITCH$(label$, s_opt1$, s_opt2$)
FN.END
FN.DEF gwafs$(label$, s_opt1$, s_opt2$) %' shortcut
  FN.RTN GW_ADD_FLIPSWITCH$(label$, s_opt1$, s_opt2$)
FN.END

FN.DEF GW_ADD_FLIPSWITCH(idx, label$, s_opt1$, s_opt2$)
  !' Add the control to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_FLIPSWITCH$(label$, s_opt1$, s_opt2$)
  !' Return the index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddFlipSwitch(idx, label$, s_opt1$, s_opt2$) %' alias
  FN.RTN GW_ADD_FLIPSWITCH(idx, label$, s_opt1$, s_opt2$)
FN.END
FN.DEF gwafs(idx, label$, s_opt1$, s_opt2$) %' shortcut
  FN.RTN GW_ADD_FLIPSWITCH(idx, label$, s_opt1$, s_opt2$)
FN.END

!'---------------------------------------------------------------------------------------------
!' FUNCTIONS TO ADD USER INPUT CONTROLS --> INPUTFORM NEEDED (HANDLED TRANSPARENTLY FOR THE USER)
!'---------------------------------------------------------------------------------------------
FN.DEF GW_OPEN_INPUTFORM$(idx) %' (internal)
  !' Open a form in the page
  u$=GW_NEWID$("form")
  FN.RTN "<form id='"+u$+"' data-ajax='false'>"
FN.END

FN.DEF GW_NEW_LI$(txt_axn$[]) %' (internal)
  ARRAY.LENGTH al, txt_axn$[]
  FOR i=1 TO al
    k=IS_IN(">", txt_axn$[i])
    IF !k THEN k=LEN(txt_axn$[i])+1
    tx$=WEB$(LEFT$(txt_axn$[i], k-1))
    ax$=GW_FORMAT_LINK$(MID$(txt_axn$[i], k+1))
    e$+="<li><a href='"+ax$+"'>"+tx$+"</a></li>"
  NEXT
  FN.RTN e$
FN.END

FN.DEF GW_ADD_INPUTLIST$(hint$, txt_axn$[])
  !' Create the control
  u$=GW_NEWID$("inputlist")
  e$="<input data-type='search' id='"+u$+"' placeholder='"+WEB$(hint$)+"' "+GW_THEME_CUSTO$("inputlist")+">"
  e$+="<ul data-filter='true' data-filter-reveal='true'"
  e$+=" data-role='listview' data-input='#"+u$+"' data-inset='true'>"
  e$+=GW_NEW_LI$(txt_axn$[])
  e$+="</ul>"
  !' Add to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddInputList$(hint$, txt_axn$[]) %' alias
  FN.RTN GW_ADD_INPUTLIST$(hint$, txt_axn$[])
FN.END
FN.DEF gwails$(hint$, txt_axn$[]) %' shortcut
  FN.RTN GW_ADD_INPUTLIST$(hint$, txt_axn$[])
FN.END

FN.DEF GW_ADD_INPUTLIST(idx, hint$, txt_axn$[])
  !' Add the element to the page
  e$ = GW_PAGE$(idx)
  IF !IS_IN("<form ",e$,IS_IN("role='content'",e$)) THEN e$+=GW_OPEN_INPUTFORM$(idx)
  e$+=GW_ADD_INPUTLIST$(hint$, txt_axn$[])
  LIST.REPLACE 1, idx, e$
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddInputList(idx, hint$, txt_axn$[]) %' alias
  FN.RTN GW_ADD_INPUTLIST(idx, hint$, txt_axn$[])
FN.END
FN.DEF gwails(idx, hint$, txt_axn$[]) %' shortcut
  FN.RTN GW_ADD_INPUTLIST(idx, hint$, txt_axn$[])
FN.END

FN.DEF GW_NEW_OPT$(txt$[]) %' (internal)
  ARRAY.LENGTH al, txt$[]
  FOR i=1 TO al
    e$+="<option "
    IF LEFT$(txt$[i], 1)=">" THEN
      e$+="selected='selected' "
      txt$[i]=MID$(txt$[i], 2)
    END IF
    e$+="value='"+INT$(i)+"'>"+WEB$(txt$[i])+"</option>"
  NEXT
  FN.RTN e$
FN.END

FN.DEF GW_ADD_SELECTBOX$(label$, txt$[])
  !' Create the control
  u$=GW_NEWID$("selectbox")
  e$="<div class='ui-field-contain'>"
  e$+="<label for='"+u$+"'>"+WEB$(label$)+"</label>"
  e$+="<select name='"+u$+"' id='"+u$+"' data-native-menu='false' "+GW_THEME_CUSTO$("selectbox")+">"
  IF label$<>"" THEN e$+="<option>"+WEB$(label$)+"</option>"
  e$+=GW_NEW_OPT$(txt$[])
  e$+="</select></div>"
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddSelectBox$(label$, txt$[]) %' alias
  FN.RTN GW_ADD_SELECTBOX$(label$, txt$[])
FN.END
FN.DEF gwasb$(label$, txt$[]) %' shortcut
  FN.RTN GW_ADD_SELECTBOX$(label$, txt$[])
FN.END

FN.DEF GW_ADD_SELECTBOX(idx, label$, txt$[])
  !' Add the control to the page
  e$ = GW_PAGE$(idx)
  IF !IS_IN("<form ",e$,IS_IN("role='content'",e$)) THEN e$+=GW_OPEN_INPUTFORM$(idx)
  e$+=GW_ADD_SELECTBOX$(label$, txt$[])
  LIST.REPLACE 1, idx, e$
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddSelectBox(idx, label$, txt$[]) %' alias
  FN.RTN GW_ADD_SELECTBOX(idx, label$, txt$[])
FN.END
FN.DEF gwasb(idx, label$, txt$[]) %' shortcut
  FN.RTN GW_ADD_SELECTBOX(idx, label$, txt$[])
FN.END

FN.DEF GW_ADD_RADIO$(parent, label$)
  !' Create the control
  u$=GW_NEWID$("radio")
  IF !parent THEN v$=u$ ELSE v$=GW_ID$(parent)
  r$=WEB$(label$)
  IF LEFT$(r$,1)=">" THEN
    checked$="checked='checked' "
    r$=MID$(r$,2)
  END IF
  e$="<label for='"+u$+"'>"+r$+"</label>"
  e$+="<input name='"+v$+"' id='"+u$+"' value='"+u$+"' "+checked$
  e$+=GW_THEME_CUSTO$("radio")+" type='radio' />"
  !' Add the parent to the list of radio parents
  LIST.SIZE 2, ls
  ls++
  IF !parent THEN parent=ls
  LIST.ADD 4, parent
  !' Add the child to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddRadio$(parent, label$) %' alias
  FN.RTN GW_ADD_RADIO$(parent, label$)
FN.END
FN.DEF gwar$(parent, label$) %' shortcut
  FN.RTN GW_ADD_RADIO$(parent, label$)
FN.END

FN.DEF GW_ADD_RADIO(idx, parent, label$)
  !' Add the control to the page
  e$ = GW_PAGE$(idx)
  IF !IS_IN("<form ",e$,IS_IN("role='content'",e$)) THEN e$+=GW_OPEN_INPUTFORM$(idx)
  e$+=GW_ADD_RADIO$(parent, label$)
  LIST.REPLACE 1, idx, e$
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddRadio(idx, parent, label$) %' alias
  FN.RTN GW_ADD_RADIO(idx, parent, label$)
FN.END
FN.DEF gwar(idx, parent, label$) %' shortcut
  FN.RTN GW_ADD_RADIO(idx, parent, label$)
FN.END

FN.DEF GW_RADIO_PARENT(ctl_id) %' (internal)
  !' Returns the radio parent id for a given radio child id
  e$=GW_ID$(ctl_id) %' "radioN"
  child_id=VAL(MID$(e$, 6)) %' N
  LIST.GET 4, child_id, parent_id
  FN.RTN parent_id
FN.END

FN.DEF GW_ADD_CHECKBOX$(label$)
  !' Create the control
  u$=GW_NEWID$("checkbox")
  r$=WEB$(label$)
  IF LEFT$(r$,1)=">" THEN
    checked$="checked='' "
    r$=MID$(r$,2)
  END IF
  IF LEN(r$) THEN e$="<label for='"+u$+"'>"+r$+"</label>"
  e$+="<input name='"+u$+"' id='"+u$+"' "+checked$
  e$+=GW_THEME_CUSTO$("checkbox")+" type='checkbox' />"
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddCheckBox$(label$) %' alias
  FN.RTN GW_ADD_CHECKBOX$(label$)
FN.END
FN.DEF gwac$(label$) %' shortcut
  FN.RTN GW_ADD_CHECKBOX$(label$)
FN.END
FN.DEF gwacb$(label$) %' alternate shortcut
  FN.RTN GW_ADD_CHECKBOX$(label$)
FN.END

FN.DEF GW_ADD_CHECKBOX(idx, label$)
  !' Add the control to the page
  e$ = GW_PAGE$(idx)
  IF !IS_IN("<form ",e$,IS_IN("role='content'",e$)) THEN e$+=GW_OPEN_INPUTFORM$(idx)
  e$+=GW_ADD_CHECKBOX$(label$)
  LIST.REPLACE 1, idx, e$
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddCheckBox(idx, label$) %' alias
  FN.RTN GW_ADD_CHECKBOX(idx, label$)
FN.END
FN.DEF gwac(idx, label$) %' shortcut
  FN.RTN GW_ADD_CHECKBOX(idx, label$)
FN.END
FN.DEF gwacb(idx, label$) %' alternate shortcut
  FN.RTN GW_ADD_CHECKBOX(idx, label$)
FN.END

FN.DEF GW_ADD_SLIDER$(label$, n_min, n_max, n_step, n_ini)
  !' Create the control
  u$=GW_NEWID$("slider")
  e$="<div data-role='fieldcontain'>"
  e$+="<label for='"+u$+"'>"+WEB$(label$)+"</label>"
  e$+="<input name='"+u$+"' id='"+u$+"' "+GW_THEME_CUSTO$("slider")
  e$+=" min='"+ENT$(n_min)+"' max='"+ENT$(n_max)+"'"
  e$+=" step='"+ENT$(n_step)+"' value='"+ENT$(n_ini)+"'"
  e$+=" type='range' data-highlight='true' />"
  e$+="</div><!-- /fieldcontain -->"
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddSlider$(label$, n_min, n_max, n_step, n_ini) %' alias
  FN.RTN GW_ADD_SLIDER$(label$, n_min, n_max, n_step, n_ini)
FN.END
FN.DEF gwasl$(label$, n_min, n_max, n_step, n_ini) %' shortcut
  FN.RTN GW_ADD_SLIDER$(label$, n_min, n_max, n_step, n_ini)
FN.END

FN.DEF GW_ADD_SLIDER(idx, label$, n_min, n_max, n_step, n_ini)
  !' Add the control to the page
  e$ = GW_PAGE$(idx)
  IF !IS_IN("<form ",e$,IS_IN("role='content'",e$)) THEN e$+=GW_OPEN_INPUTFORM$(idx)
  e$+=GW_ADD_SLIDER$(label$, n_min, n_max, n_step, n_ini)
  LIST.REPLACE 1, idx, e$
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddSlider(idx, label$, n_min, n_max, n_step, n_ini) %' alias
  FN.RTN GW_ADD_SLIDER(idx, label$, n_min, n_max, n_step, n_ini)
FN.END
FN.DEF gwasl(idx, label$, n_min, n_max, n_step, n_ini) %' shortcut
  FN.RTN GW_ADD_SLIDER(idx, label$, n_min, n_max, n_step, n_ini)
FN.END

FN.DEF GW_ADD_INPUT$(type$, label$, s_ini$) %' (internal) generic class for input controls
  !' Create the control
  u$=GW_NEWID$("input"+type$)
  e$="<div data-role='fieldcontain'>"
  e$+="<label for='"+u$+"'>"+WEB$(label$)+"</label>"
  e$+="<input name='"+u$+"' id='"+u$+"'"
  IF type$="number" THEN e$+=" step='any'" %' to allow decimal numbers
  e$+=" value='"+ WEB$(s_ini$)+"'"
  e$+=" type='"+type$+"' "+ GW_THEME_CUSTO$("input"+type$)
  e$+=" data-clear-btn='true'>"
  e$+="</div><!-- /fieldcontain -->"
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END

FN.DEF GW_ADD_INPUT(type$, idx, label$, s_ini$) %' (internal) generic class for input controls
  !' Add the control to the page
  e$ = GW_PAGE$(idx)
  IF !IS_IN("<form ",e$,IS_IN( "role='content'",e$)) THEN e$+=GW_OPEN_INPUTFORM$(idx)
  e$+=GW_ADD_INPUT$(type$, label$, s_ini$)
  LIST.REPLACE 1, idx, e$
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END

FN.DEF GW_ADD_INPUTLINE$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("text", label$, s_ini$)
FN.END
FN.DEF GwAddInputLine$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTLINE$(label$, s_ini$)
FN.END
FN.DEF gwailn$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTLINE$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTDATE$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("date", label$, s_ini$)
FN.END
FN.DEF GwAddInputDate$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTDATE$(label$, s_ini$)
FN.END
FN.DEF gwaid$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTDATE$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTTIME$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("time", label$, s_ini$)
FN.END
FN.DEF GwAddInputTime$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTTIME$(label$, s_ini$)
FN.END
FN.DEF gwaiti$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTTIME$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTDATETIME$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("datetime-local", label$, s_ini$)
FN.END
FN.DEF GwAddInputDateTime$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTDATETIME$(label$, s_ini$)
FN.END
FN.DEF gwaidt$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTDATETIME$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTMONTH$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("month", label$, s_ini$)
FN.END
FN.DEF GwAddInputMonth$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTMONTH$(label$, s_ini$)
FN.END
FN.DEF gwaim$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTMONTH$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTWEEK$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("week", label$, s_ini$)
FN.END
FN.DEF GwAddInputWeek$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTWEEK$(label$, s_ini$)
FN.END
FN.DEF gwaiw$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTWEEK$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTURL$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("url", label$, s_ini$)
FN.END
FN.DEF GwAddInputUrl$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTURL$(label$, s_ini$)
FN.END
FN.DEF gwaiu$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTURL$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTEMAIL$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("email", label$, s_ini$)
FN.END
FN.DEF GwAddInputEmail$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTEMAIL$(label$, s_ini$)
FN.END
FN.DEF gwaie$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTEMAIL$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTCOLOR$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("color", label$, s_ini$)
FN.END
FN.DEF GwAddInputColor$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTCOLOR$(label$, s_ini$)
FN.END
FN.DEF gwaic$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTCOLOR$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTNUMBER$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("number", label$, s_ini$)
FN.END
FN.DEF GwAddInputNumber$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTNUMBER$(label$, s_ini$)
FN.END
FN.DEF gwain$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTNUMBER$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTTEL$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("tel", label$, s_ini$)
FN.END
FN.DEF GwAddInputTel$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTTEL$(label$, s_ini$)
FN.END
FN.DEF gwaite$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTTEL$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTPASSWORD$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("password", label$, s_ini$)
FN.END
FN.DEF GwAddInputPassword$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTPASSWORD $(label$, s_ini$)
FN.END
FN.DEF gwaip$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTPASSWORD $(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTFILE$(label$, s_ini$)
  FN.RTN GW_ADD_INPUT$("file", label$, s_ini$)
FN.END
FN.DEF GwAddInputFile$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTFILE$(label$, s_ini$)
FN.END
FN.DEF gwaif$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTFILE$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTLINE(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("text", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputLine(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTLINE(idx, label$, s_ini$)
FN.END
FN.DEF gwailn(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTLINE(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTDATE(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("date", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputDate(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTDATE(idx, label$, s_ini$)
FN.END
FN.DEF gwaid(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTDATE(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTTIME(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("time", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputTime(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTTIME(idx, label$, s_ini$)
FN.END
FN.DEF gwaiti(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTTIME(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTDATETIME(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("datetime-local", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputDateTime(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTDATETIME(idx, label$, s_ini$)
FN.END
FN.DEF gwaidt(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTDATETIME(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTMONTH(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("month", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputMonth(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTMONTH(idx, label$, s_ini$)
FN.END
FN.DEF gwaim(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTMONTH(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTWEEK(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("week", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputWeek(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTWEEK(idx, label$, s_ini$)
FN.END
FN.DEF gwaiw(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTWEEK(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTURL(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("url", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputUrl(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTURL(idx, label$, s_ini$)
FN.END
FN.DEF gwaiu(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTURL(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTEMAIL(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("email", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputEmail(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTEMAIL(idx, label$, s_ini$)
FN.END
FN.DEF gwaie(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTEMAIL(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTCOLOR(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("color", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputColor(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTCOLOR(idx, label$, s_ini$)
FN.END
FN.DEF gwaic(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTCOLOR(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTNUMBER(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("number", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputNumber(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTNUMBER(idx, label$, s_ini$)
FN.END
FN.DEF gwain(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTNUMBER(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTTEL(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("tel", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputTel(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTTEL(idx, label$, s_ini$)
FN.END
FN.DEF gwaite(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTTEL(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTPASSWORD(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("password", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputPassword(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTPASSWORD (idx, label$, s_ini$)
FN.END
FN.DEF gwaip(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTPASSWORD (idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTFILE(idx, label$, s_ini$)
  FN.RTN GW_ADD_INPUT("file", idx, label$, s_ini$)
FN.END
FN.DEF GwAddInputFile(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTFILE(idx, label$, s_ini$)
FN.END
FN.DEF gwaif(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTFILE(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTBOX$(label$, s_ini$)
  !' Create the control
  u$=GW_NEWID$("inpbox")
  e$="<label for='"+u$+"'>"+WEB$(label$)+"</label>"
  e$+="<textarea name='"+u$+"' id='"+u$+"' "+GW_THEME_CUSTO$("inpbox")
  e$+=" cols='20' rows='3'>"+WEB$(s_ini$)+"</textarea>"
  !' Add the control to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddInputBox$(label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTBOX$(label$, s_ini$)
FN.END
FN.DEF gwaib$(label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTBOX$(label$, s_ini$)
FN.END

FN.DEF GW_ADD_INPUTBOX(idx, label$, s_ini$)
  !' Add the control to the page
  e$ = GW_PAGE$(idx)
  IF !IS_IN("<form ",e$,IS_IN("role='content'",e$)) THEN e$+=GW_OPEN_INPUTFORM$(idx)
  e$+=GW_ADD_INPUTBOX$(label$, s_ini$)
  LIST.REPLACE 1, idx, e$
  !' Return index of the control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddInputBox(idx, label$, s_ini$) %' alias
  FN.RTN GW_ADD_INPUTBOX(idx, label$, s_ini$)
FN.END
FN.DEF gwaib(idx, label$, s_ini$) %' shortcut
  FN.RTN GW_ADD_INPUTBOX(idx, label$, s_ini$)
FN.END

FN.DEF GW_ADD_SUBMIT$(submit$)
  !' Create the submit button
  u$=GW_NEWID$("submit")
  e$="<input name='"+u$+"' id='"+u$+"' value='"+WEB$(submit$)+"'"
  e$+=" type='submit' "+GW_THEME_CUSTO$("submit")+">"
  !' Add the submit button to the list of controls + return its content
  LIST.ADD 2, u$
  FN.RTN e$
FN.END
FN.DEF GwAddSubmit$(submit$) %' alias
  FN.RTN GW_ADD_SUBMIT$(submit$)
FN.END
FN.DEF gwasu$(submit$) %' shortcut
  FN.RTN GW_ADD_SUBMIT$(submit$)
FN.END

FN.DEF GW_ADD_SUBMIT(idx, submit$)
  !' Add the submit button to the page
  e$ = GW_PAGE$(idx)
  IF !IS_IN("<form ",e$,IS_IN("role='content'",e$)) THEN e$+=GW_OPEN_INPUTFORM$(idx)
  e$+=GW_ADD_SUBMIT$(submit$)
  LIST.REPLACE 1, idx, e$
  !' Return index of the submit button
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwAddSubmit(idx, submit$) %' alias
  FN.RTN GW_ADD_SUBMIT(idx, submit$)
FN.END
FN.DEF gwasu(idx, submit$) %' shortcut
  FN.RTN GW_ADD_SUBMIT(idx, submit$)
FN.END

!'---------------------------------------------------------------------------------------------
!' FUNCTIONS TO RENDER AND INTERACT WITH THE GW PAGE
!'---------------------------------------------------------------------------------------------
FN.DEF GW_PREVENT_LANDSCAPE(idx, msg$) %' deprecated, prefer: HTML.ORIENTATION 1
  e$ = GW_PAGE$(idx)
  e$=REPLACE$(e$, "data-position='fixed' ", "") %' remove the 'fixed' position of the header
  e$+="<div id='blockland' style='position:fixed; top:0; left:0; z-index:10;"
  e$+=" text-align:center; background:gray; width:100%; height:100%; display:none;'>"
  e$+="<span id='blockmsg' style='font-size:5vw; display:inline-block; vertical-align:middle; line-height:normal;'>"
  e$+=WEB$(msg$)+"</span></div>"
  e$+="<script>$(window).resize(function() {"
  e$+="($(window).width()<$(window).height())?"
  e$+="$('#blockland').css('display','none'):"
  e$+="$('#blockland').css('display','block');"
  e$+="$('#blockmsg').css('margin-top',($(window).height()-$('#blockmsg').height())/2);"
  e$+="}); $(window).trigger('resize');</script>"
  LIST.REPLACE 1, idx, e$
FN.END

FN.DEF GW_PREVENT_PORTRAIT(idx, msg$) %' deprecated, prefer: HTML.ORIENTATION 0
  e$ = GW_PAGE$(idx)
  e$=REPLACE$(e$, "data-position='fixed' ", "") %' remove the 'fixed' position of the header
  e$+="<div id='blockland' style='position:fixed; top:0; left:0; z-index:10;"
  e$+=" text-align:center; background:gray; width:100%; height:100%; display:none;'>"
  e$+="<span id='blockmsg' style='font-size:5vw; display:inline-block; vertical-align:middle; line-height:normal;'>"
  e$+=WEB$(msg$)+"</span></div>"
  e$+="<script>$(window).resize(function() {"
  e$+="($(window).width()>$(window).height())?"
  e$+="$('#blockland').css('display','none'):"
  e$+="$('#blockland').css('display','block');"
  e$+="$('#blockmsg').css('margin-top',($(window).height()-$('#blockmsg').height())/2);"
  e$+="}); $(window).trigger('resize');</script>"
  LIST.REPLACE 1, idx, e$
FN.END

FN.DEF GW_RENDER(idx)
  e$ = GW_PAGE$(idx)
  IF !IS_IN("</html>", e$) THEN
    IF IS_IN("<form ", e$) THEN e$+="</form>"
    e$+="</div><!-- /content -->"
    e$+="</div><!-- /page -->"
    e$+="</body>"
    e$+="</html>"
    LIST.REPLACE 1, idx, e$
  END IF
  HTML.LOAD.STRING e$
FN.END
FN.DEF GwRender(idx) %' alias
  FN.RTN GW_RENDER(idx)
FN.END
FN.DEF gwr(idx) %' shortcut
  FN.RTN GW_RENDER(idx)
FN.END

FN.DEF GW_WAIT_ACTION$()
  DO
    HTML.GET.DATALINK data$
    PAUSE 1
  UNTIL data$ <> ""
  IF IS_IN("BAK:", data$) = 1
    data$ = "BACK"
  ELSEIF IS_IN("DAT:", data$) = 1
    data$ = MID$(data$, 5) %' User link
  ELSEIF IS_IN("LNK:file:///", data$) = 1 & IS_IN("?", data$) %' Submit link
    i=IS_IN("?", data$)
    data$="SUBMIT&"+MID$(data$, i+1)+"&"
  END IF
  BUNDLE.PUT 1, "callback", data$
  FN.RTN data$
FN.END
FN.DEF GwWaitAction$() %' alias
  FN.RTN GW_WAIT_ACTION$()
FN.END
FN.DEF gww$() %' shortcut
  FN.RTN GW_WAIT_ACTION$()
FN.END
FN.DEF gwwa$() %' alternate shortcut
  FN.RTN GW_WAIT_ACTION$()
FN.END

FN.DEF GW_GET_VALUE(ctl_id)
  e$=GW_GET_VALUE$(ctl_id)
  IF e$="" THEN FN.RTN 0 ELSE FN.RTN VAL(e$)
FN.END
FN.DEF GwGetValue(ctl_id) %' alias
  FN.RTN GW_GET_VALUE(ctl_id)
FN.END
FN.DEF gwg(ctl_id) %' shortcut
  FN.RTN GW_GET_VALUE(ctl_id)
FN.END
FN.DEF gwgv(ctl_id) %' alternate shortcut
  FN.RTN GW_GET_VALUE(ctl_id)
FN.END

FN.DEF GW_GET_VALUE$(ctl_id)
  !' Parse the submit string and retrieve the value of the desired control
  BUNDLE.GET 1, "callback", answer$
  ctl$ = GW_ID$(ctl_id)
  i=IS_IN("&"+ctl$+"=", answer$)
  IF !i THEN %' trick to get the live content of a control
    IF IS_IN("checkbox", ctl$) THEN
      HTML.LOAD.URL "javascript:doDataLink(document.getElementById('"+ctl$+"').checked)"
      r$=GW_WAIT_ACTION$()
      IF r$="true" THEN FN.RTN "1" ELSE FN.RTN "0"
    ELSE
      HTML.LOAD.URL "javascript:doDataLink(document.getElementById('"+ctl$+"').value)"
      FN.RTN GW_WAIT_ACTION$()
    END IF
    FN.RTN r$
  ELSEIF IS_IN("checkbox", ctl$) THEN
    IF !i THEN FN.RTN "0" ELSE FN.RTN "1"
  END IF
  i+=LEN("&"+ctl$+"=")
  j=IS_IN("&", answer$, i)
  IF !j THEN FN.RTN ""
  FN.RTN URL_DECODE$(MID$(answer$, i, j-i))
FN.END
FN.DEF GwGetValue$(ctl_id) %' alias
  FN.RTN GW_GET_VALUE$(ctl_id)
FN.END
FN.DEF gwg$(ctl_id) %' shortcut
  FN.RTN GW_GET_VALUE$(ctl_id)
FN.END
FN.DEF gwgv$(ctl_id) %' alternate shortcut
  FN.RTN GW_GET_VALUE$(ctl_id)
FN.END

FN.DEF GW_CHECKBOX_CHECKED(ctl_id)
  !' Returns true/false if the checkbox is or not checked
  FN.RTN GW_GET_VALUE(ctl_id)
FN.END
FN.DEF GwCheckBoxChecked(ctl_id) %' alias
  FN.RTN GW_CHECKBOX_CHECKED(ctl_id)
FN.END
FN.DEF gwcc(ctl_id) %' shortcut
  FN.RTN GW_CHECKBOX_CHECKED(ctl_id)
FN.END
FN.DEF gwcbc(ctl_id) %' alternate shortcut
  FN.RTN GW_CHECKBOX_CHECKED(ctl_id)
FN.END

FN.DEF GW_RADIO_SELECTED(ctl_id)
  !' Returns true/false if the radio button is or not selected
  FN.RTN (GW_GET_VALUE$(GW_RADIO_PARENT(ctl_id))=GW_ID$(ctl_id))
FN.END
FN.DEF GwRadioSelected(ctl_id) %' alias
  FN.RTN GW_RADIO_SELECTED(ctl_id)
FN.END
FN.DEF gwrs(ctl_id) %' shortcut
  FN.RTN GW_RADIO_SELECTED(ctl_id)
FN.END

FN.DEF GW_FLIPSWITCH_CHANGED(ctl_id, txt$)
  !' Returns true/false if the desired flip switch was just triggered to a 'txt$' state
  BUNDLE.GET 1, "callback", answer$
  ctl$ = GW_ID$(ctl_id)
  FN.RTN (answer$=ctl$+":"+txt$)
FN.END
FN.DEF GwFlipSwitchChanged(ctl_id, txt$) %' alias
  FN.RTN GW_FLIPSWITCH_CHANGED(ctl_id, txt$)
FN.END
FN.DEF gwfc(ctl_id, txt$) %' shortcut
  FN.RTN GW_FLIPSWITCH_CHANGED(ctl_id, txt$)
FN.END
FN.DEF gwfsc(ctl_id, txt$) %' alternate shortcut
  FN.RTN GW_FLIPSWITCH_CHANGED(ctl_id, txt$)
FN.END

FN.DEF GW_MODIFY(ctl_id, key$, txt$)
  !' Get Unique IDentifier of the control
  ctl$ = GW_ID$(ctl_id)
  key$=LOWER$(key$)
  DQ$=CHR$(34)
  ctyp$=ctl$
  WHILE ASCII(ctyp$, LEN(ctyp$))<58
    ctyp$=LEFT$(ctyp$, LEN(ctyp$)-1)
  REPEAT
  !' Push the new content inside the control
  IF key$="text" & IS_IN("text", ctyp$)=1 THEN %' TEXTBOX, TEXT
    IF LEFT$(txt$,1)<>"<" THEN txt$="<p>"+txt$+"</p>"
    HTML.LOAD.URL "javascript:populate("+DQ$+ctl$+DQ$+","+DQ$+WEB$(txt$)+DQ$+")"
  ELSEIF key$="text" & (ctyp$="link" | ctyp$="button" ~
    | ctyp$="title" | ctyp$="inpbox") THEN %' LINK, BUTTON, TITLE, INPUTBOX
    HTML.LOAD.URL "javascript:populate("+DQ$+ctl$+DQ$+","+DQ$+WEB$(txt$)+DQ$+")"
  ELSEIF key$="checked" & ctyp$="checkbox" THEN %' CHECKBOX
    IF txt$="" THEN v=0 ELSE v=VAL(txt$)
    IF v THEN txt$="true" ELSE txt$="false"
    HTML.LOAD.URL "javascript:document.getElementById("+DQ$+ctl$+DQ$+").checked="+txt$
    HTML.LOAD.URL "javascript:$('#"+ctl$+"').checkboxradio('refresh')"
  ELSEIF key$="selected" & ctyp$="flipswitch" THEN %' FLIPSWITCH
    HTML.LOAD.URL "javascript:$('#"+ctl$+"').val('"+txt$+"').flipswitch('refresh')"
  ELSEIF key$="selected" & ctyp$="radio" THEN %' RADIO
    IF txt$="" THEN v=0 ELSE v=VAL(txt$)
    IF v THEN
      HTML.LOAD.URL "javascript:document.getElementById("+DQ$+ctl$+DQ$+").checked=true"
    ELSE
      HTML.LOAD.URL "javascript:$('input[name="+GW_ID$(GW_RADIO_PARENT(ctl_id))+"]').attr('checked',false)"
    END IF
    HTML.LOAD.URL "javascript:$('input[name="+GW_ID$(GW_RADIO_PARENT(ctl_id))+"]').checkboxradio('refresh')"
  ELSEIF ctyp$="slider" THEN %' SLIDER
    IF key$="val" THEN
      HTML.LOAD.URL "javascript:document.getElementById("+DQ$+ctl$+DQ$+").value="+DQ$+ENT$(VAL(txt$))+DQ$
    ELSEIF key$="min" THEN
      HTML.LOAD.URL "javascript:document.getElementById("+DQ$+ctl$+DQ$+").min="+DQ$+ENT$(VAL(txt$))+DQ$
    ELSEIF key$="max" THEN
      HTML.LOAD.URL "javascript:document.getElementById("+DQ$+ctl$+DQ$+").max="+DQ$+ENT$(VAL(txt$))+DQ$
    ELSEIF key$="step" THEN
      HTML.LOAD.URL "javascript:document.getElementById("+DQ$+ctl$+DQ$+").step="+DQ$+ENT$(VAL(txt$))+DQ$
    ELSE %' Throw an error
      (incorrect_key)
    ENDIF
  ELSEIF key$="text" & ctyp$="inputlist" THEN %' INPUTLIST
    HTML.LOAD.URL "javascript:document.getElementById("+DQ$+ctl$+DQ$+").placeholder="+DQ$+WEB$(txt$)+DQ$
  ELSEIF key$="text" & (IS_IN("input", ctyp$)=1 | ctyp$="submit") THEN %' ALL OTHER INPUT*, SUBMIT
    HTML.LOAD.URL "javascript:document.getElementById("+DQ$+ctl$+DQ$+").value="+DQ$+WEB$(txt$)+DQ$
  ELSEIF key$="link" & (ctyp$="link" | ctyp$="button") THEN %' LINK, BUTTON
    HTML.LOAD.URL "javascript:document.getElementById("+DQ$+ctl$+DQ$+").href="+DQ$+GW_FORMAT_LINK$(txt$)+DQ$
  ELSEIF key$="content" & ctyp$="image" THEN %' IMAGE
    HTML.LOAD.URL "javascript:document.getElementById("+DQ$+ctl$+DQ$+").src="+DQ$+WEB$(txt$)+DQ$
  ELSEIF (key$="title" | key$="lbutton" | key$="rbutton") & (ctyp$="titlebar" | ctyp$="footbar") THEN %' TITLEBAR/FOOTBAR
    HTML.LOAD.URL "javascript:populate("+DQ$+ctl$+"-"+key$+DQ$+","+DQ$+WEB$(txt$)+DQ$+")"
  ELSEIF (key$="title" | key$="text") & ctyp$="dlgmsg" THEN %' DIALOG_MESSAGE
    HTML.LOAD.URL "javascript:populate("+DQ$+ctl$+"-"+key$+DQ$+","+DQ$+WEB$(txt$)+DQ$+")"
  ELSE %' Throw an error
    (incorrect_key)
  END IF
FN.END
FN.DEF GwModify(ctl_id, key$, txt$) %' alias
  FN.RTN GW_MODIFY(ctl_id, key$, txt$)
FN.END
FN.DEF gwm(ctl_id, key$, txt$) %' shortcut
  FN.RTN GW_MODIFY(ctl_id, key$, txt$)
FN.END

FN.DEF GW_AMODIFY(ctl_id, key$, t$[]) %' ARRAY-MODIFY
  !' Get Unique IDentifier of the control
  ctl$ = GW_ID$(ctl_id)
  key$=LOWER$(key$)
  DQ$=CHR$(34)
  ctyp$=ctl$
  WHILE ASCII(ctyp$, LEN(ctyp$))<58
    ctyp$=LEFT$(ctyp$, LEN(ctyp$)-1)
  REPEAT
  !' Push the new content inside the control
  IF key$="content" & ctyp$="table" THEN %' TABLE
    LIST.GET 5, VAL(MID$(ctl$, 6)), n_cols
    HTML.LOAD.URL "javascript:populate("+DQ$+ctl$+DQ$+","+DQ$+WEB$(GW_NEW_TBL$(n_cols,t$[]))+DQ$+")"
  ELSEIF key$="content" & ctyp$="selectbox" THEN %' SELECTBOX
    HTML.LOAD.URL "javascript:populate("+DQ$+ctl$+DQ$+","+DQ$+GW_NEW_OPT$(t$[])+DQ$+")"
  ELSEIF key$="list" & ctyp$="inputlist" THEN %' INPUTLIST
    HTML.LOAD.URL "javascript:populate("+DQ$+ctl$+DQ$+","+DQ$+GW_NEW_LI$(t$[])+DQ$+")"
  ELSEIF key$="buttons" & ctyp$="dlgmsg" THEN %' DIALOG_MESSAGE
    HTML.LOAD.URL "javascript:populate('"+ctl$+"-buttons',"+DQ$+GW_NEW_BUTTONS$(t$[])+DQ$+")"
  ELSEIF key$="content" & ctyp$="listview" THEN %' LISTVIEW
    IF IS_IN("#", t$[1])=1 THEN %' ordered list
      HTML.LOAD.URL "javascript:replace('"+ctl$+"','ol')"
    ELSE %' unordered list
      HTML.LOAD.URL "javascript:replace('"+ctl$+"','ul')"
    END IF
    PAUSE 100
    HTML.LOAD.URL "javascript:populate("+DQ$+ctl$+DQ$+","+DQ$+GW_NEW_LV$(t$[])+DQ$+")"
    HTML.LOAD.URL "javascript:$('#"+ctl$+"').listview()" %' necessary to keep jQM listview layout
    HTML.LOAD.URL "javascript:$('#"+ctl$+"').listview('refresh')" %' necessary to keep jQM listview layout
  ELSE %' Throw an error
    (incorrect_key)
  END IF
FN.END
FN.DEF GwAModify(ctl_id, key$, t$[]) %' alias
  FN.RTN GW_AMODIFY(ctl_id, key$, t$[])
FN.END
FN.DEF gwam(ctl_id, key$, t$[]) %' shortcut
  FN.RTN GW_AMODIFY(ctl_id, key$, t$[])
FN.END

!'---------------------------------------------------------------------------------------------
!' OTHER FUNCTIONS: DEBUG, CODE-HIGHLIGHT, SUB-FUNCTIONS NEEDED BY ABOVE ONES, ETC.
!'---------------------------------------------------------------------------------------------
FN.DEF GW_PAGE$(idx) %' (internal)
  !' Get Unique IDentifier of the page
  LIST.SIZE 1, ls
  IF idx <= ls THEN LIST.GET 1, idx, e$
  FN.RTN e$
FN.END

FN.DEF GW_LAST_ID()
  !' RETURN Unique IDentifier of last added control
  LIST.SIZE 2, ls
  FN.RTN ls
FN.END
FN.DEF GwLastId() %' alias + shortcut
  FN.RTN GW_LAST_ID()
FN.END

FN.DEF GW_ID(ctl$)
  !' Get Unique IDentifier of the control
  LIST.SEARCH 2, ctl$, ctl_id
  FN.RTN ctl_id
FN.END
FN.DEF GwId(ctl$) %' alias + shortcut
  FN.RTN GW_ID(ctl$)
FN.END

FN.DEF GW_ID$(ctl_id)
  !' Get Unique IDentifier of the control
  LIST.SIZE 2, ls
  IF ctl_id <= ls THEN LIST.GET 2, ctl_id, ctl$
  FN.RTN ctl$
FN.END
FN.DEF GwId$(ctl_id) %' alias + shortcut
  FN.RTN GW_ID$(ctl_id)
FN.END

FN.DEF GW_THEME$(idx) %' (internal)
  !' Get Unique IDentifier of the control
  LIST.SIZE 3, ls
  IF idx <= ls THEN LIST.GET 3, idx, theme$
  FN.RTN theme$
FN.END

FN.DEF GW_DUMP(idx)
  PRINT GW_PAGE$(idx)
FN.END
FN.DEF GwDump(idx) %' alias
  FN.RTN GW_DUMP(idx)
FN.END
FN.DEF gwd(idx) %' shortcut
  FN.RTN GW_DUMP(idx)
FN.END

FN.DEF GW_DUMP_TO_FILE(idx, fname$)
  e$ = GW_PAGE$(idx)
  f$=fname$
  IF !IS_IN(LOWER$(f$), ".htm") THEN f$+=".html"
  BYTE.OPEN w, fid, f$
  BYTE.WRITE.BUFFER fid, e$
  BYTE.CLOSE fid
FN.END
FN.DEF GwDumpToFile(idx, fname$) %' alias
  FN.RTN GW_DUMP_TO_FILE(idx, fname$)
FN.END
FN.DEF gwdf(idx, fname$) %' shortcut
  FN.RTN GW_DUMP_TO_FILE(idx, fname$)
FN.END
FN.DEF gwdtf(idx, fname$) %' alternate shortcut
  FN.RTN GW_DUMP_TO_FILE(idx, fname$)
FN.END

FN.DEF GW_INJECT_HTML(idx, html$)
  e$ = GW_PAGE$(idx)
  e$+=html$
  LIST.REPLACE 1, idx, e$
FN.END
FN.DEF GwInjectHtml(idx, html$) %' alias
  FN.RTN GW_INJECT_HTML(idx, html$)
FN.END
FN.DEF gwih(idx, html$) %' shortcut
  FN.RTN GW_INJECT_HTML(idx, html$)
FN.END

FN.DEF GW_ADD_LISTENER$(ctl_id, event$, action$)
  !' Get Unique IDentifier of the control
  ctl$ = GW_ID$(ctl_id)
  !' Create the listener
  e$="<script>"
  IF event$="clear" THEN
    e$+="$(document.body).on('click','.ui-input-clear',function(){"
    e$+="if(this.parentNode.firstChild.id=='"+ctl$+"')"
  ELSE
!'    e$+="$('#"+ctl$+"')."
!'    e$+="bind('"+event$+"', function(){"
    e$+="$(document.body).on('"+event$+"', "
    e$+="'#"+ctl$+"', function(){"
  END IF
  e$+="doDataLink('"+action$+"');"
  e$+="})</script>"
  FN.RTN e$
FN.END
FN.DEF GwAddListener$(ctl_id, event$, action$) %' alias
  FN.RTN GW_ADD_LISTENER$(ctl_id, event$, action$)
FN.END
FN.DEF gwali$(ctl_id, event$, action$) %' shortcut
  FN.RTN GW_ADD_LISTENER$(ctl_id, event$, action$)
FN.END

FN.DEF GW_ADD_LISTENER(idx, ctl_id, event$, action$)
  !' Add the listener to the page
  LIST.REPLACE 1, idx, GW_PAGE$(idx) + GW_ADD_LISTENER$(ctl_id, event$, action$)
FN.END
FN.DEF GwAddListener(idx, ctl_id, event$, action$) %' alias
  FN.RTN GW_ADD_LISTENER(idx, ctl_id, event$, action$)
FN.END
FN.DEF gwali(idx, ctl_id, event$, action$) %' shortcut
  FN.RTN GW_ADD_LISTENER(idx, ctl_id, event$, action$)
FN.END

FN.DEF GW_ENABLE_LISTENER(e$)
  IF LEFT$(e$, 8)<>"<script>" THEN FN.RTN 0
  e$=MID$(e$, 9)
  IF RIGHT$(e$, 9)<>"</script>" THEN FN.RTN 0
  e$=LEFT$(e$, LEN(e$)-9)
  HTML.LOAD.URL "javascript:"+e$
FN.END
FN.DEF GwEnableListener(e$) %' alias
  FN.RTN GW_ENABLE_LISTENER(e$)
FN.END
FN.DEF gwel(e$) %' shortcut
  FN.RTN GW_ENABLE_LISTENER(e$)
FN.END

FN.DEF GW_LINK$(e$) %' (internal)
  IF RIGHT$(e$, 1)=">" THEN
    r$="<a target='_blank' href='"
    lnk$=LEFT$(e$, LEN(e$)-1)
  ELSE
    r$="<a href='"
    lnk$=e$
  END IF
  r$+=lnk$+"'>"+lnk$+"</a>"
  FN.RTN r$
FN.END

FN.DEF GW_CODE_HIGHLIGHT$(raw$, black$[], blue$[], red$[])
  r$=REPLACE$(raw$, "\n", "<br>")
  gwcod$="font-family: \"Lucida Console\", Monaco, monospace; font-size: 14px;"
  gwstr$="color:#007f0e; font-style:italic; font-weight: bold;"
  gwbla$="font-weight: bold;"
  gwblu$="color:blue; font-weight: bold;"
  gwred$="color:red; font-weight: bold;"
  !' Highlight content of strings (between double quotes)
  span$="<span style='"+gwstr$+"'>"
  i=IS_IN(CHR$(34), r$)
  WHILE i
    r$=LEFT$(r$, i)+span$+MID$(r$, i+1) %' Opening double quote
    i=IS_IN(CHR$(34), r$, i+1)
    r$=LEFT$(r$, i-1)+"</span>"+MID$(r$, i) %' Closing double quote
    i+=LEN("</span>")
    i=IS_IN(CHR$(34), r$, i+1)
  REPEAT
  !' Highlight inline comments
  i=IS_IN("%'", r$)
  WHILE i
    j=IS_IN("<", r$, i)
    IF !j THEN j=LEN(r$)+1
    r$=LEFT$(r$, i)+span$ +MID$(r$, i+1, j-i-1)+"</span>"+ MID$(r$, j)
    i=IS_IN("%'", r$, j)
  REPEAT
  !' Highlight GW keywords in blue
  span$="<span style='"+gwblu$+"'>"
  ARRAY.LENGTH al, blue$[]
  FOR i=1 TO al
    r$=REPLACE$(r$, blue$[i], span$+blue$[i]+"</span>")
  NEXT
  !' Highlight BASIC! keywords in black
  span$="<span style='"+gwbla$+"'>"
  ARRAY.LENGTH al, black$[]
  FOR i=1 TO al
    r$=REPLACE$(r$, black$[i], span$+black$[i]+"</span>")
  NEXT
  !' Highlight operators in red
  span$="<span style='"+gwred$+"'>"
  ARRAY.LENGTH al, red$[]
  FOR i=1 TO al
    r$=REPLACE$(r$, red$[i], span$+red$[i]+"</span>")
  NEXT
  %' Create bullets
  r$=REPLACE$(r$, ">*", ">&rarr;")
  IF IS_IN("*", r$) = 1 THEN r$ = "&rarr;" + MID$(r$, 2)
  FN.RTN "<p style='"+gwcod$+"'>"+r$+"</p>"
FN.END
FN.DEF GwCodeHighlight$(raw$, black$[], blue$[], red$[]) %' alias
  FN.RTN GW_CODE_HIGHLIGHT$(raw$, black$[], blue$[], red$[])
FN.END
FN.DEF gwch$(raw$, black$[], blue$[], red$[]) %' shortcut
  FN.RTN GW_CODE_HIGHLIGHT$(raw$, black$[], blue$[], red$[])
FN.END

FN.DEF GW_NEWID$(ctl$) %' (internal) Return a Unique IDentifier string for a control family
  BUNDLE.CONTAIN 1, ctl$, bc
  IF !bc THEN BUNDLE.PUT 1, ctl$, 0
  BUNDLE.GET 1, ctl$, n
  BUNDLE.PUT 1, ctl$, n+1
  FN.RTN ctl$+INT$(n+1)
FN.END

FN.DEF ENT$(i) %' (internal)
  e$=STR$(i)
  IF RIGHT$(e$, 2)=".0" THEN FN.RTN INT$(i) ELSE FN.RTN e$
FN.END

FN.DEF WEB$(e$) %' (internal) Return an HTML-safe version of the string
  r$=REPLACE$(e$, "°", "&deg;")
  r$=REPLACE$(r$, "\t", "&nbsp;&nbsp;&nbsp;")
  r$=REPLACE$(r$, "\n", "<br>")
  r$=REPLACE$(r$, CHR$(34), "&quot;")
  FN.RTN r$
FN.END

FN.DEF URL_ENCODE$(e$) %' (internal) URL-encode the string
  IF e$="" THEN FN.RTN ""
  c=1
  DO
    a=ASCII(MID$(e$, c, 1))
    IF (a>=48 & a<=57) | (a>=65 & a<=90) | (a>=97 & a<=122) THEN
        r$+=CHR$(a)
    ELSEIF a=32 THEN
      r$+="+" % r$+="%"+HEX$(32)
     ELSE
      r$+="%"+FORMAT$("00", HEX$(a))
    END IF
    c++
  UNTIL c=LEN(e$)+1
  FN.RTN r$
FN.END

FN.DEF URL_DECODE$(e$) %' (internal) URL-decode the string
  IF e$="" THEN FN.RTN ""
  c = 1
  DO
    a$=MID$(e$, c, 1)
    IF a$="+" THEN
      r$+=" "
    ELSEIF a$="%" THEN
      r$+=CHR$(HEX(MID$(e$, c+1, 2)))
      c+=2
    ELSE
      r$+=a$
    END IF
    c++
  UNTIL c=LEN(e$)+1
  FN.RTN r$
FN.END

FN.DEF GW_KEYWORD_NB()
  DIM kw$[299]
  FILE.SIZE fs, "../source/GW.bas"
  BYTE.OPEN r, fid, "../source/GW.bas"
  BYTE.READ.BUFFER fid, fs, e$
  BYTE.CLOSE fid
  i=IS_IN("!' Complete list of APIs:", e$)+LEN("!' Complete list of APIs:")
  j1=IS_IN("TODO TODO", e$, i)
  j2=IS_IN("!' Changelog:", e$, i)
  IF j1 THEN j=j1 ELSE j=j2
  e$=MID$(e$, i, j-i)
  i=0
  DO
    i=IS_IN("GW_", e$, i+1)
    IF i THEN
      nb++
      j=IS_IN("(", e$, i)
      IF MID$(e$, j-1, 1)=" " THEN j--
      k$=MID$(e$, i, j-i)
      ARRAY.SEARCH kw$[], k$, as
      IF as THEN nb=nb-1 ELSE kw$[nb]=k$
    END IF
  UNTIL !i
  ARRAY.DELETE kw$[]
  FN.RTN nb
FN.END
FN.DEF GwKeywordNb() %' alias
  FN.RTN GW_KEYWORD_NB()
FN.END
FN.DEF gwkn() %' shortcut
  FN.RTN GW_KEYWORD_NB()
FN.END


FN.DEF GW_POPULATE_KEYWORD_ARRAY(kw$[])
  ARRAY.LENGTH al, kw$[]
  FILE.SIZE fs, "../source/GW.bas"
  BYTE.OPEN r, fid, "../source/GW.bas"
  BYTE.READ.BUFFER fid, fs, e$
  BYTE.CLOSE fid
  i=IS_IN("!' Complete list of APIs:", e$)+LEN("!' Complete list of APIs:")
  j1=IS_IN("TODO TODO", e$, i)
  j2=IS_IN("!' Changelog:", e$, i)
  IF j1 THEN j=j1 ELSE j=j2
  e$=MID$(e$, i, j-i)
  i=0
  DO
    i=IS_IN("GW_", e$, i+1)
    IF i THEN
      nb++
      IF nb>al THEN FN.RTN 0
      j=IS_IN("(", e$, i)
      IF MID$(e$, j-1, 1)=" " THEN j--
      k$=MID$(e$, i, j-i)
      ARRAY.SEARCH kw$[], k$, as
      IF as THEN nb=nb-1 ELSE kw$[nb]=k$
    END IF
  UNTIL !i
FN.END
FN.DEF GwPopulateKeywordArray(kw$[]) %' alias
  FN.RTN GW_POPULATE_KEYWORD_ARRAY(kw$[])
FN.END
FN.DEF gwpka(kw$[]) %' shortcut
  FN.RTN GW_POPULATE_KEYWORD_ARRAY(kw$[])
FN.END

!'---------------------------------------------------------------------------------------------
!' GW SPLASH SCREEN - IT IS SAFE TO REMOVE FOLLOWING CODE IF YOU DON'T WANT IT
!'---------------------------------------------------------------------------------------------
FILE.EXISTS fe, "../source/mougino.free.fr.bas"
IF !fe
  splash = GW_NEW_PAGE()
  GW_CENTER_PAGE_VER(splash)
  GW_START_CENTER(splash)
  GW_ADD_GW_LOGO(splash)
  GW_ADD_TEXT(splash, "")
  GW_INJECT_HTML(splash, "<h3>")
  GW_ADD_TEXT(splash, "This app was created with\nthe GW lib for RFO-BASIC!")
  GW_INJECT_HTML(splash, "</h3>")
  GW_INJECT_HTML(splash, "<h3>")
  GW_ADD_LINK(splash, "www.rfo-basic.com", "RFO")
  GW_INJECT_HTML(splash, "</h3>")
  GW_STOP_CENTER(splash)
  GW_RENDER(splash)
  splash_ms = CLOCK()
  DO
    HTML.GET.DATALINK data$
    PAUSE 1
  UNTIL data$<>"" | CLOCK()-splash_ms>2500
  IF data$="DAT:RFO" THEN BROWSE "http://www.rfo-basic.com"
END IF



demover$ = "v1.9"

GOSUB DemoInit

!'==========================================================================================================
MainPage:
IF !main THEN
  code$ = SelfExtract$ ("MainPage:")
  main = GW_NEW_PAGE()
  GW_SET_TRANSITION (main, "slide")
  cartman = GW_ADD_ICON (main, "cartman.png", 24, 24) %' 24 x 24 pixels
  GW_ADD_TITLEBAR (main, GW_ADD_BAR_LBUTTON$ (GW_ICON$(cartman)) + GW_ADD_BAR_TITLE$ ("GW demo " + demover$))
  maincode = GW_ADD_PANEL (main, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_TEXT (main, "Choose one of the following demos:")
  GW_ADD_BUTTON (main, "Listview", "LISTVIEW")
  GW_ADD_BUTTON (main, "Button", "BUTTON")
  GW_ADD_BUTTON (main, "Slider", "SLIDER")
  GW_ADD_BUTTON (main, "Input controls", "INPUT")
  GW_ADD_BUTTON (main, "Flip switch", "FLIP")
  GW_ADD_BUTTON (main, "Checkbox / Radio", "CHECK")
  GW_ADD_BUTTON (main, "Dialog Message", "DLGMSG")
  GW_ADD_BUTTON (main, "Video", "VIDEO")
  GW_ADD_BUTTON (main, "Table / Image", "TABLE")
  GW_ADD_BUTTON (main, "Theme", "THEME")
  GW_ADD_TEXT (main, "")
  GW_ADD_LINK (main, "See the code of this page", GW_SHOW_PANEL$ (maincode))
  GW_ADD_TEXT (main, "(c) Nicolas MOUGIN, 2014-2015")
  GW_ADD_BUTTON (main, "Exit demo", "BYE")
  GW_PREVENT_LANDSCAPE (main, "This page only works in portrait.\nPlease turn your screen")
END IF
GW_RENDER (main)
r$ = GW_WAIT_ACTION$()
IF r$ = "BUTTON" THEN GOTO BtnPage
IF r$ = "SLIDER" THEN GOTO SliderPage
IF r$ = "INPUT" THEN GOTO InputPage
IF r$ = "FLIP" THEN GOTO FlipPage
IF r$ = "CHECK" THEN GOTO CheckPage
IF r$ = "THEME" THEN GOTO ThemePage
IF r$ = "DLGMSG" THEN GOTO DlgMsgPage
IF r$ = "VIDEO" THEN GOTO VideoPage
IF r$ = "TABLE" THEN GOTO TablePage
IF r$ = "LISTVIEW" THEN GOTO LvPage
IF r$ = "BYE" | r$ = "BACK" THEN
  POPUP "Bye!"
  EXIT
END IF

!'==========================================================================================================
BtnPage:
IF !btn THEN
  code$ = SelfExtract$ ("BtnPage:")
  btn = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (btn, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Button demo"))
  btncode = GW_ADD_PANEL (btn, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_TEXT (btn, "Click this button to change its label:")
  btnBtn = GW_ADD_BUTTON (btn, "I count to " + INT$(i), "COUNT")
  GW_ADD_TEXT (btn, "And click this other button to fill or clear the 'title' control next to it:")
  GW_ADD_BUTTON (btn, "Click me!", "TITLE")
  btnTitle = GW_ADD_TITLE (btn, "")
  GW_ADD_TEXT (btn, "")
  GW_ADD_LINK (btn, "See the code of this page", GW_SHOW_PANEL$ (btncode))
  GW_ADD_BUTTON (btn, "Back", "BACK")
END IF
GW_RENDER (btn)
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "COUNT" THEN
    i++
    GW_MODIFY (btnBtn, "text", "I count to " + INT$(i))
  ELSEIF r$ = "TITLE" THEN
    t=1-t
    IF t THEN
      GW_MODIFY (btnTitle, "text", "I'm alive!")
    ELSE
      GW_MODIFY (btnTitle, "text", "")
    END IF
  END IF
UNTIL r$ = "BACK"
i=0
t=0
GOTO MainPage

!'==========================================================================================================
SliderPage:
IF !sli THEN
  code$ = SelfExtract$ ("SliderPage:")
  sli = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (sli, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Slider demo"))
  slicode = GW_ADD_PANEL (sli, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_TEXT (sli, "Sliders are used to enter numeric values along a numeric continuum by dragging a handle or entering in a value.")
  ctl_slider1 = GW_ADD_SLIDER (sli, "Simple integer slider:", 0, 100, 1, 50)
  ctl_slider2 = GW_ADD_SLIDER (sli, "Integer slider with a step of 20:", 0, 100, 20, 40)
  ctl_slider3 = GW_ADD_SLIDER (sli, "Decimal slider:", 0.2, 0.5, 0.01, 0.2)
  GW_ADD_TEXT (sli, "Sliders are user input controls, as such they need a 'submit' control to pass their values to BASIC!\nSubmit controls physically look like a button:")
  GW_ADD_SUBMIT (sli, "Copy values below:")
  sliTxt = GW_ADD_TEXTBOX (sli, "")
  GW_ADD_TEXT (sli, "")
  GW_ADD_LINK (sli, "See the code of this page", GW_SHOW_PANEL$ (slicode))
  GW_ADD_BUTTON (sli, "Back", "BACK")
END IF
GW_RENDER (sli)
DO
  r$ = GW_WAIT_ACTION$()
  IF IS_IN ("SUBMIT", r$)=1 THEN
    e$ = "First slider value is " + GW_GET_VALUE$ (ctl_slider1) + "\n"
    e$ += "Second slider value is " + GW_GET_VALUE$ (ctl_slider2) + "\n"
    e$ += "Third slider value is " + GW_GET_VALUE$ (ctl_slider3)
    GW_MODIFY (sliTxt, "text", e$)
  END IF
UNTIL r$ = "BACK"
GOTO MainPage

!'==========================================================================================================
InputPage:
IF !inp THEN
  code$ = SelfExtract$ ("InputPage:")
  inp = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (inp, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Input controls demo"))
  inpcode = GW_ADD_PANEL (inp, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_TEXT (inp, "Text input lines and boxes are two of the most common user input controls.")
  inpl = GW_ADD_INPUTLINE (inp, "This is an input line:", "Change me!")
  GW_ADD_LISTENER (inp, inpl, "keydown", "INPUTLINE_CHANGED")
  GW_ADD_LISTENER (inp, inpl, "clear", "INPUTLINE_CHANGED")
  inpt = GW_ADD_TEXT (inp, "")
  inpaxn1 = GW_ADD_SUBMIT (inp, "Make a BASIC! popup from input line")
  GW_ADD_TEXT (inp, "")
  e$ = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec pretium, purus vitae fermentum "
  e$ += "pharetra, nulla nisi pretium nisi, vitae laoreet arcu nisi elementum turpis. Fusce ac facilisis "
  e$ += "est. Praesent sodales sagittis odio, et maximus tortor elementum at. Duis ullamcorper est justo, "
  e$ += "et viverra justo dictum id. Morbi aliquam turpis vel lorem sollicitudin, nec porta lacus aliquam. "
  e$ += "Nunc quis vehicula odio. Praesent a vehicula magna, non rhoncus risus. Fusce at eros id quam "
  e$ += "rhoncus sagittis et vel tortor. In et nulla congue ligula auctor posuere non sit amet ante. "
  e$ += "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae."
  inpb = GW_ADD_INPUTBOX (inp, "And this is an input box:", e$)
  inpaxn2 = GW_ADD_SUBMIT (inp, "Shuffle the text in the box")
  GW_ADD_TEXT (inp, "Here is an input list = an autocomplete input line with pre-defined values and actions:")
  ARRAY.LOAD tna$[], "Android>ANDRO", "iOS>IOS", "Linux>LINUX", "Mac OS>MAC", "Windows>WIN"
  oses = GW_ADD_INPUTLIST (inp, "Type an OS name...", tna$[])
  GW_ADD_LISTENER (inp, oses, "clear", "INPUTLIST_RESET")
  ARRAY.DELETE tna$[]
  GW_ADD_TEXT (inp, "And here is a select box to pick a value from a list:")
  ARRAY.LOAD fruit$[], "Apple", "Banana", "Cherry", "Cranberry", ">Grape", "Orange"
  fruitbox = GW_ADD_SELECTBOX (inp, "Pick a fruit:", fruit$[])
  GW_ADD_LISTENER (inp, fruitbox, "change", "SELECTBOX_CHANGED")
  inpaxn3 = GW_ADD_SUBMIT (inp, "What fruit did you pick?")
  GW_ADD_TEXT (inp, "And finally here are miscellaneous input controls:")
  GW_ADD_INPUTDATE (inp, "Input Date", "")
  GW_ADD_INPUTTIME (inp, "Input Time", "")
  GW_ADD_INPUTMONTH (inp, "Input Month", "")
  GW_ADD_INPUTWEEK (inp, "Input Week", "")
  GW_ADD_INPUTURL (inp, "Input URL", "")
  GW_ADD_INPUTEMAIL (inp, "Input eMail", "")
  GW_ADD_INPUTCOLOR (inp, "Input Color", "")
  GW_ADD_INPUTNUMBER (inp, "Input Number", "")
  GW_ADD_INPUTTEL (inp, "Input Tel", "")
  GW_ADD_INPUTPASSWORD (inp, "Input Password", "")
  GW_ADD_INPUTFILE (inp, "Input File", "")
  GW_ADD_SUBMIT (inp, "Submit")
  GW_ADD_TEXT (inp, "")
  GW_ADD_LINK (inp, "See the code of this page", GW_SHOW_PANEL$ (inpcode))
  GW_ADD_BUTTON (inp, "Back", "BACK")
END IF
GW_RENDER (inp)
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "ANDRO" THEN POPUP "You chose Android", 0,0,0
  IF r$ = "IOS" THEN POPUP "You chose iOS", 0,0,0
  IF r$ = "LINUX" THEN POPUP "You chose Linux", 0,0,0
  IF r$ = "MAC" THEN POPUP "You chose Mac OS", 0,0,0
  IF r$ = "WIN" THEN POPUP "You chose Windows", 0,0,0
  IF r$ = "INPUTLINE_CHANGED" THEN
    e$=GW_GET_VALUE$ (inpl)
    e$ = "User typed ''" + e$ + "'' (" + INT$(LEN (e$)) + " characters)"
    GW_MODIFY (inpt, "text", e$)
  END IF
  IF r$ = "INPUTLIST_RESET" THEN POPUP "Listener triggered:" + CHR$(10) + "input list was reset", 0,0,0
  IF r$ = "SELECTBOX_CHANGED" THEN POPUP "Listener triggered:" + CHR$(10) + "select box was changed", 0,0,0
  IF IS_IN ("SUBMIT", r$)=1 THEN
    IF IS_IN (GW_ID$(inpaxn1), r$) THEN % 'submit' after input line
      POPUP GW_GET_VALUE$ (inpl),0,0,0
    ELSEIF IS_IN (GW_ID$(inpaxn2), r$) THEN % 'submit' after box
      e$ = GW_GET_VALUE$ (inpb)
      SPLIT r$[], e$, " "
      ARRAY.SHUFFLE r$[]
      ARRAY.LENGTH al, r$[]
      e$ = ""
      FOR i=1 TO al
        e$ += r$[i] + " "
      NEXT
      ARRAY.DELETE r$[]
      GW_MODIFY (inpb, "text", e$)
    ELSEIF IS_IN (GW_ID$(inpaxn3), r$) THEN % 'submit' after fruit select box
      f = GW_GET_VALUE (fruitbox)
      e$ = "You picked a"
      r$ = LEFT$ (fruit$[f], 1)
      IF r$ = "A" | r$ = "O" THEN e$ += "n"
      e$ += " " + LOWER$(fruit$[f])
      POPUP e$,0,0,0
    END IF
  END IF
UNTIL r$ = "BACK"
GOTO MainPage

!'==========================================================================================================
FlipPage:
IF !flip THEN
  code$ = SelfExtract$ ("FlipPage:")
  flip = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (flip, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Flip switch demo"))
  flipcode = GW_ADD_PANEL (flip, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_TEXT (flip, "Flip switches are used for boolean style inputs like true/false or on/off in a compact UI element.")
  ctl_flip1 = GW_ADD_FLIPSWITCH (flip, "BASIC! vibrate", "off", "on")
  ctl_flip2 = GW_ADD_FLIPSWITCH (flip, "BASIC! beep", "0", "1")
  GW_ADD_BUTTON (flip, "Change 1st flip switch", "CHFLIP")
  GW_ADD_TEXT (flip, "")
  GW_ADD_LINK (flip, "See the code of this page", GW_SHOW_PANEL$ (flipcode))
  GW_ADD_BUTTON (flip, "Back", "BACK")
END IF
GW_RENDER (flip)
TIMER.SET 1000
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "CHFLIP" THEN
    vibr=1-vibr
    IF vibr THEN GW_MODIFY (ctl_flip1, "selected", "on")
    IF !vibr THEN GW_MODIFY (ctl_flip1, "selected", "off")
  END IF
  IF GW_FLIPSWITCH_CHANGED (ctl_flip1, "on") THEN vibr=1
  IF GW_FLIPSWITCH_CHANGED (ctl_flip1, "off") THEN vibr=0
  IF GW_FLIPSWITCH_CHANGED (ctl_flip2, "1") THEN beep=1
  IF GW_FLIPSWITCH_CHANGED (ctl_flip2, "0") THEN beep=0
UNTIL r$ = "BACK"
TIMER.CLEAR
vibr=0
beep=0
GOTO MainPage

ONTIMER:
IF vibr THEN VIBRATE buzz[], -1
IF beep THEN TONE 300, 300
TIMER.RESUME

!'==========================================================================================================
CheckPage:
IF !check THEN
  code$ = SelfExtract$ ("CheckPage:")
  check = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (check, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Checkbox + Radio demo"))
  checkcode = GW_ADD_PANEL (check, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))

  GW_ADD_TEXT (check, "Checkboxes are used to provide a list of options where more than one can be selected.")
  GW_OPEN_GROUP (check)
  ctl_check1 = GW_ADD_CHECKBOX (check, "I like red")
  ctl_check2 = GW_ADD_CHECKBOX (check, ">I like green")
  ctl_check3 = GW_ADD_CHECKBOX (check, "I like black")
  ctl_check4 = GW_ADD_CHECKBOX (check, ">I like blue")
  ctl_check5 = GW_ADD_CHECKBOX (check, "I like yellow")
  GW_CLOSE_GROUP (check)
  GW_ADD_TEXT (check, "You can retrieve checkbox values with a 'submit' control:")
  checkaxn1 = GW_ADD_SUBMIT (check, "Show the world what you like")
  GW_ADD_TEXT (check, "Or reset checkboxes with gw_modify:")
  GW_ADD_BUTTON (check, "Reset all checkboxes", "RAZCB")
  GW_ADD_TEXT (check, "")

  GW_ADD_TEXT (check, "Radio buttons are used to provide a list of options where only a single option can be selected.")
  GW_OPEN_GROUP (check)
  ctl_parent = GW_ADD_RADIO (check, 0, "I am a toddler")
  ctl_child1 = GW_ADD_RADIO (check, ctl_parent, "I am a boy")
  ctl_child2 = GW_ADD_RADIO (check, ctl_parent, ">I am a man")
  ctl_child3 = GW_ADD_RADIO (check, ctl_parent, "I am your father")
  GW_CLOSE_GROUP (check)
  GW_ADD_TEXT (check, "You can retrieve radio values with a 'submit' control:")
  checkaxn2 = GW_ADD_SUBMIT (check, "What are you?")
  GW_ADD_TEXT (check, "Or unselect a group of radio buttons with gw_modify:")
  GW_ADD_BUTTON (check, "Reset radio group", "RAZRB")
  GW_ADD_TEXT (check, "")
  GW_ADD_LINK (check, "See the code of this page", GW_SHOW_PANEL$ (checkcode))
  GW_ADD_BUTTON (check, "Back", "BACK")
END IF
GW_RENDER (check)
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "RAZRB" THEN GW_MODIFY (ctl_parent, "selected", "0")
  IF r$ = "RAZCB" THEN
    GW_MODIFY (ctl_check1, "checked", "0")
    GW_MODIFY (ctl_check2, "checked", "0")
    GW_MODIFY (ctl_check3, "checked", "0")
    GW_MODIFY (ctl_check4, "checked", "0")
    GW_MODIFY (ctl_check5, "checked", "0")
  END IF
  IF IS_IN ("SUBMIT", r$) = 1 THEN
    IF IS_IN (GW_ID$(checkaxn1), r$) THEN
      e$ = ""
      IF GW_CHECKBOX_CHECKED (ctl_check1) THEN e$ += "You like red like strawberries\n"
      IF GW_CHECKBOX_CHECKED (ctl_check2) THEN e$ += "You like green like the grass\n"
      IF GW_CHECKBOX_CHECKED (ctl_check3) THEN e$ += "You like black like the sky at night\n"
      IF GW_CHECKBOX_CHECKED (ctl_check4) THEN e$ += "You like blue like a calm sea\n"
      IF GW_CHECKBOX_CHECKED (ctl_check5) THEN e$ += "You like yellow like the sun\n"
      IF LEN (e$) THEN e$ = LEFT$ (e$, LEN (e$)-1) ELSE e$ = "You like nothing!"
      POPUP e$,0,0,0
    ELSEIF IS_IN (GW_ID$(checkaxn2), r$) THEN
      IF GW_RADIO_SELECTED (ctl_parent) THEN POPUP "A baby", 0,0,0
      IF GW_RADIO_SELECTED (ctl_child1) THEN POPUP "A preteen", 0,0,0
      IF GW_RADIO_SELECTED (ctl_child2) THEN POPUP "A grown up", 0,0,0
      IF GW_RADIO_SELECTED (ctl_child3) THEN POPUP "Darth Vader", 0,0,0
    END IF
  END IF
UNTIL r$ = "BACK"
GOTO MainPage

!'==========================================================================================================
ThemePage:
IF !thm THEN
  code$ = SelfExtract$ ("ThemePage:")
  thm = GW_NEW_PAGE()
  ARRAY.LOAD thmbna$[], "Yes>DLT", "Cancel>NO"
  thmdm = GW_ADD_DIALOG_MESSAGE (thm, "Download theme", "This theme is not on your device. Do you want to download it now?", thmbna$[])
  ARRAY.DELETE thmbna$[]
  ARRAY.LOAD thmbna$[], "OK"
  thmpb = GW_ADD_DIALOG_MESSAGE (thm, "Error", "There was a problem during download!\nTry again later.", thmbna$[])
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (thm, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Theme demo"))
  thmcode = GW_ADD_PANEL (thm, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_TEXT (thm, "You can customize controls or elements of the page (title bar, panel) thanks to themes.\nChoose a theme below (*ls means limited support):")
  GW_ADD_BUTTON (thm, "native-droid-*", "8")
  GW_ADD_BUTTON (thm, "flat-ui", "1")
  GW_ADD_BUTTON (thm, "bootstrap", "4")
  GW_ADD_BUTTON (thm, "square-ui", "6")
  GW_ADD_BUTTON (thm, "android-holo\t<small>(ls*)</small>", "5")
  GW_ADD_BUTTON (thm, "iOS\t<small>(ls*)</small>", "3")
  GW_ADD_BUTTON (thm, "classic\t<small>(ls*)</small>", "2")
  GW_ADD_BUTTON (thm, "metro\t<small>(ls*)</small>", "7")
  GW_ADD_TEXT (thm, "")
  GW_ADD_LINK (thm, "See the code of this page", GW_SHOW_PANEL$ (thmcode))
  GW_ADD_BUTTON (thm, "Back", "BACK")
END IF
GW_RENDER (thm)
IF !once THEN
  once = 1
  PAUSE 1000
  GW_SHOW_PANEL (thmcode)
END IF
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "BACK" THEN
    GOTO MainPage
  ELSEIF r$ = "DLT" THEN %' "DownLoad Theme" tapped in Dialog Message
    POPUP "Starting download..."
    GW_DOWNLOAD_THEME (GW_THEME$[n+1])
    IF GW_THEME_EXISTS (GW_THEME$[n+1]) THEN %' Theme downloaded successfully
      POPUP "Download complete!"
      GOTO n, ThemePage1, ThemePage2, ThemePage3, ThemePage4, ThemePage5, ThemePage6, ThemePage7, ThemePage8
    ELSE
      GW_SHOW_DIALOG_MESSAGE (thmpb) %' Theme download problem
    END IF
  ELSE
    n = ASCII(r$) - ASCII("1") + 1
    IF n >= 1 & n <= 8 THEN
      IF GW_THEME_EXISTS (GW_THEME$[n+1]) THEN
        GOTO n, ThemePage1, ThemePage2, ThemePage3, ThemePage4, ThemePage5, ThemePage6, ThemePage7, ThemePage8
      ELSE
        GW_SHOW_DIALOG_MESSAGE (thmdm) %' DownLoad Theme ? Y/N
      END IF
    END IF
  END IF
UNTIL 0

!'==========================================================================================================
ThemePage1:
IF !thm1 THEN
  code$ = SelfExtract$ ("ThemePage1:")
  GW_LOAD_THEME ("flat-ui")
  thm1 = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (thm1, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Theme 'flat-ui'"))
  thm1code = GW_ADD_PANEL (thm1, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))

  GW_ADD_TEXT (thm1, "Some customized buttons:")
  GW_USE_THEME_CUSTO_ONCE ("color=a icon=flat-settings")
  GW_ADD_BUTTON (thm1, "color=a\t icon=flat-settings", "")
  GW_USE_THEME_CUSTO_ONCE ("color=b icon=flat-new")
  GW_ADD_BUTTON (thm1, "color=b\t icon=flat-new", "")
  GW_USE_THEME_CUSTO_ONCE ("color=c icon=flat-man")
  GW_ADD_BUTTON (thm1, "color=c\t icon=flat-man", "")
  GW_USE_THEME_CUSTO_ONCE ("color=d icon=flat-mail")
  GW_ADD_BUTTON (thm1, "color=d\t icon=flat-mail", "")
  GW_USE_THEME_CUSTO_ONCE ("color=e icon=flat-lock")
  GW_ADD_BUTTON (thm1, "color=e\t icon=flat-lock", "")
  GW_USE_THEME_CUSTO_ONCE ("color=f icon=flat-menu")
  GW_ADD_BUTTON (thm1, "color=f\t icon=flat-menu", "")
  GW_USE_THEME_CUSTO_ONCE ("color=g icon=flat-heart")
  GW_ADD_BUTTON (thm1, "color=g\t icon=flat-heart", "")

  GW_ADD_TEXT (thm1, "Buttons with 'inline notext' custo:")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=home")
  GW_ADD_BUTTON (thm1, "", "1")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-video")
  GW_ADD_BUTTON (thm1, "", "2")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-time")
  GW_ADD_BUTTON (thm1, "", "3")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-eye")
  GW_ADD_BUTTON (thm1, "", "4")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-plus")
  GW_ADD_BUTTON (thm1, "", "5")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-location")
  GW_ADD_BUTTON (thm1, "", "6")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-cmd")
  GW_ADD_BUTTON (thm1, "", "7")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-cross")
  GW_ADD_BUTTON (thm1, "", "8")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-checkround")
  GW_ADD_BUTTON (thm1, "", "9")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-calendar")
  GW_ADD_BUTTON (thm1, "", "10")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-bubble")
  GW_ADD_BUTTON (thm1, "", "11")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-volume")
  GW_ADD_BUTTON (thm1, "", "12")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=flat-camera")
  GW_ADD_BUTTON (thm1, "", "13")
  GW_USE_THEME_CUSTO_ONCE ("color=g")
  GW_ADD_CHECKBOX (thm1, ">Check box 1")
  GW_USE_THEME_CUSTO_ONCE ("color=g")
  GW_ADD_CHECKBOX (thm1, "Check box 2")
  GW_ADD_INPUTLINE (thm1, "", "Input Line")
  GW_USE_THEME_CUSTO_ONCE ("color=d")
  r = GW_ADD_RADIO (thm1, 0, ">Radio button 1")
  GW_USE_THEME_CUSTO_ONCE ("color=d")
  GW_ADD_RADIO (thm1, r, "Radio button 2")
  GW_USE_THEME_CUSTO_ONCE ("color=b")
  thm1flip1 = GW_ADD_FLIPSWITCH (thm1, "", "Off", ">On")
  thm1flip2 = GW_ADD_FLIPSWITCH (thm1, "", "Off", "On")
  GW_USE_THEME_CUSTO_ONCE ("color=e")
  GW_ADD_SLIDER (thm1, "", 0, 100, 1, 50)

  GW_ADD_TEXT (thm1, "")
  GW_ADD_LINK (thm1, "See the code of this page", GW_SHOW_PANEL$ (thm1code))
  GW_ADD_BUTTON (thm1, "Back", "BACK")
END IF
GW_RENDER (thm1)
GW_UNLOAD_THEME() %' to avoid future pages to inherit this theme
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "1" THEN POPUP "color=f inline iconpos=notext icon=home", 0,0,0
  IF r$ = "2" THEN POPUP "color=f inline iconpos=notext icon=flat-video", 0,0,0
  IF r$ = "3" THEN POPUP "color=f inline iconpos=notext icon=flat-time", 0,0,0
  IF r$ = "4" THEN POPUP "color=f inline iconpos=notext icon=flat-eye", 0,0,0
  IF r$ = "5" THEN POPUP "color=f inline iconpos=notext icon=flat-plus", 0,0,0
  IF r$ = "6" THEN POPUP "color=f inline iconpos=notext icon=flat-location", 0,0,0
  IF r$ = "7" THEN POPUP "color=f inline iconpos=notext icon=flat-cmd", 0,0,0
  IF r$ = "8" THEN POPUP "color=f inline iconpos=notext icon=flat-cross", 0,0,0
  IF r$ = "9" THEN POPUP "color=f inline iconpos=notext icon=flat-checkround", 0,0,0
  IF r$ = "10" THEN POPUP "color=f inline iconpos=notext icon=flat-calendar", 0,0,0
  IF r$ = "11" THEN POPUP "color=f inline iconpos=notext icon=flat-bubble", 0,0,0
  IF r$ = "12" THEN POPUP "color=f inline iconpos=notext icon=flat-volume", 0,0,0
  IF r$ = "13" THEN POPUP "color=f inline iconpos=notext icon=flat-camera", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm1flip1, "Off") THEN POPUP "Switched off", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm1flip2, "On") THEN POPUP "Switched on", 0,0,0
UNTIL r$ = "BACK"
GOTO ThemePage

!'==========================================================================================================
ThemePage2:
IF !thm2 THEN
  code$ = SelfExtract$ ("ThemePage2:")
  GW_LOAD_THEME ("classic")
  thm2 = GW_NEW_PAGE()
  thm2cust = GW_NEW_THEME_CUSTO ("color=b")
  GW_USE_THEME_CUSTO(thm2cust)
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (thm2, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Theme 'classic'"))
  GW_USE_THEME_CUSTO_ONCE ("color=d")
  GW_ADD_TEXT (thm2, "The jQM 'classic' is an old theme: panels are not supported...")
  GW_USE_THEME_CUSTO_ONCE ("color=a")
  GW_ADD_BUTTON (thm2, "I am a 'color=a' button", "")
  GW_USE_THEME_CUSTO_ONCE ("color=b")
  GW_ADD_BUTTON (thm2, "I am a 'color=b' button", "")
  GW_USE_THEME_CUSTO_ONCE ("color=c")
  GW_ADD_BUTTON (thm2, "I am a 'color=c' button", "")
  GW_USE_THEME_CUSTO_ONCE ("color=d")
  GW_ADD_BUTTON (thm2, "I am a 'color=d' button", "")
  GW_USE_THEME_CUSTO_ONCE ("color=e")
  GW_ADD_BUTTON (thm2, "I am a 'color=e' button", "")
  GW_ADD_CHECKBOX (thm2, ">Check box 1")
  GW_ADD_CHECKBOX (thm2, "Check box 2")
  GW_ADD_INPUTLINE (thm2, "", "Input Line")
  r = GW_ADD_RADIO (thm2, 0, ">Radio button 1")
  GW_ADD_RADIO (thm2, r, "Radio button 2")
  GW_USE_THEME_CUSTO_ONCE ("color=e")
  thm2flip1 = GW_ADD_FLIPSWITCH (thm2, "", "Off", ">On")
  thm2flip2 = GW_ADD_FLIPSWITCH (thm2, "", "Off", "On")
  GW_USE_THEME_CUSTO_ONCE ("color=d")
  GW_ADD_SLIDER (thm2, "", 0, 100, 1, 50)
  GW_USE_THEME_CUSTO_ONCE ("color=d")
  GW_ADD_TEXT (thm2, "The code of this page:")
  GW_USE_THEME_CUSTO_ONCE ("color=d")
  GW_ADD_TEXT (thm2, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_BUTTON (thm2, "Back", "BACK")
END IF
GW_RENDER (thm2)
GW_UNLOAD_THEME() %' to avoid future pages to inherit this theme
DO
  r$ = GW_WAIT_ACTION$()
  IF GW_FLIPSWITCH_CHANGED (thm2flip1, "Off") THEN POPUP "Switched off", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm2flip2, "On") THEN POPUP "Switched on", 0,0,0
UNTIL r$ = "BACK"
GOTO ThemePage

!'==========================================================================================================
ThemePage3:
IF !thm3 THEN
  code$ = SelfExtract$ ("ThemePage3:")
  GW_LOAD_THEME ("iOS")
  thm3 = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (thm3, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Theme 'iOS'"))
  GW_ADD_TEXT (thm3, "The 'iOS' theme is an old theme: panels are not supported...")
  GW_ADD_TEXT (thm3, "Some customized buttons:")
  GW_USE_THEME_CUSTO_ONCE ("color=a icon=arrow-r iconpos=right")
  GW_ADD_BUTTON (thm3, "color=a icon=arrow-r iconpos=right", "")
  GW_USE_THEME_CUSTO_ONCE ("color=b icon=arrow-l iconpos=left")
  GW_ADD_BUTTON (thm3, "color=b icon=arrow-l iconpos=left", "")
  GW_USE_THEME_CUSTO_ONCE ("color=c icon=arrow-d iconpos=bottom")
  GW_ADD_BUTTON (thm3, "color=c icon=arrow-d iconpos=bottom", "")
  GW_USE_THEME_CUSTO_ONCE ("color=e icon=arrow-u iconpos=top")
  GW_ADD_BUTTON (thm3, "color=e icon=arrow-u iconpos=top", "")
  GW_ADD_CHECKBOX (thm3, ">Check box 1")
  GW_ADD_CHECKBOX (thm3, "Check box 2")
  GW_ADD_INPUTLINE (thm3, "", "Input Line")
  r = GW_ADD_RADIO (thm3, 0, ">Radio button 1")
  GW_ADD_RADIO (thm3, r, "Radio button 2")
  thm3flip1 = GW_ADD_FLIPSWITCH (thm3, "Flipswitch initially 'on'", "Off", ">On")
  GW_USE_THEME_CUSTO_ONCE ("color=b")
  thm3flip2 = GW_ADD_FLIPSWITCH (thm3, "Flipswitch color=b initially 'off'", "Off", "On")
  GW_ADD_SLIDER (thm3, "Slider:", 0, 100, 1, 50)
  GW_ADD_TEXT (thm3, "The code of this page:")
  GW_ADD_TEXT (thm3, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_BUTTON (thm3, "Back", "BACK")
END IF
GW_RENDER (thm3)
GW_UNLOAD_THEME() %' to avoid future pages to inherit this theme
DO
  r$ = GW_WAIT_ACTION$()
  IF GW_FLIPSWITCH_CHANGED (thm3flip1, "Off") THEN POPUP "Switched off", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm3flip2, "On") THEN POPUP "Switched on", 0,0,0
UNTIL r$ = "BACK"
GOTO ThemePage

!'==========================================================================================================
ThemePage4:
IF !thm4 THEN
  code$ = SelfExtract$ ("ThemePage4:")
  GW_LOAD_THEME ("bootstrap")
  thm4 = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("color=f icon=back iconpos=left")
  GW_ADD_TITLEBAR (thm4, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Theme 'bootstrap'"))
  thm4code = GW_ADD_PANEL (thm4, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))

  GW_ADD_TEXT (thm4, "Some customized buttons:")
  GW_USE_THEME_CUSTO_ONCE ("color=a iconpos=right icon=alert")
  GW_ADD_BUTTON (thm4, "color=a\t icon=alert", "")
  GW_USE_THEME_CUSTO_ONCE ("color=b iconpos=right icon=audio")
  GW_ADD_BUTTON (thm4, "color=b\t icon=audio", "")
  GW_USE_THEME_CUSTO_ONCE ("color=c iconpos=right icon=camera")
  GW_ADD_BUTTON (thm4, "color=c\t icon=camera", "")
  GW_USE_THEME_CUSTO_ONCE ("color=d iconpos=right icon=cloud")
  GW_ADD_BUTTON (thm4, "color=d\t icon=cloud", "")
  GW_USE_THEME_CUSTO_ONCE ("color=e iconpos=right icon=forbidden")
  GW_ADD_BUTTON (thm4, "color=e\t icon=forbidden", "")
  GW_USE_THEME_CUSTO_ONCE ("color=f iconpos=right icon=info")
  GW_ADD_BUTTON (thm4, "color=f\t icon=info", "")

  GW_ADD_TEXT (thm4, "Buttons with 'inline notext' custo:")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=video")
  GW_ADD_BUTTON (thm4, "", "1")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=recycle")
  GW_ADD_BUTTON (thm4, "", "2")
  GW_USE_THEME_CUSTO_ONCE ("color=e inline iconpos=notext icon=navigation")
  GW_ADD_BUTTON (thm4, "", "3")
  GW_USE_THEME_CUSTO_ONCE ("color=a inline iconpos=notext icon=search")
  GW_ADD_BUTTON (thm4, "", "4")
  GW_USE_THEME_CUSTO_ONCE ("color=c inline iconpos=notext icon=shop")
  GW_ADD_BUTTON (thm4, "", "5")
  GW_USE_THEME_CUSTO_ONCE ("color=d inline iconpos=notext icon=tag")
  GW_ADD_BUTTON (thm4, "", "6")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=user")
  GW_ADD_BUTTON (thm4, "", "7")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=phone")
  GW_ADD_BUTTON (thm4, "", "8")
  GW_ADD_CHECKBOX (thm4, ">Check box 1")
  GW_ADD_CHECKBOX (thm4, "Check box 2")
  GW_ADD_INPUTLINE (thm4, "", "Input Line")
  r = GW_ADD_RADIO (thm4, 0, ">Radio button 1")
  GW_ADD_RADIO (thm4, r, "Radio button 2")
  GW_USE_THEME_CUSTO_ONCE ("color=c")
  thm4flip1 = GW_ADD_FLIPSWITCH (thm4, "", "Off", ">On")
  GW_USE_THEME_CUSTO_ONCE ("color=d")
  thm4flip2 = GW_ADD_FLIPSWITCH (thm4, "", "Off", "On")
  GW_USE_THEME_CUSTO_ONCE ("color=f")
  GW_ADD_SLIDER (thm4, "", 0, 100, 1, 50)

  GW_ADD_TEXT (thm4, "")
  GW_ADD_LINK (thm4, "See the code of this page", GW_SHOW_PANEL$ (thm4code))
  GW_ADD_BUTTON (thm4, "Back", "BACK")
END IF
GW_RENDER (thm4)
GW_UNLOAD_THEME() %' to avoid future pages to inherit this theme
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "1" THEN POPUP "color=b inline iconpos=notext icon=video", 0,0,0
  IF r$ = "2" THEN POPUP "color=f inline iconpos=notext icon=recycle", 0,0,0
  IF r$ = "3" THEN POPUP "color=e inline iconpos=notext icon=navigation", 0,0,0
  IF r$ = "4" THEN POPUP "color=a inline iconpos=notext icon=search", 0,0,0
  IF r$ = "5" THEN POPUP "color=c inline iconpos=notext icon=shop", 0,0,0
  IF r$ = "6" THEN POPUP "color=d inline iconpos=notext icon=tag", 0,0,0
  IF r$ = "7" THEN POPUP "color=b inline iconpos=notext icon=user", 0,0,0
  IF r$ = "8" THEN POPUP "color=f inline iconpos=notext icon=phone", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm4flip1, "Off") THEN POPUP "Switched off", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm4flip2, "On") THEN POPUP "Switched on", 0,0,0
UNTIL r$ = "BACK"
GOTO ThemePage

!'==========================================================================================================
ThemePage5:
IF !thm5 THEN
  code$ = SelfExtract$ ("ThemePage5:")
  GW_LOAD_THEME ("android-holo")
  thm5 = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (thm5, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Theme 'android-holo'"))
  GW_ADD_TEXT (thm5, "The 'android-holo' theme is an old theme: panels are not supported...")
  GW_ADD_TEXT (thm5, "Some customized buttons:")
  GW_USE_THEME_CUSTO_ONCE ("color=a icon=back")
  GW_ADD_BUTTON (thm5, "color=a icon=back", "")
  GW_USE_THEME_CUSTO_ONCE ("color=b icon=menu")
  GW_ADD_BUTTON (thm5, "color=b icon=menu", "")
  GW_USE_THEME_CUSTO_ONCE ("color=c icon=home")
  GW_ADD_BUTTON (thm5, "color=c icon=home", "")
  GW_ADD_CHECKBOX (thm5, ">Check box 1")
  GW_ADD_CHECKBOX (thm5, "Check box 2")
  GW_ADD_INPUTLINE (thm5, "", "Input Line")
  r = GW_ADD_RADIO (thm5, 0, ">Radio button 1")
  GW_ADD_RADIO (thm5, r, "Radio button 2")
  thm5flip1 = GW_ADD_FLIPSWITCH (thm5, "Flipswitch initially 'on'", "Off", ">On")
  GW_USE_THEME_CUSTO_ONCE ("color=b")
  thm5flip2 = GW_ADD_FLIPSWITCH (thm5, "Flipswitch color=b initially 'off'", "Off", "On")
  GW_ADD_SLIDER (thm5, "Slider:", 0, 100, 1, 50)
  GW_ADD_TEXT (thm5, "The code of this page:")
  GW_ADD_TEXT (thm5, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_BUTTON (thm5, "Back", "BACK")
END IF
GW_RENDER (thm5)
GW_UNLOAD_THEME() %' to avoid future pages to inherit this theme
DO
  r$ = GW_WAIT_ACTION$()
  IF GW_FLIPSWITCH_CHANGED (thm5flip1, "Off") THEN POPUP "Switched off", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm5flip2, "On") THEN POPUP "Switched on", 0,0,0
UNTIL r$ = "BACK"
GOTO ThemePage

!'==========================================================================================================
ThemePage6:
IF !thm6 THEN
  code$ = SelfExtract$ ("ThemePage6:")
  GW_LOAD_THEME ("square-ui")
  thm6 = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (thm6, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Theme 'square-ui'"))
  thm6code = GW_ADD_PANEL (thm6, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))

  GW_ADD_TEXT (thm6, "Some customized buttons:")
  GW_USE_THEME_CUSTO_ONCE ("color=a icon=action")
  GW_ADD_BUTTON (thm6, "color=a\t icon=action", "")
  GW_USE_THEME_CUSTO_ONCE ("color=b icon=arrow-d-l")
  GW_ADD_BUTTON (thm6, "color=b\t icon=arrow-d-l", "")
  GW_USE_THEME_CUSTO_ONCE ("color=c icon=audio")
  GW_ADD_BUTTON (thm6, "color=c\t icon=audio", "")
  GW_USE_THEME_CUSTO_ONCE ("color=d icon=camera")
  GW_ADD_BUTTON (thm6, "color=d\t icon=camera", "")
  GW_USE_THEME_CUSTO_ONCE ("color=e icon=check")
  GW_ADD_BUTTON (thm6, "color=e\t icon=check", "")
  GW_USE_THEME_CUSTO_ONCE ("color=f icon=clock")
  GW_ADD_BUTTON (thm6, "color=f\t icon=clock", "")
  GW_USE_THEME_CUSTO_ONCE ("color=g icon=comment")
  GW_ADD_BUTTON (thm6, "color=g\t icon=comment", "")

  GW_ADD_TEXT (thm6, "Buttons with 'inline notext' custo:")
  GW_USE_THEME_CUSTO_ONCE ("color=b inline iconpos=notext icon=video")
  GW_ADD_BUTTON (thm6, "", "1")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=recycle")
  GW_ADD_BUTTON (thm6, "", "2")
  GW_USE_THEME_CUSTO_ONCE ("color=e inline iconpos=notext icon=navigation")
  GW_ADD_BUTTON (thm6, "", "3")
  GW_USE_THEME_CUSTO_ONCE ("color=a inline iconpos=notext icon=search")
  GW_ADD_BUTTON (thm6, "", "4")
  GW_USE_THEME_CUSTO_ONCE ("color=c inline iconpos=notext icon=shop")
  GW_ADD_BUTTON (thm6, "", "5")
  GW_USE_THEME_CUSTO_ONCE ("color=d inline iconpos=notext icon=tag")
  GW_ADD_BUTTON (thm6, "", "6")
  GW_USE_THEME_CUSTO_ONCE ("color=b inline iconpos=notext icon=user")
  GW_ADD_BUTTON (thm6, "", "7")
  GW_USE_THEME_CUSTO_ONCE ("color=f inline iconpos=notext icon=phone")
  GW_ADD_BUTTON (thm6, "", "8")
  GW_USE_THEME_CUSTO_ONCE ("color=d")
  GW_ADD_CHECKBOX (thm6, ">Check box 1")
  GW_USE_THEME_CUSTO_ONCE ("color=d")
  GW_ADD_CHECKBOX (thm6, "Check box 2")
  GW_ADD_INPUTLINE (thm6, "", "Input Line")
  GW_USE_THEME_CUSTO_ONCE ("color=e")
  r = GW_ADD_RADIO (thm6, 0, ">Radio button 1")
  GW_USE_THEME_CUSTO_ONCE ("color=e")
  GW_ADD_RADIO (thm6, r, "Radio button 2")
  GW_USE_THEME_CUSTO_ONCE ("color=b")
  thm6flip1 = GW_ADD_FLIPSWITCH (thm6, "", "Off", ">On")
  thm6flip2 = GW_ADD_FLIPSWITCH (thm6, "", "Off", "On")
  GW_USE_THEME_CUSTO_ONCE ("color=b")
  GW_ADD_SLIDER (thm6, "", 0, 100, 1, 50)

  GW_ADD_TEXT (thm6, "")
  GW_ADD_LINK (thm6, "See the code of this page", GW_SHOW_PANEL$ (thm6code))
  GW_ADD_BUTTON (thm6, "Back", "BACK")
END IF
GW_RENDER (thm6)
GW_UNLOAD_THEME() %' to avoid future pages to inherit this theme
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "1" THEN POPUP "color=b inline iconpos=notext icon=video", 0,0,0
  IF r$ = "2" THEN POPUP "color=f inline iconpos=notext icon=recycle", 0,0,0
  IF r$ = "3" THEN POPUP "color=e inline iconpos=notext icon=navigation", 0,0,0
  IF r$ = "4" THEN POPUP "color=a inline iconpos=notext icon=search", 0,0,0
  IF r$ = "5" THEN POPUP "color=c inline iconpos=notext icon=shop", 0,0,0
  IF r$ = "6" THEN POPUP "color=d inline iconpos=notext icon=tag", 0,0,0
  IF r$ = "7" THEN POPUP "color=b inline iconpos=notext icon=user", 0,0,0
  IF r$ = "8" THEN POPUP "color=f inline iconpos=notext icon=phone", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm6flip1, "Off") THEN POPUP "Switched off", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm6flip2, "On") THEN POPUP "Switched on", 0,0,0
UNTIL r$ = "BACK"
GOTO ThemePage

!'==========================================================================================================
ThemePage7:
IF !thm7 THEN
  code$ = SelfExtract$ ("ThemePage7:")
  GW_LOAD_THEME ("metro")
  thm7 = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (thm7, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Theme 'metro'"))
  GW_ADD_TEXT (thm7, "The 'metro' theme is an old theme: panels are not supported...")
  GW_ADD_TEXT (thm7, "Some customized buttons:")
  GW_USE_THEME_CUSTO_ONCE ("color=a icon=back")
  GW_ADD_BUTTON (thm7, "color=a icon=back", "")
  GW_USE_THEME_CUSTO_ONCE ("color=b icon=menu")
  GW_ADD_BUTTON (thm7, "color=b icon=menu", "")
  GW_ADD_CHECKBOX (thm7, ">Check box 1")
  GW_ADD_CHECKBOX (thm7, "Check box 2")
  GW_ADD_INPUTLINE (thm7, "", "Input Line")
  r = GW_ADD_RADIO (thm7, 0, ">Radio button 1")
  GW_ADD_RADIO (thm7, r, "Radio button 2")
  thm7flip1 = GW_ADD_FLIPSWITCH (thm7, "Flipswitch initially 'on'", "Off", ">On")
  GW_USE_THEME_CUSTO_ONCE ("color=b")
  thm7flip2 = GW_ADD_FLIPSWITCH (thm7, "Flipswitch color=b initially 'off'", "Off", "On")
  GW_ADD_SLIDER (thm7, "Slider:", 0, 100, 1, 50)
  GW_ADD_TEXT (thm7, "The code of this page:")
  GW_ADD_TEXT (thm7, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_BUTTON (thm7, "Back", "BACK")
END IF
GW_RENDER (thm7)
GW_UNLOAD_THEME() %' to avoid future pages to inherit this theme
DO
  r$ = GW_WAIT_ACTION$()
  IF GW_FLIPSWITCH_CHANGED (thm7flip1, "Off") THEN POPUP "Switched off", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm7flip2, "On") THEN POPUP "Switched on", 0,0,0
UNTIL r$ = "BACK"
GOTO ThemePage

!'==========================================================================================================
ThemePage8:
IF !tp8 THEN
  code$ = SelfExtract$ ("ThemePage8:")
  tp8 = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (tp8, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Theme 'native-droid-*'"))
  tp8code = GW_ADD_PANEL (tp8, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_TEXT (tp8, "The 'native-droid' theme family is recommended to give your app a nice Android look.\nYou can decline the theme in light/dark and several colors: blue/green/purple/red/yellow")
  GW_ADD_BUTTON (tp8, "native-droid-light-blue", "1")
  GW_ADD_BUTTON (tp8, "native-droid-light-green", "2")
  GW_ADD_BUTTON (tp8, "native-droid-light-purple", "3")
  GW_ADD_BUTTON (tp8, "native-droid-light-red", "4")
  GW_ADD_BUTTON (tp8, "native-droid-light-yellow", "5")
  GW_ADD_BUTTON (tp8, "native-droid-dark-blue", "6")
  GW_ADD_BUTTON (tp8, "native-droid-dark-green", "7")
  GW_ADD_BUTTON (tp8, "native-droid-dark-purple", "8")
  GW_ADD_BUTTON (tp8, "native-droid-dark-red", "9")
  GW_ADD_BUTTON (tp8, "native-droid-dark-yellow", "10")
  GW_ADD_TEXT (tp8, "")
  GW_ADD_LINK (tp8, "See the code of this page", GW_SHOW_PANEL$ (tp8code))
  GW_ADD_BUTTON (tp8, "Back", "BACK")
END IF
GW_RENDER (tp8)
r$ = GW_WAIT_ACTION$()
IF r$ = "BACK" THEN GOTO ThemePage
IF r$ = "1" THEN nativeandro$ = "native-droid-light-blue"
IF r$ = "2" THEN nativeandro$ = "native-droid-light-green"
IF r$ = "3" THEN nativeandro$ = "native-droid-light-purple"
IF r$ = "4" THEN nativeandro$ = "native-droid-light-red"
IF r$ = "5" THEN nativeandro$ = "native-droid-light-yellow"
IF r$ = "6" THEN nativeandro$ = "native-droid-dark-blue"
IF r$ = "7" THEN nativeandro$ = "native-droid-dark-green"
IF r$ = "8" THEN nativeandro$ = "native-droid-dark-purple"
IF r$ = "9" THEN nativeandro$ = "native-droid-dark-red"
IF r$ = "10" THEN nativeandro$ = "native-droid-dark-yellow"
GOTO ThemePage8bis

!'==========================================================================================================
ThemePage8bis:
IF !thm8 THEN
  code$ = SelfExtract$ ("ThemePage8bis:")
  GW_LOAD_THEME (nativeandro$)
  thm8 = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ( "color=b icon=menu")
  thm8code = GW_ADD_PANEL (thm8, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (thm8, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ (nativeandro$))

  GW_ADD_BUTTON (thm8, "First button", "DUMP")
  GW_ADD_BUTTON (thm8, "Second button", "")
  GW_ADD_BUTTON (thm8, "Third button", "")

  GW_ADD_TEXT (thm8, "Buttons with 'inline notext' custo:")
  GW_USE_THEME_CUSTO_ONCE ("color=b inline iconpos=notext icon=video")
  GW_ADD_BUTTON (thm8, "", "1")
  GW_USE_THEME_CUSTO_ONCE ("color=b inline iconpos=notext icon=recycle")
  GW_ADD_BUTTON (thm8, "", "2")
  GW_USE_THEME_CUSTO_ONCE ("color=b inline iconpos=notext icon=navigation")
  GW_ADD_BUTTON (thm8, "", "3")
  GW_USE_THEME_CUSTO_ONCE ("color=b inline iconpos=notext icon=search")
  GW_ADD_BUTTON (thm8, "", "4")
  GW_USE_THEME_CUSTO_ONCE ("color=b inline iconpos=notext icon=shop")
  GW_ADD_BUTTON (thm8, "", "5")
  GW_USE_THEME_CUSTO_ONCE ("color=b inline iconpos=notext icon=tag")
  GW_ADD_BUTTON (thm8, "", "6")
  GW_USE_THEME_CUSTO_ONCE ("color=b inline iconpos=notext icon=user")
  GW_ADD_BUTTON (thm8, "", "7")
  GW_USE_THEME_CUSTO_ONCE ("color=b inline iconpos=notext icon=phone")
  GW_ADD_BUTTON (thm8, "", "8")
  GW_OPEN_GROUP (thm8)
  GW_ADD_CHECKBOX (thm8, ">Check box 1")
  GW_ADD_CHECKBOX (thm8, "Check box 2")
  GW_ADD_CHECKBOX (thm8, ">Check box 3")
  GW_CLOSE_GROUP (thm8)
  GW_ADD_INPUTLINE (thm8, "", "Input Line")
  GW_OPEN_GROUP (thm8)
  r = GW_ADD_RADIO (thm8, 0, ">Radio button 1")
  GW_ADD_RADIO (thm8, r, "Radio button 2")
  GW_ADD_RADIO (thm8, r, "Radio button 3")
  GW_CLOSE_GROUP (thm8)
  thm8flip1 = GW_ADD_FLIPSWITCH (thm8, "", "Off", ">On")
  thm8flip2 = GW_ADD_FLIPSWITCH (thm8, "", "Off", "On")
  GW_ADD_SLIDER (thm8, "", 0, 100, 1, 50)

  GW_ADD_TEXT (thm8, "")
  GW_ADD_LINK (thm8, "See the code of this page", GW_SHOW_PANEL$ (thm8code))
  GW_ADD_BUTTON (thm8, "Back", "BACK")

  oldnativeandro$ = nativeandro$
ELSE %' page already made: we do a guru trick to replace the theme
  LIST.GET GW_PGE, thm8, e$
  e$ = REPLACE$ (e$, oldnativeandro$, nativeandro$)
  IF IS_IN ("-dark-", nativeandro$) & !IS_IN ("-dark-", oldnativeandro$) THEN
    e$ = REPLACE$ (e$, "jquerymobile.nativedroid.light.css", "jquerymobile.nativedroid.dark.css")
  ELSEIF IS_IN ("-light-", nativeandro$) & !IS_IN ("-light-", oldnativeandro$) THEN
    e$ = REPLACE$ (e$, "jquerymobile.nativedroid.dark.css", "jquerymobile.nativedroid.light.css")
  END IF
  IF RIGHT$ (nativeandro$, 3) <> RIGHT$ (oldnativeandro$, 3) THEN
    i = IS_IN ("-", oldnativeandro$, 16)
    ona_col$ = MID$ (oldnativeandro$, i+1)
    i = IS_IN ("-", nativeandro$, 16)
    na_col$ = MID$ (nativeandro$, i+1)
    e$ = REPLACE$ (e$, "jquerymobile.nativedroid.color."+ona_col$, "jquerymobile.nativedroid.color."+na_col$)
  END IF
  LIST.REPLACE GW_PGE, thm8, e$
  oldnativeandro$ = nativeandro$
END IF
GW_RENDER (thm8)
GW_UNLOAD_THEME() %' to avoid future pages to inherit this theme
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "1" THEN POPUP "color=b inline iconpos=notext icon=video", 0,0,0
  IF r$ = "2" THEN POPUP "color=b inline iconpos=notext icon=recycle", 0,0,0
  IF r$ = "3" THEN POPUP "color=b inline iconpos=notext icon=navigation", 0,0,0
  IF r$ = "4" THEN POPUP "color=b inline iconpos=notext icon=search", 0,0,0
  IF r$ = "5" THEN POPUP "color=b inline iconpos=notext icon=shop", 0,0,0
  IF r$ = "6" THEN POPUP "color=b inline iconpos=notext icon=tag", 0,0,0
  IF r$ = "7" THEN POPUP "color=b inline iconpos=notext icon=user", 0,0,0
  IF r$ = "8" THEN POPUP "color=b inline iconpos=notext icon=phone", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm8flip1, "Off") THEN POPUP "Switched off", 0,0,0
  IF GW_FLIPSWITCH_CHANGED (thm8flip2, "On") THEN POPUP "Switched on", 0,0,0
  IF r$ = "DUMP" THEN GW_DUMP (thm8)
UNTIL r$ = "BACK"
GOTO ThemePage8

!'==========================================================================================================
DlgMsgPage:
IF !dlm THEN
  code$ = SelfExtract$ ("DlgMsgPage:")
  dlm = GW_NEW_PAGE()
  ARRAY.LOAD bna$[], "OK"
  dm0 = GW_ADD_DIALOG_MESSAGE (dlm, "", "You can trigger a dialog message manually, for example after rendering a page...", bna$[])
  dm1 = GW_ADD_DIALOG_MESSAGE (dlm, "", "This is a dialog message without title with a single button with the default transition 'pop'", bna$[])
  ARRAY.DELETE bna$[]
  ARRAY.LOAD bna$[], "Yes>Y", "No>N"
  dm2 = GW_ADD_DIALOG_MESSAGE (dlm, "Now I have a title...", "...and 2 buttons.\nNice?", bna$[])
  ARRAY.DELETE bna$[]
  ARRAY.LOAD bna$[], "Vibrate>VIBR", "Beep>BEEP", "Cancel>0"
  dm3 = GW_ADD_DIALOG_MESSAGE (dlm, "Vibrate or Beep", "What do you want to do?", bna$[])
  ARRAY.DELETE bna$[]
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (dlm, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Dialog Message demo"))
  dlmcode = GW_ADD_PANEL (dlm, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_TEXT (dlm, "Dialog Messages are used to display a popup window and get the user feedback via 1 or more buttons.\nDialog Messages can be opened (triggered) via links or via buttons:")
  GW_ADD_LINK (dlm, "Click here for a simple dialog box", GW_SHOW_DIALOG_MESSAGE$(dm1))
  GW_ADD_TEXT (dlm, "And click the 2 following buttons for more complex dialog messages with different transitions:")
  GW_START_CENTER (dlm)
  GW_USE_THEME_CUSTO_ONCE ("inline icon=info")
  GW_SET_TRANSITION (dm2, "flip")
  GW_ADD_BUTTON (dlm, "Question", GW_SHOW_DIALOG_MESSAGE$(dm2))
  GW_USE_THEME_CUSTO_ONCE ("inline icon=grid")
  GW_SET_TRANSITION (dm3, "slidedown")
  GW_ADD_BUTTON (dlm, "3 buttons", GW_SHOW_DIALOG_MESSAGE$(dm3))
  GW_STOP_CENTER (dlm)
  GW_ADD_TEXT (dlm, "")
  GW_ADD_LINK (dlm, "See the code of this page", GW_SHOW_PANEL$ (dlmcode))
  GW_ADD_BUTTON (dlm, "Back", "BACK")
END IF
GW_RENDER (dlm)
PAUSE 1000
GW_SET_TRANSITION (dm0, "turn")
GW_SHOW_DIALOG_MESSAGE (dm0)
GW_SET_TRANSITION (dm0, "pop") %' set back the default transition to 'pop' for next DMs
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "Y" THEN POPUP "You clicked 'Yes'", 0,0,0
  IF r$ = "N" THEN POPUP "You clicked 'No'", 0,0,0
  IF r$ = "VIBR" THEN VIBRATE buzz[], -1
  IF r$ = "BEEP" THEN TONE 300, 300
UNTIL r$ = "BACK"
GOTO MainPage

!'==========================================================================================================
VideoPage:
IF !vid THEN
  code$ = SelfExtract$ ("VideoPage:")
  vid = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (vid, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Video demo"))
  vidcode = GW_ADD_PANEL (vid, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_ADD_TEXT (vid, "This is a local 3gp video:")
  GW_ADD_VIDEO (vid, "small.3gp")
  GW_ADD_TEXTBOX (vid, "<p style='color:red'>If it doesn't play, it's because you don't have it locally... In this case press the Download button below to get it from Paul Laughton's FTP:</p>")
  GW_ADD_BUTTON (vid, "Download 100kB 3gp video", "DL3GP")
  GW_ADD_TEXT (vid, "And this is an online mp4 video:")
  GW_ADD_VIDEO (vid, "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
  GW_ADD_TEXT (vid, "")
  GW_ADD_LINK (vid, "See the code of this page", GW_SHOW_PANEL$ (vidcode))
  GW_ADD_BUTTON (vid, "Back", "BACK")
END IF
GW_RENDER (vid)
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "DL3GP" THEN
    POPUP "Initializing connection to ftp.laughton.com...", 0,0,0
    FTP.OPEN "ftp.laughton.com", 21, "basic", "basic"
    FTP.GET "/html/GW (GUI-Web lib)/small.3gp", "small.3gp"
    FTP.CLOSE
    POPUP "Video downloaded locally !", 0,0,0
    GW_RENDER (vid)
  END IF
UNTIL r$ = "BACK"
GOTO MainPage

!'==========================================================================================================
TablePage:
IF !tbl THEN
  code$ = SelfExtract$ ("TablePage:")
  tbl = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (tbl, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Table demo"))
  tblcode = GW_ADD_PANEL (tbl, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  tbim1$ = GW_ADD_IMAGE$ ("cartman.png>IMG1")
  tbimg1 = GW_LAST_ID()
  tbim2$ = GW_ADD_IMAGE$ ("cartman.png>IMG2")
  tbimg2 = GW_LAST_ID()
  ARRAY.LOAD myTbl0$[], tbim1$, "< click image", "click image > ", tbim2$
  GW_ADD_TEXT (tbl, "This is a table containing local, clickable images:")
  GW_ADD_TABLE (tbl, 2, myTbl0$[]) %' n_cols = 2
  ARRAY.LOAD myTbl1$[], ~
    ">Animal", "Food", "Nemesis" ~
    "Dog", "Bone", "Cat" ~
    "Cat", "Mouse", "Dog" ~
    "Mouse", "Cheese", "Cat" ~
    "Fish", "Worm", "Cat" ~
    "Worm", "Dirt", "Fishing rod"
  GW_ADD_TEXT (tbl, "This is a 1-dimension BASIC! array, statically loaded, with a title line, rendered as a table:")
  GW_ADD_TABLE (tbl, 3, myTbl1$[]) %' n_cols = 3
  LIST.CREATE s, RndList
  FOR col=1 TO 6
    FOR row=1 TO 8
      LIST.ADD RndList, INT$(col * 100 * RND() + 0.5)
    NEXT
  NEXT
  GW_ADD_TEXT (tbl, "Now this is a 1-dimension BASIC! array of 6x8 dynamic elements (without title line) created from a LIST.TOARRAY, rendered as a table:")
  LIST.TOARRAY RndList, myTbl2$[]
  tbl_ctl2 = GW_ADD_TABLE (tbl, 6, myTbl2$[]) %' n_cols = 6
  GW_USE_THEME_CUSTO_ONCE ("inline color=b icon=plus")
  GW_START_CENTER (tbl)
  GW_ADD_BUTTON (tbl, "Add row", "ADD")
  GW_USE_THEME_CUSTO_ONCE ("inline color=b icon=minus")
  GW_ADD_BUTTON (tbl, "Remove row", "DEL")
  GW_STOP_CENTER (tbl)
  GW_ADD_TEXT (tbl, "")
  GW_ADD_LINK (tbl, "See the code of this page", GW_SHOW_PANEL$ (tblcode))
  GW_ADD_BUTTON (tbl, "Back", "BACK")
END IF
tbimsel1=0
tbimsel2=0
GW_RENDER (tbl)
DO
  r$ = GW_WAIT_ACTION$()
  IF r$ = "IMG1" THEN
    tbimsel1=1-tbimsel1
    IF tbimsel1 THEN
      GW_MODIFY (tbimg1, "content", "fly.gif")
    ELSE
      GW_MODIFY (tbimg1, "content", "cartman.png")
    END IF
  ELSEIF r$ = "IMG2" THEN
    tbimsel2=1-tbimsel2
    IF tbimsel2 THEN
      GW_MODIFY (tbimg2, "content", "fly.gif")
    ELSE
      GW_MODIFY (tbimg2, "content", "cartman.png")
    END IF
  ELSEIF r$ = "ADD" THEN
    FOR col=1 TO 6
      LIST.ADD RndList, INT$(col * 100 * RND() + 0.5)
    NEXT
    ARRAY.DELETE myTbl2$[]
    LIST.TOARRAY RndList, myTbl2$[]
    GW_AMODIFY (tbl_ctl2, "content", myTbl2$[])
  ELSEIF r$ = "DEL" THEN
    LIST.SIZE RndList, ls
    IF !ls THEN %' already empty table
      POPUP "Empty table!", 0,0,0
    ELSEIF ls=6 THEN %' remove the last line => empty table
      LIST.CLEAR RndList
      GW_MODIFY (tbl_ctl2, "content", "")
    ELSE
      FOR col=1 TO 6
        LIST.REMOVE RndList, ls
        LIST.SIZE RndList, ls
      NEXT
      ARRAY.DELETE myTbl2$[]
      LIST.TOARRAY RndList, myTbl2$[]
      GW_AMODIFY (tbl_ctl2, "content", myTbl2$[])
    END IF
  END IF
UNTIL r$ = "BACK"
GOTO MainPage

!'==========================================================================================================
LvPage:
IF !lvp THEN
  code$ = SelfExtract$ ("LvPage:")
  ARRAY.LOAD lv_typ$[], ">Cars", "Fruits", "Languages"
  act=1 %' 1st array is selected
  ARRAY.LOAD lv_car$[], "Acura ($36 945)", "Audi ($73 532)", "BMW ($58 300)", "Cadillac ($70 533)", "Ferrari ($243 090)"
  ARRAY.LOAD lv_fruit$[], "Apple", "Banana", "Cherry", "Cranberry", "Grape", "Orange"
  ARRAY.LOAD lv_lang$[], "Hungarian", "English", "Spanish", "French", "Dutch", "Deutsch", "Russian", "Turkish", "Latin"

  lvp = GW_NEW_PAGE()
  GW_USE_THEME_CUSTO_ONCE ("icon=back iconpos=left")
  GW_ADD_TITLEBAR (lvp, GW_ADD_BAR_LBUTTON$ ("Back>BACK") + GW_ADD_BAR_TITLE$ ("GW Listview demo"))
  lvcode = GW_ADD_PANEL (lvp, GW_CODE_HIGHLIGHT$ (code$, BLA$[], BLU$[], RED$[]))
  GW_USE_THEME_CUSTO_ONCE ("inline")
  lv_typ_chosen = GW_ADD_SELECTBOX (lvp, "1. Choose a type of listview:", lv_typ$[])
  GW_ADD_LISTENER (lvp, lv_typ_chosen, "change", "SELECTBOX_CHANGED")
  GW_ADD_TEXT (lvp, "2. Then select the listview settings:")
  GW_USE_THEME_CUSTO_ONCE ("inline")
  GW_OPEN_GROUP (lvp)
  ordered_chk = GW_ADD_CHECKBOX (lvp, "Ordered")
  title_chk = GW_ADD_CHECKBOX (lvp, "Title")
  linked_chk = GW_ADD_CHECKBOX (lvp, "Linked")
  GW_CLOSE_GROUP (lvp)
  GW_ADD_LISTENER (lvp, ordered_chk, "change", "ORDERED_CHANGED")
  GW_ADD_LISTENER (lvp, title_chk, "change", "TITLE_CHANGED")
  GW_ADD_LISTENER (lvp, linked_chk, "change", "LINKED_CHANGED")
  lv = GW_ADD_LISTVIEW (lvp, lv_car$[])
  GW_ADD_TEXT (lvp, "")
  GW_ADD_LINK (lvp, "See the code of this page", GW_SHOW_PANEL$ (lvcode))
  GW_ADD_BUTTON (lvp, "Back", "BACK")
END IF

GW_RENDER (lvp)
DO
  r$ = GW_WAIT_ACTION$()
  
  IF r$ = "SELECTBOX_CHANGED"
    act = GW_GET_VALUE (lv_typ_chosen)
    IF act <> sb THEN GOSUB RefreshListview
  END IF
  
  IF r$ = "ORDERED_CHANGED"
    ordered = GW_GET_VALUE (ordered_chk)
    IF ordered %' Switch to ordered listview
      lv_car$[1] = "#" + lv_car$[1] %' '#' = marker for ordered list
      lv_fruit$[1] = "#" + lv_fruit$[1]
      lv_lang$[1] = "#" + lv_lang$[1]
    ELSE %' Switch to unordered listview
      lv_car$[1] = MID$ (lv_car$[1], 2)
      lv_fruit$[1] = MID$ (lv_fruit$[1], 2)
      lv_lang$[1] = MID$ (lv_lang$[1], 2)
    END IF
    GOSUB RefreshListview
  END IF
  
  IF r$ = "TITLE_CHANGED"
    titled = GW_GET_VALUE (title_chk)
    IF titled %' Turn 1st and 3rd elements to titles
      lv_car$[1] = ">Title" %' leading '>' = marker for title
      lv_car$[3] = ">Separator"
      lv_fruit$[1] = ">Title"
      lv_fruit$[3] = ">Separator"
      lv_lang$[1] = ">Title"
      lv_lang$[3] = ">Separator"
    ELSE %' Remove title marks
      lv_car$[1] = "Acura ($36 945)"
      lv_car$[3] = "BMW ($58 300)"
      lv_fruit$[1] = "Apple"
      lv_fruit$[3] = "Cherry"
      lv_lang$[1] = "Hungarian"
      lv_lang$[3] = "Spanish"
    END IF
    IF ordered
      lv_car$[1] = "#" + lv_car$[1]
      lv_fruit$[1] = "#" + lv_fruit$[1]
      lv_lang$[1] = "#" + lv_lang$[1]
    END IF
    IF linked
      lv_car$[1] += ">LV1"
      lv_car$[3] += ">LV3"
      lv_fruit$[1] += ">LV1"
      lv_fruit$[3] += ">LV3"
      lv_lang$[1] += ">LV1"
      lv_lang$[3] += ">LV3"
    END IF
    GOSUB RefreshListview
  END IF
  
  IF r$ = "LINKED_CHANGED"
    linked = GW_GET_VALUE (linked_chk)
    IF linked %' Add a link to all elements
      ARRAY.LENGTH al, lv_car$[]
      FOR i=1 to al
        lv_car$[i] += ">LV" + INT$(i)
      NEXT
      ARRAY.LENGTH al, lv_fruit$[]
      FOR i=1 to al
        lv_fruit$[i] += ">LV" + INT$(i)
      NEXT
      ARRAY.LENGTH al, lv_lang$[]
      FOR i=1 to al
        lv_lang$[i] += ">LV" + INT$(i)
      NEXT
    ELSE %' Remove links
      ARRAY.LENGTH al, lv_car$[]
      FOR i=1 to al
        lv_car$[i] = LEFT$ (lv_car$[i], LEN (lv_car$[i]) - 4)
      NEXT
      ARRAY.LENGTH al, lv_fruit$[]
      FOR i=1 to al
        lv_fruit$[i] = LEFT$ (lv_fruit$[i], LEN (lv_fruit$[i]) - 4)
      NEXT
      ARRAY.LENGTH al, lv_lang$[]
      FOR i=1 to al
        lv_lang$[i] = LEFT$ (lv_lang$[i], LEN (lv_lang$[i]) - 4)
      NEXT
    END IF
    GOSUB RefreshListview
  END IF
  
  IF LEFT$ (r$, 2) = "LV"
    IF act=1
      e$ = lv_car$[ VAL (MID$ (r$,3)) ]
    ELSEIF act=2
      e$ = lv_fruit$[ VAL (MID$ (r$,3)) ]
    ELSE
      e$ = lv_lang$[ VAL (MID$ (r$,3)) ]
    END IF
    e$ = LEFT$ (e$, IS_IN (">", e$) - 1)
    IF  IS_IN ("#", e$) = 1 THEN e$ = MID$ (e$, 2)
    e$ = "You picked " + e$
    POPUP e$, 0,0,0
  END IF

  IF r$ = "BACK" %' reset the arrays for next time
    act = 1
    sb = act
    ordered = 0
    titled = 0
    linked = 0
    ARRAY.DELETE lv_car$[]
    ARRAY.LOAD lv_car$[], "Acura ($36 945)", "Audi ($73 532)", "BMW ($58 300)", "Cadillac ($70 533)", "Ferrari ($243 090)"
    ARRAY.DELETE lv_fruit$[]
    ARRAY.LOAD lv_fruit$[], "Apple", "Banana", "Cherry", "Cranberry", "Grape", "Orange"
    ARRAY.DELETE lv_lang$[]
    ARRAY.LOAD lv_lang$[], "Hungarian", "English", "Spanish", "French", "Dutch", "Deutsch", "Russian", "Turkish", "Latin"
  END IF

UNTIL r$ = "BACK"
GOTO MainPage

RefreshListview:
sb = act
IF sb=1
  GW_AMODIFY (lv, "content", lv_car$[])
ELSEIF sb=2 
  GW_AMODIFY (lv, "content", lv_fruit$[])
ELSEIF sb=3 
  GW_AMODIFY (lv, "content", lv_lang$[])
END IF
RETURN

!'==========================================================================================================

DemoInit:
IF demover$<>GW_VER$ THEN END "Mismatched versions: GW demo "+demover$+" Vs GW lib "+GW_VER$+CHR$(10)+"Please update your files..."

ARRAY.LOAD buzz[], 1, 100

!' Used for code syntax highlighting, see GW_CODE_HIGHLIGHT$ ()
ARRAY.LOAD BLA$[], "~", "INCLUDE", "END IF", "IF", "THEN", "ELSE", "GOTO", "GOSUB", "INT$" ~
  "LEFT$", "IS_IN", "POPUP", "ARRAY.LOAD", "ARRAY.DELETE", "ARRAY.SHUFFLE", "ARRAY.LENGTH" ~
  "PAUSE", "PRINT", "END", "DO", "UNTIL", "WHILE", "REPEAT", "RETURN", "SPLIT", "FOR", "NEXT" ~
  "LOWER$", "CHR$", "TIMER.SET", "TIMER.CLEAR", "TIMER.RESUME", "ONTIMER:", "VIBRATE", "TONE" ~
  "FTP.OPEN", "FTP.GET", "FTP.CLOSE", "LIST.CREATE", "LIST.ADD", "LIST.TOARRAY", "LIST.SIZE" ~
  "LIST.REMOVE"
ARRAY.LOAD RED$[], "+", ",", "(", ")", "!", "&", "|", "%", "[", "]"
DIM BLU$[GW_KEYWORD_NB()]
GW_POPULATE_KEYWORD_ARRAY(&BLU$[])

FN.DEF SelfExtract$ (label$)
  LF$ = CHR$(10) %' Line Feed
  DQ$ = CHR$(34) %' Double Quote
  BS$ = CHR$(92) %' Back Slash
  GRABFILE buf$, "../source/GW_demo.bas"
  i = IS_IN (LF$ + label$ + LF$, buf$)
  IF !i THEN FN.RTN ""
  i += LEN (LF$ + label$ + LF$)
  buf$ = MID$ (buf$, i)
  i = IS_IN (LF$ + "!'========", buf$)
  IF !i THEN FN.RTN ""
  buf$ = LEFT$ (buf$, i-1)
  SPLIT line$[], buf$, LF$
  ARRAY.LENGTH n, line$[]
  r$ = "* INCLUDE " + DQ$ + "GW.bas" + DQ$ + "\n"
  i=3 %' Start after "IF !page THEN" and the call to SelfExtract$ ()
  WHILE line$[i] <> "END IF" & IS_IN ("ELSE %' ", line$[i]) <> 1
    line$[i] = REPLACE$ (line$[i], BS$ + "n", " ") %' do not display \n
    line$[i] = REPLACE$ (line$[i], "<p style='color:red'>", "")
    line$[i] = REPLACE$ (line$[i], "</p>", "")
    IF REPLACE$(line$[i], " ", "") <> "" THEN r$ += "*" + line$[i] + "\n"
    i++
  REPEAT
  IF IS_IN ("ELSE %' ", line$[i]) = 1 THEN
    DO
      i++
    UNTIL line$[i] = "END IF"
  END IF
  FOR i=i+1 TO n
    line$[i] = REPLACE$ (line$[i], BS$ + "n", " ") %' do not display \n
    IF REPLACE$(line$[i], " ", "") <> "" THEN r$ += "*" + line$[i] + "\n"
  NEXT
  FN.RTN r$
FN.END

RETURN
