unit gossgui;

//-- Known Issues --------------------------------------------------------------
//
//1. Occasionally resizing the "Options" window causes the window to repaint at wrong location or main window beneath not to repaint
//
//------------------------------------------------------------------------------

interface
{$ifdef gui4} {$define gui3} {$define gamecore}{$endif}
{$ifdef gui3} {$define gui2} {$define net} {$define ipsec} {$endif}
{$ifdef gui2} {$define gui}  {$define jpeg} {$endif}
{$ifdef gui} {$define snd} {$endif}
{$ifdef con3} {$define con2} {$define net} {$define ipsec} {$endif}
{$ifdef con2} {$define jpeg} {$endif}
{$ifdef WIN64}{$define 64bit}{$endif}
{$ifdef fpc} {$mode delphi}{$define laz} {$define d3laz} {$undef d3} {$else} {$define d3} {$define d3laz} {$undef laz} {$endif}
uses gosswin2, gossroot, gossfast, gosstext, gossimg, gossio {$ifdef snd},gosssnd{$endif} ,gosswin {$ifdef gui},gossdat{$endif};
{$align on}{$iochecks on}{$O+}{$W-}{$U+}{$V+}{$B-}{$X+}{$T-}{$P+}{$H+}{$J-} { set critical compiler conditionals for proper compilation - 10aug2025 }
//## ==========================================================================================================================================================================================================================
//##
//## MIT License
//##
//## Copyright 2026 Blaiz Enterprises ( http://www.blaizenterprises.com )
//##
//## Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
//## files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
//## modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
//## is furnished to do so, subject to the following conditions:
//##
//## The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//##
//## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//## OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
//## LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OfF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//##
//## ==========================================================================================================================================================================================================================
//## Library.................. GUI (gossgui.pas)
//## Version.................. 4.00.33310 (+5929) (Build no reduced by 5611 due to WordCore (now TextCore) removed to dedicated unit gosstext.pas - 16feb2026)
//## Items.................... 46
//## Last Updated ............ 23apr2026, 22apr2026, 17apr2026, 15apr2026, 11apr2026, 07apr2026, 03apr2026,
//##                                      29mar2026, 26mar2026, 23mar2026, 18mar2026, 10mar2026, 06mar2026, 28feb2026, 26feb2026, 15feb2026, 01feb2026, 23jan2026, 13jan2026, 11jan2026, 07jan2026, 29dec2025, 27dec2025, 26dec2025, 17dec2025, 13dec2025, 12dec2025, 04dec2025, 01dec2025, 30nov2025, 28nov2025, 09nov2025, 06nov2025, 24oct2025, 08oct2025, 05oct2025, 29sep2025, 26sep2025, 18sep2025, 15sep2025, 09sep2025, 07sep2025, 28aug2025, 23aug2025, 15aug2025, 10aug2025, 08aug2025, 26jul2025, 24jul2025, 17jul2025, 14jul2025, 04jul2025, 16jun2025, 12jun2025, 09jun2025, 07jun2025, 03jun2025, 29may2025, 29apr2025, 13apr2025, 31mar2025, 24mar2025, 18feb2025, 28dec2024, 11dec2024, 29nov2024, 22nov2024, 15nov2024, 10nov2024, 04oct2024, 28aug2024, 01ug2024, 25jul2024, 28jun2024, 22mar2024, 09feb2024, 13dec2023, 25nov2023, 19may2023, 25feb2023, 30dec2022, 15nov2022, 06nov2022, 11oct2022, 28sep2022, 05jul2022, 29jun2022, 14jun2022, 31may2022, 14may2022, 30apr2022, 30mar2022, 27feb2022, 08feb2022, 31jan2021, 30dec2021,
//##                                      19dec2021, 30sep2021, 29aug2021, 09aug2021, 27jul2021, 07jul2021, 20jun2021, 02jun2021, 30may2021, 12may2021, 10may2021, 30apr2021, 19apr2021, 14apr2021, 03apr2021, 31mar2021, 20mar2021, 08mar2021, 26feb2021, 01feb2021, 28jan2021, 11oct2020, 25sep2020, 07sep2020, 26aug2020, 22aug2020, 28jul2020, 23may2020, 10may2020
//## Lines of Code............ 53,300+
//## Origin .................. Human generated and maintained
//##
//## main.pas ................ App specific code
//## gossdat.pas ............. App specific icons and help documents
//## gossfast.pas ............ FastDraw - rapid render graphic procs
//## gossgame.pas ............ GameCore - 2D game engine with integrated menu handler, xbox controller + mouse + keyboard support and window integration
//## gamefiles.pas ........... Built-in file(s) for GameCore (optional)
//## gossgui.pas ............. GUI management and controls
//## gossimg.pas ............. Multi-format graphic procs for 8, 24 and 32 bit images with IO support
//## gossio.pas .............. File IO and low level file/folder/disk/data format procs
//## gossjpg.pas ............. JPEG IO (read/write jpeg image data via third party libraries)
//## gossnet.pas ............. Networking - ip filtering, socket management etc
//## gossroot.pas ............ App startup and control (GUI, console and service)
//## gosssnd.pas ............. Sound, audio, midi and midi based chimes
//## gossteps.pas ............ System, Folder and App images
//## gosstext.pas ............ TextCore - non-GUI and GUI text engine for text boxes
//## gosswin.pas ............. Win32 api calls for 32 and 64 bit (static / api references disabled by default)
//## gosswin2.pas ............ Win32 api calls for 32 and 64 bit (dynamic - load as required with fallback failure handling and default value(s) support)
//## gosszip.pas ............. ZIP IO (read/write zip data via third party libraries)
//##
//## ==========================================================================================================================================================================================================================
//## | Name                   | Hierarchy         | Version   | Date        | Update history / brief description of function
//## |------------------------|-------------------|-----------|-------------|--------------------------------------------------------
//## | low level procs        | n/a               | 1.00.1890 | 03mar2026   | Collection of basic procedures and functions to support platform and it's controls etc - 14sep2025, 09sep2025, 05sep2025, 28aug2025, 23aug2025, 13mar2025, 11jan2025: ecomode now kicks in at 10min, 18dec2024, 17dec2024: low__font(), 11dec2024, 01dec2024: fixed font leak on Win98 for proc low__toLGF(), 26nov2024, 13dec2023, 19may2023, 11oct2022, 27sep2022, 14may2022, 21may2020
//## | scale__*               | family of procs   | 1.00.092  | 17dec2025   | System wide scaling support - 10dec2025, 05sep2025
//## | system__*              | family of procs   | 1.00.050  | 13may2025   | System management and Windows message handling
//## | sysback__*             | family of procs   | 1.00.148  | 17apr2026   | Background image management procs (integrates with tbackgroundmanager) - 07mar2026, 01mar2026, 19aug2025, 11apr2025, 18mar2025
//## | clip__*                | family of procs   | 1.00.382  | 03apr2026   | Clipboard copy/paste for text and images - 18mar2026, 01sep2025, 08aug2025: fixed "cf_png" bad value, 12jun2025, 01jun2025, 01jun2025, 29apr2025, 17mar2025, 17dec2024
//## | canvas__*              | family of procs   | 1.00.050  | 01dec2024   | TCanvas abstraction procs
//## | cols_*                 | color schemes     | 1.00.450  | 09mar2025   | Collection of built-in color schemes
//## | tbasicapp              | tobjectex         | 1.00.045  | 10dec2025   | Basic GUI app structure, complete with GUI (tbasicsystem) - 10aug2024, 30jul2021, 24jul2021
//## | trnd8                  | tobject           | 1.00.020  | 29nov2023   | Random stream generator
//## | tbackgroundmanager     | tobject           | 1.00.332  | 02mar2026   | Handles static, animated and dynamic background imagery for "tbasicsystem" - 07jan2026, 13dec2025, 03jun2025
//## | tbasicsystem           | tobject           | 1.00.6005 | 23apr2026   | GUI rendering and control system - 07apr2026, 03apr2026, 26mar2026, 10mar2026, 06mar2026, 01feb2026, 13jan2026, 29dec2025, 13dec2025, 01dec2025, 09nov2025, 08oct2025, 17sep2025, 09sep2025, 31aug2025, 27aug2025, 17aug2025, 10aug2025, 26jul2025, 04jul2025, 28may2025, 15may2025, 21apr2025, 18feb2025, 04feb2025: auto switches between using buffer 1+2 or only buffer 1 for optimal rendering, 28jan2025, 28nov2024: supports background exclusion areas, 21nov2024: background pauses for window resize/reposition, 18nov2024, 26jul2024m 28jun2024: fixed part paint, 09dec2023, 19nov2023, 12feb2023, 20may2022, 27mar2022: updated onaccept proc for deep drag and drop support, 26feb2022, Fixed ibuffer.w/h mismatch with mustmask - 21sep2021, 29aug2021, 28jul2021, 07jul2021, 18jun2021, 29may2021, 14apr2021, 03apr2021, 08mar2021, 25feb2021, 11oct2020, 28jul2020, 20may2020
//## | tbasiccontrol          | tobject           | 1.00.1270 | 29mar2026   | Flicker free base control with built-in _onnotify/_ontimer and _onpaint procs for easy customisation - 23mar2026, 25feb2026, 26dec2025, 04dec2025, 30nov2025, 05sep2025, 19jul2025, 03jul2025, 24may2025, 19apr2025, 31mar2025, 06jan2025, 25dec2024, 28nov2024, 19aug2024, 28jun2024: fixed ldso4 leak, 02dec2023: ldso4 cliparea handling, 17nov2023, 12jan2022, 09sep2021, 27mar2021, 11oct2020, 20may2020, 12apr2020, 14mar2020
//## | tbasicimgview          | tbasiccontrol     | 1.00.755  | 03apr2026   | Animated image viewer - 18feb2025, 30jan2025, 26dec2024
//## | tbasichelp             | tbasiccontrol     | 1.00.100  | 16may2025   | Realtime help scroller - 02aug2024, 12apr2020, 25mar2020
//## | tbasicnav              | tbasiccontrol     | 1.00.1258 | 18sep2025   | Multi-purpose favorites/files/folders/open/save navigation control - 04sep2025, 05jun2025, 24jan2025, 28dec2024, 01dec2024: removed " - " from preview label,22nov2024, 20aug2024, 11feb2023, 11oct2022, 27sep2022, 28jun2022, 22may2022, 23mar2022, 12jan2022, 09aug2021, 28jul2021, 18jun2021, 06apr2021, 25mar2021, 22sep2020
//## | tbasicbwp              | tbasiccontrol     | 1.00.700  | 17feb2026   | GUI front-end for TextCore -> multi-format text box -> supports txt, bwd, bwp, rtf and dic text documents - 23jan2026, 27aug2025, 20apr2025, 31mar2025, 17dec2024, 09dec2024: keyboard shortcut removed for "copy as plain text", 28aug2024, 18feb2023, 04oct2022, 24sep2022, 18jun2022, 29may2021, 12mar2021
//## | tbwpbar                | tbasiccontrol     | 1.00.160  | 01mar2026   | Font name / size / color and style toolbar for tbasicbwp text box - 15nov2023
//## | tbasiccolor            | tbasiccontrol     | 1.00.365  | 24oct2025   | Color picker with optional shade ranges - 03feb2025, 09dec2024: xshadecolor24 proc for when low__capcolor fails, 09dec2024: tweaked color capture, 01mar2021
//## | tbasiccolormatrix      | tbasiccontrol     | 1.00.098  | 02feb2025   | Realtime drawn color matrix - 02feb2025: direct color grab within color matrix, 09dec2024, 09dec2024: tweaked color capture, 2021
//## | tbasiccolormixer       | tbasiccontrol     | 1.00.030  | 11dec2025   | Automatic color mixer for color dialog -> generate shades and mixes of orginal and current colors - 05sep2025
//## | tbasicstatus           | tbasiccontrol     | 1.00.143  | 26aug2024   | Simple statusbar - 26aug2024: ofast, 29dec2021, 07jul2021, 02jun2021, 05oct2020, 12apr2020, 15mar2020
//## | tbasicgradient         | tbasiccontrol     | 1.00.022  | 20may2025   | Window transistion gradient for soft edges such as bottom of toolbars on GUI etc - 20aug2024
//## | tmenutitle             | tbasiccontrol     | 1.00.020  | 24may2025   | Modern title that mimics "tbasicmenu.title" in size, coloring and position
//## | tbasictitle            | tbasiccontrol     | 1.00.060  | 04sep2025   | Standard title -> supports both small and large modes -> exactly matches tbasictoolbar.maketitle() display output - 11may2025, 08apr2025, 12jan2025, 19nov2023, 24feb2021, 11oct2020
//## | tbasicbreak            | tbasiccontrol     | 1.00.012  | 09mar2025   | 2021
//## | tsimpleint             | tbasiccontrol     | 1.00.142  | 03mar2026   | Fast and responsive slide bar -> compact and easy to use, simpler version - 09sep2025, 05sep2025, 15aug2025, 11jul2025, 06jun2025
//## | tbasicset              | tbasiccontrol     | 1.00.308  | 29mar2026   | Upto 32 "yes/no" slots with boolean in/out for each slot -> compact multiple option chooser control - 03mar2026, 08oct2025, 05sep2025, 03jun2025, 16may2025, 25dec2022, 27mar2022, 30mar2021, 18aug2020
//## | tbasicsel              | tbasiccontrol     | 1.00.196  | 29mar2026   | Upto 32 "choose" positions with a value range of 0..31 -> each choice has help/caption for selecting a value range for a specific setting e.g. Text Feather 0=off, 1=mild, 2=strong - 03mar2026, 13sep2025, 09sep2025, 05sep2025, 21aug2025, 03jun2025,16may2025, 25dec2022, 18sep2022, 27mar2022, 29aug2021, 27mar2021, 19aug2020
//## | tbasicimageexts        | tbasiccontrol     | 1.00.025  | 21dec2024   | An action list for specific image formats -> to work with dialog windows
//## | tbasictea              | tbasiccontrol     | 1.00.280  | 23mar2026   | Mini TEA image view and adjustment editor - 03mar2026, 11dec2025, 12jan2025, 2021
//## | tbasiccolors           | tbasiccontrol     | 1.00.552  | 11dec2025   | Multi-color picker with system and static colors support - 24may2025, 09mar2025, 15mar2022, 19mar2021
//## | tbasictoolbar          | tbasiccontrol     | 1.00.3390 | 20mar2026   | Toolbar with "title + links" support - 10dec2025, 28nov2025, 04sep2025, 20jul2025, 09jun2025, 26may2025, 24mar2025, 28dec2024, 27dec2024: upgraded to support Window Head functions, 21jul2024, 09dec2023, 03nov2023, 26sep2022, 28jun2022, 25mar2022, 19dec2021, 21sep2021, 07jul2021, 30may2021, 27mar2021, 21feb2021, 11oct2020, 22sep2020, 23apr2020, 29mar2020
//## | tbasicmenu             | tbasiccontrol     | 1.00.2930 | 15apr2026   | Menu handler - 02apr2026, 21mar2026, 26feb2026, 12dec2025, 04dec2025, 04sep2025, 28aug2025, 18aug2025, 03jul2025, 16may2025, 21dec2024, 17nov2024, 04oct2024, 20jul2024: soft back shade for title items, 28sep2022, 20mar2022, 26feb2022, 08jun2021, 27mar2021, 11oct2020, 13apr2020
//## | tbasicscrollbar        | tbasiccontrol     | 1.00.490  | 12dec2025   | Streamlined scrollbar with full and partial keyboard/wheel handling -> can pass critical handling to parent control for consistent operation - 13sep2025, 04oct2022, 03mar2022, 08feb2022, 25jul2021, 13apr2020
//## | tbasicscroll           | tbasiccontrol     | 1.00.600  | 03apr2026   | Vertical scrollbox - 13jan2026, 19jul2025, 05jun2025, 14may2025, 17mar2025, 12jan2024, 17dec2024, 04oct2022, 02jun2021, 29may2021, 08mar2021, 25feb2021, 14aug2020, 05apr2020
//## | tbasicsetcolor         | tbasicscroll      | 1.00.742  | 18sep2025   | Color picker and support for "popcolor" dlg - 05sep2025, 28may2025, 01feb2025, 28jul2024: head background style, 01mar2021: created
//## | tbasiccols             | tbasiccontrol     | 1.00.485  | 13jan2026   | Multi-column handler - supports upto 10 columns - 27aug2025, 14jul2025, 12jul2025, 16may2025, 09mar2025, 03feb205: remainder "units" support like html5, 17nov2024, 07mar2022, 26feb2021
//## | tbasiccells            | tbasiccontrol     | 1.00.100  |      2022   | Horizontal cell viewer / editor
//## | tbasicsplash           | tbasicscroll      | 1.00.642  | 18mar2026   | System splash screen and about window - 28feb2026, 13jan2026, 11dec2025, 13sep2025, 14jul2025, 08apr2025, 23mar2025, 09dec2024, 04dec2024: reworked for one mode with background mask support, 15nov2025, 20jul2024: fallback to icon art if no splash image, style=2=IconArt, 24feb2022, 21sep2021, 18jun2021, 05oct2020
//## | tbasicedit             | tbasiccontrol     | 1.00.1180 | 03mar2026   | Edit box, supports makers for edit/password/drop/dropstatic/progress -> simulates 5 controls in one with many useful features and functions - 11dec2025, 28nov2025, 20may2025, 20apr2025, 09mar2025, 01aug2024, 03mar2022, 31mar2021, 07apr2020
//## | tbasicjump             | tbasiccontrol     | 1.00.232  | 03mar2026   | Realtime jumpto panel for millisecond precision position jumping for song/midi playback - 07jan2026, 13dec2025, 24oct2025, 16sep2025, 07sep2025, 27aug2025, 25jan2025, 06mar2022, 21feb2022, 22mar2021, 10mar2021
//## | tmainhelp              | tbasicscroll      | 1.00.267  | 26mar2026   | Built-in help display panel with BWP file support - 24apr2025, 25dec2024, 27apr2022, 30mar2022, 08jan2022, 22sep2021, 24jul2021, 29may2021, 26aug2020
//## | tplaylist              | tobjectex         | 1.00.370  | 19aug2025   | Integrated m3u playlist manager - syncs with list for seamless playlist handling - 20mar2022
//## | plus_* support         | family of procs   | 1.00.050  | 27jun2022   | Collection of procs for swift multi-tab "PLUS" version support
//## ==========================================================================================================================================================================================================================
//## Performance Note:
//##
//## The runtime compiler options "Range Checking" and "Overflow Checking", when enabled under Delphi 3
//## (Project > Options > Complier > Runtime Errors) slow down graphics calculations by about 50%,
//## causing ~2x more CPU to be consumed.  For optimal performance, these options should be disabled
//## when compiling.
//## ==========================================================================================================================================================================================================================


const
   static_lineheight36     =36;
   gui__scalemin           =0.60;
   gui__scalemax           =16.0;
   gui__minResizeBorder    =6;//6px at 96 dpi - for resizing a window with a thin frame or one without a frame at all - 12dec2025

   
   //system font indexs
   font__root              =0;
   font__fn                =1;
   font__fb                =2;
   font__fs                =3;
   font__fsb               =4;
   font__fs2               =5;
   font__funknown          =6;
   font__syslast           =6;
   font__userstart         =font__syslast+1;


   //system references
   WM_USER              =$0400;//anything below this is reserved
   WM_MULTIMEDIA_TIMER  =WM_USER + 127;

   //system cursors
   scNone         =0;
   scDefault      =1;
   scArrow        =2;

   //special code2 internally processed links
   scPage         ='page:';//show a page
   scDlg          ='dlg:';//set a dlg reply
   scOptions      ='sys:options';//14aug2020
   scHelp         ='sys:help';
   scSplash       ='sys:splash';//2aug2020
   scAbout        ='sys:about';
   scMixer        ='sys:mixer';//07mar2022
   scMax          ='sys:max';//15mar2022
   scOntop        ='sys:ontop';//15mar2022
   scFindpop      ='sys:find.pop';//18feb2023
   scFind         ='sys:find';//18feb2023
   scPlus         ='plus~';//used to signal a plus orientated page control
   scVisitPortal  ='visit.portal';
   scVisitProgram ='visit.program';
   //own list -> special mode
   omfree         =maxword;
   //window modes
   wmControl      =0;//control is not a window
   wmFullwin      =1;//control is a window that "must" occupy entire screen always (e.g. app root form like Clic) and sits at bottom of window stack
   wmWindow       =2;//control is a window -> e.g. normal window or a tool window that sits above wmFullwin but below wmOntop
   wmOntop        =3;//control is an ontop window -> e.g. window sits above wmWindow but below wmDialog
   wmDialog       =4;//control is a dialog window -> e.g. sits above all other window types
   wmMax          =4;

   //corner styles - 01apr2026
   corNone        =0;//same as square - 29aug2020
   corRound       =1;
   corSlight      =2;
   corMax         =2;

   //corner modes
   rmNil          =-1;
   rmAll          =0;
   rmTopOnly      =1;//only top corners (top-left and top-right)
   rmBotOnly      =2;//only bottom corners (bottom-left and bottom-right)
   rmNone         =3;
   rmMax          =3;
   
   //borderstyles
   bsInternal     =0;
   bsSystem100    =1;
   bsSystem50     =2;
   bsSystem20     =3;
   bsMax          =4;
   //-- WordCore Consts --------------------------------------------------------
   //.word wrap styles -> basicbwp and low__wordcore
   wwsNone        =0;
   wwsWindow      =1;
   wwsPage        =2;
   wwsPage2       =3;
   wwsMax         =3;
   //.multi-undo styles -> low__wordcore - 02jul2022
   musNone        =0;
   musDelL        =1;
   musDelR        =2;
   musIns         =3;
   musSel         =4;
   musSelKeep     =5;
   musRangeKeep   =6;//datastream size remains same, byte from1..xlen is replaced
   musRecovered   =7;
   musInsImg      =8;
   musMax         =8;
   //.musRecovered - actions
   muaRep         =0;
   muaAdd         =1;
   muaSub         =2;
   muaMax         =2;
   //.align styles
   wcaLeft        =0;
   wcaCenter      =1;
   wcaRight       =2;
   wcaMax         =2;

   //tbasicccols -> styles
   bcLefttoright       =0;//was vertical
   bcRighttoleft       =1;//was vertical2
   bcToptobottom       =2;//was horizontal
   bcBottomtotop       =3;//was horizontal2
   bcMax               =3;

   //tbasicmenu -> menu styles
   lsmenu              =0;
   lslist              =1;
   lspanel             =2;//18aug2025
   lsmany              =3;
   lsmax               =3;

   //chime styles (storage)
   chmsTitle                    =0;
   chmsStandard                 =1;//Melody + Dong OR Dong only
   chmsBells                    =2;//Ships Bells OR Ships Bells - British Royal
   chmsSonnerie                 =3;//Grande Sonnerie OR Petite Sonnerie

   //wordcore -> char style codes
   wc_n                =0;//no style
   wc_t                =1;//text
   wc_i                =2;//image

   //tbasicimgview.fillstyle
   vfsDefault           =0;
   vfsScale             =0;
   vfsScreen            =1;
   vfsCrop              =2;
   vfsFit               =3;
   vfsEcho              =4;
   vfsEcho2             =5;
   vfsMax               =5;

   //background manager nameids
   bkmStrength          =0;
   bkmColorise          =1;
   bkmSpeed             =2;
   bkmHstep             =3;
   bkmVstep             =4;
   bkmFstep             =5;
   bkmHwobble           =6;
   bkmVwobble           =7;
   bkmFwobble           =8;
   bkmCrate             =9;//change rate - 02mar2026
   bkmMax               =9;

   //tbasictoolbar -> special index items
   tsiStart             =0;
   tsiFinish            =6;
   tsiUser              =7;

   tsiAppicon           =0;
   tsiAppcap            =1;
   tsiMenu              =2;
   tsiFull              =3;
   tsiMin               =4;
   tsiMax               =5;
   tsiClose             =6;
   //.special text values
   tstSep               ='-';
   tstNewline           ='+';
   tstNewpartline       ='~';

   //special maker codes -> used by controls to detect what type of modified control they are running -> used when required - 23mar2022
   made_none           =0;
   made_wavevol        =1;
   made_midivol        =2;
   made_miditranspose  =3;
   
   //memory access and memory mapped file access -------------------------------
   PAGE_NOACCESS    = 1;
   PAGE_READONLY    = 2;
   PAGE_READWRITE   = 4;
   PAGE_WRITECOPY   = 8;

   FILE_MAP_COPY     = 1;
   FILE_MAP_WRITE    = 2;
   FILE_MAP_READ     = 4;
   FILE_MAP_READWRITE=FILE_MAP_COPY or FILE_MAP_WRITE or FILE_MAP_READ;


//managed states
   msFree      =0;
   msHold      =1;
   msQueued    =2;
   msWorking   =3;
   msFinished  =4;
//playback modes
   mmOnce              =0;
   mmRepeatOne         =1;
   mmRepeatAll         =2;
   mmAllOnce           =3;
   mmRandom            =4;
   mmMax               =4;


//system cursors - 27may2025, 29aug2021 ----------------------------------------
//.128x128 high-res cursor with feathering
cur_template_arrow128
:array[0..1932] of byte=(
120,1,236,221,47,86,100,71,20,6,240,206,46,178,132,89,193,44,32,62,50,11,153,29,100,3,217,2,2,129,64,32,16,8,68,206,28,4,2,17,129,64,32,16,8,68,4,2,129,64,48,249,120,23,238,191,170,87,239,117,247,163,167,243,222,87,135,97,170,154,166,105,126,245,245,173,251,96,114,242,219,239,95,191,175,186,241,21,239,191,224,207,159,239,127,126,89,253,138,25,198,247,238,125,122,247,99,181,226,27,5,40,64,1,10,80,128,2,20,160,0,5,40,64,1,10,80,128,2,20,160,0,5,40,64,1,10,80,128,2,20,160,0,5,40,64,1,10,80,128,2,20,160,0,5,40,64,1,10,80,128,2,20,160,0,5,40,64,1,10,80,128,2,20,160,0,5,40,64,1,10,44,65,224,126,181,146,183,37,124,179,123,248,61,94,118,255,129,223,95,171,21,38,216,136,61,124,134,51,126,74,0,135,188,14,238,194,142,247,90,194,175,254,50,225,46,52,118,97,194,42,145,194,207,93,104,176,235,135,160,116,60,81,161,174,134,159,187,160,212,213,137,248,108,191,5,237,240,115,23,170,248,184,81,199,150,91,144,195,127,127,143,29,105,15,158,11,222,31,86,27,111,65,37,252,15,15,15,255,118,163,189,7,93,
191,52,225,25,212,23,179,189,189,61,241,108,182,5,149,240,139,255,227,227,227,211,211,211,243,243,115,250,50,197,114,179,175,187,183,170,227,159,88,33,177,246,171,160,55,252,192,87,255,151,151,151,215,215,215,242,139,185,91,176,137,227,159,246,108,238,233,0,108,186,86,26,135,195,47,248,240,199,192,220,190,78,152,209,223,115,140,220,130,86,248,81,121,164,248,168,63,38,168,69,181,114,132,179,24,15,53,155,84,143,255,70,188,121,154,143,217,130,181,195,15,124,108,74,250,74,221,15,139,198,63,231,57,221,179,144,8,55,180,183,96,147,240,215,240,23,27,126,4,105,112,52,182,32,135,31,61,79,106,123,180,242,72,229,103,248,139,26,59,232,143,59,244,109,1,110,15,35,225,67,91,253,165,242,51,252,109,255,131,131,131,0,106,139,114,11,114,241,17,124,92,114,165,158,83,146,223,239,191,204,182,71,143,48,35,198,236,240,240,240,232,232,40,220,100,139,180,5,149,226,147,240,25,254,34,237,202,174,19,243,85,255,227,227,92,88,62,238,164,91,80,15,127,119,189,245,126,193,155,240,89,249,123,246,226,131,182,251,
27,225,7,62,198,201,201,73,248,128,45,100,11,134,195,255,118,173,213,13,173,60,216,29,123,152,183,217,146,219,158,122,254,197,31,248,167,167,167,103,103,103,145,75,87,112,251,166,11,76,252,177,91,189,224,194,141,24,254,83,186,249,194,43,191,108,65,80,145,228,171,255,249,249,121,248,112,207,194,251,251,158,7,241,103,248,123,202,78,61,255,226,47,225,7,254,223,221,232,81,127,191,217,227,35,228,222,95,241,25,254,254,93,8,186,72,190,15,63,248,47,46,46,46,47,115,181,247,159,227,253,61,62,195,223,111,174,225,199,36,140,132,175,254,87,87,87,225,126,31,139,132,239,253,53,252,197,177,139,79,102,229,215,45,248,160,236,254,70,229,241,197,71,194,15,252,127,186,17,238,218,45,228,55,92,237,11,174,194,159,109,143,226,231,252,39,124,239,127,125,125,125,115,115,227,183,32,133,31,129,199,24,234,57,241,0,12,127,175,63,122,78,12,57,121,19,190,248,223,222,222,234,22,200,213,110,53,252,40,68,24,56,118,139,240,255,209,181,253,184,136,216,254,13,251,56,131,95,25,40,231,219,36,225,227,228,149,226,163,
248,119,119,119,242,15,27,202,240,75,242,155,199,110,248,90,83,44,230,230,143,228,87,195,143,202,131,129,240,139,191,199,111,244,156,69,248,167,32,183,199,144,43,113,255,90,254,63,206,237,251,193,44,225,87,195,15,124,239,143,58,163,101,127,135,225,159,7,126,62,127,229,130,43,85,126,73,254,62,133,127,54,248,21,127,197,223,215,240,207,9,191,229,143,150,95,143,221,106,248,187,30,199,138,15,170,144,246,60,168,252,232,142,80,166,112,88,227,200,192,167,227,69,132,71,195,192,195,98,103,113,178,99,163,241,114,67,197,235,122,174,51,180,190,184,250,195,15,64,240,51,64,252,26,34,148,69,91,204,12,63,251,107,248,229,130,11,92,229,177,155,126,201,162,13,191,247,247,248,222,223,227,123,127,143,63,250,23,64,120,242,51,120,179,108,97,230,253,61,126,217,246,200,177,171,39,111,194,247,254,26,126,217,211,50,252,192,247,254,225,9,217,98,126,201,151,240,216,119,136,153,111,248,189,63,202,136,246,60,131,23,92,9,223,251,123,124,45,62,11,198,207,245,199,251,251,202,227,253,83,195,159,122,78,193,47,43,
191,84,30,239,47,149,95,240,165,242,135,40,216,98,174,201,175,228,31,62,128,146,228,123,127,13,63,240,147,191,86,30,220,94,61,118,229,228,245,149,95,146,239,253,113,236,154,119,152,205,27,63,231,223,251,251,158,199,251,55,46,184,180,242,164,182,103,48,252,129,220,22,179,199,207,254,26,126,224,123,127,192,106,217,247,254,147,132,223,188,195,108,9,248,45,127,237,121,38,9,63,78,22,140,178,231,12,228,182,88,8,126,246,215,158,103,173,240,227,165,129,161,197,199,55,252,120,192,178,242,235,5,151,121,135,217,114,240,123,253,53,252,80,197,0,111,121,236,106,241,73,248,222,223,227,167,240,7,114,91,44,10,63,251,107,207,227,253,61,62,204,245,130,87,127,218,32,123,84,237,57,189,191,111,248,205,59,204,150,134,223,235,239,27,126,239,239,241,189,191,199,71,237,170,246,156,234,31,200,109,177,64,252,236,175,101,223,251,167,202,179,229,5,151,121,135,217,50,241,123,253,125,207,147,252,181,236,111,112,193,21,200,109,177,88,252,236,175,101,223,251,251,134,191,26,126,188,88,48,170,199,174,239,57,205,
59,204,150,140,223,235,239,123,30,239,175,225,199,161,128,129,187,249,202,143,178,95,173,252,248,81,67,32,183,197,194,241,179,63,98,44,201,247,254,218,243,108,28,126,243,14,51,226,247,250,35,219,82,246,215,10,63,174,182,202,11,174,64,110,11,226,3,63,251,55,194,143,87,1,70,181,231,172,86,126,92,109,97,152,119,152,17,95,240,235,254,26,126,49,247,61,191,246,60,101,229,151,228,251,11,174,64,110,11,226,43,126,246,151,178,239,253,61,126,53,252,184,100,192,40,143,93,243,14,51,226,123,252,186,127,106,248,171,199,110,106,123,180,236,203,111,184,2,185,45,136,159,240,179,191,36,63,249,107,217,215,226,147,240,83,248,205,59,204,136,95,226,215,253,125,207,83,13,127,119,189,85,191,224,10,228,182,32,126,21,63,251,75,242,189,191,134,31,47,13,140,234,177,171,197,199,188,195,140,248,125,248,117,127,152,235,177,235,253,21,191,250,211,134,64,110,11,226,55,240,179,63,146,191,89,248,205,59,204,136,223,198,175,248,15,134,31,87,91,233,130,43,144,219,130,248,131,248,217,31,248,222,31,175,5,237,121,180,
248,16,127,210,127,119,106,121,197,44,225,123,127,223,115,234,5,87,248,100,91,48,249,99,146,47,247,49,53,204,228,216,173,246,156,222,95,26,254,240,153,182,32,254,120,252,92,127,180,237,145,228,107,241,73,248,240,55,239,48,35,254,90,248,3,254,190,225,247,61,103,32,183,5,241,215,197,175,248,227,8,208,178,239,253,245,216,53,239,48,35,254,6,248,217,255,173,251,113,254,190,231,17,255,64,110,11,226,111,134,95,241,111,132,223,188,195,140,248,27,227,183,252,83,248,3,185,45,136,191,13,126,246,215,240,3,223,251,155,119,152,17,127,75,252,150,191,246,156,129,220,22,196,223,30,63,251,251,134,95,252,205,59,204,136,63,9,126,203,31,13,127,32,183,5,241,167,194,207,254,190,225,55,239,48,35,254,132,248,189,254,129,220,22,196,159,22,63,251,75,207,99,222,97,70,252,201,241,43,254,129,220,22,196,255,12,252,236,111,222,97,70,252,79,194,31,227,79,252,207,195,31,244,39,254,167,226,183,253,137,255,217,248,13,127,226,239,0,191,207,159,248,187,193,175,250,19,127,103,248,165,63,241,119,137,159,252,137,191,
99,124,239,79,252,221,227,171,63,241,127,10,190,248,243,127,136,240,179,240,127,252,7,0,0,255,255,3,0,213,155,125,145);

//.32x32 low-res cursor without feathering for Windows 95/98
cur_template_arrow32
:array[0..509] of byte=(
120,1,236,148,57,139,34,81,20,133,111,231,211,208,161,131,73,119,54,48,121,199,210,73,69,77,255,5,67,127,132,6,134,130,153,96,166,32,26,8,130,224,146,104,162,129,168,184,131,251,142,226,134,251,190,195,204,121,46,48,216,193,160,93,149,52,22,175,30,245,168,170,239,158,119,238,189,239,237,253,245,7,29,174,87,204,191,112,63,159,238,7,18,225,9,215,233,253,113,113,158,255,16,221,199,221,129,187,3,223,201,1,52,183,112,219,33,137,68,194,223,233,241,243,147,84,10,135,195,153,76,70,165,82,241,17,5,140,127,67,144,92,46,31,12,6,187,221,174,221,110,139,68,191,63,69,191,214,55,146,201,100,143,143,207,103,14,69,163,209,229,114,9,190,94,175,63,232,191,22,120,241,61,105,181,90,141,70,243,244,244,2,154,66,161,24,141,70,251,253,30,91,224,184,143,115,208,139,95,174,90,146,78,167,243,120,60,38,147,73,44,22,199,98,177,213,106,181,221,110,109,54,27,31,226,161,132,64,14,4,2,233,116,58,24,12,78,38,19,136,239,247,251,28,199,29,248,23,211,85,202,143,31,147,197,98,137,199,227,229,114,185,215,235,173,215,
235,205,102,147,203,229,12,6,3,124,83,171,213,74,165,82,42,149,18,61,220,234,21,217,237,246,108,54,219,108,54,103,179,25,196,79,167,211,70,163,129,250,196,118,220,110,55,220,59,236,225,6,229,39,253,46,151,171,82,169,192,19,216,14,253,221,110,183,84,42,33,17,94,175,215,104,52,126,13,142,16,4,78,171,213,154,207,231,168,201,241,120,92,175,215,83,169,148,223,239,55,155,205,95,134,51,62,146,59,28,14,1,71,217,119,58,157,66,161,16,137,68,172,86,43,31,112,198,135,21,199,134,66,229,215,106,181,100,50,233,116,58,121,130,51,62,42,19,105,93,44,22,56,16,242,249,60,210,193,31,156,241,139,197,34,50,139,134,173,86,171,104,52,94,225,140,15,44,42,19,245,233,243,249,248,134,51,62,18,138,206,10,133,66,2,192,25,31,9,77,36,18,194,192,25,223,225,112,8,6,103,124,33,225,224,223,124,112,225,223,255,143,191,0,0,0,255,255,3,0,154,214,103,8);

type
   //.system support
   tbasicbwp       =class;
   //.GUI support
   tbasicsystem    =class;
   tbasiccontrol   =class;
   tbasicdebug     =class;
   tbasicimageexts =class;
   tbasicimgview   =class;
   tbasicscroll    =class;
   tbasiccols      =class;
   tbasicsplash    =class;
   tbasichelp      =class;
   tbasiccolor     =class;
   tmenutitle      =class;
   tbasictitle     =class;
   tbasicbreak     =class;
   tbasicedit      =class;
   tbasictoolbar   =class;
   tbasicstatus    =class;
   tbasicmenu      =class;
   tbasicscrollbar =class;
   tsimpleint      =class;
   tbasicset       =class;
   tbasicsel       =class;
   tbasiccolors    =class;
   tbasicnav       =class;
   tbasiccolormatrix=class;
   tbasicsetcolor  =class;
   tbasicjump      =class;
   tbasictea       =class;
   tmainhelp       =class;
   tbwpbar         =class;
   tbasicgradient  =class;
   tbasiccolormixer=class;//05sep2025

   //.events
   tsystemnotify                 =function(sender:tobject):boolean of object;
   tsystemkeyevent               =procedure(sender:tobject;xrawkey:longint;xdown:boolean) of object;
   tsystemmouseevent             =procedure(sender:tobject;xmode,xbuttonstyle,mx,my,mw,mh:longint) of object;
   tlongintevent                 =procedure(sender:tobject;xval:longint) of object;
   tlongintgetevent              =procedure(sender:tobject;var xval:longint) of object;
   tsimplestringevent            =procedure(sender:tobject;var xval:string) of object;//28feb2022
   tsimplestringeventb           =procedure(sender:tobject;xval:string) of object;//19jun2022
   tbasicmenu_getitem            =function(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean of object;//03oct2024, 24feb2021
   tbasicmenu_getitem2           =function(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor,xtepcolor2:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean of object;//03oct2024, 24feb2021
   tbasicint_onreadwriteval      =procedure(sender:tobject;var xval:longint;xwrite:boolean) of object;
   ttoolbarevent2                =function(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean of object;//15mar2021
   tstr8event                    =procedure(sender:tobject;xval:tstr8) of object;
   tmenufillevent                =procedure(sender:tobject;xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string) of object;//19mar2021, 15mar2021
   tonacceptfilesevent           =procedure(sender:tobject;var msg:twinmessage) of object;
   tonacceptevent                =function(sender:tobject;xfolder,xfilename:string;xindex,xcount:longint):boolean of object;
   tonfindheight                 =function(sender:tobject;xclientwidth:longint):longint of object;
   tnavmodifyitem                =procedure(sender:tobject;var xtab:string;var xindent,xstyle,xtepcolor,xtep:longint;var xcaption,xcaplabel:string;var xbold:boolean;xfav:boolean) of object;//03oct2024
   tgetobjectevent               =procedure(sender:tobject;xindex:longint;var xval:tobject) of object;//14jul2025


   //.system coloring record
   pvirtualinfo=^tvirtualinfo;
   tvirtualinfo=record
    //system information - read-only -------------------------------------------
    frame         :longint;//main form border - 18apr2020
    frame2        :longint;
    framefindcol  :longint;//works with winLdr - 23feb202
    framefindcol2 :longint;//works with winLdr - 23feb202
    border        :longint;
    background    :longint;
    highlight     :longint;
    hover         :longint;
    disable       :longint;//used for background
    disableborder :longint;//used for border
    disablefont   :longint;
    font          :longint;
    fonthighlight :longint;
    fontname      :string;//unicode in Delph 10
    fontsize      :longint;
    //.system font index (100%) - normal
    fn            :longint;
    fb            :longint;
    ofn           :tresfont;
    rfn           :tresslot;
    ofb           :tresfont;
    rfb           :tresslot;
    oft           :tresfont;
    rft           :tresslot;
    oft2          :tresfont;
    rft2          :tresslot;

    //.system font index (80%) - small
    ofs           :tresfont;
    rfs           :tresslot;
    ofsb          :tresfont;
    rfsb          :tresslot;
    ofs2          :tresfont;
    rfs2          :tresslot;
    fs            :longint;
    fsb           :longint;
    fs2           :longint;

    //.font heights (line height)
    ftH           :longint;
    ftH2          :longint;
    fnH           :longint;
    fbH           :longint;
    fnbH          :longint;
    fsH           :longint;
    fsbH          :longint;
    fsH2          :longint;

    //.font sizes - 04sep2025
    ftFS          :longint;
    ftFS2         :longint;
    fnFS          :longint;
    fbFS          :longint;
    fnbFS         :longint;
    fsFS          :longint;
    fsbFS         :longint;
    fsFS2         :longint;

    //.colors
    mfont             :longint;
    mback             :longint;
    mrow              :longint;
    mhint             :longint;
    mhover            :longint;
    mhover2           :longint;
    mcolhover         :longint;
    mcolhover2        :tpoint;//x=background, y=foreground
    mcolfont          :longint;
    mline             :longint;
    mline2            :longint;
    msep              :longint;
    mborder           :longint;
    mmustborder       :longint;

    end;

   pclientinfo=^tclientinfo;
   tclientinfo=record
    info              :pvirtualinfo;
    fn                :longint;
    fb                :longint;
    fs                :longint;
    fsb               :longint;
    fs2               :longint;

    ofn               :tresfont;//20feb2026
    oft               :tresfont;
    oft2              :tresfont;
    ofb               :tresfont;
    ofs               :tresfont;
    ofsb              :tresfont;
    ofs2              :tresfont;

    rfn               :tresslot;//20feb2026
    rft               :tresslot;
    rft2              :tresslot;
    rfb               :tresslot;
    rfs               :tresslot;
    rfsb              :tresslot;
    rfs2              :tresslot;

    fnH               :longint;
    ftH               :longint;
    ftH2              :longint;
    fbH               :longint;
    fnbH              :longint;
    fsH               :longint;
    fsbH              :longint;
    fsH2              :longint;

    fnFS              :longint;
    ftFS              :longint;
    ftFS2             :longint;
    fbFS              :longint;
    fnbFS             :longint;
    fsFS              :longint;
    fsbFS             :longint;
    fsFS2             :longint;

    cs                :twinrect;//client space (full area)
    ci                :twinrect;//client inner space (usable space of client, excludes frame)
    cw                :longint;//client width
    ch                :longint;//client height
    bs                :longint;//border size
    n                 :boolean;//normal
    r                 :boolean;//round
    roundframe        :boolean;
    roundstyle        :longint;
    f                 :longint;//feather
    e                 :boolean;//enabled
    sparkle           :longint;
    zoom              :longint;//zoom
    font              :longint;
    back              :longint;
    row               :longint;
    hint              :longint;
    hover             :longint;
    hover2            :longint;
    colhover          :longint;
    colhover2         :tpoint;
    colfont           :longint;
    line              :longint;
    line2             :longint;
    sep               :longint;
    border            :longint;
    mustborder        :longint;
    end;

   pvirtualmorecolors=^tvirtualmorecolors;
   tvirtualmorecolors=record
    frame         :longint;
    title         :longint;
    standard      :longint;
    allinone      :longint;
    dark_light    :longint;
    light_dark    :longint;
    end;


{tfastbufferinfo for use with tbasicsystem/background tile render}
   pfastbufferbytelist=^tfastbufferbytelist;
   tfastbufferbytelist=array[0..255] of byte;

   pfastbufferinfo=^tfastbufferinfo;
   tfastbufferinfo=packed record

    //.info for buffer2 fast draw procs
    initCode        :longint32;
    drawProc        :longint32;

    w               :longint32;//width of target buffer
    h               :longint32;//height of target buffer
    bits            :longint32;//24 or 32
    drows           :pcolorrows32;//target buffer -> buffer2
    srows           :pcolorrows32;//source buffer -> buffer

    x1              :longint;
    x2              :longint;
    y1              :longint;
    y2              :longint;

    //.brightnes adjustment optional -> 255=normal=no adjustment
    b357            :longint32;
    bCutoff255      :longint32;
    blist           :tfastbufferbytelist;

    //.background tile - optional -> use backgroundmanager.preComputeCellForRender32() proc to set and check
    tilew           :longint32;
    tileh           :longint32;
    tilebits        :longint32;//24 or 32 when valid, else 0
    tilerows        :pcolorrows32;

    power255        :longint32;

    cw              :longint32;
    ch              :longint32;
    cc              :longint32;
    ci              :longint32;

    scrollx         :longint32;
    scrolly         :longint32;
    wobblex         :longint32;
    wobbley         :longint32;

    //.buffer2 is active when "active=true"
    active        :boolean;

    //.reason for buffer2 being active
    rBrightness   :boolean;
    rBackground   :boolean;
    rHint         :boolean;
    rDragDrop     :boolean;//our internal version

    //.misc
    fallbackBW    :boolean;//true=indicates system is in the fallback black and white mode

    end;


//system objects ---------------------------------------------------------------

//tbasicapp
   tbasicapp=class(tobjectex)
   private

    igui:tbasicsystem;

    procedure xstarttimer;

   public

    //create
    constructor create(dwidth,dheight:longint); virtual;
    procedure createfinish; virtual;//30jul2021
    destructor destroy; override;

    //values
    property gui:tbasicsystem read igui;
    function rootwin:tbasicscroll;

    //workers
    procedure xloadsettings; virtual;
    procedure xsavesettings; virtual;

    //events
    procedure __ontimer(sender:tobject); virtual;

    //support
    procedure debug_tests;//19jul2024

   end;

{trnd8}
   trnd8=class(tobject)//29nov2023
   private
    icore:tstr8;
    imax,ipos,iposcount:longint;
   public
    //create
    constructor create(xsize:longint); virtual;
    destructor destroy; override;
    //workers
    function pull:byte;
    function pull2:byte;
   end;

{tbackgroundmanager}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//bbbbbbbbbbbbbbbbbbbbb
   tbackgroundmanager=class(tobject)//handles static, animated and dynamic background imagery for "tbasicsystem"
   private

    igui:tbasicsystem;
    itimer:comp;
    icrateTriggerID,iitemindex,ilimit:longint;
    icrateTriggered,imustpaint,imustupdate,iloadonce:boolean;
    icanchangevals        :array[0..99] of boolean;
    ipreComputeCellRef32  :tdynamicstring;
    isettingsRef          :string;//02mar2026

    //.animation support
    iuse_itemindex        :longint;//actual item being used

    iuse_tile32           :trawimage;//original image
    iuse_final32          :trawimage;//modified image -> values are pre-computed for rapid render - 13jan2026

    iuse_tileref          :string;
    iuse_tilew            :longint;
    iuse_tileh            :longint;

    iuse_shadepower255    :longint;
    iuse_shadepower255_inc:boolean;

    iuse_scrollx          :longint;
    iuse_scrolly          :longint;

    iuse_wobblex          :longint;
    iuse_wobbley          :longint;
    iuse_wobblef          :longint;//fade

    iuse_crate            :longint;//change rate

    iuse_cellcount        :longint;
    iuse_cellindex        :longint;

    iuse_loadid           :longint;//13jan2026
    iuse_tileok           :boolean;

    //.background exclusion mask
    tag                   :longint;

    function getname(xindex:longint):string;
    procedure setitemindex(xindex:longint);
    procedure xloadtile;
    procedure setbackgroundname(x:string);
    function getbackgroundname:string;

    //core support
    function getcount:longint;
    procedure setval(xnameid,xindex,xval:longint);
    function getval(xnameid,xindex:longint):longint;
    property val[xnameid,xindex:longint]:longint read getval write setval;

    function getstrength:longint;
    function getcolorise:longint;
    function getspeed:longint;
    function gethstep:longint;
    function gethwobble:longint;
    function getvstep:longint;
    function getvwobble:longint;
    function getfstep:longint;
    function getfwobble:longint;
    function getcrate:longint;

    procedure setstrength(x:longint);
    procedure setcolorise(x:longint);
    procedure setspeed(x:longint);
    procedure sethstep(x:longint);
    procedure sethwobble(x:longint);
    procedure setvstep(x:longint);
    procedure setvwobble(x:longint);
    procedure setfstep(x:longint);
    procedure setfwobble(x:longint);
    procedure setcrate(x:longint);

    function xsettingsChanged(xreset:boolean):boolean;//enhanced syncing - 02mar2026

   public

    constructor create(xgui:tbasicsystem); virtual;
    destructor destroy; override;
    procedure nint__onvalue(sender:tobject;var xval:longint;xwrite:boolean);
    procedure nint__onvalueDEF(sender:tobject;var xval:longint;xwrite:boolean);

    //information
    property gui:tbasicsystem read igui;
    function canchangevals:boolean;
    property name[xindex:longint]:string read getname;
    function iscustom(xindex:longint):boolean;
    property limit:longint read ilimit;
    property count:longint read getcount;
    property backgroundname:string read getbackgroundname write setbackgroundname;
    property itemindex:longint read iitemindex write setitemindex;
    function mustupdate(xreset:boolean):boolean;
    function mustpaint(xreset:boolean):boolean;
    function tileok:boolean;
    function inuse:boolean;
    property tilew:longint read iuse_tilew;
    property tileh:longint read iuse_tileh;
    property cellindex:longint read iuse_cellindex;
    property cellcount:longint read iuse_cellcount;

    property scrollx         :longint read iuse_scrollx;
    property scrolly         :longint read iuse_scrolly;
    property wobblex         :longint read iuse_wobblex;
    property wobbley         :longint read iuse_wobbley;
    property wobblef         :longint read iuse_wobblef;
    property shadepower255   :longint read iuse_shadepower255;

    //paint support
    function preComputeCellForRender32(var x:tfastbufferinfo):boolean;//13jan2026

    //adjustable values
    function canadjust:boolean;
    property strength:longint      read getstrength   write setstrength;
    property colorise:longint      read getcolorise   write setcolorise;
    property speed:longint         read getspeed      write setspeed;
    property hstep:longint         read gethstep      write sethstep;
    property hwobble:longint       read gethwobble    write sethwobble;
    property vstep:longint         read getvstep      write setvstep;
    property vwobble:longint       read getvwobble    write setvwobble;
    property fstep:longint         read getfstep      write setfstep;
    property fwobble:longint       read getfwobble    write setfwobble;
    property crate:longint         read getcrate      write setcrate;

    //timer
    function xmusttimer:boolean;
    procedure xtimer;

    //custom user image support
    function canpasteimage:boolean;
    function pasteimage:boolean;
    function canselectimage:boolean;
    function selectimage:boolean;
    function canclearimage:boolean;
    function clearimage:boolean;

    //io
    procedure storevals;
    procedure pullval(snameid:string;var xcanchange:boolean;var xval:longint);
    procedure pushval(snameid:string;xnewval:longint);

    //support
    function findnameid(xnameid_asstr:string;var xnameid:longint):boolean;
    function findbyname(xname:string):longint;
    function mint(xhost:tbasiccontrol;xnameid:string):tsimpleint;
    function sync_panel(x:tbasicscroll):boolean;
   end;


//GUI Support ------------------------------------------------------------------
{tbasicsystem}
   townlist=record
      list:array[0..maxcore] of word;
      count:longint;
      end;
   twinlist=record
      list:array[0..254] of word;
      count:longint;
      end;

   tbasicsystem=class(tobject)
   private

    //general
    ishowmenu             :tstr8;//pointer only
    isnapshot64           :comp;
    imousedownref         :comp;
    ihidecursorref        :comp;
    ipumptimer2           :comp;
    ibufferresize64       :comp;
    ilastsystem_slowref64 :comp;
    iecomode64            :comp;
    iopacitytimer         :comp;
    itimer5000            :comp;
    itimer1000            :comp;
    itimer100             :comp;
    itimer250             :comp;
    ishowonceref          :comp;
    iform_sizecheckcount  :longint;
    isizing               :longint;
    ilastmousemovecheckx  :longint;
    ilastmousemovechecky  :longint;
    icursorloadid         :longint;
    ishowaitcount         :longint;
    icloselocked          :longint;
    ilastdataid           :longint;
    iwinmax               :longint;
    iwinlimit             :longint;
    ilastsystem_mustidSLOW:longint;
    ilastsystem_mustid    :longint;
    iform_sizing          :boolean;
    if1_showhelp          :boolean;
    if2_restoredefaults   :boolean;
    iecopainting          :boolean;
    ishowoptions_crosssync:boolean;
    iwinemaximised        :boolean;
    imustcloseprompt      :boolean;
    itimer_busy           :boolean;
    idragging_fullwin     :boolean;
    iclosed               :boolean;
    iontimerbusy          :boolean;
    itiming               :boolean;
    imustclose            :boolean;
    ialigning             :boolean;
    ipaintedwithtile      :boolean;
    ipaintfirst           :boolean;
    inormalarea           :twinrect;//nor only
    istable               :byte;
    ikeyboardlaststate    :byte;
    fontimer              :tevent;
    fontimer2             :tevent;

    //game mode support - 29jan2025
    igamemode             :boolean;
    igamemode_cansize     :boolean;
    igamemode_canmove     :boolean;
    igamemode_onpaint     :tevent;
    igamemode_onshortcut  :tsystemnotify;
    igamemode_onnotify    :tsystemnotify;
    igamemode_onkey       :tsystemkeyevent;
    igamemode_onmouse     :tsystemmouseevent;
    fonkey                :tsystemkeyevent;//general purpose

    //fps painting stat
    ifps                  :longint;
    ifpscount             :longint;

    //automatic opacity
    ilastopacity100x      :longint;
    ilastopacitystep      :longint;
    ilastopacityref       :string;

    //wound support
    iwounddirx            :longint;
    iwounddiry            :longint;
    iwoundlastx           :longint;
    iwoundlasty           :longint;
    iwoundratex           :longint;
    iwoundratey           :longint;
    iwoundratelimit       :longint;
    iwoundref             :comp;

    //hint support
    ihint                 :string;
    ihintlines            :tdynamicstring;
    ihinttitle_linecount  :longint;//number of lines title covers -> usually only one or zero, but may be 2 or more if it's wrapped - 03jan2025
    ihintarea             :twinrect;
    ihintXY               :tpoint;
    ihintTimeout          :comp;
    ihintOnsecs           :longint;

    //showoptions support
    ishowoptions_inuse              :boolean;
    ishowoptions_backgroundpanel    :tbasicscroll;
    ishowoptions_window             :tbasicscroll;
    ishowoptions_settings           :tbasicscroll;
    ishowoptions_font               :tbasicscroll;
    ishowoptions_stats              :tbasicscroll;
    ishowoptions_snoop              :tbasicscroll;//28aug2025, 08mar2021
    ishowoptions_list               :tbasicmenu;
    ishowoptions_frames             :tbasicmenu;
    ishowoptions_backs              :tbasicmenu;
    ishowoptions_statslist          :tbasicmenu;
    ishowoptions_snooplist          :tbasicmenu;
    ishowoptions_options            :tbasicset;//26feb2022
    ishowoptions_cols               :tbasiccols;
    ishowoptions_backs_cols         :tbasiccols;
    ishowoptions_colors             :tbasiccolors;
    ishowoptions_framesize1         :tsimpleint;
    ishowoptions_framesize2         :tsimpleint;
    ishowoptions_sparkle1           :tsimpleint;
    ishowoptions_sparkle2           :tsimpleint;
    ishowoptions_brightness3        :tsimpleint;
    ishowoptions_focusedopacity1    :tsimpleint;
    ishowoptions_unfocusedopacity1  :tsimpleint;
    ishowoptions_opacityspeed1      :tsimpleint;
    ishowoptions_maintoolbar        :tbasictoolbar;
    ishowoptions_toolbar_background :tbasictoolbar;
    ishowoptions_timer100           :comp;
    ishowoptions_timer500           :comp;
    ishowoptions_font_vpos          :longint;
    ishowoptions_settings_vpos      :longint;
    ishowoptions_stats_vpos         :longint;
    ishowoptions_stats_vpos2        :longint;
    ishowoptions_snoop_vpos         :longint;
    ishowoptions_snoop_vpos2        :longint;

    //background support - 02mar2025
    ibackgroundmanager    :tbackgroundmanager;

    //core support
    icore                 :array[0..maxcore] of tbasiccontrol;
    icorecount            :longint;

    //action support
    ias                   :array[0..maxcore] of char;
    iam                   :array[0..maxcore] of byte;
    iax                   :array[0..maxcore] of longint;
    iay                   :array[0..maxcore] of longint;
    iacount               :longint;

    //pop support
    ipophost              :tbasiccontrol;
    ipopshortcut          :longint;//aknone=nothing

    //window support
    iwinhover             :longint;
    iwinhoverlayer        :longint;
    iwinfocus             :longint;
    iwinfocuslayer        :longint;
    idragindex            :longint;
    idragstart            :longint;
    idragrect             :twinrect;//note: used internally within "__onpaint()" only - 18may2020
    isizeindex            :longint;
    isizestart            :longint;//25feb2021

    //keyboard + mouse support
    idownrect             :twinrect;
    imousebuttonlock      :longint;
    iwheel                :longint;
    ikey                  :longint;
    imousebutton          :longint;
    ihoverindex           :longint;
    ifocusindex           :longint;
    ifocussizemodex       :longint;
    ifocussizemodey       :longint;//min32=none, -1=resize, 0..N=coreindex
    ishiftok              :boolean;
    ictrlok               :boolean;
    ialtok                :boolean;
    iscreendraggingout    :boolean;
    iscreenmovingfine     :boolean;
    iscreendragging       :boolean;
    iscreendraggingv      :boolean;
    iscreendraggingh      :boolean;
    iscreendraggingfine   :boolean;
    iscreendraggingfinev  :boolean;
    iscreendraggingfineh  :boolean;
    imousemoved           :boolean;
    imousedown            :boolean;
    imousewasdown         :boolean;
    imousedbclick         :boolean;
    iscreenmovingfinexy   :tpoint;
    imousedownxy          :tpoint;
    imousemovexy          :tpoint;
    iscreendownxy         :tpoint;
    iscreenmovexy         :tpoint;
    iscreenmovingfine64   :comp;
    imousedbclicktime     :comp;
    fonshortcut           :tsystemnotify;

    //paint support
    ipartpaint_arealist   :array[0..99] of twinrect;
    ipartpaint_count      :longint;
    ipartpaintareaok      :boolean;
    ipaintingpart         :boolean;
    imasking              :boolean;
    ipaintbusy            :boolean;
    imaskval              :longint;
    ipainting             :longint;
    imustpaint            :longint;
    imustalign            :longint;
    ialignid              :longint;
    ipaintid              :longint;
    ipostpaint_fullid     :longint;
    ipostpaint_partid     :longint;
    ipostpaint_id         :longint;

    //buffers
    ibuffer               :twinbmp;//main buffer all controls are rendered onto
    ibuffer2              :twinbmp;//bridge buffer that accepts pixels from "ibuffer" and renders them onto the form (ihost) via canvas
    ibuffer2info          :tfastbufferinfo;//set by xdrawtohost__start
    ibufferID2            :longint;
    idragbuffer           :trawimage;//drag buffer -> used for dragging windows - 28dec2025
    idragbufferRef64      :longint64;
    imask                 :tmask8;
    imaskRef64            :longint64;

    //.simple drag and drop - 21jul2024
    idragdrop_icon        :tbasicimage;//used for drag and drop dragging
    idragdrop_startarea   :twinrect;//mouse down
    idragdrop_paintarea   :twinrect;//current paint area
    idragdrop_code2       :string;
    idragdrop_ref         :string;
    idragdrop_dragging    :boolean;
    idragdrop_lastarea    :twinrect;
    idragdrop_power255    :longint;//06jun2025

    //splash
    isplash               :tbasicsplash;

    //status support
    istatuswin            :tbasicscroll;
    istatustime           :comp;
    istatuspert           :double;
    istatustab            :string;
    istatusrowcount       :longint;
    istatustext           :array[0..9] of string;
    istatustep            :array[0..9] of longint;
    istatustitle          :string;
    istatusshow           :boolean;
    istatusstopped        :boolean;

    //xdrawtohost support
    idrawtohost_count     :longint;
    idrawtohost_usetile   :boolean;
    idrawtohost_arealist  :array[0..99] of twinrect;

    //form support
    iform_handle          :hauto;
    iform_paintdc         :hauto;
    iform_lastdpi         :longint;
    iform_downrect        :twinrect;
    iform_caption         :string;
    iform_sizeref         :string;
    iform_cornersREF      :string;
    iform_fullscreen      :boolean;
    iform_active          :boolean;
    iform_width           :longint;
    iform_height          :longint;
    ipaint_tryagain_count :longint;
    iform_lastshift       :boolean;
    iform_lastalt         :boolean;
    iform_lastctrl        :boolean;
    ilaststate            :char;

    //rootwin
    irootwin              :tbasicscroll;

    function xcommonevent(a:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
    function xcommongetitem(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;//04dec2025
    procedure setfocusindex(x:longint);
    procedure sethoverindex(x:longint);
    function getfocuscontrol:tbasiccontrol;
    procedure setfocuscontrol(x:tbasiccontrol);
    function getcore(const x:longint):tbasiccontrol;
    procedure xtimer;//01dec2025
    procedure setwinfocus(x:longint);
    function getmaskval:longint;

    //host form support
    procedure __onpaint_debug(sender:tobject);
    procedure __onpaint(sender:tobject);//updated: 28jun2024, 28jul2020
    procedure __ontimer(sender:tobject);
    procedure __ontimer2(sender:tobject);
    function __onappmenu(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;

    //part paint support
    procedure xpartpaint__clear;
    function xpartpaint__addarea(x:twinrect):boolean;
    function xpartpaint__hasareaContained(x:twinrect):boolean;//for debugging

    //draw to host support
    procedure xdrawtohost__start(const xusetile:boolean);//10mar2026
    procedure xdrawtohost__addarea(const xarea:twinrect);
    procedure xdrawtohost(xarea:twinrect);//21apr2025, 09jan2025, 21nov2024: background animation pauses now during window resize/reposition events
    procedure xdrawtohost__renderBufferToForm;
    procedure xdrawhint;//13jan202

    //debug support
    procedure xbasicdebug_proc;

    //other
    function xshowoptions_getitem_stats(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;//17dec2024
    function xshowoptions_getitem_snoop(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;//17dec2024
    procedure xshowoptions_crosssync;
    property xshowoptions_list:tbasicmenu read ishowoptions_list;//Warning: can be nil - 24jul2021
    procedure xshowoptions_reload;
    procedure xshowoptions_timer(sender:tobject);
    procedure xshowoptions_showmenu(sender:tobject);
    procedure xshowoptions_click(sender:tobject);
    procedure xshowoptions_sync(sender:tobject);
    procedure xshowoptions_sync2(sender:tobject;xname:string;xclicked:boolean);
    procedure xsafearea;//14mar2025
    procedure xsnapshot_make;

    //.hint support
    procedure hint__none;
    function hint__cantitle(x:string):boolean;//03jan2025
    procedure hint__format;//09may2025: single "*" on a line for blank line, 21apr2025, 09jan2025, 03jan2025

    //.status support
    procedure __xstatus(xpert:double;xtitle:string;xshow,xupdatenow:boolean);
    function getstatustext(xindex:longint):string;
    procedure setstatustext(xindex:longint;x:string);
    function getstatustep(xindex:longint):longint;
    procedure setstatustep(xindex:longint;x:longint);
    procedure setstatuspert(xpert:double);
    function getstatusstopped:boolean;//catches "escape" key hiding status window - 02aug2021

    //.wound support
    procedure xwoundcalc(x,y:longint);

    //.fullscreen is now strictly internal use only, instead use "maxed,nomax,max or max2()" properties and procs -> max here means "max screen usage and not Ms maximise" - 09jan2025
    procedure xsyncfullscreen;//02dec2024: updated to check exact area and enforce it -> internal use only

    //.form support - 18jan2025
    function form__create(xacceptfiles:boolean):hauto;//01jun2025, 28may2025
//    procedure form__center(xmonitorindex:longint);
    function form__monitorindex:longint;
    procedure form__setcaption(x:string);
    function form__bordersize:longint;
    function form__minwidth:longint;
    function form__minheight:longint;
    function getshowing:boolean;
    function form__getontop:boolean;
    procedure form__setontop(x:boolean);
    procedure setstate(x:char);
    function getstate:char;
    function getdpi:longint;//10dec2025
    function xdpiChanged:boolean;
    procedure form__paintnow;//05oct2025
    procedure form__setval32(n:char;dv:longint);
    function form__getval32(n:char):longint;
    property form__val32[n:char]:longint read form__getval32 write form__setval32;
    function form__getarea:twinrect;
    procedure form__setarea(x:twinrect);
    property form__area:twinrect read form__getarea write form__setarea;
    function form__paintarea:twinrect;
    function form__paintarea1:twinrect;
    procedure form__setleft(x:longint);
    procedure form__settop(x:longint);
    procedure form__setwidth(x:longint);
    procedure form__setheight(x:longint);
    function form__getleft:longint;
    function form__gettop:longint;
    procedure form__wmnchittest(var m:twinmessage);//01feb2026
    procedure form__wmpaint(dc:hauto;var ps:tpaintstruct);
    procedure form__wmmousewheel(var m:twinmessage);
    procedure form__wmactivateapp(var m:twinmessage);
    procedure form__wmacceptfiles(var m:twinmessage);//08oct2024, 14feb2024: updated, drag&drop files - 24APR2011, 07DEC2009
    procedure form__wmactive(var m:twinmessage);
    procedure form__wmsetcursor(var m:twinmessage);
    procedure form__wmentersizemove;
    procedure form__wmsize(var m:twinmessage);
    procedure form__wmsizing(var m:twinmessage);//09mar2025: implemented min width/height enforcement
    procedure form__wmexitsizemove;
    procedure form__mouse(s:byte;xbut:longint;var m:twinmessage);
    procedure form__wmmousedown(xbut:longint;var m:twinmessage);
    procedure form__wmmousemove(var m:twinmessage);
    procedure form__wmmouseup(xbut:longint;var m:twinmessage);
    procedure form__wmkeydown(var m:twinmessage);
    procedure form__wmkeyup(var m:twinmessage);
    procedure form__wmsyskeydown(var m:twinmessage);
    procedure form__wmsyskeyup(var m:twinmessage);
    procedure form__wmchar(var m:twinmessage);
    procedure form__wmsyschar(var m:twinmessage);
    procedure form__wmclose(var m:twinmessage);
    procedure form__setbounds2(dx,dy,dw,dh:longint;xforcerepaint:boolean);//05may2025
    procedure form__sizeSync;
    procedure form__fadeout(const xreset:boolean);
    procedure form__fadein(const xreset:boolean);//18feb2025: tweaked, 05feb2025
    function getcursor:longint;
    procedure setcursor(x:longint);
    procedure setgamemode(x:boolean);//29jan2025
    function getbackgroundname:string;
    procedure setbackgroundname(x:string);

    //.fast draw support procs -> for rendering "buffer" onto "buffer2" - 27dec2025
    procedure xfd__renderBelowDragWindow_nochecks(const sa:twinrect;const xmaskVal:longint);
    procedure xfd__renderAboveDragWindow_nochecks(const sa:twinrect;const xmaskVal:longint);

   public

    //show modes
    smnone                :byte;
    smmodal               :byte;
    smwait                :byte;

    //index styles
    xsnone                :byte;
    xsoutside             :byte;
    xscontrol             :byte;
    xsunknown             :byte;

    //paint support
    recs                  :array[0..19] of twinrect;

    //own support
    ownlist               :townlist;
    ownid                 :longint;//for entire GUI -> increments each time *any* ownlist changes - 19mar2020

    //window support
    winlist               :twinlist;

    //mask support -> detects when the system Window mask needs to be updated
    winmask_cnt           :longint;
    winmask_id            :array[0..254] of longint;
    winmask_aid           :array[0..254] of longint;//Note: must be same size and range as "twinlist.list[0..254]" - 19may2020
    winmask_vis           :array[0..254] of boolean;
    winmask_rnd           :array[0..254] of boolean;

    //options
    otestmode            :boolean;//default=false
    ocansize             :boolean;//default=true
    ocanmove             :boolean;//defalt=true
    oeraseingbackground  :longint;//default=0, increments each time an erase background message is recieved - 24jul2025
    oclsscreen           :boolean;//default=false, true=paints screen area in case not paited over by one or more controls -> more a legacy option now - 26dec2025


    //corner processing - 24dec2025
    fdCorners            :tresslot;//01jan2026
    fdControls           :tresslot;
    fdHintEtc            :tresslot;
    fdTemp               :tresslot;

    //.dedicated fast draw procs -> render "buffer" onto "buffer2" - 11jan2026, 27dec2025
    procedure xfd__drawtohost(const x:twinrect);
    procedure xfd__drawtohost701__brightness(var x:tfastbufferinfo);//29dec2025
    procedure xfd__drawtohost702__background(var x:tfastbufferinfo);
    procedure xfd__drawtohost703__background_brightness(var x:tfastbufferinfo);

    //create
    constructor create(dwidth,dheight:longint); virtual;
    destructor destroy; override;

    function clienttoscreen(x:tpoint):tpoint;
    property showaitcount:longint read ishowaitcount;
    procedure pumptimer2;//forceably drive the timer - 15jul2021
    function xmainwin(var xwin:tbasicscroll):boolean;

    function xpopnav(var xvalue:string;xcommonfolder,xstyle:string;var daction:string):boolean;
    function xpopnav2(var xvalue:string;var xfilterindex:longint;xfilterlist,xcommonfolder,xstyle,xhisname,xtitle:string;var daction:string):boolean;
    function xpopnav3(var xvalue:string;var xfilterindex:longint;xfilterlist,xcommonfolder,xstyle,xhisname,xtitle:string;var daction:string;xcanpreview:boolean):boolean;

    property winemaximised:boolean read iwinemaximised;
    procedure form__center(xmonitorindex:longint);

    //closelock
    property mustcloseprompt:boolean read imustcloseprompt write imustcloseprompt;//allow host program to set TRUE or FALSE to PROMPT before closing the program - 26aug2021
    property closelocked:longint read icloselocked;
    procedure closelock;
    procedure closeunlock;
    procedure xfireevent(sender:tobject;xevent:tnotifyevent);//lock close -> fireevent -> unlock close - 03apr2021

    //form
    property dpi:longint read getdpi;//10dec2025
    property handle:hauto read iform_handle;
    property paintdc:hauto read iform_paintdc;
    property state:char read getstate write setstate;
    property laststate:char read ilaststate;
    property caption:string read iform_caption write form__setcaption;
    property showing:boolean read getshowing;
    property active:boolean read iform_active;
    function mainwindow:boolean;
    property area:twinrect read form__getarea write form__setarea;
    property paintarea:twinrect read form__paintarea;
    property paintarea1:twinrect read form__paintarea1;
    property cursor:longint read getcursor write setcursor;
    property paint_tryagain_count:longint read ipaint_tryagain_count write ipaint_tryagain_count;

    property left   :longint read form__getleft   write form__setleft;
    property top    :longint read form__gettop    write form__settop;
    property width  :longint read iform_width  write form__setwidth;
    property height :longint read iform_height write form__setheight;

    procedure setbounds(dx,dy,dw,dh:longint);
    procedure setbounds2(dx,dy,dw,dh:longint;xforcerepaint:boolean);

    //rootwin
    function haverootwin:boolean;
    function rootwin:tbasicscroll;

    //low level debug support -> normal window mode and game mode now supported - 04jul2025
    procedure debug(yrow:longint;xtext:string);//07apr2026, 04jul2025: persists in Gamemode, 26nov2024, 01aug2024

    //drag and drop - simple version - 21jul2024
    function dragdrop_start(dx,dy,dw,dh:longint;const dcode2:string):boolean;
    function dragdrop_start2(dx,dy,dw,dh,diconw,diconh:longint;dicon:tobject;const dcode2:string):boolean;
    function dragdrop_start3(dx,dy,dw,dh,diconw,diconh,dpower255:longint;dicon:tobject;const dcode2:string):boolean;
    function dragdrop_stop(var dcode2:string):boolean;
    function dragdrop_mustpaint:boolean;
    property dragdrop_active:boolean read idragdrop_dragging;//06jun2025

    //information
    function monitorindex:longint;//used for app__monitor* procs
    function bits:longint;//buffer.bits=24bit
    property showingoptions           :boolean                read ishowoptions_inuse;//07mar2022
    property stable                   :byte                   read istable;//0=stable, 1=creating, 2=destroying
    property alignid                  :longint                read ialignid;
    property postpaint_fullid         :longint                read ipostpaint_fullid;
    property postpaint_partid         :longint                read ipostpaint_partid;
    property postpaint_id             :longint                read ipostpaint_id;//06jan2025
    property paintfirst               :boolean                read ipaintfirst;//system has rendered the first FULL paint - 17mar2025
    property paintid                  :longint                read ipaintid;
    property painting                 :boolean                read ipaintbusy;
    property paintingpart             :boolean                read ipaintingpart;
    property partpaintareaok          :boolean                read ipartpaintareaok;
    property ecopainting              :boolean                read iecopainting;//true=system has switched to reduced painting (eco mode), false=normal painting - 16nov2023
    property fps                      :longint                read ifps;

    //showmenu support -> separate from tbasicontrol
    function canshowmenu:boolean;
    procedure showmenu(xsender:tobject;x:tstr8;xstyle:string;xevent:ttoolbarevent2);
    procedure showmenu1(xsender:tobject;x:tstr8;xstyle:string;xevent:ttoolbarevent2;var xcode:longint;var xcode2:string);
    procedure showmenu2(xsender:tobject;x:tstr8;xstyle,xmenuname:string;xtepcolor,ximagexalign:longint;xevent:ttoolbarevent2;var xcode:longint;var xcode2:string);

    //.window mask support
    property masking                  :boolean                read imasking;//paint via mask8 layer support -> for fast, multiple overlapping window support - 17may2020
    function mustmask                 :boolean;
    property maskval                  :longint                read getmaskval;
    property mask                     :tmask8                 read imask;

    //.background support
    property backgroundname           :string                 read getbackgroundname                  write setbackgroundname;
    function backgroundinuse          :boolean;
    property backgroundmanager        :tbackgroundmanager     read ibackgroundmanager;

    //.buffer2 draw procs - 25dec2024
    function xcornerCode:longint32;//05jan2026
    function xcornerMode:longint32;//13jan2026

    procedure foutlineArea(const darea:twinrect;const dcol:longint;const dround:boolean);//26mar2026
    procedure foutlineArea2(const darea:twinrect;const dcol,dpower255:longint;const dsparkle,dround:boolean);//26mar2026

    procedure ffillOUTSIDE(dx,dy,dw,dh,dcol:longint);//26mar2026, 21jul2025
    procedure ffillArea(const darea:twinrect;const dcol:longint;const dround:boolean);

    procedure fshadeArea(const darea:twinrect;const dcol1,dcol2:longint;const dround:boolean);
    procedure fshadeArea2(const darea:twinrect;const dcol1,dcol2,dcol3,dcol4,dsplice100,dpower255:longint;const dround:boolean);

    procedure ftext(const dbackRef:longint;const darea:twinrect;const dx,dy,dcol:longint;const dtab,dtext:string;const dfont:longint32);//20feb2026

    //new handlers
    function nfullwin:tbasicscroll;
    function nwindow(da:twinrect):tbasicscroll;
    function nontop(da:twinrect):tbasicscroll;
    function ndlg(da:twinrect;xshowhead:boolean):tbasicscroll;
    function ndlg2(da:twinrect;xshowhead,xstatic:boolean):tbasicscroll;
    function ndlg3(da:twinrect;xtep:longint;xtitle:string;xshowhead,xstatic:boolean):tbasicscroll;
    function nstatus(xtitle:string):tbasicscroll;
    function nscroll(da:twinrect):tbasicscroll;
    function nsetcolor(da:twinrect;xshowhead:boolean):tbasicsetcolor;//27feb2021
    function nsetcolor2(da:twinrect;xshowhead,xuse32:boolean):tbasicsetcolor;//17nov2023

    //position support (left/right/top/bottom) - 27feb2022
    function canposition:boolean;
    procedure position(xstyle:string);//18nov2024

    //pop handlers

    //.special
    function popint(var xval:longint;xmin,xmax,xdef:longint;xtep32:longint;xtitle,xcap,xhelp,xcancelcap,xokcap:string;xsize:longint):boolean;

    //.edit
    function poppass(var x:string;xcap,xhelp:string):boolean;
    function popedit(var x:string;xcap,xhelp:string):boolean;
    function popedit_small(var x:string;xcap,xhelp:string):boolean;
    function popedit2(var x:string;xtep32:longint;xtitle,xcap,xhelp,xcancelcap,xokcap:string;xsize:longint):boolean;
    function popedit3(var x:string;xtep32:longint;xtitle,xcap,xhelp,xcancelcap,xokcap:string;xsize:longint;xpassword:boolean):boolean;
    function popmanyedit2(xcount:longint;var x:array of string;xtep32:longint;xtitle:string;xcap:array of string;xhelp:array of string;xcancelcap,xokcap:string;xsize:longint):boolean;
    function popmanyedit3(xcount:longint;var x:array of string;xtep32:longint;xtitle:string;xcap:array of string;xhelp:array of string;xcolorise:array of tinputcolorise;xcancelcap,xokcap:string;xsize:longint):boolean;

    //.txt - poptext() - 22apr2026: xfont2
    procedure poptxt0(x:string;const xfont2:boolean);//for display purposes only
    procedure poptxt02(x,xcap:string;const xfont2:boolean);//for display purposes only
    function poptxt(var x:string;xwrap:longint;const xfont2:boolean;const xcap,xhelp:string):boolean;
    function poptxt2(var x:string;xwrap:longint;xreadonly,xfont2:boolean;const xcap,xhelp:string):boolean;
    function poptxt3(var x:string;xwrap:longint;xrows,xreadonly,xfont2:boolean;const xcap,xhelp,xcancelcap,xokcap:string):boolean;
    function poptxt4(var x:string;xwrap:longint;xrows,xreadonly,xfont2:boolean;const xcap,xhelp,xcancelcap,xokcap,xstyle:string;xscaleW,xscaleH:single):boolean;
    function poptxt8(xtext:tstr8;xwrap:longint;xrows,xreadonly,xfont2:boolean;const xcap,xhelp,xcancelcap,xokcap,xstyle:string):boolean;//12jan2025
    function poptxt82(xtext:tstr8;xwrap:longint;xrows,xreadonly,xfont2:boolean;const xcap,xhelp,xcancelcap,xokcap,xstyle:string;xscaleW,xscaleH:single):boolean;//12jan2025
    function poptxt__event2(a:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;

    //.query
    function popquery(const x:string):boolean;
    function popqueryAndConfirm(const x:string):boolean;//22apr2026
    function popquery1(const xtitle,x:string):boolean;
    function popquery2(const x,xcancelcap,xokcap:string;const xlarge:boolean):boolean;
    function popquery20(const xtitle,x,xcancelcap,xokcap:string;const xlarge:boolean):boolean;
    function popquery21(const x,xcancelcap,xokcap:string;const xlarge,xOKtime:boolean):boolean;
    function popquery22(const xtitle,x,xcancelcap,xokcap:string;const xlarge,xOKtime:boolean):boolean;
    function popqueryex(const x,xcancelcap,xokcap:string;const dw,dh,ccancel,cok:longint):boolean;
    function popqueryex2(xtitle,x,xcancelcap,xokcap:string;dw,dh,ccancel,cok:longint):boolean;//11dec2025
    function pop_replaceall_skipall(xtitle,xfilename:string):longint;

    //.error
    function poperror(xtitle,x:string):boolean;
    function poperror2(xtitle,x,xclosecap:string;xlarge:boolean):boolean;
    function poperrorex(xtitle,x,xclosecap:string;dw,dh,cclose:longint):boolean;

    //.status
    function popstatus(xmsg:string;xshowsec:longint):boolean;//based on font size - 11dec2025, 19jul2024: oshadeback=true, 03jnov2023

    //.msg
    function popmsg(xtitle,x:string):boolean;//23jul2024

    //.info
    function popinfo(xtitle,x:string):boolean;
    function popinfo2(xtitle,x,xclosecap:string;xlarge:boolean):boolean;
    function popinfoex(xtitle,x,xclosecap:string;dw,dh,cclose:longint):boolean;
    function poperrorORinfo(xtitle,x,xclosecap:string;dw,dh,cclose:longint;xinfo:boolean):boolean;//03jun2021
    function poperrorORinfo2(xtitle,x,xclosecap:string;dw,dh,cclose:longint;xinfo,xshowicon:boolean):boolean;//11dec2025, 23jul2024

    //.find
    function popfind(xhandler:longint;var xtext,xcmd:string):boolean;

    //.menu
    function popmenu(xpopstyle,ximagealign:longint;xmenudata:tstr8;var xcode:longint;var xcode2:string;var xtepcolor:longint):boolean;
    function popmenu2(xpopstyle,ximagealign:longint;xmenudata:tstr8;xmenuname:string;xstyle:longint;var xcode:longint;var xcode2:string;var xtepcolor:longint):boolean;
    function popmenu2b(xpopstyle,ximagealign:longint;xmenudata:tstr8;xcontrol:tbasiccontrol;xmenuname:string;xstyle:longint;var xcode:longint;var xcode2:string;var xtepcolor:longint):boolean;
    function popmenu3(xpopstyle,ximagealign:longint;xmenudata:tstr8;xcontrol:tbasiccontrol;xstyle,xpos,xhover,xselstart,xselcount:longint;var xoutpos,xouthover,xoutselstart,xoutselcount,xcode:longint;var xcode2:string;var xtepcolor:longint):boolean;
    function popmenu4(xpopstyle,ximagealign:longint;xmenudata:tstr8;xcontrol:tbasiccontrol;xshowhelp:boolean;xstyle,xdropcount,xpos,xhover,xselstart,xselcount:longint;var xoutpos,xouthover,xoutselstart,xoutselcount,xcode:longint;var xcode2:string;var xtepcolor:longint):boolean;
    function popmenu5(xpopstyle,ximagealign:longint;xmenudata:tstr8;xcontrol:tbasiccontrol;xshowhelp:boolean;xstyle,xdropcount,xpos,xhover,xselstart,xselcount:longint;var xoutpos,xouthover,xoutselstart,xoutselcount,xcode:longint;var xcode2:string;var xtepcolor:longint;xfindbycode2:string):boolean;//13apr2025, 18mar2025, 07jul2021

    //.droplist -> simulates a dropdown list -> must specify a control via "xcontrol" - 04oct2020
    function popdroplist(xmenudata:tstr8;xcontrol:tbasiccontrol;var xpos,xcode:longint;var xcode2:string;xfindbycode2:string):boolean;
    function popdroplist2(xmenudata:tstr8;xcontrol:tbasiccontrol;xdropcount:longint;var xpos,xcode:longint;var xcode2:string;xfindbycode2:string):boolean;

    //.io
    function popopenimg(var xfilename:string;var xfilterindex:longint;xcommonfolder:string):boolean;//12apr2021
    function popsaveimg(var xfilename:string;xcommonfolder:string;var daction:string):boolean;//12apr2021
    function popsaveimg2(var xfilename:string;xcommonfolder,xtitle2:string;var daction:string):boolean;//18jun2021, 12apr2021
    function popsaveimg3(var xfilename:string;xcommonfolder,xtitle2:string;xanimationformats,xlossless:boolean;var daction:string):boolean;//08nov2025, 18jun2021, 12apr2021
    function popopencur(var xfilename:string;var xfilterindex:longint;xcommonfolder:string;xmore:boolean):boolean;//29aug2021
    function popopen(var xfilename:string;var xfilterindex:longint;xfilterlist,xcommonfolder:string):boolean;
    function popopen2(var xfilename:string;var xfilterindex:longint;xfilterlist,xcommonfolder,xtitle2:string):boolean;
    function popopen3(var xfilename:string;var xfilterindex:longint;xfilterlist,xcommonfolder,xtitle2:string;xcanpreview:boolean):boolean;
    function popsave(var xfilename:string;xfilterlist,xcommonfolder:string;var daction:string):boolean;
    function popsave2(var xfilename:string;xfilterlist,xcommonfolder,xtitle2:string;var daction:string):boolean;
    function popsave3(var xfilename:string;xfilterlist,xcommonfolder,xtitle2:string;var daction:string;xcanpreview:boolean):boolean;
    function popfolder(var xfilename:string;const xcommonfolder:string):boolean;
    function popfolder1(var xfilename:string;const xmasklist,xcommonfolder:string):boolean;
    function popfolder2(var xfilename:string;const xmasklist,xcommonfolder:string;xshowfiles,xcanpreview:boolean):boolean;
    function popnewfolder(xfolder:string;var xoutfolder:string):boolean;//14apr2021
    function popfolderimg(xfolder:string):boolean;
    function popfav(var xfilename:string):boolean;
    function popnav(var xfilename:string;xcommonfolder:string):boolean;

    //.color
    function popcolorstatic(var xvalue:longint):boolean;
    function popcolorhistory(var xvalue:longint;xuse32:boolean):boolean;
    function popcolorhistory__add(xvalue:longint;xuse32:boolean):boolean;
    function popcolorhistory__edit:boolean;
    function popcolor(var xvalue:longint):boolean;
    function popcolor2(var xvalue:longint;xuse32:boolean):boolean;//11dec2025

    //..color support
    function xcolorhistory(var xvalue:longint;xaddonly,xeditonly,xuse32:boolean):boolean;//17nov2023, 19mar2021

    //.font - 26mar2022
    function popfont(var xfontname:string):boolean;//26mar2022
    function popfont2(var xfontname:string;xscreen,xprinter,xspecial,xaslist:boolean;xpopcontrol:tbasiccontrol):boolean;//05jun2025, 15nov2023

    //.pop dialogs
    procedure xsafepopXYWHex(var dx,dy,dw,dh:longint;dy2:longint);//15NOV2010
    function xshowwait(a:tbasicscroll;xpreviouscontrol:tbasiccontrol;xpreviousfocus:longint):boolean;
    function xshowwait2(a:tbasicscroll;xpreviouscontrol:tbasiccontrol;xpreviousfocus,xtimeout:longint):boolean;
    function xshowwait3(a:tbasicscroll;xpreviouscontrol:tbasiccontrol;xpreviousfocus,xtimeout:longint;xlimitsize:boolean):boolean;//09dec2024
    function xpopwait(a:tbasicscroll;xpreviousfocus,dw,dh:longint;xcenter:boolean):boolean;//21may2020
    function xpopwait2(a:tbasicscroll;xcontrol:tbasiccontrol;xpreviousfocus,dw,dh:longint;xcenter:boolean):boolean;//21may2020
    procedure xclose(a:tbasiccontrol);
    procedure xcloseok(a:tbasiccontrol);

    //.wait support - 03apr2021
    function xhavewaitfocusLOOSE:boolean;//06apr2021
    procedure xwaitfocus;

    //window handlers
    procedure showappmenu(xallwinbuttons:boolean);//07sep2025, 27dec2024
    property winhover                 :longint                read iwinhover;
    property winhoverlayer            :longint                read iwinhoverlayer;
    property winfocus                 :longint                read iwinfocus write setwinfocus;
    property winfocuslayer            :longint                read iwinfocuslayer;
    function xwinfindlayer(xcoreindex:longint;var xlayer:longint):boolean;
    function xwinfindbyxy(sx,sy:longint;var xcoreindex,xwinlayer:longint):boolean;
    procedure xwintop(x:tbasiccontrol);
    procedure xwinbot(x:tbasiccontrol);
    procedure xwinnil(x:tbasiccontrol);
    procedure xwinadd(x:tbasiccontrol;xstyle:char);
    function xdlg(var x:tbasiccontrol):boolean;//get active dialog window
    function xfindwinname(xwinname:string;var x:tbasicscroll):boolean;
    function wtop(var x:tbasiccontrol;var xindex:longint):boolean;//xxxxxxxxxxxxx//dodgy, needs upgrading........
    function xacceptfindbyxy(sx,sy:longint;var xout:tbasiccontrol):boolean;//updated - 20mar2022
    procedure xsync_opacity;//02dec2024: streamlined viopacityspeed

    //.drag support
    procedure dragstart(xcoreindex:longint);
    procedure dragstart_fullwin;//this relates to external OS only and NOT to our internal system - 15apr2021
    procedure dragstop;
    function dragging:boolean;//21nov2024
    function dragging_an_internal_window:boolean;//28nov2024

    //..drag support
    property dragging_fullwin         :boolean                read idragging_fullwin;
    property dragindex                :longint                read idragindex;//coreindex

    //.size support
    procedure sizestart(xcoreindex:longint);
    procedure sizestop;
    function resizing:boolean;//15mar2025
    property sizing                   :longint                read isizing;//0=off, 1=(was)resizing MAIN window (wm_fullwin), 2=resizing OTHER window types - 22apr2022

    //.status support
    procedure xstatuspaintnow;
    procedure xstatusstart(xrowcount:longint);
    procedure xstatusstart2(xrowcount:longint;const xtab:string);//15may2022
    procedure xstatusstart3(xrowcount:longint;const xtab:string;xresetcancel:boolean);//20may2022
    procedure xstatusstop;
    property xstatustopped:boolean read getstatusstopped;
    procedure xstatus(xpert:double;xtitle:string);//15may2022
    property xstatustext[xindex:longint]:string               read getstatustext write setstatustext;
    property xstatustep[xindex:longint]:longint               read getstatustep write setstatustep;
    procedure xstatustab(const xtab:string);//15may2022
    procedure xstatus_sysstatus_alloff;
    property xstatustitle             :string                 read istatustitle;
    property xstatuspert              :double                 read istatuspert write setstatuspert;

    //system handlers
    procedure xcenter(x:tbasiccontrol);
    procedure xshowsplash;
    procedure xshowabout;
    procedure xshowoptions;//01mar2026, 06nov2025, 05may2025, 02dec2024: font+settings.vpos, 14nov2024
    procedure xshowhelp;
    procedure xdefaults;//10dec2025
    procedure xdefaultscale;
    procedure xsnapshot;//03nov2023

    //black and white mode -> emergency paint mode that renders GUI on screen with black and white coloring regardless of user/system settings - 09dec2024
    procedure xstartbw(xpaint:boolean);
    procedure xstopbw(xpaint:boolean);

    //core handlers
    property core[const x:longint]    :tbasiccontrol          read getcore;
    property corecount                :longint                read icorecount;
    function xrootok(const x:tbasiccontrol):boolean;
    function xinuse(const xcoreindex:longint):boolean;
    function xvisible(const xcoreindex:longint):boolean;
    procedure mustclose;
    function xsafeown(var xownlist:townlist):boolean;
    function xownhave(var xownlist:townlist;const x:tbasiccontrol):boolean;
    function xownfind(var xownlist:townlist;const x:tbasiccontrol;var xownslot:longint):boolean;
    function xownfindcount(var xownlist:townlist):longint;
    function xownadd(var xownlist:townlist;const x:tbasiccontrol):boolean;
    procedure xowndel(var xownlist:townlist;const x:tbasiccontrol);
    function xownget(var xownlist:townlist;const xownslot:longint;var x:tbasiccontrol):boolean;
    function xowndel__fast(var xownlist:townlist;const xownslot:longint):boolean;//04may2021
    procedure ownadd(const xhost,xcontrol:tobject);
    procedure owndel(const xhost,xcontrol:tobject);
    function xareaok(const x:twinrect):boolean;
    function xareaongui(const x:twinrect):boolean;
    function xareaseen(const sa:twinrect;xbeneathwindowlayer:longint):boolean;//07apr2026
    function xadd(const x:tbasiccontrol;var xcoreindex:longint):boolean;
    function xdel(const xcoreindex:longint;const xfree:boolean):boolean;

    //pop support
    property pophost                  :tbasiccontrol          read ipophost;//pointer only, may be nil at anytime - 01apr2020
    property popshortcut              :longint                read ipopshortcut write ipopshortcut;//this is the shortcut the user executed whilst the menu was up and active, default=aknone -> no shortcut was triggered - 02apr2020

    //mouse system
    procedure xfindany(sx,sy:longint;var xfocusindex,xhoverindex,xsizemode,ysizemode:longint);//17aug2025
    property hoverindex               :longint                read ihoverindex write sethoverindex;
    property focusindex               :longint                read ifocusindex write setfocusindex;
    property focuscontrol             :tbasiccontrol          read getfocuscontrol write setfocuscontrol;
    property focussizemodex           :longint                read ifocussizemodex;//resize by x-coor
    property focussizemodey           :longint                read ifocussizemodey;//resize by y-coor
    property downrect                 :twinrect               read idownrect;//area of control that has focus when mouse is clicked down
    property form__downrect           :twinrect               read iform_downrect;//area of host form when mouse is clicked down
    function indexstyle(xindex:longint):longint;
    function styleindex(xstyle:longint):longint;

    //.local cursor support -> cursor position within system area
    function curpos                   :tpoint;//our internal cursor position (within the system area only) - 21may2020
    function downcurpos               :tpoint;//our internal cursor position (within the system area only) - 21may2020
    procedure showcursor;//28feb2022
    procedure hidecursor;//28feb2022
    function showingcursor            :boolean;//06dec2024

    //.localised coordinates
    property mousedbclick             :boolean                read imousedbclick;//double click
    property mousedown                :boolean                read imousedown;
    function mousedowntime            :comp;//09mar2022
    property mousewasdown             :boolean                read imousewasdown;
    property mousedownxy              :tpoint                 read imousedownxy;
    property mousemovexy              :tpoint                 read imousemovexy;

    //.takes ~20px(xfine=false) or 1px(xfine=true) to start and MUST be outside to START of specified controls' area - 09mar2021, 25feb2021
    function mousedraggingout(x:tbasiccontrol;xkeepchecking,xfine:boolean):boolean;
    function mousedraggingout2(x:twinrect;xkeepchecking,xfine:boolean):boolean;
    function mousedraggingout3(xoffx,xoffy:longint;x:twinrect;xkeepchecking,xfine:boolean):boolean;
    property mousewasdraggingout:boolean read iscreendraggingout;

    //.takes ~20px to start
    property mousedragging            :boolean                read iscreendragging;
    property mousedraggingv           :boolean                read iscreendraggingv;
    property mousedraggingh           :boolean                read iscreendraggingh;

    //.takes ~1px to start
    property mousedraggingfine        :boolean                read iscreendraggingfine;
    property mousedraggingfinev       :boolean                read iscreendraggingfinev;
    property mousedraggingfineh       :boolean                read iscreendraggingfineh;

    //.other
    property mousemoved               :boolean                read imousemoved;//mouse moved
    property mousemovingfine          :boolean                read iscreenmovingfine;//takes ~2px - 27feb2022
    function mousedownstroke          :boolean;//mouse has been clicked down
    function mouseupstroke            :boolean;//mouse has released the click

    //.strictly ONCE up and down detectors - excludes MOVE events
    function mousedownonce            :boolean;//strictly excludes ANY move events - triggers ONLY once - 19nov2023
    function mouseuponce              :boolean;//strictly excludes ANY move events - triggers ONLY once - 19nov2023

    //.button modes
    property mousebutton              :longint                read imousebutton;//abnone, ableft, abcenter, abright
    function mousenone                :boolean;
    function mouseleft                :boolean;
    function mousecenter              :boolean;
    function mouseright               :boolean;

    //.special key
    property shiftok                  :boolean                read ishiftok;
    property altok                    :boolean                read ialtok;
    property ctrlok                   :boolean                read ictrlok;
    property key                      :longint                read ikey write ikey;//aknone=off
    property wheel                    :longint                read iwheel;//0=off - wheel movement

    //.wound rates & direction - 30sep2022
    function woundratexpert1          :extended;//0.0..1.0
    function woundrateypert1          :extended;//0.0..1.0
    function woundratexpert100        :longint;//0..100
    function woundrateypert100        :longint;//0..100
    function woundratextime(xmaxtime:longint;xincludedir:boolean):longint;
    function woundrateytime(xmaxtime:longint;xincludedir:boolean):longint;
    property woundratex               :longint                read iwoundratex;//0..woundratelimit
    property woundratey               :longint                read iwoundratey;//0..woundratelimit
    property woundratelimit           :longint                read iwoundratelimit;
    property wounddirx                :longint                read iwounddirx;//-1=left, 1=right OR stopped
    property wounddiry                :longint                read iwounddiry;//-1=up,   1=down  OR stopped

    //.screen coordinates
    property screendragging           :boolean                read iscreendragging;
    property screendraggingfine       :boolean                read iscreendraggingfine;
    property screendraggingout        :boolean                read iscreendraggingout;//25feb2021
    property screendownxy             :tpoint                 read iscreendownxy write iscreendownxy;
    property screenmovexy             :tpoint                 read iscreenmovexy write iscreenmovexy;

    //action support
    function aadd(xs:char;xm:byte;xx,xy:longint):boolean;
    function apull(var xs:char;var xm:byte;var xx,xy:longint):boolean;
    procedure anext;//next action
    procedure amouseupfinalise;//14may2020

    //timer + paint support
    function  xtimerinterval          :longint;
    property  xmustpaint              :longint                read imustpaint;

    //.paint support
    property buffer                   :twinbmp                read ibuffer;
    property buffer2                  :twinbmp                read ibuffer2;
    property paintedwithtile          :boolean                read ipaintedwithtile;
    function rows                     :tstr8;
    function rows2                    :tstr8;
    function lastbuffer               :twinbmp;
    function lastrows                 :tstr8;

    //events
    procedure _onnotify(sender:tobject;xstyle:char);//06jan2025
    procedure _onnotifylast(sender:tobject;xhandled:boolean);
    function  _onshortcut(sender:tobject):boolean;
    function _onshortcutlast(sender:tobject):boolean;//09dec2024
    property onshortcut:tsystemnotify read fonshortcut write fonshortcut;//11feb2023
    property onkey:tsystemkeyevent read fonkey write fonkey;//22jul2025 - general purpose support

    //additional support
    procedure paintallnow;
    procedure paintnow;
    procedure alignallnow;
    procedure alignnow;
    procedure sizenow;
    procedure fullalignpaint;

    //special events
    property ontimer:tnotifyevent read fontimer write fontimer;//main timer -> itimer

    //game mode -> switching into gamemode=true disables all GUI related paint procs and hands control of the GUI screen over to the host for direct rendering with a 200-300% performance increase - 29jan2025
    property gamemode                 :boolean                read igamemode            write setgamemode;//29jan2025
    property gamemode__cansize        :boolean                read igamemode_cansize    write igamemode_cansize;
    property gamemode__canmove        :boolean                read igamemode_canmove    write igamemode_canmove;
    property gamemode__onpaint        :tnotifyevent           read igamemode_onpaint    write igamemode_onpaint;
    property gamemode__onkey          :tsystemkeyevent        read igamemode_onkey      write igamemode_onkey;
    property gamemode__onmouse        :tsystemmouseevent      read igamemode_onmouse    write igamemode_onmouse;//26jul2025
    property gamemode__onnotify       :tsystemnotify          read igamemode_onnotify   write igamemode_onnotify;
    property gamemode__onshortcut     :tsystemnotify          read igamemode_onshortcut write igamemode_onshortcut;

    //.raw access to form's paint handle
    function xdrawfrom(const shc:hauto;const sa:twinrect):boolean;
    function xdrawfrom2(const shc:hauto;const dx,dy:longint;const sa:twinrect):boolean;
    function xcopyfrom(const shc:hauto;const sa,da:twinrect):boolean;
    procedure xsavePosSize;

   end;

{tbasiccontrol}
   tbasiccontrol=class(tobject)
   private

    igui:tbasicsystem;//pointer only -> never nil
    iparent:tbasiccontrol;
    ioffloading,imustalign,imustpaint,ialigned,ipainted,ipainting,ialigning,itimer,itiming,ienabled,ivisible,inormal:boolean;
    iclientarea:twinrect;//area of control (visible bits or not)
    ipaintarea:twinrect;//area of control that is visible (invalid rect if nothing is visible at all)
    icaption,ihint,ihelp,ihelp2,isubhelp,isubhelp2:string;
    iroundmode2,isparkleStartPos,iwoundtime,iid,iaid,iwinstyle,iparentcoreindex,icoreindex,iheightref,ibordersize:longint;
    iidleREF64,iwoundtimer:comp;
    fontimer2,fonvalue,fonalign,fonpaint:tnotifyevent;
    fonnotify:tsystemnotify;
    fonaccept:tonacceptevent;//18jun2021
    fonfindheight:tonfindheight;//06jul2021
    fonwinLdrcolor:tlongintgetevent;
    istable:byte;//0=stable, 1=creating, 2=destroying

    //.show menu support
    ishowmenu:tstr8;//default=nil
    fshowmenuFill1,fshowmenuFillINT,fshowmenuFill2:tmenufillevent;
    fshowmenuClick1,fshowmenuClickINT,fshowmenuClick2:ttoolbarevent2;
    fonshowmenu:tnotifyevent;//optional override

    procedure setbordersize(x:longint);
    function gethelpline:string; virtual;
    function gethintline:string; virtual;
    procedure setparent(x:tbasiccontrol);
    procedure setvisible(x:boolean);
    procedure setenabled(x:boolean);
    procedure setclientarea(a:twinrect);
    function getleft:longint;
    function gettop:longint;
    function getclientwidth:longint;
    function getclientheight:longint;
    procedure setclientwidth(x:longint);
    procedure setclientheight(x:longint);
    procedure setwinstyle(x:longint);
    procedure setcaption(x:string);
    procedure setnormal(x:boolean); virtual;//19jul2025
    procedure xroundMode_StartOverride(const x:longint);
    procedure xroundMode_StopOverride;
    function xscrollingHost__captureCorners:boolean;
    procedure xframeSimple(const s:tclientinfo);//29mar2026

   public

    //options
    oflatback       :boolean;
    oborderdiff     :longint;//default=0
    omade           :longint;//default==0=made_none -> helps the control know what to do when it "makes" itself into special handler - 23mar2022
    ocanshowmenu    :boolean;//default=false
    obold           :boolean;//default=false, true=use bold font for text if supported - 03mar2021
    osafearea       :boolean;//default=true=only for window controls
    oroundStyle     :longint;//default=1=corRound
    oroundMode      :longint;//default=0=rmAll
    oautotop        :boolean;//default=true=when a window it is automatically brought to top of it's stack, false=retain stack order
    ominheight      :longint;//default=0=off, use to specify another height other than "getalignheight"
    ominwidth       :longint;//default=0=off, use to specify another width other than "getalignwidth"
    oautoheight     :boolean;//default=false=no auto fit, true=fit to remaining vertical screen space - 01mar2021
    oautowidth      :boolean;//default=false
    oautofocus      :boolean;//default=false, true=set this control to be focused when form shows - 31mar2020
    osoftclose      :boolean;//default=false=use system default, true=always softclose such as a popup menu - 03apr2021
    owinname        :string;//default=<nil>, optional - set a window name -> e.g. "sys:options" or "sys:help" or "user1" etc - 14aug2020
    opagename       :string;//default=<nil>, set to a name e.g. "user" to show/hide using the "form.page:=<page name here>" option - 04apr2020
    oseph           :longint;//optional horizontal separation spacing, default=0 -> for use with tbasicscroll class of controls etc
    osepv           :longint;//optional vertical separation spacing, default=0   -> for use with tbasicscroll class of controls etc
    oalignvert      :boolean;//default=true=align control full width and vertically, else align by ominwidth/getalignwidth and horizontally - 22apr2020

    //.special colors
    ospbackcolor    :longint;//default=clnone, override background color - 17aug2020
    ospbackname     :string;//default=<nil>, override background color with a color name via "low__color()" - 19aug2020
    oinputcolorise  :tinputcolorise;

    //.override colors
    obackcolor      :longint;//default=clnone, override back color - 22mar2021
    otextcolor      :longint;//default=clnone, override text color - 22mar2021
    owinLdrCOLOR    :longint;//default=clnone, override system CORNER patch color - 07mar2022
    oframecolor     :longint;//default=clnone, override system frame color - 17mar2021
    oframecolor2    :longint;
    oborderstyle    :longint;//default=0=internal, 1=system "vibordersize", 2=50% of system "vibordersize" - 17aug2020
    owinresizeable  :boolean;//default=false
    oimagealign     :longint;//default=iaNormal
    otab            :string;//default=tbNone - 23feb2021

    //.tag support
    tag             :longint;
    tag2            :longint;
    tagstr          :string;//05aug2020
    tagobj          :tobject;//14aug2020

    //.optional  pointers - 15mar2021
    bc1             :tbasiccontrol;
    bc2             :tbasiccontrol;
    bc3             :tbasiccontrol;
    bc4             :tbasiccontrol;

    //own support
    ownlist         :townlist;
    ownid           :longint;//04apr2020

    //window support/menu/feedback support -> return codes for "clicked" menu item - 29aug2020
    ocode           :longint;
    ocode2          :string;
    otepcolor       :longint;//02mar2021
    otepcolor2      :longint;//04dec2024
    mkescape        :boolean;
    mkreturn        :boolean;

    //system info
    paintid         :longint;//used internally to trigger a paint reguest
    postpaintid     :longint;//increments after each repaint to screen -> handled internally by tbasicsystem - 05dec2024

    //create
    constructor create(xparent:tobject); virtual;
    constructor create2(xparent:tobject;xstart:boolean); virtual;
    destructor destroy; override;
    procedure destroychildren; virtual;//1st
    procedure destroyothers; virtual;//2nd
    procedure start;//04jul2021
    property stable:byte read istable;
    function xsetclientarea(a:twinrect):boolean; virtual;
    function xlimitsize:boolean; virtual;
    function xfindheight(xclientwidth:longint;var xheight:longint):boolean;
    function getalignheight(xclientwidth:longint):longint; virtual;
    function getalignwidth(xclientheight:longint):longint; virtual;
    function client:tbasiccontrol; virtual;
    procedure xresizer; virtual;//25feb2021
    function canautoheight:boolean; virtual;//26feb2021
    function setbc14(v1,v2,v3,v4:tbasiccontrol):boolean;//15mar2021
    procedure xfaster;//boost system performance for upto 5sec - 25jul2021
    property _mustpaint:boolean read imustpaint write imustpaint;//17nov2023

    //timer
    property timer:boolean read itimer write itimer;//start or stop calling of "_ontimer()"
    procedure xtimer;//30nov2025, 02sep2025

    //align
    procedure alignpaintnow__heightcheck(xalign,xpaint:boolean;xclientwidth:longint);//06jan2025
    procedure alignallnow;
    procedure alignnow;
    procedure parentalignnow;
    procedure xalign;//internal use only
    property xmustalign:boolean read imustalign write imustalign;

    //onvalue
    procedure xonvalue; virtual;

    //winstyle
    property winstyle:longint read iwinstyle write setwinstyle;
    function iswin:boolean;//true=control is a window
    function xwinfocused:boolean;
    function xwindow(var x:tbasiccontrol):boolean;//return our containing window
    function xwindow2(var x:tbasicscroll):boolean;//return our containing window
    function xwindowindex:longint;

    //paint
    procedure paintallnow;
    procedure paintnow; virtual;//17nov2023
    procedure parentpaintnow;
    procedure paintimmediate;//use sparingly - 09sep2021
    function xcanpaint:boolean;
    function xcanpaint_fast:boolean;//checks only the current layer -> assumes all previous layers have already been checked -> done for maximum speed - 05apr2020
    function xpaint:boolean;//internal use only
    property xmustpaint:boolean read imustpaint write imustpaint;
    function xmustpaintcount:longint;
    property painted:boolean read ipainted;
    property aligned:boolean read ialigned;
    function parentpainted:boolean;
    function parentaligned:boolean;

    //align+paint
    procedure alignpaintnow;//05oct2020
    procedure alignpaintallnow;//05oct2020

    //focus
    function focused:boolean;
    procedure setfocus; virtual;
    procedure setfocusforce;//19jul2025

    //showmenu
    function canshowmenu:boolean; virtual;
    procedure showmenu; virtual;
    procedure showmenu2(xstyle:string); virtual;
    procedure autoshowmenu;//detects when menu should be displayed and displays it - 15mar2021
    procedure autoshowmenu2(xstyle:string);
    function mustshowmenu:boolean;//detects when menu should be displayed

    //.fill
    procedure showmenuFill(xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string); virtual;
    property showmenuFill1:tmenufillevent read fshowmenuFill1 write fshowmenuFill1;
    property showmenuFillINT:tmenufillevent read fshowmenuFillINT write fshowmenuFillINT;
    property showmenuFill2:tmenufillevent read fshowmenuFill2 write fshowmenuFill2;

    //.click
    function showmenuClick(sender:tobject;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean; virtual;
    property showmenuClick1:ttoolbarevent2 read fshowmenuClick1 write fshowmenuClick1;
    property showmenuClickINT:ttoolbarevent2 read fshowmenuClickINT write fshowmenuClickINT;
    property showmenuClick2:ttoolbarevent2 read fshowmenuClick2 write fshowmenuClick2;

    //.onshowmenu -> optional external event handler
    property onshowmenu:tnotifyevent read fonshowmenu write fonshowmenu;

    //sync control values from/to system handlers
    function xfromsys(xname:string):boolean;
    function xfromprg(xname:string):boolean;
    function xfromprg2(xname:string;dvars:tvars8):boolean;//prgsettings -> control -> dvars (allows for filtering of value) - 25mar2021
    function xtosys(xname:string):boolean;
    function xtoprg(xname:string):boolean;
    function xfrom(sender:tbasiccontrol;xvars:tvars8;xname:string):boolean; virtual;
    function xto(sender:tbasiccontrol;xvars:tvars8;xname:string):boolean; virtual;

    //core
    property gui:tbasicsystem read igui;//never nil
    property coreindex:longint read icoreindex;//0..N only -> position within "gui.core[n]"
    property parent:tbasiccontrol read iparent write setparent;
    property parentcoreindex:longint read iparentcoreindex;//0..N and "-1" if a root control - 19mar2020
    property xvisible:boolean read ivisible write ivisible;
    property visible:boolean read ivisible write setvisible;
    property enabled:boolean read ienabled write setenabled;
    function visibletohost:boolean;//true=control is visible and all controls directly beneath to "host form" (control.parent=nil) are visible too
    function enabledtohost:boolean;//true=control is visible and all controls directly beneath to "host form" (control.parent=nil) are enabled too
    function havecontrol(x:tbasiccontrol):boolean;//04oct2024
    function rootparent:tbasiccontrol;//01aug2021
    function areatohost(da:twinrect):twinrect;
    function setbounds(x,y,w,h:longint):boolean;
    property clientarea:twinrect read iclientarea write setclientarea;
    property left:longint read getleft;
    property top:longint read gettop;
    function headheight:longint; virtual;//25jan2021
    function clientspace:twinrect;//rect(0,0,clientwidth-1,clientheight-1) - 11apr2020
    function clientinner:twinrect;
    function clientinner2(x:tbasiccontrol):twinrect; virtual;
    property clientwidth:longint read getclientwidth write setclientwidth;
    property clientheight:longint read getclientheight write setclientheight;
    property paintarea:twinrect read ipaintarea;//visible area of control to paint
    function yshift:longint;
    function xshift:longint;
    procedure ownidInc;
    function scrolling:boolean; virtual;//13jan2026

    //area handlers
    function xinside(x:tpoint):boolean;//local coordinates
    function xinside2(sx,sy:longint):boolean;//local coordinates
    function xinsideclientarea(x:tpoint):boolean;
    function xinsideclientarea2(sx,sy:longint):boolean;

    //local mouse support
    function mousedownxy:tpoint;
    function mousemovexy:tpoint;
    function mouseinside:boolean;
    function mouseinsideclientarea:boolean;
    function translatexy(a:tpoint):tpoint;//09jan2025
    function cursorxy:tpoint;//05may2025

    //fastdraw based graphics procs -> local draw support - 07jan2026
    procedure fsketchArea(const darea:twinrect;const dcol:longint);

    procedure fcolorMatrix(const darea:twinrect;const dround:boolean);

    procedure fframe(const darea:twinrect;const dsize,dcol1,dcol2,dpower255:longint;const dsparkle,dround:boolean);
    procedure fframeSimple(const darea:twinrect;const dsize,dcol,dpower255:longint;const dsparkle,dround:boolean);

    procedure foutlineArea(const darea:twinrect;const dcol:longint;const dround:boolean);
    procedure foutlineArea2(const darea:twinrect;const dcol,dpower255:longint;const dsparkle,dround:boolean);

    procedure ffillOUTSIDE(dx,dy,dw,dh,dcol:longint);//26mar2026

    procedure ffillArea(const darea:twinrect;const dcol:longint;const dround:boolean);
    procedure ffillArea2(const darea:twinrect;const dcol,dpower255:longint;const dround:boolean);

    procedure fshadeArea(const darea:twinrect;const dcol1,dcol2:longint;const dround:boolean);
    procedure fshadeArea2(const darea:twinrect;const dcol1,dcol2,dcol3,dcol4,dsplice100,dpower255:longint;const dround:boolean);

    procedure fshadeOutlineArea(const darea:twinrect;const dcol1,dcol2,dcol3,dcol4,dsplice100,dpower255:longint;const dsparkle,dround:boolean);

    procedure finvertArea(const darea:twinrect;const dround:boolean);
    procedure finvertCorrectedArea(const darea:twinrect;const dround:boolean);

    procedure ftext(const dbackRef:longint;const darea:twinrect;const dx,dy,dcol:longint;const dtab,dtext:string;const dfont:longint32;const denabled:boolean);//20feb2026
    procedure ftext2(const dbackRef:longint;const darea:twinrect;const dx,dy,dcol,dpower255:longint;const dtab,dtext:string;const dfont,dfeather4:longint32;const denabled,dround:boolean);//20feb2026

    procedure ftep(const dindex,dx,dy,dcol:longint;const denabled:boolean);
    procedure ftep1(const dindex,dx,dy,dcol,dpower255:longint;const denabled:boolean);
    procedure ftep2(const dindex,dx,dy,dcol1,dcol2,dcol3,dcol4,dpower255:longint;const denabled:boolean);

    procedure fdraw(const d:tobject;const dx,dy,dcol,dpower255:longint;const denabled:boolean);
    procedure fdraw2(const d:tobject;const dx,dy,dcol1,dcol2,dcol3,dcol4,dpower255:longint;const denabled:boolean);
    procedure fdraw3(const d:tobject;const sa:twinrect;const dx,dy,dw,dh,dcol,dpower255,dfeather4:longint;const dmirror,dflip,denabled:boolean);
    procedure fdraw4(const d:tobject;const sa:twinrect;const dx,dy,dw,dh,dcol1,dcol2,dcol3,dcol4,dpower255,dfeather4:longint;const dmirror,dflip,denabled:boolean);

    //system id
    property id:longint read iid;//unique for each and every control system wide

    //area id
    property aid:longint read iaid;//area id -> changed each time control changes position or size or both
    procedure ainc;

    //information
    property caption:string read icaption write setcaption;
    function info:pvirtualinfo;
    function rounded:boolean;
    function xcornerMode:longint32;//13jan2026
    function xcornerCode:longint32;//05jan2026
    function info_cs:twinrect;
    function info_bs:longint;
    function info_ci:twinrect;
    function findback:longint;//find background color - 25feb2021
    procedure findbackRound(var xback:longint;var xround:boolean);
    function findtext:longint;//find text color - 22mar2021
    function findframe:longint;//find frame color - 17mar2021
    function findframe2:longint;//find frame2 color - 17mar2021
    function infovars(var xinfo:tclientinfo):boolean;//17may2025
    function infovars2(var xinfo:tclientinfo;xnormal:boolean):boolean;//17may2025
    property normal:boolean read inormal write setnormal;
    function mousex:longint;
    function mousey:longint;
    function mousexy:tpoint;
    property bordersize:longint read ibordersize write setbordersize;
    function findbordersize:longint; virtual;

    //help support
    property help:string read ihelp write ihelp;
    property help2:string read ihelp2 write ihelp2;//optional - replaces "help"
    property subhelp:string read isubhelp write isubhelp;
    property subhelp2:string read isubhelp2 write isubhelp2;//optional - replaces "subhelp"
    property helpline:string read gethelpline;

    //hint support
    property hint:string read ihint write ihint;//1) set to "*" (default) to use help as hint, 2) set to nil to disable hint, 3) set to custom hint
    property hintline:string read gethintline;
    procedure nohint;

    //new control makers
    function ntea(xcap,xhelp:string):tbasictea;
    function ndebug:tbasicdebug;//04feb2025

    //tbasicmenu.title/label mimics
    function mtitle(xcap,xhelp:string):tmenutitle;//24may2025
    function mtitleplain(xcap,xhelp:string):tmenutitle;//24may2025
    function mlabel(xcap,xhelp:string):tmenutitle;
    function mlabelplain(xcap,xhelp:string):tmenutitle;

    //children makers
    function ntitle(xlarge:boolean;xcap,xhelp:string):tbasictitle;
    function ntitle2(xlarge,xlargeheight:boolean;xcap,xhelp:string):tbasictitle;
    function ntitlebar(xlarge:boolean;xcap,xhelp:string):tbasictoolbar;
    function ntitlebar2(xlarge,xright:boolean;xcap,xhelp:string):tbasictoolbar;
    function ncontrol:tbasiccontrol;
    function nimgview:tbasicimgview;//11dec2024
    function nlabel(xcap,xhelp:string):tbasictitle;
    function ngrad:tbasicgradient;//19aug2024
    function njump(xcap,xhelp:string;xpos,xlen:longint):tbasicjump;
    function mint(xcap,xhelp:string;xmin,xmax,xdef,xval:longint):tsimpleint;//03jun2025
    function mintb(xcap,xhelplabel,xhelpbar:string;xmin,xmax,xdef,xval:longint):tsimpleint;//03jun2025
    function mint2(xcap,xhelp:string;xmin,xmax,xdef,xval:longint;xbackname:string):tsimpleint;
    function mint2b(xcap,xhelplabel,xhelpbar:string;xmin,xmax,xdef,xval:longint;xbackname:string):tsimpleint;
    function mint3(xcap,xhelp:string;xmin,xmax,xdef,xval:longint;xbackname,xloadfromname:string):tsimpleint;
    function mint3b(xcap,xhelplabel,xhelpbar:string;xmin,xmax,xdef,xval:longint;xbackname,xloadfromname:string):tsimpleint;
    function mint4(xcap,xhelplabel,xhelpbar:string;xmin,xmax,xdef,xval:longint;xbackname,xloadfromname:string):tsimpleint;
    function nset(xcap,xhelp:string;xdef,xval:longint):tbasicset;
    function nsel(xcap,xhelp:string;xdef:longint):tbasicsel;
    function mmidivol(xcap,xhelp:string):tsimpleint;//02jul2025
    function mwavevol(xcap,xhelp:string):tsimpleint;//02jul2025
    function nmidi(xcap,xhelp:string):tbasicsel;//05mar2022
    function nwave(xcap,xhelp:string):tbasicsel;//05mar2022
    function mmiditranspose(xcap,xhelp:string):tsimpleint;//02jul2025
    function nsel3(xcap,xhelp:string;xdef:longint;xloadfromname:string):tbasicsel;
    function nimgexts(xcap,xhelp:string):tbasicimageexts;//21dec2024
    function nedit(xcap,xhelp:string):tbasicedit;
    function nedit2(xcap,xhelp:string;xvert:boolean):tbasicedit;
    function ndropstatic(xhelp:string;xtep:longint):tbasicedit;
    function npass(xcap,xhelp:string):tbasicedit;
    function ncolor(xcap,xhelp:string):tbasiccolor;
    function ncolor1(xcap,xhelp:string;xuse32:boolean):tbasiccolor;
    function ncolor2(xcap,xhelp:string;xvert:boolean;hsp:longint):tbasiccolor;
    function ncolor3(xcap,xhelp:string;xvert:boolean;hsp:longint;xuse32:boolean):tbasiccolor;
    function nscrollbar(xhelp:string;xvert:boolean):tbasicscrollbar;
    function nscroll(xhelp:string):tbasicscroll;//06oct2020
    function ntoolbar(xhelp:string):tbasictoolbar;//29may2021
    function ntoolbar_buttons(xhelp:string):tbasictoolbar;//29may2021
    function ncols:tbasiccols;//columns - 06oct2020
    function ncolors:tbasiccolors;
    function nbwp(const xhelp:string;xdata:tstr8):tbasicbwp;//text box
    function nbwp2(const xhelp:string;xdata:tstr8;xwrap:longint;xrows,xautoheight:boolean):tbasicbwp;//17mar2021
    function nbwp3(const xhelp:string;xdata:tstr8;xwrap:longint;xrows,xautoheight,xretaindata:boolean):tbasicbwp;//17mar2021
    function nbwp4(const xhelp:string;xdata:tstr8;xwrap:longint;xrows,xautoheight,xretaindata,xtransform,xwebimages:boolean):tbasicbwp;//15feb2026
    function nbwp5(const xhelp:string;xdata:tstr8;xwrap:longint;xrows,xautoheight,xretaindata,xtransform,xwebimages,xviewurl,xusemake:boolean;xmake__formatlevel,xmake__useonefont:longint):tbasicbwp;//15feb2026

    function nbwpbar(xbox:tbasicbwp;xsysbox:boolean):tbwpbar;
    function nmenu(xcap,xhelp:string):tbasicmenu;
    function npoplist(xcap,xhelp:string;xlistdata:tstr8):tbasicmenu;
    function nlist(xcap,xhelp:string;xlistdata:tstr8;xrowcount:longint):tbasicmenu;
    function nlist3(xcap,xhelp:string;xlistdata:tstr8;xrowcount:longint;xloadfromname:string):tbasicmenu;
    function nlistx(xcap,xhelp:string;xcount,xrowcount:longint;xongetitem:tbasicmenu_getitem):tbasicmenu;
    function nlistx3(xcap,xhelp:string;xcount,xrowcount:longint;xongetitem:tbasicmenu_getitem;xloadfromname:string):tbasicmenu;
    function nnav:tbasicnav;//22sep2020
    function ncolormatrix:tbasiccolormatrix;//26feb2021
    function ncolormixer:tbasiccolormixer;//05sep2025
    function nsetcolor:tbasicsetcolor;//27feb2021
    function nsetcolor2(xuse32,xhead:boolean):tbasicsetcolor;//17nov2023
    function nbreak(xheight:longint):tbasicbreak;

    //events
    procedure _ontimer(sender:tobject); virtual;
    procedure _onpaint(sender:tobject); virtual;
    procedure _onalign(sender:tobject); virtual;
    function  _onshortcut(sender:tobject):boolean; virtual;
    function  _onnotify(sender:tobject):boolean; virtual;
    procedure _onfocus(sender:tobject); virtual;

    //special events
    property onalign:tnotifyevent read fonalign write fonalign;
    property onvalue:tnotifyevent read fonvalue write fonvalue;
    property onpaint:tnotifyevent read fonpaint write fonpaint;
    property onnotify:tsystemnotify read fonnotify write fonnotify;
    property ontimer2:tnotifyevent read fontimer2 write fontimer2;
    property onfindheight:tonfindheight read fonfindheight write fonfindheight;

    //offloader support - 07mar2021
    property xoffloading:boolean read ioffloading write ioffloading;//used to turn off some internal procs/functions that are not required during offloading -> purely optional - 07mar2021

    //.triggers
    function xoff_toolbaradd(x:tbasictoolbar):boolean;
    function xoff_toolbarsync(x:tbasictoolbar):boolean;
    function xoff_toolbarevent(x:tbasictoolbar):boolean;

    //.code handlers
    function _xoff_toolbaradd(x:tbasictoolbar):boolean; virtual;
    function _xoff_toolbarsync(x:tbasictoolbar):boolean; virtual;
    function _xoff_toolbarevent(x:tbasictoolbar):boolean; virtual;

    //accept support -> drag and drop - 18jun2021
    property onaccept:tonacceptevent read fonaccept write fonaccept;
    function canaccept:boolean;
    function accept_passthru(sender:tobject;xfolder,xfilename:string;xindex,xcount:longint):boolean;

    //idle tracking support - 21feb2022
    procedure notidle;
    function idletime:comp; virtual;

    //automation support
    procedure xwound_mousevert(xmaxtime:longint;xforce:boolean);
    procedure xwound_mousevert2(xmaxtime:longint;xforce,xinvert:boolean);
    procedure xwound_mousevert3(xmaxtime:longint;xforce,xinvert,xvertical:boolean);
    function xwound_mustpaint(spos,xrowsperpaint:longint;var dpos,ddir:longint):boolean;
    function xwound_mustpaint2(spos,xrowsperpaint:longint):longint;
    function xwound_off:boolean;
    procedure xwound_autooff(spos,xdir,xmin,xmax:longint);
    function xwound_finddir(xtime:longint):longint;
    function xwound_dirmatch(xtime1,xtime2:longint):boolean;
    procedure xwound_wheel(xtimems:longint);

    //-- shared handlers - 03dec2023 -------------------------------------------
    procedure make__backgroundhead; virtual;//?????????????old
    procedure make__backgroundbase; virtual;
    procedure make__normal; virtual;

    procedure background__title(da:twinrect;xback:longint;xround:boolean);
    procedure background__title2(da:twinrect;xback:longint;xflatback,xround:boolean);
    procedure background__toolbar(da:twinrect;xback,xback2:longint;xround:boolean);
    procedure background__toolbar2(da:twinrect;xback,xback2:longint;xflatback,xround:boolean);//08mar2025: fixed corner color oversight

   end;

{tbasicimgview}
   tbasicimgview=class(tbasiccontrol)
   private

    ifadetimer,ianimatetimer1,ianimatetimer2,itimer100:comp;
    inew32,iimg32,ibuf32:trawimage;
    inewfilenameREF,inewfilename:string;
    inewimagedata:tstr8;
    imustmode,ilastid,iid,iloadid,ibackcolor,ifillstyle,ifadespeed,ifadepower:longint;
    ishown,icanevent,ifillback,ianimate,icountcolors,iworking,iloading:boolean;
    fonevent:tnotifyevent;

    //image info
    iwidth:longint;
    iheight:longint;
    idelay:longint;
    ibpp:longint;
    icells:longint;
    icolors:longint;
    ibytes:comp;
    ifilename:string;
    iinfostr:string;

    procedure xincid;//settings id
    procedure xincloadid;//load id
    procedure setbackcolor(x:longint);
    procedure setfillstyle(x:longint);
    procedure setfadespeed(x:longint);
    procedure setcountcolors(x:boolean);
    procedure setanimate(x:boolean);
    procedure setfillback(x:boolean);
    function xcanload:boolean;
    procedure xload(xuseFilename,xuseData:boolean);
    procedure xkeeplast;
    function getimage32:trawimage;
    function ximgok(s:tobject):boolean;
    procedure xevent;//12dec2024
    procedure xrender__dual(sbits,sw,sh,sr,sg,sb,sa:longint;srows:pcolorrows24;a,b:tobject;fa,fb,da,db,da2,db2:twinrect;a255,b255,aa255,bb255,atrans,btrans,atc,btc:longint);

   public

    //create
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;//28may2021, 26apr2021
    function _onnotify(sender:tobject):boolean; override;

    //information
    property loading:boolean read iloading;
    function working:boolean;
    property id:longint read iid;//settings id -> increments each time a setting is changed
    property loadid:longint read iloadid;//load id -> increments each time a new image is loaded/attemped to load
    property fillstyle:longint read ifillstyle write setfillstyle;//0..vfsMax
    property backcolor:longint read ibackcolor write setbackcolor;
    property fadespeed:longint read ifadespeed write setfadespeed;//range: 0-100, 0=instant (no delay), 1=slow, 5=moderate, 100=fastest
    property countcolors:boolean read icountcolors write setcountcolors;
    property animate:boolean read ianimate write setanimate;
    property mustmode:longint read imustmode write imustmode;//-1=user clicked left side of image, 1=user clicked right side of image, 0=no useful click info
    property fillback:boolean read ifillback write setfillback;
    property shown:boolean read ishown;//default=true=last image loaded via loadfromfile has been loaded and shown in full, false=image still being processed
    property image32:trawimage read getimage32;//read only
    property fadepower:longint read ifadepower;

    //.image information
    property width:longint read iwidth;
    property height:longint read iheight;
    property delay:longint read idelay;
    property bpp:longint read ibpp;
    property colors:longint read icolors;
    property cells:longint read icells;
    property bytes:comp read ibytes;//file size on disk
    property filename:string read ifilename;
    property infostr:string read iinfostr;
    function findinfob(xname,xdefval:string):string;
    function findinfo(xname,xdefval:string;var xvalue:string):boolean;

    //io
    procedure loadfromfile(x:string;xuseai:boolean);
    procedure loadfromdata(x:pobject;xuseai:boolean);

    //events
    property onevent:tnotifyevent read fonevent write fonevent;//triggered once image has been loaded and fully displayed on the screen - 12dec2024

    //other
    procedure xrenderto(dbits,dw,dh:longint;drows:pcolorrows24);

   end;

{tbasichelp}
   tbasichelp=class(tbasiccontrol)
   private

    ipostime,itimer250:comp;
    ishowhelp:boolean;
    ideftext,itext,itextref,iinforef:string;
    iimg,ipos,itextid:longint;

    procedure settext(x:string);//14may2025
    function paintscroll:boolean;
    procedure setshowhelp(x:boolean);
    procedure xsync;

   public

    //create
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;
    function getalignheight(xclientwidth:longint):longint; override;

    //information
    property showhelp           :boolean  read ishowhelp      write setshowhelp;
    property text               :string   read itext          write settext;
    property deftext            :string   read ideftext       write ideftext;

   end;

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//nnnnnnnnnnnnnnnnnnn
{tbasicnav}
   tbasicnav=class(tbasiccontrol)
   private
    ivalueinlist_style,ireloadid,ifolderid,ifavlimit,isortstyle,istyle,inavcount,ifoldercount,ifilecount,itotalcount:longint;
    itimer100,itimer250:comp;
    ifav,ilist:tbasicmenu;//in dynamic list mode - 28sep2020
    iname,ifilter:tbasicedit;
    iaction:tbasicimageexts;
    ipreviewbox:tbasicimgview;
    ipreviewlabel:tmenutitle;
    inamelabel,ifilterlabel:tbasiccontrol;
    ifavlabel,ibar,ibut:tbasictoolbar;
    ivalueinlist,ilastpreviewfile,iprevnextcode,ifavfolder,ireloadref,ilastmask,ilastemask,ilastemask_minmax,ifolderidREF,ilistfolder,imustfolder,imustname:string;
    ihisname:string;
    isyspreview,ipreview,icanpreview,ilastpreview,imustreload:boolean;
    ilistcore:tstr8;
    ifavcore:tdynamicstring;//10mar2021
    ifavteps:tdynamicinteger;//14apr2021
    fonmodifyitem:tnavmodifyitem;
    fonclick:tnotifyevent;
    //.filter support
    findex,fcount:longint;
    fcap:array[0..99] of string;//label e.g. "Bitmap (bmp)|Jpeg Image (jpg/jpeg)"
    fext:array[0..99] of string;//extension e.g. "BMP" or "JPG;JPEG"
    fmsk:array[0..99] of string;//mask e.g. "*.bmp;*.jpg;*.jpeg"
    ftep:array[0..99] of longint;//store tep for each ext or group of exts (e.g. support for teps for "bcs", pebcs and feAllDocs(a group of document types)) - 10mar2021
    procedure setstyle(x:longint);
    function __ongetitem(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;
    function __ongetitem2(sender:tobject;xdisplayonly:boolean;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;
    procedure __onclick2(sender:tobject;xcmd:string);
    procedure __onclick(sender:tobject);
    procedure filter__onclick(sender:tobject);
    procedure setfilterlist(x:string);//18sep2025
    function getfilterlist:string;
    function getfilter:string;
    procedure setfilter(x:string);
    procedure setfilterfromfilename(x:string);
    function getfilterindex:longint;
    procedure setfilterindex(x:longint);
    procedure setvalue(x:string);
    function getvaluelist(xindex:longint):string;//28sep2022
    function getvaluelist2(xindex,xforcestyle:longint):string;//28sep2022
    function getvalue:string;//06apr2021
    function getvaluestyle:longint;
    function getvalueEXT:string;//12jan2022
    function getfolder:string;
    procedure setfolder(x:string);
    procedure setsortstyle(x:longint);
    function getdownindex:longint;
    procedure setdownindex(x:longint);
    function xfiltername(xnewname:string;xaddfilterext:boolean):string;
    procedure findex_tep;
    function xenhancednames(x:string):string;
    function getitemindex:longint;
    procedure setitemindex(x:longint);
    function getsettings:string;
    procedure setsettings(x:string);
    function xvalueinlist(var xvalue:string;var xstyle:longint):boolean;
    function getaction:string;
    //fav support
    procedure loadfav;
    function savefav(xdata:tstr8):boolean;
    procedure addfav(xfolder:string);
    function xfavfolder:string;
    //his support
    procedure sethisname(x:string);
    procedure xhisadd(xval:string;xpos,xitemindex:longint;xstorev12:boolean);//22mar2021
    //showmenu support
    procedure xshowmenuFill1(sender:tobject;xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
    procedure xshowmenuFill2(sender:tobject;xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
    procedure xshowmenuFill(sender:tobject;xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
    function xshowmenuClick1(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
    function xshowmenuClick2(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
    function xshowmenuClick(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
   public
    //options
    ocommonfolder:string;//default=<nil>
    omasklist:string;
    oemasklist:string;
    oretainpos:boolean;//default=true=keeps vertical position during reloads
    ofindname:boolean;//default=false, true=selects name from list when value is a full filename - 19dec2021
    ocansort:boolean;//default=true=allow user to change sort style - 12jan2022
    onumber:boolean;//default=false, true=number only the files list section - 20mar2022
    //.minmax range enforcer - 27sep2022
    ominsize:comp;
    omaxsize:comp;
    ominmax_emasklist:string;//files to be excluded from the "ominsize..omaxsize" range check - 27sep2022
    ohead:boolean;//default=false, true=use window head as toolbar - 12jan2025
    //create
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;
    procedure _onalign(sender:tobject); override;
    function xfrom(sender:tbasiccontrol;xvars:tvars8;xname:string):boolean; override;
    function xto(sender:tbasiccontrol;xvars:tvars8;xname:string):boolean; override;
    function xcmd(xcode:longint;xcode2:string;xtepcolor:longint):boolean;
    procedure make__backgroundhead; override;//03dec2023
    //change ids - 27sep2022
    property folderID:longint read ifolderid;//increments each time a new folder is loaded - 27sep2022
    property reloadID:longint read ireloadid;//increments each time nav is reloaded - 20aug2024
    //information
    property settings:string read getsettings write setsettings;//direct read/write of settings as a single line of text - 20aug2024
    property sortstyle:longint read isortstyle write setsortstyle;
    property style:longint read istyle write setstyle;//bnNil .. bnMax
    property filterlist:string read getfilterlist write setfilterlist;
    property filter:string read getfilter write setfilter;
    property filterfromfilename:string read getfilter write setfilterfromfilename;//18jun2021
    property filterindex:longint read getfilterindex write setfilterindex;
    property folder:string read getfolder write setfolder;
    function folderpending:boolean;//detects if folder is waiting to be set/updated - 14jul2025
    function foldervalue:string;//returns the pending "folder" first, then the actual folder that is set - 14jul2025
    property valuelist[xindex:longint]:string read getvaluelist;//28sep2022
    property value:string read getvalue write setvalue;
    property valuestyle:longint read getvaluestyle;//e.g. nltFile, nltFolder, nltNav, nltTitle etc - 22mar2021
    property valueEXT:string read getvalueext;//works for "nltFile" only and returns the file extension in LOWERCASE - 12jan2022
    function selectedfolder:string;//current item's folder "filepath" - 07apr2021
    property navcount:longint read inavcount;
    property foldercount:longint read ifoldercount;
    property filecount:longint read ifilecount;
    property totalcount:longint read itotalcount;
    property downindex:longint read getdownindex write setdownindex;
    function findinfo(var xselstart,xselcount,xdownindex,xnavindex,xfolderindex,xfileindex,xnavcount,xfoldercount,xfilecount:longint;var xisnav,xisfolder,xisfile:boolean):boolean;
    function findinfo2(xindex:longint;var xselstart,xselcount,xdownindex,xnavindex,xfolderindex,xfileindex,xnavcount,xfoldercount,xfilecount:longint;var xisnav,xisfolder,xisfile:boolean;var xsize:comp;var xvalue:string;xfindvalue:boolean):boolean;
    procedure findinfoBrief(var xisnav,xisfolder,xisfile:boolean);
    property favfolder:string read ifavfolder write ifavfolder;//optional folder to allow user to add to fav upon clicking the link "Add" - 10mar2021
    property itemindex:longint read getitemindex write setitemindex;//23mar2022
    //.direct access to selected list item -> independent of display style
    property valueinlist:string read ivalueinlist;
    property valueinlistStyle:longint read ivalueinlist_style;
    //showmenu
    function canshowmenu:boolean; override;
    procedure showmenu; override;//20mar2022
    //history support
    property hisname:string read ihisname write sethisname;//used to store folder history via system history support - default=<nil>=off
    //.prev
    function canprev:boolean;
    function prev:boolean;
    //.next
    function cannext:boolean;
    function next:boolean;
    //.fav - show fav window
    function popfav:string;
    //.preview
    property preview:boolean read ipreview write ipreview;
    property canpreview:boolean read icanpreview write icanpreview;//default=true, controls whether preview link on toolbar and preview can in fact be shown even if set to preview this overrides - 22may2022
    property syspreview:boolean read isyspreview write isyspreview;//default=false, true=read/write "preview" state from internal system vars - 22may2022
    //workers
    procedure reload;
    //makers
    function makenil:tbasicnav;
    function makefav:tbasicnav;
    function makenav:tbasicnav;
    function makefolder:tbasicnav;
    function makefolder2:tbasicnav;//20jul2024: folder and show files
    function makeopen:tbasicnav;
    function makesave:tbasicnav;
    function makefavlist:tbasicnav;
    function makenavlist:tbasicnav;//use this for a standard filebox list - 27sep2022
    function makenavlist2:tbasicnav;
    function makenamelist:tbasicnav;
    function xautoclose(x:boolean):tbasicnav;
    //.support
    function xbar:tbasictoolbar;
    function xbut:tbasictoolbar;
    function xfav:tbasicmenu;
    function xfavlabel:tbasictoolbar;
    function xpreviewbox:tbasiccontrol;//22may2022
    function xpreviewlabel:tbasiccontrol;//24jan2025, 22may2022
    function xlist:tbasicmenu;
    function xname:tbasicedit;
    function xnamelabel:tbasiccontrol;
    function xfilter:tbasicedit;
    function xfilterlabel:tbasiccontrol;
    function xaction:tbasicimageexts;//21dec2024
    function xfocusname:boolean;//11feb2023
    procedure click__list;//25jan2025
    //.special value handlers
    function xvaluefile(xdef:string):string;
    //action
    property action:string read getaction;
    //home
    function canhome:boolean;
    procedure home;
    //offloaders
    function _xoff_toolbaradd(x:tbasictoolbar):boolean; override;
    function _xoff_toolbarsync(x:tbasictoolbar):boolean; override;
    function _xoff_toolbarevent(x:tbasictoolbar):boolean; override;
    //idletime - custom
    function idletime:comp; override;//21feb2022
    //events
    property onclick:tnotifyevent read fonclick write fonclick;
    property onmodifyitem:tnavmodifyitem read fonmodifyitem write fonmodifyitem;
   end;

{tbasicbwp}
   tbasicbwp=class(tbasiccontrol)
   private

    icore:ttextcore;
    iv,ih:tbasicscrollbar;
    islowdownref,itimersync:comp;
    imustpos,imustpos2,imustscrollv_px,imustscrollv,imustscrollh,itimersync_fastcount,imleft,imright,imtop,imbottom:longint;
    iusepagecolor,ibuildingcontrol:boolean;
    iref:string;
    irevertdata:tstr8;
    fonact:tsimplestringeventb;

    //.wordcount support
    iwordcount,inewcount,inewpos,inewid:longint;
    inewword:boolean;

    procedure setpos(x:longint);
    function getpos:longint;
    procedure setposh(x:longint);
    function getposh:longint;
    function getposc:longint;
    procedure setposc(x:longint);
    function getposc2:longint;
    procedure setposc2(x:longint);
    procedure _onpos(sender:tobject);
    procedure setreadonly(x:boolean);
    function getreadonly:boolean;
    procedure setshowcursor(x:boolean);
    function getshowcursor:boolean;
    procedure setusepagecolor(x:boolean);
    function getroundstyle:longint;
    procedure setroundstyle(x:longint);
    procedure setwrap(x:longint);//0=no wrap, 1=to window, 2=to page (default)
    function getwrap:longint;
    procedure setwrapreadonly(x:boolean);//true=prevents wrapstyle from changing during "ioset()" operations - 12mar2021
    function getwrapreadonly:boolean;
    procedure xsync;
    procedure setsyscols(x:boolean);
    function getsyscols:boolean;
    function getundoenabled:boolean;
    procedure setundoenabled(x:boolean);
    procedure _onarrow(sender:tobject;var xmoveval:longint);
    procedure setlinespacing(x:longint);
    function getlinespacing:longint;
    function getcanspell:boolean;
    procedure setcanspell(x:boolean);
    procedure setstyle(x:longint);
    function getstyle:longint;
    function xvaluefromhost32(const n:string):longint32;//25mar2026

   public

    //options
    orows:boolean;//default=false, true=draw text with alternating row color - 12mar2021
    omenustyles:boolean;//default=false, true=show style options in menu - 19dec2021
    ocopystyles:boolean;//default=false=hide, true=show copy enhanced etc - 18jun2022
    vsmooth:boolean;//default=true=smooth scroll by pixels, false=older style, scroll by lines - 21jun2022
    olivewordcount:boolean;//default=false, true=wordcounts in background in realtime - 05feb2023

    //create
    constructor create(xparent:tobject); override;
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    function _onnotify(sender:tobject):boolean; override;
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;
    procedure _onalign(sender:tobject); override;
    function _onshortcut(sender:tobject):boolean; override;//09dec2024: fixed ctrl+c block when readonly, 28aug2024: fixed F3/F4 block when oreadonly=true
    procedure syncdef;//06oct2020
    procedure showmenuFill(xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string); override;
    function showmenuClick(sender:tobject;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean; override;
    procedure xwordcoretimer(xsyncnow:boolean);
    //information
    property core:ttextcore read icore;
    property roundstyle:longint read getroundstyle write setroundstyle;
    property oreadonly:boolean read getreadonly write setreadonly;
    property oshowcursor:boolean read getshowcursor write setshowcursor;
    property ousepagecolor:boolean read iusepagecolor write setusepagecolor;
    property vpos:longint read getpos write setpos;
    property hpos:longint read getposh write setposh;
    property cpos:longint read getposc write setposc;
    property cpos2:longint read getposc2 write setposc2;
    property wrap:longint read getwrap write setwrap;
    function line:longint;//current line 1..N
    function column:longint;
    function line_column(var xline,xcolumn:longint):boolean;
    function pages:longint;
    function page:longint;
    function maxline:longint;
    property wrapreadonly:boolean read getwrapreadonly write setwrapreadonly;
    property syscols:boolean read getsyscols write setsyscols;
    property linespacing:longint read getlinespacing write setlinespacing;
    property style:longint read getstyle write setstyle;//wrap: 0=none, 1=window, 2=page, 3=page + 2x, 4=manuscript
    //scrollto
    procedure vscrolltopos(xpos:longint);
    procedure scrollto(_vpos_px,_vpos,_hpos,_pos,_pos2:longint;xforcewrapall:boolean);
    //margin
    procedure margin(xl,xt,xr,xb:longint);
    property mleft:longint read imleft;
    property mtop:longint read imtop;
    property mright:longint read imright;
    property mbottom:longint read imbottom;
    //revert support
    procedure revertinit(xdata:tstr8;xenable:boolean);
    //spell
    property canspell:boolean read getcanspell write setcanspell;
    procedure spell;
    //find
    function canfind:boolean;
    procedure findpop;
    procedure find;
    //live wordcount
    property wordcount:longint read iwordcount;//approxmately only
    //io
    function ioget(xdata:tstr8;xformat:string):boolean;
    function ioset(xdata:tstr8):boolean;
    function ioset2(xdata:tstr8;xvpos_px,xvpos:longint):boolean;
    function ioset3(xdata:tstr8;xvpos_px,xvpos,xhpos,xpos,xpos2:longint;xtransform,xwebimages:boolean):boolean;
    function ioset4(xdata:tstr8;const dformat:string;xvpos_px,xvpos,xhpos,xpos,xpos2:longint;xtransform,xwebimages:boolean):boolean;//17feb2026
    //.txt
    function iogettxt(xdata:tstr8):boolean;
    function iosettxt(xdata:tstr8):boolean;
    //.bwd
    function iogetbwd(xdata:tstr8):boolean;
    function iosetbwd(xdata:tstr8):boolean;
    //.bwp
    function iogetbwp(xdata:tstr8):boolean;
    function iosetbwp(xdata:tstr8):boolean;
    //.htm
    function iogethtm(xdata:tstr8):boolean;
    function iosethtm(xdata:tstr8):boolean;
    //edit support
    //.can
    function xcan(x:string):boolean;
    function canundo:boolean;
    function canredo:boolean;
    function cancut:boolean;
    function cancopy:boolean;
    function cancopyall:boolean;
    function canpaste:boolean;
    function canpastereplace:boolean;
    function candeleteall:boolean;//has undo
    function canclearall:boolean;//no undo
    property undoenabled:boolean read getundoenabled write setundoenabled;
    //.act
    function xact(x:string;var e:string):boolean;
    //.other
    procedure undoon;
    procedure undooff;
    procedure undoclear;
    //transformers
    function makereadonly:tbasicbwp;//17mar2025
    function makeviewonly:tbasicbwp;
    //makers - 12jun2022
    //.vifontsize + onefontname="$fontname" - 21jun2022
    procedure makeplaintext1;
    procedure maketxt1;
    procedure makebwd1;
    procedure makebwp1;
    //.vifontsize2 + onefontname="$fontname2" - 21jun2022
    procedure makeplaintext2;
    procedure maketxt2;
    procedure makebwd2;
    procedure makebwp2;
    procedure makepanel2;//27aug2025
    //.full version (all fonts, styles, images etc) -21jun2022
    procedure makebwpFull;
    procedure makebwpFull2;//14nov2023
    procedure makexxx(xformatlevel:longint;xuseonefont:longint;xviewurl:boolean);//31mar2025, 12jun2022
    //events
    property onact:tsimplestringeventb read fonact write fonact;//19jun2022
   end;


{tbwpbar}
   tbwpbar=class(tbasiccontrol)
   private

    itimer250:comp;
    iref:string;
    ibox:tbasicbwp;
    imustWrapStyle,ihoverindex,idownindex,icount:longint;
    iarea:array[0..19] of twinrect;
    ipert:array[0..19] of longint;
    icap:array[0..19] of string;
    //index refs
    iname,isize,icolor,inormal,ibold,iitalic,istrikeout,iunderline,ihighlight,ileft,icenter,iright,iwrap:longint;

    procedure setbox(x:tbasicbwp);
    function xnew(xcap:string;xpert:longint):longint;

   public

    //options
    osysbox:boolean;//default=false=use specified box, true=use currently set box
    ocancolor:boolean;
    ocanalign:boolean;
    ocanname:boolean;
    ocansize:boolean;
    opassiveWrap:boolean;//true=triggers proc "mustWrapStyle" to be used, false=directly adjusts textbox wrap style - 01mar2026

    //create
    constructor create(xparent:tobject);
    constructor create2(xparent:tobject;xstart:boolean); virtual;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;
    function _onnotify(sender:tobject):boolean; override;
    function getalignheight(xclientwidth:longint):longint; override;//07sep2020
    procedure showmenuFill(xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string); override;
    function showmenuClick(sender:tobject;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean; override;

    //box
    property box:tbasicbwp read ibox write setbox;
    function findbox:tobject;
    function findbox2:tobject;
    function findindex(x,y:longint):longint;
    function mustWrapStyle(var xnewWrapStyle:longint32):boolean;//01mar2026

   end;

{tbasiccolor}
   tbasiccolor=class(tbasiccontrol)
   private
    icolor,ishadecolor:longint;
    foncolor:tlongintevent;
    ishadearea:twinrect;
    iuse32,ishadeused:boolean;
    ishadelist:tdynamicinteger;
    procedure setcolor(x:longint);
    procedure xdomenu(xcode2:string);
    procedure setcolor24(x:longint);
    function getcolor24:longint;
    function xshadecolor24:longint;//03feb2024
   public
    //options
    opopcolor:boolean;//default=true=click to show colordlg
    oshaderange:boolean;
    osleek:boolean;//default=false
    //create
    constructor create(xparent:tobject;xcaption:string);
    constructor create2(xparent:tobject;xstart:boolean;xcaption:string); virtual;
    destructor destroy; override;
    function getalignheight(xclientwidth:longint):longint; override;
    function getalignwidth(xclientheight:longint):longint; override;
    //information
    property color:longint read icolor write setcolor;
    property color24:longint read getcolor24 write setcolor24;
    property use32:boolean read iuse32 write iuse32;
    //workers
    procedure showmenu; override;
    //events
    procedure _onpaint(sender:tobject); override;
    function  _onnotify(sender:tobject):boolean; override;
    function  _onshortcut(sender:tobject):boolean; override;
    property oncolor:tlongintevent read foncolor write foncolor;//26feb2021
   end;

{tbasiccolormatrix}
   tbasiccolormatrix=class(tbasiccontrol)
   private
    icolor:longint;
    foncolor:tlongintevent;
    procedure setcolor(x:longint);
   public
    //override
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    //events
    procedure _onpaint(sender:tobject); override;
    function _onnotify(sender:tobject):boolean; override;//02feb2025
    property oncolor:tlongintevent read foncolor write foncolor;
    //information
    property color:longint read icolor write setcolor;
   end;

{tbasiccolormixer}
   tbasiccolormixerCell=record
      color :longint;
      area  :twinrect;
      end;
   tbasiccolormixer=class(tbasiccontrol)
   private

    icore:array[0..3] of array [0..19] of tbasiccolormixerCell;
    ifromcolor,itocolor,iselectedcolor:longint;
    foncolor:tlongintevent;

    procedure setfromcolor(x:longint);
    procedure settocolor(x:longint);
    function xrowheight:longint;
    function xrowcount:longint;
    procedure xmakecolors(scolor,dcolor:longint);

   public

    //create
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    function getalignheight(xclientwidth:longint):longint; override;
    procedure _onpaint(sender:tobject); override;
    function _onnotify(sender:tobject):boolean; override;//02feb2025

    //information
    property fromcolor     :longint     read ifromcolor     write setfromcolor;
    property tocolor       :longint     read itocolor       write settocolor;
    property selectedcolor :longint     read iselectedcolor;

    //workers
    procedure setparams(xfromcolor,xtocolor:longint);

    //events
    property oncolor:tlongintevent read foncolor write foncolor;

   end;


{tbasicstatus}
   tbasicstatus=class(tbasiccontrol)
   private
    //Note: Now supports auto-width if no cellwidths are set BUT "celltext[0]" has text - 05oct2020
    itimer250:comp;
    ilastflash,ipause:boolean;
    iclickindex,iflashcount:longint;
    iclickname,iinforef:string;
    icellmark:array[0..19] of boolean;
    icellflash:array[0..19] of boolean;
    icellwidth:array[0..19] of longint;
    icellalign:array[0..19] of longint;//0=left, 1=center, 2=right, 3=default=internal
    icellleft:array[0..19] of longint;//left pixel boundary that starts the cell - filled via _onpaint - 04feb2023
    icellright:array[0..19] of longint;//right pixel boundary that finished the cell - filled via _onpaint - 04feb2023
    icellpert:array[0..19] of double;
    icelltext:array[0..19] of string;
    icellname:array[0..19] of string;
    icellhelp:array[0..19] of string;//03dec2023
    icellref:array[0..19] of string;
    fclickcell:tnotifyevent;
    function xcellok(x:longint):boolean;
    procedure setcellname(x:longint;y:string);
    function getcellname(x:longint):string;
    procedure setcellhelp(x:longint;y:string);
    function getcellhelp(x:longint):string;
    procedure setcelltext(x:longint;y:string);
    function getcelltext(x:longint):string;
    procedure setcellwidth(x,y:longint);
    function getcellwidth(x:longint):longint;
    procedure setcellalign(x,y:longint);
    function getcellalign(x:longint):longint;
    procedure setcellpert(x:longint;y:double);
    function getcellpert(x:longint):double;
    procedure setcellflash(x:longint;y:boolean);
    function getcellflash(x:longint):boolean;
    procedure setcellmark(x:longint;y:boolean);
    function getcellmark(x:longint):boolean;
   public
    //options
    ocenter:boolean;//default=true=center text inside each cell, false=left align
    ofast:boolean;//default=false, true=faster change detection and repaint cycle - 26aug2024
    //create
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;
    function _onnotify(sender:tobject):boolean; override;
    function getalignheight(xclientwidth:longint):longint; override;
    //information
    property pause:boolean read ipause write ipause;
    property cellname[x:longint]:string read getcellname write setcellname;
    property cellhelp[x:longint]:string read getcellhelp write setcellhelp;
    property celltext[x:longint]:string read getcelltext write setcelltext;
    property cellwidth[x:longint]:longint read getcellwidth write setcellwidth;
    property cellalign[x:longint]:longint read getcellalign write setcellalign;//0=left, 1=center, 2=right, 3=internal
    property cellpert[x:longint]:double read getcellpert write setcellpert;//07jul2021
    property cellflash[x:longint]:boolean read getcellflash write setcellflash;//29dec2021
    property cellmark[x:longint]:boolean read getcellmark write setcellmark;//02dec2023
    //.cell click
    property clickindex:longint read iclickindex;
    property clickname:string read iclickname;
    property clickcell:tnotifyevent read fclickcell write fclickcell;
   end;

{tbasicgradient}
   tbasicgradient=class(tbasiccontrol)
   public
    //create
    constructor create(xparent:tobject;xstyle:string); virtual;
    constructor create2(xparent:tobject;xstart:boolean;xstyle:string); virtual;
    destructor destroy; override;
    procedure _onpaint(sender:tobject); override;
    function getalignheight(xclientwidth:longint):longint; override;//15may2025
   end;

{tbasicdebug}
   tbasicdebug=class(tbasiccontrol)//used to help debug any paint related issues
   private
    ipartpaint_count,iongetalignheight_count,ionpaint_count,ipaintnow_count:longint;
    ipaintarea_L_count,ipaintarea_R_count,ipaintarea_T_count,ipaintarea_B_count:longint;
    ipartpaint_notfound_count:longint;
   public
    //create
    constructor create(xparent:tobject); virtual;
    constructor create2(xparent:tobject;xstart:boolean); virtual;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;
    function getalignheight(xclientwidth:longint):longint; override;
    procedure paintnow; override;

   end;

{tmenutitle}
   tmenutitle=class(tbasiccontrol)
   private

    function xrowheight:longint;

   public

    //options
    oplain:boolean;//default=false=color matches menu, true=plain background

    //create
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    function getalignheight(xclientwidth:longint):longint; override;
    procedure _onpaint(sender:tobject); override;

   end;

{tbasictitle}
   tbasictitle=class(tbasiccontrol)
   private
    itimer250:comp;
    iinforef,itext:string;
    ilabel:boolean;
    procedure settext(x:string);
    function xtitleheight:longint;//text height
   public
    //options
    olarge:boolean;//default=false=small
    olargeheight:boolean;//default=olarge
    ocentertext:boolean;//default=false - 19nov2023
    oshadeback:boolean;//default=false - 19jul2024
    otweakv:longint;//adjust text's vertical position
    oindent:boolean;//default=true
    //create
    constructor create(xparent:tobject;xlarge,xlabel:boolean;xcaption:string);
    constructor create2(xparent:tobject;xstart,xlarge,xlabel:boolean;xcaption:string); virtual;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;//08apr2025: otab support
    function getalignheight(xclientwidth:longint):longint; override;//11may2025, 07sep2020
    //information
    property text:string read itext write settext;
    //makers
    procedure makesleek;
   end;

{tbasicbreak}
   tbasicbreak=class(tbasiccontrol)
   private
    iheight:longint;
   public
    opaint:boolean;//default=false
    //create
    constructor create(xparent:tobject;xheight:longint); virtual;
    constructor create2(xparent:tobject;xstart:boolean;xheight:longint); virtual;
    destructor destroy; override;
    function getalignheight(xclientwidth:longint):longint; override;
    //events
    procedure _onpaint(sender:tobject); override;
   end;

{tsimpleint}
   tsimpleint=class(tbasiccontrol)
   private

    icommitref,ihightimer,itimerAUTO,itimer250:comp;
    ilastval,ireloadid,idownval,ipaintid,ivalid,ilastpaintid,ilastvalid,imin,imax,idef,ival:longint;
    ffindlabel :tsimplestringevent;
    fclicklabel:tsystemnotify;
    fonreadwriteval,fonreadwritedef:tbasicint_onreadwriteval;
    fonvalue2:tlongintevent;
    foncommitvalue:tnotifyevent;
    idownball,iaball,ialabel,iabar:twinrect;
    vnone,vlabel,vbar,ihoverref,idownstyle,ihoverstyle:longint;
    icanmorelessonup:boolean;
    ilastlabel:string;

    procedure setval(xval:longint);
    procedure writeval(xval:longint);
    function readval:longint;
    function readdef:longint;
    procedure __onvol(sender:tobject;var xval:longint;xwrite:boolean);
    function xfindlabel:string;
    procedure xclicklabel;
    function vfind(x:tpoint):longint;
    procedure xmoreless;//06jun2025
    function xrowheight:longint;//05sel2025

   public

    oloadfromname:string;//get value from a system value using a name
    oautoreload:boolean;
    oalign:longint;//default=1=center, 0=left, 2=right
    ohelplabel:string;//label help
    ohelpbar  :string;//bar help
    ounit     :string;
    osep      :string;

    //create
    constructor create(xparent:tobject); virtual;
    constructor create2(xparent:tobject;xstart:boolean); virtual;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    function _onnotify(sender:tobject):boolean; override;
    procedure _onpaint(sender:tobject); override;
    function getalignheight(xclientwidth:longint):longint; override;

    //workers
    procedure setparams(xmin,xmax,xdef,xval:longint);
    procedure setparams3(xmin,xmax,xdef,xval:longint;xloadfromname:string);
    property min:longint read imin;
    property max:longint read imax;
    property def:longint read idef;
    property val:longint read readval write setval;
    procedure reload;//uses "oloadfromname" to gain value - 07sep2020

    //events
    property onfindlabel   :tsimplestringevent       read ffindlabel      write ffindlabel;
    property onclicklabel  :tsystemnotify            read fclicklabel     write fclicklabel;
    property onvalue2      :tlongintevent            read fonvalue2       write fonvalue2;//26feb2021
    property onreadwriteval:tbasicint_onreadwriteval read fonreadwriteval write fonreadwriteval;
    property onreadwritedef:tbasicint_onreadwriteval read fonreadwritedef write fonreadwritedef;
    property oncommitvalue :tnotifyevent             read foncommitvalue  write foncommitvalue;

    //makers
    procedure makemidivol;//23mar2022
    procedure makewavevol;
    procedure makevol(xmade:longint);//15aug2025, 09jan2025, 12nov2022
    procedure makemiditranspose;//15aug2025, 14feb2025

   end;

{tbasicset}
   pbasicset_valarray=^tbasicset_valarray;//08nov2025
   tbasicset_valarray=array[0..31] of boolean;

   tbasicset_onreadwriteval=procedure(sender:tobject;var xval:tbasicset_valarray;xwrite:boolean) of object;
   tbasicset=class(tbasiccontrol)
   private

    itimer250:comp;
    icaps:array[0..31] of string;
    inams:array[0..31] of string;
    ihlps:array[0..31] of string;
    ivisb:array[0..31] of boolean;
    iloadfromnames:array[0..31] of string;
    irecs:array[0..31] of twinrect;
    ilastval,ireloadid,icount,ilastitemsperline,ilastcount,iitemsperline,idownindex,ihoverindex,ipaintid,ivalid,ilastpaintid,ilastvalid,idef,ival:longint;
    fonreadwriteval:tbasicset_onreadwriteval;

    procedure setval(xval:longint);
    procedure xnorects;
    function getcaps(xindex:longint):string;
    procedure setcaps(xindex:longint;xval:string);
    function getnams(xindex:longint):string;
    procedure setnams(xindex:longint;xval:string);
    function getvisb(xindex:longint):boolean;
    procedure setvisb(xindex:longint;xval:boolean);
    function getvals(xindex:longint):boolean;
    procedure setvals(xindex:longint;xval:boolean);
    procedure setitemsperline(x:longint);
    procedure xsynccount;
    procedure ysetval(xval:longint);
    function ygetval:longint;
    property yval:longint read ygetval write ysetval;
    function getvals2(xname:string):boolean;
    procedure setvals2(xname:string;xval:boolean);
    function xrowheight:longint;//05sel2025

   public

    //options
    oautoreload:boolean;
    ovpad:longint;//default=0, set to Nxbordersize to pad vertical height to match other stacked controls - 21may2022
    oshowtitle:boolean;//default=true - 25dec2022

    //create
    constructor create(xparent:tobject); virtual;
    constructor create2(xparent:tobject;xstart:boolean); virtual;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    function _onnotify(sender:tobject):boolean; override;
    function getalignheight(xclientwidth:longint):longint; override;

    //workers
    function linecount:longint;
    property count:longint read icount;
    function viscount:longint;//visible count
    property itemsperline:longint read iitemsperline write setitemsperline;
    procedure xset(xindex:longint;xcap,xnam,xhlp:string;xval:boolean);
    procedure xset3(xindex:longint;xcap,xnam,xhlp:string;xval:boolean;xloadfromname:string);
    property caps[xindex:longint]:string read getcaps write setcaps;
    property nams[xindex:longint]:string read getnams write setnams;
    property visb[xindex:longint]:boolean read getvisb write setvisb;
    procedure setparams(xdef,xval:longint);
    procedure setparams2(xdef,xval,xitemsperline:longint);
    property def:longint read idef;
    property val:longint read ygetval write setval;
    property vals[xindex:longint]:boolean read getvals write setvals;
    property vals2[xname:string]:boolean read getvals2 write setvals2;//28feb2022
    function findname(xname:string;var xindex:longint):boolean;
    procedure reload;//uses "oloadfromname" to gain value - 07sep2020

    //events
    procedure _onpaint(sender:tobject); override;
    property onreadwriteval:tbasicset_onreadwriteval read fonreadwriteval write fonreadwriteval;

    //makers
    procedure makesleek;
    procedure makesleek2;

   end;

{tbasicsel}
   tbasicsel_onreadwriteval=procedure(sender:tobject;var xval:longint;xwrite:boolean) of object;
   tbasicsel=class(tbasiccontrol)
   private

    icaps:array[0..31] of string;
    inams:array[0..31] of string;
    ihlps:array[0..31] of string;
    istrs:array[0..31] of string;//host support only
    irecs:array[0..31] of twinrect;
    itep,ireloadid,icount,ilastitemsperline,ilastcount,iitemsperline,idownindex,ihoverindex,ipaintid,ivalid,ilastpaintid,ilastvalid,idef,ival,imax:longint;
    iwasselected:boolean;
    fonreadwriteval:tbasicsel_onreadwriteval;
    fonclick:tnotifyevent;
    itimer500:comp;

    function getval2(xmin:longint):longint;
    procedure setval2(xmin,xval:longint);
    procedure setval(xval:longint);
    procedure writeval(xval:longint);
    function readval:longint;
    procedure xnorects;
    function getcaps(xindex:longint):string;
    procedure setcaps(xindex:longint;xval:string);
    function getnams(xindex:longint):string;
    procedure setnams(xindex:longint;xval:string);
    function gethlps(xindex:longint):string;//13mar2022
    procedure sethlps(xindex:longint;xval:string);
    function getstrs(xindex:longint):string;
    procedure setstrs(xindex:longint;xval:string);
    procedure xsynccount;
    procedure setitemsperline(x:longint);
    procedure settep(x:longint);
    function xrowheight:longint;

   public

    //options
    oloadfromname:string;//get value from a system value using a name
    oautoreload:boolean;
    ovalueclick:boolean;//default=false, true=onvalue is fired EACH TIME an item is selected EVEN if it is already selected - 29aug2021
    omididevice:boolean;//running as a Midi Device selector - 05mar2022
    owavedevice:boolean;//running as a Wave Device selector - 05mar2022
    owinedevice:boolean;//maintains "wine" status label - 09sep2025
    oboldhead:boolean;//default=false - 12mar2022
    oshowtitle:boolean;//default=true

    //create
    constructor create(xparent:tobject); virtual;
    constructor create2(xparent:tobject;xstart:boolean); virtual;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    function _onnotify(sender:tobject):boolean; override;
    function getalignheight(xclientwidth:longint):longint; override;
    procedure xsyncmididevice(xforce:boolean); virtual;
    procedure xsyncwavedevice(xforce:boolean); virtual;
    procedure xsyncwinestatus;

    //workers
    property tep:longint read itep write settep;
    function linecount:longint;
    property itemsperline:longint read iitemsperline write setitemsperline;
    procedure xclear;
    procedure xadd(xcap,xnam,xhlp:string);
    procedure xadd2(xcap,xnam,xhlp,xstr:string);
    property caps[xindex:longint]:string read getcaps write setcaps;
    property nams[xindex:longint]:string read getnams write setnams;
    property hlps[xindex:longint]:string read gethlps write sethlps;
    property strs[xindex:longint]:string read getstrs write setstrs;
    procedure setparams(xdef,xval:longint);
    procedure setparams2(xdef,xval,xitemsperline:longint);
    procedure setparams3(xdef,xval,xitemsperline:longint;xloadfromname:string);
    property def:longint read idef;
    property val:longint read ival write setval;
    property val2[xmin:longint]:longint read getval2 write setval2;
    property max:longint read imax;
    procedure reload;//uses "oloadfromname" to gain value - 07sep2020
    property wasselected:boolean read iwasselected;

    //find
    function findname(xnam:string;var xindex:longint):boolean;

    //events
    procedure _onpaint(sender:tobject); override;
    property onreadwriteval:tbasicsel_onreadwriteval read fonreadwriteval write fonreadwriteval;
    property onclick:tnotifyevent read fonclick write fonclick;//07mar2022

    //makers
    procedure makesleek;
    procedure makesleek2;
    function makemididevice:tbasicsel;//09sep2025, 21aug2025
    function makewavedevice:tbasicsel;//21aug2025

   end;

{tbasictea}
   tbasictea=class(tbasiccontrol)
   private

    itimer500:comp;
    iinfocolors,iinfoshades,iteppaint,itepview,itepdata,ivieww,iviewh,ibytes:longint;
    icanundo,icanmakesolid,icanmaketransparent,iinfotrans,imustpaint:boolean;
    idata,iundo:tstr8;
    ifolder:string;
    imanage_toolbar1,imanage_toolbar2,imanage_toolbar3:tbasictoolbar;//optional integrated toolbar handlers

    function getwidth:longint;
    function getheight:longint;
    function getbytes:longint;
    function gettext:string;
    procedure settext(x:string);
    procedure xsync;
    procedure xundoFill;

   public

    //options
    odefaultmsg   :string;//default=nil="( Not in use )" -> set to override the default message - 12apr2021
    odefault      :boolean;//default=true

    //create
    constructor create(xparent:tobject); virtual;
    constructor create2(xparent:tobject;xstart:boolean); virtual;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    function _onnotify(sender:tobject):boolean; override;
    function getalignheight(xclientwidth:longint):longint; override;
    procedure xshowmenuFill(sender:tobject;xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
    function xshowmenuClick(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
    function xcmd(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;

    //information
    property width         :longint     read getwidth;
    property height        :longint     read getheight;
    property bytes         :longint     read getbytes;
    property text          :string      read gettext         write settext;

    //workers
    function setdata(xdata:tstr8):boolean;//13apr2021
    function getdata(xdata:tstr8):boolean;

    //manage
    procedure manage(xtoolbar1,xtoolbar2,xtoolbar3:tbasictoolbar);
    procedure unmanage;

    //copy
    function cancopyimage:boolean;
    procedure copyimage;

    //paste
    function canpasteimage:boolean;
    procedure pasteimage;

    //tep
    procedure usetep(const xindex:longint);

    //io
    procedure openimage;
    function cansaveimage:boolean;
    procedure saveimage;

    //maketransparent
    function canmakeimagetrans:boolean;
    procedure makeimagetrans(const xtrans:boolean;const xstyle:longint);

    //undo
    property canundo:boolean read icanundo;
    procedure undo;
    function canundoClear:boolean;
    procedure undoClear;

    //customise folder image
    procedure fromfolder(const xfolder:string);
    function cantofolder:boolean;
    procedure tofolder(const xfolder:string);

    //events
    procedure _onpaint(sender:tobject); override;

   end;

{tbasiccolors}
   tbasiccolors=class(tbasiccontrol)
   private
    istys   :array[0..299] of longint;
    icaps   :array[0..299] of string;
    inams   :array[0..299] of string;
    iidxs   :array[0..299] of longint;//for system colors
    ihlps   :array[0..299] of string;
    icols   :array[0..299] of longint;
    idefcols:array[0..299] of longint;
    irecs   :array[0..299] of twinrect;
    icount,imax,idownindex,iitemsperline,ilastalignid,ialignid,ilastpaintid,ipaintid:longint;
    ilastsysname:string;
    imustwrite:boolean;
    foncolor:tlongintevent;
    foncolorchanged:tnotifyevent;
    procedure xnewid(xalign,xpaint:boolean);
    procedure setitemsperline(x:longint);
    function getcap(x:longint):string;
    procedure setcap(x:longint;xval:string);
    function getnam(x:longint):string;
    procedure setnam(x:longint;xval:string);
    function getcol(x:longint):longint;
    procedure setcol(x:longint;xval:longint);
    procedure setcol3(x:longint;xval:longint);
    function getidx(x:longint):longint;
    procedure xsynccount;
    function getcol1(xidx:longint):longint;
    procedure setcol1(xidx:longint;xval:longint);
    procedure xsetcol(x:longint;xval:longint;xspecialoverride:boolean);
    function getcol2(xname:string):longint;
    procedure setcol2(xname:string;xval:longint);
    function xpaintcalc(xmustpaint:boolean):longint;
    function getdata:string;
    procedure setdata(x:string);
    //special color handlers - 25may2021
    procedure xset(xindex,xval:longint);
    procedure xspecial(xname,xstyle:string;xval:longint);
   public
    //options
    osyscolor:boolean;//default=false, true=directly edits "custom" colors in "syssettings"
    oshowcaps:boolean;//default=true
    opopcolor:boolean;//default=true=click/drag to adjust color, false=color is locked (static)
    otightblocks:boolean;//default=false
    oclicktouse:boolean;//default=false
    //create
    constructor create(xparent:tobject); virtual;
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;
    function _onnotify(sender:tobject):boolean; override;
    function getalignheight(xclientwidth:longint):longint; override;
    //information
    property count:longint read icount;
    property itemsperline:longint read iitemsperline write setitemsperline;
    property nam[x:longint]:string read getnam;
    property idx[x:longint]:longint read getidx;
    property cap[x:longint]:string read getcap;
    property col[x:longint]:longint read getcol write setcol;
    property col1[xidx:longint]:longint read getcol1 write setcol1;//updates when color changes
    property col2[xname:string]:longint read getcol2 write setcol2;
    property col3[xidx:longint]:longint read getcol1 write setcol3;//updates when color changes AND always updates if it's a special color being set - 25may2021
    function linecount:longint;
    function lineheight:longint;//color palette - 11dec2025, 05sep2025, 24may2025
    function lineheight2:longint;//title
    property data:string read getdata write setdata;
    //workers
    procedure clear;
    procedure addcol(xcap,xnam,xhlp:string);
    procedure addcol1(xcap:string;xidx:longint;xhlp:string);
    procedure addcol2(xcap,xnam,xhlp:string;xidx,xcol,xdefcol:longint);
    procedure addtitle(xcap,xhlp:string);
    procedure xadd(xstyle:longint;xcap,xnam,xhlp:string;xidx,xcol,xdefcol:longint);
    function findname(xname:string;var xindex:longint):boolean;
    function findidx(xidx:longint;var xindex:longint):boolean;
    //system color workers
    procedure xreadfrom(xnormal,xtitle:pvirtualinfo;xmorecolors:pvirtualmorecolors);
    procedure xwriteto(xnormal,xtitle:pvirtualinfo;xmorecolors:pvirtualmorecolors);
    procedure fromsys(xname:string);
    procedure tosys(xname:string;xautosync:boolean);
    //makers
    procedure makesystem;
    procedure makeadjustable;
    procedure makeadjustable2(xitemsperline:longint);
    //events
    property oncolor:tlongintevent read foncolor write foncolor;//tiggered when using "oclicktouse=true"
    property oncolorchanged:tnotifyevent read foncolorchanged write foncolorchanged;
   end;

{tbasictoolbar}
   tbasictoolbar=class(tbasiccontrol)
   private

    iformrect:twinrect;
    iappxy:tpoint;
    fonclick:tnotifyevent;
    fonclick2:ttoolbarevent2;
    icaption2,iinforef:string;
    ihalign,ilastfindbycode2,irowcount,istyle,idownindex,ifocusindex,ihoverindex,iaddcount,itepheight,irowpad,ibuttonpad,ibuttonvpad:longint;
    icountdown1000,itimer500,itimer250,itimer100:comp;
    imustlink,iflash,ilastflash,ipause:boolean;

    //.animation support
    ianitep:array[0..19] of longint;
    ianims :array[0..19] of longint;
    ianipos,ianicount:longint;
    ianiplay64,ianinext64:comp;

    //.image
    piw       :array[0..99] of longint;
    pih       :array[0..99] of longint;
    pit       :array[0..99] of longint;//tep

    //.text
    ptw       :array[0..99] of longint;
    pth       :array[0..99] of longint;
    ptf       :array[0..99] of longint;//font index

    //.position
    poa       :array[0..99] of twinrect;//out area
    pa        :array[0..99] of twinrect;//inner area
    puse      :array[0..99] of boolean;

    //.other
    icolor    :array[0..99] of longint;//custom tep color -> default is "clnone=Off"
    icolorb   :array[0..99] of longint;//custom tep color2  -> default is "clnone=Off"
    ititle    :array[0..99] of boolean;//17mar2025
    icap      :array[0..99] of string;
    isize     :array[0..99] of longint;//0=automatic (default), 1..N=static pixels, -1..-N=percentage
    ipert     :array[0..99] of double;//0..100 -> optional progress bar support - 07jul2021
    itep      :array[0..99] of longint;
    icode     :array[0..99] of longint;
    icode2    :array[0..99] of string;//inline with "tbasicmenu"
    ibuthelp  :array[0..99] of string;
    iref      :array[0..99] of string;
    ienableds :array[0..99] of boolean;
    ivisibles :array[0..99] of boolean;
    imarked   :array[0..99] of boolean;
    ihighlight:array[0..99] of boolean;//30may2021
    iflasher  :array[0..99] of boolean;//24feb2021
    icountdown:array[0..99] of longint;//in seconds -> "min32..0" = off, 1..max32 = seconds remaining - 05sep2020

    //window head support
    iishead,iwmin,iwmax,iwclo,iwmen,iwfull,iappicon,iappcap:boolean;
    iapptep:longint;

    procedure setstyle(x:longint);
    function xok(x:longint):boolean;
    function uok(x:longint):boolean;//user range
    procedure xsetcap(x:longint;y:string);
    function xgetcap(x:longint):string;
    procedure xsettep(x:longint;y:longint);
    function xgettep(x:longint):longint;
    procedure xsetsize(x:longint;y:longint);
    function xgetsize(x:longint):longint;
    procedure xsettitle(x:longint;y:boolean);
    function xgettitle(x:longint):boolean;
    procedure setpert(x:longint;y:double);
    function getpert(x:longint):double;
    procedure xsetcountdown(x,y:longint);//05sep2020
    function xgetcountdown(x:longint):longint;
    procedure xsetcode(x,y:longint);
    function xgetcode(x:longint):longint;
    procedure xsetcode2(x:longint;y:string);
    function xgetcode2(x:longint):string;
    procedure xsethelp(x:longint;y:string);
    function xgethelp(x:longint):string;
    procedure xsetvisibles(x:longint;y:boolean);
    function xgetvisibles(x:longint):boolean;
    procedure xsetenableds(x:longint;y:boolean);
    function xgetenableds(x:longint):boolean;
    procedure xsetmarked(x:longint;y:boolean);
    function xgetmarked(x:longint):boolean;
    procedure xsetcolor(x,y:longint);
    function xgetcolor(x:longint):longint;
    procedure xsetcolorb(x,y:longint);
    function xgetcolorb(x:longint):longint;
    procedure xsethighlight2(x:string;y:boolean);
    function xgethighlight2(x:string):boolean;
    procedure xsetcap2(x:string;y:string);
    function xgetcap2(x:string):string;
    procedure xsettep2(x:string;y:longint);
    function xgettep2(x:string):longint;
    procedure xsetflash(x:longint;y:boolean);
    function xgetflash(x:longint):boolean;
    procedure xsethighlight(x:longint;y:boolean);//15mar2022
    function xgethighlight(x:longint):boolean;
    procedure xsetvisible2(x:string;y:boolean);
    function xgetvisible2(x:string):boolean;
    procedure xsetflash2(x:string;y:boolean);
    function xgetflash2(x:string):boolean;
    procedure xsetmarked2(x:string;y:boolean);
    function xgetmarked2(x:string):boolean;
    procedure xsetenabled2(x:string;y:boolean);
    procedure xsetcolor2(x:string;y:longint);
    function xgetcolor2(x:string):longint;
    procedure xsetcolor2b(x:string;y:longint);
    function xgetcolor2b(x:string):longint;
    function xgetenabled2(x:string):boolean;
    procedure xsetsize2(x:string;y:longint);
    function xgetsize2(x:string):longint;
    procedure xsettitle2(x:string;y:boolean);
    function xgettitle2(x:string):boolean;
    procedure xsetpert2(x:string;y:double);
    function xgetpert2(x:string):double;
    procedure xsethelp2(x,y:string);//09jun2025
    function xgethelp2(x:string):string;//09jun2025
    function xcapok(xindex:longint):boolean;
    function xtepok(xindex:longint):boolean;
    function xcapok2(xindex:longint;xallowemptyCAP:boolean):boolean;
    function xtepok2(xindex:longint):boolean;//supports visible=false
    function getparentpage:string;
    procedure setparentpage(x:string);
    procedure xclickbutton(xindex:longint);
    function xflashcount:longint;
    function _onnotify2(sender:tobject;xdragonly:boolean):boolean;//28nov2025, 17aug2025 19jul2025

    //.find support
    function findhelp(xindex:longint):string;
    function xmapitems(xclientwidth,xbordersize,xminrowcount:longint;xautoheight:boolean):longint;//05jun2025: properly center small button contents, 20may2025, 04may2025, 21mar2025: fixed one item on 1st line wrap issue, 06jan2025
    procedure xcmd(x:longint);
    procedure sethalign(x:longint);
    procedure setapptep(x:longint);//app icon
    procedure setcaption2(x:string);//27dec2024
    function xcountcap(xindex:longint):string;

   public

    //options
    oclickthru:boolean;//default=false, true=transmit internally handled clicks to external host for analysis - 19jun2022
    owrap:boolean;//default=true
    odownsubtle:boolean;//default=false, true=draw background of "down" item with a subtle background shade - 11feb2023
    ocountdown:boolean;//default=true=allow countdowns
    ocountdown_dlgcheck:boolean;//default=true=countdown only if top dlg - 05sep2020
    ovpad:longint;//default=2, set in range 0..N
    ohpad:longint;//default=2, set in range 0..N
    ohbutpad:longint;//default=8
    ohbutpad1st:boolean;//default=true
    ojump:longint;//default=2 amount button shifts during down click

    //oflatback:boolean;//default=false, true=paints background using background color - overrides other effects
    ounderline:boolean;//default=true=underline text during hover/down, false=don't underline - 19jul2024
    omodified:boolean;//marks caption with an "*" to indicate changes have been made

    //.oequalwidths support
    oequalwidths:boolean;//default=false=each button assumes it's own width, true=each button has the same width as the longest/widest button - 02jun2021

    //.title support
    otitle:boolean;//default=false, true=toolbar with caption
    olarge:boolean;//default=false=small title caption, true=large title caption

    //.return values
    oindex:longint;
    ominrows:longint;//default=1
    oheadalign:boolean;//default=false, true=uses system "headalign" value for halign

    //.partline - 23mar2025
    opartline:single;//0=none, 1=full line height, 0.5=50% line height, 0.3=30% (default)
    oscaleh:single;
    oscalevpad:single;
    oscalesep:single;

    //.support
    otag2:longint;

    //create
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;//20jul2025, 14jul2025
    procedure _onpaint(sender:tobject); override;//05jun2025, 15may2025
    function  _onnotify(sender:tobject):boolean; override;//17aug2025, 19jul2025
    function getalignheight(xclientwidth:longint):longint; override;
    procedure xdragthewindow;//force head to act as a window dragger - assuming mouse input matches up - 07mar2022

    //information
    property count:longint read iaddcount;//14jul2025
    property style:longint read istyle write setstyle;//0=tep+cap, 1=tep, 2=cap
    property pause:boolean read ipause write ipause;
    property halign:longint read ihalign write sethalign;
    function find__halign:longint;
    property caption;
    property caption2:string read icaption2 write setcaption2;
    property downindex:longint read idownindex;
    property hoverindex:longint read ihoverindex;

    //.by index
    property bcolor[xindex:longint]      :longint   read xgetcolor     write xsetcolor;
    property bcolorb[xindex:longint]     :longint   read xgetcolorb    write xsetcolorb;
    property btitle[xindex:longint]      :boolean   read xgettitle     write xsettitle;
    property bcap[xindex:longint]        :string    read xgetcap       write xsetcap;//Note: '-' = vertical sep (visible line), '+' = new line (invisible)
    property bsize[xindex:longint]       :longint   read xgetsize      write xsetsize;
    property btep[xindex:longint]        :longint   read xgettep       write xsettep;
    property bcode[xindex:longint]       :longint   read xgetcode      write xsetcode;
    property bcode2[xindex:longint]      :string    read xgetcode2     write xsetcode2;
    property bcountdown[xindex:longint]  :longint   read xgetcountdown write xsetcountdown;
    property bhelp[xindex:longint]       :string    read xgethelp      write xsethelp;
    property benabled[xindex:longint]    :boolean   read xgetenableds  write xsetenableds;
    property bvisible[xindex:longint]    :boolean   read xgetvisibles  write xsetvisibles;
    property bmarked[xindex:longint]     :boolean   read xgetmarked    write xsetmarked;
    property bhighlight[xindex:longint]  :boolean   read xgethighlight write xsethighlight;//15mar2022
    property bflash[xindex:longint]      :boolean   read xgetflash     write xsetflash;

    //.by code
    property bcolor2[xcode2:string]      :longint   read xgetcolor2    write xsetcolor2;
    property bcolor2b[xcode2:string]     :longint   read xgetcolor2b   write xsetcolor2b;
    property btitle2[xcode2:string]      :boolean   read xgettitle2    write xsettitle2;
    property bsize2[xcode2:string]       :longint   read xgetsize2     write xsetsize2;
    property bpert2[xcode2:string]       :double    read xgetpert2     write xsetpert2;
    property bhelp2[xcode2:string]       :string    read xgethelp2     write xsethelp2;//09jun2025
    property benabled2[xcode2:string]    :boolean   read xgetenabled2  write xsetenabled2;
    property bvisible2[xcode2:string]    :boolean   read xgetvisible2  write xsetvisible2;
    property bmarked2[xcode2:string]     :boolean   read xgetmarked2   write xsetmarked2;
    property bhighlight2[xcode2:string]  :boolean   read xgethighlight2 write xsethighlight2;
    property bflash2[xcode2:string]      :boolean   read xgetflash2    write xsetflash2;
    property bcap2[xcode2:string]        :string    read xgetcap2      write xsetcap2;
    property btep2[xcode2:string]        :longint   read xgettep2      write xsettep2;//19dec2021
    property parentpage:string read getparentpage write setparentpage;

    //.low level
    function xtextTOP(x:longint):longint;//11may2025

    //makers
    function maketitle(xcap:string):tbasictoolbar;
    function maketitle2(xcap:string;xlarge:boolean):tbasictoolbar;
    function maketitle3(xcap:string;xlarge,xright:boolean):tbasictoolbar;
    function makelinksSubtle:tbasictoolbar;//11feb2023
    function makeWinhead(xwinallbuttons:boolean):tbasictoolbar;//26dec2024
    function makeWinhead2(xclose,xall,xappicon,xlarge:boolean;xapptep:longint):tbasictoolbar;//26dec2024
    function makeWinhead__status_small:tbasictoolbar;//26dec2024

    //add
    procedure clear;//13jul2025, 22sep2020
    procedure clear1(p:longint);//13jul2025
    function add(xcap:string;xtep,xcode:longint;xcode2,xhelp:string):longint;
    function add2(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;ximgright:boolean):longint;
    function add3(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xenabled,xvisible,ximgright:boolean):longint;
    function sadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xsize,xalign:longint):longint;
    function hcsadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xsize:longint):longint;//highlighter with button padding - 05jun2021
    function csadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xsize:longint):longint;
    function rsadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xsize:longint):longint;
    function lsadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xsize:longint):longint;
    function cadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xcountdown:longint):longint;
    function cadd2(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;ximgright:boolean;xcountdown:longint):longint;
    function cadd3(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xenabled,xvisible,ximgright:boolean;xcountdown:longint):longint;
    function cadd4(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xenabled,xvisible,ximgright,xbutpad:boolean;xcountdown,xsize,xalign:longint):longint;
    function addsep:longint;
    function addsep2(xcode2:string):longint;
    function addhline:longint;//draw horizontal line under current line - 26sep2022
    function newline:longint;//05jun2021
    function newpartline:longint;//23mar2024

    //.optional system links - 14aug2020
    procedure xaddoptions;
    procedure xaddoptions2(xtep:longint;xcmd:string);//27jan2025, 07mar2022
    procedure xaddhelp;
    procedure xaddabout;
    procedure xaddsplash;
    procedure xaddmixer;//07mar2022
    procedure xaddmax;//15mar2022
    procedure xaddonTop;//15mar2022

    //find
    function xfind(sx,sy:longint;var xindex:longint):boolean;//27dec2024
    function xfindb(sx,sy:longint):longint;
    function xfindbycode(xcode:longint):longint;
    function xfindbycodeb(xcode:longint;var xindex:longint):boolean;
    function xfindbycode2(const xcode2:string):longint;
    function xfindbycode2b(const xcode2:string;var xindex:longint):boolean;
    function xfindbycodes(xcode:longint;xcode2:string):longint;

    //window head support
    function xishead:boolean;
    property wmin:boolean read iwmin;
    property wmax:boolean read iwmax;
    property wclo:boolean read iwclo;
    property wmen:boolean read iwmen;
    property wfull:boolean read iwfull;
    property wappicon:boolean read iappicon;
    property wappcap:boolean read iappcap;
    property tep:longint read iapptep write setapptep;//app tep

    //.animate the icon
    function aniAdd(xtep,xms:longint):boolean;//16sep2022
    procedure aniClear;
    procedure aniPlay;

    //.copy from
    procedure copyitemsfrom(x:tbasictoolbar);//14jul2025
    procedure copyitemsfrom2(x:tbasictoolbar;xallitems:boolean);//14jul2025
    procedure copyitemsfrom3(s:tbasictoolbar;dkeepcount,sfromindex:longint);//14jul2025

    //special
    procedure marktab(xname:string;xmark:boolean);//11sep2021
    function canmovewindow:boolean;//20jul2025, 14jul2025

    //reference
    function visref:string;//05jun2021

    //events
    property onclick:tnotifyevent read fonclick write fonclick;
    property onclick2:ttoolbarevent2 read fonclick2 write fonclick2;

   end;

{tbasicmenu}
   tbasicmenu=class(tbasiccontrol)
   private
    imanysel1,imanysel2:longint;//28sep2022
    icountx,ireloadid,itep,iselstart,iselcount,idownpos,ilastitemindex,idownindex,ipos,ipad,imaxindentwidth,imaxttitepwidth,imaxtepwidth,imaxcapwidth,imaxtitcapwidth,imaxcutwidth,irowpad,icount,ihoverindex:longint;
    ilastflash,iwasflashing,iflashing,icandrag:boolean;
    idata:tstr8;//menu items as a realtime readable data block
    iv:tbasicscrollbar;
    fonclick,fondbclick:tnotifyevent;
    fongetitem:tbasicmenu_getitem;
    fongetitem2:tbasicmenu_getitem2;
    //.list of items painted on screen with their itemindex+vertical areas -> format: [itemindex/4]+[y.start/4]+[y.finish/4] => list of items and their click areas -> a mouse click in one of these areas equates to a menu item being actioned - 28mar2020
    ilist:tstr8;//Note: list never shrinks for maximum stability
    ilistcount:longint;//number of active items
    procedure setdata(x:tstr8);//17nov2024, 08jun2021
    procedure setpos(x:longint);
    procedure sethoverindex(x:longint);
    function xrowpad:longint;//10dec2025
    function xrowheight:longint;
    function xrowcount:longint;
    procedure _onpos(sender:tobject);
    procedure setselstart(x:longint);
    procedure setselcount(x:longint);
    procedure setcountx(x:longint);
    procedure setdownindex(x:longint);
    function getitemindex:longint;
    procedure setitemindex(x:longint);
   public

    //options
    ofast:boolean;//default=false=maxwidths are calculated, true=maxwidths are omitted and "_onpaint()" proc must work on the fly for maximum speed - use for large lists etc - 29mar2020
    orows:boolean;//default=false, true=alternate the coloring of continous items, restarts after each title item - 07apr2020
    ostyle:byte;//0(lsmenu)=menu, l(lslist)=single item highlight list, 2(lspanel)=view panel, 3(lsmany)=multi-select list
    okeepopen:boolean;//default=false, true=menu stays open after a mouse click - 07apr2020
    orowcount:longint;//default=0=off, 1..N=make # rows in height - 14aug2020
    oautoclose:boolean;//default=true
    ohoverunderline:boolean;//default=true=underline hover item, false=do not underline a hover item
    onumberfrom:longint;//default=-1=off - 20mar2022
    onumberfrom2:longint;//default=-1=off - 20mar2022
    onumberfrom3:longint;//default=-1=off - 20mar2022

    //.list based options - 07sep2020
    oloadfromname:string;
    oautoreload:boolean;
    oretainpos:boolean;//default=false, true=retain vertical position during "setdata()" - 04oct2020
    oscaleh:single;//default=1.0

    //create
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    function getalignheight(xclientwidth:longint):longint; override;
    function getalignwidth(xclientheight:longint):longint; override;
    function xsetclientarea(a:twinrect):boolean; override;
    function xgetitem(xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;//03oct2024, 20mar2022
    function xgetitem2(xindex:longint;var xtab:string;var xtep,xtepcolor,xtepcolor2:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;//03oct2024, 20mar2022
    function xgetval(xindex:longint;var xvalue:string):boolean;
    function xgetval2(xindex:longint):string;//03mar2022
    //information
    property pos:longint read ipos write setpos;//scroll position
    property hoverindex:longint read ihoverindex write sethoverindex;
    property downindex:longint read idownindex write setdownindex;//22mar2021, 24feb2021
    property countx:longint read icountx write setcountx;//-1=off (init only), 0..N=realtime dynamic list mode -> values sourced externally - 28spe2020
    property count:longint read icount;//number of menu items
    function vpos1:longint;//first visible item
    function vpos2:longint;//last visible item
    function vcount:longint;//visible count
    function scount:longint;//scroll count
    property data:tstr8 read idata write setdata;
    property tep:longint read itep write itep;//fallback tep used when no tep specified
    //.special list support
    property selstart:longint read iselstart write setselstart;
    property selcount:longint read iselcount write setselcount;
    function setsel(xselstart,xselcount:longint):boolean;
    function xsetsel(xselstart,xselcount:longint):boolean;
    property itemindex:longint read getitemindex write setitemindex;
    property rowheight:longint read xrowheight;//11oct2022
    //selectrange
    function canselectrange:boolean;//28sep2022
    procedure selectrange;
    procedure selectoff;
    //.support
    procedure xselectrange(x1,x2:longint);
    //find
    function xfindb(sx,sy:longint):longint;
    function xfind(sx,sy:longint;var xindex:longint):boolean;//07apr2020
    function xfindbycode2(xfindval:string;var xindex:longint):boolean;
    function xfindbycaption(xfindval:string;var xindex:longint):boolean;//28sep2020
    function xfindbycaption2(xfindval:string):longint;
    function xfindnext(xfindpart:string;var xindex:longint):boolean;//06oct2020
    function xok(x:longint):boolean;
    //makers
    procedure makemenu;
    procedure makelist;
    procedure makelistx(xcount:longint);//22sep2020
    procedure makepanel;//28aug2026, 18aug2025
    procedure makemany;
    procedure makepoplist;
    procedure makepopmany;
    //reload
    procedure reload;
    //events
    property onclick:tnotifyevent read fonclick write fonclick;
    property ondbclick:tnotifyevent read fondbclick write fondbclick;
    property ongetitem:tbasicmenu_getitem read fongetitem write fongetitem;//1x tepcolor
    property ongetitem2:tbasicmenu_getitem2 read fongetitem2 write fongetitem2;//2x tepcolor
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;//15apr2026, 01dec2025, 15may2025, 20jul2024: soft back shade for title items
    procedure _onalign(sender:tobject); override;
    function  _onnotify(sender:tobject):boolean; override;
    function  _onshortcut(sender:tobject):boolean; override;
   end;

{tbasicscrollbar}
   tbasicscrollbar=class(tbasiccontrol)
   private

    iposref64,idowntime64,itimer100,itimerscroll:comp;
    iinforef:string;
    idownbutindex,idownpos,ipos,imin,imax:longint;
    iscrollscope:extended;
    idragzone,idragbut:twinrect;
    idragbutdown:boolean;
    fonpos:tnotifyevent;
    fonarrow:tlongintgetevent;//21jun2022

    procedure setpos(x:longint);
    function xmoveval(x:longint):longint;

   public

    //options
    overtical         :boolean;//default=true=vertical, false=horizontal
    owheelchange      :longint;//default=1
    osmallchange      :longint;//default=1
    olargechange      :longint;//default=10
    oassistedscroll   :longint;//default=10 - 04oct2022
    ofullhandling     :boolean;//default=true=all functions handled internally, false=some keyboard and wheel functions are passed down to parent control - 04apr2020

    //create
    constructor create2(xparent:tobject;xstart:boolean); override;
    destructor destroy; override;
    function getalignheight(xclientwidth:longint):longint; override;
    function getalignwidth(xclientheight:longint):longint; override;
    //pos
    property pos:longint read ipos write setpos;
    property min:longint read imin;
    property max:longint read imax;
    procedure setparams(xpos,xmin,xmax:longint);
    procedure setparams2(xpos,xmin,xmax:longint;xevent:boolean);

    //events
    property onpos:tnotifyevent read fonpos write fonpos;
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;
    function  _onnotify(sender:tobject):boolean; override;
    property onarrow:tlongintgetevent read fonarrow write fonarrow;

   end;

{tbasicscroll}
   tbasicscroll=class(tbasiccontrol)
   private

    itimer100,itimer250:comp;
    ipageindex,irightgap,irightminwidth,irightmaxwidth,idownpos:longint;
    ipage,iposref,iinforef:string;
    iv:tbasicscrollbar;
    irightvisible2,irightmax,istatic,iscroll:boolean;

    //.built-in root controlls
    ihead:tbasictoolbar;//27dec2024
    imainhelp:tmainhelp;//24jul2021
    itoolbar,itoolbar2,itoolbar3:tbasictoolbar;
    igrad,igrad2,igrad3,igrad4:tbasicgradient;//19aug2024
    ihigh,ihigh2:tbasicscroll;//automatic-height panels - 21feb2021
    istatus,istatus2:tbasicstatus;
    icols:tbasiccols;
    ihelp:tbasichelp;
    imenu:tbasicmenu;
    iright:tbasicscroll;//optional - 24jul2021

    function getpos:longint;
    procedure setpos(x:longint);
    procedure setscroll(x:boolean);
    procedure setstatic(x:boolean);
    procedure setpage(x:string);
    procedure setpageindex(x:longint);//09jan2025
    procedure xcalcalign(xalignok:boolean;xclientwidth:longint;var xoutclientheight,xoutheight:longint);
    procedure setrightmax(x:boolean);
    procedure setrightgap(x:longint);
    procedure setrightminwidth(x:longint);
    procedure setrightmaxwidth(x:longint);
    function getrightvisible:boolean;
    procedure setrightvisible(x:boolean);
    procedure setrightvisible2(x:boolean);//optionally HIDE the right column (used for help) EVEN when it's set to SHOW - 17dec2024

   public

    //options
    osmallchange      :longint;//default=10%
    olargechange      :longint;//default=50%
    ofirstpos         :longint;//default=min32=off
    otopspace         :longint;//default=0px
    ofullalignpaint   :boolean;//default=false, true=realign entire GUI as the page being shown may adjust the GUI layout
    oclsarea          :boolean;//default=true=onpaint handler called to cls area, false=onpaint not called, upto child to paint area etc - 29mar2026

    //create
    constructor create(xparent:tobject); override;
    constructor create2(xparent:tobject;xscroll,xstart:boolean); virtual;
    destructor destroy; override;
    procedure destroychildren; override;
    function headheight:longint; override;//25jan2021
    function clientinner2(x:tbasiccontrol):twinrect; override;
    function getalignheight(xclientwidth:longint):longint; override;
    function findbordersize:longint; override;
    procedure setnormal(x:boolean); override;//19jul2025
    procedure _onpaint(sender:tobject); override;//29mar2026

    //children
    function childcount:longint;//17mar2025
    function findchild(xindex:longint;var xchild:tbasiccontrol):boolean;//17mar2025

    //information
    property pos:longint read getpos write setpos;
    function scrolling:boolean; override;//13jan2026
    property scroll:boolean read iscroll write setscroll;
    property static:boolean read istatic write setstatic;
    property page:string read ipage write setpage;
    property pageindex:longint read ipageindex write setpageindex;
    function xbuiltinOK(x:tobject):boolean;

    //auto-create controls
    function xright:tbasicscroll;//right side - 24jul2021
    function xmainhelp:tmainhelp;//14may2025, 05dec2024, 24jul2021
    function xhead:tbasictoolbar;//top
    function xhelp:tbasichelp;//top
    function xtoolbar:tbasictoolbar;//top
    function xstatus:tbasicstatus;//top
    function xgrad:tbasicgradient;//below "xhead"
    function xgrad2:tbasicgradient;//below "xtoolbar2" and above "xtoolbar3"
    function xgrad3:tbasicgradient;//below "xhigh2" and above "xstatus2"
    function xgrad4:tbasicgradient;//above "xhigh2"
    function xnograd:boolean;//13jul2025
    function xhigh:tbasicscroll;//top - 21feb2021
    function xtoolbar2:tbasictoolbar;//bottom
    function xtoolbar3:tbasictoolbar;//05jun2025
    function xhigh2:tbasicscroll;//bottom - 21feb2021
    function xstatus2:tbasicstatus;//bottom
    function xcols:tbasiccols;//standard -> base takes up entire remaining clientarea
    function xcolsh:tbasiccols;//autoheight -> base takes up enough clientheight to display static children, scroll children adapt to height - 26feb2021
    function xpage(xpagename:string;xstatic:boolean):tbasicscroll;
    function xpage1(xpagename,xheadlink,xhelp:string;xtep:longint;xstatic:boolean):tbasicscroll;//12jan2025
    function xpage2(xpagename,xtoplink,xbotlink,xhelp:string;xtep:longint;xstatic:boolean):tbasicscroll;
    function xpage3(xpagename,xheadlink,xtoplink,xbotlink,xhelp:string;xtep,xtopspace:longint;xstatic:boolean):tbasicscroll;//12jan2025
    function xmenu:tbasicmenu;//bottom

    //detect controls
    function xhaveright:boolean;
    function xhavemainhelp:boolean;
    function xhavehead:boolean;
    function xhavehelp:boolean;
    function xhavemenu:boolean;
    function xhavetoolbar:boolean;
    function xhavegrad:boolean;
    function xhavegrad2:boolean;
    function xhavegrad3:boolean;
    function xhavegrad4:boolean;
    function xhavehigh:boolean;
    function xhavehigh2:boolean;
    function xhavecols:boolean;
    function xhavestatus2:boolean;
    function xhavetoolbar2:boolean;
    function xhavetoolbar3:boolean;//05jun2025
    function xhavestatus:boolean;

    //.right support
    property rightvisible:boolean read getrightvisible write setrightvisible;
    property rightvisible2:boolean read irightvisible2 write setrightvisible2;//17dec2024
    property rightmax:boolean read irightmax write setrightmax;
    property rightgap:longint read irightgap write setrightgap;
    property rightminwidth:longint read irightminwidth write setrightminwidth;
    property rightmaxwidth:longint read irightmaxwidth write setrightmaxwidth;
    procedure setrightparams(xminwidth,xmaxwidth,xgap:longint;xrightmax,xvisible:boolean);

    //makers
    function makedlg(da:twinrect;xshowhead:boolean):tbasicscroll;//27feb2021
    function makedlg2(da:twinrect;xshowhead,xstatic,xcancel,xok:boolean):tbasicscroll;
    function makedlg3(da:twinrect;xtep:longint;xtitle:string;xshowhead,xstatic:boolean;xcanceltime,xoktime:longint):tbasicscroll;
    function makeautohigh:boolean;

    //events
    procedure _ontimer(sender:tobject); override;
    procedure _onalign(sender:tobject); override;
//????????????????? needs work for sketchFill mode    procedure _onpaint(sender:tobject); override;
    function  _onnotify(sender:tobject):boolean; override;

    //support
    function xsmall:longint;
    function xlarge:longint;
    procedure noscroll;//14jul2025

   end;

{tbasicimageexts}
   tbasicimageexts=class(tbasicscroll)
   private
    itimer250:comp;
    ilastref,iext,iactionlist:string;
    iitemsperline:longint;
    ilist:tbasicsel;
    procedure xsync;
    procedure setext(x:string);
    procedure setitemsperline(x:longint);
    procedure ____onclick(sender:tobject);
   public
    oautoshrink:boolean;//default=false, true=reduce height when no options for specified image format
    oboldhead:boolean;//default=false
    //create
    constructor create(xparent:tobject); override;
    constructor create2(xparent:tobject;xstart:boolean); virtual;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    //information
    property ext:string read iext write setext;//image format to display an action list for
    property actionlist:string read iactionlist;
    property itemsperline:longint read iitemsperline write setitemsperline;
   end;

{tbasicsetcolor}
   tbasicsetcolor=class(tbasicscroll)
   private
    icmbar:tbasictoolbar;
    ir,ig,ib,ia:tsimpleint;
    im:tbasiccolormatrix;
    icm:tbasiccolormixer;
    ic:tbasiccolor;
    icolor,iundocolor,irevertcolor:longint;
    iuse32,icanfillundo,ilocksync:boolean;
    foncolor:tlongintevent;
    procedure setcolor(x:longint);
    procedure __onclick(sender:tobject);//01feb2025
    procedure __oncolor(sender:tobject;xval:longint);
    function ext__onnotify(sender:tobject):boolean;
    procedure setcolor24(x:longint);
    function getcolor24:longint;
   public
    //create
    constructor create(xparent:tobject;xuse32,xhead:boolean); virtual;
    constructor create2(xparent:tobject;xscroll,xuse32,xhead,xstart:boolean); virtual;
    destructor destroy; override;
    //information
    property color:longint read icolor write setcolor;
    property color24:longint read getcolor24 write setcolor24;
    property revertcolor:longint read irevertcolor write irevertcolor;
    //workers
    procedure setparams(xcolor,xrevertcolor:longint;xpage:string);
    procedure getparams(var xcolor,xrevertcolor:longint;var xpage:string);
    //events
    property oncolor:tlongintevent read foncolor write foncolor;
   end;

{tbasiccols}
   tbasiccols=class(tbasiccontrol)
   private

    icols          :array[0..9] of tbasicscroll;
    isize          :array[0..9] of longint;
    iremcount      :array[0..9] of longint;//remainder in units
    imaxsizePX     :array[0..9] of longint;//in pixels
    iwratio        :array[0..9] of boolean;//default=true=adapts "fixed" sizes using vifontwidthratio
    ihsp,ivsp,istyle:longint;
    iinforef:string;
    itimer250:comp;

    procedure setremcount(x,xval:longint);
    function getremcount(x:longint):longint;
    function getcols(x:longint):tbasicscroll;
    function getcols2(x,xsize:longint;xscroll:boolean):tbasicscroll;
    function getcols3(x,xsize,xmaxsizePX:longint;xscroll:boolean):tbasicscroll;//17nov2024
    procedure setstyle(x:longint);
    procedure setsize(x,xval:longint);
    function getsize(x:longint):longint;
    procedure setmaxsizePX(x,xval:longint);
    function getmaxsizePX(x:longint):longint;
    procedure setwratio(x:longint;xval:boolean);
    function getwratio(x:longint):boolean;
    procedure sethsp(x:longint);
    procedure setvsp(x:longint);
    function xfindsize(x,cw:longint):longint;//17nov2024
    procedure setvis(x:longint;xval:boolean);
    function getvis(x:longint):boolean;
    procedure xsyncareas(xclientarea:twinrect;xcalconly:boolean);//27aug2025

   public

    //options
    ofullarea:boolean;//default=true=last column uses entire remaining space regardless of it's specified size - 07oct2020
    omakeautoheight:boolean;//default=false, true=make self and all "static" children "autoheight" where possible - 26feb2021
    ofillheight:boolean;//default=false, true=force columns to use remaining vertical height - 07mar2022 -> option was introduced because it was FAR TO DIFFICULT to work out which options were required in what order to get the same affect

    //create
    constructor create(xparent:tobject); override;
    constructor create2(xparent:tobject;xstart:boolean); virtual;
    destructor destroy; override;
    function getalignheight(xclientwidth:longint):longint; override;//12jul2025: column width correctly used now
    function canautoheight:boolean; override;

    //information
    property style:longint                read istyle write setstyle;
    property cols[x:longint]:tbasicscroll read getcols;//auto-creates "static" columns as required -> range 0..9
    property cols2[x,xsize:longint;xscroll:boolean]:tbasicscroll read getcols2;//auto-creates as required -> range 0..9
    property cols3[x,xsize,xmaxsizePX:longint;xscroll:boolean]:tbasicscroll read getcols3;//auto-creates as required -> range 0..9
    property vis[x:longint]:boolean       read getvis write setvis;
    property size[x:longint]:longint      read getsize write setsize;
    property remcount[x:longint]:longint read getremcount write setremcount;
    property maxsizePX[x:longint]:longint read getmaxsizePX write setmaxsizePX;
    property wratio[x:longint]:boolean    read getwratio write setwratio;
    property vsp:longint read ivsp write setvsp;
    property hsp:longint read ihsp write sethsp;

    //makers
    procedure makeautoheight;//sets self and all STATIC children to oautoheight=true - 26feb2021
    function makecol(xindex,xremcount:longint;xscroll:boolean):tbasicscroll;//12may2025

    //events
    procedure _ontimer(sender:tobject); override;
    procedure _onalign(sender:tobject); override;

   end;

{tbasiccells}
   tbasiccellsimageevent=function(sender:tobject;xindex,xfocus,xcount:longint;var ximage:tbasicimage;var xtranscol:longint;var xcaption:string):boolean of object;
   tbasiccellsmoveevent=function(sender:tobject;sindex,dindex,xfocus,xcount:longint):boolean of object;
   tbasiccells=class(tbasiccontrol)
   private
    fonimage:tbasiccellsimageevent;
    fonmove:tbasiccellsmoveevent;
    ilastscrollpos,ilastfocus,iprevscrollpos,iprevfocus:longint;
    idropindex,istarty,istartx,istopx,ilastzoom,iseppad,itoppad,ibotpad,ithumbw,ithumbh,ifocus,icount,ipaintid,ilastpaintid:longint;
    idragarea:twinrect;
    idownxy:tpoint;
    iscroll:tbasicscrollbar;
    idragref,iref,iref2:string;
    itimer100:comp;
    procedure xincpaint;
    procedure _onalign(sender:tobject); override;
    procedure _onpos(sender:tobject);
    function getscrollpos:longint;
    procedure setscrollpos(x:longint);
    procedure xsetfocus(x:longint);
    procedure setcount(x:longint);
   public
    //options
    oalwaysallowmove:boolean;//default=false
    //create
    constructor create(xparent:tobject); virtual;
    constructor create2(xparent:tobject;xstart:boolean); virtual;
    destructor destroy; override;
    procedure _ontimer(sender:tobject); override;
    function getalignheight(xclientwidth:longint):longint; override;
    procedure _onpaint(sender:tobject); override;
    function _onnotify(sender:tobject):boolean; override;
    //information
    property focus:longint read ifocus write xsetfocus;
    property count:longint read icount write setcount;
    property scrollpos:longint read getscrollpos write setscrollpos;
    function scrollmax:longint;
    property thumbw:longint read ithumbw;
    property thumbh:longint read ithumbh;
    procedure setthumbsize(w,h:longint);
    //keyboard support
    procedure xprev;
    procedure xnext;
    function xcanmove:boolean;
    function xmove(s,d:longint):boolean;
    //finders
    function findcell(mx:longint;var xindex:longint;xpastend:boolean):boolean;
    function findcell2(mx:longint;var xindex:longint;var xarea,xinnerarea:twinrect;xpastend:boolean):boolean;//09feb2022
    //workers
    function setparams(xscroll,xfocus,xcount:longint):boolean;
    function setparams2(xscroll,xfocus,xcount,xthumbW,xthumbH:longint):boolean;
    procedure xprevlocation;
    //external
    property onimage:tbasiccellsimageevent read fonimage write fonimage;
    property onmove:tbasiccellsmoveevent   read fonmove  write fonmove;
    //support

   end;

{tbasicsplash}
   tbasicsplash=class(tbasicscroll)
   private

    isize,igap:longint;
    ititle32:tbasicimage;
    iscreen:tbasiccontrol;
    ipreviousfocus:longint;
    itimeout:comp;
    ititleref:string;

    function onnotify__screen(sender:tobject):boolean;
    procedure onpaint__screen(sender:tobject);
    function xcontentarea:twinrect;
    procedure xmaketitle(dw,dh:longint);//scaling support - 18mar2026, 11dec2025, 13sep2025: lighter memory usage when "fontfeatherf>=1", 08apr2025: improved for short titles

   public

    //create
    constructor create(xparent:tobject); override;
    constructor create2(xparent:tobject;xstart:boolean); virtual;
    destructor destroy; override;

    //workers
    procedure xsplash;
    procedure xabout;
    function xmustclose:boolean;

   end;


{tbasicedit}
   tbasicedit=class(tbasiccontrol)
   private

    iidleref,itimerslow,itimer250:comp;
    iundodata,ibuthelp,ibuthelp2,ivalue,iref,ititle:string;
    ifont,iundoref,itep,itep2,itep2b,iimgw,iimgh,iimgw2,iimgh2:longint;
    ibutarea1,ibutarea2:twinrect;
    iscale,iprogress:single;
    iundodataOK,idropstatic,ireveal,iflash:boolean;
    fonreturn,fonshowpass,fonchange,fonclick2,fonclick1:tnotifyevent;

    procedure settep(x:longint);
    procedure settep2(x:longint);
    procedure settep2b(x:longint);
    procedure setvalue(x:string);
    procedure setprogress(x:single);
    procedure xcheckref;
    function xshowcursor:boolean;
    procedure xnotidle;
    procedure settitle(x:string);
    function xundoautofill(xref:longint):boolean;//pass-thru proc
    procedure xundofill;
    procedure xfindsync;
    function xlineheight:longint;
    procedure setscale(x:single);

   public

    //options
    olimit:longint;//0=no limit, 1..max32=limit content to this length
    oreadonly:boolean;
    opassword:boolean;//default=false, true=PASSWORD mode and thus option to hide chars and display a mask char "#"
    oborder2:boolean;//default=false, true=draw border around tep2
    omoreoptions:boolean;//default=true=full right click menu of options, false=brief right click menu - 31mar2021
    osysfind_textsync:boolean;//default=false, true=mirror text to "sysfind_text" - 18feb2023
    ohardleft:boolean;//default=false, true=text stops at left margin and shoots off the right side -> for drop lists - 27jul2024
    odel_clearstext:boolean;//default=false, true=pressing the delete key will clear all text - 09mar2025
    orightbut_narrowfocus:boolean;//default=false=dropdown list right button animates when button OR text area is clicked, true=right button animates only when button itself is clicked - 09mar2025
    ocmd2:string;//default=nil, set to an internal command e.g. "edit.visit" and when 2nd button (right) is click this command will fire - 19apr2025
    oshowborder:boolean;//default=true, 24may2025

    //create
    constructor create(xparent:tobject;xcaption:string); virtual;
    constructor create2(xparent:tobject;xstart:boolean;xcaption:string); virtual;
    destructor destroy; override;
    function getalignheight(xclientwidth:longint):longint; override;//11dec2025
    procedure showmenuFill(xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string); override;
    function showmenuClick(sender:tobject;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean; override;

    //information
    property caption;
    property title:string read ititle write settitle;
    property value:string read ivalue write setvalue;
    property progress:single read iprogress write setprogress;
    property tep:longint read itep write settep;//left
    property tep2:longint read itep2 write settep2;//right
    property tep2b:longint read itep2b write settep2b;//right
    property buthelp:string read ibuthelp write ibuthelp;
    property buthelp2:string read ibuthelp2 write ibuthelp2;
    property reveal:boolean read ireveal write ireveal;//for password mode only - 13apr2020
    property showpass:boolean read ireveal write ireveal;//18jun2022
    property scale:single read iscale write setscale;//09mar2025

    //.undo - 19jun2022
    function canundo:boolean;
    function undo:boolean;
    function undoclear:boolean;

    //.password support
    function canclearpassword:boolean;
    function clearpassword:boolean;
    function canpastepassword:boolean;
    function pastepassword:boolean;

    //.visit
    function canvisit(var xurl:string):boolean;

    //makers
    procedure makefind;
    procedure makeedit;
    procedure makepass;
    procedure makedrop;
    procedure makedropstatic;
    procedure makeprogress;

    //events
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;//28nov2025
    function  _onshortcut(sender:tobject):boolean; override;//01mar2022
    function  _onnotify(sender:tobject):boolean; override;
    property  onclick2:tnotifyevent read fonclick2 write fonclick2;//tep #2 - right
    property  onclick1:tnotifyevent read fonclick1 write fonclick1;//tep #1 - left
    property onreturn:tnotifyevent read fonreturn write fonreturn;//09mar2025
    property onchange:tnotifyevent read fonchange write fonchange;
    property onshowpass:tnotifyevent read fonshowpass write fonshowpass;

    //support
    procedure xchanged;
    procedure xshowpass;

   end;


{tbasicjump}
   tbasicjump=class(tbasiccontrol)
   private
    ipainttimer,inewref,itimer250,ihoveref:comp;
    ispeed,ilastmousex,ilasthoverpos,ihoverpos,ipos,ilen,istatus:longint;
    ifont:tresslot;
    iref:boolean;
    iflashval9,iflashval,ipower,ihoverpert,ipert:double;//06mar2022
    ipaintref:string;
    fonclick:tnotifyevent;
    procedure xsyncpos;//20feb2022
    procedure setstatus(x:longint);
    procedure setflashval(x:double);
    procedure setflashval9(x:double);
    procedure setpower(x:double);
   public

    olarge        :boolean;//default=false
    oms           :boolean;
    oscaleh       :single;//scale tweaker

    //create
    constructor create(xparent:tobject;xcaption:string); virtual;
    constructor create2(xparent:tobject;xstart:boolean;xcaption:string); virtual;
    destructor destroy; override;
    function getalignheight(xclientwidth:longint):longint; override;//13dec2025, 11dec2025, 05sep2025

    //information
    procedure setparams(xpos,xlen,xspeed:longint);//in milliseconds (xpos,xlen) and speed(10-1000%)
    property hoverpos:longint read ihoverpos;
    property hoverpert:double read ihoverpert;//0..100
    property pert:double read ipert;//0..100
    property pos:longint read ipos;
    property len:longint read ilen;
    property speed:longint read ispeed;
    property status:longint read istatus write setstatus;//0=off(default), 1=elapsed time, 2=remaining time
    procedure moveby(x:longint);
    procedure jumpto(x:longint);
    property flashval:double read iflashval write setflashval;//0..1
    property flashval9:double read iflashval9 write setflashval9;//0..1
    property power:double read ipower write setpower;//0..1

    //events
    procedure _ontimer(sender:tobject); override;
    procedure _onpaint(sender:tobject); override;//24oct2025: optimised coloring viewing for dark and light color schemes, 16sep2025: improved color variation for light backgrounds, 13sep2025, 05sep2025, 21aug2025
    function  _onnotify(sender:tobject):boolean; override;
    property  onclick:tnotifyevent read fonclick write fonclick;

   end;

{tmainhelp}
   tmainhelp=class(tbasicscroll)
   private

    ifasttimer:comp;
    ibwp:tbasicbwp;
    itopics:tdynamicstring;//list of help topics
    ibuildingcontrol:boolean;
    irootmin,irootmax,irootsize:longint32;

    procedure __onclick(sender:tobject);
    procedure xhelptopics;//24apr2025
    procedure _ontimer(sender:tobject); override;
    procedure showmenuFill(xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string); override;
    function showmenuClick(sender:tobject;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean; override;
    function xrootsizeScaled:longint32;
    procedure xchangerootsize(const xby:longint);

   public

    //create
    constructor create2(xparent:tobject;xscroll,xstart:boolean); override;
    destructor destroy; override;

    //info
    procedure xsetroundstyle(x:longint);

   end;

{tplaylist}
   tplaylist=class(tobjectex)
   private
    ilistcoreUNDO,ilistcoreFULL,ilistcore:tstr8;
    ilistcoreCANUNDO:boolean;
    ifilenameOPEN,ifilenameSAVE,ipartmask,ifullmask:string;
    ilist:tbasicmenu;
    iopenfilter,ilistcoreUNDO_itemindex,ilistcoreid:longint;
    procedure setlist(x:tbasicmenu);
    function xcopy(xall,xcut:boolean;var e:string):boolean;
    function xpaste(xclear:boolean;var e:string):boolean;
    function xundo(var e:string):boolean;
    procedure setpartmask(x:string);
    procedure setfullmask(x:string);
   public
    //create
    constructor create; override;//20mar2022
    destructor destroy; override;//20mar2022
    //internal support
    function xguiOK:boolean;
    function xgui:tbasicsystem;
    function xlistitem(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;
    procedure xfillundo;
    procedure xmask(xforce:boolean);
    procedure xlistsync;
    //information
    property id:longint read ilistcoreid;
    function listok:boolean;
    property list:tbasicmenu read ilist write setlist;//pointer only -> use to automaticaly sync with a list control - 20mar2022
    property partmask:string read ipartmask write setpartmask;//used to filter from ilistcoreFULL to ilistcore (e.g. only "*.mid")
    property fullmask:string read ifullmask write setfullmask;//used to filter paste/open to ilistcoreFULL (e.g. *.rmi;*.mid;*.midi)
    //new -> prompt to clear
    function cannew:boolean;
    function new(var e:string):boolean;
    //clear
    function canclear:boolean;
    function clear(var e:string):boolean;
    //cut
    function cancut:boolean;
    function cut(var e:string):boolean;
    //copy
    function cancopy:boolean;
    function copy(var e:string):boolean;
    //copy all
    function cancopyall:boolean;
    function copyall(var e:string):boolean;
    //paste
    function canpaste:boolean;
    function paste(var e:string):boolean;
    //replace - 19apr2022
    function canreplace:boolean;
    function replace(var e:string):boolean;
    //open
    function canopen:boolean;
    function open(var e:string):boolean;
    //save
    function cansave:boolean;
    function save(var e:string):boolean;
    //undo
    function canundo:boolean;
    function undo(var e:string):boolean;
    //file
    function canaddfile:boolean;
    function addfile(const xfilename:string;var e:string):boolean;
    //command handler
    function xcmd(n:string;var e:string):boolean;
    //open support
    function xopen(var e:string):boolean;
    function xopen2(xfilename:string;xindex:longint;xprompt,afillundo:boolean;var e:string):boolean;
    //save support
    function xsave(var e:string):boolean;
    function xsave2(dfilename:string;xprompt:boolean;var e:string):boolean;
    //add support
    function xadd(xdata:tstr8;xindex:longint;xauthoritativeFilename:string;xclear:boolean):boolean;
    function xaddone(xsec:longint;xtitle,xfilename:string):boolean;
   end;


const

//color schemes ----------------------------------------------------------------

//new built-in colors - 09nov2025, 31mar2025, 09may2021
cols_BurntYellow:array[0..83] of byte=(99,111,108,50,1,0,0,0,2,35,32,3,50,25,23,2,51,0,0,0,52,176,162,14,53,176,162,14,54,190,175,16,55,25,23,2,56,89,82,8,57,25,23,2,58,0,0,0,100,25,23,2,101,0,0,0,102,176,162,14,103,176,162,14,104,190,175,16,105,210,200,92,106,89,82,8,107,53,49,4,108,0,0,0);
cols_BurntRed:array[0..83] of byte=(99,111,108,50,1,0,0,0,2,35,3,3,50,25,2,2,51,0,0,0,52,163,0,11,53,163,0,11,54,232,0,21,55,219,213,28,56,89,8,8,57,25,2,2,58,25,2,2,100,25,2,2,101,0,0,0,102,163,0,11,103,163,0,11,104,232,0,21,105,219,213,28,106,89,8,8,107,25,2,2,108,25,2,2);
cols_BurntPurple:array[0..83] of byte=(99,111,108,50,1,0,0,0,2,26,0,26,50,18,0,20,51,0,0,0,52,63,0,66,53,63,0,66,54,156,0,163,55,27,154,188,56,99,0,104,57,18,0,20,58,0,0,0,100,18,0,20,101,0,0,0,102,63,0,66,103,63,0,66,104,156,0,163,105,27,154,188,106,99,0,104,107,18,0,20,108,0,0,0);
cols_BurntOrange:array[0..83] of byte=(99,111,108,50,1,0,0,0,2,35,14,3,50,25,13,2,51,0,0,0,52,190,98,16,53,190,98,16,54,190,99,16,55,85,42,87,56,89,36,8,57,25,13,2,58,0,0,0,100,25,13,2,101,0,0,0,102,190,98,16,103,190,98,16,104,190,99,16,105,85,42,87,106,89,36,8,107,25,13,2,108,0,0,0);
cols_Eerie:array[0..83] of byte=(99,111,108,50,1,47,17,1,2,61,48,1,50,47,17,1,51,65,38,23,52,148,148,1,53,148,148,1,54,88,120,1,55,148,148,1,56,88,120,1,57,47,17,1,58,65,38,23,100,61,48,1,101,61,48,1,102,32,44,1,103,32,44,1,104,88,120,1,105,148,148,1,106,88,120,1,107,61,48,1,108,61,48,1);
cols_Army:array[0..83] of byte=(99,111,108,50,1,80,84,73,2,205,208,198,50,240,242,235,51,225,227,221,52,184,185,180,53,184,185,180,54,114,117,107,55,255,255,255,56,114,117,107,57,240,242,235,58,240,242,235,100,205,208,198,101,205,208,198,102,112,124,106,103,112,124,106,104,85,88,78,105,235,238,228,106,85,88,78,107,205,208,198,108,205,208,198);

cols_Soft_Green      :array[0..83] of byte=(99,111,108,50,1,113,192,153,2,217,233,217,50,255,255,255,51,217,242,227,52,217,242,227,53,217,242,227,54,100,171,136,55,100,171,136,56,100,171,136,57,255,255,255,58,217,242,227,100,217,233,217,101,217,233,217,102,250,255,255,103,250,255,255,104,75,127,102,105,250,255,255,106,75,127,102,107,217,233,217,108,217,233,217);
cols_Fine_Grey       :array[0..83] of byte=(99,111,108,50,1,41,70,84,2,163,185,196,50,246,246,245,51,246,246,245,52,163,185,196,53,163,185,196,54,89,105,113,55,89,105,113,56,89,105,113,57,246,246,245,58,246,246,245,100,163,185,196,101,163,185,196,102,112,127,135,103,112,127,135,104,43,65,76,105,43,65,76,106,43,65,76,107,163,185,196,108,163,185,196);
cols_Fine_Grey2      :array[0..83] of byte=(99,111,108,50,1,41,70,84,2,163,185,196,50,255,255,255,51,255,255,255,52,209,220,226,53,209,220,226,54,138,149,154,55,104,113,117,56,138,149,154,57,255,255,255,58,255,255,255,100,163,185,196,101,163,185,196,102,112,127,135,103,112,127,135,104,43,65,76,105,43,65,76,106,43,65,76,107,163,185,196,108,163,185,196);
cols_Pale_Yellow     :array[0..83] of byte=(99,111,108,50,1,175,175,141,2,255,255,230,50,249,249,243,51,225,225,208,52,255,255,230,53,255,255,230,54,143,143,97,55,135,135,92,56,135,135,118,57,249,249,243,58,225,225,208,100,255,255,230,101,255,255,230,102,145,145,120,103,145,145,120,104,135,135,110,105,225,225,200,106,135,135,110,107,255,255,230,108,255,255,230);

cols_Marine          :array[0..83] of byte=(99,111,108,50,1,49,84,101,2,196,222,235,50,255,255,255,51,230,252,255,52,194,219,228,53,194,219,228,54,122,144,155,55,107,126,136,56,122,144,155,57,255,255,255,58,230,252,255,100,196,222,235,101,196,222,235,102,152,173,183,103,152,173,183,104,52,78,91,105,232,255,255,106,52,78,91,107,196,222,235,108,196,222,235);

cols_Lilac           :array[0..83] of byte=(99,111,108,50,1,122,122,137,2,252,198,255,50,252,209,255,51,222,179,225,52,142,99,145,53,142,99,145,54,132,89,135,55,222,179,225,56,132,89,135,57,252,209,255,58,222,179,225,100,252,198,255,101,252,198,255,102,142,88,145,103,142,88,145,104,132,78,135,105,222,168,225,106,132,78,135,107,252,198,255,108,252,198,255);

cols_Gold            :array[0..83] of byte=(99,111,108,50,1,158,149,125,2,241,241,174,50,229,228,165,51,199,198,135,52,119,118,55,53,119,118,55,54,109,108,45,55,255,255,195,56,149,148,85,57,229,228,165,58,229,228,165,100,242,242,175,101,212,212,145,102,132,132,65,103,132,132,65,104,122,122,55,105,212,212,145,106,162,162,95,107,242,242,175,108,242,242,175);
cols_Gold2           :array[0..83] of byte=(99,111,108,50,1,158,149,125,2,241,241,174,50,244,244,189,51,199,198,135,52,119,118,55,53,119,118,55,54,109,108,45,55,255,255,195,56,149,148,85,57,244,244,189,58,244,244,189,100,242,242,175,101,212,212,145,102,132,132,65,103,132,132,65,104,122,122,55,105,212,212,145,106,162,162,95,107,242,242,175,108,242,242,175);
cols_Gold3           :array[0..83] of byte=(99,111,108,50,1,152,152,68,2,230,230,166,50,242,242,175,51,242,242,175,52,194,186,112,53,194,186,112,54,122,122,55,55,122,122,55,56,122,122,55,57,242,242,175,58,242,242,175,100,230,230,166,101,230,230,166,102,194,186,112,103,194,186,112,104,122,122,55,105,122,122,55,106,122,122,55,107,230,230,166,108,230,230,166);

cols_Silver_Gold:array[0..83] of byte=(99,111,108,50,1,160,164,152,2,242,242,232,50,255,255,250,51,226,229,218,52,141,141,129,53,141,141,129,54,126,130,107,55,255,255,255,56,126,130,107,57,255,255,250,58,226,229,218,100,242,242,232,101,242,242,232,102,118,121,110,103,118,121,110,104,107,110,99,105,255,255,255,106,107,110,99,107,242,242,232,108,242,242,232);
cols_Grey:array[0..83] of byte=(99,111,108,50,1,69,79,89,2,204,218,233,50,229,239,250,51,217,225,233,52,132,144,157,53,132,144,157,54,99,114,129,55,219,234,249,56,99,114,129,57,229,239,250,58,217,225,233,100,204,218,233,101,204,218,233,102,94,108,123,103,94,108,123,104,47,55,64,105,234,248,255,106,47,55,64,107,204,218,233,108,204,218,233);
cols_Soft_Blue:array[0..83] of byte=(99,111,108,50,1,113,153,192,2,217,233,250,50,255,255,255,51,217,229,243,52,217,229,243,53,217,229,243,54,113,153,192,55,113,153,192,56,113,153,192,57,255,255,255,58,217,229,243,100,217,233,250,101,217,233,250,102,250,255,255,103,250,255,255,104,100,136,170,105,250,255,255,106,100,136,170,107,217,233,250,108,217,233,250);
cols_Emerald:array[0..83] of byte=(99,111,108,50,1,111,161,131,2,141,226,198,50,174,242,226,51,109,205,183,52,21,117,95,53,109,205,183,54,10,106,84,55,109,205,183,56,10,106,84,57,174,242,226,58,109,205,183,100,141,226,198,101,141,226,198,102,20,104,77,103,20,104,77,104,9,94,66,105,174,255,231,106,9,94,66,107,141,226,198,108,141,226,198);
cols_Aqua_Marine:array[0..83] of byte=(99,111,108,50,1,0,144,205,2,126,224,243,50,206,255,255,51,175,242,242,52,115,222,242,53,115,222,242,54,22,105,150,55,22,105,150,56,22,105,150,57,185,255,255,58,185,255,255,100,126,224,243,101,126,224,243,102,0,196,242,103,0,196,242,104,0,84,104,105,127,234,254,106,0,84,104,107,126,224,243,108,126,224,243);
cols_Washed_Crimson:array[0..83] of byte=(99,111,108,50,1,255,177,188,2,254,237,242,50,254,237,242,51,254,237,242,52,255,205,212,53,255,205,212,54,134,117,122,55,134,117,122,56,134,117,122,57,254,237,242,58,254,237,242,100,254,237,242,101,254,237,242,102,255,177,188,103,255,177,188,104,119,109,119,105,119,109,119,106,119,109,119,107,254,237,242,108,254,237,242);
cols_Dusty_Pink:array[0..83] of byte=(99,111,108,50,1,207,173,178,2,246,224,219,50,250,246,246,51,225,216,216,52,236,200,196,53,236,200,196,54,142,126,126,55,142,126,126,56,142,126,126,57,250,246,246,58,225,216,216,100,246,224,219,101,246,224,219,102,163,135,136,103,163,135,136,104,111,92,93,105,249,242,243,106,99,92,93,107,227,212,213,108,227,212,213);
cols_Golden_Sands:array[0..83] of byte=(99,111,108,50,1,157,132,82,2,240,221,192,50,252,244,224,51,221,205,160,52,170,158,125,53,170,158,125,54,154,144,91,55,252,244,224,56,154,144,91,57,252,244,224,58,221,205,160,100,240,221,192,101,240,221,192,102,130,111,82,103,130,111,82,104,120,101,72,105,210,191,162,106,120,101,72,107,240,221,192,108,240,221,192);
cols_Fern:array[0..83] of byte=(99,111,108,50,1,103,72,103,2,188,219,188,50,219,255,219,51,189,225,189,52,170,220,170,53,170,220,170,54,99,135,99,55,104,136,104,56,99,135,99,57,219,255,219,58,189,225,189,100,188,219,188,101,188,219,188,102,199,232,199,103,199,232,199,104,71,90,71,105,71,90,71,106,71,90,71,107,188,219,188,108,188,219,188);
cols_Tangerine:array[0..83] of byte=(99,111,108,50,1,145,54,54,2,255,164,164,50,255,203,203,51,225,173,173,52,255,164,164,53,255,164,164,54,135,83,83,55,135,83,83,56,135,83,83,57,255,203,203,58,255,203,203,100,255,164,164,101,255,164,164,102,209,134,134,103,209,134,134,104,135,44,44,105,135,44,44,106,135,44,44,107,255,164,164,108,255,164,164);

cols_Moon_Blue:array[0..83] of byte=(99,111,108,50,1,63,130,175,2,103,170,215,50,152,201,233,51,149,190,217,52,83,150,195,53,83,150,195,54,23,90,135,55,23,90,135,56,23,90,135,57,152,201,233,58,149,190,217,100,103,170,215,101,103,170,215,102,92,147,184,103,92,147,184,104,23,90,135,105,153,220,255,106,23,90,135,107,103,170,215,108,103,170,215);
cols_Howdy_Brown:array[0..83] of byte=(99,111,108,50,1,131,83,35,2,195,154,113,50,251,213,176,51,251,213,176,52,221,173,125,53,221,173,125,54,141,93,45,55,141,93,45,56,141,93,45,57,251,213,176,58,251,213,176,100,195,154,113,101,195,154,113,102,251,213,176,103,251,213,176,104,133,84,35,105,133,84,35,106,133,84,35,107,195,154,113,108,195,154,113);
cols_Chirpy_Charcoal:array[0..83] of byte=(99,111,108,50,1,38,38,38,2,59,59,59,50,59,59,59,51,51,51,51,52,144,144,144,53,144,144,144,54,162,162,162,55,220,220,220,56,162,162,162,57,59,59,59,58,51,51,51,100,59,59,59,101,59,59,59,102,144,144,144,103,144,144,144,104,162,162,162,105,220,220,220,106,146,146,146,107,58,58,58,108,58,58,58);

cols_DarkRedTint     :array[0..83] of byte=(99,111,108,50,1,4,2,2,2,37,13,13,50,19,0,0,51,19,0,0,52,73,47,47,53,73,47,47,54,162,153,153,55,162,153,153,56,162,153,153,57,19,0,0,58,19,0,0,100,37,13,13,101,37,13,13,102,73,47,47,103,73,47,47,104,162,153,153,105,162,153,153,106,162,153,153,107,36,13,13,108,36,13,13);
cols_DarkRedTint2    :array[0..83] of byte=(99,111,108,50,1,13,5,5,2,37,13,13,50,37,13,13,51,37,13,13,52,73,47,47,53,73,47,47,54,162,153,153,55,162,153,153,56,162,153,153,57,37,13,13,58,37,13,13,100,37,13,13,101,37,13,13,102,73,47,47,103,73,47,47,104,162,153,153,105,162,153,153,106,162,153,153,107,36,13,13,108,36,13,13);

cols_DarkAquaTint    :array[0..83] of byte=(99,111,108,50,1,15,30,30,2,32,42,42,50,16,19,19,51,16,19,19,52,127,162,162,53,127,162,162,54,143,152,152,55,16,19,19,56,112,112,112,57,16,19,19,58,16,19,19,100,32,42,42,101,32,42,42,102,127,162,162,103,127,162,162,104,143,152,152,105,16,19,19,106,143,152,152,107,32,42,42,108,32,42,42);
cols_DarkAquaTint2   :array[0..83] of byte=(99,111,108,50,1,15,30,30,2,32,42,42,50,24,36,36,51,47,55,55,52,127,162,162,53,127,162,162,54,143,152,152,55,62,62,62,56,112,112,112,57,24,36,36,58,47,55,55,100,32,42,42,101,32,42,42,102,127,162,162,103,127,162,162,104,143,152,152,105,62,62,62,106,143,152,152,107,32,42,42,108,32,42,42);

cols_DarkBlueTint    :array[0..83] of byte=(99,111,108,50,1,15,15,30,2,31,31,44,50,16,16,22,51,16,16,22,52,110,112,127,53,110,112,127,54,157,159,169,55,157,159,169,56,157,159,169,57,16,16,22,58,16,16,22,100,31,31,44,101,31,31,44,102,54,57,78,103,54,57,78,104,152,152,152,105,152,152,152,106,152,152,152,107,32,32,42,108,32,32,42);
cols_DarkBlueTint2   :array[0..83] of byte=(99,111,108,50,1,15,15,30,2,31,31,44,50,31,31,44,51,2,2,2,52,110,112,127,53,110,112,127,54,157,159,169,55,2,2,2,56,157,159,169,57,32,32,37,58,2,2,2,100,31,31,44,101,31,31,44,102,54,57,78,103,54,57,78,104,152,152,152,105,62,62,62,106,152,152,152,107,32,32,42,108,32,32,42);

cols_DarkEmerald     :array[0..83] of byte=(99,111,108,50,1,15,30,30,2,2,36,36,50,1,20,20,51,1,20,20,52,132,148,148,53,132,148,148,54,160,170,170,55,1,20,20,56,160,170,170,57,1,20,20,58,1,20,20,100,2,36,36,101,2,36,36,102,132,148,148,103,132,148,148,104,160,170,170,105,1,20,20,106,160,170,170,107,2,36,36,108,2,36,36);
cols_DarkEmerald2    :array[0..83] of byte=(99,111,108,50,1,15,30,30,2,2,36,36,50,2,36,36,51,6,48,48,52,132,148,148,53,132,148,148,54,160,170,170,55,62,62,62,56,112,112,112,57,2,36,36,58,6,48,48,100,2,36,36,101,2,36,36,102,132,148,148,103,132,148,148,104,160,170,170,105,62,62,62,106,160,170,170,107,2,36,36,108,2,36,36);

cols_DarkGreenTint   :array[0..83] of byte=(99,111,108,50,1,15,30,30,2,1,36,13,50,13,19,15,51,13,19,15,52,34,64,47,53,34,64,47,54,146,161,153,55,146,161,153,56,146,161,153,57,13,19,15,58,13,19,15,100,1,36,13,101,1,36,13,102,34,64,47,103,34,64,47,104,146,161,153,105,146,161,153,106,146,161,153,107,1,36,13,108,1,36,13);
cols_DarkGreenTint2  :array[0..83] of byte=(99,111,108,50,1,15,30,30,2,1,36,13,50,1,27,10,51,1,27,10,52,34,64,47,53,34,64,47,54,146,161,153,55,146,161,153,56,146,161,153,57,1,27,10,58,1,27,10,100,1,36,13,101,1,36,13,102,34,64,47,103,34,64,47,104,146,161,153,105,146,161,153,106,146,161,153,107,1,36,13,108,1,36,13);

cols_DarkYellowTint  :array[0..83] of byte=(99,111,108,50,1,2,2,0,2,36,36,0,50,19,19,0,51,19,19,0,52,73,73,47,53,128,128,109,54,162,162,147,55,162,162,147,56,162,162,147,57,19,19,0,58,19,19,0,100,36,36,0,101,36,36,0,102,73,73,47,103,128,128,109,104,162,162,147,105,162,162,147,106,162,162,147,107,36,36,0,108,36,36,0);
cols_DarkYellowTint2 :array[0..83] of byte=(99,111,108,50,1,14,14,0,2,36,36,0,50,32,32,0,51,32,32,0,52,73,73,47,53,128,128,109,54,162,162,147,55,162,162,147,56,162,162,147,57,32,32,0,58,32,32,0,100,36,36,0,101,36,36,0,102,73,73,47,103,128,128,109,104,162,162,147,105,162,162,147,106,162,162,147,107,36,36,0,108,36,36,0);

cols_Dreamy_Cream    :array[0..83] of byte=(99,111,108,50,1,175,175,141,2,255,255,230,50,255,255,236,51,233,232,214,52,206,203,160,53,206,203,160,54,168,166,131,55,255,255,238,56,168,166,131,57,255,255,238,58,225,225,208,100,255,255,230,101,255,255,230,102,145,145,120,103,145,145,120,104,135,135,110,105,135,135,110,106,135,135,110,107,255,255,230,108,255,255,230);
cols_Dreamy_Cream2   :array[0..83] of byte=(99,111,108,50,1,175,175,141,2,242,242,220,50,249,249,231,51,249,249,231,52,212,175,197,53,212,175,197,54,135,135,110,55,135,135,110,56,135,135,110,57,249,249,231,58,249,249,231,100,242,242,220,101,242,242,220,102,212,175,197,103,212,175,197,104,135,135,110,105,135,135,110,106,135,135,110,107,242,242,220,108,242,242,220);

cols_Gentle_Ginger   :array[0..83] of byte=(99,111,108,50,1,160,68,59,2,255,228,228,50,255,228,228,51,255,200,193,52,196,130,123,53,196,130,123,54,163,119,115,55,255,200,193,56,163,119,115,57,255,228,228,58,255,228,228,100,255,228,228,101,255,228,228,102,196,130,123,103,196,130,123,104,163,119,115,105,255,208,202,106,163,119,115,107,255,228,228,108,255,228,228);
cols_Gentle_Ginger2  :array[0..83] of byte=(99,111,108,50,1,160,68,59,2,242,217,217,50,255,228,228,51,255,228,228,52,196,130,123,53,196,130,123,54,163,119,115,55,255,208,202,56,163,119,115,57,255,228,228,58,255,228,228,100,242,217,217,101,242,217,217,102,196,130,123,103,196,130,123,104,163,119,115,105,255,208,202,106,163,119,115,107,242,217,217,108,242,217,217);

cols_Grumpy_Green:array[0..83] of byte=(99,111,108,50,1,16,41,0,2,116,141,81,50,179,192,163,51,164,174,150,52,93,116,64,53,93,116,64,54,0,9,0,55,179,192,163,56,0,9,0,57,179,192,163,58,164,174,150,100,116,141,81,101,70,98,56,102,10,18,10,103,10,18,10,104,0,8,0,105,130,158,116,106,0,8,0,107,116,141,81,108,70,98,56);



cols_Glowing_Grey    :array[0..83] of byte=(99,111,108,50,1,125,125,113,2,253,253,245,50,253,253,245,51,226,226,203,52,125,125,117,53,163,163,146,54,125,125,117,55,255,255,243,56,125,125,117,57,253,253,245,58,226,226,203,100,253,253,245,101,253,253,245,102,255,249,210,103,255,249,210,104,125,125,113,105,125,125,113,106,125,125,113,107,253,253,245,108,253,253,245);
cols_glowing_grey2   :array[0..83] of byte=(99,111,108,50,1,125,125,113,2,253,253,245,50,253,253,245,51,253,253,245,52,125,125,117,53,163,163,146,54,125,125,117,55,125,125,117,56,125,125,117,57,253,253,245,58,253,253,245,100,241,241,233,101,241,241,233,102,217,212,178,103,217,212,178,104,125,125,113,105,125,125,113,106,125,125,113,107,241,241,233,108,241,241,233);


cols_Jovial_Mauve:array[0..83] of byte=(99,111,108,50,1,168,139,175,2,248,219,242,50,248,219,247,51,228,207,227,52,138,109,137,53,188,166,194,54,140,114,139,55,234,228,236,56,140,114,139,57,248,219,247,58,228,207,227,100,248,219,242,101,248,219,242,102,138,109,132,103,138,109,132,104,140,114,139,105,140,114,139,106,140,114,139,107,248,219,242,108,248,219,242);
cols_Luscious_Lilac:array[0..83] of byte=(99,111,108,50,1,214,117,228,2,255,159,255,50,255,221,255,51,255,182,255,52,176,78,188,53,176,78,188,54,162,65,176,55,255,182,255,56,162,65,176,57,255,221,255,58,255,182,255,100,255,159,255,101,255,159,255,102,188,16,153,103,188,16,153,104,133,2,106,105,255,120,255,106,133,2,106,107,255,159,255,108,255,159,255);
cols_Slinky_Pink:array[0..83] of byte=(99,111,108,50,1,158,38,133,2,238,114,195,50,244,170,219,51,244,170,219,52,238,114,195,53,238,114,195,54,122,1,77,55,122,1,77,56,122,1,77,57,244,170,219,58,244,170,219,100,238,114,195,101,238,114,195,102,235,84,182,103,235,84,182,104,122,1,56,105,130,9,65,106,122,1,56,107,238,114,195,108,238,114,195);
cols_Rosebud_Pink:array[0..83] of byte=(99,111,108,50,1,255,89,170,2,255,155,218,50,255,242,242,51,241,214,226,52,255,142,214,53,255,142,214,54,183,101,153,55,255,226,249,56,135,74,100,57,255,237,244,58,241,214,226,100,255,155,218,101,255,155,218,102,255,67,159,103,255,67,159,104,159,60,106,105,159,60,106,106,159,60,106,107,255,155,218,108,255,155,218);
cols_Silky_Sand:array[0..83] of byte=(99,111,108,50,1,212,167,66,2,255,239,136,50,255,240,153,51,224,211,134,52,152,143,0,53,152,143,0,54,124,104,33,55,255,240,153,56,124,104,33,57,255,240,153,58,224,211,134,100,255,239,136,101,255,239,136,102,145,129,26,103,145,129,26,104,135,119,16,105,225,209,106,106,135,119,16,107,255,239,136,108,255,239,136);
cols_Red:array[0..83] of byte=(99,111,108,50,1,178,37,37,2,255,81,81,50,255,220,220,51,244,183,185,52,255,85,85,53,255,85,85,54,222,74,74,55,252,245,245,56,255,85,85,57,255,220,220,58,244,183,185,100,255,81,81,101,255,81,81,102,242,185,184,103,242,185,184,104,242,242,242,105,242,242,242,106,242,242,242,107,255,81,81,108,255,81,81);
cols_Radiant_Yellow:array[0..83] of byte=(99,111,108,50,1,201,201,112,2,255,255,159,50,255,255,220,51,247,247,154,52,255,255,159,53,255,255,159,54,114,122,1,55,114,122,1,56,114,122,1,57,255,255,220,58,247,247,154,100,255,255,159,101,255,255,159,102,123,130,9,103,123,130,9,104,114,122,1,105,195,202,24,106,114,122,1,107,255,255,159,108,255,255,159);
cols_Peach:array[0..83] of byte=(99,111,108,50,1,214,192,174,2,255,226,208,50,255,246,246,51,255,237,226,52,255,225,205,53,255,225,205,54,149,118,101,55,149,118,101,56,149,118,101,57,255,246,246,58,242,242,242,100,255,226,208,101,255,226,208,102,133,114,95,103,133,114,95,104,127,90,67,105,242,242,242,106,127,90,67,107,255,239,231,108,255,239,231);
cols_Tangy_Tangerine:array[0..83] of byte=(99,111,108,50,1,205,60,59,2,255,110,109,50,255,168,142,51,255,168,142,52,255,110,109,53,255,110,109,54,135,25,0,55,135,25,0,56,135,25,0,57,255,168,142,58,255,168,142,100,255,110,109,101,255,110,109,102,205,60,59,103,205,60,59,104,145,10,10,105,145,10,10,106,145,10,10,107,255,110,109,108,255,110,109);
cols_white_and_pale:array[0..83] of byte=(99,111,108,50,1,206,204,176,2,255,255,249,50,253,251,252,51,223,221,222,52,237,239,213,53,237,239,213,54,133,131,132,55,133,131,132,56,133,131,132,57,253,251,252,58,223,221,222,100,255,255,249,101,255,255,249,102,237,239,213,103,237,239,213,104,130,130,118,105,220,220,208,106,130,130,118,107,255,255,249,108,255,255,249);
cols_Wild_Thing:array[0..83] of byte=(99,111,108,50,1,0,106,118,2,70,206,218,50,122,221,122,51,92,191,92,52,12,111,12,53,12,111,12,54,2,101,2,55,152,251,152,56,42,141,42,57,122,221,122,58,122,221,122,100,255,192,0,101,225,162,0,102,145,82,10,103,145,82,10,104,135,72,0,105,225,162,0,106,175,112,0,107,255,192,0,108,255,192,0);
cols_Wild_Thing_Pastel:array[0..83] of byte=(99,111,108,50,1,0,106,118,2,255,230,155,50,187,237,187,51,149,189,149,52,149,189,149,53,149,189,149,54,2,101,2,55,152,251,152,56,2,101,2,57,187,237,187,58,187,237,187,100,255,230,155,101,189,136,0,102,145,82,10,103,145,82,10,104,135,72,0,105,225,162,0,106,175,112,0,107,255,230,155,108,255,230,155);
cols_black:array[0..83] of byte=(99,111,108,50,1,0,0,0,2,27,27,27,50,27,27,27,51,0,0,0,52,157,157,157,53,157,157,157,54,147,147,147,55,57,57,57,56,147,147,147,57,27,27,27,58,0,0,0,100,27,27,27,101,27,27,27,102,157,157,157,103,157,157,157,104,147,147,147,105,57,57,57,106,147,147,147,107,27,27,27,108,27,27,27);
cols_black2:array[0..83] of byte=(99,111,108,50,1,0,0,0,2,27,27,27,50,27,27,27,51,0,0,0,52,51,119,155,53,74,172,224,54,147,147,147,55,147,147,147,56,147,147,147,57,27,27,27,58,0,0,0,100,27,27,27,101,27,27,27,102,74,172,224,103,74,172,224,104,147,147,147,105,147,147,147,106,147,147,147,107,27,27,27,108,27,27,27);//09mar2025: updated with a slightly darker highlight color for use with textbox
cols_black3:array[0..83] of byte=(99,111,108,50,1,1,1,1,2,18,18,18,50,10,10,10,51,1,1,1,52,74,172,224,53,74,172,224,54,211,211,211,55,211,211,211,56,211,211,211,57,1,1,1,58,10,10,10,100,18,18,18,101,18,18,18,102,74,172,224,103,74,172,224,104,211,211,211,105,211,211,211,106,211,211,211,107,18,18,18,108,18,18,18);
cols_black4:array[0..83] of byte=(99,111,108,50,1,1,1,1,2,32,32,32,50,32,32,32,51,1,1,1,52,25,59,73,53,25,59,73,54,176,176,176,55,176,176,176,56,176,176,176,57,32,32,32,58,1,1,1,100,32,32,32,101,32,32,32,102,25,59,73,103,25,59,73,104,176,176,176,105,176,176,176,106,176,176,176,107,32,32,32,108,32,32,32);
cols_black5:array[0..83] of byte=(99,111,108,50,1,9,9,9,2,35,35,35,50,10,10,10,51,1,1,1,52,74,172,224,53,74,172,224,54,211,211,211,55,10,10,10,56,211,211,211,57,1,1,1,58,10,10,10,100,35,35,35,101,35,35,35,102,74,172,224,103,74,172,224,104,211,211,211,105,10,10,10,106,211,211,211,107,35,35,35,108,35,35,35);

cols_blue:array[0..83] of byte=(99,111,108,50,1,26,96,255,2,146,216,255,50,249,255,255,51,249,255,255,52,146,216,255,53,146,216,255,54,69,108,202,55,69,108,202,56,69,108,202,57,249,255,255,58,249,255,255,100,146,216,255,101,146,216,255,102,103,150,236,103,103,150,236,104,2,36,202,105,2,36,202,106,2,36,202,107,146,216,255,108,146,216,255);
cols_royal_blue:array[0..83] of byte=(99,111,108,50,1,0,0,255,2,77,119,255,50,245,245,245,51,245,245,245,52,138,170,255,53,138,170,255,54,0,0,255,55,0,0,255,56,0,0,255,57,245,245,245,58,245,245,245,100,77,119,255,101,77,119,255,102,237,237,237,103,237,237,237,104,0,0,135,105,0,0,135,106,0,0,135,107,77,119,255,108,77,119,255);
cols_pink:array[0..83] of byte=(99,111,108,50,1,209,129,196,2,255,223,252,50,255,223,252,51,255,223,252,52,255,179,243,53,255,179,243,54,122,86,117,55,122,86,117,56,122,86,117,57,255,223,252,58,255,223,252,100,255,223,252,101,255,223,252,102,255,158,240,103,255,158,240,104,122,86,117,105,122,86,117,106,122,86,117,107,255,223,252,108,255,223,252);
cols_wild_mix:array[0..83] of byte=(99,111,108,50,1,175,172,0,2,235,232,25,50,249,136,255,51,219,106,225,52,139,26,145,53,139,26,145,54,129,16,135,55,219,106,225,56,169,56,175,57,249,136,255,58,249,136,255,100,77,233,255,101,47,203,225,102,10,123,145,103,10,123,145,104,0,113,135,105,47,203,225,106,0,153,175,107,77,233,255,108,77,233,255);
cols_white:array[0..83] of byte=(99,111,108,50,1,210,210,210,2,255,255,255,50,255,255,255,51,214,214,214,52,204,232,255,53,204,232,255,54,65,65,65,55,65,65,65,56,65,65,65,57,255,255,255,58,214,214,214,100,255,255,255,101,255,255,255,102,204,232,255,103,204,232,255,104,65,65,65,105,65,65,65,106,65,65,65,107,255,255,255,108,255,255,255);
cols_white2:array[0..83] of byte=(99,111,108,50,1,210,210,210,2,255,255,255,50,255,255,255,51,214,214,214,52,166,165,165,53,166,165,165,54,65,65,65,55,214,214,214,56,65,65,65,57,255,255,255,58,255,255,255,100,255,255,255,101,225,225,225,102,166,165,165,103,166,165,165,104,65,65,65,105,225,225,225,106,65,65,65,107,255,255,255,108,255,255,255);
cols_white3:array[0..83] of byte=(99,111,108,50,1,210,210,210,2,255,255,255,50,255,255,255,51,214,214,214,52,204,232,255,53,204,232,255,54,139,139,139,55,139,139,139,56,139,139,139,57,255,255,255,58,214,214,214,100,255,255,255,101,255,255,255,102,204,232,255,103,204,232,255,104,139,139,139,105,139,139,139,106,139,139,139,107,255,255,255,108,255,255,255);
cols_white4:array[0..83] of byte=(99,111,108,50,1,210,210,210,2,255,255,255,50,255,255,255,51,214,214,214,52,166,165,165,53,166,165,165,54,139,139,139,55,214,214,214,56,139,139,139,57,255,255,255,58,255,255,255,100,255,255,255,101,225,225,225,102,166,165,165,103,166,165,165,104,139,139,139,105,225,225,225,106,139,139,139,107,255,255,255,108,255,255,255);
cols_white5:array[0..83] of byte=(99,111,108,50,1,210,210,210,2,255,255,255,50,249,249,249,51,249,249,249,52,204,232,255,53,204,232,255,54,139,139,139,55,139,139,139,56,139,139,139,57,249,249,249,58,249,249,249,100,255,255,255,101,255,255,255,102,204,232,255,103,204,232,255,104,139,139,139,105,139,139,139,106,139,139,139,107,255,255,255,108,255,255,255);
cols_white6:array[0..83] of byte=(99,111,108,50,1,37,37,37,2,101,101,101,50,249,249,249,51,255,255,255,52,204,232,255,53,204,232,255,54,139,139,139,55,139,139,139,56,139,139,139,57,255,255,255,58,255,255,255,100,101,101,101,101,101,101,101,102,204,232,255,103,204,232,255,104,239,239,239,105,239,239,239,106,239,239,239,107,101,101,101,108,101,101,101);
cols_white7:array[0..83] of byte=(99,111,108,50,1,37,37,37,2,23,23,23,50,249,249,249,51,249,249,249,52,204,232,255,53,204,232,255,54,139,139,139,55,139,139,139,56,139,139,139,57,249,249,249,58,249,249,249,100,23,23,23,101,23,23,23,102,204,232,255,103,204,232,255,104,240,240,240,105,239,239,239,106,239,239,239,107,23,23,23,108,23,23,23);
cols_satinpink:array[0..83] of byte=(99,111,108,50,1,115,83,113,2,251,223,255,50,254,248,255,51,224,218,225,52,255,196,249,53,255,196,249,54,134,128,135,55,143,111,145,56,174,168,175,57,254,248,255,58,254,248,255,100,253,221,255,101,223,191,225,102,239,165,198,103,239,165,198,104,133,101,135,105,143,111,145,106,173,141,175,107,253,221,255,108,253,221,255);
cols_satinpink2:array[0..83] of byte=(99,111,108,50,1,115,83,113,2,251,223,255,50,253,241,254,51,255,255,255,52,255,196,249,53,255,196,249,54,134,128,135,55,143,111,145,56,174,168,175,57,253,241,254,58,253,241,254,100,253,221,255,101,253,221,255,102,239,165,198,103,239,165,198,104,133,101,135,105,143,111,145,106,173,141,175,107,253,221,255,108,253,221,255);
cols_purple:array[0..83] of byte=(99,111,108,50,1,137,106,160,2,214,163,250,50,251,236,255,51,211,179,234,52,201,134,255,53,201,134,255,54,124,83,158,55,255,251,255,56,124,83,158,57,251,236,255,58,211,179,234,100,214,163,250,101,214,163,250,102,207,78,255,103,207,78,255,104,97,65,124,105,255,251,255,106,97,65,124,107,214,163,250,108,214,163,250);
cols_brown:array[0..83] of byte=(99,111,108,50,1,90,43,0,2,192,165,138,50,255,227,187,51,255,227,187,52,147,119,79,53,147,119,79,54,135,107,67,55,255,227,187,56,135,107,67,57,255,227,187,58,255,227,187,100,192,165,138,101,192,165,138,102,126,89,56,103,126,89,56,104,86,59,32,105,86,59,32,106,86,59,32,107,192,165,138,108,192,165,138);
cols_brown2:array[0..83] of byte=(99,111,108,50,1,90,43,0,2,192,165,138,50,255,233,203,51,255,233,203,52,211,188,150,53,211,188,150,54,135,107,67,55,135,107,67,56,135,107,67,57,255,233,203,58,255,233,203,100,192,165,138,101,192,165,138,102,126,89,56,103,126,89,56,104,86,59,32,105,86,59,32,106,86,59,32,107,192,165,138,108,192,165,138);
cols_brown3:array[0..83] of byte=(99,111,108,50,1,140,93,45,2,209,184,159,50,242,230,212,51,242,230,212,52,209,184,159,53,209,184,159,54,130,83,35,55,130,83,35,56,130,83,35,57,242,230,212,58,242,230,212,100,209,184,159,101,209,184,159,102,161,137,108,103,161,137,108,104,130,83,35,105,130,83,35,106,130,83,35,107,209,184,159,108,209,184,159);

cols_deep_purple  :array[0..83] of byte=(99,111,108,50,1,16,0,23,2,34,1,49,50,13,1,18,51,13,1,18,52,143,2,204,53,143,2,204,54,156,92,184,55,13,1,18,56,156,92,184,57,13,1,18,58,13,1,18,100,34,1,49,101,34,1,49,102,143,2,204,103,143,2,204,104,156,92,184,105,13,1,18,106,156,92,184,107,34,1,49,108,34,1,49);
cols_deep_purple2 :array[0..83] of byte=(99,111,108,50,1,11,11,11,2,42,42,42,50,12,12,12,51,1,1,1,52,179,3,255,53,179,3,255,54,156,92,184,55,12,12,12,56,156,92,184,57,1,1,1,58,12,12,12,100,42,42,42,101,42,42,42,102,179,3,255,103,179,3,255,104,156,92,184,105,12,12,12,106,156,92,184,107,42,42,42,108,42,42,42);

cols_deep_pink    :array[0..83] of byte=(99,111,108,50,1,23,4,20,2,51,8,45,50,13,0,9,51,13,0,9,52,205,12,148,53,205,12,148,54,184,94,170,55,13,0,9,56,184,94,170,57,13,0,9,58,13,0,9,100,51,10,41,101,51,10,41,102,205,12,148,103,205,12,148,104,184,94,170,105,13,0,9,106,184,94,170,107,51,10,41,108,51,10,41);
cols_deep_pink2   :array[0..83] of byte=(99,111,108,50,1,1,0,1,2,42,42,42,50,13,0,9,51,13,0,9,52,205,12,148,53,205,12,148,54,184,94,170,55,13,0,9,56,184,94,170,57,13,0,9,58,13,0,9,100,42,42,42,101,42,42,42,102,205,12,148,103,205,12,148,104,184,94,170,105,13,0,9,106,184,94,170,107,42,42,42,108,42,42,42);

cols_deep_candypink :array[0..83] of byte=(99,111,108,50,1,23,0,15,2,51,0,33,50,13,0,8,51,13,0,8,52,253,0,166,53,253,0,166,54,184,13,124,55,13,0,8,56,184,13,124,57,13,0,8,58,13,0,8,100,51,0,33,101,51,0,33,102,253,0,166,103,253,0,166,104,184,13,124,105,13,0,8,106,184,13,124,107,51,0,33,108,51,0,33);
cols_deep_candypink2:array[0..83] of byte=(99,111,108,50,1,0,0,0,2,42,42,42,50,13,0,8,51,13,0,8,52,253,0,166,53,253,0,166,54,184,13,124,55,13,0,8,56,184,13,124,57,13,0,8,58,13,0,8,100,42,42,42,101,42,42,42,102,253,0,166,103,253,0,166,104,184,13,124,105,13,0,8,106,184,13,124,107,42,42,42,108,42,42,42);

cols_deep_red     :array[0..83] of byte=(99,111,108,50,1,26,8,10,2,43,13,17,50,18,0,2,51,18,0,2,52,171,0,24,53,171,0,24,54,209,115,128,55,18,0,2,56,209,115,128,57,18,0,2,58,18,0,2,100,43,13,17,101,43,13,17,102,214,0,30,103,214,0,30,104,209,115,128,105,18,0,2,106,209,115,128,107,43,13,17,108,43,13,17);
cols_deep_red2    :array[0..83] of byte=(99,111,108,50,1,0,0,0,2,42,42,42,50,0,0,0,51,0,0,0,52,171,0,24,53,171,0,24,54,209,115,128,55,0,0,0,56,209,115,128,57,0,0,0,58,0,0,0,100,42,42,42,101,42,42,42,102,214,0,30,103,214,0,30,104,209,115,128,105,0,0,0,106,209,115,128,107,42,42,42,108,42,42,42);

cols_deep_yellow  :array[0..83] of byte=(99,111,108,50,1,12,12,0,2,26,26,0,50,14,14,0,51,14,14,0,52,241,241,0,53,241,241,0,54,194,194,124,55,14,14,0,56,194,194,124,57,14,14,0,58,14,14,0,100,26,26,0,101,26,26,0,102,241,241,0,103,241,241,0,104,194,194,124,105,14,14,0,106,194,194,124,107,48,48,0,108,48,48,0);
cols_deep_yellow2 :array[0..83] of byte=(99,111,108,50,1,11,11,11,2,42,42,42,50,12,12,12,51,1,1,1,52,241,241,0,53,241,241,0,54,194,194,124,55,12,12,12,56,194,194,124,57,1,1,1,58,12,12,12,100,42,42,42,101,42,42,42,102,241,241,0,103,241,241,0,104,194,194,124,105,12,12,12,106,194,194,124,107,42,42,42,108,42,42,42);

cols_deep_orange  :array[0..83] of byte=(99,111,108,50,1,39,24,6,2,46,36,24,50,16,8,0,51,16,8,0,52,252,135,0,53,252,135,0,54,255,234,163,55,16,8,0,56,255,234,163,57,16,8,0,58,16,8,0,100,46,36,24,101,46,36,24,102,252,135,0,103,252,135,0,104,255,234,163,105,16,8,0,106,255,234,163,107,46,36,24,108,46,36,24);
cols_deep_orange2 :array[0..83] of byte=(99,111,108,50,1,11,11,11,2,42,42,42,50,12,12,12,51,1,1,1,52,252,135,0,53,252,135,0,54,255,234,163,55,12,12,12,56,255,234,163,57,1,1,1,58,12,12,12,100,42,42,42,101,42,42,42,102,252,135,0,103,252,135,0,104,255,234,163,105,12,12,12,106,255,234,163,107,42,42,42,108,42,42,42);

cols_deep_royal_blue  :array[0..83] of byte=(99,111,108,50,1,3,1,33,2,5,1,51,50,7,5,18,51,25,23,34,52,25,3,255,53,25,3,255,54,129,125,162,55,7,5,18,56,129,125,162,57,7,5,18,58,7,5,18,100,5,1,51,101,5,1,51,102,25,3,255,103,25,3,255,104,129,125,162,105,7,5,18,106,129,125,162,107,5,1,51,108,5,1,51);
cols_deep_royal_blue2 :array[0..83] of byte=(99,111,108,50,1,0,0,0,2,42,42,42,50,9,7,24,51,9,7,24,52,25,3,255,53,25,3,255,54,129,125,162,55,9,7,24,56,129,125,162,57,1,1,1,58,1,1,1,100,42,42,42,101,42,42,42,102,25,3,255,103,25,3,255,104,129,125,162,105,9,7,24,106,129,125,162,107,42,42,42,108,42,42,42);

cols_deep_blue    :array[0..83] of byte=(99,111,108,50,1,0,10,15,2,0,28,43,50,0,12,19,51,0,12,19,52,0,139,215,53,0,139,215,54,132,193,229,55,0,12,19,56,132,193,229,57,0,12,19,58,0,12,19,100,0,28,43,101,0,28,43,102,0,139,215,103,0,139,215,104,132,193,229,105,0,12,19,106,132,193,229,107,0,28,43,108,0,28,43);
cols_deep_blue2   :array[0..83] of byte=(99,111,108,50,1,0,0,0,2,42,42,42,50,0,12,19,51,0,12,19,52,0,139,215,53,0,139,215,54,132,193,229,55,0,12,19,56,132,193,229,57,0,12,19,58,0,12,19,100,42,42,42,101,42,42,42,102,0,139,215,103,0,139,215,104,132,193,229,105,0,12,19,106,132,193,229,107,42,42,42,108,42,42,42);

cols_deep_green   :array[0..83] of byte=(99,111,108,50,1,14,17,9,2,27,34,18,50,6,11,0,51,6,11,0,52,140,246,0,53,140,246,0,54,185,217,139,55,6,11,0,56,185,217,139,57,6,11,0,58,6,11,0,100,27,34,18,101,27,34,18,102,140,246,0,103,140,246,0,104,185,217,139,105,6,11,0,106,185,217,139,107,27,34,18,108,27,34,18);
cols_deep_green2  :array[0..83] of byte=(99,111,108,50,1,0,0,0,2,42,42,42,50,0,0,0,51,0,0,0,52,140,246,0,53,140,246,0,54,185,217,139,55,0,0,0,56,185,217,139,57,0,0,0,58,0,0,0,100,42,42,42,101,42,42,42,102,140,246,0,103,140,246,0,104,185,217,139,105,0,0,0,106,185,217,139,107,42,42,42,108,42,42,42);

cols_deep_lime    :array[0..83] of byte=(99,111,108,50,1,26,8,10,2,34,44,1,50,8,11,0,51,8,11,0,52,168,219,3,53,168,219,3,54,134,175,2,55,8,11,0,56,134,175,2,57,8,11,0,58,8,11,0,100,34,44,1,101,34,44,1,102,168,219,3,103,168,219,3,104,134,175,2,105,8,11,0,106,134,175,2,107,18,0,2,108,18,0,2);
cols_deep_lime2   :array[0..83] of byte=(99,111,108,50,1,0,0,0,2,42,42,42,50,8,11,0,51,8,11,0,52,168,219,3,53,168,219,3,54,134,175,2,55,8,11,0,56,134,175,2,57,8,11,0,58,8,11,0,100,42,42,42,101,42,42,42,102,168,219,3,103,168,219,3,104,134,175,2,105,8,11,0,106,134,175,2,107,42,42,42,108,42,42,42);

cols_deep_aqua    :array[0..83] of byte=(99,111,108,50,1,0,22,22,2,0,48,50,50,0,19,20,51,0,19,20,52,0,194,202,53,0,194,202,54,0,175,182,55,0,19,20,56,0,175,182,57,0,19,20,58,0,19,20,100,0,48,50,101,0,48,50,102,0,194,202,103,0,194,202,104,0,175,182,105,0,19,20,106,0,175,182,107,0,48,50,108,0,48,50);
cols_deep_aqua2   :array[0..83] of byte=(99,111,108,50,1,0,0,0,2,42,42,42,50,0,19,20,51,0,19,20,52,0,194,202,53,0,194,202,54,0,175,182,55,0,19,20,56,0,175,182,57,0,19,20,58,0,19,20,100,42,42,42,101,42,42,42,102,0,194,202,103,0,194,202,104,0,175,182,105,0,19,20,106,0,175,182,107,42,42,42,108,42,42,42);

cols_light_and_lilac   :array[0..83] of byte=(99,111,108,50,1,197,211,249,2,220,231,245,50,241,241,241,51,241,241,241,52,210,201,255,53,164,147,255,54,134,132,178,55,134,132,178,56,134,132,178,57,241,241,241,58,241,241,241,100,220,231,245,101,241,241,241,102,210,201,255,103,164,147,255,104,134,132,178,105,134,132,178,106,134,132,178,107,241,241,241,108,241,241,241);
cols_light_and_blue    :array[0..83] of byte=(99,111,108,50,1,182,196,234,2,220,231,245,50,241,241,241,51,241,241,241,52,199,223,252,53,199,223,252,54,121,125,145,55,121,125,145,56,121,125,145,57,241,241,241,58,241,241,241,100,220,231,245,101,220,231,245,102,199,223,252,103,199,223,252,104,121,125,145,105,121,125,145,106,121,125,145,107,220,231,245,108,220,231,245);
cols_light_and_pink    :array[0..83] of byte=(99,111,108,50,1,205,175,195,2,241,206,229,50,241,241,241,51,241,241,241,52,255,156,220,53,255,156,220,54,166,122,150,55,166,122,150,56,166,122,150,57,241,241,241,58,241,241,241,100,241,206,229,101,241,206,229,102,255,156,220,103,255,156,220,104,166,122,150,105,166,122,150,106,166,122,150,107,241,206,229,108,241,206,229);
cols_light_and_warm    :array[0..83] of byte=(99,111,108,50,1,166,153,114,2,255,242,203,50,241,241,241,51,241,241,241,52,255,235,175,53,242,224,170,54,153,141,105,55,153,141,105,56,153,141,105,57,241,241,241,58,241,241,241,100,249,236,199,101,249,236,199,102,255,235,175,103,242,224,170,104,153,141,105,105,153,141,105,106,153,141,105,107,249,236,199,108,249,236,199);
cols_light_and_salmon  :array[0..83] of byte=(99,111,108,50,1,204,157,180,2,255,196,225,50,241,241,241,51,241,241,241,52,255,214,234,53,255,214,234,54,163,137,150,55,163,137,150,56,163,137,150,57,241,241,241,58,241,241,241,100,255,196,225,101,255,196,225,102,255,214,234,103,255,214,234,104,147,124,135,105,147,124,135,106,147,124,135,107,255,196,225,108,255,196,225);
cols_light_and_grey    :array[0..83] of byte=(99,111,108,50,1,130,130,130,2,217,217,217,50,241,241,241,51,241,241,241,52,217,217,217,53,217,217,217,54,122,122,122,55,122,122,122,56,122,122,122,57,241,241,241,58,241,241,241,100,217,217,217,101,217,217,217,102,178,178,178,103,178,178,178,104,122,122,122,105,122,122,122,106,122,122,122,107,217,217,217,108,217,217,217);
cols_light_and_aqua    :array[0..83] of byte=(99,111,108,50,1,185,217,216,2,218,255,254,50,242,242,242,51,242,242,242,52,218,255,254,53,73,255,254,54,108,147,146,55,108,147,146,56,108,147,146,57,242,242,242,58,242,242,242,100,218,255,254,101,218,255,254,102,218,255,254,103,73,255,254,104,108,147,146,105,108,147,146,106,108,147,146,107,218,255,254,108,218,255,254);
cols_light_and_orange  :array[0..83] of byte=(99,111,108,50,1,255,228,160,2,255,239,200,50,255,249,235,51,255,249,235,52,255,226,154,53,255,202,71,54,175,137,43,55,175,137,43,56,175,137,43,57,255,249,235,58,255,249,235,100,255,235,184,101,255,235,184,102,255,226,154,103,255,202,71,104,175,137,43,105,175,137,43,106,175,137,43,107,255,235,184,108,255,235,184);
cols_light_and_lime    :array[0..83] of byte=(99,111,108,50,1,196,252,89,2,219,253,156,50,255,249,235,51,255,249,235,52,200,252,102,53,164,250,0,54,107,162,0,55,107,162,0,56,107,162,0,57,255,249,235,58,255,249,235,100,228,253,180,101,228,253,180,102,200,252,102,103,164,250,0,104,107,162,0,105,107,162,0,106,107,162,0,107,228,253,180,108,228,253,180);
cols_light_and_mustard :array[0..83] of byte=(99,111,108,50,1,194,176,51,2,227,220,163,50,255,249,235,51,255,249,235,52,209,196,102,53,206,191,89,54,143,125,0,55,143,125,0,56,143,125,0,57,255,249,235,58,255,249,235,100,227,220,163,101,227,220,163,102,209,196,102,103,206,191,89,104,143,125,0,105,143,125,0,106,143,125,0,107,227,220,163,108,227,220,163);

cols_black_and_pink    :array[0..83] of byte=(99,111,108,50,1,255,35,175,2,64,20,48,50,14,0,4,51,14,0,4,52,255,35,175,53,255,35,175,54,255,79,191,55,14,0,4,56,255,79,191,57,14,0,4,58,14,0,4,100,14,0,4,101,14,0,4,102,255,35,175,103,255,35,175,104,255,79,191,105,14,0,4,106,255,79,191,107,14,0,4,108,14,0,4);
cols_black_and_orange  :array[0..83] of byte=(99,111,108,50,1,238,116,0,2,46,23,0,50,14,0,4,51,14,0,4,52,238,116,0,53,238,116,0,54,242,151,64,55,14,0,4,56,242,151,64,57,14,0,4,58,14,0,4,100,14,0,4,101,14,0,4,102,238,116,0,103,238,116,0,104,242,151,64,105,14,0,4,106,242,151,64,107,14,0,4,108,14,0,4);

cols_black_and_aqua    :array[0..83] of byte=(99,111,108,50,1,31,212,255,2,5,32,38,50,2,11,13,51,2,11,13,52,31,212,255,53,31,212,255,54,65,218,255,55,2,11,13,56,65,218,255,57,11,20,22,58,2,11,13,100,2,11,13,101,2,11,13,102,31,212,255,103,31,212,255,104,65,218,255,105,2,11,13,106,65,218,255,107,2,11,13,108,2,11,13);

cols_dos               :array[0..83] of byte=(99,111,108,50,1,1,0,126,2,2,0,203,50,3,0,254,51,253,253,253,52,253,253,253,53,253,253,253,54,253,253,253,55,3,0,254,56,253,253,253,57,3,0,254,58,3,0,254,100,2,0,203,101,2,0,203,102,253,253,253,103,253,253,253,104,253,253,253,105,253,253,253,106,253,253,253,107,2,0,203,108,2,0,203);


//background images ------------------------------------------------------------
back_none:array[0..0] of byte=(0);

back_plaster:array[0..21602] of byte=(
255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,255,219,0,67,0,16,11,12,14,12,10,16,14,13,14,18,17,16,19,24,40,26,24,22,22,24,49,35,37,29,40,58,51,61,60,57,51,56,55,64,72,92,78,64,68,87,69,55,56,80,109,81,87,95,98,103,104,103,62,77,113,121,112,100,120,92,101,103,99,255,219,0,67,1,17,18,18,24,21,24,47,26,26,47,99,66,56,66,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,255,192,0,17,8,1,38,1,38,3,1,34,0,2,17,1,3,17,1,255,196,0,31,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,
153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250,255,196,0,31,1,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,17,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119,0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,247,248,249,250,255,218,0,12,3,1,0,2,17,3,17,0,63,0,220,184,140,222,44,113,219,
24,132,100,239,115,130,25,120,235,143,207,173,96,221,92,79,167,94,22,141,140,114,12,171,49,31,124,19,159,226,29,122,127,156,214,167,218,109,108,85,227,137,26,87,124,23,32,149,224,103,29,125,63,66,106,164,48,46,177,125,39,159,185,31,1,134,209,133,0,112,125,242,114,59,246,169,99,70,130,220,91,27,72,37,146,234,8,229,142,52,44,207,32,200,202,142,167,60,231,159,206,171,234,23,197,45,113,15,154,141,32,85,12,73,24,234,73,238,58,99,158,249,227,165,102,93,143,177,79,44,51,131,42,39,62,96,202,176,200,28,237,239,192,253,106,116,31,107,210,246,203,33,135,231,34,32,228,146,20,38,237,160,103,191,249,237,72,13,141,62,4,142,206,55,148,49,154,85,5,164,147,230,36,144,51,207,249,233,89,111,166,207,117,44,207,111,36,106,177,179,13,206,252,179,6,231,60,112,122,246,244,250,212,49,193,119,53,236,87,80,207,190,85,25,218,236,126,98,50,219,72,207,176,227,138,233,109,35,100,72,216,195,18,153,62,105,61,67,30,125,243,201,52,214,160,97,234,112,65,3,65,111,110,251,165,66,237,243,156,231,56,234,64,199,65,210,
153,167,42,253,166,49,36,177,198,193,131,238,45,195,99,57,207,233,143,199,154,173,127,49,123,169,39,129,25,84,183,0,19,156,115,207,62,167,7,241,166,218,204,22,126,80,239,63,46,115,131,158,132,126,35,140,82,3,126,43,161,113,105,34,203,118,138,36,109,160,128,1,193,199,249,239,92,241,181,149,46,201,140,170,163,179,24,208,183,221,25,56,25,61,63,250,255,0,90,208,183,201,186,219,50,168,140,38,252,183,3,24,224,231,7,169,165,158,100,89,4,207,31,203,128,118,237,219,131,142,120,232,51,215,28,208,4,182,218,68,241,106,11,115,12,234,45,203,238,56,57,249,125,6,125,106,189,245,138,219,221,72,145,101,99,101,12,197,137,193,61,240,121,56,255,0,235,213,155,125,68,171,43,136,246,145,247,213,78,21,134,63,201,206,63,74,109,228,194,251,107,103,106,145,144,163,159,215,252,254,185,163,160,21,222,8,27,203,140,202,202,200,195,12,156,50,31,114,122,227,142,152,173,216,222,57,0,84,153,92,174,55,21,53,142,145,47,240,160,98,48,114,127,81,205,87,153,221,97,104,237,228,81,12,159,43,160,95,152,243,208,142,221,
249,247,239,66,208,11,247,186,181,177,133,146,41,93,203,110,27,144,12,116,234,15,245,168,237,175,45,152,43,226,79,48,140,49,99,184,3,235,156,231,61,63,207,21,153,21,176,141,2,237,231,239,5,36,103,191,165,60,40,149,192,92,51,159,188,6,104,187,3,165,85,142,71,44,164,57,92,140,14,199,167,248,254,180,139,28,152,117,152,6,89,50,27,11,131,233,207,175,20,219,24,188,168,149,217,220,229,112,20,30,0,250,127,159,231,78,189,154,72,109,218,116,228,5,200,94,185,57,255,0,61,251,85,8,134,214,17,96,151,44,92,178,12,18,165,49,211,61,9,235,212,126,53,51,182,39,3,168,25,200,239,158,63,250,255,0,165,83,91,248,220,37,172,247,8,243,72,229,2,174,28,16,88,128,78,56,232,7,30,253,42,120,33,242,84,249,160,22,3,36,131,215,215,250,210,25,52,162,45,164,73,30,65,234,7,95,211,154,100,79,40,117,204,44,163,31,194,217,192,30,160,244,252,51,78,142,72,230,151,9,150,41,215,3,63,175,67,77,155,83,179,183,251,243,142,78,62,64,91,7,223,29,40,2,85,62,108,76,37,135,129,194,131,130,79,3,252,72,252,42,59,91,118,182,93,134,
70,96,216,218,172,112,19,233,233,199,110,156,113,85,222,241,80,201,63,152,210,91,8,193,17,133,193,39,156,156,254,67,252,230,151,74,188,146,246,38,145,182,170,2,84,3,156,231,131,249,115,69,192,98,218,180,154,200,158,72,216,136,144,237,144,112,1,57,233,142,190,159,78,188,242,109,197,10,44,113,174,75,237,227,115,114,79,185,254,85,29,212,146,91,93,91,186,172,178,9,15,150,118,227,104,36,140,19,248,247,250,213,27,15,48,94,93,202,24,149,105,29,118,242,64,96,126,246,61,0,20,1,117,230,221,8,120,25,88,176,59,113,200,39,156,126,184,172,11,143,181,253,172,172,178,52,146,46,57,67,140,31,229,198,69,111,8,146,20,142,43,120,149,19,35,0,231,229,254,124,214,94,172,179,70,209,186,192,128,202,229,2,161,203,73,192,11,159,203,167,108,123,210,96,141,139,37,205,148,107,51,101,198,6,88,99,220,99,215,140,127,156,211,216,16,74,132,60,245,57,199,212,214,85,132,18,94,89,202,146,79,114,141,3,249,103,231,28,17,140,129,131,159,233,200,199,122,211,139,121,133,119,202,100,200,207,152,192,6,250,96,0,63,151,227,
205,49,18,22,218,197,120,25,56,245,62,184,170,26,173,164,50,236,142,234,232,69,19,17,133,207,60,117,35,219,156,147,206,0,236,51,155,251,80,149,103,25,32,16,167,174,61,127,144,170,19,90,91,234,119,83,136,238,75,60,97,85,215,5,130,28,228,122,100,253,225,248,154,0,117,197,160,16,180,151,132,25,48,54,135,124,0,221,118,128,48,15,127,115,84,237,35,141,238,7,154,4,72,220,176,45,247,142,120,228,253,106,85,150,206,226,120,252,133,103,135,229,98,87,118,64,80,112,78,225,211,7,167,255,0,170,150,238,33,230,18,185,10,192,48,44,121,231,145,144,65,238,167,175,233,64,22,50,151,5,74,91,17,212,40,192,61,56,201,231,223,243,161,172,154,53,15,203,30,167,35,167,29,58,230,169,68,241,199,34,79,25,49,186,183,166,71,185,235,220,19,158,159,133,106,163,172,193,33,156,33,222,187,149,0,108,17,142,255,0,225,64,11,108,177,91,195,184,73,149,118,44,11,113,214,138,138,242,123,87,30,84,146,132,85,57,4,28,103,142,49,142,162,138,96,102,190,201,165,134,210,246,38,87,24,77,200,220,182,113,140,246,233,223,39,233,233,
163,105,103,20,115,9,97,12,23,110,20,239,200,57,207,80,58,246,253,42,27,77,90,214,85,86,157,86,55,192,254,13,197,155,190,49,159,238,143,243,205,106,176,203,16,72,30,158,166,128,50,228,142,73,38,187,251,77,180,77,22,84,69,144,27,43,140,158,220,114,1,231,53,29,173,140,81,44,139,44,11,34,200,228,141,170,0,79,111,243,233,87,111,86,66,241,37,180,175,28,155,247,48,218,14,87,32,16,7,226,63,173,81,212,181,79,177,50,44,112,179,182,3,16,221,49,147,192,255,0,19,211,222,165,141,18,88,91,136,46,220,231,56,5,83,11,128,1,32,243,234,70,63,83,75,170,221,76,34,123,117,218,91,157,231,5,112,51,192,247,227,243,252,107,38,45,118,229,238,139,148,142,52,86,218,35,61,24,246,36,251,30,152,169,29,214,119,37,149,99,50,101,179,156,128,73,246,250,208,159,64,43,164,44,217,45,26,141,167,229,244,254,85,44,80,162,62,66,103,4,28,156,242,115,216,84,141,11,68,185,220,74,227,131,207,35,215,57,166,110,39,8,167,99,99,43,143,173,32,44,93,77,112,81,21,78,216,250,144,63,139,216,255,0,135,74,130,229,21,97,5,8,108,42,131,
128,1,4,231,63,92,99,175,189,72,165,151,110,55,16,123,159,206,137,147,207,101,40,131,105,108,31,155,39,31,135,214,152,16,71,230,18,1,36,38,58,3,244,237,249,84,219,157,6,89,72,94,129,179,140,241,255,0,214,171,81,217,236,88,242,140,219,211,27,152,16,20,14,228,142,57,230,160,84,87,201,66,1,28,0,221,122,127,245,241,138,0,141,157,210,37,85,99,181,122,158,231,158,41,161,78,29,216,161,56,249,114,50,79,115,199,245,169,222,44,163,40,145,48,160,13,163,169,29,255,0,151,95,106,83,10,168,220,249,222,173,247,73,237,215,60,208,5,116,204,159,116,140,30,72,94,114,126,164,127,250,170,104,225,82,223,48,60,243,216,83,177,31,152,66,228,21,234,172,112,122,244,167,51,12,39,149,201,10,119,14,184,254,180,196,78,151,187,93,16,48,68,12,1,124,243,143,198,155,60,55,44,237,110,136,172,91,4,183,114,51,199,242,254,117,72,149,123,168,132,196,42,23,27,247,113,197,106,217,105,173,105,35,186,78,197,72,198,210,123,224,114,127,95,206,128,50,167,179,185,138,231,114,101,100,71,220,178,247,56,227,161,237,90,208,249,
205,104,167,205,5,216,159,153,186,129,254,61,113,255,0,214,171,13,0,0,249,99,140,159,151,154,168,26,43,103,144,152,217,35,43,230,25,81,75,33,207,82,113,207,76,127,145,70,195,35,84,150,218,121,93,50,177,144,24,0,192,110,32,116,36,253,106,89,146,59,168,132,138,2,185,92,166,236,119,236,106,55,154,38,223,52,130,217,173,78,10,191,150,72,97,223,36,247,234,7,167,161,168,111,147,205,1,109,193,134,13,193,203,161,35,113,237,140,118,239,159,110,216,205,43,128,235,157,56,73,110,176,249,204,131,182,209,215,142,71,184,169,173,161,146,198,218,8,99,85,112,135,247,141,206,88,115,156,15,92,227,138,203,55,87,130,233,153,155,108,131,56,207,203,140,242,61,185,252,171,99,76,148,203,166,218,179,51,202,242,71,184,151,231,36,30,121,199,228,59,246,207,90,73,220,111,66,157,208,159,80,102,141,27,203,108,227,113,4,108,25,237,238,112,58,122,83,236,180,193,29,151,217,203,43,50,62,242,73,200,98,112,123,250,12,127,156,154,184,139,42,137,36,140,47,220,4,64,141,193,56,245,199,215,156,127,42,200,184,188,186,153,
68,82,62,206,242,52,103,13,215,238,241,208,126,188,81,234,35,69,39,222,178,187,21,84,70,219,184,250,247,252,121,252,115,81,5,150,127,40,249,3,59,176,36,80,1,143,13,198,51,159,79,204,116,230,136,112,52,200,227,155,229,64,55,187,168,35,129,200,31,151,7,131,237,86,226,242,157,114,132,178,174,2,96,238,7,233,131,199,255,0,170,152,18,70,240,137,89,80,162,179,54,93,118,140,183,29,120,252,57,252,40,201,243,36,220,129,16,14,29,136,193,255,0,14,255,0,227,215,13,150,96,177,155,136,195,201,133,217,229,170,253,230,221,143,243,237,158,181,28,76,111,45,24,220,35,42,202,72,49,114,54,128,72,235,128,121,226,152,134,189,224,137,131,52,145,36,76,126,83,230,12,18,14,15,127,90,108,58,125,177,134,117,12,92,93,55,152,206,188,142,185,24,61,59,228,126,53,156,250,116,144,198,29,36,18,60,114,249,153,67,220,123,127,123,32,117,173,105,174,82,4,30,116,136,174,160,22,81,156,158,123,15,192,255,0,94,148,33,152,118,239,41,184,68,135,96,101,36,151,136,49,45,215,183,115,215,208,212,203,110,247,11,26,163,9,29,207,
202,224,240,72,29,115,253,61,190,149,61,166,157,182,233,150,230,41,139,42,111,24,198,210,115,200,4,126,88,250,246,197,35,68,177,92,249,33,200,84,125,202,219,57,249,87,119,210,144,8,144,188,114,184,104,129,116,198,241,193,29,56,246,25,230,156,166,104,225,19,72,134,68,220,87,50,157,217,63,143,61,170,120,175,236,252,167,80,210,58,144,71,239,8,37,142,114,8,4,251,231,36,127,74,170,215,86,113,137,79,145,251,226,152,84,39,134,57,228,244,24,228,14,71,183,74,98,42,92,203,25,153,182,224,130,115,153,62,98,79,94,123,103,158,180,84,83,96,0,166,49,199,166,104,164,48,65,177,36,149,14,113,141,184,249,64,35,208,255,0,158,181,169,123,172,181,193,54,246,48,202,229,177,146,188,54,220,2,113,239,212,126,21,143,23,206,167,4,224,3,215,28,143,203,173,62,53,184,182,188,12,153,73,20,129,181,148,99,63,79,113,64,29,68,81,236,184,50,187,1,180,97,115,143,148,1,207,36,103,191,175,111,174,105,106,247,54,150,170,139,123,32,65,42,16,120,39,7,215,28,145,250,254,180,145,78,250,157,155,237,85,28,38,72,56,231,32,176,
3,208,125,121,231,143,92,239,16,105,229,236,22,234,92,172,203,41,82,65,59,72,232,14,57,231,1,121,235,235,210,155,216,21,174,58,61,52,153,218,63,52,41,57,216,113,156,128,70,79,234,63,58,109,226,11,123,133,69,144,22,85,27,179,140,6,62,153,237,76,211,53,85,146,40,132,208,47,153,2,133,89,122,238,231,7,28,112,118,254,125,241,79,189,47,44,139,32,220,84,240,1,94,64,207,78,158,213,35,106,206,196,169,33,112,170,29,72,85,192,13,254,125,250,211,216,160,10,51,201,56,234,122,250,138,175,1,116,39,43,180,240,184,207,66,77,78,85,92,18,160,156,28,158,41,161,7,200,177,182,115,193,0,3,223,214,151,33,20,182,87,39,24,3,175,62,255,0,149,86,55,27,36,229,177,131,131,145,156,10,149,88,99,60,30,120,4,242,127,194,128,30,192,239,27,24,51,47,204,14,8,42,125,191,78,105,155,49,243,47,94,234,79,74,119,24,228,28,231,191,24,20,167,114,140,110,24,35,167,67,64,14,80,229,179,144,24,231,191,56,7,174,63,17,65,94,118,140,12,12,158,121,61,250,123,212,64,48,148,96,130,21,134,9,239,210,164,243,2,50,224,134,228,252,163,
28,99,7,30,244,0,217,28,166,236,18,56,228,245,197,64,210,43,12,41,32,0,113,134,239,254,125,234,220,174,210,158,54,144,122,143,203,181,80,110,101,96,16,103,39,130,189,79,60,31,74,24,9,50,135,86,108,133,57,199,35,233,86,180,217,231,89,96,141,101,109,190,96,12,138,188,243,158,72,238,58,243,233,244,21,81,154,82,9,25,40,228,131,187,216,115,252,243,249,82,68,31,8,223,58,54,120,37,143,95,80,115,244,160,14,158,107,168,227,149,45,153,183,72,235,234,58,115,146,125,58,26,161,127,106,154,164,171,27,121,143,10,130,187,208,253,195,199,76,247,199,225,249,26,165,5,156,147,74,37,102,37,221,185,102,57,35,143,95,165,107,90,90,45,148,111,26,76,197,25,183,29,199,56,56,199,3,165,48,51,244,181,251,84,51,164,209,70,214,81,72,4,42,135,229,24,39,35,61,91,168,57,61,106,221,227,220,90,218,74,182,240,153,51,242,168,219,144,57,239,142,189,127,65,193,230,173,71,28,113,22,40,171,185,201,102,40,160,100,241,201,255,0,62,148,177,72,90,5,243,134,11,96,50,129,145,158,156,123,80,6,100,90,115,206,131,123,225,89,122,
182,75,103,167,92,214,133,172,34,27,120,160,121,4,134,52,3,39,3,3,232,58,15,240,169,110,54,45,187,23,37,21,70,78,211,143,127,243,205,100,71,170,92,33,70,16,161,140,100,50,2,115,142,220,254,95,94,180,180,65,185,174,21,35,144,20,69,86,192,92,123,14,131,245,253,106,138,105,209,27,150,152,51,72,78,236,29,220,46,73,227,223,169,166,217,234,45,115,114,33,158,5,59,139,96,169,206,209,216,48,252,249,246,30,181,163,187,44,202,62,81,235,192,31,74,55,13,138,210,217,196,175,24,103,93,229,190,64,196,2,113,207,21,99,3,251,255,0,55,215,4,211,34,129,45,213,100,192,220,223,43,227,220,142,121,61,185,245,62,158,242,150,14,9,35,113,207,4,255,0,158,59,211,73,32,184,215,33,114,135,32,55,92,226,146,40,246,28,225,114,195,146,57,200,231,25,63,137,167,55,57,5,122,247,254,148,155,89,91,3,140,115,235,138,4,53,209,54,254,237,0,25,59,184,244,254,89,172,233,180,185,175,47,132,142,232,145,168,1,118,157,205,129,239,235,214,181,9,82,55,12,140,250,175,231,76,19,71,231,198,129,134,100,7,104,232,73,29,64,252,61,232,
2,174,161,45,202,169,48,12,200,120,93,145,29,234,48,51,207,212,122,122,122,86,89,182,185,156,139,183,77,229,129,5,206,6,48,58,241,208,117,231,218,186,60,183,32,17,207,42,115,214,178,53,75,213,142,53,182,182,10,171,141,174,138,1,192,227,0,127,44,123,226,129,153,206,142,227,105,230,64,71,115,145,142,63,17,254,52,139,17,137,247,18,185,63,49,92,156,243,87,180,253,53,110,24,51,187,50,38,73,28,245,232,57,250,115,254,21,60,250,107,27,70,216,3,76,170,118,175,102,57,247,252,58,154,86,3,33,152,51,176,119,198,56,0,30,71,235,210,138,173,20,200,67,43,33,4,30,140,48,127,30,13,20,5,142,143,73,179,54,241,238,13,17,102,35,230,65,233,213,79,227,159,243,197,75,117,96,183,23,134,89,156,121,97,20,4,198,50,65,39,39,243,197,73,27,157,128,188,88,98,79,3,156,115,199,165,72,204,71,115,205,80,134,90,89,195,104,93,163,27,76,132,150,193,227,169,60,14,131,169,170,215,90,157,188,23,34,218,64,146,198,65,222,152,220,79,79,94,6,61,205,76,204,217,124,130,74,240,57,252,106,59,107,8,4,91,222,32,174,121,98,122,138,
64,80,178,209,86,57,46,76,142,72,47,251,174,153,32,28,146,64,239,254,113,82,73,48,70,107,116,59,130,12,124,160,12,103,175,245,53,171,141,184,0,142,157,123,154,207,188,181,193,105,91,118,222,75,109,235,129,207,227,250,80,198,103,22,1,182,133,231,174,65,247,255,0,63,157,73,19,17,187,242,235,75,20,30,99,177,65,242,131,200,200,60,245,253,106,195,91,70,136,178,0,6,6,118,224,131,207,244,164,5,27,132,40,252,245,110,7,31,231,252,253,42,88,128,25,44,9,29,120,62,223,231,243,169,88,13,204,0,36,175,3,35,57,247,160,42,228,5,220,1,94,184,239,64,3,49,18,109,8,81,148,122,103,61,176,42,88,173,166,156,29,187,70,63,137,143,57,237,254,126,181,12,131,100,121,92,0,58,227,214,155,14,160,17,134,224,79,25,83,187,215,29,5,48,38,158,39,135,111,152,206,249,7,5,120,193,233,143,126,222,149,45,194,217,110,43,26,72,160,16,67,227,142,113,201,231,63,202,170,220,93,139,137,28,128,21,119,1,128,114,126,188,241,68,215,98,69,8,65,5,91,39,60,126,98,141,0,158,91,120,97,153,210,54,204,106,187,128,102,237,215,191,191,
227,79,91,56,166,18,59,40,140,179,124,140,6,65,247,231,161,206,106,91,55,179,12,34,243,17,157,206,23,35,142,159,151,235,207,21,124,68,170,161,122,129,217,70,40,176,28,237,189,135,159,28,179,9,100,92,201,132,86,81,146,58,115,254,123,26,182,109,33,182,135,204,117,44,19,0,133,28,158,223,143,165,92,155,228,150,73,29,219,108,104,112,170,7,83,250,230,171,106,23,101,108,209,213,18,112,91,33,128,249,72,201,198,121,255,0,36,118,233,72,9,154,34,96,196,28,54,65,82,125,65,7,156,82,193,185,118,242,50,204,91,3,59,84,116,10,56,244,31,158,126,149,66,215,85,154,238,104,173,133,184,71,35,45,34,140,0,184,200,56,231,29,191,201,171,91,229,5,150,28,151,81,229,135,57,235,215,161,60,241,142,126,180,1,108,186,54,226,58,246,230,156,9,32,255,0,15,184,3,53,21,185,118,132,51,160,87,238,49,138,113,249,195,97,184,166,33,46,96,134,64,169,42,150,92,238,0,103,239,122,241,245,166,174,157,110,114,60,190,167,60,243,252,207,20,146,44,204,234,145,204,84,19,150,232,72,29,241,82,187,157,165,35,125,141,216,145,156,126,
127,90,67,28,2,164,91,101,11,183,56,1,73,199,39,3,241,60,82,198,152,82,118,21,36,228,134,57,63,94,51,215,138,174,94,88,161,220,243,6,43,201,59,70,49,143,111,167,235,77,68,104,196,197,7,204,126,108,22,39,156,147,192,247,39,241,166,5,178,25,152,131,130,8,164,121,35,141,7,153,156,103,128,107,157,75,249,172,45,46,160,243,144,78,172,26,16,80,100,130,121,206,50,9,199,175,169,244,173,77,46,120,239,52,232,214,121,226,154,64,55,72,21,185,82,73,199,29,71,255,0,90,139,136,208,71,71,67,176,143,161,52,216,118,74,60,197,85,108,41,1,192,206,65,199,127,78,148,216,246,228,170,198,81,16,224,57,63,120,245,63,135,79,202,149,54,199,16,72,182,42,39,76,112,61,105,128,215,146,24,75,249,178,34,176,0,157,196,110,3,56,207,211,38,165,65,16,117,43,247,179,158,181,9,85,144,239,69,234,51,184,14,163,235,81,176,145,27,131,242,130,125,56,164,50,232,117,146,49,34,227,7,154,204,158,11,111,54,22,253,228,115,54,199,29,182,156,142,123,140,244,7,25,171,59,4,156,72,50,127,47,243,218,134,128,4,80,163,104,4,145,245,254,
159,133,23,17,57,148,21,83,200,98,56,44,7,28,119,31,149,49,132,201,28,184,145,93,183,100,6,31,40,31,221,252,184,207,62,188,244,170,214,183,2,230,34,200,49,177,177,133,96,121,28,227,142,135,166,65,230,164,242,212,169,78,118,55,24,207,98,58,81,112,33,184,185,146,36,2,221,32,114,73,221,133,32,238,4,130,79,62,223,161,162,172,110,219,128,172,65,236,7,165,20,174,4,73,40,123,233,97,3,110,192,54,156,231,61,61,184,165,154,52,151,106,202,196,174,224,219,114,113,193,200,250,242,5,74,160,19,200,28,243,159,74,113,10,249,59,79,61,73,167,96,33,221,182,7,27,201,44,79,204,59,122,126,66,167,145,136,206,227,207,78,58,138,129,66,249,188,56,206,6,229,31,143,52,199,187,141,25,218,95,221,42,240,11,113,191,232,59,255,0,250,168,2,73,103,9,3,204,171,189,149,78,121,199,215,7,177,166,91,74,237,10,203,46,23,36,237,3,60,142,221,127,201,235,223,20,232,115,50,201,20,139,180,31,186,73,31,50,158,248,234,63,250,226,165,8,165,16,49,201,78,159,203,250,208,4,55,16,165,194,13,164,171,129,242,156,127,63,111,111,106,
175,110,241,3,182,73,19,205,4,231,140,126,21,114,120,85,147,247,152,0,156,115,199,53,90,55,141,247,49,24,36,0,95,167,210,129,144,93,21,85,206,54,128,7,24,233,85,252,193,202,231,24,231,158,127,207,231,90,55,144,179,91,152,204,229,91,0,150,10,112,121,246,250,244,170,22,209,44,171,33,220,193,83,228,203,12,96,255,0,158,59,210,1,198,65,36,120,233,187,158,15,63,143,227,84,202,156,224,0,160,119,110,255,0,136,235,218,173,11,103,154,231,10,22,49,215,145,142,131,63,231,138,208,125,58,221,87,14,238,170,118,169,233,146,78,0,237,239,69,155,3,19,111,151,34,18,21,73,244,31,123,241,167,180,139,146,193,215,4,130,50,115,159,241,168,53,31,58,203,80,100,149,50,172,119,41,24,33,134,79,63,94,105,146,227,230,50,43,164,139,192,13,199,225,245,235,64,23,109,100,142,41,33,243,88,132,73,51,187,96,207,28,227,159,203,252,138,184,53,23,190,212,18,56,35,113,18,22,98,20,242,216,28,19,232,51,142,190,181,148,25,25,80,33,124,145,131,158,64,56,255,0,38,155,20,146,90,93,121,145,170,111,92,140,58,142,15,126,152,199,
95,175,106,96,116,77,8,158,44,137,51,230,128,121,3,211,183,235,235,215,233,77,179,128,219,3,7,202,241,169,221,30,224,119,14,73,57,231,158,216,224,83,149,197,253,186,74,185,88,247,134,218,120,44,7,98,49,235,159,175,173,72,164,200,128,49,229,186,41,60,15,79,243,245,160,8,162,130,53,119,112,177,9,92,183,239,21,64,207,60,130,122,231,142,125,234,66,202,37,203,17,140,126,63,159,227,78,145,198,238,65,27,189,63,206,41,216,86,92,168,31,92,115,64,134,7,82,248,195,2,48,121,238,62,180,214,66,95,3,121,94,184,4,140,251,82,203,251,181,82,172,23,28,156,116,35,189,32,114,248,43,146,7,67,216,210,99,3,111,1,36,148,70,39,142,126,110,135,167,230,41,197,176,72,234,75,102,163,102,153,96,7,106,130,9,24,7,61,248,165,101,84,102,124,145,158,155,135,2,128,27,44,106,74,180,152,38,60,149,39,183,227,78,242,196,152,12,84,129,201,24,227,218,135,249,221,162,12,187,148,141,224,156,237,4,113,254,77,63,113,137,50,228,96,119,61,168,2,133,198,156,146,94,164,230,48,209,128,67,46,6,79,24,28,231,182,122,142,127,74,123,
105,150,242,66,97,242,209,85,95,35,3,57,198,72,13,158,160,103,215,191,106,188,1,56,244,239,81,170,249,108,238,164,225,219,113,199,61,177,211,159,65,69,128,146,49,133,194,182,66,156,115,201,227,212,254,6,154,251,9,85,43,157,217,33,113,144,70,58,31,78,181,5,186,165,185,144,32,218,174,251,182,133,199,56,193,169,150,85,45,128,126,92,124,217,227,174,105,220,9,119,22,7,32,54,58,85,72,162,43,12,17,249,143,188,29,227,158,72,7,56,57,246,192,252,106,80,251,25,159,121,3,30,189,249,200,199,249,253,40,46,120,61,113,156,53,0,54,226,217,37,144,74,205,183,96,7,29,1,193,200,253,70,113,236,42,24,110,149,141,209,129,49,176,255,0,171,43,215,57,59,134,7,114,127,74,5,236,82,200,171,30,247,147,110,74,129,247,115,129,158,126,181,94,19,36,49,201,116,85,160,9,203,174,114,74,1,147,237,238,62,166,144,20,69,246,165,10,152,149,17,94,110,17,222,46,65,36,242,7,3,191,124,214,196,168,200,165,34,219,185,254,102,39,175,190,57,235,233,158,195,25,226,161,139,83,183,107,54,190,6,79,47,118,29,72,251,167,140,126,191,
207,219,133,211,175,86,246,23,18,178,182,27,110,1,221,184,16,8,200,3,182,224,15,184,167,96,184,182,162,234,66,197,228,222,132,12,50,156,109,60,228,16,7,94,70,114,40,169,173,158,25,163,121,161,84,1,156,174,241,198,236,28,125,123,99,240,162,139,1,51,51,146,171,26,224,177,31,120,246,239,250,102,158,185,198,210,184,56,170,207,4,45,122,147,200,65,96,165,81,89,65,199,32,228,28,112,121,199,255,0,170,155,115,124,182,215,40,110,25,35,183,110,3,18,114,92,145,142,157,23,131,146,120,233,248,177,19,177,220,192,36,138,8,127,155,0,18,59,227,219,183,231,74,167,141,219,176,91,159,155,168,167,51,162,74,34,99,146,122,3,207,28,15,243,154,70,27,152,41,11,158,167,223,175,229,218,152,14,137,0,145,164,80,9,112,1,43,140,156,116,207,231,74,229,216,178,198,193,78,49,243,2,121,252,198,71,181,44,125,9,32,237,237,239,78,36,103,36,244,238,123,210,2,181,204,119,13,27,121,51,34,147,193,227,35,31,254,170,173,10,92,219,126,237,81,92,1,185,152,231,159,111,229,90,0,131,247,136,244,166,200,54,38,236,225,7,82,120,
192,164,4,63,126,6,242,229,95,151,44,36,192,224,250,30,48,56,53,151,185,211,80,72,136,88,212,158,2,46,51,223,25,252,63,74,187,115,4,126,115,76,37,149,50,48,241,198,70,24,250,145,131,207,57,252,170,141,176,134,107,214,243,201,147,100,159,35,4,194,156,1,140,251,231,255,0,65,247,164,51,109,25,85,54,236,218,6,78,59,14,167,52,55,153,189,54,76,0,81,243,41,80,65,57,4,31,200,31,207,218,155,113,19,121,76,34,114,141,140,6,3,56,252,233,236,118,175,204,73,245,36,213,8,100,165,29,200,220,138,227,12,114,1,56,29,121,250,19,249,213,25,224,146,27,86,134,22,5,238,36,37,165,147,0,100,156,156,143,160,199,0,116,207,122,189,140,2,64,31,133,12,189,213,182,140,251,80,2,88,194,109,32,88,207,150,92,103,46,7,94,78,63,78,42,8,237,35,55,18,202,237,189,203,157,156,231,96,35,175,63,90,176,251,182,241,215,211,61,106,52,73,195,149,4,109,32,109,193,192,24,246,199,90,0,117,188,112,219,199,229,196,187,87,36,159,152,158,122,117,63,65,72,225,38,220,142,161,145,178,165,79,235,159,202,150,48,237,131,36,187,136,29,16,
96,96,140,242,50,121,166,58,124,233,229,185,202,159,187,221,187,28,230,144,18,54,61,112,122,118,228,210,161,196,103,3,24,237,214,163,152,144,172,50,119,1,250,154,124,97,65,224,147,239,235,66,1,192,146,78,71,124,14,221,169,78,14,63,199,173,70,91,5,136,250,144,70,63,207,255,0,170,144,98,64,254,231,248,120,52,92,9,80,6,118,28,156,0,120,52,56,12,27,32,97,179,187,223,183,255,0,90,161,81,38,65,12,91,7,161,235,138,150,51,177,6,3,112,49,142,226,139,128,50,252,204,1,219,158,73,3,169,224,127,65,80,149,251,100,76,145,204,25,73,42,89,112,79,94,71,167,29,63,250,245,35,146,79,221,39,184,57,170,246,178,43,44,169,2,121,108,142,114,54,129,206,114,127,63,235,69,198,92,80,64,193,227,21,17,118,44,16,33,247,56,227,31,95,243,212,83,99,154,78,67,160,232,114,160,244,30,217,20,237,207,198,210,185,36,117,31,231,222,139,133,133,40,161,118,227,35,28,247,168,221,11,141,200,72,200,245,199,255,0,170,148,169,125,145,169,193,225,131,55,57,246,31,173,62,37,100,202,73,243,55,97,143,74,0,100,81,36,48,164,49,160,
17,170,237,81,158,212,230,28,176,44,164,118,33,133,33,102,68,80,17,89,179,142,79,3,241,2,158,99,71,92,3,129,158,121,199,210,128,24,136,129,72,201,99,208,243,214,134,69,9,32,124,108,113,180,134,198,15,108,115,235,156,83,30,222,69,251,146,129,199,117,200,207,231,207,255,0,94,148,249,145,162,131,130,135,128,192,116,247,255,0,36,208,3,99,181,130,60,170,5,64,196,151,65,200,111,168,244,250,99,165,52,88,218,65,41,186,72,146,39,85,33,140,121,28,123,129,86,23,231,79,157,118,183,25,3,214,171,249,51,121,132,153,10,199,147,242,12,16,114,0,244,200,233,218,128,36,142,80,73,17,128,216,227,35,24,235,207,228,120,231,210,138,138,35,28,68,121,124,110,4,146,123,100,228,245,231,169,162,129,19,136,213,148,52,127,41,29,50,184,198,70,113,80,106,54,31,108,68,82,204,184,202,156,30,128,250,102,175,36,129,135,77,188,231,138,175,119,123,29,164,45,44,185,10,27,0,119,61,187,247,234,126,130,157,128,91,91,113,10,162,2,118,160,249,50,7,203,212,14,126,135,30,188,123,242,249,21,176,234,24,130,120,220,7,79,113,66,
204,20,237,108,28,16,114,62,148,43,46,78,114,57,252,251,82,1,214,238,37,200,249,183,70,219,114,71,83,128,115,250,211,134,11,101,128,7,158,131,27,185,226,158,191,116,224,227,235,85,161,18,25,14,88,4,25,202,128,57,39,252,254,180,192,156,145,211,219,158,56,165,39,35,235,215,189,70,196,110,56,57,80,113,142,180,184,206,104,0,219,135,7,211,219,173,69,29,180,81,200,210,46,65,39,39,234,106,64,200,236,81,88,101,78,27,219,190,51,235,78,206,238,141,201,227,29,253,40,1,137,34,149,242,227,98,140,84,124,189,25,65,206,56,252,63,74,80,120,32,144,216,28,224,126,116,49,59,129,29,198,9,39,28,96,227,183,210,152,114,119,6,229,135,70,198,63,149,0,41,112,10,19,144,55,17,208,241,215,211,167,122,82,50,114,184,200,228,18,59,209,184,6,97,140,96,231,159,215,250,210,110,70,25,65,158,78,112,113,156,30,104,0,102,193,37,136,3,190,77,61,24,20,86,67,187,184,199,122,97,4,48,198,78,239,202,158,132,183,221,32,224,224,224,208,5,101,212,161,75,191,178,62,240,224,133,203,168,228,227,61,191,195,189,89,37,27,4,48,200,
238,69,53,162,93,232,238,129,158,60,225,138,228,168,61,113,233,66,145,36,128,115,158,160,227,165,32,43,187,135,112,80,238,193,219,140,224,100,30,226,166,140,127,14,72,3,235,197,75,54,60,182,198,50,59,231,21,10,130,84,108,202,46,56,7,175,175,126,148,0,125,159,18,22,228,96,30,51,193,165,10,1,35,128,199,211,131,82,2,127,186,51,254,127,250,245,23,207,189,92,51,109,206,112,112,63,157,22,67,6,194,176,145,78,80,140,100,19,142,113,206,59,246,231,255,0,175,85,99,249,46,165,104,158,79,222,178,185,243,14,228,60,115,183,7,32,253,125,5,77,112,136,168,210,176,118,242,198,236,100,228,240,122,82,146,175,112,17,87,44,87,115,96,231,3,183,211,156,254,95,146,212,5,102,112,28,238,56,238,91,183,210,171,73,114,96,124,158,172,3,28,142,127,63,194,173,136,176,193,131,96,145,207,82,127,14,120,57,250,244,166,94,121,76,234,9,10,192,1,243,54,1,7,249,156,138,86,11,146,91,76,36,0,21,10,221,49,156,154,115,98,55,198,70,72,202,131,215,3,175,244,166,66,184,141,8,228,129,142,65,205,57,184,249,142,8,201,227,31,225,
214,168,64,142,160,96,14,71,29,121,161,70,230,201,32,168,60,17,201,255,0,235,83,163,140,129,156,112,121,230,156,120,201,85,7,3,61,122,159,173,48,35,206,75,15,155,10,64,30,141,210,159,141,171,187,5,189,135,122,9,32,41,32,114,64,63,157,43,129,192,12,70,72,232,104,1,160,16,189,6,105,17,136,102,28,99,31,119,28,10,55,6,220,65,193,30,255,0,133,51,59,20,177,108,96,114,88,241,72,5,121,54,1,195,146,71,69,238,121,252,42,15,61,151,59,85,85,243,211,56,235,235,254,77,78,197,157,11,66,192,150,25,66,121,81,215,7,252,154,108,113,42,129,211,230,201,60,96,19,253,40,1,179,180,81,40,55,14,145,130,120,224,255,0,159,90,41,30,230,52,153,146,50,36,153,126,242,169,251,163,175,245,162,139,1,32,82,35,109,206,195,107,101,185,199,78,160,123,119,239,233,85,164,189,181,105,148,19,129,25,200,60,142,112,71,78,252,26,184,251,112,133,148,49,83,145,200,30,223,203,53,11,91,197,28,136,35,129,87,57,99,133,251,184,227,250,210,119,232,53,110,160,183,139,42,44,97,10,135,83,198,15,28,118,199,255,0,90,159,28,137,34,252,
131,4,30,148,165,64,94,0,59,57,59,179,245,226,162,71,205,216,72,208,28,242,228,15,186,49,193,63,143,245,244,167,168,104,89,147,204,123,102,242,156,44,140,56,108,14,61,240,105,224,114,8,80,6,115,207,63,231,154,104,1,91,140,226,157,206,0,28,30,158,148,196,51,202,3,42,16,2,121,37,122,255,0,141,60,174,64,206,119,14,115,215,20,110,10,74,241,159,67,222,142,173,207,110,8,61,233,129,90,214,201,173,238,166,148,176,111,55,25,61,243,207,249,252,106,157,228,51,197,103,113,229,79,43,202,197,217,64,98,8,206,120,7,182,43,92,96,140,103,160,199,29,41,143,18,58,252,216,56,63,149,43,1,151,103,118,110,52,104,174,167,144,171,156,238,100,5,134,65,219,207,215,191,214,174,71,40,146,197,94,227,41,189,1,57,110,128,143,94,63,58,87,180,141,161,22,234,129,96,238,171,129,142,115,211,211,57,247,167,5,242,17,18,8,128,82,192,149,3,133,231,159,167,25,252,126,180,1,25,135,148,1,153,182,174,220,183,37,177,208,159,215,243,168,34,41,107,107,49,184,145,99,133,88,178,156,114,1,201,36,251,228,159,211,57,171,174,251,
8,59,73,3,60,40,201,53,4,49,188,246,11,246,200,208,72,65,220,129,126,83,201,199,175,108,113,64,19,134,82,168,99,42,81,190,233,94,65,29,115,77,105,4,33,155,36,130,114,48,7,211,252,40,129,2,68,170,160,97,84,3,142,0,62,222,148,231,65,181,183,124,192,240,112,63,74,0,142,27,129,115,46,17,72,65,159,159,119,83,142,152,239,212,212,168,174,178,190,247,93,135,1,19,28,140,14,127,31,240,170,118,144,249,12,76,33,0,39,35,60,146,113,140,19,159,255,0,85,94,46,185,99,144,72,235,66,27,35,153,140,77,150,77,209,145,131,205,44,141,157,172,170,74,158,249,253,121,255,0,60,213,120,221,154,242,84,114,66,228,97,123,99,31,206,172,49,216,120,192,0,244,52,132,53,179,189,79,112,121,250,82,201,146,163,104,29,70,51,77,69,144,22,99,131,159,202,157,147,236,63,94,148,12,29,73,24,83,130,49,158,157,63,194,170,67,102,171,168,75,120,179,72,75,252,190,88,63,40,224,14,125,127,250,245,49,63,235,28,114,114,6,15,177,167,43,57,102,98,54,41,199,222,28,251,231,154,64,63,13,215,104,39,35,32,241,183,212,231,6,169,72,145,77,
118,55,52,184,63,46,192,118,134,228,142,123,144,42,225,136,200,170,194,70,81,212,156,122,143,122,134,230,20,147,12,142,203,34,16,85,205,12,17,98,38,68,38,31,49,75,42,103,110,239,155,111,76,227,175,227,76,96,201,34,225,152,227,130,49,140,244,231,215,255,0,214,106,137,178,23,55,138,110,229,34,72,70,228,84,147,133,228,224,145,215,211,159,110,181,124,174,19,203,60,130,115,144,199,39,191,225,78,224,58,73,99,142,50,102,150,56,148,156,101,206,220,241,235,78,136,58,162,171,182,247,80,20,182,49,147,235,255,0,234,170,147,39,152,201,231,50,152,87,157,140,51,187,252,255,0,90,178,178,44,152,42,217,4,241,237,69,197,98,1,18,164,17,197,4,107,28,96,141,170,56,29,114,120,253,106,195,13,160,156,224,103,173,48,19,144,163,113,35,36,18,71,31,231,52,159,44,207,157,236,202,126,82,164,113,159,167,231,76,6,101,238,23,247,82,5,92,149,46,57,35,168,227,182,115,142,185,232,71,210,68,137,84,238,63,188,124,99,113,3,63,225,79,69,1,64,0,15,76,118,164,228,156,227,159,173,0,41,32,129,129,202,244,226,171,72,72,147,
204,198,80,46,8,207,166,121,253,79,229,86,148,177,63,117,148,30,59,96,211,70,230,153,211,40,84,39,205,147,201,36,224,126,28,26,26,2,40,212,44,142,62,82,100,34,78,79,7,128,191,166,0,162,156,168,35,144,186,142,72,198,123,226,138,67,42,64,98,75,167,182,130,210,112,120,63,49,1,7,211,159,126,195,177,246,205,184,224,41,112,101,202,134,43,183,185,45,140,99,233,206,120,197,103,29,89,99,146,68,84,121,91,143,153,128,64,56,193,247,3,142,254,245,17,212,36,19,164,247,81,47,149,27,150,140,34,29,195,32,130,50,78,9,249,179,211,183,78,120,90,1,171,44,34,118,81,190,69,42,193,136,86,192,111,169,239,223,243,167,6,65,144,131,107,49,35,118,222,1,199,25,199,183,175,166,56,60,85,104,237,93,175,89,222,238,102,128,40,49,42,28,46,14,120,200,198,113,215,215,167,38,164,150,206,57,124,209,113,153,35,153,129,40,199,35,129,198,7,235,199,95,210,168,69,141,133,70,215,201,42,72,228,83,207,76,100,1,159,192,83,35,77,144,164,120,3,98,42,140,103,176,192,165,117,38,34,170,118,54,62,82,49,199,231,145,64,10,141,243,152,
195,43,96,114,51,200,255,0,235,83,206,74,14,231,235,80,198,130,36,8,171,140,117,239,207,245,167,6,25,207,211,142,148,0,245,192,57,239,72,164,96,140,96,231,154,110,115,215,25,3,177,167,124,161,190,238,226,57,160,1,137,92,28,28,159,198,145,157,209,64,10,73,200,239,211,159,229,70,226,70,113,232,121,165,39,4,125,253,192,113,129,154,96,68,146,187,207,34,60,101,85,113,181,136,227,255,0,175,254,21,18,203,57,190,120,188,164,8,137,146,219,206,121,206,56,252,59,251,243,86,87,140,183,225,158,153,170,182,49,56,179,201,143,202,150,86,221,32,46,95,158,6,114,79,112,7,210,144,22,100,112,135,107,103,147,128,113,211,140,243,233,211,249,84,78,21,65,121,10,172,96,99,43,206,7,249,197,65,97,122,247,190,100,141,7,146,168,112,27,126,224,231,190,56,30,223,157,77,117,111,231,198,71,152,84,176,60,142,199,214,128,20,71,36,113,71,181,247,97,6,125,50,7,81,254,77,59,51,137,148,156,21,254,32,121,237,255,0,234,253,125,115,79,206,88,228,169,24,30,255,0,79,243,237,81,57,84,148,52,162,53,6,77,145,146,227,146,71,
243,206,120,231,167,126,200,7,24,207,155,184,227,144,7,29,141,41,12,201,128,219,142,49,200,201,207,225,82,100,23,42,7,81,222,162,154,60,144,121,7,25,207,127,113,76,8,210,41,55,28,149,67,242,240,6,115,79,17,146,197,195,150,199,28,243,131,207,235,154,124,89,104,198,211,130,114,65,3,183,249,52,201,124,226,85,119,16,73,224,147,74,192,68,202,224,186,70,50,72,225,143,78,190,149,41,51,196,124,210,55,38,223,186,188,146,127,207,79,169,168,204,102,100,140,75,115,34,177,147,40,165,194,238,192,200,24,0,100,112,78,57,233,205,58,23,95,50,81,188,149,87,62,98,48,201,86,192,231,175,0,128,14,61,232,176,14,142,101,146,224,140,76,164,130,114,79,202,123,99,175,191,165,43,196,89,55,16,25,200,29,248,172,253,34,25,98,185,188,77,142,144,137,49,24,200,0,114,79,3,176,228,116,173,70,229,118,146,48,121,198,120,255,0,57,160,101,91,105,138,192,100,104,128,145,126,66,21,14,88,103,128,56,233,207,94,159,173,27,46,164,150,51,35,164,65,55,111,68,228,73,198,7,36,124,190,188,102,167,222,1,39,13,140,114,64,206,125,
105,76,157,20,252,163,5,183,31,187,143,175,79,242,105,136,140,68,118,51,182,14,15,4,142,113,235,199,249,226,132,80,168,20,49,247,25,239,74,20,34,8,212,156,114,114,199,60,147,158,255,0,94,148,209,27,199,191,103,39,57,59,155,128,41,1,34,32,18,115,156,170,227,113,31,231,210,149,157,84,5,7,4,231,140,245,247,166,6,4,177,4,238,192,39,31,141,47,154,162,69,70,202,130,113,220,255,0,46,157,169,129,32,206,121,108,231,244,255,0,57,168,126,126,9,60,99,159,90,151,36,168,35,183,39,20,207,56,51,20,92,146,6,73,199,7,156,80,1,36,75,36,91,93,67,43,129,158,220,103,215,212,122,250,211,147,43,184,103,35,128,1,63,215,189,52,72,190,86,21,241,215,25,234,15,249,237,65,147,230,24,67,207,3,20,0,147,46,226,54,161,101,237,138,42,188,247,254,73,36,133,94,64,195,122,209,72,101,35,40,129,221,60,190,128,21,98,128,156,251,122,227,175,95,233,84,157,4,182,166,87,101,59,164,192,228,150,207,95,235,250,213,233,188,217,12,145,189,202,174,84,150,30,81,3,140,116,228,117,193,239,218,168,164,59,3,182,19,159,152,97,179,219,
223,24,169,25,165,165,201,116,101,16,73,41,42,34,243,23,205,82,197,151,39,144,217,245,97,215,61,48,59,226,91,43,73,108,203,92,93,79,41,194,159,149,230,98,128,112,115,130,120,232,127,58,198,104,119,0,70,17,79,95,152,244,7,35,31,136,31,149,116,58,124,13,111,105,19,188,127,190,144,135,155,179,100,250,231,174,56,31,133,52,38,73,106,242,201,10,60,165,119,186,130,64,66,184,252,15,61,49,214,165,222,166,77,158,96,222,70,237,160,252,216,245,250,113,80,92,253,169,227,149,32,217,19,30,21,152,31,243,254,123,231,21,30,159,111,53,176,153,238,37,89,38,144,130,238,15,80,7,31,215,252,138,171,136,182,0,32,238,199,94,180,221,152,94,244,0,55,179,6,201,7,130,6,49,78,42,71,25,250,156,208,3,0,11,211,129,74,170,121,231,219,233,70,224,75,1,180,144,7,3,158,244,243,192,250,247,160,6,225,72,40,223,50,176,193,4,103,52,184,33,137,25,7,29,187,243,65,24,92,156,231,29,233,0,82,0,7,140,117,197,0,59,24,24,231,143,78,48,40,42,112,85,79,78,57,53,17,56,6,65,243,176,4,41,232,113,215,25,199,31,253,97,82,228,14,185,
92,246,166,4,72,187,23,148,0,103,160,29,207,39,63,141,61,159,161,193,35,30,135,249,83,130,247,32,99,222,154,251,176,67,116,164,4,78,217,73,100,84,102,8,14,20,241,156,127,156,85,95,180,125,166,19,11,91,239,118,83,134,151,110,195,223,25,31,211,211,241,169,84,19,114,142,15,200,160,128,48,115,147,212,31,211,241,167,196,224,78,222,94,214,94,248,24,30,255,0,86,200,63,214,144,197,130,22,183,134,24,119,151,218,54,231,29,169,202,10,227,115,100,128,112,88,228,227,52,215,97,128,48,118,129,146,59,98,133,35,205,98,217,206,104,16,75,35,71,111,36,138,20,50,130,64,207,7,30,245,149,164,77,117,59,92,181,194,205,203,134,12,73,33,57,229,121,60,117,29,63,30,213,172,177,70,94,38,104,247,60,96,132,99,131,179,61,126,148,246,37,126,93,160,12,28,1,200,35,63,206,134,49,241,40,8,160,31,151,160,31,210,152,202,177,128,168,21,85,70,6,208,0,80,7,255,0,170,164,200,199,25,198,120,199,24,168,228,80,203,252,88,4,119,35,56,166,34,154,93,125,150,245,214,234,95,154,103,253,220,64,19,145,156,115,129,199,0,123,100,159,
194,192,157,28,149,98,68,138,153,96,170,196,47,110,184,231,219,214,161,182,129,67,37,193,119,141,192,96,235,156,6,228,243,140,158,185,200,231,140,138,182,27,118,121,56,250,244,160,10,26,125,140,90,85,175,145,230,202,177,187,100,25,152,18,172,192,13,188,113,215,245,171,155,209,74,172,140,139,184,224,6,96,50,123,1,250,82,153,17,203,160,195,17,144,221,61,51,253,71,233,78,193,228,12,16,48,64,34,128,27,32,7,32,231,119,177,255,0,10,67,130,132,101,134,236,243,156,26,101,199,157,36,82,42,20,141,155,133,114,165,177,248,127,245,255,0,194,157,189,207,152,114,51,156,0,120,205,32,18,35,191,123,42,182,63,131,61,15,225,248,126,57,167,132,10,254,103,59,200,234,123,103,255,0,213,72,165,33,133,99,11,132,3,104,86,239,219,20,146,203,229,169,119,207,202,51,128,165,137,252,7,52,0,167,168,93,199,167,95,255,0,93,67,41,117,196,139,150,10,51,141,223,120,119,227,31,254,186,32,157,101,70,97,184,5,56,44,87,27,142,7,78,122,100,227,240,34,166,3,39,112,108,146,7,67,212,83,184,21,224,200,221,186,54,119,254,241,
96,75,122,227,160,31,79,95,204,200,145,177,112,222,82,71,147,201,61,91,169,224,131,254,121,169,186,54,236,119,199,95,231,76,142,226,35,57,143,204,79,61,134,226,171,249,122,243,255,0,234,160,8,165,132,40,228,129,147,147,207,25,231,235,69,73,52,30,102,55,12,122,237,124,115,250,81,72,12,121,238,102,23,19,109,117,117,124,40,227,219,215,233,252,254,184,75,102,144,2,178,72,238,192,99,106,147,254,64,199,111,124,213,86,82,174,8,39,146,72,86,228,115,237,254,123,84,147,56,101,41,177,85,114,51,212,14,216,255,0,63,253,124,201,66,144,151,23,75,10,33,104,228,109,160,161,206,6,121,61,243,129,159,167,233,93,28,174,51,187,119,76,134,29,121,224,254,31,79,122,230,6,67,35,249,222,64,102,0,202,135,238,231,140,245,28,115,252,235,166,137,193,183,83,30,217,19,24,87,87,221,145,235,154,104,76,115,140,100,12,140,119,0,255,0,42,54,43,132,61,15,182,56,170,26,150,147,29,249,71,13,176,169,193,96,57,110,121,7,250,85,200,34,91,123,120,163,71,102,88,211,104,44,114,79,227,253,42,132,56,198,132,16,65,35,56,11,248,
84,17,218,91,194,230,84,142,52,224,43,4,0,3,142,157,59,142,159,137,169,100,148,171,170,237,46,206,73,24,35,128,58,147,159,168,233,89,215,90,194,89,220,73,2,192,90,52,203,51,33,234,72,207,64,57,57,235,223,173,32,52,0,4,229,120,62,135,140,159,113,248,84,129,151,142,58,246,61,171,59,72,184,158,84,146,73,152,176,4,4,36,1,245,233,212,116,171,153,218,50,71,11,220,242,69,48,36,105,54,228,28,54,79,3,129,142,159,214,156,28,48,198,118,145,248,99,243,166,148,193,200,193,28,228,19,193,206,49,254,125,233,119,4,12,210,109,69,25,57,39,160,3,174,123,119,160,7,116,225,88,224,140,147,138,141,119,16,165,193,86,224,158,248,246,165,133,80,64,159,55,153,25,193,86,206,236,142,199,63,214,158,84,130,167,29,125,233,128,221,229,88,112,79,184,28,82,23,44,204,29,70,51,128,51,219,29,255,0,201,167,1,192,228,156,14,184,166,74,7,4,131,159,99,72,8,182,73,246,163,39,152,165,2,144,168,19,156,241,201,62,216,244,239,79,65,128,161,242,112,51,199,0,126,20,216,164,219,230,9,65,40,91,42,64,36,129,199,245,205,61,144,224,
128,231,118,56,56,28,82,1,15,223,3,173,55,106,130,72,24,193,193,31,92,255,0,141,72,1,7,42,51,207,97,80,44,211,61,209,38,34,150,229,14,11,14,75,103,167,94,152,230,134,4,196,96,228,228,99,145,131,215,252,105,193,129,56,39,57,24,226,161,220,9,198,121,244,234,113,72,135,112,115,153,54,18,84,110,0,116,224,145,223,31,254,177,238,0,217,229,158,57,20,194,90,78,113,229,100,0,120,39,147,130,115,211,29,7,53,62,72,81,243,21,32,242,65,224,140,244,38,169,88,153,3,56,153,165,99,36,204,202,9,36,70,185,227,57,232,56,224,15,81,239,89,215,119,242,199,117,37,164,50,140,229,139,200,27,61,114,112,57,56,192,35,167,113,219,165,23,25,208,41,35,63,231,154,69,4,177,193,57,61,57,172,237,26,121,174,36,185,19,200,94,88,48,161,177,142,189,114,6,1,229,120,252,107,69,192,12,50,72,231,0,126,20,92,65,193,4,128,79,25,227,154,73,19,17,178,137,54,110,24,86,24,224,227,182,120,164,70,253,239,13,192,234,56,231,250,211,201,3,223,60,138,96,48,13,192,115,192,255,0,57,161,135,201,180,112,8,235,211,20,144,198,97,82,128,150,
37,153,142,112,79,36,183,255,0,90,161,184,251,100,142,137,24,72,148,50,179,62,119,111,93,199,43,143,92,1,249,226,128,38,40,12,65,57,32,96,115,147,254,77,84,146,51,45,188,176,38,239,184,216,92,245,206,112,57,250,143,200,85,135,100,217,146,220,14,73,97,252,233,176,177,59,50,88,52,128,112,87,39,166,121,199,25,254,180,134,54,11,103,58,124,16,72,118,109,93,174,171,140,183,7,35,61,185,61,69,88,72,85,2,5,108,0,65,200,29,112,41,251,131,103,56,198,61,51,154,82,85,164,238,72,200,246,25,255,0,245,127,156,211,16,19,140,12,116,224,30,128,254,21,77,236,32,146,237,110,89,63,122,135,39,211,61,142,61,71,106,146,205,94,41,46,60,215,67,19,62,99,59,201,35,60,17,207,191,191,126,149,101,137,46,7,118,235,198,120,230,128,43,205,52,80,101,164,42,128,145,247,207,90,42,29,85,145,35,140,185,199,39,154,42,91,29,138,146,90,46,208,209,172,142,49,149,27,65,227,212,159,233,215,20,178,216,59,66,29,182,167,124,109,192,31,227,219,173,73,102,60,199,117,42,100,36,18,92,129,244,3,245,239,218,173,161,19,69,243,136,
216,50,224,108,108,142,135,128,125,185,160,14,126,65,19,114,36,223,142,6,58,30,191,137,252,125,42,237,164,205,100,172,137,18,98,70,12,95,7,42,120,7,142,227,3,214,159,229,189,188,131,205,17,136,184,218,87,7,112,231,215,235,215,173,89,109,61,155,230,137,211,29,23,158,190,252,82,183,97,220,153,174,237,99,67,47,157,247,176,51,146,72,63,78,213,29,182,161,98,234,236,46,35,141,195,178,176,118,1,152,142,50,50,121,7,3,7,211,222,169,201,97,113,230,109,41,184,183,76,31,214,170,222,91,253,143,14,197,75,125,237,170,70,71,215,252,247,167,118,35,78,234,205,111,150,57,224,148,28,22,10,75,238,28,140,113,140,250,99,21,135,43,8,164,145,17,129,10,219,50,1,198,127,195,53,53,206,166,46,22,53,82,203,20,73,141,155,242,62,189,129,61,63,201,170,246,211,217,178,74,247,126,98,144,184,81,18,128,88,231,223,129,254,127,20,208,205,189,23,120,179,101,4,52,106,228,40,192,200,39,4,243,233,205,104,70,87,145,242,238,199,35,211,222,155,108,99,107,40,101,183,64,168,232,25,84,13,160,103,158,221,42,95,152,50,224,128,
0,231,35,183,61,234,145,33,129,180,149,200,255,0,26,169,169,197,115,117,104,109,225,144,38,227,243,243,140,142,114,56,245,192,171,99,27,216,227,230,60,83,177,242,237,63,116,123,211,2,149,140,98,202,202,40,57,40,185,27,207,93,197,189,189,201,171,138,155,21,66,96,40,24,0,30,149,4,214,137,115,181,29,152,162,156,178,103,135,61,179,235,235,233,86,65,39,159,195,158,40,0,60,18,192,143,169,170,237,34,238,112,14,20,117,164,123,150,88,37,144,219,186,136,206,0,115,141,195,142,127,157,32,157,86,204,206,160,176,43,184,41,227,60,126,148,48,34,89,148,179,109,101,200,56,3,119,94,159,151,81,235,218,160,179,190,154,234,115,28,150,207,8,251,234,248,225,148,99,140,145,215,39,183,108,211,173,158,41,227,31,186,9,34,201,191,105,195,97,135,112,106,219,137,65,92,97,64,35,183,94,121,164,50,59,75,212,157,37,49,41,242,227,125,129,179,146,199,190,61,185,224,253,122,84,238,219,179,242,158,125,191,90,130,22,150,87,144,186,44,96,16,20,2,75,28,100,18,115,219,166,42,103,108,28,243,199,165,2,40,205,111,42,223,
193,50,34,178,43,228,241,208,30,15,227,215,244,171,113,75,4,208,59,66,234,66,177,141,143,161,94,8,35,252,250,247,167,182,197,4,28,174,227,233,212,241,143,233,72,35,85,77,187,87,146,73,1,112,13,3,40,88,60,232,146,91,34,156,198,153,73,100,13,243,22,39,4,130,114,114,65,39,167,36,215,63,28,205,48,50,58,9,55,179,17,176,146,78,57,57,255,0,235,250,26,235,146,88,164,119,129,89,90,85,234,189,199,76,255,0,49,249,143,90,134,214,194,11,121,146,91,66,81,23,228,101,83,185,88,115,234,122,231,28,251,80,213,194,228,58,101,171,90,70,37,118,218,247,1,119,6,125,164,30,120,198,58,242,6,61,115,87,73,114,164,128,34,227,112,45,206,61,73,244,239,208,212,51,93,195,246,152,35,147,114,180,135,229,12,48,185,35,60,158,153,227,167,175,231,81,106,19,222,148,205,156,82,43,163,16,73,3,4,1,249,156,251,80,4,207,119,10,134,4,135,104,241,230,109,193,40,49,156,183,60,12,126,63,90,129,174,175,159,81,196,49,68,246,188,102,80,71,67,142,115,158,112,115,248,102,174,130,205,16,102,76,49,0,178,231,56,39,168,207,122,14,228,
42,161,134,61,49,146,70,15,31,203,154,4,66,211,72,151,233,16,183,59,10,150,105,122,1,236,61,106,82,228,140,42,117,233,142,191,143,165,86,17,92,137,99,64,229,160,85,0,179,114,79,94,255,0,151,90,181,156,245,27,129,199,255,0,174,129,145,76,93,101,141,55,198,50,9,96,203,150,218,0,228,115,216,145,159,173,58,222,85,119,125,140,14,220,169,10,126,233,29,71,181,59,229,11,200,29,57,35,142,255,0,253,122,169,118,184,177,153,97,65,186,64,114,115,128,119,12,103,159,95,243,138,0,188,136,223,54,252,40,207,203,207,111,94,63,207,243,170,247,151,208,88,4,55,14,16,72,78,223,148,158,152,207,64,113,212,86,60,250,165,199,246,76,112,180,162,59,133,147,202,149,131,243,128,49,158,78,70,115,212,119,7,158,213,169,37,140,119,150,208,188,236,175,40,140,98,72,219,135,207,191,161,224,254,52,8,125,173,172,169,116,110,100,157,37,222,50,167,103,221,28,125,211,158,7,28,250,224,26,146,25,68,247,19,0,175,229,130,2,185,251,175,193,201,30,223,158,105,200,177,164,75,26,113,18,130,2,250,156,245,62,253,127,58,152,58,237,
59,112,56,206,115,64,25,122,132,203,37,215,146,66,42,162,231,50,12,134,39,208,81,86,110,98,124,130,165,243,254,192,36,255,0,158,40,164,198,71,45,191,157,181,153,150,7,4,25,25,15,222,199,108,241,159,90,111,218,163,180,62,93,206,200,242,216,67,143,149,143,92,123,99,61,234,200,115,180,6,108,103,156,14,166,163,51,54,113,133,98,122,18,71,7,158,159,227,69,192,200,212,158,38,42,80,132,194,147,199,32,115,211,61,171,86,223,237,144,219,5,112,100,113,243,21,45,207,7,166,122,115,88,247,55,55,17,234,204,163,202,89,165,216,138,219,9,12,122,118,57,239,250,14,181,190,20,92,90,174,233,74,255,0,121,162,124,114,14,49,159,173,11,80,122,19,162,8,213,75,149,235,203,98,156,232,178,99,40,172,1,220,9,25,228,127,250,186,211,36,85,104,152,57,218,54,145,156,242,163,185,207,106,130,43,167,107,55,150,234,68,1,65,37,144,113,140,14,120,252,125,62,149,66,40,77,165,74,250,148,151,49,76,33,207,204,54,14,67,99,147,252,255,0,51,74,52,75,102,114,211,51,76,205,146,119,113,146,112,114,2,227,222,180,38,101,242,156,184,
222,19,230,235,158,70,8,63,135,90,173,165,93,61,213,148,82,204,9,114,188,177,35,146,14,14,49,238,13,33,142,178,180,75,8,218,56,151,203,66,219,241,187,60,226,172,171,29,135,0,7,28,14,77,33,201,7,25,247,255,0,57,164,0,96,100,243,64,135,197,177,134,242,168,160,46,220,109,198,23,210,158,227,230,220,91,27,121,60,240,56,239,81,46,17,213,242,7,80,69,76,78,87,168,235,128,41,128,129,213,128,101,28,2,71,32,142,149,20,215,41,12,38,86,202,70,62,251,0,114,59,116,199,60,227,249,209,110,241,76,137,36,46,146,7,24,14,164,16,216,207,113,233,147,81,222,68,38,143,236,224,72,18,64,75,16,66,128,56,227,57,207,62,212,1,70,215,89,91,233,76,45,11,70,220,237,203,103,60,30,191,225,205,105,32,143,37,140,96,100,0,72,31,159,63,141,98,255,0,103,182,159,117,20,150,129,228,142,108,174,54,244,24,7,7,245,235,138,216,158,82,144,101,20,177,39,176,206,121,205,33,138,234,161,119,162,132,97,234,7,244,168,138,72,20,200,101,192,36,18,9,198,56,192,29,113,249,83,45,110,140,192,163,197,177,212,227,31,231,167,210,167,124,
143,44,239,194,231,140,31,189,245,164,2,42,237,27,139,179,240,58,159,78,254,212,201,167,16,38,72,89,31,60,40,234,123,12,14,73,228,129,68,197,188,189,216,59,184,200,25,25,57,252,234,41,174,119,193,116,177,71,43,152,215,1,151,24,99,142,220,245,28,80,3,238,47,32,134,208,206,242,7,77,187,134,209,156,158,71,78,189,125,122,99,218,164,179,184,142,242,217,102,136,182,217,7,70,25,193,244,62,253,107,31,69,211,35,120,228,146,115,189,137,40,98,97,134,28,127,23,124,224,231,233,131,206,106,77,98,250,75,88,163,178,181,249,85,84,101,195,96,168,0,96,15,203,159,243,130,224,93,190,97,108,139,44,206,234,234,248,80,29,145,88,147,198,224,58,129,254,122,212,139,106,254,89,142,226,121,29,119,13,160,14,168,49,195,113,130,78,57,39,174,79,76,154,230,83,104,222,218,132,178,199,2,168,0,130,74,229,176,64,80,51,129,140,28,14,152,25,173,237,62,206,45,59,237,51,151,3,112,4,179,12,5,85,207,36,254,39,242,167,125,66,197,211,12,127,186,92,32,141,6,21,2,12,12,116,250,17,143,212,209,5,220,119,67,229,32,58,15,222,70,
174,24,198,222,135,159,92,143,192,212,87,65,227,183,105,119,57,194,150,218,131,230,110,59,3,222,162,210,225,183,91,69,150,53,144,27,129,230,102,83,243,182,121,231,25,250,254,52,1,105,37,134,224,176,133,247,5,37,27,29,155,210,154,145,56,97,153,78,206,152,60,228,253,42,70,12,37,70,82,118,99,27,122,224,245,201,57,246,199,227,73,34,111,70,94,70,79,64,72,255,0,235,209,96,24,128,62,89,27,119,57,7,39,31,81,78,198,98,96,91,13,147,200,61,15,227,70,237,202,9,66,164,255,0,15,0,175,183,21,24,118,18,28,46,229,60,228,158,159,207,252,138,64,1,73,147,115,119,3,174,113,223,252,104,66,206,210,51,2,145,131,128,219,184,35,215,219,184,162,39,18,199,184,171,161,7,5,27,168,199,208,154,149,72,254,232,231,129,145,201,160,12,150,209,225,105,166,105,87,10,227,133,85,192,83,142,199,183,229,254,21,122,59,53,86,130,72,192,141,99,70,85,84,224,28,145,156,250,244,252,249,237,86,84,174,92,6,207,32,103,61,255,0,206,42,187,74,162,38,134,117,220,142,164,116,39,62,212,108,5,149,80,98,1,209,71,77,221,233,134,84,87,
42,167,46,184,44,8,233,147,255,0,214,170,208,73,13,156,74,129,220,129,145,131,147,211,142,227,142,59,85,144,193,142,8,56,247,239,78,224,50,9,9,182,82,173,185,149,138,147,39,83,239,199,92,140,31,199,240,5,70,37,255,0,91,184,109,196,132,12,119,24,200,56,252,79,229,69,23,1,22,205,161,125,193,119,115,156,19,201,207,166,127,250,213,99,98,178,145,156,28,231,35,241,168,98,183,242,68,131,237,14,207,33,24,66,220,12,231,160,237,158,127,200,172,168,239,226,138,250,82,204,94,205,211,62,89,203,6,61,70,1,224,126,157,15,94,13,45,16,26,50,41,154,227,202,146,72,149,130,252,172,24,23,235,158,61,56,3,252,226,174,196,60,181,35,33,65,36,252,163,0,103,154,171,103,45,181,220,178,8,225,93,145,170,133,60,140,131,215,3,28,96,168,29,250,118,169,154,35,178,70,121,23,43,211,215,3,223,174,122,211,1,154,180,101,236,36,82,62,233,7,30,188,138,195,181,83,45,220,5,64,66,92,16,92,113,193,201,245,4,255,0,136,174,128,198,102,133,227,46,74,186,145,211,4,255,0,147,92,252,150,242,67,32,73,147,231,192,227,130,113,73,
247,26,55,154,23,124,13,200,35,220,14,0,228,174,220,96,251,228,147,248,15,124,168,179,129,34,49,44,67,203,114,73,64,163,7,61,106,11,6,189,146,200,78,174,178,49,124,40,144,128,187,65,228,140,12,228,242,57,238,51,236,103,86,189,55,104,100,133,22,7,82,27,203,155,37,79,175,42,51,233,254,52,196,49,227,84,151,204,80,75,17,141,216,250,127,133,74,140,8,44,9,231,212,99,218,164,97,243,97,129,231,175,32,1,66,197,243,238,10,55,99,169,39,39,146,121,246,228,253,41,136,66,114,57,4,243,219,214,155,111,20,145,91,136,230,156,204,249,36,187,12,103,39,56,169,37,10,225,149,193,56,94,70,56,35,211,222,145,28,72,55,40,109,167,24,108,17,248,224,208,1,4,81,66,133,45,227,69,81,200,8,0,31,165,73,32,44,0,238,61,169,168,121,249,152,28,31,167,20,230,193,201,3,241,160,12,233,222,242,222,236,176,87,150,213,163,198,216,213,119,70,249,28,243,142,49,245,171,72,193,162,46,128,150,57,59,95,177,250,118,252,42,108,116,193,3,222,130,191,46,14,122,113,154,0,137,250,156,46,208,15,94,184,63,74,97,111,144,111,57,101,199,
7,249,210,187,73,230,168,24,219,206,70,121,0,119,255,0,62,181,26,103,108,193,182,171,22,32,54,61,186,144,125,243,248,98,147,25,44,138,51,128,56,61,143,113,77,251,68,65,130,7,4,147,140,14,127,47,165,69,15,157,12,120,184,148,239,46,10,171,237,25,200,3,111,191,60,250,243,138,200,212,117,8,96,146,223,236,241,199,32,141,252,198,192,32,147,140,122,123,245,164,6,165,202,59,188,77,105,28,108,37,31,188,147,113,86,101,199,28,129,158,255,0,135,242,202,215,196,183,23,49,199,111,36,82,56,5,29,99,33,136,57,232,113,211,241,171,186,206,219,155,69,111,56,67,132,108,115,254,177,78,56,234,56,233,219,208,250,212,58,36,49,220,164,119,171,42,185,66,201,32,94,8,235,201,63,66,15,249,52,1,14,167,96,255,0,102,178,177,138,32,100,140,9,28,39,56,110,153,250,100,158,184,237,91,151,86,241,220,217,203,107,35,184,14,152,37,120,36,30,252,126,53,4,98,71,212,167,145,161,217,20,113,44,106,237,193,98,9,206,61,189,79,126,49,210,172,199,42,50,160,86,13,194,159,148,238,200,36,128,120,237,199,83,239,232,105,129,157,98,
110,77,212,194,235,49,163,46,97,129,23,33,20,255,0,120,168,218,62,232,199,61,207,94,43,65,93,212,176,218,72,28,12,119,231,166,63,42,81,144,193,148,130,8,225,178,59,212,63,98,69,186,44,187,68,100,22,218,59,182,224,193,179,234,14,127,58,0,159,123,49,28,228,99,63,116,140,31,173,49,75,7,59,136,57,35,3,147,245,162,237,229,142,6,104,134,233,122,40,199,4,246,31,253,122,86,70,251,64,117,145,188,189,152,11,129,180,159,175,95,255,0,88,160,7,2,54,133,206,58,241,239,81,79,182,56,218,71,201,8,55,31,82,7,165,49,85,146,234,75,131,43,20,35,110,210,248,85,31,143,126,63,206,106,188,247,108,218,113,145,49,42,185,198,215,7,32,127,116,243,156,255,0,250,233,1,113,93,94,37,101,86,1,251,17,130,51,235,75,27,100,18,54,237,199,99,88,150,58,133,195,201,29,164,80,32,249,135,32,125,212,244,3,56,24,29,62,152,193,53,165,114,210,164,97,161,224,1,203,179,100,100,246,25,254,188,80,5,144,192,54,210,114,61,49,205,42,191,153,185,76,100,0,1,15,158,15,176,250,127,159,106,80,173,204,237,251,216,252,128,146,54,238,113,
184,231,142,61,0,247,236,58,212,215,151,81,219,201,111,22,230,6,102,194,190,55,40,250,253,115,142,248,160,9,72,72,226,11,203,0,57,29,73,252,123,212,49,194,45,230,93,139,242,176,103,85,45,200,228,103,3,249,251,253,104,190,150,40,45,3,77,27,185,60,97,64,221,252,234,182,251,107,107,187,73,98,17,237,153,76,33,147,168,251,184,207,211,0,96,244,205,0,73,155,77,67,114,13,165,227,108,16,72,252,254,156,138,41,83,77,128,59,60,46,200,172,78,118,240,65,28,99,62,156,30,63,194,138,57,87,80,185,124,192,143,25,19,68,132,186,225,198,223,211,233,205,85,147,75,180,149,155,116,49,150,198,14,70,127,159,176,166,255,0,105,36,83,77,25,70,34,21,222,228,48,200,60,112,23,169,28,245,254,85,111,30,116,123,142,65,29,64,199,28,116,53,66,34,130,217,109,100,101,141,118,198,234,55,12,224,3,158,160,99,190,121,62,194,164,153,26,72,202,41,196,139,181,183,21,200,198,115,142,195,182,63,42,69,216,0,12,173,147,193,4,0,23,0,113,197,65,117,37,202,72,134,8,35,42,170,126,102,66,112,121,227,131,158,131,211,191,189,0,79,111,
117,28,179,24,138,60,110,50,202,29,49,184,3,140,254,120,253,43,46,250,51,113,172,52,42,248,47,142,88,112,62,92,254,60,10,211,142,221,101,185,23,82,171,25,84,97,126,108,170,113,206,62,185,253,5,73,38,216,211,118,61,73,220,112,49,142,230,134,50,43,8,100,179,179,138,22,33,217,115,158,49,201,57,199,235,143,122,75,141,78,218,210,81,28,204,85,155,145,133,102,7,223,32,123,86,78,139,168,207,113,34,91,220,168,153,21,75,44,184,249,134,56,201,252,241,158,188,243,90,15,96,146,222,25,164,103,24,24,1,88,129,158,196,30,221,233,8,190,146,199,34,238,87,82,58,101,72,35,244,165,98,54,144,122,142,131,138,141,72,29,62,92,142,152,198,105,4,196,204,34,2,64,118,147,187,7,29,113,140,158,254,212,192,149,93,153,21,136,198,224,14,210,57,30,213,27,176,218,224,169,101,110,160,142,212,160,157,197,177,250,211,102,33,84,174,230,80,231,4,175,81,158,50,61,232,0,121,227,137,55,74,235,26,142,165,248,199,249,56,169,67,131,26,186,109,100,97,144,84,240,65,239,81,75,20,109,11,197,32,38,57,1,12,9,56,193,237,235,220,254,
84,91,181,195,203,63,156,168,168,49,179,97,201,35,158,77,0,60,128,64,80,10,30,159,40,231,31,90,93,165,78,14,54,145,129,215,61,251,254,84,195,242,182,65,192,62,180,168,217,80,223,119,253,159,79,202,128,25,32,32,135,236,56,252,15,255,0,94,171,173,244,15,16,80,73,28,156,30,127,58,125,212,208,36,82,60,210,133,69,4,237,82,62,108,14,159,173,99,91,79,21,229,228,40,172,209,219,110,43,180,117,44,221,251,245,63,90,67,44,92,109,185,116,243,37,192,144,227,223,61,176,58,14,213,155,169,219,200,136,247,12,10,39,156,99,216,192,130,70,56,63,74,210,212,82,120,219,22,236,89,118,40,64,157,64,245,227,191,83,248,212,58,235,36,240,194,205,58,25,148,20,120,215,13,183,212,241,156,28,224,117,164,6,125,187,200,255,0,36,174,206,145,127,171,203,22,219,142,56,207,24,224,113,210,186,40,33,123,155,88,190,215,19,55,33,159,119,202,75,2,72,200,28,16,56,235,248,128,69,87,210,45,226,75,8,238,97,50,59,132,59,215,25,220,192,231,161,29,65,199,76,116,239,85,63,182,175,96,187,243,46,34,140,13,161,94,60,48,32,117,238,
112,15,127,202,128,55,0,111,146,76,110,28,143,148,141,184,236,122,250,119,172,253,90,51,10,127,105,69,49,134,113,31,150,72,80,119,14,184,199,214,163,211,46,110,229,89,93,154,223,200,243,51,51,75,159,78,71,167,0,119,245,164,212,236,164,50,94,172,82,98,25,99,18,74,174,249,218,65,227,24,201,232,189,49,142,61,169,244,3,86,198,102,188,180,134,121,85,81,165,92,149,7,35,240,246,255,0,26,124,114,9,33,73,83,37,24,110,66,71,168,247,233,92,237,158,173,115,111,27,89,221,31,62,6,249,18,116,59,93,87,24,200,227,158,199,177,250,246,158,210,85,181,209,68,171,155,147,4,184,42,79,202,125,7,208,103,35,60,231,29,56,162,225,99,85,103,41,114,182,243,9,55,73,147,27,148,194,231,4,224,99,56,192,29,241,156,113,154,83,35,197,112,251,224,96,174,225,85,148,117,27,73,203,123,103,35,241,28,86,118,151,171,93,92,93,44,50,217,198,33,114,76,70,32,87,96,7,190,120,61,135,24,252,115,90,209,73,29,212,32,109,253,220,128,129,146,84,245,199,30,157,15,52,8,173,53,184,156,146,11,239,97,180,28,244,25,4,240,126,159,165,54,
218,219,236,109,42,110,47,28,135,118,211,201,207,67,211,168,60,126,85,45,236,38,226,206,75,96,192,177,28,17,144,50,15,30,189,197,12,232,46,119,187,170,252,194,20,12,220,146,64,56,3,61,240,56,198,120,247,160,99,210,53,73,12,142,23,121,80,4,152,249,143,98,15,31,67,248,244,226,160,157,163,137,153,230,222,144,132,249,157,122,22,201,227,142,125,120,233,215,175,102,220,234,66,25,99,69,130,73,119,201,229,111,69,27,84,228,117,63,231,161,29,141,93,86,200,86,4,143,106,98,41,125,165,109,160,70,145,77,156,79,30,16,176,203,171,30,113,180,100,123,227,240,169,110,226,71,146,55,120,247,141,195,105,110,189,122,244,237,197,88,194,73,141,234,167,105,200,200,238,41,146,160,5,92,241,128,87,233,156,127,133,32,29,36,112,188,59,101,64,197,115,199,222,224,214,117,206,151,24,49,11,73,133,189,192,112,82,70,249,143,67,192,4,242,113,207,224,106,240,150,61,229,78,23,161,193,234,50,120,207,161,52,203,136,34,188,183,88,216,182,194,3,35,131,208,142,65,227,243,160,11,18,28,0,163,3,28,142,40,164,108,170,174,226,
24,129,140,158,62,180,83,184,21,109,226,196,146,78,139,178,70,56,108,119,244,205,19,121,236,23,108,219,48,192,131,176,49,244,227,57,197,77,129,25,201,4,22,29,7,35,138,173,125,124,150,236,84,130,79,4,110,249,71,80,123,255,0,65,245,197,72,199,198,2,194,35,87,147,24,218,78,237,196,118,207,215,32,208,32,104,224,16,192,161,118,131,180,49,39,147,216,243,211,175,255,0,90,164,79,42,230,1,34,12,249,168,1,216,216,96,57,227,131,193,25,169,21,126,79,44,18,112,54,243,146,79,212,158,115,76,65,17,120,162,40,8,44,7,0,12,40,61,186,116,20,66,179,186,134,153,148,112,115,26,244,252,250,231,252,127,26,39,144,65,107,36,132,41,42,133,176,123,224,86,19,235,23,77,49,158,2,7,202,84,70,217,219,248,251,251,251,81,123,12,218,138,33,26,17,25,218,29,203,177,60,228,247,254,85,48,60,103,39,7,214,162,182,153,110,33,19,8,228,143,119,11,230,40,203,15,195,181,78,87,112,4,100,103,175,20,196,55,232,160,158,8,7,140,210,231,40,8,239,142,184,62,180,130,60,31,152,18,61,249,164,146,50,192,148,219,230,42,144,165,250,103,
240,237,159,229,64,10,112,87,229,92,243,158,56,200,168,100,133,92,229,126,87,233,230,40,27,177,198,122,143,69,3,240,20,105,255,0,106,54,231,237,145,162,74,14,114,135,130,15,63,167,79,194,167,192,108,100,0,77,0,84,186,55,107,121,110,35,141,102,181,36,137,0,200,101,227,25,206,112,122,244,198,120,252,162,211,111,100,185,186,186,138,104,60,145,16,85,1,88,48,39,44,15,60,123,113,237,90,65,84,123,31,231,64,192,96,48,184,237,197,0,48,146,50,73,42,49,201,198,104,220,3,18,15,83,216,210,227,24,0,101,84,224,238,25,227,29,51,249,84,119,49,151,129,163,70,48,177,31,124,127,8,239,64,25,250,173,146,152,101,149,35,47,33,82,3,114,199,211,167,57,235,81,89,216,203,13,131,192,224,70,167,115,75,185,75,28,144,48,23,3,166,49,200,36,117,244,171,247,70,117,138,40,173,56,195,109,59,118,252,171,130,51,131,232,72,56,246,170,50,73,119,13,148,41,54,21,8,254,17,192,0,96,14,167,235,72,101,119,146,52,102,95,48,228,96,22,139,229,31,65,232,6,0,226,157,5,197,133,178,179,170,171,75,32,196,158,105,108,191,126,249,231,
53,81,162,242,128,44,23,110,121,102,193,30,188,250,159,106,71,141,29,65,78,15,66,72,234,125,5,43,129,210,137,161,242,147,204,116,27,128,192,221,144,120,207,203,234,0,170,3,91,178,150,73,67,204,4,40,138,192,186,17,185,178,115,219,183,203,89,119,87,178,201,102,109,202,171,50,124,173,33,124,200,121,61,61,176,72,207,190,56,166,216,68,178,235,17,4,84,242,203,147,128,185,3,142,157,61,186,254,61,104,184,88,234,22,49,17,63,41,228,130,72,238,112,7,242,20,199,196,151,40,197,9,11,243,111,61,1,232,63,66,213,94,217,26,213,74,188,146,72,204,251,64,235,131,158,188,40,199,57,246,31,205,209,183,148,222,89,221,48,145,216,187,52,156,167,82,56,244,206,56,227,31,157,80,140,166,150,200,91,78,255,0,35,77,230,148,49,151,218,89,60,206,23,29,71,0,30,153,226,180,52,243,111,117,101,181,97,196,42,66,152,95,230,3,161,60,242,79,95,210,170,46,156,151,23,225,165,180,242,32,137,112,21,24,16,192,19,129,140,112,63,207,4,230,175,54,159,8,187,138,242,32,34,17,130,72,218,7,111,210,146,24,215,132,92,164,13,27,61,164,
201,184,194,165,66,225,142,125,71,79,148,156,119,28,212,182,144,27,59,72,162,105,26,70,238,70,0,4,146,127,174,63,10,115,160,121,214,86,147,126,192,118,168,220,6,123,28,103,25,198,71,78,244,150,151,77,119,109,36,162,35,144,236,145,140,224,56,28,3,237,233,143,110,148,1,44,82,69,44,107,36,5,89,1,32,149,24,201,207,63,227,239,215,189,100,107,40,30,209,161,158,78,74,75,34,21,96,160,48,232,188,245,225,136,252,255,0,13,152,87,106,153,74,36,110,195,46,20,228,103,30,189,234,41,24,22,218,241,43,50,176,232,55,99,220,228,251,143,206,134,9,216,207,208,224,186,183,211,160,73,242,184,86,5,127,136,115,242,142,59,15,155,175,57,61,177,90,64,30,118,245,39,36,133,235,254,71,31,133,34,20,133,12,146,40,65,140,146,125,187,159,65,223,255,0,175,80,219,93,155,200,26,120,211,104,12,65,25,201,28,126,189,104,216,55,44,44,155,142,220,103,57,0,226,171,106,12,82,37,149,103,147,10,202,197,99,0,151,228,97,113,215,147,129,75,44,201,246,119,101,98,84,231,7,61,13,103,54,167,44,58,148,242,200,30,88,204,33,85,35,3,
150,7,57,36,243,142,79,79,240,165,112,177,100,220,110,121,68,240,197,9,94,174,92,54,224,164,158,127,14,71,214,172,121,170,110,128,49,16,158,94,65,192,192,59,134,64,199,60,231,63,231,152,109,239,108,239,100,17,50,27,121,15,32,57,3,113,238,20,231,147,207,249,230,173,61,145,42,171,191,190,230,56,228,140,99,25,31,81,249,81,168,104,23,16,6,142,48,55,96,127,117,138,31,210,138,144,48,144,38,24,50,149,220,114,57,252,187,116,162,157,152,25,183,201,111,111,121,13,244,254,106,220,4,96,173,146,241,228,140,99,215,156,240,56,28,31,198,176,212,237,110,44,204,151,12,68,184,96,99,80,64,56,224,1,215,182,63,90,179,62,147,230,222,181,197,213,212,141,10,242,168,91,27,14,114,78,125,63,199,174,6,43,6,117,183,118,95,36,180,113,187,112,24,114,163,61,255,0,35,244,164,193,29,29,155,199,60,49,189,164,132,34,56,255,0,88,114,64,4,100,31,124,86,130,73,148,27,148,1,199,0,231,143,243,218,178,244,164,134,206,201,97,39,203,119,108,225,143,46,25,128,86,199,167,42,57,244,247,205,94,220,35,33,122,100,247,61,15,255,
0,94,152,15,149,144,91,177,149,23,96,83,158,50,48,7,160,254,85,139,99,165,249,193,193,112,54,54,208,216,206,239,165,108,94,66,242,219,205,20,111,181,156,99,145,144,63,194,177,237,181,137,173,241,246,147,230,198,50,6,212,0,142,56,3,160,199,214,135,230,8,223,80,177,34,170,1,181,64,1,64,233,233,73,184,178,169,195,41,61,152,224,228,125,15,183,74,120,12,84,243,243,3,142,127,250,213,28,69,68,142,54,108,119,203,30,58,246,206,122,103,0,123,211,16,239,52,231,238,147,156,227,2,154,9,39,113,36,171,48,43,146,56,28,112,49,244,207,62,181,28,215,9,10,177,125,200,136,11,59,227,229,0,12,159,175,30,131,214,171,223,223,193,99,110,229,154,54,145,2,226,45,251,79,95,79,78,15,110,212,1,160,188,231,168,231,189,103,94,234,107,5,245,189,132,5,90,226,86,203,6,60,34,14,73,250,145,211,252,230,227,111,107,124,133,62,96,94,136,122,28,118,206,51,248,214,117,142,147,111,99,32,156,180,173,116,203,243,187,156,115,130,73,56,233,159,114,123,80,5,251,121,124,229,112,84,238,78,55,99,1,190,131,57,237,223,175,106,152,
49,56,235,215,39,167,63,231,250,86,70,159,5,237,142,160,241,159,222,218,206,236,252,177,204,108,73,61,249,60,15,243,142,116,137,32,42,16,199,39,25,7,160,247,254,95,141,0,33,186,86,37,98,42,100,12,55,35,112,216,221,130,113,244,206,42,66,125,118,134,166,56,34,76,239,56,254,239,245,162,54,243,35,86,218,200,113,192,97,205,0,85,101,151,251,72,72,100,49,219,44,68,109,7,25,110,229,189,70,63,80,43,54,236,73,29,209,19,76,25,151,1,78,56,193,250,99,29,179,91,44,233,229,23,109,193,99,60,177,39,183,127,126,213,145,168,35,92,106,15,137,17,163,220,177,168,47,142,125,6,127,17,140,245,35,214,147,25,27,32,185,155,231,37,128,3,157,220,231,20,255,0,33,118,156,43,225,70,114,205,194,224,115,82,173,178,194,222,92,142,119,183,70,140,100,12,100,126,157,42,197,184,129,157,130,178,186,21,36,144,255,0,134,8,237,158,127,42,64,98,71,106,110,175,20,0,89,67,38,253,170,78,1,61,235,119,247,86,25,48,194,70,252,109,219,207,229,255,0,214,171,11,99,24,12,99,2,51,192,44,190,131,56,254,180,178,91,133,195,12,151,7,25,
39,52,172,199,161,145,169,92,171,216,59,121,83,36,238,84,3,131,243,28,227,35,4,227,144,120,250,122,214,149,194,4,102,18,5,17,228,16,122,96,213,11,155,119,158,225,2,151,85,13,188,5,39,229,99,206,65,255,0,56,171,254,101,180,147,125,149,137,243,223,44,19,105,218,216,28,242,56,200,224,245,238,40,223,64,32,51,128,127,209,228,0,134,201,70,108,31,95,229,82,139,134,32,157,192,142,56,94,199,142,255,0,231,189,44,214,124,6,140,111,203,116,192,192,20,201,94,59,59,86,121,131,50,132,14,66,227,45,158,195,145,211,191,214,146,82,13,3,236,170,232,88,146,194,79,152,146,7,57,255,0,235,12,126,2,170,155,117,186,51,219,198,74,152,138,135,7,35,32,140,131,248,224,254,94,245,102,254,56,230,211,102,137,3,135,88,132,158,80,63,63,168,4,96,145,205,115,250,86,145,168,189,193,154,100,48,16,1,67,188,135,201,236,48,114,6,51,156,243,250,208,214,163,91,26,141,12,150,86,233,12,140,37,140,72,60,180,63,194,199,128,49,211,31,133,77,48,184,77,70,57,17,152,70,138,187,192,0,6,228,228,123,241,159,167,168,167,199,10,71,
12,72,68,129,211,108,123,149,113,159,124,224,126,127,133,79,12,241,75,3,200,102,27,98,98,25,249,249,118,158,120,252,41,164,38,89,98,128,54,253,204,156,16,78,49,248,99,159,255,0,93,102,67,246,155,57,156,90,162,53,187,16,223,63,12,59,28,122,116,29,127,74,190,21,90,52,6,61,170,114,217,217,150,25,246,61,15,76,231,222,169,73,21,219,93,68,33,153,45,212,28,184,9,185,27,13,199,94,153,29,135,79,94,134,168,69,147,58,75,105,230,198,164,44,129,176,202,50,122,224,17,145,215,143,113,89,210,218,79,114,193,226,104,145,184,18,54,73,35,56,60,12,15,113,201,236,42,199,149,58,207,52,86,228,54,242,101,63,40,5,115,198,57,255,0,119,31,159,78,215,109,96,132,219,194,0,221,180,150,86,115,185,179,156,158,125,115,154,91,129,31,217,32,138,88,230,35,27,51,140,30,253,63,250,213,36,115,67,129,26,130,161,48,160,99,24,29,49,239,85,110,181,31,42,55,72,49,44,168,112,21,84,190,57,231,32,125,15,191,74,91,171,201,44,244,226,210,132,55,25,220,176,238,220,70,73,192,63,134,70,122,112,113,76,9,165,130,67,132,182,144,71,
24,201,39,60,238,201,207,175,28,254,24,162,159,101,113,29,212,11,44,97,153,6,84,174,70,84,241,193,247,162,152,21,84,92,217,190,247,47,114,172,14,255,0,159,133,247,231,191,30,212,219,139,11,107,187,87,16,17,1,152,103,118,6,71,32,242,7,211,249,213,187,169,25,172,216,162,7,56,35,118,224,87,0,224,253,127,198,171,233,42,39,178,113,33,98,155,182,249,103,145,140,115,249,146,127,207,84,4,214,123,86,218,32,165,71,202,48,84,96,176,245,198,7,81,237,68,168,242,36,145,137,54,23,4,2,49,144,121,233,74,202,193,76,49,7,136,42,0,146,12,31,81,142,71,96,57,207,173,58,109,254,67,121,96,7,232,14,50,87,61,241,198,64,160,67,228,149,133,179,206,8,114,129,178,87,166,65,57,31,161,21,205,77,56,157,229,153,243,243,158,220,99,39,233,235,222,181,237,175,126,213,26,69,42,7,103,82,146,21,39,0,168,235,140,103,144,65,231,214,178,175,108,228,181,144,162,41,149,15,241,184,56,239,199,183,2,147,212,104,223,181,190,130,237,246,162,176,117,25,42,222,158,188,100,30,221,234,217,28,12,146,0,230,185,237,34,234,218,206,102,
18,179,33,108,168,56,1,70,78,78,127,16,63,51,93,8,109,200,93,72,111,77,188,230,169,59,137,149,47,5,196,146,71,12,114,36,33,155,27,136,14,254,167,27,191,46,51,214,163,212,109,229,158,49,28,108,170,229,192,217,187,110,254,229,73,28,253,220,255,0,158,150,229,5,176,81,21,200,59,114,120,32,103,7,159,233,237,77,131,50,66,174,87,18,33,32,174,122,28,227,63,136,231,232,104,0,137,85,33,242,16,22,120,163,81,243,140,118,227,39,30,213,86,59,123,84,191,89,226,139,205,103,222,12,219,183,8,206,114,87,29,191,139,241,250,213,224,192,97,202,149,56,201,83,140,143,106,65,178,85,249,58,114,56,24,160,8,110,182,27,103,221,56,132,56,41,188,224,108,63,95,211,235,82,39,200,193,11,111,43,212,240,15,61,200,20,173,108,141,23,151,50,249,128,1,247,135,95,127,173,11,20,65,64,140,96,32,227,7,0,14,159,133,0,53,196,130,80,6,10,158,73,39,144,49,199,212,231,233,78,142,69,98,219,67,97,88,169,200,35,156,125,57,235,66,7,37,204,202,129,67,97,48,73,36,123,254,167,241,168,218,234,37,185,88,6,25,176,73,198,62,76,17,215,
243,160,10,26,155,220,44,74,177,169,47,230,146,133,70,123,116,62,252,212,145,160,183,211,163,123,196,121,25,95,204,56,234,8,228,19,147,201,28,14,166,180,54,129,33,60,130,14,6,70,121,168,174,162,91,132,242,201,216,164,115,140,243,234,5,0,102,11,232,175,139,143,154,38,71,218,8,36,101,120,238,43,70,222,40,214,215,100,76,228,103,118,72,201,39,223,140,87,57,120,214,240,220,203,228,179,130,175,183,12,59,142,58,231,165,110,91,207,4,54,171,36,210,133,82,64,14,78,55,113,82,134,101,234,54,215,178,76,9,183,103,9,242,174,192,196,17,207,161,35,53,56,23,16,218,195,35,205,58,178,147,148,223,149,29,48,62,152,29,15,248,214,200,144,201,14,228,33,131,15,148,19,140,254,61,185,172,109,110,231,125,200,128,58,249,105,243,62,87,31,54,15,244,254,116,62,224,92,187,189,242,161,34,95,146,232,38,84,108,56,250,119,25,237,214,169,105,154,67,164,239,52,173,42,100,28,171,30,185,57,255,0,10,207,91,151,158,225,103,197,196,203,110,194,71,228,103,104,57,234,199,147,237,239,91,111,118,35,129,46,109,81,238,35,119,
231,230,35,3,4,101,65,250,116,239,250,209,190,172,12,139,171,187,136,149,131,188,136,199,4,7,114,49,244,230,182,52,203,153,102,136,73,54,64,63,42,247,200,207,94,153,246,255,0,128,231,189,90,158,214,11,149,49,206,135,0,229,88,140,31,192,254,148,34,41,137,60,130,165,112,10,109,232,70,61,187,82,73,161,220,198,214,46,36,182,242,161,181,219,20,65,88,199,176,149,96,221,14,8,232,57,232,61,123,85,55,212,158,120,108,224,156,180,128,73,251,210,24,174,245,221,211,150,193,56,238,113,219,220,215,66,246,240,77,242,202,129,135,222,193,25,233,76,154,198,23,120,115,229,170,196,217,218,16,12,143,79,243,218,141,64,144,50,92,42,202,185,42,227,35,35,110,65,250,210,36,59,11,50,162,130,199,39,220,240,51,250,126,149,38,81,78,196,0,108,81,242,40,192,81,208,126,28,82,143,66,251,78,115,145,223,252,243,78,218,136,142,212,121,22,254,67,76,36,117,27,153,183,118,36,156,251,14,191,149,73,16,145,17,68,170,158,102,63,132,156,126,103,249,154,147,169,31,42,228,240,72,224,227,159,254,189,67,121,44,118,168,101,151,
229,141,122,224,18,122,251,123,211,17,40,32,43,147,133,78,172,199,129,142,245,135,169,107,70,98,177,233,197,138,131,243,72,192,140,244,198,57,235,156,231,62,149,45,198,164,143,20,109,36,106,209,28,230,221,159,57,25,224,177,198,59,30,57,234,13,81,183,134,54,140,6,114,20,14,135,130,78,63,250,212,152,198,9,111,68,139,33,158,86,80,49,203,31,167,3,215,173,104,233,87,66,87,41,112,128,201,185,74,179,114,192,250,103,234,127,157,80,31,44,159,34,253,11,15,97,192,0,116,171,182,46,182,251,231,109,199,229,192,81,198,238,153,205,0,3,75,23,44,205,109,114,82,7,98,254,83,112,20,231,25,0,122,224,254,20,85,155,120,83,103,218,33,157,227,86,194,144,203,158,121,244,234,61,232,170,176,139,211,178,90,47,154,23,175,4,3,199,111,240,170,49,223,199,119,49,133,124,192,35,111,48,51,1,198,8,200,252,121,31,141,20,80,4,78,134,239,83,140,200,204,68,103,122,161,39,104,199,78,61,65,25,247,253,43,69,152,170,176,236,48,127,50,69,20,84,161,145,253,167,204,91,134,198,223,36,252,216,238,7,38,168,234,119,9,42,201,111,
177,188,200,142,67,110,192,193,231,241,244,246,162,138,108,12,248,2,204,164,177,101,146,1,230,54,57,86,81,142,128,244,60,212,90,117,203,179,129,28,243,199,111,184,22,64,121,57,233,207,225,233,233,69,20,128,235,221,194,109,78,73,60,2,121,252,235,10,210,229,213,229,66,205,34,111,105,14,73,82,9,200,192,193,198,59,253,121,250,20,85,48,44,91,106,78,64,134,118,243,24,176,93,251,0,60,156,116,233,255,0,214,162,13,68,42,8,188,178,140,185,25,86,45,192,62,167,154,40,164,246,17,86,15,244,123,166,184,73,167,249,184,41,230,28,19,201,25,206,114,61,250,243,91,138,124,221,178,70,204,160,243,207,126,104,162,132,3,152,24,227,235,187,158,50,113,89,183,22,182,112,202,147,125,159,50,59,110,206,242,70,79,57,193,239,69,20,192,132,67,51,204,94,121,73,27,182,198,3,31,148,246,53,107,100,209,136,156,204,197,20,143,147,60,17,205,20,82,2,56,146,222,242,83,114,109,208,56,0,177,60,231,168,254,84,213,211,66,88,139,105,152,72,195,238,201,140,16,58,254,29,0,162,138,6,54,198,193,172,165,2,57,55,44,131,4,30,57,245,
255,0,62,180,147,105,102,234,89,36,105,153,36,44,115,142,70,59,15,202,138,41,32,35,77,56,233,235,43,25,140,144,200,134,60,116,35,113,3,222,175,88,39,218,44,163,98,193,183,6,27,138,5,224,19,142,7,30,148,81,78,192,61,46,0,145,96,69,57,251,163,61,58,102,164,154,64,155,131,3,242,46,227,142,227,6,138,41,8,107,206,130,64,133,114,88,19,237,193,170,210,106,17,71,156,163,16,164,131,211,214,138,40,25,106,54,89,45,214,109,163,145,145,237,197,38,255,0,221,121,138,56,198,113,211,181,20,85,8,122,177,11,156,13,216,6,179,181,9,22,123,54,75,148,46,170,84,54,214,198,73,57,255,0,217,104,162,165,140,168,45,149,255,0,210,20,109,140,133,42,128,159,149,66,19,239,206,23,243,168,213,248,105,2,133,27,119,0,57,35,243,250,81,69,0,77,27,5,140,14,112,164,131,254,127,10,145,101,50,32,82,73,82,113,201,237,69,20,196,104,37,215,154,24,197,148,10,118,145,142,253,104,162,138,96,127,255,217);

back_stone:array[0..15706] of byte=(
255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,255,219,0,67,0,23,16,17,20,17,14,23,20,18,20,26,24,23,27,34,57,37,34,31,31,34,70,50,53,41,57,82,72,87,85,81,72,80,78,91,102,131,111,91,97,124,98,78,80,114,155,115,124,135,139,146,148,146,88,109,160,172,159,142,170,131,143,146,141,255,219,0,67,1,24,26,26,34,30,34,67,37,37,67,141,94,80,94,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,255,192,0,17,8,1,61,1,89,3,1,34,0,2,17,1,3,17,1,255,196,0,31,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,
122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250,255,196,0,31,1,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,17,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119,0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,247,248,249,
250,255,218,0,12,3,1,0,2,17,3,17,0,63,0,176,195,43,237,222,157,63,148,177,110,71,93,221,6,15,90,141,90,67,144,85,112,8,201,207,106,126,224,132,0,170,20,242,113,92,201,51,87,98,56,220,220,68,195,238,183,245,167,238,40,2,185,201,35,32,117,38,156,54,144,85,127,12,83,34,18,46,71,83,250,138,161,3,179,196,119,4,44,222,131,173,44,133,207,65,248,209,188,183,202,1,66,189,186,211,7,152,210,252,178,236,247,198,115,76,8,140,170,229,215,42,172,188,96,158,188,117,169,227,66,145,2,164,31,80,56,168,158,209,224,103,145,20,190,238,15,122,124,88,81,128,195,24,200,231,138,76,7,43,239,113,142,220,98,156,208,202,115,144,8,39,241,20,216,216,11,143,152,229,136,224,118,205,88,93,254,96,7,166,58,82,2,36,141,82,64,15,111,106,73,209,28,124,227,35,173,73,112,193,10,228,31,74,137,228,94,6,15,39,29,41,59,220,106,197,114,89,50,138,255,0,33,227,167,74,146,59,117,85,82,132,134,207,36,113,154,129,220,9,182,63,25,239,87,99,145,20,236,39,145,237,138,122,139,65,74,182,42,52,82,25,139,247,232,58,210,249,231,206,242,
193,4,1,146,113,210,134,147,4,100,129,158,149,72,66,109,193,227,57,197,67,46,252,128,23,57,239,138,183,24,71,234,70,125,250,138,135,32,177,249,186,103,173,0,10,50,57,28,103,154,141,148,187,101,78,84,100,102,146,41,3,49,198,118,158,245,34,243,194,246,237,73,177,162,120,95,106,40,33,155,215,3,53,94,246,124,143,45,84,198,228,253,227,197,56,43,62,87,36,125,42,69,10,242,134,56,38,63,187,206,126,180,151,152,16,219,18,99,30,100,156,243,145,255,0,215,164,119,141,37,27,78,65,31,149,89,145,90,67,185,118,238,28,99,189,71,26,27,133,63,187,193,247,226,168,68,106,196,227,105,224,122,246,53,50,202,78,73,92,115,201,6,171,60,115,71,54,220,48,24,251,198,164,86,219,195,31,254,189,38,134,19,162,228,186,252,164,142,72,21,30,247,84,27,121,247,2,160,188,212,4,44,17,6,246,61,135,97,83,65,46,252,58,29,202,122,17,222,157,172,3,162,49,221,229,88,43,99,131,197,76,209,8,226,62,87,202,0,224,118,168,67,249,115,28,112,91,158,149,51,144,202,87,37,65,227,52,8,34,143,118,50,192,156,122,210,178,0,159,188,201,21,
17,64,136,10,156,1,239,83,43,174,210,3,96,145,222,128,50,110,45,47,30,229,90,28,249,57,206,51,211,240,239,87,99,83,27,135,108,144,7,78,188,212,171,254,179,27,135,76,224,113,83,164,125,65,92,134,239,64,0,144,56,12,58,83,138,159,225,235,138,132,20,66,201,156,21,167,135,39,129,158,105,88,99,30,21,127,190,1,0,228,102,144,227,118,64,233,197,60,150,57,39,165,55,203,11,157,188,115,76,64,102,216,225,3,41,98,51,239,82,2,37,143,114,231,142,181,94,40,202,114,64,221,220,142,166,155,44,173,110,48,132,109,99,147,64,15,55,10,185,70,86,221,234,7,31,157,49,247,18,72,224,31,106,148,109,16,171,16,119,55,52,9,10,146,54,252,135,189,0,68,161,130,128,35,64,79,115,159,241,169,54,159,238,210,72,160,13,199,119,30,212,187,143,168,252,233,52,49,100,57,66,84,28,116,36,14,213,18,43,46,208,196,242,120,200,167,169,112,50,185,31,74,92,114,67,202,24,168,200,201,230,141,128,122,252,185,32,80,114,114,15,0,251,211,12,160,96,140,144,125,168,36,151,7,63,90,77,130,24,192,170,225,79,63,210,161,27,204,138,51,192,231,
39,189,78,228,179,20,3,57,20,197,77,144,227,110,85,122,123,85,32,37,89,102,82,161,88,96,245,246,168,46,128,144,230,93,235,158,241,146,51,245,169,20,110,92,198,20,49,224,110,60,154,85,102,19,0,227,182,8,244,160,67,226,145,33,137,34,229,142,56,245,62,244,169,112,20,96,224,28,245,168,164,17,179,176,137,129,200,227,219,218,163,9,10,228,60,108,204,122,114,105,88,101,214,96,80,243,158,245,86,54,118,80,204,152,231,215,181,44,31,55,200,8,95,169,169,100,136,134,200,32,175,64,69,8,25,20,241,137,74,190,220,182,123,84,210,68,30,100,57,32,175,95,122,68,144,169,17,149,200,57,195,14,180,228,73,3,150,221,184,30,199,173,49,12,49,173,187,182,6,224,254,252,208,54,129,247,129,247,169,22,32,121,35,11,156,224,211,37,66,192,108,235,237,74,250,140,106,128,209,187,17,140,28,115,252,233,163,107,33,86,3,61,79,248,212,200,124,200,240,120,62,194,171,72,49,158,115,66,96,17,168,84,192,29,243,79,206,79,90,141,73,192,200,167,41,205,0,58,69,44,140,65,60,142,212,200,16,170,157,163,7,175,39,173,76,191,48,192,56,
160,40,137,185,110,131,60,208,4,23,15,242,168,109,202,195,145,142,227,210,172,219,204,35,194,177,207,28,28,84,19,57,206,192,56,61,143,74,97,80,200,23,113,36,123,208,128,210,145,209,151,174,107,46,233,75,166,244,227,3,62,153,166,92,171,20,85,220,56,29,51,82,66,3,70,22,76,231,167,52,1,152,29,164,189,147,128,160,252,167,61,51,83,91,91,203,5,200,141,100,223,27,29,220,127,9,171,235,4,97,79,46,119,118,6,150,59,88,84,130,169,142,244,92,7,36,109,231,57,192,192,199,39,189,60,238,113,146,55,47,67,197,73,19,34,166,223,67,192,163,204,2,66,23,230,67,247,168,2,33,25,243,132,128,130,42,80,165,152,171,116,245,199,56,250,210,103,247,128,71,187,24,206,71,79,165,42,182,7,28,54,123,208,129,140,141,66,184,233,220,242,115,83,75,38,196,224,100,158,128,84,2,63,153,159,61,122,250,254,20,168,172,36,44,100,220,49,192,61,168,96,53,54,146,197,186,154,78,60,204,43,145,129,247,65,160,38,9,56,237,211,53,42,166,228,243,7,64,122,250,208,3,179,193,24,57,165,31,59,240,126,111,74,68,100,44,138,196,6,94,160,85,176,
99,4,129,180,30,189,40,184,88,129,162,219,207,115,233,80,54,201,24,252,249,42,121,2,172,179,133,96,168,220,103,156,156,154,134,105,162,81,140,50,0,123,80,128,144,198,95,33,71,203,211,38,144,194,184,108,231,154,142,19,40,144,179,49,193,232,49,199,214,172,103,154,0,135,203,80,189,9,199,115,77,222,63,201,169,92,241,192,250,213,108,31,79,214,129,8,173,32,27,78,61,141,44,104,67,18,15,94,13,53,1,124,14,130,156,238,35,113,25,94,88,124,164,80,198,62,69,10,132,227,167,53,94,36,149,142,231,33,87,208,119,169,218,49,42,108,115,131,158,113,77,98,138,126,76,251,241,69,128,69,137,92,178,150,193,83,145,138,148,58,70,160,48,227,190,69,64,75,43,252,170,8,60,156,84,200,51,24,46,164,131,205,0,49,226,98,251,131,237,94,192,28,84,97,25,174,129,145,200,85,198,51,235,158,149,96,54,230,195,12,14,212,143,25,4,54,14,9,255,0,38,139,133,135,236,183,4,252,170,15,99,142,255,0,90,137,195,20,61,201,234,105,72,228,145,199,181,48,177,9,142,167,218,128,43,156,6,4,241,248,212,161,128,233,156,125,105,185,141,223,24,
32,142,198,156,238,168,164,132,206,41,136,144,62,229,83,140,31,229,83,43,1,199,173,68,168,211,70,29,97,199,31,149,40,4,99,6,149,135,114,102,35,4,10,133,102,82,229,84,231,29,72,233,67,2,200,66,156,99,131,72,170,17,118,128,0,237,78,194,3,145,157,162,162,114,234,64,42,25,125,71,81,82,158,164,122,12,212,80,72,101,139,115,40,92,244,193,205,33,139,41,49,40,44,54,169,233,66,114,155,243,158,58,98,157,229,7,32,62,10,131,78,200,70,7,110,238,220,80,3,25,151,122,140,144,231,176,237,72,21,158,92,56,44,49,215,52,226,155,159,60,99,61,59,211,246,40,101,35,131,158,198,152,17,186,133,113,184,99,183,90,82,136,1,32,131,234,49,83,49,101,227,212,114,121,235,77,141,37,156,18,19,215,158,131,255,0,175,72,69,23,143,205,202,32,57,207,94,212,232,97,112,227,158,9,193,62,181,110,75,57,226,93,209,4,227,175,114,41,145,157,138,20,144,114,115,159,90,96,43,15,47,143,81,193,197,49,36,207,96,51,77,102,148,3,24,93,233,208,19,78,64,23,10,72,30,185,164,134,18,118,101,29,123,211,162,112,231,157,200,64,234,14,69,50,76,
114,170,118,147,208,245,205,75,14,253,164,186,227,29,232,176,92,153,136,138,44,129,183,140,116,235,80,146,220,41,199,212,245,168,102,150,77,224,100,149,199,7,20,59,19,243,28,156,142,212,208,152,249,203,46,208,132,49,205,72,9,108,17,198,121,170,166,103,138,229,64,80,85,134,15,181,78,126,112,1,28,10,0,120,117,137,137,216,78,125,77,73,230,41,32,228,128,120,166,0,31,228,117,227,212,117,21,30,93,78,56,249,71,4,247,164,50,97,18,175,42,75,14,188,154,115,99,0,149,206,58,10,171,36,133,194,124,187,8,234,85,186,211,188,210,58,243,198,126,180,172,4,174,202,91,126,54,149,227,34,162,147,121,96,56,57,227,38,148,130,196,145,158,189,168,39,100,36,48,7,232,40,216,100,177,178,42,42,179,128,71,3,38,145,156,231,25,252,69,69,228,237,234,72,3,242,53,40,220,234,6,14,62,180,196,43,92,110,67,229,198,125,203,113,85,247,191,183,229,86,130,20,140,255,0,83,80,111,30,130,132,1,43,42,108,32,18,164,227,142,212,196,114,146,2,196,48,82,121,39,165,61,84,150,222,161,254,94,54,142,244,58,16,73,249,73,110,64,244,160,
8,65,115,24,145,70,228,39,174,122,213,142,29,207,108,210,74,187,109,225,92,133,35,31,202,152,175,184,97,27,57,232,84,228,26,107,81,49,193,2,156,3,206,115,82,163,113,181,177,129,235,80,153,21,49,184,129,142,164,212,45,51,73,48,41,243,71,130,63,28,82,176,203,51,72,16,18,160,96,117,57,167,194,203,36,101,186,143,82,106,56,103,141,34,231,229,110,164,17,76,102,204,132,46,227,184,114,61,169,1,59,99,140,116,168,100,144,36,123,152,157,160,250,84,139,247,70,58,84,119,74,190,65,81,158,72,233,215,173,48,1,134,10,232,9,244,226,156,144,188,243,239,56,192,235,218,148,32,80,3,183,78,50,59,212,138,225,91,105,124,100,113,138,119,17,49,116,142,45,170,122,100,115,214,171,135,68,192,108,100,241,214,148,21,36,4,32,145,212,85,107,180,243,24,5,62,217,2,132,5,162,57,198,9,21,19,184,25,33,11,31,106,70,38,36,10,1,44,170,7,34,146,55,153,212,47,149,184,183,67,219,20,0,239,48,121,125,8,108,103,4,82,91,196,18,49,242,227,60,144,58,19,72,249,46,71,204,10,245,90,121,80,88,113,156,30,134,144,199,54,49,185,126,
82,42,24,18,73,62,98,164,103,160,254,181,33,71,36,143,187,234,106,104,159,12,80,99,24,226,128,33,104,129,143,14,50,231,169,167,136,149,0,61,112,42,73,27,140,84,59,216,144,85,50,7,82,122,10,58,8,89,164,1,15,202,205,236,189,105,208,50,170,137,20,228,149,199,39,173,66,0,185,155,102,74,129,216,127,58,181,111,26,8,135,200,20,228,245,28,129,64,197,251,67,134,201,32,41,232,59,213,73,148,100,203,34,129,232,42,227,150,137,93,151,18,1,208,99,165,65,38,31,35,0,30,199,214,128,35,15,132,1,87,36,142,57,197,73,17,8,54,50,3,159,189,222,163,104,210,100,57,206,71,66,13,10,19,40,84,21,66,58,115,147,72,9,145,83,113,96,0,31,78,148,13,228,140,224,47,113,80,181,214,233,74,58,236,219,200,0,245,169,140,128,168,97,145,158,180,192,137,193,25,10,1,237,130,105,8,199,78,105,74,103,230,222,66,156,96,10,121,141,17,126,81,141,199,36,129,74,225,98,23,85,105,126,230,113,212,251,84,145,128,121,94,135,156,122,83,217,85,83,230,28,250,212,112,15,222,131,219,60,175,74,96,79,229,158,167,30,245,4,234,170,155,162,86,118,
237,87,152,98,170,72,73,144,140,1,245,160,10,69,223,121,89,19,146,50,0,167,150,109,160,224,51,14,222,213,43,4,222,64,193,61,233,193,81,49,180,96,122,10,4,69,12,161,1,89,50,1,62,157,42,127,151,32,171,15,206,152,247,77,144,22,13,217,239,197,39,152,129,151,125,191,95,78,104,106,227,185,41,114,176,50,144,50,79,36,84,81,184,110,81,151,104,245,56,230,163,184,141,102,204,113,134,64,223,129,166,199,2,164,101,20,22,96,48,51,218,132,128,183,230,151,76,21,218,125,170,47,42,58,14,228,81,188,134,32,14,130,147,204,255,0,98,129,11,35,157,161,79,92,228,1,197,53,230,8,141,179,59,219,177,52,226,202,201,176,231,220,231,21,12,223,34,238,64,25,137,206,49,212,123,83,2,73,215,237,88,69,44,163,28,158,134,163,67,13,172,138,136,24,224,96,159,74,116,87,4,163,38,113,34,253,241,142,130,159,36,232,136,21,72,4,240,71,181,37,113,177,29,214,67,183,185,233,154,91,120,34,144,190,25,148,129,134,231,189,86,153,153,16,50,158,55,113,142,213,36,82,76,90,55,136,15,155,239,18,58,211,17,108,36,80,0,204,249,231,171,81,
42,35,48,104,158,48,122,28,122,85,89,183,187,249,140,193,130,143,184,6,42,91,118,43,51,159,188,155,65,227,181,0,49,218,69,108,32,82,189,216,183,2,164,65,35,41,40,160,142,199,56,205,36,167,204,125,235,128,163,160,61,233,202,219,83,61,170,91,26,17,67,150,201,63,40,224,140,84,246,137,24,46,202,62,98,112,115,80,171,171,169,227,138,108,152,141,23,202,59,15,114,123,211,76,25,45,215,149,231,166,120,35,169,28,83,35,89,14,114,224,143,225,219,253,106,34,85,136,231,44,71,52,174,210,65,130,72,218,71,99,64,22,127,118,28,137,6,72,35,38,166,19,70,62,80,220,10,204,73,101,18,6,141,114,189,242,121,169,21,156,176,44,155,51,192,231,56,247,160,9,174,84,40,45,26,179,190,106,178,74,235,48,18,141,188,110,24,237,86,179,187,3,35,62,226,153,40,134,38,204,135,25,247,161,48,177,50,149,144,124,167,52,113,24,222,231,254,2,42,186,180,114,178,172,32,185,239,140,113,245,167,20,97,54,73,206,193,141,167,165,0,30,102,233,119,41,228,158,57,171,41,130,133,64,28,245,170,241,193,18,110,117,28,183,36,158,181,26,134,140,
57,141,155,4,140,81,184,19,174,216,223,5,128,110,159,90,176,160,14,9,170,99,153,22,70,43,233,134,236,106,91,139,163,20,67,0,14,128,147,70,224,62,236,59,32,0,225,71,39,29,77,83,93,251,142,65,13,219,35,181,63,126,78,90,93,223,65,70,237,135,25,24,231,28,116,166,32,242,144,174,220,150,233,158,105,234,232,54,163,48,82,56,25,168,144,57,132,110,0,54,58,226,152,177,20,37,157,132,164,254,20,182,220,100,175,18,51,49,15,25,90,55,42,62,6,226,113,208,85,152,98,10,128,48,252,40,88,86,32,193,71,122,47,112,41,253,165,211,119,153,23,201,233,222,166,89,124,212,204,127,119,215,60,210,73,130,197,70,61,234,168,140,199,43,60,99,142,152,207,90,73,32,108,151,205,84,32,146,197,122,28,140,243,86,14,215,76,175,94,245,65,152,237,63,46,95,161,239,244,169,227,5,16,239,126,212,192,157,100,116,225,137,34,160,203,188,234,170,112,51,147,223,34,144,92,13,251,87,145,223,61,170,76,149,145,10,186,140,30,114,40,216,4,185,83,20,91,155,27,179,192,205,71,110,254,100,4,134,203,110,198,49,78,158,116,118,62,105,93,163,175,
173,64,147,24,7,220,198,114,64,11,71,64,45,60,78,223,56,35,212,131,253,42,52,2,53,12,174,85,79,82,71,106,103,152,242,204,128,202,81,58,176,2,172,205,182,68,242,85,67,1,142,72,205,49,13,119,41,41,112,67,169,0,12,246,167,38,228,70,36,127,245,234,161,138,75,78,91,231,71,112,54,129,147,86,255,0,116,114,155,138,51,116,7,250,82,24,200,255,0,122,166,78,1,7,24,207,74,118,15,249,2,145,173,182,33,193,228,211,54,183,168,164,2,19,181,156,2,59,96,154,148,35,60,96,231,115,100,140,3,142,41,194,52,218,10,241,248,82,12,47,205,142,188,115,76,8,141,178,166,8,143,13,208,156,84,119,8,35,116,218,6,72,199,90,186,242,175,148,85,72,36,240,79,165,71,16,76,144,57,101,224,146,40,184,172,87,134,215,124,164,72,27,106,140,243,210,172,58,1,242,157,163,29,49,79,119,40,133,212,100,142,160,241,154,103,218,35,108,177,92,17,235,75,113,148,229,243,144,149,103,10,113,201,199,244,161,92,52,74,177,19,242,158,163,233,82,202,82,73,114,203,207,99,78,138,221,94,85,200,224,115,84,34,40,229,103,98,29,118,224,227,173,74,84,
170,12,54,84,245,21,96,90,198,161,182,18,185,29,206,106,158,55,39,223,201,233,129,64,22,80,2,6,222,61,169,151,68,20,95,108,210,135,242,192,10,185,252,105,179,144,193,113,207,6,146,25,90,54,42,249,28,142,212,233,9,150,77,172,66,167,83,207,52,224,131,1,136,235,83,71,0,198,64,198,14,64,166,33,91,106,70,68,64,100,80,161,202,18,220,144,62,239,74,112,136,17,146,71,212,83,8,13,144,173,200,164,49,85,136,108,237,228,119,246,168,239,35,141,149,102,156,22,41,209,123,115,235,79,12,89,240,20,238,199,39,60,82,48,70,34,46,172,70,72,161,43,6,226,91,78,88,42,3,131,252,169,242,79,182,82,165,78,123,154,106,68,11,231,5,79,74,124,139,187,168,0,14,166,128,34,19,169,45,150,207,168,7,175,210,156,243,193,130,128,114,188,253,227,81,189,170,72,235,180,168,108,247,52,153,120,228,16,152,203,17,233,78,194,184,134,224,249,202,22,49,130,70,119,30,149,52,233,44,128,18,163,30,199,154,106,152,90,102,86,92,21,228,241,156,125,42,120,164,29,137,32,242,51,218,147,118,30,228,130,37,69,249,71,231,222,163,127,153,185,
92,158,220,83,89,230,32,148,127,168,53,20,47,33,102,243,112,49,198,1,161,3,30,24,162,101,163,200,254,239,92,81,42,200,165,65,92,231,158,191,165,49,183,228,2,228,2,125,115,82,137,136,36,174,61,233,1,97,37,56,249,145,135,167,25,164,83,32,102,98,126,241,232,122,84,38,94,132,176,227,170,138,107,184,102,86,92,2,58,18,57,20,32,7,103,118,117,10,168,15,39,29,105,164,50,100,255,0,15,173,62,57,83,118,39,96,167,177,29,233,236,185,206,57,30,160,211,64,82,138,92,204,58,115,193,207,122,176,202,210,14,24,3,238,42,25,33,15,48,195,116,25,197,61,136,73,19,4,15,165,49,14,242,194,224,2,21,143,64,59,213,75,167,125,248,236,122,30,213,52,195,247,172,249,4,158,56,237,70,209,180,6,60,117,193,52,154,184,239,98,180,16,200,237,156,140,147,220,85,244,216,0,36,131,129,130,72,205,68,36,69,192,64,75,126,117,60,191,112,24,128,95,90,44,4,114,237,243,0,10,114,222,135,21,50,58,198,58,53,85,56,50,151,249,139,17,215,53,109,83,114,130,188,140,116,61,77,12,6,188,137,40,62,171,206,106,7,196,203,229,156,227,60,12,83,
228,8,196,108,24,246,160,225,127,189,215,242,166,149,132,73,16,104,193,89,73,35,177,205,46,19,219,245,166,201,38,224,63,157,55,241,165,97,143,85,40,167,141,196,212,47,49,117,216,200,201,158,228,84,190,103,204,1,198,123,251,84,18,220,199,149,92,156,142,126,180,0,248,23,108,69,73,221,159,155,39,138,150,53,27,75,110,39,113,192,0,83,14,25,62,94,184,227,52,242,75,69,242,48,14,123,250,81,112,35,157,75,168,220,204,48,122,14,148,229,133,85,126,108,125,115,78,220,89,8,101,32,143,94,134,160,196,243,70,197,74,170,131,192,63,211,52,0,187,67,157,167,138,150,217,86,41,10,238,201,30,244,216,160,151,57,114,165,127,90,14,87,4,113,219,214,139,244,1,243,202,115,181,71,212,250,84,74,169,176,10,20,21,136,135,109,196,158,189,51,68,113,51,28,40,206,57,160,6,252,184,31,56,60,144,113,79,203,75,194,42,168,31,222,230,157,229,42,43,101,70,122,211,130,129,198,127,42,76,17,28,160,44,120,80,14,41,60,221,138,170,15,24,206,5,12,68,111,176,246,28,100,245,166,73,58,101,142,50,0,206,236,112,42,144,15,102,114,131,
147,248,82,124,249,92,99,208,138,88,131,17,189,115,180,138,88,201,19,243,142,120,164,4,104,133,174,10,150,199,57,192,110,113,86,86,21,142,93,234,10,228,228,226,148,197,10,183,153,181,119,255,0,127,28,213,119,121,94,76,198,223,47,113,64,19,130,55,30,148,147,72,198,51,179,233,205,64,200,229,179,188,168,238,170,58,212,201,17,100,220,100,193,236,61,40,2,1,110,242,202,36,36,168,3,149,207,6,172,42,174,126,78,15,76,247,52,210,95,206,192,4,40,28,224,119,245,163,113,110,1,198,63,90,77,177,160,145,24,56,8,58,127,17,25,168,220,146,75,33,0,255,0,119,214,158,147,21,111,222,28,175,126,41,51,27,72,70,14,15,29,41,110,27,17,196,93,99,195,17,215,211,21,38,252,39,24,247,247,167,136,80,50,129,199,227,73,52,1,6,244,31,239,14,244,196,68,216,249,119,144,65,224,28,125,223,165,36,113,136,254,225,99,156,245,239,79,151,230,139,25,25,207,6,164,140,38,57,108,227,189,8,10,211,2,211,0,6,72,92,211,215,56,195,30,157,192,167,201,25,14,36,198,127,10,102,252,178,227,133,250,85,8,138,89,118,92,199,144,197,185,0,
1,197,88,73,62,93,192,168,207,67,214,171,94,186,159,149,50,24,250,15,206,164,143,238,42,182,72,7,156,208,3,237,239,162,30,99,59,130,49,248,159,97,83,2,172,158,106,68,87,61,65,234,69,86,107,104,218,64,241,71,140,158,160,116,57,169,228,113,12,99,229,39,177,35,181,72,199,41,249,9,34,162,218,8,5,134,49,201,207,74,89,15,154,187,114,0,36,17,207,74,123,0,188,49,45,142,217,167,96,184,182,177,13,165,136,206,122,84,55,162,85,128,249,43,243,118,205,88,105,60,146,131,36,161,24,0,1,67,201,230,17,133,32,246,4,81,212,8,45,226,127,37,119,144,91,215,165,61,151,3,106,158,71,25,7,20,187,138,241,140,10,49,33,57,69,249,79,94,113,76,68,40,84,171,147,146,84,224,231,249,210,177,243,92,42,157,160,31,155,214,163,72,36,73,114,14,70,122,213,167,6,64,6,208,74,244,97,64,17,4,86,206,56,231,243,165,242,135,247,205,53,149,247,12,28,114,112,49,78,203,255,0,117,105,88,99,194,130,120,224,210,52,81,146,20,224,96,113,142,244,144,1,142,164,156,244,53,36,106,100,98,49,130,7,67,76,65,26,8,215,46,50,216,238,42,28,133,
145,138,156,41,57,32,84,183,16,73,44,46,48,23,177,193,193,166,34,101,187,5,160,5,82,193,199,7,30,221,170,73,100,12,20,239,35,215,138,138,41,0,145,163,39,230,251,192,123,81,42,225,73,11,144,59,84,117,177,68,158,110,192,2,144,212,130,117,108,172,128,7,29,133,50,32,133,200,251,167,29,41,204,164,119,231,212,85,8,135,153,25,68,99,129,207,204,56,171,144,108,136,177,61,78,58,85,83,192,1,123,119,165,23,1,71,168,246,164,5,137,151,205,36,141,164,31,126,149,28,112,111,147,40,219,113,215,189,34,76,28,101,84,63,61,142,41,222,90,173,194,204,173,179,35,145,158,180,0,146,217,186,49,117,33,142,49,244,170,119,39,236,251,119,144,160,214,163,58,72,161,50,64,237,205,71,42,68,99,104,216,111,7,144,122,211,64,66,84,24,240,141,129,140,241,76,4,130,1,92,103,161,245,169,143,24,203,28,116,24,25,166,24,228,103,4,46,66,159,206,128,28,196,200,14,49,129,215,53,10,200,174,135,10,193,143,32,226,146,222,87,133,136,148,99,147,205,89,89,99,145,65,86,28,247,197,22,1,185,1,1,199,255,0,90,164,142,37,10,10,224,28,244,
52,27,102,56,37,240,58,154,171,114,118,56,93,220,158,105,216,69,171,153,68,113,134,92,19,156,28,85,57,75,18,24,125,209,212,80,184,50,168,45,147,158,148,231,86,192,86,4,19,206,7,74,67,16,178,186,46,233,50,125,49,78,84,100,227,112,217,212,14,245,26,237,68,109,163,145,201,167,35,41,63,49,36,19,193,20,88,9,163,108,30,64,198,122,212,210,50,162,238,251,192,142,149,78,73,140,78,84,16,64,28,84,192,147,16,37,87,223,52,88,2,24,210,87,96,8,207,166,41,90,51,11,128,23,229,61,199,175,189,66,82,57,6,252,150,113,253,211,142,126,181,34,13,235,230,62,114,191,194,205,156,125,13,0,43,46,231,27,178,64,167,173,184,50,111,35,143,65,81,171,224,96,144,49,206,106,117,155,104,31,41,252,169,136,174,209,197,20,199,118,91,36,12,10,95,179,219,151,37,67,168,60,96,211,207,151,43,229,251,118,28,84,115,72,128,241,198,58,14,230,128,17,96,217,39,202,193,151,211,56,167,186,225,75,96,1,216,19,222,160,68,119,0,145,219,185,169,164,140,38,211,34,157,203,220,115,72,100,40,133,67,4,56,32,244,53,52,108,126,241,27,72,236,
106,51,58,146,81,84,183,174,69,74,178,161,254,19,211,24,52,174,22,12,249,237,144,225,24,28,12,142,180,18,251,143,64,65,193,239,72,54,185,5,67,96,122,140,82,109,231,4,145,245,161,177,162,94,60,196,86,32,230,164,200,124,170,246,170,232,34,4,146,223,55,235,77,140,186,200,74,71,140,156,100,210,1,242,23,204,74,163,4,158,126,148,147,31,46,76,118,30,148,246,143,108,129,139,32,110,153,199,106,104,153,38,125,152,33,187,229,78,77,80,136,247,157,192,238,7,60,99,210,159,149,244,52,215,137,163,57,235,232,61,5,51,127,251,35,242,161,129,56,133,89,3,3,130,70,72,244,53,28,115,171,49,220,223,50,156,17,244,165,80,219,134,222,24,138,88,18,59,114,88,12,135,231,45,212,83,216,68,178,200,36,147,167,0,99,53,18,144,197,130,181,75,114,227,148,232,27,142,42,9,34,149,33,34,29,161,251,110,233,72,98,172,8,210,121,142,217,199,76,28,83,3,56,98,24,124,185,32,19,220,82,179,236,87,39,219,165,34,146,109,247,72,114,15,78,58,209,96,184,142,187,36,86,61,65,231,233,82,110,206,112,65,250,211,34,28,245,56,198,64,207,122,
144,128,232,51,215,190,5,38,8,137,212,188,124,147,64,145,68,101,66,240,189,241,73,44,161,23,4,19,159,65,79,139,105,136,228,19,129,206,104,64,200,212,4,201,80,85,79,37,115,82,71,4,110,235,33,39,216,230,130,160,178,149,206,15,95,106,118,242,24,110,198,222,184,239,154,96,48,92,49,109,188,18,91,28,85,166,221,183,42,170,0,233,235,85,224,88,163,243,10,40,98,199,35,60,226,172,152,252,200,114,204,84,17,211,210,134,4,49,202,174,193,134,56,237,82,2,64,12,24,1,187,161,255,0,235,83,31,100,42,219,72,221,215,166,42,36,101,218,36,110,80,54,61,126,148,0,93,134,23,68,99,40,71,65,218,163,65,186,64,8,35,111,241,84,207,34,203,146,164,228,28,3,235,76,11,135,223,38,118,159,74,4,94,51,32,139,45,158,7,165,81,104,188,233,247,22,45,208,227,24,192,244,169,194,110,59,184,233,192,166,172,168,46,9,35,15,198,252,126,148,238,0,150,163,204,98,35,92,14,120,234,105,165,20,157,202,27,39,140,250,85,135,108,62,3,99,140,212,74,165,164,192,39,7,175,53,55,212,171,17,121,88,193,86,228,250,142,105,229,67,166,210,0,110,
216,164,186,105,45,218,36,141,67,110,59,65,61,170,73,138,197,140,158,77,50,74,205,16,19,43,28,100,159,173,89,117,1,15,167,165,86,144,200,167,112,28,15,79,235,83,174,74,96,240,15,189,23,25,2,170,169,0,141,160,118,52,74,249,108,169,24,233,83,73,184,0,20,103,53,92,249,108,229,21,57,29,72,61,232,64,88,183,101,4,150,197,30,118,225,128,114,1,36,243,80,197,18,137,14,249,24,131,209,105,98,138,72,231,144,159,153,113,198,7,90,0,153,54,231,140,100,251,211,252,176,121,199,90,165,118,110,81,3,64,138,16,12,176,239,80,33,146,68,227,119,169,227,30,212,210,21,205,5,17,140,237,32,227,223,56,165,148,174,126,115,187,60,140,212,16,171,33,82,120,29,133,88,96,178,1,201,27,123,14,244,152,209,10,48,108,160,224,246,4,117,160,196,224,252,197,131,145,192,244,171,80,133,64,174,195,146,112,185,237,79,125,172,219,176,114,163,175,99,75,96,43,108,49,69,212,151,236,79,122,121,7,141,196,99,212,211,100,124,229,136,35,7,211,181,50,82,37,78,51,148,228,0,105,117,25,34,145,147,133,193,207,122,114,149,14,119,30,77,85,
130,103,35,230,224,119,31,225,79,17,49,152,179,19,207,108,213,232,73,43,140,183,56,199,127,106,129,164,66,60,165,12,206,120,4,28,31,206,172,96,145,129,193,61,199,106,118,216,0,1,200,207,169,60,230,150,195,33,134,47,179,218,145,32,125,249,36,147,201,52,221,205,233,250,83,126,215,33,156,198,163,114,31,186,212,239,222,123,126,102,128,34,201,55,38,69,103,85,11,141,167,165,88,4,147,146,50,61,248,168,91,4,99,144,61,169,35,223,35,114,221,23,52,247,17,105,182,225,121,232,65,230,155,118,231,229,85,238,51,154,175,209,178,205,187,142,121,232,105,87,18,108,4,244,224,115,218,147,67,184,187,7,150,202,114,115,201,205,73,176,148,69,7,118,6,48,105,88,136,208,237,0,159,122,140,177,63,92,122,208,33,37,204,114,5,227,110,59,118,52,226,88,143,148,149,35,169,20,210,138,132,191,39,183,29,115,79,201,29,70,20,247,166,193,14,138,64,169,150,113,187,190,122,211,93,134,226,232,65,39,130,13,53,21,28,110,147,238,169,235,220,209,63,206,184,143,0,119,200,237,82,80,168,227,39,107,100,30,249,168,100,44,103,0,158,
49,144,41,200,165,0,12,163,29,207,76,210,186,131,56,207,43,140,117,170,68,145,121,50,28,176,102,30,156,212,241,79,42,143,45,193,117,35,174,112,71,227,82,171,48,4,28,31,74,102,220,146,121,3,52,0,141,33,121,57,251,163,248,79,122,45,211,112,100,80,0,13,156,103,218,141,131,60,10,122,225,115,129,130,105,33,141,120,16,19,140,101,123,14,6,77,57,75,4,11,44,76,0,232,71,52,197,200,221,183,130,78,115,72,38,149,9,223,55,63,238,230,157,132,78,178,70,170,62,240,244,200,168,76,208,25,25,119,110,147,29,0,230,158,36,157,162,33,182,31,112,123,83,17,68,67,126,208,25,186,241,72,100,138,93,198,8,80,0,192,36,243,77,86,222,74,252,200,71,113,73,203,157,192,131,237,79,84,245,110,79,175,52,172,0,112,217,32,182,245,25,27,143,165,54,102,13,114,132,131,183,177,164,114,23,174,113,237,82,198,155,226,59,169,136,120,101,101,56,200,25,170,172,118,162,198,119,100,255,0,158,181,56,249,91,229,7,11,216,211,217,4,167,43,199,114,113,210,129,140,136,50,176,201,224,122,211,165,96,200,72,7,241,166,177,3,229,198,121,224,
212,201,24,198,24,100,84,177,162,150,1,117,206,220,253,121,167,146,197,213,115,255,0,235,167,205,12,86,192,60,73,130,236,20,129,222,154,202,122,182,225,154,164,38,63,205,40,219,159,239,30,230,157,44,203,42,156,0,15,67,81,51,7,114,7,106,104,93,207,193,193,31,173,49,16,179,4,108,48,37,207,64,123,212,168,93,72,202,228,31,210,149,163,124,177,80,27,61,115,80,177,144,58,110,56,57,61,59,14,212,1,112,204,16,0,249,24,233,145,199,214,137,27,204,92,3,180,10,128,51,121,133,114,100,192,235,216,26,112,97,184,43,18,79,231,82,198,68,178,16,252,168,61,142,59,84,168,195,39,145,207,65,75,42,132,137,156,244,235,210,160,141,193,81,242,252,231,182,122,81,96,29,16,99,181,216,96,41,36,123,212,195,120,3,127,39,215,21,93,230,43,34,142,119,99,144,7,122,177,19,55,27,183,99,189,48,35,150,231,203,251,171,187,215,156,85,121,110,67,41,9,24,235,243,26,125,210,225,129,69,227,181,68,170,11,18,253,249,199,169,167,160,133,130,80,207,181,215,232,69,79,182,31,249,230,223,149,11,16,217,191,33,113,248,82,249,171,234,
148,0,248,145,28,115,156,30,51,76,194,0,219,14,8,224,15,90,177,27,130,219,89,8,219,211,35,173,53,99,195,3,144,115,156,82,67,33,49,151,32,242,5,11,16,221,181,129,45,216,131,83,72,25,14,88,16,167,166,42,50,153,112,201,156,230,157,196,35,71,177,203,1,239,78,27,122,150,227,174,5,53,153,178,6,72,20,232,227,105,23,12,227,4,224,102,128,24,132,73,33,0,237,227,57,3,154,138,103,110,50,73,222,50,62,149,98,101,48,175,152,238,49,236,122,212,42,241,207,32,201,96,87,166,79,90,67,35,89,2,196,193,250,40,167,195,55,152,170,10,242,105,210,206,85,209,54,175,76,144,221,69,6,53,103,95,152,14,114,15,76,80,129,150,101,98,33,57,29,184,166,0,68,107,184,117,21,43,91,75,32,194,200,48,48,65,61,233,179,36,145,160,47,130,163,210,157,132,32,4,140,226,164,249,72,53,26,31,151,218,151,35,61,40,1,93,64,206,42,32,178,249,132,229,89,125,59,211,164,4,163,109,235,72,92,66,160,187,133,36,116,205,0,33,32,100,158,8,235,237,80,200,68,152,35,56,254,117,63,57,200,249,143,82,122,83,55,102,67,181,8,110,248,165,113,139,0,85,
227,34,156,229,119,236,99,212,113,233,81,249,106,141,242,191,12,121,20,146,70,167,14,24,141,163,39,240,165,96,44,131,16,37,66,170,224,103,129,214,159,24,220,153,3,57,233,85,19,118,245,56,44,175,198,127,198,172,171,108,194,115,199,0,83,16,58,174,214,24,200,2,171,194,228,199,184,100,213,169,49,177,129,24,39,142,106,18,66,34,170,0,73,61,186,80,49,4,146,28,99,140,117,24,228,211,146,99,17,42,84,130,78,122,209,53,196,16,171,51,96,49,227,56,253,41,133,160,151,107,225,125,65,160,64,24,151,99,248,140,243,75,37,196,163,24,63,149,28,17,72,23,0,228,231,218,129,136,24,76,193,39,118,11,156,240,121,252,234,219,183,31,39,204,61,8,205,103,0,179,202,9,95,154,54,56,31,135,95,214,172,238,32,128,71,29,40,96,0,30,156,12,123,211,81,150,55,204,128,5,61,233,92,178,182,51,214,160,186,125,176,252,249,250,45,8,11,164,43,127,171,96,192,251,224,213,121,80,2,187,137,60,244,199,52,137,40,56,200,198,64,63,74,145,131,200,161,129,27,191,132,246,160,9,54,241,180,41,28,113,80,60,47,181,153,72,39,29,125,234,196,106,
64,39,118,125,205,69,12,77,229,156,72,199,4,147,145,66,6,82,17,149,153,67,6,99,215,158,149,48,138,47,190,196,143,108,83,225,64,205,35,200,9,231,10,61,5,77,44,40,97,207,35,30,253,104,2,178,180,59,183,70,88,156,99,37,112,42,202,200,159,42,228,177,39,141,162,152,162,6,76,20,98,65,192,63,253,106,106,97,114,171,128,58,208,3,103,249,203,113,194,246,39,173,85,97,35,31,220,199,128,189,73,60,159,165,89,145,179,34,236,42,72,57,53,105,112,96,86,32,103,28,224,115,77,49,20,98,85,145,137,12,80,142,161,191,165,59,98,250,143,206,172,121,7,37,178,57,246,163,96,255,0,102,139,128,230,152,68,152,126,121,231,34,145,221,120,219,199,166,42,54,249,135,31,56,29,121,166,9,240,229,74,224,244,4,84,140,146,121,26,120,252,165,37,121,4,158,157,41,228,121,113,140,51,28,241,76,17,121,140,20,185,194,242,112,112,106,199,151,30,1,29,125,105,129,71,44,28,239,228,118,246,171,49,237,192,59,184,162,125,177,169,33,75,54,223,206,162,101,101,137,93,147,147,130,87,63,118,128,37,36,18,64,4,226,163,242,67,75,187,112,200,
224,125,41,222,126,8,24,95,152,117,31,214,162,125,163,14,129,157,189,67,109,205,8,5,144,121,56,218,83,230,61,169,226,217,102,5,165,109,173,220,10,77,136,160,54,119,110,238,122,212,145,193,31,147,151,218,231,215,184,167,97,15,46,109,109,201,140,52,187,59,49,234,62,180,217,47,4,150,228,132,42,122,157,220,254,84,159,35,239,77,205,133,56,60,226,149,160,143,134,243,153,72,232,56,197,12,10,232,161,201,144,117,97,128,125,170,100,140,175,32,147,237,67,229,50,0,228,117,52,200,131,238,5,137,3,60,123,208,4,202,164,246,57,244,166,179,150,83,28,241,166,1,233,158,126,180,226,74,158,181,20,210,23,125,184,227,0,3,158,126,148,0,177,236,16,140,13,252,246,244,166,4,56,101,64,202,122,175,106,149,85,219,0,58,143,69,199,74,137,230,242,164,218,87,56,234,115,73,140,149,86,61,185,43,151,29,218,145,213,212,6,92,96,244,164,44,187,3,22,31,55,60,241,79,105,70,205,138,195,118,56,197,0,49,25,203,50,72,152,200,206,87,222,166,46,21,56,235,239,81,44,171,18,23,145,128,66,70,13,61,216,48,198,63,58,0,83,26,200,48,
199,167,56,239,76,59,98,229,6,63,173,48,50,173,192,1,88,150,24,206,122,83,241,19,146,142,192,30,192,241,154,76,4,153,226,153,2,58,110,92,231,230,28,10,104,72,74,149,85,10,125,69,1,81,135,221,56,7,24,198,105,146,68,50,54,146,3,16,54,246,166,3,154,222,72,220,109,155,62,205,205,33,119,92,141,187,137,239,79,72,246,19,158,113,220,210,130,204,229,84,47,3,60,26,0,122,90,42,13,232,199,113,235,158,244,139,193,32,156,226,166,86,202,158,112,123,243,210,170,188,205,20,129,66,6,7,161,20,183,24,146,41,221,242,144,77,70,174,146,63,151,142,64,207,214,158,196,21,249,114,67,122,142,244,171,101,129,185,100,10,122,230,152,130,44,160,198,220,158,190,180,232,223,157,161,135,30,180,173,25,69,228,134,99,192,34,152,224,196,3,114,79,64,5,36,134,90,86,92,109,96,57,253,106,88,162,68,4,167,70,231,147,84,161,184,108,144,233,143,238,156,210,151,114,65,121,113,237,138,100,142,149,83,14,139,133,35,160,239,77,134,66,70,201,28,15,173,68,208,194,238,28,150,206,122,150,233,83,249,106,87,29,61,49,73,187,21,184,199,
104,96,83,180,51,147,223,214,171,28,201,135,28,2,121,83,129,79,117,5,190,110,2,247,61,51,82,36,56,81,158,157,169,183,160,145,16,70,194,187,58,253,0,226,164,50,178,176,25,192,244,29,42,64,0,24,237,233,81,188,18,74,231,143,148,247,52,147,6,135,9,24,130,195,149,61,112,105,223,55,247,27,254,250,166,152,146,53,249,122,98,147,112,254,241,167,184,17,201,34,199,200,207,212,138,149,91,25,37,122,247,167,58,171,40,56,234,42,49,20,252,24,192,9,211,29,232,220,54,22,18,24,176,56,7,61,125,106,80,206,78,192,164,143,239,122,83,124,165,222,187,243,199,56,169,100,149,88,224,113,183,165,0,69,112,238,0,25,239,197,64,103,145,134,211,201,252,170,121,225,37,65,99,147,199,231,81,32,34,83,187,145,138,0,96,1,87,60,182,58,17,64,42,172,75,113,129,210,165,49,177,194,162,140,31,90,140,137,14,241,54,14,56,3,24,166,34,34,231,121,0,140,118,165,40,27,230,39,230,250,211,29,23,126,213,82,131,28,17,86,33,182,62,73,12,228,72,122,49,28,80,0,140,134,50,7,222,29,65,233,83,64,143,44,103,206,97,215,141,190,149,86,223,113,
10,140,152,124,144,217,239,86,163,125,171,183,128,23,128,171,64,15,6,37,118,198,226,71,229,77,105,212,169,234,15,111,122,158,221,85,183,54,62,108,243,76,149,98,19,70,167,170,245,161,129,82,33,38,8,59,79,185,60,129,81,9,7,218,2,225,134,115,206,120,255,0,60,213,198,80,31,110,225,234,6,106,9,85,24,121,123,193,108,118,29,41,45,70,52,185,11,243,110,28,240,84,254,181,32,102,44,132,71,149,199,56,20,177,191,148,138,135,3,35,3,222,164,47,181,134,113,200,251,185,160,8,255,0,214,72,78,192,202,7,92,116,166,137,18,69,89,34,80,91,56,57,28,129,82,130,135,128,219,123,237,233,79,49,153,84,48,27,79,169,160,6,70,173,179,27,11,96,245,60,210,34,186,228,252,196,18,73,207,106,69,118,137,164,201,109,167,158,41,18,79,52,150,83,199,114,123,208,3,140,75,25,125,164,236,97,247,91,177,168,76,43,44,138,210,255,0,15,27,72,25,171,27,85,185,32,230,144,196,10,224,156,1,223,189,23,0,64,33,35,97,108,127,180,122,83,153,137,5,149,55,123,10,138,84,35,230,102,45,245,169,32,12,35,228,243,249,210,96,130,53,80,164,179,
30,123,122,82,129,18,177,101,95,155,212,138,116,252,196,192,117,97,138,106,66,99,132,17,147,129,201,61,104,90,234,1,44,130,62,113,147,142,64,168,242,210,0,66,145,244,230,171,221,70,46,36,70,13,149,140,228,168,171,150,204,60,161,131,145,138,111,64,33,96,85,120,92,145,235,197,11,116,124,163,231,34,142,195,230,171,45,134,207,3,53,86,225,9,3,104,59,179,199,52,45,64,99,75,34,108,145,143,238,199,76,114,8,250,212,239,43,56,10,23,112,168,109,225,154,221,112,10,20,234,87,57,171,17,195,148,44,6,7,64,13,26,0,214,43,192,56,56,164,76,200,126,78,65,234,105,226,212,31,152,184,201,60,129,200,169,119,24,136,80,56,199,106,46,5,102,133,195,245,249,127,74,122,51,96,110,32,110,252,197,62,89,151,128,115,207,165,85,118,221,198,56,238,7,20,183,30,193,56,220,184,201,60,227,0,102,166,132,200,138,21,163,37,59,17,81,130,171,181,212,231,60,98,166,14,112,51,192,62,244,216,144,225,181,155,7,34,149,92,3,181,142,8,237,73,24,18,2,193,113,142,205,80,6,223,59,110,92,255,0,74,86,1,36,42,242,99,126,70,127,42,147,
247,126,181,87,6,25,73,28,14,199,210,166,223,239,79,96,39,33,119,109,28,100,122,209,9,111,52,160,37,128,245,237,81,60,106,87,113,82,88,84,209,146,23,49,158,220,80,192,91,134,216,203,144,77,49,101,66,195,114,144,71,79,243,222,152,249,15,230,177,37,128,207,38,154,174,206,65,66,84,15,95,90,86,2,82,94,84,201,86,30,153,21,16,95,155,0,100,83,222,119,216,3,31,99,205,40,42,203,215,131,232,105,128,177,46,254,72,42,217,228,119,21,20,209,24,137,249,142,198,35,147,78,86,151,112,0,246,234,69,18,202,164,152,178,204,196,100,159,74,53,1,185,93,216,57,20,34,199,184,179,72,113,216,10,73,35,37,83,14,51,232,104,194,237,60,228,142,122,98,155,17,42,174,7,29,79,82,127,74,20,101,121,3,38,149,36,79,40,187,56,244,201,168,150,73,54,228,40,32,158,51,197,39,126,131,67,148,109,113,201,81,140,29,167,173,41,198,236,128,79,169,52,177,169,102,99,34,140,131,193,3,181,57,185,66,5,43,142,196,91,81,220,187,228,28,118,167,195,28,77,156,32,86,29,251,154,122,71,180,228,154,143,205,199,42,69,49,14,146,37,84,87,200,44,
167,130,123,26,113,138,38,219,35,57,56,224,138,106,129,34,252,199,0,244,164,32,199,133,4,129,211,61,115,64,18,24,3,97,163,32,129,232,105,165,220,157,167,60,123,82,54,98,82,99,25,238,113,214,161,158,105,74,5,140,225,152,117,244,161,0,233,166,42,248,141,1,111,226,25,237,235,74,155,149,121,218,87,61,134,41,45,209,154,48,100,249,219,185,199,83,78,72,100,49,184,32,142,127,10,26,1,200,75,124,203,156,26,89,31,13,180,114,106,84,64,16,14,132,116,246,168,229,64,178,110,35,57,239,73,52,216,88,143,112,147,41,144,8,160,63,146,8,207,62,244,197,85,220,66,225,73,234,106,95,36,48,207,82,190,244,192,141,93,164,144,57,96,0,29,49,79,155,114,219,16,178,97,143,66,105,153,17,28,17,187,222,129,47,153,181,99,32,1,207,52,0,216,148,14,138,119,55,99,198,105,26,55,71,222,84,124,220,242,41,225,219,206,10,92,59,246,3,31,40,167,103,63,235,51,156,240,77,23,1,173,33,85,202,141,199,210,164,222,172,153,126,56,201,237,138,137,228,69,145,145,187,114,56,206,104,12,23,44,65,60,244,244,160,6,170,159,40,204,138,10,145,
129,207,81,235,86,161,118,88,192,100,96,190,181,92,205,208,170,133,169,188,214,117,229,130,231,159,173,38,4,136,185,151,35,229,29,243,81,220,201,251,192,177,144,204,58,226,163,105,65,35,1,130,247,34,172,67,34,170,0,78,61,105,12,173,242,187,225,212,134,236,87,158,41,10,69,19,5,102,38,70,233,197,76,25,12,185,0,227,25,201,239,79,43,28,195,249,30,226,128,33,202,1,140,3,199,167,74,20,134,56,0,103,166,5,40,86,50,178,72,120,236,106,52,65,20,228,153,74,143,246,142,115,239,85,228,34,81,28,144,229,218,69,193,60,40,29,42,23,116,86,57,194,147,223,214,164,81,176,177,220,29,79,32,131,197,53,148,51,111,97,156,30,158,148,92,8,36,142,73,120,254,12,245,169,62,204,61,79,253,244,106,83,38,229,28,28,209,243,122,208,3,27,231,59,15,32,158,158,180,204,5,114,170,0,80,122,47,74,100,204,241,146,17,9,36,100,54,41,182,179,177,86,15,247,179,233,66,2,227,48,98,160,142,41,146,178,143,152,12,14,189,41,6,209,146,79,235,83,121,100,158,79,30,253,105,117,25,94,41,55,146,74,145,254,240,235,74,25,85,198,121,94,224,
10,177,229,249,81,231,59,136,254,247,165,68,25,12,172,131,27,184,227,218,152,134,139,132,154,50,158,102,209,211,36,84,81,91,152,228,223,27,238,39,129,220,84,205,16,112,126,66,15,173,58,36,8,2,227,167,90,119,16,198,86,99,201,193,7,181,33,28,130,135,156,126,116,231,117,145,72,139,10,67,99,56,235,78,141,130,0,88,100,227,28,122,210,220,4,137,64,25,206,88,30,61,170,101,147,118,84,213,84,202,202,223,41,218,220,146,58,102,159,247,23,129,159,111,74,151,123,148,135,25,2,185,200,200,237,239,83,101,120,219,210,170,14,164,16,196,55,33,135,106,176,167,0,22,235,78,194,184,247,98,171,198,9,61,141,86,91,69,71,46,164,134,99,157,185,224,85,130,114,56,166,56,36,229,143,215,20,92,44,32,32,131,130,15,181,10,8,110,164,253,105,24,130,51,130,24,126,181,17,103,7,120,110,27,129,237,77,1,100,198,73,39,56,226,160,219,243,18,228,143,76,82,196,219,151,150,102,36,244,38,156,145,102,82,88,1,145,215,61,105,92,44,58,218,45,146,22,36,21,235,244,169,158,66,37,219,180,128,58,55,106,142,72,134,194,80,237,108,113,
233,80,171,57,5,24,134,126,248,28,83,189,192,182,217,3,56,252,170,188,178,70,65,138,67,141,220,12,142,181,36,110,219,188,183,93,184,28,100,245,165,145,81,228,140,117,101,57,233,82,150,163,232,85,137,149,227,222,188,169,252,49,79,94,6,115,248,82,202,145,249,142,177,130,15,241,14,199,222,147,37,73,42,73,62,152,199,53,86,17,27,54,95,126,210,113,193,3,181,16,91,71,230,22,0,224,246,52,161,95,123,16,228,110,198,84,142,42,93,133,113,180,231,62,180,0,60,98,8,215,202,25,97,192,30,130,163,150,82,34,44,20,51,103,238,250,210,203,30,247,201,99,211,29,106,8,100,219,48,200,59,71,175,95,173,0,78,184,7,10,131,142,140,86,147,24,99,187,44,61,42,70,153,119,227,183,168,160,12,142,159,46,125,57,162,224,15,20,55,17,54,214,104,200,29,143,56,166,180,200,51,147,208,100,156,82,249,127,48,63,46,59,130,121,53,35,157,241,249,126,88,96,120,198,41,136,169,182,225,238,75,70,85,33,42,50,172,51,147,253,42,82,6,0,231,53,50,129,229,249,57,229,123,147,205,67,44,82,149,43,11,133,57,28,145,154,6,8,204,232,6,211,199,
31,141,77,23,43,247,113,233,205,68,16,194,48,172,199,212,19,79,12,112,163,28,129,131,73,130,28,64,234,105,133,115,147,140,210,239,24,231,169,164,50,42,144,61,105,136,80,12,96,175,24,62,149,89,203,199,41,36,240,122,84,230,64,84,212,82,70,236,78,236,159,76,80,2,25,81,101,3,121,109,253,8,21,46,87,212,84,16,0,204,203,129,242,146,1,3,160,226,167,216,63,231,165,72,201,84,163,12,108,198,58,28,84,13,24,140,179,32,4,147,222,149,183,42,231,56,29,64,166,129,33,114,49,129,239,76,2,88,129,28,17,200,226,167,142,84,206,72,193,52,213,4,103,32,26,134,115,182,62,62,247,96,105,1,100,54,244,245,244,163,144,71,1,129,170,240,185,84,7,61,57,57,237,86,21,146,65,149,57,20,222,128,70,55,172,108,203,150,94,78,15,92,122,81,20,198,70,203,169,78,58,28,80,206,195,229,13,145,158,190,212,193,30,231,44,78,59,115,222,128,24,232,166,96,2,175,35,33,65,198,106,72,80,180,121,1,134,14,48,105,55,178,21,7,5,123,28,114,42,93,219,0,27,185,60,226,152,134,148,109,188,156,103,183,173,8,93,88,46,222,162,151,120,5,157,186,14,
114,106,93,202,84,21,56,6,147,25,95,108,144,199,129,32,96,59,48,168,139,185,4,201,200,235,145,218,174,51,70,195,25,201,199,66,41,140,170,241,237,35,131,210,128,43,67,43,9,129,13,185,58,31,173,79,60,189,66,130,13,55,27,79,56,4,116,56,168,201,203,7,98,122,228,140,81,96,26,173,32,35,124,128,103,218,152,242,180,139,176,158,42,91,144,207,27,48,12,91,57,233,208,119,166,45,184,192,103,125,190,185,255,0,26,76,98,66,198,53,86,7,167,90,180,178,169,228,145,249,212,56,31,117,16,15,67,159,189,73,36,166,32,177,149,27,143,83,64,137,195,100,135,32,145,142,70,123,212,144,202,155,248,56,39,146,15,21,86,57,6,242,25,135,176,29,169,206,160,160,224,22,207,28,83,17,118,105,17,87,115,227,211,7,189,81,130,225,60,233,2,140,56,61,7,74,145,64,194,169,231,29,205,68,145,167,156,204,27,4,243,205,27,12,123,239,7,114,96,250,228,208,146,200,87,105,140,19,234,79,24,169,2,146,184,239,64,24,29,56,161,0,214,36,176,198,238,58,129,82,179,169,33,123,251,210,32,18,2,193,113,142,205,80,171,230,118,220,63,250,212,1,36,
128,15,199,167,189,49,213,183,32,24,198,121,221,222,165,89,21,142,220,100,129,159,194,135,43,129,156,113,215,52,128,71,116,46,184,94,51,130,113,210,159,128,9,95,65,81,18,85,118,49,194,47,82,41,162,76,129,142,253,137,239,233,66,2,66,1,201,228,159,231,82,44,201,111,22,227,195,55,97,233,72,187,72,249,135,35,218,137,98,45,180,100,1,234,71,20,92,1,152,92,96,169,216,221,71,189,86,11,44,121,83,39,126,123,154,146,35,251,208,23,156,131,143,108,82,0,219,79,152,6,115,206,41,136,122,64,35,25,12,207,184,231,154,115,12,30,122,250,84,43,59,6,0,238,10,167,24,29,42,66,93,159,39,29,125,105,49,138,202,190,75,30,51,211,138,173,176,134,4,244,29,234,193,125,199,133,3,181,52,33,10,66,147,184,127,123,173,52,194,194,8,88,191,65,199,175,106,25,100,97,242,182,1,235,237,74,210,48,59,66,49,207,113,65,116,64,55,241,159,108,211,17,97,162,143,202,3,104,4,12,113,80,121,99,253,154,83,112,196,99,202,59,79,70,245,166,121,163,251,173,249,26,86,24,169,229,200,128,73,201,245,164,125,177,48,59,190,94,152,52,200,151,
123,12,28,53,88,146,5,49,140,227,35,169,28,82,186,1,84,171,28,41,168,167,65,144,206,56,232,41,169,25,18,16,27,42,7,92,244,164,121,68,195,98,190,236,117,255,0,245,208,2,56,5,78,88,31,80,104,86,204,101,208,18,58,100,119,167,8,67,1,183,129,158,121,205,24,116,112,176,201,148,108,150,221,206,41,128,170,129,81,139,18,73,60,127,133,53,88,62,84,140,17,212,26,146,61,204,92,49,24,207,21,12,204,85,193,3,129,220,83,16,178,142,128,100,96,231,34,151,230,219,242,119,29,122,212,72,235,33,206,241,142,231,210,165,128,177,222,99,59,148,17,212,226,150,163,34,64,209,192,22,71,59,152,156,6,171,9,55,150,163,237,12,160,129,146,77,54,71,12,174,29,85,131,113,138,138,70,243,83,107,198,27,253,225,145,69,128,152,111,71,105,21,212,163,28,129,142,149,42,180,108,153,137,193,62,157,42,184,220,177,144,70,220,113,140,116,166,90,202,26,53,80,8,228,227,119,83,64,22,89,2,156,185,56,235,131,205,71,24,97,206,1,220,50,188,116,166,79,114,35,80,11,140,116,218,5,78,103,138,121,2,39,204,202,50,74,244,20,108,5,19,230,164,
139,243,110,57,252,7,225,82,72,141,48,43,129,140,228,228,19,255,0,234,171,13,30,233,55,17,219,173,40,149,148,21,126,158,180,196,84,4,163,97,65,61,184,234,41,210,192,146,128,100,36,118,231,174,106,97,134,39,24,60,228,83,120,121,176,65,235,192,20,152,200,96,180,137,91,107,184,220,121,7,174,5,91,120,216,29,170,199,24,234,69,41,72,192,44,87,154,141,94,70,28,56,30,184,25,205,23,11,15,41,176,1,247,184,234,123,211,20,109,149,71,56,231,140,84,167,44,55,16,65,61,105,99,7,147,158,163,31,74,0,97,108,19,142,79,165,63,5,187,115,76,69,138,71,18,131,147,247,71,29,234,50,30,57,246,140,122,231,61,5,22,2,81,28,145,101,218,69,32,158,20,14,149,11,178,2,115,133,39,245,169,99,138,79,155,230,3,63,165,43,66,185,92,252,196,126,180,196,68,57,193,41,193,238,106,77,165,155,97,4,143,81,77,101,3,32,113,71,156,207,149,0,35,103,134,20,0,58,18,57,32,1,248,230,153,230,73,149,11,26,252,188,100,211,183,237,83,213,177,197,71,34,207,32,38,60,15,161,230,147,184,208,209,112,35,188,16,185,193,43,184,122,125,42,207,156,
89,64,81,149,63,231,53,11,164,101,7,159,8,50,1,140,241,78,142,57,2,224,13,169,216,103,165,0,75,111,34,40,35,56,108,238,165,46,138,48,25,112,123,103,154,65,47,150,165,92,255,0,245,253,170,162,48,223,202,178,131,208,211,17,57,120,144,18,195,44,78,66,250,83,146,65,150,201,32,118,221,80,44,10,70,252,29,199,160,63,206,165,89,10,201,254,175,114,176,249,179,205,22,11,138,183,48,59,237,142,79,155,160,0,113,77,115,49,222,168,204,27,177,97,198,105,211,74,2,13,202,20,41,4,16,57,165,89,85,128,46,164,174,114,14,57,31,157,22,1,54,201,38,222,2,149,251,192,142,79,208,211,68,69,6,99,63,55,251,92,84,177,69,25,152,110,148,182,122,101,186,211,230,33,148,128,165,8,60,103,140,208,4,102,228,36,91,64,249,189,61,42,174,100,255,0,158,134,159,34,74,29,78,83,158,217,60,212,153,111,246,104,2,8,78,192,48,122,112,121,171,45,114,157,6,70,227,212,241,85,163,218,151,46,8,36,1,216,119,171,68,162,219,159,57,193,96,63,42,155,20,58,23,8,74,103,147,207,53,20,168,155,203,132,3,60,28,119,167,178,23,100,96,216,192,239,
74,202,79,86,200,28,211,212,67,82,60,149,96,8,32,144,126,152,164,134,39,218,119,0,57,227,20,165,131,43,34,157,198,164,134,66,173,177,215,110,58,100,245,160,8,222,57,20,1,212,19,146,71,90,133,237,229,86,93,164,16,120,220,127,135,53,162,121,92,173,71,215,25,7,6,132,192,169,228,44,114,13,192,2,57,192,254,116,143,60,81,57,45,242,238,227,235,86,165,68,116,249,143,204,189,42,23,141,54,5,98,49,156,18,122,138,104,64,143,27,199,157,161,134,122,154,112,249,228,69,0,0,15,240,211,98,128,43,100,231,96,60,15,90,145,64,92,177,42,0,245,237,72,99,220,12,29,194,171,21,10,249,81,205,78,164,16,25,78,243,253,226,114,5,65,116,242,71,25,112,155,185,236,105,0,210,177,58,48,149,50,196,231,244,164,129,85,73,0,99,216,84,105,26,238,223,32,4,212,145,49,44,70,64,199,66,125,42,132,90,243,85,147,29,7,210,152,10,231,4,128,125,15,122,105,42,114,169,72,195,106,28,128,196,119,239,64,17,21,88,156,48,63,123,142,91,185,169,163,81,201,224,115,85,216,43,186,16,85,128,63,197,158,13,93,34,43,136,48,65,13,199,205,211,154,
0,105,37,156,46,65,3,245,167,145,136,201,3,4,244,168,130,172,100,48,206,79,92,246,167,146,60,188,131,210,165,140,137,139,142,14,238,123,212,190,112,84,193,27,152,241,138,143,57,60,158,125,41,194,60,169,98,1,35,158,123,85,8,140,43,171,130,64,217,183,63,67,82,17,223,191,173,10,174,91,45,208,251,209,38,236,16,140,1,247,20,144,201,21,249,197,53,164,140,252,221,79,56,199,106,175,35,72,139,140,166,238,6,123,243,76,143,121,108,49,25,247,166,34,193,66,83,43,233,206,77,34,253,221,160,228,122,10,39,117,142,17,156,14,48,48,106,85,100,86,192,63,149,13,216,17,27,43,109,249,137,11,76,243,10,182,35,232,78,15,173,58,96,72,219,187,169,233,81,36,78,199,41,147,234,79,74,74,236,101,178,21,152,49,193,97,212,26,73,114,112,1,198,42,47,41,183,41,45,207,110,42,70,154,62,84,129,191,189,2,43,203,31,239,23,150,108,142,153,239,79,142,33,180,137,27,175,67,65,88,118,225,242,129,207,4,100,102,145,164,8,73,98,54,175,175,122,67,21,151,104,3,119,204,63,35,64,10,220,133,97,184,212,65,150,96,210,43,14,189,5,58,59,
130,120,60,26,96,90,216,10,116,199,243,168,207,33,163,206,14,59,213,137,24,8,193,218,121,233,85,83,239,19,131,146,123,250,82,87,1,143,19,0,188,231,190,224,49,79,201,198,88,22,35,214,172,22,227,165,53,215,215,156,213,8,175,60,67,122,149,27,72,4,109,94,149,87,236,255,0,237,85,221,173,187,160,198,59,82,108,111,74,78,227,30,138,35,145,157,23,12,120,39,29,105,120,98,115,205,73,128,7,92,212,81,17,186,85,32,13,167,60,122,26,98,28,83,130,122,250,211,130,141,167,61,127,157,39,36,30,153,164,98,113,158,185,160,7,110,11,247,70,7,124,83,103,87,153,80,68,0,96,126,108,244,2,144,182,0,35,7,52,215,144,194,60,237,219,115,133,38,128,18,88,101,93,164,145,128,57,193,34,128,37,82,219,152,168,24,57,28,254,21,35,72,172,129,153,195,84,123,203,140,178,252,160,240,41,12,103,152,207,47,64,0,245,169,14,90,77,164,99,60,131,81,201,128,187,246,143,67,72,147,175,153,229,150,192,3,130,105,161,22,154,25,62,232,10,61,13,85,85,49,69,206,74,169,207,57,53,105,165,13,18,160,228,122,154,100,242,237,133,74,13,217,60,
159,74,67,35,108,172,25,83,140,140,170,227,128,125,42,54,102,56,141,250,238,192,20,224,234,224,109,110,70,48,61,106,187,35,188,234,193,138,178,54,236,227,138,73,1,112,67,187,10,202,6,56,224,117,168,230,143,203,101,24,193,60,10,158,59,130,209,178,58,242,71,81,80,77,194,12,147,147,192,252,105,129,16,102,36,96,113,221,169,99,220,174,87,113,39,174,13,77,110,176,160,195,28,26,107,71,155,130,84,62,49,142,27,138,119,16,232,237,195,242,70,9,25,235,210,148,43,70,231,4,227,28,3,78,249,198,67,156,231,24,7,210,147,36,169,221,146,59,12,210,184,199,121,98,81,156,237,20,201,23,201,25,82,118,103,156,213,130,200,177,224,16,8,28,84,100,146,23,107,2,163,177,92,147,64,21,102,34,72,207,150,221,61,233,44,101,32,21,108,237,206,114,105,28,157,229,0,1,115,201,169,124,160,20,18,204,71,185,206,41,216,46,75,56,232,209,184,221,144,49,154,108,101,153,176,216,6,160,108,25,6,210,185,29,50,105,124,214,105,114,9,28,246,60,81,97,11,58,152,238,23,123,35,110,228,103,250,82,24,136,203,3,203,30,158,148,240,18,73,149,
165,43,184,14,1,52,219,183,113,179,202,0,70,140,25,187,102,149,198,48,196,251,136,198,73,232,8,226,167,140,152,192,89,35,92,119,34,165,224,144,195,154,108,163,60,118,239,83,113,216,142,85,47,243,196,219,128,225,129,28,212,207,62,204,34,199,243,99,238,231,20,203,173,191,103,38,25,20,63,240,243,222,163,84,117,133,9,37,159,110,73,61,79,173,81,35,221,164,145,55,0,170,222,155,184,164,15,25,140,163,231,118,63,35,79,103,87,143,10,112,195,167,24,21,11,70,219,150,66,203,215,5,87,156,208,2,205,34,184,207,205,145,216,14,42,188,240,137,84,73,146,88,175,32,26,181,228,130,197,134,91,61,84,158,212,145,172,100,149,195,40,29,1,161,140,169,104,174,167,104,56,200,206,13,89,117,134,47,222,182,29,199,79,173,47,144,1,5,78,57,228,158,184,169,167,9,28,120,9,201,61,187,80,129,145,44,172,81,121,98,189,50,70,42,97,192,192,228,102,152,138,206,140,1,28,12,84,137,14,209,64,0,228,123,83,137,7,131,210,171,249,195,204,100,195,13,189,200,226,165,35,32,144,121,166,33,199,7,62,130,140,55,173,68,3,25,7,60,122,84,
217,247,20,0,211,215,29,169,133,130,103,140,230,154,228,174,58,212,81,59,60,158,91,116,198,104,0,120,100,147,132,147,106,245,220,58,209,115,30,229,76,49,87,79,78,51,82,227,17,18,62,148,141,26,144,25,185,32,102,128,8,137,113,140,17,233,205,16,57,89,24,59,121,138,14,49,142,148,197,143,42,65,60,3,145,142,41,251,124,160,0,228,1,72,98,201,36,70,66,137,144,113,156,142,148,216,164,202,16,195,113,94,192,117,166,55,201,140,119,245,167,8,1,147,112,98,15,181,49,10,71,154,64,76,140,243,237,64,141,35,184,14,83,113,238,72,226,156,80,70,55,130,73,247,52,233,163,71,136,135,25,227,61,105,12,176,100,202,141,128,103,218,170,144,74,186,182,208,58,96,85,120,71,149,149,82,121,239,222,165,95,221,157,189,115,64,16,195,24,86,80,167,169,60,227,165,88,1,8,221,25,24,21,28,106,169,25,33,70,125,106,68,85,144,41,81,183,39,6,134,8,105,42,160,124,196,177,206,57,233,72,9,145,151,122,147,254,208,237,138,146,84,196,101,65,227,57,233,81,132,219,192,61,40,64,35,101,65,39,36,15,65,78,70,148,142,112,87,60,26,141,36,
99,233,143,74,147,207,114,193,120,0,240,104,176,92,116,83,44,178,237,102,60,14,8,232,106,82,169,143,149,215,39,156,102,161,216,2,228,15,187,210,162,206,27,235,78,194,37,146,77,164,100,245,226,150,50,48,62,115,235,245,161,162,243,64,201,198,71,97,81,199,24,71,41,215,222,144,199,185,80,14,49,147,218,153,12,170,199,99,17,145,200,237,82,136,130,16,217,38,154,204,36,144,41,24,247,20,0,230,33,209,176,160,142,156,211,99,64,70,210,0,197,57,112,153,192,227,29,40,198,98,47,211,184,2,128,4,217,28,197,248,193,227,142,213,53,195,164,144,157,163,32,117,21,72,109,102,42,202,56,165,96,70,88,28,115,140,83,16,235,119,192,0,156,130,113,154,176,78,122,145,182,179,228,194,198,14,51,185,185,21,100,28,199,143,235,82,215,81,220,147,112,66,48,170,20,242,113,81,200,141,36,65,35,108,109,60,115,206,40,67,146,22,157,184,197,200,193,170,16,232,224,17,160,7,45,245,230,154,241,146,167,103,201,238,5,59,205,96,152,31,175,52,213,144,147,180,143,122,0,104,5,19,118,246,220,57,201,239,74,92,202,3,1,159,113,86,21,
0,3,60,210,5,92,224,40,3,210,149,199,98,15,49,80,254,244,144,167,140,212,210,72,12,103,110,25,192,227,142,106,165,209,198,56,254,42,177,16,9,242,129,239,76,67,163,147,203,95,153,72,167,25,149,182,142,133,186,3,222,157,183,112,62,220,85,73,99,32,168,14,113,156,114,41,1,59,219,153,15,3,31,214,170,238,96,74,97,148,167,7,165,92,142,70,220,80,146,113,206,106,172,204,86,121,59,243,222,139,92,119,37,139,44,161,139,122,241,79,220,191,222,253,106,180,110,88,129,192,227,60,84,248,247,52,90,192,127,255,217);

back_swell:array[0..4891] of byte=(
255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,255,219,0,67,0,20,14,15,18,15,13,20,18,16,18,23,21,20,24,30,50,33,30,28,28,30,61,44,46,36,50,73,64,76,75,71,64,70,69,80,90,115,98,80,85,109,86,69,70,100,136,101,109,119,123,129,130,129,78,96,141,151,140,125,150,115,126,129,124,255,219,0,67,1,21,23,23,30,26,30,59,33,33,59,124,83,70,83,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,255,192,0,17,8,0,200,0,200,3,1,34,0,2,17,1,3,17,1,255,196,0,31,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,
122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250,255,196,0,31,1,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,17,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119,0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,247,248,249,
250,255,218,0,12,3,1,0,2,17,3,17,0,63,0,202,154,64,234,35,65,178,36,232,5,102,206,249,111,97,210,172,93,74,7,200,191,141,81,117,45,64,12,102,207,176,166,138,147,203,3,171,80,8,31,116,100,208,3,66,129,203,126,21,52,80,52,167,39,167,165,62,11,114,205,150,230,180,82,48,131,3,173,0,102,201,9,133,213,135,74,177,23,250,249,36,35,59,6,7,214,157,124,62,67,235,76,182,204,137,50,142,167,4,126,84,1,93,164,146,73,88,169,193,39,181,72,177,75,17,202,160,111,124,212,42,161,156,171,112,192,212,251,229,132,117,222,148,0,198,4,29,210,224,158,194,171,202,236,237,205,93,93,147,12,131,74,45,71,122,0,207,84,102,60,10,181,13,161,60,181,91,17,199,16,201,197,67,45,215,100,252,232,2,70,104,224,94,49,154,172,168,102,115,36,135,8,41,99,136,184,243,37,36,40,237,235,86,35,79,52,238,111,150,52,237,235,64,4,81,239,218,204,49,24,251,171,235,90,214,145,133,67,35,112,5,82,182,67,113,48,236,130,147,86,189,242,215,200,136,224,119,52,0,205,67,82,46,76,80,28,14,237,89,44,254,159,157,46,70,49,154,76,46,120,4,208,3,
64,44,106,120,32,105,155,106,142,59,154,150,222,209,165,57,111,149,106,227,17,12,123,99,94,7,235,64,2,36,86,203,198,51,234,106,41,46,114,195,28,138,171,49,145,219,38,163,82,202,104,3,114,59,152,37,131,202,145,14,211,214,138,165,3,171,174,15,90,40,2,129,115,247,155,169,164,8,207,201,226,164,138,63,54,76,246,21,117,97,0,80,5,21,183,39,173,78,145,5,53,59,40,90,133,228,0,208,5,152,176,42,92,224,102,169,71,46,77,90,28,138,0,175,115,243,100,85,88,101,48,201,145,156,142,8,246,171,237,30,234,130,91,77,220,226,128,9,161,91,129,230,194,126,126,226,160,89,136,27,28,114,41,66,75,11,101,79,227,82,137,226,151,137,227,59,189,87,173,0,85,221,229,190,229,232,106,127,181,229,122,211,132,112,55,73,64,246,110,41,124,171,120,249,105,23,232,40,2,190,231,148,241,147,83,164,9,8,15,49,201,61,23,214,159,230,128,191,232,232,127,223,110,130,155,26,180,206,118,146,79,241,57,254,148,0,229,86,184,147,7,0,14,184,254,31,97,239,82,183,239,25,97,136,124,163,142,41,237,182,36,17,198,42,213,172,34,8,252,198,31,59,
125,218,0,148,168,179,180,32,125,226,49,154,198,104,26,119,39,174,107,86,98,28,0,79,2,160,103,10,48,188,10,0,170,154,120,31,120,226,166,75,120,163,231,239,17,237,75,187,39,173,54,121,197,184,3,25,115,219,210,128,38,61,57,33,69,52,66,178,240,178,12,214,91,201,36,173,150,99,244,20,229,47,9,14,9,35,191,181,0,88,186,178,146,49,158,107,60,179,43,96,215,73,3,139,155,86,13,201,3,138,192,187,76,92,16,61,104,0,87,32,110,20,83,55,140,227,181,20,1,163,105,14,212,21,97,184,20,170,54,168,21,13,196,155,84,208,5,123,153,118,247,170,120,103,57,167,115,52,132,246,171,41,30,5,0,84,66,81,198,122,86,180,31,50,102,168,79,31,25,29,170,205,140,187,147,233,64,22,148,124,216,171,107,108,28,102,169,51,108,122,210,182,125,203,159,106,0,175,37,151,6,169,75,104,185,32,138,216,243,57,193,168,110,34,200,200,160,12,115,104,195,238,191,224,121,166,121,19,47,69,143,235,138,182,204,80,154,95,56,119,197,0,86,91,87,115,251,214,200,244,29,42,207,203,10,97,64,166,180,252,113,76,140,25,92,14,180,1,98,214,15,49,247,
191,221,28,154,124,178,239,114,71,3,160,21,44,223,185,136,70,189,79,38,170,181,0,35,190,6,77,83,105,154,73,54,173,58,233,240,187,115,76,181,140,158,123,147,138,0,177,188,65,17,145,187,112,61,205,103,157,243,72,73,57,39,173,75,123,54,249,54,39,221,78,7,185,168,194,159,184,159,240,35,64,14,87,138,62,15,38,172,40,73,99,56,238,42,33,110,161,121,166,199,155,121,70,126,227,113,64,26,26,51,16,207,25,60,142,43,62,251,139,183,227,166,106,229,179,8,111,209,187,63,90,175,170,166,203,215,247,20,1,94,56,119,71,154,42,213,160,221,29,20,1,108,184,2,179,174,165,46,219,65,167,75,114,49,128,106,176,4,146,199,169,160,9,227,194,45,73,231,47,173,86,218,237,210,151,236,242,227,56,160,11,91,149,197,69,19,121,19,243,247,90,160,5,227,63,54,106,82,68,201,239,64,26,19,140,160,97,86,116,249,179,242,154,163,103,47,153,25,141,254,240,224,211,225,38,25,253,168,3,74,124,171,230,164,137,131,174,211,72,195,205,136,48,235,138,138,50,85,168,2,27,184,112,107,57,242,13,111,74,130,68,207,231,89,147,65,205,0,83,92,
147,90,118,16,129,243,30,213,90,56,126,106,213,137,49,14,7,122,0,171,32,46,197,143,122,129,198,42,75,171,133,67,181,106,53,145,100,94,163,52,1,82,120,139,183,2,158,0,134,6,115,252,43,199,214,166,42,7,36,128,62,181,86,246,85,242,130,35,3,207,52,1,69,9,220,88,255,0,8,207,227,86,97,194,47,39,147,80,136,200,182,221,140,229,169,233,4,146,140,147,129,218,128,45,6,87,24,205,71,34,100,21,110,134,161,104,100,139,149,108,251,102,165,138,97,32,218,220,48,245,160,4,70,102,140,169,255,0,89,25,200,247,169,245,31,223,219,67,114,188,224,97,170,7,5,24,56,234,191,168,171,54,204,174,30,221,143,238,230,25,79,102,160,10,214,46,1,219,233,69,64,3,91,206,85,184,42,112,104,160,4,142,9,101,63,187,140,159,115,86,69,151,147,134,186,148,39,251,61,77,91,146,239,172,118,106,17,71,5,234,131,143,49,201,27,164,110,231,52,1,55,159,109,31,10,172,222,231,138,112,187,128,156,21,101,30,181,81,161,199,88,255,0,241,234,102,196,245,100,62,252,138,0,209,104,162,157,126,66,27,249,213,23,141,173,219,61,86,144,121,144,16,
202,120,245,29,13,91,142,100,187,93,146,0,31,249,208,4,32,149,97,52,125,186,143,90,186,118,205,26,186,245,197,80,193,183,147,99,125,211,210,167,130,79,34,77,164,254,237,186,123,80,6,181,156,191,46,211,83,60,92,228,85,20,59,24,48,232,107,66,41,84,168,6,128,29,30,71,90,100,177,2,106,96,84,244,160,154,0,170,144,225,179,138,154,115,229,192,72,244,169,14,20,84,51,126,246,38,29,197,0,115,119,51,177,147,2,152,179,200,190,223,141,18,169,89,155,214,153,28,45,33,201,233,64,14,107,137,31,130,228,251,10,124,118,210,73,243,21,32,123,154,102,245,67,182,21,201,254,241,171,113,71,41,25,102,57,52,0,205,236,176,149,145,64,10,120,171,22,231,122,83,69,128,115,243,49,169,226,141,32,27,119,102,128,33,153,13,83,116,59,178,56,35,189,106,176,87,251,166,170,201,15,52,1,20,114,121,163,107,112,227,245,164,92,171,109,7,7,59,144,250,31,74,70,136,131,149,225,135,74,118,124,212,61,156,117,246,52,1,45,236,95,106,132,93,70,191,56,249,101,95,122,40,182,159,203,125,236,62,70,249,101,95,235,69,0,66,127,121,242,40,
196,107,233,222,158,93,97,78,112,61,189,42,24,93,217,68,113,14,64,228,158,213,28,209,149,144,111,36,142,230,128,26,242,151,110,88,129,78,88,209,250,72,115,74,210,170,16,170,128,210,110,221,247,162,4,123,80,2,249,114,66,114,167,35,191,189,55,229,115,242,124,143,233,216,253,41,234,216,56,70,63,238,189,12,171,33,198,54,63,161,160,9,82,69,186,79,42,94,36,232,15,173,53,121,6,25,58,142,134,161,32,147,134,225,135,122,152,31,180,12,30,38,94,255,0,222,160,11,22,179,30,98,127,188,58,123,213,165,144,169,172,146,228,16,253,25,106,252,111,230,198,8,244,160,11,66,225,135,122,154,59,191,239,10,205,114,69,53,101,32,245,160,13,228,113,34,241,80,185,104,164,207,106,163,5,201,83,193,173,20,145,46,19,13,214,128,50,245,27,34,248,158,46,125,170,172,101,94,6,69,225,251,131,91,233,24,69,108,159,151,210,176,231,10,215,174,20,1,133,61,40,1,150,176,42,156,245,106,183,210,171,105,238,2,59,63,240,211,39,189,57,196,107,248,208,5,167,155,203,28,158,106,140,179,177,53,22,246,99,243,26,120,76,208,2,45,195,41,
171,144,221,135,225,255,0,58,168,208,212,69,25,15,20,1,176,99,12,55,41,200,170,211,68,84,249,137,213,122,143,81,80,218,221,20,96,27,165,92,158,65,229,249,139,211,249,80,5,66,235,184,56,251,142,48,194,138,133,193,32,249,99,42,221,135,99,69,0,79,20,191,191,192,3,7,169,3,138,181,61,184,113,200,20,230,116,134,60,170,128,107,62,75,182,44,72,38,128,25,52,13,31,108,142,199,210,150,39,236,221,106,104,110,195,252,178,142,189,233,183,22,219,126,120,249,94,188,118,160,7,20,87,28,138,137,212,160,195,13,233,250,138,106,74,87,134,252,234,95,48,17,214,128,33,110,128,231,35,179,127,141,57,70,229,220,185,12,61,59,83,73,242,219,43,200,61,71,173,42,159,41,195,175,220,111,210,128,37,101,243,148,186,143,222,168,203,47,247,135,168,166,90,205,229,190,211,247,79,74,149,134,198,89,16,224,117,200,236,104,150,220,76,173,44,35,14,57,116,31,250,16,160,11,133,67,142,42,180,145,16,106,59,91,172,124,175,249,213,224,67,15,90,0,166,164,131,86,224,152,169,164,49,3,200,166,136,200,160,11,173,113,149,172,153,68,
137,113,230,42,238,245,21,112,16,189,77,71,45,228,105,194,242,125,5,0,69,13,196,80,171,171,70,65,110,153,171,75,12,51,218,121,200,160,17,212,86,92,206,242,182,231,24,30,149,119,79,115,29,132,225,191,10,0,207,112,204,228,47,65,66,57,67,134,252,234,213,162,43,33,207,83,80,220,66,209,156,129,145,64,22,17,131,10,86,140,48,170,41,33,78,157,63,149,89,73,129,29,104,2,57,34,199,74,158,206,108,29,143,200,60,17,72,204,8,168,79,202,217,20,1,102,88,77,179,22,136,252,141,250,81,83,65,40,146,60,30,125,69,20,1,78,105,140,167,3,165,49,97,221,76,82,1,197,95,182,1,177,64,17,197,100,79,53,105,99,88,215,110,224,106,173,196,238,242,121,81,112,7,83,85,216,132,108,110,118,111,80,104,2,196,214,160,146,200,112,79,235,85,26,38,66,114,15,225,82,37,195,161,228,146,61,13,92,137,210,97,199,94,226,128,51,48,79,241,99,235,82,70,62,66,164,130,13,104,181,186,176,233,85,101,179,29,86,128,25,111,38,65,137,187,116,169,99,102,142,69,218,118,176,251,135,250,85,101,132,169,244,62,181,96,126,245,8,111,188,58,255,0,141,
0,73,53,170,221,163,77,110,54,202,63,214,71,254,21,86,43,135,136,224,231,142,221,234,196,82,56,109,200,113,50,117,255,0,104,85,150,138,13,73,119,46,35,152,117,20,1,28,119,72,226,158,211,46,58,214,124,246,147,91,177,14,135,234,42,29,231,161,114,62,162,128,44,207,57,118,218,167,173,42,4,137,114,122,213,100,32,30,14,77,88,138,217,164,59,159,59,71,90,0,108,104,215,18,231,31,40,171,55,76,32,183,49,15,188,221,105,30,230,56,23,100,95,51,122,138,163,36,133,219,115,156,158,194,128,36,138,93,143,138,188,49,42,115,89,35,37,179,90,22,239,197,0,67,53,185,70,202,212,24,193,244,53,164,238,58,26,174,241,171,244,160,10,219,156,122,26,4,135,184,197,43,196,202,120,166,140,158,24,102,128,38,138,99,19,131,216,245,162,162,198,14,211,223,165,20,0,133,72,27,179,205,104,89,182,80,159,106,167,56,196,152,21,102,212,226,221,201,236,180,1,26,54,196,150,78,228,224,84,246,182,217,143,115,117,60,212,8,155,196,40,59,252,198,180,134,17,113,237,64,21,229,182,86,94,149,76,135,182,144,16,126,153,173,45,224,154,138,
120,150,68,198,40,1,68,134,72,124,200,207,35,168,166,71,56,115,134,235,80,90,200,98,148,198,253,9,230,139,149,48,203,149,232,77,0,89,104,193,237,80,74,133,49,42,14,71,95,113,83,192,254,98,115,214,156,87,182,40,2,171,130,192,73,17,230,149,127,123,251,200,91,100,131,173,34,126,230,83,27,125,195,247,105,36,70,141,183,198,112,123,143,90,0,182,154,139,5,217,117,30,224,59,226,135,155,77,126,90,62,79,161,170,171,114,140,49,40,193,247,20,23,183,3,35,31,149,0,61,238,45,208,126,226,219,159,86,170,210,79,60,252,18,72,244,3,2,156,92,200,127,119,31,226,212,215,12,163,230,114,62,156,80,0,144,113,251,199,10,61,5,56,165,186,143,189,154,170,75,30,132,226,159,18,111,60,243,64,19,4,141,143,200,106,104,215,109,87,42,98,145,113,198,77,92,144,236,139,52,1,78,105,112,216,20,145,205,134,230,146,52,222,75,122,154,124,144,241,64,22,20,44,131,222,154,97,30,149,4,18,20,125,173,87,134,8,6,128,42,77,23,201,145,212,81,86,202,130,8,199,90,40,3,62,115,153,143,210,173,5,43,105,183,187,144,162,170,70,166,89,71,
124,154,185,38,89,214,53,254,31,148,125,123,208,4,150,137,150,121,59,116,31,133,44,210,229,176,41,210,17,12,75,26,246,21,28,49,52,173,156,80,3,163,4,154,159,105,199,53,106,27,60,47,56,21,41,131,142,198,128,48,111,35,218,225,199,30,181,44,191,191,181,87,254,32,57,169,239,225,194,145,237,85,108,91,229,100,61,40,0,180,36,54,42,211,26,69,137,87,145,76,145,177,222,128,34,185,77,233,149,251,203,200,162,55,243,99,207,122,97,155,158,181,28,46,18,86,81,208,243,64,18,50,43,31,152,80,176,198,15,2,166,41,158,69,1,66,242,104,1,24,42,47,76,85,50,76,178,96,116,20,251,137,115,192,239,79,129,54,173,0,49,227,8,148,182,137,198,227,69,195,100,133,29,205,74,0,142,32,63,58,0,99,143,50,225,20,118,228,210,222,182,230,88,215,241,162,31,145,90,103,239,210,163,76,187,25,27,189,0,77,26,133,90,115,16,120,170,239,56,28,10,143,207,57,160,7,204,152,228,117,21,61,180,187,147,6,171,121,155,184,52,212,111,46,79,99,64,26,59,168,170,109,49,20,80,4,144,41,134,63,48,143,157,184,81,83,219,46,197,51,55,166,23,252,106,
53,6,226,92,12,133,199,79,69,255,0,235,212,207,153,92,69,24,224,113,64,13,142,54,185,151,129,90,209,198,182,201,140,101,191,149,50,8,214,218,48,6,55,145,207,181,36,146,224,80,3,102,149,201,235,69,188,206,27,174,106,180,146,123,212,214,108,185,203,16,5,0,65,169,92,174,242,164,114,71,74,202,95,49,14,64,35,233,91,183,86,86,247,50,121,155,200,110,156,26,106,89,2,187,115,146,40,3,32,93,72,6,14,63,30,41,143,43,63,82,162,180,103,178,193,57,21,73,237,64,237,64,16,172,91,250,54,77,34,146,146,12,211,226,5,38,0,83,102,230,78,59,80,5,180,148,5,235,76,150,94,58,213,81,33,28,26,25,137,20,0,168,119,190,77,89,50,5,90,166,175,182,156,9,115,207,74,0,158,5,243,36,222,122,84,178,126,246,65,26,244,254,35,237,81,137,54,168,84,25,99,82,17,228,166,192,115,44,157,79,165,0,50,102,243,91,203,95,184,181,20,143,252,41,79,144,136,148,34,242,198,165,134,36,183,79,50,110,92,244,20,0,200,108,139,13,210,28,10,152,219,219,40,193,122,133,231,150,115,133,224,123,80,182,110,220,154,0,147,236,176,191,17,202,51,232,
105,146,89,184,30,163,212,83,254,196,127,188,127,26,4,83,64,119,46,118,247,199,248,80,5,70,141,212,96,140,138,42,224,157,88,102,85,5,127,188,148,80,4,241,161,142,60,117,145,250,213,184,99,91,88,247,183,50,55,79,106,116,17,117,149,250,84,23,46,119,22,111,255,0,85,0,57,166,247,170,210,220,0,58,213,121,103,39,56,233,235,85,90,66,79,28,251,208,4,239,43,57,235,129,239,79,143,230,63,126,170,0,123,154,122,156,30,13,0,105,40,97,222,165,73,89,15,90,161,29,214,222,26,172,137,81,215,42,69,0,106,35,165,194,97,184,111,231,89,215,65,80,176,244,171,22,67,205,7,21,153,114,25,238,164,70,99,181,125,59,208,4,10,112,90,83,211,160,165,72,240,133,155,169,161,74,200,251,155,132,94,0,166,207,55,152,118,160,160,8,27,27,143,165,61,35,121,62,232,53,52,112,44,96,60,199,232,41,94,239,3,8,48,40,1,5,147,127,17,166,155,96,191,196,41,141,112,199,214,164,136,51,156,158,148,1,44,106,144,41,110,167,249,210,110,216,173,35,253,243,211,218,154,88,51,255,0,176,159,169,165,92,49,243,164,251,131,238,175,247,141,0,44,
106,33,95,62,110,88,253,213,165,142,9,46,223,115,231,7,181,79,109,105,37,204,190,100,159,151,165,107,162,71,110,160,1,150,160,10,246,250,120,69,5,176,42,200,133,7,3,20,199,115,214,71,17,143,74,129,175,237,163,56,220,91,222,128,37,158,220,133,200,170,13,41,141,176,221,42,244,90,148,50,29,189,141,45,197,164,115,174,228,35,158,148,1,155,44,34,79,222,195,195,119,30,180,84,203,111,36,13,130,56,162,128,44,218,220,121,176,249,178,13,177,15,187,158,245,159,123,112,101,36,253,212,236,61,104,162,128,51,216,238,57,60,10,97,112,56,90,40,160,6,228,158,166,156,163,111,45,69,20,1,34,129,33,192,167,249,44,142,17,9,44,221,168,162,128,52,180,169,132,11,50,202,121,83,138,166,92,75,118,204,57,4,115,69,20,1,90,88,194,19,201,228,244,169,16,45,178,238,108,25,15,111,74,40,160,8,30,86,145,137,38,163,52,81,64,19,65,3,57,228,85,153,200,134,61,139,247,141,20,80,4,113,70,54,238,147,33,7,167,86,62,149,114,222,221,166,144,60,131,24,251,170,59,10,40,160,13,133,65,18,96,96,28,114,125,43,58,235,82,72,73,88,62,
119,238,198,138,40,3,42,107,135,149,137,145,201,246,21,16,42,115,192,162,138,0,150,214,54,105,50,160,226,182,4,133,33,8,79,52,81,64,18,155,143,46,213,158,97,144,58,26,40,162,128,63,255,217);

back_metal:array[0..5206] of byte=(
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,190,0,0,0,124,8,3,0,0,0,224,138,250,16,0,0,0,23,116,69,88,116,83,111,102,116,119,97,114,101,0,68,97,110,105,32,118,49,46,48,48,46,50,54,48,20,195,73,175,0,0,0,30,116,69,88,116,98,101,46,112,110,103,46,115,101,116,116,105,110,103,115,0,53,51,54,56,55,48,57,49,49,46,45,49,46,53,41,132,140,74,0,0,0,18,80,76,84,69,250,250,250,240,240,240,0,0,0,245,245,245,230,230,230,235,235,235,211,28,204,211,0,0,0,6,116,82,78,83,0,255,255,255,255,255,122,121,224,254,0,0,19,161,73,68,65,84,120,1,213,92,135,118,99,199,14,115,211,255,255,242,3,64,130,4,101,57,229,36,121,217,104,55,186,83,72,16,44,83,36,123,243,246,166,215,251,199,123,53,220,253,236,238,231,199,215,215,199,76,126,126,60,62,60,243,246,246,25,109,244,22,32,52,122,240,253,227,227,107,231,67,244,128,36,60,53,190,198,192,231,80,16,202,19,221,3,242,246,254,62,106,111,111,239,143,143,247,117,45,103,14,227,68,120,124,124,60,150,107,181,114,236,71,183,1,18,166,222,63,30,219,195,204,118,210,
24,224,17,141,8,200,231,70,27,115,96,31,84,30,33,119,188,76,74,67,245,19,145,104,228,25,35,88,10,131,87,248,250,25,237,55,240,95,211,200,70,216,78,198,137,70,249,244,19,244,15,198,250,2,66,219,25,8,224,194,106,169,176,22,166,218,30,138,67,51,24,113,90,203,92,157,170,56,166,47,171,19,130,112,11,120,137,13,246,65,18,150,150,113,90,26,21,48,142,56,163,240,182,0,216,158,149,51,10,226,159,160,199,66,134,46,85,160,181,245,242,130,189,135,78,104,50,207,168,156,53,26,200,12,178,211,133,225,199,99,231,30,147,150,167,24,1,202,42,111,16,178,109,22,238,24,193,224,34,145,253,240,191,195,234,121,40,9,31,245,0,62,43,231,172,155,79,17,169,119,25,204,250,37,31,13,226,237,41,72,51,190,206,28,86,165,86,28,143,187,227,98,33,216,11,201,103,167,10,57,97,170,13,253,181,221,10,169,23,179,99,138,154,153,151,19,166,233,8,54,161,168,143,164,109,126,0,243,121,4,126,236,156,104,109,16,9,64,50,245,250,116,103,26,28,15,129,108,103,54,135,178,112,158,73,4,0,104,188,189,71,31,162,209,203,42,188,144,103,75,72,
252,104,255,110,243,15,66,50,200,21,15,121,31,176,136,69,204,160,23,171,134,9,205,201,244,235,76,165,82,180,163,121,128,115,60,219,127,208,218,193,90,175,212,138,67,14,253,3,152,150,78,60,122,66,73,27,33,28,87,39,18,210,232,188,190,84,144,185,72,252,32,145,215,33,130,238,236,82,156,220,23,234,239,32,32,248,238,31,184,236,152,12,53,103,156,199,85,102,14,38,176,54,13,46,177,212,107,6,163,206,254,118,0,124,98,129,189,237,53,255,227,165,214,155,65,252,180,161,121,206,4,24,135,145,220,152,74,54,183,22,238,24,233,203,196,168,97,245,48,178,158,103,241,31,154,171,114,151,72,225,23,178,161,86,182,45,4,99,128,46,13,90,112,175,68,85,1,30,250,12,6,176,106,87,46,188,141,74,201,29,137,60,41,72,224,253,72,252,216,49,3,226,192,242,118,183,92,138,80,35,212,138,103,39,121,34,23,195,21,190,44,202,150,107,214,143,108,133,16,224,84,155,26,146,161,67,133,166,6,254,84,94,147,234,201,16,218,219,140,75,85,216,216,153,199,80,128,242,102,20,6,182,25,53,175,240,236,204,113,178,92,110,50,52,116,120,101,160,
148,245,65,193,134,191,81,160,78,247,176,234,205,39,211,200,138,223,72,64,222,14,175,60,211,18,144,231,68,249,185,198,74,103,245,204,67,68,145,241,157,9,251,12,236,70,65,236,203,116,144,132,196,232,42,222,171,128,83,102,124,241,82,14,16,5,113,37,208,61,53,150,215,145,172,177,9,173,27,97,176,33,76,8,73,119,176,250,179,138,194,176,177,132,197,97,216,217,79,180,152,45,157,142,98,223,56,217,155,61,137,17,60,161,139,226,51,211,122,154,29,123,60,113,156,98,116,97,240,225,114,224,29,25,37,34,105,88,47,41,200,7,123,152,112,17,49,90,18,197,99,12,196,238,74,45,239,79,180,82,198,121,199,44,8,248,66,228,195,197,242,148,157,12,84,8,122,72,31,144,170,77,9,96,225,63,69,144,246,28,27,219,147,72,174,195,33,74,199,187,115,47,209,131,13,48,75,236,197,158,139,90,190,148,213,112,87,183,127,219,39,72,209,126,128,224,64,170,186,39,126,45,129,105,186,81,168,18,101,119,116,206,71,203,25,165,121,119,186,208,220,157,231,74,196,197,190,104,42,96,228,149,177,101,102,70,25,83,160,142,11,243,108,26,79,210,
185,35,115,213,45,227,173,134,131,31,97,72,171,79,176,85,82,164,113,132,2,147,52,7,11,113,152,246,213,64,64,63,222,246,50,242,4,152,241,131,169,197,88,16,126,147,48,5,176,195,79,196,158,152,6,105,101,177,129,99,248,90,75,19,105,3,237,7,238,251,27,13,242,167,173,126,5,51,84,242,206,148,33,244,169,63,43,56,144,239,135,158,66,131,146,17,164,95,29,174,33,34,179,151,252,225,151,89,96,124,219,151,32,162,55,82,223,26,9,151,69,87,227,122,159,253,158,153,26,7,209,49,211,0,141,82,12,233,218,255,3,178,53,190,27,12,168,31,154,199,232,101,63,27,219,228,129,194,107,4,228,71,251,51,216,239,40,14,173,149,216,136,22,68,205,212,168,218,147,86,82,77,42,236,114,236,251,235,72,185,67,89,192,214,182,140,0,47,227,3,187,187,23,182,168,73,132,182,171,78,48,64,98,135,221,111,211,108,136,124,8,222,253,222,50,237,87,80,78,133,227,196,11,25,202,14,27,248,157,31,22,226,106,177,78,105,127,109,32,86,246,134,145,39,234,108,114,171,64,80,179,128,192,246,152,11,83,245,83,130,35,110,181,23,3,26,194,27,25,231,2,
153,91,215,64,3,4,36,11,226,80,132,34,52,99,81,132,107,60,158,198,122,43,163,191,245,197,78,249,210,76,202,128,117,240,156,129,75,16,19,237,108,61,114,118,84,228,151,177,38,170,220,138,76,107,105,151,27,20,134,155,118,116,116,68,228,224,26,182,178,190,92,66,8,34,81,19,39,190,12,183,235,245,9,59,114,24,205,189,65,204,78,68,244,5,141,246,214,63,248,79,86,3,44,154,93,86,205,122,195,81,238,45,253,240,132,110,205,29,141,114,7,110,179,188,195,92,170,93,7,88,24,83,220,143,252,218,226,221,41,97,249,27,4,139,115,100,22,238,55,12,130,88,49,47,94,213,145,115,145,23,101,117,250,198,197,0,246,192,30,230,122,176,196,134,158,190,58,109,123,7,147,193,16,122,143,242,142,4,16,112,209,105,77,138,107,7,3,98,166,97,190,73,224,243,141,68,74,182,102,2,19,19,77,147,43,109,194,134,193,97,207,106,119,76,46,177,89,153,132,61,150,103,245,35,252,1,52,160,220,221,60,49,131,0,137,32,16,147,188,63,240,238,149,202,49,140,76,162,51,222,100,105,154,84,145,172,228,231,224,94,255,200,54,126,146,69,49,252,180,203,
254,196,222,155,23,150,0,69,153,155,190,232,217,216,56,37,195,60,40,229,66,28,141,177,32,232,237,208,28,184,246,218,19,155,137,136,13,154,67,182,77,195,161,201,18,218,93,183,39,141,164,98,162,8,226,54,71,145,193,157,24,118,212,147,48,24,199,116,196,59,54,100,202,207,46,192,220,150,77,0,219,34,155,205,111,19,136,161,9,198,52,161,220,131,218,237,130,220,20,24,106,102,21,89,64,75,80,206,12,40,220,141,188,162,115,4,39,48,0,128,25,115,246,176,105,40,102,30,100,13,176,234,58,144,30,150,33,119,172,200,27,93,112,243,176,84,239,162,178,166,96,250,194,220,99,65,89,161,240,240,250,152,195,155,237,176,118,109,113,197,59,43,25,145,85,24,54,104,68,156,71,224,14,79,25,80,141,23,102,213,95,9,15,146,166,48,214,24,3,5,141,117,68,129,233,55,175,30,94,144,70,2,5,140,192,227,92,48,46,146,59,139,213,26,137,114,224,215,54,91,134,160,184,152,115,12,212,209,169,63,71,87,52,33,38,173,160,28,205,158,148,121,15,227,57,5,128,146,197,106,0,75,84,186,151,5,90,33,58,204,131,155,167,201,178,220,22,139,24,238,
241,161,141,41,9,126,23,17,254,89,57,229,79,141,175,252,46,57,123,204,58,224,230,141,119,44,128,217,106,168,110,174,91,40,0,242,242,216,105,241,143,189,186,124,145,229,161,107,255,8,185,108,78,251,174,102,169,235,141,129,172,30,87,114,151,119,96,232,252,64,232,145,128,189,144,166,25,110,63,205,122,83,70,68,251,167,195,110,58,1,29,241,47,6,204,68,168,165,40,175,64,37,116,86,22,195,90,195,240,195,9,186,122,12,175,196,224,222,64,76,104,56,8,85,99,184,197,249,17,14,211,163,39,5,177,181,103,88,161,48,229,30,231,163,173,57,27,25,96,140,118,192,203,143,86,224,67,77,161,33,40,117,250,107,184,198,45,32,185,141,193,156,4,152,31,167,194,52,9,8,128,13,188,130,50,164,24,193,46,46,8,133,156,134,187,15,99,174,145,149,89,63,122,76,25,128,40,149,200,190,15,122,109,58,157,245,53,16,172,215,110,174,148,132,151,129,226,114,40,151,166,39,218,158,156,124,141,148,53,226,5,32,178,130,32,26,104,107,128,191,10,212,191,148,83,176,37,209,145,162,9,151,255,234,163,228,25,202,162,163,29,128,114,124,117,46,
213,12,95,212,148,0,222,30,241,171,68,17,239,189,67,65,186,161,41,61,133,234,244,21,193,202,37,143,44,254,7,65,196,171,102,104,39,98,138,125,137,35,122,45,46,136,218,197,141,32,93,249,90,233,118,16,142,50,23,234,177,90,167,68,88,82,150,94,71,104,124,232,47,182,91,158,100,248,62,191,200,237,241,241,165,78,49,44,221,133,219,214,15,192,121,108,192,72,231,165,174,93,196,197,178,229,247,25,74,24,38,39,28,9,12,18,19,14,19,212,121,90,177,211,14,211,158,18,146,47,136,213,117,135,23,31,235,120,146,55,234,62,127,209,154,27,186,197,160,60,99,128,146,176,64,153,108,10,33,222,80,3,241,143,202,191,162,143,223,94,145,115,180,47,63,28,251,98,35,0,105,87,107,12,51,121,91,3,230,192,79,71,2,224,99,92,42,85,85,93,111,22,46,47,206,88,119,27,28,133,196,20,7,102,240,59,54,164,135,93,144,86,29,119,4,9,30,201,53,185,135,15,171,232,232,197,178,237,230,24,96,76,236,94,151,30,101,231,82,64,163,166,63,177,132,182,247,222,34,32,120,11,162,51,240,180,216,162,92,41,181,154,69,174,105,170,141,232,211,49,253,
121,124,125,77,219,30,139,52,20,26,201,235,147,60,135,19,67,105,255,16,39,98,105,126,4,232,136,0,48,213,105,162,252,120,95,198,168,196,81,134,149,47,23,47,241,100,76,36,217,249,250,82,252,53,193,207,186,240,25,191,247,84,139,150,254,211,95,89,100,135,77,127,250,24,63,72,217,177,167,161,42,73,102,164,91,12,88,209,16,21,245,132,166,148,116,107,36,46,152,220,47,187,253,163,180,170,116,17,165,101,96,0,65,68,43,242,140,88,217,102,75,123,145,216,177,128,17,69,151,145,35,211,194,197,175,55,40,252,36,138,178,212,182,9,98,227,47,126,12,210,161,193,100,225,209,8,151,94,33,76,164,217,109,27,42,25,226,81,84,71,129,136,161,91,105,17,46,39,233,8,179,195,100,211,37,189,250,129,1,51,194,240,204,50,221,14,126,151,3,81,167,92,104,65,1,66,3,174,243,87,218,38,113,108,54,239,61,53,100,188,45,55,5,50,128,232,16,217,89,81,45,92,198,10,127,204,158,238,220,23,142,49,143,5,251,114,10,210,42,173,210,90,50,196,3,138,144,43,74,100,98,24,56,26,153,229,114,195,139,73,105,195,107,6,191,193,235,193,158,43,208,
226,95,200,218,121,120,214,194,192,152,24,83,27,181,136,253,16,128,46,29,47,189,173,44,26,225,75,227,6,29,200,174,15,140,83,87,230,33,123,156,183,44,225,133,68,176,110,72,79,231,47,139,6,223,192,160,192,113,62,126,41,90,37,131,137,106,32,169,91,159,6,64,196,251,84,65,0,48,200,48,112,167,152,121,168,84,91,4,187,57,85,77,183,8,42,53,173,13,218,82,68,217,192,107,204,51,185,205,127,225,169,247,133,179,156,165,254,133,31,205,169,108,183,70,8,208,169,14,239,171,30,56,135,65,104,155,43,71,248,58,243,179,214,167,38,192,40,18,249,82,61,46,91,59,111,165,133,47,99,16,70,12,48,43,227,255,221,183,63,95,60,155,231,95,161,120,88,85,255,221,165,203,149,160,37,198,109,31,127,158,94,191,250,198,9,238,88,87,222,248,189,36,237,198,223,127,108,113,9,255,221,199,22,163,174,69,94,241,231,7,24,109,88,255,228,165,129,31,135,58,213,177,195,189,190,52,240,174,200,136,146,94,9,179,197,63,136,55,227,63,247,18,245,123,151,195,48,55,100,111,254,245,121,187,76,206,134,172,157,244,223,187,178,241,212,214,159,
127,236,194,60,59,62,204,204,133,33,14,138,191,118,97,230,206,195,248,179,38,121,94,48,228,44,158,57,123,244,173,110,47,6,78,58,252,62,16,153,111,143,254,223,63,174,232,178,33,2,255,206,135,69,230,198,23,155,9,206,52,24,42,148,111,197,7,97,101,210,158,63,44,42,187,29,119,223,127,123,133,116,168,9,241,61,254,54,236,229,68,97,154,208,83,249,196,218,4,32,151,86,13,58,75,208,236,140,17,227,5,251,25,131,158,132,165,47,63,68,148,235,87,31,213,97,15,165,50,238,177,130,36,154,223,80,28,95,204,229,9,184,182,17,79,42,80,127,203,23,37,220,160,204,8,228,42,60,8,152,246,34,71,165,24,147,81,220,156,118,63,227,202,232,232,35,192,211,66,96,188,247,121,165,104,14,43,148,79,69,182,194,129,8,213,12,13,121,91,70,115,146,205,225,193,13,115,27,122,198,48,239,255,150,198,179,254,10,121,203,36,211,6,167,39,8,142,48,196,231,103,53,82,21,32,161,170,30,234,223,11,254,249,47,9,25,88,87,217,70,176,96,59,136,65,153,165,195,191,50,190,142,144,156,62,99,126,71,42,101,9,172,83,138,1,109,96,22,70,137,70,55,58,
26,117,100,180,227,101,9,2,99,85,202,61,188,241,206,152,209,26,4,74,230,80,142,111,155,41,132,215,224,163,233,143,67,36,229,74,225,104,215,35,152,98,180,21,248,80,211,71,36,248,195,17,13,215,184,5,36,87,186,52,24,126,172,153,48,77,25,1,176,129,215,165,44,11,59,157,213,129,15,60,67,218,25,130,126,88,70,230,122,226,234,113,80,98,140,149,140,234,205,25,144,90,143,47,26,152,109,144,194,52,199,131,32,157,113,183,195,147,211,219,238,59,91,153,183,134,248,215,90,132,39,155,138,48,161,250,231,149,3,102,114,57,141,8,215,122,179,255,75,63,28,2,160,216,14,48,200,69,219,161,125,118,96,207,215,8,24,252,107,23,17,80,176,102,88,249,116,68,119,30,137,113,48,96,108,179,227,65,145,216,172,5,161,38,135,17,34,48,246,175,227,111,91,161,26,205,33,26,222,98,122,22,8,79,21,132,30,177,87,67,222,163,101,4,63,57,126,40,79,167,37,138,226,248,10,233,10,118,211,150,19,30,146,17,189,193,163,255,196,143,165,125,222,22,233,200,98,238,40,235,188,86,214,70,168,253,237,72,177,231,37,129,102,28,91,37,183,69,178,
10,137,181,5,213,49,134,26,230,99,120,224,169,134,173,65,191,142,84,224,204,139,111,12,156,92,87,22,140,88,92,171,101,52,72,172,131,178,40,68,94,119,240,215,56,67,148,134,220,113,139,7,53,160,151,137,5,48,114,35,18,19,248,165,128,116,141,220,12,0,19,187,114,2,129,242,179,156,105,188,224,118,251,161,162,191,146,102,237,215,60,134,134,242,170,143,31,50,134,55,91,143,216,141,52,231,146,32,13,41,18,235,208,218,160,232,24,68,29,140,12,26,14,153,90,61,195,173,166,141,163,57,237,30,66,26,134,219,108,68,128,25,88,181,214,198,234,231,71,188,34,220,144,56,186,72,133,71,216,232,65,96,239,170,19,58,142,70,46,28,81,226,176,254,234,5,86,134,65,243,159,248,101,48,92,236,109,65,129,35,143,114,161,41,224,49,177,225,144,29,163,83,195,14,131,3,35,191,90,249,150,168,83,161,73,40,111,127,10,67,31,5,90,57,64,185,2,77,116,45,169,26,22,132,129,3,61,190,171,217,48,218,46,106,80,19,77,148,178,19,116,52,134,127,212,12,68,102,181,156,32,176,12,109,248,239,254,69,72,146,204,138,231,37,103,217,5,81,58,59,
185,219,38,50,234,235,27,194,54,52,159,127,56,212,209,129,91,6,193,146,156,235,212,194,165,145,108,67,194,27,130,160,114,153,207,170,242,76,215,51,217,78,204,217,182,233,211,220,216,242,154,32,8,101,218,77,6,223,109,94,33,74,34,243,243,26,183,77,119,200,206,6,4,136,13,121,120,34,104,175,229,66,205,217,137,254,113,107,42,155,43,193,244,214,28,0,154,61,50,229,162,30,29,88,204,8,109,221,54,193,118,13,143,48,126,232,135,138,232,15,32,20,88,231,14,29,39,103,221,101,42,118,165,213,210,41,148,162,189,110,228,178,226,94,208,182,18,40,86,127,197,87,12,104,246,21,71,3,244,51,220,115,58,249,140,52,193,212,84,119,66,238,105,162,168,54,16,171,106,107,4,151,183,85,94,133,132,129,192,242,100,216,146,198,144,13,154,51,134,134,101,53,230,14,101,1,164,80,149,47,155,11,203,64,100,255,241,7,235,223,75,132,223,192,120,121,2,36,35,254,42,246,8,212,48,238,164,21,213,48,244,68,83,92,251,237,184,149,42,94,156,20,48,183,106,219,23,140,142,118,252,27,27,238,182,126,197,48,63,235,245,112,165,161,164,106,
84,237,77,26,228,146,10,187,70,252,205,103,42,69,174,27,76,179,179,211,192,176,221,82,178,94,88,224,157,172,237,133,116,101,164,76,253,182,193,31,184,214,133,217,147,182,192,254,218,187,237,54,70,158,19,36,232,173,117,239,92,6,229,19,179,198,150,96,117,152,86,122,197,222,234,179,237,236,220,118,73,26,87,23,102,111,101,109,196,115,132,88,140,172,130,53,164,143,82,102,181,195,151,138,0,131,219,105,242,3,89,89,140,97,232,15,40,34,151,97,76,41,70,239,87,252,39,151,32,188,59,40,162,184,190,36,123,110,100,248,117,164,95,226,31,188,78,136,65,85,219,213,171,146,162,91,83,28,72,17,255,193,235,205,180,202,121,54,53,22,208,63,246,207,141,185,171,58,174,187,134,116,82,128,0,75,23,63,242,201,194,161,91,163,17,180,13,66,207,120,74,133,139,92,91,190,193,245,87,6,146,94,123,253,91,25,21,21,186,91,45,32,245,9,132,199,24,152,32,119,140,187,240,99,99,158,239,37,80,39,116,240,112,249,121,155,177,81,60,211,99,116,24,138,158,69,110,188,64,59,46,42,70,134,165,37,64,100,13,194,153,139,22,179,165,83,
181,108,167,217,219,248,194,232,222,0,1,47,180,54,243,237,97,134,156,112,220,36,116,32,144,153,73,31,141,149,249,250,249,71,65,62,173,186,67,63,62,139,251,4,14,16,26,6,252,122,95,161,43,88,68,112,115,72,201,30,238,102,243,168,65,162,204,252,1,196,141,113,38,196,189,123,25,255,128,34,201,229,131,9,115,91,249,9,129,76,227,231,155,206,35,250,97,250,80,162,159,52,44,227,106,98,122,121,49,10,229,8,223,195,149,86,243,92,8,129,230,232,151,130,186,174,22,118,2,20,69,152,44,141,39,161,129,73,133,203,130,63,160,132,88,199,169,12,117,167,160,126,236,44,184,248,108,119,163,92,129,50,182,36,216,169,225,130,215,130,106,210,113,153,224,200,34,254,200,129,188,21,185,149,165,98,134,220,214,101,227,0,105,164,135,35,49,81,243,181,121,93,108,21,130,135,98,13,28,175,22,26,45,27,149,146,59,146,8,171,169,17,165,198,40,64,207,90,126,182,244,208,24,1,52,114,139,206,138,47,29,47,85,246,16,167,41,53,34,47,92,227,151,80,13,203,244,202,96,234,208,12,13,172,39,35,97,84,201,112,255,240,207,78,183,203,136,213,
121,246,197,186,160,9,208,223,89,160,166,94,83,72,88,207,147,199,115,221,239,46,221,138,126,248,147,69,245,143,151,79,216,75,206,60,168,51,66,249,9,77,96,140,69,135,226,165,2,132,78,73,12,18,181,15,17,116,99,213,11,220,111,71,233,73,235,236,186,9,152,74,209,142,102,248,117,154,235,238,55,142,63,90,187,0,212,115,129,160,13,155,209,251,57,30,103,119,78,162,209,254,221,230,97,143,3,54,130,26,186,36,181,185,198,217,229,26,100,204,177,1,229,41,255,60,123,68,163,227,59,10,33,0,82,143,231,246,172,183,105,252,134,48,214,221,146,188,20,195,238,183,248,242,194,156,243,14,73,81,250,17,39,183,150,35,148,71,123,79,228,124,38,215,166,232,84,110,76,57,174,130,216,184,36,148,210,194,140,61,15,130,186,135,184,199,73,155,111,30,100,59,163,69,121,142,241,117,191,206,214,112,80,70,214,86,50,180,78,54,211,204,220,80,53,152,51,65,103,32,155,1,250,30,122,2,94,103,120,177,149,120,145,182,188,110,111,246,24,230,242,127,39,10,46,123,87,72,42,128,178,202,253,104,24,65,34,167,245,189,136,218,254,24,175,
225,20,11,4,230,56,56,191,228,207,219,204,110,204,249,61,15,19,182,55,163,164,146,64,79,22,126,92,207,32,58,164,19,139,14,228,71,244,187,37,164,165,227,216,64,0,116,130,204,227,107,142,171,90,46,109,115,196,105,109,221,101,103,115,122,77,95,86,39,23,0,29,95,56,113,49,2,48,190,77,67,253,231,162,79,66,19,127,28,95,62,174,102,140,241,73,225,179,188,240,249,149,243,253,66,28,220,148,151,201,241,48,62,128,183,254,80,0,145,141,100,252,35,194,161,218,4,114,44,217,63,131,108,172,184,84,182,7,47,183,115,233,194,194,73,26,187,246,244,23,255,159,120,255,15,83,53,80,185,133,165,249,168,0,0,0,0,73,69,78,68,174,66,96,130);

back_ivy:array[0..4997] of byte=(
255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,255,219,0,67,0,27,18,20,23,20,17,27,23,22,23,30,28,27,32,40,66,43,40,37,37,40,81,58,61,48,66,96,85,101,100,95,85,93,91,106,120,153,129,106,113,144,115,91,93,133,181,134,144,158,163,171,173,171,103,128,188,201,186,166,199,153,168,171,164,255,219,0,67,1,28,30,30,40,35,40,78,43,43,78,164,110,93,110,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,255,192,0,17,8,0,189,0,189,3,1,34,0,2,17,1,3,17,1,255,196,0,31,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,
119,120,121,122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250,255,196,0,31,1,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,17,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119,0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,
247,248,249,250,255,218,0,12,3,1,0,2,17,3,17,0,63,0,205,5,163,108,243,131,239,82,133,105,15,202,115,158,244,174,80,39,32,176,244,199,53,23,79,154,50,126,153,174,113,11,44,82,70,191,119,7,220,210,110,0,114,71,224,41,201,57,42,124,211,145,158,42,120,237,22,97,195,0,61,115,70,163,31,167,175,155,38,68,64,160,234,90,175,176,10,50,163,240,197,65,9,22,224,196,128,17,245,169,60,207,148,150,97,143,64,40,24,252,141,157,179,89,119,19,48,151,229,98,59,245,169,158,241,242,84,32,197,86,141,124,219,145,215,29,77,38,34,237,170,178,195,186,70,37,159,158,77,60,181,4,147,77,40,79,222,32,47,214,179,220,101,107,155,141,131,247,108,65,245,6,160,180,184,38,98,210,177,100,232,119,28,213,242,240,99,11,16,152,142,202,185,253,106,156,151,128,229,82,202,33,245,90,213,45,4,104,121,81,127,20,72,234,122,54,208,104,123,40,72,226,52,252,133,65,167,36,177,199,137,221,118,30,66,103,145,86,89,213,70,23,63,74,157,134,81,146,0,140,228,40,81,198,48,42,12,60,127,62,246,193,233,201,171,243,47,200,122,253,42,9,80,52,
91,64,228,80,152,153,12,18,59,204,3,49,32,251,213,207,186,196,230,168,5,43,219,6,165,87,158,78,198,173,136,176,167,57,207,122,88,216,3,201,20,136,187,62,247,83,76,221,179,62,212,128,179,50,134,78,188,246,170,102,82,62,82,72,166,189,222,214,198,72,168,228,148,55,78,180,198,14,191,197,147,205,40,85,32,113,67,115,24,4,28,253,105,66,140,117,52,150,130,52,2,170,163,54,209,129,234,42,140,200,3,124,160,12,244,173,11,129,181,66,126,53,78,64,73,247,20,152,202,230,29,195,107,46,125,234,204,10,200,187,85,112,62,180,21,97,130,196,40,61,201,169,209,64,64,119,19,248,84,54,194,193,183,31,49,198,105,79,78,121,163,240,165,61,13,0,103,203,35,52,140,51,210,166,179,92,2,222,189,41,162,212,239,99,158,15,36,212,143,50,193,31,64,72,28,10,111,178,1,243,72,98,77,195,174,125,42,172,197,165,144,96,147,248,241,82,90,72,102,71,19,2,192,212,222,82,4,253,222,113,66,247,116,2,188,106,200,155,55,156,30,217,171,49,65,24,229,220,125,5,50,8,137,147,12,64,110,194,166,32,47,83,199,210,134,198,56,152,251,48,252,141,
70,204,160,241,38,63,224,38,163,154,226,40,184,44,73,244,2,163,243,55,253,220,140,250,210,212,9,12,139,255,0,61,14,127,221,52,198,117,101,217,20,170,174,127,188,49,249,84,79,39,27,87,241,53,28,139,251,176,203,140,253,41,164,23,37,141,217,70,217,10,126,53,60,45,187,229,136,238,245,192,226,178,193,53,177,167,152,227,131,104,201,115,203,113,86,196,14,73,109,184,228,85,123,129,243,117,169,167,12,187,228,206,6,254,149,21,195,41,147,130,49,64,20,164,80,132,188,157,206,20,127,90,146,211,110,94,86,0,172,99,32,122,158,212,249,150,57,39,222,192,149,3,10,190,213,60,76,138,191,42,5,31,74,111,96,185,28,17,151,1,138,158,57,60,85,209,26,16,8,64,62,162,156,165,72,24,235,78,49,55,115,64,12,149,178,236,127,10,170,229,148,252,157,79,181,58,105,4,106,92,246,168,237,110,4,191,120,0,227,242,172,221,222,160,77,20,33,126,121,14,247,247,61,42,94,77,68,242,42,12,177,250,10,154,221,94,72,247,176,0,30,131,218,164,97,138,70,244,167,183,21,27,54,209,156,100,211,16,230,226,50,113,218,177,229,14,231,28,238,
36,102,173,181,204,209,187,28,131,158,160,142,42,120,166,137,190,102,77,167,233,154,181,116,4,104,134,24,192,57,205,59,126,212,227,62,162,172,59,66,227,27,215,241,53,82,72,194,156,19,145,219,154,128,16,200,132,130,236,85,151,144,194,155,45,212,147,46,197,78,189,91,29,105,158,88,13,210,165,137,194,141,216,28,118,197,61,16,21,210,2,175,243,245,29,169,206,248,24,29,63,157,58,83,133,220,79,36,244,239,81,170,52,172,6,63,12,85,45,64,116,75,189,75,99,145,218,157,34,109,85,12,127,135,250,212,177,219,249,100,29,199,61,199,106,101,223,1,127,26,98,42,186,17,206,42,120,228,35,14,167,6,155,141,192,45,55,6,51,208,145,77,129,106,75,207,220,237,219,243,147,207,28,85,94,248,200,205,75,31,144,195,230,114,167,215,20,201,34,216,251,128,45,248,210,186,24,1,147,208,154,154,59,89,164,1,182,128,190,230,171,143,48,184,85,24,207,181,109,65,16,130,16,187,137,39,146,73,166,9,17,67,11,70,6,72,171,25,61,243,76,111,189,144,115,138,73,27,167,74,16,25,142,146,78,187,112,125,125,41,166,38,182,96,164,2,125,115,
83,18,80,179,19,211,167,21,11,51,63,83,154,139,246,1,164,147,203,18,73,173,184,128,91,100,227,141,162,177,25,195,62,7,97,90,214,211,111,176,30,171,242,211,176,34,57,152,133,37,84,177,244,2,178,36,146,227,146,206,195,219,53,117,239,68,119,123,51,129,235,239,87,110,21,102,135,121,81,211,147,138,168,160,50,99,86,216,12,140,73,110,153,61,170,110,7,122,142,70,249,212,122,116,167,15,74,77,136,115,5,56,29,207,20,231,249,120,200,207,244,166,70,63,126,78,71,202,58,85,105,174,9,99,180,254,52,173,125,6,88,46,163,3,61,58,210,163,141,216,197,103,137,14,236,213,184,177,247,179,67,141,128,179,247,152,13,163,235,83,164,64,146,17,249,244,170,193,136,249,128,207,167,52,206,91,146,72,3,160,6,164,11,143,4,163,163,103,241,170,211,43,228,41,207,183,53,126,223,121,143,247,141,159,78,41,178,194,25,243,222,169,32,42,121,50,46,62,80,63,42,108,145,78,191,56,198,207,76,213,209,147,198,114,125,113,76,184,198,237,157,128,230,155,3,50,68,7,185,230,157,20,204,178,236,104,201,94,213,46,192,199,230,237,74,21,
35,251,207,183,53,60,221,4,92,83,16,78,20,100,142,77,58,48,89,126,110,49,234,106,188,115,218,167,37,217,182,245,192,162,93,82,31,224,137,155,253,227,129,77,92,100,151,12,206,155,35,7,30,162,169,254,240,118,106,191,4,173,60,42,204,160,110,236,7,20,174,177,174,50,5,0,81,156,243,180,125,77,64,242,236,109,162,173,195,23,152,187,213,114,72,200,205,81,184,134,72,203,49,82,125,105,65,106,4,66,77,178,131,249,214,157,172,187,97,145,115,199,6,177,170,213,188,251,96,242,201,229,155,175,181,105,40,246,2,118,117,154,54,77,160,186,243,210,157,5,225,88,154,38,207,76,3,85,46,9,138,96,202,113,145,81,172,129,189,115,66,90,1,111,118,92,113,68,211,8,147,35,239,30,149,22,253,163,53,17,87,149,186,28,154,73,119,16,69,113,182,41,84,228,180,152,231,52,202,211,130,40,35,133,60,203,101,102,60,103,60,85,184,150,38,56,88,35,31,128,161,205,21,99,11,30,198,172,91,56,11,134,63,78,43,116,5,3,144,139,142,216,170,147,249,42,75,42,2,15,81,138,78,119,208,44,84,119,227,3,189,77,111,24,65,239,222,165,141,151,56,137,
7,160,111,240,169,35,141,80,101,170,68,61,9,199,160,20,187,139,48,25,226,162,146,234,24,248,102,201,244,94,106,91,103,75,132,46,160,140,28,98,168,9,66,170,243,84,229,231,44,123,213,169,142,212,35,61,106,177,59,169,73,131,43,183,7,119,173,81,145,152,78,249,195,41,60,140,214,148,168,118,213,25,96,50,58,109,251,205,198,41,67,125,68,42,39,76,100,238,255,0,34,173,11,40,149,119,74,72,39,176,52,249,100,130,200,96,176,105,7,64,43,58,91,137,110,15,67,142,192,85,217,129,179,8,85,140,5,7,0,113,81,72,196,191,20,203,121,63,112,131,60,129,200,168,222,85,83,243,28,102,179,99,41,153,165,59,4,110,80,34,142,115,142,213,42,106,63,39,239,219,205,110,195,111,245,170,102,25,56,220,184,4,100,103,210,154,99,97,216,17,237,91,217,1,52,151,48,201,146,208,149,99,221,77,84,201,61,205,41,250,83,226,136,200,122,224,14,166,171,68,4,131,46,138,101,228,40,249,71,173,39,208,81,36,170,91,106,244,245,168,203,30,221,42,82,98,30,73,63,133,88,129,243,24,28,113,85,50,88,245,167,193,187,126,225,255,0,235,161,173,0,214,
139,12,170,27,160,232,41,162,119,73,54,228,243,198,7,28,82,219,140,198,125,115,79,141,82,81,33,61,115,128,115,208,10,192,162,85,112,223,43,30,15,67,81,72,54,39,206,64,221,220,250,82,110,57,35,130,216,202,231,185,170,35,123,22,46,78,121,235,235,66,64,89,243,200,143,116,43,187,182,105,178,73,44,136,55,63,94,163,56,197,67,111,49,136,176,234,135,168,245,171,127,103,134,97,152,156,19,220,103,154,187,8,162,209,185,126,49,129,239,87,236,39,75,116,96,236,121,60,109,21,11,218,178,247,253,41,22,35,223,63,149,13,177,23,164,185,73,126,233,35,234,43,58,242,70,50,133,82,126,94,152,245,169,252,146,57,44,71,225,82,71,111,25,93,206,27,216,147,192,247,165,109,110,49,145,222,169,1,39,56,110,155,177,197,71,116,128,46,236,156,3,144,65,168,39,135,203,144,130,15,183,52,176,185,199,150,223,112,250,246,167,110,162,35,221,207,202,7,215,20,255,0,184,155,156,159,97,154,20,5,57,99,210,160,149,204,141,147,211,176,167,107,129,118,213,255,0,209,242,72,234,106,156,242,25,36,44,51,142,130,158,239,178,0,138,70,
79,38,160,167,24,235,112,53,55,121,150,104,164,3,177,71,229,138,165,34,21,57,82,113,90,65,2,244,192,30,149,90,72,246,190,59,118,164,5,35,207,223,90,73,1,101,11,31,220,29,187,213,192,128,142,130,144,192,152,206,245,31,141,62,96,51,169,71,214,173,73,7,153,247,6,227,235,140,83,215,79,59,126,103,57,244,2,175,157,88,10,209,166,121,199,21,106,222,60,146,113,210,156,44,230,232,20,113,219,53,161,107,108,22,205,150,64,162,66,220,115,210,179,114,184,210,42,44,158,92,114,115,207,111,173,32,100,28,49,198,20,115,68,241,168,125,190,106,159,247,65,168,228,242,114,73,14,199,62,184,21,40,8,157,222,70,220,73,246,171,27,178,2,186,179,183,77,202,50,71,248,209,29,200,81,182,56,34,200,238,195,113,253,105,100,187,191,96,4,110,202,15,93,160,45,13,92,99,30,206,100,249,149,119,143,97,207,229,85,130,188,77,252,74,223,149,73,24,159,206,249,139,110,61,201,171,241,198,204,187,101,118,97,232,77,59,180,34,43,91,150,144,21,147,4,143,226,169,183,14,213,32,182,136,116,65,82,172,41,215,109,43,129,12,80,238,249,
219,167,97,86,36,25,133,190,149,42,198,190,180,72,169,180,140,156,125,42,174,51,63,203,18,166,214,25,254,149,81,160,104,217,148,143,198,175,169,129,15,14,231,240,169,209,86,95,233,66,17,136,220,117,28,30,181,27,38,57,7,32,247,173,107,155,32,114,84,98,179,217,94,6,60,112,120,35,20,208,21,200,166,212,185,10,249,192,97,232,106,244,73,109,50,103,96,4,117,4,83,184,139,43,111,199,223,63,149,72,182,160,168,227,62,245,96,160,85,13,199,189,32,108,156,10,201,92,100,95,97,76,115,142,106,183,216,118,62,236,168,31,90,190,72,3,154,207,186,226,98,123,26,176,100,173,2,231,32,134,62,198,149,23,156,14,181,20,18,123,212,240,13,206,126,134,161,234,0,137,153,0,171,59,74,131,180,253,69,64,143,229,194,210,240,118,169,52,144,95,199,114,55,12,43,142,160,250,83,178,176,204,235,134,87,185,44,1,192,235,145,80,67,19,202,126,81,245,53,126,101,142,73,139,129,215,173,57,84,241,180,99,240,169,230,182,194,34,75,117,143,182,79,169,169,130,231,174,105,91,32,128,105,222,195,189,75,96,61,112,176,244,29,122,226,131,
145,200,228,122,211,231,93,144,168,247,230,136,8,60,96,83,242,0,141,129,198,105,242,48,83,145,67,68,87,145,210,162,145,86,69,42,220,131,214,152,201,35,117,111,226,7,219,52,172,249,249,120,172,87,142,75,57,193,86,59,79,67,86,162,188,254,250,19,244,53,162,242,17,27,157,172,121,226,165,251,82,219,198,25,179,236,7,122,130,76,179,150,32,129,216,85,75,178,25,192,36,241,210,146,220,69,239,237,133,206,12,109,131,239,76,146,236,200,228,42,43,15,66,42,149,170,9,110,21,72,235,159,229,91,41,107,10,42,182,223,156,241,156,211,147,75,65,149,86,217,101,25,242,213,15,251,36,212,137,105,229,140,43,31,94,149,103,1,79,221,197,72,0,35,35,21,157,192,82,126,92,86,101,204,151,86,211,3,230,18,135,167,28,125,43,93,162,13,202,156,26,173,60,65,148,164,139,193,163,84,50,184,188,89,7,204,72,53,28,210,137,152,149,60,142,180,193,14,220,169,39,114,255,0,145,76,141,118,179,85,183,160,135,59,24,226,224,242,120,171,90,124,153,11,147,236,121,170,51,182,91,28,113,82,89,177,231,131,129,83,230,34,220,205,178,206,127,
117,34,169,68,18,37,94,79,78,106,197,203,143,33,134,113,146,59,85,38,125,237,156,209,186,176,203,145,221,67,254,208,247,197,89,129,196,145,239,10,64,247,172,171,116,50,75,179,212,214,191,10,2,168,192,28,10,153,36,128,70,0,156,211,161,92,190,105,184,205,75,16,164,183,24,183,71,40,191,90,142,60,131,145,82,92,127,171,252,106,37,109,136,205,199,3,52,222,224,92,18,41,92,100,3,233,154,70,136,56,227,131,235,88,83,18,84,200,27,57,56,200,53,37,166,165,60,109,177,152,56,236,27,252,107,75,104,43,151,174,32,220,165,28,117,232,125,234,27,113,135,229,64,61,248,167,13,98,7,249,102,137,151,220,115,78,6,25,190,120,36,86,246,207,63,149,36,172,50,181,230,4,172,73,233,89,110,219,142,226,127,10,191,168,182,73,80,112,79,95,165,82,145,131,42,224,243,223,138,184,136,146,195,254,63,35,31,95,229,91,147,174,193,24,172,27,25,68,87,145,200,122,12,255,0,42,220,158,85,151,99,41,227,21,53,23,80,36,85,18,47,61,105,10,109,56,32,254,116,144,54,211,237,87,0,24,245,168,90,140,199,182,213,89,78,217,148,48,63,196,
56,53,127,237,182,146,252,173,32,83,232,195,21,206,183,90,73,27,123,126,149,165,133,115,118,120,70,55,169,12,61,65,205,103,147,130,198,171,91,51,35,224,59,40,61,121,169,102,4,100,100,114,122,212,181,109,0,136,156,154,116,110,203,247,73,250,83,113,238,42,68,12,159,48,83,245,197,12,9,167,96,35,27,212,159,65,85,151,146,91,3,242,169,90,72,246,13,196,156,119,52,200,143,152,50,7,83,197,37,176,22,108,83,27,156,253,5,90,36,1,185,136,0,117,53,28,96,71,31,36,0,58,154,169,115,57,152,97,9,217,252,234,109,204,198,44,151,102,103,216,167,106,127,58,213,180,33,225,24,61,56,53,129,16,231,53,171,167,74,82,77,172,120,110,159,90,209,165,176,175,169,114,227,136,136,252,107,62,250,66,150,111,142,248,21,163,113,247,13,100,234,45,136,85,61,78,106,62,210,25,70,57,14,221,153,227,174,40,201,83,144,42,52,226,78,79,90,151,110,79,36,226,183,100,141,0,183,98,77,73,110,194,41,209,155,32,3,206,58,211,144,127,10,128,7,249,235,67,38,211,199,79,92,84,222,227,36,186,184,243,87,99,40,39,170,183,67,138,168,200,195,
168,53,110,24,140,135,166,118,243,131,222,156,240,238,249,147,35,219,52,45,0,161,238,5,92,179,187,199,202,217,226,162,117,101,251,203,249,138,140,175,57,82,1,244,63,227,77,218,74,204,70,234,76,190,81,113,131,138,168,111,46,20,255,0,172,35,62,213,83,204,145,45,216,12,140,226,129,43,52,106,172,185,219,220,138,133,27,12,181,45,152,35,42,41,144,233,236,78,79,62,213,162,122,32,199,81,253,106,81,44,49,226,22,112,174,70,229,161,92,10,50,90,0,184,80,21,190,149,95,149,30,84,234,113,217,177,210,174,220,76,4,225,88,123,102,145,241,77,1,155,44,79,22,14,67,41,232,194,157,28,164,246,230,172,59,172,99,110,1,231,32,122,85,118,136,164,220,3,142,180,154,16,201,66,191,39,191,90,154,204,172,112,185,110,221,253,170,172,160,164,159,40,37,91,183,189,77,34,254,232,70,167,191,60,247,161,173,44,49,46,167,50,5,94,66,231,129,80,171,21,239,197,44,138,93,128,64,73,6,158,109,164,28,145,77,89,32,21,118,227,114,145,207,106,137,174,36,138,114,85,143,7,165,56,2,14,42,172,135,46,79,189,84,86,162,58,101,184,91,155,
65,42,247,234,61,13,99,106,18,3,113,183,57,192,2,165,210,37,249,37,136,158,188,129,80,184,221,59,149,28,231,174,106,45,105,12,135,203,199,45,249,84,136,55,48,205,63,202,39,144,15,29,105,120,81,210,170,247,17,50,67,150,192,232,42,89,98,204,93,58,98,146,208,254,239,53,62,224,35,25,21,32,68,138,35,101,199,167,53,36,137,183,231,3,234,49,72,195,129,83,68,62,92,125,234,0,172,83,204,231,0,26,143,236,94,103,108,84,239,251,167,233,199,106,100,147,54,198,49,28,55,106,6,70,44,37,140,245,226,166,242,1,234,41,177,25,118,230,89,89,143,166,106,94,79,82,127,58,150,192,153,219,229,141,129,233,154,165,168,33,154,252,109,56,218,130,158,147,49,65,158,199,138,35,96,215,142,72,231,167,233,84,134,67,32,249,55,23,98,203,192,230,162,243,37,60,150,205,44,174,90,67,192,20,139,205,8,145,158,91,188,187,183,28,246,171,209,2,235,243,145,159,106,168,120,28,85,155,69,231,173,54,3,254,195,188,103,28,83,101,182,141,93,118,158,71,81,87,199,220,197,86,42,55,147,81,39,160,200,227,140,32,194,40,169,27,56,228,10,144,
40,226,154,224,18,43,48,42,205,106,27,230,83,138,206,158,223,203,108,103,154,219,0,30,42,165,196,42,236,73,206,71,122,210,50,104,12,235,103,104,46,21,142,113,208,253,41,183,74,82,230,64,9,235,235,82,184,218,196,117,166,48,4,242,51,90,167,173,197,113,45,114,215,8,55,28,103,158,123,85,185,87,230,227,161,233,80,219,32,12,196,117,197,93,142,53,124,3,74,79,80,25,4,171,16,42,221,234,67,48,124,5,6,137,32,85,124,117,21,97,34,69,35,10,7,20,152,17,182,66,14,123,243,82,68,88,114,167,240,166,144,62,97,218,136,88,239,219,218,144,13,145,132,163,110,14,126,149,18,46,195,243,3,138,177,42,5,147,142,244,56,30,88,56,235,64,200,247,0,50,122,14,77,16,75,189,50,112,57,170,243,177,219,142,196,211,33,98,1,0,212,88,71,255,217);

back_pitted:array[0..2660] of byte=(
255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,255,219,0,67,0,27,18,20,23,20,17,27,23,22,23,30,28,27,32,40,66,43,40,37,37,40,81,58,61,48,66,96,85,101,100,95,85,93,91,106,120,153,129,106,113,144,115,91,93,133,181,134,144,158,163,171,173,171,103,128,188,201,186,166,199,153,168,171,164,255,219,0,67,1,28,30,30,40,35,40,78,43,43,78,164,110,93,110,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,255,192,0,17,8,0,96,0,96,3,1,34,0,2,17,1,3,17,1,255,196,0,31,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,
120,121,122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250,255,196,0,31,1,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,17,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119,0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,247,
248,249,250,255,218,0,12,3,1,0,2,17,3,17,0,63,0,153,181,155,120,74,219,233,241,180,188,224,176,21,74,206,217,30,234,105,47,88,151,12,75,22,29,5,88,72,159,77,157,33,181,182,73,37,35,115,49,25,2,139,107,105,111,117,73,222,235,229,203,109,216,189,56,226,128,33,181,156,220,68,254,82,16,133,185,200,235,77,189,140,75,113,106,183,44,118,146,70,16,116,171,183,223,100,211,237,4,81,200,197,203,140,34,156,18,51,76,154,246,87,183,17,193,107,137,192,249,11,114,70,104,2,173,172,101,239,37,149,1,127,155,106,247,192,28,85,207,33,163,183,123,167,183,82,224,128,187,143,92,211,34,181,185,178,178,83,17,9,59,156,182,211,146,106,179,219,222,93,77,139,201,221,199,4,32,60,15,202,128,23,82,51,172,246,203,41,70,149,193,33,73,225,71,99,252,233,208,105,246,246,203,27,221,48,142,70,127,148,245,205,93,54,86,179,202,175,12,139,189,19,105,220,252,154,156,216,64,174,146,59,229,212,30,1,200,20,1,157,169,69,100,28,201,11,198,236,64,83,158,185,162,223,77,187,154,68,100,154,85,65,219,118,0,167,220,71,111,100,162,
226,230,37,118,115,242,162,245,99,90,41,116,211,91,171,8,204,11,143,186,77,0,103,106,242,133,43,101,151,102,124,101,151,210,163,86,176,121,98,180,65,51,249,71,37,251,10,179,36,214,79,112,129,230,93,227,251,167,60,85,105,94,43,185,166,142,205,67,70,118,174,65,198,125,104,2,87,77,70,57,227,75,87,216,15,36,109,7,31,157,93,185,146,226,210,202,109,161,76,251,75,22,3,189,81,176,213,110,238,174,217,96,135,48,231,27,177,205,88,212,102,16,217,202,239,147,145,142,188,156,208,6,85,172,17,243,127,168,202,237,140,99,29,73,236,5,104,197,60,87,242,121,112,131,111,188,229,183,142,72,172,235,52,115,104,55,195,242,168,220,55,86,157,140,150,171,31,152,242,41,145,184,85,199,74,0,101,196,118,86,237,60,81,220,150,187,116,194,100,158,14,61,105,182,90,101,197,172,96,41,253,236,131,147,156,212,90,125,164,183,26,172,243,102,38,80,248,231,146,5,91,212,53,36,176,145,64,86,102,114,112,20,227,138,0,161,34,157,50,225,96,137,76,147,159,153,216,247,21,161,105,117,246,128,115,25,66,189,123,138,107,222,90,194,
171,115,113,17,44,195,1,113,243,26,206,154,250,75,169,74,64,223,101,181,24,56,232,91,235,64,19,219,218,198,47,158,230,242,226,53,33,201,82,242,0,0,236,49,73,168,221,190,175,118,182,150,108,124,165,36,49,28,3,81,91,233,246,211,147,42,202,155,20,124,222,103,4,159,199,173,79,167,195,178,83,42,67,177,73,249,119,80,4,218,125,174,152,146,108,255,0,89,42,12,54,6,71,231,79,58,101,176,69,88,128,80,9,99,158,245,58,201,105,99,106,216,8,131,163,49,53,80,107,22,69,194,137,79,215,105,197,0,38,157,122,144,147,5,173,177,85,206,9,39,154,135,89,136,121,209,77,41,38,49,242,132,31,222,171,182,182,119,127,111,149,196,139,28,71,156,99,154,131,82,185,154,59,168,224,130,21,155,39,113,44,50,40,2,73,36,187,187,211,196,112,196,34,228,12,145,212,83,46,222,43,89,97,183,120,188,217,130,103,9,192,90,185,29,216,184,1,50,129,147,239,42,244,6,149,99,139,205,243,26,48,205,140,102,128,42,218,73,101,167,91,22,154,84,243,31,182,57,170,114,94,75,115,122,166,222,8,158,56,249,14,224,156,212,210,89,27,171,233,154,100,
141,32,29,25,143,65,77,73,22,107,136,163,211,103,43,20,99,44,64,198,79,227,64,6,165,44,178,75,10,136,7,152,123,129,194,212,214,250,75,202,168,242,176,8,163,4,176,197,36,247,155,153,226,137,90,73,87,229,50,96,112,105,53,19,20,86,31,191,185,151,14,195,106,147,146,125,104,2,91,219,27,105,68,72,178,172,86,241,157,206,229,135,39,235,82,25,160,185,77,150,183,2,77,131,104,111,74,200,155,204,190,88,237,173,160,145,32,28,150,110,173,87,173,164,181,181,152,218,197,19,60,195,134,101,28,45,0,50,238,29,61,194,89,53,195,52,187,195,49,29,5,91,93,46,212,55,14,187,2,243,199,53,66,226,8,33,191,243,217,137,18,158,21,71,122,155,237,243,249,241,196,182,135,12,51,156,246,160,9,46,53,91,56,145,153,110,4,172,58,99,57,99,84,159,83,156,217,179,73,0,87,147,136,241,214,172,220,90,69,2,249,166,56,128,206,23,166,77,73,5,188,161,94,234,104,16,164,113,18,128,158,253,104,0,211,154,222,27,109,166,19,28,132,124,206,78,69,85,158,246,230,242,100,143,78,206,208,126,102,197,77,13,164,215,214,190,91,186,40,108,51,178,
140,113,233,78,180,242,45,109,230,54,119,41,44,170,8,68,95,90,0,67,111,109,53,242,197,121,112,12,170,152,100,29,42,187,67,5,197,239,217,33,183,41,111,11,242,221,216,211,109,101,54,82,97,173,214,107,167,249,153,153,186,26,120,154,238,91,73,101,186,136,197,18,28,159,44,96,158,113,138,0,183,230,233,214,115,152,190,103,114,114,21,122,26,138,230,227,79,186,212,35,142,117,125,232,115,128,56,30,212,195,121,20,54,235,60,22,108,27,162,151,237,239,86,44,172,146,24,229,191,145,68,142,192,184,7,171,55,255,0,174,128,27,173,95,71,13,155,65,109,32,137,198,48,7,222,34,170,168,63,98,9,27,148,18,16,25,187,156,245,230,163,178,179,185,186,185,107,153,225,220,242,28,144,71,2,173,1,52,254,108,112,198,71,148,196,6,110,156,122,80,5,89,118,195,45,186,68,28,170,100,158,245,96,65,112,215,38,238,121,252,164,60,35,22,218,21,125,41,246,240,194,136,211,94,206,85,63,188,127,144,2,172,221,219,216,222,249,25,111,221,167,221,255,0,106,128,33,185,210,196,151,72,100,152,125,154,4,201,220,120,30,181,86,234,242,77,
69,69,181,138,180,118,170,112,91,187,254,30,148,237,110,89,142,219,88,198,18,65,150,99,245,233,81,196,222,84,49,197,28,173,9,110,55,99,175,210,128,37,180,150,236,25,45,193,204,0,109,96,87,7,29,249,168,45,36,104,225,100,178,182,17,179,116,150,67,147,143,165,91,46,32,17,66,239,45,207,205,243,145,254,61,234,107,235,243,110,145,13,62,213,25,156,227,44,185,197,0,84,75,41,44,161,73,110,28,153,37,124,103,169,164,190,123,233,161,88,18,82,98,102,228,96,3,75,117,109,119,113,124,183,23,242,8,227,10,8,25,249,86,162,158,73,217,20,196,193,85,143,202,71,92,80,5,201,110,103,183,138,8,154,221,103,96,123,241,197,95,243,218,117,12,201,179,28,109,244,172,216,218,72,165,137,231,144,20,199,221,99,201,169,46,36,190,185,212,18,43,52,17,219,170,131,156,117,160,7,223,174,161,113,36,49,90,76,209,167,241,21,56,52,151,122,121,221,24,186,189,9,10,47,207,147,140,159,122,139,83,190,158,214,117,182,129,21,230,35,36,246,20,227,105,115,125,103,31,218,194,169,14,27,216,208,4,176,218,233,82,66,68,7,206,1,179,248,
213,8,172,87,81,187,50,51,199,144,112,35,15,247,64,173,113,4,22,176,51,179,166,64,254,30,128,85,29,6,24,36,105,26,20,66,3,31,153,186,208,5,217,34,73,64,18,46,64,57,170,154,140,169,4,209,121,113,227,35,106,140,103,30,245,76,53,254,163,118,4,91,224,141,113,192,173,13,69,190,203,106,202,210,33,152,47,5,189,104,1,182,54,241,201,20,158,99,231,156,231,190,115,86,230,150,214,209,20,134,88,212,31,188,221,205,80,211,110,140,118,229,37,42,196,140,177,11,210,155,169,89,139,183,134,79,49,118,46,126,82,113,156,208,5,171,181,139,81,136,7,147,120,251,195,7,173,81,99,13,189,202,9,85,131,109,249,99,140,114,7,173,61,109,109,108,103,73,46,164,43,33,31,44,73,201,197,62,121,45,75,25,83,105,185,101,194,238,63,206,128,31,117,125,109,4,177,132,181,146,226,93,187,128,111,151,21,94,202,222,230,234,73,174,231,185,104,11,114,66,182,208,162,173,88,91,121,50,27,139,128,23,35,46,238,122,154,169,173,95,91,201,108,150,112,50,174,247,27,202,243,199,191,227,252,168,2,221,165,132,111,125,36,209,78,178,167,25,125,
217,237,76,212,124,217,53,37,105,46,188,187,117,24,69,29,234,57,69,189,141,136,130,11,136,214,225,240,70,15,65,73,6,137,117,37,194,75,52,251,211,111,82,115,143,165,0,87,189,154,125,69,150,214,218,55,242,183,124,204,71,45,91,118,246,209,216,218,172,74,6,242,57,246,168,99,211,163,137,64,142,227,103,60,176,56,56,170,78,215,22,207,45,212,179,52,136,205,182,52,206,119,80,7,255,217);

back_vain:array[0..1219] of byte=(
255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,255,219,0,67,0,27,18,20,23,20,17,27,23,22,23,30,28,27,32,40,66,43,40,37,37,40,81,58,61,48,66,96,85,101,100,95,85,93,91,106,120,153,129,106,113,144,115,91,93,133,181,134,144,158,163,171,173,171,103,128,188,201,186,166,199,153,168,171,164,255,219,0,67,1,28,30,30,40,35,40,78,43,43,78,164,110,93,110,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,255,192,0,17,8,0,96,0,96,3,1,34,0,2,17,1,3,17,1,255,196,0,31,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,
120,121,122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250,255,196,0,31,1,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,17,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119,0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,247,
248,249,250,255,218,0,12,3,1,0,2,17,3,17,0,63,0,163,9,225,169,55,115,73,9,249,26,153,159,152,208,98,74,199,138,98,158,13,57,187,83,84,112,104,2,57,15,6,157,17,249,71,210,146,81,193,167,64,50,163,233,64,250,15,29,233,92,124,162,151,28,212,142,191,32,160,87,35,183,31,185,63,90,86,31,48,167,68,49,8,250,210,55,90,9,25,41,249,69,59,63,185,31,74,142,95,187,78,110,35,95,165,3,25,15,220,52,192,127,121,138,150,33,133,52,196,92,204,104,24,243,156,129,237,70,48,135,235,82,109,204,128,123,82,48,194,159,173,2,185,4,163,229,52,235,81,148,31,74,124,203,242,26,91,49,152,232,27,122,15,81,243,26,123,15,148,83,87,253,97,30,212,249,56,81,65,61,70,47,250,177,245,166,185,230,148,125,202,141,250,254,20,2,35,144,229,69,57,207,200,62,148,215,31,40,167,48,249,5,5,18,32,249,105,176,12,200,223,90,150,49,199,225,75,108,191,51,159,122,9,108,69,95,244,156,123,82,78,62,83,245,169,145,127,124,79,181,54,85,200,252,105,9,50,41,215,247,102,146,196,102,51,82,220,12,70,104,177,24,134,152,239,160,160,98,67,68,221,
5,57,70,102,63,74,39,29,40,23,82,17,247,113,81,191,90,149,6,65,250,211,28,114,40,26,35,144,124,163,235,78,35,43,74,227,129,78,35,17,138,7,114,84,28,126,20,235,117,193,111,173,34,30,77,62,35,140,208,67,21,87,247,134,152,227,63,157,61,91,146,106,54,110,127,26,4,133,156,101,8,162,208,1,21,50,102,224,209,3,254,238,130,173,161,47,73,51,76,156,242,41,187,254,106,100,173,210,128,72,16,240,126,180,142,121,20,212,60,26,24,242,40,24,173,208,125,41,236,63,118,41,140,120,169,79,220,20,0,136,121,53,34,156,3,81,71,247,141,59,183,227,64,135,131,214,162,99,201,250,211,199,67,81,117,207,214,129,160,157,184,52,216,79,238,233,39,232,105,33,255,0,86,62,148,21,208,92,252,212,217,137,165,238,105,178,243,138,0,34,36,161,62,244,140,78,225,75,15,250,179,245,164,35,230,20,0,230,36,10,152,19,176,84,82,14,5,77,143,221,138,4,194,30,172,105,196,243,76,132,240,212,132,243,64,137,73,249,106,53,60,26,24,240,106,53,60,26,1,9,49,235,68,103,228,31,74,100,167,131,75,25,249,71,210,130,135,122,210,75,142,41,115,214,
146,78,130,128,22,220,126,232,253,105,8,249,197,22,249,242,143,214,156,126,248,160,66,200,62,81,82,143,245,98,162,147,238,10,144,31,221,138,4,127,255,217);

back_fuzz:array[0..5054] of byte=(
255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,255,219,0,67,0,40,28,30,35,30,25,40,35,33,35,45,43,40,48,60,100,65,60,55,55,60,123,88,93,73,100,145,128,153,150,143,128,140,138,160,180,230,195,160,170,218,173,138,140,200,255,203,218,238,245,255,255,255,155,193,255,255,255,250,255,230,253,255,248,255,219,0,67,1,43,45,45,60,53,60,118,65,65,118,248,165,140,165,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,255,192,0,17,8,0,168,0,207,3,1,34,0,2,17,1,3,17,1,255,196,0,31,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,
116,117,118,119,120,121,122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250,255,196,0,31,1,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,17,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119,0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,
244,245,246,247,248,249,250,255,218,0,12,3,1,0,2,17,3,17,0,63,0,159,113,117,249,83,36,142,148,192,238,28,6,141,134,104,70,149,27,248,42,85,105,230,234,17,49,250,214,101,149,154,102,137,206,248,228,192,238,163,34,154,46,225,13,251,207,49,126,162,172,203,230,199,142,21,179,248,84,44,242,131,147,8,97,236,212,0,71,115,230,147,229,46,240,58,243,138,144,59,243,251,167,253,42,31,57,135,221,129,177,74,183,71,63,52,110,7,210,128,37,75,132,232,255,0,33,244,106,123,207,16,3,50,47,53,3,92,68,120,102,31,138,210,172,177,103,112,11,245,219,64,4,146,68,184,96,227,110,125,106,103,242,222,28,134,92,122,230,152,26,208,174,79,151,159,165,52,199,102,227,63,38,61,141,49,2,93,68,123,211,132,145,55,33,135,62,245,83,54,202,220,4,5,78,65,7,173,63,116,47,200,242,242,62,148,134,89,89,35,111,227,20,225,183,36,84,63,187,101,200,84,56,164,242,162,39,37,22,128,31,36,49,43,238,35,25,247,166,237,85,59,211,32,212,235,21,187,198,50,139,77,107,24,10,231,27,126,148,88,46,64,100,101,63,123,175,181,2,86,206,120,197,
76,150,80,133,33,135,62,230,160,146,210,101,147,17,40,100,247,52,88,46,44,151,56,108,4,114,125,169,18,228,146,85,81,131,30,204,49,81,136,46,153,255,0,213,0,126,180,246,51,163,149,40,153,160,9,188,217,207,30,82,253,119,80,198,93,188,196,63,58,137,38,153,127,129,127,58,95,58,112,115,184,55,177,20,0,255,0,222,42,252,234,63,3,77,19,162,19,230,124,163,177,52,23,124,101,200,35,233,210,160,146,88,219,31,48,52,92,44,91,23,182,236,126,241,250,226,151,237,17,183,220,203,255,0,186,57,21,12,51,197,204,99,230,29,169,234,241,140,149,192,245,160,5,104,120,6,39,218,125,206,69,10,110,208,99,247,78,63,17,65,134,80,127,119,40,219,254,208,163,109,194,255,0,28,109,255,0,1,166,4,114,93,204,3,35,66,164,251,53,71,230,206,59,33,162,100,155,126,252,3,254,237,70,124,239,249,228,212,1,58,25,100,76,237,92,122,103,145,81,188,232,173,182,78,24,117,226,155,19,202,146,103,99,128,120,228,84,175,115,19,156,62,115,208,228,82,0,19,196,71,222,90,127,218,70,220,4,103,227,248,70,105,187,45,164,231,106,147,82,36,182,
176,240,172,139,158,49,64,12,89,209,71,221,108,127,186,106,54,146,223,121,200,31,136,171,63,105,133,134,55,175,231,66,186,48,206,225,245,160,101,96,240,231,230,10,71,184,167,170,91,49,219,136,233,242,60,76,188,178,254,116,69,178,69,254,22,20,0,208,150,195,251,152,250,211,132,54,237,145,133,165,216,133,186,45,72,168,174,187,0,227,218,128,24,35,216,63,116,251,70,122,117,167,15,52,168,95,52,123,225,105,173,106,189,21,153,79,177,161,45,119,231,207,114,222,131,210,129,18,40,157,73,249,195,123,17,78,67,114,228,252,168,49,239,80,155,52,94,85,156,30,223,53,74,129,163,31,35,147,199,70,166,3,255,0,126,203,202,170,159,92,230,171,206,178,238,249,218,49,142,249,60,211,204,183,71,238,136,255,0,90,71,142,91,136,254,112,138,195,161,6,129,16,177,40,191,125,27,61,189,42,52,146,71,255,0,150,68,254,52,243,99,63,103,143,242,169,32,182,158,47,159,122,55,31,119,20,88,119,19,247,145,166,101,65,131,221,57,166,49,183,118,206,213,30,196,85,165,121,49,254,168,252,189,112,115,77,152,150,140,48,143,140,119,
235,72,8,23,203,66,89,2,140,119,2,165,12,142,185,1,78,122,243,85,188,237,191,54,214,31,240,19,82,219,205,27,157,132,2,115,145,129,64,14,11,47,79,63,143,247,5,77,228,73,142,101,31,247,205,85,95,56,182,3,253,119,47,74,181,137,87,111,33,200,252,40,2,39,119,136,237,104,154,69,254,240,165,89,153,198,68,15,255,0,124,212,205,44,129,127,212,231,232,212,197,157,255,0,231,147,175,235,76,5,87,119,200,72,155,241,226,134,44,191,242,205,189,248,205,61,175,113,214,9,143,209,106,63,183,198,24,137,18,69,24,254,36,162,194,26,207,18,242,84,3,254,237,52,220,66,59,255,0,227,180,173,115,14,62,246,71,210,163,243,227,57,195,82,24,239,54,6,251,133,79,225,77,243,173,143,63,187,169,19,99,14,25,69,47,150,171,38,90,48,212,12,139,205,183,32,227,203,205,61,99,141,211,56,21,52,112,192,73,38,37,252,69,35,218,140,230,57,29,62,157,41,216,87,35,88,98,39,30,82,254,34,157,246,120,10,156,32,31,78,41,141,109,50,156,253,164,227,253,218,88,97,144,110,12,236,196,244,61,40,1,143,100,152,200,105,20,255,0,189,78,142,38,140,
29,178,57,207,247,185,169,28,73,180,109,147,254,250,90,137,205,194,29,219,81,151,208,117,52,1,46,233,78,1,43,255,0,124,210,254,245,70,66,7,250,85,97,120,75,96,219,201,159,165,75,21,203,51,16,34,144,113,252,92,80,3,188,249,59,66,255,0,149,32,187,193,56,67,158,224,241,79,243,165,63,242,197,191,239,161,85,167,103,96,27,200,110,61,41,1,99,237,188,115,27,82,125,169,92,244,104,253,205,83,251,67,14,26,57,7,225,72,211,127,211,57,63,42,53,3,75,237,86,184,207,152,56,166,198,202,231,146,70,59,48,172,248,247,200,193,18,50,164,247,110,213,101,161,149,65,56,14,79,80,180,192,188,205,30,113,185,127,58,173,42,69,28,129,134,213,7,184,245,170,94,83,103,6,220,213,232,188,132,136,6,69,82,122,131,64,136,222,226,88,78,217,97,86,247,86,160,94,160,80,90,54,95,199,53,44,182,206,241,237,18,12,250,237,170,109,101,114,185,194,43,113,235,64,22,126,223,16,254,9,63,5,166,137,188,230,253,210,48,245,220,49,85,214,43,148,255,0,150,100,251,230,172,238,184,234,34,83,244,106,6,72,146,200,19,13,23,235,74,210,49,95,
245,77,249,138,135,205,156,117,183,35,234,194,156,146,191,59,162,43,248,208,2,25,89,122,195,39,233,78,73,15,252,242,111,90,26,116,79,188,24,127,192,77,53,110,35,45,242,191,90,64,72,241,70,231,44,129,191,10,65,20,95,119,110,41,133,99,199,92,123,102,161,120,131,157,222,115,168,244,221,76,7,188,113,3,180,146,49,219,117,70,18,16,113,188,143,248,29,57,18,46,238,36,247,99,147,83,68,176,244,216,135,240,164,3,163,142,55,79,144,146,191,90,144,180,191,194,202,71,161,20,223,43,229,253,211,109,95,65,76,62,114,231,107,228,227,163,45,48,36,119,144,31,224,228,84,27,101,50,112,51,255,0,2,169,17,167,49,252,201,30,105,12,211,171,46,109,212,227,208,208,4,77,49,80,67,35,131,219,43,74,178,79,140,152,215,254,250,167,205,52,143,202,69,131,223,113,166,43,207,159,245,67,254,250,164,3,139,205,142,34,252,218,155,230,202,20,254,231,245,165,243,101,94,176,191,225,205,57,101,200,63,187,113,255,0,1,160,6,178,74,232,15,149,255,0,143,116,168,152,84,175,150,3,230,100,5,189,41,166,221,6,55,52,114,47,228,104,29,
198,33,34,69,199,92,213,229,145,113,247,129,168,34,129,21,240,21,87,156,131,79,49,15,72,201,252,40,17,39,152,165,186,243,72,103,135,118,55,131,248,244,168,150,24,212,157,193,65,61,49,65,10,70,220,46,58,211,184,13,65,54,0,73,206,127,218,25,165,89,174,84,114,99,127,210,161,89,38,70,228,2,61,169,37,146,70,111,221,0,1,234,26,149,194,197,159,180,191,79,40,31,248,21,30,115,15,249,96,255,0,133,66,169,57,64,70,195,250,84,144,188,169,144,241,241,236,212,1,32,109,252,121,110,191,90,54,41,255,0,150,171,159,173,47,158,49,141,178,126,85,27,205,27,15,184,223,138,211,2,104,215,12,114,195,21,82,105,87,45,19,197,35,12,227,238,228,26,102,251,124,231,202,231,253,202,156,76,161,56,12,49,254,205,0,85,242,45,216,125,201,71,224,105,159,103,128,117,148,254,45,87,214,116,111,156,48,230,165,12,31,251,167,52,1,73,13,169,92,126,239,244,166,230,16,196,33,65,220,98,173,24,212,56,200,24,254,180,214,130,50,79,203,145,232,105,1,89,90,79,225,184,106,146,23,153,247,127,164,3,142,197,69,72,35,88,65,100,85,199,126,
42,28,32,147,120,92,30,180,14,197,145,230,128,62,235,126,148,201,36,149,78,60,191,161,13,64,153,136,218,132,41,252,233,140,46,24,141,204,128,122,142,180,8,119,153,38,220,152,191,35,76,55,88,31,234,164,252,169,66,206,14,4,139,248,173,49,190,213,158,124,175,214,128,36,251,90,145,247,95,63,238,211,150,229,122,252,195,240,168,80,78,122,136,255,0,58,158,9,140,74,86,96,0,237,142,104,1,237,58,58,227,229,52,27,72,36,140,96,46,105,173,246,119,57,30,89,252,5,52,199,10,252,228,113,223,29,189,233,128,137,20,104,74,140,123,243,71,146,128,100,32,161,173,224,151,12,7,226,166,162,251,60,113,156,57,108,30,159,53,32,36,42,184,233,214,144,160,28,174,71,252,10,154,201,31,105,74,123,102,153,229,74,91,2,124,142,220,80,49,210,196,251,254,89,8,90,4,47,142,37,231,221,105,74,79,218,84,63,85,165,62,114,15,186,36,207,247,58,138,0,114,25,97,201,96,29,63,233,159,90,85,187,94,166,41,64,247,74,135,237,108,135,230,142,69,250,138,113,188,76,240,31,62,152,166,34,99,123,110,235,141,192,31,122,104,153,8,60,159,202,
171,153,85,155,238,48,255,0,128,212,176,190,58,171,109,63,236,154,64,59,207,136,127,203,64,42,196,114,172,137,144,69,63,247,109,195,109,53,86,72,34,119,63,187,63,240,19,76,69,130,170,195,230,140,31,168,167,164,81,50,227,203,95,202,170,45,170,43,99,50,127,223,70,165,48,109,254,246,63,222,52,1,43,218,196,202,112,54,31,81,218,171,253,137,193,255,0,143,151,63,133,75,18,168,63,121,191,239,170,123,108,95,249,106,255,0,74,96,67,228,75,140,25,207,253,241,81,189,145,221,242,202,255,0,165,88,242,136,79,190,231,219,53,27,6,219,133,149,193,29,233,12,172,214,205,159,245,191,166,13,47,217,228,11,255,0,31,18,125,48,41,205,111,43,229,150,102,24,235,199,90,4,19,237,207,159,207,161,90,64,1,101,219,143,48,126,34,144,139,156,255,0,3,81,137,148,227,42,79,229,79,70,151,31,113,127,239,170,6,34,67,115,156,148,140,126,52,231,116,85,249,210,69,255,0,128,213,145,44,99,146,224,123,26,95,50,55,31,121,79,227,78,196,220,162,101,181,255,0,99,119,210,151,124,73,207,150,87,234,152,167,74,241,7,42,235,200,255,
0,102,143,54,34,58,254,98,144,200,92,65,33,226,95,47,217,78,51,78,88,35,67,204,174,222,161,143,21,54,232,157,113,149,168,204,81,176,225,152,125,26,128,25,36,54,251,131,108,252,42,101,129,21,79,150,10,154,99,89,100,113,112,255,0,141,32,134,233,78,22,117,35,182,69,0,63,247,170,216,218,164,122,131,64,147,13,202,184,255,0,128,231,249,84,110,103,254,226,159,248,21,9,36,161,198,232,241,238,13,3,36,145,247,160,228,241,211,229,53,19,204,21,190,98,195,30,170,106,218,31,48,97,77,41,109,167,14,8,160,69,53,186,139,119,15,207,210,180,35,113,34,171,47,166,69,51,49,228,99,4,26,25,34,110,170,62,180,196,72,240,71,33,203,32,38,171,155,72,84,227,230,25,255,0,104,211,252,181,86,4,51,129,254,245,61,161,89,23,27,155,62,185,166,4,13,17,81,132,145,215,241,205,62,63,51,202,255,0,90,204,217,246,166,189,172,160,124,179,49,255,0,120,84,72,179,36,156,56,199,168,20,134,76,168,238,115,254,77,35,69,114,24,48,218,125,136,233,79,253,238,51,230,174,61,214,133,105,193,251,200,127,10,4,70,26,228,174,55,71,187,177,
230,149,162,148,70,55,182,31,191,28,84,187,50,57,219,154,137,165,149,23,97,64,223,141,3,32,75,137,99,202,18,132,3,233,72,215,79,159,245,108,113,220,82,78,197,159,114,219,156,227,4,3,80,238,96,216,218,192,250,98,144,18,181,234,157,187,149,135,252,6,167,91,200,246,255,0,31,78,187,106,174,252,112,198,158,140,59,26,6,44,183,54,147,12,57,31,145,166,109,182,216,51,27,15,112,15,53,55,152,171,247,135,228,41,62,209,14,56,113,69,196,49,39,183,65,180,57,252,65,169,5,204,7,248,255,0,48,105,22,120,155,141,235,249,212,153,66,58,138,0,102,45,221,185,216,213,47,217,45,248,59,113,233,201,166,121,49,55,84,95,202,144,164,128,97,37,42,163,182,40,2,87,132,129,148,114,160,118,197,48,249,185,5,100,227,220,83,210,57,176,51,48,63,240,26,71,138,85,226,44,50,159,83,200,166,3,200,79,81,64,68,35,165,42,219,195,183,62,88,164,54,225,87,108,44,83,245,162,193,113,26,21,39,35,131,237,78,88,1,92,18,114,59,228,212,27,46,195,224,202,128,118,59,105,195,206,35,108,152,35,251,202,112,104,2,83,16,4,6,231,29,57,164,120,
151,110,84,184,35,168,205,55,5,113,251,215,31,141,41,222,23,11,33,252,64,160,6,188,100,244,149,199,227,77,217,40,251,147,145,255,0,1,164,253,230,71,239,14,63,10,147,203,124,113,41,252,133,32,16,125,168,40,196,234,127,224,52,41,148,114,200,140,125,65,197,71,254,146,185,199,150,227,223,138,55,220,41,230,52,252,233,129,46,36,43,183,203,94,79,247,233,128,76,142,197,99,206,58,141,221,105,209,187,147,243,199,143,161,165,123,168,98,97,187,120,255,0,128,154,0,132,223,96,156,193,32,199,90,69,189,142,98,20,35,111,236,42,79,181,192,121,220,219,125,212,213,129,18,112,216,25,245,197,2,42,155,152,137,231,229,246,61,169,99,149,21,247,43,140,213,210,1,236,63,42,106,249,110,118,148,25,29,104,176,92,60,251,113,214,69,252,106,57,146,214,126,241,150,29,57,167,202,129,248,10,8,250,85,118,142,60,115,26,241,237,64,33,18,40,148,238,79,231,79,43,198,106,6,183,133,135,76,125,13,52,90,160,31,41,127,251,232,210,25,51,34,191,85,31,136,166,136,34,255,0,158,107,249,84,98,32,27,151,147,254,250,169,60,174,127,
214,73,255,0,125,80,48,251,60,93,134,62,134,145,160,227,137,100,31,240,42,112,86,207,250,198,253,41,15,153,206,28,31,168,160,65,19,188,99,4,249,153,245,237,79,243,156,56,95,40,228,140,228,28,138,131,206,69,56,110,13,40,157,50,14,225,144,40,1,232,179,30,178,249,103,182,222,69,42,139,129,38,12,224,174,63,187,77,217,48,28,72,167,216,140,81,182,224,114,4,103,30,244,1,43,9,136,219,185,48,123,133,230,144,164,216,255,0,90,63,239,138,110,251,141,163,228,143,243,52,162,73,177,204,107,255,0,125,80,2,44,35,146,88,179,159,226,244,164,103,184,67,180,42,31,122,12,174,132,238,137,185,254,239,52,211,114,55,115,27,143,170,208,3,246,205,179,118,35,207,166,105,232,100,69,249,147,63,238,154,100,55,11,35,99,230,31,133,91,72,213,198,115,159,165,48,42,53,203,40,207,145,46,15,181,58,222,79,62,77,165,25,56,254,33,87,118,46,205,184,226,162,242,193,25,78,180,236,43,145,50,58,184,21,34,110,198,31,167,189,53,162,102,201,222,195,254,5,80,58,74,152,253,251,237,61,169,12,185,140,118,168,140,59,190,236,178,47,
208,213,86,121,251,76,217,250,10,116,77,62,112,215,24,255,0,128,10,46,133,98,83,20,168,127,227,225,255,0,33,77,242,149,199,239,126,102,238,104,34,98,126,105,119,46,59,46,41,165,37,227,108,220,123,173,3,35,251,60,106,123,143,198,145,237,208,247,113,244,106,149,163,153,191,229,170,255,0,223,53,25,75,133,60,60,109,245,90,64,2,212,2,49,44,163,254,5,82,32,149,87,106,186,241,253,229,230,153,251,241,255,0,60,143,231,82,198,37,147,248,99,31,240,35,64,15,88,36,111,188,209,227,29,118,255,0,245,233,90,217,199,70,67,248,83,132,141,20,96,72,141,245,65,154,95,181,197,192,33,135,252,6,170,194,185,17,134,109,153,253,223,21,30,210,58,142,125,170,216,184,141,215,228,59,143,165,66,207,15,89,131,41,245,193,164,208,38,55,25,227,109,68,251,146,65,136,183,41,31,173,44,203,19,0,98,184,97,142,193,186,210,71,22,223,152,200,205,199,122,67,21,154,80,255,0,113,113,245,165,45,56,60,42,227,208,154,111,158,49,150,86,3,215,105,165,75,128,122,171,227,215,109,0,47,154,227,172,77,248,17,71,159,142,177,201,255,0,
124,210,45,196,95,222,253,41,226,104,207,27,197,0,48,221,196,62,241,43,245,20,199,154,41,23,229,113,83,171,41,25,86,4,83,93,84,158,220,208,50,171,54,41,203,41,94,81,202,159,106,87,182,143,127,11,193,164,251,42,118,46,15,214,128,47,91,185,147,36,72,230,167,49,231,248,136,39,184,172,248,99,242,250,74,252,212,230,55,24,197,211,254,52,211,36,112,73,89,136,103,57,3,251,162,131,12,165,112,100,82,191,238,211,132,78,24,55,154,205,143,110,180,227,62,63,229,156,159,247,205,48,40,60,119,9,207,148,8,255,0,126,155,190,81,200,139,255,0,30,21,118,75,168,83,135,56,250,138,96,17,191,220,57,250,84,216,119,34,251,102,21,127,118,251,186,48,11,79,121,211,111,250,169,20,250,109,167,168,28,231,173,70,239,177,177,181,136,245,20,0,208,243,119,64,87,216,243,74,100,245,141,233,124,229,238,24,125,86,147,206,65,220,227,233,64,12,251,66,14,187,135,213,106,68,152,43,127,23,30,212,211,52,93,119,138,158,41,148,174,84,134,199,161,160,9,76,188,101,81,136,166,11,134,126,22,25,9,247,226,172,35,110,76,208,120,230,
168,66,47,42,13,35,252,202,69,53,131,159,184,64,252,42,6,121,208,244,67,69,192,71,64,234,85,199,214,163,88,182,12,7,99,159,90,121,105,92,244,8,127,60,210,101,134,65,92,251,138,145,139,191,103,200,192,149,245,164,12,157,135,90,40,160,5,13,206,71,229,75,242,250,10,40,160,100,111,12,76,114,99,20,162,40,192,225,113,244,162,138,0,110,215,29,10,145,239,82,5,108,118,162,138,4,50,64,83,4,2,217,234,7,106,69,185,88,219,18,68,227,234,40,162,128,46,69,58,73,25,43,208,84,47,112,21,176,199,20,81,78,226,23,237,17,147,215,52,233,99,129,200,243,2,231,222,138,40,2,25,32,139,27,163,102,30,202,230,146,52,85,232,204,115,234,217,162,138,6,57,169,148,81,72,96,87,218,135,85,28,50,103,20,81,72,3,100,102,63,148,178,99,251,173,81,226,93,227,23,18,17,158,134,138,40,184,88,151,204,156,17,153,113,143,246,105,206,174,227,153,14,254,196,81,69,49,17,108,156,31,245,192,253,86,156,169,48,234,234,223,134,40,162,128,63,255,217);


back_clouds:array[0..21191] of byte=(
255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,255,219,0,67,0,23,16,17,20,17,14,23,20,18,20,26,24,23,27,34,57,37,34,31,31,34,70,50,53,41,57,82,72,87,85,81,72,80,78,91,102,131,111,91,97,124,98,78,80,114,155,115,124,135,139,146,148,146,88,109,160,172,159,142,170,131,143,146,141,255,219,0,67,1,24,26,26,34,30,34,67,37,37,67,141,94,80,94,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,255,192,0,17,8,2,28,4,204,3,1,34,0,2,17,1,3,17,1,255,196,0,31,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,
122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250,255,196,0,31,1,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,17,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119,0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,247,248,249,
250,255,218,0,12,3,1,0,2,17,3,17,0,63,0,218,160,140,210,209,84,72,220,81,140,211,168,160,4,193,165,199,122,49,75,64,9,69,45,24,160,4,162,150,138,0,74,40,162,128,12,102,138,5,45,0,33,165,0,98,128,51,70,40,1,8,162,151,165,20,0,148,82,145,70,50,61,232,0,2,151,28,210,129,197,38,40,0,233,65,20,98,148,10,0,79,173,45,24,163,20,0,148,99,189,58,129,211,154,0,104,20,184,205,20,180,0,220,82,227,142,40,165,160,99,105,64,165,163,181,32,26,69,24,165,197,45,0,37,20,180,80,2,81,75,73,143,206,128,27,75,154,92,81,138,96,32,20,184,163,20,184,52,128,74,41,113,71,90,0,74,49,74,5,37,0,24,164,165,197,4,83,16,157,185,164,60,83,177,73,208,80,0,105,8,165,52,10,0,109,24,52,236,10,76,118,160,4,166,147,205,56,211,79,38,128,23,52,180,128,83,133,0,4,81,138,92,100,115,75,64,13,197,24,244,165,197,20,0,128,80,56,167,98,143,165,0,54,131,74,69,20,0,220,82,26,113,164,197,0,46,40,164,165,197,0,38,41,41,199,244,164,230,129,9,64,233,65,235,237,64,207,165,48,22,140,81,138,90,67,19,20,99,20,236,82,241,64,12,165,250,211,
177,70,13,0,70,199,20,155,169,228,82,109,197,0,34,156,142,148,162,148,45,46,41,12,76,102,138,118,41,8,160,8,200,38,141,188,96,212,152,163,20,1,30,218,77,166,165,192,206,104,199,181,0,71,182,148,10,126,40,197,0,52,10,49,78,197,46,63,58,0,102,218,54,211,192,162,128,24,5,46,41,216,164,160,4,232,104,197,46,40,197,0,54,129,78,199,20,98,128,19,20,98,151,20,118,160,4,164,205,59,28,81,138,0,109,40,165,197,45,0,55,20,99,20,234,49,64,13,197,33,25,167,210,99,210,128,35,42,73,160,10,146,148,15,106,0,140,45,24,201,169,49,237,65,228,116,160,8,194,81,180,83,200,163,20,1,30,202,54,138,146,140,80,3,54,210,237,200,167,227,52,99,154,0,102,59,80,23,156,211,241,70,40,1,180,117,167,96,81,143,74,0,111,52,109,226,156,58,209,244,160,4,233,69,45,24,160,4,52,152,165,199,52,184,205,0,32,167,117,20,152,163,20,0,210,163,52,155,78,106,78,212,157,232,1,180,134,156,122,83,14,105,128,211,69,45,40,90,4,55,20,155,78,51,82,96,118,163,20,1,17,6,146,166,219,158,180,133,69,0,71,140,211,113,82,133,246,163,110,59,80,
34,44,113,70,211,82,237,165,219,64,200,241,205,56,10,126,218,49,64,13,197,46,41,72,162,128,15,165,45,6,138,98,10,40,165,160,98,81,75,69,0,32,163,20,180,80,2,98,151,214,138,40,1,49,70,41,104,160,4,197,46,57,162,150,128,18,138,90,41,0,157,105,64,226,150,140,80,1,138,76,96,210,210,226,128,27,138,92,82,226,150,128,19,20,82,210,26,0,40,162,138,0,41,13,47,122,40,1,49,138,41,104,160,4,163,167,122,90,49,64,7,106,41,123,80,104,1,180,83,169,13,0,39,78,104,165,226,138,0,58,138,67,214,157,244,164,160,4,52,99,138,82,40,160,4,162,157,69,0,37,37,41,162,128,18,146,157,249,81,245,160,4,20,10,41,113,64,9,138,76,83,187,209,245,160,6,154,41,105,41,128,148,184,164,163,52,8,66,185,164,34,157,75,64,13,165,197,20,184,205,0,20,180,148,180,12,74,49,205,45,20,0,156,80,104,162,129,7,74,67,69,33,160,46,33,52,128,208,105,64,52,201,184,117,20,102,156,5,24,164,49,184,163,25,252,41,224,82,129,64,200,246,210,237,167,226,151,20,0,204,82,237,167,98,140,122,82,24,159,74,41,216,163,20,0,218,41,216,163,20,0,195,138,
92,83,177,69,0,55,20,162,151,20,80,3,104,167,81,64,13,197,24,167,81,64,9,138,49,75,75,252,232,24,220,81,138,90,92,113,64,134,98,150,151,20,180,12,105,164,197,56,209,64,13,197,24,226,157,138,49,197,0,54,140,100,82,247,162,128,18,138,92,115,70,40,16,148,98,150,140,115,64,9,218,140,102,151,233,69,0,38,40,197,58,138,0,111,67,69,59,20,99,154,6,54,140,83,177,70,40,1,184,165,199,20,180,98,128,18,142,220,82,209,64,13,199,20,1,78,163,28,208,3,113,75,75,64,247,160,4,163,222,150,138,0,76,81,218,151,20,80,2,98,147,20,234,78,244,0,152,230,140,83,168,197,0,38,40,197,45,24,160,4,197,24,167,117,162,128,27,69,46,5,47,20,0,220,81,138,118,40,197,0,48,210,17,79,199,181,33,20,8,143,28,209,138,117,24,230,128,19,28,81,75,138,94,244,0,157,168,218,51,78,199,52,1,197,0,55,111,52,98,157,138,49,64,13,219,197,46,41,216,245,163,20,0,204,115,73,138,121,164,160,6,98,140,122,211,187,210,80,2,81,69,20,196,47,122,41,40,160,5,162,147,181,20,0,180,81,69,0,20,119,162,150,129,133,20,148,80,2,209,73,69,0,47,74,51,69,
20,0,10,90,74,90,64,20,162,146,138,0,117,20,128,209,64,5,20,81,64,5,20,148,80,2,210,81,69,0,45,20,125,40,160,2,150,146,138,0,90,13,20,159,90,0,40,162,148,123,208,2,82,210,102,138,0,40,162,138,0,58,26,57,52,119,162,128,22,147,165,20,80,1,218,138,40,160,5,164,162,150,128,16,208,58,82,209,64,9,72,69,46,57,230,140,83,0,164,34,151,20,180,0,222,244,98,150,138,4,55,24,163,24,165,160,138,0,74,51,69,20,0,102,150,146,150,128,23,189,29,233,40,160,3,189,20,180,80,3,72,52,132,83,169,49,235,64,13,198,105,221,5,24,163,154,4,20,82,208,40,24,82,138,41,113,64,194,138,41,69,32,19,189,29,169,104,160,2,138,40,160,0,209,138,40,237,64,9,75,154,40,160,2,144,210,210,80,2,226,138,41,40,0,52,82,210,102,128,22,138,74,90,0,49,154,40,162,129,133,20,82,80,32,239,69,20,80,1,69,31,202,138,0,40,61,41,62,148,80,1,69,20,115,64,11,70,105,40,239,64,11,69,20,80,1,222,142,104,163,181,0,0,81,69,20,0,123,209,69,20,0,180,153,162,138,6,45,20,148,80,32,162,138,40,0,205,20,81,64,11,142,40,205,37,20,12,94,180,148,81,218,129,
7,122,40,162,128,10,51,69,29,232,24,180,10,63,149,25,160,5,164,254,84,81,64,5,2,150,146,128,22,146,150,146,128,16,210,17,78,164,160,66,82,115,75,73,64,11,210,129,235,69,20,0,82,208,41,104,1,49,71,122,40,226,128,10,41,40,237,64,5,33,165,164,52,0,148,148,180,148,192,67,73,69,20,8,94,244,81,73,64,11,252,168,162,138,0,90,74,41,104,0,162,146,150,128,10,40,163,181,3,10,40,165,239,64,5,20,148,180,0,81,208,81,75,64,0,162,138,41,0,180,80,40,160,4,162,138,40,0,163,60,209,69,0,20,81,69,0,20,81,69,0,46,104,52,148,80,2,209,69,20,0,81,69,20,0,81,69,20,0,157,105,104,20,80,1,69,39,106,40,1,104,237,69,20,0,80,122,81,75,64,5,20,81,64,5,29,168,160,80,1,71,106,40,160,3,181,20,1,69,0,20,134,150,131,64,9,218,140,98,150,138,0,78,180,157,41,104,166,33,180,184,165,197,46,5,1,97,180,10,82,40,197,0,24,163,20,162,138,67,19,20,98,148,209,64,9,70,41,212,157,40,1,40,197,45,20,192,40,162,142,212,128,40,233,69,20,0,82,210,82,230,128,14,148,116,162,138,0,74,13,20,180,0,82,81,69,0,20,96,209,69,0,20,102,138,40,
0,165,52,148,80,1,69,20,189,168,0,235,71,106,40,160,97,69,20,118,160,66,26,40,164,160,3,52,119,160,209,64,6,104,162,138,0,5,46,105,40,160,2,138,41,104,0,164,162,150,128,18,148,26,40,160,2,138,40,160,3,52,82,102,150,128,10,40,164,160,5,162,143,165,20,0,80,41,41,104,0,2,142,40,162,128,10,40,163,189,0,2,143,165,20,180,12,74,90,40,160,3,20,123,209,69,0,20,98,138,40,0,20,82,209,64,5,20,81,197,0,37,20,180,80,2,82,82,209,142,104,1,184,163,20,250,76,80,33,49,64,20,224,51,70,61,40,1,49,69,45,52,208,48,164,52,180,134,129,9,222,150,146,150,128,15,106,67,75,77,52,0,26,109,45,37,49,9,71,243,162,138,0,59,227,189,45,37,20,0,180,80,40,160,2,142,148,81,64,11,71,90,74,90,0,40,162,138,0,40,162,138,6,45,29,105,41,104,0,165,164,165,160,3,52,180,148,82,1,104,164,205,20,0,103,181,20,81,64,6,105,61,233,105,40,1,104,162,146,128,22,131,69,20,0,81,69,45,0,20,117,162,140,80,1,69,20,80,1,159,202,138,40,160,2,138,41,40,1,122,81,69,20,0,81,138,40,237,197,0,24,165,162,138,0,40,162,138,0,40,205,20,80,1,222,131,
73,71,90,0,90,74,13,20,0,26,41,51,74,49,76,5,205,39,90,40,160,5,206,58,210,26,41,122,244,164,2,82,209,64,160,2,138,90,40,1,13,20,180,148,0,82,210,81,64,11,154,74,41,13,0,45,20,218,80,105,128,189,104,164,205,25,160,5,162,154,104,205,2,29,70,105,185,52,102,128,29,69,52,26,117,3,12,81,74,40,164,2,81,129,75,69,0,37,20,81,64,5,20,81,64,5,20,81,64,11,73,69,20,0,82,230,147,235,69,0,45,25,164,162,128,15,106,74,94,212,148,0,82,119,165,164,62,212,0,180,157,105,104,52,0,81,69,20,0,81,197,20,80,1,211,138,62,180,81,64,11,73,69,20,0,180,116,162,146,128,22,146,138,40,0,162,138,40,0,162,150,138,0,74,40,162,128,22,142,180,148,80,2,210,210,82,208,48,163,20,82,208,2,80,5,20,26,0,41,105,41,104,0,205,37,20,180,0,81,69,20,0,81,70,121,162,128,10,40,164,160,5,30,212,81,218,138,0,40,239,75,73,64,6,113,73,159,74,41,40,1,115,73,239,69,20,8,76,243,73,214,150,131,210,128,18,143,173,45,37,0,45,33,162,144,208,2,82,115,65,164,166,33,105,41,104,160,4,165,162,138,0,40,162,138,0,95,74,74,40,160,2,148,117,164,165,
160,2,138,58,81,158,40,0,162,138,90,6,20,10,40,160,3,173,20,81,244,160,2,142,212,81,64,5,31,90,5,45,0,37,45,20,82,0,38,138,40,160,2,138,40,252,40,1,104,237,73,74,104,1,13,45,29,232,160,3,181,20,118,162,128,14,180,184,164,233,210,138,0,49,69,20,80,1,138,61,233,104,160,4,20,81,222,138,0,7,90,81,73,75,64,5,20,81,64,5,20,113,222,142,212,0,117,164,237,75,69,0,37,24,165,162,128,18,138,48,104,193,197,48,19,20,118,165,162,128,19,189,33,62,180,236,82,227,154,4,52,116,167,40,245,165,2,150,144,195,2,140,82,209,64,196,197,24,199,74,90,40,1,166,147,165,63,28,211,79,181,2,18,138,40,160,4,247,162,131,72,105,136,90,74,58,209,205,0,6,146,157,70,40,1,185,165,162,148,12,208,22,19,181,33,167,237,167,133,20,92,44,68,6,41,69,63,104,244,163,109,43,142,195,104,167,98,147,20,0,81,69,20,0,26,78,180,180,80,2,103,173,20,82,138,0,74,58,81,69,0,20,81,69,0,20,81,73,64,5,45,37,47,106,0,74,40,239,75,64,9,69,45,20,0,130,150,138,40,0,164,165,239,69,0,32,165,163,181,20,0,148,82,210,80,1,69,20,80,1,218,138,40,160,
2,138,40,160,3,20,180,81,64,5,20,81,64,5,20,81,64,9,75,69,20,0,180,116,20,153,165,160,97,69,20,80,1,71,90,40,160,2,138,59,209,64,5,25,162,146,128,29,73,69,20,0,188,210,82,102,138,0,90,40,163,52,0,119,165,205,39,106,74,0,118,105,58,81,73,64,5,20,153,163,52,8,90,41,59,210,230,128,19,189,45,20,80,2,80,105,104,160,4,20,211,205,63,181,52,208,3,77,37,56,211,77,49,5,20,98,140,80,1,69,20,180,0,148,82,209,64,9,69,45,20,0,148,82,209,138,0,40,165,162,129,137,75,138,41,104,1,40,165,162,144,9,69,46,105,41,128,10,59,82,210,126,52,0,82,209,69,32,10,41,104,160,4,162,150,140,80,1,138,40,165,199,231,64,9,69,45,37,0,20,99,154,90,40,1,5,47,122,41,104,1,40,199,173,46,41,49,64,7,106,41,113,69,0,37,20,98,150,128,18,138,40,160,2,131,75,73,64,10,40,162,138,0,74,74,117,38,40,0,162,150,143,194,128,18,151,241,162,150,128,19,20,184,160,81,64,196,34,147,20,255,0,173,33,160,67,113,138,95,122,40,160,2,150,147,30,244,234,6,20,10,41,104,0,165,164,237,69,32,2,51,73,138,81,75,64,17,149,164,197,73,72,105,136,143,
189,33,165,239,65,193,166,33,41,69,37,45,0,29,169,105,49,205,56,14,40,24,1,78,3,20,188,98,146,144,194,151,181,37,40,247,20,0,81,64,165,164,2,26,74,90,74,0,74,41,104,166,3,113,70,41,113,205,6,128,16,210,30,41,212,148,0,98,142,148,180,98,128,18,146,157,138,76,80,2,81,75,75,138,0,109,24,233,78,197,20,0,158,148,119,165,197,24,160,4,163,20,180,80,3,122,82,209,69,0,29,104,239,69,20,0,81,75,218,140,80,3,104,167,98,144,131,235,64,9,138,40,163,20,8,78,148,82,209,138,0,65,75,69,20,0,81,69,31,141,0,30,217,163,173,20,80,1,142,104,162,138,0,58,81,69,20,0,82,210,82,208,48,164,163,241,165,160,4,165,164,250,208,122,80,1,75,73,75,64,5,37,30,244,148,8,90,41,40,205,0,45,20,148,3,64,11,154,41,7,90,40,1,115,69,54,150,128,23,52,135,173,20,148,0,82,230,146,138,0,5,45,37,20,0,185,163,60,82,81,64,11,154,90,76,138,51,64,5,20,82,80,2,26,76,82,154,79,198,152,128,209,142,41,104,160,98,82,226,138,40,1,41,104,162,128,10,41,104,164,1,73,75,70,40,1,49,69,45,20,0,81,210,138,40,0,162,142,212,80,0,104,197,20,80,
1,69,29,168,160,2,148,31,90,5,20,0,81,138,41,104,1,58,82,245,165,162,128,19,181,20,234,76,80,2,98,142,148,190,212,80,2,81,75,75,138,0,74,90,40,160,97,138,49,75,69,0,38,41,8,165,162,128,19,28,81,138,117,20,0,223,231,69,46,40,160,4,162,131,197,20,8,81,205,37,45,24,56,226,129,137,73,74,122,81,64,130,148,83,105,69,0,58,138,74,51,138,6,45,7,165,39,74,9,160,0,154,76,209,72,104,16,102,151,173,37,45,0,40,207,106,41,5,40,52,12,90,41,59,210,208,1,75,69,45,32,1,64,228,82,82,253,40,0,164,162,138,0,110,220,210,17,138,125,4,100,83,17,15,126,41,115,74,234,106,50,27,56,197,49,15,205,56,123,83,85,9,235,79,198,41,49,161,104,205,54,140,208,49,217,162,155,75,64,11,64,164,20,80,2,246,162,140,226,138,0,5,45,37,45,32,14,244,132,82,154,13,0,54,140,82,209,76,3,181,29,233,51,69,0,46,115,73,222,131,69,0,7,173,3,189,20,80,1,158,105,105,40,160,5,20,126,52,10,13,32,12,81,70,41,113,64,13,163,20,180,83,1,40,163,189,20,0,82,230,146,138,0,40,235,75,69,0,38,41,63,10,117,4,80,3,104,165,34,129,64,13,165,197,46,41,
49,64,5,24,165,164,233,64,6,56,164,237,78,164,160,4,162,150,138,4,37,7,166,41,123,209,64,9,69,20,80,1,75,73,75,64,196,165,29,51,69,45,0,38,104,162,147,52,0,82,102,151,52,222,134,129,10,13,37,25,164,160,5,205,20,153,162,152,11,70,105,41,105,0,102,138,40,160,2,147,222,151,156,81,64,6,120,164,162,138,0,95,122,51,73,70,104,0,165,20,157,232,166,2,230,138,74,83,72,3,173,20,10,40,1,40,162,142,180,0,82,209,69,0,20,148,180,80,1,210,138,63,10,40,0,235,75,69,20,0,157,233,122,81,69,0,20,81,69,0,37,24,165,197,20,0,130,151,28,209,75,64,9,210,138,90,74,0,40,197,20,180,0,157,233,105,15,52,180,0,148,162,138,81,214,128,10,90,74,90,6,47,181,39,74,94,212,80,2,81,71,74,74,0,81,69,39,74,90,0,51,69,20,180,0,130,150,144,82,208,1,69,46,41,58,210,0,163,52,113,154,74,96,46,104,164,235,69,0,20,26,59,81,64,9,75,73,245,160,26,0,94,212,148,117,160,208,1,138,58,81,69,0,20,191,90,74,40,0,61,40,205,20,80,1,65,245,162,138,0,78,244,81,69,2,22,142,180,81,218,128,20,82,210,10,90,6,40,162,146,150,144,11,73,138,41,
104,1,40,165,164,160,2,156,105,56,163,181,2,19,28,211,72,167,154,67,64,198,210,19,75,73,76,3,52,148,125,104,160,65,138,90,74,90,6,47,122,50,105,59,81,64,11,154,90,74,90,0,5,45,37,20,128,90,40,38,147,173,0,37,20,26,74,96,45,20,148,80,2,230,144,241,75,73,64,5,45,20,80,1,74,41,41,69,0,40,163,20,10,41,0,81,75,73,64,5,20,81,64,5,37,45,20,0,98,147,20,189,168,160,4,2,138,90,59,80,1,73,75,222,138,0,76,102,140,82,208,104,1,180,119,165,52,80,2,81,154,90,41,128,148,98,138,40,0,164,2,150,148,10,0,74,74,119,122,74,0,76,81,75,73,64,0,233,71,106,41,123,208,1,138,13,20,134,128,27,70,105,105,8,160,66,102,138,82,41,48,104,1,40,237,75,73,197,48,18,151,241,164,165,160,3,233,69,37,25,160,5,162,138,40,0,162,138,74,0,90,59,81,73,237,64,11,69,37,20,0,190,244,82,82,208,1,218,129,69,37,0,45,45,54,150,128,10,49,75,69,32,18,138,90,74,0,90,90,65,69,0,20,180,148,180,0,148,180,119,162,128,10,40,165,239,64,9,69,45,20,0,81,71,214,138,0,40,160,209,64,5,37,45,20,0,81,69,20,0,10,40,162,128,10,90,74,40,1,113,74,
58,82,102,148,26,6,45,20,148,82,1,72,164,197,4,209,154,96,33,163,62,212,26,74,0,118,120,160,210,103,154,9,160,5,239,74,41,160,208,104,1,217,226,144,154,74,5,0,20,180,158,185,162,128,14,148,116,164,206,40,235,64,11,154,92,211,69,20,8,13,38,105,104,253,104,0,162,138,40,0,165,20,81,64,5,20,148,180,12,40,165,198,120,163,20,0,3,71,106,83,192,233,73,64,8,69,20,166,144,244,160,2,138,40,205,0,47,74,51,73,69,0,41,52,189,233,180,102,128,29,75,77,20,185,160,5,61,104,164,205,4,210,0,205,25,164,164,6,152,14,39,52,102,146,147,183,90,0,117,54,138,40,1,40,165,197,20,8,74,41,104,160,97,214,138,74,90,0,41,77,37,20,0,180,180,131,165,45,0,4,210,103,138,15,52,153,160,0,145,70,104,164,160,2,150,147,189,20,0,180,180,148,180,0,148,180,81,222,128,10,81,69,20,0,162,138,40,164,1,75,214,129,69,0,37,47,106,41,40,0,245,162,138,40,0,162,138,40,0,162,138,74,0,51,75,218,146,150,128,12,209,214,138,74,0,90,74,41,115,197,0,39,189,20,81,64,7,20,157,169,105,41,128,82,209,69,32,10,59,209,69,0,29,233,49,69,20,192,40,
162,138,0,90,74,41,13,0,24,165,198,41,40,160,0,138,105,165,237,73,64,132,164,197,46,49,197,24,160,4,162,138,74,96,20,81,73,64,133,165,237,214,146,138,0,51,69,20,80,48,162,138,40,16,82,118,165,162,128,14,244,81,154,40,0,162,151,181,37,3,10,90,74,40,1,69,20,82,210,1,40,162,138,0,90,41,51,75,64,5,45,37,20,0,180,81,218,140,208,1,69,20,80,1,75,73,75,64,5,20,81,64,5,20,81,64,5,20,81,218,128,10,40,162,128,10,40,232,40,250,208,1,71,106,40,160,2,150,146,150,128,10,40,163,138,6,47,90,76,81,69,0,29,169,41,104,239,64,132,20,180,148,80,1,75,222,146,138,0,41,105,62,180,80,48,165,237,72,56,162,129,5,20,81,64,5,37,47,74,40,1,40,20,189,40,160,0,81,69,45,0,20,148,184,205,6,129,133,29,168,52,180,0,162,150,154,41,126,148,128,83,73,75,73,64,8,77,33,52,26,74,98,10,40,239,69,0,45,39,122,41,113,64,196,165,20,82,80,3,168,163,52,80,0,77,37,6,146,128,22,138,74,90,0,41,71,2,147,138,51,64,5,20,81,64,5,20,148,180,0,81,69,29,232,1,40,239,75,69,0,25,162,146,138,0,117,25,164,205,33,160,7,83,77,46,104,20,0,148,
180,148,118,160,66,208,41,41,69,0,20,180,81,64,195,189,25,162,142,212,0,82,210,126,52,119,160,5,162,138,41,0,180,118,164,20,118,52,0,185,160,82,26,81,64,5,20,81,64,5,20,81,64,5,37,45,37,0,20,81,69,0,20,81,70,104,0,162,138,76,208,2,209,70,104,160,0,81,69,20,0,81,69,29,169,128,123,81,73,70,104,0,163,181,45,37,0,20,81,69,0,38,105,41,105,9,230,129,5,25,164,233,70,121,246,160,5,164,237,154,50,113,69,0,29,232,164,226,131,64,7,122,79,106,90,74,0,109,20,234,74,98,10,5,20,80,1,69,29,168,160,2,138,41,59,208,2,210,81,154,40,0,165,20,148,160,208,2,209,69,20,12,74,40,162,128,10,90,74,40,1,104,162,138,0,40,162,138,0,90,40,162,144,5,20,81,64,11,69,20,80,1,64,162,150,128,18,150,138,40,0,162,138,40,0,163,181,20,80,1,69,20,80,1,69,20,102,128,10,40,165,160,4,162,138,90,6,20,82,138,49,205,0,37,24,245,165,163,30,148,0,211,69,41,164,52,0,81,69,20,8,40,162,138,0,40,162,138,0,40,165,164,160,0,210,82,226,138,0,67,69,45,20,0,81,138,40,160,2,148,82,81,64,10,40,163,235,73,64,11,69,37,45,3,12,210,131,73,
64,160,7,100,82,102,147,235,73,64,11,158,105,40,162,129,9,74,41,113,233,75,64,13,165,165,164,160,97,69,6,129,197,0,40,233,69,37,6,128,18,138,90,74,4,37,45,20,80,1,75,72,40,160,98,209,138,40,160,4,252,40,162,138,0,41,115,73,70,104,0,165,164,165,160,0,210,81,69,0,46,41,40,162,129,5,31,74,74,40,1,104,162,138,0,41,69,37,46,104,0,165,164,165,160,97,69,20,80,1,69,20,80,1,154,40,162,128,22,129,210,138,74,0,41,105,40,160,7,10,41,1,165,207,20,128,51,73,75,214,146,128,10,58,209,248,209,64,5,20,102,138,0,40,20,81,64,5,6,138,78,105,128,180,148,102,138,0,40,163,181,20,0,81,73,69,0,45,37,25,226,142,212,0,189,168,164,164,233,64,5,25,230,138,40,16,103,154,74,40,160,2,146,138,40,1,105,40,205,33,160,5,164,162,138,96,29,232,164,165,160,2,146,138,40,16,98,138,90,79,122,6,37,25,165,52,157,40,16,102,147,52,102,129,154,0,41,115,239,73,72,40,16,250,40,20,126,52,12,83,210,146,138,40,24,81,75,69,0,37,20,180,98,128,14,212,81,69,0,20,81,69,0,20,81,69,0,20,180,157,168,164,2,247,162,138,51,64,11,69,37,20,
0,162,150,146,138,0,90,41,41,104,0,162,138,40,0,162,138,40,0,162,140,81,64,5,20,81,64,5,40,25,164,165,20,12,90,90,5,20,128,40,162,131,64,8,113,72,104,162,152,9,210,138,90,74,4,20,82,80,104,1,104,164,165,160,2,138,74,40,1,104,164,165,160,2,129,71,90,40,0,160,82,82,138,0,40,250,81,69,0,6,138,40,160,2,142,212,82,80,1,75,73,70,104,1,104,164,52,80,2,209,198,41,40,205,0,59,165,45,51,52,180,0,238,148,83,69,45,3,10,40,163,60,80,1,69,37,20,0,118,164,165,233,69,2,18,148,82,81,64,11,69,20,80,2,210,26,90,74,6,20,81,248,81,245,160,0,210,82,210,80,33,104,239,69,20,0,81,69,20,0,82,31,173,45,33,160,4,163,52,119,162,128,22,138,5,45,0,20,81,138,90,0,51,75,154,79,173,0,241,64,197,162,147,189,20,0,180,82,118,165,160,2,138,40,7,29,104,1,105,40,162,144,5,28,209,69,48,10,40,162,128,20,116,165,164,163,235,72,0,209,75,72,77,0,20,81,73,76,5,164,162,138,0,40,230,138,76,243,64,11,70,105,40,160,5,164,162,146,128,23,189,25,164,205,20,8,90,74,51,73,158,212,0,180,81,73,64,11,73,75,154,105,60,208,2,230,146,140,
210,19,64,1,162,147,52,83,16,102,150,146,140,208,1,223,138,51,73,154,59,80,2,230,147,52,153,163,52,0,180,82,102,138,0,90,83,77,20,180,0,148,82,119,165,160,4,239,71,110,40,162,129,11,75,138,65,65,52,12,92,210,211,115,64,60,208,3,168,164,205,45,0,6,138,51,69,0,45,20,82,254,52,134,37,20,82,83,16,180,81,69,3,10,74,40,239,64,11,69,20,80,1,218,129,69,29,169,0,180,82,82,208,1,75,154,65,69,0,47,210,138,59,209,210,128,10,81,73,69,0,45,20,82,226,128,10,49,205,2,150,129,137,73,78,235,73,138,0,74,90,40,197,0,45,25,164,233,69,0,46,105,164,208,105,40,16,185,52,82,3,131,75,64,5,24,163,20,80,1,73,78,20,134,128,18,138,90,74,0,40,162,143,210,128,12,226,143,173,20,80,1,69,31,74,40,0,162,151,235,72,125,168,0,162,138,40,0,165,164,162,128,10,40,235,73,64,11,239,73,214,151,173,37,0,20,81,73,154,0,90,41,51,69,0,46,105,65,166,208,13,0,59,52,180,208,105,115,138,0,92,209,154,74,40,0,205,45,37,25,160,2,131,69,25,160,2,138,74,90,0,90,41,40,160,5,205,20,153,162,128,23,52,81,69,0,37,20,81,64,5,45,2,146,128,
10,90,40,160,5,164,197,20,126,52,12,49,77,206,41,212,98,129,13,167,117,164,165,160,5,163,214,146,150,129,129,163,210,131,71,74,0,41,40,162,128,10,94,180,148,80,2,209,73,154,90,0,90,40,162,128,3,69,20,80,0,40,197,29,168,237,64,11,75,73,154,41,0,180,134,142,253,104,197,0,37,20,81,154,96,37,20,81,64,5,20,81,64,6,104,247,162,138,0,78,212,81,73,64,130,138,41,61,232,1,123,81,69,38,104,1,79,235,73,154,41,9,160,5,38,144,154,66,105,9,166,33,115,197,38,105,9,164,160,7,102,140,211,115,70,104,16,185,162,147,52,132,208,3,179,197,38,105,40,205,0,46,127,58,74,76,208,13,48,28,105,69,32,167,82,0,197,4,209,156,82,103,138,6,30,244,132,243,72,78,40,28,208,33,115,73,75,138,109,0,59,52,153,230,154,79,20,3,76,67,179,70,123,211,115,205,45,3,28,13,46,105,153,160,28,82,11,146,102,140,230,152,13,56,26,6,58,150,144,82,208,2,81,154,40,250,208,1,69,25,162,128,10,40,162,129,139,69,37,45,0,20,81,69,0,28,209,69,20,128,90,40,162,128,10,90,74,90,0,40,162,150,128,10,81,73,210,138,0,117,20,153,230,138,6,47,210,138,
41,51,64,10,105,40,237,70,104,0,235,69,45,4,112,104,1,180,153,165,164,197,2,12,81,69,20,0,103,20,10,41,127,10,0,41,104,2,138,6,33,164,34,148,154,74,4,39,74,41,105,15,210,128,1,75,210,146,150,128,10,40,165,239,64,5,39,122,90,74,0,40,162,138,0,40,160,115,73,64,11,205,37,20,99,154,0,40,162,146,128,23,235,73,138,90,76,208,2,82,209,158,104,237,197,48,10,74,40,160,5,2,150,146,138,64,45,20,81,64,7,90,41,51,64,226,128,22,142,148,148,98,128,22,129,73,75,64,11,69,39,189,45,0,20,81,69,0,20,81,69,0,20,80,40,160,5,162,146,150,128,10,40,163,60,80,0,40,162,138,6,20,81,73,64,11,69,37,20,8,90,40,235,69,3,20,210,81,154,61,104,0,162,138,40,0,163,233,69,20,8,41,123,210,80,104,24,238,104,164,205,25,160,5,164,165,163,61,168,0,162,138,40,0,163,52,82,99,154,0,94,180,180,218,90,0,9,164,163,52,148,0,102,150,147,181,40,160,0,81,70,104,52,0,82,82,154,67,64,5,33,163,52,132,138,4,45,20,153,163,60,80,1,154,76,208,105,164,211,16,185,164,205,38,105,185,160,46,59,52,153,164,205,39,122,98,22,138,78,244,102,129,
11,154,76,209,71,122,0,51,205,25,164,163,189,0,46,104,252,105,40,160,0,125,105,64,164,6,151,190,40,1,220,98,151,117,55,56,164,205,33,143,199,122,105,56,165,7,2,154,78,123,80,0,78,105,65,226,153,64,52,196,73,156,83,79,74,51,70,105,12,109,32,250,211,136,166,246,166,32,232,105,114,105,41,123,80,1,154,94,180,148,99,154,0,112,167,1,77,20,241,72,98,138,90,5,20,12,92,82,17,79,197,33,160,99,41,69,46,51,73,138,4,20,180,148,80,1,71,106,5,29,232,0,250,210,210,82,208,48,165,164,233,71,106,64,20,180,148,118,160,5,162,138,51,64,11,64,162,138,0,41,104,20,80,1,154,92,210,10,90,6,25,164,52,189,105,40,0,165,162,138,0,90,13,20,80,2,81,75,138,59,80,3,123,209,218,148,250,210,26,0,41,104,233,69,0,40,164,162,130,104,1,40,164,165,20,8,40,197,20,238,180,12,102,40,197,41,226,146,129,11,69,20,80,1,65,163,165,20,0,148,82,210,80,1,69,46,41,49,64,5,37,46,41,15,106,0,41,41,113,205,33,20,0,180,130,148,15,90,92,80,3,113,70,41,248,164,197,0,54,146,158,70,105,49,64,9,73,78,197,52,208,2,131,64,164,20,164,211,0,
162,146,151,20,0,31,90,5,20,148,0,82,210,81,210,128,29,75,77,165,205,32,22,138,76,209,64,11,69,37,29,232,1,104,164,6,140,208,2,209,77,60,209,154,0,119,106,41,58,209,197,0,45,20,153,163,60,80,2,209,73,154,1,160,5,165,237,77,205,45,0,20,180,148,117,160,5,162,146,140,243,64,5,31,74,63,10,74,0,90,51,73,75,64,5,45,37,20,0,185,165,164,163,61,168,24,185,205,20,81,64,5,20,102,140,208,2,209,73,212,209,64,5,6,142,244,157,168,0,162,138,40,16,82,138,74,40,1,104,162,144,241,64,195,38,155,147,70,113,69,2,10,74,74,90,96,25,164,207,20,134,138,4,25,166,147,70,105,164,208,33,115,77,205,20,220,211,16,236,243,70,105,185,163,181,2,29,73,154,74,94,212,12,90,59,82,103,138,74,0,90,40,239,71,108,208,1,244,162,146,138,0,118,120,163,52,218,119,106,0,51,73,248,209,222,148,10,0,76,241,71,210,151,20,163,210,128,25,69,41,160,10,0,92,82,138,58,10,66,104,0,38,147,30,148,26,40,0,163,240,162,138,0,61,40,164,163,52,0,245,250,83,197,70,13,60,116,164,52,60,82,227,52,130,157,65,64,13,47,90,74,81,72,6,247,163,20,226,
41,167,138,0,41,41,104,52,192,74,40,162,129,7,122,59,209,72,104,1,115,70,105,185,197,25,160,7,81,77,205,40,230,128,29,75,73,69,33,139,64,164,165,20,0,189,169,105,5,45,0,20,80,104,160,0,82,210,81,154,6,45,2,147,52,162,128,10,90,74,40,1,104,162,129,64,5,33,230,157,138,76,80,2,14,148,184,165,162,128,26,113,73,78,52,222,40,0,160,244,165,52,80,1,69,46,41,58,208,2,245,20,211,237,78,52,218,0,57,162,138,59,80,1,69,46,105,51,64,5,20,81,222,129,5,47,74,5,20,12,74,76,83,179,73,64,132,162,150,146,128,10,90,41,69,0,37,45,37,20,12,90,67,75,244,164,160,4,52,222,134,156,105,166,129,8,122,209,75,138,67,76,65,75,154,74,90,6,37,20,189,169,15,52,8,74,51,73,237,75,64,6,105,105,180,160,208,2,230,140,210,102,144,154,0,118,104,166,230,148,80,2,230,140,211,115,69,0,59,52,102,155,73,154,0,118,105,115,77,205,20,0,236,209,154,110,69,20,0,236,209,154,109,40,52,0,236,209,154,111,90,90,6,46,105,115,77,162,144,14,205,20,148,117,160,5,164,20,82,247,160,2,150,138,78,148,0,180,82,81,222,128,22,150,146,138,0,90,
40,20,80,48,163,189,20,80,2,209,73,71,74,0,41,123,82,81,64,5,37,45,37,2,22,146,142,244,80,2,230,144,158,180,26,74,0,9,166,154,83,214,144,154,96,38,121,165,28,210,82,138,4,24,165,35,138,13,27,169,12,110,5,68,70,13,74,125,233,164,102,153,44,135,52,83,218,54,2,163,53,68,139,70,120,164,163,52,0,185,226,140,210,116,162,128,20,82,211,115,138,94,123,208,2,209,73,69,0,56,82,113,154,1,197,25,164,49,104,205,39,122,51,205,0,58,129,73,158,40,160,9,0,226,155,180,211,199,65,74,105,12,140,169,165,237,79,198,69,1,123,154,2,196,125,232,219,154,148,45,40,74,7,98,47,46,154,84,140,241,86,49,72,71,181,23,11,21,168,6,165,41,147,81,176,42,105,147,97,57,52,82,131,158,41,8,231,20,0,162,158,41,161,106,69,90,6,135,10,90,5,46,106,74,10,90,74,90,0,90,49,145,64,165,20,0,221,180,220,83,251,209,64,12,197,6,157,72,86,128,18,144,210,145,72,105,136,105,20,134,156,70,69,55,218,129,9,154,112,52,218,40,1,224,210,230,163,20,236,208,59,142,205,25,166,19,131,75,154,0,144,26,90,140,26,120,60,82,24,180,80,58,81,64,5,20,
81,64,11,71,106,110,121,165,205,0,58,138,78,244,119,160,98,210,230,155,154,81,211,20,0,180,180,218,92,210,1,77,33,162,138,0,66,105,40,162,152,11,69,37,45,0,25,160,154,74,8,160,3,52,82,81,218,129,11,69,37,45,3,3,73,75,73,64,130,148,82,81,154,0,90,41,41,104,1,105,41,1,162,128,22,138,78,212,80,1,222,150,147,173,20,0,180,116,164,162,128,22,138,62,148,80,49,13,37,45,54,129,5,37,20,26,0,41,105,40,38,128,22,138,74,41,128,98,138,40,160,4,52,82,154,5,2,19,20,148,234,67,64,9,211,173,28,209,69,0,33,235,70,104,197,39,122,4,47,106,51,64,6,140,80,2,102,151,57,163,110,41,189,40,1,212,180,220,211,168,24,81,205,33,60,83,133,0,20,180,153,165,160,3,235,75,199,90,41,69,33,137,138,90,41,104,1,180,189,168,164,110,40,0,205,29,169,1,165,197,0,25,165,205,38,40,160,5,7,138,90,74,40,1,104,160,81,64,5,20,81,218,128,10,40,160,208,1,69,37,20,0,180,148,123,82,102,128,29,73,154,41,51,64,11,73,73,70,104,0,63,173,32,160,210,26,98,2,121,165,13,77,39,142,148,3,64,135,230,144,209,69,3,0,63,42,118,5,55,161,165,160,
3,142,245,3,41,21,49,52,195,239,66,19,33,197,39,122,123,15,74,143,189,81,34,230,138,78,244,80,33,65,165,205,52,26,90,0,92,209,154,76,209,64,11,70,105,164,243,70,104,24,236,209,73,71,122,0,117,40,166,117,230,156,13,0,74,15,20,103,173,51,56,164,206,105,14,228,160,211,197,66,26,156,27,154,67,76,152,83,170,53,52,241,72,161,104,197,20,80,49,164,83,24,102,164,205,33,20,8,128,174,13,53,170,114,185,168,217,41,220,155,13,64,115,237,83,14,149,24,76,84,139,210,134,52,58,138,40,164,48,165,205,55,181,45,0,46,105,115,77,163,233,64,14,162,154,13,58,128,10,40,205,20,0,132,115,77,167,26,76,80,2,96,82,50,210,208,40,2,50,49,77,53,41,92,211,88,83,38,195,41,65,164,162,152,135,17,72,56,162,130,121,164,49,65,230,156,41,128,243,78,20,0,250,90,110,120,163,52,138,22,150,144,26,40,0,165,205,54,150,128,23,52,180,193,78,6,128,29,71,106,64,120,160,123,80,3,191,149,39,227,73,154,40,1,212,157,232,165,160,98,81,69,38,104,16,180,180,218,90,0,41,40,205,28,80,2,210,81,69,0,20,102,138,79,231,64,6,105,122,244,166,
154,112,160,3,173,20,81,64,7,214,138,40,160,2,138,41,104,1,40,165,52,134,128,10,13,33,163,60,208,2,247,230,138,78,180,189,168,0,165,166,230,151,233,64,5,33,165,52,148,0,148,148,180,211,76,65,70,105,40,38,128,23,52,102,146,146,128,29,156,209,154,65,69,0,45,3,154,7,20,116,160,5,254,116,81,65,160,4,162,138,40,1,49,197,40,20,82,158,180,0,152,230,150,142,148,148,0,135,20,148,239,106,76,80,3,104,230,157,138,48,40,16,220,211,133,4,82,227,20,12,65,75,218,140,224,82,100,80,3,129,167,10,101,45,33,142,38,147,62,244,134,155,186,128,31,154,56,52,220,230,150,128,20,80,5,2,148,116,160,2,140,82,245,52,80,2,81,69,20,0,180,113,248,209,154,74,0,41,105,180,122,208,3,168,166,230,140,208,2,230,138,51,73,154,0,90,41,51,71,74,0,41,13,20,135,142,41,128,119,162,147,189,20,8,41,13,20,211,214,129,5,20,148,125,41,136,120,60,82,230,153,154,55,82,29,199,103,154,112,233,81,110,244,167,135,160,19,28,105,166,151,60,83,24,208,49,13,68,220,26,113,126,212,194,114,106,145,12,76,138,59,210,82,102,152,135,82,211,115,
70,113,64,14,250,210,115,73,154,51,205,32,23,52,82,82,230,152,11,69,39,106,41,0,180,160,243,72,57,226,142,212,0,185,165,205,37,29,232,24,234,80,73,52,208,120,197,42,241,131,64,19,173,60,84,64,224,83,131,10,146,209,45,20,208,105,73,164,48,205,6,154,91,20,210,244,0,254,41,41,55,82,22,166,33,220,81,77,221,75,154,0,117,20,128,210,210,24,102,150,147,52,80,2,209,73,159,210,138,0,81,74,41,188,210,131,64,14,163,181,38,104,221,197,0,45,37,25,162,128,10,49,71,74,40,1,59,83,72,167,154,105,20,1,30,14,105,13,72,71,20,198,20,201,27,71,90,8,163,20,196,2,156,13,48,208,40,2,64,105,115,76,206,5,0,210,29,199,230,138,74,80,40,24,3,75,73,69,0,46,104,205,52,154,55,10,0,125,20,221,212,185,164,49,217,165,166,211,187,80,2,209,197,37,20,0,19,69,20,80,1,69,20,80,1,69,20,148,0,180,10,74,90,0,41,62,180,180,26,0,110,57,165,20,81,64,11,69,20,3,64,5,20,81,64,5,45,54,151,181,0,45,37,20,148,0,30,180,159,206,130,125,41,59,208,2,230,142,212,159,90,15,181,0,40,250,80,13,38,104,52,0,185,160,154,110,234,9,166,33,105,
166,141,222,148,221,212,0,185,162,155,154,76,208,33,226,138,65,205,47,65,64,10,40,166,131,75,154,0,95,165,46,105,51,73,154,6,46,104,164,164,205,0,58,151,233,77,163,173,0,59,52,83,104,206,104,1,212,102,146,131,239,64,11,69,55,52,19,64,11,70,105,51,205,38,104,16,236,209,77,206,40,250,80,2,154,74,90,49,64,0,165,221,73,72,121,160,5,221,154,74,78,244,191,74,0,92,226,140,210,118,164,160,7,230,156,13,67,154,112,108,80,23,36,201,165,207,189,71,186,141,212,14,227,243,70,105,153,163,57,160,46,63,52,3,76,38,151,52,5,199,103,154,90,109,25,160,7,102,138,76,209,154,67,22,146,131,72,77,49,11,73,158,105,13,25,160,5,207,20,148,148,102,128,3,70,113,73,154,76,243,138,4,45,52,211,179,235,73,214,128,27,158,212,102,151,20,98,152,134,147,197,38,105,91,138,143,60,211,16,226,105,119,113,138,102,115,205,39,214,128,185,48,126,58,210,22,168,119,99,165,38,250,44,23,30,105,164,211,119,251,80,91,190,41,136,51,70,105,185,164,239,64,135,231,181,25,166,231,214,147,52,0,252,209,77,205,46,121,160,7,102,140,211,
104,6,129,143,205,20,218,90,0,81,75,154,109,25,237,64,15,163,233,77,207,20,160,210,1,195,52,185,166,210,230,129,142,221,138,112,106,143,60,210,231,181,1,114,93,254,244,187,253,234,28,210,19,233,74,195,185,33,122,97,144,231,138,97,38,155,154,118,21,201,195,250,210,110,201,234,42,44,210,131,197,22,11,147,6,167,131,80,3,129,79,13,72,105,147,131,78,168,148,212,148,138,16,26,90,104,233,75,218,128,22,138,74,90,0,40,162,138,0,51,197,20,134,140,208,2,230,148,53,51,52,80,4,128,142,244,185,168,193,226,151,60,10,67,31,218,138,104,52,102,128,20,245,166,145,65,60,83,75,83,16,134,144,208,79,52,210,105,136,13,37,40,25,163,28,102,129,6,120,167,10,101,56,80,3,133,45,38,120,162,144,199,10,40,6,140,208,49,173,237,76,201,169,77,70,195,6,129,48,167,41,166,211,133,0,60,28,154,112,52,193,74,41,20,62,147,154,1,226,140,208,2,209,69,37,0,45,20,81,154,0,40,162,138,0,40,163,165,20,0,28,209,69,2,128,10,76,83,169,40,0,162,138,74,0,90,40,239,73,64,11,222,138,76,209,64,11,218,154,77,20,148,0,180,148,103,154,
76,208,33,73,164,39,210,144,158,105,164,226,152,14,205,25,226,153,145,72,90,129,92,9,160,183,189,33,166,19,138,98,31,147,70,234,102,104,207,52,10,227,243,69,51,52,185,205,3,36,6,140,212,97,187,82,238,160,46,59,52,160,211,51,205,40,52,0,234,41,1,205,25,160,5,165,166,230,148,82,24,191,90,51,77,207,165,25,160,7,102,142,180,204,210,231,20,192,126,120,164,207,165,55,52,153,164,3,179,70,105,185,163,52,196,40,52,103,138,110,104,205,0,59,52,225,81,131,78,83,64,34,64,105,105,5,47,122,69,13,34,147,20,250,49,222,128,26,23,60,210,129,78,2,151,20,5,136,216,83,72,169,182,210,98,128,177,22,41,113,82,109,20,98,128,177,30,218,49,82,98,140,80,22,35,197,24,167,226,147,20,0,218,90,92,115,75,143,122,0,109,46,105,72,197,37,0,46,105,51,69,24,230,128,2,105,51,154,13,37,0,25,163,52,82,80,33,115,73,154,74,41,128,180,148,184,165,199,20,128,109,25,165,52,218,98,28,13,31,74,109,46,104,2,55,52,194,42,82,1,164,219,214,152,136,169,13,72,86,154,69,2,35,38,154,115,79,43,233,77,34,152,134,209,154,49,72,104,16,
185,164,207,52,157,232,247,160,7,102,147,57,164,162,128,29,154,92,211,40,207,20,0,252,210,131,76,13,197,40,52,12,144,80,122,83,51,75,154,0,80,105,105,160,243,78,160,3,52,102,151,28,82,98,128,23,52,185,166,227,138,59,208,49,249,165,205,50,148,82,1,217,164,167,116,166,154,0,67,76,61,105,254,244,210,51,76,4,205,40,106,103,181,20,8,151,52,229,53,8,36,26,145,121,164,52,88,83,82,3,197,66,166,164,169,45,10,41,217,168,193,167,3,64,199,81,73,154,61,232,1,105,51,64,160,208,1,73,65,52,148,8,90,41,40,160,7,82,102,144,209,154,0,120,52,132,211,115,70,104,1,73,166,158,148,81,154,0,74,81,239,72,77,0,211,16,252,82,118,164,205,25,164,48,226,154,104,99,73,154,98,28,13,40,53,30,105,119,80,23,37,205,27,170,48,212,185,164,59,146,103,52,214,25,164,221,75,186,128,19,233,74,188,210,19,73,64,15,207,60,83,129,168,179,74,26,128,185,46,105,65,244,168,193,167,131,72,98,230,151,52,220,241,75,64,197,207,20,180,220,209,64,14,162,155,154,81,64,11,65,164,205,20,0,180,82,102,140,208,2,209,222,147,181,46,104,0,160,
82,103,20,80,2,210,81,154,79,198,128,10,74,9,164,38,128,20,154,105,52,19,77,38,152,133,39,191,122,51,77,38,154,79,20,10,227,201,166,30,123,211,75,96,209,154,98,184,162,147,52,155,169,187,168,16,226,105,189,104,205,2,152,5,20,180,162,129,9,138,41,216,164,160,98,3,75,154,67,214,147,60,80,3,169,115,76,163,62,148,1,32,106,42,60,210,238,226,128,184,252,209,154,102,104,205,1,113,224,208,77,48,26,51,154,64,59,52,102,155,154,51,76,7,103,210,140,211,115,216,81,154,0,118,104,205,55,52,153,160,7,103,222,147,52,157,105,87,158,180,0,115,218,165,94,41,130,156,41,13,18,102,151,53,24,235,78,164,49,192,210,142,157,105,185,165,6,129,143,20,189,169,128,210,131,72,99,184,205,39,20,153,226,152,90,128,36,205,37,48,53,46,115,76,67,189,232,166,230,151,52,128,90,41,51,70,113,64,11,69,38,105,55,113,64,14,226,142,41,187,168,220,41,128,188,82,119,164,207,90,110,104,1,244,148,128,227,165,55,52,8,125,28,83,51,235,70,234,0,117,39,20,210,105,55,83,2,76,209,159,90,143,117,27,168,11,138,199,154,110,113,70,234,
110,104,16,250,51,76,205,46,104,16,236,210,230,153,154,51,64,199,83,72,163,119,20,19,64,132,34,152,86,164,164,224,241,76,8,138,241,76,43,86,113,145,76,42,41,220,86,32,218,115,237,65,28,244,169,118,246,165,9,64,172,68,23,138,76,123,85,141,148,133,59,209,113,216,175,142,105,49,205,79,229,208,99,192,162,226,177,6,40,29,106,93,148,194,49,64,7,90,51,64,20,119,160,5,20,225,77,165,20,0,241,159,194,131,64,165,246,160,99,104,167,82,129,156,80,2,0,105,227,138,0,197,6,144,192,243,76,38,134,226,154,91,189,2,12,210,19,147,73,154,110,238,105,136,83,138,67,73,154,1,160,7,10,122,212,99,165,72,162,129,162,101,169,71,74,132,84,128,241,82,82,20,83,169,162,157,72,96,41,105,41,104,0,207,173,28,81,69,0,33,164,165,235,205,33,239,76,3,249,81,158,105,41,40,16,180,102,146,146,128,28,77,38,105,185,164,205,2,184,236,251,211,115,205,52,154,67,76,87,31,187,154,3,84,121,163,117,1,114,93,222,244,22,168,139,82,110,162,193,114,82,105,51,81,23,226,141,212,5,201,55,82,231,214,162,221,75,186,128,185,38,123,208,91,
142,181,22,250,55,80,23,37,15,75,191,158,106,16,212,22,162,193,114,125,212,133,170,29,244,155,243,69,130,228,193,184,167,131,85,183,251,83,132,156,81,96,185,100,31,122,112,106,168,36,226,158,175,74,197,92,179,184,83,183,85,95,50,143,50,139,14,229,173,212,102,160,87,226,157,187,138,86,11,146,230,151,119,21,9,122,110,242,104,176,92,177,186,147,119,189,65,190,144,181,22,11,150,55,123,209,190,171,111,165,222,104,176,115,22,55,10,55,10,175,186,151,125,22,11,147,238,20,6,170,229,241,70,250,44,23,44,110,163,112,170,225,248,160,201,222,139,5,203,25,30,180,210,106,15,50,131,37,59,5,201,73,230,154,77,51,126,105,11,113,69,133,113,219,168,45,81,51,82,111,52,236,77,199,177,226,153,186,130,120,166,19,131,197,48,37,28,211,115,66,154,70,61,232,0,206,41,67,83,73,201,166,231,173,2,37,13,78,223,80,3,75,186,129,220,159,112,52,185,168,3,211,131,251,82,11,142,99,205,55,117,33,110,41,9,166,3,183,102,140,251,211,51,197,4,230,129,15,6,140,156,83,3,82,238,245,160,7,230,140,211,115,218,140,208,49,217,163,
52,192,212,110,160,67,243,70,105,155,168,207,173,0,60,26,50,105,187,168,205,3,29,154,119,29,234,61,220,82,110,52,128,121,60,241,78,86,0,117,168,179,218,147,117,1,114,98,222,148,224,213,0,106,112,108,10,44,23,39,205,46,225,222,161,13,75,186,149,135,114,93,212,110,247,168,183,82,111,162,193,114,109,244,187,184,170,251,233,67,154,44,23,39,221,77,45,205,71,190,147,117,22,11,147,134,165,6,160,13,75,187,138,44,59,147,110,163,117,67,190,147,127,20,88,46,76,95,29,232,223,233,80,110,163,117,22,11,147,23,247,166,239,168,139,82,22,167,97,92,156,55,20,187,184,226,171,239,163,125,22,11,147,239,20,155,248,168,11,231,154,77,198,139,5,203,59,169,55,113,80,7,52,133,141,22,11,147,111,165,221,80,238,164,221,69,133,114,109,212,155,170,61,212,155,168,11,147,110,166,22,230,153,187,20,22,160,46,63,117,25,166,102,140,208,4,153,163,53,30,104,205,0,75,154,92,212,97,169,67,80,50,64,105,13,55,52,155,168,1,212,3,77,206,105,104,1,217,244,164,60,245,164,205,25,205,0,25,231,218,164,4,117,168,79,92,210,238,226,
128,36,205,0,231,165,70,14,106,69,110,49,64,11,138,13,38,105,105,0,220,83,74,131,82,237,163,111,20,238,22,43,149,231,165,27,125,170,109,180,132,12,81,112,177,24,74,93,164,31,106,147,24,164,60,80,22,26,5,59,111,20,153,167,14,69,0,52,169,165,81,138,113,94,40,2,128,176,161,77,46,223,106,84,56,167,99,173,73,86,43,56,230,152,84,226,174,121,99,173,52,167,20,238,43,20,79,90,76,243,86,26,49,76,217,138,171,147,98,34,41,56,21,33,20,195,64,128,84,139,76,81,222,165,11,64,208,245,169,65,168,215,138,125,73,67,133,45,51,60,82,231,138,0,125,25,166,102,151,52,135,113,217,164,205,52,154,51,76,67,168,164,164,205,0,45,20,3,65,160,4,193,163,20,162,138,0,105,20,194,42,92,102,144,47,52,92,86,33,32,210,28,212,229,115,77,41,205,59,133,136,57,164,230,166,49,230,154,82,153,54,34,61,122,209,154,144,167,29,105,4,126,148,5,136,232,205,73,229,210,249,99,20,5,136,168,250,84,158,95,52,239,46,128,177,13,21,55,151,72,99,162,225,98,42,42,95,46,141,152,160,44,69,138,49,158,181,33,78,105,187,104,1,159,74,41,197,40,
197,0,54,128,105,113,65,20,0,100,210,238,226,155,140,82,226,128,30,31,20,190,103,189,71,138,7,52,5,199,239,247,165,15,81,226,138,0,147,117,27,169,157,232,205,0,63,52,110,166,103,245,163,52,0,240,212,110,166,102,140,231,173,0,63,52,110,231,173,51,52,155,168,1,251,253,233,55,243,81,150,166,150,239,64,92,147,117,33,122,140,154,9,166,43,146,111,247,165,15,80,231,60,81,186,128,185,41,106,77,213,30,115,70,234,0,144,181,27,189,106,61,217,164,221,64,18,238,165,220,5,65,186,130,216,160,46,74,91,222,147,62,245,30,123,82,102,128,37,221,70,239,122,140,26,51,64,18,238,163,119,189,69,187,181,25,160,9,119,209,188,84,59,168,205,0,76,90,147,117,71,154,3,80,4,187,189,40,221,197,71,187,38,141,217,160,9,119,81,186,163,221,75,186,128,31,154,51,81,238,165,221,64,15,200,163,53,30,234,81,72,9,65,162,152,13,46,234,6,63,62,244,132,211,73,164,221,64,135,230,147,62,180,208,212,153,160,7,238,197,27,184,197,71,186,140,241,64,18,110,25,163,117,71,154,51,154,0,147,117,27,234,60,226,147,60,80,4,155,169,67,84,
89,52,102,128,36,223,239,75,187,222,162,205,27,168,2,77,244,224,245,14,234,51,64,19,121,148,111,226,162,205,25,231,52,14,228,155,168,221,239,81,147,70,104,17,38,239,122,77,244,202,76,208,4,155,189,40,221,81,230,141,220,208,4,153,163,53,30,236,26,51,64,18,238,164,207,21,30,105,119,80,3,243,70,125,234,61,220,81,154,6,73,187,154,55,10,143,117,27,179,64,137,51,70,234,143,61,104,206,104,2,76,209,154,143,52,102,128,37,221,239,70,106,60,209,154,0,151,52,110,168,183,82,238,160,100,187,189,232,205,71,79,30,244,0,225,210,150,144,82,102,129,143,205,20,202,55,98,128,31,73,154,110,104,207,20,0,236,243,74,15,165,51,173,38,121,160,68,193,169,193,170,0,220,211,183,82,29,201,247,12,208,88,26,132,100,211,192,230,129,220,117,52,154,118,61,41,226,48,71,189,33,141,3,154,118,222,49,78,3,28,210,133,207,52,14,196,94,87,181,42,161,21,54,56,160,1,74,225,97,49,237,77,43,233,79,197,24,227,52,12,140,2,41,217,165,34,155,138,4,56,82,154,104,235,78,237,64,198,50,241,210,171,176,35,181,90,61,49,80,200,41,161,
52,86,39,181,33,25,25,28,83,202,0,114,122,208,0,231,138,162,6,199,141,220,212,194,160,200,13,138,153,90,147,4,72,5,62,152,14,105,65,164,80,204,210,231,138,96,52,180,196,59,52,185,166,118,165,52,0,236,209,158,41,153,163,119,20,5,199,131,75,154,98,156,212,138,41,0,153,165,165,197,52,208,49,217,163,52,222,212,160,208,3,135,74,41,185,163,52,0,234,74,64,104,205,0,45,33,20,185,226,147,154,0,76,81,138,51,70,123,80,2,80,104,162,129,5,47,20,148,80,1,197,20,148,10,0,94,244,83,88,246,164,207,122,96,59,20,17,77,221,75,154,0,54,210,109,165,205,46,69,0,51,102,104,219,79,160,138,2,196,123,115,70,61,169,228,113,77,239,64,134,237,164,197,60,210,17,205,48,25,138,49,78,237,65,20,8,110,41,49,78,34,147,20,0,152,163,20,245,28,82,237,160,8,176,105,8,197,78,23,52,210,128,154,2,196,57,166,231,154,151,104,164,40,58,208,34,58,105,169,182,10,60,176,104,11,16,226,147,181,78,99,20,194,184,166,22,33,239,73,154,147,103,52,210,153,233,64,134,230,151,52,187,113,73,138,0,74,41,66,230,159,229,230,129,145,159,173,
2,158,83,214,147,20,0,152,226,131,78,164,197,2,27,65,52,253,190,148,220,80,49,185,160,211,136,197,33,28,80,33,51,70,104,61,105,40,1,115,205,25,164,163,52,0,185,247,163,52,157,105,59,80,3,195,82,238,226,163,206,40,205,0,73,186,140,212,121,165,205,0,63,52,187,184,168,179,222,151,52,1,38,239,122,11,123,212,121,163,117,0,75,187,140,210,110,247,168,242,104,201,197,0,73,186,141,213,30,104,13,64,18,102,140,211,51,70,104,1,249,163,52,194,77,25,160,7,19,239,74,14,72,20,204,209,187,28,247,160,101,189,153,94,48,42,22,70,86,57,169,97,144,176,171,30,90,183,36,82,189,138,181,202,24,52,96,213,169,35,0,224,12,84,44,164,112,104,184,172,71,75,142,41,66,31,173,72,23,140,96,208,34,49,210,148,26,70,5,105,23,173,48,20,156,26,51,79,88,203,115,74,137,206,8,164,59,17,119,165,227,60,84,146,198,1,200,165,138,44,227,52,5,134,8,201,230,154,99,97,218,175,8,148,14,148,201,20,102,149,199,202,82,239,69,43,112,196,81,180,227,53,68,141,52,103,138,40,197,0,39,214,148,82,208,58,80,2,82,209,138,90,0,74,49,78,24,205,
25,20,0,152,163,6,156,49,154,90,0,102,41,64,205,59,140,81,144,40,0,219,237,78,11,72,27,52,185,164,49,69,25,164,221,73,158,104,1,244,98,144,12,211,197,0,46,0,30,244,152,239,78,35,36,82,149,192,235,72,118,35,197,41,2,156,49,138,8,160,6,128,51,210,145,135,122,112,198,105,229,120,160,44,86,207,62,212,245,60,210,136,131,30,105,222,86,41,138,195,215,165,56,123,84,106,49,197,74,189,105,20,56,122,83,212,80,5,40,21,37,11,74,41,41,194,129,133,6,138,40,24,157,232,205,46,51,69,33,5,52,245,167,82,83,0,2,148,244,162,147,61,168,1,166,163,108,154,144,243,77,61,40,17,93,134,41,134,64,163,154,150,65,158,69,64,84,16,115,84,75,24,88,19,145,210,164,86,166,109,24,197,42,154,100,147,169,165,205,70,13,59,52,138,5,167,129,198,106,53,169,1,226,128,12,123,81,75,154,76,208,3,77,39,52,227,214,146,129,0,205,72,135,154,101,40,56,160,100,148,99,52,221,212,110,164,49,113,70,40,205,27,168,1,15,20,153,205,4,138,97,235,76,67,243,70,105,153,62,180,3,235,64,18,102,140,211,115,70,104,1,221,232,166,230,151,52,128,13,
38,105,77,54,152,6,121,165,38,147,2,154,120,160,67,183,10,93,195,21,29,38,104,11,143,39,34,154,79,173,20,99,38,128,19,60,210,238,164,34,154,105,136,121,106,3,115,214,153,154,40,2,80,105,192,212,64,154,112,60,82,24,226,104,29,105,51,73,154,0,117,33,164,205,45,0,0,82,129,73,154,51,64,11,138,54,138,79,198,140,208,2,209,154,76,210,100,208,3,169,9,20,205,198,147,117,0,7,173,33,62,148,166,154,105,136,55,82,230,163,207,52,160,226,128,36,7,52,135,154,102,236,83,129,231,138,0,54,209,143,106,51,75,158,40,1,152,231,154,48,51,78,164,197,0,32,3,52,225,138,74,57,160,7,117,166,237,20,102,140,208,2,20,6,144,10,127,106,74,0,76,115,77,43,207,2,157,73,205,0,38,61,169,165,105,244,96,208,34,34,156,210,108,57,169,182,208,87,20,192,131,109,27,106,109,148,109,160,8,118,19,70,207,106,159,109,5,104,11,16,108,164,216,106,198,202,80,188,80,22,43,249,103,29,41,68,71,210,172,5,167,0,61,41,92,44,86,242,91,210,144,196,125,42,230,6,104,0,122,81,113,216,162,99,62,148,121,109,233,87,252,181,244,160,66,15,74,46,
22,40,121,103,184,167,108,56,233,87,254,204,189,232,54,227,20,92,57,89,67,97,163,203,62,149,113,163,80,58,82,4,24,162,225,98,168,136,154,95,40,213,157,184,237,64,92,253,40,184,88,171,229,154,60,179,86,188,186,107,46,13,23,11,21,182,28,80,35,99,208,85,216,225,86,251,213,42,66,131,181,23,5,18,8,16,175,24,171,56,227,165,56,32,29,40,199,21,55,45,43,12,96,49,239,81,121,101,219,39,165,73,130,205,199,21,42,165,1,107,145,249,88,28,10,10,226,166,52,194,185,165,113,216,175,36,5,189,170,31,179,178,183,90,191,138,66,128,211,184,185,70,36,123,84,3,205,52,166,26,167,198,5,49,243,154,7,98,61,153,167,34,96,80,26,156,13,2,30,7,20,210,153,167,14,180,225,235,72,162,171,219,179,114,160,84,77,110,253,133,94,38,147,34,157,201,113,70,92,144,58,158,148,205,166,180,37,198,13,84,60,28,85,38,67,68,123,77,46,195,138,118,104,45,76,68,101,72,163,4,83,243,158,105,51,64,12,193,205,47,61,233,73,81,220,15,198,154,101,65,252,67,243,160,5,230,147,39,189,52,207,24,234,115,244,52,195,58,31,255,0,93,0,75,186,141,245,
92,206,130,155,246,148,237,252,232,2,200,122,112,98,78,5,85,19,171,84,209,78,155,241,145,154,0,176,35,108,102,128,164,158,41,235,34,244,197,55,205,10,216,164,59,18,40,60,10,118,115,198,42,31,59,61,5,58,25,55,56,7,138,6,77,180,208,77,72,122,84,67,59,169,12,93,167,20,167,154,81,218,148,1,140,208,3,2,156,211,251,82,226,140,98,144,192,80,195,138,81,74,71,20,1,30,41,202,184,235,78,85,167,5,160,44,40,197,60,82,1,78,164,80,98,138,40,164,48,199,52,184,162,140,224,208,1,142,40,165,237,73,138,0,74,65,197,59,20,148,0,157,169,15,90,118,41,184,166,33,14,41,191,90,113,20,210,40,2,38,57,226,162,219,142,115,154,155,203,205,49,148,242,42,136,100,45,142,198,155,140,12,210,149,52,140,15,74,100,138,167,29,234,65,210,162,0,211,198,113,214,129,146,224,80,77,33,52,194,105,0,253,216,163,53,30,104,205,49,15,205,56,84,96,158,148,236,241,64,199,102,140,211,115,71,106,64,59,52,185,168,243,79,90,0,90,51,78,227,210,148,99,210,129,141,231,25,166,147,82,28,99,24,166,16,40,1,180,132,211,177,205,27,104,16,128,
210,230,130,164,82,5,52,0,185,165,28,210,168,245,167,128,59,80,49,152,164,61,106,66,5,33,25,164,3,49,233,75,140,210,226,148,10,0,97,20,1,78,34,144,83,1,15,20,139,214,159,128,122,210,132,6,128,176,198,231,181,70,84,154,177,179,218,147,103,25,197,23,11,21,240,69,32,28,213,131,21,2,49,158,104,184,172,65,222,150,167,242,133,11,16,235,69,199,98,17,154,80,13,88,8,190,148,187,87,174,41,92,44,87,218,104,218,213,99,106,209,129,69,199,98,190,211,72,126,149,103,104,34,154,98,25,162,225,98,10,42,95,43,6,151,202,24,167,113,88,135,20,132,123,85,129,23,173,47,148,13,43,133,138,165,78,51,64,92,213,179,16,199,74,111,148,51,210,139,135,41,85,144,142,217,166,237,56,171,190,88,35,165,33,132,99,165,59,135,41,71,105,237,70,195,138,184,96,25,226,143,36,81,113,114,148,182,154,93,167,160,171,130,1,215,20,24,7,165,23,14,82,158,15,67,75,222,172,249,34,144,195,232,40,184,88,174,41,70,42,111,39,20,121,62,212,92,44,70,49,70,41,254,89,7,161,160,35,30,198,128,35,43,75,182,165,17,31,122,120,135,61,141,23,11,
21,246,123,82,21,171,70,19,218,144,192,122,209,113,216,171,182,156,18,165,242,155,251,180,108,35,177,162,226,177,30,223,106,118,218,118,211,233,79,84,39,181,23,29,136,194,15,74,112,74,126,194,59,82,236,62,148,174,59,17,249,99,190,40,242,197,75,180,227,165,38,211,233,69,194,196,126,80,62,148,121,67,173,73,180,138,57,160,44,69,228,253,41,60,147,218,166,6,150,139,133,136,60,163,71,150,77,88,24,244,167,5,2,139,133,138,190,89,29,168,218,125,42,214,7,165,38,7,165,23,11,21,130,147,83,160,192,2,151,98,131,197,56,45,23,26,67,72,166,114,58,212,216,24,163,104,164,22,42,58,177,165,72,153,189,170,214,197,165,10,59,10,119,14,81,158,82,227,165,30,80,169,113,69,77,199,98,19,22,71,74,67,8,61,133,78,105,180,238,22,35,216,0,165,197,63,20,96,80,22,24,78,41,0,221,79,101,205,10,184,160,4,9,142,212,234,117,33,20,134,38,41,49,78,164,160,4,197,4,123,83,168,160,8,205,49,185,169,136,21,19,21,94,9,230,152,136,201,197,51,118,57,230,145,229,25,192,90,133,174,72,200,216,42,136,108,178,38,199,92,211,204,163,
28,86,75,222,200,27,2,53,52,229,184,157,185,0,1,244,162,193,204,105,135,207,173,59,32,85,24,167,115,128,79,233,79,105,27,105,230,149,135,113,110,46,146,54,193,4,253,43,62,125,65,67,124,177,147,248,210,206,198,70,170,69,9,126,153,171,72,134,201,190,217,41,228,41,20,198,158,224,229,129,53,98,40,129,3,129,154,37,131,174,9,20,8,160,215,82,231,151,63,157,48,207,33,39,230,99,248,210,188,68,177,36,99,214,147,203,101,110,57,31,74,98,212,111,154,199,169,166,238,62,181,43,196,65,233,248,211,4,102,152,15,71,57,25,169,192,61,106,16,132,17,235,86,210,38,242,242,69,33,149,102,37,73,226,163,83,147,87,37,131,114,244,61,42,180,113,18,252,10,4,56,167,238,233,99,66,24,26,190,150,219,163,229,77,34,192,51,211,20,92,98,35,144,51,154,14,73,201,169,76,120,82,66,240,59,98,163,64,75,242,56,164,50,72,213,136,233,248,213,168,163,192,4,245,166,32,224,0,42,194,140,47,53,45,141,33,172,204,20,144,122,84,63,107,0,97,144,138,152,46,225,143,90,137,160,27,185,4,138,1,150,18,88,206,62,110,190,162,167,11,145,237,
89,196,97,184,171,145,74,70,21,143,30,180,154,41,50,109,148,21,165,206,71,181,38,105,20,46,218,93,180,153,167,3,64,9,182,148,10,117,20,128,64,41,105,105,40,24,82,209,69,0,20,119,163,241,163,138,0,40,162,138,0,58,82,99,242,165,235,71,106,0,111,106,8,239,78,164,160,6,247,246,160,10,117,40,20,0,129,71,165,33,80,123,83,168,237,64,16,180,96,118,166,50,15,74,157,186,84,77,76,150,136,89,41,48,41,230,153,84,73,25,166,154,155,203,61,232,242,104,21,136,41,70,106,113,15,173,2,37,167,113,88,137,65,52,237,167,181,76,34,2,141,131,52,174,59,16,237,52,96,142,181,56,65,72,84,30,49,69,194,196,20,225,197,43,38,58,82,109,56,166,33,219,168,221,81,158,59,209,147,64,92,152,26,56,168,129,167,103,222,144,238,63,28,210,138,102,113,64,52,12,127,20,112,41,185,163,52,0,226,69,38,234,76,210,26,0,120,34,157,81,102,151,117,43,5,201,14,41,48,61,105,187,168,6,129,220,127,20,187,69,70,90,149,91,154,0,120,95,76,83,130,208,166,134,227,154,67,29,142,104,2,163,222,115,214,141,230,128,185,33,166,156,83,55,209,187,214,
128,184,252,210,102,154,90,144,154,98,185,39,90,13,68,31,6,157,186,139,5,199,113,75,197,68,91,154,79,51,158,180,88,46,77,184,98,141,235,235,80,23,247,166,134,162,193,204,90,46,190,180,117,233,85,131,123,212,202,220,10,44,52,238,63,52,160,211,71,52,252,82,24,102,138,80,41,8,197,33,137,72,78,104,126,57,20,192,121,166,33,217,160,26,67,197,38,104,16,252,210,22,166,110,164,221,78,193,114,76,210,100,26,102,105,55,80,43,143,207,189,25,20,204,250,210,110,247,160,46,73,145,70,225,81,238,164,205,22,21,201,132,139,142,105,124,229,170,197,189,233,165,168,176,115,23,68,138,71,90,112,113,138,161,188,142,132,210,137,88,119,163,148,124,197,226,234,15,56,20,110,83,200,197,80,50,147,212,211,132,196,119,163,148,57,139,163,111,181,25,227,138,170,146,147,222,166,15,197,43,20,153,33,193,233,70,105,161,168,205,32,28,56,164,205,52,190,41,190,96,199,90,118,11,143,44,42,7,108,26,26,64,123,212,108,244,210,37,177,219,233,67,212,5,185,167,43,83,177,55,38,15,235,75,230,10,136,154,6,77,22,29,201,131,131,210,
157,222,163,85,252,234,96,41,50,144,160,123,211,133,32,233,74,42,74,10,74,90,76,208,1,222,156,41,5,45,0,45,55,52,180,218,0,90,74,92,211,123,154,0,112,163,191,52,82,224,80,2,98,140,83,169,40,0,237,72,105,105,15,52,0,148,180,148,10,0,92,116,163,6,150,138,0,141,137,232,42,61,190,213,54,41,54,113,76,69,102,78,56,21,4,176,29,166,175,20,230,144,198,13,59,138,198,73,128,168,206,51,74,138,73,28,28,122,86,161,129,8,233,77,88,0,63,116,81,204,46,82,21,141,66,240,162,153,229,177,36,227,138,188,35,80,58,82,249,107,233,74,227,229,49,230,132,171,103,24,168,226,128,185,201,28,86,172,209,171,113,183,53,18,196,1,192,20,249,133,202,64,177,237,232,41,207,9,35,56,169,66,157,216,237,83,237,4,99,20,92,44,101,253,152,51,100,129,239,74,214,232,58,0,42,251,68,185,56,233,80,201,22,79,4,209,204,46,83,56,197,146,69,57,45,199,4,129,86,12,36,116,205,79,20,60,116,230,159,48,185,74,70,1,191,56,25,169,2,99,0,244,244,171,158,64,193,200,230,163,48,146,212,92,44,85,104,203,100,14,63,173,73,5,147,110,7,104,235,87,
34,181,29,91,57,171,42,129,122,10,27,26,137,16,128,12,113,197,63,202,80,62,232,169,6,104,34,166,229,216,132,196,10,144,5,64,45,2,156,145,87,7,2,145,142,69,23,21,145,88,160,90,104,52,249,57,52,221,160,15,122,98,29,30,0,167,48,24,61,233,138,8,60,83,246,147,64,21,157,78,9,164,66,113,205,88,104,243,193,166,249,120,61,13,59,138,195,18,86,83,198,126,149,58,200,27,216,212,98,48,15,74,93,164,114,41,12,152,30,212,241,140,212,81,146,126,240,197,76,23,189,34,144,180,185,162,146,144,199,102,143,195,154,74,7,90,0,94,212,82,210,26,0,40,160,210,80,0,104,20,81,64,11,154,59,210,80,122,208,2,210,102,147,52,134,128,29,158,40,205,55,60,82,19,64,15,39,154,9,166,110,52,114,104,16,226,69,68,230,159,131,76,101,38,152,50,38,168,205,74,80,211,124,179,232,106,136,39,60,82,102,154,90,144,181,33,142,45,154,76,250,83,115,71,61,169,138,227,179,235,77,45,205,24,38,154,192,230,129,14,221,72,90,163,201,167,40,38,152,174,59,52,102,147,6,138,67,14,166,154,69,56,80,72,166,4,103,173,0,226,149,135,113,76,193,160,67,
179,75,154,103,56,160,19,64,15,6,151,52,202,94,104,1,217,163,117,55,52,3,64,11,158,104,205,24,207,74,124,104,9,230,128,17,84,147,210,158,195,109,76,170,0,233,80,205,157,213,59,151,107,33,133,197,57,92,84,120,52,116,166,77,203,1,198,41,25,234,0,220,245,165,45,69,135,113,251,187,210,22,166,111,247,164,206,104,21,199,238,165,221,234,105,155,88,158,5,52,150,206,49,76,9,11,251,211,75,212,109,184,30,105,62,99,219,52,88,87,36,45,71,153,81,252,222,244,153,166,43,146,249,156,83,75,3,76,163,181,1,114,64,194,151,60,84,98,157,154,0,120,53,52,103,229,197,86,205,79,1,205,75,42,47,82,194,138,112,160,116,165,21,6,162,138,13,20,26,0,141,234,62,135,154,145,206,42,187,191,207,210,154,37,146,22,197,55,52,96,158,156,210,133,227,165,49,12,99,205,55,118,42,115,26,227,154,137,226,57,227,56,167,113,52,196,221,199,90,55,83,88,21,250,82,41,207,113,64,135,19,73,154,126,208,105,165,40,11,13,205,5,170,68,143,117,61,161,80,51,69,194,204,171,156,244,163,161,165,218,67,224,83,194,10,98,177,30,105,185,230,158,
209,158,212,205,188,208,38,57,65,61,41,226,38,35,138,84,3,167,165,88,84,205,38,202,72,100,104,64,233,82,129,140,113,74,5,41,21,55,52,72,110,57,163,154,118,40,2,128,35,97,235,81,182,7,108,85,130,56,233,81,74,190,212,33,52,86,35,52,152,61,234,102,76,14,148,128,3,201,170,185,22,35,219,73,140,30,42,66,48,106,51,156,211,1,64,36,212,177,169,3,20,197,60,84,241,245,164,198,135,109,56,167,10,119,20,99,154,146,197,31,74,40,20,180,134,37,38,41,221,168,160,4,239,70,77,45,33,160,4,52,156,211,169,13,0,33,165,80,113,69,40,52,0,83,133,37,20,0,191,133,20,81,138,0,41,167,165,47,62,180,210,222,244,0,159,141,0,226,144,184,20,128,231,173,2,31,158,105,212,213,233,78,205,3,12,81,64,57,20,98,128,19,169,163,109,59,28,209,237,64,5,38,61,41,123,81,64,8,61,232,34,150,144,208,3,8,166,21,197,77,138,105,25,237,64,17,5,0,116,165,167,98,144,138,4,48,130,71,2,148,71,211,138,120,6,157,138,0,140,198,15,80,41,219,58,113,79,197,40,20,12,140,161,161,19,3,145,205,73,138,90,0,64,41,113,69,20,0,82,30,105,105,40,1,13,
68,224,156,226,165,52,210,6,104,2,0,167,28,142,105,54,122,212,228,117,166,149,205,50,108,49,82,165,3,218,148,1,75,64,236,55,30,212,148,239,106,78,148,128,110,51,73,140,83,240,40,197,48,24,70,7,20,43,144,125,169,113,76,97,142,148,1,48,112,79,20,234,172,172,119,123,212,202,254,180,5,199,210,230,155,154,92,241,72,98,209,73,154,51,64,11,73,70,104,205,0,24,162,147,181,25,160,5,162,155,186,141,212,0,234,8,166,238,163,121,160,67,182,209,178,152,101,34,154,101,57,166,23,68,187,70,40,24,21,15,154,212,158,105,61,232,176,93,19,241,72,72,168,195,209,191,222,139,5,199,16,13,38,61,41,187,168,223,64,136,3,82,158,122,83,6,239,74,120,7,210,168,129,64,24,167,3,233,205,51,154,124,64,150,230,129,161,121,61,177,74,19,34,165,10,61,41,113,142,149,55,42,196,34,46,244,240,184,21,38,56,164,56,162,227,177,11,12,84,44,72,106,176,252,212,76,132,211,68,200,143,52,19,75,177,135,106,66,141,84,64,132,210,82,236,97,218,141,141,233,64,8,113,64,198,40,216,212,121,109,64,7,20,188,26,4,76,125,105,194,22,160,6,244,
233,74,42,65,15,185,165,17,96,245,165,113,217,145,212,145,100,183,29,169,226,17,79,72,194,244,165,114,146,20,103,20,201,23,140,212,180,210,50,41,20,202,217,166,183,74,152,197,207,90,107,68,123,100,213,92,134,153,93,169,181,63,146,199,168,167,44,24,63,48,167,114,108,202,216,169,146,48,123,243,83,136,20,158,148,245,137,84,112,42,91,41,68,21,70,49,72,98,4,230,159,140,14,40,164,93,136,124,157,205,147,210,151,200,24,249,106,80,49,74,40,184,89,21,154,34,51,85,101,30,89,203,28,15,122,211,34,168,222,197,27,129,230,103,3,223,20,211,38,81,40,77,121,12,127,197,184,250,47,53,92,234,77,159,150,49,143,115,85,38,93,146,144,57,231,138,122,218,202,232,25,16,145,244,173,12,139,41,169,31,227,143,241,6,164,254,209,135,25,195,103,211,21,154,232,241,182,25,72,250,211,115,235,76,70,228,82,249,168,25,84,213,235,114,51,211,21,143,167,220,128,187,27,21,177,22,7,34,179,145,164,75,52,189,233,163,165,56,116,168,53,20,254,84,30,148,189,69,38,5,0,70,192,211,54,119,169,200,20,210,49,210,129,88,140,12,30,41,
224,82,226,151,20,12,111,90,66,185,52,240,56,160,208,5,118,136,16,70,42,56,237,2,243,154,183,138,0,167,113,88,139,203,2,129,31,53,41,233,73,140,80,22,17,70,56,165,97,145,64,20,224,61,105,12,128,69,207,52,227,23,21,54,5,24,167,113,88,168,209,145,197,48,70,89,170,217,28,208,168,7,74,46,46,82,53,136,45,72,7,24,167,109,163,28,82,29,132,160,226,148,82,99,241,160,98,12,145,79,2,133,226,150,128,16,138,99,12,158,105,244,211,64,16,237,38,144,38,5,72,6,40,197,50,108,68,192,115,85,216,243,86,89,121,168,132,89,108,154,164,75,64,131,138,153,70,40,84,24,233,154,126,61,5,38,198,144,229,57,20,234,96,233,78,169,44,92,210,245,166,226,148,116,160,5,164,205,41,246,164,160,2,138,41,69,0,52,210,102,156,105,148,0,110,165,205,38,61,41,104,1,244,80,40,207,52,0,81,69,7,173,0,50,67,197,66,121,239,82,189,69,140,243,64,133,200,2,156,164,122,211,113,145,74,6,13,0,72,166,159,81,14,41,249,205,3,22,157,73,74,40,0,162,138,40,24,163,173,20,148,80,1,248,82,83,169,13,0,52,245,163,181,41,163,52,8,101,24,165,163,52,
0,160,81,212,208,57,165,226,128,0,41,104,20,80,2,210,81,69,0,20,81,65,52,0,82,119,162,138,0,67,77,237,78,205,52,208,3,78,104,90,40,160,67,168,164,29,41,192,122,208,49,49,205,32,6,157,218,138,0,111,122,13,46,57,163,189,0,49,169,135,3,173,72,106,55,25,20,196,52,16,77,61,77,70,6,58,83,198,120,160,67,193,2,157,186,152,40,160,100,128,209,192,230,163,221,75,187,60,80,3,243,154,105,106,105,106,105,110,104,11,143,7,158,180,187,133,69,186,141,212,10,228,153,30,180,160,212,99,173,63,181,3,23,35,110,106,38,117,7,173,41,63,41,170,206,79,74,104,77,142,123,152,243,212,212,127,106,76,116,53,4,136,114,113,80,140,150,197,81,23,46,125,169,125,26,156,39,7,248,127,90,134,40,195,30,69,90,16,168,3,138,64,174,39,158,160,82,137,179,208,84,77,17,207,29,41,140,254,81,198,51,64,22,119,81,184,213,101,185,140,156,22,10,125,234,112,73,28,12,138,2,230,108,90,164,145,168,86,64,248,238,79,53,102,61,94,35,254,177,25,125,199,53,90,222,195,205,102,18,110,4,116,171,50,105,145,121,31,46,67,40,234,59,213,59,9,115,
22,35,212,45,228,32,43,28,251,173,91,136,135,27,135,74,205,178,178,88,254,111,188,79,168,173,72,212,42,128,6,42,29,139,141,250,143,165,197,20,84,150,33,224,83,72,38,159,218,140,80,4,68,28,83,79,21,49,90,66,128,142,105,138,196,4,241,72,13,77,229,131,72,209,128,56,20,92,86,33,12,11,21,29,106,189,210,201,28,14,254,102,15,80,6,106,224,64,59,82,60,75,32,33,198,69,59,138,198,37,172,115,79,185,153,219,25,235,154,176,37,150,199,37,219,204,140,159,83,145,87,154,53,138,22,8,58,244,21,145,116,146,49,59,183,99,60,10,171,220,134,172,105,219,222,195,58,229,88,131,220,17,83,27,152,148,128,91,244,53,206,44,78,91,1,9,231,210,173,193,6,8,222,164,115,223,189,22,67,77,154,178,95,64,159,121,206,125,0,53,44,51,172,184,42,14,15,173,86,138,214,22,80,74,2,106,220,48,170,116,21,46,197,43,146,143,106,119,122,65,75,82,88,99,189,38,51,75,69,0,55,20,133,246,14,123,211,156,100,16,14,42,32,155,71,115,207,83,64,134,77,36,172,167,203,10,61,205,22,190,105,4,204,65,61,177,82,227,138,112,24,166,22,23,218,151,52,
148,148,134,45,29,40,200,20,153,197,0,41,28,80,41,51,197,20,0,189,106,11,136,124,194,42,106,8,160,12,171,187,16,228,48,198,239,165,75,99,22,216,200,35,161,233,87,88,12,114,42,60,128,223,45,85,201,182,166,110,163,107,185,119,22,199,53,146,209,97,182,142,107,165,184,229,48,6,107,22,240,162,63,202,0,106,168,178,36,136,32,7,126,5,111,218,12,40,205,99,89,197,230,73,146,14,49,91,113,13,170,49,158,41,72,34,90,20,225,81,169,205,60,116,168,53,29,69,20,80,0,41,58,209,218,138,0,58,82,230,146,146,128,29,218,144,138,5,20,0,152,197,46,49,75,71,122,0,65,72,70,105,212,148,0,1,138,90,40,160,2,142,212,81,64,8,121,160,12,82,154,74,0,58,81,70,113,71,122,0,65,210,150,146,151,189,0,29,41,105,57,165,160,4,166,154,113,166,145,64,13,200,205,46,65,164,163,20,0,215,56,166,239,246,21,38,220,211,118,226,129,0,39,20,185,163,20,160,1,64,10,180,234,110,105,212,12,59,209,222,138,40,0,163,173,20,10,0,40,165,163,165,0,53,169,180,252,83,72,160,2,129,69,40,226,128,22,142,162,140,209,138,0,92,247,163,181,37,53,137,
31,90,0,82,41,140,41,166,67,222,131,37,0,40,20,236,129,80,249,190,166,148,54,122,208,34,66,105,84,212,96,142,42,65,210,129,143,29,41,114,105,160,241,75,64,11,154,92,241,73,218,138,0,94,244,10,51,71,210,129,133,20,159,206,142,104,16,83,73,165,38,152,192,208,0,13,35,84,97,142,236,84,139,147,64,15,94,5,58,155,74,40,1,212,82,81,64,5,40,164,165,160,2,131,69,33,52,0,18,41,9,164,38,152,205,197,0,59,117,33,53,8,147,154,126,234,0,126,105,132,156,240,41,11,82,169,205,2,28,14,13,56,30,41,166,147,52,12,126,121,163,189,52,154,76,208,3,251,226,148,245,164,162,128,16,250,211,14,41,198,154,104,1,189,233,113,249,82,237,245,160,12,80,33,212,218,118,105,164,211,1,9,166,231,154,13,39,57,246,160,66,211,75,1,65,233,214,161,115,207,20,1,32,52,19,205,55,160,164,4,231,165,2,177,42,158,245,38,73,21,1,98,13,74,167,34,129,136,221,42,38,35,56,167,49,98,120,20,42,30,249,160,44,66,224,145,182,162,91,102,221,198,49,87,149,1,28,138,147,104,3,165,59,138,196,81,199,140,84,196,98,133,24,166,51,115,72,162,57,65,
35,173,82,159,165,92,115,154,165,63,67,84,136,101,41,8,205,49,103,145,6,21,136,30,198,164,117,199,52,139,110,238,187,148,28,26,179,59,29,8,78,115,79,11,129,64,167,86,38,227,74,227,165,56,112,41,41,104,24,180,180,153,226,140,208,2,210,211,115,69,0,45,29,168,164,52,0,102,144,154,13,52,208,0,198,147,57,20,215,165,83,242,208,32,96,58,154,169,116,200,71,43,248,226,173,17,185,113,81,180,33,134,58,208,5,123,88,212,242,9,197,79,228,41,111,90,124,113,132,80,0,169,0,231,145,76,6,199,24,94,149,40,226,144,82,247,164,49,69,47,122,109,25,160,7,81,154,110,105,104,1,105,164,82,230,138,0,65,70,104,38,147,52,0,82,138,65,131,65,160,0,154,64,69,70,228,246,52,129,177,223,243,160,68,216,165,168,196,158,180,162,65,142,162,129,146,1,138,41,161,179,72,91,29,104,0,112,42,33,128,115,77,121,246,18,88,128,42,140,247,161,101,25,35,105,160,69,139,171,149,139,28,18,79,65,85,222,196,92,201,230,57,235,216,85,59,119,121,111,12,143,150,28,224,26,218,143,158,212,211,19,68,49,91,121,107,182,172,170,113,138,112,199,
165,56,125,40,184,210,0,49,78,6,155,156,82,230,144,199,82,211,65,165,6,128,23,52,81,218,146,128,10,5,33,52,10,0,112,235,69,32,205,25,160,5,237,71,181,38,104,253,40,1,104,235,73,75,64,5,25,230,138,40,0,165,164,163,52,0,81,69,25,160,2,138,78,212,102,128,10,40,160,80,1,69,20,19,64,11,73,214,138,13,0,37,20,19,77,52,0,224,40,35,20,128,208,122,208,2,19,64,52,126,20,148,0,236,247,165,164,165,28,117,160,5,160,115,73,154,57,237,64,11,69,38,105,104,1,104,164,163,138,0,15,20,26,41,13,0,37,45,37,25,160,7,122,81,154,76,251,211,119,80,3,179,76,115,129,75,154,107,17,64,16,150,238,105,164,130,120,205,72,113,232,42,22,56,57,6,129,13,118,195,243,197,57,36,166,59,100,210,41,239,64,22,65,200,226,158,172,106,20,36,243,83,3,64,15,6,158,41,139,78,160,99,168,205,55,189,25,160,7,103,210,140,243,76,205,46,104,1,217,165,164,205,20,0,180,214,20,234,78,212,1,17,79,155,52,234,118,40,197,0,3,165,47,106,74,90,0,90,41,40,160,5,164,205,25,164,160,5,38,152,205,77,103,247,170,237,42,131,243,30,104,2,208,57,166,
55,74,136,77,199,90,134,73,206,14,13,2,18,89,54,103,142,5,9,56,98,49,154,172,101,102,110,115,131,83,66,169,193,7,38,128,45,2,8,20,244,192,168,148,129,192,230,158,9,160,9,9,164,220,58,82,100,154,76,123,208,3,243,158,40,199,57,160,116,167,80,48,7,154,82,105,162,138,0,59,243,69,39,57,165,197,2,18,140,208,105,164,208,1,154,110,115,210,161,150,93,157,233,169,33,61,232,2,193,52,132,230,163,223,244,52,224,217,20,0,23,200,192,168,137,231,29,234,76,128,115,77,60,231,29,104,1,11,0,57,205,34,182,70,69,59,1,135,52,121,96,46,0,160,4,200,21,34,14,156,211,85,121,228,84,170,184,160,5,43,78,3,138,112,198,41,24,140,80,2,103,154,55,210,126,20,211,64,15,221,154,141,232,220,64,166,151,205,0,35,176,21,16,140,51,110,62,181,38,6,115,78,207,106,98,3,10,184,193,3,31,74,149,80,42,128,0,226,149,71,25,167,80,59,11,78,237,77,20,180,134,45,25,197,37,33,160,5,205,40,52,209,75,154,0,117,20,128,210,208,0,77,0,210,119,165,233,64,5,4,102,140,208,14,104,1,172,158,244,152,192,167,19,233,71,214,128,26,41,113,71,57,
226,150,128,12,10,90,74,5,0,45,33,165,162,128,18,138,90,5,0,20,26,51,205,39,90,0,92,209,154,78,148,80,1,72,104,52,152,160,5,207,20,135,165,20,160,80,4,69,50,121,226,151,103,106,151,20,99,138,0,129,151,6,161,145,152,30,149,112,168,164,216,15,106,0,175,24,112,193,135,32,246,169,243,210,156,20,10,49,147,64,17,77,16,116,195,116,172,139,205,56,158,141,192,252,197,110,17,197,49,163,13,212,80,6,77,133,178,199,213,139,17,223,21,168,163,229,164,75,117,95,186,49,83,5,197,0,34,211,168,164,160,3,233,73,210,157,70,40,1,41,65,227,20,98,138,0,90,5,20,80,2,117,165,164,162,128,23,52,19,73,69,0,40,165,205,54,138,0,112,52,102,144,81,214,129,139,156,209,154,74,40,16,102,151,52,148,153,160,5,205,30,180,153,164,205,0,58,140,211,115,75,64,11,210,128,105,51,70,104,1,115,71,122,67,64,160,5,162,146,138,0,51,73,70,105,40,0,205,59,181,55,189,45,0,20,118,163,52,80,1,154,90,111,126,41,69,0,45,40,164,160,80,2,230,138,64,104,160,5,205,33,52,116,160,208,1,154,51,77,205,33,230,128,20,181,46,105,6,59,209,64,9,
158,104,206,40,53,19,48,6,128,28,210,84,76,231,52,164,131,210,147,30,212,128,137,201,165,197,72,69,38,13,0,70,83,119,52,4,60,84,225,122,82,237,226,128,26,188,10,119,61,168,0,210,142,59,208,3,215,129,79,205,66,88,244,20,229,7,3,39,154,0,147,52,157,232,163,147,76,5,2,148,82,10,90,0,90,51,73,70,104,24,236,241,69,37,25,160,5,160,210,102,138,0,90,67,69,29,233,0,82,82,230,146,152,132,247,166,153,2,245,164,114,123,84,50,103,20,128,138,89,254,98,0,170,236,197,206,74,244,169,194,113,239,72,84,1,199,90,0,141,165,249,48,1,205,48,149,100,247,61,169,25,88,183,181,63,203,226,128,34,94,14,5,89,68,7,29,141,71,229,17,86,20,112,40,1,203,31,21,39,65,197,55,56,233,70,252,241,64,14,39,138,1,163,140,82,98,152,15,83,198,105,249,166,40,167,1,64,14,197,24,165,164,160,3,28,81,70,105,104,1,135,173,70,216,230,165,34,161,96,121,160,10,178,174,243,140,247,164,8,71,124,212,225,50,221,41,251,71,76,82,2,20,92,113,222,164,3,156,83,246,129,78,3,138,96,66,203,201,161,71,106,148,175,20,5,246,160,6,133,199,52,153,
201,169,74,251,83,118,96,208,2,83,151,168,52,99,154,112,24,20,0,180,134,148,211,40,1,122,83,72,244,167,98,146,128,27,130,79,94,41,140,57,226,158,78,41,8,226,128,26,0,227,214,165,0,83,64,167,129,64,135,10,92,82,10,81,64,199,82,210,10,15,74,0,41,15,90,51,72,104,1,104,164,20,225,214,128,1,75,65,226,138,0,40,160,245,162,128,10,40,20,80,1,70,40,60,82,14,104,1,122,82,80,104,233,138,0,7,94,105,212,152,201,163,20,0,164,210,117,164,234,105,69,0,45,20,98,129,64,5,3,154,90,40,1,8,164,198,41,199,173,7,173,0,54,154,122,211,233,13,0,32,25,20,160,98,149,105,123,80,2,81,138,92,80,40,1,58,208,120,165,20,26,0,74,49,69,56,28,208,2,17,73,142,41,212,80,49,184,162,157,73,64,132,20,17,69,45,0,38,51,64,24,162,151,189,3,12,82,98,148,244,165,197,32,26,104,165,162,128,19,20,80,41,123,83,1,166,138,90,94,244,0,148,80,57,164,60,80,2,210,126,52,3,210,150,129,9,69,20,135,168,160,5,226,146,148,117,163,20,0,222,180,184,52,119,167,118,160,6,98,151,165,45,40,20,0,222,212,14,148,180,160,115,64,13,233,75,64,160,245,
160,4,207,173,25,20,81,214,128,23,138,67,64,20,98,128,18,151,173,2,138,0,40,20,118,160,80,1,75,69,20,0,148,162,138,65,197,0,59,20,148,160,228,80,105,12,76,209,65,235,72,104,16,132,102,128,180,180,162,129,137,138,49,75,67,14,104,2,54,56,168,89,119,28,212,206,41,8,197,0,70,171,237,79,11,154,94,212,3,64,6,202,77,188,211,169,104,1,161,105,118,211,232,199,52,0,204,96,82,21,167,250,82,129,214,128,35,8,59,211,212,98,148,117,165,239,64,9,72,41,212,152,230,128,10,92,113,71,106,40,1,41,105,123,210,103,154,0,66,105,50,105,212,152,205,0,0,241,75,154,78,148,238,212,0,148,180,148,80,0,105,41,71,74,70,52,1,25,198,105,0,231,20,227,235,66,129,131,64,12,43,205,70,201,154,159,25,162,128,42,249,92,244,167,136,248,206,42,96,6,104,35,20,1,1,83,154,112,83,82,118,160,80,3,2,250,82,98,166,192,6,138,0,104,94,41,66,211,133,40,235,64,8,22,156,5,46,41,104,1,188,209,75,218,140,80,3,113,75,138,94,212,80,2,98,155,180,26,146,144,117,160,8,196,120,165,217,197,74,7,52,17,64,16,237,197,0,100,116,167,208,40,1,187,
41,219,120,167,116,164,160,6,227,20,211,78,166,147,205,0,4,113,239,73,245,165,205,39,122,4,29,232,52,103,52,148,192,66,41,13,47,106,105,233,64,7,29,104,56,163,20,30,212,0,189,105,64,161,121,167,1,64,10,5,60,10,104,165,205,0,127,255,217);

//.tj32 (transparent jpeg)
back_balls:array[0..42385] of byte=(
120,1,236,189,5,84,92,203,182,46,220,4,39,72,72,128,224,110,129,224,144,160,1,146,224,193,161,129,198,130,75,227,238,26,32,184,5,72,112,247,166,3,161,9,174,193,131,187,59,4,215,198,229,239,220,243,246,187,251,220,251,238,62,103,159,189,239,59,247,31,239,172,49,170,151,85,23,61,87,213,154,115,214,55,191,89,56,89,242,112,11,10,226,162,0,0,183,247,0,0,36,192,95,54,3,11,0,224,110,242,110,17,240,64,86,82,70,18,128,132,184,142,244,243,230,221,12,224,21,0,3,13,13,29,13,21,3,29,29,29,19,19,3,11,155,0,7,251,254,125,108,146,135,143,240,8,40,72,169,40,41,72,201,201,169,233,217,153,168,105,159,210,145,147,51,63,127,242,148,147,139,151,151,151,138,73,64,132,159,91,152,157,135,151,251,103,35,72,152,152,152,216,247,177,137,113,112,136,185,105,200,105,184,127,247,118,215,12,192,199,184,119,139,130,139,140,68,11,184,135,143,132,140,143,116,247,13,64,133,248,157,168,72,255,182,253,47,73,0,72,247,144,81,80,209,208,49,48,177,238,35,42,192,30,0,238,33,33,35,223,67,65,70,69,69,65,8,141,228,141,184,
15,64,193,71,125,72,195,37,142,246,72,217,0,157,214,158,128,219,63,54,11,131,238,101,121,11,161,202,208,1,61,143,161,67,0,38,22,209,99,98,18,82,6,70,38,230,39,44,188,124,207,158,243,11,8,190,122,45,33,41,37,45,35,171,170,166,14,212,208,212,2,25,25,155,152,154,153,91,88,58,58,57,187,184,186,185,123,4,190,11,10,14,121,31,26,22,23,255,33,33,49,233,227,167,228,236,156,220,188,252,130,194,162,226,138,47,149,176,170,175,213,53,181,173,109,223,218,59,58,187,186,123,134,71,70,199,198,39,38,167,166,151,150,87,86,215,214,55,126,108,110,29,30,29,159,192,79,207,206,47,46,127,202,133,4,64,254,139,88,136,207,191,72,246,31,228,194,71,200,117,15,5,5,25,5,253,167,92,72,247,92,127,10,142,143,130,74,195,133,246,80,92,25,221,192,254,17,45,183,63,6,193,203,216,172,242,22,76,58,30,149,3,66,67,135,33,44,34,122,222,37,134,195,159,162,253,155,100,127,159,96,1,255,144,100,255,91,176,127,151,107,26,128,141,140,132,232,60,100,124,128,40,0,94,203,156,93,79,55,138,197,156,237,247,175,242,175,103,240,175,49,
240,123,199,0,148,247,48,58,66,79,128,18,131,254,219,43,63,130,155,125,71,49,138,217,203,245,20,43,45,227,90,249,182,138,227,140,206,188,103,11,122,35,54,118,68,107,234,209,102,43,84,209,178,7,100,145,122,151,155,189,172,207,158,176,193,82,102,100,144,76,109,26,43,53,241,114,205,161,162,7,182,225,175,183,18,143,63,115,149,55,119,95,133,76,108,110,235,249,139,161,18,40,255,241,66,40,5,172,78,156,238,170,212,121,232,178,81,125,9,212,139,44,156,235,115,172,120,217,15,105,193,246,240,28,68,151,144,32,80,66,250,31,90,208,188,199,161,168,165,203,116,137,162,237,129,195,80,41,218,94,210,90,78,19,131,24,9,199,218,224,104,123,182,139,4,13,135,186,135,207,110,60,47,129,187,185,84,166,48,233,208,110,10,69,75,64,122,24,115,230,189,95,21,236,93,23,201,240,215,181,206,244,15,210,26,179,27,125,198,10,60,211,228,19,162,73,160,153,240,194,136,75,190,81,163,90,179,130,172,62,175,27,200,12,44,63,183,95,109,133,151,154,239,100,87,240,217,123,59,22,10,13,69,137,136,152,39,188,55,234,15,57,49,11,97,
34,202,186,24,232,16,106,22,243,199,80,235,162,210,183,233,176,19,162,72,174,234,97,54,99,43,227,124,254,211,149,75,141,129,116,242,10,79,136,140,190,69,135,163,254,75,11,162,93,112,158,118,235,10,118,73,156,8,183,227,141,101,250,162,110,118,216,19,128,178,4,193,31,42,221,134,50,57,92,93,117,31,224,132,20,13,169,68,223,42,101,2,220,250,61,213,78,254,64,15,74,240,125,3,110,97,151,17,80,126,42,66,194,206,250,16,128,209,69,215,0,96,251,51,6,222,239,109,195,125,63,252,154,188,162,68,209,166,230,253,173,185,55,222,215,6,15,66,2,164,227,200,137,16,14,235,217,119,170,209,150,222,209,193,182,236,38,250,92,10,34,219,11,123,188,117,100,249,115,124,149,86,83,244,49,156,138,19,20,22,131,22,85,192,201,35,72,14,10,121,128,164,180,168,170,194,14,174,84,235,60,110,212,56,65,186,1,76,81,162,147,93,52,179,108,249,79,120,254,127,176,255,144,122,183,15,103,249,78,213,158,205,2,114,79,54,167,97,39,154,171,81,157,15,141,141,87,141,61,113,125,18,188,135,116,12,70,57,79,232,120,183,0,204,217,97,191,
81,202,133,37,160,140,225,214,45,148,142,216,17,81,0,120,38,78,40,67,20,225,220,211,176,240,84,147,40,84,13,210,180,208,15,29,236,203,179,104,62,103,84,25,178,135,108,70,29,143,53,92,217,123,118,190,43,50,86,60,210,111,146,66,249,98,24,142,116,226,240,217,4,59,151,144,142,58,42,56,177,62,186,245,150,47,89,0,248,204,43,112,140,248,0,60,6,177,49,170,251,170,181,76,159,131,203,205,37,246,232,15,138,252,135,134,251,63,243,111,107,68,92,191,26,53,246,126,233,140,23,91,237,39,245,6,23,213,147,207,45,227,27,171,140,170,210,199,207,2,184,138,212,199,251,125,24,184,96,217,242,71,105,125,221,124,95,236,115,51,223,165,101,87,56,121,142,133,35,69,97,64,122,35,21,120,112,185,5,149,154,215,102,97,65,91,21,169,0,240,180,48,106,17,108,46,229,101,39,157,205,225,142,7,213,230,133,70,152,110,121,125,61,86,160,240,68,185,151,80,69,220,60,154,11,185,187,27,211,150,164,104,108,126,243,222,143,236,48,49,2,101,9,192,239,43,106,124,108,134,3,178,98,54,198,45,194,65,122,10,34,230,247,110,232,184,179,19,
13,9,197,186,233,23,145,244,244,151,57,66,105,140,220,32,61,29,239,222,6,9,48,29,66,5,106,15,215,70,35,90,180,62,123,111,229,96,202,25,211,253,120,118,72,20,23,130,227,225,119,131,119,174,118,90,11,11,218,9,16,242,252,224,74,71,237,192,115,49,209,251,152,146,161,41,241,101,171,228,245,214,92,82,248,190,117,18,234,204,49,132,146,210,165,90,151,74,13,13,155,27,131,142,127,57,177,209,109,232,150,186,63,190,200,157,68,122,15,151,75,175,36,235,252,104,248,2,159,93,26,219,109,62,99,212,199,91,148,165,71,217,126,214,204,68,130,155,36,167,58,200,36,180,173,163,141,38,196,195,155,250,143,250,29,79,22,44,185,52,139,247,81,190,56,1,70,19,93,99,231,219,27,95,112,181,160,195,204,182,65,198,73,65,198,225,232,200,216,232,250,208,6,249,220,205,93,19,124,110,239,227,102,146,31,204,200,178,191,178,16,191,182,22,255,45,199,53,25,132,110,214,206,230,148,110,73,78,153,94,221,55,251,246,251,187,11,23,39,163,74,232,253,130,233,129,174,22,118,29,244,252,3,6,90,249,100,103,214,65,160,198,232,234,193,
147,153,236,14,57,245,89,41,245,174,206,165,225,194,59,64,43,69,30,218,92,149,206,141,212,185,106,53,165,254,18,7,150,188,171,93,196,208,90,237,241,160,103,134,229,169,238,139,14,145,23,67,111,195,233,113,101,68,250,136,60,156,33,1,203,243,212,5,196,79,21,100,74,212,252,126,91,145,252,159,148,76,5,124,87,221,41,146,107,99,22,37,228,29,250,196,196,245,149,18,154,70,120,189,74,50,91,93,219,35,67,43,175,190,155,161,221,125,189,71,101,110,141,203,71,26,106,142,209,16,142,112,175,87,236,89,174,180,251,108,113,14,50,219,58,223,57,31,91,37,111,230,201,104,39,191,180,162,88,175,182,170,123,164,194,144,37,34,97,46,110,145,106,15,226,210,50,35,87,151,173,5,209,104,126,35,210,113,202,135,37,193,156,186,13,58,101,193,147,240,229,138,211,29,23,1,169,42,99,1,80,185,89,177,206,100,23,86,221,91,96,229,184,230,174,214,87,162,84,74,86,243,177,136,147,152,82,15,170,119,215,158,188,142,180,159,164,5,72,80,14,22,148,245,70,242,183,240,45,93,192,246,143,1,7,109,131,151,26,93,135,66,211,58,172,69,116,
104,13,209,205,148,236,248,9,50,184,107,6,176,9,209,194,51,170,21,205,177,188,222,226,73,243,83,172,39,132,9,163,220,159,77,232,168,3,99,36,216,12,57,179,195,152,1,255,47,20,40,209,249,39,104,23,251,122,36,21,245,195,240,192,14,244,60,79,138,217,59,128,233,151,100,175,194,201,160,224,189,79,157,132,199,207,35,161,194,55,226,73,34,91,155,157,201,50,24,235,106,149,199,68,54,50,16,176,156,215,74,88,150,25,165,244,114,45,25,179,99,216,124,253,110,54,74,56,176,170,166,147,16,138,154,40,37,171,205,138,184,189,0,171,236,34,215,160,254,254,173,252,52,95,198,200,127,184,246,93,249,74,158,20,95,34,186,44,96,185,204,170,60,157,149,104,111,134,100,185,46,188,78,199,44,108,3,106,125,121,40,217,108,159,100,103,36,172,242,227,242,67,178,247,150,193,123,18,200,253,201,242,228,150,52,23,89,140,29,112,85,188,106,52,43,195,15,111,174,69,121,163,221,75,247,160,40,151,200,237,29,161,232,227,125,93,103,119,244,214,186,78,158,151,153,233,226,42,34,146,162,221,80,253,178,103,165,59,74,127,150,149,80,
39,155,51,108,83,124,202,110,67,168,131,189,75,158,220,119,248,60,148,102,200,90,11,40,126,26,192,51,179,74,121,7,88,210,187,191,204,241,120,118,110,78,154,46,54,74,134,126,3,162,246,118,117,231,157,71,85,205,33,11,171,14,164,72,13,249,60,10,83,116,184,218,251,213,178,247,236,76,210,238,67,66,163,158,189,149,35,168,64,156,103,120,126,111,13,47,91,9,37,108,176,80,194,235,141,134,96,193,33,124,201,134,164,73,176,193,232,144,116,111,238,12,83,151,140,184,167,28,157,176,253,38,44,121,220,88,245,212,233,163,110,122,67,254,181,74,117,108,34,99,117,23,252,45,230,117,159,7,123,252,114,10,142,44,253,28,75,251,19,242,0,31,21,239,232,243,91,216,81,99,55,141,117,143,52,45,172,114,1,127,110,74,58,179,166,153,239,97,214,56,93,13,252,215,214,125,160,69,239,89,148,154,166,169,253,90,121,47,185,113,81,167,242,165,70,94,9,107,161,9,205,135,136,0,92,113,194,126,46,243,223,116,54,16,58,162,24,148,94,100,155,167,237,62,242,85,143,208,177,251,14,176,173,145,182,221,68,0,164,232,182,2,210,68,216,119,
95,35,52,212,59,232,103,202,52,250,242,214,186,188,88,101,15,132,23,98,172,239,86,32,251,57,38,55,126,191,83,149,18,227,250,88,143,176,248,90,166,190,142,236,205,240,139,23,123,235,76,132,221,243,110,81,167,63,142,233,144,224,144,156,144,212,80,7,233,179,62,141,101,221,84,124,206,42,36,109,97,33,78,38,42,69,208,90,238,121,131,93,169,216,39,251,219,229,59,64,144,219,104,146,99,239,89,174,209,249,168,112,58,172,222,46,124,151,219,187,192,104,90,116,201,78,231,14,48,96,114,7,104,2,223,18,248,182,46,214,220,1,210,183,239,0,62,19,215,172,237,135,146,44,141,69,184,203,167,209,229,39,104,241,135,202,38,49,100,137,90,143,178,116,80,111,36,156,199,41,159,15,67,185,26,34,94,167,215,204,2,110,125,243,188,242,43,186,50,156,223,151,140,95,246,173,213,144,153,240,83,194,83,63,71,239,148,23,135,23,193,231,32,112,216,17,143,246,155,10,212,197,21,152,38,244,227,73,6,229,28,136,219,38,214,95,53,198,113,184,110,142,108,57,53,74,153,254,35,63,69,46,201,192,40,252,6,156,174,182,70,49,100,81,80,190,
125,2,100,76,90,78,19,82,21,15,69,81,240,228,90,57,190,3,144,3,231,196,90,255,100,187,131,157,241,112,227,234,222,166,127,199,32,230,217,122,227,219,195,251,73,99,198,221,251,250,74,110,49,60,110,62,59,247,94,252,24,160,112,39,60,186,3,188,207,49,30,51,166,119,133,28,220,1,136,63,38,202,242,151,37,182,11,106,240,24,183,133,109,90,81,229,201,219,190,199,31,153,204,92,225,27,214,146,196,32,236,211,236,226,47,139,235,81,2,148,74,90,75,96,176,14,103,213,188,3,88,74,151,1,244,96,56,223,22,3,197,136,53,202,163,192,41,77,226,125,78,73,21,184,238,101,150,23,45,125,0,199,231,205,142,58,107,139,109,26,82,94,109,140,53,189,109,137,151,19,64,42,123,158,161,91,98,217,1,87,148,183,43,220,204,232,35,201,103,197,7,190,65,131,156,141,85,86,246,235,5,199,80,183,82,22,175,55,8,115,91,68,252,71,223,95,160,212,123,190,234,74,207,199,214,139,10,26,204,24,155,251,32,248,210,194,195,122,177,35,221,239,161,79,140,187,213,68,119,78,243,19,230,98,200,11,194,234,229,249,224,163,97,244,76,244,171,27,241,
58,223,148,42,35,107,106,24,147,253,250,158,152,110,240,65,192,182,169,246,186,81,163,57,198,10,43,212,149,155,237,230,18,70,233,99,30,211,35,252,203,176,204,10,132,114,163,47,126,166,30,193,247,185,107,83,185,33,244,164,12,98,229,182,169,44,99,212,41,155,242,153,127,170,244,242,80,43,137,168,186,172,127,125,0,112,168,57,1,156,28,32,132,8,66,184,120,77,54,65,169,211,206,195,49,223,176,39,234,221,200,218,237,117,102,32,149,71,94,144,51,25,97,154,59,0,178,30,146,51,218,176,244,182,118,58,254,56,101,63,92,57,213,63,3,52,94,74,144,36,136,226,45,33,97,106,14,242,27,117,234,90,237,177,85,134,5,28,70,43,8,249,144,251,178,140,148,41,7,253,87,83,42,71,74,186,67,239,170,72,242,114,26,52,19,226,167,210,173,25,91,150,208,8,97,13,162,36,228,87,216,165,241,52,23,159,180,145,55,219,221,208,223,11,75,60,203,18,2,108,216,88,110,142,56,186,188,180,233,152,8,173,183,183,247,102,13,74,248,152,254,252,81,28,56,56,121,89,107,246,75,57,253,136,128,81,156,69,207,39,168,36,65,142,188,185,241,76,76,243,
147,37,145,98,227,224,2,77,239,226,212,97,210,80,165,215,242,194,175,52,128,120,150,49,175,180,106,243,52,251,143,188,127,28,129,165,186,115,186,243,118,165,140,56,191,89,228,243,128,76,241,44,35,51,79,139,213,81,141,120,33,44,210,135,169,37,248,192,116,42,203,160,28,90,136,12,183,142,39,89,50,71,24,187,149,169,238,48,69,206,124,67,73,107,211,3,154,100,140,204,26,235,31,104,72,183,12,39,148,43,215,87,26,253,65,246,26,79,249,158,236,152,2,53,168,145,53,213,219,138,192,248,69,218,146,222,129,214,142,20,115,181,138,152,12,228,118,210,69,224,111,215,84,135,104,106,247,209,147,1,134,152,64,18,148,59,64,134,236,169,16,217,15,231,251,106,201,143,85,107,196,77,208,25,20,179,202,136,146,93,76,131,146,153,179,99,254,20,48,5,209,1,15,244,196,216,173,214,223,109,108,168,240,3,238,0,130,23,77,157,30,22,85,141,46,147,226,40,171,248,93,208,188,237,94,31,250,115,47,1,247,145,245,99,36,95,59,207,177,151,58,21,111,240,30,126,137,71,193,250,97,149,223,33,80,102,169,57,63,190,150,224,79,204,151,
103,97,63,146,252,3,114,191,36,139,14,86,81,189,217,103,51,163,187,136,11,126,15,171,235,16,128,184,113,184,145,79,80,247,119,115,184,109,43,247,122,198,142,215,172,53,53,111,191,137,187,154,247,227,152,155,67,78,7,103,52,84,147,31,203,57,122,166,30,107,78,104,104,13,240,50,216,177,204,247,34,78,172,176,39,144,164,28,129,101,123,130,199,192,235,231,249,13,183,153,33,228,166,117,212,13,169,2,159,56,84,199,111,137,55,173,73,162,20,8,50,231,29,55,71,46,17,138,50,97,43,33,104,73,94,232,74,84,70,167,16,237,13,126,75,63,250,155,241,93,7,17,217,63,234,144,255,252,62,51,248,57,237,136,76,117,76,196,26,86,148,253,168,97,163,201,161,245,138,142,165,66,93,5,18,52,91,216,130,85,98,105,10,43,142,123,145,220,149,152,239,152,177,132,38,73,37,38,3,52,131,11,21,10,221,97,75,213,162,11,251,241,52,179,159,191,52,156,129,92,67,206,48,141,63,15,164,241,54,82,142,213,202,191,221,102,70,107,21,151,37,45,194,40,138,53,247,203,187,7,252,165,146,64,109,74,65,181,71,83,111,41,89,243,228,236,191,230,169,
215,250,1,220,50,113,185,247,38,0,135,58,55,187,141,60,237,46,174,229,184,224,148,70,241,62,128,253,89,172,115,233,251,213,103,103,150,189,157,124,131,11,28,140,53,51,177,161,220,34,224,138,192,218,47,12,25,226,94,220,163,216,7,188,111,86,112,40,237,60,99,124,155,147,79,4,15,23,130,30,10,233,136,161,225,233,97,158,242,237,168,247,140,165,133,33,68,251,207,35,201,193,135,253,208,74,80,164,62,70,156,250,184,60,216,206,103,255,243,217,173,126,207,68,184,243,74,142,197,70,47,141,177,179,232,51,119,228,153,107,223,174,139,222,111,233,52,41,74,53,206,184,46,235,101,105,207,159,27,51,238,80,210,30,18,212,70,182,1,58,109,192,169,45,70,241,227,254,137,2,34,150,110,43,125,30,202,97,249,165,17,183,108,154,161,68,150,61,175,118,85,164,8,65,81,44,61,206,247,165,67,105,78,139,134,73,63,199,140,189,11,153,174,201,83,114,97,121,47,82,44,142,14,211,213,20,41,86,70,53,94,239,48,115,39,32,230,135,136,126,185,82,33,230,223,148,75,243,255,48,232,169,38,143,3,230,165,28,187,223,166,86,204,89,30,115,
112,165,238,26,92,69,73,101,9,161,215,27,171,180,196,234,224,141,85,195,254,8,209,162,45,142,107,223,213,85,74,235,54,15,30,95,151,147,9,204,193,15,212,171,91,212,39,175,199,125,63,144,186,200,253,168,13,239,240,12,74,233,220,46,111,228,202,144,214,90,91,78,204,91,162,162,78,56,190,90,208,179,227,29,98,225,142,122,114,159,23,151,68,186,95,40,186,176,104,187,183,145,210,173,220,248,117,128,133,168,203,57,202,163,214,140,125,223,232,59,0,168,65,178,126,28,146,85,248,71,245,253,47,223,87,23,145,147,15,84,171,52,103,36,22,109,61,95,83,188,216,213,96,206,196,75,187,182,88,210,178,182,161,55,192,7,170,118,181,219,133,237,35,239,190,149,100,221,218,181,125,21,168,245,149,229,92,75,93,26,216,137,62,121,229,27,233,86,16,46,140,35,82,250,253,53,131,118,153,224,161,246,112,137,173,139,54,102,78,68,192,190,127,159,121,187,103,20,60,68,36,114,44,37,166,107,214,83,13,236,212,219,178,56,30,151,157,87,42,225,88,244,248,218,57,215,115,79,112,130,159,35,146,78,47,126,254,203,101,29,69,95,40,84,
100,155,123,121,31,202,167,214,75,223,137,129,9,97,19,106,59,115,29,46,83,90,188,2,134,165,90,108,211,232,173,9,177,62,129,145,249,21,231,6,32,112,128,251,139,173,97,21,93,117,202,62,199,70,39,8,167,178,39,190,149,18,217,188,181,103,19,38,37,52,105,127,238,145,12,103,166,145,115,123,72,60,166,174,244,22,149,152,48,72,54,117,191,203,66,211,195,175,152,192,12,96,20,159,12,98,46,237,248,47,81,1,149,135,0,250,84,164,209,228,238,248,111,68,155,118,70,248,95,216,237,235,248,7,150,196,72,79,84,149,199,213,52,94,37,24,196,88,140,254,61,136,12,82,223,249,234,163,165,78,128,111,175,248,117,164,87,119,97,9,99,14,163,111,131,190,6,56,49,212,61,103,86,114,78,93,174,232,12,249,14,48,46,74,122,17,223,14,236,192,145,63,168,38,129,28,236,13,127,254,132,19,143,203,154,255,217,39,161,107,74,38,66,67,194,228,25,87,159,188,137,197,61,33,214,199,155,125,78,46,14,0,84,251,42,13,226,78,190,58,107,23,52,129,82,73,103,11,254,251,227,197,115,178,24,124,169,95,235,157,11,153,234,187,182,17,250,181,122,189,
38,229,148,124,28,50,215,239,216,231,56,241,5,190,238,199,101,27,13,218,176,113,143,167,204,175,178,53,217,214,252,145,15,110,87,226,233,115,81,2,106,48,164,183,29,228,97,187,62,224,177,123,97,16,191,151,223,16,86,127,181,148,159,177,6,114,159,68,54,52,42,16,16,189,205,209,11,212,129,204,205,102,254,71,244,85,205,241,123,226,160,240,48,57,45,118,114,92,245,2,213,118,198,84,173,235,84,51,178,199,62,83,147,79,250,7,164,245,5,252,122,160,173,13,189,152,253,36,179,64,243,9,148,217,80,183,151,18,238,169,209,0,158,153,112,112,236,83,149,232,134,202,70,190,144,190,248,36,115,204,117,152,111,121,162,60,106,151,167,23,38,152,28,207,70,51,36,165,65,23,62,253,62,103,83,35,59,172,186,128,59,88,10,7,36,237,93,108,190,124,90,98,223,182,171,229,175,69,125,90,244,154,114,204,25,177,27,199,179,4,244,95,137,194,104,190,158,66,20,233,166,99,90,118,197,72,112,80,197,14,60,129,189,45,234,171,1,126,92,244,33,211,197,221,120,48,107,25,60,152,106,34,135,165,197,36,182,150,97,177,67,251,120,149,73,52,
68,57,81,212,114,62,245,219,119,11,163,226,210,106,136,86,78,241,195,124,28,151,86,13,90,217,245,179,119,48,211,138,38,137,167,98,140,141,137,7,235,69,148,121,121,109,193,148,86,150,132,33,133,20,56,94,177,4,193,36,9,157,70,122,83,7,43,237,134,212,229,53,179,17,207,106,55,224,148,203,53,246,188,59,23,49,139,39,229,59,78,202,18,14,137,255,229,16,251,157,160,20,33,104,175,117,252,194,101,182,185,194,51,29,111,157,165,143,0,169,109,91,20,207,122,111,44,178,28,184,120,13,109,185,190,186,77,216,56,91,192,46,115,229,129,84,182,72,9,28,245,3,160,110,217,201,241,218,72,199,198,25,120,123,200,246,201,117,70,7,203,203,46,205,145,169,240,214,34,38,194,19,62,66,133,210,5,101,205,35,93,214,37,207,34,201,184,7,153,103,49,43,84,202,19,39,101,27,111,14,130,51,12,136,143,31,72,159,255,224,87,190,81,188,88,174,37,101,33,171,238,200,126,106,95,76,221,90,8,192,19,87,248,27,243,28,73,165,31,234,193,226,196,180,53,27,7,219,41,205,45,45,111,110,110,63,94,179,102,103,251,209,5,208,160,60,33,61,81,142,
134,200,252,157,248,253,132,68,220,179,200,14,117,127,20,143,64,61,252,195,71,98,230,123,235,92,57,214,146,212,15,5,58,45,207,146,219,14,159,5,39,183,7,26,72,165,145,166,98,155,217,157,192,47,125,225,155,237,83,115,72,71,245,111,12,62,148,216,135,77,85,34,28,2,205,195,103,254,108,145,189,130,52,51,201,45,1,139,89,45,139,19,58,113,37,100,217,46,66,172,218,245,70,201,19,1,103,254,125,246,74,186,43,228,227,17,26,147,20,224,56,37,243,28,168,246,173,224,168,195,130,243,122,77,139,111,39,200,42,105,138,194,82,108,184,166,161,223,189,84,187,46,117,35,57,216,243,251,70,114,111,77,237,118,31,24,203,230,13,59,247,158,215,122,165,48,71,126,195,122,230,187,34,58,190,20,19,19,246,44,135,226,98,233,62,79,95,191,122,218,216,236,94,238,7,97,220,157,163,119,0,87,209,13,56,164,88,230,165,112,161,92,205,204,185,173,162,54,14,35,199,135,144,88,113,27,79,151,27,129,107,176,94,172,26,75,144,210,61,127,63,116,113,57,157,156,255,232,59,60,72,43,150,233,7,12,32,243,45,250,62,132,239,87,206,246,228,68,
118,102,10,180,123,234,53,57,158,202,227,110,41,181,104,219,12,237,167,231,28,245,121,213,45,215,141,215,140,174,162,28,224,128,37,201,71,164,63,9,209,161,239,115,241,25,18,244,137,5,50,150,181,54,176,14,165,84,208,50,127,193,82,63,87,41,105,77,99,125,73,176,169,67,72,111,30,186,20,205,151,133,173,203,66,252,40,207,188,141,194,49,34,142,184,120,71,233,74,25,219,155,229,68,25,79,22,96,248,74,181,148,114,204,148,223,113,186,52,151,114,20,233,85,215,105,174,185,72,137,154,248,174,188,185,72,33,50,201,98,241,240,171,93,109,149,87,234,12,225,211,126,92,12,33,16,165,100,150,217,100,150,129,100,65,192,183,100,150,44,94,111,176,169,219,229,184,83,183,188,16,39,55,163,2,44,131,219,25,226,30,15,49,251,158,48,37,251,250,11,91,7,142,211,139,135,163,242,233,217,126,85,72,124,65,204,45,185,85,49,237,14,81,184,156,224,124,251,141,192,215,86,123,222,142,75,115,226,206,56,148,68,40,182,145,47,57,41,231,240,214,110,192,192,250,179,165,196,76,179,74,243,104,154,28,156,17,126,186,75,71,189,32,61,
229,63,205,36,254,98,26,255,155,246,72,221,110,95,91,171,46,131,82,6,176,45,75,209,251,253,221,232,70,61,60,239,0,169,231,46,95,151,88,195,101,72,134,112,89,55,183,250,198,120,133,68,128,220,140,98,21,190,3,18,200,162,209,133,197,239,102,117,7,163,227,163,83,108,218,117,165,219,101,147,62,238,235,13,65,188,120,92,103,15,191,85,96,155,113,165,222,166,129,7,156,245,239,205,105,119,181,224,251,163,163,224,7,224,56,21,15,38,125,99,37,63,111,204,135,237,83,88,154,30,116,100,66,191,246,218,246,84,90,9,63,246,20,138,220,154,189,28,177,137,27,95,42,242,59,227,160,105,93,29,235,197,33,218,186,149,104,125,134,227,1,140,61,232,49,155,238,179,89,197,175,126,200,137,113,202,216,128,39,121,160,158,158,222,212,164,238,32,200,242,16,233,50,189,233,182,184,95,253,82,2,119,174,95,180,133,18,67,167,228,123,38,203,219,154,253,19,202,245,6,133,241,41,54,182,56,140,227,114,65,51,168,206,200,74,24,191,134,149,114,54,187,99,16,49,193,229,134,205,202,127,28,213,63,207,5,244,169,116,222,243,226,164,6,
155,118,93,34,13,28,19,30,227,22,48,165,248,210,156,65,115,26,25,87,205,15,201,211,95,97,123,56,65,83,216,155,86,54,111,97,19,239,64,85,102,170,6,136,169,243,75,212,98,78,56,132,24,93,118,190,132,148,227,37,44,231,222,24,49,170,133,152,160,70,134,242,22,136,67,12,150,119,207,169,88,9,55,161,192,70,80,13,201,129,248,18,248,142,107,204,252,113,158,133,88,26,243,61,115,195,1,203,58,114,222,24,169,225,74,218,247,74,168,246,182,157,178,70,45,254,195,48,20,97,53,135,215,92,98,196,113,109,187,106,166,81,85,27,81,95,10,100,1,237,201,130,253,105,172,166,206,219,90,241,81,149,72,209,130,206,165,221,19,16,43,29,220,122,160,206,10,4,96,242,6,150,198,191,13,138,199,133,165,113,150,133,189,121,211,251,201,18,42,137,86,246,70,112,76,178,236,220,202,140,110,250,246,209,60,199,52,219,216,12,114,194,181,116,243,13,120,106,123,3,129,193,216,180,94,98,223,179,167,77,197,189,62,129,102,178,126,47,132,48,70,18,181,72,16,168,97,255,126,148,25,129,42,149,249,232,227,239,214,114,149,202,125,17,185,28,
223,225,46,61,40,45,74,43,229,230,17,195,251,191,141,199,22,50,86,192,170,103,77,191,134,246,98,63,236,226,185,24,61,81,66,211,58,88,143,81,144,143,51,187,89,191,3,144,150,227,38,24,216,212,25,85,134,147,12,124,175,139,94,183,92,251,205,24,46,82,171,151,2,211,21,35,205,36,218,238,201,254,194,245,229,68,223,87,253,195,19,132,247,123,169,184,236,226,91,190,44,64,124,113,192,117,2,77,222,243,93,89,187,133,77,189,155,251,52,250,67,144,18,150,133,110,217,255,254,24,196,233,2,41,142,36,85,2,38,52,89,126,247,27,255,128,158,231,126,60,251,5,136,53,18,80,145,201,87,128,180,169,132,6,105,178,28,13,132,153,136,205,177,202,162,109,138,145,142,159,47,87,102,181,27,55,47,87,26,196,231,1,204,1,92,202,210,104,79,178,149,195,162,100,208,4,7,81,181,182,185,125,224,62,174,165,83,211,126,60,123,232,160,222,84,103,200,147,174,245,138,13,17,115,100,193,149,6,147,89,87,136,80,224,248,207,83,146,20,81,143,254,148,6,243,239,30,227,86,99,13,180,90,105,34,170,150,53,92,197,214,122,239,158,241,164,119,22,
122,177,210,216,46,154,82,179,244,228,198,15,98,79,12,170,31,239,183,126,169,186,157,139,178,99,80,109,30,240,184,196,170,239,105,34,227,213,70,204,176,149,126,55,160,158,75,205,73,237,39,190,24,40,39,1,48,20,13,49,2,71,115,202,117,234,105,196,106,227,75,150,191,46,207,188,80,123,171,250,227,175,194,249,8,196,232,127,196,57,238,243,101,190,47,138,217,116,72,71,69,111,21,107,144,169,186,38,190,79,116,169,28,73,156,65,75,235,149,77,109,157,158,196,24,239,92,28,160,57,206,92,110,28,64,63,214,43,22,240,165,103,174,70,97,150,165,62,133,176,226,243,57,25,73,186,67,48,112,76,179,90,8,61,208,54,117,157,31,100,91,54,123,0,35,112,180,56,191,202,14,5,109,15,20,70,226,151,35,3,63,224,13,151,103,122,12,5,200,118,225,20,82,254,236,96,195,54,38,217,38,130,74,164,175,216,48,23,129,134,237,135,2,13,91,195,138,251,98,164,203,62,130,35,122,94,27,201,253,143,174,134,121,111,79,144,132,43,214,11,229,153,64,244,41,243,69,189,236,158,131,40,142,77,160,190,79,91,238,185,219,125,74,201,10,149,72,64,23,
132,86,248,10,250,42,4,47,221,204,128,0,84,83,225,165,23,209,160,175,60,206,165,23,41,16,167,225,151,38,79,6,64,165,238,86,106,35,148,22,49,146,38,213,175,41,250,92,165,94,155,209,77,222,18,110,102,173,251,85,113,42,40,72,138,55,247,139,146,107,84,105,164,94,179,127,241,244,116,49,44,160,84,192,236,244,138,62,128,74,66,89,20,246,214,253,37,8,84,254,48,174,247,223,100,196,254,158,249,207,127,170,163,225,239,37,55,36,223,240,189,137,241,89,42,124,128,162,6,234,93,198,212,121,137,55,179,3,250,129,51,107,109,16,149,30,114,7,152,216,85,224,72,200,167,91,231,106,195,7,210,248,36,60,131,24,143,107,148,189,123,107,90,76,247,118,162,196,153,121,142,4,66,17,169,169,7,109,133,199,222,31,59,207,221,212,73,160,53,143,124,111,188,9,122,208,173,89,46,163,145,157,88,67,250,185,175,218,164,100,168,111,95,211,94,126,95,131,46,57,134,76,70,180,65,83,235,102,155,130,169,40,209,215,3,48,254,104,4,180,50,255,165,254,14,224,1,70,116,251,227,116,143,18,250,121,184,110,254,89,241,145,252,190,24,94,34,
40,135,183,241,68,238,121,131,74,34,8,96,60,236,92,252,72,70,69,158,169,65,57,81,182,186,99,7,195,212,7,150,193,51,22,154,91,252,232,5,184,234,131,140,49,251,20,95,205,146,188,240,252,150,69,66,87,159,1,64,183,53,42,191,193,113,233,107,136,158,22,254,117,133,204,234,113,4,238,134,72,113,249,163,181,160,186,120,10,221,1,157,131,254,12,138,168,104,124,229,227,46,238,73,1,114,179,123,85,22,132,234,4,44,126,4,216,0,116,128,202,68,170,249,159,53,97,248,135,219,1,154,126,129,204,152,15,162,127,12,118,236,146,159,228,135,67,233,14,31,127,11,157,151,193,55,181,134,140,17,126,110,74,224,77,25,66,218,78,242,161,25,121,122,230,158,36,251,93,52,72,96,96,101,248,115,153,15,205,102,140,192,125,18,147,29,57,63,95,118,112,51,244,90,217,211,101,3,183,153,202,163,215,179,174,40,74,107,186,42,138,82,209,94,231,146,233,150,200,52,229,14,32,44,122,196,124,7,192,250,106,180,114,243,236,72,93,37,29,20,31,48,115,28,237,101,216,104,182,32,122,150,114,92,4,129,147,213,153,246,116,141,41,98,95,114,214,
192,97,249,89,22,94,152,85,105,244,157,6,45,215,145,90,208,79,78,80,50,68,240,96,207,5,85,154,122,35,11,170,114,0,141,30,255,17,84,151,176,42,73,209,47,253,2,209,175,44,173,74,31,92,145,135,153,11,23,211,133,62,62,52,143,82,238,16,47,98,145,252,245,51,121,38,133,223,209,239,24,132,146,10,36,215,163,225,112,46,207,214,253,180,65,97,175,29,21,78,75,96,159,64,135,2,124,3,194,182,176,95,39,121,142,29,24,217,224,93,136,172,243,64,140,122,149,242,157,202,48,130,193,138,141,52,136,5,250,13,90,201,95,71,131,89,132,222,63,92,159,151,166,39,145,210,33,141,11,3,92,236,47,83,5,39,15,175,75,178,60,127,178,65,62,241,241,168,84,124,87,95,237,124,64,156,20,22,174,32,192,149,143,181,146,106,124,124,57,209,239,67,59,184,54,178,55,251,78,200,81,247,163,101,213,153,214,35,93,229,216,71,139,99,63,114,75,97,252,124,166,2,172,217,246,213,241,207,104,147,230,203,164,56,26,140,58,217,180,163,64,43,105,220,35,207,104,147,33,157,162,13,70,244,141,112,3,198,179,82,114,16,73,101,252,104,246,74,1,95,212,151,
171,209,0,31,143,81,127,200,105,180,199,43,251,125,173,70,223,6,154,140,121,63,94,82,95,143,178,227,171,49,201,140,249,44,247,134,31,247,190,197,123,142,9,48,20,206,219,122,64,16,109,216,7,53,59,197,141,61,49,62,203,150,177,76,173,152,120,243,36,238,153,150,200,86,78,149,69,255,5,239,54,88,203,102,13,147,52,62,94,215,130,185,164,130,236,71,164,62,142,133,109,161,37,230,81,92,13,52,207,139,46,187,179,192,34,182,167,59,148,216,171,102,167,177,73,245,186,92,207,247,96,163,181,206,56,226,251,71,42,247,166,57,170,149,145,67,168,161,186,154,82,49,64,137,19,64,142,164,231,108,153,122,84,147,13,124,57,36,65,24,243,103,7,119,126,151,173,171,128,55,216,44,72,86,114,75,139,127,136,142,197,188,81,132,153,247,82,135,61,142,125,143,68,80,62,160,192,186,177,79,233,22,230,94,150,171,207,153,104,212,221,199,223,222,61,133,164,218,126,203,145,124,187,44,198,240,244,187,187,64,25,147,85,124,227,122,55,227,59,96,178,252,119,7,176,202,244,132,72,73,185,195,176,158,241,158,122,240,128,72,241,180,150,
211,50,204,122,231,56,138,245,165,16,165,160,134,112,201,51,33,242,195,114,254,77,37,145,36,10,86,8,24,87,80,93,171,212,62,157,69,93,139,102,114,101,173,146,46,86,177,162,41,189,213,174,231,27,0,108,179,60,66,178,92,193,110,141,136,2,103,19,170,141,229,202,73,65,207,201,58,174,159,170,84,253,152,217,207,247,85,222,191,222,30,167,139,53,137,52,126,245,193,142,68,177,144,239,232,197,167,66,185,252,57,214,123,98,104,13,219,205,148,244,158,231,43,85,166,79,35,112,209,117,40,17,177,189,23,53,165,44,35,171,62,175,164,50,149,37,8,63,254,161,231,93,173,72,114,206,77,54,227,206,110,157,67,102,39,151,73,229,58,235,233,203,81,160,176,135,24,234,84,122,136,49,204,78,182,38,228,168,89,60,9,205,17,118,94,28,173,139,220,163,14,125,45,63,202,124,21,114,45,122,163,151,176,148,220,239,111,95,160,176,64,51,115,82,182,69,56,162,83,193,243,193,186,152,199,40,137,208,6,97,151,159,39,240,211,17,210,118,73,216,50,235,16,68,58,165,204,23,200,52,108,211,48,158,21,141,219,122,108,36,208,150,129,159,222,
158,28,138,152,148,34,62,69,27,140,55,113,215,51,50,246,204,143,111,182,133,250,207,114,121,174,70,175,168,107,188,6,148,121,111,225,111,250,148,43,111,225,150,49,58,149,199,234,22,140,103,197,251,124,98,71,235,85,145,52,58,137,50,30,199,234,105,199,242,166,125,50,168,185,19,10,68,188,76,124,181,178,44,59,193,87,184,149,149,113,71,6,228,150,10,242,30,119,0,255,122,44,99,99,87,49,174,128,239,109,65,84,27,48,211,115,188,86,21,190,111,214,79,95,39,210,157,59,128,231,118,118,150,202,171,52,169,117,11,155,62,189,40,152,175,6,143,111,184,104,63,38,158,180,78,8,106,204,192,75,176,73,145,34,97,42,241,182,236,35,208,16,16,255,91,244,80,121,87,233,14,221,4,169,34,254,2,13,46,104,183,253,233,96,73,221,91,100,243,76,220,244,176,129,161,136,252,102,76,116,64,26,44,235,111,48,89,85,141,227,248,147,156,162,10,27,184,59,9,0,91,255,32,35,93,32,131,108,203,76,113,200,37,48,250,185,192,139,182,175,71,215,37,235,125,134,135,80,103,116,67,199,62,143,253,118,240,38,109,186,116,27,57,170,146,72,117,
159,91,169,212,247,15,229,240,178,84,97,215,152,79,62,195,148,9,13,102,214,169,246,90,167,202,136,200,66,249,59,114,160,186,137,11,47,8,86,217,207,15,209,180,114,16,84,75,84,66,142,98,117,153,31,68,132,28,252,190,61,35,119,42,118,156,122,235,84,214,82,122,171,151,144,226,108,5,16,86,66,199,119,5,71,28,106,62,119,57,31,32,156,209,107,22,88,174,169,251,225,215,199,187,211,188,178,183,60,237,24,182,115,141,92,42,2,25,102,182,226,254,76,125,21,182,110,171,138,224,78,125,108,43,238,236,71,3,151,233,221,112,187,152,141,157,142,64,198,74,85,203,184,104,131,155,5,58,97,114,154,243,68,25,3,131,6,27,66,152,122,25,209,112,72,242,42,243,63,52,201,250,21,228,197,26,123,136,30,192,6,227,60,18,43,44,117,63,234,106,190,198,179,205,115,254,73,66,106,164,63,247,21,73,141,174,34,146,36,95,140,106,82,84,214,65,157,123,119,170,242,33,22,163,221,59,200,217,204,214,243,113,146,35,86,87,227,141,212,224,41,84,240,240,121,91,172,99,163,156,219,245,232,110,165,87,219,150,208,45,97,131,240,235,172,156,201,
36,130,129,244,87,134,233,244,180,117,56,82,205,73,156,93,111,100,237,117,224,227,129,158,86,223,120,229,47,52,140,193,170,73,42,108,244,170,143,72,221,82,230,179,220,24,34,150,98,162,91,115,186,41,138,47,84,113,13,23,50,164,50,212,185,45,28,204,87,197,191,107,242,168,98,231,142,130,201,163,124,212,153,14,74,148,45,52,226,141,172,228,7,96,120,137,66,65,51,147,197,250,188,229,157,244,253,132,4,241,186,168,33,129,251,101,169,104,145,126,47,198,126,164,63,62,119,88,75,248,174,237,39,92,190,36,181,114,35,56,206,243,237,37,235,220,168,37,219,158,221,52,83,160,13,199,39,144,4,141,183,188,71,103,72,35,89,41,22,148,215,144,102,107,123,96,237,150,191,108,91,110,176,244,36,79,245,161,205,7,108,91,145,6,59,33,223,23,30,227,105,246,10,185,5,53,22,154,5,70,249,32,139,222,112,243,128,84,128,102,106,252,173,119,241,218,223,57,203,101,17,160,14,83,193,142,45,193,159,13,67,24,77,9,117,9,172,98,2,220,102,195,196,223,160,25,229,203,61,181,123,61,220,211,162,44,41,35,82,4,239,61,95,222,153,177,192,
66,162,179,103,58,162,186,241,0,180,30,226,69,127,127,122,8,250,154,216,240,254,170,115,203,211,135,176,101,214,173,118,119,149,65,206,176,252,99,195,238,177,141,161,36,216,6,135,4,68,237,50,244,153,180,150,42,138,253,237,71,100,86,26,17,111,188,81,87,168,198,16,188,144,15,172,238,204,82,113,7,120,104,6,173,134,102,192,200,232,44,103,38,34,52,140,22,41,172,87,234,66,65,47,75,170,89,51,78,29,251,0,158,20,255,85,108,249,55,174,83,114,29,218,153,30,217,158,105,220,1,196,9,87,159,53,109,179,206,54,62,177,88,11,151,75,107,31,124,174,144,86,126,169,17,66,125,180,193,58,130,86,91,40,234,156,173,53,56,185,18,49,33,111,136,78,216,51,37,51,146,188,249,212,132,92,131,247,140,121,251,169,216,114,45,171,18,39,107,66,69,42,54,112,23,54,8,112,84,65,235,13,154,210,122,238,247,118,116,215,5,11,94,58,83,226,39,142,136,1,64,253,214,107,194,111,225,131,122,223,5,214,107,234,54,61,6,209,133,188,7,199,40,120,99,139,58,163,149,53,56,116,28,149,205,129,235,43,106,242,141,176,25,156,39,117,241,163,151,
170,45,232,47,40,245,47,127,248,198,148,69,125,246,162,179,58,189,164,221,19,165,75,45,188,193,68,24,146,132,6,29,147,63,45,36,44,111,4,182,175,238,179,126,148,72,204,16,99,118,92,170,189,128,182,233,106,16,150,243,90,81,76,0,249,64,248,22,54,56,36,70,233,232,123,208,72,34,71,156,76,132,28,27,163,150,177,121,57,142,157,129,201,104,74,175,29,125,181,235,219,209,16,23,102,41,111,69,215,225,187,164,172,136,248,113,43,183,87,250,135,121,250,239,28,145,251,170,239,0,141,19,215,224,41,243,130,1,246,69,247,160,232,214,246,72,87,193,215,239,168,106,119,83,111,181,202,18,71,154,65,38,213,23,83,25,35,150,65,157,199,101,197,97,41,85,60,207,22,196,71,216,170,62,192,94,138,117,104,167,222,72,201,14,255,74,7,252,81,29,242,243,251,172,145,231,193,17,151,58,52,146,62,119,128,147,178,158,194,173,105,43,143,180,240,230,22,87,184,164,72,36,192,107,205,252,86,98,27,125,113,189,118,219,243,199,117,122,78,158,234,33,85,208,30,155,205,108,169,137,150,34,221,112,77,197,196,231,181,103,48,145,230,145,
241,189,216,81,255,113,168,27,237,184,84,29,58,133,162,163,255,197,184,68,112,188,107,225,44,59,156,191,207,19,239,157,48,123,213,131,78,71,150,21,98,99,138,201,203,27,209,140,145,162,138,207,20,9,4,202,210,191,229,21,161,208,51,211,199,0,86,227,213,84,53,43,221,191,137,127,124,104,95,29,197,50,123,232,62,40,236,25,182,71,220,85,230,65,129,181,168,103,242,249,177,112,149,3,151,24,5,27,65,216,179,66,157,120,255,136,244,252,196,191,202,128,18,240,37,159,36,155,35,224,68,185,48,14,224,218,94,56,185,1,175,247,129,166,32,124,232,40,70,201,151,227,123,179,186,211,189,200,228,232,58,102,128,229,122,188,78,31,146,184,249,117,224,212,241,19,234,69,31,24,132,228,168,87,153,39,242,75,74,158,237,212,172,17,249,4,221,163,74,110,43,27,46,208,233,132,102,39,159,115,17,92,236,211,12,104,14,17,231,7,146,205,226,194,218,181,231,141,26,204,59,189,155,47,74,62,154,1,39,102,157,139,29,231,141,41,193,143,119,111,225,32,240,30,2,191,41,169,43,195,227,27,152,87,76,61,86,172,174,67,192,248,158,37,233,
245,227,49,129,241,247,32,171,13,224,194,3,202,228,137,231,61,75,50,244,7,128,110,190,94,16,168,187,80,151,133,153,254,145,222,198,193,89,27,14,120,173,191,231,101,199,43,162,205,174,85,164,91,15,32,60,55,135,242,53,195,236,9,88,250,69,159,25,54,191,146,50,64,200,195,172,230,122,203,146,249,55,104,37,191,241,234,255,89,175,206,239,109,135,208,150,119,91,251,100,198,254,97,121,7,178,19,221,97,41,102,61,142,1,125,94,226,75,244,183,93,152,215,231,101,249,97,128,142,138,131,142,52,99,245,0,18,98,220,87,78,3,101,162,121,86,67,191,151,71,253,151,250,132,161,203,34,152,124,37,180,0,125,1,164,14,223,247,30,102,23,192,57,68,66,2,71,152,48,7,91,100,91,173,100,27,202,170,81,12,56,81,134,146,104,122,49,236,50,71,247,96,173,177,178,46,197,82,38,226,161,134,80,3,207,45,223,106,35,227,185,55,91,61,228,125,21,188,5,57,248,146,116,62,13,204,42,13,20,190,36,27,240,168,78,106,132,131,142,197,26,190,56,30,61,67,16,149,43,102,37,218,232,240,90,43,157,150,68,62,150,217,220,212,205,103,197,157,205,
151,183,245,120,176,170,149,79,235,41,216,21,46,36,80,118,176,186,60,102,72,62,22,217,34,102,91,111,252,72,91,68,157,60,55,124,77,227,234,178,88,75,238,17,171,151,182,212,20,98,253,176,180,239,97,97,199,43,153,102,81,133,59,64,180,172,66,233,91,8,254,228,247,3,209,0,144,148,148,83,7,167,214,251,37,169,139,93,189,78,176,53,69,94,133,248,3,154,7,111,141,71,172,217,104,42,190,254,116,2,69,185,189,229,21,117,32,85,123,255,117,112,249,111,70,254,116,214,97,133,115,175,92,140,222,87,176,28,6,241,15,52,0,156,156,212,41,88,150,181,195,57,135,87,43,82,109,224,37,127,87,232,249,63,65,47,255,76,24,72,213,56,146,225,101,28,109,45,101,113,27,245,72,97,38,54,217,62,198,102,146,223,238,171,71,70,95,233,142,68,87,116,224,11,109,66,22,218,103,42,175,219,198,62,64,143,250,92,79,148,208,83,152,90,187,134,190,212,206,222,50,93,179,90,14,44,221,4,213,168,210,5,118,126,47,254,120,253,147,2,81,123,201,92,77,114,10,98,8,138,26,33,0,212,158,184,174,222,1,130,193,47,127,195,59,200,254,59,238,21,31,79,
105,207,198,12,75,222,199,93,9,4,50,103,162,73,145,190,246,167,83,42,249,241,228,228,79,200,31,251,31,168,4,126,175,210,248,255,111,253,136,158,48,173,143,204,20,50,252,185,50,15,197,63,56,27,140,176,56,138,225,254,61,67,226,191,179,78,241,115,82,24,164,178,131,201,244,169,224,46,5,11,28,145,141,23,46,60,209,161,70,150,144,34,128,78,124,154,137,27,32,64,164,57,54,20,200,138,29,240,100,12,53,21,109,122,140,214,16,147,194,206,173,232,199,63,139,105,143,76,165,47,51,63,133,253,118,7,61,14,207,103,170,248,150,42,120,73,55,173,179,55,226,161,111,65,131,109,12,6,117,68,224,40,41,161,250,99,75,63,192,14,234,63,39,247,237,95,47,217,223,128,7,254,128,34,35,12,42,57,135,42,12,39,125,34,50,163,120,89,5,184,6,247,193,247,195,84,184,235,237,123,8,21,15,58,59,183,199,147,229,119,208,33,115,150,64,160,216,77,246,58,47,93,97,191,244,53,58,95,159,37,213,3,167,153,55,239,71,107,58,129,111,57,125,18,22,47,163,35,109,217,181,2,106,144,183,117,78,46,19,198,218,30,14,115,93,131,221,12,242,207,6,67,
120,163,109,154,206,43,187,238,0,181,110,35,228,6,106,228,183,206,25,119,128,251,62,27,183,158,28,55,87,250,7,208,199,79,119,71,147,223,144,78,25,208,141,197,247,95,81,142,252,251,77,170,37,185,127,63,65,212,36,108,201,65,203,24,51,152,21,152,218,79,164,34,186,159,42,59,244,194,183,190,186,115,45,108,155,119,129,210,226,107,214,235,166,58,35,255,4,1,202,141,73,31,231,163,102,87,213,152,111,234,51,214,122,123,99,254,50,100,199,133,137,248,55,137,124,124,163,151,167,211,151,227,135,226,95,211,232,187,250,145,54,168,20,96,134,141,250,35,194,142,206,54,61,244,134,18,30,190,33,141,12,161,234,42,75,223,114,110,190,28,251,248,174,36,175,167,9,188,114,2,89,236,120,68,18,190,82,28,183,114,230,67,155,55,64,32,209,200,118,11,55,62,105,197,55,127,58,99,253,222,255,14,224,69,105,45,191,67,126,90,68,233,97,251,150,71,137,177,192,136,142,27,50,170,165,87,99,229,163,87,137,100,243,191,107,253,51,195,125,79,226,229,41,234,217,158,150,61,228,37,49,21,41,4,36,155,239,46,89,152,216,197,102,246,114,
237,234,25,32,178,18,222,7,16,186,177,45,244,42,72,161,175,27,236,223,18,74,117,166,11,99,147,98,144,89,129,207,52,68,20,139,206,110,213,151,207,206,142,230,251,251,119,20,228,173,37,195,83,142,24,85,202,11,74,206,147,183,110,37,111,86,80,95,192,131,251,143,200,191,60,146,38,202,211,12,133,190,228,138,32,140,77,175,152,125,207,38,77,199,88,74,255,98,76,176,109,87,101,139,32,91,229,65,178,111,236,174,198,59,222,67,188,175,155,127,161,91,139,20,114,122,2,163,227,119,47,149,12,78,111,152,79,179,140,158,182,90,4,115,179,42,103,21,38,83,89,230,169,1,121,100,71,99,102,251,108,90,98,187,218,21,14,174,212,112,72,8,11,184,19,87,143,78,5,33,143,58,52,158,197,177,116,173,66,107,160,102,7,157,209,217,141,145,180,181,222,139,139,182,123,57,11,19,23,240,109,125,62,252,176,225,97,231,208,202,205,177,132,126,164,50,143,106,99,248,251,209,75,158,109,184,137,51,118,41,137,116,23,245,42,190,156,158,242,226,0,85,136,244,98,194,89,251,156,80,196,25,213,210,112,131,194,207,116,62,198,160,182,142,21,
150,182,6,59,152,53,73,22,195,159,173,207,28,27,153,14,169,135,178,166,240,41,237,73,216,90,166,95,164,195,134,52,130,221,22,212,226,214,111,197,250,122,249,0,192,49,97,109,87,119,30,194,216,143,233,171,171,227,78,47,104,26,195,196,190,247,133,249,36,21,148,54,115,145,244,233,215,15,43,27,50,221,243,19,92,192,116,27,10,47,85,229,114,187,36,96,42,64,76,173,133,39,242,37,183,159,130,105,201,75,0,205,151,129,250,124,160,55,227,164,97,139,103,80,215,131,160,195,186,161,214,56,153,136,195,19,209,27,175,65,244,191,137,129,254,45,140,244,15,222,71,102,76,22,114,3,105,233,208,155,115,127,247,212,136,117,59,238,52,104,19,71,38,140,244,217,218,40,130,191,64,176,72,43,111,233,206,51,167,67,170,194,222,60,245,194,223,154,27,56,129,162,52,53,37,158,46,165,77,166,38,79,71,114,152,95,135,126,40,125,252,203,96,4,170,247,97,213,148,40,75,232,5,199,2,95,51,120,107,78,46,151,32,40,134,50,228,234,150,252,13,37,233,8,146,113,16,205,105,9,38,30,76,19,65,92,108,21,223,213,25,46,20,34,36,194,179,116,
11,156,134,150,146,59,21,161,80,142,165,164,144,164,172,122,170,16,139,148,168,118,229,114,122,42,127,111,238,230,84,99,195,131,129,43,201,157,10,17,220,226,60,165,167,198,194,47,198,64,210,30,227,109,109,187,234,185,97,95,131,196,53,59,226,88,252,147,8,75,232,213,21,52,183,243,31,213,176,221,47,216,122,56,169,80,22,33,137,227,169,225,47,236,216,218,206,106,19,217,120,105,6,71,176,98,251,235,217,146,208,42,121,117,37,229,238,143,190,253,134,61,170,145,157,95,147,184,218,62,53,149,161,223,137,88,7,160,43,132,121,145,59,67,201,98,172,227,28,79,87,251,10,223,106,32,177,227,164,251,186,19,126,189,93,1,21,30,253,51,96,142,95,218,96,109,241,178,48,161,39,13,220,215,33,52,196,43,135,122,148,61,239,120,65,76,250,78,209,25,107,131,142,61,211,65,228,14,208,121,189,136,220,83,25,126,18,41,70,143,53,92,63,154,195,153,46,97,164,111,254,220,197,225,17,105,170,25,76,85,238,254,85,200,180,122,185,132,159,149,229,68,114,216,14,74,196,68,221,57,203,232,204,230,211,111,71,223,216,23,222,224,221,
54,216,205,227,31,56,197,189,41,219,142,112,248,46,133,37,58,96,9,79,1,187,237,90,15,99,248,99,4,34,243,114,50,252,119,58,115,127,171,237,210,57,71,53,121,38,249,56,7,95,55,113,12,145,27,95,172,97,40,237,121,218,178,120,205,82,228,173,116,199,88,203,246,150,239,0,12,83,119,10,105,221,135,115,92,30,190,93,92,37,198,215,203,220,247,194,2,123,132,39,62,53,217,73,46,94,175,148,54,139,140,196,75,97,53,86,74,35,59,42,39,72,80,253,71,206,166,166,218,39,11,188,48,150,175,228,106,18,20,250,97,79,39,200,243,28,130,165,240,96,90,63,153,178,89,167,37,177,109,74,168,106,129,211,121,8,82,251,150,248,174,42,6,130,172,247,188,43,255,163,72,137,118,215,105,62,47,130,201,23,115,224,169,238,26,56,93,149,142,5,161,127,49,138,20,138,80,152,10,210,13,37,54,154,150,169,229,170,10,205,134,114,143,17,140,89,193,201,68,193,188,167,206,67,10,134,166,188,229,203,37,233,184,18,22,111,210,44,35,194,3,117,63,39,116,197,9,237,35,185,5,200,129,63,142,248,96,125,102,221,1,255,72,17,202,109,248,18,182,46,90,71,
187,65,25,82,125,189,189,114,195,189,91,186,143,223,210,129,227,77,114,112,172,171,221,171,255,133,199,204,109,54,67,73,224,70,52,193,110,249,201,81,207,143,194,186,156,186,236,48,214,123,1,127,162,181,194,190,234,35,106,61,79,76,4,144,35,168,71,7,190,173,37,226,75,222,236,232,115,107,60,87,92,119,0,108,32,130,65,75,206,41,97,75,28,69,60,70,224,114,47,247,79,198,246,126,25,244,127,239,62,175,68,239,14,96,182,25,63,187,138,166,126,225,224,153,113,156,209,218,104,116,152,158,111,3,71,87,154,69,214,219,63,124,164,76,84,43,216,138,209,107,50,80,184,35,10,241,26,42,236,219,152,23,50,19,224,27,10,14,218,240,249,38,63,69,248,65,189,75,53,15,24,97,60,254,142,117,184,142,133,75,130,136,70,33,33,11,75,221,77,165,146,70,118,177,136,118,200,144,248,82,253,220,112,83,89,44,141,85,18,99,27,63,78,130,80,39,138,202,146,38,186,128,208,131,185,214,94,12,63,151,80,176,101,23,104,20,34,82,220,211,210,41,11,24,64,208,169,185,50,79,33,190,116,81,9,100,63,47,180,187,137,20,151,198,140,207,198,92,169,
63,49,220,110,7,24,202,63,134,33,88,158,51,201,130,8,122,167,57,50,174,249,229,24,102,92,149,153,108,255,39,193,49,137,41,255,88,110,160,87,55,232,152,205,236,123,3,184,226,67,168,169,197,226,122,3,250,210,109,13,67,195,168,69,19,170,38,225,101,216,162,49,249,216,13,218,143,25,75,251,24,59,30,208,120,52,47,6,72,250,114,111,220,185,22,22,230,220,65,175,52,137,206,127,90,4,206,56,112,94,152,174,36,64,245,103,254,134,52,139,219,52,192,55,168,145,108,249,235,48,254,255,253,99,229,94,97,78,128,105,2,221,128,252,14,154,175,32,32,46,172,47,254,27,169,218,27,245,125,35,20,114,59,204,219,15,99,135,148,49,115,28,74,119,128,102,197,115,37,180,60,66,2,13,224,113,213,164,89,216,171,136,37,114,74,81,172,191,6,72,255,79,124,200,191,247,154,112,198,242,216,30,102,120,126,87,43,124,59,221,23,226,198,74,49,252,104,95,111,228,208,243,86,20,145,199,233,236,123,130,175,199,118,45,89,247,57,124,206,170,223,51,219,92,138,47,7,163,24,65,139,35,246,84,87,55,161,61,185,87,153,169,151,240,18,105,184,114,
145,130,53,192,86,37,124,144,67,118,196,159,37,2,57,207,162,89,80,205,223,1,5,130,97,212,7,244,247,0,126,184,63,236,199,20,246,116,37,172,42,198,254,53,6,235,75,230,194,123,89,95,87,242,36,232,201,157,32,182,204,134,153,137,47,152,17,157,95,59,134,153,179,173,237,88,0,234,75,243,24,68,227,237,214,26,41,0,77,164,121,140,27,35,56,146,198,10,13,96,110,231,109,208,25,50,196,100,22,185,15,96,242,29,150,38,56,158,186,252,37,159,112,76,38,244,83,92,148,5,155,126,111,109,100,3,105,6,231,122,150,34,60,28,94,54,86,250,102,173,230,4,218,38,7,75,82,136,123,33,71,0,164,10,65,191,152,112,215,51,57,72,11,245,255,130,240,54,124,11,161,242,80,134,189,127,218,72,32,84,84,26,99,227,237,122,147,196,237,255,35,103,159,170,181,100,219,99,174,49,210,220,56,38,240,9,21,237,163,203,12,203,3,95,34,196,130,50,189,159,238,245,104,125,60,178,232,96,87,232,146,114,95,166,10,245,81,169,116,249,78,171,127,170,216,119,129,160,129,186,195,238,0,81,54,249,46,147,157,84,160,53,61,153,50,109,199,114,129,34,186,74,
166,194,178,4,73,174,243,32,159,246,41,47,25,223,39,3,31,23,210,158,113,224,47,116,76,29,203,92,91,132,155,116,202,2,43,86,242,212,55,173,223,142,78,149,31,54,204,62,125,94,222,238,193,20,226,195,64,78,239,208,69,33,104,237,56,232,73,185,208,59,93,111,41,39,236,82,168,214,103,51,245,82,242,137,32,103,82,235,99,179,113,144,222,87,179,226,14,108,118,34,197,61,174,213,195,153,241,202,146,245,104,28,183,42,176,204,144,113,108,48,70,203,128,236,89,6,174,91,20,133,233,148,122,154,68,51,85,224,85,180,175,237,145,64,222,227,199,166,60,30,127,66,126,41,210,242,194,227,166,149,83,253,191,132,185,150,23,190,129,167,125,56,124,59,119,154,246,160,183,1,172,237,190,239,39,124,30,47,153,170,206,17,101,34,198,40,208,9,173,210,64,228,201,24,27,169,146,11,132,159,149,29,25,49,80,69,88,3,180,63,88,138,131,98,156,9,227,145,157,32,210,100,121,210,164,85,55,37,42,184,99,177,200,78,235,149,139,30,128,9,191,40,86,201,167,134,21,8,138,159,126,20,8,80,47,221,174,145,68,224,94,175,246,176,87,140,144,105,
95,43,254,172,228,184,122,253,139,153,79,37,82,134,253,124,197,198,62,136,231,43,232,123,42,60,19,123,59,10,158,100,63,95,89,134,7,234,173,102,74,6,12,36,127,201,223,212,216,16,1,191,176,220,204,101,52,83,28,29,189,127,91,238,3,227,29,195,242,45,213,135,184,118,26,9,80,137,95,51,222,1,148,22,224,109,151,97,39,91,199,28,239,22,223,147,137,30,127,187,3,112,233,165,232,201,205,254,244,156,254,178,240,72,68,139,218,151,7,0,18,250,211,188,50,142,78,208,97,121,224,78,121,13,58,137,151,171,72,8,252,218,28,89,91,229,208,52,173,32,46,235,122,156,194,206,78,84,176,91,241,189,75,164,0,26,195,212,164,237,134,168,254,45,204,237,250,236,43,232,93,223,49,185,105,54,152,245,227,173,93,159,24,213,171,205,218,181,244,66,64,208,33,13,149,221,29,64,17,52,12,205,224,165,112,241,20,170,148,114,33,166,67,23,14,212,91,201,182,124,165,58,18,167,210,220,197,239,229,43,122,140,96,53,170,253,77,196,249,31,3,246,127,209,189,132,168,107,61,90,211,114,246,76,115,145,142,240,19,66,17,187,12,124,190,22,51,179,
83,117,171,183,54,182,80,219,145,139,65,244,228,243,237,118,238,57,221,30,228,163,111,27,232,5,48,59,12,136,112,74,74,156,165,246,76,112,125,189,25,147,240,88,157,52,79,20,107,197,19,213,144,79,66,81,95,97,8,178,0,191,213,151,233,82,16,104,131,28,56,6,75,183,111,119,232,177,121,83,66,34,99,48,18,166,241,249,180,44,81,136,18,157,0,106,180,171,132,78,246,115,113,132,190,234,202,237,118,151,175,68,58,148,172,164,123,19,36,203,197,60,246,200,209,137,140,161,95,57,136,203,6,90,210,25,226,134,183,232,185,31,168,251,163,15,134,53,215,125,221,110,55,149,160,3,205,177,6,206,215,158,148,80,113,187,188,128,13,59,163,142,158,156,239,105,32,69,227,162,139,89,238,186,39,181,121,123,201,62,68,183,77,84,122,124,184,123,75,21,233,97,109,255,225,23,89,255,209,189,59,71,123,10,154,171,187,27,205,32,103,103,38,241,109,194,226,94,157,49,245,41,31,92,52,154,119,200,51,199,61,203,161,59,129,95,175,115,244,18,111,91,159,123,235,180,99,252,86,130,174,193,197,128,161,36,52,117,66,5,67,145,47,7,179,180,
186,31,71,63,168,22,56,246,96,8,130,4,33,38,203,51,126,57,150,117,255,164,12,51,123,8,134,124,2,97,166,44,127,27,143,72,221,96,146,253,142,83,72,133,56,96,48,124,197,160,23,166,239,1,152,65,124,84,199,47,58,151,74,175,159,149,176,138,54,0,192,238,183,240,71,3,177,106,94,8,250,163,209,64,39,8,144,172,229,56,255,11,205,85,142,13,32,37,52,238,52,208,82,180,22,15,229,203,224,253,128,32,185,34,104,207,144,126,120,10,207,160,95,137,16,208,105,3,162,253,169,228,133,105,89,143,244,155,130,39,235,137,61,162,130,71,188,112,62,242,144,228,201,131,134,216,186,49,186,21,63,112,177,109,34,206,167,189,129,204,23,228,154,55,25,242,22,210,6,65,24,120,70,233,138,43,205,215,219,213,165,190,216,32,50,17,92,6,1,212,110,47,252,8,151,219,79,215,96,195,250,28,165,95,220,103,232,163,243,16,158,59,128,165,14,187,130,112,199,173,243,110,194,154,47,62,175,235,115,135,174,48,105,219,84,31,17,95,157,65,116,146,236,111,17,72,252,144,237,112,183,250,248,230,77,29,239,188,149,41,105,245,22,98,8,9,172,217,176,
195,83,105,144,228,235,226,43,55,44,59,71,189,166,131,173,101,25,182,57,226,235,124,225,216,61,60,170,239,19,49,211,51,242,69,11,236,4,177,201,103,162,168,155,249,189,242,102,38,84,207,8,101,200,15,39,14,54,47,84,223,58,141,42,75,252,225,69,116,126,211,122,31,100,132,9,134,38,222,46,189,218,35,235,66,113,162,182,99,157,67,104,96,170,174,78,165,183,138,30,181,178,199,210,111,86,119,147,28,215,191,238,100,35,146,118,181,105,134,107,229,80,201,129,147,33,133,116,166,61,184,169,26,175,44,192,49,252,165,117,4,155,186,108,97,184,172,31,140,15,166,140,157,242,226,122,145,243,192,51,29,207,70,10,222,163,102,226,202,238,141,2,220,202,124,78,103,29,219,93,52,10,5,202,108,46,0,136,116,221,137,207,43,124,3,122,140,184,246,186,186,231,228,19,124,94,130,19,18,232,133,159,198,188,68,27,221,202,70,209,168,3,48,58,149,192,63,214,222,246,144,72,179,72,138,35,82,219,190,46,214,96,109,133,33,237,235,43,88,220,1,142,112,16,86,170,236,201,117,144,132,137,197,103,109,34,243,236,176,239,6,191,107,14,
174,209,248,105,177,34,81,173,99,141,220,244,51,239,156,236,225,190,186,110,218,104,90,46,87,191,239,229,9,210,200,208,191,39,130,33,233,93,78,234,105,246,217,136,9,141,250,199,119,120,250,84,67,63,93,59,230,147,121,142,199,112,160,76,140,18,174,45,60,188,22,102,192,179,11,255,150,249,117,101,225,218,151,180,214,113,45,206,208,114,171,115,160,199,114,150,67,73,167,117,252,12,135,12,251,237,16,217,219,137,252,155,53,71,254,198,224,122,14,141,37,143,174,96,69,143,6,130,132,118,21,180,247,83,193,178,77,216,176,80,130,4,159,39,222,219,159,74,176,103,194,108,88,86,29,129,244,170,234,93,235,103,185,104,61,138,251,170,165,183,240,168,248,171,209,236,159,36,225,43,41,10,139,72,209,6,51,247,219,147,145,231,13,0,29,247,173,210,184,171,81,188,231,13,192,56,91,15,128,87,197,24,73,222,246,235,47,158,99,36,38,153,104,125,12,74,159,182,100,140,139,185,187,199,43,223,137,5,155,149,94,164,151,202,51,40,199,86,128,107,83,165,173,34,142,236,245,82,14,22,94,121,134,191,159,100,250,222,137,28,61,
177,169,231,153,15,226,91,219,162,38,33,65,164,185,80,153,131,205,76,217,73,236,63,91,235,159,189,223,56,185,117,78,103,241,112,200,18,119,22,114,91,209,204,145,30,52,120,128,170,252,3,85,48,140,245,253,224,47,243,9,150,244,188,252,150,162,233,143,166,136,201,205,253,149,4,209,13,152,78,182,159,112,134,238,185,47,167,169,83,184,3,124,142,138,238,14,0,57,159,16,178,93,4,135,154,97,225,127,76,247,195,142,215,131,75,60,70,126,119,48,16,0,28,44,77,226,74,16,239,199,195,158,159,31,155,99,41,102,86,7,48,19,3,112,1,121,191,119,221,198,127,160,254,69,239,50,67,120,139,215,213,104,48,144,58,218,227,242,89,125,200,114,98,194,167,181,88,85,172,21,183,13,129,1,213,139,245,98,220,225,55,82,81,83,85,184,172,57,229,62,82,252,101,134,220,134,31,139,224,144,58,1,68,210,79,14,62,101,102,84,79,135,120,187,83,162,42,82,20,56,172,162,26,145,229,127,165,93,138,212,231,128,189,147,89,3,192,181,56,214,9,104,0,103,132,157,69,85,110,52,32,156,79,57,119,78,129,50,135,75,5,152,195,250,62,245,177,166,198,
87,97,74,115,100,246,155,78,190,62,189,175,160,201,250,20,4,5,230,170,96,254,74,202,81,151,223,109,219,158,39,251,64,162,78,166,8,141,18,118,210,23,246,225,115,149,36,10,247,183,204,0,78,241,102,40,238,185,117,46,137,141,225,44,36,248,45,46,34,229,195,243,75,173,36,247,78,177,160,73,20,43,75,197,122,202,91,193,48,9,4,182,23,65,162,248,18,87,130,237,119,65,189,40,255,43,111,99,62,51,184,99,126,254,229,97,7,178,139,136,61,34,248,120,239,215,83,225,194,173,75,135,173,100,167,196,62,191,206,15,76,153,162,27,124,30,8,118,101,72,199,244,253,41,61,33,20,214,0,7,140,85,13,34,92,28,111,158,21,232,125,198,44,48,219,172,37,134,168,183,199,219,203,104,136,215,25,196,130,123,243,204,6,43,166,166,108,150,79,87,128,36,117,66,77,37,76,22,241,66,124,128,132,125,33,168,134,20,220,143,228,49,124,226,189,181,234,48,46,236,48,86,189,118,86,38,51,194,60,25,101,235,81,25,127,53,206,45,191,15,124,104,235,209,210,158,149,194,42,34,205,46,176,173,117,95,84,193,98,121,37,29,70,13,246,206,153,79,182,65,
92,105,50,63,203,79,137,242,24,228,17,47,88,129,104,184,223,108,229,40,42,9,207,159,104,74,132,50,22,199,201,41,215,143,1,101,188,183,165,91,23,5,181,44,63,84,168,116,115,52,168,38,130,182,11,238,105,147,60,253,84,136,171,185,232,156,103,218,13,185,3,224,152,115,111,105,188,151,165,168,129,172,49,40,60,55,22,209,141,66,172,60,69,233,25,254,113,149,107,53,17,224,25,63,220,248,254,75,149,156,144,52,100,100,47,123,229,69,65,205,245,118,198,65,116,136,209,176,213,74,90,130,107,133,87,96,25,210,62,92,180,167,214,227,152,137,137,201,197,60,1,129,35,252,241,229,80,126,35,94,142,132,58,55,12,210,254,164,79,143,11,160,232,83,255,60,182,220,248,161,227,65,142,203,134,64,201,227,211,128,211,209,246,58,139,126,241,179,98,65,211,200,83,1,175,110,12,122,39,228,116,196,20,89,239,215,61,250,203,113,205,254,227,77,214,34,139,167,75,142,244,70,169,184,37,136,84,112,4,90,241,195,130,228,85,17,16,80,68,76,29,133,145,137,23,15,191,225,150,187,191,113,97,199,163,110,109,195,53,223,144,209,217,136,
135,87,171,73,247,66,213,123,100,2,125,228,250,20,74,212,80,145,162,88,109,98,194,143,86,187,217,167,32,12,117,208,170,3,59,71,56,106,19,157,213,227,130,17,153,248,196,221,16,98,91,183,109,77,133,248,55,22,105,17,174,179,206,5,124,167,82,160,181,241,171,168,202,252,171,40,88,218,199,190,162,125,183,109,173,199,26,238,3,124,10,218,179,103,165,23,123,231,194,99,173,241,86,236,130,91,43,80,62,162,36,19,198,44,143,44,73,73,75,98,234,196,75,187,247,152,40,19,16,183,199,45,81,253,101,221,17,128,191,176,33,116,31,197,21,144,177,117,207,238,212,163,102,147,221,231,18,202,127,161,91,44,189,229,25,123,178,121,62,14,125,79,155,150,252,76,190,157,203,255,7,142,205,43,108,187,215,229,175,179,148,37,1,4,203,72,40,248,49,30,129,58,65,36,32,2,71,41,155,245,55,59,34,60,179,87,64,216,31,95,71,245,30,119,73,17,16,233,67,196,3,73,113,194,245,244,231,7,175,29,190,157,61,96,52,20,77,166,122,181,187,127,171,152,175,242,243,190,82,143,36,6,29,117,216,163,207,84,212,91,151,175,167,157,219,88,159,32,243,
37,67,194,46,31,119,220,98,68,105,234,45,207,241,224,95,15,94,82,217,250,30,121,61,87,31,178,121,202,244,86,105,145,74,118,63,71,87,198,161,215,81,64,114,58,59,213,97,25,34,245,188,193,244,168,0,197,48,87,11,3,146,119,63,32,182,44,94,109,155,207,152,126,76,176,111,95,231,40,87,189,79,153,143,95,81,43,192,215,195,46,249,139,83,136,163,98,255,29,64,32,255,211,205,86,72,234,19,225,45,189,46,118,61,139,98,162,148,249,98,146,155,45,198,148,121,136,202,253,68,61,91,15,232,207,92,148,245,66,208,75,176,249,8,67,133,12,67,159,88,95,188,216,236,6,22,38,95,93,150,155,203,138,114,205,155,172,153,12,217,97,149,8,194,41,193,134,224,31,164,40,211,105,61,215,33,54,224,5,47,138,197,31,86,214,57,233,110,29,179,38,74,209,13,123,222,77,8,178,215,226,62,250,43,35,107,242,227,111,207,86,88,222,121,239,59,238,94,223,166,121,38,31,23,143,58,186,154,134,106,34,236,201,239,52,231,127,188,119,144,126,229,62,32,51,6,11,189,7,61,81,18,182,225,84,59,67,172,2,172,239,135,82,124,252,50,221,216,43,213,63,46,
7,97,228,19,60,156,9,244,154,189,74,138,207,13,183,58,36,89,66,238,149,135,166,63,10,86,97,221,74,83,108,35,245,201,46,56,51,100,18,25,181,243,197,59,104,183,247,40,104,195,227,11,13,50,138,121,104,95,185,43,26,5,118,155,0,203,88,178,82,18,115,16,99,189,152,244,118,212,75,114,60,168,218,254,78,99,109,178,184,242,142,222,199,169,170,233,190,141,87,51,233,184,65,124,148,146,255,197,216,149,165,119,144,169,123,212,69,30,191,58,99,229,201,62,158,238,66,215,11,201,22,232,219,145,198,199,23,94,189,228,230,82,103,51,2,215,95,116,19,63,45,137,136,42,182,176,48,208,229,107,32,31,237,95,55,20,51,232,238,18,26,76,30,239,99,156,35,249,107,145,0,176,236,250,165,238,223,50,54,24,14,15,147,177,58,7,160,78,7,30,51,141,142,246,20,135,17,138,97,161,1,144,253,158,128,209,246,171,91,127,121,251,255,132,61,138,137,134,74,41,242,19,98,234,136,0,214,232,9,97,116,176,79,233,233,162,241,29,160,247,249,109,200,181,175,224,142,121,38,94,106,189,212,34,9,196,212,46,150,208,68,184,140,53,168,110,132,221,
106,54,228,37,215,174,254,91,93,173,153,249,206,181,217,214,10,14,171,40,4,45,185,140,67,247,220,29,117,153,71,27,112,113,139,222,108,59,144,117,195,234,225,22,42,245,82,71,245,133,249,172,248,122,58,61,223,15,193,137,182,169,197,132,0,201,46,169,131,207,45,132,221,186,110,150,151,83,81,70,86,120,150,219,145,110,210,136,204,229,108,85,133,71,170,198,95,170,223,47,229,216,246,228,76,222,1,230,68,19,44,204,27,2,63,197,95,108,140,7,114,241,161,77,220,110,94,23,98,210,240,99,248,178,8,40,57,62,36,81,132,112,118,89,154,87,94,21,69,17,49,94,151,0,71,90,147,206,176,121,200,144,78,138,28,223,185,26,236,243,220,71,172,195,145,60,88,62,84,6,77,69,141,252,236,93,50,88,201,17,124,172,208,243,230,205,42,126,42,246,202,139,198,132,45,82,38,127,182,167,248,32,59,110,81,127,223,162,235,78,170,52,199,1,194,97,6,102,87,225,222,54,125,220,188,106,22,16,145,227,232,225,200,150,7,110,194,214,37,71,160,213,73,59,48,134,245,243,134,101,116,210,33,124,119,243,124,66,2,181,30,56,132,177,20,169,140,110,
66,181,193,199,224,32,171,160,176,243,115,145,139,127,44,23,247,159,12,35,255,226,30,254,158,189,241,231,118,65,171,68,222,88,199,84,193,0,86,202,237,214,100,249,193,117,100,170,178,142,237,139,245,170,31,153,184,68,199,75,176,212,222,143,171,17,229,194,193,111,240,190,155,126,193,107,117,11,237,223,246,253,142,0,176,60,172,9,116,253,215,69,15,138,114,110,225,77,235,11,75,138,209,75,111,164,167,230,108,124,31,33,50,28,157,84,235,144,163,42,206,61,11,102,118,185,249,133,189,122,138,162,188,127,18,183,190,178,213,11,228,205,160,206,88,145,124,216,112,164,84,28,117,186,97,5,134,137,241,209,73,199,208,155,23,230,100,23,54,19,108,253,218,249,9,216,219,100,99,251,14,141,67,7,224,174,23,79,110,29,234,203,26,97,40,215,57,166,14,162,69,254,217,177,209,223,219,158,201,220,118,204,244,44,241,203,199,116,1,142,81,96,149,114,14,39,30,123,55,83,41,98,163,248,186,242,76,28,55,83,153,37,45,85,33,77,99,211,220,66,72,166,182,57,17,131,64,167,106,84,126,222,95,59,118,127,130,2,248,43,71,241,55,
218,195,154,248,181,107,98,19,253,111,174,9,255,15,116,225,203,241,134,223,76,196,254,31,69,36,252,13,167,236,63,253,206,110,253,222,208,5,146,233,220,149,77,157,29,208,238,136,238,238,91,172,141,132,14,254,178,24,191,230,0,36,244,0,28,229,104,105,88,148,47,231,19,58,1,44,15,37,212,69,7,36,56,156,160,242,15,16,100,126,239,0,250,87,253,255,62,178,210,191,158,237,95,63,219,159,255,189,32,110,250,91,189,20,182,194,236,37,208,52,178,80,87,222,185,2,104,6,92,193,118,188,80,66,127,245,43,151,236,215,238,217,255,43,199,200,63,233,201,81,89,31,224,104,217,1,195,247,13,223,72,35,137,108,121,252,191,177,160,113,246,223,193,139,254,15,117,144,239,166,146,205,0,0,55,164,29,93,142,183,171,213,3,13,38,232,120,183,139,173,65,247,239,63,38,98,215,209,68,108,213,159,255,215,102,183,212,218,26,132,46,234,118,48,18,255,116,170,223,216,148,155,231,34,227,241,96,238,167,8,35,209,94,91,122,173,196,187,203,112,116,124,234,123,175,253,48,30,32,209,138,161,188,7,252,235,228,207,123,6,254,104,247,50,94,
120,91,206,46,53,253,127,220,125,231,91,83,79,180,53,36,33,9,45,36,116,8,37,244,94,164,132,34,66,168,130,8,130,130,210,13,72,55,84,17,16,80,9,1,164,119,144,166,134,42,189,55,81,36,32,32,189,9,2,2,18,145,38,130,2,74,71,120,243,123,238,159,240,126,186,247,211,201,147,51,231,204,204,158,57,51,207,94,123,173,217,20,251,226,96,212,2,17,170,232,153,96,116,54,20,142,199,160,98,80,246,61,144,119,20,211,99,111,65,149,222,80,93,248,208,81,161,179,40,163,160,79,76,164,55,132,188,136,212,45,248,249,87,152,95,16,96,140,193,50,113,153,93,86,253,250,136,182,253,59,211,30,173,96,29,20,116,144,70,253,131,108,117,65,19,240,145,111,101,93,15,139,128,70,234,181,218,75,23,210,124,178,84,64,229,213,208,133,41,34,54,16,248,148,141,207,241,124,119,155,186,11,1,13,108,45,137,38,95,80,0,129,113,255,221,32,245,184,80,164,222,74,164,40,196,76,44,236,89,50,51,126,78,16,14,96,148,61,186,202,244,166,63,200,205,118,87,205,66,26,155,171,235,98,5,17,244,21,0,8,140,233,128,47,206,254,104,241,116,67,139,9,73,117,
162,71,234,154,35,31,99,72,249,136,178,126,204,27,210,17,145,72,80,187,243,244,164,93,34,252,211,29,130,50,10,240,92,8,142,67,229,226,119,72,110,60,21,124,206,182,223,246,158,215,129,40,147,138,61,28,227,10,204,166,125,213,73,166,226,207,104,233,6,228,118,73,50,227,71,4,80,247,90,215,209,151,145,101,158,40,231,29,203,36,185,10,94,51,181,13,46,79,246,171,160,19,61,204,51,239,87,52,231,251,119,234,240,229,96,20,176,136,160,163,182,113,152,40,157,72,177,219,16,194,80,232,112,47,34,142,89,1,73,50,149,87,48,91,13,199,153,17,123,140,5,229,21,65,97,228,3,79,233,224,130,29,129,52,70,215,207,223,171,96,136,217,103,225,76,11,93,179,168,13,170,36,224,38,248,244,4,127,24,75,250,11,101,24,6,91,171,185,155,74,94,95,10,248,76,153,245,120,58,188,227,28,198,132,38,207,209,98,154,204,63,42,97,177,241,135,95,80,94,12,4,118,33,220,96,207,58,59,110,20,7,163,187,12,209,217,183,214,27,101,245,136,6,168,9,237,199,127,186,47,34,156,194,50,1,101,84,198,108,10,92,127,55,95,183,213,181,159,169,83,62,156,
232,112,216,226,203,174,217,2,130,30,56,135,49,228,137,64,188,16,64,143,200,4,114,222,56,48,191,110,109,80,135,175,113,236,177,161,177,239,206,30,32,30,170,100,249,172,239,55,192,57,49,84,207,105,72,131,247,243,230,80,123,72,212,170,209,251,142,189,131,198,71,98,40,226,77,191,238,63,97,1,30,208,21,63,38,245,186,162,182,171,211,88,15,94,117,187,199,233,86,12,135,128,44,13,101,192,106,191,207,219,151,237,79,194,46,236,224,208,31,217,198,81,86,201,231,136,24,83,239,142,141,139,199,210,126,5,208,200,48,233,166,243,170,64,14,80,225,115,91,217,246,176,87,99,56,32,30,158,236,165,20,84,89,157,224,237,237,128,99,131,183,188,101,196,167,36,181,48,61,242,81,134,234,105,205,112,84,122,240,35,39,33,0,1,158,199,172,125,10,107,241,152,128,128,71,151,150,54,27,92,211,81,41,145,247,210,130,248,131,203,45,126,146,94,159,109,4,128,174,177,103,123,188,126,245,85,252,73,145,27,200,66,33,68,246,79,225,242,181,250,142,50,212,147,55,120,76,172,244,92,11,53,236,194,18,164,103,176,70,208,147,169,107,172,
248,18,134,105,39,138,210,46,209,95,35,223,137,37,25,66,183,82,168,143,177,194,43,199,220,130,242,114,160,47,109,225,1,242,181,154,78,94,49,36,113,232,150,0,65,141,75,161,136,76,122,14,199,143,8,213,61,103,48,132,228,61,103,4,212,93,2,193,82,168,127,96,239,53,144,214,188,121,240,4,103,140,250,108,91,64,221,241,188,14,209,153,144,165,127,52,15,32,84,139,0,108,13,136,40,224,55,128,209,116,47,206,222,150,29,210,242,248,19,212,25,189,51,245,62,171,67,238,151,15,55,47,250,37,20,7,197,115,254,149,248,169,53,121,226,153,245,59,255,189,143,174,123,93,185,30,118,8,10,66,198,184,162,148,118,184,158,77,104,135,53,184,4,207,6,10,214,9,128,194,134,197,20,142,34,128,97,102,91,60,234,69,189,172,200,77,78,116,38,52,33,9,83,215,165,181,250,185,96,28,230,46,153,240,149,43,76,0,145,205,138,31,6,59,137,134,29,123,66,90,217,94,53,221,56,242,23,148,103,4,92,198,249,138,68,98,208,217,165,138,71,183,5,229,37,0,206,4,163,111,235,67,177,164,4,248,172,35,112,150,110,138,209,117,74,183,138,14,193,73,143,
79,99,92,240,67,53,210,77,23,119,91,61,252,22,74,89,121,178,153,241,88,96,36,50,236,28,160,85,152,74,189,206,90,186,197,254,62,15,122,61,28,211,11,102,14,203,232,102,228,244,145,215,190,187,147,169,135,181,1,229,51,58,179,56,246,8,10,114,34,94,63,165,155,14,159,184,250,41,16,177,100,10,50,208,65,205,134,255,100,53,208,201,175,21,0,52,234,163,54,48,51,138,186,114,238,85,142,197,158,242,243,239,239,245,198,96,58,255,235,115,117,202,36,178,159,59,138,39,235,186,194,6,135,79,150,1,136,50,230,174,132,27,100,224,229,193,188,63,213,234,247,13,64,255,21,204,16,90,58,34,182,127,250,61,100,197,77,153,223,15,12,136,220,103,35,79,215,236,252,62,123,221,134,198,108,12,87,104,86,13,91,67,149,184,136,71,23,85,123,71,37,50,130,196,155,141,189,209,181,213,35,189,59,181,114,51,159,199,147,182,203,49,27,71,47,170,181,178,228,231,213,25,238,187,63,21,57,63,126,165,172,180,157,128,118,166,250,187,153,192,220,114,152,73,194,133,154,220,189,27,95,164,56,20,191,175,252,199,55,126,176,165,213,142,255,
124,175,79,139,241,29,58,233,131,122,46,127,135,181,93,85,145,203,11,91,243,166,176,49,151,245,194,150,67,44,170,165,163,180,182,190,119,226,133,95,125,223,237,95,62,183,148,78,199,123,207,107,125,254,165,99,188,126,98,170,202,254,77,188,182,205,147,26,100,212,242,111,46,28,253,213,44,65,109,91,91,210,32,47,40,175,14,16,24,180,151,53,168,93,84,112,200,38,218,26,184,88,27,11,142,39,97,56,192,101,175,60,228,220,126,6,177,21,85,19,72,7,114,72,124,8,241,245,69,88,71,116,190,173,214,221,192,116,235,80,202,2,246,5,62,203,181,21,11,197,53,122,86,173,77,21,29,91,217,154,191,187,10,138,33,249,35,220,147,252,236,155,92,52,136,177,124,74,211,132,109,108,103,145,144,116,235,116,149,26,197,84,151,161,74,3,152,38,42,51,109,193,136,101,231,200,241,176,176,215,26,95,255,91,235,11,160,74,6,173,254,120,115,42,116,69,203,182,199,173,92,67,19,214,55,223,117,173,220,223,90,123,81,42,226,134,78,57,195,237,176,122,225,87,92,255,238,80,56,130,199,68,115,193,11,17,202,99,169,80,11,231,148,55,152,160,
140,163,147,253,205,205,205,121,149,99,130,189,196,195,103,180,206,105,89,122,147,140,255,176,169,50,110,37,177,84,136,50,184,248,0,233,13,102,24,200,117,66,198,251,44,213,108,147,74,110,118,115,140,72,119,126,128,88,230,156,61,163,172,118,52,130,102,233,248,16,24,11,7,20,17,246,113,23,248,204,193,158,128,168,83,43,249,9,89,125,206,49,27,120,59,135,82,132,25,175,65,212,189,4,239,192,52,1,10,0,142,248,188,188,60,91,30,255,219,166,112,29,95,205,240,144,148,206,142,230,125,30,145,232,119,162,128,74,12,138,201,237,186,100,156,49,21,58,194,31,47,143,175,35,45,46,118,240,6,5,145,65,230,204,249,76,105,167,40,142,58,58,141,89,168,96,157,53,104,207,10,173,32,222,134,201,38,159,159,139,37,61,123,6,185,178,180,68,47,180,144,17,102,86,9,201,211,79,101,20,3,72,97,136,130,4,51,134,154,78,93,25,42,54,13,141,193,221,72,32,71,55,45,10,180,10,84,230,32,242,177,126,238,166,163,114,100,137,33,221,70,204,10,0,57,105,187,105,180,50,232,35,233,94,190,124,245,234,238,86,138,84,1,8,222,189,88,253,133,
254,206,178,137,48,47,206,50,96,246,215,180,0,101,35,114,141,96,192,237,115,198,252,54,123,67,101,129,210,216,57,57,113,253,248,179,242,12,162,3,215,108,235,200,84,3,239,139,166,193,110,139,177,226,198,209,8,241,1,204,44,166,159,42,174,43,241,136,190,71,47,252,38,234,250,206,249,249,57,253,179,252,40,54,135,187,47,95,69,49,45,216,29,157,88,54,1,119,121,245,180,243,173,102,75,133,235,167,135,174,162,192,245,163,162,97,104,5,121,89,120,7,165,2,165,157,121,38,51,157,101,2,68,153,195,57,176,107,35,188,134,176,58,4,176,173,243,3,41,112,145,76,197,251,169,208,221,82,101,84,122,59,223,32,231,212,2,49,79,118,138,55,169,69,57,166,130,48,55,150,251,68,98,71,238,106,0,24,21,142,10,93,187,171,185,105,229,228,124,124,200,17,201,201,90,171,187,187,212,154,193,161,44,23,248,54,150,222,28,232,18,181,93,108,19,91,116,106,244,134,224,91,206,53,17,233,76,232,89,166,136,137,50,65,78,33,15,117,174,43,64,40,230,132,114,132,211,158,143,64,206,105,248,203,66,204,198,169,237,33,192,152,91,191,94,246,
77,83,253,118,74,205,187,138,138,188,190,206,194,204,181,32,193,21,147,138,181,219,249,221,121,113,135,167,155,190,11,226,36,35,188,77,105,237,87,125,137,118,215,11,253,223,191,121,154,73,255,182,39,111,24,84,211,223,21,133,234,61,19,231,34,121,160,26,105,115,24,136,28,83,118,196,38,98,24,113,147,58,33,234,244,45,178,29,22,242,188,116,35,135,192,209,209,25,216,3,96,66,51,240,39,89,113,188,167,131,234,37,11,95,214,94,99,247,241,254,237,226,180,75,147,139,79,209,94,139,184,240,109,75,162,210,60,10,111,70,5,160,240,144,101,163,5,63,94,56,153,30,30,243,68,45,208,175,235,114,233,217,102,189,235,234,216,235,170,213,207,95,183,203,158,7,118,255,27,163,12,221,145,20,203,17,255,219,233,98,96,48,51,87,193,66,242,89,112,109,128,250,225,159,193,137,107,63,166,74,79,10,38,54,91,246,57,212,182,106,184,203,32,151,250,81,18,96,83,160,95,224,131,174,38,96,142,251,84,108,84,233,79,236,207,217,151,51,79,126,167,178,140,174,119,184,231,250,188,24,175,58,153,240,168,120,91,222,170,78,174,225,142,
121,225,27,116,177,243,119,175,194,53,66,141,137,0,28,164,223,193,91,209,235,64,124,106,151,141,134,107,8,130,194,126,183,12,15,166,173,126,167,246,89,167,153,206,78,180,253,190,56,216,63,17,24,218,109,127,249,136,175,193,83,26,9,13,254,136,162,51,191,125,105,126,101,249,251,159,159,200,48,240,53,176,8,141,197,12,17,184,207,27,249,19,131,139,146,220,8,135,191,74,10,15,50,244,11,228,195,200,158,254,203,240,61,169,236,59,55,152,40,126,32,247,177,102,175,239,235,250,162,147,121,12,179,39,234,15,109,29,203,48,94,28,248,94,48,252,132,191,136,176,212,57,146,30,28,244,231,131,14,115,124,76,79,34,126,78,247,65,135,214,114,213,7,126,13,236,91,155,13,253,183,105,227,31,230,33,82,130,185,159,252,191,57,223,121,97,251,210,184,21,92,41,68,31,184,72,21,173,83,78,233,17,101,136,158,13,96,214,57,244,46,167,196,70,205,112,212,179,73,11,167,14,118,137,220,156,230,4,113,162,70,129,13,215,166,152,22,186,175,38,190,150,123,180,155,178,228,101,209,120,198,81,93,39,42,57,114,204,255,214,94,211,234,
46,147,245,60,227,243,109,84,101,1,177,30,220,90,192,205,35,66,208,131,248,242,98,115,17,131,218,185,183,119,156,84,18,182,172,77,130,22,182,112,223,133,205,41,228,239,84,216,91,199,72,179,167,223,170,130,96,255,74,218,227,86,159,170,175,105,83,141,250,251,221,190,61,158,60,180,62,244,179,224,126,199,192,30,47,217,89,220,238,162,173,107,75,208,46,166,130,123,42,75,123,232,105,225,149,50,255,157,181,65,234,44,41,231,91,142,233,217,47,151,220,127,51,94,145,226,216,56,130,179,167,240,122,5,32,233,113,206,2,57,21,250,212,233,186,108,145,155,151,215,59,67,136,62,183,155,165,206,39,82,191,150,30,184,127,216,74,222,93,76,2,175,148,48,88,124,151,225,248,57,30,193,152,198,100,46,202,218,29,53,171,112,254,211,118,83,29,186,138,185,45,231,152,150,138,243,125,105,248,200,141,204,99,71,37,106,38,72,234,67,251,111,40,115,22,100,50,141,134,238,98,151,36,109,51,106,51,233,26,76,177,206,207,120,223,157,249,182,179,188,55,126,242,233,108,117,217,179,206,211,167,153,28,233,245,13,109,24,221,253,
74,235,99,62,216,128,254,26,100,135,167,172,60,60,188,103,210,175,206,210,106,204,51,72,96,125,148,38,150,46,110,209,203,201,7,105,222,141,129,154,252,35,87,169,48,237,151,20,234,251,209,74,186,203,107,79,134,12,166,239,232,220,12,39,65,143,76,89,205,28,24,44,119,189,178,126,246,127,86,164,115,18,159,221,114,170,134,52,93,60,243,48,176,132,189,132,191,90,240,229,193,177,76,255,177,217,126,44,224,150,192,193,245,163,155,70,65,167,110,204,114,203,251,214,47,175,91,59,218,187,139,127,28,52,251,91,227,108,74,134,226,232,44,196,168,104,56,231,240,235,147,142,220,102,30,204,219,34,145,218,146,239,39,116,58,58,135,205,218,218,251,174,173,225,196,155,152,46,250,22,87,212,196,121,32,49,166,7,17,42,113,63,185,70,2,123,86,24,76,100,252,168,209,77,59,139,94,117,173,137,56,239,123,167,246,199,174,236,227,61,13,46,209,58,163,193,135,168,187,18,220,197,207,177,0,119,154,58,223,166,135,158,84,18,44,196,216,94,191,106,219,71,229,38,172,146,221,14,140,142,41,237,62,141,102,191,235,39,189,136,93,
96,123,198,40,165,106,108,35,157,250,71,119,111,61,185,224,188,186,151,19,158,144,235,163,177,12,206,117,71,6,119,122,127,161,235,91,77,154,223,152,148,24,190,218,61,56,239,188,217,116,85,206,88,18,254,226,53,22,80,64,45,208,118,146,18,250,54,161,238,25,252,164,246,244,182,241,245,199,224,227,70,119,96,36,159,0,12,81,15,102,20,193,46,117,202,179,45,248,81,169,8,138,177,141,166,148,58,237,80,214,26,131,126,164,253,241,47,116,123,115,162,183,203,196,236,150,103,224,23,237,9,190,55,184,18,64,61,157,221,182,121,245,235,179,116,54,148,240,202,1,163,86,1,184,57,155,193,141,52,82,219,36,96,214,64,237,207,231,129,90,254,249,150,70,228,55,242,60,241,116,77,213,247,191,119,126,241,213,12,172,229,212,208,6,239,176,99,31,32,141,236,94,4,181,26,133,206,163,212,188,40,205,213,135,124,252,138,62,91,215,15,205,160,95,192,64,171,137,78,128,197,79,99,217,166,231,78,79,181,220,49,30,111,111,40,198,230,70,154,117,96,209,125,19,59,36,216,9,216,13,120,105,77,243,105,71,251,185,172,55,225,99,246,93,
92,194,201,227,11,81,116,176,110,46,1,41,108,184,194,250,125,224,113,86,212,252,0,177,254,141,201,150,183,80,232,252,236,26,250,112,118,24,112,236,113,165,90,239,200,83,52,136,119,229,51,249,154,141,243,251,8,61,154,29,86,210,141,148,150,195,41,147,127,1,82,114,242,47,248,102,191,202,113,118,37,128,221,161,81,76,218,25,137,155,34,98,192,81,185,38,84,10,42,106,158,10,135,50,213,139,71,111,252,66,155,125,212,190,82,78,146,232,99,47,102,250,58,152,86,45,116,117,24,36,66,104,154,200,148,215,254,186,216,119,208,130,208,73,89,217,111,127,51,114,182,129,106,53,168,153,122,224,238,160,91,118,22,75,87,183,218,234,243,59,246,197,59,76,224,49,233,224,73,44,98,216,171,194,33,50,13,78,9,61,238,21,18,168,254,124,144,133,22,39,189,205,102,236,241,67,165,211,121,196,165,226,198,105,78,150,115,52,194,26,92,225,121,243,216,34,41,220,3,182,188,249,141,175,232,150,185,76,47,111,69,197,237,255,222,157,230,132,245,214,53,167,35,178,149,221,164,250,137,97,68,201,83,183,252,13,221,7,94,64,21,45,18,80,
151,67,68,106,203,239,67,19,99,89,31,89,82,139,203,141,233,160,246,243,235,187,90,117,84,54,234,12,186,100,158,105,244,26,162,219,138,89,112,91,49,105,174,177,158,34,188,47,112,1,153,42,173,187,139,94,1,157,82,139,11,6,251,192,96,38,87,125,136,81,241,95,80,47,85,8,117,41,252,218,41,166,163,176,14,150,246,133,32,243,207,153,73,238,242,14,147,18,17,11,154,167,106,19,6,129,68,183,199,187,172,103,255,24,211,0,216,144,25,89,128,57,34,198,131,60,196,169,149,233,138,26,253,208,67,211,50,150,249,219,75,168,252,231,67,159,188,217,133,210,23,48,112,205,159,175,203,69,151,252,17,113,212,109,40,125,19,225,83,18,250,36,234,26,149,32,213,135,146,145,119,91,55,85,14,111,25,24,34,169,226,205,133,29,122,199,225,56,36,121,240,225,181,85,172,207,171,128,127,88,57,100,64,130,113,244,19,170,69,12,1,161,108,45,169,155,254,214,233,247,88,239,145,196,0,149,34,109,154,171,160,151,247,189,203,54,88,36,253,149,4,56,238,1,50,199,30,170,158,242,106,72,124,216,152,255,144,167,246,121,188,25,67,62,61,89,194,
183,26,147,9,112,3,224,190,178,217,62,250,161,213,29,52,187,120,131,243,134,69,36,88,32,120,97,186,38,68,222,219,118,230,176,101,42,52,106,137,92,168,70,99,84,236,253,128,78,32,235,39,161,234,55,251,42,53,136,169,48,143,54,45,209,180,159,234,237,215,146,17,47,202,202,67,130,246,174,161,13,32,203,254,207,191,153,183,125,57,173,113,123,190,231,111,43,217,75,158,87,241,99,199,38,223,13,166,179,147,50,124,27,218,77,229,185,181,34,82,13,92,18,49,40,131,126,51,85,6,169,154,34,62,23,50,142,130,98,90,131,202,69,94,205,17,48,155,154,153,186,125,200,45,106,143,217,249,75,17,22,202,112,160,237,97,99,29,235,1,51,184,212,19,79,57,51,151,155,114,64,220,3,164,57,83,93,94,20,67,234,163,173,120,164,151,31,229,176,39,201,165,223,182,103,168,185,91,41,232,147,135,162,253,151,31,25,157,243,172,94,254,20,78,20,204,136,68,225,161,189,239,36,59,32,143,233,94,55,226,197,33,147,126,130,207,94,130,183,87,172,244,70,130,34,182,174,38,232,107,84,19,194,64,57,47,194,183,235,93,30,228,205,142,1,156,205,204,
241,230,17,94,174,169,65,141,41,35,94,26,91,164,161,60,178,155,130,67,181,51,241,151,174,71,178,225,52,211,252,239,249,50,212,28,196,90,140,10,161,250,233,7,151,202,53,74,79,186,214,44,11,8,21,33,24,183,101,143,229,192,141,31,17,140,155,127,193,98,32,30,43,231,134,58,252,170,78,165,242,103,93,185,117,55,12,233,89,202,60,109,251,155,68,89,169,153,170,105,17,142,236,244,210,21,130,211,3,228,117,105,139,150,238,141,157,16,227,149,45,89,120,124,30,5,6,176,43,68,223,137,43,159,36,70,240,138,82,116,15,9,68,3,130,58,34,45,26,229,199,94,199,225,220,125,201,150,190,55,79,12,213,53,129,231,219,140,130,9,241,64,20,234,75,238,115,138,112,238,102,140,59,255,120,207,26,6,66,99,94,90,244,23,115,104,88,244,222,185,85,3,204,180,32,52,9,121,111,185,57,122,84,34,239,27,48,243,43,29,180,79,102,239,0,78,234,63,70,181,22,55,49,235,92,10,14,99,149,53,172,137,72,163,115,218,105,117,200,142,195,94,142,120,59,64,252,83,49,219,33,244,14,194,184,143,85,46,188,20,162,251,14,146,142,156,224,144,204,111,192,
25,1,211,15,93,46,115,217,10,94,133,236,44,115,172,241,201,223,51,129,206,85,53,23,83,210,253,237,142,39,169,254,92,204,120,207,199,229,41,34,38,242,68,186,146,230,158,208,219,169,119,2,108,92,101,31,81,203,162,146,119,180,93,120,245,62,108,21,18,163,237,117,82,212,162,139,249,194,140,55,41,80,145,211,165,41,192,59,250,221,33,231,36,2,79,158,116,139,93,81,250,151,243,204,36,93,167,158,45,52,89,33,234,86,123,223,101,242,173,201,209,0,45,122,156,119,209,192,198,117,69,119,130,125,235,135,0,117,67,164,227,102,192,168,197,160,182,146,176,62,215,198,74,76,10,222,52,211,147,33,147,27,58,224,97,101,166,125,255,167,175,162,120,129,48,200,79,160,191,88,168,187,193,248,62,62,192,55,110,120,251,41,250,97,225,102,249,178,129,210,45,106,235,155,202,199,19,95,95,14,242,31,229,138,184,26,45,50,237,225,111,132,193,51,3,242,253,39,186,158,138,11,9,234,218,223,117,172,19,86,31,143,156,118,45,201,148,234,235,179,24,126,199,27,229,74,85,244,17,32,217,107,24,28,74,104,164,66,62,185,87,161,4,14,89,
44,94,188,56,235,210,131,102,7,134,37,215,85,58,203,28,89,220,171,233,206,102,212,26,111,29,58,237,23,168,50,161,145,190,167,33,225,214,128,123,31,205,176,185,57,87,58,79,6,93,114,239,189,219,112,163,227,162,5,54,107,12,86,240,79,128,5,56,21,60,86,137,223,53,136,82,41,138,98,144,38,78,126,23,165,147,156,229,61,173,14,146,212,49,227,136,192,173,165,79,3,135,101,138,251,9,118,177,187,220,79,116,238,200,145,205,175,214,157,121,53,216,115,94,118,49,176,192,55,85,197,120,24,20,92,75,27,116,80,19,5,208,94,148,122,175,225,194,98,24,152,121,131,187,55,87,186,95,232,169,249,74,120,166,105,199,213,24,108,248,197,229,237,212,47,170,239,28,46,94,191,59,105,13,254,70,184,219,240,199,77,27,242,75,67,92,176,214,32,48,135,231,231,202,106,152,67,124,81,177,170,120,160,195,229,226,50,155,177,242,6,73,7,96,25,248,86,220,119,255,157,154,251,155,31,202,180,251,54,149,84,147,222,123,64,68,184,102,184,42,63,10,222,243,209,79,161,118,74,77,31,34,66,203,24,232,29,151,202,180,124,181,160,93,31,228,235,
99,88,70,123,52,166,173,192,78,105,48,79,181,159,39,175,14,139,115,232,90,164,126,126,184,245,245,238,42,185,54,253,175,121,71,235,160,210,228,108,115,245,159,208,26,131,165,55,86,183,38,120,3,184,139,253,132,142,226,127,18,93,191,239,50,42,251,244,200,114,89,5,52,75,128,71,105,32,209,103,93,201,146,154,242,191,241,145,142,39,22,66,249,144,98,66,60,205,194,91,133,31,21,178,41,47,164,239,176,245,217,155,100,78,128,95,132,138,140,207,4,39,91,221,124,185,124,5,166,80,15,123,177,0,28,120,96,118,67,33,176,230,163,8,83,8,146,78,1,147,141,191,158,17,193,16,80,66,19,246,12,157,203,4,59,186,199,111,131,88,83,31,249,28,81,133,211,91,97,251,65,78,51,253,251,59,196,45,107,80,91,172,22,125,210,215,114,19,126,185,235,29,216,72,25,187,149,74,8,221,202,39,201,49,210,36,16,107,52,237,218,96,215,213,198,61,162,154,92,171,178,157,53,14,206,249,52,131,142,231,110,128,213,218,78,102,125,181,78,222,236,225,155,142,146,77,101,99,154,83,74,185,141,32,87,254,10,199,237,124,149,206,0,246,240,184,175,173,
232,166,219,209,112,89,29,197,255,158,49,157,38,134,142,101,224,204,170,184,27,243,167,63,90,18,124,133,7,69,231,222,191,12,91,49,51,227,120,197,174,144,34,14,116,7,27,197,28,140,101,242,173,134,239,81,175,3,205,141,92,188,181,95,80,50,75,185,23,17,126,45,146,196,120,241,27,166,150,48,165,53,170,164,30,33,106,249,62,26,168,17,187,54,78,175,211,76,217,23,151,252,130,247,84,169,51,212,1,219,230,243,208,82,150,101,55,34,217,146,188,60,246,79,255,227,0,145,103,242,185,29,71,0,246,115,196,49,179,17,132,227,80,132,46,230,60,96,21,243,225,27,86,138,148,147,233,218,129,236,113,248,11,133,218,60,205,154,148,84,167,165,255,195,28,90,254,181,130,222,175,152,4,150,56,248,57,37,221,60,201,54,59,170,19,250,205,251,175,72,241,215,112,93,103,236,175,15,198,80,226,174,253,63,17,0,164,251,113,92,185,193,190,72,26,44,132,75,114,162,200,72,173,159,222,45,18,70,167,127,67,2,117,94,38,39,246,16,210,173,247,208,196,122,123,224,71,73,96,165,172,176,246,210,50,122,67,190,195,253,158,222,28,249,123,16,
206,237,146,39,224,20,206,203,116,181,133,102,216,23,21,157,67,116,30,231,28,227,56,175,212,129,62,141,237,231,119,247,149,227,173,178,9,6,123,230,31,150,75,66,172,170,83,216,167,187,173,228,223,214,218,221,142,175,25,199,152,215,51,219,89,26,255,64,111,178,53,223,27,9,100,138,28,228,236,69,207,161,188,188,63,169,73,243,20,13,218,191,249,166,106,118,205,84,132,105,30,202,193,163,102,187,118,232,215,143,65,86,255,250,180,162,145,226,66,159,237,129,155,128,69,123,93,72,26,39,155,38,202,102,70,34,103,221,122,143,236,167,128,61,207,141,133,179,207,176,223,228,194,218,185,153,93,5,10,91,194,157,91,165,110,199,90,118,38,94,235,175,244,54,83,69,244,238,138,154,5,157,81,179,249,127,78,1,218,138,43,120,218,12,194,243,235,7,48,29,175,179,77,4,120,255,74,165,136,143,132,78,103,18,156,58,98,43,32,239,191,234,89,97,152,108,125,249,134,174,30,28,5,156,214,174,111,94,11,64,195,91,181,191,44,172,77,241,54,60,180,163,76,128,245,231,156,236,151,158,231,233,129,179,142,31,187,43,10,164,22,87,148,
121,5,160,204,13,231,30,234,255,251,27,64,219,223,97,211,6,139,11,59,207,170,18,117,105,206,124,232,156,213,121,147,71,181,190,41,224,142,34,86,43,96,227,153,61,90,117,58,54,123,141,243,155,193,212,81,145,65,75,14,236,161,234,69,234,237,122,174,88,134,192,102,224,13,118,219,211,26,241,104,177,67,159,128,251,206,117,13,137,157,117,27,197,253,214,132,51,75,84,196,221,223,185,101,176,242,234,250,211,59,151,230,141,111,106,50,158,106,206,98,120,32,44,63,192,178,232,146,107,106,220,92,217,127,48,85,159,229,217,49,144,172,221,146,56,115,205,234,171,71,1,104,182,5,100,198,1,117,83,88,32,25,120,137,51,76,37,127,150,22,18,186,58,237,183,236,66,84,117,220,14,39,105,162,143,84,253,46,211,207,31,153,42,78,148,108,197,148,175,80,218,114,138,16,3,54,179,40,189,137,141,18,98,82,203,51,59,189,57,108,227,171,94,151,35,147,104,94,90,237,27,88,187,28,63,209,232,8,240,172,177,93,33,61,63,203,202,34,43,108,103,172,191,93,25,104,201,233,166,201,173,81,208,143,125,238,140,97,172,54,126,186,213,64,221,
210,168,42,34,85,114,204,232,140,73,232,100,44,29,74,168,0,255,82,140,113,30,91,134,110,107,24,219,36,239,178,156,207,23,0,243,172,202,216,229,31,254,128,104,222,18,34,219,255,100,249,216,238,231,144,9,185,123,243,235,151,212,192,241,230,197,93,231,222,152,90,57,49,174,169,148,192,163,90,87,224,216,181,71,146,72,140,109,205,50,227,158,78,20,165,165,135,169,210,151,118,240,165,156,159,253,6,72,47,32,5,188,27,26,69,174,90,5,35,33,222,157,155,135,254,235,95,52,238,13,222,191,179,157,42,52,239,62,152,122,56,153,53,125,47,148,121,198,193,34,115,59,76,109,22,211,112,115,208,238,241,168,140,223,36,67,81,157,182,115,57,155,167,236,159,23,12,16,23,9,185,118,93,11,161,63,167,208,92,234,140,152,113,152,176,164,249,66,153,196,191,219,180,212,205,83,138,145,168,16,21,15,200,134,227,72,52,147,38,169,212,218,73,97,67,224,142,147,64,76,172,153,191,246,189,177,60,197,175,157,3,181,170,200,126,11,216,19,251,222,95,239,159,214,137,36,188,238,65,6,59,55,20,231,113,121,61,200,211,177,195,133,40,45,
207,201,96,189,132,21,204,212,235,218,128,99,109,4,84,177,2,85,124,236,141,81,46,27,253,139,10,17,241,61,174,176,157,239,6,156,218,45,83,61,2,28,42,177,116,160,195,119,31,244,165,111,160,206,94,124,147,155,37,58,188,30,95,76,20,215,74,234,205,0,204,98,51,2,196,4,100,60,110,113,46,10,72,254,166,85,228,230,82,229,69,25,114,209,187,246,220,206,86,77,15,91,31,125,117,72,152,232,122,15,210,159,6,78,48,213,205,181,108,189,20,201,64,61,203,127,248,29,55,47,113,39,253,186,18,43,176,194,245,197,233,156,192,140,60,211,220,194,218,41,99,160,235,147,43,189,126,88,252,0,51,155,250,102,156,107,109,155,137,145,24,135,147,3,68,75,144,11,196,139,189,180,61,53,224,116,57,232,12,192,151,32,11,83,135,106,30,5,50,26,24,126,108,150,199,151,211,228,190,203,117,246,13,92,82,95,62,1,34,11,6,114,183,139,43,203,169,208,164,6,255,51,217,164,231,219,61,82,178,183,204,214,116,34,83,63,73,92,29,165,85,4,219,243,179,237,27,126,128,133,41,111,39,249,251,6,94,224,78,226,39,62,18,129,15,69,11,43,123,29,142,66,
68,184,117,52,107,176,2,97,255,210,222,16,235,152,203,184,242,81,58,48,213,235,141,190,60,134,231,1,43,154,204,92,191,229,121,186,205,98,236,229,141,153,190,208,90,170,109,79,52,44,183,187,240,243,16,99,138,50,44,189,179,246,171,116,23,67,67,133,39,240,226,134,107,134,197,235,228,166,175,11,127,154,130,20,70,115,152,18,224,25,44,9,144,12,90,205,248,74,131,123,221,149,195,211,194,132,43,227,45,75,129,164,93,150,60,102,158,124,87,201,200,130,157,21,181,202,161,129,131,131,231,14,79,102,42,189,42,168,93,117,175,43,215,241,22,70,39,43,186,239,196,52,104,167,74,183,252,48,46,49,123,57,179,58,49,98,0,49,210,58,90,90,31,235,134,142,35,86,82,232,143,57,174,143,119,211,252,69,189,140,126,251,253,5,15,100,149,231,158,216,42,170,18,124,143,155,206,225,254,62,55,230,117,151,232,31,71,177,4,83,240,192,67,162,128,213,54,152,229,7,89,169,254,239,235,162,162,125,157,125,224,241,92,183,0,43,246,217,63,122,201,148,224,34,155,75,71,74,144,217,230,181,175,47,223,188,98,249,106,114,171,224,222,228,
74,177,224,105,90,201,223,188,108,33,159,104,143,199,253,49,163,87,6,150,141,243,184,51,3,56,211,103,105,205,88,137,130,111,78,139,93,10,31,178,251,171,93,119,99,176,245,12,104,182,231,228,23,214,241,229,51,19,117,47,136,80,243,197,67,172,153,226,111,250,148,112,224,136,7,135,30,90,13,30,240,35,139,183,114,216,0,21,83,159,230,42,122,58,196,64,99,124,20,189,31,96,26,219,233,79,54,76,129,109,202,110,157,223,13,8,220,161,214,136,83,37,129,3,105,74,136,229,236,195,192,221,178,199,135,224,27,199,197,119,102,174,211,44,45,148,126,175,197,53,176,12,135,186,14,60,173,104,203,195,115,179,63,68,251,60,43,3,55,188,51,177,143,73,51,120,192,76,153,214,238,230,176,134,44,165,120,254,10,252,201,189,89,167,142,214,239,184,123,90,230,58,39,98,154,9,241,142,82,211,245,127,203,70,52,218,126,184,87,119,188,247,150,140,164,249,234,104,251,25,39,102,245,242,75,189,235,231,194,209,189,83,178,162,192,206,227,19,52,220,126,77,135,251,9,41,254,162,186,174,174,252,179,186,220,210,196,75,50,48,20,190,243,
171,102,52,150,198,198,2,16,138,187,97,45,180,36,91,161,177,151,55,22,250,98,166,85,161,235,131,64,208,206,115,52,24,83,255,102,132,83,136,88,209,0,230,179,238,123,44,64,48,189,124,236,160,177,103,75,239,123,69,98,27,234,41,155,241,46,236,190,128,22,108,157,118,130,180,180,7,211,250,166,225,155,216,206,126,119,170,237,231,29,209,199,178,155,72,116,91,249,226,162,74,235,4,92,35,86,99,47,102,161,171,249,94,109,67,165,98,239,86,97,52,119,19,236,115,151,15,88,197,51,172,161,120,199,52,150,175,251,129,188,135,138,220,191,213,175,235,47,70,21,61,113,83,65,6,15,213,45,216,106,125,110,194,166,30,248,78,174,161,249,240,28,149,15,163,179,46,202,234,143,82,3,116,28,191,204,233,175,231,220,27,236,42,48,37,187,93,69,236,56,104,133,104,218,76,150,49,21,111,38,157,140,26,59,172,237,232,168,145,154,34,174,238,245,172,161,119,134,166,75,85,189,51,184,8,136,224,140,189,103,28,214,79,101,203,167,240,191,13,30,247,62,115,175,7,171,23,96,27,227,71,114,79,204,120,191,85,165,176,94,130,88,192,96,1,
203,106,252,143,62,242,107,188,186,181,67,92,154,248,2,59,137,118,160,15,242,53,81,131,171,167,240,40,162,29,103,102,23,250,12,88,99,48,48,251,222,251,182,8,167,55,105,222,222,159,102,75,219,102,108,12,28,29,22,89,163,203,86,216,158,36,197,138,178,2,184,242,110,239,244,26,123,44,185,214,250,41,225,57,214,5,201,102,191,212,94,217,110,17,151,210,219,97,54,79,58,163,32,13,166,144,196,17,175,128,59,183,166,153,18,32,24,154,110,154,126,216,102,222,124,204,39,204,59,215,150,10,173,173,72,188,252,206,166,167,215,16,118,243,215,125,41,240,77,214,12,161,114,158,191,82,47,18,39,223,29,6,141,37,66,142,127,63,130,58,99,167,111,99,96,197,20,159,105,241,116,20,221,106,228,76,206,155,199,92,170,99,244,203,100,232,27,132,109,78,63,172,21,99,229,50,62,213,252,22,169,35,14,105,121,217,104,1,139,86,121,49,250,243,64,255,233,80,20,105,52,222,123,112,65,146,127,188,221,159,106,123,62,176,145,52,218,214,158,67,115,132,9,122,219,253,104,114,196,235,93,139,135,75,84,177,51,137,142,38,94,25,254,158,123,
35,168,211,182,94,158,72,183,138,201,82,184,93,126,23,60,153,181,38,122,163,106,172,16,177,67,237,90,174,219,163,248,252,7,166,33,85,76,179,110,251,119,62,157,133,28,233,73,241,14,87,27,164,254,139,1,22,53,113,216,30,241,70,99,207,93,180,2,255,81,236,254,23,150,7,85,221,15,204,132,127,219,55,101,212,237,33,181,73,207,172,180,33,190,34,159,41,40,198,125,36,207,236,226,154,9,46,242,57,33,111,158,65,15,252,158,78,248,20,126,47,164,254,190,65,180,183,214,159,245,43,205,149,60,9,136,242,14,132,132,139,226,71,109,212,44,6,204,37,186,91,192,235,126,16,178,56,76,113,238,133,216,129,48,71,64,9,224,91,196,226,136,151,191,54,208,114,225,110,221,119,221,124,5,134,75,138,207,212,153,111,137,138,231,60,228,245,96,155,193,88,53,206,38,10,146,9,215,253,135,133,213,225,119,10,139,11,165,85,90,187,188,239,252,135,175,233,208,36,67,84,90,185,232,174,214,110,212,48,249,117,203,247,12,131,31,157,158,100,8,164,150,118,155,165,145,252,159,233,146,174,114,225,104,62,193,236,174,144,92,239,48,189,159,
207,252,253,128,166,153,132,110,247,92,90,112,173,139,11,185,130,212,212,91,81,206,86,250,76,162,21,144,128,180,247,132,246,40,165,18,190,141,68,168,196,134,51,53,198,193,222,27,85,120,26,217,39,87,75,99,160,33,20,152,168,190,168,119,54,111,190,216,51,43,58,66,198,229,243,15,125,254,116,150,151,35,15,200,247,223,45,90,248,6,168,72,216,224,254,46,195,125,31,53,135,101,164,93,213,201,135,84,240,145,28,72,107,232,134,198,17,2,143,63,157,100,74,98,141,240,154,225,222,164,245,181,118,187,30,223,106,185,89,146,27,43,159,215,229,108,211,216,249,232,215,180,230,48,92,104,236,250,199,44,30,195,15,212,31,210,98,49,201,208,149,122,233,251,125,35,54,102,154,225,79,200,111,237,29,243,42,103,215,7,219,48,69,62,72,181,173,208,42,203,34,241,90,103,5,86,167,239,253,111,56,233,60,210,234,83,205,53,199,46,161,115,63,60,141,37,93,71,236,164,138,186,21,1,45,153,244,180,40,213,207,126,49,64,191,233,118,60,181,163,32,27,70,151,250,169,7,116,71,100,0,232,90,161,89,82,81,154,242,183,83,59,6,154,113,188,
247,205,188,160,188,111,60,223,175,211,188,156,86,143,12,103,82,46,1,38,168,100,211,143,51,237,121,223,105,153,96,11,108,173,231,149,81,10,82,78,155,102,95,226,197,83,146,88,16,205,7,26,21,88,5,69,114,189,171,83,214,57,121,95,233,30,253,81,20,148,23,2,217,57,251,153,110,226,119,169,89,35,155,230,45,183,30,52,251,60,200,19,24,32,61,4,214,225,219,25,253,45,26,134,197,25,126,179,110,236,129,95,89,166,96,70,186,253,200,227,163,101,173,214,108,130,190,112,234,231,214,69,192,125,190,152,39,102,191,3,217,78,237,98,193,184,175,31,234,89,129,229,33,21,68,3,36,84,191,68,153,238,53,14,57,231,130,185,123,144,144,75,247,72,170,93,125,153,140,58,59,75,129,14,211,226,211,96,122,87,12,195,200,145,216,183,243,179,7,104,34,224,33,223,109,59,249,50,39,20,134,6,9,53,50,18,4,175,56,102,231,204,163,40,251,81,95,198,92,70,238,45,55,10,199,128,44,15,48,81,135,107,154,65,34,152,35,182,252,45,113,1,34,175,80,126,94,251,137,31,162,238,158,149,119,86,250,10,126,137,43,81,171,50,247,77,20,92,227,244,146,
107,151,50,62,77,169,120,114,9,36,29,14,77,136,14,79,86,209,170,124,130,13,163,202,235,10,122,119,127,105,221,211,125,132,100,9,180,111,16,190,69,231,43,88,234,78,176,6,9,114,243,71,126,199,16,210,185,158,42,229,110,237,233,119,8,145,149,224,110,103,231,247,174,34,149,25,211,30,99,109,180,171,217,201,244,29,51,165,230,216,10,11,85,196,83,119,79,194,225,221,63,57,119,65,2,36,191,29,91,116,17,189,74,97,182,5,222,178,72,255,236,57,116,24,137,71,1,58,125,117,168,36,200,164,11,129,175,231,41,249,16,159,219,33,207,27,168,209,174,45,18,81,143,212,16,233,223,81,111,16,169,2,53,131,126,242,170,6,97,212,136,13,14,188,83,228,124,73,210,197,242,216,40,80,200,12,175,84,239,4,188,46,177,112,17,22,182,107,98,185,224,253,234,44,127,57,121,33,49,38,44,53,64,232,64,138,40,237,117,29,100,99,240,86,22,235,62,67,187,242,195,79,114,157,18,209,51,86,46,145,23,19,43,188,33,25,83,142,26,40,246,193,61,167,109,232,82,5,116,183,50,16,48,82,252,91,111,213,174,179,5,26,47,186,16,148,74,228,133,196,4,103,81,
50,118,10,255,225,192,129,151,211,130,216,163,73,239,83,151,252,159,54,101,177,225,82,110,75,104,88,217,237,225,4,17,35,241,217,11,49,206,132,9,97,130,28,55,15,62,11,223,25,122,127,199,134,85,174,108,142,248,18,155,191,96,159,34,5,79,167,99,210,71,55,89,28,22,42,191,19,6,12,233,96,131,254,222,9,50,240,30,158,156,37,221,145,100,189,149,32,36,212,55,131,192,59,32,202,162,159,238,222,168,149,251,113,123,22,134,196,138,69,189,137,66,242,192,84,55,62,155,105,234,131,92,227,48,93,84,189,171,172,153,246,112,100,152,59,73,219,166,215,112,17,75,231,241,237,50,68,151,72,198,167,150,178,216,230,54,168,162,143,98,59,42,43,25,159,219,216,244,218,82,184,66,249,73,84,115,228,128,225,35,70,193,58,83,80,63,248,231,214,157,150,184,255,255,63,73,17,179,216,187,146,77,159,144,29,227,62,238,119,101,154,126,85,29,48,195,173,184,145,88,198,239,6,247,16,183,238,200,104,87,88,125,116,17,172,251,0,214,31,92,121,71,12,222,147,186,59,177,144,165,244,40,135,244,202,238,231,212,173,123,34,189,234,111,158,
156,117,239,33,102,93,8,57,174,151,235,77,230,85,242,183,133,103,177,237,250,50,67,28,65,45,100,20,64,25,137,173,44,201,167,245,242,79,68,73,166,52,20,191,191,178,254,46,70,45,234,164,235,160,122,93,183,161,43,228,196,191,70,70,98,22,229,98,52,98,43,211,139,205,63,139,80,75,23,122,219,28,48,107,231,18,187,111,163,14,120,139,35,207,203,95,115,157,28,176,38,73,145,189,129,19,140,195,177,109,93,12,155,5,72,105,251,21,171,139,57,65,50,46,156,113,126,189,93,255,65,234,73,153,203,53,71,41,173,76,103,194,28,172,112,218,162,202,25,184,245,33,251,192,38,119,102,244,126,34,104,243,97,67,122,117,29,222,39,178,145,123,226,158,174,235,51,76,58,99,133,189,181,189,249,171,19,6,244,17,102,39,85,21,225,211,121,119,102,94,2,23,205,232,42,118,185,106,252,11,220,247,159,226,246,108,18,235,230,154,193,217,145,34,255,71,237,15,177,80,116,74,181,212,173,233,153,207,66,56,38,68,54,29,62,151,177,70,190,183,204,58,253,233,152,71,186,171,11,161,73,162,18,247,174,207,196,250,117,26,251,251,160,85,104,91,
57,22,121,73,244,35,245,129,203,63,197,87,139,89,123,25,58,113,198,95,201,25,221,131,189,41,35,121,52,128,81,112,182,69,56,210,47,186,84,167,141,241,203,114,218,15,116,118,20,103,61,115,37,134,136,37,92,60,62,206,53,137,226,26,145,100,245,6,110,189,13,236,61,251,81,153,162,129,118,122,2,205,72,2,38,170,30,249,73,37,17,172,115,232,230,204,142,30,61,63,184,191,100,103,183,119,6,122,166,108,35,0,232,2,203,148,118,107,104,64,40,217,8,196,150,233,162,82,76,114,105,41,213,188,194,37,237,110,134,4,82,27,246,38,232,56,138,251,70,248,137,2,122,60,171,104,169,95,3,235,186,214,107,7,146,221,75,35,34,121,174,243,6,11,255,150,99,160,145,190,137,221,154,200,45,78,246,202,225,160,188,174,148,39,236,83,10,225,245,243,214,195,156,72,158,108,38,115,0,226,161,65,129,135,184,239,53,71,135,201,158,47,210,72,106,55,160,50,91,92,166,241,3,90,53,249,105,242,63,203,207,114,113,76,245,151,138,72,171,29,67,236,154,159,159,120,67,85,121,207,254,221,80,92,33,143,49,20,166,127,211,61,43,162,189,249,233,68,
159,214,120,84,145,206,130,113,77,212,164,106,172,27,97,24,176,19,228,33,169,161,217,57,250,193,66,94,87,219,18,120,4,167,148,57,164,240,181,216,101,67,171,206,23,224,253,131,212,103,49,119,92,2,246,86,6,181,111,51,78,153,185,159,192,7,192,15,88,68,63,187,125,251,143,178,226,111,102,32,54,166,173,102,88,65,253,56,134,254,249,165,219,79,47,65,167,74,35,158,241,184,107,44,247,12,226,203,192,23,221,247,199,119,4,218,11,234,56,35,173,205,5,235,88,65,58,106,226,186,48,231,180,221,153,149,244,132,82,110,214,79,241,127,5,100,245,203,172,198,162,4,225,184,148,235,52,99,254,225,70,125,70,153,132,155,202,134,154,61,254,151,20,59,192,244,108,170,183,67,71,161,32,222,224,44,66,83,205,35,207,49,237,91,202,88,158,229,252,146,152,135,182,16,138,149,154,253,229,155,215,195,43,186,212,123,226,171,173,88,1,34,200,89,225,239,210,25,132,43,21,248,83,184,135,184,244,181,126,171,185,18,148,217,36,181,40,87,239,3,223,231,147,60,215,159,163,38,238,49,202,23,164,116,128,83,249,50,157,235,88,127,56,93,
121,30,133,25,0,151,248,239,156,120,211,50,139,89,15,25,78,99,173,117,122,190,212,128,168,221,8,55,160,55,208,171,152,67,235,28,255,44,132,51,86,138,181,140,187,74,111,120,54,193,5,69,14,32,198,179,105,140,224,215,110,190,242,204,50,183,143,225,239,92,18,98,184,100,34,62,126,191,142,33,214,73,134,35,1,99,4,41,228,201,160,142,221,84,227,92,188,13,189,76,109,156,227,213,113,243,77,57,221,140,130,156,213,172,213,126,142,16,25,151,50,201,99,5,19,22,135,112,71,40,61,137,238,113,22,235,95,238,205,88,141,172,232,26,22,137,153,182,69,0,76,33,30,142,138,89,10,95,100,113,190,194,73,239,167,227,70,196,72,166,227,210,98,237,25,57,142,49,82,204,42,104,151,207,80,85,100,182,255,184,194,144,106,105,117,74,62,184,1,211,229,202,33,66,157,91,109,70,156,193,126,214,233,25,172,166,161,126,77,168,226,41,54,225,122,188,63,25,28,0,119,198,6,70,136,96,42,45,128,96,100,149,254,214,108,146,53,229,251,77,201,4,26,149,38,241,230,125,83,231,156,78,223,112,222,57,63,217,43,150,237,49,99,44,76,106,212,75,201,
20,4,60,253,87,162,208,30,134,10,43,83,118,229,138,130,245,60,148,23,228,5,113,57,95,22,216,110,49,184,236,120,124,19,253,132,222,174,102,232,143,111,179,161,15,215,47,26,161,76,30,119,129,187,146,104,151,169,43,54,202,152,71,215,213,103,69,128,206,186,85,254,69,147,166,156,70,194,236,23,185,41,63,214,122,205,100,226,15,25,246,35,38,6,247,179,178,253,169,174,10,182,224,248,114,96,20,79,152,112,12,106,135,95,101,137,216,127,215,223,251,232,247,163,152,210,190,161,104,241,176,5,133,14,9,71,169,126,77,156,208,167,46,89,46,108,104,137,92,154,242,21,185,59,133,158,242,53,86,210,123,94,178,67,144,177,127,173,210,14,51,79,39,238,61,231,52,49,106,1,56,165,244,149,16,192,92,11,139,27,14,247,93,197,198,239,203,183,104,72,31,62,22,24,248,40,123,226,237,244,174,246,119,132,152,248,216,252,114,11,192,142,18,65,144,207,173,31,143,101,40,227,190,142,226,162,15,41,161,247,91,127,240,202,43,254,249,129,245,134,158,139,190,237,193,56,30,44,2,227,8,194,40,100,151,45,205,252,253,146,242,237,23,199,
99,180,86,71,243,152,224,107,73,41,160,42,13,47,15,10,168,206,88,202,28,91,210,161,18,239,251,104,63,72,115,112,254,201,162,155,80,243,176,38,125,126,141,244,179,245,244,30,148,128,75,197,136,162,32,221,15,243,64,191,67,17,250,15,238,16,200,0,42,31,220,196,82,154,158,116,220,169,54,228,99,39,194,119,244,17,118,42,167,249,55,254,184,21,151,198,173,174,209,31,234,31,14,59,89,167,48,231,140,125,156,164,50,127,25,67,150,181,158,166,51,136,166,70,151,116,40,21,207,200,201,31,37,130,207,221,32,231,93,38,79,81,163,198,247,55,85,247,25,131,37,213,219,244,19,26,60,32,204,153,226,244,249,167,165,64,33,66,242,82,103,6,3,31,133,148,106,73,240,235,193,166,250,208,206,53,211,191,142,208,3,249,121,138,69,234,183,4,111,92,115,211,67,6,236,40,126,162,102,87,61,28,132,244,209,60,53,4,235,30,254,170,24,26,43,140,151,250,68,151,0,208,252,126,180,183,74,111,26,242,17,90,112,222,93,81,175,214,234,199,85,248,56,0,117,12,11,89,5,174,2,140,34,172,82,186,188,146,20,197,71,34,111,88,48,142,110,127,222,
127,42,71,95,243,0,15,11,43,193,215,250,133,51,51,11,40,49,70,239,235,6,24,208,43,86,196,194,222,219,36,236,45,222,120,40,242,254,95,55,119,233,249,112,212,48,141,183,40,234,79,142,1,202,201,15,48,64,78,144,93,88,190,211,48,43,218,65,117,143,207,130,74,176,173,189,253,36,250,251,38,221,133,136,142,25,147,206,113,179,76,119,96,211,8,23,17,173,30,220,59,21,177,71,221,183,251,244,57,223,205,190,206,10,142,112,122,7,145,183,3,192,1,178,59,211,46,158,23,212,48,158,155,152,82,142,137,37,159,156,156,156,6,29,3,13,168,248,57,5,148,142,177,175,45,190,26,26,55,177,57,20,0,241,150,27,150,119,228,5,36,205,195,98,251,32,29,217,244,21,156,36,3,42,142,126,58,87,1,66,168,59,248,253,205,242,73,134,89,101,61,44,63,128,141,11,139,102,240,164,206,0,112,157,119,3,151,158,22,235,202,70,33,50,224,83,78,196,95,111,152,38,194,180,238,189,53,134,48,7,239,236,125,78,126,147,210,70,78,246,237,146,251,22,241,220,205,200,91,71,161,127,145,84,89,3,117,198,79,203,104,51,115,64,217,48,34,71,187,223,215,214,208,
188,42,221,116,166,208,10,254,20,88,210,189,252,137,145,128,148,44,249,43,206,251,84,191,128,9,27,138,213,52,199,165,92,180,157,195,134,193,204,82,223,206,111,179,75,106,43,214,185,196,247,190,219,217,189,246,39,182,90,48,165,119,122,0,243,23,224,139,191,217,181,189,189,184,248,88,253,87,36,155,94,119,90,68,248,170,239,69,229,223,27,237,229,243,206,226,223,145,1,225,34,215,27,180,190,119,168,178,208,63,208,38,48,141,126,163,48,143,178,83,81,48,224,106,196,229,128,105,21,33,66,123,222,23,201,129,80,61,42,168,179,163,178,66,120,34,209,14,101,131,55,235,250,247,111,236,149,22,255,223,148,248,208,9,77,125,93,121,77,249,125,34,157,129,96,177,12,212,57,50,17,166,9,196,26,61,245,191,23,54,174,196,97,106,1,199,208,64,175,68,166,18,71,117,131,153,154,243,138,159,247,84,176,140,132,59,143,79,74,189,155,142,192,176,79,95,7,143,211,39,208,69,66,249,248,249,95,189,124,185,26,28,18,194,170,70,32,230,208,209,25,125,232,177,52,130,200,200,145,171,35,124,89,120,177,35,17,21,144,52,170,146,29,
209,19,74,58,138,32,177,116,106,166,193,111,6,17,234,12,124,189,142,190,79,67,43,51,100,6,76,2,89,219,230,14,159,25,174,108,253,108,155,164,107,73,209,62,243,214,78,101,51,57,176,126,242,110,11,110,64,37,16,89,151,10,83,191,166,111,160,182,65,154,34,76,218,165,144,129,195,104,155,35,124,210,158,110,2,145,73,149,173,56,7,164,204,28,89,75,160,103,191,6,166,176,163,253,167,255,220,179,190,174,171,104,166,208,214,155,204,158,96,227,24,49,51,211,26,240,46,174,246,75,194,228,74,65,195,18,159,39,228,106,168,200,119,233,0,162,113,182,252,244,172,60,199,215,76,10,228,53,85,18,211,245,181,27,170,13,42,100,37,233,137,191,65,33,105,151,47,89,73,115,81,70,239,218,20,21,147,179,128,76,63,138,171,201,140,66,118,251,250,245,171,254,181,237,148,71,56,184,142,255,205,88,217,56,141,80,37,246,246,128,235,6,95,54,168,164,242,167,237,168,190,68,189,129,71,162,36,117,228,117,248,206,143,37,17,93,175,152,118,121,109,34,241,209,200,55,31,48,87,192,158,34,210,241,149,192,215,178,196,189,28,7,4,116,11,
233,76,133,212,158,2,152,225,119,194,99,242,120,253,171,35,177,97,68,205,251,147,218,173,176,1,67,250,169,82,62,78,254,152,103,162,57,244,108,100,126,51,196,193,37,157,17,208,23,9,118,71,108,99,156,66,58,81,243,5,77,154,118,96,125,0,33,243,198,126,12,166,191,44,183,81,240,101,106,199,13,177,247,194,242,96,11,108,90,206,147,40,248,130,211,65,185,13,253,20,76,61,240,42,230,133,110,167,242,206,229,71,30,206,155,107,8,16,3,56,144,206,180,109,104,182,22,54,30,249,48,90,143,251,95,200,146,249,44,78,84,160,251,67,22,155,27,92,254,97,100,102,242,254,179,240,123,119,211,168,75,59,148,12,101,243,234,37,159,10,68,74,204,50,214,123,87,63,10,254,129,240,222,70,125,228,94,47,230,99,93,139,80,247,156,114,187,159,196,61,51,160,201,44,178,34,11,23,12,247,35,95,39,182,228,33,125,184,189,65,29,164,82,230,30,67,241,54,44,162,47,152,56,21,39,224,3,139,193,96,146,225,39,197,92,80,46,236,227,23,91,156,217,118,11,102,119,28,187,150,65,57,9,156,28,175,129,8,77,123,20,71,9,163,213,119,17,14,222,35,178,
224,35,38,102,254,98,50,193,137,249,170,37,232,53,168,204,45,36,187,11,44,24,78,1,29,43,188,237,11,0,175,54,142,127,25,0,156,24,184,241,133,123,147,52,68,14,148,12,177,70,170,178,80,183,182,66,59,155,246,101,171,156,73,80,230,123,105,33,208,14,245,231,94,40,111,204,111,210,157,222,149,87,5,153,5,83,182,15,120,188,175,60,11,161,58,196,131,248,221,195,159,69,133,136,176,105,39,130,155,185,229,79,226,129,122,84,153,24,209,96,18,136,15,148,38,200,128,19,212,158,145,187,19,215,37,216,143,138,248,22,2,124,65,243,80,15,85,124,203,18,40,93,163,219,119,129,2,78,0,109,22,190,176,255,0,200,5,22,2,35,187,231,123,116,50,102,118,255,205,135,74,195,187,245,119,180,135,101,245,118,94,71,135,89,19,33,25,145,125,212,130,36,11,185,0,64,36,129,141,154,226,179,5,172,59,18,232,179,136,92,24,65,214,162,237,216,190,21,153,192,185,72,79,170,203,5,245,106,86,93,52,234,63,182,27,109,37,246,70,126,144,214,184,42,179,123,6,108,209,243,116,170,43,129,166,97,59,92,155,212,17,44,143,29,99,18,126,179,130,36,
19,224,245,119,217,169,111,151,131,250,64,49,140,38,93,203,165,156,74,51,185,15,194,71,110,163,92,111,213,167,92,191,197,152,123,10,157,207,109,55,56,138,191,20,81,58,5,221,198,108,160,182,247,185,68,70,75,19,27,43,13,49,206,28,3,143,83,92,57,234,204,24,226,13,92,252,56,111,199,57,62,54,236,137,34,112,248,98,132,204,50,41,212,208,209,172,84,90,182,30,29,5,75,6,238,81,221,71,211,91,190,216,40,215,232,112,122,215,155,140,83,166,253,72,130,136,194,44,109,212,45,77,121,117,248,252,190,209,228,207,5,97,219,2,232,131,28,107,227,117,11,222,171,87,94,52,190,161,250,135,97,5,201,71,72,243,140,37,80,153,82,73,108,8,60,111,8,148,182,0,216,58,213,88,212,137,117,147,28,20,197,168,172,158,171,9,194,157,172,43,192,105,195,119,92,89,96,98,235,0,126,85,222,50,49,115,47,154,99,243,101,89,205,23,39,106,225,173,241,197,124,49,213,162,97,68,118,221,65,41,199,88,17,39,181,71,54,150,53,14,0,123,107,88,38,70,225,230,163,184,246,222,203,12,234,248,143,207,162,181,73,81,10,149,96,143,171,187,40,2,111,
7,106,81,124,131,234,165,158,81,171,75,146,158,36,132,55,116,176,32,72,125,124,182,71,129,73,196,2,212,200,29,103,167,40,177,58,188,205,168,4,112,1,60,26,78,183,228,230,80,82,44,88,166,225,253,217,243,17,157,24,30,239,92,205,29,48,207,50,220,4,124,97,21,28,210,214,218,244,46,211,191,206,195,249,178,210,215,174,214,198,60,122,20,232,14,98,202,157,74,136,228,93,6,91,24,146,164,214,73,140,160,203,253,102,176,18,1,123,220,117,21,132,23,78,49,99,20,14,122,29,204,104,161,44,127,153,250,18,248,84,9,216,81,27,128,50,58,253,164,84,36,9,201,191,173,170,95,99,115,68,69,43,177,74,37,144,61,65,101,16,158,69,44,166,98,166,98,36,41,249,102,98,88,62,119,251,137,67,130,222,168,210,60,209,180,21,32,79,66,101,44,93,219,132,15,251,170,183,160,7,133,166,132,34,231,157,165,167,177,48,231,220,75,18,144,236,219,41,57,50,114,45,33,28,23,30,218,164,212,107,110,19,76,197,82,74,250,213,12,219,88,80,27,123,34,107,6,8,3,92,150,235,113,60,93,20,71,168,178,129,40,250,182,33,227,71,241,208,38,20,188,33,155,129,
38,86,185,237,19,109,212,221,134,127,55,238,160,143,132,6,187,164,52,32,10,213,190,34,56,179,35,132,173,195,128,45,35,168,144,105,11,16,102,6,143,176,102,172,16,158,221,25,123,58,148,88,155,65,139,21,88,177,26,183,240,254,238,69,129,26,182,116,73,34,19,143,99,106,184,223,13,133,233,64,20,220,111,193,234,108,4,244,252,151,66,31,117,234,145,66,5,70,213,43,26,227,136,73,32,78,88,175,64,77,84,211,183,76,4,254,146,182,174,12,241,3,49,50,103,230,42,220,247,248,150,174,118,68,90,20,227,181,105,50,241,19,73,115,202,163,111,69,45,156,31,225,232,235,76,16,170,83,209,58,240,22,31,189,6,45,73,74,73,192,175,209,230,215,63,163,237,167,49,201,63,190,208,6,217,157,13,63,139,33,58,115,210,213,54,176,88,169,76,147,50,9,119,127,15,88,164,232,65,74,202,125,119,86,207,228,225,59,79,202,198,114,16,11,169,102,254,248,61,140,96,4,239,11,12,125,220,242,35,109,144,58,42,165,120,204,141,117,193,12,83,133,231,164,227,181,0,142,119,117,54,188,179,46,101,123,233,44,243,157,201,143,66,44,36,59,45,22,192,194,
64,80,85,236,72,227,165,136,71,204,184,179,143,75,127,205,255,32,119,181,240,34,0,49,129,20,225,215,190,200,200,2,95,92,224,68,185,206,203,116,225,115,44,144,94,13,133,204,159,2,30,127,227,236,125,203,97,74,59,242,231,87,250,177,169,108,246,157,231,66,168,54,7,135,254,5,99,195,238,34,92,248,153,155,183,120,192,95,129,8,68,64,90,106,18,65,51,68,157,105,53,190,246,164,12,54,100,6,26,124,111,165,34,60,10,54,12,17,190,159,163,252,215,112,25,126,67,158,53,173,60,133,23,194,237,71,50,138,250,179,82,154,241,238,79,237,88,168,74,231,116,52,166,145,227,203,75,235,161,14,123,180,184,78,242,2,187,170,63,250,99,215,41,50,75,118,17,149,167,46,198,38,203,146,92,74,245,242,232,194,69,110,189,213,24,244,133,40,167,117,119,102,159,18,157,252,243,186,114,30,99,18,245,37,177,223,40,42,62,170,216,132,238,242,194,219,163,14,105,162,30,150,105,121,85,168,178,253,87,60,99,3,178,30,145,216,38,217,212,231,53,204,103,189,240,32,116,161,221,107,217,43,52,197,161,86,43,21,39,239,243,230,171,84,202,52,228,
143,247,135,155,247,239,104,219,93,52,78,137,242,150,7,121,22,215,222,52,116,208,139,68,230,187,74,152,169,168,2,254,138,240,207,164,89,93,4,25,189,57,251,37,0,242,204,71,94,240,158,44,251,107,25,39,54,145,86,52,62,4,47,231,119,95,76,248,212,217,33,176,35,182,8,119,134,139,181,206,234,37,235,19,19,55,160,57,76,243,94,142,14,155,143,175,179,108,151,214,129,90,20,7,174,106,220,174,183,45,32,220,234,194,75,208,44,241,9,211,137,164,119,13,115,102,26,227,205,64,224,156,163,81,3,50,0,118,253,107,172,10,153,225,187,164,136,203,189,68,73,240,123,95,109,105,218,129,214,153,152,103,173,163,183,101,60,214,132,232,85,85,83,25,57,227,219,12,126,204,250,230,133,97,195,226,70,118,165,43,45,222,119,234,248,190,243,123,31,141,240,238,201,56,46,171,68,154,191,188,111,253,154,28,191,121,59,134,43,175,137,26,20,134,13,103,112,250,230,222,92,178,74,167,189,99,80,52,192,156,203,147,68,96,89,136,249,134,38,115,247,177,209,245,27,228,173,124,23,76,237,114,227,209,161,211,79,234,180,148,117,186,54,226,
109,221,19,60,25,183,246,238,122,193,168,79,221,181,97,180,186,78,203,212,214,48,120,156,65,122,59,99,82,91,154,100,93,226,28,218,152,254,157,252,23,4,113,20,215,208,242,132,237,171,31,78,72,94,154,159,172,155,117,183,189,103,85,54,137,123,83,249,112,236,91,62,85,112,98,33,239,8,59,172,137,215,250,183,204,177,249,76,128,216,156,25,38,4,184,85,219,253,46,6,201,171,35,229,25,200,199,46,95,112,43,201,102,62,98,225,138,211,125,183,255,16,8,243,213,235,7,217,17,29,235,58,202,216,209,21,54,198,103,137,42,34,141,218,162,192,197,35,245,215,103,118,66,200,96,112,77,183,95,248,63,86,97,69,167,215,145,98,58,224,151,16,25,23,205,229,39,116,72,126,195,74,247,243,190,57,114,186,26,76,227,134,231,204,182,37,6,252,254,5,128,49,202,146,1,132,214,129,163,144,101,166,25,104,219,134,166,129,171,127,68,197,46,11,120,53,103,220,124,225,251,128,13,86,86,34,148,50,135,58,101,12,200,27,122,24,138,80,164,71,103,18,14,151,174,182,218,14,6,70,248,204,213,40,210,113,213,151,208,211,252,236,52,7,69,48,6,152,
10,120,225,8,210,154,214,45,119,126,168,244,7,80,177,55,49,222,150,175,198,182,80,142,249,70,245,99,14,110,238,200,228,86,114,69,61,4,180,76,80,55,148,187,114,224,194,29,5,78,29,75,119,138,120,124,228,249,191,125,30,60,152,186,162,255,225,113,26,2,217,168,57,143,30,57,253,129,105,67,61,130,223,21,121,212,126,93,124,227,175,83,14,141,151,102,240,62,136,45,126,142,14,160,41,46,40,207,85,112,117,117,234,248,245,49,52,168,226,190,150,125,58,242,101,6,225,39,191,213,140,244,31,186,118,243,198,201,174,95,154,82,125,52,253,247,41,254,236,114,160,206,23,107,151,17,197,134,127,216,209,155,174,73,24,134,184,119,238,180,206,102,195,114,163,209,140,133,148,36,4,155,189,63,78,24,98,49,55,175,10,226,104,198,169,195,32,179,47,155,215,128,11,36,28,160,159,92,45,12,172,0,255,251,75,107,156,195,78,205,207,226,159,229,88,112,250,117,224,174,245,124,190,86,118,75,196,241,182,121,81,216,207,180,74,241,209,66,121,23,91,154,30,49,49,117,204,77,165,91,76,25,212,123,252,171,0,235,254,124,37,224,92,149,
189,138,179,76,160,243,11,198,80,7,0,172,243,173,9,200,201,44,28,38,221,73,237,255,146,181,117,61,194,216,162,252,53,221,163,71,21,60,134,156,107,42,115,249,108,1,84,247,180,15,220,44,53,205,254,161,218,200,119,191,1,196,193,57,12,100,165,241,127,86,51,191,2,182,105,31,176,43,62,0,133,153,245,115,41,17,175,250,249,104,106,61,52,47,127,73,149,184,151,194,103,190,206,214,243,144,24,128,82,164,247,233,212,187,2,255,135,97,0,103,51,28,85,90,236,236,34,111,71,220,7,55,88,190,85,253,111,195,62,155,187,181,111,197,128,224,228,199,115,178,110,115,124,191,227,190,132,44,122,114,202,167,186,251,36,99,125,144,218,14,66,36,64,30,242,189,163,231,199,104,245,127,132,148,145,218,200,180,3,112,31,67,176,152,206,232,71,183,100,76,66,92,75,188,218,180,230,116,109,171,164,126,104,208,15,50,237,168,222,42,208,17,116,229,201,208,238,80,27,230,236,25,83,232,0,86,179,221,194,71,181,158,40,35,0,47,114,58,116,114,144,119,255,23,82,117,179,73,229,19,69,38,17,180,172,17,28,6,230,15,135,19,5,197,17,103,
33,79,159,18,18,119,24,122,177,175,92,49,10,27,245,79,173,166,88,161,61,101,238,14,215,205,115,16,75,57,121,247,107,128,195,138,116,188,36,27,121,77,42,129,119,148,252,166,28,181,181,114,221,52,201,102,12,191,188,159,246,227,116,246,184,88,249,244,210,186,98,22,63,222,97,36,96,248,216,167,167,229,229,242,204,203,223,52,155,66,178,173,143,10,54,241,59,93,233,226,80,57,185,218,144,254,94,197,169,136,143,175,200,0,63,46,86,103,12,211,114,194,73,134,229,27,78,188,134,116,92,37,37,147,224,83,234,9,155,122,54,249,122,212,15,135,180,16,223,32,166,160,229,239,233,242,17,188,55,186,41,60,79,118,78,142,176,11,209,91,241,18,70,172,3,216,115,222,17,238,151,145,152,132,248,54,213,31,63,141,31,171,218,216,78,118,181,254,150,231,240,142,98,122,18,129,216,10,78,121,138,161,41,228,200,118,170,51,166,184,246,89,146,224,170,32,22,60,39,103,200,196,89,64,201,197,186,129,49,49,202,29,82,192,23,211,129,138,68,113,3,196,181,99,81,101,152,132,200,98,206,41,129,5,97,66,38,221,128,65,94,102,95,95,150,
205,221,79,120,27,122,79,217,152,11,18,244,219,129,105,178,237,127,164,222,48,21,89,179,94,170,221,254,57,10,66,129,51,242,158,253,108,41,152,242,131,196,225,237,209,48,91,233,67,6,10,128,38,16,43,36,174,235,40,207,174,233,59,127,56,41,212,132,180,46,201,94,66,226,23,118,0,27,111,89,115,248,99,17,231,126,122,1,113,33,40,61,153,138,133,147,205,221,95,60,173,171,165,39,178,122,17,12,160,225,109,11,65,61,186,171,148,119,198,198,217,149,44,229,78,115,183,19,43,218,197,254,152,227,54,64,153,224,213,79,103,251,38,4,228,169,62,254,198,96,5,223,208,225,170,119,53,5,168,65,188,78,68,126,42,119,48,243,167,30,192,238,235,116,131,189,105,40,193,20,156,163,202,147,115,229,75,118,133,145,114,254,86,73,109,236,29,88,131,227,130,150,201,123,56,49,4,39,3,62,14,150,192,36,191,24,163,171,138,97,58,101,18,5,184,50,75,246,98,63,228,226,1,42,86,173,117,88,65,121,26,128,50,111,56,83,15,118,220,194,108,20,160,250,253,51,140,45,236,139,58,23,142,43,92,194,57,243,55,15,15,30,204,43,206,47,46,192,41,22,
14,73,160,229,246,196,135,249,236,180,143,28,208,80,127,193,221,239,143,67,224,27,225,208,137,36,250,50,106,127,103,190,89,151,8,147,116,109,220,181,122,71,29,13,227,169,163,18,26,20,92,201,204,142,83,128,236,227,215,216,102,135,105,140,174,116,34,203,47,72,89,41,32,178,161,248,148,95,53,28,44,211,15,100,107,25,179,215,110,10,124,38,64,255,82,188,166,160,231,241,124,75,111,135,11,1,197,46,183,95,53,139,2,174,194,161,180,90,129,126,197,249,38,97,249,242,95,244,108,231,250,77,4,125,19,192,127,255,152,8,54,206,187,59,213,199,211,254,174,98,192,11,69,214,53,124,110,80,163,196,7,120,40,200,129,0,207,25,179,150,48,69,27,86,13,157,202,168,251,124,187,193,158,114,3,254,127,79,196,93,231,5,210,252,54,139,6,225,174,80,100,117,24,204,64,120,0,198,145,162,164,67,165,82,255,8,47,196,128,208,201,84,115,216,63,130,24,170,24,140,78,56,14,99,78,185,69,162,236,47,102,204,255,201,184,145,102,96,202,165,12,110,56,168,253,48,249,130,98,156,58,35,80,6,12,61,231,143,206,253,31,83,129,168,207,25,204,
24,40,101,204,64,238,130,55,225,148,31,226,3,225,142,110,25,16,193,186,71,160,52,79,12,122,246,157,48,156,74,16,131,38,50,80,158,198,66,83,24,197,105,41,102,166,92,128,148,139,5,212,215,180,32,130,112,1,199,203,8,17,3,234,92,168,40,226,81,12,136,135,186,0,216,185,66,81,210,253,47,24,11,43,53,64,253,234,238,251,248,204,214,87,35,20,177,50,21,116,75,40,124,241,180,39,158,34,3,220,23,172,187,76,137,199,89,203,177,226,184,16,179,10,128,171,224,243,247,201,173,12,92,243,166,160,207,49,164,247,245,95,127,156,115,83,59,230,197,144,208,136,13,165,21,38,173,38,19,242,172,167,96,157,44,8,150,188,199,162,105,207,33,141,99,68,204,242,0,78,175,158,46,133,38,119,44,205,241,132,224,228,17,86,140,128,211,232,135,203,248,167,54,201,127,29,79,131,238,0,25,145,58,32,116,20,230,52,248,115,151,183,210,78,231,103,93,45,202,193,229,244,179,172,145,56,105,132,21,16,80,45,116,204,2,86,51,8,149,98,204,80,217,133,243,121,75,185,50,238,212,49,234,97,47,67,155,18,151,115,233,52,135,118,93,14,73,219,99,125,
244,167,180,142,151,85,27,74,244,176,63,160,77,190,218,133,0,228,250,32,240,238,33,175,14,98,20,26,74,235,248,3,42,211,112,62,89,29,95,165,34,117,69,0,240,214,206,236,166,182,124,215,244,244,116,235,162,238,47,73,227,112,68,134,122,2,60,112,40,191,14,143,12,123,24,123,1,206,27,19,125,21,143,145,80,13,145,177,67,233,218,60,67,151,81,17,236,255,7,235,27,245,123,204,24,109,118,77,28,74,29,208,112,235,215,27,182,149,67,83,125,34,237,191,242,165,245,63,72,125,162,132,106,41,123,134,5,246,58,69,12,88,244,47,229,70,6,51,81,72,85,160,73,10,138,140,10,222,114,85,121,203,122,145,108,15,121,239,19,11,85,18,22,171,164,49,146,10,247,163,74,36,127,76,206,203,155,63,248,190,102,96,165,195,73,45,169,163,15,149,57,233,98,22,176,177,122,129,188,178,121,33,91,197,86,245,235,8,218,86,86,252,192,87,219,132,166,15,20,20,116,232,127,86,197,180,208,222,201,146,5,167,144,226,169,7,163,70,213,208,14,151,158,32,85,14,250,192,95,143,151,18,191,145,214,94,198,97,216,217,236,36,56,176,172,244,28,36,75,236,
127,232,219,182,76,12,198,157,252,237,91,253,35,13,141,112,190,12,132,167,142,217,43,193,99,242,148,236,155,191,199,237,198,149,23,178,50,185,75,119,149,1,153,85,206,178,225,75,117,218,52,58,32,29,224,141,27,99,111,63,126,74,15,19,204,48,67,68,216,48,156,30,97,167,179,77,23,218,42,140,243,46,174,219,169,188,127,50,10,205,232,94,182,131,123,226,143,232,210,110,167,100,99,130,201,250,73,51,39,36,153,99,80,6,149,1,60,175,75,25,36,0,202,123,176,48,205,180,198,48,216,253,243,246,193,143,95,251,221,200,143,155,76,207,48,18,210,217,55,3,88,180,167,34,192,20,216,146,138,233,221,192,174,3,127,219,254,65,69,134,25,75,196,17,235,225,159,46,223,196,47,193,3,15,95,209,245,14,153,47,204,171,170,227,206,29,64,116,2,136,212,75,10,242,44,212,118,196,247,128,105,186,72,186,72,218,12,200,147,31,187,151,249,3,191,255,91,228,212,182,0,185,67,61,21,98,110,212,15,64,122,233,213,150,154,91,109,101,79,81,247,170,30,75,254,121,103,165,145,246,219,225,182,122,103,199,109,80,67,100,204,97,221,26,192,10,
186,140,142,172,36,149,147,255,217,131,223,215,147,174,62,154,149,73,137,144,143,40,131,106,67,235,56,223,63,189,113,162,61,244,183,219,198,241,69,139,253,155,91,183,94,57,57,92,61,66,253,186,97,123,229,253,227,82,138,178,30,43,73,237,28,158,173,219,140,104,176,129,91,164,100,147,191,127,191,49,47,176,133,42,166,88,73,2,250,54,204,236,93,230,102,23,85,26,226,232,218,43,39,127,67,166,201,46,42,195,218,138,126,56,82,4,136,224,30,150,112,136,237,164,178,195,122,106,43,192,211,110,146,175,239,252,30,117,4,81,27,244,71,162,216,9,237,172,20,157,169,67,221,6,97,185,163,152,240,85,68,114,92,89,33,37,211,89,179,154,229,213,223,115,83,246,182,96,144,142,42,51,87,216,121,126,27,249,89,54,116,135,29,35,3,191,139,55,215,118,2,236,144,46,154,121,218,152,174,137,211,126,59,126,179,2,124,40,70,183,154,161,94,105,225,184,43,63,90,77,61,81,93,179,237,232,231,145,120,186,80,49,124,114,61,9,99,152,152,142,151,4,47,95,102,237,32,175,223,8,166,39,171,72,151,99,153,16,32,21,139,72,162,108,36,25,184,
47,70,199,79,118,171,184,105,99,4,121,76,31,113,88,89,1,246,120,195,181,129,193,30,38,27,118,61,38,188,255,187,167,163,64,167,240,255,120,59,175,160,166,194,6,76,147,66,18,122,232,29,66,149,94,2,162,128,66,2,161,131,34,210,59,24,138,10,74,23,17,145,16,170,20,41,82,165,132,42,8,10,130,8,82,19,154,116,34,34,69,5,67,83,154,74,81,81,164,236,241,223,221,217,187,189,217,249,55,119,103,38,57,231,107,51,231,43,207,251,68,69,2,203,69,124,253,218,146,41,234,68,227,41,201,69,10,33,189,157,92,33,86,205,182,232,226,124,127,24,190,191,223,210,18,112,74,250,39,16,236,175,216,14,127,45,173,145,30,110,165,249,144,181,81,34,112,112,191,105,107,85,140,134,150,240,225,21,252,201,71,54,14,55,118,38,113,34,54,212,235,170,105,221,211,189,235,180,147,99,101,4,40,152,121,28,126,43,207,181,245,56,103,165,241,37,79,78,194,66,225,245,173,243,76,188,101,176,220,44,150,207,31,93,130,171,31,37,155,27,192,56,110,33,254,237,44,75,235,89,49,49,202,249,174,18,150,170,46,3,180,68,27,87,54,91,49,50,58,224,212,6,
165,185,26,110,33,97,251,68,5,142,179,189,12,255,238,216,72,185,214,22,66,139,111,237,139,102,246,243,190,244,153,67,37,155,116,159,50,50,242,65,240,7,184,154,126,206,206,146,249,64,63,55,9,25,246,27,179,148,65,18,73,103,133,125,123,63,107,238,244,152,215,69,147,84,169,162,190,53,162,120,66,199,223,234,73,115,78,135,237,151,238,124,58,244,75,96,91,88,144,20,103,216,192,150,17,235,89,120,91,172,125,94,217,143,63,251,188,240,234,194,222,13,153,65,124,218,61,92,171,207,204,245,183,54,50,177,101,165,252,100,83,21,137,210,207,49,159,3,116,143,187,57,193,85,66,82,80,177,124,38,79,69,140,118,192,23,108,24,16,165,140,224,130,125,119,9,134,59,196,108,170,103,47,139,102,176,68,244,221,89,52,136,51,159,194,163,148,32,129,162,247,95,99,82,160,77,236,126,230,162,162,127,253,47,190,216,161,148,107,179,133,69,126,172,32,30,227,229,218,236,178,33,21,53,191,253,22,141,242,239,254,189,195,111,230,120,22,44,166,248,20,143,18,129,216,48,127,12,157,213,152,212,94,80,211,195,152,79,38,224,100,60,195,
176,117,113,147,185,131,249,113,98,56,217,3,187,135,144,84,243,120,23,91,248,93,150,29,199,156,87,56,168,158,253,251,33,154,203,32,93,87,175,217,143,24,119,38,69,232,49,78,141,55,115,15,117,81,49,157,53,62,157,180,230,241,24,34,69,228,216,20,91,24,70,243,38,98,18,135,93,209,72,249,82,81,37,58,89,174,72,212,2,145,215,225,171,80,87,95,252,163,71,197,125,93,21,178,183,84,215,232,54,64,185,234,251,113,95,219,134,135,50,173,44,20,165,75,8,125,98,189,94,238,120,100,247,118,46,128,62,86,55,99,180,248,12,242,134,117,108,117,48,91,62,97,2,233,97,70,235,113,244,29,21,92,15,197,199,73,113,204,74,229,209,187,31,232,133,243,246,80,22,138,246,66,86,53,228,201,119,243,15,16,217,157,204,34,228,75,31,37,70,143,200,29,63,172,24,51,182,231,124,161,194,54,120,119,37,98,208,89,183,72,22,29,228,119,80,33,124,195,236,69,77,28,87,130,245,36,101,114,167,200,228,40,249,198,141,246,66,19,69,135,212,36,246,193,198,192,60,102,37,145,147,49,240,67,182,227,67,144,112,226,30,109,7,219,251,208,4,174,159,164,
255,237,75,78,109,169,235,112,16,112,48,203,147,154,49,68,238,72,210,106,33,117,245,117,134,52,40,156,251,226,244,225,227,91,109,187,189,167,234,215,53,228,192,98,252,75,78,147,63,253,191,122,235,237,37,116,230,158,100,133,161,50,224,219,82,60,33,228,184,125,253,65,76,72,232,158,103,98,238,243,81,122,113,100,140,42,136,255,197,85,120,162,85,206,225,41,27,247,81,176,71,145,79,118,121,211,102,242,109,219,156,102,1,81,80,110,178,201,32,169,136,85,114,145,16,39,28,62,191,246,253,155,153,18,248,205,110,89,125,143,195,248,36,59,162,38,250,45,198,182,45,205,87,90,210,169,247,49,207,168,125,186,138,164,19,205,89,22,200,100,44,172,40,104,157,83,138,144,47,160,87,20,6,229,50,92,102,233,138,50,208,129,56,85,227,177,70,90,205,179,201,15,220,111,138,125,62,23,240,137,240,6,228,31,183,8,29,105,255,56,222,219,153,32,165,12,136,62,82,86,176,135,97,231,181,248,91,155,221,67,80,216,225,70,242,156,31,189,247,182,144,105,161,85,11,155,205,185,17,23,105,128,30,120,242,47,24,125,36,156,159,134,103,
216,243,45,0,89,199,83,89,23,92,75,74,68,50,159,98,140,150,208,6,247,155,93,229,192,23,96,141,231,176,210,188,239,46,228,69,51,63,100,85,248,70,183,151,50,100,75,146,8,172,177,234,143,80,230,32,152,195,122,96,75,122,214,218,30,33,99,168,171,112,61,184,64,216,182,228,58,235,141,46,183,145,152,184,225,140,86,227,104,135,171,226,13,124,80,52,32,125,33,237,49,236,179,93,156,200,92,55,182,85,76,163,97,70,139,13,70,21,80,39,73,179,140,207,132,236,169,216,169,64,213,234,198,50,156,59,1,209,135,49,107,74,46,19,144,212,22,203,81,249,178,168,245,195,134,10,242,139,171,16,138,84,58,131,119,66,145,235,208,236,246,204,64,217,191,233,29,194,120,151,122,179,34,144,138,37,20,42,151,101,14,219,42,221,75,189,183,25,107,205,248,81,138,39,52,153,219,69,4,172,58,26,25,6,196,182,175,232,136,205,49,236,94,113,1,72,209,250,235,171,180,105,31,254,61,241,195,85,177,81,1,78,66,37,138,230,71,123,66,24,85,90,168,97,186,84,4,187,146,133,45,176,55,78,235,11,202,121,179,105,178,234,46,155,217,31,161,196,74,
224,195,167,206,245,219,153,68,106,116,21,209,189,235,21,78,186,154,163,26,135,186,164,105,95,232,251,188,39,89,159,60,71,247,132,48,174,116,161,78,64,114,149,182,220,162,112,195,16,49,201,242,235,202,91,164,100,189,108,54,177,159,129,95,190,131,25,234,153,152,127,141,214,148,172,252,68,0,37,177,65,75,139,153,231,149,52,242,84,29,145,17,51,54,176,122,225,133,26,113,228,32,84,138,209,252,144,79,8,146,122,133,147,215,221,171,244,24,181,140,155,82,172,89,115,164,109,234,190,139,179,7,160,141,85,135,74,5,58,58,37,190,249,10,188,195,248,199,169,143,172,137,25,91,179,242,200,186,214,253,40,67,6,104,200,88,67,74,92,172,121,151,158,9,232,14,20,69,228,100,20,19,13,146,184,228,219,237,129,109,147,39,121,43,188,76,38,197,166,167,73,65,13,246,183,61,251,1,118,32,29,20,153,216,230,44,11,126,32,109,205,226,233,184,152,251,204,235,225,111,124,4,43,143,2,190,238,64,15,137,208,144,177,69,75,72,223,46,35,151,251,197,37,58,234,77,80,244,98,19,223,57,195,129,177,176,161,143,203,204,18,202,58,87,
115,13,179,234,46,188,219,111,171,192,0,112,34,251,98,158,113,61,10,214,68,225,9,16,132,35,87,210,174,110,147,131,29,161,17,32,234,89,103,153,103,127,186,58,155,248,50,186,79,170,103,76,139,147,240,71,28,137,79,143,201,116,249,15,225,120,23,206,50,1,122,8,145,198,22,212,43,60,247,54,51,66,205,186,71,61,193,214,8,85,196,214,200,62,106,179,139,88,167,53,29,227,220,109,17,191,201,141,235,253,219,98,93,39,5,42,204,111,108,136,219,66,179,215,232,135,170,138,209,146,17,149,62,113,146,242,250,208,156,52,140,128,253,157,200,196,219,206,23,130,179,33,28,46,154,238,225,187,147,82,105,63,75,20,193,199,242,181,235,200,231,51,142,191,196,46,188,212,43,149,44,94,209,156,229,37,168,59,57,59,168,138,55,156,3,134,37,138,85,85,144,241,165,107,141,80,238,91,231,83,171,152,93,161,181,247,82,5,140,35,156,170,211,225,0,107,226,135,210,86,142,104,160,148,232,162,145,143,61,162,55,158,22,127,161,173,206,105,184,246,228,140,105,142,81,60,3,188,13,146,200,91,236,8,52,249,176,236,91,253,74,18,75,149,211,
176,115,6,40,204,243,175,221,228,169,90,81,246,100,110,149,90,192,9,211,233,110,97,133,205,253,28,82,92,193,106,22,85,179,156,192,31,55,209,246,179,236,153,215,5,10,236,103,107,225,154,238,72,186,204,208,212,188,117,53,186,76,145,63,114,186,83,23,234,156,126,107,252,168,211,243,72,74,51,92,163,187,218,233,9,215,165,33,206,212,147,131,230,1,88,99,230,37,31,238,115,116,67,242,93,199,74,158,76,15,196,104,141,13,251,145,117,116,0,140,35,73,55,242,199,192,111,88,33,63,211,71,181,156,206,53,224,50,22,93,118,85,41,52,88,40,124,162,73,162,37,45,218,172,135,178,55,141,221,152,62,206,100,161,105,80,255,24,152,164,61,41,53,250,121,243,7,254,164,38,40,250,110,110,8,175,6,195,133,170,101,146,211,151,27,139,53,68,33,203,168,86,122,21,37,255,242,38,108,144,224,154,167,247,156,191,191,210,94,242,48,38,110,153,28,92,76,77,13,191,250,186,126,249,239,106,128,110,68,103,154,52,219,44,163,81,192,107,127,149,220,63,6,84,66,30,99,219,149,189,145,183,23,85,185,37,151,72,33,18,172,8,214,228,98,77,176,
82,103,209,132,218,205,137,169,119,193,66,156,130,190,47,40,163,31,97,183,159,130,231,19,47,39,143,212,45,124,111,116,42,57,249,85,222,245,245,100,236,9,125,112,173,57,184,6,224,22,139,236,23,113,133,163,151,168,145,170,230,244,73,103,7,111,224,234,174,121,159,140,91,228,13,60,125,176,127,79,71,155,237,80,194,168,109,92,244,224,93,107,182,243,244,7,14,195,97,88,28,103,160,237,13,136,12,252,228,248,143,241,141,62,81,142,123,184,51,75,141,21,126,209,239,15,104,105,77,172,247,182,201,186,75,224,44,55,38,161,8,229,226,237,100,208,181,166,76,113,78,189,1,152,125,163,228,115,163,12,145,230,63,156,231,231,78,88,206,136,151,179,219,137,223,253,114,166,215,40,108,176,222,184,65,136,70,88,10,48,244,61,119,247,248,186,221,177,133,81,83,158,21,21,63,20,28,36,46,61,79,87,21,131,147,168,194,109,20,90,219,191,194,139,248,185,158,239,48,160,31,52,223,214,100,45,167,255,131,211,169,239,14,104,216,98,185,215,58,2,227,73,58,91,50,43,33,35,153,103,109,249,154,96,32,17,100,229,209,203,145,92,101,
119,197,233,21,198,168,107,155,156,171,236,214,245,94,204,110,183,123,225,211,42,49,117,185,165,254,15,189,96,133,191,141,136,167,169,7,186,215,253,75,63,123,170,177,198,236,76,134,83,155,91,38,54,0,148,135,185,77,27,102,237,132,73,68,3,211,22,119,179,128,208,155,215,199,96,121,238,163,129,67,218,196,160,54,65,213,154,104,131,177,212,108,198,121,193,145,83,118,4,140,5,236,179,130,138,92,107,219,129,244,235,211,172,206,206,46,12,82,146,122,128,139,203,205,153,158,227,238,25,207,171,126,52,121,238,251,178,3,93,98,30,183,247,12,73,124,111,183,121,7,149,187,171,233,209,91,20,232,204,167,192,195,223,59,250,19,36,168,20,212,6,41,16,169,242,221,240,194,229,118,97,13,76,43,165,195,86,22,35,193,48,31,237,167,146,90,56,250,229,169,34,30,229,140,178,14,80,4,92,43,1,193,193,201,192,138,70,19,100,26,131,140,49,55,121,244,202,50,242,142,142,69,129,133,5,79,31,140,39,32,221,86,213,234,76,94,42,34,213,41,195,243,236,21,71,103,46,98,31,61,9,140,164,204,207,159,79,107,215,182,4,63,140,205,100,
147,187,238,241,241,190,242,162,127,242,21,98,73,139,64,20,78,195,62,38,228,167,219,107,91,116,116,28,201,26,133,219,86,19,213,99,48,68,244,192,159,1,179,53,214,159,12,115,52,164,214,161,159,55,224,220,33,115,65,2,8,50,244,238,49,9,70,154,197,197,197,1,17,233,39,88,68,25,202,185,253,149,229,31,14,159,233,214,245,90,125,141,188,46,54,123,226,56,224,135,178,84,3,225,73,17,148,175,79,125,233,123,160,192,114,103,98,66,249,236,202,161,66,225,246,246,222,177,206,14,161,6,120,229,66,220,179,88,152,133,40,139,116,166,135,190,34,136,173,76,10,247,32,109,0,48,217,0,171,169,159,63,89,0,161,140,85,79,214,14,37,181,6,30,0,232,100,126,237,75,205,145,24,253,62,176,113,233,230,139,16,52,208,209,25,40,141,158,222,229,44,75,80,34,237,232,136,55,109,255,150,101,204,26,98,24,126,75,133,183,207,17,37,44,180,213,63,214,132,205,81,105,215,74,228,209,45,228,34,172,201,159,225,196,231,11,115,65,150,1,241,142,84,204,167,48,25,169,104,100,10,27,62,170,52,149,85,218,127,98,203,181,43,80,3,241,71,78,201,
123,198,168,46,93,12,121,119,74,18,178,70,63,0,172,213,68,163,6,155,171,17,73,108,146,87,121,214,105,213,40,255,2,22,189,142,141,228,114,210,14,193,4,185,237,250,100,16,83,7,77,167,124,248,80,239,70,138,1,172,50,165,177,219,210,14,65,197,248,157,77,23,42,1,39,21,225,240,131,39,219,37,223,114,40,137,250,89,48,57,111,178,232,7,239,77,36,199,155,14,25,208,210,79,103,100,162,235,100,0,126,14,205,229,221,51,127,68,84,168,187,205,45,8,114,4,85,211,62,157,221,46,65,198,172,193,61,149,206,10,15,142,234,125,53,41,52,219,251,108,249,128,254,57,165,203,218,247,75,15,223,100,243,157,192,27,25,135,11,209,136,240,51,249,215,72,143,160,48,254,68,79,58,57,164,120,250,234,179,168,193,123,195,240,110,252,140,78,37,68,149,7,223,255,104,117,150,229,171,59,89,64,249,217,90,229,115,194,205,209,136,219,10,101,76,118,155,183,3,143,90,143,25,141,116,177,15,178,49,144,124,71,46,184,184,58,228,50,51,153,126,28,18,8,19,205,139,72,95,163,105,255,250,61,125,123,64,230,230,17,53,244,134,71,143,164,19,227,158,
235,155,143,47,247,29,191,188,156,102,139,87,127,225,58,53,177,219,189,206,190,125,195,234,29,121,11,154,111,97,140,71,221,199,82,232,219,70,21,85,99,118,0,225,139,33,92,227,185,229,28,227,219,51,254,26,167,255,39,208,186,174,189,159,193,196,59,158,169,170,255,96,105,193,79,43,145,91,21,90,118,211,250,180,165,118,169,52,68,240,200,134,145,181,189,114,3,107,2,31,178,77,228,96,120,46,145,142,50,105,163,52,227,181,135,242,169,114,248,83,71,167,188,76,238,18,149,101,86,13,70,101,167,58,101,31,23,233,243,144,233,7,171,230,140,31,4,59,94,141,140,240,133,118,116,147,4,170,139,80,34,184,124,139,240,140,213,253,0,254,188,140,6,137,138,97,56,16,231,215,70,142,89,253,218,64,3,7,218,38,66,109,27,35,178,221,238,144,173,153,180,212,25,239,71,82,64,72,87,38,141,244,241,145,15,225,107,15,125,63,170,242,189,141,78,226,95,159,236,97,101,150,56,204,143,228,26,88,222,69,50,219,204,94,237,150,232,22,190,161,151,190,21,164,19,160,69,126,192,80,85,177,209,81,144,98,242,224,66,237,28,25,93,173,59,225,
39,56,128,158,51,113,164,126,20,21,172,230,151,27,89,9,180,158,11,4,139,187,142,210,1,204,33,48,81,209,94,68,240,91,135,208,205,16,250,100,36,178,92,101,49,41,154,219,172,97,26,209,199,54,91,207,208,181,138,5,106,130,213,156,236,237,181,92,151,25,125,126,86,50,241,170,67,74,65,38,207,54,135,26,151,56,141,18,191,104,162,104,243,86,181,48,173,34,119,111,189,90,79,247,51,22,218,233,173,144,102,110,199,135,68,77,245,0,158,80,153,57,140,183,255,231,124,105,155,54,53,77,246,183,207,234,206,55,130,70,161,43,243,57,248,2,42,107,144,70,138,67,8,155,124,6,82,102,14,37,181,127,193,9,26,37,116,241,87,125,200,182,199,142,156,28,118,125,63,86,21,206,242,231,26,86,243,21,251,201,168,143,232,192,10,46,50,174,172,101,25,215,97,124,198,242,29,170,114,97,250,170,239,64,157,6,20,47,114,18,159,167,151,96,209,237,40,253,88,120,16,64,198,116,162,70,212,203,175,231,110,159,91,237,42,54,146,120,92,111,64,78,41,25,92,49,196,21,91,7,142,141,250,56,217,2,240,46,11,16,35,100,19,172,55,104,178,217,195,13,
184,104,42,200,197,233,242,189,53,91,189,192,82,214,109,110,222,223,45,197,201,248,114,231,117,224,59,204,93,192,84,196,181,138,58,34,13,190,208,227,38,188,216,235,74,93,240,77,224,47,126,159,255,28,203,157,235,124,16,61,190,209,250,100,46,137,121,16,230,131,213,28,206,29,62,54,141,7,91,19,127,148,135,70,170,237,224,229,185,134,177,205,142,30,15,53,20,22,165,24,124,246,223,189,239,99,249,229,85,196,38,136,111,193,142,44,200,249,240,51,102,44,86,88,179,12,194,246,178,103,120,100,21,173,137,16,17,220,137,241,99,254,172,47,228,233,78,151,195,100,180,219,139,241,122,135,177,54,158,64,84,187,250,196,144,181,204,71,24,199,157,169,228,28,187,151,2,241,50,138,113,123,82,190,41,55,115,252,162,251,147,175,201,160,182,171,147,139,232,12,45,87,233,222,50,62,237,122,172,90,208,144,120,235,225,178,158,16,156,127,237,207,89,86,50,108,238,179,90,11,54,60,122,28,162,217,226,248,152,43,134,57,40,86,226,138,213,184,126,88,250,205,213,111,114,29,78,143,143,240,115,23,239,251,237,29,77,205,116,76,
161,20,139,90,169,116,109,63,166,165,79,70,205,189,185,57,4,99,117,91,25,133,53,217,186,26,223,205,182,154,249,240,45,218,51,230,136,9,22,38,108,161,62,221,255,198,241,77,233,35,172,76,96,112,116,38,176,30,107,197,122,191,82,233,110,95,29,243,228,100,13,147,133,241,166,243,163,137,149,107,1,187,206,15,137,120,153,142,78,95,103,217,178,81,229,212,243,114,47,15,211,82,15,173,126,179,47,179,84,229,188,126,185,207,139,222,216,75,30,242,143,254,201,240,77,240,108,248,133,170,24,37,175,138,101,18,11,190,211,110,247,155,130,69,92,124,41,117,100,37,253,140,150,173,44,234,71,53,163,142,214,132,246,43,94,175,168,0,6,176,133,70,64,11,69,86,215,254,160,60,83,24,126,222,252,178,219,100,217,171,168,25,184,225,233,90,21,137,203,88,227,206,210,165,236,5,90,48,252,105,139,214,26,102,136,132,48,56,7,252,163,82,216,94,217,166,77,35,118,241,131,150,172,140,116,77,94,165,160,234,173,253,178,55,235,205,187,244,83,55,30,122,8,47,59,123,115,223,119,125,72,239,107,31,104,117,28,95,146,140,107,32,76,18,
242,202,151,208,200,197,68,170,68,27,203,184,65,88,226,247,87,137,142,91,25,146,231,245,10,178,56,165,166,86,170,3,36,114,118,140,244,173,35,242,189,14,200,212,87,251,163,29,0,29,141,81,174,74,90,42,238,201,124,99,177,224,171,121,39,10,34,121,110,168,37,119,46,87,254,105,232,70,142,100,105,219,55,87,111,202,243,200,231,119,200,10,33,230,46,181,180,44,70,60,81,227,234,14,187,101,62,99,147,73,80,186,246,155,203,226,191,60,100,212,215,233,204,129,131,15,27,162,134,73,254,150,171,155,31,73,87,30,79,36,30,173,217,19,35,238,218,122,104,92,231,182,166,168,125,97,99,142,83,47,167,233,46,193,63,132,110,235,127,33,159,255,66,252,180,154,32,33,65,227,184,150,211,115,219,225,236,238,132,41,227,89,210,13,234,251,100,29,212,181,203,216,242,44,237,139,95,68,10,231,95,209,122,183,197,116,116,175,189,47,48,188,208,62,253,43,164,125,253,233,141,243,183,228,99,46,166,198,98,26,64,141,1,43,136,87,156,138,113,247,198,172,200,184,80,181,178,208,138,48,133,197,211,58,34,5,85,61,66,135,137,67,9,107,
20,216,93,239,167,59,222,45,133,185,212,235,78,79,202,155,8,135,174,87,59,40,115,106,41,221,181,84,252,184,236,11,134,75,160,151,121,140,118,75,77,99,155,6,171,175,255,196,148,252,50,235,150,187,41,218,147,224,139,122,65,141,158,191,214,155,184,47,141,35,33,169,243,107,229,105,104,219,188,194,109,67,181,5,119,183,123,7,13,42,151,41,104,20,247,43,73,173,158,243,125,87,74,5,194,115,24,113,82,95,214,22,239,178,108,132,127,250,48,127,246,214,161,134,168,32,11,232,59,169,167,41,59,120,55,228,176,121,184,91,222,59,232,23,242,147,142,227,95,163,187,151,162,93,72,69,187,230,161,108,80,209,120,102,185,119,164,117,253,142,179,122,131,130,174,69,70,113,197,202,155,49,209,251,15,142,156,251,245,156,204,85,195,222,185,244,130,184,187,229,115,95,3,42,148,3,112,73,205,155,241,97,202,84,49,228,50,11,82,53,179,138,247,206,69,135,101,197,137,47,244,97,159,54,106,183,58,179,102,105,133,113,47,75,189,126,181,190,247,170,108,133,191,7,159,97,86,75,254,62,152,95,21,255,123,254,187,101,213,29,22,164,
69,193,18,242,47,131,134,76,251,155,15,55,190,236,114,186,78,192,8,83,38,113,37,31,56,75,67,89,116,209,250,165,65,226,60,35,51,62,111,169,154,214,146,134,184,244,155,239,67,100,101,225,194,22,77,172,144,195,10,163,130,39,88,101,166,28,199,237,11,99,55,255,196,182,124,38,68,51,201,172,92,142,122,26,20,255,236,217,155,68,224,24,191,133,254,249,88,121,70,83,141,1,169,40,27,82,98,187,118,127,223,100,185,227,109,239,2,145,248,4,214,180,14,182,93,161,3,139,149,12,195,242,126,246,152,210,155,68,77,217,104,245,90,54,24,247,21,219,182,11,85,239,196,138,202,218,231,118,232,82,111,200,192,31,75,62,218,80,239,185,24,110,252,53,22,253,53,84,255,116,235,108,66,56,131,251,225,183,106,96,35,243,154,122,153,28,252,134,92,136,227,19,154,174,66,219,7,43,93,147,223,70,254,39,178,202,102,246,69,187,217,159,155,64,183,100,224,236,193,212,236,168,139,124,107,69,34,244,69,127,35,42,1,91,131,133,208,239,147,115,236,198,187,14,103,89,27,60,170,229,225,175,21,230,138,68,115,184,111,118,126,150,248,147,
41,106,166,12,9,248,32,226,55,75,178,121,168,170,224,181,133,235,46,50,252,205,192,38,165,245,105,78,105,36,87,198,121,242,253,109,211,115,215,155,69,9,233,23,185,39,208,152,11,247,234,210,168,216,179,164,70,237,182,7,94,59,127,107,181,23,79,165,77,25,44,247,50,93,210,218,142,238,203,10,154,46,81,153,212,62,87,176,230,236,205,155,177,154,227,116,245,130,140,91,112,120,104,226,169,89,212,31,246,177,96,119,93,91,248,58,234,106,190,182,174,130,235,154,144,192,172,147,112,199,165,206,6,202,227,248,32,228,200,32,219,210,188,71,120,201,47,227,116,108,144,216,128,198,7,107,150,136,172,71,82,220,43,104,215,35,123,177,51,75,127,191,151,135,32,27,95,36,137,242,24,109,136,107,36,30,138,166,221,42,24,32,44,135,129,157,74,43,130,253,186,6,93,94,230,170,135,193,171,107,153,110,111,62,120,87,234,194,29,203,212,7,138,59,119,234,195,111,143,64,210,129,7,228,50,171,58,84,86,147,227,20,9,242,47,125,63,92,57,106,205,2,227,187,106,38,51,25,247,241,94,29,144,55,248,117,188,104,34,236,36,10,215,240,
87,30,196,136,59,38,139,230,20,189,83,58,136,151,194,4,86,164,49,212,72,92,20,254,219,218,227,148,155,241,72,34,16,236,36,182,38,212,86,148,137,149,24,25,242,234,187,197,204,16,165,3,172,248,180,4,117,109,209,245,36,254,55,214,218,179,167,189,83,153,72,128,131,47,29,47,187,58,232,123,216,240,67,45,241,51,93,225,203,149,201,251,92,225,215,35,209,66,45,122,221,57,173,93,201,95,126,169,79,144,9,143,137,204,184,150,44,170,106,11,231,125,99,171,70,74,101,103,103,235,247,246,240,182,32,82,206,214,132,81,57,100,182,113,214,177,244,31,110,160,222,156,129,221,233,157,108,68,78,39,63,198,75,13,5,96,184,190,79,184,61,119,198,250,197,81,7,180,110,226,3,221,11,111,29,24,183,83,153,207,191,251,26,53,123,45,68,140,8,43,82,190,80,230,176,184,199,30,176,14,248,44,172,80,82,243,128,14,177,206,91,253,39,134,31,117,114,73,41,122,130,252,98,116,41,161,82,204,236,210,225,159,211,206,51,103,32,233,153,81,82,24,135,242,115,10,155,214,99,157,69,3,191,134,216,52,249,185,218,138,230,24,230,38,37,8,245,
102,187,90,205,3,253,111,163,234,104,179,49,223,174,189,39,180,190,124,200,102,173,139,80,250,109,215,74,119,31,192,75,240,180,150,208,6,44,204,36,167,35,228,126,206,45,67,84,89,154,19,131,22,226,224,46,103,171,17,154,39,134,185,17,126,105,16,115,217,209,144,45,34,238,118,49,61,88,238,12,113,70,210,236,241,132,60,48,23,197,149,63,129,151,137,38,82,232,178,64,247,178,25,201,244,223,197,77,54,212,90,217,21,131,63,177,153,61,212,9,215,230,217,3,39,84,144,220,246,37,211,12,224,237,120,247,172,228,202,34,204,113,113,54,78,170,134,191,227,130,82,145,167,188,49,115,230,145,61,86,59,250,250,166,77,84,189,185,46,18,200,207,191,126,125,115,21,252,156,195,20,93,125,207,222,57,167,108,155,242,232,121,30,47,84,114,46,212,253,61,95,207,57,195,55,64,158,128,20,95,188,17,246,130,211,91,206,80,76,93,127,70,217,117,69,215,214,206,83,129,54,179,177,184,35,251,27,163,0,251,71,46,48,69,16,2,8,191,203,188,188,229,174,194,190,226,145,130,126,204,243,137,82,217,37,160,51,7,54,23,203,148,236,249,18,88,
195,6,49,44,231,183,154,109,91,145,69,227,185,208,173,251,155,2,104,181,112,193,101,139,211,194,31,107,34,232,116,162,99,232,184,177,73,180,153,191,127,31,5,129,184,32,73,254,103,212,60,68,249,37,181,248,58,88,204,34,176,76,11,159,188,60,65,155,185,3,164,127,129,4,225,210,61,41,177,246,133,182,248,81,230,133,190,112,78,141,137,169,159,140,79,0,200,225,247,159,223,191,15,15,193,122,225,119,102,244,149,92,221,220,72,188,24,85,36,58,61,96,122,229,158,220,11,243,227,6,161,173,23,116,231,150,207,139,8,167,51,179,254,26,51,215,101,206,224,239,138,218,145,11,22,30,220,173,172,255,212,247,246,104,217,54,170,62,150,173,24,131,248,15,240,176,215,244,155,73,36,42,134,105,197,167,18,69,220,54,204,98,102,221,119,32,220,162,126,183,15,161,166,50,207,18,19,238,4,252,184,168,143,55,12,15,238,48,139,170,51,7,220,132,202,129,34,31,17,162,100,215,240,72,14,195,134,229,117,6,71,202,196,157,229,152,239,159,240,215,46,249,84,249,6,21,83,47,2,63,87,254,204,127,43,37,238,24,194,22,203,228,23,202,32,
29,235,190,206,237,13,14,109,231,140,8,248,97,148,53,152,178,187,128,188,88,14,169,187,209,197,241,147,46,50,64,62,114,155,51,197,61,65,133,96,5,250,1,182,97,14,27,138,214,85,48,250,91,71,104,233,153,39,17,245,205,6,46,176,106,152,186,89,42,81,249,172,50,41,111,116,10,230,32,114,232,229,41,217,138,203,206,112,75,87,44,144,130,253,63,164,4,29,112,82,134,29,162,111,86,43,192,83,75,39,192,219,212,129,176,23,196,243,215,113,227,94,49,39,199,106,253,238,202,252,84,234,38,245,230,135,112,201,138,61,78,231,164,6,158,20,182,62,87,21,189,214,206,183,203,182,121,168,75,132,112,182,49,83,204,168,41,143,84,38,246,84,18,3,121,255,13,22,26,87,162,123,88,123,19,198,59,104,213,164,49,134,218,119,127,124,176,87,122,90,2,57,185,30,2,104,52,183,232,23,255,23,84,225,112,220,217,117,108,27,128,93,71,255,198,161,215,164,165,248,191,107,104,37,158,22,111,191,62,240,68,108,225,15,0,248,56,93,253,12,90,109,158,64,101,129,238,52,56,177,61,59,168,81,40,190,166,152,247,10,245,11,140,192,242,99,237,233,224,
121,228,106,186,133,94,195,65,198,33,82,83,10,190,227,195,58,121,38,209,93,232,150,200,143,191,34,15,209,72,171,52,25,43,22,161,15,129,168,76,102,173,91,31,53,68,70,151,248,55,8,115,76,122,8,119,168,238,255,54,57,164,75,30,63,11,201,205,78,185,101,1,79,52,53,199,146,140,141,102,136,127,49,220,196,24,166,2,208,106,118,208,76,39,40,50,104,12,129,223,129,10,87,239,99,142,224,150,200,149,214,204,222,103,177,12,58,9,255,129,52,104,92,127,6,195,191,83,65,211,137,21,167,175,60,149,149,254,181,78,231,191,207,201,123,136,149,92,255,240,168,47,89,29,50,108,2,123,252,227,189,119,241,216,146,172,29,5,94,134,138,60,222,237,151,193,142,143,67,189,37,172,157,49,232,179,22,214,232,5,237,16,203,106,184,177,106,96,215,95,204,43,148,38,243,148,49,178,159,228,234,162,135,62,251,116,70,99,47,132,231,162,179,172,40,249,94,180,190,12,22,0,60,172,81,86,214,23,164,6,121,53,136,151,221,88,198,194,121,129,92,194,149,54,67,201,209,184,166,63,116,214,150,218,204,72,131,247,204,50,202,124,157,245,241,207,
11,79,163,210,251,47,215,171,44,120,205,106,75,112,153,55,152,209,75,18,213,160,168,101,151,183,160,24,204,243,10,33,89,233,143,69,190,178,62,239,253,8,231,247,195,94,97,82,99,143,64,171,21,123,106,109,1,239,220,134,0,211,7,41,214,189,144,238,154,74,37,169,148,103,176,183,54,222,171,122,192,171,149,200,218,96,136,155,130,184,168,73,111,80,88,69,67,30,121,88,202,97,126,13,171,103,144,88,33,249,166,173,221,217,217,222,95,65,171,91,148,210,136,219,175,86,189,255,252,144,247,69,252,7,28,1,7,81,94,9,127,67,245,170,212,78,39,226,131,41,31,147,18,13,77,89,161,252,235,119,166,64,157,254,56,119,105,64,164,171,201,54,230,17,45,181,102,127,117,32,122,55,248,142,223,149,79,35,224,130,250,20,228,246,153,79,242,245,26,176,75,15,198,198,100,4,132,125,167,120,197,207,133,140,229,85,22,14,29,96,177,8,255,20,26,142,102,237,14,2,162,17,153,189,24,187,162,170,108,111,102,153,239,207,5,103,156,172,121,168,105,118,155,113,158,177,57,94,41,165,209,20,143,218,235,56,191,177,188,118,206,108,182,115,167,
138,62,87,143,66,186,111,123,189,146,31,195,165,187,151,11,43,25,223,7,65,134,141,214,62,218,116,136,155,249,38,212,218,188,8,239,49,228,66,158,186,78,153,73,241,24,178,207,98,147,148,18,230,176,254,230,17,235,14,182,112,173,33,36,84,186,162,88,137,180,152,107,222,25,58,68,6,122,247,227,122,37,220,15,0,139,125,132,254,43,192,67,151,208,76,58,32,228,49,5,156,170,226,202,46,206,186,128,158,228,151,240,149,190,206,127,18,24,45,125,140,74,246,55,117,205,71,79,15,85,136,23,38,44,170,96,86,236,179,33,25,55,74,230,70,6,167,184,21,240,33,39,171,83,217,206,175,255,50,69,122,40,182,190,66,53,49,13,0,42,143,134,194,144,239,131,86,53,41,36,211,24,52,230,64,34,201,79,141,19,193,189,146,18,154,207,164,94,230,252,37,238,126,203,51,136,225,75,79,75,40,227,237,171,237,66,63,230,31,201,117,224,206,188,33,180,179,197,252,171,167,84,141,249,213,235,231,115,155,27,163,107,160,1,220,209,12,177,140,231,174,20,5,18,206,178,133,74,99,127,198,12,11,118,200,214,205,205,238,177,203,172,190,232,208,233,198,
69,53,209,19,56,222,91,178,137,247,227,118,69,125,47,104,153,89,201,66,22,208,14,18,143,66,117,48,208,113,104,65,227,56,122,154,98,136,72,192,190,53,38,229,83,39,69,59,128,249,140,21,16,41,254,27,216,6,204,231,151,194,116,168,133,33,198,38,9,146,217,131,78,201,165,110,162,150,12,36,206,149,149,108,217,127,79,212,102,150,235,143,102,237,99,106,75,117,147,2,235,163,44,223,96,235,248,179,232,175,20,120,136,87,146,26,31,134,140,35,72,177,7,200,2,164,56,70,192,233,162,107,13,255,38,107,32,64,63,37,46,224,243,113,52,241,127,128,20,21,23,122,42,134,109,170,36,145,217,58,163,98,23,43,43,102,229,32,81,122,90,61,230,117,66,31,84,243,182,84,53,230,144,254,107,4,232,116,103,242,65,138,155,52,24,34,214,160,15,71,192,140,212,51,119,177,43,21,156,122,137,47,154,217,76,25,11,198,28,149,46,11,56,137,129,43,158,191,123,24,90,252,252,134,40,175,165,26,95,181,154,131,2,123,43,146,32,17,73,167,103,153,133,13,178,150,54,77,199,79,175,130,196,101,242,200,83,224,25,166,134,111,47,118,226,153,54,71,234,
57,65,226,42,66,224,212,55,79,190,225,214,224,232,79,8,34,37,211,186,170,163,217,148,129,239,56,112,69,253,165,177,19,156,73,44,31,129,126,128,81,226,123,54,3,32,80,124,48,194,17,16,128,39,93,189,78,65,20,12,11,92,173,59,26,116,240,203,102,72,239,224,144,142,161,231,179,84,230,171,234,181,151,99,231,67,18,92,116,26,182,113,22,152,108,107,168,153,211,29,150,94,10,219,31,35,206,185,170,173,236,140,70,37,169,10,223,135,90,238,71,14,234,236,40,112,167,24,149,175,53,239,134,57,171,65,30,115,70,5,199,237,235,231,51,154,29,97,154,201,254,249,29,141,253,56,210,247,134,150,46,79,44,206,221,23,90,16,105,201,169,151,223,194,211,69,88,106,80,120,121,77,196,247,155,169,37,246,45,142,86,183,68,157,127,189,155,132,169,71,188,216,5,169,67,127,202,246,240,111,59,176,174,52,140,195,191,73,138,71,127,80,169,172,251,32,91,51,19,1,24,195,49,208,120,35,119,31,174,218,24,146,134,190,10,216,222,99,255,44,25,90,226,43,201,252,41,56,18,194,190,38,10,148,248,183,181,138,222,52,7,90,84,134,173,58,148,234,
41,74,106,61,150,31,226,0,60,220,124,244,4,13,157,0,67,21,69,202,192,189,195,184,71,152,180,95,223,51,152,12,215,213,187,98,17,204,177,228,226,192,34,89,74,252,189,227,246,125,166,149,24,66,91,98,63,7,225,13,114,86,183,227,226,1,254,197,193,174,1,0,22,49,39,144,77,202,187,126,46,46,110,12,100,254,187,29,63,97,90,117,225,231,231,193,208,213,77,0,81,226,227,35,60,187,210,189,243,145,220,236,185,3,124,217,156,136,185,82,33,250,231,86,129,214,238,83,224,50,37,142,204,206,104,44,250,192,70,176,235,159,240,59,137,253,44,142,129,211,46,181,222,77,17,44,23,90,235,47,44,248,207,236,238,3,173,14,11,139,191,207,198,65,8,149,64,30,172,181,61,26,154,102,7,137,7,112,129,26,41,151,18,127,211,177,207,34,0,105,125,106,136,250,35,19,104,26,64,63,157,101,100,23,69,129,5,177,209,126,13,25,105,222,106,73,228,64,40,135,176,208,189,244,139,117,44,160,175,7,205,167,239,127,125,5,160,40,125,6,219,138,251,35,135,194,246,55,62,61,255,140,35,217,65,57,248,85,66,29,235,171,129,166,108,192,1,49,118,179,173,
211,211,249,8,102,2,0,108,33,172,29,164,217,237,197,129,135,72,253,18,216,52,135,198,99,128,109,100,232,19,133,44,132,2,7,1,7,79,174,211,150,183,0,138,89,143,144,17,254,225,40,206,4,160,73,255,21,182,45,30,27,93,11,78,160,100,87,114,16,250,197,200,41,160,228,77,96,81,138,96,38,98,196,33,222,98,34,48,215,28,83,40,79,44,80,92,108,81,255,19,14,2,22,0,202,152,25,149,153,78,129,153,0,212,172,129,52,238,105,147,68,38,1,48,24,44,46,55,142,147,32,37,150,190,230,110,98,227,237,242,175,199,96,160,74,162,199,125,239,154,255,78,185,129,65,0,112,110,255,149,38,249,191,220,154,172,135,252,29,123,69,44,212,235,244,191,26,34,65,82,144,73,74,52,162,201,87,188,1,9,116,117,58,43,207,164,91,157,52,59,31,43,48,136,2,102,27,241,226,13,10,64,167,143,108,40,79,231,0,3,26,104,197,179,126,14,192,113,45,15,208,233,94,63,121,175,155,65,97,56,212,27,74,244,77,247,55,64,77,20,160,64,131,197,77,101,191,3,136,198,255,223,245,250,127,110,76,50,29,226,176,155,14,248,156,156,64,232,16,122,223,152,255,135,0,0,0,
0,255,255,3,0,176,119,205,243);

//background images - end ------------------------------------------------------


//system variable support ------------------------------------------------------
var
   //.system state support
   system_started_gui    :boolean=false;//23jun2024
   sicloseprompting      :boolean=false;//26aug2021
   sicloseviapostDONE    :boolean=false;
   visyncing             :boolean=false;
   visyncid              :longint=0;//changes each time system updates - 13feb2022
   vimustsync            :boolean=false;
   vimustloadid          :boolean=false;
   visyssettingsloaded   :boolean=false;
   viprgsettingsloaded   :boolean=false;
   //.0 or 1 based string handling
   stroffset             :longint=1;//Win32
   //.gui support
   stschemedata          :string='';//for stsync
   stlastschemedata      :string='*';
   vidataid              :longint=0;//increments each time "visync" fires with new data
   viloadid              :longint=0;//increments each time "visync" fires due to siLoadsettings
   vinormal              :tvirtualinfo;//set by "stsync"
   vititle               :tvirtualinfo;
   vimorecolors          :tvirtualmorecolors;//25may2021

   //.scale and zoom
   vilineVsep1           :longint=1;
   vilineVsep1orLESS     :longint=1;//2x per lineheight - 10dec2025
   vitepheight20         :longint=20;//20 px
   virowheight20         :longint=20;
   virowheight20orLESS   :longint=20;
   virowheight30         :longint=30;
   vilineheight20        :longint=20;
   vilineheight24        :longint=24;
   vilineheight30        :longint=30;
   vilineheight44        :longint=44;//11dec2025

   vizoom                :longint =1;//read-only -> calculated within visync() - 10dec2025
   viscale               :double  =1.0;//10dec2025
   viscale32             :longint =1;//int version of viscale 1..N, rounded down to nearest whole number - 26mar2026
   viscalemode           :longint =2;//2=automatic

   vitextscalingONCE     :boolean=false;
   vitextscaling         :double=100.0;//04sep2025
   vifontnameraw         :string='';//includes custom "?" - 26mar2022
   vifontnameraw2        :string='';//includes custom "?"
   vifontname            :string='';
   vifontname2           :string='';
   vifontsize__root      :longint=8;//used for system settings etc without scaling applied - 14mar2021
   vifontsize__root2     :longint=8;//used for system settings etc without scaling applied - 14mar2021
   vifontsize            :longint=8;
   vifontsize2           :longint=8;
   vifontheight          :word=14;
   vititlefontsize       :word=14;
   vititlefontsize2      :word=22;
   vititleheight         :word=22;
   vititleheight2        :word=32;
   vifontwidthratio      :single=1;//FontSize=8 is normal "1", larger fontsizes increase ratio and the reverse is true
   vitabratio            :single=1;//feeds from "viFontWidthRatio" but with safe range enforced
   viscrollsize__root    :longint=16;//14mar2021
   viscrollsize          :longint=16;
   viwheelspeed          :longint=1;
   vitouch               :boolean=false;
   vitouchsize20         :longint=20;
   vidoubleclicks        :boolean=true;
   viframemax            :boolean=false;//14mar2021
   viframemaxScope       :longint=0;//0=maximised only, 1=includes fullscreen - 04dec2024
   vidragtrigger         :longint=20;//was 10px, now 20 pixels before "dragging=true" - 05sep2020, 31mar2020
   vidragtriggerfine     :longint=1;//2 pixels before "draggingfine=true" - 17may2020
   viround               :boolean=false;
   vimultimonitor        :boolean=false;
   vidragfast            :boolean=false;
   visoftclose           :boolean=false;
   vifeather             :longint=1;//0=none, 1=low, 2=medium, 3=high
   visafearea            :boolean=true;//28aug2020
   visplash              :boolean=true;//29aug2020
   vihelp                :boolean=false;
   vihint                :boolean=false;//25dec2024
   viAppFirstRun         :boolean=false;//detect app's first time running - 04sep2025//1st run of app
   viontop               :boolean=false;
   viretainpos           :boolean=false;//13dec2025
   vihelp_bw             :boolean=false;//24jul2021
   vihelp_show           :boolean=false;//24jul2021
   vihelp_max            :boolean=false;//18dec2021, 24jul2021
   viecomode             :boolean=false;//09may2021
   virows                :boolean=true;//19aug2024
   vi32bit               :boolean=true;//09may2021
   viemboss              :boolean=false;//19nov2023
   vistartlink           :boolean=false;
   videsktoplink         :boolean=false;
   vistartuplink         :boolean=false;//09dec2023
   vistartstyle          :longint=0;//0=window, 1=min, 2=max, 3=fullscreen
   vistartstyleONCE      :boolean=true;
   vispecialcolors       :boolean=true;
   vicolorname           :string='';//default
   viclicklock           :boolean=false;//once a button is clicked down, it will always fire even if the mouse cursor on the up stroke is nowhere in the region of the original down click - 14mar2020
   visparkle             :longint=0;//0=off, 1..20=sparkle range
   vibrightness          :longint=0;//60..140
   visafestrength        :boolean=true;//limits the background strength that can be applied - 04dec2024
   viminimiseeffect      :boolean=true;//20jan2025
   vibordersize__temp    :longint=32;//default - 07jun2021
   vibordersize__root    :longint=5;//14mar2021
   vibordersize          :longint=5;
   vifocusedopacity      :longint=255;//27nov2027
   viunfocusedopacity    :longint=255;//27nov2027
   viopacityspeed        :longint=9;//27nov2024
   viLockposition        :boolean=false;
   viWinemode            :longint=0;//02feb2022
   viWine                :boolean=false;//determines whether or not the system should use wine
   //.sleek level
   vimodern              :boolean=false;//27may2025
   visleekAssitedscroll  :boolean=false;//28sep2022
   visleekHighlight      :boolean=false;
   visleekImages         :boolean=false;//09may2025
   visleekGradient       :boolean=false;

   viStartupdone         :boolean=false;//changes to TRUE when system has finished starting, e.g. loaded vars, aligned atleast once and displayed splash(if set)- 15nov2023
   viMaster              :boolean=true;//set in siIint() proc - FALSE=means program does not write settings to folder - read only mode

   //.midi device
   vimididevice          :longint=mmsys_mid_midimapper;//09sep2025, 05mar2022
   vimidideviceNEW       :longint=min32;//used to trigger an update to support controls etc - 05mar2022

   //.wave device
   viwavedevice          :longint=0;//05mar2022
   viwavedeviceNEW       :longint=-1;//used to trigger an update to support controls etc - 05mar2022
   //.frame support - 23feb2022
   viframename           :string='';
   viframeCODE           :tstr8=nil;
   viframeID             :longint=0;
   viFrameminsize        :longint=0;//for information purposes only - 27feb2022
   //.background support - 21jul2024
   vibackname            :string='';
   //.events
   visyncevent           :tnotifyevent=nil;
   //system vars
   programactivedebugger :boolean=false;

   //.window head support ------------------------------------------------------
   viheadcenter          :boolean=false;//11oct2022
   viheadalign           :longint=0;//0=left, 1=center, 2=right -> head based toolbars - 06jan2025

   //system debug support ------------------------------------------------------
   debug_msstart         :comp=0;
   debug_msstop          :comp=0;
   debug_mstimetotal     :comp=0;
   debug_mstimecount     :comp=0;
   debug_mstimetotal2    :comp=0;
   debug_mstimecount2    :comp=0;
   debug_mstimeavefast   :comp=0;
   debug_msstartave      :comp=0;
   debug_junk1           :string='';//22feb2022
   debug_junk2           :longint=0;//15mar2022
   debug_junk3           :comp=0;//22apr2022
   debug_junk4           :tobject=nil;//22apr2022

   //.tbasicdebug support
   debug_basicdebug_area              :twinrect;
   debug_basicdebug_areacheck         :boolean=false;
   debug_basicdebug_areafail_count    :longint=0;
   debug_basicdebug_areaoverlap_count :longint=0;
   debug_basicdebug_int1              :longint=0;

   //mis support
   system_default_ai     :tanimationinformation;//29may2019
   programdisablegraphics:boolean=false;//used to disable ALL graphic support for debug purposes

   //system translations
   tsBytes,tsB,tsKB,tsMB,tsGB:string;

   //system keybord support ----------------------------------------------------
   syskeyboard_laststate :byte=0;

   //system mouse support ------------------------------------------------------
   sysmouse_fine         :boolean=false;
   sysmouse_downxy       :tpoint=(x:0;y:0);
   sysmouse_movexy       :tpoint=(x:0;y:0);
   sysmouse_down         :boolean=false;
   //.used when "getcursorpos" is not possible - 10may2020
   miscursorpos_x        :longint=0;
   miscursorpos_y        :longint=0;


   //system menu support -------------------------------------------------------
   sysmenu_name          :array[0..19] of string;
   sysmenu_pos           :array[0..19] of longint;
   sysmenu_hover         :array[0..19] of longint;
   sysmenu_selstart      :array[0..19] of longint;
   sysmenu_selcount      :array[0..19] of longint;
   sysmenu_ref64         :array[0..19] of comp;

   //system cursor
   system_cursor            :longint;//index to "system_cursorlist()" list below
   system_cursorREF         :hcursor;//track any changes to current cursor image
   system_cursorlist        :array[0..2] of hcursor;
   system_cursorchanged     :boolean=false;
   system_clipcursor_active :boolean=false;//26jul2025: when TRUE, win____clipcursor is active and tbasicsystem won't run the resize window cursors or drag window actions

   //system support ------------------------------------------------------------
   system_guifirst       :tbasicsystem=nil;
   system_guiactive      :tbasicsystem=nil;
   system_debugrows      :array[0..49] of string;//17jul2025
   system_debugrows_count:longint=0;
   sysnewid              :longint=0;//unique system wide -> general purpose id -> range: 0..N
   sysnewid1             :longint=1;//unique system wide -> general purpose id -> range: 1..N
   system_mustpaint      :longint=0;
   system_mustpaintSLOW  :longint=0;
   system_mustalign      :longint=0;
   system_mustid         :longint=0;
   system_mustidSLOW     :longint=0;
   system_program        :tbasicapp=nil;//20jan2025, 24jul2021
   system_winepresent    :boolean=false;//TRUE when Wine is detected, i.e we are running inside Wine on Linux - 02feb2022
   system_instanceid     :longint=0;//set by "gossgui__start"
   system_instanceidREF  :tobject=nil;
   system_defaultcolors  :string='';//27mar2022
   system_onshowoptions1 :tnotifyevent=nil;//open
   system_onshowoptions2 :tnotifyevent=nil;//close
   system_onshowoptionsCLOSEDELAY:longint=0;//optionally close dialog after X seconds - 12nov2022
   system_onshowoptionsINITPAGENAME:string='';//intital page name to show - 06nov2022
   system_blackwhitecount:longint=0;//special black and white override mode - 09dec2024

   //.basicsystem list - 18jan2025
   system_list:array[0..9] of tbasicsystem;

   //.realtime process (program) support - 25mar2022
   system_realtimeSYNCING:boolean=false;
   system_realtime64     :comp=0;//determines whether realtime mode should be ON or OFF
   system_realtime642    :comp=0;//time cycle before re-syncing realtime mode (incase Task Manager manually overrides us) - 25mar2022

   //.frame code slots
   system_framename     :array[0..99] of string;
   system_framecode     :array[0..99] of string;
   system_framecount    :longint=0;

   //.color slots - built-in colors (excludes custom slots and user save file slots) - 13sep2025, 28jul2024
   system_colorname    :array[0..399] of string;
   system_colordata    :array[0..399] of tlistptr;
   system_colorval1    :array[0..399] of longint;
   system_colorcount   :longint=0;

   //system integrated status support - 04oct2022 ------------------------------
   sysstatus_fromfile               :longint=-1;//off
   sysstatus_tofile                 :longint=-1;
   sysstatus_encrypt                :longint=-1;
   sysstatus_blaizfolder            :longint=-1;//07oct2022
   sysstatus_blaizfolder_setpert    :boolean=false;
   sysstatus_painttime              :longint=350;//every 350ms

   //system find support ------------------------------------------------------- 18feb2023
   sysfind_handler                  :longint=0;//none -> use to instruct "find" capable handlers whether they're able to find or if the task belongs to another
   sysfind_text                     :string='';//text to find
   sysfind_cmd                      :string='';//action to take -> 'find' (find forward)
   sysfind_dlgshowing               :boolean=false;


   //system background support -------------------------------------------------
   sysback_count         :longint=0;
   sysback_name          :array[0..199] of string;
   sysback_datafromptr   :array[0..199] of tlistptr;
   sysback_datafromfile  :array[0..199] of string;//load tile from filename (name part only, no path or extension, e.g. "custom1")
   sysback_makename      :array[0..199] of string;//make tile from a name/vals - 02mar2026
   sysback_iscustom      :array[0..199] of boolean;
   sysback_canadjust     :array[0..199] of boolean;//default=false, true=one or more properties can be adjusted by user - 13mar2025

   sysback_remakeonScreen:array[0..199] of boolean;//tile is dynamic and should be remade when screen size changes - 02mar2026
   sysback_remakeonScale :array[0..199] of boolean;//tile is dynamic and should be remade when "viscale" changes - 02mar2026
   sysback_remakeonCrate :array[0..199] of boolean;//tile is super dynamic and should be remade everytime its queried, e.g. Random Color - 02mar2026

   sysback_canstrength   :array[0..199] of boolean;
   sysback_strength      :array[0..199] of longint;
   sysback_cancolorise   :array[0..199] of boolean;
   sysback_colorise      :array[0..199] of longint;
   sysback_canspeed      :array[0..199] of boolean;
   sysback_speed         :array[0..199] of longint;
   sysback_canhstep      :array[0..199] of boolean;
   sysback_hstep         :array[0..199] of longint;
   sysback_canvstep      :array[0..199] of boolean;
   sysback_vstep         :array[0..199] of longint;
   sysback_canfstep      :array[0..199] of boolean;//fade step
   sysback_fstep         :array[0..199] of longint;
   sysback_canhwobble    :array[0..199] of boolean;
   sysback_hwobble       :array[0..199] of longint;
   sysback_canvwobble    :array[0..199] of boolean;
   sysback_vwobble       :array[0..199] of longint;
   sysback_canfwobble    :array[0..199] of boolean;//fade wobble
   sysback_fwobble       :array[0..199] of longint;
   sysback_cancrate      :array[0..199] of boolean;//change rate -> for dynamic tiles
   sysback_crate         :array[0..199] of longint;

   //.default values
   sysback_strengthDEF   :array[0..199] of longint;
   sysback_coloriseDEF   :array[0..199] of longint;
   sysback_speedDEF      :array[0..199] of longint;
   sysback_hstepDEF      :array[0..199] of longint;
   sysback_vstepDEF      :array[0..199] of longint;
   sysback_fstepDEF      :array[0..199] of longint;
   sysback_hwobbleDEF    :array[0..199] of longint;
   sysback_vwobbleDEF    :array[0..199] of longint;
   sysback_fwobbleDEF    :array[0..199] of longint;
   sysback_crateDEF      :array[0..199] of longint;

   //common global filenames ---------------------------------------------------
   sysfile_colorscheme          :string='';
   sysfile_teaimg               :string='';
   sysfile_teaimg_openfilter    :longint=0;//open filter index
   sysfile_cursor               :string='';
   sysfile_cursor_openfilter    :longint=0;
   sysfile_background           :string='';//22jul2024
   sysfile_background_openfilter:longint=0;
   sysfolder_imagefilename      :string='';//21mar2026
   sysfolder_imageopenfilter    :longint=0;//21mar2026


   //system handlers support ---------------------------------------------------
   system_options_str1   :string='';
   system_options_pos1   :longint=0;
   //.sound volume support
   sys_sndvol32          :string='';
   //.system flash support
   sysflash              :boolean=false;
   sysflash_timer        :comp=0;
   //.system close support
   syslist               :array[0..39] of tobject;
   sysclose_count        :longint=0;//low level version in addition to basicsystem.closelocked (count) - 03apr2021
   systimer_enabled      :boolean=true;
   syswait_focus         :tobject=nil;//used for tbasicsystem.xshowwait to set/detect if it's the main tbasicsystem in use, and whether to cancel any showing dialog windows etc -> prevents 2 or more simultanous tbasicsystem's from locking in a cyclic "xshowwait()" reference stall or unexpected behaviour - 03apr2021

   //special clipboard formats -------------------------------------------------
   cf_png                :word=0;//08aug2025
   cf_bwd                :word=0;//26sep2022
   cf_bwp                :word=0;

   cf_rtf__RTFasText     :word=0;//16feb2026
   cf_rtf                :word=0;//16feb2026

   cf_html               :word=0;

   //system fast references ----------------------------------------------------
   sysfast_root          :string='';
   sysfast_settings      :string='';
   sysfast_schemes       :string='';
   sysfast_startmenu     :string='';
   sysfast_desktop       :string='';
   sysfast_programs      :string='';
   sysfast_blaiz         :string='';

   //system multi-tab support --------------------------------------------------
   //.optional -> used for general reference and return values for host application
   system_plus0          :array[0..programplusmax] of tobject;
   system_plus1          :array[0..programplusmax] of tobject;
   system_plus2          :array[0..programplusmax] of tobject;
   system_plus3          :array[0..programplusmax] of tobject;
   system_plus4          :array[0..programplusmax] of tobject;
   system_plus5          :array[0..programplusmax] of tobject;
   system_plus6          :array[0..programplusmax] of tobject;
   system_plus7          :array[0..programplusmax] of tobject;
   system_plus8          :array[0..programplusmax] of tobject;
   system_plus9          :array[0..programplusmax] of tobject;

   //main form round corner support --------------------------------------------
   system_patchcornerw   :boolean=false;//horizontal aspect of corner needs patching (+1 px)
   system_patchcornerh   :boolean=false;//vertical aspect of corner needs patching (+1 px)


   //system settings -----------------------------------------------------------
   syssettings           :tvars8=nil;
   prgsettings           :tvars8=nil;

   //EXE system storage --------------------------------------------------------
   //Streams are set when EXE has data packed behind it, which switches it to
   //slave mode with "viMaster=false"
   usrdata               :tstr8=nil;
   sysmore               :tvars8=nil;

   //sysbox
   sysbox                :tobject=nil;//tracks last active text box - 15feb2026, 14nov2023

   //system cursor support -----------------------------------------------------
   system_cursorname     :string='';
   system_cursorcolor1   :longint=0;
   system_cursorcolor2   :longint=0;
   system_cursorsize     :longint=0;
   system_cursorref64    :comp=0;

   //system timer --------------------------------------------------------------
   //.normal timer control - 30sep2021
   systimer64             :comp=0;//normal timer - (16ms/turbo) or (30-500ms/normal)
   systimer1000           :comp=0;
   systimerTICK           :comp=0;
   systimerLAG            :comp=0;
   systimerlasttick       :comp=0;
   systimerlastlag        :comp=0;
   systimerlagref         :comp=0;
   //..events
   systimer_owner        :array[0..199] of tobject;
   systimer_event        :array[0..199] of tnotifyevent;
   systimer_busy         :array[0..199] of boolean;
   systimer_delay        :array[0..199] of comp;
   systimer_ref64        :array[0..199] of comp;
   //.high speed timer in use status - for all subsystems that adapt to higher speed timing cycles - 30sep2021
   sysfasttiminginuse    :boolean=false;


   //system dlg value caching --------------------------------------------------
   sysdlg_popcolor_color :longint=0;
   sysdlg_popcolor_page  :string='';


   //system history support ----------------------------------------------------
   syshis_nam:array[0..39] of string;
   syshis_val:array[0..39] of array[0..99] of string;//each value is NIL(not used), "A<value>" active, "N<normal>"
   syshis_ref1:array[0..39] of array[0..99] of longint;
   syshis_ref2:array[0..39] of array[0..99] of longint;
   syshis_last:longint=0;


   //link1 support -------------------------------------------------------------
   syslink1_slot            :longint=1;
   syslink1_hdrsize         :longint=15;//state.1 + reply.bol.1 + bol1.1 + int1.4 + nlen.4 + vlen.4 = 15 bytes
   syslink1_size            :longint=60015;//60k
   syslink1_startref64      :comp=0;
   syslink1_DEADPUSHref64   :comp=0;
   syslink1_DEADPULLref64   :comp=0;
   syslink1_pushbusy        :boolean=false;



//start-stop procs -------------------------------------------------------------
procedure gossgui__start;
procedure gossgui__stop;

//info procs -------------------------------------------------------------------
function app__info(xname:string):string;
function info__gui(xname:string):string;//information specific to this unit of code


//system status support --------------------------------------------------------
function sysstatus_settext(const xindex:longint;const xvalue:string):boolean;//07oct2022
function sysstatus_setpert(const xpert:double):boolean;//07oct2022
function sysstatus_paintnow:boolean;//07oct2022
function sysstatus_stopped:boolean;//07oct2022
function sysstatus0(const xindex:longint;const xvalue:string):boolean;//07oct2022
function sysstatus(var xref64:comp;const xindex:longint;const xvalue:string):boolean;//04oct2022
function sysstatus2(var xref64:comp;const xindex:longint;const xvalue:string;xnewtitle:string;xnewpert:double):boolean;//07oct2022

//system procedures and functions ----------------------------------------------
function sysprogram:tbasicapp;
function sysprogram_monitorindex:longint;//26nov2024
function sysprogram_wh(var dw,dh:longint):boolean;

//-- system background support -------------------------------------------------
procedure sysback__init;//17apr2026, 19aug2025, 08mar2025
function sysback__maketileFromName(const d:tobject;const sv:string):boolean;
procedure sysback__clear(xindex:longint);
function sysback__canadjust(xindex:longint):boolean;
function sysback__findnameid(xnameid_asstr:string;var xnameid:longint):boolean;
function sysback__findbyname(xname:string;var xindex:longint):boolean;
procedure sysback__loadfrom(x:tvars8;xforce:boolean);
procedure sysback__saveto(x:tvars8);
function sysback__readvals(xindex:longint;v:tvars8;xforce:boolean):boolean;
procedure sysback__writevals(xindex:longint;v:tvars8);
function sysback__usedindex(xindex:longint):boolean;
function sysback__enforcerange(xnameid,xval:longint):longint;//enforce range
function sysback__setval2(xnameid,xindex,xval:longint;xforce:boolean):boolean;
function sysback__getval(xnameid,xindex:longint):longint;
function sysback__getval2(xnameid,xindex:longint;var xcanchange:boolean;var xval:longint):boolean;
function sysback__getval3(xnameid,xindex:longint;var xcanchange:boolean;var xval,xdef:longint):boolean;


//.system close support - 03apr2021
procedure low__sysadd(x:tobject);
procedure low__sysdel(x:tobject);
function low__closecount:longint;
procedure low__closelock;
procedure low__closeunlock;
//.other
function siFontname2_deffont:string;//12jun2022
function siFiltersettings(x:tvars8):boolean;
function siLoadsyssettings:boolean;
function siLoadprgsettings:boolean;
procedure siLoadsyssettingsfrom(x:tstr8);
procedure siLoadprgsettingsfrom(x:tstr8);
function siSavesyssettings:boolean;
function siSaveprgsettings:boolean;
procedure siSaveallsettings;//23mar2022
procedure siCloseprompt(x:tbasicsystem);
procedure viSyncandsave;//24jul2021
procedure viSyncandsave2(xforce:boolean);//04may2025
procedure viSync;//viscale and viscalemode - 10dec2025, 06may2025: bkSoft0/1/2, 11dec2024: now supports "Black and White" mode for emergency "Restore Defaults"
procedure vicopy(var s,d:tvirtualinfo);
procedure vicopy2(var s,d:tvirtualinfo;xbwmode:boolean);//02sep2025
procedure vimoderncolors(var x:tclientinfo);//05jun2025: line2, 04jun2025, 26may2025: tweaked
function viclientinfo(var x:tclientinfo;s:tbasiccontrol;xnormal:boolean):boolean;//18may2025

//.color procs
function sicolors_name(xpos:longint;var xname:string):boolean;
function sicolors_find(xname:string;var xdata:tlistptr;var val1:longint):boolean;
procedure sicolors;//28aug2025, 28jul2024

//.frame procs
function sifindframe(xname:string):string;//07jun2022
procedure siframes;//loads frames into system storage ready for use - 27feb2022


//system wide tracking procs - 01may2021 ------------------------------ TRACKING
//.idle trackers
function low__inputidle_nokeyboard:comp;//06dec2024
function low__moveidle_global:comp;
function low__canecopaint(var xtime64:comp):boolean;//11jan2025: 0..10m=normal speed, 10..30m=2fps, 30m+=1fps
//.other
function stableobj(x:tobject):boolean;//07mar2021
procedure low__showhelp(dshow:boolean);//13mar2025, 03nov2023
function low__vol(var xfilename:string):boolean;//check once only - 10OCT2010
function low__canshowvol:boolean;//07mar2022
procedure low__showvol;


//.keyboard support ------------------------------------------------------------
function low__shortcutOK(xcode:longint):boolean;//true=ak_key is assumed to be a shortcut key, false=else not
function low__akstr(xcode:longint;var xtext:string):boolean;//convert action key "ak*" -> "text char or text label" - 01apr2020
function low__akstrb(xcode:longint):string;//convert action key "ak*" -> "text char or text label" - 01apr2020
function low__keyboard__fromak(xcode:longint;var xctrl,xalt,xshift,xkeyx:boolean;var xkey:longint;var xhavekey:boolean):boolean;
function low__keyboard(xstyle:char;xkey:longint;xshift,xctrl,xalt:boolean;var xoutkey:longint):boolean;
function low__keyboard2(xstyle:char;xkey:longint;xshift,xctrl,xalt:boolean;var xoutkey:longint;var xlaststate:byte):boolean;
function low__makebasic__akkey(xkey:longint):longint;//22jul2025


//.mouse support -> fine control - 17mar2020 -----------------------------------
procedure low__mousefine_turnon(x:boolean);
function low__mousefine:boolean;
function low__mouse(x:tobject;xstyle:string):tpoint;
procedure low__mouse2(x:tobject;xstyle:string;var dx,dy:longint);
function low__getcursorpos(var x:tpoint):boolean;
function low__getcursorposb:tpoint;
function low__getcursordownpos(var x:tpoint):boolean;
function low__getcursordownposb:tpoint;


//.master support --------------------------------------------------------------
procedure master__storevars(xvars:tvars8;xsyssettings,xprgsettings,xwidth,xheight,xcursor:boolean;xtitle:string);
procedure master__size(swidth,sheight:longint;var dwidth,dheight:longint);
procedure master__title;
procedure master__cursor;//uses smore: "cursor"
procedure master__cursorCLEAN;


//.raw support -----------------------------------------------------------------
function low__imgdraw2432(s:tobject;stransparent:boolean;d:tobject;dx,dy,dswapblack:longint;dclip:twinrect;xgreyscale,xfocus:boolean):boolean;


//system font procs ------------------------------------------------------------

procedure font__smallfont(const xinfo:tvirtualinfo;var xresfont,xfontheight:longint);
procedure font__smallfont2(const xinfo:tvirtualinfo;const xscaleThreshold:double;var xresfont,xfontheight:longint);


//.0 and 1 based string handling support ---------------------------------------
//note: process strings consistently over zero-based systems (Android) and one-based systems (Windows)
function strbyte1x(const x:string;xpos:longint64):byte;//1based always -> backward compatible with D3 - 02may2020
function strcopy0x(const x:string;xpos:longint64;const xlen:longint64):string;//0based always -> forward compatible with D10 - 02may2020
function strcopy1x(const x:string;xpos:longint64;const xlen:longint64):string;//1based always -> backward compatible with D3 - 02may2020
function strlastMatch(const x:string;const xvaluetomatch:string):boolean;//07jan2022
function strlastx(const x:string):string;//returns last char of string or nil if string is empty


//.number and string support ---------------------------------------------------
function low__newid:longint;
function low__newid1:longint;
function largestwinrect(a,b:twinrect):twinrect;//12nov2017
function low__xyinarea(sx,sy:longint;xarea:twinrect):boolean;
function low__ptinarea(x:tpoint;xarea:twinrect):boolean;
function low__areaequal(a,b:twinrect):boolean;
function largestcur(a,b:currency):currency;//20jan2016
function csmallestex(a:array of currency):currency;//22JAN2008
function clargestex(a:array of currency):currency;//22JAN2008
function frccurmax(x,max:currency):currency;
function frcrangeex(x,min,max,defvalue:longint):longint;//14-JAN-2007
function frccurrange(x,min,max:currency):currency;//date: 02-APR-2004
function frcextmin(x,min:extended):extended;//07NOV20210
function frcextrange(x,min,max:extended):extended;//06JUN2007
function low__makepertD0(xpos,xlen:longint):double;//22nov2024, 06mar2022
function low__rateASstatus(_starttime64:currency;_totalBYTES:comp):string;
function low__rateASbytes32(_starttime64:currency;_totalBYTES:comp):longint;
function low__firstline(var _data:string):string;//08oct2018
procedure low__checkfilebadchars(xfilename:string);//soure code checker/clean code checker - 30jul2021
function low__findtext(var _pos:longint;var _data:string;_find:string):boolean;
function low__findtextL(var _pos:longint;_len:longint;var _data:string;_find:string):boolean;//22apr2014
function low__readline(var _pos,_start,_length:longint;var _data:string):boolean;
function low__readlineb(var _pos,_start,_length:longint;var _data:string;var _winrc:boolean):boolean;
function low__readlinec(var _pos,_start,_length:longint;var _data:string;_datalen:longint;var _winrc:boolean):boolean;//16may2022
function low__aswin95(const x:string):string;//31mar2021, 21-AUG-2004
function low__asname(const x:string):string;//02mar2022
procedure safeinc(var x:longint);//16jun2014
function int32RANGE(x,xmin,xmax:comp):longint;
function int32(x:comp):longint;
function strcur(x:string):currency;//v1.00.070 - 07NOV2010
function curstr(x:currency):string;//27nov2017
function extstr(x:extended):string;//17sep2018
function bn(const x:boolean):byte;
function nb(const x:byte):boolean;
function fromnullstr(const a:pointer3264;const asize:longint64):string;
function low__nullstr(const x:longint64;const y:char):string;
function low__rembinaryb(const x:string):string;//07apr2020
function strint_filtered(const x:string):longint;//removes "comma,space" automatically
function strint_filtered64(const x:string):comp;//removes "comma,space" automatically
procedure low__minwh(var a:twinrect;const aminwidth,aminheight:longint);//25feb2021
function low__cap2432(const xpos,ypos,dw,dh:longint;const d:tobject):boolean;//low version - 07mar2020, 30may2019, 21jan2015, 17-JAN-2007
function low__cap2432b(const d:tobject):boolean;
function low__cap2432c(xpos,ypos,dw,dh:longint;const d:tobject):boolean;//17nov2024: xpos/ypos range checking dropped for multi-monitor support, low version - 09sep2021, 07mar2020, 30may2019, 21jan2015, 17-JAN-2007
function low__capcolor(const xpos,ypos:longint;const xfromcursor:boolean):longint;//09sep2025
function low__capcolor2(xpos,ypos:longint;const xfromcursor:boolean;const xfromGUIbuffer:tbasiccontrol;const xforceGUIbuffer:boolean):longint;//09sep2025
function low__firstnbl(xdata,xoutdata:tstr8):boolean;//first non-blank line
function low__firstnbl2(const xtext:string):string;


//.platform support ------------------------------------------------------------
function low__plat(xcmd,xprgname:string;xrunaction:boolean):string;
function low__platroot:string;
function low__platfolder(xname:string):string;
function low__platfolder2(xname:string;xcreate:boolean):string;//10feb2023
function low__platsyssettings:string;//system settings
function low__platprgsettings:string;//prorgam settings - 05oct2020
function low__platimages:string;//images folder - 12feb2022
function low__plattemp:string;//tep folder - 19feb2022
function low__platonce:string;
function low__platactive:string;
function low__platsysext(xext:string):string;//29aug2021
function low__platprgext(xext:string):string;//29aug2021
function low__platDLLname(xname:string):string;//26sep2021


//.system timer support --------------------------------------------------------
//uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//ttttttttttttttttttttttttttt
function low__timerfound(xowner:tobject;x:tnotifyevent):boolean;
function low__timerset(xowner:tobject;x:tnotifyevent;xdelay:comp):boolean;//auto create/maintain a timer
function low__timerdelay(xowner:tobject;x:tnotifyevent;xnewdelay:comp):boolean;//set new delay of existing timer (if deleted, it won't be auto-created) - 19feb2021
function low__timerfinddelay(xowner:tobject;x:tnotifyevent;var xdelay:comp):boolean;
function low__timerdel(xowner:tobject;x:tnotifyevent):boolean;//delete timer


//.misc support ----------------------------------------------------------------
function low__setbc(var xdata:tbasiccontrol;xnewvalue:tbasiccontrol):boolean;//15mar2021
function low__vifontscale(xwidth:longint):longint;//use to scale width of columns and height of other items according to current "vifontheight" setting based on a default value of "16"
function low__t(x:boolean):longint;
function low__maplist(const x:array of byte):tlistptr;
function low__maplist2(x:tstr8):tlistptr;//07apr2021
function low__compareint(x,xval:longint):boolean;
function low__strASarray__debugonly(xdata:string):string;
function low__trimdec(x:string):string;//01aug2021
function low__instouch(xval,xtouchval:longint):longint;//06may2020
function low__instouch2(xval,xtouchval:longint;xallowtouch:boolean):longint;//06may2020


//clipboard procs --------------------------------------------------------------
//.text
function clip__hasformat(xformat:uint32):boolean;
function clip__cancopytext:boolean;//20mar2021
function clip__copytext(const xdata:string):boolean;//26apr2025
function clip__copytext2(xdata:pobject):boolean;//01jun2025, 26apr2025

function clip__canpastetext:boolean;//16mar2021
function clip__pastetext(var xdata:string):boolean;//01sep2025, 27apr2025
function clip__pastetextb:string;//27apr2025
function clip__pastetext2(xdata:pobject):boolean;//27apr2025

//.image
function clip__cancopyimage:boolean;//12apr2021
function clip__copyimage(s:tobject):boolean;//10jun2025, 09jun2025, 26apr2025

function clip__copyimageAsArrayByte(const s:tobject;const dformat:string;const dShowSuccess:boolean):boolean;//18mar2026
function clip__copyimageAsBase64(const s:tobject;dformat:string;const dShowSuccess:boolean):boolean;//18mar2026

function clip__canpasteimage(const xenhancedformats:boolean):boolean;//18mar2026, 29apr2025
function clip__pasteimage(const d:tobject;const xenhancedformats:boolean):boolean;//18mar2026, 12jun2025, 08jun2025, 01jun2025, 29apr2025

function clip__canpasteimagefrom(const xaltsource:tobject;const xenhancedformats:boolean):boolean;//12apr2021
function clip__pasteimagefrom(const d:tobject;const xaltsource:tobject;const xenhancedformats,xfit:boolean):boolean;//17mar2025, 12apr2021
function clip__pasteimagefrom2(const d:tobject;const xaltsource:tobject;const xenhancedformats,xfit:boolean;xfitmaxW,xfitmaxH:longint):boolean;//29apr2025, 17mar2025, 14apr2021, 12apr2021

//.wordcore
function clip__copymulti(xformat:array of word;xdata:array of pobject):boolean;
function clip__pasteformat(xformat:word;xout:pobject):boolean;//27apr2025

//.support
function clip__opened(var xopened:boolean):boolean;//01sep2025
function clip__openedAndclear(var xopened:boolean):boolean;//01sep2025


//error messages
function gec__taskfailed(var e:string):boolean;//pass-thru support


//history support --------------------------------------------------------------
function his__found(xname:string):boolean;
function his__find(xname:string;var xindex:longint):boolean;
function his__clear(xname:string):boolean;
//.prev
function his__canprev(xname:string):boolean;
function his__prev(xname:string;var xoutval:string;xmove:boolean):boolean;
function his__prev2(xname:string;var xoutval:string;var v1,v2:longint;xmove:boolean):boolean;
//.next
function his__cannext(xname:string):boolean;
function his__next(xname:string;var xoutval:string;xmove:boolean):boolean;
function his__next2(xname:string;var xoutval:string;var v1,v2:longint;xmove:boolean):boolean;
//.active
function his__active(xname:string;var xoutval:string):boolean;
function his__active2(xname:string;var xoutval:string;var v1,v2:longint):boolean;
function his__setactiveref(xname:string;v1,v2:longint):boolean;//sets ref of active item
//.add
function his__add(xname,xval:string):boolean;
function his__add2(xname,xval:string;v1,v2:longint;xstorev12:boolean):boolean;


//draw support -----------------------------------------------------------------
function gui__newrgn(x,y,x2,y2:longint32;const xrounded:boolean):hrgn;//26mar2026, 01aug2024, 31aug2016
procedure gui__delrgn(var x:hrgn);


//system object checkers -------------------------------------------------------
function sbwpok(x:tobject):boolean;
function sbwp(x:tobject):tbasicbwp;

//.transparent color support (multiple colors supported) - 28jan2021
function mistransNEXT(var xindex:longint;var xoutlabel:string;xstart:boolean):boolean;
function mistransNEXT2(var xindex,xoutindex:longint;var xoutlabel:string;var xoutcustomok:boolean;xcustom:string;xstart:boolean):boolean;
function mistransLABEL(stranscolORstyle:longint;xcustom:string):string;
function mistransCUSTOM(stranscolORstyle:longint):boolean;
function mistransISOK(a,b:longint):boolean;
function misreduce82432(s:tobject;stranscol,slessdata:longint;var e:string):boolean;

//.menu support -> normal sequence: init() + title()/item()/sep() + end()
procedure low__menuinit(const x:tstr8);
function low__menutitle(const x:tstr8;const xtep:longint;const xcaption,xhelp:string):boolean;
function low__menuitem(const x:tstr8;const xtep:longint;const xcaption,xhelp,xcode2:string;const xcode:longint;const xenabled:boolean):boolean;
function low__menuitem2(const x:tstr8;const xtep:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut:longint;const xenabled:boolean):boolean;
function low__menuitem2b(const x:tstr8;const xtep:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut:longint;const xenabled:boolean;const xindentLevel:longint):boolean;//07jun2021
function low__menuitem3(const x:tstr8;const xtep:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut:longint;const xflash,xenabled:boolean):boolean;
function low__menuitem4(const x:tstr8;const xtep:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut,xindent:longint;const xflash,xenabled:boolean):boolean;
//..custom tep color support
function low__menutitlex(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp:string):boolean;
function low__menuitemx(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp,xcode2:string;const xcode:longint;const xenabled:boolean):boolean;
function low__menuitemx2(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut:longint;const xenabled:boolean):boolean;
function low__menuitemx3(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut:longint;const xflash,xenabled:boolean):boolean;
function low__menuitemx4(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut,xindent:longint;const xflash,xenabled:boolean):boolean;
//..continue
function low__menusep(const x:tstr8):boolean;
function low__menuend(const x:tstr8):boolean;
function low__menucount(const x:tstr8):longint;//number of items in menu
function low__menuget(const x:tstr8;const xindex:longint;var xtep,xtepcolor:longint;var xcaption,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep:boolean):boolean;
function low__menuadd(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut,xindent:longint;const xflash,xenabled,xtitle,xsep:boolean):boolean;
function low__menufindbycode2(const x:tstr8;const xfindval:string;var xindex:longint):boolean;
function low__menucode2(const x:tstr8;const xindex:longint):string;


//file support -----------------------------------------------------------------
function low__nn(x:string):boolean;//14apr2021
function low__dk(x:string):boolean;//14apr2021
procedure low__reloadfastvars;
function low__makerelative(xfilename,xauthoritiveFilenameORfolder:string):string;//20mar2022
function low__readrelative(xfilename,xauthoritiveFilenameORfolder:string):string;//fixed 31may2022, 20mar2022

//system support ---------------------------------------------------------------
//.talk indirectly to all active "tbasicsystem" controls
procedure system_paintallnowSLOW;
procedure system_paintallnow;
procedure system_paintnow;
procedure system_alignallnow;
procedure system_alignnow;
procedure system_sizenow;
//.debug support
procedure pop_junk(x:string);
function pop_error(x:string):boolean;//10feb2023
function pop_query(x:string):boolean;//05feb2023
function pop_query2(x,xcancelcap,xokcap:string):boolean;//11feb2023
function pop_info(xtitle,x:string):boolean;//05feb2023
function pop_msg(xtitle,x:string):boolean;//23jul2024
function pop_txt2(var x:string;xwrap:longint;xreadonly:boolean;xcap,xhelp:string):boolean;
function pop_save(var xfilename:string;xfilterlist,xcommonfolder:string;var daction:string):boolean;
function pop_save2(var xfilename:string;xfilterlist,xcommonfolder,xtitle2:string;var daction:string):boolean;
function pop_find(xhandler:longint;var xtext,xcmd:string):boolean;
procedure showa(x:longint);
procedure showa1;
procedure showa2;
procedure showa3;
procedure showa4;
procedure showa5;
procedure showa6;
procedure showa7;
procedure showa8;
procedure showa9;
procedure showb1;
procedure showb2;
procedure showb3;
procedure showb4;
procedure showc1;
procedure showc2;
procedure showc3;
procedure showc4;
procedure showerror8(e:tstr8);//04sep2025, 19aug2020
procedure dbRGBA(x:longint);//26jun2021
procedure dbtext(yrow:longint;xtext:string);//21nov2024
procedure dbimage(s:tobject;szoom:longint;susealpha:boolean);//strictly debug purposes only - 21dec2021, 07jun2021 -> misshow/low__show/imageshow
procedure dbimage1(s:tobject;szoom:longint;susealpha:boolean;smsg:string);
procedure dbimage1b(s:tobject;szoom:longint;susealpha:boolean;smsg:string;sshowcolor:longint);//21nov2024: updated to handle sshowcolor properly, 18nov2024, 05aug2024
procedure dbimage2(s,s2:tobject;szoom:longint);//strictly debug purposes only
procedure dbimage3(s,s2:tobject;szoom:longint;xcap:string);//strictly debug purposes only - 30dec2022
procedure dbstatus(p:longint;x:string);//16may2025
procedure dbstart;
procedure dbstop;
function dbtime:string;
function dbtimeave:string;
function dbtimeavefast:string;
procedure dbshow(xlabel:string);//show label + dbtime
procedure dbstopshow(xlabel:string);//show label + dbtime


//-- ease of use tstr8 system handlers -----------------------------------------
function bif(const s,d:tstr8):boolean;
function bifnot(const s,d:tstr8):boolean;
function blen(const x:tstr8):longint64;
function blen32(const x:tstr8):longint32;
function bsetlen(const x:tstr8;const xlen:longint64):boolean;
function bchar(const xval:longint32):tstr8;
function bstr(const x:tstr8):string;
function bcheck(const x:tstr8;const xpos:longint64):boolean;//05may2021
function bcheck2(const x:tstr8;const xpos:longint64;const xdebugid:longint32):boolean;//05may2021
//access system values by name - 07sep2020
function sfromname(n:string):string;
function ifromname(const n:string):longint;
function bfromname(const n:string):boolean;


//color list support - 09mar2021 -----------------------------------------------
//Note: direct and rapid access to all colors in color list
function low__colorsarray(xdata:string;const xfullset:boolean):string;//20jul2024: option xfullset added
function low__fixcolors(xdata:string):string;//fixes any errors by filtering out bad data
function low__validcolor(const xindex:longint;var xdefcol:longint):boolean;
function low__criticalcolor(const xindex:longint):boolean;//22jul2021
function low__getcolor(const xdata:string;const xindex:longint;var xcolor:longint):boolean;
function low__getcolor2(const xdata:string;const xindex:longint;var xcolor:longint):boolean;
function low__setcolor(const xdata:string;const xindex,xcolor:longint):string;//outputs entire color stream
function low__setcolorb(const xdata:string;const xindex,xcolor:longint;const xadjBrightness100:longint):string;//outputs entire color stream
function low__setcolor2(const xdata:string;const xindex,xcolor:longint):string;//outputs entire color stream
function low__setcolor3(const xdata:string;const xindex:longint;xcolor:longint;const xadjBrightness100:longint):string;//18sep2022 outputs entire color stream
function low__getcolors(const xnormal,xtitle:pvirtualinfo;const xmorecolors:pvirtualmorecolors):string;
procedure low__setcolors(const xdata:string;const xnormal,xtitle:pvirtualinfo;const xmorecolors:pvirtualmorecolors);
function low__setcolorsbyname(xname:string;const xnormal,xtitle:pvirtualinfo;const xmorecolors:pvirtualmorecolors):boolean;
function low__findbuiltincolor(const n:string;const xexpand:boolean;var xadjBrightness100:longint):string;
function low__tocompactcolors(const xdata:string):string;
function low__fromcompactcolors(const xdata:string;var xout:string):boolean;
function low__fromcompactcolors2(xdata:string;const xadjBrightness100:longint;var xout:string):boolean;
function low__coloradjBrightness(x:byte;const xadjBrightness100:longint):byte;


//external support -------------------------------------------------------------
function low__clienttoscreen(x:tobject;s:tpoint):tpoint;


//PLUS support -----------------------------------------------------------------
//date   : 27jun2022
//version: 1.00.050
function plus_index:longint;
function plus_indexb(var x:longint):boolean;//pass-thru
function plus_index2(x:tobject;xrangecheck:boolean):longint;
procedure plus_setindex(x:tobject;xindex:longint);
function plus_pagename(xpageindex:longint):string;
function plus_stamppagename(x:tobject;xpageindex:longint):boolean;//pass-thru - use to set a controls "opagename" to a value of "scPlus0..7"
function plus_scpagecode(xpageindex:longint):string;//for adding "scPage" control codes to toolbars -> tells toolbar button to SHOW a particular set of controls with then "opagename=scPlusN" where N is "0..7" - 27jun2022
function plus_toolbar(x:tobject;var y:tbasictoolbar):boolean;
function plus_toolbar2(x:tobject;var y:tbasictoolbar):boolean;
procedure plus_bhighlight(x:tobject);
procedure plus_bhighlight2(x:tobject);
procedure plus_addlinks(x:tobject;xtep:longint;xmaincap,xhelp:string;xnewline,xmorepadding:boolean);
procedure plus_addlinks2(x:tobject;xtep:longint;xmaincap,xhelp:string;xnewline,xmorepadding:boolean);


//system support ---------------------------------------------------------------
function form__position(h:hauto;dx,dy,dw,dh:longint):boolean;
function form__move(h:hauto;dx,dy,dw,dh:longint;xrepaint:boolean):boolean;//09sep2025
procedure system__setontop(x:boolean);
function system__include(x:tbasicsystem):boolean;
function system__exclude(x:tbasicsystem):boolean;
procedure system__sync;
function system__findbyformhandle(h:hauto;var x:tbasicsystem):boolean;
function system__windowproc(h:hauto;m:msg_message;w:msg_wparam;l:msg_lparam):msg_result; stdcall;


//scale support ----------------------------------------------------------------

//.scale calculations for "viscale" setting
function scale__adjustment(const xscale:double;const xscalemode:longint):double;//11dec2025
function scale__calculate:double;//17dec2025, 10dec2025
function scale__modeNormal:longint;
function scale__modecount:longint;
function scale__modelabel(const xscalemode:longint):string;//10dec2025
function scale__modehelp(const xscalemode:longint):string;//17dec2025, 10dec2025

//.pixel adjusters
function scale__px20(const xsubscale,xval:double):longint;//rounds down - 10dec2025
function scale__px21(const xsubscale,xval:double;const xmin:longint):longint;//rounds down - 10dec2025
function scale__px22(const xsubscale,xval:double;const xmin,xmax:longint):longint;//rounds down - 10dec2025

function scale__px0(const xval:double):longint;//rounds down - 10dec2025
function scale__px1(const xval:double;const xmin:longint):longint;//rounds down - 10dec2025
function scale__px2(const xval:double;const xmin,xmax:longint):longint;//rounds down - 10dec2025


//.font scaling countering
function scale__fontRatioCorrection:double;
function scale__counterScaling(const xvalue:longint):longint;


//app support ------------------------------------------------------------------
function gui__dpi:longint;//10dec2025
procedure gui__zoom(var aw,ah:longint);//10dec2025
procedure gui__scale(var aw,ah:longint);//10dec2025
procedure gui__scale2(const sw,sh:longint;var dw,dh:longint);//11dec2025
procedure gui__scale3(const sw,sh,dminw,dminh:longint;var dw,dh:longint);//11dec2025
procedure gui__scale4(const smultipler:double;const sw,sh,dminw,dminh:longint;var dw,dh:longint);//11dec2025
procedure gui__smallfont(const xinfo:tvirtualinfo;var xfontindex,xfontheight:longint);
procedure gui__smallfont2(const xinfo:tvirtualinfo;const xscaleThreshold:double;var xfontindex,xfontheight:longint);

procedure gui__timers;

//.dynamic cursor
procedure app__loadcursor(xforce:boolean);
function app__cursorcolorinfo(xname:string;var s,d:longint):boolean;
procedure app__loadcursorinfo(var xname,xfilename:string);
procedure app__savecursor(xname:string;xhost:tbasicsystem);//09mar2025, 24jan2025
procedure app__cursorSoftsaveandload;

//.screen cursor
procedure app__reloadcursorifsizehaschanged;
function app__cursor:longint;
procedure app__setcursor(x:longint);

procedure app__cursorReapply;
function app__cursorhandle:longint;
function app__gui:tbasicsystem;
function app__guiactive:tbasicsystem;
function app__guihandle:hauto;
function app__guiactivehandle:hauto;
function app__cursorsize:longint;

//.realtime support - 25mar2022
function app__realtimeOK:boolean;
procedure app__realtime;
procedure app__realtimeSYNC;//internally called by system procs - 19apr2022


implementation

uses main, gossteps, gossnet;


//start-stop procs -------------------------------------------------------------
procedure gossgui__start;
var
   p:longint;
   cmp1:comp;
   a,b:hrgn;
   ar,br:twinrect;
begin
try

//check
if system_started_gui then exit else system_started_gui:=true;
gui__running:=true;

//debug init
system_debugPaintcount:=0;
system_debugPainttime:=slowms64;
for p:=0 to high(system_debugrows) do system_debugrows[p]:='';

//.needed support - these can be disabled - 31may2022, 24may2022
need_ico;
need_gif;

//system id -> unique for each running copy of program - 16jan2025, 19feb2022
system_instanceidREF:=tobject.create;
system_instanceid:=longint(system_instanceidREF);//use address of object for a unique number for each copy of app

//form list
for p:=0 to high(system_list) do system_list[p]:=nil;

//cursor list
try
system_cursorlist[0]:=0;//hidden => no cursor
for p:=1 to high(system_cursorlist) do system_cursorlist[p]:=win____LoadCursor(0,idc_arrow);
system_cursor:=scArrow;
system_cursorREF:=0;
except;end;

//system_plus0-N - 27jun2022
for p:=0 to programplusmax do
begin
system_plus0[p]:=nil;
system_plus1[p]:=nil;
system_plus2[p]:=nil;
system_plus3[p]:=nil;
system_plus4[p]:=nil;
system_plus5[p]:=nil;
system_plus6[p]:=nil;
system_plus7[p]:=nil;
system_plus8[p]:=nil;
system_plus9[p]:=nil;
end;//p

//colors
sicolors;

//frames
siframes;

//round corner patching under Windows - 01aug2024
try
a:=win____createroundrectrgn(1,1,10,10,viCornerA,viCornerB);
b:=win____createrectrgn(1,1,10,10);
track__inc(satRegion,2);//18dec2024
win____getrgnbox(a,ar);
win____getrgnbox(b,br);
gui__delrgn(a);
gui__delrgn(b);
system_patchcornerw:=(ar.right-ar.left)<>(br.right-br.left);
system_patchcornerh:=(ar.bottom-ar.top)<>(br.bottom-br.top);
except;end;


//system timer - 19feb2021
cmp1:=slowms64;
for p:=0 to high(systimer_event) do
begin
systimer_owner[p]  :=nil;
systimer_event[p]  :=nil;
systimer_busy[p]   :=false;
systimer_delay[p]  :=0;//off
systimer_ref64[p]  :=cmp1;
end;//p

//syshis_nam - 21mar2021
for p:=0 to high(syshis_nam) do syshis_nam[p]:='';


//init system vars

//system storage handlers ------------------------------------------------------
usrdata:=str__new8;
sysmore:=vnew;

//.program code checker - use code "-1745" to disable - 27sep2022, 28aug2021
xcodecheck;

//.viMaster - FALSE=means code is not connected to a folder - all settings strictly in RAM - e.g. a EXE Document
if (sysmore.len>=1) or (blen(usrdata)>=1) then viMaster:=false;

//WINE Support - 02feb2022 -----------------------------------------------------
system_winepresent:=io__driveexists('z:\');


//system settings handlers -----------------------------------------------------
syssettings:=vnew2(953);
prgsettings:=vnew2(954);

//special clipboard formats ----------------------------------------------------
try

cf_html            :=win____registerclipboardformat('HTML Format');//16feb2026 - supported by all browsers

cf_rtf__RTFasText  :=win____registerclipboardformat('RTF As Text');//16feb2026
cf_rtf             :=win____registerclipboardformat('Rich Text Format');//16feb2026

cf_png             :=win____registerclipboardformat('PNG');//08aug2025
cf_bwd             :=win____registerclipboardformat('Blaiz Writer Document');
cf_bwp             :=win____registerclipboardformat('Blaiz Word Processor Document');

except;end;

//string support ---------------------------------------------------------------
//translated strings
tsBytes:=ntranslate('bytes');
tsB:=strup(translate('b'));//single byte - 24feb2016
tsKB:=strup(translate('kb'));
tsMB:=strup(translate('mb'));
tsGB:=strup(translate('gb'));

//sysarrays --------------------------------------------------------------------
//.system menu
for p:=0 to high(sysmenu_name) do
begin

sysmenu_name[p]        :='';
sysmenu_pos[p]         :=0;
sysmenu_hover[p]       :=-1;
sysmenu_selstart[p]    :=0;
sysmenu_selcount[p]    :=0;
sysmenu_ref64[p]       :=0;

end;//p


//system fast vars - 06apr2021
low__reloadfastvars;

//fill "sysback_" structure ready for loadsyssettings and tbackgroundmanager - 08mar2025
sysback__init;

//system settings
siLoadsyssettings;
siLoadprgsettings;

master__cursor;
except;end;
end;

procedure gossgui__stop;
begin
try

//check
if not system_started_gui then exit else system_started_gui:=false;

//Assumed to be safe to shutdown at this point, since "siClosing" will trigger ALL instances of "tbasicsystem" and the like to cancel menus etc OR wait till dialogs are done
//        before calling this proc "siHalt;" - 03apr2021

//main timer -> disable main timer so no new procs are fired etc - 03apr2021
systimer_enabled:=false;


//disconnect vital events
visyncevent:=nil;
//was: fasttimer__stop;//07oct2021


//system helpers ---------------------------------------------------------------
//was: if zzok(programhelpviewer,1040) then freeobj(@programhelpviewer);


//system hubs ------------------------------------------------------------------
//mm_shut;//29mar2021


//system settings handlers -----------------------------------------------------
siSavesyssettings;
siSaveprgsettings;


//master support cleanup -------------------------------------------------------
master__cursorCLEAN;//15nov2023


//system storage handlers ------------------------------------------------------
str__free(@usrdata);
freeobj(@sysmore);


//system settings handlers #2 --------------------------------------------------
freeobj(@viframecode);//23feb2022
freeobj(@syssettings);//12dec2025
freeobj(@prgsettings);//12dec2025


//last -------------------------------------------------------------------------
freeobj(@system_instanceidREF);

except;end;

//terminate
gui__running:=false;

end;


//info procs -------------------------------------------------------------------
function app__info(xname:string):string;
begin
result:=info__rootfind(xname);
end;

function info__gui(xname:string):string;//information specific to this unit of code
begin
//defaults
result:='';

try
//init
xname:=strlow(xname);

//check -> xname must be "gossgui.*"
if (strcopy1(xname,1,8)='gossgui.') then strdel1(xname,1,8) else exit;

//get
if      (xname='ver')        then result:='4.00.33310'
else if (xname='date')       then result:='23apr2026'
else if (xname='name')       then result:='GUI'
else
   begin
   //nil
   end;

except;end;
end;


//-- App Support - 30sep2021 ---------------------------------------------------
//xxxxxxxxxxxxxxxxxxxxxxxxxxx//111111111111111111
procedure app__cursorSoftsaveandload;
var
   s,d:longint;
begin
app__cursorcolorinfo(system_cursorname,s,d);
if (strcopy1(system_cursorname,1,1)='!') and ((system_cursorcolor1<>s) or (system_cursorcolor2<>d)) then app__savecursor(system_cursorname,nil);
app__loadcursor(false);
end;

function app__cursorcolorinfo(xname:string;var s,d:longint):boolean;
      procedure xset(sr,sg,sb,dr,dg,db:longint);
      begin
      result:=true;
      s:=rgba0__int(sr,sg,sb);
      d:=rgba0__int(dr,dg,db);
      end;

      procedure xset0(dr,dg,db:longint);
      begin
      result:=true;
      d:=rgba0__int(dr,dg,db);
      s:=int__dif24(d,-100);
      s:=int__makevis24(s,d,60);
      end;

      procedure xset1(x:longint);
      var
         a:tcolor32;
      begin
      a:=inta__c32(x,255);
      xset0(a.r,a.g,a.b);
      end;
begin
//defaults
result:=false;

//init
xname:=strlow(xname);

//get
if      (xname='white')    then xset(0,0,0,255,255,255)
else if (xname='black')    then xset(255,255,255,0,0,0)
else if (xname='red')      then xset0(255,20,20)
else if (xname='pink')     then xset0(255,162,232)
else if (xname='orange')   then xset0(255,105,55)
else if (xname='aqua')     then xset0(156,255,255)
else if (xname='yellow')   then xset0(255,234,13)
else if (xname='purple')   then xset0(242,40,255)
else if (xname='blue')     then xset0(150,211,255)
else if (xname='green')    then xset0(154,255,122)
else if (xname='grey')     then xset0(191,190,186)
else if (xname='!title')   then xset1(vititle.background)
else if (xname='!hover')   then xset1(vinormal.hover);
end;

procedure app__savecursor(xname:string;xhost:tbasicsystem);//09mar2025, 24jan2025
var//Note: Saves data to disk, but for new cursor to take affect a call must be made to app__loadcursor() - 24jan2024
   n,sname,df,e:string;
   a:tstr8;
   b:tbasicimage;
   ss,dd,int1,int2,int3:longint;

   procedure xusea;
   begin
   try
   if (a=nil) then a:=str__new8;
   a.clear;
   except;end;
   end;

   procedure xdefcursor;
   var
      e:string;
   begin
   xname:='default';
   io__tofilestr(low__platsysext('cur.inf'),xname,e);
   end;

   procedure xsavecursor;
   var
      a:tstr8;
      s:tbasicimage;
      e,df:string;
      v,sw,sh,sx,sy:longint;
      sc,dc,c32:tcolor32;
      sr32:pcolorrow32;
   begin
   try
   //defaults
   a:=nil;
   s:=nil;

   //init
   a:=str__new8;
   s:=misimg32(1,1);
   df:=low__platsysext('cur');
   sc:=inta__c32(ss,255);
   dc:=inta__c32(dd,255);

   //load cursor template => red=transparent color, black=cursor outline, white=cursor inner area
   if system_osWin9X then a.aadd(cur_template_arrow32)//for Windows 95/98 which handles max 64x64 cursor but without alpha support
   else                   a.aadd(cur_template_arrow128);

   if (io__anyformatb(@a)='ZIP') then low__decompress(@a);//25jan2025

   //from image
   mis__fromdata(s,@a,e);

   //color the cursor
   if misok32(s,sw,sh) then
      begin
      for sy:=0 to (sh-1) do
      begin
      if not misscan32(s,sy,sr32) then break;

      for sx:=0 to (sw-1) do
      begin
      c32:=sr32[sx];

      //.red = transparent background
      if (c32.r>c32.g) and (c32.r>c32.b) then
         begin
         v:=255-c32.r;
         c32.a:=v;
         c32.r:=( (v*sc.r) + ((255-v)*(0)) ) div 256;
         c32.g:=( (v*sc.g) + ((255-v)*(0)) ) div 256;
         c32.b:=( (v*sc.b) + ((255-v)*(0)) ) div 256;
         end
      else
         begin
         v:=c32.r;
         if (c32.g>v) then v:=c32.g;
         if (c32.b>v) then v:=c32.b;

         c32.r:=( (v*dc.r) + ((255-v)*(sc.r)) ) div 256;
         c32.g:=( (v*dc.g) + ((255-v)*(sc.g)) ) div 256;
         c32.b:=( (v*dc.b) + ((255-v)*(sc.b)) ) div 256;

         //if (v<=0) then c32.a:=120 else
         c32.a:=255;
         end;

      sr32[sx]:=c32;
      end;//dx
      end;//dy
      end;

   //save as cursor + auto hotspot
   cur32__todata(s,@a);//27may2025

   io__tofile(df,@a,e);
   io__tofilestr(low__platsysext('cur.inf'),xname,e);
   except;end;
   try
   str__free(@a);
   freeobj(@s);
   except;end;
   end;
begin
try
//init
xname:=strlow(xname);
sname:=xname;
df:=low__platsysext('cur');
a:=nil;
b:=nil;

//get
if      (xname='default')                           then xdefcursor
else if app__cursorcolorinfo(xname,ss,dd)           then xsavecursor
else if (xname='custom') or (xname='custom.prompt') then
   begin
   xname:='custom';

   //prompt for custom cursor file
   if (sname='custom.prompt') and (xhost<>nil) and xhost.popopencur(sysfile_cursor,sysfile_cursor_openfilter,'',true) then
      begin
      n:=io__readfileext_low(sysfile_cursor);

      //.png
      if (n='png') then
         begin
         xusea;
         b:=misimg32(1,1);
         if mis__fromfile(b,sysfile_cursor,e) then
            begin
            low__toico32(b,true,false,0,32,-1,-1,int1,int2,int3,a,e);
            io__tofile(low__platprgext('cur'),@a,e);
            end;
         end
      //.gif
      else if (n='gif') or (n='san') or (n='pic8') or (n='tea') or (n='img32') then//16sep2025
         begin
         xusea;
         b:=misimg32(1,1);
         b.ai.use32:=true;
         if mis__fromfile(b,sysfile_cursor,e) then
            begin
            if b.ai.transparent then mask__feather(b,b,0,mispixel24VAL(b,0,0),int1);
            low__toani32(b,nil,'ani',false,0,b.ai.delay,-1,-1,true,a,e);
            io__tofile(low__platprgext('cur'),@a,e);
            end;
         end
      //.cur + ani
      else io__copyfile(sysfile_cursor,low__platprgext('cur'),e);
      end;

   //inform system we are using the custom cursor
   io__tofilestr(low__platsysext('cur.inf'),xname,e);

   //load cursor - 09mar2025
   app__loadcursor(true);
   end
else xdefcursor;

//vars
if (system_cursor=scArrow) then system_cursorchanged:=true;
except;end;
try
str__free(@a);
freeobj(@b);
except;end;
end;

procedure app__loadcursorinfo(var xname,xfilename:string);
var
   s,d:longint;
   e:string;
begin
try
//get name from disk
if not io__fromfilestr(low__platsysext('cur.inf'),xname,e) then xname:='default';

//decide
xname:=strlow(xname);

if (xname='default') or (xname='custom') or app__cursorcolorinfo(xname,s,d) then
   begin
   //ok
   end
else xname:='default';

//filename
if      (xname='default')    then xfilename:=''
else if (xname='custom')     then xfilename:=low__platprgext('cur') //program cursor
else                              xfilename:=low__platsysext('cur');//system cursor
except;end;
end;

procedure app__loadcursor(xforce:boolean);
var
   xname,xfilename:string;
   s,d,xsize:longint;
begin
try
//load info
app__loadcursorinfo(xname,xfilename);
app__cursorcolorinfo(xname,s,d);

//get
xsize:=strint32(reg__readval(0,'Control Panel\Cursors\CursorBaseSize',true));

if (xname<>system_cursorname) or ((strcopy1(xname,1,1)='!') and ((system_cursorcolor1<>s) or (system_cursorcolor2<>d)) ) or (system_cursorsize<>xsize) or xforce then
   begin
   system_cursorname:=xname;
   system_cursorcolor1:=s;
   system_cursorcolor2:=d;
   system_cursorsize:=xsize;
   system_cursorref64:=slowms64+10000;//10s
   xforce:=true;
   end;

//set
if xforce then
   begin
   if (xfilename<>'') then system_cursorlist[scArrow]:=win____loadcursorfromfile(pchar(xfilename));
   if (xfilename='') or (system_cursorlist[scArrow]=0) then system_cursorlist[scArrow]:=win____loadcursor(0,IDC_ARROW);
   end;

//sync
if (system_cursor=scArrow) and (xforce or system_cursorchanged) then
   begin
   system_cursorchanged:=true;
   app__setcursor(system_cursor);
   end;
except;end;
end;

procedure app__reloadcursorifsizehaschanged;
begin
if (not strmatch(system_cursorname,'default')) and (system_cursorsize<>strint32(reg__readval(0,'Control Panel\Cursors\CursorBaseSize',true))) then app__loadcursor(false);
end;

function app__cursor:longint;
begin
result:=system_cursor;
end;

procedure app__setcursor(x:longint);
begin
x:=frcrange32(x,0,high(system_cursorlist));
if (x<>system_cursor) or (system_cursorlist[x]<>system_cursorREF) or system_cursorchanged then
   begin
   //catch any invalid cursors and replace with system arrow
   if (x>scNone) and (system_cursorlist[x]=0) then system_cursorlist[x]:=win____loadcursor(0,idc_arrow);
   system_cursor:=x;
   system_cursorREF:=system_cursorlist[x];
   system_cursorchanged:=false;
   app__cursorReapply;
   end;
end;

procedure app__cursorReapply;
begin
win____setcursor(system_cursorlist[system_cursor]);
end;

function app__cursorhandle:longint;
begin
result:=system_cursorlist[system_cursor];
end;

function app__gui:tbasicsystem;
begin
result:=system_guifirst;
end;

function app__guiactive:tbasicsystem;
begin
result:=system_guiactive;
end;

function app__guihandle:hauto;
begin
if (system_guifirst<>nil) then result:=system_guifirst.handle else result:=0;
end;

function app__guiactivehandle:hauto;
begin
if (system_guiactive<>nil) then result:=system_guiactive.handle else result:=0;
end;

function app__cursorsize:longint;
begin
result:=system_cursorsize;
end;

function gui__dpi:longint;
begin

case (app__gui<>nil) of
true:result:=app__gui.dpi;
else result:=96;
end;//case

end;

procedure gui__zoom(var aw,ah:longint);//for teps etc - 10dec2025
begin

aw:=aw*vizoom;
ah:=ah*vizoom;

end;

procedure gui__smallfont(const xinfo:tvirtualinfo;var xfontindex,xfontheight:longint);
begin
gui__smallfont2(xinfo,1.0,xfontindex,xfontheight);
end;

procedure gui__smallfont2(const xinfo:tvirtualinfo;const xscaleThreshold:double;var xfontindex,xfontheight:longint);
begin

//use smaller font2 for scaling < 100%
case (viscale>=xscaleThreshold) of
true:begin

   xfontindex  :=xinfo.fs;
   xfontheight :=xinfo.fsH;

   end;
else begin

   xfontindex  :=xinfo.fs2;
   xfontheight :=xinfo.fsH2;

   end;
end;//case

end;

procedure gui__scale(var aw,ah:longint);//10dec2025
begin

gui__scale4(1.0,aw,ah,1,1,aw,ah);

end;

procedure gui__scale2(const sw,sh:longint;var dw,dh:longint);//11dec2025
begin

gui__scale4(1.0,sw,sh,1,1,dw,dh);

end;

procedure gui__scale3(const sw,sh,dminw,dminh:longint;var dw,dh:longint);//11dec2025
begin

gui__scale4(1.0,sw,sh,dminw,dminh,dw,dh);

end;

procedure gui__scale4(const smultipler:double;const sw,sh,dminw,dminh:longint;var dw,dh:longint);//11dec2025
begin

//(1) major adjustment based scaling and
//(2) minor adjustment based on font size (more width than height)

dw:=scale__px1( (smultipler*sw) + (smultipler*0.50*sw*frcminD64(vifontwidthratio-1,0)) ,dminw );
dh:=scale__px1( (smultipler*sh) + (smultipler*0.10*sh*frcminD64(vifontwidthratio-1,0)) ,dminh );

if (app__gui<>nil) then
   begin

   dw:=frcmax32( dw, app__gui.width  );
   dh:=frcmax32( dh, app__gui.height );

   end;

end;

procedure gui__timers;
var
   tmp64,d64,v64:comp;
   p:longint;
begin
try

//shutdown - thread safe - 30sep2021
if gui__closing and (not sicloseviapostDONE) and (low__closecount<=0) then
   begin

   sicloseviapostDONE   :=true;//do only once - 30sep2021
   systimer_enabled     :=false;
   gui__running         :=false;//stop the message loop - 17nov2023

   //was: postmessage(app__handle,wm_quit,0,0);//thread friendly shutdown signal - 26may2021
   //was:win____postmessage(0,wm_quit,0,0);//thread friendly shutdown signal -> post to the app thread - 16jan2025, 26may2021
   exit;

   end;


//check
if (not systimer_enabled) or (not gui__running) then exit;


//normal timers ----------------------------------------------------------------
v64            :=fastms64;//16ms accuracy

//.normal timers
if (v64>=systimer64) then
   begin

   //sync realtime - 25mar2022
   app__realtimeSYNC;

   //lag
   if (systimerLAGref<>0) then
      begin

      tmp64:=sub64(v64,systimerLAGref);
      if (tmp64>systimerlastLAG) then systimerlastLAG:=tmp64;

      end;

    systimerLAGref:=v64;

   //tick counter
   systimerlasttick:=systimerlasttick+1;

   if (v64>=systimer1000) then
      begin

      systimer1000      :=v64+1000;
      systimerTICK      :=systimerlasttick;
      systimerlasttick  :=0;
      systimerLAG       :=systimerlastlag;//07oct2021
      systimerlastlag   :=0;

      end;

   //speed + events
   d64:=100;

   for p:=0 to high(systimer_event) do if assigned(systimer_event[p]) then
      begin

      //smallest system delay
      if (systimer_delay[p]>=1) and (systimer_delay[p]<d64) then d64:=systimer_delay[p];

      //fire timer event
      if (systimer_delay[p]>=1) and (v64>=systimer_ref64[p]) and (not systimer_busy[p]) then
         begin

         //Critical Note: This is the only pointer other than within "gossgui__start" that a timer's busy state is modified -> all other timer procs work around it - 19feb2021
         systimer_busy[p]   :=true;//lock the timer
         systimer_ref64[p]  :=v64+systimer_delay[p];

         //.fire timer event
         try;systimer_event[p](nil);except;end;

         systimer_busy[p]   :=false;//unlock the timer (even if it has been deleted)

         end;

      end;//p

   //.min delay for normal timers is 30ms
   d64:=div64(d64,2);//divide smallest delay in half for a better, rounder delay
   if (d64<30) then d64:=30;

   //.turbo mode is on
   if app__turboOK then d64:=1;

   //.finalise speed
   systimer64:=v64+d64;

   end;//p

//.reload CURSOR whenever we are NOT running the default system cursor -> Changes to the size of the Windows cursor causes damaging distortion to a ready loaded and active cursor, thus ANY custom based cursor MUST be reloaded to allow for windows to resample the cursor at the new system dimensions - 28may2022
if (slowms64>=system_cursorref64) then
   begin

   app__reloadcursorifsizehaschanged;
   system_cursorref64:=slowms64+10000;//10s

   end;

except;end;
end;

function gui__newrgn(x,y,x2,y2:longint32;const xrounded:boolean):hrgn;//01aug2024, 31aug2016
begin//Stable now for Linux and Windows (Note: Linux is 100% correct)

//defaults
result      :=nullregion;

//check -> invalid/empty space range check -> nothing to do - fixed - 31aug2016
if (x2<x) or (y2<y) then exit;

try

//get
case xrounded of
true:begin

   //Windows patch check -> Windows is out by 1w x 1h pixels on createroundrectrgn, adjust value to compensate:
   if system_patchcornerw then inc(x2);
   if system_patchcornerh then inc(y2);

   //get
   result   :=win____createroundrectrgn( x ,y ,x2 ,y2 ,viCornerA*viscale32 ,viCornerB*viscale32 );

   end;
else begin

   result   :=win____createrectrgn(x,y,x2,y2);

   end;
end;//case

//stats
if (result<>nullregion) then track__inc(satRegion,1);

except;end;
end;

procedure gui__delrgn(var x:hrgn);
begin
try

if (x<>nullregion) then
   begin

   //get
   win____deleteobject(x);
   x        :=nullregion;

   //stats
   track__inc(satRegion,-1);

   end;

except;end;
end;


//realtime process (program) support -------------------------------------------
function app__realtimeOK:boolean;
begin
result:=(system_realtime64>=slowms64);
end;

procedure app__realtime;
var
   bol1:boolean;
begin
//get
bol1:=app__realtimeOK;
system_realtime64:=slowms64+5000;//turn on realtime for 5s
//sync immediately
if not bol1 then
   begin
   system_realtime642:=0;
   app__realtimeSYNC;
   end;
end;

procedure app__realtimeSYNC;//internally called by system procs - 19apr2022
label//Special Note: Realtime mode can only be achivied when program is "Run as Administrator" - 19apr2022
   skipend;
var
   sv,dv:dword32;
   st,dt:longint;
begin
try
//check
if system_realtimeSYNCING then exit else system_realtimeSYNCING:=true;
if (system_realtime642>slowms64) then goto skipend else system_realtime642:=slowms64+5000;
//get
sv:=win____getpriorityclass(win____getcurrentprocess);
st:=win____getthreadpriority(win____getcurrentprocess);

if app__realtimeOK then
   begin
   dv:=REALTIME_PRIORITY_CLASS;//process
   dt:=THREAD_PRIORITY_TIME_CRITICAL;//thread
   end
else
   begin
   dv:=NORMAL_PRIORITY_CLASS;
   dt:=THREAD_PRIORITY_NORMAL;
   end;

//set
if (sv<>dv) or (st<>dt) then
   begin
   win____setpriorityclass(win____getcurrentprocess,dv);
   win____setthreadpriority(win____getcurrentprocess,dt);
   end;
skipend:
except;end;
try;system_realtimeSYNCING:=false;except;end;
end;


//-- cursor support ------------------------------------------------------------
function low__clienttoscreen(x:tobject;s:tpoint):tpoint;
begin
try
result:=s;
//was: if (x is tcommonform) then win____clienttoscreen((x as tcommonform).handle,result);
if (x<>nil) and (x is tbasicsystem) then win____clienttoscreen((x as tbasicsystem).handle,result);
except;end;
end;


//-- system background support -------------------------------------------------
procedure sysback__init;//17apr2026, 19aug2025, 08mar2025
var
   xlimit,p:longint;
   xcanwrite:boolean;

   function xscreenHeight:longint;
   begin
   result:=monitors__screenheight_auto;
   end;

   function xscreenWidth:longint;
   begin
   result:=monitors__screenwidth_auto;
   end;

   procedure xnew2(const xname:string;const xiscustom:boolean;const xfromfile,xmakename:string;const xfromarray:array of byte);
   begin

   if (sysback_count<xlimit) and xcanwrite then
      begin

      if (xname<>'') then
         begin

         //clear
         sysback__clear(sysback_count);

         //get
         sysback_name[sysback_count]          :=xname;
         sysback_iscustom[sysback_count]      :=xiscustom;
         sysback_datafromfile[sysback_count]  :=xfromfile;
         sysback_makename[sysback_count]      :=xmakename;
         sysback_datafromptr[sysback_count]   :=low__maplist(xfromarray);
         inc(sysback_count);

         end;

      end
   else xcanwrite:=false;//stop writing

   end;

   procedure xnew(const xname:string;const xiscustom:boolean;const xfromfile:string;const xfromarray:array of byte);
   begin

   xnew2(xname,xiscustom,xfromfile,'',xfromarray);

   end;

   procedure s(xnameid,xindex,xval:longint;xcanchange:boolean);
   begin

   if not xcanwrite then exit;

   sysback__setval2(xnameid,xindex,xval,true);

   //.store defaults
   case xnameid of
   bkmStrength  :sysback_strengthDEF[xindex]  :=sysback_strength[xindex];
   bkmColorise  :sysback_coloriseDEF[xindex]  :=sysback_colorise[xindex];
   bkmSpeed     :sysback_speedDEF[xindex]     :=sysback_speed[xindex];
   bkmHstep     :sysback_hstepDEF[xindex]     :=sysback_hstep[xindex];
   bkmVstep     :sysback_vstepDEF[xindex]     :=sysback_vstep[xindex];
   bkmFstep     :sysback_fstepDEF[xindex]     :=sysback_fstep[xindex];
   bkmHwobble   :sysback_hwobbleDEF[xindex]   :=sysback_hwobble[xindex];
   bkmVwobble   :sysback_vwobbleDEF[xindex]   :=sysback_vwobble[xindex];
   bkmFwobble   :sysback_fwobbleDEF[xindex]   :=sysback_fwobble[xindex];
   bkmCrate     :sysback_crateDEF[xindex]     :=sysback_crate[xindex];
   end;//case


   if xcanchange then
      begin
      case xnameid of
      bkmStrength  :sysback_canstrength[xindex]  :=xcanchange;
      bkmColorise  :sysback_cancolorise[xindex]  :=xcanchange;
      bkmSpeed     :sysback_canspeed[xindex]     :=xcanchange;
      bkmHstep     :sysback_canhstep[xindex]     :=xcanchange;
      bkmVstep     :sysback_canvstep[xindex]     :=xcanchange;
      bkmFstep     :sysback_canfstep[xindex]     :=xcanchange;
      bkmHwobble   :sysback_canhwobble[xindex]   :=xcanchange;
      bkmVwobble   :sysback_canvwobble[xindex]   :=xcanchange;
      bkmFwobble   :sysback_canfwobble[xindex]   :=xcanchange;
      bkmCrate     :sysback_cancrate[xindex]     :=xcanchange;
      end;//case

      sysback_canadjust[xindex]                  :=true;
      end;

   end;

   procedure s0(xnameid,xval:longint);//set value and but disable any user alterations
   begin
   s(xnameid,sysback_count-1,xval,false);
   end;

   procedure s1(xnameid,xval:longint);//set value and enable
   begin
   s(xnameid,sysback_count-1,xval,true);
   end;

   procedure sall;
   begin

   s1(bkmStrength,0);
   s1(bkmColorise,0);
   s1(bkmSpeed,0);
   s1(bkmHstep,0);
   s1(bkmVstep,0);
   s1(bkmFstep,0);
   s1(bkmHwobble,0);
   s1(bkmVwobble,0);
   s1(bkmFwobble,0);
   s1(bkmCrate,0);//17apr2026

   end;

   procedure xnewfull(const xname:string;const xfromarray:array of byte);
   begin

   xnew(xname,false,'',xfromarray);
   sall;
   s1(bkmStrength,55);
   s0(bkmColorise,-100);
   s1(bkmSpeed,frcmax32(20,background_speed_limit));//07jan2026, 30dec2025
   s1(bkmVstep,1);
   s1(bkmHstep,1);

   end;

   procedure pnew(const xname,xmakename:string);
   begin

   xnew2(xname,false,'',xmakename+';',back_none);

   end;

   procedure pGradient(const xname:string;const r,g,b:byte);
   var//w=width, h=height, k=background color(0..N, -1=transparent, -2=not used), a-d=color1..4, s=splice100(0..100), p=power255(0..255),
      hratio,hratio2:double;
      dcol,p:longint;
      v:string;
   begin

   dcol     :=rgba0__int(r,g,b);

   for p:=0 to 3 do
   begin

   case p of

   0:begin

      v               :=' (Static)';
      hratio          :=1.0;
      hratio2         :=1.0;

      end;

   1:begin

      v:=' (Fade)';
      hratio          :=1.0;
      hratio2         :=1.0;

      end;

   2:begin

      v:=' (Scrolling)';
      hratio          :=1.5;
      hratio2         :=1.0;

      end;

   3:begin

      v:=' (Scrolling-Narrow)';
      hratio          :=1.5;
      hratio2         :=0.5;

      end;

   else
      begin

      v:='';
      hratio:=1.0;

      end;

   end;//case

   pnew('Gradient'+insstr(#32,xname<>'')+xname+v,'!gradient;w2;h'+intstr32(round32(xscreenHeight*hratio))+';j'+intstr32(round32(xscreenHeight*hratio2))+';k0;a0;b'+intstr32(dcol)+';c'+intstr32(dcol)+';d0;p255;s50');//full gradient does not required a background color "k-2"

   //.remake tile when screen changes
   if (sysback_count<xlimit) then
      begin

      sysback_remakeonScreen[sysback_count-1] :=true;

      end;

   s1(bkmStrength,60);

   case (r=255) and (g=255) and (b=255) of
   true:s0(bkmColorise,-100);//system
   else s0(bkmColorise,100);//color
   end;//case

   //.speed
   case p of
   1..3:s1(bkmSpeed,18);
   end;

   //.fstep
   case p of
   1..3:s1(bkmFstep,2);
   end;

   //.vstep
   case p of
   2..3:s1(bkmVstep,5);
   end;

   end;//p

   end;

   procedure pVLine(const xname:string;const r,g,b:byte);
   var//w=width, h=height, k=background color(0..N, -1=transparent, -2=not used), a-d=color1..4, s=splice100(0..100), p=power255(0..255),
      dcol,p:longint;
      v:string;
   begin

   dcol     :=rgba0__int(r,g,b);

   for p:=1 to 2 do
   begin

   case p of
   2    :v:=' (Strobe)';
   else  v:='';
   end;//case

   pnew('Gradient-Line'+insstr(#32,xname<>'')+xname+v,'!v-line;w'+intstr32(xscreenWidth)+';h2;k-1;a'+intstr32(int__splice24(0.35,0,dcol))+';b'+intstr32(dcol)+';c'+intstr32(dcol)+';d'+intstr32(int__splice24(0.35,0,dcol))+';p255;s50');//full gradient does not required a background color "k-1"

   //.remake tile when "viscale" changes
   if (sysback_count<xlimit) then
      begin

      sysback_remakeonScreen[sysback_count-1] :=true;
      sysback_remakeonScale[sysback_count-1]  :=true;

      end;

   case p of
   1:s1(bkmStrength,40);//no strobe
   2:s1(bkmStrength,45);//with strobe
   end;//case

   case (r=255) and (g=255) and (b=255) of
   true:s0(bkmColorise,-100);//system
   else s0(bkmColorise,100);//color
   end;//case

   //.speed
   case p of
   1..2:s1(bkmSpeed,18);
   end;

   //.fstep
   case p of
   2..2:s1(bkmFstep,6);
   end;

   //.hstep
   case p of
   1..2:s1(bkmHstep,3);
   end;

   end;//p

   end;

   procedure pMake(const xtype:longint32;const xname:string;const r,g,b:byte);
   begin

   case xtype of
   0:pGradient(xname,r,g,b);
   1:pVLine(xname,r,g,b);
   end;//case

   end;

   function pRandomColor(const xtype:longint):boolean;
   var
      vlabel:string;
   begin

   //init
   result:=(xtype>=0) and (xtype<=3);
   if not result then exit;

   //0=random color
   //1=random color + strobe
   //2=random color + system
   //3=random color + system/strobe

   case xtype of
   1   :vlabel:=' (Fade)';
   2   :vlabel:=' (System)';
   3   :vlabel:=' (System-Fade)';
   else vlabel:='';
   end;//case

   pnew('Random Color'+vlabel,'!random-color;w10;h10;k-1;');

   //.remake always
   if (sysback_count<xlimit) then
      begin

      sysback_remakeonScreen[sysback_count-1] :=true;
      sysback_remakeonCrate[sysback_count-1]  :=true;

      end;

   s1(bkmStrength,40);

   case xtype of
   2..3:s0(bkmColorise,-100);
   else s0(bkmColorise,100);
   end;//case

   s1(bkmSpeed,5);
   s1(bkmCrate,2);

   case xtype of
   1,3:s1(bkmFstep,10);
   end;//case

   end;

begin
//check
if (sysback_count<>0) then exit;

//init
xlimit    :=high(sysback_name);
xcanwrite :=true;

//built-in
xnew('Default',false,'',back_none);
xnew('None',false,'',back_none);

//.fuzz
xnewfull('Fuzz',back_fuzz);

xnew('Fuzz 2',false,'',back_fuzz);
s1(bkmStrength,18);
s0(bkmColorise,-100);

xnew('Fuzz 3',false,'',back_fuzz);
s1(bkmStrength,18);
s0(bkmColorise,100);

//.plaster
xnewfull('Plaster',back_plaster);

xnew('Plaster 2',false,'',back_plaster);
s1(bkmStrength,18);
s0(bkmColorise,-100);

xnew('Plaster 3',false,'',back_plaster);
s1(bkmStrength,18);
s0(bkmColorise,100);

//.stone
xnewfull('Stone',back_stone);

xnew('Stone 2',false,'',back_stone);//17apr2026
s1(bkmStrength,18);
s0(bkmColorise,-100);

xnew('Stone 3',false,'',back_stone);
s1(bkmStrength,18);
s0(bkmColorise,100);

//.balls
xnewfull('Balls',back_balls);

xnew('Balls 2',false,'',back_balls);
sall;
s1(bkmStrength,100);
s1(bkmColorise,-100);
s1(bkmSpeed,20);
s1(bkmHstep,7);
s1(bkmVstep,-3);
s1(bkmFstep,8);
s1(bkmVwobble,8);


//.make in realtime ------------------------------------------------------------

//.simple random color
for p:=0 to max32 do if not pRandomColor(p) then break;

//.gradient based
for p:=0 to 1 do
begin

pMake(p,'Pink',255,0,128);
pMake(p,'Red',255,0,0);
pMake(p,'Green',0,255,0);
pMake(p,'Blue',0,0,255);
pMake(p,'Yellow',255,255,0);
pMake(p,'Orange',255,128,0);
pMake(p,'Purple',128,0,255);
pMake(p,'System',255,255,255);

end;//p


//.pitted ----------------------------------------------------------------------
xnewfull('Pitted',back_pitted);

xnew('Pitted 2',false,'',back_pitted);
s1(bkmStrength,10);
s0(bkmColorise,-100);

xnew('Pitted 3',false,'',back_pitted);
s1(bkmStrength,10);
s0(bkmColorise,100);

xnew('Pitted 4',false,'',back_pitted);
s0(bkmStrength,25);

//.vain
xnewfull('Vain',back_vain);

xnew('Vain 2',false,'',back_vain);
s1(bkmStrength,17);
s0(bkmColorise,-100);

xnew('Vain 3',false,'',back_vain);
s1(bkmStrength,17);
s0(bkmColorise,100);

//.clouds
xnew('Clouds',false,'',back_clouds);
sall;
s1(bkmStrength,50);
s1(bkmColorise,100);
s1(bkmSpeed,20);
s1(bkmHstep,-5);
s1(bkmVstep,-2);

xnew('Clouds 2',false,'',back_clouds);
sall;
s1(bkmStrength,50);
s1(bkmColorise,-100);
s1(bkmSpeed,20);
s1(bkmHstep,3);
s1(bkmVstep,1);

//.ivy
xnewfull('Ivy',back_ivy);

xnew('Ivy 2',false,'',back_ivy);
s1(bkmStrength,20);
s0(bkmColorise,-100);

xnew('Ivy 3',false,'',back_ivy);
s1(bkmStrength,20);
s0(bkmColorise,100);

//.swell
xnewfull('Swell',back_swell);

xnew('Swell 2',false,'',back_swell);
s1(bkmStrength,20);
s0(bkmColorise,-100);

xnew('Swell 3',false,'',back_swell);
s1(bkmStrength,20);
s0(bkmColorise,100);

//.metal
xnewfull('Metal',back_metal);

xnew('Metal 2',false,'',back_metal);
s1(bkmStrength,20);
s0(bkmColorise,-100);

xnew('Metal 3',false,'',back_metal);
s1(bkmStrength,20);
s0(bkmColorise,100);

//custom
for p:=1 to 10 do
begin
xnew('Custom '+intstr32(p),true,'background'+intstr32(p)+'.'+feimg32,back_none);
s1(bkmStrength,50);
s1(bkmColorise,100);
s1(bkmSpeed,0);
s1(bkmHstep,0);
s1(bkmVstep,0);
s1(bkmFstep,0);
s1(bkmHwobble,0);
s1(bkmVwobble,0);
s1(bkmFwobble,0);
s1(bkmCrate,0);
end;//p

end;

function sysback__maketileFromName(const d:tobject;const sv:string):boolean;
label
   skipend;
var
   da:twinrect;
   b:tbasicimage;
   r:tresslot;
   xPreviousSlot:pfastdraw;
   lp,slen,p,xbits,xw,xh:longint;
   pn,n,v:string;
   v32,dw,dh,dh2,dbackcol,dcol1,dcol2,dcol3,dcol4,dpower255,dsplice100:longint;
   xbackFilled:boolean;

   function m(const xname:string):boolean;
   begin

   result:=strmatch(n,xname);

   end;

   function r100_255:longint;
   begin

   result:=frcrange32(100+random(156),0,255);

   end;

begin

//defaults
result                :=false;
r                     :=res_nil;
xPreviousSlot         :=nil;
b                     :=nil;

//check
if not misok82432(d,xbits,xw,xh) then exit;
if (sv='')                       then exit;

//init
pn          :='';//proc name
dw          :=1920;
dh          :=1080;
dh2         :=0;//not set
dbackcol    :=0;
dcol1       :=0;
dcol2       :=255;
dcol3       :=255;
dcol4       :=0;
dpower255   :=255;
dsplice100  :=50;
slen        :=low__len32(sv);
lp          :=1;
xbackFilled :=false;

//read values
for p:=1 to slen do if (sv[p-1+stroffset]=';') then
   begin

   //get
   v        :=strcopy1(sv,lp,p-lp);
   if (v<>'') then
      begin

      //get
      n     :=strcopy1(v,1,1);
      v     :=strcopy1(v,2,low__len32(v));
      v32   :=strint32(v);

      //set
      if      m('!') then pn           :=v
      else if m('w') then dw           :=v32
      else if m('h') then dh           :=v32
      else if m('j') then dh2          :=v32//height 2
      else if m('k') then dbackcol     :=v32
      else if m('a') then dcol1        :=v32
      else if m('b') then dcol2        :=v32
      else if m('c') then dcol3        :=v32
      else if m('d') then dcol4        :=v32
      else if m('p') then dpower255    :=v32
      else if m('s') then dsplice100   :=v32;

      end;

   //inc
   lp       :=p+1;

   end;

//check -> must have a proc name
if (pn='') then exit;


try


//range check ------------------------------------------------------------------

if (dh2<=0) then dh2:=dh;


//init -------------------------------------------------------------------------

fd__selStore(xPreviousSlot);
r           :=fd__new;//new + defaults
fd__select(r);

//size
if not missize( d ,dw ,dh ) then goto skipend;

da          :=misarea( d );

fd__setbuffer( fd_buffer ,d );

//background color
if (dbackcol>=0) then
   begin

   xbackFilled        :=true;
   fast__fillArea(da,da,dbackcol);

   end
else if (dbackcol=-1) then//transparent
   begin

   xbackFilled        :=true;
   mis__cls(d,0,0,0,0);

   end;


//make -------------------------------------------------------------------------

if (pn='gradient') then
   begin

   //cls unused area
   if (dh2<dh) and (not xbackFilled) then mis__cls(d,0,0,0,0);

   //draw
   da       :=area__make(da.left,0,da.right,frcmin32(dh2-1,0));
   fast__shadeArea3(da,da,dcol1,dcol2,dcol3,dcol4,dsplice100,dpower255,0,0,false);

   end
else if (pn='v-line') then
   begin

   //create line horizontally and then rotate and draw onto main image
   b        :=misimg24(dh,round32(100*viscale));
   fd__setbuffer( fd_buffer ,b );

   fast__shadeArea3(misarea(b),misarea(b),dcol1,dcol2,dcol3,dcol4,dsplice100,dpower255,0,0,false);

   //roate
   mis__rotate82432(b,-90);

   //draw
   fd__setbuffer( fd_buffer  ,d );
   fd__setbuffer( fd_buffer2 ,b );

   fd__setarea( fd_area  ,misarea(b));
   fd__setarea( fd_area2 ,misarea(b));

   fd__render( fd_drawRGB );

   end
else if (pn='random-color') then
   begin

   fast__fillArea(da,da,rgba0__int( r100_255 ,r100_255 ,r100_255 ) );

   end
else goto skipend;

//successful
result:=true;
skipend:

except;end;

//finalise
mis__nocells(d);//required

//previous slot
if (xPreviousSlot<>nil) then fd__selRestore(xPreviousSlot);

//free
res__del(r);
freeobj(@b);

end;

procedure sysback__clear(xindex:longint);
begin
if (xindex>=0) and (xindex<=high(sysback_name)) then
   begin
   sysback_name          [xindex]:='';
   sysback_datafromptr   [xindex].count:=0;
   sysback_datafromptr   [xindex].bytes:=nil;
   sysback_datafromfile  [xindex]:='';
   sysback_makename      [xindex]:='';

   sysback_remakeonScale [xindex]:=false;//02mar2026
   sysback_remakeonCrate [xindex]:=false;//02mar2026

   sysback_iscustom      [xindex]:=false;
   sysback_canadjust     [xindex]:=false;

   sysback_canstrength   [xindex]:=false;
   sysback_strength      [xindex]:=0;
   sysback_cancolorise   [xindex]:=false;
   sysback_colorise      [xindex]:=0;
   sysback_canspeed      [xindex]:=false;
   sysback_speed         [xindex]:=0;
   sysback_canhstep      [xindex]:=false;
   sysback_hstep         [xindex]:=0;
   sysback_canvstep      [xindex]:=false;
   sysback_vstep         [xindex]:=0;
   sysback_canfstep      [xindex]:=false;
   sysback_fstep         [xindex]:=0;
   sysback_canhwobble    [xindex]:=false;
   sysback_hwobble       [xindex]:=0;
   sysback_canvwobble    [xindex]:=false;
   sysback_vwobble       [xindex]:=0;
   sysback_canfwobble    [xindex]:=false;
   sysback_fwobble       [xindex]:=0;
   sysback_cancrate      [xindex]:=false;
   sysback_crate         [xindex]:=0;

   //.default values
   sysback_strengthDEF   [xindex]:=0;
   sysback_coloriseDEF   [xindex]:=0;
   sysback_speedDEF      [xindex]:=0;
   sysback_hstepDEF      [xindex]:=0;
   sysback_vstepDEF      [xindex]:=0;
   sysback_fstepDEF      [xindex]:=0;
   sysback_hwobbleDEF    [xindex]:=0;
   sysback_vwobbleDEF    [xindex]:=0;
   sysback_fwobbleDEF    [xindex]:=0;
   sysback_crateDEF      [xindex]:=0;

   end;

end;

function sysback__findnameid(xnameid_asstr:string;var xnameid:longint):boolean;
   function n(x:string):boolean;
   begin
   result:=strmatch(xnameid_asstr,x);
   end;

   procedure s(x:longint);
   begin
   xnameid:=x;
   result:=true;
   end;
begin
if      n('strength')    then s(bkmStrength)
else if n('colorise')    then s(bkmColorise)
else if n('speed')       then s(bkmSpeed)
else if n('hstep')       then s(bkmHstep)
else if n('vstep')       then s(bkmVstep)
else if n('fstep')       then s(bkmFstep)
else if n('hwobble')     then s(bkmHwobble)
else if n('vwobble')     then s(bkmVwobble)
else if n('fwobble')     then s(bkmFwobble)
else if n('crate')       then s(bkmCrate)
else                           result:=false;
end;

function sysback__findbyname(xname:string;var xindex:longint):boolean;
var
   p:longint;
begin

//defaults
result      :=false;
xindex      :=0;

//special
if strmatch(xname,'default') then xname:=app__info('back.name');

//find
if (sysback_count>=1) and (xname<>'') then
   begin

   for p:=1 to sysback_count do if strmatch(sysback_name[p],xname) then
      begin

      xindex:=p;
      result:=true;
      break;

      end;

   end;

end;

procedure sysback__loadfrom(x:tvars8;xforce:boolean);
var
   p:longint;
begin

if (sysback_count>=1) and (x<>nil) then
   begin

   for p:=0 to (sysback_count-1) do if xforce or x.found('sysback.'+sysback_name[p]) then sysback__readvals(p,x,xforce);

   end;

end;

procedure sysback__saveto(x:tvars8);
var
   p:longint;
begin

if (sysback_count>=1) and (x<>nil) then
   begin

   for p:=0 to (sysback_count-1) do sysback__writevals(p,x);

   end;

end;

procedure sysback__writevals(xindex:longint;v:tvars8);
var
   z:string;

   procedure iadd(xvalname:string;xcanchange:boolean;xval:longint);
   begin

   if xcanchange and (xvalname<>'') then z:=z+xvalname+':'+intstr32(xval)+';';

   end;

begin

if sysback__usedindex(xindex) and (v<>nil) then
   begin

   //init
   z:='';

   //get
   iadd('strength'    ,sysback_canstrength[xindex]   ,sysback_strength[xindex]);
   iadd('colorise'    ,sysback_cancolorise[xindex]   ,sysback_colorise[xindex]);
   iadd('speed'       ,sysback_canspeed[xindex]      ,sysback_speed[xindex]);
   iadd('hstep'       ,sysback_canhstep[xindex]      ,sysback_hstep[xindex]);
   iadd('vstep'       ,sysback_canvstep[xindex]      ,sysback_vstep[xindex]);
   iadd('fstep'       ,sysback_canfstep[xindex]      ,sysback_fstep[xindex]);
   iadd('hwobble'     ,sysback_canhwobble[xindex]    ,sysback_hwobble[xindex]);
   iadd('vwobble'     ,sysback_canvwobble[xindex]    ,sysback_vwobble[xindex]);
   iadd('fwobble'     ,sysback_canfwobble[xindex]    ,sysback_fwobble[xindex]);
   iadd('crate'       ,sysback_cancrate[xindex]      ,sysback_crate[xindex]);

   //set
   if (z<>'') then v.s['sysback.'+sysback_name[xindex]]:=z;

   end;

end;

function sysback__readvals(xindex:longint;v:tvars8;xforce:boolean):boolean;
var
   xnameid,zlen,lp,p:longint;
   n,vv,z:string;
begin

//defaults
result      :=false;

//get
if sysback__usedindex(xindex) and (v<>nil) then
   begin

   //get
   z        :=v.s['sysback.'+sysback_name[xindex]];
   zlen     :=low__len32(z);

   //clear -> restore defaults
   if xforce then
      begin

      sysback_strength[xindex]  :=sysback_strengthDEF[xindex];
      sysback_colorise[xindex]  :=sysback_coloriseDEF[xindex];
      sysback_speed[xindex]     :=sysback_speedDEF[xindex];
      sysback_hstep[xindex]     :=sysback_hstepDEF[xindex];
      sysback_vstep[xindex]     :=sysback_vstepDEF[xindex];
      sysback_fstep[xindex]     :=sysback_fstepDEF[xindex];
      sysback_hwobble[xindex]   :=sysback_hwobbleDEF[xindex];
      sysback_vwobble[xindex]   :=sysback_vwobbleDEF[xindex];
      sysback_fwobble[xindex]   :=sysback_fwobbleDEF[xindex];
      sysback_crate[xindex]     :=sysback_crateDEF[xindex];

      end;

   //set
   if (zlen>=3) then
      begin

      lp    :=1;

      for p:=1 to zlen do if (z[p-1+stroffset]=';') then
         begin

         //get
         low__splitstr(strcopy1(z,lp,p-lp),ssColon,n,vv);

         lp :=p+1;
         n  :=strlow(n);

         //decide
         if      (n='strength')    then xnameid:=bkmStrength
         else if (n='colorise')    then xnameid:=bkmColorise
         else if (n='speed')       then xnameid:=bkmSpeed
         else if (n='hstep')       then xnameid:=bkmHstep
         else if (n='vstep')       then xnameid:=bkmVstep
         else if (n='fstep')       then xnameid:=bkmFstep
         else if (n='hwobble')     then xnameid:=bkmHwobble
         else if (n='vwobble')     then xnameid:=bkmVwobble
         else if (n='fwobble')     then xnameid:=bkmFwobble
         else if (n='crate')       then xnameid:=bkmCrate
         else                      xnameid:=-1;

         //set
         if (xnameid>=0) and sysback__setval2(xnameid,xindex,strint32(vv),false) then result:=true;

         end;//p

      end;

   end;

end;

function sysback__usedindex(xindex:longint):boolean;
begin

result:=(xindex>=0) and (xindex<sysback_count);

end;

function sysback__enforcerange(xnameid,xval:longint):longint;//enforce range

  procedure r(xmin,xmax:longint);
  begin

  result:=frcrange32(xval,xmin,xmax);

  end;

begin

case xnameid of
bkmStrength  :r(0,220);//was: 255 -> too strong for an upper limit - 01mar2025
bkmColorise  :r(-100,100);
bkmSpeed     :r(0,background_speed_limit);//07jan2026, 30dec2025
bkmHstep     :r(-200,200);//02mar2026
bkmVstep     :r(-200,200);//02mar2026
bkmFstep     :r(0,50);
bkmHwobble   :r(0,300);
bkmVwobble   :r(0,300);
bkmFwobble   :r(0,200);
bkmCrate     :r(0,100);//change rate -> 0-100% of current speed
else          r(0,0);
end;//case

end;

function sysback__setval2(xnameid,xindex,xval:longint;xforce:boolean):boolean;

   procedure s(xbol:boolean;var xint:longint);
   begin

   result:=(xbol or xforce) and low__setint(xint,sysback__enforcerange(xnameid,xval));

   end;

begin

if sysback__usedindex(xindex) then
   begin

   case xnameid of
   bkmStrength  :s(sysback_canstrength[xindex] ,sysback_strength[xindex]);
   bkmColorise  :s(sysback_cancolorise[xindex] ,sysback_colorise[xindex]);
   bkmSpeed     :s(sysback_canspeed[xindex]    ,sysback_speed[xindex]);
   bkmHstep     :s(sysback_canhstep[xindex]    ,sysback_hstep[xindex]);
   bkmVstep     :s(sysback_canvstep[xindex]    ,sysback_vstep[xindex]);
   bkmFstep     :s(sysback_canfstep[xindex]    ,sysback_fstep[xindex]);
   bkmHwobble   :s(sysback_canhwobble[xindex]  ,sysback_hwobble[xindex]);
   bkmVwobble   :s(sysback_canvwobble[xindex]  ,sysback_vwobble[xindex]);
   bkmFwobble   :s(sysback_canfwobble[xindex]  ,sysback_fwobble[xindex]);
   bkmCrate     :s(sysback_cancrate[xindex]    ,sysback_crate[xindex]);
   else          result:=false;
   end;//case

   end
else result:=false;

end;

function sysback__getval(xnameid,xindex:longint):longint;
var
   bol1:boolean;
begin

sysback__getval2(xnameid,xindex,bol1,result);

end;

function sysback__getval2(xnameid,xindex:longint;var xcanchange:boolean;var xval:longint):boolean;
var
   xdef:longint;
begin

result:=sysback__getval3(xnameid,xindex,xcanchange,xval,xdef);

end;

function sysback__getval3(xnameid,xindex:longint;var xcanchange:boolean;var xval,xdef:longint):boolean;

   procedure s(xbol:boolean;xint,xintDEF:longint);
   begin

   xcanchange :=xbol;
   xval       :=xint;
   xdef       :=xintDEF;
   result     :=true;

   end;

   procedure xno;
   begin

   xcanchange :=false;
   xval       :=0;
   xdef       :=0;
   result     :=false;

   end;

begin

if sysback__usedindex(xindex) then
   begin

   case xnameid of
   bkmStrength  :s(sysback_canstrength[xindex]  ,sysback_strength[xindex]   ,sysback_strengthDEF[xindex]);
   bkmColorise  :s(sysback_cancolorise[xindex]  ,sysback_colorise[xindex]   ,sysback_coloriseDEF[xindex]);
   bkmSpeed     :s(sysback_canspeed[xindex]     ,sysback_speed[xindex]      ,sysback_speedDEF[xindex]);
   bkmHstep     :s(sysback_canhstep[xindex]     ,sysback_hstep[xindex]      ,sysback_hstepDEF[xindex]);
   bkmVstep     :s(sysback_canvstep[xindex]     ,sysback_vstep[xindex]      ,sysback_vstepDEF[xindex]);
   bkmFstep     :s(sysback_canfstep[xindex]     ,sysback_fstep[xindex]      ,sysback_fstepDEF[xindex]);
   bkmHwobble   :s(sysback_canhwobble[xindex]   ,sysback_hwobble[xindex]    ,sysback_hwobbleDEF[xindex]);
   bkmVwobble   :s(sysback_canvwobble[xindex]   ,sysback_vwobble[xindex]    ,sysback_vwobbleDEF[xindex]);
   bkmFwobble   :s(sysback_canfwobble[xindex]   ,sysback_fwobble[xindex]    ,sysback_fwobbleDEF[xindex]);
   bkmCrate     :s(sysback_cancrate[xindex]     ,sysback_crate[xindex]      ,sysback_crateDEF[xindex]);
   else          xno;
   end;//case

   end
else xno;

end;

function sysback__canadjust(xindex:longint):boolean;
begin

result:=sysback__usedindex(xindex) and sysback_canadjust[xindex];

end;

//-- PLUS support - 27jun2022 --------------------------------------------------
function plus_index:longint;
begin
result:=plus_index2(nil,false);
end;

function plus_indexb(var x:longint):boolean;//pass-thru
begin
result:=true;
x:=plus_index2(nil,false);
end;

function plus_index2(x:tobject;xrangecheck:boolean):longint;
begin
//defaults
result:=0;

try
//check
if (programplusmax<=0) then exit;
//range
if (x=nil) and (sysprogram<>nil) then x:=sysprogram.rootwin;
//get
if (x<>nil) and (x is tbasicscroll) and strmatch(strcopy1((x as tbasicscroll).page,1,low__len32(scplus)),scplus) then
   begin
   result:=frcrange32(strint32(strcopy1((x as tbasicscroll).page,low__len32(scplus)+1,low__len32((x as tbasicscroll).page))),0,programplusmax);
   if (result>=1) and xrangecheck and (system_plus0[result]=nil) then result:=0;
   end;
except;end;
end;

procedure plus_setindex(x:tobject;xindex:longint);
var
   a:tbasicscroll;
   n:string;
begin
try
//range
xindex:=frcrange32(xindex,0,programplusmax);
if (x=nil) and (sysprogram<>nil) then x:=sysprogram.rootwin;
//get
if (x<>nil) and (x is tbasicscroll) then
   begin
   a:=(x as tbasicscroll);
   n:=plus_pagename(xindex);
   if a.xhavetoolbar  then a.xtoolbar.setparentpage(n);//but ALSO need to sync "A's" top/bottom toolbars as these aren't synced by the search and set "toolbar.setparentpage" handler
   if a.xhavetoolbar2 then a.xtoolbar2.setparentpage(n);
   if a.xhavetoolbar3 then a.xtoolbar3.setparentpage(n);
   //Oonly needs to be done IF either of the toolbars above haven't already set it - i.e. they have no buttons that are using a "scPage+scPlus" instruction set - 28jun2022
   a.page:=n;//main page SHOW/HIDE handler
   end;
except;end;
end;

function plus_pagename(xpageindex:longint):string;
begin
result:=scplus+intstr32(frcrange32(xpageindex,0,programplusmax));
end;

function plus_stamppagename(x:tobject;xpageindex:longint):boolean;//pass-thru
begin
result:=true;if (x<>nil) and (x is tbasiccontrol) then (x as tbasiccontrol).opagename:=plus_pagename(xpageindex);
end;

function plus_scpagecode(xpageindex:longint):string;//for adding "scPage" control codes to toolbars
begin
result:=scpage+scplus+intstr32(frcrange32(xpageindex,0,programplusmax));
end;

function plus_toolbar(x:tobject;var y:tbasictoolbar):boolean;
begin
//defaults
result:=false;
y:=nil;

try
//get
if      (x<>nil) and (x is tbasictoolbar)                                                    then y:=(x as tbasictoolbar)
else if (sysprogram<>nil) and (sysprogram.rootwin<>nil) and sysprogram.rootwin.xhavetoolbar  then y:=sysprogram.rootwin.xtoolbar
else if (sysprogram<>nil) and (sysprogram.rootwin<>nil) and sysprogram.rootwin.xhavetoolbar2 then y:=sysprogram.rootwin.xtoolbar2
else if (sysprogram<>nil) and (sysprogram.rootwin<>nil) and sysprogram.rootwin.xhavetoolbar3 then y:=sysprogram.rootwin.xtoolbar3;
//set
result:=(y<>nil);
except;end;
end;

function plus_toolbar2(x:tobject;var y:tbasictoolbar):boolean;
begin
//defaults
result:=false;
y:=nil;

try
//get
if      (x<>nil) and (x is tbasictoolbar) then y:=(x as tbasictoolbar)
else if (sysprogram<>nil) and (sysprogram.rootwin<>nil) and sysprogram.rootwin.xhavetoolbar3 then y:=sysprogram.rootwin.xtoolbar3
else if (sysprogram<>nil) and (sysprogram.rootwin<>nil) and sysprogram.rootwin.xhavetoolbar2 then y:=sysprogram.rootwin.xtoolbar2
else if (sysprogram<>nil) and (sysprogram.rootwin<>nil) and sysprogram.rootwin.xhavetoolbar  then y:=sysprogram.rootwin.xtoolbar;
//set
result:=(y<>nil);
except;end;
end;

procedure plus_bhighlight(x:tobject);
var
   a:tbasictoolbar;
   v,p:longint;
begin
try;if plus_toolbar(x,a) and plus_indexb(v) then for p:=0 to programplusmax do (x as tbasictoolbar).bhighlight2[plus_scpagecode(p)]:=(p=v);except;end;
end;

procedure plus_bhighlight2(x:tobject);
var
   a:tbasictoolbar;
   v,p:longint;
begin
try;if plus_toolbar2(x,a) and plus_indexb(v) then for p:=0 to programplusmax do (x as tbasictoolbar).bhighlight2[plus_scpagecode(p)]:=(p=v);except;end;
end;

procedure plus_addlinks(x:tobject;xtep:longint;xmaincap,xhelp:string;xnewline,xmorepadding:boolean);
var
   a:tbasictoolbar;
   p:longint;
begin
try
if plus_toolbar(x,a) then
   begin
   //range
   if (xtep=tepNone) then xtep:=tepPanel20;
   //init
   xmaincap:=strdefb(xmaincap,'Panel %0%');
   xhelp:=strdefb(xhelp,'Show panel %0%');
   //get
   for p:=0 to programplusmax do a.hcsadd(low__swapvals0(xmaincap,intstr32(p+1)),xtep,0,plus_scpagecode(p),low__swapvals0(xhelp,intstr32(p+1)),-10);//malfunctions with 7 items each at -13 -> can't make it mind up if it's ONE or TWO rows - 05jul2022
   if xnewline then
      begin
      a.addhline;
      a.newline;
      end;

   if xmorepadding then a.ovpad:=6;
   end;
except;end;
end;

procedure plus_addlinks2(x:tobject;xtep:longint;xmaincap,xhelp:string;xnewline,xmorepadding:boolean);
var
   a:tbasictoolbar;
   p:longint;
begin
try
if plus_toolbar2(x,a) then
   begin
   //range
   if (xtep=tepNone) then xtep:=tepPanel20;
   //init
   xmaincap:=strdefb(xmaincap,'Panel %0%');
   xhelp:=strdefb(xhelp,'Show panel %0%');
   //get
   for p:=0 to programplusmax do a.hcsadd(low__swapvals0(xmaincap,intstr32(p+1)),xtep,0,plus_scpagecode(p),low__swapvals0(xhelp,intstr32(p+1)),0);
   if xnewline then a.newline;
   if xmorepadding then a.ovpad:=6;
   end;
except;end;
end;


//-- ease of use tstr8 system handlers -----------------------------------------
function bif(const s,d:tstr8):boolean;
begin

result:=low__true2(str__lock(@s),str__lock(@d)) and (zzstr(s,60).len=zzstr(d,61).len) and s.same(d);
str__uaf(@s);
str__uaf(@d);

end;

function bifnot(const s,d:tstr8):boolean;
begin

result:=not bif(s,d);

end;

function blen(const x:tstr8):longint64;
begin

if zzok(x,1000) then result:=x.len else result:=0;
str__af(@x);

end;

function blen32(const x:tstr8):longint32;
begin

if zzok(x,1000) then result:=x.len32 else result:=0;
str__af(@x);

end;

function bsetlen(const x:tstr8;const xlen:longint64):boolean;
begin

result:=zzok(x,1002) and x.setlen(frcmin64(xlen,0));
str__af(@x);

end;

function bchar(const xval:longint32):tstr8;
begin

result:=str__newaf8;
if (result<>nil) then result.addbyt1(byte( frcrange32(xval,0,255) ));

end;

function bstr(const x:tstr8):string;
begin

//get
try
if zzok(x,1004) and (not x.empty) then result:=x.text else result:='';
except;end;

//free
str__af(@x);

end;

function bcheck(const x:tstr8;const xpos:longint64):boolean;//05may2021
begin
result:=bcheck2(x,xpos,0);
end;

function bcheck2(const x:tstr8;const xpos:longint64;const xdebugid:longint32):boolean;//05may2021
begin

//pass-thru
result:=true;

//get
case zzok(x,8023) of
true:if (xpos<0) or (xpos>=x.datalen) then showerror('bCheck: Pos('+k64(xpos)+') out of range (0...'+k64(x.datalen-1)+')'+rcode+'Ref ID: '+k64(xdebugid));
else showerror('bCheck: Object not valid'+rcode+'Ref ID: '+k64(xdebugid));
end;

end;

//-- Access system values by name - 07sep2020 ----------------------------------
function sfromname(n:string):string;
var
   str1:string;
begin

//get
n:=strlow(n);

if        (n='colorname')      then result:=vicolorname
else if   (n='startlink')      then result:=bnc(vistartlink)
else if   (n='desktoplink')    then result:=bnc(videsktoplink)
else if   (n='startuplink')    then result:=bnc(vistartuplink)
else if   (n='startstyle')     then result:=intstr32(vistartstyle)//09dec2023
else if   (n='modern')         then result:=bolstr(vimodern)//27may2025
else if   (n='round')          then result:=bnc(viround)
else if   (n='multimonitor')   then result:=bnc(vimultimonitor)//17nov2024
else if   (n='headalign')      then result:=intstr32(viheadalign)//06jan2025
else if   (n='softclose')      then result:=bnc(visoftclose)
else if   (n='framemax')       then result:=bnc(viframemax)//04mar2022, 14mar2021
else if   (n='ecomode')        then result:=bnc(viecomode)//09may2021
else if   (n='32bit')          then result:=bnc(vi32bit)//09may2021
else if   (n='lockposition')   then result:=bnc(viLockposition)//27feb2022
else if   (n='winemode')       then result:=intstr32(viwinemode)//02feb2022
else if   (n='wine')           then result:=bnc(viwine)//02feb2022
else if   (n='safearea')       then result:=bnc(visafearea)
else if   (n='splash')         then result:=bnc(visplash)
else if   (n='help')           then result:=bnc(vihelp)
else if   (n='hint')           then result:=bnc(vihint)
else if   (n='ontop')          then result:=bnc(viontop)
else if   (n='retainpos')      then result:=bnc(viretainpos)
else if   (n='help.bw')        then result:=bnc(vihelp_bw)
else if   (n='help.show')      then result:=bnc(vihelp_show)
else if   (n='help.max')       then result:=bnc(vihelp_max)//18dec2021, 24jul2021
else if   (n='headcenter')     then result:=bnc(viheadcenter)//11oct2022
else if   (n='touch')          then result:=bnc(vitouch)
else if   (n='doubleclicks')   then result:=bnc(vidoubleclicks)
else if   (n='specialcolors')  then result:=bnc(vispecialcolors)
else if   (n='emboss')         then result:=bnc(viemboss)//19nov2023
else if   (n='sparkle')        then result:=intstr32(visparkle)//09mar2021
else if   (n='brightness')     then result:=intstr32(vibrightness)//21jul2024
else if   (n='scalemode')      then result:=intstr32(viscalemode)//10dec2025
else if   (n='safestrength')   then result:=bnc(visafestrength)
else if   (n='focusedopacity')    then result:=intstr32(vifocusedopacity)
else if   (n='unfocusedopacity')  then result:=intstr32(viunfocusedopacity)
else if   (n='opacityspeed')      then result:=intstr32(viopacityspeed)
else if   (n='bordersize')     then result:=intstr32(vibordersize__root)
else if   (n='scrollsize')     then result:=intstr32(viscrollsize__root)
else if   (n='cursorname')     then app__loadcursorinfo(result,str1)//load name only - 29aug2021
else if   (n='backname')       then result:=vibackname//21jul2024
else if   (n='framename')      then result:=viframename//23feb2022
else if   (n='fontnameraw')    then result:=vifontnameraw//26mar2022
else if   (n='fontnameraw2')   then result:=vifontnameraw2
else if   (n='fontname')       then result:=vifontname
else if   (n='fontname2')      then result:=vifontname2//for text boxes etc - 05feb2022
else if   (n='fontsize')       then result:=intstr32(vifontsize__root)//14mar2021
else if   (n='fontsize2')      then result:=intstr32(vifontsize__root2)//14mar2021
else if   (n='fontfeather')    then result:=intstr32(vifeather)

//.not found
else                                result:='';

end;

function ifromname(const n:string):longint;
begin
result:=strint32(sfromname(n));
end;

function bfromname(const n:string):boolean;
begin
result:=(ifromname(n)<>0);
end;

function low__colorsarray(xdata:string;const xfullset:boolean):string;//20jul2024: option xfullset added
var
   xcount,xlinelen,p:longint;
   xcolor:tint4;

   procedure xadd(const x:byte);
   begin

   if (result<>'') then
      begin

      result:=result+',';
      inc(xlinelen);

      end;

   result:=result+intstr32(x);

   inc(xlinelen);
   inc(xcount);

   //line limit
   if (xlinelen>=200) then
      begin

      xlinelen:=0;
      result:=result+rcode;

      end;

   end;

begin

//defaults
result    :='';

try
//init
xcount    :=0;
xlinelen  :=0;

low__fromcompactcolors(xdata,xdata);//convert "col2/col3" -> "col2" - 22jul2021
xdata     :=low__fixcolors(xdata);

//header -> "col2"
xadd(llc);
xadd(llo);
xadd(lll);
xadd(nn2);

//colors -> "index,r,g,b" all byte
for p:=0 to 255 do
begin

if (xfullset or low__criticalcolor(p)) and low__getcolor2(xdata,p,xcolor.val) then
   begin

   xadd(p);
   xadd(xcolor.r);
   xadd(xcolor.g);
   xadd(xcolor.b);

   end;

end;//p

//finish
result:=':array[0..'+intstr32(xcount-1)+'] of byte=('+result+');';

except;end;
end;

function low__fixcolors(xdata:string):string;//fixes any errors by filtering out bad data
var
   p,dlen,slen:longint;
   v:byte;

   procedure xadd;
   begin

   inc(dlen);
   if (dlen<>p) then xdata[dlen-1+stroffset]:=char(v);

   end;

begin
//defaults
result   :='';

try
//init
xdata    :=strlow(xdata);
slen     :=low__len32(xdata);
dlen     :=0;

//check
if (slen<4) then exit;

//get
for p:=1 to slen do
begin

v:=strbyte1x(xdata,p);

//header
case dlen of
0    :if (v=llc) then xadd;
1    :if (v=llo) then xadd;
2    :if (v=lll) then xadd;
3    :if (v=nn2) then xadd;
else  if (v>=nn0) and (v<=nn9) then xadd;
end;//case

end;//p

//set
if (dlen>=4) then result:=strcopy1(xdata,1,dlen);

except;end;
end;

function low__validcolor(const xindex:longint;var xdefcol:longint):boolean;
const
   xwhite=255+(255*256)+(255*256*256);
begin

case xindex of
cnFrame     :xdefcol:=15;
cnFrame2    :xdefcol:=255;
//.standard colors
cnBack1     :xdefcol:=0;
cnBorder1   :xdefcol:=21;
cnHigh1     :xdefcol:=0;
cnHover1    :xdefcol:=0;
cnText1     :xdefcol:=0;
cnTexthigh1 :xdefcol:=0;
cnTextdis1  :xdefcol:=0;
cnDis1      :xdefcol:=0;
cnDisbr1    :xdefcol:=0;
//.title colors
cnBack2     :xdefcol:=0;
cnBorder2   :xdefcol:=0;
cnHigh2     :xdefcol:=0;
cnHover2    :xdefcol:=0;
cnText2     :xdefcol:=0;
cnTexthigh2 :xdefcol:=0;
cnTextdis2  :xdefcol:=0;
cnDis2      :xdefcol:=0;
cnDisbr2    :xdefcol:=0;
//.more colors
cnsFrame    :xdefcol:=xwhite;
cnsTitle    :xdefcol:=xwhite;
cnsStandard :xdefcol:=xwhite;
cnsAllinone :xdefcol:=xwhite;
cnsDark_light  :xdefcol:=xwhite;
cnsLight_dark  :xdefcol:=xwhite;

//.other
else          xdefcol:=clnone;
end;//case

result:=(xdefcol<>clnone);

end;

function low__criticalcolor(const xindex:longint):boolean;//20may2025, 22jul2021
begin

case xindex of
cnFrame     :result:=true;
cnFrame2    :result:=true;
//.standard colors
cnBack1     :result:=true;
cnBorder1   :result:=true;
cnHigh1     :result:=true;
cnHover1    :result:=true;
cnText1     :result:=true;
cnTexthigh1 :result:=true;
cnTextdis1  :result:=true;
cnDis1      :result:=true;
cnDisbr1    :result:=true;
//.title colors
cnBack2     :result:=true;
cnBorder2   :result:=true;
cnHigh2     :result:=true;
cnHover2    :result:=true;
cnText2     :result:=true;
cnTexthigh2 :result:=true;
cnTextdis2  :result:=true;
cnDis2      :result:=true;
cnDisbr2    :result:=true;
else         result:=false;
end;//case

end;

function low__tocompactcolors(const xdata:string):string;
var//Note: Returns only the most basic colors in HEX format to keep output small to fit on Twitter - 22jul2021
   p:longint;
   int1:tint4;
begin

//defaults
result:='(col3';

//get
for p:=0 to 255 do if low__criticalcolor(p) and low__getcolor(xdata,p,int1.val) then
   begin

   int1.a:=p;//insert color index
   result:=result+int__hex8(int1.val,false);

   end;

//finalise
result:=strlow(result+')');

end;

function low__fromcompactcolors(const xdata:string;var xout:string):boolean;
begin
result:=low__fromcompactcolors2(xdata,0,xout);
end;

function low__fromcompactcolors2(xdata:string;const xadjBrightness100:longint;var xout:string):boolean;
label
   redo,skipend;
var
   int1:tint4;
   xindex,v,xpos,xlen,xdatalen,p:longint;
   xclean:string;
   xwithin:boolean;
begin

//defaults
result    :=false;

//init
xdata     :=strcopy1(xdata,1,5000);//limit inbound data to max of 5K - 22jul2021
xdatalen  :=low__len32(xdata);
xout      :=low__getcolors(@vinormal,@vititle,@vimorecolors);

//check
if (xdatalen<4) then goto skipend;

//clean -> expects "(....)"
xwithin   :=false;
xclean    :='';

for p:=1 to low__len32(xdata) do
begin

v         :=strbyte1(xdata,p);

if (v=ssLRoundbracket)             then xwithin:=true;//start
if xwithin and (v=ssRRoundbracket) then break;//stop

//.scan
if xwithin then
   begin

   if ((v>=nn0) and (v<=nn9)) or ((v>=llA) and (v<=llZ)) or ((v>=uuA) and (v<=uuZ)) then xclean:=xclean+char(v);

   end;

end;//p

//clean2 - assumes "...." (no brackets) - 22jul2021
if not xwithin then
   begin

   for p:=1 to low__len32(xdata) do
   begin

   v:=strbyte1(xdata,p);
   if (v=uuC) or (v=llC) then xwithin:=true;//start

   //.scan
   if xwithin then
      begin

      if ((v>=nn0) and (v<=nn9)) or ((v>=llA) and (v<=llZ)) or ((v>=uuA) and (v<=uuZ)) then xclean:=xclean+char(v);

      end;

   end;//p

   end;

//header
if strmatch(strcopy1(xclean,1,4),'col2') then//already in native format -> use as is
   begin

   xout   :=xclean;
   result :=true;
   goto skipend;

   end;

if not strmatch(strcopy1(xclean,1,4),'col3') then goto skipend;

//get
xpos      :=5;//start past header
xlen      :=low__len32(xclean);

redo:

if ((xpos+7)<=xlen) then
   begin

   int1.val  :=hex8__int(strcopy1(xclean,xpos,8),0,0);
   xindex    :=int1.a;
   int1.a    :=0;

   if low__criticalcolor(xindex) then
      begin

      xout   :=low__setcolor(xout,xindex,int1.val);
      result :=true;//successful

      end;

   //inc
   inc(xpos,8);
   goto redo;

   end;

skipend:

//brighten colors
if (xadjBrightness100<>0) then xout:=low__setcolorb(xout,-1,0,xadjBrightness100);

//filter
xout:=low__fixcolors(xout);

end;

function low__getcolor(const xdata:string;const xindex:longint;var xcolor:longint):boolean;
begin
result:=low__getcolor2(xdata,xindex,xcolor);
end;

function low__getcolor2(const xdata:string;const xindex:longint;var xcolor:longint):boolean;
label
   dodef,redo,redo2;
var
   xadjBrightness100,p,xlen,dlen:longint;
   str1:string;

   function xval255(const xpos:longint):byte;
   begin
   result:=frcrange32(strint32(strcopy1x(xdata,xpos,3)),0,255);
   end;

   function dval255(const xpos:longint):byte;
   begin
   result:=frcrange32(strint32(strcopy1(system_defaultcolors,xpos,3)),0,255);
   end;

begin
//defaults
result  :=false;

//init
xcolor  :=0;
xlen    :=low__len32(xdata);
dlen    :=low__len32(system_defaultcolors);
xadjBrightness100:=0;

//check
if not low__validcolor(xindex,xcolor)         then exit;
if (xlen<4) or (strcopy1x(xdata,1,4)<>'col2') then goto dodef;

//get
p :=5;//jump over 4byte header
redo:

if ((p+11)<=xlen) then//1..3=index, 4..6=red, 7..9=green, 10..12=blue = 12 bytes
   begin

   case (xindex=xval255(p+0)) of
   true:begin

      xcolor:=rgba0__int(xval255(p+3),xval255(p+6),xval255(p+9));
      result:=true;

      end;
   else begin//loop

      inc(p,12);
      goto redo;

      end;
   end;//case

   end;

//fallback to "xdefdata" -> system default colors - 09mar2021
dodef:

//prime "system_defaultcolors" -> this stores the system DEFAULT color scheme -> now set to the program's default - 27mar2022
if (dlen<=0) then
   begin

   str1                 :=low__findbuiltincolor('?'+app__info('color.name'),true,xadjBrightness100);//brightness handled within
   system_defaultcolors :=str1;
   dlen                 :=low__len32(system_defaultcolors);

   end;

p :=5;//jump over 4byte header
redo2:

if (not result) and (dlen>=1) and ((p+11)<=dlen) then//1..3=index, 4..6=red, 7..9=green, 10..12=blue = 12 bytes
   begin

   case (xindex=dval255(p+0)) of
   true:begin

      xcolor:=rgba0__int(dval255(p+3),dval255(p+6),dval255(p+9));
      result:=true;

      end;
   else begin//loop

      inc(p,12);
      goto redo2;

      end;
   end;//case

   end;

end;

function low__setcolor(const xdata:string;const xindex,xcolor:longint):string;//outputs entire color stream
begin
result:=low__setcolor2(xdata,xindex,xcolor);
end;

function low__setcolorb(const xdata:string;const xindex,xcolor:longint;const xadjBrightness100:longint):string;//outputs entire color stream
begin
result:=low__setcolor3(xdata,xindex,xcolor,xadjBrightness100);
end;

function low__setcolor2(const xdata:string;const xindex,xcolor:longint):string;//outputs entire color stream
begin
result:=low__setcolor3(xdata,xindex,xcolor,0);
end;

function low__setcolor3(const xdata:string;const xindex:longint;xcolor:longint;const xadjBrightness100:longint):string;//18sep2022 outputs entire color stream
var
   p,xdefcol,int1:longint;

   function xcolset(const xindex,xcolor:longint):string;
   var
      v4:tint4;

      function x255(const x:byte):string;
      begin

      case x of
      0..9:  result:='00'+intstr32(x);// -> 009
      10..99:result:='0'+intstr32(x);//  -> 099
      else   result:=intstr32(x);//      -> 199
      end;//case

      end;

   begin

   //defaults
   result :='';

   //range
   v4.val :=xcolor;
   v4.a   :=frcrange32(xindex,0,255);

   //.adjBrightness - 18sep2022
   if (xadjBrightness100<>0) then
      begin

      v4.r:=low__coloradjBrightness(v4.r,xadjBrightness100);
      v4.g:=low__coloradjBrightness(v4.g,xadjBrightness100);
      v4.b:=low__coloradjBrightness(v4.b,xadjBrightness100);

      end;

   //get
   result:=x255(v4.a)+x255(v4.r)+x255(v4.g)+x255(v4.b);

   end;

begin

//defaults
result :='col2';//header
xcolor :=frcrange32(xcolor,0,16777215);

//get
for p:=0 to 255 do if low__validcolor(p,xdefcol) then
   begin

   if (p=xindex)                        then result:=result+xcolset(p,xcolor)
   else if low__getcolor2(xdata,p,int1) then result:=result+xcolset(p,int1)
   else                                      result:=result+xcolset(p,xdefcol);

   end;//p

end;

function low__getcolors(const xnormal,xtitle:pvirtualinfo;const xmorecolors:pvirtualmorecolors):string;

   procedure xadd(const xindex,xcolor:longint);
   begin
   result:=low__setcolor2(result,xindex,xcolor);
   end;

begin

//defaults
result :='';

//get
//.standard colors
if (xnormal<>nil) then
   begin

   xadd(cnFrame,xnormal.frame);
   xadd(cnFrame2,xnormal.frame2);
   xadd(cnback1,xnormal.background);
   xadd(cnborder1,xnormal.border);
   xadd(cnhigh1,xnormal.highlight);
   xadd(cnhover1,xnormal.hover);
   xadd(cntext1,xnormal.font);
   xadd(cntexthigh1,xnormal.fonthighlight);
   xadd(cntextdis1,xnormal.disablefont);
   xadd(cndis1,xnormal.disable);
   xadd(cndisbr1,xnormal.disableborder);

   end;

//.title colors
if (xtitle<>nil) then
   begin

   xadd(cnFrame,xtitle.frame);
   xadd(cnFrame2,xtitle.frame2);
   xadd(cnback2,xtitle.background);
   xadd(cnborder2,xtitle.border);
   xadd(cnhigh2,xtitle.highlight);
   xadd(cnhover2,xtitle.hover);
   xadd(cntext2,xtitle.font);
   xadd(cntexthigh2,xtitle.fonthighlight);
   xadd(cntextdis2,xtitle.disablefont);
   xadd(cndis2,xtitle.disable);
   xadd(cndisbr2,xtitle.disableborder);

   end;

//.more colors
if (xmorecolors<>nil) then
   begin

   xadd(cnsFrame,xmorecolors.frame);
   xadd(cnsTitle,xmorecolors.title);
   xadd(cnsStandard,xmorecolors.standard);
   xadd(cnsAllinone,xmorecolors.allinone);
   xadd(cnsDark_light,xmorecolors.dark_light);
   xadd(cnsLight_dark,xmorecolors.light_dark);

   end;

end;

procedure low__setcolors(const xdata:string;const xnormal,xtitle:pvirtualinfo;const xmorecolors:pvirtualmorecolors);

   procedure xadd(const xindex:longint;var xcolor:longint);
   begin
   low__getcolor2(xdata,xindex,xcolor);
   end;

begin

//get
//.standard colors
if (xnormal<>nil) then
   begin

   xadd(cnFrame,xnormal.frame);
   xadd(cnFrame2,xnormal.frame2);
   xadd(cnback1,xnormal.background);
   xadd(cnborder1,xnormal.border);
   xadd(cnhigh1,xnormal.highlight);
   xadd(cnhover1,xnormal.hover);
   xadd(cntext1,xnormal.font);
   xadd(cntexthigh1,xnormal.fonthighlight);
   xadd(cntextdis1,xnormal.disablefont);
   xadd(cndis1,xnormal.disable);
   xadd(cndisbr1,xnormal.disableborder);

   end;

//.title colors
if (xtitle<>nil) then
   begin

   xadd(cnFrame,xtitle.frame);
   xadd(cnFrame2,xtitle.frame2);
   xadd(cnback2,xtitle.background);
   xadd(cnborder2,xtitle.border);
   xadd(cnhigh2,xtitle.highlight);
   xadd(cnhover2,xtitle.hover);
   xadd(cntext2,xtitle.font);
   xadd(cntexthigh2,xtitle.fonthighlight);
   xadd(cntextdis2,xtitle.disablefont);
   xadd(cndis2,xtitle.disable);
   xadd(cndisbr2,xtitle.disableborder);

   end;

//.more colors
if (xmorecolors<>nil) then
   begin

   xadd(cnsframe,xmorecolors.frame);
   xadd(cnstitle,xmorecolors.title);
   xadd(cnsstandard,xmorecolors.standard);
   xadd(cnsallinone,xmorecolors.allinone);
   xadd(cnsdark_light,xmorecolors.dark_light);
   xadd(cnslight_dark,xmorecolors.light_dark);

   end;

end;

function low__setcolorsbyname(xname:string;const xnormal,xtitle:pvirtualinfo;const xmorecolors:pvirtualmorecolors):boolean;
label
   redo;
var
   dcount,xadjBrightness100,int1:longint;
   n,xdata:string;
   xdefonce,xchecknameonly:boolean;

   function x255(x:byte):string;//argb -> don't adjust "a" this is a color index number - 18sep2022
   begin

   //inc
   inc(dcount);
   case dcount of
   1:;
   2..4:x:=low__coloradjBrightness(x,xadjBrightness100);
   end;

   if (dcount>=4) then dcount:=0;

   //get
   case x of
   0..9:  xdata:=xdata+'00'+intstr32(x);// -> 009
   10..99:xdata:=xdata+'0'+intstr32(x);//  -> 099
   else   xdata:=xdata+intstr32(x);//      -> 199
   end;//case

   end;

   procedure aset(const x:array of byte;const x2:string);
   var
      a:tstr8;
      p:longint;
   begin
   //defaults
   result  :=true;
   dcount  :=0;
   a       :=nil;

   try
   //get
   if not xchecknameonly then
      begin
      a:=str__new8;

      if (x2<>'')   then a.sadd(x2) else a.aadd(x);
      if (a.len>=1) then
         begin

         for p:=0 to (a.len32-1) do if (p<=3) then xdata:=xdata+char(a.pbytes[p]) else x255(a.pbytes[p]);

         end;
      end;
   except;end;

   //free
   str__free(@a);

   end;

   procedure fset(const x:string);
   var
      a:tstr8;
      n,e:string;
   begin

   //defaults
   a:=nil;

   try
   //get
   n:=low__platfolder('schemes')+x+'.'+cnFileEXT;

   case xchecknameonly of
   true:result:=io__fileexists(n);
   else begin
      a:=str__new8;

      if io__fromfile(low__platfolder('schemes')+x+'.'+cnFileEXT,@a,e) then
         begin

         xdata:=a.text;
         result:=true;

         end;

      end;//begin
   end;//case

   except;end;

   //free
   str__free(@a);

   end;

   procedure xadd(const xindex:longint;var xcolor:longint);
   begin
   low__getcolor2(xdata,xindex,xcolor);
   end;

   function m(const xname:string):boolean;
   begin
   result:=strmatch(xname,n);
   end;

begin

//defaults
result             :=false;
xdefonce           :=true;
xdata              :='';
xchecknameonly     :=(xnormal=nil) and (xtitle=nil) and (xmorecolors=nil);
xadjBrightness100  :=0;
dcount             :=0;

//get
redo:
n                  :=strlow(xname);

//.nil
if (n='') then
   begin
   //nil
   end

//.internal
else if (strcopy1(n,1,1)='?') then
   begin

   //.if padder
   if (n='?') then
      begin
      //nil
      end

   //.custom
   else if strmatch(strcopy1(n,1,7),'?custom') then
      begin

      int1:=strint32(strcopy1(n,8,low__len32(n)));

      if (int1>=0) and (int1<cnCustomLimit) then
         begin

         result:=true;
         if (not xchecknameonly) and zzok(syssettings,1016) then xdata:=syssettings.value[n];

         end;

      end

   //.paste and use - 27mar2022
   else if (n='?paste_and_use') then
      begin

      result:=true;

      if (not xchecknameonly) and zzok(syssettings,1016) then xdata:=syssettings.value[n];

      end
   //.static - built-in colors - 09may2021
   else if (n='?default')    then
      begin

      if (app__info('color.name')<>'') and xdefonce then
         begin

         xdefonce :=false;
         xname    :='?'+app__info('color.name');

         goto redo;

         end

      //else if (sizeof(cols__default)>=2) then aset(cols__default,'')
      else aset(cols_black2,'')//23nov2024, 5mar2022 - was: glowing_grey)//10mar2021

      end

   //.newer built-in colors - 22jul2021
   else aset([0],low__findbuiltincolor(n,false,xadjBrightness100));//brightness MUST be handled by "aset()"

   end

//.file
else fset(xname);//retain name case

//set
if not xchecknameonly then low__setcolors(xdata,xnormal,xtitle,xmorecolors);

end;

function low__coloradjBrightness(x:byte;const xadjBrightness100:longint):byte;
var
   v:longint;
begin

//defaults
result:=x;

//filter
if (xadjBrightness100<>0) then
   begin

   //get
   if (result<1) then result:=1;//lift the value so we can esculate
   v:=round(result+(result*( frcrange32(xadjBrightness100,-100,100) /100)));

   //set
   result:=byte( frcrange32(v ,0 ,255) );

   end;

end;

function low__findbuiltincolor(const n:string;const xexpand:boolean;var xadjBrightness100:longint):string;
var
   dcount,xval1:longint;
   xdata:tlistptr;

   function x255(x:byte):string;//argb -> don't adjust "a" this is a color index number - 18sep2022
   begin

   //inc
   inc(dcount);

   case dcount of
   1:;
   2..4:x:=low__coloradjBrightness(x,xadjBrightness100);
   end;

   if (dcount>=4) then dcount:=0;

   //get
   case x of
   0..9:  result:='00'+intstr32(x);// -> 009
   10..99:result:='0'+intstr32(x);//  -> 099
   else   result:=intstr32(x);//      -> 199
   end;//case

   end;

   procedure xset(var x:tlistptr;const xbrightness:longint);
   var
      a:tstr8;
      p:longint;
   begin

   //defaults
   a:=nil;

   //check
   if (x.count<=0) then exit;

   try
   //get
   a                 :=str__new8;
   xadjBrightness100 :=xbrightness;
   str__padd(@a,x.bytes,x.count);

   if xexpand then
      begin

      if (a.len>=1) then
         begin

         for p:=0 to restrict32(a.len-1) do if (p<=3) then result:=result+char(a.pbytes[p]) else result:=result+x255(a.pbytes[p]);

         end;

      end

   else result:=a.text;

   except;end;

   //free
   str__free(@a);

   end;

begin

//init
result            :='';
xadjBrightness100 :=0;
dcount            :=0;

//get
if (strcopy1(n,1,1)='?') and sicolors_find(strcopy1(n,2,low__len32(n)),xdata,xval1) then
   begin
   xset(xdata,xval1);
   end
else
   begin
   xdata:=low__maplist(cols_black2);
   xset(xdata,0);
   end;

end;

function sysstatus0(const xindex:longint;const xvalue:string):boolean;//07oct2022
var
   xref64:comp;
begin

xref64:=slowms64;
result:=sysstatus(xref64,xindex,xvalue);

end;

function sysstatus(var xref64:comp;const xindex:longint;const xvalue:string):boolean;//04oct2022
begin
result:=sysstatus2(xref64,xindex,xvalue,'',-1);
end;

function sysstatus2(var xref64:comp;const xindex:longint;const xvalue:string;xnewtitle:string;xnewpert:double):boolean;//07oct2022
begin//Note: returns TRUE when stopped

if (xindex>=0) and (sysprogram<>nil) and (slowms64>=xref64) then
   begin

   if (xnewtitle<>'') or (xnewpert>=0) then
      begin
      //init
      if (xnewtitle='') then xnewtitle:=sysprogram.gui.xstatustitle;
      if (xnewpert<0)   then xnewpert:=sysprogram.gui.xstatuspert;
      //get
      sysprogram.gui.xstatus(xnewpert,xnewtitle);
      end;

   result:=sysstatus_settext(xindex,xvalue);
   sysstatus_paintnow;
   xref64:=slowms64+sysstatus_painttime;

   end
else result:=false;

end;

function sysstatus_settext(const xindex:longint;const xvalue:string):boolean;//07oct2022
begin//Note: returns TRUE when stopped

if (xindex>=0) and (sysprogram<>nil) then
   begin
   sysprogram.gui.xstatustext[xindex]:=xvalue;
   result:=sysstatus_stopped;
   end
else result:=false;

end;

function sysstatus_setpert(const xpert:double):boolean;//07oct2022
begin//Note: returns TRUE when stopped

if (sysprogram<>nil) then
   begin

   sysprogram.gui.xstatuspert :=xpert;
   result                     :=sysstatus_stopped;

   end
else result                   :=false;

end;

function sysstatus_paintnow:boolean;//07oct2022
begin//Note: returns TRUE when stopped

if (sysprogram<>nil) then
   begin
   sysprogram.gui.xstatuspaintnow;
   result:=sysstatus_stopped;
   end
else result:=false;

end;

function sysstatus_stopped:boolean;//07oct2022
begin
result:=(sysprogram<>nil) and sysprogram.gui.xstatustopped;
end;


//platform support -------------------------------------------------------------
function low__plat(xcmd,xprgname:string;xrunaction:boolean):string;
var
   xprgnameORG,v,xval:string;
   p:longint;

   function xstoragefolder:string;
   begin
   result:=app__folder2('',false);//don't create the folder here
   end;

   function xnospaces(const x:string):string;//02may2022
   var
      p:longint;
   begin
   result:=x;
   for p:=1 to low__len32(result) do if (strcopy1(result,p,1)=#32) or (strcopy1(result,p,1)=#160) or (strcopy1(result,p,1)=#9) then result[p-1+stroffset]:=#32;
   low__remchar(result,#32);
   end;

   function xvisit(xname,xmore:string):string;
   begin
   result:=app__info(xname+xmore);
   if xrunaction and (result<>'') then runlow(result,'');
   end;
begin
//defaults
result:='';

try
//init
xcmd:=strlow(xcmd);
xval:='';
xprgnameORG:=xprgname;
if (xprgname='') then xprgname:=programwebname;
//.split
if (xcmd<>'') then
   begin
   for p:=1 to low__len32(xcmd) do if (strcopy1(xcmd,p,1)='.') then
      begin
      xval:=strcopy1(xcmd,p+1,low__len32(xcmd));
      xcmd:=strcopy1(xcmd,1,p-1);
      break;
      end;//p
   end;

//get
if      (xcmd='newinstance') then
   begin
   result:=io__exename;
   if xrunaction then
      begin
      siSaveallsettings;
      runLOW(result,'');
      end;
   end
//.folder
else if (xcmd='folder') then
   begin
   result:=xstoragefolder;//this folder and up we own
   //filter
   if (xprgname<>'') then
      begin
      xprgname:=io__safefilename(xprgname,true);
      result:=io__asfolder(result+xprgname);
      end;
   //get
   if xrunaction and viMaster and (not io__folderexists(result)) then io__makefolder(result);
   end
//.folderbe
else if (xcmd='folderbe') then
   begin
   result:=xstoragefolder;//this folder and up we own
   if xrunaction and viMaster and (not io__folderexists(result)) then io__makefolder(result);
   end
else if (xcmd='root') then result:=io__asfolder(io__extractfilepath(io__exename))
else if (xcmd='showroot') then
   begin
   result:=io__asfolder(io__extractfilepath(io__exename));
   runlow(result,'');
   end

//.help
else if (xcmd='showhelp') then low__showhelp(not vihelp_show)

//.websites and web links
else if (xcmd='portal')       then result:=xvisit('url.portal','')
else if (xcmd='contact')      then result:=xvisit('url.contact','')
else if (xcmd='software')     then result:=xvisit('url.software','')
else if (xcmd='instagram')    then result:=xvisit('url.instagram','')
else if (xcmd='facebook')     then result:=xvisit('url.facebook','')
else if (xcmd='mastodon')     then result:=xvisit('url.mastodon','')//11dec2023
else if (xcmd='twitter')      then result:=xvisit('url.twitter','')
else if (xcmd='sourceforge')  then result:=xvisit('url.sourceforge','')
else if (xcmd='github')       then result:=xvisit('url.github','')//02dec2023
else if (xcmd='nprogram') or (xcmd='program') then result:=xvisit('url.software','')
else if (xcmd='nprogramzip') or (xcmd='programzip') then result:=xvisit('url.software.zip','')

//.start menu
else if (xcmd='startmenu') then
   begin
   result:=io__winprograms+app__info('linkname');
   //.create
   if      (xval='') or (xval='create') then
      begin
      if xrunaction and (not io__fileexists(result)) then io__createlink(result,io__exename,'','');
      end
   //.del
   else if (xval='del') then
      begin
      if xrunaction then io__remfile(result);
      end
   //.exists
   else if (xval='exists') then result:=bnc(io__fileexists(result))
   //.toggle
   else if (xval='toggle') then
      begin
      case io__fileexists(result) of
      true:low__plat(xcmd+'.del',xprgname,xrunaction);//delete existing
      else low__plat(xcmd,xprgname,xrunaction);//create new
      end;//case
      end
   //.error
   else showerror('Unknown directive "'+xcmd+'.'+xval+'" [006]');
   end
//.desktop
else if (xcmd='desktop') then
   begin
   result:=io__windesktop+app__info('linkname');
   //.create
   if      (xval='') or (xval='create') then
      begin
      //init
      if viwine then v:=io__remlastext(result)+'.desktop' else v:='';
      //get
      if xrunaction and ( (not io__fileexists(result)) and (not io__fileexists(v)) ) then
         begin
         io__createlink(result,io__exename,'','');
         //Note: Wine writes the ".lnk" and makes it's own ".desktop" files -> only the ".desktop" works as a link so we should delete the ".lnk" as it just wastes desktop space - 05feb2022
         if viwine and io__fileexists(result) and (v<>'') then
            begin
            //slight delay on a Windowed Ubuntu v20 - so try 20 times 100ms apart - 05feb2022
            for p:=1 to 20 do
            begin
            if io__fileexists(v) then
               begin
               io__remfile(result);
               break;
               end;
            win____sleep(100);
            end;//p
            end;
         end;
      end
   //.del
   else if (xval='del') then
      begin
      if xrunaction then
         begin
         io__remfile(result);
         //Note: Wine generates a duplicate file ending with ".desktop" - 05feb2022
         if viwine then io__remfile(io__remlastext(result)+'.desktop');
         end;
      end
   //.exists
   else if (xval='exists') then result:=bnc(io__fileexists(result))
   //.toggle
   else if (xval='toggle') then
      begin
      case io__fileexists(result) of
      true:low__plat(xcmd+'.del',xprgname,xrunaction);//delete existing
      else low__plat(xcmd,xprgname,xrunaction);//create new
      end;//case
      end
   //.error
   else showerror('Unknown directive "'+xcmd+'.'+xval+'" [006]');
   end
//.startup (auto startup) link
else if (xcmd='startup') then
   begin
   result:=io__winstartup+io__safefilename(io__exename,false)+'.lnk';
   //.create
   if      (xval='') or (xval='create') then
      begin
      if xrunaction and (not io__fileexists(result)) then io__createlink(result,io__exename,'','');
      end
   //.del
   else if (xval='del') then
      begin
      if xrunaction then io__remfile(result);
      end
   //.exists
   else if (xval='exists') then result:=bnc(io__fileexists(result))
   //.toggle
   else if (xval='toggle') then
      begin
      case io__fileexists(result) of
      true:low__plat(xcmd+'.del',xprgname,xrunaction);//delete existing
      else low__plat(xcmd,xprgname,xrunaction);//create new
      end;//case
      end
   //.error
   else showerror('Unknown directive "'+xcmd+'.'+xval+'" [007]');
   end
else showerror('Unknown directive "'+xcmd+'" [007]');
except;end;
end;

function low__platroot:string;
begin
result:=low__plat('root','',true);
end;

function low__platfolder(xname:string):string;//06oct2020
begin
case (xname<>'') of
true:result:=low__plat('folder',xname,true);
else result:=low__plat('folderbe','',true);
end;
end;

function low__platfolder2(xname:string;xcreate:boolean):string;//10feb2023
begin
case (xname<>'') of
true:result:=low__plat('folder',xname,xcreate);
else result:=low__plat('folderbe','',xcreate);
end;
end;

function low__plattemp:string;
begin
result:=low__platfolder('temp');
end;

function low__platDLLname(xname:string):string;//26sep2021
begin
//was: result:=low__platfolder('settings')+strlow(xname)+insstr('-',xname<>'')+io__ownname+'.dll';
result:=low__platfolder('settings')+strlow(xname)+'.'+'d'+'ll';
end;

function low__platsyssettings:string;
begin
//was: result:=low__platfolder('settings')+'sys-'+io__ownname+'.ini';
result:=low__platfolder('settings')+'sys-settings.ini';
end;

function low__platprgsettings:string;
begin
//was: result:=low__platfolder('settings')+'prg-'+io__ownname+'.ini';
result:=low__platfolder('settings')+'prg-settings.ini';
end;

function low__platonce:string;
begin
//was: result:=low__platfolder('settings')+io__ownname+'.one';
result:=low__platfolder('settings')+'active.one';
end;

function low__platactive:string;
begin
//was: result:=low__platfolder('settings')+io__ownname+'.act';
result:=low__platfolder('settings')+'active.act';
end;

function low__platimages:string;
begin
result:=low__platfolder('images');
end;

function low__platsysext(xext:string):string;//29aug2021
begin
xext:=strlow(xext);
case viMaster of
//was: true:result:=low__platfolder('settings')+'sys-'+io__ownname+insstr('.',xext<>'')+xext;
true:result:=low__platfolder('settings')+'sys-settings'+insstr('.',xext<>'')+xext;
else result:=io__wintemp+'sys-'+intstr32(system_instanceid)+insstr('.',xext<>'')+xext;
end;
end;

function low__platprgext(xext:string):string;//29aug2021
begin
xext:=strlow(xext);
case viMaster of
//was: true:result:=low__platfolder('settings')+'prg-'+io__ownname+insstr('.',xext<>'')+xext;
true:result:=low__platfolder('settings')+'prg-settings'+insstr('.',xext<>'')+xext;
else result:=io__wintemp+'prg-'+intstr32(system_instanceid)+insstr('.',xext<>'')+xext;
end;
end;

function low__t(x:boolean):longint;
begin
if x then result:=tepOn else result:=tepOff;
end;

function low__instouch(xval,xtouchval:longint):longint;//06may2020
begin
result:=low__instouch2(xval,xtouchval,true);
end;

function low__instouch2(xval,xtouchval:longint;xallowtouch:boolean):longint;//06may2020
begin
if xallowtouch and vitouch then result:=frcmin32(xval,xtouchval) else result:=xval;
end;


//clipboard procs --------------------------------------------------------------
function clip__opened(var xopened:boolean):boolean;//01sep2025
var
   p,h:longint;
begin

for p:=1 to 10 do
begin

if (app__gui<>nil) then h:=app__gui.handle else h:=0;

xopened   :=win____OpenClipboard(h);
result    :=xopened;

if result then break else win____sleep(1);

end;//p

end;

function clip__openedAndclear(var xopened:boolean):boolean;//01sep2025
var
   p,h:longint;
begin

for p:=1 to 10 do
begin

if (app__gui<>nil) then h:=app__gui.handle else h:=0;

xopened   :=win____OpenClipboard(h);
result    :=xopened and win____EmptyClipboard;

if result then break else win____sleep(1);

end;//p

end;

function clip__copymulti(xformat:array of word;xdata:array of pobject):boolean;//01sep2025
label
   skipend;
var
   d:tstr8;
   xcount,p:longint;
   xopened:boolean;
begin
//defaults
result   :=false;
xopened  :=false;
d        :=nil;

try
//init
xcount:=1+smallest32(high(xformat),high(xdata));
d     :=str__new8;

//lock
for p:=0 to high(xdata) do str__lock(xdata[p]);

//get
if clip__openedAndclear(xopened) then
   begin

   for p:=0 to (xcount-1) do if (xformat[p]>=1) and (xdata[p]<>nil) then
      begin

      d.makeglobal;//clear + new handle

      if not str__add(@d,xdata[p]) then goto skipend;

      if (0=win____setclipboarddata(xformat[p],d.handle)) then goto skipend;//clipboard now owns our memory handle - 15may2025

      d.ejectcore;

      end;

   //successful
   result:=true;
   end;

skipend:
except;end;
try

//free
str__free(@d);
for p:=0 to high(xdata) do str__uaf(@xdata[p]);

//close clipboard
if xopened then win____CloseClipboard;

except;end;
end;

function clip__hasformat(xformat:uint32):boolean;
begin
result:=win____IsClipboardFormatAvailable(xformat);
end;

function clip__cancopytext:boolean;//20mar2021
begin
result:=true;
end;

function clip__copytext(const xdata:string):boolean;//01sep2025, 26apr2025
var
   d:tstr8;
   p:longint3264;
   xlen:longint64;
   xopened:boolean;

begin

//defaults
result      :=false;
xopened     :=false;
d           :=nil;
xlen        :=low__len32(xdata);

try

//init
d:=str__new8;
d.makeglobal;

//get
if d.setlen(xlen+1) and clip__openedAndclear(xopened) then
   begin

   //get
   for p:=1 to int64__3264(xlen) do d.pbytes[p-1]:=byte(xdata[p-1+stroffset]);
   d.pbytes[ int64__3264(xlen) ]:=0;

   //set
   result:=(0<>win____setclipboarddata(CF_TEXT,d.handle));
   if result then d.ejectcore;

   end;

except;end;

//free
freeobj(@d);

//close clipboard
if xopened then win____CloseClipboard;

end;

function clip__copytext2(xdata:pobject):boolean;//01sep2025, 01jun2025, 26apr2025
var
   d:tstr8;
   xlen:longint64;
   p:longint3264;
   xopened:boolean;
begin
//defaults
result      :=false;
xopened     :=false;
d           :=nil;

try
//init
if str__lock(xdata) then
   begin

   d    :=str__new8;
   d.makeglobal;//15may2025
   xlen :=str__len32(xdata);//01jun2025

   //get
   if d.setlen(xlen+1) and clip__openedAndclear(xopened) then
      begin

      //get
      for p:=0 to int64__3264(xlen-1) do d.pbytes[p]:=str__pbytes0(xdata,p);
      d.pbytes[ int64__3264(xlen) ]:=0;

      //set
      result:=(0<>win____setclipboarddata(CF_TEXT,d.handle));
      if result then d.ejectcore;

      end;

   end;

except;end;

//free
freeobj(@d);
str__uaf(xdata);

//close clipboard
if xopened then win____CloseClipboard;

end;

function clip__canpastetext:boolean;//16mar2021
begin
result:=clip__hasformat(cf_text);
end;

function clip__pastetext(var xdata:string):boolean;//01sep2025, 27apr2025
var
   h:longint3264;
   xopened:boolean;
begin
//defaults
result   :=false;
xdata    :='';
xopened  :=false;

try

if clip__canpastetext and clip__opened(xopened) then
   begin

   //get
   h:=win____GetClipboardData(cf_text);

   try

   if (h<>0) then
      begin

      xdata:=pchar(win____globallock(h));
      result:=true;

      end;

   except;end;

   //unlock but DO NOT free -> the Clipboard owns this memory handler
   if (h<>0) then win____globalunlock(h);

   end;

except;end;

//close clipboard
if xopened then win____closeclipboard;

end;

function clip__pastetextb:string;//27apr2025
begin
clip__pastetext(result);
end;

function clip__pastetext2(xdata:pobject):boolean;//27apr2025
label
   skipend;
var
   h:longint3264;
   xopened:boolean;
begin
//defaults
result  :=false;
xopened :=false;

try
//check
if     str__lock(xdata)  then str__clear(xdata) else goto skipend;
if not clip__canpastetext then goto skipend;

//get
if clip__opened(xopened) then
   begin

   //get
   h:=win____GetClipboardData(cf_text);

   try;result:=str__settext(xdata, pchar(win____globallock(h)) );except;end;

   //unlock but DO NOT free -> the Clipboard owns this memory handler
   win____globalunlock(h);

   end;


skipend:
except;end;

//clear on error
if not result then str__clear(xdata);

//free
str__uaf(xdata);

//close clipboard
if xopened then win____CloseClipboard;

end;

function clip__pasteformat(xformat:word;xout:pobject):boolean;//27apr2025
label
   skipend;
var
   h:longint3264;
   slist:pdlbyte;
   p,xlen:longint;
   xopened:boolean;
begin
//defaults
result  :=false;
xopened :=false;

try
//check
if     str__lock(xout)          then str__clear(xout) else goto skipend;
if not clip__hasformat(xformat) then goto skipend;

//get
if clip__opened(xopened) then
   begin
   h:=win____GetClipboardData(xformat);

   try
   slist:=win____globallock(h);
   xlen :=frcmin32( win____globalsize(h) ,0);

   if str__setlen(xout,xlen) then
      begin
      case str__is8(xout) of
      true:for p:=0 to (xlen-1) do (xout^ as tstr8).pbytes[p]:=slist[p];
      else for p:=0 to (xlen-1) do str__setpbytes0(xout,p,slist[p]);
      end;//case

      //successful
      result:=true;
      end;
   except;end;

   //unlock but DO NOT free -> the Clipboard owns this memory handler
   win____globalunlock(h);

   end;

skipend:
except;end;

//clear on error
if not result then str__clear(xout);

//free
str__uaf(xout);

//close clipboard
if xopened then win____CloseClipboard;

end;

function clip__canpasteimage(const xenhancedformats:boolean):boolean;//18mar2026, 29apr2025
begin
result:=clip__hasformat(cf_png) or clip__hasformat(cf_dibv5) or clip__hasformat(cf_dib) or clip__hasformat(cf_bitmap) or (xenhancedformats and clip__canpastetext);
end;

function clip__pasteimage(const d:tobject;const xenhancedformats:boolean):boolean;//18mar2026, 12jun2025, 08jun2025, 01jun2025, 29apr2025
label
   skipend;
var
   e:string;
   a:tstr8;
   xopened:boolean;
   xbmp:tbitmapheader;
   xinfo:TBitmapInfoHeader;
   xdc:hdc;
   cbmp:hbitmap;
   dr32:pcolorrow32;
   dr24:pcolorrow24;
   dr8 :pcolorrow8;
   c24:tcolor24;
   c32:tcolor32;
   dpos,drowsize,xlen,sbits,dbits,dy,dx,dw,dh:longint;
   hmem:hglobal;
   hptr:pointer;
   hlist:pdlbyte;

   procedure xpull32;
   begin
   c32.b:=hlist[dpos+0];
   c32.g:=hlist[dpos+1];
   c32.r:=hlist[dpos+2];
   c32.a:=hlist[dpos+3];
   inc(dpos,4);
   end;

   procedure xpull24;
   begin
   c24.b:=hlist[dpos+0];
   c24.g:=hlist[dpos+1];
   c24.r:=hlist[dpos+2];
   inc(dpos,3);
   end;
begin

//defaults
result  :=false;
a       :=nil;
xdc     :=0;
hmem    :=0;
hptr    :=nil;
xopened :=false;

try

//check
if not clip__opened(xopened)   then goto skipend;
if not misokk82432(d)          then goto skipend;

//init
dbits  :=misb(d);
a      :=str__new8;

//png
if (not result) and clip__hasformat(cf_png) then
   begin
   try
   a.clear;
   a.makeglobalFROM( win____GetClipboardData(cf_png) , false);
   if (a.len>=1) then
      begin
      result:=png__fromdata(d,@a,e);
      a.ejectcore;
      end;
   except;end;
   end;

//dibv5
if (not result) and clip__hasformat(cf_dibv5) then
   begin
   try
   a.clear;
   a.makeglobalFROM( win____GetClipboardData(cf_dibv5) , false);
   if (a.len>=1) then
      begin
      result:=bmp32__fromdata2(d,@a,true);//allow the "dib_patch_12" mode
      a.ejectcore;
      end;
   except;end;
   end;

//dib
if (not result) and clip__hasformat(cf_dib) then
   begin
   try
   a.clear;
   a.makeglobalFROM( win____GetClipboardData(cf_dib) , false);
   if (a.len>=1) then
      begin
      result:=bmp32__fromdata(d,@a);
      a.ejectcore;
      end;
   except;end;
   end;

//bitmap
if (not result) and clip__hasformat(cf_bitmap) then
   begin
   //get handle to "hbitmap" in Clipboard
   cbmp:=win____GetClipboardData(cf_bitmap);
   if (cbmp=0) then goto skipend;

   low__cls(@xbmp,sizeof(xbmp));
   if (0=win____getobject(cbmp,sizeof(xbmp),@xbmp)) then goto skipend;

   dw   :=xbmp.bmwidth;
   dh   :=xbmp.bmheight;
   sbits:=32;//force as 32 bits - 01jun2025
   if (dw<1) or (dh<1) then goto skipend;

   low__cls(@xinfo,sizeof(xinfo));
   xinfo.bisize       :=sizeof(xinfo);
   xinfo.biwidth      :=dw;
   xinfo.biheight     :=dh;
   xinfo.biBitCount   :=sbits;
   xinfo.biPlanes     :=1;
   xinfo.biCompression:=0;

   xdc:=win____getdc(0);
   if (0=win____GetDIBits(xdc,cbmp,0,dh,nil,xinfo,DIB_RGB_COLORS)) then goto skipend;
   if (dw<=0) or (dh<=0) or ((sbits<>24) and (sbits<>32)) then goto skipend;

   //init
   drowsize  :=mis__rowsize4(dw,sbits);//27may2025
   xlen      :=dh * drowsize;

   //get pixels
   hmem:=win____GlobalAlloc(GMEM_MOVEABLE,xlen);
   hptr:=win____Globallock(hmem);
   hlist:=hptr;

   if (0=win____GetDIBits(xdc,cbmp,0,dh,hptr,xinfo,DIB_RGB_COLORS)) then goto skipend;

   //read pixels
   if not missize(d,dw,dh) then goto skipend;

   for dy:=0 to (dh-1) do
   begin
   if not misscan82432(d,dy,dr8,dr24,dr32) then goto skipend;

   dpos:=(dh-1-dy)*drowsize;

   //32 -> 32
   if (sbits=32) and (dbits=32) then
      begin
      for dx:=0 to (dw-1) do
      begin
      xpull32;
      dr32[dx]:=c32;
      end;
      end
   //32 -> 24
   else if (sbits=32) and (dbits=24) then
      begin
      for dx:=0 to (dw-1) do
      begin
      xpull32;
      c24.r:=c32.r;
      c24.g:=c32.g;
      c24.b:=c32.b;
      dr24[dx]:=c24;
      end;
      end
   //32 -> 8
   else if (sbits=32) and (dbits=8) then
      begin
      for dx:=0 to (dw-1) do
      begin
      xpull32;
      if (c32.g>c32.r) then c32.r:=c32.g;
      if (c32.b>c32.r) then c32.r:=c32.b;
      dr8[dx]:=c32.r;
      end;
      end
   //24 -> 32
   else if (sbits=24) and (dbits=32) then
      begin
      for dx:=0 to (dw-1) do
      begin
      xpull24;
      c32.r:=c24.r;
      c32.g:=c24.g;
      c32.b:=c24.b;
      c32.a:=255;
      dr32[dx]:=c32;
      end;
      end
   //24 -> 24
   else if (sbits=24) and (dbits=24) then
      begin
      for dx:=0 to (dw-1) do
      begin
      xpull24;
      dr24[dx]:=c24;
      end;
      end
   //24 -> 8
   else if (sbits=24) and (dbits=8) then
      begin
      for dx:=0 to (dw-1) do
      begin
      xpull24;
      if (c24.g>c24.r) then c24.r:=c24.g;
      if (c24.b>c24.r) then c24.r:=c24.b;
      dr8[dx]:=c24.r;
      end;
      end;
   end;//dy

   //detect an empty mask and convert to a visible mask
   if mask__empty(d) then mask__setval(d,255);

   //successful
   result:=true;
   end;

//enhanced formats - 18mar2026
if (not result) and xenhancedformats and clip__canpastetext then
   begin
   try

   //init
   a.clear;

   //paste text
   if clip__pastetext2(@a) then
      begin

      //read text as image data (e.g. TEP v1)
      if mis__fromdata(d,@a,e) then
         begin

         result   :=true;

         end

      //read text as pascal array of byte
      else if mis__fromarrayBYTE(d,@a) then
         begin

         result   :=true

         end

      //read text as base64
      else if mis__frombase64(d,@a) then
         begin

         result   :=true

         end;

      end;

   except;end;
   end;

skipend:
except;end;
try

//clear on error
if not result then missize(d,1,1);

//free
if (hptr<>nil) then win____globalunlock(hmem);
if (hmem<>0)   then win____globalfree(hmem);
if (xdc<>0)    then win____deletedc(xdc);

//a
if (a<>nil) then a.ejectcore;//let go of global memory + unlock it -> only ever read-only from Clipboard supplied handle, so OK to eject an empty core - 09jun2025
str__free(@a);

//close clipboard
if xopened then win____CloseClipboard;

except;end;
end;

function clip__canpasteimagefrom(const xaltsource:tobject;const xenhancedformats:boolean):boolean;//12apr2021
var
   xbits,xw,xh:longint;
begin

case zzok(xaltsource,1021) of
true:result:=misok82432(xaltsource,xbits,xw,xh)
else result:=clip__canpasteimage(xenhancedformats);
end;//case

end;

function clip__pasteimagefrom(const d:tobject;const xaltsource:tobject;const xenhancedformats,xfit:boolean):boolean;//17mar2025, 12apr2021
begin
result:=clip__pasteimagefrom2(d,xaltsource,xenhancedformats,xfit,0,0);
end;

function clip__pasteimagefrom2(const d:tobject;const xaltsource:tobject;const xenhancedformats,xfit:boolean;xfitmaxW,xfitmaxH:longint):boolean;//29apr2025, 17mar2025, 14apr2021, 12apr2021
label
   skipend;
var
   a:tobject;
   aw,ah,xbits,xw,xh,ddw,ddh:longint;
begin
//defaults
result :=false;
a      :=nil;
ddw    :=1;
ddh    :=1;

//check
if zznil(d,2004)                                            then exit;
if not clip__canpasteimagefrom(xaltsource,xenhancedformats) then exit;

try
//range
xfitmaxW:=frcmin32(xfitmaxW,0);
xfitmaxH:=frcmin32(xfitmaxH,0);

//get
//.xaltsource -> a
if zzok(xaltsource,1022) then
   begin
   
   if not misok82432(xaltsource,xbits,xw,xh) then goto skipend;

   a:=misraw32(xw,xh);

   if (xw<>misw(a)) or (xh<>mish(a))                         then goto skipend;
   if mishasai(xaltsource) and (not misaicopy(xaltsource,a)) then goto skipend;

   if not mis__copyfast( maxarea ,area__make(0,0,xw-1,xh-1) ,0 ,0 ,xw ,xh ,xaltsource ,a ) then goto skipend;//fixed - 03apr2026, 14apr2021

   end
//.clipoard -> a
else
   begin

   a        :=misraw32(1,1);
   if not clip__pasteimage(a,xenhancedformats) then goto skipend;

   end;

//set
aw  :=misw(a);
ah  :=mish(a);
ddw :=aw;
ddh :=ah;

//.size
if xfit then
   begin
   //.stretch fit
   if (xfitmaxW=0) and (xfitmaxH=0) then
      begin
      ddw:=frcmin32(misw(d),1);
      ddh:=frcmin32(mish(d),1);
      end
   //.scale fit
   else if (xfitmaxW>=1) and (xfitmaxH>=1) then
      begin
      low__scaledown(xfitmaxW,xfitmaxH,aw,ah,ddw,ddh);
      end
   //.fixed width and variable height
   else if (xfitmaxW>=1) and (xfitmaxH=0) then
      begin
      ddw:=xfitmaxW;
      ddh:=frcmin32(round((xfitmaxW/frcmin32(aw,1))*ah),1);
      end
   //.fixed height and variable width
   else if (xfitmaxH>=1) and (xfitmaxW=0) then
      begin
      ddh:=xfitmaxH;
      ddw:=frcmin32(round((xfitmaxH/frcmin32(ah,1))*aw),1);
      end;
   end;

if (ddw<=0) or (ddh<=0) then goto skipend;
if ((ddw<>misw(d)) or (ddh<>mish(d))) and (not missize(d,ddw,ddh)) then goto skipend;

if not mis__copyfast( maxarea ,area__make(0,0,aw-1,ah-1) ,0 ,0 ,ddw ,ddh ,a ,d ) then goto skipend;//03apr2026

//Note: Any change in cellwidth/cellheight has to be modified
if mishasai(a) and mishasai(d) and (not misaicopy(a,d)) then goto skipend;

//successful
result:=true;
skipend:
except;end;

//free
freeobj(@a);

end;

function clip__cancopyimage:boolean;//12apr2021
begin
result:=true;
end;

function clip__copyimageAsArrayByte(const s:tobject;const dformat:string;const dShowSuccess:boolean):boolean;//18mar2026
var
   d,dtmp:tstr8;
   e:string;
begin

//defaults
result      :=false;
d           :=nil;
dtmp        :=nil;

//check
if not misokk82432(s) then exit;

try

//dformat - e.g. "png"
d        :=str__new8;
dtmp     :=str__new8;
mis__todata(s,@dtmp,dformat,e);

//array
if str__toarrayBYTE( @dtmp ,@d) and clip__copytext2( @d ) then
   begin

   if dShowSuccess and (app__gui<>nil) then app__gui.popstatus(low__mbAUTO2(str__len32(@d),1,true)+' of text copied to Clipboard',1);

   //successful
   result   :=true;

   end;

except;end;

//free
str__free(@dtmp);
str__free(@d);

end;

function clip__copyimageAsBase64(const s:tobject;dformat:string;const dShowSuccess:boolean):boolean;//18mar2026
var
   d:tstr8;
   e:string;
begin

//defaults
result      :=false;
d           :=nil;

//check
if not misokk82432(s) then exit;

try

//dformat - e.g. "png"
d        :=str__new8;

case strmatch(dformat,'gif') or strmatch(dformat,'ico') or strmatch(dformat,'png') of
true:;
else dformat:='png';
end;//case

mis__todata(s,@d,dformat,e);

//base64
if str__tob64(@d,@d,0) and d.sins('data:'+net__mimefind(dformat)+';base64,',0) and clip__copytext2( @d ) then
   begin

   if dShowSuccess and (app__gui<>nil) then app__gui.popstatus(low__mbAUTO2(str__len32(@d),1,true)+' of text copied to Clipboard',1);

   //successful
   result   :=true;

   end;

except;end;

//free
str__free(@d);

end;

function clip__copyimage(s:tobject):boolean;//10jun2025, 09jun2025, 26apr2025
label
   skipend;
var
   e:string;
   d:tstr8;
   sbits,sw,sh:longint;
   xopened,shasai:boolean;
begin
//defaults
result      :=false;
xopened     :=false;
d           :=nil;

try
//open clipboard
if not clip__openedAndclear(xopened) then goto skipend;

//init
if not misinfo(s,sbits,sw,sh,shasai) then goto skipend;
d:=str__new8;

//write PNG - only if image has transparent pixels - MS Paint for Win11 requires PNG, whereas Gimp v2.10.34 accepts PNG/DIB
if mask__hasTransparency32(s) then
   begin
   d.makeglobal;
   if not png__todata(s,@d,e)                      then goto skipend;
   if (0=win____setclipboarddata(cf_png,d.handle)) then goto skipend;
   d.ejectcore;
   end;

//write DIBv5
d.makeglobal;
//if not bmp32__todata3(s,@d,false,hsV05,low__aorb(32,24,misb(s)=24)) then goto skipend;
if not bmp32__todata3(s,@d,false,hsV05,32)          then goto skipend;
if (0=win____setclipboarddata(cf_dibv5,d.handle))   then goto skipend;//11jun2025: fixed
d.ejectcore;

//write DIBv1
d.makeglobal;
if not bmp32__todata3(s,@d,false,hsW95,24)      then goto skipend;//use old V1 header which has no transparency for backward compatibility such as WordPad on Win11 - 09jun2025
if (0=win____setclipboarddata(cf_dib,d.handle)) then goto skipend;
d.ejectcore;

//successful
result:=true;
skipend:
except;end;

//free
freeobj(@d);

//close clipboard
if xopened then win____CloseClipboard;

end;


//error messages ---------------------------------------------------------------
function gec__taskfailed(var e:string):boolean;//pass-thru support
begin
result:=true;
e:=gecTaskfailed;
end;


//history support --------------------------------------------------------------
function his__found(xname:string):boolean;
var
   int1:longint;
begin
result:=his__find(xname,int1);
end;

function his__find(xname:string;var xindex:longint):boolean;
var
   p:longint;
begin
//defaults
result:=false;
xindex:=0;

try
//check
if (xname='') then exit;
//fast find
if (syshis_last>=0) and (syshis_last<=high(syshis_nam)) and strmatch(xname,syshis_nam[syshis_last]) then
   begin
   xindex:=syshis_last;
   if (xindex>=0) and (xindex<=high(syshis_nam)) and (syshis_nam[xindex]<>'') then//27apr2021
      begin
      result:=true;
      exit;
      end;
   end;
//find
for p:=0 to high(syshis_nam) do
begin
if (syshis_nam[p]<>'') and strmatch(xname,syshis_nam[p]) then
   begin
   xindex:=p;
   syshis_last:=p;//fast find
   result:=true;
   break;
   end;
end;//p
except;end;
end;

function his__clear(xname:string):boolean;
var
   p,int1:longint;
begin
result:=true;

try
if his__find(xname,int1) then
   begin
   for p:=0 to high(syshis_val[int1]) do
   begin
   syshis_val[int1][p]:='';
   syshis_ref1[int1][p]:=0;
   syshis_ref2[int1][p]:=0;
   end;//p
   syshis_nam[int1]:='';
   end;
except;end;
end;

function his__canprev(xname:string):boolean;
var
   str1:string;
begin
result:=his__prev(xname,str1,false);
end;

function his__prev(xname:string;var xoutval:string;xmove:boolean):boolean;
var
   v1,v2:longint;
begin
result:=his__prev2(xname,xoutval,v1,v2,xmove);
end;

function his__prev2(xname:string;var xoutval:string;var v1,v2:longint;xmove:boolean):boolean;
var
   p,int1:longint;
begin

//defaults
result   :=false;
xoutval  :='';
v1       :=0;
v2       :=0;

try

//get
if his__find(xname,int1) then
   begin

   for p:=0 to high(syshis_val[int1]) do
   begin

   if (syshis_val[int1][p]='') then break
   else if (strcopy1x(syshis_val[int1][p],1,1)='A') then
      begin

      if (p>=1) and (syshis_val[int1][p-1]<>'') then
         begin

         if xmove then
            begin
            syshis_val[int1][p]    :='N'+strcopy1x(syshis_val[int1][p],2,low__len32(syshis_val[int1][p]));//mark normal
            syshis_val[int1][p-1]  :='A'+strcopy1x(syshis_val[int1][p-1],2,low__len32(syshis_val[int1][p-1]));//mark active
            end;

         xoutval                   :=strcopy1x(syshis_val[int1][p-1],2,low__len32(syshis_val[int1][p-1]));//return active value
         v1                        :=syshis_ref1[int1][p-1];
         v2                        :=syshis_ref2[int1][p-1];
         result                    :=true;

         end;

      break;

      end;

   end;//p
   end;

except;end;
end;

function his__cannext(xname:string):boolean;
var
   str1:string;
begin
result:=his__next(xname,str1,false);
end;

function his__next(xname:string;var xoutval:string;xmove:boolean):boolean;
var
   v1,v2:longint;
begin
result:=his__next2(xname,xoutval,v1,v2,xmove);
end;

function his__next2(xname:string;var xoutval:string;var v1,v2:longint;xmove:boolean):boolean;
var
   p,int1:longint;
begin
//defaults
result:=false;
xoutval:='';
v1:=0;
v2:=0;

try
//get
if his__find(xname,int1) then
   begin
   for p:=0 to high(syshis_val[int1]) do
   begin
   if (syshis_val[int1][p]='') then break
   else if (strcopy1x(syshis_val[int1][p],1,1)='A') then
      begin
      if (p<high(syshis_val[int1])) and (syshis_val[int1][p+1]<>'') then
         begin
         if xmove then
            begin
            syshis_val[int1][p]:='N'+strcopy1x(syshis_val[int1][p],2,low__len32(syshis_val[int1][p]));//mark normal
            syshis_val[int1][p+1]:='A'+strcopy1x(syshis_val[int1][p+1],2,low__len32(syshis_val[int1][p+1]));//mark active
            end;
         xoutval:=strcopy1x(syshis_val[int1][p+1],2,low__len32(syshis_val[int1][p+1]));//return active value
         v1:=syshis_ref1[int1][p+1];
         v2:=syshis_ref2[int1][p+1];
         result:=true;
         end;
      break;
      end;
   end;//p
   end;
except;end;
end;

function his__active(xname:string;var xoutval:string):boolean;
var
   v1,v2:longint;
begin
result:=his__active2(xname,xoutval,v1,v2);
end;

function his__active2(xname:string;var xoutval:string;var v1,v2:longint):boolean;
var
   p,int1:longint;
begin
//defaults
result:=false;
xoutval:='';
v1:=0;
v2:=0;

try
//get
if his__find(xname,int1) then
   begin
   for p:=0 to high(syshis_val[int1]) do
   begin
   if (syshis_val[int1][p]='') then break
   else if (strcopy1x(syshis_val[int1][p],1,1)='A') then
      begin
      xoutval:=strcopy1x(syshis_val[int1][p],2,low__len32(syshis_val[int1][p]));//return active value
      v1:=syshis_ref1[int1][p];
      v2:=syshis_ref2[int1][p];
      result:=true;
      break;
      end;
   end;//p
   end;
except;end;
end;

function his__setactiveref(xname:string;v1,v2:longint):boolean;//sets ref of active item
var
   p,int1:longint;
begin
result:=false;

try
if his__find(xname,int1) then
   begin
   for p:=0 to high(syshis_val[int1]) do
   begin
   if (syshis_val[int1][p]='') then break
   else if (strcopy1x(syshis_val[int1][p],1,1)='A') then
      begin
      syshis_ref1[int1][p]:=v1;
      syshis_ref2[int1][p]:=v2;
      result:=true;
      break;
      end;
   end;//p
   end;
except;end;
end;

function his__add(xname,xval:string):boolean;
begin
result:=his__add2(xname,xval,0,0,false);
end;

function his__add2(xname,xval:string;v1,v2:longint;xstorev12:boolean):boolean;
label
   skipend;
var
   p,int1,int2:longint;
begin
//defaults
result:=false;
int1:=-1;

try
//check
if (xname='') then exit;

//find existing OR create new
if his__find(xname,int2) then int1:=int2
else
   begin//new
   for p:=0 to high(syshis_nam) do if (syshis_nam[p]='') then
      begin
      int1:=p;
      syshis_nam[p]:=xname;
      //init -> clear all values if any still present
      for int2:=0 to high(syshis_val[int1]) do
      begin
      syshis_val[int1][int2]:='';
      syshis_ref1[int1][int2]:=0;
      syshis_ref2[int1][int2]:=0;
      end;//int2
      break;
      end;//p
   end;

//check
if (int1<=-1) then exit;

//add
for p:=0 to high(syshis_val[int1]) do
begin
if (syshis_val[int1][p]='') then
   begin
   syshis_val[int1][p]:='A'+xval;
   if xstorev12 then
      begin
      syshis_ref1[int1][p]:=v1;
      syshis_ref2[int1][p]:=v2;
      end;
   result:=true;
   break;
   end
else if (strcopy1x(syshis_val[int1][p],1,1)='A') then
   begin
   //check -> already active
   if strmatch(syshis_val[int1][p],'A'+xval) then
      begin
      if xstorev12 then
         begin
         syshis_ref1[int1][p]:=v1;
         syshis_ref2[int1][p]:=v2;
         end;
      result:=true;
      goto skipend;
      end;
   //mark normal
   syshis_val[int1][p]:='N'+strcopy1x(syshis_val[int1][p],2,low__len32(syshis_val[int1][p]));//mark normal
   //add - have room
   if (p<high(syshis_val[int1])) then
      begin
      syshis_val[int1][p+1]:='A'+xval;
      if xstorev12 then
         begin
         syshis_ref1[int1][p+1]:=v1;
         syshis_ref2[int1][p+1]:=v2;
         end;
      //.wipe out any forward facing items
      if ((p+2)<=high(syshis_val[int1])) then
         begin
         for int2:=p+2 to high(syshis_val[int1]) do
         begin
         syshis_val[int1][int2]:='';
         syshis_ref1[int1][int2]:=0;
         syshis_ref2[int1][int2]:=0;
         end;//int2
         end;
      result:=true;
      end
   //add - make room
   else
      begin
      //shift up one
      for int2:=1 to high(syshis_val[int1]) do
      begin
      syshis_val[int1][int2-1]:=syshis_val[int1][int2];
      syshis_ref1[int1][int2-1]:=syshis_ref1[int1][int2];
      syshis_ref2[int1][int2-1]:=syshis_ref2[int1][int2];
      end;//p
      //set
      syshis_val[int1][p]:='A'+xval;
      syshis_ref1[int1][p]:=low__insint(v1,xstorev12);
      syshis_ref2[int1][p]:=low__insint(v2,xstorev12);
      result:=true;
      end;
   //stop
   break;
   end;
end;//p

skipend:
except;end;
end;

procedure low__showhelp(dshow:boolean);//13mar2025, 03nov2023
var
   a:tbasicapp;
begin
try
{//was:
//create
dw:=700;
dh:=600;
if zznil(programhelpviewer,2040) then
   begin
   //range
   if (dw<=0) then dw:=700;
   if (dh<=0) then dh:=700;
   //get
   programhelpviewer:=thelpviewer.create;
   programhelpviewer.setsize(dw,dh);
   end;
//show
programhelpviewer.center;
programhelpviewer.show;
{}

//filter
if ((sizeof(apphelp)<2) and (sizeof(syshelp)<2)) or (not viMaster) then dshow:=false;//13mar2025: updated to check dual help streams

//now:
if (system_program<>nil) then
   begin
   //init
   a:=system_program;
   //get
   case dshow of
   true:begin
      if not a.rootwin.xhavemainhelp then a.rootwin.xmainhelp;
      a.rootwin.rightvisible:=dshow;
      end;
   else if a.rootwin.xhavemainhelp then a.rootwin.rightvisible:=dshow;
   end;//case
  //.set style here
  a.rootwin.rightmax:=vihelp_max;
   //store
   if (dshow<>vihelp_show) and visyssettingsloaded then
      begin
      syssettings.b['help.show']:=dshow;
      visyncandsave;
      end;
   end;
except;end;
end;

function low__vol(var xfilename:string):boolean;//check once only - 10OCT2010
label
   skipdone;
var
   z:string;
begin
//defaults
result:=false;

try
xfilename:='';
//get
if (sys_sndvol32='') then
   begin
   //Vista
   //.1
   z:=io__winsystem+'SNDVOL.EXE';
   if io__fileexists(z) then goto skipdone;
   //.2
   z:=io__winroot+'SNDVOL.EXE';
   if io__fileexists(z) then goto skipdone;
   //XP
   z:=io__winsystem+'SNDVOL32.EXE';
   if io__fileexists(z) then goto skipdone;
   //Win98
   z:=io__winroot+'SNDVOL32.EXE';
   if io__fileexists(z) then goto skipdone;
   //set
   skipdone:
   if not io__fileexists(z) then z:='?';//mark as not found - 10mar2021
   sys_sndvol32:=z;
   end;
//set
if (sys_sndvol32<>'') and (sys_sndvol32<>'?') then
   begin
   xfilename:=sys_sndvol32;
   result:=true;
   end;
except;end;
end;

function low__canshowvol:boolean;
var
   str1:string;
begin
result:=low__vol(str1);
end;

procedure low__showvol;
var
   str1:string;
begin
if low__vol(str1) then runlow(str1,'');
end;

function stableobj(x:tobject):boolean;//07mar2021
begin
if zznil(x,2050)             then result:=false
else if (x is tbasicsystem)  then result:=((x as tbasicsystem).stable =0)//25dec2025
else if (x is tbasiccontrol) then result:=((x as tbasiccontrol).stable=0)//25dec2025
else                              result:=false;
end;

procedure low__sysadd(x:tobject);
var
   p:longint;
begin
try
if (x<>nil) then
   begin
   //check for existing
   for p:=0 to high(syslist) do if (x=syslist[p]) then exit;
   //add
   for p:=0 to high(syslist) do if (nil=syslist[p]) then
      begin
      syslist[p]:=x;
      break;
      end;//p
   end;
except;end;
end;

procedure low__sysdel(x:tobject);
var
   p:longint;
begin
try
if (x<>nil) then
   begin
   //find
   for p:=0 to high(syslist) do if (x=syslist[p]) then
      begin
      syslist[p]:=nil;
      break;
      end;//p
   end;
except;end;
end;

function low__closecount:longint;
var
   p:longint;
begin
//defaults
result:=sysclose_count;

try;for p:=0 to high(syslist) do if zzok(syslist[p],1030) and (syslist[p] is tbasicsystem) then inc(result,(syslist[p] as tbasicsystem).closelocked);except;end;
end;

procedure low__closelock;
begin
if (sysclose_count<max32) then inc(sysclose_count,1);
end;

procedure low__closeunlock;
begin
if (sysclose_count>min32) then sysclose_count:=frcmin32(sysclose_count-1,0);
end;

function sifindframe(xname:string):string;//07jun2022
label
   redo;
var
   xtrycount,p:longint;
   str1:string;
begin
//defaults
result:='';

try
xtrycount:=0;
//find
redo:
for p:=0 to (system_framecount-1) do if strmatch(xname,system_framename[p]) then
   begin
   result:=system_framecode[p];
   break;
   end;
//check
if (result='') then
   begin
   //default frame name
   str1:=app__info('frame.name');
   if (str1<>'') then
      begin
      xname:=str1;
      //.emergency fallback - fixed - 07jun2022
      inc(xtrycount);
      if (xtrycount<=2) then goto redo;
      end;
   //fallback default
   if (result='') then result:='100,ss,dd';//modern
   end;
except;end;
end;

procedure siframes;//11oct2022

   procedure xadd(xname,xcode:string);
   begin
   try
   //check
   if (xname='') or (xcode='') or (system_framecount>high(system_framename)) then exit;
   //get
   system_framename[system_framecount]:=xname;
   system_framecode[system_framecount]:=xcode;
   inc(system_framecount);
   except;end;
   end;
begin
try
//check
if (system_framecount>=1) then exit;
//get

xadd('Antique'        ,'m24|20,s,d|10,d,ds20|30,ds20,ds70|30,ds70,ds50|100,ds50,s');
xadd('Antique 2'      ,'m30|30,s,ds10|10,ds10,ds20|20,ds20,ds70|20,ds70,ds50|10,ds50,d|100,d,s');
xadd('Antique 3'      ,'m30|20,s,d|10,d,ds20|20,ds20,ds70|20,ds70,ds50|10,ds50,s|100,s,s');
xadd('Traditional'    ,'m16|80,ss,dd|100,dd,ss');
xadd('Traditional 2'  ,'m16|70,ss,dd|100,dd,ss');
xadd('Traditional 3'  ,'m16|50,ss,dd|10,dd,ss|35,ss,ss|100,dd,dd');
xadd('Traditional 4'  ,'m26|85,s,d|8,d,s|100,s,s');
xadd('Traditional 5'  ,'m26|70,s,d|8,d,s|100,s,s');
xadd('Flat'           ,'m32|20,ss,dd|8,dd,ss|65,ss,ss|100,dd,dd');
xadd('Flat 2'         ,'m22|10,ss,dd|4,dd,ss|82,ss,ss|100,dd,dd');
xadd('Flat 3'         ,'m22|95,ss,sd10|100,dd,dd');
xadd('Flat 4'         ,'m22|95,ss,sd30|100,dd,dd');
xadd('Flat 5'         ,'m22|95,sd30,ss|100,dd,dd');
xadd('Flat 6'         ,'m16|50,s,d|30,d,d|100,d,s');
xadd('Flat 7'         ,'m16|20,s,d|50,d,d|100,d,s');
xadd('Flat 8'         ,'m24|20,s,d|70,d,d|100,d,s');

xadd('Minimal'         ,'m5|20,s,d|100,d,d');
xadd('Minimal 2'       ,'m5|10,s,d|100,d,d');
xadd('Minimal 3'       ,'m5|20,d,s|100,s,s');
xadd('Minimal 4'       ,'m5|10,d,s|100,s,s');

xadd('Narrow'         ,'m5|60,s,d|100,d,d');
xadd('Narrow 2'       ,'m5|60,d,s|100,s,s');

xadd('Null'            ,'m5|100,s,s');
xadd('Null 2'          ,'m5|100,d,d');

xadd('Modern'         ,'m5|100,sb60,d');
xadd('Modern 2'       ,'m5|100,s,d');
xadd('Classic'        ,'m40|10,sb60,dd|20,dd,sb60|30,sb80,sb80|5,dd,sb60|5,dd,sb60|100,dd,sb60');
xadd('Classic 2'      ,'m40|10,sb60,dd|20,dd,ss60|30,ss80,ss80|5,dd,sb60|5,dd,sb60|100,dd,ss');
xadd('Classic 3'      ,'m40|10,sw60,dd|20,dd,ss60|30,ss80,ss80|8,dd,sd60|8,dd,sd60|100,dd,ss');
xadd('Lines'          ,'m22|10,ss,dd|5,dd,ss|30,ss,ss|5,dd,dd|30,ss,ss|5,dd,dd|30,ss,ss|100,dd,dd');
xadd('Lines 2'        ,'m22|10,ss,dd|5,dd,ss|20,ss,ss|5,dd,dd|20,ss,ss|5,dd,dd|20,ss,ss|5,dd,dd|20,ss,ss|100,dd,dd');
xadd('Double'         ,'m10|50,ss,dd50|12,dd50,db50|100,db50,dd');
xadd('Double 2'       ,'m24|30,ss,dd50|8,dd50,db50|20,db50,db70|100,db70,dd');
xadd('Double 3'       ,'m24|30,ss,dd50|8,dd50,sd50|20,sd50,sd70|100,sd70,dd');
xadd('Double 4'       ,'m24|30,ss,dd|8,dd,sd50|50,sd50,sd70|100,sd70,dd');
xadd('Double 5'       ,'m27|40,s,d|8,d,s|30,s,s|8,s,d|100,d,s');
xadd('Double 6'       ,'m16|20,s,d|20,d,s60|30,s60,s60|20,s60,d|100,d,s');
xadd('Stacked'        ,'m20|30,s,d|8,d,s|30,s,d|8,d,s|30,s,d|100,d,sd50');
xadd('Stacked 2'      ,'m20|20,s,d|8,d,s|20,s,d|8,d,s|20,s,d|8,d,s|20,s,d|100,d,sd50');
xadd('Stacked 3'      ,'m20|15,s,d|8,d,s|15,s,d|8,d,s|15,s,d|8,d,s|15,s,d|8,d,s|15,s,d|100,d,sd50');
xadd('Stacked 4'      ,'m20|10,s,d|7,d,s|10,s,d|7,d,s|10,s,d|7,d,s|10,s,d|7,d,s|10,s,d|7,d,s|10,s,d|100,d,sd50');
xadd('Stacked 5'      ,'m20|10,s,d|6,d,s|10,s,d|7,d,s|10,s,d|7,d,s|10,s,d|7,d,s|10,s,d|7,d,s|10,s,d|7,d,s|10,s,d|100,d,sd50');
xadd('Fuzz'           ,'m10|50,dd,ss50|15,ss50,sb50|100,sb50,sw50');
xadd('Fuzz 2'         ,'m20|50,dd,ss50|15,ss50,sw50|100,sw50,sb50');
xadd('Fuzz 3'         ,'m20|50,dd,ss50|15,ss50,sw50|100,sw50,sw50');
xadd('Old World'      ,'m14|50,ss,dd|100,dd,ss');
xadd('Modern Insert'  ,'m40|20,sb62,dd|56,d,sb62|17,sb55,sb55|8,sb55,dd|100,d,d');
xadd('Gallery'        ,'m22|10,ss60,dd|10,dd,sb60|67,ss80,ss80|8,sb80,dd|100,dd,sb100');
xadd('Gallery 2'      ,'m22|10,ss60,dd|10,dd,sb60|67,ss80,sb80|8,sb80,dd|100,dd,sb100');
xadd('Gallery 3'      ,'m22|10,ss60,dd|10,dd,sb60|67,sb70,ss70|8,ss70,dd|100,dd,sb100');
except;end;
end;


function sicolors_name(xpos:longint;var xname:string):boolean;
begin
result:=(xpos>=0) and (xpos<system_colorcount);
if result then xname:=system_colorname[xpos];
end;

function sicolors_find(xname:string;var xdata:tlistptr;var val1:longint):boolean;
var
   p:longint;
begin
//defaults
result:=false;
xdata.count:=0;
val1:=0;

//check
if (system_colorcount<=0) or (xname='') then exit;

//find
for p:=0 to (system_colorcount-1) do
begin
if strmatch(xname,system_colorname[p]) then
   begin
   result:=true;
   xdata:=system_colordata[p];
   val1 :=system_colorval1[p];
   break;
   end;
end;//p
end;

procedure sicolors;//28aug2025, 28jul2024
var
   xnames:tdynamicvars;

   procedure a2(n:string;const v:array of byte;val1:longint);
   label
      redo;
   var
      dn:string;
      nc:longint;
   begin
   //check
   if (n='') or (system_colorcount>high(system_colorname)) then exit;

   //duplicate name check
   nc:=1;
   dn:=n;
   redo:
   if (nc<=50) and xnames.found(dn) then
      begin
      inc(nc);
      dn:=n+#32+intstr32(nc);
      goto redo;
      end;

   //store
   xnames.value[dn]:='1';

   //get
   system_colorname[system_colorcount]:=dn;
   system_colordata[system_colorcount]:=low__maplist(v);
   system_colorval1[system_colorcount]:=val1;

   //inc
   inc(system_colorcount);
   end;

   procedure a(n:string;const v:array of byte);
   begin
   a2(n,v,0);
   end;

   procedure a3(n:string;const v:array of byte;val1:longint);//09sep2025
   begin

   a2(n,v,0);
   a2(n,v,30);

   end;

begin
try
//defaults
xnames:=nil;

//check
if (system_colorcount>=1) then exit;

//init
xnames:=tdynamicvars.create;

//get
a2('Aqua Marine',      cols_Aqua_Marine,0);

a2('Army',cols_army,0);

a2('Burnt Yellow',cols_BurntYellow,0);
a2('Burnt Yellow',cols_BurntYellow,20);
a2('Burnt Red',cols_BurntRed,0);
a2('Burnt Red',cols_BurntRed,20);
a2('Burnt Purple',    cols_BurntPurple,0);//11oct2022
a2('Burnt Purple',    cols_BurntPurple,20);
a2('Burnt Orange',    cols_BurntOrange,0);//11oct2022
a2('Burnt Orange',    cols_BurntOrange,20);
a2('Brown',           cols_brown,0);
a2('Brown',           cols_brown,10);
a2('Brown',           cols_brown2,0);
a2('Brown',           cols_brown3,0);
a2('Blue',            cols_blue,0);
a2('Blue',            cols_blue,6);

a3('Dos Editor',      cols_dos,0);//03mar2026

a3('Deep Purple',     cols_deep_purple,0);//28aug2025
a3('Deep Purple',     cols_deep_purple2,0);//09sep2025

a3('Deep Pink',       cols_deep_pink,0);//09sep2025
a3('Deep Pink',       cols_deep_pink2,0);//09sep2025

a3('Deep Candy Pink', cols_deep_candypink,0);//13sep2025
a3('Deep Candy Pink', cols_deep_candypink2,0);//13sep2025

a3('Deep Red',        cols_deep_red,0);//09sep2025
a3('Deep Red',        cols_deep_red2,0);

a3('Deep Yellow',     cols_deep_yellow,0);//09sep2025
a3('Deep Yellow',     cols_deep_yellow2,0);//09sep2025

a3('Deep Orange',     cols_deep_orange,0);//09sep2025
a3('Deep Orange',     cols_deep_orange2,0);

a3('Deep Blue',       cols_deep_blue,0);//13sep2025
a3('Deep Blue',       cols_deep_blue2,0);//13sep2025

a3('Deep Royal Blue', cols_deep_royal_blue,0);//09sep2025
a3('Deep Royal Blue', cols_deep_royal_blue2,0);//09sep2025

a3('Deep Aqua',       cols_deep_aqua,0);//13sep2025
a3('Deep Aqua',       cols_deep_aqua2,0);//13sep2025

a3('Deep Green',      cols_deep_green,0);//09sep2025
a3('Deep Green',      cols_deep_green2,0);//09sep2025

a3('Deep Lime',       cols_deep_lime,0);//13sep2025
a3('Deep Lime',       cols_deep_lime2,0);//13sep2025


a2('Light and Blue',   cols_light_and_blue,0);//05sep2025
a2('Light and Lilac',  cols_light_and_lilac,0);//14sep2025
a2('Light and Pink',   cols_light_and_pink,0);//14sep2025
a2('Light and Warm',   cols_light_and_warm,0);//14sep2025
a2('Light and Salmon', cols_light_and_salmon,0);//14sep2025
a2('Light and Grey',   cols_light_and_grey,0);//14sep2025
a2('Light and Aqua',   cols_light_and_aqua,0);//14sep2025
a2('Light and Orange', cols_light_and_orange,0);//24oct2025
a2('Light and Lime',   cols_light_and_lime,0);//24oct2025
a2('Light and Mustard',cols_light_and_mustard,0);//24oct2025

a2('Black and Pink',   cols_black_and_pink,0);//24oct2025
a2('Black and Orange', cols_black_and_orange,0);//24oct2025
a2('Black and Aqua',   cols_black_and_aqua,0);//24oct2025


a2('Eerie',           cols_Eerie,-20);//11oct2022
a2('Eerie',           cols_Eerie,0);
a2('Soft Green',      cols_Soft_Green,0);
a2('Fine Grey',       cols_Fine_Grey,0);
a2('Fine Grey',       cols_Fine_Grey2,0);

a2('Marine',          cols_Marine,0);
a2('Lilac',           cols_Lilac,0);
a2('Gold',            cols_Gold3,0);//09sep2025
a2('Gold',            cols_Gold,0);
a2('Gold',            cols_Gold2,0);
a2('Silver Gold',     cols_Silver_Gold,0);
a2('Grey',            cols_Grey,0);
a2('Soft Blue',       cols_Soft_Blue,0);
a2('Emerald',         cols_Emerald,0);
a2('Washed Crimson',  cols_Washed_Crimson,0);
a2('Dusty Pink',      cols_Dusty_Pink,0);
a2('Golden Sands',    cols_Golden_Sands,0);
a2('Fern',            cols_Fern,0);
a2('Fern',            cols_Fern,5);
a2('Tangerine',       cols_Tangerine,0);
a2('Tangerine',       cols_Tangerine,10);

//.new built-in colors - 09may2021
a2('Pale Yellow',     cols_Pale_Yellow,0);
a2('Moon Blue',       cols_Moon_Blue,0);
a2('Howdy Brown',     cols_Howdy_Brown,0);
a2('Chirpy Charcoal', cols_Chirpy_Charcoal,30);

a3('Dark Red Tint',   cols_DarkRedTint,0);//09sep2025
a3('Dark Red Tint',   cols_DarkRedTint2,0);//09sep2025

a3('Dark Blue Tint',  cols_DarkBlueTint,0);//09sep2025
a3('Dark Blue Tint',  cols_DarkBlueTint2,0);//02may2022

a3('Dark Green Tint', cols_DarkGreenTint,0);//09sep2025
a3('Dark Green Tint', cols_DarkGreenTint2,0);//09sep2025

a3('Dark Yellow Tint',cols_DarkYellowTint,0);//09sep2025
a3('Dark Yellow Tint',cols_DarkYellowTint2,0);//09sep2025

a3('Dark Aqua Tint',  cols_DarkAquaTint,0);//09sep2025
a3('Dark Aqua Tint',  cols_DarkAquaTint2,0);//02may2022

a3('Dark Emerald',    cols_DarkEmerald,0);//09sep2025
a3('Dark Emerald',    cols_DarkEmerald2,0);

a2('Dreamy Cream',    cols_Dreamy_Cream2,0);//09sep2025
a2('Dreamy Cream',    cols_Dreamy_Cream,0);

a2('Gentle Ginger',   cols_Gentle_Ginger2,0);//09sep2025
a2('Gentle Ginger',   cols_Gentle_Ginger,0);

a2('Glowing Grey',    cols_Glowing_Grey2,0);//09sep2025
a2('Glowing Grey',    cols_Glowing_Grey,0);

a2('Grumpy Green',    cols_Grumpy_Green,0);
a2('Jovial Mauve',    cols_Jovial_Mauve,0);
a2('Luscious Lilac',  cols_Luscious_Lilac,0);
a2('Slinky Pink',     cols_Slinky_Pink,0);
a2('Slinky Pink',     cols_Slinky_Pink,10);
a2('Rosebud Pink',    cols_Rosebud_Pink,0);
a2('Silky Sand',      cols_Silky_Sand,0);
a2('Red',             cols_Red,0);
a2('Radiant Yellow',  cols_Radiant_Yellow,0);
a2('Peach',           cols_Peach,0);
a2('Pink',            cols_pink,0);
a2('Pink',            cols_pink,10);
a2('Tangy Tangerine', cols_Tangy_Tangerine,0);
a2('Tangy Tangerine', cols_Tangy_Tangerine,20);
a2('White and Pale',  cols_white_and_pale,0);
a2('Wild Thing',      cols_Wild_Thing,0);//31may2021
a2('Wild Thing Pastel',cols_Wild_Thing_Pastel,0);//28jul2024

a2('Black',           cols_Black,0);//26aug2021
a2('Black',           cols_Black,20);//26aug2021
a2('Black',           cols_Black2,0);//23nov2024
a2('Black',           cols_Black2,20);//23nov2024
a2('Black',           cols_Black3,0);//23nov2024
a2('Black',           cols_black4,0);//12mar2025
a2('Black',           cols_black5,0);//06may2025
a2('Black',           cols_black5,20);//06may2025

a2('White',           cols_White,0);//26aug2021
a2('White',           cols_White2,0);//20jul2024
a2('White',           cols_White3,0);//10aug2024
a2('White',           cols_White4,0);//10aug2024
a2('White',           cols_white5,0);//24mar2025
a2('White',           cols_white6,0);//06may2025
a2('White',           cols_white7,0);//06may2025

a2('Wild Mix',        cols_Wild_Mix,0);//26aug2021
a2('Royal Blue',      cols_royal_blue,0);//26aug2021
a2('Royal Blue',      cols_royal_blue,20);//26aug2021
a2('Satin Pink',      cols_satinpink,0);//15mar2021
a2('Satin Pink',      cols_satinpink,10);//15mar2021
a2('Satin Pink',      cols_satinpink2,0);//05feb2025
//.purple
a2('Purple',          cols_purple,0);//01aug2024, 07jun2022

except;end;

//free
freeobj(@xnames);

end;

procedure siCloseprompt(x:tbasicsystem);
begin
try
//check
if gui__closing or sicloseprompting or (x=nil) then exit;
sicloseprompting:=true;

//prompt
case (not x.mustcloseprompt) or x.popquery2(ntranslate('Close app?'),'','Close App',false) of
true:app__startclose;//no need to reset because we are now closing down - 26aug2021
else sicloseprompting:=false;//cancelled -> reset and allow for another attempt
end;

except;end;
end;

function siLoadsyssettings:boolean;
var
   a:tstr8;
   e:string;
begin

//defaults
result :=false;
a      :=nil;

try
//init
a      :=str__new8;
result :=io__fromfile(low__platsyssettings,@a,e);

//get
if viMaster then result:=io__fromfile(low__platsyssettings,@a,e) else result:=a.add(sysmore.d['_syssettings']);

if viMaster and (not result) then viAppFirstRun:=true;

if zzok(syssettings,1041) then
   begin

   //load
   siLoadsyssettingsfrom(a);

   //loaded
   visyssettingsloaded:=true;

   end;

except;end;

//free
str__free(@a);

end;

function siLoadprgsettings:boolean;
var
   a:tstr8;
   e:string;
begin

//defaults
result :=false;
a      :=nil;

try
//init
a     :=str__new8;

if viMaster then result:=io__fromfile(low__platprgsettings,@a,e) else result:=a.add(sysmore.d['_prgsettings']);

if zzok(prgsettings,1042) then
   begin

   zzvars(prgsettings,110);

   prgsettings.data     :=a;
   zzstr(a,111);

   viprgsettingsloaded  :=true;
   vimustloadid         :=true;
   vimustsync           :=true;

   end;

except;end;

//free
str__free(@a);

end;

procedure siLoadsyssettingsfrom(x:tstr8);
var
   v:array[-1..(cnCustomLimit-1)] of string;
   p:longint;
begin
try
//init
str__lock(@x);//allow x to be nil
//get
if zzok(syssettings,1044) then
   begin
   //02aug2024: retain custom schemes when applying defaults -> under some circumstances, e.g. clicking the "Restore Defaults" button twice will wipe the custom color schemes previously
   if (x=nil) then
      begin
      v[-1]:=syssettings.s['?paste_and_use'];
      for p:=0 to (cnCustomLimit-1) do v[p]:=syssettings.s['?custom'+intstr32(p)];
      end;
   //get
   syssettings.data:=x;

   //.re-apply retained custom schemes
   if (x=nil) then
      begin
      syssettings.s['?paste_and_use']:=v[-1];
      for p:=0 to (cnCustomLimit-1) do syssettings.s['?custom'+intstr32(p)]:=v[p];
      end;

   //.sysback support
   sysback__loadfrom(syssettings,true);

   //.filter
   siFiltersettings(syssettings);
   zzvars(syssettings,116);
   //done
   vimustloadid:=true;
   vimustsync:=true;
   end;
except;end;
try;str__uaf(@x);except;end;
end;

procedure siLoadprgsettingsfrom(x:tstr8);
begin
try
//init
str__lock(@x);//allow x to be nil
//get
if zzok(prgsettings,1045) then
   begin
   zzvars(prgsettings,117);
   prgsettings.data:=x;
   vimustloadid:=true;
   vimustsync:=true;
   end;
except;end;
try;str__uaf(@x);except;end;
end;

function siSavesyssettings:boolean;
var
   e:string;
begin

if (app__gui<>nil) then app__gui.xsavePosSize;//13dec2025

result:=zzok(syssettings,1046) and zzok(syssettings,1047) and viMaster and io__tofile(low__platsyssettings,cache__ptr(syssettings.data),e);

end;

function siSaveprgsettings:boolean;
var
   e:string;
begin
result:=zzok(prgsettings,1048) and zzok(prgsettings,1049) and viMaster and io__tofile(low__platprgsettings,cache__ptr(prgsettings.data),e);
end;

procedure siSaveallsettings;//23mar2022
begin

//.save program based settings so new instance has the up-to-date information to run - 05mar2022
if (system_program<>nil) then system_program.xsavesettings else siSaveprgsettings;

//.save system based settings
siSavesyssettings;

end;

function siFontname2_deffont:string;//11dec2024, 12jun2022
begin
result:=strdefb(app__info('font2.name'),'Courier New');
end;

function siFiltersettings(x:tvars8):boolean;
var
   a:tvars8;
   xwinemode,p:longint;
   str1:string;
   xwinedefaults,xwine:boolean;

   procedure bset(xname:string;xdef,xval:boolean);
   begin

   //def
   if not a.found(xname) then
      begin
      a.b[xname]:=xdef;
      result:=true;
      end

   //val in range
   else if (a.b[xname]<>xval) then
      begin
      a.b[xname]:=xval;
      result:=true;
      end;

   //sync
   x.value[xname]:=a.value[xname];

   end;

   procedure iset(xname:string;xmin,xmax,xdef,xval:longint);
   begin

   xdef  :=frcrange32(xdef,xmin,xmax);
   xval  :=frcrange32(xval,xmin,xmax);

   //def
   if not a.found(xname) then
      begin
      a.i[xname]:=xdef;
      result:=true;
      end

   //val in range
   else if (a.i[xname]<>xval) then
      begin
      a.i[xname]:=xval;
      result:=true;
      end;

   //sync
   x.i[xname]:=a.i[xname];

   end;

   procedure sset(xname,xdef,xval:string);
   begin

   //def
   if not a.found(xname) then
      begin
      a.s[xname]:=xdef;
      result:=true;
      end

   //val in range
   else if (a.s[xname]<>xval) then
      begin
      a.s[xname]:=xval;
      result:=true;
      end;

   //sync
   x.s[xname]:=a.s[xname];

   end;

begin

//defaults
result                     :=false;
a                          :=nil;

try
//check
if zznil(x,2060) then exit;

//init -------------------------------------------------------------------------
a                          :=vnew2(955);
a.data                     :=zzvars(x,133).data;
x.clear;

//.set best Wine based defaults
xwineDefaults              :=not a.found('winemode');

//get --------------------------------------------------------------------------

//color
str1                       :=a.value['colorname'];
if not low__setcolorsbyname(str1,nil,nil,nil) then str1:='?Default';
sset('colorname',str1,str1);

//fontname
sset('fontname'   ,font__defaultname1,strdefb(a.value['fontname']   ,font__defaultname1));//11dec2024

//fontname.c
sset('fontname.c' ,'Arial',strdefb(a.value['fontname.c'] ,'Arial'));

//fontname2
sset('fontname2'  ,font__defaultname2,strdefb(a.value['fontname2']  ,font__defaultname2));//12jun2022

//fontname2.c
sset('fontname2.c',font__defaultname2,strdefb(a.value['fontname2.c'],font__defaultname2));//12jun2022

//bordersize -> do before anything else as it affects the MAX FONT ZOOM permitted - 07jun2021
iset('bordersize',0,72,strint32(app__info('bordersize')),a.i['bordersize']);
vibordersize__temp         :=frcmin32(x.i['bordersize'],0);//07jun2021

//fontsize
iset('fontsize' ,6,72,frcrange32(strint32(app__info('font.size')) ,6,72),a.i['fontsize']);//11dec2024, 05sep2020
iset('fontsize2',6,72,frcrange32(strint32(app__info('font2.size')),6,72),a.i['fontsize2']);//11dec2024, 12jun2022, 26feb2022, 05feb2022

//framename
sset('framename','default',a.value['framename']);//23feb2022
if (viframecode=nil) then viframecode:=str__new8;

//backname
sset('backname','default',a.value['backname']);//21jul2024

//other
bset('startlink',false,a.b['startlink']);//def=OFF - 24aug2020
bset('desktoplink',false,a.b['desktoplink']);//def=OFF
bset('startuplink',false,a.b['startuplink']);//def=OFF
iset('startstyle',0,3,0,a.i['startstyle']);//18jan2025, 09dec2023
bset('modern',strbol(app__info('modern')),a.b['modern']);//27may2025

bset('touch',false,a.b['touch']);
bset('doubleclicks',true,a.b['doubleclicks']);//08oct2020
bset('round',true,a.b['round']);
bset('multimonitor',false,a.b['multimonitor']);

bset('headcenter',strbol(app__info('head.center')),a.b['headcenter']);//11oct2022
iset('headalign',0,2,strint32(app__info('head.align')),a.i['headalign']);//0=left, 1=center, 2=right

bset('dragfast',false,a.b['dragfast']);
bset('softclose',true,a.b['softclose']);
bset('framemax',strbol(app__info('frame.max')),a.b['framemax']);//04mar2022, 14mar2021
bset('ecomode',strbol(app__info('ecomode')),a.b['ecomode']);//09may2021
bset('32bit',true,a.b['32bit']);//09may2021

//was: bset('lockposition',false,a.b['lockposition']);//27feb2022
iset('winemode',0,2,0,a.i['winemode']);//0=auto, 1=enable, 2=disable - 02feb2022
bset('realtimehelp',strbol(app__info('realtimehelp')),a.b['realtimehelp']);
bset('hint',strbol(app__info('hint')),a.b['hint']);//25dec2024
bset('ontop',false,a.b['ontop']);
bset('retainpos',false,a.b['retainpos']);//13dec2025
iset('mididevice',low(mmsys_mid_deviceok),high(mmsys_mid_deviceok),mmsys_mid_midimapper,a.i['mididevice']);//09sep2025, 05mar2022
iset('wavedevice',0,99,0,a.i['wavedevice']);//05mar2022
bset('help.bw',false,a.b['help.bw']);//04dec2024, 24jul2021
bset('help.show',false,a.b['help.show']);//04dec2024, 24jul2021
bset('help.max',false,a.b['help.max']);//18dec2021, 24jul2021
iset('opensave.sort',0,nlMax,nlName,a.i['opensave.sort']);//25mar2021
bset('opensave.preview',true,a.b['opensave.preview']);//22may2022
iset('folder.sort',0,nlMax,nlName,a.i['folder.sort']);//20jul2024
bset('folder.preview',true,a.b['folder.preview']);//20jul2024
iset('nav.sort',0,nlMax,nlName,a.i['nav.sort']);//25mar2021
bset('specialcolors',true,a.b['specialcolors']);
iset('sparkle',0,20,strint32(app__info('sparkle')),a.i['sparkle']);//15mar2022
iset('focusedopacity',50,255,strint32(app__info('focused.opacity')),a.i['focusedopacity']);//27nov2024
iset('unfocusedopacity',30,255,strint32(app__info('unfocused.opacity')),a.i['unfocusedopacity']);//27nov2024
iset('opacityspeed',1,10,strint32(app__info('opacity.speed')),a.i['opacityspeed']);//27nov2024

iset('brightness',60,130,strint32(app__info('brightness')),a.i['brightness']);//21jul2024
iset('scalemode',0,pred(scale__modecount),3,a.i['scalemode']);//3=normal - 10dec2025

bset('safestrength',true,a.b['safestrength']);

//was: iset('bordersize',0,72,32,a.i['bordersize']); -> now handled 1st up above - 07jun2021
iset('scrollsize',5,72,strint32(app__info('scroll.size')),a.i['scrollsize']);//20px - 29mar2021
iset('fontfeather',0,4,1,a.i['fontfeather']);//0=none, 1=low, 2=medium, 3=high, 4=ultra
bset('emboss',strbol(app__info('emboss')),a.b['emboss']);//19nov2023
bset('safearea',true,a.b['safearea']);
bset('splash',true,a.b['splash']);


//.system background support - 08mar2025 ---------------------------------------
sysback__saveto(x);


//.custom color schemes --------------------------------------------------------
for p:=0 to (cnCustomLimit-1) do
begin
str1  :=a.s['?custom'+intstr32(p)];
str1  :=low__setcolor2(str1,-1,0);
x.s['?custom'+intstr32(p)]:=str1;
end;//p

//.paste and use
str1  :=a.s['?paste_and_use'];
x.s['?paste_and_use']:=low__setcolor2(str1,-1,0);

//.Wine specific defaults - 13feb2022 ------------------------------------------
if xwineDefaults then
   begin
   //init
   xwinemode :=frcrange32(a.i['winemode'],0,2);//0=automatic, 1=enable, 2=disable - 02feb2022
   xwine     :=(xwinemode=1) or ((xwinemode=0) and system_winepresent);

   //get
   if xwine then
      begin

      iset('fontfeather'  ,0,4,1,0);//0=none, 1=low, 2=medium, 3=high, 4=ultra

      end;

   end;


//.retain pos and size - 13dec2025 ---------------------------------------------
x.i['left']     :=a.i['left'];
x.i['top']      :=a.i['top'];
x.i['width']    :=a.i['width'];
x.i['height']   :=a.i['height'];
x.i['wh.scale'] :=a.i['wh.scale'];//actual scale width and height was stored at - 17dec2025

except;end;

//free
freeobj(@a);

end;

procedure viSyncandsave;
begin
viSyncandsave2(false);
end;

procedure viSyncandsave2(xforce:boolean);
begin

//check
if (not xforce) and (not visyssettingsloaded) then exit;

//get
viSync;
siSavesyssettings;//save -> only need to save system settings here - 05oct2020

end;

procedure viSync;//scaling support - 11dec2025, 06may2025: bkSoft0/1/2, 11dec2024: now supports "Black and White" mode for emergency "Restore Defaults"
label
   skipscheme;
var
   s:tvars8;
   xnormal,xtitle:tvirtualinfo;
   int1:longint;
   str1,xcolorname,sfontname,sfontname2,xfontname,xfontname2:string;
   xbwmode,xtouch,xmustloadid:boolean;
   xminsize,xfontsize,xfontsize2:longint;
   xfontsize__root,xfontsize__root2:longint;//root versions -> these are the values BEFORE any zoom is applied - 14mar2021

   procedure xcolorchecks(var x:tvirtualinfo);
   begin
   with x do
   begin
   //new, less restrictive color checkers - 27mar2021
   highlight       :=int__makevis24(highlight,background,10);
   font            :=int__makevis24(font,background,30);
   fonthighlight   :=int__makevis24(fonthighlight,highlight,10);
//was: - these were too restrictive and were causing some colors not to appear when the user would otherwise expect them too - 17mar2021
//   highlight       :=int__makevis24(highlight,background,20);
//   font            :=int__makevis24(font,background,30);
//   fonthighlight   :=int__makevis24(fonthighlight,highlight,30);
//   disableborder   :=int__makevis24(disableborder,disable,20);
//   disablefont     :=int__makevis24(disablefont,disable,30);
   end;
   end;

   function xrunframe:longint;//returns minsize for frame
   var
      s,d:longint;
   begin
   low__framecols(vititle.background,vititle.frame,vititle.frame2,result,s,d);
   vititle.framefindcol   :=s;
   vititle.framefindcol2  :=d;
   vinormal.framefindcol  :=s;
   vinormal.framefindcol2 :=d;
   end;

   procedure xmoderncolors(var x:tvirtualinfo);
   var
      c:tclientinfo;
   begin

   //get
   c.font          :=x.font;
   c.back          :=x.background;
   c.row           :=c.back;
   c.hint          :=c.back;
   c.hover         :=x.hover;
   c.hover2        :=x.hover;
   c.colhover      :=x.hover;
   c.colfont       :=x.fonthighlight;
   c.line          :=x.hover;
   c.line2         :=x.hover;
   c.sep           :=x.hover;
   c.border        :=x.border;
   c.mustborder    :=x.border;

   //calc
   vimoderncolors(c);

   //set
   x.mfont         :=c.font;
   x.mback         :=c.back;
   x.mrow          :=c.row;
   x.mhint         :=c.hint;
   x.mhover        :=c.hover;
   x.mhover2       :=c.hover2;
   x.mcolhover     :=c.colhover;
   x.mcolhover2    :=c.colhover2;
   x.mcolfont      :=c.colfont;
   x.mline         :=c.line;
   x.mline2        :=c.line2;
   x.msep          :=c.sep;
   x.mborder       :=c.border;
   x.mmustborder   :=c.mustborder;

   end;

   procedure xtextscaling;
   var
      a:twinbmp;
   begin

   //defaults
   a   :=nil;

   try
   a   :=twinbmp.create;
   a.setfont('arial',false,false,48,1,0);

   vitextscaling:=frcrangeD64( a.fontheight/72 , 1,3)*100;//100-300% and size=48 @ 100% = 72px height

   except;end;

   //free
   freeobj(@a);

   end;

begin
//defaults
s:=nil;
xmustloadid:=vimustloadid;
vimustloadid:=false;

try
//lock
if visyncing then exit else visyncing:=true;


//init
viscale       :=scale__calculate;//automatically takes into account for "system_blackwhitecount>=1" - 10dec2025
viscale32     :=frcmin32( trunc32(viscale) ,1 );//26mar2026
vizoom        :=viscale32;
vitepheight20 :=vizoom*20;//zoom based image height of 20px - 10dec2025

xbwmode      :=(system_blackwhitecount>=1);//special "black and white" override mode - 09dec2024
s            :=vnew2(956);

if zzok(syssettings,1050) then s.data:=zzvars(syssettings,140).data;
siFiltersettings(s);
zzvars(s,141);//re-check


//get

//.wine -> not supported for Store Apps - 30mar2022
if not system_msix then
   begin
   viwinemode :=frcrange32(s.i['winemode'],0,2);//0=automatic, 1=enable, 2=disable - 02feb2022
   viwine     :=(viwinemode=1) or ((viwinemode=0) and system_winepresent);
   end;

viminimiseeffect:=not viwine;//11mar2025

xcolorname            :=s.value['colorname'];//case sensitive to allow for filenames with both lower and upper case characters - 09mar2021

//.calculate text scaling -> used to counter OS Text Scaling and keep GUI standard - 04sep2025
if low__setbol(vitextscalingONCE,true) then xtextscaling;

//.fontname
str1                  :=low__aorbstr(strdefb(s.value['fontname'],'Arial'),app__info('font.name'),xbwmode);//11dec2024
vifontnameraw         :=str1;
if (strcopy1(str1,1,1)='*') then str1:=strdefb(s.value['fontname.c'],'Arial');
sfontname             :=str1;


//.fontname2
str1                  :=low__aorbstr(strdefb(s.value['fontname2'],siFontname2_deffont),app__info('font2.name'),xbwmode);//11dec2024
vifontnameraw2        :=str1;
if (strcopy1(str1,1,1)='*') then str1:=strdefb(s.value['fontname2.c'],siFontname2_deffont);
sfontname2            :=str1;

//.default
xfontname             :=font__realname0(font__name1,sfontname,sfontname2);//convert dynamic font name into a real font name - 03mar2026
xfontname2            :=font__realname0(font__name2,sfontname,sfontname2);//03mar2026

xtouch                :=s.b['touch'];

//.user controlled settings -> which go on to generate the final values for "vizoom" and "vifontsize/vifontsize2" system values - 26feb2022, 14mar2021
xfontsize__root       :=frcrange32(low__aorb(s.i['fontsize'],strint32(app__info('font.size')),xbwmode),6,72);
xfontsize__root2      :=frcrange32(low__aorb(s.i['fontsize2'],strint32(app__info('font2.size')),xbwmode),6,72);//26feb2022

//.xfontsize
xfontsize             :=frcmin32( trunc( xfontsize__root  * scale__fontRatioCorrection * frcminD64(viscale,0.75) ) ,2);
xfontsize2            :=frcmin32( trunc( xfontsize__root2 * scale__fontRatioCorrection * frcminD64(viscale,0.75) ) ,2);
xminsize              :=round( 7 * vizoom * scale__fontRatioCorrection );

//res fonts --------------------------------------------------------------------

//normal
xnormal.fontname      :=xfontname;
xnormal.fnFS          :=xfontsize;
xnormal.fn            :=resfont_fn;
xnormal.rfn           :=resfont_fn;
xnormal.ofn           :=res__font(xnormal.rfn);
xnormal.ofn.setparams(xfontname,xnormal.fnFS,true,false,false);
xnormal.fnH           :=xnormal.ofn.height;

//bold
xnormal.fbFS          :=xfontsize;
xnormal.fb            :=resfont_fb;
xnormal.rfb           :=resfont_fb;
xnormal.ofb           :=res__font(xnormal.rfb);
xnormal.ofb.setparams(xfontname,xnormal.fbFS,true,true,false);
xnormal.fbH           :=xnormal.ofb.height;

//small
xnormal.fsFS          :=frcmin32( trunc(xfontsize*0.8), xminsize );
xnormal.fs            :=resfont_fs;
xnormal.rfs           :=resfont_fs;
xnormal.ofs           :=res__font(xnormal.rfs);
xnormal.ofs.setparams(xfontname,xnormal.fsFS,true,false,false);
xnormal.fsH           :=xnormal.ofs.height;

//small bold
xnormal.fsbFS         :=frcmin32( trunc(xfontsize*0.8), xminsize );
xnormal.fsb           :=resfont_fsb;
xnormal.rfsb          :=resfont_fsb;
xnormal.ofsb          :=res__font(xnormal.rfsb);
xnormal.ofsb.setparams(xfontname,xnormal.fsbFS,true,true,false);
xnormal.fsbH          :=xnormal.ofsb.height;

//small2
xnormal.fsFS2         :=frcmin32( trunc(xfontsize*0.70), round( 6 * vizoom * scale__fontRatioCorrection ) );
xnormal.fs2           :=resfont_fs2;
xnormal.rfs2          :=resfont_fs2;
xnormal.ofs2          :=res__font(xnormal.rfs2);
xnormal.ofs2.setparams(xfontname,xnormal.fsFS2,true,false,false);
xnormal.fsH2          :=xnormal.ofs2.height;

//.fnbH
if (xnormal.fnH>=xnormal.fbH) then
   begin

   xnormal.fnbH   :=xnormal.fnH;
   xnormal.fnbFS  :=xnormal.fnFS;

   end
else
   begin

   xnormal.fnbH   :=xnormal.fbH;
   xnormal.fnbFS  :=xnormal.fbFS;

   end;

//.title
xtitle.fontname       :=xfontname;

xtitle.fn             :=xnormal.fn;//normal
xtitle.fnH            :=xnormal.fnH;
xtitle.fnFS           :=xnormal.fnFS;
xtitle.rfn            :=xnormal.rfn;
xtitle.ofn            :=xnormal.ofn;

xtitle.fb             :=xnormal.fb;//bold
xtitle.fbH            :=xnormal.fbH;
xtitle.fbFS           :=xnormal.fbFS;
xtitle.rfb            :=xnormal.rfb;
xtitle.ofb            :=xnormal.ofb;

xtitle.fs             :=xnormal.fs;//small
xtitle.fsH            :=xnormal.fsH;
xtitle.fsFS           :=xnormal.fsFS;
xtitle.rfs            :=xnormal.rfs;
xtitle.ofs            :=xnormal.ofs;

xtitle.fsb            :=xnormal.fsb;//small bold
xtitle.fsbH           :=xnormal.fsbH;
xtitle.fsbFS          :=xnormal.fsbFS;
xtitle.rfsb           :=xnormal.rfsb;
xtitle.ofsb           :=xnormal.ofsb;

xtitle.fnbH           :=xnormal.fnbH;
xtitle.fnbFS          :=xnormal.fnbFS;

xtitle.fs2            :=xnormal.fs2;//small 2
xtitle.fsH2           :=xnormal.fsH2;
xtitle.fsFS2          :=xnormal.fsFS2;
xtitle.rfs2           :=xnormal.rfs2;
xtitle.ofs2           :=xnormal.ofs2;


//.colorname -> colors
low__setcolorsbyname(xcolorname,@xnormal,@xtitle,@vimorecolors);

//.drag
vidragtrigger      :=20*vizoom;
vidragtriggerfine  :=1*vizoom;

//.fontheight
int1:=0;
int1:=largest32(int1,xnormal.fnH);
int1:=largest32(int1,xnormal.fbH);

if (xtitle.fn<>xnormal.fn) then int1:=largest32(int1,xtitle.fnH);
if (xtitle.fb<>xnormal.fb) then int1:=largest32(int1,xtitle.fbH);

vifontheight      :=int1;

//.titleheight(s)
vititleheight     :=vifontheight;
vititleheight2    :=round(vifontheight*1.5);//frcmin32(round(int1*1.5),low__insint(touchnormal,xtouch));
vititlefontsize   :=xfontsize;//05sep2025
vititlefontsize2  :=font__findsize(vititleheight2);

//.font ratio -> compared to base font of "arial 10pt"
vifontwidthratio  :=( largest32(xnormal.fnH,xnormal.fbH) / 16 );//16px=10pt
vitabratio        :=frcrangeD64(vifontwidthratio,0.5,2.3);


//title fonts - 20feb2026 ------------------------------------------------------

xnormal.ftFS          :=vititlefontsize;
xnormal.rft           :=resfont_ft;
xnormal.oft           :=res__font(xnormal.rft);
xnormal.oft.setparams(xfontname,xnormal.ftFS,true,true,false);
xnormal.ftH           :=xnormal.oft.height;

xnormal.ftFS2         :=vititlefontsize2;
xnormal.rft2          :=resfont_ft2;
xnormal.oft2          :=res__font(xnormal.rft2);
xnormal.oft2.setparams(xfontname,xnormal.ftFS2,true,true,false);
xnormal.ftH2          :=xnormal.oft2.height;

xtitle.ftFS           :=xnormal.ftFS;
xtitle.rft            :=xnormal.rft;
xtitle.oft            :=xnormal.oft;
xtitle.ftH            :=xnormal.ftH;

xtitle.ftFS2          :=xnormal.ftFS2;
xtitle.rft2           :=xnormal.rft2;
xtitle.oft2           :=xnormal.oft2;
xtitle.ftH2           :=xnormal.ftH2;

//------------------------------------------------------------------------------



//.sleek level
vimodern              :=s.b['modern'];//27may2025
visleekAssitedscroll  :=true;
visleekHighlight      :=true;
visleekGradient       :=true;
visleekImages         :=vimodern;

//.bordersize
vibordersize__root    :=frcrange32(low__aorb(s.i['bordersize'],strint32(app__info('bordersize')),xbwmode),0,72);
vibordersize          :=scale__px1( vibordersize__root ,insint(1,vibordersize__root>=1) );

//.touch
vitouch               :=xtouch;
vitouchsize20         :=round( low__aorb(20,30,vitouch) * frcminD64(viscale,1) );

//.finalise colors
xcolorchecks(xnormal);
xcolorchecks(xtitle);

vicopy2(xnormal,vinormal,xbwmode);
vicopy2(xtitle,vititle,xbwmode);

xmoderncolors(vinormal);
xmoderncolors(vititle);

//.other settings
vidoubleclicks        :=s.b['doubleclicks'];
viround               :=s.b['round'];
vimultimonitor        :=s.b['multimonitor'];
vidragfast            :=false;//locked off - s.b['dragfast'];
visoftclose           :=s.b['softclose'];
viframemax            :=s.b['framemax'];//04mar2022, 14mar2021
viecomode             :=s.b['ecomode'];//09may2021
vi32bit               :=s.b['32bit'];//09may2021

//was: viLockposition        :=s.b['lockposition'];//27feb2022
viheadcenter          :=s.b['headcenter'];//11oct2022
viheadalign           :=s.i['headalign'];//06jan2025
viscalemode           :=s.i['scalemode'];//10dec2025

//.feather
vifeather             :=frcrange32(s.i['fontfeather'],0,4);
visafearea            :=s.b['safearea'];
visplash              :=s.b['splash'];//29aug2020
viemboss              :=s.b['emboss'];//19nov2023
vihelp                :=s.b['realtimehelp'];
vihint                :=s.b['hint'];
vispecialcolors       :=s.b['specialcolors'];
vifocusedopacity      :=s.i['focusedopacity'];//27nov2024
viunfocusedopacity    :=s.i['unfocusedopacity'];//27nov2024
viopacityspeed        :=s.i['opacityspeed'];//27nov2024


//.sparkle list - 27feb2022
visparkle             :=frcrange32(s.i['sparkle'],0,20);

//.fast sparkle support - 27mar2026
fd__sparkleNewLevel(visparkle);

//.background support
vibrightness          :=frcrange32(s.i['brightness'],60,130);
visafestrength        :=s.b['safestrength'];

//.frame
if low__setstr(viframename,s.value['framename']) then
   begin
   low__iroll(viframeid,1);//detect different frame so that CUSTOM colored windows can update their pathc colors - 24feb2022
   viframecode.text:=sifindframe(viframename);
   end;
viFrameminsize:=xrunframe;

//.background
vibackname            :=s.value['backname'];

//.other
viscrollsize__root    :=frcrange32(low__aorb(s.i['scrollsize'],strint32(app__info('scroll.size')),xbwmode),5,100);
viscrollsize          :=scale__px1(viscrollsize__root,4);//11dec2025
vicolorname           :=xcolorname;
vifontname            :=sfontname;//02feb2022
vifontname2           :=sfontname2;
vifontsize__root      :=xfontsize__root;//14mar2021
vifontsize__root2     :=xfontsize__root2;
vifontsize            :=xfontsize;
vifontsize2           :=xfontsize2;
vistartlink           :=s.b['startlink'];
videsktoplink         :=s.b['desktoplink'];
vistartuplink         :=s.b['startuplink'];
vistartstyle          :=frcrange32(s.i['startstyle'],0,3);
viontop               :=s.b['ontop'];
viretainpos           :=s.b['retainpos'];
vihelp_bw             :=s.b['help.bw'];
vihelp_show           :=s.b['help.show'];
vihelp_max            :=s.b['help.max'];

vilineVsep1orLESS     :=scale__px0(1);
vilineVsep1           :=frcmin32(vilineVsep1orLESS,1);

virowheight20         :=scale__px1(20, frcmin32( vifontheight, vitepheight20 ) );//11dec2025
virowheight30         :=scale__px1(30, virowheight20);//11dec2025

vilineheight20        :=frcmin32( scale__px1(20 + (2*vilineVsep1orLESS) ,vifontheight), vitouchsize20);
vilineheight24        :=frcmin32( scale__px1(24 + (2*vilineVsep1orLESS) ,vifontheight), vitouchsize20);
vilineheight30        :=frcmin32( scale__px1(30 + (2*vilineVsep1orLESS) ,vifontheight), vitouchsize20);
vilineheight44        :=frcmin32( scale__px1(44 + (2*vilineVsep1orLESS) ,vifontheight), vitouchsize20);
virowheight20orLESS   :=frcmin32( scale__px1(20,vifontheight) ,insint(vitouchsize20,vitouch) );


//.mididevice - 01sep2025, 07mar2022
int1                  :=frcrange32(s.i['mididevice'],low(mmsys_mid_deviceok),high(mmsys_mid_deviceok));
if (int1<>vimididevice) then
   begin

   vimididevice:=int1;
   if mid_inuse and (int1<>mid_deviceindex) then mid_setdeviceindex(int1);

   end;
vimidideviceNEW:=int1;//update any "nmididevice" control

//.wavedevice - 01sep2025, 07mar2022
int1                  :=frcrange32(s.i['wavedevice'],0,99);
if (int1<>viwavedevice) then
   begin
   viwavedevice:=int1;
   if wav_inuse and (int1<>wav_deviceindex) then wav_setdeviceindex(int1);
   end;
viwavedeviceNEW:=int1;//update any "nwavedevice" control

//sync system links - 10dec2025, 30mar2022
low__plat('startmenu.'+low__aorbstr('del','create',vistartlink),'',true);
low__plat('desktop.'+low__aorbstr('del','create',videsktoplink),'',true);
low__plat('startup.'+low__aorbstr('del','create',vistartuplink),'',true);//09dec2023

//sync mainhelp
low__showhelp(vihelp_show);//24jul2021

//sync cursor - 29aug2021
app__cursorSoftsaveandload;

//on tops
system__setontop(viontop);

//background
if (app__gui<>nil) then app__gui.backgroundname:=vibackname;

//inc
low__iroll(vidataid,1);
if xmustloadid then low__iroll(viloadid,1);

skipscheme:
except;end;
try
//free
freeobj(@s);

//inc id
low__iroll(visyncid,1);//13feb2022

//sync with a host
if assigned(visyncevent) then visyncevent(nil);

//stop
visyncing:=false;
except;end;
end;

procedure vimoderncolors(var x:tclientinfo);//05jun2025: line2, 04jun2025, 26may2025: tweaked
var
   vlum,v:longint;
begin
//background -------------------------------------------------------------------
v   :=x.back;
vlum:=c24__lum(int__c24(v));


case vlum of
0..50:begin//adjust for very dark background
   x.row           :=int__dif242(v,10,false);
   x.hint          :=int__dif242(v,20,false);
   x.hover         :=int__dif242(v,35,false);
   x.hover2        :=int__dif242(v,60,false);
   x.line          :=int__dif242(v,40,false);
   x.line2         :=int__dif242(v,100,false);
   x.sep           :=int__dif242(v,13+insint(8,vlum<=30),false);//04jun2025: increased to 8 from 6
   x.border        :=v;
   x.mustborder    :=int__dif242(v,20,false);//for controls that must display a border, e.g. some tbasicedit
   end;
235..255:begin//adjust for very light background
   x.row           :=int__dif242(v,-5,false);
   x.hint          :=int__dif242(v,-10,false);
   x.hover         :=int__dif242(v,-15,false);
   x.hover2        :=int__dif242(v,-25,false);
   x.line          :=int__dif242(v,-20,false);
   x.line2         :=int__dif242(v,-60,false);
   x.sep           :=int__dif242(v,-16,false);
   x.border        :=v;
   x.mustborder    :=int__dif242(v,-10,false);//for controls that must display a border, e.g. some tbasicedit
   end;
else
   begin//normal operation
   x.row           :=int__dif242(v,5,false);
   x.hint          :=int__dif242(v,10,false);
   x.hover         :=int__dif242(v,20,false);
   x.hover2        :=int__dif242(v,30,false);
   x.line          :=int__dif242(v,18,false);
   x.line2         :=int__dif242(v,38,false);//05jun2025
   x.sep           :=int__dif242(v,10,false);
   x.border        :=v;
   x.mustborder    :=int__dif242(v,10,false);//for controls that must display a border, e.g. some tbasicedit
   end;
end;//case

//color highlight  -------------------------------------------------------------

x.colhover :=int__splice24(0.5,x.hover,x.colhover);
v          :=x.colhover;

case int__lum(v) of
0..160:x.colfont:=int__dif242(v,80,false);
else   x.colfont:=int__dif242(v,-80,false);
end;//case


case int__lum(x.back) of
160..255:begin

   x.colhover2.x:=int__splice24(0.15,x.colhover,0);//0.15 for reasonable contrast - 13sep2025
   x.colhover2.y:=x.colhover;

   end;
else
   begin

   x.colhover2.x:=x.back;
   x.colhover2.y:=x.colhover;

   end;
end;//case

end;

function viclientinfo(var x:tclientinfo;s:tbasiccontrol;xnormal:boolean):boolean;//18may2025
begin
//check
result:=(s<>nil);
if not result then exit;

//get
x.n            :=xnormal;
if x.n then x.info:=@vinormal else x.info:=@vititle;
x.cs           :=s.clientspace;
x.cw           :=s.clientwidth;
x.ch           :=s.clientheight;
x.e            :=s.enabled;
x.r            :=s.rounded;
x.roundframe   :=x.r;//???????????
x.roundstyle   :=s.oroundstyle;
x.bs           :=s.findbordersize;
x.ci           :=area__make(x.bs,x.bs,x.cw-x.bs-1,x.ch-x.bs-1);
x.f            :=vifeather;
x.sparkle      :=visparkle;
x.zoom         :=vizoom;

x.fn           :=x.info.fn;//old
x.fb           :=x.info.fb;
x.fs           :=x.info.fs;
x.fsb          :=x.info.fsb;
x.fs2          :=x.info.fs2;

x.rfn          :=x.info.rfn;//20feb2026
x.rft          :=x.info.rft;
x.rft2         :=x.info.rft2;
x.rfb          :=x.info.rfb;
x.rfs          :=x.info.rfs;
x.rfsb         :=x.info.rfsb;
x.rfs2         :=x.info.rfs2;

x.ofn          :=x.info.ofn;//20feb2026
x.oft          :=x.info.oft;
x.oft2         :=x.info.oft2;
x.ofb          :=x.info.ofb;
x.ofs          :=x.info.ofs;
x.ofsb         :=x.info.ofsb;
x.ofs2         :=x.info.ofs2;

x.fnH          :=x.info.fnH;
x.ftH          :=x.info.ftH;
x.ftH2         :=x.info.ftH2;
x.fbH          :=x.info.fbH;
x.fnbH         :=x.info.fnbH;
x.fsH          :=x.info.fsH;
x.fsbH         :=x.info.fsbH;
x.fsH2         :=x.info.fsH2;

x.fnFS         :=x.info.fnFS;
x.ftFS         :=x.info.ftFS;
x.ftFS2        :=x.info.ftFS2;
x.fbFS         :=x.info.fbFS;
x.fnbFS        :=x.info.fnbFS;
x.fsFS         :=x.info.fsFS;
x.fsbFS        :=x.info.fsbFS;
x.fsFS2        :=x.info.fsFS2;

x.font         :=x.info.mfont;
x.back         :=x.info.mback;
x.row          :=x.info.mrow;
x.hint         :=x.info.mhint;
x.hover        :=x.info.mhover;
x.hover2       :=x.info.mhover2;

x.colhover     :=x.info.mcolhover;
x.colhover2    :=x.info.mcolhover2;
x.colfont      :=x.info.mcolfont;

x.line         :=x.info.mline;
x.line2        :=x.info.mline2;//05jun2025
x.sep          :=x.info.msep;
x.border       :=x.info.mborder;
x.mustborder   :=x.info.mmustborder;

//.override handlers
if x.e and vispecialcolors then
   begin
   //.primary override
   if (s.ospbackcolor<>clnone) then
      begin
      x.back:=s.ospbackcolor;
      x.font:=int__dif24(x.back,-140);
      end
   //.secondary override
   else if (s.ospbackname<>'') then
      begin
      x.back:=int__splice24(0.85,x.back,inta0__findcolor(s.ospbackname) );//19may2025
      x.font:=int__dif24(x.back,-140);
      end
   end;

if (s.otextcolor<>clnone) then x.font:=s.otextcolor;
if (s.obackcolor<>clnone) then x.back:=s.obackcolor;

//resample modern colors
if (x.font<>x.info.mfont) or (x.back<>x.info.mback) then vimoderncolors(x);

end;

procedure vicopy(var s,d:tvirtualinfo);
begin
vicopy2(s,d,false);
end;

procedure vicopy2(var s,d:tvirtualinfo;xbwmode:boolean);//02sep2025
var
   h,b,g,w:longint;
begin
//init
b:=rgba0__int(15 , 15, 15);
g:=rgba0__int(127,127,127);
h:=rgba0__int(240,240,240);
w:=rgba0__int(255,255,255);

//core values
d.ofn              :=s.ofn;
d.rfn              :=s.rfn;
d.fn               :=s.fn;
d.fnH              :=s.fnH;
d.fnFS             :=s.fnFS;

d.oft              :=s.oft;//20feb2026
d.rft              :=s.rft;
d.ftH              :=s.ftH;
d.ftFS             :=s.ftFS;

d.oft2             :=s.oft2;//20feb2026
d.rft2             :=s.rft2;
d.ftH2             :=s.ftH2;
d.ftFS2            :=s.ftFS2;

d.ofb              :=s.ofb;
d.rfb              :=s.rfb;
d.fb               :=s.fb;
d.fbH              :=s.fbH;
d.fbFS             :=s.fbFS;

d.fnbH             :=s.fnbH;
d.fnbFS            :=s.fnbFS;

d.ofs              :=s.ofs;
d.rfs              :=s.rfs;
d.fs               :=s.fs;
d.fsH              :=s.fsH;
d.fsFS             :=s.fsFS;

d.ofsb             :=s.ofsb;
d.rfsb             :=s.rfsb;
d.fsb              :=s.fsb;
d.fsbH             :=s.fsbH;
d.fsbFS            :=s.fsbFS;

d.ofs2             :=s.ofs2;
d.rfs2             :=s.rfs2;
d.fs2              :=s.fs2;
d.fsH2             :=s.fsH2;
d.fsFS2            :=s.fsFS2;

d.frame            :=low__aorb(s.frame         ,g,xbwmode);
d.frame2           :=low__aorb(s.frame2        ,b,xbwmode);
d.border           :=low__aorb(s.border        ,b,xbwmode);
d.background       :=low__aorb(s.background    ,b,xbwmode);
d.highlight        :=low__aorb(s.highlight     ,h,xbwmode);
d.hover            :=low__aorb(s.hover         ,h,xbwmode);
d.disable          :=low__aorb(s.disable       ,b,xbwmode);
d.disableborder    :=low__aorb(s.disableborder ,b,xbwmode);
d.disablefont      :=low__aorb(s.disablefont   ,w,xbwmode);
d.font             :=low__aorb(s.font          ,w,xbwmode);
d.fonthighlight    :=low__aorb(s.fonthighlight ,w,xbwmode);
d.fontname         :=s.fontname;
end;


//-- System Object Checkers Support --------------------------------------------
function sbwpok(x:tobject):boolean;
begin
result:=zzok(x,1060) and (x is tbasicbwp);
end;

function sbwp(x:tobject):tbasicbwp;
begin
if sbwpok(x) then result:=(x as tbasicbwp) else result:=nil;
end;

function mistransNEXT(var xindex:longint;var xoutlabel:string;xstart:boolean):boolean;
var
   int1:longint;
   bol1:boolean;
begin
result:=mistransNEXT2(xindex,int1,xoutlabel,bol1,'',xstart);
end;

function mistransNEXT2(var xindex,xoutindex:longint;var xoutlabel:string;var xoutcustomok:boolean;xcustom:string;xstart:boolean):boolean;
begin
//defaults
result:=true;
xoutindex:=clTopleft;
xoutlabel:='';
xoutcustomok:=false;

try
//init
if xstart then xindex:=cltopleft;
//get
xoutindex:=xindex;
case xindex of
cltopleft:xindex:=clWhite;
clWhite:xindex:=clBlack;
clBlack:xindex:=clRed;
clRed:xindex:=clLime;
clLime:xindex:=clBlue;
clBlue:xindex:=-1000;//custom
-1000:begin
   xindex:=-1001;//stop
   xoutcustomok:=true;
   end;
else result:=false;
end;
//set
if result then xoutlabel:=mistransLABEL(xoutindex,xcustom);
except;end;
end;

function mistransLABEL(stranscolORstyle:longint;xcustom:string):string;
begin
case stranscolORstyle of
cltopleft:result:='Top-Left';
clwhite:result:='White';
clBlack:result:='Black';
clRed:result:='Red';
clLime:result:='Green';
clBlue:result:='Blue';
else result:=strdefb(xcustom,'Custom');
end;
end;

function mistransCUSTOM(stranscolORstyle:longint):boolean;

   function nok(x:longint):boolean;
   begin
   result:=(x<>stranscolORstyle);
   end;
begin
result:=nok(cltopleft) and nok(clwhite) and nok(clblack) and nok(clred) and nok(cllime) and nok(clblue);
end;

function mistransISOK(a,b:longint):boolean;

   function nindex(x:longint):longint;
   begin
   case x of
   cltopleft:result:=1;
   clwhite:result:=2;
   clBlack:result:=3;
   clRed:result:=4;
   clLime:result:=5;
   clBlue:result:=6;
   else result:=0;
   end;//case
   end;
begin
result:=(nindex(a)=nindex(b));
end;

function misreduce82432(s:tobject;stranscol,slessdata:longint;var e:string):boolean;
label
   skipend;
var
   sr8 :pcolorrow8;
   sr24:pcolorrow24;
   sr32:pcolorrow32;
   sc24:tcolor24;
   sc32:tcolor32;
   sx,sy,sw,sh,sbits,tr,tg,tb,trSAFE,tgSAFE,tbSAFE,xreducer1,xreducer2:longint;
   xreducerok:boolean;

   procedure xreduce32;
   const
      xthreshold=50;
   begin
   //.leave these primary colors FULLY intact - 13jan2021
   if ((sc32.r<>255) or (sc32.g<>255) or (sc32.b<>255)) and//white clwhite
      ((sc32.r<>0  ) or (sc32.g<>0  ) or (sc32.b<>0  )) and//black clblack
      ((sc32.r<>255) or (sc32.g<>0  ) or (sc32.b<>0  )) and//red   clred
      ((sc32.r<>0  ) or (sc32.g<>255) or (sc32.b<>0  )) and//lime  clime
      ((sc32.r<>0  ) or (sc32.g<>0  ) or (sc32.b<>255)) and//blue clblue
      ((sc32.r<>tr ) or (sc32.g<>tg ) or (sc32.b<>tb))  then//transparent color if specified - 20jan2021
      begin
      //get
      if (sc32.r>xthreshold) then sc32.r:=(sc32.r div xreducer1)*xreducer1 else sc32.r:=(sc32.r div xreducer2)*xreducer2;
      if (sc32.g>xthreshold) then sc32.g:=(sc32.g div xreducer1)*xreducer1 else sc32.g:=(sc32.g div xreducer2)*xreducer2;
      if (sc32.b>xthreshold) then sc32.b:=(sc32.b div xreducer1)*xreducer1 else sc32.b:=(sc32.b div xreducer2)*xreducer2;
      //restrict
      if (sc32.r=tr) and (sc32.g=tg) and (sc32.b=tb) then//transparent color
         begin
         sc32.r:=trSAFE;
         sc32.g:=tbSAFE;
         sc32.b:=tgSAFE;
         end
      else if (sc32.r=255) and (sc32.g=255) and (sc32.b=255) then//non-white
         begin
         sc32.r:=254;
         sc32.g:=254;
         sc32.b:=254;
         end
      else if (sc32.r=0) and (sc32.g=0) and (sc32.b=0) then//non-black
         begin
         sc32.r:=1;
         sc32.g:=1;
         sc32.b:=1;
         end
      else if (sc32.r=255) and (sc32.g=0) and (sc32.b=0) then//non-red
         begin
         sc32.r:=254;
         sc32.g:=0;
         sc32.b:=0;
         end
      else if (sc32.r=0) and (sc32.g=255) and (sc32.b=0) then//non-green
         begin
         sc32.r:=0;
         sc32.g:=254;
         sc32.b:=0;
         end
      else if (sc32.r=0) and (sc32.g=0) and (sc32.b=255) then//non-blue
         begin
         sc32.r:=0;
         sc32.g:=0;
         sc32.b:=254;
         end;
      end;
   //.leave these alpha values FULLY intact - 13jan2021
   if (sc32.a<>0) then
      begin
      if (sc32.a>xthreshold) then sc32.a:=(sc32.a div xreducer1)*xreducer1 else sc32.a:=(sc32.a div xreducer2)*xreducer2;
      if (sc32.a=0) then sc32.a:=xreducer1;
      end;
   end;
begin
//defaults
result:=false;
e:=gecTaskfailed;

try
//init
if not misok82432(s,sbits,sw,sh) then goto skipend;

//range
slessdata:=frcrange32(slessdata,0,5);

//slessdata
xreducer1:=slessdata;
xreducer2:=xreducer1+1;
xreducerok:=(xreducer1>=2) or (xreducer2>=2);
if not xreducerok then//nothing to do when "slessdata=0"
   begin
   result:=true;
   goto skipend;
   end;
//xtranscol -> used in this proc for reduce32 (to avoid reducing this particular color)
tr:=-1;
tg:=-1;
tb:=-1;
if (stranscol<>clnone) then
   begin
   sc24:=int__c24(stranscol);
   if (sbits=8) then
      begin
      if (sc24.g>sc24.r) then sc24.r:=sc24.g;
      if (sc24.b>sc24.r) then sc24.r:=sc24.b;
      end;
   tr:=sc24.r;
   tg:=sc24.g;
   tb:=sc24.b;
   //.filter
   if (tr=255) and (tg=255) and (tb=255) then
      begin
      trSAFE:=254;
      tgSAFE:=254;
      tbSAFE:=254;
      end
   else
      begin
      trSAFE:=255;
      tgSAFE:=255;
      tbSAFE:=255;
      end;
   end;

//get
for sy:=0 to (sh-1) do
begin
if not misscan82432(s,sy,sr8,sr24,sr32) then goto skipend;
//.8
if (sbits=8) then
   begin
   for sx:=0 to (sw-1) do
   begin
   sc32.r:=sr8[sx];
   sc32.g:=0;
   sc32.b:=0;
   sc32.a:=0;
   xreduce32;
   sr8[sx]:=sc32.r;
   end;//sx
   end
//.24
else if (sbits=24) then
   begin
   for sx:=0 to (sw-1) do
   begin
   sc24:=sr24[sx];
   sc32.r:=sc24.r;
   sc32.g:=sc24.g;
   sc32.b:=sc24.b;
   sc32.a:=0;//not used
   xreduce32;
   sc24.r:=sc32.r;
   sc24.g:=sc32.g;
   sc24.b:=sc32.b;
   sr24[sx]:=sc24;
   end;//sx
   end
//.32
else if (sbits=32) then
   begin
   for sx:=0 to (sw-1) do
   begin
   sc32:=sr32[sx];
   xreduce32;
   sr32[sx]:=sc32;
   end;//sx
   end;
end;//sy

//successful
result:=true;
skipend:
except;end;
end;


//-- menu support --------------------------------------------------------------
procedure low__menuinit(const x:tstr8);
begin

if zzok(x,7021) then
   begin

   x.clear;
   x.aadd([llm,lle,uuN,nn2]);//'meN2';

   end;

//free
str__af(@x);

end;

function low__menutitle(const x:tstr8;const xtep:longint;const xcaption,xhelp:string):boolean;
begin//add menu title
result:=low__menuadd(x,xtep,clnone,xcaption,xhelp,'',0,aknone,0,false,true,true,false);
end;

function low__menuitem(const x:tstr8;const xtep:longint;const xcaption,xhelp,xcode2:string;const xcode:longint;const xenabled:boolean):boolean;
begin//add menu item
result:=low__menuadd(x,xtep,clnone,xcaption,xhelp,xcode2,xcode,aknone,0,false,xenabled,false,false);
end;

function low__menuitem2(const x:tstr8;const xtep:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut:longint;const xenabled:boolean):boolean;
begin//add menu item
result:=low__menuadd(x,xtep,clnone,xcaption,xhelp,xcode2,xcode,xshortcut,0,false,xenabled,false,false);
end;

function low__menuitem2b(const x:tstr8;const xtep:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut:longint;const xenabled:boolean;const xindentLevel:longint):boolean;//07jun2021
begin//add menu item
result:=low__menuadd(x,xtep,clnone,xcaption,xhelp,xcode2,xcode,xshortcut,18*vizoom*frcrange32(xindentLevel,0,5),false,xenabled,false,false);
end;

function low__menuitem3(const x:tstr8;const xtep:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut:longint;const xflash,xenabled:boolean):boolean;
begin//add menu item
result:=low__menuadd(x,xtep,clnone,xcaption,xhelp,xcode2,xcode,xshortcut,0,xflash,xenabled,false,false);
end;

function low__menuitem4(const x:tstr8;const xtep:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut,xindent:longint;const xflash,xenabled:boolean):boolean;
begin
result:=low__menuadd(x,xtep,clnone,xcaption,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,false,false);
end;

function low__menutitlex(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp:string):boolean;
begin//add menu title
result:=low__menuadd(x,xtep,xtepcolor,xcaption,xhelp,'',0,aknone,0,false,true,true,false);
end;

function low__menuitemx(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp,xcode2:string;const xcode:longint;const xenabled:boolean):boolean;
begin//add menu item
result:=low__menuadd(x,xtep,xtepcolor,xcaption,xhelp,xcode2,xcode,aknone,0,false,xenabled,false,false);
end;

function low__menuitemx2(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut:longint;const xenabled:boolean):boolean;
begin//add menu item
result:=low__menuadd(x,xtep,xtepcolor,xcaption,xhelp,xcode2,xcode,xshortcut,0,false,xenabled,false,false);
end;

function low__menuitemx3(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut:longint;const xflash,xenabled:boolean):boolean;
begin//add menu item
result:=low__menuadd(x,xtep,xtepcolor,xcaption,xhelp,xcode2,xcode,xshortcut,0,xflash,xenabled,false,false);
end;

function low__menuitemx4(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut,xindent:longint;const xflash,xenabled:boolean):boolean;
begin
result:=low__menuadd(x,xtep,xtepcolor,xcaption,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,false,false);
end;

function low__menusep(const x:tstr8):boolean;
begin//add menu separator (on the tail of previous item)
result:=low__menuadd(x,tepNone,clnone,'','','',0,aknone,0,false,false,false,true);
end;

function low__menuend(const x:tstr8):boolean;
label
   skipend,redo;
var
   xtmp,xindex:tstr8;
   xpos,xlen,xchunksize:longint;
begin
//defaults
result:=false;

try
xindex:=nil;
xtmp:=nil;
str__lock(@x);
//check
if zznil(x,2172) or x.empty then goto skipend;
//check
//.menu has already been finalised
if x.asame([109,101,110,50]) then//men2
   begin
   result:=true;
   goto skipend;
   end
//.menu format is unknown
else if not x.asame([109,101,78,50]) then goto skipend;//meN2

//-- Finalise menu -------------------------------------------------------------
//Note: Build and insert menu index
//finalise menu datablock
x.setlen(x.count);

//init
xindex :=str__new8;
xlen   :=x.count32;

//check
if (xlen<4) or (not x.asame([109,101,78,50])) then goto skipend;//meN2

//get
xpos:=5;//skip over main head (temp at this stage)
redo:
if (xpos<=(xlen+3)) then
   begin
   xchunksize:=x.int4[xpos-1];
   if (xchunksize>=1) then
      begin
      xindex.addint4(xpos-4);
      //loop
      inc(xpos,xchunksize);
      goto redo;
      end;
   end;
//.insert index into menu datablock and mark as done with "men2"
xtmp:=str__new8;
xtmp.aadd([109,101,110,50]);//men2 -> 0..3
xtmp.addint4(xindex.count32 div 4);//4..7
xtmp.add(xindex);
xtmp.add2(x,4,x.count-1);
x.clear;
x.add(xtmp);
//successful
result:=true;
skipend:
except;end;
try
freeobj(@xindex);
freeobj(@xtmp);
str__uaf(@x);
except;end;
end;

function low__menucount(const x:tstr8):longint;//number of items in menu
begin
str__lock(@x);
result:=0;
if zzok(x,7021) and x.asame([109,101,110,50]) then result:=frcmin32(x.int4[4],0);
str__uaf(@x);
end;

function low__menuget(const x:tstr8;const xindex:longint;var xtep,xtepcolor:longint;var xcaption,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep:boolean):boolean;
label
   skipend;
var
   xlen,xpos,xcount:longint;
   xval:tstr8;

   function xpull:boolean;
   var
      int1:longint;
   begin

   //defaults
   result:=false;
   xval.clear;

   //check
   if (xpos<1) or ((xpos+3)>xlen) then exit;

   //get
   int1:=frcmin32(x.int4[xpos-1],0);
   inc(xpos,4);

   if (int1>=1) then
      begin
      xval.add2(x,xpos-1,xpos-1+int1-1);
      inc(xpos,int1);
      end;

   //successful
   result:=(int1>=0);

   end;

   function xpullint4(var xval:longint):boolean;
   begin

   //defaults
   result:=false;
   xval:=0;

   //check
   if (xpos<1) or ((xpos+3)>xlen) then exit;

   //get
   xval:=x.int4[xpos-1];
   inc(xpos,4);

   //successful
   result:=true;

   end;
begin

//defaults
result       :=false;

try
//init
str__lock(@x);
xval         :=nil;
xtep         :=tepNone;
xtepcolor    :=clnone;
xcaption     :='';
xhelp        :='';
xcode2       :='';
xcode        :=0;
xshortcut    :=aknone;
xindent      :=0;
xenabled     :=false;
xtitle       :=false;
xsep         :=false;
xflash       :=false;

//check                      //'men2'
if zznil(x,2173) or (x.count<8) or (not x.asame([109,101,110,50])) then goto skipend;
xlen:=x.count32;

//init
xval:=small__new8;//29aug2025

//range
xcount:=frcmin32(x.int4[4],0);
if (xindex<0) or (xindex>=xcount) then goto skipend;

//index slot -> start of menuitem data chunk
xpos:=9+(xindex*4);
if (xpos<1) or ((xpos+3)>xlen) then goto skipend;
xpos:=4+4+(xcount*4)+x.int4[xpos-1];
if (xpos<1) or ((xpos+3)>xlen) then goto skipend;

//.skip over chunksize
inc(xpos,4);

//get
if not xpullint4(xtep)      then goto skipend;//06may2020
if not xpullint4(xtepcolor) then goto skipend;//02mar2021
if xpull                    then xcaption:=xval.text else goto skipend;
if xpull                    then xhelp:=xval.text    else goto skipend;
if xpull                    then xcode2:=xval.text   else goto skipend;
if xpull then
   begin

   xcode       :=xval.int4[0];//0..3  to32bit(copy(xval,1,4));//1..4
   xshortcut   :=xval.int4[4];//4..7  to32bit(copy(xval,5,4));//5..8
   xindent     :=frcmin32(xval.int4[8],0);//8..11  frcmin32(to32bit(copy(xval,9,4)),0);//9..12
   xflash      :=(xval.byt1[12]=1);
   xenabled    :=(xval.byt1[13]=1);//(copy(xval,13,1)=#1);//13
   xtitle      :=(xval.byt1[14]=1);//(copy(xval,14,1)=#1);//14
   xsep        :=(xval.byt1[15]=1);//(copy(xval,15,1)=#1);//15

   end
else goto skipend;

//successful
result:=true;
skipend:

except;end;

//free
small__free8(@xval);
str__uaf(@x);

end;

function low__menuadd(const x:tstr8;const xtep,xtepcolor:longint;const xcaption,xhelp,xcode2:string;const xcode,xshortcut,xindent:longint;const xflash,xenabled,xtitle,xsep:boolean):boolean;
label
   skipend;
var
   xval:tstr8;
begin

//defaults
result:=false;

try

//init
xval:=nil;
str__lock(@x);

//check
if zznil(x,2174) or (not x.asame([109,101,78,50])) then goto skipend;//meN2

//special overrides
if xsep and (xcaption='') then
   begin
   if (x.count32>=1) then x.pbytes[x.count32-1]:=1;//adjust the previous item to include a trailing separater - 28mar2020
   result:=true;
   exit;
   end;

//get
xval:=small__new8;//29aug2025
xval.addint4(xtep);//06may2020
xval.addint4(xtepcolor);//02mar2021
xval.addint4(low__len32(xcaption));xval.addstr(xcaption);
xval.addint4(low__len32(xhelp));xval.addstr(xhelp);
xval.addint4(low__len32(xcode2));xval.addstr(xcode2);
xval.addint4(16);//this covers: xcode+xshortcut+xindent+xenabled+xtitle+xsep below - 01apr2020, 26mar2020
xval.addint4(xcode);
xval.addint4(xshortcut);
xval.addint4( frcmin32(xindent,0) );//07apr2020
xval.addbyt1(low__aorb(0,1,xflash));//25mar2021
xval.addbyt1(low__aorb(0,1,xenabled));
xval.addbyt1(low__aorb(0,1,xtitle));
xval.addbyt1(low__aorb(0,1,xsep));//this trailing var "sep" is automatically modified by menu handler procs -> always have as last in list - 25mar2021
//add
//was: result:=pushb(xdatalen,xdata,from32bit(4+low__len32(xval))+xval);
x.addint4(4+xval.count32);
x.add(xval);

//successful
result:=true;

skipend:
except;end;

//free
small__free8(@xval);
str__uaf(@x);

end;

function low__menufindbycode2(const x:tstr8;const xfindval:string;var xindex:longint):boolean;
label
   skipend;
var
   xtep,xtepcolor,xcode,xshortcut,xindent,p,xcount:longint;
   xcaption,xhelp,xcode2:string;
   xflash,xenabled,xtitle,xsep:boolean;
begin

//defaults
result   :=false;

try
//init
str__lock(@x);
xindex   :=0;
xcount   :=low__menucount(x);

//check
if (xcount<=0) then goto skipend;

//find
for p:=0 to (xcount-1) do if low__menuget(x,p,xtep,xtepcolor,xcaption,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep) and strmatch(xfindval,xcode2) then
   begin

   xindex:=p;
   result:=true;
   break;

   end;

skipend:
except;end;

//free
str__uaf(@x);

end;

function low__menucode2(const x:tstr8;const xindex:longint):string;
var
   xtep,xtepcolor:longint;
   xcaption,xhelp,xcode2:string;
   xcode,xshortcut,xindent:longint;
   xflash,xenabled,xtitle,xsep:boolean;
begin
if low__menuget(x,xindex,xtep,xtepcolor,xcaption,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep) then result:=xcode2 else result:='';
end;


//file support -----------------------------------------------------------------
function low__nn(x:string):boolean;//14apr2021
begin
result:=(strcopy1(x,1,1)='@');
end;

function low__dk(x:string):boolean;//14apr2021
begin
result:=(strcopy1(x,1,1)=intdisk_char);
end;

procedure low__reloadfastvars;
begin
sysfast_root        :=low__platroot;
sysfast_settings    :=low__platfolder('settings');
sysfast_schemes     :=low__platfolder('schemes');
sysfast_startmenu   :=io__winstartmenu;
sysfast_desktop     :=io__windesktop;
sysfast_programs    :=io__winprograms;
sysfast_blaiz       :=low__platfolder('');
end;


function low__makerelative(xfilename,xauthoritiveFilenameORfolder:string):string;//20mar2022
var
   str1,xroot:string;
   p:longint;
   xonce:boolean;
begin
{
Example:
r:='c:\temp\f\1\2\z.m3u';
s:='c:\temp\a\b\c.mid';
d:=low__makerelative(s,r);
d:="..\..\..\temp\a\b\c.mid"
//debug code for testing:
showtext('-- make relative --'+rcode+
'r: '+r+'<<'+rcode+
's: '+s+'<<'+rcode+
'd: '+d+'<<'+rcode+
}//yyyy

//defaults
result:=xfilename;

try
xroot:=io__extractfilepath(xauthoritiveFilenameORfolder);
//check
if (strcopy1(xroot,2,2)<>':\') and (strcopy1(xroot,2,2)<>':/') then exit;//must be a local drive
if not strmatch(strcopy1(result,1,3),strcopy1(xroot,1,3)) then exit;//must be on same drive
//get
if strmatch(xroot,strcopy1(result,1,low__len32(xroot))) then strdel1(result,1,low__len32(xroot))
else
   begin//xfilename is on same drive BUT in another folder structure from the xroot e.g. "xfilename=d:\temp\music\1.mid" and "xroot=d:\temp2\mymusic\" so "result=..\..\temp\music\1.mid"
   //get -> count down through root's subfolders till we match that of the xfilename
   str1:='';
   xonce:=true;
   for p:=low__len32(xroot) downto 1 do
   begin
   if (xroot[p-1+stroffset]='\') or (xroot[p-1+stroffset]='/') then
      begin
      if not xonce then str1:=str1+'..\';
      if strmatch(strcopy1(xroot,1,p),strcopy1(result,1,p)) then
         begin
         result:=str1+strcopy1(result,p+1,low__len32(result));
         break;
         end;
      if xonce then xonce:=false;
      end;
   end;
   end;
except;end;
end;

function low__readrelative(xfilename,xauthoritiveFilenameORfolder:string):string;//fixed 31may2022, 20mar2022
var
   xroot:string;
   xonce:boolean;
   xcount,xcount2,p:longint;
begin
//defaults
result:=xfilename;

try
//check
xroot:=io__extractfilepath(xauthoritiveFilenameORfolder);
if (strcopy1(xroot,2,2)<>':\') and (strcopy1(xroot,2,2)<>':/') then exit;//must be a local drive
//special check
if (strcopy1(xfilename,1,3)<>'..\') then//critical fix - 31may2022
   begin
   if (strcopy1(xfilename,2,2)<>':\') and (strcopy1(xfilename,2,2)<>':/') then result:=xroot+xfilename;
   exit;
   end;
//count
xcount:=0;
xcount2:=0;
for p:=1 to low__len32(result) do
begin
if (p>=3) and ((result[p-1+stroffset]='\') or (result[p-1+stroffset]='/')) and ( (strcopy1(result,p-2,3)='..\') or (strcopy1(result,p-2,3)='../') ) then inc(xcount);
end;//p
//get
if (xcount>=1) then
   begin
   xonce:=true;
   for p:=low__len32(xroot) downto 1 do
   begin
   if (xroot[p-1+stroffset]='\') or (xroot[p-1+stroffset]='/') then
      begin
      if not xonce then
         begin
         inc(xcount2);
         if (xcount=xcount2) then
            begin
            result:=strcopy1(xroot,1,p)+strcopy1(result,xcount*3+1,low__len32(result));
            break;
            end;
         end;
      if xonce then xonce:=false;
      end;
   end;//p
   end;
except;end;
end;


//system support ---------------------------------------------------------------
procedure system_paintallnowSLOW;
begin
system_mustpaintSLOW:=2;low__iroll(system_mustidSLOW,1);
end;

procedure system_paintallnow;
begin
system_mustpaint:=2;low__iroll(system_mustid,1);
end;

procedure system_paintnow;
begin
if (system_mustpaint<1) then
   begin
   system_mustpaint:=1;
   low__iroll(system_mustid,1);
   end;
end;

procedure system_alignallnow;
begin
system_mustalign:=2;low__iroll(system_mustid,1);
end;

procedure system_alignnow;
begin
if (system_mustalign<1) then
   begin
   system_mustalign:=1;
   low__iroll(system_mustid,1);
   end;
end;

procedure system_sizenow;
begin
system_mustalign:=2;//full
system_mustpaint:=2;//full
low__iroll(system_mustid,1);
end;

procedure dbRGBA(x:longint);//26jun2021
var
   a:tint4;
begin
a.val:=x;
showtext(
'R: '+intstr32(a.r)+rcode+
'G: '+intstr32(a.g)+rcode+
'B: '+intstr32(a.b)+rcode+
'A: '+intstr32(a.a)+rcode+
'');
end;

procedure dbtext(yrow:longint;xtext:string);//21nov2024
begin//canvas.textout//dbtext
if (app__guiactive<>nil) then app__guiactive.debug(yrow,xtext);
end;

procedure dbimage(s:tobject;szoom:longint;susealpha:boolean);//strictly debug purposes only - 21dec2021, 07jun2021
begin
dbimage1(s,szoom,susealpha,'');
end;

procedure dbimage1(s:tobject;szoom:longint;susealpha:boolean;smsg:string);
begin
dbimage1b(s,szoom,susealpha,smsg,clnone);
end;

procedure dbimage1b(s:tobject;szoom:longint;susealpha:boolean;smsg:string;sshowcolor:longint);//21nov2024: updated to handle sshowcolor properly, 18nov2024, 05aug2024
begin
showtext('option temporarily disabled due to its reliance on tform');
{
label//Note: Now supports 32bit images with alpha masking - 07jun2021
   skipend;
var
   x:tform;
   b:tbmp;
   c:trawimage;
   e:string;
   v:tint4;
   sx,sy,sw,sh:longint;
   sr32:pcolorrow32;
   c32:tcolor32;
begin
try
//defaults
x:=nil;
b:=nil;
c:=nil;
szoom:=frcrange32(szoom,1,50);
//check
if zznil(s,2192) then
   begin
   showtext('no image');
   exit;
   end;
//init
c:=misraw32(1,1);
if str__ok(@s) then
   begin
   if not mis__fromdata(c,@s,e) then goto skipend;
   end
else if not miscopy(s,c) then goto skipend;

//highlight transparent areas with a color to contrast
if (sshowcolor<>clnone) then
   begin
   susealpha:=false;
   sw:=misw(c);
   sh:=mish(c);
   v.val:=sshowcolor;

   for sy:=0 to (sh-1) do
   begin
   if not misscan32(c,sy,sr32) then goto skipend;

   for sx:=0 to (sw-1) do
   begin
   c32:=sr32[sx];
   if (c32.a<255) then
      begin
      c32.r:=((c32.r*c32.a) + (v.r*(255-c32.a))) div 256;
      c32.g:=((c32.g*c32.a) + (v.g*(255-c32.a))) div 256;
      c32.b:=((c32.b*c32.a) + (v.b*(255-c32.a))) div 256;
      c32.a:=255;
      sr32[sx]:=c32;
      end;
   end;//sx
   end;//sy
   end;

b:=misbmp(32,misw(c)*szoom,mish(c)*szoom);//07jun2021
x:=tform.create(nil);
x.vertscrollbar.visible:=false;
x.horzscrollbar.visible:=false;
x.borderstyle:=bsNone;
x.bordericons:=[];
monitors__centerformINarea_auto(x,-1,10,misw(b),mish(b));
x.show;
app__processallmessages;

b.lock;
miscls(b,0);
miscopyareaxx8(maxarea,0,0,misw(b),mish(b),misarea(c),b,c,nil,nil,nil,nil,nil,nil,0,0,false,255,0,clnone,0,0,0,nil,nil,nil,nil,nil,nil,nil,susealpha);
if (b.core is tbitmap) then x.canvas.draw(0,0,b.core as tbitmap);
b.unlock;
showtext(strdefb(smsg,'dbimage'));

skipend:
except;end;
try
freeobj(@b);
freeobj(@x);
freeobj(@c);
except;end;
}
end;

procedure dbimage2(s,s2:tobject;szoom:longint);//strictly debug purposes only
begin
dbimage3(s,s2,szoom,'');
end;

procedure dbimage3(s,s2:tobject;szoom:longint;xcap:string);//30dec2022, strictly debug purposes only
begin
showtext('option temporarily disabled due to its reliance on tform');
{
var
   x:tform;
   b:tbmp;
begin
try
//defaults
x:=nil;
b:=nil;
szoom:=frcrange32(szoom,1,50);
//check
if zznil(s,2192) then
   begin
   showtext('no image');
   exit;
   end;
//init
b:=misbmp(24,misw(s)*szoom,mish(s)*szoom);
x:=tform.create(nil);
x.vertscrollbar.visible:=false;
x.horzscrollbar.visible:=false;
x.borderstyle:=bsNone;
x.bordericons:=[];
monitors__centerformINarea_auto(x,-1,10,misw(b),mish(b));
x.show;
app__processallmessages;
b.lock;
//.s
miscopyareaxx(maxarea,0,0,misw(b),mish(b),misarea(s),b,s,255,0,clnone,0);
//.s2
miscopyareaxx(maxarea,0,0,misw(b),mish(b),misarea(s),b,s2,150,1,mispixel24VAL(s2,0,0),0);
if (b.core is tbitmap) then x.canvas.draw(0,0,b.core as tbitmap);
b.unlock;
showtext(strdefb(xcap,'dbimage'));
except;end;
try
freeobj(@b);
freeobj(@x);
except;end;
}
end;

procedure dbstatus(p:longint;x:string);//16may2025
begin
if (app__gui<>nil) then app__gui.debug(p,x);
end;

procedure dbstart;
begin
try
debug_msstart:=slowms64;
debug_msstop:=debug_msstart;
if (debug_msstartave=0) then debug_msstartave:=slowms64;
except;end;
end;

procedure dbstop;
begin

debug_msstop       :=slowms64;
debug_mstimetotal  :=debug_mstimetotal+(debug_msstop-debug_msstart);
debug_mstimecount  :=debug_mstimecount+1;

//.avefast
debug_mstimetotal2 :=debug_mstimetotal2+(debug_msstop-debug_msstart);
debug_mstimecount2 :=debug_mstimecount2+1;

if ((slowms64-debug_msstartave)>=1000) then
   begin

   debug_mstimeavefast :=div64(debug_mstimetotal2, frcmin64(debug_mstimecount2,1) );

   //reset
   debug_mstimetotal2  :=0;
   debug_mstimecount2  :=0;
   debug_msstartave    :=0;

   end;

   end;

function dbtime:string;
begin
result:=k64(debug_msstop-debug_msstart)+' ms';
end;

function dbtimeave:string;
begin
result:=k64( div64( debug_mstimetotal, frcmin64(debug_mstimecount,1) ) )+' ms';
end;

function dbtimeavefast:string;
begin
result:=k64(debug_mstimeavefast)+' ms';
end;

procedure dbshow(xlabel:string);//show label + dbtime
begin
showtext(xlabel+'<<'+dbtime);
end;

procedure dbstopshow(xlabel:string);//show label + dbtime
begin
dbstop;
showtext(xlabel+'<<'+dbtime);
end;

procedure pop_junk(x:string);
begin
if (sysprogram<>nil) and (sysprogram.rootwin<>nil) then sysprogram.rootwin.xhead.caption:=x+'<<'+ms64str;
end;

function pop_error(x:string):boolean;//10feb2023
begin
if (sysprogram<>nil) and (sysprogram.gui<>nil) then result:=sysprogram.gui.poperror('',x)
else
   begin
   result:=false;
   showerror(x);
   end;
end;

function pop_query(x:string):boolean;//05feb2023
begin
if (sysprogram<>nil) and (sysprogram.gui<>nil) then result:=sysprogram.gui.popquery(x)
else
   begin
   result:=false;
   showtext(x);
   end;
end;

function pop_query2(x,xcancelcap,xokcap:string):boolean;//11feb2023
begin
if (sysprogram<>nil) and (sysprogram.gui<>nil) then result:=sysprogram.gui.popqueryex(x,xcancelcap,xokcap,450,200,60,0)
else
   begin
   result:=false;
   showtext(x);
   end;
end;

function pop_info(xtitle,x:string):boolean;//05feb2023
begin//pass-thru

result:=true;
if (sysprogram<>nil) and (sysprogram.gui<>nil) then sysprogram.gui.popinfo(xtitle,x) else showtext(x);

end;

function pop_msg(xtitle,x:string):boolean;//23jul2024
begin//pass-thru
result:=true;
if (sysprogram<>nil) and (sysprogram.gui<>nil) then sysprogram.gui.popmsg(xtitle,x) else showtext(x);
end;

function pop_txt2(var x:string;xwrap:longint;xreadonly:boolean;xcap,xhelp:string):boolean;
begin
if (sysprogram<>nil) and (sysprogram.gui<>nil) then result:=sysprogram.gui.poptxt2(x,xwrap,xreadonly,true,xcap,xhelp) else result:=false;
end;

function pop_save(var xfilename:string;xfilterlist,xcommonfolder:string;var daction:string):boolean;
begin
result:=pop_save2(xfilename,xfilterlist,xcommonfolder,'',daction);
end;

function pop_save2(var xfilename:string;xfilterlist,xcommonfolder,xtitle2:string;var daction:string):boolean;
var
   xfilterindex:longint;
begin
xfilterindex:=0;
if (sysprogram<>nil) and (sysprogram.gui<>nil) then result:=sysprogram.gui.xpopnav2(xfilename,xfilterindex,xfilterlist,xcommonfolder,'save','','Save'+insstr(#32,xtitle2<>'')+xtitle2,daction) else result:=false;
end;

function pop_find(xhandler:longint;var xtext,xcmd:string):boolean;
begin//pass-thru
result:=true;
if (sysprogram<>nil) and (sysprogram.gui<>nil) then sysprogram.gui.popfind(xhandler,xtext,xcmd);
end;

procedure showa(x:longint);
begin
showtext('a'+intstr32(x));
end;

procedure showb(x:longint);
begin
showtext('b'+intstr32(x));
end;

procedure showc(x:longint);
begin
showtext('c'+intstr32(x));
end;

procedure showa1;
begin
showa(1);
end;

procedure showa2;
begin
showa(2);
end;

procedure showa3;
begin
showa(3);
end;

procedure showa4;
begin
showa(4);
end;

procedure showa5;
begin
showa(5);
end;

procedure showa6;
begin
showa(6);
end;

procedure showa7;
begin
showa(7);
end;

procedure showa8;
begin
showa(8);
end;

procedure showa9;
begin
showa(9);
end;

procedure showb1;
begin
showb(1);
end;

procedure showb2;
begin
showb(2);
end;

procedure showb3;
begin
showb(3);
end;

procedure showb4;
begin
showb(4);
end;

procedure showc1;
begin
showc(1);
end;

procedure showc2;
begin
showc(2);
end;

procedure showc3;
begin
showc(3);
end;

procedure showc4;
begin
showc(4);
end;

procedure showerror8(e:tstr8);//04sep2025, 19aug2020
begin//Do not check "e" for risk of cyclic error

//lock
low__closelock;
str__lock(@e);

//get
try;if (e<>nil) and (not e.empty) then win____messagebox(app__handle,pchar(e.text),'Error!',$00000000+$10);except;end;

//free
str__uaf(@e);

//unlock
low__closeunlock;

end;

//-- Idle Trackers -------------------------------------------------------------
function low__inputidle_nokeyboard:comp;//06dec2024
var
   a:comp;
begin
//defaults
result:=0;

try
//get
a:=sysclicktime;
if (syswheeltime>a) then a:=syswheeltime;
if (sysmovetime>a) then a:=sysmovetime;
if (sysdowntime>a) then a:=sysdowntime;//mousedown
//.global mouse move
low__moveidle_global;
if (sysmovetime_global>a) then a:=sysmovetime_global;
//set
result:=frcmin64(slowms64-a,0);
except;end;
end;

function low__canecopaint(var xtime64:comp):boolean;//11jan2025: 0..10m=normal speed, 10..30m=2fps, 30m+=1fps
var
   v:comp;
begin
//defaults
result:=not viecomode;

try
//get
if not result then
   begin
   //init
   v:=low__inputidle;
   //get
   if (system_ecomode_pause>slowms64) then result:=true//app is overriding the eco mode - 06dec2024
   else if (v<=600000)             then result:=true//0..10m => normal speed
   else if (slowms64>=xtime64)        then
      begin
      result:=true;
      if     (v<=1800000) then xtime64:=slowms64+500 //10m..30m = 2fps
      else                    xtime64:=slowms64+1000;//30m+     = 1fps
      end;
   end;
except;end;
end;


function low__moveidle_global:comp;
var
   a:tpoint;
begin
result:=0;
a:=low__getcursorposb;

try
if (a.x<>sysmovetime_globalx) or (a.y<>sysmovetime_globaly) then sysmovetime_global:=slowms64;
sysmovetime_globalx:=a.x;
sysmovetime_globaly:=a.y;
result:=frcmin64(slowms64-sysmovetime_global,0);
except;end;
end;

//string support ---------------------------------------------------------------
function strcopy0x(const x:string;xpos:longint64;const xlen:longint64):string;//0based always -> forward compatible with D10 - 02may2020
begin

result:='';

try

if (xlen<1) then exit;
if (xpos<0) then xpos:=0;
result:=copy(x, int64__3264(xpos+stroffset) ,int64__3264(xlen) );

except;end;

end;

function strlastMatch(const x:string;const xvaluetomatch:string):boolean;//07jan2022
begin
result:=(low__len32(xvaluetomatch)<=low__len32(x)) and strmatch(strcopy1x(x,low__len32(x)-low__len32(xvaluetomatch)+1,low__len32(xvaluetomatch)),xvaluetomatch);
end;

function strlastx(const x:string):string;//returns last char of string or nil if string is empty
begin
result:=strcopy1x(x,low__len32(x),1);
end;

function strcopy1x(const x:string;xpos:longint64;const xlen:longint64):string;//1based always -> backward compatible with D3 - 02may2020
begin

result:='';

try

if (xlen<1) then exit;
if (xpos<1) then xpos:=1;
result:=copy(x, int64__3264(xpos-1+stroffset) ,int64__3264(xlen) );

except;end;

end;

function strbyte1x(const x:string;xpos:longint64):byte;//1based always -> backward compatible with D3 - 02may2020
var
   xlen:longint64;
begin

result:=0;

try

if (xpos<1) then xpos:=1;
xlen:=low__len32(x);
if (xlen>=1) and (xpos<=xlen) then result:=byte(x[ int64__3264(xpos-1+stroffset) ]);

except;end;

end;

function low__aswin95(const x:string):string;//31mar2021, 21-AUG-2004
var
   p,xlen:longint;
   z:string;
begin

//defaults
result:='';

try
//init
xlen:=low__len32(x);

//check
if (xlen<=0) then
   begin
   result:='';
   exit;
   end;

//get
if (x[0+stroffset]='&') then p:=1 else p:=0;//fixed - 31mar2021

result:=strlow(x);

if (p<=(xLen-1+stroffset)) then
   begin
   z:=strup(x[p+stroffset]);
   result[p+stroffset]:=z[0+stroffset];
   end;

except;end;
end;
{was:
function low__asname(x:string):string;//31mar2021, 10JUN2007
var//Note: "/=47" and "\=92" support added 10JUN2007
   int1,xlen,lp,p:longint;
   str1:string;
begin
try
//defaults
result:=x;
//init
xlen:=low__len32(x);
//check
if (xlen<=0) then exit;
//get
lp:=1;
for p:=1 to xlen do
begin
case byte(x[p-1+stroffset]) of
34,39,10,9,95,32,45,126,47,92:begin
   str1:=low__aswin95(strcopy1(x,lp,p-lp))+strcopy1(x,p,1);//exclude the sep char from the "low__aswin95()" process
   if (str1<>'') then for int1:=1 to low__len32(str1) do result[(lp-1)+stroffset+(int1-1)]:=str1[int1-1+stroffset];
   lp:=p+1;
   end;
else
   begin
   if (p>=xlen) then
      begin
      str1:=low__aswin95(strcopy1(x,lp,p-lp));
      if (str1<>'') then for int1:=1 to low__len32(str1) do result[(lp-1)+stroffset+(int1-1)]:=str1[int1-1+stroffset];
      end;
   end;
end;//case
end;//p
except;end;
end;
{}

function low__asname(const x:string):string;//02mar2022
var
   lc,v,xlen,p:longint;

   function xAB09(const x:longint):boolean;
   begin
   result:=false;

   case x of
   48..57,65..90,97..122:result:=true;
   end;//case

   end;
begin

//defaults
result:=x;

try
//init
xlen:=low__len32(x);
if (xlen<=0) then exit;

//get
lc:=32;

for p:=1 to xlen do
begin

v:=strbyte1x(result,p);

if xAB09(v) then
   begin

   case xAB09(lc) of
   true:begin
      if(v>=65) and (v<=90) then
         begin
         inc(v,32);
         result[p-1+stroffset]:=char(v);
         end;
      end;
   else begin
      if(v>=97) and (v<=122) then
         begin
         dec(v,32);
         result[p-1+stroffset]:=char(v);
         end;
      end;
   end;//case

   end;

lc:=v;
end;//p

except;end;
end;

function bn(const x:boolean):byte;
begin
if x then result:=1 else result:=0;
end;

function nb(const x:byte):boolean;
begin
result:=(x=1);
end;

function fromnullstr(const a:pointer3264;const asize:longint64):string;
var
   p:longint3264;
   b:pdlBYTE;
begin

//defaults
result:='';

try
//init
low__setlen(result,asize);
b:=a;

//get
for p:=0 to int64__3264(asize-1) do
    begin

    result[ p+stroffset ]:=chr(b[p]);

    if (b[p]=0) then
       begin

       low__setlen(result,p);
       break;

       end;

    end;

except;end;
end;

function low__nullstr(const x:longint64;const y:char):string;
var//speed: 8-9Mb/sec, tested at 9Mb=1,000ms @ 200Mhz
   p:longint3264;
begin
result:='';

try

low__setlen(result,x);
for p:=int64__3264(low__len32(result)-1) downto 0 do result[ p+stroffset ]:=y;

except;end;
end;

function low__rembinaryb(const x:string):string;//07apr2020
begin

result:=x;
low__rembinary(result);

end;

function strint_filtered(const x:string):longint;//removes "comma,space" automatically
var
   a:string;
begin

result:=0;

try

a:=x;
low__remchar(a,',');
low__remchar(a,#32);
result:=strint32(a);

except;end;
end;

function strint_filtered64(const x:string):comp;//removes "comma,space" automatically
var
   a:string;
begin
result:=0;

try
a:=x;
low__remchar(a,',');
low__remchar(a,#32);
result:=strint64(a);
except;end;
end;

function low__firstline(var _data:string):string;//08oct2018
var//Now supports #10, #13 and #13#10 combinations
   ok:boolean;
   p:longint3264;
   v:byte;
begin

//defaults
result :='';
ok     :=false;

try

//get
for p:=1 to int64__3264(low__len32(_data)) do
begin

v:=strbyte1(_data,p);

if (v=10) or (v=13) then//fixed 08oct2018
   begin

   ok     :=true;
   result :=strcopy1(_data,1,p-1);

   break;

   end;

end;//p

if not ok then result:=_data;

except;end;
end;

procedure low__checkfilebadchars(xfilename:string);//soure code checker/clean code checker
label
   skipend2,skipend;
var
   x:tstr8;
   xlinecount,lv,v,p,xlen,xbadcount:longint;
   xreclist,xfirst,e:string;
begin
try
//init
e:='';
xreclist:='';
xfirst:='';
x:=nil;
x:=str__new8;
xbadcount:=0;
xlinecount:=0;
if io__fromfile(xfilename,@x,e) then e:='';
xlen:=x.len32;
if (xlen<=0) then goto skipend;
//get
lv:=0;
for p:=0 to (xlen-1) do
begin
v:=x.pbytes[p];

//.return code checker
if (v=10) then inc(xlinecount);
if (v=10) and (lv=10) then
   begin
   showtext('Error at line '+k64(xlinecount)+' - incorrect return code (10+10) instead of (13+10) for file "'+io__extractfilename(xfilename)+'".');
   goto skipend2;
   end;
lv:=v;

{
if (v=124) and (xreccount<0) then xreccount:=0;//start recording
if (xreccount>=0) then
   begin
   inc(xreccount);
   if (xreccount<=400) then xreclist:=xreclist+intstr32(v)+' ';
   end;
{}
{
case v of
0..8,11..12,14..31,127..255:begin
   inc(xbadcount);
   if (xbadcount=1) then
      begin
      str1:='';
      for i:=(p-1) downto (p-250) do str1:=char(x.pbytes[i])+str1;
      xfirst:='Text before bad character: >>'+str1+'<<';
      end;
   end;
end;
{}//xxxxx
end;//p
skipend:
//prompt
if (e<>'') then showtext(e)
else if (xbadcount<=0) then
   begin
   showtext(
   'Code is clean.'+rcode+
   'No bad characters detected.'+rcode+
   'Scanned '+k64(xlen)+'c in '+xfilename+rcode+
   rcode+
   'Reclist>>'+xreclist+'<<'+rcode
   );
   end
else
   begin
   showtext(
   'Warning: '+k64(xbadcount)+' bad characters detected within code.'+rcode+
   rcode+
   xfirst+rcode+
   rcode+
   'Scanned '+k64(xlen)+'c in '+xfilename+rcode+
   rcode+
   'Reclist>>'+xreclist+'<<'+rcode
   );
   end;
skipend2:
except;end;

//free
str__free(@x);

end;

function low__findtext(var _pos:longint;var _data:string;_find:string):boolean;
begin
result:=low__findtextL(_pos,low__len32(_data),_data,_find);
end;

function low__findtextL(var _pos:longint;_len:longint;var _data:string;_find:string):boolean;//22apr2014
var//optimised for speed: 70,000 lines in ~270ms
   a,b,d,f:byte;
   p2,p,fLEN:longint;
begin
//defaults
result:=false;

try
fLEN:=low__len32(_find);
//check
if (_len=0) or (fLEN=0) or (fLEN>_LEN) then exit;
if (_pos<1) or (_pos>_len) then exit;//range check - 22apr2014
//.d
d:=ord(_find[1]);
if (d>=97) and (d<=122) then d:=d-32;//uppercase
//process
for p:=_pos to (_LEN-fLEN+1) do
begin
//.get
f:=ord(_data[p]);
if (f>=97) and (f<=122) then f:=f-32;//uppercase

//.compare
if (f=d) then
   begin
   //fLEN=1
   if (fLEN=1) then
      begin
      result:=true;
      _pos:=p;
      exit;
      end;

   //fLEN=2..n
   for p2:=2 to fLEN do
   begin

   a:=ord(_find[p2]);if (a>=97) and (a<=122) then a:=a-32;//uppercase
   b:=ord(_data[p+p2-1]);if (b>=97) and (b<=122) then b:=b-32;//uppercase
   if (a<>b) then break
   else if (p2=fLEN) then
      begin
      result:=true;
      _pos:=p;
      exit;
      end;

   end;//p2
   end;//if

end;//p
except;end;
end;

function low__readline(var _pos,_start,_length:longint;var _data:string):boolean;
var
   _winrc:boolean;
begin
result:=low__readlinec(_pos,_start,_length,_data,low__len32(_data),_winrc);
end;

function low__readlineb(var _pos,_start,_length:longint;var _data:string;var _winrc:boolean):boolean;
begin
result:=low__readlinec(_pos,_start,_length,_data,low__len32(_data),_winrc);
end;

function low__readlinec(var _pos,_start,_length:longint;var _data:string;_datalen:longint;var _winrc:boolean):boolean;//16may2022
var//Supports: Unix return codes "#10" and Windows/DOS return codes "#13+#10"
   lv,v:byte;
   p,LEN:longint;
begin
//defaults
result:=false;

try
_winrc:=false;
//check
if (_pos<1) then exit;
//init
LEN:=frcrange32(_datalen,0,low__len32(_data));//limit range to safe range - 29dec2018
if (len=0) then exit;
_start:=_pos;
_length:=0;
lv:=0;
//get
for p:=_pos to LEN do
begin
//.get
v:=ord(_data[p-1+stroffset]);

//.set
if ((v=10) or (p=LEN)) then
   begin
   //.length
   _length:=p-_start;
   if (lv=13) then
      begin
      _length:=_length-1;
      _winrc:=true;
      end
   else if (p=LEN) and (v<>10) then _length:=_length+1;
   //.pos
   _pos:=p+1;
   //.successful
   result:=true;
   break;
   end;//if
//.lv
lv:=v;
end;
except;end;
end;

function extstr(x:extended):string;//17sep2018
begin
result:=floattostrex2(x);
end;

function curstr(x:currency):string;//27nov2017
begin
result:=floattostrex2(x);
end;

function strcur(x:string):currency;//v1.00.070 - 07NOV2010
label
   skipone;
var //similar speed to "strtoint" - no errors are produced though
   n,xlen,z,y:longint;
   dotdiv:currency;
   dotok:boolean;
begin
//default
result:=0;

try
if (x='') then exit;
//init
xlen:=low__len32(x);
n:=1;
dotok:=false;
dotdiv:=10;
//get
z:=1;
while true do
begin
y:=byte(x[z-1+stroffset]);
if (y=45) then n:=-1
else if (y=ssComma) then//05jun2021
   begin
   //nil
   end
else
    begin
    //decide
    if (not dotok) and (y=46) then
       begin
       dotok:=true;//decimal point - 07NOV2010
       goto skipone;
       end
    else if (y<48) or (y>57) then break;
    //set - 07NOV2010
    case dotok of
    true:begin//5 digit max - (x/100,000)
       if (dotdiv<>0) then result:=result+((y-48)/nozero__cur(1200001,dotdiv));
       dotdiv:=dotdiv*10;
       if (dotdiv>=1000000) then break;
       end;
    else result:=result*10+y-48;
    end;//case
    end;
skipone:
inc(z);
if (z>xlen) then break;
end;//loop
//n
result:=result*n;
except;end;
end;

function int32(x:comp):longint;
begin//Note: Clip a 64bit longint32 to a 32bit longint32 range
if (x>max32) then x:=max32;
if (x<min32) then x:=min32;
result:=round(x);
end;

function int32RANGE(x,xmin,xmax:comp):longint;
begin//Note: Clip a 64bit longint32 to a 32bit longint32 range
//range
if (x<xmin) then x:=xmin;
if (x>xmax) then x:=xmax;
//32bit range
if (x>max32) then x:=max32;
if (x<min32) then x:=min32;
//get
result:=round(x);
end;

procedure safeinc(var x:longint);//16jun2014
begin
if (x<max32) then inc(x);
end;


//-- System Timer Support - ----------------------------------------------------
function low__timerfound(xowner:tobject;x:tnotifyevent):boolean;
var
   p:longint;
begin
//defaults
result:=false;

try
//check
if not assigned(x) then exit;
//find
for p:=0 to high(systimer_event) do if (xowner=systimer_owner[p]) and (@x=@systimer_event[p]) then
   begin
   result:=true;
   break;
   end;
except;end;
end;

function low__timerset(xowner:tobject;x:tnotifyevent;xdelay:comp):boolean;
var//Note: accepts "xowner=nil" but beware this timer will not be unique if more than one instance the object etc is used
   pnew,p:longint;
begin
//defaults
result:=false;
pnew:=-1;

try
//check
if not assigned(x) then exit;
//existing
for p:=0 to high(systimer_event) do
begin
if (xowner=systimer_owner[p]) and (@x=@systimer_event[p]) then
   begin
   systimer_delay[p]:=xdelay;
   if (sub64(systimer_ref64[p],slowms64)>xdelay) then systimer_ref64[p]:=slowms64;//fast reset incase last was a long delay - 05may2021
   result:=true;
   break;
   end
else if (pnew<0) and (not assigned(systimer_event[p])) and (not systimer_busy[p]) then pnew:=p;
end;//p
//new
if (not result) and (pnew>=0) then
   begin
   systimer_owner[pnew]:=xowner;//required as "tnotifyevents" on an object are NOT unique between instances of the same object - 19feb2021
   systimer_event[pnew]:=x;
   systimer_delay[pnew]:=xdelay;
   systimer_ref64[pnew]:=slowms64;//fast reset incase last was a long delay
   track__inc(satTimer,1);
   result:=true;
   end;
except;end;
end;

function low__timerdelay(xowner:tobject;x:tnotifyevent;xnewdelay:comp):boolean;
var
   p:longint;
begin
//defaults
result:=false;

try

//check
if not assigned(x) then exit;

//find
for p:=0 to high(systimer_event) do if (xowner=systimer_owner[p]) and (@x=@systimer_event[p]) then
   begin
   systimer_delay[p]:=xnewdelay;
   if (sub64(systimer_ref64[p],slowms64)>xnewdelay) then systimer_ref64[p]:=slowms64;//fast reset incase last was a long delay - 05may2021
   result:=true;
   break;
   end;

except;end;
end;

function low__timerfinddelay(xowner:tobject;x:tnotifyevent;var xdelay:comp):boolean;
var
   p:longint;
begin
//defaults
result:=false;
xdelay:=0;

try
//check
if not assigned(x) then exit;
//find
for p:=0 to high(systimer_event) do if (xowner=systimer_owner[p]) and (@x=@systimer_event[p]) then
   begin
   xdelay:=systimer_delay[p];
   result:=true;
   break;
   end;
except;end;
end;

function low__timerdel(xowner:tobject;x:tnotifyevent):boolean;
var
   p:longint;
begin
//defaults
result:=false;

try
//check
if not assigned(x) then exit;
//get
for p:=0 to high(systimer_event) do if (xowner=systimer_owner[p]) and (@x=@systimer_event[p]) then//works even when the timer is currently locked mid-way through firing the "_event()" proc - 19feb2021
   begin
   systimer_owner[p]:=nil;
   systimer_event[p]:=nil;
   systimer_delay[p]:=0;//off
   result:=true;
   track__inc(satTimer,-1);
   break;
   end;//p
except;end;
end;


//## trnd8 #####################################################################
constructor trnd8.create(xsize:longint);
var
   p:longint;
begin
//self
if classnameis('trnd8') then track__inc(satOther,1);
zzadd(self);
inherited create;
//range
imax:=frcmin32(xsize,100);
//vars
icore:=str__new8;
icore.setlen(imax+1);
for p:=0 to imax do icore.pbytes[p]:=random(256);//0..255 range
ipos:=0;
iposcount:=0;
end;

destructor trnd8.destroy;
begin
try
//controls
freeobj(@icore);
//self
inherited destroy;
if classnameis('trnd8') then track__inc(satOther,-1);
except;end;
end;

function trnd8.pull:byte;
begin
ipos:=ipos+1;
if (ipos>imax) then ipos:=0;
result:=icore.pbytes[ipos];
end;

function trnd8.pull2:byte;
begin
//get
if (ipos<imax) then result:=icore.pbytes[ipos] else result:=0;
//inc
if (iposcount>=500) then
   begin
   ipos:=ipos+random(51);
   iposcount:=0;
   end
else ipos:=ipos+1;//slightly faster than using "inc()"
if (ipos>imax) then ipos:=0;
inc(iposcount);
end;


//## tbwpbar ###################################################################
constructor tbwpbar.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tbwpbar.create2(xparent:tobject;xstart:boolean);
var
   p:longint;
begin

//self
if classnameis('tbwpbar') then track__inc(satBwpbar,1);
inherited create2(xparent,false);

//vars
itimer250             :=slowms64;
ibordersize           :=1;
iref                  :='';
icount                :=0;
ihoverindex           :=-1;
idownindex            :=-1;
ocanshowmenu          :=true;
ocancolor             :=true;
ocanalign             :=true;
ocanname              :=true;
ocansize              :=true;
opassiveWrap          :=false;
imustWrapStyle        :=-1;//off

//items
for p:=0 to high(iarea) do
begin

iarea[p]    :=nilrect;
ipert[p]    :=0;

end;

iname       :=xnew('name',30);
xnew('-',1);
isize       :=xnew('size',10);
xnew('-',1);
icolor      :=xnew('Color',15);
xnew('-',2);
inormal     :=xnew('N',4);
ibold       :=xnew('B',4);
iitalic     :=xnew('I',4);
iunderline  :=xnew('U',4);
istrikeout  :=xnew('S',4);
ihighlight  :=xnew('H',4);
xnew('-',2);
ileft       :=xnew('L',4);
icenter     :=xnew('C',4);
iright      :=xnew('R',4);
xnew('-',2);
iwrap       :=xnew('W',4);

//controls
//clientheight:=20;

//start
if xstart then start;

end;

destructor tbwpbar.destroy;
begin
try

inherited destroy;
if classnameis('tbwpbar') then track__inc(satBwpbar,-1);

except;end;
end;

function tbwpbar.mustWrapStyle(var xnewWrapStyle:longint32):boolean;//01mar2026
begin

if (imustWrapStyle>=0) then
   begin

   result             :=true;
   xnewWrapStyle      :=imustWrapStyle;
   imustWrapStyle     :=-1;//turn off
   
   end
else
   begin

   result             :=false;
   xnewWrapStyle      :=0;

   end;

end;


function tbwpbar.xnew(xcap:string;xpert:longint):longint;
begin

result                :=frcrange32(icount,0,high(iarea));
icap[result]          :=xcap;
ipert[result]         :=xpert;

inc(icount);

end;

function tbwpbar.getalignheight(xclientwidth:longint):longint;//15nov2023
begin

result:=frcmin32(round32(vilineheight30*viscale),1);

end;

function tbwpbar.findbox:tobject;
begin

if osysbox then result:=sysbox else result:=ibox;

end;

function tbwpbar.findbox2:tobject;
var
   x:tobject;
begin

//get
result :=nil;
x      :=findbox;

//set
if (x<>nil) then
   begin

   if (x is tbasicbwp) and (x as tbasicbwp).visible and (x as tbasicbwp).enabled and (not (x as tbasicbwp).oreadonly) then result:=x;

   end;
end;

procedure tbwpbar.showmenuFill(xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
var
   m:tstr8;//pointer only
   b:tobject;
   p,v:longint;

   procedure nsize(x:longint);
   begin
   low__menuitem(m,tepNone,intstr32(x),'Set font size to '+intstr32(x),'size.'+intstr32(x),100,true);
   end;

begin

//check
if zznil(xmenudata,2325) then exit else m:=xmenudata;
xmenuname :='bwpbar.1';
b         :=findbox2;

//get
if (xstyle='size') then
   begin

   v:=6;

   for p:=1 to 30 do
   begin

   nsize(v);
   if (v<=28) then inc(v,2) else inc(v,4);

   end;//p

   end
else if (xstyle='wrap') then
   begin

   if (b is tbasicbwp) then v:=(b as tbasicbwp).style
   else                     v:=0;

   low__menutitle(m,tepnone,'Word Wrap','Select word wrap style');
   low__menuitem(m,tep__tick(v=0),'None','No wrap','wrap.0',100,true);
   low__menuitem(m,tep__tick(v=1),'Window','Wrap to window','wrap.1',100,true);
   low__menuitem(m,tep__tick(v=2),'Page','Wrap to page','wrap.2',100,true);
   low__menuitem(m,tep__tick(v=3),'Page + 2x','Wrap to page','wrap.3',100,true);
   low__menuitem(m,tep__tick(v=4),'Manuscript','Wrap to manuscript','wrap.4',100,true);

   end;

end;

function tbwpbar.showmenuClick(sender:tobject;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
var
   v:longint;
   b:tobject;
begin

//handled
result  :=true;
b       :=findbox2;

if (strcopy1(xcode2,1,5)='size.') then
   begin

   v:=font__safesize( strint32(strcopy1(xcode2,6,low__len32(xcode2))) );

   if (b is tbasicbwp) then
      begin

      (b as tbasicbwp).core.csize:=v;
      (b as tbasicbwp).core.cwritesel__hasUndo(smFontsize);

      end;

   end

else if (strcopy1(xcode2,1,5)='wrap.') then
   begin

   v:=frcrange32(strint32(strcopy1(xcode2,6,low__len32(xcode2))),0,4);

   case opassiveWrap of
   true:imustWrapStyle:=v;
   else begin

      if (b is tbasicbwp) then (b as tbasicbwp).style:=v;

      end;
   end;//case

   end

//not handled
else result:=false;

end;

procedure tbwpbar._ontimer(sender:tobject);
var
   xmustpaint:boolean;
   b:tobject;
   int1,int2:longint;
begin
try
//defaults
xmustpaint:=false;

//.itimer250
if (slowms64>itimer250) then
   begin

   //box data has changed
   b     :=findbox2;
   int1  :=-1;
   int2  :=-1;

   if (b<>nil) then
      begin

      if (b is tbasicbwp) then
         begin

         int1:=(b as tbasicbwp).core.cursorpos;
         int2:=(b as tbasicbwp).core.dataid3;

         end;

      end;

   if low__setstr(iref,bolstr(ocanalign)+bolstr(ocancolor)+'|'+intstr32(int1)+'-'+intstr32(int2)) then xmustpaint:=true;

   //reset
   itimer250:=slowms64+250;

   end;

//paint
if xmustpaint then paintnow;

except;end;
end;

procedure tbwpbar.setbox(x:tbasicbwp);
begin

if (x<>ibox) then
   begin

   ibox:=x;
   paintnow;

   end;

end;

function tbwpbar.findindex(x,y:longint):longint;
var
   p:longint;
begin

result      :=-1;

for p:=(icount-1) downto 0 do if area__within(iarea[p],x,y) and (icap[p]<>'-') then
   begin

   result   :=p;
   break;

   end;//p

end;

function tbwpbar._onnotify(sender:tobject):boolean;
var
   v,int1:longint;
   xmustpaint:boolean;
   str1:string;
   b:tobject;

   function b1:tbasicbwp;
   begin
   result:=(b as tbasicbwp);
   end;

begin

//defaults
result      :=true;//handled

try
xmustpaint:=false;

//down index
if gui.mousedown and (not gui.mousewasdown) then
   begin

   if low__setint(idownindex,findindex(mousemovexy.x,mousemovexy.y)) then xmustpaint:=true;

   end;

//hover index
if low__setint(ihoverindex,findindex(mousemovexy.x,mousemovexy.y)) then xmustpaint:=true;


//mouse up
if (not gui.mousedown) and gui.mousewasdown then
   begin
   //.act - button was clicked
   v        :=idownindex;
   b        :=findbox2;

   if      (v=isize) then showmenu2('size')
   else if (v=iwrap) then showmenu2('wrap')

   //bwp -----------------------------------------------------------------------
   else if (b is tbasicbwp) then
      begin

      //.style
      if      (v=inormal)       then b1.core.cmakenormal(false)
      else if (v=ibold)         then b1.core.cmakebold(false,not b1.core.cbold)
      else if (v=iitalic)       then b1.core.cmakeitalic(false,not b1.core.citalic)
      else if (v=iunderline)    then b1.core.cmakeunderline(false,not b1.core.cunderline)
      else if (v=istrikeout)    then b1.core.cmakestrikeout(false,not b1.core.cstrikeout)
      else if (v=ihighlight)    then b1.core.cmakehighlight(false)

      //.align
      else if (v=ileft)         then b1.core.cmakeleft(false)
      else if (v=icenter)       then b1.core.cmakecenter(false)
      else if (v=iright)        then b1.core.cmakeright(false)

      //.name
      else if (v=iname)         then
         begin

         str1:=b1.core.cname;
         if gui.popfont2(str1,true,true,true,true,self) then b1.core.cmakename(false,str1);

         end

      //.color
      else if (v=icolor) then
         begin

         int1:=b1.core.ccolor;
         if gui.popcolor(int1) then b1.core.cmakecolor(false,int1);

         end

      end;//if

   //.turn off button
   if low__setint(idownindex,-1) then xmustpaint:=true;

   end;

//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);

//xmustpaint
if xmustpaint then paintnow;

except;end;
end;

procedure tbwpbar._onpaint(sender:tobject);
var
   s:tclientinfo;
   p,xnextx,dh,fc:longint;
   b:tobject;
   xbold,xitalic,xunderline,xstrikeout:boolean;
   xfontsize,xcolor,xbgcolor,xalign:longint;
   xfontname:string;

   function b1:tbasicbwp;
   begin
   result:=(b as tbasicbwp);
   end;

   procedure xnextarea(xindex:longint);
   var
      dw:longint;
   begin

   //range
   dw:=frcmin32( round((s.ci.right-s.ci.left)*(frcrange32(ipert[xindex],1,100)/100)) ,1);

   //get
   iarea[xindex].top:=s.ci.top;
   iarea[xindex].bottom:=s.ci.bottom;
   iarea[xindex].left:=xnextx-dw+1;
   iarea[xindex].right:=xnextx;

   if (xindex=0) then iarea[xindex].left:=s.ci.left;//use all remaining space

   //inc
   dec(xnextx,dw);

   end;

   procedure xdraw(xindex:longint);
   var
      a:twinrect;
      c:string;
      dx,dy:longint;
      amark,ahover,adown:boolean;

      function na(var x:twinrect):boolean;//no area
      begin

      result :=true;//pass-thru
      x      :=area__nil;

      end;
      
   begin

   //check
   if (ipert[xindex]<=0)                  then exit;

   if (not ocancolor) and (xindex=icolor) and na(iarea[xindex]) then exit;
   if (not ocansize)  and (xindex=isize)  and na(iarea[xindex]) then exit;
   if (not ocanname)  and (xindex=iname)  and na(iarea[xindex]) then exit;

   if (not ocanalign) then
      begin

      if (xindex=ileft) or (xindex=icenter) or (xindex=iright) then exit;

      end;

   //get
   a        :=iarea[xindex];
   c        :=icap[xindex];

   if (xindex=iname) then
      begin

      if (b<>nil) then c:=xfontname else c:=viFontname;

      //nice label - 01mar2026
      if      strmatch(c,font__name1) then c:='System Font 1'
      else if strmatch(c,font__name2) then c:='System Font 2';

      end

   else if (xindex=isize) then
      begin

      if (b<>nil) then c:=intstr32(xfontsize) else c:=intstr32(viFontsize);

      end;

   adown    :=(xindex=idownindex);
   ahover   :=(xindex=ihoverindex);
   amark    :=false;

   if (b<>nil) then
      begin

      if      (xindex=inormal)      then amark:=(not xbold) and (not xitalic) and (not xunderline) and (not xstrikeout) and (xbgcolor=clnone)
      else if (xindex=ibold)        then amark:=xbold
      else if (xindex=iitalic)      then amark:=xitalic
      else if (xindex=iunderline)   then amark:=xunderline
      else if (xindex=istrikeout)   then amark:=xstrikeout
      else if (xindex=ihighlight)   then amark:=(xbgcolor<>clnone)
      else if (xindex=ileft)        then amark:=(xalign=0)
      else if (xindex=icenter)      then amark:=(xalign=1)
      else if (xindex=iright)       then amark:=(xalign=2);

      end;

   //set
   if (c='-') then
      begin

      //space

      end
   else if (c<>'') then
      begin

      dx    :=a.left+(  ((a.right-a.left)-fast__textwidth('',c,fc))  div 2);
      dy    :=a.top+((dh-resfont__height(fc)) div 2);

      if adown then
         begin

         inc(dx);
         inc(dy);

         end;

      //.background
      if (ahover and (not adown)) or amark then ffillArea(a,s.hover,s.r);

      //.caption
      ftext( s.back ,s.ci ,dx ,dy ,s.font ,'' ,c ,fc ,true );

      end;

   end;

begin

//init
infovars(s);

dh          :=frcmin32(s.ch-(2*s.bs),1);
fc          :=s.fn;
xnextx      :=s.ci.right;
b           :=findbox2;

if (b is tbasicbwp) then
   begin

   xfontname    :=b1.core.cname;
   xfontsize    :=b1.core.csize;
   xbold        :=b1.core.cbold;
   xitalic      :=b1.core.citalic;
   xstrikeout   :=b1.core.cstrikeout;
   xunderline   :=b1.core.cunderline;
   xcolor       :=b1.core.ccolor;
   xbgcolor     :=b1.core.cbgcolor;
   xalign       :=b1.core.xfastfindalign( b1.core.cursorpos );

   end;

//size items
for p:=(icount-1) downto 0 do xnextarea(p);

//cls
ffillArea(s.cs,s.back,false);

//draw items - right to left to use ALL available space
for p:=(icount-1) downto 0 do xdraw(p);

//frame
xframeSimple( s );

end;


//-- Master Support - 15nov2023 ------------------------------------------------
procedure master__storevars(xvars:tvars8;xsyssettings,xprgsettings,xwidth,xheight,xcursor:boolean;xtitle:string);
var
   n,e:string;
   a:tstr8;
begin
try
//init
a:=nil;
//check
if (xvars=nil) then exit;
//init
a:=str__new8;
//get
if xsyssettings then xvars.d['_syssettings']:=syssettings.data;
if xprgsettings then xvars.d['_prgsettings']:=prgsettings.data;
if (sysprogram<>nil) then
   begin
   if xwidth       then xvars.i['_width']:=frcmin32(sysprogram.rootwin.clientwidth,0);
   if xheight      then xvars.i['_height']:=frcmin32(sysprogram.rootwin.clientheight,0);
   end;
if (xtitle<>'') then xvars.value['_title']:=xtitle;
//.cursor
if xcursor then
   begin
   //init
   io__fromfile(low__platsysext('cur.inf'),@a,e);
   n:=strlow(a.text);
   //get
   xvars.value['_curinf']:=n;
   //.system cursor
   if (n<>'default') and (n<>'custom') then
      begin
      io__fromfile(low__platsysext('cur'),@a,e);
      xvars.d['_syscur']:=a;
      end
   else xvars.value['_syscur']:='';
   //.custom cursor
   if (n='custom') then
      begin
      io__fromfile(low__platprgext('cur'),@a,e);
      xvars.d['_prgcur']:=a;
      end
   else xvars.value['_prgcur']:='';
   end;
except;end;

//free
freeobj(@a);

end;

procedure master__size(swidth,sheight:longint;var dwidth,dheight:longint);//uses smore: "width" and "height"
const
   xmin=32;
var
   int1:longint;
begin
try
//range
int1:=frcmin32(vizoom,1);
swidth:=frcmin32(swidth,xmin);
sheight:=frcmin32(sheight,xmin);
//decide
if not viMaster then
   begin
   if sysmore.found('_width')  then swidth:=frcmin32(sysmore.i['_width'],xmin);
   if sysmore.found('_height') then sheight:=frcmin32(sysmore.i['_height'],xmin);
   end;
dwidth:=swidth div int1;
dheight:=sheight div int1;
except;end;
end;

procedure master__title;//uses smore: "title"
var
   str1:string;
begin
try
if (not viMaster) and (sysprogram<>nil) and (app__gui<>nil) then
   begin
   str1:=sysmore.value['_title'];
   if sysprogram.rootwin.xhavehead then sysprogram.rootwin.xhead.caption:=str1;
   app__gui.caption:=str1;
   end;
except;end;
end;

procedure master__cursor;//uses smore: "cursor"
var
   a:tstr8;
   e:string;
begin
try
//init
a:=nil;
if not viMaster then
   begin
   //init
   a:=str__new8;
   //get
   if sysmore.dget('_prgcur',a) and (a.len>=1) then io__tofile(low__platprgext('cur'),@a,e);
   if sysmore.dget('_syscur',a) and (a.len>=1) then io__tofile(low__platsysext('cur'),@a,e);
   io__tofile(low__platsysext('cur.inf'),cache__ptr(sysmore.d['_curinf']),e);
   end;
except;end;

//free
str__free(@a);

end;

procedure master__cursorCLEAN;
begin
try

if not viMaster then
   begin

   io__remfile(low__platprgext('cur'));
   io__remfile(low__platsysext('cur'));
   io__remfile(low__platsysext('cur.inf'));

   end;

except;end;
end;


//-- Range Support -------------------------------------------------------------
function low__newid:longint;
begin//Range: 0..N
low__iroll(sysnewid,1);result:=sysnewid;
end;

function low__newid1:longint;
begin//Range: 1..N
low__iroll(sysnewid1,1);
if (sysnewid1<1) then sysnewid1:=1;
result:=sysnewid1;
end;

function largestwinrect(a,b:twinrect):twinrect;//12nov2017
begin
result:=a;
if (b.left<result.left) then result.left:=b.left;
if (b.top<result.top) then result.top:=b.top;
if (b.right>result.right) then result.right:=b.right;
if (b.bottom>result.bottom) then result.bottom:=b.bottom;
end;

function low__xyinarea(sx,sy:longint;xarea:twinrect):boolean;
begin
result:=(xarea.left<=xarea.right) and (xarea.top<=xarea.bottom) and (sx>=xarea.left) and (sx<=xarea.right) and (sy>=xarea.top) and (sy<=xarea.bottom);
end;

function low__ptinarea(x:tpoint;xarea:twinrect):boolean;
begin
result:=(xarea.left<=xarea.right) and (xarea.top<=xarea.bottom) and (x.x>=xarea.left) and (x.x<=xarea.right) and (x.y>=xarea.top) and (x.y<=xarea.bottom);
end;

function low__areaequal(a,b:twinrect):boolean;
begin
result:=(a.left=b.left) and (a.top=b.top) and (a.right=b.right) and (a.bottom=b.bottom);
end;

function largestcur(a,b:currency):currency;//20jan2016
begin
if (a<b) then result:=b else result:=a;
end;

function csmallestex(a:array of currency):currency;//22JAN2008
var
   p:longint;
begin
result:=maxcur;
for p:=low(a) to high(a) do if (a[p]<result) then result:=a[p];
end;

function clargestex(a:array of currency):currency;//22JAN2008
var
   p:longint;
begin
result:=mincur;
for p:=low(a) to high(a) do if (a[p]>result) then result:=a[p];
end;

function frccurmax(x,max:currency):currency;
begin
if (x>max) then result:=max else result:=x;
end;

function frcrangeex(x,min,max,defvalue:longint):longint;//14-JAN-2007
begin
if (x=0) then x:=defvalue;
result:=frcrange32(x,min,max);
end;

function frccurrange(x,min,max:currency):currency;//date: 02-APR-2004
begin
result:=x;
if (result<min) then result:=min;
if (result>max) then result:=max;
end;

function frcextmin(x,min:extended):extended;//07NOV20210
begin
if (x<min) then result:=min else result:=x;
end;

function frcextrange(x,min,max:extended):extended;//06JUN2007
begin
result:=x;
if (result<min) then result:=min;
if (result>max) then result:=max;
end;

function low__setbc(var xdata:tbasiccontrol;xnewvalue:tbasiccontrol):boolean;//15mar2021
begin
if (xnewvalue<>xdata) then
   begin
   result:=true;
   xdata:=xnewvalue;
   end
else result:=false;
end;

function low__vifontscale(xwidth:longint):longint;//use to scale width of columns and height of other items according to current "viFontheight" setting based on a default value of "16"
begin
result:=round((vifontheight/14)*xwidth);
end;

function low__maplist(const x:array of byte):tlistptr;
begin
if (low(x)=0) then
   begin
   result.count:=high(x)+1;
   result.bytes:=@x;
   end
else
   begin
   result.count:=0;
   result.bytes:=nil;
   end;
end;

function low__maplist2(x:tstr8):tlistptr;//07apr2021
begin
if str__lock(@x) and (not x.oautofree) then result:=x.maplist
else
   begin
   result.count:=0;
   result.bytes:=nil;
   end;
str__uaf(@x);
end;

function low__compareint(x,xval:longint):boolean;
begin
result:=(x=xval);

if not result then
   begin
   if (x>=97) and (x<=122)       then dec(x,32);//a-z -> A-Z
   if (xval>=97) and (xval<=122) then dec(xval,32);//a-z -> A-Z
   result:=(x=xval);
   end;
end;

function low__strASarray__debugonly(xdata:string):string;
var//WARNING: Not to be used in a program -> for strict debug and data
   //         management use only -> will not work in D10 - 19aug2020
   xlen,p:longint;
begin
//defaults
result:='';

try
//check
xlen:=low__len32(xdata);
if (xlen<=0) then exit;
//get
for p:=1 to xlen do
begin
result:=result+intstr32(byte(xdata[p-1+stroffset]));
if (p<xlen) then result:=result+',';
end;
result:='['+result+']';
except;end;
end;

function low__trimdec(x:string):string;//01aug2021
begin//auto trim ".0" or  ".10" or  ".100"
result:=x;

try
if (strcopy1(result,low__len32(result)-1,2)='.0') then result:=strcopy1(result,1,low__len32(result)-2)
else if (strcopy1(result,low__len32(result)-2,3)='.10') then result:=strcopy1(result,1,low__len32(result)-1)
else if (strcopy1(result,low__len32(result)-3,4)='.100') then result:=strcopy1(result,1,low__len32(result)-2);
except;end;
end;

//-- Color Support -------------------------------------------------------------
function low__makepertD0(xpos,xlen:longint):double;//22nov2024, 06mar2022
begin//Note: xpos=0..(len-1)
//init
result:=0;
xlen:=frcrange32(xlen,0,max32);
xpos:=frcrange32(xpos,0,xlen);
//get
try
result:=(xpos/frcmin32(xlen-1,1))*100;
if (result<0) then result:=0 else if (result>100) then result:=100;
except;end;
end;

function low__rateASstatus(_starttime64:currency;_totalBYTES:comp):string;
begin
result:=low__mbauto(low__rateASbytes32(_starttime64,_totalBYTES),true)+'/'+translate('sec');
end;

function low__rateASbytes32(_starttime64:currency;_totalBYTES:comp):longint;
var
   _rate,_sec:currency;
begin
//range
_totalBYTES:=restrict64(_totalBYTES);
//get
//.sec
_sec:=slowms64;
_sec:=_sec-_starttime64;
_sec:=_sec/1000;//ms -> sec
if (_sec<1) then _sec:=1;
//.rate
if (_totalBYTES<0) then _totalBYTES:=0;
_rate:=_totalBYTES/nozero__cur(1200017,_sec);
//.range
if (_rate<0) then _rate:=0
else if (_rate>max32) then _rate:=max32;
//set
result:=round(_rate);
end;

procedure low__minwh(var a:twinrect;const aminwidth,aminheight:longint);//14dec2025, 25feb2021
begin
a.right   :=frcmin32(a.right  ,a.left  + frcmin32(aminwidth,0)  );
a.bottom  :=frcmin32(a.bottom ,a.top   + frcmin32(aminheight,0) );
end;

function low__cap2432(const xpos,ypos,dw,dh:longint;const d:tobject):boolean;//low version - 07mar2020, 30may2019, 21jan2015, 17-JAN-2007
begin
result:=low__cap2432c(xpos,ypos,dw,dh,d);
end;

function low__cap2432c(xpos,ypos,dw,dh:longint;const d:tobject):boolean;//17nov2024: xpos/ypos range checking dropped for multi-monitor support, low version - 09sep2021, 07mar2020, 30may2019, 21jan2015, 17-JAN-2007
label//Note: doutofrangeColor=optional=clNone=disabled, else paint this color and capture overtop
   skipend;
var//Stabilised and verified at 21jan2015
   a:twinbmp;
   dc:hauto;
   h:hauto;
   dbits,sw,sh:longint;
   sa:twinrect;
begin
//defaults
result :=false;
a      :=nil;

try
//range
if not misok2432(d,dbits,sw,sh) then exit;

//init
sa:=monitors__totalarea;
sw:=frcmin32(sa.right-sa.left+1,1);
sh:=frcmin32(sa.bottom-sa.top+1,1);

//.size
if (dw<1) then dw:=sw;
if (dh<1) then dh:=sh;
dw:=frcrange32(dw,1,sw);
dh:=frcrange32(dh,1,sh);
if (misw(d)<>dw) or (mish(d)<>dh) then
   begin
   missize(d,1,1);
   if not missize(d,dw,dh) then goto skipend;
   end;

//.pos
xpos:=frcrange32(xpos,sa.left,frcmin32(sa.right-(dw-1),sa.left));
ypos:=frcrange32(ypos,sa.top,frcmin32(sa.bottom-(dh-1),sa.top));

//init
h  :=win____getdesktopwindow;
dc :=win____getwindowdc(h);
a  :=miswin32(dw,dh);

//.screen -> a
a.copyarea2(misarea(a),misrect(xpos,ypos,xpos+dw-1,ypos+dh-1),dc);

//a -> d
mis__copyfast(maxarea,misarea(a),0,0,dw,dh,a,d);

//clear
win____releasedc(h,dc);
//successful
result:=true;
skipend:
except;end;
//free
freeobj(@a);
end;

function low__cap2432b(const d:tobject):boolean;
begin//Note: Capture fullscreen
result:=low__cap2432(0,0,0,0,d);
end;

function low__capcolor(const xpos,ypos:longint;const xfromcursor:boolean):longint;//09sep2025
begin

case viwine and (app__gui<>nil) and (app__gui.rootwin<>nil) of
true:result:=low__capcolor2(xpos,ypos,xfromcursor,app__gui.rootwin,true);//09sep2025: Mac and Linux fail to screen capture color -> default to main window buffer color capture - 09sep2025
else result:=low__capcolor2(xpos,ypos,xfromcursor,nil,false);
end;//case

end;

function low__capcolor2(xpos,ypos:longint;const xfromcursor:boolean;const xfromGUIbuffer:tbasiccontrol;const xforceGUIbuffer:boolean):longint;//09sep2025
label
   skipend;
var
   a:twinbmp;
   b:tpoint;
   dx,dy:longint;
   c:tint4;
   c24:tcolor24;
   xfrombufferOK:boolean;
begin
//defaults
result        :=0;
xfrombufferOK :=false;
a             :=nil;

try

//init
if xfromcursor then
   begin
   low__getcursorpos(b);
   xpos:=b.x;
   ypos:=b.y;
   end;

//get
//.from buffer -> capture color directly from system.gui.buffer to avoid capturing the wrong color due to a system background image and/or system brightness setting - 24jul2024
if (xfromGUIbuffer<>nil) and (xfromGUIbuffer.gui<>nil) and (xforceGUIbuffer or xfromGUIbuffer.gui.paintedwithtile) then
   begin

   dx  :=xpos-xfromGUIbuffer.gui.left;
   dy  :=ypos-xfromGUIbuffer.gui.top;

   if area__within(area__make(0,0,xfromGUIbuffer.gui.width-1,xfromGUIbuffer.gui.height-1),dx,dy) and area__within(misarea(xfromGUIbuffer.gui.buffer),dx,dy) then
      begin

      xfrombufferOK :=true;
      c24           :=mispixel24(xfromGUIbuffer.gui.buffer,dy,dx);
      c.r           :=c24.r;
      c.g           :=c24.g;
      c.b           :=c24.b;
      c.a           :=0;
      result        :=c.val;

      end;

   end;

//.from screen
if not xfrombufferOK then
   begin

   a   :=miswin32(1,1);
   if low__cap2432(xpos,ypos,1,1,a) then result:=rgba0__int(a.prows32[0][0].r,a.prows32[0][0].g,a.prows32[0][0].b);

   end;

skipend:
except;end;
//free
freeobj(@a);
end;

function low__firstnbl(xdata,xoutdata:tstr8):boolean;//first non-blank line
label
   skipend;
var
   xline:tstr8;
   p:longint;
begin
//defaults
result:=false;

try
xline:=nil;
str__lock(@xdata);
str__lock(@xoutdata);
//check
if zznil(xdata,2198) or zznil(xoutdata,2199) then goto skipend;
//init
xline:=str__new8;
p:=0;
//get
while low__nextline0(xdata,xline,p) do if (xline.count>=1) then
   begin
   xoutdata.replace:=xline;
   result:=true;
   break;
   end;
skipend:
except;end;
try
freeobj(@xline);
str__uaf(@xdata);
str__uaf(@xoutdata);
except;end;
end;

function low__firstnbl2(const xtext:string):string;
var
   a,b:tstr8;
begin

//defaults
result :='';

//check
if (xtext='') then exit;

//init
a      :=nil;
b      :=nil;

try
//get
a      :=str__new8b(xtext);
b      :=str__new8;

if low__firstnbl(a,b) then result:=b.text;

except;end;

//free
freeobj(@a);
freeobj(@b);

end;


//-- keyboard support ----------------------------------------------------------
function low__shortcutOK(xcode:longint):boolean;//true=ak_key is assumed to be a shortcut key, false=else not
begin//Note: xcode is an action code, e.g. akctrlA => "CTRL+A"
result:=false;
case xcode of
akctrlA..akctrlZ,akaltA..akaltZ,akF1..akF12:result:=true;
end;//case
end;

function low__akstr(xcode:longint;var xtext:string):boolean;
label//Note: xcode is an action code, e.g. akctrlA => "CTRL+A"
   skipend;
begin
//defaults
result:=false;
xtext:='';

try
//get
case xcode of
0..255                 :xtext:=char(xcode);
akctrlA..akctrlZ       :xtext:='Ctrl+'+char(65+xcode-akctrlA);
akaltA..akaltZ         :xtext:='Alt+' +char(65+xcode-akaltA);
akf1..akf12            :xtext:='F'    +intstr32(xcode-akf1+1);
akreturn               :xtext:=#13;
akreturn_press         :xtext:=#13;//31mar2021
aktab                  :xtext:=#9;
akdelete               :xtext:='Delete';
akback                 :xtext:='Back';
akescape               :xtext:='Esc';
//.direction keys
akleft                 :xtext:='Left';
akright                :xtext:='Right';
akup                   :xtext:='Up';
akdown                 :xtext:='Down';
//.extended direction keys
akhome                 :xtext:='Home';
akend                  :xtext:='End';
akprev                 :xtext:='Prev';
aknext                 :xtext:='Next';
else goto skipend;
end;//case
//successful
result:=true;
skipend:
except;end;
end;

function low__akstrb(xcode:longint):string;
begin
low__akstr(xcode,result);
end;

function low__keyboard__fromak(xcode:longint;var xctrl,xalt,xshift,xkeyx:boolean;var xkey:longint;var xhavekey:boolean):boolean;
label
   redo;
var
   xonce:boolean;

   procedure kx(xval:longint);
   begin
   xkey:=xval;
   xkeyx:=true;
   xhavekey:=true;
   end;
begin
//defaults
result:=false;
xonce   :=true;
xctrl   :=false;
xalt    :=false;
xshift  :=false;
xkeyx   :=false;
xkey    :=63;//?
xhavekey:=false;

try
//check
if (xcode=aknone) then exit;
//get
redo:
case xcode of
0..255:begin
   xkey:=xcode;
   xhavekey:=true;
   end;
akshift        :xshift:=true;
akshiftup      :xshift:=false;
akreturn       :kx(13);
akreturn_press :kx(13);//31mar2021
aktab          :kx(9);
akback         :kx(vkback);
akdelete       :kx(vkdelete);
akleft         :kx(vkleft);
akright        :kx(vkright);
akup           :kx(vkup);
akdown         :kx(vkdown);
akprev         :kx(vkprior);
aknext         :kx(vknext);
akhome         :kx(vkhome);
akend          :kx(vkend);
akaltA..akaltZ :begin
   xkeyx:=true;
   xkey:=65+(xcode-akaltA);
   xhavekey:=true;
   xalt:=true;
   end;
akctrlA..akctrlZ :begin
   xkeyx:=true;
   xkey:=65+(xcode-akctrlA);
   xhavekey:=true;
   xctrl:=true;
   end;
akf1..akf12:begin
   kx(vkf1+(xcode-akf1));
   end;
akctrlNone..akctrlLast:if xonce then
   begin
   xonce:=false;
   xctrl:=true;
   xcode:=xcode-akctrlnone+aknone;//convert from "akctrlleft -> akleft" - 31mar2021
   goto redo;
   end;
akaltNone..akaltLast:if xonce then
   begin
   xonce:=false;
   xalt:=true;
   xcode:=xcode-akaltnone+aknone;//convert from "akaltleft -> akleft" - 31mar2021
   goto redo;
   end;
end;
except;end;
end;

function low__keyboard(xstyle:char;xkey:longint;xshift,xctrl,xalt:boolean;var xoutkey:longint):boolean;
begin
result:=low__keyboard2(xstyle,xkey,xshift,xctrl,xalt,xoutkey,syskeyboard_laststate);
end;

function low__keyboard2(xstyle:char;xkey:longint;xshift,xctrl,xalt:boolean;var xoutkey:longint;var xlaststate:byte):boolean;
label//tshiftstate = set of (ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble);
   skipend;
var
   a:tint4;
   xval:longint;
   sshift,sctrl,salt:boolean;
   b1:byte;
begin
//defaults
result:=false;
xoutkey:=aknone;
xval:=aknone;

try
//init
sshift:=false;
sctrl:=false;
salt:=false;
b1:=xlaststate;
if (b1>=4) then
   begin
   salt:=true;
   dec(b1,4);
   end;
if (b1>=2) then
   begin
   sctrl:=true;
   dec(b1,2);
   end;
if (b1>=1) then sshift:=true;
if ((xstyle='d') or (xstyle='u')) and ((xshift<>sshift) or (xctrl<>sctrl) or (xalt<>salt)) then result:=true;
//get
if      (xstyle='d') then
   begin
   case xkey of
   vkdelete:xval:=akdelete;
   vkback:xval:=akback;
   //.direction keys
   vkleft: xval:=akleft   +low__aorb(low__insint(akctrlNone-aknone,xctrl),akaltNone-aknone,xalt);
   vkright:xval:=akright  +low__aorb(low__insint(akctrlNone-aknone,xctrl),akaltNone-aknone,xalt);
   vkup:   xval:=akup     +low__aorb(low__insint(akctrlNone-aknone,xctrl),akaltNone-aknone,xalt);
   vkdown: xval:=akdown   +low__aorb(low__insint(akctrlNone-aknone,xctrl),akaltNone-aknone,xalt);
   //.extended direction keys
   vkprior:xval:=akprev;
   vknext:xval:=aknext;
   vkhome:xval:=akhome;
   vkend:xval:=akend;
   else
      begin
      if xctrl and (xkey>=akA) and (xkey<=akZ) then xval:=akctrlA+(xkey-akA)//auto repeat support = YES - 01apr2020
      else if not result then goto skipend;
      end;
   end;
   end
else if (xstyle='p') or (xstyle='k') then
   begin
   //range: 32 - 255 and 13 - 31mar2021
   if (not xctrl) and (not xalt) and (xkey>=32) and (xkey<=255) then xval:=xkey
   else if (xkey=vkreturn) then xval:=akreturn_press
   else goto skipend;
   end
else if (xstyle='u') then
   begin
   case xkey of
   vkescape:xval:=akescape;
   vkreturn:xval:=akreturn;
   vktab:xval:=aktab;
   vkf1:xval:=akf1;
   vkf2:xval:=akf2;
   vkf3:xval:=akf3;
   vkf4:xval:=akf4;
   vkf5:xval:=akf5;
   vkf6:xval:=akf6;
   vkf7:xval:=akf7;
   vkf8:xval:=akf8;
   vkf9:xval:=akf9;
   vkf10:xval:=akf10;
   vkf11:xval:=akf11;
   vkf12:xval:=akf12;
   else
      begin
      if xalt and (xkey>=akA) and (xkey<=akZ) then xval:=akaltA+(xkey-akA)//auto repeat support = NO - 01apr2020
      else if not result then goto skipend;
      end;
   end;//case
   end;
//set
b1:=0;
if xshift then inc(b1,1);
if xctrl  then inc(b1,2);
if xalt   then inc(b1,4);
a.val:=xval;
a.bytes[3]:=b1;
xoutkey:=a.val;
xlaststate:=b1;
//successful
result:=true;
skipend:
except;end;
end;

function low__makebasic__akkey(xkey:longint):longint;//22jul2025
begin

case xkey of
vkdelete:    result:=akdelete;
vkback:      result:=akback;
vkescape:    result:=akescape;
vkreturn:    result:=akreturn;
vktab:       result:=aktab;
vkf1..vkf12: result:=akf1+(xkey-vkf1);

//.direction keys
vkleft:      result:=akleft;
vkright:     result:=akright;
vkup:        result:=akup;
vkdown:      result:=akdown;

//.extended direction keys
vkprior:    result:=akprev;
vknext:     result:=aknext;
vkhome:     result:=akhome;
vkend:      result:=akend;

//.other
else if (xkey>=32) then result:=xkey else result:=aknone;
end;//case

end;


//-- mouse support -------------------------------------------------------------
procedure low__mousefine_turnon(x:boolean);
begin
if x then low__mouse(nil,'f.on') else low__mouse(nil,'f.off');
end;

function low__mousefine:boolean;
begin
result:=sysmouse_fine;
end;

function low__mouse(x:tobject;xstyle:string):tpoint;
const
   xval=5;
var
   a:tpoint;

   procedure xsync(xdown,xmove:boolean);
   begin
   case low__mousefine of
   true:begin
      a.x:=sysmouse_downxy.x+((a.x-sysmouse_movexy.x) div xval);
      a.y:=sysmouse_downxy.y+((a.y-sysmouse_movexy.y) div xval);
      end;
   else begin
      if xdown then sysmouse_downxy:=a;
      if xmove then sysmouse_movexy:=a;
      end;
   end;
   end;
begin
//defaults
result:=low__point(0,0);

try
xstyle:=strlow(xstyle);
//get
//.style
if      (xstyle='d') then
   begin
   a:=miscursorpos;
   xsync(true,true);
   sysmouse_down:=true;
   result:=a;
   end
else if (xstyle='m') then
   begin
   a:=miscursorpos;
   xsync(false,true);
   result:=a;
   end
else if (xstyle='u') then
   begin
   a:=miscursorpos;
   xsync(false,true);
   sysmouse_down:=false;//18mar2020
   result:=a;
   end
else if (xstyle='f.on') then//turn fine mode ON
   begin
   //off -> on
   if not low__mousefine then
      begin
      a:=miscursorpos;
      sysmouse_downxy:=a;
      sysmouse_movexy:=a;
      end;
   sysmouse_fine:=true;
   end
else if (xstyle='f.off') then//turn fine mode OFF
   begin
   sysmouse_fine:=false;
   end
else if system_debug then showerror('Mouse directive "'+xstyle+'" not supported');//15nov2022
//.localise
if (x<>nil) then
   begin
   //was:   if zzok(x,7040) and (x is tcommonform) then a:=(x as tcommonform).clienttoscreen(low__point(0,0)) else a:=low__point(0,0);
   //was: if zzok(x,7040) and (x is tcommonform) then a:=low__clienttoscreen(x,low__point(0,0)) else a:=low__point(0,0);
   if (x<>nil) and (x is tbasicsystem) then a:=low__clienttoscreen(x,low__point(0,0)) else a:=low__point(0,0);

   result.x:=result.x-a.x;
   result.y:=result.y-a.y;
   end;
except;end;
end;

procedure low__mouse2(x:tobject;xstyle:string;var dx,dy:longint);
var
   a:tpoint;
begin
a:=low__mouse(x,xstyle);
dx:=a.x;
dy:=a.y;
end;

function low__getcursorpos(var x:tpoint):boolean;
begin//As a function this proc can be used inline, e.g. if a and b and "low__getcursorpos(c)" and (c.x>=n) and (c.y>=n2) then ....
result:=true;
x:=low__mouse(nil,'m');
end;

function low__getcursorposb:tpoint;
begin
result:=low__mouse(nil,'m');
end;

function low__getcursordownpos(var x:tpoint):boolean;
begin//As a function this proc can be used inline, e.g. if a and b and "low__getcursorpos(c)" and (c.x>=n) and (c.y>=n2) then ....
result:=true;
x:=sysmouse_downxy;
end;

function low__getcursordownposb:tpoint;
begin
low__getcursordownpos(result);
end;


//-- raw support ---------------------------------------------------------------
function low__imgdraw2432(s:tobject;stransparent:boolean;d:tobject;dx,dy,dswapblack:longint;dclip:twinrect;xgreyscale,xfocus:boolean):boolean;
label
   skipend;
const
   fv=30;
var
   v,sbits,sw,sh,dbits,ddx,ddy,dw,dh,sx,sy:longint;
   dr24,sr24:pcolorrow24;
   dr32,sr32:pcolorrow32;
   c24,cswapblack:tcolor24;
   c32:tcolor32;
   //.transparency
   tr,tg,tb:byte;
   dswap,tok:boolean;

   procedure g24;
   begin
   if (c24.g>c24.r) then c24.r:=c24.g;
   if (c24.b>c24.r) then c24.r:=c24.b;
   if (c24.r<100) then c24.r:=100;
   c24.g:=c24.r;
   c24.b:=c24.r;
   end;

   procedure g32;
   begin
   if (c32.g>c32.r) then c32.r:=c32.g;
   if (c32.b>c32.r) then c32.r:=c32.b;
   if (c32.r<100) then c32.r:=100;
   c32.g:=c32.r;
   c32.b:=c32.r;
   end;

   procedure f24;
   begin
   //.r
   v:=c24.r+fv;
   if (v<100) then v:=100;
   if (v>255) then v:=255;
   c24.r:=byte(v);
   //.g
   v:=c24.g+fv;
   if (v<100) then v:=100;
   if (v>255) then v:=255;
   c24.g:=byte(v);
   //.b
   v:=c24.b+fv;
   if (v<100) then v:=100;
   if (v>255) then v:=255;
   c24.b:=byte(v);
   end;

   procedure f32;
   begin
   //.r
   v:=c32.r+fv;
   if (v<100) then v:=100;
   if (v>255) then v:=255;
   c32.r:=byte(v);
   //.g
   v:=c32.g+fv;
   if (v<100) then v:=100;
   if (v>255) then v:=255;
   c32.g:=byte(v);
   //.b
   v:=c32.b+fv;
   if (v<100) then v:=100;
   if (v>255) then v:=255;
   c32.b:=byte(v);
   end;
begin
//defaults
result:=false;
tr:=0;
tg:=0;
tb:=0;

try
//check
//.s
if zznil(s,2209) then exit;
sw:=misw(s);
sh:=mish(s);
sbits:=misb(s);
if (sw<1) or (sh<1) or ((sbits<>24) and (sbits<>32)) then exit;
//.d
if zznil(d,2210) then exit;
dw:=misw(d);
dh:=mish(d);
dbits:=misb(d);
if (dw<1) or (dh<1) or ((dbits<>24) and (dbits<>32)) then exit;
//init
//.dclip
dclip.left:=frcrange32(dclip.left,0,dw-1);
dclip.right:=frcrange32(dclip.right,dclip.left,dw-1);
dclip.top:=frcrange32(dclip.top,0,dh-1);
dclip.bottom:=frcrange32(dclip.bottom,dclip.top,dh-1);
//.check -> dx/dy out of range -> do nothing
if (dx>dclip.right) or ((dx+sw)<dclip.left) or (dy>dclip.bottom) or ((dy+sh)<dclip.top) then
   begin
   result:=true;
   goto skipend;
   end;
//.tok
tok:=stransparent;
if tok then
   begin
   if not misscan2432(s,0,sr24,sr32) then goto skipend;
   case sbits of
   24:begin
      tr:=sr24[0].r;
      tg:=sr24[0].g;
      tb:=sr24[0].b;
      end;
   32:begin
      tr:=sr32[0].r;
      tg:=sr32[0].g;
      tb:=sr32[0].b;
      end;
   end;//case
   end;
//.dswapblack
dswap:=(dswapblack<>clnone);
if dswap then cswapblack:=int__c24(dswapblack);

//.s24 -> d24
if (sbits=24) and (dbits=24) then
   begin
   for sy:=0 to (sh-1) do
   begin
   ddy:=dy+sy;
   if (ddy>=dclip.top) and (ddy<=dclip.bottom) then
      begin
      if not misscan2432(s,sy,sr24,sr32) then goto skipend;
      if not misscan2432(d,ddy,dr24,dr32) then goto skipend;
      for sx:=0 to (sw-1) do
      begin
      ddx:=dx+sx;
      if (ddx>=dclip.left) and (ddx<=dclip.right) then
         begin
         c24:=sr24[sx];
         if (not tok) or (tr<>c24.r) or (tg<>c24.g) or (tb<>c24.b) then
            begin
            if dswap and (c24.r=0) and (c24.g=0) and (c24.b=0) then c24:=cswapblack;
            if xfocus then f24;
            if xgreyscale then g24;
            dr24[ddx]:=c24;
            end;
         end;//ddx
      end;//sx
      end;//ddy
   end;//sy
   end
//.s24 -> d32
else if (sbits=24) and (dbits=32) then
   begin
   for sy:=0 to (sh-1) do
   begin
   ddy:=dy+sy;
   if (ddy>=dclip.top) and (ddy<=dclip.bottom) then
      begin
      if not misscan2432(s,sy,sr24,sr32) then goto skipend;
      if not misscan2432(d,ddy,dr24,dr32) then goto skipend;
      for sx:=0 to (sw-1) do
      begin
      ddx:=dx+sx;
      if (ddx>=dclip.left) and (ddx<=dclip.right) then
         begin
         c24:=sr24[sx];
         if (not tok) or (tr<>c24.r) or (tg<>c24.g) or (tb<>c24.b) then
            begin
            if dswap and (c24.r=0) and (c24.g=0) and (c24.b=0) then c24:=cswapblack;
            c32.r:=c24.r;
            c32.g:=c24.g;
            c32.b:=c24.b;
            c32.a:=255;//fully solid
            if xfocus then f32;
            if xgreyscale then g32;
            dr32[ddx]:=c32;
            end;
         end;//ddx
      end;//sx
      end;//ddy
   end;//sy
   end
//.s32 -> d24
else if (sbits=32) and (dbits=24) then
   begin
   for sy:=0 to (sh-1) do
   begin
   ddy:=dy+sy;
   if (ddy>=dclip.top) and (ddy<=dclip.bottom) then
      begin
      if not misscan2432(s,sy,sr24,sr32) then goto skipend;
      if not misscan2432(d,ddy,dr24,dr32) then goto skipend;
      for sx:=0 to (sw-1) do
      begin
      ddx:=dx+sx;
      if (ddx>=dclip.left) and (ddx<=dclip.right) then
         begin
         c32:=sr32[sx];
         if (not tok) or (tr<>c32.r) or (tg<>c32.g) or (tb<>c32.b) then
            begin
            if dswap and (c32.r=0) and (c32.g=0) and (c32.b=0) then
               begin
               c32.r:=cswapblack.r;
               c32.g:=cswapblack.g;
               c32.b:=cswapblack.b;
               end;
            c24.r:=c32.r;
            c24.g:=c32.g;
            c24.b:=c32.b;
            if xfocus then f24;
            if xgreyscale then g24;
            dr24[ddx]:=c24;
            end;
         end;//ddx
      end;//sx
      end;//ddy
   end;//sy
   end
//.s32 -> d32
else if (sbits=32) and (dbits=32) then
   begin
   for sy:=0 to (sh-1) do
   begin
   ddy:=dy+sy;
   if (ddy>=dclip.top) and (ddy<=dclip.bottom) then
      begin
      if not misscan2432(s,sy,sr24,sr32) then goto skipend;
      if not misscan2432(d,ddy,dr24,dr32) then goto skipend;
      for sx:=0 to (sw-1) do
      begin
      ddx:=dx+sx;
      if (ddx>=dclip.left) and (ddx<=dclip.right) then
         begin
         c32:=sr32[sx];
         if (not tok) or (tr<>c32.r) or (tg<>c32.g) or (tb<>c32.b) then
            begin
            if dswap and (c32.r=0) and (c32.g=0) and (c32.b=0) then
               begin
               c32.r:=cswapblack.r;
               c32.g:=cswapblack.g;
               c32.b:=cswapblack.b;
               end;
            if xfocus then f32;
            if xgreyscale then g32;
            dr32[ddx]:=c32;
            end;
         end;//ddx
      end;//sx
      end;//ddy
   end;//sy
   end;
//successful
result:=true;
skipend:
except;end;
end;


//system font procs ------------------------------------------------------------

procedure font__smallfont(const xinfo:tvirtualinfo;var xresfont,xfontheight:longint);
begin

font__smallfont2(xinfo,1.0,xresfont,xfontheight);

end;

procedure font__smallfont2(const xinfo:tvirtualinfo;const xscaleThreshold:double;var xresfont,xfontheight:longint);
begin

//use smaller font2 for scaling < 100%
case (viscale>=xscaleThreshold) of
true:begin

   xresfont    :=xinfo.Rfs;
   xfontheight :=xinfo.fsH;

   end;
else begin

   xresfont    :=xinfo.Rfs2;
   xfontheight :=xinfo.fsH2;

   end;
end;//case

end;


//## tbasicapp #################################################################
function sysprogram:tbasicapp;
begin
if (system_program<>nil) and (system_program is tbasicapp) then result:=(system_program as tbasicapp) else result:=nil;
end;

function sysprogram_monitorindex:longint;
begin
if (sysprogram<>nil) and (sysprogram.gui<>nil) then result:=sysprogram.gui.monitorindex else result:=monitors__primaryindex;
end;

function sysprogram_wh(var dw,dh:longint):boolean;
begin
if (sysprogram<>nil) and (sysprogram.rootwin<>nil) then
   begin
   dw:=sysprogram.rootwin.clientwidth;
   dh:=sysprogram.rootwin.clientheight;
   result:=true;
   end
else
   begin
   dw:=0;
   dh:=0;
   result:=false;
   end;
end;

constructor tbasicapp.create(dwidth,dheight:longint);
begin//Note: dwidth + dheight based on 96dpi on 1920x1080 screen - 13dec2025
//track
track__inc(satBasicapp,1);

//defaults
igui:=nil;

//self
inherited create;

//system
igui:=tbasicsystem.create(dwidth,dheight);
if (system_program=nil) then system_program:=self;

//.rootwin
if rootwin.xhavehead then rootwin.xhead.setfocus else rootwin.setfocus;

//.sysprogram
if (system_program=nil) then system_program:=self;

end;

procedure tbasicapp.createfinish;
begin
xstarttimer;
low__showhelp(vihelp_show);//24jul2021
end;

destructor tbasicapp.destroy;
begin
try
//system
if (self=system_program) then system_program:=nil;

//controls
freeobj(@igui);

//self
inherited destroy;

//track
track__inc(satBasicapp,-1);
except;end;
end;

function tbasicapp.rootwin:tbasicscroll;
begin
result:=gui.rootwin;
end;

procedure tbasicapp.xstarttimer;
begin
igui.ontimer:=__ontimer;
end;

procedure tbasicapp.xloadsettings;
begin

end;

procedure tbasicapp.xsavesettings;
begin

end;

procedure tbasicapp.__ontimer(sender:tobject);
begin
//nil
end;

procedure tbasicapp.debug_tests;//19jul2024
begin
try
//debug support
if system_debug then
   begin
   if system_debugFAST then rootwin.paintallnow;
   if system_debugRESIZE then
      begin
      if (system_debugwidth<=0) then system_debugwidth:=gui.width;
      if (system_debugheight<=0) then system_debugheight:=gui.height;
      //change the width and height to stress
      //was: if (random(10)=0) then gui.setbounds(gui.left,gui.top,system_debugwidth+random(32)-16,system_debugheight+random(128)-64);
      gui.setbounds(gui.left,gui.top,system_debugwidth+random(32)-16,system_debugheight+random(128)-64);
      end;
   end;
except;end;
end;


//GUI Support ------------------------------------------------------------------
function form__position(h:hauto;dx,dy,dw,dh:longint):boolean;
begin
dw:=frcmin32(dw,0);
dh:=frcmin32(dh,0);
result:=(h<>0) and win____setwindowpos(h,0,dx,dy,dw,dh,SWP_NOACTIVATE or SWP_NOZORDER);
end;

function form__move(h:hauto;dx,dy,dw,dh:longint;xrepaint:boolean):boolean;//09sep2025
begin

dw:=frcmin32(dw,0);
dh:=frcmin32(dh,0);


//.use this proc to enable "full window dragging" with proper screen repainting under Windows 9X
if system_osWin9X then
   begin

   //win____setwindowpos does NOT repaint a wonky window under Ubuntu Linux with below flags - 09sep2025
   result:=(h<>0) and win____SetWindowPos(h, 0, dx, dy, dw, dh, insint(SWP_NOREDRAW,xrepaint) or SWP_FRAMECHANGED);

   end

//.repaints screen correctly after Windows 9X, e.g. Windows 10/11
else

   begin

   //win____movewindow() repaints a wonky window under Ubuntu Linux - 09sep2025
   result:=win____movewindow(h,dx,dy,dw,dh,xrepaint);

   end;




end;

procedure system__setontop(x:boolean);
var
   p:longint;
begin
for p:=high(system_list) downto 0 do if (system_list[p]<>nil) then system_list[p].form__setontop(x);
end;

function system__include(x:tbasicsystem):boolean;
var
   p:longint;
begin
result:=false;

//check
if (x=nil) then exit;

//find existing
for p:=0 to high(system_list) do if (x=system_list[p]) then
   begin
   result:=true;
   break;
   end;

//add new
if not result then for p:=0 to high(system_list) do if (nil=system_list[p]) then
   begin
   system_list[p]:=x;
   result:=true;
   break;
   end;

system__sync;
end;

function system__exclude(x:tbasicsystem):boolean;
var
   p:longint;
begin
result:=false;

if (x<>nil) then for p:=0 to high(system_list) do if (x=system_list[p]) then
   begin
   system_list[p]:=nil;
   result:=true;
   break;
   end;

system__sync;
end;

procedure system__sync;
var
   p:longint;
   v,va:tbasicsystem;
begin
//first window as app handle
v:=nil;
for p:=0 to high(system_list) do if (system_list[p]<>nil) then
   begin
   v:=system_list[p];
   break;
   end;
system_guifirst:=v;

//first showing+active window
v:=nil;
va:=nil;
for p:=0 to high(system_list) do if (system_list[p]<>nil) and system_list[p].showing then//((system_formlist[p].state='n') or (system_formlist[p].state='+') or (system_formlist[p].state='f')) then
   begin
   if (v=nil)                            then v:=system_list[p];
   if (va=nil) and system_list[p].active then va:=system_list[p];

   if (v<>nil) and (va<>nil)             then break;
   end;

if (va<>nil)     then system_guiactive:=va
else if (v<>nil) then system_guiactive:=v
else                  system_guiactive:=system_guifirst;
end;

function system__findbyformhandle(h:hauto;var x:tbasicsystem):boolean;
var
   p:longint;
begin
result:=false;

for p:=0 to high(system_list) do if (system_list[p]<>nil) and (h=system_list[p].handle) then
   begin
   x:=system_list[p];
   result:=true;
   break;
   end;
end;

function system__windowproc(h:hauto;m:msg_message;w:msg_wparam;l:msg_lparam):msg_result; stdcall;
var
   wf:tbasicsystem;
   wm:twinmessage;

   function d:boolean;
   begin
   result:=true;
   wm.r:=win____defwindowproc(h,m,w,l);
   end;

   function wfind:boolean;
   begin
   result:=system__findbyformhandle(h,wf);
   if not result then wf:=nil;
   end;

   procedure wpaint;
   var
      a:twinrect;
      dc:hauto;
      ps:tpaintstruct;
      xtryagain:boolean;
   begin
   //check
   if (h=0) then exit;

   //check #2
   if win____isiconic(h) or (not win____iswindowvisible(h)) then
      begin
      win____beginpaint(h,ps);
      win____endpaint(h,ps);
      exit;
      end;

   //get
   dc:=win____beginpaint(h,ps);

   a:=wf.paintarea;
   xtryagain:=(wf.paint_tryagain_count<=10) and ((ps.rcPaint.left>a.left) or (ps.rcPaint.top>a.top) or (ps.rcPaint.right<a.right) or (ps.rcPaint.bottom<a.bottom));

   try;if (not xtryagain) and (dc<>0) then wf.form__wmpaint(dc,ps);except;end;
   win____endpaint(h,ps);

   //try again - we want ENTIRE window area for painting purposes
   if xtryagain then
      begin
      wf.paint_tryagain_count:=wf.paint_tryagain_count+1;
      wf.form__paintnow;
      end
   else wf.paint_tryagain_count:=0;
   end;

   procedure werasebkgnd;
   begin

   if not win____isiconic(h) then
      begin
      wm.r:=1;

      if wfind then
         begin

         low__irollone(wf.oeraseingbackground);//24jul2025
         wf.paintallnow;//13may2025: for Win98 and Gamemode

         end;

      end
   else
      begin
      m:=wm_iconerasebkgnd;
      d;
      end;

   end;

   procedure whittest;
   begin
   d;
   if wfind and (wf.state='n') then wf.form__wmnchittest(wm) else wm.r:=htclient;

   //.need to reload cursor if it's size has changed -> else Windows displays a corrupted cursor on Win11
   if (wm.r=htcaption) then
      begin
      app__reloadcursorifsizehaschanged;
      end;

   end;

   procedure wsyscommand;
   begin

   case msg_w32(wm.w) of
   sc_restore:begin
      wf.form__fadein(true);//paints during fade in now for smoother restore
      d;
      wf.form__fadein(false);
      wf.paintallnow;
      end;
   sc_minimize:begin
      wf.form__fadeout(false);
      d;
      wf.form__fadeout(true);
      wf.paintallnow;
      end;
   else d;
   end;//case

   end;
begin
//defaults
result:=0;
wm.m:=m;
wm.w:=w;
wm.l:=l;
wm.r:=0;

try
case m of
wm_erasebkgnd  :werasebkgnd;
wm_nchittest   :whittest;
wm_mousewheel  :if wfind then wf.form__wmmousewheel(wm);
wm_dropfiles   :if wfind then wf.form__wmacceptfiles(wm);
wm_entersizemove:if wfind then wf.form__wmentersizemove;
wm_size        :if wfind then wf.form__wmsize(wm);
wm_sizing      :if wfind then wf.form__wmsizing(wm);
wm_exitsizemove:if wfind then wf.form__wmexitsizemove;
wm_paint       :if wfind then wpaint;
wm_setcursor   :begin
   if wfind then wf.form__wmsetcursor(wm);
   if (wm.r=0) then d;
   end;
wm_activate    :if wfind then wf.form__wmactive(wm);
wm_activateapp :if wfind then wf.form__wmactivateapp(wm);
wm_syscommand  :if wfind then wsyscommand;
//.mouse
wm_mousemove  :if wfind then wf.form__wmmousemove(wm);
wm_lbuttondown:if wfind then wf.form__wmmousedown(1,wm);
wm_mbuttondown:if wfind then wf.form__wmmousedown(2,wm);
wm_rbuttondown:if wfind then wf.form__wmmousedown(3,wm);
wm_lbuttonup  :if wfind then wf.form__wmmouseup(1,wm);
wm_mbuttonup  :if wfind then wf.form__wmmouseup(2,wm);
wm_rbuttonup  :if wfind then wf.form__wmmouseup(3,wm);
//.keyboard
wm_keydown     :if wfind then wf.form__wmkeydown(wm);
wm_keyup       :if wfind then wf.form__wmkeyup(wm);
wm_syskeydown  :if wfind then wf.form__wmsyskeydown(wm);
wm_syskeyup    :if wfind then wf.form__wmsyskeyup(wm);
wm_char        :if wfind then wf.form__wmchar(wm);
wm_syschar     :if wfind then wf.form__wmsyschar(wm);
wm_close       :if wfind then wf.form__wmclose(wm);
//disable non-client processing - 20jan2025
wm_nccalcsize:;
wm_ncactivate:begin
   l:=-1;//don't paint non-client area BUT allow activation information to be processed - 20jan2025
   d;
   end;
wm_ncpaint:;

else
   begin

   //detect changes in monitor settings and setup
   if monitors__mustsync(m) then monitors__sync;//01feb2026

   //pass message onto subsystem
   d;

   //full area paint -> required (prevents form from being only partially painted)
   if (m=wm_windowposchanged) and bit__hasval32(pwindowpos( msg_l32(wm.l) ).flags,32768) and wfind then//SWP_STATECHANGED =0x8000 => Winehq source
      begin
      wf.paintallnow;
      end;

   end;
end;//case

//return result
result:=wm.r;
except;end;
end;


//scale procs ------------------------------------------------------------------

function scale__adjustment(const xscale:double;const xscalemode:longint):double;//11dec2025
begin

//defaults
result :=xscale;

//scale check for low res screens


//get
if (system_blackwhitecount>=1) and (xscalemode>=scale__modeNormal) then//special "black and white" override mode - 09dec2024
   begin

   //only reset scale to 1.0 when larger than 100%, assume all smaller scales are fine

   end
else
   begin

   case frcrange32( xscalemode, 0, pred(scale__modecount) ) of
   0:result:=(result*0.60);
   1:result:=(result*0.70);
   2:result:=(result*0.80);
   4:result:=(result*1.25);
   5:result:=(result*1.50);
   6:result:=(result*1.75);
   7:result:=(result*2.00);

   else begin//3=normal=100%
      //nil
      end;
   end;//case

   end;

//enforce range
result:=frcrangeD64( result, gui__scalemin, gui__scalemax );

end;

function scale__calculate:double;//17dec2025, 10dec2025
var
   w,h:longint;
begin

//init
w      :=monitors__screenwidth_auto;
h      :=monitors__screenheight_auto;

//get
result :=gui__dpi/96;

//.adjust down for smaller screens
result :=frcrangeD64( result * smallestD64( (w/1920), (h/1080) ) , 0.6, result );//17dec2025

//set
result :=scale__adjustment( result , syssettings.i['scalemode'] );

end;

function scale__modeNormal:longint;
begin

result:=3;

end;

function scale__modecount:longint;
begin

result:=8;

end;

function scale__modelabel(const xscalemode:longint):string;//10dec2025
begin

case frcrange32( xscalemode, 0, pred(scale__modecount) ) of
0     :result:='60%';
1     :result:='70%';
2     :result:='80%';
4     :result:='125%';
5     :result:='150%';
6     :result:='175%';
7     :result:='200%';
else   result:='Normal';//3=normal
end;//case

end;

function scale__modehelp(const xscalemode:longint):string;//17dec2025, 10dec2025
var
   v:longint;
begin

//range
v:=frcrange32( xscalemode, 0, pred(scale__modecount) );

//get
case v of
3     :result:='100%';
else   result:=scale__modelabel(v);
end;//case

result:='Scale|Scale app to '+result+' of system';

end;

function scale__px20(const xsubscale,xval:double):longint;//rounds down - 10dec2025
begin

result:=frcmin32( trunc( xval * viscale * frcrangeD64(xsubscale,0.1,2.0) ) , 0 );

end;

function scale__px21(const xsubscale,xval:double;const xmin:longint):longint;//rounds down - 10dec2025
begin

result:=frcmin32( trunc( xval * viscale * frcrangeD64(xsubscale,0.1,2.0) ) , xmin );

end;

function scale__px22(const xsubscale,xval:double;const xmin,xmax:longint):longint;//rounds down - 10dec2025
begin

result:=frcrange32( trunc( xval * viscale * frcrangeD64(xsubscale,0.1,2.0) ) , xmin, xmax );

end;

function scale__px0(const xval:double):longint;//rounds down - 10dec2025
begin

result:=scale__px20(1.0,xval);

end;

function scale__px1(const xval:double;const xmin:longint):longint;//rounds down - 10dec2025
begin

result:=scale__px21(1.0,xval,xmin);

end;

function scale__px2(const xval:double; const xmin,xmax:longint):longint;//rounds down - 10dec2025
begin

result:=scale__px22(1.0,xval,xmin,xmax);

end;

function scale__fontRatioCorrection:double;
begin

result:=(100/vitextscaling);

end;

function scale__counterScaling(const xvalue:longint):longint;
begin

case (vitextscaling<>100) of
true:begin

   result:=round( xvalue * (100/vitextscaling) );
   //.min value
   if (result<=0) and (xvalue>=1) then result:=1;

   end;
else result:=xvalue;
end;//case

end;

//## tbackgroundmanager ########################################################
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//bbbbbbbbbbbbbbbbbbbbb
constructor tbackgroundmanager.create(xgui:tbasicsystem);
begin

//self
igui        :=xgui;

if (igui=nil) then showerror('Gui in tbackgroundmanager.create must not be nil.');
track__inc(satOther,1);

low__sysadd(self);
inherited create;

//vars
ilimit                :=high(sysback_name)+1;
tag                   :=0;
iloadonce             :=true;
iitemindex            :=0;
imustpaint            :=false;
imustupdate           :=false;
itimer                :=0;
isettingsRef          :='';

icrateTriggerID       :=0;
icrateTriggered       :=false;

iuse_itemindex        :=0;
iuse_tile32           :=nil;
iuse_final32          :=nil;//13jan2026
iuse_tileref          :='';
iuse_tileok           :=false;
iuse_tilew            :=1;
iuse_tileh            :=1;
iuse_shadepower255    :=255;
iuse_shadepower255_inc:=true;
iuse_scrollx          :=0;
iuse_scrolly          :=0;
iuse_wobblex          :=0;
iuse_wobbley          :=0;
iuse_wobblef          :=0;
iuse_crate            :=0;
iuse_cellcount        :=1;
iuse_cellindex        :=0;
iuse_loadid           :=1;//increments each time a different tile image is loaded - 13jan2026
ipreComputeCellRef32  :=tdynamicstring.create;//track which cell has been pre-computed and which needs to be updated - 13jan2026

//load default value here - 21mar2025
setbackgroundname(vibackname);

//defaults
imustpaint:=true;

end;

destructor tbackgroundmanager.destroy;
begin
try

//controls
freeobj(@iuse_final32);
freeobj(@iuse_tile32);
freeobj(@ipreComputeCellRef32);

//self
low__sysdel(self);
inherited destroy;

//track
track__inc(satOther,-1);

except;end;
end;

function tbackgroundmanager.preComputeCellForRender32(var x:tfastbufferinfo):boolean;//13jan2026
label
   coloriseNONE,coloriseLESS,coloriseMORE,xnone,xmore,xless;
var
   dr32,sr32:pcolorrows32;
   bk32,c32:tcolor32;
   v,v2,ta,la,ca,cainv,dy,dx,dx1,dx2,dBackstrength,dpower255,dback,dcolorise:longint;
   dstop,dindex,sindex:iauto;
   xref:string;
begin

//load tile if changed
xloadTile;

//return status: true=background in use, false=background not in use
dBackstrength   :=frcrange32( strength ,0 ,low__aorb(255,100,visafestrength) );
dPower255       :=frcrange32(round32( (low__aorb(255,iuse_wobblef,iuse_wobblef>=1)/255) * (iuse_shadepower255/255) * dBackstrength ) ,0 ,255 );
result          :=(sysback_strength[iuse_itemindex]>=1) and iuse_tileok and (dPower255>=1);

//check
if not result then exit;//background tile not in use -> nothing to do, no preCompute required

//support values for render system
dcolorise       :=frcrange32(round32((colorise*255) div 100),-255,255);
dback           :=vinormal.hover;
ta              :=0;
la              :=0;
ca              :=0;
cainv           :=255;

//buffer "final32"
if (iuse_final32=nil) then iuse_final32:=misraw32(1,1);
if (iuse_final32.width<>iuse_tile32.width) or (iuse_final32.height<>iuse_tile32.height) then missize(iuse_final32,iuse_tile32.width,iuse_tile32.height);

//x.power255      :=dPower255;
x.tilew         :=iuse_final32.width;
x.tileh         :=iuse_final32.height;
x.tilebits      :=iuse_final32.bits;
x.tilerows      :=iuse_final32.prows32;
x.cw            :=frcrange32(iuse_tile32.ai.cellwidth  ,1 ,x.tilew );
x.ch            :=frcrange32(iuse_tile32.ai.cellheight ,1 ,x.tileh );
x.cc            :=frcmin32  (iuse_tile32.ai.count ,1 );
x.ci            :=frcrange32(cellindex ,0 ,frcmin32(x.cc-1,0) );
x.power255      :=dPower255;
x.scrollx       :=frcrange32(x.cw-scrollx,0,x.cw);
x.scrolly       :=frcrange32(x.ch-scrolly,0,x.ch);
x.wobblex       :=wobblex;
x.wobbley       :=wobbley;

with x do
begin

if (wobblex<>0) then
   begin

   inc(scrollx,wobblex);
   if (scrollx<0)       then scrollx:=cw+(scrollx-((scrollx div cw)*cw))
   else if (scrollx>cw) then scrollx:=scrollx-((scrollx div cw)*cw);

   end;

if (wobbley<>0) then
   begin

   inc(scrolly,wobbley);
   if (scrolly<0)       then scrolly:=ch+(scrolly-((scrolly div ch)*ch))
   else if (scrolly>ch) then scrolly:=scrolly-((scrolly div ch)*ch);

   end;

end;//x


//check if pre-compute required for current cell
xref:=intstr32(iuse_loadid)+'|'+intstr32(dcolorise)+'|'+intstr32(dback)+'|'+intstr32(dPower255);

case (xref=ipreComputeCellRef32.value[x.ci]) of
true:exit;
else ipreComputeCellRef32.value[x.ci]:=xref;
end;//case


//pre-compute current cell
sr32            :=iuse_tile32.prows32;
dr32            :=x.tileRows;
dx1             :=x.cw * x.ci;
dx2             :=dx1 + x.cw -1;
bk32            :=int__c32( dback );

if (dcolorise=255)     then goto coloriseNONE
else if (dcolorise>=0) then goto coloriseMORE
else                        goto coloriseLESS;

//coloriseNONE -----------------------------------------------------------------
coloriseNONE:

for dy:=0 to (x.ch-1) do
begin

sindex     :=iauto( @sr32[dy][dx1] );
dindex     :=iauto( @dr32[dy][dx1] );
dstop      :=iauto( @dr32[dy][dx2] );

xnone:

//render pixel
ta:=pcolor32(sindex).a;
if (ta<>la) then
   begin

   la     :=ta;
   ca     :=(ta*dPower255) shr 8;
   cainv  :=255-ca;

   end;

pcolor32(dindex).r  :=(ca*pcolor32(sindex).r) shr 8;
pcolor32(dindex).g  :=(ca*pcolor32(sindex).g) shr 8;
pcolor32(dindex).b  :=(ca*pcolor32(sindex).b) shr 8;
pcolor32(dindex).a  :=cainv;

//inc x
if (dindex<>dstop) then
   begin

   inc( sindex, sizeof(tcolor32) );
   inc( dindex, sizeof(tcolor32) );
   goto xnone;

   end;

end;//dy


//done
exit;


//coloriseMORE -----------------------------------------------------------------
coloriseMORE:

for dy:=0 to (x.ch-1) do
begin

sindex     :=iauto( @sr32[dy][dx1] );
dindex     :=iauto( @dr32[dy][dx1] );
dstop      :=iauto( @dr32[dy][dx2] );

xmore:

//render pixel
c32 :=pcolor32(sindex)^;
if (c32.a<>la) then
   begin

   la     :=c32.a;
   ca     :=(c32.a*dPower255) shr 8;
   cainv  :=255-ca;

   end;

v                  :=c32.r;
if (c32.g>v) then v:=c32.g;
if (c32.b>v) then v:=c32.b;

v2                 :=(ca*v*(255-dcolorise)) shr 16;
pcolor32(dindex).r :=((ca*c32.r*dcolorise) shr 16) + v2;
pcolor32(dindex).g :=((ca*c32.g*dcolorise) shr 16) + v2;
pcolor32(dindex).b :=((ca*c32.b*dcolorise) shr 16) + v2;
pcolor32(dindex).a :=cainv;

//inc x
if (dindex<>dstop) then
   begin

   inc( sindex, sizeof(tcolor32) );
   inc( dindex, sizeof(tcolor32) );
   goto xmore;

   end;

end;//dy

//done
exit;


//coloriseLESS -----------------------------------------------------------------
coloriseLESS:

for dy:=0 to (x.ch-1) do
begin

sindex     :=iauto( @sr32[dy][dx1] );
dindex     :=iauto( @dr32[dy][dx1] );
dstop      :=iauto( @dr32[dy][dx2] );

xless:

//render pixel
c32 :=pcolor32(sindex)^;
if (c32.a<>la) then
   begin

   la     :=c32.a;
   ca     :=(c32.a*dPower255) shr 8;
   cainv  :=255-ca;

   end;

v                  :=c32.r;
if (c32.g>v) then v:=c32.g;
if (c32.b>v) then v:=c32.b;

v2                 :=( ca * v * (255+dcolorise)*(255+dcolorise) ) shr 24;
pcolor32(dindex).r :=( (ca*bk32.r*v*-dcolorise) shr 24 ) + v2;
pcolor32(dindex).g :=( (ca*bk32.g*v*-dcolorise) shr 24 ) + v2;
pcolor32(dindex).b :=( (ca*bk32.b*v*-dcolorise) shr 24 ) + v2;
pcolor32(dindex).a :=cainv;

//inc x
if (dindex<>dstop) then
   begin

   inc( sindex, sizeof(tcolor32) );
   inc( dindex, sizeof(tcolor32) );
   goto xless;

   end;

end;//dy

//done
exit;

end;

function tbackgroundmanager.mint(xhost:tbasiccontrol;xnameid:string):tsimpleint;
var
   xdef,xmin,xmax,inameid:longint;
   xlabel,xhelplabel,xhelpbar:string;

   procedure s(slabel,shelplabel,shelpbar:string);
   begin
   xlabel:=slabel;
   xhelplabel:=shelplabel;
   xhelpbar:=shelpbar;
   xmin:=sysback__enforcerange(inameid,min32);
   xmax:=sysback__enforcerange(inameid,max32);
   xdef:=frcrange32(0,xmin,xmax);
   end;
begin
//check
if (xhost=nil) then
   begin
   result:=nil;
   exit;
   end;

//get
if not findnameid(xnameid,inameid) then inameid:=0;

case inameid of
bkmStrength  :s('Strength','','Background Image Strength | Defines how much of the background image shows into the GUI | A strength over a 100 is limited by default as the GUI may be hard to read |'+' To remove this restriction unselect the "Safe Background Strength" option under the "Settings" tab | At anytime you can press the "F2" key to restore defaults');
bkmColorise  :s('Colorise','','Colorise | Adjust image coloring | Value range is from -100 (scheme color) to 100 (image colors)');
bkmSpeed     :s('Speed','','Speed | Background animation rate | Value range is from 0fps (static) to '+k64(background_speed_limit)+'fps (fast)');//30dec2025
bkmHstep     :s('Horizontal Scroll','','Background Animation | Scroll the background image left(-) or right(+) | Set a large scroll value for swift movement | Value range is from 0px (off) to +/-100px (fast)');
bkmVstep     :s('Vertical Scroll','','Background Animation | Scroll the background image up(-) or down(+) | Set a large scroll value for swift movement | Value range is from 0px (off) to +/-100px (fast)');
bkmFstep     :s('Fade In/Out','','Background Animation | Fade the background image in and out of view | Set a large step value for swift change | Value range is from 0 (off) to 50 (fast)');
bkmHwobble   :s('Horizontal Wobble','','Adjust horizontal scroll wobble');
bkmVwobble   :s('Vertical Wobble','','Adjust vertical scroll wobble');
bkmFwobble   :s('Fade Wobble','','Adjust fade in/out wobble');
bkmCrate     :s('Change Rate','','Adjust change rate');
end;//case

//set
result:=xhost.mint3b(xlabel,xhelplabel,xhelpbar,xmin,xmax,xdef,0,'','');
result.tagstr:=xnameid;
result.tag:=100;
result.onreadwriteval:=nint__onvalue;
result.onreadwritedef:=nint__onvalueDEF;
end;

function tbackgroundmanager.sync_panel(x:tbasicscroll):boolean;
var
   int1,xnameid,xcount,p:longint;
   xvis:boolean;
   a:tbasiccontrol;
begin
//no change
result:=false;

//get
if (x<>nil) then
   begin
   //init
   xcount     :=x.childcount;

   //get
   if (xcount>=1) then for p:=0 to (xcount-1) do if x.findchild(p,a) and (a is tsimpleint) and (a.tag=100) and (a.tagstr<>'') and findnameid(a.tagstr,xnameid) then
      begin
      sysback__getval2(xnameid,iuse_itemindex,xvis,int1);
      if (xvis<>a.visible) then
         begin
         a.visible:=xvis;
         result:=true;
         end;
      end;//p
   end;
end;

procedure tbackgroundmanager.nint__onvalue(sender:tobject;var xval:longint;xwrite:boolean);
var
   int1,inameid:longint;
   bol1:boolean;
   n:string;
begin
if (sender is tsimpleint) then n:=(sender as tsimpleint).tagstr else n:='';

if findnameid(n,inameid) then
   begin

   if xwrite then
      begin

      if sysback__setval2(inameid,iuse_itemindex,xval,false) then
         begin

         storevals;

         //repaint entire screen for static or low frame rates -> high frame rates auto paints screen already - 13jan2026
         if (speed<=5) then gui.paintallnow;

         end;

      end
   else xval:=getval(inameid,iuse_itemindex);

   //visible
   sysback__getval2(inameid,iuse_itemindex,bol1,int1);

   end
else xval:=0;

end;

procedure tbackgroundmanager.nint__onvalueDEF(sender:tobject;var xval:longint;xwrite:boolean);
var
   int1,inameid:longint;
   bol1:boolean;
   n:string;
begin
if (sender is tsimpleint) then n:=(sender as tsimpleint).tagstr else n:='';

if findnameid(n,inameid) then sysback__getval3(inameid,iuse_itemindex,bol1,int1,xval) else xval:=0;
end;

procedure tbackgroundmanager.setval(xnameid,xindex,xval:longint);
begin
if sysback__setval2(xnameid,xindex,xval,false) then storevals;
end;

function tbackgroundmanager.getval(xnameid,xindex:longint):longint;
var
   bol1:boolean;
begin
sysback__getval2(xnameid,xindex,bol1,result);
end;

procedure tbackgroundmanager.pullval(snameid:string;var xcanchange:boolean;var xval:longint);
var
   inameid:longint;
begin
if findnameid(snameid,inameid) then sysback__getval2(inameid,iuse_itemindex,xcanchange,xval)
else
   begin
   xcanchange :=false;
   xval       :=0;
   end;
end;

procedure tbackgroundmanager.pushval(snameid:string;xnewval:longint);
var
   inameid:longint;
begin
if findnameid(snameid,inameid) then setval(inameid,iuse_itemindex,xnewval);
end;

function tbackgroundmanager.canadjust:boolean;
begin
result:=sysback__canadjust(iuse_itemindex);
end;

function tbackgroundmanager.getstrength:longint;
begin
result:=val[bkmStrength,iuse_itemindex];
end;

function tbackgroundmanager.getcolorise:longint;
begin
result:=val[bkmColorise,iuse_itemindex];
end;

function tbackgroundmanager.getspeed:longint;
begin
result:=val[bkmSpeed,iuse_itemindex];
end;

function tbackgroundmanager.gethstep:longint;
begin
result:=val[bkmHstep,iuse_itemindex];
end;

function tbackgroundmanager.gethwobble:longint;
begin
result:=val[bkmHwobble,iuse_itemindex];
end;

function tbackgroundmanager.getvstep:longint;
begin
result:=val[bkmVstep,iuse_itemindex];
end;

function tbackgroundmanager.getvwobble:longint;
begin
result:=val[bkmVwobble,iuse_itemindex];
end;

function tbackgroundmanager.getfstep:longint;
begin
result:=val[bkmFstep,iuse_itemindex];
end;

function tbackgroundmanager.getfwobble:longint;
begin
result:=val[bkmFwobble,iuse_itemindex];
end;

function tbackgroundmanager.getcrate:longint;
begin
result:=val[bkmCrate,iuse_itemindex];
end;

procedure tbackgroundmanager.setstrength(x:longint);
begin
val[bkmStrength,iuse_itemindex]:=x;
end;

procedure tbackgroundmanager.setcolorise(x:longint);
begin
val[bkmColorise,iuse_itemindex]:=x;
end;

procedure tbackgroundmanager.setspeed(x:longint);
begin
val[bkmSpeed,iuse_itemindex]:=x;
end;

procedure tbackgroundmanager.sethstep(x:longint);
begin
val[bkmHstep,iuse_itemindex]:=x;
end;

procedure tbackgroundmanager.sethwobble(x:longint);
begin
val[bkmHwobble,iuse_itemindex]:=x;
end;

procedure tbackgroundmanager.setvstep(x:longint);
begin
val[bkmVstep,iuse_itemindex]:=x;
end;

procedure tbackgroundmanager.setvwobble(x:longint);
begin
val[bkmVwobble,iuse_itemindex]:=x;
end;

procedure tbackgroundmanager.setfstep(x:longint);
begin
val[bkmFstep,iuse_itemindex]:=x;
end;

procedure tbackgroundmanager.setfwobble(x:longint);
begin
val[bkmFwobble,iuse_itemindex]:=x;
end;

procedure tbackgroundmanager.setcrate(x:longint);
begin
val[bkmCrate,iuse_itemindex]:=x;
end;

procedure tbackgroundmanager.storevals;
begin
sysback__writevals(iuse_itemindex,syssettings);
end;

function tbackgroundmanager.tileok:boolean;
begin
result:=iuse_tileok;
end;

function tbackgroundmanager.inuse:boolean;
begin
result:=(sysback_strength[iuse_itemindex]>=1) and iuse_tileok;
end;

//.custom image support --------------------------------------------------------
function tbackgroundmanager.canpasteimage:boolean;
begin
result:=(sysback_datafromfile[iuse_itemindex]<>'');
end;

function tbackgroundmanager.pasteimage:boolean;
var
   a:tbasicimage;
   e:string;
begin
//defaults
result:=false;
a:=nil;

try
//get
if canpasteimage and clip__canpasteimage(true) then
   begin
   a:=misimg32(1,1);
   if clip__pasteimage(a,true) then
      begin
      mis__tofile(a,app__subfolder('settings')+sysback_datafromfile[iuse_itemindex],feimg32,e);
      iuse_tileref:='';//force tile to reload
      gui.paintallnow;
      result:=true;
      end;
   end;
except;end;

//free
freeobj(@a);
end;

function tbackgroundmanager.canselectimage:boolean;
begin
result:=(sysback_datafromfile[iuse_itemindex]<>'');
end;

function tbackgroundmanager.selectimage:boolean;
var
   a:tbasicimage;
   e:string;
begin
//defaults
result:=false;
a:=nil;

try
//get
if canselectimage and gui.popopenimg(sysfile_background,sysfile_background_openfilter,'images') then
   begin
   a:=misimg32(1,1);

   if mis__fromfile(a,sysfile_background,e) and mis__tofile(a,app__subfolder('settings')+sysback_datafromfile[iuse_itemindex],feimg32,e) then
      begin
      iuse_tileref:='';//force tile to reload
      gui.paintallnow;
      result:=true;
      end;

   end;
except;end;

//free
freeobj(@a);
end;

function tbackgroundmanager.canclearimage:boolean;
begin
result:=(sysback_datafromfile[iuse_itemindex]<>'') and io__fileexists(app__subfolder('settings')+sysback_datafromfile[iuse_itemindex]);
end;

function tbackgroundmanager.clearimage:boolean;
var
   n:string;
begin
//defaults
result:=false;

try
//get
if canclearimage then
   begin
   n:=app__subfolder('settings')+sysback_datafromfile[iuse_itemindex];
   if io__fileexists(n) and gui.popquery('Clear background slot?') then
      begin
      io__remfile(n);
      iuse_tileref:='';//force back tile to reload
      gui.paintallnow;
      end;
   end;
except;end;
end;

function tbackgroundmanager.canchangevals:boolean;
begin
result:=icanchangevals[iuse_itemindex];
end;

function tbackgroundmanager.getcount:longint;
begin
result:=sysback_count;
end;

procedure tbackgroundmanager.setbackgroundname(x:string);
begin

itemindex:=findbyname(x);

if iloadonce then
   begin

   //prep first time only -> switches background mode on when app first starts (if background is set)
   iloadonce:=false;
   xloadtile;

   end;

end;

function tbackgroundmanager.getbackgroundname:string;
begin
result:=sysback_name[itemindex];
end;

function tbackgroundmanager.findnameid(xnameid_asstr:string;var xnameid:longint):boolean;
begin
result:=sysback__findnameid(xnameid_asstr,xnameid);
end;

function tbackgroundmanager.findbyname(xname:string):longint;
begin
sysback__findbyname(xname,result);
end;

procedure tbackgroundmanager.xloadtile;//called by "preComputeCellForRender32()"
var
   a:tstr8;
   e:string;
   xbits:longint;

   procedure xnotile;
   begin

   missize(iuse_tile32,1,1);

   end;


   function xtileRef:string;

      procedure v(const n,x:string);
      begin

      result:=result+'|'+n+'_'+x;

      end;

      procedure v32(const n:string;const x:longint);
      begin

      v(n,intstr32(x));

      end;

   begin

   result:=sysback_name[iuse_itemindex];

   if sysback_remakeonScreen[iuse_itemindex] then
      begin

      v32( 'w' , monitors__screenwidth_auto );
      v32( 'h' , monitors__screenheight_auto );

      end;

   if sysback_remakeonScale[iuse_itemindex] then v32( 's' ,round32(viscale*1000) );

   if sysback_remakeonCrate[iuse_itemindex] then v32( 'a' ,icrateTriggerID );//just needs to be different each time to FORCE a remake

   end;

begin

//defaults
a:=nil;

try

//get -> supports static tiles (load once), dynamic tiles (remake on scale) and (remake always e.g. Random Color)
if low__setstr( iuse_tileref ,xtileRef ) then
   begin

   //.image handler - 13jan2026
   if (iuse_tile32=nil)   then iuse_tile32   :=misraw32(1,1);

   //.create tile from proc
   if (sysback_makename[iuse_itemindex]<>'') then
      begin

      if not sysback__makeTileFromName(iuse_tile32,sysback_makename[iuse_itemindex]) then xnotile;

      end

   //.load tile from "name" in "settings" folder
   else if (sysback_datafromfile[iuse_itemindex]<>'') then
      begin

      if not mis__fromfile(iuse_tile32,app__subfolder('settings')+sysback_datafromfile[iuse_itemindex],e) then xnotile;

      end

   //.load tile from data ptr
   else if (sysback_datafromptr[iuse_itemindex].count>=2) and (sysback_datafromptr[iuse_itemindex].bytes<>nil) then
      begin

      a:=str__new8;
      if not str__padd(@a,sysback_datafromptr[iuse_itemindex].bytes,sysback_datafromptr[iuse_itemindex].count) then xnotile;
      if not mis__fromdata(iuse_tile32,@a,e) then xnotile;

      end

   //.no tile to load
   else xnotile;

   //reset
   iuse_tileok     :=misok82432(iuse_tile32,xbits,iuse_tilew,iuse_tileh) and (xbits=32) and (iuse_tilew>=2) and (iuse_tileh>=2);
   iuse_cellcount  :=miscc(iuse_tile32);
   iuse_cellindex  :=0;
   iuse_scrollx    :=0;
   iuse_scrolly    :=0;
   iuse_wobblex    :=0;
   iuse_wobbley    :=0;
   iuse_wobblef    :=0;
   iuse_crate      :=0;

   rollid32(iuse_loadid);

   //.reset the cell timer BUT signal the timer NOT to increment to the next cell until the next timer cycle - 02mar2025, 26jul2024
   itimer:=min32;//reset

   end;

except;end;

//free
freeobj(@a);

end;

function tbackgroundmanager.xmusttimer:boolean;
begin
result:=(fastms64>=itimer);//27dec2025
end;

procedure tbackgroundmanager.xtimer;
label
   reset_timer_only;
var
   xcrateTriggered,xreset:boolean;
   int1,xwas_fade255,xwas_scrollx,xwas_scrolly,xwas_wobblex,xwas_wobbley,xwas_wobblefade:longint32;
   cstep,climit:longint32;
begin

//a window is being dragged or resized -> stop background animation until task is finished - 04apr2026
if gui.dragging then exit;

//background animation ---------------------------------------------------------

//.don't animate the background while we are resizing a floating window, the main window, or repositioning a floating window -> helps to maintain GUI speed, especially when spanned over multiple monitors - 21nov2024
if xmusttimer then
   begin

   //reset timer but don't increment anything
   if (itimer=min32) then goto reset_timer_only;

   //init
   xreset           :=false;
   xwas_fade255     :=iuse_shadepower255;
   xwas_scrollx     :=iuse_scrollx;
   xwas_scrolly     :=iuse_scrolly;
   xwas_wobblex     :=iuse_wobblex;
   xwas_wobbley     :=iuse_wobbley;
   xwas_wobblefade  :=iuse_wobblef;
   xcrateTriggered  :=false;

   //turn off background animater WHEN tile is empty, strength is 0 or animation speed is 0
   if (strength<=0) or (speed<=0) or misempty(iuse_tile32) or ((fstep<=0) and (hstep=0) and (vstep=0) and (hwobble=0) and (vwobble=0) and (fwobble=0) and (crate=0)) then
      begin

      if (iuse_shadepower255<>255) or (iuse_scrollx<>0) or (iuse_scrolly<>0) or (iuse_wobblex<>0) or (iuse_wobbley<>0) or (iuse_wobblef<>0) or (iuse_crate<>0) then
         begin

         iuse_shadepower255     :=255;
         iuse_shadepower255_inc :=true;
         iuse_scrollx           :=0;
         iuse_scrolly           :=0;
         iuse_wobblex           :=0;
         iuse_wobbley           :=0;
         iuse_wobblef           :=0;
         iuse_crate             :=0;
         xreset                 :=true;

         end;

      end
   else
      begin


      //change rate ------------------------------------------------------------
      if (crate>=1) then
         begin

         cstep  :=frcmin32( crate*speed ,1 );
         climit :=100*speed;

         case (iuse_crate<climit) of
         true:begin

            inc(iuse_crate,cstep);

            if (iuse_crate>=climit) then
               begin

               roll32(icrateTriggerID);

               icrateTriggered  :=true;//trigger action
               xcrateTriggered  :=true;//local to this proc
               imustpaint       :=true;

               end;

            end;
         else iuse_crate:=0;
         end;//case

         end
      else iuse_crate:=0;


      //wobble -----------------------------------------------------------------

      //.wobble x
      case (hwobble<>0) of
      true :iuse_wobblex:=random(hwobble)-(hwobble div 2);
      else  iuse_wobblex:=0;
      end;//case

      //.wobble y
      case (vwobble<>0) of
      true :iuse_wobbley:=random(vwobble)-(vwobble div 2);
      else  iuse_wobbley:=0;
      end;//case

      //.wobble fade
      case (fwobble<>0) of
      true :iuse_wobblef:=random(fwobble)-(fwobble div 2);
      else  iuse_wobblef:=0;
      end;//case


      //fade step --------------------------------------------------------------
      if (fstep>=1) then
         begin

         int1:=100;//bottom range - required
         iuse_shadepower255:=frcrange32(iuse_shadepower255+(low__aorb(-1,1,iuse_shadepower255_inc)*fstep),int1,255);

         case iuse_shadepower255_inc of
         true :if (iuse_shadepower255>=255 ) then iuse_shadepower255_inc:=false;
         else  if (iuse_shadepower255<=int1) then iuse_shadepower255_inc:=true;
         end;//case

         end
      else
         begin

         if (iuse_shadepower255<>255) then
            begin

            iuse_shadepower255:=255;
            xreset:=true;

            end;

         iuse_shadepower255_inc:=true;

         end;


      //scroll step (x) -----------------------------------------------------------
      if (hstep<>0) then
         begin

         int1:=frcmin32(miscw(iuse_tile32),1);

         if (hstep>=1) then
            begin

            inc(iuse_scrollx,hstep);
            if (iuse_scrollx>=int1) then iuse_scrollx:=frcmin32(iuse_scrollx-((iuse_scrollx div int1)*int1),0);

            end
         else if (hstep<=-1) then
            begin

            dec(iuse_scrollx,-hstep);
            if (iuse_scrollx<=0) then iuse_scrollx:=frcmin32(iuse_scrollx+int1+((iuse_scrollx div int1)*int1),0);

            end;

         end
      else if (iuse_scrollx<>0) then
         begin

         iuse_scrollx:=0;
         xreset:=true;

         end;


      //vscroll step (y) ----------------------------------------------------------
      if (vstep<>0) then
         begin

         int1:=frcmin32(misch(iuse_tile32),1);

         if (vstep>=1) then
            begin

            inc(iuse_scrolly,vstep);
            if (iuse_scrolly>=int1) then iuse_scrolly:=frcmin32(iuse_scrolly-((iuse_scrolly div int1)*int1),0);

            end
         else if (vstep<=-1) then
            begin

            dec(iuse_scrolly,-vstep);
            if (iuse_scrolly<=0) then iuse_scrolly:=frcmin32(iuse_scrolly+int1+((iuse_scrolly div int1)*int1),0);

            end;

         end
      else if (iuse_scrolly<>0) then
         begin

         iuse_scrolly:=0;
         xreset:=true;

         end;

      end;//if


   //cycle through cells of background animation
   if (iuse_cellcount>=2) and (speed>=1) and (crate>=1) then
      begin

      int1:=iuse_cellindex;
      if xcrateTriggered then inc(int1);

      if (int1<0) then int1:=0 else if (int1>=iuse_cellcount) then int1:=0;

      end
   else int1:=0;

   if low__setint(iuse_cellindex,int1) then imustpaint:=true;


   //must paint
   if (xwas_fade255<>iuse_shadepower255) or (xwas_scrollx<>iuse_scrollx) or (xwas_scrolly<>iuse_scrolly) or (xwas_wobblex<>iuse_wobblex) or (xwas_wobbley<>iuse_wobbley) or (xwas_wobblefade<>iuse_wobblef) or icratetriggered or xreset then
      begin

      imustpaint:=true;

      end;


   //reset timer
   reset_timer_only:
   case (speed>=1) and (not misempty(iuse_tile32)) and ( (fstep>=1) or (hstep<>0) or (vstep<>0) or (hwobble<>0) or (vwobble<>0) or (fwobble<>0) or (crate<>0) or (iuse_cellcount>=2) ) of
   true:begin

      if (speed>10) then app__turbo;//boost performance
      itimer:=fastms64 + round(1000/frcrange32(speed,1,background_speed_limit));//1..N fps - 07jan2026, 30dec2025

      end;
   else itimer:=fastms64+1000;

   end;//case

   end;

end;

function tbackgroundmanager.mustupdate(xreset:boolean):boolean;
begin

result:=imustupdate;
if xreset then imustupdate:=false;

end;

function tbackgroundmanager.mustpaint(xreset:boolean):boolean;
begin

result:=xsettingsChanged(xreset) or icratetriggered or imustpaint;

if xreset then
   begin

   imustpaint         :=false;
   icratetriggered    :=false;

   end;
   
end;

function tbackgroundmanager.xsettingsChanged(xreset:boolean):boolean;//enhanced syncing - 02mar2026
var
   xref:string;
begin

//get
xref:=
 intstr32(strength)+'|'+
 intstr32(colorise)+'|'+
 intstr32(speed)+'|'+

 intstr32(hstep)+'|'+
 intstr32(hwobble)+'|'+

 intstr32(vstep)+'|'+
 intstr32(vwobble)+'|'+

 intstr32(fstep)+'|'+
 intstr32(fwobble)+'|'+

 intstr32(crate)+'|'+

 '';

//set
result:=(isettingsRef<>xref);
if xreset then isettingsRef:=xref;

end;

procedure tbackgroundmanager.setitemindex(xindex:longint);

   procedure s(xnewindex:longint);
   begin

   if low__setint(iuse_itemindex,xnewindex) then iuse_tileref:='';

   end;

begin

if low__setint(iitemindex, frcrange32(xindex,0,frcmin32(ilimit-1,0)) ) then
   begin

   if strmatch(sysback_name[iitemindex],'default') then s(findbyname(app__info('back.name')))
   else                                                 s(iitemindex);

   imustpaint:=true;

   end;

end;

function tbackgroundmanager.getname(xindex:longint):string;
begin
if sysback__usedindex(xindex) then result:=sysback_name[xindex] else result:='';
end;

function tbackgroundmanager.iscustom(xindex:longint):boolean;
begin
if sysback__usedindex(xindex) then result:=sysback_iscustom[xindex] else result:=false;
end;


//## tbasicsystem ##############################################################
constructor tbasicsystem.create(dwidth,dheight:longint);
var
   w,h,v,xmonitorindex,p:longint;
begin

//self
if classnameis('tbasicsystem') then track__inc(satSystem,1);
zzadd(self);

if1_showhelp             :=false;
if2_restoredefaults      :=false;
imustcloseprompt         :=false;//26aug2021
ilastmousemovecheckx     :=min32;//07mar2022
ilastmousemovechecky     :=min32;
iecopainting             :=false;//16nov2023
icursorloadid            :=-1;
iclosed                  :=false;
icloselocked             :=0;

low__sysadd(self);

ishowmenu                :=nil;
ilaststate               :='h';

//vars
ifocusindex              :=min32;//no focus
oclsscreen               :=false;//26dec2025

//.rootwin support
irootwin                 :=nil;

//.game mode support
igamemode                :=false;
igamemode_cansize        :=false;
igamemode_canmove        :=false;
igamemode_onpaint        :=nil;
igamemode_onshortcut     :=nil;
igamemode_onnotify       :=nil;
igamemode_onkey          :=nil;//22jul2025
igamemode_onmouse        :=nil;//22jul2025
fonkey                   :=nil;//22jul2025
oeraseingbackground      :=0;//24jul2025

//.form support
otestmode                :=false;
ocansize                 :=true;
ocanmove                 :=true;
ipaint_tryagain_count    :=0;
iform_lastshift          :=false;
iform_lastalt            :=false;
iform_lastctrl           :=false;
iform_width              :=0;
iform_height             :=0;
iform_handle             :=0;
iform_paintdc            :=0;
iform_caption            :='';
iform_active             :=false;
iform_cornersREF         :='';
iform_fullscreen         :=false;
iform_sizeref            :='';
iform_handle             :=form__create(true);
iform_lastdpi            :=getdpi;//requires above form handle to function - 10dec2025
iform_sizecheckcount     :=0;
form__setcaption(app__info('name'));

//.showoptions support
ipumptimer2              :=slowms64;
ishowoptions_inuse       :=false;
ishowoptions_maintoolbar :=nil;
ishowoptions_toolbar_background:=nil;
ishowoptions_window      :=nil;
ishowoptions_frames      :=nil;
ishowoptions_backs       :=nil;
ishowoptions_backgroundpanel:=nil;
ishowoptions_backs_cols  :=nil;
ishowoptions_statslist   :=nil;
ishowoptions_snooplist   :=nil;
ishowoptions_list        :=nil;
ishowoptions_cols        :=nil;
ishowoptions_options     :=nil;
ishowoptions_colors      :=nil;
ishowoptions_font        :=nil;
ishowoptions_font_vpos   :=0;

ishowoptions_stats       :=nil;
ishowoptions_stats_vpos  :=0;
ishowoptions_stats_vpos2 :=0;

ishowoptions_snoop       :=nil;
ishowoptions_snoop_vpos  :=0;
ishowoptions_snoop_vpos2 :=0;

ishowoptions_settings    :=nil;
ishowoptions_settings_vpos:=0;//02dec2024
ishowoptions_framesize1  :=nil;
ishowoptions_framesize2  :=nil;
ishowoptions_sparkle1    :=nil;
ishowoptions_sparkle2    :=nil;
ishowoptions_brightness3 :=nil;
ishowoptions_focusedopacity1:=nil;
ishowoptions_unfocusedopacity1:=nil;
ishowoptions_opacityspeed1:=nil;
ishowoptions_timer100    :=slowms64;
ishowoptions_timer500    :=slowms64;

//.background support - 02mar2025
ibackgroundmanager       :=tbackgroundmanager.create(self);

//.other
itimer_busy              :=false;//05may2021
isplash                  :=nil;
ilastdataid              :=-1;
fontimer                 :=nil;
iontimerbusy             :=false;
ishowoptions_crosssync   :=false;//26feb2022
itiming                  :=false;
istable                  :=1;//0=stable, 1=creating, 2=destroying
ipaintfirst              :=false;//true=1st full paint has been done, false=no full paint done yet -> used for paint sensitive procs that must work AFTER at least the first fullpaint -> 02dec2024
//.background tile and animation support
ipaintedwithtile         :=false;

//.system visual buffers
ibuffer                  :=nil;
ibuffer2                 :=nil;
ibufferID2               :=0;
low__cls(@ibuffer2info,sizeof(ibuffer2info));
idragbuffer              :=nil;
idragbufferRef64         :=0;
idragdrop_icon           :=nil;
ihidecursorref           :=0;//off - 28feb2022
isizing                  :=0;//22apr2022
iform_sizing             :=false;
imask                    :=nil;
imaskRef64               :=0;

inherited create;

//init
ilastsystem_slowref64    :=slowms64;//10may2021
iecomode64               :=slowms64;
ishowonceref             :=add64(slowms64,30000);
ibufferresize64          :=slowms64;
itimer100                :=slowms64;
itimer250                :=slowms64;
itimer1000               :=slowms64;
itimer5000               :=slowms64;
isnapshot64              :=0;//off - 03nov2023
iopacitytimer            :=slowms64;
idrawtohost_count        :=0;//12jan2025

//.fastdraw support - 01jan2026
fdCorners                :=fd__new;
fdControls               :=fd__new;
fdHintEtc                :=fd__new;
fdTemp                   :=fd__new;

//.fps
ifpscount                :=0;
ifps                     :=0;

//.do not zoom window -> done by tbasicapp which calls this proc - 05may2025
xmonitorindex            :=monitors__findBYcursor;

//.status support
istatuswin               :=nil;
istatustime              :=slowms64;
istatuspert              :=0;
istatusrowcount          :=0;
istatustab               :=tbDefault;//05oct2022 -> unrestricted second column

for p:=0 to high(istatustext) do
begin

istatustext[p]           :='';
istatustep[p]            :=tepNone;

end;//p

istatustitle             :='Status';
istatusshow              :=false;
istatusstopped           :=false;

//gui state
iwinemaximised           :=false;//supports PROPER maximise display in Wine - 05feb2022
inormalarea              :=area__make(0,0,100,100);

//show modes
smnone                   :=0;
smmodal                  :=1;
smwait                   :=2;
//xxxxxxxxxxishowmode:=smnone;

//index styles
xsnone                   :=0;//nothing is selected
xsoutside                :=1;//coordinates outside of form
//was: xssize             :=2;//resize bar selected (resizing form)
xscontrol                :=3;//a control is selected
xsunknown                :=4;//unknown state

//pop support
ipophost                 :=nil;
ipopshortcut             :=aknone;

//window support
iwinfocus                :=-1;
iwinfocuslayer           :=-1;
iwinhover                :=-1;
iwinhoverlayer           :=-1;
idragindex               :=-1;
idragstart               :=-1;
isizeindex               :=-1;
isizestart               :=-1;
idragging_fullwin        :=false;//15apr2021

//32bit buffer for "twinbmp" is slightly faster -> e.g. upto 25% faster...............//??????????????
ibuffer                  :=miswin(24,1,1);//starts off as 24bit, when it changes to 32bit make sure to set alpha to 255 as no integrated(attached to tbasicsystem) fastdraw proc will
ibuffer2                 :=miswin(24,1,1);//as with "ibuffer"
idragbuffer              :=misraw(24,1,1);//as with "ibuffer"

//.drag and drop
idragdrop_icon           :=misimg(32,1,1);//fixed at 32bit for system opacity and icon transparency - 06jun2025
idragdrop_startarea      :=noarea;
idragdrop_paintarea      :=noarea;
idragdrop_code2          :='';
idragdrop_ref            :='';
idragdrop_dragging       :=false;
idragdrop_lastarea       :=noarea;
idragdrop_power255       :=190;

//.mask
imask                    :=tmask8.create(1,1);//high-speed window based mask for detecting window paint layers
imaskval                 :=-1;//off
ikeyboardlaststate       :=0;
imousebuttonlock         :=-1;//off
ilastsystem_mustid       :=-1;
ilastsystem_mustidSLOW   :=-1;//10may2021
imustclose               :=false;
iwheel                   :=0;
ishiftok                 :=false;
ictrlok                  :=false;
ialtok                   :=false;
ikey                     :=aknone;
imousedbclicktime        :=sub64(slowms64,30000);
imousedbclick            :=false;
imousedown               :=false;
imousedownref            :=0;//off
imousemoved              :=false;
imousewasdown            :=false;
imousedownxy             :=low__point(0,0);
imousemovexy             :=low__point(0,0);
iscreendownxy            :=low__point(0,0);
iscreenmovexy            :=low__point(0,0);
iscreendragging          :=false;
iscreendraggingv         :=false;
iscreendraggingh         :=false;
iscreendraggingfine      :=false;
iscreendraggingfinev     :=false;
iscreendraggingfineh     :=false;
iscreendraggingout       :=false;
iscreenmovingfine        :=false;
iscreenmovingfinexy      :=low__point(0,0);
iscreenmovingfine64      :=slowms64;
imousebutton             :=abnone;//off

//wound support - 30sep2022
iwoundratelimit          :=5000;
iwoundratex              :=0;
iwoundratey              :=0;
iwounddirx               :=1;
iwounddiry               :=1;
iwoundlastx              :=0;
iwoundlasty              :=0;
iwoundref                :=slowms64;

//hint support - 25dec2024
ihint                    :='';
ihintlines               :=nil;
ihinttitle_linecount     :=0;
ihintarea                :=nilarea;
ihintXY                  :=low__point(0,0);
ihintTimeout             :=0;//off
ihintOnsecs              :=5;

//own support
ownlist.count            :=0;
ownid                    :=0;

//window support
iwinlimit                :=high(winlist.list)+1;//255 -> max. number of windows is 255 (0..254), 255=reserved for graphic mask as "nil"
iwinmax                  :=high(winlist.list);//254 -> window layer range is 0..254
winlist.count            :=0;

//window mask support
winmask_cnt              :=0;

for p:=0 to high(winmask_id) do
begin

winmask_id[p]            :=-1;
winmask_aid[p]           :=-1;
winmask_vis[p]           :=false;
winmask_rnd[p]           :=false;

end;//p

//automatic opacity
ilastopacity100x         :=viunfocusedopacity*100;
ilastopacitystep         :=1;
ilastopacityref          :='';

//core
icorecount               :=0;
for p:=0 to high(icore) do icore[p]:=nil;

//action
iacount                  :=0;

//paint
for p:=0 to high(recs) do recs[p]:=area__make(0,0,0,0);

ialignid                 :=0;
ipaintid                 :=0;
ipostpaint_fullid        :=0;
ipostpaint_partid        :=0;

//vars
imasking                 :=false;
ipaintbusy               :=false;
ipainting                :=0;
ipaintingpart            :=false;
ipartpaintareaok         :=false;
ipartpaint_count         :=0;
imustpaint               :=0;
imustalign               :=0;
ialigning                :=false;


//.system
system__include(self);//required for "app__gui" to work - 11dec2025


//.size width and height
viscale                  :=scale__calculate;//automatically takes into account for "system_blackwhitecount>=1" - 10dec2025
v                        :=frcmin32(monitors__scale(xmonitorindex),96);
w                        :=monitors__workareawidth_auto(xmonitorindex);
h                        :=monitors__workareaheight_auto(xmonitorindex);

width                    :=round( (dwidth  / 1920) * (v/96) * frcmax32(w,1920) );
height                   :=round( (dheight / 1080) * (v/96) * frcmax32(h,1080) );


//.center window
form__center(xmonitorindex);


//.timer
low__timerset(self,__ontimer,50);


//ready ------------------------------------------------------------------------
istable                  :=0;//0=stable, 1=creating, 2=destroying
imustalign               :=2;
imustpaint               :=2;


//drag and drop init -----------------------------------------------------------
win____dragacceptfiles(iform_handle,true);

end;

destructor tbasicsystem.destroy;
var
   p:longint;
begin
try

//init
istable:=2;

//store pos / size in system settings
xsavePosSize;

//stop drag and drop
if (iform_handle<>0) then win____dragacceptfiles(iform_handle,false);

//disconnect timers
low__timerdel(self,__ontimer);//disconnect our timer event from the system timer
fontimer          :=nil;
fontimer2         :=nil;

//disconnect gamemode
igamemode            :=false;
igamemode_onpaint    :=nil;
igamemode_onnotify   :=nil;
igamemode_onshortcut :=nil;
igamemode_onkey      :=nil;
igamemode_onmouse    :=nil;
fonkey               :=nil;

//remove iform from system list
system__exclude(self);

//free specific controls
freeobj(@isplash);

//core - destroy any remaining windows/objects
for p:=0 to high(icore) do if zzok(icore[p],7092) then freeobj(@icore[p]);

//.fastdraw support
fd__del( fdCorners  );
fd__del( fdControls );
fd__del( fdHintEtc );
fd__del( fdTemp );

//.buffers etc
freeobj(@ibuffer);
freeobj(@ibuffer2);
freeobj(@idragbuffer);
freeobj(@idragdrop_icon);
freeobj(@imask);
freeobj(@ihintlines);
freeobj(@ibackgroundmanager);

//.iform
win____destroywindow(iform_handle);

//self
low__sysdel(self);
inherited destroy;

//track
if classnameis('tbasicsystem') then track__inc(satSystem,-1);

except;end;
end;

procedure tbasicsystem.xsavePosSize;
begin

//pos and size
if (syssettings<>nil) and (state='n') then
   begin

   syssettings.i['left']     :=left;
   syssettings.i['top']      :=top;
   syssettings.i['width']    :=width;
   syssettings.i['height']   :=height;
   syssettings.i['wh.scale'] :=round32( viscale*100 );//17dec2025

   end;

end;

function tbasicsystem.getbackgroundname:string;
begin

result:=ibackgroundmanager.backgroundname;

end;

procedure tbasicsystem.setbackgroundname(x:string);
begin

if (ibackgroundmanager.backgroundname<>x) then
   begin

   ibackgroundmanager.backgroundname:=x;
   ibackgroundmanager.sync_panel(ishowoptions_backgroundpanel);

   end;

end;

function tbasicsystem.backgroundinuse:boolean;
begin
result:=ibackgroundmanager.inuse;
end;

function tbasicsystem.lastbuffer:twinbmp;
begin
if ibuffer2info.active then result:=ibuffer2 else result:=ibuffer;
end;

function tbasicsystem.lastrows:tstr8;
begin
if ibuffer2info.active then result:=ibuffer2.rows else result:=ibuffer.rows;
end;

function tbasicsystem.getcursor:longint;
begin
result:=app__cursor;
end;

procedure tbasicsystem.setcursor(x:longint);
begin
app__setcursor(x);
end;

function tbasicsystem.haverootwin:boolean;
begin
result:=(irootwin<>nil);
end;

function tbasicsystem.rootwin:tbasicscroll;
begin
if (irootwin=nil) then irootwin:=nfullwin;
result:=irootwin;
end;

function tbasicsystem.form__create(xacceptfiles:boolean):hauto;//01jun2025, 28may2025
const
   xclassname='basicsystem';
var
   a:twndclassex;
   s:longint;
begin

low__cls(@a,sizeof(a));//05oct2025

with a do
begin
cbsize          :=sizeof(a);
lpfnWndProc     :=@system__windowproc;
//lpszMenuName    :=nil;
lpszClassName   :=pchar(xclassname);
hIcon           :=win____loadicon(app__hinstance,pchar('MAINICON'));//app icon - 28may2025
hCursor         :=win____loadcursor(0,IDC_ARROW);
hinstance       :=app__hinstance;
end;

win____registerclassexa(a);

//note: ws_minimizebox informs then taskbar that this app can be minimised by single clicking it's taskbar button - 20jan2025
//was: result:=win____createwindowex( WS_EX_APPWINDOW or insint(WS_EX_ACCEPTFILES,xacceptfiles) or insint(WS_EX_LAYERED,app__cansetwindowalpha) ,pchar(xclassname),'',ws_popup or ws_minimizebox,0,0,0,0,0,0,app__hinstance,nil);

//create a minimal resizable window for Win10/11 etc - 03dec2025
s:=or32(ws_popup,ws_minimizebox);

//Win98: Additional styles "ws_thickframe, ws_sysmenu" required for Win98 (OS=v4) -> ws_sysmenu: puts an icon on the taskbar but disables window resizing, ws_thickframe re-enables window resizing, but under Win10/11 causes momentary blackness during window resizing - 01jun2025
if system_osWin9X then s:=s or ws_thickframe or ws_sysmenu;

//create window
result:=win____createwindowex( WS_EX_APPWINDOW or insint(WS_EX_ACCEPTFILES,xacceptfiles) or insint(WS_EX_LAYERED,app__cansetwindowalpha) ,pchar(xclassname),'',s,0,0,0,0,0,0,app__hinstance,nil);

end;

function tbasicsystem.form__monitorindex:longint;
begin
result:=monitors__findBYarea(area);
end;

procedure tbasicsystem.form__center(xmonitorindex:longint);
var//note: xfromTop=optional=0=off, 1..N shifts form down from top of upper boundary
   //note: xmonitorindex=-1=off, 0..N=use this for area
   d:twinrect;
   dw,dh:longint;
begin
//range
dw:=frcmin32(width,1);
dh:=frcmin32(height,1);

//set
if (xmonitorindex<0) then xmonitorindex:=gui__sysprogram_monitorindex;
d:=monitors__centerINarea_auto(dw,dh,xmonitorindex,true);
setbounds(d.left,d.top,d.right-d.left+1,d.bottom-d.top+1);
end;

procedure tbasicsystem.form__setcaption(x:string);
begin
if low__setstr(iform_caption,x) then win____SetWindowText(iform_handle,pchar(x));
end;

function tbasicsystem.form__bordersize:longint;
begin
if haverootwin then result:=rootwin.findbordersize else result:=0;
end;

function tbasicsystem.form__minwidth:longint;
begin
if haverootwin then result:=rootwin.ominwidth else result:=0;
result:=frcmin32(result,minwinsize);
end;

function tbasicsystem.form__minheight:longint;
begin
if haverootwin then result:=rootwin.ominheight else result:=0;
result:=frcmin32(result,minwinsize);
end;

function tbasicsystem.getshowing:boolean;
var
   v:char;
begin
v:=state;
result:=(v='n') or (v='+') or (v='f');
end;

function tbasicsystem.form__getontop:boolean;
begin
result:=bit__hasval32(win____GetWindowLong(iform_handle,GWL_EXSTYLE),WS_EX_TOPMOST);
end;

procedure tbasicsystem.form__setontop(x:boolean);
begin
if (x<>form__getontop) then
   begin
   if x then win____setwindowpos(iform_handle,HWND_TOPMOST  ,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE or WS_EX_TOPMOST)
   else      win____setwindowpos(iform_handle,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE);
   end;
end;

function tbasicsystem.xdrawfrom(const shc:hauto;const sa:twinrect):boolean;
begin

result:=(iform_paintdc<>0) and (shc<>0) and validarea(sa) and win____StretchBlt(iform_paintdc,sa.left,sa.top,sa.right-sa.left+1,sa.bottom-sa.top+1,shc,sa.left,sa.top,sa.right-sa.left+1,sa.bottom-sa.top+1,srcCopy);

end;

function tbasicsystem.xdrawfrom2(const shc:hauto;const dx,dy:longint;const sa:twinrect):boolean;
begin

result:=(iform_paintdc<>0) and (shc<>0) and validarea(sa) and win____StretchBlt(iform_paintdc,dx,dy,sa.right-sa.left+1,sa.bottom-sa.top+1,shc,sa.left,sa.top,sa.right-sa.left+1,sa.bottom-sa.top+1,srcCopy);

end;

function tbasicsystem.xcopyfrom(const shc:hauto;const sa,da:twinrect):boolean;
begin

result:=(iform_paintdc<>0) and (shc<>0) and validarea(da) and validarea(sa) and win____StretchBlt(iform_paintdc,da.left,da.top,da.right-da.left+1,da.bottom-da.top+1,shc,sa.left,sa.top,sa.right-sa.left+1,sa.bottom-sa.top+1,srcCopy);

end;

procedure tbasicsystem.form__fadeout(const xreset:boolean);
var
   p:longint;
begin

if not app__cansetwindowalpha then exit
else if not viminimiseeffect  then exit
else if xreset                then app__setwindowalpha(iform_handle,vifocusedopacity)
else
   begin

   for p:=10 downto 1 do
   begin

   app__setwindowalpha(iform_handle, frcrange32(round(vifocusedopacity*(p/10)),0,255) );
   win____sleep(15);

   end;//p

   end;

end;

procedure tbasicsystem.form__fadein(const xreset:boolean);//18feb2025: tweaked, 05feb2025
var
   p:longint;
begin

if not app__cansetwindowalpha then exit
else if not viminimiseeffect  then exit
else if xreset                then app__setwindowalpha(iform_handle,1)//almost invisible -> enough for window to fire wm_paint message
else
   begin

   //update and paint GUI
   paintallnow;
   app__timers;
   app__processallmessages;
   app__timers;

   //fade-in updated GUI smoothly
   for p:=1 to 10 do
   begin

   app__setwindowalpha(iform_handle, frcrange32(round(vifocusedopacity*(p/10)),0,255) );
   win____sleep(15);

   end;//p

   end;

end;

procedure tbasicsystem.setstate(x:char);
begin

//filter
if (x<>'n') and (x<>'-') and (x<>'+') and (x<>'f') and (x<>'h') then x:='n';

//update fullscreen mode ONLY for visual modes
if (x='n') or (x='+') or (x='f') then iform_fullscreen:=(x='f');

//set
if      (x=state)          then exit
else if (x='n')            then win____showwindow(iform_handle,SW_SHOWNORMAL)
else if (x='-')            then win____sendmessage(iform_handle,wm_syscommand,sc_minimize,0)
else if (x='+') or (x='f') then win____sendmessage(iform_handle,wm_syscommand,sc_maximize,0)
else if (x='h')            then win____sendmessage(iform_handle,wm_syscommand,sc_minimize,0);//was win____showwindow(iform_handle,SW_HIDE);

//reset size count checker - 09sep2025
iform_sizecheckcount:=0;

//sync
form__sizeSync;

end;

procedure tbasicsystem.form__paintnow;//05oct2025
begin

if (iform_handle<>0) and (not win____isiconic(iform_handle)) and win____iswindowvisible(iform_handle) then
   begin

   win____InvalidateRect(iform_handle,nil,false);

   //force immediate repaint - 05oct2025
   //win____updatewindow(iform_handle);

   end;

end;

function tbasicsystem.getdpi:longint;//10dec2025
var
   v:longint;
begin

//DPI_AWARENESS_INVALID            = -1
//DPI_AWARENESS_UNAWARE            = 0
//DPI_AWARENESS_SYSTEM_AWARE       = 1
//DPI_AWARENESS_PER_MONITOR_AWARE  = 2

//A value of 96 dpi is considered the default => scaling 1.0 => 100%
v:=win2____GetDpiForWindow(handle);

case v of
1          :result:=win2____GetDpiForSystem;
2          :result:=win2____GetDpiForSystem;
96..maxint :result:=v;
else        result:=96;
end;//case

result:=frcrange32(result, 96, round(96*gui__scalemax) );//1.0x to 16.0x

end;

function tbasicsystem.xdpiChanged:boolean;
begin

result:=low__setint( iform_lastdpi, round(100*scale__calculate) );

end;

function tbasicsystem.getstate:char;
var
   a:TWindowPlacement;
   v:longint;
begin

//init
a.length:=sizeof(a);

//decide
if      win____isiconic(iform_handle)              then v:=sw_hide
else if not win____iswindowvisible(iform_handle)   then v:=sw_hide
else if win____GetWindowPlacement(iform_handle,@a) then v:=a.showcmd
else                                                    v:=sw_hide;

//get
case v of
sw_hide              :result:='h';
sw_normal            :result:='n';
sw_showminimized     :result:='-';
sw_maximize          :result:='+';
sw_shownoactivate    :result:='n';
sw_show              :result:='n';
sw_minimize          :result:='-';
sw_showminnoactive   :result:='-';
sw_showna            :result:='n';
sw_restore           :result:='n';
sw_showdefault       :result:='n';
11                   :result:='-';//SW_FORCEMINIMIZE
else                  result:='n';
end;//case

//fullscreen check
if (result='+') and iform_fullscreen then result:='f';

ilaststate:=result;

end;

procedure tbasicsystem.form__wmsetcursor(var m:twinmessage);
begin
if (tint4( msg_l32(m.l) ).bytes[0]=htclient) or (tint4( msg_l32(m.l) ).bytes[0]=htcaption) then
   begin
   app__cursorReapply;
   m.r:=1;
   end;
end;

procedure tbasicsystem.form__wmentersizemove;
begin
iform_sizing:=true;
end;

procedure tbasicsystem.form__wmexitsizemove;
begin
iform_sizing:=false;
paintallnow;//13may2025: for Win98
end;

procedure tbasicsystem.form__wmsize(var m:twinmessage);
var
   a:twinrect;
   v:char;
begin

v:=state;

if (v='+') then
   begin

   a:=monitors__workarea_auto(monitorindex);
   setbounds(a.left,a.top,a.right-a.left+1,a.bottom-a.top+1);

   end
else if (v='f') then
   begin

   a:=monitors__area_auto(monitorindex);
   setbounds(a.left,a.top,a.right-a.left+1,a.bottom-a.top+1);

   end
else if (v='n') then form__sizeSync;

end;

procedure tbasicsystem.form__wmsizing(var m:twinmessage);//09mar2025: implemented min width/height enforcement

   procedure xtest;
   begin

   if (pwinrect( msg_l32(m.l) ).right>800) then
      begin

      pwinrect( msg_l32(m.l) ).right:=800;
      m.r:=1;

      end;

   end;

begin

if otestmode then xtest
else
   begin

   pwinrect( msg_l32(m.l) ).right :=frcmin32(pwinrect( msg_l32(m.l) ).right ,pwinrect( msg_l32(m.l) ).left+minwinsize-1);
   pwinrect( msg_l32(m.l) ).bottom:=frcmin32(pwinrect( msg_l32(m.l) ).bottom,pwinrect( msg_l32(m.l) ).top+minwinsize-1);

   end;
end;

procedure tbasicsystem.setbounds(dx,dy,dw,dh:longint);
begin
form__setbounds2(dx,dy,dw,dh,false);
end;

procedure tbasicsystem.setbounds2(dx,dy,dw,dh:longint;xforcerepaint:boolean);
begin
form__setbounds2(dx,dy,dw,dh,xforcerepaint);
end;

procedure tbasicsystem.form__setbounds2(dx,dy,dw,dh:longint;xforcerepaint:boolean);//05may2025
var
   a:twinrect;
begin

//range
a:=area;
dw:=frcmax32( frcmin32( dw, (2*form__bordersize)+ form__minwidth  ), monitors__areatotalwidth);
dh:=frcmax32( frcmin32( dh, (2*form__bordersize)+ form__minheight ), monitors__areatotalheight);

//get
form__move(iform_handle,dx,dy,dw,dh, xforcerepaint or (dw<>(a.right-a.left+1)) or (dh<>(a.bottom-a.top+1)) );
form__sizeSync;

end;

procedure tbasicsystem.form__sizeSync;
var
   a:twinrect;
   dw,dh:longint;
begin

//read actual width/height
a:=area;
dw:=frcmin32(a.right-a.left+1,0);
dh:=frcmin32(a.bottom-a.top+1,0);

if (dw<>iform_width) or (dh<>iform_height) then
   begin

   iform_width:=dw;
   iform_height:=dh;
   imustalign:=2;
   imustpaint:=2;
   form__paintnow;
   app__turbo;

   end;

end;

procedure tbasicsystem.form__setval32(n:char;dv:longint);
var
   a:twinrect;
begin

if (n='l') or (n='t') or (n='w') or (n='h') then
   begin

   a:=form__area;

   if      (n='l') then form__setbounds2(dv,a.top,a.right-a.left+1,a.bottom-a.top+1,false)
   else if (n='r') then form__setbounds2(a.left,dv,a.right-a.left+1,a.bottom-a.top+1,false)
   else if (n='w') then form__setbounds2(a.left,a.top,dv,a.bottom-a.top+1,false)
   else if (n='h') then form__setbounds2(a.left,a.top,a.right-a.left+1,dv,false);

   end;

end;

function tbasicsystem.form__getval32(n:char):longint;
var
   a:twinrect;
begin

if (n='l') or (n='t') or (n='w') or (n='h') then
   begin

   a:=form__area;

   if      (n='l') then result:=a.left
   else if (n='t') then result:=a.top//09mar2025: fixed
   else if (n='w') then result:=a.right-a.left+1
   else if (n='h') then result:=a.bottom-a.top+1
   else                 result:=0;

   end
else result:=0;

end;

function tbasicsystem.form__getarea:twinrect;
begin

if win____getwindowrect(iform_handle,result) then
   begin

   //convert to zero based area
   dec(result.right);
   dec(result.bottom);

   end
else result:=area__make(0,0,0,0);

end;

procedure tbasicsystem.form__setarea(x:twinrect);
begin

form__setbounds2(x.left,x.top,x.right-x.left+1,x.bottom-x.top+1,false);

end;

function tbasicsystem.form__paintarea:twinrect;
begin

result:=form__area;

dec(result.right,result.left+1);//zero based
result.left:=0;

dec(result.bottom,result.top+1);
result.top:=0;

end;

function tbasicsystem.form__paintarea1:twinrect;
begin

result:=form__area;

dec(result.right,result.left);
result.left:=0;

dec(result.bottom,result.top);
result.top:=0;

inc(result.right);
inc(result.bottom);

end;

procedure tbasicsystem.form__setleft(x:longint);
begin
form__val32['l']:=x;
end;

procedure tbasicsystem.form__settop(x:longint);
begin
form__val32['t']:=x;
end;

procedure tbasicsystem.form__setwidth(x:longint);
begin
form__val32['w']:=x;
end;

procedure tbasicsystem.form__setheight(x:longint);
begin
form__val32['h']:=x;
end;

function tbasicsystem.form__getleft:longint;
begin
result:=form__val32['l'];
end;

function tbasicsystem.form__gettop:longint;
begin
result:=form__val32['t'];
end;

procedure tbasicsystem.form__wmnchittest(var m:twinmessage);//01feb2026
var
   fw:tbasiccontrol;

   procedure xperform(xcansize,xcanmove:boolean);
   var
      a:twinrect;
      c:tpoint;
      bs:longint;
      l,r,t,b:boolean;

   begin

   a   :=area;
   c   :=low__getcursorposb;
   bs  :=frcmin32( form__bordersize ,round32(gui__minResizeBorder*viscale) );//form__bordersize=pre-scaled - 01feb2026

   xcansize:=xcansize and (ocansize and ((not igamemode) or igamemode_cansize) );
   xcanmove:=xcanmove and (ocanmove and ((not igamemode) or igamemode_canmove) );

   r:=xcansize and (c.x>=(a.right-bs));
   l:=xcansize and (c.x<=(a.left+bs));
   t:=xcansize and (c.y<=(a.top+bs));
   b:=xcansize and (c.y>=(a.bottom-bs));

   if xcanmove and igamemode then xcanmove:=(c.y<=(area.top+bs+32));

   if      t and l        then m.r:=httopleft
   else if t and r        then m.r:=httopright
   else if b and r        then m.r:=htbottomright
   else if b and l        then m.r:=htbottomleft
   else if l              then m.r:=htleft
   else if r              then m.r:=htright
   else if t              then m.r:=httop
   else if b              then m.r:=htbottom
   else if (m.r=htclient) then m.r:=low__aorb(htclient,htcaption,xcanmove)
   else                        m.r:=htclient;

   end;
begin

m.r:=htclient;

//26jul2025
if system_clipcursor_active or (imousebuttonlock<>-1) then exit;

if haverootwin then
   begin

   if igamemode then xperform(igamemode_cansize,igamemode_canmove)
   else
      begin

      //which window is focused
      if (focuscontrol=nil) then fw:=rootwin else focuscontrol.xwindow(fw);

      //resize or drag window
      if (fw=rootwin) then xperform(true,rootwin.xhavehead and rootwin.xhead.canmovewindow);

      end;
   end;
end;


procedure tbasicsystem.form__wmpaint(dc:hauto;var ps:tpaintstruct);

   procedure xtest;
   var
      b:hauto;
      t:string;
   begin

   if (iform_paintdc<>0) then
      begin

      b:=win____GetSysColorBrush(3);
      win____fillrect(iform_paintdc,paintarea1,b);

      t:=bolstr(iform_active)+'<'+k64(width)+' x '+k64(height)+'<<'+ms64str;
      win____TextOut(iform_paintdc,5,5,pchar(t),low__len32(t));

      end;

   end;
begin
try

iform_paintdc:=dc;

if otestmode then xtest
else
   begin

   //   imustpaint:=2;//assume full paint
   __onpaint(self);

   end;
except;end;

iform_paintdc:=0;

end;

procedure tbasicsystem.form__wmmousewheel(var m:twinmessage);
var//Tested and correct on XP HOME on 05-FEB-2006
   a:tint4;
   xval:longint;
begin
try

//handled
m.r:=0;
low__resetwheeltime;//03apr2021

//get
if (istable=0) then
   begin

   a.val  :=msg_w32(m.w);
   xval   :=round(smallint(a.wrds[1])/120)*viwheelspeed;

   if (xval<>0) then aadd('w',0,xval,0);

   end;

except;end;
end;

procedure tbasicsystem.form__wmacceptfiles(var m:twinmessage);//08oct2024, 14feb2024: updated, drag&drop files - 24APR2011, 07DEC2009
label
   skipend;
const
   flimit=1024;
var
   a:tbasiccontrol;
   b:tpoint;
   p,count:longint;
   f:array [0..flimit] of char;
   ffolder,fstr:string;
begin
try
//init
fillchar(f,sizeof(f),#0);//23APR2011
//find out how many files we're accepting
//was: count:=win____dragqueryfile(m.w,$FFFFFFFF,f,flimit);
count:=win____dragqueryfile( msg_w32(m.w) ,-1,f,flimit);
//get control
b:=low__mouse(self,'m');
if not xacceptfindbyxy(b.x,b.y,a) then goto skipend;

//query Windows one at a time for the file name
for p:=0 to (count-1) do
begin

///check
if (istable<>0) or gui__closing then break;//03apr2021

//.start
win____dragqueryfile( msg_w32(m.w) ,p,f,flimit);

//.filename
fstr:=fromnullstr(@f,sizeof(f));

//.foldername
case io__folderexists(fstr) of
true:begin//dropped item is a folder
   ffolder:=io__asfolder(fstr);
   fstr:=ffolder;//ensure supplied filename is converted to a folder - 24APR2011
   end;
else ffolder:=io__asfolder(io__extractfilepath(fstr));//dropped item is a file
end;

//.set
if (a=nil) or (not a.accept_passthru(self,ffolder,fstr,p,count)) then break;
end;
skipend:
except;end;
//let Windows know that we're done
try;win____dragfinish( msg_w32(m.w) );except;end;
end;

procedure tbasicsystem.form__wmactivateapp(var m:twinmessage);
begin
if low__setbol(iform_active,bool( msg_w32(m.w) )) then paintallnow;
end;

procedure tbasicsystem.form__wmactive(var m:twinmessage);
begin
if low__setbol(iform_active,(tint4( msg_w32(m.w) ).wrds[0]=1) or (tint4( msg_w32(m.w) ).wrds[0]=2)) then paintallnow;
end;

procedure tbasicsystem.form__mouse(s:byte;xbut:longint;var m:twinmessage);
label
   skipend;
var
   dx,dy:longint;

   procedure xextmouse;
   begin

   //check
   if (s<0) or (s>2) then exit;

   //event
   if assigned(igamemode_onmouse) then igamemode_onmouse(self,s,xbut,dx,dy,width,height);

   end;

begin

//check
if (istable<>0) then exit;

//init
dx:=tint4(msg_l32(m.l)).sint[0];
dy:=tint4(msg_l32(m.l)).sint[1];

//events

//.mouse down
if (s=0) then
   begin

   xextmouse;//external event - 26jul2025

   low__resetclicktime;//03apr2021
   xwaitfocus;//03apr2021

   //.mouse button already down and locked
   if (imousebuttonlock=-1) then imousebuttonlock:=xbut else goto skipend;

   low__mouse2(self,'d',dx,dy);
   aadd('d',xbut,dx,dy);

   end
//.mouse move
else if (s=1) then
   begin

   if (dx<>ilastmousemovecheckx) or (dy<>ilastmousemovechecky) then
      begin

      xextmouse;//external event - 26jul2025

      xwoundcalc(dx,dy);
      ilastmousemovecheckx:=dx;
      ilastmousemovechecky:=dy;
      low__resetmovetime;//03apr2021
      low__mouse2(self,'m',dx,dy);
      aadd('m',0,dx,dy);

      end;

   end
//.mouse up
else if (s=2) then
   begin

   xextmouse;//external event - 26jul2025

   low__resetclicktime;//03apr2021
   xwaitfocus;//03apr2021

   //.mouse button already down and locked -> ignore this button
   if (imousebuttonlock=-1) or (imousebuttonlock<>xbut) then goto skipend;

   low__mouse2(self,'u',dx,dy);
   aadd('u',xbut,dx,dy);
   imousebuttonlock:=-1;//off

   end;

skipend:
end;

procedure tbasicsystem.form__wmmousedown(xbut:longint;var m:twinmessage);
begin
if not assigned(igamemode_onmouse) then win____SetCapture(iform_handle);//capture the mouse
form__mouse(0,xbut,m);
end;

procedure tbasicsystem.form__wmmousemove(var m:twinmessage);
begin
form__mouse(1,0,m);
end;

procedure tbasicsystem.form__wmmouseup(xbut:longint;var m:twinmessage);
begin
form__mouse(2,xbut,m);
if not assigned(igamemode_onmouse) then win____ReleaseCapture;//release captured mouse
end;

procedure tbasicsystem.form__wmkeydown(var m:twinmessage);//23jan2025
var
   p,int1:longint;
begin

low__resetkeytime;//03apr2021

case msg_w32(m.w) of
16:iform_lastshift:=true;
17:iform_lastctrl :=true;
18:iform_lastalt  :=true;
end;

low__mousefine_turnon(iform_lastshift);
for p:=1 to tint4(msg_l32(m.l)).bytes[0] do if low__keyboard2('d',msg_w32(m.w),iform_lastshift,iform_lastctrl,iform_lastalt,int1,ikeyboardlaststate) then aadd('k',0,int1,0);

//.onkeydown - 22jul2025
if gamemode and assigned(igamemode_onkey) then igamemode_onkey(self, msg_w32(m.w) ,true);
if assigned(fonkey)                       then fonkey(self, msg_w32(m.w) ,true);

end;

procedure tbasicsystem.form__wmkeyup(var m:twinmessage);
var
   p,int1:longint;
begin

low__resetkeytime;//03apr2021

case msg_w32(m.w) of
16:iform_lastshift:=false;
17:iform_lastctrl :=false;
18:iform_lastalt  :=false;
end;

low__mousefine_turnon(iform_lastshift);
for p:=1 to tint4(msg_l32(m.l)).bytes[0] do if low__keyboard2('u',msg_w32(m.w),iform_lastshift,iform_lastctrl,iform_lastalt,int1,ikeyboardlaststate) then aadd('k',0,int1,0);

//.onkeydown - 22jul2025
if gamemode and assigned(igamemode_onkey) then igamemode_onkey(self, msg_w32(m.w) ,false);
if assigned(fonkey)                       then fonkey(self, msg_w32(m.w) ,false);

end;

procedure tbasicsystem.form__wmchar(var m:twinmessage);
var
   p,int1:longint;
begin
low__resetkeytime;//03apr2021
for p:=1 to tint4(msg_l32(m.l)).bytes[0] do if low__keyboard2('k',msg_w32(m.w),false,false,false,int1,ikeyboardlaststate) then aadd('k',0,int1,0);
end;

procedure tbasicsystem.form__wmsyschar(var m:twinmessage);
begin

end;

procedure tbasicsystem.form__wmsyskeydown(var m:twinmessage);
begin

end;

procedure tbasicsystem.form__wmsyskeyup(var m:twinmessage);
begin

end;

procedure tbasicsystem.form__wmclose(var m:twinmessage);
begin

end;

function tbasicsystem.canshowmenu:boolean;
begin
result:=(ishowmenu=nil);
end;

procedure tbasicsystem.showmenu(xsender:tobject;x:tstr8;xstyle:string;xevent:ttoolbarevent2);
var
   int1:longint;
   str1:string;
begin
showmenu1(xsender,x,xstyle,xevent,int1,str1);
end;

procedure tbasicsystem.showmenu1(xsender:tobject;x:tstr8;xstyle:string;xevent:ttoolbarevent2;var xcode:longint;var xcode2:string);
begin
showmenu2(xsender,x,xstyle,'',clnone,iaNormal,xevent,xcode,xcode2);
end;

procedure tbasicsystem.showmenu2(xsender:tobject;x:tstr8;xstyle,xmenuname:string;xtepcolor,ximagexalign:longint;xevent:ttoolbarevent2;var xcode:longint;var xcode2:string);
var
   a,xfocuscontrol:tbasiccontrol;
begin
try
//check
if not canshowmenu then exit;

//init
closelock;//prevent shutdown of system while proc in use - 03apr2021
ishowmenu      :=x;//pointer only
xstyle         :=strlow(xstyle);//03jun2021
xcode          :=0;
xcode2         :='';
xfocuscontrol :=focuscontrol;

//show
if (xsender is tbasiccontrol) then a:=(xsender as tbasiccontrol) else a:=nil;

if (low__menucount(ishowmenu)>=1) and popmenu2(pmNormal,ximagexalign,ishowmenu,xmenuname,0,xcode,xcode2,xtepcolor) and assigned(xevent) then xevent(a,xstyle,xcode,xcode2,xtepcolor);

//restore
focuscontrol:=xfocuscontrol;
except;end;
try
ishowmenu:=nil;
closeunlock;
except;end;
end;

procedure tbasicsystem.showappmenu(xallwinbuttons:boolean);//07sep2025, 27dec2024
var
   a:tstr8;
   xcode:longint;
   xcode2,xhint1:string;
   bol1:boolean;
begin

//defaults
a    :=nil;

try
//init
a    :=str__new8;
low__menuinit(a);

low__menutitle(a,tepnone,'Online Resources','');

xhint1:='External Content|View webpage in browser';

if (app__info('url.software')<>'')    then low__menuitem2(a,strint32(app__info('software.tep')),'App Website',xhint1,'nprogram',100,aknone,true);
if (app__info('url.portal')<>'')      then low__menuitem2(a,strint32(app__info('portal.tep')),app__info('portal.name'),xhint1,'be',100,aknone,true);
if (app__info('url.github')<>'')      then low__menuitem2(a,tepGitHub20,'GitHub',xhint1,'github',100,aknone,true);
if (app__info('url.sourceforge')<>'') then low__menuitem2(a,tepSourceforge20,'Sourceforge',xhint1,'sourceforge',100,aknone,true);
if (app__info('url.mastodon')<>'')    then low__menuitem2(a,tepMastodon20,'Mastodon',xhint1,'mastodon',100,aknone,true);
if (app__info('url.facebook')<>'')    then low__menuitem2(a,tepFacebook20,'Facebook',xhint1,'facebook',100,aknone,true);
if (app__info('url.twitter')<>'')     then low__menuitem2(a,tepTwitter20,'X',xhint1,'twitter',100,aknone,true);
if (app__info('url.instagram')<>'')   then low__menuitem2(a,tepInstagram20,'Instagram',xhint1,'instagram',100,aknone,true);
if (app__info('url.contact')<>'')     then low__menuitem2(a,tepTXT20,'Contact Us','External Content|Contact us via our contact form','contact',100,aknone,true);//07sep2025
low__menuitem2(a,tepAbout20,'About','About|About this app','about',100,aknone,true);

low__menutitle(a,tepnone,'Settings and Information','');
low__menuitem2(a,tepCapture20,'Capture Snapshot','Snapshot|Capture a snapshot of app and copy to Clipboard','snapshot.program',100,aknone,true);
low__menuitem2(a,tep__yes(viOntop),'On Top','On Top|Place app window above other windows','toggle.ontop',100,aknone,true);
low__menuitem2(a,tep__yes(viTouch),'Touch','Touch|Toggle touch mode for larger control surfaces','toggle.touch',100,aknone,true);
low__menuitem2(a,tep__yes(viHint),'Hints','Hints | Toggle display of popup hints','toggle.hint',100,aknone,true);
low__menuitem2(a,tep__yes(viHelp),'Realtime Help','Realtime Help | Toggle display of scrolling realtime help','toggle.realtimehelp',100,aknone,true);

if viMaster then low__menuitem2(a,tepOptions20,'Options','App Options|Adjust app coloring, font size and other settings','options',100,aknone,true);

if viMaster and ((sizeof(apphelp)>=2) or (sizeof(syshelp)>=2)) then low__menuitem2(a,tepHelp20,'Help','App Help|Toggle app help panel, or press the "F1" key to show','help',100,aknone,true);//24jul2021

if mm_ok or mid_ok or wav_ok then low__menuitem2(a,tepVol20,'Volume Mixer','External App|Show Volume Mixer','mixer',100,aknone,low__canshowvol);

low__menuitem2(a,tepRefresh20,'Restore Default Scale','Defaults|Restore default scale','defaultscale',100,aknone,viscale<>1.0);
if viMaster then low__menuitem2(a,tepRefresh20,'Restore Defaults...','Defaults|Restore default settings or press the "F2" key','defaults',100,aknone,true);

//.position
bol1:=canposition;
low__menutitle(a,tepnone,'Position','Position app on screen');
low__menuitem2(a,tepTop20,'Top of Screen','App|Position app window at top of screen','position.t',100,aknone,bol1);
low__menuitem2(a,tepLeft20,'Left of Screen','App|Position app window at left of screen','position.l',100,aknone,bol1);
low__menuitem2(a,tepRight20,'Right of Screen','App|Position app window at right of screen','position.r',100,aknone,bol1);
low__menuitem2(a,tepBottom20,'Bottom of Screen','App|Position app window at bottom of screen','position.b',100,aknone,bol1);
//was: low__menuitem2(a,tep__yes(vilockposition),'Lock Position','Ticked: Lock main window in place - disallow resize, disallow move | Not Ticked: Allow main window to resize and move','position.lt',100,aknone,bol1);

low__menutitle(a,tepnone,'Window','Window options');
if xallwinbuttons then
   begin
   if (state='n') then low__menuitem2(a,tepmax,'Maximise','App|Maximise app window','win.max',100,aknone,true)
   else                low__menuitem2(a,tepnor,'Normalise','App|Normalise app window','win.nor',100,aknone,true);
   end;
low__menuitem2(a,tepmin,'Minimise','App|Minimise app window','win.min',100,aknone,xallwinbuttons and (state<>'-'));
low__menuitem2(a,tepclo,'Close','App|Close app','win.clo',100,aknone,true);

//.additional
low__menutitle(a,tepnone,'Additional','');
if programnewinstance then low__menuitem2(a,tepexe20,'New App Instance','App|Launch a new instance of this app','newinstance',100,aknone,true);
low__menuitem2(a,tepFolder20,'Show App Folder','App|Show the folder which contains this app','folder',100,aknone,true);

//.finalise
low__menuend(a);

//.pop
showmenu2(self,a,'','app.menu',clnone,iaNormal,__onappmenu,xcode,xcode2);

except;end;

//free
str__free(@a);

end;

function tbasicsystem.__onappmenu(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
begin
//defaults
result:=true;//handled

try
//information
if (xcode2='about') then xshowabout
else if (xcode2='toggle.ontop') then
   begin
   syssettings.b['ontop']:=not syssettings.b['ontop'];
   viSyncandsave;
   end
else if (xcode2='toggle.touch') then//27mar2022
   begin
   syssettings.b['touch']:=not syssettings.b['touch'];
   viSyncandsave;
   end
else if (xcode2='toggle.hint') then//27dec2024
   begin
   syssettings.b['hint']:=not syssettings.b['hint'];
   viSyncandsave;
   end
else if (xcode2='toggle.realtimehelp') then//09mar2025
   begin
   syssettings.b['realtimehelp']:=not syssettings.b['realtimehelp'];
   viSyncandsave;
   end
else if (xcode2='snapshot.program') then xsnapshot//03nov2023
else if (xcode2='options') then xshowoptions
else if (xcode2='mixer') then low__showvol//06nov2022
else if (xcode2='help') then xshowhelp
else if (xcode2='defaultscale') then xdefaultscale//10dec2025
else if (xcode2='defaults') then xdefaults
//visit blaiz enterprises
else if (xcode2='be') then low__plat('portal','',true)
else if (xcode2='contact') then low__plat('contact','',true)
else if (xcode2='vintage') then low__plat('vintage','',true)
else if (xcode2='software') then low__plat('software','',true)
else if (xcode2='nprogram') then low__plat('nprogram','',true)//new program
else if (xcode2='vprogram') then low__plat('vprogram','',true)//vintage program
else if (xcode2='instagram') then low__plat('instagram','',true)
else if (xcode2='facebook') then low__plat('facebook','',true)
else if (xcode2='mastodon') then low__plat('mastodon','',true)
else if (xcode2='twitter') then low__plat('twitter','',true)
else if (xcode2='sourceforge') then low__plat('sourceforge','',true)//02dec2023
else if (xcode2='github') then low__plat('github','',true)//02dec2023
//position
else if strmatch(strcopy1(xcode2,1,9),'position.') then position(xcode2)//27feb2022
//window - 06nov2022
else if (xcode2='win.max') then
   begin
   if (state='n') then state:='+' else state:='n';
   end
else if (xcode2='win.nor') then state:='n'
else if (xcode2='win.min') then state:='-'
else if (xcode2='win.clo') then
   begin
   if mainwindow then siCloseprompt(self);//18feb2025
   end
//additional
else if (xcode2='newinstance') then low__plat('newinstance','',true)
else if (xcode2='folder') then low__plat('showroot','',true)
//not handled
else result:=false;
except;end;
end;

function tbasicsystem.monitorindex:longint;
begin
if (iform_handle<>0) then result:=monitors__findBYarea(area) else result:=monitors__primaryindex;
end;

procedure tbasicsystem.debug(yrow:longint;xtext:string);//07apr2026, 04jul2025: persists in Gamemode, 26nov2024, 01aug2024
var
   p,vcount:longint;
begin//canvas.textout//dbtext

//check
case igamemode of
true:if (paintdc=0) then exit;
end;//case

//init
yrow:=frcrange32(yrow,0,high(system_debugrows));
if (xtext<>'') then xtext:=k64(yrow)+'. '+xtext+'          ';

//get
system_debugrows[yrow]:=xtext;

//count
vcount:=0;
for p:=high(system_debugrows) downto 0 do if (system_debugrows[p]<>'') then
   begin

   vcount:=p+1;
   break;

   end;

system_debugrows_count:=vcount;

//paint
case igamemode of
true:if (paintdc<>0) then win____TextOut(paintdc,0,(yrow*vifontheight),pchar(xtext),low__len32(xtext))
else if not ipaintbusy then form__paintnow;
end;//case

end;

procedure tbasicsystem.closelock;
begin
inc(icloselocked,1);
end;

procedure tbasicsystem.closeunlock;
begin
icloselocked:=frcmin32(icloselocked-1,0);
end;

procedure tbasicsystem.xfireevent(sender:tobject;xevent:tnotifyevent);//lock close -> fireevent -> unlock close - 03apr2021
begin
try
if assigned(xevent) then
   begin
   closelock;
   try;xevent(sender);except;end;
   closeunlock;
   end;
except;end;
end;

function tbasicsystem.dragdrop_stop(var dcode2:string):boolean;
begin

if idragdrop_dragging then
   begin

   //stop
   idragdrop_dragging:=false;
   result:=true;

   //get
   dcode2:=idragdrop_code2;

   //full repaint
   paintallnow;

   end
else result:=false;

end;

function tbasicsystem.dragdrop_start(dx,dy,dw,dh:longint;const dcode2:string):boolean;
begin

result:=dragdrop_start3(dx,dy,dw,dh,dw,dh,190,nil,dcode2);

end;

function tbasicsystem.dragdrop_start2(dx,dy,dw,dh,diconw,diconh:longint;dicon:tobject;const dcode2:string):boolean;
begin
result:=dragdrop_start3(dx,dy,dw,dh,diconw,diconh,190,dicon,dcode2);
end;

function tbasicsystem.dragdrop_start3(dx,dy,dw,dh,diconw,diconh,dpower255:longint;dicon:tobject;const dcode2:string):boolean;
begin

//defaults
result:=false;

try

//check
if idragdrop_dragging or (dw<1) or (dh<1) then exit;

//range
dx    :=frcrange32(dx,0,frcmin32(iform_width-1,0));
dy    :=frcrange32(dy,0,frcmin32(iform_height-1,0));
diconw:=frcmin32(diconw,1);
diconh:=frcmin32(diconh,1);

//init
idragdrop_startarea.left    :=dx;
idragdrop_startarea.right   :=dx+dw-1;
idragdrop_startarea.top     :=dy;
idragdrop_startarea.bottom  :=dy+dh-1;
idragdrop_paintarea         :=idragdrop_startarea;
idragdrop_code2             :=dcode2;
idragdrop_ref               :='';
idragdrop_dragging          :=true;
idragdrop_power255          :=frcrange32(dpower255,0,255);

//build dragdrop icon
missize(idragdrop_icon,diconw,diconh);

case (dicon<>nil) of
true:mis__copyfast(maxarea,misarea(dicon)      ,0,0,diconw,diconh ,dicon   ,idragdrop_icon);//from supplied image
else mis__copyfast(maxarea,idragdrop_startarea ,0,0,diconw,diconh ,ibuffer ,idragdrop_icon);//from screen area
end;//case

//full repaint
paintallnow;

except;end;
end;

function tbasicsystem.dragdrop_mustpaint:boolean;
begin

result:=idragdrop_dragging and low__setstr(idragdrop_ref,intstr32(screenmovexy.x)+'x'+intstr32(screenmovexy.y)+'_'+bolstr(mousedown)+bolstr(mouseuponce));

end;

function tbasicsystem.bits:longint;
begin
result:=ibuffer.bits;//was 24;
end;

function tbasicsystem.mainwindow:boolean;
begin
result:=(system_guifirst<>nil) and (self=system_guifirst);
end;

function tbasicsystem.canposition:boolean;
begin
result:=(state='n');
end;

procedure tbasicsystem.position(xstyle:string);//18nov2024
var
   a:twinrect;
   w,h,w2,h2:longint;
begin
try
//check
if not canposition then exit;

//init
xstyle:=strlow(xstyle);
a:=monitors__workarea_auto(monitorindex);//26nov2024
h:=a.bottom-a.top+1;
w:=a.right-a.left+1;
h2:=h div 2;
w2:=w div 2;
//get
if      (xstyle='position.t') then setbounds(a.left,a.top,w,h2)
else if (xstyle='position.b') then setbounds(a.left,a.bottom-h2,w,h2)
else if (xstyle='position.l') then setbounds(a.left,a.top,w2,h)
else if (xstyle='position.r') then setbounds(a.right-w2,a.top,w2,h)
else if (xstyle='position.lt') then
   begin
   syssettings.b['lockposition']:=not syssettings.b['lockposition'];
   viSyncandsave;
   end;
except;end;
end;

function tbasicsystem.xmainwin(var xwin:tbasicscroll):boolean;
var//Note: May not always return a result
   i,p:longint;
begin
//defaults
result:=false;

try
xwin:=nil;
//find
if (winlist.count>=1) then
   begin
   for p:=0 to (winlist.count-1) do
   begin
   i:=winlist.list[p];
   if (i>=0) and (i<icorecount) and zzok(icore[i],7095) and (icore[i] is tbasicscroll) and (icore[i].winstyle=wmfullwin) and icore[i].visible then
      begin
      xwin:=icore[i] as tbasicscroll;
      result:=true;
      break;
      end;
   end;//p
   end;
except;end;
end;

procedure tbasicsystem.xsafearea;//14mar2025
var
   a:twinrect;
   b:tbasicscroll;
   sl,st,dl,dt,dw,dh,p,i,xsize,xsize0:longint;

   procedure xcheck;//updated 01feb2021
   const
      minspace=48;
   var
      xbs,dx,dy,dw,dh:longint;
      xheadok:boolean;
   begin
   //check
   if zznil(b,2290) or (b.winstyle=wmfullwin) then exit;
   //init
   dx:=b.left;
   dy:=b.top;
   dw:=b.clientwidth;
   dh:=b.clientheight;
   xheadok:=b.xhavehead and b.xhead.visible;
   xbs:=b.findbordersize;
   xsize0:=xbs+low__insint(minspace,not xheadok);
   xsize:=xbs+minspace;
   //get
   //.left
   if ((dx+dw-xsize)<a.left) then dx:=a.left-dw+xsize;
   //.right
   if ((dx+xsize)>a.right) then dx:=a.right-xsize;
   //.top
   case xheadok of
   true:if (dy<(a.top-xsize0)) then dy:=a.top-xsize0;//don't allow HEADER to vanish off top of screen
   else if ((dy+dh-xsize0)<a.top) then dy:=a.top-dh+xsize0;//HEADER is not visible/present so allow MOST of form to vanish off top of screen - 01feb2021
   end;
   //.bottom
   if ((dy+xsize)>a.bottom) then dy:=a.bottom-xsize;
   //set
   if (dx<>b.left) or (dy<>b.top) or (dw<>b.clientwidth) or (dh<>b.clientheight) then
      begin
      if b.setbounds(dx,dy,dw,dh) then b.alignnow;
      end;
   end;
begin
try
//check
if mousedown then exit;

//-- Main Screen ---------------------------------------------------------------
//Note: Main screen as a window on MS Windows
if visafearea or viretainpos then
   begin

   //init
   a:=monitors__totalworkarea;//26nov2024

   //.xsize
   if xmainwin(b) then
      begin

      xsize0:=b.findbordersize;
      xsize:=xsize0;
      if b.xhavehead and b.xhead.visible then inc(xsize,b.xhead.clientheight);

      end
   else
      begin

      xsize0:=0;
      xsize:=0;

      end;

   dl:=left;
   dt:=top;
   dw:=width;
   dh:=height;
   sl:=dl;
   st:=dt;

   //get
   //.left
   if ((dl+dw-xsize)<a.left) then dl:=a.left-dw+xsize;
   //.right
   if ((dl+xsize)>a.right)   then dl:=a.right-xsize;
   //.top
   if ((dt+xsize0)<a.top)    then dt:=a.top-xsize0;
   //.bottom
   if ((dt+xsize)>a.bottom)  then dt:=a.bottom-xsize;

   //set
   if (sl<>dl) or (st<>dt) then setbounds(dl,dt,dw,dh);
   end;

//-- All our windows -----------------------------------------------------------
//Note: Skip over "wmfullwin" they are handled automatically and
//      elsewhere by the system - 14mar2025: don't check whilst app is minimised, 28aug2020
//was: if visafearea and (winlist.count>=1) then
//Important Note: All Gossamer based windows are on screen at all times as of 27mar2021
if (winlist.count>=1) and (state<>'h') then
   begin
   a:=area__make(0,0,width-1,height-1);
   for p:=0 to (winlist.count-1) do
   begin
   i:=winlist.list[p];
   if (i>=0) and (i<icorecount) and zzok(icore[i],7096) and (icore[i] is tbasicscroll) and (icore[i].winstyle>wmfullwin) and (icore[i].winstyle<=wmMax) and icore[i].visible then
      begin
      b:=icore[i] as tbasicscroll;
      xcheck;
      end;
   end;//p
   end;

except;end;
end;

procedure tbasicsystem.xcenter(x:tbasiccontrol);
var
   dx,dy,dw,dh,cw,ch:longint;
begin
try
if zzok(x,7405) and (x is tbasicscroll) then
   begin
   //get
   cw:=width;
   ch:=height;
   dw:=frcmax32((x as tbasicscroll).clientwidth,cw);
   dh:=frcmax32((x as tbasicscroll).clientheight,ch);
   dx:=(cw-dw) div 2;
   dy:=(ch-dh) div 2;
   //set
   (x as tbasicscroll).setbounds(dx,dy,dw,dh);
   end;
except;end;
end;

procedure tbasicsystem.xshowsplash;
begin
if zzok(isplash,7098) or igamemode then exit;
isplash:=tbasicsplash.create(self);
if (isplash<>nil) then isplash.xsplash;
end;

procedure tbasicsystem.xshowabout;
begin
if zzok(isplash,7099) then exit;
isplash:=tbasicsplash.create(self);
if (isplash<>nil) then isplash.xabout;
end;

procedure tbasicsystem.xsnapshot;
begin
isnapshot64:=slowms64+500;
end;

procedure tbasicsystem.xsnapshot_make;
var
   d:tbasicimage;
   dw,dh:longint;
begin
try

d           :=nil;
dw          :=width;
dh          :=height;
d           :=misimg24(dw,dh);

mis__copyfast( maxarea ,area__make(0,0,dw-1,dh-1) ,0 ,0 ,dw ,dh ,lastbuffer ,d );

clip__copyimage(d);

popstatus('Snapshot copied to Clipboard',0);

except;end;

//free
freeobj(@d);

end;

function tbasicsystem.xshowoptions_getitem_stats(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;//17dec2024
var
   n,v,vc,vd:string;
   xcount:longint;
begin

//defaults
result:=true;

//init
xtab        :='L200;R150;R150;R150;';//28aug2025
xtep        :=tepNone;
xtepcolor   :=clnone;
xcaption    :='';//k64(xindex)+' index';
xcaplabel   :='';//k64(xindex)+' cap.label';
xflash      :=false;
xenabled    :=true;
xtitle      :=false;
xsep        :=false;
xbold       :=false;
xcode       :=0;
xshortcut   :=akNone;
xindent     :=0;

//get
track__findvalue(xindex,false,xcount,n,v,vc,vd,xtitle);
xcaplabel:=n+#9+v+#9+vc+#9+vd;

end;

function tbasicsystem.xshowoptions_getitem_snoop(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;//17dec2024
var
   v1,v2,v3,v4:string;
begin

//defaults
result:=true;

//init
xtab        :='L260;L170;R150;';//28aug2025
xtep        :=tepNone;
xtepcolor   :=clnone;
xcaption    :='';
xcaplabel   :='';
xflash      :=false;
xenabled    :=true;
xtitle      :=false;
xsep        :=false;
xbold       :=false;
xcode       :=0;
xshortcut   :=akNone;
xindent     :=0;

//get
if win__infofind(xindex,v1,v2,v3,v4,xtitle) then
   begin

   xcaplabel:=v1+#9+v2+#9+v3;

   end
else xcaplabel:='';

end;

procedure tbasicsystem.xshowoptions;//01mar2026, 06nov2025, 05may2025, 02dec2024: font+settings.vpos, 14nov2024
var
   vsp2,vsp,vsp0,dw,dh,int1,xpreviousfocus:longint;
   xpreviouscontrol:tbasiccontrol;
   xcolor,a,ca:tbasicscroll;
   b,b2:tstr8;
   xcolorscheme:tbasicmenu;
   str1:string;
   bs:longint;
   xhost0,xhost:tbasiccontrol;

   function dint3(xlabel,xname,xhelplabel,xhelpbar:string;xmin,xmax,xdef:longint;xvalname:string):tsimpleint;
   begin
   if zznil(xhost,2291) then result:=nil
   else
      begin
      result:=xhost.mint3b(xlabel,xhelplabel,xhelpbar,xmin,xmax,xdef,0,'',xvalname);
      result.tagstr:=xname;
      result.onvalue:=xshowoptions_sync;
      result.oautoreload:=true;
      end;
   end;

   function dint4b(var xout:tsimpleint;xlabel,xname,xhelplabel,xhelpbar:string;xmin,xmax,xdef:longint;xvalname:string;xvsep:longint):tsimpleint;
   begin
   result:=dint3(xlabel,xname,xhelplabel,xhelpbar,xmin,xmax,xdef,xvalname);
   result.osepv:=xvsep;
   xout:=result;
   end;

   function dback(xnameid:string):tsimpleint;
   begin
   result:=ibackgroundmanager.mint(xhost,xnameid);
   result.osepv:=7*vizoom;
   end;

   function dint3b(var xout:tsimpleint;xlabel,xname,xhelplabel,xhelpbar:string;xmin,xmax,xdef:longint;xvalname:string):tsimpleint;
   begin
   result:=dint4b(xout,xlabel,xname,xhelplabel,xhelpbar,xmin,xmax,xdef,xvalname,0);
   end;

   function dset(xlabel,xname,xhelp:string;xdef:longint):tbasicset;
   begin
   if zznil(xhost,2292) then result:=nil
   else
      begin
      result:=xhost.nset(xlabel,xhelp,xdef,0);
      result.tagstr:=xname;
      result.onvalue:=xshowoptions_sync;
      result.oautoreload:=true;
      end;
   end;

   function dsel3(xlabel,xname,xhelp:string;xdef:longint;xvalname:string):tbasicsel;
   begin
   if zznil(xhost,2293) then result:=nil
   else
      begin
      result:=xhost.nsel3(xlabel,xhelp,xdef,xvalname);
      result.tagstr:=xname;
      result.onvalue:=xshowoptions_sync;
      result.oautoreload:=true;
      end;
   end;

   function dcols2:tbasiccols;
   begin
   if zznil(xhost,2293) then result:=nil
   else
      begin
      result:=xhost.ncols;
      result.makeautoheight;
      end;
   end;

   function cursor_builtin_hint(xmore:string):string;
   begin
   result:='Built in Cursor | A built-in, static, scalable mouse pointer in '+xmore;
   end;
begin
try
//defaults
a:=nil;
b:=nil;
b2:=nil;
xpreviousfocus:=winfocus;
xpreviouscontrol:=focuscontrol;
xhost:=nil;

//check
if ishowoptions_inuse then exit else ishowoptions_inuse:=true;

//init
vsp                    :=10*vizoom;
vsp0                   :=vsp;
vsp2                   :=2*vizoom;
ishowoptions_timer100  :=slowms64;
ishowoptions_timer500  :=slowms64;

//get
gui__scale3(800,750,580,350,dw,dh);

bs                     :=vibordersize;
a                      :=ndlg2(area__make(0,0,dw+(2*bs),dh+(2*bs)),true,true);
a.ontimer2             :=xshowoptions_timer;
a.xhead.caption        :=ntranslate('Options');

ishowoptions_maintoolbar:=a.xhead;

a.xgrad;
a.xtoolbar2.add(ntranslate('Restore Defaults...'),tepRefresh20,2,'defaults',rthtranslate('Restore default settings | Click to restore defaults, or press the "F2" key'));
a.xtoolbar2.cadd(ntranslate('OK'),tepYes20,1,scdlg,rthtranslate('Close window'),low__aorb(60*5,system_onshowoptionsCLOSEDELAY,system_onshowoptionsCLOSEDELAY>=1));//12nov2022

//.host system > open - 06nov2022
if assigned(system_onshowoptions1) then system_onshowoptions1(a);


//color ------------------------------------------------------------------------
ishowoptions_maintoolbar.add('Menu',tepMenu20,3,'options.menu',rthtranslate('Color|Show color menu'));
ishowoptions_maintoolbar.benabled2['options.menu']:=false;

xcolor                 :=a.xpage1('color','Color','Color|View and edit color schemes',tepColor20,true);
xcolor.xcols.style     :=bcLefttoright;

//add('Darken',tepLess20,3,'options.darken',rthtranslate('Darken color scheme colors'));//18sep2022
//add('Brighten',tepMore20,3,'options.brighten',rthtranslate('Brighten color scheme colors'));//18sep2022

//.color schemes list
with xcolor.xcols.cols2[0,50,false] do
begin
xhost:=client;
//.colorname.top
xcolorscheme:=nlist3('','Select color scheme',nil,8,'colorname');//read/write via system var.name of "colorname" - 09oct2020
xcolorscheme.tagstr:='colorname';
ishowoptions_list:=xcolorscheme;
ishowoptions_list.onshowmenu:=xshowoptions_showmenu;//11oct2020
ishowoptions_list.ocanshowmenu:=true;//26mar2021
ishowoptions_list.onumberfrom:=1;
//was: xshowoptions_reload;
end;//end-color

//.colorname.bottom
with xcolor.xcols.cols2[1,50,true] do
begin
ishowoptions_colors:=ncolors;
ishowoptions_colors.makesystem;
end;
xcolor.xcols.vis[1]:=false;
ishowoptions_cols:=xcolor.xcols;
xhost:=xcolor.xhigh2.client;


//background -------------------------------------------------------------------
with a.xpage1('background','Background','Background|View and edit background schemes',tepBackground20,true) do
begin
xhost:=client;
ishowoptions_backs_cols:=xcols;

//.left column
with xcols.cols2[0,50,false] do
begin
xhost:=client;

ishowoptions_backs:=nlist3('','Select background',nil,0,'backname');//read/write via system var.name of "colorname" - 09oct2020
ishowoptions_backs.tagstr:='backname';
ishowoptions_backs.onumberfrom:=0;

end;

//.right column
ishowoptions_backgroundpanel:=xcols.cols2[1,50,true];
with ishowoptions_backgroundpanel do
begin
xhost:=client;

ishowoptions_toolbar_background:=xtoolbar;
ishowoptions_toolbar_background.visible:=false;

with ishowoptions_toolbar_background do
begin
add('File',tepOpen20,3,'options.backfile',rthtranslate('Custom Background | Select a custom background image from disk and apply'));
add('Paste',tepPaste20,3,'options.backpaste',rthtranslate('Custom Background | Paste a custom background image from Clipboard and apply'));
add('Clear',tepClose20,3,'options.backclear',rthtranslate('Custom Background | Clear custom background image and apply'));
onclick:=xshowoptions_sync;
end;

dback('strength');
dback('colorise');
dback('speed');
dback('hstep');
dback('hwobble');
dback('vstep');
dback('vwobble');
dback('fstep');
dback('fwobble');
dback('crate');

end;

//sync panel (sliders) - 01mar2026
ibackgroundmanager.sync_panel(ishowoptions_backgroundpanel);

end;


//frame ------------------------------------------------------------------------
with a.xpage1('frame','Frame','Frame|View and adjust frame styles',tepFrame20,true) do
begin
xhost:=client;
//ntitle(false,'Frame Styles','Frame Styles');

ishowoptions_frames:=nlist3('','Select frame',nil,0,'framename');//read/write via system var.name of "colorname" - 09oct2020
ishowoptions_frames.tagstr:='framename';
ishowoptions_frames.onumberfrom:=0;

with xhigh2 do
begin
xhost:=client;
dint3b(ishowoptions_sparkle1,'Sparkle','sparkle','','Adjust Sparkle',0,20,strint32(app__info('sparkle')),'sparkle').osepv:=5*vizoom;
dint3b(ishowoptions_framesize1,'Size','bordersize','','Adjust Frame Size',0,72,strint32(app__info('bordersize')),'bordersize');
end;

end;


//font -------------------------------------------------------------------------
ishowoptions_font:=a.xpage1('font','Font','Font|Adjust font settings and behaviour',tepFont20,false);
ishowoptions_font.ofirstpos:=ishowoptions_font_vpos;

with ishowoptions_font do
begin
xhost:=client;

with dsel3('Font Size','fontsize','',0,'fontsize') do
begin

osepv        :=vsp;
itemsperline :=5;

xadd('6','6','6pt');
xadd('7','7','7pt');
xadd('8','8','8pt');
xadd('9','9','9pt');
xadd('10','10','10pt');
xadd('11','11','11pt');
xadd('12','12','12pt');
xadd('14','14','14pt');
xadd('16','16','16pt');
xadd('22','22','22pt');
xadd('24','24','24pt');

reload;
ospbackname:='green';

end;

with dsel3('Font Name','fontname','',0,'fontnameraw') do
begin
osepv:=vsp;
itemsperline:=4;
str1:='Select font name';
xadd('Arial','Arial',str1);
xadd('MS Sans Serif','MS Sans Serif',str1);
xadd('Times New Roman','Times New Roman',str1);
xadd('Courier New','Courier New',str1);
xadd('System','System',str1);
xadd('Segoe UI','Segoe UI',str1);
xadd('Tahoma','Tahoma',str1);
xadd('Verdana','Verdana',str1);
xadd('@MS Gothic','@MS Gothic',str1);
xadd('DejaVu Sans','DejaVu Sans',str1);
xadd('DejaVu Serif','DejaVu Serif',str1);
xadd('Consolas','Consolas',str1);//11dec2025
xadd('Lucida Console','Lucida Console',str1);//11dec2025

xadd('Custom','*','Select once to use custom font.  Select again to choose font from list of available fonts');
reload;
ospbackname:='green';
onclick:=xshowoptions_click;
end;

with dsel3('Font Feathering','fontfeather','',0,'fontfeather') do
begin

osepv                 :=vsp;
xadd('Off','0','No font feathering');
xadd('Low','1','Subtle font feathering');
xadd('Medium','2','Additional font feathering');
xadd('High','3','Significant font feathering');
xadd('Ultra','4','Extreme font feathering');
reload;
ospbackname           :='yellow';

end;

with dsel3('Font Name 2 - Text Entry','fontname2','',0,'fontnameraw2') do
begin
osepv:=vsp;
itemsperline:=4;//28feb2026
str1:='Select font name';
xadd('Arial','Arial',str1);
xadd('MS Sans Serif','MS Sans Serif',str1);
xadd('Times New Roman','Times New Roman',str1);
xadd('Courier New','Courier New',str1);
xadd('System','System',str1);
xadd('Segoe UI','Segoe UI',str1);
xadd('Tahoma','Tahoma',str1);
xadd('Verdana','Verdana',str1);
xadd('@MS Gothic','@MS Gothic',str1);
xadd('DejaVu Sans','DejaVu Sans',str1);
xadd('DejaVu Serif','DejaVu Serif',str1);
xadd('Consolas','Consolas',str1);//11dec2025
xadd('Lucida Console','Lucida Console',str1);//11dec2025
xadd('Custom','*',str1);
reload;
ospbackname:='blue';
visible:=strbol(app__info('font2.use'));//11dec2024, 04dec2024
onclick:=xshowoptions_click;
end;

with dsel3('Font Size 2 - Text Entry','fontsize2','',0,'fontsize2') do//26feb2022
begin
osepv:=vsp;
itemsperline:=5;
xadd('6','6','6pt');
xadd('7','7','7pt');//06nov2025
xadd('8','8','8pt');
xadd('9','9','9pt');
xadd('10','10','10pt');
xadd('11','11','11pt');
xadd('12','12','12pt');
xadd('14','14','14pt');
xadd('16','16','16pt');
xadd('22','22','22pt');
xadd('24','24','24pt');
reload;
ospbackname:='blue';
visible:=strbol(app__info('font2.use'));//11dec2024, 04dec2024
end;

end;//end-font


//settings ---------------------------------------------------------------------
ishowoptions_settings:=a.xpage1('settings','Settings','Settings|Adjust app settings',tepSettings20,false);
ishowoptions_settings.ofirstpos:=ishowoptions_settings_vpos;

with ishowoptions_settings do
begin
xhost:=client;


//app links
with dset('App Links','','',0) do//10dec2025
begin

osepv        :=vsp;
ospbackname :='red';

xset3(0,'Start button link','startlink','App Link | Create and maintain a link to this app on your Start button/menu | Un-select to remove the link',false,'startlink');
xset3(1,'Desktop link','desktoplink','App Link | Create and maintain a link to this app on your Desktop | Un-select to remove the link',false,'desktoplink');
xset3(2,'Automatic Startup link','startuplink','App Link | Create and maintain a link to automatically start the app | Un-select to remove the link',false,'startuplink');

end;


//start style
with dsel3('Start Style','startstyle','',0,'startstyle') do
begin
osepv:=vsp;
itemsperline:=4;
xadd('Normal','0','Start Style | Start app normally (as a window - default)');
xadd('Minimised','1','Start Style | Start app minimised (hidden from view)');
xadd('Maximised','2','Start Style | Start app maximised (expand to use most of screen)');
xadd('Fullscreen','3','Start Style | Start app fullscreen');
reload;
ospbackname:='green';
end;

//scale mode - 10dec2025
with dsel3('Scale','scalemode','Scale|Set app scale',0,'scalemode') do
begin
itemsperline :=scale__modecount;
osepv        :=vsp;

for int1:=0 to pred(scale__modecount) do
begin

xadd( scale__modelabel(int1) ,intstr32(int1), scale__modehelp(int1) );

end;//int1

ovalueclick  :=true;
ospbackname  :='yellow';
reload;

end;


//display
ishowoptions_options:=dset('Display','','',0);
with ishowoptions_options do
begin
osepv:=vsp;
itemsperline:=5;

xset3(0,'Show Splash','splash','Display | Display an artistic splash screen on app start',false,'splash');
xset3(1,'Round Corners','round','Display | Round corners for windows and controls',false,'round');
xset3(2,'Monochromatic Images','modern','Display | Use high-contrast, color-adaptive, monochromatic images',false,'modern');//12feb2022
xset3(3,'Soft Close','softclose','Display | Click outside dialog window to close',false,'softclose');
xset3(4,'Safe Area','safearea','Display | Ensure main app window is always visible on screen',false,'safearea');//Main window option as of 27mar2021

xset3(5,'Multi-Monitor','multimonitor','Display | Span multiple monitors when maximised or in fullscreen mode',false,'multimonitor');
xset3(6,'Hints','hint','Display | Display an information popup bubble for the current control',false,'hint');
xset3(7,'Realtime Help','realtimehelp','Display | Scroll help information across the top of the current window or menu',false,'help');
xset3(8,'Double Clicks','doubleclicks','Display | Use traditional double clicks and taps',false,'doubleclicks');
xset3(9,'Touch','touch','Display | Enlarge controls that are unconfortably small for touch access',false,'touch');
xset3(10,'Economy','ecomode','Display | Reduce paint cycles and CPU usage during long periods of idleness | 2 fps when idle for 10min+ | 1 fps when idle for 30min+',false,'ecomode');

xset3(11,'On Top','ontop','Display | Set the app above all other windows',false,'ontop');

xset3(12,'Emboss Text','emboss','Emboss Text | Emboss important GUI text.  Text appears clearer over a larger range of background colors and shades, making it easier to read.',false,'emboss');
xset3(13,'Color Contrast','specialcolors','Color Contrast | Color contrast important settings and input areas',false,'specialcolors');
xset3(14,'Center Title','headcenter','Window Title | Center name in window header',false,'headcenter');//11oct2022

xset3(15,'Frame Maximised','framemax','Display | Show app frame when maximised | The frame is always hidden during fullscreen mode',false,'framemax');
xset3(16,'Safe Background','safestrength','Safe Background Strength|Limit how much the background image can show through',false,'safestrength');
xset3(17,'32bit Graphics','32bit','Display | 32bit graphics is standard for best performance | Un-select to cater for old computers',false,'32bit');//12feb2022

xset3(18,'Retain Pos / Size','retainpos','Retain Pos / Size|Window position and size for next start',false,'retainpos');


//was: too dangerous to implement: xset3(13,'Lock Position','lockposition','Selected: Lock main window in place - disallow resize, disallow move | Not Selected: Allow main window to resize and move',false,'lockposition');
ospbackname:='green';
end;


//debugging only - 11dec2025 ---------------------------------------------------
{
xhost0:=xhost;
dcols2.osepv:=vsp;

with dcols2 do
begin

xhost:=cols2[0,33,false].client;
xhost.mint('mint','',0,100,0,0).ospbackname:='green';

xhost:=cols2[1,33,false].client;
with xhost.nset('nset','',0,0) do
begin
ospbackname:='green';
itemsperline:=3;
xset(0,'1','1','',true);
xset(1,'2','2','',true);
xset(2,'3','3','',true);
end;

xhost:=cols2[2,33,false].client;
with xhost.nsel('nsel','',0) do
begin
ospbackname:='green';
itemsperline:=5;
xadd('1','','');
xadd('2','','');
xadd('3','','');
xadd('4','','');
xadd('5','','');

end;

end;//with

//.revert
xhost:=xhost0;
}
//end of debugging -------------------------------------------------------------



//brightness and toolbar alignment
xhost0:=xhost;
dcols2.osepv:=vsp;
with dcols2 do
begin

xhost:=cols2[0,50,false].client;

with dint3b(ishowoptions_brightness3,'Brightness','brightness','','Brightness | Adjust brightness from 60 (darker) to 130 (brighter)',60,130,100,'brightness') do
begin
ospbackname:='green';
end;

xhost:=cols2[1,50,false].client;

with dsel3('Toolbar Alignment','headalign','Window toolbar alignment',0,'headalign') do
begin

itemsperline:=3;

xadd('Left','0','Window Toolbar | Left align toolbar links');
xadd('Center','1','Window Toolbar | Center toolbar links');
xadd('Right','2','Window Toolbar | Right align toolbar links');

ovalueclick:=true;
ospbackname:='green';
reload;

end;

end;//with

//.revert
xhost:=xhost0;


//cursor
with dsel3('Cursor','cursorname','',0,'cursorname') do
begin
osepv:=vsp;
itemsperline:=5;
xadd('Default','default','Cursor | Use the default mouse pointer');
xadd('Adaptive - Hover','!hover','Adaptive Cursor | A mouse pointer that color harmonises to the app''s color scheme');
xadd('Adaptive - Title','!title','Adaptive Cursor | A mouse pointer that color harmonises to the app''s color scheme');
xadd('Red','red',cursor_builtin_hint('red'));
xadd('Orange','orange',cursor_builtin_hint('orange'));
xadd('Pink','pink',cursor_builtin_hint('pink'));
xadd('Yellow','yellow',cursor_builtin_hint('yellow'));
xadd('Purple','purple',cursor_builtin_hint('purple'));
xadd('Aqua','aqua',cursor_builtin_hint('aqua'));
xadd('Blue','blue',cursor_builtin_hint('blue'));
xadd('Green','green',cursor_builtin_hint('green'));
xadd('Grey','grey',cursor_builtin_hint('grey'));
xadd('Black','black',cursor_builtin_hint('black'));
xadd('White','white',cursor_builtin_hint('white'));
xadd('Custom','custom','Custom Cursor | User definable mouse pointer. Select to use, and select again to choose a new cursor.');
reload;
ovalueclick:=true;
ospbackname:='blue';
end;


//show opacity controllers when OS supports it
if app__cansetwindowalpha then
   begin
   xhost0:=xhost;

   dcols2.osepv:=vsp;
   with dcols2 do
   begin

   xhost:=makecol(0,50,false).client;
   with dint3b(ishowoptions_unfocusedopacity1,'Unfocused Opacity','unfocusedopacity','','Unfocused Opacity | Set app opacity when not focused 30-255 | 30=App mostly transparent | 255=App fully opaque (completely visible)',30,255,strint32(app__info('unfocused.opacity')),'unfocusedopacity') do
   begin
   osepv:=vsp2;
   ospbackname:='green';
   end;

   xhost:=makecol(1,42,false).client;
   with dint3b(ishowoptions_opacityspeed1,'Speed','opacityspeed','','Opacity Transition Speed | The speed by which to switch opacity between focused and unfocused | Speed range 1-10 | 1=Slowest | 10=Fastest',1,10,strint32(app__info('opacity.speed')),'opacityspeed') do
   begin
   osepv:=vsp2;
   ospbackname:='green';
   end;

   xhost:=makecol(2,50,false).client;
   with dint3b(ishowoptions_focusedopacity1,'Focused Opacity','focusedopacity','','Focused Opacity | Set app opacity when focused 50-255 | 50=App semi-transparent | 255=App fully opaque (completely visible)',50,255,strint32(app__info('focused.opacity')),'focusedopacity') do
   begin
   osepv:=vsp2;
   ospbackname:='green';
   end;

   end;//cols2

   //revert
   xhost:=xhost0;
   end;//if



xhost0:=xhost;
dcols2.osepv:=vsp;
with dcols2 do
begin

xhost:=makecol(0,50,false).client;
with dint3b(ishowoptions_framesize2,'Frame Size','bordersize','','Frame Size | The app''s frame size can be adjust from 0 (none) to 72 (large)',0,72,strint32(app__info('bordersize')),'bordersize') do
begin
ospbackname:='green';
end;

xhost:=makecol(1,42,false).client;
with dint3b(ishowoptions_sparkle2,'Frame Sparkle','sparkle','','Frame Sparkle | Set the intensity of the random texture in the frame and window header | A range of 0 (off) to 20 (intense) is supported',0,20,strint32(app__info('sparkle')),'sparkle') do
begin
ospbackname:='green';
end;

xhost:=makecol(2,50,false).client;
with dint3('Scrollbar Size','scrollsize','','Scrollbar Size | Set the width or height of all scrollbars | Supports a range of 5 (thin/short) to 72 (wide/tall)',5,72,20,'scrollsize') do
begin
ospbackname:='green';
end;

end;//cols2
xhost:=xhost0;//revert


//.wine options -> not supported for Store Apps - 10dec2025, 30mar2022
if not system_msix then
   begin

   with dsel3('','winemode','Wine Compatibility | Allows for some operations to be specifically tweaked for operation on Linux and Mac. | '+'One such operation is volume handling. | For more information on Wine refer to their website https://www.winehq.org | '+'Detection of Wine is based on the presence of drive "Z:\".',0,'winemode') do
   begin

   xsyncwinestatus;

   owinedevice :=true;
   osepv       :=vsp;
   tep         :=tepWine20;

   xadd('Automatic','0','Wine Compatibility | Automatically detect and engage Wine support');
   xadd('Enable','1','Wine Compatibility | Forceably engage Wine support');
   xadd('Disable','2','Wine Compatibility | Disable Wine support');

   reload;
   ospbackname :='red';

   end;

   end;

end;//end-settings


//stats ------------------------------------------------------------------------
ishowoptions_stats:=a.xpage1('stats','Stats','Stats|View realtime codebase statistics',tepScreen20,true);

with ishowoptions_stats do
begin

xhost:=client;
int1:=track__findvalue_count;
ishowoptions_statslist                 :=nlistx('','Statistics',int1,int1,xshowoptions_getitem_stats);
ishowoptions_statslist.makepanel;
ishowoptions_statslist.itemindex       :=ishowoptions_stats_vpos2;
ishowoptions_statslist.pos             :=ishowoptions_stats_vpos;

end;//end-stats

//stats ------------------------------------------------------------------------
ishowoptions_snoop:=a.xpage1('snoop','Snoop','Snoop|View realtime Win32 API status and usage',tepzoom20,true);

with ishowoptions_snoop do
begin

xhost:=client;
int1:=win__infocount;
ishowoptions_snooplist                 :=nlistx('','Snoop Information',int1,int1,xshowoptions_getitem_snoop);
ishowoptions_snooplist.makepanel;
ishowoptions_snooplist.itemindex       :=ishowoptions_snoop_vpos2;
ishowoptions_snooplist.pos             :=ishowoptions_snoop_vpos;
end;//end-stats






//reload
xshowoptions_reload;

//events
ishowoptions_frames.onclick:=xshowoptions_sync;
ishowoptions_backs.onclick:=xshowoptions_sync;
xcolorscheme.onclick:=xshowoptions_sync;

a.xhead.onclick:=xshowoptions_sync;
a.xhead.oclickthru:=true;

a.xtoolbar2.onclick:=xshowoptions_sync;
//set
a.page:=strdefb(system_options_str1,strdefb(system_onshowoptionsINITPAGENAME,xcolor.opagename));//fixed - 29may2021
xcolor.ofirstpos:=system_options_pos1;
ishowoptions_window:=a;
xcenter(a);
xshowwait(a,xpreviouscontrol,xpreviousfocus);
system_options_str1:=a.page;
system_options_pos1:=xcolor.pos;

//.host system > close - 06nov2022
if assigned(system_onshowoptions2) then system_onshowoptions2(a);

//sync
viSyncandsave;
except;end;
try
//.vpos history

ishowoptions_font_vpos     :=ishowoptions_font.pos;
ishowoptions_settings_vpos :=ishowoptions_settings.pos;

ishowoptions_stats_vpos    :=ishowoptions_statslist.pos;
ishowoptions_stats_vpos2   :=ishowoptions_statslist.itemindex;

ishowoptions_snoop_vpos    :=ishowoptions_snooplist.pos;//24oct2025
ishowoptions_snoop_vpos2   :=ishowoptions_snooplist.itemindex;

//.reset control pointers
ishowoptions_toolbar_background:=nil;//22jul2024
ishowoptions_window:=nil;
ishowoptions_frames:=nil;
ishowoptions_backs:=nil;
ishowoptions_backgroundpanel:=nil;
ishowoptions_backs_cols:=nil;
ishowoptions_statslist:=nil;
ishowoptions_snooplist:=nil;
ishowoptions_list:=nil;
ishowoptions_cols:=nil;
ishowoptions_colors:=nil;
ishowoptions_options:=nil;
ishowoptions_font:=nil;
ishowoptions_settings:=nil;
ishowoptions_stats:=nil;
ishowoptions_snoop:=nil;
ishowoptions_framesize1:=nil;
ishowoptions_framesize2:=nil;
ishowoptions_sparkle1:=nil;
ishowoptions_sparkle2:=nil;
ishowoptions_brightness3:=nil;
ishowoptions_focusedopacity1:=nil;
ishowoptions_unfocusedopacity1:=nil;
ishowoptions_opacityspeed1:=nil;
ishowoptions_crosssync:=false;
freeobj(@a);
freeobj(@b);
except;end;
try;ishowoptions_inuse:=false;except;end;
end;

procedure tbasicsystem.xshowoptions_reload;
var
   a,b:tstr8;
   c:tdynamicstring;
   str1,xname,xlabel,xhelp:string;
   xsize:comp;
   bcount,xcurrentTEP,xstyle,xtep,p:longint;
   xincludeQuerymark:boolean;

   procedure baddtitle(xcap:string);
   begin
   low__menutitle(b,tepNone,xcap,'');
   inc(bcount);
   end;

   procedure badd2(xcap,xname:string);
   begin
   low__menuitem(b,xcurrentTEP,xcap,xhelp,xname,100,true);
   inc(bcount);
   end;

   procedure badd(xcap,xname:string);
   begin
   badd2(xcap,insstr('?',xincludeQuerymark)+xname);
   end;

   procedure xadd(xcap:string);
   begin
   badd2(xcap,insstr('?',xincludeQuerymark)+xcap);
   end;

   procedure xadd3(xcap:string);
   begin
   c.value[c.count]:=xcap;
   end;

   procedure xaddall3(xsort:boolean);
   var
      p:longint;
   begin
   if xsort then c.sort(true);
   if (c.count>=1) then
      begin
      for p:=0 to (c.count-1) do xadd(c.svalue[p]);
      end;
   end;
begin
try
//defaults
a:=nil;
b:=nil;
c:=nil;
//init
a:=str__new8;
b:=str__new8;
c:=tdynamicstring.create;
bcount:=0;

//-- color ---------------------------------------------------------------------
//init
a.clear;
b.clear;
c.clear;
xincludeQuerymark:=true;
xhelp:='Select color scheme';
xcurrentTEP:=tepColor20;
low__menuinit(b);
//internal
baddtitle('Built-In');
if (ishowoptions_list<>nil) then ishowoptions_list.onumberfrom:=bcount;
xadd('Default');

//color schemes
for p:=0 to max32 do if sicolors_name(p,str1) then xadd3(str1) else break;

{
xadd3('Army');
xadd3('Army 2');
xadd3('Burnt Yellow');//11oct2022
xadd3('Burnt Yellow 2');
xadd3('Burnt Yellow 3');
xadd3('Burnt Red');//11oct2022
xadd3('Burnt Red 2');
xadd3('Burnt Red 3');
xadd3('Burnt Purple');//11oct2022
xadd3('Burnt Purple 2');
xadd3('Burnt Purple 3');
xadd3('Burnt Orange');//11oct2022
xadd3('Burnt Orange 2');
xadd3('Burnt Orange 3');
xadd3('Eerie');//11oct2022
xadd3('Eerie 2');
xadd3('Eerie 3');
xadd3('Soft Green');
xadd3('Soft Green 2');
xadd3('Soft Green 3');
xadd3('Soft Green 4');
xadd3('Aqua Marine');
xadd3('Aqua Marine 2');
xadd3('Aqua Marine 3');
xadd3('Fine Grey');
xadd3('Marine');
xadd3('Marine 2');
xadd3('Marine 3');
xadd3('Marine 4');
xadd3('Lilac');
xadd3('Lilac 2');
xadd3('Lilac 3');
xadd3('Gold');
xadd3('Gold 2');
xadd3('Gold 3');
xadd3('Gold 4');
xadd3('Silver Gold');
xadd3('Silver Gold 2');
xadd3('Grey');
xadd3('Grey 2');
xadd3('Grey 3');
xadd3('Grey 4');
xadd3('Grey 5');
xadd3('Grey 6');
xadd3('Soft Blue');
xadd3('Soft Blue 2');
xadd3('Soft Blue 3');
xadd3('Soft Blue 4');
xadd3('Soft Blue 5');//14nov2022
xadd3('Emerald');
xadd3('Emerald 2');
xadd3('Emerald 3');
xadd3('Washed Crimson');
xadd3('Dusty Pink');
xadd3('Dusty Pink 2');
xadd3('Dusty Pink 3');
xadd3('Golden Sands');
xadd3('Golden Sands 2');
xadd3('Golden Sands 3');
xadd3('Fern');
xadd3('Fern 2');
xadd3('Tangerine');
xadd3('Tangerine 2');
xadd3('Tangerine 3');
xadd3('Barely Beige');
xadd3('Barely Beige 2');
xadd3('Moon Blue');
xadd3('Moon Blue 2');
xadd3('Moon Blue 3');
xadd3('Moon Blue 4');
xadd3('Moon Blue 5');
xadd3('Howdy Brown');
xadd3('Howdy Brown 2');
xadd3('Howdy Brown 3');
xadd3('Chirpy Charcoal');
xadd3('Chirpy Charcoal 2');
xadd3('Dark Red Tint');//02may2022
xadd3('Dark Green Tint');//02may2022
xadd3('Dark Blue Tint');//02may2022
xadd3('Dark Yellow Tint');//02may2022
xadd3('Dark Aqua Tint');//02may2022
xadd3('Dreamy Cream');
xadd3('Dreamy Cream 2');
xadd3('Dreamy Cream 3');
xadd3('Gentle Ginger');
xadd3('Grumpy Green');
xadd3('Grumpy Green 2');
xadd3('Grumpy Green 3');
xadd3('Grumpy Green 4');
xadd3('Glowing Grey');
xadd3('Glowing Grey 2');
xadd3('Glowing Grey 3');
xadd3('Glowing Grey 4');
xadd3('Jovial Mauve');
xadd3('Jovial Mauve 2');
xadd3('Jovial Mauve 3');
xadd3('Luscious Lilac');
xadd3('Slinky Pink');
xadd3('Slinky Pink 2');
xadd3('Slinky Pink 3');
xadd3('Rosebud Pink');
xadd3('Rosebud Pink 2');
xadd3('Silky Sand');
xadd3('Silky Sand 2');
xadd3('Silky Sand 3');
xadd3('Silky Sand 4');
xadd3('Really Red');
xadd3('Really Red 2');
xadd3('Really Red 3');
xadd3('Robust Red');
xadd3('Robust Red 2');
xadd3('Robust Red 3');
xadd3('Red');
xadd3('Red 2');
xadd3('Red 3');
xadd3('Red 4');
xadd3('Red 5');
xadd3('Red 6');
xadd3('Peach');
xadd3('Peach 2');
xadd3('Peach 3');
xadd3('Radiant Yellow');
xadd3('Radiant Yellow 2');
xadd3('Tangy Tangerine');
xadd3('Tangy Tangerine 2');
xadd3('Tangy Tangerine 3');

xadd3('Wild Thing');
xadd3('Wild Thing Pastel');

xadd3('Black');
xadd3('Black 2');
xadd3('Black 3');//03nov2023
xadd3('Black 4');//03nov2023
xadd3('White');
xadd3('White 2');
xadd3('White and Pale');

//xadd3('White 3');//20jul2024
xadd3('Blue');
xadd3('Blue 2');
xadd3('Blue 3');
xadd3('Blue 4');
xadd3('Blue 5');
xadd3('Blue 6');
xadd3('Royal Blue');
xadd3('Royal Blue 2');
xadd3('Royal Blue 3');
xadd3('Royal Blue 4');
xadd3('Royal Blue 5');
xadd3('Pink');
xadd3('Pink 2');
xadd3('Satin Pink');//15mar2022
xadd3('Satin Pink 2');//15mar2022
xadd3('Satin Pink 3');//15mar2022
xadd3('Satin Pink 4');//15mar2022
xadd3('Wild Mix');
//.purple - 07jun2022
xadd3('Purple');
xadd3('Purple 2');
xadd3('Purple 3');
xadd3('Purple 4');
xadd3('Purple 5');
xadd3('Purple 6');
xadd3('Purple 7');
xadd3('Purple 8');
xadd3('Purple 9');
//.brown - 12jun2022
xadd3('Brown');
xadd3('Brown 2');
xadd3('Brown 3');
xadd3('Brown 4');
xadd3('Brown 5');
xadd3('Brown 6');//21jun2022
xadd3('Brown 7');//21jun2022
xadd3('Brown 8');//21jun2022
xadd3('Brown 9');//21jun2022
}

//.finialise
xaddall3(true);
badd('Paste and Use','paste_and_use');//02aug2024: new label, 27mar2022

//custom
baddtitle('Custom');
if (ishowoptions_list<>nil) then ishowoptions_list.onumberfrom2:=bcount;
for p:=0 to (cnCustomLimit-1) do badd('Custom '+intstr32(1+p),'custom'+intstr32(p));
//files
baddtitle('Saved');
if (ishowoptions_list<>nil) then ishowoptions_list.onumberfrom3:=bcount;
nav__list(a,nlName,low__platfolder('schemes'),'*.'+cnFileEXT,'',false,false,true);
for p:=0 to max32 do
begin
case nav__get(a,p,xstyle,xtep,xsize,xname,xlabel) of
true:begin
   xname:=io__remlastext(xname);
   if (xname<>'') then badd2(xname,xname);//exclude ".bcs" as this is "<nil>" when extension is stripped which is same as default color scheme - 13apr2021
   end;
else break;
end;
end;//p

//finalise
low__menuend(b);
//set
if zzok(ishowoptions_list,7100) then
   begin
   ishowoptions_list.data:=b;
   if (ishowoptions_list.oloadfromname<>'') then ishowoptions_list.reload;
   end;


//backgrounds ------------------------------------------------------------------
if (ishowoptions_backs<>nil) and (ishowoptions_backs.data.len<=0) then
   begin

   //init
   bcount             :=0;
   a.clear;
   b.clear;
   c.clear;
   xincludeQuerymark  :=false;
   xcurrentTEP        :=tepBackground20;
   xhelp              :='Select background';
   low__menuinit(b);

   //internal
   baddtitle('Built-In');
   ishowoptions_backs.onumberfrom:=bcount;
   xadd('Default');
   xadd('None');

   //.built-in
   if (backgroundmanager.count>=1) then
      begin

      for p:=0 to (ibackgroundmanager.count-1) do if (not ibackgroundmanager.iscustom(p)) and (not strmatch(ibackgroundmanager.name[p],'none')) and (not strmatch(ibackgroundmanager.name[p],'default')) then xadd3(ibackgroundmanager.name[p]);

      end;

   xaddall3(true);

   //.custom
   if (ibackgroundmanager.count>=1) then
      begin

      baddtitle('Custom');
      ishowoptions_backs.onumberfrom2:=bcount;

      for p:=0 to (ibackgroundmanager.count-1) do if ibackgroundmanager.iscustom(p) then badd(ibackgroundmanager.name[p],ibackgroundmanager.name[p]);

      end;

   //finalise
   low__menuend(b);

   //set
   ishowoptions_backs.data:=b;

   end;

if (ishowoptions_backs<>nil) and (ishowoptions_backs.oloadfromname<>'') then ishowoptions_backs.reload;

if (ishowoptions_backs<>nil) and (ishowoptions_backs_cols<>nil) then
   begin

   ishowoptions_backs_cols.vis[1]:=(ibackgroundmanager<>nil) and ibackgroundmanager.canadjust;

   end;


//frames -----------------------------------------------------------------------
if (ishowoptions_frames<>nil) and (ishowoptions_frames.data.len<=0) then
   begin
   //init
   a.clear;
   b.clear;
   c.clear;
   xincludeQuerymark:=false;
   xcurrentTEP:=tepFrame20;
   xhelp:='Select frame';
   low__menuinit(b);
   //internal
   xadd('Default');
   if (system_framecount>=1) then
      begin
      for p:=0 to (system_framecount-1) do xadd3(system_framename[p]);
      end;
   xaddall3(true);

   //finalise
   low__menuend(b);
   //set
   ishowoptions_frames.data:=b;
   end;

if (ishowoptions_frames<>nil) and (ishowoptions_frames.oloadfromname<>'') then ishowoptions_frames.reload;

except;end;
try
str__free(@a);
str__free(@b);
freeobj(@c);
except;end;
end;

procedure tbasicsystem.xshowoptions_timer(sender:tobject);
var
   bol1,bol2:boolean;
begin
try

//timer100
if (slowms64>=ishowoptions_timer100) then
   begin
   //get
   if zzok(ishowoptions_cols,7101) then ishowoptions_cols.vis[1]:=strmatch(strcopy1(vicolorname,1,7),'?custom') or (not strmatch(strcopy1(vicolorname,1,1),'?'));

   //reset
   ishowoptions_timer100:=slowms64+100;
   end;

//timer500
bol1:=(ishowoptions_statslist<>nil) and low__setint(ishowoptions_statslist.tag,ishowoptions_statslist.hoverindex) or
      (ishowoptions_snooplist<>nil) and low__setint(ishowoptions_snooplist.tag,ishowoptions_snooplist.hoverindex);

bol2:=(ibackgroundmanager<>nil) and low__setint(ibackgroundmanager.tag,insint(1,ibackgroundmanager.canselectimage));

if (slowms64>=ishowoptions_timer500) or bol1 or bol2 then
   begin
   //background toolbar
   if (ishowoptions_toolbar_background<>nil) then
      begin
      ishowoptions_toolbar_background.benabled2['options.backfile']:=ibackgroundmanager.canselectimage;
      ishowoptions_toolbar_background.benabled2['options.backpaste']:=ibackgroundmanager.canpasteimage;
      ishowoptions_toolbar_background.benabled2['options.backclear']:=ibackgroundmanager.canclearimage;

      bol1:=ibackgroundmanager.canselectimage;
      ishowoptions_toolbar_background.bvisible2['options.backfile']:=bol1;
      ishowoptions_toolbar_background.bvisible2['options.backpaste']:=bol1;
      ishowoptions_toolbar_background.bvisible2['options.backclear']:=bol1;
      end;

   //stats
   if (ishowoptions_statslist<>nil) then ishowoptions_statslist.paintnow;
   if (ishowoptions_snooplist<>nil) then
      begin

      if (ishowoptions_snooplist.countx<>win__infocount) then ishowoptions_snooplist.countx:=win__infocount;
      ishowoptions_snooplist.paintnow;

      end;
      
   //reset
   ishowoptions_timer500:=slowms64+500;
   end;

except;end;
end;

procedure tbasicsystem.xshowoptions_showmenu(sender:tobject);
begin
xshowoptions_sync2(sender,'options.menu',false);
end;

procedure tbasicsystem.xshowoptions_click(sender:tobject);
begin
xshowoptions_sync2(sender,'',true);
end;

procedure tbasicsystem.xshowoptions_sync(sender:tobject);
begin
xshowoptions_sync2(sender,'',false);
end;

procedure tbasicsystem.xshowoptions_sync2(sender:tobject;xname:string;xclicked:boolean);
label
   skipend;
var
   str1,str2,e,n,v:string;
   p,int1,int2:longint;
   bol1:boolean;
   aset:tbasicset;//pointer only

   procedure xoptions_menu(xcode2:string);
   var
      b,m:tstr8;
      xcode,xtepcolor:longint;
      bol1,bol2:boolean;
      daction:string;
   begin
   try
   //defaults
   m:=nil;
   b:=nil;
   //init
   if (xcode2='') then
      begin
      m:=str__new8;
      bol1:=strmatch(strcopy1(vicolorname,1,7),'?custom') or (not strmatch(strcopy1(vicolorname,1,1),'?'));
      bol2:=clip__canpastetext;
      low__menuinit(m);
      low__menutitle(m,tepNone,'Color Schemes - Options','Color options');
      low__menuitem2(m,tepCopy20,'Copy',rthtranslate('Copy color scheme to Clipboard as plain text - safe to share with friends etc'),'copy',100,aknone,true);
      //was: low__menuitem2(m,tepPaste20,'Paste and Use - Brighten Colors',rthtranslate('Paste color scheme from Clipboard and brighten colors and use'),'pasteuse2',100,aknone,bol2);//18sep2022
      low__menuitem2(m,tepPaste20,'Paste as Custom...',rthtranslate('Paste color scheme from Clipboard into selected custom slot'),'paste',100,aknone,bol1 and bol2);//14mar2021
      low__menuitem2(m,tepPaste20,'Paste New...',rthtranslate('Paste color scheme from Clipboard and save to file'),'pastenew',100,aknone,bol2);//14mar2021
      low__menuitem2(m,tepPaste20,'Paste and Use',rthtranslate('Paste color scheme from Clipboard and use immediately'),'pasteuse',100,aknone,bol2);//27mar2022
      low__menusep(m);
      low__menuitem2(m,tepRefresh20,'Refresh','Refresh color schemes list','refresh',100,aknone,true);
      low__menuitem2(m,tepSave20,'Save As...','Save color scheme to file','save',100,aknone,true);
      low__menuitem2(m,tepFolder20,'Show Folder','Show color schemes folder','folder',100,aknone,true);
      low__menuend(m);
      end;
   //get
   if (xcode2<>'') or popmenu(pmNormal,iaNormal,m,xcode,xcode2,xtepcolor) then
      begin
      if      (xcode2='refresh') then xshowoptions_reload
      else if (xcode2='copy') and zzok(ishowoptions_colors,7103)  then ishowoptions_colors.tosys('?copy.hex',false)
      else if (xcode2='pasteuse') and zzok(ishowoptions_colors,7104) then ishowoptions_colors.tosys('?pasteuse.hex',true)
      else if (xcode2='pasteuse2') and zzok(ishowoptions_colors,7104) then ishowoptions_colors.tosys('?pasteuse2.hex',true)
      else if (xcode2='brighten') and zzok(ishowoptions_colors,7104) then ishowoptions_colors.tosys('?brighten.hex',true)
      else if (xcode2='darken') and zzok(ishowoptions_colors,7104) then ishowoptions_colors.tosys('?darken.hex',true)
      else if (xcode2='paste') and zzok(ishowoptions_colors,7104) then ishowoptions_colors.tosys('?paste.hex',true)
      else if (xcode2='pastenew') and zzok(ishowoptions_colors,7104) then ishowoptions_colors.tosys('?pastenew.hex',true)
      else if (xcode2='folder') then runlow(low__platfolder('schemes'),'')
      else if (xcode2='save') then
         begin
         if (sysfile_colorscheme='') then sysfile_colorscheme:=low__platfolder('schemes')+'Untitled.'+cnFileEXT;
         daction:='';
         if popsave(sysfile_colorscheme,pebcs,low__platfolder('schemes'),daction) then
            begin
            b:=str__new8;
            b.text:=low__getcolors(@vinormal,@vititle,@vimorecolors);//25may2021
            case io__tofile(sysfile_colorscheme,@b,e) of
            true:xshowoptions_reload;
            else poperror('',e);
            end;//case
            end;
         end;
      end;
   except;end;
   try
   str__free(@m);
   str__free(@b);
   except;end;
   end;
begin
try
//defaults
n:='';
v:='';
str1:='';
//init
xname:=strlow(xname);


//get
if      (xname='options.menu') then xoptions_menu('')
else if zznil(sender,7407) then goto skipend//04may2021
else if (sender is tbasicmenu) then
   begin
   n:=(sender as tbasicmenu).tagstr;
   v:=(sender as tbasicmenu).ocode2;
   if zzok(syssettings,7105) then
      begin
      if (n='colorname') or (n='fontname') or (n='fontname2') or (n='framename') or (n='backname') then//21jul2024, 24feb2022
         begin
         syssettings.value[n]:=v;
         vimustsync:=true;
         end;
      end;
   end
else if (sender is tsimpleint) then
   begin
   n:=(sender as tsimpleint).tagstr;
   int1:=(sender as tsimpleint).val;
   if zzok(syssettings,7107) then
      begin
      syssettings.i[n]:=int1;
      vimustsync:=true;
      end;
   end
else if (sender is tbasicset) then
   begin
   //init
   n:=(sender as tbasicset).tagstr;
   aset:=(sender as tbasicset);
   //get
   if zzok(syssettings,7108) then
      begin
      for p:=0 to max32 do
      begin
      case (aset.caps[p]<>'') of
      true:if (aset.nams[p]<>'') then syssettings.b[aset.nams[p]]:=aset.vals[p];
      else break;
      end;//case
      end;//p
      vimustsync:=true;
      end;
   end
else if (sender is tbasicsel) then
   begin

   n    :=(sender as tbasicsel).tagstr;
   int1 :=(sender as tbasicsel).val;

   if zzok(syssettings,7109) then
      begin

      if (n='fontsize') or (n='fontsize2')then//05sep2025, 26feb2022
         begin

         int2:=int1;

         case int2 of
         0:int1:=6;
         1:int1:=7;
         2:int1:=8;
         3:int1:=9;
         4:int1:=10;
         5:int1:=11;
         6:int1:=12;
         7:int1:=14;
         8:int1:=16;
         9:int1:=22;
         10:int1:=24;
         else int1:=8;
         end;//case

         end
      else if (n='fontname') or (n='fontname2') then
         begin
         str1:=(sender as tbasicsel).nams[int1];
         if xclicked and (str1='*') then
            begin
            if (sender as tbasicsel).wasselected then
               begin
               str2:=syssettings.s[n+'.c'];
               if popfont(str2) then syssettings.s[n+'.c']:=str2 else goto skipend;
               end
            else goto skipend;
            end;
         end
      else if (n='cursorname') then
         begin

         str1:=(sender as tbasicsel).nams[int1];//29aug2021

         if strmatch(str1,'custom') and strmatch(str1,system_cursorname) and (sender as tbasicsel).focused and (sender as tbasicsel).gui.mouseupstroke then str1:='custom.prompt'
         else if strmatch(str1,system_cursorname) then goto skipend;

         end;

      //set
      if (str1<>'') then
         begin
         if (n='cursorname') then app__savecursor(str1,(sender as tbasicsel).gui)//24jan2025, 29aug2021
         else syssettings.s[n]:=str1;
         end
      else syssettings.i[n]:=int1;

      vimustsync:=true;
      end;
   end
else if (sender is tbasictoolbar) then
   begin
   str1:=strlow((sender as tbasictoolbar).ocode2);

   if      (str1='defaults')           then xdefaults
   else if (str1='options.menu')       then xoptions_menu('')
   else if (str1='options.copycols')   then xoptions_menu('copy')
   else if (str1='options.pastecols')  then xoptions_menu('pasteuse')//27mar2022
   else if (str1='options.pastecols2') then xoptions_menu('pasteuse2')//18sep2022
   else if (str1='options.brighten')   then xoptions_menu('brighten')//18sep2022
   else if (str1='options.darken')     then xoptions_menu('darken')//18sep2022
   //background tile support - 22jul2024
   else if (str1='options.backpaste') then
      begin
      if ibackgroundmanager.canpasteimage then ibackgroundmanager.pasteimage;
      end
   else if (str1='options.backfile') then
      begin
      if ibackgroundmanager.canselectimage then ibackgroundmanager.selectimage;
      end
   else if (str1='options.backclear') then
      begin
      if ibackgroundmanager.canclearimage then ibackgroundmanager.clearimage;
      end;
   end;

//cross value sync - 26feb2022
ishowoptions_crosssync:=true;

//was: if (sender=ishowoptions_options) or (sender=ishowoptions_frameoptions) then ishowoptions_crosssync:=true;
skipend:


//color schemes -> show/hide "... menu" link
if (ishowoptions_window<>nil) and (ishowoptions_maintoolbar<>nil) then
   begin

   bol1:=(ishowoptions_window.page='color');
   if (bol1<>ishowoptions_maintoolbar.benabled2['options.menu']) then ishowoptions_maintoolbar.benabled2['options.menu']:=bol1;

   end;

//background schemes -> toolbar show/hide
if (ishowoptions_toolbar_background<>nil) then
   begin

   bol1:=strmatch(strcopy1(syssettings.value['backname'],1,6),'custom');
   if (bol1<>ishowoptions_toolbar_background.visible) then ishowoptions_toolbar_background.visible:=bol1;

   end;
   
except;end;
end;

procedure tbasicsystem.xshowoptions_crosssync;
begin
try
//special cross-control update -> when one control has another's value and thus both might need to reload to relfect that cross-control change - 26feb2022
if (ishowoptions_framesize1<>nil) and (ishowoptions_framesize2<>nil) then
   begin
   ishowoptions_framesize1.reload;
   ishowoptions_framesize2.reload;
   ishowoptions_framesize1.ounit:=insstr('  (Best viewed at '+k64(viFrameminsize)+'+)',(viFrameminsize>=1) and (viFrameminsize>viBordersize));
   ishowoptions_framesize2.ounit:=ishowoptions_framesize1.ounit;
   end;
if (ishowoptions_sparkle1<>nil) and (ishowoptions_sparkle2<>nil) then
   begin
   ishowoptions_sparkle1.reload;
   ishowoptions_sparkle2.reload;
   end;
if (ishowoptions_brightness3<>nil) then ishowoptions_brightness3.reload;

//.show / hide "Options > Background > Adjustments" column
if (ishowoptions_backs<>nil) and (ishowoptions_backs_cols<>nil) then
   begin
   ishowoptions_backs_cols.vis[1]:=(ibackgroundmanager<>nil) and ibackgroundmanager.canadjust;
   end;
{was:
if (ishowoptions_options<>nil) and (ishowoptions_frameoptions<>nil) then
   begin
   ishowoptions_frameoptions.reload;
   ishowoptions_options.reload;
   end;
{}//xxxxx
except;end;
end;

procedure tbasicsystem.xshowhelp;
begin
low__plat('showhelp','',false);
end;

procedure tbasicsystem.xdefaults;//10dec2025
label
   skipend;
begin

//disable normal operations
xstartbw(true);

//prompt
if not popquery22('Restore Defaults','To restore default settings for appearance, background, font, settings etc, click the "Restore Defaults" button below or press the "Enter" key.','','Restore Defaults',false,false) then goto skipend;

//get
app__savecursor('default',nil);
siLoadsyssettingsfrom(nil);

skipend:

//restore normal operations
xstopbw(true);

end;

procedure tbasicsystem.xdefaultscale;//no switches "scalemode" back to 0 -> automatic mode - 10dec2025
begin

//get
syssettings.i['scalemode']:=0;

//sync
viSync;

//save
siSavesyssettings;//only need to save system settings here - 05oct2020

end;

procedure tbasicsystem.xstartbw(xpaint:boolean);
begin

inc(system_blackwhitecount);
visync;
if xpaint then fullalignpaint;

end;

procedure tbasicsystem.xstopbw(xpaint:boolean);
begin

system_blackwhitecount:=frcmin32(system_blackwhitecount-1,0);
visync;
if xpaint then fullalignpaint;

end;

procedure tbasicsystem.xsyncfullscreen;//02dec2024: updated to check exact area and enforce it -> internal use only
var
   a:twinrect;
   s:char;
begin

//check
s:=state;
if (istable<>0) or ((s<>'+') and (s<>'f')) then exit;

//filter
if (s='f') and viwine then s:='+';

//get
if      (s='+') then a:=monitors__workarea_auto(monitorindex)
else if (s='f') then a:=monitors__area_auto(monitorindex)
else                 a:=monitors__workarea_auto(monitorindex);

//set
if (left<>a.left) or (top<>a.top) or (width<>(a.right-a.left+1)) or (height<>(a.bottom-a.top+1)) then
   begin
   setbounds(a.left,a.top,a.right-a.left+1,a.bottom-a.top+1);

   //detect faulty size behaviour -> such as under Mac and Linxu via Wine when attempting "Maximise" or "Full Screen" modes - 09sep2025
   inc(iform_sizecheckcount);
   if (iform_sizecheckcount>=3) then
      begin

      iform_sizecheckcount:=0;
      if      (state='f') then state:='+'//downgrade from full screen to maximise
      else if (state='+') then state:='n';//downgrade from maximise to normal

      end;

   end;

end;

function tbasicsystem.curpos:tpoint;//our internal cursor position (within the system area only) - 21may2020
var
   a,b:tpoint;
begin
b:=clienttoscreen(low__point(0,0));
low__getcursorpos(a);
result.x:=a.x-b.x;
result.y:=a.y-b.y;
end;

function tbasicsystem.downcurpos:tpoint;//our internal cursor position (within the system area only) - 21may2020
var
   a,b:tpoint;
begin
b:=clienttoscreen(low__point(0,0));
low__getcursordownpos(a);
result.x:=a.x-b.x;
result.y:=a.y-b.y;
end;

function tbasicsystem.getmaskval:longint;
begin
if imasking then result:=imaskval else result:=-1;
end;

function tbasicsystem.mustmask:boolean;
var
   i,p:longint;
begin

//defaults
result:=false;

try

//check
if (winlist.count<=1) then exit;//only required if 2 or more windows

//get
//.dimensions
if (not result) and ((imask.width<>ibuffer.width) or (imask.height<>ibuffer.height)) then result:=true;

//.count
if (not result) and (winmask_cnt<>winlist.count) then result:=true;

//.visual values
if (not result) then
   begin

   for p:=0 to (winlist.count-1) do
   begin

   i:=winlist.list[p];

   if (i>=0) and (i<icorecount) and zzok(icore[i],7111) and ((winmask_id[p]<>icore[i].id) or (winmask_aid[p]<>icore[i].aid) or (winmask_vis[p]<>icore[i].visible) or (winmask_rnd[p]<>icore[i].rounded)) then
      begin

      result:=true;
      break;

      end;

   end;//p

   end;

except;end;
end;

procedure tbasicsystem.dragstart(xcoreindex:longint);
begin

if (idragindex=-1) and xvisible(xcoreindex) and (icore[xcoreindex].winstyle>wmfullwin) then
   begin

   sizestop;
   track__inc(satDragcount,1);
   idragindex:=xcoreindex;
   idragstart:=xcoreindex;
   paintallnow;

   end;

end;

function tbasicsystem.dragging:boolean;//21nov2024
begin//dragging a floating window or resizing a window
result:=(idragindex>=0) or idragging_fullwin;
end;

function tbasicsystem.dragging_an_internal_window:boolean;//28nov2024
begin//dragging a floating window
result:=(idragindex>=0);
end;

procedure tbasicsystem.dragstart_fullwin;//this relates to external OS only and NOT to our internal system - 15apr2021
begin
idragging_fullwin:=true;
end;

procedure tbasicsystem.dragstop;
var
   xmustpaint:boolean;
begin

//init
xmustpaint:=false;

//get
if (idragindex>=0) then
   begin

   idragindex:=-1;
   idragstart:=-1;
   xmustpaint:=true;

   end;

if idragging_fullwin then
   begin

   idragging_fullwin:=false;
   xmustpaint:=true;

   end;

//set
if xmustpaint then paintallnow;

end;

procedure tbasicsystem.sizestart(xcoreindex:longint);
begin//Note: sizing=0=off, 1=resizing MAIN window, 2=resizing all other window types - 22apr2022

if (isizeindex=-1) and xvisible(xcoreindex) then
   begin

   //was: if (isizing<1) then isizing:=1;//22apr2022

   if (icore[xcoreindex].winstyle>wmfullwin) then
      begin

      track__inc(satSizecount,1);
      dragstop;
      isizeindex:=xcoreindex;
      isizestart:=xcoreindex;
      isizing:=2;
      paintallnow;

      end;

   end;

end;

procedure tbasicsystem.sizestop;
begin

if (isizeindex>=0) then
   begin

   isizeindex:=-1;
   isizestart:=-1;
   paintallnow;

   end;

isizing:=0;

end;

function tbasicsystem.resizing:boolean;//15mar2025
begin//Note: We used to adjust the main form's size (isizing=1), but this is now done by the OS (iform_sizing=true)

result:=(isizing>=1) or iform_sizing;

end;

function tbasicsystem.xdlg(var x:tbasiccontrol):boolean;
var
   p,i:longint;
begin
//defaults
result:=false;

try
x:=nil;
//find
if (winlist.count>=1) then
   begin
   for p:=(winlist.count-1) downto 0 do
   begin
   i:=winlist.list[p];
   if xinuse(i) and (icore[i].winstyle=wmdialog) and icore[i].visible then
      begin
      x:=icore[i];
      result:=true;
      break;
      end;
   end;//p
   end;
except;end;
end;

function tbasicsystem.xwinfindlayer(xcoreindex:longint;var xlayer:longint):boolean;
var
   p:longint;
begin
//defaults
result:=false;

try
xlayer:=-1;//not found
//find
if (xcoreindex>=0) and (xcoreindex<icorecount) and (winlist.count>=1) then
   begin
   for p:=0 to (winlist.count-1) do if (xcoreindex=winlist.list[p]) then
      begin
      xlayer:=p;
      result:=true;
      break;
      end;//p
   end;
except;end;
end;

function tbasicsystem.xwinfindbyxy(sx,sy:longint;var xcoreindex,xwinlayer:longint):boolean;
var
   p,i:longint;
begin
//defaults
result:=false;

try
xcoreindex:=0;
xwinlayer:=0;
//check
if (winlist.count<=0) then exit;
//find
for p:=(winlist.count-1) downto 0 do
begin
i:=winlist.list[p];
if xinuse(i) and (icore[i].winstyle>wmcontrol) and icore[i].visible then
   begin
   if (sx>=icore[i].paintarea.left) and (sx<=icore[i].paintarea.right) and (sy>=icore[i].paintarea.top) and (sy<=icore[i].paintarea.bottom) then
      begin
      xcoreindex:=i;
      xwinlayer:=p;
      result:=true;
      break;
      end;
   //.dialog -> go no further than topmost dialog
   if (icore[i].winstyle=wmdialog) then break;
   end;
end;//p
except;end;
end;

function tbasicsystem.xfindwinname(xwinname:string;var x:tbasicscroll):boolean;
var
   p,i:longint;
begin
//defaults
result:=false;

try
x:=nil;
//find
if (winlist.count>=1) then
   begin
   for p:=(winlist.count-1) downto 0 do
   begin
   i:=winlist.list[p];
   if xinuse(i) and zzok(icore[i],7408) and (icore[i] is tbasicscroll) and strmatch(xwinname,icore[i].owinname) then
      begin
      x:=icore[i] as tbasicscroll;
      result:=true;
      break;
      end;
   end;//p
   end;
except;end;
end;

function tbasicsystem.xacceptfindbyxy(sx,sy:longint;var xout:tbasiccontrol):boolean;//updated - 20mar2022
var
   p2,p,i:longint;
begin
//defaults
result:=false;

try
xout:=nil;
//check
if (winlist.count<=0) then exit;
//find window
for p:=(winlist.count-1) downto 0 do
begin
i:=winlist.list[p];
if xinuse(i) and (icore[i].winstyle>wmcontrol) then
   begin
   //.a window to be searched
   if (sx>=icore[i].paintarea.left) and (sx<=icore[i].paintarea.right) and (sy>=icore[i].paintarea.top) and (sy<=icore[i].paintarea.bottom) then
      begin
      //.search EVERY control in the SYSTEM and look at those on the CURRENT window being searched - slower, BUT simple and accurate - 20mar2022
      for p2:=(icorecount-1) downto 0 do
      begin
      if xinuse(p2) and (p2<>i) and (icore[p2]<>nil) and (icore[p2].winstyle=wmcontrol) and (sx>=icore[p2].paintarea.left) and (sx<=icore[p2].paintarea.right) and (sy>=icore[p2].paintarea.top) and (sy<=icore[p2].paintarea.bottom) and (icore[i]=icore[p2].rootparent) and icore[p2].canaccept then
         begin
         xout:=icore[p2];
         result:=true;
         break;
         end;
      end;//p2
      //.now check the window itself LAST - 20mar2022
      if (not result) and icore[i].canaccept then
         begin
         xout:=icore[i];
         result:=true;
         end;
      end;
   //check
   if result then break;
   //.dialog -> go no further than topmost dialog
   if (icore[i].winstyle=wmdialog) then break;
   end;
end;//p
except;end;
end;

procedure tbasicsystem.xwintop(x:tbasiccontrol);
begin
xwinadd(x,'t');
end;

procedure tbasicsystem.xwinbot(x:tbasiccontrol);
begin
xwinadd(x,'b');
end;

procedure tbasicsystem.xwinnil(x:tbasiccontrol);
begin
xwinadd(x,'n');
end;

procedure tbasicsystem.xwinadd(x:tbasiccontrol;xstyle:char);
var
   dv:twinlist;
   i,p:longint;
   bol1,xbot,xtop,xonce:boolean;

   procedure xadd(xwinstyle:longint);
   var
      xlist:twinlist;
      p:longint;
   begin
   //init
   xlist.count:=0;
   //get
   //.bot
   if (not xonce) and xbot and zzok(x,7112) and (x.winstyle=xwinstyle) and (xlist.count<iwinlimit) then
      begin
      inc(xlist.count);
      xlist.list[xlist.count-1]:=x.coreindex;
      xonce:=true;
      end;
   //.del - 14may2020 @ 12.11am!!!
   if (winlist.count>=1) then
      begin
      for p:=0 to (winlist.count-1) do
      begin
      i:=winlist.list[p];
      if xinuse(i) and (icore[i].winstyle=xwinstyle) and (xlist.count<iwinlimit) then
         begin
         if zzok(x,7113) and (i=x.coreindex) and (xbot or xtop or xonce) then
            begin
            //window already handled or set to be handled
            end
         else
            begin
            inc(xlist.count);
            xlist.list[xlist.count-1]:=i;
            if zzok(x,7114) and (i=x.coreindex) then xonce:=true;
            end;
         end;//i
      end;//p
      end;
   //.top -> force top or add at top of this stack if not already existent in stack - 14may2020
   if ((not xonce) or xtop) and zzok(x,7115) and (x.winstyle=xwinstyle) and (xlist.count<iwinlimit) then
      begin
      inc(xlist.count);
      xlist.list[xlist.count-1]:=x.coreindex;
      xonce:=true;
      end;
   //set
   if (xlist.count>=1) then
      begin
      for p:=0 to (xlist.count-1) do
      begin
      if (dv.count<iwinlimit) then
         begin
         inc(dv.count);
         dv.list[dv.count-1]:=xlist.list[p];
         end
      else break;
      end;//p
      end;
   end;
begin
try
//init
xbot:=(xstyle='b');
xtop:=(xstyle='t');
xonce:=false;
dv.count:=0;

//get
xadd(wmFullwin);
xadd(wmWindow);
xadd(wmOntop);
xadd(wmDialog);

//set
bol1:=false;
if (winlist.count<>dv.count) then bol1:=true
else if (winlist.count>=1) then
   begin
   for p:=0 to (winlist.count-1) do if (winlist.list[p]<>dv.list[p]) then
      begin
      bol1:=true;
      break;
      end;//p
   end;
winlist:=dv;
//.list has changed -> update
if bol1 then
   begin
   alignallnow;
   paintallnow;
   end;
except;end;
end;

procedure tbasicsystem.xwoundcalc(x,y:longint);
const
   xlagfactor=3;

   function xmakerate(xref:comp;xlen:longint):longint;//pixels per second -> 0..1,000
   var
      v,l:longint;
   begin
   //defaults
   result:=0;

   try
   //get
   v:=frcrange32(sub32(slowms64,xref),1,3000);
   l:=frcrange32(low__posn(xlen),0,1000);
   //set
   result:=frcrange32(round(l*(1000/v)),0,1000);
   except;end;
   end;
begin
try
//y
iwoundratey:=frcrange32(((iwoundratey*xlagfactor)+xmakerate(iwoundref,y-iwoundlasty)) div (xlagfactor+1),0,iwoundratelimit);
iwounddiry:=low__aorb(-1,1,y>=iwoundlasty);
//x
iwoundratex:=frcrange32(((iwoundratex*xlagfactor)+xmakerate(iwoundref,x-iwoundlastx)) div (xlagfactor+1),0,iwoundratelimit);
iwounddirx:=low__aorb(-1,1,x>=iwoundlastx);
//reset
iwoundref:=slowms64;
iwoundlastx:=x;
iwoundlasty:=y;
except;end;
end;

function tbasicsystem.woundratextime(xmaxtime:longint;xincludedir:boolean):longint;
begin
result:=round(xmaxtime*woundratexpert1)*low__aorb(1,-1,xincludedir and (iwounddirx<0));
end;

function tbasicsystem.woundrateytime(xmaxtime:longint;xincludedir:boolean):longint;
begin
result:=round(xmaxtime*woundrateypert1)*low__aorb(1,-1,xincludedir and (iwounddiry<0));
end;

function tbasicsystem.woundratexpert1:extended;
begin
result:=(iwoundratex/iwoundratelimit);
end;

function tbasicsystem.woundrateypert1:extended;
begin
result:=(iwoundratey/iwoundratelimit);
end;

function tbasicsystem.woundratexpert100:longint;
begin
result:=frcrange32(round(woundratexpert1*100),0,100);
end;

function tbasicsystem.woundrateypert100:longint;
begin
result:=frcrange32(round(woundrateypert1*100),0,100);
end;

procedure tbasicsystem.xpartpaint__clear;
begin
ipartpaint_count:=0;
end;

function tbasicsystem.xpartpaint__addarea(x:twinrect):boolean;
var
   p:longint;
   xmustadd:boolean;
begin
//defaults
result:=true;
xmustadd:=true;

//check
if (ipartpaint_count>high(ipartpaint_arealist)) then//at capacity
   begin
   result:=false;
   exit;
   end;

//check
if (x.right<x.left) or (x.bottom<x.top) or (x.right<0) or (x.bottom<0) or (x.left>=iform_width) or (x.top>=iform_height) then exit;

//range
x.left    :=frcrange32(x.left,0,iform_width-1);
x.top     :=frcrange32(x.top,0,iform_height-1);
x.right   :=frcrange32(x.right,x.left,iform_width-1);
x.bottom  :=frcrange32(x.bottom,x.top,iform_height-1);

//find existing -> does the new area fit within an existing area, if so, don't add the new area - 12jan2025
if (ipartpaint_count>=1) then
   begin
   for p:=0 to (ipartpaint_count-1) do if low__areawithinrect(ipartpaint_arealist[p],x) then
      begin
      xmustadd:=false;
      break;
      end;//p
   end;

//add
if xmustadd then
   begin
   ipartpaint_arealist[ipartpaint_count]:=x;
   inc(ipartpaint_count);
   end;
end;

function tbasicsystem.xpartpaint__hasareaContained(x:twinrect):boolean;//for debugging
var
   p:longint;
begin
//defaults
result:=false;

//find
if (x.left<x.right) and (x.top<x.bottom) and (ipartpaint_count>=1) then
   begin
   for p:=0 to (ipartpaint_count-1) do if (x.left>=ipartpaint_arealist[p].left) and (x.right<=ipartpaint_arealist[p].right) and (x.top>=ipartpaint_arealist[p].top) and (x.bottom<=ipartpaint_arealist[p].bottom) then
      begin
      result:=true;
      break;
      end;
   end;
end;

function tbasicsystem.xareaongui(const x:twinrect):boolean;
begin

//was: result:=not ( (x.right<0) or (x.left>=iform_width) or (x.bottom<0) or (x.top>=iform_height) or (x.right<x.left) or (x.bottom<x.top) );

result:=
 (x.left<=x.right) and (x.top<=x.bottom)    and//valid area check
 (x.right>=0)      and (x.left<iform_width) and//gui area check
 (x.bottom>=0)     and (x.top<iform_height);

end;

function tbasicsystem.xareaseen(const sa:twinrect;xbeneathwindowlayer:longint):boolean;//07apr2026
var
   xpad,ypad,i,p:longint;
   a:twinrect;
begin

//defaults
result :=false;

//check
if not xareaongui(sa) then exit;

//range
xbeneathwindowlayer   :=frcrange32(xbeneathwindowlayer,0,iwinlimit);

//.x/ypad for spacing out the required squares area below a rounded area - 22may2020
with res__fastdraw( fdCorners ).core do
begin

xpad                  :=rimage.w * vizoom;
ypad                  :=rimage.h * vizoom;

end;

//quick check
if (winlist.count<=0) or (xbeneathwindowlayer>=winlist.count) then
   begin

   result:=true;
   exit;

   end;

//slow check
result :=true;

for p:=xbeneathwindowlayer to (winlist.count-1) do
begin

i:=winlist.list[p];

if xvisible(i) then
   begin

   a:=icore[i].paintarea;

   if xareaongui(a) then
      begin

      case icore[i].rounded of

      //.compare with rounded area using "xpad/ypad" compensation
      true:begin

         if (a.left<=(sa.left-xpad)) and (a.right>=(sa.right+xpad)) and (a.top<=(sa.top-ypad)) and (a.bottom>=(sa.bottom+ypad)) then
            begin

            result:=false;
            break;

            end;

         end;

      //.compare with square area directly
      else begin

         if (a.left<=sa.left) and (a.right>=sa.right) and (a.top<=sa.top) and (a.bottom>=sa.bottom) then
            begin

            result:=false;
            break;

            end;

         end;

      end;//case

      end;

   end;

end;//p

end;

procedure tbasicsystem.xdrawtohost__start(const xusetile:boolean);//10mar2026
var
   dBrightness357 :longint;
   dFallbackBW    :boolean;
   p              :longint;
begin

idrawtohost_count   :=0;
idrawtohost_usetile :=xusetile;

//note: do not change value during rendering -> unexpected results will occur - 04feb2025
//was: ilastbuffer2:=(ihintTimeout<>-1) or (vibrightness<>100) or idragdrop_dragging or (xusetile and ibackgroundmanager.inuse);

dFallbackBW         :=(system_blackwhitecount>=1);
dBrightness357      :=( frcrange32( low__aorb(vibrightness,100,dfallbackBW) ,60 ,130 ) * 255 ) div 100;//range: 153..331

with ibuffer2info do
begin

//are we in fallback black and white mode? -------------------------------------
fallbackBW          :=dfallbackBW;


//why is buffer2 active --------------------------------------------------------

rHint               :=(ihintTimeout<>-1) and (ihintTimeout<>0);
rBrightness         :=(dBrightness357<>255);
rDragDrop           :=idragdrop_dragging;
rBackground         :=xusetile and (not dfallbackBW) and ibackgroundmanager.preComputeCellForRender32( ibuffer2info );
active              :=rBrightness or rDragDrop or rBackground or rHint;//rHint requires buffer2 for post-hint cls - 10mar2026
ipaintedwithtile    :=rBackground;//13jan2026


//fast draw procs info ---------------------------------------------------------

//defaults
initCode            :=init_notset;
drawProc            :=0;

//get
if active then
   begin

   //init
   w                :=ibuffer2.width;
   h                :=ibuffer2.height;
   bits             :=ibuffer2.bits;

   drows            :=ibuffer2.prows32;
   srows            :=ibuffer .prows32;

   x1               :=0;
   x2               :=0;
   y1               :=0;
   y2               :=0;

   b357             :=dBrightness357;
   bCutoff255       :=(255*256) div frcmin32(b357,1);//29dec2025

   for p:=0 to high(blist) do blist[p]:=byte(frcrange32( (p*b357) shr 8 ,0 ,255 ));

   //finalise -> ok if both buffers match
   case (w<=ibuffer.width) and (h<=ibuffer.height) and (bits=ibuffer.bits) of
   true:initCode:=init_ok;
   else initCode:=init_err;
   end;//case

   //current dragDrop area
   if rDragDrop and (idragdrop_icon<>nil) then
      begin

      idragdrop_paintarea.left    :=mousemovexy.x - (idragdrop_icon.width div 2);
      idragdrop_paintarea.right   :=idragdrop_paintarea.left + idragdrop_icon.width - 1;
      idragdrop_paintarea.top     :=mousemovexy.y - (idragdrop_icon.height div 2);
      idragdrop_paintarea.bottom  :=idragdrop_paintarea.top + idragdrop_icon.height - 1;

      end;

   end;

end;//with

end;

procedure tbasicsystem.xdrawtohost__addarea(const xarea:twinrect);//14feb2025
var
   p:longint;
   xmustadd:boolean;
begin

//defaults
xmustadd :=true;

//check
if not validarea(xarea) then exit;

//find existing -> does the new area fit within an existing area, if so, don't add the new area - 12jan2025
if (idrawtohost_count>=1) then
   begin

   for p:=0 to (idrawtohost_count-1) do if low__areawithinrect(idrawtohost_arealist[p],xarea) then
      begin

      xmustadd:=false;
      break;

      end;//p

   end;

//add
if xmustadd and (idrawtohost_count<high(idrawtohost_arealist)) then
   begin

   idrawtohost_arealist[idrawtohost_count]:=xarea;
   inc(idrawtohost_count);

   end;

end;

procedure tbasicsystem.xdrawtohost__renderBufferToForm;
var
   p:longint;
begin

//erase previous hint
if validarea(ihintarea) then
   begin

   xdrawtohost(ihintarea);
   ihintarea:=nilarea;//remove area -> exclude from paint list from now on

   end;


//erase previous dragdrop
if validarea(idragdrop_lastarea) then
   begin

   xdrawtohost(idragdrop_lastarea);

   end;


//draw current hint
xdrawhint;


//draw current dragDrop area
if ibuffer2info.active and ibuffer2info.rDragDrop then
   begin

   fd__select( fdTemp );
   fd__defaults;

   fd__setbuffer( fd_buffer  ,ibuffer2 );
   fd__setbuffer( fd_buffer2 ,idragdrop_icon  );
   fd__setval( fd_power ,idragdrop_power255 );

   fd__setarea( fd_area  ,idragdrop_paintarea );
   fd__setarea2( fd_area2 ,0,0,idragdrop_paintarea.right-idragdrop_paintarea.left+1,idragdrop_paintarea.bottom-idragdrop_paintarea.top+1 );

   fd__render( fd_drawRGB );

   idragdrop_lastarea:=idragdrop_paintarea;
   xdrawtohost__addarea( idragdrop_paintarea );

   end;


//paint all modified areas on the screen
if (idrawtohost_count>=1) and (iform_handle<>0) then
   begin

   //simplify overlapping areas -> reduce area complexity to simple areas - 04feb2025
   area__simplifyoverlapping(idrawtohost_arealist,idrawtohost_count);


   //DEBUG Support: tbasicdebug -> paint related debugging
   if debug_basicdebug_areacheck then
      begin

      debug_basicdebug_areacheck:=false;
      xbasicdebug_proc;

      end;


   //render with buffer #1 or buffer #2
   for p:=0 to (idrawtohost_count-1) do xdrawfrom( lastbuffer.dc ,idrawtohost_arealist[p] );

   end;

end;

procedure tbasicsystem.xdrawhint;//13jan202
var
   ha:twinrect;
   pw,ph,t,b,v,dy,p,w,xbrightness357:longint;

   function fi(xlineindex:longint):longint;
   begin

   if (ihinttitle_linecount>=1) and (xlineindex<ihinttitle_linecount) then result:=vinormal.Rfsb else result:=vinormal.Rfs;

   end;

   function fh(xlineindex:longint):longint;
   begin

   if (ihinttitle_linecount>=1) and (xlineindex<ihinttitle_linecount) then result:=vinormal.fsbH else result:=vinormal.fsH;

   end;

begin

//check
if (ihintlines=nil) or (ihintlines.count<=0) or (not vihint) or (low__len32(ihint)<5) or (ihintTimeout<1) or gameMode then
   begin

   ihintarea:=nilarea;
   exit;

   end;

//init
pw          :=round(vinormal.fsH*0.75);
ph          :=round(vinormal.fsH*0.75);

//get
ha.left     :=ihintxy.x;
ha.right    :=ha.left;
ha.top      :=ihintxy.y+app__cursorsize;
ha.bottom   :=ha.top+(2*ph);
w           :=0;

for p:=0 to (ihintlines.count-1) do
begin

w           :=largest32( w ,fast__textwidth('',ihintlines.value[p],fi(p)) );
inc(ha.bottom,fh(p));

end;//p

ha.right    :=ha.left+w+(2*pw);

//check area on screen
//.right
if (ha.right>=width) then
   begin

   v        :=ha.right-(width-1);
   dec(ha.right,v);
   dec(ha.left,v);

   end;

//.left
if (ha.left<0) then
   begin

   v        :=-ha.left;
   inc(ha.right,v);
   inc(ha.left,v);

   end;

//.bottom
if (ha.bottom>=height) then
   begin

   v        :=ha.bottom-(height-1);
   dec(ha.top,v);
   dec(ha.bottom,v);

   end;

//.position hint above cursor when cursor.y is below the half way height mark - 21apr2025
if (ihintxy.y>(height div 2)) then
   begin

   v        :=ha.bottom-ha.top+1;
   ha.top:=ihintxy.y-v-app__cursorsize;
   ha.bottom:=ha.top+v;

   end;

//.top
if (ha.top<0) then
   begin

   v        :=-ha.top;
   inc(ha.top,v);
   inc(ha.bottom,v);

   end;


if validarea(ha) then
   begin

   //apply brightness
   xbrightness357  :=(frcrange32(low__aorb(vibrightness,100, (system_blackwhitecount>=1) ),60,130)*255) div 100;
   t               :=int__setbrightness357(vinormal.mfont,xbrightness357);
   b               :=int__setbrightness357(vinormal.mhint,xbrightness357);

   //background shade
   fshadeArea( ha ,b ,b ,viround );

   //text
   dy              :=ha.top+ph;

   for p:=0 to (ihintlines.count-1) do
   begin

   if (ihintlines.value[p]<>'*') then ftext(b,area__make(ha.left+1,ha.top+1,ha.right-1,ha.bottom-1),ha.left+pw,dy,t,'',ihintlines.value[p],fi(p));

   inc(dy,fh(p));

   end;//p

   //add area to proc paint list
   xdrawtohost__addarea(ha);

   end;

//set
ihintarea:=ha;

end;

procedure tbasicsystem.xbasicdebug_proc;
var
   bol1:boolean;
   dc,p,int1:longint;
   s,d:twinrect;
begin
try
//init
bol1:=false;
int1:=0;
s:=debug_basicdebug_area;

case debug_basicdebug_int1 of
0:dc:=clred;
1:dc:=clyellow;
2:dc:=cllime;
else
   begin
   dc:=clblue;
   debug_basicdebug_int1:=-1;
   end;
end;
inc(debug_basicdebug_int1);


//detect overlapping paint areas
for p:=0 to (idrawtohost_count-1) do
begin
if low__areawithinrect(idrawtohost_arealist[p],debug_basicdebug_area) then bol1:=true;

d:=idrawtohost_arealist[p];

if (d.top<=s.bottom) and (d.bottom>=s.top) and (d.left<=s.right) and (d.right>=s.left) then inc(int1);
end;//p

if not bol1 then low__irollone(debug_basicdebug_areafail_count);
if (int1>=2) then low__irollone(debug_basicdebug_areaoverlap_count);


//draw outline of areas to be rendered
for p:=0 to (idrawtohost_count-1) do foutlineArea(d,dc,false);

except;end;
end;

procedure tbasicsystem.xdrawtohost(xarea:twinrect);//21apr2025, 09jan2025, 21nov2024: background animation pauses now during window resize/reposition events
begin

//range
if (xarea.right<xarea.left) or (xarea.bottom<xarea.top) then exit;
xarea:=area__clip( area__make(0,0,width-1,height-1) ,xarea );

//get
xfd__drawtohost( xarea );

//add area to proc paint list
xdrawtohost__addarea(xarea);

end;

procedure tbasicsystem.xfd__renderBelowDragWindow_nochecks(const sa:twinrect;const xmaskVal:longint);
label//draw bottom.window up to (drag.window-1)
   l32,y32,l24,y24;
var
   sr8      :pcolorrows8;
   sr24,dr24:pcolorrows24;
   sr32,dr32:pcolorrows32;
   dx,dy:longint;
begin

//init
case imasking of
true:sr8:=imask.prows8;//2x faster than "mrow()"
else sr8:=nil;
end;//case

case ibuffer.bits of
32   :begin

   sr32      :=idragbuffer.prows32;
   dr32      :=ibuffer.prows32;

   case (sr8<>nil) of
   true:goto l32;
   else goto y32;
   end;//case

   end;
24   :begin

   sr24      :=idragbuffer.prows24;
   dr24      :=ibuffer.prows24;

   case (sr8<>nil) of
   true:goto l24;
   else goto y24;
   end;//case

   end;
else  exit;
end;//case


//layer.render32 ---------------------------------------------------------------
l32:

for dy:=sa.top to sa.bottom do
begin

for dx:=sa.left to sa.right do if (sr8[dy][dx]<xmaskVal) then dr32[dy][dx]:=sr32[dy][dx];

end;//dy

//done
exit;


//render32 ---------------------------------------------------------------------
y32:

for dy:=sa.top to sa.bottom do
begin

for dx:=sa.left to sa.right do dr32[dy][dx]:=sr32[dy][dx];

end;//dy

//done
exit;


//layer.render24 ---------------------------------------------------------------
l24:

for dy:=sa.top to sa.bottom do
begin

for dx:=sa.left to sa.right do if (sr8[dy][dx]<xmaskVal) then dr24[dy][dx]:=sr24[dy][dx];

end;//dy

//done
exit;


//render24 ---------------------------------------------------------------------
y24:

for dy:=sa.top to sa.bottom do
begin

for dx:=sa.left to sa.right do dr24[dy][dx]:=sr24[dy][dx];

end;//dy

//done

end;

procedure tbasicsystem.xfd__renderAboveDragWindow_nochecks(const sa:twinrect;const xmaskVal:longint);
label//.drag (drag.window+1)..254 -> this part only works if "imask" is active "imasking=true" - 05jan2026, 17may2020
   l32,l24;
var
   sr8      :pcolorrows8;
   sr24,dr24:pcolorrows24;
   sr32,dr32:pcolorrows32;
   dx,dy:longint;
begin

//init
case imasking of
true:sr8:=imask.prows8;//2x faster than "mrow()"
else exit;
end;//case

case ibuffer.bits of
32   :begin

   sr32      :=idragbuffer.prows32;
   dr32      :=ibuffer.prows32;
   goto l32;

   end;
24   :begin

   sr24      :=idragbuffer.prows24;
   dr24      :=ibuffer.prows24;
   goto l24;

   end;
else  exit;
end;//case


//layer.render32 ---------------------------------------------------------------
l32:

for dy:=sa.top to sa.bottom do
begin

for dx:=sa.left to sa.right do if (sr8[dy][dx]>xmaskVal) then dr32[dy][dx]:=sr32[dy][dx];

end;//dy

//done
exit;


//layer.render24 ---------------------------------------------------------------
l24:

for dy:=sa.top to sa.bottom do
begin

for dx:=sa.left to sa.right do if (sr8[dy][dx]>xmaskVal) then dr24[dy][dx]:=sr24[dy][dx];

end;//dy

//done

end;

procedure tbasicsystem.xfd__drawtohost(const x:twinrect);
begin

if (ibuffer2info.initCode=init_ok) and ibuffer2info.active then
   begin

   //range check
   if (ibuffer2info.w<1) or (ibuffer2info.h<1) or (x.right<x.left) or (x.bottom<x.top) then exit;

   //x range
   if      (x.left<0)                   then ibuffer2info.x1:=0
   else if (x.left>=ibuffer2info.w)     then ibuffer2info.x1:=ibuffer2info.w-1
   else                                      ibuffer2info.x1:=x.left;

   if      (x.right<ibuffer2info.x1)    then ibuffer2info.x2:=ibuffer2info.x1
   else if (x.right>=ibuffer2info.w)    then ibuffer2info.x2:=ibuffer2info.w-1
   else                                      ibuffer2info.x2:=x.right;

   //y range
   if      (x.top<0)                    then ibuffer2info.y1:=0
   else if (x.top>=ibuffer2info.h)      then ibuffer2info.y1:=ibuffer2info.h-1
   else                                      ibuffer2info.y1:=x.top;

   if      (x.bottom<ibuffer2info.y1)   then ibuffer2info.y2:=ibuffer2info.y1
   else if (x.bottom>=ibuffer2info.h)   then ibuffer2info.y2:=ibuffer2info.h-1
   else                                      ibuffer2info.y2:=x.bottom;

   //brightness + background
   if ibuffer2info.rBackground and ibuffer2info.rBrightness then
      begin

      xfd__drawtohost703__background_brightness(ibuffer2info);

      end

   //brightness only
   else if ibuffer2info.rBrightness then xfd__drawtohost701__brightness(ibuffer2info)

   //background only
   else if ibuffer2info.rBackground then xfd__drawtohost702__background(ibuffer2info)

   //other -> rHint or rDragDrop
   else
      begin

      fd__select( fdTemp );
      fd__defaults;
      fd__setbuffer( fd_buffer  ,ibuffer2 );
      fd__setbuffer( fd_buffer2 ,ibuffer  );
      fd__setarea( fd_area12, x );
      fd__render( fd_drawRGB );

      end;

   end;

end;

procedure tbasicsystem.xfd__drawtohost701__brightness(var x:tfastbufferinfo);//29dec2025
label//mps ratings below are for an Intel Core i5 2.5 GHz
   yredo24,xredo24,yredo32,xredo32,
   yredo96_32,xredo96_32,
   yredo96_24,xredo96_24;
var
   sr24:pcolorrows24;
   dr24:pcolorrows24;
   sr32:pcolorrows32;
   dr32:pcolorrows32;
   sr96:pcolorrows96;
   dr96:pcolorrows96;
   xstop,ystop,xreset,dx,dy:longint32;
   vlist:tfastbufferbytelist;
   lx1,lx2,rx1,rx2,xreset96,xstop96:longint32;
   dstop96,dindex,sindex:iauto;

   function xcan96:boolean;
   begin

   result:=xfd__canrow962(x.bits,xreset,xstop,lx1,lx2,rx1,rx2,xreset96,xstop96) and (xstop96>=xreset96);

   if result then
      begin

      dr96   :=pcolorrows96(x.drows);
      sr96   :=pcolorrows96(x.srows);

      end;

   end;

begin

//defaults
x.drawProc  :=701;

//quick check
if (x.initcode<>init_ok) then exit;

//init
xreset      :=x.x1;
xstop       :=x.x2;
dx          :=xreset;
dy          :=x.y1;
ystop       :=x.y2;
vlist       :=x.blist;

//.bits
case x.bits of
24:begin

   dr24   :=pcolorrows24(x.drows);
   sr24   :=pcolorrows24(x.srows);

   case xcan96 of
   true:goto yredo96_24;
   else goto yredo24;
   end;//case

   end;
32:begin

   dr32   :=pcolorrows32(x.drows);
   sr32   :=pcolorrows32(x.srows);

   case xcan96 of
   true:goto yredo96_32;
   else goto yredo32;
   end;//case

   end;
else exit;
end;//case


//render96_32 (590mps) -------------------------------------------------=-------
yredo96_32:

xfd__inc32(xstop-xreset+1);
dindex :=iauto( @dr96[dy][xreset96] );
sindex :=iauto( @sr96[dy][xreset96] );
dstop96:=iauto( @dr96[dy][xstop96] );
xredo96_32:

//render pixel
pcolor96(dindex).v0  :=vlist[ pcolor96(sindex).v0  ];
pcolor96(dindex).v1  :=vlist[ pcolor96(sindex).v1  ];
pcolor96(dindex).v2  :=vlist[ pcolor96(sindex).v2  ];
//.a - leave as is
pcolor96(dindex).v4  :=vlist[ pcolor96(sindex).v4  ];
pcolor96(dindex).v5  :=vlist[ pcolor96(sindex).v5  ];
pcolor96(dindex).v6  :=vlist[ pcolor96(sindex).v6  ];
//.a - leave as is
pcolor96(dindex).v8  :=vlist[ pcolor96(sindex).v8  ];
pcolor96(dindex).v9  :=vlist[ pcolor96(sindex).v9  ];
pcolor96(dindex).v10 :=vlist[ pcolor96(sindex).v10 ];
//.a - leave as is

//inc x
if (dindex<>dstop96) then
   begin

   inc( dindex ,sizeof(tcolor96) );
   inc( sindex ,sizeof(tcolor96) );
   goto xredo96_32;

   end;

//row "begin" and "end" gaps
for dx:=lx1 to lx2 do
begin

dindex  :=iauto( @dr32[dy][dx] );
sindex  :=iauto( @sr32[dy][dx] );
pcolor32(dindex).r:=vlist[ pcolor32(sindex).r ];
pcolor32(dindex).g:=vlist[ pcolor32(sindex).g ];
pcolor32(dindex).b:=vlist[ pcolor32(sindex).b ];

end;//dx

for dx:=rx1 to rx2 do
begin

dindex  :=iauto( @dr32[dy][dx] );
sindex  :=iauto( @sr32[dy][dx] );
pcolor32(dindex).r:=vlist[ pcolor32(sindex).r ];
pcolor32(dindex).g:=vlist[ pcolor32(sindex).g ];
pcolor32(dindex).b:=vlist[ pcolor32(sindex).b ];

end;//dx

//inc y
if (dy<>ystop) then
   begin

   inc(dy,1);
   goto yredo96_32;

   end;

//done
xfd__inc64;
exit;


//render96_24 (530mps) ---------------------------------------------------------
yredo96_24:

xfd__inc32(xstop-xreset+1);
dindex :=iauto( @dr96[dy][xreset96] );
sindex :=iauto( @sr96[dy][xreset96] );
dstop96:=iauto( @dr96[dy][xstop96] );
xredo96_24:

//render pixel
pcolor96(dindex).v0  :=vlist[ pcolor96(sindex).v0  ];
pcolor96(dindex).v1  :=vlist[ pcolor96(sindex).v1  ];
pcolor96(dindex).v2  :=vlist[ pcolor96(sindex).v2  ];
pcolor96(dindex).v3  :=vlist[ pcolor96(sindex).v3  ];
pcolor96(dindex).v4  :=vlist[ pcolor96(sindex).v4  ];
pcolor96(dindex).v5  :=vlist[ pcolor96(sindex).v5  ];
pcolor96(dindex).v6  :=vlist[ pcolor96(sindex).v6  ];
pcolor96(dindex).v7  :=vlist[ pcolor96(sindex).v7  ];
pcolor96(dindex).v8  :=vlist[ pcolor96(sindex).v8  ];
pcolor96(dindex).v9  :=vlist[ pcolor96(sindex).v9  ];
pcolor96(dindex).v10 :=vlist[ pcolor96(sindex).v10 ];
pcolor96(dindex).v11 :=vlist[ pcolor96(sindex).v11 ];

//inc x
if (dindex<>dstop96) then
   begin

   inc( dindex ,sizeof(tcolor96) );
   inc( sindex ,sizeof(tcolor96) );
   goto xredo96_24;

   end;

//row "begin" and "end" gaps
for dx:=lx1 to lx2 do
begin

dindex  :=iauto( @dr24[dy][dx] );
sindex  :=iauto( @sr24[dy][dx] );
pcolor24(dindex).r:=vlist[ pcolor24(sindex).r ];
pcolor24(dindex).g:=vlist[ pcolor24(sindex).g ];
pcolor24(dindex).b:=vlist[ pcolor24(sindex).b ];

end;//dx

for dx:=rx1 to rx2 do
begin

dindex  :=iauto( @dr24[dy][dx] );
sindex  :=iauto( @sr24[dy][dx] );
pcolor24(dindex).r:=vlist[ pcolor24(sindex).r ];
pcolor24(dindex).g:=vlist[ pcolor24(sindex).g ];
pcolor24(dindex).b:=vlist[ pcolor24(sindex).b ];

end;//dx

//inc y
if (dy<>ystop) then
   begin

   inc(dy,1);
   goto yredo96_24;

   end;

//done
xfd__inc64;
exit;


//render32 (540mps) ------------------------------------------------------------
yredo32:

xfd__inc32(xstop-xreset+1);
dindex  :=iauto( @dr32[dy][xreset] );
sindex  :=iauto( @sr32[dy][xreset] );
dstop96 :=iauto( @dr32[dy][xstop] );

xredo32:

//render pixel
pcolor32(dindex).r:=vlist[ pcolor32(sindex).r ];
pcolor32(dindex).g:=vlist[ pcolor32(sindex).g ];
pcolor32(dindex).b:=vlist[ pcolor32(sindex).b ];

//inc x
if (dindex<>dstop96) then
   begin

   inc( dindex ,sizeof(tcolor32) );
   inc( sindex ,sizeof(tcolor32) );
   goto xredo32;

   end;

//inc y
if (dy<>ystop) then
   begin

   inc(dy,1);
   goto yredo32;

   end;

//done
xfd__inc64;
exit;


//render24 (420mps) ------------------------------------------------------------
yredo24:

xfd__inc32(xstop-xreset+1);
dindex  :=iauto( @dr24[dy][xreset] );
sindex  :=iauto( @sr24[dy][xreset] );
dstop96 :=iauto( @dr24[dy][xstop] );

xredo24:

//render pixel
pcolor24(dindex).r:=vlist[ pcolor24(sindex).r ];
pcolor24(dindex).g:=vlist[ pcolor24(sindex).g ];
pcolor24(dindex).b:=vlist[ pcolor24(sindex).b ];

//inc x
if (dindex<>dstop96) then
   begin

   inc( dindex ,sizeof(tcolor24) );
   inc( sindex ,sizeof(tcolor24) );
   goto xredo24;

   end;

//inc y
if (dy<>ystop) then
   begin

   inc(dy,1);
   goto yredo24;

   end;

//done
xfd__inc64;

end;

procedure tbasicsystem.xfd__drawtohost702__background(var x:tfastbufferinfo);
label
   yredo24,xredo24,yredo32,xredo32,yredo96_32,xredo96_32;
var
   sr24:pcolorrows24;
   dr24:pcolorrows24;
   sr32:pcolorrows32;
   dr32:pcolorrows32;
   tr32:pcolorrows32;
   sr96:pcolorrows96;
   dr96:pcolorrows96;

   xstop,ystop,xreset,txmin,txmax,txreset,ty,dx,dy:longint32;
   txstart,txstop,tystop:iauto;
   ta,la,ca,cainv:longint;
   dstop96,dindex,sindex,tindex:iauto;//32-64 bit
   tx,tr,tg,tb,lx1,lx2,rx1,rx2,xreset96,xstop96:longint32;

   function xcan96:boolean;
   begin

   result:=xfd__canrow962(x.bits,xreset,xstop,lx1,lx2,rx1,rx2,xreset96,xstop96);

   if result then
      begin

      dr96   :=pcolorrows96(x.drows);
      sr96   :=pcolorrows96(x.srows);

      end;

   end;

   function xfindtx(const vx:longint32):longint32;
   begin

   result:=txmin + ((vx + x.scrollx) mod x.cw);

   end;

begin

//defaults
x.drawProc  :=702;

//quick check
if (x.initcode<>init_ok) or (x.tilebits<>32) then exit;

//init
xreset      :=x.x1;
xstop       :=x.x2;
dx          :=xreset;
dy          :=x.y1;
ystop       :=x.y2;
ta          :=0;
la          :=0;
ca          :=0;
cainv       :=255-ca;
txmin       :=x.ci * x.cw;
txmax       :=txmin + x.cw - 1;
tr32        :=pcolorrows32(x.tilerows);
ty          :=(x.y1+x.scrolly) mod x.ch;
tystop      :=x.ch-1;

//.bits
case x.bits of
24:begin

   txreset  :=xfindtx(xreset);
   dr24     :=pcolorrows24(x.drows);
   sr24     :=pcolorrows24(x.srows);
   goto yredo24;

   end;
32:begin

   dr32     :=pcolorrows32(x.drows);
   sr32     :=pcolorrows32(x.srows);

   case xcan96 of
   true:begin

      txreset:=xfindtx(lx2+1);
      goto yredo96_32;

      end;
   else begin

      txreset:=xfindtx(xreset);
      goto yredo32;

      end;
   end;//case

   end;
else exit;
end;//case


//render96_32 ------------------------------------------------------------------
yredo96_32:

xfd__inc32(xstop-xreset+1);
dindex     :=iauto( @dr96[dy][xreset96] );
sindex     :=iauto( @sr96[dy][xreset96] );
dstop96    :=iauto( @dr96[dy][xstop96] );

if (ty>tystop) then ty:=0;

txstart    :=iauto( @tr32[ty][ txmin ] );
txstop     :=iauto( @tr32[ty][ txmax ] );
tindex     :=iauto( @tr32[ty][ txreset ] );
xredo96_32:

//render pixel
//.1
cainv                :=pcolor32(tindex).a;
pcolor96(dindex).v0  :=( (cainv*pcolor96(sindex).v0 ) shr 8 ) + pcolor32(tindex).b;
pcolor96(dindex).v1  :=( (cainv*pcolor96(sindex).v1 ) shr 8 ) + pcolor32(tindex).g;
pcolor96(dindex).v2  :=( (cainv*pcolor96(sindex).v2 ) shr 8 ) + pcolor32(tindex).r;

//inc tx
inc( tindex ,sizeof(tcolor32) );
if (tindex>txstop) then tindex:=txstart;

//.2
cainv                :=pcolor32(tindex).a;
pcolor96(dindex).v4  :=( (cainv*pcolor96(sindex).v4 ) shr 8 ) + pcolor32(tindex).b;
pcolor96(dindex).v5  :=( (cainv*pcolor96(sindex).v5 ) shr 8 ) + pcolor32(tindex).g;
pcolor96(dindex).v6  :=( (cainv*pcolor96(sindex).v6 ) shr 8 ) + pcolor32(tindex).r;

//inc tx
inc( tindex ,sizeof(tcolor32) );
if (tindex>txstop) then tindex:=txstart;

//.3
cainv                :=pcolor32(tindex).a;
pcolor96(dindex).v8  :=( (cainv*pcolor96(sindex).v8 ) shr 8 ) + pcolor32(tindex).b;
pcolor96(dindex).v9  :=( (cainv*pcolor96(sindex).v9 ) shr 8 ) + pcolor32(tindex).g;
pcolor96(dindex).v10 :=( (cainv*pcolor96(sindex).v10) shr 8 ) + pcolor32(tindex).r;

//inc tx
inc( tindex ,sizeof(tcolor32) );
if (tindex>txstop) then tindex:=txstart;

//inc x
if (dindex<>dstop96) then
   begin

   inc( dindex ,sizeof(tcolor96) );
   inc( sindex ,sizeof(tcolor96) );
   goto xredo96_32;

   end;

//row "begin" and "end" gaps
tx:=xfindtx(lx1);

for dx:=lx1 to lx2 do
begin

dindex              :=iauto( @dr32[dy][dx] );
sindex              :=iauto( @sr32[dy][dx] );
tindex              :=iauto( @tr32[ty][tx] );
cainv               :=pcolor32(tindex).a;
pcolor32(dindex).r  :=( (cainv*pcolor32(sindex).r ) shr 8 ) + pcolor32(tindex).r;
pcolor32(dindex).g  :=( (cainv*pcolor32(sindex).g ) shr 8 ) + pcolor32(tindex).g;
pcolor32(dindex).b  :=( (cainv*pcolor32(sindex).b ) shr 8 ) + pcolor32(tindex).b;

inc(tx);
if (tx>txmax) then tx:=txmin;

end;//dx

tx:=xfindtx(rx1);

for dx:=rx1 to rx2 do
begin

dindex              :=iauto( @dr32[dy][dx] );
sindex              :=iauto( @sr32[dy][dx] );
tindex              :=iauto( @tr32[ty][tx] );
cainv               :=pcolor32(tindex).a;
pcolor32(dindex).r  :=( (cainv*pcolor32(sindex).r ) shr 8 ) + pcolor32(tindex).r;
pcolor32(dindex).g  :=( (cainv*pcolor32(sindex).g ) shr 8 ) + pcolor32(tindex).g;
pcolor32(dindex).b  :=( (cainv*pcolor32(sindex).b ) shr 8 ) + pcolor32(tindex).b;

inc(tx);
if (tx>txmax) then tx:=txmin;

end;//dx

//inc y
if (dy<>ystop) then
   begin

   inc(dy,1);
   inc(ty,1);
   goto yredo96_32;

   end;

//done
xfd__inc64;
exit;


//render32 ---------------------------------------------------------------------
yredo32:

xfd__inc32(xstop-xreset+1);
dindex     :=iauto( @dr32[dy][xreset] );
sindex     :=iauto( @sr32[dy][xreset] );
dstop96    :=iauto( @dr32[dy][xstop] );

if (ty>tystop) then ty:=0;

txstart    :=iauto( @tr32[ty][ txmin ] );
txstop     :=iauto( @tr32[ty][ txmax ] );
tindex     :=iauto( @tr32[ty][ txreset ] );

xredo32:

//render pixel
cainv               :=pcolor32(tindex).a;
pcolor32(dindex).r  :=( (cainv*pcolor32(sindex).r ) shr 8 ) + pcolor32(tindex).r;
pcolor32(dindex).g  :=( (cainv*pcolor32(sindex).g ) shr 8 ) + pcolor32(tindex).g;
pcolor32(dindex).b  :=( (cainv*pcolor32(sindex).b ) shr 8 ) + pcolor32(tindex).b;

//inc tx
inc( tindex ,sizeof(tcolor32) );
if (tindex>txstop) then tindex:=txstart;

//inc x
if (dindex<>dstop96) then
   begin

   inc( dindex ,sizeof(tcolor32) );
   inc( sindex ,sizeof(tcolor32) );
   goto xredo32;

   end;

//inc y
if (dy<>ystop) then
   begin

   inc(dy,1);
   inc(ty,1);
   goto yredo32;

   end;

//done
xfd__inc64;
exit;


//render24 ---------------------------------------------------------------------
yredo24:

xfd__inc32(xstop-xreset+1);
dindex     :=iauto( @dr24[dy][xreset] );
sindex     :=iauto( @sr24[dy][xreset] );
dstop96    :=iauto( @dr24[dy][xstop] );

if (ty>tystop) then ty:=0;

txstart    :=iauto( @tr32[ty][ txmin ] );
txstop     :=iauto( @tr32[ty][ txmax ] );
tindex     :=iauto( @tr32[ty][ txreset ] );

xredo24:

//render pixel
cainv               :=pcolor32(tindex).a;
pcolor24(dindex).r  :=( (cainv*pcolor24(sindex).r ) shr 8 ) + pcolor32(tindex).r;
pcolor24(dindex).g  :=( (cainv*pcolor24(sindex).g ) shr 8 ) + pcolor32(tindex).g;
pcolor24(dindex).b  :=( (cainv*pcolor24(sindex).b ) shr 8 ) + pcolor32(tindex).b;

//inc tx
inc( tindex ,sizeof(tcolor32) );
if (tindex>txstop) then tindex:=txstart;

//inc x
if (dindex<>dstop96) then
   begin

   inc( dindex ,sizeof(tcolor24) );
   inc( sindex ,sizeof(tcolor24) );
   goto xredo24;

   end;

//inc y
if (dy<>ystop) then
   begin

   inc(dy,1);
   inc(ty,1);
   goto yredo24;

   end;

//done
xfd__inc64;

end;

procedure tbasicsystem.xfd__drawtohost703__background_brightness(var x:tfastbufferinfo);
label
   yredo24,xredo24,yredo32,xredo32,yredo96_32,xredo96_32;
var
   sr24:pcolorrows24;
   dr24:pcolorrows24;
   sr32:pcolorrows32;
   dr32:pcolorrows32;
   tr32:pcolorrows32;
   sr96:pcolorrows96;
   dr96:pcolorrows96;

   vlist:tfastbufferbytelist;
   xstop,ystop,xreset,txmin,txmax,txreset,ty,dx,dy:longint32;
   txstart,txstop,tystop:iauto;
   ta,la,ca,cainv:longint;
   dstop96,dindex,sindex,tindex:iauto;//32-64 bit
   tx,tr,tg,tb,lx1,lx2,rx1,rx2,xreset96,xstop96:longint32;

   function xcan96:boolean;
   begin

   result:=xfd__canrow962(x.bits,xreset,xstop,lx1,lx2,rx1,rx2,xreset96,xstop96);

   if result then
      begin

      dr96   :=pcolorrows96(x.drows);
      sr96   :=pcolorrows96(x.srows);

      end;

   end;

   function xfindtx(const vx:longint32):longint32;
   begin

   result:=txmin + ((vx + x.scrollx) mod x.cw);

   end;

begin

//defaults
x.drawProc  :=703;

//quick check
if (x.initcode<>init_ok) or (x.tilebits<>32) then exit;

//init
xreset      :=x.x1;
xstop       :=x.x2;
dx          :=xreset;
dy          :=x.y1;
ystop       :=x.y2;
ta          :=0;
la          :=0;
ca          :=0;
cainv       :=255-ca;
txmin       :=x.ci * x.cw;
txmax       :=txmin + x.cw - 1;
tr32        :=pcolorrows32(x.tilerows);
ty          :=(x.y1+x.scrolly) mod x.ch;
tystop      :=x.ch-1;
vlist       :=x.blist;

//.bits
case x.bits of
24:begin

   txreset  :=xfindtx(xreset);
   dr24     :=pcolorrows24(x.drows);
   sr24     :=pcolorrows24(x.srows);
   goto yredo24;

   end;
32:begin

   dr32     :=pcolorrows32(x.drows);
   sr32     :=pcolorrows32(x.srows);

   case xcan96 of
   true:begin

      txreset:=xfindtx(lx2+1);
      goto yredo96_32;

      end;
   else begin

      txreset:=xfindtx(xreset);
      goto yredo32;

      end;
   end;//case

   end;
else exit;
end;//case


//render96_32 ------------------------------------------------------------------
yredo96_32:

xfd__inc32(xstop-xreset+1);
dindex     :=iauto( @dr96[dy][xreset96] );
sindex     :=iauto( @sr96[dy][xreset96] );
dstop96    :=iauto( @dr96[dy][xstop96] );

if (ty>tystop) then ty:=0;

txstart    :=iauto( @tr32[ty][ txmin ] );
txstop     :=iauto( @tr32[ty][ txmax ] );
tindex     :=iauto( @tr32[ty][ txreset ] );
xredo96_32:

//render pixel
//.1
cainv                :=pcolor32(tindex).a;
pcolor96(dindex).v0  :=vlist[ ( (cainv*pcolor96(sindex).v0 ) shr 8 ) + pcolor32(tindex).b ];
pcolor96(dindex).v1  :=vlist[ ( (cainv*pcolor96(sindex).v1 ) shr 8 ) + pcolor32(tindex).g ];
pcolor96(dindex).v2  :=vlist[ ( (cainv*pcolor96(sindex).v2 ) shr 8 ) + pcolor32(tindex).r ];

//inc tx
inc( tindex ,sizeof(tcolor32) );
if (tindex>txstop) then tindex:=txstart;

//.2
cainv                :=pcolor32(tindex).a;
pcolor96(dindex).v4  :=vlist[ ( (cainv*pcolor96(sindex).v4 ) shr 8 ) + pcolor32(tindex).b ];
pcolor96(dindex).v5  :=vlist[ ( (cainv*pcolor96(sindex).v5 ) shr 8 ) + pcolor32(tindex).g ];
pcolor96(dindex).v6  :=vlist[ ( (cainv*pcolor96(sindex).v6 ) shr 8 ) + pcolor32(tindex).r ];

//inc tx
inc( tindex ,sizeof(tcolor32) );
if (tindex>txstop) then tindex:=txstart;

//.3
cainv                :=pcolor32(tindex).a;
pcolor96(dindex).v8  :=vlist[ ( (cainv*pcolor96(sindex).v8 ) shr 8 ) + pcolor32(tindex).b ];
pcolor96(dindex).v9  :=vlist[ ( (cainv*pcolor96(sindex).v9 ) shr 8 ) + pcolor32(tindex).g ];
pcolor96(dindex).v10 :=vlist[ ( (cainv*pcolor96(sindex).v10) shr 8 ) + pcolor32(tindex).r ];

//inc tx
inc( tindex ,sizeof(tcolor32) );
if (tindex>txstop) then tindex:=txstart;

//inc x
if (dindex<>dstop96) then
   begin

   inc( dindex ,sizeof(tcolor96) );
   inc( sindex ,sizeof(tcolor96) );
   goto xredo96_32;

   end;

//row "begin" and "end" gaps
tx:=xfindtx(lx1);

for dx:=lx1 to lx2 do
begin

dindex              :=iauto( @dr32[dy][dx] );
sindex              :=iauto( @sr32[dy][dx] );
tindex              :=iauto( @tr32[ty][tx] );
cainv               :=pcolor32(tindex).a;
pcolor32(dindex).r  :=vlist[ ( (cainv*pcolor32(sindex).r ) shr 8 ) + pcolor32(tindex).r ];
pcolor32(dindex).g  :=vlist[ ( (cainv*pcolor32(sindex).g ) shr 8 ) + pcolor32(tindex).g ];
pcolor32(dindex).b  :=vlist[ ( (cainv*pcolor32(sindex).b ) shr 8 ) + pcolor32(tindex).b ];

inc(tx);
if (tx>txmax) then tx:=txmin;

end;//dx

tx:=xfindtx(rx1);

for dx:=rx1 to rx2 do
begin

dindex              :=iauto( @dr32[dy][dx] );
sindex              :=iauto( @sr32[dy][dx] );
tindex              :=iauto( @tr32[ty][tx] );
cainv               :=pcolor32(tindex).a;
pcolor32(dindex).r  :=vlist[ ( (cainv*pcolor32(sindex).r ) shr 8 ) + pcolor32(tindex).r ];
pcolor32(dindex).g  :=vlist[ ( (cainv*pcolor32(sindex).g ) shr 8 ) + pcolor32(tindex).g ];
pcolor32(dindex).b  :=vlist[ ( (cainv*pcolor32(sindex).b ) shr 8 ) + pcolor32(tindex).b ];

inc(tx);
if (tx>txmax) then tx:=txmin;

end;//dx

//inc y
if (dy<>ystop) then
   begin

   inc(dy,1);
   inc(ty,1);
   goto yredo96_32;

   end;

//done
xfd__inc64;
exit;


//render32 ---------------------------------------------------------------------
yredo32:

xfd__inc32(xstop-xreset+1);
dindex     :=iauto( @dr32[dy][xreset] );
sindex     :=iauto( @sr32[dy][xreset] );
dstop96    :=iauto( @dr32[dy][xstop] );

if (ty>tystop) then ty:=0;

txstart    :=iauto( @tr32[ty][ txmin ] );
txstop     :=iauto( @tr32[ty][ txmax ] );
tindex     :=iauto( @tr32[ty][ txreset ] );

xredo32:

//render pixel
cainv               :=pcolor32(tindex).a;
pcolor32(dindex).r  :=vlist[ ( (cainv*pcolor32(sindex).r ) shr 8 ) + pcolor32(tindex).r ];
pcolor32(dindex).g  :=vlist[ ( (cainv*pcolor32(sindex).g ) shr 8 ) + pcolor32(tindex).g ];
pcolor32(dindex).b  :=vlist[ ( (cainv*pcolor32(sindex).b ) shr 8 ) + pcolor32(tindex).b ];

//inc tx
inc( tindex ,sizeof(tcolor32) );
if (tindex>txstop) then tindex:=txstart;

//inc x
if (dindex<>dstop96) then
   begin

   inc( dindex ,sizeof(tcolor32) );
   inc( sindex ,sizeof(tcolor32) );
   goto xredo32;

   end;

//inc y
if (dy<>ystop) then
   begin

   inc(dy,1);
   inc(ty,1);
   goto yredo32;

   end;

//done
xfd__inc64;
exit;


//render24 ---------------------------------------------------------------------
yredo24:

xfd__inc32(xstop-xreset+1);
dindex     :=iauto( @dr24[dy][xreset] );
sindex     :=iauto( @sr24[dy][xreset] );
dstop96    :=iauto( @dr24[dy][xstop] );

if (ty>tystop) then ty:=0;

txstart    :=iauto( @tr32[ty][ txmin ] );
txstop     :=iauto( @tr32[ty][ txmax ] );
tindex     :=iauto( @tr32[ty][ txreset ] );

xredo24:

//render pixel
cainv               :=pcolor32(tindex).a;
pcolor24(dindex).r  :=vlist[ ( (cainv*pcolor24(sindex).r ) shr 8 ) + pcolor32(tindex).r ];
pcolor24(dindex).g  :=vlist[ ( (cainv*pcolor24(sindex).g ) shr 8 ) + pcolor32(tindex).g ];
pcolor24(dindex).b  :=vlist[ ( (cainv*pcolor24(sindex).b ) shr 8 ) + pcolor32(tindex).b ];

//inc tx
inc( tindex ,sizeof(tcolor32) );
if (tindex>txstop) then tindex:=txstart;

//inc x
if (dindex<>dstop96) then
   begin

   inc( dindex ,sizeof(tcolor24) );
   inc( sindex ,sizeof(tcolor24) );
   goto xredo24;

   end;

//inc y
if (dy<>ystop) then
   begin

   inc(dy,1);
   inc(ty,1);
   goto yredo24;

   end;

//done
xfd__inc64;

end;

procedure tbasicsystem.ffillOUTSIDE(dx,dy,dw,dh,dcol:longint);//21jul2025
var
   cw,ch:longint;
begin

//init
dw:=frcmin32(dw,0);
dh:=frcmin32(dh,0);
cw:=width;
ch:=height;

//left
ffillArea(area__make(0,0,dx-1,ch-1),dcol,false);

//right
ffillArea(area__make(dx+dw,0,cw-1,ch-1),dcol,false);

//top
ffillArea(area__make(dx,0,dx+dw-1,dy-1),dcol,false);

//bottom
ffillArea(area__make(dx,dy+dh,dx+dw-1,ch-1),dcol,false);

end;

function tbasicsystem.xcornerCode:longint32;//05jan2026
begin

case viRound of
true:result:=fd_roundCorner;
else result:=fd_roundNone;
end;//case

end;

function tbasicsystem.xcornerMode:longint32;//13jan2026
begin

case viRound of
true:result:=rmAll;
else result:=rmNone;
end;//case

end;


procedure tbasicsystem.foutlineArea(const darea:twinrect;const dcol:longint;const dround:boolean);//26mar2026
begin

foutlineArea2( darea ,dcol ,255 ,false ,dround );

end;

procedure tbasicsystem.foutlineArea2(const darea:twinrect;const dcol,dpower255:longint;const dsparkle,dround:boolean);//26mar2026
var
   x:pfastdraw;
begin

fd__selStore( x );
fd__select( fdHintEtc );

case dround or dsparkle of
true:fast__outlineArea2( darea ,darea ,dcol ,dpower255 ,xcornerCode ,xcornerMode ,dsparkle ,dround );
else fast__outlineArea ( darea ,darea ,dcol ,dpower255 );
end;//case

fd__selRestore( x );

end;

procedure tbasicsystem.ffillArea(const darea:twinrect;const dcol:longint;const dround:boolean);
var
   x:pfastdraw;
begin

fd__selStore( x );
fd__select( fdHintEtc );

case dround of
true:fast__fillArea2( darea ,darea ,dcol ,xcornerCode ,xcornerMode ,true);
else fast__fillArea ( darea ,darea ,dcol );
end;//case

fd__selRestore( x );

end;

procedure tbasicsystem.fshadeArea(const darea:twinrect;const dcol1,dcol2:longint;const dround:boolean);
var
   x:pfastdraw;
begin

fd__selStore( x );
fd__select( fdHintEtc );
fd__set( fd_fillAreaDefaults );
fd__setval( fd_color1, dcol1 );
fd__setval( fd_color2, dcol2 );
fd__setarea( fd_clip ,darea );
fd__setarea( fd_area ,darea );

if dround then
   begin

   fd__setCorner( xcornerCode );
   fd__setCorner( xcornerMode );
   fd__render( fd_roundStartFromArea );

   end;

fd__render( fd_shadeArea );

if dround then fd__render( fd_roundStopAndRender );
fd__selRestore( x );

end;

procedure tbasicsystem.fshadeArea2(const darea:twinrect;const dcol1,dcol2,dcol3,dcol4,dsplice100,dpower255:longint;const dround:boolean);
var
   x:pfastdraw;
begin

fd__selStore( x );
fd__select( fdHintEtc );
fd__set( fd_fillAreaDefaults );
fd__setval( fd_color1, dcol1 );
fd__setval( fd_color2, dcol2 );
fd__setval( fd_color3, dcol3 );
fd__setval( fd_color4, dcol4 );
fd__setval( fd_splice, dsplice100 );
fd__setval( fd_power, dpower255 );
fd__setarea( fd_clip ,darea );
fd__setarea( fd_area ,darea );

if dround then
   begin

   fd__setCorner( xcornerCode );
   fd__setCorner( xcornerMode );
   fd__render( fd_roundStartFromArea );

   end;

fd__render( fd_shadeArea );

if dround then fd__render( fd_roundStopAndRender );
fd__selRestore( x );

end;

procedure tbasicsystem.ftext(const dbackRef:longint;const darea:twinrect;const dx,dy,dcol:longint;const dtab,dtext:string;const dfont:longint32);//20feb2026
var
   x:pfastdraw;
begin

fd__selStore( x );
fd__select( fdHintEtc );

fast__drawText( low__aorb( clnone ,dbackRef ,viemboss ) ,maxarea ,darea ,dx ,dy ,dcol ,dtab ,dtext ,dfont ,cdNone ,viFeather );

fd__selRestore( x );

end;


//-- gamemode support ----------------------------------------------------------
procedure tbasicsystem.setgamemode(x:boolean);//29jan2025
begin
if (x<>igamemode) and low__setbol(igamemode,x and assigned(igamemode_onpaint) and assigned(igamemode_onnotify) and assigned(igamemode_onshortcut)) then
   begin
   //re-sync previously inivisible GUI
   if not igamemode then
      begin
      imustalign:=2;
      imustpaint:=2;
      end;
   //paint the screen
   paintnow;
   end;
end;

procedure tbasicsystem.__onpaint_debug(sender:tobject);//system._onpaint
begin
//missize(ibuffer2,width,height);
//miscls(ibuffer2,random(max32));
//ihost.canvas.draw(0,0,ibuffer2);
end;

procedure tbasicsystem.__onpaint(sender:tobject);//updated: 28jun2024, 28jul2020
label
   partpaint,fullpaint,done,skipend;
const
   xpartpaintlimit=10;
var//Note: -1=no paint, 0=full paint, 1..N=paint rects
   //.other
   xdragpaintarea,ppa,sa,da:twinrect;
   pa:tpoint;
   int1,int2,int3,xcount,xfn,tw,cw,ch,dx,dy,p,i:longint;
   xline:tstr8;
   xnormalmode,bol1,xback_animationcycle_mustpaint,xdragpaintareaok,xshowing,xdragfast,xmustmask,xmustfull:boolean;
   xstate:char;
   str1:string;
   //.drag and window support
   xmustpaint,xmustalign,xdragindex,xdragstart,xdraglayer,xtoplayer,xwincount:longint;

   procedure dfull0;
   var
      a:pfastdraw;
   begin

   if oclsscreen and xareaseen(area__make(0,0,cw-1,ch-1),0) then
      begin

      fd__selStore( a );
      fd__select( fdTemp );
      fd__defaults;
      fd__setbuffer( fd_buffer ,ibuffer );
      fd__setval( fd_color1 ,vinormal.background );
      fd__render( fd_fillArea );
      fd__selRestore( a );

      end;

   end;

   procedure dfull1(xto:longint;const xinclusive:boolean);
   var
      p,i:longint;
   begin

   //check
   if (xto<0) or (winlist.count<=0) then exit;

   //get
   for p:=0 to (winlist.count-1) do
   begin

   i:=winlist.list[p];
   if imasking then imaskval:=p+1;

   if (i=xto) then
      begin

      if xinclusive then icore[i].xpaint;

      break;

      end
   else icore[i].xpaint;

   end;//p

   end;

   procedure dfull2(xfrom:longint;const xinclusive:boolean);
   label
      skipone;
   var
      p,i:longint;
      xok:boolean;
   begin

   //check
   if (winlist.count<=0) or (xfrom>=icorecount) then exit;
   if (xfrom<0)                                 then xfrom:=0;

   //get
   xok:=false;

   for p:=0 to (winlist.count-1) do
   begin

   i:=winlist.list[p];

   if imasking then imaskval:=p+1;

   if (not xok) and (i=xfrom) then
      begin

      xok:=true;
      if not xinclusive then goto skipone;

      end;

   if xok then icore[i].xpaint;

   skipone:
   end;//p

   end;

   function xabort:boolean;
   begin

   result:=visyncing;
   if result then paintallnow;

   end;

   procedure xrender_fullscreen;
   begin

   xdrawtohost(area__make(0,0,width-1,height-1));

   end;

   procedure xrender_partscreen;//redraw requested sections of screen
   var
      p:longint;
   begin

   //draw - already optimised for best use of resources (duplicates etc have been removed) - 21jul2024
   for p:=1 to ipartpaint_count do
   begin

   if xabort then break;
   xdrawtohost(ipartpaint_arealist[p-1]);

   end;//p

   end;

   procedure xcorners;//26mar2026
   var
      bol1:boolean;
   begin

   bol1:=viround and (xstate='n');

   if low__setstr(iform_cornersREF,bnc(bol1)+bnc(viontop)+'|'+intstr32(cw)+'|'+intstr32(ch)+'|'+intstr32(viscale32)) and win____setwindowrgn(iform_handle,gui__newrgn(0,0,cw,ch,bol1),false) then
      begin

      track__inc(satRegion,-1);
      xmustalign:=2;
      xmustpaint:=2;

      end;

   end;

   procedure xfastDrawSync;
   begin

   //hint level buffer1 or buffer2
   fd__select( fdHintEtc );
   fd__defaults;
   fd__setBuffer( fd_buffer ,lastbuffer );

   //for control corner painting only
   fd__select( fdCorners );
   fd__defaults;
   fd__set( fd_roundNone );
   fd__setBuffer( fd_buffer ,self );//05jan2026
   fd__setLayerMask( self );

   //for general drawing by controls
   fd__select( fdControls );
   fd__defaults;
   fd__set( fd_roundNone );
   fd__setBuffer( fd_buffer ,self );//05jan2026
   fd__setLayerMask( self );

   end;

begin

//defaults
xline           :=nil;
xmustfull       :=false;
xnormalmode     :=not igamemode;
xstate          :=state;//update state -> last state - 26mar2026, 29aug2025

try


//check ------------------------------------------------------------------------

if (istable<>0) or (not showing) then exit;

if ipaintbusy then
   begin

   paintallnow;
   exit;

   end
else ipaintbusy:=true;

//dimensions
cw              :=frcmin32(iform_width,1);
ch              :=frcmin32(iform_height,1);

//game mode painting -> GUI is hidden and entire form is used for painting - 28jan2025
if igamemode then
   begin

   xcorners;//26mar2026

   ipaintbusy   :=false;
   iecopainting :=false;

   if assigned(igamemode_onpaint) then
      begin

      //increment frame counter - 01apr2026
      fd__renderFPS_incFrameCount;

      //paint proc
      igamemode_onpaint(self);

      end;

   exit;

   end;

//.eco mode
if not low__canecopaint(iecomode64) then
   begin

   ipaintbusy   :=false;
   iecopainting :=true;

   paintallnow;

   exit;

   end
else iecopainting:=false;


//init -------------------------------------------------------------------------
xcount          :=-1;

//.increment frame counter - 01apr2026
fd__renderFPS_incFrameCount;

//.drag and window support
xdragindex      :=idragindex;
xdragstart      :=idragstart;

//.check #2
if xabort then goto skipend;

//.reset trigger vars - 19jan2025
xmustalign      :=imustalign;
xmustpaint      :=imustpaint;
imustalign      :=0;
imustpaint      :=0;

case xmustalign of
2:track__inc(satFullalign,1);//16may2025
1:track__inc(satPartalign,1);//16may2025
end;

//.reuse the "drag system" for the "size system" - 25feb2021
if (xdragindex<0) and (isizeindex>=0) then
   begin

   xdragindex:=isizeindex;
   xdragstart:=isizestart;

   end;

xdraglayer      :=-1;
xtoplayer       :=-1;
xwincount       :=0;
xdragfast       :=vidragfast;
xdragpaintareaok:=false;

//.fps tracking - 02dec2024
if (ifpscount<max32) then inc(ifpscount);

//.window layers
if (winlist.count>=1) then
   begin

   for p:=0 to (winlist.count-1) do
   begin

   i:=winlist.list[p];

   if xvisible(i) then
      begin

      inc(xwincount);
      if (i=xdragindex) then xdraglayer:=p;
      xtoplayer:=p;

      end;

   end;//p

   end;

//.reset
imaskval    :=-1;


//buffer size ------------------------------------------------------------------

//.enlarge as required in realtime
if (cw>ibuffer.width) or (ch>ibuffer.height) or ( ibuffer.bits <> low__aorb(24,32,vi32bit) ) then
   begin

   //Important Note: Previously we just set the ibuffer to a larger size for faster resize speeds, but the subsystem "mustmask()" read this
   //                value thinking it was the intended size of ibuffer, when in fact it was just an oversized version for speed, this caused
   //                a continuous paint cycle until 5,000ms was up and the buffer was finally sized correctly - now further down below mask.resize()
   //                now uses "ibuffer.width,ibuffer.height" instead of old "cw,ch" - 28feb2022

   //get
   int1             :=ibuffer.width;
   int2             :=ibuffer.height;
   int3             :=ibuffer.bits;

   //set
   ibuffer .setparams( low__aorb(24,32,vi32bit) ,frcmin32(cw+100,ibuffer.width) ,frcmin32(ch+100,ibuffer.height) );

   //.sync buffer2 with buffer
   missetb(ibuffer2,ibuffer.bits);
   missize(ibuffer2,ibuffer.width,ibuffer.height);

   //.sync dragbuffer bits
   missetb(idragbuffer,ibuffer.bits);

   low__iroll(ibufferID2,1);
   ibufferresize64  :=slowms64+5000;

   //check - updated: 28jun2024
   if (ibuffer.width<>int1) or (ibuffer.height<>int2) or (ibuffer.bits<>int3) then xmustfull:=true;//full paint required - 20jul2024

   end

//.shrink backdown after a safe delay BUT only when not dragging a window (xdragindex<=-1) - 24jul2024: fixed paint scramble due to buffer resize DURING a window drag
else if (slowms64>=ibufferresize64) and (xdragindex<=-1) and ((ibuffer.width<>cw) or (ibuffer.height<>ch)) then
   begin

   //get
   int1             :=ibuffer.width;
   int2             :=ibuffer.height;

   //set
   ibuffer .setparams( ibuffer.bits ,cw ,ch );
   ibuffer2.setparams( ibuffer.bits ,cw ,ch );

   low__iroll(ibufferID2,1);
   ibufferresize64  :=slowms64+5000;

   //check - updated: 28jun2024
   if (ibuffer.width<>int1) or (ibuffer.height<>int2) then xmustfull:=true;//full paint required - 20jul2024

   end;


//corners ----------------------------------------------------------------------

xcorners;//26mar2026


//align ------------------------------------------------------------------------

//.all align events
if low__setstr(iform_sizeref,intstr32(cw)+'|'+intstr32(ch)) then
   begin

   xmustalign:=2;
   xmustpaint:=2;

   end;

if (xmustalign>=1) then
   begin

   low__iroll(ialignid,1);
   for p:=0 to (icorecount-1) do if xrootok(icore[p]) then icore[p].xalign;

   end;


//background animation paint request -------------------------------------------
xback_animationcycle_mustpaint:=ibackgroundmanager.mustpaint(true);//02mar2026, 13mar2025


//paint mode -------------------------------------------------------------------
//.mask check -> detect any changes in Window mask and switch to full paint mode if there are any found
xmustmask:=mustmask;//assumes "ibuffer" is already correctly sized - 19may2020
if xmustmask then xmustfull:=true;

//.paint check -> has full paint mode been requested, if so, switch to full paint mode
if (xmustpaint>=2) then xmustfull:=true;


//paint start ------------------------------------------------------------------
//init
if (cw<1) or (ch<1) then goto skipend;
low__iroll(ipaintid,1);


//decide
if xmustfull then goto fullpaint else goto partpaint;


//part paint -------------------------------------------------------------------

partpaint:

xpartpaint__clear;
xdrawtohost__start(true);
xfastDrawSync;//25dec2025

//check
if (winlist.count<=0) then goto done;

//check load -> if too many controls need to paint then switch to fullscreen paint - 20may2020
int1:=0;

for p:=0 to (winlist.count-1) do
begin

i:=winlist.list[p];

if (i>=0) and (i<icorecount) and xvisible(i) then
   begin

   inc(int1,icore[i].xmustpaintcount);
   if (int1>xpartpaintlimit) then goto fullpaint;

   end;//i

end;//p

//get
track__inc(satPartpaint,1);

if (int1>=1) then
   begin

   try

   ipaintingpart:=true;//trigger control based partpaint mode - 20may2020

   for p:=0 to (winlist.count-1) do
   begin

   i:=winlist.list[p];
   if (i>=0) and (i<icorecount) and zzok(icore[i],7119) then
      begin

      //get
      if imasking then imaskval:=p+1 else imaskval:=-1;
      if icore[i].visible then icore[i].xpaint;//self and all children
      icore[i].xmustpaint:=false;

      end;//i

   end;//p

   except;end;
   end;//if


goto done;


//full paint -------------------------------------------------------------------
fullpaint:

xpartpaint__clear;
xdrawtohost__start(true);
xdrawtohost__addarea(area__make(0,0,iform_width-1,iform_height-1));

//.disable any "part-paint" modes
xmustfull          :=true;
ipaintingpart      :=false;

//.update mask
if      (xwincount<=1) then imasking:=false
else if ((xdragindex<0) or (xdragstart>=0)) and xmustmask then
   begin

//was:   if imask.resize(cw,ch) then//this was actually out-of-sync with ibuffer when window is resized or sized 1st time -> causing mask in some cases to be smaller than ibuffer causing graphic routines to DISABLE mask support!!!! - 28feb2022
   if imask.resize(ibuffer.width,ibuffer.height) then
      begin

      track__inc(satMaskcapture,1);
      imasking:=true;
      imask.cls(0);

      //draw window outlines -> top-down for max. speed
      for p:=(winlist.count-1) downto 0 do
      begin

      i:=winlist.list[p];

      //Special Note: Windows of type "wmFullwin" use a square mask at all times no matter their "rounded" status - 28aug2020
      if xvisible(i) and (i<>xdragstart) then imask.fill2(icore[i].clientarea,p+1,(icore[i].rounded and (icore[i].winstyle<>wmFullwin)));//0=none, 1..255=window layer

      end;//p

      //update mask refs
      winmask_cnt:=winlist.count;

      for p:=0 to (winlist.count-1) do
      begin

      i:=winlist.list[p];

      if (i<>xdragstart) and (i>=0) and (i<icorecount) and zzok(icore[i],7120) then
         begin

         winmask_id[p] :=icore[i].id;
         winmask_aid[p]:=icore[i].aid;
         winmask_vis[p]:=icore[i].visible;
         winmask_rnd[p]:=icore[i].rounded;

         end;

      end;//p

      end;

   end;

//.buffer and mask8 are correctly sized at this point
xfastDrawSync;//25dec2025

//.capture screen into "dragbuffer" - 17may2020
if imasking and (xdragindex>=0) and (xdragstart>=0) then
   begin

   //init
   track__inc(satDragcapture,1);

   idragstart        :=-1;//turn off
   isizestart        :=-1;//turn off
   idragbufferRef64  :=add64(slowms64,30000);//retain buffer size for 30s

   //size "idragbuffer" using "ibuffer", as "ibuffer" is usually oversized - 07apr2026
   if (idragbuffer.width<>ibuffer.width) or (idragbuffer.height<>ibuffer.height) then missize(idragbuffer,ibuffer.width,ibuffer.height);

   //redraw screen without the "drag form" painted
   if not xdragfast then
      begin

      dfull0;
      dfull1(xdragindex,false);
      dfull2(xdragindex,false);

      end;

   //capture
   fd__select( fdTemp );
   fd__defaults;
   fd__setbuffer( fd_buffer ,idragbuffer );
   fd__setbuffer( fd_buffer2 ,ibuffer );
   fd__render( fd_drawRGB );

   //switch back to fdControls
   fd__select( fdControls );

   end;

//.fullpaint -> in "drag buffer" mode
if imasking and (xdragindex>=0) and (idragbuffer.width>=cw) and (idragbuffer.height>=ch) then
   begin

   //init -> note: 1-based, e.g. background=layer0, window0=layer1, window3=layer4, window254=layer255 (last window/layer) - 17may2020
   track__inc(satDragpaint,1);

   if (xdraglayer=-1) then int1:=iwinlimit else int1:=xdraglayer+1;

   //.sa
   if (xdragstart>=0) then sa:=area__make(0,0,cw-1,ch-1)
   else
      begin

      sa           :=idragrect;
      sa.left      :=frcrange32(sa.left,0,cw-1);
      sa.right     :=frcrange32(sa.right,sa.left,cw-1);
      sa.top       :=frcrange32(sa.top,0,ch-1);
      sa.bottom    :=frcrange32(sa.bottom,sa.top,ch-1);

      end;

   //.da
   da              :=area__make(0,0,cw-1,ch-1);

   //draw: bottom.window...(drag.window-1)
   xfd__renderBelowDragWindow_nochecks( sa ,int1 );//05jan2026

   //.drag.window
   if (xdragindex>=0) and xvisible(xdragindex) then
      begin

      imaskval     :=-1;//20may2020

      //paint drag window
      icore[xdragindex].xpaint;

      da           :=icore[xdragindex].paintarea;

      end;


   //.note: sa needs to adapt to larger area of both "original sa" and
   //       output "da" to correctly paint area on screen for dragging movement
   //       etc -> now allows for a single window ontop of base window, which
   //       previously failed to repaint ALL the edge areas in a timely
   //       manner -> now does - 28jul2020

   sa.left         :=frcrange32(smallest32(sa.left,da.left),0,cw-1);
   sa.right        :=frcrange32(largest32(sa.right,da.right),da.left,cw-1);
   sa.top          :=frcrange32(smallest32(sa.top,da.top),0,ch-1);
   sa.bottom       :=frcrange32(largest32(sa.bottom,da.bottom),da.top,ch-1);

   //.(drag.window+1)..254 -> this part only works if "imask" is active "imasking=true" - 17may2020
   //was: if (int1<iwinlimit) and (int1<xtoplayer) and imasking then
   if imasking and (int1<iwinlimit) and (int1<=xtoplayer) then//fixed 25feb2021
      begin

      xfd__renderAboveDragWindow_nochecks( sa ,int1 );//05jan2026

      end;

   //.idragrect
   idragrect       :=da;
   xdragpaintarea  :=sa;
   xdragpaintareaok:=true;

   end

//.fullpaint -> in normal "paint entire screen" mode
else
   begin

   //xref:=slowms64;//xxxxxxxxxxxx
   track__inc(satFullpaint,1);

   dfull0;
   dfull2(0,true);

   end;


goto done;


//done -------------------------------------------------------------------------
done:


//render finalised pixels to screen - 26dec2025 --------------------------------
if xabort then goto skipend;

//.background animation requires full repaint when animating
if      xback_animationcycle_mustpaint then xrender_fullscreen

//.drag area based render
else if xmustfull and xdragpaintareaok then
   begin

   xdrawtohost(xdragpaintarea);//was: xrender_drag;
   xrender_partscreen;//for dbstatus -> uses areas to map paint

   end

//.full screen render
else if xmustfull                      then xrender_fullscreen

//.part screen render
else                                        xrender_partscreen;//part-paint


//batch draw all modified areas for best sync - 12jan2025
xdrawtohost__renderBufferToForm;


//debug rows -------------------------------------------------------------------
if (system_debugrows_count>=1) then//consumes 0.51 ms on Intel Core i5 2.5 GHz
   begin

   for p:=0 to (system_debugrows_count-1) do if (system_debugrows[p]<>'') then
   begin

   win____GetTextExtentPoint(iform_paintdc,pchar('#asdf897'),8,pa);
   win____TextOut(iform_paintdc,0,p*pa.y,pchar(system_debugrows[p]),low__len32(system_debugrows[p]));

   end;//p

   end;


//debug leak hunters -----------------------------------------------------------
//Note: these items display directly onto the MS Windows tform without using
//      any of Gossamer's systems -> required in order to properly hunt down
//      and isolate any system leaks - 28jan2021
if system_debug and sysleak_show and (iform_handle<>0) then
   begin

   win____GetTextExtentPoint(iform_handle,pchar('#asdf897'),8,pa);
   for p:=0 to high(sysleak_start) do if leak__info(p,str1) then win____TextOut(iform_handle,0,p*pa.y,pchar(str1),low__len32(str1));

   end;

skipend:
except;end;
try


//paintfirst
if xmustfull then ipaintfirst:=true;

//.clean up
if (xline<>nil) then str__free(@xline);

//shrink optional buffers ------------------------------------------------------

//.drag -> shrink after a short delay, for faster reuse
if (xdragindex=-1) and ((idragbuffer.width>1) or (idragbuffer.height>1)) and (slowms64>=idragbufferRef64) then
   begin

   idragbufferRef64:=0;
   missize(idragbuffer,1,1);

   end;

//.mask -> shrink after a short delay, for faster reuse
if not imasking and ((imask.width>1) or (imask.height>1)) and (slowms64>=imaskRef64) then
   begin

   imaskRef64:=0;
   imask.resize(1,1);

   end;


//.reset
imaskval:=-1;

except;end;
try
ipaintingpart:=false;
ipaintbusy:=false;

//postpaint id
if xmustfull then low__irollone(ipostpaint_fullid) else low__irollone(ipostpaint_partid);//post paint id - 05dec2025
low__irollone(ipostpaint_id);

//disable "idragdrop_lastarea" if dragging has ceased
if not idragdrop_dragging then idragdrop_lastarea:=noarea;

except;end;
end;

procedure tbasicsystem.__ontimer(sender:tobject);
begin

if not itiming then
   begin
   itiming:=true;

   try
   xtimer;
   except;end;

   itiming:=false;
   end;

end;

procedure tbasicsystem.__ontimer2(sender:tobject);
begin

try
xtimer;
except;end;

end;

procedure tbasicsystem.pumptimer2;//forceably drive the timer - 15jul2021
begin//Warning: Use of this proc can cause out of order mouse messages etc via the "anext" proc being called simultaneously

app__timers;//24jan2025, 19feb2021
__ontimer2(self);

if (slowms64>=ipumptimer2) then
   begin
   app__processallmessages;
   ipumptimer2:=slowms64+100;
   end;

end;

procedure tbasicsystem.xtimer;//01dec2025
label
   reset_timer_only;
var
   p,cw,ch:longint;
   v64:comp;
   xnormalmode:boolean;
   str1:string;
begin
try

//check
if iclosed or (istable<>0) then exit;

//closing
if gui__closing and (icloselocked<=0) then//07jul2025
   begin

   iclosed:=true;
   exit;

   end;

//init
v64          :=slowms64;
cw           :=frcmin32(iform_width,1);
ch           :=frcmin32(iform_height,1);
xnormalmode  :=not igamemode;

//sysflash - allow to run under gamemode - 01dec2025
if (v64>=sysflash_timer) then
   begin

   sysflash_timer:=v64+700;
   sysflash:=not sysflash;

   end;

//.mustsync - mainform only - 14mar2021, 16aug2020
if vimustsync and (not visyncing) then
   begin

   vimustsync:=false;

   if (app__gui<>nil) then visync;

   alignallnow;
   paintallnow;

   end;

//itimer100
if (v64>=itimer100) then
   begin

   //hint - 25dec2025 ----------------------------------------------------------

   //.turn off
   if (ihintTimeout>=1) then
      begin

      if (not vihint) or (low__len32(ihint)<=4) or (v64>ihintTimeout) then//or (not low__nrw(mousemovexy.x,ihintxy.x,5)) or (not low__nrw(mousemovexy.y,ihintxy.y,5)) then
         begin

         ihintTimeout:=-1;
         paintallnow;

         end;

      end

   //.turn on
   else if vihint and (low__len32(ihint)>=5) and (ihintTimeout>=0) then
      begin

      if (low__moveidle_global>=500) then
         begin

         ihintXY     :=mousemovexy;
         ihintTimeout:=add64(v64,ihintOnsecs*1000);
         paintallnow;

         end;

      end
   //.turn off #2
   else if (ihintTimeout=0) then ihintTimeout:=-1//off

   //.turn off #3
   else if (not vihint) and (ihintTimeout=-2) then ihintTimeout:=-1;//off

   //reset - 09mar2025: fixed, was "itimer1000"!
   itimer100:=v64+100;

   end;

//itimer250
if (v64>=itimer250) then
   begin

   //wound rates
   xwoundcalc(iwoundlastx,iwoundlasty);//30sep2022

   //downidle reset - 03apr2021
   if mousedown then low__resetdowntime;

   //settings check
   if visyssettingsloaded and viprgsettingsloaded and (ialignid>=1) then
      begin

      //show splash
      if (ishowonceref<>0) and (v64<ishowonceref) and showing then
         begin
         ishowonceref:=0;//off
         //show splash on startup
         if visplash and viMaster and mainwindow then xshowsplash else viStartupdone:=true;
         end;

      //splash
      if zzok(isplash,7122) and isplash.xmustclose then
         begin
         freeobj(@isplash);
         viStartupdone:=true;//15nov2023
         end;

      end;

   //xsyncfullscreen - 28jul2020
   xsyncfullscreen;

   //ilastsystem_mustid
   if (ilastsystem_mustid<>system_mustid) then
      begin
      ilastsystem_mustid:=system_mustid;
      if (imustpaint<system_mustpaint) then imustpaint:=system_mustpaint;
      if (imustalign<system_mustalign) then imustalign:=system_mustalign;
      end;

   //ilastsystem_mustidSLOW - used by debug system to optionally paint the screen SLOWLY with debug information rather than racing full speed ahead - 10may2021
   if (v64>=ilastsystem_slowref64) then
      begin

      ilastsystem_slowref64:=v64+1000;

      if (ilastsystem_mustidSLOW<>system_mustidSLOW) then
         begin

         ilastsystem_mustidSLOW:=system_mustidSLOW;
         if (imustpaint<system_mustpaint) then imustpaint:=system_mustpaint;
         if (imustalign<system_mustalign) then imustalign:=system_mustalign;

         end;

      end;


   //.mousemoving - turnoff - 27feb2022
   if iscreenmovingfine and (v64>=iscreenmovingfine64) then iscreenmovingfine:=false;


   //hidecursor - 28feb2022
   if (ihidecursorref>0) then
      begin

      if (ihidecursorref>v64) then//on - hide cursor
         begin

         if (cursor<>scNone) then cursor:=scNone;

         end
      else//off - restore cursor
         begin

         if (cursor=scNone) then cursor:=scArrow;
         ihidecursorref:=0;//06dec2024

         end;

      end;


   //if1_showhelp
   if xnormalmode and if1_showhelp then
      begin

      if1_showhelp:=false;
      low__showhelp(true);

      end;

   //if2_restoredefaults
   if xnormalmode and if2_restoredefaults then
      begin

      iopacitytimer       :=v64;//update immediately
      if2_restoredefaults :=false;

      if (system_blackwhitecount<5) then xdefaults;//at most, five instances of the restore defaults prompt - 09dec2024

      end;

   //reset
   itimer250:=v64+250;

   end;

//find support - host "find" dialog here so as not to lock up wordcore / basicbwp timers - 18feb2023
if xnormalmode and (sysfind_cmd<>'') then
   begin

   if (sysfind_cmd='find.pop') then
      begin

      sysfind_cmd:='';

      if not sysfind_dlgshowing then
         begin

         sysfind_dlgshowing:=true;

         if (sysfind_handler<>0)     then pop_find(sysfind_handler,sysfind_text,sysfind_cmd);
         if (sysfind_cmd='find.pop') then sysfind_cmd:='';//cancel repeats

         sysfind_dlgshowing:=false;

         end;

      end
   else if (sysfind_cmd='find.finished') then
      begin

      sysfind_cmd:='';

      if (sysfind_handler<>0)          then pop_info('Find','Find complete');
      if (sysfind_cmd='find.finished') then sysfind_cmd:='';//cancel repeats

      end;
   end;

//size
if (cw<>iform_width) or (ch<>iform_height) or (vidataid<>ilastdataid) then
   begin

   ilastdataid :=vidataid;//16aug2020
   imustalign  :=2;
   imustpaint  :=2;

   end;

//actionlist
//was: if (iacount>=1) and xhavewaitfocusLOOSE then anext;
if (iacount>=1) then anext;//this allows non-focused windows to still react to hover events etc - 19apr2021

//children timer's
if (icorecount>=1) then
   begin

   for p:=0 to (icorecount-1) do if zzok(icore[p],5000+p) then icore[p].xtimer;

   end;


//interval ---------------------------------------------------------------------
low__timerdelay(self,__ontimer,xtimerinterval);

//drag and drop
if idragdrop_dragging and (not mousedown) then
   begin

   dragdrop_stop(str1);

   end;

if dragdrop_mustpaint then
   begin

   if (imustpaint<1) then imustpaint:=1;//now support partial paint -> was "2" => full paint
   app__turbo;//smooth drop mode - 26jul2021

   end;


//background mananger timer/animation handler
if xnormalmode and ibackgroundmanager.xmusttimer and (not dragging) and (not resizing) then ibackgroundmanager.xtimer;


//xmustpaint
if (imustpaint>=1) or (imustalign>=1) or ibackgroundmanager.mustpaint(false) then
   begin

   if xnormalmode then form__paintnow;

   end;


//.timer1000
if (v64>=itimer1000) then
   begin

   //safearea - 28aug2020
   xsafearea;

   //fps tracking - 02dec2024
   ifps      :=ifpscount;
   ifpscount :=0;

   //force refresh and render rates to be current - 01apr2026
   fd__renderfps;
   fd__rendermps;

   //dpi change checker - 10dec2025
   if (not visyncing) and xdpiChanged then vimustsync:=true;

   //reset
   itimer1000:=add64(v64,1000);

   end;

//.timer5000
if (v64>=itimer5000) then
   begin

   //iform_sizecheckcount -> used to detect wonky "Maximise" and "Full Screen" actions under Mac and Linux via Wine - 09sep2025
   iform_sizecheckcount:=0;

   //reset
   itimer5000:=add64(v64,5000);

   end;


//external timer link - 28jul2020  "istable<=1" => was "not icreating"
if (not iontimerbusy) and (istable<>1) and assigned(fontimer) and (not iontimerbusy) then
   begin

   iontimerbusy:=true;
   try;fontimer(self);except;end;
   iontimerbusy:=false;

   end;

//xoptions_mustcrosssync - 26feb2022
if ishowoptions_crosssync and (not visyncing) and (not vimustsync) then
   begin

   ishowoptions_crosssync:=false;
   xshowoptions_crosssync;

   end;

//isnapshot64
if (isnapshot64<>0) and (v64>=isnapshot64) then
   begin

   isnapshot64:=0;
   xsnapshot_make;

   end;

//.automatic opacity
if (v64>=iopacitytimer) and (ipaintfirst or (not xnormalmode)) then
   begin

   iopacitytimer:=v64+200;
   xsync_opacity;

   end;


//leak__hunt(-1,'sys.xtimer');
except;end;
end;

procedure tbasicsystem.xsync_opacity;//02dec2024: streamlined viopacityspeed
const
   m=100;
var
   xspeed100,l,sv,dv:longint;
   xmustupdate:boolean;
begin
try
//check
if (iform_handle=0) or (not app__cansetwindowalpha) or (not showing) then exit;

//init
xmustupdate:=false;

//get
if active then
   begin
   sv:=frcrange32(viunfocusedopacity,30,255)*m;
   dv:=frcrange32(vifocusedopacity,50,255)*m;
   end
else
   begin
   sv:=frcrange32(vifocusedopacity,50,255)*m;
   dv:=frcrange32(viunfocusedopacity,30,255)*m;
   end;

//black and white mode override
if (system_blackwhitecount>=1) then
   begin
   sv:=255*m;
   dv:=255*m;
   end;

//detect changes and adjust on-the-fly
if low__setstr(ilastopacityref,intstr32(system_blackwhitecount)+'|'+intstr32(viopacityspeed)+'|'+intstr32(viunfocusedopacity)+'|'+intstr32(vifocusedopacity)) then
   begin
   case viopacityspeed of
   10:xspeed100:=1;
    9:xspeed100:=3;
    8:xspeed100:=5;
    7:xspeed100:=8;
    6:xspeed100:=10;
    5:xspeed100:=15;
    4:xspeed100:=20;
    3:xspeed100:=25;
    2:xspeed100:=30;
   else xspeed100:=45;
   end;

   ilastopacitystep:=frcmin32( (largest32(dv,sv)-smallest32(dv,sv)) div frcmin32(xspeed100,1) ,1);

   if      (ilastopacity100x<smallest32(sv,dv)) then ilastopacity100x:=smallest32(sv,dv)
   else if (ilastopacity100x>largest32(sv,dv))  then ilastopacity100x:=largest32(sv,dv);

   xmustupdate:=true;
   end;

//set
if (ilastopacity100x<>dv) or xmustupdate then
   begin
   l:=ilastopacity100x;
   if      (dv>l) then l:=frcmax32(l+ilastopacitystep,dv)
   else if (dv<l) then l:=frcmin32(l-ilastopacitystep,dv);

   ilastopacity100x:=frcrange32(l,30*m,255*m);
   app__setwindowalpha(iform_handle,ilastopacity100x div m);
   iopacitytimer:=slowms64+20;//faster turn around
   app__turbo;
   end;

except;end;
end;

procedure tbasicsystem.hidecursor;//28feb2022
begin
ihidecursorref:=slowms64+2000;
end;

procedure tbasicsystem.showcursor;//28feb2022
begin
ihidecursorref:=1;
end;

function tbasicsystem.showingcursor:boolean;//06dec2024
begin
if      (ihidecursorref=0) then result:=(iform_handle<>0) and (cursor<>scNone)
else if (ihidecursorref=1) then result:=true//visible OR about to be
else                            result:=false;//not visible OR about to be
end;

function tbasicsystem.xtimerinterval:longint;
begin
if app__turboOK then result:=1 else result:=50;
end;

//new handlers -----------------------------------------------------------------
function tbasicsystem.nfullwin:tbasicscroll;
begin

result               :=tbasicscroll.create(self);

if (result=nil) then exit;

result.winstyle       :=wmfullwin;
result.oroundstyle    :=corRound;
result.oborderstyle   :=bsSystem100;
result.owinresizeable :=true;//25feb2021

result.xhelp;//every normal window has help by default
result.xsetclientarea(area__make(0,0,0,0));

result.help           :=programslogan;//10mar2021
focuscontrol          :=result;

end;

function tbasicsystem.nwindow(da:twinrect):tbasicscroll;
begin

result                :=tbasicscroll.create(self);

if (result=nil) then exit;

result.winstyle       :=wmwindow;
result.oroundstyle    :=corRound;
result.oborderstyle   :=bsSystem100;
result.owinresizeable :=true;//25feb2021

result.xhelp;//every normal window has help by default
result.xsetclientarea(da);

result.help           :=programslogan;//10mar2021
focuscontrol          :=result;

end;

function tbasicsystem.nontop(da:twinrect):tbasicscroll;
begin

result                :=tbasicscroll.create(self);

if (result=nil) then exit;

result.winstyle       :=wmontop;
result.oroundstyle    :=corRound;
result.oborderstyle   :=bsSystem100;
result.owinresizeable :=true;//25feb2021

result.xhelp;//every normal window has help by default
result.xsetclientarea(da);

result.help           :=programslogan;//10mar2021
focuscontrol          :=result;

end;

function tbasicsystem.nsetcolor(da:twinrect;xshowhead:boolean):tbasicsetcolor;//27feb2021
begin
result:=nsetcolor2(da,xshowhead,false);
end;

function tbasicsystem.nsetcolor2(da:twinrect;xshowhead,xuse32:boolean):tbasicsetcolor;//17nov2023
begin
result:=tbasicsetcolor.create(self,xuse32,xshowhead);
if (result=nil) then exit;
result.makedlg3(da,tepColor24,'Color',xshowhead,true,500,0);
end;

function tbasicsystem.ndlg(da:twinrect;xshowhead:boolean):tbasicscroll;
begin
result:=ndlg2(da,xshowhead,true);
end;

function tbasicsystem.ndlg2(da:twinrect;xshowhead,xstatic:boolean):tbasicscroll;
begin
result:=ndlg3(da,tepnone,'',xshowhead,xstatic);
end;

function tbasicsystem.ndlg3(da:twinrect;xtep:longint;xtitle:string;xshowhead,xstatic:boolean):tbasicscroll;
begin
result                   :=tbasicscroll.create(self);

if (result=nil) then exit;

result.winstyle          :=wmdialog;
result.oroundstyle       :=corRound;
result.oborderstyle      :=bsSystem100;
result.owinresizeable    :=true;//25feb2021
result.mkescape          :=true;
result.mkreturn          :=true;
result.ocode             :=0;//cancelled
result.ocode2            :='';
result.otepcolor         :=clnone;//none
result.otepcolor2        :=clnone;//none - 04dec2025
result.static            :=xstatic;//17aug2020

if xshowhead then
   begin

   if (xtep<>tepnone) then result.xhead.tep:=xtep;
   if (xtitle<>'')    then result.xhead.caption:=xtitle;

   end;

result.xhelp;//every normal window has help by default
result.xsetclientarea(da);

result.help              :=programslogan;//10mar2021
focuscontrol             :=result;

end;

function tbasicsystem.xcommonevent(a:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
begin

//defaults
result:=true;//handled

try

//check
if zznil(a,2299) then exit;

//get
if (xcode2='status.cancel') then istatusstopped:=true;

except;end;
end;

function tbasicsystem.xcommongetitem(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;//04dec2025
begin

//defaults
result:=false;

try
//init
xtab           :='';//none
xtep           :=tepNone;
xcaption       :='';
xcaplabel      :='';
xhelp          :='';
xcode2         :='';
xcode          :=0;
xshortcut      :=aknone;
xindent        :=0;
xenabled       :=false;
xtitle         :=false;
xsep           :=false;
xflash         :=false;
xbold          :=false;

//get
if (istatuswin<>nil) and istatuswin.xhavemenu and (sender=istatuswin.xmenu) then
   begin

   xenabled:=true;

   if (xindex>=0) and (xindex<=high(istatustext)) then
      begin

      xcaption :=istatustext[xindex];
      xtep     :=istatustep[xindex];
      xtab     :=istatustab;

      end;

   result:=true;

   end;

except;end;
end;

procedure tbasicsystem.xstatus_sysstatus_alloff;
begin
//low level support - 04oct2022
sysstatus_fromfile:=-1;
sysstatus_tofile:=-1;
sysstatus_encrypt:=-1;
sysstatus_blaizfolder:=-1;
sysstatus_blaizfolder_setpert:=false;
end;

procedure tbasicsystem.xstatusstart(xrowcount:longint);
begin//note: *=reuse current tab setting - 15may2022
xstatusstart3(xrowcount,'*',true);
end;

procedure tbasicsystem.xstatusstart2(xrowcount:longint;const xtab:string);
begin
xstatusstart3(xrowcount,xtab,true);
end;

procedure tbasicsystem.xstatusstart3(xrowcount:longint;const xtab:string;xresetcancel:boolean);//20may2022
begin
if (xtab<>'') and (xtab<>'*') then istatustab:=xtab;

if xresetcancel then
   begin
   istatusstopped:=false;
   xstatus_sysstatus_alloff;//low level support - 04oct2022
   end;
istatusrowcount:=frcrange32(xrowcount,0,high(istatustext)+1);
istatustime:=slowms64;
end;

procedure tbasicsystem.xstatustab(const xtab:string);
begin
istatustab:=xtab;
end;

function tbasicsystem.getstatusstopped:boolean;
begin
result:=istatusstopped;

if (not result) and ((istatuswin<>nil) and (not istatuswin.visible)) then
   begin
   istatusstopped:=true;
   result:=istatusstopped;
   end;
end;

function tbasicsystem.getstatustext(xindex:longint):string;
begin
if (xindex>=0) and (xindex<=high(istatustext)) then result:=istatustext[xindex] else result:='';
end;

procedure tbasicsystem.setstatustext(xindex:longint;x:string);
begin
if (xindex>=0) and (xindex<=high(istatustext)) then istatustext[xindex]:=x;
end;

function tbasicsystem.getstatustep(xindex:longint):longint;
begin
if (xindex>=0) and (xindex<=high(istatustext)) then result:=istatustep[xindex] else result:=tepNone;
end;

procedure tbasicsystem.setstatustep(xindex:longint;x:longint);
begin
if (xindex>=0) and (xindex<=high(istatustext)) then istatustep[xindex]:=x;
end;

procedure tbasicsystem.xstatusstop;
begin
__xstatus(istatuspert,istatustitle,false,false);
end;

procedure tbasicsystem.xstatus(xpert:double;xtitle:string);
begin
__xstatus(xpert,xtitle,true,false);
end;

procedure tbasicsystem.setstatuspert(xpert:double);
begin
__xstatus(xpert,xstatustitle,true,false);
end;

procedure tbasicsystem.xstatuspaintnow;
begin
if (istatuswin<>nil) then
   begin
   istatuswin.xhead.caption:=istatustitle;
   istatuswin.xtoolbar2.bpert2['status.cancel']:=istatuspert;
   istatuswin.xmenu.paintimmediate;
   end;
end;

procedure tbasicsystem.__xstatus(xpert:double;xtitle:string;xshow,xupdatenow:boolean);
begin
try
//range
if (xpert<0) then xpert:=0 else if (xpert>100) then xpert:=100;
//get
istatuspert:=xpert;
if (xtitle<>'*') then istatustitle:=strdefb(xtitle,'Status');//"*"=reuse current title - 15may2022

//adjust - 16may2022
if xshow and (istatuswin<>nil) then
   begin
   if (istatuswin.xmenu.countx<>istatusrowcount) then
      begin
      xupdatenow:=true;
      istatuswin.xmenu.makelistx(istatusrowcount);
      istatuswin.makeautohigh;
      end;
   end;

//set
case xshow of
true:begin

   xstatusstart3(istatusrowcount,'*',false);

   if (istatuswin=nil) then
      begin

      //lock
      inc(ishowaitcount);//20jun2021
      closelock;
      xwaitfocus;//set us as the current waitfocus -> causes all other "tbasicsystem's" to cancel any of their active wait tasks - 03par2021

      //finalise mouse
      amouseupfinalise;

      //create
      istatuswin:=nstatus(istatustitle);
      istatuswin.xmenu.orowcount:=istatusrowcount;
      istatuswin.xmenu.ofast:=true;
      istatuswin.xmenu.orows:=true;
      istatuswin.xmenu.oautoheight:=false;//true;
      istatuswin.xmenu.makelistx(istatusrowcount);
      istatuswin.xmenu.oautoclose:=false;
      istatuswin.xtoolbar2.hcsadd('Cancel',tepStop20,100,'status.cancel','Cancel task',-100);
      istatuswin.xtoolbar2.onclick2:=xcommonevent;
      istatuswin.makeautohigh;
      focuscontrol:=istatuswin.xtoolbar2;

      //.events
      istatuswin.xmenu.ongetitem:=xcommongetitem;

      //update
      xupdatenow:=true;

      end;

   //.update by time
   if (slowms64>=istatustime) then
      begin

      xupdatenow   :=true;
      istatustime  :=slowms64+200;

      end;

   //.update
   if xupdatenow then
      begin

      istatuswin.xmenu.paintnow;
      istatuswin.xhead.caption:=istatustitle;
      istatuswin.xtoolbar2.bpert2['status.cancel']:=istatuspert;

      end;
   end;
else begin

   if (istatuswin<>nil) then
      begin

      istatuswin.visible :=false;
      winfocus           :=istatuswin.tag;

      freeobj(@istatuswin);
      closeunlock;//close unlock

      ishowaitcount      :=frcmin32(ishowaitcount-1,0);//20jun2021

      end;

   //low level support - 04oct2022
   xstatus_sysstatus_alloff;

   end;
end;//case

//update system
pumptimer2;

except;end;
end;

function tbasicsystem.nstatus(xtitle:string):tbasicscroll;
const
   xcancelcap='';
var
   dw,dh:longint;
   da:twinrect;
begin

//defaults
result                 :=nil;

try
//get
result                 :=tbasicscroll.create(self);
result.tag             :=winfocus;//remember previous focus
result.winstyle        :=wmdialog;
result.oroundstyle     :=corRound;
result.oborderstyle    :=bsSystem50;
result.owinresizeable  :=false;//25feb2021
result.mkescape        :=true;
result.mkreturn        :=false;//02aug2021
result.ocode           :=0;//cancelled
result.ocode2          :='';
result.otepcolor       :=clnone;//none
result.otepcolor2      :=clnone;//none - 04dec2025
result.static          :=true;
result.help            :=programslogan;//10mar2021

if (xtitle<>'') then
   begin

   result.xhead.caption:=xtitle;
   result.xhead.makeWinhead__status_small;
   result.xgrad;//27dec2024

   end;

result.xhelp;//every normal window has help by default
result.oautoheight     :=true;

//.da
gui__scale3(400,320,100,50,dw,dh);//11dec2025

da.left                :=(width-dw) div 2;
da.top                 :=(height-dh) div 2;
da.right               :=da.left+dw-1;
da.bottom              :=da.top+dh-1;

result.xsetclientarea(da);

except;end;
end;

function tbasicsystem.nscroll(da:twinrect):tbasicscroll;
begin
result:=tbasicscroll.create(self);
if (result=nil) then exit;
result.xsetclientarea(da);
end;

//pop handlers -----------------------------------------------------------------
procedure tbasicsystem.xsafepopXYWHex(var dx,dy,dw,dh:longint;dy2:longint);//15NOV2010
label//Note: works within the user's workarea
   redo;
var
   once:boolean;
begin
try
//get
dw:=frcrange32(dw,16,iform_width);
dh:=frcrange32(dh,16,iform_height);
once:=true;
//set
if (dx<=0) then dx:=0 else if ((dx+dw)>iform_width) then dx:=iform_width-dw;
//..y
redo:
if (dy<=0) then dy:=0;
if ((dy+dh)>iform_height) then
   begin
   //.sy2 - optional fallback position
   if once and (dy2<>max32) then
      begin
      once:=false;
      dy:=dy2;
      goto redo;
      end;
   //set
   dy:=iform_height-dh;
   end;
except;end;
end;

function tbasicsystem.xhavewaitfocusLOOSE:boolean;//06apr2021
begin//Yes, "syswait_focus=nil" is valid -> esentially we assume we have focus control if "syswait_focus" is not set to a valid control other than ourselves hence the nil=ok=no other control has taken waitfocus - 06apr2021
result:=(syswait_focus=nil) or (syswait_focus=self);
end;

procedure tbasicsystem.xwaitfocus;
begin
syswait_focus:=self;
end;

function tbasicsystem.xshowwait(a:tbasicscroll;xpreviouscontrol:tbasiccontrol;xpreviousfocus:longint):boolean;
begin
result:=xshowwait2(a,xpreviouscontrol,xpreviousfocus,0);
end;

function tbasicsystem.xshowwait2(a:tbasicscroll;xpreviouscontrol:tbasiccontrol;xpreviousfocus,xtimeout:longint):boolean;
begin
result:=xshowwait3(a,xpreviouscontrol,xpreviousfocus,xtimeout,true);
end;

function tbasicsystem.xshowwait3(a:tbasicscroll;xpreviouscontrol:tbasiccontrol;xpreviousfocus,xtimeout:longint;xlimitsize:boolean):boolean;//09dec2024
var//Note: xlimitsize=true=window can't be larger than actual screen so limit it's size to the screen or less - 08mar2021
   //Now supports "non-softclose" mode override when in Black and White mode (system_blackwhitecount>=1) - 09dec2024
   xautoclose:comp;
begin

//defaults
result      :=false;

try
//check
if zznil(a,2297) or (not showing) then exit;//28jul2021

//lock
inc(ishowaitcount);//20jun2021
closelock;
xwaitfocus;//set us as the current waitfocus -> causes all other "tbasicsystem's" to cancel any of their active wait tasks - 03par2021

//finalise mouse
amouseupfinalise;

//init
if (xtimeout>=1) then xautoclose:=slowms64+xtimeout else xautoclose:=0;
if xlimitsize then a.xlimitsize;

//.force focus if it's been lost - 19mar2025
winfocus    :=a.coreindex;

//get
while true do
begin

//shutdown -> was "idestroying" -> "istable>=2"
if (istable>=2) or gui__closing or (not xhavewaitfocusLOOSE) then break;//03apr2021

//window has been closed
if (not a.visible) or (a.stable<>0) or (istable<>0) then break;

//soft close -> ignore if system is in Black and White mode - 11dec2024
if ( (visoftclose and (system_blackwhitecount<=0)) or a.osoftclose) and (iwinfocus<>a.coreindex) then break;

//.autoclose
if (xautoclose>=1) and (slowms64>=xautoclose) then break;

//keep system alive
__ontimer2(self);

//fixed -> OK now - 05may2021
app__rootWaitAndMessages;

end;//with

//return result
result      :=(a.ocode>=1);

except;end;
try

hint__none;
a.visible   :=false;
winfocus    :=xpreviousfocus;

if (xpreviouscontrol<>nil) then focuscontrol:=xpreviouscontrol;//18feb2023

closeunlock;//close unlock
ishowaitcount:=frcmin32(ishowaitcount-1,0);//20jun2021

except;end;
end;

function tbasicsystem.xpopwait(a:tbasicscroll;xpreviousfocus,dw,dh:longint;xcenter:boolean):boolean;//21may2020
begin
result:=xpopwait2(a,nil,xpreviousfocus,dw,dh,xcenter);
end;

function tbasicsystem.xpopwait2(a:tbasicscroll;xcontrol:tbasiccontrol;xpreviousfocus,dw,dh:longint;xcenter:boolean):boolean;//21may2020
var//Note: xcontrol is optional, if set, then "a" pops below or aboe "xcontrol" like a dropdown list - 04oct2020
   dx,dy,dy2:longint;
   b:tpoint;
begin//Align "d" on screen ready to pop based on "s" position or "sx,sy"

//defaults
result      :=false;

//check
if zznil(a,2298) or (not showing) then exit;//28jul2021

try

//init
a.mkescape  :=true;
a.mkreturn  :=false;//must click a menu item instead

//range
dw          :=frcmin32(dw,(2*a.findbordersize)+a.ominwidth);
dh          :=frcmin32(dh,(2*a.findbordersize)+a.ominheight);

//init
b           :=downcurpos;//stops mouse up drift -> slight delay between mouse up and menu display can result in menu being placed in the wrong place -> this function locks the position in at the point of the mouse being clicked down - 29mar2020
dx          :=b.x;
dy          :=b.y;
dy2         :=b.y-dh;

if xcenter then
   begin

   dx       :=(iform_width-dw) div 2;
   dy       :=(iform_height-dh) div 2;
   dy2      :=dy;

   end

else if zzok(xcontrol,7130) and xcontrol.visibletohost then
   begin

   dx       :=xcontrol.clientarea.left;
   dy       :=xcontrol.clientarea.bottom;
   dw       :=frcmin32(dw,xcontrol.clientarea.right-xcontrol.clientarea.left);

   end;

//get
xsafepopXYWHex(dx,dy,dw,dh,dy2);

if a.setbounds(dx,dy,dw,dh) then a.alignnow;

//set
result      :=xshowwait(a,nil,xpreviousfocus);

except;end;
end;

procedure tbasicsystem.xclose(a:tbasiccontrol);
var
   b:tbasiccontrol;
begin

if zzok(a,7131) and a.xwindow(b) then b.visible:=false;

end;

procedure tbasicsystem.xcloseok(a:tbasiccontrol);
var
   b:tbasiccontrol;
begin

if zzok(a,7132) and a.xwindow(b) then
   begin

   b.ocode  :=1;//OK
   b.visible:=false;

   end;

end;

function tbasicsystem.popint(var xval:longint;xmin,xmax,xdef:longint;xtep32:longint;xtitle,xcap,xhelp,xcancelcap,xokcap:string;xsize:longint):boolean;
var
   a:tbasicscroll;
   b:tsimpleint;
   da:twinrect;
   xpreviousfocus,dw,dh:longint;
begin

//defaults
result           :=false;
a                :=nil;

try
//init
xpreviousfocus   :=winfocus;

if (xsize<=0) then xsize:=100;

dw               :=round(350*(xsize/100));
dh               :=320;

//was: low__winzoom(dw,dh);//17mar2021
gui__scale4(1.1 ,dw ,dh ,0 ,0 ,dw ,dh );//11dec2025


da.left          :=(width-dw) div 2;
da.top           :=(height-dh) div 2;
da.right         :=da.left+dw-1;
da.bottom        :=da.top+dh-1;

//get
a                :=ndlg(da,false);
a.oborderstyle   :=bsSystem50;
a.static         :=true;
a.oautoheight    :=true;
a.xhead.caption  :=strdefb(xtitle,'Query');

//.tep
if (xtep32=tepNone) then xtep32:=tepQuery24;

a.xhead.tep      :=xtep32;
a.xhelp;

b                :=a.mint(xcap,xhelp,xmin,xmax,xdef,xval);

with a.xtoolbar2 do
begin

cadd(strdefb(xcancelcap,ntranslate('Cancel')),tepClose20,0,scdlg,rthtranslate('Cancel'),120);
cadd(strdefb(xokcap,ntranslate('OK')),tepYes20,1,scdlg,rthtranslate('OK'),0);

end;//with

//set
a.makeautohigh;
focuscontrol     :=b;
result           :=xshowwait(a,nil,xpreviousfocus);

if result then xval:=b.val;

except;end;

//free
freeobj(@a);

end;

function tbasicsystem.popfind(xhandler:longint;var xtext,xcmd:string):boolean;
var
   a:tbasicscroll;
   b:tbasicedit;
   da:twinrect;
   xpreviousfocus,dw,dh:longint;
   xpreviouscontrol:tbasiccontrol;
begin

//defaults
result             :=false;
a                  :=nil;

try
//init
xpreviousfocus     :=winfocus;
xpreviouscontrol   :=focuscontrol;

//.reset
sysfind_cmd        :='';
sysfind_handler    :=xhandler;

//was: dw:=300;dh:=320;low__winzoom(dw,dh);//17mar2021
gui__scale4(1.1,300,320,0,0,dw,dh);//11dec2025

da.left            :=(width-dw) div 2;
da.top             :=(height-dh) div 2;
da.right           :=da.left+dw-1;
da.bottom          :=da.top+dh-1;

//get
a                  :=ndlg(da,false);
a.oborderstyle     :=bsSystem50;
a.static           :=true;
a.oautoheight      :=true;
a.xhead.caption    :='Find';

//.tep
a.xhead.tep        :=tepInfo24;
a.xhelp;
a.nlabel('Find Text','');

b                  :=a.nedit('','Find Text');
b.value            :=xtext;
b.makefind;

with a.xtoolbar2 do
begin

cadd(ntranslate('Cancel'),tepClose20,0,scdlg,rthtranslate('Cancel'),600);
cadd(ntranslate('Find'),tepNext20,1,scfind,rthtranslate('Find text'),0);

end;//with

//set
a.makeautohigh;

focuscontrol       :=b;
result             :=xshowwait(a,xpreviouscontrol,xpreviousfocus);

if result then
   begin

   xtext           :=b.value;
   sysfind_cmd     :='find';

   end;

except;end;

//free
freeobj(@a);

end;

function tbasicsystem.poppass(var x:string;xcap,xhelp:string):boolean;
begin
result:=popedit3(x,tepNone,'',xcap,xhelp,'','',0,true);
end;

function tbasicsystem.popedit(var x:string;xcap,xhelp:string):boolean;
begin
result:=popedit2(x,tepNone,'',xcap,xhelp,'','',0);
end;

function tbasicsystem.popedit_small(var x:string;xcap,xhelp:string):boolean;
begin
result:=popedit2(x,tepNone,'',xcap,xhelp,'','',50);
end;

function tbasicsystem.popedit2(var x:string;xtep32:longint;xtitle,xcap,xhelp,xcancelcap,xokcap:string;xsize:longint):boolean;
begin
result:=popedit3(x,xtep32,xtitle,xcap,xhelp,xcancelcap,xokcap,xsize,false);
end;

function tbasicsystem.popedit3(var x:string;xtep32:longint;xtitle,xcap,xhelp,xcancelcap,xokcap:string;xsize:longint;xpassword:boolean):boolean;
var
   a:tbasicscroll;
   b:tbasicedit;
   da:twinrect;
   xpreviousfocus,dw,dh:longint;
   xpreviouscontrol:tbasiccontrol;
begin

//defaults
result            :=false;
a                 :=nil;

try
//init
xpreviousfocus    :=winfocus;
xpreviouscontrol  :=focuscontrol;

//init
if (xsize<=0) then xsize:=100;
gui__scale2( round(550*(xsize/100)), 320, dw, dh);

da.left           :=(width-dw) div 2;
da.top            :=(height-dh) div 2;
da.right          :=da.left+dw-1;
da.bottom         :=da.top+dh-1;

//get
a                 :=ndlg(da,false);
a.oborderstyle    :=bsSystem50;
a.static          :=true;
a.oautoheight     :=true;
a.xhead.caption   :=strdefb(xtitle,'Query');
a.xgrad;

//.tep
if (xtep32=tepNone) then xtep32:=tepQuery24;

a.xhead.tep       :=xtep32;
a.xhelp;
a.nlabel(xcap,xhelp);

b                 :=a.nedit('',xhelp);
if xpassword then b.makepass;
b.value           :=x;

with a.xtoolbar2 do
begin

cadd(strdefb(xcancelcap,ntranslate('Cancel')),tepClose20,0,scdlg,rthtranslate('Cancel'),120);
cadd(strdefb(xokcap,ntranslate('OK')),tepYes20,1,scdlg,rthtranslate('OK'),0);

end;//with

//set
a.makeautohigh;
focuscontrol      :=b;

result            :=xshowwait(a,xpreviouscontrol,xpreviousfocus);
if result then x:=b.value;

except;end;

//free
freeobj(@a);

end;

function tbasicsystem.popmanyedit2(xcount:longint;var x:array of string;xtep32:longint;xtitle:string;xcap:array of string;xhelp:array of string;xcancelcap,xokcap:string;xsize:longint):boolean;
var
   a:tinputcolorise;
begin
a.use:=false;
result:=popmanyedit3(xcount,x,xtep32,xtitle,xcap,xhelp,[a],xcancelcap,xokcap,xsize);
end;

function tbasicsystem.popmanyedit3(xcount:longint;var x:array of string;xtep32:longint;xtitle:string;xcap:array of string;xhelp:array of string;xcolorise:array of tinputcolorise;xcancelcap,xokcap:string;xsize:longint):boolean;
var
   a:tbasicscroll;
   b:array[0..99] of tbasicedit;
   da:twinrect;
   p,xpreviousfocus,dw,dh:longint;
   xpreviouscontrol:tbasiccontrol;
begin
//defaults
result           :=false;
xpreviousfocus   :=winfocus;
xpreviouscontrol :=focuscontrol;
a                :=nil;

try
//check
if (low(x)<>0) or (xcount<=0) then exit;

//init
xcount           :=frcmax32(xcount,high(x)+1);
if (xsize<=0) then xsize:=100;

dw               :=round(550*(xsize/100));
dh               :=320;
//was:low__winzoom(dw,dh);//17mar2021
gui__scale4(1.1,dw,dh,0,0,dw,dh);

da.left          :=(width-dw) div 2;
da.top           :=(height-dh) div 2;
da.right         :=da.left+dw-1;
da.bottom        :=da.top+dh-1;

//get
a                :=ndlg(da,false);
a.oborderstyle   :=bsSystem50;
a.static         :=true;
a.oautoheight    :=true;
a.xhead.caption  :=strdefb(xtitle,'Query');

//.tep
if (xtep32=tepNone) then xtep32:=tepIcon24;//17auh2025

a.xhead.tep      :=xtep32;
a.xhelp;

for p:=0 to (xcount-1) do
begin

with a.nlabel(xcap[p],xhelp[p]) do
begin

osepv            :=low__aorb(2,5,p>=1)*vizoom;
normal           :=false;

end;//with

b[p]             :=a.nedit('',xhelp[p]);
b[p].value       :=x[p];

//.input colorise info
if (p<=high(xcolorise)) and xcolorise[p].use then b[p].oinputcolorise:=xcolorise[p];

end;//p

with a.xtoolbar2 do
begin

cadd(strdefb(xcancelcap,ntranslate('Cancel')),tepClose20,0,scdlg,rthtranslate('Cancel'),120);
cadd(strdefb(xokcap,ntranslate('OK')),tepYes20,1,scdlg,rthtranslate('OK'),0);

end;//with

//set
a.makeautohigh;
focuscontrol     :=b[0];
result           :=xshowwait(a,xpreviouscontrol,xpreviousfocus);

if result then
   begin

   for p:=0 to (xcount-1) do x[p]:=b[p].value;

   end;

except;end;

//free
freeobj(@a);

end;

procedure tbasicsystem.poptxt0(x:string;const xfont2:boolean);//for display purposes only - 15sep2025
begin
poptxt3(x,0,false,true,xfont2,'','','','');
end;

procedure tbasicsystem.poptxt02(x,xcap:string;const xfont2:boolean);//for display purposes only - 15sep2025
begin
poptxt3(x,0,false,true,xfont2,xcap,'','','');
end;

function tbasicsystem.poptxt(var x:string;xwrap:longint;const xfont2:boolean;const xcap,xhelp:string):boolean;
begin
result:=poptxt3(x,xwrap,false,false,xfont2,xcap,xhelp,'','');
end;

function tbasicsystem.poptxt2(var x:string;xwrap:longint;xreadonly,xfont2:boolean;const xcap,xhelp:string):boolean;
begin
result:=poptxt3(x,xwrap,false,xreadonly,xfont2,xcap,xhelp,'','');
end;

function tbasicsystem.poptxt3(var x:string;xwrap:longint;xrows,xreadonly,xfont2:boolean;const xcap,xhelp,xcancelcap,xokcap:string):boolean;
begin
result:=poptxt4(x,xwrap,xrows,xreadonly,xfont2,xcap,xhelp,xcancelcap,xokcap,'',1,1);
end;

function tbasicsystem.poptxt4(var x:string;xwrap:longint;xrows,xreadonly,xfont2:boolean;const xcap,xhelp,xcancelcap,xokcap,xstyle:string;xscaleW,xscaleH:single):boolean;
var
   a:tstr8;
begin

//defaults
result      :=false;
a           :=nil;

try

//init
a           :=str__new8;
a.text      :=x;

//get
if poptxt82(a,xwrap,xrows,xreadonly,xfont2,xcap,xhelp,xcancelcap,xokcap,xstyle,xscaleW,xscaleH) then
   begin

   x        :=a.text;
   result   :=true;

   end;
except;end;

//free
str__free(@a);

end;

function tbasicsystem.poptxt8(xtext:tstr8;xwrap:longint;xrows,xreadonly,xfont2:boolean;const xcap,xhelp,xcancelcap,xokcap,xstyle:string):boolean;//12jan2025
begin
result:=poptxt82(xtext,xwrap,xrows,xreadonly,xfont2,xcap,xhelp,xcancelcap,xokcap,xstyle,1,1);
end;

function tbasicsystem.poptxt82(xtext:tstr8;xwrap:longint;xrows,xreadonly,xfont2:boolean;const xcap,xhelp,xcancelcap,xokcap,xstyle:string;xscaleW,xscaleH:single):boolean;//12jan2025
var
   a:tbasicscroll;
   b:tbasicbwp;
   da:twinrect;
   xpreviousfocus,dw,dh:longint;
   xpreviouscontrol:tbasiccontrol;
begin

//defaults
result               :=false;
a                    :=nil;

try
//init
xpreviousfocus       :=winfocus;
xpreviouscontrol     :=focuscontrol;
str__lock(@xtext);

//was: dw:=550;dh:=450;low__winzoom(dw,dh);//17mar2021
gui__scale4(1.1,550,450,0,0,dw,dh);//11dec2025

//.scale
dw                   :=frcmin32(round(dw*xscaleW),100);
dh                   :=frcmin32(round(dh*xscaleH),100);

da.left              :=(width-dw) div 2;
da.top               :=(height-dh) div 2;
da.right             :=da.left+dw-1;
da.bottom            :=da.top+dh-1;

//get
a                    :=ndlg(da,false);
a.mkreturn           :=false;//we need the return key for the text box - 11mar2021
a.static             :=true;
a.xhead.caption      :=strdefb(xcap,'Text');
a.xhead.tep          :=tepIcon24;
a.xhelp;
a.xgrad;
a.xhead.add('Edit',tepEdit20,0,'edit','Show edit menu');


//retain data for later down - 17mar2021
if      strmatch(xstyle,'plaintext')  then b:=a.nbwp5(xhelp,xtext,xwrap,xrows,true,true,false,false,true,true,0,1)//plain text using GUI font (usually Arial)
else if strmatch(xstyle,'plaintext2') then b:=a.nbwp5(xhelp,xtext,xwrap,xrows,true,true,false,false,true,true,0,2)//plain text using secondary font (usually Courier New)
else                                       b:=a.nbwp5(xhelp,xtext,xwrap,xrows,true,true,false,false,true,false,0,0);//default wordcore settings

if xfont2 then
   begin

   b.core.onefontname:=font_name2;//????????????????????
   b.core.onefontsize:=1;

   end
else
   begin

   b.core.onefontsize   :=0;//system font size - 05sep2025

   end;

b.oreadonly          :=xreadonly;

with a.xtoolbar2 do
begin

cadd(strdefb(xcancelcap,ntranslate('Cancel')),tepClose20,0,scdlg,rthtranslate('Cancel'),300);//5m
cadd(strdefb(xokcap,ntranslate('OK')),tepYes20,1,scdlg,rthtranslate('OK'),0);

end;//with

//init
b.revertinit(xtext,true);
b.undoon;//18jun2022

//events
a.xhead.setbc14(a,b,nil,nil);
a.xhead.onclick2     :=poptxt__event2;

//set
focuscontrol         :=b;
result               :=xshowwait(a,xpreviouscontrol,xpreviousfocus);

if result and zzok(xtext,7134) then
   begin

   xtext.clear;
   b.iogettxt(xtext);

   end;

except;end;

//free
freeobj(@a);
str__uaf(@xtext);

end;

function tbasicsystem.poptxt__event2(a:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
begin
result:=true;//handled

//check
if zznil(a,2299) then exit;
//get
if (xcode2='edit') and sbwpok(a.bc2) then sbwp(a.bc2).showmenu;
end;

function tbasicsystem.popquery(const x:string):boolean;
begin

result:=popquery2(x,'','',false);

end;

function tbasicsystem.popqueryAndConfirm(const x:string):boolean;//22apr2026
begin

result:=popquery(x) and popquery('Last chance to cancel?');

end;

function tbasicsystem.popquery1(const xtitle,x:string):boolean;
begin
result:=popquery20(xtitle,x,'','',false);
end;

function tbasicsystem.popquery2(const x,xcancelcap,xokcap:string;const xlarge:boolean):boolean;
begin
result:=popqueryex(x,xcancelcap,xokcap,low__aorb(380,550,xlarge),low__aorb(230,320,xlarge),60,0);
end;

function tbasicsystem.popquery20(const xtitle,x,xcancelcap,xokcap:string;const xlarge:boolean):boolean;
begin
result:=popqueryex2(xtitle,x,xcancelcap,xokcap,low__aorb(380,550,xlarge),low__aorb(230,320,xlarge),60,0);
end;

function tbasicsystem.popquery21(const x,xcancelcap,xokcap:string;const xlarge,xOKtime:boolean):boolean;
begin
result:=popquery22('',x,xcancelcap,xokcap,xlarge,xOKtime);
end;

function tbasicsystem.popquery22(const xtitle,x,xcancelcap,xokcap:string;const xlarge,xOKtime:boolean):boolean;
begin
result:=popqueryex2(xtitle,x,xcancelcap,xokcap,low__aorb(380,550,xlarge),low__aorb(230,320,xlarge),insint(60,not xOKtime),insint(60,xOKtime));
end;

function tbasicsystem.popqueryex(const x,xcancelcap,xokcap:string;const dw,dh,ccancel,cok:longint):boolean;
begin
result:=popqueryex2('',x,xcancelcap,xokcap,dw,dh,ccancel,cok);
end;

function tbasicsystem.popqueryex2(xtitle,x,xcancelcap,xokcap:string;dw,dh,ccancel,cok:longint):boolean;//11dec2025
var
   a:tbasicscroll;
   da:twinrect;
   xpreviousfocus:longint;
   xpreviouscontrol:tbasiccontrol;
begin

//defaults
result            :=false;
a                 :=nil;

try
//init
xpreviousfocus    :=winfocus;
xpreviouscontrol  :=focuscontrol;

gui__scale3(dw,dh,50,50,dw,dh);//11dec2025

da.left           :=(width-dw) div 2;
da.top            :=(height-dh) div 2;
da.right          :=da.left+dw-1;
da.bottom         :=da.top+dh-1;

//get
a                 :=ndlg(da,false);
a.oborderstyle    :=bsSystem50;
a.static          :=true;
a.xhead.caption   :=strdefb(xtitle,'Query');
a.xhead.tep       :=tepQuery24;
a.xhelp;
a.xgrad;//09dec2024
a.nbwp('Query message',str__newaf8b(x)).makeviewonly;

with a.xtoolbar2 do
begin

cadd(strdefb(xcancelcap,ntranslate('Cancel')),tepClose20,0,scdlg,rthtranslate('Cancel'),ccancel);
cadd(strdefb(xokcap,ntranslate('OK')),tepYes20,1,scdlg,rthtranslate('OK'),cok);

end;//with

//set
result            :=xshowwait(a,xpreviouscontrol,xpreviousfocus);

except;end;

//free
freeobj(@a);

end;

function tbasicsystem.pop_replaceall_skipall(xtitle,xfilename:string):longint;
var
   a:tbasicscroll;
   da:twinrect;
   dw,dh,xpreviousfocus:longint;
   xpreviouscontrol:tbasiccontrol;
begin
//defaults
result                :=0;//0=cancel, 1=skip all, 2=replace all
a                     :=nil;

try
//init
xpreviousfocus        :=winfocus;
xpreviouscontrol      :=focuscontrol;
//init
//was:dw:=400;dh:=200;low__winzoom2(dw,dh,50,50);//17mar2021
gui__scale4(1.1 ,400 ,200 ,50 ,50 ,dw ,dh );//11dec2025

da.left               :=(width-dw) div 2;
da.top                :=(height-dh) div 2;
da.right              :=da.left+dw-1;
da.bottom             :=da.top+dh-1;

//get
a                     :=ndlg(da,false);
a.oborderstyle        :=bsSystem50;
a.static              :=true;
a.xhead.caption       :=strdefb(xtitle,'Replace File');
a.xhead.tep           :=tepQuery24;
a.xhelp;
a.xgrad;//09dec2024
a.nbwp('',str__newaf8b(xfilename)).makeviewonly;

with a.xtoolbar2 do
begin

cadd(ntranslate('Replace All'),tepYes20,2,scdlg,rthtranslate('Replace all files'),0);
cadd(ntranslate('Skip All'),tepClose20,1,scdlg,rthtranslate('Skip all files'),0);
cadd(ntranslate('Cancel'),tepStop20,0,scdlg,rthtranslate('Cancel'),-120);

end;//with

//set
if xshowwait(a,xpreviouscontrol,xpreviousfocus) then result:=a.ocode;

except;end;

//free
freeobj(@a);

end;

function tbasicsystem.popmsg(xtitle,x:string):boolean;//23jul2024
begin
result:=poperrorORinfo2(xtitle,x,'',350,200,60,true,false);
end;

function tbasicsystem.popinfo(xtitle,x:string):boolean;
begin
result:=popinfo2(xtitle,x,'',false);
end;

function tbasicsystem.popinfo2(xtitle,x,xclosecap:string;xlarge:boolean):boolean;
begin
result:=popinfoex(xtitle,x,xclosecap,low__aorb(350,550,xlarge),low__aorb(200,320,xlarge),60);
end;

function tbasicsystem.popinfoex(xtitle,x,xclosecap:string;dw,dh,cclose:longint):boolean;
begin
result:=poperrorORinfo(xtitle,x,xclosecap,dw,dh,cclose,true);
end;

function tbasicsystem.poperror(xtitle,x:string):boolean;
begin
result:=poperror2(xtitle,x,'',false);
end;

function tbasicsystem.poperror2(xtitle,x,xclosecap:string;xlarge:boolean):boolean;
begin
result:=poperrorex(xtitle,x,xclosecap,low__aorb(350,550,xlarge),low__aorb(200,320,xlarge),60);
end;

function tbasicsystem.poperrorex(xtitle,x,xclosecap:string;dw,dh,cclose:longint):boolean;
begin
result:=poperrorORinfo(xtitle,x,xclosecap,dw,dh,cclose,false);
end;

function tbasicsystem.poperrorORinfo(xtitle,x,xclosecap:string;dw,dh,cclose:longint;xinfo:boolean):boolean;//03jun2021
begin
result:=poperrorORinfo2(xtitle,x,xclosecap,dw,dh,cclose,xinfo,true);
end;

function tbasicsystem.poperrorORinfo2(xtitle,x,xclosecap:string;dw,dh,cclose:longint;xinfo,xshowicon:boolean):boolean;//11dec2025, 23jul2024
var
   a:tbasicscroll;
   da:twinrect;
   xpreviousfocus:longint;
   xpreviouscontrol:tbasiccontrol;
begin

//defaults
result                :=false;
a                     :=nil;

try
//init
xpreviousfocus        :=winfocus;
xpreviouscontrol      :=focuscontrol;

//was: low__winzoom2(dw,dh,50,50);//17mar2021
gui__scale4(1.1,dw,dh,50,50,dw,dh);//11dec2025

da.left               :=(width-dw) div 2;
da.top                :=(height-dh) div 2;
da.right              :=da.left+dw-1;
da.bottom             :=da.top+dh-1;

//get
a                     :=ndlg(da,false);
a.oborderstyle        :=bsSystem50;
a.static              :=true;

if xinfo then
   begin

   a.xhead.caption    :=strdefb(xtitle,'Information');//03jun2021
   a.xhead.tep        :=low__aorb(tepNone,tepInfo24,xshowicon);
   a.xhelp;
   a.xgrad;//09dec2024

   a.nbwp('Information',str__newaf8b(x)).makeviewonly;

   end
else
   begin

   a.xhead.caption    :=strdefb(xtitle,'Error');//11oct2020
   a.xhead.tep        :=low__aorb(tepNone,tepError24,xshowicon);
   a.xhelp;
   a.xgrad;//09dec2024
   a.nbwp('Error message',str__newaf8b(x)).makeviewonly;

   end;

with a.xtoolbar2 do
begin

cadd(strdefb(xclosecap,ntranslate('Close')),tepYes20,1,scdlg,rthtranslate('Close'),cclose);

end;

//set
result:=xshowwait(a,xpreviouscontrol,xpreviousfocus);

except;end;

//free
freeobj(@a);

end;

function tbasicsystem.popstatus(xmsg:string;xshowsec:longint):boolean;//based on font size - 11dec2025, 19jul2024: oshadeback=true, 03jnov2023
const
   xpad='WWW';

var
   a:tbasicscroll;
   dlabel:tbasictitle;
   da:twinrect;
   dw,dh,xpreviousfocus:longint;
   xpreviouscontrol:tbasiccontrol;

begin

//defaults
result                    :=false;
a                         :=nil;

try
//init
xpreviousfocus            :=winfocus;
xpreviouscontrol          :=focuscontrol;
da                        :=area__make(0,0,0,0);

if (xshowsec=0) then xshowsec:=2;
xshowsec                  :=frcmin32(xshowsec,1)*1000;


//get
a                         :=ndlg(da,false);
a.ominheight              :=0;
a.oborderstyle            :=bsSystem20;
a.static                  :=true;
a.xhelp.showhelp          :=false;

dlabel:=a.nlabel(xmsg,'');
with dlabel do
begin

oautoheight               :=true;
ocentertext               :=true;//19nov2023
oshadeback                :=true;//19jul2024

end;//with

//width + height -> based on text and font.size
dh                        :=trunc(dlabel.getalignheight(0)*2);
dw                        :=frcmin32( fast__textwidth('',xpad+xmsg+xpad,dlabel.info.Rfn), scale__px0(300) ) + (2*a.findbordersize);
da.left                   :=(width  - dw) div 2;
da.top                    :=(height - dh) div 2;
da.right                  :=da.left+dw-1;
da.bottom                 :=da.top+dh-1;

a.xsetclientarea(da);

//set
result                 :=xshowwait2(a,xpreviouscontrol,xpreviousfocus,xshowsec);

except;end;

//free
freeobj(@a);

end;

function tbasicsystem.popmenu(xpopstyle,ximagealign:longint;xmenudata:tstr8;var xcode:longint;var xcode2:string;var xtepcolor:longint):boolean;
var
   xoutpos,xouthover,xoutselstart,xoutselcount:longint;
begin
result:=popmenu3(xpopstyle,ximagealign,xmenudata,nil,0,0,-1,0,0,xoutpos,xouthover,xoutselstart,xoutselcount,xcode,xcode2,xtepcolor);
end;

function tbasicsystem.popmenu2(xpopstyle,ximagealign:longint;xmenudata:tstr8;xmenuname:string;xstyle:longint;var xcode:longint;var xcode2:string;var xtepcolor:longint):boolean;
begin
result:=popmenu2b(xpopstyle,ximagealign,xmenudata,nil,xmenuname,xstyle,xcode,xcode2,xtepcolor);
end;

function tbasicsystem.popmenu2b(xpopstyle,ximagealign:longint;xmenudata:tstr8;xcontrol:tbasiccontrol;xmenuname:string;xstyle:longint;var xcode:longint;var xcode2:string;var xtepcolor:longint):boolean;
label
   skipend;
var//Special Note: menu position is remembered for next time when use clicks a menu item - 31mar2020
   int1,int2,int3,int4,i,p:longint;
   xref:comp;
   xok:boolean;
begin

//defaults
result     :=false;
xcode      :=0;
xcode2     :='';
xtepcolor  :=clnone;

try
//check
if not str__lock(@xmenudata) then exit;

//do not remember
if (xmenuname='') then
   begin

   result:=popmenu3(xpopstyle,ximagealign,xmenudata,nil,xstyle,0,-1,0,0,int1,int2,int3,int4,xcode,xcode2,xtepcolor);
   goto skipend;

   end;

//remember
xok        :=false;
i          :=0;
xmenuname  :=strlow(xmenuname);

//.find existing
if not xok then
   begin

   for p:=0 to high(sysmenu_name) do if (xmenuname=sysmenu_name[p]) then
      begin

      sysmenu_ref64[p] :=slowms64;
      i                :=p;
      xok              :=true;

      break;

      end;//p

   end;

//.find new
if not xok then
   begin

   //get
   xok   :=true;
   xref  :=max64;

   for p:=0 to high(sysmenu_name) do if (sysmenu_ref64[p]<xref) then
      begin

      xref :=sysmenu_ref64[p];
      i    :=p;

      end;//p

   //set
   sysmenu_name[i]       :=xmenuname;
   sysmenu_pos[i]        :=0;
   sysmenu_hover[i]      :=-1;
   sysmenu_selstart[i]   :=0;
   sysmenu_selcount[i]   :=0;//none
   sysmenu_ref64[i]      :=slowms64;

   end;

//pop
result:=popmenu3(xpopstyle,ximagealign,xmenudata,nil,xstyle,sysmenu_pos[i],sysmenu_hover[i],sysmenu_selstart[i],sysmenu_selcount[i],int1,int2,int3,int4,xcode,xcode2,xtepcolor);

if result then
   begin
   sysmenu_pos[i]       :=int1;
   sysmenu_hover[i]     :=int2;
   sysmenu_selstart[i]  :=int3;
   sysmenu_selcount[i]  :=int4;
   end;

skipend:
except;end;

//free
str__uaf(@xmenudata);

end;

function tbasicsystem.popmenu3(xpopstyle,ximagealign:longint;xmenudata:tstr8;xcontrol:tbasiccontrol;xstyle,xpos,xhover,xselstart,xselcount:longint;var xoutpos,xouthover,xoutselstart,xoutselcount,xcode:longint;var xcode2:string;var xtepcolor:longint):boolean;
begin
result:=popmenu4(xpopstyle,ximagealign,xmenudata,xcontrol,true,xstyle,0,xpos,xhover,xselstart,xselcount,xoutpos,xouthover,xoutselstart,xoutselcount,xcode,xcode2,xtepcolor);
end;

function tbasicsystem.popmenu4(xpopstyle,ximagealign:longint;xmenudata:tstr8;xcontrol:tbasiccontrol;xshowhelp:boolean;xstyle,xdropcount,xpos,xhover,xselstart,xselcount:longint;var xoutpos,xouthover,xoutselstart,xoutselcount,xcode:longint;var xcode2:string;var xtepcolor:longint):boolean;
begin
result:=popmenu5(xpopstyle,ximagealign,xmenudata,xcontrol,xshowhelp,xstyle,xdropcount,xpos,xhover,xselstart,xselcount,xoutpos,xouthover,xoutselstart,xoutselcount,xcode,xcode2,xtepcolor,'');
end;

function tbasicsystem.popmenu5(xpopstyle,ximagealign:longint;xmenudata:tstr8;xcontrol:tbasiccontrol;xshowhelp:boolean;xstyle,xdropcount,xpos,xhover,xselstart,xselcount:longint;var xoutpos,xouthover,xoutselstart,xoutselcount,xcode:longint;var xcode2:string;var xtepcolor:longint;xfindbycode2:string):boolean;//13apr2025, 18mar2025, 07jul2021
label
   skipend;
var
   a:tbasicscroll;
   xpreviousfocus,int1,int2,xindex:longint;
   xpreviouscontrol:tbasiccontrol;
   xminwidth:boolean;
begin

//defaults
result:=false;

try
//init
xpreviousfocus    :=winfocus;
xpreviouscontrol  :=focuscontrol;
xoutpos           :=0;
xouthover         :=-1;
xoutselstart      :=0;
xoutselcount      :=0;
xcode             :=0;//none
xcode2            :='';
xtepcolor         :=clnone;
xshowhelp         :=xshowhelp and vihelp;//syncs with "tbasichelp's" own internal setting checker - 14mar2021
a                 :=nil;

str__lock(@xmenudata);

//check
if (low__menucount(xmenudata)<=0) then goto skipend;

//special options
xminwidth:=true;

if (xpopstyle=pmNarrow) then
   begin
   xminwidth:=false;
   end;

//init
a                 :=ndlg(area__make(0,0,1,1),false);
a.owinresizeable  :=false;//08mar2021
a.osafearea       :=false;//29aug2020
a.osoftclose      :=true;//force "softclose" mode for menus always - 03apr2021

if (xstyle=lslist) and zzok(xcontrol,7135) then
   begin
   a.oborderstyle:=bsSystem20;
   end
else a.oborderstyle:=bsSystem50;//50% - 29aug2020

a.ominwidth       :=low__insint(48,xminwidth)+(2*a.findbordersize);
a.xhelp.showhelp  :=xshowhelp;//19mar2021
a.xmenu.orowcount :=frcmin32(xdropcount,0);
a.xmenu.bordersize:=0;
a.xmenu.ostyle    :=frcrange32(xstyle,0,2);//lsmenu(0)..lsmany(2)
a.xmenu.oimagealign:=ximagealign;

if      (a.xmenu.ostyle=lsmenu)  then a.xmenu.makemenu
else if (a.xmenu.ostyle=lslist)  then a.xmenu.makepoplist
else if (a.xmenu.ostyle=lspanel) then a.xmenu.makepoplist
else if (a.xmenu.ostyle=lsmany)  then a.xmenu.makepopmany;

a.xmenu.data:=xmenudata;//allowed -> takes a copy

//.optional -> highlight item in list by searching for "xcode2" via "xfindbycode2" - 07jul2021
if (xfindbycode2<>'') and a.xmenu.xfindbycode2(xfindbycode2,xindex) then
   begin
   a.xmenu.itemindex:=xindex;
   end
else
   begin
   a.xmenu.pos:=frcmin32(xpos,0);//07jul2021
   a.xmenu.xsetsel(xselstart,xselcount);
   end;

a.xmenu.hoverindex:=xhover;
a.xmenu.oautofocus:=true;

//int1 + int2
int1:=2*a.findbordersize;
if a.xhavehead then inc(int1,a.xhead.getalignheight(0));//here just incase it's ever used - 01mar2021
if a.xhavehelp and xshowhelp then int2:=a.xhelp.getalignheight(0) else int2:=0;

//.focus the control -> provides wheel ++ support to control - 21may2020
focuscontrol:=a.xmenu;

//get
if xpopwait2(a,xcontrol,xpreviousfocus,int1+a.xmenu.getalignwidth(0),int1+a.xmenu.getalignheight(0)+int2,false) then
   begin

   xoutpos           :=a.xmenu.pos;
   xouthover         :=a.xmenu.hoverindex;
   xoutselstart      :=a.xmenu.selstart;
   xoutselcount      :=a.xmenu.selcount;
   xcode             :=a.xmenu.ocode;
   xcode2            :=a.xmenu.ocode2;
   xtepcolor         :=a.xmenu.otepcolor;//02mar2021

   result:=(xcode<>0) or (xcode2<>'');//13apr2025

   end;

//popshortcut -> user executed a shortcut (doesn't matter if it exists or not) -> menu has been closed and the shortcut, now feed stored shortcut back to host form for execution - 02apr2020


//18mar2025: restore previous focus
if (xpreviouscontrol<>nil) then focuscontrol:=xpreviouscontrol;

skipend:
except;end;

//free
freeobj(@a);
str__uaf(@xmenudata);

end;

function tbasicsystem.popfont(var xfontname:string):boolean;//26mar2022
begin
result:=popfont2(xfontname,true,true,false,false,nil);
end;

function tbasicsystem.popfont2(var xfontname:string;xscreen,xprinter,xspecial,xaslist:boolean;xpopcontrol:tbasiccontrol):boolean;//05jun2025, 15nov2023
label
   skipdone;
var
   a:tbasicscroll;
   b:tbasicmenu;
   da:twinrect;
   xtepcolor,xcode,int1,xpos,xcount,xpreviousfocus,dw,dh:longint;
   xcode2:string;
   xlist,xline,xpoplist:tstr8;
   xpreviouscontrol:tbasiccontrol;
begin

//defaults
result                :=false;
a                     :=nil;

try
//init
xpreviousfocus        :=winfocus;
xpreviouscontrol      :=focuscontrol;
xlist                 :=nil;
xline                 :=nil;
xpoplist              :=nil;

//was:dw:=400;dh:=320;low__winzoom(dw,dh);//17mar2021
gui__scale4(1.1,400,320,0,0,dw,dh);//11dec2025

da.left               :=(width-dw) div 2;
da.top                :=(height-dh) div 2;
da.right              :=da.left+dw-1;
da.bottom             :=da.top+dh-1;

xlist                 :=str__new8;
xline                 :=str__new8;
xpoplist              :=str__new8;

low__menuinit(xpoplist);
font__list2(@xlist,xscreen,xprinter,xspecial);

//get
xpos                  :=0;
xcount                :=0;

while true do
begin

if not low__nextline0(xlist,xline,xpos) then break;
low__menuadd(xpoplist,tepFNew20,clnone,xline.text,'Select font',xline.text,xcount,aknone,0,false,true,false,false);
inc(xcount);

end;//while

low__menuend(xpoplist);

//.show as a menu list
if xaslist then
   begin

   if popmenu2b(pmNormal,iaNormal,xpoplist,xpopcontrol,'popfont2',0,xcode,xcode2,xtepcolor) then
      begin

      xfontname :=xcode2;
      result    :=true;

      end;

   goto skipdone;

   end;

//.show as a window
a                     :=ndlg(da,false);
a.oborderstyle        :=bsSystem50;
//a.static:=true;
a.oautoheight         :=true;
a.xhead.caption       :='Font';

//.tep
a.xhead.tep           :=tepIcon24;
a.xgrad;//12jan2025
a.xhelp;
//a.nlabel(xcap,xhelp);

b                     :=a.nlist('','Select a font',xpoplist,16);//05jun2025
b.xfindbycode2(xfontname,int1);
b.itemindex           :=int1;
b.onumberfrom         :=0;

with a.xtoolbar2 do
begin

cadd(ntranslate('Cancel'),tepClose20,0,scdlg,rthtranslate('Cancel'),120);
cadd(ntranslate('OK'),tepYes20,1,scdlg,rthtranslate('OK'),0);

end;//with

//show
a.makeautohigh;
focuscontrol          :=b;
result                :=xshowwait(a,xpreviouscontrol,xpreviousfocus);

if result then xfontname:=b.xgetval2(b.itemindex);

skipdone:
except;end;

//free
freeobj(@a);
freeobj(@xline);
freeobj(@xlist);
freeobj(@xpoplist);

end;

function tbasicsystem.popdroplist(xmenudata:tstr8;xcontrol:tbasiccontrol;var xpos,xcode:longint;var xcode2:string;xfindbycode2:string):boolean;
begin
result:=popdroplist2(xmenudata,xcontrol,0,xpos,xcode,xcode2,xfindbycode2);
end;

function tbasicsystem.popdroplist2(xmenudata:tstr8;xcontrol:tbasiccontrol;xdropcount:longint;var xpos,xcode:longint;var xcode2:string;xfindbycode2:string):boolean;
var
   xoutpos,xouthover,xoutselstart,xoutselcount,xtepcolor:longint;
begin
result:=false;

try
xdropcount:=frcmin32(xdropcount,0);
result:=popmenu5(pmNormal,iaNormal,xmenudata,xcontrol,false,lslist,xdropcount,xpos,xpos,xpos,1,xoutpos,xouthover,xoutselstart,xoutselcount,xcode,xcode2,xtepcolor,xfindbycode2);
if result then xpos:=frcmin32(xoutselstart,0);
except;end;
end;

function tbasicsystem.popopenimg(var xfilename:string;var xfilterindex:longint;xcommonfolder:string):boolean;//12apr2021
var
   daction,xfilterlist:string;
begin
result:=false;
daction:='';

try
//filterlist
xfilterlist:=
peallimgs+
pepng+
pegif+
{$ifdef jpeg}pejpg+pejif+pejpeg+petj32+{$endif}

pebmp+
pedib+//14may2025
peico+pecur+peani+
petea+
petga+//18mar2025
peppm+//18mar2025
pepgm+//18mar2025
pepbm+//18mar2025
pepnm+//18mar2025
pexbm+
peimg32+//27jul2024
pesan+//16sep2025
{$ifdef gamecore}pepic8+{$endif}//16sep2025
perle6+
perle8+
perle32+
peany;

//get
result:=xpopnav3(xfilename,xfilterindex,xfilterlist,strdefb(xcommonfolder,low__platimages),'open','','Open Image',daction,true);
except;end;
end;

function tbasicsystem.popsaveimg(var xfilename:string;xcommonfolder:string;var daction:string):boolean;//12apr2021
begin
result:=popsaveimg2(xfilename,xcommonfolder,'',daction);
end;

function tbasicsystem.popsaveimg2(var xfilename:string;xcommonfolder,xtitle2:string;var daction:string):boolean;//18jun2021, 12apr2021
begin
result:=popsaveimg3(xfilename,xcommonfolder,xtitle2,false,false,daction);
end;

function tbasicsystem.popsaveimg3(var xfilename:string;xcommonfolder,xtitle2:string;xanimationformats,xlossless:boolean;var daction:string):boolean;//08nov2025, 18jun2021, 12apr2021
var
   xfilterindex:longint;
   xfilterlist:string;
begin
result:=false;

try
//filterlist
xfilterindex:=0;

if xanimationformats then//08nov2025
   begin
   xfilterlist:=
   peani+
   pegif+
   {$ifdef jpeg}petj32+{$endif}
   pesan+//16sep2025
   peimg32;//27jul2024
   end
else if xlossless then
   begin
   xfilterlist:=
   pepng+
   pebmp+
   pedib+
   petea+
   petga+//18mar2025
   peppm+//18mar2025
   pepnm+//18mar2025
   pesan+//16sep2025
   {$ifdef gamecore}pepic8+{$endif}//16sep2025
   perle6+//06mar2026
   perle8+//25feb2026
   perle32+//05mar2026
   peimg32;//27jul2024
   end
else
   begin
   xfilterlist:=
   pepng+
   pegif+
   {$ifdef jpeg}pejpg+pejif+pejpeg+petj32+{$endif}
   pebmp+
   pedib+
   peico+pecur+peani+
   petea+
   petga+//18mar2025
   peppm+//18mar2025
   pepgm+//18mar2025
   pepbm+//18mar2025
   pepnm+//18mar2025
   pexbm+
   pesan+//16sep2025
   {$ifdef gamecore}pepic8+{$endif}//16sep2025
   perle6+//06mar2026
   perle8+//25feb2026
   perle32+//05mar2026
   peimg32;//27jul2024
   end;

//get
result:=xpopnav3(xfilename,xfilterindex,xfilterlist,strdefb(xcommonfolder,low__platimages),'save','','Save Image'+xtitle2,daction,true);
except;end;
end;

function tbasicsystem.popopencur(var xfilename:string;var xfilterindex:longint;xcommonfolder:string;xmore:boolean):boolean;//29aug2021
var
   daction,xfilterlist:string;
   xcanpreview:boolean;
begin
result:=false;

try
daction:='';
xcanpreview:=false;
//filterlist
xfilterlist:=
peallcurs+
pecur+
peani;

if xmore then
   begin
   xcanpreview:=true;
   xfilterlist:=
   peallcurs2+
   pecur+
   peani+
   peico+
   pepng+
   pegif+
   petea+
   peimg32+
   {$ifdef gamecore}pepic8+{$endif}
   perle6+//06mar2026
   perle8+
   perle32+//05mar2026
   pesan;
   end;

//get
result:=xpopnav3(xfilename,xfilterindex,xfilterlist,strdefb(xcommonfolder,low__platfolder('cursors')),'open','','Open Cursor',daction,xcanpreview);
except;end;
end;

function tbasicsystem.popopen(var xfilename:string;var xfilterindex:longint;xfilterlist,xcommonfolder:string):boolean;
begin
result:=popopen2(xfilename,xfilterindex,xfilterlist,xcommonfolder,'');
end;

function tbasicsystem.popopen2(var xfilename:string;var xfilterindex:longint;xfilterlist,xcommonfolder,xtitle2:string):boolean;
begin
result:=popopen3(xfilename,xfilterindex,xfilterlist,xcommonfolder,xtitle2,false);
end;

function tbasicsystem.popopen3(var xfilename:string;var xfilterindex:longint;xfilterlist,xcommonfolder,xtitle2:string;xcanpreview:boolean):boolean;
var
   daction:string;
begin
daction:='';
result:=xpopnav3(xfilename,xfilterindex,xfilterlist,xcommonfolder,'open','','Open'+insstr(#32,xtitle2<>'')+xtitle2,daction,xcanpreview);
end;

function tbasicsystem.popsave(var xfilename:string;xfilterlist,xcommonfolder:string;var daction:string):boolean;
begin
result:=popsave2(xfilename,xfilterlist,xcommonfolder,'',daction);
end;

function tbasicsystem.popsave2(var xfilename:string;xfilterlist,xcommonfolder,xtitle2:string;var daction:string):boolean;
begin
result:=popsave3(xfilename,xfilterlist,xcommonfolder,xtitle2,daction,false);
end;

function tbasicsystem.popsave3(var xfilename:string;xfilterlist,xcommonfolder,xtitle2:string;var daction:string;xcanpreview:boolean):boolean;
var
   xfilterindex:longint;
begin
xfilterindex:=0;
result:=xpopnav3(xfilename,xfilterindex,xfilterlist,xcommonfolder,'save','','Save'+insstr(#32,xtitle2<>'')+xtitle2,daction,xcanpreview);
end;

function tbasicsystem.popfolder(var xfilename:string;const xcommonfolder:string):boolean;
begin
result:=popfolder2(xfilename,'',xcommonfolder,false,false);
end;

function tbasicsystem.popfolder1(var xfilename:string;const xmasklist,xcommonfolder:string):boolean;
begin
result:=popfolder2(xfilename,xmasklist,xcommonfolder,false,false);
end;

function tbasicsystem.popfolder2(var xfilename:string;const xmasklist,xcommonfolder:string;xshowfiles,xcanpreview:boolean):boolean;
var
   int1:longint;
   daction:string;
begin
int1:=0;
daction:='';
result:=xpopnav3(xfilename,int1,xmasklist,xcommonfolder,low__aorbstr('folder','folder2',xshowfiles),'','',daction,xcanpreview);
end;

function tbasicsystem.popnewfolder(xfolder:string;var xoutfolder:string):boolean;//14apr2021
label
   redo;
var
   str1,xname:string;
begin
//defaults
result:=false;

try
xoutfolder:='';
//range
xfolder:=io__asfolderNIL(xfolder);
if (xfolder='') then exit;
//init
xname:='';
redo:
if popedit2(xname,tepNewfolder24,'New Folder','Folder Name','Type a name for the folder','','Create Folder',70) and (xname<>'') then
   begin
   xname:=io__safename(xname);
   str1:=io__asfolder(xfolder+xname);
   case io__makefolder(str1) of
   true:begin
      xoutfolder:=str1;
      result:=true;
      end;
   else begin
      poperror('','Failed to create folder "'+xname+'"');
      goto redo;
      end;
   end;//case
   end;
except;end;
end;

function tbasicsystem.popfolderimg(xfolder:string):boolean;
const
   xhelphead='Folder Image|';
var
   a:tbasicscroll;
   b:tbasictea;
   t2:tbasictoolbar;
   da:twinrect;
   xpreviousfocus,dw,dh:longint;
   xpreviouscontrol:tbasiccontrol;
begin

//defaults
result                   :=false;
a                        :=nil;

try
//init
xpreviousfocus           :=winfocus;
xpreviouscontrol         :=focuscontrol;
xfolder                  :=io__asfoldernil(xfolder);

//was:dw:=500;dh:=320;low__winzoom(dw,dh);//17mar2021
gui__scale4(1.1,420,320,0,0,dw,dh);//11dec2025

da.left                  :=(width-dw) div 2;
da.top                   :=(height-dh) div 2;
da.right                 :=da.left+dw-1;
da.bottom                :=da.top+dh-1;

//get
a                        :=ndlg(da,false);
a.oborderstyle           :=bsSystem50;
a.static                 :=true;
a.oautoheight            :=true;
a.xhead.caption          :='Folder Image';
a.xhead.tep              :=tepFolderimage24;
a.xhelp;

t2:=a.ntoolbar('');
with t2 do
begin
csadd(ntranslate('Undo')     ,tepUndo20   ,0,'tea.undo'   ,rthtranslate(xhelphead+'Undo last change'),0);
csadd(ntranslate('Default')  ,tepRefresh20,0,'tea.default',rthtranslate(xhelphead+'Restore default image'),0);
csadd(ntranslate('Images')   ,tepZoom20,0,'tea.images' ,rthtranslate(xhelphead+'Show list of built-in images'),0);
addsep;
csadd(ntranslate('Open')     ,tepOpen20   ,0,'tea.open'   ,rthtranslate(xhelphead+'Open image from file'),0);
csadd(ntranslate('Save As')  ,tepSave20   ,0,'tea.save'   ,rthtranslate(xhelphead+'Save image to file'),0);
end;

b                        :=a.ntea('Folder Image','Change folder image');
b.odefaultmsg            :='( Default Image In Use )';

//.load image from folder
b.fromfolder(xfolder);


with a.xhead do
begin

cadd(ntranslate('Menu')     ,tepMenu20   ,0,'tea.menu'   ,rthtranslate(xhelphead+'Show menu'),0);
cadd(ntranslate('Copy')     ,tepCopy20   ,0,'tea.copy'   ,rthtranslate(xhelphead+'Copy image to Clipboard'),0);
cadd(ntranslate('Paste')    ,tepPaste20  ,0,'tea.paste'  ,rthtranslate(xhelphead+'Paste image from Clipboard'),0);

end;//with

a.xgrad;

with a.xtoolbar2 do
begin


cadd(ntranslate('Cancel'),tepClose20,0,scdlg,rthtranslate('Cancel'),300);
cadd(ntranslate('OK'),tepYes20,1,scdlg,rthtranslate('OK'),0);

end;//with

//events
a.xhead.onclick2         :=b.xcmd;
a.xtoolbar2.onclick2     :=b.xcmd;
t2.onclick2              :=b.xcmd;

//.handles the button states for selected buttons on these toolbars
b.manage(a.xhead,t2,a.xtoolbar2);

//set
a.makeautohigh;
focuscontrol             :=b;
result:=xshowwait(a,xpreviouscontrol,xpreviousfocus);

//.unmanage
b.unmanage;

//.result -> write image to folder
if result then b.tofolder(xfolder);

except;end;

//free
freeobj(@a);

end;

function tbasicsystem.popfav(var xfilename:string):boolean;
var
   daction:string;
begin
daction:='';
result:=xpopnav(xfilename,'','fav',daction);
end;

function tbasicsystem.popnav(var xfilename:string;xcommonfolder:string):boolean;
var
   daction:string;
begin
daction:='';
result:=xpopnav(xfilename,xcommonfolder,'nav',daction);
end;

function tbasicsystem.xpopnav(var xvalue:string;xcommonfolder,xstyle:string;var daction:string):boolean;
var
   xfilters:string;
   xfilterindex:longint;
begin
xfilterindex:=0;
xfilters:='';
result:=xpopnav2(xvalue,xfilterindex,xfilters,xcommonfolder,xstyle,'','',daction);
end;

function tbasicsystem.xpopnav2(var xvalue:string;var xfilterindex:longint;xfilterlist,xcommonfolder,xstyle,xhisname,xtitle:string;var daction:string):boolean;
begin
result:=xpopnav3(xvalue,xfilterindex,xfilterlist,xcommonfolder,xstyle,xhisname,xtitle,daction,false);
end;

function tbasicsystem.xpopnav3(var xvalue:string;var xfilterindex:longint;xfilterlist,xcommonfolder,xstyle,xhisname,xtitle:string;var daction:string;xcanpreview:boolean):boolean;
label
   redo;
var
   a:tbasicscroll;
   b:tbasicnav;
   da:twinrect;
   xpreviousfocus,dw,dh:longint;
   xpreviouscontrol:tbasiccontrol;
   xcap:string;
begin
//defaults
result:=false;

try
xpreviousfocus:=winfocus;
xpreviouscontrol:=focuscontrol;
a:=nil;
//init
if (xstyle='nav') then
   begin
   dw:=600;
   dh:=550;
   end
else if (xstyle='fav') then
   begin
   dw:=500;
   dh:=450;
   end
else
   begin
   dw:=800;
   dh:=650;//21dec2024 - was: 550;
   end;

//was: low__winzoom(dw,dh);//17mar2021
gui__scale4(1.1 ,dw ,dh ,560 ,0 ,dw ,dh );//11dec2025

da.left:=(width-dw) div 2;
da.top:=(height-dh) div 2;
da.right:=da.left+dw-1;
da.bottom:=da.top+dh-1;

//get
a:=ndlg(da,false);
a.oborderstyle:=bsSystem100;
a.static:=true;
b:=a.nnav;
b.oautoheight:=true;
a.xhelp;
a.xgrad;

//decide
redo:
if      (xstyle='open') then
   begin
   xhisname:=strdefb(xhisname,'opensave');
   xcap:=strdefb(xtitle,'Open');
   b.ohead:=true;
   b.syspreview:=true;//22may2022
   b.canpreview:=xcanpreview;
   b.makeopen;
   b.xfromsys('opensave');
   b.ocommonfolder:=xcommonfolder;
   b.filterlist:=xfilterlist;
   b.filterindex:=xfilterindex;//set BEFORE value - 09mar2021
   b.value:=xvalue;
   b.favfolder:=xvalue;//folder to be added if user clicks "add" -> "add to favs list"
   b.xfocusname;//11feb2023
   end
else if (xstyle='save') then
   begin
   xhisname:=strdefb(xhisname,'opensave');
   xcap:=strdefb(xtitle,'Save As');
   b.ohead:=true;
   b.syspreview:=true;//22may2022
   b.canpreview:=xcanpreview;
   b.makesave;
   b.xfromsys('opensave');
   b.ocommonfolder:=xcommonfolder;
   b.filterlist:=xfilterlist;
   b.filterfromfilename:=xvalue;//18jun2021
//was: b.filterindex:=xfilterindex;//set BEFORE value - 09mar2021
   b.value:=xvalue;
   b.favfolder:=xvalue;//folder to be added if user clicks "add" -> "add to favs list"
   b.xfocusname;//11feb2023
   end
else if (xstyle='folder') or (xstyle='folder2') then
   begin
   xhisname:=strdefb(xhisname,'folder');
   xcap:=strdefb(xtitle,'Select Folder');
   b.ohead:=true;
   if (xstyle='folder2') then
      begin
      b.syspreview:=true;//22may2022
      b.canpreview:=xcanpreview;
      b.makefolder2;
      end
   else b.makefolder;

   //optional: xfilterlist is a "masklist" e.g. "*.txt" - 21mar2025
   if (xfilterlist<>'') then b.omasklist:=xfilterlist;

   b.xfromsys('folder');
   b.ocommonfolder:=xcommonfolder;
   b.value:=xvalue;
   b.favfolder:=xvalue;//folder to be added if user clicks "add" -> "add to favs list"
   end
else if (xstyle='nav') then
   begin
   xhisname:=strdefb(xhisname,'nav');
   xcap:=strdefb(xtitle,'Navigate');
   b.makenav;
   b.xfromsys('nav');
   b.ocommonfolder:=xcommonfolder;
   b.value:=xvalue;
   b.favfolder:=xvalue;//folder to be added if user clicks "add" -> "add to favs list"
   end
else if (xstyle='fav') then
   begin
   xhisname:='';//not used
   xcap:=strdefb(xtitle,'Favourites');
   b.ohead:=true;
   b.makefav;
   b.sortstyle:=nlName;
   b.ocommonfolder:='';
   b.xautoclose(true);
   b.favfolder:=xvalue;//folder to be added if user clicks "add" -> "add to favs list"
   end
else
   begin
   xstyle:='open';
   goto redo;
   end;
//set
if not b.ohead then b.make__backgroundhead;//03dec2023
b.hisname:=xhisname;
a.xhead.caption:=xcap;
result:=xshowwait(a,xpreviouscontrol,xpreviousfocus);
if result then
   begin
   xvalue:=b.value;
   //.daction
   if (b.action<>'') then daction:=ia__add(daction,b.action);
   end;
xfilterindex:=b.filterindex;//always return this even on a "cancel" - 10mar2021
//.sortstyle
if (xstyle='open') or (xstyle='save') then
   begin
   b.xtosys('opensave');
   viSync;
   siSavesyssettings;
   end
else if (xstyle='nav') then
   begin
   b.xtosys('nav');
   viSync;
   siSavesyssettings;
   end
else if (xstyle='folder') or (xstyle='folder2') then
   begin
   if result and (b.selectedfolder<>'') then xvalue:=b.selectedfolder;
   b.xtosys('folder');
   viSync;
   siSavesyssettings;
   end;
except;end;

//free
freeobj(@a);

end;

function tbasicsystem.popcolorstatic(var xvalue:longint):boolean;
var
   m:tstr8;
   xcode,xtepcolor:longint;
   xhelp,xcode2:string;

   procedure xadd(xcap:string;xr,xg,xb:longint);
   begin
   if (xcap='') then xcap:=low__digpad11(xr,3)+'r, '+low__digpad11(xg,3)+'g, '+low__digpad11(xb,3)+'b';
   low__menuitemx2(m,tepColorPal20,rgba0__int(xr,xg,xb),xcap,xhelp,'color',100,aknone,true);
   end;

   procedure xadd2(xcap:string;xshiftby,xr,xg,xb:longint);
   begin
   if (xshiftby<>0) then
      begin
      xr:=frcrange32(xr+xshiftby,0,255);
      xg:=frcrange32(xg+xshiftby,0,255);
      xb:=frcrange32(xb+xshiftby,0,255);
      end;
   if (xcap='') then xcap:=low__digpad11(xr,3)+'r, '+low__digpad11(xg,3)+'g, '+low__digpad11(xb,3)+'b';
   low__menuitemx2(m,tepColorPal20,rgba0__int(xr,xg,xb),xcap,xhelp,'color',100,aknone,true);
   end;
begin
//defaults
result:=false;

try
m:=nil;
xhelp:='Click to use color';
//init
m:=str__new8;
low__menuinit(m);
low__menutitle(m,tepNone,'Static Colors','List of static colors');
xadd('White',255,255,255);
xadd('Silver',192,192,192);
xadd('Gray',128,128,128);
xadd('Black',0,0,0);
//.red
xadd2('Pastel Red',100,255,0,0);
xadd('Red',255,0,0);
xadd2('Red 2',-50,255,0,0);
xadd2('Maroon',-127,255,0,0);
xadd2('Maroon 2',-150,255,0,0);
xadd2('Maroon 3',-200,255,0,0);
//.lime
xadd2('Pastel Lime',100,0,255,0);
xadd('Lime',0,255,0);
xadd2('Lime 2',-50,0,255,0);
xadd2('Green',-127,0,255,0);
xadd2('Green 2',-150,0,255,0);
xadd2('Green 3',-200,0,255,0);
//.blue
xadd2('Pastel Blue',100,0,0,255);
xadd('Blue',0,0,255);
xadd2('Blue',-50,0,0,255);
xadd2('Navy',-127,0,0,255);
xadd2('Navy 2',-150,0,0,255);
xadd2('Navy 3',-200,0,0,255);
//.fuchisa
xadd2('Pastel Fuchisa',100,255,0,255);
xadd('Fuchisa',255,0,255);
xadd2('Fuchisa 2',-50,255,0,255);
xadd2('Purple',-127,255,0,255);
xadd2('Purple 2',-150,255,0,255);
xadd2('Purple 3',-200,255,0,255);
//.yellow
xadd2('Pastel Yellow',100,255,255,0);
xadd('Yellow',255,255,0);
xadd2('Yellow 2',-50,255,255,0);
xadd2('Olive',-127,255,255,0);
xadd2('Olive 2',-150,255,255,0);
xadd2('Olive 3',-200,255,255,0);
//.aqua
xadd2('Pastel Aqua',100,0,255,255);
xadd('Aqua',0,255,255);
xadd2('Aqua 2',-50,0,255,255);
xadd2('Teal',-127,0,255,255);
xadd2('Teal 2',-150,0,255,255);
xadd2('Teal 3',-200,0,255,255);
//.orange
xadd2('Pastel Orange',100,255,128,0);
xadd2('Orange',20,255,128,0);
xadd2('Orange 2',0,255,128,0);
xadd2('Orange 3',-50,255,128,0);
//.pink
xadd2('Pink',20,255,198,255);
xadd2('Pink 2',0,255,198,255);
xadd2('Pink 3',-50,255,198,255);
xadd2('Pink 4',-127,255,198,255);
//.pale blue
xadd2('Sea Blue',60,0,128,255);
xadd2('Sea Blue 2',20,0,128,255);
xadd2('Sea Blue 3',0,0,128,255);
xadd2('Sea Blue 4',-50,0,128,255);
//.natural green
xadd2('Natural Green',60,128,255,0);
xadd2('Natural Green 2',20,128,255,0);
xadd2('Natural Green 3',0,128,255,0);
xadd2('Natural Green 4',-50,128,255,0);
//.lush green
xadd2('Alternative Green',60,128,255,128);
xadd2('Alternative Green 2',20,128,255,128);
xadd2('Alternative Green 3',0,128,255,128);
xadd2('Alternative Green 4',-50,128,255,128);
//.brown
xadd2('Pastel Brown',100,128,64,0);
xadd2('Brown',20,128,64,0);
xadd2('Brown 2',0,128,64,0);
xadd2('Brown 3',-50,128,64,0);
//.alternative pink
xadd2('Alternative Pink',20,255,0,128);
xadd2('Alternative Pink 2',0,255,0,128);
xadd2('Alternative Pink 3',-50,255,0,128);
//.alternative purple
xadd2('Alternative Purple',50,128,0,255);
xadd2('Alternative Purple 2',0,128,0,255);
xadd2('Alternative Purple 3',-50,128,0,255);

low__menuend(m);
//get
if popmenu2(pmNormal,iaNormal,m,'popcolorstatic',0,xcode,xcode2,xtepcolor) then
   begin
   xvalue:=xtepcolor;
   result:=true;
   end;
except;end;

//free
freeobj(@m);

end;

function tbasicsystem.popcolorhistory(var xvalue:longint;xuse32:boolean):boolean;
begin
result:=xcolorhistory(xvalue,false,false,xuse32);
end;

function tbasicsystem.popcolorhistory__add(xvalue:longint;xuse32:boolean):boolean;//19mar2021
begin
result:=xcolorhistory(xvalue,true,false,xuse32);
end;

function tbasicsystem.popcolorhistory__edit:boolean;//19mar2021
var
   int1:longint;
begin
int1:=clnone;
result:=xcolorhistory(int1,false,true,false);
end;

function tbasicsystem.xcolorhistory(var xvalue:longint;xaddonly,xeditonly,xuse32:boolean):boolean;//17nov2023, 19mar2021
label//xaddonly: true=add "xvalue" to top of color history, false=display color history in a popup list
   skipend;
var
   xhis:array[0..99] of longint;
   xdata,m:tstr8;
   xcount,lp,vc,v,vint,vr,vg,vb,va,p,xcode,xtepcolor:longint;
   str1,e,vstr,xhelp,xcode2:string;
   c32:tcolor32;

   procedure hadd(xr,xg,xb,xa:longint);
   var
      dcol,p:longint;
   begin
   try
   //check
   if (xcount>high(xhis)) then exit;
   //init
   dcol:=rgba__int(xr,xg,xb,xa);
   //find existing
   if (xcount>=1) then
      begin
      for p:=0 to (xcount-1) do if (xhis[p]=dcol) then
         begin
         exit;
         end;
      end;
   //add new
   xhis[xcount]:=dcol;
   inc(xcount);
   except;end;
   end;

   procedure xadd(xr,xg,xb,xa:longint);
   var
      xcap:string;
   begin
   xcap:=low__digpad11(xr,3)+'r, '+low__digpad11(xg,3)+'g, '+low__digpad11(xb,3)+'b'+insstr(', '+low__digpad11(xa,3)+'a',xuse32);
   low__menuitemx2(m,tepColorPal20,rgba__int(xr,xg,xb,xa),xcap,xhelp,'color',100,aknone,true);
   end;
begin
//defaults
result:=false;

try
m:=nil;
xdata:=nil;
xcount:=0;

//1st
if xaddonly and (xvalue>=0) then
   begin
   c32:=int__c32(xvalue);
   hadd(c32.r,c32.g,c32.b,c32.a);
   end;

//load
xdata:=str__new8;
io__fromfile(low__platfolder('settings')+'colhis.txt',@xdata,e);
//.edit
if xeditonly then
   begin
   str1:=xdata.text;
   if not poptxt(str1,wwsNone,true,'Edit Color History','Type one red,green,blue number per line') then goto skipend;
   xdata.text:=str1;
   end;
//.add to history list
if (xdata.len>=1) then
   begin
   vr:=0;
   vg:=0;
   vb:=0;
   va:=255;//default
   vc:=0;
   lp:=0;
   xdata.aadd([ss10]);//always ends in a return code
   for p:=0 to (xdata.len32-1) do
   begin
   v:=xdata.pbytes[p];
   if (v=ssComma) or (v=ss10) or (v=ss13) then
      begin
      //get
      vstr:=xdata.str[lp,p-lp];//0-based
      vint:=frcrange32(strint32(vstr),0,255);
      case vc of
      0:vr:=vint;
      1:vg:=vint;
      2:vb:=vint;
      3:va:=vint;
      end;
      //set
      if ((v=ss10) or (v=ss13)) then
         begin
         //set
         if (vc>=1) then//at least one comma to confirm it is a color we are reading - 19mar2021
            begin
            hadd(vr,vg,vb,va);
            end;
         //reset
         vr:=0;
         vg:=0;
         vb:=0;
         va:=255;//default
         vc:=-1;
         end;
      //inc
      inc(vc);
      lp:=p+1;
      end;
   //check
   if (xcount>high(xhis)) then break;
   end;//p
   end;
//.store
if xaddonly or xeditonly then
   begin
   xdata.clear;
   if (xcount>=1) then
      begin
      for p:=0 to (xcount-1) do
      begin
      c32:=int__c32(xhis[p]);
      xdata.sadd(low__digpad11(c32.r,3)+','+low__digpad11(c32.g,3)+','+low__digpad11(c32.b,3)+','+low__digpad11(c32.a,3)+rcode);
      end;//p
      end;
   if not io__tofile(low__platfolder('settings')+'colhis.txt',@xdata,e) then goto skipend;
   result:=true;
   goto skipend;
   end;

//prompt user
m:=str__new8;
xhelp:='Click to use color';
low__menuinit(m);
low__menutitle(m,tepNone,'Color History','History of colors');
if (xcount>=1) then
   begin
   for p:=0 to (xcount-1) do
   begin
   c32:=int__c32(xhis[p]);
   xadd(c32.r,c32.g,c32.b,c32.a);
   end;//p
   end;
if (xcount>=1) then low__menusep(m);
low__menuitem(m,tepEdit20,'Edit History...','Edit color history','edit',100,true);
low__menuend(m);
//get
if popmenu2(pmNormal,iaRight,m,'popcolorhistory',0,xcode,xcode2,xtepcolor) then
   begin
   if (xcode2='edit') then result:=popcolorhistory__edit
   else
      begin
      xvalue:=xtepcolor;
      result:=true;
      end;
   end;

skipend:
except;end;

//free
str__free(@m);
str__free(@xdata);

end;

function tbasicsystem.popcolor(var xvalue:longint):boolean;
begin
result:=popcolor2(xvalue,false);
end;

function tbasicsystem.popcolor2(var xvalue:longint;xuse32:boolean):boolean;//11dec2025
var
   a:tbasicsetcolor;
   da:twinrect;
   int1,xpreviousfocus,dw,dh:longint;
   xpreviouscontrol:tbasiccontrol;
begin

//defaults
result            :=false;
a                 :=nil;

try
//previous
xpreviousfocus    :=winfocus;
xpreviouscontrol  :=focuscontrol;

//init
gui__scale4(1.1,620,700,480,0,dw,dh);//was 550x500 = 11dec2025

da.left           :=(width-dw) div 2;
da.top            :=(height-dh) div 2;
da.right          :=da.left+dw-1;
da.bottom         :=da.top+dh-1;

//get
a                 :=nsetcolor2(da,true,xuse32);

//pop
(a as tbasicsetcolor).setparams(xvalue,xvalue,sysdlg_popcolor_page);
result            :=xshowwait(a,xpreviouscontrol,xpreviousfocus);

if result then
   begin

   (a as tbasicsetcolor).getparams(sysdlg_popcolor_color,int1,sysdlg_popcolor_page);

   xvalue:=sysdlg_popcolor_color;

   if (xvalue>=0) then popcolorhistory__add(xvalue,xuse32);

   end;

except;end;

//free
freeobj(@a);

end;

function tbasicsystem.clienttoscreen(x:tpoint):tpoint;
begin
result:=low__clienttoscreen(self,x);
end;

procedure tbasicsystem.mustclose;
begin
imustclose:=true;
end;

procedure tbasicsystem.paintallnow;
begin
imustpaint:=2;
end;

procedure tbasicsystem.paintnow;
begin
if      igamemode      then form__paintnow//issue an immedate paint request//29jan2025
else if (imustpaint<1) then imustpaint:=1;
end;

procedure tbasicsystem.alignallnow;
begin
imustalign:=2;
end;

procedure tbasicsystem.alignnow;
begin
if (imustalign<1) then imustalign:=1;
end;

procedure tbasicsystem.sizenow;
begin
imustalign:=2;//full
imustpaint:=2;//full
end;

procedure tbasicsystem.fullalignpaint;
begin
imustalign:=2;//full
imustpaint:=2;//full
end;

function tbasicsystem.aadd(xs:char;xm:byte;xx,xy:longint):boolean;
var
   p:longint;
begin
//defaults
result:=false;

try
//full
if (iacount>high(iam)) then exit;
//add
p:=iacount;
ias[p]:=xs;
iam[p]:=xm;
iax[p]:=xx;
iay[p]:=xy;
inc(iacount);
//successful
result:=true;
except;end;
end;

function tbasicsystem.apull(var xs:char;var xm:byte;var xx,xy:longint):boolean;
var
   c,p:longint;
begin
//defaults
result:=false;

try
//empty
c:=iacount;
if (c<=0) then exit;
//get
xs:=ias[0];
xm:=iam[0];
xx:=iax[0];
xy:=iay[0];
//del
if (c>=2) then
   begin
   for p:=0 to (c-2) do
   begin
   ias[p]:=ias[p+1];
   iam[p]:=iam[p+1];
   iax[p]:=iax[p+1];
   iay[p]:=iay[p+1];
   end;//p
   end;
//set
iacount:=frcmin32(c-1,0);
result:=true;
except;end;
end;

procedure tbasicsystem.anext;//next action
label//Try to avoid using this proc whilst "__onpaint()" is engaged - 17may2020
   skipone,skipend,redo;
var
   xstyle:char;
   mb:byte;
   xkey,sx,sy,int1,int2,int3,int4,int5:longint;
   xtimerfast:currency;
   s:tpoint;
   xshift,xctrl,xalt:boolean;

   procedure xwintrack(xdown:boolean);
   var
      int1,int2:longint;
   begin
   //get
   if not xwinfindbyxy(sx,sy,int1,int2) then
      begin
      int1:=-1;
      int2:=-1;
      end;
   //set
   iwinhover:=int1;
   iwinhoverlayer:=int2;
   if xdown then
      begin
      iwinfocus:=int1;
      iwinfocuslayer:=int2;
      if xinuse(iwinfocus) and ((icore[iwinfocus].winstyle=wmwindow) or (icore[iwinfocus].winstyle=wmontop)) and icore[iwinfocus].oautotop then xwintop(icore[iwinfocus]);
      end;
   end;

   procedure xkeyboard;
   var
      a:tint4;
      b1:byte;
   begin
   a.val:=sx;
   b1:=a.bytes[3];
   a.bytes[3]:=0;
   xkey:=a.val;
   if (b1>=4) then
      begin
      xalt:=true;
      dec(b1,4);
      end;
   if (b1>=2) then
      begin
      xctrl:=true;
      dec(b1,2);
      end;
   if (b1>=1) then xshift:=true;
   end;
begin
try//Note: Do NOT use a busy lock here - "Options" dialog and others will lock up - 19nov2023
//check
if (iacount<=0) then exit;

//init
xshift :=false;
xctrl  :=false;
xalt   :=false;
xtimerfast:=slowms64+50;

redo:
//xxxxxxxxxif painting or (not apull(xstyle,mb,sx,sy)) then goto skipend;
if not apull(xstyle,mb,sx,sy) then goto skipend;

//-- wheel support -------------------------------------------------------------
if (xstyle='w') then
   begin
   iwheel:=sx;
   try;if (iwheel<>0) then _onnotify(self,'w');except;end;
   iwheel:=0;//off
   end
//-- keyboard support ----------------------------------------------------------
else if (xstyle='k') then
   begin
   //init
   xkeyboard;
   //.akshift/akshiftup
   if low__setbol(ishiftok,xshift) then
      begin
      ikey:=low__aorb(akshiftup,akshift,ishiftok);
      try;_onnotify(self,'k');except;end;
      end;
   ictrlok  :=xctrl;
   ialtok   :=xalt;
   ikey     :=xkey;
   //event
   try;_onnotify(self,'k');except;end;
   //off
   ikey     :=aknone;
   end

//-- mouse support -------------------------------------------------------------
//.mouse down
else if (xstyle='d') then
   begin
   //init
   xwintrack(true);
   imousedown:=true;
   imousedownref:=slowms64;//09mar2022
   imousewasdown:=false;
//was:   imousedbclick:=((slowms64-imousedbclicktime)<=500);
   imousedbclick:=((slowms64-imousedbclicktime)<=350);//require a slightly faster double click - more stable - 22apr2021
   imousedbclicktime:=slowms64;
   imousedownxy:=low__point(sx,sy);
   imousemovexy:=low__point(sx,sy);

   case mb of
   1:imousebutton:=ableft;
   2:imousebutton:=abcenter;
   3:imousebutton:=abright;
   else imousebutton:=abnone;
   end;//case

   low__getcursorpos(s);
   iscreendownxy:=s;
   iscreenmovexy:=s;
   iscreendragging:=false;
   iscreendraggingv:=false;
   iscreendraggingh:=false;
   iscreendraggingfine:=false;
   iscreendraggingfinev:=false;
   iscreendraggingfineh:=false;
   iscreendraggingout:=false;//25feb2021

   //mouse focusindex
   xfindany(sx,sy,int1,int2,int3,int4);
   ifocussizemodex:=int3;
   ifocussizemodey:=int4;
   focusindex:=int1;
   hoverindex:=int2;
   if xinuse(int1) and zzok(core[int1],7142) then idownrect:=core[int1].clientarea else idownrect:=nilrect;
   iform_downrect:=area;

   //get
   try;_onnotify(self,'m');except;end;
   imousewasdown:=true;
   end
//.mouse up
else if (xstyle='u') then
   begin
   xwintrack(false);
   imousemovexy:=low__point(sx,sy);
   low__getcursorpos(s);
   iscreenmovexy:=s;
   imousedown:=false;
   imousedownref:=0;
   try;_onnotify(self,'m');except;end;
   imousedown:=false;
   imousedownref:=0;
   imousewasdown:=false;
   imousebutton:=abnone;//off
   iscreendragging:=false;
   iscreendraggingv:=false;
   iscreendraggingh:=false;
   iscreendraggingfine:=false;
   iscreendraggingfinev:=false;
   iscreendraggingfineh:=false;
   iscreendraggingout:=false;//25feb2021
   end
//.mouse move
else if (xstyle='m') then
   begin
   xwintrack(false);
   imousemoved:=true;
   try
   imousemovexy:=low__point(sx,sy);
   low__getcursorpos(s);
   iscreenmovexy:=s;
   if imousedown and (not iscreendragging) then
      begin
      //h
      if not low__nrw(iscreenmovexy.x,iscreendownxy.x,vidragtrigger) then
         begin
         iscreendragging:=true;
         iscreendraggingh:=true;
         end;
      //v
      if not low__nrw(iscreenmovexy.y,iscreendownxy.y,vidragtrigger) then
         begin
         iscreendragging:=true;
         iscreendraggingv:=true;
         end;
      end;
   //.fine
   if imousedown and (not iscreendraggingfine) then
      begin
      //h
      if not low__nrw(iscreenmovexy.x,iscreendownxy.x,vidragtriggerfine) then
         begin
         iscreendraggingfine:=true;
         iscreendraggingfineh:=true;
         end;
      //v
      if not low__nrw(iscreenmovexy.y,iscreendownxy.y,vidragtriggerfine) then
         begin
         iscreendraggingfine:=true;
         iscreendraggingfinev:=true;
         end;
      end;

   //.fine - mousemoving - 27feb2022
   if (not low__nrw(iscreenmovingfinexy.x,iscreenmovexy.x,1+vidragtriggerfine)) or (not low__nrw(iscreenmovingfinexy.y,iscreenmovexy.y,1+vidragtriggerfine)) then
      begin
      iscreenmovingfinexy.x:=iscreenmovexy.x;
      iscreenmovingfinexy.y:=iscreenmovexy.y;
      iscreenmovingfine:=true;
      iscreenmovingfine64:=slowms64+1000;
      end;

   //.other
   if not imousedown then
      begin
      int5:=ihoverindex;
      xfindany(sx,sy,int1,int2,int3,int4);
      hoverindex:=int2;
      //.tell previous "hoverindex" control that it nolonger has hover index (e.g. cursor is xsoutside)
      //was: if (int5<>ihoverindex) and (indexstyle(int5)=xscontrol) and zzok(icore[int5],7146) then icore[int5]._onnotify(self);
      if (int5<>ihoverindex) and (indexstyle(int5)=xscontrol) and zzok(icore[int5],7146) then icore[int5]._onnotify(icore[int5]);//06dec2024
      end;
   try;_onnotify(self,'m');except;end;
   except;end;
   imousemoved:=false;
   end
//.unknown style
else showerror('Unknown action style "'+xstyle+'"');

//.next
skipone:
if (iacount>=1) and (slowms64<=xtimerfast) then goto redo;
skipend:
except;end;
end;

function tbasicsystem.mousedraggingout2(x:twinrect;xkeepchecking,xfine:boolean):boolean;
begin
result:=mousedraggingout3(0,0,x,xkeepchecking,xfine);
end;

function tbasicsystem.mousedraggingout3(xoffx,xoffy:longint;x:twinrect;xkeepchecking,xfine:boolean):boolean;
begin//Note: xoffx and xoffy allows for realtime adjustment of a "strictly local area of 0..N" inside of a control to be extended to a screen based (within system.host clientarea) without sender having to convert the area thenselves - 25feb2021
//defaults
result:=false;

if xkeepchecking and imousedown and low__aorbbol(iscreendragging,iscreendraggingfine,xfine) and ((imousemovexy.x<(xoffx+x.left)) or (imousemovexy.x>(xoffx+x.right)) or (imousemovexy.y<(xoffy+x.top)) or (imousemovexy.y>(xoffy+x.bottom))) then
   begin
   result:=true;
   iscreendraggingout:=true;
   end;
if not xkeepchecking then result:=iscreendraggingout;
end;

function tbasicsystem.mousedraggingout(x:tbasiccontrol;xkeepchecking,xfine:boolean):boolean;
begin
//defaults
result:=false;

//get
if xkeepchecking and imousedown and low__aorbbol(iscreendragging,iscreendraggingfine,xfine) and zzok(x,7147) and x.enabled and x.visible then result:=mousedraggingout2(x.clientarea,xkeepchecking,xfine);
if not xkeepchecking then result:=iscreendraggingout;
end;

procedure tbasicsystem.amouseupfinalise;//14may2020
begin
imousedown:=false;
imousedownref:=0;//off
imousewasdown:=false;
imousebutton:=abnone;//off
iscreendragging:=false;
iscreendraggingv:=false;
iscreendraggingh:=false;
iscreendraggingfine:=false;
iscreendraggingfinev:=false;
iscreendraggingfineh:=false;
end;

function tbasicsystem.mousedowntime:comp;//09mar2022
begin
if imousedown and (imousedownref<>0) then result:=frcmin64(sub64(slowms64,imousedownref),0) else result:=0;
end;

function tbasicsystem.mousedownstroke:boolean;
begin
result:=imousedown and (not imousewasdown);
end;

function tbasicsystem.mouseupstroke:boolean;
begin
result:=(not imousedown) and imousewasdown;
end;

function tbasicsystem.mousedownonce:boolean;//strictly excludes ANY move events - triggers ONLY once - 19nov2023
begin
result:=(not imousemoved) and imousedown and (not imousewasdown);
end;

function tbasicsystem.mouseuponce:boolean;//strictly excludes ANY move events - triggers ONLY once - 19nov2023
begin
result:=(not imousemoved) and (not imousedown) and imousewasdown;
end;

function tbasicsystem.mousenone:boolean;
begin
result:=(imousebutton=abnone);
end;

function tbasicsystem.mouseleft:boolean;
begin
result:=(imousebutton=ableft);
end;

function tbasicsystem.mousecenter:boolean;
begin
result:=(imousebutton=abcenter);
end;

function tbasicsystem.mouseright:boolean;
begin
result:=(imousebutton=abright);
end;

function tbasicsystem.indexstyle(xindex:longint):longint;
begin
if      (xindex=min32)                             then result:=xsnone
else if (xindex=-2)                                 then result:=xsoutside
//was: else if (xindex=-1)                                 then result:=xssize
else if (xindex>=0) and (xindex<icorecount)         then result:=xscontrol
else                                                     result:=xsunknown;
end;

function tbasicsystem.styleindex(xstyle:longint):longint;
begin
if      (xstyle=xsnone)                             then result:=min32
else if (xstyle=xsoutside)                          then result:=-2
//was: else if (xstyle=xssize)                             then result:=-1
else if (xstyle=xscontrol)                          then result:=0
else if (xstyle=xsunknown)                          then result:=min32+1
else                                                     result:=min32+1;
end;

procedure tbasicsystem.xfindany(sx,sy:longint;var xfocusindex,xhoverindex,xsizemode,ysizemode:longint);//17aug2025
label
   skipend;
var
   a:tbasiccontrol;
   b:twinrect;
   bs,int1,i,p,cw,ch:longint;

   function afind(x:tbasiccontrol;xfindfocus:boolean):boolean;
   var
      a:tbasiccontrol;
      p:longint;
   begin

   //defaults
   result:=false;

   //check
   if zznil(x,2300) or (not x.visible) then exit;

   //init
   xhoverindex:=x.coreindex;
   if xfindfocus and x.enabled then xfocusindex:=x.coreindex;

   //.this is the topmost child -> no more to look through
   if (x.ownlist.count<=0) then
      begin
      result:=true;
      exit;
      end;

   //find
   if (x.ownlist.count>=1) then
      begin

//was: for p:=0 to (x.ownlist.count-1) do if xownget(x.ownlist,p,a) and a.visible and (sx>=a.clientarea.left) and (sx<=a.clientarea.right) and (sy>=a.clientarea.top) and (sy<=a.clientarea.bottom) and afind(a,xfindfocus and a.enabled) then
      //17aug2025: switched to reverse order
      for p:=(x.ownlist.count-1) downto 0 do if xownget(x.ownlist,p,a) and a.visible and (sx>=a.clientarea.left) and (sx<=a.clientarea.right) and (sy>=a.clientarea.top) and (sy<=a.clientarea.bottom) and afind(a,xfindfocus and a.enabled) then
         begin
         result:=true;
         break;
         end;

      end;//p

   end;
begin
try
//defaults
xfocusindex:=min32;//none
xhoverindex:=min32;//none
xsizemode:=sbnone;
ysizemode:=sbnone;
//init
cw:=iform_width;
ch:=iform_height;

//-- out-of-range --------------------------------------------------------------
if ((sx<0) or (sx>=cw) or (sy<0) or (sy>=ch)) then
   begin
   xhoverindex:=styleindex(xsoutside);//fixed - 31mar2020
   goto skipend;
   end;

//-- windows -------------------------------------------------------------------
if (winlist.count>=1) then
   begin
   int1:=min32;//none
   for p:=(winlist.count-1) downto 0 do
   begin
   i:=winlist.list[p];
   if xvisible(i) then
      begin
      if (sx>=icore[i].clientarea.left) and (sx<=icore[i].clientarea.right) and (sy>=icore[i].clientarea.top) and (sy<=icore[i].clientarea.bottom) then
         begin
         afind(icore[i],true);
         break;
         end;
      //.go no further than current dialog
      if (icore[i].winstyle=wmdialog) then break;
      end;//i
   end;//p
   end;


//-- border resizers -----------------------------------------------------------
if (xhoverindex=xfocusindex) and xinuse(xfocusindex) then
   begin
   a:=core[xfocusindex];
   if zzok(a,7149) and a.visible and a.enabled and a.owinresizeable then
      begin
      //init
      bs:=a.findbordersize;
      b:=a.clientarea;
      //x
      if (bs>=1) and (sx>=b.left) and (sx<(b.left+bs)) then
         begin
         xsizemode:=sbleft;
         if      (sy>=b.top) and (sy<(b.top+(2*bs)))       then ysizemode:=sbtop
         else if (sy>(b.bottom-(2*bs))) and (sy<=b.bottom) then ysizemode:=sbbottom;
         end
      else if (bs>=1) and (sx>(b.right-bs)) and (sx<=b.right) then
         begin
         xsizemode:=sbright;
         if      (sy>=b.top) and (sy<(b.top+(2*bs)))       then ysizemode:=sbtop
         else if (sy>(b.bottom-(2*bs))) and (sy<=b.bottom) then ysizemode:=sbbottom;
         end;
      //y
      if      (bs>=1) and (sy>=b.top) and (sy<(b.top+bs)) then
         begin
         ysizemode:=sbtop;
         if      (sx>=0) and (sx<(b.left+(2*bs)))         then xsizemode:=sbleft
         else if (sx>(b.right-(2*bs))) and (sx<=b.right)  then xsizemode:=sbright;
         end
      else if (bs>=1) and (sy>(b.bottom-bs)) and (sy<=b.bottom) then
         begin
         ysizemode:=sbbottom;
         if      (sx>=0) and (sx<(b.left+(2*bs)))         then xsizemode:=sbleft
         else if (sx>(b.right-(2*bs))) and (sx<=b.right)  then xsizemode:=sbright;
         end;
      end;
   end;
skipend:
except;end;
end;

function tbasicsystem.wtop(var x:tbasiccontrol;var xindex:longint):boolean;
var
   p:longint;
begin
//defaults
result:=false;

try
x:=nil;
xindex:=0;
//get
if (icorecount>=1) then
   begin
   for p:=(icorecount-1) downto 0 do if zzok(icore[p],4006) and (icore[p].parent=nil) and icore[p].visible then
      begin
      x:=icore[p];
      xindex:=p;
      result:=true;
      break;
      end;//p
   end;
except;end;
end;

procedure tbasicsystem._onnotify(sender:tobject;xstyle:char);//06jan2025
var
   s:tbasiccontrol;
   xfocusstyle,xhoverstyle,xfocussizemodex,xfocussizemodey:longint;
   xnormalmode:boolean;

   procedure xnotify(s:tbasiccontrol);
   label
      skipend,redo;
   var
      xonce,xhandled:boolean;
      xhint,xhelp:string;
      a:tbasicscroll;
   begin
   //defaults
   xhandled:=false;
   xonce:=true;
   xhelp:='';
   xhint:='';

   //gamemode
   if not xnormalmode then
      begin

      ihintTimeout:=-1;//disable hint
      if assigned(igamemode_onnotify) then xhandled:=igamemode_onnotify(self);
      exit;

      end;

   //check
   if zznil(s,2300) then goto skipend;

   //get
   redo:
   if s.visible then
      begin
//was:      xhandled:=s._onnotify(self);
      xhandled:=s._onnotify(s);//06dec2024
      if xonce then
         begin
         xonce:=false;
         xhelp:=s.helpline;
         xhint:=str__from32(s.coreindex)+s.hintline;//detect hints of the same value but of different controls -> first four bytes records the control coreindex (or id)
         end;
      end;
   if (not xhandled) and zzok(s.parent,7150) then
      begin
      s:=s.parent;
      goto redo;
      end;
   //last -> form based handler -> used for shortcuts etc or for doing something above and beyond the controls themselves -> hence the "ok=true=handled" - 31mar2020
   skipend:

   //root form
   _onnotifylast(self,xhandled);

   //update realtime help - 07sep2020
   if zzok(s,7151) and s.visible and s.xwindow2(a) and a.xhavehelp then a.xhelp.text:=xhelp;

   //hint - 25dec2024
   if low__setstr(ihint,xhint) then
      begin
      ihintxy:=mousemovexy;
      hint__format;
      end;

   if mousedown or mouseupstroke then ihintTimeout:=-1;//disable hint

   end;

   procedure xshortcut(s:tbasiccontrol);
   var
      p:longint;
      xhandled:boolean;
   begin
   //defaults
   xhandled:=false;

   //check
   if not low__shortcutok(ikey) then exit;

   //game mode
   if not xnormalmode then
      begin
      if assigned(igamemode_onshortcut) then xhandled:=igamemode_onshortcut(self);
      exit;
      end;

   //s "focused control" as priority
   if (not xhandled) and zzok(s,7152) and s._onshortcut(s) then xhandled:=true;//09dec2024

   //all other controls as second priority
   if (not xhandled) and (icorecount>=1) then
      begin
      for p:=0 to (icorecount-1) do if zzok(icore[p],7154) and (icore[p]<>s) and icore[p]._onshortcut(icore[p]) then//09dec2024
         begin
         xhandled:=true;
         break;
         end;//p
      end;

   //root form
   if (not xhandled) then xhandled:=_onshortcut(self);
   if (not xhandled) and assigned(fonshortcut) then xhandled:=fonshortcut(self);//11feb2023

   //last
   _onshortcutlast(self);
   end;
begin
try
//defaults
xfocusstyle:=indexstyle(ifocusindex);
xhoverstyle:=indexstyle(ihoverindex);
xfocussizemodex:=ifocussizemodex;
xfocussizemodey:=ifocussizemodey;
xnormalmode:=not igamemode;

//-- mouse ---------------------------------------------------------------------
if (xstyle='m') or (xstyle='M') then
   begin
   if mouseupstroke then sizestop;//stop

   if imousedown then
      begin
      if (xfocusstyle=xscontrol) and zzok(core[ifocusindex],7157) then
         begin
         if (xfocussizemodex<>sbnone) or (xfocussizemodey<>sbnone) then core[ifocusindex].xresizer else xnotify(core[ifocusindex]);
         end
      else xnotify(nil);
      end
   else
      begin
      if      (xhoverstyle=xscontrol) and zzok(core[ihoverindex],7158) then xnotify(core[ihoverindex])
      else                                                                  xnotify(nil);
      end;
   end
//-- keyboard ------------------------------------------------------------------
else if (xstyle='k') or (xstyle='K') then
   begin
   //init
   if (xfocusstyle=xscontrol) and zzok(core[ifocusindex],7159) then s:=core[ifocusindex] else s:=nil;
   //get
   case low__shortcutok(ikey) of
   true :xshortcut(s);//key is a shortcut -> use shortcut handler instead of "_onnotify()" procs
   else xnotify(s);//fire normal "_onnotify()" procs
   end;
   end
//-- wheel ---------------------------------------------------------------------
else if (xstyle='w') or (xstyle='W') then
   begin
   if (xfocusstyle=xscontrol) and zzok(core[ifocusindex],7160) then xnotify(core[ifocusindex])
   else xnotify(nil);
   end;

except;end;
end;

procedure tbasicsystem.hint__none;
begin

ihintTimeout:=-2;//cancel the next hint -> e.g. when closing a menu or dialog window

end;

function tbasicsystem.hint__cantitle(x:string):boolean;//03jan2025
begin

result:=not low__havechars(x,[':','.','-','"']);

end;

procedure tbasicsystem.hint__format;//09may2025: single "*" on a line for blank line, 21apr2025, 09jan2025, 03jan2025
var
   xmaxwidth,xlinelimit:longint;
   xhint:string;

   procedure ladd(xline:string);
   var
      xlen,lp,p:longint;
      c:char;
      dline,v:string;
   begin
   //init
   if (xline='') then exit else xlen:=low__len32(xline);

   //get
   dline:='';
   lp:=1;

   for p:=1 to xlen do
   begin
   c:=xline[p-1+stroffset];

   if (c=#32) or (p=xlen) then
      begin
      v:=strcopy1(xline,lp,p-lp+1);
      lp:=p+1;

      if (v<>'') and ( (low__len32(dline)+low__len32(v)) > xlinelimit ) then
         begin
         ihintlines.value[ihintlines.count]:=dline;
         dline:=v;
         end
      else dline:=dline+v;
      end;

   end;//p

   //finalise
   if (dline<>'') then ihintlines.value[ihintlines.count]:=dline;
   end;

   procedure lparse;//parse into lines with white space stripped from beginning and end of each line
   var
      xlen,xlinecount,p,lp:longint;
      v:string;
      xonce:boolean;
   begin
   xlen:=low__len32(xhint);
   xonce:=true;
   xlinecount:=0;
   lp:=1;

   for p:=1 to xlen do if (xhint[p-1+stroffset]='|') then
      begin
      inc(xlinecount);
      if (xlinecount>=2) then break;
      end;

   for p:=1 to xlen do if (xhint[p-1+stroffset]='|') then
      begin
      v:=stripwhitespace_lt(strcopy1(xhint,lp,p-lp));
      if (v<>'') then
         begin
         //add line to hint list
         ladd(v);

         //calc how many lines the title takes up - it may be wrapped over multiple lines - 09jan2025: fixed title count wrap
         if xonce and (xlinecount>=2) then
            begin
            xonce:=false;
            if (v<>'') and hint__cantitle(v) then ihinttitle_linecount:=ihintlines.count;
            end;
         end;

      lp:=p+1;
      end;//p
   end;
begin
try
//check
if not vihint then exit;

//init
ihinttitle_linecount:=0;

if (ihintTimeout=-2)                      then ihintTimeout:=-1 else ihintTimeout:=0;
if (ihintlines<>nil)                      then ihintlines.clear;
if (low__len32(ihint)<=4) or (not vihint) then exit;
if (ihintlines=nil)                       then ihintlines:=tdynamicstring.create;

xhint:=strcopy1(ihint,5,low__len32(ihint))+'|';

//max-width tailored to current screen width
xmaxwidth :=frcmin32( frcmax32( round(width*0.80), round(450*vizoom*vifontwidthratio)), 32*vizoom);//21apr2025
xlinelimit:=frcmin32(xmaxwidth div frcmin32(resfont__wave(vinormal.Rfn),5) , 5);

//parse lines
lparse;

//timer
ihintOnsecs:=frcmin32(ihintlines.count*5,5);
except;end;
end;

function tbasicsystem._onshortcut(sender:tobject):boolean;
begin
result:=false;
end;

function tbasicsystem._onshortcutlast(sender:tobject):boolean;//09dec2024
begin
result:=false;

case key of
akf1:if1_showhelp:=true;
akf2:if2_restoredefaults:=true;//display "Restore Defaults" in black and white emergency mode
end;//case
end;

procedure tbasicsystem._onnotifylast(sender:tobject;xhandled:boolean);
var
   x:tbasiccontrol;
begin
//close form
case key of
akescape:if xdlg(x) and x.mkescape then
   begin
   x.ocode:=0;
   x.visible:=false;
   end;
akreturn:if xdlg(x) and x.mkreturn then
   begin
   x.ocode:=1;
   x.visible:=false;
   end;
end;//case
end;

procedure tbasicsystem.setfocusindex(x:longint);
var
   xwas:longint;
   a:tbasiccontrol;
begin
try
//get
if (x=ifocusindex) then exit;
xwas:=ifocusindex;
ifocusindex:=x;
//.winfocus/layer
if xinuse(x) then icore[x].xwindow(a) else a:=nil;
if zzok(a,7161) then
   begin
   iwinfocus:=a.coreindex;
   xwinfindlayer(a.coreindex,iwinfocuslayer);
   end
else
   begin
   iwinfocus:=-1;
   iwinfocuslayer:=-1;
   end;
//was
if zzok(core[xwas],7162)    then core[xwas]._onfocus(self);
//new
if zzok(core[x],7163)       then core[x]._onfocus(self);
except;end;
end;

procedure tbasicsystem.setwinfocus(x:longint);
var
   int1,int2,p:longint;
begin
try
//defaults
int1:=-1;
int2:=-1;
//find
if (winlist.count>=1) then
   begin
   for p:=0 to (winlist.count-1) do if (winlist.list[p]=x) then
      begin
      int1:=x;
      int2:=p;
      break;
      end;
   end;
//set
if (iwinfocus<>int1) or (iwinfocuslayer<>int2) then
   begin
   iwinfocus:=int1;
   iwinfocuslayer:=int2;
   paintallnow;
   end;
except;end;
end;

procedure tbasicsystem.sethoverindex(x:longint);
begin
ihoverindex:=x;
end;

function tbasicsystem.getfocuscontrol:tbasiccontrol;
begin
result:=core[ifocusindex];
end;

procedure tbasicsystem.setfocuscontrol(x:tbasiccontrol);
var
   p,int1:longint;
begin

//defaults
int1            :=min32;//none

//get
if zzok(x,7164) and (icorecount>=1) then
   begin
   for p:=0 to (icorecount-1) do if (x=icore[p]) then
      begin
      int1:=p;
      break;
      end;//p
   end;

//set
ifocusindex:=int1;

end;

function tbasicsystem.xrootok(const x:tbasiccontrol):boolean;
begin

result:=(x<>nil) and (x.parent=nil);

end;

function tbasicsystem.xsafeown(var xownlist:townlist):boolean;
begin

result:=true;

if      (xownlist.count<0)                       then xownlist.count:=0
else if (xownlist.count>(high(xownlist.list)+1)) then xownlist.count:=high(xownlist.list)+1;

end;

function tbasicsystem.xownhave(var xownlist:townlist;const x:tbasiccontrol):boolean;
var
   int1:longint;
begin

result:=xownfind(xownlist,x,int1);

end;

function tbasicsystem.xownfind(var xownlist:townlist;const x:tbasiccontrol;var xownslot:longint):boolean;
var
   v,p:longint;
begin

//defaults
result   :=false;
xownslot :=0;

//range
xsafeown(xownlist);

//check
if (xownlist.count<=0) or (x=nil) then exit;

//find
for p:=0 to (xownlist.count-1) do
begin

v:=xownlist.list[p];

if xinuse(v) and (x=icore[v]) then
   begin

   xownslot :=p;
   result   :=true;
   break;

   end;

end;//p

end;

function tbasicsystem.xownfindcount(var xownlist:townlist):longint;
var
   p:longint;
begin
result:=0;

try;if xsafeown(xownlist) and (xownlist.count>=1) then for p:=0 to (xownlist.count-1) do if (xownlist.list[p]<>omfree) then result:=p+1;except;end;
end;

function tbasicsystem.xownadd(var xownlist:townlist;const x:tbasiccontrol):boolean;
var
   p:longint;
begin

//defaults
result :=false;

//check
if (x=nil) or xownhave(xownlist,x) then exit;

//find first empty slot "omfree=maxword"
for p:=0 to (xownlist.count-1) do
begin

if (xownlist.list[p]=omfree) then//previously used slot but now FREE - 19mar2020
   begin

   xownlist.list[p] :=x.coreindex;
   result           :=true;
   break;

   end;

end;//p

//add a slot
if (not result) and (xownlist.count<=high(xownlist.list)) then
   begin

   //enlarge ownlist + store + fill new free slots with "omfree"
   xownlist.list[xownlist.count] :=x.coreindex;//store control in first new slot
   result                        :=true;

   //inc
   inc(xownlist.count,1);

   end;

end;

procedure tbasicsystem.xowndel(var xownlist:townlist;const x:tbasiccontrol);
var
   p:longint;
begin

if (x<>nil) and xownfind(xownlist,x,p) then
   begin

   //delete
   xownlist.list[p] :=omfree;

   //shrink "xowncount"
   xownlist.count   :=xownfindcount(xownlist);

   end;

end;

function tbasicsystem.xownget(var xownlist:townlist;const xownslot:longint;var x:tbasiccontrol):boolean;
var
   v:longint;
begin

//defaults
result :=false;
x      :=nil;

//get
if xsafeown(xownlist) and (xownslot>=0) and (xownslot<xownlist.count) then
   begin

   v:=xownlist.list[xownslot];

   if xinuse(v) then
      begin

      x:=icore[v];
      result:=true;

      end;

   end;

end;

function tbasicsystem.xowndel__fast(var xownlist:townlist;const xownslot:longint):boolean;//04may2021
var
   v:longint;
   x:tbasiccontrol;
begin

//defaults
result :=false;

//get
if xsafeown(xownlist) and (xownslot>=0) and (xownslot<xownlist.count) then
   begin

   v:=xownlist.list[xownslot];

   if xinuse(v) then
      begin

      x:=icore[v];

      //close slot
      xownlist.list[v]:=omfree;
      icore[v]:=nil;

      //close control
      freeobj(@x);
      result:=true;

      end;

   end;

end;

procedure tbasicsystem.ownadd(const xhost,xcontrol:tobject);
begin

//check
if not (xcontrol is tbasiccontrol) then exit;

//get
if      (xhost=nil) or (xhost=self) then xownadd(ownlist,xcontrol as tbasiccontrol)//add to form as a root control
else if (xhost is tbasiccontrol)    then xownadd((xhost as tbasiccontrol).ownlist,xcontrol as tbasiccontrol)
else                                     showerror('Invalid ownadd host');

//inc
low__iroll(ownid,1);
if (xhost is tbasiccontrol) then (xhost as tbasiccontrol).ownidInc;

end;

procedure tbasicsystem.owndel(const xhost,xcontrol:tobject);
begin

//check
if not (xcontrol is tbasiccontrol)  then exit;

//get
if      (xhost=nil) or (xhost=self) then xowndel(ownlist,xcontrol as tbasiccontrol)//del from form
else if (xhost is tbasiccontrol)    then xowndel((xhost as tbasiccontrol).ownlist,xcontrol as tbasiccontrol)
else                                     showerror('Invalid owndel host');

//inc
low__iroll(ownid,1);
if (xhost is tbasiccontrol) then (xhost as tbasiccontrol).ownidInc;

end;

function tbasicsystem.xareaok(const x:twinrect):boolean;
begin

result:=(x.right>=x.left) and (x.bottom>=x.top);

end;

function tbasicsystem.getcore(const x:longint):tbasiccontrol;
begin

if (x>=0) and (x<=high(icore)) and (x<icorecount) then result:=icore[x] else result:=nil;

end;

function tbasicsystem.xinuse(const xcoreindex:longint):boolean;
begin

result:=(xcoreindex>=0) and (xcoreindex<=high(icore)) and (xcoreindex<icorecount) and (icore[xcoreindex]<>nil);

end;

function tbasicsystem.xvisible(const xcoreindex:longint):boolean;
begin

result:=(xcoreindex>=0) and (xcoreindex<=high(icore)) and (xcoreindex<icorecount) and (icore[xcoreindex]<>nil) and icore[xcoreindex].visible;

end;

function tbasicsystem.xadd(const x:tbasiccontrol;var xcoreindex:longint):boolean;
var
   p:longint;
begin

//defaults
result      :=false;
xcoreindex  :=0;

//check
if (x=nil) then exit;

//find existing
if not result then
   begin

   for p:=0 to high(icore) do if (x=icore[p]) then
      begin

      xcoreindex  :=p;
      result      :=true;
      break;

      end;//p

   end;

//add new
if not result then
   begin

   for p:=0 to high(icore) do if (nil=icore[p]) then
      begin

      icore[p]    :=x;
      xcoreindex  :=p;
      if (p>=icorecount) then icorecount:=p+1;
      result      :=true;

      break;

      end;//p

   end;

end;

function tbasicsystem.xdel(const xcoreindex:longint;const xfree:boolean):boolean;
begin

//defaults
result :=false;

//check
if (xcoreindex<0) or (xcoreindex>high(icore)) then exit;

//get
//.already deleted
if zznil(icore[xcoreindex],4007) then
   begin

   result:=true;
   exit;

   end;

//.delete
if xfree then freeobj(@icore[xcoreindex]);
icore[xcoreindex]:=nil;

//.shrink icorecount
if (icorecount>=1) and ((xcoreindex+1)=icorecount) then dec(icorecount);

//successful
result:=true;

end;

function tbasicsystem.rows:tstr8;
begin
result:=ibuffer.rows;
end;

function tbasicsystem.rows2:tstr8;
begin
result:=ibuffer2.rows;
end;


//## tbasiccontrol #############################################################
constructor tbasiccontrol.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tbasiccontrol.create2(xparent:tobject;xstart:boolean);
begin
//self
zzadd(self);

oinputcolorise.use       :=false;//20apr2025
oinputcolorise.backTRUE  :=cllime;
oinputcolorise.backFALSE :=clred;
oinputcolorise.minlen    :=0;
oinputcolorise.code      :=icNone;//default behaviour
tag                      :=0;
tag2                     :=0;
tagstr                   :='';
tagobj                   :=nil;
oflatback                :=false;
istable                  :=1;//0=stable, 1=creating, 2=destroying
oborderdiff              :=0;//19apr2025
postpaintid              :=0;//05dec2024
omade                    :=made_none;//23mar2022
ioffloading              :=false;//07mar2021
isparkleStartPos         :=fd__sparkleUniqueStart;//27mar2026, 03dec2023
osoftclose               :=false;
obold                    :=false;//03mar2021
otab                     :='';//none
owinresizeable           :=false;//25feb2021
owinLdrCOLOR             :=clnone;//07mar2022
fontimer2                :=nil;
fonalign                 :=nil;
fonvalue                 :=nil;
fonfindheight            :=nil;//06jul2021
iwinstyle                :=wmControl;
oroundStyle              :=corRound;
oroundMode               :=rmAll;//13jan2026
iroundmode2              :=rmNil;//13jan2026
ishowmenu                :=nil;//optional menu pointer -> for displaying "popup" menus
ocanshowmenu             :=false;//disable "showmenu" by default
iid                      :=low__newid;//system id
iaid                     :=0;
iidleREF64               :=slowms64;

if classnameis('tbasiccontrol') then track__inc(satControl,1);//track

iwoundtime               :=0;
iwoundtimer              :=slowms64;

inherited create;

//defaults
osafearea                :=true;//28aug2020
oborderstyle             :=bsInternal;

//.special color overriders
ospbackcolor             :=clnone;
ospbackname              :='';

//.direct color overriders
obackcolor               :=clnone;//22mar2021
otextcolor               :=clnone;//22mar2021
oframecolor              :=clnone;
oframecolor2             :=clnone;

//.continue
oautotop                 :=true;
oalignvert               :=true;
oimagealign              :=iaNormal;//19mar2021
ipainting                :=false;
ipainted                 :=false;
imustpaint               :=false;
imustalign               :=false;
ialigned                 :=false;
ialigning                :=false;
itiming                  :=false;
itimer                   :=false;

//.own support
ownlist.count            :=0;
ownid                    :=0;

//.window support
ocode                    :=0;
ocode2                   :='';
otepcolor                :=clnone;
otepcolor2               :=clnone;
mkescape                 :=false;
mkreturn                 :=false;

//.misc
bc1                      :=nil;//15mar2021
bc2                      :=nil;
bc3                      :=nil;
bc4                      :=nil;

//.other
iheightref               :=-1;
icaption                 :='';
ihint                    :='*';//25dec2024
ihelp                    :='';
ihelp2                   :='';
isubhelp                 :='';//19aug2020
isubhelp2                :='';//07sep2020
inormal                  :=true;
ibordersize              :=1;
ivisible                 :=false;
ienabled                 :=false;
iclientarea              :=area__make(0,0,7,7);//8x8

//.options
owinname                 :='';
opagename                :='';
oautofocus               :=false;
oautoheight              :=false;
oautowidth               :=false;
ominheight               :=0;
ominwidth                :=0;
oseph                    :=0;
osepv                    :=0;

//init
if zznil(xparent,2311) then//invalid value -> can't function with this!
   begin

   iparent  :=nil;
   igui     :=nil;

   end
else if (xparent is tbasicsystem) then
   begin

   iparent  :=nil;
   igui     :=(xparent as tbasicsystem);

   end
else if (xparent is tbasiccontrol) then
   begin

   iparent  :=(xparent as tbasiccontrol);
   igui     :=iparent.gui;

   end;

//check
if     zznil(gui,2312)           then showerror('GUI not set for "'+classname+'"');
if not gui.xadd(self,icoreindex) then showerror('GUI at capacity');

//add
gui.ownadd(iparent,self);

if zzok(iparent,7173) and (iparent is tbasiccontrol) then iparentcoreindex:=(iparent as tbasiccontrol).coreindex else iparentcoreindex:=-1;

enabled                  :=true;
visible                  :=true;

//start
if xstart then start;

end;

destructor tbasiccontrol.destroy;
begin
try

//stop
istable                  :=2;//26dec2025

//external events
fontimer2                :=nil;//01mar2021
fonalign                 :=nil;
ocanshowmenu             :=false;

//disconnect timer
timer                    :=false;

//remove ourselves from the window list "gui.winlist"
if (winstyle>wmcontrol) then winstyle:=wmcontrol;

//destroy children - child controls visible on this control
destroychildren;

//destroy other - support controls etc
destroyothers;

//self -> disconnect from GUI and destroy ourself - 04apr2020
gui.xdel(icoreindex,false);//no need to "freeobj" since we are already "destroying" ourself

inherited destroy;

//delete special vars
if zzok(ishowmenu,7174) then str__free(@ishowmenu);

//update system stats
if classnameis('tbasiccontrol') then track__inc(satControl,-1);//track

except;end;
end;

procedure tbasiccontrol.destroychildren;
var
   p:longint;
begin
try

if gui.xsafeown(ownlist) and (ownlist.count>=1) then
   begin
   for p:=(ownlist.count-1) downto 0 do gui.xowndel__fast(ownlist,p);
   end;

except;end;
end;

procedure tbasiccontrol.destroyothers;
begin

//called after "destroychildren", use to destroy special support controls etc

end;

//-- shared handlers -----------------------------------------------------------
procedure tbasiccontrol.make__backgroundhead;//????????????????????
begin

bordersize    :=0;

end;

procedure tbasiccontrol.make__backgroundbase;//?????????????????
begin

bordersize    :=0;

end;

procedure tbasiccontrol.make__normal;//??????????????
begin

bordersize    :=0;

end;

procedure tbasiccontrol.background__title(da:twinrect;xback:longint;xround:boolean);
begin

background__title2(da,xback,false,xround);

end;

procedure tbasiccontrol.background__title2(da:twinrect;xback:longint;xflatback,xround:boolean);
begin

case xflatback of
true:ffillArea(da,xback,xround);//''
else ffillArea(da,int__dif24(xback,-10),xround);//'g50'
end;//case

end;

procedure tbasiccontrol.background__toolbar(da:twinrect;xback,xback2:longint;xround:boolean);
begin

background__toolbar2(da,xback,xback2,false,xround);

end;

procedure tbasiccontrol.background__toolbar2(da:twinrect;xback,xback2:longint;xflatback,xround:boolean);//08mar2025: fixed corner color oversight
begin

ffillarea(da,xback,xround);//''

end;

//-- other ---------------------------------------------------------------------
procedure tbasiccontrol.xwound_wheel(xtimems:longint);//04oct2022
begin

if visleekAssitedscroll and (xtimems<>0) then
   begin

   if not xwound_dirmatch(xtimems,iwoundtime) then xwound_off;
   iwoundtime:=iwoundtime+xtimems;

   end;

end;

procedure tbasiccontrol.xwound_mousevert(xmaxtime:longint;xforce:boolean);
begin

xwound_mousevert2(xmaxtime,xforce,false);

end;

procedure tbasiccontrol.xwound_mousevert2(xmaxtime:longint;xforce,xinvert:boolean);
begin

xwound_mousevert3(xmaxtime,xforce,xinvert,true);

end;

procedure tbasiccontrol.xwound_mousevert3(xmaxtime:longint;xforce,xinvert,xvertical:boolean);
begin

case xvertical of
true:if visleekAssitedscroll and (xmaxtime<>0) and (gui.woundrateypert100>=12) and (xforce or (gui.mouseupstroke and gui.mousedragging and gui.mouseleft)) then iwoundtime:=gui.woundrateytime(xmaxtime,xforce)*low__aorb(1,-1,xinvert);
else if visleekAssitedscroll and (xmaxtime<>0) and (gui.woundratexpert100>=12) and (xforce or (gui.mouseupstroke and gui.mousedragging and gui.mouseleft)) then iwoundtime:=gui.woundratextime(xmaxtime,xforce)*low__aorb(1,-1,xinvert);
end;//case

end;

function tbasiccontrol.xwound_mustpaint(spos,xrowsperpaint:longint;var dpos,ddir:longint):boolean;
const
   xtimeblock=30;//30ms
begin
//defaults
result:=false;

try
dpos:=spos;
ddir:=low__aorb(-1,1,iwoundtime>=0);
//check
if not visleekAssitedscroll then exit;
//get
if (slowms64>=iwoundtimer) then
   begin
   if (iwoundtime<>0) then
      begin
      if (not gui.mousedown) then
         begin
         dpos:=spos+round( frcmin32(xrowsperpaint,1) * (frcrange32(-iwoundtime,-500,500)/500) );
         if (dpos<>spos) then result:=true;
         end;
      //.shrink time
      iwoundtime:=frcmin32(low__posn(iwoundtime)-xtimeblock,0)*low__aorb(1,-1,iwoundtime<0);
      end;
   iwoundtimer:=slowms64+xtimeblock;
   end;
except;end;
end;

function tbasiccontrol.xwound_mustpaint2(spos,xrowsperpaint:longint):longint;
var
   int1:longint;
begin
xwound_mustpaint(spos,xrowsperpaint,result,int1);
end;

function tbasiccontrol.xwound_off:boolean;
begin
result:=(iwoundtime<>0);iwoundtime:=0;
end;

procedure tbasiccontrol.xwound_autooff(spos,xdir,xmin,xmax:longint);
begin
if ((xdir>=1) and (spos>=xmax)) or ((xdir<=-1) and (spos<=xmin)) then xwound_off;
end;

function tbasiccontrol.xwound_finddir(xtime:longint):longint;
begin
if (xtime>=0) then result:=1 else result:=-1;
end;

function tbasiccontrol.xwound_dirmatch(xtime1,xtime2:longint):boolean;
begin
result:=(xwound_finddir(xtime1)=xwound_finddir(xtime2));
end;

procedure tbasiccontrol.notidle;
begin
iidleREF64:=slowms64;
end;

function tbasiccontrol.idletime:comp;
begin
result:=sub64(slowms64,iidleREF64);
end;

procedure tbasiccontrol.xfaster;
begin
app__turbo;
end;

procedure tbasiccontrol.setnormal(x:boolean);//19jul2025
begin
inormal:=x;
end;

function tbasiccontrol.canaccept:boolean;
begin
result:=visible and enabled and assigned(fonaccept);
end;

function tbasiccontrol.accept_passthru(sender:tobject;xfolder,xfilename:string;xindex,xcount:longint):boolean;
begin
if assigned(fonaccept) then result:=fonaccept(self,xfolder,xfilename,xindex,xcount) else result:=false;
end;

procedure tbasiccontrol.autoshowmenu;
begin
autoshowmenu2('');
end;

procedure tbasiccontrol.autoshowmenu2(xstyle:string);
begin
if mustshowmenu then showmenu2(xstyle);
end;

function tbasiccontrol.mustshowmenu:boolean;
begin
result:=canshowmenu and gui.mouseupstroke and gui.mouseright;
end;

function tbasiccontrol.canshowmenu:boolean;
begin
result:=ocanshowmenu and zznil(ishowmenu,2312) and enabled;
end;

procedure tbasiccontrol.showmenu;
begin
showmenu2('');
end;

procedure tbasiccontrol.showmenu2(xstyle:string);
label
   skipdone;
var
   ximagealign,xcode,xtepcolor:longint;
   xmenuname,xcode2:string;
   xfocuscontrol:tbasiccontrol;
begin
try
//check
if not canshowmenu then exit;
//init
gui.closelock;//prevent shutdown of system while proc in use - 03apr2021
xstyle:=strlow(xstyle);//03jun2021
xcode:=0;
xtepcolor:=clnone;
xcode2:='';
ishowmenu:=str__new8;
xmenuname:='';
xfocuscontrol:=gui.focuscontrol;
ximagealign:=iaNormal;

//fill
//.start
low__menuinit(ishowmenu);

//.optional external fillter #1
if assigned(fshowmenuFill1) then fshowmenuFill1(self,xstyle,ishowmenu,ximagealign,xmenuname);

//.internal menu filler
showmenuFill(xstyle,ishowmenu,ximagealign,xmenuname);//can override this and place our code before it and after it to extend the built-in menu's function - 15mar2021
if assigned(fshowmenuFillINT) then fshowmenuFillINT(self,xstyle,ishowmenu,ximagealign,xmenuname);

//.optional external fillter #2
if assigned(fshowmenuFill2) then fshowmenuFill2(self,xstyle,ishowmenu,ximagealign,xmenuname);

//.finalise
low__menuend(ishowmenu);

//show
if (low__menucount(ishowmenu)>=1) and gui.popmenu2(pmNormal,ximagealign,ishowmenu,xmenuname,0,xcode,xcode2,xtepcolor) then
   begin
   //click handlers
   //.internal click handlers - 12jan2022
   if assigned(fshowmenuClick1) and fshowmenuClick1(self,xstyle,xcode,xcode2,xtepcolor) then goto skipdone;//permitts override of ALL internal functions by PRECEEDING BOTH internal handlers
   if showmenuClick(self,xstyle,xcode,xcode2,xtepcolor) then goto skipdone;//primary internal handler
   if assigned(fshowmenuClickINT) and fshowmenuClickINT(self,xstyle,xcode,xcode2,xtepcolor) then goto skipdone;//additional internal handler
   if assigned(fshowmenuClick2) and fshowmenuClick2(self,xstyle,xcode,xcode2,xtepcolor) then goto skipdone;//secondary optional handler
   end;
skipdone:
//onshowmenu
if assigned(fonshowmenu) then fonshowmenu(self);//26mar2021
//restore
gui.focuscontrol:=xfocuscontrol;
except;end;
try
str__free(@ishowmenu);
gui.closeunlock;
except;end;
end;

procedure tbasiccontrol.showmenuFill(xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
begin
//override to populate menu
end;

function tbasiccontrol.showmenuClick(sender:tobject;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
begin
result:=false;//not handled -> override to process menu click
end;

function tbasiccontrol.xfromsys(xname:string):boolean;
begin
result:=visyssettingsloaded and zzok(syssettings,7175) and xfrom(self,syssettings,strdefb(xname,'control'));
end;

function tbasiccontrol.xfromprg(xname:string):boolean;
begin
result:=viprgsettingsloaded and zzok(prgsettings,7176) and xfrom(self,prgsettings,strdefb(xname,'control'));
end;

function tbasiccontrol.xfromprg2(xname:string;dvars:tvars8):boolean;//prgsettings -> control -> dvars (allows for filtering of value) - 25mar2021
begin
result:=viprgsettingsloaded and zzok(prgsettings,7177) and xfrom(self,prgsettings,strdefb(xname,'control'));
if result and zzok(dvars,7177) then result:=xto(self,dvars,xname);
end;

function tbasiccontrol.xtosys(xname:string):boolean;
begin
result:=visyssettingsloaded and zzok(syssettings,7178) and xto(self,syssettings,strdefb(xname,'control'));
end;

function tbasiccontrol.xtoprg(xname:string):boolean;
begin
result:=viprgsettingsloaded and zzok(prgsettings,7179) and xto(self,prgsettings,strdefb(xname,'control'));
end;

function tbasiccontrol.xfrom(sender:tbasiccontrol;xvars:tvars8;xname:string):boolean;
begin
result:=true;//handled
end;

function tbasiccontrol.xto(sender:tbasiccontrol;xvars:tvars8;xname:string):boolean;
begin
result:=true;//handled
end;

function tbasiccontrol.setbc14(v1,v2,v3,v4:tbasiccontrol):boolean;//15mar2021
begin
result:=false;
if low__setbc(bc1,v1) then result:=true;
if low__setbc(bc2,v2) then result:=true;
if low__setbc(bc3,v3) then result:=true;
if low__setbc(bc4,v4) then result:=true;
end;

//-- Offloaders ----------------------------------------------------------------
//Note: These procs/functions will offload their work to other, generally more
//      centralised objects of the same type inorder to minimise GUI clutter or
//      waste screen space by combining multiple objects into a single handler,
//      for instance a main toolbar that might control a navbox, options, several
//      menus and pages - 07mar2021
function tbasiccontrol.xoff_toolbaradd(x:tbasictoolbar):boolean;
begin
result:=stableobj(x) and _xoff_toolbaradd(x);
end;

function tbasiccontrol.xoff_toolbarsync(x:tbasictoolbar):boolean;
begin
result:=stableobj(x) and _xoff_toolbarsync(x);
end;

function tbasiccontrol.xoff_toolbarevent(x:tbasictoolbar):boolean;
begin
result:=stableobj(x) and _xoff_toolbarevent(x);
end;

function tbasiccontrol._xoff_toolbaradd(x:tbasictoolbar):boolean;
begin
result:=false;
end;

function tbasiccontrol._xoff_toolbarsync(x:tbasictoolbar):boolean;
begin
result:=false;
end;

function tbasiccontrol._xoff_toolbarevent(x:tbasictoolbar):boolean;
begin
result:=false;
end;

//-- Other ---------------------------------------------------------------------
function tbasiccontrol.canautoheight:boolean;
begin
result:=oautoheight;
end;

procedure tbasiccontrol.xresizer;//25feb2021
var
   s,d:twinrect;
   xval,yval,xm,ym:longint;
begin
try
//init
xm:=gui.focussizemodex;
ym:=gui.focussizemodey;
xval:=(gui.screenmovexy.x-gui.screendownxy.x);
yval:=(gui.screenmovexy.y-gui.screendownxy.y);
if  (not owinresizeable) or ((xm=sbnone) and (ym=sbnone)) or (not enabled) or (not visible) then exit;
if (winstyle=wmfullwin) then
   begin
   if vilockposition then exit;//27feb2022
   s:=gui.form__downrect;
   end
else s:=gui.downrect;
d:=s;
app__turbo;//high speed timing
//get
if (xm=sbleft)    then inc(d.left,xval);//left
if (xm=sbright)   then inc(d.right,xval);//right
if (ym=sbtop)     then inc(d.top,yval);//top
if (ym=sbbottom)  then inc(d.bottom,yval);//bottom

//start
if gui.mousedown and gui.screendraggingfine then gui.sizestart(gui.focusindex);

//set
if (d.left<d.right) and (d.top<d.bottom) and (winstyle<>wmfullwin) then setbounds(d.left,d.top,d.right-d.left+1,d.bottom-d.top+1);
except;end;
end;

function tbasiccontrol.headheight:longint;
begin
result:=0;
end;

function tbasiccontrol.client:tbasiccontrol;
begin
result:=self;
end;

procedure tbasiccontrol.ainc;
begin
low__iroll(iaid,1);
end;

function tbasiccontrol.iswin:boolean;
begin
result:=(iwinstyle>=wmFullwin);
end;

procedure tbasiccontrol.setwinstyle(x:longint);
begin
if low__setint(iwinstyle,frcrange32(x,0,wmmax)) then gui.xwinnil(self);
end;

procedure tbasiccontrol.setcaption(x:string);
begin
if low__setstr(icaption,x) then paintnow;
end;

procedure tbasiccontrol.xonvalue;
begin
if assigned(fonvalue) then fonvalue(self);
end;

//-- new control makers --------------------------------------------------------

function tbasiccontrol.ntea(xcap,xhelp:string):tbasictea;
begin

result:=tbasictea.create(self);

if (result<>nil) then
   begin

   result.caption:=xcap;
   result.help:=xhelp;

   end;

end;

function tbasiccontrol.ndebug:tbasicdebug;//04feb2025
begin
result:=tbasicdebug.create(self);
end;

function tbasiccontrol.mtitle(xcap,xhelp:string):tmenutitle;
begin
result:=tmenutitle.create(self);
if (result<>nil) then
   begin
   result.caption:=xcap;
   result.help   :=xhelp;
   end;
end;

function tbasiccontrol.mtitleplain(xcap,xhelp:string):tmenutitle;
begin
result:=mtitle(xcap,xhelp);
if (result<>nil) then result.oplain:=true;
end;

function tbasiccontrol.mlabel(xcap,xhelp:string):tmenutitle;
begin
result:=mtitle(xcap,xhelp);
if (result<>nil) then
   begin
   result.obold :=false;
   end;
end;

function tbasiccontrol.mlabelplain(xcap,xhelp:string):tmenutitle;
begin
result:=mtitle(xcap,xhelp);
if (result<>nil) then
   begin
   result.obold :=false;
   result.oplain:=true;
   end;
end;

function tbasiccontrol.ntitle(xlarge:boolean;xcap,xhelp:string):tbasictitle;
begin
result:=tbasictitle.create(self,xlarge,false,xcap);
if (result<>nil) then result.help:=xhelp;
end;

function tbasiccontrol.ntitle2(xlarge,xlargeheight:boolean;xcap,xhelp:string):tbasictitle;
begin
result:=ntitle(xlarge,xcap,xhelp);
if (result<>nil) then result.olargeheight:=xlargeheight;
end;

function tbasiccontrol.ntitlebar(xlarge:boolean;xcap,xhelp:string):tbasictoolbar;
begin
result:=tbasictoolbar.create(self);
if (result<>nil) then
   begin
   result.maketitle3(xcap,xlarge,false);
   result.help:=xhelp;
   end;
end;

function tbasiccontrol.ntitlebar2(xlarge,xright:boolean;xcap,xhelp:string):tbasictoolbar;
begin
result:=tbasictoolbar.create(self);
if (result<>nil) then
   begin
   result.maketitle3(xcap,xlarge,xright);
   result.help:=xhelp;
   end;
end;

function tbasiccontrol.ncontrol:tbasiccontrol;
begin
result:=tbasiccontrol.create(self);
end;

function tbasiccontrol.nimgview:tbasicimgview;
begin
result:=tbasicimgview.create(self);
end;

function tbasiccontrol.nlabel(xcap,xhelp:string):tbasictitle;
begin
result:=tbasictitle.create(self,false,true,xcap);
if (result<>nil) then result.help:=xhelp;
end;

function tbasiccontrol.ngrad:tbasicgradient;
begin
result:=tbasicgradient.create(self,'');
end;

function tbasiccontrol.njump(xcap,xhelp:string;xpos,xlen:longint):tbasicjump;
begin
result:=tbasicjump.create(self,xcap);
if (result<>nil) then
   begin
   result.help:=xhelp;
   result.setparams(xpos,xlen,100);
   end;
end;

function tbasiccontrol.mint(xcap,xhelp:string;xmin,xmax,xdef,xval:longint):tsimpleint;//03jun2025
begin
result:=mint4(xcap,xhelp,xhelp,xmin,xmax,xdef,xval,'','');
end;

function tbasiccontrol.mintb(xcap,xhelplabel,xhelpbar:string;xmin,xmax,xdef,xval:longint):tsimpleint;//03jun2025
begin
result:=mint4(xcap,xhelplabel,xhelpbar,xmin,xmax,xdef,xval,'','');
end;

function tbasiccontrol.mint2(xcap,xhelp:string;xmin,xmax,xdef,xval:longint;xbackname:string):tsimpleint;
begin
result:=mint4(xcap,xhelp,xhelp,xmin,xmax,xdef,xval,'','');
end;

function tbasiccontrol.mint2b(xcap,xhelplabel,xhelpbar:string;xmin,xmax,xdef,xval:longint;xbackname:string):tsimpleint;
begin
result:=mint4(xcap,xhelplabel,xhelpbar,xmin,xmax,xdef,xval,'','');
end;

function tbasiccontrol.mint3(xcap,xhelp:string;xmin,xmax,xdef,xval:longint;xbackname,xloadfromname:string):tsimpleint;
begin
result:=mint4(xcap,xhelp,xhelp,xmin,xmax,xdef,xval,xbackname,xloadfromname);
end;

function tbasiccontrol.mint3b(xcap,xhelplabel,xhelpbar:string;xmin,xmax,xdef,xval:longint;xbackname,xloadfromname:string):tsimpleint;
begin
result:=mint4(xcap,xhelplabel,xhelpbar,xmin,xmax,xdef,xval,xbackname,xloadfromname);
end;

function tbasiccontrol.mint4(xcap,xhelplabel,xhelpbar:string;xmin,xmax,xdef,xval:longint;xbackname,xloadfromname:string):tsimpleint;
begin
result:=tsimpleint.create(self);
if (result<>nil) then
   begin
   result.caption     :=xcap;
   result.ohelplabel  :=xhelplabel;
   result.ohelpbar    :=xhelpbar;
   result.ospbackname :=xbackname;
   result.setparams3(xmin,xmax,xdef,xval,xloadfromname);
   end;
end;

function tbasiccontrol.mmidivol(xcap,xhelp:string):tsimpleint;//02jul2025
begin
result:=tsimpleint.create(self);

if (result<>nil) then
   begin

   result.makemidivol;

   if (xcap<>'')  then result.caption:=xcap;

   if (xhelp<>'') then
      begin
      result.ohelplabel:=xhelp;
      result.ohelpbar  :=xhelp;
      end;

   end;

end;

function tbasiccontrol.mwavevol(xcap,xhelp:string):tsimpleint;//02jul2025
begin
result:=tsimpleint.create(self);

if (result<>nil) then
   begin

   result.makewavevol;

   if (xcap<>'')  then result.caption:=xcap;

   if (xhelp<>'') then
      begin
      result.ohelplabel:=xhelp;
      result.ohelpbar  :=xhelp;
      end;

   end;
end;

function tbasiccontrol.nmidi(xcap,xhelp:string):tbasicsel;//05mar2022
begin
result:=tbasicsel.create(self);
if (result<>nil) then
   begin
   result.makemididevice;
   if (xcap<>'')  then result.caption:=xcap;
   if (xhelp<>'') then result.help:=xhelp;
   end;
end;

function tbasiccontrol.nwave(xcap,xhelp:string):tbasicsel;//05mar2022
begin
result:=tbasicsel.create(self);
if (result<>nil) then
   begin
   result.makewavedevice;
   if (xcap<>'')  then result.caption:=xcap;
   if (xhelp<>'') then result.help:=xhelp;
   end;
end;

function tbasiccontrol.mmiditranspose(xcap,xhelp:string):tsimpleint;//03jul2025
begin
result:=tsimpleint.create(self);

if (result<>nil) then
   begin

   result.makemiditranspose;

   if (xcap<>'')  then result.caption:=xcap;

   if (xhelp<>'') then
      begin
      result.ohelplabel:=xhelp;
      result.ohelpbar  :=xhelp;
      end;

   end;
end;

function tbasiccontrol.nimgexts(xcap,xhelp:string):tbasicimageexts;//21dec2024
begin
result:=tbasicimageexts.create(self);
if (result<>nil) then
   begin
   result.caption:=xcap;
   result.help:=xhelp;
   end;
end;

function tbasiccontrol.nset(xcap,xhelp:string;xdef,xval:longint):tbasicset;
begin
result:=tbasicset.create(self);
if (result<>nil) then
   begin
   result.caption:=xcap;
   result.help:=xhelp;
   result.setparams(xdef,xval);
   end;
end;

function tbasiccontrol.nsel(xcap,xhelp:string;xdef:longint):tbasicsel;
begin
result:=tbasicsel.create(self);
if (result<>nil) then
   begin
   result.caption:=xcap;
   result.help:=xhelp;
   result.setparams(xdef,0);
   end;
end;

function tbasiccontrol.nsel3(xcap,xhelp:string;xdef:longint;xloadfromname:string):tbasicsel;
begin
result:=tbasicsel.create(self);
if (result<>nil) then
   begin
   result.caption:=xcap;
   result.help:=xhelp;
   result.setparams3(xdef,0,result.itemsperline,xloadfromname);
   end;
end;

function tbasiccontrol.nedit(xcap,xhelp:string):tbasicedit;
begin
result:=nedit2(xcap,xhelp,true);
end;

function tbasiccontrol.nedit2(xcap,xhelp:string;xvert:boolean):tbasicedit;
begin
result:=tbasicedit.create(self,xcap);
if (result<>nil) then
   begin
   result.help:=xhelp;
   result.oalignvert:=xvert;
   end;
end;

function tbasiccontrol.ndropstatic(xhelp:string;xtep:longint):tbasicedit;
begin
result:=tbasicedit.create(self,'');
if (result<>nil) then
   begin
   result.help:='Select file format';
   result.tep:=tepFNew20;
   result.makedropstatic;
   end;
end;

function tbasiccontrol.npass(xcap,xhelp:string):tbasicedit;
begin
result:=tbasicedit.create(self,xcap);
if (result<>nil) then
   begin
   result.makepass;
   result.help:=xhelp;
   result.oalignvert:=true;
   end;
end;

function tbasiccontrol.ncolor(xcap,xhelp:string):tbasiccolor;
begin
result:=ncolor2(xcap,xhelp,true,0);
end;

function tbasiccontrol.ncolor1(xcap,xhelp:string;xuse32:boolean):tbasiccolor;
begin
result:=ncolor3(xcap,xhelp,true,0,xuse32);
end;

function tbasiccontrol.ncolor2(xcap,xhelp:string;xvert:boolean;hsp:longint):tbasiccolor;
begin
result:=ncolor3(xcap,xhelp,xvert,hsp,false);
end;

function tbasiccontrol.ncolor3(xcap,xhelp:string;xvert:boolean;hsp:longint;xuse32:boolean):tbasiccolor;
begin
result:=tbasiccolor.create(self,xcap);
if (result<>nil) then
   begin
   result.help:=xhelp;
   result.oalignvert:=xvert;
   result.oseph:=hsp;
   result.use32:=xuse32;
   end;
end;

function tbasiccontrol.nscrollbar(xhelp:string;xvert:boolean):tbasicscrollbar;
begin
result:=tbasicscrollbar.create(self);
if (result<>nil) then
   begin
   result.help:=xhelp;
   result.oalignvert:=xvert;
   end;
end;

function tbasiccontrol.nscroll(xhelp:string):tbasicscroll;//06oct2020
begin
result:=tbasicscroll.create(self);
if (result<>nil) then
   begin
   result.help:=xhelp;
   result.bordersize:=1;
   result.normal:=true;
   end;
end;

function tbasiccontrol.ntoolbar(xhelp:string):tbasictoolbar;//29may2021
begin
result:=tbasictoolbar.create(self);
if (result<>nil) then
   begin
   result.help:=xhelp;
   result.normal:=true;
   end;
end;

function tbasiccontrol.ntoolbar_buttons(xhelp:string):tbasictoolbar;//29may2021
begin
result:=tbasictoolbar.create(self);
if (result<>nil) then
   begin
   result.help:=xhelp;
   with result do
   begin
   bordersize:=0;
   normal:=true;
   osepv:=1;//11oct2020
   end;
   end;
end;

function tbasiccontrol.ncols:tbasiccols;//columns - 06oct2020
begin
result:=tbasiccols.create(self);
end;

function tbasiccontrol.ncolors:tbasiccolors;//colors set - 07oct2020
begin
result:=tbasiccolors.create(self);
end;

function tbasiccontrol.nbwp(const xhelp:string;xdata:tstr8):tbasicbwp;
begin
result:=nbwp4(xhelp,xdata,wwsWindow,false,false,false,false,false);
end;

function tbasiccontrol.nbwp2(const xhelp:string;xdata:tstr8;xwrap:longint;xrows,xautoheight:boolean):tbasicbwp;//17mar2021
begin
result:=nbwp4(xhelp,xdata,xwrap,xrows,xautoheight,false,false,false);
end;

function tbasiccontrol.nbwp3(const xhelp:string;xdata:tstr8;xwrap:longint;xrows,xautoheight,xretaindata:boolean):tbasicbwp;//17mar2021
begin
result:=nbwp4(xhelp,xdata,xwrap,xrows,xautoheight,xretaindata,false,false);
end;

function tbasiccontrol.nbwp4(const xhelp:string;xdata:tstr8;xwrap:longint;xrows,xautoheight,xretaindata,xtransform,xwebimages:boolean):tbasicbwp;//15feb2026
begin
result:=nbwp5(xhelp,xdata,xwrap,xrows,xautoheight,xretaindata,xtransform,xwebimages,true,false,0,0);
end;

function tbasiccontrol.nbwp5(const xhelp:string;xdata:tstr8;xwrap:longint;xrows,xautoheight,xretaindata,xtransform,xwebimages,xviewurl,xusemake:boolean;xmake__formatlevel,xmake__useonefont:longint):tbasicbwp;//15feb2026
var
   a:tstr8;
begin

//defaults
result                :=nil;
a                     :=nil;

try

//get
result                :=tbasicbwp.create(self);
result.help           :=xhelp;
result.wrap           :=frcrange32(xwrap,0,wwsMax);
result.oautoheight    :=xautoheight;
result.orows          :=xrows;
result.core.viewurl   :=xviewurl;

if xusemake then result.makexxx(xmake__formatlevel,xmake__useonefont,xviewurl);//31mar2025

if xretaindata then//by default "low__wordcore..4()" wipes or alters inbound datastream handler "xdata", with xretaindata=true a copy is used thus preserving original data stream - 17mar2021
   begin

   a:=str__new8;
   a.add(xdata);
   result.ioset3(a,-1,-1,-1,-1,-1,xtransform,xwebimages);

   end
else result.ioset3(xdata,-1,-1,-1,-1,-1,xtransform,xwebimages);

except;end;

//free
str__free(@a);

end;

function tbasiccontrol.nbwpbar(xbox:tbasicbwp;xsysbox:boolean):tbwpbar;//14nov2023
begin
result:=tbwpbar.create(self);
if (result<>nil) then
   begin
   result.box:=xbox;
   result.osysbox:=xsysbox;
   end;
end;

function tbasiccontrol.nmenu(xcap,xhelp:string):tbasicmenu;
begin
result:=tbasicmenu.create(self);
if (result<>nil) then result.help:=xhelp;
end;

function tbasiccontrol.npoplist(xcap,xhelp:string;xlistdata:tstr8):tbasicmenu;
begin
str__lock(@xlistdata);

result:=tbasicmenu.create(self);
if (result<>nil) then
   begin
   result.help:=xhelp;
   result.makepoplist;
   result.data:=xlistdata;
   end;

str__uaf(@xlistdata);
end;

function tbasiccontrol.nlist(xcap,xhelp:string;xlistdata:tstr8;xrowcount:longint):tbasicmenu;
begin
result:=nlist3(xcap,xhelp,xlistdata,xrowcount,'');
end;

function tbasiccontrol.nlist3(xcap,xhelp:string;xlistdata:tstr8;xrowcount:longint;xloadfromname:string):tbasicmenu;
begin
str__lock(@xlistdata);
if (xcap<>'') then nlabel(xcap,xhelp);//14nov2022

result:=tbasicmenu.create(self);
if (result<>nil) then
   begin
   result.help:=xhelp;
   result.makelist;
   result.orowcount:=xrowcount;
   result.oautoclose:=false;
   result.data:=xlistdata;
   result.oloadfromname:=xloadfromname;
   result.oautoreload:=true;
   if (xloadfromname<>'') then result.reload;
   end;

str__uaf(@xlistdata);
end;

function tbasiccontrol.nlistx(xcap,xhelp:string;xcount,xrowcount:longint;xongetitem:tbasicmenu_getitem):tbasicmenu;
begin
result:=nlistx3(xcap,xhelp,xcount,xrowcount,xongetitem,'');
end;

function tbasiccontrol.nlistx3(xcap,xhelp:string;xcount,xrowcount:longint;xongetitem:tbasicmenu_getitem;xloadfromname:string):tbasicmenu;
begin
if (xcap<>'') then nlabel(xcap,xhelp);//14nov2022

result:=tbasicmenu.create(self);
if (result<>nil) then
   begin
   result.help:=xhelp;
   result.makelistx(xcount);
   result.orowcount:=xrowcount;
   result.oautoclose:=false;//22sep2020
   result.ongetitem:=xongetitem;
   result.oloadfromname:=xloadfromname;
   result.oautoreload:=true;
   if (xloadfromname<>'') then result.reload;
   end;
end;

function tbasiccontrol.nnav:tbasicnav;
begin
result:=tbasicnav.create(self);
end;

function tbasiccontrol.ncolormatrix:tbasiccolormatrix;//26feb2021
begin
result:=tbasiccolormatrix.create(self);
end;

function tbasiccontrol.ncolormixer:tbasiccolormixer;//05sep2025
begin
result:=tbasiccolormixer.create(self);
end;

function tbasiccontrol.nsetcolor:tbasicsetcolor;//27feb2021
begin
result:=tbasicsetcolor.create(self,false,false);
end;

function tbasiccontrol.nsetcolor2(xuse32,xhead:boolean):tbasicsetcolor;//27feb2021
begin
result:=tbasicsetcolor.create(self,xuse32,xhead);
end;

function tbasiccontrol.nbreak(xheight:longint):tbasicbreak;
begin
result:=tbasicbreak.create(self,xheight);
end;

procedure tbasiccontrol.start;
begin

timer     :=true;
istable   :=0;

end;

function tbasiccontrol.info:pvirtualinfo;
begin
if inormal then result:=@vinormal else result:=@vititle;
end;

function tbasiccontrol.info_cs:twinrect;
begin
result:=clientspace;
end;

function tbasiccontrol.info_bs:longint;
begin
result:=findbordersize;
end;

function tbasiccontrol.info_ci:twinrect;
var
   bs:longint;
begin
bs:=info_bs;
result:=clientspace;
if (bs>=1) then
   begin
   inc(result.left);
   dec(result.right);
   inc(result.top);
   dec(result.bottom);
   end;
end;

function tbasiccontrol.findback:longint;//find background color - 25feb2021
var
   s:tclientinfo;
begin
infovars(s);
result:=s.back;
end;

procedure tbasiccontrol.findbackRound(var xback:longint;var xround:boolean);
var
   s:tclientinfo;
begin
infovars(s);
xback :=s.back;
xround:=s.r;
end;

function tbasiccontrol.findtext:longint;//find text color - 22mar2021
var
   s:tclientinfo;
begin
result:=otextcolor;
if (result=clnone) then
   begin
   infovars(s);
   result:=s.font;
   end;
end;

function tbasiccontrol.findframe:longint;//find frame color - 17mar2021
begin
result:=oframecolor;
if (result=clnone) then result:=info.frame;
end;

function tbasiccontrol.findframe2:longint;//find frame2 color - 17mar2021
begin
result:=oframecolor2;
if (result=clnone) then result:=info.frame2;
end;

function tbasiccontrol.infovars(var xinfo:tclientinfo):boolean;//17may2025
begin
result:=viclientinfo(xinfo,self,normal);
end;

function tbasiccontrol.infovars2(var xinfo:tclientinfo;xnormal:boolean):boolean;//17may2025
begin
result:=viclientinfo(xinfo,self,xnormal);
end;

procedure tbasiccontrol.ownidInc;
begin
low__iroll(ownid,1);
end;

function tbasiccontrol.mousedownxy:tpoint;
begin
result:=gui.mousedownxy;
dec(result.x,iclientarea.left);
dec(result.y,iclientarea.top);
end;

function tbasiccontrol.mousemovexy:tpoint;
begin
result:=gui.mousemovexy;
dec(result.x,iclientarea.left);
dec(result.y,iclientarea.top);
end;

function tbasiccontrol.cursorxy:tpoint;//05may2025
begin
result:=gui.curpos;
dec(result.x,iclientarea.left);
dec(result.y,iclientarea.top);
end;

function tbasiccontrol.translatexy(a:tpoint):tpoint;
var
   s:twinrect;
begin
s:=gui.area;
result.x:=a.x-iclientarea.left-s.left;
result.y:=a.y-iclientarea.top-s.top;
end;

function tbasiccontrol.mouseinside:boolean;
begin
result:=xinside(mousemovexy);
end;

function tbasiccontrol.mouseinsideclientarea:boolean;
begin
result:=xinsideclientarea(mousemovexy);
end;

procedure tbasiccontrol.setparent(x:tbasiccontrol);
begin//Note: GUI is set once, and remains unchanged for the life of the control -> maximum stability - 19mar2020
if (x<>iparent) then
   begin
   gui.owndel(iparent,self);
   iparent:=x;
   if zzok(iparent,7180) then iparentcoreindex:=x.coreindex else iparentcoreindex:=-1;
   gui.ownadd(x,self);
   end;
end;

function tbasiccontrol.visibletohost:boolean;
label
   redo;
var
   a:tbasiccontrol;
begin
result:=false;
a:=self;
redo:
if zzok(a,2312) and a.visible then
   begin
   if zznil(a.parent,2312) then result:=true
   else
      begin
      a:=a.parent;
      goto redo;
      end;
   end;
end;

function tbasiccontrol.enabledtohost:boolean;
label
   redo;
var
   a:tbasiccontrol;
begin
result:=false;
a:=self;
redo:
if zzok(a,2313) and a.enabled then
   begin
   if zznil(a.parent,2313) then result:=true
   else
      begin
      a:=a.parent;
      goto redo;
      end;
   end;
end;

function tbasiccontrol.havecontrol(x:tbasiccontrol):boolean;//04oct2024
label
   redo;
begin
result:=false;

redo:
if (x<>nil) then
   begin
   if (x=self) then result:=true
   else
      begin
      x:=x.parent;
      goto redo;
      end;
   end;
end;

function tbasiccontrol.rootparent:tbasiccontrol;
label
   redo;
begin
result:=self;
redo:
if zzok(result,2312) and result.visible then
   begin
   if zzok(result.parent,2312) then
      begin
      result:=result.parent;
      goto redo;
      end;
   end;
//.finalise
if (result=self) then result:=nil;
end;

function tbasiccontrol.areatohost(da:twinrect):twinrect;
label
   redo;
var
   a:tbasiccontrol;
   aa:twinrect;
begin
result:=nilarea;//invalid area

try
a:=self;
redo:
if zzok(a,4001) and a.visible then
   begin
   //limit
   if zzok(a.parent,4002)   then aa:=a.parent.clientinner2(a) else aa:=a.clientarea;//detect useable area within parent -> e.g. don't paint over the parent's border area etc
   if (da.left<aa.left)     then da.left:=aa.left;
   if (da.right>aa.right)   then da.right:=aa.right;
   if (da.top<aa.top)       then da.top:=aa.top;
   if (da.bottom>aa.bottom) then da.bottom:=aa.bottom;
   //loop
   if gui.xareaok(da) then
      begin
      if zznil(a.parent,2114) then result:=da
      else
         begin
         a:=a.parent;
         goto redo;
         end;
      end;
   end;
except;end;
end;

procedure tbasiccontrol.setvisible(x:boolean);
begin

if (x<>ivisible) then
   begin
   ivisible:=x;

   //.tell paint system to repaint screen area the window "had" occupied - 21may2020
   if (winstyle>wmcontrol) and (not x) then gui.paintallnow
   else parentpaintnow;

   end;

end;

procedure tbasiccontrol.setenabled(x:boolean);
begin
if (x<>ienabled) then
   begin
   ienabled:=x;
   parentpaintnow;
   end;
end;

function tbasiccontrol.setbounds(x,y,w,h:longint):boolean;
begin
if zzok(parent,7181) then
   begin
   inc(x,parent.clientarea.left);
   inc(y,parent.clientarea.top);
   end;
result:=xsetclientarea(area__make(x,y,x+w-1,y+h-1));
end;

procedure tbasiccontrol.setclientarea(a:twinrect);
begin
xsetclientarea(a);
end;

function tbasiccontrol.xsetclientarea(a:twinrect):boolean;
var
   bs:longint;
begin
//defaults
result:=false;

try
//range
if (a.left>min32) then a.right:=frcmin32(a.right,a.left-1);
if (a.top>min32)  then a.bottom:=frcmin32(a.bottom,a.top-1);
//decide
if (winstyle>=wmFullwin) then//01mar2021, 25feb2021
   begin
   bs:=findbordersize;
   low__minwh(a,frcmin32(frcmin32(ominwidth,2*bs),minwinsize),frcmin32(frcmin32(ominheight,2*bs),minwinsize));
   end;
//Note: We MUST allow controls to have an invalid area so they do not show on the screen under important circumstances - 01mar2021
//was: else low__minwh(a,ominwidth,ominheight);
//get
if (iclientarea.left<>a.left) or (iclientarea.right<>a.right) or
   (iclientarea.top<>a.top) or (iclientarea.bottom<>a.bottom) then
   begin
   iclientarea.left:=a.left;
   iclientarea.right:=a.right;
   iclientarea.top:=a.top;
   iclientarea.bottom:=a.bottom;
   ainc;
   result:=true;
   end;
except;end;
end;

function tbasiccontrol.xlimitsize:boolean;
var
   a:twinrect;
begin
result:=false;

try
a:=iclientarea;
if ((a.right-a.left+1)>gui.width) then
   begin
   a.left:=0;
   a.right:=gui.width-1;
   result:=true;
   end;
if ((a.bottom-a.top+1)>gui.height) then
   begin
   a.top:=0;
   a.bottom:=gui.height-1;
   result:=true;
   end;
if result then xsetclientarea(a);
except;end;
end;

function tbasiccontrol.getleft:longint;
begin
result:=iclientarea.left;
if zzok(iparent,7182) then dec(result,iparent.clientarea.left);
end;

function tbasiccontrol.gettop:longint;
begin
result:=iclientarea.top;
if zzok(iparent,7183) then dec(result,iparent.clientarea.top);
end;

function tbasiccontrol.clientspace:twinrect;
begin
result:=area__make(0,0,iclientarea.right-iclientarea.left,iclientarea.bottom-iclientarea.top);
end;

function tbasiccontrol.clientinner:twinrect;
begin
result:=clientinner2(nil);
end;

function tbasiccontrol.clientinner2(x:tbasiccontrol):twinrect;
var
   a:twinrect;
   bs:longint;
begin
a:=iclientarea;
bs:=findbordersize;
result:=area__make(a.left+bs,a.top+bs,a.right-bs,a.bottom-bs);
end;

function tbasiccontrol.getclientwidth:longint;
begin
result:=iclientarea.right-iclientarea.left+1;
end;

function tbasiccontrol.getclientheight:longint;
begin
result:=iclientarea.bottom-iclientarea.top+1;
end;

procedure tbasiccontrol.setclientwidth(x:longint);
begin
setbounds(iclientarea.left,iclientarea.top,x,clientheight);
end;

procedure tbasiccontrol.setclientheight(x:longint);
begin
setbounds(iclientarea.left,iclientarea.top,clientwidth,x);
end;

function tbasiccontrol.xinside(x:tpoint):boolean;
begin
result:=xinside2(x.x,x.y);
end;

function tbasiccontrol.xinside2(sx,sy:longint):boolean;
var
   a:tbasiccontrol;
begin
result:=false;

try
if xwindow(a) and (gui.winhover=a.coreindex) then//cursor is on our form
   begin
   inc(sx,iclientarea.left);
   inc(sy,iclientarea.top);
   result:=(sx>=ipaintarea.left) and (sx<=ipaintarea.right) and (sy>=ipaintarea.top) and (sy<=ipaintarea.bottom);
   end;
except;end;
end;

function tbasiccontrol.xinsideclientarea(x:tpoint):boolean;
begin
result:=xinsideclientarea2(x.x,x.y);
end;

function tbasiccontrol.xinsideclientarea2(sx,sy:longint):boolean;
var
   a:tbasiccontrol;
   bs:longint;
begin
result:=false;

try
if xwindow(a) and (gui.winhover=a.coreindex) then//cursor is on our form
   begin
   bs:=findbordersize;
   inc(sx,iclientarea.left);
   inc(sy,iclientarea.top);
   result:=(sx>=(ipaintarea.left+bs)) and (sx<=(ipaintarea.right-bs)) and (sy>=(ipaintarea.top+bs)) and (sy<=(ipaintarea.bottom-bs));
   end;
except;end;
end;

function tbasiccontrol.xwinfocused:boolean;
var
   a:tbasiccontrol;
begin
result:=xwindow(a) and (a.coreindex=gui.winfocus);
end;

function tbasiccontrol.xwindow2(var x:tbasicscroll):boolean;//return our containing window
var
   a:tbasiccontrol;
begin
//defaults
result:=false;

try
x:=nil;
//get
if xwindow(a) and (a<>nil) and (a is tbasicscroll) then
   begin
   result:=true;
   x:=(a as tbasicscroll);
   end;
except;end;
end;

function tbasiccontrol.xwindow(var x:tbasiccontrol):boolean;//return our containing window
label
   redo;
var
   a:tbasiccontrol;
begin
//defaults
result:=false;

try
a:=self;
//find
redo:
if zzok(a,7185) and (a.winstyle<=wmcontrol) and zzok(a.parent,7186) then
   begin
   a:=a.parent;
   goto redo;
   end;
//get
if zzok(a,7186) and (a.winstyle>wmcontrol) then
   begin
   x:=a;
   result:=true;
   end;
except;end;
end;

function tbasiccontrol.xwindowindex:longint;
var
   a:tbasiccontrol;
begin
if xwindow(a) then result:=a.coreindex else result:=-1;
end;

function tbasiccontrol.gethelpline:string;
var
   str1,str2:string;
begin
str1:=strdefb(ihelp2,ihelp);
str2:=strdefb(isubhelp2,isubhelp);
result:=str1+insstr(' | ',(str1<>'') and (str2<>''))+str2;
end;

function tbasiccontrol.gethintline:string;
begin
if (ihint='*') then result:=helpline else result:=ihint;
end;

procedure tbasiccontrol.nohint;
begin
ihint:='';
end;

function tbasiccontrol.xfindheight(xclientwidth:longint;var xheight:longint):boolean;
begin
//defaults
result:=false;
xheight:=0;

try
//event
if assigned(fonfindheight) then
   begin
   xheight:=fonfindheight(self,xclientwidth);
   result:=true;
   end;
except;end;
end;

function tbasiccontrol.getalignheight(xclientwidth:longint):longint;
begin
if not xfindheight(xclientwidth,result) then result:=frcmin32(frcmin32(clientheight,ominheight),0);
end;

function tbasiccontrol.getalignwidth(xclientheight:longint):longint;
begin
result:=frcmin32(frcmin32(clientwidth,ominwidth),0);
end;

procedure tbasiccontrol.setbordersize(x:longint);
begin
ibordersize:=frcrange32(x,0,72);
end;

function tbasiccontrol.findbordersize:longint;//16may2025
begin
case oborderstyle of
bsInternal:result:=ibordersize*vizoom;
bsSystem100:result:=vibordersize;
bsSystem50:result:=frcmin32(vibordersize div 2,low__insint(4*vizoom,vibordersize>=1));//16may2025
bsSystem20:result:=frcmin32(vibordersize div 5,low__insint(4*vizoom,vibordersize>=1));//16may2025
else result:=ibordersize*vizoom;
end;
end;

procedure tbasiccontrol._ontimer(sender:tobject);
begin
//nil
end;

procedure tbasiccontrol.xtimer;//30nov2025, 02sep2025
begin

//lock
if itiming or (istable<>0) then exit else itiming:=true;

//event
if itimer then
   begin

   try
   _ontimer(self);
   if assigned(fontimer2) then fontimer2(self);
   except;end;

   end;

//unlock
itiming:=false;

end;

procedure tbasiccontrol.alignpaintnow__heightcheck(xalign,xpaint:boolean;xclientwidth:longint);//06jan2025
begin
//full
if (xalign or xpaint) and (getalignheight(xclientwidth)<>clientheight) then gui.fullalignpaint;
//partial
if xalign then alignnow;
if xpaint then paintnow;
end;

procedure tbasiccontrol.alignallnow;
begin//host does all alignment at once as a whole -> slower but easier and reliable
gui.alignallnow;
end;

procedure tbasiccontrol.alignnow;
begin//host does all alignment at once as a whole -> slower but easier and reliable
if not visibletohost then exit;
imustalign:=true;
gui.alignnow;
end;

procedure tbasiccontrol._onalign(sender:tobject);
begin
//We are expected to size and child controls we own - no need to tell host
//of a size or paint request -> this is automatic when done within this proc.
//But outside of this proc a paintnow / alignnow request will probably be
//required for the GUI to update properly - 20mar2020
if assigned(onalign) then onalign(self);
end;

procedure tbasiccontrol.xalign;
var
   a:tbasiccontrol;
   p:longint;
begin
try
//check
if ialigning or (istable<>0) then exit else ialigning:=true;

//init
ialigned:=false;

//.wmfullmode -> parentless window only
if zznil(parent,2315) and (winstyle=wmfullwin) then
   begin
   if setbounds(0,0,gui.width,gui.height) then imustalign:=true;
   end;

if imustalign or parentaligned then
   begin
   ialigned:=true;
   _onalign(self);//self
   end;

//align children
if (ownlist.count>=1) then
   begin
   for p:=0 to (ownlist.count-1) do if gui.xownget(ownlist,p,a) then
      begin
      if a.visible then a.xalign;
      a.xmustalign:=false;
      end;//p
   end;

except;end;
try
ialigned:=false;
ialigning:=false;
except;end;
end;

procedure tbasiccontrol.paintallnow;
begin
gui.paintallnow;
end;

procedure tbasiccontrol.paintnow;
begin//mark ourselves as needing to repaint AND tell the host to fire up the GUI paint proc
//check - detect if control is "not visible" or "scrolled out of sight" etc - 05apr2020
if (not visibletohost) or (not xcanpaint) then exit;
imustpaint:=true;
gui.paintnow;
end;

procedure tbasiccontrol.paintimmediate;//use sparingly - 09sep2021
begin
paintnow;
gui.pumptimer2;
end;

procedure tbasiccontrol.parentpaintnow;
begin//mark ourselves as needing to repaint AND tell the host to fire up the GUI paint proc
if zzok(iparent,7188) and parent.visibletohost then parent.paintnow else paintnow;
end;

procedure tbasiccontrol.parentalignnow;
begin//host does all alignment at once as a whole -> slower but easier and reliable
if zzok(iparent,7187) and iparent.visibletohost then iparent.alignnow else alignnow;
end;

procedure tbasiccontrol.alignpaintnow;//05oct2020
begin
alignnow;
paintnow;
end;

procedure tbasiccontrol.alignpaintallnow;//05oct2020
begin
alignallnow;
paintallnow;
end;

procedure tbasiccontrol.xframeSimple(const s:tclientinfo);//29mar2026
begin

if (s.bs>=1) then fframeSimple( s.cs ,s.bs ,s.border ,255 ,false ,s.r );

end;

procedure tbasiccontrol._onpaint(sender:tobject);
var
   s:tclientinfo;
begin

//external event override
if assigned(fonpaint) then
   begin
   fonpaint(sender);
   exit;
   end;

//init
infovars(s);

//cls
if      (winstyle=wmfullwin)                       then ffillArea(s.cs,s.back,s.r)//13jan2026
else if (winstyle>wmfullwin) and (winstyle<=wmmax) then ffillArea(s.cs,s.back,s.r)
else                                                    ffillArea(s.cs,s.back,false);

//frame
if (s.bs>=1) then
   begin

   //window frame -> needs "dround" for roundness override feature//xxxxxxxxxxxxxx add this back in...xxxxxxxxxxxxxxxxxxxx//was:...
   if      (winstyle=wmfullwin) then//01aug2020
      begin

      fframe( s.cs ,s.bs ,findframe ,findframe2 ,255 ,(s.sparkle>=1) ,s.r );

      end

   else if (winstyle>wmfullwin) and (winstyle<=wmmax) then
      begin

      fframe( s.cs ,s.bs ,findframe ,findframe2 ,255 ,(s.sparkle>=1) ,s.r );

      end

   //control frame
   else
      begin

      fframe( s.cs ,s.bs ,s.border ,s.back ,255 ,false ,s.roundframe );//28mar2026

      end;

   end;

end;

function tbasiccontrol.xcanpaint:boolean;
begin
result:=ivisible and visibletohost and gui.xareaok(iclientarea) and gui.xareaok(areatohost(iclientarea));
end;

function tbasiccontrol.xcanpaint_fast:boolean;//checks only the current layer -> assumes all previous layers have already been checked -> done for maximum speed - 05apr2020
begin
result:=ivisible and gui.xareaok(iclientarea);
end;

function tbasiccontrol.parentpainted:boolean;
begin
result:=zzok(iparent,7191) and iparent.painted;
end;

function tbasiccontrol.parentaligned:boolean;
begin
result:=zzok(iparent,7192) and iparent.aligned;
end;

function tbasiccontrol.scrolling:boolean;//13jan2026
begin
result:=false;
end;

function tbasiccontrol.xscrollingHost__captureCorners:boolean;
var
   xpaintarea:twinrect;
begin

if rounded then
   begin

   xpaintarea :=areatohost(iclientarea);
   result     :=area__valid(xpaintarea);

   if result then
      begin

      fd__select( gui.fdCorners );
      fd__setCorner( xcornerCode );//07jan2026
      fd__setCorner( xcornerMode );//13jan2026
      fd__setarea( fd_clip ,xpaintarea );
      fd__setarea( fd_area ,iclientarea );
      fd__render( fd_roundStartFromArea );

      end;

   end
else result:=false;

end;

function tbasiccontrol.xpaint:boolean;//21mar2020
var
   xcaptureCount,p:longint;
   a:tbasiccontrol;//pointer only
   xmustCorners,xmustpaint:boolean;

   //if we are in partial.paint mode and our parent/parents are scrolling, then our parent/parents need to capture their corners first, and render them last
   procedure xscrollingHosts__captureCorners;
   label
      redo;
   var
      a:tbasiccontrol;
   begin

   //check
   if not gui.paintingpart then exit;

   //get
   a:=self;
   redo:

   a:=a.parent;
   if (a<>nil) and (a.winstyle=wmControl) then
      begin

      if a.scrolling and a.xscrollingHost__captureCorners then inc(xcaptureCount);
      goto redo;

      end;

   end;

begin

//defaults
result        :=false;

//check
if ipainting or (istable<>0) or (gui.stable<>0) then exit else ipainting:=true;

//init
xmustpaint        :=imustpaint;
imustpaint        :=false;
ipainted          :=false;

//get
if xcanpaint then
   begin

   ipaintarea:=areatohost(iclientarea);

   if (not gui.paintingpart) or (xmustpaint or parentpainted) then
      begin

      //init
      ipainted        :=true;
      xmustCorners    :=true;
      xcaptureCount   :=0;

      //partial paint -> if we are a control on a scrolling host we must ask the host to capture its corners BEFORE we paint, so we can RENDER the host cornders AFTER our own - 13jan2026
      if gui.paintingpart then xscrollingHosts__captureCorners;

      //round corners (capture)
      fd__select( gui.fdCorners );
      fd__setCorner( xcornerCode );//07jan2026
      fd__setCorner( xcornerMode );//13jan2026
      fd__setarea( fd_clip ,ipaintarea );
      fd__setarea( fd_area ,iclientarea );
      fd__render( fd_roundStartFromArea );

      //paint control
      fd__select( gui.fdControls );
      fd__setarea( fd_clip ,ipaintarea );
      fd__setarea( fd_area ,iclientarea );
      fd__setval( fd_layer ,gui.maskval );

      _onpaint(self);

      //add paint area
      if gui.paintingpart then gui.xpartpaint__addarea(ipaintarea);

      //.paint tracking
      low__iroll(postpaintid,1);

      end
   else xmustCorners:=false;

   //paint children
   if (ownlist.count>=1) then
      begin

      for p:=0 to (ownlist.count-1) do if gui.xownget(ownlist,p,a) then
         begin

         if a.visible then a.xpaint;
         a.xmustpaint:=false;

         end;//p

      end;

   //render corners -> draw round corners (erase any square corners rendered by control or control's children)
   if xmustCorners then
      begin

      fd__select( gui.fdCorners );
      fd__render( fd_roundStopAndRender );

      //render scrollHosts corners
      for p:=1 to xcaptureCount do fd__render( fd_roundStopAndRender )

      end;

   //successful
   result:=true;

   end;

//finished
ipainted     :=false;
ipainting    :=false;

end;

function tbasiccontrol.xmustpaintcount:longint;
var
   p:longint;
   a:tbasiccontrol;
begin

//defaults
result :=0;

//check
if (istable<>0) then exit;

//get
if xmustpaint then inc(result);

//.children
if (ownlist.count>=1) then
   begin

   for p:=0 to (ownlist.count-1) do if gui.xownget(ownlist,p,a) and a.visible then inc(result,a.xmustpaintcount);

   end;

end;

function tbasiccontrol.yshift:longint;
begin
result:=ipaintarea.top-iclientarea.top;
end;

function tbasiccontrol.xshift:longint;
begin
result:=ipaintarea.left-iclientarea.left;
end;

function tbasiccontrol.mousex:longint;
begin
result:=mousexy.x;
end;

function tbasiccontrol.mousey:longint;
begin
result:=mousexy.y;
end;

function tbasiccontrol.mousexy:tpoint;
var
   a,b:tpoint;
begin
result:=low__point(0,0);

try
b:=gui.clienttoscreen(low__point(0,0));
low__getcursorpos(a);
result.x:=a.x-b.x-iclientarea.left;
result.y:=a.y-b.y-iclientarea.top;
except;end;
end;

function tbasiccontrol._onnotify(sender:tobject):boolean;
begin
//defaults
result:=false;

try
//external event override
if assigned(fonnotify) then result:=fonnotify(sender)
//showmenu - 11oct2020
else if mustshowmenu then
   begin
   showmenu;
   result:=true;
   end;
except;end;
end;

function tbasiccontrol._onshortcut(sender:tobject):boolean;
begin
result:=false;
end;

procedure tbasiccontrol._onfocus(sender:tobject);
begin
//nil
end;

function tbasiccontrol.focused:boolean;
begin
result:=(gui.focuscontrol=self);
end;

procedure tbasiccontrol.setfocus;
begin
if visible and enabled then gui.focuscontrol:=self;
end;

procedure tbasiccontrol.setfocusforce;
begin
gui.focuscontrol:=self;
end;


//-- draw support --------------------------------------------------------------

procedure tbasiccontrol.ffillOUTSIDE(dx,dy,dw,dh,dcol:longint);//26mar2026
var
   cw,ch:longint;
begin

//init
dw          :=frcmin32(dw,0);
dh          :=frcmin32(dh,0);
cw          :=clientwidth;
ch          :=clientheight;

//left
ffillArea(area__make(0,0,dx-1,ch-1),dcol,false);

//right
ffillArea(area__make(dx+dw,0,cw-1,ch-1),dcol,false);

//top
ffillArea(area__make(dx,0,dx+dw-1,dy-1),dcol,false);

//bottom
ffillArea(area__make(dx,dy+dh,dx+dw-1,ch-1),dcol,false);

end;

function tbasiccontrol.rounded:boolean;
begin
result:=viround and ((oroundstyle=corRound) or (oroundstyle=corSlight));
end;

function tbasiccontrol.xcornerCode:longint32;//08jan2026, 05jan2026
begin

if viround then
   begin

   case oroundstyle of
   corRound     :result:=fd_roundCorner;
   corSlight    :result:=fd_roundCornerTight;
   else          result:=fd_roundNone;
   end;//case

   end
else result:=fd_roundNone;

end;

function tbasiccontrol.xcornerMode:longint32;//13jan2026
begin

if viRound then
   begin

   if (iroundmode2<>rmNil) then
      begin

      case iroundMode2 of
      rmAll     :result:=fd_roundmodeAll;
      rmTopOnly :result:=fd_roundmodeTopOnly;
      rmBotOnly :result:=fd_roundmodeBotOnly;
      else       result:=fd_roundmodeNone;
      end;//case

      end
   else
      begin

      case oroundMode of
      rmAll     :result:=fd_roundmodeAll;
      rmTopOnly :result:=fd_roundmodeTopOnly;
      rmBotOnly :result:=fd_roundmodeBotOnly;
      else       result:=fd_roundmodeNone;
      end;//case

      end;

   end
else result:=fd_roundmodeNone;

end;

procedure tbasiccontrol.xroundMode_StartOverride(const x:longint);
begin
iroundMode2:=x;
end;

procedure tbasiccontrol.xroundMode_StopOverride;
begin
iroundMode2:=rmNil;
end;

procedure tbasiccontrol.fsketchArea(const darea:twinrect;const dcol:longint);
begin//requires corner image "xcornerCode" for measurements - 13jan2026

fast__sketchArea( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dcol ,xcornerCode );

end;

procedure tbasiccontrol.fframe(const darea:twinrect;const dsize,dcol1,dcol2,dpower255:longint;const dsparkle,dround:boolean);
begin

if dsparkle then fd__sparkleSetPos( isparkleStartPos );

case dround of
true:fast__frameArea( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,viFramecode ,dsize ,dcol1 ,dcol2 ,dpower255 ,xcornerCode ,xcornerMode ,dsparkle ,dround );
else fast__frameArea( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,viFramecode ,dsize ,dcol1 ,dcol2 ,dpower255 ,0           ,0           ,dsparkle ,false  );
end;//case

end;

procedure tbasiccontrol.fframeSimple(const darea:twinrect;const dsize,dcol,dpower255:longint;const dsparkle,dround:boolean);
begin

if dsparkle then fd__sparkleSetPos( isparkleStartPos );

case dround of
true:fast__frameSimpleArea( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dsize ,dcol ,dpower255 ,xcornerCode ,xcornerMode ,dsparkle ,dround );
else fast__frameSimpleArea( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dsize ,dcol ,dpower255 ,0           ,0           ,dsparkle ,false  );
end;//case

end;

procedure tbasiccontrol.fcolorMatrix(const darea:twinrect;const dround:boolean);
begin

case dround of
true:fast__colorMatrix( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,xcornerCode ,xcornerMode ,dround );
else fast__colorMatrix( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,0           ,0           ,false  );
end;//case

end;

procedure tbasiccontrol.foutlineArea(const darea:twinrect;const dcol:longint;const dround:boolean);
begin

foutlineArea2( darea ,dcol ,255 ,false ,dround );

end;

procedure tbasiccontrol.foutlineArea2(const darea:twinrect;const dcol,dpower255:longint;const dsparkle,dround:boolean);
begin

case dround or dsparkle of
true:begin

   if dsparkle then fd__sparkleSetPos( isparkleStartPos );

   fast__outlineArea2( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dcol ,dpower255 ,xcornerCode ,xcornerMode ,dsparkle ,dround);

   end;
else fast__outlineArea ( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dcol ,dpower255 );
end;//case

end;

procedure tbasiccontrol.ffillArea(const darea:twinrect;const dcol:longint;const dround:boolean);
begin

case dround of
true:fast__fillArea2( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dcol ,xcornerCode ,xcornerMode ,true);
else fast__fillArea ( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dcol );
end;//case

end;

procedure tbasiccontrol.ffillArea2(const darea:twinrect;const dcol,dpower255:longint;const dround:boolean);
begin

fast__fillArea3( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dcol ,dpower255 ,xcornerCode ,xcornerMode ,dround);

end;

procedure tbasiccontrol.fshadeArea(const darea:twinrect;const dcol1,dcol2:longint;const dround:boolean);
begin

case dround of
true:fast__shadeArea2( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dcol1 ,dcol2 ,xcornerCode ,xcornerMode ,true );
else fast__shadeArea ( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dcol1 ,dcol2 );
end;//case

end;

procedure tbasiccontrol.fshadeArea2(const darea:twinrect;const dcol1,dcol2,dcol3,dcol4,dsplice100,dpower255:longint;const dround:boolean);
begin

fast__shadeArea3( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dcol1 ,dcol2 ,dcol3 ,dcol4 ,dsplice100 ,dpower255 ,xcornerCode ,xcornerMode ,dround );

end;

procedure tbasiccontrol.fshadeOutlineArea(const darea:twinrect;const dcol1,dcol2,dcol3,dcol4,dsplice100,dpower255:longint;const dsparkle,dround:boolean);
begin

if dsparkle then fd__sparkleSetPos( isparkleStartPos );

case dround of
true:fast__shadeOutlineArea( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dcol1 ,dcol2 ,dcol3 ,dcol4 ,dsplice100 ,dpower255 ,xcornerCode ,xcornerMode ,dsparkle ,dround );
else fast__shadeOutlineArea( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,dcol1 ,dcol2 ,dcol3 ,dcol4 ,dsplice100 ,dpower255 ,0           ,0           ,dsparkle ,false );
end;//case

end;

procedure tbasiccontrol.finvertArea(const darea:twinrect;const dround:boolean);
begin

case dround of
true:fast__invertArea2( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,xcornerCode ,xcornerMode ,true);
else fast__invertArea ( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) );
end;//case

end;

procedure tbasiccontrol.finvertCorrectedArea(const darea:twinrect;const dround:boolean);
begin

case dround of
true:fast__invertCorrectedArea2( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) ,xcornerCode ,xcornerMode ,true);
else fast__invertCorrectedArea ( ipaintarea ,area__make(darea.left+iclientarea.left,darea.top+iclientarea.top,darea.right+iclientarea.left,darea.bottom+iclientarea.top) );
end;//case

end;

procedure tbasiccontrol.ftext(const dbackRef:longint;const darea:twinrect;const dx,dy,dcol:longint;const dtab,dtext:string;const dfont:longint32;const denabled:boolean);//20feb2026
var
   da:twinrect;
begin

da:=area__clip( area__shift(darea,iclientarea.left,iclientarea.top) ,ipaintarea );

case denabled of
true:fast__drawText ( low__aorb( clnone ,dbackRef ,viemboss ) ,da ,da ,dx+iclientarea.left ,dy+iclientarea.top ,dcol ,dtab ,dtext ,dfont ,cdNone ,vifeather );
else fast__drawText2( low__aorb( clnone ,dbackRef ,viemboss ) ,da ,da ,dx+iclientarea.left ,dy+iclientarea.top ,dcol ,power_disabled ,dtab ,dtext ,dfont ,cdNone ,0 ,0 ,vifeather ,false );
end;//case

end;

procedure tbasiccontrol.ftext2(const dbackRef:longint;const darea:twinrect;const dx,dy,dcol,dpower255:longint;const dtab,dtext:string;const dfont,dfeather4:longint32;const denabled,dround:boolean);//20feb2026
var
   da:twinrect;
begin

da:=area__clip( area__shift(darea,iclientarea.left,iclientarea.top) ,ipaintarea );

if (dpower255<=0) then exit

else if dround or (dpower255<255) or (not denabled) then
   begin

   fast__drawText2(  low__aorb( clnone ,dbackRef ,viemboss ) ,da ,da ,dx+iclientarea.left ,dy+iclientarea.top ,dcol ,fast__calcPower255(dpower255,denabled) ,dtab ,dtext ,dfont ,cdNone ,xcornerCode ,xcornerMode ,dfeather4 ,dRound );

   end

else
   begin

   fast__drawText (  low__aorb( clnone ,dbackRef ,viemboss ) ,da ,da ,dx+iclientarea.left ,dy+iclientarea.top ,dcol ,dtab ,dtext ,dfont ,cdNone, dfeather4 );

   end;

end;

procedure tbasiccontrol.ftep(const dindex,dx,dy,dcol:longint;const denabled:boolean);
begin

tep__draw(ipaintarea,dindex,iclientarea.left+dx,iclientarea.top+dy,dcol,fast__calcPower255(power_enabled,denabled));

end;

procedure tbasiccontrol.ftep1(const dindex,dx,dy,dcol,dpower255:longint;const denabled:boolean);
begin

tep__draw(ipaintarea,dindex,iclientarea.left+dx,iclientarea.top+dy,dcol ,fast__calcPower255(dpower255,denabled) );

end;

procedure tbasiccontrol.ftep2(const dindex,dx,dy,dcol1,dcol2,dcol3,dcol4,dpower255:longint;const denabled:boolean);
begin

tep__draw2(ipaintarea,dindex,iclientarea.left+dx,iclientarea.top+dy,dcol1,dcol2,dcol3,dcol4 ,fast__calcPower255(dpower255,denabled) );

end;

procedure tbasiccontrol.fdraw(const d:tobject;const dx,dy,dcol,dpower255:longint;const denabled:boolean);
begin

fast__draw(ipaintarea,d,iclientarea.left+dx,iclientarea.top+dy,dcol, fast__calcPower255(dpower255,denabled) ,false ,false );

end;

procedure tbasiccontrol.fdraw2(const d:tobject;const dx,dy,dcol1,dcol2,dcol3,dcol4,dpower255:longint;const denabled:boolean);
begin

fast__draw2(ipaintarea,d,iclientarea.left+dx,iclientarea.top+dy,dcol1,dcol2,dcol3,dcol4,fast__calcPower255(dpower255,denabled),viFeather,false,false);

end;

procedure tbasiccontrol.fdraw3(const d:tobject;const sa:twinrect;const dx,dy,dw,dh,dcol,dpower255,dfeather4:longint;const dmirror,dflip,denabled:boolean);
begin

fast__draw3(ipaintarea,d,sa,iclientarea.left+dx,iclientarea.top+dy,dw,dh,dcol,dcol,dcol,dcol,fast__calcPower255(dpower255,denabled),dfeather4,dmirror,dflip);

end;

procedure tbasiccontrol.fdraw4(const d:tobject;const sa:twinrect;const dx,dy,dw,dh,dcol1,dcol2,dcol3,dcol4,dpower255,dfeather4:longint;const dmirror,dflip,denabled:boolean);
begin

fast__draw3(ipaintarea,d,sa,iclientarea.left+dx,iclientarea.top+dy,dw,dh,dcol1,dcol2,dcol3,dcol4,fast__calcPower255(dpower255,denabled),dfeather4,dmirror,dflip);

end;


//## tbasicimgview #############################################################
constructor tbasicimgview.create2(xparent:tobject;xstart:boolean);
begin
//self
if classnameis('tbasicimgview') then track__inc(satImgview,1);
inherited create2(xparent,false);

//vars
inewimagedata         :=nil;
ishown                :=true;
fonevent              :=nil;
icanevent             :=false;
itimer100             :=slowms64;
ianimatetimer1        :=slowms64;
ianimatetimer2        :=ianimatetimer1;
ifadetimer            :=slowms64;
iloading              :=false;
iworking              :=false;
iid                   :=0;
iloadid               :=0;
ilastid               :=iid;
ibackcolor            :=clnone;
ifillstyle            :=vfsDefault;
ifadespeed            :=15;//faster
ifadepower            :=0;
icountcolors          :=false;
ifillback             :=false;
ianimate              :=true;

//.image info
iwidth                :=0;
iheight               :=0;
ibpp                  :=0;
icolors               :=0;
icells                :=0;
idelay                :=0;
ibytes                :=0;
ifilename             :='';
iinfostr              :='';

//.new
inewfilename          :='';
inewfilenameREF       :='';

//controls
iimg32    :=misraw32(1,1);
inew32    :=misraw32(1,1);
ibuf32    :=misraw32(1,1);

//start
if xstart then start;

end;

destructor tbasicimgview.destroy;
begin
try

//disconnect timer
timer                 :=false;

//controls
freeobj(@ibuf32);
freeobj(@inew32);
freeobj(@iimg32);
str__free(@inewimagedata);

//self
inherited destroy;
if classnameis('tbasicimgview') then track__inc(satImgview,-1);

except;end;
end;

procedure tbasicimgview.xincid;//settings id
begin
low__iroll(iid,1);
end;

procedure tbasicimgview.xincloadid;//load id
begin
low__iroll(iloadid,1);
end;

procedure tbasicimgview.setbackcolor(x:longint);
begin
if low__setint(ibackcolor,x) then xincid;
end;

procedure tbasicimgview.setfillstyle(x:longint);
begin
if low__setint(ifillstyle,frcrange32(x,0,vfsMax)) then xincid;
end;

procedure tbasicimgview.setfadespeed(x:longint);
begin
if low__setint(ifadespeed,frcrange32(x,0,100)) then xincid;
end;

procedure tbasicimgview.setcountcolors(x:boolean);
begin
if low__setbol(icountcolors,x) then xincid;
end;

procedure tbasicimgview.setanimate(x:boolean);
begin
if low__setbol(ianimate,x) then xincid;
end;

procedure tbasicimgview.setfillback(x:boolean);
begin
if low__setbol(ifillback,x) then xincid;
end;

function tbasicimgview.findinfob(xname,xdefval:string):string;
begin
findinfo(xname,xdefval,result);
end;

function tbasicimgview.findinfo(xname,xdefval:string;var xvalue:string):boolean;
begin
//defaults
result:=true;

//init
xname:=strlow(xname);

//get
if      (xname='wh')       then xvalue:=k64(iwidth)+'w x '+k64(iheight)+'h'
else if (xname='bpp')      then xvalue:=k64(ibpp)
else if (xname='cells')    then xvalue:=k64(icells)
else if (xname='delay')    then xvalue:=k64(idelay)
else if (xname='colors')   then xvalue:=k64(icolors)
else if (xname='bytes')    then xvalue:=k64(ibytes)
else if (xname='file')     then xvalue:=ifilename
else                            result:=false;

//set
if result then xvalue:=strdefb(xvalue,xdefval) else xvalue:='';
end;

procedure tbasicimgview.loadfromfile(x:string;xuseai:boolean);
begin

iloading    :=true;
icanevent   :=true;
ishown      :=false;
inewfilename:=bolstr(xuseai)+x;
itimer100   :=1;//reset timer

end;

procedure tbasicimgview.loadfromdata(x:pobject;xuseai:boolean);
begin
//check
if not str__lock(x) then exit;

//get
iloading    :=true;
icanevent   :=true;
ishown      :=false;

if (inewimagedata=nil) then inewimagedata:=str__new8;
inewimagedata.clear;
str__add(@inewimagedata,x);

inewimagedata.tag1:=1;//signal timer we're active
inewimagedata.tag2:=insint(1,xuseai);
itimer100   :=1;//reset timer

str__uaf(x);

end;

function tbasicimgview.working:boolean;
begin
result:=iloading or iworking or (ifadepower<510);
end;

function tbasicimgview.xcanload:boolean;
begin
result:=(inewfilename<>'');
end;

procedure tbasicimgview.xload(xuseFilename,xuseData:boolean);
const
   sep=' | ';
var
   xfilename,e:string;
   int1,sw,sh:longint;
   shasai,stransparent:boolean;

   procedure xclear;
   begin
   missize(inew32,1,1);
   ibytes   :=0;
   end;

begin
try

//from filename ----------------------------------------------------------------
if xuseFilename then
   begin

   //get
   inew32.ai.use32    :=strbol(strcopy1(inewfilename,1,1));
   xfilename          :=strcopy1(inewfilename,2,low__len32(inewfilename));

   //.last
   if (ifadepower<510) then xkeeplast;

   //.from file
   case mis__fromfile(inew32,xfilename,e) of
   true:ibytes:=io__filesize64(xfilename);
   else xclear;
   end;//case

   end

//from data --------------------------------------------------------------------
else if xusedata and (inewimagedata<>nil) then
   begin

   //get
   inew32.ai.use32    :=(inewimagedata.tag2>=1);
   xfilename          :='';//internal data stream -> therefore we have no filename

   //.last
   if (ifadepower<510) then xkeeplast;

   //.from data
   case mis__fromdata(inew32,@inewimagedata,e) of
   true:ibytes:=str__len32(@inewimagedata);
   else xclear;
   end;//case
   
   end

//clear ------------------------------------------------------------------------
else xclear;

//info
if inew32.ai.use32 then inew32.ai.itemindex:=0;

if ximgok(inew32) then
   begin

   //get
   miscells(inew32,int1,sw,sh,icells,iwidth,iheight,idelay,shasai,stransparent);
   ibpp     :=misai(inew32).bpp;

   case icountcolors of
   true:icolors:=miscountcolors(inew32);
   else icolors:=0;
   end;//case

   //set
   iinfostr :=k64(iwidth)+'w x '+k64(iheight)+'h'+sep+intstr32(ibpp)+' bit'+insstr(sep+k64(icells)+' cells',icells>=2)+insstr(sep+k64(icolors)+' colors',icountcolors);

   end
else
   begin

   iwidth   :=0;
   iheight  :=0;
   idelay   :=0;
   ibpp     :=0;
   icells   :=0;
   icolors  :=0;
   ibytes   :=0;
   iinfostr :='';

   end;

//set
ifilename             :=xfilename;
ifadepower            :=0;
ianimatetimer1        :=0;
ianimatetimer2        :=0;
ifadetimer            :=0;

//id - 05dec2024
low__iroll(iloadid,1);

except;end;
end;

procedure tbasicimgview.xkeeplast;
begin

if (ifadespeed>=1) then miscopy(inew32,iimg32) else missize(iimg32,1,1);

end;

function tbasicimgview.getimage32:trawimage;
begin
if (ifadespeed>=1) then result:=iimg32 else result:=inew32;
end;

procedure tbasicimgview._ontimer(sender:tobject);
var
   xmustpaint:boolean;
   xms64:comp;
   vold:longint;

   function xanimate(s:tobject):comp;
   var
      int1:longint;
      a:panimationinformation;
   begin

   if ximgok(s) then
      begin

      //get
      a     :=misai(s);
      int1  :=frcrange32(a.itemindex,0,frcmin32(a.count-1,0));

      if (a.delay<=0) or (a.count<=1)  then int1:=0 else inc(int1);
      if (int1>=a.count)               then int1:=0;
      if low__setint(a.itemindex,int1) then xmustpaint:=true;

      //set
      result:=add64(xms64,frcrange32(a.delay,50,1000));

      end

   else result:=add64(xms64,1000);

   end;

begin

//check
if (istable<>0) then exit;

//init
xmustpaint  :=false;
xms64       :=slowms64;

try

//.itimer100
if (xms64>itimer100) then
   begin

   //ref
   if low__setint(ilastid,iid) then xmustpaint:=true;//12dec2024

   //load
   if low__setstr(inewfilenameREF,inewfilename) then
      begin

      iworking        :=true;
      xload(true,false);
      xmustpaint      :=true;

      end;

   //load 2
   if (inewimagedata<>nil) and (inewimagedata.tag1=1) then
      begin

      inewimagedata.tag1     :=0;

      xload(false,true);

      xmustpaint             :=true;

      inewimagedata.clear;

      end;

   //reset
   iloading           :=false;
   itimer100          :=add64(xms64,100);

   end;

//.animate timers
if ianimate then
   begin

   if (xms64>=ianimatetimer1) and ximgok(inew32) then ianimatetimer1:=xanimate(inew32);
   if (xms64>=ianimatetimer2) and ximgok(iimg32) then ianimatetimer2:=xanimate(iimg32);

   end;

//.fade timer
if (xms64>ifadetimer) or (ifadespeed<=0) then
   begin

   if (ifadepower<510) then
      begin

      vold  :=ifadepower;

      //.wait for last paint before incrementing further
      case (ifadespeed<=0) of
      true:ifadepower:=510//instant
      else ifadepower:=frcrange32(ifadepower+(5*ifadespeed),0,510);
      end;//case

      //.finished incrementing
      if (ifadepower>=510) then
         begin

         case (ifadespeed>=1) of
         true:miscopy(inew32,iimg32);
         else missize(iimg32,1,1);
         end;//case

         end;

      //.have incremented -> signal a repaint and higher system performance
      if (vold<>ifadepower) then
         begin

         xmustpaint   :=true;
         app__turbo;

         end;

      //.set a fast timer response
      ifadetimer      :=add64(xms64,50);

      end
   else ifadetimer    :=add64(xms64,100);

   end;

//paint
if xmustpaint then paintnow;

//working
if (ifadepower>=510) then
   begin

   iworking :=false;
   if icanevent then xevent;

   end;

except;end;
end;

procedure tbasicimgview.xevent;//12dec2024
begin
try

ishown      :=true;
icanevent   :=false;

if assigned(fonevent) then fonevent(self);

except;end;
end;

procedure tbasicimgview.xrender__dual(sbits,sw,sh,sr,sg,sb,sa:longint;srows:pcolorrows24;a,b:tobject;fa,fb,da,db,da2,db2:twinrect;a255,b255,aa255,bb255,atrans,btrans,atc,btc:longint);
label//render upto 2 images upto 2 times on the screen in one pass for maximum throughput -> upto 400% faster than using separate passes
     //assumes "a" and "b" to be 32bit images
   skipend;
var
   ars32,brs32:pcolorrows32;
   sr32,ar32,br32,ar322,br322:pcolorrow32;
   sr24:pcolorrow24;
   b32,s32,d32:tcolor32;
   d24:tcolor24;
   ar,ag,ab,br,bg,bb:longint32;
   ax ,ay ,bx ,by :pdllongint;
   ax2,ay2,bx2,by2:pdllongint;
   _ax ,_ay ,_bx ,_by :tdynamicinteger;//mapper support
   _ax2,_ay2,_bx2,_by2:tdynamicinteger;//mapper support

   //.image values
   aok:boolean;
   bok:boolean;
   aay2,aay,abits,aw,ah:longint;
   bby2,bby,bbits,bw,bh:longint;

   //.other
   p255,sx,p,dw,fw,dx,dy:longint;
   bol1:boolean;

   function ra(var a:twinrect;const aw,ah:longint):boolean;//restrict area
   begin

   a.left   :=frcrange32(a.left   ,0 ,aw-1 );
   a.right  :=frcrange32(a.right  ,0 ,aw-1 );
   a.top    :=frcrange32(a.top    ,0 ,ah-1 );
   a.bottom :=frcrange32(a.bottom ,0 ,ah-1 );

   result   :=(a.right>=a.left) and (a.bottom>=a.top);

   end;

   function mapx(const fa,da:twinrect;var xlist:pdllongint;var xcore:tdynamicinteger):boolean;
   begin

   //defaults
   result   :=false;

   //map destination.x to source.image.x
   xcore    :=rescache__newMapped( 1 ,(da.right-da.left+1) ,fa.left ,fa.right ,(fa.right-fa.left+1) );
   xlist    :=xcore.core;

   //successful
   result   :=true;

   end;

   function mapy(const fa,da:twinrect;var xlist:pdllongint;var xcore:tdynamicinteger):boolean;
   begin

   //defaults
   result   :=false;

   //map destination.y to source.image.y
   xcore    :=rescache__newMapped( 1 ,(da.bottom-da.top+1) ,fa.top ,fa.bottom ,(fa.bottom-fa.top+1) );
   xlist    :=xcore.core;

   //successful
   result   :=true;

   end;

   procedure xtrans(const xmode,xcolor:longint32;var r,g,b:longint);
   var
      c24:tcolor24;
   begin

   if (xmode>=1) and (xcolor<>clnone) then
      begin

      c24   :=int__c24(xcolor);
      r     :=c24.r;
      g     :=c24.g;
      b     :=c24.b;

      end
   else
      begin

      r     :=-1;
      g     :=-1;
      b     :=-1;

      end;

   end;

begin

//defaults
_ax         :=nil;
_ay         :=nil;
_ax2        :=nil;
_ay2        :=nil;
_bx         :=nil;
_by         :=nil;
_bx2        :=nil;
_by2        :=nil;
sr24        :=nil;
sr32        :=nil;
ar32        :=nil;
br32        :=nil;
ar322       :=nil;
br322       :=nil;

try

//check
if ((sbits<>24) and (sbits<>32)) or (sw<1) or (sh<1) or (srows=nil) then goto skipend;//screen to render to

//range
a255        :=frcrange32(a255,0,255);
b255        :=frcrange32(b255,0,255);
aa255       :=frcrange32(aa255,0,255);
bb255       :=frcrange32(bb255,0,255);
aok         :=(a255>=1) and misok82432(a,abits,aw,ah) and (abits=32) and (fa.right>=fa.left) and (fa.bottom>=fa.top) and misrows32(a,ars32);//1st image
bok         :=(b255>=1) and misok82432(b,bbits,bw,bh) and (bbits=32) and (fb.right>=fb.left) and (fb.bottom>=fb.top) and misrows32(b,brs32);//2nd image

//map x and y coordinates (sx -> dx)
if aok then
   begin

   if not ra(fa,aw,ah)       then goto skipend;
   if not mapx(fa,da,ax,_ax) then goto skipend;
   if not mapy(fa,da,ay,_ay) then goto skipend;

   if (aa255>=1) then
      begin

      if not mapx(fa,da2,ax2,_ax2) then goto skipend;
      if not mapy(fa,da2,ay2,_ay2) then goto skipend;

      end;

   end;

if bok then
   begin

   if not ra(fb,bw,bh)       then goto skipend;
   if not mapx(fb,db,bx,_bx) then goto skipend;
   if not mapy(fb,db,by,_by) then goto skipend;

   if (bb255>=1) then
      begin

      if not mapx(fb,db2,bx2,_bx2) then goto skipend;
      if not mapy(fb,db2,by2,_by2) then goto skipend;

      end;

   end;

//transparent color
xtrans(atrans,atc,ar,ag,ab);
xtrans(btrans,btc,br,bg,bb);

//background color
b32.r       :=frcrange32(sr,0,255);
b32.g       :=frcrange32(sg,0,255);
b32.b       :=frcrange32(sb,0,255);
b32.a       :=frcrange32(sa,0,255);

//draw color pixels ------------------------------------------------------------
//dy
for dy:=0 to pred(sh) do
begin

if aok and (dy>=da.top) and (dy<=da.bottom) then
   begin

   aay      :=ay[dy-da.top];
   ar32     :=ars32[aay];

   end
else aay    :=-1;

if aok and (aa255>=1) and (dy>=da2.top) and (dy<=da2.bottom) then
   begin

   aay2     :=ay2[dy-da2.top];
   ar322    :=ars32[aay2];

   end
else aay2   :=-1;

if bok and (dy>=db.top) and (dy<=db.bottom) then
   begin

   bby      :=by[dy-db.top];
   br32     :=brs32[bby];

   end
else bby    :=-1;

if bok and (bb255>=1) and (dy>=db2.top) and (dy<=db2.bottom) then
   begin

   bby2     :=by2[dy-db2.top];
   br322    :=brs32[bby2];

   end
else bby2   :=-1;


if      (sbits=32) then sr32:=pcolorrow32(srows[dy])
else if (sbits=24) then sr24:=pcolorrow24(srows[dy])
else                    break;


//dx
for dx:=0 to pred(sw) do
begin

//start with background color
d32         :=b32;

//.1st image - background echo (bottom layer)
if (aay2>=0) and (dx>=da2.left) and (dx<=da2.right) then
   begin

   sx       :=ax2[dx-da2.left];
   s32      :=ar322[sx];

   if (ar<>s32.r) or (ag<>s32.g) or (ab<>s32.b) then
      begin

      p255  :=(s32.a*aa255) shr 8;

      if (p255>d32.a) then d32.a:=p255;

      if (p255=255) then d32:=s32
      else if (p255>=1) then
                        begin

                        d32.r:=((d32.r*(255-p255)) + (s32.r*p255)) shr 8;
                        d32.g:=((d32.g*(255-p255)) + (s32.g*p255)) shr 8;
                        d32.b:=((d32.b*(255-p255)) + (s32.b*p255)) shr 8;

                        end;

      end;

   end;//aay2


//.2nd image - background echo (top layer)
if (bby2>=0) and (dx>=db2.left) and (dx<=db2.right) then
   begin

   sx       :=bx2[dx-db2.left];
   s32      :=br322[sx];

   if (br<>s32.r) or (bg<>s32.g) or (bb<>s32.b) then
      begin

      p255  :=(s32.a*bb255) shr 8;

      if (p255>d32.a) then d32.a:=p255;

      if (p255=255) then d32:=s32
      else if (p255>=1) then
                        begin

                        d32.r:=((d32.r*(255-p255)) + (s32.r*p255)) shr 8;
                        d32.g:=((d32.g*(255-p255)) + (s32.g*p255)) shr 8;
                        d32.b:=((d32.b*(255-p255)) + (s32.b*p255)) shr 8;

                        end;

      end;

   end;//bby


//.1st image
if (aay>=0) and (dx>=da.left) and (dx<=da.right) then
   begin

   sx       :=ax[dx-da.left];
   s32      :=ar32[sx];

   if (ar<>s32.r) or (ag<>s32.g) or (ab<>s32.b) then
      begin

      p255  :=(s32.a*a255) shr 8;

      if (p255>d32.a) then d32.a:=p255;

      if (p255=255) then d32:=s32
      else if (p255>=1) then
                        begin

                        d32.r:=((d32.r*(255-p255)) + (s32.r*p255)) shr 8;
                        d32.g:=((d32.g*(255-p255)) + (s32.g*p255)) shr 8;
                        d32.b:=((d32.b*(255-p255)) + (s32.b*p255)) shr 8;

                        end;

      end;

   end;//aay


//.2nd image
if (bby>=0) and (dx>=db.left) and (dx<=db.right) then
   begin

   sx       :=bx[dx-db.left];
   s32      :=br32[sx];

   if (br<>s32.r) or (bg<>s32.g) or (bb<>s32.b) then
      begin

      p255  :=(s32.a*b255) shr 8;

      if (p255>d32.a) then d32.a:=p255;

      if (p255=255) then d32:=s32
      else if (p255>=1) then
                        begin

                        d32.r:=((d32.r*(255-p255)) + (s32.r*p255)) shr 8;
                        d32.g:=((d32.g*(255-p255)) + (s32.g*p255)) shr 8;
                        d32.b:=((d32.b*(255-p255)) + (s32.b*p255)) shr 8;

                        end;

      end;

   end;//bby


//.write pixel
if      (sbits=32)  then sr32[dx]:=d32
else if (sbits=24)  then
   begin

   d24.r    :=d32.r;
   d24.g    :=d32.g;
   d24.b    :=d32.b;
   sr24[dx] :=d24;//03feb2025

   end;

end;//dx

end;//dy

skipend:
except;end;

//free
rescache__delMapped( @_ax );
rescache__delMapped( @_ay );
rescache__delMapped( @_ax2 );
rescache__delMapped( @_ay2 );

rescache__delMapped( @_bx );
rescache__delMapped( @_by );
rescache__delMapped( @_bx2 );
rescache__delMapped( @_by2 );

end;

procedure tbasicimgview._onpaint(sender:tobject);//28may2021, 26apr2021
begin

xrenderto(0,0,0,nil);

end;

procedure tbasicimgview.xrenderto(dbits,dw,dh:longint;drows:pcolorrows24);
var
   s:tclientinfo;
   xanimate,xrender:boolean;
   cw,ch:longint;
   cs,ci:twinrect;

   procedure xscale(s:tobject;s255:longint;var sa,da,de:twinrect;var de255,xtrans,xtc:longint);
   var
      a:panimationinformation;
      z:twinrect;
      n:string;
      int1,int2,sbits,sw,sh,dw,dh,cpos:longint;
   begin

   z        :=miscellarea(s,0);
   sw       :=z.right-z.left+1;
   sh       :=z.bottom-z.top+1;

   if misok82432(s,sbits,int1,int2) and ( ((sw>=2) and (sh>=1)) or ((sw>=1) and (sh>=2)) ) then
      begin
      //.fill style
      case ifillstyle of
      vfsScale:begin
         low__scaledown(cw,ch,sw,sh,dw,dh);
         de255:=0;
         end;
      vfsScreen:begin
         low__scale(cw,ch,sw,sh,dw,dh);
         de255:=0;
         end;
      vfsCrop:begin
         low__scalecrop(cw,ch,sw,sh,dw,dh);
         de255:=0;
         end;
      vfsFit:begin
         dw:=cw;
         dh:=ch;
         de255:=0;
         end;
      vfsEcho:begin
         low__scaledown(cw,ch,sw,sh,dw,dh);
         de255:=s255;
         end;
      vfsEcho2:begin
         low__scaledown(cw,ch,sw,sh,dw,dh);
         de255:=s255;
         end;
      else
         begin
         low__scaledown(cw,ch,sw,sh,dw,dh);
         de255:=0;
         end;
      end;//case

      da.left    :=(cw-dw) div 2;
      da.right   :=da.left+dw-1;
      da.top     :=(ch-dh) div 2;
      da.bottom  :=da.top+dh-1;

      a          :=misai(s);
      n          :=strlow(a.format);
      xtrans     :=insint(1,a.transparent and (n<>'png') and (n<>'gif') and (n<>'ani') and (n<>'ico') and (n<>'cur') and (n<>''));//don't use old top-left transparency method for formats that accidently fail to provide a format value - 23may2022
      xtc        :=low__aorb(clnone,mispixel24VAL(s,0,0),xtrans>=1);

      if xanimate then cpos:=frcrange32(a.itemindex,0,frcmin32(a.count-1,0)) else cpos:=0;

      sa         :=miscellarea(s,cpos);

      end
   else
      begin

      dw         :=0;
      dh         :=0;
      de255      :=0;
      de         :=nilarea;
      da         :=nilarea;
      sa         :=nilarea;
      xtrans     :=0;
      xtc        :=clnone;

      end;//if

   //.background -> echo -> enlarged/faint view of image
   if (de255>=1) then
      begin

      low__scalecrop(cw,ch,sw,sh,dw,dh);
      dw        :=dw*2;
      dh        :=dh*2;
      de.left   :=(cw-dw) div 2;
      de.right  :=de.left+dw;
      de.top    :=(ch-dh) div 2;
      de.bottom :=de.top+dh;

      if (ifillstyle=vfsEcho2) then de255:=frcmin32(round(de255*0.75),1);

      end;

   end;

   procedure xdraw2(a:tobject;a255:longint;ause:boolean;b:tobject;b255:longint;buse:boolean);
   var
      aok,bok:boolean;
      fa,fb,da,db,daa,dbb:twinrect;
      aa255,bb255,atrans,atc,btrans,btc:longint;
      c24:tcolor24;
    begin

   //init
   aok      :=ause and (a255>=0) and (a<>nil);
   bok      :=buse and (b255>=0) and (b<>nil);
   cw       :=ci.right  - ci.left + 1;
   ch       :=ci.bottom - ci.top  + 1;

   //.a
   if aok then xscale(a,a255,fa,da,daa,aa255,atrans,atc)
   else
      begin

      a255            :=0;
      aa255           :=0;
      atrans          :=0;
      atc             :=clnone;
      fa              :=nilarea;

      end;

   //.b
   if bok then xscale(b,b255,fb,db,dbb,bb255,btrans,btc)
   else
      begin

      b255            :=0;
      bb255           :=0;
      btrans          :=0;
      btc             :=clnone;
      fb              :=nilarea;
      
      end;

   //get
   if xrender then
      begin

      if (misw(ibuf32)<>1) or (mish(ibuf32)<>1) then missize(ibuf32,1,1);//shrink to save on memory

      xrender__dual(dbits,dw,dh,0,0,0,255,drows,a,b,fa,fb,da,db,daa,dbb,a255,b255,aa255,bb255,atrans,btrans,atc,btc);

      end
   else
      begin

      if (misw(ibuf32)<>cw) or (mish(ibuf32)<>ch) then missize(ibuf32,cw,ch);

      c24   :=int__c24(s.back);//18may2025

      xrender__dual( misb(ibuf32) ,misw(ibuf32) ,mish(ibuf32) ,c24.r ,c24.g ,c24.b ,0 ,
                     ibuf32.prows24 ,a ,b ,fa ,fb ,da ,db ,daa ,dbb ,a255 ,b255 ,aa255 ,bb255 ,atrans ,btrans ,atc ,btc );

      fdraw(ibuf32,ci.left,ci.top,clnone,power_enabled ,true);//02apr2026

      end;

   end;

begin

//init
xrender     :=(dbits>=1) and (dw>=1) and (dh>=1) and (drows<>nil);
xanimate    :=ianimate;

if xrender then
   begin

   cs       :=area__make(0,0,dw-1,dh-1);
   ci       :=cs;
   cw       :=dw;
   ch       :=dh;

   end
else
   begin

   infovars(s);
   cs       :=s.cs;
   ci       :=s.ci;
   cw       :=ci.right-ci.left+1;
   ch       :=ci.bottom-ci.top+1;

   if (ibackcolor<>clnone) and (system_blackwhitecount<=0) then s.back:=ibackcolor;//11dec2024

   end;

//cls
if not xrender then ffillArea(ci,s.back,s.r);

//draw image(s)
if (ifadespeed=0)                                  then xdraw2(inew32,255,true,  nil,0,false)
else
   begin

  if (not ximgok(inew32)) and ximgok(iimg32)      then
     begin

     xdraw2(iimg32,(510-ifadepower) div 2,ifadepower>=1,  nil,0,false);

     end

   else if ximgok(inew32) and (not ximgok(iimg32)) then
      begin

      xdraw2(inew32,ifadepower div 2,true,  nil,0,false);

      end

   else if ximgok(inew32) and ximgok(iimg32) then
      begin

      case (ifadepower<=255) of
      true:xdraw2(iimg32,255,true,  inew32,ifadepower,ifadepower>=1);
      else xdraw2(iimg32,510-ifadepower,(510-ifadepower)>=1,  inew32,255,true);
      end;//case

      end;

   end;

//normal mode
if not xrender then
   begin

   //frame
   if (s.bs>=1) then fframeSimple( s.cs ,s.bs ,s.border ,255 ,false ,s.roundFrame );

   end;

end;

function tbasicimgview._onnotify(sender:tobject):boolean;
begin
//defaults
result:=false;//handled

try

if gui.mousedown and (not gui.mousewasdown) then
   begin
   if      (mousedownxy.x<round(clientwidth*0.3)) then imustmode:=-1//prev
   else if (mousedownxy.x>round(clientwidth*0.7)) then imustmode:=1//next
   else                                                imustmode:=0;//none
   end;

//event
if assigned(onnotify) then result:=onnotify(sender);
except;end;
end;

function tbasicimgview.ximgok(s:tobject):boolean;
var
   sbits,sw,sh:longint;
begin
result:=misok82432(s,sbits,sw,sh) and ( ((sw>=2) and (sh>=1)) or ((sw>=1) and (sh>=2)) );
end;


//## tbasicscrollbar ###########################################################
constructor tbasicscrollbar.create2(xparent:tobject;xstart:boolean);
begin

//self
if classnameis('tbasicscrollbar') then track__inc(satScrollbar,1);
inherited create2(xparent,false);

//options
overtical           :=true;
owheelchange        :=1;
osmallchange        :=1;
olargechange        :=10;
oassistedscroll     :=10;
ofullhandling       :=true;

//vars
inormal             :=true;
ipos                :=0;
imin                :=0;
imax                :=0;
idownpos            :=0;
idownbutindex       :=-1;//off
iscrollscope        :=0;
ibordersize         :=1;
idowntime64         :=0;//off
itimer100           :=slowms64;
itimerscroll        :=slowms64;
idragbut            :=area__make(0,0,-1,-1);
idragzone           :=area__make(0,0,-1,-1);
idragbutdown        :=false;//09feb2022
fonpos              :=nil;
fonarrow            :=nil;

//controls
clientheight        :=5;

//start
if xstart then start;

end;

destructor tbasicscrollbar.destroy;
begin
try
//disconnect timer
timer:=false;
//disconnect events
fonpos:=nil;
//self
inherited destroy;
if classnameis('tbasicscrollbar') then track__inc(satScrollbar,-1);
except;end;
end;

procedure tbasicscrollbar.setpos(x:longint);
begin
setparams(x,imin,imax);
end;

procedure tbasicscrollbar.setparams(xpos,xmin,xmax:longint);
begin
setparams2(xpos,xmin,xmax,true);
end;

procedure tbasicscrollbar.setparams2(xpos,xmin,xmax:longint;xevent:boolean);
begin//Note: paint handled via "ontimer()" proc
try
//range
xmax:=frcmin32(xmax,xmin);
xpos:=frcrange32(xpos,xmin,xmax);
//get
if (xpos<>ipos) or (xmin<>imin) or (xmax<>imax) then
   begin
   ipos:=xpos;
   imin:=xmin;
   imax:=xmax;
   iposref64:=slowms64+2000;//faster tracking - 08feb2022
   xfaster;
   if xevent and assigned(fonpos) then fonpos(self);
   end;
except;end;
end;

procedure tbasicscrollbar._ontimer(sender:tobject);
const
   xlimit=20000;
var
   xmustpaint:boolean;
   xdir,int1:longint;

   procedure xincpos(const xdown:boolean);
   begin
   pos:=pos+xmoveval( low__aorb(-1,1,xdown) );
   end;

begin
try

//defaults
xmustpaint:=false;

//.itimer100
if (slowms64>itimer100) then
   begin

   //control info
   if low__setstr(iinforef,bolstr(gui.hoverindex=icoreindex)+bolstr(overtical)+bolstr(inormal)+pcRefsep+intstr32(findbordersize)+pcRefsep+intstr32(ipos)+pcRefsep+intstr32(imin)+pcRefsep+intstr32(imax)+pcRefsep+intstr32(viscrollsize)) then xmustpaint:=true;

   //reset
   itimer100:=slowms64+low__aorb(100,10,iposref64>=slowms64);//08feb2022

   end;

//.itimerscroll
if (slowms64>itimerscroll) then
   begin

   //slow
   int1:=250;

   //get
   if focused and enabled and gui.mousedown and (not gui.mousedraggingfine) and (not gui.mouseupstroke) and (slowms64>=idowntime64) then
      begin

      case overtical of
      true:xincpos( mousedownxy.y>=(clientheight div 2) );
      else xincpos( mousedownxy.x>=(clientwidth div 2) );
      end;//case

      //variable autoscroll speed - 12dec2025
      int1:=10 + round(160*(1-( div64(frcrange64(sub64(slowms64,idowntime64),0,xlimit),xlimit) )));

      end;

   //reset
   itimerscroll:=slowms64+int1;

   end;

//wound scroller - 28sep2022
if (oassistedscroll<>0) and xwound_mustpaint(pos,oassistedscroll,int1,xdir) then
   begin

   if (int1<>pos) then pos:=int1;
   xwound_autooff(pos,xdir,min,max);

   end;

//paint
if xmustpaint then paintnow;

except;end;
end;

function tbasicscrollbar.getalignheight(xclientwidth:longint):longint;
begin
if overtical then result:=clientheight else result:=frcmin32((2*findbordersize)+low__instouch(viscrollsize,vitouchsize20),0);
result:=frcmin32(result,ominheight);//25jul2021
end;

function tbasicscrollbar.getalignwidth(xclientheight:longint):longint;
begin
if overtical then result:=frcmin32((2*findbordersize)+low__instouch(viscrollsize,vitouchsize20),0) else result:=clientwidth;
result:=frcmin32(result,ominwidth);//25jul2021
end;

function tbasicscrollbar.xmoveval(x:longint):longint;
begin
if assigned(fonarrow) then fonarrow(self,result) else result:=x;
end;

function tbasicscrollbar._onnotify(sender:tobject):boolean;
var
   int1,dx,dy:longint;
begin

//defaults
result     :=ofullhandling;//not handled

try

//wheel
if ofullhandling and (gui.wheel<>0) then
   begin

   result:=true;//12dec2025

   if enabled then
      begin

      pos:=pos-(gui.wheel*owheelchange);
      xwound_wheel(gui.wheel*70);

      end;

   end;

//key
if ofullhandling and (gui.key<>aknone) then
   begin
   case gui.key of
   akhome:begin
      if enabled then pos:=imin;
      result:=true;
      end;
   akend:begin
      if enabled then pos:=imax;
      result:=true;
      end;
   akleft,akup:begin
      if enabled then pos:=pos+xmoveval(-1);
      result:=true;
      end;
   akright,akdown:begin
      if enabled then pos:=pos+xmoveval(1);
      result:=true;
      end;
   akprev:begin
      if enabled then pos:=pos+xmoveval(-olargechange);
      result:=true;
      end;
   aknext:begin
      if enabled then pos:=pos+xmoveval(olargechange);
      result:=true;
      end;
   end;//case
   end;

//mousedownstroke
if gui.mousedownstroke then
   begin

   idowntime64  :=slowms64+500;
   idownpos     :=pos;
   dx           :=mousex;
   dy           :=mousey;
   idragbutdown :=low__xyinarea(dx,dy,idragbut);

   if low__xyinarea(dx,dy,idragzone) then idownbutindex:=2//drag
   else                                   idownbutindex:=-1;//off

   end;

//mouse down
if gui.mousedown then
   begin
   result:=true;
   end;

//mouse move
if gui.mousedown and gui.mousemoved and (not gui.mousedownstroke) then
   begin

   result:=true;

   if enabled and (iscrollscope>=1) and (idownbutindex=2) and gui.mouseleft then
      begin

      if overtical then int1:=gui.mousemovexy.y-gui.mousedownxy.y else int1:=gui.mousemovexy.x-gui.mousedownxy.x;
      pos:=round(idownpos+((int1)*iscrollscope));//normal

      end;

   end;

//mouse up - wound support - 04oct2022
if gui.mouseupstroke and gui.mousedragging and gui.mouseleft then xwound_mousevert3(3000,true,true,overtical);

//mouse up
if gui.mouseupstroke then
   begin

   result        :=true;
   idowntime64   :=0;
   idownbutindex :=-1;//off

   end;

//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);
except;end;
end;

procedure tbasicscrollbar._onpaint(sender:tobject);
label
   dovertical,dohorizontal,done;
const
   xmindrag=24;
var
   s:tclientinfo;
   dw,dh,pad1,p,int1,int2,int3,int4,int5,xmin,xmax:longint;
   xhoverok,xvertical:boolean;

   function xsmaller(x:twinrect;w,h,xminimalsize:boolean):twinrect;
   var
      v:longint;
   begin
   result:=x;

   //.width
   if w then
      begin

      case xminimalsize of
      true:v:=frcmin32( trunc( (x.right-x.left+1) * 0.3 ) ,2);
      else v:=frcmin32( (result.right-result.left+1) div 4 ,2);
      end;//case

      result.left :=frcrange32(result.left+v,result.left,result.right);
      result.right:=frcrange32(result.right-v,result.left,result.right);

      end;

   //.height
   if h then
      begin

      case xminimalsize of
      true:v:=frcmin32( trunc( (result.bottom-result.top+1) * 0.3 ) ,2);
      else v:=frcmin32( (result.bottom-result.top+1) div 4 ,2);
      end;//case

      result.top   :=frcrange32(result.top+v,result.top,result.bottom);
      result.bottom:=frcrange32(result.bottom-v,result.top,result.bottom);

      end;

   end;
begin
//init
infovars(s);
pad1      :=5*s.zoom;
xmin      :=imin;
xmax      :=imax;
s.e       :=s.e and (xmax>xmin);//adjust value
xvertical :=overtical;
dw        :=(s.cs.right-s.cs.left+1)-(2*s.bs);
dh        :=(s.cs.bottom-s.cs.top+1)-(2*s.bs);
xhoverok  :=s.e and (gui.hoverindex=icoreindex);

//cls
ffillArea(s.cs,s.back,false);

//decide
if xvertical then goto dovertical else goto dohorizontal;

//-- vertical ------------------------------------------------------------------
dovertical:

idragzone :=area__make(0,1,s.cw-1,s.ch-1);//11oct2020
int4      :=frcmin32(imax-imin+1,1);//count
int1      :=frcmin32(idragzone.bottom-idragzone.top+1,0);
int2      :=frcmin32(int1-int4,low__instouch(xmindrag,vitouchsize20));
int3      :=frcmin32(int1-int2,0);
int5      :=frcmin32(int1-int2,0);

if (int5<=0) then iscrollscope:=0 else iscrollscope:=int4/int5;

if (int3>=1) then
   begin
   p:=round(((pos-imin)/int4)*int3);
   idragbut:=area__make(idragzone.left,idragzone.top+p,idragzone.right,idragzone.top+int2-1+p);

   if (imax<>imin) then
      begin

      ffillarea( xsmaller(idragbut,true,false,not xhoverok),low__aorb(s.hover,s.hover2,xhoverok),s.r );//28mar2026

      end;

   end
else idragbut:=area__make(0,0,-1,-1);

goto done;

//-- horizontal ----------------------------------------------------------------
dohorizontal:

idragzone :=area__make(1,0,s.cw-1,s.ch-1);//17mar2021, 11oct2020
int4      :=frcmin32(imax-imin+1,1);//count
int1      :=frcmin32(idragzone.right-idragzone.left+1,0);
int2      :=frcmin32(int1-int4,low__instouch(xmindrag,vitouchsize20));
int3      :=frcmin32(int1-int2,0);
int5      :=frcmin32(int1-int2,0);

if (int5<=0) then iscrollscope:=0 else iscrollscope:=int4/int5;

if (int3>=1) then
   begin
   p:=round(((pos-imin)/int4)*int3);
   idragbut:=area__make(idragzone.left+p,idragzone.top,idragzone.left+int2-1+p,idragzone.bottom);

   if (imax<>imin) then
      begin

      ffillArea( xsmaller(idragbut,false,true,not xhoverok),low__aorb(s.hover,s.hover2,xhoverok),s.r );//13sep2025

      end;

   end
else idragbut:=area__make(0,0,-1,-1);

goto done;

//-- done ----------------------------------------------------------------------
done:

end;

//## tbasicsplash ##############################################################
constructor tbasicsplash.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tbasicsplash.create2(xparent:tobject;xstart:boolean);
begin

//self
if classnameis('tbasicsplash') then track__inc(satSplash,1);
inherited create2(xparent,false,false);

//vars
igap                :=1;
isize               :=1;
ititleref           :='';
ipreviousfocus      :=-1;//off
itimeout            :=0;//off
mkescape            :=true;
mkreturn            :=true;
ocode               :=0;//cancelled
ocode2              :='';
otepcolor           :=clnone;
otepcolor2          :=clnone;
bordersize          :=0;
winstyle            :=wmdialog;
static              :=true;
xhead.visible       :=false;
xhead.caption       :='About';
xhelp;
xhelp.showhelp      :=false;//don't show realtime help
normal              :=true;

//.screen -> image viewer
iscreen             :=ncontrol;
iscreen.oautoheight :=true;
iscreen.normal      :=true;
ititle32            :=misimg32(1,1);

//events
iscreen.onnotify    :=onnotify__screen;
iscreen.onpaint     :=onpaint__screen;

//start
if xstart then start;

end;

destructor tbasicsplash.destroy;
begin
try

freeobj(@ititle32);

inherited destroy;

if classnameis('tbasicsplash') then track__inc(satSplash,-1);

//restore previous focus -> splash only - 05sep2020
if (ipreviousfocus>=0) then
   begin

   //was: gui.winfocus:=ipreviousfocus; <- not enough on program 1st startup
   gui.focusindex :=ipreviousfocus;
   ipreviousfocus :=-1;

   end;

except;end;
end;

procedure tbasicsplash.xmaketitle(dw,dh:longint);//scaling support - 18mar2026, 11dec2025, 13sep2025: lighter memory usage when "fontfeatherf>=1", 08apr2025: improved for short titles
label
   skipend;
var
   xlast:pfastdraw;
   l:tresslot;
   f:tresslot;
   s:tclientinfo;
   sr32:pcolorrow32;
   f24:tcolor24;
   s32:tcolor32;
   a:tbasicimage;//pointer only
   v,sx,sy,bw,bh,aw,ah,fW,fH,sw,sh:longint;
   xname:string;
   bol1:boolean;
   b:tbasicimage;
   busedarea:twinrect;
begin

//defaults
b           :=nil;
l           :=res_nil;
f           :=res_nil;

//check
if not misok32(ititle32,sw,sh) then exit;

//name
xname:=app__info('name');
if not low__setstr(ititleref,intstr32(sw)+'|'+intstr32(sh)+'|'+xname) then exit;

try
//init

fd__selStore(xlast);
l           :=res__newFastdraw;//use a new dedicated fastdraw slot/record - 28feb2026
fd__select(l);
fd__defaults;

iscreen.infovars(s);

a           :=ititle32;
f           :=res__newfont;
res__font(f).setparams( 'arial' ,scale__px1(68,7) ,true ,true ,false );//18mar2026 - bold
fW          :=frcmin32(resfont__textwidth(f,xname),400);//for short names enforce a minimum width of 400px - 11dec2025, 08apr2025
fH          :=resfont__height(f);
f24         :=int__c24(s.font);

//get
missize(a,2+fW,2+fH);
aw          :=misw(a);
ah          :=mish(a);
miscls(a,0);

fd__setbuffer( fd_buffer ,a );
fast__drawText( clnone ,misarea(a) ,misarea(a) ,1 ,1 ,rgba__int(255,255,255,255) ,'' ,xname ,f ,cdNone ,viFeather );

//.create a 300-400% buffer a24b to enlarge the text in buffer a24 for upscaling/blurring
b           :=misimg32(3*misw(a),3*mish(a));//using font based feathering required less upscaling/blurring - 13sep2025
bw          :=misw(b);
bh          :=mish(b);

//.copy TEXT image a onto b
if not mis__copyfast(maxarea,misarea(a),0,0,misw(b),mish(b),a,b) then goto skipend;


//.blur the enlarged TEXT to generate a finer quality text outline
misblur82432(b);

//.find used area
busedarea.left        :=bw-1;
busedarea.right       :=0;
busedarea.top         :=bh-1;
busedarea.bottom      :=0;

for sy:=0 to (bh-1) do
begin

if not misscan32(b,sy,sr32) then goto skipend;

bol1        :=false;

for sx:=0 to (bw-1) do
begin

s32         :=sr32[sx];
v           :=s32.r;
if (s32.g>v) then v:=s32.g;
if (s32.b>v) then v:=s32.b;

if (v>=1) then
   begin

   if (sx<busedarea.left)      then busedarea.left:=sx;
   bol1:=true;

   end;

end;//sx

if bol1 then
   begin

   if (sy<busedarea.top)       then busedarea.top:=sy;
   if (sy>busedarea.bottom)    then busedarea.bottom:=sy;

   end;

end;//dy

//.use to the right hand margin
busedarea.right       :=bw-1;

//.shrink draw b buffer back onto a buffer
missize(a,dw,dh);

aw                    :=misw(a);
ah                    :=mish(a);

if not mis__copyfast(maxarea,busedarea,0,0,misw(a),mish(a),b,a) then goto skipend;

//.make mask based on b32.r/g/b
for sy:=0 to (ah-1) do
begin

if not misscan32(a,sy,sr32) then goto skipend;

for sx:=0 to (aw-1) do
begin

s32         :=sr32[sx];
v           :=s32.r;
if (s32.g>v) then v:=s32.g;
if (s32.b>v) then v:=s32.b;
s32.a       :=v;

if (v=255) then
   begin

   s32.r    :=f24.r;
   s32.g    :=f24.g;
   s32.b    :=f24.b;

   end
else if (v>=1) then
   begin

   s32.r    :=( (f24.r*v) + ((255-v)*91) ) div 256;
   s32.g    :=( (f24.g*v) + ((255-v)*91) ) div 256;
   s32.b    :=( (f24.b*v) + ((255-v)*91) ) div 256;

   end;

sr32[sx]    :=s32;

end;//sx

end;//dy

skipend:
except;end;

//free
freeobj(@b);
res__del( f );
fd__selRestore(xlast);
res__del( l );

end;

function tbasicsplash.onnotify__screen(sender:tobject):boolean;
begin
result:=false;
end;

procedure tbasicsplash.xsplash;
begin
try

ipreviousfocus        :=frcmin32(gui.winfocus,0);
winstyle              :=wmontop;
oborderstyle          :=bsSystem50;
xhead.visible         :=false;
xtoolbar2.visible     :=false;//27apr2022
xgrad.visible         :=false;//19aug2024

xsetclientarea(xcontentarea);
gui.xcenter(self);

gui.focuscontrol      :=self;
itimeout              :=slowms64+2000;//on

except;end;
end;

procedure tbasicsplash.xabout;
var
   xpreviouscontrol:tbasiccontrol;
begin
try

//init
xpreviouscontrol      :=gui.focuscontrol;
ipreviousfocus        :=gui.winfocus;
itimeout              :=0;//off
winstyle              :=wmdialog;
oborderstyle          :=bsSystem100;
xhead.visible         :=true;
xtoolbar2.visible     :=true;
xtoolbar2.normal      :=true;
xtoolbar2.oautoheight :=false;//disable wrap and force to one line - 25may2025
xgrad.visible         :=true;

//was: xgrad2.visible:=false;//true;//08apr2025
if (app__info('url.software')<>'') then xtoolbar2.cadd(ntranslate('App Website'),tepGo20,0,scVisitProgram,rthtranslate('External Content|Visit app website'),0);
if (app__info('url.portal')<>'')   then xtoolbar2.cadd(ntranslate('Web Portal'),tepGo20,0,scVisitPortal,rthtranslate('External Content|Visit web portal'),0);

xtoolbar2.cadd(ntranslate('OK'),tepYes20,1,scdlg,rthtranslate('App|Close window'),60*5);
xsetclientarea(xcontentarea);

gui.xcenter(self);
gui.focuscontrol      :=self;

gui.xshowwait(self,xpreviouscontrol,ipreviousfocus);

visible               :=false;//hide
itimeout              :=slowms64+1;
ipreviousfocus        :=-1;//off

except;end;
end;

function tbasicsplash.xcontentarea:twinrect;
label
   redo;
var
   p,xlinecount,xsize,xgap,sw,sh,cw,ch,int1:longint;
   xname,xvalue:string;
begin

//defaults
result :=area__make(0,0,300,100);

try
//init
sw     :=frcmin32(gui.width,1);
sh     :=frcmin32(gui.height,1);

if xhavehead and xhead.visible         then dec(sh,xhead.getalignheight(0));
if xhavetoolbar2 and xtoolbar2.visible then dec(sh,xtoolbar2.getalignheight(0));
if xhavegrad2 and xgrad2.visible       then dec(sh,xgrad.getalignheight(0));

sh     :=frcmin32(sh,1);

xlinecount:=0;
for p:=0 to 9 do if splash__findvalue(p,xname,xvalue) then inc(xlinecount);

//find acceptable size
int1   :=2*findbordersize;
xgap   :=15;
xsize  :=scale__px1(520,1);//11dec2025

redo:
cw:=frcmin32(((xgap+xsize+xgap))-1+int1,1);
ch:=frcmin32(((xgap+round(xsize / 3.0)+xgap))-1+int1,1);

if (cw>sw) or (ch>sh) then
   begin
   if (xsize>96) then
      begin
      xsize:=frcmin32(xsize-8,32);
      xgap:=frcmin32(xgap-1,2);
      goto redo;
      end;
   end;

//set
inc(cw, low__len32(app__info('name')) * 5 );
inc(ch, xlinecount*vifontheight div 2);

result:=area__make(0,0,cw-1,ch-1);
if xhavehead and xhead.visible         then inc(result.bottom,xhead.getalignheight(0));
if xhavetoolbar2 and xtoolbar2.visible then inc(result.bottom,xtoolbar2.getalignheight(0));
if xhavegrad2 and xgrad2.visible       then inc(result.bottom,xgrad.getalignheight(0));

isize:=frcmin32(xsize,1);
igap:=frcmin32(xgap,1);
except;end;
end;

procedure tbasicsplash.onpaint__screen(sender:tobject);
label
   redo;

var
   s:tclientinfo;
   xsize,xgap,ncount,xlineheight,tgap,ih,dy,p:longint;
   ta,ia:twinrect;
   str1,str2:string;
   v:array[0..9] of string;

begin

//defaults
iscreen.infovars(s);

xgap        :=frcmin32( round32(igap*viscale) ,1 );
xsize       :=frcmin32(isize,1);

//title
ta.top      :=xgap;//round(s.ch*0.15);
ta.bottom   :=round(s.ch / 3.0);//was 2.5 - 14jul2025
ta.left     :=xgap;
ta.right    :=s.cw-xgap;

xmaketitle(ta.right-ta.left+1,ta.bottom-ta.top+1);
//was: iscreen.ldc3(ta,ta.left,ta.top,ta.right-ta.left+1,ta.bottom-ta.top+1,misarea(ititle32),ititle32,255,0,0,clnone,0,true,true);
iscreen.fdraw3(ititle32,misarea(ititle32),ta.left,ta.top,ta.right-ta.left+1,ta.bottom-ta.top+1,clnone,power_enabled,vifeather,false,false,true);

//information text
ia.left     :=ta.left+round32(2*viscale);
ia.right    :=s.cw-1;
ia.top      :=ta.bottom;
ia.bottom   :=s.ch-1-xgap;
ih          :=ia.bottom-ia.top+1;
tgap        :=15*s.zoom;

ncount:=0;
for p:=0 to high(v) do if splash__findvalue(p,str1,str2) then
   begin

   v[ncount]          :=str1+#9+str2;
   inc(ncount);

   end;

if (ncount>=1) then
   begin

   redo:

   xlineheight        :=round(s.fnH*1.25);

   //.center vertically in remaining window space
   dy:=ta.bottom+round32(2*viscale)+ ( s.ch-ta.bottom - (ncount*xlineheight) ) div 2;

   for p:=0 to (ncount-1) do
   begin

   iscreen.ftext( s.back ,ia ,ia.left ,dy ,s.font ,'L70;L500;' ,v[p] ,s.Rfn ,true );//28feb2026
   inc(dy,xlineheight);

   end;//p

   end;

end;

function tbasicsplash.xmustclose:boolean;
begin
if (itimeout<>0) and ((slowms64>=itimeout) or (gui.focuscontrol<>self)) then result:=true else result:=false;
end;


//## tbasiccols ################################################################
constructor tbasiccols.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tbasiccols.create2(xparent:tobject;xstart:boolean);
var
   p:longint;
begin

//self
if classnameis('tbasiccols') then track__inc(satCols,1);
inherited create2(xparent,false);

//vars
omakeautoheight :=false;//26feb2021
ofillheight     :=false;//punches through everything and JUST makes it the full height of the parent's remainging vertical height - 07mar2022
ofullarea       :=true;
inormal         :=true;
ibordersize     :=0;
itimer250       :=slowms64;
iinforef        :='';
istyle          :=bcLefttoright;
ihsp            :=5;
ivsp            :=5;

//controls
for p:=0 to high(icols) do
begin
icols[p]      :=nil;
isize[p]      :=20;//20% each
imaxsizePX[p] :=0;//off
iwratio[p]    :=true;
iremcount[p]  :=0;//03feb2025
end;//p

//defaults
clientheight:=5;

//start
if xstart then start;

end;

destructor tbasiccols.destroy;
begin
try
inherited destroy;
if classnameis('tbasiccols') then track__inc(satCols,-1);
except;end;
end;

function tbasiccols.makecol(xindex,xremcount:longint;xscroll:boolean):tbasicscroll;//12may2025
begin
remcount[xindex]:=xremcount;
result:=cols2[xindex,1,xscroll];
end;

procedure tbasiccols.makeautoheight;//sets self and all STATIC children to oautoheight=true - 01mar2021, 26feb2021
var
   p:longint;
begin
try
omakeautoheight:=true;//signals all references to "getcols/2" to run THIS proc each time to maintain consistent autoheight expectation -> allows for code like this "rootwin.xhigh.xcolsh.cols[..]" where both "xcolsh" and "cols[..]" check and maintain autoheight for self and all children
oautoheight:=true;
for p:=0 to high(icols) do if zzok(icols[p],7200) and icols[p].static then icols[p].oautoheight:=true;
except;end;
end;

function tbasiccols.canautoheight:boolean;
var
   p:longint;
begin
result:=false;

try
if oautoheight then
   begin
   for p:=0 to high(icols) do if zzok(icols[p],7201) and icols[p].visible and icols[p].static and icols[p].oautoheight then
      begin
      result:=true;
      break;
      end;//p
   end;
except;end;
end;

function tbasiccols.getalignheight(xclientwidth:longint):longint;//12jul2025: column width correctly used now
var
   int1,v,p:longint;
   xok:boolean;

   function xcolumnwidth(xindex:longint):longint;//14jul2025, 12jul2025
   begin
   //14jul2025: xfindsize proc upgraded to handle "remcount"
   if (xindex>=0) and (xindex<=high(icols)) then result:=xfindsize(xindex,xclientwidth) else result:=0;
   end;
begin
//defaults
result:=0;

try
//init
xok:=false;
if omakeautoheight then makeautoheight;

//get
if canautoheight then
   begin

   for p:=0 to high(icols) do if zzok(icols[p],7202) and icols[p].visible and icols[p].static and icols[p].oautoheight then
      begin
      //was: v:=icols[p].getalignheight(xclientwidth);
      v:=icols[p].getalignheight( xcolumnwidth(p) );
      if (v>result) then result:=v;
      xok:=true;//atleast one panel has an autoheight value set we can use - 26feb2021
      end;//p

   end;

//fallback
if not xok then inherited getalignheight(xclientwidth);

//min
result:=frcmin32(result,ominheight);

//external - 06jul2021
if xfindheight(xclientwidth,int1) then result:=frcmin32(result,int1);

except;end;
end;

procedure tbasiccols.setstyle(x:longint);
begin
istyle:=frcrange32(x,0,bcMax);
end;

function tbasiccols.getcols(x:longint):tbasicscroll;
begin
result:=getcols2(x,50,false);
end;

function tbasiccols.getcols2(x,xsize:longint;xscroll:boolean):tbasicscroll;
begin
result:=getcols3(x,xsize,0,xscroll);
end;

function tbasiccols.getcols3(x,xsize,xmaxsizePX:longint;xscroll:boolean):tbasicscroll;//17nov2024
begin
//defaults
result:=nil;

try
//range
x:=frcrange32(x,0,high(icols));
//init
if zznil(icols[x],2319) then
   begin
   icols[x]:=nscroll('');
   icols[x].static:=not xscroll;
   icols[x].bordersize:=0;
   size[x]:=xsize;
   maxsizePX[x]:=xmaxsizePX;
   end;
//get
result:=icols[x];
if omakeautoheight then makeautoheight;
except;end;
end;

procedure tbasiccols.setvis(x:longint;xval:boolean);
begin
x:=frcrange32(x,0,high(icols));
if zzok(icols[x],7204) and (icols[x].visible<>xval) then
   begin
   icols[x].visible:=xval;
   alignpaintnow;
   end;
end;

function tbasiccols.getvis(x:longint):boolean;
begin
x:=frcrange32(x,0,high(icols));
result:=zzok(icols[x],7205) and icols[x].visible;
end;

procedure tbasiccols.setsize(x,xval:longint);
begin
isize[frcrange32(x,0,high(icols))]:=frcmax32(xval,100);
end;

function tbasiccols.getsize(x:longint):longint;
begin
result:=isize[frcrange32(x,0,high(icols))];
end;

procedure tbasiccols.setremcount(x,xval:longint);
begin
iremcount[frcrange32(x,0,high(icols))]:=frcmin32(xval,0);
end;

function tbasiccols.getremcount(x:longint):longint;
begin
result:=iremcount[frcrange32(x,0,high(icols))];
end;

procedure tbasiccols.setmaxsizePX(x,xval:longint);
begin
imaxsizePX[frcrange32(x,0,high(icols))]:=frcmin32(xval,0);//0=off=disabled=not used
end;

function tbasiccols.getmaxsizePX(x:longint):longint;
begin
result:=imaxsizePX[frcrange32(x,0,high(icols))];
end;

function tbasiccols.xfindsize(x,cw:longint):longint;//17nov2024
var
   rcount,p,int1:longint;
begin
//defaults
result:=0;

try
//range
cw:=frcmin32(cw,0);

//check
if (cw<=0) then exit;

//init
x:=frcrange32(x,0,high(icols));
int1:=isize[x];

//get
//.size as percentage of "cw"
if (int1>=1) then
   begin
   int1:=frcrange32(int1,1,100);//1..100%
   result:=frcrange32(round((int1/100)*cw),1,cw);
   end

//.size as fixed size + optional wration "fontwidth" scaling
else if (int1<=-1) then
   begin
   int1:=-int1;
   if iwratio[x] then int1:=round(int1*vifontwidthratio);
   //.also scale by vizoom - 17nov2024
   result:=frcrange32(int1*vizoom,1,cw);
   end;

 //.apply an upper limit range in STATIC PIXELS if one is set:
if (imaxsizePX[x]>=1) then result:=frcmax32(result,imaxsizePX[x]*vizoom);

//.size as remainder -> 14jul2025: remcount code was missing, causing inital misalignment before delayed correction
if (iremcount[x]>=1) then
   begin

   //get total rcount
   rcount:=0;
   for p:=0 to high(iremcount) do if (iremcount[p]>=1) then inc(rcount,iremcount[p]);

   //set
   result:=round( cw*(iremcount[x]/frcmin32(rcount,1)) );

   end;

except;end;
end;

procedure tbasiccols.setwratio(x:longint;xval:boolean);
begin
iwratio[frcrange32(x,0,high(icols))]:=xval;
end;

function tbasiccols.getwratio(x:longint):boolean;
begin
result:=iwratio[frcrange32(x,0,high(icols))];
end;

procedure tbasiccols.sethsp(x:longint);
begin
ihsp:=frcrange32(x,0,500);
end;

procedure tbasiccols.setvsp(x:longint);
begin
ivsp:=frcrange32(x,0,500);
end;

procedure tbasiccols._ontimer(sender:tobject);
var
   ca:twinrect;
   cw,ch,p:longint;
   str1:string;
   xmustalignpaint:boolean;
begin
try
//defaults
xmustalignpaint:=false;

//timer250
if (slowms64>=itimer250) then
   begin
   //get
   ca:=clientinner;
   cw:=frcmin32(ca.right-ca.left+1,0);
   ch:=frcmin32(ca.bottom-ca.top+1,0);
   str1:=intstr32(istyle)+'|';

   for p:=0 to high(icols) do if zzok(icols[p],7205) and icols[p].visible and (isize[p]<>0) then str1:=str1+intstr32(p)+'_'+intstr32(xfindsize(p,cw))+'_'+intstr32(xfindsize(p,ch))+'|';

   if low__setstr(iinforef,str1) then xmustalignpaint:=true;

   //reset
   itimer250:=slowms64+250;
   end;

//xmustalignpaint
if xmustalignpaint then alignpaintnow;
except;end;
end;

procedure tbasiccols._onalign(sender:tobject);
begin

//re-calculate all column widths/heights
xsyncareas(clientinner,false);

end;

procedure tbasiccols.xsyncareas(xclientarea:twinrect;xcalconly:boolean);//27aug2025
type
   tslotinfo=record
     slot:longint;
     size:longint;
     remcount:longint;
     end;
var
   ca:twinrect;
   p,vcount,cw,ch,xvsp,xhsp:longint;
   xfullarea:boolean;

   //.slot info (columns) - 03feb2025
   slist:array[0..high(icols)] of tslotinfo;

   function sok(x:longint):boolean;
   begin
   result:=(x>=0) and (x<=high(icols)) and zzok(icols[x],7206) and icols[x].visible and (isize[x]<>0);
   end;

   procedure sa(x:tbasiccontrol;da:twinrect);
   begin
   //check
   if zznil(x,2320) then exit;

   //range
   if (da.left<ca.left)     then da.left:=ca.left;
   if (da.right>ca.right)   then da.right:=ca.right;
   if (da.top<ca.top)       then da.top:=ca.top;
   if (da.bottom>ca.bottom) then da.bottom:=ca.bottom;

   //set
   if not xcalconly then x.xsetclientarea(da);//14jul2025
   end;

   procedure hcalc(xreverse,xvertical:boolean);
   var
      dpos,dsize,scount,rcount,xlast,xfreesize,xusedsize,i,p:longint;
   begin

   //init
   case (vcount>=2) of
   true:xusedsize:=pred(vcount)*low__aorb(xhsp,xvsp,xvertical);//take into account column spacing - 27aug2025
   else xusedsize :=0;
   end;//case
   
   scount    :=0;
   rcount    :=0;

   //find last slot
   if xreverse then xlast:=high(icols) else xlast:=0;

   for i:=0 to high(icols) do
   begin
   if xreverse then p:=high(icols)-i else p:=i;
   if sok(p)   then xlast:=p;
   end;

   //scan used slots
   for i:=0 to high(icols) do
   begin
   if xreverse then p:=high(icols)-i else p:=i;

   if sok(p) then
      begin
      slist[scount].slot:=p;

      if (remcount[p]>=1) then
         begin
         slist[scount].size:=0;
         slist[scount].remcount:=remcount[p];
         end
      else if (p=xlast) and (rcount<=0) and xfullarea then
         begin
         slist[scount].size:=low__aorb(cw+xhsp,ch+xvsp,xvertical);
         slist[scount].remcount:=0;
         end
      else
         begin
         if xvertical then slist[scount].size:=xfindsize(p,ch)+xvsp
         else              slist[scount].size:=xfindsize(p,cw)+xhsp;

         slist[scount].remcount:=0;
         end;

      //inc
      inc(xusedsize,slist[scount].size-low__aorb(xhsp,xvsp,xvertical));//09mar2025: fixed odd "vsp/hsp" at right margin for "rightotleft"
      inc(rcount,slist[scount].remcount);
      inc(scount);

      //check
      if (scount>high(icols)) then break;
      end;
   end;//p

   //fill slots marked "remcount>=1" with shared remaining space
   xfreesize:=frcmin32(low__aorb(cw,ch,xvertical)-xusedsize,0);
   if (rcount>=1) then
      begin

      for p:=0 to (scount-1) do if (slist[p].remcount>=1) then slist[p].size:=frcmin32(round(xfreesize*(slist[p].remcount/rcount)),0);

      end;

   //size columns
   if xvertical then dpos:=ca.top else dpos:=ca.left;

   for p:=0 to (scount-1) do
   begin

   dsize:=frcmin32(slist[p].size-low__aorb(xhsp,xvsp,xvertical),0);

   if xvertical then sa(icols[ slist[p].slot ],area__make(ca.left,dpos,ca.right,dpos+dsize))
   else              sa(icols[ slist[p].slot ],area__make(dpos,ca.top,dpos+dsize,ca.bottom));

   if xvertical then inc(dpos,dsize+xvsp)
   else              inc(dpos,dsize+xhsp);

   end;//p

   end;
begin

//init
xfullarea :=ofullarea;
xhsp      :=ihsp;
xvsp      :=ivsp;
vcount    :=0;

for p:=0 to high(icols) do if vis[p] then inc(vcount);//27aug2025

ca        :=xclientarea;//was: clientinner
cw        :=frcmin32(ca.right-ca.left+1,0);
ch        :=frcmin32(ca.bottom-ca.top+1,0);

//get
case istyle of
bcLefttoright  :hcalc(false,false);
bcRighttoleft  :hcalc(true,false);
bcToptobottom  :hcalc(false,true);
bcBottomtotop  :hcalc(true,true);
end;//case

end;


//## tbasiccells ###############################################################
constructor tbasiccells.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tbasiccells.create2(xparent:tobject;xstart:boolean);
begin
//self
if classnameis('tbasiccells') then track__inc(satCells,1);
inherited create2(xparent,false);
//vars
oalwaysallowmove:=false;
ilastzoom:=vizoom;
itimer100:=slowms64;
ilastpaintid:=0;
ipaintid:=0;
ithumbw:=48;
ithumbh:=48;
istartx:=0;
istopx:=0;
istarty:=0;
iref:='';
iref2:='';
idragref:='';
itoppad:=10;
ibotpad:=10;
iseppad:=10;
ifocus:=0;
icount:=0;
ilastscrollpos:=0;
ilastfocus:=0;
iprevscrollpos:=0;
iprevfocus:=0;
//.scroll
iscroll:=nscrollbar('Scroll thumbnails',true);
iscroll.overtical:=false;
iscroll.ofullhandling:=false;

//events
iscroll.onpos:=_onpos;
//start
if xstart then start;
end;

destructor tbasiccells.destroy;
begin
inherited destroy;
if classnameis('tbasiccells') then track__inc(satCells,-1);
end;

procedure tbasiccells._onpos(sender:tobject);
begin
if (sender=iscroll) then
   begin
   xfaster;
   xincpaint;
   end;
end;

function tbasiccells.getalignheight(xclientwidth:longint):longint;
begin
result:=(2*frcmin32(findbordersize,1))+(vizoom*itoppad)+(vizoom*ithumbH)+(vizoom*ibotpad)+iscroll.getalignheight(0);
end;

procedure tbasiccells._onalign(sender:tobject);
var
   ci:twinrect;
   sh:longint;
begin
ci:=clientinner;
sh:=iscroll.getalignheight(0);
iscroll.xsetclientarea(area__make(ci.left,ci.bottom-sh,ci.right,ci.bottom));
end;

function tbasiccells.findcell(mx:longint;var xindex:longint;xpastend:boolean):boolean;
var
   xarea,xarea2:twinrect;
begin
result:=findcell2(mx,xindex,xarea,xarea2,xpastend);
end;

function tbasiccells.findcell2(mx:longint;var xindex:longint;var xarea,xinnerarea:twinrect;xpastend:boolean):boolean;//09feb2022
var//xpastend=false=strictly xindex=0..(xcount-1), true=xindex=0..xcount (allow +1 past end of list)
   xspace,xcellwidth,si,sx,sy,p,xzoom,xseppad,xthumbW,xthumbH,xcount,xscrollpos:longint;
begin
//defaults
result:=false;

try
xindex:=0;
xarea:=nilarea;
xinnerarea:=xarea;
//init
xzoom:=vizoom;
xscrollpos:=scrollpos;
xcount:=count;
xseppad:=(xzoom*iseppad);
xthumbW:=(xzoom*thumbW);
xthumbH:=(xzoom*thumbH);
xcellwidth:=xthumbw+xseppad;
xspace:=(xcellwidth-xthumbw) div 2;
si:=xscrollpos div xcellwidth;
sx:=istartx+(si*xcellwidth)-xscrollpos;
sy:=istarty;
//find
for p:=si to low__aorb(xcount-1,xcount,xpastend) do
begin
if (mx>=sx) and (mx<(sx+xcellwidth)) then
   begin
   xindex:=p;
   //.xarea
   xarea.left:=sx;
   xarea.right:=sx+xcellwidth-1;
   xarea.top:=sy;
   xarea.bottom:=sy+xthumbH;
   //.xinnerarea
   xinnerarea.left:=sx+(xspace-1);
   xinnerarea.right:=sx+xcellwidth-1-(xspace-1);
   xinnerarea.top:=xarea.top-1;
   xinnerarea.bottom:=xarea.bottom+1;
   //.ok
   result:=true;
   break;
   end;
//.inc
inc(sx,xcellwidth);
end;//p
except;end;
end;

procedure tbasiccells._onpaint(sender:tobject);
var
   s:tclientinfo;
   za,ta,fa,da,ia,ca:twinrect;
   xdropindex,xdrag,xspace,xcellwidth,si,sx,sy,p,xseppad,xtoppad,xbotpad,xthumbW,xthumbH,xfocus,xcount,xscrollpos:longint;
   //cell support
   simage:tbasicimage;//pointer only
   scaption:string;
   stranscol,sbits,sw,sh:longint;
   shasai:boolean;
begin
try
//init
infovars(s);
ca:=s.ci;
ca.bottom:=iscroll.top-1;
xscrollpos:=scrollpos;
xfocus:=focus;
xdropindex:=idropindex;
xdrag:=low__aorb(xfocus,idropindex,xdropindex>=0);
xcount:=count;
xseppad:=(s.zoom*iseppad);
xthumbW:=(s.zoom*thumbW);
xthumbH:=(s.zoom*thumbH);
xtoppad:=(s.zoom*itoppad);
xbotpad:=(s.zoom*ibotpad);
xcellwidth:=xthumbw+xseppad;
ia.top:=ca.top+xtoppad;
ia.bottom:=ca.top+xtoppad+xthumbH;
da.top:=ia.top-1;
da.bottom:=ia.bottom+1;
xspace:=(xcellwidth-xthumbw) div 2;
fa:=da;
fa.top    :=da.top   -xspace;
fa.bottom :=da.bottom+xspace;
ta.top    :=da.top   -(2*xspace);
ta.bottom :=da.bottom+(2*xspace);
za.top    :=da.top   -(2*xspace);
za.bottom :=da.top;
si:=xscrollpos div xcellwidth;
istartx:=ca.left+xspace;
istopx:=ca.right;
sx:=ca.left+(si*xcellwidth)-xscrollpos+xspace;
sy:=ca.top+xtoppad;
istarty:=sy;

//cls
ffillArea(s.cs,s.back,false);

//get
for p:=si to (xcount-1) do
begin
ia.left:=sx+xspace;//image area
ia.right:=sx+xcellwidth-1-xspace;
da.left:=ia.left-1;//frame around outside edge of image
da.right:=ia.right+1;
fa.left:=da.left-xspace;//focus area
fa.right:=da.right+xspace;
//.drag highlight
if (xdrag<>xfocus) and (p=xdrag) then
   begin
   if (xdrag>xfocus) then
      begin
      ta.left:=sx+xcellwidth-1-xspace;
      ta.right:=ta.left+(2*xspace);
      end
   else
      begin
      ta.right:=sx+xspace;
      ta.left:=ta.right-(2*xspace);
      end;
   ffillArea(ta,s.hover,s.r);
   end;

//.focus highlight
if (p=xfocus) then fframeSimple( fa ,xspace ,s.hover ,255 ,false ,false );

//.focus dot
if (xdropindex=-1) and (p=xfocus) then
   begin
   za.right:=sx+xspace;
   za.left:=za.right-(2*xspace);
   ffillArea(za,int__dif24(s.hover,20),s.r);
   end;

//.draw cell image
simage      :=nil;
stranscol   :=clnone;
scaption    :='';

if assigned(fonimage) and fonimage(self,p,xfocus,xcount,simage,stranscol,scaption) then
   begin

   if misinfo82432(simage,sbits,sw,sh,shasai) then
      begin

      //was: ldc2(ca,da.left,da.top,da.right-da.left+1,da.bottom-da.top+1,miscellarea(simage,0),simage,255,low__aorb(0,1,stranscol<>clnone),stranscol,clnone,0,true);
      fdraw3( simage ,miscellarea(simage,0) ,da.left,da.top,da.right-da.left+1,da.bottom-da.top+1 ,clnone ,power_enabled ,s.f ,false,false,true );

      end
   else if (scaption<>'') then
      begin

      ftext(s.back,da,da.left,da.top+(((da.bottom-da.top)-s.fnH) div 2),s.font,'',scaption,s.Rfn ,true);

      end;
   end;

//.frame
foutlinearea(da,s.font,false);
//.inc
inc(sx,xcellwidth);
if (sx>ca.right) then break;
end;//p

//.terminator item
if (sx<=ca.right) then
   begin
   da.left:=sx+xspace;
   da.right:=sx+(xspace*4);
   fa.left:=da.left-xspace;//focus area
   fa.right:=da.right+xspace;

   //.focus highlight
   if (xcount=xfocus) then fframeSimple( fa ,xspace ,s.hover ,255 ,false ,false );

   //.focus dot
   if (xdropindex=-1) and (p=xfocus) then
      begin
      za.right:=sx+xspace;
      za.left:=za.right-(2*xspace);
      ffillArea(za,int__dif24(s.hover,20),s.r);
      end;

   //.frame
   foutlinearea(da,s.font,false);

   end;

//frame
xframeSimple( s );

except;end;
end;

function tbasiccells.getscrollpos:longint;
begin
result:=iscroll.pos;
end;

procedure tbasiccells.setscrollpos(x:longint);
begin
setparams(x,focus,count);
end;

function tbasiccells.scrollmax:longint;
begin
result:=iscroll.max;
end;

procedure tbasiccells.xsetfocus(x:longint);
begin
setparams(scrollpos,x,count);
end;

procedure tbasiccells.setcount(x:longint);
begin
setparams(scrollpos,focus,x);
end;

procedure tbasiccells.setthumbsize(w,h:longint);
begin
setparams2(scrollpos,focus,count,w,h);
end;

function tbasiccells.setparams(xscroll,xfocus,xcount:longint):boolean;
begin
result:=setparams2(xscroll,xfocus,xcount,ithumbW,ithumbH);
end;

function tbasiccells.setparams2(xscroll,xfocus,xcount,xthumbW,xthumbH:longint):boolean;
var
   xcellwidth,xseppad,xzoom,xscrollmax:longint;
begin
//defaults
result:=false;

try
xzoom:=vizoom;
//range
xcount:=frcrange32(xcount,0,max32);
xfocus:=frcrange32(xfocus,0,xcount);
xseppad:=xzoom*iseppad;
xthumbW:=frcrange32(xthumbW,20,200);
xthumbH:=frcrange32(xthumbH,20,200);
xcellwidth:=(xzoom*xthumbW)+xseppad;
xscrollmax:=xcount*xcellwidth;
xscroll:=frcrange32(xscroll,0,xscrollmax);
//get
if low__setstr(iref,intstr32(xzoom)+'|'+intstr32(xscroll)+'|'+intstr32(xscrollmax)+'|'+intstr32(xfocus)+'|'+intstr32(xcount)+'|'+intstr32(xthumbW)+'|'+intstr32(xthumbH)) then
   begin
//   if (ifocus<>xfocus) and (xscrollmax<>iscroll.max) and (xthumbW=ithumbW) then xscroll:=frcmin32((xfocus-1)*xcellwidth,0);

   ifocus:=xfocus;
   icount:=xcount;
   ithumbW:=xthumbW;
   ithumbH:=xthumbH;
   iscroll.setparams(xscroll,0,xscrollmax);
   case visible and low__setstr(iref2,intstr32(xzoom)+'|'+intstr32(xthumbW)+'|'+intstr32(xthumbH)) of
   true:gui.fullalignpaint;
   else xincpaint;
   end;
   end;
except;end;
end;

procedure tbasiccells.xincpaint;
begin
low__iroll(ipaintid,1);
end;

procedure tbasiccells.xprev;
begin
focus:=focus-1;
end;

procedure tbasiccells.xnext;
begin
focus:=focus+1;
end;

function tbasiccells.xcanmove:boolean;
begin
result:=assigned(fonmove) or oalwaysallowmove;//22jul2024
end;

function tbasiccells.xmove(s,d:longint):boolean;
begin
result:=false;

try
if (s<>d) and (s>=0) and (s<count) and (d>=0) and (d<count) and xcanmove then
   begin
   if assigned(fonmove) then
      begin
      result:=fonmove(self,s,d,focus,count);
      focus:=d;
      end
   else
      begin
      result:=true;
      focus:=d;
      end;
   xincpaint;
   end;
except;end;
end;

function tbasiccells._onnotify(sender:tobject):boolean;
var
   int1:longint;
   xmustpaint:boolean;
   xarea:twinrect;
begin
//defaults
result:=false;

try
xmustpaint:=false;

//wheel
if (gui.wheel<>0) and enabled then
   begin
   scrollpos:=scrollpos-(gui.wheel*(ithumbW div 2));
   result:=true;//own the wheel
   end;


//key
if (gui.key<>aknone) then
   begin
   case gui.key of
   akhome:begin
      if enabled then focus:=0;
      result:=true;
      end;
   akend:begin
      if enabled then focus:=frcmin32(count-1,0);
      result:=true;
      end;
   akleft,akup:begin
      if enabled then xprev;
      result:=true;
      end;
   akright,akdown:begin
      if enabled then xnext;
      result:=true;
      end;
   akprev:begin
      if enabled then xprev;
      result:=true;
      end;
   aknext:begin
      if enabled then xnext;
      result:=true;
      end;
   end;//case
   end;

//mouse down
if gui.mousedownstroke then
   begin
   idownxy:=mousedownxy;
   idropindex:=-1;//off
   idragarea:=nilarea;
   if findcell2(idownxy.x,int1,xarea,idragarea,true) then focus:=int1;
   //prev support
//   if (ilastscrollpos<>scrollpos) and (ilastfocus<>focus) then
   if (ilastfocus<(focus-2)) or (ilastfocus>(focus+2)) then
      begin
      iprevscrollpos:=ilastscrollpos;
      iprevfocus:=ilastfocus;
      ilastscrollpos:=scrollpos;
      ilastfocus:=focus;
      end;
   //paint
   xmustpaint:=true;
   end;

//mouse move
if gui.mousedown and gui.mousemoved and (not gui.mousedownstroke) then
   begin
   if gui.mousedragging and (focus>=0) and (focus<count) and xcanmove then
      begin
      if low__setstr(idragref,intstr32(mousemovexy.x)+'='+intstr32(mousemovexy.y)) then xmustpaint:=true;
      if findcell(mousemovexy.x,int1,false) and low__setint(idropindex,int1) then xmustpaint:=true;//0..xcount
      gui.dragdrop_start(idragarea.left+paintarea.left,idragarea.top+paintarea.top,idragarea.right-idragarea.left+1,idragarea.bottom-idragarea.top+1,'GotMe__FromCells');
      end;
   end;

//mouse up
if gui.mouseupstroke then
   begin
   if (idropindex>=0) then
      begin
      if xmove(focus,idropindex) then xmustpaint:=true;
      end;
   if low__setint(idropindex,-1) then xmustpaint:=true;
   end;

//external event override - 01mar2021
//if assigned(fonnotify) then fonnotify(sender);
{}
//paint
if xmustpaint then xincpaint;

except;end;
end;

procedure tbasiccells.xprevlocation;
var
   int1,int2:longint;
begin
int1:=scrollpos;
int2:=focus;
setparams(iprevscrollpos,iprevfocus,icount);
ilastscrollpos:=iprevscrollpos;
ilastfocus:=iprevfocus;
iprevscrollpos:=int1;
iprevfocus:=int2;
end;

procedure tbasiccells._ontimer(sender:tobject);
var
   xmustpaint:boolean;
begin
try
xmustpaint:=false;

//timer100
if (slowms64>=itimer100) then
   begin
   if low__setint(ilastzoom,vizoom) then setparams(scrollpos,focus,count);
   itimer100:=slowms64+100;
   end;

//delayed paint
if (ilastpaintid<>ipaintid) then
   begin
   ilastpaintid:=ipaintid;
   xmustpaint:=true;
   end;

//paint
if xmustpaint then paintnow;
except;end;
end;


//## tbasicscroll ##############################################################
constructor tbasicscroll.create(xparent:tobject);
begin
create2(xparent,true,true);
end;

constructor tbasicscroll.create2(xparent:tobject;xscroll,xstart:boolean);
begin

//self
if classnameis('tbasicscroll') then track__inc(satScroll,1);
inherited create2(xparent,false);

//vars
//.right support - 24jul2021
irightvisible2       :=true;
irightmax            :=false;
irightgap            :=0;
irightminwidth       :=-50;
irightmaxwidth       :=350;//uses viScale to adapt dynamically to scaling changes - 03apr2026
iright               :=nil;

//.continue
oclsarea             :=true;//29mar2026
ofullalignpaint      :=false;
otopspace            :=0;
iscroll              :=xscroll;
istatic              :=false;
ofirstpos            :=min32;//off
osmallchange         :=10;
olargechange         :=50;
imainhelp            :=nil;//optional
ihead                :=nil;//optional
ihelp                :=nil;//optional
itoolbar             :=nil;//optional
itoolbar2            :=nil;//optional
itoolbar3            :=nil;//optional
igrad                :=nil;//optional
igrad2               :=nil;//optional
igrad3               :=nil;//optional
igrad4               :=nil;//optional
ihigh                :=nil;//optional
ihigh2               :=nil;//optional
istatus              :=nil;//optional
istatus2             :=nil;//optional
icols                :=nil;//optional
imenu                :=nil;//optional
inormal              :=true;
ibordersize          :=1;//30;//10;//no border -> can't repaint the controls in the clientarea without overwriting the border!!! - reconfirmed on 01aug2020
itimer100            :=slowms64;
itimer250            :=slowms64;
iinforef             :='';
iposref              :='';
idownpos             :=0;
ipage                :='';

//controls
iv                   :=tbasicscrollbar.create(self);
iv.overtical         :=true;
iv.ofullhandling     :=false;//allow our "_onnotify()" to handle the sensitive parts of scrolling and navigation etc - 04apr2020
iv.osmallchange      :=10;

//defaults
clientheight         :=5;

//start
if xstart then start;

end;

destructor tbasicscroll.destroy;
begin
try

inherited destroy;

if classnameis('tbasicscroll') then track__inc(satScroll,-1);

except;end;
end;

procedure tbasicscroll.setnormal(x:boolean);//19jul2025
begin
inherited setnormal(x);
iv.setnormal(x);
end;

procedure tbasicscroll.noscroll;//14jul2025
begin
scroll:=false;
static:=true;
end;

procedure tbasicscroll.destroychildren;
var
   b:tbasiccontrol;
   i,i2,p:longint;
begin
try
//children
i:=-1;
i2:=-1;
if gui.xsafeown(ownlist) and (ownlist.count>=1) then
   begin
   for p:=(ownlist.count-1) downto 0 do if gui.xownget(ownlist,p,b) then
      begin
      if (b=iv) then i:=p
      else if (b=iright) and (iright<>nil) then i2:=p
      else gui.xowndel__fast(ownlist,p);
      end;//p
   end;
//finalise
if (i2>=0) and gui.xowndel__fast(ownlist,i2) then iright:=nil;
if (i>=0) and gui.xowndel__fast(ownlist,i) then iv:=nil;
except;end;
end;

function tbasicscroll.childcount:longint;//17mar2025
begin
if gui.xsafeown(ownlist) then result:=ownlist.count else result:=0;
end;

function tbasicscroll.findchild(xindex:longint;var xchild:tbasiccontrol):boolean;//17mar2025
var
   xcount:longint;
begin
xchild :=nil;
xcount :=childcount;
result :=(xcount>=1) and gui.xownget(ownlist,frcrange32(xindex,0,xcount-1),xchild) and (xchild<>nil);
end;

function tbasicscroll.scrolling:boolean;//13jan2026
begin
result:=scroll and (iv.max>=1);
end;

function tbasicscroll.findbordersize:longint;
var
   s:char;
begin
//was: s:=gui.state;
s:=gui.laststate;//less stressful state proc

if (winstyle=wmfullwin) then
   begin

   if      (s='f') and ((not viframemax) or (viframemaxScope<1)) then result:=0//04dec2025

   else if (s='+') and (not viframemax)                          then result:=0

   else                                                               result:=inherited findbordersize;

   end
else result:=inherited findbordersize;

end;

function tbasicscroll.makeautohigh:boolean;
begin
ominheight:=2;
owinresizeable:=false;
oautoheight:=true;
setbounds(clientarea.left,clientarea.top,clientarea.right-clientarea.left+1,getalignheight(clientarea.right-clientarea.left+1));
gui.xcenter(self);
result:=true;
end;

function tbasicscroll.makedlg(da:twinrect;xshowhead:boolean):tbasicscroll;//27feb2021
begin
result:=makedlg2(da,xshowhead,false,true,true);
end;

function tbasicscroll.makedlg2(da:twinrect;xshowhead,xstatic,xcancel,xok:boolean):tbasicscroll;
begin
result:=makedlg3(da,tepnone,'',xshowhead,xstatic,0,120);
end;

function tbasicscroll.makedlg3(da:twinrect;xtep:longint;xtitle:string;xshowhead,xstatic:boolean;xcanceltime,xoktime:longint):tbasicscroll;
begin
result:=self;
if (result=nil) then exit;
result.winstyle:=wmdialog;
result.oroundstyle:=corRound;
result.oborderstyle:=bsSystem100;
result.owinresizeable:=true;//25feb2021
result.mkescape:=true;
result.mkreturn:=true;
result.ocode:=0;//cancelled
result.ocode2:='';
result.otepcolor:=clnone;
result.otepcolor2:=clnone;
result.static:=xstatic;//17aug2020
if xshowhead then
   begin
   if (xtep<>tepnone) then result.xhead.tep:=xtep;
   if (xtitle<>'')    then result.xhead.caption:=xtitle;
   result.xgrad;
   end;
result.xhelp;//every normal window has help by default
result.xsetclientarea(da);
gui.focuscontrol:=result;
//.buttons
with result.xtoolbar2 do
begin
if (xcanceltime>=0) then cadd(ntranslate('Cancel'),tepClose20,0,scdlg,rthtranslate('Cancel'),xcanceltime);
if (xoktime>=0) then cadd(ntranslate('OK'),tepYes20,1,scdlg,rthtranslate('OK'),xoktime);
end;
end;

procedure tbasicscroll.setpage(x:string);
var
   a:tbasiccontrol;
   dcount,dindex,p:longint;
   str1:string;
   xmustalign,bol1:boolean;
begin
try
//filter
x:=strlow(x);
if (x='') then x:='user';
//check
if strmatch(x,ipage) then exit;
//get
ipage:=x;
dcount:=0;
dindex:=-1;
str1:=ipage;
xmustalign:=false;

if (ownlist.count>=1) then
   begin
   for p:=0 to (ownlist.count-1) do if gui.xownget(ownlist,p,a) and (a.opagename<>'') then
   begin
   bol1:=strmatch(str1,a.opagename);

   if bol1 and (dindex<0) then dindex:=dcount;

   if (bol1<>a.visible) then
      begin
      a.visible:=bol1;
      xmustalign:=true;
      end;

   inc(dcount);
   end;//p
   end;


ipageindex:=frcmin32(dindex,0);//09jan2025


//set -> must update parent incases of height changing -> requires BOTH align and paint triggers -> 02jun2021
if xmustalign then
   begin

   if ofullalignpaint then gui.fullalignpaint
   else
      begin
      parentalignnow;
      parentpaintnow;
      end;

   end;

except;end;
end;

procedure tbasicscroll.setpageindex(x:longint);
var
   a:tbasiccontrol;
   dcount,p:longint;
   dpage:string;
begin
//check
if (ownlist.count<=0) then exit;

//init
x:=frcmin32(x,0);
dpage:='';
dcount:=0;

//find
for p:=0 to (ownlist.count-1) do if gui.xownget(ownlist,p,a) and (a.opagename<>'') then
   begin
   //first -> incase no matches are found
   if (dcount=0) then dpage:=a.opagename;

   //attempt to match by index
   if (x=dcount) then
      begin
      dpage:=a.opagename;
      break;
      end;

   inc(dcount);
   end;//p

//set
page:=dpage;
end;

procedure tbasicscroll._ontimer(sender:tobject);
var
   int1,xdir:longint;
   xmustalign,xmustpaint:boolean;
begin
try

//defaults
xmustalign:=false;
xmustpaint:=false;

//.itimer250
if (slowms64>itimer250) then
   begin
   //control info
   if low__setstr(iinforef,bnc(inormal)+pcRefsep+intstr32(findbordersize)) then xmustpaint:=true;
   //reset
   itimer250:=slowms64+250;
   end;

//.itimer100
if (slowms64>itimer100) then
   begin
   //pos info
   if low__setstr(iposref,intstr32(pos)+#1+intstr32(iv.max)+#1+intstr32(clientwidth)+#1+intstr32(clientheight)+#1+intstr32(ownid)+#1+intstr32(parentcoreindex)) then
      begin
      xmustalign:=true;
      xmustpaint:=true;
      app__turbo;
      end;
   //reset
   itimer100:=slowms64+low__aorb(0,100,low__downidle>=1000);//12jan2025
   end;

//wound scroller - 28sep2022                            //round(clientheight*0.3)
if (iv<>nil) and xwound_mustpaint(iv.pos,xsmall,int1,xdir) then
   begin
   if (int1<>pos) then pos:=int1;
   xwound_autooff(pos,xdir,iv.min,iv.max);
   end;

//paint
if xmustalign then alignnow;
if xmustpaint then paintnow;
except;end;
end;

function tbasicscroll.clientinner2(x:tbasiccontrol):twinrect;
var
   a:twinrect;
   bs:longint;
begin
a:=iclientarea;
bs:=findbordersize;
case xbuiltinok(x) of
true:result:=area__make(a.left+bs,a.top+bs,a.right-bs,a.bottom-bs);
else result:=area__make(a.left+bs,iv.clientarea.top,iv.clientarea.left-1,iv.clientarea.bottom);
end;
end;

function tbasicscroll.headheight:longint;//25jan2021
begin
if zzok(iv,7207) and iv.visible then result:=frcmin32(iv.clientarea.top-iclientarea.top,0) else result:=0;
end;

function tbasicscroll.getalignheight(xclientwidth:longint):longint;
var
   int1:longint;
begin

if oautoheight then
   begin
   xcalcalign(false,xclientwidth,int1,result);
   result:=frcrange32(frcmin32(result,ominheight),0,gui.height);
   end
else result:=frcmin32(frcmin32(clientheight,ominheight),0);

//external - 06jul2021
if xfindheight(xclientwidth,int1) then result:=frcmin32(result,int1);

end;

procedure tbasicscroll._onpaint(sender:tobject);//29mar2026
begin

if oclsarea then inherited _onpaint(sender);

end;

{
procedure tbasicscroll._onpaint(sender:tobject);
var
   s:tclientinfo;
begin

if (winstyle=wmcontrol) then
   begin

   infovars(s);



   //have controls (e.g. iv.max>=1) and are scrolling -> no areas unused, safe to sketchFill - 05jan2026
   if iv.visible and (iv.max>=1) then
      begin

      lds0( s.ci ,140+random(100),false);

      end

   else lds0( s.ci ,s.back, childcount>=1 );


   //draw frame

   end

else inherited _onpaint(sender);

end;
{}//???????????????????????????????

procedure tbasicscroll._onalign(sender:tobject);
var
   int1,int2:longint;
begin
xcalcalign(true,0,int1,int2);
end;

procedure tbasicscroll.xcalcalign(xalignok:boolean;xclientwidth:longint;var xoutclientheight,xoutheight:longint);
label
   skipend;
var
   a:tbasiccontrol;
   xrootca,ca:twinrect;
   xzoom,tmpw,xrightgap,xrightY1,xrightY2,xrightw,xtop,cy1,cy2,int1,int2,int3,xright,law,lah,lhsp,lvsp,hsp,vsp,lav,av,ldy,lineh,sh,aw,ah,tw,th,p,dx,dy,dy2,bs,sw,fcw2,fcw,cw2,cw,ch,dh,xlast:longint;
   xrightmax,xrightok,xstatic,xscroll,xok:boolean;

   function hlimit(x:longint):longint;
   begin
   result:=frcrange32(x,0,frcmin32(dy2-dy+0,0));
   end;

   procedure xnextinit;
   begin
   th:=0;
   tw:=0;
   dx:=0;
   dy:=0;
   lineh:=0;
   av:=1;
   lav:=-1;
   a:=nil;
   vsp:=0;
   hsp:=0;
   lvsp:=0;
   lhsp:=0;
   law:=0;
   lah:=0;
   end;

   procedure xnext;
   begin
   //check
   if zznil(a,2321) then exit;

   //init
   av   :=low__aorb(0,1,a.oalignvert);
   if (av=1) then aw:=frcmin32(cw2,0) else aw:=frcmin32(frcmin32(a.getalignwidth(ch-(2*bs)),a.ominwidth),0);
   ah   :=a.getalignheight(cw2);
   hsp  :=frcmin32(a.oseph,0);
   vsp  :=frcmin32(a.osepv,0);//include optional vertical spacing

   //get
   case av of
   0:begin//horizontal alignment
      if (lav<>av) then
         begin
         if (lah>=1) then inc(dy,lah+lvsp);
         dx  :=0;
         law :=0;
         lhsp:=0;
         end;
      if ((ah+vsp)>lineh) then lineh:=ah+vsp;
      inc(dx,law+hsp);//immediate horizontal sep
      if ((dx+aw)>=cw2) and (dx>0) then
         begin
         inc(dy,lineh);
         lineh:=ah+vsp;
         dx  :=0;
         law :=aw;
         lhsp:=0;
         end
      else
         begin
         law :=aw;
         lhsp:=hsp;
         end;
       end;
   1:begin//vertical
      if (lav<>av) and (lineh>=1) then inc(dy,lineh+vsp)
      else                             inc(dy,lah+vsp);//imediate vertical space
      dx  :=0;
      law :=0;
      lhsp:=0;
      lvsp:=0;
      end;
   end;
   //set
   aw  :=frcmax32(aw,cw2);//limit width to "cw2" -> no wider than scrollbar
   lav :=av;
   lah :=ah;
//   lvsp:=vsp;
   end;

   procedure xnextfinish;
   begin
   case lav of
   0:if (lineh>=1) then inc(dy,lineh);
   1:if (lah>=1)   then inc(dy,lah+lvsp);
   end;//case

   lav:=-1;
   end;
begin
try
//init
a                   :=nil;
xzoom               :=vizoom;
xrightok            :=rightvisible;
xrightmax           :=irightmax;
xrightgap           :=irightgap*xzoom;
xrightw             :=0;
xoutclientheight    :=0;
xoutheight          :=0;
xstatic             :=istatic;
xscroll             :=iscroll;
bs                  :=findbordersize;
xrootca             :=clientarea;
ca                  :=xrootca;
ch                  :=low__aorb(maxheight,clientheight,xalignok);

if xrightok then
   begin

   int1:=frcmin32(largest32(clientwidth,xclientwidth)-(2*bs),0);
   int2:=irightminwidth;

   if (int2<0) then int2:=round((-int2/100)*int1) else int2:=trunc32(int2*viScale);//03apr2026

   int3:=irightmaxwidth;
   if (int3<0) then int3:=round((-int3/100)*int1) else int3:=trunc32(int3*viScale);//03apr2026

   inc(int2,xrightgap);
   inc(int3,xrightgap);

   xrightw:=int3;

   if ((int1-xrightw)<int2) then xrightw:=frcmin32(int1-int2,0);
   if (xrightw>int3) then xrightw:=int3;

   ca.right:=frcmin32(xrootca.right-xrightw,0);

   end;

if xscroll and (not xstatic) then sw:=iv.getalignwidth(0) else sw:=0;

cw        :=frcmin32(largest32(clientwidth,xclientwidth)-(2*bs)-xrightw,0);
cw2       :=frcmin32(cw-sw,0);
fcw       :=frcmin32(largest32(clientwidth,xclientwidth)-(2*bs),0);
fcw2      :=frcmin32(fcw-sw,0);
xtop      :=clientarea.top;

//static controls --------------------------------------------------------------
//init
dy        :=bs+otopspace;//17aug2020
dy2       :=ch-bs;
xrightY1  :=dy;
xrightY2  :=dy2-1;

//Note: System controls are aligned in priority order, e.g. the most important
//      controls get first access to limited screen space, then if there is any
//      leftover, other less important controls, and so on.

//.head - (top-down)
if zzok(ihead,7210) and ihead.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   dh:=hlimit(ihead.getalignheight(tmpw));
   if xalignok then ihead.setbounds(bs,dy,tmpw,dh);
   inc(dy,dh);
   end;

//.help - (top-down)
if zzok(ihelp,7211) and ihelp.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   dh:=hlimit(ihelp.getalignheight(tmpw));
   if xalignok then ihelp.setbounds(bs,dy,tmpw,dh);
   inc(dy,dh);
   end;

//.status2 - (bottom-up)
if zzok(istatus2,7212) and istatus2.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   dh:=hlimit(istatus2.getalignheight(tmpw));
   if xalignok then istatus2.setbounds(bs,dy2-dh,tmpw,dh);
   dec(dy2,dh);
   end;

//.toolbar3 - (bottom-up/used for bottom edge toolbar) - 05jun2025
if zzok(itoolbar3,7213) and itoolbar3.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   dh:=hlimit(itoolbar3.getalignheight(tmpw));
   if xalignok then itoolbar3.setbounds(bs,dy2-dh,tmpw,dh);
   dec(dy2,dh+itoolbar3.osepv);
   end;

//.grad2 - (botton-up for window) - 19aug2024
if zzok(igrad2,7214) and igrad2.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   dh:=hlimit(igrad2.getalignheight(tmpw));
   if xalignok then igrad2.setbounds(bs,dy2-dh,tmpw,dh);
   dec(dy2,dh);
   //was: igrad2.ohavestatus:=xhavestatus2;
   end;

//.toolbar2 - (bottom-up/used for buttons on a dlg window)
if zzok(itoolbar2,7213) and itoolbar2.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   dh:=hlimit(itoolbar2.getalignheight(tmpw));
   if xalignok then itoolbar2.setbounds(bs,dy2-dh,tmpw,dh);
   dec(dy2,dh+itoolbar2.osepv);
   end;

//.grad3 - (botton-up for window) - 05jun2025
if zzok(igrad3,7214) and igrad3.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   dh:=hlimit(igrad3.getalignheight(tmpw));
   if xalignok then igrad3.setbounds(bs,dy2-dh,tmpw,dh);
   dec(dy2,dh);
   end;

//.toolbar - (top-down/main toolbar for window)
if zzok(itoolbar,7214) and itoolbar.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   //Note: for "getalignheight" to work correctly it needs to know the width
   dh:=hlimit(itoolbar.getalignheight(tmpw));
   if xalignok then itoolbar.setbounds(bs,dy,tmpw,dh);
   inc(dy,dh);
   end;

//.status - (top-down)
if zzok(istatus,7215) and istatus.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   //Note: for "getalignheight" to work correctly it needs to know the width
   dh:=hlimit(istatus.getalignheight(tmpw));
   if xalignok then istatus.setbounds(bs,dy,tmpw,dh);
   inc(dy,dh);
   end;

//.grad - (top-down for window) - 19aug2024
if zzok(igrad,7214) and igrad.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   dh:=hlimit(igrad.getalignheight(tmpw));
   if xalignok then igrad.setbounds(bs,dy,tmpw,dh);
   inc(dy,dh);
   end;

//.high - (bottom-up/used for controls at the top of a window)
if zzok(ihigh,7216) and ihigh.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   //Special Note: This panel "high" must be able to have an optional
   //              mode that allows the system to automatically detect
   //              the required height of the panel based on the controls
   //              within it -> it would probably have to be static (no scrolling)
   //              date: 19aug2020 - *** todo ***
   dh:=hlimit(ihigh.getalignheight(tmpw));
   //note: top+bottom fixed - 07oct2020
   if xalignok then ihigh.setbounds(bs,dy,tmpw,dh);
   inc(dy,dh);
   end;

//.high2 - (bottom-up/used for controls at the bottom of a window)
if zzok(ihigh2,7217) and ihigh2.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   //Special Note: This panel "high2" must be able to have an optional
   //              mode that allows the system to automatically detect
   //              the required height of the panel based on the controls
   //              within it -> it would probably have to be static (no scrolling)
   //              date: 19aug2020 - *** todo ***
   dh:=hlimit(ihigh2.getalignheight(tmpw));
   //note: top+bottom fixed - 07oct2020
   //was: if xalignok and ihigh2.setbounds(bs,dy2-dh+1,cw,dh) then bol1:=true;//struc(x,y,w,h)
   if xalignok then ihigh2.setbounds(bs,dy2-dh,tmpw,dh);
   dec(dy2,dh);
   end;

//.grad4 - (botton-up for window) - 13jul2025
if zzok(igrad4,7214) and igrad4.visible then
   begin
   tmpw:=low__aorb(fcw,cw,xrightmax);
   dh:=hlimit(igrad4.getalignheight(tmpw));
   if xalignok then igrad4.setbounds(bs,dy2-dh,tmpw,dh);
   dec(dy2,dh);
   end;

//.icols - (bottom-up/used for controls at the bottom of a window)
if zzok(icols,7218) and icols.visible then
   begin
   if      icols.ofillheight    then dh:=hlimit(ch)//assumes full remaining height
   else if icols.canautoheight  then dh:=hlimit(icols.getalignheight(cw))//assumes full remaining height
   else                              dh:=hlimit(ch);//assumes full remaining height
{was:
   case icols.canautoheight of
   true:dh:=hlimit(icols.getalignheight(cw));//assumes full remaining height
   false:dh:=hlimit(ch);//assumes full remaining height
   end;
{}
   //note: top+bottom fixed - 07oct2020
   //was: if xalignok and icols.setbounds(bs,dy2-dh+1,cw,dh) then bol1:=true;//struc(x,y,w,h)
   if xalignok then icols.setbounds(bs,dy2-dh,cw,dh);
   dec(dy2,dh);
   end;

//.menu - (top-down)
if zzok(imenu,7218) and imenu.visible then
   begin
   //Note: for "getalignheight" to work correctly it needs to know the width
   dh:=hlimit(imenu.getalignheight(cw));
   if xalignok then imenu.setbounds(bs,dy,cw,dh);
   inc(dy,dh);
   end;

//.right - right hand side full height - 24jul2021
if zzok(iright,7219) and iright.visible then
   begin
   //special
   int2:=dy2;
   if zzok(icols,7218) and icols.visible and (icols.clientarea.top<=dy) then int2:=icols.clientarea.bottom;

   //set
   case xrightmax of
   true:begin//18dec2021
      end;
   else begin
      xrightY1:=dy;
      xrightY2:=int2-1;
      end;
   end;//case

   //.corner patching
   if xalignok then iright.setbounds(xrootca.right-xrightw-bs+1+xrightgap,xrightY1,xrightw-xrightgap,xrightY2-xrightY1+1);
   end;

//.client area - find last client control -> we can make this fit remaining area (override getalignheight)
xlast:=-1;//none
if (ownlist.count>=1) then
   begin
   for p:=(ownlist.count-1) downto 0 do if gui.xownget(ownlist,p,a) and (not xbuiltinOK(a)) and a.visible then
      begin
      xlast:=p;
      break;
      end;
   end;
{
//.client area - align controls
if (ownlist.count>=1) then
   begin
   for p:=0 to (ownlist.count-1) do if gui.xownget(ownlist,p,a) and (not xbuiltinOK(a)) and a.visible then
      begin
      int1:=frcmin32(dy2-dy+1,0);
      dh:=hlimit(largest32(a.getalignheight(cw2),frcmin32(a.ominheight,0)));
      if (p>=xlast) then dh:=hlimit(int1);
      if a.setbounds(bs,dy,cw2,dh) then bol1:=true;//struc(x,y,w,h)
      inc(dy,dh);
      end;//p
   end;
//.unused client area
ipainty:=dy;
ipainty2:=dy2;
//.align all children controls -> fire internal align event "_onalign()"
if (ownlist.count>=1) then
   begin
   for p:=0 to (ownlist.count-1) do if gui.xownget(ownlist,p,a) and (not xbuiltinOK(a)) and a.visible then
      begin
      xfindalign(a,low__aorb(-2,-1,bol1));//-1=align all regardless, -2=search for 1st align, then align from there up - 05apr2020
      end;//p
   end;
{}//xxxxxxxxxxxxxxxxxx


//align all children controls --------------------------------------------------

//init
int1 :=dy;//remember this value
sh   :=frcmin32(dy2-dy,0);
cy1  :=xtop+dy;//works now, used to be "top" but now uses "xtop=clientarea.top" - 01aug2020
cy2  :=xtop+dy2-1;

//get
//.calculate total height required
xnextinit;
if (ownlist.count>=1) then
   begin
   for p:=0 to (ownlist.count-1) do if gui.xownget(ownlist,p,a) and (not xbuiltinOK(a)) and a.visible then xnext;
   xnextfinish;
   end;
th:=dy;

//.autoheight support - 21feb2021
xoutclientheight :=frcmin32(int1+th+((ch-bs)-dy2),0);
xoutheight       :=xoutclientheight+bs;//only "1x bs" as one has already been counted - 08mar2021
if not xalignok then goto skipend;

//v -> supports "ofirstpos" - 14aug2020
case xstatic of
true:iv.setparams(0,0,0);
else iv.setparams(low__aorb(pos,ofirstpos,ofirstpos<>min32),0,frcmin32(th-sh,0));
end;

if (ofirstpos<>min32) then ofirstpos:=min32;//turn off

xok        :=(iv.max>=1);
iv.enabled :=xok;
iv.visible :=(sw>=1);
iv.xsetclientarea(area__make(ca.right-(sw-1)-bs,cy1,ca.right-bs,cy2));

//controls
xnextinit;
dy         :=cy1-iv.pos;//vertical shift pos
dx         :=0;
xright     :=ca.right-sw-bs;

if (ownlist.count>=1) then
   begin
   for p:=0 to (ownlist.count-1) do if gui.xownget(ownlist,p,a) and (not xbuiltinOK(a)) and a.visible then
      begin
      xnext;
      if (xstatic or (not xscroll)) and (xlast=p) and a.oautoheight then int1:=cy2 else int1:=dy+(ah-1);
      if xalignok then a.xsetclientarea(area__make(ca.left+bs+dx,dy,frcmax32(ca.left+bs+dx+(aw-1),xright),int1));
      end;//p
   end;
skipend:
except;end;
//event
try;if assigned(onalign) then onalign(self);except;end;
end;

function tbasicscroll.xbuiltinOK(x:tobject):boolean;
begin
if (x=nil) then result:=false
else result:=
 (x=ihead) or (x=ihelp) or (x=imenu) or
 (x=itoolbar) or (x=itoolbar2) or (x=itoolbar3) or
 (x=igrad) or (x=igrad2) or (x=igrad3) or (x=igrad4) or
 (x=ihigh) or (x=ihigh2) or (x=icols) or
 (x=istatus) or (x=istatus2) or
 (x=imainhelp) or
 (x=iv) or (x=iright);
end;

function tbasicscroll.xsmall:longint;
begin
result:=frcmin32( round((frcmin32(osmallchange,1)/100)*clientheight) ,1);
end;

function tbasicscroll.xlarge:longint;
begin
result:=frcmin32( round((frcmin32(olargechange,1)/100)*clientheight) ,1);
end;

function tbasicscroll._onnotify(sender:tobject):boolean;

   function xinsideclientinner:boolean;
   var
      a:tbasiccontrol;
      b:twinrect;
      sx,sy:longint;
   begin
   if xwindow(a) and (gui.winhover=a.coreindex) then//cursor is on our form
      begin
      sx:=gui.mousedownxy.x;
      sy:=gui.mousedownxy.y;
      b:=clientinner2(nil);
      result:=(sx>=b.left) and (sx<=b.right) and (sy>=b.top) and (sy<=b.bottom);
      end
   else result:=false;
   end;
begin
//defaults
result:=true;

try
//wheel
if (gui.wheel<>0) then
   begin
   if enabled then
      begin
      pos:=pos-(gui.wheel*xsmall);
      xwound_wheel(gui.wheel*70);
      end;
   end;

//key
if (gui.key<>aknone) then
   begin
   if enabled then
      begin
      case gui.key of
      akhome:pos:=0;
      akend:pos:=iv.max;
      akleft,akup:pos:=pos-xsmall;
      akright,akdown:pos:=pos+xsmall;
      akprev:pos:=pos-xlarge;
      aknext:pos:=pos+xlarge;
      end;//case
      end;
   end;

//mousedownstroke
if gui.mousedownstroke then
   begin
   idownpos:=pos;
   end;

//mouse move
if gui.mousedown and gui.mousemoved and (not gui.mousedownstroke) then
   begin
//was: if enabled and xinsideclientinner then pos:=round(idownpos-(gui.mousemovexy.y-gui.mousedownxy.y));
   if enabled then pos:=round(idownpos-(gui.mousemovexy.y-gui.mousedownxy.y));//allows cursor to be outside of the scrollbox while down and dragging and still work - 27feb2021
   end;

//mouse up - wound support - 04oct2022
if gui.mouseupstroke and gui.mousedragging and gui.mouseleft then xwound_mousevert(3000,true);

//external event override - 01feb2021
if assigned(fonnotify) then fonnotify(sender);
except;end;
end;

function tbasicscroll.getpos:longint;
begin
result:=iv.pos;
end;

procedure tbasicscroll.setpos(x:longint);
begin
iv.pos:=x;
end;

procedure tbasicscroll.setscroll(x:boolean);
begin
if low__setbol(iscroll,x) then alignnow;
end;

procedure tbasicscroll.setstatic(x:boolean);
begin
if low__setbol(istatic,x) then alignnow;
end;

procedure tbasicscroll.setrightmax(x:boolean);
begin
setrightparams(irightminwidth,irightmaxwidth,irightgap,x,rightvisible);
end;

procedure tbasicscroll.setrightgap(x:longint);
begin
setrightparams(irightminwidth,irightmaxwidth,x,irightmax,rightvisible);
end;

procedure tbasicscroll.setrightminwidth(x:longint);
begin
setrightparams(x,irightmaxwidth,irightgap,irightmax,rightvisible);
end;

procedure tbasicscroll.setrightmaxwidth(x:longint);
begin
setrightparams(irightminwidth,x,irightgap,irightmax,rightvisible);
end;

procedure tbasicscroll.setrightparams(xminwidth,xmaxwidth,xgap:longint;xrightmax,xvisible:boolean);
var
   xmustvisible:boolean;
begin
try
//range
xminwidth:=frcmin32(xminwidth,-100);//-1..-100=percentage, 1..N=pixels
xmaxwidth:=frcmin32(xmaxwidth,-100);
xgap:=frcrange32(xgap,0,30);
xmustvisible:=(xvisible<>rightvisible);
//get
if (irightminwidth<>xminwidth) or (irightmaxwidth<>xmaxwidth) or (irightgap<>xgap) or (irightmax<>xrightmax) or xmustvisible or (xvisible and (not irightvisible2)) then
   begin
   irightminwidth:=xminwidth;
   irightmaxwidth:=xmaxwidth;
   irightgap:=xgap;
   irightmax:=xrightmax;
   case xvisible of
   true:xright.visible:=irightvisible2;//auto-create
   else if xhaveright then xright.visible:=false;
   end;

   //was: alignpaintnow;
   gui.fullalignpaint;//17dec2024
   end;
except;end;
end;

function tbasicscroll.getrightvisible:boolean;
begin
result:=zzok(iright,100) and iright.visible;
end;

procedure tbasicscroll.setrightvisible(x:boolean);
begin
setrightparams(irightminwidth,irightmaxwidth,irightgap,irightmax,x);
end;

procedure tbasicscroll.setrightvisible2(x:boolean);//optionally HIDE the right column (used for help) EVEN when it's set to SHOW - 17dec2024
begin
if low__setbol(irightvisible2,x) then setrightparams(irightminwidth,irightmaxwidth,irightgap,irightmax,rightvisible);
end;

function tbasicscroll.xright:tbasicscroll;
begin
if zzok(iright,7218) then result:=iright
else
   begin
   iright:=tbasicscroll.create(self);
   result:=iright;
   if (result=nil) then exit;

   iright.static:=true;
   iright.bordersize:=0;
   end;
end;

function tbasicscroll.xmainhelp:tmainhelp;//14may2025, 05dec2024, 24jul2021
var
   xonce:boolean;
begin
if zzok(imainhelp,7227) then result:=imainhelp
else
   begin
   xonce:=not xhaveright;
   imainhelp:=tmainhelp.create(xright);
   result:=imainhelp;
   if (result=nil) then exit;

   imainhelp.oautoheight:=true;//50%, 390px, 2px
   if xonce then setrightparams(-50,strint32(app__info('help.maxwidth')),0,false,true);//14may2025: removed gap of 5px, 05dec2024
   end;
end;

function tbasicscroll.xhead:tbasictoolbar;
begin
if zzok(ihead,7218) then result:=ihead
else
   begin

   ihead:=tbasictoolbar.create(self);
   result:=ihead;
   if (result=nil) then exit;
   result.makewinhead(winstyle=wmfullwin);

   with result do
   begin
   caption      :=programname;
   bordersize   :=0;//02dec2023
   oroundMode   :=rmTopOnly;
   end;

   end;
end;

function tbasicscroll.xhelp:tbasichelp;//realtime help scroller
begin

if zzok(ihelp,7219) then result:=ihelp
else
   begin

   ihelp  :=tbasichelp.create(self);
   result :=ihelp;
   if (result=nil) then exit;

   end;
end;

function tbasicscroll.xtoolbar:tbasictoolbar;
begin
if zzok(itoolbar,7220) then result:=itoolbar
else
   begin
   itoolbar:=tbasictoolbar.create(self);
   result:=itoolbar;
   if (result<>nil) then
      begin
      if iswin then result.make__backgroundhead;
      end;
   end;
end;

function tbasicscroll.xnograd:boolean;//13jul2025
begin
result:=true;//pass-thru

if xhavegrad  then xgrad.visible:=false;
if xhavegrad2 then xgrad2.visible:=false;
if xhavegrad3 then xgrad3.visible:=false;

end;

function tbasicscroll.xgrad:tbasicgradient;
begin
if zzok(igrad,7220) then result:=igrad
else
   begin
   igrad:=tbasicgradient.create(self,'');
   result:=igrad;
   end;
end;

function tbasicscroll.xgrad2:tbasicgradient;
begin
if zzok(igrad2,7220) then result:=igrad2
else
   begin
   igrad2:=tbasicgradient.create(self,'');
   result:=igrad2;
   end;
end;

function tbasicscroll.xgrad3:tbasicgradient;
begin
if zzok(igrad3,7220) then result:=igrad3
else
   begin
   igrad3:=tbasicgradient.create(self,'');
   result:=igrad3;
   end;
end;

function tbasicscroll.xgrad4:tbasicgradient;
begin
if zzok(igrad4,7220) then result:=igrad4
else
   begin
   igrad4:=tbasicgradient.create(self,'');
   result:=igrad4;
   end;
end;

function tbasicscroll.xtoolbar2:tbasictoolbar;
begin
if zzok(itoolbar2,7221) then result:=itoolbar2
else
   begin
   itoolbar2:=tbasictoolbar.create(self);
   result:=itoolbar2;
   if (result=nil) then exit;

   if iswin then result.make__backgroundbase;

   with result do
   begin
   bordersize   :=0;
   oheadalign   :=false;
   halign       :=2;
   normal       :=true;
   //was: osepv:=1;//05jun2025, 11oct2020
   end;//with
   end;
end;

function tbasicscroll.xtoolbar3:tbasictoolbar;
begin
if zzok(itoolbar3,7220) then result:=itoolbar3
else
   begin
   itoolbar3:=tbasictoolbar.create(self);
   result:=itoolbar3;
   if (result<>nil) and iswin then result.make__backgroundhead;
   end;
end;

function tbasicscroll.xhigh:tbasicscroll;
begin
if zzok(ihigh,7222) then result:=ihigh
else
   begin
   ihigh:=tbasicscroll.create(self);
   result:=ihigh;
   if (result=nil) then exit;
   with result do
   begin
   bordersize:=0;
   normal:=true;
   oautoheight:=true;//21feb2021
   static:=true;
   scroll:=false;
   end;//with
   end;
end;

function tbasicscroll.xhigh2:tbasicscroll;
begin
if zzok(ihigh2,7223) then result:=ihigh2
else
   begin
   ihigh2:=tbasicscroll.create(self);
   result:=ihigh2;
   if (result=nil) then exit;
   with result do
   begin
   bordersize:=0;
   normal:=true;
   oautoheight:=true;//21feb2021
   static:=true;
   scroll:=false;
   end;//with
   end;
end;

function tbasicscroll.xpage(xpagename:string;xstatic:boolean):tbasicscroll;
begin
result:=xpage3(xpagename,'','','','',tepNone,0,xstatic);
end;

function tbasicscroll.xpage1(xpagename,xheadlink,xhelp:string;xtep:longint;xstatic:boolean):tbasicscroll;//12jan2025
begin
result:=xpage3(xpagename,xheadlink,'','',xhelp,xtep,0,xstatic);
end;

function tbasicscroll.xpage2(xpagename,xtoplink,xbotlink,xhelp:string;xtep:longint;xstatic:boolean):tbasicscroll;
begin
result:=xpage3(xpagename,'',xtoplink,xbotlink,xhelp,xtep,0,xstatic);
end;

function tbasicscroll.xpage3(xpagename,xheadlink,xtoplink,xbotlink,xhelp:string;xtep,xtopspace:longint;xstatic:boolean):tbasicscroll;//12jan2025
begin
result:=tbasicscroll.create(self);
if (result=nil) then exit;
result.opagename:=xpagename;
result.oautoheight:=true;
result.static:=xstatic;
result.otopspace:=frcmin32(xtopspace,0);
result.bordersize:=0;
//.headlink
if (xheadlink<>'') then xhead.add(xheadlink,xtep,0,scPage+xpagename,xhelp);
//.toplink
if (xtoplink<>'') then xtoolbar.add(xtoplink,xtep,0,scPage+xpagename,xhelp);
//.botlink
if (xbotlink<>'') then xtoolbar2.add(xbotlink,xtep,0,scPage+xpagename,xhelp);
end;

function tbasicscroll.xmenu:tbasicmenu;
begin
if zzok(imenu,7225) then result:=imenu
else
   begin
   imenu:=tbasicmenu.create(self);
   result:=imenu;
   end;
end;

function tbasicscroll.xstatus:tbasicstatus;
begin
if zzok(istatus,7226) then result:=istatus
else
   begin
   istatus:=tbasicstatus.create(self);
   result:=istatus;
   if (result<>nil) and iswin then result.make__backgroundhead;
   end;
end;

function tbasicscroll.xstatus2:tbasicstatus;
begin

if zzok(istatus2,7227) then result:=istatus2
else
   begin

   istatus2:=tbasicstatus.create(self);
   result:=istatus2;
   if (result<>nil) and iswin then result.make__backgroundbase;

   end;

end;

function tbasicscroll.xcols:tbasiccols;//standard
begin

if zzok(icols,7228) then result:=icols
else
   begin

   icols  :=tbasiccols.create(self);
   result :=icols;

   end;

end;

function tbasicscroll.xcolsh:tbasiccols;//autoheight version
begin

if zzok(icols,7229) then result:=icols
else
   begin

   icols  :=tbasiccols.create(self);
   result :=icols;

   end;

//apply each time -> allows for each new child to be checked
if (result<>nil) then result.makeautoheight;//applies to self and all currently created children - 26feb2021

end;

function tbasicscroll.xhaveright:boolean;
begin
result:=zzok(iright,7231);
end;

function tbasicscroll.xhavemainhelp:boolean;
begin
result:=zzok(imainhelp,7232);
end;

function tbasicscroll.xhavehead:boolean;
begin
result:=zzok(ihead,7231);
end;

function tbasicscroll.xhavehelp:boolean;
begin
result:=zzok(ihelp,7232);
end;

function tbasicscroll.xhavemenu:boolean;
begin
result:=zzok(imenu,7234);
end;

function tbasicscroll.xhavetoolbar:boolean;
begin
result:=zzok(itoolbar,7235);
end;

function tbasicscroll.xhavegrad:boolean;
begin
result:=zzok(igrad,7235);
end;

function tbasicscroll.xhavegrad2:boolean;
begin
result:=zzok(igrad2,7235);
end;

function tbasicscroll.xhavegrad3:boolean;
begin
result:=zzok(igrad3,7235);
end;

function tbasicscroll.xhavegrad4:boolean;
begin
result:=zzok(igrad4,7235);
end;

function tbasicscroll.xhavestatus2:boolean;
begin
result:=zzok(istatus2,7236);
end;

function tbasicscroll.xhavehigh:boolean;
begin
result:=zzok(ihigh,7237);
end;

function tbasicscroll.xhavehigh2:boolean;
begin
result:=zzok(ihigh2,7238);
end;

function tbasicscroll.xhavecols:boolean;
begin
result:=zzok(icols,7239);
end;

function tbasicscroll.xhavetoolbar2:boolean;
begin
result:=zzok(itoolbar2,7240);
end;

function tbasicscroll.xhavetoolbar3:boolean;
begin
result:=zzok(itoolbar3,7240);
end;

function tbasicscroll.xhavestatus:boolean;
begin
result:=zzok(istatus,7241);
end;

//## tbasicsetcolor ############################################################
constructor tbasicsetcolor.create(xparent:tobject;xuse32,xhead:boolean);
begin
create2(xparent,false,xuse32,xhead,true);
end;

constructor tbasicsetcolor.create2(xparent:tobject;xscroll,xuse32,xhead,xstart:boolean);
var
   d:tbasictoolbar;
begin
if classnameis('tbasicsetcolor') then track__inc(satSetcolor,1);
inherited create2(xparent,false,false);//force "xscroll=false" - fixed 02aug2021
//vars
ilocksync:=false;
icanfillundo:=true;
iuse32:=xuse32;
//controls
//.toolbar

if xhead then d:=self.xhead
else
   begin
   d:=xtoolbar;
   d.make__backgroundhead;//28jul2024
   end;

d.add('Revert',tepRefresh20,0,'revert','Revert to orginal color');
d.add('Menu',tepMenu20,0,'menu','Show color menu');
d.add('Static',tepColors20,0,'static','Show static colors');
d.add('History',tepColorHistory20,0,'history','Show color history');
d.add('Invert',tepInvert20,0,'invert','Invert color');
d.add('Undo',tepUndo20,0,'undo','Undo last color change');

//.color matrix
im:=ncolormatrix;
im.oautoheight:=true;

//.color mixer
with xhigh2 do
begin

icmbar:=ntitlebar(false,'Color Mixer','Color Mixer | Mix current color with original color in various shades');
with icmbar do
begin
halign:=2;//right
add('Update',tepRefresh20,0,'colormixer.sync','Color Mixer | Update from current color');
end;

icm:=ncolormixer;
end;

//.columns
with xhigh2.xcolsh.cols2[0,50,false] do
begin
mtitle('Color Levels','Click and drag to adjust the red, green and blue elements of the color');
ir:=mint2b('Red','','Color|Adjust red level 0-255',0,255,127,0,'');
ig:=mint2b('Green','','Color|Adjust green level 0-255',0,255,127,0,'');
ib:=mint2b('Blue','','Color|Adjust blue level 0-255',0,255,127,0,'');
ia:=mint2b('Alpha','','Alpha|Adjust alpha level 0-255',0,255,127,0,'');
end;

with xhigh2.xcolsh.cols2[1,50,false] do
begin
mtitle('Color / Shade','Current color and shade range');
ic:=ncolor1('Color','Current color',iuse32);
ic.opopcolor:=false;
ic.oautoheight:=true;
end;

//default color
icolor:=0;
irevertcolor:=0;
iundocolor:=0;
color:=rgba__int(127,127,127,255);//sync all controls - 17nov2023

//events
ir.onvalue2    :=__oncolor;
ig.onvalue2    :=__oncolor;
ib.onvalue2    :=__oncolor;
ia.onvalue2    :=__oncolor;
im.oncolor     :=__oncolor;
ic.oncolor     :=__oncolor;
d.onclick      :=__onclick;
icm.oncolor    :=__oncolor;

ir.onnotify    :=ext__onnotify;
ig.onnotify    :=ext__onnotify;
ib.onnotify    :=ext__onnotify;
ia.onnotify    :=ext__onnotify;
im.onnotify    :=ext__onnotify;
ic.onnotify    :=ext__onnotify;

icmbar.onclick :=__onclick;

//defaults
ia.visible:=iuse32;
clientheight:=32;
help:='Click on color matrix to acquire color | Hold down and drag to continuously acquire color | Alternatively drag outside matrix to acquire screen color';

//start
if xstart then start;//02aug2021
end;

destructor tbasicsetcolor.destroy;
begin
try
inherited destroy;
if classnameis('tbasicsetcolor') then track__inc(satSetcolor,-1);
except;end;
end;

function tbasicsetcolor.ext__onnotify(sender:tobject):boolean;
begin
result:=true;
if gui.mouseupstroke then icanfillundo:=true;
end;

procedure tbasicsetcolor.setparams(xcolor,xrevertcolor:longint;xpage:string);
begin
iundocolor:=xrevertcolor;
irevertcolor:=xrevertcolor;
color:=xcolor;
if (xpage<>'matrix') and (xpage<>'static') then xpage:='matrix';
page:=xpage;
icm.setparams(xrevertcolor,xcolor);//05sep2025
end;

procedure tbasicsetcolor.getparams(var xcolor,xrevertcolor:longint;var xpage:string);
begin
xcolor:=color;
xrevertcolor:=irevertcolor;
xpage:=page;
end;

procedure tbasicsetcolor.setcolor24(x:longint);
var
   s,d:tcolor32;
begin
s:=int__c32(icolor);
d:=int__c32(x);
color:=rgba__int(d.r,d.g,d.b,s.a);//retain s.a alpha value - 17nov2023
end;

function tbasicsetcolor.getcolor24:longint;
var
   d:tcolor32;
begin
d:=int__c32(icolor);
d.a:=255;
result:=rgba__int(d.r,d.g,d.b,d.a);
end;

procedure tbasicsetcolor.setcolor(x:longint);
var
   v,v2:tint4;
begin
try

//init
if icanfillundo then
   begin
   icanfillundo:=false;
   iundocolor:=icolor;
   end;

//get
if low__setint(icolor,x) then
   begin
   v.val:=x;

   try

   ilocksync:=true;

   if zzok(ir,7250) then ir.val:=v.r;
   if zzok(ig,7251) then ig.val:=v.g;
   if zzok(ib,7252) then ib.val:=v.b;
   if iuse32 and zzok(ia,7252) then ia.val:=v.a;//17nov2023
   if zzok(im,7253) then im.color:=v.val;
   if zzok(ic,7254) then ic.color:=v.val;

   //.color mixer
   if zzok(icm,7254) then
      begin
      v2.val  :=v.val;
      v2.a    :=0;
      if (icm.selectedcolor<>v2.val) then icm.tocolor:=v.val;
      end;

   except;end;

   ilocksync:=false;

   //event
   if assigned(foncolor) then foncolor(self,v.val);

   end;

except;end;
end;

procedure tbasicsetcolor.__onclick(sender:tobject);//01feb2025
var
   n:string;
   int1:longint;
begin
try
if (sender is tbasictoolbar) then
   begin
   n:=strlow((sender as tbasictoolbar).ocode2);
   if (n='menu') then
      begin
      ic.showmenu;
      icanfillundo:=true;
      end
   else if (n='static') then
      begin
      icanfillundo:=true;
      int1:=icolor;
      if gui.popcolorstatic(int1) then color24:=int1;
      icanfillundo:=true;
      end
   else if (n='history') then
      begin
      icanfillundo:=true;
      int1:=icolor;
      if gui.popcolorhistory(int1,iuse32) then
         begin
         if iuse32 then color:=int1 else color24:=int1;
         end;
      icanfillundo:=true;
      end
   else if (n='revert') then
      begin
      icanfillundo:=true;
      color:=revertcolor;
      icm.fromcolor:=color;
      icanfillundo:=true;
      end
   else if (n='invert') then
      begin
      icanfillundo:=true;
      color24:=int__invertb(color);
      icanfillundo:=true;
      end
   else if (n='undo') then
      begin
      icanfillundo:=true;
      color:=iundocolor;
      icanfillundo:=true;
      end
   else if (n='colormixer.sync') then
      begin
      icm.fromcolor:=color;
      end;
   end;
except;end;
end;

procedure tbasicsetcolor.__oncolor(sender:tobject;xval:longint);
var
   v:tint4;
   a:byte;
begin
try

//check
if ilocksync then exit;

//init
v.val:=icolor;
a:=v.a;

//get
if      (sender=ir) then v.r:=ir.val
else if (sender=ig) then v.g:=ig.val
else if (sender=ib) then v.b:=ib.val
else if (sender=ia) then
   begin
   if iuse32 then v.a:=ia.val;
   end
else if (sender=im) then
   begin
   v.val:=im.color;
   v.a:=a;
   end
else if (sender=ic) then
   begin
   v.val:=ic.color;
   if not iuse32 then v.a:=a;
   end
else if (sender=icm) and (icm.selectedcolor<>clnone) then
   begin
   v.val:=icm.selectedcolor;
   v.a:=a;
   end;

//set
color:=v.val;

except;end;
end;


//## tbasiccolormixer ##########################################################
constructor tbasiccolormixer.create2(xparent:tobject;xstart:boolean);
begin

//self
if classnameis('tbasiccolormixer') then track__inc(satOther,1);
inherited create2(xparent,false);

//init
low__cls(@icore,sizeof(icore));
iselectedcolor:=clnone;

//vars
ifromcolor   :=rgba0__int(30,255,255);
itocolor     :=rgba0__int(255,127,30);

//defaults
xmakecolors(ifromcolor,itocolor);

//start
if xstart then start;//02aug2021

end;

destructor tbasiccolormixer.destroy;
begin
try
inherited destroy;
if classnameis('tbasiccolormixer') then track__inc(satOther,-1);
except;end;
end;

function tbasiccolormixer.xrowheight:longint;
var
   int1:longint;
begin

gui__smallfont(info^,int1,result);
result:=2*result;

end;

function tbasiccolormixer.xrowcount:longint;
begin
result:=high(icore)+1;
end;

function tbasiccolormixer.getalignheight(xclientwidth:longint):longint;
begin
result:=xrowcount * xrowheight;
end;

procedure tbasiccolormixer.xmakecolors(scolor,dcolor:longint);
var
   xcolor,xgrey,xdark,xlight,ppert,pcount,p:longint;
begin

//check
if (high(icore)<3) then exit;

//init
pcount       :=1 + high(icore[0]);
xgrey        :=ggga0__int(127);
xdark        :=ggga0__int(0);//09sep2025
xlight       :=ggga0__int(255);

//mix the colors
for p:=0 to (pcount-1) do
begin

ppert        :=(p*100) div pcount;

//.color
xcolor             :=int__splice24_100(ppert,scolor,dcolor);
icore[0][p].color  :=xcolor;

//.light
icore[1][p].color  :=int__splice24_100(ppert,xlight,xcolor);

//.grey
icore[2][p].color  :=int__splice24_100(ppert,xgrey,xcolor);

//.dark
icore[3][p].color  :=int__splice24_100(ppert,xdark,xcolor);

end;//p

end;

procedure tbasiccolormixer._onpaint(sender:tobject);
var
   s:tclientinfo;
   fs,fsH,tw,dw,dh,dx,dy,rcount,icount,r,i:longint;
   da:twinrect;
   t:string;
begin
try

//init
infovars(s);
rcount    :=1+high(icore);
icount    :=1 + high(icore[0]);
dx        :=0;
dy        :=0;
dw        :=frcmin32(s.cw div icount,1);
dh        :=frcmin32(s.ch div rcount,1);
font__smallfont(info^,fs,fsH);//new resfont

//colors
for r:=0 to (rcount-1) do
begin

for i:=0 to (icount-1) do
begin

//.area
da.left           :=i*dw;
da.right          :=da.left+dw-1;
da.top            :=r*dh;
da.bottom         :=da.top+dh-1;
icore[r][i].area  :=da;

//.round up to far boundary
if (i>=(icount-1)) then da.right :=s.cs.right;
if (r>=(rcount-1)) then da.bottom:=s.cs.bottom;

//.draw
ffillArea(da,icore[r][i].color,false);

//.labels
t   :=intstr32(int__c8(icore[r][i].color));
tw  :=fast__textwidth('',t,fs);
ftext(s.back,da,da.left+((da.right-da.left+1-tw) div 2),da.top+((da.bottom-da.top+1-fsH) div 2),int__colorlabel( icore[r][i].color ),'',t,fs ,true);

end;//i

end;//r

//vertical dividers
for i:=1 to (icount-1) do ffillArea( area__make( i*dw ,s.cs.top ,i*dw ,s.cs.bottom) ,s.hover ,false );

//horizontal diviers
for r:=1 to (rcount-1) do ffillArea( area__make( s.cs.left ,r*dh ,s.cs.right ,r*dh ) ,s.hover ,false );

except;end;
end;

function tbasiccolormixer._onnotify(sender:tobject):boolean;//25jan2025
var
   a:tpoint;
   xcolor,r,i:longint;
begin
//handled
result:=true;

//find color
if gui.mouseupstroke then
   begin
   a:=mousemovexy;

   //find color from touch position
   if xinsideclientarea2(a.x,a.y) then
      begin

      //init
      xcolor:=clnone;

      //get
      for r:=0 to high(icore) do
      begin

      for i:=0 to high(icore[0]) do if area__within2(icore[r][i].area,a) then
         begin

         xcolor:=icore[r][i].color;
         break;

         end;

      if (xcolor<>clnone) then break;

      end;

      //set
      if (xcolor<>clnone) then
         begin

         iselectedcolor:=xcolor;
         if assigned(foncolor) then foncolor(self,iselectedcolor);

         end;

      end;

   end;

end;

procedure tbasiccolormixer.setfromcolor(x:longint);
begin
setparams(fromcolor,x);
end;

procedure tbasiccolormixer.settocolor(x:longint);
begin
setparams(x,tocolor);
end;

procedure tbasiccolormixer.setparams(xfromcolor,xtocolor:longint);
begin

if low__or2( low__setint(ifromcolor,xfromcolor), low__setint(itocolor,xtocolor) ) then
   begin

   xmakecolors(ifromcolor,itocolor);
   paintnow;

   end;

end;


//## tbasiccolormatrix #########################################################
constructor tbasiccolormatrix.create2(xparent:tobject;xstart:boolean);
begin
if classnameis('tbasiccolormatrix') then track__inc(satColmatrix,1);
inherited create2(xparent,false);
icolor:=int_127_127_127;
clientheight:=32;
help:='Click on color matrix to acquire color | Hold down and drag to continuously acquire color | Alternatively drag outside matrix to acquire screen color';
//start
if xstart then start;//02aug2021
end;

destructor tbasiccolormatrix.destroy;
begin
try
inherited destroy;
if classnameis('tbasiccolormatrix') then track__inc(satColmatrix,-1);
except;end;
end;

procedure tbasiccolormatrix._onpaint(sender:tobject);
var
   s:tclientinfo;
begin

//init
infovars(s);

//cls
fcolorMatrix(s.ci,s.r);

//frame
xframeSimple( s );

end;

function tbasiccolormatrix._onnotify(sender:tobject):boolean;//25jan2025
var
   a:tpoint;
begin
//handled
result:=true;

try
//event
if gui.mousedown and (gui.mousedownstroke or gui.mousemoved) then
   begin
   a:=mousemovexy;
   if xinsideclientarea2(a.x,a.y) then color:=c24__int(mis__colormatrixpixel24(a.x,a.y,clientwidth,clientheight))//02feb2025
   else                                color:=low__capcolor(0,0,true);
   end;

//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);
except;end;
end;

procedure tbasiccolormatrix.setcolor(x:longint);
begin
if low__setint(icolor,x) and assigned(foncolor) then foncolor(self,icolor);
end;


//## tbasicbwp #################################################################
constructor tbasicbwp.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tbasicbwp.create2(xparent:tobject;xstart:boolean);
begin

//self
if classnameis('tbasicbwp') then track__inc(satBWP,1);
inherited create2(xparent,false);

//vars
fonact               :=nil;//19jun2022
imustscrollv         :=-1;//off
imustscrollv_px      :=-1;//off
imustscrollh         :=-1;//off
imustpos             :=-1;//off
imustpos2            :=-1;//off
vsmooth              :=true;//scroll by pixels instead of by lines - 21jun2022
ocanshowmenu         :=true;
ibuildingcontrol     :=true;
irevertdata          :=nil;
omenustyles          :=false;
ocopystyles          :=false;//05feb2023
orows                :=false;
inormal              :=true;
ibordersize          :=0;//04dec2024
islowdownref         :=slowms64;
itimersync           :=slowms64;
itimersync_fastcount :=0;
iwordcount           :=0;
inewcount            :=0;
inewpos              :=0;
inewid               :=0;
inewword             :=false;

//.margin
imleft               :=2;
imright              :=2;
imtop                :=0;
imbottom             :=0;

//.h
ih                   :=nscrollbar('Click and drag to scroll',true);
ih.overtical         :=false;
ih.ofullhandling     :=false;

//.v
iv                   :=nscrollbar('Click and drag to scroll',true);
iv.overtical         :=true;
iv.ofullhandling     :=false;

//.core
icore                :=ttextcore.create(false);//15feb2026
iusepagecolor        :=false;
syncdef;

//events
iv.onpos             :=_onpos;
iv.onarrow           :=_onarrow;//redirect up/down scrolling to wordcore's "vwheel()" proc handler when "vsmooth=true" - 21jun2022
ih.onpos             :=_onpos;
icore.onvaluefromhost:=xvaluefromhost32;

//defaults
ibuildingcontrol     :=false;
clientheight         :=100;
xsync;
syscols              :=true;
undoenabled          :=true;//21jun2022



//start
if xstart then start;

end;

destructor tbasicbwp.destroy;
begin
try

ibuildingcontrol:=true;
if (sysbox=self) then sysbox:=nil;//disconnect

//control
freeobj(@icore);
str__free(@irevertdata);

//set
inherited destroy;
if classnameis('tbasicbwp') then track__inc(satBWP,-1);

except;end;
end;

function tbasicbwp.xvaluefromhost32(const n:string):longint32;//25mar2026
begin

if      (n='mfont') then result:=info.mfont
else if (n='mline') then result:=info.mline
else                     result:=0;

end;


procedure tbasicbwp.setstyle(x:longint);
var
   w,s:longint;
begin

//get
if (x=0) then
   begin
   w:=0;
   s:=1;
   end
else if (x=1) then
   begin
   w:=1;
   s:=1;
   end
else if (x=2) then
   begin
   w:=2;
   s:=1;
   end
else if (x=3) then
   begin
   w:=2;
   s:=2;
   end
else if (x=4) then
   begin
   w:=3;
   s:=2;
   end
else
   begin
   w:=0;
   s:=1;
   end;

//set
wrap:=w;
linespacing:=s;


end;

function tbasicbwp.getstyle:longint;
var
   w,s:longint;
begin

w:=frcrange32(wrap,0,3);
s:=frcrange32(linespacing,1,2);

if      (w=0) and (s=1) then result:=0
else if (w=1) and (s=1) then result:=1
else if (w=2) and (s=1) then result:=2
else if (w=2) and (s=2) then result:=3
else if (w=3) and (s=2) then result:=4
else                         result:=0;

end;

function tbasicbwp.canfind:boolean;
begin
result:=enabled;
end;

procedure tbasicbwp.findpop;
begin

if canfind then
   begin

   sysfind_handler :=icore.findhandler;
   sysfind_cmd     :='find.pop';

   end;

end;

procedure tbasicbwp.find;
begin

if canfind then
   begin

   sysfind_handler :=icore.findhandler;
   sysfind_cmd     :=low__aorbstr('find','find.pop',(sysfind_text=''));

   end;
   
end;

function tbasicbwp.pages:longint;
var
   xtotalheight,xpageheight:longint;
begin

xtotalheight    :=icore.totalheight;
xpageheight     :=frcmin32(icore.pageheight,1);
result          :=frcmin32(xtotalheight div xpageheight,1);

if ((result*xpageheight)<>xtotalheight) then inc(result);//round up to nearest page

end;

function tbasicbwp.page:longint;
var
   int1:longint;
begin

int1        :=pages;
result      :=frcrange32(1+trunc((line/(1+maxline))*int1),1,int1);

end;

function tbasicbwp.getcanspell:boolean;
begin

result:=icore.candic;

end;

procedure tbasicbwp.setcanspell(x:boolean);
begin

icore.candic:=x;
if x then dic__init;

end;

procedure tbasicbwp.spell;
begin

if canspell then icore.spell

end;

function tbasicbwp.getundoenabled:boolean;
begin
result:=icore.undoUse;
end;

procedure tbasicbwp.setundoenabled(x:boolean);
begin
icore.undoUse:=x and viMaster;
end;

procedure tbasicbwp.undoclear;
begin
icore.undoClear;
end;

procedure tbasicbwp.undoon;
begin
undoenabled:=true;
end;

procedure tbasicbwp.undooff;
begin
undoenabled:=false;
end;

function tbasicbwp.xcan(x:string):boolean;
begin

//defaults
result :=false;

//filters
if strmatch(x,'canpastereplace') then x:='canpaste';

//get
result:=icore.canact(x);

end;

function tbasicbwp.canundo:boolean;
begin
result:=icore.canundo;
end;

function tbasicbwp.canredo:boolean;
begin
result:=icore.canredo;
end;

function tbasicbwp.cancut:boolean;
begin
result:=icore.cancut;
end;

function tbasicbwp.cancopy:boolean;
begin
result:=icore.cancopy;
end;

function tbasicbwp.cancopyall:boolean;
begin
result:=icore.cancopyall;
end;

function tbasicbwp.canpaste:boolean;
begin
result:=icore.canpaste;
end;

function tbasicbwp.canpastereplace:boolean;
begin
result:=icore.canpastereplace;
end;

function tbasicbwp.candeleteall:boolean;//has undo
begin
result:=icore.candeleteall;
end;

function tbasicbwp.canclearall:boolean;
begin
result:=icore.canclearall;
end;

function tbasicbwp.xact(x:string;var e:string):boolean;
label
   skipend;
var
   xformat:string;
begin

//defaults
result      :=false;
e           :=gecTaskfailed;
x           :=strlow(x);

//init
case frcmax32(icore.formatLevel,icore.maxformatlevel) of//0=plaintext, 1=enhanced text, 2=advanced text (default) - 12jun2022
fmlTXT :xformat:='txt';
fmlBWD :xformat:='bwd';
fmlBWP :xformat:='bwp';
else    xformat:='txt';
end;//case

//get
if (x='undo') or (x='redo') or (x='copy') or (x='copyall') or (x='paste') or (x='pastereplace') or (x='deleteall') or (x='clearall') then
   begin

   icore.act(x);

   end
else goto skipend;

//events
if ((x='paste') or (x='pastereplace')) and assigned(fonact) then fonact(self,x);

//successful
result:=true;
skipend:

end;

procedure tbasicbwp._onarrow(sender:tobject;var xmoveval:longint);
begin

if (sender=iv) and vsmooth then
   begin

   icore.vwheel(-xmoveval);
   xmoveval:=0;

   end;

end;

procedure tbasicbwp.makeplaintext1;
begin
makexxx(0,1,false);
end;

procedure tbasicbwp.maketxt1;
begin
makexxx(0,1,false);
end;

procedure tbasicbwp.makebwd1;
begin
makexxx(1,1,false);
end;

procedure tbasicbwp.makebwp1;
begin
makexxx(2,1,false);
end;

procedure tbasicbwp.makeplaintext2;
begin
makexxx(0,2,false);
end;

procedure tbasicbwp.makepanel2;//27aug2025
begin
makexxx(0,2,true);
oautoheight        :=true;
icore.readonly     :=true;
icore.showcursor   :=false;
end;

procedure tbasicbwp.maketxt2;
begin
makexxx(0,2,false);
end;

procedure tbasicbwp.makebwd2;
begin
makexxx(1,2,false);
end;

procedure tbasicbwp.makebwp2;
begin
makexxx(2,2,false);
end;

procedure tbasicbwp.makebwpFull;
begin
makexxx(2,0,false);
end;

procedure tbasicbwp.makebwpFull2;//14nov2023
begin
makexxx(2,0,false);
icore.viewurl:=true;
icore.pageoverride2:=false;
end;

procedure tbasicbwp.makexxx(xformatlevel:longint;xuseonefont:longint;xviewurl:boolean);//31mar2025, 12jun2022
begin

//range
xformatlevel:=frcrange32(xformatlevel,0,2);//0=txt, 1=bwd, 2=bwp

//get
omenustyles:=(xformatlevel>=1);

icore.viewurl:=xviewurl;//31mar2025

case xuseonefont of
2:begin
   icore.onefontname:='$fontname2';//05feb2022
   icore.onefontsize:=1;//viFontsize2 - system size - 05feb2022
   end;
1:begin
   icore.onefontname:='$fontname';//05feb2022
   icore.onefontsize:=0;//viFontsize - system size - 05feb2022
   end;
else
   begin
   icore.onefontname:='';
   icore.onefontsize:=-1;
   end;
end;//case

icore.maxformatlevel:=xformatlevel;//plain text only - 12jun2022

end;

procedure tbasicbwp.setsyscols(x:boolean);
begin
icore.pageoverride2:=x;
end;

function tbasicbwp.getsyscols:boolean;
begin
result:=icore.pageoverride2;
end;

procedure tbasicbwp.vscrolltopos(xpos:longint);
begin

scrollto( -1 ,icore.pos__toline(xpos) ,-1 ,-1 ,-1 ,false );

end;

procedure tbasicbwp.scrollto(_vpos_px,_vpos,_hpos,_pos,_pos2:longint;xforcewrapall:boolean);
begin

if xforcewrapall then icore.wrapall;

if (_vpos_px>=0) then
   begin
   imustscrollv_px:=_vpos_px;
   imustscrollv:=-1;
   end
else
   begin
   imustscrollv_px:=-1;
   imustscrollv:=_vpos;
   end;

imustscrollh  :=_hpos;
imustpos      :=_pos;
imustpos2     :=_pos2;

end;

procedure tbasicbwp.revertinit(xdata:tstr8;xenable:boolean);
begin

try
str__lock(@xdata);

if xenable then
   begin

   if zznil(irevertdata,2324) then irevertdata:=str__new8;

   irevertdata.clear;
   irevertdata.add(xdata);

   end
else str__free(@irevertdata)

except;end;

//free
str__uaf(@xdata);

end;

procedure tbasicbwp.showmenuFill(xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);//24sep2022
var
   m:tstr8;//pointer only
   bol1,xselok,xcanpaste,xcanundo,xcanredo,xreadonly:boolean;
begin

//check
if zznil(xmenudata,2325) then exit else m:=xmenudata;
xmenuname             :='bwp2.1';

//init
xreadonly             :=oreadonly;
xselok                :=(icore.selcount>=1);
xcanpaste             :=icore.canpaste;
xcanundo              :=icore.canundo;
xcanredo              :=icore.canredo;

//get
low__menutitle(m,tepNone,'Edit','Edit options');
if (not xreadonly) and zzok(irevertdata,7257) then
   begin
   low__menuitem2(m,teprefresh20,'Revert...','Revert to original text','bwp.revert',100,aknone,not xreadonly);
   low__menusep(m);
   end;
if (not xreadonly) then
   begin
   if icore.undoUse then
      begin
      low__menuitem2(m,tepredo20,'Redo','Redo last change','bwp.redo',100,akctrlR,xcanredo);
      low__menuitem2(m,tepundo20,'Undo','Undo last change','bwp.undo',100,akctrlU,xcanundo);
      end;
   end;
if not xreadonly then
   begin
   low__menuitem2(m,tepcut20,'Cut','Cut text to Clipboard','bwp.cut',100,akctrlT,xselok and (not xreadonly));//26sep2022
//was:   low__menuitem2(m,tepclose20,'Delete All','Delete all text','bwp.deleteall',100,aknone,low__wordcore(icore,'candeleteall',nil));//28jun2022, 19jun2022
   end;
low__menuitem2(m,tepcopy20,'Copy','Copy text to Clipboard','bwp.copy',100,akctrlC,xselok);//26sep2022
low__menuitem2(m,tepcopy20,'Copy All','Copy all text to Clipboard','bwp.copyall',100,aknone,true);//26sep2022

if not xreadonly then
   begin
   low__menuitem2(m,teppaste20,'Paste','Paste text from Clipboard','bwp.paste',100,akctrlP,xcanpaste and (not xreadonly));
   low__menuitem2(m,teppaste20,'Replace All','Replace with text from Clipboard','bwp.pastereplace',100,aknone,xcanpaste and (not xreadonly));
   end;

low__menuitem2(m,tepselectall20,'Select All','Select all text','bwp.selectall',100,aknone,true);
if not xreadonly then low__menuitem2(m,tepclose20,'Delete All','Delete all text','bwp.deleteall',100,aknone,icore.candeleteall);//28jun2022, 19jun2022

//.menu styles
if (not xreadonly) and omenustyles then
   begin
   bol1:=true;

   if (icore.maxformatlevel>=fmlBWD) then
      begin

      low__menutitle(m,tepNone,'Style','Set style');
      low__menuitem2(m,tep__yes((not icore.cbold) and (not icore.citalic) and (not icore.cunderline) and (not icore.cstrikeout) and (icore.cbgcolor=clnone)),'Normal','Normal','bwp.normal',100,akctrlN,bol1);
      low__menuitem2(m,tep__yes(icore.cbold),'Bold','Bold','bwp.bold',100,akctrlB,bol1);
      low__menuitem2(m,tep__yes(icore.citalic),'Italic','Italic','bwp.italic',100,akctrlI,bol1);
      low__menuitem2(m,tep__yes(icore.cunderline),'Underline','Underline','bwp.underline',100,akctrlD,bol1);
      low__menuitem2(m,tep__yes(icore.cstrikeout),'Strikeout','Strikeout','bwp.strikeout',100,akctrlK,bol1);
      low__menuitem2(m,tep__yes(icore.cbgcolor<>clnone),'Highlight','Highlight','bwp.highlight',100,akctrlH,bol1);//19jun2022

      end;

   if (icore.maxformatlevel>=fmlBWP) then
      begin
      low__menutitle(m,tepNone,'Alignment','Set alignment');
      low__menuitem2(m,tep__tick(icore.calign=0),'Left','Align left','bwp.left',100,akctrlZ,true);
      low__menuitem2(m,tep__tick(icore.calign=1),'Center','Align center','bwp.center',100,akctrlZ,true);
      low__menuitem2(m,tep__tick(icore.calign=2),'Right','Align right','bwp.right',100,akctrlZ,true);
      end;

   end;

if (not xreadonly) then
   begin
   //if omenustyles then low__menutitle(m,tepNone,'Adjust','Adjustments') else low__menusep(m);
   low__menutitle(m,tepNone,'Adjust','Apply adjustment');
   low__menuitem2(m,tepUpper20,ntranslate('Upper Case'),'Make text upper case - ABCD','bwp.uppercase',100,aknone,xselok);//27mar2022
   low__menuitem2(m,tepLower20,ntranslate('Lower Case'),'Make text lower case - abcd','bwp.lowercase',100,aknone,xselok);
   end;

end;

function tbasicbwp.showmenuClick(sender:tobject;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
begin

//handled
result      :=true;

//information
if (xcode2='bwp.revert') then
   begin
   if zzok(irevertdata,7258) and gui.popquery2('Revert to original text and discard any changes?','','Revert',false) then iosetbwp(irevertdata);
   end

//.edit
else if (xcode2='bwp.undo')         then icore.undo
else if (xcode2='bwp.redo')         then icore.redo
else if (xcode2='bwp.cut')          then icore.cut
else if (xcode2='bwp.copy')         then icore.copy
else if (xcode2='bwp.copyall')      then icore.copyall
else if (xcode2='bwp.paste')        then icore.paste
else if (xcode2='bwp.pastereplace') then icore.pastereplace
else if (xcode2='bwp.selectall')    then icore.selectall
else if (xcode2='bwp.clearall')     then//no undo
   begin

   if zzok(irevertdata,7257) or undoenabled or gui.popquery('Clear all?') then icore.clearall;

   end
else if (xcode2='bwp.deleteall')     then//has undo
   begin

   if zzok(irevertdata,7257) or undoenabled or gui.popquery('Delete all?') then icore.deleteall;

   end

//.menu styles
else if (xcode2='bwp.normal')       then icore.cmakenormal(false)
else if (xcode2='bwp.bold')         then icore.cmakebold(false,not icore.cbold)
else if (xcode2='bwp.italic')       then icore.cmakeitalic(false,not icore.citalic)
else if (xcode2='bwp.underline')    then icore.cmakeunderline(false,not icore.cunderline)
else if (xcode2='bwp.strikeout')    then icore.cmakestrikeout(false,not icore.cstrikeout)
else if (xcode2='bwp.highlight')    then icore.cmakehighlight(false)
else if (xcode2='bwp.uppercase')    then icore.cmakeuppercase(false)
else if (xcode2='bwp.lowercase')    then icore.cmakelowercase(false)

//.menu align
else if (xcode2='bwp.left')         then icore.cmakeleft(false)
else if (xcode2='bwp.center')       then icore.cmakecenter(false)
else if (xcode2='bwp.right')        then icore.cmakeright(false)

//not handled
else result:=false;

end;

procedure tbasicbwp.margin(xl,xt,xr,xb:longint);
const
   xmax=500;
var
   bol1:boolean;
begin
try
bol1:=false;
if low__setint(imleft,frcrange32(xl,0,xmax)) then bol1:=true;
if low__setint(imtop,frcrange32(xt,0,xmax)) then bol1:=true;
if low__setint(imright,frcrange32(xr,0,xmax)) then bol1:=true;
if low__setint(imbottom,frcrange32(xb,0,xmax)) then bol1:=true;
if bol1 then
   begin
   alignnow;
   paintnow;
   end;
except;end;
end;

procedure tbasicbwp.setwrap(x:longint);//0=no wrap, 1=to window, 2=to page (default)
begin
icore.wrapstyle:=x;
end;

function tbasicbwp.getwrap:longint;
begin
result:=icore.wrapstyle;
end;

procedure tbasicbwp.setwrapreadonly(x:boolean);//true=prevents wrapstyle from changing during "ioset()" operations - 12mar2021
begin
icore.wrapreadonly:=x;
end;

function tbasicbwp.getwrapreadonly:boolean;
begin
result:=icore.wrapreadonly;
end;

procedure tbasicbwp.setlinespacing(x:longint);
begin
icore.linespacing:=x;
end;

function tbasicbwp.getlinespacing:longint;
begin
result:=icore.linespacing;
end;

function tbasicbwp.getroundstyle:longint;
begin

result:=oroundstyle;

end;

procedure tbasicbwp.setroundstyle(x:longint);
begin

oroundstyle     :=x;
iv.oroundstyle  :=x;
ih.oroundstyle  :=x;

end;

procedure tbasicbwp.syncdef;//06oct2020
begin

icore.syncdef(

vifontname,
vifontsize__root,//non-zoomed version
vinormal.font,
vinormal.background,
vinormal.highlight,
vinormal.fonthighlight,
int__dif24(vinormal.background,50)

);

end;

function tbasicbwp.getreadonly:boolean;
begin
result:=icore.readonly;
end;

procedure tbasicbwp.setreadonly(x:boolean);
begin
icore.readonly:=x;
end;

function tbasicbwp.makereadonly:tbasicbwp;//17mar2025
begin
result:=self;
icore.readonly:=true;
icore.undoUse:=false;
end;

function tbasicbwp.makeviewonly:tbasicbwp;
begin
result:=self;
result.core.onefontsize:=0;//system font
result.oautoheight:=true;
icore.readonly:=true;
icore.showcursor:=false;
end;

function tbasicbwp.ioset(xdata:tstr8):boolean;
begin
result:=ioset3(xdata,-1,-1,-1,-1,-1,false,false);
end;

function tbasicbwp.ioset2(xdata:tstr8;xvpos_px,xvpos:longint):boolean;
begin
result:=ioset3(xdata,xvpos_px,xvpos,-1,-1,-1,false,false);
end;

function tbasicbwp.ioset3(xdata:tstr8;xvpos_px,xvpos,xhpos,xpos,xpos2:longint;xtransform,xwebimages:boolean):boolean;
begin
result:=ioset4(xdata,'',xvpos_px,xvpos,xhpos,xpos,xpos2,xtransform,xwebimages);
end;

function tbasicbwp.ioset4(xdata:tstr8;const dformat:string;xvpos_px,xvpos,xhpos,xpos,xpos2:longint;xtransform,xwebimages:boolean):boolean;//17feb2026
begin

result:=true;

icore.clear2;//leaves UNDO alone - 27sep2022
icore.iosetdata2(xdata,dformat);

if xtransform then icore.transform(xwebimages,false,nil);//25mar2026, 16feb2026

icore.cursorpos       :=0;

case (xvpos_px>=0) of
true:icore.vpos_px   :=frcmin32(xvpos_px,0);
else icore.vpos       :=frcmin32(xvpos,0);
end;//case

icore.hpos:=frcmin32(xhpos,0);

if icore.undoUse then undoclear;//23jan2026, wipe undo - 27aug2024: but only if enabled, saves ~150ms, 26sep2022

xsync;//12mar2021

//.delayed scroll - 18dec2021
if (xvpos_px>=0) or (xvpos>=0) or (xhpos>=0) or (xpos>=0) or (xpos2>=0) then scrollto(xvpos_px,xvpos,xhpos,xpos,xpos2,true);
itimersync_fastcount:=20;//20 fast cycles

end;

function tbasicbwp.ioget(xdata:tstr8;xformat:string):boolean;
begin

result:=false;

try

if str__lock(@xdata) then
   begin

   result:=true;
   xdata.clear;
   icore.iogetdata(xdata, strdefb(xformat,'txt') );

//   if not result then xdata.clear;

   end;
except;end;

//free
str__uaf(@xdata);

end;

function tbasicbwp.iosettxt(xdata:tstr8):boolean;
begin
result:=ioset2(xdata,0,-1);
end;

function tbasicbwp.iosetbwd(xdata:tstr8):boolean;
begin
result:=ioset2(xdata,0,-1);
end;

function tbasicbwp.iosetbwp(xdata:tstr8):boolean;
begin
result:=ioset2(xdata,0,-1);
end;

function tbasicbwp.iosethtm(xdata:tstr8):boolean;
begin
result:=ioset2(xdata,0,-1);
end;

function tbasicbwp.iogettxt(xdata:tstr8):boolean;
begin
result:=ioget(xdata,'txt');
end;

function tbasicbwp.iogetbwd(xdata:tstr8):boolean;
begin
result:=ioget(xdata,'bwd');
end;

function tbasicbwp.iogetbwp(xdata:tstr8):boolean;
begin
result:=ioget(xdata,'bwp');
end;

function tbasicbwp.iogethtm(xdata:tstr8):boolean;
begin
result:=ioget(xdata,'htm');
end;

function tbasicbwp.line:longint;//current line 1..N
begin
result:=1+icore.pos__toline(cpos);
end;

function tbasicbwp.column:longint;
begin
result:=1+cpos-icore.line__topos(line-1);
end;

function tbasicbwp.line_column(var xline,xcolumn:longint):boolean;
var
   xcpos:longint;
begin

result      :=true;//pass-thru

//.cpos
xcpos       :=cpos;

//.line
xline       :=1+icore.pos__toline(xcpos);

//.column
xcolumn     :=1+xcpos-icore.line__topos(xline-1);

end;

function tbasicbwp.maxline:longint;
begin
result:=1+icore.pos__toline(max32);
end;

procedure tbasicbwp.setpos(x:longint);
begin
icore.vpos:=x;
end;

function tbasicbwp.getpos:longint;
begin
result:=icore.vpos;
end;

function tbasicbwp.getposh:longint;
begin
result:=icore.hpos;
end;

procedure tbasicbwp.setposh(x:longint);
begin
icore.hpos:=x;
end;

function tbasicbwp.getposc:longint;
begin
result:=icore.cursorpos;
end;

procedure tbasicbwp.setposc(x:longint);
begin
icore.cursorpos:=frcmin32(x,0);
end;

function tbasicbwp.getposc2:longint;
begin
result:=icore.cursorpos2;
end;

procedure tbasicbwp.setposc2(x:longint);
begin
icore.cursorpos2:=frcmin32(x,0);
end;

procedure tbasicbwp._onpos(sender:tobject);
begin

if (sender=iv) then
   begin

   case vsmooth of
   true:icore.vpos_px :=iv.pos;
   else icore.vpos    :=iv.pos;
   end;//case

   end

else if (sender=ih) then icore.hpos:=ih.pos;

//faster
xfaster;

end;

procedure tbasicbwp.setshowcursor(x:boolean);
begin
icore.showcursor:=x;
end;

function tbasicbwp.getshowcursor:boolean;
begin
result:=icore.showcursor;
end;

procedure tbasicbwp.setusepagecolor(x:boolean);
begin

if (x<>iusepagecolor) then
   begin

   iusepagecolor:=x;
   paintnow;

   end;

end;

function tbasicbwp._onshortcut(sender:tobject):boolean;//09dec2024: fixed ctrl+c block when readonly, 28aug2024: fixed F3/F4 block when oreadonly=true
begin

if enabled and focused and ( (gui.key=akF3) or (gui.key=akF4) or (gui.key=akCTRLC) or (not oreadonly) ) and (gui.key<>aknone) and icore.canshortcut(gui.key) then
   begin

   result:=true;//handled
   if (gui.key=akF3) or (gui.key=akF4) then sysfind_handler:=icore.findhandler;

   icore.keyboard2(gui.key);

   end

else result:=false;//not handled

end;

function tbasicbwp._onnotify(sender:tobject):boolean;
begin

//handled
result      :=true;//take control -> cancels system drag up/down and allows for screen color grab based dragging - 28jul2020

//wheel
if (gui.wheel<>0) then
   begin

   if enabled then
      begin

      case vsmooth of
      true:icore.vwheel(gui.wheel);//move Y row.pixels
      else vpos:=vpos-gui.wheel;
      end;//case

      end;

   xfaster;

   end;

//key
if (gui.key<>aknone) then
   begin

   if enabled and (gui.key<>aknone) and (gui.key<>akreturn) then icore.keyboard2(gui.key);

   xfaster;

   end;

//mouse
if gui.mousedownstroke then
   begin

   icore.mouse(mousex-imleft,mousey-imtop,true,gui.mouseright);

   xfaster;

   end
else if gui.mouseupstroke then
   begin

   icore.mouse(mousex-imleft,mousey-imtop,false,gui.mouseright);

   autoshowmenu;
   xfaster;

   end
else if gui.mousemoved then
   begin

   icore.mouse(mousex-imleft,mousey-imtop,gui.mousedown,gui.mouseright);

   if gui.mousedown then xfaster;

   end;

//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);

end;

procedure tbasicbwp._ontimer(sender:tobject);
begin
xwordcoretimer(false);
end;

procedure tbasicbwp.xwordcoretimer(xsyncnow:boolean);
var
   p:longint;
   bol1:boolean;
begin
try
//check
if ibuildingcontrol then exit;

//slow down checking when not visible to user -> check the "visibletohost" chain for this -> reduces number of calls made using "bnew" each second -  05jul2022
if not xsyncnow then
   begin

   if (islowdownref>slowms64) then exit else islowdownref:=slowms64+low__insint(500,not visibletohost);

   end;

//timer event - high speed
icore.hostsizing      :=gui.resizing;
icore.xtimer;

//v+h scrollbars
if ((slowms64>=itimersync) or (itimersync_fastcount>=1) or xsyncnow) then
   begin

   //check
   if (itimersync_fastcount>=1) then dec(itimersync_fastcount);

   //get
   if low__setstr(iref,bnc(orows)) then icore.mustpaint:=true;

   xsync;

   //reset
   itimersync:=slowms64+low__aorb(200,50,itimersync_fastcount>=1);//fastcount allows for a short but fast period of rapid repeat checking for important GUI changes, usually after a call to "ioset()" - 12mar2021

   end;

//paint event
if icore.canpaint and icore.mustpaint then
   begin

   icore.mustpaint:=false;
   paintnow;

   end;

//realtime word counter - 05feb2023
if olivewordcount and visible and ((inewpos>0) or low__setint(inewid,icore.dataid3)) then
   begin

   for p:=1 to 50000 do
   begin

   bol1:=icore.docsep(inewpos);

   if (bol1<>inewword) then
      begin

      inewword:=bol1;
      if not inewword then inc(inewcount);

      end;

   inc(inewpos);

   if (inewpos>=blen(icore.data)) then
      begin

      iwordcount      :=inewcount;
      inewpos         :=0;
      inewcount       :=0;
      inewword        :=false;
      break;

      end;

   end;//p

   end;

except;end;
end;

procedure tbasicbwp._onpaint(sender:tobject);
var
   s:tclientinfo;
   da:twinrect;
   pw,dleft,dright,lrpad,xrowcolor,int1,int2:longint;
begin
try

//check
if ibuildingcontrol or (not icore.paintlock(true)) then
   begin

   icore.mustpaint:=true;//retry later
   exit;

   end;

//init
xsync;
infovars(s);
lrpad                 :=s.zoom*10;

case orows of
true:xrowcolor        :=s.row;
else xrowcolor        :=clnone;
end;//case

dleft                 :=imleft+lrpad;
dright                :=imright+lrpad;
pw                    :=icore.pagewidth;

//inputbased colorising - 20apr2025
if oinputcolorise.use then s.back:=inputcolorise__backcolor(oinputcolorise,0.1,icore.data.len32-1,s.back);//-1 on len as there's always a trailing return code present

//cls
if ousepagecolor and (not icore.pageoverride2) and (icore.pagecolor<>clnone) then s.back:=icore.pagecolor;
ffillArea(s.cs,s.back,false);

//paint -> updated to handle wwsNone, wwsWindow and wwsPage - 12mar2021
case icore.wrapstyle of
wwsPage,wwsPage2:begin
   da.left:=iclientarea.left+s.bs+imleft;
   if (icore.pagewidth<icore.viewwidth) then inc(da.left,(icore.viewwidth-icore.pagewidth) div 2);//center the page when page is smaller than the viewing width
   end;
else da.left:=iclientarea.left+s.bs+imleft;
end;
da.right:=iv.clientarea.left-1-imright;//12mar2021
da.top:=iclientarea.top+s.bs+imtop;
if ih.visible then da.bottom:=ih.clientarea.top-1-imbottom else da.bottom:=iclientarea.bottom-s.bs-imbottom;


//render text
icore.render(da,ipaintarea,255,xrowcolor,s.back);

//draw page edges
if (icore.pagewidth<icore.viewwidth) and (icore.wrapstyle>=2) then
   begin

   int1:=int__dif24(s.back,-10);
   int2:=((s.cs.right-s.cs.left-iv.clientwidth)-pw) div 2;

   ffillArea(area__make(s.cs.left,s.cs.top,int2-dleft,s.cs.bottom),int1,false);
   ffillArea(area__make(s.cs.right-int2-iv.clientwidth+1,s.cs.top,s.cs.right-int2-iv.clientwidth+dright,s.cs.bottom),s.back,false);//patch vertical area with background - rows overwrite to far right of control - 04feb2023
   ffillArea(area__make(s.cs.right-int2-iv.clientwidth+dright,s.cs.top,iv.left-1,s.cs.bottom),int1,false);

   end;

//frame
if (s.bs>=1) then fframeSimple( s.cs ,s.bs ,int__dif24(s.border,oborderdiff),255 ,false ,s.r );

except;end;

//unlock paint
icore.paintlock(false);

end;

procedure tbasicbwp.xsync;
var//Note: Using "breuse()" proc greatly reduces the number of tstr8 objects needed to be created per second - 05jul2022
   int0,int1,int2,int3,int4:longint;
   xmousedown:boolean;
begin

//init
xmousedown  :=gui.mousedown;

//get
//.imustscrollto - delayed vertical scroll - 18dec2021
if ((imustscrollv_px>=0) or (imustscrollv>=0) or (imustscrollh>=0) or (imustpos>=0) or (imustpos2>=0)) and (not icore.wrapbusy) then
   begin

   int0:=imustscrollv_px; imustscrollv_px:=-1;
   int1:=imustscrollv;    imustscrollv:=-1;
   int2:=imustscrollh;    imustscrollh:=-1;
   int3:=imustpos;        imustpos:=-1;
   int4:=imustpos2;       imustpos2:=-1;

   //.cursorpos/2
   if (int3>=0) then icore.cursorpos:=int3;
   if (int4>=0) then icore.cursorpos2:=int4;

   //.force above cursor tasks to COMPLETE before issuing below h/vpos tasks - 07feb2023
   icore.xtimer;

   //.h/vpos
   if (int1>=0) then icore.vpos:=int1;
   if (int0>=0) then icore.vpos_px:=int0;//07feb2023
   if (int2>=0) then icore.hpos:=int2;

   end;

//.havefocus
//was: low__wordcore(icore,'havefocus',bn(focused or scrollbar1.focused or scrollbar2.focused));
icore.havefocus:=focused or iv.focused or ih.focused;

//.v
if icore.vhostsync then
   begin

   //int2:=low__wordcore2(icore,'vmax'+insstr('.px',vsmooth),nil);
   if icore.wrapdone then//or (int2>iv.max) then
      begin

      icore.vhostsync :=false;

      if vsmooth then
         begin
         int1         :=icore.vpos_px;
         int2         :=icore.vmax_px;
         end
      else
         begin
         int1         :=icore.vpos;
         int2         :=icore.vmax;
         end;

      iv.setparams2(int1,0,frcmin32(int2-low__insint(icore.viewheight-1,vsmooth),0),false);//prevent feedback loop to "_onpos => wordcore.set.vpos"

      end;

   end;

//.h
if (not xmousedown) and icore.hhostsync then
   begin

   icore.hhostsync    :=false;
   int1               :=icore.hpos;
   int2               :=icore.hmax;

   ih.setparams2(int1,0,int2,false);//prevent feedback loop to "_onpos => wordcore.set.hpos"

   end;

//.h.visible -> check rapidly -> hides control BEFORE screen is painting - 12mar2021
ih.visible:=icore.hshow;

//.line + column status
//   ilncount:=low__wordcore2(icore,'linecount','');
//   iln:=low__wordcore2(icore,'line','');
//   icol:=low__wordcore2(icore,'col','');

//wound scroller - 04oct2022
iv.oassistedscroll:=frcmin32(low__aorb(vifontsize,(clientheight div 5),vsmooth),1);//different scroll rates when vsmooth is ON or OFF

//.system colors
icore.pageselcolor        :=vinormal.highlight;
icore.pagefontselcolor    :=vinormal.fonthighlight;

//..override colors for pagecolor2 and pagefontcolor2 (overrides all font colors) when "pageoverride2=true"
//icore.pagecolorise2       :=false;//21jun2022
icore.pagecolor2          :=vinormal.background;
icore.pagefontcolor2      :=vinormal.font;//overrides internal font colors

end;

procedure tbasicbwp._onalign(sender:tobject);
var
   ci:twinrect;
   vwidth,hheight:longint;
begin

//get
//.v
vwidth                :=iv.getalignwidth(0);
ci                    :=clientinner;
iv.xsetclientarea(area__make(ci.right-vwidth-1,ci.top,ci.right,ci.bottom));

//.h -> size it always even when NOT visible -> paint system relies on it having valid coordinates at ALL times - 12mar2021
hheight               :=ih.getalignheight(0);
ih.xsetclientarea(area__make(ci.left,ci.bottom-(hheight-1),iv.clientarea.left-1,ci.bottom));

//.viewwidth
icore.viewwidth       :=frcmin32(ci.right-ci.left+1-vwidth-imleft-imright,0);

//.viewheight
icore.viewheight      :=frcmin32(ci.bottom-ci.top+1-hheight-imtop-imbottom,0);

//.update wordcore with current clientwidth immediately for BEST screen start - 29may2021
xwordcoretimer(true);

end;

//## tbasiccolor ###############################################################
constructor tbasiccolor.create(xparent:tobject;xcaption:string);
begin
create2(xparent,true,xcaption);
end;

constructor tbasiccolor.create2(xparent:tobject;xstart:boolean;xcaption:string);
begin
//self
if classnameis('tbasiccolor') then track__inc(satColor,1);
inherited create2(xparent,false);
//vars
foncolor:=nil;
ishadearea:=nilrect;
ishadeused:=false;
opopcolor:=true;
oshaderange:=true;//false;
osleek:=false;
inormal:=true;
iuse32:=false;
icolor:=int_255_255_255;
ibordersize:=1;
ishadelist:=tdynamicinteger.create;
//defaults
clientheight:=20;
//start
if xstart then start;
end;

destructor tbasiccolor.destroy;
begin
try
//controls
freeobj(@ishadelist);
//self
inherited destroy;
if classnameis('tbasiccolor') then track__inc(satColor,-1);
except;end;
end;

procedure tbasiccolor.setcolor24(x:longint);
var
   s,d:tcolor32;
begin
s:=int__c32(icolor);
d:=int__c32(x);
color:=rgba__int(d.r,d.g,d.b,s.a);//retain s.a alpha value - 17nov2023
end;

function tbasiccolor.getcolor24:longint;
begin
result:=inta__int(icolor,255);
end;

procedure tbasiccolor.setcolor(x:longint);
var
   bol1,bol2:boolean;
begin
try
bol1:=low__setint(icolor,x);
if ishadeused then bol2:=false else bol2:=low__setint(ishadecolor,x);
if bol1 or bol2 then
   begin
   if assigned(foncolor) then foncolor(self,icolor);//26feb2021
   paintnow;
   end;
except;end;
end;

function tbasiccolor.getalignheight(xclientwidth:longint):longint;
var
   int1:longint;
begin
//was: try;result:=frcmin32((2*findbordersize)+(2*vifontheight),0);except;end;
if osleek then int1:=1 else int1:=2;
result:=frcmin32(frcmin32(2+(int1*vifontheight)+(2*frcmin32(findbordersize,1)),ominheight),int1*20);//matches "tbasicint" height - 27feb2021
end;

function tbasiccolor.getalignwidth(xclientheight:longint):longint;
begin
result:=100;
end;

function tbasiccolor._onshortcut(sender:tobject):boolean;
var
   xcode2:string;
begin//store shortcut so we can transmitt it to our host form later (once we've closed the menu) - 02apr2020
//defaults
result:=false;

try
xcode2:='';
//get
case gui.key of
akctrlP:xcode2:='paste';
akctrlH:xcode2:='copyhex';
akctrlR:xcode2:='copyrgb';
akctrlN:xcode2:='copynum';
akctrlI:xcode2:='copypix';
akctrlV:xcode2:='invert';
end;//case
//set
if (xcode2<>'') then
   begin
   result:=true;
   xdomenu(xcode2);
   end;
except;end;
end;

function tbasiccolor._onnotify(sender:tobject):boolean;
var
   int1:longint;
begin
//handled
result:=true;//take control -> cancels system drag up/down and allows for screen color grab based dragging - 28jul2020

try
//mouse down
if gui.mousedownstroke then
   begin
   ishadeused:=oshaderange and area__within(ishadearea,mousex,mousey);
   end;

//mouse move
if gui.mousemoved and enabled and gui.mousedown and gui.mouseleft then
   begin
   //was: true:color24:=low__capcolor(0,0,true);

   case oshaderange and ishadeused of
   true:color24:=xshadecolor24;
   else if gui.mousedraggingout(self,true,true) then color24:=low__capcolor(0,0,true);
   end;//case
   end;

//mouse up
if gui.mouseupstroke and enabled and gui.mouseleft and (not gui.mousewasdraggingout) then
   begin
//was:   if oshaderange then color24:=low__capcolor2(0,0,true,self)
   if oshaderange then color24:=xshadecolor24
   else if opopcolor then
      begin
      int1:=icolor;
      if gui.popcolor2(int1,iuse32) then
         begin
         if iuse32 then color:=int1 else color24:=int1;
         end;
      end;
   end;

//showmenu
if gui.mouseupstroke and enabled and ( ((not opopcolor) and (not ishadeused) and gui.mouseleft) or gui.mouseright) and (not gui.mousewasdraggingout) then showmenu;

//update shadecolor
if gui.mouseupstroke and oshaderange then
   begin
   ishadeused:=false;
   if low__setint(ishadecolor,icolor) then paintnow;
   end;

//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);
except;end;
end;

procedure tbasiccolor.showmenu;
var
   m:tstr8;
   bol1:boolean;
   xcode,xtepcolor:longint;
   xcode2:string;
begin
try
//defaults
m:=nil;
//init
bol1:=clip__hasformat(cf_text);
m:=str__new8;
low__menuinit(m);
low__menuitem2(m,tepCopy20,translate('Copy as HEX'),'Copy color to Clipboard in hex format','copyhex',100,aknone,true);
low__menuitem2(m,tepCopy20,translate('Copy as RGB'),'Copy color to Clipboard in red green blue format','copyrgb',100,aknone,true);
low__menuitem2(m,tepCopy20,translate('Copy as Number'),'Copy color to Clipboard as whole number','copynum',100,aknone,true);
low__menusep(m);
//no support yet: low__menuitem2(m,tepCopy20,translate('Copy as Pixel'),'Copy color to Clipboard as a 1 pixel image','copypix',100,aknone,true);
low__menuitem2(m,tepPaste20,ntranslate('Paste'),'Paste color from Clipboard','paste',100,aknone,bol1);
low__menuitem2(m,tepInvert20,translate('Invert'),'Invert color','invert',100,aknone,true);
low__menuend(m);
//get
if gui.popmenu(pmNormal,iaNormal,m,xcode,xcode2,xtepcolor) then xdomenu(xcode2);
except;end;

//free
freeobj(@m);

end;

procedure tbasiccolor.xdomenu(xcode2:string);
var
   a:tint4;
   c:tdynamicstring;
   z:string;
begin
try
//defaults
c:=nil;
//get
if      (xcode2='paste') then
   begin
{//no support yet
   if clip__hasformat(cf_bitmap) then
      begin
      b:=ccs.newbmp(1,1);
      b.assign(clipboard);
      if ccs.valid24(b) then color:=ccs.pixels[b,0,0];
      end
{}
   if clip__hasformat(cf_text) then
      begin
      //get
      z:=clip__pastetextb;
      z:=low__firstline(z);
      //decide
      //.hex -> accepts #fff / fff / #fffa / fffa / #ffffff / ffffff - mixture of 24bit and 32bit hex colors with or without leading hash - 17nov2023
      if (strcopy1(z,1,1)='#') then color:=hex8__int(z,255,rgba__int(127,127,127,255))
      //.rgb
      else if (low__findchar(z,',')>=1) then
         begin
         //init
         c:=tdynamicstring.create;
         swapchars(z,',',#10);
         c.text:=z;
         if (c.count>=4) and iuse32 then
            begin
            a.r:=frcrange32(strint32(c.value[0]),0,255);
            a.g:=frcrange32(strint32(c.value[1]),0,255);
            a.b:=frcrange32(strint32(c.value[2]),0,255);
            a.a:=frcrange32(strint32(c.value[3]),0,255);
            color:=a.val;
            end
         else
            begin
            c.text:=z+rcode+'0'+rcode+'0'+rcode+'0'+rcode+'0';
            a.r:=frcrange32(strint32(c.value[0]),0,255);
            a.g:=frcrange32(strint32(c.value[1]),0,255);
            a.b:=frcrange32(strint32(c.value[2]),0,255);
            color24:=a.val;
            end;
         end
      //.number
      else
         begin
         case iuse32 of
         true:color:=strint32(z);
         else color24:=frcmin32(strint32(z),0);
         end;
         end;
      end;
   end
//was:
else if (xcode2='copyhex') then
   begin
   case iuse32 of
   true:clip__copytext(int__hex8(icolor,true));
   else clip__copytext(int__hex6(icolor,true));
   end;
   end
else if (xcode2='copyrgb') then
   begin
   a.val:=icolor;
   case iuse32 of
   true:clip__copytext(intstr32(a.r)+','+intstr32(a.g)+','+intstr32(a.b)+','+intstr32(a.a));
   else clip__copytext(intstr32(a.r)+','+intstr32(a.g)+','+intstr32(a.b));
   end;//case
   end
else if (xcode2='copynum') then clip__copytext(intstr32(icolor))
else if (xcode2='copypix') then
   begin
//Windows only:
{
   if (oscode=oswindows) then
      begin
      b:=low__newbmp24CLS(1,1,icolor);
      clip__copyimage(b);
      end;
{}//xxxxxxxxxxx

   end
else if (xcode2='invert') then color24:=int__invertb(color);
except;end;
//free
freeobj(@c);
end;

function tbasiccolor.xshadecolor24:longint;//03feb2024
var
   a:tpoint;
   w,i:longint;
begin
if validarea(ishadearea) and (ishadelist.count>=1) then
   begin
   //read color value directly from the shade list -> palette still functions even if global color grab "low__capcolor()" proc fails - 03feb2025
   a.x:=mousemovexy.x;
   a.y:=mousemovexy.y;
   if (a.x>=ishadearea.left) and (a.x<=ishadearea.right) and (a.y>=ishadearea.top) and (a.y<=ishadearea.bottom) then
      begin
      w:=frcmin32(ishadearea.right-ishadearea.left+1,1);
      i:=frcrange32( round(((a.x-ishadearea.left)/w)*ishadelist.count),0,ishadelist.count-1);
      result:=ishadelist.value[i];
      end
   else result:=low__capcolor(0,0,true);
   end
else result:=low__capcolor(0,0,true);
end;

procedure tbasiccolor._onpaint(sender:tobject);
const
   sp=2;
var
   s:tclientinfo;
   tw,tc,pcount,xcolor,xshadecolor,int1,dx:longint;
   a1,a2:twinrect;
   c32:tcolor32;

   procedure pdraw(sc,dc:longint);
   var
      c,ppert,p:longint;
   begin

   //range
   if (pcount<1) then pcount:=1;

   //get
   for p:=1 to pcount do
   begin

   ppert    :=frcrange32(round((p*100)/pcount),0,100);

   c        :=int__splice24_100(ppert,sc,dc);

   ffillarea( area__make( dx ,a2.top ,dx ,a2.bottom ) ,c ,false );

   ishadelist.value[dx-s.ci.left]:=c;

   inc(dx);
   if (dx>s.ci.right) then break;

   end;//p

   end;

begin
try

//init
infovars(s);
xcolor      :=icolor;
xshadecolor :=ishadecolor;

//apply alpha when use32=true - 17nov2023
if iuse32 then
   begin

   c32      :=int__c32(xcolor);
   xcolor   :=int__splice24((255-c32.a)/255,rgba0__int(c32.r,c32.g,c32.b),int_255_255_255);

   end;

//cls
if oshaderange then
   begin

   //init
   int1               :=((s.ci.bottom-s.ci.top+1) div 2);
   a1                 :=s.ci;
   a1.bottom          :=a1.top+int1;
   a2                 :=s.ci;
   a2.top             :=a1.bottom+1;
   a2.bottom          :=s.ci.bottom;

   pcount             :=frcmin32(s.ci.left+((s.ci.right-s.ci.left+1) div 4),1);
   ishadearea         :=area__make(s.ci.left+2,a2.top,s.ci.right-2,s.ci.bottom-1);

   ishadelist.clear;//cache shade colors for direct color grab - 03feb2025

   //actual color
   ffillArea(a1,xcolor,false);

   //shade ranges
   dx                 :=s.ci.left;

   pdraw(0,xshadecolor);
   pdraw(xshadecolor,int_255_255_255);
   pdraw(int_255_255_255,int__invertb(xshadecolor));
   pdraw(int__invertb(xshadecolor),0);

   end
else
   begin

   ffillArea(s.ci,xcolor,s.r);

   end;

//caption - 24oct2025
if (caption<>'') then
   begin

   tc       :=int__colorlabel(xcolor);
   tw       :=fast__textwidth('',caption,s.Rfn);
   ftext(s.back,s.cs,s.cs.left + ((s.cw-tw) div 2), s.cs.top + ((s.ch-s.fnH) div 2), tc, '',caption,s.Rfn ,true);

   end;

//frame
xframeSimple( s );

except;end;
end;


//## tbasichelp ################################################################
constructor tbasichelp.create2(xparent:tobject;xstart:boolean);
begin

//self
if classnameis('tbasichelp') then track__inc(satHelp,1);
inherited create2(xparent,false);

//vars
ishowhelp   :=true;//19mar2021, 19aug2020
iimg        :=tepHelphint;
inormal     :=false;
ipos        :=1;
itextref    :='';
itext       :='';
itextid     :=0;
ibordersize :=0;
itimer250   :=slowms64;
ipostime    :=slowms64;
ideftext    :=rthtranslate('Hover cursor over app for realtime help');

//defaults
text        :='';
clientheight:=20;

//sync
xsync;

//start
if xstart then start;

end;

destructor tbasichelp.destroy;
begin
try

inherited destroy;
if classnameis('tbasichelp') then track__inc(satHelp,-1);

except;end;
end;

procedure tbasichelp.setshowhelp(x:boolean);
begin

ishowhelp:=x;
xsync;

end;

procedure tbasichelp.xsync;
var
   bol1:boolean;
begin

bol1:=ishowhelp and vihelp;

if (visible<>bol1) then
   begin

   visible:=bol1;
   gui.fullalignpaint;

   end;

end;

procedure tbasichelp._ontimer(sender:tobject);
var
   xmustpaint:boolean;
begin
try

//defaults
xmustpaint:=false;

//.itimer250
if (slowms64>itimer250) then
   begin

   //control info
   if low__setstr(iinforef,bnc(inormal)+pcRefsep+intstr32(findbordersize)+pcRefsep+intstr32(vifontheight)+pcRefsep+intstr32(itextid)) then xmustpaint:=true;

   //.scroll
   if (itext<>'') and (slowms64>ipostime) then paintscroll;//time reset internally

   //.sync -> detects change in "vihelp" and "ohelp" - 19mar2021
   xsync;

   //reset
   itimer250:=slowms64+250;

   end;

//paint
if xmustpaint then paintnow;

except;end;
end;

function tbasichelp.paintscroll:boolean;
var
   i:longint;
begin

//defaults
result      :=false;

try

//check
if (itext='') or (not visibletohost) then exit;

//scan - never to end (as we should always have content)
i           :=ipos+3;//6 chars per second

if (i>=low__len32(itext)) then i:=1;

ipos        :=i;
ipostime    :=slowms64+low__aorb(350,2000,ipos=1);

//paint
paintnow;

//successful
result      :=true;

except;end;
end;

procedure tbasichelp.settext(x:string);//14may2025

   function xformat:string;
   var
      xfirst:boolean;
      xlen,p:longint;
      c:char;

      function f(xpos:longint):char;
      begin

      if (xpos>=1) and (xpos<=xlen) then result:=x[xpos-1+stroffset] else result:=#0;

      end;

      procedure a(x:char);
      begin

      result:=result+x;

      end;

   begin

   //defaults
   result   :='';
   xlen     :=low__len32(x);
   xfirst   :=true;

   //get
   for p:=1 to low__len32(x) do
   begin

   c        :=x[p-1+stroffset];

   if (c='|') and (xfirst or ((f(p-1)<>#32) and (f(p+1)<>#32))) then
      begin

      if xfirst then
         begin

         a(#32);
         a('-');
         a(#32);

         end

      else a(#32);

      xfirst:=false;

      end

   else a(c);

   end;//p

   end;
begin

//filter
if (x='') then x:=ideftext;

//get
if (x<>itextref) then
   begin

   //set
   itextref :=x;
   itext    :=xformat;

   low__iroll(itextid,1);//id

   //reset
   ipostime :=slowms64+2000;
   ipos     :=1;

   paintnow;

   end;

end;

function tbasichelp.getalignheight(xclientwidth:longint):longint;
begin

result:=frcmin32( (2*findbordersize) + largest32(vifontheight,tep__height(iimg)) ,0 );

end;

procedure tbasichelp._onpaint(sender:tobject);
var
   s:tclientinfo;
   dx:longint;
begin

//init
infovars(s);
dx          :=1;

//cls
ffillArea(s.cs,s.back,false);

//image
if (iimg<>tepnone) then
   begin

   ftep(iimg,dx,(s.ch-tep__height(iimg)) div 2,s.font,true);
   inc(dx,tep__width(iimg)+2);

   end;

//text
ftext(s.back,s.ci,dx,(s.ch-s.fsH) div 2,s.font,'',strcopy1(itext,ipos,low__len32(itext)),s.Rfs ,true);

end;


//## tbasicnav #################################################################
constructor tbasicnav.create2(xparent:tobject;xstart:boolean);
begin

//self
if classnameis('tbasicnav') then track__inc(satNav,1);
inherited create2(xparent,false);

//vars
ohead                 :=false;
ominsize              :=min64;
omaxsize              :=max64;
ifolderid             :=0;
onumber               :=false;
ipreview              :=false;//22may2022
icanpreview           :=false;
isyspreview           :=false;
ilastpreview          :=false;
ilastpreviewfile      :='';//22may2022
ocansort              :=true;//12jan2022
ofindname             :=false;
ifavlimit             :=100;//limit the number of items in favourities list to 100 -> faster "folderimg" loading - 14apr2021
bordersize            :=0;//21feb2021
ihisname              :='';//21mar2021
iprevnextcode         :=':';//used to signal to history that a PREV or NEXT is in action and not to store the value - 04apr2021
ifavfolder            :='';
isortstyle            :=nlName;
oretainpos            :=true;
itimer100             :=slowms64;//22may2022
itimer250             :=slowms64;
ivalueinlist          :='';
ifolderidREF          :='?';//triggers an initial update for "ifolderid" - 27sep2022
ilistfolder           :='';
imustfolder           :='';
imustname             :='';
imustreload           :=false;
omasklist             :='';//defaults to "*"
oemasklist            :='';//defaults to "nil" = off/disabled
ominmax_emasklist     :='';//off
findex                :=0;
fcount                :=0;
ilastmask             :=omasklist;
ilastemask            :=oemasklist;
ilastemask_minmax     :=ominmax_emasklist;

//controls
ifav                  :=nil;
ifavcore              :=nil;
ifavteps              :=nil;
ifavlabel             :=nil;
ipreviewlabel         :=nil;
ipreviewbox           :=nil;
iaction               :=nil;
ilist                 :=nil;
ilistcore             :=nil;
iname                 :=nil;
inamelabel            :=nil;
ifilter               :=nil;
ifilterlabel          :=nil;
ibar                  :=nil;
ibut                  :=nil;

//defaults
istyle                :=bnNil;
clientheight          :=200;

//start
if xstart then start;

end;

destructor tbasicnav.destroy;
begin
try

//controls
freeobj(@ifavcore);
freeobj(@ifavteps);//14apr2021
freeobj(@ilistcore);

//other
inherited destroy;
if classnameis('tbasicnav') then track__inc(satNav,-1);

except;end;
end;

function tbasicnav.getaction:string;
begin
if (iaction<>nil) and iaction.visible then result:=iaction.actionlist;
end;

function tbasicnav.xfocusname:boolean;//11feb2023
begin
result:=(iname<>nil) and iname.visible;
if result then gui.focuscontrol:=iname;
end;

function tbasicnav.getitemindex:longint;
begin
if (ilist<>nil)     then result:=ilist.itemindex
else if (ifav<>nil) then result:=ifav.itemindex
else                     result:=-1;
end;

procedure tbasicnav.setitemindex(x:longint);
begin
if (ilist<>nil) then ilist.itemindex:=frcrange32(x,0,frcmin32(ilist.count-1,0))
else if (ifav<>nil) then ifav.itemindex:=frcrange32(x,0,frcmin32(ifav.count-1,0));
end;

function tbasicnav.idletime:comp;//21feb2022
begin
result:=inherited idletime;
if (ilist<>nil)    then result:=smallest64(result,ilist.idletime);
if (ifav<>nil)     then result:=smallest64(result,ifav.idletime);
if (iname<>nil)    then result:=smallest64(result,iname.idletime);
if (ifilter<>nil)  then result:=smallest64(result,ifilter.idletime);
end;

function tbasicnav.xfrom(sender:tbasiccontrol;xvars:tvars8;xname:string):boolean;
begin
result:=zzok(xvars,7260);//handled
if result then
   begin
   sortstyle:=frcrange32(xvars.idef(xname+'.sort',nlName),0,nlMax);
   if isyspreview then preview:=xvars.bdef(xname+'.preview',false);
   end;
end;

function tbasicnav.xto(sender:tbasiccontrol;xvars:tvars8;xname:string):boolean;
begin
result:=zzok(xvars,7261);//handled
if result then
   begin
   xvars.i[xname+'.sort']:=frcrange32(sortstyle,0,nlMax);
   if isyspreview then xvars.b[xname+'.preview']:=preview;
   end;
end;

function tbasicnav.getsettings:string;
begin
result:='s'+intstr32(frcrange32(sortstyle,0,nlMax))+'|p'+bolstr(isyspreview and preview);
end;

procedure tbasicnav.setsettings(x:string);
var
   lp,p:longint;
   n,v:string;
begin
x:=strlow(x+'|');
lp:=1;

for p:=1 to low__len32(x) do
begin
if (x[p-1+stroffset]='|') then
   begin
   n:=x[lp-1+stroffset];
   v:=strcopy1(x,lp+1,p-lp-1);
   if (n='s') then
      begin
      if (v='') then v:=intstr32(nlName);
      sortstyle:=frcrange32(strint32(v),0,nlmax);
      end
   else if (n='p') then
      begin
      if isyspreview then preview:=strbol(v);
      end;
   end;
end;//p
end;

procedure tbasicnav.sethisname(x:string);
var
   bol1:boolean;
begin
bol1:=not strmatch(ihisname,x);
ihisname:=x;
if zzok(ilist,7262) then xhisadd(folder,ilist.pos,ilist.selstart,bol1);
end;

procedure tbasicnav.xshowmenuFill1(sender:tobject;xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
begin
if assigned(showmenuFill1) then showmenuFill1(sender,xstyle,xmenudata,ximagealign,xmenuname);
end;

procedure tbasicnav.xshowmenuFill2(sender:tobject;xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
begin
if assigned(showmenufill2) then showmenuFill2(sender,xstyle,xmenudata,ximagealign,xmenuname);
end;

procedure tbasicnav.xshowmenuFill(sender:tobject;xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
var
   xlistvalueStyle,astyle,xsortval:longint;
   xfileok,xfolderok,xanyfolderok,xcansort:boolean;
   xlistValue,xanyfile,xanyfolder:string;

   procedure xsort(xcap:string;xval:longint);
   begin
   low__menuitem2(xmenudata,tep__tick(xsortval=xval),xcap,'Sort by '+xcap,'nav.sort.'+intstr32(xval),100,aknone,xcansort);
   end;

begin
try

//check
if zznil(xmenudata,2326) then exit;
xmenuname   :=strdefb('nav.1',hisname);

//init
astyle      :=style;
xsortval    :=sortstyle;
xcansort    :=ocansort;


//sort
if (astyle=bnOpen) or (astyle=bnSave) or (astyle=bnNav) or (astyle=bnNavlist) or (astyle=bnNamelist) or (astyle=bnFolder) or (astyle=bnFolder2) then
   begin

   //init
   xvalueinlist(xlistValue,xlistvalueStyle);

   xfileok            :=(xlistvalueStyle=nltFile);//23mar2026 - value hightlighted in list and NOT the value in the filename box (when a save/open dlg)

   case xfileok of
   true:xanyfile:=xlistvalue;
   else xanyfile:='';
   end;//case

   xfolderok          :=(folder<>'');

   xanyfolder         :=selectedfolder;
   xanyfolderok       :=(xanyfolder<>'');


   //sort by
   low__menutitle(xmenudata,tepnone,'Sort By','Change sort order');
   xsort('Name (A-Z)',nlName);
   xsort('Name (Z-A)',nlNameD);
   xsort('Date (Old-New)',nlDate);
   xsort('Date (New-Old)',nlDateD);
   xsort('Size (Small-Large)',nlSize);
   xsort('Size (Large-Small)',nlSizeD);
   xsort('Type (.AAA-.ZZZ)',nlType);
   xsort('Type (.ZZZ-.AAA)',nlTypeD);
   xsort('As Is (A-Z)',nlAsis);
   xsort('As Is (Z-A)',nlAsisD);
   //folder options
   if (astyle<>bnNamelist) then
      begin
      low__menutitle(xmenudata,tepNone,'Folder Options','Folder options');
      low__menuitem2(xmenudata,tepNewfolder20,'New Folder...','Create a new folder','nav.newfolder',100,aknone,xfolderok);
      low__menuitem2(xmenudata,tepFolderimage20,'Change Folder Image...','Set a custom image for the folder','nav.folderimage',100,aknone,xanyfolderok);
      low__menuitem2(xmenudata,tepFolder20,'Show Folder','Show selected folder or folder of selected file','nav.showfolder',100,aknone,io__canshowfolder(xanyfolder));

      if io__canEditWithPaint(xanyfile)   then low__menuitem2(xmenudata,tepPaint20,'Edit with Paint','Edit selected file in Windows Paint','nav.editwithpaint.'+xanyFile,100,aknone,true);//23mar2026, 18sep2025
      if io__canEditWithNotepad(xanyfile) then low__menuitem2(xmenudata,tepNotepad20,'Edit with Notepad','Edit selected file in Windows Notepad','nav.editwithnotepad.'+xanyFile,100,aknone,true);//23mar2026, 18sep2025
      if io__canprint(xanyfile) then low__menuitem2(xmenudata,tepPrint20,'Print...','Print selected file using Windows','nav.print.'+xanyFile,100,aknone,true);//23mar2026, 18sep2025

      low__menuitem2(xmenudata,tepCopy20,'Copy Filename','Copy selected filename to Clipboard','nav.copy',100,aknone,xfileok);
      low__menuitem2(xmenudata,tepCopy20,'Copy All Filenames','Copy all filenames to Clipboard','nav.copyall',100,aknone,xfileok);

      //select options
      if (ilist<>nil) and (ilist.ostyle=lsmany) then
         begin
         low__menutitle(xmenudata,tepSelectAll20,'Selection Options','Selection options');
         low__menuitem2(xmenudata,tepSelectAll20,'To Start','To Start','nav.selectstart',100,aknone,ilist.selcount>=2);
         low__menuitem2(xmenudata,tepSelectAll20,'To End','To End','nav.selectend',100,aknone,ilist.selcount>=2);
         low__menuitem2(xmenudata,tepSelectAll20,'Select Range','Select range','nav.selectrange',100,aknone,ilist.canselectrange);
         low__menuitem2(xmenudata,tepSelectAll20,'Select All','Select All','nav.selectall',100,aknone,ilist.count>=2);
         end;

      end;

   end;

except;end;
end;

function tbasicnav.xshowmenuClick1(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
begin
if assigned(showmenuclick1) then result:=showmenuclick1(sender,xstyle,xcode,xcode2,xtepcolor) else result:=false;
end;

function tbasicnav.xshowmenuClick2(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
begin
if assigned(showmenuclick2) then result:=showmenuclick2(sender,xstyle,xcode,xcode2,xtepcolor) else result:=false;
end;

function tbasicnav.xshowmenuClick(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
begin
result:=xcmd(xcode,xcode2,clnone);
end;

function tbasicnav._xoff_toolbaradd(x:tbasictoolbar):boolean;
var
   xstyle:longint;

   procedure xadd(n:string);
   begin
   n:=strlow(n);
   if (n='prev')                        then x.add('Prev',tepPrev20,0,'nav.prev','Previous folder')
   else if (n='next')                   then x.add('Next',tepNext20,0,'nav.next','Next folder')
   else if (n='home')                   then x.add('Home',tepHome20,0,'nav.home','Home folder')
   else if (n='up')                     then x.add('Up',tepUpOne20,0,'nav.up','Up one folder')
   else if (n='fav.add') or (n='add')   then x.add('Add',tepFavadd20,0,'nav.favadd','Favourites|Add current folder to list')
   else if (n='fav.edit') or (n='edit') then x.add('Edit',tepFavedit20,0,'nav.favedit','Favourites|Edit list')
   else if (n='fav')                    then x.add('Fav',tepFav20,0,'nav.fav','Show favourites list')
   else if (n='newfolder')              then x.add('New Folder',tepNewfolder20,0,'nav.newfolder','Create a new folder')
   else if (n='explore')                then x.add('Explore',tepFolder20,0,'nav.explore','Explore current folder')
   else if (n='menu')                   then x.add('Menu',tepMenu20,0,'nav.showmenu','Show menu')
   else if (n='refresh')                then x.add('Refresh',tepRefresh20,0,'nav.refresh','Refresh list')
   else if (n='selectall')              then x.add('Select All',tepSelectall20,0,'nav.selectall','Select All')//28sep2022
   else if (n='preview')                then x.add('Preview',tepScreen20,0,'nav.preview','Toggle preview display')
   else if (n='sep')                    then x.add('-',tepNone,0,'','');
   end;

   procedure fadd(n:string);//favourites toolbar
   begin
   n:=strlow(n);
   if (ifavlabel<>nil) then
      begin
      if      (n='fav.add') or (n='add')   then ifavlabel.add('Add',tepFavadd20,0,'nav.favadd','Favourites|Add current folder to list')
      else if (n='fav.edit') or (n='edit') then ifavlabel.add('Edit',tepFavedit20,0,'nav.favedit','Favourites|Edit list');
      end
   else xadd(n);
   end;
begin
//defaluts
result:=false;

try
xstyle:=istyle;
//get
if (xstyle=bnNav) or (xstyle=bnNavlist) or (xstyle=bnNamelist) then//Special Note: bnNavlist/bnNamelist=does not show internal toolbar, rather the links are for a host's toolbar should it "xoff load" this control's toolbar duty - 08mar2021
   begin
   xadd('prev');
   xadd('next');
   xadd('fav');
   xadd('menu');
   xadd('refresh');
   end
else if (xstyle=bnOpen) or (xstyle=bnSave) or (xstyle=bnFolder) or (xstyle=bnFolder2) then
   begin
   if (xstyle=bnOpen) or (xstyle=bnSave) or (xstyle=bnFolder2) then xadd('preview');//22may2022
   fadd('fav.add');
   fadd('fav.edit');
   xadd('prev');
   xadd('next');
   xadd('home');
   xadd('up');
   xadd('menu');
   xadd('refresh');
   xadd('newfolder');
   xadd('explore');
   end
else if (xstyle=bnFav) then
   begin
   xadd('add');
   xadd('edit');
   end;

//successful
result:=true;
except;end;
end;

function tbasicnav._xoff_toolbarsync(x:tbasictoolbar):boolean;
var
   xfolder:string;
begin
result:=false;

try
xfolder:=folder;
x.benabled2['nav.favadd']:=(xfavfolder<>'');//changes depending on if it's an open/save/nav etc box
if (ifavlabel<>nil) then ifavlabel.benabled2['nav.favadd']:=(xfavfolder<>'');//changes depending on if it's an open/save/nav etc box
x.benabled2['nav.prev']:=canprev;
x.benabled2['nav.next']:=cannext;
x.benabled2['nav.home']:=(xfolder<>'');
x.benabled2['nav.up']:=(xfolder<>'');
x.benabled2['nav.newfolder']:=(xfolder<>'');
x.benabled2['nav.explore']:=io__canshowfolder(xfolder);//04sep2025
x.bvisible2['nav.preview']:=canpreview;
x.bmarked2['nav.preview']:=canpreview and preview;
x.benabled2['nav.commonfolder']:=(ocommonfolder<>'');
if (istyle=bnOpen) and zzok(iname,7263) then x.benabled2['nav.openprompt']:=(ilistfolder<>'') and (iname.value<>'');
if (istyle=bnSave) and zzok(iname,7264) then x.benabled2['nav.saveprompt']:=(ilistfolder<>'') and (iname.value<>'');
//was: x.benabled2['nav.commonfolder']:=(ocommonfolder<>'') and (not strmatch(xfolder,ocommonfolder));
except;end;
end;

function tbasicnav.xfavfolder:string;
begin
if (istyle=bnFav) or (istyle=bnFavlist) then result:=ifavfolder
else if (istyle=bnOpen) or (istyle=bnSave) then result:=io__asfoldernil(ilistfolder)
else if (istyle=bnFolder) or (istyle=bnFolder2) then result:=io__asfoldernil(ilistfolder)
else if (istyle=bnNav) or (istyle=bnNavlist) or (istyle=bnNamelist) then result:=io__asfoldernil(ilistfolder)
else result:='';
end;

function tbasicnav._xoff_toolbarevent(x:tbasictoolbar):boolean;
begin
result:=zzok(x,7265) and xcmd(x.ocode,x.ocode2,x.otepcolor);
end;

function tbasicnav.popfav:string;
begin
result:=folder;
if gui.popfav(result) then folder:=result;
end;

function tbasicnav.xcmd(xcode:longint;xcode2:string;xtepcolor:longint):boolean;
label
   skipend;
var
   a:tbasiccontrol;
   b:tstr8;
   v32,p,xstyle,xtep:longint;
   xsize:comp;
   v,xname,xlabel,xfolder,str1:string;

   function m(const xname:string):boolean;
   begin

   result:=strmatch(xname,xcode2);

   end;

   function mv(const s:string):boolean;
   begin

   result:=strm(xcode2,s,v,v32);

   end;

begin

//defaults
result      :=true;//handled
v           :='';
v32         :=0;
b           :=nil;
xfolder     :=folder;

try

//get
if m('nav.home') then imustfolder:='home'
else if m('nav.refresh') then reload
else if m('nav.commonfolder') then imustfolder:=ocommonfolder
else if m('nav.prev') then prev
else if m('nav.next') then next
else if m('nav.fav') then popfav
else if m('nav.favadd') then
   begin

   if (xfavfolder<>'') then addfav(xfavfolder);//02jun2021

   end
else if m('nav.favedit') then
   begin

   if zzok(ifavcore,7266) then
      begin

      str1:=ifavcore.text;

      if gui.poptxt(str1,wwsNone,true,'Edit Favourites List','Folder Format|Type one full folder name per line including trailing slash - e.g. C:\Windows\ |*|Portable folders (folders on same drive as app) begin with "?:\"') then
         begin

         savefav(str__newaf8b(low__remdup2(str1,true,false,false)));
         loadfav;

         end;

      end;

   end
else if m('nav.up') then
   begin

   if (xfolder<>'') then
      begin

      str1:='home';

      if (low__len32(xfolder)>=2) then
         begin

         for p:=(low__len32(xfolder)-1) downto 1 do if (strcopy1x(xfolder,p,1)='\') or (strcopy1x(xfolder,p,1)='/') then
            begin

            str1:=strcopy1(xfolder,1,p);
            break;

            end;//p

         end;

      folder:=str1;

      end;

   end
else if m('nav.showfolder') then
   begin

   str1:=selectedfolder;
   if (str1<>'') then runlow(str1,'');

   end

else if mv('nav.editwithnotepad.') then//23mar2026, 18sep2025
   begin

   if (v<>'') then runlow('notepad',v);

   end
else if mv('nav.editwithpaint.') then//23mar2026, 18sep2025
   begin

   if (v<>'') then runlow('mspaint',v);

   end
else if mv('nav.print.') then//23mar2026, 18sep2025
   begin

   if (v<>'') then runlow('print',v);

   end
else if m('nav.copy') then clip__copytext(value)//30mar2022
else if m('nav.copyall') then
   begin

   b:=str__new8;

   if zzok(ilistcore,7284) then
      begin

      for p:=0 to max32 do
      begin

      if not nav__get(ilistcore,p,xstyle,xtep,xsize,xname,xlabel) then break;
      if (xstyle=nltFile) then b.sadd(ilistfolder+xname+rcode);

      end;//p

      clip__copytext(b.text);

      end;

   end
else if m('nav.selectall') then
   begin

   if (ilist<>nil) then ilist.setsel(0,ilist.count);

   end
else if m('nav.selectrange') then
   begin

   if (ilist<>nil) then ilist.selectrange;

   end
else if m('nav.selectstart') then
   begin

   if (ilist<>nil) then ilist.pos:=ilist.selstart-(ilist.vcount div 2);

   end
else if m('nav.selectend') then
   begin

   if (ilist<>nil) then ilist.pos:=ilist.selstart+frcmin32(ilist.selcount-1,0)-(ilist.vcount div 2);

   end
else if mv('nav.sort.') then
   begin

   sortstyle:=frcrange32(v32,0,nlMax);

   end
else if m('nav.newfolder') then
   begin

   if gui.popnewfolder(xfolder,str1) then folder:=str1;//14apr2021

   end
else if m('nav.folderimage') then
   begin

   str1:=selectedfolder;
   if (str1<>'') and io__driveexists(str1) and gui.popfolderimg(str1) then imustreload:=true;//12apr2021

   end
else if m('nav.openprompt') then
   begin

   str1:=value;

   if not io__fileexists(str1) then
      begin

      gui.poperror('','File not found "'+io__extractfilename(str1)+'"');
      goto skipend;

      end;

   //close the dlg window with the "open" button as clicked - 03mar2021
   if gui.xdlg(a) then
      begin

      a.ocode:=1;
      a.ocode2:='open';
      a.visible:=false;

      end;

   end
else if m('nav.saveprompt') then
   begin

   str1:=value;

   if io__fileexists(str1) then
      begin

      if not gui.popquery2('Replace existing file "'+io__extractfilename(str1)+'" ?','','Replace',false) then goto skipend;

      end;

   //close the dlg window with the "save" button as clicked - 03mar2021
   if gui.xdlg(a) then
      begin

      a.ocode:=1;
      a.ocode2:='save';
      a.visible:=false;

      end;

   end
else if m('nav.explore') then
   begin

   if (xfolder<>'') then runlow(xfolder,'');

   end
else if m('nav.preview') then preview:=not preview//22may2022
else if m('nav.showmenu') then
   begin

   if      zzok(ilist,7267) and ilist.ocanshowmenu then ilist.showmenu
   else if zzok(ifav,7268)  and ifav.ocanshowmenu  then ifav.showmenu;

   end
else result:=false;//not handled

skipend:
except;end;

//free
str__free(@b);

end;

function tbasicnav.canshowmenu:boolean;
begin
if zzok(ilist,7267)     then result:=ilist.ocanshowmenu
else if zzok(ifav,7268) then result:=ifav.ocanshowmenu
else                         result:=inherited canshowmenu;
end;

procedure tbasicnav.showmenu;//20mar2022
begin
if zzok(ilist,7267) and ilist.ocanshowmenu then ilist.showmenu
else if zzok(ifav,7268) and ifav.ocanshowmenu then ifav.showmenu
else inherited showmenu;
end;

function tbasicnav.getdownindex:longint;
begin
if zzok(ilist,7269) then result:=ilist.downindex else result:=0;
end;

procedure tbasicnav.setdownindex(x:longint);
begin
if zzok(ilist,7270) then ilist.downindex:=x;
end;

procedure tbasicnav.findinfoBrief(var xisnav,xisfolder,xisfile:boolean);
var
   xselstart,xselcount,xdownindex,xnavindex,xfolderindex,xfileindex,xnavcount,xfoldercount,xfilecount:longint;
begin
findinfo(xselstart,xselcount,xdownindex,xnavindex,xfolderindex,xfileindex,xnavcount,xfoldercount,xfilecount,xisnav,xisfolder,xisfile);
end;

function tbasicnav.findinfo(var xselstart,xselcount,xdownindex,xnavindex,xfolderindex,xfileindex,xnavcount,xfoldercount,xfilecount:longint;var xisnav,xisfolder,xisfile:boolean):boolean;
var
   xsize:comp;
   xfilename:string;
begin
result:=findinfo2(max32,xselstart,xselcount,xdownindex,xnavindex,xfolderindex,xfileindex,xnavcount,xfoldercount,xfilecount,xisnav,xisfolder,xisfile,xsize,xfilename,false);
end;

function tbasicnav.findinfo2(xindex:longint;var xselstart,xselcount,xdownindex,xnavindex,xfolderindex,xfileindex,xnavcount,xfoldercount,xfilecount:longint;var xisnav,xisfolder,xisfile:boolean;var xsize:comp;var xvalue:string;xfindvalue:boolean):boolean;
label
   skipend;
var//Note: xindex=max32=used internal value from list or value provided by xselstart, else OVERRIDE no matter what - 28sep2022
   xnav1,xnav2,xfolder1,xfolder2,xfile1,xfile2:longint;
   xstyle2,xtep2:longint;
   xname2,xlabel2:string;
begin
//defaults
result:=false;

try
xselstart:=0;
xselcount:=0;
xdownindex:=0;
xnavindex:=0;
xfolderindex:=0;
xfileindex:=0;
xisnav:=false;
xisfolder:=false;
xisfile:=false;
xvalue:='';
xsize:=-1;
//init
if zzok(ilist,7271) then
   begin
   xselstart:=ilist.selstart;
   xselcount:=ilist.selcount;
   //.override with this index value - 28sep2022
   if (xindex<max32) then
      begin
      if (xindex<0) or (xindex>=ilist.count) then goto skipend;
      end
   else xindex:=ilist.selstart;
   //.xsize
   if zzok(ilistcore,7284) then nav__get(ilistcore,xindex,xstyle2,xtep2,xsize,xname2,xlabel2);
   end
else xindex:=0;

xdownindex:=getdownindex;
xnavcount:=navcount;
xfoldercount:=foldercount;
xfilecount:=filecount;
xnav1:=0;
xnav2:=xnav1+(xnavcount-1);
xfolder1:=xnav2+1;
xfolder2:=xfolder1+(xfoldercount-1);
xfile1:=xfolder2+1;
xfile2:=xfile1+(xfilecount-1);
//nav
xisnav:=(xindex>=xnav1) and (xindex<=xnav2);
if xisnav then xnavindex:=xindex-xnav1;
//folder
xisfolder:=(xindex>=xfolder1) and (xindex<=xfolder2);
if xisfolder then xfolderindex:=xindex-xfolder1;
//file
xisfile:=(xindex>=xfile1) and (xindex<=xfile2);
if xisfile then xfileindex:=xindex-xfile1;
//value
if xfindvalue then xvalue:=valuelist[xindex];
//successful
result:=true;
skipend:
except;end;
end;

procedure tbasicnav.setsortstyle(x:longint);
begin
if low__setint(isortstyle,frcrange32(x,0,nlMax)) then imustreload:=true;
end;

procedure tbasicnav.setfilterlist(x:string);//18sep2025
var//Note: expects a list of KNOWN extensions e.g. "bat;txt;bmp;tea" etc
   dcount,dindex,xlen,lp,p:longint;
   dlabel,dext,dmask:string;
   c:char;
begin
try

//init
dindex:=0;
dcount:=0;

//sort the list - 18sep2025
x:=filter__sort(x);

//get
xlen:=low__len32(x);
if (xlen>=1) then
   begin
   //init
   lp:=1;
   x:=x+fesep;
   xlen:=low__len32(x);
   //get
   for p:=1 to xlen do
   begin

   c:=x[p-1+stroffset];

   if (c=fesep) then
      begin

      //add
      if io__findext(strcopy1(x,lp,p-lp),dlabel,dext,dmask) then
         begin

         if (dcount>=high(fcap)) then break;

         fcap[dcount]:=dlabel;
         fext[dcount]:=dext;
         fmsk[dcount]:=dmask;
         ftep[dcount]:=tep__filetype20('.'+dext);

         inc(dcount);

         end;

      //reset
      lp:=p+1;

      end;

   end;//p

   end;//if

//set
fcount:=dcount;
findex:=frcrange32(dindex,0,frcmin32(dcount-1,0));
findex_tep;

except;end;
end;

procedure tbasicnav.findex_tep;
var
   dtep:longint;
begin

dtep:=tepXXX20;
if (fcount>=1) then dtep:=tep__filetype20('.'+fext[frcrange32(findex,0,fcount-1)]);
if zzok(ifilter,7272) and (ifilter.tep<>dtep) then ifilter.tep:=dtep;

end;

function tbasicnav.getfilterlist:string;
var
   p:longint;
begin
result:='';
if (fcount>=1) then for p:=0 to (fcount-1) do if (fext[p]<>'') then result:=result+fext[p]+fesep;
end;

function tbasicnav.getfilter:string;
begin
//defaults
result:='';
if (fcount>=1) then result:=fext[0];
//active filter
if (fcount>=1) then result:=fext[frcrange32(findex,0,fcount-1)];
end;

function tbasicnav.getfilterindex:longint;
begin
result:=frcrange32(findex,0,frcmin32(fcount-1,0));
end;

procedure tbasicnav.setfilterindex(x:longint);
begin
findex:=frcrange32(x,0,frcmin32(fcount-1,0));findex_tep;
end;

procedure tbasicnav.setfilter(x:string);
var
   p:longint;
begin
//check
if (fcount<=0) then exit;
//find
for p:=0 to (fcount-1) do if strmatch(x,fext[p]) then
   begin
   findex:=p;
   findex_tep;
   break;
   end;
end;

procedure tbasicnav.setfilterfromfilename(x:string);//used by "popsave()" to automatically choose save filter by filename extension - 18jun2021
begin
filter:=io__readfileext(x,false);
end;

procedure tbasicnav.setvalue(x:string);
var
   xmustfolder,xmustname:string;
   p:longint;
begin
try
//defaults
if (strcopy1(x,2,1)=':') then//fixed - 09aug2021
   begin
   xmustfolder:=x;
   xmustname:='';
   end
else
   begin
   xmustfolder:='';
   xmustname:=x;
   end;
//get
if (x<>'') then
   begin
   for p:=low__len32(x) downto 1 do if (strbyte1(x,p)=ssBackslash) or (strbyte1(x,p)=ssSlash) then
      begin
      xmustfolder:=strcopy1(x,1,p);
      xmustname:=strcopy1(x,p+1,low__len32(x));
      break;
      end;
   end;
//filter
if (xmustfolder='') then xmustfolder:='home';
//set
imustfolder:=xmustfolder;
imustname:=xmustname;
except;end;
end;

function tbasicnav.xfiltername(xnewname:string;xaddfilterext:boolean):string;
var
   xfilter:string;

   function xmultimaskORanymask:boolean;
   var
      xlen,p:longint;
   begin//Note: detects presence of mask "*" or "*;" as a part of a series of masks -> this mask changes how filenames and their extensions are treated - 09mar2021
   result:=false;

   try
   xlen:=low__len32(xfilter);
   if (xlen>=1) then
      begin
      for p:=1 to xlen do if (strcopy1x(xfilter,p,1)='*') or (strcopy1x(xfilter,p,1)=fesepX) then
         begin
         result:=true;
         break;
         end;//p
      end;
   except;end;
   end;
begin
result:='';

try
//init
xfilter:=filter;
//get
case xmultimaskORanymask of
true:begin
   result:=io__safename(io__extractfilename(xnewname));//filename with extension assumed
   end;
else begin
   case xaddfilterext of
   true:begin
      result:=io__safename(io__extractfilename(xnewname));
      if (xfilter<>'') and (not strmatch(xfilter,io__lastext(result))) then
         begin
         result:=result+'.?';//fake ext for "low__forceext2()" to work with - 09mar2021
         result:=io__forceext2(result,xfilter,false);//use currently active filter - 03mar2021
         end;
      end;
   else result:=io__safename(io__remlastext(io__extractfilename(xnewname)));
   end;//case
//   if not xaddfilterext then result:=io__remlastext(result);//only remove ext if value is being assigned to internal "iname.value" else it might be a name with a user defined extension that must be preserved - 09mar2021
//   result:=io__safename(result);
//   if xaddfilterext and (xfilter<>'') then result:=low__forceext2(result,xfilter,false);//use currently active filter - 03mar2021
   end;
end;//case
except;end;
end;

function tbasicnav.getvalue:string;//06apr2021
begin
result:=valuelist[max32];
end;

function tbasicnav.getvaluelist(xindex:longint):string;//28sep2022
begin
result:=getvaluelist2(xindex,bnNil);
end;

function tbasicnav.getvaluelist2(xindex,xforcestyle:longint):string;//28sep2022
var//Note: xindex=max32 => switches to internal list focusindex - 28sep2022
   xstyle,xtep,xtepcolor:longint;
   xtab,xcaption,xcaplabel,xhelp,xcode2:string;
   xcode,xshortcut,xindent:longint;
   xflash,xenabled,xtitle,xsep,xbold:boolean;
begin
//defaults
result:='';

try
//init
xstyle:=low__aorb(istyle,xforcestyle,xforcestyle>bnNil);
//get
if (xstyle=bnOpen) or (xstyle=bnSave) then
   begin
   if zzok(iname,7273) then result:=ilistfolder+xfiltername(iname.value,true);
   end
else if (xstyle=bnNav) or (xstyle=bnNavlist) or (xstyle=bnNamelist) then//06apr2021
   begin
   //special
   if (xindex=max32) then xindex:=ilist.selstart;
   //folder or folder+filename
   result:=ilistfolder;
   if __ongetitem2(ilist,false,xindex,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) then
      begin
      case xcode of
      nltFile:result:=result+xcaption;
      nltFolder:result:=io__asfoldernil(result+xcaption);
      nltNav,nltSysfolder:begin
         result:=xcaption;
         if strmatch(result,'home') then result:='';
         end;
      end;//case
      end;
   end
else if (xstyle=bnFolder) or (xstyle=bnFolder2) then
   begin
   result:=ilistfolder;
   end
else if (xstyle=bnFav) or (xstyle=bnFavlist) then
   begin
   //special
   if (xindex=max32) then xindex:=ifav.selstart;
   //get
   if zzok(ifav,7275) and __ongetitem2(ifav,false,xindex,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) then result:=xcaption;
   end;
except;end;
end;

function tbasicnav.selectedfolder:string;
var
   xtep,xtepcolor:longint;
   xtab,xcaption,xcaplabel,xhelp,xcode2:string;
   xcode,xshortcut,xindent:longint;
   xflash,xenabled,xtitle,xsep,xbold:boolean;
begin
result:='';

try
if (istyle=bnFav) or (istyle=bnFavlist) then
   begin
   if zzok(ifav,7276) and __ongetitem2(ifav,false,ifav.selstart,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) then result:=xcaption;
   end
else
   begin
   result:=ilistfolder;
   if __ongetitem2(ilist,false,ilist.selstart,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) then
      begin
      case xcode of
      nltFile:;
      nltFolder:result:=io__asfoldernil(result+xcaption);
      nltNav,nltSysfolder:begin
         result:=xcaption;
         if strmatch(result,'home') then result:='';
         end;
      end;//case
      end;
   end;
except;end;
end;

function tbasicnav.getvalueEXT:string;//12jan2022
begin
if (valuestyle=nltFile) and (value<>'') then result:=io__readfileext_low(value) else result:='';
end;

function tbasicnav.getvaluestyle:longint;
var
   xtep,xtepcolor:longint;
   xtab,xcaption,xcaplabel,xhelp,xcode2:string;
   xcode,xshortcut,xindent:longint;
   xflash,xenabled,xtitle,xsep,xbold:boolean;
begin
result:=nltNone;//none

try
if (istyle=bnOpen) or (istyle=bnSave) then
   begin
   result:=nltFile;
   end
else if (istyle=bnNav) or (istyle=bnNavlist) or (istyle=bnNamelist) then
   begin
   if __ongetitem2(ilist,false,ilist.selstart,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) then result:=xcode;
   end
else if (istyle=bnFolder) or (istyle=bnFolder2) then
   begin
   if __ongetitem2(ilist,false,ilist.selstart,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) then result:=xcode;
   end
else if (istyle=bnFav) or (istyle=bnFavlist) then
   begin
   if zzok(ifav,7277) and __ongetitem2(ifav,false,ifav.selstart,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) then result:=xcode;
   end;
except;end;
end;

function tbasicnav.getfolder:string;
begin
if (istyle=bnFav) or (istyle=bnFavlist) then result:='' else result:=ilistfolder;
end;

procedure tbasicnav.setfolder(x:string);
begin
if (istyle=bnFav) or (istyle=bnFavlist) then
   begin
   //nil
   end
else
   begin
   if (x='') or strmatch(x,'home') then x:='home' else x:=io__asfoldernil(x);
   imustfolder:=x;
   end;
end;

function tbasicnav.folderpending:boolean;
begin
result:=(imustfolder<>'');
end;

function tbasicnav.foldervalue:string;//14jul2025
begin

if (istyle=bnFav) or (istyle=bnFavlist) then result:=''
else if (imustfolder<>'')               then result:=imustfolder
else                                         result:=ilistfolder;

end;

function tbasicnav.xenhancednames(x:string):string;
begin
if (x<>'') then result:=x else result:='home';
end;

procedure tbasicnav.xhisadd(xval:string;xpos,xitemindex:longint;xstorev12:boolean);//22mar2021
begin
//filter -> enforce trailing slash for folders -> ensures history does not duplicate entries based on a trailing slash or not - 31mar2021
xval:=io__asfoldernil(xenhancednames(xval));
//get
if (ihisname<>'') and (strcopy1(xval,1,1)<>iprevnextcode) then his__add2(ihisname,xval,xpos,xitemindex,xstorev12);
end;

function tbasicnav.canhome:boolean;
begin
result:=(folder<>'');
end;

procedure tbasicnav.home;
begin
folder:='home';
end;

procedure tbasicnav.filter__onclick(sender:tobject);
var
   m:tstr8;
   xcode:longint;
   xcode2:string;
   int1,p,i:longint;
begin
try
//defaults
m:=nil;
//check
if (fcount<=0) or zznil(ifilter,2327) or ((istyle<>bnOpen) and (istyle<>bnSave))then exit;
//init
m:=str__new8;

//get
low__menuinit(m);
low__menutitle(m,tepnone,'Available Formats','');
for p:=0 to (fcount-1) do low__menuitem2(m,ftep[p],fcap[p],'','mask',1+p,aknone,true);
low__menuend(m);

//set
int1:=findex+1;
if gui.popdroplist(m,ifilter,int1,xcode,xcode2,'') then
   begin
   if (xcode2='mask') then
      begin
      i:=frcmax32(frcrange32(xcode-1,0,frcmin32(fcount-1,0)),high(fcap));
      if (i>=0) and (i<fcount) then
         begin
         findex:=i;
         findex_tep;
         end;
      end;
   end;

//filter value
if zzok(iname,7278) and ((istyle=bnOpen) or (istyle=bnSave)) then iname.value:=xfiltername(iname.value,false);
except;end;

//free
str__free(@m);

end;

procedure tbasicnav.click__list;//25jan2025
begin
if (ilist<>nil) and ilist.visible then __onclick2(ilist,'dblclick');
end;

procedure tbasicnav.__onclick(sender:tobject);
begin
__onclick2(sender,'');
end;

procedure tbasicnav.__onclick2(sender:tobject;xcmd:string);
label
   skipend;
var
   xtep,xtepcolor:longint;
   xtab,xcode2,xcaption,xcaplabel,xhelp:string;
   xcode,xshortcut,xindent:longint;
   xflash,xenabled,xtitle,xsep,xbold:boolean;
   xdblclickDisabled,xdbclick:boolean;
begin
try
//check
if zznil(sender,2329) then exit;
xdbclick:=gui.mousedbclick or (xcmd='dblclick');
//get
if (sender is tbasictoolbar) then xoff_toolbarevent(sender as tbasictoolbar)//07mar2021
else if (sender=ifav) then
   begin
   if __ongetitem2(ifav,false,ifav.selstart,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) then imustfolder:=xcaption;
   end
else if (sender=ilist) then
   begin
   if __ongetitem2(ilist,false,ilist.selstart,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) then
      begin
      //.fix for "single click" lists running in "lsMany" mode -> single click restricted to image on left side of list (first ~40px) - 11oct2022
      xdblclickDisabled:=(not vidoubleclicks) and ((ilist.ostyle<>lsmany) or (ilist.mousex<=(largest32(40*vizoom,ilist.rowheight))));
      case xcode of
      nltFolder:begin
         if xdblclickDisabled or xdbclick then imustfolder:=ilistfolder+xcaption;
         ivalueinlist:=ilistfolder+xcaption;
         end;
      nltNav,nltSysfolder:begin
         if xdblclickDisabled or xdbclick then imustfolder:=xcaption;
         if (xcode=nltNav) and strmatch('home',xcaption) then ivalueinlist:='' else ivalueinlist:=xcaption;
         end;
      nltFile:begin
         if zzok(iname,7279) and ((style=bnOpen) or (style=bnSave)) then iname.value:=xfiltername(xcaption,false);
         ivalueinlist:=folder+xcaption;//by-pass mask enforcement and use raw filename from list
         end;
      else ivalueinlist:='';
      end;//case
      ivalueinlist_style:=xcode;
      //his-sync
      if zzok(ilist,7280) then xhisadd(ilistfolder,ilist.pos,ilist.selstart,true);//22mar2021
      end;
   end;
skipend:
gui.xfireevent(self,fonclick);//supports closelock - 03apr2021
except;end;
end;

function tbasicnav.xvalueinlist(var xvalue:string;var xstyle:longint):boolean;
var//realtime version for preview system -> it can scan the list for currently selected file and create a preview - 22nov2024
   xtep,xtepcolor:longint;
   xtab,xcode2,xcaption,xcaplabel,xhelp:string;
   xcode,xshortcut,xindent:longint;
   xflash,xenabled,xtitle,xsep,xbold:boolean;
begin

result:=__ongetitem2(ilist,false,ilist.selstart,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold);

if result then
   begin

   case xcode of
   nltFolder            :xvalue:=ilistfolder+xcaption;
   nltNav,nltSysfolder  :if (xcode=nltNav) and strmatch('home',xcaption) then xvalue:='' else xvalue:=xcaption;
   nltFile              :xvalue:=folder+xcaption;//by-pass mask enforcement and use raw filename from list
   else                  xvalue:='';
   end;//case

   xstyle:=xcode;

   end
else
   begin

   xvalue:='';
   xstyle:=nltNone;

   end;

end;

procedure tbasicnav.make__backgroundhead;//03dec2023
begin
if (ibar<>nil) and (not ibar.xishead) then ibar.make__backgroundhead;
end;

procedure tbasicnav._onalign(sender:tobject);
var
   ci:twinrect;
   xzoom,vsp,hsp,int1,xsplit,xsplit2,xtop,xbot,ltop,cw,xstyle:longint;
   dpreviewattop,dpreview:boolean;
   a1,a2,b1,b2:tbasiccontrol;

   function sok(x:tbasiccontrol):boolean;
   begin
   result:=zzok(x,7281);
   end;

   procedure sa(x:tbasiccontrol;da:twinrect);
   begin
   //check
   if zznil(x,2330) then exit;
   //range
   if (da.left<ci.left)     then da.left:=ci.left;
   if (da.right>ci.right)   then da.right:=ci.right;
   if (da.top<ci.top)       then da.top:=ci.top;
   if (da.bottom>ci.bottom) then da.bottom:=ci.bottom;
   //set
   x.xsetclientarea(da);
   end;
begin
try
//init
xzoom:=vizoom;
vsp:=2*xzoom;
hsp:=2*xzoom;
xstyle:=istyle;
ci:=clientinner;
cw:=ci.right-ci.left+1;
xtop:=ci.top;
xbot:=ci.bottom;
xsplit:=frcrange32(ci.left+round(0.35*(ci.right-ci.left)),ci.left,ci.right);
xsplit2:=xsplit+hsp;
dpreview:=canpreview and preview and sok(ipreviewbox);//22may2022
dpreviewattop:=true;//set to TOP by default, but can be switched to bottom - 23may2022
//but
if sok(ibut) and ibut.visible then
   begin
   sa(ibut,area__make(ci.left,xbot-ibut.getalignheight(cw),ci.right,xbot));
   xbot:=ibut.clientarea.top-vsp;
   end;
//bar
if sok(ibar) and (not ibar.xishead) and ibar.visible then
   begin
   sa(ibar,area__make(ci.left,xtop,ci.right,xtop+ibar.getalignheight(cw)));
   xtop:=ibar.clientarea.bottom+1;
   end;
//get
if (xstyle=bnFav) or (xstyle=bnFavlist) then
   begin
   if sok(ifav) then sa(ifav,area__make(ci.left,xtop,ci.right,xbot));
   end
else if (xstyle=bnNav) or (xstyle=bnNavlist) or (xstyle=bnNamelist) then
   begin
   if sok(ilist) then sa(ilist,area__make(ci.left,xtop,ci.right,xbot));
   end
else if (xstyle=bnFolder) then
   begin
   if sok(ifav)  then sa(ifav,area__make(ci.left,xtop,xsplit,xbot));
   if sok(ilist) then sa(ilist,area__make(xsplit2,xtop,ci.right,xbot));
   end
else if (xstyle=bnOpen) or (xstyle=bnSave) or (xstyle=bnFolder2) then
   begin
   //name
   if sok(iname) then sa(iname,area__make(xsplit2,xbot-iname.getalignheight(cw),ci.right,xbot));
   //filter
   if sok(ifilter) then sa(ifilter,area__make(ci.left,xbot-ifilter.getalignheight(cw),xsplit,xbot));
   //.new xbot
   if sok(ifilter) then xbot:=ifilter.clientarea.top-1 else if sok(iname) then xbot:=iname.clientarea.top-1;
   //filterlabel + namelabel
   if sok(ifilterlabel) then sa(ifilterlabel,area__make(ci.left,xbot-ifilterlabel.getalignheight(cw),xsplit,xbot));
   if sok(inamelabel) then sa(inamelabel,area__make(xsplit2,xbot-inamelabel.getalignheight(cw),ci.right,xbot));
   //.new xbot
   if sok(ifilterlabel) then xbot:=ifilterlabel.clientarea.top-vsp else if sok(inamelabel) then xbot:=inamelabel.clientarea.top-vsp;
   //action + new xbot
   if sok(iaction) then
      begin
      int1:=iaction.getalignheight(cw);
      sa(iaction,area__make(ci.left,xbot-int1,ci.right,xbot));
      xbot:=frcmin32(xbot-int1,ci.top);
      end;

   //fav + preview -------------------------------------------------------------
   //.get
   if dpreviewattop and dpreview then
      begin
      a1:=ipreviewlabel;
      a2:=ipreviewbox;
      b1:=ifavlabel;
      b2:=ifav;
      end
   else
      begin
      a1:=ifavlabel;
      a2:=ifav;
      b1:=ipreviewlabel;
      b2:=ipreviewbox;
      end;
   //.set
   ltop:=xtop;
   if sok(a1) then
      begin
      int1:=a1.getalignheight(xsplit-ci.left+1);
      sa(a1,area__make(ci.left,xtop,xsplit,xtop+int1-1));
      inc(ltop,int1);
      end;
   if sok(a2) then
      begin
      if dpreview then int1:=xtop+((xbot-xtop) div 2) else int1:=xbot;//23may2022
      sa(a2,area__make(ci.left,ltop,xsplit,int1));
      ltop:=int1+1;
      end;
   //preview - optional- 22may2022
   if dpreview then
      begin
      if sok(b1) then
         begin
         int1:=b1.getalignheight(xsplit-ci.left+1);
         sa(b1,area__make(ci.left,ltop,xsplit,ltop+int1-1));
         inc(ltop,int1);
         end;
      if sok(b2) then sa(b2,area__make(ci.left,ltop,xsplit,xbot));
      end;
   //list
   if sok(ilist) then sa(ilist,area__make(xsplit2,xtop,ci.right,xbot));
   end;
except;end;
end;

function tbasicnav.__ongetitem(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;
begin
result:=__ongetitem2(sender,true,xindex,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold);
end;

function tbasicnav.__ongetitem2(sender:tobject;xdisplayonly:boolean;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;
const
   xindentstep=5;
var
   int1,xstyle:longint;
   xsize:comp;
   xname,xlabel:string;
begin

//defaults
result       :=false;

try
//init
xindent      :=0;
xtab         :=otab;
xtepcolor    :=clnone;
xflash       :=false;

//get
if zznil(sender,2131) then exit
else if (sender=ifav) then
   begin

   xcaplabel:='';

   if zzok(ifavcore,7282) and (xindex>=0) and (xindex<ifavcore.count) then xcaption:=io__readportablefilename(ifavcore.items[xindex]^) else xcaption:='?';
   if xdisplayonly then xcaption:=io__folderaslabel(xcaption);

   xtep:=tepFolder20;

   if zzok(ifavteps,7283) and (xindex>=0) and (xindex<ifavteps.count) then
      begin

      int1:=ifavteps.value[xindex];
      if (int1<>tepNone) then xtep:=int1;

      end;

   result:=true;

   end
else if (sender=ilist) then
   begin

   if zzok(ilistcore,7284) and nav__get(ilistcore,xindex,xstyle,xtep,xsize,xname,xlabel) then
      begin

      xcode:=xstyle;
      xcaption:=xname;

      case xstyle of//0=nav, 1=folder, 2=file, 3=full folder
      nltTitle:begin

         if (xindex=0) and (xcaption='') then
            begin

            xcaption:=insstr(caption+'  ',caption<>'')+k64(ifoldercount)+' folder'+insstr('s',ifoldercount<>1)+', '+k64(ifilecount)+' file'+insstr('s',ifilecount<>1);
            xindent:=0;//xindentstep;

            end;

         xtep:=tepNone;
         xtitle:=true;

         end;

      nltNav:xindent:=frcmin32(xindex-1,0)*xindentstep;

      nltFolder,nltSysfolder:;

      nltFile:;

      else xtep:=tepUnknown20;
      end;//case

      //caption filter
      if ((xstyle=nltNav) or (xstyle=nltSysfolder)) and xdisplayonly and (xcaption<>'') then xcaption:=io__folderaslabel(xcaption);

      //special overrides
      if (xstyle=nltNav) and (xname='') then
         begin

         xindent:=0;
         xcaption:='Home';
         xcaplabel:=xlabel;
         xtep:=tepHome20;

         end
      else if (xstyle=nltTitle) then
         begin

         xcaplabel:=xlabel;

         end
      else if (low__len32(xname)=3) and (strbyte1(xname,2)=ssColon) and ((strbyte1(xname,3)=ssbackslash) or (strbyte1(xname,3)=ssSlash)) then//05apr2021
         begin

         xcaption:=strup(xcaption);
         xcaplabel:=xlabel;

         end

      else if (xstyle=nltNav) or (xstyle=nltSysfolder) then xcaplabel:=xlabel

      else if (xstyle=nltFolder) then xcaplabel:=xlabel;

      end
   else
      begin

      xcaption:='list__'+intstr32(xindex);
      xcaplabel:='list.label__'+intstr32(xindex);

      if (xtep=tepnone) then xtep:=tepNew20;

      end;

   result:=true;

   end;

//optional value modifier - 03oct2024
if assigned(fonmodifyitem) then fonmodifyitem(self,xtab,xindent,xstyle,xtepcolor,xtep,xcaption,xcaplabel,xbold,(sender=ifav));

except;end;
end;

function tbasicnav.xbar:tbasictoolbar;
var
   a:tbasicscroll;
begin
result:=ibar;
if zznil(result,2340) then
   begin
   if ohead and xwindow2(a) then ibar:=a.xhead
   else ibar:=tbasictoolbar.create(self);
   result:=ibar;
   if (result=nil) then exit;
   result.onclick:=__onclick;
   _xoff_toolbaradd(result);
   end;
end;

function tbasicnav.xbut:tbasictoolbar;
begin
result:=ibut;
if zznil(result,2341) then
   begin
   ibut:=tbasictoolbar.create(self);
   result:=ibut;
   if (result=nil) then exit;

   with result do
   begin
   bordersize:=0;
   halign:=2;//orighttoleft:=true;
   normal:=true;
   end;

   result.onclick:=__onclick;
   end;
end;

function tbasicnav.xfav:tbasicmenu;
begin
result:=ifav;
if zznil(result,2342) then
   begin
   ifav:=tbasicmenu.create(self);
   result:=ifav;
   if (result=nil) then exit;

   ifav.oautoclose:=false;
   ifav.help:='Jump to favourite folder';
   ifav.nohint;
   ifav.ongetitem:=__ongetitem;
   ifav.onclick:=__onclick;
   end;
end;

function tbasicnav.xfavlabel:tbasictoolbar;
begin
result:=ifavlabel;
if zznil(result,2343) then
   begin
   ifavlabel:=ntitlebar(false,'Favourites','Jump to favourite folder');
   result:=ifavlabel;
   if (result=nil) then exit;
   result.onclick:=__onclick;
   end;
end;

function tbasicnav.xlist:tbasicmenu;
begin
result:=ilist;
if zznil(result,2344) then
   begin
   ilist:=tbasicmenu.create(self);
   result:=ilist;
   if (result=nil) then exit;

   ilist.oautoclose:=false;
   ilist.help:='Select a file or folder';
   ilist.nohint;
   ilist.makelistx(0);
   ilist.ongetitem:=__ongetitem;
   ilist.onclick:=__onclick;
   end;
end;

function tbasicnav.xpreviewbox:tbasiccontrol;//22may2022
begin
result:=ipreviewbox;
if zznil(result,2344) then
   begin
   ipreviewbox:=nimgview;
   ipreviewbox.bordersize:=0;//20jul2024
   result:=ipreviewbox;
   if (result=nil) then exit;
   ipreviewbox.help:='Preview';
   ipreviewbox.nohint;
   end;
end;

function tbasicnav.xpreviewlabel:tbasiccontrol;//24jan2025, 22may2022
begin
result:=ipreviewlabel;
if zznil(result,2345) then
   begin
   ipreviewlabel:=mtitle('Preview','File Preview');//mimic's title in list
   result:=ipreviewlabel;
   if (result=nil) then exit;
   end;
end;

function tbasicnav.xname:tbasicedit;
begin
result:=iname;
if zznil(result,2346) then
   begin
   iname:=tbasicedit.create(self,'');
   result:=iname;
   if (result=nil) then exit;

   iname.help:='Type a filename';
   end;
end;

function tbasicnav.xfilter:tbasicedit;
begin
result:=ifilter;
if zznil(result,2347) then
   begin
   ifilter:=tbasicedit.create(self,'');
   result:=ifilter;
   if (result=nil) then exit;

   ifilter.help:='Select file format';
   ifilter.tep:=tepFNew20;
   ifilter.makedropstatic;
   ifilter.onclick2:=filter__onclick;
   end;
end;

function tbasicnav.xaction:tbasicimageexts;
begin
result:=iaction;
if zznil(result,2347) then
   begin
   iaction:=nimgexts('Options','Select a format specific option');
   result:=iaction;
   if (result=nil) then exit;
   iaction.oautoshrink:=true;
   iaction.oboldhead:=true;//title
   iaction.itemsperline:=6;
   iaction.help:='Select option';
   end;
end;

function tbasicnav.xnamelabel:tbasiccontrol;
begin
result:=inamelabel;
if zznil(result,2348) then
   begin
   inamelabel:=mtitle('Name','Type a filename');
   result:=inamelabel;
   if (result=nil) then exit;

   result.obold:=true;
   end;
end;

function tbasicnav.xfilterlabel:tbasiccontrol;
begin
result:=ifilterlabel;
if zznil(result,2349) then
   begin
   ifilterlabel:=mtitle('Format','Select file format');
   result:=ifilterlabel;
   if (result=nil) then exit;

   result.obold:=true;
   end;
end;

function tbasicnav.xvaluefile(xdef:string):string;//28jun2022
begin
result:=strdefb(insstr(value,valuestyle=nltFile),xdef);
end;

procedure tbasicnav.setstyle(x:longint);
const
   xcountdown=300;//5 minutes
label
   redo;

   procedure xhide(x:tbasiccontrol);
   begin
   if zzok(x,7285) then x.visible:=false;
   end;

   procedure xshow(x:tbasiccontrol);//22may2022
   begin
   if zzok(x,7286) then
      begin
      if (x=ipreviewbox) or (x=ipreviewlabel) then x.visible:=(canpreview and preview) else x.visible:=true;
      end;
   end;

   procedure xfavcore;
   begin
   if zznil(ifavcore,2349) then ifavcore:=tdynamicstring.create;
   if zznil(ifavteps,2350) then ifavteps:=tdynamicinteger.create;
   end;

   procedure xlistcore;
   begin
   if zznil(ilistcore,2351) then ilistcore:=str__new8;
   end;
begin
try
//init
redo:
if not low__setint(istyle,x) then exit;
//get
if (x=bnNil) then
   begin
   xhide(iaction);//21dec2024
   xhide(ipreviewbox);//22may2022
   xhide(ipreviewlabel);
   xhide(ifav);
   xhide(ifavlabel);
   xhide(ilist);
   xhide(iname);
   xhide(inamelabel);
   xhide(ifilter);
   xhide(ifilterlabel);
   xhide(ibar);
   xhide(ibut);
   if zzok(ibut,7287) then ibut.clear;
   end
else if (x=bnFav) then
   begin
   xhide(iaction);//21dec2024
   xhide(ipreviewbox);//22may2022
   xhide(ipreviewlabel);
   xshow(xfav);
   xshow(xfavlabel);
   xhide(ilist);
   xhide(iname);
   xhide(inamelabel);
   xhide(ifilter);
   xhide(ifilterlabel);
   xshow(xbar);
   xshow(xbut);
   //.buttons
   xbut.clear;
   xbut.cadd('Close',tepClose20,0,scdlg,'Close window',xcountdown);
   //.other
   xfavcore;
   end
else if (x=bnFavlist) then
   begin
   xhide(iaction);//21dec2024
   xhide(ipreviewbox);//22may2022
   xhide(ipreviewlabel);
   xshow(xfav);
   xshow(xfavlabel);
   xhide(ilist);
   xhide(iname);
   xhide(inamelabel);
   xhide(ifilter);
   xhide(ifilterlabel);
   xhide(ibar);
   xhide(ibut);
   if zzok(ibut,7288) then ibut.clear;
   //.other
   xfavcore;
   end
else if (x=bnNav) then
   begin
   xhide(iaction);//21dec2024
   xhide(ipreviewbox);//22may2022
   xhide(ipreviewlabel);
   xhide(ifav);
   xhide(ifavlabel);
   xshow(xlist);
   xhide(iname);
   xhide(inamelabel);
   xhide(ifilter);
   xhide(ifilterlabel);
   xshow(xbar);
   xshow(xbut);
   //.buttons
   xbut.clear;
   xbut.add('Common Folder',tepHome20,0,'nav.commonfolder','Goto common folder');
   xbut.cadd('Cancel',tepClose20,0,scdlg,'Close window',xcountdown);
   xbut.add('Select',tepOK20,1,scdlg,'Select folder');
   //.other
   xlistcore;
   end
else if (x=bnNavlist) then
   begin
   xhide(iaction);//21dec2024
   xhide(ipreviewbox);//22may2022
   xhide(ipreviewlabel);
   xhide(ifav);
   xhide(ifavlabel);
   xshow(xlist);
   xhide(iname);
   xhide(ifilter);
   xhide(inamelabel);
   xhide(ifilterlabel);
   xhide(ibar);
   xhide(ibut);
   if zzok(ibut,7289) then ibut.clear;
   //.other
   xlistcore;
   end
else if (x=bnNamelist) then//12jan2022
   begin
   xhide(iaction);//21dec2024
   xhide(ipreviewbox);//22may2022
   xhide(ipreviewlabel);
   xhide(ifav);
   xhide(ifavlabel);
   xshow(xlist);
   xhide(iname);
   xhide(ifilter);
   xhide(inamelabel);
   xhide(ifilterlabel);
   xhide(ibar);
   xhide(ibut);
   if zzok(ibut,7289) then ibut.clear;
   //.other
   xlistcore;
   end
else if (x=bnFolder) or (x=bnFolder2) then
   begin
   if (x=bnFolder2) then
      begin
      xshow(xpreviewbox);
      xshow(xpreviewlabel);
      end
   else
      begin
      xhide(ipreviewbox);//22may2022
      xhide(ipreviewlabel);
      end;
   xhide(iaction);//21dec2024
   xshow(xfav);
   xshow(xfavlabel);
   xshow(xlist);
   xhide(iname);
   xhide(inamelabel);
   xhide(ifilter);
   xhide(ifilterlabel);
   xshow(xbar);
   xshow(xbut);
   //.buttons
   xbut.clear;
   xbut.add('Common Folder',tepHome20,0,'nav.commonfolder','Goto common folder');
   xbut.cadd('Cancel',tepClose20,0,scdlg,'Close window',xcountdown);
   xbut.add('Select',tepOK20,1,scdlg,'Select folder');
   //.other
   xfavcore;
   xlistcore;
   end
else if (x=bnOpen) then
   begin
   xhide(iaction);//21dec2024
   xshow(xpreviewbox);//22may2022
   xshow(xpreviewlabel);
   xshow(xfav);
   xshow(xfavlabel);
   xshow(xlist);
   xshow(xname);
   xshow(xnamelabel);
   xshow(xfilter);
   xshow(xfilterlabel);
   xshow(xbar);
   xshow(xbut);
   //.buttons
   xbut.clear;
//was:   xbut.add('Open',tepOpen20,1,scdlg+'open','Open file');
   xbut.add('Common Folder',tepHome20,0,'nav.commonfolder','Goto common folder');
   xbut.cadd('Cancel',tepClose20,0,scdlg,'Close window',xcountdown);
   xbut.add('Open',tepOpen20,0,'nav.openprompt','Open file');
   //.other
   xfavcore;
   xlistcore;
   end
else if (x=bnSave) then
   begin
   xshow(xpreviewbox);//22may2022
   xshow(xpreviewlabel);
   xshow(xfav);
   xshow(xfavlabel);
   xshow(xlist);
   xshow(xname);
   xshow(xnamelabel);
   xshow(xfilter);
   xshow(xfilterlabel);
   xshow(xaction);//21dec2024
   xshow(xbar);
   xshow(xbut);
   //.buttons
   xbut.clear;
//was:   xbut.add('Save',tepSave20,1,scdlg+'save','Save file'); ..but we need to prompt the filename for save replace - 03mar2021
   xbut.add('Common Folder',tepHome20,0,'nav.commonfolder','Goto common folder');
   xbut.cadd('Cancel',tepClose20,0,scdlg,'Close window',xcountdown);
   xbut.add('Save',tepSave20,0,'nav.saveprompt','Save file');
   //.other
   xfavcore;
   xlistcore;
   end
else
   begin
   x:=bnNil;
   goto redo;
   end;
except;end;
//.finalise
try
if zzok(ilist,7290) then
   begin
   ilist.showmenuFill1:=xshowmenuFill1;
   ilist.showmenuFill2:=xshowmenuFill2;
   ilist.showmenuFillINT:=xshowmenuFill;
   ilist.showmenuClick1:=xshowmenuClick1;
   ilist.showmenuClickINT:=xshowmenuClick;
   ilist.showmenuClick2:=xshowmenuClick2;
   ilist.ocanshowmenu:=true;
   end;
reload;
except;end;
end;

procedure tbasicnav.reload;
begin
imustreload:=true;
end;

function tbasicnav.xautoclose(x:boolean):tbasicnav;
begin
result:=self;
if zzok(ifav,7291) then ifav.oautoclose:=x and (istyle=bnFav);
end;

function tbasicnav.makenil:tbasicnav;
begin
result:=self;
style:=bnNil;
end;

function tbasicnav.makefav:tbasicnav;
begin
result:=self;
style:=bnFav;
end;

function tbasicnav.makefavlist:tbasicnav;
begin
result:=self;
style:=bnFavlist;
end;

function tbasicnav.makenav:tbasicnav;
begin
result:=self;
style:=bnNav;
onumber:=true;
end;

function tbasicnav.makenavlist:tbasicnav;
begin
result:=self;
style:=bnNavlist;
onumber:=true;
end;

function tbasicnav.makenavlist2:tbasicnav;
begin
result:=self;
style:=bnNavlist;
ofindname:=true;
end;

function tbasicnav.makenamelist:tbasicnav;
begin
result:=self;
style:=bnNamelist;
end;

function tbasicnav.makefolder:tbasicnav;
begin
result:=self;
style:=bnFolder;
end;

function tbasicnav.makefolder2:tbasicnav;//20jul2024: folder and show files
begin
result:=self;
style:=bnFolder2;
end;

function tbasicnav.makeopen:tbasicnav;
begin
result:=self;
style:=bnOpen;
onumber:=true;
end;

function tbasicnav.makesave:tbasicnav;
begin
result:=self;
style:=bnSave;
onumber:=true;
end;

function tbasicnav.canprev:boolean;
begin
result:=(ihisname<>'') and zzok(ilist,7292) and his__canprev(ihisname);
end;

function tbasicnav.cannext:boolean;
begin
result:=(ihisname<>'') and zzok(ilist,8293) and his__cannext(ihisname);
end;

function tbasicnav.prev:boolean;
var
   str1:string;
begin
result:=false;
if canprev then
   begin
   his__setactiveref(ihisname,ilist.pos,ilist.selstart);
   if his__prev(ihisname,str1,true) then
      begin
      imustfolder:=iprevnextcode+str1;
      result:=true;
      end;
   end;
end;

function tbasicnav.next:boolean;
var
   str1:string;
begin
result:=false;
if cannext then
   begin
   his__setactiveref(ihisname,ilist.pos,ilist.selstart);
   if his__next(ihisname,str1,true) then
      begin
      imustfolder:=iprevnextcode+str1;
      result:=true;
      end;
   end;
end;

procedure tbasicnav._ontimer(sender:tobject);
var
   v1,v2,int1,xnavcount,xfoldercount,xfilecount,xtotalcount:longint;
   str1:string;
   bol1,xnav,xfolders,xfiles,xmustreload:boolean;

   procedure pfilter;
   var
      int1:longint;
      str1:string;
   begin
   try
   //filter
   int1:=frcrange32(findex,0,frcmin32(fcount-1,0));
   if (int1>=0) and (int1<fcount) and (int1<=high(fcap)) and ((istyle=bnOpen) or (istyle=bnSave)) then
      begin
      //omasklist
      str1:=fmsk[int1];
      if not strmatch(str1,omasklist) then
         begin
         omasklist:=str1;
         xmustreload:=true;
         end;
      //filter.value
      if zzok(ifilter,7294) and (not strmatch(ifilter.value,fcap[int1])) then
         begin
         ifilter.value:=fcap[int1];
         //action
         if zzok(iaction,1) and iaction.visible then iaction.ext:=fext[int1];
         end;
      end;
   except;end;
   end;
begin
try
//init
xmustreload:=false;

//.imustfolder
if (imustfolder<>'') then
   begin
   bol1:=(strcopy1(imustfolder,1,1)=iprevnextcode);
   xhisadd(imustfolder,0,0,not bol1);
   if bol1 then imustfolder:=strcopy1(imustfolder,2,low__len32(imustfolder));
   if strmatch(imustfolder,'home') then ilistfolder:='' else ilistfolder:=io__asfoldernil(imustfolder);
   imustfolder:='';
   xmustreload:=true;
   end;
//.imustreload
if imustreload then
   begin
   imustreload:=false;
   xmustreload:=true;
   end;

//.itimer250
if (slowms64>itimer250) or xmustreload then//"xmustreload" added - 28jul2021 -> fixed out-of-sync list (full list showed for 0.2sec before actual list was filtered)
   begin
   //init
   if zzok(ilist,7295) then ilist.oretainpos:=oretainpos;
   if zzok(ifav,7296)  then ifav.oretainpos:=oretainpos;//10mar2021

   //filter
   pfilter;

   //mask
   if low__setstr(ilastmask,omasklist) then xmustreload:=true;
   if low__setstr(ilastemask,oemasklist) then xmustreload:=true;
   if low__setstr(ilastemask_minmax,ominmax_emasklist) then xmustreload:=true;
   //toolbars
   if zzok(ibar,7297) and ibar.visible then xoff_toolbarsync(ibar);
   if zzok(ibut,7298) and ibut.visible then xoff_toolbarsync(ibut);

   //reset
   itimer250:=slowms64+250;
   end;

//.reload
if xmustreload then
   begin
   //.listcore
   if zzok(ilist,7299) and (ilist.countx>=0) and zzok(ilistcore,7300) then
      begin
      //init
      int1:=istyle;
      xnav:=(int1=bnNav) or (int1=bnNavlist) or (int1=bnFolder) or (int1=bnFolder2) or (int1=bnOpen) or (int1=bnSave);
      xfolders:=(int1=bnNav) or (int1=bnNavlist) or (int1=bnFolder) or (int1=bnFolder2) or (int1=bnOpen) or (int1=bnSave);
      xfiles:=(int1=bnNav) or (int1=bnNavlist) or (int1=bnNamelist) or (int1=bnOpen) or (int1=bnSave) or (int1=bnFolder2);
      //get
      nav__list2(ilistcore,isortstyle,ilistfolder,omasklist,oemasklist,xnav,xfolders,xfiles,ominsize,omaxsize,ominmax_emasklist);//27sep2022, now sortable - 20feb2021
      nav__info(ilistcore,xnavcount,xfoldercount,xfilecount,xtotalcount);
      inavcount     :=xnavcount;
      ifoldercount  :=xfoldercount;
      ifilecount    :=xfilecount;
      itotalcount   :=xtotalcount;
      ilist.countx  :=xtotalcount;
      ilist.onumberfrom:=low__aorb(-1,inavcount+ifoldercount,onumber);//20mar2022
      ilist.paintnow;
      //position
      if low__setstr(ireloadref,xenhancednames(ilistfolder)) then
         begin
         v1:=0;
         v2:=0;
         if (ihisname<>'') then
            begin
            his__active2(ihisname,str1,v1,v2);
            end;
         ilist.pos:=v1;
         ilist.setsel(v2,1);
         end;
      //.folderID
      if low__setstr(ifolderidREF,ilistfolder) then low__iroll(ifolderid,1);//27sep2022
      //.reloadID
      low__iroll(ireloadid,1);//20aug2024
      end;
   //.favcore
   loadfav;
   end;

//.mustname
if (imustname<>'') then
   begin
   //init
   str1:=imustname;
   imustname:='';
   //filter -> update filter immediately as this affects how "iname.value" is set via "xfiltername()"
   pfilter;
   //get
   if ((istyle=bnOpen) or (istyle=bnSave) or ofindname) then
      begin
      if zzok(iname,7301) then iname.value:=xfiltername(str1,false);
      if zzok(ilist,7302) and ilist.xfindbycaption(str1,int1) then
         begin
         ilist.setsel(int1,1);
         ilist.pos:=int1;
         end;
      end;
   end;

//.ilastpreview
if (ilastpreview<>(canpreview and preview)) then
   begin
   ilastpreview:=(canpreview and preview);
   if (ipreviewlabel<>nil) then ipreviewlabel.visible:=ilastpreview;
   if (ipreviewbox<>nil)   then ipreviewbox.visible:=ilastpreview;
   gui.fullalignpaint;
   end;

//.preview - 20jul2024: included folder2 support
if (slowms64>itimer100) then
   begin
   if (ipreviewbox<>nil) and (canpreview and preview) and ipreviewbox.visible then
      begin
      //must be a file for us to preview it - 22nov2024
      //was: if (valueinlistStyle=nltFile) then str1:=valueinlist else str1:='';
      if (not xvalueinlist(str1,int1)) or (int1<>nltFile) then str1:='';

      //get
      if not strmatch(ilastpreviewfile,str1) then
         begin
         ilastpreviewfile:=str1;
         ipreviewbox.loadfromfile(ilastpreviewfile,true);
         end;
      end
   else if (ipreviewbox<>nil) and ((not canpreview) or (not preview)) and (ilastpreviewfile<>'') then//20jul2024: fixed
      begin
      ilastpreviewfile:='';
      if (ipreviewbox<>nil) then ipreviewbox.loadfromfile('',true);//reduce memory
      end;

   //previewlabel
   if (ipreviewlabel<>nil) and (ipreviewbox<>nil) and canpreview and preview then
      begin
      str1:='Preview'+insstr(#32+ipreviewbox.infostr,ipreviewbox.infostr<>'');//11dec2024
      if (ipreviewlabel.caption<>str1) then ipreviewlabel.caption:=str1;
      end;

   //reset
   itimer100:=slowms64+100;
   end;
except;end;
end;

procedure tbasicnav._onpaint(sender:tobject);
begin
//Does not need to paint anything as the child control "ilist" does all the necessary painting
//was: xparentcorners;
end;

procedure tbasicnav.loadfav;
var
   a:tstr8;
   p:longint;
   e:string;
begin

//defaults
a           :=nil;

try

if zzok(ifav,7303) and zzok(ifavcore,7304) then
   begin

   //get
   a                  :=str__new8;

   io__fromfile(low__platfolder('settings')+'fav.txt',@a,e);

   ifavcore.text      :=low__limitlines(low__remdup2(a.text,true,false,false),ifavlimit);//11sep2021

   //.ifavteps
   if (ifavcore.count>=1) then
      begin

      ifavteps.atleast(ifavcore.count);

      for p:=0 to (ifavcore.count-1) do
      begin

      ifavteps.value[p]:=tep__folderimage20(io__readportablefilename(ifavcore.value[p]),true);

      end;//p

      end;

   //sync
   ifav.countx        :=ifavcore.count;
   ifav.paintnow;

   end;

except;end;

//free
str__free(@a);

end;

function tbasicnav.savefav(xdata:tstr8):boolean;
var
   e:string;
begin
result:=io__tofile(low__platfolder('settings')+'fav.txt',@xdata,e);
end;

procedure tbasicnav.addfav(xfolder:string);
var//Note: xfolder can be a filename, so we must determine which it is so we can extract the folder - 10mar2021
   //Note: Assumes xfolder is a filename if there is a DOT after the last slash, else it's assumed to be a folder - 10mar2021
   a,b:tstr8;
   str1,e:string;
   p:longint;
begin
try
//defaults
a:=nil;
b:=nil;
//check
if (xfolder='') then exit;
//init
for p:=low__len32(xfolder) downto 1 do
begin
if (strcopy1(xfolder,p,1)='/') or (strcopy1(xfolder,p,1)='\') then break
else if (strcopy1(xfolder,p,1)='.') then
   begin
   xfolder:=io__extractfilepath(xfolder);
   break;
   end;
end;//p
xfolder:=io__asfoldernil(xfolder);
//get
if zzok(ifav,7305) and zzok(ifavcore,7306) and (xfolder<>'') then
   begin
   xfolder:=io__makeportablefilename(xfolder);//make folder portable!!! - 11sep2021
   a:=str__new8;
   b:=str__new8;
   io__fromfile(low__platfolder('settings')+'fav.txt',@b,e);
   str1:=b.text;
   a.text:=low__limitlines(low__remdup2(xfolder+insstr(rcode,str1<>'')+str1,true,false,false),ifavlimit);
   savefav(a);
   loadfav;
   end;
except;end;
try
str__free(@a);
str__free(@b);
except;end;
end;


//## tbasicjump ################################################################
constructor tbasicjump.create(xparent:tobject;xcaption:string);
begin
create2(xparent,true,xcaption);
end;

constructor tbasicjump.create2(xparent:tobject;xstart:boolean;xcaption:string);
begin

//self
if classnameis('tbasicjump') then track__inc(satJump,1);
inherited create2(xparent,false);

//vars
ifont          :=res__newfont;//03mar2026
olarge         :=false;
oscaleh        :=1.0;//13dec2025
oms            :=true;
ispeed         :=100;
istatus        :=0;
iref           :=olarge;
ilastmousex    :=min32;
inewref        :=0;
ihoveref       :=slowms64;
itimer250      :=slowms64;
ipainttimer    :=slowms64;
ipaintref      :='';
fonclick       :=nil;
imustpaint     :=false;
ipos           :=0;
ipert          :=0;
ilen           :=0;
ihoverpos      :=0;
ihoverpert     :=0;
ilasthoverpos  :=0;
bordersize     :=0;//19jan2025

//start
if xstart then start;

end;

destructor tbasicjump.destroy;
begin
try

//disconnect events
fonclick:=nil;

//controls
res__del(ifont);

//destroy
inherited destroy;
if classnameis('tbasicjump') then track__inc(satJump,-1);

except;end;
end;

procedure tbasicjump.setflashval(x:double);
begin
x:=frcrangeD64(x,0,1);

if (x<>iflashval) then
   begin

   iflashval:=x;
   paintnow;

   end;

end;

procedure tbasicjump.setflashval9(x:double);
begin
x:=frcrangeD64(x,0,1);

if (x<>iflashval9) then
   begin

   iflashval9:=x;
   paintnow;

   end;

end;

procedure tbasicjump.setpower(x:double);
begin
x:=frcrangeD64(x,0,1);

if (x<>ipower) then
   begin

   ipower:=x;
   paintnow;

   end;

end;

procedure tbasicjump.setstatus(x:longint);
begin
if low__setint(istatus,frcrange32(x,0,2)) then paintnow;
end;

function tbasicjump.getalignheight(xclientwidth:longint):longint;//13dec2025, 11dec2025, 05sep2025
begin

result:=frcmin32( round( oscaleh * 65 * viscale * low__aorbD64(0.8,1.3,olarge) ), 1);

end;

procedure tbasicjump.setparams(xpos,xlen,xspeed:longint);//in milliseconds
begin

//range
xlen     :=frcrange32(xlen,0,max32);
xpos     :=frcrange32(xpos,0,frcmin32(xlen-1,0));
xspeed   :=frcrange32(xspeed,10,1000);

//get
if (xpos<>ipos) or (ilen<>xlen) or (ispeed<>xspeed) then
   begin

   ilen     :=xlen;
   ipos     :=xpos;
   ispeed   :=xspeed;

   ipert:=low__makepertD0(xpos,xlen);

   if focused then xsyncpos;//required when FAST changes are required such when used as a jumpto panel for Music Player - 20feb2022

   ilasthoverpos:=ihoverpos;
   imustpaint:=true;

   end;

end;

procedure tbasicjump._ontimer(sender:tobject);
begin
try

//inewpos
if (inewref<>0) and (slowms64>=inewref) then
   begin
   gui.xfireevent(self,fonclick);//supports closelock - 03apr2021
   inewref:=0;
   end;

//hoverpos
if low__setint(ilasthoverpos,ihoverpos) or (focused and gui.mousedown) then
   begin
   ihoveref:=frcmin64(slowms64+1000,ihoveref);
   imustpaint:=true;
   end;

//timer250;
if (slowms64>=itimer250) then
   begin

   if low__setstr(ipaintref,bnc(ihoveref>=slowms64)) then imustpaint:=true;
   if low__setbol(iref,olarge) then
      begin
      imustpaint:=false;
      gui.fullalignpaint;
      end;

   //reset
   itimer250:=slowms64+250;
   end;

//paint
if (slowms64>=ipainttimer) then
   begin

   if imustpaint then
      begin

      imustpaint:=false;
      paintnow;

      end;

   //reset
   ipainttimer:=slowms64+50;//~20fps

   end;

except;end;
end;

procedure tbasicjump._onpaint(sender:tobject);//24oct2025: optimised coloring viewing for dark and light color schemes, 16sep2025: improved color variation for light backgrounds, 13sep2025, 05sep2025, 21aug2025
var
   s:tclientinfo;
   ba,da:twinrect;

   dback,dbeat:tpoint;
   v1,v2,spos,slen,shoverpos,int1,vmid,vpos,fheight,jw,xhoverpos,xpos,xlen,dx,tw,th:longint;
   str1:string;
   xdark,xhoverok:boolean;

   procedure xdrawbar(da:twinrect);//07jan2026, 13sep2025
   var
      v:longint;
   begin

   v:=int__splice24(0.90,dback.y,s.font);
   fshadeArea2( da, dback.x, v, v, dback.x, 50, 255, false);

   end;

begin
try

//init
infovars(s);

xhoverpos  :=ihoverpos;
xpos       :=ipos;
xlen       :=frcmin32(ilen,1);
jw         :=frcmin32(s.ci.right-s.ci.left+1-(2*s.bs),1);
res__font( ifont ).setparams( s.info.fontname ,-frcmin32(round32(s.ch*0.7),5) ,true ,false ,false );//03mar2026
fheight    :=resfont__height( ifont );

xhoverok   :=(ihoveref>=slowms64);
xdark      :=(int__lum(s.back)<100);


//background shade color
dback.x    :=int__splice24(0.12,s.back,col_black24);
dback.y    :=int__splice24(0.12,s.back,col_white24);


//volume-adjusted shade color
case xdark of
true:begin

   dbeat.x    :=int__splice24(1.5*iflashval*ipower*(frcmin32( gui.backgroundmanager.strength,50) / 50 ), dback.x, s.colhover2.x );
   dbeat.y    :=int__splice24(1.5*iflashval*ipower*(frcmin32( gui.backgroundmanager.strength,50) / 50 ), dback.y, s.colhover2.y );

   end;
else begin

   dbeat.x    :=int__splice24(1.2*iflashval*ipower*(frcmin32( gui.backgroundmanager.strength,50) / 50 ), dback.x, s.info.hover );
   dbeat.y    :=int__splice24(0.2*iflashval*ipower*(frcmin32( gui.backgroundmanager.strength,50) / 50 ), dback.y, s.info.hover );

   end;
end;//case


//speed adjust values - 07sep2025
slen       :=frcmin32( trunc( xlen*(100/ispeed)) ,1);
spos       :=trunc( (xpos/xlen)*slen );
shoverpos  :=trunc( (ihoverpos/xlen)*slen );


//beat bar
vpos      :=round( frcrangeD64(0.35+(1-iflashval9),0,1) * (s.cs.right-s.cs.left+1) * 0.5 );
vmid      :=s.cs.left + ((s.cs.right-s.cs.left+1) div 2);

ba.left   :=frcrange32(vmid-vpos,s.cs.left,s.cs.right);
ba.right  :=frcrange32(vmid+vpos,s.cs.left,s.cs.right);
ba.top    :=s.cs.top;
ba.bottom :=s.cs.bottom;
fshadeArea2( ba, dbeat.x,dbeat.y,dbeat.y,dbeat.x, 50, 255, false);


//cls unused area
if (ba.left>s.cs.left)    then fshadeArea2( area__make(s.cs.left,s.cs.top,ba.left,s.cs.bottom),   dback.x, dback.y, dback.y, dback.x, 50, 255, false);
if (ba.right<s.cs.right)  then fshadeArea2( area__make(ba.right,s.cs.top,s.cs.right,s.cs.bottom), dback.x, dback.y, dback.y, dback.x, 50, 255, false);

//status
if (istatus>=1) and (not xhoverok) then
   begin

   //get
   case istatus of
   1:if (xlen<=1) then str1:='' else str1:=low__uptime(spos+1,(slen>=3600000),(slen>=60000),(slen>=1000),true,oms,#32);
   2:if (xlen<=1) then str1:='' else str1:=low__uptime(slen-(spos+1),(slen>=3600000),(slen>=60000),(slen>=1000),true,oms,#32);
   else str1:='';
   end;//case

   if (str1<>'') then
      begin

      tw:=fast__textwidth('',str1,ifont);
      ftext(dback.y,s.ci,(s.ci.right-s.ci.left+1-tw) div 2,(s.ci.bottom-s.ci.top+1-fheight) div 2,low__aorb(s.font,s.hover2,xhoverok),'',str1,ifont ,true);

      end;

   end;


//xpos
dx         :=s.ci.left+round((xpos/xlen)*jw);
da.top     :=s.ci.top;
da.bottom  :=s.ci.bottom;
da.left    :=dx;
da.right   :=da.left-1+(low__aorb(3,5,olarge)*vizoom);
xdrawbar(da);


//xhoverpos
if xhoverok then
   begin
   dx         :=s.ci.left+round((xhoverpos/xlen)*jw);
   da.top     :=s.ci.top;
   da.bottom  :=s.ci.bottom;
   da.left    :=dx;
   da.right   :=da.left-1+(low__aorb(3,5,olarge)*vizoom);
   xdrawbar(da);

   //caption
   case istatus of
   2   :int1:=slen-(shoverpos+1);
   else int1:=shoverpos+1;
   end;//case

   str1:=#32#32+low__uptime(int1,(slen>=3600000),(slen>=60000),(slen>=1000),true,oms,#32);

   tw:=fast__textwidth('',str1,ifont);
   th:=resfont__height(ifont);

   case (dx<=(s.cw div 2)) of
   true:ftext(s.back,s.ci,dx+10,s.ci.top+((s.ci.bottom-s.ci.top+1-th) div 2),s.font,'',str1,ifont ,true);
   else ftext(s.back,s.ci,dx-tw-10,s.ci.top+((s.ci.bottom-s.ci.top+1-th) div 2),s.font,'',str1,ifont ,true);
   end;//case

   end;


//border
xframeSimple( s );

except;end;
end;

procedure tbasicjump.moveby(x:longint);
var
   xpos:longint;
begin
try
xpos:=low__aorb(ipos,ihoverpos,inewref<>0);
jumpto(xpos+x);
inewref:=0;
//ilastmousex:=mousex;
xsyncpos;
gui.xfireevent(self,fonclick);//supports closelock - 03apr2021
except;end;
end;

procedure tbasicjump.jumpto(x:longint);
begin
try
ilastmousex:=min32;//disable
ihoverpos:=frcrange32(x,0,frcmin32(ilen-1,0));
ihoverpert:=low__makepertD0(frcrange32(x,0,frcmin32(ilen-1,0)),ilen);//06mar2022
inewref:=slowms64+500;
ihoveref:=slowms64+2000;
paintnow;
except;end;
end;

function tbasicjump._onnotify(sender:tobject):boolean;
var
   xpos:longint;

   procedure xsetpos(x:longint);
   begin
   jumpto(x);
   end;
begin
//handled
result:=true;

try
//key
if (gui.key<>aknone) then
   begin
   xpos:=low__aorb(ipos,ihoverpos,inewref<>0);
   case gui.key of
   akhome:begin
      if enabled then xsetpos(0);
      end;
   akend:begin
      if enabled then xsetpos(len);
      end;
   akleft,akup:begin
      if enabled then xsetpos(xpos-500*low__aorb(1,4,gui.shiftok));
      end;
   akright,akdown:begin
      if enabled then xsetpos(xpos+500*low__aorb(1,4,gui.shiftok));
      end;
   akprev:begin
      if enabled then xsetpos(xpos-10000);
      end;
   aknext:begin
      if enabled then xsetpos(xpos+10000);
      end;
   end;//case
   end;

//mouse -> special note: "mousemovingfine" allows for 2px mouse wobble with no FALSE ON event - 27feb2022
if gui.mousemovingfine then
   begin
   ilastmousex:=mousex;
   xsyncpos;
   end;
if gui.mousedownstroke or gui.mouseupstroke or (gui.mousedown and gui.mousemovingfine) then
   begin
   inewref:=0;
   ilastmousex:=mousex;
   xsyncpos;
   gui.xfireevent(self,fonclick);//supports closelock - 03apr2021
   end;
except;end;
end;

procedure tbasicjump.xsyncpos;//20feb2022
begin
if (ilastmousex>min32) then
   begin
   ihoverpos:=frcrange32(round((ilastmousex/clientwidth)*ilen),0,frcmin32(ilen-1,0));//10mar2021
   ihoverpert:=low__makepertD0(ilastmousex,clientwidth);//06mar2022
   end;
end;


//## tbasicedit ################################################################
constructor tbasicedit.create(xparent:tobject;xcaption:string);
begin
create2(xparent,true,xcaption);
end;

constructor tbasicedit.create2(xparent:tobject;xstart:boolean;xcaption:string);
begin

//self
if classnameis('tbasicedit') then track__inc(satEdit,1);
inherited create2(xparent,false);

//vars
oshowborder           :=true;
ifont                 :=res_nil;//optional
ocmd2                 :='';//19apr2025
orightbut_narrowfocus :=false;
iscale                :=1;
odel_clearstext       :=false;
osysfind_textsync     :=false;
ohardleft             :=false;
omoreoptions          :=true;
ocanshowmenu          :=true;
idropstatic           :=false;
olimit                :=max32;
oreadonly             :=false;
opassword             :=false;
oborder2              :=false;
iundodata             :='';
iundoref              :=0;//0=not set, 1=adding, 2=deleting, 3=swapping
iundodataOK           :=false;
ireveal               :=false;
iprogress             :=0;
ibutarea1             :=area__make(0,0,-1,-1);
ibutarea2             :=area__make(0,0,-1,-1);
itep                  :=tepnone;
itep2                 :=tepnone;
itep2b                :=tepnone;
iimgw                 :=0;
iimgw2                :=0;
iimgh                 :=0;
iimgh2                :=0;
iidleref              :=slowms64;
itimer250             :=slowms64;
itimerslow            :=slowms64;
iflash                :=false;
inormal               :=true;
icaption              :=xcaption;
ititle                :='';
ivalue                :='';
ibordersize           :=1;
iref                  :='';
fonclick2             :=nil;
fonclick1             :=nil;
fonchange             :=nil;//13mar2022
onshowpass            :=nil;//19jun2022

//defaults
clientheight          :=20;
xfindsync;

//start
if xstart then start;

end;

destructor tbasicedit.destroy;
begin
try

//disconnect events
fonclick2             :=nil;
fonclick1             :=nil;

//controls
res__del(ifont);

//destroy
inherited destroy;
if classnameis('tbasicedit') then track__inc(satEdit,-1);

except;end;
end;

procedure tbasicedit.setscale(x:single);
begin

if (x<1) then x:=1 else if (x>5) then x:=5;
iscale:=x;

end;

procedure tbasicedit.makefind;
begin

osysfind_textsync  :=true;
omoreoptions       :=true;
ocanshowmenu       :=true;
idropstatic        :=false;
oreadonly          :=false;
opassword          :=false;
oborder2           :=false;
tep                :=tepnone;
tep2               :=tepnone;

xfindsync;
paintnow;

end;

procedure tbasicedit.xfindsync;
begin
if osysfind_textsync then sysfind_text:=ivalue;
end;

function tbasicedit.canundo:boolean;
begin
result:=(not oreadonly) and iundodataOK;
end;

function tbasicedit.undo:boolean;
var
   x:string;
begin
//defaults
result:=false;

try
//check
if not canundo then exit;
//get
x:=value;
if (olimit>=1) then value:=strcopy1(iundodata,1,olimit);//enforce limit - 19jun2022
iundodata:=x;
iundoref:=0;
except;end;
end;

function tbasicedit.undoclear:boolean;
begin
result:=true;
iundodata:='';
iundodataOK:=false;
end;

function tbasicedit.xundoautofill(xref:longint):boolean;//pass-thru proc
begin//xref: 0=not set, 1=adding, 2=deleting, 3=swapping (paste, insert, replace etc)
result:=true;//always TRUE - 18jun2022

try
//range
xref:=frcrange32(xref,0,4);
//get
if (xref<>iundoref) then
   begin
   iundoref:=xref;
   xundofill;
   end;
except;end;
end;

procedure tbasicedit.xundofill;
begin
iundodata:=ivalue;
iundodataOK:=true;
end;

procedure tbasicedit.settitle(x:string);
begin
try
if ((x='') and (ititle<>'')) or ((x<>'') and (ititle='')) then
   begin
   ititle:=x;
   alignpaintallnow;
   end
else if low__setstr(ititle,x) then paintnow;
except;end;
end;

function tbasicedit.canclearpassword:boolean;
begin
result:=(not oreadonly) and opassword and ((ivalue<>'') or iundodataOK);
end;

function tbasicedit.clearpassword:boolean;
begin
result:=true;
if canclearpassword and gui.popquery('Clear password?') then
   begin
   value:='';
   undoclear;
   end;
end;

function tbasicedit.canpastepassword:boolean;
begin
result:=(not oreadonly) and opassword and clip__canpastetext;
end;

function tbasicedit.pastepassword:boolean;
var
   str1:string;
begin
//check
result:=false;
//get
if canpastepassword and clip__pastetext(str1) then
   begin
   xundofill;
   value:=str1;
   result:=true;
   end;
end;

function tbasicedit.canvisit(var xurl:string):boolean;
   function m(const s:string):boolean;
   begin
   result:=strmatch(strcopy1(ivalue,1,low__len32(s)),s);
   end;
begin
if m('https://') or m('http://') then
   begin
   result:=true;
   xurl:=ivalue;
   end
else
   begin
   result:=false;
   xurl:='';
   end;
end;

procedure tbasicedit.showmenuFill(xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
var
   xcanedit,xcancopy,xcanpaste,xreadonly:boolean;
   str1:string;
begin
try
//check
if zznil(xmenudata,2352) then exit;
xmenuname:='edit.1';
//checkers

//init
xreadonly:=oreadonly;
xcanedit:=(ivalue<>'') and (not xreadonly);
xcancopy:=clip__cancopytext and (ivalue<>'');
xcanpaste:=(not xreadonly) and clip__canpastetext;

//get
if canvisit(str1) then low__menuitem2(xmenudata,tepGo20,'Visit Url','','edit.visit',100,aknone,true);//19apr2025

if not xreadonly then low__menuitem2(xmenudata,tepundo20,'Undo','Undo last changes','edit.undo',100,akctrlU,canundo);
if not xreadonly then low__menuitem2(xmenudata,tepcut20,'Cut','Cut text to Clipboard','edit.cuttxt',100,akctrlT,xcancopy and (not xreadonly));
low__menuitem2(xmenudata,tepcopy20,'Copy','Copy text to Clipboard','edit.copytxt',100,akctrlC,xcancopy);
if not xreadonly then
   begin
   low__menuitem2(xmenudata,teppaste20,'Paste','Replace with text from Clipboard','edit.paste',100,akctrlP,xcanpaste and (not xreadonly));//20may2025
   low__menuitem2(xmenudata,teppaste20,'Paste After','Paste text from Clipboard after current text','edit.pasteafter',100,akNone,xcanpaste and (not xreadonly));
   if not opassword then low__menuitem2(xmenudata,tepclose20,'Delete All','Clear all text','edit.clear',100,akctrlD,xcanedit);
   end;
//.additional menu - 31mar2021
if opassword then
   begin
   low__menusep(xmenudata);
   low__menuitem2(xmenudata,tep__yes(ireveal),ntranslate('Show Password'),'Ticked: Show password characters','edit.togglepass',100,aknone,true);
   low__menuitem2(xmenudata,tepClose20,ntranslate('Clear Password'),'Remove password and clear undo','edit.clearpass',100,aknone,xcanedit or iundodataOK);
   end;
if (not xreadonly) and omoreoptions then
   begin
   low__menusep(xmenudata);
   low__menuitem2(xmenudata,tepUpper20,ntranslate('Upper Case'),'Make text upper case - ABCD','edit.upper',100,akctrlR,xcanedit);
   low__menuitem2(xmenudata,tepLower20,ntranslate('Lower Case'),'Make text lower case - abcd','edit.lower',100,akctrlL,xcanedit);
   low__menuitem2(xmenudata,tepName20,ntranslate('Name Case'),'Make text name case - Abcd','edit.name',100,akctrlN,xcanedit);
   low__menuitem2(xmenudata,tepNew20,ntranslate('Remove html brackets'),'Remove html brackets "<" and ">" from text','edit.rem<>',100,aknone,xcanedit);
   low__menuitem2(xmenudata,tepNew20,ntranslate('Remove Spaces'),'Remove spaces from text','edit.remspace',100,aknone,xcanedit);
   low__menuitem2(xmenudata,tepNew20,ntranslate('Remove Tabs'),'Remove tabs from text','edit.remtab',100,aknone,xcanedit);
   low__menuitem2(xmenudata,tepNew20,ntranslate('Remove Binary'),'Remove binary characters (ASCII #0..#31) from text','edit.rembin',100,aknone,xcanedit);
   end;
except;end;
end;

function tbasicedit.showmenuClick(sender:tobject;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
label
   skipend;
var
   v,str1,e:string;

   function xcanpaste:boolean;
   begin
   result:=(not oreadonly) and clip__canpastetext;
   end;

   function xcancopy:boolean;
   begin
   result:=(ivalue<>'');
   end;

   function m(const s:string):boolean;
   begin
   result:=strmatch(strcopy1(xcode2,1,low__len32(s)),s);
   if result then v:=strcopy1(xcode2,low__len32(s)+1,low__len32(xcode2));
   end;
begin
//handled
result:=true;

try
e:='';
v:='';

//information
//.cut
if (xcode2='edit.cuttxt') then
   begin
   if xcancopy then
      begin
      if (not clip__copytext(ivalue)) and gec__taskfailed(e) then goto skipend;
      xundoautofill(2);
      value:='';
      end;
   end
//.undo
else if (xcode2='edit.undo') then undo
//.copy
else if (xcode2='edit.copytxt') then
   begin
   if xcancopy and (not clip__copytext(ivalue)) and gec__taskfailed(e) then goto skipend;
   end
//.paste
else if (xcode2='edit.paste') then
   begin
   if xcanpaste then
      begin
      if (not clip__pastetext(str1)) and gec__taskfailed(e) then goto skipend;
      xundofill;
      value:=str1;
      end;
   end
//.pasteafter
else if (xcode2='edit.pasteafter') then
   begin
   if xcanpaste then
      begin
      if (not clip__pastetext(str1)) and gec__taskfailed(e) then goto skipend;
      if (str1<>'') then
         begin
         xundoautofill(1);
         value:=value+str1;
         end;
      end;
   end
//.clear
else if (xcode2='edit.clear') then
   begin
   if (not oreadonly) and (value<>'') then
      begin
      xundofill;
      value:='';
      end;
   end
//.optional menu items
else if (xcode2='edit.clearpass') then clearpassword
else if (xcode2='edit.flush') then
   begin
   if not oreadonly then
      begin
      value:='';
      undoclear;
      end;
   end
else if (xcode2='edit.togglepass') then
   begin
   if not oreadonly then
      begin
      ireveal:=not ireveal;//19jun2022
      xshowpass;
      end;
   end
else if (xcode2='edit.showpass') then
   begin
   if not oreadonly then
      begin
      ireveal:=true;
      xshowpass;
      end;
   end
else if (xcode2='edit.hidepass') then
   begin
   if not oreadonly then
      begin
      ireveal:=false;
      xshowpass;
      end;
   end
else if (xcode2='edit.delete') then
   begin
   if (not oreadonly) and (ivalue<>'') and xundoautofill(2) then value:='';
   end
else if (xcode2='edit.upper') then
   begin
   if (not oreadonly) and (ivalue<>'') and xundoautofill(4) then value:=strup(value);
   end
else if (xcode2='edit.lower') then
   begin
   if (not oreadonly) and (ivalue<>'') and xundoautofill(4) then value:=strlow(value);
   end
else if (xcode2='edit.name') then
   begin
   if (not oreadonly) and (ivalue<>'') and xundoautofill(4) then value:=low__asname(value);
   end
else if (xcode2='edit.remspace') then
   begin
   if (not oreadonly) and (ivalue<>'') and xundoautofill(4) then value:=low__remcharb(value,#32)
   end
else if (xcode2='edit.remtab') then
   begin
   if (not oreadonly) and (ivalue<>'') and xundoautofill(4) then value:=low__remcharb(value,#9);
   end
else if (xcode2='edit.rem<>') then
   begin
   if (not oreadonly) and (ivalue<>'') and xundoautofill(4) then value:=low__remcharb(low__remcharb(value,'<'),'>');
   end
else if (xcode2='edit.rembin') then
   begin
   if (not oreadonly) and (ivalue<>'') and xundoautofill(4) then value:=low__rembinaryb(value);
   end
else if m('edit.visit') then
   begin
   if canvisit(v) then runlow(v,'');
   end

//not handled
else result:=false;

skipend:
except;end;
try;if (e<>'') then gui.poperror('',e);except;end;
end;

procedure tbasicedit.makeedit;
begin
ohardleft:=false;
omoreoptions:=true;
ocanshowmenu:=true;
idropstatic:=false;
oreadonly:=false;
opassword:=false;
oborder2:=false;
tep2:=tepnone;
paintnow;
end;

procedure tbasicedit.makepass;
begin
ohardleft:=false;
omoreoptions:=true;
ocanshowmenu:=true;
idropstatic:=false;
oreadonly:=false;
opassword:=true;
oborder2:=true;//false;
tep2:=tepRefresh20;
tep2b:=tepRefresh20;
buthelp2:='Toggle password display';
paintnow;
end;

procedure tbasicedit.makedrop;
begin
ohardleft:=false;
omoreoptions:=false;
ocanshowmenu:=true;
idropstatic:=false;
oreadonly:=false;
opassword:=false;
oborder2:=true;
tep2:=tepDown;
buthelp2:='Show list';
paintnow;
end;

procedure tbasicedit.makedropstatic;
begin
ohardleft:=true;//27jul2024
omoreoptions:=false;
ocanshowmenu:=false;
idropstatic:=true;
oreadonly:=true;
opassword:=false;
oborder2:=true;
tep2:=tepDown;
buthelp2:='Show list';
paintnow;
end;

procedure tbasicedit.makeprogress;
begin
ohardleft:=false;
omoreoptions:=false;
ocanshowmenu:=false;
idropstatic:=false;
oreadonly:=true;
opassword:=false;
oborder2:=false;
tep2:=tepnone;
paintnow;
end;

procedure tbasicedit.settep(x:longint);
begin

if low__setint(itep,x) then
   begin
   tep__info(itep,iimgw,iimgh);
   paintnow;
   end;

end;

procedure tbasicedit.settep2(x:longint);
begin

if low__setint(itep2,x) then
   begin
   tep__info(itep2,iimgw2,iimgh2);
   paintnow;
   end;

end;

procedure tbasicedit.settep2b(x:longint);
begin
itep2b:=x;
end;

procedure tbasicedit.setvalue(x:string);
begin
try
//filter
x:=low__firstnbl2(x);
//.enforce length limit
if (olimit>=1) then x:=strcopy1(x,1,olimit);
//get
if low__setstr(ivalue,x) then
   begin
   xnotidle;
   paintnow;
   xchanged;
   end;
//.findsync
xfindsync;
except;end;
end;

procedure tbasicedit.xchanged;
begin
if assigned(fonchange) then fonchange(self);
end;

procedure tbasicedit.xshowpass;
begin
if assigned(fonshowpass) then fonshowpass(self);
end;

procedure tbasicedit.setprogress(x:single);
begin
if (x<0) then x:=0 else if (x>100) then x:=100;
if (x<>iprogress) then
   begin
   iprogress:=x;
   paintnow;
   end;
end;

function tbasicedit.xlineheight:longint;
begin

case (ititle<>'') of
true:result:=frcmin32( trunc(iscale*vilineheight20) ,vitepheight20 );//multi-line (title+edit) => smaller lineheight
else result:=frcmin32( trunc(iscale*vilineheight30) ,vitepheight20 );//single-line (edit only) => larger lineheight
end;//case

end;

function tbasicedit.getalignheight(xclientwidth:longint):longint;//11dec2025, 03mar2022
begin

result:=xlineheight*low__aorb(1,2,ititle<>'');

end;

procedure tbasicedit._ontimer(sender:tobject);
begin
try
if (slowms64>itimer250) then
   begin
   xcheckref;
   itimer250:=slowms64+250;
   end;
if (slowms64>itimerslow) then
   begin
   iflash:=not iflash;
   xcheckref;
   itimerslow:=slowms64+600;
   end;
except;end;
end;

procedure tbasicedit._onpaint(sender:tobject);//28nov2025
label
   skiptext;
var
   s:tclientinfo;
   pa,ta:twinrect;
   zw,ty,dlineheight,fn,fnH,shiftby,xpad0,xpad1,xpad2,xtep,xtep2,xtep2b,p,xw,xh,int1,int2,int3,tw,dx2,dx:longint;
   xmousedown,bol1,ashowcursor:boolean;
   xvalue,xcap,xtitle,z:string;
   xprogress:single;
begin
try

//init
infovars(s);

xtitle        :=ititle;
dlineheight   :=xlineheight;
xpad0         :=2*s.zoom;//left image margin AND cursor-padding
xpad1         :=5*s.zoom;
xpad2         :=5*s.zoom;
shiftby       :=2*s.zoom;//space to shift down and to right when "down" or "marked"

fn            :=s.Rfn;
fnH           :=s.fnH;

if (iscale<>1) then
   begin

   if (ifont=res_nil) then ifont:=res__newfont;

   fn         :=ifont;

   res__font( ifont ).setparams( s.info.fontname ,-frcmin32(round32(fnH*iscale),5) ,true ,false ,false );

   fnH        :=resfont__height(fn);

   end
else ifont:=res__del(ifont);//free font

ashowcursor   :=xshowcursor;
xmousedown    :=gui.mousedown and focused;//01aug2024: added "focused"
xprogress     :=iprogress;
xtep          :=itep;
xtep2         :=itep2;
xtep2b        :=itep2b;//14jun2022
xvalue        :=ivalue;
ty            :=s.ch-s.bs-xlineheight+((xlineheight-fnH) div 2);

//inputbased colorising - 20apr2025
if oinputcolorise.use then
   begin

   s.back:=inputcolorise__backcolor(oinputcolorise,0.1,low__len32(xvalue),s.back);

   end;

//.reveal password mode
if opassword and (xvalue<>'') then
   begin

   if (xtep2<>tepnone) then bol1:=(not ireveal) else bol1:=(not (gui.mousedown and gui.mouseleft and focused));

   if bol1 then
      begin

      for p:=0 to (low__len32(xvalue)-1) do xvalue[p+stroffset]:='*';

      end;

   end;

xcap          :=icaption;
ta            :=area__make(s.bs,s.bs,s.cw-1-s.bs,s.ch-1-s.bs);//start out using entire area, and gradually reduce to exact dimensions

//cls
ffillArea(s.cs,s.back,false);

//image - left
dx:=s.bs+xpad0;

if (xtep<>tepnone) then
   begin

   tep__info(xtep,xw,xh);

   //was: if (xprogress>=1) then lds2(area__make(ta.left,ta.top,dx+xw+xpad2,ta.bottom),s.hover,clnone,clnone,0,'h12',false);
   if (xprogress>=1) then fshadeArea(area__make(ta.left,ta.top,dx+xw+xpad2,ta.bottom),s.hover,s.hover,false);

   ftep(xtep,dx,((s.ch-xh) div 2),s.font,s.e);

   ibutarea1:=area__make(s.bs,0,xw+xpad2,s.ch-1);

   inc(dx,xw+xpad2);

   end
else ibutarea1:=area__make(0,0,-1,-1);

//image2 - right
if oborder2 then int3:=low__instouch(xpad1,vitouchsize20) else int3:=0;

dx2:=s.cw-1-frcmin32(s.bs,0)-low__insint(xpad1,int3<=0);

if (xtep2<>tepnone) then
   begin

   //Special Note: Force fit the button snug when zoom=1, else space it out from border when zoom>=2 - 19mar2021
   tep__info(xtep2,xw,xh);

   zw:=scale__px0(xw);

   dec(dx2,zw-1+(2*int3));

   ibutarea2:=area__make(
    dx2,
    s.ch-s.bs-xlineheight,
    dx2+int3+zw-1+int3+low__insint(1,s.zoom<=1),
    s.ch-1-s.bs+low__insint(1,s.zoom<=1)
    );

   if (int3>=1) and low__xyinarea(mousex,mousey,ibutarea2) then ffillArea(ibutarea2,s.hover,s.r);

   //note: dropdown list uses "orightbut_narrowfocus=false" - 09mar2025
   if orightbut_narrowfocus then bol1:=xmousedown and low__xyinarea(mousex,mousey,ibutarea2) else bol1:=xmousedown;

   ftep( low__aorb(xtep2,xtep2b,ireveal and (xtep2b<>tepNone)), ibutarea2.left+((ibutarea2.right-ibutarea2.left+1-xw) div 2)+low__insint(shiftby,bol1),low__insint(shiftby,bol1)+ibutarea2.top+((ibutarea2.bottom-ibutarea2.top+1-xh) div 2),s.font,s.e);

   dec(dx2,xpad2);

   end
else ibutarea2:=area__make(0,0,-1,-1);

//text init
ta.left       :=dx;
ta.right      :=dx2;
if (ta.right<=ta.left) then goto skiptext;

//progress bar
if (xprogress>=1) then
   begin

   pa                 :=ta;
   if (xtep=tepnone)  then pa.left:=s.bs;

   int1               :=low__aorb(ta.right,s.cw-1-s.bs,xtep2=tepnone);
   pa.right:=frcrange32(trunc((xprogress/100)*int1),ta.left,int1);
   //was: if (xprogress>=1) then lds2(pa,s.hover,clnone,clnone,0,'h12',false);
   if (xprogress>=1) then fshadeArea(pa,s.hover,s.hover,false);

   end;

//title
if (xtitle<>'') then
   begin

   z    :=xlang(xtitle);
   ftext(s.back,ta,ta.left,s.bs,s.font,'',z,fn ,true);

   end;

//optional background caption - 11dec2025
if (xvalue='') and (xcap<>'') then
   begin

   z    :=xlang(xcap);
   ftext(s.back,ta,ta.left,ty,int__splice24(0.5,s.font,s.back),'',z,fn ,true);//03mar2026

   end;

//value
int2    :=0;
tw      :=0;

if (xvalue<>'') then
   begin

   tw   :=fast__textwidth('',xvalue,fn);
   int1 :=(ta.right-ta.left)+1;

   if       ohardleft then int2:=0
   else if (tw>int1)  then int2:=-(tw-int1);

   ftext(s.back,ta,ta.left+int2,ty,s.font,'',xvalue,fn ,true);

   end;

//slim cursor => scale=0.5 (50%)
if ashowcursor then
   begin

   finvertCorrectedArea( area__make( ta.left+tw+int2, s.ch-s.bs-xlineheight+1+xpad0 , ta.left+tw+int2+font__lineThickness2( fn, 0.5 )-1 ,s.ch-1-s.bs-xpad0) ,false );

   end;

skiptext:

//frame - special note: fills in outside corner areas with "xback" -> requires when progress is >=1 as it is square and the control/frame may be round, thus the outside corner area must be filled with "xback" to erase and overlap from the square progress shading - 13apr2020
if (s.bs>=1) then fframeSimple( s.cs ,s.bs ,low__aorb(s.back,s.mustborder,oshowborder) ,255 ,false ,s.r );

except;end;
end;

function tbasicedit._onshortcut(sender:tobject):boolean;//01mar2022
var
   xcode2:string;
begin//store shortcut so we can transmitt it to our host form later (once we've closed the menu) - 02apr2020
//defaults
result:=false;

try
xcode2:='';
//get
case gui.key of
akctrlU:xcode2:='edit.undo';//19jun2022
akctrlT:xcode2:='edit.cuttxt';//01mar2022
akctrlC:xcode2:='edit.copytxt';//01mar2022
akctrlP:xcode2:='edit.paste';
akctrlD:if not opassword then xcode2:='edit.clear';
akctrlR:xcode2:='edit.upper';
akctrlL:xcode2:='edit.lower';
akctrlN:xcode2:='edit.name';
end;//case
//set
if (xcode2<>'') then
   begin
   result:=true;
   showmenuClick(self,'',100,xcode2,clnone);
   end;
except;end;
end;

function tbasicedit._onnotify(sender:tobject):boolean;
var
   a:tpoint;
begin
//not handled
result:=false;

try
//key
if (gui.key<>aknone) then
   begin
   result:=true;
   if enabled and (not oreadonly) then
      begin
      case gui.key of
      0..255:if xundoautofill(1) then value:=value+char(gui.key);
      aktab:if xundoautofill(1) then value:=value+#9;
      //was: akdelete:value:='';// BUT mum likes both delete keys to delete ONE char at a time rather than clear the entire line of text - 20mar2021
      akdelete,akback:begin
         if (gui.key=akdelete) and odel_clearstext then value:=''
         else if (ivalue<>'') and xundoautofill(2) then value:=strcopy1(value,1,low__len32(value)-1);
         end;
      akreturn:if assigned(fonreturn) then low__fireevent(self,fonreturn);
      end;//case
      end;
   end;
//mouse
if gui.mouseupstroke and enabled then
   begin
   a:=mousedownxy;
   if      low__ptinarea(a,ibutarea2) then
      begin
      if assigned(fonclick2) then gui.xfireevent(self,fonclick2)//supports closelock - 03apr2021
      else if opassword then
         begin
         ireveal:=not ireveal;
         xshowpass;
         end
      else if (ocmd2<>'') then showmenuClick(self,'',100,ocmd2,clnone);//19apr2025
      end
   else if low__ptinarea(a,ibutarea1) and assigned(fonclick1) then gui.xfireevent(self,fonclick1)//supports closelock - 03apr2021
   else if idropstatic then
      begin
      if assigned(fonclick2) then gui.xfireevent(self,fonclick2);//supports closelock - 03apr2021
      end
   //double click show/hide for password only - 24sep2022
   else if gui.mousedbclick and opassword then
      begin
      ireveal:=not ireveal;
      xshowpass;
      end;
   end;
//.up/down stroke
if gui.mousedownstroke or gui.mouseupstroke or gui.mousemoved then xcheckref;
if gui.mousedownstroke or gui.mousedown or gui.mouseupstroke then xnotidle;
//.help
if gui.mousemoved and (not gui.mousedown) then
   begin
   //get
   a:=mousemovexy;
   if low__ptinarea(a,ibutarea1) then help2:=ibuthelp
   else if low__ptinarea(a,ibutarea2) then help2:=ibuthelp2
   else help2:='';//revert back to "help"
   end;
//showmenu - 20mar2021
if mustshowmenu then
   begin
   showmenu;
   result:=true;
   end;
//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);


//paint the right button
if (gui.mousedownstroke or gui.mouseupstroke) and enabled then
   begin
   a:=mousedownxy;
   if low__ptinarea(a,ibutarea1) or low__ptinarea(a,ibutarea2) then paintnow;
   end;
except;end;
end;

procedure tbasicedit.xcheckref;
begin
if visible and low__setstr(iref,bnc(opassword)+pcrefsep+bnc(ireveal)+pcrefsep+bnc(opassword and gui.mousedownstroke and focused)+pcrefsep+bnc(opassword and gui.mouseupstroke)+pcrefsep+bnc(oborder2)+pcrefsep+bnc(oborder2 and low__ptinarea(mousemovexy,ibutarea2))+pcrefsep+bnc(xshowcursor)+pcrefsep+bnc(focused)+pcrefsep+bnc(mouseinside)+pcrefsep+bnc(visible)+pcrefsep+bnc(enabled)) then paintnow;
end;

function tbasicedit.xshowcursor:boolean;
begin
result:=enabled and (not oreadonly) and focused and ((iidleref>=slowms64) or iflash);
end;

procedure tbasicedit.xnotidle;
begin
iidleref:=slowms64+750;
end;


//tbasicgradient ---------------------------------------------------------------
constructor tbasicgradient.create(xparent:tobject;xstyle:string);
begin
create2(xparent,true,xstyle);
end;

constructor tbasicgradient.create2(xparent:tobject;xstart:boolean;xstyle:string);
begin
if classnameis('tbasicgradient') then track__inc(satGrad,1);
inherited create2(xparent,false);
oroundstyle:=0;
bordersize:=0;

//start
if xstart then start;
end;

destructor tbasicgradient.destroy;
begin
inherited destroy;
if classnameis('tbasicgradient') then track__inc(satGrad,-1);
end;

procedure tbasicgradient._onpaint(sender:tobject);
var
   t,n:tclientinfo;
begin
try
//init
infovars2(n,true);//normal
infovars2(t,false);//title

//get
ffillArea(n.cs,int__splice24(0.35,t.back,n.back),n.r);
except;end;
end;

function tbasicgradient.getalignheight(xclientwidth:longint):longint;//15may2025
begin
result:=vizoom;
end;

//## tbasicdebug ###############################################################
constructor tbasicdebug.create(xparent:tobject);
begin
create2(xparent,true);

//vars
iongetalignheight_count     :=0;
ionpaint_count              :=0;
ipaintnow_count             :=0;
ipartpaint_count            :=0;
ipaintarea_L_count          :=0;
ipaintarea_R_count          :=0;
ipaintarea_T_count          :=0;
ipaintarea_B_count          :=0;
ipartpaint_notfound_count   :=0;

//system vars
debug_basicdebug_area           :=nilarea;
debug_basicdebug_areacheck      :=false;
debug_basicdebug_areafail_count :=0;
debug_basicdebug_areaoverlap_count:=0;
debug_basicdebug_int1           :=0;
end;

constructor tbasicdebug.create2(xparent:tobject;xstart:boolean);
begin
//self
inherited create2(xparent,false);
//vars

//start
if xstart then start;
end;

destructor tbasicdebug.destroy;
begin
try
//self
inherited destroy;
except;end;
end;

function tbasicdebug.getalignheight(xclientwidth:longint):longint;
begin
result:=vifontheight*15;
end;

procedure tbasicdebug._ontimer(sender:tobject);
begin
paintnow;
end;

procedure tbasicdebug._onpaint(sender:tobject);
var
   s:tclientinfo;
   dx,dy:longint;

   procedure dlink(xcap:string);
   begin
   ftext(s.back,s.cs,dx,dy,s.font,'',xcap,s.Rfn ,true);
   inc(dy,s.fnH);
   end;
begin
try
//init
infovars(s);
dx:=5;
dy:=5;
low__irollone(ionpaint_count);
if (ipaintarea.left<>iclientarea.left)     then low__irollone(ipaintarea_L_count);
if (ipaintarea.right<>iclientarea.right)   then low__irollone(ipaintarea_R_count);
if (ipaintarea.top<>iclientarea.top)       then low__irollone(ipaintarea_T_count);
if (ipaintarea.bottom<>iclientarea.bottom) then low__irollone(ipaintarea_B_count);

if not gui.xpartpaint__hasareaContained(ipaintarea) then low__irollone(ipartpaint_notfound_count);

debug_basicdebug_area           :=ipaintarea;
debug_basicdebug_areacheck      :=true;//perform GUI host check


//cls
ffillArea(s.cs,random(max16),false);

//info
dlink('onpaint.count: '+k64(ionpaint_count));
dlink('paintnow.count: '+k64(ipaintnow_count));
dlink('ongetalignheight.count: '+k64(iongetalignheight_count));
dlink('partpaint.count: '+k64(ipartpaint_count));
dlink('paintarea.L.count: '+k64(ipaintarea_L_count));
dlink('paintarea.R.count: '+k64(ipaintarea_R_count));
dlink('paintarea.T.count: '+k64(ipaintarea_T_count));
dlink('paintarea.B.count: '+k64(ipaintarea_B_count));
dlink('partpaint.404.count: '+k64(ipartpaint_notfound_count));
dlink('partpaint.areaFail.count: '+k64(debug_basicdebug_areafail_count));
dlink('partpaint.areaOverlap.count: '+k64(debug_basicdebug_areaoverlap_count));

except;end;
end;

procedure tbasicdebug.paintnow;
begin
low__irollone(ipaintnow_count);
inherited paintnow;
end;


//## tmenutitle ################################################################
constructor tmenutitle.create2(xparent:tobject;xstart:boolean);
begin
//self
if classnameis('tmenutitle') then track__inc(satOther,1);
inherited create2(xparent,false);

//vars
bordersize     :=0;//20jul2024
obold          :=true;
oplain         :=false;

//start
if xstart then start;
end;

destructor tmenutitle.destroy;
begin
try
inherited destroy;
if classnameis('tmenutitle') then track__inc(satOther,-1);
except;end;
end;

function tmenutitle.xrowheight:longint;
begin

result:=vilineheight30;//11dec2025

end;

function tmenutitle.getalignheight(xclientwidth:longint):longint;
begin
result:=(2*findbordersize)+xrowheight;
end;

procedure tmenutitle._onpaint(sender:tobject);
const
   xpad=5;
var
   s:tclientinfo;
   xrowpad,dy,dh,rh,fi,fiH:longint;

   function xrowarea:twinrect;
   begin
   result:=area__make(s.bs,dy+xrowpad,s.cw-1-s.bs,dy+rh-1-xrowpad);
   end;

begin
try

//init
infovars(s);
dh       :=frcmin32(s.ch-(2*s.bs),1);
dy       :=s.bs;
rh       :=xrowheight;
xrowpad  :=scale__px0(2);
fi       :=low__aorb(s.Rfn ,s.Rfb,obold);//resFont
fiH      :=low__aorb(s.fnH ,s.fbH,obold);

//cls
ffillArea(s.cs,s.back,false);

//hover
if (not oplain) then ffillArea(xrowarea,s.hover,s.r);

//text
ftext(s.back,s.ci,s.bs+xpad,s.ci.top+((dh-fiH ) div 2),s.font,otab,caption,fi ,true);

//frame
xframeSimple( s );

except;end;
end;


//## tbasictitle ###############################################################
constructor tbasictitle.create(xparent:tobject;xlarge,xlabel:boolean;xcaption:string);
begin
create2(xparent,true,xlarge,xlabel,xcaption);
end;

constructor tbasictitle.create2(xparent:tobject;xstart,xlarge,xlabel:boolean;xcaption:string);
begin
//self
if classnameis('tbasictitle') then track__inc(satTitle,1);
inherited create2(xparent,false);
//vars
oindent      :=true;
otweakv      :=0;
itimer250    :=slowms64;
olargeheight :=false;

case xlabel of
true:begin
   ilabel:=true;
   inormal:=true;
   ibordersize:=0;
   end;
else begin
   ilabel:=false;
   inormal:=false;
   ibordersize:=0;
   end;
end;

itext        :=xcaption;
iinforef     :='';
olarge       :=xlarge;
ocentertext  :=false;
oflatback    :=false;
oshadeback   :=false;

//controls
clientheight :=20;

//start
if xstart then start;
end;

destructor tbasictitle.destroy;
begin
try
inherited destroy;
if classnameis('tbasictitle') then track__inc(satTitle,-1);
except;end;
end;

procedure tbasictitle.makesleek;
begin
oflatback:=true;
end;

procedure tbasictitle._ontimer(sender:tobject);
var
   xmustpaint:boolean;
begin
try
//defaults
xmustpaint:=false;

//.itimer250
if (slowms64>itimer250) then
   begin
   //control info
   if low__setstr(iinforef,bnc(olarge)+pcrefsep+bnc(inormal)+pcrefsep+bnc(ilabel)) then
      begin
      xmustpaint:=true;
      end;
   //reset
   itimer250:=slowms64+250;
   end;

//paint
if xmustpaint then paintnow;
except;end;
end;

function tbasictitle.xtitleheight:longint;//text height
begin
if ilabel then result:=vifontheight else result:=low__aorb(vititleheight,vititleheight2,olarge);
end;

function tbasictitle.getalignheight(xclientwidth:longint):longint;//04sep2025, 16may2025, 07sep2020
begin

result:=frcmin32(viTitleheight2 ,vilineheight30);

end;

procedure tbasictitle.settext(x:string);
begin
if low__setstr(itext,x) then paintnow;
end;

procedure tbasictitle._onpaint(sender:tobject);//08apr2025: otab support
var
   s:tclientinfo;
   dx,dh,fc:longint;
begin
try
//init
infovars(s);
dh  :=frcmin32(s.ch-(2*s.bs),1);

//.font
case ilabel of
true:fc:=s.Rfn;
else fc:=s.Rfb;
end;

//cls
if visleekHighlight then ffillArea(s.cs,s.back,false)//15may2025
else if oflatback   then background__title2(s.cs,s.back,true,false)
else if oshadeback  then background__toolbar(s.cs,s.back,s.back,false)
else                     ffillArea(s.cs,s.back,false);

//text
dx:=s.bs+insint(8*vizoom,oindent);

if (otab='') then
   begin

   if ocentertext then
      begin

      dx:=frcmin32((s.cw-fast__textwidth('',itext,fc)) div 2,dx);

      end;
      
   ftext(s.back,s.ci,dx,s.ci.top+((dh-resfont__height(fc) ) div 2),s.font,'',itext,fc ,true);//up 1px - 01feb2025, 24feb2021

   end
else
   begin

   ftext(s.back,s.ci,dx,s.ci.top+((dh-resfont__height(fc) ) div 2),s.font,otab,itext,fc ,true);

   end;

//frame
xframeSimple( s );

except;end;
end;


//## tbasicstatus ##############################################################
constructor tbasicstatus.create2(xparent:tobject;xstart:boolean);
var
   p:longint;
begin
//self
if classnameis('tbasicstatus') then track__inc(satStatus,1);
inherited create2(xparent,false);
//vars
ocenter:=true;
inormal:=false;
ibordersize:=3;
itimer250:=slowms64;
ipause:=false;
ilastflash:=false;
iflashcount:=0;
for p:=0 to high(icellwidth) do
begin
icellref[p]:='';
icellwidth[p]:=0;
icellalign[p]:=3;//0=left, 1=center, 2=right, 3=internal
icellleft[p]:=0;
icellright[p]:=-1;
icellpert[p]:=0;
icelltext[p]:='';
icellname[p]:='';
icellflash[p]:=false;
icellmark[p]:=false;
end;//p
iclickindex:=-1;
iclickname:='';
fclickcell:=nil;
//controls
clientheight:=20;
//start
if xstart then start;
end;

destructor tbasicstatus.destroy;
begin
try
inherited destroy;
if classnameis('tbasicstatus') then track__inc(satStatus,-1);
except;end;
end;

function tbasicstatus._onnotify(sender:tobject):boolean;
var
   dindex,sx,p:longint;
begin
//defaults
result:=false;
dindex:=-1;

try
//find
sx:=mousexy.x;
for p:=0 to high(icellwidth) do
begin
if (icellwidth[p]>=1) and (sx>=icellleft[p]) and (sx<=icellright[p]) then
   begin
   dindex:=p;
   break;
   end;
end;//p
//help
if (dindex>=0) then help2:=icellhelp[dindex] else help2:='';
//get
if gui.mouseupstroke then//and (not gui.mousewasdown) then
   begin
   //init
   result:=true;
   //get
   iclickindex:=dindex;
   if (dindex>=0) then iclickname:=icellname[dindex] else iclickname:='';
   //event
   if (dindex>=0) then low__fireevent(self,fclickcell);
   end;
//self
result:=inherited _onnotify(sender);
except;end;
end;

procedure tbasicstatus._ontimer(sender:tobject);
var
   xmustpaint:boolean;
   p:longint;
   str1:string;
   bol1:boolean;
begin
try
//defaults
xmustpaint:=false;

//.itimer250
if (slowms64>itimer250) then
   begin
   //cellref
   if not ipause then
      begin
      bol1:=false;
      for p:=0 to high(icellwidth) do
      begin
      str1:=intstr32(icellwidth[p])+#7+icelltext[p];
      if (str1<>icellref[p]) then
         begin
         icellref[p]:=str1;
         bol1:=true;
         end;
      end;//p
      if bol1 then xmustpaint:=true;
      end;
   //control info
   if low__setstr(iinforef,intstr32(iflashcount)+pcrefsep+bnc(inormal)+pcrefsep+intstr32(findbordersize)+pcrefsep+intstr32(vifontheight)) then//29dec2021
      begin
      //was: if ((align=altop) or (align=albottom)) then height:=getalignheight;
      xmustpaint:=true;
      end;
   //reset
   itimer250:=slowms64+low__aorb(250,100,ofast);//26aug2024
   end;

//.flash support
if (iflashcount>=1) and (ilastflash<>sysflash) then
   begin
   ilastflash:=sysflash;
   xmustpaint:=true;
   end;

//paint
if xmustpaint then paintnow;
except;end;
end;

function tbasicstatus.getalignheight(xclientwidth:longint):longint;
var
   v:longint;
begin
v:=2*findbordersize;
result:=frcmin32(v+4+vifontheight,v+(static_lineheight36*vizoom));
end;

procedure tbasicstatus._onpaint(sender:tobject);
const
   sp=3;
var
   s:tclientinfo;
   da,pa:twinrect;
   dcellwidth,xsepwidth,p2,px,xlast,dx,dy,p:longint;
   dpert:double;
   smark,sflash,dflash:boolean;
   dleft:array[0..high(icellleft)] of longint;
   dright:array[0..high(icellleft)] of longint;
   xflash:boolean;

   function xcellwidth(x:longint):longint;
   begin
   result:=icellwidth[x];
   if (result>=1) then result:=frcmin32(round(icellwidth[x]*s.zoom*vifontwidthratio),1);
   end;

   function dxalign(xalign:longint;x:string):longint;
   begin
   if (xalign=3) then xalign:=low__aorb(0,1,ocenter);

   case xalign of
   1:result:=frcmin32(((da.right-da.left+1)-fast__textwidth('',x,s.fn)) div 2,0);//center
   2:result:=frcmin32(da.right-1-fast__textwidth('',x,s.fn),0);//right
   else result:=0;//left
   end;//case

   end;
begin
try
//init
infovars(s);

//cls
ffillArea(s.cs,s.back,false);

xflash   :=(iflashcount>=1) and ilastflash;
xsepwidth:=low__aorb(1,2,s.bs>=1)*s.zoom;

//dleft
for p:=0 to high(dleft) do
begin
dleft[p] :=0;
dright[p]:=-1;
end;//p

//find last
for p:=high(icellwidth) downto 0 do
begin
xlast:=p;
if (icellwidth[p]>=1) then break;
end;//p

//text
dx:=s.bs+1+sp;
px:=s.bs;
dy:=(s.ch-s.fnH) div 2;

for p:=0 to high(icellwidth) do if (icellwidth[p]>=1) or (icelltext[0]<>'') or (icellpert[p]>0) or (icellmark[p]) then
   begin
   //init
   smark      :=icellmark[p];
   sflash     :=icellflash[p];
   dflash     :=sflash and xflash;
   dcellwidth :=xcellwidth(p);
   dpert      :=icellpert[p];
   da.left    :=dx;

   if ((p=0) and (dcellwidth<=0)) or (p=xlast) then da.right:=s.cw-1-s.bs else da.right:=frcmin32(dx+dcellwidth-1-sp,dx);

   da.right   :=frcmax32(da.right,s.cs.right-s.bs);
   da.top     :=s.bs;
   da.bottom  :=s.ch-1-s.bs;
   dleft[p]   :=da.left;
   dright[p]  :=da.right;

   //get
   //.progress bar
   if (dpert>0) then
      begin
      pa      :=da;
      pa.left :=px;
      pa.right:=frcrange32(pa.left+round((pa.right-pa.left)*(dpert/100)),px,da.right);

      //.progress color
      if (not sflash) or dflash then
         begin
         ffillArea(pa,s.hover2,false);
         end;

      //.text
      ftext(s.back,da,da.left+dxalign(icellalign[p],icelltext[p]),dy,s.font,'',icelltext[p],s.Rfn ,true);//flash support - 29dec2021

      end
   else if dflash or (smark and (not sflash)) then
      begin
      pa      :=da;
      pa.left :=px;

      //.background
      ffillArea(pa,s.hover,false);

      //.text
      ftext(s.back,da,da.left+dxalign(icellalign[p],icelltext[p]),dy,s.font,'',icelltext[p],s.Rfn ,true);//flash support - 29dec2021

      end
   else//normal
      begin

      ftext(s.back,da,da.left+dxalign(icellalign[p],icelltext[p]),dy,s.font,'',icelltext[p],s.Rfn ,true);

      end;

   //vertical dividers -> 2px wide
   px:=da.right;
   if (p<xlast) and (xsepwidth>=1) then
      begin
      for p2:=1 to xsepwidth do ffillArea(area__make(da.right+p2,s.bs,da.right+p2,s.ch-1-s.bs),s.sep,false);//26may2025
      px:=da.right+xsepwidth;
      end;

   //inc
   inc(dx,dcellwidth+xsepwidth);
   end;

//frame
if (s.bs>=1) then fframeSimple( s.cs ,s.bs ,s.border ,255 ,false ,s.roundFrame );

//set
for p:=0 to high(dleft) do
begin
icellleft[p] :=dleft[p];
icellright[p]:=dright[p];
end;//p

except;end;
end;

function tbasicstatus.xcellok(x:longint):boolean;
begin
result:=(x>=0) and (x<=high(icellwidth));
end;

procedure tbasicstatus.setcellname(x:longint;y:string);
begin
if xcellok(x) then icellname[x]:=y;
end;

function tbasicstatus.getcellname(x:longint):string;
begin
if xcellok(x) then result:=icellname[x] else result:='';
end;

procedure tbasicstatus.setcellhelp(x:longint;y:string);
begin
if xcellok(x) then icellhelp[x]:=y;
end;

function tbasicstatus.getcellhelp(x:longint):string;
begin
if xcellok(x) then result:=icellhelp[x] else result:='';
end;

procedure tbasicstatus.setcelltext(x:longint;y:string);
begin
if xcellok(x) then icelltext[x]:=y;
end;

function tbasicstatus.getcelltext(x:longint):string;
begin
if xcellok(x) then result:=icelltext[x] else result:='';
end;

procedure tbasicstatus.setcellwidth(x,y:longint);
begin
if xcellok(x) then icellwidth[x]:=frcrange32(y,0,999999);
end;

function tbasicstatus.getcellwidth(x:longint):longint;
begin
if xcellok(x) then result:=icellwidth[x] else result:=0;
end;

procedure tbasicstatus.setcellalign(x,y:longint);
begin
if xcellok(x) then icellalign[x]:=frcrange32(y,0,2);
end;

function tbasicstatus.getcellalign(x:longint):longint;
begin
if xcellok(x) then result:=icellalign[x] else result:=0;
end;

procedure tbasicstatus.setcellpert(x:longint;y:double);
begin
if (y<0) then y:=0 else if (y>100) then y:=100;
if xcellok(x) and (icellpert[x]<>y) then
   begin
   icellpert[x]:=y;
   paintnow;
   end;
end;

function tbasicstatus.getcellpert(x:longint):double;
begin
if xcellok(x) then result:=icellpert[x] else result:=0;
end;

procedure tbasicstatus.setcellflash(x:longint;y:boolean);
begin
if xcellok(x) and (icellflash[x]<>y) then
   begin
   icellflash[x]:=y;
   if y then inc(iflashcount) else iflashcount:=frcmin32(iflashcount-1,0);
   paintnow;
   end;
end;

function tbasicstatus.getcellflash(x:longint):boolean;
begin
if xcellok(x) then result:=icellflash[x] else result:=false;
end;

procedure tbasicstatus.setcellmark(x:longint;y:boolean);
begin
if xcellok(x) and low__setbol(icellmark[x],y) then paintnow;
end;

function tbasicstatus.getcellmark(x:longint):boolean;
begin
if xcellok(x) then result:=icellmark[x] else result:=false;
end;


//## tbasictoolbar ##############################################################
constructor tbasictoolbar.create2(xparent:tobject;xstart:boolean);
var
   p:longint;
begin                      

//self
if classnameis('tbasictoolbar') then track__inc(satToolbar,1);
inherited create2(xparent,false);

//options
//.window head related
omodified :=false;
otag2     :=0;
opartline :=0.3;
oscaleh   :=1;//24mar2025
oscalevpad:=1;//16may2025
oscalesep :=1;//04jun2025
iishead   :=false;
iwmin     :=false;
iwmax     :=false;
iwclo     :=false;
iwmen     :=false;
iwfull    :=false;
iappicon  :=false;
iappcap   :=false;
iformrect :=area__make(0,0,0,0);
iapptep   :=tepNone;
iappxy.x  :=0;
iappxy.y  :=0;

//.animated icon
ianicount :=0;//30apr2022
ianipos   :=0;
ianiplay64:=0;
ianinext64:=0;

//.title support            `
otitle    :=false;
olarge    :=false;

//.other
oflatback :=false;
oclickthru:=false;
ominrows  :=1;
oequalwidths:=false;
ocountdown:=true;
ocountdown_dlgcheck:=true;
oautoheight:=true;
odownsubtle:=false;
owrap     :=true;
oheadalign:=true;//16may2025
oindex    :=-1;
ocode     :=0;
ocode2    :='';
otepcolor :=clnone;
otepcolor2:=clnone;
ounderline:=true;

//vars
ihalign:=0;
fonclick:=nil;
fonclick2:=nil;
ilastfindbycode2:=-1;//07mar2021
imustlink:=false;
istyle:=0;
irowpad:=0;
irowcount:=1;
idownindex  :=-1;
ifocusindex :=-1;
ihoverindex :=-1;
ibuttonpad:=5;
ibuttonvpad:=2;
ovpad:=0;
ohpad:=2;
ohbutpad:=8;
ohbutpad1st:=true;
ojump:=1;//16may2025
iinforef:='';
inormal:=false;
iaddcount:=tsiUser;
itepheight:=systepHeight20;
ibordersize:=2;//looks better than 3 - 17mar2021
icountdown1000:=slowms64;
itimer500:=slowms64;
itimer250:=slowms64;
itimer100:=slowms64;
iflash:=false;
ilastflash:=sysflash;
ipause:=false;

for p:=0 to high(icap) do clear1(p);//13jul2025

//controls
bordersize:=0;//03dec2023
clientheight:=20;

//start
if xstart then start;

end;

destructor tbasictoolbar.destroy;
begin
try
//disconnect timer
timer:=false;
fonclick:=nil;
fonclick2:=nil;
//self
inherited destroy;
if classnameis('tbasictoolbar') then track__inc(satToolbar,-1);
except;end;
end;

procedure tbasictoolbar.copyitemsfrom(x:tbasictoolbar);//14jul2025
begin
copyitemsfrom2(x,false);
end;

procedure tbasictoolbar.copyitemsfrom2(x:tbasictoolbar;xallitems:boolean);//14jul2025
begin
copyitemsfrom3(x, low__aorb(tsiUser,0,xallitems), low__aorb(tsiUser,0,xallitems) );
end;

procedure tbasictoolbar.copyitemsfrom3(s:tbasictoolbar;dkeepcount,sfromindex:longint);//14jul2025
var
   dc,p:longint;
begin

//range
dkeepcount :=frcrange32(dkeepcount,0,1+high(icolor));
sfromindex :=frcrange32(sfromindex,0,high(icolor));
dc         :=dkeepcount;

//check
if (sfromindex>=s.iaddcount) then exit;

//get
for p:=sfromindex to frcmax32(s.iaddcount,high(icolor)) do if (dc<=high(icolor)) then
   begin

   //get
   puse[dc]        :=s.puse[p];
   piw[dc]         :=s.piw[p];
   pih[dc]         :=s.pih[p];
   pit[dc]         :=s.pit[p];
   ptw[dc]         :=s.ptw[p];
   pth[dc]         :=s.pth[p];
   ptf[dc]         :=s.ptf[p];
   poa[dc]         :=s.poa[p];
   pa[dc]          :=s.pa[p];

   icolor[dc]      :=s.icolor[p];
   icolorb[dc]     :=s.icolorb[p];
   ititle[dc]      :=s.ititle[p];
   icap[dc]        :=s.icap[p];
   isize[dc]       :=s.isize[p];
   ipert[dc]       :=s.ipert[p];
   itep[dc]        :=s.itep[p];
   icode[dc]       :=s.icode[p];
   icode2[dc]      :=s.icode2[p];
   ibuthelp[dc]    :=s.ibuthelp[p];
   iref[dc]        :=s.iref[p];
   ienableds[dc]   :=s.ienableds[p];
   ivisibles[dc]   :=s.ivisibles[p];
   imarked[dc]     :=s.imarked[p];
   ihighlight[dc]  :=s.ihighlight[p];
   iflasher[dc]    :=s.iflasher[p];
   icountdown[dc]  :=s.icountdown[p];

   //inc
   inc(dc);
   if (dc>high(icolor)) then break;

   end;//p

//set
iaddcount:=dc;

end;

procedure tbasictoolbar.setcaption2(x:string);//27dec2024
begin
if low__setstr(icaption2,x) then gui.fullalignpaint;
end;

function tbasictoolbar.aniAdd(xtep,xms:longint):boolean;//16sep2022
var
   p:longint;
begin

//defaults
result                :=false;

//check
if (ianicount>high(ianitep)) then exit;

//get
if tep__find(xtep) then
   begin

   p                  :=ianicount;
   ianitep[p]         :=xtep;
   ianims[p]          :=frcrange32(xms,50,10000);

   inc(ianicount,1);

   end;

//successful
result                :=true;

end;

procedure tbasictoolbar.aniClear;
begin

if (ianicount>=1) then
   begin

   tep      :=ianitep[0];
   ianicount:=0;

   end;

end;

procedure tbasictoolbar.aniPlay;
begin
if (ianicount>=1) then ianiplay64:=slowms64+2000;
end;

procedure tbasictoolbar.setapptep(x:longint);//app icon - 25may2025
begin
if low__setint(iapptep,x) then paintnow;
end;

procedure tbasictoolbar.marktab(xname:string;xmark:boolean);//11sep2021
begin
bhighlight2[xname]:=xmark;
bflash2[xname]:=xmark;
end;

procedure tbasictoolbar.xaddoptions;
begin
xaddoptions2(tepNone,'');
end;

procedure tbasictoolbar.xaddoptions2(xtep:longint;xcmd:string);
begin
if viMaster then add('Options',low__aorb(tepoptions20,xtep,xtep<>tepNone),0,strdefb(xcmd,scOptions),'App Options|Adjust app coloring, font size and other settings');
end;

procedure tbasictoolbar.xaddhelp;
begin
if viMaster and ((sizeof(apphelp)>=2) or (sizeof(syshelp)>=2)) then add('Help',tephelp20,0,scHelp,'App Help|Toggle app help panel, or press the "F1" key to show');//03nov2023, 24jul2021
end;

procedure tbasictoolbar.xaddabout;
begin
add('About',tepAbout20,0,scAbout,'Show About');
end;

procedure tbasictoolbar.xaddsplash;
begin
add('Splash',tepAbout20,0,scSplash,'Show Splash');
end;

procedure tbasictoolbar.xaddmixer;//07mar2022
begin
add('Mixer',tepVol20,0,scMixer,'Show Mixer');
end;

procedure tbasictoolbar.xaddmax;//15mar2022
begin
add('Max',tepMax20,0,scMax,'Toggle Fullscreen mode');
end;

procedure tbasictoolbar.xaddonTop;//15mar2022
begin
hcsadd('On Top',tepOntop20,0,scOntop,'Toggle On Top',0);
end;

function tbasictoolbar.getparentpage:string;
label
   redo;
var
   a:tbasiccontrol;
begin
//defaults
result:='';

try
//get
a:=self;
redo:
if      zzok(a,7307) and (a is tbasicscroll) then result:=(a as tbasicscroll).page
else if zzok(a,7308) then
   begin
   a:=a.parent;
   goto redo;
   end;
except;end;
end;

procedure tbasictoolbar.setparentpage(x:string);
label
   redo;
var
   b:array[0..maxcore] of boolean;
   a,pa:tbasiccontrol;
   p:longint;
   xmustlink:boolean;
begin
try
xmustlink:=false;
a:=self;
//clear
for p:=0 to high(b) do b[p]:=false;

//standard page handler -> OUR parent is assumed to control the PLUS page display -> but when columns are used
redo:
if      zzok(a,7310) and (a is tbasicscroll) then
   begin
   if not strmatch((a as tbasicscroll).page,x) then
      begin
      (a as tbasicscroll).page:=x;
      b[a.coreindex]:=true;
      xmustlink:=true;
      end;
   end
else if zzok(a,7311) then
   begin
   a:=a.parent;
   goto redo;
   end;

//dedicated PLUS handler -> sniff out ALL page handlers that support PLUS based pages and set them SYSTEM WIDE, regardless of their parent, rootwin, etc - 28jun2022
if strmatch(strcopy1(x,1,low__len32(scPlus)),scPlus) then
   begin
   //find the base handlers "tbasicscroll" controls and fire them off individually
   for p:=0 to (gui.corecount-1) do
   begin
   if gui.xinuse(p) then
      begin
      a:=gui.core[p];
      if (a<>nil) and (a.opagename<>'') and strmatch(strcopy1(a.opagename,1,low__len32(scPlus)),scPlus) then
         begin
         pa:=a.parent;
         if (pa<>nil) and gui.xinuse(pa.coreindex) and (pa is tbasicscroll) and (not b[pa.coreindex]) then
            begin
            b[pa.coreindex]:=true;
            (pa as tbasicscroll).page:=x;
            xmustlink:=true;
            end;
         end;
      end;
   end;//p
   end;
//xmustlink
if xmustlink then imustlink:=true;
except;end;
end;

procedure tbasictoolbar.setstyle(x:longint);
begin
istyle:=frcrange32(x,0,2);
end;

procedure tbasictoolbar._ontimer(sender:tobject);//20jul2025, 14jul2025
var
   xmustalign,xmustpaint:boolean;
   int1,p:longint;
   xpp,str1:string;
   xvisible,xonce,xmustcount,bol1:boolean;
   a,b:tbasiccontrol;
begin
try
//defaults
xvisible  :=visible;
xmustalign:=false;
xmustpaint:=false;
xmustcount:=false;

//flash
if (sysflash<>ilastflash) then
   begin
   ilastflash:=sysflash;
   if (xflashcount=0) then
      begin
      if low__setbol(iflash,false) then xmustpaint:=true;
      end
   else
      begin
      iflash:=sysflash;
      xmustpaint:=true;
      end;
   end;

//.itimer250
if (slowms64>itimer250) or imustlink then
   begin
   //imustlink
   imustlink:=false;

   //window state
   if iwmax or iwfull then xcmd(min32);

   //countdown
   if (slowms64>=icountdown1000) then
      begin
      xmustcount:=enabled and ocountdown and (not ipause) and xvisible;
      icountdown1000:=slowms64+1000;
      end;

   //cellref
   //was: if (not ipause) then
   if (not ipause) and xvisible then
      begin
      bol1:=false;
      xpp:=parentpage;
      xonce:=true;

      for p:=0 to (iaddcount-1) do//was: high(icap) do - 20jul2025
      begin

      //countdown
      if xmustcount and ienableds[p] and ivisibles[p] and (icountdown[p]>=1) then
         begin

         //.once only
         if xonce then
            begin
            xonce:=false;
            if xmustcount and ocountdown_dlgcheck then//might be time consuming -> do only ONCE and only when we have 1 or MORE countdowns to process - 05sep2020
               begin
               gui.xdlg(a);
               xwindow(b);
               if (zzok(a,7312) and (a<>b)) then xmustcount:=false;
               end;
            end;

         //.mustcount
         if xmustcount then
            begin
            icountdown[p]:=frcmin32(icountdown[p]-1,0);
            //.auto trigger click event for link/button
            if (icountdown[p]=0) then xclickbutton(p);
            end;
         end;

      //special internally managed links
      if (icode2[p]<>'') and strmatch(strcopy1(icode2[p],1,low__len32(scpage)),scpage) then imarked[p]:=strmatch(strcopy1(icode2[p],low__len32(scpage)+1,low__len32(icode2[p])),xpp);

      //refs
      str1:=intstr32(isize[p])+pcrefsep+bolstr(ititle[p])+bolstr(ihighlight[p])+bolstr(ienableds[p])+bolstr(ivisibles[p])+bolstr(iflasher[p])+bolstr(imarked[p])+pcrefsep+intstr32(icolor[p])+pcrefsep+intstr32(itep[p])+pcrefsep+intstr32(low__len32(icap[p]))+pcrefsep+icap[p]+pcrefsep+intstr32(icountdown[p])+pcrefsep+intstr32(low__len32(ibuthelp[p]))+pcrefsep+ibuthelp[p];
      if (str1<>iref[p]) then
         begin
         iref[p]:=str1;
         bol1:=true;
         end;

      end;//p

      if bol1 then
         begin
         xmustalign:=true;
         xmustpaint:=true;
         end;

      end;

   //control info

   //was: if xvisible and low__setstr(iinforef,bolstr(omodified)+bolstr(xishead and (gui.state='f'))+intstr32(find__halign)+pcrefsep+intstr32(istyle)+pcrefsep+bnc(vitouch)+bnc(ocountdown)+pcrefsep+bnc(viround)+pcrefsep+bnc(owrap)+pcrefsep+bnc(enabled)+pcrefsep+bnc(inormal)+pcrefsep+intstr32(findbordersize)+pcrefsep+intstr32(vifontheight)+pcrefsep+intstr32(itepheight)+pcrefsep+intstr32(irowpad)+pcrefsep+intstr32(ibuttonpad)+pcrefsep+intstr32(frcmin32(ovpad,0))+pcrefsep+intstr32(ibuttonvpad)+insstr(bnc(olarge)+caption,otitle)) then
   if xvisible and low__setstr(iinforef,bolstr(omodified)+bolstr(xishead and (gui.laststate='f'))+intstr32(find__halign)+pcrefsep+intstr32(istyle)+pcrefsep+bnc(vitouch)+bnc(ocountdown)+pcrefsep+bnc(viround)+pcrefsep+bnc(owrap)+pcrefsep+bnc(enabled)+pcrefsep+bnc(inormal)+pcrefsep+intstr32(findbordersize)+pcrefsep+intstr32(vifontheight)+pcrefsep+intstr32(itepheight)+pcrefsep+intstr32(irowpad)+pcrefsep+intstr32(ibuttonpad)+pcrefsep+intstr32(frcmin32(ovpad,0))+pcrefsep+intstr32(ibuttonvpad)+insstr(bnc(olarge)+caption,otitle)) then
      begin
      xmustalign:=true;
      xmustpaint:=true;
      end;

   //reset
   itimer250:=slowms64+250;
   end;

//.itimer500
if xvisible and (slowms64>itimer500) then
   begin

   //special built-in system links - 15mar2022
   if xfindbycode2b(scMixer,int1) then benabled[int1]:=low__canshowvol;//07mar2022

   if xfindbycode2b(scOntop,int1) then
      begin
      bhighlight[int1]:=viontop;
      bflash[int1]:=viontop;
      end;

   if xfindbycode2b(scMax,int1) then
      begin
      //was: bmarked[int1]:=(gui.state='f');
      bmarked[int1]:=(gui.laststate='f');
      bflash[int1]:=bmarked[int1];//25dec2024
      end;

   //reset
   itimer500:=slowms64+500;
   end;

//.aniPlay
if xvisible and (ianicount>=1) and (ianiplay64<>0) then
   begin

   if (slowms64>ianiplay64) then//stopped
      begin
      ianiplay64:=0;//stop
      ianipos:=0;
      tep:=ianitep[0];//restore default icon - 1st in the set
      end
   else if (slowms64>=ianinext64) then
      begin
      p:=ianipos+1;
      if (p>=ianicount) then p:=0;
      ianinext64:=add64(slowms64,ianims[p]);
      ianipos:=p;
      tep:=ianitep[p];//paint new icon
      end;

   end;

//paint - 14jul2025
//was: if xmustalign or xmustpaint then alignpaintnow__heightcheck(xmustalign,xmustpaint,clientwidth);
if xvisible and (xmustalign or xmustpaint) then alignpaintnow__heightcheck(xmustalign,xmustpaint,clientwidth);
except;end;
end;

function tbasictoolbar.xflashcount:longint;
var
   p:longint;
begin
result:=0;
for p:=0 to high(icap) do if puse[p] and ivisibles[p] and (xcapok(p) or xtepok(p)) and iflasher[p] then inc(result);
end;

function tbasictoolbar.xfindb(sx,sy:longint):longint;
begin
xfind(sx,sy,result);
end;

function tbasictoolbar.xfind(sx,sy:longint;var xindex:longint):boolean;//27dec2024
var
   p:longint;
begin
//defaults
result:=false;
xindex:=-1;

//find
for p:=high(icap) downto 0 do if puse[p] then
   begin

   if area__within(poa[p],sx,sy) then
      begin
      xindex:=p;
      result:=true;
      break;
      end;

   end;//p

end;

function tbasictoolbar.xfindbycode(xcode:longint):longint;
var
   p:longint;
begin
//defaults
result:=-1;
//find
for p:=high(icap) downto 0 do if (xcode=icode[p]) and (xcapok2(p,true) or xtepok2(p)) then
   begin
   result:=p;
   break;
   end;
end;

function tbasictoolbar.xfindbycodeb(xcode:longint;var xindex:longint):boolean;
begin
xindex:=xfindbycode(xcode);
result:=(xindex>=0);
end;

function tbasictoolbar.xfindbycode2(const xcode2:string):longint;
var
   p:longint;
begin
//defaults
result:=-1;

try
//ultra-fast
if (ilastfindbycode2>=0) and (ilastfindbycode2<=high(icap)) and strmatch(xcode2,icode2[ilastfindbycode2]) and (xcapok2(ilastfindbycode2,true) or xtepok2(ilastfindbycode2)) then
   begin
   result:=ilastfindbycode2;
   exit;
   end;

//find
for p:=high(icap) downto 0 do if strmatch(xcode2,icode2[p]) and (xcapok2(p,true) or xtepok2(p)) then
   begin
   result:=p;
   break;
   end;

//store:ultra-fast
ilastfindbycode2:=result;
except;end;
end;

function tbasictoolbar.xfindbycode2b(const xcode2:string;var xindex:longint):boolean;
begin
xindex:=xfindbycode2(xcode2);
result:=(xindex>=0);
end;

function tbasictoolbar.xfindbycodes(xcode:longint;xcode2:string):longint;
var
   p:longint;
begin
//defaults
result:=-1;

try
//find
for p:=high(icap) downto 0 do if puse[p] and (xcode=icode[p]) and (xcode2=icode2[p]) and (xcapok(p) or xtepok(p)) then
   begin
   result:=p;
   break;
   end;
except;end;
end;

procedure tbasictoolbar.xdragthewindow;//force head to act as a window dragger - assuming mouse input matches up - 07mar2022
begin
_onnotify2(nil,true);
end;

function tbasictoolbar._onnotify(sender:tobject):boolean;
begin
result:=_onnotify2(sender,false);
end;

function tbasictoolbar._onnotify2(sender:tobject;xdragonly:boolean):boolean;//28nov2025, 17aug2025 19jul2025
var
   xwinstyle,xclickindex,int1:longint;
   xmustreset,xmustpaint:boolean;
   a:tbasiccontrol;
begin

//defaults
result       :=true;//handled - 17aug2025
xmustpaint   :=false;
xmustreset   :=false;
xclickindex  :=-1;

try

//focus
if gui.mousedown and (not gui.mousewasdown) then
   begin

   iappxy.x:=gui.left;
   iappxy.y:=gui.top;

   if xdragonly then int1:=-1 else int1:=xfindb(mousedownxy.x,mousedownxy.y);

   if (int1<>idownindex) then
      begin

      if (int1>=0) and ( (not ienableds[int1]) or ((int1>=tsiUser) and (icap[int1]='-')) ) then int1:=-1;
      idownindex:=int1;
      xmustpaint:=true;

      end;

   end;

//hover
if xdragonly then int1:=-1 else int1:=xfindb(mousemovexy.x,mousemovexy.y);

if (int1<>ihoverindex) then
   begin

   if (int1>=tsiUser) and (icap[int1]='-') then int1:=-1;//can't hover or select a vertical sep line - 27dec2024

   ihoverindex        :=int1;
   //was:if enabled and xok(int1) and ienableds[int1] then screen.cursor:=crHandpoint else screen.cursor:=scDefault;
   xmustpaint         :=true;

   end;

//help
if gui.mousemoved and (not gui.mousedown) then
   begin

   if xok(int1) then help2:=findhelp(int1) else help2:='';

   end;

//drag window
if ((idownindex=-1) or (idownindex=tsiAppicon) or (idownindex=tsiAppcap)) and gui.mousedown then
   begin

   //init
   xwinstyle:=wmcontrol;
   xwindow(a);
   if zzok(a,7195) then xwinstyle:=a.winstyle;

   //get
   if zzok(a,7196) and (xwinstyle>wmcontrol) then
      begin

      //init
      app__turbo;//high speed timing

      //get
      case xwinstyle of
      wmFullwin:begin//normally handled by wndproc except for when "xdragonly=true" -> e.g. when a clock face needs to drag entire window about the screen - 28nov2025

         if xdragonly then
            begin

            gui.setbounds(
             iappxy.x + gui.screenmovexy.x - gui.screendownxy.x,
             iappxy.y + gui.screenmovexy.y - gui.screendownxy.y,
             gui.width,
             gui.height
             );

            end;

         end;

      wmWindow..wmMax:begin

         //mouse down
         if not gui.mousewasdown then
            begin
            iformrect:=area__make(a.clientarea.left,a.clientarea.top,a.clientarea.right-a.clientarea.left+1,a.clientarea.bottom-a.clientarea.top+1);
            end;

         //move
         if gui.screendraggingfine then
            begin
            a.setbounds(iformrect.left+(gui.screenmovexy.x-gui.screendownxy.x),iformrect.top+(gui.screenmovexy.y-gui.screendownxy.y),iformrect.right,iformrect.bottom);
            gui.dragstart(a.coreindex);
            alignallnow;
            paintallnow;
            end;

         end;
      end;//case
      end;
   end;

//mouse up
if (not gui.mousedown) and gui.mousewasdown then
   begin
   //drag stop
   gui.dragstop;

{
   //.double click -> to maximise the main window - 27dec2024
   if xishead and gui.mouseleft and ((idownindex<0) or (idownindex=tsiAppicon) or (idownindex=tsiAppcap)) and gui.mousedbclick and vidoubleclicks and xwindow(a) and (a.winstyle=wmfullwin) then
      begin
      xcmd(tsiMax);
      ///if (gui.gstate=gsNormal) then xcmd(tsiMax) else xcmd(tsiNor);
      end;//case
}//xxxxxxxxxxxxxxxxxxxx

   //click + reset + paint
   xclickindex:=idownindex;
   idownindex:=-1;//release the button -> prevents painting of button down action whilst another dialog is ontop - 05sep2020
   ihoverindex:=-1;
   xmustpaint:=true;

   setfocus;//14jul2025
   end;

//xmustpaint
if xmustpaint then paintnow;
except;end;

//click the button -> ignore drag status for "tsiClose" and "tsiAppIcon..tsiAppCap" -> makes toolbar buttons more usable under user load - 19jul2025
try
if gui.mouseupstroke and (xclickindex>=0) and enabled and xok(xclickindex) and ienableds[xclickindex] and ivisibles[xclickindex] and gui.mouseleft and ( (not gui.mousedragging) or ((xclickindex>tsiAppcap) and (xclickindex<>tsiClose)) ) then
   begin
   xmustreset:=true;
   xclickbutton(xclickindex);
   end;
except;end;
try
//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);

//xmustreset -> resets AND repaints the toolbar after a click event -> removes highlight text color in some color schemes restoring the toolbar back to pre-click visuals - 20mar2022
if xmustreset then
   begin
   idownindex:=-1;
   ihoverindex:=-1;
   paintnow;
   end;
except;end;
end;

function tbasictoolbar.canmovewindow:boolean;//20jul2025, 14jul2025
var
   a:tpoint;
   i:longint;
begin
a:=translatexy(low__getcursorposb);//not a screen buffer coordinate, but a clientspace coordinate (0..clientwidth-1, 0..clientheight-1) - 20jul2025

//was: if area__within2(paintarea,a) then
if area__within2(clientspace,a) then
   begin

   i:=xfindb(a.x,a.y);
   result:=(i=-1) or (i=tsiAppicon) or (i=tsiAppcap);

   //unhighlight item on toolbar - 18jan2025
   if result and low__setint(ihoverindex,-1) then paintnow;

   end
else result:=false;

end;

procedure tbasictoolbar.xclickbutton(xindex:longint);
var
   a:tbasiccontrol;
   xmustclick:boolean;

   procedure xclicks;
   begin
   gui.closelock;//prevent shutdown of system while proc in use - 03apr2021
   try
   if assigned(fonclick) then fonclick(self);
   if assigned(fonclick2) then fonclick2(self,'',ocode,ocode2,otepcolor);
   except;end;
   gui.closeunlock;
   end;
begin
try

if enabled and xok(xindex) and ienableds[xindex] and ivisibles[xindex] then
   begin

   xmustclick    :=false;
   oindex        :=xindex;
   ocode         :=bcode[xindex];
   ocode2        :=bcode2[xindex];
   otepcolor     :=clnone;//not used
   otepcolor2    :=clnone;//not used

   //special internally managed "code2" links
   if      strmatch(strcopy1(ocode2,1,low__len32(scpage)),scpage) then parentpage:=strcopy1(ocode2,low__len32(scpage)+1,low__len32(ocode2))//"page:" - 22apr2020
   else if strmatch(strcopy1(ocode2,1,low__len32(scdlg)),scdlg) then
      begin
      if gui.xdlg(a) then
         begin

         a.ocode     :=ocode;
         a.ocode2    :=strcopy1(ocode2,low__len32(scdlg)+1,low__len32(ocode2));
         a.visible   :=false;

         end;
      end
   //.sys:options -> show options
   else if strmatch(ocode2,scoptions) then gui.xshowoptions
   //.sys:help -> show help
   else if strmatch(ocode2,schelp) then gui.xshowhelp
   //.sys:about -> show about
   else if strmatch(ocode2,scabout) then gui.xshowabout
   //.sys:splash -> show splash
   else if strmatch(ocode2,scsplash) then gui.xshowsplash
   //.sys:mixer -> show mixer
   else if strmatch(ocode2,scmixer) then low__showvol
   //.sys:find -> signal system find handler var - 18feb2023
   else if strmatch(ocode2,scFindpop)  then sysfind_cmd:='find.pop'
   else if strmatch(ocode2,scfind) then sysfind_cmd:='find'
   //.urls - 20jul2024
   else if strmatch(ocode2,scVisitPortal) and (app__info('url.portal')<>'') then runlow(app__info('url.portal'),'')
   else if strmatch(ocode2,scVisitProgram) and (app__info('url.software')<>'') then runlow(app__info('url.software'),'')
   //.sys:ontop -> toggle ontop
   else if strmatch(ocode2,scontop) then
      begin
      syssettings.b['ontop']:=not syssettings.b['ontop'];
      viSyncandsave;
      end
   //.sys:max -> toggle fullscreen
//   else if strmatch(ocode2,scmax) then gui.fullscreen:=not gui.fullscreen//15mar2022
   else if strmatch(ocode2,scmax) then
      begin
      if (gui.state<>'f') then gui.state:='f' else gui.state:='n';
      end
   //.window head buttons
   else if (ocode2='winhead.f') then xcmd(tsiFull)
   else if (ocode2='winhead.-') then xcmd(tsiMin)
   else if (ocode2='winhead.+') then xcmd(tsiMax)
   else if (ocode2='winhead.x') then xcmd(tsiClose)
   else if (ocode2='winhead.m') then xcmd(tsiMenu)
   //.event
   else xmustclick:=true;

   //click events
   if xmustclick or oclickthru then xclicks;//19jun2022

   end;
except;end;
end;

function tbasictoolbar.xcapok(xindex:longint):boolean;
begin
result:=((istyle=0) or (istyle=2)) and xok(xindex) and ivisibles[xindex] and (icap[xindex]<>'');
end;

function tbasictoolbar.xcapok2(xindex:longint;xallowemptyCAP:boolean):boolean;
begin
result:=((istyle=0) or (istyle=2)) and xok(xindex) and (xallowemptyCAP or (icap[xindex]<>''));
end;

function tbasictoolbar.xtepok(xindex:longint):boolean;
begin
result:=((istyle=0) or (istyle=1)) and xok(xindex) and ivisibles[xindex] and (piw[xindex]>=1) and (pih[xindex]>=1) and (itep[xindex]<>tepnone);
end;

function tbasictoolbar.xtepok2(xindex:longint):boolean;
begin
result:=((istyle=0) or (istyle=1)) and xok(xindex) and (piw[xindex]>=1) and (pih[xindex]>=1) and (itep[xindex]<>tepnone);
end;

function tbasictoolbar.maketitle(xcap:string):tbasictoolbar;
begin
result:=maketitle3(xcap,false,false);
end;

function tbasictoolbar.maketitle2(xcap:string;xlarge:boolean):tbasictoolbar;
begin
result:=maketitle3(xcap,xlarge,false);
end;

function tbasictoolbar.maketitle3(xcap:string;xlarge,xright:boolean):tbasictoolbar;
begin

result      :=self;
otitle      :=true;
olarge      :=xlarge;

if xright then halign:=2 else oheadalign:=true;

ibordersize :=0;
caption     :=xcap;
iappcap     :=false;
iappicon    :=false;
iwmen       :=false;
iwfull      :=false;
iwclo       :=false;
iwmin       :=false;
iwmax       :=false;
iishead     :=false;

end;

function tbasictoolbar.makelinksSubtle:tbasictoolbar;//11feb2023
begin
result:=self;
otitle:=false;
olarge:=false;
halign:=0;
ibordersize:=0;
odownsubtle:=true;
end;

function tbasictoolbar.makeWinhead(xwinallbuttons:boolean):tbasictoolbar;//26dec2024
begin
result:=makeWinhead2(true,xwinallbuttons,true,true,tepIcon24);
end;

function tbasictoolbar.makeWinhead__status_small:tbasictoolbar;//26dec2024
begin
result:=makeWinhead2(false,false,false,false,tepIcon24);
end;

function tbasictoolbar.makeWinhead2(xclose,xall,xappicon,xlarge:boolean;xapptep:longint):tbasictoolbar;//26dec2024
var
   str1:string;

   procedure s(x,xtep:longint;y:boolean;xcode2,h:string);
   begin
   ivisibles[x]:=y;
   ienableds[x]:=y;
   itep[x]     :=xtep;
   ibuthelp[x] :=h;
   icode2[x]   :=xcode2;
   end;
   
begin

result      :=self;
oflatback   :=true;
normal      :=false;
oautoheight :=true;
otitle      :=false;
olarge      :=xlarge;
oheadalign  :=true;//use system "viheadalign"
ibordersize :=0;
odownsubtle :=false;
ihelp       :=programslogan+insstr(' | ',programslogan<>'')+'Click and drag to position window | Press the "F2" key to restore defaults';
iishead     :=true;
iappcap     :=true;
iappicon    :=xappicon;
iwmen       :=xall;
iwfull      :=xall;
iwclo       :=xclose or xall;
iwmin       :=xall;
iwmax       :=xall;

s(tsiAppicon,tepNone   ,true,'','');
s(tsiAppcap,tepNone    ,true,'','');
s(tsiMenu,tepInf       ,iwmen,'winhead.m','App|Show app menu');
s(tsiFull,tepFull      ,iwfull,'winhead.f','App|Enter or exit fullscreen mode');
s(tsiMin,tepMin        ,iwmin,'winhead.-','App|Minimise app to taskbar');
s(tsiMax,tepMax        ,iwmax,'winhead.+','App|Maximise or normalise app window');

//.help
if (rootparent<>nil) and (rootparent.winstyle=wmFullwin) then str1:='Exit|Close app' else str1:='App|Close window';
s(tsiClose,tepClo      ,iwclo,'winhead.x',str1);

tep         :=xapptep;
caption     :='';//set internally to programname

end;

function tbasictoolbar.getalignheight(xclientwidth:longint):longint;
var
   bs:longint;
begin

bs     :=findbordersize;
result :=xmapitems( frcmin32(xclientwidth,1) ,bs ,ominrows ,oautoheight) + (2*bs);

end;

function tbasictoolbar.findhelp(xindex:longint):string;
begin
if (xindex=tsiAppicon) or (xindex=tsiAppcap) then result:=helpline
else if (xindex>=0) and (xindex<=high(puse)) then result:=ibuthelp[xindex]
else                                              result:='';
end;

function tbasictoolbar.xishead:boolean;
begin
result:=iishead;
end;

function tbasictoolbar.xmapitems(xclientwidth,xbordersize,xminrowcount:longint;xautoheight:boolean):longint;//05jun2025: properly center small button contents, 20may2025, 04may2025, 21mar2025: fixed one item on 1st line wrap issue, 06jan2025
label
   redo,skipend;
const
   teph=24;
var
   xminwidth,vpad,lp,xwinbarLeft,lw,lw2,lh,dx,dx2,dy,dinw,dw,dh,xlinecount,pad1,pad2,xzoom:longint;
   xsepwidth,xlineheight,xhalign,int1,xshiftby,v,cw,lusecount,p:longint;
   dpartline:single;

   function xfindused(xindex:longint):boolean;
   begin

   case xindex of
   tsiUser..high(puse) :result:=ivisibles[xindex] and ((icap[xindex]<>'') or (itep[xindex]<>tepNone));
   tsiAppCap           :result:=iappcap or otitle;
   tsiAppIcon          :result:=iappicon;
   tsiMenu             :result:=iwmen;
   tsiFull             :result:=iwfull;
   tsiMin              :result:=iwmin;
   tsiMax              :result:=iwmax;
   tsiClose            :result:=iwclo;
   else                 result:=false;
   end;//case

   end;

   function xfindimage(xindex:longint;var xtep,xw,xh:longint):boolean;
   begin

   case xindex of
   tsiAppIcon            :xtep:=low__aorb(tepNone,iapptep,iappicon);
   tsiAppcap..high(puse) :xtep:=low__aorb(tepNone,itep[xindex],ivisibles[xindex]);
   else                   xtep:=tepNone;
   end;//case

   //get
   if (xtep=tepNone) then
      begin

      xw     :=0;
      xh     :=0;
      result :=false;

      end
   else if (xindex=tsiAppicon) then
      begin

      if tep__info(xtep,xw,xh) and (xw>=1) and (xh>=1) then
         begin

         xh      :=teph*xzoom;
         xw      :=teph*xzoom;
         result  :=true;

         end
      else
         begin

         xh      :=0;
         xw      :=0;
         result  :=false;

         end;
      end
   else if tep__info(xtep,xw,xh) then
      begin

      result :=true;

      end
   else
      begin

      xw     :=0;
      xh     :=0;
      result :=false;

      end;
   end;

   procedure xfindtext(xindex:longint;var xf,xw,xh:longint);
   var
      xcap:string;
   begin

   //.xcap
   case xindex of
   tsiUser..high(puse) :if ivisibles[xindex] then xcap:=xcountcap(xindex) else xcap:='';
   tsiAppcap           :xcap:=icap[xindex];
   else                 xcap:='';
   end;//case

   //.filter
   if (xindex>=tsiUser) then
      begin

      if (xcap=tstSep) then
         begin

         xf   :=info.rfn;
         xw   :=1;
         xh   :=1;
         xcap :='';

         end
      else if (xcap=tstNewline) then
         begin

         xf   :=info.rfn;
         xw   :=1;
         xh   :=1;
         xcap :='';

         end
      else if (xcap=tstNewpartline) then
         begin

         xf   :=info.rfn;
         xw   :=1;
         xh   :=1;
         xcap :='';

         end
      else
         begin

         xf   :=low__aorb(info.rfn,info.rfb,ititle[xindex]);//17mar2025
         xw   :=resfont__textwidth(xf,xcap);
         xh   :=resfont__height(xf);

         end;

      end

   else if (xindex=tsiAppcap) and (xcap<>'') then
      begin

      if      iappcap     then xf:=info.rfn//12dec2025, 16may2025
      else if otitle      then xf:=low__aorb(info.rft,info.rft2,olarge)//20feb2026
      else                     xf:=info.rfn;

      xw                       :=resfont__textwidth(xf,xcap);
      xh                       :=resfont__height(xf);

      end
   else
      begin

      xf  :=info.rfn;
      xw  :=0;
      xh  :=0;

      end;

   end;

   function xfindwidth(xindex:longint;var xinner:longint):longint;
   var
      v:longint;

      procedure xset1(xw:longint);
      begin
      result:=frcmin32(xw,xminwidth);
      xinner:=xw;
      end;

      procedure xset2(xw,xinside:longint);
      begin
      result:=frcmin32(xw,xminwidth);
      xinner:=frcmax32(xinside,xw);
      end;
   begin

   case xindex of
   tsiUser..high(puse):begin

      v:=piw[xindex] + insint(pad1 , (piw[xindex]>=1) and (ptw[xindex]>=1) ) + ptw[xindex];//05jun2025: centers small button contents properly

      case isize[xindex] of
      0          :result:=v;
      1..maxint  :result:=round32(isize[xindex]*vifontwidthratio);//fixed -> but scales width ZOOM and Fontsize - 30may2021
      else        result:=round32((-isize[xindex]/100)*frcmin32(cw-pad2,1));//26may2025: fixed, was missing the "-pad2" -> percentage
      end;//case

      xset2(result,v);
      end;

   tsiAppicon        :xset1(piw[xindex]);
   tsiAppcap         :xset1(ptw[xindex]);
   tsiMenu..tsiClose :xset1(piw[xindex]);
   else               xset1(0);
   end;//case
   end;

   procedure xalignitems;
   var
      i,xshift:longint;
   begin

   //get
   case xhalign of
   1   :xshift:=lw div 2;//center
   2   :xshift:=lw;//right
   else xshift:=0;
   end;//case

   //set - 05feb2025: updated from ">=1" to "<>0" for better right alignment
   if (xshift<>0) then
      begin

      for i:=frcmin32(lp,tsiUser) to (p-1) do if puse[i] then
      begin

      inc(poa[i].left  ,xshift);
      inc(poa[i].right ,xshift);
      inc(pa[i] .left  ,xshift);
      inc(pa[i] .right ,xshift);

      end;//i

      end;

   lp:=p;
   end;

   procedure xnewline2(xforcedown,xpartline:boolean);
   label
      redo;
   var
      xonce:boolean;
   begin

   //lw2
   if (lw2>=1) and (not xforcedown) then
      begin

      xalignitems;

      lusecount :=0;
      lw        :=lw2;
      lw2       :=0;
      dx        :=dx2;

      exit;

      end;

   //xautoheight=false -> keep using current line -> no more wrapping allowed
   if (not xautoheight) and (xlinecount>=1) then
      begin

      //xalignitems;
      inc(xlinecount);
      lusecount:=0;

      exit;

      end;

   //init
   xonce:=true;
   xalignitems;

   redo:

   inc(xlinecount);

   lusecount :=0;
   lw        :=frcmin32(cw,0);
   lw2       :=0;
   dx        :=0;
   dx2       :=0;

   if xpartline then lh:=round(lh*dpartline)+insint(vpad,xlinecount>=2);//23mar2025

   inc(dy,lh+xshiftby);
   
   if (xlinecount>=2) then inc(dy,vpad);

   lh        :=xlineheight;

   //get
   if (xlinecount<=1) and (lw>=1) then
      begin

      if iappcap and viheadcenter then
         begin

         lw   :=frcmin32(poa[tsiAppcap].left-poa[tsiAppicon].right-1,0);
         dx   :=poa[tsiAppicon].right+1;
         lw2  :=frcmin32(xwinbarLeft-poa[tsiAppcap].right-1,0);
         dx2  :=poa[tsiAppcap].right+1;

         end

      else if iappcap or iappicon or otitle then
         begin

         dx   :=largest32(poa[tsiAppicon].right+1,poa[tsiAppcap].right+1);
         lw   :=(xwinbarLeft+1)-dx;
         lw2  :=0;
         dx2  :=0;

         end;

      end;

   //auto new line if this one is 0px wide
   if xonce and xautoheight and (xlinecount=1) and (cw>=1) and (lw=0) and (lw2=0) then
      begin

      xonce:=false;
      goto redo;

      end;
   end;

   procedure xnewline(xforcedown:boolean);
   begin

   xnewline2(xforcedown,false);

   end;
begin

//defaults
result        :=0;
dpartline     :=low__aorbD64(0,opartline,viscale>=1);
xlinecount    :=0;
xzoom         :=vizoom;
pad1          :=scale__px1(4,0);//space between image and caption (if both present)
pad2          :=scale__px1(ohbutpad,0);//space between last item and next item
vpad          :=scale__px1( 5 * oscalevpad * frcmaxD64(viscale,1) , 0 );
xhalign       :=find__halign;
lw            :=0;
lw2           :=0;
lh            :=0;
dx            :=min32;
dx2           :=min32;
dy            :=0;
xshiftby      :=frcrange32(ojump,0,ohpad)*xzoom;//space to shift down and to right when "down" or "marked"
xsepwidth     :=scale__px1( 20*oscalesep ,0);
xminwidth     :=24*xzoom;

//common lineheight        -> use viscale again to esculate scale reduction
xlineheight   :=frcmin32( trunc( 0.96 * oscaleh * vilineheight44 ) ,vitepheight20 );

//sync
icap[tsiAppcap]:=#32 + caption + insstr('*',omodified) + icaption2;

//init
for p:=0 to high(puse) do
begin

if xfindused(p) then
   begin

   xfindimage(p,pit[p],piw[p],pih[p]);
   xfindtext(p,ptf[p],ptw[p],pth[p]);

   end
else
   begin

   //.image
   piw[p]:=0;
   pih[p]:=0;
   pit[p]:=tepNone;

   //.text
   ptw[p]:=0;
   pth[p]:=0;
   ptf[p]:=0;

   end;

//.position
poa[p] :=area__make(0,0,0,0);
pa[p]  :=poa[p];
puse[p]:=false;

end;//p


cw:=frcmin32(xclientwidth-(2*findbordersize),0);
if (cw<=0) then goto skipend;


//special items ----------------------------------------------------------------
lh           :=xlineheight;
dx           :=cw-1-xshiftby;
xwinbarLeft  :=dx;

for p:=tsiClose downto tsiMenu do if xfindused(p) then
   begin

   dw             :=frcmin32(piw[p],xlineheight);
   dh             :=frcmin32(pih[p],xlineheight);

   //was:
   //inc(dw,xlineheight);//without the vpadding

   poa[p].right   :=dx;
   poa[p].left    :=poa[p].right-(dw-xzoom);
   poa[p].top     :=0;
   poa[p].bottom  :=poa[p].top+dh-xzoom-xshiftby;
   pa[p]          :=poa[p];

//was:   dec(dx,poa[p].right-poa[p].left+1+(5*xzoom)+insint(2*pad2,p=tsiClose));
//was:   dec(dx,poa[p].right-poa[p].left+1+(5*xzoom));

   dec(dx,poa[p].right-poa[p].left+1);

   xwinbarLeft    :=smallest32(xwinbarLeft,dx);//poa[p].left);
   puse[p]        :=true;

   end;//p

if iappicon and xfindused(tsiAppicon) then
   begin

   pa[tsiAppicon].left    :=0;
   pa[tsiAppicon].right   :=pa[tsiAppicon].left+piw[tsiAppicon]-xzoom;
   pa[tsiAppicon].top     :=0;
   pa[tsiAppicon].bottom  :=pih[tsiAppicon]-xzoom;

   poa[tsiAppicon]        :=pa[tsiAppicon];
   poa[tsiAppicon].top    :=0;
   poa[tsiAppicon].bottom :=lh-1+xshiftby;
   poa[tsiAppicon].right  :=pa[tsiAppicon].left+largest32(piw[tsiAppicon],pih[tsiAppicon])+9*xzoom;//06jan2025: bit more space to center of app icon V and H

   puse[tsiAppicon]        :=true;

   end;

if (iappcap or otitle) and xfindused(tsiAppcap) then
   begin

   //variable width jitter stabaliser -> slightly wider text area than required allows for minor text adjustments without realignment of toolbar
   int1  :=frcmin32(pth[tsiAppcap],1);
   v     :=(ptw[tsiAppcap] div int1)*int1;

   if (v<ptw[tsiAppcap]) then inc(v,int1);

   if viheadcenter and (not otitle) then
      begin

      poa[tsiAppcap].left    :=frcmin32( ((cw-v) div 2) - (2*pad2),poa[tsiAppicon].right+1);
      poa[tsiAppcap].right   :=poa[tsiAppcap].left+v-1+(4*pad2);
      poa[tsiAppcap].top     :=0;
      poa[tsiAppcap].bottom  :=lh-1+xshiftby;
      pa[tsiAppcap]          :=poa[tsiAppcap];

      end
   else
      begin
      poa[tsiAppcap].left    :=poa[tsiAppicon].right+1;

      //.indent slightl for titles and labels
      if (not iappcap) then poa[tsiAppcap].left:=frcmin32(poa[tsiAppcap].left,xbordersize+8*xzoom);

      poa[tsiAppcap].right   :=poa[tsiAppcap].left+v-1+(0*pad2);
      poa[tsiAppcap].top     :=0;
      poa[tsiAppcap].bottom  :=lh-1+xshiftby;
      pa[tsiAppcap]          :=poa[tsiAppcap];

      end;

   puse[tsiAppcap]:=true;

   end;


//map items --------------------------------------------------------------------
dx         :=0;
dx2        :=0;
dy         :=0;
lh         :=0;
lw         :=0;
lw2        :=0;
p          :=tsiUser;
lusecount  :=0;
lp         :=-1;

xnewline(false);

lp         :=-1;
lp         :=tsiUser;

for p:=tsiUser to high(puse) do if xfindused(p) then
   begin

   if (p<>tsiAppcap) and (icap[p]='-') then
      begin
      dw  :=xsepwidth;
      dinw:=dw;
      end
   else if (isize[p]<0) then dw:=xfindwidth(p,dinw)//25may2025 - no padding for percentage based buttons
   else                      dw:=(pad1*3)+xfindwidth(p,dinw);

   redo:

   if      (icap[p]=tstNewline)     then xnewline(true)//force a new line
   else if (icap[p]=tstNewpartline) then xnewline2(true,true)//force a new part-line
   else if (dw>lw) and (xlinecount=1) and (iappicon or iappcap or otitle) then
      begin
      //special case: a toolbar with only one item on first line SHOULD stay remain that item on the line unless it's an app head with app icon and window.system buttons (e.g. min/max/close) - 21mar2025
      if (lusecount>=1) or (iappicon or iappcap or iwmen or iwfull or iwclo or iwmin or iwmax) then
         begin
         xnewline(false);
         goto redo;
         end;
      end
   else if (dw>lw) and (lusecount>=1) then
      begin
      xnewline(false);
      end;

   if ((pth[p]>=1) or (pih[p]>=1)) and ((icap[p]<>tstNewline) and (icap[p]<>tstNewpartline)) then//23mar2025
      begin

      dh:=xlineheight;//frcmax32(largest32(largest32(pih[p],pth[p]),xlineheight),lh);
      //was: dw:=frcmax32(dw,lw);//for percentage based items that may use up more line width than is available, even at one item per line
      //dw line above caused "img+caption" elements to squeeze together when toolbar wrapped over a narrow width (line width) - 11jan2025

      //.outside area
      poa[p].left   :=dx;
      poa[p].right  :=dx+dw-1;
      poa[p].top    :=frcmin32(dy+lh-dh-xshiftby,0);
      poa[p].bottom :=poa[p].top+dh-1-xzoom-xshiftby;


      //.inner area
      pa[p].left    :=poa[p].left+((poa[p].right-poa[p].left+1-dinw) div 2);
      pa[p].right   :=frcmax32(pa[p].left+dinw,poa[p].right);
      pa[p].top     :=poa[p].top;
      pa[p].bottom  :=poa[p].bottom;

      puse[p]       :=true;

      dec(lw,dw+pad1);
      inc(dx,dw+pad1);
      inc(lusecount);

      end;
   end;//p

//alignment.finalise
if (lusecount>=1) then
   begin

   p:=high(pa);
   xalignitems;

   end;

//xminrowcount
if (xminrowcount>=1) and (xlinecount<xminrowcount) then
   begin

   for p:=xlinecount to xminrowcount do
   begin

   inc(dy,lh+xshiftby);
   lh:=xlineheight;

   end;

   lusecount:=1;

   end;


//finish
result:=dy + insint(lh,lusecount>=1);//lusecount => number of items used on the last line (current line)

//at least one whole lineheight tall - 12jan2025
result:=frcmin32(result,lh+xshiftby);

//head/title has no items thus no height at this point so make some
result:=largest32(result,xlineheight);

//adjust for bordersize
if (xbordersize<>0) then for p:=0 to high(puse) do if puse[p] then
   begin
   inc(poa[p].left,xbordersize);
   inc(poa[p].right,xbordersize);
   inc(poa[p].top,xbordersize);
   inc(poa[p].bottom,xbordersize);

   inc(pa[p].left,xbordersize);
   inc(pa[p].right,xbordersize);
   inc(pa[p].top,xbordersize);
   inc(pa[p].bottom,xbordersize);
   end;//p

skipend:
end;

function tbasictoolbar.xcountcap(xindex:longint):string;
begin
result:=icap[xindex];
if ocountdown and (icountdown[xindex]>=1) then result:=result+' - '+k64(icountdown[xindex])+'s';//05sep2020
end;

procedure tbasictoolbar._onpaint(sender:tobject);//05jun2025, 15may2025
const
   teph=24;

var
   s:tclientinfo;
   ppa,doa,da:twinrect;
   dbold,dflash,xflash,denabled,ddown,xhavefocus,xactive:boolean;
   dcolor,dcolorb,aw,ah,p,pad1,pad2,xshiftby:longint;

begin
try
//init
xroundMode_StartOverride(rmAll);
infovars(s);

pad1       :=scale__px1(4,0);//space between image and caption (if both present)
pad2       :=scale__px1(ohbutpad,0);//space between last item and next item

xshiftby    :=frcrange32(ojump,0,ohpad)*s.zoom;//space to shift down and to right when "down" or "marked"
xflash      :=iflash;

//.toggle head.active mode - 23jan2025
if   xishead then xactive:=gui.active and (xwindowindex=gui.winfocus)
else              xactive:=true;

//map items again ready for paint
xmapitems(s.ci.right-s.ci.left+1,s.bs,ominrows,oautoheight);

//cls
ffillArea(s.cs,s.back,false);

//paint items
for p:=0 to high(puse) do
begin

if puse[p] then
   begin

   xhavefocus    :=((p=ihoverindex) or (p=idownindex) or imarked[p] or ihighlight[p]) and (p<>tsiAppicon) and (p<>tsiAppcap) and s.e and ienableds[p];
   ddown         :=xhavefocus and ((p=idownindex) or imarked[p]) and (not ititle[p]);
   dbold         :=ititle[p];
   doa           :=poa[p];
   da            :=pa[p];
   denabled      :=s.e and ( (p<tsiUser) or ienableds[p] );
   dflash        :=xflash and (p>=tsiUser) and iflasher[p];

   dcolor        :=icolor[p];//optional custom color - 13jul2025
   if (dcolor=clnone) then dcolor:=s.font;

   dcolorb       :=icolorb[p];//optional 2nd custom color - 13jul2025
   if (dcolorb=clnone) then dcolorb:=s.line;//used as a border

   if ddown and (p<>tsiAppicon) and (p<>tsiAppcap) then
      begin
      doa:=low__shiftarea(doa,xshiftby,xshiftby);
      da :=low__shiftarea(da ,xshiftby,xshiftby);
      end;

   //highlight
   if xhavefocus and (not ititle[p]) then
      begin

      ffillArea(doa,low__aorb(s.hover,clred,p=tsiClose),s.r);

      end;

   //progress bar
   if (ipert[p]>=1) then
      begin

      ppa:=doa;
      ppa.right:=frcrange32(ppa.left+round((ppa.right-ppa.left)*(ipert[p]/100)),ppa.left,ppa.right);

      ffillArea(ppa,s.hover2,s.r);

      end;

   //image
   if ((pit[p]<>tepNone) or (p=tsiAppicon)) and (not dflash) then
      begin

      if (p=tsiAppicon) then
         begin

         //.draw using direct TEP data -> faster and simplier -> fallback to app icon "tepIcon24" when supplied tep is too tall to fit - 13dec2025, 25may2025
         if tep__info(iapptep,aw,ah) then
            begin

            ftep(iapptep,doa.left+((doa.right-doa.left+1-aw) div 2),doa.top+((doa.bottom-doa.top+1-ah) div 2),dcolor,true);

            end;

         end
      else if (p>=tsiMenu) and (p<=tsiClose) then
         begin

         ftep(pit[p],da.left+((da.right-da.left+1-piw[p]) div 2),da.top+((da.bottom-da.top+1-pih[p]) div 2),low__aorb(dcolor,clwhite,xhavefocus and (p=tsiClose)),true);

         end

      else ftep(pit[p],da.left,da.top+((da.bottom-da.top+1-pih[p]) div 2),dcolor,denabled);//15mar2026

      end;

   //text
   if (p=tsiAppcap) then
      begin

      ftext( s.back ,da,da.left,da.top+((da.bottom-da.top+1-pth[p]) div 2),s.font,'',icap[p],ptf[p] ,true);

      end
   else if (icap[p]='-') then
      begin

      ppa        :=da;
      ppa.left   :=da.left+((da.right-da.left+1) div 2);
      ppa.right  :=ppa.left;
      ffillArea(ppa,s.sep,false);

      end

   else if (p<tsiUser) then
      begin

      //was: ldt2(s.back,da,da.right-ptw[p],da.top,s.font,icap[p],ptf[p],s.f,false,false,false,false,s.r);
      ftext( s.back ,da,da.right-ptw[p],da.top,s.font,'',icap[p],ptf[p] ,true);

      end
   else
      begin

      //was: ldt2(xback,da,da.right-ptw[p],da.top+((da.bottom-da.top+1-pth[p]) div 2),dfont,xcountcap(p),ptf[p],xfeather,false,false,dunderline,false,xround);
      //was: ldt2(s.back,da,da.left+(da.right-da.left+1-ptw[p]),da.top+((da.bottom-da.top+1-pth[p]) div 2),s.font,xcountcap(p),ptf[p],s.f,false,false,false,false,s.r);

      ftext( s.back ,da,da.left+(da.right-da.left+1-ptw[p]),da.top+((da.bottom-da.top+1-pth[p]) div 2),s.font,'',xcountcap(p),ptf[p] ,denabled);

      end;
   end;

end;//p

except;end;

//stop
xroundMode_StopOverride;

end;

procedure tbasictoolbar.xcmd(x:longint);
label
   skipend;
var
   a:tbasiccontrol;
begin
try
//init
if not xwindow(a) then exit;
if gui__closing then exit;//17nov2023

//window commands
if (a.winstyle=wmfullwin) then
   begin
   case x of
   tsiFull:if iwfull then
      begin
      if (gui.state<>'f') then gui.state:='f' else gui.state:='n';
      end;
   tsiMin:if iwmin   then gui.state:='-';
   tsiMax:if iwmax   then
      begin
      if (gui.state='f') or (gui.state='+') then gui.state:='n' else gui.state:='+';
      end;
   tsiMenu:if iwmen then gui.showappmenu(iwmax);
   tsiClose:if iwclo then
      begin
      if gui.mainwindow then siCloseprompt(gui) else gui.state:='h';
      //check
      if app__closeinited then goto skipend;
      end;
   end;//case
   end
else
   begin
   case x of
   tsiMenu:if iwmen then gui.showappmenu(iwmax);
   tsiClose:if iwclo then a.visible:=false;
   end;//case
   end;
//sync
itep[tsiMax] :=low__aorb(tepMaximise,tepNormal,gui.state<>'n');
itep[tsiFull]:=low__aorb(tepFull,tepFullExit,gui.state='f');

skipend:
except;end;
end;

function tbasictoolbar.sadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xsize,xalign:longint):longint;
begin
result:=cadd4(xcap,xtep,xcode,xcode2,xhelp,true,true,false,false,0,xsize,xalign);
end;

function tbasictoolbar.csadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xsize:longint):longint;
begin
result:=cadd4(xcap,xtep,xcode,xcode2,xhelp,true,true,false,false,0,xsize,taC);
end;

function tbasictoolbar.hcsadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xsize:longint):longint;//highlighter with button padding - 05jun2021
begin
result:=cadd4(xcap,xtep,xcode,xcode2,xhelp,true,true,false,true,0,xsize,taC);
end;

function tbasictoolbar.rsadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xsize:longint):longint;
begin
result:=cadd4(xcap,xtep,xcode,xcode2,xhelp,true,true,false,false,0,xsize,taR);
end;

function tbasictoolbar.lsadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xsize:longint):longint;
begin
result:=cadd4(xcap,xtep,xcode,xcode2,xhelp,true,true,false,false,0,xsize,taL);
end;

function tbasictoolbar.add(xcap:string;xtep,xcode:longint;xcode2,xhelp:string):longint;
begin
result:=cadd4(xcap,xtep,xcode,xcode2,xhelp,true,true,false,false,0,0,0);
end;

function tbasictoolbar.add2(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;ximgright:boolean):longint;
begin
result:=cadd4(xcap,xtep,xcode,xcode2,xhelp,true,true,ximgright,false,0,0,0);
end;

function tbasictoolbar.add3(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xenabled,xvisible,ximgright:boolean):longint;
begin
result:=cadd4(xcap,xtep,xcode,xcode2,xhelp,xenabled,xvisible,ximgright,false,0,0,0);
end;

function tbasictoolbar.cadd(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xcountdown:longint):longint;
begin
result:=cadd4(xcap,xtep,xcode,xcode2,xhelp,true,true,false,false,xcountdown,0,0);
end;

function tbasictoolbar.cadd2(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;ximgright:boolean;xcountdown:longint):longint;
begin
result:=cadd4(xcap,xtep,xcode,xcode2,xhelp,true,true,ximgright,false,xcountdown,0,0);
end;

function tbasictoolbar.cadd3(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xenabled,xvisible,ximgright:boolean;xcountdown:longint):longint;
begin
result:=cadd4(xcap,xtep,xcode,xcode2,xhelp,xenabled,xvisible,ximgright,false,xcountdown,0,0);
end;

function tbasictoolbar.cadd4(xcap:string;xtep,xcode:longint;xcode2,xhelp:string;xenabled,xvisible,ximgright,xbutpad:boolean;xcountdown,xsize,xalign:longint):longint;
begin

//defaults
result:=-1;

try
//check
if not xok(iaddcount) then exit;

//get
icap[iaddcount]:=xcap;

if (xtep<>itep[iaddcount]) then
   begin

   itep[iaddcount]:=xtep;
   tep__info(xtep,piw[iaddcount],pih[iaddcount]);

   end;

ititle[iaddcount]        :=false;
isize[iaddcount]         :=xsize;//30may2021
icountdown[iaddcount]    :=xcountdown;
icode[iaddcount]         :=xcode;
icode2[iaddcount]        :=xcode2;
ibuthelp[iaddcount]      :=xhelp;
ienableds[iaddcount]     :=xenabled;
ivisibles[iaddcount]     :=xvisible;
ihighlight[iaddcount]    :=false;
ipert[iaddcount]         :=0;//07jul2021

//set
result:=iaddcount;

//inc
inc(iaddcount);
except;end;
end;

procedure tbasictoolbar.sethalign(x:longint);
begin
oheadalign:=false;
ihalign:=frcrange32(x,0,2);//0=left, 1=center, 2=right
end;

function tbasictoolbar.find__halign:longint;//06jan2025
begin
if oheadalign then result:=viheadalign
else               result:=ihalign;
end;

procedure tbasictoolbar.clear;//13jul2025, 22sep2020
var
   p:longint;
begin
iaddcount:=tsiUser;
for p:=low__aorb(0,tsiUser,xishead) to high(icap) do clear1(p);
end;

procedure tbasictoolbar.clear1(p:longint);//13jul2025
begin

if (p>=0) and (p<=high(icolor)) then
   begin
   puse[p]         :=false;
   piw[p]          :=0;
   pih[p]          :=0;
   icolor[p]       :=clnone;//off -> use system font color by default - 13jul2025
   icolorb[p]      :=clnone;//off -> use system font color by default - 13jul2025
   ititle[p]       :=false;
   icap[p]         :='';
   isize[p]        :=0;//30may2021
   ipert[p]        :=0;//07jul2021
   itep[p]         :=tepnone;
   icode[p]        :=0;
   icode2[p]       :='';
   ibuthelp[p]     :='';
   iref[p]         :='';
   ienableds[p]    :=false;
   ivisibles[p]    :=false;
   imarked[p]      :=false;
   ihighlight[p]   :=false;
   icountdown[p]   :=0;//off
   end;

end;

function tbasictoolbar.addsep:longint;
begin
result:=add3('-',tepnone,0,'','',true,true,false);
end;

function tbasictoolbar.addsep2(xcode2:string):longint;
begin
result:=add3('-',tepnone,0,xcode2,'',true,true,false);
end;

function tbasictoolbar.addhline:longint;//draw horizontal line under current line - 26sep2022
begin
result:=add3('*',tepnone,0,'','',true,true,false);
end;

function tbasictoolbar.newline:longint;//05jun2021
begin
result:=add3('+',tepnone,0,'','',true,true,false);
end;

function tbasictoolbar.newpartline:longint;//23mar2024
begin
result:=add3(tstNewpartline,tepnone,0,'','',true,true,false);
end;

function tbasictoolbar.xok(x:longint):boolean;
begin
result:=(x>=0) and (x<=high(icap));
end;

function tbasictoolbar.uok(x:longint):boolean;//user range
begin
result:=(x>=tsiUser) and (x<=high(icap));
end;

procedure tbasictoolbar.xsetcap(x:longint;y:string);
begin
if uok(x) then icap[x]:=y;
end;

function tbasictoolbar.xgetcap(x:longint):string;
begin
if xok(x) then result:=icap[x] else result:='';
end;

procedure tbasictoolbar.xsettep(x:longint;y:longint);
begin

if uok(x) and (y<>itep[x]) then
   begin

   itep[x]:=y;
   tep__info(itep[x],piw[x],pih[x]);

   end;

end;

function tbasictoolbar.xgettep(x:longint):longint;
begin
if xok(x) then result:=itep[x] else result:=tepnone;
end;

procedure tbasictoolbar.xsetsize(x:longint;y:longint);
begin
if uok(x) and (y<>isize[x]) then isize[x]:=y;
end;

function tbasictoolbar.xgetsize(x:longint):longint;
begin
if xok(x) then result:=isize[x] else result:=0;
end;

procedure tbasictoolbar.xsettitle(x:longint;y:boolean);
begin
if uok(x) and (y<>ititle[x]) then ititle[x]:=y;
end;

function tbasictoolbar.xgettitle(x:longint):boolean;
begin
if xok(x) then result:=ititle[x] else result:=false;
end;

function tbasictoolbar.xtextTOP(x:longint):longint;//11may2025
begin
if xok(x) then result:=pa[x].bottom-pth[x] else result:=0;
end;

procedure tbasictoolbar.setpert(x:longint;y:double);
begin
if (y<0) then y:=0 else if (y>100) then y:=100;
if uok(x) and (y<>ipert[x]) then
   begin
   ipert[x]:=y;
   paintnow;
   end;
end;

function tbasictoolbar.getpert(x:longint):double;
begin
if xok(x) then result:=ipert[x] else result:=0;
end;

procedure tbasictoolbar.xsetcountdown(x,y:longint);//05sep2020
begin
if uok(x) then icountdown[x]:=frcmin32(y,0);
end;

function tbasictoolbar.xgetcountdown(x:longint):longint;
begin
if xok(x) then result:=icountdown[x] else result:=0;
end;

procedure tbasictoolbar.xsetcode(x,y:longint);
begin
if uok(x) then icode[x]:=y;
end;

function tbasictoolbar.xgetcode(x:longint):longint;
begin
if xok(x) then result:=icode[x] else result:=0;
end;

procedure tbasictoolbar.xsetcode2(x:longint;y:string);
begin
if uok(x) then icode2[x]:=y;
end;

function tbasictoolbar.xgetcode2(x:longint):string;
begin
if xok(x) then result:=icode2[x] else result:='';
end;

procedure tbasictoolbar.xsethelp(x:longint;y:string);
begin
if uok(x) then ibuthelp[x]:=y;
end;

function tbasictoolbar.xgethelp(x:longint):string;
begin
if xok(x) then result:=ibuthelp[x] else result:='';
end;

procedure tbasictoolbar.xsetvisibles(x:longint;y:boolean);
begin
if uok(x) then ivisibles[x]:=y;
end;

function tbasictoolbar.xgetvisibles(x:longint):boolean;
begin
if xok(x) then result:=ivisibles[x] else result:=false;
end;

procedure tbasictoolbar.xsetenableds(x:longint;y:boolean);
begin
if uok(x) then ienableds[x]:=y;
end;

function tbasictoolbar.xgetenableds(x:longint):boolean;
begin
if xok(x) then result:=ienableds[x] else result:=false;
end;

procedure tbasictoolbar.xsetmarked(x:longint;y:boolean);
begin
if uok(x) then imarked[x]:=y;
end;

function tbasictoolbar.xgetmarked(x:longint):boolean;
begin
if xok(x) then result:=imarked[x] else result:=false;
end;

procedure tbasictoolbar.xsetcolor(x,y:longint);
begin
if uok(x) then icolor[x]:=y;
end;

function tbasictoolbar.xgetcolor(x:longint):longint;
begin
if xok(x) then result:=icolor[x] else result:=clnone;
end;

procedure tbasictoolbar.xsetcolorb(x,y:longint);
begin
if uok(x) then icolorb[x]:=y;
end;

function tbasictoolbar.xgetcolorb(x:longint):longint;
begin
if xok(x) then result:=icolorb[x] else result:=clnone;
end;

procedure tbasictoolbar.xsetflash(x:longint;y:boolean);
begin
if uok(x) then iflasher[x]:=y;
end;

function tbasictoolbar.xgetflash(x:longint):boolean;
begin
if xok(x) then result:=iflasher[x] else result:=false;
end;

procedure tbasictoolbar.xsethighlight(x:longint;y:boolean);//15mar2022
begin
if uok(x) then ihighlight[x]:=y;
end;

function tbasictoolbar.xgethighlight(x:longint):boolean;
begin
if xok(x) then result:=ihighlight[x] else result:=false;
end;

function tbasictoolbar.visref:string;//05jun2021
var
   p:longint;
begin
low__setlen(result,high(ivisibles)+1);
for p:=0 to high(ivisibles) do if ivisibles[p] then result[p+stroffset]:='1' else result[p+stroffset]:='0';
end;

//by code2 names ---------------------------------------------------------------
procedure tbasictoolbar.xsetvisible2(x:string;y:boolean);
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then ivisibles[int1]:=y;
end;

function tbasictoolbar.xgetvisible2(x:string):boolean;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=ivisibles[int1] else result:=false;
end;

procedure tbasictoolbar.xsetflash2(x:string;y:boolean);
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then iflasher[int1]:=y;
end;

function tbasictoolbar.xgetflash2(x:string):boolean;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=iflasher[int1] else result:=false;
end;

procedure tbasictoolbar.xsetmarked2(x:string;y:boolean);
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then imarked[int1]:=y;
end;

function tbasictoolbar.xgetmarked2(x:string):boolean;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=imarked[int1] else result:=false;
end;

procedure tbasictoolbar.xsetcolor2(x:string;y:longint);
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then icolor[int1]:=y;
end;

function tbasictoolbar.xgetcolor2(x:string):longint;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=icolor[int1] else result:=clnone;
end;

procedure tbasictoolbar.xsetcolor2b(x:string;y:longint);
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then icolorb[int1]:=y;
end;

function tbasictoolbar.xgetcolor2b(x:string):longint;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=icolorb[int1] else result:=clnone;
end;

procedure tbasictoolbar.xsethighlight2(x:string;y:boolean);
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then ihighlight[int1]:=y;
end;

function tbasictoolbar.xgethighlight2(x:string):boolean;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=ihighlight[int1] else result:=false;
end;

procedure tbasictoolbar.xsetenabled2(x:string;y:boolean);
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then ienableds[int1]:=y;
end;

function tbasictoolbar.xgetenabled2(x:string):boolean;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=ienableds[int1] else result:=false;
end;

procedure tbasictoolbar.xsetcap2(x:string;y:string);
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then icap[int1]:=y;
end;

function tbasictoolbar.xgetcap2(x:string):string;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=icap[int1] else result:='';
end;

procedure tbasictoolbar.xsettep2(x:string;y:longint);
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then xsettep(int1,y);
end;

function tbasictoolbar.xgettep2(x:string):longint;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=itep[int1] else result:=tepNone;
end;

procedure tbasictoolbar.xsetsize2(x:string;y:longint);
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then isize[int1]:=y;
end;

function tbasictoolbar.xgetsize2(x:string):longint;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=isize[int1] else result:=0;
end;

procedure tbasictoolbar.xsettitle2(x:string;y:boolean);
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then ititle[int1]:=y;
end;

function tbasictoolbar.xgettitle2(x:string):boolean;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=ititle[int1] else result:=false;
end;

procedure tbasictoolbar.xsetpert2(x:string;y:double);
var
   int1:longint;
begin
if (y<0) then y:=0 else if (y>100) then y:=100;
if xfindbycode2b(x,int1) and (ipert[int1]<>y) then
   begin
   ipert[int1]:=y;
   paintnow;
   end;
end;

function tbasictoolbar.xgetpert2(x:string):double;
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=ipert[int1] else result:=0;
end;

procedure tbasictoolbar.xsethelp2(x,y:string);//09jun2025
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then ibuthelp[int1]:=y;
end;

function tbasictoolbar.xgethelp2(x:string):string;//09jun2025
var
   int1:longint;
begin
if xfindbycode2b(x,int1) then result:=ibuthelp[int1] else result:='';
end;


//## tbasicmenu ################################################################
constructor tbasicmenu.create2(xparent:tobject;xstart:boolean);
begin
//self
if classnameis('tbasicmenu') then track__inc(satMenu,1);
inherited create2(xparent,false);

//options
oscaleh            :=1.0;
imanysel1          :=0;
imanysel2          :=0;
onumberfrom        :=-1;
onumberfrom2       :=-1;
onumberfrom3       :=-1;
iwasflashing       :=false;
iflashing          :=false;//true=one or more visible items requires flash support
ilastflash         :=sysflash;
ohoverunderline    :=true;
icountx            :=-1;//off -> set to "0..N" via "makelistx()" to use a realtime list -> items source via external proc in realtime - 22sep2020
ireloadid          :=viloadid;
oautoreload        :=false;
oloadfromname      :='';//off
oautoclose         :=true;
ocode              :=0;
ocode2             :='';
otepcolor          :=clnone;
otepcolor2         :=clnone;//10dec2025
orowcount          :=0;
oautoheight        :=true;
oautowidth         :=true;
ofast              :=false;
orows              :=false;
ostyle             :=lsmenu;
okeepopen          :=false;

//vars
icandrag           :=false;
fonclick           :=nil;
ilist              :=str__new8;
ilist.floatsize    :=5000;
ilistcount         :=0;
itep               :=tepnone;
iselstart          :=0;
iselcount          :=0;
ipos               :=0;
idata              :=str__new8;
idata.floatsize    :=5000;
icount             :=0;
ihoverindex        :=-1;
inormal            :=true;
irowpad            :=2;
ibordersize        :=0;//20jul2024
ipad               :=5;
imaxindentwidth    :=0;
imaxtepwidth       :=0;
imaxcapwidth       :=0;
imaxtitcapwidth    :=0;
imaxttitepwidth    :=0;
imaxcutwidth       :=0;//shortcut -> e.g "CTRL+S"
idownpos           :=0;
idownindex         :=0;
ilastitemindex     :=-99;

//controls
iv                 :=tbasicscrollbar.create(self);
iv.overtical       :=true;
iv.ofullhandling   :=false;//allow our "_onnotify()" to handle the sensitive parts of scrolling and navigation etc - 04apr2020
iv.onpos           :=_onpos;

//defaults
clientheight       :=20;

//start
if xstart then start;

end;

destructor tbasicmenu.destroy;
begin
try

//disconnect timer
timer:=false;

//disconnect events
fonclick:=nil;

//self
inherited destroy;

//controls
freeobj(@idata);
freeobj(@ilist);

//sat
if classnameis('tbasicmenu') then track__inc(satMenu,-1);

except;end;
end;

function tbasicmenu.xfindbycode2(xfindval:string;var xindex:longint):boolean;//04dec2025
var
   xtep,xtepcolor,xcode,xshortcut,xindent,p,xcount:longint;
   xtab,xcaption,xcaplabel,xhelp,xcode2:string;
   xflash,xenabled,xtitle,xsep,xbold:boolean;
begin

//defaults
result :=false;
xindex :=0;
xcount :=icount;

//check
if (xcount<=0) then exit;

//find
for p:=0 to (xcount-1) do if xgetitem(p,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) and strmatch(xfindval,xcode2) then
   begin

   xindex :=p;
   result :=true;
   break;

   end;//p

end;

function tbasicmenu.xfindbycaption2(xfindval:string):longint;
begin
xfindbycaption(xfindval,result);
end;

function tbasicmenu.xfindbycaption(xfindval:string;var xindex:longint):boolean;//04dec2025
var
   xtep,xtepcolor,xcode,xshortcut,xindent,p,xcount:longint;
   xtab,xcaption,xcaplabel,xhelp,xcode2:string;
   xflash,xenabled,xtitle,xsep,xbold:boolean;
begin

//defaults
result :=false;
xindex :=0;
xcount :=icount;

//check
if (xcount<=0) then exit;

//find
for p:=0 to (xcount-1) do if xgetitem(p,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) and strmatch(xfindval,xcaption) then
   begin

   xindex :=p;
   result :=true;
   break;

   end;//p

end;

function tbasicmenu.xfindnext(xfindpart:string;var xindex:longint):boolean;//06oct2020
var
   xlen,xtep,xtepcolor,xcode,xshortcut,xindent,i,p,xcount:longint;
   xtab,xcaption,xcaplabel,xhelp,xcode2:string;
   xflash,xenabled,xtitle,xsep,xbold:boolean;
begin

//defaults
result :=false;
xindex :=0;
xcount :=icount;

//check
if (xcount<=0) then exit;

xlen   :=low__len32(xfindpart);

if (xlen<=0)   then exit;

//find
p      :=frcmin32(selstart,0)+1;
if (p>=xcount) then p:=0;

for i:=0 to (xcount-1) do
begin

if xgetitem(p,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) and strmatch(xfindpart,strcopy1(xcaplabel,1,xlen)) then
   begin

   xindex :=p;
   result :=true;
   break;

   end;

//inc
inc(p);
if (p>=xcount) then p:=0;

end;//p

end;

procedure tbasicmenu.reload;
var
   int1:longint;
begin
if (oloadfromname<>'') then
   begin
   if not xfindbycode2(sfromname(oloadfromname),int1) then int1:=0;
   setsel(int1,1);
   if (int1<vpos1) or (int1>vpos2) then pos:=int1;
   end;
end;

procedure tbasicmenu.makemenu;
begin
icountx    :=-1;//turn of "listx" override mode - 22sep2020
ofast      :=false;
ostyle     :=lsmenu;
orows      :=false;
okeepopen  :=false;
end;

procedure tbasicmenu.makelist;
begin
icountx    :=-1;//turn off "listx" override mode - 22sep2020
ofast      :=false;
ostyle     :=lslist;
orows      :=false;
okeepopen  :=true;
end;

procedure tbasicmenu.makelistx(xcount:longint);
begin
ofast      :=true;
ostyle     :=lslist;
orows      :=false;//true;
okeepopen  :=true;
icountx    :=frcmin32(xcount,0);//must be 0..N to override internal data block - 22sep2020
setdata(nil);//dump previous data and set list to "xcount" items
end;

procedure tbasicmenu.makepanel;//28aug2026, 18aug2025
begin
ofast            :=true;
ostyle           :=lspanel;
orows            :=false;
okeepopen        :=true;
ohoverunderline  :=false;
end;

procedure tbasicmenu.setcountx(x:longint);
begin
icountx    :=frcmin32(x,0);
setdata(nil);//dump previous data and set list to "xcount" items
end;

procedure tbasicmenu.makemany;
begin
icountx    :=-1;//turn of "listx" override mode - 22sep2020
ofast      :=false;
ostyle     :=lsmany;
orows      :=false;//true;
okeepopen  :=true;
end;

procedure tbasicmenu.makepoplist;
begin
icountx:=-1;//turn of "listx" override mode - 22sep2020
ofast:=false;
ostyle:=lslist;
orows:=false;//true;
okeepopen:=false;
end;

procedure tbasicmenu.makepopmany;
begin
icountx:=-1;//turn of "listx" override mode - 22sep2020
ofast:=false;
ostyle:=lsmany;
orows:=false;//true;
okeepopen:=false;
end;

function tbasicmenu.xsetclientarea(a:twinrect):boolean;
var
   int1:longint;
begin
result:=inherited xsetclientarea(a);
//iv
int1:=scount;
iv.setparams(pos,0,int1);
iv.visible:=(int1>=1);
end;

procedure tbasicmenu._onpos(sender:tobject);
begin
if (iv.pos<>pos) then pos:=iv.pos;
end;

procedure tbasicmenu.setpos(x:longint);
begin
x:=frcrange32(x,0,frcmin32(scount,0));//scount is the difference of screen capacity to required capacity -> no need to shrink by "-1"
if low__setint(ipos,x) then paintnow;
if (iv.pos<>ipos) then iv.pos:=ipos;
end;

procedure tbasicmenu.sethoverindex(x:longint);
begin
x:=frcrange32(x,-1,frcmin32(icount-1,0));
if low__setint(ihoverindex,x) then paintnow;
end;

procedure tbasicmenu.setdata(x:tstr8);//17nov2024, 08jun2021
label
   skipend,done,redo;
const
   xnilval='(..nil..)';//unicode safe
var
   a:pvirtualinfo;
   int1,int2,xcode,xshortcut,xindent,xcount,xlasttep,xtep,xtepcolor,p,w0,w1,w2,w3,w4,w5:longint;
   str1,xlasttitcap,xlastcap,xlastcut,xcaption,xhelp,xcode2:string;
   xflash,xenabled,xtitle,xsep:boolean;
begin
//defaults
xcount           :=0;

try
//check
str__lock(@x);

//init
w0               :=0;
w1               :=0;
w2               :=0;
w3               :=0;
w4               :=0;
w5               :=0;

//check
if (icountx>=0) then goto done;
if zznil(x,2352) or idata.same(x) then goto skipend;

//init continued
a               :=info;
xcount          :=low__menucount(x);

if (xcount<=0) or ofast then goto done;

//get
xlastcap        :=xnilval;
xlasttep        :=min32;//trigger a check even for "xtep=<nil>"
xlastcut        :=xnilval;
xlasttitcap     :=xnilval;
p               :=0;

redo:

if (p<xcount) and low__menuget(x,p,xtep,xtepcolor,xcaption,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep) then
   begin

   //.indent
   if (xindent>w0) then w0:=xindent;

   //.tep
   if low__setint(xlasttep,xtep) then
      begin

      tep__info(xtep,int1,int2);//aw,ah

      if (int1>w1)                  then w1:=int1;
      if xtitle and (xtep<>tepnone) then w5:=w1;//always same as normal items BUT is only set if a title uses a tep image - 29mar2020

      end;

   //.caption
   case xtitle of
   true:begin

      if (xcaption<>'') and low__setstr(xlasttitcap,xcaption) then
         begin

         int1:=fast__textwidth('',xcaption,a.fb);//fixed - was "a.fn" - 08jun2021
         if (int1>w4) then w4:=int1;

         end;

      end;
   else begin

      if (xcaption<>'') and low__setstr(xlastcap,xcaption) then
         begin

         int1:=fast__textwidth('',xcaption,a.fn);
         if (int1>w2) then w2:=int1;

         end;

      end;
   end;//case

   //.shortcut
   if (not xtitle) and (xshortcut<>aknone) and low__akstr(xshortcut,str1) and low__setstr(xlastcut,str1) then
      begin

      int1:=fast__textwidth('',str1,a.fn);
      if (int1>w3) then w3:=int1;

      end;

   //loop
   inc(p);
   goto redo;

   end;

//set
done:
ihoverindex     :=-1;

if (icountx>=0) then
   begin

   idata.replace:=nil;
   if low__setint(icount,icountx) then alignnow;

   end
else
   begin

   idata.replace:=x;//takes a copy
   if low__setint(icount,xcount) then alignnow;

   end;

//.reset position - 04oct2020

if oretainpos then ipos:=frcrange32(ipos,0,frcmin32(icount-1,0)) else ipos:=0;

imaxindentwidth  :=w0;
imaxtepwidth     :=w1;
imaxcapwidth     :=w2;
imaxcutwidth     :=w3;
imaxtitcapwidth  :=w4;
imaxttitepwidth  :=w5;
iselstart        :=frcrange32(iselstart,0,frcmin32(icount-1,0));//fixed - 17nov2024
iselcount        :=frcrange32(iselcount,0,icount);//fixed - 17nov2024

paintnow;

skipend:
except;end;

//free
str__uaf(@x);

end;

procedure tbasicmenu.setselstart(x:longint);
begin
if xsetsel(x,iselcount) then paintnow;
end;

procedure tbasicmenu.setselcount(x:longint);
begin
if xsetsel(iselstart,x) then paintnow;
end;

function tbasicmenu.setsel(xselstart,xselcount:longint):boolean;
begin
result:=true;
if xsetsel(xselstart,xselcount) then paintnow;
end;

function tbasicmenu.getitemindex:longint;
begin
result:=iselstart;
end;

procedure tbasicmenu.setitemindex(x:longint);
var
   bol1:boolean;
begin
bol1:=xsetsel(x,1);
if (x<pos) then
   begin
   pos:=x;
   bol1:=false;
   end
else if (x>(pos+vcount-1)) then
   begin
   pos:=x-vcount+1;
   bol1:=false;
   end;
if bol1 then paintnow;
end;

function tbasicmenu.xsetsel(xselstart,xselcount:longint):boolean;
begin
result:=false;
if (ostyle<lsmany) then xselcount:=1;
if low__setint(iselstart,frcrange32(xselstart,0,frcmin32(icount-1,0))) then result:=true;
if low__setint(iselcount,frcrange32(xselcount,0,icount)) then result:=true;
end;

function tbasicmenu.xrowpad:longint;
begin

result:=scale__px1( irowpad * viscale ,0);

end;

function tbasicmenu.xrowheight:longint;
begin

result:=frcmin32( trunc(virowheight30*oscaleh) + (2 * xrowpad ) ,vitepheight20);

end;

function tbasicmenu.xrowcount:longint;
begin
result:=frcmin32(icount,1);
end;

function tbasicmenu.getalignheight(xclientwidth:longint):longint;
begin

result:=(2*findbordersize)+(frcmax32(xrowcount,low__aorb(xrowcount,orowcount,orowcount>=1))*xrowheight);

end;

function tbasicmenu.getalignwidth(xclientheight:longint):longint;
var
   xmaxtepwidth,xmaxttitepwidth,xzoom,int1,int2,int3:longint;
begin
if oautowidth then
   begin
   //.xzoom
   xzoom:=vizoom;
   xmaxttitepwidth:=imaxttitepwidth*xzoom;
   xmaxtepwidth:=imaxtepwidth*xzoom;
   //.scrollbar width
   int3:=iv.getalignwidth(0);
   //.normal menu item
   int1:=(ipad*vizoom)+(imaxindentwidth*vizoom)+(xmaxtepwidth*vizoom)+low__insint(ipad*vizoom,xmaxtepwidth>=1)+imaxcapwidth+low__insint(2*ipad*vizoom,imaxcutwidth>=1)+imaxcutwidth+(ipad*vizoom)+int3;
   //.title menu item (different width of tep's and also bold text) - 29mar2020
   int2:=(ipad*vizoom)+(imaxindentwidth*vizoom)+(xmaxttitepwidth*vizoom)+low__insint((ipad*vizoom),xmaxttitepwidth>=1)+imaxtitcapwidth+(ipad*vizoom)+int3;
   result:=largest32(int1,int2);
   end
else result:=frcmin32(frcmin32(clientwidth,ominwidth*vizoom),0);
end;

procedure tbasicmenu._onalign(sender:tobject);
var
   ci:twinrect;
begin
ci:=clientinner;

case iv.overtical of
true:iv.xsetclientarea(area__make(ci.right-(iv.getalignwidth(0)-1),ci.top,ci.right,ci.bottom));
else iv.xsetclientarea(area__make(ci.left,ci.top,ci.right,ci.top+iv.getalignheight(0)-1));//this mode is for debug purposes only - 04apr2020
end;
end;

procedure tbasicmenu._ontimer(sender:tobject);
var
   xdir,int1:longint;
   xmustpaint:boolean;
begin
try
//defaults
xmustpaint:=false;
//reload - 07sep2020
if oautoreload and (ireloadid<>viloadid) and (not visyncing) and (not gui.mousedown) then
   begin
   ireloadid:=viloadid;
   reload;
   end;
//flash
if (sysflash<>ilastflash) then
   begin
   ilastflash:=sysflash;
   if iflashing or iwasflashing then xmustpaint:=true;
   end;
//wound scroller - 28sep2022
if xwound_mustpaint(pos,round(xrowheight*0.3),int1,xdir) then
   begin
   if (int1<>pos) then pos:=int1;
   xwound_autooff(pos,xdir,0,count-1);
   end;

//mustpaint
if xmustpaint then paintnow;
except;end;
end;

function tbasicmenu.xfindb(sx,sy:longint):longint;
begin
xfind(sx,sy,result);
end;

function tbasicmenu.xfind(sx,sy:longint;var xindex:longint):boolean;//07apr2020
var
   xi,y1,y2,i,p:longint;
   a:tint4;
   xmany:boolean;
begin
//defaults
result:=false;
xindex:=-1;
xmany:=(ostyle>=lsmany);

try
//find
for p:=(ilistcount-1) downto 0 do
begin
i:=(p*12);//0-based
//.xindex
a.bytes[0]:=ilist.pbytes[i+0];
a.bytes[1]:=ilist.pbytes[i+1];
a.bytes[2]:=ilist.pbytes[i+2];
a.bytes[3]:=ilist.pbytes[i+3];
xi:=a.val;
//.y1
a.bytes[0]:=ilist.pbytes[i+4];
a.bytes[1]:=ilist.pbytes[i+5];
a.bytes[2]:=ilist.pbytes[i+6];
a.bytes[3]:=ilist.pbytes[i+7];
y1:=a.val;
//.y2
a.bytes[0]:=ilist.pbytes[i+8];
a.bytes[1]:=ilist.pbytes[i+9];
a.bytes[2]:=ilist.pbytes[i+10];
a.bytes[3]:=ilist.pbytes[i+11];
y2:=a.val;
//xmany -> using a "many" list we should always return a valid itemindex even when not in proper range -> for accurate selstart..selcount handling - 07apr2020
if xmany then
   begin
   if (xindex=-1) then xindex:=xi
   else if (sy<y2) then xindex:=xi;
   end;
//get
if (sy>=y1) and (sy<=y2) and (sx<iv.left) then
   begin
   xindex:=xi;
   result:=true;
   break;
   end;
end;//p

except;end;
end;

function tbasicmenu.xgetval2(xindex:longint):string;//03mar2022
begin
xgetval(xindex,result);
end;

function tbasicmenu.xgetval(xindex:longint;var xvalue:string):boolean;
var
   xtep,xtepcolor:longint;
   xtab,xcaplabel,xhelp,xcode2:string;
   xcode,xshortcut,xindent:longint;
   xflash,xenabled,xtitle,xsep,xbold:boolean;
begin

result:=xgetitem(xindex,xtab,xtep,xtepcolor,xvalue,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold);

end;

function tbasicmenu.xgetitem(xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;//03oct2024, 20mar2022
var
   xtepcolor2:longint;
begin
result:=xgetitem2(xindex,xtab,xtep,xtepcolor,xtepcolor2,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold);
end;

function tbasicmenu.xgetitem2(xindex:longint;var xtab:string;var xtep,xtepcolor,xtepcolor2:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;//03oct2024, 20mar2022
begin

//defaults
result       :=false;
xtab         :=otab;
xtepcolor    :=clnone;//20mar2022
xtepcolor2   :=clnone;//04dec2025
xtep         :=tepNone;
xcaption     :='';
xcaplabel    :='';
xhelp        :='';
xcode2       :='';
xcode        :=0;
xshortcut    :=aknone;
xindent      :=0;
xenabled     :=false;
xtitle       :=false;
xsep         :=false;
xflash       :=false;
xbold        :=false;

try
//check
if (xindex<0) or (xindex>=icount) then exit;

//get
if (icountx>=0) then
   begin
   xenabled:=true;

   if      assigned(fongetitem2) then fongetitem2(self,xindex,xtab,xtep,xtepcolor,xtepcolor2,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold)
   else if assigned(fongetitem)  then fongetitem(self,xindex,xtab,xtep,xtepcolor,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold)
   else
      begin

      xcaption :='??'+intstr32(xindex)+'??';
      xtep     :=tepNew20;

      end;

   result:=true;

   end
else
   begin

   result:=low__menuget(idata,xindex,xtep,xtepcolor,xcaption,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep);

   end;

//set
if (xcaplabel='') then xcaplabel:=xcaption;//27mar2022

except;end;
end;

function tbasicmenu._onshortcut(sender:tobject):boolean;
begin//store shortcut so we can transmitt it to our host form later (once we've closed the menu) - 02apr2020
result:=false;//not used -> do NOT handle, allow all shortcuts to flow back to system for processing - 11feb2023
{//was:
result:=true;
gui.popshortcut:=gui.key;
{}
end;

function tbasicmenu._onnotify(sender:tobject):boolean;
var
   int1,xkey,xnewhoverindex:longint;
   xmustpaint:boolean;
   xtab,xcaption,xcaplabel,xhelp,xcode2:string;
   xtep,xtepcolor,xtepcolor2,xcode,xshortcut,xindent:longint;
   xclickonce,xkeyok,xflash,xenabled,xtitle,xsep,xbold:boolean;

   procedure xselect;//list support
   var
      int1,int2:longint;
   begin
   if (ostyle=lsmenu) or ((gui.mousedownstroke and gui.mouseleft and ((ostyle<=lsmany) or (not icandrag)) ) or (xkeyok and (not gui.shiftok)) ) then
      begin
      if xsetsel(ihoverindex,1) then xmustpaint:=true;
      end
   else if (ostyle>lsmany) and ( (gui.mousedown and gui.mouseleft and (not icandrag)) or (xkeyok and gui.shiftok) ) then
      begin
      int1:=smallest32(ihoverindex,idownindex);
      int2:=largest32(ihoverindex,idownindex);
      if xsetsel(int1,(int2-int1+1)) then xmustpaint:=true;
      end;
   end;

   procedure xclick;
   begin

   //fire click event
   if (ihoverindex>=0) and xgetitem2(ihoverindex,xtab,xtep,xtepcolor,xtepcolor2,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) and xenabled and (not xtitle) then
      begin

      if (ostyle=lsmenu) or (iselcount<=0) or (gui.key=akspace) then xselect;//list support

      ocode      :=xcode;
      ocode2     :=xcode2;
      otepcolor  :=xtepcolor;
      otepcolor2 :=xtepcolor2;

      //.fire click event
      if xclickonce then
         begin

         //once only
         xclickonce:=false;

         //events
         gui.closelock;//prevent shutdown of system while proc in use - 03apr2021

         try
         if assigned(fonclick) then fonclick(self);
         if assigned(fondbclick) and gui.mousedbclick then fondbclick(self);

         //autoclose form - optional - 14aug2020
         if oautoclose then gui.xcloseok(self);

         except;end;

         gui.closeunlock;

         end;

      end;

   end;

   procedure xselectrangeADD;
   begin

   //check
   if (ostyle<>lsmany) then exit;

   //get
   if low__setint(ilastitemindex,itemindex) or (focused and gui.mousedbclick) then//don't change highlight/itemindex when "double clicking" -> vital for stable switching between disk drives and folders etc inside a "tbasicnav" list - 28sep2022
      begin

      imanysel1 :=imanysel2;
      imanysel2 :=itemindex;

      if xkeyok then xsetsel(itemindex,1);//required for keyboard syncing - 28sep2022

      xmustpaint:=true;

      end
   else
      begin

      xselectrange(imanysel1,imanysel2);

      ilastitemindex :=-99;
      xmustpaint     :=true;

      end;

   end;

begin

//defaults
result          :=true;//handled
xclickonce      :=true;
xmustpaint      :=false;
xnewhoverindex  :=max32;//off
xkeyok          :=false;

try

if gui.mousedownstroke then icandrag:=(ostyle<=lsmany);//was: or (mousex>=(round(0.5*iv.left)));

//wheel
if (gui.wheel<>0) then
   begin

   pos:=pos-gui.wheel;
   notidle;
   xwound_wheel(gui.wheel*70);

   end;

//key
xkey:=gui.key;

if (xkey<>aknone) then
   begin

   case xkey of

   akhome:begin

      notidle;
      pos            :=0;
      xnewhoverindex :=0;
      xkeyok         :=true;

      end;

   akend:begin

      notidle;
      pos            :=count;
      xnewhoverindex :=frcmin32(count-1,0);
      xkeyok         :=true;

      end;

   akleft,akup:begin

      notidle;
{//was:
      if      (iselstart>(pos+vcount-1)) then xnewhoverindex:=frcmin32(pos+vcount-1,0)
      else if (iselstart<pos) then xnewhoverindex:=pos
      else if (iselstart>pos) then xnewhoverindex:=iselstart-1
      else
         begin
         pos:=pos-1;
         xnewhoverindex:=pos;
         end;
{}
      if      (ihoverindex>(pos+vcount-1)) then xnewhoverindex:=frcmin32(pos+vcount-1,0)
      else if (ihoverindex<pos)            then xnewhoverindex:=pos
      else if (ihoverindex>pos)            then xnewhoverindex:=ihoverindex-1
      else
         begin

         pos            :=pos-1;
         xnewhoverindex :=pos;

         end;

      xkeyok:=true;

      end;

   akright,akdown,aktab:begin

      notidle;

   {was:
      if      (iselstart>(pos+vcount-1)) then xnewhoverindex:=frcmin32(pos+vcount-1,0)
      else if (iselstart<pos) then xnewhoverindex:=pos
      else if (iselstart<(pos+vcount-1)) then xnewhoverindex:=iselstart+1
      else
         begin
         pos:=pos+1;
         xnewhoverindex:=pos+frcmin32(vcount-1,0);
         end;
{}

      if      (ihoverindex>(pos+vcount-1)) then xnewhoverindex:=frcmin32(pos+vcount-1,0)
      else if (ihoverindex<pos)            then xnewhoverindex:=pos
      else if (ihoverindex<(pos+vcount-1)) then xnewhoverindex:=ihoverindex+1
      else
         begin

         pos            :=pos+1;
         xnewhoverindex :=pos+frcmin32(vcount-1,0);

         end;

      xkeyok:=true;

      end;

   akprev:begin

      notidle;

      if (ihoverindex<>pos) then xnewhoverindex:=pos
      else
         begin

         pos            :=pos-vcount;
         xnewhoverindex :=pos;

         end;

      xkeyok:=true;

      end;

   aknext:begin

      notidle;

      if (ihoverindex<>(pos+frcmin32(vcount-1,0))) then xnewhoverindex:=pos+frcmin32(vcount-1,0)
      else
         begin

         pos            :=pos+vcount;
         xnewhoverindex :=pos+frcmin32(vcount-1,0);

         end;

      xkeyok:=true;

      end;

   akreturn,akspace:begin

      notidle;

      xkeyok:=true;
      xclick;
      xselectrangeADD;

      end;

   else
      begin

      if (ostyle>=lslist) and (xkey>=akspace) and xfindnext(char(xkey),int1) then
         begin

         notidle;
         xsetsel(int1,1);

         if (int1<vpos1) or (int1>vpos2) then pos:=int1;

         ihoverindex :=int1;

         xclick;
         xselectrangeADD;
         xmustpaint  :=true;

         end;

      end;

   end;//case
   end;

//hover - 24jul2021
if (not gui.mousedragging) and (not gui.mousewasdown) and (gui.wheel=0) and (gui.key=aknone) then xnewhoverindex:=xfindb(mousemovexy.x,mousemovexy.y);

//xnewhoverindex
if (xnewhoverindex<>max32) then
   begin

   xenabled:=false;

   case xok(xnewhoverindex) of
   true:begin

      xgetitem2(xnewhoverindex,xtab,xtep,xtepcolor,xtepcolor2,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold);
      help2:=xhelp;

      end;
   else help2:='';//revert back to "help" - 07sep2020
   end;//case

   if (xnewhoverindex<>ihoverindex) then
      begin

      ihoverindex:=xnewhoverindex;
      //was:if xok(xnewhoverindex) and xenabled and (not xtitle) then screen.cursor:=crHandpoint else screen.cursor:=scDefault;
      if (ostyle=lsmenu) or ohoverunderline then xmustpaint:=true;//22feb2022 - reduce unnecessary repaints when an "info list" e.g. a status panel in mode "lslist" -> hover is not used for anything so no need to paint the screen

      end;

   end;

//mouse down
if gui.mousedownstroke or (gui.key=akshift) then
   begin

   idownpos   :=pos;
   idownindex :=frcrange32(ihoverindex,0,frcmin32(icount-1,0));

   end;

//list support
if (xnewhoverindex<>max32) then
   begin

   xselect;

   //.listclick
   if xkeyok and (ostyle>=lslist) then
      begin

      notidle;
      xclick;

      end;

   end;

//mouse move
if gui.mousedown and gui.mousedragging and icandrag then
   begin

   notidle;
   pos:=idownpos+((gui.screendownxy.y-gui.screenmovexy.y) div xrowheight);

   end;

//mouse up - wound support - 04oct2022
if gui.mouseupstroke and icandrag and gui.mousedragging and gui.mouseleft then xwound_mousevert(3000,true);

//mouse up
if gui.mouseupstroke and ((not gui.mousedragging) or (not icandrag) ) and gui.mouseleft then
   begin

   xselectrangeADD;

   pos:=idownpos;//FIXED: Keyboard highlight mismatch/misbehaviour -> used to show Options window, select first frame in "Frame" and then key down, but keyboard highlight would JUMP to the original highlight item when window first displayed - 26feb2022

   notidle;
   xclick;

   end;

//additional paint events
if gui.mousedownstroke or gui.mouseupstroke then xmustpaint:=true;

//showmenu
autoshowmenu;

//xmustpaint
if xmustpaint then paintnow;

//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);

except;end;
end;

function tbasicmenu.canselectrange:boolean;//28sep2022
begin
result:=(ostyle=lsmany) and (imanysel1<>imanysel2);
end;

procedure tbasicmenu.selectrange;
begin
if canselectrange then xselectrange(imanysel1,imanysel2);
end;

procedure tbasicmenu.selectoff;
begin
imanysel1:=-1;
imanysel2:=-1;
ilastitemindex:=-2;
end;

procedure tbasicmenu.xselectrange(x1,x2:longint);
begin
xsetsel(smallest32(x1,x2),largest32(x1,x2)-smallest32(x1,x2)+1);
end;

procedure tbasicmenu.setdownindex(x:longint);
begin
idownindex:=frcrange32(x,0,frcmin32(icount-1,0));
end;

function tbasicmenu.vcount:longint;//visible count
begin
result:=frcmin32((frcmin32(clientheight,1)-(2*frcmin32(findbordersize,0))) div xrowheight,1);
end;

function tbasicmenu.vpos1:longint;//first visible item
begin
result:=frcrange32(pos,0,frcmin32(icount-1,0));
end;

function tbasicmenu.vpos2:longint;//last visible item
begin
result:=frcrange32(pos+frcmin32(vcount-1,0),0,frcmin32(icount-1,0));
end;

function tbasicmenu.scount:longint;//scroll count
begin
result:=frcmin32(icount-vcount,0);
end;

function tbasicmenu.xok(x:longint):boolean;
begin
result:=(x>=0) and (x<icount);
end;

procedure tbasicmenu._onpaint(sender:tobject);//15apr2026, 01dec2025, 15may2025, 20jul2024: soft back for title items
label
   redo;

const
   xpad=5;
   //color modes
   mnor=0;
   mdis=1;
   mhov=2;

var
   //infovars
   s:tclientinfo;
   ra:twinrect;
   cw,ch,findex:longint;
   xtepType,xoff,yoff,drowpad,xfont,xback,xteptmp,ximagealign,xtep,xtepcolor,xtepcolor2,th,xmaxcutwidth,xmaxindentwidth,xmaxtepwidth,xmaxcapwidth,int1,int2,int3,vc,xcode,xshortcut,xindent,rh,p,dx,dy:longint;
   xtab,str1,str2,xcaption,xcaplabel,xhelp,xcode2:string;
   xenabled,xmarkrow,xflashON,xflash,xflashing,xrowbol,xrows,xtitle,xsep,xbold:boolean;
   xstyle:byte;
   xlist:tstr8;
   v:byte;

   function xrowarea:twinrect;
   begin

   result:=area__make(xoff+s.bs,yoff+dy+drowpad,xoff+cw-1-s.bs,yoff+dy+rh-1-drowpad);

   end;

   function xtepColorsNULL:boolean;
   begin

   result             :=true;
   xtepColor          :=clnone;
   xtepColor2         :=clnone;

   end;

begin
try

//defaults
xlist      :=nil;
xflashing  :=false;
xflashON   :=not sysflash;
drowpad    :=xrowpad;

//init
infovars(s);

if oinputcolorise.use then s.back:=inputcolorise__backcolor(oinputcolorise,0.1,0,s.back);

ch      :=s.ch;
cw      :=s.cw;
th      :=s.fnbH;//18apr2020
xtab    :=otab;//24feb2021
xstyle  :=ostyle;
xrows   :=virows and orows;
xrowbol :=false;
findex  :=s.Rfn;

cw      :=frcmin32(cw-low__insint(iv.clientwidth,iv.visible),1);//adjust down to exclude scrollbar width
rh      :=xrowheight;
dy      :=s.bs;
vc      :=vcount;//visible count

xlist   :=small__new8;//29aug2025

//.system widths -> for debug purposes, paint proc can adapt these values if too small OR if not set - 28mar2020
//note: for lists (with very long datasets, we can't calc imaxtepheight, so we have to assume viTepHeight20 - zoomed version )
xmaxindentwidth  :=frcmin32(imaxindentwidth,0);
xmaxtepwidth     :=frcmin32(imaxtepwidth,0)*s.zoom;
xmaxcapwidth     :=frcmin32(imaxcapwidth,0);
xmaxcutwidth     :=frcmin32(imaxcutwidth,0);
ximagealign      :=frcrange32(oimagealign,0,iaMax);

//cls
ffillArea(s.cs,s.back,false);

//get
p           :=frcrange32(ipos,0,frcmin32(icount-vc,0));//restrict scroll range

redo:

dx          :=s.bs+xpad;

if (p>=0) and (p<icount) and (dy<=(ch-1-s.bs)) and xtepColorsNULL and xgetitem2(p,xtab,xtep,xtepcolor,xtepcolor2,xcaption,xcaplabel,xhelp,xcode2,xcode,xshortcut,xindent,xflash,xenabled,xtitle,xsep,xbold) then
   begin

   //down
   case xenabled and (p=ihoverindex) and gui.mousedown and focused of
   true:xoff:=2*vilineVsep1orLESS;
   else xoff:=0;
   end;//case

   yoff     :=xoff;


   //init
   case xbold  of
   true:findex:=s.Rfb;
   else findex:=s.Rfn;//03oct2024
   end;

   if xflash then xflashing:=true;//tell system we need flashing support - 25mar2021

   xback      :=s.back;
   xfont      :=s.font;

   //ra
   ra         :=area__make(s.bs,dy,cw-1-s.bs,dy+rh-1);

   //show highlight/disabled etc

   //.title
   if xtitle then
      begin

      xback :=s.hover;
      findex:=s.Rfb;

      end

   //.disabled
   else if not xenabled then
      begin
      //nil
      end

   //.hover
   else if (xstyle=lsmenu) and (p=ihoverindex) then
      begin

      xback :=s.hover;

      end

   //.selection
   else if (xstyle>=lslist) and (p>=iselstart) and (p<(iselstart+iselcount)) then
      begin

      if (xstyle=lspanel) then xback:=s.row//very subtle highlight
      else
         begin

         xback :=s.colhover;
         xfont :=s.colfont;

         end;

      end

   //.no hover highlight
   else if (xstyle=lslist) and (p=ihoverindex) then//no hover highlight for lsmany - 07apr2020
      begin

      xback :=s.hover;

      end

   //.no hover highlight
   else if (xstyle=lspanel) and (p=ihoverindex) then
      begin

      xback :=s.row;//very subtle

      end

   //.items
   else
      begin

      if xrows and xrowbol  then xback:=s.row;

      end;


   //.altnerate row tracker
   if not xtitle then xrowbol:=not xrowbol;

   //.row background
   if (xback<>s.back) then ffillArea(xrowarea,xback,s.r);

   //.xmarkrow
   xmarkrow :=(ostyle=lsmany) and ((p=imanysel1) or (p=imanysel2)) and (imanysel1<>imanysel2) and (not xtitle);//for "select to here" visual markings - 28sep2022


   //indent --------------------------------------------------------------------

   //.scale
   if (xindent>=1) and (viscale>=1) then xindent:=scale__px0(xindent);

   //.largest
   if (xindent>xmaxindentwidth) then xmaxindentwidth:=xindent;
   inc(dx,xindent);


   //tep
   if (xtep<>tepnone) then
      begin

      //.auto system-zooms tep dimensions - 19aug2024, 03aug2024
      tep__info2(xtep,int1,int2,xtepType);//aw,ah

      case ximagealign of
      iaLeft    :xteptmp:=0;
      iaCenter  :xteptmp:=frcmin32((xmaxtepwidth-int1) div 2,0);
      iaRight   :xteptmp:=frcmin32(xmaxtepwidth-int1,0);
      else       xteptmp:=0;
      end;//case

      if (not xflash) or xflashON then
         begin

         //updated - 15apr2026, 19mar2026, 04dec2025, fixed 13apr2021, 26mar2021 //was "s.border" - 01dec2025

         case xtepType of
         it_rle8:ftep2(xtep,xoff+dx+xteptmp,yoff+dy+((rh-int2) div 2) ,low__aorb(xfont,xtepcolor,xtepcolor<>clnone) ,low__aorb(s.line,xtepcolor2,xtepcolor2<>clnone) ,low__aorb(clwhite,xtepcolor,xtepcolor<>clnone) ,low__aorb(clblack,xtepcolor2,xtepcolor2<>clnone) ,255 ,xenabled );
         else    ftep2(xtep,xoff+dx+xteptmp,yoff+dy+((rh-int2) div 2) ,xfont ,s.line ,low__aorb(clwhite,xtepcolor,xtepcolor<>clnone) ,low__aorb(clblack,xtepcolor2,xtepcolor2<>clnone) ,255 ,xenabled );
         end;//case

         end;

      if (int1>xmaxtepwidth) then xmaxtepwidth:=int1;

      end;

   //caption
   if (not xtitle) or (xtep<>tepnone) then inc(dx,xmaxtepwidth+low__insint(xpad,xmaxtepwidth>=1));

   str1:=strdefb(xcaplabel,xcaption);
   if (str1<>'') then
      begin

      //.onumberfrom - use carefully - 20mar2022
      if (not xtitle) then
         begin

         if      (onumberfrom3>=0) and (p>=onumberfrom3) then str1:=k64(p-onumberfrom3+1)+'. '+str1
         else if (onumberfrom2>=0) and (p>=onumberfrom2) then str1:=k64(p-onumberfrom2+1)+'. '+str1
         else if (onumberfrom>=0)  and (p>=onumberfrom)  then str1:=k64(p-onumberfrom+1)+'. '+str1;

         end;


      ftext( s.back ,ra,xoff+dx,yoff+dy+((rh-th) div 2),xfont,xtab,str1,findex,xenabled);//21mar2026, 26feb2026
      int1:=fast__textwidth(xtab,str1,findex);
      if (not xtitle) and (int1>xmaxcapwidth) then xmaxcapwidth:=int1;

      end;

   //row marker - 04oct2024, 28sep2022
//was:   if xmarkrow then ffillArea(rect(cw-1-xbordersize-xpad-10,dy+2,cw-1-xbordersize-xpad-3,dy+rh-3),fcol,true);
   if xmarkrow then
      begin

      int3:=tepRight;
      tep__info(int3,int1,int2);//aw,ah

      //was: ldis2(ra,0,dy+((rh-int2) div 2),xfont,xfont,int3,(p=ihoverindex) and (xstyle=lsmenu) and xenabled and (not xtitle),not xenabled,s.r);
      ftep2(int3,0,dy+((rh-int2) div 2),xfont,xfont,xfont,xfont,255,xenabled);

      end;

   //hover and click item list
   xlist.addint4(p);
   xlist.addint4(dy);
   xlist.addint4(dy+rh);

   //shortcut - left align within it's column - 21mar2026, 13apr2020
   if (not xtitle) then
      begin

      inc(dx,xmaxcapwidth);

      if low__akstr(xshortcut,str2) and (str2<>'') then
         begin

         ftext( s.back ,area__make(xoff+dx,yoff+dy,cw-1-s.bs,dy+rh-1),cw-1-s.bs-xpad-largest32(xmaxcutwidth,fast__textwidth('',str2,findex)),dy+((rh-th) div 2),xfont,'',str2,findex,xenabled);

         end;

      end;

   //sep
   if xsep then ffillarea( area__make( ra.left ,ra.bottom ,ra.right ,ra.bottom) ,s.sep,s.r);//19may2025

   //next row
   inc(dy,rh);

   //loop
   inc(p);
   goto redo;

   end;

//draw border -> by default a menu has no border and instead relies on the underlying form for a border - 04apr2020
//Menu needs softening as it butts up against many other common controls -> this helps lighten the butt joins - 17mar2021
//was: if (s.bs>=1) then ldf(s.cs,s.border,int__dif24(s.back,-20),s.bs,nil,s.r);//26feb2022
xframeSimple( s );

//merge into existing list
if (xlist.count>=1) then
   begin

   if (xlist.count>ilist.count) then ilist.setlen(xlist.count);

   //was: for p:=0 to (xlist.count-1) do ilist.pbytes[p]:=xlist.pbytes[p];
   //faster - 22apr2022
   for p:=0 to (xlist.count32-1) do
   begin

   v:=xlist.pbytes[p];
   ilist.pbytes[p]:=v;

   end;//p

   end;

ilistcount:=xlist.count32 div 12;

//flash support
iwasflashing:=iflashing;
iflashing:=xflashing;

except;end;

//free
small__free8(@xlist);

end;

//## tbasicbreak ###############################################################
constructor tbasicbreak.create(xparent:tobject;xheight:longint);
begin
create2(xparent,true,xheight);
end;

constructor tbasicbreak.create2(xparent:tobject;xstart:boolean;xheight:longint);
begin
//self
if classnameis('tbasicbreak') then track__inc(satBreak,1);
inherited create2(xparent,false);
//vars
opaint:=false;
iheight:=frcmin32(xheight,0);
ibordersize:=0;
inormal:=true;
//start
if xstart then start;
end;

destructor tbasicbreak.destroy;
begin
try
inherited destroy;
if classnameis('tbasicbreak') then track__inc(satBreak,-1);
except;end;
end;

function tbasicbreak.getalignheight(xclientwidth:longint):longint;
begin
result:=frcmin32(iheight,ominheight);
end;

procedure tbasicbreak._onpaint(sender:tobject);
begin
if opaint then inherited _onpaint(sender);
end;


//## tsimpleint ################################################################
constructor tsimpleint.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tsimpleint.create2(xparent:tobject;xstart:boolean);
begin
//self
if classnameis('tbasicint2') then track__inc(satInt,1);
inherited create2(xparent,false);

//vars
vnone         :=0;
vlabel        :=1;
vbar          :=2;
itimerAUTO    :=slowms64;
itimer250     :=slowms64;
ihightimer    :=0;
ireloadid     :=viloadid;
oautoreload   :=false;
oloadfromname :='';//off
idownval      :=0;
ibordersize   :=0;
inormal       :=true;
ilastval      :=min32;//28jul2021
imin          :=0;
imax          :=0;
idef          :=0;
ival          :=0;
ipaintid      :=0;
ivalid        :=0;
ilastpaintid  :=0;
ilastvalid    :=0;
ialabel       :=nilrect;
iabar         :=nilrect;
iaball        :=nilrect;
idownball     :=nilrect;
idownstyle    :=0;
ihoverstyle   :=0;
ihoverref     :=0;
oalign        :=1;
ohelplabel    :='';
ohelpbar      :='';
ounit         :='';
osep          :=#32#32;
ilastlabel    :='';
icommitref    :=0;
icanmorelessonup:=false;

//start
if xstart then start;
end;

destructor tsimpleint.destroy;
begin
try
inherited destroy;
if classnameis('tbasicint2') then track__inc(satInt,-1);
except;end;
end;

procedure tsimpleint.makemidivol;
begin
makevol(made_midivol);
end;

procedure tsimpleint.makewavevol;
begin
makevol(made_wavevol);
end;

procedure tsimpleint.makevol(xmade:longint);//15aug2025, 09jan2025, 12nov2022
const
   defVol=100;//12nov2022, was 50% - 01mar2022
begin
//range
if (xmade<>made_wavevol) and (xmade<>made_midivol) then xmade:=made_midivol;

//get
omade          :=xmade;
onreadwriteval :=__onvol;
caption        :='Volume';
ounit          :=' %';//09sep2025

case xmade of
made_midivol:begin
   ohelplabel:='Midi Volume | Restore default volume level';
   ohelpbar  :='Midi Volume | Set midi volume level from 0% to 200%.  A volume level above|100% boosts the volume of individual midi notes.';
   setparams(0,200,defVol,mid_vol);
   end;
made_wavevol:begin
   ohelplabel:='Wave Volume | Restore default volume level';
   ohelpbar  :='Wave Volume | Set volume level';
   setparams(0,100,defVol,wav_vol);
   end;
end;//case

end;

procedure tsimpleint.makemiditranspose;//15aug2025, 14feb2025
begin

omade          :=made_miditranspose;
onreadwriteval :=__onvol;
caption        :='Transpose';
ohelplabel     :='Midi Transpose | Restore default transpose level of 0 - notes are|not shifted';
ohelpbar       :='Midi Transpose | Set transpose level from -127 to +127 to shift midi notes|up and down the musical scale';

setparams(-127,127,0,mid_transpose);

end;

procedure tsimpleint.__onvol(sender:tobject;var xval:longint;xwrite:boolean);
begin

case omade of
made_midivol       :if xwrite then mid_setvol(xval)         else xval:=mid_vol;
made_wavevol       :if xwrite then wav_setvol(xval)         else xval:=wav_vol;
made_miditranspose :if xwrite then mid_settranspose(xval)   else xval:=mid_transpose;
end;//case

if low__setint(ival,xval) then low__iroll(ipaintid,1);

end;

procedure tsimpleint.reload;
begin
if (oloadfromname<>'') then setparams3(imin,imax,idef,ival,oloadfromname);
end;

procedure tsimpleint.setparams(xmin,xmax,xdef,xval:longint);
begin
setparams3(xmin,xmax,xdef,xval,'');
end;

procedure tsimpleint.setparams3(xmin,xmax,xdef,xval:longint;xloadfromname:string);
begin
try
//range
if (xmin>xmax) then low__swapint(xmin,xmax);
xdef:=frcrange32(xdef,xmin,xmax);
xval:=frcrange32(xval,xmin,xmax);

//xloadfromname -> overrides "xval" and sets "oloadfromname" in one go - 07sep2020
if (xloadfromname<>'') then
   begin
   oloadfromname:=xloadfromname;
   xval:=frcrange32(ifromname(xloadfromname),xmin,xmax);
   end;

//set
if (xmin<>imin) or (xmax<>imax) or (xdef<>readdef) or (xval<>readval) then
   begin
   imin:=xmin;
   imax:=xmax;
   idef:=xdef;

   if (readval<>xval) then
      begin
      writeval(xval);
      if assigned(fonvalue2) then fonvalue2(self,readval);//26feb2021
      low__iroll(ivalid,1);

      icommitref:=slowms64+1000;//1 sec - 11jul2025
      end;

   low__iroll(ipaintid,1);
   end;
except;end;
end;

procedure tsimpleint.setval(xval:longint);
begin
setparams(imin,imax,idef,xval);
end;

procedure tsimpleint.writeval(xval:longint);
begin
xval:=frcrange32(xval,imin,imax);
if assigned(fonreadwriteval) then fonreadwriteval(self,xval,true) else ival:=xval;
end;

function tsimpleint.readval:longint;
begin
if assigned(fonreadwriteval) then
   begin
   result:=idef;
   fonreadwriteval(self,result,false);
   end
else result:=ival;

//enforce range
result:=frcrange32(result,imin,imax);
end;

function tsimpleint.readdef:longint;
begin
result:=idef;
if assigned(fonreadwritedef) then fonreadwritedef(self,result,false);

//enforce range
result:=frcrange32(result,imin,imax);
end;

procedure tsimpleint._ontimer(sender:tobject);
var
   xmustpaint:boolean;
begin
try
xmustpaint:=false;

//reload - 07sep2020
if oautoreload and (ireloadid<>viloadid) and (not visyncing) and ((not focused) or (not gui.mousedown)) then
   begin
   ireloadid:=viloadid;
   reload;
   end;

//valid
if (ilastvalid<>ivalid) then
   begin
   ilastvalid:=ivalid;
   xonvalue;
   end;

//paintid
if (ilastpaintid<>ipaintid) then
   begin
   ilastpaintid:=ipaintid;
   xmustpaint:=true;
   end;

//readval
if (slowms64>=itimer250) then
   begin

   if ((not focused) or (not gui.mousedown)) and (not visyncing) and assigned(fonreadwriteval) and low__setint(ilastval,readval) then
      begin
      val:=readval;
      xmustpaint:=true;//fixed - 28jul2021
      end;

   //detect changes in label - 11jul2025
   if assigned(ffindlabel) and low__setstr(ilastlabel,xfindlabel) then xmustpaint:=true;

   //value commit event - 11jul2025
   if (icommitref<>0) and (not gui.mousedown) and (slowms64>=icommitref) then
      begin

      //fire event
      if assigned(foncommitvalue) then foncommitvalue(self);

      //turn off
      icommitref:=0;

      end;


   //reset
   itimer250:=slowms64+250;
   end;

//auto-click when mouse/tap is held down - 09mar2022
if (slowms64>=itimerAUTO) and (not gui.mousedraggingfine) and (gui.mousedowntime>=1000) then
   begin
   //get
   if enabled and (idownstyle=vbar) then
      begin
      icanmorelessonup:=false;
      xmoreless;
      end;

   //dynamic reset
   itimerAUTO:=slowms64+div64(frcmin64(3000-gui.mousedowntime,0),10);
   end;

//highlight timer
if (ihightimer<>0) and (slowms64>ihightimer) then
   begin
   ihightimer:=0;
   xmustpaint:=true;
   end;

//xmustpaint
if xmustpaint then paintnow;
except;end;
end;

function tsimpleint.xrowheight:longint;//10dec2025
begin
result:=virowheight20orLESS;
end;

function tsimpleint.getalignheight(xclientwidth:longint):longint;
begin
result:=frcmin32( (2*xrowheight) + (2*frcmin32(findbordersize,1)), scale__px0(ominheight) );
end;

procedure tsimpleint._onpaint(sender:tobject);
var
   s:tclientinfo;
   xtouch,xhighbar,xdownlabel,xenabled:boolean;
   xval,tw,vsp,xlineheight,hsp,int0,int1,int2,int3,int4:longint;
   ta,ba,da,da2:twinrect;
   z:string;
begin
try

//init
infovars(s);
xval        :=val;
xlineheight :=xrowheight;//05sep2025
vsp         :=vilineVsep1orLESS;//2 per line
hsp         :=2*s.zoom;
xtouch      :=vitouch;
xenabled    :=enabled;
xdownlabel  :=gui.mousedown and (ihoverstyle=vlabel);
xhighbar    :=(gui.mousedown and (idownstyle=vbar)) or (ihightimer>slowms64);

//cls
ffillArea(s.cs,s.back,false);

//label
z:=xfindlabel;
ilastlabel:=z;

if (z<>'') then
   begin
   tw:=fast__textwidth('',z,s.Rfn);

   case oalign of
   1   :ta.left:=s.ci.left+ (((s.ci.right-s.ci.left+1)-tw) div 2);//center
   2   :ta.left:=s.ci.right-tw-hsp;//right
   else ta.left:=s.ci.left+hsp;//left
   end;//case

   ta :=area__make(ta.left,s.ci.top+1,ta.left+tw-1,s.ci.top+1+xlineheight);
   da2:=area__make(s.ci.left,s.ci.top,s.ci.right,s.ci.top+1+s.fnH);

   //hover focus
   if xenabled and (ihoverstyle=vlabel) then ffillArea(da2,s.hover,s.r);

   //label
   ftext( s.back ,s.ci,ta.left+insint(s.zoom,xdownlabel),ta.top+insint(s.zoom,xdownlabel),s.font,'',z,s.Rfn,true);

   //click area
   ialabel:=da2;

   end
else ialabel:=nilarea;


//bar outer area
da.left    :=s.ci.left   + hsp;
da.right   :=s.ci.right  - hsp;
da.top     :=s.ci.bottom -1 - (xlineheight - (2*vsp));
da.bottom  :=s.ci.bottom -1 - vsp;


//bar-line
ba         :=da;
ba.top     :=ba.top+(ba.bottom-ba.top) div 2;
ba.bottom  :=ba.top+s.zoom;

if xenabled and ((ihoverstyle=vbar) or (idownstyle=vbar)) then
   begin
   dec(ba.top,s.zoom);
   inc(ba.bottom,s.zoom);
   end;

ffillArea(ba,s.line,false);

//.ball
int4:=scale__px1(10,2);//ball width
int0:=frcmin32(da.right-da.left+1-int4,1);
int1:=frcmin32(imax-imin,1);
int2:=xval-imin;
int3:=frcrange32(round(int0*(int2/int1)),0,int0);

da2.top     :=da.top;
da2.bottom  :=da.bottom;
da2.left    :=da.left+frcmin32(int3-1,0);
da2.right   :=da2.left+int4;
iaball      :=da2;

//.bar-line usage indicator
if (da2.left>ba.left) then ffillArea(area__make(ba.left,ba.top,da2.left,ba.bottom),low__aorb(s.line2,s.colhover,xhighbar),s.r);

if ((idownstyle<>vbar) and (ihoverstyle<>vbar)) or (not enabled) then
   begin
   inc(da2.top,2*s.zoom);
   dec(da2.bottom,2*s.zoom);
   end;

//.draw ball
ffillArea(da2,s.font,s.r);
if xhighbar then ffillArea(area__grow(da2,-3*s.zoom),s.colhover,s.r);

//click area
iabar:=da;

//frame
xframeSimple( s );

except;end;
end;

function tsimpleint.vfind(x:tpoint):longint;
begin
if      area__within2(ialabel,x) then result:=vlabel
else if area__within2(iabar,x)   then result:=vbar
else                                  result:=vnone;
end;

function tsimpleint._onnotify(sender:tobject):boolean;
var
   int1,int2:longint;
   xmustpaint:boolean;
begin
//defaults
result    :=false;
xmustpaint:=false;

try
//wheel
if (gui.wheel<>0) then
   begin
   if enabled then
      begin
      val:=val-gui.wheel;
      result:=true;//own the wheel
      end;
   end;

//key
if (gui.key<>aknone) then
   begin
   case gui.key of
   akhome:begin
      if enabled then val:=imin;
      result:=true;
      end;
   akend:begin
      if enabled then val:=imax;
      result:=true;
      end;
   akleft,akup:begin
      if enabled then val:=val-1;
      result:=true;
      end;
   akright,akdown:begin
      if enabled then val:=val+1;
      result:=true;
      end;
   akprev:begin
      if enabled then val:=val-1;
      result:=true;
      end;
   aknext:begin
      if enabled then val:=val+1;
      result:=true;
      end;
   end;//case
   end;

//mouse down
if gui.mousedownstroke then
   begin
   idownval        :=val;
   idownstyle      :=vfind(mousedownxy);
   idownball       :=iaball;
   icanmorelessonup:=true;
   if (idownstyle=vbar) then ihightimer:=slowms64+250;

   //paint
   xmustpaint:=true;
   end;

//mouse move
if gui.mousemoved then
   begin
   //.hover state
   ihoverstyle:=vfind(mousemovexy);

   if      (ihoverstyle=vlabel) then help:=strdefb(ohelplabel,'Default|Click for default value')
   else if (ihoverstyle=vbar)   then help:=strdefb(ohelpbar,'Value|Slide to change value')
   else                              help:='';

   if low__setint(ihoverref,ihoverstyle) then xmustpaint:=true;

   //.shift bar ball
   if gui.mousedown and gui.mousedraggingfine and (not gui.mousedownstroke) and (idownstyle=vbar) then
      begin
      icanmorelessonup:=false;
      int1:=mousexy.x-mousedownxy.x;
      int2:=round((int1/frcmin32(clientwidth,1))*(imax-imin+1));
      val:=idownval+int2;
      end;
   end;

//mouse up
if gui.mouseupstroke then
   begin
   if (idownstyle=vlabel) then xclicklabel;

   //click more/less
   if (idownstyle=vbar) and icanmorelessonup then xmoreless;

   //reset
   if (idownstyle<>vnone) then
      begin
      idownstyle:=vnone;
      xmustpaint:=true;
      end;
   end;

//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);

//paint
if xmustpaint then paintnow;
except;end;
end;

procedure tsimpleint.xmoreless;//06jun2025

   function vdir(vball:twinrect):longint;
   var
      vpad:longint;
   begin
   vpad:=3*vizoom;

   if not area__valid(vball)                  then result:=0
   else if (mousemovexy.x<(vball.left -vpad)) then result:=-1//down
   else if (mousemovexy.x>(vball.right+vpad)) then result:=+1//up
   else                                            result:=0;
   end;
begin

//.adjustment relative to ball position
if (vdir(idownball)=vdir(iaball)) then
   begin
   case vdir(idownball) of
   -1:val:=val-1;
   +1:val:=val+1;
   end;//case
   end;

end;

function tsimpleint.xfindlabel:string;
begin
result:=icaption+osep+k64(val)+ounit;
if assigned(ffindlabel) then ffindlabel(self,result);
end;

procedure tsimpleint.xclicklabel;//11jul2025
begin
if (not assigned(fclicklabel)) or (not fclicklabel(self)) then setparams(imin,imax,readdef,readdef);
end;


//## tbasicset #################################################################
constructor tbasicset.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tbasicset.create2(xparent:tobject;xstart:boolean);
var
   p:longint;
begin
//self
if classnameis('tbasicset') then track__inc(satSet,1);
inherited create2(xparent,false);
//vars
itimer250:=slowms64;
ireloadid:=viloadid;
oshowtitle:=true;
oflatback:=true;//24jul2024
oautoreload:=false;
ovpad:=0;
for p:=0 to high(icaps) do
begin
icaps[p]:='';
inams[p]:='';
ihlps[p]:='';
ivisb[p]:=true;
iloadfromnames[p]:='';
end;//p
idownindex  :=-1;
ihoverindex :=-1;//03jun2025
ibordersize:=0;//was: 1
inormal:=true;
idef:=0;
ival:=0;
ipaintid:=0;
ivalid:=0;
ilastpaintid:=0;
ilastvalid:=0;
icount:=0;
ilastcount:=0;
iitemsperline:=0;//no limit => all items on one line only - 28aug2020
ilastval:=0;
xnorects;
//start
if xstart then start;
end;

destructor tbasicset.destroy;
begin
try
inherited destroy;
if classnameis('tbasicset') then track__inc(satSet,-1);
except;end;
end;

procedure tbasicset.makesleek;
begin
oflatback:=true;
end;

procedure tbasicset.makesleek2;
begin
oflatback:=true;
oshowtitle:=false;
end;

procedure tbasicset.ysetval(xval:longint);
var
   v:tbasicset_valarray;
   a:tint4;
   p:longint;
begin
try

if assigned(fonreadwriteval) then
   begin

   //get
   a.val:=xval;
   for p:=0 to high(icaps) do v[p]:=(p in a.bits);
   fonreadwriteval(self,v,true);

   end
else ival:=xval;

except;end;
end;

function tbasicset.ygetval:longint;
var
   v:tbasicset_valarray;
   a:tint4;
   p:longint;
begin
//defaults
result:=idef;

try

//get
if assigned(fonreadwriteval) then
   begin

   //get
   for p:=0 to high(icaps) do v[p]:=false;
   fonreadwriteval(self,v,false);

   //set
   a.val:=0;
   for p:=0 to high(icaps) do if v[p] then include(a.bits,p);
   result:=a.val;

   end
else result:=ival;

except;end;
end;

procedure tbasicset.setitemsperline(x:longint);
begin
setparams2(idef,yval,x);
end;

procedure tbasicset.reload;
var
   p:longint;
begin
try;for p:=0 to high(iloadfromnames) do if (iloadfromnames[p]<>'') and (icaps[p]<>'') then xset3(p,icaps[p],inams[p],ihlps[p],vals[p],iloadfromnames[p]);except;end;
end;

procedure tbasicset.setparams(xdef,xval:longint);
begin
setparams2(xdef,xval,iitemsperline);
end;

procedure tbasicset.setparams2(xdef,xval,xitemsperline:longint);
begin
//range
xitemsperline:=frcrange32(xitemsperline,0,100);
//set
if (xdef<>idef) or (xval<>yval) or (xitemsperline<>iitemsperline) then
   begin
   idef:=xdef;
   if (yval<>xval) then
      begin
      yval:=xval;
      low__iroll(ivalid,1);
      end;
   iitemsperline:=xitemsperline;
   low__iroll(ipaintid,1);
   end;
end;

procedure tbasicset.xnorects;
var
   p:longint;
begin
for p:=0 to high(icaps) do irecs[p]:=nilrect;
end;

procedure tbasicset.setval(xval:longint);
begin
setparams(idef,xval);
end;

procedure tbasicset._ontimer(sender:tobject);
var
   xmustalign,xmustpaint:boolean;
begin
try
//defaults
xmustalign:=false;
xmustpaint:=false;

//reload - 07sep2020
if oautoreload and (ireloadid<>viloadid) and (not visyncing) and ((not focused) or (not gui.mousedown)) then
   begin
   ireloadid:=viloadid;
   reload;
   end;

//valid
if (ilastvalid<>ivalid) then
   begin
   ilastvalid:=ivalid;
   xonvalue;
   end;
//alignid
if (ilastitemsperline<>iitemsperline) or (ilastcount<>icount) then
   begin
   ilastitemsperline:=iitemsperline;
   ilastcount:=icount;
   xmustalign:=true;
   end;
//paintid
if (ilastpaintid<>ipaintid) then
   begin
   ilastpaintid:=ipaintid;
   xmustpaint:=true;
   end;
//mustpaint
if (slowms64>=itimer250) then
   begin
   if assigned(onreadwriteval) and (not visyncing) and ((not focused) or (not gui.mousedown)) and low__setint(ilastval,val) then xmustpaint:=true;
   itimer250:=slowms64+250;
   end;

//xmustpaint
if xmustalign then alignnow;
if xmustpaint then paintnow;
except;end;
end;

function tbasicset.linecount:longint;
begin
if (iitemsperline>=1) then
   begin
   result:=icount div iitemsperline;
   if ((result*iitemsperline)<>icount) then inc(result);
   end
else result:=1;
end;

function tbasicset.xrowheight:longint;//10dec2025
begin
result:=virowheight20orLESS;
end;

function tbasicset.getalignheight(xclientwidth:longint):longint;//10dec2025
begin
result:=frcmin32( ((low__insint(1,oshowtitle)+linecount)*xrowheight)+((2+ovpad)*frcmin32(findbordersize,1)) ,scale__px0(ominheight) );
end;

procedure tbasicset.xsynccount;
var
   p,int1:longint;
begin
int1:=0;
for p:=0 to high(icaps) do if (low__len32(icaps[p])>=1) then inc(int1);
icount:=int1;
end;

procedure tbasicset.xset(xindex:longint;xcap,xnam,xhlp:string;xval:boolean);
begin
xset3(xindex,xcap,xnam,xhlp,xval,'');
end;

procedure tbasicset.xset3(xindex:longint;xcap,xnam,xhlp:string;xval:boolean;xloadfromname:string);
begin
if (xindex>=0) and (xindex<=high(icaps)) then
   begin
   if (xloadfromname<>'') then xval:=bfromname(xloadfromname);
   icaps[xindex]:=xcap;
   inams[xindex]:=xnam;
   ihlps[xindex]:=xhlp;
   iloadfromnames[xindex]:=xloadfromname;
   vals[xindex]:=xval;
   xsynccount;
   end;
end;

function tbasicset.getcaps(xindex:longint):string;
begin
if (xindex>=0) and (xindex<=high(icaps)) then result:=icaps[xindex] else result:='';
end;

procedure tbasicset.setcaps(xindex:longint;xval:string);
begin
if (xindex>=0) and (xindex<=high(icaps)) and (xval<>icaps[xindex]) then
   begin
   icaps[xindex]:=xval;
   xsynccount;
   low__iroll(ipaintid,1);
   end;
end;

function tbasicset.getnams(xindex:longint):string;
begin
if (xindex>=0) and (xindex<=high(icaps)) then result:=inams[xindex] else result:='';
end;

procedure tbasicset.setnams(xindex:longint;xval:string);
begin
if (xindex>=0) and (xindex<=high(icaps)) and (xval<>inams[xindex]) then
   begin
   inams[xindex]:=xval;
   low__iroll(ipaintid,1);
   end;
end;

function tbasicset.getvisb(xindex:longint):boolean;//31jul2021
begin
if (xindex>=0) and (xindex<=high(ivisb)) then result:=ivisb[xindex] else result:=false;
end;

procedure tbasicset.setvisb(xindex:longint;xval:boolean);
begin
if (xindex>=0) and (xindex<=high(ivisb)) and (xval<>ivisb[xindex]) then
   begin
   ivisb[xindex]:=xval;
   low__iroll(ipaintid,1);
   end;
end;

function tbasicset.getvals(xindex:longint):boolean;
var
   a:tint4;
begin
if (xindex>=0) and (xindex<=high(icaps)) then
   begin
   a.val:=yval;
   result:=(xindex in a.bits);
   end
else result:=false;
end;

procedure tbasicset.setvals(xindex:longint;xval:boolean);
var
   a:tint4;
   bol1:boolean;
begin
if (xindex>=0) and (xindex<=high(icaps)) then
   begin
   a.val:=yval;
   bol1:=(xindex in a.bits);
   if (bol1<>xval) then
      begin
      if xval then include(a.bits,xindex) else exclude(a.bits,xindex);
      val:=a.val;
      end;
   end;
end;

function tbasicset.findname(xname:string;var xindex:longint):boolean;
var
   p:longint;
begin
//defaults
result:=false;
xindex:=0;
//check
if (xname='') then exit;
//find
for p:=0 to high(inams) do
begin
if (inams[p]<>'') and strmatch(xname,inams[p]) then
   begin
   xindex:=p;
   result:=true;
   break;
   end;
end;//p
end;

function tbasicset.getvals2(xname:string):boolean;
var
   xindex:longint;
begin
result:=findname(xname,xindex) and vals[xindex];
end;

procedure tbasicset.setvals2(xname:string;xval:boolean);
var
   xindex:longint;
begin
if findname(xname,xindex) then vals[xindex]:=xval;
end;

function tbasicset.viscount:longint;
var
   p:longint;
begin
result:=0;
for p:=0 to (icount-1) do if ivisb[p] then inc(result);
end;

procedure tbasicset._onpaint(sender:tobject);
var
   s:tclientinfo;
   xdown:boolean;
   xhoverindex,int1,dcount,vcount,vsp,hsp,xlineheight,xlinecount,xcount,xsetwidth,xcapright,p,dx,dy:longint;
   z:string;
   v:tint4;

   function xlink(zindex:longint;zdraw:boolean):twinrect;
   var
      tw:longint;
      z:string;
      zdown,zhighlight:boolean;
   begin

   //defaults
   result   :=nilrect;

   //check
   z        :=icaps[zindex];
   if (z='') then exit;

   //get
   z        :=#32+z+#32;
   tw       :=fast__textwidth('',z,s.Rfn);
   int1     :=xlineheight - (2*vsp) - 1;
   result   :=area__make(dx,dy+vsp,dx+xsetwidth-1,dy+int1);

   if zdraw then
      begin
      //.down
      zdown:=xdown and (xhoverindex=zindex);

      //.highlight
      zhighlight:=(zindex in v.bits);

      //.cls
      if      zhighlight           then ffillArea(area__shift(result,insint(vsp,zdown),insint(vsp,zdown)),s.font,s.r)
      else if (xhoverindex=zindex) then ffillArea(area__shift(result,insint(vsp,zdown),insint(vsp,zdown)),s.hover,s.r);

      //.text
      ftext( low__aorb(s.back,s.font,zhighlight) ,result,dx+((xsetwidth-tw) div 2)+insint(s.zoom,zdown),dy+vsp+((int1-s.fnH) div 2)+insint(s.zoom,zdown),low__aorb(s.font,s.back,zhighlight),'',z,s.Rfn,true);

      end;

   end;

begin
try
//init
infovars(s);

//.xcount + xsetwidth
hsp                :=2*s.zoom;
vsp                :=vilineVsep1orLESS;
xlineheight        :=xrowheight;//05sep2025
v.val              :=yval;
xlinecount         :=linecount;
xcount             :=low__aorb(icount,itemsperline,itemsperline>=1);
vcount             :=low__aorb(viscount,itemsperline,itemsperline>=1);
xsetwidth          :=frcmin32( (s.ci.right-s.ci.left+1-((vcount+1)*hsp)) div frcmin32(vcount,1),1);
xhoverindex        :=ihoverindex;
xdown              :=gui.mousedown and focused;

//cls
ffillArea(s.cs,s.back,false);

//caption
xcapright :=s.ci.left+(5*s.zoom);
z         :=caption;

if (z<>'') and oshowtitle then
   begin

   ftext( s.back ,s.ci,xcapright,s.ci.top+1,s.font,'',z,s.Rfn,true);

   end;

//links
dx       :=s.ci.left+hsp;
dy       :=s.ci.bottom-(xlinecount*xlineheight)+vsp-1;
dcount   :=1;

for p:=0 to high(icaps) do
begin

if (icaps[p]<>'') and ivisb[p] then
   begin

   irecs[p] :=xlink(p,true);

   inc(dx,xsetwidth+hsp);
   inc(dcount);

   if (dcount>xcount) then
      begin

      dcount :=1;
      dx     :=s.ci.left+hsp;

      inc(dy,xlineheight);

      end;

   end
else irecs[p]:=nilrect;

end;//p

//frame
xframeSimple( s );

except;end;
end;

function tbasicset._onnotify(sender:tobject):boolean;
var
   p:longint;

   function xfinditem(s:tpoint;var xindex:longint):boolean;
   var
      p:longint;
   begin
   result:=false;
   xindex:=-1;
   for p:=0 to high(icaps) do if (icaps[p]<>'') and area__within2(irecs[p],s) then
      begin
      xindex:=p;
      result:=true;
      break;
      end;
   end;
begin
//defaults
result:=false;

try
//wheel
if (gui.wheel<>0) then
   begin
   //not used: if enabled then val:=val-gui.wheel;
   end;

//key
if (gui.key<>aknone) then
   begin
//   case gui.key of
//   end;//case
   end;

//mouse down
if gui.mousedownstroke then
   begin
   xfinditem(mousedownxy,idownindex);
   ihoverindex:=idownindex;
   paintnow;
   end;

//help
if gui.mousemoved and (not gui.mousedown) then
   begin
   if xfinditem(mousexy,p) then help2:=ihlps[p] else help2:='';
   if low__setint(ihoverindex,p) then paintnow;
   end;

//mouse up
if gui.mouseupstroke then
   begin
   if (idownindex>=0) and (idownindex<=high(icaps)) then vals[idownindex]:=not vals[idownindex];
   //reset
   if (idownindex>=0) then
      begin
      idownindex  :=-1;
      paintnow;
      end;
   end;

//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);
except;end;
end;

//## tbasicsel #################################################################
constructor tbasicsel.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tbasicsel.create2(xparent:tobject;xstart:boolean);
var
   p:longint;
begin

//self
if classnameis('tbasicsel') then track__inc(satSel,1);
inherited create2(xparent,false);

//vars
oshowtitle           :=true;
oflatback            :=true;//24jul2024
iwasselected         :=false;
ireloadid            :=viloadid;
itimer500            :=slowms64;
oboldhead            :=false;
omididevice          :=false;
owavedevice          :=false;
owinedevice          :=false;
oautoreload          :=false;
oloadfromname        :='';//off
ovalueclick          :=false;
for p:=0 to high(icaps) do
begin
istrs[p]             :='';
icaps[p]             :='';
inams[p]             :='';
ihlps[p]             :='';
end;//p
icount               :=0;
ilastitemsperline    :=0;
ilastcount           :=0;
iitemsperline        :=0;
idownindex           :=-1;
ihoverindex          :=-1;
ibordersize          :=0;//was: 1
inormal              :=true;
idef                 :=0;
ival                 :=0;
imax                 :=0;
ipaintid             :=0;
ivalid               :=0;
ilastpaintid         :=0;
ilastvalid           :=0;
xnorects;

//start
if xstart then start;

end;

destructor tbasicsel.destroy;
begin
try
inherited destroy;
if classnameis('tbasicsel') then track__inc(satSel,-1);
except;end;
end;

function tbasicsel.getval2(xmin:longint):longint;
begin
result:=add32(val,xmin);
end;

procedure tbasicsel.setval2(xmin,xval:longint);
begin
val:=add32(xval,-xmin);
end;

procedure tbasicsel.makesleek;
begin
oflatback:=true;
end;

procedure tbasicsel.makesleek2;
begin
oflatback:=true;
oshowtitle:=false;
end;

function tbasicsel.makemididevice:tbasicsel;//09sep2025, 21aug2025
var
   p:longint;

   function xname:string;
   begin

   case p of
   mmsys_mid_broadcast   :result:='All Midi Devices';
   mmsys_mid_midimapper  :result:='Midi Mapper';
   else                   result:='Midi Device #'+intstr32(p+1);
   end;//case

   end;

begin

//pass-thru
result:=self;

//device list
help:='Select midi playback device';
for p:=mid_safeDeviceIndexRange(min32) to mid_safeDeviceIndexRange(max32) do xadd('-',intstr32(p),'Playback Device|'+xname);

xsyncmididevice(true);
omididevice:=true;

end;

function tbasicsel.makewavedevice:tbasicsel;//21aug2025
var
   p:longint;
begin

//defaults
result:=self;//pass-thru

try

//.devicelist
help:='Select wave playback device';
for p:=0 to frcmax32((wav_devicelimit-1),19) do xadd('-',intstr32(p),'Playback Device|'+low__aorbstr('Wave Mapper','Wave Device #'+intstr32(p),p>=1));
xsyncwavedevice(true);
owavedevice:=true;

except;end;
end;

procedure tbasicsel.xsyncwinestatus;
var
   str1:string;
begin

if (viwinemode=1)          then str1:='Manually Enabled'
else if (viwinemode=2)     then str1:='Manually Disabled'
else if system_winepresent then str1:='Detected'
else                            str1:='Not Detected';

caption:='Wine Compatibility ( '+str1+' )';

end;

procedure tbasicsel.xsyncmididevice(xforce:boolean);
var
   str1,str2:string;
   xmin,xmax,int1:longint;

   procedure xdevicelist;
   var
      dp,i,p2,p:longint;
      bol1,iok:boolean;
      xname,str1,str2:string;

      procedure s(const xlabel,xname:string);
      begin

      str1:=xlabel;
      str2:=xname;

      end;

   begin
   try

   //init
   i     :=val2[xmin];
   iok   :=mid_deviceok(i);
   xname :='';

   //fill list GUI
   for p:=0 to max do
   begin

   //.shift range to match system device mapping range (-2..devicecount-1) - 09sep2025
   dp:=p+xmin;

   case dp of
   mmsys_mid_broadcast    :s('A', mid_devicename(dp,'') );
   mmsys_mid_midimapper   :s('M', mid_devicename(dp,'') );
   else
      begin

      bol1:=mid_deviceok(dp);
      s( low__aorbstr('-', k64(dp+1),bol1), insstr(mid_devicename(dp,''),bol1) );

      end;

   end;//case

   if not strmatch(caps[p],str1) then caps[p]:=str1;
   if not strmatch(strs[p],str2) then strs[p]:=str2;//12may2021

   //find left
   if (not iok) and (i>mmsys_mid_devicestart) then
      begin

      for p2:=(i-1) downto mmsys_mid_devicestart do if mid_deviceok(p2) then
         begin

         val :=p2-xmin;
         iok :=true;
         break;

         end;

      end;

   //find right
   if (not iok) and (i<mmsys_mid_devicefinish) then
      begin

      for p2:=(i+1) to mmsys_mid_devicefinish do if mid_deviceok(p2) then
         begin

         val :=p2-xmin;
         iok :=true;
         break;

         end;

      end;

   end;//p2

   except;end;
   end;
begin
try

//init
xmin   :=mid_safeDeviceIndexRange(min32);
xmax   :=mid_safeDeviceIndexRange(max32);

if (vimidideviceNew>min32) then
   begin

   val               :=mid_safeDeviceIndexRange(vimidideviceNew)-xmin;//-2..N -> 0..N+2
   vimidideviceNew   :=min32;//off

   end;

//sync device list
if xforce or (low__inputidle_nomove>=1000) then xdevicelist;

//get
int1  :=mid_safeDeviceIndexRange(val+xmin);

if visyssettingsloaded and low__setint(vimididevice,int1) and (int1<>syssettings.i['mididevice']) then
   begin

   syssettings.i['mididevice']:=int1;
   viSyncandsave;

   end;

if (not gui.mousedown) and (vimididevice<>mid_deviceindex) then mid_setdeviceindex(vimididevice);

//set
int1   :=val+xmin;
str1   :=mid_devicename( int1,'');

if (int1=mmsys_mid_broadcast) then str1:=str1+' ( '+k64(mid_devicecount)+'x )';

str2   :='Playback Device'+insstr(': ',str1<>'')+str1;
if not strmatch(caption,str2) then caption:=str2;

except;end;
end;

procedure tbasicsel.xsyncwavedevice(xforce:boolean);
var
   str1,str2:string;
   int1:longint;

   procedure xdevicelist;
   var
      i,p2,p:longint;
      iok:boolean;
      xname,str1,str2:string;
   begin
   try
   //init
   i:=val;
   iok:=wav_deviceok(i);
   xname:='';
   //fill list GUI
   for p:=0 to max do
   begin
   if (p>=1) and (not wav_deviceok(p)) then
      begin
      str1:='-';
      str2:='';
      end
   else
      begin
      str1:=low__aorbstr('Map',intstr32(p),p>=1);
      str2:=wav_devicename(p,'');//allow nil
      end;
   if not strmatch(caps[p],str1) then caps[p]:=str1;
   if not strmatch(strs[p],str2) then strs[p]:=str2;//12may2021
   //find left
   if (not iok) and (i>=1) then
      begin
      for p2:=(i-1) downto 0 do if wav_deviceok(p2) then
         begin
         val:=p2;
         iok:=true;
         break;
         end;
      end;
   //find right
   if (not iok) and (i<max) then
      begin
      for p2:=(i+1) to max do if wav_deviceok(p2) then
         begin
         val:=p2;
         iok:=true;
         break;
         end;
      end;
   end;//p2
   except;end;
   end;
begin
try
//init
if (viwavedeviceNew>=0) then
   begin
   val:=viwavedeviceNew;
   viwavedeviceNew:=-1;//off
   end;
//sync device list
if xforce or (low__inputidle_nomove>=1000) then xdevicelist;
//get
int1:=frcrange32(val,0,99);
if visyssettingsloaded and low__setint(viwavedevice,int1) and (int1<>syssettings.i['wavedevice']) then
   begin
   syssettings.i['wavedevice']:=int1;
   viSyncandsave;
   end;
if (not gui.mousedown) and (viwavedevice<>wav_deviceindex) then wav_setdeviceindex(viwavedevice);
//set
str1:=wav_devicename(val,'');
str2:='Playback Device'+insstr(': ',str1<>'')+str1;
if not strmatch(caption,str2) then caption:=str2;
except;end;
end;

procedure tbasicsel.settep(x:longint);
begin
if low__setint(itep,x) then paintnow;
end;

procedure tbasicsel.reload;
begin
if (oloadfromname<>'') then setparams3(idef,ival,iitemsperline,oloadfromname);
end;

function tbasicsel.findname(xnam:string;var xindex:longint):boolean;
var
   p:longint;
begin
//defaults
result:=false;
xindex:=0;

try
//find
for p:=0 to high(inams) do
begin
if strmatch(inams[p],xnam) then
   begin
   xindex:=p;
   result:=true;
   break;
   end
else if (icaps[p]='') then break;
end;//p
except;end;
end;

procedure tbasicsel.setitemsperline(x:longint);
begin
setparams2(idef,ival,x);
end;

procedure tbasicsel.setparams(xdef,xval:longint);
begin
setparams2(xdef,xval,iitemsperline);
end;

procedure tbasicsel.setparams2(xdef,xval,xitemsperline:longint);
begin
setparams3(xdef,xval,xitemsperline,'');
end;

procedure tbasicsel.setparams3(xdef,xval,xitemsperline:longint;xloadfromname:string);
var
   n:string;
   p:longint;
begin
try
//range
xval:=frcrange32(xval,0,imax);
xitemsperline:=frcrange32(xitemsperline,0,100);
//xloadfromname -> overrides "xval" and sets "oloadfromname" in one go - 07sep2020
if (xloadfromname<>'') then
   begin
   oloadfromname:=xloadfromname;
   n:=sfromname(xloadfromname);
   for p:=0 to high(inams) do
   begin
   if strmatch(inams[p],n) then
      begin
      xval:=p;
      break;
      end
   else if (icaps[p]='') then break;
   end;//p
   end;
//set
if (xdef<>idef) or (xval<>ival) or (xitemsperline<>iitemsperline) then
   begin
   idef:=xdef;
   if (readval<>xval) then
      begin
      writeval(xval);
      low__iroll(ivalid,1);
      end;
   iitemsperline:=xitemsperline;
   low__iroll(ipaintid,1);
   end;
except;end;
end;

procedure tbasicsel.xnorects;
var
   p:longint;
begin
for p:=0 to high(icaps) do irecs[p]:=nilrect;
end;

procedure tbasicsel.setval(xval:longint);
begin
setparams(idef,xval);
end;

procedure tbasicsel.writeval(xval:longint);
begin
if assigned(fonreadwriteval) then
   begin
   xval:=frcrange32(xval,0,imax);
   fonreadwriteval(self,xval,true);
   end;
ival:=frcrange32(xval,0,imax);
end;

function tbasicsel.readval:longint;
begin
result:=ival;
if assigned(fonreadwriteval) then fonreadwriteval(self,result,false);
result:=frcrange32(result,0,imax);
end;

procedure tbasicsel._ontimer(sender:tobject);
var
   xmustalign,xmustpaint:boolean;
begin
try
//defaults
xmustalign:=false;
xmustpaint:=false;

//reload - 07sep2020
if oautoreload and (ireloadid<>viloadid) and (not visyncing) and ((not focused) or (not gui.mousedown)) then
   begin
   ireloadid:=viloadid;
   reload;
   end;

//valid
if (ilastvalid<>ivalid) then
   begin
   ilastvalid:=ivalid;
   xonvalue;
   end;

//timer500
if (slowms64>=itimer500) then
   begin

   //get
   if      omididevice then xsyncmididevice(false)//05mar2022
   else if owavedevice then xsyncwavedevice(false)
   else if owinedevice then xsyncwinestatus;//09sep2025

   //reset
   itimer500:=slowms64+500;

   end;


//alignid
if (ilastitemsperline<>iitemsperline) or (ilastcount<>icount) then
   begin
   ilastitemsperline:=iitemsperline;
   ilastcount:=icount;
   xmustalign:=true;
   end;
//paintid
if (ilastpaintid<>ipaintid) then
   begin
   ilastpaintid:=ipaintid;
   xmustpaint:=true;
   end;
//xmustpaint
if xmustalign then alignnow;
if xmustpaint then paintnow;
except;end;
end;

function tbasicsel.linecount:longint;
begin
if (iitemsperline>=1) then
   begin
   result:=icount div iitemsperline;
   if ((result*iitemsperline)<>icount) then inc(result);
   end
else result:=1;
end;

function tbasicsel.xrowheight:longint;//10dec2025
begin
result:=virowheight20orLESS;
end;

function tbasicsel.getalignheight(xclientwidth:longint):longint;//10dec2025
begin
result:=frcmin32( ((low__insint(1,oshowtitle)+linecount)*xrowheight)+(2*frcmin32(findbordersize,1)) ,scale__px0(ominheight) );
end;

procedure tbasicsel.xclear;
var
   p:longint;
begin
for p:=0 to high(icaps) do
begin
istrs[p]:='';
icaps[p]:='';
inams[p]:='';
ihlps[p]:='';
end;//p

val:=0;
xsynccount;
end;

procedure tbasicsel.xadd(xcap,xnam,xhlp:string);
begin
xadd2(xcap,xnam,xhlp,'');
end;

procedure tbasicsel.xadd2(xcap,xnam,xhlp,xstr:string);
var
   p:longint;
begin
for p:=0 to high(icaps) do if (icaps[p]='') then
   begin
   istrs[p]:=xstr;//12may2021
   icaps[p]:=xcap;
   inams[p]:=xnam;//07sep2020
   ihlps[p]:=xhlp;
   break;
   end;

xsynccount;
end;

procedure tbasicsel.xsynccount;
var
   p,int1,int2:longint;
begin
int1:=0;
int2:=0;
for p:=0 to high(icaps) do if (low__len32(icaps[p])>=1) then
   begin
   inc(int1);
   int2:=p;
   end;

icount:=int1;
imax:=int2;
end;

function tbasicsel.getcaps(xindex:longint):string;
begin
if (xindex>=0) and (xindex<=high(icaps)) then result:=icaps[xindex] else result:='';
end;

procedure tbasicsel.setcaps(xindex:longint;xval:string);
begin
if (xindex>=0) and (xindex<=high(icaps)) and (xval<>icaps[xindex]) then
   begin
   icaps[xindex]:=xval;
   xsynccount;
   low__iroll(ipaintid,1);
   end;
end;

function tbasicsel.getnams(xindex:longint):string;
begin
if (xindex>=0) and (xindex<=high(icaps)) then result:=inams[xindex] else result:='';
end;

procedure tbasicsel.setnams(xindex:longint;xval:string);
begin
if (xindex>=0) and (xindex<=high(icaps)) and (xval<>inams[xindex]) then inams[xindex]:=xval;
end;

function tbasicsel.gethlps(xindex:longint):string;//13mar2022
begin
if (xindex>=0) and (xindex<=high(icaps)) then result:=ihlps[xindex] else result:='';
end;

procedure tbasicsel.sethlps(xindex:longint;xval:string);
begin
if (xindex>=0) and (xindex<=high(icaps)) and (xval<>ihlps[xindex]) then ihlps[xindex]:=xval;
end;

function tbasicsel.getstrs(xindex:longint):string;
begin
if (xindex>=0) and (xindex<=high(icaps)) then result:=istrs[xindex] else result:='';
end;

procedure tbasicsel.setstrs(xindex:longint;xval:string);
begin
if (xindex>=0) and (xindex<=high(icaps)) and (xval<>istrs[xindex]) then istrs[xindex]:=xval;
end;

procedure tbasicsel._onpaint(sender:tobject);
const//Supports enhanced shading
   hsp=2;
var
   s:tclientinfo;
   xhoverindex,v,vsp,int1,int2,xtep,dcount,xlineheight,xlinecount,xcount,xsetwidth,xcapright,p,dx,dy:longint;
   xdown:boolean;
   z:string;

   function xlink(zindex:longint;zdraw:boolean):twinrect;
   const
      hsp=2;
   var
      int1,tw:longint;
      z:string;
      zdown,zhighlight:boolean;
   begin

   //defaults
   result     :=nilrect;

   //check
   z          :=icaps[zindex];
   if (z='') then exit;

   //get
   z          :=#32+z+#32;
   tw         :=fast__textwidth('',z,s.Rfn);
   int1       :=xlineheight-(2*vsp)-1;
   result     :=area__make(dx,dy+vsp,dx+xsetwidth-1,dy+int1);

   if zdraw then
      begin

      //.down
      zdown       :=xdown and (xhoverindex=zindex);

      //.highlight
      zhighlight  :=(zindex=v);

      //.cls
      if      zhighlight           then ffillArea(area__shift(result,insint(vsp,zdown),insint(vsp,zdown)),s.font,s.r)
      else if (xhoverindex=zindex) then ffillArea(area__shift(result,insint(vsp,zdown),insint(vsp,zdown)),s.hover,s.r);

      //.text
      ftext( low__aorb(s.back,s.font,zhighlight) ,result,dx+((xsetwidth-tw) div 2)+insint(s.zoom,zdown),dy+vsp+((int1-s.fnH) div 2)+insint(s.zoom,zdown),low__aorb(s.font,s.back,zhighlight),'',z,s.Rfn,true);

      end;

   end;

begin
try

//init
infovars(s);

//.xcount + xsetwidth
vsp                :=vilineVsep1orLESS;
xlineheight        :=xrowheight;//05sel2025
v                  :=ival;
xlinecount         :=linecount;
xcount             :=low__aorb(icount,itemsperline,itemsperline>=1);
xsetwidth          :=frcmin32( (s.ci.right-s.ci.left+1-((xcount+1)*hsp)) div frcmin32(xcount,1),1);
xtep               :=itep;
xhoverindex        :=ihoverindex;
xdown              :=gui.mousedown and focused;

//cls
ffillArea(s.cs,s.back,false);

//tep + caption
xcapright:=s.ci.left+5;

//.tep
if (xtep<>tepNone) and oshowtitle then
   begin

   tep__info(xtep,int1,int2);
   dy:=(xlineheight-int2) div 2;
   //was: ldis2(s.ci,xcapright,s.ci.top+dy,s.font,clnone,xtep,false,not s.e,s.r);
   ftep(xtep,xcapright,s.ci.top+dy,s.font,s.e);
   inc(xcapright,int1+(4*s.zoom));

   end;

//.caption
z:=caption;
if (z<>'') and oshowtitle then
   begin

   ftext( s.back ,s.ci,xcapright,s.ci.top+1,s.font,'',z,low__aorb(s.Rfn,s.Rfb,oboldhead),true);

   end;

//links
dx          :=s.ci.left+hsp;
dy          :=s.ci.bottom-(xlinecount*xlineheight)+vsp-1;
dcount      :=1;

for p:=0 to high(icaps) do
begin

if (icaps[p]<>'') then
   begin
   irecs[p]:=xlink(p,true);
   //was: irecs[p].top:=0;
   inc(dx,xsetwidth+hsp);
   inc(dcount);

   if (dcount>xcount) then
      begin
      dcount:=1;
      dx:=s.ci.left+hsp;
      inc(dy,xlineheight);
      end;

   end
else irecs[p]:=nilrect;

end;//p

//frame
xframeSimple( s );

except;end;
end;

function tbasicsel._onnotify(sender:tobject):boolean;
var
   p:longint;

   function xfinditem(s:tpoint;var xindex:longint):boolean;
   var
      p:longint;
   begin
   result:=false;
   xindex:=-1;
   for p:=0 to high(icaps) do if (icaps[p]<>'') and area__within2(irecs[p],s) then
      begin
      xindex:=p;
      result:=true;
      break;
      end;
   end;
begin
//defaults
result:=false;

try
//wheel
if (gui.wheel<>0) then
   begin
   if enabled then
      begin
      val:=val-gui.wheel;
      result:=true;//own the wheel!
      end;
   end;

//key
if (gui.key<>aknone) then
   begin
   case gui.key of
   akhome:begin
      if enabled then val:=0;
      result:=true;
      end;
   akend:begin
      if enabled then val:=imax;
      result:=true;
      end;
   akleft,akup:begin
      if enabled then val:=val-1;
      result:=true;
      end;
   akright,akdown:begin
      if enabled then val:=val+1;
      result:=true;
      end;
   akprev:begin
      if enabled then val:=val+1;
      result:=true;
      end;
   aknext:begin
      if enabled then val:=val+1;
      result:=true;
      end;
   end;//case
   end;

//mouse down
if gui.mousedownstroke then
   begin
   xfinditem(mousedownxy,idownindex);
   ihoverindex:=idownindex;
   paintnow;
   end;

//mouse move
if gui.mousemoved and (not gui.mousedown) then
   begin
   if xfinditem(mousexy,p) then help2:=ihlps[p] else help2:='';
   if low__setint(ihoverindex,p) then paintnow;
   end;

//mouse up
if gui.mouseupstroke then
   begin
   if (idownindex>=0) and (idownindex<=high(icaps)) then
      begin
      iwasselected:=(val=idownindex);
      val:=idownindex;
      end
   else iwasselected:=true;//use with "fonclick" to know if current item was previously selected or not - 26mar2022
   //reset
   if (idownindex>=0) then
      begin
      idownindex:=-1;
      paintnow;
      if ovalueclick then xonvalue;//29aug2021
      if assigned(fonclick) then fonclick(self);//07mar2022
      end;
   end;

//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);
except;end;
end;

//## tbasicimageexts ###########################################################
constructor tbasicimageexts.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tbasicimageexts.create2(xparent:tobject;xstart:boolean);
begin
//self
if classnameis('tbasicimageexts') then track__inc(satImageexts,1);
inherited create2(xparent,false,false);
bordersize:=0;

//vars
oautoshrink:=false;
oboldhead:=false;
itimer250:=slowms64;
iitemsperline:=0;
ilastref:='';
iext:='';
iactionlist:='';

//controls
ilist:=xhigh.nsel('','Select an option',0);
oautoheight:=true;

//events
ilist.onclick:=____onclick;

//start
if xstart then start;
end;

destructor tbasicimageexts.destroy;
begin
try
//self
inherited destroy;
if classnameis('tbasicimageexts') then track__inc(satImageexts,-1);
except;end;
end;

procedure tbasicimageexts._ontimer(sender:tobject);
begin
try

//itimer250
if (slowms64>itimer250) then
   begin
   xsync;
   itimer250:=slowms64+250;
   end;

except;end;
end;

procedure tbasicimageexts.____onclick(sender:tobject);
var
   xlistindex,xlistcount:longint;
   xlabel,xhelp:string;
begin
if (iext<>'') then
   begin
   xlistindex:=ilist.val;
   ia__useroptions(false,false,iext,xlistindex,xlistcount,xlabel,xhelp,iactionlist);
   end;
end;

procedure tbasicimageexts.xsync;
var
   sp,p,xlistindex,xlistcount:longint;
   xlabel,xhelp,xaction:string;
begin
try
if low__setstr(ilastref,intstr32(iitemsperline)+'|'+bolstr(oboldhead)+bolstr(oautoshrink)+'|'+iext+'|'+caption) then
   begin
   //init
   ia__useroptions(true,true,iext,xlistindex,xlistcount,xlabel,xhelp,iactionlist);
   //fill list
   ilist.xclear;
   if (xlistcount>=1) then
      begin
      for p:=0 to (xlistcount-1) do
      begin
      sp:=p;
      ia__useroptions(false,true,iext,sp,xlistcount,xlabel,xhelp,xaction);
      ilist.xadd(xlabel,xaction,xhelp);
      end;//p
      end;

   //set to last position
   ilist.setparams2(0,xlistindex,iitemsperline);
   if (ilist.caption<>caption) then ilist.caption:=caption;
   ilist.oboldhead:=oboldhead;
   ilist.paintnow;

   ilist.visible:=(not oautoshrink) or (xlistcount>=1);
   if oautoshrink then gui.fullalignpaint;
   end;
except;end;
end;

procedure tbasicimageexts.setext(x:string);
begin
if low__setstr(iext,x) then xsync;
end;

procedure tbasicimageexts.setitemsperline(x:longint);
begin
if low__setint(iitemsperline,frcmin32(x,0)) then xsync;
end;


//## tbasictea #################################################################
constructor tbasictea.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tbasictea.create2(xparent:tobject;xstart:boolean);
begin

//self
if classnameis('tbasictea') then track__inc(satTEA,1);
inherited create2(xparent,false);

//vars
bordersize         :=0;
itepdata           :=tepTemp20_noscaling;//use system "tepTemp20" for system scaling and management work - 21mar2026
itepview           :=tepTemp20;
iteppaint          :=tepFolder20;
odefault           :=true;
odefaultmsg        :='';
imanage_toolbar1   :=nil;
imanage_toolbar2   :=nil;
imanage_toolbar3   :=nil;
itimer500          :=slowms64;
ivieww             :=64;
iviewh             :=64;
idata              :=str__new8;
iundo              :=str__new8;
imustpaint         :=false;
icanundo           :=false;

if (sysfolder_imagefilename='') then sysfolder_imagefilename:=io__windrive+'untitled.png';

iinfocolors        :=0;
iinfoshades        :=0;
iinfotrans         :=false;
icanmakesolid      :=false;
icanmaketransparent:=true;
ifolder            :='';

//.showmenu
showmenuFillINT    :=xshowmenuFill;
showmenuClickINT   :=xshowmenuClick;
ocanshowmenu       :=true;

//start
if xstart then start;

end;

destructor tbasictea.destroy;
begin
try

//unmanage
unmanage;

//vars
str__free(@idata);
str__free(@iundo);

//self
inherited destroy;
if classnameis('tbasictea') then track__inc(satTEA,-1);

except;end;
end;

function tbasictea.getwidth:longint;
begin

result:=tep__width( itepdata );

end;

function tbasictea.getheight:longint;
begin

result:=tep__height( itepdata );

end;

function tbasictea.getbytes:longint;
begin

result:=tep__bytes( itepdata );

end;

procedure tbasictea.manage(xtoolbar1,xtoolbar2,xtoolbar3:tbasictoolbar);
begin

imanage_toolbar1:=xtoolbar1;
imanage_toolbar2:=xtoolbar2;
imanage_toolbar3:=xtoolbar3;

end;

procedure tbasictea.unmanage;
begin

manage(nil,nil,nil);

end;

procedure tbasictea.xshowmenuFill(sender:tobject;xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
var
   xcansave,xcancopy,xcanpaste:boolean;
   xhelptitle:string;
   c,p:longint;
begin

//check
if zznil(xmenudata,2354) then exit;
xmenuname   :='tea.1';

//init
xhelptitle  :=caption+insstr('|',caption<>'');


//get
if (xstyle='images') then
   begin

   low__menutitle(xmenudata,tepnone,'Built-In Images','Select an image to use');

   c        :=1;

   for p:=ls_system to (ls_folder-1) do
   begin

   case p of
   tepNone,tepBlank20,tepYesBlank20,tepTEMP20_noscaling,tepTemp20:;

   else begin

      if (tep__name(p)<>'') and (tep__rootheight(p)>=1) and (tep__rootheight(p)<=20) then
         begin

         low__menuitem2(xmenudata,p,k64(c)+'. '+tep__name(p),xhelptitle+'Use built-in image','tea.image.'+intstr32(p),100,aknone,true);

         //inc
         inc(c);

         end;

      end;

   end;//case

   end;//p

   end
else
   begin

   //init
   xcancopy    :=cancopyimage;
   xcanpaste   :=canpasteimage;
   xcansave    :=cansaveimage;

   //get
   low__menutitle(xmenudata,tepnone,'Edit',xhelptitle+'Edit options');
   low__menuitem2(xmenudata,tepUndo20,'Undo',xhelptitle+'Undo last change','tea.undo',100,aknone,canundo);
   low__menuitem2(xmenudata,tepCopy20,'Copy',xhelptitle+'Copy image to Clipboard','tea.copy',100,aknone,xcancopy);
   low__menuitem2(xmenudata,tepPaste20,'Paste',xhelptitle+'Paste image from Clipboard','tea.paste',100,aknone,xcanpaste);

   low__menusep(xmenudata);

   low__menuitem2(xmenudata,tepInvert20,'Make Transparent (Top-Left)',xhelptitle+'Make transparency from top-left pixel color','tea.maketransparent.tl',100,aknone,icanmaketransparent);
   low__menuitem2(xmenudata,tepInvert20,'Make Transparent (Bottom-Right)',xhelptitle+'Make transparency from bottom-left pixel color','tea.maketransparent.bl',100,aknone,icanmaketransparent);
   low__menuitem2(xmenudata,tepInvert20,'Make Solid',xhelptitle+'Make transparent pixels solid','tea.makesolid',100,aknone,icanmakesolid);

   low__menusep(xmenudata);

   low__menuitem2(xmenudata,tepOpen20,'Open',xhelptitle+'Open image from file','tea.open',100,aknone,true);
   low__menuitem2(xmenudata,tepSave20,'Save As',xhelptitle+'Save image to file','tea.save',100,aknone,xcansave);

   if odefault then low__menuitem2(xmenudata,tepRefresh20,'Default Image',xhelptitle+'Restore default image','tea.default',100,aknone,xcancopy);

   end;

end;

function tbasictea.xshowmenuClick(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
begin
result:=xcmd(self,xstyle,xcode,xcode2,clnone);
end;

function tbasictea.xcmd(sender:tbasiccontrol;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
var
   v:string;
   v32:longint32;

   function m(const xname:string):boolean;
   begin

   result:=strmatch(xname,xcode2);

   end;

   function mv(const s:string):boolean;
   begin

   result:=strm(xcode2,s,v,v32);

   end;

begin

//defaults
result      :=true;//handled
v           :='';
v32         :=0;

//get
if      m('tea.menu')    then showmenu
else if m('tea.images')  then showmenu2('images')
else if mv('tea.image.') then usetep( v32 )
else if m('tea.default') then
   begin

   if (idata.len>=1) then
      begin

      xundoFill;
      setdata(nil);

      end;
      
   end
else if m('tea.maketransparent.tl') then makeimagetrans(true,0)
else if m('tea.maketransparent.bl') then makeimagetrans(true,1)
else if m('tea.makesolid')          then makeimagetrans(false,0)
else if m('tea.open')               then openimage
else if m('tea.save')               then saveimage
else if m('tea.undo')               then undo
else if m('tea.copy')               then copyimage
else if m('tea.paste')              then pasteimage
else
   begin

   result:=false;

   end;

end;


function tbasictea.canmakeimagetrans:boolean;
begin

result:=(idata.len>=2);

end;

procedure tbasictea.makeimagetrans(const xtrans:boolean;const xstyle:longint);
label
   skipend;

var
   a:tbasicimage;
   b:tstr8;
   e:string;
begin

//defaults
a           :=nil;
b           :=nil;
e           :=gecTaskfailed;

//check
if not canmakeimagetrans then exit;

//init
a           :=misimg32(1,1);
b           :=str__new8;

//get
if not mis__fromdata(a,@idata,e) then goto skipend;

case xtrans of

true:begin

   if not mask__hastransparency32( a ) then
       begin

       case xstyle of
       1   :mask__makesimple0255( a ,mispixel24val(a,mish(a)-1,0) );//bottom-left
       else mask__makesimple0255( a ,mispixel24val(a,0,0) );//top-left
       end;//case

       mis__todata( a,@b,'tea',e);
       xundoFill;
       setdata(b);

       end;

   end;

else begin

   if mask__hastransparency32( a ) then
       begin

       mask__setval( a ,255 );
       mis__todata( a,@b,'tea',e);
       xundoFill;
       setdata(b);

       end;
   end;

end;//case

//successful
e           :='';
skipend:

//free
freeobj(@a);
str__free(@b);

//show error
if (e<>'') then gui.poperror('',e);

end;

procedure tbasictea.openimage;
label
   skipend;

var
   a:tbasicimage;
   b:tstr8;
   e:string;

begin

//defaults
a           :=nil;
b           :=nil;
e           :=gecTaskfailed;

try

//get

if gui.popopenimg(sysfolder_imagefilename,sysfolder_imageopenfilter,'') then
   begin

   //get
   a        :=misimg32(1,1);
   b        :=str__new8;

   if not mis__fromfile(a,sysfolder_imagefilename,e)   then goto skipend;
   if not mis__todata(a,@b,'bmp',e)                    then goto skipend;//bmp is faster than png for large, detailed images

   //set
   xundoFill;
   setdata(b);

   end
else begin

  //re-instate the image for "tepTEMP20" as it can be modified by a call to "popopen()->changefolderimage()" - 23mar2026
  setdata(idata);

  end;

//successful
e           :='';
skipend:

except;end;

//free
freeobj(@a);
str__free(@b);

//show error
if (e<>'') then gui.poperror('',e);

end;

function tbasictea.cansaveimage:boolean;
begin

result:=(idata.len32>=2) or (ifolder<>'');

end;

procedure tbasictea.saveimage;
label
   skipend;

var
   a:tbasicimage;
   s:tclientinfo;
   daction,e:string;

begin

//check
if not cansaveimage then exit;

//defaults
a           :=nil;
e           :=gecTaskfailed;
daction     :='';

try

//get
if gui.popsaveimg(sysfolder_imagefilename,'',daction) then
   begin

   //get
   a        :=misimg32(1,1);

   case (idata.len>=2) of
   true:if not mis__fromdata(a,@idata,e) then goto skipend;
   else begin

      infovars( s );
      tep__copytoimage(a,tep__folderimageDefault20(ifolder),s.font,s.line,clWhite,clBlack);

      end;

   end;//case

   if not mis__tofile(a,sysfolder_imagefilename,io__extractfileext(sysfolder_imagefilename),e) then goto skipend;

   end;

//successful
e           :='';
skipend:

except;end;

//free
freeobj(@a);

//show error
if (e<>'') then gui.poperror('',e);

end;

function tbasictea.cancopyimage:boolean;
begin

result:=(idata.len32>=2) or (ifolder<>'');

end;

procedure tbasictea.copyimage;
label
   skipend;

var
   a:tbasicimage;
   s:tclientinfo;
   e:string;

begin

//check
if not cancopyimage then exit;

//defaults
a           :=nil;
e           :=gecTaskfailed;

try

//get
a        :=misimg32(1,1);

if not mis__fromdata(a,@idata,e) then
   begin

   infovars( s );
   tep__copytoimage(a,tep__folderimageDefault20(ifolder),s.font,s.line,clWhite,clBlack);

   end;

if not clip__copyimage(a) then
   begin

   e        :=gecTaskfailed;
   goto skipend;

   end;

//successful
e           :='';
skipend:

except;end;

//free
freeobj(@a);

//show error
if (e<>'') then gui.poperror('',e);

end;

procedure tbasictea.usetep(const xindex:longint);
var
   a:tbasicimage;
   b:tstr8;
   s:tclientinfo;
   e:string;
begin

//defaults
a           :=nil;
b           :=nil;

//check
if not tep__find(xindex) then exit;

//init
a        :=misimg32(tep__width(xindex),tep__height(xindex));
b        :=str__new8;

//get
infovars( s );
tep__copytoimage(a,xindex,s.font,s.line,clWhite,clBlack);
mis__todata(a,@b,'tea',e);

xundoFill;
setdata(b);


//free
freeobj(@a);
str__free(@b);

end;

function tbasictea.canpasteimage:boolean;
begin

result:=clip__canpasteimage(true);

end;

procedure tbasictea.pasteimage;
label
   skipend;

var
   a:tbasicimage;
   b:tstr8;
   e:string;

begin

//check
if not canpasteimage then exit;

//defaults
a           :=nil;
b           :=nil;
e           :=gecTaskfailed;

try

//get
a        :=misimg32(1,1);
b        :=str__new8;

if not clip__pasteimage(a,true)   then goto skipend;
if not mis__todata(a,@b,'png',e)  then goto skipend;

//set
xundoFill;
setdata(b);

//successful
e           :='';
skipend:

except;end;

//free
freeobj(@a);
str__free(@b);

//show error
if (e<>'') then gui.poperror('',e);

end;

procedure tbasictea.fromfolder(const xfolder:string);
var
   b:tstr8;
   e:string;
begin

//defaults
b           :=nil;
ifolder     :=xfolder;

//init
b           :=str__new8;
io__fromfile( tep__folderimageFilename(xfolder) ,@b ,e );
setdata(b);

icanundo    :=io__fileexists( tep__folderimageUndoFilename(ifolder) );
io__fromfile( tep__folderimageUndoFilename(ifolder) ,@iundo ,e );

//free
str__free(@b);

end;

function tbasictea.cantofolder:boolean;
begin

result:=true;

end;

procedure tbasictea.tofolder(const xfolder:string);
var
   e:string;
begin

//check
if not cantofolder then exit;

//get
tep__setfolderimage20(xfolder,@idata);
io__tofile( tep__folderimageUndoFilename(xfolder) ,@iundo ,e );

end;

procedure tbasictea.xundoFill;
begin

str__clear(@iundo);
str__add  (@iundo,@idata);
icanundo    :=true;

end;

function tbasictea.canundoClear:boolean;
begin

result      :=canundo;

end;

procedure tbasictea.undoClear;
begin

if canundoClear then io__remfile( tep__folderimageUndoFilename(ifolder) );

end;

procedure tbasictea.undo;
var
   b:tstr8;
begin

//check
if not canundo then exit;

//defaults
b           :=nil;
b           :=str__new8;

//data -> b
str__add(@b,@idata);

//undo -> setdata()
setdata(iundo);

//b -> undo
str__clear(@iundo);
str__add  (@iundo,@b);

//free
str__free(@b);

end;

function tbasictea.setdata(xdata:tstr8):boolean;
var
   a:tbasicimage;
   b:tstr8;
   s:tclientinfo;
   e:string;

   procedure xclear;
   begin

   tep__clearpersistentdata( itepview );
   tep__clearpersistentdata( itepdata );
   tep__20 ( itepview ,[0] ,tep_temp20 ,df_mono ,df_color );
   tep__20 ( itepdata ,[0] ,tep_temp20 ,df_mono ,df_color );

   idata.clear;

   icanmakesolid      :=false;
   icanmaketransparent:=false;

   end;

begin

//defaults
a           :=nil;
b           :=nil;

//lock
str__lock(@xdata);

//init
a           :=misimg32(1,1);
b           :=str__new8;

//get
case (str__len32(@xdata)>=2) of
true:begin

   if mis__fromdata(a,@xdata,e) then
      begin

      //force image dimensions to that of a folder image
      tep__squareScaleImage( a ,tep_folderImageWH );

      //save in TEA format
      mis__todata(a,@idata,'tea',e);

      //store image in temp TEP slot
      tep__setpersistentdata( itepview ,@idata ,[0] );
      tep__setpersistentdata( itepdata ,@idata ,[0] );
      tep__20( itepview ,[0] ,tep_blank20 ,df_mono ,df_color );
      tep__20( itepdata ,[0] ,tep_blank20 ,df_mono ,df_color );

      //get data from slot -> unscaled for "itep=tepTEMP20_noscaling"
      tep__todata(itepdata,@idata,'tea');//for accurate "bytes" value

      end
   else xclear;

   end;

else xclear;

end;//case

//information
tep__todata(itepdata,@b,'tea');//for accurate "bytes" value

mis__fromdata(a,@b,e);

case (idata.len>=2) of
true:begin

   iteppaint          :=itepview;
   iinfocolors        :=miscountcolors( a );
   iinfoshades        :=mask__count( a );
   iinfotrans         :=mask__hastransparency32( a );

   end;
else begin

   iteppaint          :=tep__folderimageDefault20( ifolder );

   infovars( s );

   tep__copytoimage( a ,iteppaint ,s.font ,s.line ,clWhite ,clBlack );

   end;
end;//case

iinfocolors           :=miscountcolors( a );
iinfoshades           :=mask__count( a );
iinfotrans            :=mask__hastransparency32( a );

icanmaketransparent   :=(idata.len>=2) and (not iinfotrans);
icanmakesolid         :=(idata.len>=2) and iinfotrans;

//paint
imustpaint  :=true;

//free
freeobj(@a);
str__free(@b);
str__uaf(@xdata);

end;

function tbasictea.getdata(xdata:tstr8):boolean;
begin

//lock
result:=str__lock(@xdata);

//get
if result then
   begin

   str__clear(@xdata);
   str__add(@xdata,@idata);

   end;

//free
str__uaf(@xdata);

end;

function tbasictea.gettext:string;
begin

result:=idata.text;

end;

procedure tbasictea.settext(x:string);
var
   a:tstr8;
begin

//defaults
a           :=nil;

try

//get
a           :=str__new8;
a.text      :=x;
setdata(a);

except;end;

//free
str__free(@a);

end;

procedure tbasictea._ontimer(sender:tobject);
var
   xmustpaint:boolean;
begin

//defaults
xmustpaint            :=false;

//imustpaint
if imustpaint then
   begin

   xmustpaint         :=true;
   imustpaint         :=false;

   end;

//itimer500
if (slowms64>=itimer500) then
   begin

   //sync
   xsync;

   //reset
   itimer500          :=add64(slowms64,500);

   end;

//xmustpaint
if xmustpaint then paintnow;

end;

procedure tbasictea.xsync;
var
   xcansave,xcanundo,xcancopy,xcanpaste:boolean;

   procedure t(const x:tbasictoolbar);
   begin

   //check
   if (x=nil) then exit;

   //sync
   with x do
   begin

   benabled2['tea.undo']        :=xcanundo;
   benabled2['tea.default']     :=xcancopy;
   benabled2['tea.copy']        :=xcancopy;
   benabled2['tea.paste']       :=xcanpaste;
   benabled2['tea.save']        :=xcansave;

   end;

   end;

begin

//init
xcanundo    :=canundo;
xcancopy    :=cancopyimage;
xcanpaste   :=canpasteimage;
xcansave    :=cansaveimage;

//sync
t(imanage_toolbar1);
t(imanage_toolbar2);
t(imanage_toolbar3);

end;

function tbasictea.getalignheight(xclientwidth:longint):longint;
begin

result:=frcmin32( 6*vilineheight20, scale__px1(iviewH,1) ) + (2*frcmin32(findbordersize,1));

end;

procedure tbasictea._onpaint(sender:tobject);
const
   tcount=6;

var
   s:tclientinfo;
   rw,rh,aw,ah,dtep,p,dx,dy,vw,vh:longint;
   da:twinrect;

   function xinfo(x:longint;xval:boolean):string;
   begin

   result:='';

   case x of
   0:if xval then result:=low__aorbstr('Default ( Built-In )','Custom ('+tep__folderimageFilename(' ')+' )',idata.len>=2) else result:='Source';
   1:begin

      if xval then
         begin

         if (rw<=0) and (rh<=0) then result:=strdefb(odefaultmsg,'( Not in use )') else result:=k64(rw)+'w x '+k64(rh)+'h';

         end
      else result:='Dimensions';

      end;
   2:if xval then result:=low__aorbstr('-',low__b(idata.len32,true),idata.len32>=1) else result:='Size';
   3:if xval then result:=low__aorbstr('No','Yes',iinfotrans) else result:='Transparent';
   4:if xval then result:=k64(iinfocolors) else result:='Colors';
   5:if xval then result:=k64(iinfoshades) else result:='Shades';
   end;//case

   end;
begin
try


//init
infovars(s);

dtep        :=iteppaint;
aw          :=tep__width ( dtep );
ah          :=tep__height( dtep );
rw          :=tep__rootwidth ( dtep );
rh          :=tep__rootheight( dtep );
dx          :=scale__px1(20,2);
dy          :=s.ci.top;
vw          :=scale__px1(ivieww,1);
vh          :=scale__px1(iviewh,1);


//cls
ffillArea(s.cs,s.back,false);


//image
dy             :=(s.ch-vh) div 2;
da             :=area__make(dx,dy,dx+vw-1,dy+vh-1);

ftep( dtep ,da.left+((vw-aw) div 2) ,da.top+((vH-ah) div 2) ,s.font ,true );

foutlinearea(area__grow(da,1),s.line,false);


//information (5x lines)
inc(dx,vw + scale__px0(30) );
dy             :=(s.ch-(tcount*s.fnH)) div 2;

for p:=0 to pred(tcount) do
begin

ftext(s.back,s.ci,dx,dy,s.font,tbL100_L500,xinfo(p,false)+#9+xinfo(p,true),s.Rfn,true);
inc(dy,s.fnH);

end;//p


//frame
xframeSimple( s );

except;end;
end;

function tbasictea._onnotify(sender:tobject):boolean;
begin

//defaults
result      :=false;

//mouse down
if gui.mouseupstroke then
   begin

   autoshowmenu;
   result   :=true;

   end;

//external event override - 23mar2026, 01mar2021
if assigned(fonnotify) then
   begin

   result:=result or fonnotify(sender);

   end;

end;


//## tbasiccolors ##############################################################
constructor tbasiccolors.create(xparent:tobject);
begin
create2(xparent,true);
end;

constructor tbasiccolors.create2(xparent:tobject;xstart:boolean);
begin

//self
if classnameis('tbasiccolors') then track__inc(satColors,1);
inherited create2(xparent,false);

//vars
foncolor           :=nil;
foncolorchanged    :=nil;
osyscolor          :=false;
opopcolor          :=true;//28feb2021
oshowcaps          :=true;
otightblocks       :=false;
oclicktouse        :=false;
ilastsysname       :='';
caption            :='';
iitemsperline      :=4;
idownindex         :=-1;
ibordersize        :=0;
inormal            :=true;
ilastalignid       :=-1;
ialignid           :=0;
ilastpaintid       :=-1;
ipaintid           :=0;
imustwrite         :=false;

clear;

//start
if xstart then start;

end;

destructor tbasiccolors.destroy;
begin
try
inherited destroy;
if classnameis('tbasiccolors') then track__inc(satColors,-1);
except;end;
end;

procedure tbasiccolors.xreadfrom(xnormal,xtitle:pvirtualinfo;xmorecolors:pvirtualmorecolors);
begin
try
//normal
if (xnormal<>nil) then
   begin
   //.frame
   col1[cnframe]       :=xnormal.frame;
   col1[cnframe2]      :=xnormal.frame2;
   //.normal
   col1[cnback1]       :=xnormal.background;
   col1[cnborder1]     :=xnormal.border;
   col1[cnhigh1]       :=xnormal.highlight;
   col1[cnhover1]      :=xnormal.hover;
   col1[cntext1]       :=xnormal.font;
   col1[cntexthigh1]   :=xnormal.fonthighlight;
   col1[cntextdis1]    :=xnormal.disablefont;
   col1[cndis1]        :=xnormal.disable;
   col1[cndisbr1]      :=xnormal.disableborder;
   end;
//title
if (xtitle<>nil) then
   begin
   //.frame
   col1[cnframe]       :=xtitle.frame;
   col1[cnframe2]      :=xtitle.frame2;
   //.title
   col1[cnback2]       :=xtitle.background;
   col1[cnborder2]     :=xtitle.border;
   col1[cnhigh2]       :=xtitle.highlight;
   col1[cnhover2]      :=xtitle.hover;
   col1[cntext2]       :=xtitle.font;
   col1[cntexthigh2]   :=xtitle.fonthighlight;
   col1[cntextdis2]    :=xtitle.disablefont;
   col1[cndis2]        :=xtitle.disable;
   col1[cndisbr2]      :=xtitle.disableborder;
   end;
//xmorecolors
if (xmorecolors<>nil) then
   begin
   col1[cnsframe]      :=xmorecolors.frame;
   col1[cnstitle]      :=xmorecolors.title;
   col1[cnsstandard]   :=xmorecolors.standard;
   col1[cnsallinone]   :=xmorecolors.allinone;
   col1[cnsdark_light] :=xmorecolors.dark_light;
   col1[cnslight_dark] :=xmorecolors.light_dark;
   end;
except;end;
end;

procedure tbasiccolors.xwriteto(xnormal,xtitle:pvirtualinfo;xmorecolors:pvirtualmorecolors);
begin
try
//normal
if (xnormal<>nil) then
   begin
   //.frame
   xnormal.frame        :=col1[cnframe];
   xnormal.frame2       :=col1[cnframe2];
   //.normal
   xnormal.background   :=col1[cnback1];
   xnormal.border       :=col1[cnborder1];
   xnormal.highlight    :=col1[cnhigh1];
   xnormal.hover        :=col1[cnhover1];
   xnormal.font         :=col1[cntext1];
   xnormal.fonthighlight:=col1[cntexthigh1];
   xnormal.disablefont  :=col1[cntextdis1];
   xnormal.disable      :=col1[cndis1];
   xnormal.disableborder:=col1[cndisbr1];
   end;
//title
if (xtitle<>nil) then
   begin
   //.frame
   xtitle.frame         :=col1[cnframe];
   xtitle.frame2        :=col1[cnframe2];
   //.title
   xtitle.background    :=col1[cnback2];
   xtitle.border        :=col1[cnborder2];
   xtitle.highlight     :=col1[cnhigh2];
   xtitle.hover         :=col1[cnhover2];
   xtitle.font          :=col1[cntext2];
   xtitle.fonthighlight :=col1[cntexthigh2];
   xtitle.disablefont   :=col1[cntextdis2];
   xtitle.disable       :=col1[cndis2];
   xtitle.disableborder :=col1[cndisbr2];
   end;
//xmorecolors
if (xmorecolors<>nil) then
   begin
   xmorecolors.frame    :=col1[cnsframe];
   xmorecolors.title    :=col1[cnstitle];
   xmorecolors.standard :=col1[cnsstandard];
   xmorecolors.allinone :=col1[cnsallinone];
   xmorecolors.dark_light:=col1[cnsdark_light];
   xmorecolors.light_dark:=col1[cnslight_dark];
   end;
except;end;
end;

procedure tbasiccolors.fromsys(xname:string);
var
   xnormal,xtitle:tvirtualinfo;
begin
low__setcolorsbyname(xname,@xnormal,@xtitle,@vimorecolors);
xreadfrom(@xnormal,@xtitle,@vimorecolors);
end;

procedure tbasiccolors.tosys(xname:string;xautosync:boolean);
label
   skipend;
var
   c,b:tstr8;
   daction,xdata,str1,f,n,e:string;
   int1,p:longint;
   bol1:boolean;
begin
try
//defaults
b:=nil;
c:=nil;
bol1:=false;

//check
n:=strlow(xname);
if (n='') then exit;

//get
xdata:='';
for p:=0 to high(icaps) do if (icaps[p]<>'') and (istys[p]=0) then xdata:=low__setcolor2(xdata,iidxs[p],icols[p]);//istys=0=color, 1=title

//set
//.internal
if strmatch(strcopy1(n,1,7),'?custom') then
   begin
   int1:=frcrange32(strint32(strcopy1(n,8,low__len32(n))),0,cnCustomLimit-1);
   str1:=syssettings.s['?custom'+intstr32(int1)];
   bol1:=low__setstr(str1,xdata);
   if bol1 then syssettings.s['?custom'+intstr32(int1)]:=str1;//store
   end
//.paste_and_use
else if strmatch(n,'?paste_and_use') then
   begin
   str1:=syssettings.s[n];
   bol1:=low__setstr(str1,xdata);
   if bol1 then syssettings.s[n]:=str1;//store
   end
//.file
else if (strcopy1(n,1,1)<>'?') then
   begin
   //init
   f:=low__platfolder('schemes')+xname+'.'+cnFileEXT;//no forced lowercase or uppercase on xname
   b:=str__new8;
   c:=str__new8;
   //get
   b.text:=xdata;
   if io__fromfile(f,@c,e) then
      begin
      if not c.same(b) then bol1:=io__tofile(f,@b,e);
      end;
   end
//.copy
else if (n='?copy') then
   begin
   clip__copytext(xdata);
   end
//.copy.hex
else if (n='?copy.hex') then//22jul2021
   begin
   clip__copytext(low__tocompactcolors(xdata));
   end
//.paste
else if (n='?paste') or (n='?paste.hex') then
   begin
   if  gui.popquery2('Replace current color scheme with Clipboard color scheme?','','Replace',false) then data:=clip__pastetextb;
   end
//.paste new
else if (n='?pastenew') or (n='?pastenew.hex') then
   begin
   if (sysfile_colorscheme='') then sysfile_colorscheme:=low__platfolder('schemes')+'Untitled.'+cnFileEXT;
   daction:='';
   if gui.popsave(sysfile_colorscheme,pebcs,low__platfolder('schemes'),daction) then
      begin
      b:=str__new8;
      str1:=clip__pastetextb;
      if not low__fromcompactcolors(str1,str1) then
         begin
         gui.poperror('',gecUnknownformat);
         goto skipend;
         end;
      b.text:=str1;
      case io__tofile(sysfile_colorscheme,@b,e) of
      true:begin
         syssettings.value['colorname']:=io__remlastext(io__extractfilename(sysfile_colorscheme));//24jul2021
         visync;
         gui.xshowoptions_reload;
         end;
      else gui.poperror('',e);
      end;//case
      end;
   end
//.paste use
else if (n='?pasteuse') or (n='?pasteuse.hex') or (n='?pasteuse2') or (n='?pasteuse2.hex') then
   begin
   str1:=clip__pastetextb;
   int1:=0;
   if (n='?pasteuse2') or (n='?pasteuse2.hex') then int1:=10;//+10% brighter
   if not low__fromcompactcolors2(str1,int1,str1) then
      begin
      gui.poperror('',gecUnknownformat);
      goto skipend;
      end;
   syssettings.value['colorname']:='?paste_and_use';
   syssettings.value['?paste_and_use']:=str1;
   if strmatch(ilastsysname,'?paste_and_use') then fromsys(ilastsysname);
   visync;
   gui.xshowoptions_reload;
   end
//.brighten / darken -> currently ONLY works with colorname="?paste_and_use" - 18sep2022
else if (n='?brighten') or (n='?brighten.hex') or (n='?darken') or (n='?darken.hex') then
   begin
   str1:=syssettings.value['?paste_and_use'];
   if low__fromcompactcolors2(str1,low__aorb(-10,10,(n='?brighten') or (n='?brighten.hex')),str1) then
      begin
      syssettings.value['?paste_and_use']:=str1;
      if strmatch(ilastsysname,'?paste_and_use') then fromsys(ilastsysname);
      visync;
      gui.xshowoptions_reload;
      end;
   end;

//sync
if xautosync and bol1 then visync;
skipend:
except;end;
try
freeobj(@b);
freeobj(@c);
except;end;
end;

function tbasiccolors.getdata:string;
var
   p:longint;
begin
result:='';
for p:=0 to high(icaps) do if (icaps[p]<>'') and (istys[p]=0) then low__setcolor2(result,iidxs[p],icols[p]);
end;

procedure tbasiccolors.setdata(x:string);
var
   int1,p:longint;
   bol1:boolean;
begin
try
bol1:=false;
//filter
low__fromcompactcolors(x,x);//accepts both "col2" and "col3" formats and converts them into "col2"
//get
for p:=0 to high(icaps) do if (icaps[p]<>'') and (istys[p]=0) then
   begin
   if low__getcolor2(x,iidxs[p],int1) and low__setint(icols[p],int1) then bol1:=true;
   end;
if bol1 then
   begin
   xnewid(false,true);
   imustwrite:=true;
   end;
except;end;
end;

procedure tbasiccolors.setitemsperline(x:longint);
begin
if low__setint(iitemsperline,frcrange32(x,0,500)) then xnewid(true,true);
end;
//## getcap ##
function tbasiccolors.getcap(x:longint):string;
begin
if (x>=0) and (x<=high(icaps)) then result:=icaps[x] else result:='';
end;

procedure tbasiccolors.setcap(x:longint;xval:string);
begin
if (x>=0) and (x<=high(icaps)) and low__setstr(icaps[x],xval) then xnewid(true,true);
end;

function tbasiccolors.getnam(x:longint):string;
begin
if (x>=0) and (x<=high(icaps)) then result:=inams[x] else result:='';
end;

function tbasiccolors.getidx(x:longint):longint;
begin
if (x>=0) and (x<=high(icaps)) then result:=iidxs[x] else result:=0;
end;

procedure tbasiccolors.setnam(x:longint;xval:string);
begin
if (x>=0) and (x<=high(icaps)) then low__setstr(inams[x],xval);
end;

function tbasiccolors.getcol(x:longint):longint;
begin
if (x>=0) and (x<=high(icaps)) then result:=icols[x] else result:=0;
end;

procedure tbasiccolors.xset(xindex,xval:longint);
var
   int1:longint;
begin
if findidx(xindex,int1) then icols[int1]:=xval;
end;

procedure tbasiccolors.xspecial(xname,xstyle:string;xval:longint);
var
   f1,f2,tc,bc:longint;
   xframe1,xframe2,xback,xborder,xhigh,xhover,xtext,xtexthigh,xtextdis,xdis,xdisborder:longint;
begin
try
//init
xname:=strlow(xname);
xstyle:=strlow(xstyle);

//style
if (xstyle='dark') then
   begin
   //init
   f1         :=int__dif24(xval,-80);
   f2         :=int__dif24(xval,20);
   if (int__greyscale_ave(f1)>int__greyscale_ave(f2)) then low__swapint(f1,f2);
   bc         :=int__dif24(xval,-40);
   tc         :=int__dif24(xval,-120);
   //get
   xframe1    :=f1;
   xframe2    :=f2;
   xback      :=bc;
   xborder    :=int__dif24(bc,-30);
   xhigh      :=int__dif24(tc,20);
   xhover     :=int__dif24(tc,20);
   xtext      :=tc;
   xtexthigh  :=int__dif24(bc,50);
   xtextdis   :=int__dif24(bc,-80);
   xdis       :=int__dif24(bc,-40);
   xdisborder :=int__dif24(bc,-50);
   end
else if (xstyle='light') then
   begin
   //init
   f1         :=int__dif24(xval,-80);
   f2         :=int__dif24(xval,20);
   if (int__greyscale_ave(f1)>int__greyscale_ave(f2)) then low__swapint(f1,f2);
   bc         :=int__dif24(xval,30);
   tc         :=int__dif24(xval,-120);
   //get
   xframe1    :=f1;
   xframe2    :=f2;
   xback      :=bc;
   xborder    :=int__dif24(bc,-30);
   xhigh      :=int__dif24(tc,10);
   xhover     :=int__dif24(tc,10);
   xtext      :=tc;
   xtexthigh  :=int__dif24(bc,30);
   xtextdis   :=int__dif24(bc,-80);
   xdis       :=int__dif24(bc,-40);
   xdisborder :=int__dif24(bc,-50);
   end
else//normal
   begin
   //init
   f1         :=int__dif24(xval,-80);
   f2         :=int__dif24(xval,20);
   if (int__greyscale_ave(f1)>int__greyscale_ave(f2)) then low__swapint(f1,f2);
   bc         :=int__dif24(xval,0);
   tc         :=int__dif24(xval,-120);
   //get
   xframe1    :=f1;
   xframe2    :=f2;
   xback      :=bc;
   xborder    :=int__dif24(bc,-30);
   xhigh      :=int__dif24(tc,10);
   xhover     :=int__dif24(tc,10);
   xtext      :=tc;
   xtexthigh  :=int__dif24(bc,30);
   xtextdis   :=int__dif24(bc,-80);
   xdis       :=int__dif24(bc,-40);
   xdisborder :=int__dif24(bc,-50);
   end;

//name
if (xname='frame') then
   begin
   xset(cnframe,xframe1);
   xset(cnframe2,xframe2);
   end
else if (xname='title') then
   begin
   xset(cnback2,xback);
   xset(cnBorder2,xborder);
   xset(cnHigh2,xhigh);
   xset(cnHover2,xhover);
   xset(cnText2,xtext);
   xset(cnTexthigh2,xtexthigh);
   xset(cnTextdis2,xtextdis);
   xset(cnDis2,xdis);
   xset(cnDisbr2,xdisborder);
   end
else if (xname='standard') then
   begin
   xset(cnback1,xback);
   xset(cnBorder1,xborder);
   xset(cnHigh1,xhigh);
   xset(cnHover1,xhover);
   xset(cnText1,xtext);
   xset(cnTexthigh1,xtexthigh);
   xset(cnTextdis1,xtextdis);
   xset(cnDis1,xdis);
   xset(cnDisbr1,xdisborder);
   end;
except;end;
end;

procedure tbasiccolors.setcol(x:longint;xval:longint);
begin
xsetcol(x,xval,false);
end;

procedure tbasiccolors.setcol3(x:longint;xval:longint);
begin
xsetcol(x,xval,true);
end;

procedure tbasiccolors.xsetcol(x:longint;xval:longint;xspecialoverride:boolean);
begin
if (x>=0) and (x<=high(icaps)) and (low__setint(icols[x],xval) or (xspecialoverride and (iidxs[x]>=cnsSpecialstart))) then
   begin
   //special color handlers -> takes special color and spreads it to the corresponding sub-colors
   case iidxs[x] of
   cnsFrame:xspecial('frame','',xval);
   cnsTitle:xspecial('title','',xval);
   cnsStandard:xspecial('standard','',xval);
   cnsAllinone:begin
      xspecial('frame','',xval);
      xspecial('title','',xval);
      xspecial('standard','',xval);
      end;
   cnsDark_light:begin
      xspecial('frame','',xval);
      xspecial('title','dark',xval);
      xspecial('standard','light',xval);
      end;
   cnsLight_dark:begin
      xspecial('frame','',xval);
      xspecial('title','light',xval);
      xspecial('standard','dark',xval);
      end;
   end;//case
   //set
   xnewid(false,true);
   imustwrite:=true;
   end;
end;

function tbasiccolors.getcol2(xname:string):longint;
var
   int1:longint;
begin
if findname(xname,int1) then result:=icols[int1] else result:=0;
end;

procedure tbasiccolors.setcol2(xname:string;xval:longint);
var
   int1:longint;
begin
if findname(xname,int1) and low__setint(icols[int1],xval) then
   begin
   xnewid(false,true);
   imustwrite:=true;
   end;
end;

function tbasiccolors.getcol1(xidx:longint):longint;
var
   int1:longint;
begin
if findidx(xidx,int1) then result:=icols[int1] else result:=0;
end;

procedure tbasiccolors.setcol1(xidx:longint;xval:longint);
var
   int1:longint;
begin
if findidx(xidx,int1) and low__setint(icols[int1],xval) then
   begin
   xnewid(false,true);
   imustwrite:=true;
   end;
end;

function tbasiccolors.findname(xname:string;var xindex:longint):boolean;
var
   p:longint;
begin
//defaults
result:=false;
xindex:=0;
//check
if (xname='') then exit;
//find
for p:=0 to high(icaps) do if (icaps[p]<>'') and strmatch(xname,inams[p]) then
   begin
   xindex:=p;
   result:=true;
   break;
   end;//p
end;

function tbasiccolors.findidx(xidx:longint;var xindex:longint):boolean;
var
   p:longint;
begin
//defaults
result:=false;
xindex:=0;
//find
for p:=0 to high(icaps) do if (icaps[p]<>'') and (xidx=iidxs[p]) then
   begin
   xindex:=p;
   result:=true;
   break;
   end;//p
end;

procedure tbasiccolors.clear;
var
   p:longint;
begin

for p:=0 to high(icaps) do
begin

istys[p]    :=0;//0=color, 1=title
icaps[p]    :='';
inams[p]    :='';
iidxs[p]    :=0;
ihlps[p]    :='';
icols[p]    :=0;
idefcols[p] :=0;
irecs[p]    :=nilrect;

end;//p

icount :=0;
imax   :=0;

xnewid(true,true);

end;

procedure tbasiccolors.addtitle(xcap,xhlp:string);
begin
xadd(1,xcap,'',xhlp,0,0,0);
end;

procedure tbasiccolors.addcol(xcap,xnam,xhlp:string);
begin
xadd(0,xcap,xnam,xhlp,0,0,0);
end;

procedure tbasiccolors.addcol1(xcap:string;xidx:longint;xhlp:string);
begin
xadd(0,xcap,'',xhlp,xidx,0,0);
end;

procedure tbasiccolors.addcol2(xcap,xnam,xhlp:string;xidx,xcol,xdefcol:longint);
begin
xadd(0,xcap,xnam,xhlp,xidx,xcol,xdefcol);
end;

procedure tbasiccolors.xadd(xstyle:longint;xcap,xnam,xhlp:string;xidx,xcol,xdefcol:longint);
var
   p:longint;
begin

for p:=0 to high(icaps) do if (low__len32(icaps[p])=0) then
   begin

   istys[p]    :=xstyle;
   icaps[p]    :=xcap;
   inams[p]    :=xnam;
   iidxs[p]    :=xidx;
   ihlps[p]    :=xhlp;
   icols[p]    :=xcol;
   idefcols[p] :=xdefcol;

   xsynccount;
   break;

   end;

end;

procedure tbasiccolors.xnewid(xalign,xpaint:boolean);
begin
if xalign then low__iroll(ialignid,1);
if xpaint then low__iroll(ipaintid,1);
end;

procedure tbasiccolors._ontimer(sender:tobject);
var
   xmustalign,xmustpaint:boolean;
begin
try
//defaults
xmustalign:=false;
xmustpaint:=false;

//sysref
if osyscolor and (not strmatch(ilastsysname,vicolorname)) then
   begin

   tosys(ilastsysname,false);
   ilastsysname  :=vicolorname;
   fromsys(ilastsysname);
   imustwrite    :=false;

   end;

//mustwrite
if imustwrite then
   begin

   imustwrite    :=false;
   if osyscolor then tosys(ilastsysname,true);
   if assigned(foncolorchanged) then foncolorchanged(self);//15mar2022

   end;

//alignid
if (ilastalignid<>ialignid) then
   begin

   ilastalignid  :=ialignid;
   xmustalign    :=true;

   end;

//paintid
if (ilastpaintid<>ipaintid) then
   begin

   ilastpaintid  :=ipaintid;
   xmustpaint    :=true;

   end;

//xmustpaint
if xmustalign then alignnow;
if xmustpaint then paintnow;

except;end;
end;

function tbasiccolors.linecount:longint;
begin

if (iitemsperline>=1) then
   begin

   result:=icount div iitemsperline;
   if ((result*iitemsperline)<>icount) then inc(result);

   end
else result:=1;

end;

function tbasiccolors.lineheight:longint;//color palette - 11dec2025, 05sep2025, 24may2025
begin
result:=vilineheight30;
end;

function tbasiccolors.lineheight2:longint;//title
begin
result:=lineheight;
end;

function tbasiccolors.getalignheight(xclientwidth:longint):longint;
begin
result:=(2*frcmin32(findbordersize,1))+xpaintcalc(false);
end;

procedure tbasiccolors.xsynccount;
var
   p,int1,int2:longint;
begin
int1:=0;
int2:=0;
for p:=0 to high(icaps) do if (low__len32(icaps[p])>=1) then
   begin
   inc(int1);
   int2:=p;
   end;

icount:=int1;
imax:=int2;
end;

procedure tbasiccolors.makeadjustable;
begin
makeadjustable2(4);
end;

procedure tbasiccolors.makeadjustable2(xitemsperline:longint);
begin
clear;
oshowcaps:=true;
osyscolor:=false;
opopcolor:=true;
otightblocks:=false;
oclicktouse:=false;
itemsperline:=frcmin32(xitemsperline,1);
end;

procedure tbasiccolors.makesystem;
begin
//init
clear;
oshowcaps:=true;
osyscolor:=true;
opopcolor:=true;
otightblocks:=false;
oclicktouse:=false;
itemsperline:=2;
//.frame
addtitle('Frame Colors','Window frame colors');
addcol1('Frame',cnframe,'Frame color');
addcol1('Frame 2',cnframe2,'Frame color 2');
//.title
addtitle('Title Colors','Title colors');
addcol1('Background',cnback2,'Title background color');
addcol1('Border',cnborder2,'Title border color');
addcol1('Highlight',cnhigh2,'Title highlight color');
addcol1('Hover',cnhover2,'Title hover color');
addcol1('Text',cntext2,'Title text color');
addcol1('Text Highlight',cntexthigh2,'Title text highlight color');
addcol1('Text Disable',cntextdis2,'Title text disable color');
addcol1('Disable',cndis2,'Title disable color');
addcol1('Disable Border',cndisbr2,'Title disable border color');
//.standard
addtitle('Standard Colors','Standard colors');
addcol1('Background',cnback1,'Standard background color');
addcol1('Border',cnborder1,'Standard border color');
addcol1('Highlight',cnhigh1,'Standard highlight color');
addcol1('Hover',cnhover1,'Standard hover color');
addcol1('Text',cntext1,'Standard text color');
addcol1('Text Highlight',cntexthigh1,'Standard text highlight color');
addcol1('Text Disable',cntextdis1,'Standard text disable color');
addcol1('Disable',cndis1,'Standard disable color');
addcol1('Disable Border',cndisbr1,'Standard disable border color');
//.standard
addtitle('Special Color Generators','Color Generators');
addcol1('Frame',cnsFrame,'Select a single color and generate all Frame colors automatically');
addcol1('Title',cnsTitle,'Select a single color and generate all Title colors automatically');
addcol1('Standard',cnsStandard,'Select a single color and generate all Standard colors automatically');
addcol1('All in one',cnsAllinone,'Select a single color and generate all Frame, Title and Standard colors automatically');
addcol1('Dark + Light',cnsDark_light,'Select a single color and generate all Frame, Title (darker) and Standard (lighter) colors automatically');
addcol1('Light + Dark',cnsLight_dark,'Select a single color and generate all Frame, Title (lighter) and Standard (darker) colors automatically');
end;

procedure tbasiccolors._onpaint(sender:tobject);
begin
xpaintcalc(true);
end;

function tbasiccolors.xpaintcalc(xmustpaint:boolean):longint;
const//Supports enhanced shading
   _hsp=2;
   _vsp=2;
var
   s:tclientinfo;
   b:twinrect;
   hsp,vsp,int2,int1,xlaststyle,xlineheight,xlineheight2,dcount,xcount,xsetwidth,p,dx,dy:longint;
   xtightblocks,xonce:boolean;

   function xlink(zindex:longint):twinrect;
   var
      br,bc,tc,tw:longint;
      z:string;
      xtitle:boolean;
   begin

   //defaults
   result   :=nilrect;

   //check
   z      :=icaps[zindex];

   if (z='') then exit;

   xtitle :=(istys[zindex]=1);

   if xtitle and xtightblocks then exit;//don't draw titles when in xtightblocks mode

   //get
   z        :=#32+z+#32;
   tw       :=fast__textwidth('',z,s.Rfn);

   case xtitle of
   true:begin//title

      result:=area__make(s.ci.left,dy,s.ci.right,dy+xlineheight2-1);
      if xmustpaint then
         begin

         //init
         br:=low__aorb(vititle.disableborder,vititle.border,s.e);
         bc:=low__aorb(vititle.disable,vititle.background,s.e);
         tc:=low__aorb(vititle.disablefont,vititle.font,s.e);

         //color block
         ffillarea   ( result ,bc ,viround );
         foutlinearea( result ,br ,viround );

         //text
         ftext(bc,result,result.left+2,dy+((xlineheight2-s.fnH) div 2),tc,'',z,s.Rfb,true);

         end;

      end;
   else begin

      result:=area__make(dx,dy,dx+xsetwidth-1,dy+xlineheight-1);

      if xtightblocks then
         begin

         if ((s.ci.right-result.right)<xsetwidth) then result.right:=s.ci.right;//stretch to far right -> no right rounding gap
         //no: looks bad: if ((ci.bottom-result.bottom)<xlineheight) then result.bottom:=ci.bottom;//stretch to far bottom -> no bottom rounding gap

         end;

      if xmustpaint then
         begin

         //init
         br  :=s.border;
         bc  :=icols[zindex];
         //was: tc  :=int__invert2b(bc,true);
         tc  :=int__colorlabel(bc);//13sep2024

         case xtightblocks of
         true:begin                     //show the click

            ffillarea   ( result ,bc                                                   ,false );//color block
            foutlinearea( result ,low__aorb(bc,tc,oclicktouse and (zindex=idownindex)) ,false );

            end;
         else begin

            ffillarea   ( result ,bc ,viround );//color block
            foutlinearea( result ,br ,viround );

            if oshowcaps then ftext(bc,result,dx+((xsetwidth-tw) div 2),dy+((xlineheight-s.fnH) div 2),tc,'',z,s.Rfn,true);//text

            end;
         end;//case

         end;
      end;
   end;//case
   end;
begin
//defaults
result:=0;

try
//init
infovars(s);

//.xcount + xsetwidth
xtightblocks   :=otightblocks;
hsp            :=low__insint(_hsp*s.zoom,not xtightblocks);
vsp            :=low__insint(_vsp*s.zoom,not xtightblocks);
xcount         :=low__aorb(icount,itemsperline,itemsperline>=1);
xsetwidth      :=frcmin32( (s.ci.right-s.ci.left+1-((xcount+1)*hsp)) div frcmin32(xcount,1),1);

if xtightblocks then
   begin

   int1        :=0;

   for p:=0 to high(icaps) do if (icaps[p]<>'') and (istys[p]=0) then inc(int1);

   int2        :=int1 div xcount;
   if ((int2*xcount)<>int1) then inc(int2);

   xlineheight :=(s.ci.bottom-s.ci.top+1) div int2;
   xlineheight2:=xlineheight;

   end
else
   begin

   xlineheight :=lineheight;//color palette
   xlineheight2:=lineheight2;//title

   end;

xlaststyle:=-1;
xonce:=true;

//cls
if xmustpaint then ffillArea(s.cs,s.back,false);

//links
dx:=s.ci.left+hsp;
dy:=s.ci.top;
dcount:=0;

for p:=0 to high(icaps) do
begin

if (icaps[p]<>'') then
   begin

   if xonce and (istys[p]<>1) then inc(dy,vsp);
   inc(dcount);

   if (dcount>xcount) or ((istys[p]=1) and (xlaststyle=0)) or ((xlaststyle<>istys[p]) and (not xonce)) then
      begin

      dcount          :=1;
      dx              :=s.ci.left+hsp;

      inc(dy,low__aorb(xlineheight,xlineheight2,(xlaststyle=1))+vsp);

      if (istys[p]=1) and (xlaststyle<>1) then inc(dy,3);

      end;

   b                  :=xlink(p);

   if xmustpaint then irecs[p]:=b;

   inc(dx,xsetwidth+hsp);

   xlaststyle         :=istys[p];
   xonce              :=false;

   end
else
   begin

   if xmustpaint then irecs[p]:=nilrect;

   end;

end;//p

//frame
if xmustpaint then xframeSimple( s);

//return result
if (dy>=1) then result:=dy+xlineheight+vsp;

except;end;
end;

function tbasiccolors._onnotify(sender:tobject):boolean;
var
   int1,int2,p:longint;

   function xfinditem(s:tpoint;var xindex:longint):boolean;
   var
      p:longint;
   begin

   result   :=false;
   xindex   :=-1;

   for p:=0 to high(icaps) do if (icaps[p]<>'') and area__within2(irecs[p],s) then
      begin

      xindex:=p;
      result:=true;
      break;

      end;

   end;

   function xfinditem2(s:tpoint;var xindex:longint):boolean;
   var
      p:longint;
   begin

   result   :=false;
   xindex   :=-1;

   for p:=0 to high(icaps) do if (icaps[p]<>'') and (istys[p]=0) and area__within2(irecs[p],s) then
      begin

      xindex:=p;
      result:=true;
      break;

      end;

   end;

begin

//defaults
result      :=false;

try

//mouse down
if gui.mousedownstroke then
   begin

   result   :=true;
   xfinditem2(mousedownxy,idownindex);
   paintnow;

   end;

//mouse move
if gui.mousemoved and (not gui.mousedown) then
   begin

   result   :=true;
   if xfinditem(mousexy,p) then help2:=ihlps[p] else help2:='';

   end;

if gui.mousemoved and gui.mousedown then
   begin

   result   :=true;
   if opopcolor and (idownindex>=0) and (idownindex<=high(icaps)) and gui.mousedraggingout3(clientarea.left,clientarea.top,irecs[idownindex],true,true) then col[idownindex]:=low__capcolor(0,0,true);

   end;

//mouse up
if gui.mouseupstroke then
   begin

   result   :=true;

   //reset
   if (idownindex>=0) then
      begin

      int1            :=idownindex;
      idownindex      :=-1;

      if oclicktouse and (int1>=0) and (not gui.mousewasdraggingout) and assigned(foncolor) then
         begin

         foncolor(self,icols[int1]);

         end

      else if opopcolor and (int1>=0) and (not gui.mousewasdraggingout) then
         begin

         int2         :=col[int1];

         if gui.popcolor(int2) then col3[int1]:=int2;//25may2021, 25feb2021

         end;

      paintnow;

      end;

   end;

//external event override - 01mar2021
if assigned(fonnotify) then fonnotify(sender);

except;end;
end;


//## tmainhelp #################################################################
constructor tmainhelp.create2(xparent:tobject;xscroll,xstart:boolean);
var
   s1,s2,d:tstr8;
begin

if classnameis('tmainhelp') then track__inc(satMainhelp,1);
inherited create2(xparent,false,false);//force "xscroll=false" - fixed 02aug2021

//** Information ***
//Use special insert tags to insert text and images using a txt or bwd document:
// [l] or [c] or [r] = align single line of text as left, center or right align
// [banner]          = insert "programbanner" image
// [sep]             = insert "tepBanner" text image
// [*]               = insert "tepBullet" text image
// [programname]     = insert "programname" text
// [programversion]  = insert "programversion" text
// [programurl]      = insert program website url
// [programzip]      = insert program website zip
// [softwareurl      = insert software website url
// [vintageurl]      = insert vintage website url
// [beurl]           = insert portal address for Blaiz Enterprises
// [bename]          = insert Blaiz Enterprises name "BlaizEnterprises.com"
// [twitterurl]      = insert BE twitter url
// [facebookurl]     = insert BE facebook url
// [instagramurl]    = insert BE instagram url
// [t]               = mark as $claude.header1 and include as a help topic
// [h1]..[h5]        = mark as $claude.header1..5 and include as a help topic

//defaults
s1      :=nil;
s2      :=nil;
d       :=nil;
itopics :=nil;

//vars
bordersize       :=0;
ibuildingcontrol :=true;
ifasttimer       :=slowms64;
irootmin         :=6;
irootmax         :=24;
irootsize        :=10;
itopics          :=tdynamicstring.create;

xtoolbar;
xtoolbar.oflatback:=true;
xtoolbar.add('Help Topics',tepList20,0,'topics','Show list of help topics');
xtoolbar.add('Menu',tepmenu20,0,'menu','Show menu');
xtoolbar.hcsadd('B/W',tepBW20,0,'bw','Switch between app colors and high-contrast black and white',0);

xtoolbar.add('',tepless20,0,'smaller','Decrease text size');
xtoolbar.add2('',tepmore20,0,'larger','Increase text size',true);
xtoolbar.add('Hide',tepClose20,0,'closehelp','Hide help panel');
xtoolbar.bvisible2['topics']:=false;//hide by default

try
//init
s1:=str__new8;
s2:=str__new8;
d :=str__new8;

s1.aadd(apphelp);
s2.aadd(syshelp);

//get
textcore__2to1(s1,s2,d,'bwp',#10#10);

//.read combined help file
ibwp                         :=nbwp3(programname+' Help',d,wwsWindow,false,false,false);
ibwp.core.maxformatlevel     :=fmlBWP;//allow for images
ibwp.makeviewonly;
ibwp.core.onefontsize        :=-1;
ibwp.core.onefontname        :='$fontname';
ibwp.oautoheight             :=true;
ibwp.ousepagecolor           :=true;
ibwp.wrap                    :=wwsWindow;
ibwp.wrapreadonly            :=true;//lock in wrap mode - 12mar2021
ibwp.setfocus;
ibwp.hint                    :='';//25dec2024

xhelptopics;

except;end;

//events
xtoolbar.onclick:=__onclick;

//defaults
ibuildingcontrol:=false;
ocanshowmenu:=true;

//free
str__free(@s1);
str__free(@s2);
str__free(@d);

//start
if xstart then start;//fixed - 02aug2021

end;

destructor tmainhelp.destroy;
begin
try
ibuildingcontrol:=true;
timer:=false;
inherited destroy;
freeobj(@itopics);
if classnameis('tmainhelp') then track__inc(satMainhelp,-1);
except;end;
end;

procedure tmainhelp.xsetroundstyle(x:longint);//15mar2022
begin
xtoolbar.oroundstyle:=x;
ibwp.oroundstyle:=x;
end;

procedure tmainhelp.showmenuFill(xstyle:string;xmenudata:tstr8;var ximagealign:longint;var xmenuname:string);
var
   str1:string;
   int1:longint;
begin
try
//check
if zznil(xmenudata,2318) then exit;
xmenuname:='mainhelp.1';

if (xstyle='menu') then
   begin
   //edit
   //no need for a title at this point -> "tbasicbwp" already has a title -> low__menutitle(xmenudata,tepnone,'Edit,'Edit options');
   int1:=ximagealign;
   str1:=xmenuname;
   ibwp.showmenuFill('',xmenudata,int1,str1);

   //special mode
   if system_debug then low__menuitem2(xmenudata,tepcopy20,'Copy Document To Clipboard','Copy document to Clipboard','bwp.copyallbwp',100,aknone,true);

   //settings
   low__menutitle(xmenudata,tepnone,'Settings','Settings');
   low__menuitem2(xmenudata,tepmore20,'Increase Text Size','Increase text size','larger',100,aknone,irootsize<irootmax);
   low__menuitem2(xmenudata,tepless20,'Decrease Text Size','Decrease text size','smaller',100,aknone,irootsize>irootmin);
   low__menuitem2(xmenudata,tep__yes(vihelp_bw),'High-Contrast Black and White','Ticked: Show help in high-contrast black and white','toggle.helpbw',100,aknone,true);
   low__menuitem2(xmenudata,tep__yes(vihelp_max),'Full Height Help','Toggle full height help display','helpmax.toggle',100,aknone,true);
   low__menuitem2(xmenudata,tepClose20,'Hide Help','Hide Built-in Help','closehelp',100,aknone,true);

   end;

except;end;
end;

function tmainhelp.showmenuClick(sender:tobject;xstyle:string;xcode:longint;xcode2:string;xtepcolor:longint):boolean;
begin
//handled
result:=true;

try
//information
if      (xcode2='help')               then gui.xshowhelp
else if (strcopy1(xcode2,1,4)='bwp.') then ibwp.showmenuClick(sender,xstyle,xcode,xcode2,xtepcolor)
else if (xcode2='closehelp')          then low__showhelp(false)
else if (xcode2='smaller')            then xchangerootsize(-1)
else if (xcode2='larger')             then xchangerootsize(+1)
else if (xcode2='toggle.helpbw') then
   begin
   syssettings.b['help.bw']:=not syssettings.b['help.bw'];
   visyncandsave;
   end
else if (xcode2='helpmax.toggle') then
   begin
   syssettings.b['help.max']:=not vihelp_max;//18dec2021
   visyncandsave;
   end
//not handled
else result:=false;
except;end;
end;

procedure tmainhelp.xhelptopics;//24apr2025
begin
try

//check
if zznil(itopics,2356) or zznil(ibwp,2357) or (ibwp.core=nil) or (itopics=nil) then exit;

//clear
itopics.clear;

//transform
ibwp.core.transform(true,false,itopics);//25mar2026

//set
xtoolbar.bvisible2['topics']:=(itopics.count>=1);

with ibwp.core do
begin

cursorpos:=0;
cursorpos2:=len32;

csize            :=xrootsizeScaled;
cwritesel( smFontsize );

cname        :=font__name1;
cwritesel( smFontname );

nosel;

end;

except;end;
end;

procedure tmainhelp.xchangerootsize(const xby:longint);
begin

irootsize:=frcrange32( irootsize + xby ,irootmin ,irootmax );

end;

function tmainhelp.xrootsizeScaled:longint32;
begin

result:=frcmin32( round32(irootsize * viscale) ,6 );

end;

procedure tmainhelp._ontimer(sender:tobject);
var
   bol1:boolean;
begin

//ifasttimer
if (slowms64>=ifasttimer) then
   begin

   //black and white
   bol1                         :=vihelp_bw;
   ibwp.syscols                 :=not bol1;
   xtoolbar.bhighlight2['bw']   :=bol1;
   xtoolbar.bflash2['bw']       :=bol1;

   //size
   xtoolbar.benabled2['smaller']:=(irootsize>irootmin);
   xtoolbar.benabled2['larger'] :=(irootsize<irootmax);


   //rootsize.scaled
   if (ibwp.core.csize<>xrootsizeScaled) then
      begin

      with ibwp.core do
      begin

      cursorpos                 :=0;
      cursorpos2                :=len32;

      csize                     :=xrootsizeScaled;
      cwritesel( smFontsize );

      nosel;

      end;//with

      end;

   //reset
   ifasttimer                   :=add64(slowms64,200);

   end;

end;

procedure tmainhelp.__onclick(sender:tobject);
var
   xcode2,str1,n:string;
   xcode,xtepcolor,int1,xpos,v:longint;
   xonce:boolean;
   m:tstr8;

   function xnexttopic(var xtextpos:longint;var xtext:string):boolean;
   var
      xdata:string;
      xlen,p:longint;
   begin
   //defaults
   result:=false;
   xtextpos:=1;
   xtext:='';

   try
   //check
   if (xpos<0) then xpos:=0;
   if (xpos>=itopics.count) then exit;

   //init
   xdata:=itopics.value[xpos];
   xlen:=low__len32(xdata);

   //get
   if (xlen>=2) then
      begin
      for p:=1 to xlen do if (strcopy1(xdata,p,1)='|') then
         begin
         xtextpos:=strint32(strcopy1(xdata,1,p-1));
         xtext:=strcopy1(xdata,p+1,xlen);
         break;
         end;//p
      end;

   //inc
   inc(xpos);

   //successful
   result:=true;
   except;end;
   end;
begin
try
//defaults
m:=nil;

//check
if zznil(sender,2359) then exit;

//get
if (sender is tbasictoolbar) then
   begin
   //init
   n:=strlow((sender as tbasictoolbar).ocode2);
   v:=(sender as tbasictoolbar).ocode;

   //get
   if (n='bw') then showmenuClick(sender,'',100,'toggle.helpbw',clnone)
   else if (n='closehelp') then low__showhelp(false)
   else if (n='smaller') then showmenuClick(sender,'',100,'smaller',clnone)
   else if (n='larger') then showmenuClick(sender,'',100,'larger',clnone)
   else if (n='menu') then showmenu2('menu')
   else if (n='topics') then
      begin
      //get
      m:=str__new8;
      low__menuinit(m);
      low__menutitle(m,tepNone,'Help Topics','Select a help topic to view');
      xonce:=true;
      xpos:=0;
      while true do
      begin
      if xnexttopic(int1,str1) then
         begin
         if (str1<>'') then
            begin
            if xonce then
               begin
               xonce:=false;
               if (int1>1) then low__menuitem2(m,tepUp20,'Start of Help','Scroll to beginning of help','help.topic',100+1,aknone,true);
               end;
            low__menuitem2(m,tepHelpdoc20,str1,'Select help topic to view','help.topic',100+int1,aknone,true);
            end;
         end
      else break;
      end;
      low__menuend(m);

      //show
      if gui.popmenu2(pmNormal,iaNormal,m,'help.viewer',lslist,xcode,xcode2,xtepcolor) then
         begin
         if (xcode2='help.topic') then
            begin
            ibwp.vscrolltopos(xcode-100);
            ibwp.setfocus;//refocus the text box - 27apr2022
            end;
         end;
      end;
   end;
except;end;
//free
str__free(@m);
end;

//## tplaylist #################################################################
constructor tplaylist.create;//20mar2022
begin
try
//self
if classnameis('tplaylist') then track__inc(satPlaylist,1);
inherited create;
//vars
iopenfilter:=0;
ilistcoreid:=0;
ilistcoreUNDO:=str__new8;
ilistcoreFULL:=str__new8;
ilistcore:=str__new8;
ilist:=nil;
ilistcoreCANUNDO:=false;
ilistcoreUNDO_itemindex:=0;
ifilenameOPEN:=io__windrive+'Untitled.m3u';
ifilenameSAVE:=ifilenameOPEN;
ipartmask:='';
ifullmask:='';
except;end;
end;

destructor tplaylist.destroy;//20mar2022
begin
try
//vars
list:=nil;//disconnect
str__free(@ilistcoreUNDO);
str__free(@ilistcoreFULL);
str__free(@ilistcore);
//self
inherited destroy;
if classnameis('tplaylist') then track__inc(satPlaylist,-1);
except;end;
end;

function tplaylist.xlistitem(sender:tobject;xindex:longint;var xtab:string;var xtep,xtepcolor:longint;var xcaption,xcaplabel,xhelp,xcode2:string;var xcode,xshortcut,xindent:longint;var xflash,xenabled,xtitle,xsep,xbold:boolean):boolean;
var
   asec:longint;
   atitle,afilename:string;
begin
if listok and (sender=ilist) then
   begin
   result:=true;
   playlist__getone('',ilistcore,xindex,asec,atitle,afilename);
   xtep:=tep__filetype202(afilename,tepFNew20);
   xcaplabel:=atitle;
   xcaption:=afilename;
   end
else result:=false;
end;

function tplaylist.listok:boolean;
begin
result:=(ilist<>nil);
end;

procedure tplaylist.setlist(x:tbasicmenu);
begin
if (x<>ilist) then
   begin
   //disconnect list
   if (x=nil) and listok then ilist.ongetitem:=nil;
   //get
   ilist:=x;
   //connect list and sync
   if listok then
      begin
      ilist.ongetitem:=xlistitem;
      xlistsync;
      end;
   end;
end;

procedure tplaylist.setpartmask(x:string);
begin
if low__setstr(ipartmask,x) then xmask(true);
end;

procedure tplaylist.setfullmask(x:string);
begin
ifullmask:=x;
end;

procedure tplaylist.xmask(xforce:boolean);
var
   a:tstr8;
   p,xsec:longint;
   xtitle,xfilename,v:string;
begin
try
//defaults
a:=nil;
//get
v:=ipartmask;
if (v<>ipartmask) or xforce then
   begin
   //init
   ipartmask:=v;
   a:=str__new8;
   //get
   for p:=0 to playlist__count(ilistcoreFULL) do
   begin
   playlist__getone('',ilistcoreFULL,p,xsec,xtitle,xfilename);
   playlist__addone('',a,xsec,xtitle,xfilename,ipartmask);
   end;//p
   //set
   ilistcore.clear;
   ilistcore.add(a);//all in one go
   //.inc id
   low__iroll(ilistcoreid,1);
   //.sync with host list
   xlistsync;
   end;
except;end;

//free
str__free(@a);

end;

procedure tplaylist.xlistsync;
begin
//check
if not listok then exit;
//get
ilist.makelistx(playlist__count(ilistcore));
ilist.itemindex:=frcrange32(ilist.itemindex,0,frcmin32(ilist.count-1,0));//20mar2022
end;

function tplaylist.canclear:boolean;
var
   e:string;
begin
result:=xcmd('canclear',e);
end;

function tplaylist.clear(var e:string):boolean;
begin
result:=xcmd('clear',e);
end;

function tplaylist.cannew:boolean;
var
   e:string;
begin
result:=xcmd('cannew',e);
end;

function tplaylist.new(var e:string):boolean;
begin
result:=xcmd('new',e);
end;

function tplaylist.cancut:boolean;
var
   e:string;
begin
result:=xcmd('cancut',e);
end;

function tplaylist.cut(var e:string):boolean;
begin
result:=xcmd('cut',e);
end;

function tplaylist.cancopy:boolean;
var
   e:string;
begin
result:=xcmd('cancopy',e);
end;

function tplaylist.copy(var e:string):boolean;
begin
result:=xcmd('copy',e);
end;

function tplaylist.cancopyall:boolean;
var
   e:string;
begin
result:=xcmd('cancopyall',e);
end;

function tplaylist.copyall(var e:string):boolean;
begin
result:=xcmd('copyall',e);
end;

function tplaylist.canpaste:boolean;
var
   e:string;
begin
result:=xcmd('canpaste',e);
end;

function tplaylist.paste(var e:string):boolean;
begin
result:=xcmd('paste',e);
end;

function tplaylist.canreplace:boolean;
var
   e:string;
begin
result:=xcmd('canreplace',e);
end;

function tplaylist.replace(var e:string):boolean;
begin
result:=xcmd('replace',e);
end;

function tplaylist.canopen:boolean;
var
   e:string;
begin
result:=xcmd('canopen',e);
end;

function tplaylist.open(var e:string):boolean;
begin
result:=xcmd('open',e);
end;

function tplaylist.cansave:boolean;
var
   e:string;
begin
result:=xcmd('cansave',e);
end;

function tplaylist.save(var e:string):boolean;
begin
result:=xcmd('save',e);
end;

function tplaylist.canundo:boolean;
var
   e:string;
begin
result:=xcmd('canundo',e);
end;

function tplaylist.undo(var e:string):boolean;
begin
result:=xcmd('undo',e);
end;

procedure tplaylist.xfillundo;
begin
ilistcoreCANUNDO:=true;
if listok then ilistcoreUNDO_itemindex:=ilist.itemindex;
ilistcoreUNDO.clear;
ilistcoreUNDO.add(ilistcoreFULL);
end;

function tplaylist.xundo(var e:string):boolean;
var
   a:tstr8;
   int1:longint;
begin
//defaults
result:=false;
a:=nil;
e:=gecTaskfailed;

try
//1
a:=str__new8;
a.add(ilistcoreUNDO);
int1:=ilistcoreUNDO_itemindex;
//2
ilistcoreUNDO.clear;
ilistcoreUNDO.add(ilistcoreFULL);
if listok then ilistcoreUNDO_itemindex:=ilist.itemindex;
//3
ilistcoreFULL.clear;
ilistcoreFULL.add(a);
xmask(true);
if listok then ilist.itemindex:=int1;
//successful
result:=true;
except;end;

str__free(@a);
end;

function tplaylist.xguiOK:boolean;
begin
result:=(system_program<>nil) and (system_program.gui<>nil);
end;

function tplaylist.xgui:tbasicsystem;
begin
if xguiOK then result:=system_program.gui else result:=nil;
end;

function tplaylist.xcmd(n:string;var e:string):boolean;
begin
//defaults
result:=true;
e:=gecTaskfailed;

try
//init
n:=strlow(n);

//new
if (n='cannew') then result:=true
else if (n='new') then
   begin
   if xcmd('cannew',e) and xguiOK and xgui.popquery('Clear current playlist?') then
      begin
      xfillundo;
      ilistcoreFULL.clear;
      xmask(true);
      end;
   end
//clear
else if (n='canclear') then result:=true
else if (n='clear') then
   begin
   if xcmd('canclear',e) then
      begin
      xfillundo;
      ilistcoreFULL.clear;
      xmask(true);
      end;
   end
//cut
else if (n='cancut') then
   begin
   if listok then result:=(playlist__count(ilistcore)>=1) else result:=(playlist__count(ilistcoreFULL)>=1);
   end
else if (n='cut') then//one
   begin
   result:=xcmd('cancopy',e) and xcopy(false,true,e);
   end
//copy
else if (n='cancopy') then
   begin
   if listok then result:=(playlist__count(ilistcore)>=1) else result:=(playlist__count(ilistcoreFULL)>=1);
   end
else if (n='copy')       then result:=xcmd('cancopy',e) and xcopy(false,false,e)
//copy all
else if (n='cancopyall') then result:=(playlist__count(ilistcore)>=1)
else if (n='copyall')    then result:=xcmd('cancopyall',e) and xcopy(true,false,e)
//paste
else if (n='canpaste')   then result:=clip__canpastetext
else if (n='paste')      then result:=xcmd('canpaste',e) and xpaste(false,e)
//replace
else if (n='canreplace')   then result:=clip__canpastetext
else if (n='replace')      then result:=xcmd('canreplace',e) and xpaste(true,e)
//undo
else if (n='canundo')   then result:=ilistcoreCANUNDO
else if (n='undo')      then result:=xcmd('canundo',e) and xundo(e)
//open
else if (n='canopen')   then result:=true
else if (n='open')      then result:=xcmd('canopen',e) and xopen(e)
//saveas
else if (n='cansave')   then result:=(playlist__count(ilistcoreFULL)>=1)
else if (n='save')      then result:=xcmd('cansave',e) and xsave(e);

except;end;
end;

function tplaylist.xcopy(xall,xcut:boolean;var e:string):boolean;
label
   skipend;
var
   xdata,a:tstr8;
   int1,s,t,p,xsec:longint;
   xtitle,xfilename:string;
begin
//defaults
result:=false;
e:=gecTaskfailed;
xdata:=nil;

try
//init
a:=ilistcoreFULL;//pointer only -> the full list behind the scenes list - 20mar2022
s:=0;
t:=frcmin32(playlist__count(a)-1,0);
if (not xall) and listok then
   begin
   a:=ilistcore;//the what we see list
   s:=ilist.itemindex;
   t:=s;
   end;
//check
if (playlist__count(a)<=0) then
   begin
   result:=true;
   goto skipend;
   end;
//range
s:=frcrange32(s,0,playlist__count(a)-1);
t:=frcrange32(t,s,playlist__count(a)-1);
//get
xdata:=str__new8;
xdata.sadd('#EXTM3U'+rcode);
for p:=s to t do
begin
playlist__getone('',a,p,xsec,xtitle,xfilename);
xdata.sadd('#EXTINF:'+intstr32(xsec)+','+xtitle+rcode);
xdata.sadd(low__makerelative(xfilename,'')+rcode+rcode);//1 blank line
end;//p
//set
if not clip__copytext2(@xdata) then goto skipend;
//cut
if xcut then
   begin
   //init
   xdata.clear;
   if listok then int1:=ilist.itemindex else int1:=0;
   //get
   xdata.sadd('#EXTM3U'+rcode);
   for p:=0 to frcmin32(playlist__count(a)-1,0) do
   begin
   if (p<>int1) then//omit the currently selected item - 20mar2022
      begin
      playlist__getone('',a,p,xsec,xtitle,xfilename);
      xdata.sadd('#EXTINF:'+intstr32(xsec)+','+xtitle+rcode);
      xdata.sadd(low__makerelative(xfilename,'')+rcode+rcode);//1 blank line
      end;
   end;//p
   //set
   xfillundo;
   xadd(xdata,int1,'',true);
   end;

//successful
result:=true;
skipend:
except;end;
str__free(@xdata);
end;

function tplaylist.xpaste(xclear:boolean;var e:string):boolean;
label
   skipend;
var
   a:tstr8;
   int1:longint;
begin
//defaults
result :=false;
a      :=nil;
e      :=gecTaskfailed;

try
//init
a:=str__new8;

//get
if listok then int1:=ilist.itemindex else int1:=0;
if not clip__pastetext2(@a) then goto skipend;

xfillundo;

if xclear then int1:=0;
if not xadd(a,int1,'',xclear) then goto skipend;//append to existing list

//sucessful
result:=true;
skipend:
except;end;

//free
str__free(@a);

end;

function tplaylist.canaddfile:boolean;
begin
result:=true;
end;

function tplaylist.addfile(const xfilename:string;var e:string):boolean;
label
   skipend;
var
   a:tstr8;
   int1:longint;
begin

//defaults
result :=false;
a      :=nil;
e      :=gecTaskfailed;

//check
if not canaddfile then exit;

if not io__fileexists(xfilename) then
   begin

   e:=gecFilenotfound;
   exit;

   end;

try
//init
a:=str__new8;

//get
a.text:=xfilename;
if listok then int1:=ilist.itemindex else int1:=0;

xfillundo;

if not xadd(a,int1,'',false) then goto skipend;//append to existing list

//sucessful
result:=true;
skipend:
except;end;

//free
str__free(@a);

end;

function tplaylist.xaddone(xsec:longint;xtitle,xfilename:string):boolean;//now supports "m3u" as well - 27mar2022
var
   a:tstr8;
   e:string;
   int1:longint;
begin
//defaults
result:=false;
a:=nil;

try
//get
if (io__readfileext_low(xfilename)='m3u') then
   begin
   a:=str__new8;
   if listok then int1:=ilist.itemindex else int1:=0;
   if io__fromfile(xfilename,@a,e) and (a.len>=1) then result:=xadd(a,int1,xfilename,false);
   end
else result:=playlist__addone('',ilistcoreFULL,xsec,xtitle,xfilename,ifullmask);
except;end;
try;if (a<>nil) then str__free(@a);except;end;
end;

function tplaylist.xadd(xdata:tstr8;xindex:longint;xauthoritativeFilename:string;xclear:boolean):boolean;
label
   skipend;
begin
//defaults
result:=false;

try
//check
if not str__lock(@xdata) then exit;
//set
if xclear then ilistcoreFULL.clear;
playlist__addall('',xauthoritativeFilename,ilistcoreFULL,xdata,ifullmask);
xmask(true);
if listok then ilist.itemindex:=frcrange32(xindex,0,frcmin32(ilist.count-1,0));
//successful
result:=true;
except;end;
try;str__uaf(@xdata);except;end;
end;

function tplaylist.xopen(var e:string):boolean;
var
   int1:longint;
begin
if listok then int1:=ilist.itemindex else int1:=0;
result:=xopen2(ifilenameOPEN,int1,true,true,e);
end;

function tplaylist.xopen2(xfilename:string;xindex:longint;xprompt,afillundo:boolean;var e:string):boolean;
label
   skipend;
var
   xdata:tstr8;
begin
//defaults
result:=false;
e:=gecTaskfailed;
xdata:=nil;

try
//prompt
if xprompt then
   begin
   ifilenameOPEN:=xfilename;
   if (not xguiok) or (not xgui.popopen(xfilename,iopenfilter,peM3U,'')) then
      begin
      result:=true;
      goto skipend;
      end;
   ifilenameOPEN:=xfilename;
   end;
//get
xdata:=str__new8;
if not io__fromfile(xfilename,@xdata,e) then goto skipend;
//set
e:=gecTaskfailed;
if afillundo then xfillundo;//fill undo
if not xadd(xdata,xindex,xfilename,true) then goto skipend;
//successful
result:=true;
skipend:
except;end;

//free
str__free(@xdata);

end;

function tplaylist.xsave(var e:string):boolean;
begin
result:=xsave2(ifilenameSAVE,true,e);
end;

function tplaylist.xsave2(dfilename:string;xprompt:boolean;var e:string):boolean;
label
   skipend;
var
   xdata:tstr8;
   daction,xtitle,xfilename:string;
   xsec,p,xcount:longint;
begin
//defaults
result:=false;
e:=gecTaskfailed;
xdata:=nil;

try
//prompt
if xprompt then
   begin
   ifilenameSAVE:=dfilename;
   daction:='';
   if (not xguiok) or (not xgui.popsave(dfilename,peM3U,'',daction)) then
      begin
      result:=true;
      goto skipend;//report no error
      end;
   ifilenameSAVE:=dfilename;
   end;
//init
xdata:=str__new8;
//get
//.header
xdata.sadd('#EXTM3U'+rcode);
//.contents
xcount:=playlist__count(ilistcoreFULL);
for p:=0 to (xcount-1) do
begin
playlist__getone('',ilistcoreFULL,p,xsec,xtitle,xfilename);
xdata.sadd('#EXTINF:'+intstr32(xsec)+','+xtitle+rcode);
xdata.sadd(low__makerelative(xfilename,dfilename)+rcode+rcode);//1 blank line
end;//p
//set
if not io__tofile(dfilename,@xdata,e) then goto skipend;
//successful
result:=true;
skipend:
except;end;

//free
str__free(@xdata);

end;

end.

