diff --git a/Makefile b/Makefile index b09afc37..2d9b3fa2 100644 --- a/Makefile +++ b/Makefile @@ -287,5 +287,5 @@ clean: $(MAKE) -C src/tools/proxy clean $(MAKE) -C src/installer clean rm -rf obj bin/host bin/test bin/system - rm -rf bin/config bin/widgets bin/libs bin/sdk + rm -rf bin/shared bin/widgets bin/libs bin/sdk rm -f docs/*.html diff --git a/README.md b/README.md index 4ceb00ba..ab7e2057 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,9 @@ It provides a Motif-inspired desktop, a cooperative multitasking kernel, a widget toolkit, a compiled BASIC language with a visual form designer, and a small set of bundled applications. -The system is a compositor built on VESA VBE 2.0+ linear framebuffer -video modes. A dirty-rectangle compositor keeps redraw cost proportional +The system is a compositor built on VESA VBE video modes: the linear +framebuffer where the card has one, its 64 KB bank window where it does +not. A dirty-rectangle compositor keeps redraw cost proportional to what actually changes on screen, so the desktop is responsive even at 1024x768 on modest hardware. @@ -43,10 +44,12 @@ to what actually changes on screen, so the desktop is responsive even at * DOS with a 386-class CPU or newer (486 recommended, Pentium for best performance) -* VESA BIOS Extensions 2.0 or newer with linear framebuffer support +* A VESA BIOS (VBE 1.2 or newer; a VBE driver such as UniVBE for cards + without one in ROM). A linear framebuffer (VBE 2.0) is faster; + without one DVX writes through the 64 KB bank window * 4 MB of extended memory minimum; 8 MB or more recommended -* Any resolution the video card reports at 8, 15, 16, 24, or 32 bits - per pixel. 640x480, 800x600, and 1024x768 are the common cases. +* Any resolution the video card reports at 8, 15, 16, or 32 bits per + pixel (24 is not supported). 640x480, 800x600, and 1024x768 are the common cases. * Two-button mouse; scroll wheel supported if a compatible driver is loaded @@ -108,7 +111,7 @@ it in 640x480 safe video mode. dvxgui/ assets/ logo and splash artwork bin/ build output (runtime tree; mirrors what ships) - config/ shipped INI, themes, wallpapers + config/ shipped DVX.INI, ASSOC.INI, themes, and wallpapers dist/ release media from `make dist` (not in git) docs/ HTML exports of the built-in help content LICENSE.txt MIT license @@ -128,6 +131,27 @@ dvxgui/ installToolchain.sh) ``` +An installed DVX (and `bin/`) keeps program files and user files apart: + +``` +DVX.EXE SETUP.EXE SETUP.LST +SYSTEM/ tools, SPLASH.RAW, and the shipped DVX.INI and ASSOC.INI +LIBS/ WIDGETS/ +APPS/// a program, its help, and DATA/ (files it ships) +SHARED/ FONTS, SOUNDS, THEMES, WPAPER: shipped for every program +USER/ everything written while DVX runs (back up this folder) + DVX.INI ASSOC.INI DVX.LOG + FONTS/ SOUNDS/ THEMES/ WPAPER/ the user's own (found before SHARED's) + APPS/// each program's settings and saved files + DOWNLOAD/ Terminal's downloads +``` + +`SET DVXUSER=D:\MYDVX` puts the user folder elsewhere (when DVX's disk +cannot be written it goes in TEMP). Only DVX's own package fills +SHARED; programs keep their own files with them. The package never +holds USER, so an upgrade replaces every program file and leaves the +user's alone. `claudeDocs/folderLayout.md` has the reasoning. + See `src/tools/README.md` for the host-side development tools (resource tool, icon generators, help compiler, proxy), and `src/apps/kpunch/README.md` for the SDK contract applications must diff --git a/config/README.md b/config/README.md index 850b6a37..2a7f8446 100644 --- a/config/README.md +++ b/config/README.md @@ -1,45 +1,38 @@ -# DVX Configuration Files +# DVX Shipped Settings and Shared Files -Runtime configuration, theme files, wallpaper images, and module -dependency files. These are copied into `bin/config/` (INI, themes, -wallpapers) or `bin/libs/` and `bin/widgets/` (dep files) during the -build. Text files are converted to DOS line endings (CR+LF) via sed. +The settings files DVX ships and the files it shares with every program. +The build copies them into `bin/` (text files converted to DOS line +endings, CR+LF, with sed): the settings into `bin/system/`, the themes and +wallpapers into `bin/shared/`. At its first start DVX copies `DVX.INI` to +the user folder (`USER`, or the folder `DVXUSER` names), where every +change is saved; the shipped copy is never written. File types work the +same way, except that the user's `ASSOC.INI` holds only their changes to +the shipped list. ## Files | Source File | Build Output | Description | |-------------|-------------|-------------| -| `dvx.ini` | `bin/config/dvx.ini` | System configuration | -| `ASSOC.INI` | `bin/config/ASSOC.INI` | File associations: which program opens each document type (shellAssoc.h; edited on the Control Panel's File Types page) | -| `themes/cde.thm` | `bin/config/themes/cde.thm` | CDE color theme | -| `themes/geos.thm` | `bin/config/themes/geos.thm` | GEOS Ensemble theme | -| `themes/hotdog.thm` | `bin/config/themes/hotdog.thm` | Hot Dog Stand theme | -| `themes/win31.thm` | `bin/config/themes/win31.thm` | Windows 3.1 theme | -| `wpaper/blueglow.jpg` | `bin/config/wpaper/blueglow.jpg` | Wallpaper image | -| `wpaper/swoop.jpg` | `bin/config/wpaper/swoop.jpg` | Wallpaper image | -| `wpaper/triangle.jpg` | `bin/config/wpaper/triangle.jpg` | Wallpaper image | -| `libdvx.dep` | `bin/libs/libdvx.dep` | libdvx dependency file | -| `texthelp.dep` | `bin/libs/texthelp.dep` | texthelp dependency file | -| `listhelp.dep` | `bin/libs/listhelp.dep` | listhelp dependency file | -| `dvxshell.dep` | `bin/libs/dvxshell.dep` | dvxshell dependency file | -| `textinpt.dep` | `bin/widgets/textinpt.dep` | TextInput widget dep file | -| `combobox.dep` | `bin/widgets/combobox.dep` | ComboBox widget dep file | -| `spinner.dep` | `bin/widgets/spinner.dep` | Spinner widget dep file | -| `terminal.dep` | `bin/widgets/terminal.dep` | AnsiTerm widget dep file | -| `dropdown.dep` | `bin/widgets/dropdown.dep` | Dropdown widget dep file | -| `listbox.dep` | `bin/widgets/listbox.dep` | ListBox widget dep file | -| `listview.dep` | `bin/widgets/listview.dep` | ListView widget dep file | -| `treeview.dep` | `bin/widgets/treeview.dep` | TreeView widget dep file | -| `basrt.dep` | `bin/libs/basrt.dep` | BASIC runtime dep file | -| `serial.dep` | `bin/libs/serial.dep` | Serial communications dep file | +| `dvx.ini` | `bin/system/DVX.INI` | The settings a new user starts with | +| `ASSOC.INI` | `bin/system/ASSOC.INI` | File associations: which program opens each document type (shellAssoc.h; changed on the Control Panel's File Types page, in the user's ASSOC.INI) | +| `themes/cde.thm` | `bin/shared/themes/cde.thm` | CDE color theme | +| `themes/geos.thm` | `bin/shared/themes/geos.thm` | GEOS Ensemble theme | +| `themes/hotdog.thm` | `bin/shared/themes/hotdog.thm` | Hot Dog Stand theme | +| `themes/win31.thm` | `bin/shared/themes/win31.thm` | Windows 3.1 theme | +| `wpaper/blueglow.jpg` | `bin/shared/wpaper/blueglow.jpg` | Wallpaper image | +| `wpaper/swoop.jpg` | `bin/shared/wpaper/swoop.jpg` | Wallpaper image | +| `wpaper/triangle.jpg` | `bin/shared/wpaper/triangle.jpg` | Wallpaper image | + +The desktop sounds (`bin/shared/sounds/`) are made by mksounds and the +fonts (`bin/shared/fonts/`) by mkfont (src/tools). ## dvx.ini Format Standard INI format with `[section]` headers and `key = value` pairs. -Comments start with `;`. The shell loads this at startup via -`prefsLoad("CONFIG/DVX.INI")`. +Comments start with `;`. The shell loads the user's copy at startup via +`prefsLoad(platformDvxIniPath())`. ### [video] Section diff --git a/config/dvx.ini b/config/dvx.ini index d56d0dc5..f4418dc8 100644 --- a/config/dvx.ini +++ b/config/dvx.ini @@ -113,20 +113,22 @@ fmTones = true midi = auto mpuMode = gm -; Desktop sounds (Control Panel's Sounds page): the sound file (WAV or VOC, -; path from the DVX folder) played for each event; empty = no sound. +; Desktop sounds (Control Panel's Sounds page): the sound file (WAV or VOC) +; played for each event; empty = no sound. A name alone is a file in the +; sound folders (your own in USER\SOUNDS first, then DVX's in +; SHARED\SOUNDS); a name with a folder in it is that file. ; default: the default beep (also message boxes without an icon) ; startup, exit: DVX starting and ending ; error, warning, question, information: message boxes of that kind ; windowOpen, windowClose: a window opening or closing (not dialogs) [sounds] -default = config/sounds/beep.wav -startup = config/sounds/startup.wav -exit = config/sounds/exit.wav -error = config/sounds/error.wav -warning = config/sounds/warning.wav -question = config/sounds/question.wav -information = config/sounds/info.wav +default = beep.wav +startup = startup.wav +exit = exit.wav +error = error.wav +warning = warning.wav +question = question.wav +information = info.wav windowOpen = windowClose = diff --git a/docs/dvx_basic_reference.html b/docs/dvx_basic_reference.html index 49a3d62c..10bc6814 100644 --- a/docs/dvx_basic_reference.html +++ b/docs/dvx_basic_reference.html @@ -196,9 +196,9 @@ img { max-width: 100%; }
  • AND
  • ANSI Terminal
  • App
  • -
  • App.Config
  • App.Data
  • App.Path
  • +
  • App.User
  • Arrange
  • ARRAY
  • ASC
  • @@ -511,6 +511,11 @@ img { max-width: 100%; }
  • FileOpsIsWritable
  • FileOpsJobBytesDone
  • FileOpsJobClearAttr
  • +
  • FileOpsKindBrowseDir$
  • +
  • FileOpsKindDir$
  • +
  • FileOpsKindFind$
  • +
  • FileOpsKindList
  • +
  • FileOpsKindName$
  • FileOpsLongNames
  • FileOpsMakePath
  • FileOpsPathIsAbsolute
  • @@ -523,6 +528,9 @@ img { max-width: 100%; }
  • FileOpsShortPath$
  • FileOpsTempDir$
  • FileOpsTotalBytes
  • +
  • FileOpsUserDir$
  • +
  • FileOpsUserInTemp
  • +
  • FileOpsUserPath$
  • FileOpsValidLongName
  • FileOpsValidName
  • FileOpsValidShortName
  • @@ -1082,7 +1090,6 @@ img { max-width: 100%; }
  • ShellArgQuote$
  • ShellCommandArgs$
  • ShellCommandProgram$
  • -
  • ShellConfigFile$
  • ShellGroupsLoad
  • ShellItemGet$
  • ShellItemIcon$
  • @@ -1250,6 +1257,7 @@ img { max-width: 100%; }
  • Unload
  • UNTIL
  • UseMaskColor
  • +
  • User Folder
  • UserControl
  • USERCONTROL
  • UserControls in the IDE
  • @@ -2076,7 +2084,7 @@ End Sub

    Preferences

    -

    Open via Tools > Preferences. Settings are saved to dvxbasic.ini in the app's config directory. The dialog has two tabs.

    +

    Open via Tools > Preferences. Settings are saved to dvxbasic.ini in the IDE's folder in your user folder (USER\APPS\KPUNCH\DVXBASIC). The dialog has two tabs.

    General Tab

    Editor Section

      Setting                                          Description                                                                           Default
    @@ -4608,14 +4616,16 @@ SQLClose db

    App Object

    -

    The App object provides read-only properties for the application's directory paths.

    +

    The App object provides read-only properties for the program's folders.

      Property      Returns   Description
       --------      -------   -----------
    -  App.Path      String    Directory containing the application's executable
    -  App.Config    String    Directory for application configuration files
    -  App.Data      String    Directory for application data files (databases, etc.)
    -
    configFile$ = App.Config & "\settings.ini"
    -dbPath$ = App.Data & "\myapp.db"
    +  App.Path      String    The folder the program is in
    +  App.User      String    The program's own folder in the user folder: its settings and every file it saves (databases, saved games, documents)
    +  App.Data      String    The DATA folder in the program's folder: the files the program comes with (read-only)
    +

    App.User is the place to write: it is kept apart from the program, so installing a new version never overwrites what is there, and backing up the user folder keeps it. Every copy of the program gets the same folder. It is made the first time App.User is used. App.Data is for reading only: on a CD-ROM it cannot be written at all. Programs never write in DVX's SHARED folder.

    +
    settingsFile$ = App.User & "\settings.ini"
    +dbPath$ = App.User & "\myapp.db"
    +levelFile$ = App.Data & "\level1.dat"
     Print "Running from: " & App.Path
    @@ -4670,13 +4680,13 @@ End Sub

    IniRead

    Reads a value from an INI file. Returns the default value if the file, section, or key is not found. All four arguments are required. Section and key names match without regard to case, and blanks around them are ignored ([ User ] is section User). If a name appears twice, the first one counts. Keys above the first section header belong to section "" (an empty section name). Lines starting with ; or # are comments.

    value$ = IniRead(file$, section$, key$, default$)
    -
    name$ = IniRead(App.Config & "\app.ini", "User", "Name", "Unknown")
    -fontSize = Val(IniRead(App.Config & "\app.ini", "Display", "FontSize", "12"))
    +
    name$ = IniRead(App.User & "\app.ini", "User", "Name", "Unknown")
    +fontSize = Val(IniRead(App.User & "\app.ini", "Display", "FontSize", "12"))

    IniWrite

    Writes a value to an INI file. Creates the file, section, or key if they do not exist. A new key goes after the last key of its section and a new section at the end of the file. Every other line -- comments, blank lines, other keys, lines of any length -- is kept exactly as it is. The changed key is written as key = value. Every line of the saved file ends in a carriage return and line feed (CR LF). The file is saved through a temporary file, so a failed write leaves the old file intact. If the file exists but cannot be read, or the new file cannot be written, IniWrite raises error 75 (Path/file access error) and leaves the file alone.

    INIWRITE file$, section$, key$, value$
    -
    IniWrite App.Config & "\app.ini", "User", "Name", "Scott"
    -IniWrite App.Config & "\app.ini", "Display", "FontSize", Str$(fontSize)
    +
    IniWrite App.User & "\app.ini", "User", "Name", "Scott"
    +IniWrite App.User & "\app.ini", "Display", "FontSize", Str$(fontSize)

    Predefined Constants

    @@ -4917,7 +4927,7 @@ End Sub compiler.bas The BASIC compiler: compile a project or files you give it, find compile errors in their files, list a program's procedures and the language's keywords, build an .app or a control file; put a project's UserControls on a form designer's toolbox; read source text as the compiler does (tokens, code or string or comment, renaming a control in code, WithEvents variables, class Events), F1 help topics; open, change, and save project files and UserControl headers (CompSourceFromProject, CompSourceAdd, CompCompile, CompError$, CompMapFile$, CompProcList$, CompBuildApp, CompDesignControls, CompTokens$, CompRenameInCode$, CompHelpTopic$, ProjOpen, ProjSave, ProjCtlSetHeader$, ...) debug.bas Run a compiled program inside yours and debug it: breakpoints, stepping, its variables, expressions, Immediate-window lines, its PRINT output (RunCreate, RunStart, RunPoll, DbgSetBreakpoints, DbgStepOver, DbgLocals$, DbgEval$, DbgExec$, ...) designer.bas Form designers: the control types, whether each holds other controls and can be placed, the names of new controls, default events, toolbox tooltips and icons, and each type's properties (with their types and value names), methods, and events (with each event's parameters); the names in .frm and class module text; .frm files as data to read, edit, and write, controls copied and pasted as text, and a loaded form written back as .frm text (CtlTypeCount, CtlTypeName$, CtlTypeFlags, CtlPropCount, CtlPropName$, CtlPropType, CtlEventList$, CtlEventParams$, CtlTypeEventParams$, FrmFormName$, FrmControlNames$, ClsClassName$, FrmOpen, FrmText$, FrmCtlAdd, FrmCtlText$, FrmCtlPaste, FrmMenuAdd, FormText$, ...) - shell.bas DVX itself, everything Program Manager and Task Manager do: start programs and open documents, command lines (split into their parts) and the Run dialog, the installed programs and their names, file types, the running programs (find one, bring it to the front, ask it to close, or end it), this program's priority, keys that work in every program, Task Manager, system information, Exit DVX, the desktop and the program started after it, this program's settings folder, the DVX log; Program Manager's program groups with their items, shortcut keys, and icons (ShellRun, ShellRunProgram, ShellProgramScan, ShellAssocCount, ShellRunningId, ShellRunningActivate, ShellRunningClose, ShellArg$, ShellSetPriority, HotkeyAdd, ShellExitDvx, ShellConfigFile$, ShellGroupsLoad, ShellItemGet$, ShellItemIcon$, ...) + shell.bas DVX itself, everything Program Manager and Task Manager do: start programs and open documents, command lines (split into their parts) and the Run dialog, the installed programs and their names, file types, the running programs (find one, bring it to the front, ask it to close, or end it), this program's priority, keys that work in every program, Task Manager, system information, Exit DVX, the desktop and the program started after it, the DVX log; Program Manager's program groups with their items, shortcut keys, and icons (ShellRun, ShellRunProgram, ShellProgramScan, ShellAssocCount, ShellRunningId, ShellRunningActivate, ShellRunningClose, ShellArg$, ShellSetPriority, HotkeyAdd, ShellExitDvx, ShellGroupsLoad, ShellItemGet$, ShellItemIcon$, ...)

    Using an Include Library

    ' With commdlg.bas added to the project
     Dim path As String
    @@ -5093,7 +5103,8 @@ End Sub

    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.

    Paths: FileOpsPathNormalize$ (the full path of an existing folder, or ""), FileOpsPathParent$, FileOpsPathJoin$, FileOpsPathSame, FileOpsPathIsRoot, FileOpsPathIsAbsolute (True for a path that is complete by itself, such as "C:\DOCS", 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, "\" on DOS), FileOpsPathNative$ (a path written with that character, for showing it: "C:/DOCS/A.TXT" becomes "C:\DOCS\A.TXT"), FileOpsBaseName$, and FileOpsExtension$. Every one of them takes / and \ alike and gives back \. 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 "*.bmp;*.png", case not mattering.

    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 "YYYY-MM-DD HH:MM"; FileOpsSetModified returns False for a date that does not exist), FileOpsTreeSize with FileOpsTreeBytes, FileOpsTreeFiles, and FileOpsTreeFolders (the size of a whole folder), and FileOpsFormatSize$.

    -

    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 ("" when there is none).

    +

    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 nothing can be saved: DVX runs from such a disk and there is no TEMP folder to keep the user folder in. FileOpsTempDir$() is the folder for scratch files ("" when there is none).

    +

    DVX's folders: FileOpsUserDir$() is the user folder (USER in the DVX folder, or the folder DVXUSER names), where everything DVX and its programs save goes; FileOpsUserPath$(name) is a file or folder in it, for example FileOpsUserPath$("DOWNLOAD"); FileOpsUserInTemp() is True when DVX runs from a disk it cannot write to and keeps the user folder in the TEMP folder. A program's own folder there is App.User. The fonts, sounds, themes, and desktop pictures come in two folders each, DVX's own in SHARED and the user's in the user folder; the kinds are FILEOPS_KIND_FONTS, FILEOPS_KIND_SOUNDS, FILEOPS_KIND_THEMES, and FILEOPS_KIND_WPAPER. FileOpsKindDir$(kind, user) is DVX's folder of a kind (user False) or the user's (True); FileOpsKindBrowseDir$(kind) is the one a file dialog starts in (the user's when it exists); FileOpsKindFind$(kind, fileName) finds a file by name, the user's first ("" when there is none); FileOpsKindName$(kind, path) is the name alone of a file in one of the two folders, the way settings store it ("" for any other path); FileOpsKindList(kind) lists both folders as one, sorted by name, a user's file hiding DVX's of the same name (a list for FileOpsListCount, FileOpsListName$, and the rest; FileOpsListFree when done). Programs read DVX's SHARED folder but never write in it.

    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.

    Dim job As Long
     
    @@ -5149,15 +5160,15 @@ Sub FillTaskList ()
     End Sub

    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 ("" 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 "notepad.app", ShellArgQuote$(path$)). COMMAND$(n) gives this program's own arguments the same way.

    Keys for every program. HotkeyAdd(keyText) makes a key such as "Ctrl+Alt+E" 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 ("ctrl+alt+e" gives "Ctrl+Alt+E"; "" 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 ("" for no shortcut is valid too).

    -

    This program. ShellAppPath$ is this program's own path (ShellRun ShellAppPath$(), "" 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 "Allow more than one copy to run at once" 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 ("" 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 ("" for none).

    +

    This program. ShellAppPath$ is this program's own path (ShellRun ShellAppPath$(), "" 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 "Allow more than one copy to run at once" ticked. A program keeps its settings in App.User, as DVX's own programs do; 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 ("" 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 ("" for none).

    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 ("name", "program", "args", "folder", "icon", "key", "minimized", "col", "row", "description"); 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 ("view": SHELL_VIEW_LARGE, SHELL_VIEW_SMALL, or SHELL_VIEW_LIST; "group", the group shown; "autoArrange", "minimizeOnRun", "restoreAlone"), 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.

    Dim groups As Long, main As Long, i As Long
    -groups = ShellGroupsLoad(ShellConfigFile$("groups.ini"))
    +groups = ShellGroupsLoad(App.User & "\groups.ini")
     main = ShellGroupFind(groups, "Main")
     i = ShellItemAdd(groups, main, "Notepad", "APPS\KPUNCH\NOTEPAD\NOTEPAD.APP")
     If Not ShellItemSet(groups, main, i, "key", "Ctrl+Alt+N") Then MsgBox "Not a shortcut."
     picIcon.Picture = LOADPICTURE(ShellItemIcon$(ShellItemGet$(groups, main, i, "icon"), ShellItemGet$(groups, main, i, "program")))
    -If Not ShellGroupsSave(groups, ShellConfigFile$("groups.ini")) Then MsgBox "Not saved."
    +If Not ShellGroupsSave(groups, App.User & "\groups.ini") Then MsgBox "Not saved."
     ShellGroupsFree groups
    Sub Form1_Load ()
         Dim copies As Long
    @@ -5181,7 +5192,7 @@ End Sub

    Changing DVX's Settings

    With system.bas in the project, a program changes what Control Panel changes, at once for the whole desktop. Add prefs.bas too: the settings are saved through a prefs.bas handle.

    Screen mode: SysVideoModeCount() says how many modes the display offers (numbered from 0), and SysVideoModeWidth, SysVideoModeHeight, and SysVideoModeBpp (bits per pixel) describe each. SysSetVideoMode(wide, high, bpp) changes the mode and keeps every window; it returns False when the mode could not be set (the old one stays), also while a program has the whole screen to itself. A mode the monitor cannot show leaves the user unable to answer, so do as Control Panel does: ask "Keep this mode?" and go back to the old mode by itself after some seconds. Screen.Width, Screen.Height, and Screen.BitsPerPixel tell the mode in use, and SYS_VIDEO_DEFAULT_WIDTH, SYS_VIDEO_DEFAULT_HEIGHT, and SYS_VIDEO_DEFAULT_BPP the mode DVX starts in when its settings name none. SysScreenshot(path) saves the whole screen as a picture file (BMP when path ends in .bmp, PNG otherwise) and returns True when it was written.

    -

    Colors: the system colors are numbered from 0 to SysColorCount() - 1. SysColorLabel$(id) is the text to show for one ("Desktop", "Window Face" ...), SysColorName$(id) the name it is stored as, and SysColorId(colorName) the id of a name (-1 for none) -- to draw in the user's colors, for example SysGetColor(SysColorId("desktop")). SysGetColor and SysSetColor read and set a color as an RGB() value; each SysSetColor redraws the whole screen. SysResetColors goes back to DVX's own colors. SysLoadTheme(path) and SysSaveTheme(path) read and write a theme file (.THM, kept in CONFIG\THEMES); both return True when they worked.

    +

    Colors: the system colors are numbered from 0 to SysColorCount() - 1. SysColorLabel$(id) is the text to show for one ("Desktop", "Window Face" ...), SysColorName$(id) the name it is stored as, and SysColorId(colorName) the id of a name (-1 for none) -- to draw in the user's colors, for example SysGetColor(SysColorId("desktop")). SysGetColor and SysSetColor read and set a color as an RGB() value; each SysSetColor redraws the whole screen. SysResetColors goes back to DVX's own colors. SysLoadTheme(path) and SysSaveTheme(path) read and write a theme file (.THM; DVX's own are in SHARED\THEMES, the user's in the THEMES folder of the user folder, FileOpsKindDir$(FILEOPS_KIND_THEMES, True)); both return True when they worked.

    Wallpaper: SysSetWallpaper(path) shows a BMP, JPG, PNG, or GIF image behind the desktop ("" for none) and returns False when the image could not be loaded (the old one stays). SysSetWallpaperMode mode says how it fills the screen, a choice of PREFS_CHOICE_WALLPAPER (Stretch, Tile, or Center; see Settings Files). SysWallpaper$() and SysWallpaperMode() tell what is in use.

    Text: SysSetTextSmoothing True smooths the edges of text and SysSetTextSmoothing False stops it; SysTextSmoothing() tells which the user chose. Text is smoothed only when the screen shows more than 256 colors, and only in the fonts and sizes that come smoothed. Every window is drawn again when it changes.

    Mouse: SysSetMouse wheelDir, dblClickMs, accel, mickeys, wheelStep applies a whole mouse setup at once: the scroll wheel's direction (1 or -1, the values of PREFS_CHOICE_WHEEL), the double-click time in milliseconds, the acceleration (a value of PREFS_CHOICE_ACCEL), how far the mouse moves for 8 pixels of pointer movement (8 is normal, higher is slower), and the lines scrolled per wheel notch (1 to 10). An accel or mickeys of 0 leaves that one as it is. SysMouseWheelDir, SysMouseDoubleClick, SysMouseAccel, SysMouseMickeys, and SysMouseWheelStep read the setup in effect. MOUSE_WHEEL_STEP_MIN and MOUSE_WHEEL_STEP_MAX are the limits of the wheel step, and MOUSE_WHEEL_STEP_DEFAULT, MOUSE_DBLCLICK_DEFAULT_MS, and MOUSE_SPEED_DEFAULT are DVX's defaults (what a Default button puts back).

    @@ -5569,7 +5580,7 @@ SecDhFree dh

    Settings Files

    With prefs.bas in the project, a program keeps its settings in an INI file the way DVX's own programs do. PrefsLoad(path) reads the file once (a file that is not there reads as empty); PrefsGet$, PrefsGetInt, and PrefsGetBool read a key of a section (each with the value to use when it is missing), and PrefsSet, PrefsSetInt, PrefsSetBool, and PrefsRemove change it in memory. PrefsSave writes it back, keeping comments and every line it did not change. To write a whole new file -- dropping sections that are no longer wanted -- fill a PrefsCreate handle and save it with PrefsSaveAs: the old file is replaced only once the new one is completely written. PrefsClose frees a handle. IniRead and IniWrite (built in) do one value at a time and read or write the whole file each time; prefs.bas is the faster choice for many settings.

    Dim ini As Long
    -ini = PrefsLoad(ShellConfigFile$("MYAPP.INI"))
    +ini = PrefsLoad(App.User & "\MYAPP.INI")
     userName = PrefsGet$(ini, "User", "Name", "Unknown")
     PrefsSetInt ini, "Window", "Left", Me.Left
     If Not PrefsSave(ini) Then MsgBox "The settings could not be saved."
    diff --git a/docs/dvx_system_reference.html b/docs/dvx_system_reference.html
    index 80711039..02d8a186 100644
    --- a/docs/dvx_system_reference.html
    +++ b/docs/dvx_system_reference.html
    @@ -66,6 +66,7 @@ img { max-width: 100%; }
     
  • Modal Dialogs
  • Resource System
  • Preferences System
  • +
  • DVX Folders
  • Per-App Memory Tracking
  • DXE Module System
  • Event Model
  • @@ -131,7 +132,7 @@ img { max-width: 100%; }
  • Lifecycle API
  • Query API
  • Starting Up
  • -
  • Configuration API
  • +
  • Program Folders API
  • Desktop Callbacks
  • System Information
  • Installed Programs
  • @@ -358,6 +359,7 @@ img { max-width: 100%; }
  • audioTone
  • Back
  • Backbuffer
  • +
  • Backing Up
  • basArrayNew
  • BasArrayT
  • BasArrayT
  • @@ -442,7 +444,6 @@ img { max-width: 100%; }
  • Common Properties
  • compiler.bas
  • Compositing
  • -
  • configDir
  • conn
  • conn.bas
  • ConnAttach
  • @@ -777,6 +778,8 @@ img { max-width: 100%; }
  • dvxUnregisterAppHotkeys
  • dvxUnregisterHotkey
  • dvxUpdate
  • +
  • DVXUSER
  • +
  • DVXUSER
  • dvxVideo
  • dvxVideo.h
  • dvxWallpaperFromPrefs
  • @@ -823,6 +826,7 @@ img { max-width: 100%; }
  • Flowing text
  • flushRect
  • Folders
  • +
  • Folders
  • Font
  • Font families
  • Font files
  • @@ -1102,6 +1106,7 @@ img { max-width: 100%; }
  • Platform Layer
  • PLATFORM_LONG_NAME_MAX
  • platformAppExit
  • +
  • platformBankChunk
  • platformBootDrive
  • platformClock
  • platformDirIsWritable
  • @@ -1160,6 +1165,7 @@ img { max-width: 100%; }
  • platformValidateLongName
  • platformValidateShortName
  • platformVideoInit
  • +
  • platformVideoReadBack
  • PlayTone
  • PlayWave
  • pmHotkeyParse
  • @@ -1316,6 +1322,7 @@ img { max-width: 100%; }
  • Settings
  • Setup
  • SHA-256
  • +
  • SHARED
  • Shared Library
  • shell.bas
  • SHELL_APP_DESCRIPTOR
  • @@ -1360,12 +1367,11 @@ img { max-width: 100%; }
  • shellCloseApp
  • ShellCommandArgs
  • ShellCommandProgram
  • -
  • ShellConfigFile
  • -
  • shellConfigPath
  • shellCtrlEscFn
  • +
  • shellDataPath
  • shellDesktopChangeCount
  • shellDesktopUpdate
  • -
  • shellEnsureConfigDir
  • +
  • shellEnsureUserDir
  • ShellExitDvx
  • shellForceKillApp
  • shellGetApp
  • @@ -1438,6 +1444,7 @@ img { max-width: 100%; }
  • shellUnregisterAppCleanup
  • shellUnregisterDesktopUpdate
  • shellUnregisterIdle
  • +
  • shellUserPath
  • Shift Key at Start
  • Shortcut Keys
  • Slider
  • @@ -1556,8 +1563,11 @@ img { max-width: 100%; }
  • Undo
  • Uninstalling DVX
  • Upgrading DVX
  • +
  • User Folder
  • +
  • User folder
  • User Guide
  • UserControl (SDK)
  • +
  • userDir
  • Using BASIC Controls from C
  • VBE
  • VBox
  • @@ -1992,7 +2002,7 @@ img { max-width: 100%; }

    What You Need

    • A PC running DOS with a 386 processor or better. A 486 or Pentium is recommended.
    • -
    • A video card that supports VESA 2.0 graphics. Most video cards made since the mid 1990s do.
    • +
    • A video card with VESA graphics, which nearly every card from about 1992 on has (some need their VESA driver loaded first; see Troubleshooting).
    • At least 4 MB of memory. 8 MB or more is recommended.
    • A mouse, with its DOS mouse driver loaded before you start DVX. A scroll wheel works if your mouse driver supports it.
    @@ -2286,6 +2296,10 @@ img { max-width: 100%; }

    Settings you keep are saved, and DVX uses them again the next time it starts.

    DVX plays a short sound when it starts and when it ends, and when a message appears (a different one for errors, warnings, questions, and information). Each sound can be changed or turned off, and the volume set, in the settings program.

    Tip: If a new screen resolution leaves the screen unreadable, just wait: DVX goes back to the old one after 15 seconds unless you confirm the change.
    +

    Where your settings and files are kept

    +

    Everything DVX and its programs save for you goes in one folder, the USER folder inside the DVX folder (for example C:\DVX\USER): your settings, each program's settings and the files it saves (such as saved games), Terminal's downloads, and DVX's log. To back up your work, copy this one folder. Installing a new version of DVX never changes it.

    +

    The fonts, sounds, themes, and desktop pictures that come with DVX are in the SHARED folder. To add your own, put them in the folder of the same name in your USER folder: FONTS, SOUNDS, THEMES, or WPAPER. The settings program lists yours together with DVX's, and a file of yours with the same name as one of DVX's is used instead of it. Themes you save go there too.

    +

    To keep the USER folder somewhere else (on another disk, or one for each person who uses the computer), set DVXUSER to that folder before starting DVX, for example SET DVXUSER=D:\MYDVX in AUTOEXEC.BAT.

    Task Manager

    @@ -2359,7 +2373,7 @@ img { max-width: 100%; }

    The mouse pointer does not move

    DVX uses your DOS mouse driver. Load the mouse driver (usually from AUTOEXEC.BAT, or by typing its name at the DOS prompt) before you start DVX. If the scroll wheel does nothing, your mouse driver may not support wheels; everything else still works. If the pointer is too fast or too slow, change the mouse settings (see Changing Settings).

    DVX will not start, or the screen stays blank

    -

    DVX needs a video card with VESA 2.0 graphics. Some older cards need a VESA driver program loaded first; check the card's manual.

    +

    DVX needs a video card with a VESA video BIOS and a mode of at least 640x480 at 256 colors or more, which nearly every card from about 1992 on has. Many older cards need their VESA driver program loaded first (from AUTOEXEC.BAT, or by typing its name at the DOS prompt): UniVBE (Scitech Display Doctor) works with most cards, and some cards came with their own, such as S3VBE20 for S3 cards and M64VBE for ATI Mach64 cards. Older cards work too, but the screen updates more slowly on them. If DVX still will not start, DVX.LOG in the USER folder says why.

    If the screen goes wrong right after you picked a new screen resolution, wait 15 seconds and DVX puts the old one back.

    Safe video mode

    If the screen resolution DVX is set to use does not work on your computer (for example after changing video cards), DVX starts in safe video mode instead: 640x480, which every video card can show. A message tells you so and asks whether to use this mode from now on. Answer Yes to keep it, or No to try the old resolution again at the next start.

    @@ -2372,9 +2386,9 @@ img { max-width: 100%; }

    Installing, upgrading, and removing DVX

    DVX is installed with SETUP, from the DVX CD or from Disk 1 of the DVX floppy disks: change to that drive and type SETUP. Setup shows the licence, asks for the folder to install DVX in and which fonts to install, checks that there is room, and unpacks DVX there, asking for each floppy disk it needs in turn. It can also make DVX start when the computer starts (it shows the line it adds to AUTOEXEC.BAT and keeps a copy of the old file as AUTOEXEC.DVX). Setup never writes to the CD or the floppy disks.

    The fonts are up to you. None keeps DVX to its own font; the base set adds DejaVu Sans, Sans Mono, and Serif in all their styles (about 2 MB); and All adds every font that comes with DVX (about 8 MB). A program that asks for a font you did not install shows its text in DVX's own font instead, unless it carries that font itself (some programs do, such as Welcome and the DVX Demo). Every font file holds its own licence: the Licence button of the Font dialog shows it. With None or the base set, Setup does not ask for the last floppy disks, which hold only fonts.

    -

    To upgrade or repair DVX, run Setup again and choose the same folder: answer Yes to keep your settings. Setup starts with the fonts that folder already has; choose others to add fonts or remove them. To remove DVX, run SETUP in the DVX folder (for example C:\DVX\SETUP) and choose Uninstall. Files you added to the folder yourself are not removed, and your settings are only removed if you ask.

    +

    To upgrade or repair DVX, run Setup again and choose the same folder: answer Yes to keep your settings and saved files (the USER folder), or No to remove them and start over. Setup starts with the fonts that folder already has; choose others to add fonts or remove them. To remove DVX, run SETUP in the DVX folder (for example C:\DVX\SETUP) and choose Uninstall. Files you added to the folder yourself are not removed, and the USER folder is only removed if you ask.

    Running DVX from a CD-ROM or a write-protected disk

    -

    DVX also runs straight from a disk it cannot write to. It then tells you once that changed settings last only until you exit DVX, and the help files are used as they are. To keep your settings, install DVX on your hard disk with Setup.

    +

    DVX also runs straight from a disk it cannot write to. It then keeps your settings and files in a DVXUSER folder in your TEMP folder, and tells you so once. To keep them somewhere of your choosing, set DVXUSER to a folder on your hard disk before starting DVX (see Changing Settings). Without a TEMP folder, DVX tells you that changed settings last only until you exit DVX. Either way the help files are used as they are. To keep everything on your hard disk, install DVX there with Setup.

    A program is already running

    Most programs can only be open once. Use Alt+Tab or the Task Manager (Ctrl+Esc) to find its window. If you cannot see it, it may be minimized to an icon at the bottom of the screen.

    "This program was built for a different version of DVX"

    @@ -2388,7 +2402,7 @@ img { max-width: 100%; }

    DVX will not exit

    When you exit DVX, each program is closed as if you had closed it yourself. If you answer Cancel when a program asks to save its work, DVX stays running. Save or close that program, then choose Exit DVX again.

    Reporting a problem

    -

    DVX writes a record of what happened to the file DVX.LOG, in the same folder as DVX.EXE. If a program crashes, this file contains details that help the program's author find the problem. The file is started fresh each time DVX starts, so copy it before starting DVX again.

    +

    DVX writes a record of what happened to the file DVX.LOG, in your USER folder (for example C:\DVX\USER\DVX.LOG). If a program crashes, this file contains details that help the program's author find the problem. The file is started fresh each time DVX starts, so copy it before starting DVX again.

    Changing Settings

    Task Manager

    @@ -2407,7 +2421,7 @@ img { max-width: 100%; }

    What Is libdvx?

    libdvx is the heart of DVX -- a DXE3 library that provides: