Big disks, FAT32, and long filenames are now supported.

This commit is contained in:
Scott Duensing 2026-10-12 21:23:16 -05:00
parent 824fe02f8d
commit eaf965555b
332 changed files with 4080 additions and 1130 deletions

View file

@ -501,6 +501,7 @@ img { max-width: 100%; }
<li><a href="#lang.runtime">FileOpsIsWritable</a></li>
<li><a href="#lang.runtime">FileOpsJobBytesDone</a></li>
<li><a href="#lang.runtime">FileOpsJobClearAttr</a></li>
<li><a href="#lang.runtime">FileOpsLongNames</a></li>
<li><a href="#lang.runtime">FileOpsMakePath</a></li>
<li><a href="#lang.runtime">FileOpsPathIsAbsolute</a></li>
<li><a href="#lang.runtime">FileOpsPathIsInside</a></li>
@ -508,9 +509,12 @@ img { max-width: 100%; }
<li><a href="#lang.runtime">FileOpsReadOnlySystem</a></li>
<li><a href="#lang.runtime">FileOpsReplaceFile</a></li>
<li><a href="#lang.runtime">FileOpsSetModified</a></li>
<li><a href="#lang.runtime">FileOpsShortPath$</a></li>
<li><a href="#lang.runtime">FileOpsTempDir$</a></li>
<li><a href="#lang.runtime">FileOpsTotalBytes</a></li>
<li><a href="#lang.runtime">FileOpsValidLongName</a></li>
<li><a href="#lang.runtime">FileOpsValidName</a></li>
<li><a href="#lang.runtime">FileOpsValidShortName</a></li>
<li><a href="#ctrl.drawing">FillColor</a></li>
<li><a href="#ctrl.drawing">FillStyle</a></li>
<li><a href="#lang.func.string">FILTER</a></li>
@ -528,6 +532,7 @@ img { max-width: 100%; }
<li><a href="#lang.runtime">FmRawAcquire</a></li>
<li><a href="#lang.runtime">FmWrite</a></li>
<li><a href="#ctrl.drawing">Focus rectangle</a></li>
<li><a href="#ctrl.drawing">FontScale</a></li>
<li><a href="#lang.loops">FOR</a></li>
<li><a href="#lang.fileio">FOR APPEND</a></li>
<li><a href="#lang.fileio">FOR BINARY</a></li>
@ -694,6 +699,7 @@ img { max-width: 100%; }
<li><a href="#lang.func.fileio">LOF</a></li>
<li><a href="#lang.func.math">LOG</a></li>
<li><a href="#lang.datatypes">Long</a></li>
<li><a href="#lang.runtime">Long File Names</a></li>
<li><a href="#lang.loops">LOOP</a></li>
<li><a href="#lang.io">LPRINT</a></li>
<li><a href="#lang.io">LPRINT USING</a></li>
@ -969,6 +975,7 @@ img { max-width: 100%; }
<li><a href="#lang.screenobj">Screen.Width</a></li>
<li><a href="#ctrl.scrollpane">Scrollable Container</a></li>
<li><a href="#ctrl.drawing">ScrollBarClick</a></li>
<li><a href="#ctrl.drawing">ScrollBarsNeeded</a></li>
<li><a href="#ctrl.scrollpane">ScrollPane</a></li>
<li><a href="#ctrl.common.props">ScrollToControl</a></li>
<li><a href="#ide.findreplace">Search</a></li>
@ -1021,6 +1028,7 @@ img { max-width: 100%; }
<li><a href="#lang.runtime">ShellAppMemory</a></li>
<li><a href="#lang.runtime">ShellArg$</a></li>
<li><a href="#lang.runtime">ShellArgCount</a></li>
<li><a href="#lang.runtime">ShellArgQuote$</a></li>
<li><a href="#lang.runtime">ShellCommandArgs$</a></li>
<li><a href="#lang.runtime">ShellCommandProgram$</a></li>
<li><a href="#lang.runtime">ShellConfigFile$</a></li>
@ -1213,6 +1221,7 @@ img { max-width: 100%; }
<li><a href="#lang.constants">vbBlack</a></li>
<li><a href="#lang.constants">vbBlue</a></li>
<li><a href="#lang.constants">vbBoolean</a></li>
<li><a href="#ctrl.drawing">vbBoth</a></li>
<li><a href="#lang.constants">vbByte</a></li>
<li><a href="#lang.constants">vbCancel</a></li>
<li><a href="#lang.screenobj">vbCascade</a></li>
@ -1245,6 +1254,7 @@ img { max-width: 100%; }
<li><a href="#lang.constants">vbHidden</a></li>
<li><a href="#lang.constants">vbHimetric</a></li>
<li><a href="#ctrl.drawing">vbHimetric</a></li>
<li><a href="#ctrl.drawing">vbHorizontal</a></li>
<li><a href="#lang.screenobj">vbHourglass</a></li>
<li><a href="#lang.constants">vbInches</a></li>
<li><a href="#lang.constants">vbInformation</a></li>
@ -1290,6 +1300,7 @@ img { max-width: 100%; }
<li><a href="#lang.constants">vbRetryCancel</a></li>
<li><a href="#lang.constants">vbRightButton</a></li>
<li><a href="#lang.constants">vbSaturday</a></li>
<li><a href="#ctrl.drawing">vbSBNone</a></li>
<li><a href="#lang.constants">vbSet</a></li>
<li><a href="#lang.constants">vbSingle</a></li>
<li><a href="#ctrl.common.props">vbSizeNESW</a></li>
@ -1321,6 +1332,7 @@ img { max-width: 100%; }
<li><a href="#lang.constants">vbUseSystem</a></li>
<li><a href="#lang.constants">vbUseSystemDayOfWeek</a></li>
<li><a href="#lang.constants">vbVariant</a></li>
<li><a href="#ctrl.drawing">vbVertical</a></li>
<li><a href="#lang.constants">vbWednesday</a></li>
<li><a href="#lang.constants">vbWhite</a></li>
<li><a href="#lang.constants">vbYellow</a></li>
@ -1369,7 +1381,7 @@ img { max-width: 100%; }
<main>
<div class="topic" id="ide.overview">
<h1>DVX BASIC IDE Guide</h1>
<p>DVX BASIC is a Visual BASIC development environment for DVX. It provides a VB3-style integrated development environment with a code editor, form designer, project system, and a full interactive debugger -- all integrated into DVX itself.</p>
<p>DVX BASIC is a BASIC development environment for DVX. It provides a VB3-style integrated development environment with a code editor, form designer, project system, and a full interactive debugger -- all integrated into DVX itself.</p>
<p>This guide covers every feature of the IDE: menus, toolbar, editor, form designer, project management, debugger, and auxiliary windows.</p>
<h2>IDE Windows</h2>
<p>The DVX BASIC IDE is modeled after Visual Basic 3.0. It consists of several floating windows arranged on the DVX desktop:</p>
@ -2171,13 +2183,22 @@ End Sub</code></pre>
<li>VAL keeps the magnitude of very long digit strings. Running out of memory while building a string raises error 14.</li>
<li>REDIM PRESERVE of a TYPE array keeps the existing elements.</li>
<li>Appending to a String variable with s = s + x or s = s &amp; x no longer copies the whole string each time, so building long strings in a loop is much faster. When x is InputBox$, MsgBox, CreateForm, CreateControl or Shell, s is still read before x runs (left to right).</li>
<li>And, Or, Xor, Eqv and Imp of two Booleans give a Boolean, and Not of a Boolean gives a Boolean, as in Visual Basic 4 and later: Print (a &gt; 1) Or (b &gt; 1) prints True instead of -1, and TypeName gives &quot;Boolean&quot;. With a number on either side they still work on the bits and give a number.</li>
<li>Big disks and long file names: where the disk takes long file names (DVX under Windows, or a long file name driver loaded before DVX), OPEN, KILL, NAME, MKDIR, DIR$ and the other file statements use them, and the File Manager, the file dialogs and Terminal downloads keep them. A file can be bigger than 2 GB on a FAT32 disk; LOF, FILELEN, LOC and SEEK raise error 6 (Overflow) for a size or position past 2 GB rather than give a wrong number, and EOF stays right below it. FileOpsFreeBytes and FileOpsTotalBytes are right for disks past 2 GB.</li>
<li>Changed: FileOpsValidName takes the folder the name is for, FileOpsValidName(folder, itemName), since the rules depend on its disk; XferSafeName$ takes the folder a file is received into, XferSafeName$(name, folder). New: FileOpsLongNames, FileOpsShortPath$, FileOpsValidLongName and FileOpsValidShortName (fileops.bas), and ShellArgQuote$ (shell.bas), which puts a path with spaces in quotes for a command line.</li>
<li>Programs compiled with an older release must be rebuilt. A program whose procedure table records more than 64 locals for a procedure is refused when it is loaded.</li>
<li>A class may have at most 65536 member variables and a form at most 65536 form-level variables (as many as the compiled program can number); more is a compile error (&quot;Too many member variables in X&quot;, &quot;Too many form-level variables&quot;), and a program file that records more is refused when it is loaded.</li>
</ul>
<h2>Forms and Controls</h2>
<ul>
<li>A reference to a removed control or to a control of an unloaded form raises an &quot;unknown control&quot; runtime error. CreateControl with a parent that is not a container on the same form raises &quot;CreateControl: invalid parent&quot;.</li>
<li>SetEvent works on forms (Me) and menu items; a handler without parameters is called without the event's arguments.</li>
<li>Frame: the Caption from the .frm file or set by code now shows on the frame's border, and reading Caption gives it back (it was ignored and read back &quot;&quot;).</li>
<li>A control's Index below 0, in a .frm file or typed in the designer, means the control is not in a control array, in the designer, the form loader and the saved file alike (a negative Index was kept, saved without an Index line and read back as a different control).</li>
<li>ListBox: a horizontal scroll bar appears when the box is narrower than its longest item (its MaxWidth, or a narrow form); Left and Right scroll it a character at a time.</li>
<li>Padding = 0 and Spacing = 0 now mean no padding and no space (before, 0 meant the default). A form, box or ScrollPane that sets none keeps its own (4 pixels for forms, VBox and HBox; a Frame's Spacing is 0, a ScrollPane's both 0), and reading Padding or Spacing gives the pixels in use. In the designer, an empty Padding or Spacing on the form means the layout's own.</li>
<li>MaxWidth and MaxHeight win over MinWidth / MinHeight and over the size a control's contents ask for, and the space above the cap goes to the other controls instead of staying empty.</li>
<li>New drawing members on forms and PictureBoxes: FontScale (Print, TextWidth and TextHeight up to 8 times as large, for titles) and ScrollBarsNeeded (which scroll bars content of a size needs in an area, as the controls decide it; vbSBNone, vbHorizontal, vbVertical, vbBoth).</li>
<li>Form.Visible = True/False behaves exactly like Show/Hide, but only on a real change: Visible = True on a form that is already shown does nothing (a modal form stays modal), and on a form that has no window it is ignored. MinWidth and MinHeight read back the value that was set. Size properties are limited to 0..32767.</li>
<li>Disabling a container (for example Frame.Enabled = False) blocks mouse and keyboard input to every control inside it (also inside a disabled ScrollPane or Splitter), and SetFocus on such a control does nothing.</li>
<li>OptionButton.Value is a read/write Boolean (True = selected); the button's index is the new read-only OptionIndex. Setting Value raises no Click.</li>
@ -2479,7 +2500,7 @@ If file$ Like &quot;*.[!b]*&quot; Then Print &quot;Not a .b... extension&quot;</
If a Is b Then Print &quot;Same object&quot;
If TypeOf Source Is TextBox Then Print Source.Text</code></pre>
<h2>Logical / Bitwise Operators</h2>
<p>The logical operators work on Boolean values and also perform bitwise operations on integer values. With Null they give Null unless the other side decides the answer (False And Null is False, True Or Null is True); see Variants.</p>
<p>The logical operators work on Boolean values and also perform bitwise operations on integer values. As in Visual Basic, two Booleans give a Boolean (True And False is False, Not True is False, and Print (a &gt; 1) Or (b &gt; 1) prints True); when either side is a number they work on the bits and give a number (an Integer, or a Long when a side is Long): True And 3 is 3. With Null they give Null unless the other side decides the answer (False And Null is False, True Or Null is True, a Boolean as the other side is); see Variants.</p>
<pre> Operator Description
-------- -----------
NOT Logical/bitwise complement
@ -2544,7 +2565,7 @@ Dim matrix(1 To 10, 1 To 10) As Single
Dim Shared globalFlag As Boolean
Dim record As PersonType
Dim fixedStr As String * 20</code></pre>
<blockquote><strong>Note:</strong> A module-level variable is visible inside a SUB or FUNCTION only when it is declared with DIM SHARED (or named in a SHARED statement in that procedure). See Variable Scope below. Inside a SUB or FUNCTION, DIM declares a local variable that is recreated on each call (use STATIC to retain its value between calls). A SUB or FUNCTION holds at most 64 parameters and local variables together, including a few hidden ones that statements such as ON ... GOTO, SWAP and READ into array elements use while they run; a procedure that needs more fails to compile with &quot;Too many local variables&quot;.</blockquote>
<blockquote><strong>Note:</strong> A module-level variable is visible inside a SUB or FUNCTION only when it is declared with DIM SHARED (or named in a SHARED statement in that procedure). See Variable Scope below. Inside a SUB or FUNCTION, DIM declares a local variable that is recreated on each call (use STATIC to retain its value between calls). A SUB or FUNCTION holds at most 64 parameters and local variables together, including a few hidden ones that statements such as ON ... GOTO, SWAP and READ into array elements use while they run; a procedure that needs more fails to compile with &quot;Too many local variables&quot;. A program holds at most 512 module-level variables, a form at most 65536 form-level variables and a class at most 65536 member variables; more fails to compile.</blockquote>
<p>Fixed-length strings (STRING * n) are padded with spaces and truncated when assigned so their length is always exactly n.</p>
<p>DIM variable AS NEW ClassName (or AS NEW Collection) creates a new object at the DIM and stores it in the variable; without NEW an object variable starts as Nothing. See Objects and Class Modules. DIM variable AS NEW FormName makes a new copy of a form of the project (see Several Copies of a Form in the Form topic); DIM variable AS FormName declares a variable for that form or a copy of it.</p>
<h2>Variable Scope and SHARED</h2>
@ -3223,7 +3244,7 @@ ErrorHandler:
3 RETURN without GOSUB
4 Out of DATA
5 Illegal function call (bad argument to a built-in function; an undefined math result such as a negative number to a fractional power)
6 Overflow (value does not fit the target type; EXP, ^ or other math leaving the numeric range)
6 Overflow (value does not fit the target type; EXP, ^ or other math leaving the numeric range; a file size or position past 2 GB in LOF, FILELEN, LOC, SEEK, GET or PUT)
7 Out of memory
9 Subscript out of range / invalid variable or field index
10 This array is fixed or temporarily locked (REDIM, or ERASE of a dynamic array, while one of its elements, or a field of one, is passed by reference to a procedure that is still running)
@ -3653,7 +3674,7 @@ WHILE first$ &lt;&gt; &quot;&quot;
first$ = DIR$ ' next match, no argument
WEND</code></pre>
<h2>FILELEN</h2>
<p>Returns the length of a file in bytes. A file that does not exist raises error 53 (File not found).</p>
<p>Returns the length of a file in bytes. A file that does not exist raises error 53 (File not found); one past 2 GB raises error 6 (Overflow).</p>
<pre><code>bytes = FILELEN(filename$)</code></pre>
</div>
<div class="topic" id="lang.func.string">
@ -3915,6 +3936,7 @@ Print MonthName(Month(Date)); &quot; &quot;; WeekdayName(Weekday(Date), True)</c
LBOUND(array [, dim]) Integer Lower bound of an array dimension (default dim = 1)
UBOUND(array [, dim]) Integer Upper bound of an array dimension (default dim = 1)</pre>
<p>The dim argument of LBOUND and UBOUND must be a constant from 1 to 8.</p>
<p>File sizes and positions are Longs, so they stop at 2 GB (2,147,483,647 bytes). A disk can hold bigger files (up to 4 GB on FAT32); LOF, FILELEN, LOC and SEEK raise error 6 (Overflow) for a size or position past 2 GB rather than give a wrong number, and GET and PUT do the same for a record that would end past it. EOF stays right while the position is below 2 GB. FileOpsListSize and FileOpsTreeBytes (fileops.bas) give any file's size as a Double.</p>
</div>
<div class="topic" id="lang.func.misc">
<h1>Miscellaneous Functions</h1>
@ -4284,6 +4306,7 @@ NoMoney:
<li>A member's name cannot be a reserved word. Names such as Name, Show, Hide, Load, Print, Open, Close, Line, Input, Get, Put, Type, Error and Timer are keywords in DVX BASIC and cannot be used; Text, Caption, Value, Count, Item and Add are fine.</li>
<li>SHARED and DIM SHARED cannot be used in a class module; a class's code reaches the program's module variables that are declared DIM SHARED or PUBLIC.</li>
<li>A STATIC variable in a class procedure is kept per object, as in Visual Basic: each object has its own copy.</li>
<li>A class has at most 65536 member variables, its procedures' STATIC variables included; more fails to compile with &quot;Too many member variables in ClassName&quot;.</li>
<li>Class_Initialize and Class_Terminate take no parameters.</li>
<li>A class module cannot hold statements outside its procedures; the compiler reports &quot;Only declarations are allowed outside procedures in a class module&quot;.</li>
<li>NEW, PROPERTY, PUBLIC, PRIVATE and TYPEOF are reserved words. VARIANT, OBJECT, COLLECTION, EMPTY, NULL, EACH and IN are not.</li>
@ -4981,8 +5004,8 @@ End Sub</code></pre>
<h2>Files and Folders</h2>
<p>With fileops.bas in the project, a program can show and change what is on the disks. FileOpsList(folder, filter) reads a folder once -- its folders and the files matching filter -- and returns a listing (a number; FileOpsListFree frees it). FileOpsListRows$ gives the whole listing as name, size, type and date columns, ready for a ListView's SetRows, so even a folder of hundreds of files fills the list at once; FileOpsListSort re-sorts it by name, size, type or date with folders first. FileOpsListName$, FileOpsListIsFolder and FileOpsListSize read single entries, and FileOpsListFind finds one by name.</p>
<p>Paths: FileOpsPathNormalize$ (the full path of an existing folder, or &quot;&quot;), FileOpsPathParent$, FileOpsPathJoin$, FileOpsPathSame, FileOpsPathIsRoot, FileOpsPathIsAbsolute (True for a path that is complete by itself, such as &quot;C:\DOCS&quot;, False for one that counts from the current folder), FileOpsPathIsInside(path, folder) (True when path is folder itself or anywhere inside it: check it before copying or moving a folder, so it is never copied into itself), FileOpsPathSep$ (the character between folder names, &quot;\&quot; on DOS), FileOpsBaseName$ and FileOpsExtension$. FileOpsFilterMatch(itemName, filter) tells whether a name matches a filter the way the file dialogs match it: wildcards * and ?, several patterns separated by ; such as &quot;*.bmp;*.png&quot;, case not mattering.</p>
<p>Files: FileOpsMakeDir and FileOpsRename (FileOpsError$ says why one failed), FileOpsTempPath$ and FileOpsReplaceFile (save safely: write the new file to FileOpsTempPath$(path$), then FileOpsReplaceFile swaps it in; the old file comes back if that fails), FileOpsValidName (whether a name can be used as a file name here; FileOpsError$ says why not), FileOpsMakePath (a folder and every missing folder above it, which MKDIR does not make), FileOpsIsFolder, FileOpsGetAttr and FileOpsSetAttr (the FILEOPS_ATTR_ bits), FileOpsModified$ and FileOpsSetModified (when a file was last changed, read and set in the form &quot;YYYY-MM-DD HH:MM&quot;; FileOpsSetModified returns False for a date that does not exist), FileOpsTreeSize with FileOpsTreeBytes, FileOpsTreeFiles and FileOpsTreeFolders (the size of a whole folder) and FileOpsFormatSize$.</p>
<p>Drives: FileOpsDriveList$ (the drive letters), FileOpsDriveType (FILEOPS_DRIVE_FIXED for a hard disk, FILEOPS_DRIVE_REMOVABLE for a floppy disk drive, FILEOPS_DRIVE_REMOTE for a network drive or a CD-ROM; asking never makes a drive spin up), FileOpsBootDrive$ (the drive the computer started from), FileOpsFreeBytes, FileOpsFreeKb and FileOpsTotalBytes (the size of the disk). FileOpsIsWritable(folder) is False where files cannot be made (a CD-ROM, a write-protected floppy), and FileOpsReadOnlySystem() is True when DVX itself runs from such a disk, so settings cannot be saved in its folder. FileOpsTempDir$() is the folder for scratch files (&quot;&quot; when there is none).</p>
<p>Files: FileOpsMakeDir and FileOpsRename (FileOpsError$ says why one failed), FileOpsTempPath$ and FileOpsReplaceFile (save safely: write the new file to FileOpsTempPath$(path$), then FileOpsReplaceFile swaps it in; the old file comes back if that fails), FileOpsValidName(folder, itemName) (whether a name can be used for a new file or folder in folder, by the rules of its disk; FileOpsError$ says why not), FileOpsValidLongName and FileOpsValidShortName (the long-name or the 8.3 rules by themselves, whatever the disk takes), FileOpsShortPath$ (the short 8.3 form of an existing path, for an old program that cannot take long names or blanks), FileOpsMakePath (a folder and every missing folder above it, which MKDIR does not make), FileOpsIsFolder, FileOpsGetAttr and FileOpsSetAttr (the FILEOPS_ATTR_ bits), FileOpsModified$ and FileOpsSetModified (when a file was last changed, read and set in the form &quot;YYYY-MM-DD HH:MM&quot;; FileOpsSetModified returns False for a date that does not exist), FileOpsTreeSize with FileOpsTreeBytes, FileOpsTreeFiles and FileOpsTreeFolders (the size of a whole folder) and FileOpsFormatSize$.</p>
<p>Drives: FileOpsDriveList$ (the drive letters), FileOpsDriveType (FILEOPS_DRIVE_FIXED for a hard disk, FILEOPS_DRIVE_REMOVABLE for a floppy disk drive, FILEOPS_DRIVE_REMOTE for a network drive or a CD-ROM; asking never makes a drive spin up), FileOpsBootDrive$ (the drive the computer started from), FileOpsFreeBytes, FileOpsFreeKb and FileOpsTotalBytes (the size of the disk; right for disks past 2 GB too), FileOpsLongNames(path) (True when the disk holding path takes long file names: up to 255 characters, with spaces and several dots; otherwise names are 8.3). FileOpsIsWritable(folder) is False where files cannot be made (a CD-ROM, a write-protected floppy), and FileOpsReadOnlySystem() is True when DVX itself runs from such a disk, so settings cannot be saved in its folder. FileOpsTempDir$() is the folder for scratch files (&quot;&quot; when there is none).</p>
<p>FileOpsCopyTree, FileOpsMoveTree and FileOpsDeleteTree do a whole folder at once. For a long copy, move or delete the program stays usable when it runs the work as a job, a little at a time from a Timer: FileOpsJobCreate, then FileOpsJobAddSource for each file or folder, then FileOpsJobRunFor from the timer until it returns FILEOPS_STEP_DONE or FILEOPS_STEP_CANCELLED. When it returns FILEOPS_STEP_ASK (a file already exists, a file is read-only) or FILEOPS_STEP_ERROR, show FileOpsJobMessage$ and pass the user's choice to FileOpsJobAnswer. FileOpsJobCurrent$, FileOpsJobFilesDone, FileOpsJobFilesTotal, FileOpsJobPercent, FileOpsJobBytesDone and FileOpsJobBytesTotal show the progress, and FileOpsJobCancel stops the job. Files copied from a CD-ROM are read-only; FileOpsJobClearAttr job, FILEOPS_ATTR_READONLY before the job runs makes every copy changeable (FILEOPS_ATTR_EDITABLE clears all four attribute bits). Whatever a program leaves open is freed when it ends.</p>
<pre><code>Dim job As Long
@ -5036,7 +5059,7 @@ Sub FillTaskList ()
End If
Next i
End Sub</code></pre>
<p>Command lines. ShellCommandProgram$(commandLine) and ShellCommandArgs$(commandLine) split a command line the way ShellRunCommand does: the program (the first word, or the text in double quotes when it starts with one) and the arguments after it. ShellArgCount(commandLine) and ShellArg$(commandLine, index) split any command line into its words (index from 0) by DVX's rule: words are separated by blanks, and a word with blanks in it is written in double quotes, which ShellArg$ leaves off (&quot;&quot; past the last word). COMMAND$(n) gives this program's own arguments the same way.</p>
<p>Command lines. ShellCommandProgram$(commandLine) and ShellCommandArgs$(commandLine) split a command line the way ShellRunCommand does: the program (the first word, or the text in double quotes when it starts with one) and the arguments after it. ShellArgCount(commandLine) and ShellArg$(commandLine, index) split any command line into its words (index from 0) by DVX's rule: words are separated by blanks, and a word with blanks in it is written in double quotes, which ShellArg$ leaves off (&quot;&quot; past the last word). ShellArgQuote$(text) writes one word that way: text in double quotes when it holds blanks, as it is otherwise, so a folder or file name with spaces in it reaches the program it is passed to whole (ShellRun &quot;notepad.app&quot;, ShellArgQuote$(path$)). COMMAND$(n) gives this program's own arguments the same way.</p>
<p>Keys for every program. HotkeyAdd(keyText) makes a key such as &quot;Ctrl+Alt+E&quot; work whichever program is in front and returns its id (0 when it is not a key, needs Ctrl or Alt, or another program uses it). The program asks for the keys pressed from a Timer: HotkeyNext() returns the id of the oldest one not asked for yet, 0 when there is none. HotkeyRemove id stops one; the rest stop when the program ends. HotkeyText$(keyText) writes a key the way DVX does (&quot;ctrl+alt+e&quot; gives &quot;Ctrl+Alt+E&quot;; &quot;&quot; when it is not a key), handy for checking what the user typed. ShellItemKeyValid(keyText) is Program Manager's rule for an item's shortcut: Ctrl together with Alt or Shift, so it never takes a key a program uses itself (&quot;&quot; for no shortcut is valid too).</p>
<p>This program. ShellAppPath$ is this program's own path (ShellRun ShellAppPath$(), &quot;&quot; starts another copy), and ShellInstanceCount says how many copies are running, for example to place each new window a little lower and to the right. ShellSetPriority(priority) gives this program more or less of the computer's time while other programs run too: SHELL_PRIORITY_LOW, SHELL_PRIORITY_NORMAL (what every program starts with), SHELL_PRIORITY_HIGH or any number between; ShellPriority() reads it. A program busy with long work leaves the others room at low priority. A program allows more than one copy when Project Properties has &quot;Allow more than one copy to run at once&quot; ticked. ShellConfigFile$(fileName) is the full path of fileName in this program's settings folder -- where DVX's own programs keep their settings, the same for every copy of the program -- and makes the folder when it is missing; keep a desktop's groups there with prefs.bas. ShellLog text writes a line to the DVX log. ShellSetDesktop program makes a program the desktop DVX starts with the next time (&quot;&quot; for Program Manager again); when the desktop ends, DVX ends. ShellSetWelcome program sets the program DVX starts after the desktop the next time it starts (&quot;&quot; for none).</p>
<p>Program groups. Program Manager keeps its groups in PROGMAN.INI; a desktop written in BASIC uses the same model and file format. ShellGroupsLoad(path) opens a groups file (a file not saved yet has the groups Main and Startup) and returns a handle, ShellGroupsSave(groups, path) writes it and ShellGroupsFree frees it. Groups and items are numbered from 0; group 0 is Installed Programs, which ShellGroupsScan(groups, skipPath) fills with every installed program and which is never saved. ShellGroupsChanged tells cheaply whether a program was installed or removed since. ShellGroupCount, ShellGroupName$, ShellGroupFind, ShellGroupAdd, ShellGroupRename, ShellGroupDelete and ShellGroupNameValid manage the groups. ShellItemCount and ShellItemAdd(groups, group, name, program) list and add items; ShellItemGet$ and ShellItemSet read and change an item's fields by name (&quot;name&quot;, &quot;program&quot;, &quot;args&quot;, &quot;folder&quot;, &quot;icon&quot;, &quot;key&quot;, &quot;minimized&quot;, &quot;col&quot;, &quot;row&quot;, &quot;description&quot;); ShellItemDelete, ShellItemCopy, ShellItemMove, ShellItemReorder and ShellItemPlace rearrange them, ShellGroupArrange and ShellGroupPlaceUnplaced lay out an icon grid, and ShellItemMatches is Program Manager's search. ShellGroupsGet and ShellGroupsSet read and set the options (&quot;view&quot;: SHELL_VIEW_LARGE, SHELL_VIEW_SMALL or SHELL_VIEW_LIST; &quot;group&quot;, the group shown; &quot;autoArrange&quot;, &quot;minimizeOnRun&quot;, &quot;restoreAlone&quot;), and ShellGroupsHistory$ / ShellGroupsHistoryAdd keep the Run history (what ShellRunDialog$ takes). ShellItemIcon$(iconFile, program) is the file an item's icon comes from -- its icon file, else its program or picture, else the program that opens the document -- ready for LOADPICTURE.</p>
@ -5332,7 +5355,7 @@ Sub Timer1_Timer ()
End Sub</code></pre>
<h2>File Transfers</h2>
<p>With xfer.bas in the project, a program sends and receives files with XMODEM, XMODEM-1K, YMODEM or ZMODEM. A transfer is a number: XferSendFile and XferReceive start one on a serial port opened with SerOpen (comm.bas), and ConnSendFiles and ConnReceiveFiles start one on a connection (conn.bas), with the options Terminal has: escaping every control character, asking the receiver to continue interrupted files, and what to do with a file that is already there. On a serial port XferPoll moves the transfer along; on a connection ConnPoll does. XferStatus tells where it is (XFER_RUNNING until it ends with XFER_DONE, XFER_FAILED or XFER_CANCELLED), and XferBytes, XferSize, XferFile$, XferFileIndex, XferFileCount, XferBatchBytes, XferBatchSize, XferResumedAt and XferErrors show its progress; XferMessage$ says how it ended. A receive with XFER_EXIST_ASK stops in XFER_ASKING when a file already exists: XferAskSize, XferAskRemoteSize (the size the sender offers, -1 when it did not say) and XferCanResume describe it, and XferAnswer continues with an XFER_EXIST_ choice. XferCancel stops a transfer and XferClose frees it.</p>
<p>XferCrc16(bytes) and XferCrc32(bytes) give the check values the protocols use (CRC-16 as XMODEM computes it, 0 to 65535; the CRC-32 of ZMODEM and ZIP files as a Long, negative when its top bit is set) for any bytes. XferSafeName$(name) gives the 8.3 name a receive stores a sender's file name as: no folder or device name, only characters every disk accepts.</p>
<p>XferCrc16(bytes) and XferCrc32(bytes) give the check values the protocols use (CRC-16 as XMODEM computes it, 0 to 65535; the CRC-32 of ZMODEM and ZIP files as a Long, negative when its top bit is set) for any bytes. XferSafeName$(name, folder) gives the name a receive into folder stores a sender's file name as: no folder or device name; a long name, its case kept, where folder's disk takes long names (a character a name cannot hold becomes _), else an 8.3 name of characters every disk accepts.</p>
<h2>Lists You Draw Yourself</h2>
<p>With listhelp.bas in the project, a list or icon view a program draws itself -- in a UserControl or a PictureBox -- follows the same rules as ListBox and ListView. ListSelCreate(multi, count) makes a selection for count items (several at a time when multi is True) and returns a handle; it remembers which items are selected and which one is current (the one the keyboard moves). Items are numbered from 0. Give it the clicks and keys, and ask it what to draw:</p>
<pre> Function Description
@ -5567,8 +5590,8 @@ End Sub</code></pre>
Height Integer R/W Current height in pixels. Setting this changes the minimum height constraint.
MinWidth Integer R/W Minimum width for layout. Setting it works like setting Width; reading it returns the minimum that was set.
MinHeight Integer R/W Minimum height for layout. Setting it works like setting Height; reading it returns the minimum that was set.
MaxWidth Integer R/W Maximum width cap (0 = no limit, stretch to fill).
MaxHeight Integer R/W Maximum height cap (0 = no limit, stretch to fill).
MaxWidth Integer R/W Maximum width cap (0 = no limit, stretch to fill). It wins over MinWidth and over the width the control's contents ask for.
MaxHeight Integer R/W Maximum height cap (0 = no limit, stretch to fill). It wins over MinHeight and over the height the control's contents ask for.
Weight Integer R/W Layout weight. 0 = fixed size, &gt;0 = share extra space proportionally.
Visible Boolean R/W Whether the control is visible.
Enabled Boolean R/W Whether the control accepts user input. Disabling a container (Frame, VBox, HBox...) also blocks mouse and keyboard input to every control inside it.
@ -5658,13 +5681,13 @@ End Sub</code></pre>
Circle [Step](x, y), radius [, color [, start [, end [, aspect]]]] Draws a circle, ellipse or arc, filled with FillColor when FillStyle is 0 (full circles).
DrawFocusRect x, y, width, height [, color] Draws the dotted rectangle DVX shows around the control that has the keyboard focus (every other pixel of its edge), for things a program draws itself, such as the focused link of a help topic. A negative width or height counts from the other edge.
Point(x, y) The colour of a pixel, -1 outside the picture. With fewer than 16 million colours on the screen it is the colour the screen shows: black, white and full colours such as RGB(255, 0, 0) read back exactly, others may differ slightly.
Print items Writes text at CurrentX, CurrentY in ForeColor, with PRINT's ; , SPC and TAB; ends by moving to the next line unless the last item is followed by ; or ,.
Print items Writes text at CurrentX, CurrentY in ForeColor, FontScale times as large, with PRINT's ; , SPC and TAB; ends by moving to the next line unless the last item is followed by ; or ,.
PaintPicture picture, x, y [, width, height [, srcX, srcY, srcWidth, srcHeight [, opcode]]] Copies a picture, stretched to width x height: an image file (BMP, PNG, JPEG or GIF), a picture from LOADPICTURE, or a PictureBox given by its name as a string or by a Control variable. opcode combines each pixel with the one already there (see Raster Operations).
Scale [(x1, y1)-(x2, y2)] Gives the drawing coordinates of its own: (x1, y1) is the top-left corner and (x2, y2) the bottom-right one (y2 below y1 makes y go up). Scale alone goes back to pixels.
ScaleX(width [, fromScale [, toScale]]) A width in fromScale converted to toScale (see Scales).
ScaleY(height [, fromScale [, toScale]]) A height in fromScale converted to toScale.
TextWidth(text) Width of the text in the scale's units.
TextHeight(text) Height of a line of text in the scale's units.</pre>
TextWidth(text) Width of the text in the scale's units, at the FontScale size.
TextHeight(text) Height of a line of text in the scale's units, at the FontScale size.</pre>
<h2>Drawing the DVX Look</h2>
<p>These methods draw the parts DVX's own controls are made of, in the colours of the current theme, for controls a program draws itself (a PictureBox that acts as a list or a toolbar). Coordinates and lengths are in the scale's units; colours are RGB values.</p>
<pre> Method Description
@ -5675,6 +5698,7 @@ End Sub</code></pre>
DrawScrollBar x, y, length, position, visible, total [, horizontal [, control]] A scroll bar with its arrows and its thumb, for a list of total rows of which visible are shown from row position, with its top-left corner at x, y. It stands upright (16 pixels wide, length tall, arrows at the top and bottom) unless horizontal is True: then it lies across (length wide, 16 pixels tall, arrows at the left and right ends). With control True it is the narrower bar of a control such as ListBox (14 pixels).
DrawScrollArrow x, y, size, direction One arrow button of a scroll bar, as at the ends of DrawScrollBar's bars: a square button size wide and tall (size in the scale's horizontal units) with its top-left corner at x, y and an arrow pointing dvxArrowUp, dvxArrowDown, dvxArrowLeft or dvxArrowRight, in the theme's scroll bar colours.
ScrollBarClick(length, offset, position, visible, total [, horizontal [, control]]) The new position after a click on a scroll bar DrawScrollBar drew with the same length, rows, direction and kind: offset is how far the click is from the top of the bar, or from its left end when horizontal is True. The arrows move one row, the trough a page, the thumb leaves it as it is. Needs no drawing.
ScrollBarsNeeded(contentWidth, contentHeight, areaWidth, areaHeight) Which scroll bars content that big needs in an area that big, as DVX's controls decide it: vbSBNone (0), vbHorizontal (1), vbVertical (2) or vbBoth (3). A vertical bar narrows the area and may make a horizontal one needed, and the other way round. The sizes are in the object's scale. Needs no drawing.
PrintAccel text [, enabled] Prints a caption at CurrentX, CurrentY with the letter after &amp; underlined (&amp;&amp; prints one &amp;); enabled False gives the greyed, embossed look of a disabled control. CurrentX moves past the text.
TextWidthAccel(text) Width of a caption without its &amp; signs, in the scale's units.
AccelKey(text) The access key of a caption in lower case (&quot;f&quot; for &quot;&amp;File&quot;), &quot;&quot; when it has none.</pre>
@ -5745,6 +5769,7 @@ End Sub</code></pre>
DrawWidth Integer 1 Pen width in pixels.
FillStyle Integer 1 How boxes (B) and circles are filled with FillColor: 0 solid, 1 (the default) not at all, 2 horizontal lines, 3 vertical lines, 4 upward diagonals, 5 downward diagonals, 6 a cross hatch, 7 a diagonal cross hatch (the lines 8 pixels apart, the gaps left as they are). Other values are an error. BF fills solid in the line's colour.
FillColor Long &amp;H000000 Colour boxes and circles are filled with.
FontScale Integer 1 How many times as large Print writes its text (1 to 8): each dot of DVX's 8 x 16 font becomes a FontScale x FontScale block, for titles and banners. TextWidth and TextHeight follow it; PrintAccel does not.
AutoRedraw Boolean False True: no Paint events (see above).
ScaleMode Integer 3 Units of the coordinates (see Scales).
ScaleLeft Single 0 Coordinate of the left edge.
@ -6073,8 +6098,8 @@ End Sub</code></pre>
Visible Boolean False True shows the form and False hides it, exactly like Show and Hide (the first show fires Activate).
ContextMenu String &quot;&quot; Name of a popup menu shown when the form is right-clicked.
HelpTopic String &quot;&quot; Help topic opened by F1 while the form is active and the focused control has no HelpTopic of its own. Empty opens the project's help file at its default page.
Padding Integer 0 Space in pixels between the window's edges and the controls (the content box's Padding); 0 is the default of 4 pixels.
Spacing Integer 0 Space in pixels between one control and the next (the content box's Spacing); 0 is the default of 4 pixels.
Padding Integer 4 Space in pixels between the window's edges and the controls (the content box's Padding); 0 is none.
Spacing Integer 4 Space in pixels between one control and the next (the content box's Spacing); 0 is none.
WindowState Integer 0 vbNormal (0), vbMinimized (1, shown only as an icon at the bottom of the screen) or vbMaximized (2, filling the screen). Set on a hidden form (or in the .frm file), it takes effect when the form is shown; reading it then gives the state the form will have.
Controls Collection (none) The form's controls (read-only), in the order they were made: Me.Controls.Count, Me.Controls(1) (the first), Me.Controls(&quot;Text1&quot;), For Each c In Me.Controls. Elements of a control array are in it too but have no name key. Each use makes a new Collection; changing it does not change the form.
DesignMode Boolean False True puts the form in design mode, for a form designer: see Designing Forms below. Not in .frm files.
@ -6154,7 +6179,7 @@ Dim g As New Form1 ' declares and makes a copy at once</code></pre>
End If
End Sub</code></pre>
<h2>Drawing</h2>
<p>Forms have Visual Basic's drawing methods and properties (Cls, PSet, Line, Circle, Point, Print, PaintPicture, DrawFocusRect, DrawBevel, DrawButtonFace, DrawArrow, DrawScrollBar, DrawScrollArrow, ScrollBarClick, PrintAccel, Scale, CurrentX, CurrentY, ForeColor, BackColor, DrawWidth, FillColor, FillStyle, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight): see Drawing on Forms and PictureBoxes. In the form's own code use Me.Line, Me.Circle and so on.</p>
<p>Forms have Visual Basic's drawing methods and properties (Cls, PSet, Line, Circle, Point, Print, PaintPicture, DrawFocusRect, DrawBevel, DrawButtonFace, DrawArrow, DrawScrollBar, DrawScrollArrow, ScrollBarClick, ScrollBarsNeeded, PrintAccel, Scale, CurrentX, CurrentY, ForeColor, BackColor, DrawWidth, FillColor, FillStyle, FontScale, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight): see Drawing on Forms and PictureBoxes. In the form's own code use Me.Line, Me.Circle and so on.</p>
<h2>Example</h2>
<pre><code>Sub Form1_Load ()
Form1.Caption = &quot;Hello World&quot;
@ -6254,8 +6279,8 @@ End Sub</code></pre>
Invalidate Asks for UserControl_Paint at the next chance, once however often it is called before then: change many things (add a hundred items) and the control is drawn once.
PropertyChanged name Tells a designer that a property changed, so its property sheet shows the new value.
Cls, Line, PSet, Circle, Print, Point, PaintPicture, DrawFocusRect, TextWidth, TextHeight, Scale, ScaleX, ScaleY Drawing, as on a PictureBox.
DrawBevel, DrawButtonFace, DrawArrow, DrawScrollBar, DrawScrollArrow, ScrollBarClick, PrintAccel, TextWidthAccel, AccelKey Drawing in DVX's own look (bevels, button faces, arrows, upright and horizontal scroll bars and their arrow buttons, captions with an underlined access key), as on a PictureBox.
CurrentX, CurrentY, ForeColor, BackColor, FillColor, FillStyle, DrawWidth, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight Drawing properties, as on a PictureBox.</pre>
DrawBevel, DrawButtonFace, DrawArrow, DrawScrollBar, DrawScrollArrow, ScrollBarClick, ScrollBarsNeeded, PrintAccel, TextWidthAccel, AccelKey Drawing in DVX's own look (bevels, button faces, arrows, upright and horizontal scroll bars and their arrow buttons, captions with an underlined access key), as on a PictureBox.
CurrentX, CurrentY, ForeColor, BackColor, FillColor, FillStyle, FontScale, DrawWidth, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight Drawing properties, as on a PictureBox.</pre>
<p>The drawing members work exactly as on a PictureBox (see Drawing on Forms and PictureBoxes). Write them with UserControl in front -- UserControl.Line, UserControl.Print -- as a form's code writes Me.Line: a drawing statement on its own (Line, Cls, Print) draws on the program's screen, not on the control.</p>
<p>The drawing stays until you draw again. UserControl_Paint runs when the control first appears, after its size changed, when you call Refresh and after you call Invalidate; draw everything there and call UserControl.Invalidate (or UserControl.Refresh, to see the result at once) whenever what it shows changes.</p>
<h2>The Control's Events</h2>
@ -6369,8 +6394,8 @@ End Sub</code></pre>
<pre> Property Type Description
-------- ------- -------------------------------------------
Alignment Enum Where the children sit along the frame from top to bottom when they do not fill it: Left (the top, the default), Center or Right (the bottom).
Padding Integer Space in pixels between the border and the children; 0 (the default) means 4 pixels.
Spacing Integer Space in pixels between one child and the next; 0 (the default) means no space.</pre>
Padding Integer Space in pixels between the border and the children: 4 unless set; 0 is none.
Spacing Integer Space in pixels between one child and the next: none unless set.</pre>
<p>No type-specific methods or events.</p>
<p>Setting Enabled = False on a Frame disables every control inside it for mouse and keyboard input.</p>
<p>Container: Yes</p>
@ -6395,8 +6420,8 @@ End</code></pre>
<pre> Property Type Description
-------- ------- -------------------------------------------
Alignment Enum Where the children sit along the row when they do not fill it: Left (the left, the default), Center or Right (the right).
Padding Integer Space in pixels between the edge of the box and the children; 0 (the default) means 4 pixels.
Spacing Integer Space in pixels between one child and the next; 0 (the default) means 4 pixels.</pre>
Padding Integer Space in pixels between the edge of the box and the children: 4 unless set; 0 is none.
Spacing Integer Space in pixels between one child and the next: 4 unless set; 0 is none.</pre>
<p>Alignment = Right puts a row of buttons at the right, as dialog boxes have them.</p>
<p>No type-specific methods or events.</p>
<p>Container: Yes</p>
@ -6422,8 +6447,8 @@ End</code></pre>
<pre> Property Type Description
-------- ------- -------------------------------------------
Alignment Enum Where the children sit along the column when they do not fill it: Left (the top, the default), Center or Right (the bottom).
Padding Integer Space in pixels between the edge of the box and the children; 0 (the default) means 4 pixels.
Spacing Integer Space in pixels between one child and the next; 0 (the default) means 4 pixels.</pre>
Padding Integer Space in pixels between the edge of the box and the children: 4 unless set; 0 is none.
Spacing Integer Space in pixels between one child and the next: 4 unless set; 0 is none.</pre>
<p>No type-specific methods or events.</p>
<p>Container: Yes</p>
<p>Default Event: Click</p>
@ -6504,7 +6529,7 @@ Picture1.DrawText 60, 130, &quot;Hello!&quot;
If Picture1.Save(&quot;output.bmp&quot;) &lt;&gt; 0 Then
MsgBox &quot;Could not save output.bmp&quot;
End If</code></pre>
<p>A PictureBox also has Visual Basic's drawing methods and properties (Cls, PSet, Line, Circle, Point, Print, PaintPicture, DrawFocusRect, DrawBevel, DrawButtonFace, DrawArrow, DrawScrollBar, DrawScrollArrow, ScrollBarClick, PrintAccel, Scale, CurrentX, CurrentY, ForeColor, BackColor, DrawWidth, FillColor, FillStyle, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight) and a Paint event: see Drawing on Forms and PictureBoxes.</p>
<p>A PictureBox also has Visual Basic's drawing methods and properties (Cls, PSet, Line, Circle, Point, Print, PaintPicture, DrawFocusRect, DrawBevel, DrawButtonFace, DrawArrow, DrawScrollBar, DrawScrollArrow, ScrollBarClick, ScrollBarsNeeded, PrintAccel, Scale, CurrentX, CurrentY, ForeColor, BackColor, DrawWidth, FillColor, FillStyle, FontScale, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight) and a Paint event: see Drawing on Forms and PictureBoxes.</p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.drawing">Drawing on Forms and PictureBoxes</a></p>
</div>
@ -6820,7 +6845,7 @@ End</code></pre>
<div class="topic" id="ctrl.listbox">
<h1>ListBox</h1>
<p>VB Equivalent: ListBox -- DVX Widget: listbox</p>
<p>A scrollable list of selectable items. Items are managed via methods (AddItem, RemoveItem, Clear). Supports single and multi-select modes, drag-to-reorder, and keyboard navigation with type-ahead search.</p>
<p>A scrollable list of selectable items. Items are managed via methods (AddItem, RemoveItem, Clear). Supports single and multi-select modes, drag-to-reorder, and keyboard navigation with type-ahead search. When the box is narrower than its longest item (its width limited by MaxWidth or by the form), a horizontal scroll bar appears; it and the Left and Right keys scroll the items sideways a character at a time.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
--------- ------- -------------------------------------------

View file

@ -528,6 +528,7 @@ img { max-width: 100%; }
<li><a href="#api.draw">drawText</a></li>
<li><a href="#api.draw">drawTextAccel</a></li>
<li><a href="#api.draw">drawTextN</a></li>
<li><a href="#api.draw">drawTextScaled</a></li>
<li><a href="#api.draw">drawVLine</a></li>
<li><a href="#lib.serial.security">DRBG</a></li>
<li><a href="#api.driver">Driver Modules</a></li>
@ -558,6 +559,7 @@ img { max-width: 100%; }
<li><a href="#api.app">dvxAppHungForget</a></li>
<li><a href="#api.app">dvxAppIsHung</a></li>
<li><a href="#api.app">dvxApplyColorScheme</a></li>
<li><a href="#api.platform">dvxArgAppend</a></li>
<li><a href="#api.app">dvxBeep</a></li>
<li><a href="#api.dialog">dvxButtonBox</a></li>
<li><a href="#api.mem">dvxCalloc</a></li>
@ -755,6 +757,7 @@ img { max-width: 100%; }
<li><a href="#shell.lifecycle">Exit DVX</a></li>
<li><a href="#user.start">Exiting DVX</a></li>
<li><a href="#user.help">F1</a></li>
<li><a href="#api.platform">FAT32</a></li>
<li><a href="#shell.assoc">File Associations</a></li>
<li><a href="#arch.dialogs">File Dialog</a></li>
<li><a href="#lib.xfer">File Transfer</a></li>
@ -939,6 +942,7 @@ img { max-width: 100%; }
<li><a href="#widget.listview">ListViewColT</a></li>
<li><a href="#widget.listview">ListViewSortE</a></li>
<li><a href="#user.trouble">Log File</a></li>
<li><a href="#api.platform">Long File Names</a></li>
<li><a href="#lib.dvxnet">lwIP</a></li>
<li><a href="#sdk.packaging">make package</a></li>
<li><a href="#arch.build">Makefile</a></li>
@ -1037,6 +1041,7 @@ img { max-width: 100%; }
<li><a href="#lib.serial.packet">PktStreamT</a></li>
<li><a href="#arch.platform">Platform Layer</a></li>
<li><a href="#api.platform">Platform Layer</a></li>
<li><a href="#api.platform">PLATFORM_LONG_NAME_MAX</a></li>
<li><a href="#api.platform">platformAppExit</a></li>
<li><a href="#api.platform">platformBootDrive</a></li>
<li><a href="#api.platform">platformClock</a></li>
@ -1060,6 +1065,8 @@ img { max-width: 100%; }
<li><a href="#api.platform">platformKeyStateGet</a></li>
<li><a href="#api.platform">platformLockRegion</a></li>
<li><a href="#api.platform">platformLogMemory</a></li>
<li><a href="#api.platform">platformLongNameChar</a></li>
<li><a href="#api.platform">platformLongNames</a></li>
<li><a href="#api.platform">platformMicros</a></li>
<li><a href="#games.timing">platformMicros</a></li>
<li><a href="#api.platform">platformMousePoll</a></li>
@ -1070,9 +1077,11 @@ img { max-width: 100%; }
<li><a href="#api.platform">platformSetAppExitHook</a></li>
<li><a href="#api.platform">platformSetLogMemory</a></li>
<li><a href="#api.platform">platformSetReadOnly</a></li>
<li><a href="#api.platform">platformShortPath</a></li>
<li><a href="#api.platform">platformShutdownHookAdd</a></li>
<li><a href="#api.platform">platformShutdownHookRemove</a></li>
<li><a href="#api.platform">platformSplashNearestColor</a></li>
<li><a href="#api.platform">platformStatSize</a></li>
<li><a href="#api.platform">platformTempDir</a></li>
<li><a href="#api.platform">platformTimerAdd</a></li>
<li><a href="#api.platform">platformTimerAddFast</a></li>
@ -1082,6 +1091,8 @@ img { max-width: 100%; }
<li><a href="#api.platform">platformTimerStats</a></li>
<li><a href="#api.platform">PlatformTimerStatsT</a></li>
<li><a href="#api.platform">platformUnlockRegion</a></li>
<li><a href="#api.platform">platformValidateLongName</a></li>
<li><a href="#api.platform">platformValidateShortName</a></li>
<li><a href="#api.platform">platformVideoInit</a></li>
<li><a href="#lib.audio">PlayTone</a></li>
<li><a href="#lib.audio">PlayWave</a></li>
@ -1245,6 +1256,7 @@ img { max-width: 100%; }
<li><a href="#shell.types">ShellAppT</a></li>
<li><a href="#shell.basic">ShellArg</a></li>
<li><a href="#shell.basic">ShellArgCount</a></li>
<li><a href="#shell.basic">ShellArgQuote</a></li>
<li><a href="#shell.assoc">shellAssocCommand</a></li>
<li><a href="#shell.basic">ShellAssocCommand</a></li>
<li><a href="#shell.assoc">shellAssocCount</a></li>
@ -1504,6 +1516,7 @@ img { max-width: 100%; }
<li><a href="#widget.canvas">wgtCanvasDrawLine</a></li>
<li><a href="#widget.canvas">wgtCanvasDrawRect</a></li>
<li><a href="#widget.canvas">wgtCanvasDrawText</a></li>
<li><a href="#widget.canvas">wgtCanvasDrawTextScaled</a></li>
<li><a href="#widget.canvas">wgtCanvasFillCircle</a></li>
<li><a href="#widget.canvas">wgtCanvasFillRect</a></li>
<li><a href="#widget.canvas">wgtCanvasGetBorderStyle</a></li>
@ -1778,6 +1791,7 @@ img { max-width: 100%; }
<li><a href="#lib.listhelp">widgetPaintPopupList</a></li>
<li><a href="#arch.widgets">Widgets</a></li>
<li><a href="#api.widgetplugin">widgetScrollbarApplyHit</a></li>
<li><a href="#api.widgetplugin">widgetScrollbarNeeds</a></li>
<li><a href="#arch.widgets">WidgetT</a></li>
<li><a href="#api.widget">WidgetT</a></li>
<li><a href="#widget.base">WidgetT</a></li>
@ -3496,6 +3510,18 @@ DVX_ABI_STAMP(mylib);</code></pre>
count Number of characters to render
fg, bg Foreground and background packed colors
opaque true = fill background, false = transparent</pre>
<h2>drawTextScaled</h2>
<pre><code>void drawTextScaled(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, const char *text, int32_t scale, uint32_t fg);</code></pre>
<p>Draw a null-terminated string scale times as large: every glyph pixel becomes a scale x scale block in fg, and the background shows through. For titles and banners in the 8x16 font (DVX Setup's title, the Welcome window). The text is textWidth(font, text) * scale wide and font-&gt;charHeight * scale tall. Each run of set pixels in a glyph row is one rectFill, which clips. Scale 1 is drawText; a scale below 1 draws nothing. BASIC: FontScale on a form or PictureBox (Print, TextWidth, TextHeight).</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
font Bitmap font
x, y Top-left corner
text Null-terminated string
scale Size multiple (1 = normal)
fg Packed text color</pre>
<h2>textWidth</h2>
<pre><code>int32_t textWidth(const BitmapFontT *font, const char *text);</code></pre>
<p>Return the pixel width of a null-terminated string (strlen(text) * charWidth).</p>
@ -5068,10 +5094,10 @@ bool dvxAppIsHung(const AppContextT *ctx, int32_t appId);</code></pre>
void wgtSetPaddingPx(WidgetT *w, int32_t pixels);
int32_t wgtGetSpacingPx(const WidgetT *w);
void wgtSetSpacingPx(WidgetT *w, int32_t pixels);</code></pre>
<p>A container's padding (space inside its edge) and spacing (gap between children) in pixels. The getters return 0 when the size is unset (the container's default) or given in another unit. The setters clamp to 0..WGT_GAP_PIXELS_MAX (0 restores the default) and re-lay out the window. The BASIC Padding and Spacing properties of VBox, HBox, Frame and ScrollPane use these.</p>
<p>A container's padding (space inside its edge) and spacing (gap between children) in pixels. The getters return what the layout uses: the container's default while the field is WGT_GAP_DEFAULT (every widget starts so), and 0 for a size given in another unit. The setters clamp to 0..WGT_GAP_PIXELS_MAX (0 is no gap) and re-lay out the window. The BASIC Padding and Spacing properties of VBox, HBox, Frame and ScrollPane use these.</p>
<h3>wgtLayout</h3>
<pre><code>void wgtLayout(WidgetT *root, int32_t availW, int32_t availH, const BitmapFontT *font);</code></pre>
<p>Execute the full two-pass layout algorithm on a tree at an explicit size. Pass 1 (bottom-up): compute minimum sizes. Pass 2 (top-down): allocate space with weighted distribution; a weighted child capped by maxW/maxH stops at its cap and the space it cannot take goes to the other weighted children. Window-managed trees are laid out by wgtInvalidate and the paint path; this is for laying out a tree on demand.</p>
<p>Execute the full two-pass layout algorithm on a tree at an explicit size. Pass 1 (bottom-up): compute minimum sizes; a cap (maxW/maxH) wins over a larger minimum, so a widget whose content asks for more than its cap is given its cap and the rest of the space goes to its siblings. Pass 2 (top-down): allocate space with weighted distribution; a weighted child capped by maxW/maxH stops at its cap and the space it cannot take goes to the other weighted children. Window-managed trees are laid out by wgtInvalidate and the paint path; this is for laying out a tree on demand.</p>
<pre> Parameter Description
--------- -----------
root Root widget
@ -5300,6 +5326,7 @@ static const ButtonApiT sApi = {
WGT_SIZE_PIXELS 0x00000000 Unit tag: pixels
WGT_SIZE_CHARS 0x40000000 Unit tag: character widths
WGT_SIZE_PERCENT 0x80000000 Unit tag: percentage of parent
WGT_GAP_DEFAULT 0xC0000000 padding / spacing: the container's own default (wgtPixels(0) is no gap)
WGT_WEIGHT_FILL 100 Default &quot;flexible&quot; weight value</pre>
<h2>Widget Interface Descriptors</h2>
<h3>WgtPropDescT</h3>
@ -6069,6 +6096,9 @@ VALIDATE_WIDGET_VOID(w, wtype); // returns void on mismatch</code></pre>
<h3>widgetScrollbarThumbDragScroll</h3>
<pre><code>int32_t widgetScrollbarThumbDragScroll(int32_t trackLen, int32_t total, int32_t visible, int32_t relMouse, int32_t maxScroll);</code></pre>
<p>Map a dragged thumb position to a scroll position in [0, maxScroll]. relMouse is where the thumb's leading edge should be, relative to the start of a track of trackLen pixels (the mouse position minus the grab offset). Returns 0 when maxScroll &lt;= 0.</p>
<h3>widgetScrollbarNeeds</h3>
<pre><code>void widgetScrollbarNeeds(int32_t totalW, int32_t totalH, int32_t *innerW, int32_t *innerH, bool *needV, bool *needH);</code></pre>
<p>Which scrollbars content totalW x totalH pixels needs in a viewport of *innerW x *innerH (the area inside the widget's border). A vertical bar narrows the viewport, which may make the content too wide; a horizontal bar shortens it, which may make the content too tall; both cases are followed through. *innerW and *innerH come back less the bars (WGT_SB_W each). For rows of a fixed height pass rows * height: the content is too tall exactly when there are more rows than whole rows fit. ListBox, ListView, TreeView, ScrollPane and DBGrid decide their bars with it; BASIC's ScrollBarsNeeded is the same rule.</p>
<h2>Layout Functions</h2>
<h3>widgetCalcMinSizeBox / widgetCalcMinSizeTree</h3>
<pre><code>void widgetCalcMinSizeBox(WidgetT *w, const BitmapFontT *font);
@ -6282,8 +6312,24 @@ void platformInjectScan(uint8_t scan);</code></pre>
<p>Query total and free physical memory.</p>
<h2>File System</h2>
<h3>platformValidateFilename</h3>
<pre><code>const char *platformValidateFilename(const char *name);</code></pre>
<p>Validate a filename against platform-specific rules (8.3 on DOS). Returns NULL if valid, or a human-readable error string.</p>
<pre><code>const char *platformValidateFilename(const char *dir, const char *name);</code></pre>
<p>Validate a name for a new file or folder in folder dir (NULL or &quot;&quot; for the current one) against the rules of its disk. On DOS: platformValidateLongName where platformLongNames(dir), else platformValidateShortName, and dir with the name must stay under DVX_MAX_PATH. The host backend refuses an empty name, . and .., separators and control characters, and ignores dir. Returns NULL if valid, or a human-readable error string. The file dialog, the File Manager (fileOpsValidateName) and the IDE's project rename all use it.</p>
<h3>Long file names: platformLongNames / platformValidateLongName / platformValidateShortName / platformLongNameChar / platformShortPath</h3>
<pre><code>#define PLATFORM_LONG_NAME_MAX 255
bool platformLongNames(const char *path);
const char *platformValidateLongName(const char *name);
const char *platformValidateShortName(const char *name);
bool platformLongNameChar(char c);
bool platformShortPath(const char *path, char *out, int32_t outSize);</code></pre>
<p>The DOS C library uses the long-name calls (INT 21h 71xxh) by itself whenever a driver provides them (Windows, DOSLFN), so open, fopen, rename, mkdir, stat and the directory readers all take and return long names; these functions cover what the C library does not.</p>
<p>platformLongNames is true when the drive holding path (NULL or &quot;&quot;: the current drive) takes long file names. On DOS that is a loaded long-name driver covering that drive; elsewhere always.</p>
<p>platformValidateLongName and platformValidateShortName are the two DOS name rules by themselves, whatever the disk takes; each returns NULL or why the name is not valid. A long name has 1 to PLATFORM_LONG_NAME_MAX characters and may hold spaces, several dots and + , ; = [ ]; it may not hold a control character or \ / : * ? &quot; &lt; &gt; |, and may not end with a dot or a space (DOS drops them). An 8.3 name has 1 to 8 printable ASCII characters, then at most one dot and up to 3 more, none of them a space or &quot; * + , / : ; &lt; = &gt; ? [ \ ] |. Neither may be . or .., or a device name (CON, PRN, AUX, NUL, CLOCK$, COM1 to COM9, LPT1 to LPT9) before its first dot. They are shared code, so the host tests check the DOS rules too.</p>
<p>platformLongNameChar is true when a long name may hold character c; a file transfer uses it to turn the characters a sender's name cannot keep into _.</p>
<p>platformShortPath writes the short (8.3) form of an existing path into out, for what reads names before a long-name driver loads (AUTOEXEC.BAT) or cannot take blanks (an old program's command line). On a drive with long names DOS gives every part's short name (INT 21h AX=7160h CL=1); elsewhere, and when DOS cannot, path itself is copied. False when out is too small.</p>
<h3>platformStatSize</h3>
<pre><code>uint64_t platformStatSize(const struct stat *st);</code></pre>
<p>The size stat reported for a file. A FAT32 file reaches 4 GB - 1 byte, but the DOS C library's st_size is a signed 32-bit off_t, so a file past 2 GB reads as negative there; platformStatSize reads it as the unsigned 32-bit size DOS keeps. Use it wherever a file size comes from stat or fstat.</p>
<h3>platformMkdirRecursive</h3>
<pre><code>int32_t platformMkdirRecursive(const char *path);</code></pre>
<p>Create a directory and all parent directories (like mkdir -p). Existing directories are not an error. Returns 0 on success, -1 on failure (including a path of DVX_MAX_PATH characters or more).</p>
@ -6341,7 +6387,7 @@ int32_t platformDriveList(PlatformDriveT *out, int32_t max);
bool platformDiskSpace(const char *path, uint64_t *totalBytes, uint64_t *freeBytes);
char platformBootDrive(void);</code></pre>
<p>platformDriveList fills out[] with the drives that exist, in letter order, and returns the count. On DOS it uses IOCTL calls only (INT 21h AX=4409h remote, 440Eh logical drive map, 4408h removable), never the media, so empty floppy and CD-ROM drives are listed at once; the second letter of a shared floppy drive (B: on a one-floppy system) is left out because using it makes DOS ask for a disk swap. The host backend reports one drive, &quot;/&quot;. System Information and the file operations library both use it.</p>
<p>platformDiskSpace reports the size and free space of the disk holding path (DOS: INT 21h AH=36h on the path's drive letter, or the current drive; host: statvfs of the nearest existing folder of path, so a folder about to be created reports its disk). False when unknown.</p>
<p>platformDiskSpace reports the size and free space of the disk holding path (DOS: INT 21h AX=7303h, the FAT32 call that counts past 2 GB, on the root of the path's drive letter or the current drive, falling back to AH=36h, which tops out near 2 GB, where DOS does not have it; host: statvfs of the nearest existing folder of path, so a folder about to be created reports its disk). False when unknown.</p>
<p>platformBootDrive returns the letter of the drive DOS started from (INT 21h AX=3305h, DOS 4.0+), whose root holds AUTOEXEC.BAT, or 0 where there is none (older DOS, and every platform but DOS).</p>
<h3>Read-only media: platformSetReadOnly / platformIsReadOnly / platformDirIsWritable / platformTempDir / platformSetLogMemory / platformLogMemory</h3>
<pre><code>#define PLATFORM_LOG_MEM_MAX 16384
@ -6379,6 +6425,9 @@ char arg[DVX_MAX_PATH];
while ((p = dvxNextArg(p, arg, sizeof(arg), &amp;quoted)) != NULL) {
// use arg
}</code></pre>
<h3>dvxArgAppend</h3>
<pre><code>int32_t dvxArgAppend(char *buf, int32_t bufSize, int32_t pos, const char *arg);</code></pre>
<p>Append arg to the command line in buf at pos as one argument that dvxNextArg reads back whole: in double quotes when it holds a blank or a tab (a long name such as C:\My Programs\Thing.app), as it is otherwise. Returns the new length, or -1 when it does not fit (as dvxStrAppendf). The shell's file-type associations and F1 help build their command lines with it; BASIC programs have ShellArgQuote$.</p>
<h2>DXE Module Support</h2>
<h3>platformRegisterDxeExports</h3>
<pre><code>void platformRegisterDxeExports(void);</code></pre>
@ -6749,6 +6798,7 @@ BasValueT basValToBool(BasValueT v);</code></pre>
BAS_VM_CALL_STACK_SIZE 64 Maximum call nesting depth.
BAS_VM_MAX_GLOBALS 512 Global variable slots.
BAS_VM_MAX_LOCALS 64 Local variables per stack frame.
BAS_VM_MAX_MEMBER_VARS 65536 Member variables per class object; variables per form (their opcodes' 16-bit index).
BAS_VM_MAX_FOR_DEPTH 32 Maximum nested FOR loop depth.
BAS_VM_MAX_FILES 16 Open file channels (1-based).</pre>
<h2>BasVmResultE</h2>
@ -7721,7 +7771,7 @@ bool shellAssocGet(int32_t index, char *extension, int32_t extensionSize, cha
<h2>Opening a Document</h2>
<pre><code>bool shellAssocCommand(const char *documentPath, char *program, int32_t programSize, char *args, int32_t argsSize);
bool shellAssocOpenDocument(AppContextT *ctx, const char *documentPath);</code></pre>
<p>shellAssocCommand builds the program and argument string that open a document: the value is split at the first comma, every %1 in the arguments becomes documentPath, and without arguments documentPath alone is passed (in double quotes when it contains a blank, so dvxNextArg and COMMAND$(1) still return it whole). A program that opens documents takes the first argument of its DxeAppContextT.args (dvxNextArg) as the file to open when it starts; a BASIC program uses COMMAND$(1). shellAssocOpenDocument does that and starts the program; false when there is no association or the program does not start. It shows nothing to the user (shellRunProgram does, for a document it cannot open).</p>
<p>shellAssocCommand builds the program and argument string that open a document: the value is split at the first comma, every %1 in the arguments becomes documentPath, and without arguments documentPath alone is passed. The path goes in double quotes when it contains a blank (dvxArgAppend), so dvxNextArg and COMMAND$(1) still return a long name such as C:\My Documents\Letter.txt whole; a template that already quotes the token (&quot;%1&quot;) gets the path as it is. A program that opens documents takes the first argument of its DxeAppContextT.args (dvxNextArg) as the file to open when it starts; a BASIC program uses COMMAND$(1). shellAssocOpenDocument does that and starts the program; false when there is no association or the program does not start. It shows nothing to the user (shellRunProgram does, for a document it cannot open).</p>
<h2>Changing</h2>
<pre><code>bool shellAssocSet(const char *extension, const char *programPath);
bool shellAssocRemove(const char *extension);
@ -7781,10 +7831,11 @@ int32_t ShellAppMemory(int32_t appId);</code></pre>
const char *ShellCommandArgs(const char *command);
int32_t ShellArgCount(const char *command);
const char *ShellArg(const char *command, int32_t index);
const char *ShellArgQuote(const char *arg);
int32_t ShellAppId(void);
int32_t ShellPriority(void);
int32_t ShellSetPriority(int32_t priority);</code></pre>
<p>ShellCommandProgram and ShellCommandArgs are the two parts of shellSplitCommand (what shellRunCommand runs). ShellArgCount and ShellArg walk a command line with dvxNextArg -- the tokenizer shellSplitCommand and COMMAND$(n) use -- counting the program as argument 0; ShellArg drops the quotes and gives &quot;&quot; past the last. ShellAppId is ctx-&gt;currentAppId. ShellPriority and ShellSetPriority are tsGetPriority / tsSetPriority on the running program's mainTaskId (TS_PRIORITY_LOW .. TS_PRIORITY_HIGH, shell.bas SHELL_PRIORITY_*); -1 / False for a program without a task of its own (every BASIC program has one) or a priority out of range.</p>
<p>ShellCommandProgram and ShellCommandArgs are the two parts of shellSplitCommand (what shellRunCommand runs). ShellArgCount and ShellArg walk a command line with dvxNextArg -- the tokenizer shellSplitCommand and COMMAND$(n) use -- counting the program as argument 0; ShellArg drops the quotes and gives &quot;&quot; past the last. ShellArgQuote is the other direction (dvxArgAppend): arg as one word of a command line, in double quotes when it holds blanks, &quot;&quot; when it is too long for one (SHELL_ARGS_MAX). ShellAppId is ctx-&gt;currentAppId. ShellPriority and ShellSetPriority are tsGetPriority / tsSetPriority on the running program's mainTaskId (TS_PRIORITY_LOW .. TS_PRIORITY_HIGH, shell.bas SHELL_PRIORITY_*); -1 / False for a program without a task of its own (every BASIC program has one) or a priority out of range.</p>
<h2>Hotkeys</h2>
<pre><code>int32_t HotkeyAdd(const char *keyText);
int32_t HotkeyNext(void);
@ -8133,6 +8184,8 @@ dvxSqlExec(db, sql);</code></pre>
<p>Loaded as: bin/libs/kpunch/fileops/fileops.lib</p>
<h2>DOS Disk Errors</h2>
<p>On DOS, touching a drive with no disk (or a write-protected or removed one) raises a critical error, which would normally wait at an &quot;Abort, Retry, Fail&quot; prompt on the hidden text screen. DVX installs a critical-error handler at startup (platformInit) that answers Fail, so every call here, and your own disk code, simply gets an error (errno) instead. platformDriveList never touches the media at all (IOCTL calls only), so listing drives costs nothing even with empty drives.</p>
<h2>Big Disks and Long File Names</h2>
<p>Disks past 2 GB report their real size and free space: platformDiskSpace asks DOS with the FAT32 call first and falls back to the older one, which stops near 2 GB. File sizes are 64-bit (FileOpsEntryT.size, fileOpsTreeSize, the job byte counts); a FAT32 file reaches 4 GB - 1 byte, and platformStatSize reads it correctly where stat's st_size would be negative. Where a long-name driver is running (Windows, DOSLFN) and covers the drive (platformLongNames), listings show long names, jobs copy and move them, attributes and renames work on them, fileOpsValidateName accepts them and fileOpsPathNormalize keeps their case; elsewhere the 8.3 rules apply.</p>
<h2>Attributes and Dates</h2>
<pre> Function Description
-------- -----------
@ -8152,13 +8205,13 @@ dvxSqlExec(db, sql);</code></pre>
fileOpsTreeSize(path, &amp;bytes, &amp;files, &amp;folders) Total size of a file or of a folder and everything in it.
fileOpsMakeDir(dir, name, err, errSize) Create a folder; a reason in err on failure.
fileOpsRename(dir, oldName, newName, err, errSize) Rename within a folder; refuses a name already in use.
fileOpsValidateName(name, err, errSize) Check a new name (8.3 rules and device names on DOS).
fileOpsValidateName(dir, name, err, errSize) Check a new name for folder dir by the rules of its disk (platformValidateFilename): on DOS long names where the drive takes them (platformLongNames), else 8.3; never a device name.
fileOpsPathJoin(out, size, dir, name) dir + separator + name; false when it does not fit.
fileOpsPathParent(path, out, size) Parent folder; false at a root.
fileOpsPathIsRoot(path) True for &quot;C:\&quot;, &quot;C:&quot; or &quot;/&quot;.
fileOpsPathIsInside(path, dir) True when path is dir or below it.
fileOpsPathSame(a, b) Same place (separators equal, DOS ignores case, a trailing separator ignored).
fileOpsPathNormalize(path, out, size) Canonical absolute form of an existing folder.</pre>
fileOpsPathNormalize(path, out, size) Canonical absolute form of an existing folder (DOS: upper case, except names on a disk with long names, which keep their case).</pre>
<h2>Jobs</h2>
<p>A job copies, moves or deletes any number of files and folders (recursively):</p>
<pre><code>FileOpsJobT *job = fileOpsJobCreate(FileOpsCopyE, &quot;C:\\BACKUP&quot;);
@ -8204,7 +8257,7 @@ fileOpsJobFree(job);</code></pre>
<p>fileOpsJobClearAttr(job, attr), called before the first step, clears those attribute bits on every file a copy or move writes: Setup passes FILEOPS_ATTR_READONLY, because every file on a CD-ROM is read-only and the installed copies must not be.</p>
<p>fileOpsJobRun(job, callbacks) runs a job to the end instead: progress(job, ctx) is called after every step (return false to cancel) and ask(job, kind, message, ctx) answers questions. With no callbacks, existing files are kept (No) and failing items are skipped.</p>
<h2>BASIC</h2>
<p>src/include/basic/fileops.bas declares the BASIC functions (fileOpsBas.c): whole trees at once (FileOpsCopyTree, FileOpsMoveTree, FileOpsDeleteTree), drives and disks (FileOpsDriveList$, FileOpsDriveType (the PlatformDriveTypeE of platformDriveList, CONSTs FILEOPS_DRIVE_*; -1 for no such drive), FileOpsBootDrive$ (platformBootDrive, &quot;&quot; when none), FileOpsFreeKb, FileOpsFreeBytes and FileOpsTotalBytes (platformDiskSpace), FileOpsIsWritable (platformDirIsWritable), FileOpsReadOnlySystem (platformIsReadOnly), FileOpsTempDir$ (platformTempDir, &quot;&quot; when none)), folder listings (FileOpsList, FileOpsListCount, FileOpsListSort, FileOpsListFind, FileOpsListName$, FileOpsListIsFolder, FileOpsListSize, FileOpsListRows$, FileOpsListFree), paths and names (FileOpsPathNormalize$, FileOpsPathParent$, FileOpsPathJoin$, FileOpsPathSame, FileOpsPathIsRoot, FileOpsPathIsAbsolute (platformPathIsAbsolute), FileOpsPathIsInside, FileOpsPathSep$ (DVX_PATH_SEP), FileOpsFilterMatch (platformFilterMatch), FileOpsBaseName$, FileOpsExtension$), files and folders (FileOpsMakeDir, FileOpsMakePath (platformMkdirRecursive), FileOpsRename, FileOpsError$, FileOpsTempPath$ and FileOpsReplaceFile (an atomic save: platformPathSibling + platformReplaceFile), FileOpsValidName (platformValidateFilename), FileOpsIsFolder, FileOpsGetAttr, FileOpsSetAttr, FileOpsModified$, FileOpsSetModified (fileOpsParseDate + fileOpsSetTime), FileOpsTreeSize with FileOpsTreeBytes / FileOpsTreeFiles / FileOpsTreeFolders, FileOpsFormatSize$) and jobs (FileOpsJobCreate, FileOpsJobAddSource, FileOpsJobClearAttr (masked to FILEOPS_ATTR_EDITABLE), FileOpsJobRunFor, FileOpsJobMessage$, FileOpsJobAnswer, FileOpsJobCancel, FileOpsJobCurrent$, FileOpsJobFilesDone, FileOpsJobFilesTotal, FileOpsJobPercent, FileOpsJobBytesDone, FileOpsJobBytesTotal (FileOpsProgressT; byte counts are DOUBLE), FileOpsJobFree). The fileops.bas CONSTs mirror fileOps.h and dvxPlat.h; the basdev test suite (caseIncludeConsts) checks each against its C value.</p>
<p>src/include/basic/fileops.bas declares the BASIC functions (fileOpsBas.c): whole trees at once (FileOpsCopyTree, FileOpsMoveTree, FileOpsDeleteTree), drives and disks (FileOpsDriveList$, FileOpsDriveType (the PlatformDriveTypeE of platformDriveList, CONSTs FILEOPS_DRIVE_*; -1 for no such drive), FileOpsBootDrive$ (platformBootDrive, &quot;&quot; when none), FileOpsFreeKb, FileOpsFreeBytes and FileOpsTotalBytes (platformDiskSpace), FileOpsIsWritable (platformDirIsWritable), FileOpsReadOnlySystem (platformIsReadOnly), FileOpsTempDir$ (platformTempDir, &quot;&quot; when none)), folder listings (FileOpsList, FileOpsListCount, FileOpsListSort, FileOpsListFind, FileOpsListName$, FileOpsListIsFolder, FileOpsListSize, FileOpsListRows$, FileOpsListFree), paths and names (FileOpsPathNormalize$, FileOpsPathParent$, FileOpsPathJoin$, FileOpsPathSame, FileOpsPathIsRoot, FileOpsPathIsAbsolute (platformPathIsAbsolute), FileOpsPathIsInside, FileOpsPathSep$ (DVX_PATH_SEP), FileOpsFilterMatch (platformFilterMatch), FileOpsBaseName$, FileOpsExtension$), files and folders (FileOpsMakeDir, FileOpsMakePath (platformMkdirRecursive), FileOpsRename, FileOpsError$, FileOpsTempPath$ and FileOpsReplaceFile (an atomic save: platformPathSibling + platformReplaceFile), FileOpsValidName (platformValidateFilename for a name in a folder), FileOpsValidLongName and FileOpsValidShortName (platformValidateLongName / platformValidateShortName, the rules alone), FileOpsLongNames (platformLongNames), FileOpsShortPath$ (platformShortPath, &quot;&quot; when it does not fit), FileOpsIsFolder, FileOpsGetAttr, FileOpsSetAttr, FileOpsModified$, FileOpsSetModified (fileOpsParseDate + fileOpsSetTime), FileOpsTreeSize with FileOpsTreeBytes / FileOpsTreeFiles / FileOpsTreeFolders, FileOpsFormatSize$) and jobs (FileOpsJobCreate, FileOpsJobAddSource, FileOpsJobClearAttr (masked to FILEOPS_ATTR_EDITABLE), FileOpsJobRunFor, FileOpsJobMessage$, FileOpsJobAnswer, FileOpsJobCancel, FileOpsJobCurrent$, FileOpsJobFilesDone, FileOpsJobFilesTotal, FileOpsJobPercent, FileOpsJobBytesDone, FileOpsJobBytesTotal (FileOpsProgressT; byte counts are DOUBLE), FileOpsJobFree). The fileops.bas CONSTs mirror fileOps.h and dvxPlat.h; the basdev test suite (caseIncludeConsts) checks each against its C value.</p>
<p>Listings and jobs are handles (small numbers, 0 = none) into a table owned by the library; each records the app that made it, and the shell's app-cleanup hook frees what an app leaves open when it ends. FileOpsJobRunFor(job, ms) steps the job until the time is used or it needs an answer, so a BASIC Timer can run it without blocking the program. A returned string stays valid until the next call returning one (the BASIC runtime copies it at once). Single files are handled by the built-in FILECOPY, KILL, NAME, MKDIR, RMDIR, GETATTR and SETATTR statements.</p>
</div>
<div class="topic" id="lib.game">
@ -10326,14 +10379,14 @@ if (xferPoll(x, nowMs()) != XferRunningE) {
XferT *xferCreate(void) Allocate an idle transfer (NULL when out of memory).
void xferDestroy(x) Close any open file and free the transfer.
void xferOptionsDefaults(opt) Ask when a file exists, no window limit, no extra escaping, no resume request.
bool xferStartSend(x, proto, io, opt, paths, count, now) Send count files (XMODEM sends the first). False, with the reason in the message, when a file cannot be opened. opt may be NULL.
bool xferStartSend(x, proto, io, opt, paths, count, now) Send count files (XMODEM sends the first). False, with the reason in the message, when a file cannot be opened or is larger than 2 GB. opt may be NULL.
bool xferStartReceive(x, proto, io, opt, target, now) XMODEM: target is the file to create. YMODEM and ZMODEM: target is the folder for the files.
XferStatusE xferPoll(x, now) Move the transfer along. now is a millisecond clock (wrapping is fine).
void xferCancel(x) Send the cancel sequence to the other side and end with XferCancelledE.
void xferAnswer(x, action, now) Answer XferAskingE: XferExistResumeE, RenameE, OverwriteE or SkipE.
const XferProgressT *xferProgress(x) Progress and outcome.
bool xferDetectFeed(d, byte) Feed received terminal bytes; true when a ZMODEM sender's start frame (ZRQINIT) has arrived, so a terminal can start a ZMODEM receive by itself.
void xferSafeName(name, out) Reduce a sender's file name to a safe 8.3 name: no path, no drive, no DOS device name (CON, PRN, COM1 and so on get a leading _), only portable characters. out holds XFER_NAME_MAX bytes.
void xferSafeName(name, longNames, out) Reduce a sender's file name to a safe one: no path, no drive, no DOS device name (CON, PRN, COM1 and so on get a leading _). With longNames (the receiving disk takes long names, platformLongNames) a long name keeping its case, blanks and dots, where a character a long name cannot hold becomes _ and leading blanks and trailing dots and blanks go (RECEIVED when nothing is left); otherwise an 8.3 name of portable characters in upper case. out holds XFER_NAME_MAX bytes (PLATFORM_LONG_NAME_MAX + 1).
uint16_t xferCrc16(data, len) CRC-16/XMODEM (polynomial 0x1021).
uint32_t xferCrc32(data, len) CRC-32 (IEEE 802.3), as ZMODEM uses it.
int32_t xferBasNew(&amp;x) For the BASIC functions of other libraries: a new xfer.bas handle owning a new idle transfer (in x) that belongs to the running program; 0 when no handle is free. The library starts the transfer over its own transport; the program follows it with the Xfer functions (the connection library's ConnSendFiles and ConnReceiveFiles work this way).
@ -10346,11 +10399,12 @@ if (xferPoll(x, nowMs()) != XferRunningE) {
<h2>XMODEM and XMODEM-1K</h2>
<p>Packets are SOH (128 bytes) or STX (1024 bytes), the block number and its complement, the data, and a CRC-16 or a one-byte checksum. The receiver asks for CRC mode with 'C' every 3 seconds and falls back to checksums (NAK) after three tries, unless the sender has already started. Every packet is answered with ACK or NAK; two CANs cancel. After 10 failed tries of one packet the transfer gives up and cancels the other side. A damaged packet is refused only once the line has been quiet for a second, so the rest of it cannot be mistaken for the next packet. An EOT counts only when the line stays quiet after it (a stray 0x04 inside a damaged packet does not end the file early). A sender whose 1K block fails three times sends that block and the rest of the file in 128-byte blocks. XMODEM pads the last block with 0x1A (SUB); the receiver keeps the padding because the protocol does not carry the file size.</p>
<h2>YMODEM</h2>
<p>A batch of files, always with CRC and 1K blocks (a tail of at most 128 bytes goes in a 128-byte block). Block 0 carries the file name and size before each file, and an empty block 0 ends the batch. The receiver refuses the first EOT of each file and accepts the second, and cuts the padding using the size.</p>
<p>A batch of files, always with CRC and 1K blocks (a tail of at most 128 bytes goes in a 128-byte block). Block 0 carries the file name and size before each file (the long name when it fits in the 128-byte block beside the other fields, else the 8.3 name), and an empty block 0 ends the batch. The receiver refuses the first EOT of each file and accepts the second, and cuts the padding using the size.</p>
<h2>ZMODEM</h2>
<p>Headers are sent in hex (to start and answer) or binary with CRC-16 or CRC-32; data travels in subpackets with a CRC over the data and the frame end. ZDLE escaping protects ZDLE, DLE, XON and XOFF (with and without the high bit) and a CR after '@'; with escapeCtl every control character is escaped (the sender announces it with ZSINIT; the receiver asks for it in ZRINIT). Five CANs in a row cancel.</p>
<p>The sender streams: it keeps at most 8 KB unacknowledged, asks for a progress acknowledgement every 4 KB, honours the receiver's buffer size (a receiver without flow control should set rxWindow to what its hardware buffer holds, so a slow frame never loses data), and builds a subpacket only when the transport has sent nearly everything it was given (XferIoT.pending). On an error the receiver sends ZRPOS with the last good position; the sender goes back there and halves its subpacket size (down to 64 bytes), then doubles it again after eight clean subpackets. A sender that gets no acknowledgement for the window goes back to the last acknowledged position. File names travel in the ZFILE subpacket with the size and the files and bytes left in the batch, which the receiver shows as batch progress. Commands from the other side (ZCOMMAND) are never run.</p>
<p>Interoperability: the engines are tested against lrz and lsz (lrzsz 0.12.20) in both directions for every protocol, including escaping and resume.</p>
<p>The sender streams: it keeps at most 8 KB unacknowledged, asks for a progress acknowledgement every 4 KB, honours the receiver's buffer size (a receiver without flow control should set rxWindow to what its hardware buffer holds, so a slow frame never loses data), and builds a subpacket only when the transport has sent nearly everything it was given (XferIoT.pending). On an error the receiver sends ZRPOS with the last good position; the sender goes back there and halves its subpacket size (down to 64 bytes), then doubles it again after eight clean subpackets. A sender that gets no acknowledgement for the window goes back to the last acknowledged position. File names (long names as they are) travel in the ZFILE subpacket with the size and the files and bytes left in the batch, which the receiver shows as batch progress. Commands from the other side (ZCOMMAND) are never run.</p>
<p>Files are at most 2 GB (sizes and positions are 32-bit): a send refuses a larger file, a size offered past 2 GB reads as unknown, and a receive that passes 2 GB stops with &quot;A file larger than 2 GB cannot be transferred&quot;. A file already on the disk is never mistaken for a missing one, whatever its size.</p>
<p>Interoperability: the engines are tested against lrz and lsz (lrzsz 0.12.20) in both directions for every protocol, including escaping, resume and long file names.</p>
</div>
<div class="topic" id="lib.xfer.basic">
<h1>File Transfers from BASIC</h1>
@ -10375,7 +10429,7 @@ if (xferPoll(x, nowMs()) != XferRunningE) {
XferCancel handle Stop a running transfer (the other side is told).
XferClose handle Free the handle.
XferCrc16(bytes), XferCrc32(bytes) xferCrc16 / xferCrc32 of a BINARY STRING (every byte value counts); the CRC-32 as a LONG (negative when its top bit is set).
XferSafeName$(fileName) xferSafeName: the 8.3 name a receive stores a sender's file name as.</pre>
XferSafeName$(fileName, folder) xferSafeName: the name a receive into folder stores a sender's file name as (a long name where folder's disk takes them, else 8.3).</pre>
<p>XFER_WINDOW_MAX (xfer.bas) is the largest ZMODEM receive window conn.bas's ConnSetXferWindow takes.</p>
<p>Protocols: XFER_XMODEM, XFER_XMODEM1K, XFER_YMODEM, XFER_ZMODEM. At most eight transfers run at once (XFER_MAX_FILES files in one batch).</p>
<pre><code>Dim h As Long
@ -10409,8 +10463,8 @@ End Sub</code></pre>
prefW, prefH int32_t (tagged) Preferred size. 0 = auto.
weight int32_t Extra-space distribution weight. 0 = fixed, 100 = normal. A widget with weight=200 gets twice the extra space of one with weight=100.
align WidgetAlignE Main-axis alignment for children: AlignStartE, AlignCenterE, AlignEndE.
spacing int32_t (tagged) Spacing between children (containers only). 0 = default.
padding int32_t (tagged) Internal padding (containers only). 0 = default.
spacing int32_t (tagged) Spacing between children (containers only). WGT_GAP_DEFAULT = the class's default; 0 = none.
padding int32_t (tagged) Internal padding (containers only). WGT_GAP_DEFAULT = the class's default; 0 = none.
fgColor uint32_t Foreground color override. 0 = use color scheme default.
bgColor uint32_t Background color override. 0 = use color scheme default.
visible bool Visibility state.
@ -10570,8 +10624,8 @@ WidgetT *group = wgtFrame(parent, &quot;Options&quot;);</code></pre>
<pre> Field Description
----- -----------
align Main-axis alignment of children. HBox: Start=left, Center=center, End=right. VBox: Start=top, Center=center, End=bottom.
spacing Gap between children (tagged size). Default 4 pixels for VBox/HBox, 0 for Frame.
padding Internal padding around children (tagged size). Default 4 pixels.
spacing Gap between children (tagged size). WGT_GAP_DEFAULT (the default): 4 pixels for VBox/HBox, 0 for Frame; wgtPixels(0) is none.
padding Internal padding around children (tagged size). WGT_GAP_DEFAULT (the default): 4 pixels; wgtPixels(0) is none.
weight Controls how the box itself stretches within its parent.</pre>
<p>Frame text is managed via the standard wgtSetText() / wgtGetText() interface (the widget has WCLASS_HAS_TEXT). BASIC code can set its title via the generic &quot;Caption&quot; or &quot;Text&quot; property.</p>
<h3>Events</h3>
@ -10629,6 +10683,7 @@ btn-&gt;onClick = onOkClicked;</code></pre>
void wgtCanvasSetPixel(w, x, y, color) Set a single pixel to the given packed color.
uint32_t wgtCanvasGetPixel(w, x, y) Read a single pixel. Returns packed color.
void wgtCanvasDrawText(w, x, y, text) Draw text at the given canvas coordinates using the current pen color.
void wgtCanvasDrawTextScaled(w, x, y, text, scale) Draw text scale times as large (each font pixel a scale x scale block) in the pen color: titles. Scale 1 is wgtCanvasDrawText. BASIC: FontScale and Print on a PictureBox.
void wgtCanvasSetMouseCallback(w, cb) Set a mouse callback. Signature: void (*cb)(WidgetT *w, int32_t cx, int32_t cy, bool drag). cx/cy are canvas-relative, drag=true on mouse-move during press.
int32_t wgtCanvasSave(w, path) Save the canvas buffer to an image file: BMP when path ends in .bmp, PNG otherwise. Returns 0 on success, -1 on error.
int32_t wgtCanvasLoad(w, path) Load an image file into the canvas (resizes buffer to match). Returns 0 on success, -1 on error.
@ -10657,7 +10712,8 @@ btn-&gt;onClick = onOkClicked;</code></pre>
resize wgtCanvasResize
setBorderStyle wgtCanvasSetBorderStyle
getBorderStyle wgtCanvasGetBorderStyle
getDisplay wgtCanvasGetDisplay</pre>
getDisplay wgtCanvasGetDisplay
drawTextScaled wgtCanvasDrawTextScaled</pre>
<h3>Properties</h3>
<p>Drawing state (pen color, pen size) is managed by the API functions above. The BASIC interface registers these properties:</p>
<pre> Property Type Access Description
@ -11114,7 +11170,7 @@ btn-&gt;onClick = onSaveClicked;</code></pre>
</div>
<div class="topic" id="widget.listbox">
<h2>ListBox</h2>
<p>A scrollable list of text items. Supports single and multi-select modes (Shift-click for range, Ctrl-click to toggle), drag-to-reorder, mouse wheel scroll, and keyboard navigation (Up/Down/PgUp/PgDn/Home/End with type-ahead search on printable keys). Depends on the &quot;listhelp&quot; helper library (declared in listbox.dep).</p>
<p>A scrollable list of text items. Supports single and multi-select modes (Shift-click for range, Ctrl-click to toggle), drag-to-reorder, mouse wheel scroll, and keyboard navigation (Up/Down/PgUp/PgDn/Home/End with type-ahead search on printable keys). A horizontal scrollbar appears when the box is laid out narrower than its widest item (a maxW below it); it and Left/Right scroll a character at a time. The bars follow widgetScrollbarNeeds. Depends on the &quot;listhelp&quot; helper library (declared in listbox.dep).</p>
<p>Items can be set from a caller-owned array (wgtListBoxSetItems, which keeps a pointer to it) or managed with AddItem/RemoveItem/Clear. AddItem and RemoveItem on a list set from an array first copy that array, so they extend or shorten the caller's list without modifying it; drag-to-reorder also works on the copy.</p>
<p>Header: widgets/listBox.h</p>
<h3>Creation</h3>
@ -11366,7 +11422,7 @@ WidgetT *content = wgtVBox(sp);
void wgtScrollPaneSetScrollTop(w, pos) Set the vertical scroll position; the layout clamps it to the content.
int32_t wgtScrollPaneGetScrollLeft(w) Horizontal scroll position in pixels.
void wgtScrollPaneSetScrollLeft(w, pos) Set the horizontal scroll position; the layout clamps it to the content.</pre>
<p>Padding and spacing are the common WidgetT padding / spacing fields (unset = none); wgtSetPaddingPx / wgtSetSpacingPx set them in pixels.</p>
<p>Padding and spacing are the common WidgetT padding / spacing fields (WGT_GAP_DEFAULT, the default, is none); wgtSetPaddingPx / wgtSetSpacingPx set them in pixels.</p>
<p>When the user moves the scroll position (scrollbar arrows and trough, dragging a thumb, the arrow, page, Home and End keys) the scroll pane fires onChange (widgetFireChange) after the position is clamped; the setters, wgtScrollPaneScrollToTop and scrolling a focused child into view do not. BASIC sees it as the ScrollPane's Change event.</p>
<h3>API Struct (wgtRegisterApi &quot;scrollpane&quot;)</h3>
<pre> Slot Function
@ -11888,8 +11944,8 @@ wgtButton(wrap, &quot;Tag 3&quot;);</code></pre>
<p>WrapBox uses the common WidgetT container fields for layout control:</p>
<pre> Property Description
-------- -----------
spacing Gap between children in both the horizontal and vertical directions (tagged size). Default is 4 pixels.
padding Internal padding around children (tagged size). Default is 2 pixels.</pre>
spacing Gap between children in both the horizontal and vertical directions (tagged size). Default is 4 pixels; wgtPixels(0) is none.
padding Internal padding around children (tagged size). Default is 2 pixels; wgtPixels(0) is none.</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------

View file

@ -230,9 +230,10 @@ else
echo "installToolchain: 86Box ROM set installed in ${BOX86_ROMS}"
fi
# FreeDOS boot files, the CD-ROM driver and CuteMouse. The pin names the
# files taken from the image, so a change to the list installs again.
FREEDOS_IMG_FILES="KERNEL.SYS COMMAND.COM FREEDOS/BIN/HIMEMX.EXE FREEDOS/BIN/UDVD2.SYS FREEDOS/BIN/SHSUCDX.COM"
# FreeDOS boot files, the CD-ROM driver, the long file name driver
# (DOSLFN, for "# LFN" scripts) and CuteMouse. The pin names the files
# taken from the image, so a change to the list installs again.
FREEDOS_IMG_FILES="KERNEL.SYS COMMAND.COM FREEDOS/BIN/HIMEMX.EXE FREEDOS/BIN/UDVD2.SYS FREEDOS/BIN/SHSUCDX.COM FREEDOS/BIN/DOSLFN.COM"
FREEDOS_PIN="${FREEDOS_SHA256} ${CTMOUSE_SHA256} ${FREEDOS_IMG_FILES// /,}"
if [ "${FORCE}" -eq 0 ] && pinned "${FREEDOS_DIR}" "${FREEDOS_PIN}"; then

BIN
screenshots/86box/apps-clock.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-desktop.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-dvxbasic.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-dvxdemo.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-filemgr.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-iconed.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-imgview.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-notepad.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-resedit.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-welcome.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/boot-boot.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/exit-cancel.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/exit-savechg.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/f1-h-dvxbas.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/f1-h-welcom.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/firstrun-fr-open.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/fullmode-fm-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/fullscr-fs-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/hang-ended.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/hang-taskmgr.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/install-in-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/install-in-welc.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/install-su-copy.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/install-su-done.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/install-su-fold.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/install-su-lic.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/install-su-unin.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/lfn-fm-big.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/lfn-fm-old.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/lfn-lfnsmk.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/menus-m-design.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/menus-m-file.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/menus-m-run.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/net-netsmk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/pardsgn-pardsgn.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/parhlp-parhlp-l.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/parhlp-parhlp.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/parpm-parpm.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/print-print1.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/safevid-sv-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sdk-sdkapp.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sdk-sdkbas.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sdk-sdkgreet.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sdk-sdktbx.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sdkgame-sdkgame.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sql-sqlsmk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/ucdemo-ucdemo.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/ucide-ucide-ds.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/ucide-ucide-ru.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/ucide-ucide-tb.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/upgrade-su-copy.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/upgrade-su-done.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/upgrade-su-fold.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/upgrade-su-lic.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/upgrade-su-unin.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/upgrade-su-upgr.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/welcome-wl-help.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/welcome-wl-open.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/welcome-wl-tour.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/welcome-wl-tour2.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/winops-w-back.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/winops-w-min.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/winops-w-move.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/winops-w-rest.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/winops-w-size.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/apps-clock.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/apps-desktop.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/apps-dvxbasic.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/apps-dvxdemo.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/apps-filemgr.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/apps-iconed.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/apps-imgview.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/apps-notepad.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/apps-resedit.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/apps-welcome.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/boot-boot.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/exit-cancel.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/exit-savechg.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/f1-h-dvxbas.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/f1-h-welcom.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/firstrun-fr-open.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/fullmode-fm-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/fullscr-fs-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/hang-ended.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/hang-taskmgr.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/install-in-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/install-in-welc.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/install-su-copy.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/install-su-disk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/install-su-done.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/install-su-fold.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/install-su-lic.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/install-su-unin.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/install-su-wrong.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/menus-m-design.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/menus-m-file.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/dosbox/menus-m-run.png (Stored with Git LFS)

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more