diff --git a/BUGS-TO-REPORT.md b/BUGS-TO-REPORT.md index 8124b90dc..39d25c9c1 100644 --- a/BUGS-TO-REPORT.md +++ b/BUGS-TO-REPORT.md @@ -6283,3 +6283,127 @@ This looks like the same cause as #2497 (fixed in BETA 1004), where a constant o Severity: low. The error is raised and is easy to see; the statement that raises it holds a correct value. A program meets it only when a constant that overflows is followed in the same procedure by a constant `Double` expression, which is mostly code that tests overflow handling. + +--- + +## A 64-bit build prints a negative zero as `-0` + +**Describe the bug** +A `Single` or `Double` that holds a negative zero (the sign bit set, every other bit clear) converts to the text `-0` in a 64-bit build: `CStr`, `Str$` (with no leading space), `Format$`, concatenation with `&` and `Debug.Print` all give it. A 32-bit twinBASIC build gives `0` (`Str$` gives ` 0`), and so does VB6. Both builds hold the negative zero: the sign bit (`&H80000000` in a `Single`, `&H8000000000000000` in a `Double`) is read back through `RtlMoveMemory`, and the value compares equal to 0. It was found on a page of the documentation whose sample prints a GDI+ matrix offset that is a negative zero, `0 5 -0` in a 64-bit build where the page says `0 5 0`. It was observed in IDE runs. + +**To Reproduce** +Steps to reproduce the behavior: +1. Open `negative-zero-text-win64.twinproj` (attached as `negative-zero-text-win64.zip`). Its module `NegativeZeroTextTests` has one `[TestCase]` for each conversion, asserting what VB6 gives, two cases that check the sign bit, and two controls. +2. Run the test cases as a 64-bit build (`tbrun --tests --arch win64`). The seven conversion cases fail, with `-0` as `Actual`; the sign-bit cases and the controls pass. As a 32-bit build all eleven pass. +3. The shortest form of it, in a 64-bit build: +```vb +Dim s As Single +s = 0! +s = -s +Debug.Print CStr(s), Str$(s), Format$(s), "x=" & s ' VB6 and 32-bit: 0 " 0" 0 x=0 ; 64-bit: -0 -0 -0 x=-0 +``` + +**Expected behavior** +The same text in a 64-bit build as in a 32-bit one and in VB6: `0` from `CStr`, `Format$` and `&`, and ` 0` from `Str$`. The reproducer's `vb6/` project prints them (attached as `negative-zero-text-win64-vb6.zip`). + +**Desktop:** + - OS: Windows 10 Pro 22H2 (build 19045) + - twinBASIC compiler version: BETA 1010 + +**Additional context** +The reproducer's `repro.json` names the 64-bit build (`"arch": "win64"`). A positive zero and an ordinary negative number (`-1.5`) print the same in both builds. Severity: low. A negative zero is the result of `-x` for a zero `x`, and a COM or API result can hold one, so a program meets it, and one that shows or compares the text behaves differently in the two builds. + + + +--- + +## A class field whose initializer reads another field of the class fails the build with a codegen error + +**Describe the bug** +A field initializer in a class that reads another field of the same class (`Public Second As Long = First + 1`) compiles with no diagnostic, and the build fails once the class is used: `[LINKER] compilation (codegen) error detected in 'Counter.{fields_init}' at line #1`, then `[LINKER] FAILED due to compilation errors`. A run in the IDE goes ahead instead, and the field holds an arbitrary number: with `A` = 1, `X = A + 1` read `1073741889`. Observed with `tbbuild --build` and with `tbrun` (a `[RunAfterBuild]` procedure in the IDE). + +**To Reproduce** +Steps to reproduce the behavior: +1. Open `class-field-init-reads-field.twinproj` (attached as `class-field-init-reads-field.zip`). Its file `Startup.twin` is: + ``` + Module Startup + Public Sub Main() + Dim c As New Counter + Debug.Print c.First & ", " & c.Second + End Sub + End Module + + Class Counter + Public First As Long = 1 + Public Second As Long = First + 1 + End Class + ``` +2. Compile the project: no diagnostic. +3. Build it. The DEBUG CONSOLE prints `[LINKER] compilation (codegen) error detected in 'Counter.{fields_init}' at line #1` and `[BUILD] failed`. + +**Expected behavior** +The build succeeds and `Main` prints `1, 2`: `Second`'s initializer reads `First`, whose initializer comes before it. If reading another field is not meant to be allowed, the compiler should say so at the declaration, as it does for a call to a procedure of the project (TB5079). Field initializers are a twinBASIC extension, so there is no VB6 behaviour to compare with. + +**Desktop:** + - OS: Windows 10 Pro 22H2 (build 19045) + - twinBASIC compiler version: BETA 1010 + +**Additional context** +The same codegen error, one line per class, for `X = A` with no arithmetic, `X = Me.A + 1`, `String` fields (`X = S & "b"`), a `ReadOnly` field read, a field declared below the one that reads it, and a field with no initializer of its own, in 32-bit and 64-bit builds. These are right: a field that reads a module-level variable (`X = Mods.MV + 1`) or a constant, a module-level variable that reads a variable of its own module (`MW = MV + 1`), and a class that is never created (it is not compiled, so the build does not fail). + +Severity: medium. The build fails with a message that names the class but not the field or the reason, and the IDE run gives a wrong value with no message at all. Setting the field in `Class_Initialize` or `Sub New` avoids it. + +Not tried: an `Object` or `Variant` field, LLVM. + + + +--- + +## In the IDE, a module-level initializer that reads another module's variable leaves every module-level variable at 0 + +**Describe the bug** +When one module-level variable's initializer reads a variable of another module (`Public FromConfig As Long = Config.Limit + 100`), code run in the IDE reads every module-level variable of the project as 0, including ones whose initializers are constants (`Public Limit As Long = 5`). The built exe gets them all right. Observed with a `[RunAfterBuild]` procedure, through `tbrun` and `bug_repro.mjs run`; the exe was run with `tbrun --exe`. + +**To Reproduce** +Steps to reproduce the behavior: +1. Open `module-init-reads-other-module-ide.twinproj` (attached as `module-init-reads-other-module-ide.zip`). Its file `Startup.twin` is: + ``` + Module Config + Public Const Base As Long = 7 + Public Limit As Long = 5 + Public Doubled As Long = Base * 2 + End Module + + Module Other + Public FromConfig As Long = Config.Limit + 100 + End Module + + Class Box + Public Size As Long = 3 + End Class + + Module Startup + Public Sub Main() + Dim b As New Box + Debug.Print "Limit=" & Config.Limit & " Doubled=" & Config.Doubled & " FromConfig=" & Other.FromConfig & " Box.Size=" & b.Size + End Sub + End Module + ``` +2. Add a module with a `[RunAfterBuild]` procedure that calls `Startup.Main`, and build the project. +3. The DEBUG CONSOLE prints `Limit=0 Doubled=0 FromConfig=0 Box.Size=3`. + +**Expected behavior** +`Limit=5 Doubled=14 FromConfig=105 Box.Size=3`, which is what the built exe prints. Module-level initializers are a twinBASIC extension, so there is no VB6 behaviour to compare with. + +**Desktop:** + - OS: Windows 10 Pro 22H2 (build 19045) + - twinBASIC compiler version: BETA 1010 + +**Additional context** +Every module-level variable reads 0 as long as one initializer reads another module's variable. Each of these makes the IDE print `Limit=5 Doubled=14`: the same project without `Other`, `FromConfig = 100`, `FromConfig = Config.Base + 100` (another module's constant), and `FromConfig = Limit2 + 100`, where `Limit2` is a variable of `Other` itself. A class field initializer runs either way (`Box.Size=3`). In the exe, a module whose initializer reads a module that is set up after it reads 0 there; that is a matter of order, and the IDE gives 0 for every module, whatever the order. + +Severity: medium. A `[RunAfterBuild]` procedure that signs or post-processes the build sees wrong settings with no message, and code that runs correctly as an exe behaves differently in the IDE. + +Not tried: a run with F5 (only `[RunAfterBuild]` was observed), a variable of the module's own read with a qualified name (`Other.Limit2`), 64-bit, LLVM. + + diff --git a/WIP.BigNumberLib.md b/WIP.BigNumberLib.md new file mode 100644 index 000000000..2e63befd0 --- /dev/null +++ b/WIP.BigNumberLib.md @@ -0,0 +1,28 @@ +# BigNumberLib --- working notes + +The contributed BigNumberLib package, documented at `docs/Reference/Contributed/BigNumberLib/`, +its test project at `test/package-tests/BigNumberLib/`. This file holds what is known about the +package and is not on its pages yet, with the reason. + +## Unconfirmed: AssignDivision near the library's capacity (1.0.4.0, BETA 1010) + +Seen by one agent only, while it confirmed the hang of `AssignModulus` and `AssignAdditionModulus` +(the 1.0.4.0 WARNING on the BigNumber page). The owner's rule is that a defect goes on a page only +once a second, independent agent has reproduced it, so this stays here until one has. + +- **Corrupt quotient, no error.** In a 32-bit program `AssignDivision` of a dividend of 4300 bits + gave a quotient of 2173 bits (about 4280 expected); 4288 bits was right. In a 64-bit program a + dividend of 4544 bits gave 2305 bits (about 4524 expected); 4300 bits was right. The edge is a + dividend of FP_SIZE - 1 digits or more: over about 4288 bits (32-bit), 4480 bits (64-bit). +- **Cause, from the source.** TomsFastMath 0.13.1 `fp_div` sets `q.used = a.used + 2`; when that + exceeds FP_SIZE (136 digits of 32 bits, 72 of 64), `fp_clamp` stops at a stray digit and the + quotient's `used` is wrong. BigNumber.twin's `AssignDivision` calls `fp_div` with no guard. +- **Also seen:** `AssignDivision` hangs from the same edge as `AssignModulus`, since both go + through `fp_div`, which drops the carry of `fp_mul_2d` when the normalised dividend does not + fit. +- Both need a dividend beyond the 4096 bits the class supports, which a product that + `AssignMultiplication` accepts can be. + +**To settle it:** a raise-or-right case in `OverflowTests.twin` (as +`Overflow_ModulusOfANumberThatFillsTheLibrary_RaisesErrorOrIsRight`), a second agent with the +verifier brief, then the BigNumber page's overflow WARNING and `expect.json`. diff --git a/WIP.ExamplesBuild.md b/WIP.ExamplesBuild.md index ce7302434..8fcfe58d8 100644 --- a/WIP.ExamplesBuild.md +++ b/WIP.ExamplesBuild.md @@ -428,6 +428,30 @@ sample that names it. One project per fence is unaffordable. What makes it tractable is that **IDE cost is flat in project size**: what is paid for is startup, not compilation. +**So a lane starts its IDE once.** Each lane holds an `IdeSession` +([scripts/lib/tb-session.mjs](scripts/lib/tb-session.mjs)) beside its slot, and every project +after the first opens in that IDE through the page's own File > Open Project. Before each switch +the session undoes the Safe Mode a crash loop leaves and the TRACE-MODE a native exception turns +on; a project that crashed the compiler is closed at once and never reopened in that IDE, and +its bisect halves, which are other projects, go to the same IDE. A failed switch, exit 2 and +exit 3 give the IDE up for a new one, and a project a reused IDE never reported open, or met a +harness fault in, is built again in a new IDE before its result counts. Why each of those, and +the measurements: [WIP.Harness.md](WIP.Harness.md#one-ide-per-project-or-one-per-lane). +`--fresh` starts a new IDE for every project, and is the control: a full run with it and one +without must report the same findings. The run's summary line says how many IDEs started and +how many projects were opened in one already running. + +**A batch that meets its limit is a finding, not the end of the run.** Its samples are not +judged, and it is not split: a slow template's batches meet the `compile` limit with no samples +in them, because the time is the template's load (WinReg's did, which is why its samples are not +marked). The run goes on, so one slow template cannot cost the +other batches their result. +The template built with no samples (`ownRowsOf`, which tells the template's own rows from +a batch's) is built once more when it meets the limit; met twice, the batch that asked is not +judged and the template is forgotten, so the next batch asks again. Taking that empty read as +a clean template blamed every sample of a package that does not compile on its own: a shared +`--fresh` run reported 17 ArrayListLib samples for the package's own TB5001 rows. + **Fill the lanes, not the batches.** Filling each batch to `--batch` before opening another would put 120, 55, 4 and 3 samples on four lanes, and a run takes as long as its biggest batch. The batcher sizes to `ceil(total / jobs)` instead. @@ -802,7 +826,10 @@ LLVM refusal is isolated, and its samples reported as failing the build, as any wedge and neither ever returns. Each lane owns a workspace, not just a slot. - **A run's folder is named for its process**, `tbexamples\`, so runs at once never share one; a later run removes the folders of runs whose process has ended, and leaves one - it cannot remove yet. Before each IDE ran in its launcher's job, a run that died left its + it cannot remove yet. A `--keep` run marks its folder with a `.keep` file from the start + (`keepRunFolder` in `scripts/lib/tb-registry.mjs`), and the sweep leaves a marked folder + for good; before that, a kept folder went within seconds of the next run starting. + `sweep_attributes.mjs` sweeps `tbsweep\` the same way. Before each IDE ran in its launcher's job, a run that died left its lanes' IDEs running on desktops nobody could see, holding that folder. - **Batches are packed in process by impexp** (`packTree` in `scripts/lib/tb-project.mjs`), never by the compiler executable's `import`, which exits 999 with nothing written on a diff --git a/WIP.Harness.md b/WIP.Harness.md index 833b03f5d..f14829655 100644 --- a/WIP.Harness.md +++ b/WIP.Harness.md @@ -541,21 +541,69 @@ Watching the page's traffic is another matter: CDP shows it to the harness with the wait for a compile ends on it (*How the wait for the compile ends*, above). The diagnostics still come from the IDE's own report walk. -### One project per IDE, and that is the scaling unit - -**Reusing a live IDE for a second project does not work.** `root.loadProject` against a -running IDE wedges it: `Runtime.evaluate` stops returning while browser-level CDP still -answers, and no javascript dialog is pending --- so the renderer is blocked inside a -synchronous host call, not on something dismissable. The IDE holds one project at a time and -closing the previous one is part of that path. - -So the cold start is not overhead to be optimised away; it is the unit of work. `tbbuild` -starting a fresh IDE per project is the design, not a convenience. - -**It costs less than it sounds like.** Measured: **6 to 8 seconds per project, and flat in -project size** --- a one-file template and the template that carries the whole of VBCCR both -land at about six seconds, because what is being paid for is IDE startup and not compilation. -Time it before quoting it. +### One IDE per project, or one per lane + +**`tbbuild` and `tbrun` start a fresh IDE per project; `check_examples` opens project after +project in one IDE per lane.** A tool that builds one project gains nothing from keeping its IDE. +For one that builds a hundred, the IDE's start is most of what it pays: **6 to 8 seconds per +project, and flat in project size** --- a one-file template and the template that carries the +whole of VBCCR both land at about six seconds. In a full `examples.bat` run on four lanes +(BETA 1010), each project's start and teardown took 1.94 s beside its compile wait. Time it +before quoting it. + +**The switch is the page's own File > Open Project** (`IdeSession`, +[scripts/lib/tb-session.mjs](scripts/lib/tb-session.mjs)). `openProject()` calls +`hostAppObject.OpenProject` (a native file dialog, which nobody can answer on a private +desktop) and then `closeProjectSafely(() => root.loadProject(path))`. The session replaces +`hostAppObject`, for that one synchronous call, with an object whose `OpenProject` returns the +path, and puts the real one back in the same evaluate. `closeProjectNow` ends the old compiler +(`root.forceTerminate`), and the restart's `isClosingProject` branch clears the console, unsets +`projectFilePath` and runs the callback, which loads the new project in a new compiler. A changed +project first gets the page's own HTML modal (*Save now?*), which the session answers Discard +Changes; no switch in the measurements below found a project changed (0 of 158). File > Close +Project (`tbProject_Close`) sends the compiler nothing and ends it with `taskkill`. + +**`root.loadProject` called over CDP is not a switch** (BETA 1010, the shipped IDE and tblaunch +alike): it skips `closeProjectSafely`, so it sends a second LoadProject on the compiler +connection that still holds the old project. The page loads the new project's saved state, but +the tree keeps the old project; the page stays responsive and shows no dialog. The page also +holds about 90 `debugger;` statements, `openProject`'s callback among them: a CDP client with +the Debugger domain enabled stops at them, which looks like a hang. + +**Measured** (BETA 1010, the 74 batch projects of a full `examples.bat` run, and a set of +probe projects: errors, an embedded package, a compiler crash, `[RunAfterBuild]` runs that +print, raise an access violation, run `End` and raise an unhandled error). Every project gave +the same diagnostics and run output after a switch as in a fresh IDE, once the resets below +were in place. One after another, the 74 took 351 s in fresh IDEs and 213 s in one IDE; on four +lanes at once, 134 s (the `examples.bat` run itself, 71 of them) against 72.6 s. In a switch the +new compile starts about 1.4 s after `openProject()`. Over 74 switches the IDE's processes stayed +at 13, its working set between 0.99 and 1.25 GB with no trend, its temp folder at 2 or 3 files; a +`Static` in a `[RunAfterBuild]` Sub read 1 on every visit, since each project has a new +compiler process; the registry's association, `IDESettings` and recent list were unchanged. + +**What a project leaves in the IDE, and the session undoes before each switch:** + +- **Safe Mode.** After a compiler crash loop the build box reads `nocompile`, and the page's + `loadProject` keeps the target when it does: every project opened after it read as a crash. The + remedy (owner): close the project, set the box to win32 with no project open, then open the + next (0.22 s). The compiler's pid does not change when the box is set with no project open, so + nothing waits for one. A project that put the IDE into Safe Mode crashes back into it when it + is opened again, so it never is; a bisect half is another project and goes to the same IDE. +- **TRACE-MODE.** Any native exception, at compile or in a run, sets the page's `g_TraceMode` for + the rest of the session, and each new compiler starts with it (`RequestPreInitialize`). A later + crash then prints a thread dump where a fresh IDE prints two `[IDE] auto-activated TRACE-MODE` + lines. The session sets it back to false: the Help menu's toggle without its restart. +- **The harness's own page state.** `keepClears` starts a new record on each call + (`tb-ide-console.mjs`), because the close clears the console and that clear is the last + project's. `compileProject` reports the page's dialogs from a mark it takes after the switch. + +**When the session gives its IDE up.** A switch that fails (the page does not answer, the IDE +has ended, `openProject()` did not ask for a path), a harness fault (2) and a compile that never +settled (3) end the IDE by its pid, and the next project starts cold. A project opened by a +switch that ended in a harness fault, or that the IDE never reported open, is built again in a +new IDE before its result counts. A compile that met its limit after the project opened is not: +WinReg's batches meet it in a fresh IDE as well. A compiler crash (4) is recovered in place: the +project is closed at once, so that its compiler stops restarting. **Concurrency works and is the route to a fast probe suite.** Each run takes a slot from `tbbroker` ([WIP.Broker.md](WIP.Broker.md)) --- a private desktop, and the number its WebView2 @@ -881,8 +929,9 @@ What it showed on BETA 1010 (350 compiles: `check_examples --build` and `--llvm` `addin_test` lane, `tbbuild`/`tbrun` probes on both arches), median / p95 / max in seconds: IDE start to project open 2.85 / 3.46 / 4.04; the compiler's own compile, `compilationStarted` to the last file's diagnostics, 0.03 / 0.08 / 0.30; the whole compile wait, project load included, 3.33 / 5.34 / -13.8, its tail the 5 s stand-still `waitForCompile` needs when a package's own files have errors -(WinReg, ArrayListLib), where the early path never agrees; a build, Build pressed to linked, at +13.8, its tail the compiler's start-up for a project that embeds a large package (WinReg, +ArrayListLib; the early path now agrees for a package whose own files have errors, by adding the +panel's rows of files the wire does not report on, `unlistedRows`); a build, Build pressed to linked, at most 1.0 (4.97 with LLVM); a `[RunAfterBuild]` run at most 0.83 (25.3 with LLVM, one of them printing for 15 s and finishing). None reached a timeout. diff --git a/WIP.PackageTests.md b/WIP.PackageTests.md index 0ac57d26c..00939a5c2 100644 --- a/WIP.PackageTests.md +++ b/WIP.PackageTests.md @@ -52,8 +52,7 @@ hand-kept list of calls drifts from the cases; the gate refuses a stale one. ## A case that never returns -Some defects are a loop that never ends (BigNumberLib's modular inverse of zero, TBMANLIB_Xml on -some malformed text). In test mode such a case holds the compiler: `tbrun` gives up on it after +Some defects are a loop that never ends (TBMANLIB_Xml on some malformed text). In test mode such a case holds the compiler: `tbrun` gives up on it after its timeout, and every case after it would time out too. So the runner, on a case that does not return, records it and runs the cases after it again in a new IDE; once `expect.json` says `hangs`, the case is run alone with a short timeout, and `RunAll` skips it, because an author's diff --git a/WIP.Screenshots.md b/WIP.Screenshots.md index 70662e7a9..07d78089e 100644 --- a/WIP.Screenshots.md +++ b/WIP.Screenshots.md @@ -87,7 +87,9 @@ Measured: run before the first capture and again when a capture is chosen, with the SVG under `--svg`: the page can draw again in between, as Project Settings does, putting the real build path back over the template a shot had set in the page only (a shot that sets a - value types it, `input` and `change`, so the page keeps it). + value types it, `input` and `change`, so the page keeps it). The `settings` setups open + their project with the templates' own build path (`startSettings`), so that a row drawn + again holds no user name either: `llvmdoc1` failed the check now and then without it. ## Capture @@ -107,13 +109,24 @@ Measured: between versions a few pixels apart by 1-14 grey levels: dialog shadow edges, the status bar's scaled Ko-fi bitmap, panel dividers, rounded corners. `captureBeyondViewport` and `fromSurface: false` are stable but drop the scrollbars and the cut-outs' alpha, so neither is - usable. `capture` waits 1 s before the first capture (without it rounded-corner pixels come out a - grey level off and stay so), then takes up to 8, 150 ms apart: it keeps one equal to the file on - disk, else the first two in a row that agree, and fails if none agree. So a picture is rewritten - when the IDE draws something different, not when the noise flips. + usable. Measured on BETA 1010 (launcher-re, `plan/PLAN-webview-ide.md` section 24: 194 shots, + about 35,000 captures, alone and with six IDEs at once), a picture of a still state is final at + its first capture once the page is quiet and two frames are drawn. So `capture` has no rest: it + captures back to back until one equals the file on disk or two in a row agree, and a picture + that has not changed costs one capture. **A picture two captures agree on that is not the file + is not kept at once** (owner): `capture` captures on at `CAPTURE_GAPS` (150 ms rising to 1.5 s) + until one equals the file or 5.5 s have gone, and keeps the last two that agreed. Keeping it at + once failed a second run on BETA 1010, in two ways: a raster drawn in several versions that + turn over in the idle time between captures, not under captures back to back (the striped + ground round a designer, 47,000 pixels apart; About's gradient boxes, dithered 10,000 pixels + apart; a submenu's shadow corner; the splash's rounded corner, 4 pixels by many levels); and + a state still on its way when the shot's own condition is met (Rename_Box's box red for a + moment, a designer readout fading in), which the old 1 s rest had hidden. With no two + agreeing in 5.5 s it fails. So a picture is rewritten when the IDE draws something different, + not when the noise flips, and a changed picture costs about 5.5 s. Under the full parallel load a run now and then settles on the other version of one or two pictures (1-3 grey levels, a few pixels to a few hundred along an edge) and keeps it through - every capture, so a longer wait in `capture` does not help; each is unchanged when its setup + every capture, so longer captures in `capture` do not help; each is unchanged when its setup runs alone, and which one varies from run to run. So **a picture within a capture's noise of its file is left as it is** (`nearly`: one size, no channel more than 16 levels apart, at most 0.5% of the pixels apart), reported `unchanged but for a capture's noise`, with a `.noise` @@ -126,7 +139,18 @@ Measured: so the flicker never rewrites the file. Use it for a pixel no condition settles, as small as the element allows: the WebView2 download page's Version arrow (`#version .px-dropdown__icon`, 8 by 9) changes a pixel by more than the noise between any two - captures, animations and transitions off. A shot without it compares byte for byte. + captures, animations and transitions off. So do the two "See your logo here!" boxes of About + and the splash (owner; `VIP_GOLD_SPARES`, the last two `.vipGoldX`): their gradient is + dithered differently from capture to capture, a level or two over thousands of pixels, + beyond a capture's noise. So does the time of the GitHub release's zip ("8 hours ago", + "yesterday"; owner), which moves on by itself: an `{rect}` from the Assets list's + `relative-time`, widened leftward to the widest it is drawn, since it is right-aligned. So + do the splash's four rounded corners in the dark theme (owner; 4 by 4 CSS px each: 4 pixels + flipped), and the shadow round each TabIndex circle of Designer_TabIndex (owner; + `tabIndexRings`, a ring from 2 px inside the circle to 6 px beyond it, so the number is still + compared): the shadow over the grid's dots is dithered in one of two versions, about 600 + pixels apart, the same two bytes for bytes in every run. A shot without it compares byte for + byte. - **Settle by condition, not by sleep.** Fixed sleeps would be most of a run (a closed menu leaves a 2x8 px empty `#contextMenu`, so a wait for it to vanish always runs out its 2 s). A menu is closed when it holds no items; a dialog is still when a MutationObserver has seen no @@ -179,7 +203,10 @@ Exit codes: 0 every picture written or unchanged, 1 a picture failed, 2 the tool - **Setups**: one IDE each --- `no-project` (menus, dialogs, panels), `help` (the add-in's eight, `test/addin/helpdemo`), `project`, `sample`, the `settings` setups, `glyphs`, `global-search` (Sample 15 exported from the install, built into the lane's copy as an add-in, its own project - opened), `sample6` (Sample 6 exported and opened) and `designer` (the sample fixture with + opened; once a search settles, its results list is told through its own `notifyChangedItem` + that every row changed, so that it measures them again (owner): it keeps a row's height from + its first measure and sets its scroll range from those, and under load a thumb showed over + two results that fit), `sample6` (Sample 6 exported and opened) and `designer` (the sample fixture with `test/shots/designer/` staged onto it, plus the Global Search add-in for Toolbar_3; it sets the page's `currentDPI` to the 2x ratio, or the IDE's 5 s DPI check covers every designer with RESYNC), and `forms` (the same without the add-in), `community` (the demo, its compiler @@ -194,8 +221,8 @@ Exit codes: 0 every picture written or unchanged, 1 a picture failed, 2 the tool - **Jobs**: `--jobs N` (default 6) runs setups at once, each IDE in a slot of its own from `tbbroker` (a private desktop; the help setup's slot also carries the detached window's port) with a DevTools port Windows picks, and splits the big setups into parts, longest first; a full run with `--svg` is - about 17 minutes in both themes on BETA 1005: the jobs add up to about 5,900 s, and the longest - part, `forms-chapter`, takes about 450 s on its own, so six IDEs cannot do much better. + about 12 minutes in both themes on BETA 1010: the jobs add up to about 4,100 s, and the longest + part, `forms-chapter`, takes about 270 s on its own, so six IDEs cannot do much better. `--jobs 1` runs one IDE per setup in table order. Per-run state lives on the connection (`c.shot`), never in module variables. - **Diffs**: `--diffs ` (never under `docs/`) writes, for each picture that differs from the @@ -417,6 +444,63 @@ none, which `New Project.md` also shows). button before the export, and emptied again afterwards; the shot is the setup's last. The times are set in the page (`fixConsoleTimes`). Both lines fit with no scrolling. +## The "Building" chapter + +Six setups, their fixtures under `test/shots/building/`, copied from the Building lanes' +`test/ide/probes/building-{exe,ax,pkg}`: `exe` is Program, a Standard EXE whose Sub Main waits a +minute (so that a second build finds its file in use), `ax` is ShotActiveX, an ActiveX DLL whose +class has GUIDs of its own (`B01D...B001` to `B003`, not the lanes', so that a lane and a shot run +at once never share a registration), and `pkg` is MyPackage, a PRIVATE package. Each project is +staged in a folder of the tool's own on `PACKAGE_ROOT` named for its setup (`C:\tbshots\Building` +and so on), with the templates' build path, so that a console line names no user; the setup's +`end` removes the folder once its IDE has ended. Its 14 pictures +are under `docs/IDE/Building/Images/`. + +- **`building`** (exe): the console after a build, a failed build and a build refused by the + running exe, the configuration box's list, and the safe-mode box. **`building-new`**: an IDE with + no project, then New Project's Standard EXE tile, Open and Continue, for the box Build opens on a + project with no file. **`building-ax`**: Clean after a build of `ax`. **`building-hklm`**: `ax` + with Register DLLs to HKLM, packed before an IDE with no project starts and opened from the + Recent list by the warning's picture (the IDE is not elevated, so nothing registers). + **`building-llvm`**: `exe` with `+llvm`. **`building-pkg`**: `pkg`. +- **The console is floated 900 wide and grown a row at a time until the picture's lines show + whole** (`fitConsole`): its rows are in a `.listItems` box that clips them, and its list keeps + copies of rows that are not shown, so a row or a link is judged by where it is drawn + (`elementFromPoint` for a link). Then it settles, and only then are its times set in the page, + and the LOCKED BY pid set to 4120 (the page's own example): a resize draws the rows again. +- **The console's scroll bar thumb is put at the top of its track in the page** + (`fixConsoleThumb`). Its lines fit, so the thumb is the track's whole height, but the console + leaves it a few pixels up or down where an earlier length of the list put it, differently from + run to run; the shot fails if the thumb is not the whole track. +- **The IDE behind the console is hidden for the capture**, its ancestors' other children marked + and set `visibility: hidden`, on a ground of the panel's colour, with no shadow. The SVG + otherwise draws the IDE under the panel, and the editor there is laid out a pixel taller or + shorter from run to run. It is not a cut-out (`keep`): that sets everything inside the panel + visible, and the console's hidden copies of its rows would show over the real ones. +- **The locked exe is started with Launch EXE** (a real click; the compiler runs it on the IDE's + desktop) and ended with Terminate after the capture; the shot waits for the exe's end by its pid + and the console's `exited` line, and ends it by its pid if it still runs. +- **Safe_Mode** opens the box with a click and chooses with Down and Enter, twice (win64, then + safeMode, each a compiler restart), and goes back with Ctrl+F2. **Configuration_List** is the + toolbar's group between its splitters, the list a replica (`listClip`); the Light theme's list + is shorter. +- **Every ActiveX build is followed by Clean**, in a `finally`. The HKLM project's Clean shows the + Delete It And Continue box, whose Cancel stops it, and the DLL (registered nowhere) is deleted from + the setup's folder. A setup's `end`, run once its IDE has ended, checks that none of the + fixture's keys (`axShotKeys`: class, interface, type library and ProgID, both views, HKCU and + HKLM) exists, and reports one that does; nothing removes a key. +- **Compiling** holds the build's last progress event (-1) in the page until the capture, so the + box stays at the 0.0% the compiler sends before it (LLVM sends no other value). The setup leases + the LLVM cache before its IDE starts (`holdLlvmCache`) and its `end` releases it; a Community or + Personal licence fails the setup. +- **Nothing reaches the package server**: `building-pkg` installs the Building lanes' `guard` + (CDP blocks `*everythingaccess*`, the page's XMLHttpRequest and fetch send nowhere and record), and + each picture fails on a recorded request or a `[PUBLISH] attempting` line. The saved publisher + name and password are emptied in the page; Publish_Confirm sets a made-up publisher + (`ExamplePublisher`) and a session id in the page and cancels the box; Publish_Result is the + IDE's own `showModalNotification` with the success text. The pane floats at the bottom left, out + from behind the boxes. + ## Special IDE states - **`Services_Unavailable`**: the badge in the `no-project` setup. With no project the badge's @@ -485,8 +569,11 @@ none, which `New Project.md` also shows). About 0.5 s a call (a PowerShell start). The IDE's window class is `ThunderForm`; the Webpage pane's second WebView2 is a `Chrome_WidgetWin_1` child (title `Google`) of zero size until the pane shows. The capture also returns the visible frame (`DWMWA_EXTENDED_FRAME_BOUNDS`), the - client area and a layered window's key and alpha. `tb-launch.ps1` is 28,576 characters of the - 30,000 its environment variable allows. + client area, a layered window's key and alpha, and whether the caption is drawn active + (`WS_ACTIVECAPTION`). `activateWindow(desktop, hwnd)` makes a window the active one of its + desktop (its thread's input attached for `BringWindowToTop`, `SetForegroundWindow`, + `SetActiveWindow` and `SetFocus`) and says whether its caption then is. `tb-launch.ps1` is + 24,771 characters, its comment lines emptied, of the 30,000 its environment variable allows. ## Pictures of a running program @@ -507,7 +594,9 @@ none, which `New Project.md` also shows). it and loses it again now and then, and one run from the IDE never gets it, so the form draws its frame as active (`WM_NCACTIVATE`) whenever it is not the foreground window; and no control takes the focus (`TabStop` off), since a focused one drew a caret or, now and then, a focus - rectangle. With both, repeated runs are unchanged. + rectangle. Even so a form drew its caption inactive now and then (4829696d and 599a66ad, one + run each), so `programShot` makes the form the active window (`activateWindow`) before its + captures and again whenever a capture finds the caption inactive (owner). - **85f25aa2** (Opacity 75, TransparencyKey red): `PW_RENDERFULLCONTENT` draws the key colour black and every pixel opaque, so the tool reads the key's pixels from a client-only capture (flags 1) and gives the picture the window's own alpha (191) and alpha 0 there: the page is @@ -546,7 +635,7 @@ none, which `New Project.md` also shows). ## Package server -Taken on BETA 1005, in both themes where the theme shows. +Taken on BETA 1010, in both themes where the theme shows. - **Setup `package-server`**: the sample with `test/shots/packages` (Greeting, a class to type `fmt.` into), signed out, TWINSERV's live list. Its APPDATA is `PACKAGE_ROOT\AppData\Roaming`, @@ -586,7 +675,10 @@ Taken on BETA 1005, in both themes where the theme shows. spinner no two captures hold alike. **`e2a65dfe`**: the completion list is the IDE's own (`.debugConsoleEntryIntellisenseBox`), shows types as `...` until the compiler gives them (now and then never: the dot is retyped), and is placed by the list the name before the dot - opened unless that is closed first. + opened unless that is closed first. It is 500 px wide (its CSS); `triggerIntellisense` + places it at the text cursor's box as drawn at the time, which is at the dot or, now and then, + already after it (the picture 1198 px wide against 1184): the shot moves it to where the + cursor's box stood at the dot (owner). - **Compiler crash, not narrowed**: about 3 runs in 10 of the setup, an Apply that embeds or removes CSharpishStringFormater meets `NATIVE EXCEPTION: ACCESS_VIOLATION {no-basic-code} [twinBASIC_win32.dll+0010BD3F]`; ten probe cycles of the same steps did not reproduce it. Not @@ -596,7 +688,7 @@ Taken on BETA 1005, in both themes where the theme shows. ## Not of the IDE -Taken on BETA 1005. +Taken on BETA 1010. - **`16833fae`** (setup `import`): the sample open, and `test/shots/vbp` (ImportDemo: a form, a module, `..\Shared\modShared.bas` for `{PARENT-FOLDER}`) staged with CRLF on @@ -643,6 +735,11 @@ Taken on BETA 1005. user's choices and nothing is written to the registry. - **About's licence line**: the tool waits for `licenceIsSet` before opening About, so it shows the edition, never NOT READY. +- **The window is shown maximized** (owner): the title bar's Restore button, not Maximize, + whatever the user's own IDE window was. `PAGE_DEFAULTS` calls the page's + `cefWindowChangeNotification("WINDOW-MAXIMIZED")`, what the host calls when it maximizes the + window; the window itself is left alone, since the IDE saves its place in the registry + (the `Window` key) whenever it is maximized or restored. - **The language tick** stays on whatever language the IDE runs in. - **`llvmdoc2`** shows the default thread count, 1. @@ -817,6 +914,13 @@ the PNG was just captured from, and the build shows it in place of the PNG - **The bar** (`SVG_FAITHFUL` in `shoot_docs.mjs`): an SVG with more than 0.25% of its pixels 96 grey levels or more off is not written, and an older one is removed. Anything not drawn falls to it. +- **An SVG changes with its PNG** (owner). The SVG of a picture whose PNG is not rewritten + (unchanged, or within a capture's noise) stays as it is, with its bundle, when there is one: + it is drawn from the whole page, layers the picture does not show included, and those + differ from run to run (PackagePublishing_1, a floating panel over a form designer still + drawing; CallStack_Frames.light), and one sitting on the bar (Properties_SystemColours.light + at 0.251%, 94490c87) was written in one run and removed in the next. `replay.mjs` draws it + again after a change to the converter. - **One line** (`oneLine`). Git checks a picture's SVG out with CRLF where `core.autocrlf` says so, since no `.gitattributes` rule can tell it from a diagram's SVG. An SVG icon embedded as text and the annotation layer's XML hold line breaks; so each is written as the space an XML diff --git a/WIP.md b/WIP.md index fe879f4d9..ff49f7c8b 100644 --- a/WIP.md +++ b/WIP.md @@ -38,7 +38,7 @@ sibling. History goes nowhere: git keeps it. Reference documentation is **complete** for all thirteen packages: VBA, VBRUN, VB, WebView2, Assert, CustomControls, CEF, WinEventLogLib, WinNamedPipesLib, WinServicesLib, tbIDE, WinNativeCommonCtls and AppGlobalClassObject. It is adapted from primary sources: Microsoft VBA-Docs (CC-BY-4.0) for the runtime library, `.twin` source for the twinBASIC-specific packages. The CEF and WebView2 packages also carry a tutorial set. -Twenty-seven **contributed** packages from TWINSERV have sections under `docs/Reference/Contributed/`: ArrayListLib, DetoursLib, FileProps, Fmt, Generics, OLEGuids, WinReg, TwinTimerLib, tbFileSysTools, TBMANLIB, TBMANLIB_Aes, TBMANLIB_ConsoleComponents, TBMANLIB_ConsoleCore, TBMANLIB_Diagnostic, TBMANLIB_Dialog, TBMANLIB_ListBoxHScroll, TBMANLIB_RES, TBMANLIB_Xml, tbProjPacker, tbRegExp, tsJson, tsPwGen, VBA_JSON, xCalendar, AutoCompleteLib and VBComDlg complete; BigNumberLib its main class only. TBMANLIB_ConsoleCore's console claims are checked by its test cases, each on a console screen buffer of its own with its input written by `WriteConsoleInput`; TBMANLIB_ConsoleComponents' follow the source, because the samples harness cannot capture a console. Generics (seven tuple classes) and xCalendar (one control) are each one page (owner), so `analyze` in audit mode lists their classes and members as undocumented. What xCalendar's page says it does at run time comes from `test/package-tests/xCalendar/probe/`, which runs the control on a form in a built exe. Fmt documents its test code (`HelloWorldClass`, `HelloWorldModule`, `Pootle`) in one paragraph of its landing page, which `exclude_from_docs` names; Generics' `exclude_from_docs` names its test code, `HelloWorldModule`, which the page does not mention. VBComDlg's `exclude_from_docs` names `CommonDialogBase`, and AutoCompleteLib's `AutoCompleteHandle`, each a module whose public procedures only its class calls. DetoursLib's names its demonstration module, `DetoursTest` (message boxes), which its landing page describes in a paragraph. Its test cases run in the IDE's own process, so each detours `MulDiv` of kernel32 and answers for itself only for one marked argument, passing every other call (another thread's included) to the original. `CreateDetourAtFuncAddress` does not check a *newAddress* of 0, and SlimDetours then reads address 0 inside a transaction that has the process's other threads suspended; no case tries it, since it would leave the IDE frozen, and the page states the missing check from the source alone. tbRegExp's `exclude_from_docs` names its private engine module, `StaticRegex`, and tbProjPacker's its helper modules, `modImpExp` and `modWin32`: the indexer counts a Public Enum as public even inside a Private Module, because a built-in package's are reached through its library symbol written with an asterisk (`*WinNativeCommonCtls`, as `ImlDrawConstants` says). By its bare name no such enum is reachable, in a built-in or a contributed package (TB5079 on BETA 1010). OLEGuids documents each interface's methods on the interface's page. What TBMANLIB_Dialog's pages say its dialogs do comes from `test/package-tests/TBMANLIB_Dialog/probe/`, which operates them in a built exe on a private desktop; run it again when the package's version changes. TBMANLIB_Dialog 1.1.0.0 has a page of its own for each class except cDialog, which keeps a page for each member, so `analyze` in audit mode lists the members of those one-page classes as undocumented; its `exclude_from_docs` names its test module, `TestModule`, and the seven COM interface declarations that cDialogEx calls inside (`IOleWindow`, `IModalWindow`, `IShellItem`, `IShellItemArray`, `IFileDialog`, `IFileOpenDialog`, `IFileSaveDialog`), which its landing page describes in a paragraph. cDialogEx 1.1.0.0 returns the name of the chosen file, not its path, ignores `InitialDir` and ignores a `Filter` that has no closing pipe, each documented as a WARNING. tbRegExp is the first section drafted by the doc-draft workflow ([WIP.Indexer.md](WIP.Indexer.md#draft-and-the-doc-draft-workflow)), then reviewed against the sources, the package's README and VBScript's own **RegExp** under `cscript`. tbRegExp 1.9.0.0 raises `vbObjectError + 3016` from a search that uses up its step budget and returns nothing (1.8.0.0's `SearchAborted` is gone); the budget is 10 steps for each character squared, at least 1,000,000 and at most 100,000,000, for the search of one match, and `RegExp.SearchStepLimit` replaces it with a fixed number, documented on its own page and in a section of the landing page. On the dev box (BETA 1010, win32) `\d+x` costs 2.0 × n² steps (2.002 to 2.009 for 500 to 2,000 digits), so it finishes on 7,000 digits (16 s) and raises on 10,000 (16 s); `(a+)+b` raises in 0.2 s on 30 or 300 `a` but takes 16 s on 3,000; `a*` matches 1,000,000 characters whole in about half a second. Its pattern syntax has a page of its own, `PatternSyntax.md`. Each one that is not Experimental has a chapter in the book's Packages part; the Experimental ones are left out of the book. **ArrayListLib, BigNumberLib, GdiPlus, TBMANLIB, TBMANLIB_Aes, TBMANLIB_ConsoleComponents, TBMANLIB_ConsoleCore, TBMANLIB_Diagnostic, TBMANLIB_Dialog, TBMANLIB_ListBoxHScroll, TBMANLIB_Xml, WinReg and xCalendar are listed under Experimental Packages** (`docs/Reference/Experimental.md`, owner): ArrayListLib and WinReg do not compile on BETA 1010 (each documented from its source and a copy of it that builds, its samples compile-only; in a copy of ArrayListLib 1.6.151.1 with the arguments of its three `VSwap` calls passed `ByVal` and `LSetByVal` taking a `LongPtr`, a For Each over a list with no items fails, ToString of such a list never returns, Reverse keeps the middle pair of an even run in place and a second GetEnumerator over a list ignores its arguments; in a copy of WinReg's source with its four failing calls passed `ByVal`, ReadString, GetRegistryValueType and the first ConvertValueToString give wrong results), xCalendar has a grid that keeps the old month's dates when Value is set to another month, and text colour properties that have no effect, BigNumberLib 1.0.2.0 compiles, but loses the minus sign after `IsNegative = True` and in a negative operand of the greatest common divisor and the least common multiple, makes a zero from `AssignFromLong` negative, and does not return from the modular inverse of zero (all four confirmed by a second agent), TBMANLIB 1.0.0.29 does not compile in a 64-bit build (TB5001 in cSubClass, where the window procedure is passed as a Long) and has many members that fail or give wrong results, TBMANLIB_ConsoleComponents cannot take a cConsole of the published TBMANLIB_ConsoleCore (it embeds a copy of it, the same package at 1.0.0.1, whose types the compiler treats as different; checked in a project made by the IDE's own import, in either order), TBMANLIB_ConsoleCore reads keys wrongly, TBMANLIB_Diagnostic cannot create its Dictionary and misplaces List items, TBMANLIB_Dialog 1.1.0.0 has classes that fail at their main task (cDialogFindReplace reports nothing, cDialogPageSetup ignores paper and orientation, cDialogEx returns names without their folder, cDialogPassword shows the password in its confirmation boxes; every defect confirmed by a second agent, owner), TBMANLIB_ListBoxHScroll 1.0.0.1 moves the thumb 20 px per arrow and one page per track click while the list box scrolls its contents by its own step, so thumb and text disagree (confirmed by a second agent, owner), TBMANLIB_Aes runs other cipher modes than the ones named (its default CBC is ECB) and fails the NIST test vectors, and TBMANLIB_Xml's parser misreads self-closing elements and entities and does not return for some malformed text (and its XPath engine reads the step `..` and `and` with `or` wrongly). TBMANLIB_Xml's `exclude_from_docs` names its test module, `mXmlTests`, which its landing page describes in a paragraph, and the five types of its XPath engine (`XPathTokenType`, `XPathAxisType`, `XPathOperator`, `XPathStep`, `XPathPredicate`), which no public member takes or returns and which the mXPath page mentions in a paragraph; tsPwGen's names its five test modules and its six internal modules, and tsJson's its test and internal modules likewise, which their landing pages describe in a paragraph each. TBMANLIB_Diagnostic's `List` page has a NOTE labelled BETA 1010 under its `SetItem` sample: in a 32-bit IDE run `Err.Description` of the error 5 that `SetItem 0` raises on a list of one item (`Dim x As New List(Of String)`) is "Automation error", while the exe, a 64-bit IDE run and VB6 give "Invalid procedure call or argument" (`bugs/list-error5-automation-text`, with its case `ListTests.SetItem_AtZeroOnOneItemList_ErrorHasTheRuntimeText`). The samples harness runs in the IDE and has no per-sample way to state output that differs from an exe's, so that sample prints `Err.Number` only and the text is in the NOTE; when the entry is retired the NOTE goes and the sample prints `Err.Description` again, with the output `5: Invalid procedure call or argument`. See *Where things live* for how a package moves between the two lists. +Twenty-seven **contributed** packages from TWINSERV have sections under `docs/Reference/Contributed/`: ArrayListLib, DetoursLib, FileProps, Fmt, Generics, OLEGuids, WinReg, TwinTimerLib, tbFileSysTools, TBMANLIB, TBMANLIB_Aes, TBMANLIB_ConsoleComponents, TBMANLIB_ConsoleCore, TBMANLIB_Diagnostic, TBMANLIB_Dialog, TBMANLIB_ListBoxHScroll, TBMANLIB_RES, TBMANLIB_Xml, tbProjPacker, tbRegExp, tsJson, tsPwGen, VBA_JSON, xCalendar, AutoCompleteLib and VBComDlg complete; BigNumberLib its main class only. TBMANLIB_ConsoleCore's console claims are checked by its test cases, each on a console screen buffer of its own with its input written by `WriteConsoleInput`; TBMANLIB_ConsoleComponents' follow the source, because the samples harness cannot capture a console. Generics (seven tuple classes) and xCalendar (one control) are each one page (owner), so `analyze` in audit mode lists their classes and members as undocumented. What xCalendar's page says it does at run time comes from `test/package-tests/xCalendar/probe/`, which runs the control on a form in a built exe. Fmt documents its test code (`HelloWorldClass`, `HelloWorldModule`, `Pootle`) in one paragraph of its landing page, which `exclude_from_docs` names; Generics' `exclude_from_docs` names its test code, `HelloWorldModule`, which the page does not mention. VBComDlg's `exclude_from_docs` names `CommonDialogBase`, and AutoCompleteLib's `AutoCompleteHandle`, each a module whose public procedures only its class calls. DetoursLib's names its demonstration module, `DetoursTest` (message boxes), which its landing page describes in a paragraph. Its test cases run in the IDE's own process, so each detours `MulDiv` of kernel32 and answers for itself only for one marked argument, passing every other call (another thread's included) to the original. `CreateDetourAtFuncAddress` does not check a *newAddress* of 0, and SlimDetours then reads address 0 inside a transaction that has the process's other threads suspended; no case tries it, since it would leave the IDE frozen, and the page states the missing check from the source alone. tbRegExp's `exclude_from_docs` names its private engine module, `StaticRegex`, and tbProjPacker's its helper modules, `modImpExp` and `modWin32`: the indexer counts a Public Enum as public even inside a Private Module, because a built-in package's are reached through its library symbol written with an asterisk (`*WinNativeCommonCtls`, as `ImlDrawConstants` says). By its bare name no such enum is reachable, in a built-in or a contributed package (TB5079 on BETA 1010). OLEGuids documents each interface's methods on the interface's page. What TBMANLIB_Dialog's pages say its dialogs do comes from `test/package-tests/TBMANLIB_Dialog/probe/`, which operates them in a built exe on a private desktop; run it again when the package's version changes. TBMANLIB_Dialog 1.1.0.0 has a page of its own for each class except cDialog, which keeps a page for each member, so `analyze` in audit mode lists the members of those one-page classes as undocumented; its `exclude_from_docs` names its test module, `TestModule`, and the seven COM interface declarations that cDialogEx calls inside (`IOleWindow`, `IModalWindow`, `IShellItem`, `IShellItemArray`, `IFileDialog`, `IFileOpenDialog`, `IFileSaveDialog`), which its landing page describes in a paragraph. cDialogEx 1.1.0.0 returns the name of the chosen file, not its path, ignores `InitialDir` and ignores a `Filter` that has no closing pipe, each documented as a WARNING. tbRegExp is the first section drafted by the doc-draft workflow ([WIP.Indexer.md](WIP.Indexer.md#draft-and-the-doc-draft-workflow)), then reviewed against the sources, the package's README and VBScript's own **RegExp** under `cscript`. tbRegExp 1.9.0.0 raises `vbObjectError + 3016` from a search that uses up its step budget and returns nothing (1.8.0.0's `SearchAborted` is gone); the budget is 10 steps for each character squared, at least 1,000,000 and at most 100,000,000, for the search of one match, and `RegExp.SearchStepLimit` replaces it with a fixed number, documented on its own page and in a section of the landing page. On the dev box (BETA 1010, win32) `\d+x` costs 2.0 × n² steps (2.002 to 2.009 for 500 to 2,000 digits), so it finishes on 7,000 digits (16 s) and raises on 10,000 (16 s); `(a+)+b` raises in 0.2 s on 30 or 300 `a` but takes 16 s on 3,000; `a*` matches 1,000,000 characters whole in about half a second. Its pattern syntax has a page of its own, `PatternSyntax.md`. Each one that is not Experimental has a chapter in the book's Packages part; the Experimental ones are left out of the book. **ArrayListLib, GdiPlus, TBMANLIB, TBMANLIB_Aes, TBMANLIB_ConsoleComponents, TBMANLIB_ConsoleCore, TBMANLIB_Diagnostic, TBMANLIB_Dialog, TBMANLIB_ListBoxHScroll, TBMANLIB_Xml, WinReg and xCalendar are listed under Experimental Packages** (`docs/Reference/Experimental.md`, owner): ArrayListLib and WinReg do not compile on BETA 1010 (each documented from its source and a copy of it that builds; ArrayListLib's samples are compile-only, and WinReg's are not marked `check_build` at all, because under four lanes its template's compile outruns the 10 s limit: mark them again when a version of WinReg compiles; in a copy of ArrayListLib 1.6.151.1 with the arguments of its three `VSwap` calls passed `ByVal` and `LSetByVal` taking a `LongPtr`, a For Each over a list with no items fails, ToString of such a list never returns, Reverse keeps the middle pair of an even run in place and a second GetEnumerator over a list ignores its arguments; in a copy of WinReg's source with its four failing calls passed `ByVal`, ReadString, GetRegistryValueType and the first ConvertValueToString give wrong results), xCalendar has a grid that keeps the old month's dates when Value is set to another month, and text colour properties that have no effect, TBMANLIB 1.0.0.29 does not compile in a 64-bit build (TB5001 in cSubClass, where the window procedure is passed as a Long) and has many members that fail or give wrong results, TBMANLIB_ConsoleComponents cannot take a cConsole of the published TBMANLIB_ConsoleCore (it embeds a copy of it, the same package at 1.0.0.1, whose types the compiler treats as different; checked in a project made by the IDE's own import, in either order), TBMANLIB_ConsoleCore reads keys wrongly, TBMANLIB_Diagnostic cannot create its Dictionary and misplaces List items, TBMANLIB_Dialog 1.1.0.0 has classes that fail at their main task (cDialogFindReplace reports nothing, cDialogPageSetup ignores paper and orientation, cDialogEx returns names without their folder, cDialogPassword shows the password in its confirmation boxes; every defect confirmed by a second agent, owner), TBMANLIB_ListBoxHScroll 1.0.0.1 moves the thumb 20 px per arrow and one page per track click while the list box scrolls its contents by its own step, so thumb and text disagree (confirmed by a second agent, owner), TBMANLIB_Aes runs other cipher modes than the ones named (its default CBC is ECB) and fails the NIST test vectors, and TBMANLIB_Xml's parser misreads self-closing elements and entities and does not return for some malformed text (and its XPath engine reads the step `..` and `and` with `or` wrongly). TBMANLIB_Xml's `exclude_from_docs` names its test module, `mXmlTests`, which its landing page describes in a paragraph, and the five types of its XPath engine (`XPathTokenType`, `XPathAxisType`, `XPathOperator`, `XPathStep`, `XPathPredicate`), which no public member takes or returns and which the mXPath page mentions in a paragraph; tsPwGen's names its five test modules and its six internal modules, and tsJson's its test and internal modules likewise, which their landing pages describe in a paragraph each. TBMANLIB_Diagnostic's `List` page has a NOTE labelled BETA 1010 under its `SetItem` sample: in a 32-bit IDE run `Err.Description` of the error 5 that `SetItem 0` raises on a list of one item (`Dim x As New List(Of String)`) is "Automation error", while the exe, a 64-bit IDE run and VB6 give "Invalid procedure call or argument" (`bugs/list-error5-automation-text`, with its case `ListTests.SetItem_AtZeroOnOneItemList_ErrorHasTheRuntimeText`). The samples harness runs in the IDE and has no per-sample way to state output that differs from an exe's, so that sample prints `Err.Number` only and the text is in the NOTE; when the entry is retired the NOTE goes and the sample prints `Err.Description` again, with the output `5: Invalid procedure call or argument`. See *Where things live* for how a package moves between the two lists. The rest of this file is the maintenance guide for updating existing pages or adding new ones: package surface notes, page conventions, and the integrity check. @@ -107,6 +107,7 @@ Per-package content-shape references live in sibling files. Open the relevant on - [WinServicesLib Package](WIP.WinServicesLib.md) — thin OS-services wrapper: `Services` singleton + `ServiceManager` + `ServiceCreator(Of T)` + `ServiceState` + `ITbService` + four enums. - [tbIDE Package](WIP.tbIDE.md) — the addin SDK (type-only compiler package): 23 CoClasses + `AddinTimer` + the HTML/DOM `[COMExtensible]` surface + samples 10–15 idiom map. - [WinNativeCommonCtls Package](WIP.WinNativeCommonCtls.md) — VB6-compatible `MSCOMCTL.OCX` replacement: 8 controls + 8 sub-objects + per-control nested enums + 10 module-level enums. +- [BigNumberLib Package](WIP.BigNumberLib.md) — contributed: what is known about the package and not on its pages yet (an unconfirmed `AssignDivision` defect near the library's capacity). The three "winlibs" packages — [WinServicesLib](WIP.WinServicesLib.md), [WinEventLogLib](WIP.WinEventLogLib.md), and [WinNamedPipesLib](WIP.WinNamedPipesLib.md) — share an essential set of integration idioms: composition-delegation on `EventLog(Of …)`, the `ManualMessageLoopEnter` / `Leave` pattern coupling `NamedPipeServer` to a service's `ChangeState` handler, and `PropertyBag` as the canonical pipe payload. When working on any of the three, check the other two for cross-references. @@ -134,7 +135,7 @@ node scripts/tbrun.mjs # what does it print - **Pack and unpack projects with `impexp`, never with the compiler executable's `import` or `export` verbs.** The tooling does both in process, through `packTree` and `unpackProject` in `scripts/lib/tb-project.mjs`; by hand it is `node scripts/impexp.mjs`. The compiler's `import` refuses a project that embeds a package (exit 999, twinbasic/twinbasic#841), and both verbs exit 0 after the failures they report. The reasons, and the path and stdin rules for anything that does run the executable (`bug_repro`'s `cli` mode), are in [WIP.Harness.md](WIP.Harness.md#getting-at-the-twin-sources). - **`tbbuild` exit codes:** 0 clean, 1 the project has errors, 2 the harness failed or the project file cannot be read (empty, cut short, not a project: it is read before an IDE starts), 3 the compile never settled or met its limit, 4 the project crashes the compiler, 5 the build failed after a clean compile (an LLVM refusal in its log included, an exe linked or not, and the build's limit). `--json` returns one object, `--keep` leaves the IDE running. **`--build` and `--llvm` (which implies it) build the project after a clean compile**, because LLVM code generation runs in a build and a compile never asks for it. They first stage a copy with an explicit build path (`%TEMP%\tbbuild\\`), so the given `.twinproj` is untouched. A plain `--build` is the control for an `--llvm` run. `--llvm` refuses a Community or Personal licence. - **It runs the IDE on a private Windows desktop**, so it cannot seize focus. Set `TBBUILD_SHOW=1` while working interactively and leave it unset for unattended runs: a wedged IDE nobody can see is expensive to diagnose. -- **One project per IDE**, 6--8 seconds each and flat in project size. Reusing a live IDE for a second project wedges it, so the cold start is the unit of work, not overhead to optimise away. Run concurrently to go faster: **every run takes a slot from `tbbroker`** ([WIP.Broker.md](WIP.Broker.md)) --- a private desktop, and the number its user-data folder, temp folder (`%TEMP%\tbbuild-tmp-`), work folders and project ids are named by --- **and its IDE's DevTools port is one Windows picks** (`--remote-debugging-port=0`, read back from `DevToolsActivePort`), so runs at once never meet on a port or a desktop. Never choose a port for an IDE, and never make a desktop: `leaseSlot`, `launchIde` and `launchOnDesktop` (`scripts/lib/tb-ide.mjs`) take them from the broker. `shutdownIde` removes the temp folder and the user-data folder (`%TEMP%\tbbuild-wv2-`, 28 MB) once the IDE has ended, and `launchIde` empties both again at the next launch in the slot, for what a killed run left; a kept IDE's stay until the next run. +- **`tbbuild` and `tbrun` start one IDE per project**, 6--8 seconds each and flat in project size: a fresh IDE and compiler per project. **`examples.bat` opens project after project in one IDE per lane** (`IdeSession`, `scripts/lib/tb-session.mjs`; `--fresh` starts one per project), through the page's own `openProject()` with the host's file dialog answered in the page, which closes the old project and its compiler first. Never call `root.loadProject` over CDP to switch: it skips the close, and the project tree keeps the old project. Before each switch the session undoes what a project leaves in the IDE: Safe Mode (close the project, set the build box to win32 with no project open, then open the next) and TRACE-MODE (`g_TraceMode`, which any native exception turns on). A project that put the IDE into Safe Mode is never opened again in that IDE; a bisect half is another project. A failed switch, a harness fault (2) or a compile that never settled (3) ends the IDE by pid, and the next project starts cold ([WIP.Harness.md](WIP.Harness.md#one-ide-per-project-or-one-per-lane)). Run concurrently to go faster: **every run takes a slot from `tbbroker`** ([WIP.Broker.md](WIP.Broker.md)) --- a private desktop, and the number its user-data folder, temp folder (`%TEMP%\tbbuild-tmp-`), work folders and project ids are named by --- **and its IDE's DevTools port is one Windows picks** (`--remote-debugging-port=0`, read back from `DevToolsActivePort`), so runs at once never meet on a port or a desktop. Never choose a port for an IDE, and never make a desktop: `leaseSlot`, `launchIde` and `launchOnDesktop` (`scripts/lib/tb-ide.mjs`) take them from the broker. `shutdownIde` removes the temp folder and the user-data folder (`%TEMP%\tbbuild-wv2-`, 28 MB) once the IDE has ended, and `launchIde` empties both again at the next launch in the slot, for what a killed run left; a kept IDE's stay until the next run. - **Keep a probe that might crash the compiler in a project of its own.** twinBASIC runs the compiler in the same process as user code, so one bad probe can take the run down and cost the other probes their answer. - **`tbrun` takes an exported tree, not a `.twinproj`**, because it pins `project.buildPath` in its own staged copy, to know where the built file is. The probe is a module with a `[RunAfterBuild]` Sub, and must start with `Debug.Cls`. Its exit codes: 0 the probe ran and its output was captured, 1 the project has compile errors, 2 the harness failed or the build did after a clean compile, 3 no output, 4 the compiler crashed, as `tbbuild` reports it, 5 the probe ended before it returned (`End`, or an error raised with no handler in LLVM-compiled code, which ends the run silently), 6 with `--exe`, the exe exited with a code other than 0, the event log records that it faulted, it opened a box (an unhandled error opens one, and `tbrun` closes it), or it was still running at its limit, 7 with `--tests`, a case failed. **Every phase's limit is in `test/harness.json`**, with an option and a `TB_` variable over it: [test/harness.md](test/harness.md). - **A project's own unit tests: `tbrun --tests`.** It builds nothing: it runs each `[TestCase]` Sub of each `[TestFixture]` Module in the compiler's test mode, the debugger's `evaluate` request with `isTest`, which the IDE itself never sends (BETA 1010 has no test runner a person can use), and prints `PASS` or `FAIL` for each. A failed assertion, an unhandled error and an access violation each end only their case. A defect that is a diagnostic is a compile case instead, a line ending `' CASE : `. A follow-up issue's regression tests are written this way: [WIP.Harness.md](WIP.Harness.md#running-a-projects-test-cases). @@ -434,6 +435,12 @@ and run `node scripts/check_impexp_parity.mjs` with `IMPEXP_EXE` set to its exe, `--self-test` and command sequence are its tests: no gate can build it, so nothing else will. **A change to what impexp does, or to its self-test, is made in all three editions** in one commit; CI compares only the Node and Python ones. +**tblaunch (the launcher repository) compiles every file of `scripts/impexp/src/Sources/` but +`Program.twin`, by name, from this checkout**, under a `Sub Main` of its own: renaming or adding a +module there, or giving one a public name tblaunch also has (`Json`, `Launcher`, `Container`, +`Pack`, `Session`, `Install`, `Fmt`, `StdIo` and others), breaks its build, so tell the tblaunch +session first. tblaunch packs a folder with `Impexp.PackTree`, through a class of its own that +implements `ImpexpSource`: a change to the members of either is made with the tblaunch session too. `scripts/broker/` is a twinBASIC program too, `tbbroker`, which hands out private desktops, slots and ports to every tool on the machine, launcher-re's `tblaunch` among them, and needs desktops, process handles and overlapped pipes, which Node cannot make without a native addon @@ -441,6 +448,11 @@ desktops, process handles and overlapped pipes, which Node cannot make without a (`node scripts/impexp.mjs import scripts/broker/tbbroker.twinproj scripts/broker/src --overwrite`), install it with `node scripts/tbbroker.mjs install`, and run `test/broker.test.mjs` with `TBBROKER_EXE` set to `%LOCALAPPDATA%\tbbroker\tbbroker.exe`: no gate can build it. +**tblaunch compiles every file of `scripts/broker/src/Sources/` but `Program.twin` and +`BrokerHost.twin`, by name, from this checkout**, as it does impexp's, and has a `BrokerHost` of +its own: what differs between the two programs (the name in messages, the output, the version's +suffix, the server's command line) is in `BrokerHost` and nowhere else, so a change to its members, +a renamed or added module, or a public name tblaunch also has, is made with the tblaunch session. **No tool makes a desktop of its own**: each leases one ([WIP.Broker.md](WIP.Broker.md)). `scripts/lib/llvm-cache/`, the lease on twinBASIC's LLVM cache server with its probes (one of them @@ -570,7 +582,7 @@ Why the report separates the wedged task from the merely blocked ones, and why - `addin-test.bat` — tests IDE add-ins by operating an IDE: every lane in `test/addin/lanes.mjs` builds the add-ins it tests into a private copy of the install, opens a project and checks what the add-in does. Outside every gate and outside CI for the same reasons as `examples.bat`; the seventeen lanes: Samples 10 and 15, the thirteen probe lanes behind Stage 2's answers in [WIP.HelpAddin.md](WIP.HelpAddin.md), and the help add-in in `add-in/` twice, built with its committed copy of the symbol index, `add-in/Resources/SYMBOLS/symbols.json`, which a local build rewrites whenever the index changes. The `help` lane serves the built `docs/_site` on localhost to the add-in's pane; `help-offline` builds the add-in with a help archive of `docs/_site-offline` and the pane's pages come from the add-in's own server. So run `build.bat` first. Exit 0 every lane passed and the registry is as it was found, 1 a lane failed, 2 the harness failed, 3 the registry or a work folder was not put back. See [Driving the twinBASIC compiler](#driving-the-twinbasic-compiler) for its rules. - `ide-test.bat` --- the same runner for scenarios that operate the IDE itself rather than an add-in: every lane in `test/ide/lanes.mjs`. Same exit codes, same standing outside every gate and outside CI, same rules. - `try-help-addin.bat` --- opens one IDE on the user's desktop with the help add-in built and loaded, to try it by hand, and puts the registry back once it is closed (see [Driving the twinBASIC compiler](#driving-the-twinbasic-compiler)). Needs `build.bat` first. Exit 0 closed and put back, 1 the add-in or the project did not compile, 2 the tool could not run, 3 not put back. -- `node scripts/shoot_docs.mjs` --- writes the documentation's IDE screenshots (plan and owner's decisions: [WIP.Screenshots.md](WIP.Screenshots.md)). Each picture is a shot in a table, `out` its path under `docs/` (`--only` matches it), in a setup (the main three below; the full list is in WIP.Screenshots.md), each one IDE on a **private** desktop started only when a shot in it is selected: `help` (builds the add-in as `try-help-addin.bat` does, opens `test/addin/helpdemo`, `TB_DOCS_HELP_REAL_TITLEBAR=0`: the eight `docs/IDE/AddIns/Images/Help_.png`), `no-project` (`Lane.openNoProject` with `includeProjects`: the menus, cut out with alpha, the dialogs that need no project, and the empty panels, each floated on its own, after the dialogs) and `project` (the demo without the add-in: About, which needs the compiler's licence answer, and IDE Options, whose font lists need a project). One setup is not an IDE: `web` starts puppeteer's Chrome through `launchOnDesktop` on a private desktop of its own (never headless, never on the user's desktop; native-window occlusion and occluded-window backgrounding switched off, or a capture waits forever or comes back blank) for the two public pages the FAQ shows, taken once; it needs the network, as do `webpage` (the Webpage pane on `https://docs.twinbasic.com/`, its page captured from the pane's own DevTools target and pasted into the pane's place) and the package-server setups, which never publish. Every IDE gets `--force-device-scale-factor=1` (`Lane`'s `browserArgs`), else the page follows the display's scaling; the page is overridden to 1280x880 at 2x, and `PAGE_DEFAULTS` puts the IDE's options, panel layouts and keyboard groups to their defaults and the recent lists to the tool's own **in the page only**, nothing written because the IDE has `IDE_FLAGS` (the one recent-list call they do not guard, `RemoveRecentsList`, is replaced first). Each picture is a `Page.captureScreenshot` with a `clip`; a page showing it gives it `{:width height}` of half its pixel size. **Every picture is taken in two themes by one IDE**: dark as `X.png`, then, after `backToPrepared` and `tbTheme_SwitchToLightMode`, Light (not Classic) as `X.light.png` beside it, which the build pairs by name ([WIP.Build.md](WIP.Build.md#pictures-in-two-themes)); a light picture with the dark one's pixels is not kept, and one more than 32 device pixels off the dark one's size fails (a wrong state, not the theme). A label's pill follows the theme unless the shot names a `tone`. A shot's `annotate` list (arrows, rings, badges...) is drawn by `scripts/lib/shot-annotate.mjs` as one SVG layer over the page before the capture and removed after it, the clip growing to hold it. A picture is rewritten only when its bytes differ, and a second run reports every one `unchanged`; a capture is not byte-stable, so `capture` takes up to eight and keeps one equal to the file on disk, and a picture that differs from the file only by a capture's noise (16 grey levels, 0.5% of its pixels) is left as it is. `--jobs N` (default 6) runs the setups at once, each in a slot of its own from `tbbroker`, a full run with `--svg` in about 17 minutes on BETA 1005 (`--jobs 1`: one at a time); `--diffs ` writes the old picture, the new one and an amplified difference map for each that changed, named with its theme. Settle by a condition, never a fixed sleep, and a picture that shows some state sets it itself rather than relying on the shots before it. The page's animations and carets are switched off through a style sheet put into the document and every shadow root; a picture that holds DEBUG CONSOLE lines has their times (and a CodeLens run's time taken) set in the page once the real ones show. **A running program's window** (setup `programs`, fixture `test/shots/programs`) is taken **once** (`once: true`, the dark pass only) with `captureWindow`, cropped to its visible frame, at the display's DPI, shown at its size at 96 DPI. **The Windows user name must never be in a published picture**: the visible text of the page, text boxes included, is searched for it before the first capture and again when a capture is chosen, with the picture's SVG under `--svg` (a page can draw again in between: Project Settings puts a real path back over the one the shot set), and for a program's window the texts of the window and its children, and the run fails when it is there. The tool finds each name it presses F1 on by searching the demo's source, not by line. The add-in's detached window has a port from the broker (the help setup's slot carries one), since the add-in is told it before it binds it. **`--svg`** also draws each picture as SVG from the page as it stands at the capture (`scripts/svgshot/`: a DOM snapshot converted, its text set in per-picture subsets of the fonts the IDE drew it with, cut by `scripts/subset_font.py`, which needs Python with fontTools), compares it with the PNG, and writes `X.svg` or `X.light.svg` beside it only when no more than 0.25% of its pixels are far off; otherwise an older SVG is removed and the page shows the PNG ([WIP.Build.md](WIP.Build.md#pictures-as-svg)). With `--svg` each picture's *bundle*, what its SVG is drawn from, is saved in the gitignored `.svgshot-bundles/` (`--bundles`; never under `docs/`, a bundle holds the user name), and **after a change to the converter, `node scripts/svgshot/replay.mjs` draws every SVG again from the bundles, with no IDE**, in about 20 s for the 370 (an SVG the same as its file is not compared again, `--recheck` compares all; the fonts' cuts are kept in `.svgshot-bundles/subsets/`; one browser per process, GPU off); it lists the pictures whose bundle cannot answer what the converter now asks, with the `--only` command that retakes them ([WIP.Screenshots.md](WIP.Screenshots.md#pictures-as-svg)). `node scripts/svgshot/bench.mjs` tests the converter's replicas of what Chromium draws outside the DOM (scrollbars, drop-down lists) in Edge, with no IDE ([WIP.Screenshots.md](WIP.Screenshots.md#pictures-as-svg)). No wrapper; outside every gate and outside CI, as `try-help-addin.bat` is. Exit 0 every picture written or unchanged, 1 a picture failed, 2 the tool could not run, 3 not put back. Run `build.bat` first. +- `node scripts/shoot_docs.mjs` --- writes the documentation's IDE screenshots (plan and owner's decisions: [WIP.Screenshots.md](WIP.Screenshots.md)). Each picture is a shot in a table, `out` its path under `docs/` (`--only` matches it), in a setup (the main three below; the full list is in WIP.Screenshots.md), each one IDE on a **private** desktop started only when a shot in it is selected: `help` (builds the add-in as `try-help-addin.bat` does, opens `test/addin/helpdemo`, `TB_DOCS_HELP_REAL_TITLEBAR=0`: the eight `docs/IDE/AddIns/Images/Help_.png`), `no-project` (`Lane.openNoProject` with `includeProjects`: the menus, cut out with alpha, the dialogs that need no project, and the empty panels, each floated on its own, after the dialogs) and `project` (the demo without the add-in: About, which needs the compiler's licence answer, and IDE Options, whose font lists need a project). One setup is not an IDE: `web` starts puppeteer's Chrome through `launchOnDesktop` on a private desktop of its own (never headless, never on the user's desktop; native-window occlusion and occluded-window backgrounding switched off, or a capture waits forever or comes back blank) for the two public pages the FAQ shows, taken once; it needs the network, as do `webpage` (the Webpage pane on `https://docs.twinbasic.com/`, its page captured from the pane's own DevTools target and pasted into the pane's place) and the package-server setups, which never publish. Every IDE gets `--force-device-scale-factor=1` (`Lane`'s `browserArgs`), else the page follows the display's scaling; the page is overridden to 1280x880 at 2x, and `PAGE_DEFAULTS` puts the IDE's options, panel layouts and keyboard groups to their defaults and the recent lists to the tool's own **in the page only**, nothing written because the IDE has `IDE_FLAGS` (the one recent-list call they do not guard, `RemoveRecentsList`, is replaced first). Each picture is a `Page.captureScreenshot` with a `clip`; a page showing it gives it `{:width height}` of half its pixel size. **Every picture is taken in two themes by one IDE**: dark as `X.png`, then, after `backToPrepared` and `tbTheme_SwitchToLightMode`, Light (not Classic) as `X.light.png` beside it, which the build pairs by name ([WIP.Build.md](WIP.Build.md#pictures-in-two-themes)); a light picture with the dark one's pixels is not kept, and one more than 32 device pixels off the dark one's size fails (a wrong state, not the theme). A label's pill follows the theme unless the shot names a `tone`. A shot's `annotate` list (arrows, rings, badges...) is drawn by `scripts/lib/shot-annotate.mjs` as one SVG layer over the page before the capture and removed after it, the clip growing to hold it. A picture is rewritten only when its bytes differ, and a second run reports every one `unchanged`; a capture is not byte-stable, so `capture` captures back to back, with no rest, until one equals the file on disk or two agree, and, when the two that agree are not the file, goes on capturing further apart, for 5.5 s at most, until one is, keeping the last two that agreed, and a picture that differs from the file only by a capture's noise (16 grey levels, 0.5% of its pixels) is left as it is. `--jobs N` (default 6) runs the setups at once, each in a slot of its own from `tbbroker`, a full run with `--svg` in about 12 minutes on BETA 1010 (`--jobs 1`: one at a time); `--diffs ` writes the old picture, the new one and an amplified difference map for each that changed, named with its theme. Settle by a condition, never a fixed sleep, and a picture that shows some state sets it itself rather than relying on the shots before it. The page's animations and carets are switched off through a style sheet put into the document and every shadow root; a picture that holds DEBUG CONSOLE lines has their times (and a CodeLens run's time taken) set in the page once the real ones show. **A running program's window** (setup `programs`, fixture `test/shots/programs`) is taken **once** (`once: true`, the dark pass only) with `captureWindow`, cropped to its visible frame, at the display's DPI, shown at its size at 96 DPI. **The Windows user name must never be in a published picture**: the visible text of the page, text boxes included, is searched for it before the first capture and again when a capture is chosen, with the picture's SVG under `--svg` (a page can draw again in between: Project Settings puts a real path back over the one the shot set), and for a program's window the texts of the window and its children, and the run fails when it is there. The tool finds each name it presses F1 on by searching the demo's source, not by line. The add-in's detached window has a port from the broker (the help setup's slot carries one), since the add-in is told it before it binds it. **`--svg`** also draws each picture as SVG from the page as it stands at the capture (`scripts/svgshot/`: a DOM snapshot converted, its text set in per-picture subsets of the fonts the IDE drew it with, cut by `scripts/subset_font.py`, which needs Python with fontTools), compares it with the PNG, and writes `X.svg` or `X.light.svg` beside it only when no more than 0.25% of its pixels are far off; otherwise an older SVG is removed and the page shows the PNG; the SVG of a picture whose PNG is not rewritten stays as it is, with its bundle (owner) ([WIP.Build.md](WIP.Build.md#pictures-as-svg)). With `--svg` each picture's *bundle*, what its SVG is drawn from, is saved in the gitignored `.svgshot-bundles/` (`--bundles`; never under `docs/`, a bundle holds the user name), and **after a change to the converter, `node scripts/svgshot/replay.mjs` draws every SVG again from the bundles, with no IDE**, in about 20 s for the 370 (an SVG the same as its file is not compared again, `--recheck` compares all; the fonts' cuts are kept in `.svgshot-bundles/subsets/`; one browser per process, GPU off); it lists the pictures whose bundle cannot answer what the converter now asks, with the `--only` command that retakes them ([WIP.Screenshots.md](WIP.Screenshots.md#pictures-as-svg)). `node scripts/svgshot/bench.mjs` tests the converter's replicas of what Chromium draws outside the DOM (scrollbars, drop-down lists) in Edge, with no IDE ([WIP.Screenshots.md](WIP.Screenshots.md#pictures-as-svg)). No wrapper; outside every gate and outside CI, as `try-help-addin.bat` is. Exit 0 every picture written or unchanged, 1 a picture failed, 2 the tool could not run, 3 not put back. Run `build.bat` first. - **The help add-in's project file is written by every build, CI's included.** The `addinProject` task (`builder/addin-project.mjs`) packs `add-in/` into `tB/IDE/AddIns/downloads/tbDocsHelp.twinproj` in the **online tree only**, which the Help Add-In page offers as a download; `_config.yml`'s `addin_project` declares both ends, so a fixture config gets none. It waits for the `helpArchive` task. It packs the files `git ls-files` lists there, read from the working folder, never a `Resources/HELP/` file from the disk, with CRLF made LF outside `Resources/` (so a Windows and a Linux build write the same bytes), the `tB/symbols.json` the same build wrote in place of the committed copy, and **the zip that build's archive task wrote** as `Resources/HELP/site.zip`, passed in memory (a build that wrote none --- `--no-help-archive`, `--serve`, another `--dest`, a fixture --- packs without it, and the summary line says `without the offline archive`). The download is about 51 MB with the archive, 1 MB without. The offline tree holds no copy (the project carries that tree's archive, so a copy there would be circular), and its links to the file are rewritten to the website by the general rule in `offline-rewrite.mjs`: a URL the offline tree lacks but the online tree has becomes `site.url` + path, and is no miss (`computeWebsiteUrl`; the offline link check's `forbidExempt` excuses exactly those links, `isWebsiteOnlyLink`). The pack is `packFiles` from `scripts/impexp.mjs`, in memory (never staged through `%TEMP%`), the one module under `scripts/` that `builder/` may import (`biome.jsonc`); `check_tree_fresh.mjs` watches it and `add-in/` for that reason. The publish allowlist exempts the one path in the trees only (`publishPolicyFor`'s `generated`); a `.twinproj` anywhere else, or in `docs/`, is refused. `--serve` writes it into its one tree; `--dry-run` writes nothing. A failure (no git) fails the build with exit 1 and the index audit names the missing file. **Don't build the DLLs in CI from it**: that needs a twinBASIC install; the download is the project, and the reader builds it. Why each of these: [WIP.Build.md](WIP.Build.md#the-help-add-ins-project-file); `test/addin-project.test.mjs` is the gate. - **The help archive is the `helpArchive` task of the build's graph.** `builder/help-archive-step.mjs` writes `add-in/Resources/HELP/site.zip` from `docs/_site-offline` through `lib/help-archive.mjs`, once every task that writes into the offline tree has finished (`flushJoin`, `scss`, `writeOffline`; the archive task lists exactly those) and **before** the Gantt injection. **The archive leaves out `HELP_ARCHIVE_SKIP`** (`builder/help-archive-step.mjs`): the Documentation Development section (`BuildInfo.html` and `assets/images/gantt.svg` with it, so the chart never reaches the zip), Videos and their poster frames, Challenges, and **every download, which stays online** (owner): a file readers download goes in a `downloads` folder beside its page, and the step fails the build when the Downloads page offers a file the archive would hold. The add-in's server redirects any file the archive lacks to the website, because pages link to all of these; a new entry needs nothing else. It reads the file back to verify it. A mismatch fails the build (exit 1). After the Gantt injection `recheckHelpArchive` checks that the offline tree on disk lists the same files as the archive and differs from it only in `BuildInfo.html` and `gantt.svg`; a task that wrote into the offline tree late fails the build there. The help add-in embeds the zip as a resource and serves the pages from it with its own server; a build of the add-in without it uses the live site. The file is gitignored (about 26 MB), so a build of the add-in from a clean clone is the online one until `build.bat` has run. The download carries the same zip (previous bullet). **`--no-help-archive` turns the step off, and neither CI workflow may pass it** (`check_ci_workflows.mjs` refuses it, in `ALLOWED.forbiddenBuildFlags`), because CI's published download would then hold no archive. It runs only for the guarded source tree (`docs`) built into the default `docs/_site-offline` (not another `--dest`, so `compare_trees` and `check_links_diff` leave it alone), never under `--serve` or `--dry-run`, never without an offline tree, and not keyed on `$CI`. There is no command-line tool for the archive: the `help-offline` lane makes its own with `writeHelpArchive`. The zip's format is fixed by the add-in's reader, which does no inflating ([WIP.HelpAddin.md](WIP.HelpAddin.md), Stage 4, increment 5). - `node scripts/bug_repro.mjs` --- the reproducer projects under `bugs//` for the entries of [BUGS-TO-REPORT.md](BUGS-TO-REPORT.md): `new`, `pack` (impexp, then the zip, written in Node), `compile`, `build` and `run` through `tbbuild` and `tbrun`, `vb6` (builds the optional `vb6/` VB6 project beside the twinBASIC one in a temp copy, runs its exe on a private desktop, and prints its `out.txt`; a project with a form or a user control is built without Unattended Execution, which VB6 refuses for it; `pack` zips its sources into `-vb6.zip`; VB6 is started only by `scripts/lib/vb6.mjs`, never from a shell; a graphical defect's `images` key makes `run` and `vb6` keep what the `PngDump` modules of `test/repro-templates/png/` draw as `images/-tb.png` and `-vb6.png`, with a `-compare.png` of both, tested by `test/png.test.mjs`), `file` (moves a filed entry and its reproducer to `bugs/filed//`; `file --marked` does every marked entry), and `verify`, which reads each `bugs/*/repro.json` and `bugs/filed/*/repro.json` and says whether the bug still reproduces on the newest beta; a `lane` reproducer names the `ide-test` or `addin-test` lane and tests that assert its bug, which `verify` runs last through that runner, a `probe` one a script under `scripts/`, and a `test` one its own `[TestCase]` Subs and compile cases through `tbrun --tests`, judged by the `PASS` lines of what is fixed and the `FAIL` lines of the bug (`new --template tests` starts one). **No reproducer should need a person at the IDE** (owner): a bug the IDE has to be operated for gets a lane test, and `manual` is left for what cannot be automated at all. It has no wrapper. **`verify` is run by a person only**, never by a gate or CI: it needs a twinBASIC install, like `examples.bat`. Each `tbbuild` and `tbrun` it starts takes a slot of its own from `tbbroker`; `--jobs N` runs N at once. Its command-line cases are in `scripts/lib/cli-cases.mjs`, and need no IDE. diff --git a/bugs/class-field-init-reads-field/class-field-init-reads-field.twinproj b/bugs/class-field-init-reads-field/class-field-init-reads-field.twinproj new file mode 100644 index 000000000..d539203bf Binary files /dev/null and b/bugs/class-field-init-reads-field/class-field-init-reads-field.twinproj differ diff --git a/bugs/class-field-init-reads-field/repro.json b/bugs/class-field-init-reads-field/repro.json new file mode 100644 index 000000000..a8cf82943 --- /dev/null +++ b/bugs/class-field-init-reads-field/repro.json @@ -0,0 +1,7 @@ +{ + "mode": "build", + "expect": { + "exit": 5, + "message": "compilation \\(codegen\\) error detected in 'Counter\\.\\{fields_init\\}'" + } +} diff --git a/bugs/class-field-init-reads-field/src/Settings b/bugs/class-field-init-reads-field/src/Settings new file mode 100644 index 000000000..c985738c8 --- /dev/null +++ b/bugs/class-field-init-reads-field/src/Settings @@ -0,0 +1,61 @@ +{ + "configuration.inherits": "Defaults", + "project.appTitle": "ClassFieldInitReadsField", + "project.buildPath": "${SourcePath}\\Build\\${ProjectName}_${Architecture}.${FileExtension}", + "project.buildType": "Standard EXE", + "project.description": "Reproduces: A class field whose initializer reads another field of the class fails the build with a codegen error", + "project.exportPathIsV2": true, + "project.id": "{8E5B537E-5C7C-48C6-BE1C-F9258B8ED71B}", + "project.name": "ClassFieldInitReadsField", + "project.optionExplicit": true, + "project.references": [ + { + "id": "{00020430-0000-0000-C000-000000000046}", + "lcid": 0, + "name": "OLE Automation", + "path32": "C:\\Windows\\SysWOW64\\stdole2.tlb", + "path64": "C:\\Windows\\System32\\stdole2.tlb", + "symbolId": "stdole", + "versionMajor": 2, + "versionMinor": 0 + }, + { + "id": "{F50B82D0-DCAB-43FE-9631-11959D4A4728}", + "isCompilerPackage": true, + "licence": "MIT", + "name": "[COMPILER PACKAGE] twinBASIC - VB Compatibility Package (Forms)", + "path32": "", + "path64": "", + "publisher": "TWINBASIC-COMPILER", + "symbolId": "VB", + "versionBuild": 0, + "versionMajor": 0, + "versionMinor": 0, + "versionRevision": 31 + }, + { + "id": "{C192FB39-64CA-4D9B-B477-A5502F48EFCC}", + "isCompilerPackage": true, + "licence": "MIT", + "name": "[COMPILER PACKAGE] twinBASIC - App global class object", + "path32": "", + "path64": "", + "publisher": "TWINBASIC-COMPILER", + "symbolId": "AppGlobalClassProject", + "versionBuild": 0, + "versionMajor": 1, + "versionMinor": 0, + "versionRevision": 0 + } + ], + "project.settingsVersion": 1, + "project.startupObject": "Sub Main", + "project.warnings": { + "errors": [], + "hints": [], + "ignored": [], + "info": [], + "warnings": [] + }, + "runtime.useUnicodeStandardLibrary": true +} diff --git a/bugs/class-field-init-reads-field/src/Sources/Startup.twin b/bugs/class-field-init-reads-field/src/Sources/Startup.twin new file mode 100644 index 000000000..ef3b6fa2c --- /dev/null +++ b/bugs/class-field-init-reads-field/src/Sources/Startup.twin @@ -0,0 +1,19 @@ +' A field initializer in a class that reads another field of the same class. The +' project compiles with no diagnostic; the build fails with "compilation (codegen) +' error detected in 'Counter.{fields_init}'". The same for X = A, Me.A + 1, String +' fields, a ReadOnly field, a field declared later, and a field with no initializer, +' in 32-bit and 64-bit builds. Fine: a field that reads a module-level variable or a +' constant, and a module-level variable that reads another of its module. +Module Startup + + Public Sub Main() + Dim c As New Counter + Debug.Print c.First & ", " & c.Second + End Sub + +End Module + +Class Counter + Public First As Long = 1 + Public Second As Long = First + 1 +End Class diff --git a/bugs/module-init-reads-other-module-ide/module-init-reads-other-module-ide.twinproj b/bugs/module-init-reads-other-module-ide/module-init-reads-other-module-ide.twinproj new file mode 100644 index 000000000..57e045fc2 Binary files /dev/null and b/bugs/module-init-reads-other-module-ide/module-init-reads-other-module-ide.twinproj differ diff --git a/bugs/module-init-reads-other-module-ide/repro.json b/bugs/module-init-reads-other-module-ide/repro.json new file mode 100644 index 000000000..46a3ddb5e --- /dev/null +++ b/bugs/module-init-reads-other-module-ide/repro.json @@ -0,0 +1,9 @@ +{ + "mode": "run", + "expect": { + "exit": 0, + "output": [ + "^Limit=0 Doubled=0 FromConfig=0 Box\\.Size=3$" + ] + } +} diff --git a/bugs/module-init-reads-other-module-ide/src/Settings b/bugs/module-init-reads-other-module-ide/src/Settings new file mode 100644 index 000000000..11005c858 --- /dev/null +++ b/bugs/module-init-reads-other-module-ide/src/Settings @@ -0,0 +1,61 @@ +{ + "configuration.inherits": "Defaults", + "project.appTitle": "ModuleInitReadsOtherModuleIde", + "project.buildPath": "${SourcePath}\\Build\\${ProjectName}_${Architecture}.${FileExtension}", + "project.buildType": "Standard EXE", + "project.description": "Reproduces: In the IDE, a module-level initializer that reads another module's variable leaves every module-level variable at 0", + "project.exportPathIsV2": true, + "project.id": "{EFEC6B41-9B55-4BF0-94D1-5D422D9CBF6D}", + "project.name": "ModuleInitReadsOtherModuleIde", + "project.optionExplicit": true, + "project.references": [ + { + "id": "{00020430-0000-0000-C000-000000000046}", + "lcid": 0, + "name": "OLE Automation", + "path32": "C:\\Windows\\SysWOW64\\stdole2.tlb", + "path64": "C:\\Windows\\System32\\stdole2.tlb", + "symbolId": "stdole", + "versionMajor": 2, + "versionMinor": 0 + }, + { + "id": "{F50B82D0-DCAB-43FE-9631-11959D4A4728}", + "isCompilerPackage": true, + "licence": "MIT", + "name": "[COMPILER PACKAGE] twinBASIC - VB Compatibility Package (Forms)", + "path32": "", + "path64": "", + "publisher": "TWINBASIC-COMPILER", + "symbolId": "VB", + "versionBuild": 0, + "versionMajor": 0, + "versionMinor": 0, + "versionRevision": 31 + }, + { + "id": "{C192FB39-64CA-4D9B-B477-A5502F48EFCC}", + "isCompilerPackage": true, + "licence": "MIT", + "name": "[COMPILER PACKAGE] twinBASIC - App global class object", + "path32": "", + "path64": "", + "publisher": "TWINBASIC-COMPILER", + "symbolId": "AppGlobalClassProject", + "versionBuild": 0, + "versionMajor": 1, + "versionMinor": 0, + "versionRevision": 0 + } + ], + "project.settingsVersion": 1, + "project.startupObject": "Sub Main", + "project.warnings": { + "errors": [], + "hints": [], + "ignored": [], + "info": [], + "warnings": [] + }, + "runtime.useUnicodeStandardLibrary": true +} diff --git a/bugs/module-init-reads-other-module-ide/src/Sources/Startup.twin b/bugs/module-init-reads-other-module-ide/src/Sources/Startup.twin new file mode 100644 index 000000000..1b28e0dc5 --- /dev/null +++ b/bugs/module-init-reads-other-module-ide/src/Sources/Startup.twin @@ -0,0 +1,28 @@ +' Module-level variables with initializers, read in the IDE (bug_repro run calls Main +' from a [RunAfterBuild] procedure). Because Other.FromConfig's initializer reads +' Config.Limit, a variable of another module, every module-level variable reads 0, +' Config's own included. Without that initializer, or with FromConfig reading +' Config.Base (a constant) or a variable of its own module, they read 5, 14 and 105. +' A class field initializer runs either way, and the built exe prints the right values. +Module Config + Public Const Base As Long = 7 + Public Limit As Long = 5 + Public Doubled As Long = Base * 2 +End Module + +Module Other + Public FromConfig As Long = Config.Limit + 100 +End Module + +Class Box + Public Size As Long = 3 +End Class + +Module Startup + + Public Sub Main() + Dim b As New Box + Debug.Print "Limit=" & Config.Limit & " Doubled=" & Config.Doubled & " FromConfig=" & Other.FromConfig & " Box.Size=" & b.Size + End Sub + +End Module diff --git a/bugs/negative-zero-text-win64/negative-zero-text-win64.twinproj b/bugs/negative-zero-text-win64/negative-zero-text-win64.twinproj new file mode 100644 index 000000000..8b8af5f5c Binary files /dev/null and b/bugs/negative-zero-text-win64/negative-zero-text-win64.twinproj differ diff --git a/bugs/negative-zero-text-win64/repro.json b/bugs/negative-zero-text-win64/repro.json new file mode 100644 index 000000000..346122f12 --- /dev/null +++ b/bugs/negative-zero-text-win64/repro.json @@ -0,0 +1,20 @@ +{ + "mode": "test", + "arch": "win64", + "expect": { + "exit": 7, + "output": [ + "^PASS NegativeZeroTextTests.NegativeZeroDouble_HoldsTheSignBit$", + "^PASS NegativeZeroTextTests.NegativeZeroSingle_HoldsTheSignBit$", + "^FAIL NegativeZeroTextTests.CStrOfNegativeZeroDouble_Is0: ", + "^FAIL NegativeZeroTextTests.CStrOfNegativeZeroSingle_Is0: ", + "^FAIL NegativeZeroTextTests.StrOfNegativeZeroDouble_IsSpace0: ", + "^FAIL NegativeZeroTextTests.StrOfNegativeZeroSingle_IsSpace0: ", + "^FAIL NegativeZeroTextTests.FormatOfNegativeZeroDouble_Is0: ", + "^FAIL NegativeZeroTextTests.ConcatenatedNegativeZeroDouble_Is0: ", + "^FAIL NegativeZeroTextTests.ConcatenatedNegativeZeroSingle_Is0: ", + "^PASS NegativeZeroTextTests.CStrOfPositiveZero_Is0$", + "^PASS NegativeZeroTextTests.CStrOfNegativeNumber_IsUnchanged$" + ] + } +} diff --git a/bugs/negative-zero-text-win64/src/Settings b/bugs/negative-zero-text-win64/src/Settings new file mode 100644 index 000000000..4572e0dc7 --- /dev/null +++ b/bugs/negative-zero-text-win64/src/Settings @@ -0,0 +1,75 @@ +{ + "configuration.inherits": "Defaults", + "project.appTitle": "NegativeZeroTextWin64", + "project.buildPath": "${SourcePath}\\Build\\${ProjectName}_${Architecture}.${FileExtension}", + "project.buildType": "Standard EXE", + "project.description": "Reproduces: A 64-bit build prints a negative zero as `-0`", + "project.exportPathIsV2": true, + "project.id": "{F3F18CB6-F877-42CA-B45F-833BBE938AF2}", + "project.name": "NegativeZeroTextWin64", + "project.optionExplicit": true, + "project.references": [ + { + "id": "{00020430-0000-0000-C000-000000000046}", + "lcid": 0, + "name": "OLE Automation", + "path32": "C:\\Windows\\SysWOW64\\stdole2.tlb", + "path64": "C:\\Windows\\System32\\stdole2.tlb", + "symbolId": "stdole", + "versionMajor": 2, + "versionMinor": 0 + }, + { + "id": "{F50B82D0-DCAB-43FE-9631-11959D4A4728}", + "isCompilerPackage": true, + "licence": "MIT", + "name": "[COMPILER PACKAGE] twinBASIC - VB Compatibility Package (Forms)", + "path32": "", + "path64": "", + "publisher": "TWINBASIC-COMPILER", + "symbolId": "VB", + "versionBuild": 0, + "versionMajor": 0, + "versionMinor": 0, + "versionRevision": 31 + }, + { + "id": "{C192FB39-64CA-4D9B-B477-A5502F48EFCC}", + "isCompilerPackage": true, + "licence": "MIT", + "name": "[COMPILER PACKAGE] twinBASIC - App global class object", + "path32": "", + "path64": "", + "publisher": "TWINBASIC-COMPILER", + "symbolId": "AppGlobalClassProject", + "versionBuild": 0, + "versionMajor": 1, + "versionMinor": 0, + "versionRevision": 0 + }, + { + "id": "{9847A10D-8987-44B2-8B87-EA77DEF7F1D9}", + "isCompilerPackage": true, + "licence": "MIT", + "name": "[COMPILER PACKAGE] Assert", + "path32": "", + "path64": "", + "publisher": "TWINBASIC-COMPILER", + "symbolId": "Assert", + "versionBuild": 0, + "versionMajor": 0, + "versionMinor": 0, + "versionRevision": 24 + } + ], + "project.settingsVersion": 1, + "project.startupObject": "Sub Main", + "project.warnings": { + "errors": [], + "hints": [], + "ignored": [], + "info": [], + "warnings": [] + }, + "runtime.useUnicodeStandardLibrary": true +} diff --git a/bugs/negative-zero-text-win64/src/Sources/RegressionTests.twin b/bugs/negative-zero-text-win64/src/Sources/RegressionTests.twin new file mode 100644 index 000000000..59e99af8c --- /dev/null +++ b/bugs/negative-zero-text-win64/src/Sources/RegressionTests.twin @@ -0,0 +1,99 @@ +' Regression tests: the text of a Single or Double that holds a negative zero (sign bit set, +' every other bit clear). VB6, and a 32-bit twinBASIC build, give "0" from CStr, Format and +' concatenation and " 0" from Str. A 64-bit build gives "-0" ("-0" from Str too, with no +' leading space). The value is made by copying its bytes into a variable, so that no +' arithmetic or constant folding can decide the sign, and the first two cases check that +' the variable holds it. The cases assert VB6's text, so they fail in a 64-bit build +' (repro.json names it) and pass in a 32-bit one (the VB6 project beside this one prints it). + +[TestFixture] +Module NegativeZeroTextTests + + Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As LongPtr) + + Private Function NegativeZeroDouble() As Double + Dim bits As LongLong + Dim result As Double + bits = &H8000000000000000^ + CopyMemory result, bits, 8 + Return result + End Function + + Private Function NegativeZeroSingle() As Single + Dim bits As Long + Dim result As Single + bits = &H80000000 + CopyMemory result, bits, 4 + Return result + End Function + + ' Controls: the variable holds a negative zero, and compares equal to zero. + + [TestCase] + Public Sub NegativeZeroDouble_HoldsTheSignBit() + Dim x As Double + Dim bits As LongLong + x = NegativeZeroDouble() + CopyMemory bits, x, 8 + Assert.Strict.AreEqual True, (bits = &H8000000000000000^) + Assert.Strict.AreEqual True, (x = 0) + End Sub + + [TestCase] + Public Sub NegativeZeroSingle_HoldsTheSignBit() + Dim x As Single + Dim bits As Long + x = NegativeZeroSingle() + CopyMemory bits, x, 4 + Assert.Strict.AreEqual True, (bits = &H80000000) + Assert.Strict.AreEqual True, (x = 0) + End Sub + + [TestCase] + Public Sub CStrOfNegativeZeroDouble_Is0() + Assert.Strict.AreEqual "0", CStr(NegativeZeroDouble()) + End Sub + + [TestCase] + Public Sub CStrOfNegativeZeroSingle_Is0() + Assert.Strict.AreEqual "0", CStr(NegativeZeroSingle()) + End Sub + + [TestCase] + Public Sub StrOfNegativeZeroDouble_IsSpace0() + Assert.Strict.AreEqual " 0", Str$(NegativeZeroDouble()) + End Sub + + [TestCase] + Public Sub StrOfNegativeZeroSingle_IsSpace0() + Assert.Strict.AreEqual " 0", Str$(NegativeZeroSingle()) + End Sub + + [TestCase] + Public Sub FormatOfNegativeZeroDouble_Is0() + Assert.Strict.AreEqual "0", Format$(NegativeZeroDouble()) + End Sub + + [TestCase] + Public Sub ConcatenatedNegativeZeroDouble_Is0() + Assert.Strict.AreEqual "x=0", "x=" & NegativeZeroDouble() + End Sub + + [TestCase] + Public Sub ConcatenatedNegativeZeroSingle_Is0() + Assert.Strict.AreEqual "x=0", "x=" & NegativeZeroSingle() + End Sub + + ' Controls: a positive zero and an ordinary negative number print the same in both builds. + + [TestCase] + Public Sub CStrOfPositiveZero_Is0() + Assert.Strict.AreEqual "0", CStr(0#) + End Sub + + [TestCase] + Public Sub CStrOfNegativeNumber_IsUnchanged() + Assert.Strict.AreEqual "-1.5", CStr(-1.5) + End Sub + +End Module diff --git a/bugs/negative-zero-text-win64/src/Sources/Startup.twin b/bugs/negative-zero-text-win64/src/Sources/Startup.twin new file mode 100644 index 000000000..20233b3a9 --- /dev/null +++ b/bugs/negative-zero-text-win64/src/Sources/Startup.twin @@ -0,0 +1,6 @@ +Module Startup + + Public Sub Main() + End Sub + +End Module diff --git a/bugs/negative-zero-text-win64/vb6/Module1.bas b/bugs/negative-zero-text-win64/vb6/Module1.bas new file mode 100644 index 000000000..d90c7760d --- /dev/null +++ b/bugs/negative-zero-text-win64/vb6/Module1.bas @@ -0,0 +1,49 @@ +Attribute VB_Name = "Module1" +Option Explicit + +' The text VB6 gives for a negative zero, which the twinBASIC reproducer's cases assert +' (a 32-bit twinBASIC build gives the same; a 64-bit one gives -0 from CStr, Str, Format +' and concatenation). The value is made by copying its bytes into the variable, and the +' bytes are read back to show that the sign bit is set. + +Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long) + +Private Sub P(ByVal s As String) + Print #9, s +End Sub + +Sub Main() + On Error GoTo Fail + Open App.Path & "\out.txt" For Output As #9 + Dim d As Double, w(1) As Long, s As Single, n As Long, back(1) As Long + On Error Resume Next + + w(0) = 0 + w(1) = &H80000000 + CopyMemory d, w(0), 8 + CopyMemory back(0), d, 8 + P "Double high word = " & Hex$(back(1)) & ", d = 0 is " & (d = 0) + P "CStr(-0#) = [" & CStr(d) & "]" + P "Str$(-0#) = [" & Str$(d) & "]" + P "Format$(-0#) = [" & Format$(d) & "]" + P "Concatenated = [x=" & d & "]" + + n = &H80000000 + CopyMemory s, n, 4 + CopyMemory back(0), s, 4 + P "Single bits = " & Hex$(back(0)) & ", s = 0 is " & (s = 0) + P "CStr(-0!) = [" & CStr(s) & "]" + P "Str$(-0!) = [" & Str$(s) & "]" + P "Concatenated = [x=" & s & "]" + + P "CStr(0#) = [" & CStr(0#) & "]" + P "CStr(-1.5) = [" & CStr(-1.5) & "]" + P "error " & Err.Number & " " & Err.Description + + Close #9 + Exit Sub +Fail: + On Error Resume Next + Print #9, "unhandled error " & Err.Number & ": " & Err.Description + Close #9 +End Sub diff --git a/bugs/negative-zero-text-win64/vb6/Probe.vbp b/bugs/negative-zero-text-win64/vb6/Probe.vbp new file mode 100644 index 000000000..4d210b0e8 --- /dev/null +++ b/bugs/negative-zero-text-win64/vb6/Probe.vbp @@ -0,0 +1,7 @@ +Type=Exe +Module=Module1; Module1.bas +Startup="Sub Main" +ExeName32="Probe.exe" +Name="Probe" +CompilationType=0 +OptimizationType=0 diff --git a/builder/page-baseline.json b/builder/page-baseline.json index a243fc34c..0a44df948 100644 --- a/builder/page-baseline.json +++ b/builder/page-baseline.json @@ -1,5 +1,5 @@ { "src": "docs", "pages": 1502, - "staticFiles": 1068 + "staticFiles": 1124 } diff --git a/docs/Documentation/Tools-Compiler.md b/docs/Documentation/Tools-Compiler.md index 279bea75b..7ab15bd73 100644 --- a/docs/Documentation/Tools-Compiler.md +++ b/docs/Documentation/Tools-Compiler.md @@ -55,7 +55,7 @@ So that the built file lands in a folder the run owns and the given project is l **It runs the IDE on a private Windows desktop**, because the IDE calls `HostForceFocus()` when it loads and takes the keyboard whatever window style it starts with. The cost: a wedged IDE there is invisible until you run again visible. Export `TBBUILD_SHOW=1` while you work interactively, and leave it unset for unattended runs. -**One IDE handles one project.** Loading a second project into a running IDE wedges it, so each project gets a fresh IDE, at roughly 6 to 8 seconds whatever its size. To make a batch of probes fast, run them at once: each run has a slot and a DevTools port of its own. Keep a question that might crash the compiler in a project of its own, so one bad probe cannot cost the others their answer. +**One IDE handles one project.** Each project gets a fresh IDE and compiler, at roughly 6 to 8 seconds whatever its size, so nothing one project leaves in the IDE can change the next one's result. To make a batch of probes fast, run them at once: each run has a slot and a DevTools port of its own. Keep a question that might crash the compiler in a project of its own, so one bad probe cannot cost the others their answer. **The IDE it starts ends with it.** The IDE runs inside a Windows job object, so when `tbbuild` ends --- finished, failed, or stopped with Ctrl+C --- every process the IDE started ends too, a restarting compiler included. The exceptions are `--keep`, where the IDE lives until you close it, and `--show`, where it starts on your desktop without the job. diff --git a/docs/Documentation/Tools-IDE.md b/docs/Documentation/Tools-IDE.md index 4bfd7ce67..e4b14ebbc 100644 --- a/docs/Documentation/Tools-IDE.md +++ b/docs/Documentation/Tools-IDE.md @@ -122,7 +122,7 @@ The pictures are repeatable. The IDE lays its page out at 100% whatever the disp Menus are cut out, transparent around the menu; dialogs are taken whole. A running program's window is taken once, not in two themes, at the display's scaling. Arrows, rings and numbered badges are drawn by the tool (`scripts/lib/shot-annotate.mjs`), anchored to the element they point at, so a retake after a new BETA puts them where the element now is. -A picture is written only when it differs from the file already there by more than the noise two captures of an unchanged screen show. Each is reported as `new`, `updated` or `unchanged`; a second run with nothing changed reports every picture `unchanged`. +A picture is written only when it differs from the file already there by more than the noise two captures of an unchanged screen show. The tool captures the page again and again, with no pause, until one capture is the file already there or two in a row are the same. When those two differ from the file, it goes on capturing, further and further apart, for up to 5.5 seconds, and keeps the file if a capture equals it, else the last two captures that agreed: some pictures are drawn in more than one version from one capture to the next, and some states take a moment to settle. Each picture is reported as `new`, `updated` or `unchanged`; a second run with nothing changed reports every picture `unchanged`. The Windows user name must never be in a published picture. Before each one is kept, the visible text of its page is searched for the name, and a picture whose page holds it is refused. @@ -139,7 +139,7 @@ Flags: - `--diffs` names a folder, outside `docs`, for a difference picture of each updated picture: the file on disk, the new picture and their difference side by side, with the region that differs magnified underneath. A matching pixel is dark grey; a differing one is yellow for one grey level, shading to red for large differences. File names end in `.dark` or `.light`. A `.capture-` file is written for each two captures of one state that disagree, and a `.noise` file for a picture left as it is because it differs from the file only by that variation. - `--jobs` is how many IDEs run at once, 6 by default and at most 16. Each runs on a private desktop (a slot from [`tbbroker`](Tools-Compiler#tbbroker)) with a work folder and an install copy of its own, and a DevTools port Windows picks. The setups wait in a queue, the longest first, and the three long ones (no-project, sample and customcontrols) are cut into three parts, each in an IDE of its own. Every line of output starts with the setup or part it is from. `--jobs 1` runs each setup whole, one after another. - The help setup's slot also carries a port from the broker for the add-in's detached window, which the add-in has to be told before it binds it. The add-in's saved settings (`tbDocsHelp`) are emptied for the run and, with the IDE's project state, put back at the end. -- `--svg` also draws each picture as SVG, from the page as it stands at the capture, and writes it beside the PNG as `X.svg` when it is close enough to the PNG (see [A picture as SVG](Authoring#a-picture-as-svg)). It needs Python with fontTools. What the SVG is drawn from --- the page's layout, styles and measurements --- is saved for each picture as a *bundle* in the folder `--bundles` names, `.svgshot-bundles` in the repository by default, so that [`replay.mjs`](#replay) can draw the SVG again without the IDE. Git ignores that folder, and it must stay outside `docs`: a bundle holds the Windows user name. +- `--svg` also draws each picture as SVG, from the page as it stands at the capture, and writes it beside the PNG as `X.svg` when it is close enough to the PNG (see [A picture as SVG](Authoring#a-picture-as-svg)). An SVG already there is rewritten only when its PNG is. It needs Python with fontTools. What the SVG is drawn from --- the page's layout, styles and measurements --- is saved for each picture as a *bundle* in the folder `--bundles` names, `.svgshot-bundles` in the repository by default, so that [`replay.mjs`](#replay) can draw the SVG again without the IDE. Git ignores that folder, and it must stay outside `docs`: a bundle holds the Windows user name. Exit codes: **0** every picture was written or was unchanged; **1** a picture failed (an element was not found, the page showed the user name, or a light picture was more than 32 pixels off the dark one's size), the add-in did not build, or the demo project does not compile; **2** the tool could not run: a refused command line, no IDE, no built site, a registry it could not record, or a crash; **3** the registry or the work folder was not put back (see the lines above). diff --git a/docs/Documentation/Tools-Samples.md b/docs/Documentation/Tools-Samples.md index 969652950..c2992d281 100644 --- a/docs/Documentation/Tools-Samples.md +++ b/docs/Documentation/Tools-Samples.md @@ -19,8 +19,8 @@ Compiles the documentation's own code samples, and surveys and probes where the node scripts/check_examples.mjs [--only ] [--census] [--propose [--apply]] [--report ] [--jobs N] [--batch N] - [--ide ] [--build | --llvm] [--keep] [--verbose] - [--json] + [--ide ] [--build | --llvm] [--keep] [--fresh] + [--verbose] [--json] Compiles the documentation's own code samples. No other gate evaluates a ` ```tb ` fence ([`check_code_regions.mjs`](Tools-Toolchain-Tests#check-code-regions) only protects its contents), so a sample that does not compile can ship with every gate green. This tool asks the compiler. [`examples.bat`](Tools#examplesbat) is how it is usually run, and [Authoring Pages](Authoring#checking-that-a-sample-compiles) is where a sample opts in. @@ -41,12 +41,13 @@ Each marked sample is generated into its own `Module tbx_`, packed with a | `--propose` | Compile the unmarked samples too, and list the ones that would pass. An unmarked sample that fails does not fail the run; a marked one does. It ends with the grouping `--report` prints. | | `--apply` | With `--propose`, add the bare marker to the fences that passed in that run. It never touches a fence that already carries markup, so a re-run is a no-op. Read the diff. | | `--report ` | Group the findings of a survey saved with `--propose --json`: by diagnostic, section, unresolved name, wrapper and page. It needs no compiler, so the slow run happens once and the grouping can be iterated on. | -| `--jobs ` | Concurrent IDE lanes. Default 4. Each lane has its own workspace and slot from [`tbbroker`](Tools-Compiler#tbbroker) (a private desktop), and each IDE a DevTools port Windows picks. | +| `--jobs ` | Concurrent IDE lanes. Default 4. Each lane has its own workspace and slot from [`tbbroker`](Tools-Compiler#tbbroker) (a private desktop), and each IDE a DevTools port Windows picks. A lane opens its projects one after another in one IDE. | | `--batch ` | Upper bound on samples per generated project. Default 120. The batcher packs fewer when there are lanes to fill. | | `--ide ` | `twinBASIC.exe`. Default: `$TB_IDE`, else the newest `twinBASIC_IDE_BETA_` on the Desktop. | | `--build` | Also build each project that compiles without errors. A project whose build fails is cut down, as for a crash, to the samples that fail it. A project whose compile has errors is not built: the run names its first error and counts its samples as "compiled but not built". | | `--llvm` | Build with LLVM (implies `--build`) by setting each project's compiler options to `+llvm`. It needs a Professional or Ultimate licence and exits 2 without one. A sample that fails under `--llvm` but not under a plain `--build` is one LLVM cannot generate code for. The run holds one lease on the LLVM cache server, which every lane's compiler shares, for its whole length, so that the server never ends with one lane's IDE. | -| `--keep` | Leave the generated projects on disk and print where. | +| `--keep` | Leave the generated projects on disk and print where. The folder stays until it is deleted by hand: a later run removes the folder of an earlier run that has ended, but not one that run was told to keep. | +| `--fresh` | Start a new IDE for every project, as `tbbuild` does, instead of opening each lane's projects one after another in one IDE. It reports the same findings, more slowly. It cannot be given with `--census` or `--report`, which start no IDE. | | `--verbose` | Report warnings as well as errors. Only errors ever fail the run. | | `--json` | One object on stdout; every report line moves to stderr. | @@ -95,6 +96,10 @@ path>` --- in any language, typically ` ```json ` --- is written into the genera **A diagnostic can also land outside every sample**, inside a referenced package's own source. For example, a generic instantiated with a type the project does not have is reported against the generic's own type parameter, in the package's file, and the sample that provoked it has no diagnostic of its own. The run fails with a row naming no page, and the same splitting isolates the sample, after one build of the empty template decides whether the row is the template's own. A split never cuts a `projname` group in half, and never separates a page's `hidden` context from the samples that need it. +**A lane opens project after project in one IDE.** Starting an IDE costs more than compiling a batch, so each lane starts one and opens every later project through the IDE's own **File > Open Project**, which closes the previous project and its compiler first. Before each switch the lane undoes what a project can leave in the IDE: the Safe Mode a compiler crash loop sets, and the trace mode a native exception turns on. A project that crashed the compiler is closed at once and never opened again in that IDE; the halves of its batch are other projects, and are. A lane gives its IDE up and starts a new one when a switch fails, after a harness fault, and after a compile that never settled, and a project that a reused IDE never reported open, or met a harness fault in, is built again in a new IDE before its result counts. The run's summary says how many IDEs were started and how many projects were opened in one already running. `--fresh` starts a new IDE for every project instead; the session that does this is `scripts/lib/tb-session.mjs`. + +**A batch can meet its time limit.** A batch whose compile does not settle within `test/harness.json`'s `compile` limit, or that the IDE never reports open, is not judged. It is one finding, against its first sample, and the run goes on. Splitting it would not help: a template can meet the limit with no samples in it, when what is slow is loading the template and the package it embeds. The same holds for the build of a template with no samples in it, which tells a template's own errors from a batch's: when it meets the limit twice, the batch that asked is not judged, and the next batch of that template asks again. + Four files under `scripts/lib/` belong to the tool: - `tb-fences.mjs` needs no compiler --- fence extraction, the markup and the classifier --- and is where a new key or slot goes. @@ -102,7 +107,7 @@ Four files under `scripts/lib/` belong to the tool: - `example-run.mjs` is what `check_run` needs without an IDE: which samples may be run, what a sample says it prints, the generated dispatcher, and the reading of the run's markers. - `tb-install.mjs` finds the IDE and the compiler beside it, and is shared with the two other IDE-driving tools. -Exit codes: **0** every marked sample compiles, or none is marked (`--report` always, and `--propose` when it found only unmarked samples that fail, which is advisory); **1** a marked sample does not compile, a marker is misused, a template does not compile, the compiler crashed on a project, `--build` or `--llvm` found a sample that fails the build, or a `check_run` sample raised an error, did not return or printed something other than the page says (the report names each); **2** the harness could not run: a refused command line, a failed self-test probe, no IDE, an unreadable `--report` file, a work folder it could not clear, an `--llvm` run on a Community or Personal licence, or a crash. +Exit codes: **0** every marked sample compiles, or none is marked (`--report` always, and `--propose` when it found only unmarked samples that fail, which is advisory); **1** a marked sample does not compile, a marker is misused, a template does not compile, the compiler crashed on a project, `--build` or `--llvm` found a sample that fails the build, a batch met its time limit, or a `check_run` sample raised an error, did not return or printed something other than the page says (the report names each); **2** the harness could not run: a refused command line, a failed self-test probe, no IDE, an unreadable `--report` file, a work folder it could not clear, an `--llvm` run on a Community or Personal licence, or a crash. ## package_tests.mjs {: #package-tests } @@ -221,7 +226,7 @@ The names come from every entry in `Attributes.md`, every name in the compiler's | `--verify N` | Rebuild N random probes and compare. | | `--out ` | Write the Markdown report there. Without it the report goes to standard output. | | `--dump-results ` | Also write every result, raw, as JSON: each name at each site with the answer for each argument shape. | -| `--work`, `--keep` | Where projects are staged, which must be under the system temp folder, and whether to keep them. | +| `--work`, `--keep` | Where projects are staged, which must be under the system temp folder, and whether to keep them. Kept projects stay until they are deleted by hand: a later run clears the default folders of runs that have ended, but not a kept one. | | `--preflight` | Build only the canaries, baselines and controls, and stop. About 20 seconds, and the way to check a change to a site. | | `--dry-run` | Count the probes and build nothing. | | `--timeout ` | The compile's limit for one build. Default: `compile` in `test/harness.json`. | diff --git a/docs/Documentation/Tools-Toolchain-Tests.md b/docs/Documentation/Tools-Toolchain-Tests.md index 0b86feb1e..eb2be997a 100644 --- a/docs/Documentation/Tools-Toolchain-Tests.md +++ b/docs/Documentation/Tools-Toolchain-Tests.md @@ -274,7 +274,7 @@ Exit codes: **0** every test passed, **1** a test failed. Runs the probes of [`check_examples.mjs`](Tools-Samples#check-examples) under Node's own test runner. `check_examples.mjs` runs them before every run too, but it needs a twinBASIC install, so it runs only by hand and never in CI. -The probes live in `scripts/lib/example-batches.mjs`. They cover how samples are packed into projects, how a batch whose build crashed the compiler is cut down to the samples that crash it, the canary every batch carries, the fence classifier, and how a `check_run` sample is refused, read for what it says it prints, called and judged. They need no IDE: crash isolation runs through a fake lane whose builds crash on the samples a probe chooses. +The probes live in `scripts/lib/example-batches.mjs`. They cover how samples are packed into projects, how a batch whose build crashed the compiler is cut down to the samples that crash it, a batch that meets its time limit, the canary every batch carries, the fence classifier, how a `check_run` sample is refused, read for what it says it prints, called and judged, and how a lane's IDE opens project after project: the switch, each case in which it starts a new IDE instead, and what it resets after a compiler crash, and the sweep at the start of a run, which removes an ended run's folder but not one kept with `--keep`. They need no IDE: crash isolation runs through a fake lane whose builds crash on the samples a probe chooses, and the lane's IDE through a page that is a plain object. The same file runs the probes of [`vb6run.mjs`](Tools-Defects#vb6run), from `scripts/lib/vb6.mjs`: the `Debug.Print` rewrite on strings, comments, statement separators, single-line `If` and a bare `Debug.Print`, the generated modules, the reading of VB6's build log and the Windows-1252 encoding. It also holds the probes for a bug reproducer's VB6 project (see [`bug_repro.mjs`](Tools-Defects#bug-repro)): which files go into its zip, what refuses a project (the `PngDump.bas` picture module among the sources that must pass), and the project file the build copy gets. They need no VB6. No browser, no built tree, well under a second. diff --git a/docs/Documentation/Tools.md b/docs/Documentation/Tools.md index a9669f08b..887d4bde4 100644 --- a/docs/Documentation/Tools.md +++ b/docs/Documentation/Tools.md @@ -246,7 +246,7 @@ Compiles the documentation's own twinBASIC code samples --- every ` ```tb ` fenc **It is not one of the gates, and must not become one.** It is absent from `build.bat`, `check.bat`, `test.bat` and both CI workflows, because it needs a twinBASIC install (`npm install` alone must suffice to build the docs) and Windows with a private desktop and a CDP-reachable WebView2 (the CI box has neither). An IDE cold start also takes 6 to 8 seconds, against four for a whole site build. A person runs it, as with [`sweep_a11y.mjs`](Tools-Site-Checks#sweep-a11y). -Exit codes, those of [`check_examples.mjs`](Tools-Samples#check-examples): **0** clean, **1** a sample does not compile, or does not run as its page says, **2** the harness failed. +Exit codes, those of [`check_examples.mjs`](Tools-Samples#check-examples): **0** clean, **1** a sample does not compile, does not run as its page says, or is in a batch that met its time limit, **2** the harness failed. ### package-tests.bat {: #package-testsbat } diff --git a/docs/Features/Advanced/Classes-and-Modules.md b/docs/Features/Advanced/Classes-and-Modules.md index 2535077ec..22fceb821 100644 --- a/docs/Features/Advanced/Classes-and-Modules.md +++ b/docs/Features/Advanced/Classes-and-Modules.md @@ -40,13 +40,79 @@ then created by `Dim mc As MyClass = New MyClass(123)`, which sets `MyClassVar` > [!IMPORTANT] > A class that is not `Private` is exposed to COM, and COM creates objects without arguments. So a class whose `Sub New` takes arguments must be `Private`, have the `[COMCreatable(False)]` attribute, or also have a constructor that takes no arguments --- a `Class_Initialize()`, or a second `Sub New` with no parameters. Otherwise it fails to compile with TB5135. `Class_Initialize()` replaces `New` in callers of a compiled OCX. +### `Class_Initialize` or `Sub New`? + +Both are constructors: code that runs once, as the object is created, before anything else can use it. Only one of them runs for any one object. `Class_Initialize` is inherited from VB6 and VBA, and follows COM's rule that an object is created without arguments; `Sub New` is twinBASIC's addition. They differ in what they can take and who can use them: + +| | `Class_Initialize` | `Sub New` | +|---|---|---| +| Arguments | None. | Any. A class can have several `Sub New`s with different parameters, and `New` picks the one its arguments match. | +| VB6 and VBA | The same as in VB6 and VBA. | twinBASIC only. | +| COM clients | Can create the object. | Can create the object only through a `Sub New` that can be called without arguments: one with no parameters, or one whose parameters are all `Optional`, which then get their default values. | +| [`As New`](../../tB/Core/New) | Yes. | Only a `Sub New` that can be called without arguments. | +| Called from code | Possible, but it is an event handler, and the compiler warns: [TB0008](../Compiler-IDE/Compiler-Warnings#tb0008-suspicious-call). | Not possible: TB5053, *Cannot call New() constructor directly*. A derived class calls its base class's, as `Base.New(...)`. | + +Which to use: + +- **`Class_Initialize`** when setting up the object needs no information from the caller --- creating a `Collection`, reading a default --- and for code that must also compile in VB6 or VBA. +- **`Sub New(...)`** when the object is not usable until it is given something: a name, a file path, a connection. Requiring it as an argument means no caller can forget it, and no code has to check for an object that was created but not yet set up. It also sets [`ReadOnly`](#readonly-variables) fields, which nothing outside a constructor can change. +- **Both** when the class should be creatable with arguments, and also without them --- by `As New`, or by a COM client. The two never run one after the other, so code both of them need goes in a `Private` procedure that each calls. + +Field initializers --- `Private _name As String = "nobody"` --- run before either constructor, whichever one `New` picks. + +A class cannot have both a `Class_Initialize` and a `Sub New` without parameters: a plain `New` would match both, and fails with TB5073. Choose one of the two. + +### Example: both constructors + +`Greeter` can be created with a name or without one. The common part of the setup is in `Setup`, which both constructors call: + +```tb check_build projname=ctor-both slot=file +Class Greeter + Private _name As String = "nobody" + + Private Sub Class_Initialize() + Debug.Print "Class_Initialize, _name = " & _name + Setup "world" + End Sub + + Public Sub New(ByVal Name As String) + Debug.Print "Sub New, _name = " & _name + Setup Name + End Sub + + Private Sub Setup(ByVal Name As String) + _name = Name + End Sub + + Public Function Greet() As String + Return "Hello, " & _name & "!" + End Function +End Class +``` + +```tb check_run projname=ctor-both +Dim a As Greeter = New Greeter +Debug.Print a.Greet() +Dim b As Greeter = New Greeter("Ada") +Debug.Print b.Greet() +' Output: +' Class_Initialize, _name = nobody +' Hello, world! +' Sub New, _name = nobody +' Hello, Ada! +``` + +`New Greeter("Ada")` runs `Sub New` only: `Class_Initialize` does not run first. Both constructors see the field's initial value, `nobody`. + +A class that [inherits](../Language/Inheritance#inherits-for-complete-oop) another runs the base class's constructor as well as its own. [Constructors in Derived Classes](../Language/Inheritance#constructors-in-derived-classes) says which of the base's constructors runs, and what the derived class must do so that the base is set up. + ## Private/Public Modifiers for Modules and Classes A private module or class won't have its members entered into the type library in an ActiveX project. ## ReadOnly Variables -In a class, module-level variables can be declared as `ReadOnly`, e.g. `Private ReadOnly mStartDate As Date`. This allows more complex constant assignments: you can use a function return to set it inline, `Private ReadOnly mStartDate As Date = Now()`, or `ReadOnly` constants can be set in `Class_Initialize` or `Sub New(...)` (see parameterized class constructors above), but everywhere else, they can only be read, not changed. +In a class, module-level variables can be declared as `ReadOnly`, e.g. `Private ReadOnly mStartDate As Date`. This allows more complex constant assignments: a built-in function's result can set it inline, `Private ReadOnly mStartDate As Date = Now()` --- a procedure of the project cannot, see [What an Initializer Can Use](../Language/Inline-Initialization#what-an-initializer-can-use) --- or `ReadOnly` constants can be set in `Class_Initialize` or `Sub New(...)` (see parameterized class constructors above), but everywhere else, they can only be read, not changed. ## Get/Let/Set Notification for Class Public Variables diff --git a/docs/Features/Images/22660f54-ff5d-4b21-93d3-39715f1f35ed.light.png b/docs/Features/Images/22660f54-ff5d-4b21-93d3-39715f1f35ed.light.png index 3d624bf97..05386a151 100644 Binary files a/docs/Features/Images/22660f54-ff5d-4b21-93d3-39715f1f35ed.light.png and b/docs/Features/Images/22660f54-ff5d-4b21-93d3-39715f1f35ed.light.png differ diff --git a/docs/Features/Images/22660f54-ff5d-4b21-93d3-39715f1f35ed.png b/docs/Features/Images/22660f54-ff5d-4b21-93d3-39715f1f35ed.png index 3adeebdf8..38f4944b7 100644 Binary files a/docs/Features/Images/22660f54-ff5d-4b21-93d3-39715f1f35ed.png and b/docs/Features/Images/22660f54-ff5d-4b21-93d3-39715f1f35ed.png differ diff --git a/docs/Features/Images/351d0147-cad3-4e16-89e5-0a9e43496740.light.png b/docs/Features/Images/351d0147-cad3-4e16-89e5-0a9e43496740.light.png index 8021a8277..8c68d27ab 100644 Binary files a/docs/Features/Images/351d0147-cad3-4e16-89e5-0a9e43496740.light.png and b/docs/Features/Images/351d0147-cad3-4e16-89e5-0a9e43496740.light.png differ diff --git a/docs/Features/Images/351d0147-cad3-4e16-89e5-0a9e43496740.png b/docs/Features/Images/351d0147-cad3-4e16-89e5-0a9e43496740.png index b882c3f3b..ab81011da 100644 Binary files a/docs/Features/Images/351d0147-cad3-4e16-89e5-0a9e43496740.png and b/docs/Features/Images/351d0147-cad3-4e16-89e5-0a9e43496740.png differ diff --git a/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.light.png b/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.light.png index 4d2062a2a..5e818e297 100644 Binary files a/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.light.png and b/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.light.png differ diff --git a/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.light.svg b/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.light.svg index 54f433882..4bd816176 100644 --- a/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.light.svg +++ b/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.light.svg @@ -1 +1 @@ -+ menuBIU8pt+-PROPERTIESLAYOUTGENERALDDETabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }Dock0 - vbDockNoneTagLinkItemLinkMode0 - vbLinkNoneLinkTimeout50LinkTopicText1    TextBox0 - vbDockNone1 - vbDockLeft2 - vbDockTop3 - vbDockRight4 - vbDockBottom5 - vbDockFill ++ menuBIU8pt+-PROPERTIESLAYOUTGENERALDDETabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }Dock0 - vbDockNoneDockOrder0TagLinkItemLinkMode0 - vbLinkNoneLinkTimeout50Text1    TextBox5 - vbDockFill4 - vbDockBottom3 - vbDockRight2 - vbDockTop1 - vbDockLeft0 - vbDockNone diff --git a/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.png b/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.png index 25c18f254..d3a60a419 100644 Binary files a/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.png and b/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.png differ diff --git a/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.svg b/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.svg index 334516854..ac546423f 100644 --- a/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.svg +++ b/docs/Features/Images/4c8b881e-1216-4819-a558-d2ce20f47fcd.svg @@ -1 +1 @@ -+ menuBIU8pt+-PROPERTIESLAYOUTGENERALDDETabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }Dock0 - vbDockNoneTagLinkItemLinkMode0 - vbLinkNoneLinkTimeout50LinkTopicText1    TextBox0 - vbDockNone1 - vbDockLeft2 - vbDockTop3 - vbDockRight4 - vbDockBottom5 - vbDockFill ++ menuBIU8pt+-PROPERTIESLAYOUTGENERALDDETabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }Dock0 - vbDockNoneDockOrder0TagLinkItemLinkMode0 - vbLinkNoneLinkTimeout50Text1    TextBox5 - vbDockFill4 - vbDockBottom3 - vbDockRight2 - vbDockTop1 - vbDockLeft0 - vbDockNone diff --git a/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.light.png b/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.light.png index 55c6d5ed1..0417f563f 100644 Binary files a/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.light.png and b/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.light.png differ diff --git a/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.light.svg b/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.light.svg index 4ba2bf3b9..2f3ca9cbc 100644 --- a/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.light.svg +++ b/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.light.svg @@ -1 +1 @@ -EDITOR 1Project SettingsBuilt ExecutablesIf YES, the compiler will include procedure name symbols in built EXEs and DLLs. These symbols are used when enumerating the live callstackinformation. When disabled, ErrorStackFrame interface will return "{unknown}" for symbols in built executables. minorly increases the size of built executables, but does not harm runtime performance.Trace FlagsTrace Procedure Entry and Exit pointsTrace Procedure Arguments (requires Trace Procedure Entry and Exit points, also)Trace IDispatch::QueryInterface callsTrace IDispatch::GetIDsOfNames callsTrace IDispatch::Invoke callsTrace Window (HWND) MessagesTrace Debug.TracePrint outputBuffered Trace Log File Writing (do not use for tracing a hard crash)Trace IClassFactory::CreateInstance and IClassFactory2::CreateInstanceLic calls for exposed COM classesTrace DllGetClassObject calls (COM/AX creation of your exposed classes)Trace RaiseEvent calls and argumentsUsed in combination with `Compilation: Trace Output`Trace OutputUsed in combination with `Compilation: Trace Flags`.Full path where the log file will be saved.You can use the following special placeholders in the path:${SESSIONID} == unique GUID per session and per thread${DATE} == current date in YYYYMMDD format${TIME} == current time in HHNNSS format${DEBUG} == output to IDE DEBUG CONSOLE onlyIMPORTANT: you MUST use ${SESSIONID} in your path to ensure multiple threads can create trace logs.(enter text to filter) +EDITOR 1Project SettingsBuilt ExecutablesIf YES, the compiler will include procedure name symbols in built EXEs and DLLs. These symbols are used when enumerating the live callstackinformation. When disabled, ErrorStackFrame interface will return "{unknown}" for symbols in built executables. minorly increases the size of built executables, but does not harm runtime performance.Trace FlagsTrace Procedure Entry and Exit pointsTrace Procedure Arguments (requires Trace Procedure Entry and Exit points, also)Trace IDispatch::QueryInterface callsTrace IDispatch::GetIDsOfNames callsTrace IDispatch::Invoke callsTrace Window (HWND) MessagesTrace Debug.TracePrint outputBuffered Trace Log File Writing (do not use for tracing a hard crash)Trace IClassFactory::CreateInstance and IClassFactory2::CreateInstanceLic calls for exposed COM classesTrace DllGetClassObject calls (COM/AX creation of your exposed classes)Trace RaiseEvent calls and argumentsUsed in combination with `Compilation: Trace Output`Trace OutputUsed in combination with `Compilation: Trace Flags`.Full path where the log file will be saved.You can use the following special placeholders in the path:${SESSIONID} == unique GUID per session and per thread${DATE} == current date in YYYYMMDD format${TIME} == current time in HHNNSS format${DEBUG} == output to IDE DEBUG CONSOLE onlyIMPORTANT: you MUST use ${SESSIONID} in your path to ensure multiple threads can create trace logs.(enter text to filter) diff --git a/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.svg b/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.svg index c3233fd0b..4451a8254 100644 --- a/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.svg +++ b/docs/Features/Images/4fc2bf99-2bec-4943-837d-21038d791574.svg @@ -1 +1 @@ -win32EDITOR 1Project SettingsBuilt ExecutablesIf YES, the compiler will include procedure name symbols in built EXEs and DLLs. These symbols are used when enumerating the live callstackinformation. When disabled, ErrorStackFrame interface will return "{unknown}" for symbols in built executables. minorly increases the size of built executables, but does not harm runtime performance.Trace FlagsTrace Procedure Entry and Exit pointsTrace Procedure Arguments (requires Trace Procedure Entry and Exit points, also)Trace IDispatch::QueryInterface callsTrace IDispatch::GetIDsOfNames callsTrace IDispatch::Invoke callsTrace Window (HWND) MessagesTrace Debug.TracePrint outputBuffered Trace Log File Writing (do not use for tracing a hard crash)Trace IClassFactory::CreateInstance and IClassFactory2::CreateInstanceLic calls for exposed COM classesTrace DllGetClassObject calls (COM/AX creation of your exposed classes)Trace RaiseEvent calls and argumentsUsed in combination with `Compilation: Trace Output`Trace OutputUsed in combination with `Compilation: Trace Flags`.Full path where the log file will be saved.You can use the following special placeholders in the path:${SESSIONID} == unique GUID per session and per thread${DATE} == current date in YYYYMMDD format${TIME} == current time in HHNNSS format${DEBUG} == output to IDE DEBUG CONSOLE onlyIMPORTANT: you MUST use ${SESSIONID} in your path to ensure multiple threads can create trace logs.(enter text to filter) +win32EDITOR 1Project SettingsBuilt ExecutablesIf YES, the compiler will include procedure name symbols in built EXEs and DLLs. These symbols are used when enumerating the live callstackinformation. When disabled, ErrorStackFrame interface will return "{unknown}" for symbols in built executables. minorly increases the size of built executables, but does not harm runtime performance.Trace FlagsTrace Procedure Entry and Exit pointsTrace Procedure Arguments (requires Trace Procedure Entry and Exit points, also)Trace IDispatch::QueryInterface callsTrace IDispatch::GetIDsOfNames callsTrace IDispatch::Invoke callsTrace Window (HWND) MessagesTrace Debug.TracePrint outputBuffered Trace Log File Writing (do not use for tracing a hard crash)Trace IClassFactory::CreateInstance and IClassFactory2::CreateInstanceLic calls for exposed COM classesTrace DllGetClassObject calls (COM/AX creation of your exposed classes)Trace RaiseEvent calls and argumentsUsed in combination with `Compilation: Trace Output`Trace OutputUsed in combination with `Compilation: Trace Flags`.Full path where the log file will be saved.You can use the following special placeholders in the path:${SESSIONID} == unique GUID per session and per thread${DATE} == current date in YYYYMMDD format${TIME} == current time in HHNNSS format${DEBUG} == output to IDE DEBUG CONSOLE onlyIMPORTANT: you MUST use ${SESSIONID} in your path to ensure multiple threads can create trace logs.(enter text to filter) diff --git a/docs/Features/Images/54ed49d8-b434-45e3-9e63-a1fe75cdf814.light.png b/docs/Features/Images/54ed49d8-b434-45e3-9e63-a1fe75cdf814.light.png index 037617740..0027957b2 100644 Binary files a/docs/Features/Images/54ed49d8-b434-45e3-9e63-a1fe75cdf814.light.png and b/docs/Features/Images/54ed49d8-b434-45e3-9e63-a1fe75cdf814.light.png differ diff --git a/docs/Features/Images/54ed49d8-b434-45e3-9e63-a1fe75cdf814.png b/docs/Features/Images/54ed49d8-b434-45e3-9e63-a1fe75cdf814.png index 4f0a74cf1..4a2913791 100644 Binary files a/docs/Features/Images/54ed49d8-b434-45e3-9e63-a1fe75cdf814.png and b/docs/Features/Images/54ed49d8-b434-45e3-9e63-a1fe75cdf814.png differ diff --git a/docs/Features/Images/569099635-bc9553a6-fcce-487d-a478-dbee557f33b1.light.png b/docs/Features/Images/569099635-bc9553a6-fcce-487d-a478-dbee557f33b1.light.png index 8fba10511..f02c9353b 100644 Binary files a/docs/Features/Images/569099635-bc9553a6-fcce-487d-a478-dbee557f33b1.light.png and b/docs/Features/Images/569099635-bc9553a6-fcce-487d-a478-dbee557f33b1.light.png differ diff --git a/docs/Features/Images/569099635-bc9553a6-fcce-487d-a478-dbee557f33b1.png b/docs/Features/Images/569099635-bc9553a6-fcce-487d-a478-dbee557f33b1.png index 53f1d854c..e8aab19f5 100644 Binary files a/docs/Features/Images/569099635-bc9553a6-fcce-487d-a478-dbee557f33b1.png and b/docs/Features/Images/569099635-bc9553a6-fcce-487d-a478-dbee557f33b1.png differ diff --git a/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.light.png b/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.light.png index bb7d705d3..252535260 100644 Binary files a/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.light.png and b/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.light.png differ diff --git a/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.light.svg b/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.light.svg index 0ca5181d5..a2c00fcf8 100644 --- a/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.light.svg +++ b/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.light.svg @@ -1 +1 @@ -EDITOR 1PROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdProject SettingsUse Project ID for type library IDIf YES, the compiler will use the project ID for the type library ID. If NO, a unique type library ID will be generated during the build process.Build Output PathEnter the full path to the output file that will be created by the compiler. Available variables: ${SourcePath}, ${ProjectName}, ${ProjectID},${FileExtension}, ${Architecture}, ${VersionMajor}, ${VersionMinor}, ${VersionBuild}, ${VersionRevision}${Architecture} == "win32" / "win64"ActiveX Fusion Host EXEOutput PathEnter the full path to the output file that will be created by the compiler for the ActiveX Fusion host companion EXE. Available variables:${SourcePath}, ${ProjectName}, ${ProjectID}, ${FileExtension}, ${Architecture}, ${VersionMajor}, ${VersionMinor}, ${VersionBuild},${VersionRevision}${Architecture} == "win32host" / "win64host"If not specified, the template set for `Build Output Path` will be used when necessary.PLEASE NOTEThe runtime location of this file (for built executables) should be the same folder as the root project EXE, otherwise you must override theexpected folder path by setting App.FusionHostExePath during your startup routine.TB0019    Implicit enumeration conversionTB0020    Suspicious interface conversionTB0021    Implicit enumeration conversion to/from numericTB0022    Suspicious assignment (e.g. array subtype mismatch)TB0023    Unusual use of implicit field generated from an Implements statementTB0024    Unused local variableTB0025    Unused procedure parameterTB0026    Mismatched delegate typesTB0027    Return Without GosubTB0028    Control is overshadowed by base form method or property of the same nameTB0029    Missing PtrSafe syntax on API Declares for VBA7 compatibilityTB0030    Declare Alias is not required as it is identical to the declared nameTB0031    Suspicious use of Erase statementTB0032    Unused line labelTB0032    Duplicate definition, consider changing the name to be uniqueIGNOREIGNOREIGNOREIGNOREWARNINGWARNINGIGNOREIGNOREWARNINGWARNINGWARNINGIGNOREHINTWARNINGWARNINGWARNINGCOMPILER DEFAULT - No${SourcePath}\Build\${ProjectName}_${Architecture}.${FileExtension}Package TWINPACK(enter text to filter) +EDITOR 1PROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdProject SettingsUse Project ID for type library IDIf YES, the compiler will use the project ID for the type library ID. If NO, a unique type library ID will be generated during the build process.Build Output PathEnter the full path to the output file that will be created by the compiler. Available variables: ${SourcePath}, ${ProjectName}, ${ProjectID},${FileExtension}, ${Bitness}, ${Architecture}, ${VersionMajor}, ${VersionMinor}, ${VersionBuild}, ${VersionRevision}${Architecture} == "win32" / "win64"${Bitness} == "32" / "64"ActiveX Fusion Host EXEOutput PathEnter the full path to the output file that will be created by the compiler for the ActiveX Fusion host companion EXE. Available variables:${SourcePath}, ${ProjectName}, ${ProjectID}, ${FileExtension}, ${Bitness}, ${Architecture}, ${VersionMajor}, ${VersionMinor}, ${VersionBuild},${VersionRevision}${Architecture} == "win32host" / "win64host"${Bitness} == "32" / "64"If not specified, the template set for `Build Output Path` will be used when necessary.PLEASE NOTEThe runtime location of this file (for built executables) should be the same folder as the root project EXE, otherwise you must override theexpected folder path by setting App.FusionHostExePath during your startup routine.TB0019    Implicit enumeration conversionTB0020    Suspicious interface conversionTB0021    Implicit enumeration conversion to/from numericTB0022    Suspicious assignment (e.g. array subtype mismatch)TB0023    Unusual use of implicit field generated from an Implements statementTB0024    Unused local variableTB0025    Unused procedure parameterTB0026    Mismatched delegate typesTB0027    Return Without GosubTB0028    Control is overshadowed by base form method or property of the same nameTB0029    Missing PtrSafe syntax on API Declares for VBA7 compatibilityTB0030    Declare Alias is not required as it is identical to the declared nameTB0031    Suspicious use of Erase statementTB0032    Unused line labelTB0032    Duplicate definition, consider changing the name to be uniqueIGNOREIGNOREIGNOREIGNOREWARNINGWARNINGIGNOREIGNOREWARNINGWARNINGWARNINGIGNOREHINTWARNINGWARNINGWARNINGCOMPILER DEFAULT - No${SourcePath}\Build\${ProjectName}_${Architecture}.${FileExtension}(enter text to filter) diff --git a/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.png b/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.png index cc07a3518..18d08dc2a 100644 Binary files a/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.png and b/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.png differ diff --git a/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.svg b/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.svg index 7dd5c3ea5..c2c9e5d1f 100644 --- a/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.svg +++ b/docs/Features/Images/569150839-9ffc87ac-250d-40a4-bb47-669b607ad76f.svg @@ -1 +1 @@ -win32100%EDITOR 1PROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdProject SettingsUse Project ID for type library IDIf YES, the compiler will use the project ID for the type library ID. If NO, a unique type library ID will be generated during the build process.Build Output PathEnter the full path to the output file that will be created by the compiler. Available variables: ${SourcePath}, ${ProjectName}, ${ProjectID},${FileExtension}, ${Architecture}, ${VersionMajor}, ${VersionMinor}, ${VersionBuild}, ${VersionRevision}${Architecture} == "win32" / "win64"ActiveX Fusion Host EXEOutput PathEnter the full path to the output file that will be created by the compiler for the ActiveX Fusion host companion EXE. Available variables:${SourcePath}, ${ProjectName}, ${ProjectID}, ${FileExtension}, ${Architecture}, ${VersionMajor}, ${VersionMinor}, ${VersionBuild},${VersionRevision}${Architecture} == "win32host" / "win64host"If not specified, the template set for `Build Output Path` will be used when necessary.PLEASE NOTEThe runtime location of this file (for built executables) should be the same folder as the root project EXE, otherwise you must override theexpected folder path by setting App.FusionHostExePath during your startup routine.TB0019    Implicit enumeration conversionTB0020    Suspicious interface conversionTB0021    Implicit enumeration conversion to/from numericTB0022    Suspicious assignment (e.g. array subtype mismatch)TB0023    Unusual use of implicit field generated from an Implements statementTB0024    Unused local variableTB0025    Unused procedure parameterTB0026    Mismatched delegate typesTB0027    Return Without GosubTB0028    Control is overshadowed by base form method or property of the same nameTB0029    Missing PtrSafe syntax on API Declares for VBA7 compatibilityTB0030    Declare Alias is not required as it is identical to the declared nameTB0031    Suspicious use of Erase statementTB0032    Unused line labelTB0032    Duplicate definition, consider changing the name to be uniqueIGNOREIGNOREIGNOREIGNOREWARNINGWARNINGIGNOREIGNOREWARNINGWARNINGWARNINGIGNOREHINTWARNINGWARNINGWARNINGCOMPILER DEFAULT - No${SourcePath}\Build\${ProjectName}_${Architecture}.${FileExtension}Package TWINPACK(enter text to filter) +win32100%EDITOR 1PROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdProject SettingsUse Project ID for type library IDIf YES, the compiler will use the project ID for the type library ID. If NO, a unique type library ID will be generated during the build process.Build Output PathEnter the full path to the output file that will be created by the compiler. Available variables: ${SourcePath}, ${ProjectName}, ${ProjectID},${FileExtension}, ${Bitness}, ${Architecture}, ${VersionMajor}, ${VersionMinor}, ${VersionBuild}, ${VersionRevision}${Architecture} == "win32" / "win64"${Bitness} == "32" / "64"ActiveX Fusion Host EXEOutput PathEnter the full path to the output file that will be created by the compiler for the ActiveX Fusion host companion EXE. Available variables:${SourcePath}, ${ProjectName}, ${ProjectID}, ${FileExtension}, ${Bitness}, ${Architecture}, ${VersionMajor}, ${VersionMinor}, ${VersionBuild},${VersionRevision}${Architecture} == "win32host" / "win64host"${Bitness} == "32" / "64"If not specified, the template set for `Build Output Path` will be used when necessary.PLEASE NOTEThe runtime location of this file (for built executables) should be the same folder as the root project EXE, otherwise you must override theexpected folder path by setting App.FusionHostExePath during your startup routine.TB0019    Implicit enumeration conversionTB0020    Suspicious interface conversionTB0021    Implicit enumeration conversion to/from numericTB0022    Suspicious assignment (e.g. array subtype mismatch)TB0023    Unusual use of implicit field generated from an Implements statementTB0024    Unused local variableTB0025    Unused procedure parameterTB0026    Mismatched delegate typesTB0027    Return Without GosubTB0028    Control is overshadowed by base form method or property of the same nameTB0029    Missing PtrSafe syntax on API Declares for VBA7 compatibilityTB0030    Declare Alias is not required as it is identical to the declared nameTB0031    Suspicious use of Erase statementTB0032    Unused line labelTB0032    Duplicate definition, consider changing the name to be uniqueIGNOREIGNOREIGNOREIGNOREWARNINGWARNINGIGNOREIGNOREWARNINGWARNINGWARNINGIGNOREHINTWARNINGWARNINGWARNINGCOMPILER DEFAULT - No${SourcePath}\Build\${ProjectName}_${Architecture}.${FileExtension}(enter text to filter) diff --git a/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.light.png b/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.light.png index 75a8465ba..5ba72d2d9 100644 Binary files a/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.light.png and b/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.light.png differ diff --git a/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.light.svg b/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.light.svg index 970710846..93f4e605c 100644 --- a/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.light.svg +++ b/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.light.svg @@ -1 +1 @@ -ImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinGreeting.twinIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeImport from file...LampsAppGlobalClassProjectcefPackagecefPackagecefPackageWinNativeCommonCtlsCustomControlsCustomControlsPackagetbIDEAssertVBWebView2PackageWinEventLogLibWinNamedPipesLibWinServicesLibTBMANLIB1.0.0.0[BUILT-IN] twinBASIC - App global class object1.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1091.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1451.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v491.0.0.0[BUILT-IN] twinBASIC - Common Controls Compatibility Package0.0.0.1[BUILT-IN] twinBASIC - CustomControls DESIGNER Package0.0.0.24[BUILT-IN] twinBASIC - CustomControls Package0.0.0.5[BUILT-IN] twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN] twinBASIC - Unit Testing Package0.0.0.24[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0[BUILT-IN] twinBASIC - WinServicesLib0.1.0.0✨ – A Rapid Development Toolkit for TwinBasic1.0.29.0Library SymbolEmbeddedVersion +ImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinGreeting.twinIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeImport from file...LampsAppGlobalClassProjectcefPackagecefPackagecefPackageWinNativeCommonCtlsCustomControlsCustomControlsPackagetbIDEAssertVBWebView2PackageWinEventLogLibWinNamedPipesLibWinServicesLibTBMANLIB1.0.0.0[BUILT-IN] twinBASIC - App global class object1.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1091.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1451.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v491.0.0.0[BUILT-IN] twinBASIC - Common Controls Compatibility Package0.0.0.1[BUILT-IN] twinBASIC - CustomControls DESIGNER Package0.0.0.24[BUILT-IN] twinBASIC - CustomControls Package0.0.0.5[BUILT-IN] twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN] twinBASIC - Unit Testing Package0.0.0.24[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0[BUILT-IN] twinBASIC - WinServicesLib0.1.0.0✨ – A Rapid Development Toolkit for TwinBasic1.0.29.0Library SymbolEmbeddedVersion diff --git a/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.png b/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.png index 2aa0df1f4..55158a524 100644 Binary files a/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.png and b/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.png differ diff --git a/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.svg b/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.svg index e6b84f26f..743537bb7 100644 --- a/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.svg +++ b/docs/Features/Images/5951dab6-738e-4b63-83c4-3331ec6d36b9.svg @@ -1 +1 @@ -ImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinGreeting.twinIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeImport from file...LampsAppGlobalClassProjectcefPackagecefPackagecefPackageWinNativeCommonCtlsCustomControlsCustomControlsPackagetbIDEAssertVBWebView2PackageWinEventLogLibWinNamedPipesLibWinServicesLibTBMANLIB1.0.0.0[BUILT-IN] twinBASIC - App global class object1.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1091.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1451.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v491.0.0.0[BUILT-IN] twinBASIC - Common Controls Compatibility Package0.0.0.1[BUILT-IN] twinBASIC - CustomControls DESIGNER Package0.0.0.24[BUILT-IN] twinBASIC - CustomControls Package0.0.0.5[BUILT-IN] twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN] twinBASIC - Unit Testing Package0.0.0.24[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0[BUILT-IN] twinBASIC - WinServicesLib0.1.0.0✨ – A Rapid Development Toolkit for TwinBasic1.0.29.0Library SymbolEmbeddedVersion +ImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinGreeting.twinIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeImport from file...LampsAppGlobalClassProjectcefPackagecefPackagecefPackageWinNativeCommonCtlsCustomControlsCustomControlsPackagetbIDEAssertVBWebView2PackageWinEventLogLibWinNamedPipesLibWinServicesLibTBMANLIB1.0.0.0[BUILT-IN] twinBASIC - App global class object1.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1091.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1451.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v491.0.0.0[BUILT-IN] twinBASIC - Common Controls Compatibility Package0.0.0.1[BUILT-IN] twinBASIC - CustomControls DESIGNER Package0.0.0.24[BUILT-IN] twinBASIC - CustomControls Package0.0.0.5[BUILT-IN] twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN] twinBASIC - Unit Testing Package0.0.0.24[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0[BUILT-IN] twinBASIC - WinServicesLib0.1.0.0✨ – A Rapid Development Toolkit for TwinBasic1.0.29.0Library SymbolEmbeddedVersion diff --git a/docs/Features/Images/9a5c50d5-a9f8-44a7-96f7-ae84548bd7ef.png b/docs/Features/Images/9a5c50d5-a9f8-44a7-96f7-ae84548bd7ef.png index 7a3c27eb2..26a301082 100644 Binary files a/docs/Features/Images/9a5c50d5-a9f8-44a7-96f7-ae84548bd7ef.png and b/docs/Features/Images/9a5c50d5-a9f8-44a7-96f7-ae84548bd7ef.png differ diff --git a/docs/Features/Images/IDE-FeatureMap.light.png b/docs/Features/Images/IDE-FeatureMap.light.png index bf5ca3628..0e726f6e5 100644 Binary files a/docs/Features/Images/IDE-FeatureMap.light.png and b/docs/Features/Images/IDE-FeatureMap.light.png differ diff --git a/docs/Features/Images/IDE-FeatureMap.light.svg b/docs/Features/Images/IDE-FeatureMap.light.svg index 61dd71389..244b44d59 100644 --- a/docs/Features/Images/IDE-FeatureMap.light.svg +++ b/docs/Features/Images/IDE-FeatureMap.light.svg @@ -1 +1 @@ -tB Services: OPERATIONALULTIMATE EDITION175.6MBin use  |  100ui objects  |  16gdi objectsFileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32100%PREVIEWPROJECT EXPLORERFeatureTourImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesInventory.twinMainModule.twinTypes.twinOUTLINEInventoryHISTORY09:12Inventory.Add10:05Inventory.Find11:48Inventory.TotalDIAGNOSTICS0300Inventory.twinMainModule.twin[18,13]TB0003Datatype has not been explicitly declared so will default to Variant[19,13]TB0003Datatype has not been explicitly declared so will default to Variant[6,13]TB0003Datatype has not been explicitly declared so will default to VariantEDITOR 1Inventory(general)ItemByIndexInventory.twin1920212223242526272829303132333435363738394041424344454647484950515253545556DimnoteDimpriceAsDoubleFori=0Tocount-1Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIf🠈 items(i).Quantity > 100EndIf🠈 items(i).Quantity > 0Next🠈 i = 0 To count - 1Total=subtotalEndFunction🠈 TotalPublicFunctionFind(ByValnameAsString)AsLongFind=-1DimiAsLongFori=0Tocount-1Ifitems(i).Name=nameThenFind=iExitForEndIf🠈 items(i).Name = nameNext🠈 i = 0 To count - 1EndFunction🠈 FindPublicSubClear()Eraseitemscount=0EndSub🠈 ClearPublicFunctionItemByIndex(ByValpositionAsLong)AsStockItemItemByIndex=items(position)EndFunction🠈 ItemByIndexEndClass🠈 Inventory16PublicFunctionTotal(ByValtaxRateAsDouble)AsDouble1ClassInventorytypeStockItemin component FeatureTour.Typescontains elements[offset &H0000]Name As String[offset &H0004]Quantity As Long[offset &H0008]Price As DoubleLenB() = &H0010Len() = &H0010UDT Alignment = &H0008(offsets and lengths calculated for current Win32 target)Sticky scrollColour matchingUnicode in the editorIndent guidesInline code hintsAdvanced info popupMini-mapFolding controlsMemory usage and object countsOutlineHistoryDiagnostics +tB Services: OPERATIONALULTIMATE EDITION175.6MBin use  |  100ui objects  |  16gdi objectsFileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32100%PREVIEWPROJECT EXPLORERFeatureTourImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesInventory.twinMainModule.twinTypes.twinOUTLINEInventoryHISTORY09:12Inventory.Add10:05Inventory.Find11:48Inventory.TotalDIAGNOSTICS0300Inventory.twinMainModule.twin[18,13]TB0003Datatype has not been explicitly declared so will default to Variant[19,13]TB0003Datatype has not been explicitly declared so will default to Variant[6,13]TB0003Datatype has not been explicitly declared so will default to VariantEDITOR 1Inventory(general)ItemByIndexInventory.twin1920212223242526272829303132333435363738394041424344454647484950515253545556DimnoteDimpriceAsDoubleFori=0Tocount-1Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIf🠈 items(i).Quantity > 100EndIf🠈 items(i).Quantity > 0Next🠈 i = 0 To count - 1Total=subtotalEndFunction🠈 TotalPublicFunctionFind(ByValnameAsString)AsLongFind=-1DimiAsLongFori=0Tocount-1Ifitems(i).Name=nameThenFind=iExitForEndIf🠈 items(i).Name = nameNext🠈 i = 0 To count - 1EndFunction🠈 FindPublicSubClear()Eraseitemscount=0EndSub🠈 ClearPublicFunctionItemByIndex(ByValpositionAsLong)AsStockItemItemByIndex=items(position)EndFunction🠈 ItemByIndexEndClass🠈 Inventory16PublicFunctionTotal(ByValtaxRateAsDouble)AsDouble1ClassInventorytypeStockItemin component FeatureTour.Typescontains elements[offset &H0000]Name As String[offset &H0004]Quantity As Long[offset &H0008]Price As DoubleLenB() = &H0010Len() = &H0010UDT Alignment = &H0008(offsets and lengths calculated for current Win32 target)Sticky scrollColour matchingUnicode in the editorIndent guidesInline code hintsAdvanced info popupMini-mapFolding controlsMemory usage and object countsOutlineHistoryDiagnostics diff --git a/docs/Features/Images/IDE-FeatureMap.png b/docs/Features/Images/IDE-FeatureMap.png index 0872d21e8..e98e44b11 100644 Binary files a/docs/Features/Images/IDE-FeatureMap.png and b/docs/Features/Images/IDE-FeatureMap.png differ diff --git a/docs/Features/Images/IDE-FeatureMap.svg b/docs/Features/Images/IDE-FeatureMap.svg index 3b864bcf0..a4d6bf1ae 100644 --- a/docs/Features/Images/IDE-FeatureMap.svg +++ b/docs/Features/Images/IDE-FeatureMap.svg @@ -1 +1 @@ -tB Services: OPERATIONALULTIMATE EDITION175.6MBin use  |  100ui objects  |  16gdi objectsFileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32100%PREVIEWPROJECT EXPLORERFeatureTourImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesInventory.twinMainModule.twinTypes.twinOUTLINEInventoryHISTORY09:12Inventory.Add10:05Inventory.Find11:48Inventory.TotalDIAGNOSTICS0300Inventory.twinMainModule.twin[18,13]TB0003Datatype has not been explicitly declared so will default to Variant[19,13]TB0003Datatype has not been explicitly declared so will default to Variant[6,13]TB0003Datatype has not been explicitly declared so will default to VariantEDITOR 1Inventory(general)ItemByIndexInventory.twin1920212223242526272829303132333435363738394041424344454647484950515253545556DimnoteDimpriceAsDoubleFori=0Tocount-1Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIf🠈 items(i).Quantity > 100EndIf🠈 items(i).Quantity > 0Next🠈 i = 0 To count - 1Total=subtotalEndFunction🠈 TotalPublicFunctionFind(ByValnameAsString)AsLongFind=-1DimiAsLongFori=0Tocount-1Ifitems(i).Name=nameThenFind=iExitForEndIf🠈 items(i).Name = nameNext🠈 i = 0 To count - 1EndFunction🠈 FindPublicSubClear()Eraseitemscount=0EndSub🠈 ClearPublicFunctionItemByIndex(ByValpositionAsLong)AsStockItemItemByIndex=items(position)EndFunction🠈 ItemByIndexEndClass🠈 Inventory16PublicFunctionTotal(ByValtaxRateAsDouble)AsDouble1ClassInventorytypeStockItemin component FeatureTour.Typescontains elements[offset &H0000]Name As String[offset &H0004]Quantity As Long[offset &H0008]Price As DoubleLenB() = &H0010Len() = &H0010UDT Alignment = &H0008(offsets and lengths calculated for current Win32 target)Sticky scrollColour matchingUnicode in the editorIndent guidesInline code hintsAdvanced info popupMini-mapFolding controlsMemory usage and object countsOutlineHistoryDiagnostics +tB Services: OPERATIONALULTIMATE EDITION175.6MBin use  |  100ui objects  |  16gdi objectsFileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32100%PREVIEWPROJECT EXPLORERFeatureTourImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesInventory.twinMainModule.twinTypes.twinOUTLINEInventoryHISTORY09:12Inventory.Add10:05Inventory.Find11:48Inventory.TotalDIAGNOSTICS0300Inventory.twinMainModule.twin[18,13]TB0003Datatype has not been explicitly declared so will default to Variant[19,13]TB0003Datatype has not been explicitly declared so will default to Variant[6,13]TB0003Datatype has not been explicitly declared so will default to VariantEDITOR 1Inventory(general)ItemByIndexInventory.twin1920212223242526272829303132333435363738394041424344454647484950515253545556DimnoteDimpriceAsDoubleFori=0Tocount-1Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIf🠈 items(i).Quantity > 100EndIf🠈 items(i).Quantity > 0Next🠈 i = 0 To count - 1Total=subtotalEndFunction🠈 TotalPublicFunctionFind(ByValnameAsString)AsLongFind=-1DimiAsLongFori=0Tocount-1Ifitems(i).Name=nameThenFind=iExitForEndIf🠈 items(i).Name = nameNext🠈 i = 0 To count - 1EndFunction🠈 FindPublicSubClear()Eraseitemscount=0EndSub🠈 ClearPublicFunctionItemByIndex(ByValpositionAsLong)AsStockItemItemByIndex=items(position)EndFunction🠈 ItemByIndexEndClass🠈 Inventory16PublicFunctionTotal(ByValtaxRateAsDouble)AsDouble1ClassInventorytypeStockItemin component FeatureTour.Typescontains elements[offset &H0000]Name As String[offset &H0004]Quantity As Long[offset &H0008]Price As DoubleLenB() = &H0010Len() = &H0010UDT Alignment = &H0008(offsets and lengths calculated for current Win32 target)Sticky scrollColour matchingUnicode in the editorIndent guidesInline code hintsAdvanced info popupMini-mapFolding controlsMemory usage and object countsOutlineHistoryDiagnostics diff --git a/docs/Features/Images/a6525b1d-ac22-4303-ae27-7984c20eba0c.light.png b/docs/Features/Images/a6525b1d-ac22-4303-ae27-7984c20eba0c.light.png index 056da57df..c8ae58f9b 100644 Binary files a/docs/Features/Images/a6525b1d-ac22-4303-ae27-7984c20eba0c.light.png and b/docs/Features/Images/a6525b1d-ac22-4303-ae27-7984c20eba0c.light.png differ diff --git a/docs/Features/Images/a6525b1d-ac22-4303-ae27-7984c20eba0c.png b/docs/Features/Images/a6525b1d-ac22-4303-ae27-7984c20eba0c.png index 06e00f4cd..dd22789de 100644 Binary files a/docs/Features/Images/a6525b1d-ac22-4303-ae27-7984c20eba0c.png and b/docs/Features/Images/a6525b1d-ac22-4303-ae27-7984c20eba0c.png differ diff --git a/docs/Features/Images/b000d3aa-3689-4d94-88e3-bca44f8b7de6.light.png b/docs/Features/Images/b000d3aa-3689-4d94-88e3-bca44f8b7de6.light.png index b1a613d59..a9eac963d 100644 Binary files a/docs/Features/Images/b000d3aa-3689-4d94-88e3-bca44f8b7de6.light.png and b/docs/Features/Images/b000d3aa-3689-4d94-88e3-bca44f8b7de6.light.png differ diff --git a/docs/Features/Images/b000d3aa-3689-4d94-88e3-bca44f8b7de6.png b/docs/Features/Images/b000d3aa-3689-4d94-88e3-bca44f8b7de6.png index 5b35075c9..114065672 100644 Binary files a/docs/Features/Images/b000d3aa-3689-4d94-88e3-bca44f8b7de6.png and b/docs/Features/Images/b000d3aa-3689-4d94-88e3-bca44f8b7de6.png differ diff --git a/docs/Features/Images/b0724fe2-636d-47db-a8fc-531a585ddaf9.light.png b/docs/Features/Images/b0724fe2-636d-47db-a8fc-531a585ddaf9.light.png index bcf0bfc9c..46b880fd2 100644 Binary files a/docs/Features/Images/b0724fe2-636d-47db-a8fc-531a585ddaf9.light.png and b/docs/Features/Images/b0724fe2-636d-47db-a8fc-531a585ddaf9.light.png differ diff --git a/docs/Features/Images/b0724fe2-636d-47db-a8fc-531a585ddaf9.png b/docs/Features/Images/b0724fe2-636d-47db-a8fc-531a585ddaf9.png index 5def0d9e8..fffede670 100644 Binary files a/docs/Features/Images/b0724fe2-636d-47db-a8fc-531a585ddaf9.png and b/docs/Features/Images/b0724fe2-636d-47db-a8fc-531a585ddaf9.png differ diff --git a/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.light.png b/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.light.png index da4e56dd6..0bb136026 100644 Binary files a/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.light.png and b/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.light.png differ diff --git a/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.light.svg b/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.light.svg index e755653da..89897e795 100644 --- a/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.light.svg +++ b/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.light.svg @@ -1 +1 @@ -+ menuBIU8pt+-PROPERTIESLAYOUTTabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }Dock0 - vbDockNoneText1    TextBox ++ menuBIU8pt+-PROPERTIESLAYOUTTabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }Dock0 - vbDockNoneDockOrder0Text1    TextBox diff --git a/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.png b/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.png index 99fe2224f..0c731acce 100644 Binary files a/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.png and b/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.png differ diff --git a/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.svg b/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.svg index 244cfd45a..aa6834a0d 100644 --- a/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.svg +++ b/docs/Features/Images/b26da59b-4e98-40b7-b97b-bb3cef4ca1d0.svg @@ -1 +1 @@ -+ menuBIU8pt+-PROPERTIESLAYOUTTabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }Dock0 - vbDockNoneText1    TextBox ++ menuBIU8pt+-PROPERTIESLAYOUTTabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }Dock0 - vbDockNoneDockOrder0Text1    TextBox diff --git a/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.light.png b/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.light.png index 8e3b68232..6e2fd104d 100644 Binary files a/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.light.png and b/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.light.png differ diff --git a/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.light.svg b/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.light.svg index c3f0ecd8f..a518ac89c 100644 --- a/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.light.svg +++ b/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.light.svg @@ -1 +1 @@ -+ menuBIU8pt+-PROPERTIESLAYOUTTabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }LeftTrueTopTrueRightFalseBottomFalseDock0 - vbDockNoneText1    TextBox ++ menuBIU8pt+-PROPERTIESLAYOUTTabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }LeftTrueTopTrueRightFalseBottomFalseDock0 - vbDockNoneDockOrder0Text1    TextBox diff --git a/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.png b/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.png index ba0cd072a..2ef2d37ac 100644 Binary files a/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.png and b/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.png differ diff --git a/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.svg b/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.svg index 8c9fbc7e5..8b4046b3a 100644 --- a/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.svg +++ b/docs/Features/Images/d5dff8f5-c5fa-4620-ba11-430d06276b27.svg @@ -1 +1 @@ -+ menuBIU8pt+-PROPERTIESLAYOUTTabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }LeftTrueTopTrueRightFalseBottomFalseDock0 - vbDockNoneText1    TextBox ++ menuBIU8pt+-PROPERTIESLAYOUTTabStopTrueTabIndex0TabFocusAutoSelectTrueLeft300Top300Width2100Height360Anchors▶... { AnchorsData }LeftTrueTopTrueRightFalseBottomFalseDock0 - vbDockNoneDockOrder0Text1    TextBox diff --git a/docs/Features/Language/Inheritance.md b/docs/Features/Language/Inheritance.md index bd708a78f..a138b9714 100644 --- a/docs/Features/Language/Inheritance.md +++ b/docs/Features/Language/Inheritance.md @@ -108,7 +108,7 @@ End Class Others can inherit. Constructors are not inherited, so each derived class declares its own `Sub New`. Without one, a `Cat` cannot be created with arguments: `New Cat("Misty", #20-Nov-2022#)` fails with TB5030, *Unexpected call arguments*. -When the base class's `Sub New` takes arguments, the derived class's `Sub New` must call it --- `Dog` calls `Animal.New` below, and `GuardDog` calls `Dog.New`. Nothing else calls it. If the call is left out --- or the derived class has no `Sub New` and is created without arguments --- the code still compiles and runs. The base constructor never runs, and the fields it sets keep their default values. No error or warning reports it. A base `Sub New` that takes no arguments is different: it runs automatically, before the derived class's `Sub New`. +When the base class's `Sub New` takes arguments, the derived class's `Sub New` must call it --- `Dog` calls `Animal.New` below, and `GuardDog` calls `Dog.New`. Nothing else calls it. If the call is left out --- or the derived class has no `Sub New` and is created without arguments --- the code still compiles and runs. The base constructor never runs, and the fields it sets keep their default values. No error or warning reports it. A base `Sub New` that takes no arguments is different: it runs automatically, before the derived class's `Sub New`. [Constructors in Derived Classes](#constructors-in-derived-classes) covers every combination of base and derived constructors. ```tb check_build projname=inheritance-animals ' ===== Derived: Dog ===== @@ -203,3 +203,81 @@ Misty says: meow ``` The classes come from Sample 23, which also has an `AnimalWatcher` class that handles the `Spoke` event, and a longer demonstration routine. To open it, choose **File → New Project**, then the **Samples** tab, and pick **Sample 23. OOP Inheritance Example (Animals)**. The [New Project](../../tB/IDE/Project/New#samples) page lists every sample. + +## Constructors in Derived Classes + +A class has two kinds of constructor: `Class_Initialize`, which takes no arguments, and `Sub New`, which can take arguments. [`Class_Initialize` or `Sub New`?](../Advanced/Classes-and-Modules#class_initialize-or-sub-new) compares them. When a derived class is created, the base class's constructor runs as well as the derived class's own, and it runs first. Which of the base's constructors runs depends on whether the derived class's constructor calls one: + +- **No call:** the base's constructor without arguments --- its `Class_Initialize`, or its `Sub New` with no parameters --- runs automatically, before the derived class's constructor. This holds whichever kind of constructor the derived class has, and when it has none. It holds at every level, too: when `C` inherits `B`, which inherits `A`, creating a `C` runs `A`'s constructor, then `B`'s, then `C`'s. +- **A call, `Base.New(...)`:** that constructor runs, where the call is written, and the automatic call is skipped. A derived `Class_Initialize` can make the call too. + +What the derived class's author does depends on the base class: + +1. **The base has only a `Class_Initialize`** --- typical of code that comes from VB6. Nothing: it runs on its own. +2. **The base has a `Sub New` with no parameters.** Nothing, as for `Class_Initialize`. Calling it, `Base.New()`, is allowed, and it still runs once. +3. **The base has only a `Sub New` with arguments.** Every constructor of the derived class must call it, its `Class_Initialize` included. If one does not, the base's constructor never runs, its fields keep their default values, and no error or warning reports it. +4. **The base has a constructor without arguments and a `Sub New` with arguments.** Each derived constructor chooses: leave out the call to have the one without arguments run, or call `Base.New(...)` to have that one run instead. + +Where a derived constructor calls `Base.New`, make the call its first statement, and make it on every path through the constructor: + +- Statements before the call run while the base is not yet set up. +- A call inside an `If` turns off the automatic call even when the `If` does not run it. On that path, *no* constructor of the base runs --- not even its `Class_Initialize`. The compiler decides by whether the call is in the code, not by whether it runs. + +Constructors are not inherited. A derived class whose only constructor is a `Sub New` with arguments cannot be created with a plain `New`, even when the base has a `Class_Initialize`: the call fails with TB5103, *Too few arguments*. To keep a plain `New`, and [`As New`](../../tB/Core/New), give the derived class a constructor without arguments as well. A derived class with no constructor at all can be created with a plain `New`, or declared `As New`, and either runs the base's constructor without arguments. As in any class, a derived class cannot have both a `Class_Initialize` and a `Sub New` without parameters: a plain `New` matches both, and fails with TB5073. + +The field initializers of every class in the chain --- `Private _name As String = "nobody"` --- run before any of the constructors, the base's included. So a base constructor that calls an `Overridable` method sees the derived class's fields at their initial values when the derived class overrides that method. + +A COM client that creates a public derived class, with `CreateObject` for example, gets the same constructors as a plain `New` in twinBASIC: the derived class's constructor without arguments, and before it the base's, unless the derived constructor calls `Base.New(...)` itself. + +When the object is destroyed, the `Class_Terminate` of each class runs, the base class's first. That is the opposite of the order the constructors run in, so a derived class's `Class_Terminate` must not use anything the base's `Class_Terminate` releases. + +### Example: Base Constructors + +`Shape` has both kinds of constructor. `Circle` does not call either, so `Shape`'s `Class_Initialize` runs. `Square` calls `Shape.New`, so `Shape`'s `Class_Initialize` does not run: + +```tb check_build projname=inheritance-ctors slot=file +Private Class Shape + Private Sub Class_Initialize() + Debug.Print "Shape.Class_Initialize" + End Sub + Public Sub New(ByVal Kind As String) + Debug.Print "Shape.New(" & Kind & ")" + End Sub + Private Sub Class_Terminate() + Debug.Print "Shape.Class_Terminate" + End Sub +End Class + +Private Class Circle + Inherits Shape + Public Sub New(ByVal Radius As Double) + Debug.Print "Circle.New(" & Radius & ")" + End Sub + Private Sub Class_Terminate() + Debug.Print "Circle.Class_Terminate" + End Sub +End Class + +Private Class Square + Inherits Shape + Public Sub New(ByVal Side As Double) + Shape.New("square") + Debug.Print "Square.New(" & Side & ")" + End Sub +End Class +``` + +```tb check_run projname=inheritance-ctors +Dim c As Circle = New Circle(2) +Set c = Nothing +Dim s As Square = New Square(3) +Set s = Nothing +' Output: +' Shape.Class_Initialize +' Circle.New(2) +' Shape.Class_Terminate +' Circle.Class_Terminate +' Shape.New(square) +' Square.New(3) +' Shape.Class_Terminate +``` diff --git a/docs/Features/Language/Inline-Initialization.md b/docs/Features/Language/Inline-Initialization.md index 0dd87b5a2..2ef9d37f8 100644 --- a/docs/Features/Language/Inline-Initialization.md +++ b/docs/Features/Language/Inline-Initialization.md @@ -22,6 +22,43 @@ Dim strArr(2) As String = Array("a", "b", "c") Dim cMC As cMyClass = New cMyClass(customConstructorArgs) ``` +## What an Initializer Can Use + +What the expression after `=` may contain depends on where the variable is declared. + +**`Dim` inside a procedure.** Any expression, including a call to a procedure of the project. The initializer runs when execution reaches the declaration, like an assignment on the next line. + +**A `Static` variable, a module-level variable, or a field of a class.** No call to a procedure of the project: neither one in the same module or class, nor one in another module, called bare or qualified. The call fails with TB5079, *Unrecognized symbol*, or, qualified, with TB5027, *does not contain ... or it is inaccessible in this context*. Built-in functions, constants and [`New`](../../tB/Core/New), with or without constructor arguments, are allowed: + +```tb check_build slot=file +Class Order + Private _created As Date = Now() + Private _lines As Collection = New Collection + Private _limit As Long = 10 * 1024 +End Class +``` + +```tb expect-error=TB5079 slot=file +Class Invoice + Private _id As String = NewId() ' TB5079: Unrecognized symbol 'NewId' + + Private Function NewId() As String + NewId = CStr(Int(Rnd * 1000000)) + End Function +End Class +``` + +Set a value that needs a procedure of the project in code instead: a class field in [`Class_Initialize` or `Sub New`](../Advanced/Classes-and-Modules#class_initialize-or-sub-new), a module-level variable in the procedure that first needs it. + +An initializer at module or class level can also read a variable, but not every variable: + +- **A class field can read a module-level variable.** The modules are set up before any object is created. +- **A class field cannot read another field of the same class.** `Public X As Long = A + 1`, where `A` is a field, compiles, but the build fails with *[LINKER] compilation (codegen) error detected in 'MyClass.{fields_init}'*. A run in the IDE goes ahead, and the field holds an arbitrary number. Set the field in a constructor. +- **A module-level variable can read a variable declared above it in the same module.** +- **A module-level variable should not read another module's variable.** Modules are set up one at a time, so the other module's variable may still be 0 or empty. The order is neither the order of the files nor the alphabetical order of the modules' names. + + + ## Inline Variable Declaration for For A counter variable needs no separate `Dim` statement: diff --git a/docs/Features/Packages/Images/0fa1272d-41d6-4d0f-b19c-f47f24a47c4d.light.svg b/docs/Features/Packages/Images/0fa1272d-41d6-4d0f-b19c-f47f24a47c4d.light.svg index 578d687b2..6c553557a 100644 --- a/docs/Features/Packages/Images/0fa1272d-41d6-4d0f-b19c-f47f24a47c4d.light.svg +++ b/docs/Features/Packages/Images/0fa1272d-41d6-4d0f-b19c-f47f24a47c4d.light.svg @@ -1 +1 @@ -PROPERTIESSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeVBWebView2PackageWinEventLogLibWinNamedPipesLibWinServicesLibTBMANLIB[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0[BUILT-IN] twinBASIC - WinServicesLib0.1.0.0✨ – A Rapid Development Toolkit for TwinBasic1.0.29.0 +PROPERTIESSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeVBWebView2PackageWinEventLogLibWinNamedPipesLibWinServicesLibTBMANLIB[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0[BUILT-IN] twinBASIC - WinServicesLib0.1.0.0✨ – A Rapid Development Toolkit for TwinBasic1.0.29.0 diff --git a/docs/Features/Packages/Images/0fa1272d-41d6-4d0f-b19c-f47f24a47c4d.svg b/docs/Features/Packages/Images/0fa1272d-41d6-4d0f-b19c-f47f24a47c4d.svg index c73f53803..8e58ea9ab 100644 --- a/docs/Features/Packages/Images/0fa1272d-41d6-4d0f-b19c-f47f24a47c4d.svg +++ b/docs/Features/Packages/Images/0fa1272d-41d6-4d0f-b19c-f47f24a47c4d.svg @@ -1 +1 @@ -PROPERTIESSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeVBWebView2PackageWinEventLogLibWinNamedPipesLibWinServicesLibTBMANLIB[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0[BUILT-IN] twinBASIC - WinServicesLib0.1.0.0✨ – A Rapid Development Toolkit for TwinBasic1.0.29.0 +PROPERTIESSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeVBWebView2PackageWinEventLogLibWinNamedPipesLibWinServicesLibTBMANLIB[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0[BUILT-IN] twinBASIC - WinServicesLib0.1.0.0✨ – A Rapid Development Toolkit for TwinBasic1.0.29.0 diff --git a/docs/Features/Packages/Images/1f7e3574-f3c8-4aee-972a-ff161c0e51ac.svg b/docs/Features/Packages/Images/1f7e3574-f3c8-4aee-972a-ff161c0e51ac.svg index 6f73b8a06..f5e9f1831 100644 --- a/docs/Features/Packages/Images/1f7e3574-f3c8-4aee-972a-ff161c0e51ac.svg +++ b/docs/Features/Packages/Images/1f7e3574-f3c8-4aee-972a-ff161c0e51ac.svg @@ -1 +1 @@ -ImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinGreeting.twinEnabled LibrariesAvailable COM ReferencesAvailable PackagesGdiPlusGenericsTBMANLIB_ListBoxHScrollArrayListLibNewTabCtlOLEGuidstsJsonGdiPlus class library for tBGenericsHorizontal scroll bar for Twinbasic ListBox controlmscorlib's ArrayList drop-in replacementNewTab: tabbed control (by EduardoVB, experimental 64-bit compatible version)OLE Guid and interface definitions for 32-bit and 64-bitParse, query, patch, validate - one JSON model.Library SymbolEmbedded +ImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinGreeting.twinEnabled LibrariesAvailable COM ReferencesAvailable PackagesGdiPlusGenericsTBMANLIB_ListBoxHScrollArrayListLibNewTabCtlOLEGuidstsJsonGdiPlus class library for tBGenericsHorizontal scroll bar for Twinbasic ListBox controlmscorlib's ArrayList drop-in replacementNewTab: tabbed control (by EduardoVB, experimental 64-bit compatible version)OLE Guid and interface definitions for 32-bit and 64-bitParse, query, patch, validate - one JSON model.Library SymbolEmbedded diff --git a/docs/Features/Packages/Images/4d90f313-35d5-426d-8fc3-852ca03382fa.light.png b/docs/Features/Packages/Images/4d90f313-35d5-426d-8fc3-852ca03382fa.light.png index 8a4974cda..9e916fc25 100644 Binary files a/docs/Features/Packages/Images/4d90f313-35d5-426d-8fc3-852ca03382fa.light.png and b/docs/Features/Packages/Images/4d90f313-35d5-426d-8fc3-852ca03382fa.light.png differ diff --git a/docs/Features/Packages/Images/4d90f313-35d5-426d-8fc3-852ca03382fa.png b/docs/Features/Packages/Images/4d90f313-35d5-426d-8fc3-852ca03382fa.png index aa52f5769..e3c390ecd 100644 Binary files a/docs/Features/Packages/Images/4d90f313-35d5-426d-8fc3-852ca03382fa.png and b/docs/Features/Packages/Images/4d90f313-35d5-426d-8fc3-852ca03382fa.png differ diff --git a/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.light.png b/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.light.png index de6ece767..e29b225ad 100644 Binary files a/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.light.png and b/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.light.png differ diff --git a/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.light.svg b/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.light.svg index ab3b83957..9d7c1daf4 100644 --- a/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.light.svg +++ b/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.light.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentSample 4. MyVBEAddin (NEW with ToolWindow)Sample 5. MyCOMAddinSample 6. CustomControlsSample 7. PackageSample 8. FilePropertyViewer (CustomControls)Sample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE AddinSample 11. twinBASIC IDE Addin (Chart) +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentSample 4. MyVBEAddin (NEW with ToolWindow)Sample 5. MyCOMAddinSample 6. CustomControlsSample 7. PackageSample 8. FilePropertyViewer (CustomControls)Sample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE AddinSample 11. twinBASIC IDE Addin (Chart) diff --git a/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.png b/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.png index b56d6c888..b04537d83 100644 Binary files a/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.png and b/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.png differ diff --git a/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.svg b/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.svg index 6d3efa654..1d5feddd4 100644 --- a/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.svg +++ b/docs/Features/Packages/Images/6ad7a172-0e1b-4276-ac89-042681552507.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentSample 4. MyVBEAddin (NEW with ToolWindow)Sample 5. MyCOMAddinSample 6. CustomControlsSample 7. PackageSample 8. FilePropertyViewer (CustomControls)Sample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE AddinSample 11. twinBASIC IDE Addin (Chart) +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentSample 4. MyVBEAddin (NEW with ToolWindow)Sample 5. MyCOMAddinSample 6. CustomControlsSample 7. PackageSample 8. FilePropertyViewer (CustomControls)Sample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE AddinSample 11. twinBASIC IDE Addin (Chart) diff --git a/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.light.png b/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.light.png index 4c14b5534..d8eb10c20 100644 Binary files a/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.light.png and b/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.light.png differ diff --git a/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.light.svg b/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.light.svg index 4bde81568..2588560d5 100644 --- a/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.light.svg +++ b/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.light.svg @@ -1 +1 @@ -tbProjPackertbRegExpTBMANLIB_XmlTBMANLIB_AesTBMANLIB_DialogTBMANLIB_DiagnosticTBMANLIB_RESTBMANLIB_ConsoleCoreProject (Un)Packer for .twinproj and .twinpack FilesRegular Expressions Object - Replacement for VBScript.RegExpTBMAN: A complete XML object written in pure TwinbasicTBMAN: A crypto library contains AES (ECB/CBC/CFB/OFB/CTR/GCM)TBMAN: A file dialog has open/save functions, and a folder dialog has an input box.TBMAN: Diagnostic tools output with JSON/HTML/TEXTTBMAN: Easy to use ResourcesFiles with Res objectTBMAN: Modern console library with UTF-8, colors, and full-screen support.twinBASICUse Existing Local PackageOverwrite Local Package (export it from this project)CancelLocal Package already exists:C:\tbshots\AppData\Roaming\twinBASIC\packages\OLEGuids.twinpackLocal Version: 1.0.0.10Embedded Version: 1.0.0.10What do you want to do? +tbProjPackertbRegExpTBMANLIB_XmlTBMANLIB_AesTBMANLIB_DialogTBMANLIB_DiagnosticTBMANLIB_RESTBMANLIB_ConsoleCoreProject (Un)Packer for .twinproj and .twinpack FilesRegular Expressions Object - Replacement for VBScript.RegExpTBMAN: A complete XML object written in pure TwinbasicTBMAN: A crypto library contains AES (ECB/CBC/CFB/OFB/CTR/GCM)TBMAN: A file dialog has open/save functions, and a folder dialog has an input box.TBMAN: Diagnostic tools output with JSON/HTML/TEXTTBMAN: Easy to use ResourcesFiles with Res objectTBMAN: Modern console library with UTF-8, colors, and full-screen support.twinBASICUse Existing Local PackageOverwrite Local Package (export it from this project)CancelLocal Package already exists:C:\tbshots\AppData\Roaming\twinBASIC\packages\OLEGuids.twinpackLocal Version: 1.0.0.10Embedded Version: 1.0.0.10What do you want to do? diff --git a/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.png b/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.png index 90f391d7c..a5ea7b30b 100644 Binary files a/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.png and b/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.png differ diff --git a/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.svg b/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.svg index 773f37e13..a282ab102 100644 --- a/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.svg +++ b/docs/Features/Packages/Images/8cf72685-1188-4607-a55a-df16d4280474.svg @@ -1 +1 @@ -tbProjPackertbRegExpTBMANLIB_XmlTBMANLIB_AesTBMANLIB_DialogTBMANLIB_DiagnosticTBMANLIB_RESTBMANLIB_ConsoleCoreProject (Un)Packer for .twinproj and .twinpack FilesRegular Expressions Object - Replacement for VBScript.RegExpTBMAN: A complete XML object written in pure TwinbasicTBMAN: A crypto library contains AES (ECB/CBC/CFB/OFB/CTR/GCM)TBMAN: A file dialog has open/save functions, and a folder dialog has an input box.TBMAN: Diagnostic tools output with JSON/HTML/TEXTTBMAN: Easy to use ResourcesFiles with Res objectTBMAN: Modern console library with UTF-8, colors, and full-screen support.twinBASICUse Existing Local PackageOverwrite Local Package (export it from this project)CancelLocal Package already exists:C:\tbshots\AppData\Roaming\twinBASIC\packages\OLEGuids.twinpackLocal Version: 1.0.0.10Embedded Version: 1.0.0.10What do you want to do? +tbProjPackertbRegExpTBMANLIB_XmlTBMANLIB_AesTBMANLIB_DialogTBMANLIB_DiagnosticTBMANLIB_RESTBMANLIB_ConsoleCoreProject (Un)Packer for .twinproj and .twinpack FilesRegular Expressions Object - Replacement for VBScript.RegExpTBMAN: A complete XML object written in pure TwinbasicTBMAN: A crypto library contains AES (ECB/CBC/CFB/OFB/CTR/GCM)TBMAN: A file dialog has open/save functions, and a folder dialog has an input box.TBMAN: Diagnostic tools output with JSON/HTML/TEXTTBMAN: Easy to use ResourcesFiles with Res objectTBMAN: Modern console library with UTF-8, colors, and full-screen support.twinBASICUse Existing Local PackageOverwrite Local Package (export it from this project)CancelLocal Package already exists:C:\tbshots\AppData\Roaming\twinBASIC\packages\OLEGuids.twinpackLocal Version: 1.0.0.10Embedded Version: 1.0.0.10What do you want to do? diff --git a/docs/Features/Packages/Images/8d74d820-9907-4e76-ac42-71d0233187f1.light.png b/docs/Features/Packages/Images/8d74d820-9907-4e76-ac42-71d0233187f1.light.png index d81616245..66a4164a7 100644 Binary files a/docs/Features/Packages/Images/8d74d820-9907-4e76-ac42-71d0233187f1.light.png and b/docs/Features/Packages/Images/8d74d820-9907-4e76-ac42-71d0233187f1.light.png differ diff --git a/docs/Features/Packages/Images/8d74d820-9907-4e76-ac42-71d0233187f1.png b/docs/Features/Packages/Images/8d74d820-9907-4e76-ac42-71d0233187f1.png index 8d60cd9f6..f9ee426e9 100644 Binary files a/docs/Features/Packages/Images/8d74d820-9907-4e76-ac42-71d0233187f1.png and b/docs/Features/Packages/Images/8d74d820-9907-4e76-ac42-71d0233187f1.png differ diff --git a/docs/Features/Packages/Images/9eeffbcf-d73e-4a92-bce5-811ed60aba98.light.png b/docs/Features/Packages/Images/9eeffbcf-d73e-4a92-bce5-811ed60aba98.light.png index d975bb747..00553982f 100644 Binary files a/docs/Features/Packages/Images/9eeffbcf-d73e-4a92-bce5-811ed60aba98.light.png and b/docs/Features/Packages/Images/9eeffbcf-d73e-4a92-bce5-811ed60aba98.light.png differ diff --git a/docs/Features/Packages/Images/9eeffbcf-d73e-4a92-bce5-811ed60aba98.png b/docs/Features/Packages/Images/9eeffbcf-d73e-4a92-bce5-811ed60aba98.png index c44be3254..82fea01de 100644 Binary files a/docs/Features/Packages/Images/9eeffbcf-d73e-4a92-bce5-811ed60aba98.png and b/docs/Features/Packages/Images/9eeffbcf-d73e-4a92-bce5-811ed60aba98.png differ diff --git a/docs/Features/Packages/Images/LibrarySymbols.light.png b/docs/Features/Packages/Images/LibrarySymbols.light.png index 581cd76ba..7cdef7487 100644 Binary files a/docs/Features/Packages/Images/LibrarySymbols.light.png and b/docs/Features/Packages/Images/LibrarySymbols.light.png differ diff --git a/docs/Features/Packages/Images/db4636f6-d988-4e31-94a2-c4c170418e81.light.png b/docs/Features/Packages/Images/db4636f6-d988-4e31-94a2-c4c170418e81.light.png index d673ffa38..49c424d96 100644 Binary files a/docs/Features/Packages/Images/db4636f6-d988-4e31-94a2-c4c170418e81.light.png and b/docs/Features/Packages/Images/db4636f6-d988-4e31-94a2-c4c170418e81.light.png differ diff --git a/docs/Features/Packages/Images/db4636f6-d988-4e31-94a2-c4c170418e81.png b/docs/Features/Packages/Images/db4636f6-d988-4e31-94a2-c4c170418e81.png index 3c8ce6729..e7734b197 100644 Binary files a/docs/Features/Packages/Images/db4636f6-d988-4e31-94a2-c4c170418e81.png and b/docs/Features/Packages/Images/db4636f6-d988-4e31-94a2-c4c170418e81.png differ diff --git a/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.light.png b/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.light.png index e43b4fe33..9a42024c3 100644 Binary files a/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.light.png and b/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.light.png differ diff --git a/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.light.svg b/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.light.svg index d6feda883..9223289f7 100644 --- a/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.light.svg +++ b/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.light.svg @@ -1 +1 @@ -PublicSubShow()fmt.EndSubEndClassAsciiEscapeBaseCopyCapitalisationStringCurrencySFIDateTimeSFIDateTimeSFIDecimalSFIDecimalSFIEscapeSequenceEscapeSequenceExponentialSFIExponentialSFIFixedPointSFIFixedPointSFIFormerEntryPointFormerStringFormatStringGeneralNumericSFIGeneralNumericSFIGenericDateTimeSFIGenericDateTimeSFIenum(...)returns variablevariablevariablevariablevariablevariablemodule(...)returns variablevariable +PublicSubShow()fmt.EndSubEndClassAsciiEscapeBaseCopyCapitalisationStringCurrencySFICurrencySFIDateTimeSFIDateTimeSFIDecimalSFIDecimalSFIEscapeSequenceEscapeSequenceExponentialSFIExponentialSFIFixedPointSFIFixedPointSFIFormerEntryPointFormerStringFormatStringGeneralNumericSFIGeneralNumericSFIGenericDateTimeSFIGenericDateTimeSFIenum(...)returns variablevariablevariablevariablevariablevariablemodule(...)returns variablevariable diff --git a/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.png b/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.png index a53ef5625..94d5d7b40 100644 Binary files a/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.png and b/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.png differ diff --git a/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.svg b/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.svg index 73ea892ab..8c5373070 100644 --- a/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.svg +++ b/docs/Features/Packages/Images/e2a65dfe-4a9d-4524-b6d6-7a6d1bc35cdb.svg @@ -1 +1 @@ -PublicSubShow()fmt.EndSubEndClassAsciiEscapeBaseCopyCapitalisationStringCurrencySFIDateTimeSFIDateTimeSFIDecimalSFIDecimalSFIEscapeSequenceEscapeSequenceExponentialSFIExponentialSFIFixedPointSFIFixedPointSFIFormerEntryPointFormerStringFormatStringGeneralNumericSFIGeneralNumericSFIGenericDateTimeSFIGenericDateTimeSFIenum(...)returns variablevariablevariablevariablevariablevariablemodule(...)returns variablevariable +PublicSubShow()fmt.EndSubEndClassAsciiEscapeBaseCopyCapitalisationStringCurrencySFICurrencySFIDateTimeSFIDateTimeSFIDecimalSFIDecimalSFIEscapeSequenceEscapeSequenceExponentialSFIExponentialSFIFixedPointSFIFixedPointSFIFormerEntryPointFormerStringFormatStringGeneralNumericSFIGeneralNumericSFIGenericDateTimeSFIGenericDateTimeSFIenum(...)returns variablevariablevariablevariablevariablevariablemodule(...)returns variablevariable diff --git a/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.light.png b/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.light.png index 2783d0816..a58f6e414 100644 Binary files a/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.light.png and b/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.light.png differ diff --git a/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.light.svg b/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.light.svg index d6beae02a..a39a6bd47 100644 --- a/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.light.svg +++ b/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.light.svg @@ -1 +1 @@ -PROPERTIESSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeImport from file...WinDevLibWinRegWindows Development Library for twinBASIC v9.5.7459.5.745.0WinReg1.0.1.14 +PROPERTIESSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeImport from file...WinDevLibWinRegWindows Development Library for twinBASIC v9.5.7479.5.747.0WinReg1.0.1.14 diff --git a/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.png b/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.png index 6110ffd89..e0a7d2f00 100644 Binary files a/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.png and b/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.png differ diff --git a/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.svg b/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.svg index dc39de43a..1d05af8e0 100644 --- a/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.svg +++ b/docs/Features/Packages/Images/e35d5955-9e70-4d6e-abd7-748558da75ba.svg @@ -1 +1 @@ -PROPERTIESSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeImport from file...WinDevLibWinRegWindows Development Library for twinBASIC v9.5.7459.5.745.0WinReg1.0.1.14 +PROPERTIESSelect references that will be used during compilation of this project⚠ TIP: LOGIN to see any PRIVATE packages you've madeImport from file...WinDevLibWinRegWindows Development Library for twinBASIC v9.5.7479.5.747.0WinReg1.0.1.14 diff --git a/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.light.png b/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.light.png index 0def49262..b2edc96ae 100644 Binary files a/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.light.png and b/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.light.png differ diff --git a/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.light.svg b/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.light.svg index 7b3679d0c..75a33795e 100644 --- a/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.light.svg +++ b/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.light.svg @@ -1 +1 @@ -win32100%PREVIEWEDITOR 1PROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinGreeting.twinIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsIcon FormWhen set, the icon from this form will be imported into the ICON resources during build. The icon will be imported as the #1 resource entry inthe RT_GROUP_ICON group. The OS typically uses this icon to represent the application.Library ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectCOMPILER DEFAULT - (none)LampsAppGlobalClassProjectcefPackagecefPackagecefPackageWinNativeCommonCtlsCustomControlsCustomControlsPackagetbIDEAssertVBWebView2PackageWinEventLogLibWinNamedPipesLib1.0.0.0[BUILT-IN] twinBASIC - App global class object1.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1091.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1451.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v491.0.0.0[BUILT-IN] twinBASIC - Common Controls Compatibility Package0.0.0.1[BUILT-IN] twinBASIC - CustomControls DESIGNER Package0.0.0.24[BUILT-IN] twinBASIC - CustomControls Package0.0.0.5[BUILT-IN] twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN] twinBASIC - Unit Testing Package0.0.0.24[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0Library SymbolEmbeddedVersion(enter text to filter)123 +win32100%PREVIEWEDITOR 1PROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinGreeting.twinIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsIcon FormWhen set, the icon from this form will be imported into the ICON resources during build. The icon will be imported as the #1 resource entry inthe RT_GROUP_ICON group. The OS typically uses this icon to represent the application.Library ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectCOMPILER DEFAULT - (none)LampsAppGlobalClassProjectcefPackagecefPackagecefPackageWinNativeCommonCtlsCustomControlsCustomControlsPackagetbIDEAssertVBWebView2PackageWinEventLogLibWinNamedPipesLib1.0.0.0[BUILT-IN] twinBASIC - App global class object1.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1091.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1451.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v491.0.0.0[BUILT-IN] twinBASIC - Common Controls Compatibility Package0.0.0.1[BUILT-IN] twinBASIC - CustomControls DESIGNER Package0.0.0.24[BUILT-IN] twinBASIC - CustomControls Package0.0.0.5[BUILT-IN] twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN] twinBASIC - Unit Testing Package0.0.0.24[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0Library SymbolEmbeddedVersion(enter text to filter)123 diff --git a/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.png b/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.png index 80e21c7fa..2b8309294 100644 Binary files a/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.png and b/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.png differ diff --git a/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.svg b/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.svg index 6386b46d2..bf46f8ce4 100644 --- a/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.svg +++ b/docs/Features/Packages/Images/e749e10f-e361-4f15-a977-d756fcb3b5dd.svg @@ -1 +1 @@ -win32100%PREVIEWTOOLBOXEDITOR 1PROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinGreeting.twinIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsIcon FormWhen set, the icon from this form will be imported into the ICON resources during build. The icon will be imported as the #1 resource entry inthe RT_GROUP_ICON group. The OS typically uses this icon to represent the application.Library ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectCOMPILER DEFAULT - (none)LampsAppGlobalClassProjectcefPackagecefPackagecefPackageWinNativeCommonCtlsCustomControlsCustomControlsPackagetbIDEAssertVBWebView2PackageWinEventLogLibWinNamedPipesLib1.0.0.0[BUILT-IN] twinBASIC - App global class object1.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1091.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1451.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v491.0.0.0[BUILT-IN] twinBASIC - Common Controls Compatibility Package0.0.0.1[BUILT-IN] twinBASIC - CustomControls DESIGNER Package0.0.0.24[BUILT-IN] twinBASIC - CustomControls Package0.0.0.5[BUILT-IN] twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN] twinBASIC - Unit Testing Package0.0.0.24[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0Library SymbolEmbeddedVersion(enter text to filter)123 +win32100%PREVIEWTOOLBOXEDITOR 1PROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinGreeting.twinIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsIcon FormWhen set, the icon from this form will be imported into the ICON resources during build. The icon will be imported as the #1 resource entry inthe RT_GROUP_ICON group. The OS typically uses this icon to represent the application.Library ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectCOMPILER DEFAULT - (none)LampsAppGlobalClassProjectcefPackagecefPackagecefPackageWinNativeCommonCtlsCustomControlsCustomControlsPackagetbIDEAssertVBWebView2PackageWinEventLogLibWinNamedPipesLib1.0.0.0[BUILT-IN] twinBASIC - App global class object1.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1091.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v1451.0.0.0[BUILT-IN] twinBASIC - Chromium Embedded Framework Package v491.0.0.0[BUILT-IN] twinBASIC - Common Controls Compatibility Package0.0.0.1[BUILT-IN] twinBASIC - CustomControls DESIGNER Package0.0.0.24[BUILT-IN] twinBASIC - CustomControls Package0.0.0.5[BUILT-IN] twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN] twinBASIC - Unit Testing Package0.0.0.24[BUILT-IN] twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN] twinBASIC - WebView2 Package0.0.0.3[BUILT-IN] twinBASIC - WinEventLogLib0.1.0.0[BUILT-IN] twinBASIC - WinNamedPipesLib0.1.0.0Library SymbolEmbeddedVersion(enter text to filter)123 diff --git a/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.light.png b/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.light.png index 9bd5bd3be..49e814645 100644 Binary files a/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.light.png and b/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.light.png differ diff --git a/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.light.svg b/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.light.svg index 170992e1a..ee66320b0 100644 --- a/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.light.svg +++ b/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.light.svg @@ -1 +1 @@ -Enabled LibrariesAvailable COM ReferencesAvailable PackagesGdiPlus class library for tBGenericsHorizontal scroll bar for Twinbasic ListBox controlmscorlib's ArrayList drop-in replacementNewTab: tabbed control (by EduardoVB, experimental 64-bit compatible version)OLE Guid and interface definitions for 32-bit and 64-bitParse, query, patch, validate - one JSON model.Passwords you can measure before you generate.Project (Un)Packer for .twinproj and .twinpack FilesRegular Expressions Object - Replacement for VBScript.RegExpTBMAN: A complete XML object written in pure TwinbasicTBMAN: A crypto library contains AES (ECB/CBC/CFB/OFB/CTR/GCM)TBMAN: A file dialog has open/save functions, and a folder dialog has an input box.TBMAN: Diagnostic tools output with JSON/HTML/TEXTTBMAN: Easy to use ResourcesFiles with Res objectTBMAN: Modern console library with UTF-8, colors, and full-screen support.TBMAN: Text UI (TUI) component library base on ConsoleCoreEmbeddedtwinBASICUse Local Package (LINK)Download it from TWINSERV (EMBED)CancelLocal Package exists:C:\tbshots\AppData\Roaming\twinBASIC\packages\OLEGuids.twinpackLocal Version: 1.0.0.10TWINSERV Version: 1.0.0.10What do you want to do? +Enabled LibrariesAvailable COM ReferencesAvailable PackagesGdiPlus class library for tBGenericsHorizontal scroll bar for Twinbasic ListBox controlmscorlib's ArrayList drop-in replacementNewTab: tabbed control (by EduardoVB, experimental 64-bit compatible version)OLE Guid and interface definitions for 32-bit and 64-bitParse, query, patch, validate - one JSON model.Passwords you can measure before you generate.Project (Un)Packer for .twinproj and .twinpack FilesRegular Expressions Object - Replacement for VBScript.RegExpTBMAN: A complete XML object written in pure TwinbasicTBMAN: A crypto library contains AES (ECB/CBC/CFB/OFB/CTR/GCM)TBMAN: A file dialog has open/save functions, and a folder dialog has an input box.TBMAN: Diagnostic tools output with JSON/HTML/TEXTTBMAN: Easy to use ResourcesFiles with Res objectTBMAN: Modern console library with UTF-8, colors, and full-screen support.TBMAN: Text UI (TUI) component library base on ConsoleCoreEmbeddedtwinBASICUse Local Package (LINK)Download it from TWINSERV (EMBED)CancelLocal Package exists:C:\tbshots\AppData\Roaming\twinBASIC\packages\OLEGuids.twinpackLocal Version: 1.0.0.10TWINSERV Version: 1.0.0.10What do you want to do? diff --git a/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.png b/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.png index b68e5d719..65e94ad64 100644 Binary files a/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.png and b/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.png differ diff --git a/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.svg b/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.svg index 46ded277a..300bce77a 100644 --- a/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.svg +++ b/docs/Features/Packages/Images/f48a7254-e5c9-48c5-8099-725c0951ae5f.svg @@ -1 +1 @@ -Enabled LibrariesAvailable COM ReferencesAvailable PackagesGdiPlus class library for tBGenericsHorizontal scroll bar for Twinbasic ListBox controlmscorlib's ArrayList drop-in replacementNewTab: tabbed control (by EduardoVB, experimental 64-bit compatible version)OLE Guid and interface definitions for 32-bit and 64-bitParse, query, patch, validate - one JSON model.Passwords you can measure before you generate.Project (Un)Packer for .twinproj and .twinpack FilesRegular Expressions Object - Replacement for VBScript.RegExpTBMAN: A complete XML object written in pure TwinbasicTBMAN: A crypto library contains AES (ECB/CBC/CFB/OFB/CTR/GCM)TBMAN: A file dialog has open/save functions, and a folder dialog has an input box.TBMAN: Diagnostic tools output with JSON/HTML/TEXTTBMAN: Easy to use ResourcesFiles with Res objectTBMAN: Modern console library with UTF-8, colors, and full-screen support.TBMAN: Text UI (TUI) component library base on ConsoleCoreEmbeddedtwinBASICUse Local Package (LINK)Download it from TWINSERV (EMBED)CancelLocal Package exists:C:\tbshots\AppData\Roaming\twinBASIC\packages\OLEGuids.twinpackLocal Version: 1.0.0.10TWINSERV Version: 1.0.0.10What do you want to do? +Enabled LibrariesAvailable COM ReferencesAvailable PackagesGdiPlus class library for tBGenericsHorizontal scroll bar for Twinbasic ListBox controlmscorlib's ArrayList drop-in replacementNewTab: tabbed control (by EduardoVB, experimental 64-bit compatible version)OLE Guid and interface definitions for 32-bit and 64-bitParse, query, patch, validate - one JSON model.Passwords you can measure before you generate.Project (Un)Packer for .twinproj and .twinpack FilesRegular Expressions Object - Replacement for VBScript.RegExpTBMAN: A complete XML object written in pure TwinbasicTBMAN: A crypto library contains AES (ECB/CBC/CFB/OFB/CTR/GCM)TBMAN: A file dialog has open/save functions, and a folder dialog has an input box.TBMAN: Diagnostic tools output with JSON/HTML/TEXTTBMAN: Easy to use ResourcesFiles with Res objectTBMAN: Modern console library with UTF-8, colors, and full-screen support.TBMAN: Text UI (TUI) component library base on ConsoleCoreEmbeddedtwinBASICUse Local Package (LINK)Download it from TWINSERV (EMBED)CancelLocal Package exists:C:\tbshots\AppData\Roaming\twinBASIC\packages\OLEGuids.twinpackLocal Version: 1.0.0.10TWINSERV Version: 1.0.0.10What do you want to do? diff --git a/docs/Features/Packages/Images/packLicenceFiles.light.png b/docs/Features/Packages/Images/packLicenceFiles.light.png index 884acda44..164d00c76 100644 Binary files a/docs/Features/Packages/Images/packLicenceFiles.light.png and b/docs/Features/Packages/Images/packLicenceFiles.light.png differ diff --git a/docs/Features/Packages/Images/packLicenceFiles.png b/docs/Features/Packages/Images/packLicenceFiles.png index 914509223..df632c2e6 100644 Binary files a/docs/Features/Packages/Images/packLicenceFiles.png and b/docs/Features/Packages/Images/packLicenceFiles.png differ diff --git a/docs/Features/Packages/Images/packPublishButton.png b/docs/Features/Packages/Images/packPublishButton.png index 807f0051b..541e4301d 100644 Binary files a/docs/Features/Packages/Images/packPublishButton.png and b/docs/Features/Packages/Images/packPublishButton.png differ diff --git a/docs/IDE/AddIns/Images/GlobalSearch.light.png b/docs/IDE/AddIns/Images/GlobalSearch.light.png index b15da9940..98a61242a 100644 Binary files a/docs/IDE/AddIns/Images/GlobalSearch.light.png and b/docs/IDE/AddIns/Images/GlobalSearch.light.png differ diff --git a/docs/IDE/AddIns/Images/GlobalSearch.png b/docs/IDE/AddIns/Images/GlobalSearch.png index 814db06b6..7733ae518 100644 Binary files a/docs/IDE/AddIns/Images/GlobalSearch.png and b/docs/IDE/AddIns/Images/GlobalSearch.png differ diff --git a/docs/IDE/AddIns/Images/GlobalSearch_2.light.png b/docs/IDE/AddIns/Images/GlobalSearch_2.light.png index 5e0d00178..a5d2e7017 100644 Binary files a/docs/IDE/AddIns/Images/GlobalSearch_2.light.png and b/docs/IDE/AddIns/Images/GlobalSearch_2.light.png differ diff --git a/docs/IDE/AddIns/Images/GlobalSearch_2.light.svg b/docs/IDE/AddIns/Images/GlobalSearch_2.light.svg index 41ed8a637..12f4d1795 100644 --- a/docs/IDE/AddIns/Images/GlobalSearch_2.light.svg +++ b/docs/IDE/AddIns/Images/GlobalSearch_2.light.svg @@ -1 +1 @@ -GLOBAL SEARCHIn packagesMatch caseWhole wordExclude commentsButton15460 bytesConstants.twintwinbasic:/tbGlobalSearchAddIn1/Packages/tbIDE/Packages/VBA/Sources/Constants.twin1 match[128,18]vbDefaultButton1 = 05460 bytesConstants.twintwinbasic:/tbGlobalSearchAddIn1/Packages/tbIDE/Packages/VBA/Sources/Constants.twin1 match[128,18]vbDefaultButton1 = 0 +GLOBAL SEARCHIn packagesMatch caseWhole wordExclude commentsButton15592 bytesConstants.twintwinbasic:/tbGlobalSearchAddIn1/Packages/tbIDE/Packages/VBA/Sources/Constants.twin1 match[133,18]vbDefaultButton1 = 05592 bytesConstants.twintwinbasic:/tbGlobalSearchAddIn1/Packages/tbIDE/Packages/VBA/Sources/Constants.twin1 match[133,18]vbDefaultButton1 = 0 diff --git a/docs/IDE/AddIns/Images/GlobalSearch_2.png b/docs/IDE/AddIns/Images/GlobalSearch_2.png index 60e853519..4d3dbcc07 100644 Binary files a/docs/IDE/AddIns/Images/GlobalSearch_2.png and b/docs/IDE/AddIns/Images/GlobalSearch_2.png differ diff --git a/docs/IDE/AddIns/Images/GlobalSearch_2.svg b/docs/IDE/AddIns/Images/GlobalSearch_2.svg index 3417a7b3c..2ef24cd5e 100644 --- a/docs/IDE/AddIns/Images/GlobalSearch_2.svg +++ b/docs/IDE/AddIns/Images/GlobalSearch_2.svg @@ -1 +1 @@ -GLOBAL SEARCHIn packagesMatch caseWhole wordExclude commentsButton15460 bytesConstants.twintwinbasic:/tbGlobalSearchAddIn1/Packages/tbIDE/Packages/VBA/Sources/Constants.twin1 match[128,18]vbDefaultButton1 = 05460 bytesConstants.twintwinbasic:/tbGlobalSearchAddIn1/Packages/tbIDE/Packages/VBA/Sources/Constants.twin1 match[128,18]vbDefaultButton1 = 0 +GLOBAL SEARCHIn packagesMatch caseWhole wordExclude commentsButton15592 bytesConstants.twintwinbasic:/tbGlobalSearchAddIn1/Packages/tbIDE/Packages/VBA/Sources/Constants.twin1 match[133,18]vbDefaultButton1 = 05592 bytesConstants.twintwinbasic:/tbGlobalSearchAddIn1/Packages/tbIDE/Packages/VBA/Sources/Constants.twin1 match[133,18]vbDefaultButton1 = 0 diff --git a/docs/IDE/AddIns/Images/Help_Choices.light.png b/docs/IDE/AddIns/Images/Help_Choices.light.png index 6a5c691bb..a01f006bd 100644 Binary files a/docs/IDE/AddIns/Images/Help_Choices.light.png and b/docs/IDE/AddIns/Images/Help_Choices.light.png differ diff --git a/docs/IDE/AddIns/Images/Help_Choices.png b/docs/IDE/AddIns/Images/Help_Choices.png index 57e99d24c..a0d98f1ae 100644 Binary files a/docs/IDE/AddIns/Images/Help_Choices.png and b/docs/IDE/AddIns/Images/Help_Choices.png differ diff --git a/docs/IDE/AddIns/Images/Help_Description.light.png b/docs/IDE/AddIns/Images/Help_Description.light.png index d6983fce2..c9dc786d7 100644 Binary files a/docs/IDE/AddIns/Images/Help_Description.light.png and b/docs/IDE/AddIns/Images/Help_Description.light.png differ diff --git a/docs/IDE/AddIns/Images/Help_Description.png b/docs/IDE/AddIns/Images/Help_Description.png index a67e77da5..51c55bda2 100644 Binary files a/docs/IDE/AddIns/Images/Help_Description.png and b/docs/IDE/AddIns/Images/Help_Description.png differ diff --git a/docs/IDE/AddIns/Images/Help_Hover.light.png b/docs/IDE/AddIns/Images/Help_Hover.light.png index f998fe897..39b692bf5 100644 Binary files a/docs/IDE/AddIns/Images/Help_Hover.light.png and b/docs/IDE/AddIns/Images/Help_Hover.light.png differ diff --git a/docs/IDE/AddIns/Images/Help_Hover.png b/docs/IDE/AddIns/Images/Help_Hover.png index ad25e6041..ea418ed35 100644 Binary files a/docs/IDE/AddIns/Images/Help_Hover.png and b/docs/IDE/AddIns/Images/Help_Hover.png differ diff --git a/docs/IDE/AddIns/Images/Help_Pane.light.png b/docs/IDE/AddIns/Images/Help_Pane.light.png index 1c4113338..c70172ce6 100644 Binary files a/docs/IDE/AddIns/Images/Help_Pane.light.png and b/docs/IDE/AddIns/Images/Help_Pane.light.png differ diff --git a/docs/IDE/AddIns/Images/Help_Pane.png b/docs/IDE/AddIns/Images/Help_Pane.png index 2a1dfe60f..cb244d228 100644 Binary files a/docs/IDE/AddIns/Images/Help_Pane.png and b/docs/IDE/AddIns/Images/Help_Pane.png differ diff --git a/docs/IDE/AddIns/Images/Help_Settings.light.png b/docs/IDE/AddIns/Images/Help_Settings.light.png index 45631ecd9..816af5bac 100644 Binary files a/docs/IDE/AddIns/Images/Help_Settings.light.png and b/docs/IDE/AddIns/Images/Help_Settings.light.png differ diff --git a/docs/IDE/AddIns/Images/Help_Settings.png b/docs/IDE/AddIns/Images/Help_Settings.png index c9616a288..cdf34650b 100644 Binary files a/docs/IDE/AddIns/Images/Help_Settings.png and b/docs/IDE/AddIns/Images/Help_Settings.png differ diff --git a/docs/IDE/AddIns/Images/Help_Toolbar.light.png b/docs/IDE/AddIns/Images/Help_Toolbar.light.png index 2fcdb4b46..842066f86 100644 Binary files a/docs/IDE/AddIns/Images/Help_Toolbar.light.png and b/docs/IDE/AddIns/Images/Help_Toolbar.light.png differ diff --git a/docs/IDE/AddIns/Images/Help_Toolbar.png b/docs/IDE/AddIns/Images/Help_Toolbar.png index 3aa22fb8c..0cc369c4d 100644 Binary files a/docs/IDE/AddIns/Images/Help_Toolbar.png and b/docs/IDE/AddIns/Images/Help_Toolbar.png differ diff --git a/docs/IDE/AddIns/Images/Help_Window.light.png b/docs/IDE/AddIns/Images/Help_Window.light.png index 8e94a99ac..514625af0 100644 Binary files a/docs/IDE/AddIns/Images/Help_Window.light.png and b/docs/IDE/AddIns/Images/Help_Window.light.png differ diff --git a/docs/IDE/AddIns/Images/Help_Window.png b/docs/IDE/AddIns/Images/Help_Window.png index de6732965..d4feaaac0 100644 Binary files a/docs/IDE/AddIns/Images/Help_Window.png and b/docs/IDE/AddIns/Images/Help_Window.png differ diff --git a/docs/IDE/AddIns/Images/Toolbar_GlobalSearch.light.png b/docs/IDE/AddIns/Images/Toolbar_GlobalSearch.light.png index 56d5b3ab1..7e887e046 100644 Binary files a/docs/IDE/AddIns/Images/Toolbar_GlobalSearch.light.png and b/docs/IDE/AddIns/Images/Toolbar_GlobalSearch.light.png differ diff --git a/docs/IDE/Building/ActiveX-Registration.md b/docs/IDE/Building/ActiveX-Registration.md index f8dd26099..8047dc860 100644 --- a/docs/IDE/Building/ActiveX-Registration.md +++ b/docs/IDE/Building/ActiveX-Registration.md @@ -60,7 +60,7 @@ A project with *Register DLLs to HKLM* at **Yes** registers its DLL under `HKEY_ Its one button is **Continue Anyway**. The box does not appear when *Register DLL after build* is **No**. An IDE that runs as an administrator shows **ADMIN** in its title area and does not open it. - +![The warning box the IDE shows as it opens a project that registers to HKEY_LOCAL_MACHINE while the IDE is not elevated, with one button.](Images/HKLM_Warning.png){:width="532" height="245"} > [!NOTE] BETA 1010 > The warning opens twice each time you open the project, and also for a Standard EXE project that has *Register DLLs to HKLM* at **Yes**, although an EXE registers nothing. Choose **Continue Anyway** each time. To stop the box, set *Register DLLs to HKLM* or *Register DLL after build* to **No**. @@ -81,7 +81,7 @@ For a DLL registered under `HKEY_LOCAL_MACHINE`, in an IDE that is not elevated, **Build failed: unable to unregister the previous DLL. Continue anyway?** - +![The box a build shows when it cannot deregister the previous DLL.](Images/Delete_It_And_Continue.png){:width="537" height="158"} ### Delete It And Continue {: #delete-it-and-continue } diff --git a/docs/IDE/Building/Build-Configuration.md b/docs/IDE/Building/Build-Configuration.md index d829b7e60..d82354f45 100644 --- a/docs/IDE/Building/Build-Configuration.md +++ b/docs/IDE/Building/Build-Configuration.md @@ -30,7 +30,7 @@ The box is a drop-down list with three entries, and its tooltip is **Choose a bu **safeMode** : Opens the project without the compiler. See [Safe mode](#safe-mode). - +![The build configuration box on the toolbar with its list open below it and win32 chosen.](Images/Configuration_List.png){:width="181" height="102"} There are no **Debug** and **Release** entries, and none for AnyCPU or ARM. The split between the program that runs in the IDE and the program that a build writes is made in [Project Settings](../Project-Settings), by two sets of options: [*Compiler Options (BUILD)*](../Project-Settings#compiler-options-build) for **Build** and [*Compiler Options (DEBUG)*](../Project-Settings#compiler-options-debug) for **Start**. @@ -64,7 +64,7 @@ When you open a project from its file, from **Open Recent** or from the command **safeMode** opens the project's files without starting the compiler's services. It gives access to the project's files when the compiler's services get in the way, for example when the compiler keeps crashing. After a project loads in safe mode, a box explains it, in these words: **SafeMode is designed to give you access to the file system of your project, without starting all of the associated compiler services. Use this mode to investigate / fix / recover your code before saving and restarting in normal mode.** Choose **OK**. - +![The box the IDE shows once a project is open in safe mode, with an OK button.](Images/Safe_Mode.png){:width="547" height="188"} In safe mode: diff --git a/docs/IDE/Building/Build-and-Clean.md b/docs/IDE/Building/Build-and-Clean.md index dc4375ba3..08ef181c8 100644 --- a/docs/IDE/Building/Build-and-Clean.md +++ b/docs/IDE/Building/Build-and-Clean.md @@ -43,7 +43,7 @@ A build does not save the project and does not ask you to. The compiler builds t A project made from a template, a sample or a folder, or imported from a VB6 project, has no `.twinproj` file until it is saved. **Build** and **Clean** both open a box titled **twinBASIC** for such a project, with the question **You must first save the project. Save now?** and the buttons **Save** and **Cancel**. - +![The question a build of a project with no file asks, in a box titled twinBASIC.](Images/Save_First.png){:width="362" height="144"} **Cancel** closes the box. Nothing is written, and the console prints nothing. **Save** opens the Windows **Save As** dialog, with the name of the project's folder proposed, such as `NewProject`. @@ -69,7 +69,7 @@ A build that succeeds writes these lines: | Standard DLL | As an ActiveX DLL, with no `[REGISTER]` line. | | Package TWINPACK | `[BUILD] Creating TWINPACK file ''`, then `[BUILD] successful.` There are no links. | - +![The DEBUG CONSOLE, floating, after a build of a Standard EXE: the start line, the line naming the file written, and the line with the two links drawn as green buttons.](Images/Console_Exe.png){:width="900" height="115"} The log has no summary line. A clean build ends with the line for the file, or with the links beneath it. A build with errors ends differently, as [When a build fails](#when-a-build-fails) shows. @@ -110,7 +110,7 @@ An error in a procedure that nothing calls does not stop the build, although the [BUILD] failed ``` - +![The DEBUG CONSOLE, floating, after a build stopped by an error in the code: the start line, the two linker lines and the failure line in red.](Images/Console_Failed.png){:width="900" height="134"} No box opens. The [DIAGNOSTICS](../Code/Diagnostics) panel is unchanged: it already listed the error. The failed build deletes the file the previous build made. @@ -130,7 +130,7 @@ LOCKED BY: The old file is kept. The red link **Terminate** ends the program, with no question, and the next **Build** succeeds. The same program stops **Clean** from deleting the file. The line is `[BUILD-CLEAN] failed to delete the previous build file. Check the file is not in use or currently executing.` - +![The DEBUG CONSOLE, floating, after a build that could not replace a running program: the failure lines in red, the program's name and process id, and the Terminate link drawn as a red button.](Images/Console_Locked.png){:width="900" height="153"} When the file is a DLL that is registered, a failed deregistration can open another question. See [ActiveX registration](ActiveX-Registration#delete-it-and-continue). @@ -148,7 +148,7 @@ Its log is short: The `[UNREGISTER]` line comes only for an ActiveX build. **Clean** on a project that was never built prints the first and last lines, and so does a second **Clean**. After you change the *Build Type* setting, **Clean** removes the file of the current path only: the file of the old type stays. - +![The DEBUG CONSOLE, floating, after Clean of an ActiveX DLL that was built: the start line, the deregistration line and the cleanup line.](Images/Console_Clean.png){:width="900" height="115"} **Clean** also asks the **twinBASIC** question for a project with no file. See [A project with no file](#a-project-with-no-file). diff --git a/docs/IDE/Building/Images/Compiling.light.png b/docs/IDE/Building/Images/Compiling.light.png new file mode 100644 index 000000000..481fba1e3 Binary files /dev/null and b/docs/IDE/Building/Images/Compiling.light.png differ diff --git a/docs/IDE/Building/Images/Compiling.light.svg b/docs/IDE/Building/Images/Compiling.light.svg new file mode 100644 index 000000000..cd07d9f6f --- /dev/null +++ b/docs/IDE/Building/Images/Compiling.light.svg @@ -0,0 +1 @@ +Compiling...0.0% diff --git a/docs/IDE/Building/Images/Compiling.png b/docs/IDE/Building/Images/Compiling.png new file mode 100644 index 000000000..55bcb11e5 Binary files /dev/null and b/docs/IDE/Building/Images/Compiling.png differ diff --git a/docs/IDE/Building/Images/Compiling.svg b/docs/IDE/Building/Images/Compiling.svg new file mode 100644 index 000000000..18a82513b --- /dev/null +++ b/docs/IDE/Building/Images/Compiling.svg @@ -0,0 +1 @@ +Compiling...0.0% diff --git a/docs/IDE/Building/Images/Configuration_List.light.png b/docs/IDE/Building/Images/Configuration_List.light.png new file mode 100644 index 000000000..81a5f4782 Binary files /dev/null and b/docs/IDE/Building/Images/Configuration_List.light.png differ diff --git a/docs/IDE/Building/Images/Configuration_List.light.svg b/docs/IDE/Building/Images/Configuration_List.light.svg new file mode 100644 index 000000000..5effc2921 --- /dev/null +++ b/docs/IDE/Building/Images/Configuration_List.light.svg @@ -0,0 +1 @@ +RunToolsAdd-InsWindowwin32win32win64safeMode diff --git a/docs/IDE/Building/Images/Configuration_List.png b/docs/IDE/Building/Images/Configuration_List.png new file mode 100644 index 000000000..97e13d0f9 Binary files /dev/null and b/docs/IDE/Building/Images/Configuration_List.png differ diff --git a/docs/IDE/Building/Images/Configuration_List.svg b/docs/IDE/Building/Images/Configuration_List.svg new file mode 100644 index 000000000..2ad89a2bb --- /dev/null +++ b/docs/IDE/Building/Images/Configuration_List.svg @@ -0,0 +1 @@ +RunToolsAdd-InsWindowwin32win32win64safeMode diff --git a/docs/IDE/Building/Images/Console_Clean.light.png b/docs/IDE/Building/Images/Console_Clean.light.png new file mode 100644 index 000000000..3f4cadd86 Binary files /dev/null and b/docs/IDE/Building/Images/Console_Clean.light.png differ diff --git a/docs/IDE/Building/Images/Console_Clean.light.svg b/docs/IDE/Building/Images/Console_Clean.light.svg new file mode 100644 index 000000000..4c34d1e8d --- /dev/null +++ b/docs/IDE/Building/Images/Console_Clean.light.svg @@ -0,0 +1 @@ +DEBUG CONSOLE>16:41:58.204[BUILD] Starting...16:41:58.204[UNREGISTER] previous type-library deregistration completed. DllUnregisterServer() returned OK16:41:58.204[BUILD-CLEAN] build cleanup completed. diff --git a/docs/IDE/Building/Images/Console_Clean.png b/docs/IDE/Building/Images/Console_Clean.png new file mode 100644 index 000000000..4c3f1c018 Binary files /dev/null and b/docs/IDE/Building/Images/Console_Clean.png differ diff --git a/docs/IDE/Building/Images/Console_Clean.svg b/docs/IDE/Building/Images/Console_Clean.svg new file mode 100644 index 000000000..0f70a4cf2 --- /dev/null +++ b/docs/IDE/Building/Images/Console_Clean.svg @@ -0,0 +1 @@ +DEBUG CONSOLE>16:41:58.204[BUILD] Starting...16:41:58.204[UNREGISTER] previous type-library deregistration completed. DllUnregisterServer() returned OK16:41:58.204[BUILD-CLEAN] build cleanup completed. diff --git a/docs/IDE/Building/Images/Console_Exe.light.png b/docs/IDE/Building/Images/Console_Exe.light.png new file mode 100644 index 000000000..b4d8634c3 Binary files /dev/null and b/docs/IDE/Building/Images/Console_Exe.light.png differ diff --git a/docs/IDE/Building/Images/Console_Exe.light.svg b/docs/IDE/Building/Images/Console_Exe.light.svg new file mode 100644 index 000000000..43d73d6ff --- /dev/null +++ b/docs/IDE/Building/Images/Console_Exe.light.svg @@ -0,0 +1 @@ +DEBUG CONSOLE>16:41:58.204[BUILD] Starting...16:41:58.204[LINKER] SUCCESS created output file 'C:\tbshots\Building\Build\Program_win32.exe'16:41:58.204[LINKER] Launch EXE Open Folder diff --git a/docs/IDE/Building/Images/Console_Exe.png b/docs/IDE/Building/Images/Console_Exe.png new file mode 100644 index 000000000..abfed456f Binary files /dev/null and b/docs/IDE/Building/Images/Console_Exe.png differ diff --git a/docs/IDE/Building/Images/Console_Exe.svg b/docs/IDE/Building/Images/Console_Exe.svg new file mode 100644 index 000000000..8d7739b27 --- /dev/null +++ b/docs/IDE/Building/Images/Console_Exe.svg @@ -0,0 +1 @@ +DEBUG CONSOLE>16:41:58.204[BUILD] Starting...16:41:58.204[LINKER] SUCCESS created output file 'C:\tbshots\Building\Build\Program_win32.exe'16:41:58.204[LINKER] Launch EXE Open Folder diff --git a/docs/IDE/Building/Images/Console_Failed.light.png b/docs/IDE/Building/Images/Console_Failed.light.png new file mode 100644 index 000000000..1826f9420 Binary files /dev/null and b/docs/IDE/Building/Images/Console_Failed.light.png differ diff --git a/docs/IDE/Building/Images/Console_Failed.light.svg b/docs/IDE/Building/Images/Console_Failed.light.svg new file mode 100644 index 000000000..119c52589 --- /dev/null +++ b/docs/IDE/Building/Images/Console_Failed.light.svg @@ -0,0 +1 @@ +DEBUG CONSOLE>16:41:58.204[BUILD] Starting...16:41:58.204[LINKER] compilation (codegen) error detected in 'MainMod.Mainrootmain' at line #116:41:58.204[LINKER] FAILED due to compilation errors 'C:\tbshots\Building\Build\Program_win32.exe'16:41:58.204[BUILD] failed diff --git a/docs/IDE/Building/Images/Console_Failed.png b/docs/IDE/Building/Images/Console_Failed.png new file mode 100644 index 000000000..008dab1ab Binary files /dev/null and b/docs/IDE/Building/Images/Console_Failed.png differ diff --git a/docs/IDE/Building/Images/Console_Failed.svg b/docs/IDE/Building/Images/Console_Failed.svg new file mode 100644 index 000000000..58237f3f9 --- /dev/null +++ b/docs/IDE/Building/Images/Console_Failed.svg @@ -0,0 +1 @@ +DEBUG CONSOLE>16:41:58.204[BUILD] Starting...16:41:58.204[LINKER] compilation (codegen) error detected in 'MainMod.Mainrootmain' at line #116:41:58.204[LINKER] FAILED due to compilation errors 'C:\tbshots\Building\Build\Program_win32.exe'16:41:58.204[BUILD] failed diff --git a/docs/IDE/Building/Images/Console_Locked.light.png b/docs/IDE/Building/Images/Console_Locked.light.png new file mode 100644 index 000000000..9e1f78b58 Binary files /dev/null and b/docs/IDE/Building/Images/Console_Locked.light.png differ diff --git a/docs/IDE/Building/Images/Console_Locked.light.svg b/docs/IDE/Building/Images/Console_Locked.light.svg new file mode 100644 index 000000000..b0d295dd3 --- /dev/null +++ b/docs/IDE/Building/Images/Console_Locked.light.svg @@ -0,0 +1 @@ +DEBUG CONSOLE>16:41:58.204[BUILD] Starting...16:41:58.204[LINKER] FAILED to create output file 'C:\tbshots\Building\Build\Program_win32.exe' (error code 32)16:41:58.204LOCKED BY:16:41:58.204   Program_win32.exe (pid 4120) Terminate16:41:58.204[BUILD] failed diff --git a/docs/IDE/Building/Images/Console_Locked.png b/docs/IDE/Building/Images/Console_Locked.png new file mode 100644 index 000000000..c4dd27345 Binary files /dev/null and b/docs/IDE/Building/Images/Console_Locked.png differ diff --git a/docs/IDE/Building/Images/Console_Locked.svg b/docs/IDE/Building/Images/Console_Locked.svg new file mode 100644 index 000000000..9131ca283 --- /dev/null +++ b/docs/IDE/Building/Images/Console_Locked.svg @@ -0,0 +1 @@ +DEBUG CONSOLE>16:41:58.204[BUILD] Starting...16:41:58.204[LINKER] FAILED to create output file 'C:\tbshots\Building\Build\Program_win32.exe' (error code 32)16:41:58.204LOCKED BY:16:41:58.204   Program_win32.exe (pid 4120) Terminate16:41:58.204[BUILD] failed diff --git a/docs/IDE/Building/Images/Delete_It_And_Continue.light.png b/docs/IDE/Building/Images/Delete_It_And_Continue.light.png new file mode 100644 index 000000000..c8fca58c1 Binary files /dev/null and b/docs/IDE/Building/Images/Delete_It_And_Continue.light.png differ diff --git a/docs/IDE/Building/Images/Delete_It_And_Continue.light.svg b/docs/IDE/Building/Images/Delete_It_And_Continue.light.svg new file mode 100644 index 000000000..a337d977e --- /dev/null +++ b/docs/IDE/Building/Images/Delete_It_And_Continue.light.svg @@ -0,0 +1 @@ +twinBASICDelete It And ContinueCancelBuild failed: unable to unregister the previous DLL. Continue anyway? diff --git a/docs/IDE/Building/Images/Delete_It_And_Continue.png b/docs/IDE/Building/Images/Delete_It_And_Continue.png new file mode 100644 index 000000000..4887cffb7 Binary files /dev/null and b/docs/IDE/Building/Images/Delete_It_And_Continue.png differ diff --git a/docs/IDE/Building/Images/Delete_It_And_Continue.svg b/docs/IDE/Building/Images/Delete_It_And_Continue.svg new file mode 100644 index 000000000..e0cd1889d --- /dev/null +++ b/docs/IDE/Building/Images/Delete_It_And_Continue.svg @@ -0,0 +1 @@ +twinBASICDelete It And ContinueCancelBuild failed: unable to unregister the previous DLL. Continue anyway? diff --git a/docs/IDE/Building/Images/HKLM_Warning.light.png b/docs/IDE/Building/Images/HKLM_Warning.light.png new file mode 100644 index 000000000..495a81a35 Binary files /dev/null and b/docs/IDE/Building/Images/HKLM_Warning.light.png differ diff --git a/docs/IDE/Building/Images/HKLM_Warning.light.svg b/docs/IDE/Building/Images/HKLM_Warning.light.svg new file mode 100644 index 000000000..3db8a40d4 --- /dev/null +++ b/docs/IDE/Building/Images/HKLM_Warning.light.svg @@ -0,0 +1 @@ +Please wait...5.0%twinBASICContinue AnywayWARNING: This project registers itself to the HKEY_LOCAL_MACHINEregistry hive which requires ADMIN permissions.The twinBASIC IDE is not currently running elevated, and sothe registration of the DLL will fail during the build process.For the build to be successful, please restart the twinBASIC IDEusing the 'Run As Administrator' Windows option. diff --git a/docs/IDE/Building/Images/HKLM_Warning.png b/docs/IDE/Building/Images/HKLM_Warning.png new file mode 100644 index 000000000..9e5d65f5b Binary files /dev/null and b/docs/IDE/Building/Images/HKLM_Warning.png differ diff --git a/docs/IDE/Building/Images/HKLM_Warning.svg b/docs/IDE/Building/Images/HKLM_Warning.svg new file mode 100644 index 000000000..9cb4ab631 --- /dev/null +++ b/docs/IDE/Building/Images/HKLM_Warning.svg @@ -0,0 +1 @@ +Please wait...5.0%twinBASICContinue AnywayWARNING: This project registers itself to the HKEY_LOCAL_MACHINEregistry hive which requires ADMIN permissions.The twinBASIC IDE is not currently running elevated, and sothe registration of the DLL will fail during the build process.For the build to be successful, please restart the twinBASIC IDEusing the 'Run As Administrator' Windows option. diff --git a/docs/IDE/Building/Images/Publish_Confirm.light.png b/docs/IDE/Building/Images/Publish_Confirm.light.png new file mode 100644 index 000000000..94b816fe9 Binary files /dev/null and b/docs/IDE/Building/Images/Publish_Confirm.light.png differ diff --git a/docs/IDE/Building/Images/Publish_Confirm.light.svg b/docs/IDE/Building/Images/Publish_Confirm.light.svg new file mode 100644 index 000000000..3f30a01cf --- /dev/null +++ b/docs/IDE/Building/Images/Publish_Confirm.light.svg @@ -0,0 +1 @@ +SIGN INEDITtwinBASICContinueCancelIMPORTANT: Please check the following information before publishing to the online database:PUBLISHER: ExamplePublisherPACKAGE NAMESPACE: MyPackagePACKAGE DESCRIPTION: Greeting functionsPACKAGE VERSION: 1.0.0.0PACKAGE LICENCE: MITDo you want to proceed? diff --git a/docs/IDE/Building/Images/Publish_Confirm.png b/docs/IDE/Building/Images/Publish_Confirm.png new file mode 100644 index 000000000..56c79e45e Binary files /dev/null and b/docs/IDE/Building/Images/Publish_Confirm.png differ diff --git a/docs/IDE/Building/Images/Publish_Confirm.svg b/docs/IDE/Building/Images/Publish_Confirm.svg new file mode 100644 index 000000000..b51f42658 --- /dev/null +++ b/docs/IDE/Building/Images/Publish_Confirm.svg @@ -0,0 +1 @@ +SIGN INEDITtwinBASICContinueCancelIMPORTANT: Please check the following information before publishing to the online database:PUBLISHER: ExamplePublisherPACKAGE NAMESPACE: MyPackagePACKAGE DESCRIPTION: Greeting functionsPACKAGE VERSION: 1.0.0.0PACKAGE LICENCE: MITDo you want to proceed? diff --git a/docs/IDE/Building/Images/Publish_Result.light.png b/docs/IDE/Building/Images/Publish_Result.light.png new file mode 100644 index 000000000..41d32f6a1 Binary files /dev/null and b/docs/IDE/Building/Images/Publish_Result.light.png differ diff --git a/docs/IDE/Building/Images/Publish_Result.light.svg b/docs/IDE/Building/Images/Publish_Result.light.svg new file mode 100644 index 000000000..c88d063e8 --- /dev/null +++ b/docs/IDE/Building/Images/Publish_Result.light.svg @@ -0,0 +1 @@ +twinBASICOK[PUBLISH] successful. Your package should appear in the package manager database shortly. diff --git a/docs/IDE/Building/Images/Publish_Result.png b/docs/IDE/Building/Images/Publish_Result.png new file mode 100644 index 000000000..72879527b Binary files /dev/null and b/docs/IDE/Building/Images/Publish_Result.png differ diff --git a/docs/IDE/Building/Images/Publish_Result.svg b/docs/IDE/Building/Images/Publish_Result.svg new file mode 100644 index 000000000..8b2823749 --- /dev/null +++ b/docs/IDE/Building/Images/Publish_Result.svg @@ -0,0 +1 @@ +twinBASICOK[PUBLISH] successful. Your package should appear in the package manager database shortly. diff --git a/docs/IDE/Building/Images/Safe_Mode.light.png b/docs/IDE/Building/Images/Safe_Mode.light.png new file mode 100644 index 000000000..c2ff5b6a6 Binary files /dev/null and b/docs/IDE/Building/Images/Safe_Mode.light.png differ diff --git a/docs/IDE/Building/Images/Safe_Mode.light.svg b/docs/IDE/Building/Images/Safe_Mode.light.svg new file mode 100644 index 000000000..ec34ad64e --- /dev/null +++ b/docs/IDE/Building/Images/Safe_Mode.light.svg @@ -0,0 +1 @@ +twinBASICOKSafeMode is designed to give you access to the file systemof your project, without starting all of the associated compiler services.Use this mode to investigate / fix / recover your code before savingand restarting in normal mode. diff --git a/docs/IDE/Building/Images/Safe_Mode.png b/docs/IDE/Building/Images/Safe_Mode.png new file mode 100644 index 000000000..26d9d3ebb Binary files /dev/null and b/docs/IDE/Building/Images/Safe_Mode.png differ diff --git a/docs/IDE/Building/Images/Safe_Mode.svg b/docs/IDE/Building/Images/Safe_Mode.svg new file mode 100644 index 000000000..55f783ac4 --- /dev/null +++ b/docs/IDE/Building/Images/Safe_Mode.svg @@ -0,0 +1 @@ +twinBASICOKSafeMode is designed to give you access to the file systemof your project, without starting all of the associated compiler services.Use this mode to investigate / fix / recover your code before savingand restarting in normal mode. diff --git a/docs/IDE/Building/Images/Save_First.light.png b/docs/IDE/Building/Images/Save_First.light.png new file mode 100644 index 000000000..d2dc42f73 Binary files /dev/null and b/docs/IDE/Building/Images/Save_First.light.png differ diff --git a/docs/IDE/Building/Images/Save_First.light.svg b/docs/IDE/Building/Images/Save_First.light.svg new file mode 100644 index 000000000..f5843840c --- /dev/null +++ b/docs/IDE/Building/Images/Save_First.light.svg @@ -0,0 +1 @@ +twinBASICSaveCancelYou must first save the project. Save now? diff --git a/docs/IDE/Building/Images/Save_First.png b/docs/IDE/Building/Images/Save_First.png new file mode 100644 index 000000000..b6d0973fc Binary files /dev/null and b/docs/IDE/Building/Images/Save_First.png differ diff --git a/docs/IDE/Building/Images/Save_First.svg b/docs/IDE/Building/Images/Save_First.svg new file mode 100644 index 000000000..0f7bc2a55 --- /dev/null +++ b/docs/IDE/Building/Images/Save_First.svg @@ -0,0 +1 @@ +twinBASICSaveCancelYou must first save the project. Save now? diff --git a/docs/IDE/Building/Images/SignIn_Login.light.png b/docs/IDE/Building/Images/SignIn_Login.light.png new file mode 100644 index 000000000..78f090b9e Binary files /dev/null and b/docs/IDE/Building/Images/SignIn_Login.light.png differ diff --git a/docs/IDE/Building/Images/SignIn_Login.light.svg b/docs/IDE/Building/Images/SignIn_Login.light.svg new file mode 100644 index 000000000..f0d3dd0a7 --- /dev/null +++ b/docs/IDE/Building/Images/SignIn_Login.light.svg @@ -0,0 +1 @@ +DIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROPERTIESSIGN INEDITEDITEDITEDITEDIT(changes not effective until published)twinBASIC Publisher Login / SignupCancelLOGINUSERNAMEPASSWORDRemember password on this deviceLOG IN   ➤ExamplePublisherTERMS AND CONDITIONSThis service is subject to the following Terms andConditions.  These terms may be updated at any timewithout notice to you.This service allows you to store and share your contentand/or receive material from others.  We don't claimownership of your content; it remains your content andyou are responsible for it.Use of this service is at your own risk.  Published packagesmay contain full source code which will be visible toeveryone using this service.• Don't do anything illegal.• Don't publish spam.• Don't engage in any activity that exploits or harmschildren.• Don't use the service to share inappropriatecontent (e.g., nudity, pornography, violence, orcriminal activity).• Don't attempt to circumventsecurity/authentication restrictions.• Don't attempt to damage, overburden, or impairthe services.• Don't engage in any activity that is false ormisleading (e.g., impersonating someone).• Don't engage in any activity that is harmful to you,the service, or others (e.g., publishing viruses).• Don't infringe upon the rights of others (e.g.,unauthorized sharing of copyrighted material).• Don't help others break these rules.If you violate these terms, we may stop providing theservice to you, close your account, revoke your access, ordelete or unlist your package(s).REGISTER diff --git a/docs/IDE/Building/Images/SignIn_Login.png b/docs/IDE/Building/Images/SignIn_Login.png new file mode 100644 index 000000000..4c403138c Binary files /dev/null and b/docs/IDE/Building/Images/SignIn_Login.png differ diff --git a/docs/IDE/Building/Images/SignIn_Login.svg b/docs/IDE/Building/Images/SignIn_Login.svg new file mode 100644 index 000000000..3ea109926 --- /dev/null +++ b/docs/IDE/Building/Images/SignIn_Login.svg @@ -0,0 +1 @@ +DIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROPERTIESSIGN INEDITEDITEDITEDITEDIT(changes not effective until published)twinBASIC Publisher Login / SignupCancelLOGINUSERNAMEPASSWORDRemember password on this deviceLOG IN   ➤ExamplePublisherTERMS AND CONDITIONSThis service is subject to the following Terms andConditions.  These terms may be updated at any timewithout notice to you.This service allows you to store and share your contentand/or receive material from others.  We don't claimownership of your content; it remains your content andyou are responsible for it.Use of this service is at your own risk.  Published packagesmay contain full source code which will be visible toeveryone using this service.• Don't do anything illegal.• Don't publish spam.• Don't engage in any activity that exploits or harmschildren.• Don't use the service to share inappropriatecontent (e.g., nudity, pornography, violence, orcriminal activity).• Don't attempt to circumventsecurity/authentication restrictions.• Don't attempt to damage, overburden, or impairthe services.• Don't engage in any activity that is false ormisleading (e.g., impersonating someone).• Don't engage in any activity that is harmful to you,the service, or others (e.g., publishing viruses).• Don't infringe upon the rights of others (e.g.,unauthorized sharing of copyrighted material).• Don't help others break these rules.If you violate these terms, we may stop providing theservice to you, close your account, revoke your access, ordelete or unlist your package(s).REGISTER diff --git a/docs/IDE/Building/Images/SignIn_Register.light.png b/docs/IDE/Building/Images/SignIn_Register.light.png new file mode 100644 index 000000000..e8c69513d Binary files /dev/null and b/docs/IDE/Building/Images/SignIn_Register.light.png differ diff --git a/docs/IDE/Building/Images/SignIn_Register.light.svg b/docs/IDE/Building/Images/SignIn_Register.light.svg new file mode 100644 index 000000000..9567e63b6 --- /dev/null +++ b/docs/IDE/Building/Images/SignIn_Register.light.svg @@ -0,0 +1 @@ +DIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROPERTIESSIGN INEDITEDITEDITEDITEDIT(changes not effective until published)twinBASIC Publisher Login / SignupCancelREGISTERUSERNAMEEMAILPASSWORDI agree to the terms & conditionsRemember password on this deviceSIGN UP   ➤ERROR: Username must be at least 4 characters longabcTERMS AND CONDITIONSThis service is subject to the following Terms andConditions.  These terms may be updated at any timewithout notice to you.This service allows you to store and share your contentand/or receive material from others.  We don't claimownership of your content; it remains your content andyou are responsible for it.Use of this service is at your own risk.  Published packagesmay contain full source code which will be visible toeveryone using this service.• Don't do anything illegal.• Don't publish spam.• Don't engage in any activity that exploits or harmschildren.• Don't use the service to share inappropriatecontent (e.g., nudity, pornography, violence, orcriminal activity).• Don't attempt to circumventsecurity/authentication restrictions.• Don't attempt to damage, overburden, or impairthe services.• Don't engage in any activity that is false ormisleading (e.g., impersonating someone).• Don't engage in any activity that is harmful to you,the service, or others (e.g., publishing viruses).• Don't infringe upon the rights of others (e.g.,unauthorized sharing of copyrighted material).• Don't help others break these rules.If you violate these terms, we may stop providing theservice to you, close your account, revoke your access, ordelete or unlist your package(s).LOGIN>=4 characters, visible to everyone, no expletivesthis is used for account recovery only>=8 characters diff --git a/docs/IDE/Building/Images/SignIn_Register.png b/docs/IDE/Building/Images/SignIn_Register.png new file mode 100644 index 000000000..4c4a2c033 Binary files /dev/null and b/docs/IDE/Building/Images/SignIn_Register.png differ diff --git a/docs/IDE/Building/Images/SignIn_Register.svg b/docs/IDE/Building/Images/SignIn_Register.svg new file mode 100644 index 000000000..dc8dc3288 --- /dev/null +++ b/docs/IDE/Building/Images/SignIn_Register.svg @@ -0,0 +1 @@ +DIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROPERTIESSIGN INEDITEDITEDITEDITEDIT(changes not effective until published)twinBASIC Publisher Login / SignupCancelREGISTERUSERNAMEEMAILPASSWORDI agree to the terms & conditionsRemember password on this deviceSIGN UP   ➤ERROR: Username must be at least 4 characters longabcTERMS AND CONDITIONSThis service is subject to the following Terms andConditions.  These terms may be updated at any timewithout notice to you.This service allows you to store and share your contentand/or receive material from others.  We don't claimownership of your content; it remains your content andyou are responsible for it.Use of this service is at your own risk.  Published packagesmay contain full source code which will be visible toeveryone using this service.• Don't do anything illegal.• Don't publish spam.• Don't engage in any activity that exploits or harmschildren.• Don't use the service to share inappropriatecontent (e.g., nudity, pornography, violence, orcriminal activity).• Don't attempt to circumventsecurity/authentication restrictions.• Don't attempt to damage, overburden, or impairthe services.• Don't engage in any activity that is false ormisleading (e.g., impersonating someone).• Don't engage in any activity that is harmful to you,the service, or others (e.g., publishing viruses).• Don't infringe upon the rights of others (e.g.,unauthorized sharing of copyrighted material).• Don't help others break these rules.If you violate these terms, we may stop providing theservice to you, close your account, revoke your access, ordelete or unlist your package(s).LOGIN>=4 characters, visible to everyone, no expletivesthis is used for account recovery only>=8 characters diff --git a/docs/IDE/Building/LLVM-in-the-IDE.md b/docs/IDE/Building/LLVM-in-the-IDE.md index 6661ed446..bfccad31b 100644 --- a/docs/IDE/Building/LLVM-in-the-IDE.md +++ b/docs/IDE/Building/LLVM-in-the-IDE.md @@ -38,9 +38,9 @@ The banner follows the licence badge at the moment the dialog opens. [Getting St ## The progress box {: #the-progress-box } -When the compiler reports progress, the IDE opens a box titled **Compiling...** with a bar,, and the compiler can also fill an item of the status bar with the percentage, such as **LLVM: n%**. The box is modal: the IDE cannot be used until it closes, and it closes by itself when the build ends. Which builds report progress is the compiler's choice. A small project compiled with LLVM takes a fraction of a second, so the box is gone almost at once. +When the compiler reports progress, the IDE opens a box titled **Compiling...** with a progress bar, and the compiler can also fill an item of the status bar with the percentage, such as **LLVM: n%**. The box is modal: the IDE cannot be used until it closes, and it closes by itself when the build ends. Which builds report progress is the compiler's choice. A small project compiled with LLVM takes a fraction of a second, so the box is gone almost at once. - +![The Compiling... box of an LLVM build, its progress bar at the start.](Images/Compiling.png){:width="302" height="71"} > [!NOTE] BETA 1010 > If another box opens while **Compiling...** is on screen, the end of the build closes that box instead of the progress box, so the other box is lost. The **Compiling...** box stays, with no button, and the IDE cannot be used. Restart the IDE. diff --git a/docs/IDE/Building/Package-Publishing.md b/docs/IDE/Building/Package-Publishing.md index 6c4176c65..081ef8b71 100644 --- a/docs/IDE/Building/Package-Publishing.md +++ b/docs/IDE/Building/Package-Publishing.md @@ -58,9 +58,9 @@ TWINSERV accepts a package only from a publisher that has an account. The accoun **SIGN IN** opens a box titled **twinBASIC Publisher Login / Signup**. The terms and conditions are beside two forms, which two tabs choose, **LOGIN** and **REGISTER**. The box has one button, **Cancel**. It opens on **LOGIN**, with the password box focused, when the IDE knows a publisher name, and on **REGISTER** when it does not. - +![The publisher sign-in box on its LOGIN tab, a name typed and the password empty, Remember password on this device ticked; the terms and conditions fill its right side.](Images/SignIn_Login.png){:width="826" height="603"} - +![The publisher sign-in box on its REGISTER tab after SIGN UP with a three-letter username: the error line in red under the form.](Images/SignIn_Register.png){:width="826" height="603"} **To register**, fill in **USERNAME** (at least 4 characters, visible to everyone), **EMAIL** (used for account recovery only), **PASSWORD** (at least 8 characters), tick **I agree to the terms & conditions**, and press **SIGN UP**. The IDE checks these on your machine first, in this order, and shows the first fault as **ERROR:** under the form, with the field focused: **Username must be at least 4 characters long**, **invalid email address**, **Password must be at least 8 characters long**, **You must agree to the terms and conditions**. The server can still refuse the name (**Username already taken.**). When the account is made, a box says **Publisher account created successfully. You will now be logged in.** @@ -91,11 +91,11 @@ The password is stored in the IDE's settings in the registry with a simple obfus The confirmation reads **IMPORTANT: Please check the following information before publishing to the online database:** and then lists **PUBLISHER**, **PACKAGE NAMESPACE**, **PACKAGE DESCRIPTION**, **PACKAGE VERSION** and **PACKAGE LICENCE**. For a package with the visibility **PUBLIC**, the box starts with **WARNING: publishing a PUBLIC package will allow everyone to download the package and see the sourcecode within it.** Its buttons are **Continue**, which is the default, and **Cancel**. - +![The confirmation PUBLISH THIS PACKAGE shows for a private package, listing the publisher and the package's details, with Continue as the default button.](Images/Publish_Confirm.png){:width="704" height="302"} **Continue** prints `[PUBLISH] attempting to publish project '' to the online database...` in the console. The result is not in the console: a box with **OK** shows it. - +![The box that shows the result of a publish, here a success, with an OK button.](Images/Publish_Result.png){:width="691" height="158"} | Result | The box says | |---|---| diff --git a/docs/IDE/Code/Images/Bookmarks.light.png b/docs/IDE/Code/Images/Bookmarks.light.png index 343c79e19..36a7f09fe 100644 Binary files a/docs/IDE/Code/Images/Bookmarks.light.png and b/docs/IDE/Code/Images/Bookmarks.light.png differ diff --git a/docs/IDE/Code/Images/Bookmarks.png b/docs/IDE/Code/Images/Bookmarks.png index 01cc976da..306706a18 100644 Binary files a/docs/IDE/Code/Images/Bookmarks.png and b/docs/IDE/Code/Images/Bookmarks.png differ diff --git a/docs/IDE/Code/Images/Combo_Lists.png b/docs/IDE/Code/Images/Combo_Lists.png index e6f745a76..9e1f7d217 100644 Binary files a/docs/IDE/Code/Images/Combo_Lists.png and b/docs/IDE/Code/Images/Combo_Lists.png differ diff --git a/docs/IDE/Code/Images/Combos.light.png b/docs/IDE/Code/Images/Combos.light.png index d30eec63a..4496c48d7 100644 Binary files a/docs/IDE/Code/Images/Combos.light.png and b/docs/IDE/Code/Images/Combos.light.png differ diff --git a/docs/IDE/Code/Images/Combos.png b/docs/IDE/Code/Images/Combos.png index 911bb665d..98f71e38b 100644 Binary files a/docs/IDE/Code/Images/Combos.png and b/docs/IDE/Code/Images/Combos.png differ diff --git a/docs/IDE/Code/Images/Command_Palette.light.png b/docs/IDE/Code/Images/Command_Palette.light.png index 9cc0b86fc..3665d8ca8 100644 Binary files a/docs/IDE/Code/Images/Command_Palette.light.png and b/docs/IDE/Code/Images/Command_Palette.light.png differ diff --git a/docs/IDE/Code/Images/Command_Palette.png b/docs/IDE/Code/Images/Command_Palette.png index 277f5d153..7e8a0c179 100644 Binary files a/docs/IDE/Code/Images/Command_Palette.png and b/docs/IDE/Code/Images/Command_Palette.png differ diff --git a/docs/IDE/Code/Images/Context_Menu.light.svg b/docs/IDE/Code/Images/Context_Menu.light.svg index ed6297a02..61083b3c7 100644 --- a/docs/IDE/Code/Images/Context_Menu.light.svg +++ b/docs/IDE/Code/Images/Context_Menu.light.svg @@ -1 +1 @@ -111213141516171819202122232425PublicFunctionTwice(ByValnAsLong)AsLongReturnn*2EndFunctionPublicSubWithWarning()ReDimmade(3)Debug.PrintUBound(made)EndSubPublicSubThird()Debug.PrintTwice(5)EndSubEndModule▶   run Helpers.WithWarning▶   run Helpers.ThirdDIAGNOSTICS0411Helpers.twinInventory.twinMainModule.twin[16,15]TB0003Datatype has not been explicitly declared so will default to Variant[18,13]TB0003Datatype has not been explicitly declared so will default to Variant[19,13]TB0003Datatype has not been explicitly declared so will default to VariantCALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]Go To DefinitionSHIFT+F2 / F12Last PositionCTRL+SHIFT+F2Toggle BookmarkCTRL+BNext BookmarkPrevious BookmarkCTRL+MClear Bookmarks (Document)Clear Bookmarks (Project)Rename SymbolF2Change All OccurrencesCutCTRL+X / SHIFT+DELETECopyCTRL+C / CTRL+INSERTPasteCTRL+VPaste As CommentCTRL+ALT+VQuick Find...ALT+FQuick Replace...ALT+HMonaco Command PaletteCode Editor OptionsShow Code FoldingRender WhitespaceFont SizeShow Navigation BarShow Indent GuidesShow Line NumbersCode Hints Always VisibleSticky ScrollShow MiniMapShow Advanced Info On HoverShow Single Row Of TabsAuto Prettify CodeShow CodeLens Run Procedurewhen hoveringnone13pxabove +111213141516171819202122232425PublicFunctionTwice(ByValnAsLong)AsLongReturnn*2EndFunctionPublicSubWithWarning()ReDimmade(3)Debug.PrintUBound(made)EndSubPublicSubThird()Debug.PrintTwice(5)EndSubEndModule▶   run Helpers.WithWarning▶   run Helpers.ThirdDIAGNOSTICS0411Helpers.twinInventory.twinMainModule.twin[16,15]TB0003Datatype has not been explicitly declared so will default to Variant[18,13]TB0003Datatype has not been explicitly declared so will default to Variant[19,13]TB0003Datatype has not been explicitly declared so will default to VariantCALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]Go To DefinitionSHIFT+F2 / F12Last PositionCTRL+SHIFT+F2Toggle BookmarkCTRL+BNext BookmarkPrevious BookmarkCTRL+MClear Bookmarks (Document)Clear Bookmarks (Project)Rename SymbolF2Change All OccurrencesCutCTRL+X / SHIFT+DELETECopyCTRL+C / CTRL+INSERTPasteCTRL+VPaste As CommentCTRL+ALT+VQuick Find...ALT+FQuick Replace...ALT+HMonaco Command PaletteCode Editor OptionsShow Code FoldingRender WhitespaceFont SizeShow Navigation BarShow Indent GuidesShow Line NumbersCode Hints Always VisibleSticky ScrollShow MiniMapShow Advanced Info On HoverShow Single Row Of TabsAuto Prettify CodeShow CodeLens Run Procedurewhen hoveringnone13pxabove diff --git a/docs/IDE/Code/Images/Context_Menu.png b/docs/IDE/Code/Images/Context_Menu.png index 036009139..aba04d5ce 100644 Binary files a/docs/IDE/Code/Images/Context_Menu.png and b/docs/IDE/Code/Images/Context_Menu.png differ diff --git a/docs/IDE/Code/Images/Context_Menu.svg b/docs/IDE/Code/Images/Context_Menu.svg index 2b8574b47..505d4ce2e 100644 --- a/docs/IDE/Code/Images/Context_Menu.svg +++ b/docs/IDE/Code/Images/Context_Menu.svg @@ -1 +1 @@ -111213141516171819202122232425PublicFunctionTwice(ByValnAsLong)AsLongReturnn*2EndFunctionPublicSubWithWarning()ReDimmade(3)Debug.PrintUBound(made)EndSubPublicSubThird()Debug.PrintTwice(5)EndSubEndModule▶   run Helpers.WithWarning▶   run Helpers.ThirdDIAGNOSTICS0411Helpers.twinInventory.twinMainModule.twin[16,15]TB0003Datatype has not been explicitly declared so will default to Variant[18,13]TB0003Datatype has not been explicitly declared so will default to Variant[19,13]TB0003Datatype has not been explicitly declared so will default to VariantCALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]Go To DefinitionSHIFT+F2 / F12Last PositionCTRL+SHIFT+F2Toggle BookmarkCTRL+BNext BookmarkPrevious BookmarkCTRL+MClear Bookmarks (Document)Clear Bookmarks (Project)Rename SymbolF2Change All OccurrencesCutCTRL+X / SHIFT+DELETECopyCTRL+C / CTRL+INSERTPasteCTRL+VPaste As CommentCTRL+ALT+VQuick Find...ALT+FQuick Replace...ALT+HMonaco Command PaletteCode Editor OptionsShow Code FoldingRender WhitespaceFont SizeShow Navigation BarShow Indent GuidesShow Line NumbersCode Hints Always VisibleSticky ScrollShow MiniMapShow Advanced Info On HoverShow Single Row Of TabsAuto Prettify CodeShow CodeLens Run Procedurewhen hoveringnone13pxabove +111213141516171819202122232425PublicFunctionTwice(ByValnAsLong)AsLongReturnn*2EndFunctionPublicSubWithWarning()ReDimmade(3)Debug.PrintUBound(made)EndSubPublicSubThird()Debug.PrintTwice(5)EndSubEndModule▶   run Helpers.WithWarning▶   run Helpers.ThirdDIAGNOSTICS0411Helpers.twinInventory.twinMainModule.twin[16,15]TB0003Datatype has not been explicitly declared so will default to Variant[18,13]TB0003Datatype has not been explicitly declared so will default to Variant[19,13]TB0003Datatype has not been explicitly declared so will default to VariantCALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]Go To DefinitionSHIFT+F2 / F12Last PositionCTRL+SHIFT+F2Toggle BookmarkCTRL+BNext BookmarkPrevious BookmarkCTRL+MClear Bookmarks (Document)Clear Bookmarks (Project)Rename SymbolF2Change All OccurrencesCutCTRL+X / SHIFT+DELETECopyCTRL+C / CTRL+INSERTPasteCTRL+VPaste As CommentCTRL+ALT+VQuick Find...ALT+FQuick Replace...ALT+HMonaco Command PaletteCode Editor OptionsShow Code FoldingRender WhitespaceFont SizeShow Navigation BarShow Indent GuidesShow Line NumbersCode Hints Always VisibleSticky ScrollShow MiniMapShow Advanced Info On HoverShow Single Row Of TabsAuto Prettify CodeShow CodeLens Run Procedurewhen hoveringnone13pxabove diff --git a/docs/IDE/Code/Images/Diagnostics_Menu.png b/docs/IDE/Code/Images/Diagnostics_Menu.png index 120141b77..617e5eb8a 100644 Binary files a/docs/IDE/Code/Images/Diagnostics_Menu.png and b/docs/IDE/Code/Images/Diagnostics_Menu.png differ diff --git a/docs/IDE/Code/Images/Diagnostics_Rows.png b/docs/IDE/Code/Images/Diagnostics_Rows.png index fcaf485bb..143ef498d 100644 Binary files a/docs/IDE/Code/Images/Diagnostics_Rows.png and b/docs/IDE/Code/Images/Diagnostics_Rows.png differ diff --git a/docs/IDE/Code/Images/Editor_Panel.png b/docs/IDE/Code/Images/Editor_Panel.png index 1a16d8613..0808b9cac 100644 Binary files a/docs/IDE/Code/Images/Editor_Panel.png and b/docs/IDE/Code/Images/Editor_Panel.png differ diff --git a/docs/IDE/Code/Images/Find_Project.light.png b/docs/IDE/Code/Images/Find_Project.light.png index c3d717aef..51082f5a9 100644 Binary files a/docs/IDE/Code/Images/Find_Project.light.png and b/docs/IDE/Code/Images/Find_Project.light.png differ diff --git a/docs/IDE/Code/Images/Find_Project.png b/docs/IDE/Code/Images/Find_Project.png index cebc72719..73dd65639 100644 Binary files a/docs/IDE/Code/Images/Find_Project.png and b/docs/IDE/Code/Images/Find_Project.png differ diff --git a/docs/IDE/Code/Images/Hints.light.png b/docs/IDE/Code/Images/Hints.light.png index 604326f7c..f9cb925cb 100644 Binary files a/docs/IDE/Code/Images/Hints.light.png and b/docs/IDE/Code/Images/Hints.light.png differ diff --git a/docs/IDE/Code/Images/Hints.png b/docs/IDE/Code/Images/Hints.png index 34104b0c2..ad638271c 100644 Binary files a/docs/IDE/Code/Images/Hints.png and b/docs/IDE/Code/Images/Hints.png differ diff --git a/docs/IDE/Code/Images/Hover.light.png b/docs/IDE/Code/Images/Hover.light.png index b8ad7e017..fe0e5200a 100644 Binary files a/docs/IDE/Code/Images/Hover.light.png and b/docs/IDE/Code/Images/Hover.light.png differ diff --git a/docs/IDE/Code/Images/Hover.png b/docs/IDE/Code/Images/Hover.png index 1bf0e4b0f..8a7957614 100644 Binary files a/docs/IDE/Code/Images/Hover.png and b/docs/IDE/Code/Images/Hover.png differ diff --git a/docs/IDE/Code/Images/Paste_As_Comment.light.png b/docs/IDE/Code/Images/Paste_As_Comment.light.png index 22a5cae96..8b6a33c44 100644 Binary files a/docs/IDE/Code/Images/Paste_As_Comment.light.png and b/docs/IDE/Code/Images/Paste_As_Comment.light.png differ diff --git a/docs/IDE/Code/Images/Paste_As_Comment.light.svg b/docs/IDE/Code/Images/Paste_As_Comment.light.svg index 7a7c377b5..d85d0f50d 100644 --- a/docs/IDE/Code/Images/Paste_As_Comment.light.svg +++ b/docs/IDE/Code/Images/Paste_As_Comment.light.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXEDITOR 1Helpers(general)Helpers.twin12ModuleHelpersTwiceReplace +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXEDITOR 1Helpers(general)Helpers.twin12ModuleHelpersTwiceReplace diff --git a/docs/IDE/Code/Images/Paste_As_Comment.png b/docs/IDE/Code/Images/Paste_As_Comment.png index 4209db078..a101e235a 100644 Binary files a/docs/IDE/Code/Images/Paste_As_Comment.png and b/docs/IDE/Code/Images/Paste_As_Comment.png differ diff --git a/docs/IDE/Code/Images/Paste_As_Comment.svg b/docs/IDE/Code/Images/Paste_As_Comment.svg index 07bdd6f04..b2065245e 100644 --- a/docs/IDE/Code/Images/Paste_As_Comment.svg +++ b/docs/IDE/Code/Images/Paste_As_Comment.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXEDITOR 1Helpers(general)Helpers.twin12ModuleHelpers +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXEDITOR 1Helpers(general)Helpers.twin12ModuleHelpers diff --git a/docs/IDE/Code/Images/Quick_Find.light.png b/docs/IDE/Code/Images/Quick_Find.light.png index 453b0e07f..44824752d 100644 Binary files a/docs/IDE/Code/Images/Quick_Find.light.png and b/docs/IDE/Code/Images/Quick_Find.light.png differ diff --git a/docs/IDE/Code/Images/Quick_Find.png b/docs/IDE/Code/Images/Quick_Find.png index 08706e645..af8702449 100644 Binary files a/docs/IDE/Code/Images/Quick_Find.png and b/docs/IDE/Code/Images/Quick_Find.png differ diff --git a/docs/IDE/Code/Images/SignatureHelp.light.png b/docs/IDE/Code/Images/SignatureHelp.light.png index 09199c99e..de5447ab7 100644 Binary files a/docs/IDE/Code/Images/SignatureHelp.light.png and b/docs/IDE/Code/Images/SignatureHelp.light.png differ diff --git a/docs/IDE/Code/Images/SignatureHelp.png b/docs/IDE/Code/Images/SignatureHelp.png index e41718c32..0d98155a9 100644 Binary files a/docs/IDE/Code/Images/SignatureHelp.png and b/docs/IDE/Code/Images/SignatureHelp.png differ diff --git a/docs/IDE/Code/Images/SignatureHelp_Expanded.light.png b/docs/IDE/Code/Images/SignatureHelp_Expanded.light.png index 8145f96d6..c078f7543 100644 Binary files a/docs/IDE/Code/Images/SignatureHelp_Expanded.light.png and b/docs/IDE/Code/Images/SignatureHelp_Expanded.light.png differ diff --git a/docs/IDE/Code/Images/SignatureHelp_Expanded.png b/docs/IDE/Code/Images/SignatureHelp_Expanded.png index 4bf42985e..b2f545e3d 100644 Binary files a/docs/IDE/Code/Images/SignatureHelp_Expanded.png and b/docs/IDE/Code/Images/SignatureHelp_Expanded.png differ diff --git a/docs/IDE/Code/Images/Tab_Menu.light.png b/docs/IDE/Code/Images/Tab_Menu.light.png index 3847ce618..9d350da4f 100644 Binary files a/docs/IDE/Code/Images/Tab_Menu.light.png and b/docs/IDE/Code/Images/Tab_Menu.light.png differ diff --git a/docs/IDE/Code/Images/Tab_Menu.png b/docs/IDE/Code/Images/Tab_Menu.png index c3ceacddc..55456a316 100644 Binary files a/docs/IDE/Code/Images/Tab_Menu.png and b/docs/IDE/Code/Images/Tab_Menu.png differ diff --git a/docs/IDE/Code/Images/Tabs_States.light.png b/docs/IDE/Code/Images/Tabs_States.light.png index d44dcfb13..f379c9c5c 100644 Binary files a/docs/IDE/Code/Images/Tabs_States.light.png and b/docs/IDE/Code/Images/Tabs_States.light.png differ diff --git a/docs/IDE/Code/Images/Tabs_States.png b/docs/IDE/Code/Images/Tabs_States.png index 6cc2adead..807bd59bc 100644 Binary files a/docs/IDE/Code/Images/Tabs_States.png and b/docs/IDE/Code/Images/Tabs_States.png differ diff --git a/docs/IDE/Debugging/Images/Breakpoint_Glyphs.light.png b/docs/IDE/Debugging/Images/Breakpoint_Glyphs.light.png index 0557658d2..1114ce30f 100644 Binary files a/docs/IDE/Debugging/Images/Breakpoint_Glyphs.light.png and b/docs/IDE/Debugging/Images/Breakpoint_Glyphs.light.png differ diff --git a/docs/IDE/Debugging/Images/Breakpoint_Glyphs.png b/docs/IDE/Debugging/Images/Breakpoint_Glyphs.png index 074bd0321..b782b1742 100644 Binary files a/docs/IDE/Debugging/Images/Breakpoint_Glyphs.png and b/docs/IDE/Debugging/Images/Breakpoint_Glyphs.png differ diff --git a/docs/IDE/Debugging/Images/CallStack_Frames.light.png b/docs/IDE/Debugging/Images/CallStack_Frames.light.png index 120f6a674..8c28e3237 100644 Binary files a/docs/IDE/Debugging/Images/CallStack_Frames.light.png and b/docs/IDE/Debugging/Images/CallStack_Frames.light.png differ diff --git a/docs/IDE/Debugging/Images/CallStack_Frames.light.svg b/docs/IDE/Debugging/Images/CallStack_Frames.light.svg index 2b0e3a0d8..8f7735638 100644 --- a/docs/IDE/Debugging/Images/CallStack_Frames.light.svg +++ b/docs/IDE/Debugging/Images/CallStack_Frames.light.svg @@ -1 +1 @@ -EDITOR 1MainModule(general)MainInventory.twinMainModule.twin123456789101112131415ModuleMainModulePublicSubMain()DimstockAsNewInventoryDimfirstAsStockItemDimcoststock.Add"Widget",120,2.5stock.Add"Gadget",8,14.75cost=stock.Total(0.2)first=stock.ItemByIndex(stock.Find("Widget"))Debug.Printfirst.Quantity, costEndSubEndModule▶   run MainModule.MainCALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsfirst:{user defined type, 16 bytes}StockItemstock:{object: 441954992}Inventorycost:EmptyVariant [Empty] +EDITOR 1MainModule(general)MainInventory.twinMainModule.twin123456789101112131415ModuleMainModulePublicSubMain()DimstockAsNewInventoryDimfirstAsStockItemDimcoststock.Add"Widget",120,2.5stock.Add"Gadget",8,14.75cost=stock.Total(0.2)first=stock.ItemByIndex(stock.Find("Widget"))Debug.Printfirst.Quantity, costEndSubEndModule▶   run MainModule.MainCALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsfirst:{user defined type, 16 bytes}StockItemstock:{object: 441954992}Inventorycost:EmptyVariant [Empty] diff --git a/docs/IDE/Debugging/Images/CallStack_Frames.png b/docs/IDE/Debugging/Images/CallStack_Frames.png index ad2f18f28..8c734c160 100644 Binary files a/docs/IDE/Debugging/Images/CallStack_Frames.png and b/docs/IDE/Debugging/Images/CallStack_Frames.png differ diff --git a/docs/IDE/Debugging/Images/CallStack_Frames.svg b/docs/IDE/Debugging/Images/CallStack_Frames.svg index 20694b7a5..f61b00b4c 100644 --- a/docs/IDE/Debugging/Images/CallStack_Frames.svg +++ b/docs/IDE/Debugging/Images/CallStack_Frames.svg @@ -1 +1 @@ -EDITOR 1MainModule(general)MainInventory.twinMainModule.twin123456789101112131415ModuleMainModulePublicSubMain()DimstockAsNewInventoryDimfirstAsStockItemDimcoststock.Add"Widget",120,2.5stock.Add"Gadget",8,14.75cost=stock.Total(0.2)first=stock.ItemByIndex(stock.Find("Widget"))Debug.Printfirst.Quantity, costEndSubEndModule▶   run MainModule.MainCALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsfirst:{user defined type, 16 bytes}StockItemstock:{object: 441954992}Inventorycost:EmptyVariant [Empty] +EDITOR 1MainModule(general)MainInventory.twinMainModule.twin123456789101112131415ModuleMainModulePublicSubMain()DimstockAsNewInventoryDimfirstAsStockItemDimcoststock.Add"Widget",120,2.5stock.Add"Gadget",8,14.75cost=stock.Total(0.2)first=stock.ItemByIndex(stock.Find("Widget"))Debug.Printfirst.Quantity, costEndSubEndModule▶   run MainModule.MainCALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsfirst:{user defined type, 16 bytes}StockItemstock:{object: 441954992}Inventorycost:EmptyVariant [Empty] diff --git a/docs/IDE/Debugging/Images/Console_Menu.light.png b/docs/IDE/Debugging/Images/Console_Menu.light.png index ece475f83..25ca06462 100644 Binary files a/docs/IDE/Debugging/Images/Console_Menu.light.png and b/docs/IDE/Debugging/Images/Console_Menu.light.png differ diff --git a/docs/IDE/Debugging/Images/Console_Menu.png b/docs/IDE/Debugging/Images/Console_Menu.png index 6cb556d7b..de7e3a597 100644 Binary files a/docs/IDE/Debugging/Images/Console_Menu.png and b/docs/IDE/Debugging/Images/Console_Menu.png differ diff --git a/docs/IDE/Debugging/Images/Console_Run.light.png b/docs/IDE/Debugging/Images/Console_Run.light.png index 96db0d289..76848c5c5 100644 Binary files a/docs/IDE/Debugging/Images/Console_Run.light.png and b/docs/IDE/Debugging/Images/Console_Run.light.png differ diff --git a/docs/IDE/Debugging/Images/Console_Run.png b/docs/IDE/Debugging/Images/Console_Run.png index 0f9d0f2fd..9fea85aaf 100644 Binary files a/docs/IDE/Debugging/Images/Console_Run.png and b/docs/IDE/Debugging/Images/Console_Run.png differ diff --git a/docs/IDE/Debugging/Images/Error_Panel.light.png b/docs/IDE/Debugging/Images/Error_Panel.light.png index e5e5420b8..71f386a90 100644 Binary files a/docs/IDE/Debugging/Images/Error_Panel.light.png and b/docs/IDE/Debugging/Images/Error_Panel.light.png differ diff --git a/docs/IDE/Debugging/Images/Error_Panel.light.svg b/docs/IDE/Debugging/Images/Error_Panel.light.svg index a30320e0e..80f3653af 100644 --- a/docs/IDE/Debugging/Images/Error_Panel.light.svg +++ b/docs/IDE/Debugging/Images/Error_Panel.light.svg @@ -1 +1 @@ -EDITOR 1Checks(general)FillTableChecks.twin5678910111213141516171819PublicSubFillTable()Dima(5)AsLongDimiAsLongDimidxAsLongDimtotalAsLongFori=1To6idx=Choose(i,1,3,5,7,2,4)a(idx)=i*10total=total+iDebug.Print"i = "&i&", idx = "&idx&", total = "&totalNextiDebug.Print"loop finished, i = "&i&", total = "&totalEndSub' A program that the program starts, short-lived and with no window: the PROCESS box.Run-time error 9 (00000009)DESCRIPTION:Subscript out of rangeTry Again (Resume)Ignore (Resume Next)StopSearch OnlineCALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [EXECUTING]12:1FillTableChecks.twinVARIABLESLocalsa:{array of 6 elements}Long()i:4Longidx:7Longtotal:6Long +EDITOR 1Checks(general)FillTableChecks.twin5678910111213141516171819PublicSubFillTable()Dima(5)AsLongDimiAsLongDimidxAsLongDimtotalAsLongFori=1To6idx=Choose(i,1,3,5,7,2,4)a(idx)=i*10total=total+iDebug.Print"i = "&i&", idx = "&idx&", total = "&totalNextiDebug.Print"loop finished, i = "&i&", total = "&totalEndSub' A program that the program starts, short-lived and with no window: the PROCESS box.Run-time error 9 (00000009)DESCRIPTION:Subscript out of rangeTry Again (Resume)Ignore (Resume Next)StopSearch OnlineCALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [EXECUTING]12:1FillTableChecks.twinVARIABLESLocalsa:{array of 6 elements}Long()i:4Longidx:7Longtotal:6Long diff --git a/docs/IDE/Debugging/Images/Error_Panel.png b/docs/IDE/Debugging/Images/Error_Panel.png index c8f2faf7a..951a2a6fe 100644 Binary files a/docs/IDE/Debugging/Images/Error_Panel.png and b/docs/IDE/Debugging/Images/Error_Panel.png differ diff --git a/docs/IDE/Debugging/Images/Error_Panel.svg b/docs/IDE/Debugging/Images/Error_Panel.svg index 71b1c8ae7..d56e6c382 100644 --- a/docs/IDE/Debugging/Images/Error_Panel.svg +++ b/docs/IDE/Debugging/Images/Error_Panel.svg @@ -1 +1 @@ -EDITOR 1Checks(general)FillTableChecks.twin5678910111213141516171819PublicSubFillTable()Dima(5)AsLongDimiAsLongDimidxAsLongDimtotalAsLongFori=1To6idx=Choose(i,1,3,5,7,2,4)a(idx)=i*10total=total+iDebug.Print"i = "&i&", idx = "&idx&", total = "&totalNextiDebug.Print"loop finished, i = "&i&", total = "&totalEndSub' A program that the program starts, short-lived and with no window: the PROCESS box.Run-time error 9 (00000009)DESCRIPTION:Subscript out of rangeTry Again (Resume)Ignore (Resume Next)StopSearch OnlineCALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [EXECUTING]12:1FillTableChecks.twinVARIABLESLocalsa:{array of 6 elements}Long()i:4Longidx:7Longtotal:6Long +EDITOR 1Checks(general)FillTableChecks.twin5678910111213141516171819PublicSubFillTable()Dima(5)AsLongDimiAsLongDimidxAsLongDimtotalAsLongFori=1To6idx=Choose(i,1,3,5,7,2,4)a(idx)=i*10total=total+iDebug.Print"i = "&i&", idx = "&idx&", total = "&totalNextiDebug.Print"loop finished, i = "&i&", total = "&totalEndSub' A program that the program starts, short-lived and with no window: the PROCESS box.Run-time error 9 (00000009)DESCRIPTION:Subscript out of rangeTry Again (Resume)Ignore (Resume Next)StopSearch OnlineCALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [EXECUTING]12:1FillTableChecks.twinVARIABLESLocalsa:{array of 6 elements}Long()i:4Longidx:7Longtotal:6Long diff --git a/docs/IDE/Debugging/Images/Hover_Paused.light.png b/docs/IDE/Debugging/Images/Hover_Paused.light.png index 9be8b6d7a..2b112df64 100644 Binary files a/docs/IDE/Debugging/Images/Hover_Paused.light.png and b/docs/IDE/Debugging/Images/Hover_Paused.light.png differ diff --git a/docs/IDE/Debugging/Images/Hover_Paused.png b/docs/IDE/Debugging/Images/Hover_Paused.png index a26a9906a..0312a3140 100644 Binary files a/docs/IDE/Debugging/Images/Hover_Paused.png and b/docs/IDE/Debugging/Images/Hover_Paused.png differ diff --git a/docs/IDE/Debugging/Images/Hover_Selection.light.png b/docs/IDE/Debugging/Images/Hover_Selection.light.png index e3c826f31..d84aa2a8c 100644 Binary files a/docs/IDE/Debugging/Images/Hover_Selection.light.png and b/docs/IDE/Debugging/Images/Hover_Selection.light.png differ diff --git a/docs/IDE/Debugging/Images/Hover_Selection.png b/docs/IDE/Debugging/Images/Hover_Selection.png index 6ba274d40..d5deb11a1 100644 Binary files a/docs/IDE/Debugging/Images/Hover_Selection.png and b/docs/IDE/Debugging/Images/Hover_Selection.png differ diff --git a/docs/IDE/Debugging/Images/Paused_Line.light.png b/docs/IDE/Debugging/Images/Paused_Line.light.png index 8503f7f5a..6ed99fc27 100644 Binary files a/docs/IDE/Debugging/Images/Paused_Line.light.png and b/docs/IDE/Debugging/Images/Paused_Line.light.png differ diff --git a/docs/IDE/Debugging/Images/Paused_Line.light.svg b/docs/IDE/Debugging/Images/Paused_Line.light.svg index 1fee76d6c..4af3434e4 100644 --- a/docs/IDE/Debugging/Images/Paused_Line.light.svg +++ b/docs/IDE/Debugging/Images/Paused_Line.light.svg @@ -1 +1 @@ -EDITOR 1Inventory(general)TotalInventory.twin222324252627282930313233343536161718192021Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIfEndIfNextTotal=subtotalEndFunctionPublicFunctionFind(ByValnameAsString)AsLongFind=-1PublicFunctionTotal(ByValtaxRateAsDouble)AsDoubleDimiAsLongDimsubtotalDimnoteDimpriceAsDoubleFori=0Tocount-1CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsMe:{object: 441954992}InventoryTotal:0Doublei:0Longnote:EmptyVariant [Empty]price:3Double +EDITOR 1Inventory(general)TotalInventory.twin222324252627282930313233343536161718192021Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIfEndIfNextTotal=subtotalEndFunctionPublicFunctionFind(ByValnameAsString)AsLongFind=-1PublicFunctionTotal(ByValtaxRateAsDouble)AsDoubleDimiAsLongDimsubtotalDimnoteDimpriceAsDoubleFori=0Tocount-1CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsMe:{object: 441954992}InventoryTotal:0Doublei:0Longnote:EmptyVariant [Empty]price:3Double diff --git a/docs/IDE/Debugging/Images/Paused_Line.png b/docs/IDE/Debugging/Images/Paused_Line.png index 4dab332e0..9b84032f5 100644 Binary files a/docs/IDE/Debugging/Images/Paused_Line.png and b/docs/IDE/Debugging/Images/Paused_Line.png differ diff --git a/docs/IDE/Debugging/Images/Paused_Line.svg b/docs/IDE/Debugging/Images/Paused_Line.svg index 4157a3077..967ea6ab7 100644 --- a/docs/IDE/Debugging/Images/Paused_Line.svg +++ b/docs/IDE/Debugging/Images/Paused_Line.svg @@ -1 +1 @@ -EDITOR 1Inventory(general)TotalInventory.twin222324252627282930313233343536161718192021Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIfEndIfNextTotal=subtotalEndFunctionPublicFunctionFind(ByValnameAsString)AsLongFind=-1PublicFunctionTotal(ByValtaxRateAsDouble)AsDoubleDimiAsLongDimsubtotalDimnoteDimpriceAsDoubleFori=0Tocount-1CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsMe:{object: 441954992}InventoryTotal:0Doublei:0Longnote:EmptyVariant [Empty]price:3Double +EDITOR 1Inventory(general)TotalInventory.twin222324252627282930313233343536161718192021Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIfEndIfNextTotal=subtotalEndFunctionPublicFunctionFind(ByValnameAsString)AsLongFind=-1PublicFunctionTotal(ByValtaxRateAsDouble)AsDoubleDimiAsLongDimsubtotalDimnoteDimpriceAsDoubleFori=0Tocount-1CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsMe:{object: 441954992}InventoryTotal:0Doublei:0Longnote:EmptyVariant [Empty]price:3Double diff --git a/docs/IDE/Debugging/Images/Paused_Panels.light.png b/docs/IDE/Debugging/Images/Paused_Panels.light.png index fe2c81279..bc58c88f5 100644 Binary files a/docs/IDE/Debugging/Images/Paused_Panels.light.png and b/docs/IDE/Debugging/Images/Paused_Panels.light.png differ diff --git a/docs/IDE/Debugging/Images/Paused_Panels.light.svg b/docs/IDE/Debugging/Images/Paused_Panels.light.svg index 92a0d0d9a..c69b4ecee 100644 --- a/docs/IDE/Debugging/Images/Paused_Panels.light.svg +++ b/docs/IDE/Debugging/Images/Paused_Panels.light.svg @@ -1 +1 @@ -tB Services: OPERATIONALULTIMATE EDITIONFileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32100%PREVIEWEDITOR 1Inventory(general)TotalInventory.twin1617181920212223242526272829303132333435363738PublicFunctionTotal(ByValtaxRateAsDouble)AsDoubleDimiAsLongDimsubtotalDimnoteDimpriceAsDoubleFori=0Tocount-1Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIfEndIfNextTotal=subtotalEndFunctionPublicFunctionFind(ByValnameAsString)AsLongFind=-1DimiAsLongFori=0Tocount-1DEBUG CONSOLE>16:41:58.204Executing 'Main'...16:41:58.204Grüße 👋 こんにちは: WidgetCALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsMe:{object: 441954992}InventoryTotal:0Doublei:1Longnote:"Grüße 👋 こんにちは"Variant [String]price:17.7Doublesubtotal:360Variant [Double]taxRate:0.2DoubleWATCHESitems(i).Quantity:8Longsubtotal:360Variant [Double] +tB Services: OPERATIONALULTIMATE EDITIONFileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32100%PREVIEWEDITOR 1Inventory(general)TotalInventory.twin1617181920212223242526272829303132333435363738PublicFunctionTotal(ByValtaxRateAsDouble)AsDoubleDimiAsLongDimsubtotalDimnoteDimpriceAsDoubleFori=0Tocount-1Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIfEndIfNextTotal=subtotalEndFunctionPublicFunctionFind(ByValnameAsString)AsLongFind=-1DimiAsLongFori=0Tocount-1DEBUG CONSOLE>16:41:58.204Executing 'Main'...16:41:58.204Grüße 👋 こんにちは: WidgetCALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsMe:{object: 441954992}InventoryTotal:0Doublei:1Longnote:"Grüße 👋 こんにちは"Variant [String]price:17.7Doublesubtotal:360Variant [Double]taxRate:0.2DoubleWATCHESitems(i).Quantity:8Longsubtotal:360Variant [Double] diff --git a/docs/IDE/Debugging/Images/Paused_Panels.png b/docs/IDE/Debugging/Images/Paused_Panels.png index 7290c1039..1b20c4a7e 100644 Binary files a/docs/IDE/Debugging/Images/Paused_Panels.png and b/docs/IDE/Debugging/Images/Paused_Panels.png differ diff --git a/docs/IDE/Debugging/Images/Paused_Panels.svg b/docs/IDE/Debugging/Images/Paused_Panels.svg index a40b3f561..e41cc2a01 100644 --- a/docs/IDE/Debugging/Images/Paused_Panels.svg +++ b/docs/IDE/Debugging/Images/Paused_Panels.svg @@ -1 +1 @@ -tB Services: OPERATIONALULTIMATE EDITIONFileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32100%PREVIEWEDITOR 1Inventory(general)TotalInventory.twin161718192021222324252627282930313233343536373839PublicFunctionTotal(ByValtaxRateAsDouble)AsDoubleDimiAsLongDimsubtotalDimnoteDimpriceAsDoubleFori=0Tocount-1Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIfEndIfNextTotal=subtotalEndFunctionPublicFunctionFind(ByValnameAsString)AsLongFind=-1DimiAsLongFori=0Tocount-1Ifitems(i).Name=nameThenDEBUG CONSOLE>16:41:58.204Executing 'Main'...16:41:58.204Grüße 👋 こんにちは: WidgetCALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsMe:{object: 441954992}InventoryTotal:0Doublei:1Longnote:"Grüße 👋 こんにちは"Variant [String]price:17.7Doublesubtotal:360Variant [Double]taxRate:0.2DoubleWATCHESitems(i).Quantity:8Longsubtotal:360Variant [Double] +tB Services: OPERATIONALULTIMATE EDITIONFileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32100%PREVIEWEDITOR 1Inventory(general)TotalInventory.twin161718192021222324252627282930313233343536373839PublicFunctionTotal(ByValtaxRateAsDouble)AsDoubleDimiAsLongDimsubtotalDimnoteDimpriceAsDoubleFori=0Tocount-1Ifitems(i).Quantity>0Thenprice=Round(items(i).Price*(1+taxRate),2)subtotal=subtotal+items(i).Quantity*priceIfitems(i).Quantity>100Thennote="Grüße 👋 こんにちは"Debug.Printnote&": "&items(i).NameEndIfEndIfNextTotal=subtotalEndFunctionPublicFunctionFind(ByValnameAsString)AsLongFind=-1DimiAsLongFori=0Tocount-1Ifitems(i).Name=nameThenDEBUG CONSOLE>16:41:58.204Executing 'Main'...16:41:58.204Grüße 👋 こんにちは: WidgetCALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [EXECUTING]24:1TotalInventory.twin9:1MainMainModule.twinVARIABLESLocalsMe:{object: 441954992}InventoryTotal:0Doublei:1Longnote:"Grüße 👋 こんにちは"Variant [String]price:17.7Doublesubtotal:360Variant [Double]taxRate:0.2DoubleWATCHESitems(i).Quantity:8Longsubtotal:360Variant [Double] diff --git a/docs/IDE/Debugging/Images/Toolbar_Paused.light.png b/docs/IDE/Debugging/Images/Toolbar_Paused.light.png index 7d93ff04a..5faee5e1c 100644 Binary files a/docs/IDE/Debugging/Images/Toolbar_Paused.light.png and b/docs/IDE/Debugging/Images/Toolbar_Paused.light.png differ diff --git a/docs/IDE/Debugging/Images/Toolbar_Paused.png b/docs/IDE/Debugging/Images/Toolbar_Paused.png index 06f787501..355f2405b 100644 Binary files a/docs/IDE/Debugging/Images/Toolbar_Paused.png and b/docs/IDE/Debugging/Images/Toolbar_Paused.png differ diff --git a/docs/IDE/Debugging/Images/Variables_Edit.png b/docs/IDE/Debugging/Images/Variables_Edit.png index 07b00bc10..9b7d4fd8c 100644 Binary files a/docs/IDE/Debugging/Images/Variables_Edit.png and b/docs/IDE/Debugging/Images/Variables_Edit.png differ diff --git a/docs/IDE/Debugging/Images/Variables_Expanded.png b/docs/IDE/Debugging/Images/Variables_Expanded.png index ffc817be9..13f5a832a 100644 Binary files a/docs/IDE/Debugging/Images/Variables_Expanded.png and b/docs/IDE/Debugging/Images/Variables_Expanded.png differ diff --git a/docs/IDE/Debugging/Images/Variables_Tooltip.light.png b/docs/IDE/Debugging/Images/Variables_Tooltip.light.png index 6be3ffa0f..a942fc593 100644 Binary files a/docs/IDE/Debugging/Images/Variables_Tooltip.light.png and b/docs/IDE/Debugging/Images/Variables_Tooltip.light.png differ diff --git a/docs/IDE/Debugging/Images/Variables_Tooltip.png b/docs/IDE/Debugging/Images/Variables_Tooltip.png index 81a21655b..4355edb65 100644 Binary files a/docs/IDE/Debugging/Images/Variables_Tooltip.png and b/docs/IDE/Debugging/Images/Variables_Tooltip.png differ diff --git a/docs/IDE/Debugging/Images/Variables_Tooltip.svg b/docs/IDE/Debugging/Images/Variables_Tooltip.svg index 78a91ffd1..14a60847a 100644 --- a/docs/IDE/Debugging/Images/Variables_Tooltip.svg +++ b/docs/IDE/Debugging/Images/Variables_Tooltip.svg @@ -1 +1 @@ -VARIABLESLocalsMe:{object: 441954992}InventoryTotal:0Doublei:1Longnote:"Grüße 👋 こんにちは"Variant [String]price:17.7Doublesubtotal:360Variant [Double]taxRate:0.2DoublesubtotalTypeVariant [Double]ValuePointer360(&H0019F3A4) +VARIABLESLocalsMe:{object: 441954992}InventoryTotal:0Doublei:1Longnote:"Grüße 👋 こんにちは"Variant [String]price:17.7Doublesubtotal:360Variant [Double]taxRate:0.2DoublesubtotalTypeVariant [Double]ValuePointer360(&H0019F3A4) diff --git a/docs/IDE/Debugging/Images/Watches_NotAvailable.png b/docs/IDE/Debugging/Images/Watches_NotAvailable.png index 2c2899217..016818b57 100644 Binary files a/docs/IDE/Debugging/Images/Watches_NotAvailable.png and b/docs/IDE/Debugging/Images/Watches_NotAvailable.png differ diff --git a/docs/IDE/Debugging/Images/Watches_Values.png b/docs/IDE/Debugging/Images/Watches_Values.png index 6fb7cda79..fd22c9ed5 100644 Binary files a/docs/IDE/Debugging/Images/Watches_Values.png and b/docs/IDE/Debugging/Images/Watches_Values.png differ diff --git a/docs/IDE/Forms/Images/Controls_Container.light.png b/docs/IDE/Forms/Images/Controls_Container.light.png index 3d92e4b2f..ceafbd6bb 100644 Binary files a/docs/IDE/Forms/Images/Controls_Container.light.png and b/docs/IDE/Forms/Images/Controls_Container.light.png differ diff --git a/docs/IDE/Forms/Images/Controls_Container.png b/docs/IDE/Forms/Images/Controls_Container.png index bbf6869e1..3ca724141 100644 Binary files a/docs/IDE/Forms/Images/Controls_Container.png and b/docs/IDE/Forms/Images/Controls_Container.png differ diff --git a/docs/IDE/Forms/Images/Controls_ContextMenu.light.png b/docs/IDE/Forms/Images/Controls_ContextMenu.light.png index 9264a1bc3..bccab8341 100644 Binary files a/docs/IDE/Forms/Images/Controls_ContextMenu.light.png and b/docs/IDE/Forms/Images/Controls_ContextMenu.light.png differ diff --git a/docs/IDE/Forms/Images/Controls_ContextMenu.png b/docs/IDE/Forms/Images/Controls_ContextMenu.png index dd3e28f23..9cc14efec 100644 Binary files a/docs/IDE/Forms/Images/Controls_ContextMenu.png and b/docs/IDE/Forms/Images/Controls_ContextMenu.png differ diff --git a/docs/IDE/Forms/Images/Controls_MultiSelect.light.png b/docs/IDE/Forms/Images/Controls_MultiSelect.light.png index 25328f5d3..779aa795f 100644 Binary files a/docs/IDE/Forms/Images/Controls_MultiSelect.light.png and b/docs/IDE/Forms/Images/Controls_MultiSelect.light.png differ diff --git a/docs/IDE/Forms/Images/Controls_MultiSelect.png b/docs/IDE/Forms/Images/Controls_MultiSelect.png index 41e2ca014..cd28eecb9 100644 Binary files a/docs/IDE/Forms/Images/Controls_MultiSelect.png and b/docs/IDE/Forms/Images/Controls_MultiSelect.png differ diff --git a/docs/IDE/Forms/Images/Controls_RubberBand.light.png b/docs/IDE/Forms/Images/Controls_RubberBand.light.png index 264c3fbd1..819eefd96 100644 Binary files a/docs/IDE/Forms/Images/Controls_RubberBand.light.png and b/docs/IDE/Forms/Images/Controls_RubberBand.light.png differ diff --git a/docs/IDE/Forms/Images/Controls_RubberBand.png b/docs/IDE/Forms/Images/Controls_RubberBand.png index 124666040..e9b4bfe4a 100644 Binary files a/docs/IDE/Forms/Images/Controls_RubberBand.png and b/docs/IDE/Forms/Images/Controls_RubberBand.png differ diff --git a/docs/IDE/Forms/Images/Designer_AddName.light.png b/docs/IDE/Forms/Images/Designer_AddName.light.png index 449e2b144..ba8a1d939 100644 Binary files a/docs/IDE/Forms/Images/Designer_AddName.light.png and b/docs/IDE/Forms/Images/Designer_AddName.light.png differ diff --git a/docs/IDE/Forms/Images/Designer_AddName.png b/docs/IDE/Forms/Images/Designer_AddName.png index 9ee5bd4eb..a692c1671 100644 Binary files a/docs/IDE/Forms/Images/Designer_AddName.png and b/docs/IDE/Forms/Images/Designer_AddName.png differ diff --git a/docs/IDE/Forms/Images/Designer_GridOptions.light.png b/docs/IDE/Forms/Images/Designer_GridOptions.light.png index 553757122..cce0b9906 100644 Binary files a/docs/IDE/Forms/Images/Designer_GridOptions.light.png and b/docs/IDE/Forms/Images/Designer_GridOptions.light.png differ diff --git a/docs/IDE/Forms/Images/Designer_GridOptions.png b/docs/IDE/Forms/Images/Designer_GridOptions.png index 5ac0a5ccd..42b7e5abd 100644 Binary files a/docs/IDE/Forms/Images/Designer_GridOptions.png and b/docs/IDE/Forms/Images/Designer_GridOptions.png differ diff --git a/docs/IDE/Forms/Images/Designer_Locked.light.png b/docs/IDE/Forms/Images/Designer_Locked.light.png index 927fd7691..748846752 100644 Binary files a/docs/IDE/Forms/Images/Designer_Locked.light.png and b/docs/IDE/Forms/Images/Designer_Locked.light.png differ diff --git a/docs/IDE/Forms/Images/Designer_Locked.png b/docs/IDE/Forms/Images/Designer_Locked.png index 285a349b0..f2d192281 100644 Binary files a/docs/IDE/Forms/Images/Designer_Locked.png and b/docs/IDE/Forms/Images/Designer_Locked.png differ diff --git a/docs/IDE/Forms/Images/Designer_PackageNeeded.light.png b/docs/IDE/Forms/Images/Designer_PackageNeeded.light.png index 32a7e9c76..08e4de0f6 100644 Binary files a/docs/IDE/Forms/Images/Designer_PackageNeeded.light.png and b/docs/IDE/Forms/Images/Designer_PackageNeeded.light.png differ diff --git a/docs/IDE/Forms/Images/Designer_PackageNeeded.png b/docs/IDE/Forms/Images/Designer_PackageNeeded.png index 0e31d794d..53af2fff5 100644 Binary files a/docs/IDE/Forms/Images/Designer_PackageNeeded.png and b/docs/IDE/Forms/Images/Designer_PackageNeeded.png differ diff --git a/docs/IDE/Forms/Images/Designer_Selected.light.png b/docs/IDE/Forms/Images/Designer_Selected.light.png index cdcf1da69..98d1a8c92 100644 Binary files a/docs/IDE/Forms/Images/Designer_Selected.light.png and b/docs/IDE/Forms/Images/Designer_Selected.light.png differ diff --git a/docs/IDE/Forms/Images/Designer_Selected.png b/docs/IDE/Forms/Images/Designer_Selected.png index 5faf36951..870ae8dc0 100644 Binary files a/docs/IDE/Forms/Images/Designer_Selected.png and b/docs/IDE/Forms/Images/Designer_Selected.png differ diff --git a/docs/IDE/Forms/Images/Designer_TabIndex.light.png b/docs/IDE/Forms/Images/Designer_TabIndex.light.png index 7442ae295..d0bcd2f00 100644 Binary files a/docs/IDE/Forms/Images/Designer_TabIndex.light.png and b/docs/IDE/Forms/Images/Designer_TabIndex.light.png differ diff --git a/docs/IDE/Forms/Images/Designer_TabIndex.png b/docs/IDE/Forms/Images/Designer_TabIndex.png index 5ad3e5591..d76b375af 100644 Binary files a/docs/IDE/Forms/Images/Designer_TabIndex.png and b/docs/IDE/Forms/Images/Designer_TabIndex.png differ diff --git a/docs/IDE/Forms/Images/Designer_Zoom.light.png b/docs/IDE/Forms/Images/Designer_Zoom.light.png index e7d86e461..ff853487c 100644 Binary files a/docs/IDE/Forms/Images/Designer_Zoom.light.png and b/docs/IDE/Forms/Images/Designer_Zoom.light.png differ diff --git a/docs/IDE/Forms/Images/Designer_Zoom.png b/docs/IDE/Forms/Images/Designer_Zoom.png index 5a6f848ef..222f0c3d6 100644 Binary files a/docs/IDE/Forms/Images/Designer_Zoom.png and b/docs/IDE/Forms/Images/Designer_Zoom.png differ diff --git a/docs/IDE/Forms/Images/MenuEditor_Bar.light.png b/docs/IDE/Forms/Images/MenuEditor_Bar.light.png index 12477d9e2..0d485ce6c 100644 Binary files a/docs/IDE/Forms/Images/MenuEditor_Bar.light.png and b/docs/IDE/Forms/Images/MenuEditor_Bar.light.png differ diff --git a/docs/IDE/Forms/Images/MenuEditor_Bar.png b/docs/IDE/Forms/Images/MenuEditor_Bar.png index d5262bba6..fb1b2669b 100644 Binary files a/docs/IDE/Forms/Images/MenuEditor_Bar.png and b/docs/IDE/Forms/Images/MenuEditor_Bar.png differ diff --git a/docs/IDE/Forms/Images/MenuEditor_Open.light.png b/docs/IDE/Forms/Images/MenuEditor_Open.light.png index d2d7b60e2..36f7ff98c 100644 Binary files a/docs/IDE/Forms/Images/MenuEditor_Open.light.png and b/docs/IDE/Forms/Images/MenuEditor_Open.light.png differ diff --git a/docs/IDE/Forms/Images/MenuEditor_Open.png b/docs/IDE/Forms/Images/MenuEditor_Open.png index d977014d6..06651d193 100644 Binary files a/docs/IDE/Forms/Images/MenuEditor_Open.png and b/docs/IDE/Forms/Images/MenuEditor_Open.png differ diff --git a/docs/IDE/Forms/Images/Properties_ColourPicker.light.png b/docs/IDE/Forms/Images/Properties_ColourPicker.light.png index 5e8c230ce..70952cac1 100644 Binary files a/docs/IDE/Forms/Images/Properties_ColourPicker.light.png and b/docs/IDE/Forms/Images/Properties_ColourPicker.light.png differ diff --git a/docs/IDE/Forms/Images/Properties_ColourPicker.png b/docs/IDE/Forms/Images/Properties_ColourPicker.png index f2f4393df..7fa0d0cc6 100644 Binary files a/docs/IDE/Forms/Images/Properties_ColourPicker.png and b/docs/IDE/Forms/Images/Properties_ColourPicker.png differ diff --git a/docs/IDE/Forms/Images/Properties_Control.light.png b/docs/IDE/Forms/Images/Properties_Control.light.png index fb6ea4f89..821a34186 100644 Binary files a/docs/IDE/Forms/Images/Properties_Control.light.png and b/docs/IDE/Forms/Images/Properties_Control.light.png differ diff --git a/docs/IDE/Forms/Images/Properties_Control.light.svg b/docs/IDE/Forms/Images/Properties_Control.light.svg index 856806a21..a628382f8 100644 --- a/docs/IDE/Forms/Images/Properties_Control.light.svg +++ b/docs/IDE/Forms/Images/Properties_Control.light.svg @@ -1 +1 @@ -ImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinMyReport.tbreportMyReport.twinStartup.twinPROPERTIESPROPERTIESEVENTSDESIGNAPPEARANCEDRAWINGNameCommand1IndexCaption...Command1ToolTipText...VisualStylesTrueAppearance1 - vbAppear3dBackColor&H(BGR)8000000FForeColor&H(BGR)80000012Style0 - vbButtonStandardFontNameSegoe UIFontSize8FontBoldFalseFontItalicFalseFontStrikethruFalseFontUnderlineFalsePicture{0 bytes}...PictureDpiScalingFalseDownPicture{0 bytes}...DisabledPicture{0 bytes}...PictureAlignment1 - vbAlignTopCommand1    CommandButtonTabsObject drop-downCategory +ImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinMyReport.tbreportMyReport.twinStartup.twinPROPERTIESPROPERTIESEVENTSDESIGNAPPEARANCEDRAWINGNameCommand1IndexCaption...Command1ToolTipText...VisualStylesTrueAppearance1 - vbAppear3dBackColor&H(BGR)8000000FForeColor&H(BGR)80000012Style0 - vbButtonStandardFontNameSegoe UIFontSize8FontBoldFalseFontItalicFalseFontStrikethruFalseFontUnderlineFalsePicture{0 bytes}...PictureDpiScalingFalseDownPicture{0 bytes}...DisabledPicture{0 bytes}...PictureAlignment1 - vbAlignTopCommand1    CommandButtonTabsObject drop-downCategory diff --git a/docs/IDE/Forms/Images/Properties_Control.png b/docs/IDE/Forms/Images/Properties_Control.png index f39b1fb4f..c25a5eb91 100644 Binary files a/docs/IDE/Forms/Images/Properties_Control.png and b/docs/IDE/Forms/Images/Properties_Control.png differ diff --git a/docs/IDE/Forms/Images/Properties_Control.svg b/docs/IDE/Forms/Images/Properties_Control.svg index 37325589b..e5191f228 100644 --- a/docs/IDE/Forms/Images/Properties_Control.svg +++ b/docs/IDE/Forms/Images/Properties_Control.svg @@ -1 +1 @@ -ImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinMyReport.tbreportMyReport.twinStartup.twinPROPERTIESPROPERTIESEVENTSDESIGNAPPEARANCEDRAWINGNameCommand1IndexCaption...Command1ToolTipText...VisualStylesTrueAppearance1 - vbAppear3dBackColor&H(BGR)8000000FForeColor&H(BGR)80000012Style0 - vbButtonStandardFontNameSegoe UIFontSize8FontBoldFalseFontItalicFalseFontStrikethruFalseFontUnderlineFalsePicture{0 bytes}...PictureDpiScalingFalseDownPicture{0 bytes}...DisabledPicture{0 bytes}...Command1    CommandButtonTabsObject drop-downCategory +ImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesfrmMain.tbformfrmMain.twinMyReport.tbreportMyReport.twinStartup.twinPROPERTIESPROPERTIESEVENTSDESIGNAPPEARANCEDRAWINGNameCommand1IndexCaption...Command1ToolTipText...VisualStylesTrueAppearance1 - vbAppear3dBackColor&H(BGR)8000000FForeColor&H(BGR)80000012Style0 - vbButtonStandardFontNameSegoe UIFontSize8FontBoldFalseFontItalicFalseFontStrikethruFalseFontUnderlineFalsePicture{0 bytes}...PictureDpiScalingFalseDownPicture{0 bytes}...DisabledPicture{0 bytes}...Command1    CommandButtonTabsObject drop-downCategory diff --git a/docs/IDE/Forms/Images/Properties_SystemColours.light.png b/docs/IDE/Forms/Images/Properties_SystemColours.light.png index fa9784a9f..574309221 100644 Binary files a/docs/IDE/Forms/Images/Properties_SystemColours.light.png and b/docs/IDE/Forms/Images/Properties_SystemColours.light.png differ diff --git a/docs/IDE/Forms/Images/Properties_SystemColours.png b/docs/IDE/Forms/Images/Properties_SystemColours.png index 280c9c5c3..05600a801 100644 Binary files a/docs/IDE/Forms/Images/Properties_SystemColours.png and b/docs/IDE/Forms/Images/Properties_SystemColours.png differ diff --git a/docs/IDE/Forms/Images/Toolbox_Form.light.png b/docs/IDE/Forms/Images/Toolbox_Form.light.png index f787d3e4b..ada28347f 100644 Binary files a/docs/IDE/Forms/Images/Toolbox_Form.light.png and b/docs/IDE/Forms/Images/Toolbox_Form.light.png differ diff --git a/docs/IDE/Forms/Images/Toolbox_Form.png b/docs/IDE/Forms/Images/Toolbox_Form.png index 85daefdec..b16a9d19d 100644 Binary files a/docs/IDE/Forms/Images/Toolbox_Form.png and b/docs/IDE/Forms/Images/Toolbox_Form.png differ diff --git a/docs/IDE/Forms/Images/Toolbox_Search.light.png b/docs/IDE/Forms/Images/Toolbox_Search.light.png index 07a18c307..80afec338 100644 Binary files a/docs/IDE/Forms/Images/Toolbox_Search.light.png and b/docs/IDE/Forms/Images/Toolbox_Search.light.png differ diff --git a/docs/IDE/Forms/Images/Toolbox_Search.png b/docs/IDE/Forms/Images/Toolbox_Search.png index 02e078bef..c69c8a68d 100644 Binary files a/docs/IDE/Forms/Images/Toolbox_Search.png and b/docs/IDE/Forms/Images/Toolbox_Search.png differ diff --git a/docs/IDE/Images/Add.light.png b/docs/IDE/Images/Add.light.png index 434175ef6..40ac62170 100644 Binary files a/docs/IDE/Images/Add.light.png and b/docs/IDE/Images/Add.light.png differ diff --git a/docs/IDE/Images/Add.png b/docs/IDE/Images/Add.png index 42f076a19..f2b08d033 100644 Binary files a/docs/IDE/Images/Add.png and b/docs/IDE/Images/Add.png differ diff --git a/docs/IDE/Images/CallStack.light.png b/docs/IDE/Images/CallStack.light.png index 4763969b8..7cd8a969a 100644 Binary files a/docs/IDE/Images/CallStack.light.png and b/docs/IDE/Images/CallStack.light.png differ diff --git a/docs/IDE/Images/CallStack.light.svg b/docs/IDE/Images/CallStack.light.svg index 803f4e166..40f8cb784 100644 --- a/docs/IDE/Images/CallStack.light.svg +++ b/docs/IDE/Images/CallStack.light.svg @@ -1 +1 @@ -CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]Active Threads +CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]Active Threads diff --git a/docs/IDE/Images/CallStack.png b/docs/IDE/Images/CallStack.png index 03a0bd811..fd9aa19b4 100644 Binary files a/docs/IDE/Images/CallStack.png and b/docs/IDE/Images/CallStack.png differ diff --git a/docs/IDE/Images/CallStack.svg b/docs/IDE/Images/CallStack.svg index 3e463c394..4c8876f7f 100644 --- a/docs/IDE/Images/CallStack.svg +++ b/docs/IDE/Images/CallStack.svg @@ -1 +1 @@ -CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]Active Threads +CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]Active Threads diff --git a/docs/IDE/Images/Clear.light.png b/docs/IDE/Images/Clear.light.png index 6943b86de..d6b414318 100644 Binary files a/docs/IDE/Images/Clear.light.png and b/docs/IDE/Images/Clear.light.png differ diff --git a/docs/IDE/Images/Clear.png b/docs/IDE/Images/Clear.png index c1c8cdd6f..13c69e446 100644 Binary files a/docs/IDE/Images/Clear.png and b/docs/IDE/Images/Clear.png differ diff --git a/docs/IDE/Images/Components_Message.png b/docs/IDE/Images/Components_Message.png index c9f3062ec..fd492bdad 100644 Binary files a/docs/IDE/Images/Components_Message.png and b/docs/IDE/Images/Components_Message.png differ diff --git a/docs/IDE/Images/DebugConsole_AutoScroll.light.png b/docs/IDE/Images/DebugConsole_AutoScroll.light.png index 78680cdf2..28498fb66 100644 Binary files a/docs/IDE/Images/DebugConsole_AutoScroll.light.png and b/docs/IDE/Images/DebugConsole_AutoScroll.light.png differ diff --git a/docs/IDE/Images/DebugConsole_AutoScroll.png b/docs/IDE/Images/DebugConsole_AutoScroll.png index 1310d834a..89ea1b518 100644 Binary files a/docs/IDE/Images/DebugConsole_AutoScroll.png and b/docs/IDE/Images/DebugConsole_AutoScroll.png differ diff --git a/docs/IDE/Images/DebugConsole_Clear.light.png b/docs/IDE/Images/DebugConsole_Clear.light.png index 571bdebea..623b793f4 100644 Binary files a/docs/IDE/Images/DebugConsole_Clear.light.png and b/docs/IDE/Images/DebugConsole_Clear.light.png differ diff --git a/docs/IDE/Images/DebugConsole_Clear.png b/docs/IDE/Images/DebugConsole_Clear.png index a24519084..07d20f87d 100644 Binary files a/docs/IDE/Images/DebugConsole_Clear.png and b/docs/IDE/Images/DebugConsole_Clear.png differ diff --git a/docs/IDE/Images/DebugConsole_Input.png b/docs/IDE/Images/DebugConsole_Input.png index d961c390e..a11b7a5a1 100644 Binary files a/docs/IDE/Images/DebugConsole_Input.png and b/docs/IDE/Images/DebugConsole_Input.png differ diff --git a/docs/IDE/Images/DebugConsole_Options.light.png b/docs/IDE/Images/DebugConsole_Options.light.png index e3dbaba47..1518a85d2 100644 Binary files a/docs/IDE/Images/DebugConsole_Options.light.png and b/docs/IDE/Images/DebugConsole_Options.light.png differ diff --git a/docs/IDE/Images/DebugConsole_Options.png b/docs/IDE/Images/DebugConsole_Options.png index 5a4b87dbf..efdba15ed 100644 Binary files a/docs/IDE/Images/DebugConsole_Options.png and b/docs/IDE/Images/DebugConsole_Options.png differ diff --git a/docs/IDE/Images/Diagnostics.light.png b/docs/IDE/Images/Diagnostics.light.png index bda6101e2..bf7657e27 100644 Binary files a/docs/IDE/Images/Diagnostics.light.png and b/docs/IDE/Images/Diagnostics.light.png differ diff --git a/docs/IDE/Images/Diagnostics.png b/docs/IDE/Images/Diagnostics.png index ecbb2d1a4..77834ab70 100644 Binary files a/docs/IDE/Images/Diagnostics.png and b/docs/IDE/Images/Diagnostics.png differ diff --git a/docs/IDE/Images/Diagnostics_Toggles.light.png b/docs/IDE/Images/Diagnostics_Toggles.light.png index 4cc6cf896..1f50919dc 100644 Binary files a/docs/IDE/Images/Diagnostics_Toggles.light.png and b/docs/IDE/Images/Diagnostics_Toggles.light.png differ diff --git a/docs/IDE/Images/Diagnostics_Toggles.png b/docs/IDE/Images/Diagnostics_Toggles.png index 2f9ca1b95..994357fb1 100644 Binary files a/docs/IDE/Images/Diagnostics_Toggles.png and b/docs/IDE/Images/Diagnostics_Toggles.png differ diff --git a/docs/IDE/Images/Diagnostics_Totals.light.png b/docs/IDE/Images/Diagnostics_Totals.light.png index 5201df946..70dad4eed 100644 Binary files a/docs/IDE/Images/Diagnostics_Totals.light.png and b/docs/IDE/Images/Diagnostics_Totals.light.png differ diff --git a/docs/IDE/Images/Diagnostics_Totals.png b/docs/IDE/Images/Diagnostics_Totals.png index 36367d202..e0f7854d3 100644 Binary files a/docs/IDE/Images/Diagnostics_Totals.png and b/docs/IDE/Images/Diagnostics_Totals.png differ diff --git a/docs/IDE/Images/Editor.light.png b/docs/IDE/Images/Editor.light.png index de158f59a..ad273645f 100644 Binary files a/docs/IDE/Images/Editor.light.png and b/docs/IDE/Images/Editor.light.png differ diff --git a/docs/IDE/Images/Editor.png b/docs/IDE/Images/Editor.png index f6d6701fa..d3701c32b 100644 Binary files a/docs/IDE/Images/Editor.png and b/docs/IDE/Images/Editor.png differ diff --git a/docs/IDE/Images/File-Green.light.png b/docs/IDE/Images/File-Green.light.png index 539c60137..eb1eebb10 100644 Binary files a/docs/IDE/Images/File-Green.light.png and b/docs/IDE/Images/File-Green.light.png differ diff --git a/docs/IDE/Images/File-Green.png b/docs/IDE/Images/File-Green.png index 28224e9e1..2485cf8b7 100644 Binary files a/docs/IDE/Images/File-Green.png and b/docs/IDE/Images/File-Green.png differ diff --git a/docs/IDE/Images/FindReplace.png b/docs/IDE/Images/FindReplace.png index cf47aa81d..0112df408 100644 Binary files a/docs/IDE/Images/FindReplace.png and b/docs/IDE/Images/FindReplace.png differ diff --git a/docs/IDE/Images/FindReplace_Direction.png b/docs/IDE/Images/FindReplace_Direction.png index 51b41cc88..c9738e5b4 100644 Binary files a/docs/IDE/Images/FindReplace_Direction.png and b/docs/IDE/Images/FindReplace_Direction.png differ diff --git a/docs/IDE/Images/Folder.light.png b/docs/IDE/Images/Folder.light.png index 1bcd55907..deef56e08 100644 Binary files a/docs/IDE/Images/Folder.light.png and b/docs/IDE/Images/Folder.light.png differ diff --git a/docs/IDE/Images/Folder.png b/docs/IDE/Images/Folder.png index 6fea24a2e..97e547dc5 100644 Binary files a/docs/IDE/Images/Folder.png and b/docs/IDE/Images/Folder.png differ diff --git a/docs/IDE/Images/History_1.png b/docs/IDE/Images/History_1.png index 8c2268869..3e4b45d09 100644 Binary files a/docs/IDE/Images/History_1.png and b/docs/IDE/Images/History_1.png differ diff --git a/docs/IDE/Images/History_2.light.png b/docs/IDE/Images/History_2.light.png index 4ca5400da..0a4e64778 100644 Binary files a/docs/IDE/Images/History_2.light.png and b/docs/IDE/Images/History_2.light.png differ diff --git a/docs/IDE/Images/History_2.light.svg b/docs/IDE/Images/History_2.light.svg index 0ba9a2baa..52de4be58 100644 --- a/docs/IDE/Images/History_2.light.svg +++ b/docs/IDE/Images/History_2.light.svg @@ -1 +1 @@ -HISTORY16:41frmMain18:02frmMain/SampleProject/Sources/frmMain.tbform [line: undefined]Fri Jan 09 2026 18:02:51 GMT+0000 (GMT+00:00) +HISTORY16:41frmMain18:02frmMain/SampleProject/Sources/frmMain.tbform [line: undefined]Fri Jan 09 2026 18:02:51 GMT+0000 (Greenwich Mean Time) diff --git a/docs/IDE/Images/History_2.png b/docs/IDE/Images/History_2.png index a4df9f176..1d0c2de30 100644 Binary files a/docs/IDE/Images/History_2.png and b/docs/IDE/Images/History_2.png differ diff --git a/docs/IDE/Images/History_2.svg b/docs/IDE/Images/History_2.svg index 7d0fff54c..09f460786 100644 --- a/docs/IDE/Images/History_2.svg +++ b/docs/IDE/Images/History_2.svg @@ -1 +1 @@ -+ menuHISTORY16:41frmMain18:02frmMain/SampleProject/Sources/frmMain.tbform [line: undefined]Fri Jan 09 2026 18:02:51 GMT+0000 (GMT+00:00) ++ menuHISTORY16:41frmMain18:02frmMain/SampleProject/Sources/frmMain.tbform [line: undefined]Fri Jan 09 2026 18:02:51 GMT+0000 (Greenwich Mean Time) diff --git a/docs/IDE/Images/History_3.light.png b/docs/IDE/Images/History_3.light.png index f5abbc403..2172dfba3 100644 Binary files a/docs/IDE/Images/History_3.light.png and b/docs/IDE/Images/History_3.light.png differ diff --git a/docs/IDE/Images/History_3.light.svg b/docs/IDE/Images/History_3.light.svg index b5b3a1394..69df35fad 100644 --- a/docs/IDE/Images/History_3.light.svg +++ b/docs/IDE/Images/History_3.light.svg @@ -1 +1 @@ -HISTORY16:41frmMain18:02frmMain/SampleProject/Sources/frmMain.twin [line: 4]Fri Jan 09 2026 16:41:58 GMT+0000 (GMT+00:00) +HISTORY16:41frmMain18:02frmMain/SampleProject/Sources/frmMain.twin [line: 4]Fri Jan 09 2026 16:41:58 GMT+0000 (Greenwich Mean Time) diff --git a/docs/IDE/Images/History_3.png b/docs/IDE/Images/History_3.png index fc14b86d2..c07a6e7d0 100644 Binary files a/docs/IDE/Images/History_3.png and b/docs/IDE/Images/History_3.png differ diff --git a/docs/IDE/Images/History_3.svg b/docs/IDE/Images/History_3.svg index 7f43e539f..54e81d6a2 100644 --- a/docs/IDE/Images/History_3.svg +++ b/docs/IDE/Images/History_3.svg @@ -1 +1 @@ -+ menuHISTORY16:41frmMain18:02frmMain/SampleProject/Sources/frmMain.twin [line: 4]Fri Jan 09 2026 16:41:58 GMT+0000 (GMT+00:00) ++ menuHISTORY16:41frmMain18:02frmMain/SampleProject/Sources/frmMain.twin [line: 4]Fri Jan 09 2026 16:41:58 GMT+0000 (Greenwich Mean Time) diff --git a/docs/IDE/Images/IDE.light.png b/docs/IDE/Images/IDE.light.png index 0f2d138e0..43b5d8712 100644 Binary files a/docs/IDE/Images/IDE.light.png and b/docs/IDE/Images/IDE.light.png differ diff --git a/docs/IDE/Images/IDE.png b/docs/IDE/Images/IDE.png index 482046638..a834b258b 100644 Binary files a/docs/IDE/Images/IDE.png and b/docs/IDE/Images/IDE.png differ diff --git a/docs/IDE/Images/Memory.png b/docs/IDE/Images/Memory.png index ad730e58b..f06df4e8f 100644 Binary files a/docs/IDE/Images/Memory.png and b/docs/IDE/Images/Memory.png differ diff --git a/docs/IDE/Images/Memory_String.png b/docs/IDE/Images/Memory_String.png index 42aab1198..806539f2c 100644 Binary files a/docs/IDE/Images/Memory_String.png and b/docs/IDE/Images/Memory_String.png differ diff --git a/docs/IDE/Images/New_Project.light.png b/docs/IDE/Images/New_Project.light.png index 96f4784c8..13c1e9e97 100644 Binary files a/docs/IDE/Images/New_Project.light.png and b/docs/IDE/Images/New_Project.light.png differ diff --git a/docs/IDE/Images/New_Project.light.svg b/docs/IDE/Images/New_Project.light.svg index 611179918..0af03645d 100644 --- a/docs/IDE/Images/New_Project.light.svg +++ b/docs/IDE/Images/New_Project.light.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentStandard EXEActiveX ControlActiveX DLLStandard DLL(non-ActiveX)Standard EXE(Console App)Standard EXE (plusVBCCR v1.8)(experimental)Import from VBP...Import fromfolder... +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentStandard EXEActiveX ControlActiveX DLLStandard DLL(non-ActiveX)Standard EXE(Console App)Standard EXE (plusVBCCR v1.8)(experimental)Import from VBP...Import fromfolder... diff --git a/docs/IDE/Images/New_Project.png b/docs/IDE/Images/New_Project.png index 325842f44..3bd531e23 100644 Binary files a/docs/IDE/Images/New_Project.png and b/docs/IDE/Images/New_Project.png differ diff --git a/docs/IDE/Images/New_Project.svg b/docs/IDE/Images/New_Project.svg index 7f97cea15..500eba62d 100644 --- a/docs/IDE/Images/New_Project.svg +++ b/docs/IDE/Images/New_Project.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentStandard EXEActiveX ControlActiveX DLLStandard DLL(non-ActiveX)Standard EXE(Console App)Standard EXE (plusVBCCR v1.8)(experimental)Import from VBP...Import fromfolder... +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentStandard EXEActiveX ControlActiveX DLLStandard DLL(non-ActiveX)Standard EXE(Console App)Standard EXE (plusVBCCR v1.8)(experimental)Import from VBP...Import fromfolder... diff --git a/docs/IDE/Images/New_Project_Recent_1.light.png b/docs/IDE/Images/New_Project_Recent_1.light.png index 14762d0d2..6bc08531d 100644 Binary files a/docs/IDE/Images/New_Project_Recent_1.light.png and b/docs/IDE/Images/New_Project_Recent_1.light.png differ diff --git a/docs/IDE/Images/New_Project_Recent_1.light.svg b/docs/IDE/Images/New_Project_Recent_1.light.svg index fd7352c0c..dca346328 100644 --- a/docs/IDE/Images/New_Project_Recent_1.light.svg +++ b/docs/IDE/Images/New_Project_Recent_1.light.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecent +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecent diff --git a/docs/IDE/Images/New_Project_Recent_1.png b/docs/IDE/Images/New_Project_Recent_1.png index 7ca390683..6cb2ccf25 100644 Binary files a/docs/IDE/Images/New_Project_Recent_1.png and b/docs/IDE/Images/New_Project_Recent_1.png differ diff --git a/docs/IDE/Images/New_Project_Recent_1.svg b/docs/IDE/Images/New_Project_Recent_1.svg index eafa8329d..494f9fc6d 100644 --- a/docs/IDE/Images/New_Project_Recent_1.svg +++ b/docs/IDE/Images/New_Project_Recent_1.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecent +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecent diff --git a/docs/IDE/Images/New_Project_Recent_2.light.png b/docs/IDE/Images/New_Project_Recent_2.light.png index 176a3f13c..682229f6e 100644 Binary files a/docs/IDE/Images/New_Project_Recent_2.light.png and b/docs/IDE/Images/New_Project_Recent_2.light.png differ diff --git a/docs/IDE/Images/New_Project_Recent_2.light.svg b/docs/IDE/Images/New_Project_Recent_2.light.svg index 5f801743f..5fb766aef 100644 --- a/docs/IDE/Images/New_Project_Recent_2.light.svg +++ b/docs/IDE/Images/New_Project_Recent_2.light.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecent +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecent diff --git a/docs/IDE/Images/New_Project_Recent_2.png b/docs/IDE/Images/New_Project_Recent_2.png index 0440362a3..f7bc5a899 100644 Binary files a/docs/IDE/Images/New_Project_Recent_2.png and b/docs/IDE/Images/New_Project_Recent_2.png differ diff --git a/docs/IDE/Images/New_Project_Recent_2.svg b/docs/IDE/Images/New_Project_Recent_2.svg index d5b781176..f16f7ee1f 100644 --- a/docs/IDE/Images/New_Project_Recent_2.svg +++ b/docs/IDE/Images/New_Project_Recent_2.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecent +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecent diff --git a/docs/IDE/Images/New_Project_Samples.light.png b/docs/IDE/Images/New_Project_Samples.light.png index d6764f94b..a26babe31 100644 Binary files a/docs/IDE/Images/New_Project_Samples.light.png and b/docs/IDE/Images/New_Project_Samples.light.png differ diff --git a/docs/IDE/Images/New_Project_Samples.light.svg b/docs/IDE/Images/New_Project_Samples.light.svg index 6a7c6d187..ab9e0cca5 100644 --- a/docs/IDE/Images/New_Project_Samples.light.svg +++ b/docs/IDE/Images/New_Project_Samples.light.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentSample 0. Reports (Experimental)Sample 1. HelloWorldSample 1a. WebView2 ExamplesSample 1b. Chromium Embedded Framework ExamplesSample 2. GetIPAddressesSample 3. MyCodeLibrary +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentSample 0. Reports (Experimental)Sample 1. HelloWorldSample 1a. WebView2 ExamplesSample 1b. Chromium Embedded Framework ExamplesSample 2. GetIPAddressesSample 3. MyCodeLibrary diff --git a/docs/IDE/Images/New_Project_Samples.png b/docs/IDE/Images/New_Project_Samples.png index d6fe21932..44eac6304 100644 Binary files a/docs/IDE/Images/New_Project_Samples.png and b/docs/IDE/Images/New_Project_Samples.png differ diff --git a/docs/IDE/Images/New_Project_Samples.svg b/docs/IDE/Images/New_Project_Samples.svg index 396f2bb71..96190c79c 100644 --- a/docs/IDE/Images/New_Project_Samples.svg +++ b/docs/IDE/Images/New_Project_Samples.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentSample 0. Reports (Experimental)Sample 1. HelloWorldSample 1a. WebView2 ExamplesSample 1b. Chromium Embedded Framework ExamplesSample 2. GetIPAddressesSample 3. MyCodeLibrary +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentSample 0. Reports (Experimental)Sample 1. HelloWorldSample 1a. WebView2 ExamplesSample 1b. Chromium Embedded Framework ExamplesSample 2. GetIPAddressesSample 3. MyCodeLibrary diff --git a/docs/IDE/Images/OpenEditors_1.light.png b/docs/IDE/Images/OpenEditors_1.light.png index 7f85a0ccd..a54fafe2b 100644 Binary files a/docs/IDE/Images/OpenEditors_1.light.png and b/docs/IDE/Images/OpenEditors_1.light.png differ diff --git a/docs/IDE/Images/OpenEditors_1.png b/docs/IDE/Images/OpenEditors_1.png index 27e2ad184..4e3b350b1 100644 Binary files a/docs/IDE/Images/OpenEditors_1.png and b/docs/IDE/Images/OpenEditors_1.png differ diff --git a/docs/IDE/Images/Outline_1.png b/docs/IDE/Images/Outline_1.png index dbfc1539d..954791332 100644 Binary files a/docs/IDE/Images/Outline_1.png and b/docs/IDE/Images/Outline_1.png differ diff --git a/docs/IDE/Images/PackagePublishing.png b/docs/IDE/Images/PackagePublishing.png index 46be9c6cf..77012a91f 100644 Binary files a/docs/IDE/Images/PackagePublishing.png and b/docs/IDE/Images/PackagePublishing.png differ diff --git a/docs/IDE/Images/PackagePublishing_1.light.png b/docs/IDE/Images/PackagePublishing_1.light.png index a3cdde859..85b2f56bb 100644 Binary files a/docs/IDE/Images/PackagePublishing_1.light.png and b/docs/IDE/Images/PackagePublishing_1.light.png differ diff --git a/docs/IDE/Images/PackagePublishing_1.png b/docs/IDE/Images/PackagePublishing_1.png index 6dd21a525..dec630318 100644 Binary files a/docs/IDE/Images/PackagePublishing_1.png and b/docs/IDE/Images/PackagePublishing_1.png differ diff --git a/docs/IDE/Images/ProjectExplorer_Header.light.png b/docs/IDE/Images/ProjectExplorer_Header.light.png index 98eca93b5..a26cdf374 100644 Binary files a/docs/IDE/Images/ProjectExplorer_Header.light.png and b/docs/IDE/Images/ProjectExplorer_Header.light.png differ diff --git a/docs/IDE/Images/ProjectExplorer_Header.png b/docs/IDE/Images/ProjectExplorer_Header.png index e43d14a30..6b5cd8dc2 100644 Binary files a/docs/IDE/Images/ProjectExplorer_Header.png and b/docs/IDE/Images/ProjectExplorer_Header.png differ diff --git a/docs/IDE/Images/ProjectExplorer_Sample.light.png b/docs/IDE/Images/ProjectExplorer_Sample.light.png index 1b7ee4ba8..90441b94a 100644 Binary files a/docs/IDE/Images/ProjectExplorer_Sample.light.png and b/docs/IDE/Images/ProjectExplorer_Sample.light.png differ diff --git a/docs/IDE/Images/ProjectExplorer_Sample.png b/docs/IDE/Images/ProjectExplorer_Sample.png index 55f9544ea..b35df91b6 100644 Binary files a/docs/IDE/Images/ProjectExplorer_Sample.png and b/docs/IDE/Images/ProjectExplorer_Sample.png differ diff --git a/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.light.png b/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.light.png index 2125a3621..1f5d65824 100644 Binary files a/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.light.png and b/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.light.png differ diff --git a/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.light.svg b/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.light.svg index e6f6ac67d..ad618b1ff 100644 --- a/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.light.svg +++ b/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.light.svg @@ -1 +1 @@ -EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsCancelLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectImport from file..................................................................ABBYY FineReader 16 SharePoint Integration Component16.2026AccessibilityCplAdmin 1.0 Type Library1.0Acrobat1.0Acrobat Access 3.0 Type Library3.0AcroBrokerLib1.0Active DS Type Library1.0Active Messaging Object Library1.1ActiveMovie control type library1.0ActiveX DLL to perform Migration of MS Repository V1 to V211.0AddinLoaderLib1.0Adobe Acrobat 1.0 WebView Proxy Type Library1.0Adobe Acrobat 10.0 Type Library1.1Adobe Acrobat Browser Control Type Library 1.01.0Adobe Acrobat File Preview Type Library1.0AFormAut 1.0 Type Library1.0AgentWmiLib1.0AirplaneMode Interfaces1.0AP Client 1.0 HelpPane Type Library1.0AP Client 1.0 Type Library1.0AppIdPolicyEngineApi 1.0 Type Library1.0Apple Bonjour Library 1.01.0Library SymbolVersionPublisherproject.referencesApply Changes +EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsCancelLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectImport from file..................................................................ABBYY FineReader 16 SharePoint Integration Component16.2026AccessibilityCplAdmin 1.0 Type Library1.0Acrobat1.0Acrobat Access 3.0 Type Library3.0AcroBrokerLib1.0Active DS Type Library1.0Active Messaging Object Library1.1ActiveMovie control type library1.0ActiveX DLL to perform Migration of MS Repository V1 to V211.0AddinLoaderLib1.0Adobe Acrobat 1.0 WebView Proxy Type Library1.0Adobe Acrobat 10.0 Type Library1.1Adobe Acrobat Browser Control Type Library 1.01.0Adobe Acrobat File Preview Type Library1.0AFormAut 1.0 Type Library1.0AgentWmiLib1.0AirplaneMode Interfaces1.0AP Client 1.0 HelpPane Type Library1.0AP Client 1.0 Type Library1.0AppIdPolicyEngineApi 1.0 Type Library1.0Apple Bonjour Library 1.01.0Library SymbolVersionPublisherproject.referencesApply Changes diff --git a/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.svg b/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.svg index 891b03f2d..eebf754fe 100644 --- a/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.svg +++ b/docs/IDE/Images/ProjectSettings_AvailableCOMReferences.svg @@ -1 +1 @@ -win32100%EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsCancelLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectImport from file..................................................................ABBYY FineReader 16 SharePoint Integration Component16.2026AccessibilityCplAdmin 1.0 Type Library1.0Acrobat1.0Acrobat Access 3.0 Type Library3.0AcroBrokerLib1.0Active DS Type Library1.0Active Messaging Object Library1.1ActiveMovie control type library1.0ActiveX DLL to perform Migration of MS Repository V1 to V211.0AddinLoaderLib1.0Adobe Acrobat 1.0 WebView Proxy Type Library1.0Adobe Acrobat 10.0 Type Library1.1Adobe Acrobat Browser Control Type Library 1.01.0Adobe Acrobat File Preview Type Library1.0AFormAut 1.0 Type Library1.0AgentWmiLib1.0AirplaneMode Interfaces1.0AP Client 1.0 HelpPane Type Library1.0AP Client 1.0 Type Library1.0AppIdPolicyEngineApi 1.0 Type Library1.0Apple Bonjour Library 1.01.0Library SymbolVersionPublisherproject.referencesApply Changes +win32100%EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsCancelLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectImport from file..................................................................ABBYY FineReader 16 SharePoint Integration Component16.2026AccessibilityCplAdmin 1.0 Type Library1.0Acrobat1.0Acrobat Access 3.0 Type Library3.0AcroBrokerLib1.0Active DS Type Library1.0Active Messaging Object Library1.1ActiveMovie control type library1.0ActiveX DLL to perform Migration of MS Repository V1 to V211.0AddinLoaderLib1.0Adobe Acrobat 1.0 WebView Proxy Type Library1.0Adobe Acrobat 10.0 Type Library1.1Adobe Acrobat Browser Control Type Library 1.01.0Adobe Acrobat File Preview Type Library1.0AFormAut 1.0 Type Library1.0AgentWmiLib1.0AirplaneMode Interfaces1.0AP Client 1.0 HelpPane Type Library1.0AP Client 1.0 Type Library1.0AppIdPolicyEngineApi 1.0 Type Library1.0Apple Bonjour Library 1.01.0Library SymbolVersionPublisherproject.referencesApply Changes diff --git a/docs/IDE/Images/ProjectSettings_LibraryReferences.light.png b/docs/IDE/Images/ProjectSettings_LibraryReferences.light.png index d61cfb5ef..b8c40c4c6 100644 Binary files a/docs/IDE/Images/ProjectSettings_LibraryReferences.light.png and b/docs/IDE/Images/ProjectSettings_LibraryReferences.light.png differ diff --git a/docs/IDE/Images/ProjectSettings_LibraryReferences.light.svg b/docs/IDE/Images/ProjectSettings_LibraryReferences.light.svg index 56ac47fde..48cf2a8dd 100644 --- a/docs/IDE/Images/ProjectSettings_LibraryReferences.light.svg +++ b/docs/IDE/Images/ProjectSettings_LibraryReferences.light.svg @@ -1 +1 @@ -EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsCancelLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectImport from file...VBAVBRUNstdoletbIDEtwinBASIC - VBA Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VBRUN Compatibility Package0.0.0.1[BUILT-IN]OLE Automation2.0twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN]🖉🖉🖉🖉Library SymbolNamein order of priorityVersionPublisherproject.referencesApply Changes +EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsCancelLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectImport from file...VBAVBRUNstdoletbIDEtwinBASIC - VBA Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VBRUN Compatibility Package0.0.0.1[BUILT-IN]OLE Automation2.0twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN]🖉🖉🖉🖉Library SymbolNamein order of priorityVersionPublisherproject.referencesApply Changes diff --git a/docs/IDE/Images/ProjectSettings_LibraryReferences.svg b/docs/IDE/Images/ProjectSettings_LibraryReferences.svg index 268d0479e..3a69f50c7 100644 --- a/docs/IDE/Images/ProjectSettings_LibraryReferences.svg +++ b/docs/IDE/Images/ProjectSettings_LibraryReferences.svg @@ -1 +1 @@ -win32100%EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsCancelLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectImport from file...VBAVBRUNstdoletbIDEtwinBASIC - VBA Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VBRUN Compatibility Package0.0.0.1[BUILT-IN]OLE Automation2.0twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN]🖉🖉🖉🖉Library SymbolNamein order of priorityVersionPublisherproject.referencesApply Changes +win32100%EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsCancelLibrary ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesSelect references that will be used during compilation of this projectImport from file...VBAVBRUNstdoletbIDEtwinBASIC - VBA Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VBRUN Compatibility Package0.0.0.1[BUILT-IN]OLE Automation2.0twinBASIC - IDE Extensibility Package0.0.0.1[BUILT-IN]🖉🖉🖉🖉Library SymbolNamein order of priorityVersionPublisherproject.referencesApply Changes diff --git a/docs/IDE/Images/RightClick-Add-CustomControlsForm-Popup.light.png b/docs/IDE/Images/RightClick-Add-CustomControlsForm-Popup.light.png index eb762e9a7..e0fa096ff 100644 Binary files a/docs/IDE/Images/RightClick-Add-CustomControlsForm-Popup.light.png and b/docs/IDE/Images/RightClick-Add-CustomControlsForm-Popup.light.png differ diff --git a/docs/IDE/Images/RightClick-Add-CustomControlsForm-Popup.png b/docs/IDE/Images/RightClick-Add-CustomControlsForm-Popup.png index 0acf09db9..dc8a711e7 100644 Binary files a/docs/IDE/Images/RightClick-Add-CustomControlsForm-Popup.png and b/docs/IDE/Images/RightClick-Add-CustomControlsForm-Popup.png differ diff --git a/docs/IDE/Images/Services_Operational.light.png b/docs/IDE/Images/Services_Operational.light.png index 7b6510513..258c489db 100644 Binary files a/docs/IDE/Images/Services_Operational.light.png and b/docs/IDE/Images/Services_Operational.light.png differ diff --git a/docs/IDE/Images/Services_Operational.png b/docs/IDE/Images/Services_Operational.png index 0fef3d7e1..bd023ef32 100644 Binary files a/docs/IDE/Images/Services_Operational.png and b/docs/IDE/Images/Services_Operational.png differ diff --git a/docs/IDE/Images/Services_Operational_Tooltip.png b/docs/IDE/Images/Services_Operational_Tooltip.png index cf529a4a2..58ec8bf6c 100644 Binary files a/docs/IDE/Images/Services_Operational_Tooltip.png and b/docs/IDE/Images/Services_Operational_Tooltip.png differ diff --git a/docs/IDE/Images/Services_Unavailable_Tooltip.png b/docs/IDE/Images/Services_Unavailable_Tooltip.png index 23f79dfbc..a7479df77 100644 Binary files a/docs/IDE/Images/Services_Unavailable_Tooltip.png and b/docs/IDE/Images/Services_Unavailable_Tooltip.png differ diff --git a/docs/IDE/Images/Settings.light.png b/docs/IDE/Images/Settings.light.png index 384ca6d19..d4cadf21e 100644 Binary files a/docs/IDE/Images/Settings.light.png and b/docs/IDE/Images/Settings.light.png differ diff --git a/docs/IDE/Images/Settings.png b/docs/IDE/Images/Settings.png index 1cf170573..a414f0659 100644 Binary files a/docs/IDE/Images/Settings.png and b/docs/IDE/Images/Settings.png differ diff --git a/docs/IDE/Images/Splash_Screen.light.png b/docs/IDE/Images/Splash_Screen.light.png index 96f0d6834..5772eb5c4 100644 Binary files a/docs/IDE/Images/Splash_Screen.light.png and b/docs/IDE/Images/Splash_Screen.light.png differ diff --git a/docs/IDE/Images/Splash_Screen.png b/docs/IDE/Images/Splash_Screen.png index 9fd9eee4c..c5cf6c430 100644 Binary files a/docs/IDE/Images/Splash_Screen.png and b/docs/IDE/Images/Splash_Screen.png differ diff --git a/docs/IDE/Images/StatusBar.png b/docs/IDE/Images/StatusBar.png index c99f78d0f..696dff685 100644 Binary files a/docs/IDE/Images/StatusBar.png and b/docs/IDE/Images/StatusBar.png differ diff --git a/docs/IDE/Images/Toggle.light.png b/docs/IDE/Images/Toggle.light.png index d8951cada..30595a465 100644 Binary files a/docs/IDE/Images/Toggle.light.png and b/docs/IDE/Images/Toggle.light.png differ diff --git a/docs/IDE/Images/Toggle.png b/docs/IDE/Images/Toggle.png index 7c9799f3c..c06922067 100644 Binary files a/docs/IDE/Images/Toggle.png and b/docs/IDE/Images/Toggle.png differ diff --git a/docs/IDE/Images/Toolbar_1.light.png b/docs/IDE/Images/Toolbar_1.light.png index 53f0ca3f4..0a048cb68 100644 Binary files a/docs/IDE/Images/Toolbar_1.light.png and b/docs/IDE/Images/Toolbar_1.light.png differ diff --git a/docs/IDE/Images/Toolbar_1.png b/docs/IDE/Images/Toolbar_1.png index 47c4bf688..a08c7e26e 100644 Binary files a/docs/IDE/Images/Toolbar_1.png and b/docs/IDE/Images/Toolbar_1.png differ diff --git a/docs/IDE/Images/Toolbar_2.light.png b/docs/IDE/Images/Toolbar_2.light.png index 5f7ba4ceb..e911a8029 100644 Binary files a/docs/IDE/Images/Toolbar_2.light.png and b/docs/IDE/Images/Toolbar_2.light.png differ diff --git a/docs/IDE/Images/Toolbar_2.png b/docs/IDE/Images/Toolbar_2.png index 46a9ed6b0..f56d70d3a 100644 Binary files a/docs/IDE/Images/Toolbar_2.png and b/docs/IDE/Images/Toolbar_2.png differ diff --git a/docs/IDE/Images/Toolbar_3.light.png b/docs/IDE/Images/Toolbar_3.light.png index 70f0e6d68..f8c870207 100644 Binary files a/docs/IDE/Images/Toolbar_3.light.png and b/docs/IDE/Images/Toolbar_3.light.png differ diff --git a/docs/IDE/Images/Toolbar_3.png b/docs/IDE/Images/Toolbar_3.png index 7d27df43b..0f06729ac 100644 Binary files a/docs/IDE/Images/Toolbar_3.png and b/docs/IDE/Images/Toolbar_3.png differ diff --git a/docs/IDE/Images/Toolbar_4.light.png b/docs/IDE/Images/Toolbar_4.light.png index 702d3c448..f0f5394b8 100644 Binary files a/docs/IDE/Images/Toolbar_4.light.png and b/docs/IDE/Images/Toolbar_4.light.png differ diff --git a/docs/IDE/Images/Toolbar_4.png b/docs/IDE/Images/Toolbar_4.png index 137e43943..ea1f12b9b 100644 Binary files a/docs/IDE/Images/Toolbar_4.png and b/docs/IDE/Images/Toolbar_4.png differ diff --git a/docs/IDE/Images/Toolbox_MoreComponents.light.png b/docs/IDE/Images/Toolbox_MoreComponents.light.png index 03e05d05d..4cfe2b997 100644 Binary files a/docs/IDE/Images/Toolbox_MoreComponents.light.png and b/docs/IDE/Images/Toolbox_MoreComponents.light.png differ diff --git a/docs/IDE/Images/Toolbox_MoreComponents.png b/docs/IDE/Images/Toolbox_MoreComponents.png index 4b9937d44..f9d652ec7 100644 Binary files a/docs/IDE/Images/Toolbox_MoreComponents.png and b/docs/IDE/Images/Toolbox_MoreComponents.png differ diff --git a/docs/IDE/Images/Toolbox_Report.light.png b/docs/IDE/Images/Toolbox_Report.light.png index ba847c7d8..1185c1129 100644 Binary files a/docs/IDE/Images/Toolbox_Report.light.png and b/docs/IDE/Images/Toolbox_Report.light.png differ diff --git a/docs/IDE/Images/Toolbox_Report.png b/docs/IDE/Images/Toolbox_Report.png index 4d9c5701e..c0662b80f 100644 Binary files a/docs/IDE/Images/Toolbox_Report.png and b/docs/IDE/Images/Toolbox_Report.png differ diff --git a/docs/IDE/Images/Watches_1.light.png b/docs/IDE/Images/Watches_1.light.png index 882508c7b..a28851f63 100644 Binary files a/docs/IDE/Images/Watches_1.light.png and b/docs/IDE/Images/Watches_1.light.png differ diff --git a/docs/IDE/Images/Watches_1.png b/docs/IDE/Images/Watches_1.png index 208c0f740..af7f6ecf1 100644 Binary files a/docs/IDE/Images/Watches_1.png and b/docs/IDE/Images/Watches_1.png differ diff --git a/docs/IDE/Images/Watches_2.light.png b/docs/IDE/Images/Watches_2.light.png index e6c106247..9daff5d47 100644 Binary files a/docs/IDE/Images/Watches_2.light.png and b/docs/IDE/Images/Watches_2.light.png differ diff --git a/docs/IDE/Images/Watches_2.png b/docs/IDE/Images/Watches_2.png index f6a8c1231..b538f5e69 100644 Binary files a/docs/IDE/Images/Watches_2.png and b/docs/IDE/Images/Watches_2.png differ diff --git a/docs/IDE/Images/Webpage.light.png b/docs/IDE/Images/Webpage.light.png index 721197301..cec3c73a8 100644 Binary files a/docs/IDE/Images/Webpage.light.png and b/docs/IDE/Images/Webpage.light.png differ diff --git a/docs/IDE/Images/Webpage.png b/docs/IDE/Images/Webpage.png index 6bec0c763..516090ac5 100644 Binary files a/docs/IDE/Images/Webpage.png and b/docs/IDE/Images/Webpage.png differ diff --git a/docs/IDE/Images/project settings description text.svg b/docs/IDE/Images/project settings description text.svg index 52334a2d9..d96622595 100644 --- a/docs/IDE/Images/project settings description text.svg +++ b/docs/IDE/Images/project settings description text.svg @@ -1 +1 @@ -Option Explicit OnThis option takes effect if Option Explicit On/Off is not specified in the source fileYes +Option Explicit OnThis option takes effect if Option Explicit On/Off is not specified in the source fileYes diff --git a/docs/IDE/Images/tB-Blue.light.png b/docs/IDE/Images/tB-Blue.light.png index 4f32ef13f..47aa4d3dc 100644 Binary files a/docs/IDE/Images/tB-Blue.light.png and b/docs/IDE/Images/tB-Blue.light.png differ diff --git a/docs/IDE/Images/tB-Blue.png b/docs/IDE/Images/tB-Blue.png index 257b1e9bc..0d4e102f9 100644 Binary files a/docs/IDE/Images/tB-Blue.png and b/docs/IDE/Images/tB-Blue.png differ diff --git a/docs/IDE/Images/tB-Green.light.png b/docs/IDE/Images/tB-Green.light.png index ff898a226..215fddad6 100644 Binary files a/docs/IDE/Images/tB-Green.light.png and b/docs/IDE/Images/tB-Green.light.png differ diff --git a/docs/IDE/Images/tB-Green.png b/docs/IDE/Images/tB-Green.png index 72ba7abbd..9ec317d5d 100644 Binary files a/docs/IDE/Images/tB-Green.png and b/docs/IDE/Images/tB-Green.png differ diff --git a/docs/IDE/Images/tB-Orange.light.png b/docs/IDE/Images/tB-Orange.light.png index 1eb7fe3aa..fafb3c431 100644 Binary files a/docs/IDE/Images/tB-Orange.light.png and b/docs/IDE/Images/tB-Orange.light.png differ diff --git a/docs/IDE/Images/tB-Orange.png b/docs/IDE/Images/tB-Orange.png index 62e06ca6b..cae282013 100644 Binary files a/docs/IDE/Images/tB-Orange.png and b/docs/IDE/Images/tB-Orange.png differ diff --git a/docs/IDE/Images/tB-Red.light.png b/docs/IDE/Images/tB-Red.light.png index 9cd30c811..8dbfa5c00 100644 Binary files a/docs/IDE/Images/tB-Red.light.png and b/docs/IDE/Images/tB-Red.light.png differ diff --git a/docs/IDE/Images/tB-Red.png b/docs/IDE/Images/tB-Red.png index aa6fa9a0c..f264e3b7b 100644 Binary files a/docs/IDE/Images/tB-Red.png and b/docs/IDE/Images/tB-Red.png differ diff --git a/docs/IDE/Images/tbForm.light.png b/docs/IDE/Images/tbForm.light.png index 5b643f49a..24509e752 100644 Binary files a/docs/IDE/Images/tbForm.light.png and b/docs/IDE/Images/tbForm.light.png differ diff --git a/docs/IDE/Images/tbForm.png b/docs/IDE/Images/tbForm.png index bade96c8d..01ff199b6 100644 Binary files a/docs/IDE/Images/tbForm.png and b/docs/IDE/Images/tbForm.png differ diff --git a/docs/IDE/Images/tbReport.light.png b/docs/IDE/Images/tbReport.light.png index a7b598232..22f545057 100644 Binary files a/docs/IDE/Images/tbReport.light.png and b/docs/IDE/Images/tbReport.light.png differ diff --git a/docs/IDE/Images/tbReport.png b/docs/IDE/Images/tbReport.png index 736d4dd79..33690f8a0 100644 Binary files a/docs/IDE/Images/tbReport.png and b/docs/IDE/Images/tbReport.png differ diff --git a/docs/IDE/Menu/Images/Menu.png b/docs/IDE/Menu/Images/Menu.png index f523f5687..f34c67293 100644 Binary files a/docs/IDE/Menu/Images/Menu.png and b/docs/IDE/Menu/Images/Menu.png differ diff --git a/docs/IDE/Menu/Images/Menu_Add-Ins.light.png b/docs/IDE/Menu/Images/Menu_Add-Ins.light.png index f27be0657..2520e0246 100644 Binary files a/docs/IDE/Menu/Images/Menu_Add-Ins.light.png and b/docs/IDE/Menu/Images/Menu_Add-Ins.light.png differ diff --git a/docs/IDE/Menu/Images/Menu_Add-Ins.png b/docs/IDE/Menu/Images/Menu_Add-Ins.png index 9898da8ed..1d05082f4 100644 Binary files a/docs/IDE/Menu/Images/Menu_Add-Ins.png and b/docs/IDE/Menu/Images/Menu_Add-Ins.png differ diff --git a/docs/IDE/Menu/Images/Menu_Add-Ins_GlobalSearch.light.png b/docs/IDE/Menu/Images/Menu_Add-Ins_GlobalSearch.light.png index b7351a31c..329e942e6 100644 Binary files a/docs/IDE/Menu/Images/Menu_Add-Ins_GlobalSearch.light.png and b/docs/IDE/Menu/Images/Menu_Add-Ins_GlobalSearch.light.png differ diff --git a/docs/IDE/Menu/Images/Menu_Add-Ins_GlobalSearch.png b/docs/IDE/Menu/Images/Menu_Add-Ins_GlobalSearch.png index 992289854..6b3007828 100644 Binary files a/docs/IDE/Menu/Images/Menu_Add-Ins_GlobalSearch.png and b/docs/IDE/Menu/Images/Menu_Add-Ins_GlobalSearch.png differ diff --git a/docs/IDE/Menu/Images/Menu_Debug_DebuggerOptions.light.png b/docs/IDE/Menu/Images/Menu_Debug_DebuggerOptions.light.png index b9d66daeb..32d56a13b 100644 Binary files a/docs/IDE/Menu/Images/Menu_Debug_DebuggerOptions.light.png and b/docs/IDE/Menu/Images/Menu_Debug_DebuggerOptions.light.png differ diff --git a/docs/IDE/Menu/Images/Menu_Debug_DebuggerOptions.png b/docs/IDE/Menu/Images/Menu_Debug_DebuggerOptions.png index 7f18721a4..b3ea8eaac 100644 Binary files a/docs/IDE/Menu/Images/Menu_Debug_DebuggerOptions.png and b/docs/IDE/Menu/Images/Menu_Debug_DebuggerOptions.png differ diff --git a/docs/IDE/Menu/Images/Menu_Edit.png b/docs/IDE/Menu/Images/Menu_Edit.png index 8ef053ef1..c4d65ff6b 100644 Binary files a/docs/IDE/Menu/Images/Menu_Edit.png and b/docs/IDE/Menu/Images/Menu_Edit.png differ diff --git a/docs/IDE/Menu/Images/Menu_File.light.png b/docs/IDE/Menu/Images/Menu_File.light.png index 28d4627f0..9d00146a9 100644 Binary files a/docs/IDE/Menu/Images/Menu_File.light.png and b/docs/IDE/Menu/Images/Menu_File.light.png differ diff --git a/docs/IDE/Menu/Images/Menu_File.png b/docs/IDE/Menu/Images/Menu_File.png index d3ccfc081..5325f2509 100644 Binary files a/docs/IDE/Menu/Images/Menu_File.png and b/docs/IDE/Menu/Images/Menu_File.png differ diff --git a/docs/IDE/Menu/Images/Menu_Format.light.png b/docs/IDE/Menu/Images/Menu_Format.light.png index 0ff9c5528..b2c7e63e8 100644 Binary files a/docs/IDE/Menu/Images/Menu_Format.light.png and b/docs/IDE/Menu/Images/Menu_Format.light.png differ diff --git a/docs/IDE/Menu/Images/Menu_Format.png b/docs/IDE/Menu/Images/Menu_Format.png index bbc856a97..d6be785cd 100644 Binary files a/docs/IDE/Menu/Images/Menu_Format.png and b/docs/IDE/Menu/Images/Menu_Format.png differ diff --git a/docs/IDE/Menu/Images/Menu_Help_About.light.png b/docs/IDE/Menu/Images/Menu_Help_About.light.png index d745dd19f..8d50b59ab 100644 Binary files a/docs/IDE/Menu/Images/Menu_Help_About.light.png and b/docs/IDE/Menu/Images/Menu_Help_About.light.png differ diff --git a/docs/IDE/Menu/Images/Menu_Help_About.light.svg b/docs/IDE/Menu/Images/Menu_Help_About.light.svg index 31a3e9c00..ba401498b 100644 --- a/docs/IDE/Menu/Images/Menu_Help_About.light.svg +++ b/docs/IDE/Menu/Images/Menu_Help_About.light.svg @@ -1 +1 @@ -Add-InsWindowHelpproject.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32Inventory(general)(declaration)NewCollection"Widget""Sprocket""Gasket"ObjectCreateObject("Scripting.Dictionary")"Widget",4.5"Sprocket",12"Gasket",0.75VariantInnamesitem,prices(item)"Total: "&TotalPrice(prices),vbInformation[Description("Adds up the prices held in a Dictionary.")]TotalPrice(ByValpricesAsObject)AsDoubleVariantDoubleprices.KeysDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLESAbout twinBASIC...Closeversion: twinBASIC IDE BETA 1005© 2026 TWINBASIC LTDIn the development of twinBASIC, the essence of community support has been thecornerstone of our progress and success. This project thrives not just on code andtechnology, but on the invaluable contributions, insights, and feedback provided by adiverse and active community of developers, users, and enthusiasts.SPECIAL THANKS: ... coming soon :)VIP Gold SupportersSee your logo here!Become a VIP Gold supporterSee your logo here!Become a VIP Gold supporterPortions of this software utilize third-party open-source libraries. Namely:MONACO - CODE EDITOR (see file ide\licences\monaco.txt)CODICON - ICONS (see file ide\licences\codicon.txt)LLVM - OPTIMIZING BACKEND COMPILER (see file ide\licences\llvm.txt)LODEPNG - PNG DECODER (see file ide\licences\lodepng.txt)SPECTRUM - JS COLOR PICKER (see file ide\licences\spectrum.txt)GRAPICK - JS GRADIENT PICKER (see file ide\licences\grapick.txt)CHARTJS - JS CHARTS (see file ide\licences\chartjs.txt)JQUERY - JS HELPER (see file ide\licences\jquery.txt)VBQRCODEGEN - QRCODE library by wqweto (see file ide\licences\VbQRCodegen.txt)LZ4 - LZ4 COMPRESSION LIBRARY (see file ide\licences\lz4.txt)LICENCE: ULTIMATE EDITION +Add-InsWindowHelpproject.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32Inventory(general)(declaration)NewCollection"Widget""Sprocket""Gasket"ObjectCreateObject("Scripting.Dictionary")"Widget",4.5"Sprocket",12"Gasket",0.75VariantInnamesitem,prices(item)"Total: "&TotalPrice(prices),vbInformation[Description("Adds up the prices held in a Dictionary.")]TotalPrice(ByValpricesAsObject)AsDoubleVariantDoubleprices.KeysDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESAbout twinBASIC...Closeversion: twinBASIC IDE BETA 1010© 2026 TWINBASIC LTDIn the development of twinBASIC, the essence of community support has been thecornerstone of our progress and success. This project thrives not just on code andtechnology, but on the invaluable contributions, insights, and feedback provided by adiverse and active community of developers, users, and enthusiasts.SPECIAL THANKS: ... coming soon :)VIP Gold SupportersSee your logo here!Become a VIP Gold supporterSee your logo here!Become a VIP Gold supporterPortions of this software utilize third-party open-source libraries. Namely:MONACO - CODE EDITOR (see file ide\licences\monaco.txt)CODICON - ICONS (see file ide\licences\codicon.txt)LLVM - OPTIMIZING BACKEND COMPILER (see file ide\licences\llvm.txt)LODEPNG - PNG DECODER (see file ide\licences\lodepng.txt)SPECTRUM - JS COLOR PICKER (see file ide\licences\spectrum.txt)GRAPICK - JS GRADIENT PICKER (see file ide\licences\grapick.txt)CHARTJS - JS CHARTS (see file ide\licences\chartjs.txt)JQUERY - JS HELPER (see file ide\licences\jquery.txt)VBQRCODEGEN - QRCODE library by wqweto (see file ide\licences\VbQRCodegen.txt)LZ4 - LZ4 COMPRESSION LIBRARY (see file ide\licences\lz4.txt)LICENCE: ULTIMATE EDITION diff --git a/docs/IDE/Menu/Images/Menu_Help_About.png b/docs/IDE/Menu/Images/Menu_Help_About.png index e0509c6a9..5fb371469 100644 Binary files a/docs/IDE/Menu/Images/Menu_Help_About.png and b/docs/IDE/Menu/Images/Menu_Help_About.png differ diff --git a/docs/IDE/Menu/Images/Menu_Help_About.svg b/docs/IDE/Menu/Images/Menu_Help_About.svg index fe806fd99..fdab1617c 100644 --- a/docs/IDE/Menu/Images/Menu_Help_About.svg +++ b/docs/IDE/Menu/Images/Menu_Help_About.svg @@ -1 +1 @@ -Add-InsWindowHelpproject.twinproj - twinBASIC (twinBASIC IDE BETA 1005)Inventory(general)(declaration)Collection"Widget""Sprocket""Gasket"ObjectCreateObject("Scripting.Dictionary")"Widget",4.5"Sprocket",12"Gasket",0.75Variantnamesitem,prices(item)&TotalPrice(prices),vbInformation[Description("Adds up the prices held in a Dictionary.")]TotalPrice(ByValpricesAsObject)AsDoubleVariantDoubleprices.KeysDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLESAbout twinBASIC...Closeversion: twinBASIC IDE BETA 1005© 2026 TWINBASIC LTDIn the development of twinBASIC, the essence of community support has been thecornerstone of our progress and success. This project thrives not just on code andtechnology, but on the invaluable contributions, insights, and feedback provided by adiverse and active community of developers, users, and enthusiasts.SPECIAL THANKS: ... coming soon :)VIP Gold SupportersSee your logo here!Become a VIP Gold supporterSee your logo here!Become a VIP Gold supporterPortions of this software utilize third-party open-source libraries. Namely:MONACO - CODE EDITOR (see file ide\licences\monaco.txt)CODICON - ICONS (see file ide\licences\codicon.txt)LLVM - OPTIMIZING BACKEND COMPILER (see file ide\licences\llvm.txt)LODEPNG - PNG DECODER (see file ide\licences\lodepng.txt)SPECTRUM - JS COLOR PICKER (see file ide\licences\spectrum.txt)GRAPICK - JS GRADIENT PICKER (see file ide\licences\grapick.txt)CHARTJS - JS CHARTS (see file ide\licences\chartjs.txt)JQUERY - JS HELPER (see file ide\licences\jquery.txt)VBQRCODEGEN - QRCODE library by wqweto (see file ide\licences\VbQRCodegen.txt)LZ4 - LZ4 COMPRESSION LIBRARY (see file ide\licences\lz4.txt)LICENCE: ULTIMATE EDITION +Add-InsWindowHelpproject.twinproj - twinBASIC (twinBASIC IDE BETA 1010)Inventory(general)(declaration)Collection"Widget""Sprocket""Gasket"ObjectCreateObject("Scripting.Dictionary")"Widget",4.5"Sprocket",12"Gasket",0.75Variantnamesitem,prices(item)&TotalPrice(prices),vbInformation[Description("Adds up the prices held in a Dictionary.")]TotalPrice(ByValpricesAsObject)AsDoubleVariantDoubleprices.KeysDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESAbout twinBASIC...Closeversion: twinBASIC IDE BETA 1010© 2026 TWINBASIC LTDIn the development of twinBASIC, the essence of community support has been thecornerstone of our progress and success. This project thrives not just on code andtechnology, but on the invaluable contributions, insights, and feedback provided by adiverse and active community of developers, users, and enthusiasts.SPECIAL THANKS: ... coming soon :)VIP Gold SupportersSee your logo here!Become a VIP Gold supporterSee your logo here!Become a VIP Gold supporterPortions of this software utilize third-party open-source libraries. Namely:MONACO - CODE EDITOR (see file ide\licences\monaco.txt)CODICON - ICONS (see file ide\licences\codicon.txt)LLVM - OPTIMIZING BACKEND COMPILER (see file ide\licences\llvm.txt)LODEPNG - PNG DECODER (see file ide\licences\lodepng.txt)SPECTRUM - JS COLOR PICKER (see file ide\licences\spectrum.txt)GRAPICK - JS GRADIENT PICKER (see file ide\licences\grapick.txt)CHARTJS - JS CHARTS (see file ide\licences\chartjs.txt)JQUERY - JS HELPER (see file ide\licences\jquery.txt)VBQRCODEGEN - QRCODE library by wqweto (see file ide\licences\VbQRCodegen.txt)LZ4 - LZ4 COMPRESSION LIBRARY (see file ide\licences\lz4.txt)LICENCE: ULTIMATE EDITION diff --git a/docs/IDE/Menu/Images/Menu_Project.light.png b/docs/IDE/Menu/Images/Menu_Project.light.png index f8c16d308..328fa5eae 100644 Binary files a/docs/IDE/Menu/Images/Menu_Project.light.png and b/docs/IDE/Menu/Images/Menu_Project.light.png differ diff --git a/docs/IDE/Menu/Images/Menu_Project.png b/docs/IDE/Menu/Images/Menu_Project.png index 976254cf4..994e52af0 100644 Binary files a/docs/IDE/Menu/Images/Menu_Project.png and b/docs/IDE/Menu/Images/Menu_Project.png differ diff --git a/docs/IDE/Menu/Images/Menu_Run.light.png b/docs/IDE/Menu/Images/Menu_Run.light.png index af93c3119..70a3db055 100644 Binary files a/docs/IDE/Menu/Images/Menu_Run.light.png and b/docs/IDE/Menu/Images/Menu_Run.light.png differ diff --git a/docs/IDE/Menu/Images/Menu_Run.png b/docs/IDE/Menu/Images/Menu_Run.png index 906c9758d..b04d2bbfb 100644 Binary files a/docs/IDE/Menu/Images/Menu_Run.png and b/docs/IDE/Menu/Images/Menu_Run.png differ diff --git a/docs/IDE/Menu/Images/Menu_Tools.light.png b/docs/IDE/Menu/Images/Menu_Tools.light.png index 9e26e9a04..a67a90055 100644 Binary files a/docs/IDE/Menu/Images/Menu_Tools.light.png and b/docs/IDE/Menu/Images/Menu_Tools.light.png differ diff --git a/docs/IDE/Menu/Images/Menu_Tools.png b/docs/IDE/Menu/Images/Menu_Tools.png index 16d34d47b..cb95cf39b 100644 Binary files a/docs/IDE/Menu/Images/Menu_Tools.png and b/docs/IDE/Menu/Images/Menu_Tools.png differ diff --git a/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.light.png b/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.light.png index 3d5d689c4..aa3e872d7 100644 Binary files a/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.light.png and b/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.light.png differ diff --git a/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.light.svg b/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.light.svg index f4fb0d9e9..a9fafe6e7 100644 --- a/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.light.svg +++ b/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.light.svg @@ -1 +1 @@ -Inventory(general)(declaration)InventoryMain()namesAsNewCollectionAdd"Widget"Add"Sprocket"Add"Gasket"pricesAsObjectprices=CreateObject("Scripting.Dictionary")Add"Widget",4.5Add"Sprocket",12Add"Gasket",0.75itemAsVariantEachitemInnamesDebug.Printitem,prices(item)"Total: "&TotalPrice(prices),vbInformation[Description("Adds up the prices held in a Dictionary.")]FunctionTotalPrice(ByValpricesAsObject)AsDoubleAsVarianttotalAsDoubleEachkeyInprices.Keys▶   run Inventory.MainDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLEStwinBASIC IDE OptionsChange Licence...CloseSave ChangesTab SizeIDE Font SizeIDE FontCode Editor Font SizeCode Editor FontCode Editor Font: Use LigaturesShow Code Editor Combo SelectorsMonaco: Render WhitespaceLLVM Compiler: Maximum number of threadsLLVM Compiler: Complex procedure reporting threshold(milliseconds)LLVM Compiler: Keep cache process alive after exiting theIDERestore Editors State When Opening ProjectFocus The 'Recent' Tab On IDE StartupFile Explorer: Ask Before Delete FilesFile Explorer: Single-Click PreviewIDE: Show Advanced Info On HoverIDE: Show Hidden MembersIDE: Use new Handles/Implements syntax413pxSegoe UI13pxabovenone110000 +Inventory(general)(declaration)InventoryMain()namesAsNewCollectionAdd"Widget"Add"Sprocket"Add"Gasket"pricesAsObjectprices=CreateObject("Scripting.Dictionary")Add"Widget",4.5Add"Sprocket",12Add"Gasket",0.75itemAsVariantEachitemInnamesDebug.Printitem,prices(item)"Total: "&TotalPrice(prices),vbInformation[Description("Adds up the prices held in a Dictionary.")]FunctionTotalPrice(ByValpricesAsObject)AsDoubleAsVarianttotalAsDoubleEachkeyInprices.Keys▶   run Inventory.MainDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLEStwinBASIC IDE OptionsChange Licence...CloseSave ChangesTab SizeIDE Font SizeIDE FontCode Editor Font SizeCode Editor FontCode Editor Font: Use LigaturesShow Code Editor Combo SelectorsMonaco: Render WhitespaceLLVM Compiler: Maximum number of threadsLLVM Compiler: Complex procedure reporting threshold(milliseconds)LLVM Compiler: Keep cache process alive after exiting theIDERestore Editors State When Opening ProjectFocus The 'Recent' Tab On IDE StartupFile Explorer: Ask Before Delete FilesFile Explorer: Single-Click PreviewIDE: Show Advanced Info On HoverIDE: Show Hidden MembersIDE: Use new Handles/Implements syntax413pxSegoe UI13pxabovenone110000 diff --git a/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.png b/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.png index e5eb3a17d..ed7d8bb97 100644 Binary files a/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.png and b/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.png differ diff --git a/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.svg b/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.svg index 3b9737c88..f40e329c4 100644 --- a/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.svg +++ b/docs/IDE/Menu/Images/Menu_Tools_IDEOptions.svg @@ -1 +1 @@ -Inventory(general)(declaration)InventoryMain()namesAsNewCollectionAdd"Widget"Add"Sprocket"Add"Gasket"pricesAsObjectprices=CreateObject("Scripting.Dictionary")Add"Widget",4.5Add"Sprocket",12Add"Gasket",0.75itemAsVariantEachitemInnamesDebug.Printitem,prices(item)"Total: "&TotalPrice(prices),vbInformation[Description("Adds up the prices held in a Dictionary.")]FunctionTotalPrice(ByValpricesAsObject)AsDoubleAsVarianttotalAsDoubleEachkeyInprices.Keys▶   run Inventory.MainDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLEStwinBASIC IDE OptionsChange Licence...CloseSave ChangesTab SizeIDE Font SizeIDE FontCode Editor Font SizeCode Editor FontCode Editor Font: Use LigaturesShow Code Editor Combo SelectorsMonaco: Render WhitespaceLLVM Compiler: Maximum number of threadsLLVM Compiler: Complex procedure reporting threshold(milliseconds)LLVM Compiler: Keep cache process alive after exiting theIDERestore Editors State When Opening ProjectFocus The 'Recent' Tab On IDE StartupFile Explorer: Ask Before Delete FilesFile Explorer: Single-Click PreviewIDE: Show Advanced Info On HoverIDE: Show Hidden MembersIDE: Use new Handles/Implements syntax413pxSegoe UI13pxabovenone110000 +Inventory(general)(declaration)InventoryMain()namesAsNewCollectionAdd"Widget"Add"Sprocket"Add"Gasket"pricesAsObjectprices=CreateObject("Scripting.Dictionary")Add"Widget",4.5Add"Sprocket",12Add"Gasket",0.75itemAsVariantEachitemInnamesDebug.Printitem,prices(item)"Total: "&TotalPrice(prices),vbInformation[Description("Adds up the prices held in a Dictionary.")]FunctionTotalPrice(ByValpricesAsObject)AsDoubleAsVarianttotalAsDoubleEachkeyInprices.Keys▶   run Inventory.MainDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLEStwinBASIC IDE OptionsChange Licence...CloseSave ChangesTab SizeIDE Font SizeIDE FontCode Editor Font SizeCode Editor FontCode Editor Font: Use LigaturesShow Code Editor Combo SelectorsMonaco: Render WhitespaceLLVM Compiler: Maximum number of threadsLLVM Compiler: Complex procedure reporting threshold(milliseconds)LLVM Compiler: Keep cache process alive after exiting theIDERestore Editors State When Opening ProjectFocus The 'Recent' Tab On IDE StartupFile Explorer: Ask Before Delete FilesFile Explorer: Single-Click PreviewIDE: Show Advanced Info On HoverIDE: Show Hidden MembersIDE: Use new Handles/Implements syntax413pxSegoe UI13pxabovenone110000 diff --git a/docs/IDE/Menu/Images/Menu_Window.png b/docs/IDE/Menu/Images/Menu_Window.png index dfffcc09b..b8f33ffa1 100644 Binary files a/docs/IDE/Menu/Images/Menu_Window.png and b/docs/IDE/Menu/Images/Menu_Window.png differ diff --git a/docs/IDE/Projects/Images/Close_Question.light.png b/docs/IDE/Projects/Images/Close_Question.light.png index 313fbb8fd..35f961f26 100644 Binary files a/docs/IDE/Projects/Images/Close_Question.light.png and b/docs/IDE/Projects/Images/Close_Question.light.png differ diff --git a/docs/IDE/Projects/Images/Close_Question.png b/docs/IDE/Projects/Images/Close_Question.png index a750227b4..fecf9a0d8 100644 Binary files a/docs/IDE/Projects/Images/Close_Question.png and b/docs/IDE/Projects/Images/Close_Question.png differ diff --git a/docs/IDE/Projects/Images/Delete_Pair.light.png b/docs/IDE/Projects/Images/Delete_Pair.light.png index 7292d6ca1..526195a13 100644 Binary files a/docs/IDE/Projects/Images/Delete_Pair.light.png and b/docs/IDE/Projects/Images/Delete_Pair.light.png differ diff --git a/docs/IDE/Projects/Images/Delete_Pair.png b/docs/IDE/Projects/Images/Delete_Pair.png index b819335ef..5f9852f70 100644 Binary files a/docs/IDE/Projects/Images/Delete_Pair.png and b/docs/IDE/Projects/Images/Delete_Pair.png differ diff --git a/docs/IDE/Projects/Images/Failed_To_Load.png b/docs/IDE/Projects/Images/Failed_To_Load.png index f860c97c7..bfb1ed728 100644 Binary files a/docs/IDE/Projects/Images/Failed_To_Load.png and b/docs/IDE/Projects/Images/Failed_To_Load.png differ diff --git a/docs/IDE/Projects/Images/Menu_File_Project.png b/docs/IDE/Projects/Images/Menu_File_Project.png index de8ffb39c..fc084cfb0 100644 Binary files a/docs/IDE/Projects/Images/Menu_File_Project.png and b/docs/IDE/Projects/Images/Menu_File_Project.png differ diff --git a/docs/IDE/Projects/Images/ObjectView_Search.png b/docs/IDE/Projects/Images/ObjectView_Search.png index 85b581190..149ce0eca 100644 Binary files a/docs/IDE/Projects/Images/ObjectView_Search.png and b/docs/IDE/Projects/Images/ObjectView_Search.png differ diff --git a/docs/IDE/Projects/Images/References_Detail.light.png b/docs/IDE/Projects/Images/References_Detail.light.png index d402e5c20..ca4fa5e44 100644 Binary files a/docs/IDE/Projects/Images/References_Detail.light.png and b/docs/IDE/Projects/Images/References_Detail.light.png differ diff --git a/docs/IDE/Projects/Images/Rename_Box.light.png b/docs/IDE/Projects/Images/Rename_Box.light.png index 156b97366..52931d28d 100644 Binary files a/docs/IDE/Projects/Images/Rename_Box.light.png and b/docs/IDE/Projects/Images/Rename_Box.light.png differ diff --git a/docs/IDE/Projects/Images/Rename_Box.png b/docs/IDE/Projects/Images/Rename_Box.png index a156c744c..95da63e61 100644 Binary files a/docs/IDE/Projects/Images/Rename_Box.png and b/docs/IDE/Projects/Images/Rename_Box.png differ diff --git a/docs/IDE/Projects/Images/Rename_Invalid.light.png b/docs/IDE/Projects/Images/Rename_Invalid.light.png index 5f914c227..a3493e332 100644 Binary files a/docs/IDE/Projects/Images/Rename_Invalid.light.png and b/docs/IDE/Projects/Images/Rename_Invalid.light.png differ diff --git a/docs/IDE/Projects/Images/Rename_Invalid.png b/docs/IDE/Projects/Images/Rename_Invalid.png index 6cbd44c48..2b7595b29 100644 Binary files a/docs/IDE/Projects/Images/Rename_Invalid.png and b/docs/IDE/Projects/Images/Rename_Invalid.png differ diff --git a/docs/IDE/Projects/Images/Resource_Exists.light.png b/docs/IDE/Projects/Images/Resource_Exists.light.png index 395fde039..d1007781a 100644 Binary files a/docs/IDE/Projects/Images/Resource_Exists.light.png and b/docs/IDE/Projects/Images/Resource_Exists.light.png differ diff --git a/docs/IDE/Projects/Images/Resource_Exists.png b/docs/IDE/Projects/Images/Resource_Exists.png index bfa1d72b7..ac3141edf 100644 Binary files a/docs/IDE/Projects/Images/Resource_Exists.png and b/docs/IDE/Projects/Images/Resource_Exists.png differ diff --git a/docs/IDE/Projects/Images/Resource_Preview.png b/docs/IDE/Projects/Images/Resource_Preview.png index 9599ede02..57cce62a1 100644 Binary files a/docs/IDE/Projects/Images/Resource_Preview.png and b/docs/IDE/Projects/Images/Resource_Preview.png differ diff --git a/docs/IDE/Projects/Images/RightClick-File.light.png b/docs/IDE/Projects/Images/RightClick-File.light.png index a6c6ebbba..34c81b3cb 100644 Binary files a/docs/IDE/Projects/Images/RightClick-File.light.png and b/docs/IDE/Projects/Images/RightClick-File.light.png differ diff --git a/docs/IDE/Projects/Images/RightClick-File.png b/docs/IDE/Projects/Images/RightClick-File.png index 3d88e91e8..8f0049e74 100644 Binary files a/docs/IDE/Projects/Images/RightClick-File.png and b/docs/IDE/Projects/Images/RightClick-File.png differ diff --git a/docs/IDE/Projects/Images/Settings_Close.light.png b/docs/IDE/Projects/Images/Settings_Close.light.png index e4cc0f08f..8634d5715 100644 Binary files a/docs/IDE/Projects/Images/Settings_Close.light.png and b/docs/IDE/Projects/Images/Settings_Close.light.png differ diff --git a/docs/IDE/Projects/Images/Settings_Close.light.svg b/docs/IDE/Projects/Images/Settings_Close.light.svg index 88f177a30..469c2816d 100644 --- a/docs/IDE/Projects/Images/Settings_Close.light.svg +++ b/docs/IDE/Projects/Images/Settings_Close.light.svg @@ -1 +1 @@ -EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERMyProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesHelpersfrmMain.tbformfrmMain.twinLegacy.basStartup.twinPROPERTIESProject SettingsApply ChangesCancelProject NameThis is the namespace symbol used to represent the project via code. If a type library is generated, this is the type library nameProject DescriptionIf a type library is generated, this is the type library description. You can include compiler variables here, such as ${Architecture},${VersionMajor}, ${VersionMinor}, ${VersionBuild}, ${VersionRevision}Application TitleThis is used for the default title caption of MsgBox and InputBox, and also is the value returned from the App.Title propertyApplication HelpFileThis is accesible at runtime via the App.HelpFile property, and is used in the Forms runtime help system (F1 / WhatsThis)Startup ObjectThis is the form that will be shown at startup, or 'Sub Main'. If not specified, 'Sub Main' is the default for EXEs, '(none)' is the default for DLLs.Icon FormWhen set, the icon from this form will be imported into the ICON resources during build. The icon will be imported as the #1 resource entry inthe RT_GROUP_ICON group. The OS typically uses this icon to represent the application.Library ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesMyProjectA small sample project. Updated.MyProject(unset)Sub MainCOMPILER DEFAULT - (none)VBAVBRUNVBstdoleScriptingtwinBASIC - VBA Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VBRUN Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN]OLE Automation2.0Microsoft Scripting Runtime1.0🖉🖉🖉🖉🖉Library SymbolNamein order of priorityVersionPublisher(enter text to filter)twinBASICYes, closeNo, keep editingWARNING: you made changes but haven't saved them.Close without saving? +EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERMyProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesHelpersfrmMain.tbformfrmMain.twinLegacy.basStartup.twinPROPERTIESProject SettingsApply ChangesCancelProject NameThis is the namespace symbol used to represent the project via code. If a type library is generated, this is the type library nameProject DescriptionIf a type library is generated, this is the type library description. You can include compiler variables here, such as ${Bitness}, ${Architecture},${VersionMajor}, ${VersionMinor}, ${VersionBuild}, ${VersionRevision}Application TitleThis is used for the default title caption of MsgBox and InputBox, and also is the value returned from the App.Title propertyApplication HelpFileThis is accesible at runtime via the App.HelpFile property, and is used in the Forms runtime help system (F1 / WhatsThis)Startup ObjectThis is the form that will be shown at startup, or 'Sub Main'. If not specified, 'Sub Main' is the default for EXEs, '(none)' is the default for DLLs.Icon FormWhen set, the icon from this form will be imported into the ICON resources during build. The icon will be imported as the #1 resource entry inthe RT_GROUP_ICON group. The OS typically uses this icon to represent the application.Library ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesMyProjectA small sample project. Updated.MyProject(unset)Sub MainCOMPILER DEFAULT - (none)VBAVBRUNVBstdoleScriptingtwinBASIC - VBA Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VBRUN Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN]OLE Automation2.0Microsoft Scripting Runtime1.0🖉🖉🖉🖉🖉Library SymbolNamein order of priorityVersionPublisher(enter text to filter)twinBASICYes, closeNo, keep editingWARNING: you made changes but haven't saved them.Close without saving? diff --git a/docs/IDE/Projects/Images/Settings_Close.png b/docs/IDE/Projects/Images/Settings_Close.png index 93a876dc0..4a1278726 100644 Binary files a/docs/IDE/Projects/Images/Settings_Close.png and b/docs/IDE/Projects/Images/Settings_Close.png differ diff --git a/docs/IDE/Projects/Images/Settings_Close.svg b/docs/IDE/Projects/Images/Settings_Close.svg index 150d24d8e..b7ab08939 100644 --- a/docs/IDE/Projects/Images/Settings_Close.svg +++ b/docs/IDE/Projects/Images/Settings_Close.svg @@ -1 +1 @@ -win32100%EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERMyProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesHelpersfrmMain.tbformfrmMain.twinLegacy.basStartup.twinPROPERTIESProject SettingsApply ChangesCancelProject NameThis is the namespace symbol used to represent the project via code. If a type library is generated, this is the type library nameProject DescriptionIf a type library is generated, this is the type library description. You can include compiler variables here, such as ${Architecture},${VersionMajor}, ${VersionMinor}, ${VersionBuild}, ${VersionRevision}Application TitleThis is used for the default title caption of MsgBox and InputBox, and also is the value returned from the App.Title propertyApplication HelpFileThis is accesible at runtime via the App.HelpFile property, and is used in the Forms runtime help system (F1 / WhatsThis)Startup ObjectThis is the form that will be shown at startup, or 'Sub Main'. If not specified, 'Sub Main' is the default for EXEs, '(none)' is the default for DLLs.Icon FormWhen set, the icon from this form will be imported into the ICON resources during build. The icon will be imported as the #1 resource entry inthe RT_GROUP_ICON group. The OS typically uses this icon to represent the application.Library ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesMyProjectA small sample project. Updated.MyProject(unset)Sub MainCOMPILER DEFAULT - (none)VBAVBRUNVBstdoleScriptingtwinBASIC - VBA Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VBRUN Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN]OLE Automation2.0Microsoft Scripting Runtime1.0🖉🖉🖉🖉🖉Library SymbolNamein order of priorityVersionPublisher(enter text to filter)twinBASICYes, closeNo, keep editingWARNING: you made changes but haven't saved them.Close without saving? +win32100%EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERMyProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesHelpersfrmMain.tbformfrmMain.twinLegacy.basStartup.twinPROPERTIESProject SettingsApply ChangesCancelProject NameThis is the namespace symbol used to represent the project via code. If a type library is generated, this is the type library nameProject DescriptionIf a type library is generated, this is the type library description. You can include compiler variables here, such as ${Bitness}, ${Architecture},${VersionMajor}, ${VersionMinor}, ${VersionBuild}, ${VersionRevision}Application TitleThis is used for the default title caption of MsgBox and InputBox, and also is the value returned from the App.Title propertyApplication HelpFileThis is accesible at runtime via the App.HelpFile property, and is used in the Forms runtime help system (F1 / WhatsThis)Startup ObjectThis is the form that will be shown at startup, or 'Sub Main'. If not specified, 'Sub Main' is the default for EXEs, '(none)' is the default for DLLs.Icon FormWhen set, the icon from this form will be imported into the ICON resources during build. The icon will be imported as the #1 resource entry inthe RT_GROUP_ICON group. The OS typically uses this icon to represent the application.Library ReferencesEnabled LibrariesAvailable COM ReferencesAvailable PackagesMyProjectA small sample project. Updated.MyProject(unset)Sub MainCOMPILER DEFAULT - (none)VBAVBRUNVBstdoleScriptingtwinBASIC - VBA Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VBRUN Compatibility Package0.0.0.1[BUILT-IN]twinBASIC - VB Compatibility Package (Forms)0.0.0.31[BUILT-IN]OLE Automation2.0Microsoft Scripting Runtime1.0🖉🖉🖉🖉🖉Library SymbolNamein order of priorityVersionPublisher(enter text to filter)twinBASICYes, closeNo, keep editingWARNING: you made changes but haven't saved them.Close without saving? diff --git a/docs/IDE/Projects/Images/Title_Changed.light.png b/docs/IDE/Projects/Images/Title_Changed.light.png index 8a08655c0..ec70001ab 100644 Binary files a/docs/IDE/Projects/Images/Title_Changed.light.png and b/docs/IDE/Projects/Images/Title_Changed.light.png differ diff --git a/docs/IDE/Projects/Images/Title_Changed.light.svg b/docs/IDE/Projects/Images/Title_Changed.light.svg index 6b83fdc07..a1ea23f9e 100644 --- a/docs/IDE/Projects/Images/Title_Changed.light.svg +++ b/docs/IDE/Projects/Images/Title_Changed.light.svg @@ -1 +1 @@ -• project.twinproj - twinBASIC (twinBASIC IDE BETA 1005) +• project.twinproj - twinBASIC (twinBASIC IDE BETA 1010) diff --git a/docs/IDE/Projects/Images/Title_Changed.png b/docs/IDE/Projects/Images/Title_Changed.png index 251eeca33..7a0cd4a11 100644 Binary files a/docs/IDE/Projects/Images/Title_Changed.png and b/docs/IDE/Projects/Images/Title_Changed.png differ diff --git a/docs/IDE/Projects/Images/Title_Changed.svg b/docs/IDE/Projects/Images/Title_Changed.svg index 8655f04a5..ea29f1f58 100644 --- a/docs/IDE/Projects/Images/Title_Changed.svg +++ b/docs/IDE/Projects/Images/Title_Changed.svg @@ -1 +1 @@ -• project.twinproj - twinBASIC (twinBASIC IDE BETA 1005) +• project.twinproj - twinBASIC (twinBASIC IDE BETA 1010) diff --git a/docs/IDE/Projects/Images/Tree_Tints.light.png b/docs/IDE/Projects/Images/Tree_Tints.light.png index 159e6cb3c..1c730f086 100644 Binary files a/docs/IDE/Projects/Images/Tree_Tints.light.png and b/docs/IDE/Projects/Images/Tree_Tints.light.png differ diff --git a/docs/IDE/Projects/Images/Tree_Tints.png b/docs/IDE/Projects/Images/Tree_Tints.png index d32233d51..6e3b94063 100644 Binary files a/docs/IDE/Projects/Images/Tree_Tints.png and b/docs/IDE/Projects/Images/Tree_Tints.png differ diff --git a/docs/IDE/Reports/Images/Report_Controls.light.png b/docs/IDE/Reports/Images/Report_Controls.light.png index 13c0ea5d5..ada99a7c4 100644 Binary files a/docs/IDE/Reports/Images/Report_Controls.light.png and b/docs/IDE/Reports/Images/Report_Controls.light.png differ diff --git a/docs/IDE/Reports/Images/Report_Controls.png b/docs/IDE/Reports/Images/Report_Controls.png index d5a876ba4..e3c3e45e8 100644 Binary files a/docs/IDE/Reports/Images/Report_Controls.png and b/docs/IDE/Reports/Images/Report_Controls.png differ diff --git a/docs/LLVM/Images/llvmdoc1.light.png b/docs/LLVM/Images/llvmdoc1.light.png index 3c0306231..a36058911 100644 Binary files a/docs/LLVM/Images/llvmdoc1.light.png and b/docs/LLVM/Images/llvmdoc1.light.png differ diff --git a/docs/LLVM/Images/llvmdoc1.light.svg b/docs/LLVM/Images/llvmdoc1.light.svg index 94cf21cc3..fcd2a5472 100644 --- a/docs/LLVM/Images/llvmdoc1.light.svg +++ b/docs/LLVM/Images/llvmdoc1.light.svg @@ -1 +1 @@ -EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsApply ChangesCancelSlider ControlTreeView ControlUpDown ControlCompress Runtime Class Dispatch InfoCompress Runtime Error TablesCompress Misc DataButtons support Graphical styleRuntime PNG support (via Global.LoadPicture)Here you can disable certain project features in order to reduce the compiled build size.Compiler Options (BUILD)Enable LLVM CompilationLLVM: Generate optimized codeLLVM: Optimize for smaller filesizeLLVM: Target CPUs with AESLLVM: Target CPUs with AVXLLVM: Target CPUs with AVX2LLVM: Target CPUs with BMI2LLVM: Target CPUs with FMALLVM: Target CPUs with FXSRLLVM: Target CPUs with LZCNTLLVM: Target CPUs with POPCNTLLVM: Target CPUs with RDSEEDLLVM: Target CPUs with SHALLVM: Target CPUs with SSELLVM: Target CPUs with SSE2LLVM: Target CPUs with SSE3LLVM: Target CPUs with SSE4.1LLVM: Target CPUs with SSE4.2LLVM: Target CPUs with SSSE3LLVM: Target CPUs with XSAVELLVM: Target CPUs with XSAVECLLVM: Target CPUs with XSAVEOPTLLVM: Target CPUs with XSAVESHere you can enable compiler options via a comma-delimited list of flags that will be applied to built executables.NOTE: If you enable targeting for a specific CPU architecture feature, your software will not run on any CPU that does not support that feature.Compiler Options (DEBUG)Enable LLVM CompilationLLVM: Generate optimized codeLLVM: Optimize for smaller filesizeLLVM: Target CPUs with AESLLVM: Target CPUs with AVXLLVM: Target CPUs with AVX2LLVM: Target CPUs with BMI2LLVM: Target CPUs with FMALLVM: Target CPUs with FXSRLLVM: Target CPUs with LZCNTLLVM: Target CPUs with POPCNTLLVM: Target CPUs with RDSEEDLLVM: Target CPUs with SHALLVM: Target CPUs with SSELLVM: Target CPUs with SSE2LLVM: Target CPUs with SSE3LLVM: Target CPUs with SSE4.1LLVM: Target CPUs with SSE4.2LLVM: Target CPUs with SSSE3LLVM: Target CPUs with XSAVELLVM: Target CPUs with XSAVECLLVM: Target CPUs with XSAVEOPTLLVM: Target CPUs with XSAVESHere you can enable compiler options via a comma-delimited list of flags that will be applied to the IDE environment.NOTE: Enabling LLVM compilation in the IDE debug environment is NOT recommended. You will not be able to debug LLVMcompiled code.(enter text to filter) +EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsApply ChangesCancelSlider ControlTreeView ControlUpDown ControlCompress Runtime Class Dispatch InfoCompress Runtime Error TablesCompress Misc DataButtons support Graphical styleRuntime PNG support (via Global.LoadPicture)Here you can disable certain project features in order to reduce the compiled build size.Compiler Options (BUILD)Enable LLVM CompilationLLVM: Generate optimized codeLLVM: Optimize for smaller filesizeLLVM: Target CPUs with AESLLVM: Target CPUs with AVXLLVM: Target CPUs with AVX2LLVM: Target CPUs with BMI2LLVM: Target CPUs with FMALLVM: Target CPUs with FXSRLLVM: Target CPUs with LZCNTLLVM: Target CPUs with POPCNTLLVM: Target CPUs with RDSEEDLLVM: Target CPUs with SHALLVM: Target CPUs with SSELLVM: Target CPUs with SSE2LLVM: Target CPUs with SSE3LLVM: Target CPUs with SSE4.1LLVM: Target CPUs with SSE4.2LLVM: Target CPUs with SSSE3LLVM: Target CPUs with XSAVELLVM: Target CPUs with XSAVECLLVM: Target CPUs with XSAVEOPTLLVM: Target CPUs with XSAVESHere you can enable compiler options via a comma-delimited list of flags that will be applied to built executables.NOTE: If you enable targeting for a specific CPU architecture feature, your software will not run on any CPU that does not support that feature.Compiler Options (DEBUG)Enable LLVM CompilationLLVM: Generate optimized codeLLVM: Optimize for smaller filesizeLLVM: Target CPUs with AESLLVM: Target CPUs with AVXLLVM: Target CPUs with AVX2LLVM: Target CPUs with BMI2LLVM: Target CPUs with FMALLVM: Target CPUs with FXSRLLVM: Target CPUs with LZCNTLLVM: Target CPUs with POPCNTLLVM: Target CPUs with RDSEEDLLVM: Target CPUs with SHALLVM: Target CPUs with SSELLVM: Target CPUs with SSE2LLVM: Target CPUs with SSE3LLVM: Target CPUs with SSE4.1LLVM: Target CPUs with SSE4.2LLVM: Target CPUs with SSSE3LLVM: Target CPUs with XSAVELLVM: Target CPUs with XSAVECLLVM: Target CPUs with XSAVEOPTLLVM: Target CPUs with XSAVESHere you can enable compiler options via a comma-delimited list of flags that will be applied to the IDE environment.NOTE: Enabling LLVM compilation in the IDE debug environment is NOT recommended. You will not be able to debug LLVMcompiled code.(enter text to filter) diff --git a/docs/LLVM/Images/llvmdoc1.svg b/docs/LLVM/Images/llvmdoc1.svg index 695af7ad7..f6ae7a2dc 100644 --- a/docs/LLVM/Images/llvmdoc1.svg +++ b/docs/LLVM/Images/llvmdoc1.svg @@ -1 +1 @@ -win32100%EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1005MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsApply ChangesCancelSlider ControlTreeView ControlUpDown ControlCompress Runtime Class Dispatch InfoCompress Runtime Error TablesCompress Misc DataButtons support Graphical styleRuntime PNG support (via Global.LoadPicture)Here you can disable certain project features in order to reduce the compiled build size.Compiler Options (BUILD)Enable LLVM CompilationLLVM: Generate optimized codeLLVM: Optimize for smaller filesizeLLVM: Target CPUs with AESLLVM: Target CPUs with AVXLLVM: Target CPUs with AVX2LLVM: Target CPUs with BMI2LLVM: Target CPUs with FMALLVM: Target CPUs with FXSRLLVM: Target CPUs with LZCNTLLVM: Target CPUs with POPCNTLLVM: Target CPUs with RDSEEDLLVM: Target CPUs with SHALLVM: Target CPUs with SSELLVM: Target CPUs with SSE2LLVM: Target CPUs with SSE3LLVM: Target CPUs with SSE4.1LLVM: Target CPUs with SSE4.2LLVM: Target CPUs with SSSE3LLVM: Target CPUs with XSAVELLVM: Target CPUs with XSAVECLLVM: Target CPUs with XSAVEOPTLLVM: Target CPUs with XSAVESHere you can enable compiler options via a comma-delimited list of flags that will be applied to built executables.NOTE: If you enable targeting for a specific CPU architecture feature, your software will not run on any CPU that does not support that feature.Compiler Options (DEBUG)Enable LLVM CompilationLLVM: Generate optimized codeLLVM: Optimize for smaller filesizeLLVM: Target CPUs with AESLLVM: Target CPUs with AVXLLVM: Target CPUs with AVX2LLVM: Target CPUs with BMI2LLVM: Target CPUs with FMALLVM: Target CPUs with FXSRLLVM: Target CPUs with LZCNTLLVM: Target CPUs with POPCNTLLVM: Target CPUs with RDSEEDLLVM: Target CPUs with SHALLVM: Target CPUs with SSELLVM: Target CPUs with SSE2LLVM: Target CPUs with SSE3LLVM: Target CPUs with SSE4.1LLVM: Target CPUs with SSE4.2LLVM: Target CPUs with SSSE3LLVM: Target CPUs with XSAVELLVM: Target CPUs with XSAVECLLVM: Target CPUs with XSAVEOPTLLVM: Target CPUs with XSAVESHere you can enable compiler options via a comma-delimited list of flags that will be applied to the IDE environment.NOTE: Enabling LLVM compilation in the IDE debug environment is NOT recommended. You will not be able to debug LLVMcompiled code.(enter text to filter) +win32100%EDITOR 1DEBUG CONSOLEDIAGNOSTICS0000CALL STACKCOMPILER [Win32] v0.15.1010MAIN_THREAD [IDLE]VARIABLESPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesSourcesIShape.twinMainModule.twinTypes.twinCHANGELOG.mdLICENCE.mdPROPERTIESProject SettingsApply ChangesCancelSlider ControlTreeView ControlUpDown ControlCompress Runtime Class Dispatch InfoCompress Runtime Error TablesCompress Misc DataButtons support Graphical styleRuntime PNG support (via Global.LoadPicture)Here you can disable certain project features in order to reduce the compiled build size.Compiler Options (BUILD)Enable LLVM CompilationLLVM: Generate optimized codeLLVM: Optimize for smaller filesizeLLVM: Target CPUs with AESLLVM: Target CPUs with AVXLLVM: Target CPUs with AVX2LLVM: Target CPUs with BMI2LLVM: Target CPUs with FMALLVM: Target CPUs with FXSRLLVM: Target CPUs with LZCNTLLVM: Target CPUs with POPCNTLLVM: Target CPUs with RDSEEDLLVM: Target CPUs with SHALLVM: Target CPUs with SSELLVM: Target CPUs with SSE2LLVM: Target CPUs with SSE3LLVM: Target CPUs with SSE4.1LLVM: Target CPUs with SSE4.2LLVM: Target CPUs with SSSE3LLVM: Target CPUs with XSAVELLVM: Target CPUs with XSAVECLLVM: Target CPUs with XSAVEOPTLLVM: Target CPUs with XSAVESHere you can enable compiler options via a comma-delimited list of flags that will be applied to built executables.NOTE: If you enable targeting for a specific CPU architecture feature, your software will not run on any CPU that does not support that feature.Compiler Options (DEBUG)Enable LLVM CompilationLLVM: Generate optimized codeLLVM: Optimize for smaller filesizeLLVM: Target CPUs with AESLLVM: Target CPUs with AVXLLVM: Target CPUs with AVX2LLVM: Target CPUs with BMI2LLVM: Target CPUs with FMALLVM: Target CPUs with FXSRLLVM: Target CPUs with LZCNTLLVM: Target CPUs with POPCNTLLVM: Target CPUs with RDSEEDLLVM: Target CPUs with SHALLVM: Target CPUs with SSELLVM: Target CPUs with SSE2LLVM: Target CPUs with SSE3LLVM: Target CPUs with SSE4.1LLVM: Target CPUs with SSE4.2LLVM: Target CPUs with SSSE3LLVM: Target CPUs with XSAVELLVM: Target CPUs with XSAVECLLVM: Target CPUs with XSAVEOPTLLVM: Target CPUs with XSAVESHere you can enable compiler options via a comma-delimited list of flags that will be applied to the IDE environment.NOTE: Enabling LLVM compilation in the IDE debug environment is NOT recommended. You will not be able to debug LLVMcompiled code.(enter text to filter) diff --git a/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.light.png b/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.light.png index 513745475..d8a59cebc 100644 Binary files a/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.light.png and b/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.light.png differ diff --git a/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.light.svg b/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.light.svg index 86588106e..52f2f1d2c 100644 --- a/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.light.svg +++ b/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.light.svg @@ -1 +1 @@ -EDITOR 1Project SettingsConditional Compilation ArgsEnter a colon delimited list of name=value pairs used by the compiler during conditional compilation evaluation. to 32767 are allowed. for example: foo=42:bar=-42Option Explicit OnThis option takes effect if Option Explicit On/Off is not specified in the source file(unset)Yes(enter text to filter) +EDITOR 1Project SettingsConditional Compilation ArgsEnter a colon delimited list of name=value pairs used by the compiler during conditional compilation evaluation. to 32767 are allowed. for example: foo=42:bar=-42Option Explicit OnThis option takes effect if Option Explicit On/Off is not specified in the source file(unset)Yes(enter text to filter) diff --git a/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.svg b/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.svg index 9e53d6acd..33c13df8d 100644 --- a/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.svg +++ b/docs/Miscellaneous/Images/01009879-fdbc-4a8e-8683-353aab6193df.svg @@ -1 +1 @@ -win32EDITOR 1Project SettingsConditional Compilation ArgsEnter a colon delimited list of name=value pairs used by the compiler during conditional compilation evaluation. to 32767 are allowed. for example: foo=42:bar=-42Option Explicit OnThis option takes effect if Option Explicit On/Off is not specified in the source file(unset)Yes(enter text to filter) +win32EDITOR 1Project SettingsConditional Compilation ArgsEnter a colon delimited list of name=value pairs used by the compiler during conditional compilation evaluation. to 32767 are allowed. for example: foo=42:bar=-42Option Explicit OnThis option takes effect if Option Explicit On/Off is not specified in the source file(unset)Yes(enter text to filter) diff --git a/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.light.png b/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.light.png index 7f2a4c675..7b540ad48 100644 Binary files a/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.light.png and b/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.light.png differ diff --git a/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.light.svg b/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.light.svg index 4f98e998b..ad87e330e 100644 --- a/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.light.svg +++ b/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.light.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentSample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE AddinSample 11. twinBASIC IDE Addin (Chart)Sample 12. twinBASIC IDE Addin (Monaco)Sample 13. twinBASIC IDE Addin (ListView)Sample 14. twinBASIC IDE Addin (VirtualListView)Sample 15. twinBASIC IDE Addin (GlobalSearch)Sample 16. twinBASIC IDE Addin (TODO Widgets demo) +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentSample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE AddinSample 11. twinBASIC IDE Addin (Chart)Sample 12. twinBASIC IDE Addin (Monaco)Sample 13. twinBASIC IDE Addin (ListView)Sample 14. twinBASIC IDE Addin (VirtualListView)Sample 15. twinBASIC IDE Addin (GlobalSearch)Sample 16. twinBASIC IDE Addin (TODO Widgets demo) diff --git a/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.png b/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.png index c538ce785..ab8b2b5a5 100644 Binary files a/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.png and b/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.png differ diff --git a/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.svg b/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.svg index 1a4313e2a..246c4d81f 100644 --- a/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.svg +++ b/docs/Miscellaneous/Images/0e24eb5c-c9af-49a9-a908-03968b211554.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentSample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE AddinSample 11. twinBASIC IDE Addin (Chart)Sample 12. twinBASIC IDE Addin (Monaco)Sample 13. twinBASIC IDE Addin (ListView)Sample 14. twinBASIC IDE Addin (VirtualListView)Sample 15. twinBASIC IDE Addin (GlobalSearch)Sample 16. twinBASIC IDE Addin (TODO Widgets demo) +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentSample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE AddinSample 11. twinBASIC IDE Addin (Chart)Sample 12. twinBASIC IDE Addin (Monaco)Sample 13. twinBASIC IDE Addin (ListView)Sample 14. twinBASIC IDE Addin (VirtualListView)Sample 15. twinBASIC IDE Addin (GlobalSearch)Sample 16. twinBASIC IDE Addin (TODO Widgets demo) diff --git a/docs/Miscellaneous/Images/2a1c71fd-f81c-4bd3-b61a-0f2979e8961f.svg b/docs/Miscellaneous/Images/2a1c71fd-f81c-4bd3-b61a-0f2979e8961f.svg index fcfd2af04..619a6e19d 100644 --- a/docs/Miscellaneous/Images/2a1c71fd-f81c-4bd3-b61a-0f2979e8961f.svg +++ b/docs/Miscellaneous/Images/2a1c71fd-f81c-4bd3-b61a-0f2979e8961f.svg @@ -1 +1 @@ -MiscellaneousPackagesReferencesResourcesSourcesCHANGELOG.mdLICENCE.mdCompiler WarningsDefine how the compiler is to treat warnings inside this project. These settings can be overriden with Class/Module/procedure attributes:[ EnforceWarnings(TBxxxx) ][ EnforceErrors(TBxxxx) ][ IgnoreWarnings(TBxxxx) ]TB0001    Use of legacy DefType statements is strongly discouragedTB0002    This variable has been auto-declared by the compiler due to Option Explicit being OFFTB0003    Datatype has not been explicitly declared so will default to VariantTB0004    [Exit Sub/Function] inside a Property-Get procedure is only supported for backwards compatibility. Use [Exit Property] instead.TB0005    #Warning directive was encounteredTB0006    Record length is ignored in binary modeTB0007    Mismatched datatype hintTB0008    Suspicious callTB0009    Member is unimplementedTB0010    Duplicate DLL declaration detectedTB0011    Use of legacy date/time property-let assignments are strongly discouragedTB0012    Possible misuse of hexadecimal literal notationTB0013    It is strongly recommended to specify an [ InterfaceId() ] attribute for this classTB0014    The inline ByVal attribute is ignored on User Defined TypesTB0015    Use of legacy DLL {LEGACY.DLL} has been redirected to {MODERN.DLL}WARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGHINTWARNINGWARNINGHINTINFOIGNOREERROR +MiscellaneousPackagesReferencesResourcesSourcesCHANGELOG.mdLICENCE.mdCompiler WarningsDefine how the compiler is to treat warnings inside this project. These settings can be overriden with Class/Module/procedure attributes:[ EnforceWarnings(TBxxxx) ][ EnforceErrors(TBxxxx) ][ IgnoreWarnings(TBxxxx) ]TB0001    Use of legacy DefType statements is strongly discouragedTB0002    This variable has been auto-declared by the compiler due to Option Explicit being OFFTB0003    Datatype has not been explicitly declared so will default to VariantTB0004    [Exit Sub/Function] inside a Property-Get procedure is only supported for backwards compatibility. Use [Exit Property] instead.TB0005    #Warning directive was encounteredTB0006    Record length is ignored in binary modeTB0007    Mismatched datatype hintTB0008    Suspicious callTB0009    Member is unimplementedTB0010    Duplicate DLL declaration detectedTB0011    Use of legacy date/time property-let assignments are strongly discouragedTB0012    Possible misuse of hexadecimal literal notationTB0013    It is strongly recommended to specify an [ InterfaceId() ] attribute for this classTB0014    The inline ByVal attribute is ignored on User Defined TypesTB0015    Use of legacy DLL {LEGACY.DLL} has been redirected to {MODERN.DLL}WARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGHINTWARNINGWARNINGHINTINFOIGNOREERROR diff --git a/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.light.png b/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.light.png index cc40fcec4..1cf7df8e5 100644 Binary files a/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.light.png and b/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.light.png differ diff --git a/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.light.svg b/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.light.svg index c9b8d32a5..0c716ed88 100644 --- a/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.light.svg +++ b/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.light.svg @@ -1 +1 @@ -ToolsAdd-InsWindowHelpproject.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32100%PREVIEWMainModule(general)(declaration)Main()Show▶   run MainModule.MainPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesICONtwinBASIC.icoMANIFEST#1.xmlMESSAGETABLESTRINGSourcesfrmMain.tbformfrmMain.twinIShape.twinMainModule.twin +ToolsAdd-InsWindowHelpproject.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32100%PREVIEWMainModule(general)(declaration)Main()Show▶   run MainModule.MainPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesICONtwinBASIC.icoMANIFEST#1.xmlMESSAGETABLESTRINGSourcesfrmMain.tbformfrmMain.twinIShape.twinMainModule.twin diff --git a/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.png b/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.png index 022031183..0b18b42f2 100644 Binary files a/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.png and b/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.png differ diff --git a/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.svg b/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.svg index 5ae2d8738..c57d32a9c 100644 --- a/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.svg +++ b/docs/Miscellaneous/Images/71ddde83-a091-47e3-b5b8-681954b0639d.svg @@ -1 +1 @@ -ToolsAdd-InsWindowHelpproject.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32100%PREVIEWMainModule(general)(declaration)Main()Show▶   run MainModule.MainPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesICONtwinBASIC.icoMANIFEST#1.xmlMESSAGETABLESTRINGSourcesfrmMain.tbformfrmMain.twinIShape.twin +ToolsAdd-InsWindowHelpproject.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32100%PREVIEWMainModule(general)(declaration)Main()Show▶   run MainModule.MainPROJECT EXPLORERSampleProjectImportedTypeLibrariesMiscellaneousPackagesReferencesResourcesICONtwinBASIC.icoMANIFEST#1.xmlMESSAGETABLESTRINGSourcesfrmMain.tbformfrmMain.twinIShape.twin diff --git a/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.light.png b/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.light.png index 2345d63f4..af6944fbd 100644 Binary files a/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.light.png and b/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.light.png differ diff --git a/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.light.svg b/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.light.svg index f922c5356..9dda8ce9e 100644 --- a/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.light.svg +++ b/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.light.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentStandard EXEActiveX ControlActiveX DLLStandard DLL(non-ActiveX)Standard EXE(Console App)Standard EXE (plusVBCCR v1.8)(experimental)Import from VBP...Import fromfolder... +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentStandard EXEActiveX ControlActiveX DLLStandard DLL(non-ActiveX)Standard EXE(Console App)Standard EXE (plusVBCCR v1.8)(experimental)Import from VBP...Import fromfolder... diff --git a/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.png b/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.png index 7d286409d..a9512617e 100644 Binary files a/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.png and b/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.png differ diff --git a/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.svg b/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.svg index 223d90293..7c9c49402 100644 --- a/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.svg +++ b/docs/Miscellaneous/Images/7e1cb69c-6db3-4f3f-aea1-c1fae25938a2.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentStandard EXEActiveX ControlActiveX DLLStandard DLL(non-ActiveX)Standard EXE(Console App)Standard EXE (plusVBCCR v1.8)(experimental)Import from VBP...Import fromfolder... +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentStandard EXEActiveX ControlActiveX DLLStandard DLL(non-ActiveX)Standard EXE(Console App)Standard EXE (plusVBCCR v1.8)(experimental)Import from VBP...Import fromfolder... diff --git a/docs/Miscellaneous/Images/8611d12a-d7a6-48cc-9544-cb27c5299aa5.light.png b/docs/Miscellaneous/Images/8611d12a-d7a6-48cc-9544-cb27c5299aa5.light.png index d1fcf4bab..b0f0bca14 100644 Binary files a/docs/Miscellaneous/Images/8611d12a-d7a6-48cc-9544-cb27c5299aa5.light.png and b/docs/Miscellaneous/Images/8611d12a-d7a6-48cc-9544-cb27c5299aa5.light.png differ diff --git a/docs/Miscellaneous/Images/8611d12a-d7a6-48cc-9544-cb27c5299aa5.png b/docs/Miscellaneous/Images/8611d12a-d7a6-48cc-9544-cb27c5299aa5.png index 37144d407..78c3c0fbb 100644 Binary files a/docs/Miscellaneous/Images/8611d12a-d7a6-48cc-9544-cb27c5299aa5.png and b/docs/Miscellaneous/Images/8611d12a-d7a6-48cc-9544-cb27c5299aa5.png differ diff --git a/docs/Miscellaneous/Images/94490c87-fafe-4d5b-ae39-d3cedba1c21d.png b/docs/Miscellaneous/Images/94490c87-fafe-4d5b-ae39-d3cedba1c21d.png index 90b6c5a7b..ff615bc02 100644 Binary files a/docs/Miscellaneous/Images/94490c87-fafe-4d5b-ae39-d3cedba1c21d.png and b/docs/Miscellaneous/Images/94490c87-fafe-4d5b-ae39-d3cedba1c21d.png differ diff --git a/docs/Miscellaneous/Images/94490c87-fafe-4d5b-ae39-d3cedba1c21d.svg b/docs/Miscellaneous/Images/94490c87-fafe-4d5b-ae39-d3cedba1c21d.svg index 87c7ec182..100fa7ce9 100644 --- a/docs/Miscellaneous/Images/94490c87-fafe-4d5b-ae39-d3cedba1c21d.svg +++ b/docs/Miscellaneous/Images/94490c87-fafe-4d5b-ae39-d3cedba1c21d.svg @@ -1 +1 @@ -The Bootstrapper is a tiny installer thatdownloads the Evergreen Runtime matchingdevice architecture and installs it locally. There isalso a Link that allows you to programmaticallydownload the Bootstrapper.Evergreen BootstrapperGet the LinkDownloadA full-blown installer that can install theEvergreen Runtime in offline environment.Available for x86/x64/ARM64.Evergreen Standalone Installerx86x64ARM64Select and package a specific version of theWebView2 Runtime with your application.Select VersionSelect ArchitectureFixed Version155.0.4283.45arm64DownloadDownload the WebView2 RuntimeWhen distributing your application, there are a few ways you can ensure theWebView2 Runtime is on client machines. Learn more about those options.For installation issues and error codes see our troubleshooting guide. +The Bootstrapper is a tiny installer thatdownloads the Evergreen Runtime matchingdevice architecture and installs it locally. There isalso a Link that allows you to programmaticallydownload the Bootstrapper.Evergreen BootstrapperGet the LinkDownloadA full-blown installer that can install theEvergreen Runtime in offline environment.Available for x86/x64/ARM64.Evergreen Standalone Installerx86x64ARM64Select and package a specific version of theWebView2 Runtime with your application.Select VersionSelect ArchitectureFixed Version155.0.4283.62x86DownloadDownload the WebView2 RuntimeWhen distributing your application, there are a few ways you can ensure theWebView2 Runtime is on client machines. Learn more about those options.For installation issues and error codes see our troubleshooting guide. diff --git a/docs/Miscellaneous/Images/97cc8655-7a8b-47f3-b52c-eb1ddfce662f.light.png b/docs/Miscellaneous/Images/97cc8655-7a8b-47f3-b52c-eb1ddfce662f.light.png index 1f400e35b..594a88dee 100644 Binary files a/docs/Miscellaneous/Images/97cc8655-7a8b-47f3-b52c-eb1ddfce662f.light.png and b/docs/Miscellaneous/Images/97cc8655-7a8b-47f3-b52c-eb1ddfce662f.light.png differ diff --git a/docs/Miscellaneous/Images/97cc8655-7a8b-47f3-b52c-eb1ddfce662f.png b/docs/Miscellaneous/Images/97cc8655-7a8b-47f3-b52c-eb1ddfce662f.png index 5cd557c23..e5b5c6882 100644 Binary files a/docs/Miscellaneous/Images/97cc8655-7a8b-47f3-b52c-eb1ddfce662f.png and b/docs/Miscellaneous/Images/97cc8655-7a8b-47f3-b52c-eb1ddfce662f.png differ diff --git a/docs/Miscellaneous/Images/ac019c1a-dcef-4964-a730-bc5b86c644ba.png b/docs/Miscellaneous/Images/ac019c1a-dcef-4964-a730-bc5b86c644ba.png index 00f0f0a99..1620411d8 100644 Binary files a/docs/Miscellaneous/Images/ac019c1a-dcef-4964-a730-bc5b86c644ba.png and b/docs/Miscellaneous/Images/ac019c1a-dcef-4964-a730-bc5b86c644ba.png differ diff --git a/docs/Miscellaneous/Images/ac019c1a-dcef-4964-a730-bc5b86c644ba.svg b/docs/Miscellaneous/Images/ac019c1a-dcef-4964-a730-bc5b86c644ba.svg index c5556923a..2335646bb 100644 --- a/docs/Miscellaneous/Images/ac019c1a-dcef-4964-a730-bc5b86c644ba.svg +++ b/docs/Miscellaneous/Images/ac019c1a-dcef-4964-a730-bc5b86c644ba.svg @@ -1 +1 @@ -▾ Assets3twinBASIC_IDE_BETA_1005.zip39.3 MB5 days agoSource code (zip)Jun 29Source code (tar.gz)Jun 29sha256:0339c1f969d4b7d5f8f483767840e7ea24b373c2bfc3292869e827b571fa928d +▾ Assets3twinBASIC_IDE_BETA_1015.zip39.2 MB3 hours agoSource code (zip)Jun 29Source code (tar.gz)Jun 29sha256:300b6fb25616cd89963327b904cb00218f8519ef6554ddb2fb6a0347e8e9c0a6 diff --git a/docs/Miscellaneous/Images/e409ea37-96ad-44c5-8017-3699ef04b53d.light.png b/docs/Miscellaneous/Images/e409ea37-96ad-44c5-8017-3699ef04b53d.light.png index 483e3e395..27c2a51a7 100644 Binary files a/docs/Miscellaneous/Images/e409ea37-96ad-44c5-8017-3699ef04b53d.light.png and b/docs/Miscellaneous/Images/e409ea37-96ad-44c5-8017-3699ef04b53d.light.png differ diff --git a/docs/Miscellaneous/Images/e409ea37-96ad-44c5-8017-3699ef04b53d.png b/docs/Miscellaneous/Images/e409ea37-96ad-44c5-8017-3699ef04b53d.png index d8fa28437..c81331727 100644 Binary files a/docs/Miscellaneous/Images/e409ea37-96ad-44c5-8017-3699ef04b53d.png and b/docs/Miscellaneous/Images/e409ea37-96ad-44c5-8017-3699ef04b53d.png differ diff --git a/docs/Reference/Contributed.md b/docs/Reference/Contributed.md index 9df3f400c..2b036d947 100644 --- a/docs/Reference/Contributed.md +++ b/docs/Reference/Contributed.md @@ -13,6 +13,7 @@ Community-authored packages published through TWINSERV, the twinBASIC package re Each package is versioned apart from twinBASIC, and its section says which version it documents. Packages that are not yet ready for use in a program are listed under [Experimental Packages](../Experimental/). - [**AutoCompleteLib**](AutoCompleteLib/) -- Windows shell auto-complete for text-input controls +- [**BigNumberLib**](BigNumberLib/) -- arbitrary-precision signed integer arithmetic, up to 4096 bits - [**DetoursLib**](DetoursLib/) -- detours of functions in the program's own process, made with SlimDetours - [**FileProps**](FileProps/) -- the Windows shell properties of a file, read and written - [**Fmt**](Fmt/) -- **StringFormat**, a string built from a format string and values, in the style of C#'s **String.Format** diff --git a/docs/Reference/Contributed/BigNumberLib/BigNumber.md b/docs/Reference/Contributed/BigNumberLib/BigNumber.md index 3c56eb88a..a7ff84108 100644 --- a/docs/Reference/Contributed/BigNumberLib/BigNumber.md +++ b/docs/Reference/Contributed/BigNumberLib/BigNumber.md @@ -28,12 +28,23 @@ Debug.Print result.ValueString ' 1111111110111111111011111111100 > The class needs this build of twinBASIC or a later one. -> [!NOTE] 1.0.2.0 +> [!NOTE] 1.0.4.0 > String-to-value conversions silently stop at the first invalid character --- for example, setting `ValueHex = "ABC123he"` stores `&HABC123` without raising an error. - -> [!WARNING] 1.0.2.0 -> Overflow is not trapped. A result that needs more bits than the library holds loses its high bits, and a string with more digits than fit gives a wrong value. No error is raised in either case. The library holds a little more than the 4096 bits the class supports, 4352 bits in a 32-bit program and 4608 in a 64-bit one, so a result a few bits over 4096 may still be right. + +The library holds a little more than the 4096 bits the class supports, 4352 bits in a 32-bit program and 4608 in a 64-bit one, so a result a few bits over 4096 may still be right. [**AssignAddition**](#assignaddition), [**AssignMultiplication**](#assignmultiplication) and [**AssignShiftLeft**](#assignshiftleft) raise run-time error 6 for a result that needs more bits than the library holds, and so do [**ValueString**](#valuestring) and [**ValueHex**](#valuehex) for a string with more digits than fit. + + + +> [!WARNING] 1.0.4.0 +> Overflow is not trapped everywhere. [**AssignModulus**](#assignmodulus) and [**AssignAdditionModulus**](#assignadditionmodulus) do not return, and the program stops responding, when the dividend or the sum comes within one word (32 bits in a 32-bit program, 64 bits in a 64-bit one) of what the library holds: how close depends on the divisor. A two-factor product that **AssignMultiplication** accepts can be that large. These members raise no error when a value needs more bits than the library holds, and give a wrong result, often zero: +> +> - [**AssignSubtraction**](#assignsubtraction), and [**AssignSquared**](#assignsquared) for a square of more than about 4320 bits in a 32-bit program, or 4544 bits in a 64-bit one. +> - [**AssignMultiplication**](#assignmultiplication) for a product of more than 4320 bits (4544 in a 64-bit program) and up to one bit more than the library holds. A larger product raises error 6. +> - [**AssignAdditionModulus**](#assignadditionmodulus), [**AssignSubtractionModulus**](#assignsubtractionmodulus), [**AssignMultiplicationModulus**](#assignmultiplicationmodulus) and [**AssignSquaredModulus**](#assignsquaredmodulus), when the sum, difference, product or square that they compute before taking the remainder does not fit, even with a small modulus. For the last two, that is the case with operands of more than about 2160 bits (2270 in a 64-bit program). +> - [**ValueOctal**](#valueoctal) and [**ValueBinary**](#valuebinary), which keep only the low bits of a string with more digits than fit. +> +> Values within the limits that the class states, numbers of up to 4096 bits and multiplication operands of up to 2048 bits, are not affected. * TOC {:toc} @@ -111,28 +122,24 @@ The getter returns the digits without leading zeros, preceded by a minus sign fo ### IsNegative {: .no_toc } - + Returns or sets whether the value is negative. Syntax: *object*.**IsNegative** [ = *value* ] *value* -: A **Boolean**. Setting **False** makes the number non-negative. Setting **True** is meant to make it negative, but see the warning. - -The getter returns **True** for a negative number, and **False** for a positive number and for zero, except the negative zero that [**AssignFromLong**](#assignfromlong) describes. - +: A **Boolean**. Setting **True** makes the number negative, and setting **False** makes it non-negative. - -> [!WARNING] 1.0.2.0 -> Setting **IsNegative** to **True** does not make the number negative. The property stores -1, the value of **True**, where the library expects 1, so the number is in a state that the library does not handle: [**ValueString**](#valuestring) and the other conversions show no minus sign, **IsNegative** still returns **True**, and arithmetic with the number gives wrong results. To make a number negative, set **ValueString** to a string that starts with a minus sign, or use [**AssignNegation**](#assignnegation). [**AssignGreatestCommonDivisor**](#assigngreatestcommondivisor) and [**AssignLeastCommonMultiple**](#assignleastcommonmultiple) set this state in a negative operand. +The getter returns **True** for a negative number, and **False** for a positive number and for zero. ```tb check_build check_run Dim n As New BigNumber n.ValueString = "5" n.IsNegative = True Debug.Print n.IsNegative ' True -Debug.Print n.ValueString ' 5 +Debug.Print n.ValueString ' -5 ``` + ## Methods @@ -217,7 +224,7 @@ Debug.Print q.ValueString ' -3 ### AssignModulus {: .no_toc } - + Sets this instance to `a Mod b`. The result is zero or has the sign of *b*, so `-7 Mod 2` is 1 and `7 Mod -2` is -1. Raises run-time error 5 if *b* is zero. Syntax: *object*.**AssignModulus** *a*, *b* @@ -229,10 +236,6 @@ Syntax: *object*.**AssignModulus** *a*, *b* : *required* A **BigNumber** holding the divisor. Must not be zero. - -> [!WARNING] 1.0.2.0 -> When *b* is negative and the result is zero, the result is a negative zero: [**IsNegative**](#isnegative) returns **True** and [**IsEqualTo**](#isequalto) does not find it equal to a zero read from a string. [**AssignFromLong**](#assignfromlong) describes it. - ```tb check_build check_run Dim a As New BigNumber Dim b As New BigNumber @@ -251,7 +254,7 @@ Debug.Print r.ValueString ' -1 ### AssignSquared {: .no_toc } - + Sets this instance to `a * a` (the square of *a*). Syntax: *object*.**AssignSquared** *a* @@ -260,10 +263,6 @@ Syntax: *object*.**AssignSquared** *a* : *required* A **BigNumber** holding the value to square. - -> [!WARNING] 1.0.2.0 -> The square of zero is a negative zero, as [**AssignFromLong**](#assignfromlong) describes. - ### AssignAdditionModulus {: .no_toc } @@ -354,8 +353,8 @@ Syntax: *object*.**AssignSquaredModulus** *a*, *mod_b* ### AssignModularMultiplicativeInverse {: .no_toc } - -Sets this instance to the modular multiplicative inverse of *a* modulo *mod_b* --- the value *x* such that `(a * x) Mod mod_b = 1`. Raises run-time error 5 if the inverse does not exist, which is the case when *a* and *mod_b* have a common factor greater than 1, such as when *a* is a multiple of *mod_b*. For a negative *a* the result is negative: the inverse of -3 modulo 7 is -5, because `(-3 * -5) Mod 7` is 1. Modulo 1 there is no error: the inverse of 5 modulo 1 is 0. + +Sets this instance to the modular multiplicative inverse of *a* modulo *mod_b* --- the value *x* such that `(a * x) Mod mod_b = 1`. Raises run-time error 5 if the inverse does not exist, which is the case when *a* and *mod_b* have a common factor greater than 1, such as when *a* is a multiple of *mod_b* or is zero. For a negative *a* the result is negative: the inverse of -3 modulo 7 is -5, because `(-3 * -5) Mod 7` is 1. Modulo 1 there is no error: the inverse of 5 modulo 1 is 0. Syntax: *object*.**AssignModularMultiplicativeInverse** *a*, *mod_b* @@ -363,13 +362,9 @@ Syntax: *object*.**AssignModularMultiplicativeInverse** *a*, *mod_b* : *required* A **BigNumber** holding the value to invert. *mod_b* -: *required* A **BigNumber** holding the modulus. It must be positive. +: *required* A **BigNumber** holding the modulus. It must be positive: a zero or negative *mod_b* raises run-time error 5. - -> [!WARNING] 1.0.2.0 -> The call does not return, and the program stops responding, when *mod_b* is odd and either *a* is zero or *mod_b* is negative. A zero *a* with an even *mod_b*, and any *a* with a negative even *mod_b*, raise error 5. - ```tb check_build check_run Dim a As New BigNumber Dim m As New BigNumber @@ -389,8 +384,8 @@ Debug.Print Err.Number & " " & Err.Description ' 5 invalid operation ### AssignGreatestCommonDivisor {: .no_toc } - -Sets this instance to the greatest common divisor of *a* and *b*. The signs of *a* and *b* are ignored; the result is always non-negative. The greatest common divisor of zero and *b* is the absolute value of *b*, and that of two zeros is zero. + +Sets this instance to the greatest common divisor of *a* and *b*. The signs of *a* and *b* are ignored; the result is always non-negative, and *a* and *b* keep their values. The greatest common divisor of zero and *b* is the absolute value of *b*, and that of two zeros is zero. Syntax: *object*.**AssignGreatestCommonDivisor** *a*, *b* @@ -399,11 +394,6 @@ Syntax: *object*.**AssignGreatestCommonDivisor** *a*, *b* *b* : *required* A **BigNumber** holding the second value. - - - -> [!WARNING] 1.0.2.0 -> A negative *a* or *b* is changed by the call. The method clears the sign of each operand and puts it back with [**IsNegative**](#isnegative), which leaves the operand in the state that the warning there describes: it shows no minus sign, and arithmetic with it gives wrong results. ```tb check_build check_run Dim a As New BigNumber @@ -413,14 +403,15 @@ a.ValueString = "-12" b.ValueString = "18" g.AssignGreatestCommonDivisor a, b Debug.Print g.ValueString ' 6 -Debug.Print a.ValueString ' 12 +Debug.Print a.ValueString ' -12 ``` + ### AssignLeastCommonMultiple {: .no_toc } - -Sets this instance to the least common multiple of *a* and *b*. The signs of *a* and *b* are ignored; the result is non-negative. The least common multiple of zero and a value that is not zero is zero. + +Sets this instance to the least common multiple of *a* and *b*. The signs of *a* and *b* are ignored; the result is non-negative, and *a* and *b* keep their values. The least common multiple of zero and a value that is not zero is zero. Syntax: *object*.**AssignLeastCommonMultiple** *a*, *b* @@ -431,12 +422,8 @@ Syntax: *object*.**AssignLeastCommonMultiple** *a*, *b* : *required* A **BigNumber** holding the second value. - -> [!WARNING] 1.0.2.0 -> A negative *a* or *b* is changed by the call, as [**AssignGreatestCommonDivisor**](#assigngreatestcommondivisor) describes. - -> [!WARNING] 1.0.2.0 +> [!WARNING] 1.0.4.0 > In a 64-bit program, when *a* and *b* are both zero, this instance keeps the value it had: the result is not set to zero. In a 32-bit program the result is zero or the value the instance had, differing from one build of the program to the next. ### AssignShiftRight @@ -468,7 +455,7 @@ Debug.Print r.ValueString ' 0 ### AssignShiftLeft {: .no_toc } - + Sets this instance to *a* left-shifted by *shiftAmount_b* bits (equivalent to multiplication by 2^*shiftAmount_b*). Syntax: *object*.**AssignShiftLeft** *a*, *shiftAmount_b* @@ -477,7 +464,7 @@ Syntax: *object*.**AssignShiftLeft** *a*, *shiftAmount_b* : *required* A **BigNumber** holding the value to shift. *shiftAmount_b* -: *required* A **Long** specifying the number of bit positions to shift left. It must not be negative: a negative amount gives a wrong result, not a shift to the right. +: *required* A **Long** specifying the number of bit positions to shift left. It must not be negative: a negative amount raises run-time error 5, and this instance keeps its value. ```tb check_build check_run Dim a As New BigNumber @@ -519,29 +506,22 @@ Syntax: *object*.**AssignAbsolute** *a* ### AssignFromLong {: .no_toc } - + Sets this instance to a value from a native **Long** integer. Syntax: *object*.**AssignFromLong** *a* *a* : *required* A **Long** holding the value to assign. Negative values (including `&H80000000`) are handled correctly. - - - -> [!WARNING] 1.0.2.0 -> Assigning 0 gives a negative zero: [**IsNegative**](#isnegative) returns **True**, [**IsLessThan**](#islessthan) finds the number less than a zero read from the string `"0"`, and [**IsEqualTo**](#isequalto) does not find it equal. Its text is still `0`, and adding it to another number or subtracting it gives the right result. The same negative zero comes from [**AssignSquared**](#assignsquared) with a zero argument, and from [**AssignModulus**](#assignmodulus) when the divisor is negative and the result is zero. To get a true zero, set [**ValueString**](#valuestring) to `"0"`, or set **IsNegative** to **False** after the assignment. ```tb check_build check_run -Dim z As New BigNumber -Dim s As New BigNumber -z.AssignFromLong 0 -s.ValueString = "0" -Debug.Print z.ValueString ' 0 -Debug.Print z.IsNegative ' True -Debug.Print z.IsEqualTo(s) ' False -Debug.Print z.IsLessThan(s) ' True +Dim n As New BigNumber +n.AssignFromLong -42 +Debug.Print n.ValueString ' -42 +n.AssignFromLong &H80000000 +Debug.Print n.ValueString ' -2147483648 ``` + ### HandleError {: .no_toc } diff --git a/docs/Reference/Contributed/BigNumberLib/index.md b/docs/Reference/Contributed/BigNumberLib/index.md index e63963e17..60b36cbc8 100644 --- a/docs/Reference/Contributed/BigNumberLib/index.md +++ b/docs/Reference/Contributed/BigNumberLib/index.md @@ -1,8 +1,8 @@ --- title: BigNumberLib Package -parent: Experimental Packages +parent: Contributed Packages has_toc: false -indexed_from: 1.0.2.0 +indexed_from: 1.0.4.0 exclude_from_docs: - Absolute - AddModulus @@ -34,21 +34,18 @@ permalink: /tB/Packages/Contributed/BigNumberLib/ # BigNumberLib Package {: .no_toc } -**Author:** WaynePhillipsEA. **Version:** 1.0.2.0. **On GitHub:** [libtom/tomsfastmath](https://github.com/libtom/tomsfastmath), the C library that the package wraps. +**Author:** WaynePhillipsEA. **Version:** 1.0.4.0. **On GitHub:** [libtom/tomsfastmath](https://github.com/libtom/tomsfastmath), the C library that the package wraps. The **BigNumberLib** contributed package provides arbitrary-precision signed integer arithmetic for twinBASIC. Its one class, [**BigNumber**](BigNumber), holds an integer of up to 4096 bits. The arithmetic is done by version 0.13.1 of the TomsFastMath (libtfm) C library, which the package links as a static library, one build for 32-bit programs and one for 64-bit programs. A number is set and read as a string in decimal, hexadecimal, octal or binary, or is set from a **Long**. The class adds, subtracts, multiplies, divides and squares; takes a remainder, also of a sum, a difference, a product or a square; finds a modular inverse, a greatest common divisor and a least common multiple; shifts; and compares. - -> [!WARNING] 1.0.2.0 -> Some members give wrong results, or do not return. Each is described under its member on the [**BigNumber**](BigNumber) page: + +> [!WARNING] 1.0.4.0 +> Some members give wrong results with no error, or do not return. The [**BigNumber**](BigNumber) page describes each: > -> - Setting [**IsNegative**](BigNumber#isnegative) to **True** does not make a number negative. [**AssignGreatestCommonDivisor**](BigNumber#assigngreatestcommondivisor) and [**AssignLeastCommonMultiple**](BigNumber#assignleastcommonmultiple) leave a negative operand in the same state, with its minus sign gone. -> - [**AssignFromLong**](BigNumber#assignfromlong) with 0 gives a zero that is flagged negative, which [**IsEqualTo**](BigNumber#isequalto) does not find equal to a zero read from a string. [**AssignSquared**](BigNumber#assignsquared) of zero and [**AssignModulus**](BigNumber#assignmodulus) with a negative divisor can give the same zero. -> - [**AssignModularMultiplicativeInverse**](BigNumber#assignmodularmultiplicativeinverse) does not return when the modulus is odd and the value is zero or the modulus is negative. > - [**AssignLeastCommonMultiple**](BigNumber#assignleastcommonmultiple) of two zeros leaves the number as it was. -> - Overflow is not trapped: a result of more than the library holds, a little over 4096 bits, loses its high bits, with no error. +> - Overflow is trapped by some members only. A value of more bits than the library holds, a little over 4096, gives a wrong result with no error in subtraction, squaring, the modular operations, some multiplications, and **ValueOctal** and **ValueBinary**. A remainder of a number within one word of what the library holds does not return. ## Classes @@ -56,7 +53,7 @@ A number is set and read as a string in decimal, hexadecimal, octal or binary, o ## Test code -The package also contains **BigNumberTests**, a module with one **Sub**, **RunAllTests**, which runs the **RunTests** Sub of 22 test modules, one for each operation and each string conversion (**Addition**, **Divide**, **Modulus**, **ShiftLeft**, **ValueHex**, **Comparisons** and so on). Together they make 777 checks with **Debug.Assert**, which a built program skips. Run in the IDE, version 1.0.2.0 passes all of them. These modules have no pages of their own here. +The package also contains **BigNumberTests**, a module with one **Sub**, **RunAllTests**, which runs the **RunTests** Sub of 22 test modules, one for each operation and each string conversion (**Addition**, **Divide**, **Modulus**, **ShiftLeft**, **ValueHex**, **Comparisons** and so on). Together they make 777 checks with **Debug.Assert**, which a built program skips. Run in the IDE, version 1.0.4.0 passes all of them. These modules have no pages of their own here. **BigNumber** also declares a structure type, **fp_int**, which holds the number for the library, and a program does not use it. diff --git a/docs/Reference/Contributed/WinReg/RegCls/ConvertValueToString.md b/docs/Reference/Contributed/WinReg/RegCls/ConvertValueToString.md index faf7bba97..9e9bec8dc 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/ConvertValueToString.md +++ b/docs/Reference/Contributed/WinReg/RegCls/ConvertValueToString.md @@ -58,7 +58,7 @@ Overload 1 neither closes nor otherwise modifies *hKey*. When using Overload 1, This example opens a registry key, calls Overload 1 on a value, then closes the key. The key handle is a **LongPtr**, which the method takes as a **Long**. -```tb check_build +```tb Dim reg As New RegCls Dim hKey As LongPtr Dim ret As Long @@ -74,7 +74,7 @@ End If This example uses Overload 2 inside a value-enumeration loop. -```tb check_build +```tb Dim reg As New RegCls Dim dict As Dictionary Set dict = reg.EnumValues(HKEY_CURRENT_USER, "Software\MyApp") diff --git a/docs/Reference/Contributed/WinReg/RegCls/CreateKey.md b/docs/Reference/Contributed/WinReg/RegCls/CreateKey.md index 74ef553aa..a432ffbd2 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/CreateKey.md +++ b/docs/Reference/Contributed/WinReg/RegCls/CreateKey.md @@ -28,7 +28,7 @@ Returns **True** if the key was created or already existed, **False** if the ope This example creates a multi-level registry key under **HKEY_CURRENT_USER** and checks whether the operation succeeded. -```tb check_build +```tb Dim Reg As New RegCls Dim Success As Boolean diff --git a/docs/Reference/Contributed/WinReg/RegCls/DeleteKey.md b/docs/Reference/Contributed/WinReg/RegCls/DeleteKey.md index 74af624cd..8f2ca7b16 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/DeleteKey.md +++ b/docs/Reference/Contributed/WinReg/RegCls/DeleteKey.md @@ -26,7 +26,7 @@ Returns **True** if the key was deleted successfully, or **False** if the call f This example removes the `Settings` key under `HKEY_CURRENT_USER\Software\MyApp` and reports whether the deletion succeeded. The call fails if the key has subkeys. -```tb check_build +```tb Dim reg As New RegCls If reg.DeleteKey(HKEY_CURRENT_USER, "Software\MyApp\Settings") Then diff --git a/docs/Reference/Contributed/WinReg/RegCls/DeleteKeyEx.md b/docs/Reference/Contributed/WinReg/RegCls/DeleteKeyEx.md index 6a0225c41..b571bd86b 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/DeleteKeyEx.md +++ b/docs/Reference/Contributed/WinReg/RegCls/DeleteKeyEx.md @@ -34,7 +34,7 @@ Both enumeration loops always request index 0 and rely on each deletion to expos This example removes the `Software\MyApp` key and all of its contents from `HKEY_CURRENT_USER`. -```tb check_build +```tb Dim reg As New RegCls Dim success As Boolean diff --git a/docs/Reference/Contributed/WinReg/RegCls/DeleteValue.md b/docs/Reference/Contributed/WinReg/RegCls/DeleteValue.md index be167f787..402a888d6 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/DeleteValue.md +++ b/docs/Reference/Contributed/WinReg/RegCls/DeleteValue.md @@ -35,7 +35,7 @@ Deleting a value entry is permanent. The value cannot be recovered through this This example removes the `"RunCount"` value from `HKEY_CURRENT_USER\Software\MyApp`. If the value does not exist or the key cannot be opened, the call returns **False** and no error is raised. -```tb check_build +```tb Dim reg As New RegCls Dim bDeleted As BOOL diff --git a/docs/Reference/Contributed/WinReg/RegCls/EnumValues.md b/docs/Reference/Contributed/WinReg/RegCls/EnumValues.md index 54fc89288..a1622984d 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/EnumValues.md +++ b/docs/Reference/Contributed/WinReg/RegCls/EnumValues.md @@ -39,7 +39,7 @@ Each value's data is converted to a **String** as follows: This example enumerates all values under a registry key and prints each name and its data to the debug console. -```tb check_build +```tb Dim reg As New RegCls Dim dict As Dictionary Dim key As Variant diff --git a/docs/Reference/Contributed/WinReg/RegCls/GetRegistryValueType.md b/docs/Reference/Contributed/WinReg/RegCls/GetRegistryValueType.md index dcdf52e7b..e7eefdc40 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/GetRegistryValueType.md +++ b/docs/Reference/Contributed/WinReg/RegCls/GetRegistryValueType.md @@ -34,7 +34,7 @@ If the key cannot be opened or the value query fails, the function returns `REGT This example reads the data type of the `UserName` value under `HKEY_CURRENT_USER\Software\MyApp` and displays a message describing the type. -```tb check_build +```tb Dim reg As New RegCls Dim t As REGTYPES diff --git a/docs/Reference/Contributed/WinReg/RegCls/KeyExists.md b/docs/Reference/Contributed/WinReg/RegCls/KeyExists.md index 1af5bb78e..6556c37dc 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/KeyExists.md +++ b/docs/Reference/Contributed/WinReg/RegCls/KeyExists.md @@ -27,7 +27,7 @@ No error is raised when the key does not exist. On any failure, including access This example checks for a registry key before attempting to read a value from it. -```tb check_build +```tb Dim reg As New RegCls If reg.KeyExists(HKEY_CURRENT_USER, "Software\MyApp") Then diff --git a/docs/Reference/Contributed/WinReg/RegCls/ReadDWORD.md b/docs/Reference/Contributed/WinReg/RegCls/ReadDWORD.md index 748fdc9bf..68c2b08b3 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/ReadDWORD.md +++ b/docs/Reference/Contributed/WinReg/RegCls/ReadDWORD.md @@ -37,7 +37,7 @@ Registry DWORD values are 32-bit unsigned integers; the Windows API stores them This example reads a run-count value from the registry, increments it, and writes it back. -```tb check_build +```tb Dim reg As New RegCls Dim RunCount As Long diff --git a/docs/Reference/Contributed/WinReg/RegCls/ReadString.md b/docs/Reference/Contributed/WinReg/RegCls/ReadString.md index 23d93304b..1a79b37ff 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/ReadString.md +++ b/docs/Reference/Contributed/WinReg/RegCls/ReadString.md @@ -40,7 +40,7 @@ The function uses `On Error Resume Next` internally. Errors from the Win32 regis This example reads an application setting stored under `HKEY_CURRENT_USER`, falling back to a hard-coded default when the value is absent. -```tb check_build +```tb Dim Reg As New RegCls Dim UserName As String @@ -50,7 +50,7 @@ Debug.Print "User: " & UserName This example cuts the result at the first NUL character, which leaves the stored text, or the default: -```tb check_build +```tb Dim Reg As New RegCls Dim UserName As String @@ -61,7 +61,7 @@ Debug.Print "User: " & UserName This example checks whether a value was present by comparing the result against the default: -```tb check_build +```tb Dim Reg As New RegCls Const NotFound As String = "" diff --git a/docs/Reference/Contributed/WinReg/RegCls/ValueExists.md b/docs/Reference/Contributed/WinReg/RegCls/ValueExists.md index 429a0f9bc..31e09ffbc 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/ValueExists.md +++ b/docs/Reference/Contributed/WinReg/RegCls/ValueExists.md @@ -32,7 +32,7 @@ To test whether a key itself exists---rather than a value within it---use [**Key This example checks whether a user preference value is present before reading it. -```tb check_build +```tb Dim reg As New RegCls If reg.ValueExists(HKEY_CURRENT_USER, "Software\MyApp", "UserName") Then diff --git a/docs/Reference/Contributed/WinReg/RegCls/WriteDWORD.md b/docs/Reference/Contributed/WinReg/RegCls/WriteDWORD.md index bf8848fe4..783b1f5ed 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/WriteDWORD.md +++ b/docs/Reference/Contributed/WinReg/RegCls/WriteDWORD.md @@ -40,7 +40,7 @@ The value is stored as a little-endian 32-bit integer, which is the standard **R This example stores an application run count and a feature flag under `HKEY_CURRENT_USER`. -```tb check_build +```tb Dim reg As New RegCls If reg.WriteDWORD(HKEY_CURRENT_USER, "Software\MyApp", "RunCount", 1) Then diff --git a/docs/Reference/Contributed/WinReg/RegCls/WriteString.md b/docs/Reference/Contributed/WinReg/RegCls/WriteString.md index 3b02f5cea..3df25bdc5 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/WriteString.md +++ b/docs/Reference/Contributed/WinReg/RegCls/WriteString.md @@ -36,7 +36,7 @@ The return value is a **BOOL**: **True** if the value was written successfully, This example writes a user name string under `HKEY_CURRENT_USER`. -```tb check_build +```tb Dim reg As New RegCls If reg.WriteString(HKEY_CURRENT_USER, "Software\MyApp", "UserName", "Alice") Then diff --git a/docs/Reference/Contributed/WinReg/RegCls/index.md b/docs/Reference/Contributed/WinReg/RegCls/index.md index 20012cd1b..63aaf7982 100644 --- a/docs/Reference/Contributed/WinReg/RegCls/index.md +++ b/docs/Reference/Contributed/WinReg/RegCls/index.md @@ -12,7 +12,7 @@ A Windows Registry helper class that reads, writes, deletes, and enumerates regi **RegCls** wraps the most common registry operations---reading and writing string and DWORD values, creating and deleting keys, checking whether a key or value exists, and enumerating all values under a key---into a single class. It declares the [**RegKeyspace**](../RegKeyspace) and [**enumRegSzType**](../enumRegSzType) enumerations and its own copies of the `advapi32` declarations it uses, and takes `RegOpenKeyEx`, `RegSetValueEx` and the types **BOOL** and **REGTYPES** from the **WinDevLib** package. A comment in the source recommends the declarations of **WinDevLib** over the class's own. -```tb check_build +```tb Dim reg As New RegCls ' Write a value @@ -313,7 +313,7 @@ Registry handles are closed with `RegCloseKey` in every code path where `RegOpen This example stores and retrieves application settings. -```tb check_build +```tb Dim reg As New RegCls Const AppKey As String = "Software\MyApp" diff --git a/docs/Reference/Contributed/WinReg/RegKeyspace.md b/docs/Reference/Contributed/WinReg/RegKeyspace.md index 5324f519c..331787a29 100644 --- a/docs/Reference/Contributed/WinReg/RegKeyspace.md +++ b/docs/Reference/Contributed/WinReg/RegKeyspace.md @@ -29,7 +29,7 @@ The enumeration is declared inside the [**RegCls**](RegCls/) class, and its memb The high bit of every value is set, so each value is a negative **Long**: `CLng(RegKeyspace.HKEY_CURRENT_USER)` is -2147483647. -```tb check_build +```tb Debug.Print Hex$(RegKeyspace.HKEY_CLASSES_ROOT) ' 80000000 Debug.Print Hex$(RegKeyspace.HKEY_CURRENT_USER) ' 80000001 Debug.Print CLng(RegKeyspace.HKEY_CURRENT_USER) ' -2147483647 @@ -37,7 +37,7 @@ Debug.Print CLng(RegKeyspace.HKEY_CURRENT_USER) ' -2147483647 The **WinDevLib** package declares an enumeration of the same name with the same members and values. A project that references both **WinReg** and **WinDevLib** has two enumerations named **RegKeyspace**, and `WinReg.RegKeyspace` names this one. A member of either is accepted as an argument of a **RegCls** method. -```tb check_build +```tb Dim reg As New RegCls Dim root As WinReg.RegKeyspace diff --git a/docs/Reference/Contributed/WinReg/enumRegSzType.md b/docs/Reference/Contributed/WinReg/enumRegSzType.md index 3f92a5bbb..82e2efb5d 100644 --- a/docs/Reference/Contributed/WinReg/enumRegSzType.md +++ b/docs/Reference/Contributed/WinReg/enumRegSzType.md @@ -31,7 +31,7 @@ The enumeration is declared inside the **RegCls** class, and its members are wri [**EnumValues**](RegCls/EnumValues) converts the data of **REG_SZ**, **REG_EXPAND_SZ**, **REG_DWORD**, **REG_DWORD_LITTLE_ENDIAN**, **REG_DWORD_BIG_ENDIAN** and **REG_BINARY** values to text, and gives `"Unsupported type: "` and the code for every other type. -```tb check_build +```tb Debug.Print enumRegSzType.REG_SZ ' 1 Debug.Print enumRegSzType.REG_DWORD ' 4 Debug.Print enumRegSzType.REG_MULTI_SZ ' 7 diff --git a/docs/Reference/Data-Types/String.md b/docs/Reference/Data-Types/String.md index fa9085ce0..13f68aa9a 100644 --- a/docs/Reference/Data-Types/String.md +++ b/docs/Reference/Data-Types/String.md @@ -48,11 +48,11 @@ Debug.Print Len(Pair) ' 2 ## Fixed-length strings -A fixed-length **String** always has the length it is declared with. A value shorter than that is padded on the right with spaces when it is assigned, and a longer one is cut off. `LenB` is twice the length, and a fixed-length member of a **Type** takes that many bytes. Join a fixed-length string to another with `&`, and the result is a variable-length **String**. +A fixed-length **String** always has the length it is declared with. Until a value is assigned, each of its characters is `Chr(0)`. A value shorter than that is padded on the right with spaces when it is assigned, and a longer one is cut off. `LenB` is twice the length, and a fixed-length member of a **Type** takes that many bytes. Join a fixed-length string to another with `&`, and the result is a variable-length **String**. ```tb check_run Dim Code As String * 3 -Debug.Print "[" & Code & "]" ' [ ] +Debug.Print AscW(Code) ' 0 Code = "a" Debug.Print "[" & Code & "]" ' [a ] Code = "abcdef" diff --git a/docs/Reference/Default/VBA/Conversion/CStr.md b/docs/Reference/Default/VBA/Conversion/CStr.md index f2377004f..c12692f61 100644 --- a/docs/Reference/Default/VBA/Conversion/CStr.md +++ b/docs/Reference/Default/VBA/Conversion/CStr.md @@ -29,6 +29,9 @@ The return type is **String**. The result depends on the type of *expression*: **CStr** is the internationally aware alternative to [**Str**](Str) for converting a number to a string. **CStr** recognizes different decimal separators properly, depending on the system's locale setting. +> [!WARNING] BETA 1010 +> A 64-bit build converts a negative zero of type **Single** or **Double** (a value that equals 0 and has its sign bit set) to `"-0"`. A 32-bit build and VB6 give `"0"`. The same happens when such a value is joined to a string with `&`. + ### Example This example uses the **CStr** function to convert a numeric value to a **String**. diff --git a/docs/Reference/Default/VBA/Conversion/Str.md b/docs/Reference/Default/VBA/Conversion/Str.md index f9ee62efb..8e87e5de8 100644 --- a/docs/Reference/Default/VBA/Conversion/Str.md +++ b/docs/Reference/Default/VBA/Conversion/Str.md @@ -25,6 +25,9 @@ When numbers are converted to strings, a leading space is always reserved for th Use the [**Format**](../Strings/Format) function to convert numeric values to be formatted as dates, times, or currency, or in other user-defined formats. Unlike **Str**, the **Format** function doesn't include a leading space for the sign of *number*. +> [!WARNING] BETA 1010 +> A 64-bit build converts a negative zero of type **Single** or **Double** (a value that equals 0 and has its sign bit set) to `"-0"`, with no leading space. A 32-bit build and VB6 give `" 0"`. + > [!NOTE] > The **Str** function recognizes only the period (`.`) as a valid decimal separator. When different decimal separators may be used (for example, in international applications), use [**CStr**](CStr) to convert a number to a string. diff --git a/docs/Reference/Default/VBA/Strings/Format.md b/docs/Reference/Default/VBA/Strings/Format.md index 925d597ec..c3316281f 100644 --- a/docs/Reference/Default/VBA/Strings/Format.md +++ b/docs/Reference/Default/VBA/Strings/Format.md @@ -58,6 +58,9 @@ The *firstWeekOfYear* argument has these settings. When formatting a number without specifying *format*, **Format** provides functionality similar to the **Str** function, although it is internationally aware. However, positive numbers formatted as strings using **Format** don't include a leading space reserved for the sign of the value; those converted using **Str** retain the leading space. +> [!WARNING] BETA 1010 +> A 64-bit build formats a negative zero of type **Single** or **Double** (a value that equals 0 and has its sign bit set) as `"-0"` when *format* is omitted. A 32-bit build and VB6 give `"0"`. + When formatting a non-localized numeric string, use a user-defined numeric format to ensure the desired appearance. > [!NOTE] diff --git a/docs/Reference/Experimental.md b/docs/Reference/Experimental.md index 8c06c5abe..0c3ac0d2b 100644 --- a/docs/Reference/Experimental.md +++ b/docs/Reference/Experimental.md @@ -13,7 +13,6 @@ Community-authored packages from TWINSERV that are not yet ready for use in a pr These packages are published through TWINSERV, as the [Contributed Packages](../Contributed/) are, and are documented in the same way. A package is listed here when its newest version does not compile in the current twinBASIC, or when it has defects that a program would meet. Each section says which version it documents and what does not work yet. A package moves to the Contributed Packages once a version of it works, and its pages keep their addresses. - [**ArrayListLib**](../Contributed/ArrayListLib/) -- a list class in place of .NET's `ArrayList`. Version 1.6.151.1 does not compile in twinBASIC BETA 1010, and in a copy that does, a **For Each** over a list with no items fails, **ToString** of such a list never returns, **Reverse** leaves the two middle items of an even run in place, and a second **GetEnumerator** over the same list ignores its arguments. -- [**BigNumberLib**](../Contributed/BigNumberLib/) -- arbitrary-precision signed integer arithmetic. Version 1.0.2.0 compiles, and has several members that give wrong results or do not return: setting **IsNegative** to **True**, a negative operand of the greatest common divisor and the least common multiple, the least common multiple of two zeros, a zero from **AssignFromLong**, and the modular inverse of zero. - [**GdiPlus**](../Contributed/GdiPlus/) -- Windows GDI+: lines, shapes, text and images drawn with pens, brushes, fonts, paths and transformations. Version 0.9.45.0 compiles, and has many members that give wrong results, fail or do not return: a colour given as a **Long** has its red and blue swapped and loses its alpha, saving an image with encoder parameters fails, the font collections cannot be created, and several path, metafile and effect members fail. - [**TBMANLIB**](../Contributed/TBMANLIB/) -- a toolkit of helpers: JSON, an HTTP client, logs, INI and CSV files, timers, strings, bytes, files and dictionaries. Version 1.0.0.29 compiles for 32-bit programs, does not compile in a 64-bit build, and has several members that fail or give wrong results. - [**TBMANLIB_Aes**](../Contributed/TBMANLIB_Aes/) -- AES encryption of text and byte arrays. Version 1.0.0.4 compiles, and its cipher modes are not the ones their names say: the default mode, CBC, runs ECB, and the output does not match the standard test vectors. diff --git a/docs/Reference/Images/TYizrRW.light.png b/docs/Reference/Images/TYizrRW.light.png index 0b319ae5e..17c359bc8 100644 Binary files a/docs/Reference/Images/TYizrRW.light.png and b/docs/Reference/Images/TYizrRW.light.png differ diff --git a/docs/Reference/Images/TYizrRW.png b/docs/Reference/Images/TYizrRW.png index bfc2bab25..af2b6ce09 100644 Binary files a/docs/Reference/Images/TYizrRW.png and b/docs/Reference/Images/TYizrRW.png differ diff --git a/docs/Reference/Images/flags-attribute.light.png b/docs/Reference/Images/flags-attribute.light.png index 3f5e6c738..3c81f9b80 100644 Binary files a/docs/Reference/Images/flags-attribute.light.png and b/docs/Reference/Images/flags-attribute.light.png differ diff --git a/docs/Reference/Images/flags-attribute.png b/docs/Reference/Images/flags-attribute.png index 2cb8a8cf8..b81710a15 100644 Binary files a/docs/Reference/Images/flags-attribute.png and b/docs/Reference/Images/flags-attribute.png differ diff --git a/docs/Reference/Images/oHpCiV1.light.png b/docs/Reference/Images/oHpCiV1.light.png index b9e0c5b4b..f67203d32 100644 Binary files a/docs/Reference/Images/oHpCiV1.light.png and b/docs/Reference/Images/oHpCiV1.light.png differ diff --git a/docs/Reference/Images/oHpCiV1.png b/docs/Reference/Images/oHpCiV1.png index ab8b4d2e9..da0c48ad9 100644 Binary files a/docs/Reference/Images/oHpCiV1.png and b/docs/Reference/Images/oHpCiV1.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccCOMCreatable.light.png b/docs/Tutorials/CustomControls/Images/ccCOMCreatable.light.png index 4d8d45409..017108673 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccCOMCreatable.light.png and b/docs/Tutorials/CustomControls/Images/ccCOMCreatable.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccCOMCreatable.png b/docs/Tutorials/CustomControls/Images/ccCOMCreatable.png index 0d0201ee3..fc2e87232 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccCOMCreatable.png and b/docs/Tutorials/CustomControls/Images/ccCOMCreatable.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccClassIdAttribute.light.png b/docs/Tutorials/CustomControls/Images/ccClassIdAttribute.light.png index 029d2aaf0..6d638dcd6 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccClassIdAttribute.light.png and b/docs/Tutorials/CustomControls/Images/ccClassIdAttribute.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccClassIdAttribute.png b/docs/Tutorials/CustomControls/Images/ccClassIdAttribute.png index c507ffcc8..16fb89080 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccClassIdAttribute.png and b/docs/Tutorials/CustomControls/Images/ccClassIdAttribute.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccClassIdInsert.light.png b/docs/Tutorials/CustomControls/Images/ccClassIdInsert.light.png index 08f71039e..a2c64f761 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccClassIdInsert.light.png and b/docs/Tutorials/CustomControls/Images/ccClassIdInsert.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccClassIdInsert.png b/docs/Tutorials/CustomControls/Images/ccClassIdInsert.png index b7b8d4b07..db60e4663 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccClassIdInsert.png and b/docs/Tutorials/CustomControls/Images/ccClassIdInsert.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccCustomControlAttribute.light.png b/docs/Tutorials/CustomControls/Images/ccCustomControlAttribute.light.png index 8d8a42fc4..8136ed235 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccCustomControlAttribute.light.png and b/docs/Tutorials/CustomControls/Images/ccCustomControlAttribute.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccCustomControlAttribute.png b/docs/Tutorials/CustomControls/Images/ccCustomControlAttribute.png index 7b50010ac..efc55b076 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccCustomControlAttribute.png and b/docs/Tutorials/CustomControls/Images/ccCustomControlAttribute.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccEvents.light.svg b/docs/Tutorials/CustomControls/Images/ccEvents.light.svg index d78074804..5bb4ab0db 100644 --- a/docs/Tutorials/CustomControls/Images/ccEvents.light.svg +++ b/docs/Tutorials/CustomControls/Images/ccEvents.light.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32TOOLBOXEDITOR 1MyButton.twinfrmCustom.tbformMyGrid.twin +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32TOOLBOXEDITOR 1MyButton.twinfrmCustom.tbformMyGrid.twin diff --git a/docs/Tutorials/CustomControls/Images/ccEvents.png b/docs/Tutorials/CustomControls/Images/ccEvents.png index 92533a339..e4822ba0b 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccEvents.png and b/docs/Tutorials/CustomControls/Images/ccEvents.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccEvents.svg b/docs/Tutorials/CustomControls/Images/ccEvents.svg index 47621bbaf..763ad0773 100644 --- a/docs/Tutorials/CustomControls/Images/ccEvents.svg +++ b/docs/Tutorials/CustomControls/Images/ccEvents.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32TOOLBOXEDITOR 1MyButton.twinfrmCustom.tbformMyGrid.twin +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32TOOLBOXEDITOR 1MyButton.twinfrmCustom.tbformMyGrid.twin diff --git a/docs/Tutorials/CustomControls/Images/ccGridButtonImage.light.png b/docs/Tutorials/CustomControls/Images/ccGridButtonImage.light.png index b09a822bc..3c5400a07 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccGridButtonImage.light.png and b/docs/Tutorials/CustomControls/Images/ccGridButtonImage.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccGridButtonImage.png b/docs/Tutorials/CustomControls/Images/ccGridButtonImage.png index 8db8aeffa..2a6f78980 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccGridButtonImage.png and b/docs/Tutorials/CustomControls/Images/ccGridButtonImage.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccICustomControl.light.png b/docs/Tutorials/CustomControls/Images/ccICustomControl.light.png index b3ad1549b..c2d2fe60f 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccICustomControl.light.png and b/docs/Tutorials/CustomControls/Images/ccICustomControl.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccICustomControl.png b/docs/Tutorials/CustomControls/Images/ccICustomControl.png index 27f0279f2..52b59fb40 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccICustomControl.png and b/docs/Tutorials/CustomControls/Images/ccICustomControl.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.light.png b/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.light.png index 05cb568ba..5be0717a8 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.light.png and b/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.light.svg b/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.light.svg index 15156eec5..74c547a3e 100644 --- a/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.light.svg +++ b/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.light.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents.EDITOR 1MyGrid.twinfrmCustom.tbform +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents.EDITOR 1MyGrid.twinfrmCustom.tbform diff --git a/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.png b/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.png index d2130fbec..cfbae35e1 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.png and b/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.svg b/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.svg index db58311ac..be9803564 100644 --- a/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.svg +++ b/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyGrid.twinfrmCustom.tbform +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyGrid.twinfrmCustom.tbform diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldArray.light.png b/docs/Tutorials/CustomControls/Images/ccMyFieldArray.light.png index c768bfb1b..517ffca6d 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccMyFieldArray.light.png and b/docs/Tutorials/CustomControls/Images/ccMyFieldArray.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldArray.light.svg b/docs/Tutorials/CustomControls/Images/ccMyFieldArray.light.svg index 1c89152bc..f05b69ef2 100644 --- a/docs/Tutorials/CustomControls/Images/ccMyFieldArray.light.svg +++ b/docs/Tutorials/CustomControls/Images/ccMyFieldArray.light.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyButton.twinfrmCustom.tbformMyGrid.twin +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyButton.twinfrmCustom.tbformMyGrid.twin diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldArray.png b/docs/Tutorials/CustomControls/Images/ccMyFieldArray.png index e4b19bbcd..b6a1717ea 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccMyFieldArray.png and b/docs/Tutorials/CustomControls/Images/ccMyFieldArray.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldArray.svg b/docs/Tutorials/CustomControls/Images/ccMyFieldArray.svg index e91ef71f1..1748bc12b 100644 --- a/docs/Tutorials/CustomControls/Images/ccMyFieldArray.svg +++ b/docs/Tutorials/CustomControls/Images/ccMyFieldArray.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyButton.twinfrmCustom.tbformMyGrid.twin +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyButton.twinfrmCustom.tbformMyGrid.twin diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldClass.light.png b/docs/Tutorials/CustomControls/Images/ccMyFieldClass.light.png index 695a5db38..922fa1b69 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccMyFieldClass.light.png and b/docs/Tutorials/CustomControls/Images/ccMyFieldClass.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldClass.light.svg b/docs/Tutorials/CustomControls/Images/ccMyFieldClass.light.svg index f692858df..565927d11 100644 --- a/docs/Tutorials/CustomControls/Images/ccMyFieldClass.light.svg +++ b/docs/Tutorials/CustomControls/Images/ccMyFieldClass.light.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32100%TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyButton.twinfrmCustom.tbform480 x 320 +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelp• project.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32100%TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyButton.twinfrmCustom.tbform480 x 320 diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldClass.png b/docs/Tutorials/CustomControls/Images/ccMyFieldClass.png index 8bcd4c661..f186fa1b4 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccMyFieldClass.png and b/docs/Tutorials/CustomControls/Images/ccMyFieldClass.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldClass.svg b/docs/Tutorials/CustomControls/Images/ccMyFieldClass.svg index 2cc3f489b..f2ea06c9b 100644 --- a/docs/Tutorials/CustomControls/Images/ccMyFieldClass.svg +++ b/docs/Tutorials/CustomControls/Images/ccMyFieldClass.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpproject.twinproj - twinBASIC (twinBASIC IDE BETA 1005)win32100%TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyButton.twinfrmCustom.tbform480 x 320 +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpproject.twinproj - twinBASIC (twinBASIC IDE BETA 1010)win32100%TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyButton.twinfrmCustom.tbform480 x 320 diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldCustomProperty.light.png b/docs/Tutorials/CustomControls/Images/ccMyFieldCustomProperty.light.png index 272054b2a..80f2d0b62 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccMyFieldCustomProperty.light.png and b/docs/Tutorials/CustomControls/Images/ccMyFieldCustomProperty.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldCustomProperty.png b/docs/Tutorials/CustomControls/Images/ccMyFieldCustomProperty.png index d85b242bb..e2c067513 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccMyFieldCustomProperty.png and b/docs/Tutorials/CustomControls/Images/ccMyFieldCustomProperty.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldJson1a.light.png b/docs/Tutorials/CustomControls/Images/ccMyFieldJson1a.light.png index 5da81a1fb..9acfcf9dd 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccMyFieldJson1a.light.png and b/docs/Tutorials/CustomControls/Images/ccMyFieldJson1a.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldJson1a.png b/docs/Tutorials/CustomControls/Images/ccMyFieldJson1a.png index 5915bc9b2..bf716cddc 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccMyFieldJson1a.png and b/docs/Tutorials/CustomControls/Images/ccMyFieldJson1a.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1a.light.svg b/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1a.light.svg index 7b7dc49c4..dd91d9214 100644 --- a/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1a.light.svg +++ b/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1a.light.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyGrid.twinfrmCustom.tbform +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyGrid.twinfrmCustom.tbform diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1a.svg b/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1a.svg index e553004ef..2cef5d909 100644 --- a/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1a.svg +++ b/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1a.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyGrid.twinfrmCustom.tbform +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyGrid.twinfrmCustom.tbform diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1b.light.svg b/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1b.light.svg index ed7d24240..237a102ea 100644 --- a/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1b.light.svg +++ b/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1b.light.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyGrid.twinfrmCustom.tbform +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyGrid.twinfrmCustom.tbform diff --git a/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1b.svg b/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1b.svg index 29818ce5c..d8d08de58 100644 --- a/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1b.svg +++ b/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1b.svg @@ -1 +1 @@ -FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyGrid.twinfrmCustom.tbform +FileEditViewProjectFormatDebugRunToolsAdd-InsWindowHelpwin32TOOLBOXCustomControlsDemoMorecomponents...EDITOR 1MyGrid.twinfrmCustom.tbform diff --git a/docs/Tutorials/CustomControls/Images/ccSampleProject.light.png b/docs/Tutorials/CustomControls/Images/ccSampleProject.light.png index d50f980d2..c18bc7c88 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccSampleProject.light.png and b/docs/Tutorials/CustomControls/Images/ccSampleProject.light.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccSampleProject.light.svg b/docs/Tutorials/CustomControls/Images/ccSampleProject.light.svg index 8c9ffa0b9..94111890f 100644 --- a/docs/Tutorials/CustomControls/Images/ccSampleProject.light.svg +++ b/docs/Tutorials/CustomControls/Images/ccSampleProject.light.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentSample 3. MyCodeLibrarySample 4. MyVBEAddin (NEW with ToolWindow)Sample 5. MyCOMAddinSample 6. CustomControlsSample 7. PackageSample 8. FilePropertyViewer (CustomControls)Sample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE Addin12 +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentSample 3. MyCodeLibrarySample 4. MyVBEAddin (NEW with ToolWindow)Sample 5. MyCOMAddinSample 6. CustomControlsSample 7. PackageSample 8. FilePropertyViewer (CustomControls)Sample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE Addin12 diff --git a/docs/Tutorials/CustomControls/Images/ccSampleProject.png b/docs/Tutorials/CustomControls/Images/ccSampleProject.png index 5d76986ac..adab63da6 100644 Binary files a/docs/Tutorials/CustomControls/Images/ccSampleProject.png and b/docs/Tutorials/CustomControls/Images/ccSampleProject.png differ diff --git a/docs/Tutorials/CustomControls/Images/ccSampleProject.svg b/docs/Tutorials/CustomControls/Images/ccSampleProject.svg index 4c2536307..e9dbbfc99 100644 --- a/docs/Tutorials/CustomControls/Images/ccSampleProject.svg +++ b/docs/Tutorials/CustomControls/Images/ccSampleProject.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentSample 3. MyCodeLibrarySample 4. MyVBEAddin (NEW with ToolWindow)Sample 5. MyCOMAddinSample 6. CustomControlsSample 7. PackageSample 8. FilePropertyViewer (CustomControls)Sample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE Addin12 +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentSample 3. MyCodeLibrarySample 4. MyVBEAddin (NEW with ToolWindow)Sample 5. MyCOMAddinSample 6. CustomControlsSample 7. PackageSample 8. FilePropertyViewer (CustomControls)Sample 9. ActiveX Control WebView2 + MonacoSample 10. twinBASIC IDE Addin12 diff --git a/docs/Tutorials/WebView2/Images/tbWebView2CreateEvent.light.png b/docs/Tutorials/WebView2/Images/tbWebView2CreateEvent.light.png index 179b57170..58070e4ca 100644 Binary files a/docs/Tutorials/WebView2/Images/tbWebView2CreateEvent.light.png and b/docs/Tutorials/WebView2/Images/tbWebView2CreateEvent.light.png differ diff --git a/docs/Tutorials/WebView2/Images/tbWebView2CreateEvent.png b/docs/Tutorials/WebView2/Images/tbWebView2CreateEvent.png index 52f7c54ac..4cd620e94 100644 Binary files a/docs/Tutorials/WebView2/Images/tbWebView2CreateEvent.png and b/docs/Tutorials/WebView2/Images/tbWebView2CreateEvent.png differ diff --git a/docs/Tutorials/WebView2/Images/tbWebView2Properties.light.png b/docs/Tutorials/WebView2/Images/tbWebView2Properties.light.png index 79b2f2a04..44b5a9055 100644 Binary files a/docs/Tutorials/WebView2/Images/tbWebView2Properties.light.png and b/docs/Tutorials/WebView2/Images/tbWebView2Properties.light.png differ diff --git a/docs/Tutorials/WebView2/Images/tbWebView2Properties.light.svg b/docs/Tutorials/WebView2/Images/tbWebView2Properties.light.svg index bdf85d081..6a10dc5a9 100644 --- a/docs/Tutorials/WebView2/Images/tbWebView2Properties.light.svg +++ b/docs/Tutorials/WebView2/Images/tbWebView2Properties.light.svg @@ -1 +1 @@ -win32DIAGNOSTICS000300 x 300PROPERTIESGENERALHeight3600Anchors▶... { AnchorsData }Dock0 - vbDockNoneAdditionalAllowedFrameAncestorsAreBrowserAcceleratorKeysEnabledTrueAreDefaultContextMenusEnabledTrueAreDefaultScriptDialogsEnabledTrueAreDevToolsEnabledTrueAreHostObjectsAllowedTrueDocumentURLEnvironmentOptions▶... { WebView2EnvironmentOptions }IsBuiltInErrorPageEnabledTrueIsGeneralAutoFillEnabledTrueIsMutedFalseIsPasswordAutoSaveEnabledTrueIsPinchZoomEnabledTrueIsScriptEnabledTrueIsStatusBarEnabledTrueIsSwipeNavigationEnabledTrueIsWebMessageEnabledTrueIsZoomControlEnabledTrueTagUseDeferredEventsTrueUserAgentZoomFactor0Web1    WebView2 +win32DIAGNOSTICS000300 x 300PROPERTIESGENERALAnchors▶... { AnchorsData }Dock0 - vbDockNoneDockOrder0AdditionalAllowedFrameAncestorsAreBrowserAcceleratorKeysEnabledTrueAreDefaultContextMenusEnabledTrueAreDefaultScriptDialogsEnabledTrueAreDevToolsEnabledTrueAreHostObjectsAllowedTrueDocumentURLEnvironmentOptions▶... { WebView2EnvironmentOptions }IsBuiltInErrorPageEnabledTrueIsGeneralAutoFillEnabledTrueIsMutedFalseIsPasswordAutoSaveEnabledTrueIsPinchZoomEnabledTrueIsScriptEnabledTrueIsStatusBarEnabledTrueIsSwipeNavigationEnabledTrueIsWebMessageEnabledTrueIsZoomControlEnabledTrueTagUseDeferredEventsTrueUserAgentZoomFactor0Web1    WebView2 diff --git a/docs/Tutorials/WebView2/Images/tbWebView2Properties.png b/docs/Tutorials/WebView2/Images/tbWebView2Properties.png index b16b4c175..8696e92c7 100644 Binary files a/docs/Tutorials/WebView2/Images/tbWebView2Properties.png and b/docs/Tutorials/WebView2/Images/tbWebView2Properties.png differ diff --git a/docs/Tutorials/WebView2/Images/tbWebView2Properties.svg b/docs/Tutorials/WebView2/Images/tbWebView2Properties.svg index c1ef28694..419614c2c 100644 --- a/docs/Tutorials/WebView2/Images/tbWebView2Properties.svg +++ b/docs/Tutorials/WebView2/Images/tbWebView2Properties.svg @@ -1 +1 @@ -win32DIAGNOSTICS000300 x 300PROPERTIESGENERALWidth3900Height3600Anchors▶... { AnchorsData }Dock0 - vbDockNoneAdditionalAllowedFrameAncestorsAreBrowserAcceleratorKeysEnabledTrueAreDefaultContextMenusEnabledTrueAreDefaultScriptDialogsEnabledTrueAreDevToolsEnabledTrueAreHostObjectsAllowedTrueDocumentURLEnvironmentOptions▶... { WebView2EnvironmentOptions }IsBuiltInErrorPageEnabledTrueIsGeneralAutoFillEnabledTrueIsMutedFalseIsPasswordAutoSaveEnabledTrueIsPinchZoomEnabledTrueIsScriptEnabledTrueIsStatusBarEnabledTrueIsSwipeNavigationEnabledTrueIsWebMessageEnabledTrueIsZoomControlEnabledTrueTagUseDeferredEventsTrueUserAgentZoomFactor0Web1    WebView2 +win32DIAGNOSTICS000300 x 300PROPERTIESGENERALHeight3600Anchors▶... { AnchorsData }Dock0 - vbDockNoneDockOrder0AdditionalAllowedFrameAncestorsAreBrowserAcceleratorKeysEnabledTrueAreDefaultContextMenusEnabledTrueAreDefaultScriptDialogsEnabledTrueAreDevToolsEnabledTrueAreHostObjectsAllowedTrueDocumentURLEnvironmentOptions▶... { WebView2EnvironmentOptions }IsBuiltInErrorPageEnabledTrueIsGeneralAutoFillEnabledTrueIsMutedFalseIsPasswordAutoSaveEnabledTrueIsPinchZoomEnabledTrueIsScriptEnabledTrueIsStatusBarEnabledTrueIsSwipeNavigationEnabledTrueIsWebMessageEnabledTrueIsZoomControlEnabledTrueTagUseDeferredEventsTrueUserAgentZoomFactor0Web1    WebView2 diff --git a/docs/Tutorials/WebView2/Images/tbWebView2Sample0.light.png b/docs/Tutorials/WebView2/Images/tbWebView2Sample0.light.png index 40655cf81..f856f1ded 100644 Binary files a/docs/Tutorials/WebView2/Images/tbWebView2Sample0.light.png and b/docs/Tutorials/WebView2/Images/tbWebView2Sample0.light.png differ diff --git a/docs/Tutorials/WebView2/Images/tbWebView2Sample0.light.svg b/docs/Tutorials/WebView2/Images/tbWebView2Sample0.light.svg index c77a1d11d..b33574bf0 100644 --- a/docs/Tutorials/WebView2/Images/tbWebView2Sample0.light.svg +++ b/docs/Tutorials/WebView2/Images/tbWebView2Sample0.light.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentSample 0. Reports (Experimental)Sample 1. HelloWorldSample 1a. WebView2 ExamplesSample 1b. Chromium Embedded Framework ExamplesSample 2. GetIPAddressesSample 3. MyCodeLibrary +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentSample 0. Reports (Experimental)Sample 1. HelloWorldSample 1a. WebView2 ExamplesSample 1b. Chromium Embedded Framework ExamplesSample 2. GetIPAddressesSample 3. MyCodeLibrary diff --git a/docs/Tutorials/WebView2/Images/tbWebView2Sample0.png b/docs/Tutorials/WebView2/Images/tbWebView2Sample0.png index 5b7f62836..40b796d5c 100644 Binary files a/docs/Tutorials/WebView2/Images/tbWebView2Sample0.png and b/docs/Tutorials/WebView2/Images/tbWebView2Sample0.png differ diff --git a/docs/Tutorials/WebView2/Images/tbWebView2Sample0.svg b/docs/Tutorials/WebView2/Images/tbWebView2Sample0.svg index f48c262d4..b18ea78c3 100644 --- a/docs/Tutorials/WebView2/Images/tbWebView2Sample0.svg +++ b/docs/Tutorials/WebView2/Images/tbWebView2Sample0.svg @@ -1 +1 @@ -New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1005NewSamplesRecentSample 0. Reports (Experimental)Sample 1. HelloWorldSample 1a. WebView2 ExamplesSample 1b. Chromium Embedded Framework ExamplesSample 2. GetIPAddressesSample 3. MyCodeLibrary +New / Open Project...Browse...OpenCanceltwinBASIC IDE BETA 1010NewSamplesRecentSample 0. Reports (Experimental)Sample 1. HelloWorldSample 1a. WebView2 ExamplesSample 1b. Chromium Embedded Framework ExamplesSample 2. GetIPAddressesSample 3. MyCodeLibrary diff --git a/docs/Tutorials/WebView2/Images/tbWebView2Toolbox.light.png b/docs/Tutorials/WebView2/Images/tbWebView2Toolbox.light.png index 446688295..9f2b5dcf3 100644 Binary files a/docs/Tutorials/WebView2/Images/tbWebView2Toolbox.light.png and b/docs/Tutorials/WebView2/Images/tbWebView2Toolbox.light.png differ diff --git a/docs/Tutorials/WebView2/Images/tbWebView2Toolbox.png b/docs/Tutorials/WebView2/Images/tbWebView2Toolbox.png index 6ce2e39e1..82c314c0e 100644 Binary files a/docs/Tutorials/WebView2/Images/tbWebView2Toolbox.png and b/docs/Tutorials/WebView2/Images/tbWebView2Toolbox.png differ diff --git a/docs/_book.yml b/docs/_book.yml index 5e21fb1f1..aa4c7794c 100644 --- a/docs/_book.yml +++ b/docs/_book.yml @@ -612,6 +612,13 @@ parts: landing_is_target: true outline_closed: true + - title: BigNumberLib Package + subtitle: Arbitrary-precision signed integer arithmetic, up to 4096 bits + landing_page: /tB/Packages/Contributed/BigNumberLib/ + page: /tB/Packages/Contributed/BigNumberLib/ + landing_is_target: true + outline_closed: true + - title: Appendices outline_closed: false @@ -653,7 +660,6 @@ left_out: - reason: Experimental packages, which do not yet work well enough to use in a program; the book is for packages ready for use pages: - /tB/Packages/Contributed/ArrayListLib/ - - /tB/Packages/Contributed/BigNumberLib/ - /tB/Packages/Contributed/GdiPlus/ - /tB/Packages/Contributed/TBMANLIB/ - /tB/Packages/Contributed/TBMANLIB_Aes/ diff --git a/indexer/snapshots/contributed/BigNumberLib/api.json b/indexer/snapshots/contributed/BigNumberLib/api.json index 3312c63d6..f8167bb65 100644 --- a/indexer/snapshots/contributed/BigNumberLib/api.json +++ b/indexer/snapshots/contributed/BigNumberLib/api.json @@ -2,7 +2,7 @@ "format": 3, "package": "BigNumberLib", "project": "BigNumberLib", - "version": "1.0.2.0", + "version": "1.0.4.0", "types": [ { "name": "Absolute", @@ -54,7 +54,7 @@ {"name":"AssignMultiplication","kind":"sub","vis":"public","signature":"Public Sub AssignMultiplication(ByRef a As BigNumber, ByRef b As BigNumber)","description":"{this} = a * b"}, {"name":"AssignMultiplicationModulus","kind":"sub","vis":"public","signature":"Public Sub AssignMultiplicationModulus(ByRef a As BigNumber, ByRef b As BigNumber, ByRef mod_c As BigNumber)","description":"{this} = a * b (mod c)"}, {"name":"AssignNegation","kind":"function","vis":"public","signature":"Public Function AssignNegation(ByRef a As BigNumber) As Boolean","returnType":"Boolean","description":"{this} = -a"}, - {"name":"AssignShiftLeft","kind":"sub","vis":"public","signature":"Public Sub AssignShiftLeft(ByRef a As BigNumber, ByVal shiftAmount_b As Long)","description":"{this} = a << b"}, + {"name":"AssignShiftLeft","kind":"sub","vis":"public","signature":"Public Sub AssignShiftLeft(ByVal a As BigNumber, ByVal shiftAmount_b As Long)","description":"{this} = a << b"}, {"name":"AssignShiftRight","kind":"sub","vis":"public","signature":"Public Sub AssignShiftRight(ByRef a As BigNumber, ByVal shiftAmount_b As Long)","description":"{this} = a >> b"}, {"name":"AssignSquared","kind":"sub","vis":"public","signature":"Public Sub AssignSquared(ByRef a As BigNumber)","description":"{this} = a * a"}, {"name":"AssignSquaredModulus","kind":"sub","vis":"public","signature":"Public Sub AssignSquaredModulus(ByRef a As BigNumber, ByRef mod_b As BigNumber)","description":"{this} = a * a (mod b)"}, @@ -77,6 +77,7 @@ {"name":"IsLessThanOrEqualTo","kind":"function","vis":"public","signature":"Public Function IsLessThanOrEqualTo(ByRef b As BigNumber) As Boolean","returnType":"Boolean","description":"a <= b"}, {"name":"IsNegative","kind":"property","vis":"public","signature":"Public Property Get IsNegative() As Boolean","returnType":"Boolean","accessor":"Get"}, {"name":"IsNegative","kind":"property","vis":"public","signature":"Public Property Let IsNegative(Value As Boolean)","accessor":"Let"}, + {"name":"MAX_BITS","kind":"const","vis":"private","signatures":[{"cond":"Win64","signature":"Const MAX_BITS As Long = 4608"},{"cond":"Not (Win64)","signature":"Const MAX_BITS As Long = 4352"}]}, {"name":"OctalRadix","kind":"const","vis":"private","signature":"Const OctalRadix As Long = 8"}, {"name":"ValueBinary","kind":"property","vis":"public","signature":"Property Get ValueBinary() As String","returnType":"String","accessor":"Get","description":"returns/sets the value as a binary-string respresentation"}, {"name":"ValueBinary","kind":"property","vis":"public","signature":"Property Let ValueBinary(ByVal Value As String)","accessor":"Let","description":"returns/sets the value as a binary-string respresentation"}, @@ -90,6 +91,7 @@ {"name":"fp_addmod","kind":"function","vis":"private","declare":true,"signature":"Private Declare PtrSafe Function fp_addmod CDecl Lib libtfm (ByRef a As fp_int, ByRef b As fp_int, ByRef mod As fp_int, ByRef out As fp_int) As Long","returnType":"Long"}, {"name":"fp_cmp","kind":"function","vis":"private","declare":true,"signature":"Private Declare PtrSafe Function fp_cmp CDecl Lib libtfm (ByRef a As fp_int, ByRef b As fp_int) As Long","returnType":"Long"}, {"name":"fp_cmp_mag","kind":"function","vis":"private","declare":true,"signature":"Private Declare PtrSafe Function fp_cmp_mag CDecl Lib libtfm (ByRef a As fp_int, ByRef b As fp_int) As Long","returnType":"Long"}, + {"name":"fp_count_bits","kind":"function","vis":"private","declare":true,"signature":"Private Declare PtrSafe Function fp_count_bits CDecl Lib libtfm (ByRef a As fp_int) As Long","returnType":"Long"}, {"name":"fp_div","kind":"function","vis":"private","declare":true,"signature":"Private Declare PtrSafe Function fp_div CDecl Lib libtfm (ByRef a As fp_int, ByRef b As fp_int, ByRef out As fp_int, ByRef remainder As fp_int) As Long","returnType":"Long"}, {"name":"fp_div_2","kind":"sub","vis":"private","declare":true,"signature":"Private Declare PtrSafe Sub fp_div_2 CDecl Lib libtfm (ByRef a As fp_int, ByRef b As fp_int)"}, {"name":"fp_div_2d","kind":"sub","vis":"private","declare":true,"signature":"Private Declare PtrSafe Sub fp_div_2d CDecl Lib libtfm (ByRef a As fp_int, ByVal b As Long, ByRef out As fp_int, ByRef remainder As fp_int)"}, diff --git a/scripts/broker/src/Sources/ByteList.twin b/scripts/broker/src/Sources/BrokerByteList.twin similarity index 93% rename from scripts/broker/src/Sources/ByteList.twin rename to scripts/broker/src/Sources/BrokerByteList.twin index 5167b0351..a4a78efb2 100644 --- a/scripts/broker/src/Sources/ByteList.twin +++ b/scripts/broker/src/Sources/BrokerByteList.twin @@ -1,5 +1,5 @@ ' Bytes gathered from reads, for a reply that may arrive in pieces. -Class ByteList +Class BrokerByteList Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As LongPtr) Private mData() As Byte @@ -28,6 +28,6 @@ Class ByteList If mData(n - 1) <> 10 And mData(n - 1) <> 13 Then Exit Do n = n - 1 Loop - AsText = Text.FromUtf8(mData, 0, n) + AsText = BrokerText.FromUtf8(mData, 0, n) End Function End Class diff --git a/scripts/broker/src/Sources/Conn.twin b/scripts/broker/src/Sources/BrokerConn.twin similarity index 97% rename from scripts/broker/src/Sources/Conn.twin rename to scripts/broker/src/Sources/BrokerConn.twin index 4e22206ad..913e740a0 100644 --- a/scripts/broker/src/Sources/Conn.twin +++ b/scripts/broker/src/Sources/BrokerConn.twin @@ -1,5 +1,5 @@ ' One instance of the pipe: listening for a client, then connected to one. -Class Conn +Class BrokerConn Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As LongPtr) Public Id As Long @@ -55,7 +55,7 @@ Class Conn If n > 0 Then If mIn(n - 1) = 13 Then n = n - 1 End If - line = Text.FromUtf8(mIn, 0, n) + line = BrokerText.FromUtf8(mIn, 0, n) If i + 1 < mInLen Then RtlMoveMemory VarPtr(mIn(0)), VarPtr(mIn(i + 1)), mInLen - i - 1 mInLen = mInLen - i - 1 TakeLine = True diff --git a/scripts/broker/src/Sources/BrokerHost.twin b/scripts/broker/src/Sources/BrokerHost.twin new file mode 100644 index 000000000..50d52505f --- /dev/null +++ b/scripts/broker/src/Sources/BrokerHost.twin @@ -0,0 +1,65 @@ +' What tbbroker says of itself, for the modules it shares with tblaunch (BrokerMain.twin says +' which). tblaunch has a BrokerHost of its own with these members, and compiles neither this +' file nor Program.twin: change a member's name or signature in both programs at once. +Module BrokerHost + Private Declare PtrSafe Function GetModuleFileNameW Lib "kernel32" (ByVal hModule As LongPtr, ByVal lpFilename As LongPtr, ByVal nSize As Long) As Long + Private Declare PtrSafe Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As LongPtr + Private Declare PtrSafe Function AttachConsole Lib "kernel32" (ByVal dwProcessId As Long) As Long + Private Declare PtrSafe Function CreateFileW Lib "kernel32" (ByVal lpFileName As LongPtr, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As LongPtr, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As LongPtr) As LongPtr + Private Declare PtrSafe Function WriteFile Lib "kernel32" (ByVal hFile As LongPtr, ByVal lpBuffer As LongPtr, ByVal nNumberOfBytesToWrite As Long, ByRef lpNumberOfBytesWritten As Long, ByVal lpOverlapped As LongPtr) As Long + + Private Const STD_OUTPUT_HANDLE As Long = -11 + Private Const STD_ERROR_HANDLE As Long = -12 + Private Const ATTACH_PARENT_PROCESS As Long = -1 + Private Const GENERIC_WRITE As Long = &H40000000 + Private Const FILE_SHARE_WRITE As Long = 2 + Private Const OPEN_EXISTING As Long = 3 + Private Const INVALID_HANDLE_VALUE As LongPtr = -1 + + ' The program's name in messages and in the usage text. + Public Const PROGRAM_NAME As String = "tbbroker" + ' What follows "1.0" in the version the broker reports. + Public Const VERSION_SUFFIX As String = "" + ' What follows the server's exe on the command line `start` runs. + Public Const SERVE_ARGS As String = "--serve" + + Private mOut As LongPtr + Private mErr As LongPtr + + ' The exe `start` runs as the server: this one. "" when there is none, the reason written. + Public Function ServerExe() As String + Dim exe As String, n As Long + exe = String$(32768, vbNullChar) + n = GetModuleFileNameW(0, StrPtr(exe), 32768) + ServerExe = Left$(exe, n) + End Function + + ' Standard output, or the console of the process that started this one: the broker is a + ' windows program, so it has a console only when it borrows one. + Private Function OutHandle(ByVal which As Long) As LongPtr + Dim h As LongPtr + h = GetStdHandle(which) + If h = 0 Or h = INVALID_HANDLE_VALUE Then + AttachConsole ATTACH_PARENT_PROCESS + h = CreateFileW(StrPtr("CONOUT$"), GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0) + End If + OutHandle = h + End Function + + Private Sub WriteTo(ByVal h As LongPtr, ByVal s As String) + Dim b() As Byte, n As Long, done As Long + If h = 0 Or h = INVALID_HANDLE_VALUE Then Exit Sub + n = BrokerText.ToUtf8(s & vbCrLf, b) + If n > 0 Then WriteFile h, VarPtr(b(0)), n, done, 0 + End Sub + + Public Sub WriteOut(ByVal s As String) + If mOut = 0 Then mOut = OutHandle(STD_OUTPUT_HANDLE) + WriteTo mOut, s + End Sub + + Public Sub WriteErr(ByVal s As String) + If mErr = 0 Then mErr = OutHandle(STD_ERROR_HANDLE) + WriteTo mErr, s + End Sub +End Module diff --git a/scripts/broker/src/Sources/Lease.twin b/scripts/broker/src/Sources/BrokerLease.twin similarity index 97% rename from scripts/broker/src/Sources/Lease.twin rename to scripts/broker/src/Sources/BrokerLease.twin index ec6055435..c739de5f4 100644 --- a/scripts/broker/src/Sources/Lease.twin +++ b/scripts/broker/src/Sources/BrokerLease.twin @@ -1,6 +1,6 @@ ' One lease: a slot, its desktop, perhaps a port, and who keeps it. It ends once the connection ' that took it has closed or released it, and every process held for it has ended. -Class Lease +Class BrokerLease Public Id As Long Public Slot As Long Public Port As Long diff --git a/scripts/broker/src/Sources/MainModule.twin b/scripts/broker/src/Sources/BrokerMain.twin similarity index 71% rename from scripts/broker/src/Sources/MainModule.twin rename to scripts/broker/src/Sources/BrokerMain.twin index 14ae92cc4..fdb0cdde6 100644 --- a/scripts/broker/src/Sources/MainModule.twin +++ b/scripts/broker/src/Sources/BrokerMain.twin @@ -1,6 +1,12 @@ ' tbbroker -- hands out private desktops, slots and ports to the tools that start twinBASIC IDEs ' and programs, and takes them back when the processes using them end. See WIP.Broker.md. -Module MainModule +' +' The broker's command line. tbbroker's Sub Main (Program.twin) and tblaunch's `broker` command +' both call RunArgs. Every module whose name starts with Broker but BrokerHost is compiled into +' tblaunch as it is, so what differs between the two programs is in BrokerHost, which each of +' them has its own of: the name in messages, the output, the version's suffix and the server's +' command line. +Module BrokerMain Private Type STARTUPINFOW cb As Long lpReserved As LongPtr @@ -29,32 +35,19 @@ Module MainModule dwThreadId As Long End Type - Private Declare PtrSafe Function GetCommandLineW Lib "kernel32" () As LongPtr - Private Declare PtrSafe Function CommandLineToArgvW Lib "shell32" (ByVal lpCmdLine As LongPtr, ByRef pNumArgs As Long) As LongPtr - Private Declare PtrSafe Function LocalFree Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr - Private Declare PtrSafe Function lstrlenW Lib "kernel32" (ByVal lpString As LongPtr) As Long - Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As LongPtr) - Private Declare PtrSafe Sub ExitProcess Lib "kernel32" (ByVal uExitCode As Long) - Private Declare PtrSafe Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As LongPtr - Private Declare PtrSafe Function AttachConsole Lib "kernel32" (ByVal dwProcessId As Long) As Long Private Declare PtrSafe Function CreateFileW Lib "kernel32" (ByVal lpFileName As LongPtr, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As LongPtr, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As LongPtr) As LongPtr Private Declare PtrSafe Function ReadFile Lib "kernel32" (ByVal hFile As LongPtr, ByVal lpBuffer As LongPtr, ByVal nNumberOfBytesToRead As Long, ByRef lpNumberOfBytesRead As Long, ByVal lpOverlapped As LongPtr) As Long Private Declare PtrSafe Function WriteFile Lib "kernel32" (ByVal hFile As LongPtr, ByVal lpBuffer As LongPtr, ByVal nNumberOfBytesToWrite As Long, ByRef lpNumberOfBytesWritten As Long, ByVal lpOverlapped As LongPtr) As Long Private Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongPtr) As Long Private Declare PtrSafe Function WaitNamedPipeW Lib "kernel32" (ByVal lpNamedPipeName As LongPtr, ByVal nTimeOut As Long) As Long - Private Declare PtrSafe Function GetModuleFileNameW Lib "kernel32" (ByVal hModule As LongPtr, ByVal lpFilename As LongPtr, ByVal nSize As Long) As Long Private Declare PtrSafe Function CreateProcessW Lib "kernel32" (ByVal lpApplicationName As LongPtr, ByVal lpCommandLine As LongPtr, ByVal lpProcessAttributes As LongPtr, ByVal lpThreadAttributes As LongPtr, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As LongPtr, ByVal lpCurrentDirectory As LongPtr, ByRef lpStartupInfo As STARTUPINFOW, ByRef lpProcessInformation As PROCESS_INFORMATION) As Long Private Declare PtrSafe Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As LongPtr, ByVal dwMilliseconds As Long) As Long Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As LongPtr, ByRef lpExitCode As Long) As Long Private Declare PtrSafe Function GetTickCount64 Lib "kernel32" () As LongLong Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) - Private Const STD_OUTPUT_HANDLE As Long = -11 - Private Const STD_ERROR_HANDLE As Long = -12 - Private Const ATTACH_PARENT_PROCESS As Long = -1 Private Const GENERIC_READ As Long = &H80000000 Private Const GENERIC_WRITE As Long = &H40000000 - Private Const FILE_SHARE_WRITE As Long = 2 Private Const OPEN_EXISTING As Long = 3 Private Const INVALID_HANDLE_VALUE As LongPtr = -1 Private Const ERROR_ACCESS_DENIED As Long = 5 @@ -72,29 +65,26 @@ Module MainModule Private Const EXIT_USAGE As Long = 2 Private Const EXIT_NOT_RUNNING As Long = 4 - Private mOut As LongPtr - Private mErr As LongPtr - - Public Sub Main() - Dim code As Long + ' Runs the broker's command line, argv being the arguments after the program's name (after + ' tblaunch's `broker`), and returns the exit code. + Public Function RunArgs(ByVal argv As Collection) As Long On Error GoTo Crashed - code = Run(Arguments()) - ExitProcess code - Exit Sub + RunArgs = Run(argv) + Exit Function Crashed: - Text.Log "crashed: " & Err.Description - WriteErr "tbbroker: " & Err.Description - ExitProcess EXIT_FAILED - End Sub + BrokerText.Log "crashed: " & Err.Description + BrokerHost.WriteErr BrokerHost.PROGRAM_NAME & ": " & Err.Description + RunArgs = EXIT_FAILED + End Function Private Function Usage() As String Usage = Join(Array( _ "Usage:", _ - " tbbroker [start] [options] start the broker unless it runs already, and wait until it", _ + " " & BrokerHost.PROGRAM_NAME & " [start] [options] start the broker unless it runs already, and wait until it", _ " answers; the broker itself runs detached until logoff", _ - " tbbroker status [--pipe N] print the broker's state as one line of JSON", _ - " tbbroker stop [--pipe N] end the broker; its desktops go with it", _ - " tbbroker --serve [options] be the broker (what start runs)", _ + " " & BrokerHost.PROGRAM_NAME & " status [--pipe N] print the broker's state as one line of JSON", _ + " " & BrokerHost.PROGRAM_NAME & " stop [--pipe N] end the broker; its desktops go with it", _ + " " & BrokerHost.PROGRAM_NAME & " --serve [options] be the broker (what start runs)", _ "", _ "Options (start and --serve):", _ " --pipe the pipe (default \\.\pipe\tbbroker-)", _ @@ -111,23 +101,8 @@ Module MainModule " 4 status and stop: no broker runs"), vbCrLf) End Function - ' The arguments after the program's name, as the C runtime splits them. - Private Function Arguments() As Collection - Dim r As New Collection, argv As LongPtr, argc As Long, i As Long, p As LongPtr, n As Long, s As String - argv = CommandLineToArgvW(GetCommandLineW(), argc) - For i = 1 To argc - 1 - RtlMoveMemory VarPtr(p), argv + i * LenB(p), LenB(p) - n = lstrlenW(p) - s = String$(n, vbNullChar) - If n > 0 Then RtlMoveMemory StrPtr(s), p, 2 * n - r.Add s - Next - LocalFree argv - Set Arguments = r - End Function - Public Function DefaultPipe() As String - DefaultPipe = "\\.\pipe\tbbroker-" & Text.Env("USERNAME") + DefaultPipe = "\\.\pipe\tbbroker-" & BrokerText.Env("USERNAME") End Function Private Function Run(ByVal argv As Collection) As Long @@ -139,7 +114,7 @@ Module MainModule max = 32 portFirst = 48000 portLast = 48199 - logPath = Text.HomeFolder() & "\tbbroker.log" + logPath = BrokerText.HomeFolder() & "\tbbroker.log" i = 1 Do While i <= argv.Count a = argv(i) @@ -151,7 +126,7 @@ Module MainModule End If verb = a Case "--help", "-h" - WriteOut Usage() + BrokerHost.WriteOut Usage() Exit Function Case "--pipe", "--prefix", "--max", "--ports", "--log" If i = argv.Count Then @@ -215,9 +190,9 @@ Module MainModule If Len(verb) = 0 Then verb = "start" Select Case verb Case "--serve" - Text.LogPath = logPath - Pool.Init prefix, max, portFirst, portLast - Run = Server.Serve(pipeName) + BrokerText.LogPath = logPath + BrokerPool.Init prefix, max, portFirst, portLast + Run = BrokerServer.Serve(pipeName) Case "start" Run = Start(pipeName, passOn) Case "status" @@ -245,7 +220,7 @@ Module MainModule End Function Private Function UsageError(ByVal message As String) As Long - WriteErr "tbbroker: " & message & vbCrLf & vbCrLf & Usage() + BrokerHost.WriteErr BrokerHost.PROGRAM_NAME & ": " & message & vbCrLf & vbCrLf & Usage() UsageError = EXIT_USAGE End Function @@ -261,21 +236,23 @@ Module MainModule End If End Function - ' Starts `tbbroker --serve` as a process of its own, out of the caller's job when the job lets - ' it go and out of the caller's process tree, since this process ends at once; then waits until - ' it answers. + ' Starts the server (BrokerHost.ServerExe with BrokerHost.SERVE_ARGS: `tbbroker --serve`) as a + ' process of its own, out of the caller's job when the job lets it go and out of the caller's + ' process tree, since this process ends at once; then waits until it answers. Private Function Start(ByVal pipeName As String, ByVal passOn As String) As Long - Dim exe As String, n As Long, folder As String, cmd As String, si As STARTUPINFOW, pi As PROCESS_INFORMATION + Dim exe As String, folder As String, cmd As String, si As STARTUPINFOW, pi As PROCESS_INFORMATION Dim flags As Long, ok As Long, until As LongLong, code As Long If Answers(pipeName) Then - WriteOut "tbbroker: running at " & pipeName + BrokerHost.WriteOut BrokerHost.PROGRAM_NAME & ": running at " & pipeName + Exit Function + End If + exe = BrokerHost.ServerExe() + If Len(exe) = 0 Then + Start = EXIT_FAILED Exit Function End If - exe = String$(32768, vbNullChar) - n = GetModuleFileNameW(0, StrPtr(exe), 32768) - exe = Left$(exe, n) folder = Left$(exe, InStrRev(exe, "\") - 1) - cmd = """" & exe & """ --serve" & passOn + cmd = """" & exe & """ " & BrokerHost.SERVE_ARGS & passOn si.cb = LenB(si) flags = DETACHED_PROCESS Or CREATE_NEW_PROCESS_GROUP Or CREATE_BREAKAWAY_FROM_JOB ok = CreateProcessW(StrPtr(exe), StrPtr(cmd), 0, 0, 0, flags, 0, StrPtr(folder), si, pi) @@ -285,7 +262,7 @@ Module MainModule ok = CreateProcessW(StrPtr(exe), StrPtr(cmd), 0, 0, 0, flags, 0, StrPtr(folder), si, pi) End If If ok = 0 Then - WriteErr "tbbroker: could not start the broker: error " & Err.LastDllError + BrokerHost.WriteErr BrokerHost.PROGRAM_NAME & ": could not start the broker: error " & Err.LastDllError Start = EXIT_FAILED Exit Function End If @@ -294,24 +271,24 @@ Module MainModule Do If Answers(pipeName) Then CloseHandle pi.hProcess - WriteOut "tbbroker: running at " & pipeName & ", pid " & pi.dwProcessId + BrokerHost.WriteOut BrokerHost.PROGRAM_NAME & ": running at " & pipeName & ", pid " & pi.dwProcessId Exit Function End If If WaitForSingleObject(pi.hProcess, 0) = WAIT_OBJECT_0 Then GetExitCodeProcess pi.hProcess, code CloseHandle pi.hProcess ' Another broker won the pipe a moment earlier: that one serves. - If code = Server.SERVE_ALREADY_RUNNING And Answers(pipeName) Then - WriteOut "tbbroker: running at " & pipeName + If code = BrokerServer.SERVE_ALREADY_RUNNING And Answers(pipeName) Then + BrokerHost.WriteOut BrokerHost.PROGRAM_NAME & ": running at " & pipeName Exit Function End If - WriteErr "tbbroker: the broker ended at once, with exit code " & code & "; see its log" + BrokerHost.WriteErr BrokerHost.PROGRAM_NAME & ": the broker ended at once, with exit code " & code & "; see its log" Start = EXIT_FAILED Exit Function End If If GetTickCount64() > until Then CloseHandle pi.hProcess - WriteErr "tbbroker: the broker did not open " & pipeName & " within " & (START_WAIT_MS \ 1000) & " s" + BrokerHost.WriteErr BrokerHost.PROGRAM_NAME & ": the broker did not open " & pipeName & " within " & (START_WAIT_MS \ 1000) & " s" Start = EXIT_FAILED Exit Function End If @@ -321,23 +298,23 @@ Module MainModule ' Sends one request and prints the reply line. Private Function Ask(ByVal pipeName As String, ByVal request As String) As Long - Dim h As LongPtr, b() As Byte, n As Long, done As Long, buf(0 To 4095) As Byte, got As Long, reply As New ByteList + Dim h As LongPtr, b() As Byte, n As Long, done As Long, buf(0 To 4095) As Byte, got As Long, reply As New BrokerByteList Dim tries As Long Do h = CreateFileW(StrPtr(pipeName), GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0) If h <> INVALID_HANDLE_VALUE Then Exit Do If Err.LastDllError <> ERROR_PIPE_BUSY Or tries > 10 Then - WriteErr "tbbroker: no broker answers at " & pipeName + BrokerHost.WriteErr BrokerHost.PROGRAM_NAME & ": no broker answers at " & pipeName Ask = EXIT_NOT_RUNNING Exit Function End If tries = tries + 1 WaitNamedPipeW StrPtr(pipeName), 1000 Loop - n = Text.ToUtf8(request & vbLf, b) + n = BrokerText.ToUtf8(request & vbLf, b) If WriteFile(h, VarPtr(b(0)), n, done, 0) = 0 Then CloseHandle h - WriteErr "tbbroker: could not write to " & pipeName + BrokerHost.WriteErr BrokerHost.PROGRAM_NAME & ": could not write to " & pipeName Ask = EXIT_FAILED Exit Function End If @@ -347,39 +324,10 @@ Module MainModule Loop Until reply.EndsWithLineFeed CloseHandle h If reply.Count = 0 Then - WriteErr "tbbroker: no reply from " & pipeName + BrokerHost.WriteErr BrokerHost.PROGRAM_NAME & ": no reply from " & pipeName Ask = EXIT_FAILED Exit Function End If - WriteOut reply.AsText() + BrokerHost.WriteOut reply.AsText() End Function - - ' Standard output, or the console of the process that started this one: the broker is a - ' windows program, so it has a console only when it borrows one. - Private Function OutHandle(ByVal which As Long) As LongPtr - Dim h As LongPtr - h = GetStdHandle(which) - If h = 0 Or h = INVALID_HANDLE_VALUE Then - AttachConsole ATTACH_PARENT_PROCESS - h = CreateFileW(StrPtr("CONOUT$"), GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0) - End If - OutHandle = h - End Function - - Private Sub WriteTo(ByVal h As LongPtr, ByVal s As String) - Dim b() As Byte, n As Long, done As Long - If h = 0 Or h = INVALID_HANDLE_VALUE Then Exit Sub - n = Text.ToUtf8(s & vbCrLf, b) - If n > 0 Then WriteFile h, VarPtr(b(0)), n, done, 0 - End Sub - - Private Sub WriteOut(ByVal s As String) - If mOut = 0 Then mOut = OutHandle(STD_OUTPUT_HANDLE) - WriteTo mOut, s - End Sub - - Private Sub WriteErr(ByVal s As String) - If mErr = 0 Then mErr = OutHandle(STD_ERROR_HANDLE) - WriteTo mErr, s - End Sub End Module diff --git a/scripts/broker/src/Sources/Pool.twin b/scripts/broker/src/Sources/BrokerPool.twin similarity index 82% rename from scripts/broker/src/Sources/Pool.twin rename to scripts/broker/src/Sources/BrokerPool.twin index e2676c91e..502b4d2cf 100644 --- a/scripts/broker/src/Sources/Pool.twin +++ b/scripts/broker/src/Sources/BrokerPool.twin @@ -3,7 +3,7 @@ ' state for every desktop ever made and never lets it go, and walks all of it on every window ' change. A slot is free, leased, or dirty: a desktop whose lease has ended while windows are still ' on it is not handed out again until they have gone. -Module Pool +Module BrokerPool Private Declare PtrSafe Function CreateDesktopW Lib "user32" (ByVal lpszDesktop As LongPtr, ByVal lpszDevice As LongPtr, ByVal pDevmode As LongPtr, ByVal dwFlags As Long, ByVal dwDesiredAccess As Long, ByVal lpsa As LongPtr) As LongPtr Private Declare PtrSafe Function OpenDesktopW Lib "user32" (ByVal lpszDesktop As LongPtr, ByVal dwFlags As Long, ByVal fInherit As Long, ByVal dwDesiredAccess As Long) As LongPtr Private Declare PtrSafe Function EnumDesktopWindows Lib "user32" (ByVal hDesktop As LongPtr, ByVal lpfn As LongPtr, ByVal lParam As LongPtr) As Long @@ -73,7 +73,7 @@ Module Pool If h <> 0 Then mDesk(i) = h mState(i) = STATE_DIRTY - Text.Log "found " & DesktopName(i) & " already there; held" + BrokerText.Log "found " & DesktopName(i) & " already there; held" End If Next CheckDirty @@ -115,7 +115,7 @@ Module Pool mWindows(i) = WindowCount(mDesk(i)) If mWindows(i) = 0 Then mState(i) = STATE_FREE - Text.Log DesktopName(i) & " is empty again" + BrokerText.Log DesktopName(i) & " is empty again" End If End If Next @@ -136,7 +136,7 @@ Module Pool End Function Private Function PortLeased(ByVal port As Long) As Boolean - Dim l As Lease + Dim l As BrokerLease For Each l In mLeases If l.Port = port Then PortLeased = True @@ -178,7 +178,7 @@ Module Pool End If mDesk(i) = h mState(i) = STATE_FREE - Text.Log "made " & DesktopName(i) + BrokerText.Log "made " & DesktopName(i) FreeSlot = i Exit Function End If @@ -189,7 +189,7 @@ Module Pool ' message set. A request that may wait and finds no slot is queued and answered later; then ' the result is "" and code is "". Public Function Take(ByVal connId As Long, ByVal clientPid As Long, ByVal idText As String, ByVal wantPort As Boolean, ByVal tag As String, ByVal mayWait As Boolean, ByRef code As String, ByRef message As String) As String - Dim slot As Long, port As Long, failure As String, l As Lease, w As Waiter + Dim slot As Long, port As Long, failure As String, l As BrokerLease, w As BrokerWaiter code = "" ' A request that may wait goes behind those already waiting. If Not (mayWait And mWaiting.Count > 0) Then slot = FreeSlot(failure) @@ -198,14 +198,14 @@ Module Pool code = "desktop" message = failure ElseIf mayWait Then - Set w = New Waiter + Set w = New BrokerWaiter w.ConnId = connId w.ClientPid = clientPid w.IdText = idText w.WantPort = wantPort w.Tag = tag mWaiting.Add w - Text.Log "connection " & connId & " waits for a slot (" & tag & ")" + BrokerText.Log "connection " & connId & " waits for a slot (" & tag & ")" Else code = "full" message = "all " & mMax & " slots are leased or not yet empty" @@ -226,7 +226,7 @@ Module Pool End If End If mNextLease = mNextLease + 1 - Set l = New Lease + Set l = New BrokerLease l.Id = mNextLease l.Slot = slot l.Port = port @@ -237,19 +237,19 @@ Module Pool mLeases.Add l, CStr(l.Id) mState(slot) = STATE_LEASED mLeaseOf(slot) = l.Id - Text.Log "lease " & l.Id & ": " & DesktopName(slot) & IIf(port > 0, " port " & port, "") & " to pid " & clientPid & " (" & tag & ")" - Take = Text.Member("lease", CStr(l.Id)) & "," & Text.Member("slot", CStr(slot)) & "," & _ - Text.Member("desktop", Text.Quote(DesktopName(slot))) & "," & Text.Member("port", CStr(port)) + BrokerText.Log "lease " & l.Id & ": " & DesktopName(slot) & IIf(port > 0, " port " & port, "") & " to pid " & clientPid & " (" & tag & ")" + Take = BrokerText.Member("lease", CStr(l.Id)) & "," & BrokerText.Member("slot", CStr(slot)) & "," & _ + BrokerText.Member("desktop", BrokerText.Quote(DesktopName(slot))) & "," & BrokerText.Member("port", CStr(port)) End Function - Private Function Find(ByVal leaseId As Long) As Lease + Private Function Find(ByVal leaseId As Long) As BrokerLease On Error Resume Next Set Find = mLeases(CStr(leaseId)) End Function ' "" when done, else the error code; message says more. Public Function Hold(ByVal connId As Long, ByVal leaseId As Long, ByVal pid As Long, ByRef message As String) As String - Dim l As Lease, h As LongPtr + Dim l As BrokerLease, h As LongPtr Set l = Find(leaseId) If l Is Nothing Then Hold = "no-lease" @@ -274,11 +274,11 @@ Module Pool Exit Function End If l.Holds.Add Array(pid, h) - Text.Log "lease " & leaseId & ": holds pid " & pid + BrokerText.Log "lease " & leaseId & ": holds pid " & pid End Function Public Function Release(ByVal connId As Long, ByVal leaseId As Long, ByRef message As String) As String - Dim l As Lease + Dim l As BrokerLease Set l = Find(leaseId) If l Is Nothing Then Release = "no-lease" @@ -291,14 +291,14 @@ Module Pool Exit Function End If l.ConnId = 0 - Text.Log "lease " & leaseId & ": released by its connection" + BrokerText.Log "lease " & leaseId & ": released by its connection" Settle End Function ' A connection has closed: what it took is no longer kept by it, and what it waits for is ' no longer wanted. Public Sub ConnClosed(ByVal connId As Long) - Dim l As Lease, i As Long, w As Waiter + Dim l As BrokerLease, i As Long, w As BrokerWaiter For Each l In mLeases If l.ConnId = connId Then l.ConnId = 0 Next @@ -311,7 +311,7 @@ Module Pool ' Ends each lease nothing keeps any more: no connection, and no held process still running. Private Sub Settle() - Dim i As Long, j As Long, l As Lease, hold As Variant + Dim i As Long, j As Long, l As BrokerLease, hold As Variant For i = mLeases.Count To 1 Step -1 Set l = mLeases(i) For j = l.Holds.Count To 1 Step -1 @@ -319,7 +319,7 @@ Module Pool If WaitForSingleObject(hold(1), 0) = WAIT_OBJECT_0 Then CloseHandle hold(1) l.Holds.Remove j - Text.Log "lease " & l.Id & ": pid " & hold(0) & " has ended" + BrokerText.Log "lease " & l.Id & ": pid " & hold(0) & " has ended" End If Next If l.ConnId = 0 And l.Holds.Count = 0 Then @@ -328,10 +328,10 @@ Module Pool mWindows(l.Slot) = WindowCount(mDesk(l.Slot)) If mWindows(l.Slot) = 0 Then mState(l.Slot) = STATE_FREE - Text.Log "lease " & l.Id & " ended; " & DesktopName(l.Slot) & " is free" + BrokerText.Log "lease " & l.Id & " ended; " & DesktopName(l.Slot) & " is free" Else mState(l.Slot) = STATE_DIRTY - Text.Log "lease " & l.Id & " ended; " & DesktopName(l.Slot) & " still has " & mWindows(l.Slot) & " windows" + BrokerText.Log "lease " & l.Id & " ended; " & DesktopName(l.Slot) & " still has " & mWindows(l.Slot) & " windows" End If End If Next @@ -345,7 +345,7 @@ Module Pool End Sub Private Sub ServeWaiting() - Dim w As Waiter, result As String, code As String, message As String + Dim w As BrokerWaiter, result As String, code As String, message As String ' First come, first served: the first waiter that finds no slot stops the rest. Do While mWaiting.Count > 0 Set w = mWaiting(1) @@ -353,15 +353,15 @@ Module Pool If code = "full" Then Exit Do mWaiting.Remove 1 If Len(result) > 0 Then - Server.SendOk w.ConnId, w.IdText, result + BrokerServer.SendOk w.ConnId, w.IdText, result Else - Server.SendError w.ConnId, w.IdText, code, message + BrokerServer.SendError w.ConnId, w.IdText, code, message End If Loop End Sub Public Function StatusMembers() As String - Dim i As Long, l As Lease, j As Long, s As String, items As String, hold As Variant, state As String + Dim i As Long, l As BrokerLease, j As Long, s As String, items As String, hold As Variant, state As String For i = 1 To mMax If mState(i) <> STATE_NONE Then Select Case mState(i) @@ -373,12 +373,12 @@ Module Pool state = "dirty" End Select If Len(items) > 0 Then items = items & "," - items = items & "{" & Text.Member("slot", CStr(i)) & "," & Text.Member("desktop", Text.Quote(DesktopName(i))) & "," & _ - Text.Member("state", Text.Quote(state)) & "," & Text.Member("lease", CStr(mLeaseOf(i))) & "," & _ - Text.Member("windows", CStr(WindowCount(mDesk(i)))) & "}" + items = items & "{" & BrokerText.Member("slot", CStr(i)) & "," & BrokerText.Member("desktop", BrokerText.Quote(DesktopName(i))) & "," & _ + BrokerText.Member("state", BrokerText.Quote(state)) & "," & BrokerText.Member("lease", CStr(mLeaseOf(i))) & "," & _ + BrokerText.Member("windows", CStr(WindowCount(mDesk(i)))) & "}" End If Next - s = Text.Member("slots", "[" & items & "]") + s = BrokerText.Member("slots", "[" & items & "]") items = "" For Each l In mLeases Dim holds As String @@ -389,13 +389,13 @@ Module Pool holds = holds & hold(0) Next If Len(items) > 0 Then items = items & "," - items = items & "{" & Text.Member("lease", CStr(l.Id)) & "," & Text.Member("slot", CStr(l.Slot)) & "," & _ - Text.Member("desktop", Text.Quote(DesktopName(l.Slot))) & "," & Text.Member("port", CStr(l.Port)) & "," & _ - Text.Member("tag", Text.Quote(l.Tag)) & "," & Text.Member("client", CStr(l.ClientPid)) & "," & _ - Text.Member("connected", Text.Bool(l.ConnId <> 0)) & "," & Text.Member("holds", "[" & holds & "]") & "," & _ - Text.Member("taken", Text.Quote(Format$(l.Taken, "yyyy-mm-dd hh:nn:ss"))) & "}" + items = items & "{" & BrokerText.Member("lease", CStr(l.Id)) & "," & BrokerText.Member("slot", CStr(l.Slot)) & "," & _ + BrokerText.Member("desktop", BrokerText.Quote(DesktopName(l.Slot))) & "," & BrokerText.Member("port", CStr(l.Port)) & "," & _ + BrokerText.Member("tag", BrokerText.Quote(l.Tag)) & "," & BrokerText.Member("client", CStr(l.ClientPid)) & "," & _ + BrokerText.Member("connected", BrokerText.Bool(l.ConnId <> 0)) & "," & BrokerText.Member("holds", "[" & holds & "]") & "," & _ + BrokerText.Member("taken", BrokerText.Quote(Format$(l.Taken, "yyyy-mm-dd hh:nn:ss"))) & "}" Next - s = s & "," & Text.Member("leases", "[" & items & "]") & "," & Text.Member("waiting", CStr(mWaiting.Count)) + s = s & "," & BrokerText.Member("leases", "[" & items & "]") & "," & BrokerText.Member("waiting", CStr(mWaiting.Count)) StatusMembers = s End Function End Module diff --git a/scripts/broker/src/Sources/Request.twin b/scripts/broker/src/Sources/BrokerRequest.twin similarity index 99% rename from scripts/broker/src/Sources/Request.twin rename to scripts/broker/src/Sources/BrokerRequest.twin index 737408150..29e557d79 100644 --- a/scripts/broker/src/Sources/Request.twin +++ b/scripts/broker/src/Sources/BrokerRequest.twin @@ -2,7 +2,7 @@ ' strings, numbers, true, false or null; a member that is an object or an array is skipped over ' and reads as absent. The id member is kept as the JSON text it was, so that the reply can give ' it back exactly. -Class Request +Class BrokerRequest Public Valid As Boolean Public Problem As String Public IdText As String diff --git a/scripts/broker/src/Sources/Server.twin b/scripts/broker/src/Sources/BrokerServer.twin similarity index 78% rename from scripts/broker/src/Sources/Server.twin rename to scripts/broker/src/Sources/BrokerServer.twin index f9e6b53e0..bf349369d 100644 --- a/scripts/broker/src/Sources/Server.twin +++ b/scripts/broker/src/Sources/BrokerServer.twin @@ -2,7 +2,7 @@ ' loop waits on for a quarter of a second at a time, and between packets the pool looks at the ' processes it holds for. No thread of the runtime's is involved, and there is no limit of 64 ' handles to wait on. -Module Server +Module BrokerServer Private Declare PtrSafe Function CreateNamedPipeW Lib "kernel32" (ByVal lpName As LongPtr, ByVal dwOpenMode As Long, ByVal dwPipeMode As Long, ByVal nMaxInstances As Long, ByVal nOutBufferSize As Long, ByVal nInBufferSize As Long, ByVal nDefaultTimeOut As Long, ByVal lpSecurityAttributes As LongPtr) As LongPtr Private Declare PtrSafe Function ConnectNamedPipe Lib "kernel32" (ByVal hNamedPipe As LongPtr, ByVal lpOverlapped As LongPtr) As Long Private Declare PtrSafe Function GetNamedPipeClientProcessId Lib "kernel32" (ByVal Pipe As LongPtr, ByRef ClientProcessId As Long) As Long @@ -45,7 +45,8 @@ Module Server Private Const TICK_MS As Long = 250 Public Const PROTOCOL As Long = 1 - Public Const VERSION As String = "1.0" + ' "1.0", and after it what the program serving says of itself (" tblaunch" in tblaunch). + Public Const VERSION As String = "1.0" & BrokerHost.VERSION_SUFFIX ' Exit codes of Serve. Public Const SERVE_STOPPED As Long = 0 @@ -71,7 +72,7 @@ Module Server mStarted = Now mPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1) If mPort = 0 Then - Text.Log "CreateIoCompletionPort failed with error " & Err.LastDllError + BrokerText.Log "CreateIoCompletionPort failed with error " & Err.LastDllError Serve = SERVE_FAILED Exit Function End If @@ -84,8 +85,8 @@ Module Server Serve = SERVE_FAILED Exit Function End Select - Text.Log "serving " & mPipeName & ": slots " & Pool.Prefix & "1-" & Pool.MaxSlots & _ - IIf(Len(Pool.PortRange()) > 0, ", ports " & Pool.PortRange(), ", no ports") + BrokerText.Log "serving " & mPipeName & ": slots " & BrokerPool.Prefix & "1-" & BrokerPool.MaxSlots & _ + IIf(Len(BrokerPool.PortRange()) > 0, ", ports " & BrokerPool.PortRange(), ", no ports") lastTick = GetTickCount64() Do ov = 0 @@ -98,29 +99,29 @@ Module Server If now64 - lastTick >= TICK_MS Then lastTick = now64 If mNeedListener Then Listen False - Pool.Tick + BrokerPool.Tick End If Loop Until mStopping - Text.Log "stopped" + BrokerText.Log "stopped" Serve = SERVE_STOPPED End Function ' A new pipe instance, waiting for a client. 0, or the error that stopped it. Private Function Listen(ByVal first As Boolean) As Long - Dim c As Conn, h As LongPtr, mode As Long, e As Long + Dim c As BrokerConn, h As LongPtr, mode As Long, e As Long mode = PIPE_ACCESS_DUPLEX Or FILE_FLAG_OVERLAPPED If first Then mode = mode Or FILE_FLAG_FIRST_PIPE_INSTANCE h = CreateNamedPipeW(StrPtr(mPipeName), mode, PIPE_REJECT_REMOTE_CLIENTS, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER, PIPE_BUFFER, 0, 0) If h = INVALID_HANDLE_VALUE Then e = Err.LastDllError - If Not first Or e <> ERROR_ACCESS_DENIED Then Text.Log "CreateNamedPipe failed with error " & e + If Not first Or e <> ERROR_ACCESS_DENIED Then BrokerText.Log "CreateNamedPipe failed with error " & e mNeedListener = True Listen = e Exit Function End If mNeedListener = False mNextConn = mNextConn + 1 - Set c = New Conn + Set c = New BrokerConn c.Id = mNextConn c.Handle = h c.Listening = True @@ -138,7 +139,7 @@ Module Server ' A client came between the two calls; no packet will say so. Connected c Else - Text.Log "ConnectNamedPipe failed with error " & e + BrokerText.Log "ConnectNamedPipe failed with error " & e Drop c mNeedListener = True End If @@ -147,13 +148,13 @@ Module Server End If End Function - Private Function Find(ByVal id As Long) As Conn + Private Function Find(ByVal id As Long) As BrokerConn On Error Resume Next Set Find = mConns(CStr(id)) End Function Private Sub Completed(ByVal ok As Boolean, ByVal bytes As Long, ByVal id As Long) - Dim c As Conn + Dim c As BrokerConn Set c = Find(id) If c Is Nothing Then Exit Sub c.Pending = False @@ -190,18 +191,18 @@ Module Server Read c End Sub - Private Sub Connected(ByVal c As Conn) + Private Sub Connected(ByVal c As BrokerConn) Dim pid As Long c.Listening = False GetNamedPipeClientProcessId c.Handle, pid c.ClientPid = pid - Text.Log "connection " & c.Id & " from pid " & pid + BrokerText.Log "connection " & c.Id & " from pid " & pid ' The next client needs an instance of its own to connect to. Listen False Read c End Sub - Private Sub Read(ByVal c As Conn) + Private Sub Read(ByVal c As BrokerConn) Dim e As Long RtlZeroMemory c.Block, OVERLAPPED_SPACE If ReadFile(c.Handle, c.Block + OVERLAPPED_SPACE, READ_SIZE, 0, c.Block) = 0 Then @@ -216,12 +217,12 @@ Module Server End Sub ' Closes the connection, and gives back what it kept. - Private Sub Drop(ByVal c As Conn) + Private Sub Drop(ByVal c As BrokerConn) If Not c.Open Then Exit Sub c.Open = False If Not c.Listening Then - Text.Log "connection " & c.Id & " closed" - Pool.ConnClosed c.Id + BrokerText.Log "connection " & c.Id & " closed" + BrokerPool.ConnClosed c.Id End If If c.Pending Then ' The cancelled request still owes a packet, and its memory is not ours until then. @@ -234,7 +235,7 @@ Module Server End If End Sub - Private Sub Free(ByVal c As Conn) + Private Sub Free(ByVal c As BrokerConn) If c.Open Then CloseHandle c.Handle c.Open = False HeapFree GetProcessHeap(), 0, c.Block @@ -246,10 +247,10 @@ Module Server ' Writes a line to the connection and waits for it to be taken. A client that does not read ' its replies is cut off rather than allowed to stop the broker. - Private Sub Send(ByVal c As Conn, ByVal json As String) + Private Sub Send(ByVal c As BrokerConn, ByVal json As String) Dim b() As Byte, n As Long, e As Long, done As Long, ev As LongPtr, pEvent As LongPtr If Not c.Open Or c.Listening Then Exit Sub - n = Text.ToUtf8(json & vbLf, b) + n = BrokerText.ToUtf8(json & vbLf, b) RtlZeroMemory c.WriteBlock, OVERLAPPED_SPACE ' The event's handle with its lowest bit set: the write's completion then goes to the ' event and not to the completion port, which has nothing to do with it. @@ -265,7 +266,7 @@ Module Server If WaitForSingleObject(c.WriteEvent, WRITE_TIMEOUT_MS) = WAIT_TIMEOUT Then CancelIoEx c.Handle, c.WriteBlock GetOverlappedResult c.Handle, c.WriteBlock, done, 1 - Text.Log "connection " & c.Id & " took no reply for " & WRITE_TIMEOUT_MS & " ms" + BrokerText.Log "connection " & c.Id & " took no reply for " & WRITE_TIMEOUT_MS & " ms" Drop c Exit Sub End If @@ -276,26 +277,26 @@ Module Server Private Function Reply(ByVal idText As String, ByVal ok As Boolean, ByVal members As String) As String Dim s As String s = "{" - If Len(idText) > 0 Then s = s & Text.Member("id", idText) & "," - s = s & Text.Member("ok", Text.Bool(ok)) + If Len(idText) > 0 Then s = s & BrokerText.Member("id", idText) & "," + s = s & BrokerText.Member("ok", BrokerText.Bool(ok)) If Len(members) > 0 Then s = s & "," & members Reply = s & "}" End Function Public Sub SendOk(ByVal connId As Long, ByVal idText As String, ByVal members As String) - Dim c As Conn + Dim c As BrokerConn Set c = Find(connId) If Not c Is Nothing Then Send c, Reply(idText, True, members) End Sub Public Sub SendError(ByVal connId As Long, ByVal idText As String, ByVal code As String, ByVal message As String) - Dim c As Conn + Dim c As BrokerConn Set c = Find(connId) - If Not c Is Nothing Then Send c, Reply(idText, False, Text.Member("error", Text.Quote(code)) & "," & Text.Member("message", Text.Quote(message))) + If Not c Is Nothing Then Send c, Reply(idText, False, BrokerText.Member("error", BrokerText.Quote(code)) & "," & BrokerText.Member("message", BrokerText.Quote(message))) End Sub - Private Sub Answer(ByVal c As Conn, ByVal line As String) - Dim r As New Request, op As String, result As String, code As String, message As String + Private Sub Answer(ByVal c As BrokerConn, ByVal line As String) + Dim r As New BrokerRequest, op As String, result As String, code As String, message As String If Len(Trim$(line)) = 0 Then Exit Sub r.Parse line If Not r.Valid Then @@ -306,10 +307,10 @@ Module Server Select Case op Case "hello" If r.Has("client") Then c.ClientName = r.StringOf("client") - SendOk c.Id, r.IdText, Text.Member("protocol", CStr(PROTOCOL)) & "," & Text.Member("version", Text.Quote(VERSION)) & "," & _ - Text.Member("pid", CStr(GetCurrentProcessId())) & "," & Text.Member("client", CStr(c.ClientPid)) + SendOk c.Id, r.IdText, BrokerText.Member("protocol", CStr(PROTOCOL)) & "," & BrokerText.Member("version", BrokerText.Quote(VERSION)) & "," & _ + BrokerText.Member("pid", CStr(GetCurrentProcessId())) & "," & BrokerText.Member("client", CStr(c.ClientPid)) Case "lease" - result = Pool.Take(c.Id, c.ClientPid, r.IdText, r.Flag("port"), r.StringOf("tag"), r.Flag("wait"), code, message) + result = BrokerPool.Take(c.Id, c.ClientPid, r.IdText, r.Flag("port"), r.StringOf("tag"), r.Flag("wait"), code, message) If Len(result) > 0 Then SendOk c.Id, r.IdText, result ElseIf Len(code) > 0 Then @@ -320,19 +321,19 @@ Module Server SendError c.Id, r.IdText, "bad-request", "hold takes a lease and a pid" Exit Sub End If - code = Pool.Hold(c.Id, CLng(r.Number("lease")), CLng(r.Number("pid")), message) + code = BrokerPool.Hold(c.Id, CLng(r.Number("lease")), CLng(r.Number("pid")), message) If Len(code) = 0 Then SendOk c.Id, r.IdText, "" Else SendError c.Id, r.IdText, code, message Case "release" If Not r.IsNumber("lease") Then SendError c.Id, r.IdText, "bad-request", "release takes a lease" Exit Sub End If - code = Pool.Release(c.Id, CLng(r.Number("lease")), message) + code = BrokerPool.Release(c.Id, CLng(r.Number("lease")), message) If Len(code) = 0 Then SendOk c.Id, r.IdText, "" Else SendError c.Id, r.IdText, code, message Case "status" SendOk c.Id, r.IdText, StatusMembers() Case "stop" - Text.Log "stop requested by pid " & c.ClientPid + BrokerText.Log "stop requested by pid " & c.ClientPid SendOk c.Id, r.IdText, "" mStopping = True Case "" @@ -343,20 +344,20 @@ Module Server End Sub Private Function StatusMembers() As String - Dim s As String, c As Conn, items As String - s = Text.Member("broker", "{" & Text.Member("pid", CStr(GetCurrentProcessId())) & "," & _ - Text.Member("protocol", CStr(PROTOCOL)) & "," & Text.Member("version", Text.Quote(VERSION)) & "," & _ - Text.Member("pipe", Text.Quote(mPipeName)) & "," & Text.Member("prefix", Text.Quote(Pool.Prefix)) & "," & _ - Text.Member("max", CStr(Pool.MaxSlots)) & "," & Text.Member("ports", Text.Quote(Pool.PortRange())) & "," & _ - Text.Member("started", Text.Quote(Format$(mStarted, "yyyy-mm-dd hh:nn:ss"))) & "," & _ - Text.Member("log", Text.Quote(Text.LogPath)) & "}") + Dim s As String, c As BrokerConn, items As String + s = BrokerText.Member("broker", "{" & BrokerText.Member("pid", CStr(GetCurrentProcessId())) & "," & _ + BrokerText.Member("protocol", CStr(PROTOCOL)) & "," & BrokerText.Member("version", BrokerText.Quote(VERSION)) & "," & _ + BrokerText.Member("pipe", BrokerText.Quote(mPipeName)) & "," & BrokerText.Member("prefix", BrokerText.Quote(BrokerPool.Prefix)) & "," & _ + BrokerText.Member("max", CStr(BrokerPool.MaxSlots)) & "," & BrokerText.Member("ports", BrokerText.Quote(BrokerPool.PortRange())) & "," & _ + BrokerText.Member("started", BrokerText.Quote(Format$(mStarted, "yyyy-mm-dd hh:nn:ss"))) & "," & _ + BrokerText.Member("log", BrokerText.Quote(BrokerText.LogPath)) & "}") For Each c In mConns If c.Open And Not c.Listening Then If Len(items) > 0 Then items = items & "," - items = items & "{" & Text.Member("connection", CStr(c.Id)) & "," & Text.Member("pid", CStr(c.ClientPid)) & "," & _ - Text.Member("client", Text.Quote(c.ClientName)) & "}" + items = items & "{" & BrokerText.Member("connection", CStr(c.Id)) & "," & BrokerText.Member("pid", CStr(c.ClientPid)) & "," & _ + BrokerText.Member("client", BrokerText.Quote(c.ClientName)) & "}" End If Next - StatusMembers = s & "," & Text.Member("connections", "[" & items & "]") & "," & Pool.StatusMembers() + StatusMembers = s & "," & BrokerText.Member("connections", "[" & items & "]") & "," & BrokerPool.StatusMembers() End Function End Module diff --git a/scripts/broker/src/Sources/Text.twin b/scripts/broker/src/Sources/BrokerText.twin similarity index 99% rename from scripts/broker/src/Sources/Text.twin rename to scripts/broker/src/Sources/BrokerText.twin index f1f14e0d7..53f7a83de 100644 --- a/scripts/broker/src/Sources/Text.twin +++ b/scripts/broker/src/Sources/BrokerText.twin @@ -1,5 +1,5 @@ ' UTF-8 to and from strings, JSON text for the replies, and the log. -Module Text +Module BrokerText Private Declare PtrSafe Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As LongPtr, ByVal cbMultiByte As Long, ByVal lpWideCharStr As LongPtr, ByVal cchWideChar As Long) As Long Private Declare PtrSafe Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As LongPtr, ByVal cchWideChar As Long, ByVal lpMultiByteStr As LongPtr, ByVal cbMultiByte As Long, ByVal lpDefaultChar As LongPtr, ByVal lpUsedDefaultChar As LongPtr) As Long Private Declare PtrSafe Function CreateFileW Lib "kernel32" (ByVal lpFileName As LongPtr, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As LongPtr, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As LongPtr) As LongPtr diff --git a/scripts/broker/src/Sources/Waiter.twin b/scripts/broker/src/Sources/BrokerWaiter.twin similarity index 92% rename from scripts/broker/src/Sources/Waiter.twin rename to scripts/broker/src/Sources/BrokerWaiter.twin index d993ae0f3..b391b6774 100644 --- a/scripts/broker/src/Sources/Waiter.twin +++ b/scripts/broker/src/Sources/BrokerWaiter.twin @@ -1,5 +1,5 @@ ' A lease request that asked to wait for a free slot, answered when one comes free. -Class Waiter +Class BrokerWaiter Public ConnId As Long Public ClientPid As Long Public IdText As String diff --git a/scripts/broker/src/Sources/Program.twin b/scripts/broker/src/Sources/Program.twin new file mode 100644 index 000000000..2eb1da57f --- /dev/null +++ b/scripts/broker/src/Sources/Program.twin @@ -0,0 +1,28 @@ +' tbbroker's Sub Main. tblaunch has a Sub Main of its own and does not compile this file. +Module Program + Private Declare PtrSafe Function GetCommandLineW Lib "kernel32" () As LongPtr + Private Declare PtrSafe Function CommandLineToArgvW Lib "shell32" (ByVal lpCmdLine As LongPtr, ByRef pNumArgs As Long) As LongPtr + Private Declare PtrSafe Function LocalFree Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr + Private Declare PtrSafe Function lstrlenW Lib "kernel32" (ByVal lpString As LongPtr) As Long + Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As LongPtr) + Private Declare PtrSafe Sub ExitProcess Lib "kernel32" (ByVal uExitCode As Long) + + Public Sub Main() + ExitProcess BrokerMain.RunArgs(Arguments()) + End Sub + + ' The arguments after the program's name, as the C runtime splits them. + Private Function Arguments() As Collection + Dim r As New Collection, argv As LongPtr, argc As Long, i As Long, p As LongPtr, n As Long, s As String + argv = CommandLineToArgvW(GetCommandLineW(), argc) + For i = 1 To argc - 1 + RtlMoveMemory VarPtr(p), argv + i * LenB(p), LenB(p) + n = lstrlenW(p) + s = String$(n, vbNullChar) + If n > 0 Then RtlMoveMemory StrPtr(s), p, 2 * n + r.Add s + Next + LocalFree argv + Set Arguments = r + End Function +End Module diff --git a/scripts/broker/tbbroker.twinproj b/scripts/broker/tbbroker.twinproj index fe21ba878..6c77771d8 100644 Binary files a/scripts/broker/tbbroker.twinproj and b/scripts/broker/tbbroker.twinproj differ diff --git a/scripts/check_examples.mjs b/scripts/check_examples.mjs index 7cfe27f3d..42b5954c5 100644 --- a/scripts/check_examples.mjs +++ b/scripts/check_examples.mjs @@ -148,13 +148,14 @@ import { } from "./lib/example-run.mjs"; import { HarnessError, HARNESS_NAME, optionSeconds, readHarness, timeoutMs } from "./lib/harness-settings.mjs"; import { compileProject } from "./lib/tb-build.mjs"; +import { IdeSession } from "./lib/tb-session.mjs"; import { timing } from "./lib/tb-timings.mjs"; import { leaseSlot, wantShow } from "./lib/tb-ide.mjs"; import { asksForLlvm, holdLlvmCache } from "./lib/tb-llvm-cache.mjs"; import { buildNumber, findIde, unsupportedIde } from "./lib/tb-install.mjs"; import { packTree, unpackProject } from "./lib/tb-project.mjs"; import { downloadPackage } from "../indexer/lib/twinserv-client.mjs"; -import { alive, finishTidy, startTidy } from "./lib/tb-registry.mjs"; +import { finishTidy, keepRunFolder, startTidy, sweepRunFolders } from "./lib/tb-registry.mjs"; import { DOCS_DIR, REPO_ROOT } from "../lib/repo-paths.mjs"; const TEMPLATES = path.join(REPO_ROOT, "test", "example-projects"); @@ -180,6 +181,7 @@ const { values } = withUsageError( verbose: { type: "boolean", default: false }, json: { type: "boolean", default: false }, keep: { type: "boolean", default: false }, + fresh: { type: "boolean", default: false }, build: { type: "boolean", default: false }, llvm: { type: "boolean", default: false }, show: { type: "boolean", default: false }, @@ -215,7 +217,10 @@ InputBox, or contains End, or is not slot=sub, is refused without being built. whose build fails is cut down to the samples that fail it --llvm build with LLVM (implies --build); needs a Professional or Ultimate licence, and --build alone is its control - --keep leave the generated projects on disk and say where + --keep leave the generated projects on disk and say where; they + stay until deleted by hand + --fresh start a new IDE for every project; by default each lane opens + project after project in one IDE --show, --hide as tbbuild's --compile-timeout , --build-timeout , --compiler-run-timeout , --compiler-run-quiet @@ -230,8 +235,9 @@ Exit codes: when it found only unmarked samples that fail (advisory) 1 a marked sample does not compile, a marker is misused, a template does not compile, the compiler crashed on a project, --build or --llvm found a sample - that fails the build, or a \`${RUN_MARKER}\` sample raised an error, did not return or - printed something other than the page says; the report names each + that fails the build, a batch met its time limit, or a \`${RUN_MARKER}\` sample raised + an error, did not return or printed something other than the page says; the report + names each 2 the harness could not run: a refused command line, a failed self-test probe, no IDE, an unreadable --report file, a work folder it could not clear, test/harness.json missing or malformed (its exclusions included), a TB_ @@ -246,6 +252,9 @@ const { only, jobs, batchSize, seconds } = withUsageError( () => { refuseTogether(values, ["report", "census", "propose"]); refuseTogether(values, ["show", "hide"]); + // Neither starts an IDE, so there is nothing for --fresh to change. + refuseTogether(values, ["fresh", "census"]); + refuseTogether(values, ["fresh", "report"]); if (values.apply && !values.propose) throw new CliError("conflict", "--apply needs --propose", { option: "--apply" }); const jobs = numberOption(values.jobs ?? String(DEFAULT_JOBS), { option: "--jobs", integer: true, min: 1 }); @@ -758,15 +767,14 @@ const timingBatch = (batch, staged) => * Take one batch of an exclusion's canary to its stage, once: no second build, * no halving. Returns the stage it failed at, or null (canaryBatchStage). */ -async function buildCanary(batch, slot, work) { +async function buildCanary(batch, session, work) { const staged = stageBatch(batch, work); timingBatch(batch, staged); const run = staged.runs.length ? runWait() : null; const r = await compileProject({ project: staged.proj, ide: IDE, - slot, - show: wantShow({ show: values.show, hide: values.hide }), + session, build: BUILD || !!run, llvm: LLVM, run, @@ -787,7 +795,7 @@ async function buildCanary(batch, slot, work) { return { canary: batch.canary, failedAt }; } -async function buildStaged(staged, slot) { +async function buildStaged(staged, session) { // A run batch is built and its [RunAfterBuild] Sub is run, in every mode. The // run is over when the dispatcher says it is done, or when the console has // been quiet for the run's quiet period, counted from [BUILD] Executing or the @@ -798,8 +806,7 @@ async function buildStaged(staged, slot) { compileProject({ project: staged.proj, ide: IDE, - slot, - show: wantShow({ show: values.show, hide: values.hide }), + session, build: BUILD || !!run, llvm: LLVM, run, @@ -819,6 +826,10 @@ async function buildStaged(staged, slot) { // A build that failed after a clean compile is isolated as a crash is: nothing // names a sample, so it is cut down by halving. `named` is empty for that. if (r.code === 5) return { crashed: true, buildFailed: true, named: new Set(), detail: r.message }; + // A compile that met its limit, or never reported the project open: the + // batch is not judged, and that is a finding, not the end of the run + // (test/harness.md, the limits). + if (r.code === 3) return { timedOut: true, detail: r.message }; if (r.code !== 0 && r.code !== 1) { throw new Error(`tbbuild exited ${r.code} on ${staged.proj}\n${r.message}`); } @@ -886,12 +897,12 @@ async function buildStaged(staged, slot) { * isolation is tested without an IDE, and without a crash that needs two real * samples to happen. */ -function laneOf(slot, work) { +function laneOf(session, work) { return { async build(batch) { const staged = stageBatch(batch, work); timingBatch(batch, staged); - const result = await buildStaged(staged, slot); + const result = await buildStaged(staged, session); if (!values.keep) rmSync(staged.dir, { recursive: true, force: true }); return result; }, @@ -901,8 +912,12 @@ function laneOf(slot, work) { }; } -/** Run every batch across `jobs` lanes, each with its own slot and workspace. */ -async function runAll(batches, work) { +/** + * Run every batch across `jobs` lanes, each with its own slot, workspace and + * IDE session: a lane opens project after project in one IDE (lib/tb-session.mjs), + * or, with --fresh, starts a new IDE for each. `ides` counts what the lanes did. + */ +async function runAll(batches, work, ides = { starts: 0, switches: 0 }) { const queue = [...batches]; const results = []; const lanes = Array.from({ length: Math.min(jobs, queue.length) }, async (_, i) => { @@ -912,17 +927,27 @@ async function runAll(batches, work) { const laneWork = path.join(work, `lane${i}`); mkdirSync(laneWork, { recursive: true }); const slot = await leaseSlot({ tag: `check_examples lane ${i}` }); + const session = new IdeSession({ + ide: IDE, + slot, + show: wantShow({ show: values.show, hide: values.hide }), + fresh: values.fresh, + note: (line) => process.stderr.write(`${line} (lane ${i})\n`), + }); try { - const lane = laneOf(slot, laneWork); + const lane = laneOf(session, laneWork); while (queue.length) { const batch = queue.shift(); process.stderr.write( ` building ${batch.fences.length} sample(s) [${batch.project}]${batch.canary ? " (canary)" : ""} on lane ${i}\n`, ); // A canary's batch is taken to its stage once and judged as a whole. - results.push(batch.canary ? await buildCanary(batch, slot, laneWork) : await runBatch(batch, lane)); + results.push(batch.canary ? await buildCanary(batch, session, laneWork) : await runBatch(batch, lane)); } } finally { + await session.end(); + ides.starts += session.starts; + ides.switches += session.switches; await slot.release(); } }); @@ -1226,21 +1251,16 @@ async function main() { }); const batches = [...canaryBatches, ...restBatches, ...runBatches]; // The run's folder is named for this process, so that runs at once never share - // one. A folder an earlier run left, whose process has ended, goes; one that - // cannot be removed yet is still held by something of that run's (an IDE from - // before each IDE ran in its launcher's job, WIP.Harness.md, "The IDE runs - // inside a job"), and is left for a later run. + // one. A folder an earlier run left, whose process has ended, goes, unless + // that run was given --keep; one that cannot be removed yet is still held by + // something of that run's (an IDE from before each IDE ran in its launcher's + // job, WIP.Harness.md, "The IDE runs inside a job"), and is left for a later run. const runs = path.join(tmpdir(), "tbexamples"); - for (const name of existsSync(runs) ? readdirSync(runs) : []) { - if (!/^\d+$/.test(name) || alive(Number(name))) continue; - try { - rmSync(path.join(runs, name), { recursive: true, force: true }); - } catch { - // still held - } - } + sweepRunFolders(runs); const work = path.join(runs, String(process.pid)); mkdirSync(work, { recursive: true }); + // Marked from the start, so that a kept run that dies keeps its folder too. + if (values.keep) keepRunFolder(work); await fetchEmbedded(new Set(batches.map((b) => b.project))); const staged = selected.length - samples.length; @@ -1282,9 +1302,10 @@ async function main() { tidy = startTidy({ prefixes: [work] }); const t0 = Date.now(); + const ides = { starts: 0, switches: 0 }; let results; try { - results = await runAll(batches, work); + results = await runAll(batches, work, ides); } catch (e) { console.error(`check_examples: ${e.message}`); finishTidy(tidy); @@ -1448,6 +1469,7 @@ async function main() { `${real} finding(s), ${secs}s` + (real ? "" : " -- clean"), ); + say(`${ides.starts} IDE start(s), ${ides.switches} project(s) opened in an IDE already running`); for (const line of canaryLines) say(line); if (wantRun) { say( diff --git a/scripts/check_impexp_parity.mjs b/scripts/check_impexp_parity.mjs index 35d53c913..aef4dfa10 100644 --- a/scripts/check_impexp_parity.mjs +++ b/scripts/check_impexp_parity.mjs @@ -117,6 +117,25 @@ const COMMANDS = [ { args: ["import", "console.twinproj", "console"], exit: 3, why: "refused: the project exists" }, { args: ["import", "console.twinproj", "console", "--overwrite"], exit: 0 }, { args: ["export", "console.twinproj", "console-out"], exit: 0 }, + { + args: ["import", "names.twinproj", "names"], + exit: 0, + why: "names that sort apart by code point and by code unit, and a Kelvin sign in Packages", + setup: (dir) => { + cpSync(path.join(dir, "console"), path.join(dir, "names"), { recursive: true }); + for (const name of ["\u{1F600}.twin", "\u{FF21}.twin"]) + writeFileSync(path.join(dir, "names", "Sources", name), "Module M\nEnd Module\n"); + const kelvin = path.join(dir, "names", "Pac\u{212A}ages", "Pkg"); + mkdirSync(kelvin, { recursive: true }); + writeFileSync(path.join(kelvin, "Settings"), "{}\r\n"); + }, + }, + { + args: ["export", "names.twinproj", "names", "--overwrite"], + exit: 6, + why: "warns, in UTF-8: a file the project lacks, with a name outside the ANSI code page", + setup: (dir) => writeFileSync(path.join(dir, "names", "Sources", "\u{3A9}\u{1F600}.txt"), "\r\n"), + }, { args: ["settings", "sample.twinpack"], exit: 0 }, { args: ["licence", "sample.twinpack"], exit: 0 }, { args: ["changelog", "sample.twinpack"], exit: 0 }, diff --git a/scripts/impexp.mjs b/scripts/impexp.mjs index c28aef2d9..7942e1827 100644 --- a/scripts/impexp.mjs +++ b/scripts/impexp.mjs @@ -294,7 +294,8 @@ function exitCodeFor(outcome) { return outcome.stale?.length || outcome.repeated?.length ? EXIT.warned : EXIT.done; } -const byCodePoint = (a, b) => (a < b ? -1 : a > b ? 1 : 0); +// By UTF-16 code unit, as < compares strings: impexp.py and the twinBASIC edition sort the same way. +const byCodeUnit = (a, b) => (a < b ? -1 : a > b ? 1 : 0); const count = (n, noun) => `${n} ${noun}${n === 1 ? "" : "s"}`; // Paths compare without regard to case on Windows, as the file system does. @@ -440,7 +441,7 @@ export function exportProject(projectPath, folder, { overwrite = false } = {}) { const source = pathKey(projectPath); const stale = []; (function scan(dir, rel) { - for (const name of fs.readdirSync(dir).sort(byCodePoint)) { + for (const name of fs.readdirSync(dir).sort(byCodeUnit)) { if (name.toLowerCase() === GIT_NAME) continue; const full = path.join(dir, name); const entryRel = rel ? `${rel}/${name}` : name; @@ -532,7 +533,7 @@ function buildTree(src, name, rel, skipped, added) { const have = new Set(names.map((n) => n.toLowerCase())); for (const folder of STANDARD_FOLDERS) if (!have.has(folder.toLowerCase())) missing.add(folder); } - for (const entry of [...names, ...missing].sort(byCodePoint)) { + for (const entry of [...names, ...missing].sort(byCodeUnit)) { const entryRel = rel ? `${rel}/${entry}` : entry; if (missing.has(entry)) { subdirs.push(entry); @@ -746,11 +747,11 @@ function selfTest() { })(tree, ""); return out; } - const listing = (tree) => JSON.stringify([...contents(tree)].sort(([a], [b]) => byCodePoint(a, b))); + const listing = (tree) => JSON.stringify([...contents(tree)].sort(([a], [b]) => byCodeUnit(a, b))); function diskListing(d) { const out = []; (function walk(p, rel) { - for (const name of fs.readdirSync(p).sort(byCodePoint)) { + for (const name of fs.readdirSync(p).sort(byCodeUnit)) { const full = path.join(p, name), r = rel ? `${rel}/${name}` : name; if (fs.statSync(full).isDirectory()) { @@ -850,7 +851,7 @@ function selfTest() { "contents", ); eq(back.children.find((c) => c.name === "Miscellaneous").category, CATEGORY.Miscellaneous, "category"); - eq(fs.readdirSync(src).sort(byCodePoint).join(), "Packages,Settings,resources", "the tree on disk changed"); + eq(fs.readdirSync(src).sort(byCodeUnit).join(), "Packages,Settings,resources", "the tree on disk changed"); }); test("Export without --overwrite refuses, and writes nothing", () => { diff --git a/scripts/impexp.py b/scripts/impexp.py index 2be77cd5e..b238246d7 100644 --- a/scripts/impexp.py +++ b/scripts/impexp.py @@ -95,7 +95,8 @@ STANDARD_FOLDERS = ('ImportedTypeLibraries', 'Miscellaneous', 'Packages', 'Resources', 'Sources') -PROJECT_FILE = re.compile(r'\.(twinproj|twinpack)$', re.IGNORECASE) +# re.ASCII, as in a JavaScript /i regex: without it the Kelvin sign matches k. +PROJECT_FILE = re.compile(r'\.(twinproj|twinpack)$', re.IGNORECASE | re.ASCII) # -------------------------- Parser (binary -> tree) -------------------------- @@ -266,6 +267,12 @@ def exit_code_for(outcome): return EXIT['done'] +def _by_code_unit(s): + # The order of JavaScript's < on strings, by UTF-16 code unit: a character above + # U+FFFF sorts before one from U+E000 to U+FFFF, where code point order has it after. + return s.encode('utf-16-be', 'surrogatepass') + + def _count(n, noun): return f'{n} {noun}{"" if n == 1 else "s"}' @@ -426,7 +433,7 @@ def on_disk(rel): stale = [] def scan(d, rel): - for name in sorted(os.listdir(d)): + for name in sorted(os.listdir(d), key=_by_code_unit): if name.lower() == GIT_NAME: continue full = os.path.join(d, name) @@ -473,11 +480,11 @@ def _build_tree(dir_path, rel, self_key, skipped, added): # The standard folders this tree lacks, if it is the project or a package # embedded in it. missing = set() - if rel == '' or (re.fullmatch(r'packages/[^/]+', rel, re.IGNORECASE) + if rel == '' or (re.fullmatch(r'packages/[^/]+', rel, re.IGNORECASE | re.ASCII) and 'Settings' in names): have = {n.lower() for n in names} missing = {f for f in STANDARD_FOLDERS if f.lower() not in have} - for name in sorted(names + list(missing)): + for name in sorted(names + list(missing), key=_by_code_unit): full = os.path.join(dir_path, name) entry_rel = f'{rel}/{name}' if rel else name if name in missing: @@ -675,13 +682,13 @@ def walk(e, rel): return out def listing(tree): - return json.dumps(sorted(contents(tree).items())) + return json.dumps(sorted(contents(tree).items(), key=lambda kv: _by_code_unit(kv[0]))) def disk_listing(d): out = [] def walk(p, rel): - for name in sorted(os.listdir(p)): + for name in sorted(os.listdir(p), key=_by_code_unit): full = os.path.join(p, name) r = f'{rel}/{name}' if rel else name if os.path.isdir(full): @@ -788,7 +795,7 @@ def t_standard_folders(): 'Sources/,resources/,Settings', 'contents') misc = [c for c in back['children'] if c['name'] == 'Miscellaneous'][0] eq(misc['category'], CATEGORY_MISCELLANEOUS, 'category') - eq(','.join(sorted(os.listdir(src))), 'Packages,Settings,resources', + eq(','.join(sorted(os.listdir(src), key=_by_code_unit)), 'Packages,Settings,resources', 'the tree on disk changed') test('Import adds the empty folders the IDE expects, to the project and ' 'each package in it', t_standard_folders) @@ -1164,4 +1171,8 @@ def main(argv): if __name__ == '__main__': + # UTF-8 to a file or a pipe, as the other two editions write, not the ANSI code page, + # which cannot hold every name a project can have. + sys.stdout.reconfigure(encoding='utf-8') + sys.stderr.reconfigure(encoding='utf-8') sys.exit(main(sys.argv[1:])) diff --git a/scripts/impexp/impexp.twinproj b/scripts/impexp/impexp.twinproj index 62ee239cc..49a61f60b 100644 Binary files a/scripts/impexp/impexp.twinproj and b/scripts/impexp/impexp.twinproj differ diff --git a/scripts/impexp/src/Sources/ByteBuilder.twin b/scripts/impexp/src/Sources/ByteBuilder.twin index 5be7c1ba2..a3e8d4bec 100644 --- a/scripts/impexp/src/Sources/ByteBuilder.twin +++ b/scripts/impexp/src/Sources/ByteBuilder.twin @@ -50,9 +50,14 @@ Class ByteBuilder ToArray = mLen End Function + ' Room for extra more bytes: twice what is needed, up to the largest array a Long can index. Private Sub Reserve(ByVal extra As Long) - If mLen + extra <= mCap Then Exit Sub - mCap = 2 * (mLen + extra) + 64 + Dim want As Double + If CDbl(mLen) + extra <= mCap Then Exit Sub + want = 2# * (CDbl(mLen) + extra) + 64 + If want > &H7FFFFFFF Then want = CDbl(mLen) + extra + If want > &H7FFFFFFF Then Err.Raise 6 + mCap = CLng(want) ReDim Preserve mData(0 To mCap - 1) End Sub End Class diff --git a/scripts/impexp/src/Sources/FileSys.twin b/scripts/impexp/src/Sources/FileSys.twin index b5c167438..d33074e1c 100644 --- a/scripts/impexp/src/Sources/FileSys.twin +++ b/scripts/impexp/src/Sources/FileSys.twin @@ -43,6 +43,8 @@ Module FileSys Public Const KIND_NONE As Long = 0 Public Const KIND_FILE As Long = 1 Public Const KIND_FOLDER As Long = 2 + ' A file that is the project file being written, which import leaves out (ImpexpSource.KindOf only). + Public Const KIND_SELF As Long = 3 Private Const GENERIC_READ As Long = &H80000000 Private Const GENERIC_WRITE As Long = &H40000000 diff --git a/scripts/impexp/src/Sources/Impexp.twin b/scripts/impexp/src/Sources/Impexp.twin index 8f68e8e01..e3f458f95 100644 --- a/scripts/impexp/src/Sources/Impexp.twin +++ b/scripts/impexp/src/Sources/Impexp.twin @@ -3,6 +3,7 @@ ' LastReason, LastMessage and LastDetails, and has written nothing. Module Impexp Private Declare PtrSafe Function GetCurrentProcessId Lib "kernel32" () As Long + Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As LongPtr) Public Const REFUSED As Long = vbObjectError + &H1100 @@ -275,51 +276,70 @@ Module Impexp End Sub ' LF made CRLF in a code file; any other file as it is. + ' The LFs are counted first, and the runs between them copied whole. Private Function ToCrlf(ByVal name As String, b() As Byte, ByVal length As Long, out() As Byte) As Long - Dim w As ByteBuilder, i As Long - If InStr(CRLF_EXTENSIONS, "|" & LCase$(FileSys.ExtName(name)) & "|") = 0 Or Len(FileSys.ExtName(name)) = 0 Then - Erase out + Dim i As Long, adds As Long, start As Long, w As Long + Erase out + If InStr(CRLF_EXTENSIONS, "|" & TextKit.LowerAscii(FileSys.ExtName(name), True) & "|") = 0 Or Len(FileSys.ExtName(name)) = 0 Then If length > 0 Then out = b ToCrlf = length Exit Function End If - Set w = New ByteBuilder For i = 0 To length - 1 If b(i) = 10 Then If i = 0 Then - w.AddU8 13 + adds = adds + 1 ElseIf b(i - 1) <> 13 Then - w.AddU8 13 + adds = adds + 1 End If End If - w.AddU8 b(i) Next - ToCrlf = w.ToArray(out) + ToCrlf = length + adds + If length = 0 Then Exit Function + ReDim out(0 To length + adds - 1) + If adds > 0 Then + For i = 0 To length - 1 + If b(i) = 10 Then + If i = 0 Then + out(w) = 13 + w = w + 1 + ElseIf b(i - 1) <> 13 Then + RtlMoveMemory VarPtr(out(w)), VarPtr(b(start)), i - start + w = w + i - start + out(w) = 13 + w = w + 1 + start = i + End If + End If + Next + End If + RtlMoveMemory VarPtr(out(w)), VarPtr(b(start)), length - start End Function - ' The project's name in its Settings, or "" when it names none. - Private Function ProjectNameIn(ByVal settingsPath As String) As String + ' The project's name in the Settings src gives, or "" when it names none or cannot be read. + Private Function ProjectNameIn(ByVal src As ImpexpSource) As String Dim b() As Byte, n As Long, settingsText As String On Error GoTo Unreadable - n = FileSys.ReadAllBytes(settingsPath, b) + n = src.ReadAll("Settings", b) settingsText = TextKit.Utf8Decode(b, 0, n) If Len(settingsText) > 0 Then If (AscW(settingsText) And &HFFFF&) = &HFEFF& Then settingsText = Mid$(settingsText, 2) End If - ProjectNameIn = Json.TopLevelString(settingsText, "project.name") + ProjectNameIn = JsonMember.TopLevelString(settingsText, "project.name") Unreadable: End Function - Private Function BuildTree(ByVal dirPath As String, ByVal rel As String, ByVal self As String, ByVal r As Outcome) As Entry + ' The folder at rel ("" for the top one) of the tree src gives, as an entry named folderName. + Private Function BuildTree(ByVal src As ImpexpSource, ByVal rel As String, ByVal folderName As String, ByVal r As Outcome) As Entry Dim names() As String, n As Long, i As Long, total As Long Dim missing As String, have As String, standard As Variant, name As String, entryRel As String - Dim all() As String, subdirs As New Collection, files As New Collection, full As String, kind As Long - n = FileSys.ListNames(dirPath, names) + Dim all() As String, subdirs As New Collection, files As New Collection, kind As Long + n = src.ListNames(rel, names) ' The standard folders this tree lacks, if it is the project or a package in it. Dim isPackage As Boolean If rel <> "" Then - If LCase$(Left$(rel, 9)) = "packages/" And InStr(10, rel, "/") = 0 And Len(rel) > 9 Then + If TextKit.LowerAscii(Left$(rel, 9), False) = "packages/" And InStr(10, rel, "/") = 0 And Len(rel) > 9 Then For i = 0 To n - 1 If names(i) = "Settings" Then isPackage = True Next @@ -329,10 +349,10 @@ Module Impexp If rel = "" Or isPackage Then have = "|" For i = 0 To n - 1 - have = have & LCase$(names(i)) & "|" + have = have & TextKit.LowerAscii(names(i), True) & "|" Next For Each standard In Split(STANDARD_FOLDERS, "|") - If InStr(have, "|" & LCase$(standard) & "|") = 0 Then missing = missing & standard & "|" + If InStr(have, "|" & TextKit.LowerAscii(standard, True) & "|") = 0 Then missing = missing & standard & "|" Next End If @@ -351,47 +371,64 @@ Module Impexp For i = 0 To total - 1 name = all(i) - full = FileSys.JoinPath(dirPath, name) If Len(rel) > 0 Then entryRel = rel & "/" & name Else entryRel = name If InStr(missing, "|" & name & "|") > 0 Then subdirs.Add name r.Added.Add entryRel - ElseIf LCase$(name) = GIT_NAME Then + ElseIf TextKit.LowerAscii(name, True) = GIT_NAME Then r.Skipped.Add Array(entryRel, "Git's own folder") Else - kind = FileSys.KindOf(full) + kind = src.KindOf(entryRel) If kind = FileSys.KIND_FOLDER Then subdirs.Add name + ElseIf kind = FileSys.KIND_SELF Then + r.Skipped.Add Array(entryRel, "the project file itself") ElseIf kind = FileSys.KIND_FILE Then - If FileSys.PathKey(full) = self Then - r.Skipped.Add Array(entryRel, "the project file itself") - Else - files.Add name - End If + files.Add name End If End If Next Dim e As Entry, d As Variant, f As Variant, b() As Byte, crlf() As Byte, length As Long - Set e = ProjectFormat.NewFolder(FileSys.BaseName(dirPath)) + Set e = ProjectFormat.NewFolder(folderName) For Each d In subdirs If InStr(missing, "|" & d & "|") > 0 Then e.Children.Add ProjectFormat.NewFolder(d) Else If Len(rel) > 0 Then entryRel = rel & "/" & d Else entryRel = d - e.Children.Add BuildTree(FileSys.JoinPath(dirPath, d), entryRel, self, r) + e.Children.Add BuildTree(src, entryRel, d, r) End If Next For Each f In files - length = FileSys.ReadAllBytes(FileSys.JoinPath(dirPath, f), b) + If Len(rel) > 0 Then entryRel = rel & "/" & f Else entryRel = f + length = src.ReadAll(entryRel, b) length = ToCrlf(f, b, length, crlf) e.Children.Add ProjectFormat.NewFile(f, crlf, length) Next Set BuildTree = e End Function + ' The tree src gives, named after its Settings' project, or folderName when they name none. + Private Function RootTree(ByVal src As ImpexpSource, ByVal folderName As String, ByVal r As Outcome) As Entry + Dim root As Entry, name As String + Set root = BuildTree(src, "", folderName, r) + ' The IDE names the root after the project; the folder's name is the fallback. + name = ProjectNameIn(src) + If Len(name) > 0 Then root.Name = name + root.Category = ProjectFormat.CATEGORY_DEFAULT + Set RootTree = root + End Function + + ' The project file import writes for the tree src gives, into out, and its length: what Node's packFiles + ' gives for those files. folderName names the project when its Settings do not. Nothing is checked first + ' (the top folder's Settings, the file written) and nothing is written; what src raises is raised as it is. + Public Function PackTree(ByVal src As ImpexpSource, ByVal folderName As String, out() As Byte) As Long + Dim r As New Outcome + PackTree = ProjectFormat.Serialize(RootTree(src, folderName, r), out) + End Function + Public Function ImportProject(ByVal projectPath As String, ByVal folder As String, ByVal overwrite As Boolean) As Outcome - Dim settings As String, existing As Long, r As New Outcome, root As Entry, name As String + Dim settings As String, existing As Long, r As New Outcome, root As Entry, src As New ImpexpSource Dim b() As Byte, n As Long ' Everything is checked before the tree is read, so a refusal leaves the project file as it was. If FileSys.KindOf(folder) <> FileSys.KIND_FOLDER Then Refuse "missing", "input folder does not exist: " & folder, HintImport() @@ -405,11 +442,8 @@ Module Impexp Refuse "exists", projectPath & " already exists, and --overwrite is not set", HintImport() End If - Set root = BuildTree(FileSys.FullPath(folder), "", FileSys.PathKey(projectPath), r) - ' The IDE names the root after the project; the folder's name is the fallback. - name = ProjectNameIn(settings) - If Len(name) > 0 Then root.Name = name - root.Category = ProjectFormat.CATEGORY_DEFAULT + src.Init FileSys.FullPath(folder), FileSys.PathKey(projectPath) + Set root = RootTree(src, FileSys.BaseName(FileSys.FullPath(folder)), r) n = ProjectFormat.Serialize(root, b) WriteReplacing projectPath, b, n diff --git a/scripts/impexp/src/Sources/ImpexpSource.twin b/scripts/impexp/src/Sources/ImpexpSource.twin new file mode 100644 index 000000000..9613fbc81 --- /dev/null +++ b/scripts/impexp/src/Sources/ImpexpSource.twin @@ -0,0 +1,38 @@ +' Where import reads the folder it packs: the disk below the folder Init names, as this class does. +' Every path is relative to that folder, with forward slashes: "" for the folder itself, "Sources/A.twin" +' below it. Another program gives Impexp.PackTree files of its own with a class that Implements +' ImpexpSource (tblaunch's PackSource), and raises its own errors from it; its Init is never called. +Class ImpexpSource + Private mRoot As String + Private mSelf As String + + ' The folder read, and the PathKey of the project file being written, which KindOf calls KIND_SELF. + Public Sub Init(ByVal root As String, ByVal selfKey As String) + mRoot = root + mSelf = selfKey + End Sub + + ' The names in the folder at rel, "." and ".." left out, in any order, and their count. + Public Function ListNames(ByVal rel As String, names() As String) As Long + ListNames = FileSys.ListNames(PathOf(rel), names) + End Function + + ' FileSys.KIND_FILE, KIND_FOLDER or KIND_NONE for what is at rel; KIND_SELF for the project file. + Public Function KindOf(ByVal rel As String) As Long + Dim full As String + full = PathOf(rel) + KindOf = FileSys.KindOf(full) + If KindOf = FileSys.KIND_FILE Then + If FileSys.PathKey(full) = mSelf Then KindOf = FileSys.KIND_SELF + End If + End Function + + ' The bytes of the file at rel into data, and their count. + Public Function ReadAll(ByVal rel As String, data() As Byte) As Long + ReadAll = FileSys.ReadAllBytes(PathOf(rel), data) + End Function + + Private Function PathOf(ByVal rel As String) As String + If Len(rel) = 0 Then PathOf = mRoot Else PathOf = FileSys.JoinPath(mRoot, rel) + End Function +End Class diff --git a/scripts/impexp/src/Sources/Json.twin b/scripts/impexp/src/Sources/JsonMember.twin similarity index 98% rename from scripts/impexp/src/Sources/Json.twin rename to scripts/impexp/src/Sources/JsonMember.twin index b5bebe4c0..9b579f111 100644 --- a/scripts/impexp/src/Sources/Json.twin +++ b/scripts/impexp/src/Sources/JsonMember.twin @@ -1,6 +1,7 @@ ' Reads one string member of a JSON object's top level, as JSON.parse(text)[key] would find it: -' the text must be JSON as a whole, and the last of two members with one name wins. -Module Json +' the text must be JSON as a whole, and the last of two members with one name wins. Not named Json, +' because tblaunch, which compiles these modules too, has a Json module of its own. +Module JsonMember Private mText As String Private mPos As Long Private mBad As Boolean diff --git a/scripts/impexp/src/Sources/MainModule.twin b/scripts/impexp/src/Sources/MainModule.twin index b07656c10..9c05e3021 100644 --- a/scripts/impexp/src/Sources/MainModule.twin +++ b/scripts/impexp/src/Sources/MainModule.twin @@ -1,31 +1,16 @@ ' impexp -- the twinBASIC edition of scripts/impexp.mjs and scripts/impexp.py: the same commands, -' the same output and the same exit codes, and byte-identical project files. +' the same output and the same exit codes, and byte-identical project files. Run takes the command +' line and returns the exit code; Program.Main is the program's own entry point, kept apart so that +' tblaunch can compile every module but Program and call Run under its own Sub Main. Module MainModule Private Declare PtrSafe Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As LongPtr Private Declare PtrSafe Function GetConsoleMode Lib "kernel32" (ByVal hConsoleHandle As LongPtr, ByRef lpMode As Long) As Long Private Declare PtrSafe Function WriteConsoleW Lib "kernel32" (ByVal hConsoleOutput As LongPtr, ByVal lpBuffer As LongPtr, ByVal nNumberOfCharsToWrite As Long, ByRef lpNumberOfCharsWritten As Long, ByVal lpReserved As LongPtr) As Long Private Declare PtrSafe Function WriteFile Lib "kernel32" (ByVal hFile As LongPtr, ByVal lpBuffer As LongPtr, ByVal nNumberOfBytesToWrite As Long, ByRef lpNumberOfBytesWritten As Long, ByVal lpOverlapped As LongPtr) As Long - Private Declare PtrSafe Function GetCommandLineW Lib "kernel32" () As LongPtr - Private Declare PtrSafe Function CommandLineToArgvW Lib "shell32" (ByVal lpCmdLine As LongPtr, ByRef pNumArgs As Long) As LongPtr - Private Declare PtrSafe Function LocalFree Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr - Private Declare PtrSafe Function lstrlenW Lib "kernel32" (ByVal lpString As LongPtr) As Long - Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As LongPtr) - Private Declare PtrSafe Sub ExitProcess Lib "kernel32" (ByVal uExitCode As Long) Private Const STD_OUTPUT_HANDLE As Long = -11 Private Const STD_ERROR_HANDLE As Long = -12 - Public Sub Main() - Dim code As Long - On Error GoTo Crashed - code = Run(Arguments()) - ExitProcess code - Exit Sub - Crashed: - WriteErr " ERROR: " & Err.Description - ExitProcess Impexp.EXIT_FAILED - End Sub - Public Function Usage() As String Usage = Join(Array( _ "Usage:", _ @@ -54,21 +39,6 @@ Module MainModule " or the project holds one name twice"), vbLf) End Function - ' The arguments after the program's name, as the C runtime splits them. - Private Function Arguments() As Collection - Dim r As New Collection, argv As LongPtr, argc As Long, i As Long, p As LongPtr, n As Long, s As String - argv = CommandLineToArgvW(GetCommandLineW(), argc) - For i = 1 To argc - 1 - RtlMoveMemory VarPtr(p), argv + i * LenB(p), LenB(p) - n = lstrlenW(p) - s = String$(n, vbNullChar) - If n > 0 Then RtlMoveMemory StrPtr(s), p, 2 * n - r.Add s - Next - LocalFree argv - Set Arguments = r - End Function - Private Function IsProjectFile(ByVal name As String) As Boolean name = LCase$(name) IsProjectFile = Right$(name, 9) = ".twinproj" Or Right$(name, 9) = ".twinpack" diff --git a/scripts/impexp/src/Sources/Program.twin b/scripts/impexp/src/Sources/Program.twin new file mode 100644 index 000000000..2089246a9 --- /dev/null +++ b/scripts/impexp/src/Sources/Program.twin @@ -0,0 +1,36 @@ +' The program: reads the command line and hands it to MainModule.Run. Everything else is in the other +' modules, so that another program (tblaunch) can compile them under a Sub Main of its own. +Module Program + Private Declare PtrSafe Function GetCommandLineW Lib "kernel32" () As LongPtr + Private Declare PtrSafe Function CommandLineToArgvW Lib "shell32" (ByVal lpCmdLine As LongPtr, ByRef pNumArgs As Long) As LongPtr + Private Declare PtrSafe Function LocalFree Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr + Private Declare PtrSafe Function lstrlenW Lib "kernel32" (ByVal lpString As LongPtr) As Long + Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As LongPtr) + Private Declare PtrSafe Sub ExitProcess Lib "kernel32" (ByVal uExitCode As Long) + + Public Sub Main() + Dim code As Long + On Error GoTo Crashed + code = MainModule.Run(Arguments()) + ExitProcess code + Exit Sub + Crashed: + MainModule.WriteErr " ERROR: " & Err.Description + ExitProcess Impexp.EXIT_FAILED + End Sub + + ' The arguments after the program's name, as the C runtime splits them. + Private Function Arguments() As Collection + Dim r As New Collection, argv As LongPtr, argc As Long, i As Long, p As LongPtr, n As Long, s As String + argv = CommandLineToArgvW(GetCommandLineW(), argc) + For i = 1 To argc - 1 + RtlMoveMemory VarPtr(p), argv + i * LenB(p), LenB(p) + n = lstrlenW(p) + s = String$(n, vbNullChar) + If n > 0 Then RtlMoveMemory StrPtr(s), p, 2 * n + r.Add s + Next + LocalFree argv + Set Arguments = r + End Function +End Module diff --git a/scripts/impexp/src/Sources/TextKit.twin b/scripts/impexp/src/Sources/TextKit.twin index 3222155b0..f227b0ba4 100644 --- a/scripts/impexp/src/Sources/TextKit.twin +++ b/scripts/impexp/src/Sources/TextKit.twin @@ -49,6 +49,22 @@ Module TextKit Latin1Encode = Len(s) End Function + ' The ASCII capitals made small, and with kelvin the Kelvin sign (U+212A) made k; every other character + ' kept. Compared with an ASCII name, that is JavaScript's toLowerCase (kelvin True), or a /i regex + ' (kelvin False): no other character becomes ASCII in either. LCase$ differs (it keeps U+212A). + Public Function LowerAscii(ByVal s As String, ByVal kelvin As Boolean) As String + Dim i As Long, c As Long + LowerAscii = s + For i = 1 To Len(s) + c = AscW(Mid$(s, i, 1)) And &HFFFF& + If c >= 65 And c <= 90 Then + Mid$(LowerAscii, i, 1) = ChrW$(c + 32) + ElseIf c = &H212A& And kelvin Then + Mid$(LowerAscii, i, 1) = "k" + End If + Next + End Function + ' -1, 0 or 1 by UTF-16 code unit, as JavaScript's < compares two strings. Public Function CompareOrdinal(ByVal a As String, ByVal b As String) As Long Dim i As Long, n As Long, ca As Long, cb As Long @@ -69,18 +85,41 @@ Module TextKit End If End Function - ' Sorts items(0 To count - 1) by CompareOrdinal; equal items keep their order. + ' Sorts items(0 To count - 1) by CompareOrdinal; equal items keep their order (a merge sort). Public Sub SortOrdinal(items() As String, ByVal count As Long) - Dim i As Long, j As Long, v As String - For i = 1 To count - 1 - v = items(i) - j = i - 1 - Do While j >= 0 - If CompareOrdinal(items(j), v) <= 0 Then Exit Do - items(j + 1) = items(j) - j = j - 1 - Loop - items(j + 1) = v + Dim tmp() As String + If count < 2 Then Exit Sub + ReDim tmp(0 To count - 1) + MergeSort items, tmp, 0, count + End Sub + + ' items(lo To hi - 1) sorted, through tmp. + Private Sub MergeSort(items() As String, tmp() As String, ByVal lo As Long, ByVal hi As Long) + Dim half As Long, i As Long, j As Long, k As Long + If hi - lo < 2 Then Exit Sub + half = lo + (hi - lo) \ 2 + MergeSort items, tmp, lo, half + MergeSort items, tmp, half, hi + If CompareOrdinal(items(half - 1), items(half)) <= 0 Then Exit Sub + i = lo + j = half + For k = lo To hi - 1 + If j >= hi Then + tmp(k) = items(i) + i = i + 1 + ElseIf i >= half Then + tmp(k) = items(j) + j = j + 1 + ElseIf CompareOrdinal(items(j), items(i)) < 0 Then + tmp(k) = items(j) + j = j + 1 + Else + tmp(k) = items(i) + i = i + 1 + End If + Next + For k = lo To hi - 1 + items(k) = tmp(k) Next End Sub diff --git a/scripts/lib/cli-cases.mjs b/scripts/lib/cli-cases.mjs index 23d32eee2..e7dcd2ae9 100644 --- a/scripts/lib/cli-cases.mjs +++ b/scripts/lib/cli-cases.mjs @@ -880,6 +880,9 @@ bad("scripts/shoot_docs.mjs", ["--jobs=17"], "--jobs expects a whole number from say("--report, --census and --propose cannot be given together"), ); bad(tool, ["--show", "--hide"], say("--show and --hide cannot be given together")); + // --fresh changes how the lanes start their IDEs, and neither of these starts one. + bad(tool, ["--fresh", "--census"], say("--fresh and --census cannot be given together")); + bad(tool, ["--report", "survey.json", "--fresh"], say("--fresh and --report cannot be given together")); } bad( diff --git a/scripts/lib/example-batches.mjs b/scripts/lib/example-batches.mjs index 11fc7a473..85acd2883 100644 --- a/scripts/lib/example-batches.mjs +++ b/scripts/lib/example-batches.mjs @@ -8,11 +8,14 @@ // run. The lane that stages and builds for real stays in check_examples.mjs, // with everything else that reads the command line. -import { existsSync, readdirSync, readFileSync } from "node:fs"; +import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; import path from "node:path"; import { REPO_ROOT } from "../../lib/repo-paths.mjs"; import { EXCLUSION_MODES, EXCLUSION_STAGES, exclusionProblems } from "./harness-settings.mjs"; import { LLVM_REFUSAL } from "./tb-ide.mjs"; +import { keepRunFolder, sweepRunFolders } from "./tb-registry.mjs"; +import { IdeSession } from "./tb-session.mjs"; import { BODY_SLOTS, CONCAT_KEY, @@ -494,16 +497,18 @@ export function failureStage(line, log = []) { * The stage a canary's batch failed at, from its one build: compile errors and * a crash are `build`, a failed build is where its line is (failureStage, so an * LLVM refusal is `build`), and a run that did not finish (it never began, - * stopped, or a sample did not return) is `compiler-run`. Null when it got through. + * stopped, or a sample did not return) is `compiler-run`. A compile that met its + * limit (3) is `limit`: the batch was not judged. Null when it got through. * * @param {{ code: number, message?: string, log?: string[], run?: { done: boolean } | null }} r * compileProject's code, message and build log, and the parsed run of a run batch - * @returns {"build" | "compiler-run" | null} - * @throws {Error} for a code that is the harness's (2, 3) + * @returns {"build" | "compiler-run" | "limit" | null} + * @throws {Error} for a code that is the harness's (2) */ export function canaryBatchStage({ code, message, log = [], run = null }) { if (code === 1 || code === 4) return "build"; if (code === 5) return failureStage(message, log); + if (code === 3) return "limit"; if (code === 0) return run && !run.done ? "compiler-run" : null; throw new Error(message || `the build exited ${code}`); } @@ -518,6 +523,9 @@ export function canaryBatchStage({ code, message, log = [], run = null }) { * @returns {{ finding: boolean, text: string }} */ export function canaryVerdict({ pkg, stage, count }, failedAt) { + if (failedAt.includes("limit")) { + return { finding: true, text: `${pkg}: a canary batch met its limit (test/harness.json), so it was not judged` }; + } if (stage !== "build" && failedAt.includes("build")) { return { finding: true, text: `${pkg}: canary failed at build, before ${stage}: re-probe its exclusions` }; } @@ -694,6 +702,20 @@ const sameRow = (row) => row.replace(/[/\\]DocSamples\d+[/\\]/, "/"); * sample -- hundreds of IDE starts -- and then blame an arbitrary one. */ const templateOwnRows = new Map(); + +/** + * The template built with no samples met its limit twice, so what it draws on + * its own is not known. runBatch reports the batch that asked as not judged. + */ +class TemplateTimeout extends Error { + constructor(project, detail) { + super( + `the \`${project}\` template, built with no samples to tell its own rows from a batch's, met its limit twice`, + ); + this.detail = `${this.message}: ${detail}`; + } +} + function ownRowsOf(project, lane) { if (!templateOwnRows.has(project)) { templateOwnRows.set( @@ -702,10 +724,16 @@ function ownRowsOf(project, lane) { // A read with no rows and no canary is read once more, and never believed: // it would leave every row of the template counted as a sample's, for the // rest of the run. A read with rows of its own was not silent, and needs - // no canary, as in runBatch. + // no canary, as in runBatch. A build that met its limit read nothing at + // all, and is built once more too; met twice, it is forgotten, so that + // a later batch asks again, and never taken for a clean template. const silent = (r) => !r.crashed && r.canaryProblem && !(r.unattributed ?? []).length; let result = await lane.build({ project, fences: [] }); - if (silent(result)) result = await lane.build({ project, fences: [] }); + if (result.timedOut || silent(result)) result = await lane.build({ project, fences: [] }); + if (result.timedOut) { + templateOwnRows.delete(project); + throw new TemplateTimeout(project, result.detail); + } if (silent(result)) { throw new Error( `the canary did not report in the \`${project}\` template built with no samples, ` + @@ -908,6 +936,24 @@ async function together(batch, a, b, lane, failed = false) { return { ...blank(), blamed: members.map((f) => f.id) }; } +/** + * A batch whose compile met its limit, or that the IDE never reported open: the + * IDE said nothing about any sample in it, and splitting would not help, since + * what is slow is the template's load (WinReg's batches take as long with no + * samples in them). One finding, against its first sample, says so, and the + * samples come back as crashed ones do, so that none is counted as compiling. + * The run goes on (test/harness.md, the limits). + */ +function notJudged(batch, lane, detail) { + const { rep, ids } = leafOf(batch); + lane.finding( + rep, + `was not judged: its batch of ${ids.length} sample(s) [${batch.project}] did not finish compiling within its limit`, + detail, + ); + return { ...blank(), crashed: ids }; +} + /** * Build a batch, isolating a crash or an unattributable diagnostic. * @@ -921,7 +967,17 @@ async function together(batch, a, b, lane, failed = false) { * compiling while the run fails with a row naming no page. */ export async function runBatch(batch, lane) { + try { + return await judgeBatch(batch, lane); + } catch (e) { + if (e instanceof TemplateTimeout) return notJudged(batch, lane, e.detail); + throw e; + } +} + +async function judgeBatch(batch, lane) { let result = await buildTwiceOnFailure(batch, lane); + if (result.timedOut) return notJudged(batch, lane, result.detail); if (result.crashed) return isolateCrash(batch, result.named, lane, !!result.buildFailed, result.detail); // The canary is needed only by a read that holds no error: that is the read @@ -937,6 +993,7 @@ export async function runBatch(batch, lane) { `(${result.canaryProblem}), and nothing else did: building it again`, ); result = await buildTwiceOnFailure(batch, lane); + if (result.timedOut) return notJudged(batch, lane, result.detail); if (result.crashed) return isolateCrash(batch, result.named, lane, !!result.buildFailed, result.detail); if (result.canaryProblem && !(await heard(result, batch.project, lane))) { // Twice silent: either the IDE keeps reading early under this load, or a @@ -1124,6 +1181,146 @@ const INFO_PROBES = [ ["another language is untouched", "js", (p) => p.lang === "js"], ]; +/** + * The sweep at the start of a run (tb-registry.mjs, sweepRunFolders), on a + * folder of its own: an ended run's folder goes, a kept one, a live run's and + * one not named for a process stay. Returns the failures. + */ +function sweepProbes() { + const root = mkdtempSync(path.join(tmpdir(), "tbx-sweep-probe-")); + try { + for (const name of ["11", "12", "13", "notes"]) { + mkdirSync(path.join(root, name)); + writeFileSync(path.join(root, name, "x.twin"), ""); + } + keepRunFolder(path.join(root, "12")); + const removed = sweepRunFolders(root, { isAlive: (pid) => pid === 13 }); + const left = readdirSync(root).sort(); + return `${removed} / ${left}` === "11 / 12,13,notes" + ? [] + : [`sweep: removed ${removed}, left ${left} (wanted 11 removed; 12 kept, 13 alive, notes not a run)`]; + } finally { + rmSync(root, { recursive: true, force: true }); + } +} + +/** + * A lane's IDE session (tb-session.mjs) through a page that is a plain object: + * the switch, each way the IDE is given up for a new one, and what is reset in + * the page before a switch. Each case is a list of what the driver was asked + * to do; returns the failures. + */ +async function sessionProbes() { + const failures = []; + const run = async (name, steps, want, setup = {}) => { + const log = []; + const page = { p: null, target: "win32", trace: false, dirty: false, alive: true, dead: false, asks: 1, ...setup }; + let pid = 100; + const driver = { + launch: async ({ project }) => { + log.push(`launch ${project}`); + Object.assign(page, { p: project, alive: true, dead: false }); + return { pid: ++pid, port: 1 }; + }, + attach: async () => (page.noPort ? null : { dialogs: [], close: () => {} }), + shutdown: async (h) => log.push(`end ${h.pid}`), + alive: () => page.alive, + state: async () => { + if (page.dead) throw new Error("the page did not answer"); + return { p: page.p, closing: false, dirty: page.dirty, target: page.target, trace: page.trace }; + }, + switchTo: async (_c, project) => { + if (page.dead) throw new Error("the page did not answer"); + const dirty = page.dirty; + if (page.asks) { + page.p = project; + log.push(`switch ${project}`); + } + return { asked: page.asks, dirty }; + }, + closeProject: async () => { + log.push("close"); + page.p = null; + }, + resetTarget: async () => { + log.push("win32"); + page.target = "win32"; + }, + traceOff: async () => { + log.push("trace off"); + page.trace = false; + }, + discard: async () => { + log.push("discard"); + page.dirty = false; + }, + sleep: async () => {}, + }; + const s = new IdeSession({ ide: "tb.exe", fresh: !!setup.fresh, driver }); + try { + for (const step of steps) await step(s, page); + } catch (e) { + log.push(`threw ${e.message}`); + } + if (log.join(" | ") !== want.join(" | ")) failures.push(`session: ${name} -> ${log.join(" | ")}`); + }; + const open = (p) => (s) => s.open(p); + const after = (code) => (s) => s.after(code); + const set = (fields) => (_s, page) => Object.assign(page, fields); + // A switch: the second project opens in the first one's IDE. + await run("a switch", [open("A"), after(0), open("B"), after(1), open("C")], ["launch A", "switch B", "switch C"]); + // --fresh: a new IDE for every project. + await run("--fresh", [open("A"), after(0), open("B")], ["launch A", "end 101", "launch B"], { fresh: true }); + // A harness fault or a compile that never settled gives the IDE up. + for (const code of [2, 3]) { + await run(`exit ${code}`, [open("A"), after(code), open("B")], ["launch A", "end 101", "launch B"]); + } + // A page that does not answer, an IDE that has ended, a page with no openProject(). + await run("a dead page", [open("A"), after(0), set({ dead: true }), open("B")], ["launch A", "end 101", "launch B"]); + await run( + "an ended IDE", + [open("A"), after(0), set({ alive: false }), open("B")], + ["launch A", "end 101", "launch B"], + ); + await run( + "no openProject()", + [open("A"), after(0), set({ asks: 0 }), open("B")], + ["launch A", "end 101", "launch B"], + ); + // A new IDE that opens no debug port is the caller's exit 2. + await run( + "no debug port", + [set({ noPort: true }), open("A")], + ["launch A", "end 101", "threw the IDE never exposed a debug port"], + ); + // A crash: the project is closed at once, Safe Mode and TRACE-MODE are undone, + // and the next project opens by a switch in the same IDE. + await run( + "a crash into Safe Mode", + [open("A"), set({ target: "nocompile", trace: true }), after(4), open("B")], + ["launch A", "close", "win32", "trace off", "switch B"], + ); + // Safe Mode or TRACE-MODE found at a switch, whatever the last project's exit. + await run( + "Safe Mode at a switch", + [open("A"), after(0), set({ target: "nocompile" }), open("B")], + ["launch A", "close", "win32", "switch B"], + ); + await run( + "TRACE-MODE at a switch", + [open("A"), after(0), set({ trace: true }), open("B")], + ["launch A", "trace off", "switch B"], + ); + // A changed project's "Save now?" is answered Discard Changes. + await run( + "a changed project", + [open("A"), after(0), set({ dirty: true }), open("B")], + ["launch A", "switch B", "discard"], + ); + return failures; +} +const SESSION_PROBES = 13; + export async function runProbes(say) { const failures = []; for (const [name, src, want] of CLASSIFIER_PROBES) { @@ -1403,6 +1600,23 @@ export async function runProbes(say) { ) { failures.push(`failed build: two samples that fail only together -> ${JSON.stringify(pair.said[0])}`); } + // A batch that met its limit is one finding and is not split: every sample in it + // comes back unjudged, none as compiling, and the run goes on. + const slow = fakeLane(() => false); + slow.build = async () => { + slow.builds++; + return { timedOut: true, detail: "timeout: the compile did not settle within 10 s" }; + }; + const slowResult = await runBatch(five, slow); + if ( + `${[...slowResult.crashed].sort()} / ${slow.found} / ${slow.builds}` !== "a,b,c,d,e / a / 1" || + !slow.said[0]?.[0].startsWith("was not judged: its batch of 5 sample(s) [console]") || + !slow.said[0]?.[1].includes("did not settle") + ) { + failures.push(`limit: a batch that met its limit -> ${slowResult.crashed} / ${JSON.stringify(slow.said)}`); + } + failures.push(...(await sessionProbes())); + failures.push(...sweepProbes()); // The canaries: what a batch's rows say about them, and what runBatch does when // they are not there. A batch with no rows at all is the one that matters, since // it is what an IDE that read its diagnostics early returns. @@ -1520,6 +1734,56 @@ export async function runProbes(say) { if (!ownSet?.has(sameRow(ownRow)) || cl.builds !== 1) { failures.push(`canaries: an empty template with rows of its own was not believed (${cl.builds} builds)`); } + // A template built with no samples that meets its limit is built once more. + // Met twice, its rows are not known: the batch that asked is not judged, and + // the template is forgotten for the next batch to ask again, never taken as + // one that draws nothing (which would blame the samples for its rows). + const pkgRow = "{ERROR} /Packages/P/Sources/P.twin [1,1]: TB5001 p"; + const slowTemplate = (times) => { + const lane = canaryLane( + () => null, + () => [], + () => [pkgRow], + ); + const build = lane.build; + lane.slow = 0; + lane.found = []; + lane.finding = (_rep, ...lines) => lane.found.push(lines.join(" | ")); + lane.build = async (b) => { + if (b.fences.length || lane.slow >= times) return build(b); + lane.slow++; + lane.builds++; + return { timedOut: true, detail: "timeout: the compile did not settle within 10 s" }; + }; + return lane; + }; + templateOwnRows.clear(); + cl = slowTemplate(1); + let templateResult = await runBatch(five, cl); + if ( + cl.builds !== 3 || + templateResult.crashed.length || + templateResult.blamed.length || + !templateResult.templateFaults.length + ) { + failures.push( + `canaries: a template that met its limit once was not built again and believed ` + + `(${cl.builds} builds, crashed ${templateResult.crashed}, blamed ${templateResult.blamed})`, + ); + } + templateOwnRows.clear(); + cl = slowTemplate(2); + templateResult = await runBatch(five, cl); + if ( + `${[...templateResult.crashed].sort()} / ${templateResult.blamed.length} / ${cl.builds}` !== "a,b,c,d,e / 0 / 3" || + !cl.found[0]?.includes("met its limit twice") || + templateOwnRows.has("console") + ) { + failures.push( + `canaries: a template that met its limit twice was taken as clean or remembered ` + + `(${templateResult.crashed} / ${templateResult.blamed} / ${cl.builds} builds / ${JSON.stringify(cl.found)})`, + ); + } templateOwnRows.clear(); cl = canaryLane((ids) => (ids.has("a") && ids.has("e") ? "masked" : null)); threw = await outcome(cl, five); @@ -2183,11 +2447,12 @@ export async function runProbes(say) { // 10: the stage a canary's batch failed at, from its one build. let harness = false; try { - canaryBatchStage({ code: 3, message: "never settled" }); + canaryBatchStage({ code: 2, message: "the IDE never exposed a debug port" }); } catch { harness = true; } if ( + canaryBatchStage({ code: 3, message: "never settled" }) !== "limit" || canaryBatchStage({ code: 1 }) !== "build" || canaryBatchStage({ code: 4 }) !== "build" || canaryBatchStage({ code: 5, message: codegen }) !== "build" || @@ -2228,6 +2493,12 @@ export async function runProbes(say) { "Re: canary failed at build as expected, 41 samples not built", ], [{ pkg: "Re", stage: "build", count: 41 }, [null], true, "Re: canary passed build: re-probe its exclusions"], + [ + { pkg: "Re", stage: "build", count: 41 }, + ["build", "limit"], + true, + "Re: a canary batch met its limit (test/harness.json), so it was not judged", + ], ]; for (const [canary, failedAt, finding, text] of verdicts) { const v = canaryVerdict(canary, failedAt); @@ -2245,10 +2516,11 @@ export async function runProbes(say) { // 7 of what runBatch does about a batch whose canary did not report, 3 of the // template built with no samples) + 7 of a failed build (wording, when to // record it, one that passes when built again, a pair that fails only together) - // + 17 of the exclusion list + the check_run probes, which count themselves. + // + 1 of a batch that met its limit + 18 of the exclusion list + the IDE + // session's (SESSION_PROBES) + the check_run probes, which count themselves. say( - `ok ${CLASSIFIER_PROBES.length + INFO_PROBES.length + 114 + runProbeCount} probes: ` + - "classifier, markup, line mapping, batching, splitting, crash isolation, failed builds, canaries, concat, " + + `ok ${CLASSIFIER_PROBES.length + INFO_PROBES.length + 116 + SESSION_PROBES + runProbeCount} probes: ` + + "classifier, markup, line mapping, batching, splitting, crash isolation, failed builds, limits, the IDE session, canaries, concat, " + "resources, exclusions, the report and check_run", ); return true; diff --git a/scripts/lib/tb-build.mjs b/scripts/lib/tb-build.mjs index 010af9af7..ce473c866 100644 --- a/scripts/lib/tb-build.mjs +++ b/scripts/lib/tb-build.mjs @@ -24,9 +24,11 @@ // which can be a clean compile with no rows. Every caller here packs its own // projects, which are always readable. // -// It always ends its IDE before it returns, unless `keep` is set. Node holds the -// IDE's launcher in a job of its own (launchIde), so an IDE also goes when the -// process does -- a run that is stopped leaves none of its lanes' IDEs behind. +// It always ends its IDE before it returns, unless `keep` is set, or unless the +// IDE is a session's (tb-session.mjs), which opens project after project in one +// IDE and ends it itself. Node holds the IDE's launcher in a job of its own +// (launchIde), so an IDE also goes when the process does -- a run that is +// stopped leaves none of its lanes' IDEs behind. // // Concurrency: calls are independent and can run at once, each IDE on a slot (a private // desktop, from tbbroker) and a DevTools port of its own, in different slots when the @@ -75,6 +77,15 @@ import { timing } from "./tb-timings.mjs"; * own `compiler.buildOptions` is what asks for LLVM * @param {boolean} [o.followRun] whether the project has a [RunAfterBuild] Sub whose compile * the build follows after the link (buildProject); unknown by default + * @param {import("./tb-session.mjs").IdeSession} [o.session] the IDE to open the project + * in, by a switch when it holds one already (tb-session.mjs), in place of a new IDE + * for this call; the session owns the IDE, so it is left running, and `slot`, + * `port`, `show` and `keep` are the session's business. A project opened by a + * switch that ends in a harness fault (2), or that the IDE never reported open (3), + * is built once more in a new IDE, and that result is the one returned: a reused + * IDE's fault is never reported as the project's. A compile that met its limit + * after the project opened is the project's (WinReg's batches meet it in a new IDE + * too), and is not built again * @param {number} [o.buildTimeout] ms for the build, from the press to its end (default: * test/harness.json's `build`); with `run`, to [BUILD] Executing * @param {{done?: (lines: string[]) => boolean, runMs?: number, quietMs?: number} | null} [o.run] @@ -98,9 +109,19 @@ import { timing } from "./tb-timings.mjs"; * of the log. `counts` is errors, warnings, hints, infos. `crashFiles` names, * for 4, the files the compiler died parsing. `built` is the file a * successful build wrote, and `buildLog` the console from the build's first - * line on. + * line on. `how` is "cold" or, with a session, "switch"; `opened` is false when + * the IDE never reported the project open; `retried` is the message of a reused + * IDE's result that sent the project to a new IDE. */ -export async function compileProject({ +export async function compileProject(o) { + const r = await compileOnce(o); + const reusedFault = r.code === 2 || (r.code === 3 && r.opened === false); + if (!o.session || r.how !== "switch" || !reusedFault) return r; + // session.after has ended that IDE, so this opens a new one. + return { ...(await compileOnce(o)), retried: r.message }; +} + +async function compileOnce({ project, ide, slot = null, @@ -114,12 +135,27 @@ export async function compileProject({ buildTimeout, followRun, run = null, + session = null, }) { let handle = null; let c = null; + // With a session: how the project was opened, and where this project's dialogs begin. + let how = "cold"; + let dialogsFrom = 0; + let ended = 2; const t0 = Date.now(); const result = (code, fields = {}) => { - timing("project", { project: path.resolve(project), code, arch, llvm, build, run: !!run, ms: Date.now() - t0 }); + ended = code; + timing("project", { + project: path.resolve(project), + code, + arch, + llvm, + build, + run: !!run, + how, + ms: Date.now() - t0, + }); return outcomeOf(code, fields); }; const outcomeOf = (code, fields) => ({ @@ -127,7 +163,7 @@ export async function compileProject({ message: "", rows: [], counts: [0, 0, 0, 0], - dialogs: c ? c.dialogs.map((d) => d.message) : [], + dialogs: c ? c.dialogs.slice(dialogsFrom).map((d) => d.message) : [], openedIn: null, arch, idePid: handle?.pid ?? null, @@ -135,19 +171,36 @@ export async function compileProject({ crashFiles: [], built: null, buildLog: [], + how, ...fields, }); try { - try { - handle = await launchIde({ exe: ide, project, slot, port, show, keep }); - } catch (e) { - return result(2, { message: e.message }); + if (session) { + try { + ({ c, handle, how } = await session.open(project)); + } catch (e) { + return result(2, { message: e.message }); + } + dialogsFrom = c.dialogs.length; + } else { + try { + handle = await launchIde({ exe: ide, project, slot, port, show, keep }); + } catch (e) { + return result(2, { message: e.message }); + } + c = await attachIde(handle.port); + if (!c) return result(2, { message: "the IDE never exposed a debug port" }); } - c = await attachIde(handle.port); - if (!c) return result(2, { message: "the IDE never exposed a debug port" }); - let outcome = compileOutcome(await waitForCompile(c, { project, timeout }), { name: project }); - if (!outcome.ok) return result(outcome.code, { message: outcome.message, crashFiles: outcome.crashFiles ?? [] }); + const waited = await waitForCompile(c, { project, timeout }); + let outcome = compileOutcome(waited, { name: project }); + if (!outcome.ok) { + return result(outcome.code, { + message: outcome.message, + crashFiles: outcome.crashFiles ?? [], + opened: waited.loaded, + }); + } // Set on every run, win32 included, and what is reported is the compile under // it: see setBuildTarget. Switching restarts the compiler, which compiles the @@ -199,12 +252,17 @@ export async function compileProject({ if (!built.ok) return result(5, { ...found, message: built.message, buildLog: built.log }); return result(0, { ...found, built: built.file, buildLog: built.log }); } finally { - // A close that threw must not skip ending the IDE, or mask what was thrown. - try { - c?.close(); - } catch { - /* the IDE is about to be ended */ + if (session) { + // The session's IDE: kept for the next project, recovered, or ended (IdeSession.after). + await session.after(ended); + } else { + // A close that threw must not skip ending the IDE, or mask what was thrown. + try { + c?.close(); + } catch { + /* the IDE is about to be ended */ + } + if (!keep) await shutdownIdeAsync(handle); } - if (!keep) await shutdownIdeAsync(handle); } } diff --git a/scripts/lib/tb-ide-console.mjs b/scripts/lib/tb-ide-console.mjs index 69d52d883..a00bc8377 100644 --- a/scripts/lib/tb-ide-console.mjs +++ b/scripts/lib/tb-ide-console.mjs @@ -137,24 +137,27 @@ export async function linesSince(c, mark = null, { prefix } = {}) { // event_clearDebugConsole, which a program's Debug.Cls raises, from the pane's // Clear command, and on closing the project. So a wrapper assigned to that // global sees each of those clears, and reads the console as readConsole does, -// without timestamps, before letting it go. A page is wrapped once: a second -// call finds the record already there and leaves it alone. +// without timestamps, before letting it go. A page is wrapped once, and each +// call starts the record afresh: an IDE that opens project after project +// (tb-session.mjs) clears the console as it closes each one, and those clears +// are the last project's, not the next one's. const KEEP_CLEARS_JS = `(() => { if (typeof clearDebugConsole !== "function") return false; if (!Array.isArray(window.__tbKeptClears)) { const clear = clearDebugConsole; - window.__tbKeptClears = []; clearDebugConsole = function () { window.__tbKeptClears.push(${consoleJs(false, 0, null)} ?? ""); return clear.apply(this, arguments); }; } + window.__tbKeptClears = []; return true; })()`; /** - * Keep what each later clear of the DEBUG CONSOLE erases, for keptClears. - * False when this IDE has no global `clearDebugConsole()` to wrap. + * Keep what each later clear of the DEBUG CONSOLE erases, for keptClears, + * forgetting what earlier clears erased. False when this IDE has no global + * `clearDebugConsole()` to wrap. */ export const keepClears = (c) => c.evaluate(KEEP_CLEARS_JS); diff --git a/scripts/lib/tb-ide.mjs b/scripts/lib/tb-ide.mjs index 56184b0e0..ded95dd91 100644 --- a/scripts/lib/tb-ide.mjs +++ b/scripts/lib/tb-ide.mjs @@ -656,10 +656,11 @@ export function desktopWindows(desktop, { children = false } = {}) { * [left, top, right, bottom] in the picture's pixels. With PW_CLIENTONLY (1) the client area * is drawn at the picture's top left. `layered` is a layered window's [colour key as a * COLORREF, alpha, LWA_ flags], else null: PW_RENDERFULLCONTENT draws the key colour's pixels - * black and every pixel opaque, and flags 1 draws them in the key colour. + * black and every pixel opaque, and flags 1 draws them in the key colour. `active` says whether + * its caption is drawn as the active window's (WS_ACTIVECAPTION). * * @param {number} [o.flags] PrintWindow's flags (default 2) - * @returns {Promise<{width: number, height: number, dpi: number, frame: number[], client: number[], layered: number[] | null, texts: string[]}>} + * @returns {Promise<{width: number, height: number, dpi: number, frame: number[], client: number[], layered: number[] | null, active: boolean, texts: string[]}>} */ export function captureWindow(desktop, hwnd, file, { flags = 2 } = {}) { return onDesktopWindows(desktop, { @@ -693,6 +694,20 @@ export function postWindowMessage(desktop, hwnd, msg, wParam = 0, lParam = 0) { }); } +/** + * Makes a window on a private desktop the active window there, as a click on it does: a + * program started on a desktop that is not on screen can be left with its caption drawn + * inactive. Its thread's input is attached to the caller's for SetForegroundWindow, + * SetActiveWindow and SetFocus. + * + * @param {string} desktop + * @param {number} hwnd from desktopWindows + * @returns {Promise<{active: boolean}>} whether its caption is then drawn active + */ +export function activateWindow(desktop, hwnd) { + return onDesktopWindows(desktop, { TBBUILD_WINDOWS: "activate", TBBUILD_HWND: String(hwnd) }); +} + /** * What a tool prints under --keep: the kept IDE's pid, and the commands that end * it with every process it started (/T takes the compiler and the rest of its @@ -1079,6 +1094,39 @@ export async function awaitCrashName(c, crash, { timeout = 5000 } = {}) { // before the edit's for the answer. const EARLY_QUIET_MS = 300; +// The status bar's column of each problems-panel label, in the order of the +// counts the wire keeps (errors, warnings, hints, infos). +const ROW_LABEL_COLUMN = { "{ERROR}": 0, "{WARNING}": 1, "{HINT}": 2, "{INFO}": 3 }; + +/** + * The panel rows that are not in a file the wire reports on. The compiler + * reports no diagnostics for References or Packages (`src` in BUILD_STATE_JS + * leaves both out), yet the panel and the status bar count what an embedded + * package has wrong with itself, so for such a project the wire's counts can + * never equal the page's. Those rows are the difference. + * + * A row that does not read as `{LABEL} [line,col]: text`, or whose label + * is unknown, is not counted here: the sample then has a row more than the + * wire's total explains, and does not agree. So does a row of a listed file + * whose path was read differently. + * + * @param {string[]} rows the sample's rows (readBuildState) + * @param {string[]} src the files the wire reports on, as `twinbasic:` + * @returns {{n: number, counts: number[]}} + */ +export function unlistedRows(rows, src) { + const listed = new Set(src.map((u) => u.replace(/^twinbasic:/, "").toLowerCase())); + const counts = [0, 0, 0, 0]; + let n = 0; + for (const r of rows) { + const m = /^(\{[A-Z]+\}) (.*?) \[\d+,\d+\]: /.exec(r); + if (!m || !(m[1] in ROW_LABEL_COLUMN) || listed.has(m[2].toLowerCase())) continue; + counts[ROW_LABEL_COLUMN[m[1]]]++; + n++; + } + return { n, counts }; +} + /** * Wait for the project to open and its compile to settle. * @@ -1091,8 +1139,11 @@ const EARLY_QUIET_MS = 300; * * The wait ends when the sample has stood still for five seconds, or sooner * when `c.wire` has seen the compile end and the sample agrees with it: the - * same counts, and a row for each. A compile the wire had already seen end - * when the wait began does not count. A wait that follows an action --- an + * same counts, and a row for each. The rows of files the wire does not report + * on, an embedded package's own errors, are added to the wire's counts + * (unlistedRows), and the sample must then stand unchanged for the quiet + * period as well, since nothing else vouches that they have all arrived. A + * compile the wire had already seen end when the wait began does not count. A wait that follows an action --- an * Apply, an edit --- could otherwise begin before the action's compile and * take the one before it, so it waits for a newer compile, or for the sample * to stand still. @@ -1189,12 +1240,15 @@ export async function waitForCompile(c, { project, timeout = timeoutMs("compile" // behind its traffic. Then the compile must still be the latest after // EARLY_QUIET_MS, since each keystroke starts a compile of its own. wire.expect(v.src); - let w = up ? wire.check(v.src) : null; + let w = wire.check(v.src); if (w && before.done && w.seq <= before.seq) w = null; const counts = [v.e, v.w, v.h, v.i].map(Number); - const total = w ? w.counts.reduce((a, b) => a + b, 0) : -1; - if (w && w.counts.every((n, k) => n === counts[k]) && v.rows.length === total) { - if (agreed?.seq !== w.seq) agreed = { seq: w.seq, at: now }; + // What the wire cannot see, the rows of an embedded package's own files. + const extra = w ? unlistedRows(v.rows, v.src) : null; + const total = w ? w.counts.reduce((a, b) => a + b, 0) + extra.n : -1; + if (up && w && w.counts.every((n, k) => n + extra.counts[k] === counts[k]) && v.rows.length === total) { + // With rows of the wire's blind spot, the quiet is the sample's too. + if (agreed?.seq !== w.seq || (extra.n > 0 && agreed.s !== s)) agreed = { seq: w.seq, at: now, s }; else if (now - agreed.at >= EARLY_QUIET_MS) { last = s; early = true; @@ -1204,7 +1258,10 @@ export async function waitForCompile(c, { project, timeout = timeoutMs("compile" next = Math.min(next, agreed.at + EARLY_QUIET_MS); } else { agreed = null; - if (w && now - w.at < 2000) next = Math.min(next, now + 50); + // The wire has the compile and the page has yet to show it (the status, + // the counts, the rows), or has yet to list its files: look again soon. + const at = w ? w.at : v.src ? null : wire.lastAt(); + if (at && now - at < 2000) next = Math.min(next, now + 50); } } if (!up || s !== last) stableSince = now; diff --git a/scripts/lib/tb-launch.ps1 b/scripts/lib/tb-launch.ps1 index 736f2f93f..6d22c8c4c 100644 --- a/scripts/lib/tb-launch.ps1 +++ b/scripts/lib/tb-launch.ps1 @@ -40,8 +40,8 @@ # # With TBBUILD_WINDOWS set, nothing is launched: the script works on the windows # of the private desktop TBBUILD_DESKTOP, which a launch made and still holds -# open, prints one line of JSON and ends (tb-ide.mjs's desktopWindows and -# captureWindow): +# open, prints one line of JSON and ends (tb-ide.mjs's desktopWindows, +# captureWindow, postWindowMessage and activateWindow): # # TBBUILD_WINDOWS=list every top-level window on the desktop, with # TBBUILD_CHILDREN=1 the children of each visible one @@ -62,6 +62,10 @@ # pressed on a desktop that is not on screen reaches # no window, so WM_SYSCOMMAND SC_KEYMENU with a letter # opens a window's menu, as Alt and the letter do +# TBBUILD_WINDOWS=activate makes the window TBBUILD_HWND the active window of +# its desktop, as a click on it does, its thread's +# input attached to this one's for the calls; the line +# says whether its caption is then drawn active # # tb-ide.mjs passes the script with each line that is only a comment emptied, so # no line of the C# below may start with `#`. @@ -120,6 +124,10 @@ using System.Threading; public static class TbWindows { public delegate bool EnumProc(IntPtr hwnd, IntPtr lParam); [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left, Top, Right, Bottom; } + [StructLayout(LayoutKind.Sequential)] public struct WINDOWINFO { + public uint cbSize; public RECT rcWindow, rcClient; public uint dwStyle, dwExStyle, dwWindowStatus; + public uint cxWindowBorders, cyWindowBorders; public ushort atomWindowType, wCreatorVersion; + } [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] static extern IntPtr OpenDesktop(string name, int flags, bool inherit, uint access); @@ -138,6 +146,13 @@ public static class TbWindows { [DllImport("user32.dll")] static extern IntPtr SetThreadDpiAwarenessContext(IntPtr ctx); [DllImport("user32.dll", SetLastError = true)] static extern bool PrintWindow(IntPtr h, IntPtr hdc, uint flags); [DllImport("user32.dll", SetLastError = true)] static extern bool PostMessage(IntPtr h, uint m, IntPtr w, IntPtr l); + [DllImport("user32.dll")] static extern bool GetWindowInfo(IntPtr h, ref WINDOWINFO i); + [DllImport("user32.dll")] static extern bool AttachThreadInput(uint from, uint to, bool attach); + [DllImport("user32.dll")] static extern bool BringWindowToTop(IntPtr h); + [DllImport("user32.dll")] static extern bool SetForegroundWindow(IntPtr h); + [DllImport("user32.dll")] static extern IntPtr SetActiveWindow(IntPtr h); + [DllImport("user32.dll")] static extern IntPtr SetFocus(IntPtr h); + [DllImport("kernel32.dll")] static extern uint GetCurrentThreadId(); [DllImport("user32.dll")] static extern bool GetLayeredWindowAttributes(IntPtr h, out uint key, out byte alpha, out uint flags); [DllImport("dwmapi.dll")] static extern int DwmGetWindowAttribute(IntPtr h, int a, out RECT r, int n); [DllImport("user32.dll")] static extern bool GetClientRect(IntPtr h, out RECT r); @@ -161,6 +176,12 @@ public static class TbWindows { CloseHandle(p); return System.IO.Path.GetFileName(r); } + // whether the window's caption is drawn active (WS_ACTIVECAPTION) + static bool Active(IntPtr h) { + WINDOWINFO i = new WINDOWINFO(); + i.cbSize = (uint)Marshal.SizeOf(typeof(WINDOWINFO)); + return GetWindowInfo(h, ref i) && (i.dwWindowStatus & 1) != 0; + } static string Str(string s) { StringBuilder b = new StringBuilder("\""); foreach (char c in s) { @@ -251,7 +272,7 @@ public static class TbWindows { string layered = GetLayeredWindowAttributes(h, out key, out alpha, out lf) ? "[" + key + "," + alpha + "," + lf + "]" : "null"; result = "{\"width\":" + w + ",\"height\":" + ht + ",\"dpi\":" + GetDpiForWindow(h) + ",\"frame\":" + Box(f, r) + ",\"client\":" + Box(cr, r) + - ",\"layered\":" + layered + ",\"texts\":[" + string.Join(",", texts.ToArray()) + "]}"; + ",\"layered\":" + layered + ",\"active\":" + (Active(h) ? "true" : "false") + ",\"texts\":[" + string.Join(",", texts.ToArray()) + "]}"; }); return result; } @@ -264,6 +285,28 @@ public static class TbWindows { }); return "{\"posted\":true}"; } + + public static string Activate(string desktop, long hwnd) { + bool active = false; + OnDesktop(desktop, (desk) => { + IntPtr h = new IntPtr(hwnd); + if (!IsWindow(h)) throw new Exception("there is no window " + hwnd); + uint pid; + uint them = GetWindowThreadProcessId(h, out pid); + uint me = GetCurrentThreadId(); + bool attached = AttachThreadInput(me, them, true); + try { + BringWindowToTop(h); + SetForegroundWindow(h); + SetActiveWindow(h); + SetFocus(h); + } finally { + if (attached) AttachThreadInput(me, them, false); + } + for (int i = 0; i < 20 && !(active = Active(h)); i++) Thread.Sleep(50); + }); + return "{\"active\":" + (active ? "true" : "false") + "}"; + } } '@ $desktop = $env:TBBUILD_DESKTOP @@ -274,8 +317,10 @@ public static class TbWindows { Write-Output ([TbWindows]::Capture($desktop, [long]$env:TBBUILD_HWND, $flags, $env:TBBUILD_FILE)) } elseif ($env:TBBUILD_WINDOWS -eq "post") { Write-Output ([TbWindows]::Post($desktop, [long]$env:TBBUILD_HWND, [uint32]$env:TBBUILD_MSG, [long]$env:TBBUILD_WPARAM, [long]$env:TBBUILD_LPARAM)) + } elseif ($env:TBBUILD_WINDOWS -eq "activate") { + Write-Output ([TbWindows]::Activate($desktop, [long]$env:TBBUILD_HWND)) } else { - throw "TBBUILD_WINDOWS is not list, capture or post: $($env:TBBUILD_WINDOWS)" + throw "TBBUILD_WINDOWS is not list, capture, post or activate: $($env:TBBUILD_WINDOWS)" } exit 0 } diff --git a/scripts/lib/tb-registry.mjs b/scripts/lib/tb-registry.mjs index 82d6fe914..67d1297ec 100644 --- a/scripts/lib/tb-registry.mjs +++ b/scripts/lib/tb-registry.mjs @@ -495,6 +495,36 @@ export function alive(pid) { } } +/** The file a run's folder holds when it was asked to keep it (--keep). */ +export const KEEP_MARK = ".keep"; + +/** Mark a run's folder as one to keep: sweepRunFolders leaves it alone. */ +export function keepRunFolder(dir) { + mkdirSync(dir, { recursive: true }); + writeFileSync(path.join(dir, KEEP_MARK), "kept with --keep: delete this folder by hand\n"); +} + +/** + * Remove the folders earlier runs left under `runs`, each named for its run's + * process id, whose process has ended. A folder marked by keepRunFolder stays, + * and so does one that cannot be removed yet (still held by something of that + * run's), for a later run to try again. Returns the names removed. + */ +export function sweepRunFolders(runs, { isAlive = alive } = {}) { + const removed = []; + for (const name of existsSync(runs) ? readdirSync(runs) : []) { + if (!/^\d+$/.test(name) || isAlive(Number(name))) continue; + if (existsSync(path.join(runs, name, KEEP_MARK))) continue; + try { + rmSync(path.join(runs, name), { recursive: true, force: true }); + removed.push(name); + } catch { + // still held + } + } + return removed; +} + /** * Take charge of the registry for this run: record what is there, and clear * out what an earlier run on the same folders left behind. diff --git a/scripts/lib/tb-session.mjs b/scripts/lib/tb-session.mjs new file mode 100644 index 000000000..083c5af84 --- /dev/null +++ b/scripts/lib/tb-session.mjs @@ -0,0 +1,233 @@ +// One IDE for many projects: the first is opened as the IDE starts, and each +// later one through the page's own File > Open Project, so a tool that compiles +// project after project pays an IDE start once rather than once a project. +// +// The switch is the page's `openProject()`, with `hostAppObject` replaced for +// that one call by an object whose OpenProject answers with the path: the real +// one opens a native file dialog, which nobody can answer on a private desktop. +// openProject() then runs `closeProjectSafely`, which ends the old project's +// compiler and loads the new project in a new one. Calling `root.loadProject` +// over CDP is NOT a switch: it skips the close, and the tree keeps the old +// project (WIP.Harness.md, "One project per IDE"). Nothing here enables CDP's +// Debugger domain either: the page holds about 90 `debugger;` statements. +// +// What a reused IDE carries from one project to the next, and what this undoes +// before each switch (BETA 1010, each measured): +// +// * Safe Mode. A compiler crash loop sets the build box to `nocompile`, and +// the page's loadProject keeps that target: every project opened after it +// reads as a crash. The remedy (owner): close the project, set the box to +// win32 with no project open, then open the next one. A project that put the +// IDE into Safe Mode is never opened again in that IDE (it crashes back into +// it); a bisect half is another project and may be. +// * TRACE-MODE. Any NATIVE EXCEPTION turns on `g_TraceMode` for the IDE's +// session, and each new compiler starts with it, so a later crash prints a +// thread dump where a fresh IDE prints two "[IDE] auto-activated TRACE-MODE" +// lines. It is set back to false, which is the Help menu's toggle without +// its restart (the switch restarts the compiler). +// * A changed project's "Save now?" box, which closeProjectSafely opens; it is +// answered Discard Changes. No harness project is edited, so it is not +// expected. +// +// The harness's own state on the page and the connection is reset by its +// owners: keepClears starts a new record on each call (tb-ide-console.mjs), and +// compileProject reads `c.dialogs` from a mark it takes after the switch. +// +// A reused IDE is given up, and the next project starts a new one, when a +// switch fails (the page does not answer, the IDE has ended, openProject() did +// not ask for a path), and after a project that ended in a harness fault (2) or +// a compile that never settled (3). compileProject builds such a project once +// more in a new IDE before it believes the result. A compiler crash (4) is +// recovered in place: the project is closed and the box set back to win32. +// +// The decisions are written against a driver, so that the probes can drive a +// session through a page that is a plain object (test/example-batches.test.mjs). + +import { attachIde, launchIde, shutdownIdeAsync, sleep } from "./tb-ide.mjs"; +import { click } from "./tb-click.mjs"; +import { timing } from "./tb-timings.mjs"; + +// What a switch needs to know about the page, in one evaluate. +const STATE_JS = `JSON.stringify({ + p: typeof projectFilePath === "undefined" ? null : projectFilePath || null, + closing: typeof isClosingProject !== "undefined" && !!isClosingProject, + dirty: typeof projectIsDirty !== "undefined" && !!projectIsDirty, + target: typeof buildConfigSelector !== "undefined" && buildConfigSelector ? buildConfigSelector.value : null, + trace: typeof g_TraceMode !== "undefined" && g_TraceMode === true, +})`; + +// openProject() with the host's file dialog answered by `path`. openProject asks +// for the path synchronously, as its first act, so hostAppObject is the real one +// again before this evaluate returns. `asked` is how many times it asked: 0 means +// this IDE has no such path, and the switch did nothing. +const switchJs = (path) => `(() => { + if (typeof openProject !== "function" || typeof hostAppObject === "undefined") return JSON.stringify({ asked: 0 }); + const dirty = typeof projectIsDirty !== "undefined" && !!projectIsDirty; + const real = hostAppObject; + let asked = 0; + hostAppObject = { OpenProject: () => { asked++; return Promise.resolve(${JSON.stringify(path)}); } }; + try { openProject(); } finally { hostAppObject = real; } + return JSON.stringify({ asked: asked, dirty: dirty }); +})()`; + +// The modal box closeProjectSafely opens for a changed project. +const DISCARD = { css: ".modalDialogContainer .msgBoxButton", text: "Discard Changes", last: true }; + +/** The real IDE, for a session that is not a probe's. */ +export const IDE_DRIVER = { + launch: (o) => launchIde(o), + attach: (port) => attachIde(port), + shutdown: (handle) => shutdownIdeAsync(handle), + alive(pid) { + try { + process.kill(pid, 0); + return true; + } catch { + return false; + } + }, + state: async (c) => JSON.parse(await c.evaluate(STATE_JS)), + switchTo: async (c, project) => JSON.parse(await c.evaluate(switchJs(project))), + closeProject: (c) => + c.evaluate(`typeof executeIdeCommand === "function" ? executeIdeCommand("tbProject_Close") : closeProjectSafely()`), + resetTarget: (c) => + c.evaluate(`cancelAllModalDialogs(); buildConfigSelector.value = "win32"; buildConfigSelector.onchange()`), + traceOff: (c) => c.evaluate("g_TraceMode = false"), + discard: (c) => click(c, DISCARD), + sleep, +}; + +// How long a close may take before the IDE is given up: measured at 0.22 to 0.34 s. +const CLOSE_MS = 10 * 1000; + +export class IdeSession { + /** + * @param {object} o + * @param {string} o.ide twinBASIC.exe + * @param {object} [o.slot] the slot (leaseSlot) every IDE of the session goes on + * @param {boolean} [o.show] on the user's desktop instead of a private one + * @param {boolean} [o.fresh] a new IDE for every project: the session only launches and ends + * @param {(line: string) => void} [o.note] says why an IDE was given up + * @param {object} [o.driver] IDE_DRIVER, or a probe's + */ + constructor({ ide, slot = null, show = false, fresh = false, note = () => {}, driver = IDE_DRIVER }) { + Object.assign(this, { ide, slot, show, fresh, note, driver }); + this.handle = null; + this.c = null; + // Counts, for a run's summary: IDEs started, and projects opened by a switch. + this.starts = 0; + this.switches = 0; + } + + get live() { + return this.handle !== null; + } + + /** + * Open `project`: in a new IDE, or by a switch in the one the session holds. + * @returns {Promise<{c: object, handle: object, how: "cold" | "switch"}>} + * @throws {Error} when a new IDE cannot be started or attached, with the message compileProject reports as exit 2 + */ + async open(project) { + if (this.live && this.fresh) await this.end(); + if (!this.live) return this.#cold(project); + if (!this.driver.alive(this.handle.pid)) { + await this.end("the IDE has ended"); + return this.#cold(project); + } + const t0 = Date.now(); + let reset = {}; + try { + reset = await this.#reset(); + const r = await this.driver.switchTo(this.c, project); + if (!r.asked) throw new Error("openProject() did not ask for a path"); + if (r.dirty) await this.driver.discard(this.c); + this.switches++; + timing("switch", { project, ms: Date.now() - t0, dirty: !!r.dirty, ...reset }); + return { c: this.c, handle: this.handle, how: "switch" }; + } catch (e) { + await this.end(`a switch failed (${e.message})`); + return this.#cold(project); + } + } + + /** + * What the project's result means for the IDE: given up after a harness fault + * or a compile that never settled, recovered in place after a compiler crash, + * kept otherwise. Never throws. + * @param {number} code compileProject's + */ + async after(code) { + if (!this.live) return; + if (this.fresh) return this.end(); + if (code === 2 || code === 3) return this.end(`its last project ended with exit ${code}`); + if (code !== 4) return; + // The crashed project is closed now, so that its compiler stops restarting, + // and is never opened again in this IDE. + try { + await this.#close(); + await this.#reset(); + } catch (e) { + await this.end(`the crashed project did not close (${e.message})`); + } + } + + /** End the IDE, by its pid; the next open starts a new one. Never throws. */ + async end(why = "") { + const { handle, c } = this; + this.handle = null; + this.c = null; + if (!handle) return; + if (why) this.note(` starting a new IDE: ${why}`); + try { + c?.close(); + } catch { + /* the IDE is about to be ended */ + } + try { + await this.driver.shutdown(handle); + } catch { + /* gone already */ + } + } + + async #cold(project) { + const handle = await this.driver.launch({ exe: this.ide, project, slot: this.slot, show: this.show }); + const c = await this.driver.attach(handle.port); + if (!c) { + await this.driver.shutdown(handle); + throw new Error("the IDE never exposed a debug port"); + } + this.handle = handle; + this.c = c; + this.starts++; + return { c, handle, how: "cold" }; + } + + // Close the project the page holds, and wait for the close to finish. + async #close() { + let s = await this.driver.state(this.c); + if (!s.p) return; + await this.driver.closeProject(this.c); + if (s.dirty) await this.driver.discard(this.c); + const until = Date.now() + CLOSE_MS; + for (;;) { + s = await this.driver.state(this.c); + if (!s.p && !s.closing) return; + if (Date.now() > until) throw new Error(`the project was still open ${CLOSE_MS / 1000} s after File > Close`); + await this.driver.sleep(100); + } + } + + // Undo what a project leaves in the page: Safe Mode and TRACE-MODE. + async #reset() { + const s = await this.driver.state(this.c); + const out = { safeMode: s.target === "nocompile", trace: s.trace }; + if (out.safeMode) { + await this.#close(); + await this.driver.resetTarget(this.c); + } + if (s.trace) await this.driver.traceOff(this.c); + return out; + } +} diff --git a/scripts/lib/tb-wire.mjs b/scripts/lib/tb-wire.mjs index 2e98a764b..3d77672d2 100644 --- a/scripts/lib/tb-wire.mjs +++ b/scripts/lib/tb-wire.mjs @@ -7,19 +7,35 @@ export function watchCompiles(c) { let seq = 0; let expected = []; let waiters = []; + // A wake that came while nobody was waiting -- waitForCompile reading a + // sample -- is kept for the next changed(), which then returns at once. + let pending = false; // The last few compiles, for tb-timings.mjs (`compiles`). const history = []; const socks = new Set(); const wake = () => { const w = waiters; waiters = []; + if (!w.length) pending = true; for (const f of w) f(); }; const complete = (uris) => cur && cur.gen === gen && uris.length > 0 && uris.every((u) => cur.done.has(u)); const take = (o, id) => { if (o.event === "compilationStarted") { socks.add(id); - cur = { seq: ++seq, gen, done: new Map(), started: Date.now() }; + // A compiler's first two compiles, ids 0 and 1, come within a few ms of + // each other as it starts, and only one set of diagnostics follows the + // pair. They come on the debugger socket and the diagnostics on the + // language socket, so the set can arrive before id 1 does; taken as a + // compile of its own, id 1 then never completes, and the wait stands + // still for five seconds. So id 1 after id 0 of the same compiler is the + // same compile. + const cid = Number.parseInt(o.body?.compileId, 16); + if (cid === 1 && cur?.cid === 0 && cur.gen === gen) { + cur.cid = 1; + return; + } + cur = { seq: ++seq, gen, cid, done: new Map(), started: Date.now() }; history.push(cur); if (history.length > 10) history.shift(); } else if (o.method === "textDocument/publishDiagnostics" && cur && o.params?.uri) { @@ -27,7 +43,11 @@ export function watchCompiles(c) { const p = o.params; const was = complete(expected); cur.done.set(p.uri, { n: [p.errorCount, p.warningCount, p.hintCount, p.infoCount].map(Number), at: Date.now() }); - if (!was && complete(expected)) wake(); + // Wake for the compile completing, and for a file the waiter does not + // know of. Before the page's tree has its files, `expected` is empty and + // nothing could complete it: a compile that ended then woke no one, and + // the wait took it only on the next 1 Hz sample, 0.94 s later (median). + if (!was && (complete(expected) || !expected.includes(p.uri))) wake(); } }; c.on((m) => { @@ -67,7 +87,16 @@ export function watchCompiles(c) { return { seq: h.seq, started: h.started, ended: ats.length ? Math.max(...ats) : null, files: ats.length }; }); }, + // When the current compile's latest diagnostics arrived, or null. + lastAt() { + if (!cur || cur.gen !== gen || !cur.done.size) return null; + return Math.max(...[...cur.done.values()].map((d) => d.at)); + }, changed(ms) { + if (pending) { + pending = false; + return Promise.resolve(); + } return new Promise((resolve) => { const done = () => { clearTimeout(t); diff --git a/scripts/probe_build_twice.mjs b/scripts/probe_build_twice.mjs index 6d80a8510..04ba7cf9d 100644 --- a/scripts/probe_build_twice.mjs +++ b/scripts/probe_build_twice.mjs @@ -15,8 +15,8 @@ // lengths sometimes fall in different 4-byte steps, which moves everything after // the block by 4 and changes about 44 bytes of .text. // -// Each build is made in an IDE of its own (an IDE reused for a second project -// wedges), in one slot (tbbroker), from a project staged again before each build into the +// Each build is made in an IDE of its own, so that nothing an IDE kept from the first +// build can be what differs, in one slot (tbbroker), from a project staged again before each build into the // same folders with the same build path, so that no path can be what differs. The // exe is copied out as soon as the build is done. --vb6 does the same with VB6, // for the reproducer's vb6/ project, whose exe has no such block, and prints every diff --git a/scripts/shoot_docs.mjs b/scripts/shoot_docs.mjs index 27a6db517..2da41ac96 100644 --- a/scripts/shoot_docs.mjs +++ b/scripts/shoot_docs.mjs @@ -167,6 +167,7 @@ import { attach } from "./lib/tb-cdp.mjs"; import { consoleMark, linesSince } from "./lib/tb-ide-console.mjs"; import { removeTree } from "./lib/tb-ide-copy.mjs"; import { + activateWindow, awaitNewCompiler, buildProject, captureWindow, @@ -184,11 +185,14 @@ import { dropBundle, writeBundle } from "./svgshot/bundle.mjs"; import { svgOfPage } from "./svgshot/capture.mjs"; import { useSubsetCache } from "./svgshot/fonts.mjs"; import { holdsUserName, judgeSvg, SVG_FAITHFUL, writeSvg } from "./svgshot/keep.mjs"; -import { unpackProject } from "./lib/tb-project.mjs"; +import { stageProject, unpackProject } from "./lib/tb-project.mjs"; +import { holdLlvmCache } from "./lib/tb-llvm-cache.mjs"; +import { guard, presentKeys, press, serverRequests } from "../test/ide/building-kit.mjs"; import { checkHarness } from "./lib/harness-settings.mjs"; import { findIde, unsupportedIde } from "./lib/tb-install.mjs"; import { Lane } from "./lib/tb-lane.mjs"; import { + answerMessageBox, click, clickAt, editorText, @@ -618,11 +622,13 @@ async function unsteadyRects(conn, clip, unsteady) { }); } -// The pauses between the captures `capture` takes of one state, in milliseconds: the -// last two let the page rest long enough to settle. +// The pauses between captures, in milliseconds, once two agree on a picture that is not the +// one wanted: a raster's other version turns over in the idle time between captures, not +// under captures back to back, and a state still on its way settles. const CAPTURE_GAPS = [150, 150, 300, 600, 1500, 1500]; -// How long the page is left alone before the first capture. -const REST_MS = 1000; +// How long `capture` goes on for a picture that has not settled, or that has settled on +// another picture than the one wanted. +const CAPTURE_BUDGET_MS = 5500; // Fails the picture `name` when `text` holds the Windows user name, quoting where. function refuseUserName(text, name, what) { @@ -649,27 +655,21 @@ async function capture(conn, name, clip, { frame, away = null, keep = null, soli try { if (keep) await cutoutOn(conn, keep, solid); else await frames(conn); - // The corner pixels of a rounded box that has just appeared (a menu, a submenu, a - // dialog) are drawn a grey level differently when the page is captured within about a - // second of it, and stay so whatever follows. The page changes nothing in that second - // (no element, class or style changes), so there is no condition to wait for. - await sleep(REST_MS); const params = { format: "png" }; if (clip) params.clip = { ...clip, scale: 1 }; - // Captures of one unchanged state come out as two or more versions that differ in a - // few pixels by a few grey levels (the edge of a shadow's blur, of the status bar's - // scaled Ko-fi icon): the compositor draws them a little differently from frame to - // frame, which pixels and how often varies from run to run, and no way of taking the - // capture removes it (captureBeyondViewport and fromSurface:false do, but they also - // drop the scrollbars and the alpha channel). Some of it also settles only once the - // page has been left alone for a second or so after the last change, and captures in - // quick succession do not leave it alone: a submenu's corner pixel, the shadows of a - // dialog's buttons just after another dialog with large pictures has closed. Nothing in - // the page says when. So the captures are taken further and further apart - // (CAPTURE_GAPS), and the picture is the one that equals the file already there when a - // capture does, else the last capture that equals the one before it; with no file - // there, the first that does. A picture is rewritten only when the IDE draws something - // else. + // A picture that has not changed is final at its first capture once the page is quiet + // and two frames are drawn, so the page is captured back to back, with no rest, until + // one capture equals the file already there or two in a row agree. But a capture is not + // byte-stable: the compositor draws some pictures in two or more versions, a few pixels + // to tens of thousands apart, from one capture to the next (a submenu's shadow corner, a + // gradient's dither, the striped ground round a designer), and no way of taking it + // removes that (captureBeyondViewport and fromSurface:false do, but they also drop the + // scrollbars and the alpha channel); and some states are still on their way when the + // shot's own condition is met (a rename box's colour, a designer's readout fading in). So + // a picture two captures agree on that is not the file is not kept at once: the captures + // go on, CAPTURE_GAPS apart, until one equals the file or CAPTURE_BUDGET_MS have gone, + // and the last two that agreed are kept. A picture is rewritten only when the IDE draws + // something else. // A new light picture has no file to equal, and prefers the dark picture (`prefer`) as // long as its first capture is within the noise of it: then one the theme does not change // comes out with the dark one's pixels. Else it is taken as a new picture. @@ -693,8 +693,10 @@ async function capture(conn, name, clip, { frame, away = null, keep = null, soli // one that matches the file or the dark picture there keeps that picture's bytes, so a // pixel that flickers does not rewrite the file on every run. const masks = await unsteadyRects(conn, clip, unsteady); + const t0 = Date.now(); let last = null; let agreed = null; + let gap = 0; for (let i = 0; ; i++) { const { data } = await conn.send("Page.captureScreenshot", params); const png = Buffer.from(data, "base64"); @@ -707,11 +709,13 @@ async function capture(conn, name, clip, { frame, away = null, keep = null, soli labels: { before: `CAPTURE ${i - 1}`, after: `CAPTURE ${i}` }, }); } - if (last && same(last, png, masks)) agreed = png; - if (agreed && !want && !prefer) return await picked(agreed); - if (i === CAPTURE_GAPS.length) break; + if (last && same(last, png, masks)) { + agreed = png; + if (!want && !prefer) return await picked(agreed); + } + if (Date.now() - t0 >= CAPTURE_BUDGET_MS) break; + if (agreed) await sleep(CAPTURE_GAPS[Math.min(gap++, CAPTURE_GAPS.length - 1)]); last = png; - await sleep(CAPTURE_GAPS[i]); } if (agreed) return await picked(agreed); throw new Error(`the page for ${name} kept changing: no two captures in a row were equal`); @@ -929,8 +933,10 @@ async function fixPageSize(c) { // not guarded, RemoveRecentsList, is replaced by a call that does nothing. Then // the IDE's options go back to their defaults, the saved panel layouts and // keyboard groups go, the panel features are all allowed, and the recent lists -// are the tool's own. The language is left as the IDE runs it, and so are the -// options the schema does not list. Returns what differed from the defaults. +// are the tool's own. The title bar shows the window maximized, as the host tells the page +// when it maximizes the window (the window itself is left alone: maximizing it would have the +// IDE save its place in the registry). The language is left as the IDE runs it, and so are +// the options the schema does not list. Returns what differed from the defaults. const PAGE_DEFAULTS = `(() => { const blocked = new Set(["RemoveRecentsList"]); hostAppObject = new Proxy(hostAppObject, { @@ -962,6 +968,8 @@ const PAGE_DEFAULTS = `(() => { e.classList.add("frontPageListViewLIST"); listviewFromArray(e, [], () => {}); }; + if (!rootMenuMaximize?.classList.contains("isMaximized")) differed.push("the window was not maximized"); + cefWindowChangeNotification("WINDOW-MAXIMIZED"); changedIdeOptions(); return JSON.stringify(differed); })()`; @@ -978,7 +986,10 @@ const setRecents = (c, entries) => // A setup is one IDE: `start` which opens it and returns the connection, // `prepare` which brings it to a state the shots start from and returns their // context, and `port` when it needs a port chosen before it is bound (the help -// add-in's detached window), which its slot then carries. `run` holds the lane, +// add-in's detached window), which its slot then carries; `end`, when given, runs +// once the IDE has ended, whatever happened, to check or give back what the setup +// holds (a lease, the registry the Building setups' ActiveX builds wrote and +// cleaned). `run` holds the lane, // its slot (tbbroker: the IDE's private desktop), the work folder and what the // setup has to put back. @@ -1110,7 +1121,9 @@ async function startSample(run) { // references, the warnings and the aliases a Project Settings picture shows. Without the // VB package the form cannot compile, so the form and the line that shows it go // (`keepForm` leaves them, for a variant that has the package). `stage`, a folder, is copied -// onto the project as well. +// onto the project as well. The build path is the templates' own: the dialog draws a row +// again now and then with the project's real value, over the one a shot sets in the page +// (templateBuildPath), and the lane's default is in its temporary folder, under the user's. const startSettings = (variant, { keepForm = false, stage = null } = {}) => async (run) => { @@ -1125,7 +1138,7 @@ const startSettings = const main = path.join(src, "Sources", "MainModule.twin"); writeFileSync(main, readFileSync(main, "utf8").replace("frmMain.Show", 'Debug.Print "Hello"')); } - return run.lane.open(src); + return run.lane.open(src, { buildPath: BD_BUILD_PATH }); }; async function prepareSample(run) { @@ -1469,6 +1482,25 @@ const SETUPS = { projects: { start: startProjects(), prepare: prepareSample }, "projects-refs": { start: startProjects({ refs: true }), prepare: prepareProjectsRefs }, "projects-start": { start: startNoProject, prepare: prepareNoProject }, + building: { start: (run) => startBuilding("exe", "Building")(run), prepare: prepareSample, end: endBuilding }, + "building-new": { start: startNoProject, prepare: prepareBuildingNew }, + "building-ax": { + start: (run) => startBuilding("ax", "BuildingActiveX")(run), + prepare: prepareBuildingAx, + end: endBuilding, + }, + "building-hklm": { start: startBuildingHklm, prepare: prepareNoProject, end: endBuilding }, + "building-llvm": { + start: (run) => + startBuilding("exe", "BuildingLLVM", { settings: { "compiler.buildOptions": "+llvm" }, llvm: true })(run), + prepare: prepareBuildingLlvm, + end: endBuilding, + }, + "building-pkg": { + start: (run) => startBuilding("pkg", "BuildingPackage")(run), + prepare: prepareBuildingPkg, + end: endBuilding, + }, customcontrols: { start: startCustomControls, prepare: prepareWithDesigners }, code: { start: startCode, prepare: prepareSample }, sample9: { start: startSample9, prepare: prepareSample }, @@ -1611,7 +1643,7 @@ async function dialogStill(c, { ms = 250, timeout = 5000, root = TOP_MODAL, what // `annotate`, a shot's list of primitives (lib/shot-annotate.mjs), is drawn over // the page for the capture and taken off again however that goes; the clip grows to // hold what it drew. -async function dialogShot(c, name, clipOf = (m) => m, annotate = null) { +async function dialogShot(c, name, clipOf = (m) => m, annotate = null, { unsteady = null } = {}) { await c.evaluate("document.activeElement?.blur?.()"); await frames(c); const box = (await modals(c)).pop(); @@ -1622,12 +1654,17 @@ async function dialogShot(c, name, clipOf = (m) => m, annotate = null) { const { box: drawn } = await annotateOver(c, annotate); if (drawn) area = union(area, drawn); } - return await capture(c, name, snapOut(area), { away: () => parkMouse(c) }); + return await capture(c, name, snapOut(area), { away: () => parkMouse(c), unsteady }); } finally { if (annotate) await unannotate(c); } } +// The two "See your logo here!" boxes of the VIP Gold supporters on About and the splash, the +// last two of the logos: their gradient is dithered differently from capture to capture, by a +// level or two over thousands of pixels, beyond a capture's noise (owner: unsteady). +const VIP_GOLD_SPARES = [{ on: { css: ".vipGoldX:nth-last-child(2)" } }, { on: { css: ".vipGoldX:last-child" } }]; + // Opens a dialog by its command and returns once its title is in and it has stopped // changing for `still` milliseconds; `run` takes the picture and the dialog is closed // with `close` however that goes. @@ -3668,6 +3705,33 @@ async function gsSearch(c, query, { packages = false } = {}) { ); if (!settled) throw new Error(`the search for "${query}" never settled`); await c.evaluate(`${GS_BODY}.getRootNode().activeElement?.blur()`); + // The list keeps each row's height from when it first measured it and sets its scroll range + // from those: a row measured while the panel or its fonts were settling keeps a height a + // little too tall, and a thumb showed over two results that fit (owner: measure them again). + // The list's own notifyChangedItem, which the IDE calls when a row changes, drops a row's + // height; the list measures it again when it repaints. + const LIST = `${GS_BODY}.querySelector("#resultsList")?.listview`; + const before = await c.evaluate(`(() => { + const l = ${LIST}; + if (!l || typeof l.notifyChangedItem !== "function" || l.useCachedItemHeights) return null; + const at = { paint: l.lastRepaintTime ?? 0, range: l.lastScrollRangeUpdateTime ?? 0 }; + for (let i = 0; i < l.itemCount; i++) l.notifyChangedItem(i); + return at; +})()`); + if (!before) throw new Error("the results list cannot be told to measure its rows again"); + if (last) { + const measured = await waitFor( + c, + () => + c.evaluate(`(() => { + const l = ${LIST}; + return !l.repaintTimer && !l.scrollrangeTimer && + ((l.lastRepaintTime ?? 0) > ${before.paint} || (l.lastScrollRangeUpdateTime ?? 0) > ${before.range}); +})()`), + { timeout: 3000, interval: 50 }, + ); + if (!measured) throw new Error("the results list did not repaint after its rows were measured again"); + } await frames(c); return last; } @@ -4768,34 +4832,55 @@ const formsChapterShots = [ } }, }, - formStateShot("Designer_TabIndex", async (c) => { - // the designer focused with a click on an empty part of the form, the pointer left there - // (moved away, the pointer readout shows or not by the moment it left), then Ctrl held - const at = await formPoint(c, 300, 245); - await pressAt(c, at.x, at.y); + formStateShot( + "Designer_TabIndex", + async (c) => { + // the designer focused with a click on an empty part of the form, the pointer left there + // (moved away, the pointer readout shows or not by the moment it left), then Ctrl held + const at = await formPoint(c, 300, 245); + await pressAt(c, at.x, at.y); + await mouseMove(c, at.x, at.y); + const readout = () => + c.evaluate(`(() => { + const e = ${DESIGNER_GLOBALS}.designerDragInfoLeft; + return !!e && e.getBoundingClientRect().width > 0 && e.innerText.includes("x:300 y:245"); +})()`); + if (!(await waitFor(c, readout, { timeout: 3000, interval: 50 }))) { + throw new Error("the pointer readout does not show x:300 y:245"); + } + await c.send("Input.dispatchKeyEvent", { + type: "rawKeyDown", + key: "Control", + code: "ControlLeft", + windowsVirtualKeyCode: 17, + nativeVirtualKeyCode: 17, + modifiers: 2, + }); + const shown = () => c.evaluate(`${DESIGNER_GLOBALS}.designer.classList.contains("designerShowTabIndex")`); + if (!(await waitFor(c, shown, { timeout: 3000, interval: 50 }))) { + throw new Error("holding Ctrl showed no TabIndex circles"); + } + }, + { unsteady: tabIndexRings }, + ), + formStateShot("Controls_MultiSelect", async (c) => { + await selectNamed(c, ["Command1", "Text1", "Check1"]); + // the pointer rests on Check1, where it clicked last; the readout shows where it is once + // the pointer moves there after the click, as Designer_TabIndex's does + const at = await c.evaluate(`(() => { + const r = ${DESIGNER_GLOBALS}.allControls.find((x) => x.properties.Name === "Check1").getBoundingClientRect(); + return { x: r.x + r.width / 2, y: r.y + r.height / 2 }; +})()`); await mouseMove(c, at.x, at.y); const readout = () => c.evaluate(`(() => { const e = ${DESIGNER_GLOBALS}.designerDragInfoLeft; - return !!e && e.getBoundingClientRect().width > 0 && e.innerText.includes("x:300 y:245"); + return !!e && e.getBoundingClientRect().width > 0 && /x:\\d+ y:\\d+/.test(e.innerText); })()`); if (!(await waitFor(c, readout, { timeout: 3000, interval: 50 }))) { - throw new Error("the pointer readout does not show x:300 y:245"); - } - await c.send("Input.dispatchKeyEvent", { - type: "rawKeyDown", - key: "Control", - code: "ControlLeft", - windowsVirtualKeyCode: 17, - nativeVirtualKeyCode: 17, - modifiers: 2, - }); - const shown = () => c.evaluate(`${DESIGNER_GLOBALS}.designer.classList.contains("designerShowTabIndex")`); - if (!(await waitFor(c, shown, { timeout: 3000, interval: 50 }))) { - throw new Error("holding Ctrl showed no TabIndex circles"); + throw new Error("the pointer readout does not show where the pointer rests"); } }), - formStateShot("Controls_MultiSelect", (c) => selectNamed(c, ["Command1", "Text1", "Check1"])), formStateShot( "Controls_RubberBand", async (c) => { @@ -5614,9 +5699,39 @@ async function gridOptions(c) { await frames(c); } +// The soft shadow round each TabIndex circle (a control's ::after, box-shadow 1px 1px 4px) is +// dithered in one of two versions from capture to capture, some 600 pixels apart, over the dots +// of the grid (owner: unsteady). These are capture's `unsteady` regions for a ring round each +// circle, from 2 pixels inside its edge to 6 beyond it, so that its number is still compared. +async function tabIndexRings(c) { + const circles = await c.evaluate(`[...document.querySelectorAll(".designerShowTabIndex .baseControl")] + .map((e) => { + const r = e.getBoundingClientRect(); + const a = getComputedStyle(e, "::after"); + if (a.content === "none" || !r.width) return null; + const px = (v) => parseFloat(v) || 0; + const width = px(a.width) + px(a.paddingLeft) + px(a.paddingRight); + const height = px(a.height) + px(a.paddingTop) + px(a.paddingBottom); + return { x: r.right - px(a.right) - width, y: r.top + px(a.top), width, height }; + }) + .filter(Boolean)`); + if (!circles.length) throw new Error("no TabIndex circle to leave its shadow out"); + return circles.flatMap((b) => { + const o = grow(b, 6); + const i = grow(b, -2); + return [ + { x: o.x, y: o.y, width: o.width, height: i.y - o.y }, + { x: o.x, y: i.y + i.height, width: o.width, height: o.y + o.height - i.y - i.height }, + { x: o.x, y: i.y, width: i.x - o.x, height: i.height }, + { x: i.x + i.width, y: i.y, width: o.x + o.width - i.x - i.width, height: i.height }, + ].map((rect) => ({ on: { rect }, pad: 0 })); + }); +} + // frmMain's form, its menu bar and readouts, in the state `state(c)` brings it to; `after(c)` -// runs once the picture is taken, before the tab is closed. -function formStateShot(name, state, { after = null, out = FORMS_IMAGE(name) } = {}) { +// runs once the picture is taken, before the tab is closed. `unsteady(c)` gives more of +// capture's `unsteady` regions than the ground's. +function formStateShot(name, state, { after = null, out = FORMS_IMAGE(name), unsteady = null } = {}) { return { out, setup: "forms-chapter", @@ -5626,7 +5741,9 @@ function formStateShot(name, state, { after = null, out = FORMS_IMAGE(name) } = await state(c); const area = await formArea(c); const clip = snapOut({ x: area.x, y: area.y, width: area.width + 6, height: area.height + 8 }); - return await capture(c, name, clip, { unsteady: await groundUnsteady(c, clip) }); + return await capture(c, name, clip, { + unsteady: [...(await groundUnsteady(c, clip)), ...(unsteady ? await unsteady(c) : [])], + }); } finally { if (after) await after(c); await c.evaluate(`document.getElementById("tbShotBlink")?.remove()`); @@ -5819,7 +5936,18 @@ async function peDoubleClick(c, text) { async function peRename(c, name, to) { await peSelect(c, name); await pressKey(c, "F2"); - if (!(await nameBox(c))) throw new Error(`F2 on ${name} opened no name box`); + // the box selects the base name a moment after it takes the focus; typed before that, the + // keys land round the name (frmA.tbform once came back naifrmA.tbform) + const base = name.lastIndexOf(".") < 0 ? name.length : name.lastIndexOf("."); + const box = await waitFor( + c, + async () => { + const b = await nameBox(c); + return b?.value === name && b.start === 0 && b.end === base && b; + }, + { timeout: 3000, interval: 50 }, + ); + if (!box) throw new Error(`F2 on ${name} opened ${JSON.stringify(await nameBox(c))}`); await typeText(c, to); await pressKey(c, "Enter"); } @@ -5861,7 +5989,13 @@ function renameBoxShot(name, typed = null) { try { await peFolders(c, SOURCES_OPEN); await peSelect(c, "Legacy.bas"); - await pressKey(c, "F2"); + // Rename from the row's menu, not F2: the box checks its name on each key's release + // (invalidRename), and with F2, whose release lands in the box or not by how soon the + // box takes the focus, it came out red now and then + await peRightClick(c, "Legacy.bas"); + const rename = (await menuItems(c)).find((i) => i.text.startsWith("Rename")); + if (!rename) throw new Error("the menu of Legacy.bas has no Rename"); + await clickAt(c, rename.x + rename.width / 2, rename.y + rename.height / 2); // the box selects the base name a moment after it takes the focus const box = await waitFor( c, @@ -5871,7 +6005,7 @@ function renameBoxShot(name, typed = null) { }, { timeout: 3000, interval: 50 }, ); - if (!box) throw new Error(`F2 on Legacy.bas opened ${JSON.stringify(await nameBox(c))}`); + if (!box) throw new Error(`Rename on Legacy.bas opened ${JSON.stringify(await nameBox(c))}`); if (typed) { await typeText(c, typed); if (!(await waitFor(c, async () => (await nameBox(c))?.invalid, { timeout: 3000, interval: 50 }))) { @@ -6390,6 +6524,857 @@ const RECENT_GONE = [ "C:\\Projects\\Reports\\Reports.twinproj", ]; +// ---------------------------------------------------------------- the Building chapter + +// The pictures of docs/IDE/Building/ (setups building, building-new, building-ax, +// building-hklm, building-llvm and building-pkg). The fixtures are test/shots/building/: exe +// (Program, a Standard EXE whose Sub Main waits a minute), ax (ShotActiveX, an ActiveX DLL with +// one class of fixed GUIDs) and pkg (MyPackage, a PRIVATE package). Each project is staged in a +// folder of the tool's own on PACKAGE_ROOT, named for its setup, with the templates' build +// path, so that the DEBUG CONSOLE's lines name no user: the files a build writes go into that +// folder's Build. Every picture builds what it shows and leaves the IDE as it found it. + +const BUILDING = path.join(REPO_ROOT, "test", "shots", "building"); +const BD_IMAGE = (name) => `IDE/Building/Images/${name}.png`; +const BD_FILE = (rest) => `/Program/${rest}`; +const BD_BUILD_PATH = "${SourcePath}\\Build\\${ProjectName}_${Architecture}.${FileExtension}"; +// The folder a setup's project is staged in, emptied first. +const buildingFolder = (name) => { + const dir = path.join(PACKAGE_ROOT, name); + rmSync(dir, { recursive: true, force: true }); + return dir; +}; +// The setup's folder, recorded for its `end`, which removes it. +const runFolder = (run, name) => { + run.buildingDir = buildingFolder(name); + return run.buildingDir; +}; + +// A copy of the fixture `name` in the work folder, its Settings changed by `settings`. +function stageBuilding(run, name, settings = {}) { + const src = path.join(run.work, `${name}-src`); + rmSync(src, { recursive: true, force: true }); + cpSync(path.join(BUILDING, name), src, { recursive: true }); + const file = path.join(src, "Settings"); + const s = JSON.parse(readFileSync(file, "utf8")); + writeFileSync(file, `${JSON.stringify({ ...s, ...settings }, null, "\t")}\n`); + return src; +} + +// `llvm`: the LLVM cache server leased before the IDE starts, so that it is never one this +// IDE's compiler starts in its own job (tb-llvm-cache.mjs); the setup's `end` releases it. +const startBuilding = + (name, folder, { settings = {}, llvm = false } = {}) => + async (run) => { + if (llvm) run.lease = await holdLlvmCache(ide); + run.step = "open"; + const dir = runFolder(run, folder); + say(run.name, `opening ${path.relative(REPO_ROOT, path.join(BUILDING, name))} in ${dir}`); + return run.lane.open(stageBuilding(run, name, settings), { folder: dir, buildPath: BD_BUILD_PATH }); + }; + +// The keys a build of the ax fixture can write, in HKCU and HKLM, both views: its class's +// GUIDs, its ProgID and its type library, whose id is the project's. +const AX_SHOT_IDS = ["B001", "B002", "B003"].map((x) => `{B01D0000-0000-4000-8000-00000000${x}}`); +function axShotKeys(projectId) { + const rel = [ + ...AX_SHOT_IDS.flatMap((g) => [ + `CLSID\\${g}`, + `Interface\\${g}`, + `WOW6432Node\\CLSID\\${g}`, + `WOW6432Node\\Interface\\${g}`, + ]), + `TypeLib\\${projectId}`, + `WOW6432Node\\TypeLib\\${projectId}`, + "ShotActiveX.MyClass", + ]; + return ["HKCU\\Software\\Classes", "HKLM\\Software\\Classes"].flatMap((r) => rel.map((k) => `${r}\\${k}`)); +} + +// The ax project's keys, from the id the lane gave it, and a check that none exists yet. +async function prepareBuildingAx(run) { + const ctx = await prepareSample(run); + const id = await run.c.evaluate(`new Promise((done) => getProjectSettings((s) => done(s["project.id"])))`, { + awaitPromise: true, + }); + run.axKeys = axShotKeys(id); + const left = presentKeys(run.axKeys); + if (left.length) throw new Error(`the ax fixture's keys exist before any build: ${left.join(", ")}`); + return ctx; +} + +// At a setup's end, its IDE gone: a key of the ax fixture's still in the registry is reported, +// never removed (nothing here writes the registry), the LLVM lease is released, and the +// setup's folder on PACKAGE_ROOT is removed (PACKAGE_ROOT itself stays when it was there before +// the run). +async function endBuilding(run) { + run.lease?.release(); + if (run.buildingDir) rmSync(run.buildingDir, { recursive: true, force: true }); + if (run.axKeys) { + const left = presentKeys(run.axKeys); + if (left.length) throw new Error(`the ax fixture's keys are in the registry: ${left.join(", ")}`); + say(run.name, "none of the ax fixture's registry keys exists, in HKCU or HKLM"); + } +} + +// building-hklm: the ax fixture with Register DLLs to HKLM, packed into its folder before an +// IDE with no project starts, and opened from the Recent list by the picture of the warning +// the IDE shows as it opens it (the IDE is not elevated). Nothing registers: HKLM refuses. +const hklmProject = () => path.join(PACKAGE_ROOT, "BuildingHKLM", "project.twinproj"); +async function startBuildingHklm(run) { + const dir = runFolder(run, "BuildingHKLM"); + mkdirSync(dir, { recursive: true }); + stageProject({ + src: stageBuilding(run, "ax", { "project.dllRegisterLocalMachine": true }), + stage: path.join(run.work, "hklm-stage"), + project: hklmProject(), + settings: { "project.buildPath": BD_BUILD_PATH, "project.id": "{B01D0000-0000-4000-8000-00000000B0F0}" }, + }); + run.axKeys = axShotKeys("{B01D0000-0000-4000-8000-00000000B0F0}"); + const left = presentKeys(run.axKeys); + if (left.length) throw new Error(`the ax fixture's keys exist before any build: ${left.join(", ")}`); + return startNoProject(run); +} + +// building-pkg: the package server blocked in the page and by CDP for the whole setup +// (building-kit.mjs's guard, which also records any request), and the saved publisher name +// and password emptied, in the page only. +async function prepareBuildingPkg(run) { + const ctx = await prepareSample(run); + await guard(run.c); + await run.c.evaluate(`packagePublisherName = ""; packagePublisherPassword = ""; packagePublisherSessionID = ""`); + return ctx; +} + +// building-llvm: LLVM needs a licence that allows it, which the lane's IDE reads from the +// user's settings; a Community or Personal one refuses the build, and the setup with it. +async function prepareBuildingLlvm(run) { + const ctx = await prepareSample(run); + const { c } = run; + if ( + !(await waitFor(c, () => c.evaluate("licenceIsSet === true && !!compilerLicence.innerText"), { + timeout: 60000, + interval: 250, + })) + ) { + throw new Error("the compiler never answered the licence check"); + } + const edition = await c.evaluate("compilerLicence.innerText"); + if (/COMMUNITY|PERSONAL/i.test(edition)) throw new Error(`the licence (${edition}) refuses an LLVM build`); + return ctx; +} + +// Throws when the page has made a request to the package server, or started a publish. +async function noServerRequests(c) { + const seen = await serverRequests(c); + if (seen.length) throw new Error(`a request to the package server: ${seen.join(", ")}`); + if ((await consoleText(c)).includes("[PUBLISH] attempting")) throw new Error("a publish was started"); +} + +// building-new: the IDE with no project, then New Project's Standard EXE tile, Open, and +// Continue in New Project Options, as a person makes a project: it has no file. +async function prepareBuildingNew(run) { + const ctx = await prepareNoProject(run); + const { c } = run; + await command(c, "tbProject_New"); + if (!(await waitModal(c, "New / Open", { timeout: 10000 }))) throw new Error("New Project opened no dialog"); + await dialogStill(c); + const tile = await c.evaluate(`(() => { + const e = [...document.querySelectorAll(".frontPageListViewItem")].find((x) => x.getBoundingClientRect().width && x.innerText.trim().startsWith("Standard EXE")); + const r = e && e.getBoundingClientRect(); + return r ? { x: r.x + r.width / 2, y: r.y + r.height / 2 } : null; +})()`); + if (!tile) throw new Error("the New tab has no Standard EXE tile"); + await clickAt(c, tile.x, tile.y); + await clickInModal(c, "Open", ".msgBoxButton"); + if (!(await waitModal(c, "New Project Options", { timeout: 60000 }))) { + throw new Error("Open on Standard EXE did not show the New Project Options dialog"); + } + await dialogStill(c); + await closeModal(c, "Continue"); + if ( + !(await waitFor(c, async () => (await c.evaluate("licenceIsSet === true")) && !(await modals(c)).length, { + timeout: 60000, + interval: 250, + })) + ) { + throw new Error("the new project's compiler never answered the licence check"); + } + // the new project's form opens in the editor a while after its compiler answers + await dialogStill(c, { ms: 1500, timeout: 20000, root: "document.body", what: "IDE" }); + // and is closed: its designer's grid, behind the box, is drawn a little differently each + // time, which changed the picture's SVG + await closeTabs(c, [], { discard: true }); + await parkMouse(c); + return ctx; +} + +// The DEBUG CONSOLE floated on its own, wide enough for a build's longest line, and emptied. +const BD_CONSOLE = { width: 900, height: 96 }; +async function buildConsole(c) { + await floatPanel(c, "DEBUG CONSOLE", BD_CONSOLE); + await clearConsole(c); +} + +// The floated console grown a line at a time until `lines` lines show whole in it: it draws +// its lines in a box of its own (.listItems), which clips them, with a scroll bar of its own. +async function fitConsole(c, lines) { + const hidden = () => + c.evaluate(`(() => { + const p = document.querySelector(${JSON.stringify(panelSel("DEBUG CONSOLE"))}); + const box = p.querySelector(".listItems").getBoundingClientRect(); + const rows = [...p.querySelectorAll(".listItems .listitem")].map((e) => e.getBoundingClientRect()).filter((r) => r.height); + if (rows.length >= ${lines} && rows.every((r) => r.top >= box.top && r.bottom <= box.bottom)) return false; + p.style.height = (p.getBoundingClientRect().height + (rows[0]?.height ?? 20)) + "px"; + return true; +})()`); + for (let i = 0; i < 12 && (await hidden()); i++) await frames(c); + if (await hidden()) throw new Error(`the DEBUG CONSOLE does not show its ${lines} lines`); + // the console draws its lines again after a resize: what is clicked or set in the page is + // clicked or set after + await dialogStill(c, { + ms: 500, + root: `document.querySelector(${JSON.stringify(panelSel("DEBUG CONSOLE"))})`, + what: "console", + }); +} + +// The console's scroll bar thumb put at the top of its track, in the page. Its lines fit, so +// the thumb is the track's whole height, but the console leaves it where an earlier length of +// the list put it (a few pixels up or down, differing from run to run). +async function fixConsoleThumb(c) { + const ok = await c.evaluate(`(() => { + const p = document.querySelector(${JSON.stringify(panelSel("DEBUG CONSOLE"))}); + const thumb = p.querySelector(".scrollBackV > div:nth-child(2) > div"); + if (!thumb || thumb.style.height !== "100%") return false; + thumb.style.top = "0px"; + return true; +})()`); + if (!ok) throw new Error("the DEBUG CONSOLE's scroll bar thumb is not the whole track"); +} + +// The floated console grown to show its `lines` lines, its times and scroll bar set, captured; +// `fix` sets what else changes from run to run, in the page. +async function consolePicture(c, name, lines, fix = null) { + await fitConsole(c, lines); + if (fix) await fix(); + await fixConsoleTimes(c); + await fixConsoleThumb(c); + await parkMouse(c); + await frames(c); + // the IDE behind the panel hidden, on a ground of the panel's colour: the SVG would + // otherwise hold it, and its editor is laid out a pixel taller or shorter from run to run. + // Not a cut-out (`keep`), which shows every element inside the panel, and the console + // keeps hidden copies of its rows there + const sel = panelSel("DEBUG CONSOLE"); + const ground = await groundOf(c, `${sel} .sectionBody`); + if (!ground) throw new Error("the DEBUG CONSOLE has no background colour"); + await c.evaluate(`(() => { + for (let e = document.querySelector(${JSON.stringify(sel)}); e.parentElement; e = e.parentElement) + for (const s of e.parentElement.children) if (s !== e) s.setAttribute("data-tb-behind", ""); + const s = document.createElement("style"); + s.id = "tbBehind"; + s.textContent = ${JSON.stringify(`[data-tb-behind],[data-tb-behind] *{visibility:hidden !important}html,body,#bodyInner{background:${ground} !important;background-image:none !important}.floatingPanel{box-shadow:none !important}`)}; + document.head.appendChild(s); +})()`); + try { + await frames(c); + return await capture(c, name, snapOut(await rectOf(c, sel)), { away: () => parkMouse(c) }); + } finally { + await c.evaluate(`(() => { + document.getElementById("tbBehind")?.remove(); + for (const e of document.querySelectorAll("[data-tb-behind]")) e.removeAttribute("data-tb-behind"); +})()`); + await frames(c); + } +} + +// The console's link `text`, clicked with the mouse: the one drawn where the mouse reaches it +// (the console's list keeps copies of its rows that are not shown). +async function consoleLink(c, text) { + const p = await c.evaluate(`(() => { + const links = [...document.querySelectorAll(".debugConsoleOuter a")].filter((x) => x.textContent.replace(/\\s+/g, " ").trim() === ${JSON.stringify(text)}); + for (const e of links.reverse()) { + const r = e.getBoundingClientRect(); + if (!r.width) continue; + const x = r.x + r.width / 2, y = r.y + r.height / 2; + const at = document.elementFromPoint(x, y); + if (at && e.contains(at)) return { x, y }; + } + return null; +})()`); + if (!p) throw new Error(`the DEBUG CONSOLE shows no ${text} link`); + await clickAt(c, p.x, p.y); +} + +// The console's lines since `mark` once one matches `re`. +async function consoleLine(c, mark, re, timeout = 15000) { + const lines = await waitFor( + c, + async () => { + const l = await linesSince(c, mark); + return l.some((x) => re.test(x)) && l; + }, + { timeout, interval: 150 }, + ); + if (!lines) { + throw new Error( + `the DEBUG CONSOLE printed no line matching ${re}, only: ${(await linesSince(c, mark)).join(" / ")}`, + ); + } + return lines.map((l) => l.trim()).find((x) => re.test(x)); +} + +// The pid in LOCKED BY's line, set in the page to the one the page's text names. +const LOCKED_PID = 4120; +const fixLockedPid = (c) => + c.evaluate(`(() => { + const walk = document.createTreeWalker(document.querySelector(".debugConsoleOuter"), NodeFilter.SHOW_TEXT); + for (let n = walk.nextNode(); n; n = walk.nextNode()) n.nodeValue = n.nodeValue.replace(/\\(pid \\d+\\)/, "(pid ${LOCKED_PID})"); +})()`); + +const processAlive = (pid) => { + try { + process.kill(pid, 0); + return true; + } catch { + return false; + } +}; + +// The build configuration box's value, and the IDE settled after a switch: the compiler +// has the project and nothing covers the IDE. +const configValue = (c) => c.evaluate("buildConfigSelector.value"); +async function configSettled(c, value) { + const ok = await waitFor( + c, + async () => + (await configValue(c)) === value && + (value === "nocompile" || (await c.evaluate("licenceIsSet === true && !(lockUICount > 0)"))) && + !(await modals(c)).some((m) => /Please wait/i.test(m.title)), + { timeout: 90000, interval: 250 }, + ); + if (!ok) throw new Error(`the build configuration did not settle at ${value}: ${await configValue(c)}`); +} + +// The box opened with a real click, and the next entry chosen with the keys, as a person does. +async function configDown(c) { + const b = await rectOf(c, "#buildConfigSelector"); + await clickAt(c, b.x + b.width / 2, b.y + b.height / 2); + await sleep(300); + await pressKey(c, "ArrowDown"); + await pressKey(c, "Enter"); +} + +// The modal whose text holds `text`: its box (the top one of them). +const modalHolding = (c, text) => + c.evaluate(`(() => { + const m = [...document.querySelectorAll(".modalDialogContainer")].filter((x) => x.getBoundingClientRect().width && x.innerText.includes(${JSON.stringify(text)})).pop(); + const r = m && m.getBoundingClientRect(); + return r ? { x: r.x, y: r.y, width: r.width, height: r.height } : null; +})()`); + +// A capture of the modal holding `text`, the focus out of it. +async function modalPicture(c, name, text) { + await c.evaluate("document.activeElement?.blur?.()"); + await parkMouse(c); + await frames(c); + const box = await modalHolding(c, text); + if (!box) throw new Error(`no dialog holds "${text}"`); + return capture(c, name, snapOut(box), { away: () => parkMouse(c) }); +} + +// The PACKAGE PUBLISHING pane floated, as View > Package Publishing shows it. +const publishingPane = (c) => floatPanel(c, "PACKAGE PUBLISHING", { width: 300, height: 330, left: 20, top: 520 }); + +// A real click on the smallest element of the top dialog whose text starts with `text`. +async function clickInModalStarting(c, text) { + const p = await c.evaluate(`(() => { + const m = [...document.querySelectorAll(".modalDialogContainer")].filter((x) => x.getBoundingClientRect().width).pop(); + const area = (e) => e.getBoundingClientRect().width * e.getBoundingClientRect().height; + const e = m && [...m.querySelectorAll("*")].filter((x) => area(x) && x.textContent.trim().startsWith(${JSON.stringify(text)})).sort((a, b) => area(a) - area(b))[0]; + const r = e && e.getBoundingClientRect(); + return r ? { x: r.x + r.width / 2, y: r.y + r.height / 2 } : null; +})()`); + if (!p) throw new Error(`nothing in the top dialog starts "${text}"`); + await clickAt(c, p.x, p.y); +} + +// A real click on the element of the PACKAGE PUBLISHING pane whose text is `text`. +async function paneLink(c, text) { + const p = await c.evaluate(`(() => { + const e = [...document.querySelectorAll(${JSON.stringify(`${panelSel("PACKAGE PUBLISHING")} *`)})].find((x) => x.children.length === 0 && x.textContent.trim() === ${JSON.stringify(text)} && x.getBoundingClientRect().width); + const r = e && e.getBoundingClientRect(); + return r ? { x: r.x + r.width / 2, y: r.y + r.height / 2 } : null; +})()`); + if (!p) throw new Error(`the PACKAGE PUBLISHING pane has no ${text}`); + await clickAt(c, p.x, p.y); +} + +// The sign-in box opened from the pane's SIGN IN, once it shows. +async function signInBox(c) { + await publishingPane(c); + await paneLink(c, "SIGN IN"); + if (!(await waitModal(c, "Publisher Login", { timeout: 10000 }))) throw new Error("SIGN IN opened no box"); + await dialogStill(c); +} + +// The text box `id` of the sign-in box emptied and `text` typed into it, with real keys. +async function signInType(c, id, text) { + const b = await rectOf(c, `#${id}`); + if (!b) throw new Error(`the sign-in box shows no #${id}`); + await clickAt(c, b.x + 10, b.y + b.height / 2); + await c.evaluate(`document.getElementById(${JSON.stringify(id)}).select()`); + await pressKey(c, "Backspace"); + if (text) await typeText(c, text); +} + +// The tab LOGIN or REGISTER of the sign-in box, chosen with a click unless it shows. +async function signInTab(c, tab) { + const login = () => c.evaluate(`!!document.querySelector(".isLogin")`); + if ((await login()) === (tab === "LOGIN")) return; + await clickInModal(c, tab); + if (!(await waitFor(c, async () => (await login()) === (tab === "LOGIN"), { timeout: 3000, interval: 100 }))) { + throw new Error(`the sign-in box did not switch to ${tab}`); + } +} + +// The success text of a publish, as the IDE shows it (ide/main.js). +const PUBLISH_SUCCESS = "[PUBLISH] successful. Your package should appear in the package manager database shortly."; +// The made-up publisher of the pictures. +const SHOT_PUBLISHER = "ExamplePublisher"; + +// The hook that holds an LLVM build's last progress event (-1, which closes the Compiling... +// box) until the picture is taken; the events before it pass. +const HOLD_BUILD_END = `(() => { + const proto = Object.getPrototypeOf(debugSocket); + if (!window.__realBuildProgress) { + window.__realBuildProgress = proto.event_setBuildProgress; + proto.event_setBuildProgress = function (e) { + if (window.__holdBuildEnd && e.body.percent10 === -10) { window.__heldBuild = [this, e]; return; } + return window.__realBuildProgress.call(this, e); + }; + } + window.__holdBuildEnd = true; + window.__heldBuild = null; +})()`; +const RELEASE_BUILD_END = `(() => { + window.__holdBuildEnd = false; + const h = window.__heldBuild; + window.__heldBuild = null; + if (h) window.__realBuildProgress.call(h[0], h[1]); + return !!h; +})()`; + +const buildingShots = [ + { + // a project made by New Project, never saved: the box Build opens; Cancel + out: BD_IMAGE("Save_First"), + setup: "building-new", + async take({ c }) { + await resetUi(c); + const b = await rectOf(c, "#buildIcon"); + await clickAt(c, b.x + b.width / 2, b.y + b.height / 2); + if (!(await waitFor(c, () => modalHolding(c, "You must first save"), { timeout: 10000, interval: 150 }))) { + throw new Error("Build on a project with no file asked nothing"); + } + await dialogStill(c); + try { + return await modalPicture(c, "Save_First", "You must first save"); + } finally { + await closeModal(c, "Cancel"); + } + }, + }, + { + // a build of the exe: the console's three lines, the links on the last + out: BD_IMAGE("Console_Exe"), + setup: "building", + async take({ c }) { + await resetUi(c); + try { + await buildConsole(c); + const r = await press(c, "build"); + if (!r.lines.some((l) => l.startsWith("[LINKER] SUCCESS"))) throw new Error(`the build failed: ${r.lines}`); + return await consolePicture(c, "Console_Exe", 3); + } finally { + await clearConsole(c); + await unfloatPanel(c, "DEBUG CONSOLE"); + } + }, + }, + { + // NoSuchProcedure 1 typed into Sub Main, its error listed, then Build: the failure lines; + // the edit undone after + out: BD_IMAGE("Console_Failed"), + setup: "building", + async take({ c }) { + await resetUi(c); + await openFile(c, BD_FILE("Sources/MainMod.twin")); + try { + return await editedThenUndone(c, async () => { + const at = await caretOn(c, "Public Sub Main()"); + await setCursor(c, at.line, 9999); + await pressKey(c, "Enter"); + await typeText(c, "NoSuchProcedure 1"); + await pressKey(c, "Escape"); + if (!(await waitFor(c, async () => (await diagCounts(c))[0] > 0, { timeout: 30000, interval: 250 }))) { + throw new Error("the call to NoSuchProcedure was not listed as an error"); + } + await buildConsole(c); + const r = await press(c, "build"); + if (r.lines.at(-1) !== "[BUILD] failed") throw new Error(`the build did not fail: ${r.lines}`); + return await consolePicture(c, "Console_Failed", 4); + }); + } finally { + await clearConsole(c); + await unfloatPanel(c, "DEBUG CONSOLE"); + await closeTabs(c, [], { discard: true }); + await waitCounts(c, [0, 0, 0, 0]); + } + }, + }, + { + // the exe built and started with Launch EXE, then Build again: LOCKED BY and the red + // Terminate link, the pid the page's; Terminate after, and the exe ended by its pid if + // it still runs + out: BD_IMAGE("Console_Locked"), + setup: "building", + async take({ c }) { + await resetUi(c); + let pid = null; + try { + await buildConsole(c); + const r = await press(c, "build"); + if (!r.lines.some((l) => l.startsWith("[LINKER] SUCCESS"))) throw new Error(`the build failed: ${r.lines}`); + await fitConsole(c, 3); + const mark = await consoleMark(c); + await consoleLink(c, "Launch EXE"); + pid = Number((await consoleLine(c, mark, /\[SHELL\] process \d+ started/)).match(/process (\d+)/)[1]); + await clearConsole(c); + const locked = await press(c, "build"); + if (!locked.lines.includes("LOCKED BY:")) throw new Error(`the second build was not refused: ${locked.lines}`); + return await consolePicture(c, "Console_Locked", 5, () => fixLockedPid(c)); + } finally { + if (pid) { + const mark = await consoleMark(c); + await consoleLink(c, "Terminate").catch((e) => complain(c.shot.name, e.message)); + await waitFor(c, async () => !processAlive(pid), { timeout: 10000, interval: 200 }); + // the compiler's line for the exe's end, before the console is emptied + await consoleLine(c, mark, /exited with code/, 10000).catch((e) => complain(c.shot.name, e.message)); + if (processAlive(pid)) { + const printed = (await linesSince(c, mark)).join(" / "); + complain( + c.shot.name, + `Terminate left the exe running (the console printed: ${printed}): ending pid ${pid}`, + ); + killTree(pid); + } + } + await clearConsole(c); + await unfloatPanel(c, "DEBUG CONSOLE"); + } + }, + }, + { + // the build configuration box with its list open (the list a replica: the OS draws the + // real one), win32 chosen + out: BD_IMAGE("Configuration_List"), + setup: "building", + async take({ c }) { + await resetUi(c); + if ((await configValue(c)) !== "win32") throw new Error(`the box shows ${await configValue(c)}`); + // the toolbar's group of the box: from the splitter before it to the one after Build + // (the box, Restart, Clean and Build) + const group = await c.evaluate(`(() => { + const kids = [...buildConfigSelector.parentElement.children]; + const i = kids.indexOf(buildConfigSelector); + const before = kids.slice(0, i).reverse().find((e) => e.classList.contains("toolbarSplitter")); + const after = kids.slice(i).find((e) => e.classList.contains("toolbarSplitter")); + if (!before || !after) return null; + const a = before.getBoundingClientRect(), b = after.getBoundingClientRect(); + return { x: a.x, right: b.x + b.width }; +})()`); + if (!group) throw new Error("the build configuration box has no splitter on each side"); + const bar = await toolbarRect(c); + const area = { x: group.x, y: bar.y, width: group.right - group.x, height: bar.height }; + return listClip(c, "Configuration_List", area, [{ type: "list", select: { css: "#buildConfigSelector" } }]); + }, + }, + { + // the box set to safeMode with the keys (Down twice from win32): the box the IDE shows + // once the project is open in safe mode; OK, and Ctrl+F2 back to win32 + out: BD_IMAGE("Safe_Mode"), + setup: "building", + async take({ c }) { + await resetUi(c); + try { + await configDown(c); + await configSettled(c, "win64"); + await configDown(c); + if (!(await waitFor(c, () => modalHolding(c, "SafeMode is designed"), { timeout: 90000, interval: 250 }))) { + throw new Error("safeMode showed no box"); + } + await dialogStill(c, { ms: 500 }); + return await modalPicture(c, "Safe_Mode", "SafeMode is designed"); + } finally { + if (await modalHolding(c, "SafeMode is designed")) await closeModal(c, "OK"); + await pressKey(c, "F2", { ctrl: true }); + await configSettled(c, "win32"); + await resetUi(c); + } + }, + }, + { + // the ax fixture built (registered in HKCU), the console emptied, then Clean: its lines; + // a build that Clean did not follow is cleaned after + out: BD_IMAGE("Console_Clean"), + setup: "building-ax", + async take({ c }) { + await resetUi(c); + let built = false; + try { + await buildConsole(c); + const b = await press(c, "build"); + built = true; + if (!b.lines.some((l) => /^\[REGISTER\] .* returned OK$/.test(l))) + throw new Error(`the build failed: ${b.lines}`); + await clearConsole(c); + const r = await press(c, "clean"); + built = false; + if ( + r.lines.at(-1) !== "[BUILD-CLEAN] build cleanup completed." || + !r.lines.some((l) => l.startsWith("[UNREGISTER]")) + ) { + throw new Error(`Clean did not deregister and delete: ${r.lines}`); + } + return await consolePicture(c, "Console_Clean", 3); + } finally { + if (built) await press(c, "clean"); + await clearConsole(c); + await unfloatPanel(c, "DEBUG CONSOLE"); + } + }, + }, + { + // the HKLM project opened from the Recent list: the first of the two warnings it shows; + // Continue Anyway to each, and the project open + out: BD_IMAGE("HKLM_Warning"), + setup: "building-hklm", + async take({ c }) { + await resetUi(c); + const project = hklmProject(); + await setRecents(c, [{ name: project, projectPath: project }]); + let shown = false; + try { + await command(c, "tbProject_OpenRecent"); + if (!(await waitModal(c, "New / Open", { timeout: 10000 }))) throw new Error("Open Recent opened no dialog"); + await dialogStill(c); + const row = await c.evaluate(`(() => { + const e = [...document.querySelectorAll(".frontPageListViewItem")].find((x) => x.getBoundingClientRect().width && x.textContent.trim() === ${JSON.stringify(project)}); + const r = e && e.getBoundingClientRect(); + return r ? { x: r.x + r.width / 3, y: r.y + r.height / 2 } : null; +})()`); + if (!row) throw new Error("the Recent tab does not list the project"); + await mouseMove(c, row.x, row.y); + for (const clickCount of [1, 2]) { + for (const type of ["mousePressed", "mouseReleased"]) { + await c.send("Input.dispatchMouseEvent", { + type, + x: row.x, + y: row.y, + button: "left", + buttons: type === "mousePressed" ? 1 : 0, + clickCount, + }); + } + } + if (!(await waitFor(c, () => modalHolding(c, "HKEY_LOCAL_MACHINE"), { timeout: 60000, interval: 150 }))) { + throw new Error("the project opened with no HKLM warning"); + } + shown = true; + await dialogStill(c, { ms: 500 }); + return await modalPicture(c, "HKLM_Warning", "HKEY_LOCAL_MACHINE"); + } finally { + if (shown) { + // each warning answered as it shows; the load waits for them + let quiet = 0; + for (let i = 0; i < 200 && quiet < 12; i++) { + if (await modalHolding(c, "HKEY_LOCAL_MACHINE")) { + await answerMessageBox(c, "Continue Anyway"); + quiet = 0; + } else if ((await c.evaluate("licenceIsSet === true")) && !(await modals(c)).length) quiet++; + await sleep(250); + } + } + await setRecents(c, []); + await resetUi(c); + } + }, + }, + { + // the HKLM project built twice, the second build's deregistration failed: the box; + // Cancel, then Clean (its box cancelled too) and the DLL deleted from the setup's folder + out: BD_IMAGE("Delete_It_And_Continue"), + setup: "building-hklm", + async take({ c }) { + await resetUi(c); + const dll = path.join(path.dirname(hklmProject()), "Build", "ShotActiveX_win32.dll"); + rmSync(dll, { force: true }); + try { + const first = await press(c, "build"); + if (first.lines.at(-1) !== "[BUILD] failed" || !first.lines.some((l) => l.startsWith("[REGISTER]"))) { + throw new Error(`the first build did not fail to register: ${first.lines}`); + } + const second = await press(c, "build"); + if (!second.boxes.some((b) => b.includes("unable to unregister"))) { + throw new Error(`the second build asked nothing: ${second.lines} ${second.boxes}`); + } + await dialogStill(c, { ms: 500 }); + return await modalPicture(c, "Delete_It_And_Continue", "unable to unregister"); + } finally { + if (await modalHolding(c, "unable to unregister")) await closeModal(c, "Cancel"); + const r = await press(c, "clean"); + if (r.boxes.length) await closeModal(c, "Cancel"); + rmSync(dll, { force: true }); + await resetUi(c); + } + }, + }, + { + // an LLVM build with its last progress event held: the Compiling... box + out: BD_IMAGE("Compiling"), + setup: "building-llvm", + async take({ c }) { + await resetUi(c); + await c.evaluate(HOLD_BUILD_END); + try { + await press(c, "build"); + if (!(await waitFor(c, () => c.evaluate("!!window.__heldBuild"), { timeout: 60000, interval: 100 }))) { + throw new Error("the LLVM build never ended"); + } + if (!(await modalHolding(c, "Compiling"))) throw new Error("the LLVM build showed no Compiling... box"); + await dialogStill(c, { ms: 500 }); + return await modalPicture(c, "Compiling", "Compiling"); + } finally { + await c.evaluate(RELEASE_BUILD_END); + if ( + !(await waitFor(c, async () => !(await modals(c)).length && (await c.evaluate("lockUICount")) === 0, { + timeout: 10000, + interval: 100, + })) + ) { + // what is left closed from the page, as the lane does, so that the IDE can go on + complain(c.shot.name, "the Compiling... box stayed after the build's end was let through"); + failed = 1; + for (let i = 0; i < 3 && (await c.evaluate("modalDialogs.length")) > 0; i++) { + await c.evaluate("hideModalDialog()"); + } + } + } + }, + }, + { + // the sign-in box on LOGIN, a made-up name typed, Remember password ticked; Cancel + out: BD_IMAGE("SignIn_Login"), + setup: "building-pkg", + async take({ c }) { + await resetUi(c); + try { + await signInBox(c); + await signInTab(c, "LOGIN"); + await signInType(c, "PublisherUserIdLogin", SHOT_PUBLISHER); + await signInType(c, "PublisherPasswordLogin", ""); + const remember = await c.evaluate(`(() => { + const g = document.getElementById("PublisherLoginGroup"); + const i = g && [...g.querySelectorAll("input[type=checkbox]")].find((x) => x.getBoundingClientRect().width); + const r = i && i.getBoundingClientRect(); + return r ? { checked: i.checked, x: r.x + r.width / 2, y: r.y + r.height / 2 } : null; +})()`); + if (!remember) throw new Error("the LOGIN form has no Remember password box"); + if (!remember.checked) await clickAt(c, remember.x, remember.y); + await dialogStill(c); + return await modalPicture(c, "SignIn_Login", "Remember password"); + } finally { + if (await modalHolding(c, "Remember password")) await closeModal(c, "Cancel"); + await unfloatPanel(c, "PACKAGE PUBLISHING"); + await noServerRequests(c); + } + }, + }, + { + // the sign-in box on REGISTER, SIGN UP pressed with a username of three letters: the + // error under the form; Cancel + out: BD_IMAGE("SignIn_Register"), + setup: "building-pkg", + async take({ c }) { + await resetUi(c); + try { + await signInBox(c); + await signInTab(c, "REGISTER"); + await signInType(c, "PublisherUserId", "abc"); + await clickInModalStarting(c, "SIGN UP"); + const error = "ERROR: Username must be at least 4 characters long"; + if (!(await waitFor(c, () => modalHolding(c, error), { timeout: 5000, interval: 100 }))) { + throw new Error("SIGN UP showed no error for a username of three letters"); + } + await dialogStill(c); + return await modalPicture(c, "SignIn_Register", error); + } finally { + if (await modalHolding(c, "Remember password")) await closeModal(c, "Cancel"); + await unfloatPanel(c, "PACKAGE PUBLISHING"); + await noServerRequests(c); + } + }, + }, + { + // a login made up in the page (a session id and a publisher's name), then PUBLISH THIS + // PACKAGE: the confirmation; Cancel, and the login undone + out: BD_IMAGE("Publish_Confirm"), + setup: "building-pkg", + async take({ c }) { + await resetUi(c); + await c.evaluate( + `packagePublisherName = ${JSON.stringify(SHOT_PUBLISHER)}; packagePublisherSessionID = "not-a-real-session"`, + ); + try { + await publishingPane(c); + await paneLink(c, "PUBLISH THIS PACKAGE"); + if (!(await waitFor(c, () => modalHolding(c, "Do you want to proceed?"), { timeout: 30000, interval: 200 }))) { + throw new Error("PUBLISH THIS PACKAGE asked nothing"); + } + await dialogStill(c); + return await modalPicture(c, "Publish_Confirm", "Do you want to proceed?"); + } finally { + if (await modalHolding(c, "Do you want to proceed?")) await closeModal(c, "Cancel"); + await c.evaluate(`packagePublisherName = ""; packagePublisherSessionID = ""`); + await unfloatPanel(c, "PACKAGE PUBLISHING"); + await noServerRequests(c); + } + }, + }, + { + // the box a publish's result is shown in, with the success text, shown by the IDE's own + // showModalNotification (nothing is uploaded); OK + out: BD_IMAGE("Publish_Result"), + setup: "building-pkg", + async take({ c }) { + await resetUi(c); + await c.evaluate(`showModalNotification(${JSON.stringify(PUBLISH_SUCCESS)})`); + try { + if (!(await waitFor(c, () => modalHolding(c, "[PUBLISH] successful"), { timeout: 5000, interval: 100 }))) { + throw new Error("showModalNotification showed no box"); + } + await dialogStill(c); + return await modalPicture(c, "Publish_Result", "[PUBLISH] successful"); + } finally { + if (await modalHolding(c, "[PUBLISH] successful")) await closeModal(c, "OK"); + await noServerRequests(c); + } + }, + }, +]; + // The editor and the Project Explorer alone, side by side, for the preview tab. const PREVIEW_LAYOUT = { type: "horizontal", @@ -9416,7 +10401,7 @@ const aboutShot = { ); if (!ready) throw new Error("the compiler never answered the licence check, so About would say NOT READY"); return inDialog(c, { command: "tbHelp_ShowAboutWindow", title: "About", close: "Close" }, () => - dialogShot(c, "Menu_Help_About"), + dialogShot(c, "Menu_Help_About", undefined, null, { unsteady: VIP_GOLD_SPARES }), ); }, }; @@ -9558,6 +10543,9 @@ const communityShot = { await resetUi(c); const text = await c.evaluate("compilerLicence.innerText"); if (text !== "COMMUNITY EDITION") throw new Error(`the licence badge says ${JSON.stringify(text)}`); + // the restart Services_Limited makes can write its line, which names the user's folder, + // after that shot has cleared the console + await clearUserFromConsole(c); return capture(c, "Licence_CommunityEdition", snapOut(await rectOf(c, "#compilerLicenceOuter")), { away: () => parkMouse(c), }); @@ -9688,7 +10676,17 @@ const splashShot = { if (!(await waitModal(c, "Loading"))) throw new Error("the splash did not open"); await dialogStill(c); await dialogBackgrounds(c); - return await dialogShot(c, "Splash_Screen"); + // its rounded corners come out a few pixels apart from capture to capture in the dark + // theme (owner: unsteady) + const box = (await modals(c)).pop(); + const corner = (i, j) => ({ + x: box.x + i * (box.width - 4), + y: box.y + j * (box.height - 4), + width: 4, + height: 4, + }); + const corners = [0, 1].flatMap((i) => [0, 1].map((j) => ({ on: { rect: corner(i, j) } }))); + return await dialogShot(c, "Splash_Screen", undefined, null, { unsteady: [...VIP_GOLD_SPARES, ...corners] }); } finally { await c.evaluate(`(() => { const close = window.tbSplashClose; delete window.tbSplashClose; close?.(); })()`); if (await waitModal(c, "New / Open", { timeout: 10000 })) await closeModal(c, "Cancel"); @@ -9792,16 +10790,29 @@ function crop({ width, rgba }, [left, top, right, bottom]) { return { width: w, height: h, rgba: out }; } +// Makes a program's window the active one of its desktop (activateWindow): a program started on +// a desktop not on screen now and then draws its caption inactive (owner: made active). +async function activated(desktop, hwnd, name) { + if (!(await activateWindow(desktop, hwnd)).active) throw new Error(`the window of ${name} would not become active`); +} + // One capture of a window, as `captureWindow` writes it to `file`, once two in a row are equal // (a window being drawn can differ from one to the next); refused when a text of the window -// holds the user name. -async function stableWindow(desktop, hwnd, name, file, flags = 2) { +// holds the user name. With `active`, the window is made active first, and again whenever a +// capture finds its caption drawn inactive. +async function stableWindow(desktop, hwnd, name, file, flags = 2, { active = false } = {}) { let last = null; + if (active) await activated(desktop, hwnd, name); for (let i = 0; i < 8; i++) { const info = await captureWindow(desktop, hwnd, file, { flags }); const named = info.texts.find((t) => t.toLowerCase().includes(USER.toLowerCase())); if (named !== undefined) throw new Error(`the window of ${name} shows the Windows user name in ${JSON.stringify(named)}`); + if (active && !info.active) { + await activated(desktop, hwnd, name); + last = null; + continue; + } const png = readFileSync(file); if (last?.equals(png)) return { info, picture: decodePng(png) }; last = png; @@ -9814,12 +10825,15 @@ async function stableWindow(desktop, hwnd, name, file, flags = 2) { // TransparencyKey) is given the alpha the system blends it with what is under it: its alpha // everywhere, and none where its client area has the key colour. PW_RENDERFULLCONTENT draws // those pixels black, so they are read from a capture of the client area alone (flags 1), -// which draws them in the key colour. The page is then what is under the window. -async function windowPicture(desktop, hwnd, name, file) { - const { info, picture } = await stableWindow(desktop, hwnd, name, file); +// which draws them in the key colour. The page is then what is under the window. `active`: +// as stableWindow's. +async function windowPicture(desktop, hwnd, name, file, { active = false } = {}) { + const { info, picture } = await stableWindow(desktop, hwnd, name, file, 2, { active }); if (info.layered) { const [key, alpha, lwa] = info.layered; - const { picture: client } = await stableWindow(desktop, hwnd, name, file.replace(/\.png$/, "-client.png"), 1); + const { picture: client } = await stableWindow(desktop, hwnd, name, file.replace(/\.png$/, "-client.png"), 1, { + active, + }); const [cl, ct, cr, cb] = info.client; const k = [key & 255, (key >> 8) & 255, (key >> 16) & 255]; for (let y = 0; y < picture.height; y++) { @@ -9919,18 +10933,18 @@ async function withProgram(ctx, scene, fn) { } // A form of the program, `scene` its command line; with `grow`, the form and then the form -// made larger, side by side. +// made larger, side by side. The form is the active window, its caption drawn so. const programShot = (out, scene, { grow = false } = {}) => ({ out, setup: "programs", once: true, take: (ctx) => withProgram(ctx, scene, async (dir, w) => { - const shown = [await windowPicture(ctx.desktop, w.hwnd, scene, path.join(dir, "before.png"))]; + const shown = [await windowPicture(ctx.desktop, w.hwnd, scene, path.join(dir, "before.png"), { active: true })]; if (grow) { writeFileSync(path.join(dir, "grow"), ""); await signalled(dir, "grown"); - shown.push(await windowPicture(ctx.desktop, w.hwnd, scene, path.join(dir, "after.png"))); + shown.push(await windowPicture(ctx.desktop, w.hwnd, scene, path.join(dir, "after.png"), { active: true })); } return besideEachOther(shown); }), @@ -10734,14 +11748,15 @@ const packageServerShots = [ was = { text: await editorText(c), counts: await diagCounts(c) }; await setCursor(c, 4, 1); await typeText(c, " fmt"); - // The list shows each member's type as "..." until the compiler has given it, which it - // now and then never does for a list: the dot is typed again then. + // The list shows each member's type as "...", or a variable's or a function's kind with + // no type after it, until the compiler has given it, which it now and then never does + // for a list: the dot is typed again then. const listed = (resolved) => c.evaluate(`(() => { const b = [...document.querySelectorAll(${JSON.stringify(COMPLETIONS)})].find((b) => b.getBoundingClientRect().width); const rows = b ? [...b.querySelectorAll(".listitem")] : []; if (!rows.some((r) => r.innerText.includes("AsciiEscapeBase"))) return false; - return !${resolved} || rows.every((r) => [...(r.querySelector(".isenseType")?.childNodes ?? [])].every((n) => n.nodeType !== 3 || n.nodeValue !== "...")); + return !${resolved} || rows.every((r) => [...(r.querySelector(".isenseType")?.childNodes ?? [])].every((n) => n.nodeType !== 3 || n.nodeValue !== "...") && !/(variable|returns)\\s*$/.test(r.innerText)); })()`); // A list opened by the name typed before the dot is placed where that name starts, and // the dot's list then opens where that one was: closed first, the dot's list opens at @@ -10772,6 +11787,18 @@ const packageServerShots = [ } if (!shown) throw new Error("the completion list never showed its members' types"); await sleep(500); + // The IDE places the list at its text cursor's box as drawn when the list is asked for, + // and that is at the dot or, now and then, already after it, 7 pixels to the right + // (triggerIntellisense): the list is put where the cursor stood at the dot (owner). + await c.evaluate(`(() => { + const b = [...document.querySelectorAll(${JSON.stringify(COMPLETIONS)})].find((b) => b.getBoundingClientRect().width); + const cursor = document.body.getElementsByClassName("cursor monaco-mouse-cursor-text")[0].getBoundingClientRect(); + const left = (column) => editor.getScrolledVisiblePosition({ lineNumber: 4, column }).left; + const p = editor.getPosition(); + const x = cursor.left - (left(p.column) - left(editor.getModel().getLineContent(4).indexOf(".") + 1)); + b.style.left = x + "px"; +})()`); + await frames(c); const area = await c.evaluate(`(() => { const ed = editor.getDomNode().getBoundingClientRect(); const left = ed.x + editor.getLayoutInfo().contentLeft; @@ -11353,6 +12380,8 @@ const webView2Shot = { // wide enough for the start of the file's SHA-256. The list, without the release's box around it. const ASSETS = `[...document.querySelectorAll("summary")].find((s) => /^Assets/.test(s.textContent.trim()))`; const RELEASE_WIDTH = 1280; +// the widest the zip's time is drawn ("23 minutes ago"), in CSS pixels +const RELEASE_TIME_WIDTH = 104; const releaseShot = { out: "Miscellaneous/Images/ac019c1a-dcef-4964-a730-bc5b86c644ba.png", setup: "web", @@ -11369,7 +12398,20 @@ const releaseShot = { const list = await c.evaluate( `(() => { const r = ${ASSETS}.parentElement.getBoundingClientRect(); return { x: r.x, y: r.y, width: r.width, height: r.height }; })()`, ); - return capture(c, "release", await pageClip(c, grow(list, 12), RELEASE_WIDTH), { away: () => parkMouse(c) }); + // The zip's time ("8 hours ago", "yesterday") moves on by itself (owner: unsteady). It is + // right-aligned and its width goes with its words, so the region reaches RELEASE_TIME_WIDTH + // left of its right edge, short of the size before it. + const time = await c.evaluate(`(() => { + const t = ${ASSETS}.parentElement.querySelector("relative-time"); + if (!t) return null; + const r = t.getBoundingClientRect(); + return { x: r.right - ${RELEASE_TIME_WIDTH}, y: r.y, width: ${RELEASE_TIME_WIDTH}, height: r.height }; +})()`); + if (!time) throw new Error("the Assets list shows no time"); + return capture(c, "release", await pageClip(c, grow(list, 12), RELEASE_WIDTH), { + away: () => parkMouse(c), + unsteady: [{ on: { rect: time } }], + }); }, }; @@ -11835,6 +12877,7 @@ const SHOTS = [ ...formShots, ...formsChapterShots, ...projectsShots, + ...buildingShots, ...customControlsShots, ...customControlsCodeShots, ...codeShots, @@ -11906,6 +12949,12 @@ const JOB_SECONDS = { projects: 120, "projects-refs": 20, "projects-start": 20, + building: 90, + "building-new": 25, + "building-ax": 25, + "building-hklm": 40, + "building-llvm": 20, + "building-pkg": 30, customcontrols: 54, "customcontrols-2": 53, "customcontrols-3": 35, @@ -12042,7 +13091,8 @@ const SIZE_SLACK = 32; // file's): one with the same pixels, but for a capture's noise (`nearly`), is not kept, and a // light file there already is removed, since the page shows X.png in both themes then; one // more than SIZE_SLACK off its size fails. A picture within a capture's noise of its file is -// not written either. +// not written either. Returns whether the picture was written, or null for a light picture +// that is the dark one. function keep(name, out, png, theme, dark, scale = SCALE) { const file = path.join(outRoot, themedOut(out, theme)); const { w, h } = pngSize(png); @@ -12070,7 +13120,7 @@ function keep(name, out, png, theme, dark, scale = SCALE) { name, `${themedOut(out, theme)}: the dark picture's pixels, but for a capture's noise: ${had ? "removed" : "not written"}`, ); - return false; + return null; } } mkdirSync(path.dirname(file), { recursive: true }); @@ -12098,6 +13148,7 @@ function keep(name, out, png, theme, dark, scale = SCALE) { name, `${themedOut(out, theme)}: ${state} (${w}x${h} px, ${png.length} bytes; shown at {:width="${Math.round(w / scale)}" height="${Math.round(h / scale)}"}${other})`, ); + return write; } // A `once` picture has no light file: one left from before is removed, and its SVG. @@ -12122,9 +13173,18 @@ const svgResults = []; // written before is removed. Says how much of it differs from the PNG. The // picture's bundle goes to the bundle cache whether or not its SVG is written, // so that replay.mjs can draw it again once the converter draws it better. -async function keepSvg(name, out, png, picture) { +async function keepSvg(name, out, png, picture, written) { const svgOut = out.replace(/\.png$/i, ".svg"); const file = path.join(outRoot, svgOut); + // An SVG is drawn from the whole page, layers the picture does not show included, and those + // can differ from run to run (a designer still drawing under a floating panel); and one that + // sits on SVG_FAITHFUL's bar is written in one run and removed in the next. So the SVG of a + // picture whose PNG was not written stays as it is, with its bundle (owner): it changes + // with its PNG, or when replay.mjs draws it again after a change to the converter. + if (!written && existsSync(file)) { + say(name, `${svgOut}: unchanged, as its PNG is`); + return; + } const drop = (why) => { const had = existsSync(file); if (had) rmSync(file); @@ -12279,7 +13339,7 @@ async function runJob(job) { if (shot.once) dropLight(job.name, shot.out); // A light picture that is the dark one is not kept, and neither is its SVG or bundle. const svgFile = path.join(outRoot, out.replace(/\.png$/i, ".svg")); - if (values.svg && kept !== false) await keepSvg(job.name, out, png, state.svg); + if (values.svg && kept !== null) await keepSvg(job.name, out, png, state.svg, kept); else if (values.svg) { if (existsSync(svgFile)) rmSync(svgFile); dropBundle(bundlesRoot, out); @@ -12306,6 +13366,15 @@ async function runJob(job) { failed = Math.max(failed, own ? 1 : 2); } await endRun(run); + // what a setup checks or gives back once its IDE has ended + if (setup.end) { + try { + await setup.end(run); + } catch (e) { + complain(job.name, e.message); + failed = Math.max(failed, 1); + } + } say(job.name, `done in ${((Date.now() - started) / 1000).toFixed(1)} s`); } diff --git a/scripts/sweep_attributes.mjs b/scripts/sweep_attributes.mjs index fdeba27df..49df43421 100644 --- a/scripts/sweep_attributes.mjs +++ b/scripts/sweep_attributes.mjs @@ -64,7 +64,7 @@ // // Needs a twinBASIC install and Windows with a private desktop, like // examples.bat, so it is outside every gate and outside CI. -import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import { parseAttributes } from "./lib/attributes-doc.mjs"; @@ -104,7 +104,7 @@ import { leaseSlot, sleep, wantShow } from "./lib/tb-ide.mjs"; import { checkHarness } from "./lib/harness-settings.mjs"; import { buildNumber, findIde, unsupportedIde } from "./lib/tb-install.mjs"; import { packTree } from "./lib/tb-project.mjs"; -import { alive, finishTidy, startTidy } from "./lib/tb-registry.mjs"; +import { finishTidy, keepRunFolder, startTidy, sweepRunFolders } from "./lib/tb-registry.mjs"; import { CliError, choiceOption, @@ -156,7 +156,7 @@ accepts, laid against Reference/Attributes.md. also write every result, raw, as JSON --work where projects are staged; must be under the system temp folder (default %TEMP%/tbsweep/) - --keep keep the staged projects + --keep keep the staged projects, until deleted by hand --preflight build only the canaries, baselines and controls, and stop --dry-run count the probes and build nothing --list-sites print the site ids and exit @@ -896,19 +896,11 @@ async function main() { } const started = Date.now(); // The default folder is named for this process, so that runs at once never - // share one. A folder an earlier run left there, whose process has ended, goes. - if (!values.work) { - const runs = path.dirname(workRoot); - for (const name of existsSync(runs) ? readdirSync(runs) : []) { - if (!/^\d+$/.test(name) || alive(Number(name))) continue; - try { - rmSync(path.join(runs, name), { recursive: true, force: true }); - } catch { - // still in use: a later run tries again - } - } - } + // share one. A folder an earlier run left there, whose process has ended, + // goes, unless that run was given --keep. + if (!values.work) sweepRunFolders(path.dirname(workRoot)); mkdirSync(workRoot, { recursive: true }); + if (values.keep) keepRunFolder(workRoot); tidy = startTidy({ prefixes: [workRoot] }); let verify = null; try { diff --git a/test/example-projects/contributed-BigNumberLib/Settings b/test/example-projects/contributed-BigNumberLib/Settings index d31bf3831..e90cdbfc8 100644 --- a/test/example-projects/contributed-BigNumberLib/Settings +++ b/test/example-projects/contributed-BigNumberLib/Settings @@ -51,14 +51,14 @@ "autoCtlExt": true, "id": "{C8320E09-7273-4873-9646-DD1155EC9500}", "licence": "LibTom (Pubic Domain)", - "name": "[IMPORTED] BigNumberLib (Experimental) TomsFastMath Static Library", + "name": "[IMPORTED] BigNumberLib - TomsFastMath Static Library", "path32": "/Packages/BigNumberLib", "path64": "/Packages/BigNumberLib", "symbolId": "BigNumberLib", "versionBuild": "0", "versionMajor": "1", "versionMinor": "0", - "versionRevision": "2" + "versionRevision": "4" } ], "project.settingsVersion": 1, diff --git a/test/harness.md b/test/harness.md index 6cf08c88a..be74130a6 100644 --- a/test/harness.md +++ b/test/harness.md @@ -281,7 +281,10 @@ the median; the compiler's own compile at most 0.30 s under the IDE and 1.27 s u cold start included; IDE start to project open at most 4.04 s; a build at most 1.0 s, 4.97 s with LLVM; a compiler run at most 0.83 s without LLVM. What 10 s cuts off is known and accepted: the documentation harness's compile wait for the WinReg batches (12.5--13.8 s, project load -included) and one TBMANLIB_Aes LLVM run that printed for 15 s, both Experimental packages. +included; WinReg's samples are no longer marked `check_build`, so none is compiled) and one TBMANLIB_Aes LLVM run that printed for 15 s, both Experimental packages. +`check_examples` reports a batch whose compile meets its limit, or that the IDE never reports +open, as one finding ("was not judged"), against its first sample, and goes on with the other +batches; a canary batch that meets it is a finding of its canary. `package_tests.mjs` passes its own limit for a test case's run (`--timeout`, 60 s by default), because a case's run time is the package's own: tbRegExp's step-limit cases take about 16 s. diff --git a/test/package-tests/BigNumberLib/Sources/InverseTests.twin b/test/package-tests/BigNumberLib/Sources/InverseTests.twin index 0b855347d..f16088a05 100644 --- a/test/package-tests/BigNumberLib/Sources/InverseTests.twin +++ b/test/package-tests/BigNumberLib/Sources/InverseTests.twin @@ -123,7 +123,12 @@ Module InverseTests Expect.Done End Sub - ' The two cases below do not return on 1.0.2.0: the call stays in a loop. + [TestCase] + Public Sub Inverse_ZeroModulusRaisesError5() + Expect.Begin + Expect.AreEqual "5 invalid operation", InverseError("3", "0"), "error for the inverse of 3 modulo 0" + Expect.Done + End Sub [TestCase] Public Sub Inverse_ZeroValueOddModulus_RaisesError5() diff --git a/test/package-tests/BigNumberLib/Sources/OverflowTests.twin b/test/package-tests/BigNumberLib/Sources/OverflowTests.twin index fa8795b1f..35296fd56 100644 --- a/test/package-tests/BigNumberLib/Sources/OverflowTests.twin +++ b/test/package-tests/BigNumberLib/Sources/OverflowTests.twin @@ -127,4 +127,351 @@ Module OverflowTests Expect.Done End Sub + ' ---- helpers ---- + + ' A new BigNumber holding 2 to the power Exponent. + Private Function PowerOfTwo(ByVal Exponent As Long) As BigNumber + Dim one As New BigNumber + one.ValueString = "1" + Set PowerOfTwo = New BigNumber + PowerOfTwo.AssignShiftLeft one, Exponent + End Function + + ' The binary text of (2^K - 1) * (2^M - 1), for K and M of at least 1. + Private Function ExpectedProduct(ByVal K As Long, ByVal M As Long) As String + Dim t As Long + If K > M Then + t = K + K = M + M = t + End If + If K = 1 Then + ExpectedProduct = Rep("1", M) + Else + ExpectedProduct = Rep("1", K - 1) & "0" & Rep("1", M - K) & Rep("0", K - 1) & "1" + End If + End Function + + ' How (2^K - 1) * (2^M - 1) comes out: "ok", "error " or "wrong". + Private Function ProductOutcome(ByVal K As Long, ByVal M As Long) As String + Dim a As New BigNumber + Dim b As New BigNumber + Dim r As New BigNumber + a.ValueBinary = Rep("1", K) + b.ValueBinary = Rep("1", M) + On Error Resume Next + r.AssignMultiplication a, b + If Err.Number <> 0 Then + ProductOutcome = "error " & Err.Number + Err.Clear + Exit Function + End If + On Error GoTo 0 + If r.ValueBinary = ExpectedProduct(K, M) Then ProductOutcome = "ok" Else ProductOutcome = "wrong" + End Function + + ' The value of the binary text Bits modulo Modulus (Modulus below 1,000,000,000). + Private Function ModOfBinary(ByVal Bits As String, ByVal Modulus As Long) As Long + Dim i As Long + Dim r As Long + For i = 1 To Len(Bits) + r = (r * 2 + (Asc(Mid$(Bits, i, 1)) - 48)) Mod Modulus + Next i + ModOfBinary = r + End Function + + ' ---- subtraction, squaring, octal and binary text ---- + + [TestCase] + Public Sub Overflow_SubtractionBeyondTheLibrary_RaisesErrorOrIsRight() + Expect.Begin + Dim a As BigNumber + Dim b As New BigNumber + Dim r As New BigNumber + Dim e As Long + Set a = PowerOfTwo(LibraryBits() - 1) + b.ValueBinary = a.ValueBinary + b.IsNegative = True + On Error Resume Next + r.AssignSubtraction a, b + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual "1" & Rep("0", LibraryBits()), r.ValueBinary, "2^" & (LibraryBits() - 1) & " - (-2^" & (LibraryBits() - 1) & ") raised no error; ValueBinary" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_SquareBeyondTheLibrary_RaisesErrorOrIsRight() + Expect.Begin + Dim a As BigNumber + Dim r As New BigNumber + Dim e As Long + Set a = PowerOfTwo(3000) + On Error Resume Next + r.AssignSquared a + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual "1" & Rep("0", 6000), r.ValueBinary, "(2^3000)^2 raised no error; ValueBinary" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_SquareOneBitOverTheLibrary_RaisesErrorOrIsRight() + Expect.Begin + Dim a As BigNumber + Dim r As New BigNumber + Dim e As Long + Dim bits As Long + bits = (LibraryBits() + 2) \ 2 + Set a = PowerOfTwo(bits - 1) + On Error Resume Next + r.AssignSquared a + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual "1" & Rep("0", 2 * bits - 2), r.ValueBinary, "(2^" & (bits - 1) & ")^2, a power of two of " & (2 * bits - 1) & " bits, raised no error; ValueBinary" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_ValueOctalWithTooManyDigits_RaisesErrorOrIsRight() + Expect.Begin + Dim n As New BigNumber + Dim e As Long + On Error Resume Next + n.ValueOctal = Rep("7", 2000) + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual Rep("7", 2000), n.ValueOctal, "ValueOctal of 2,000 sevens (6,000 bits) raised no error; read back" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_ValueBinaryWithTooManyDigits_RaisesErrorOrIsRight() + Expect.Begin + Dim n As New BigNumber + Dim e As Long + On Error Resume Next + n.ValueBinary = Rep("1", 6000) + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual Rep("1", 6000), n.ValueBinary, "ValueBinary of 6,000 one digits raised no error; read back" + End If + Expect.Done + End Sub + + ' ---- multiplication near the limit ---- + + [TestCase] + Public Sub Overflow_MultiplicationOneBitOverTheLibrary_RaisesErrorOrIsRight() + Expect.Begin + Dim k As Long + Dim m As Long + Dim o As String + k = LibraryBits() \ 2 + m = LibraryBits() + 1 - k + o = ProductOutcome(k, m) + If o = "wrong" Then + Expect.Fail "(2^" & k & " - 1) * (2^" & m & " - 1), a product of " & (k + m) & " bits, raised no error and gave a wrong value" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_MultiplicationOfUnequalSizesOneBitOverTheLibrary_RaisesErrorOrIsRight() + Expect.Begin + Dim o As String + o = ProductOutcome(100, LibraryBits() + 1 - 100) + If o = "wrong" Then + Expect.Fail "(2^100 - 1) * (2^" & (LibraryBits() + 1 - 100) & " - 1), a product of " & (LibraryBits() + 1) & " bits, raised no error and gave a wrong value" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_ProductOfExactlyTheLibraryBits_RaisesErrorOrIsRight() + Expect.Begin + Dim k As Long + Dim m As Long + k = LibraryBits() \ 2 + m = LibraryBits() - k + If ProductOutcome(k, m) = "wrong" Then + Expect.Fail "(2^" & k & " - 1) * (2^" & m & " - 1), a product of " & LibraryBits() & " bits, raised no error and gave a wrong value" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Capacity_ProductOfTheLargestWholeNumberOfDigitsIsRight() + Expect.Begin + Dim t As Long + #If Win64 Then + t = LibraryBits() - 64 + #Else + t = LibraryBits() - 32 + #End If + Expect.AreEqual "ok", ProductOutcome(t \ 2, t - t \ 2), "(2^" & (t \ 2) & " - 1) * (2^" & (t - t \ 2) & " - 1), a product of " & t & " bits" + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_NegationOfA4200BitNumber_RaisesErrorOrIsRight() + Expect.Begin + Dim a As New BigNumber + Dim r As New BigNumber + Dim e As Long + a.ValueBinary = "1" & Rep("0", 4199) + On Error Resume Next + r.AssignNegation a + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual "-1" & Rep("0", 4199), r.ValueBinary, "AssignNegation of 2^4199, as binary" + End If + Expect.Done + End Sub + + ' ---- modular operations whose intermediate value does not fit ---- + + [TestCase] + Public Sub Overflow_MultiplicationModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight() + Expect.Begin + Dim a As New BigNumber + Dim b As New BigNumber + Dim c As New BigNumber + Dim r As New BigNumber + Dim sa As String + Dim sb As String + Dim e As Long + sa = Rep("1", 3000) + sb = Rep("1", 2900) + a.ValueBinary = sa + b.ValueBinary = sb + c.ValueString = "1000003" + On Error Resume Next + r.AssignMultiplicationModulus a, b, c + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual RefMath.DecMod(RefMath.DecMul(CStr(ModOfBinary(sa, 1000003)), CStr(ModOfBinary(sb, 1000003))), "1000003"), r.ValueString, "(a * b) mod 1000003 for a of 3,000 one bits and b of 2,900 one bits, whose product has 5,900 bits, raised no error; ValueString" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_SquaredModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight() + Expect.Begin + Dim a As New BigNumber + Dim c As New BigNumber + Dim r As New BigNumber + Dim sa As String + Dim e As Long + sa = Rep("1", 3000) + a.ValueBinary = sa + c.ValueString = "1000003" + On Error Resume Next + r.AssignSquaredModulus a, c + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual RefMath.DecMod(RefMath.DecMul(CStr(ModOfBinary(sa, 1000003)), CStr(ModOfBinary(sa, 1000003))), "1000003"), r.ValueString, "(a * a) mod 1000003 for a of 3,000 one bits, whose square has 6,000 bits, raised no error; ValueString" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_AdditionModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight() + Expect.Begin + Dim a As New BigNumber + Dim c As New BigNumber + Dim r As New BigNumber + Dim sa As String + Dim e As Long + sa = Rep("1", LibraryBits()) + a.ValueBinary = sa + c.ValueString = "1000003" + On Error Resume Next + r.AssignAdditionModulus a, a, c + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual CStr((2 * ModOfBinary(sa, 1000003)) Mod 1000003), r.ValueString, "(a + a) mod 1000003 for a of " & LibraryBits() & " one bits, whose sum has one bit more, raised no error; ValueString" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_ModulusOfANumberThatFillsTheLibrary_RaisesErrorOrIsRight() + Expect.Begin + Dim a As New BigNumber + Dim c As New BigNumber + Dim r As New BigNumber + Dim sa As String + Dim e As Long + sa = "1" & Rep("0", LibraryBits() - 1) + a.ValueBinary = sa + c.ValueString = "1000003" + On Error Resume Next + r.AssignModulus a, c + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual CStr(ModOfBinary(sa, 1000003)), r.ValueString, "2^" & (LibraryBits() - 1) & " mod 1000003, a number of " & LibraryBits() & " bits, raised no error; ValueString" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_AdditionModulusWhoseSumFillsTheLibrary_RaisesErrorOrIsRight() + Expect.Begin + Dim a As New BigNumber + Dim c As New BigNumber + Dim r As New BigNumber + Dim sa As String + Dim e As Long + sa = "1" & Rep("0", LibraryBits() - 2) + a.ValueBinary = sa + c.ValueString = "1000003" + On Error Resume Next + r.AssignAdditionModulus a, a, c + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual CStr((2 * ModOfBinary(sa, 1000003)) Mod 1000003), r.ValueString, "(2^" & (LibraryBits() - 2) & " + 2^" & (LibraryBits() - 2) & ") mod 1000003, a sum of " & LibraryBits() & " bits, raised no error; ValueString" + End If + Expect.Done + End Sub + + [TestCase] + Public Sub Overflow_SubtractionModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight() + Expect.Begin + Dim a As New BigNumber + Dim b As New BigNumber + Dim c As New BigNumber + Dim r As New BigNumber + Dim sa As String + Dim e As Long + sa = Rep("1", LibraryBits()) + a.ValueBinary = sa + b.ValueBinary = sa + b.IsNegative = True + c.ValueString = "1000003" + On Error Resume Next + r.AssignSubtractionModulus a, b, c + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual CStr((2 * ModOfBinary(sa, 1000003)) Mod 1000003), r.ValueString, "(a - (-a)) mod 1000003 for a of " & LibraryBits() & " one bits, whose difference has one bit more, raised no error; ValueString" + End If + Expect.Done + End Sub + End Module diff --git a/test/package-tests/BigNumberLib/Sources/RunAll.twin b/test/package-tests/BigNumberLib/Sources/RunAll.twin index 293a08190..af44ed077 100644 --- a/test/package-tests/BigNumberLib/Sources/RunAll.twin +++ b/test/package-tests/BigNumberLib/Sources/RunAll.twin @@ -1,11 +1,11 @@ ' Generated by scripts/package_tests.mjs from this project's [TestCase] Subs and expect.json: ' do not edit. Run Sub Main: each case prints PASS, FAIL or SKIP in the DEBUG CONSOLE. -' The cases are written for the package BigNumberLib, version 1.0.2.0. Each one checks what is +' The cases are written for the package BigNumberLib, version 1.0.4.0. Each one checks what is ' correct, so a case that fails names a defect of the package. Module RunAll Public Sub Main() - Expect.StartRun "BigNumberLib 1.0.2.0: 128 test cases" + Expect.StartRun "BigNumberLib 1.0.4.0: 145 test cases" On Error Resume Next Expect.StartCase Err.Clear @@ -287,8 +287,18 @@ Module RunAll Err.Clear InverseTests.Inverse_NegativeEvenModulusRaisesError5 Expect.EndCase "InverseTests.Inverse_NegativeEvenModulusRaisesError5", Err.Number, Err.Description - Expect.Skip "InverseTests.Inverse_ZeroValueOddModulus_RaisesError5", "it does not return in version 1.0.2.0" - Expect.Skip "InverseTests.Inverse_NegativeOddModulus_RaisesError5", "it does not return in version 1.0.2.0" + Expect.StartCase + Err.Clear + InverseTests.Inverse_ZeroModulusRaisesError5 + Expect.EndCase "InverseTests.Inverse_ZeroModulusRaisesError5", Err.Number, Err.Description + Expect.StartCase + Err.Clear + InverseTests.Inverse_ZeroValueOddModulus_RaisesError5 + Expect.EndCase "InverseTests.Inverse_ZeroValueOddModulus_RaisesError5", Err.Number, Err.Description + Expect.StartCase + Err.Clear + InverseTests.Inverse_NegativeOddModulus_RaisesError5 + Expect.EndCase "InverseTests.Inverse_NegativeOddModulus_RaisesError5", Err.Number, Err.Description Expect.StartCase Err.Clear ModulusTests.AssignModulus_PositiveDivisor @@ -387,6 +397,64 @@ Module RunAll Expect.EndCase "OverflowTests.Overflow_ValueHexWithTooManyDigits_RaisesErrorOrIsRight", Err.Number, Err.Description Expect.StartCase Err.Clear + OverflowTests.Overflow_SubtractionBeyondTheLibrary_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_SubtractionBeyondTheLibrary_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Overflow_SquareBeyondTheLibrary_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_SquareBeyondTheLibrary_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Overflow_SquareOneBitOverTheLibrary_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_SquareOneBitOverTheLibrary_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Overflow_ValueOctalWithTooManyDigits_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_ValueOctalWithTooManyDigits_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Overflow_ValueBinaryWithTooManyDigits_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_ValueBinaryWithTooManyDigits_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Overflow_MultiplicationOneBitOverTheLibrary_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_MultiplicationOneBitOverTheLibrary_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Overflow_MultiplicationOfUnequalSizesOneBitOverTheLibrary_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_MultiplicationOfUnequalSizesOneBitOverTheLibrary_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Overflow_ProductOfExactlyTheLibraryBits_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_ProductOfExactlyTheLibraryBits_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Capacity_ProductOfTheLargestWholeNumberOfDigitsIsRight + Expect.EndCase "OverflowTests.Capacity_ProductOfTheLargestWholeNumberOfDigitsIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Overflow_NegationOfA4200BitNumber_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_NegationOfA4200BitNumber_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Overflow_MultiplicationModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_MultiplicationModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Overflow_SquaredModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_SquaredModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear + OverflowTests.Overflow_AdditionModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_AdditionModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.Skip "OverflowTests.Overflow_ModulusOfANumberThatFillsTheLibrary_RaisesErrorOrIsRight", "it does not return in version 1.0.4.0" + Expect.Skip "OverflowTests.Overflow_AdditionModulusWhoseSumFillsTheLibrary_RaisesErrorOrIsRight", "it does not return in version 1.0.4.0" + Expect.StartCase + Err.Clear + OverflowTests.Overflow_SubtractionModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight + Expect.EndCase "OverflowTests.Overflow_SubtractionModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight", Err.Number, Err.Description + Expect.StartCase + Err.Clear ShiftTests.ShiftLeft_MultipliesByPowerOfTwo Expect.EndCase "ShiftTests.ShiftLeft_MultipliesByPowerOfTwo", Err.Number, Err.Description Expect.StartCase @@ -399,8 +467,8 @@ Module RunAll Expect.EndCase "ShiftTests.ShiftLeft_ByThousandsOfBits", Err.Number, Err.Description Expect.StartCase Err.Clear - ShiftTests.ShiftLeft_NegativeAmountDoesNotShiftRight - Expect.EndCase "ShiftTests.ShiftLeft_NegativeAmountDoesNotShiftRight", Err.Number, Err.Description + ShiftTests.ShiftLeft_NegativeAmountRaisesError5OrShiftsRight + Expect.EndCase "ShiftTests.ShiftLeft_NegativeAmountRaisesError5OrShiftsRight", Err.Number, Err.Description Expect.StartCase Err.Clear ShiftTests.ShiftRight_DividesByPowerOfTwoTruncatingTowardZero diff --git a/test/package-tests/BigNumberLib/Sources/ShiftTests.twin b/test/package-tests/BigNumberLib/Sources/ShiftTests.twin index b6d9fdc6a..d7a28a901 100644 --- a/test/package-tests/BigNumberLib/Sources/ShiftTests.twin +++ b/test/package-tests/BigNumberLib/Sources/ShiftTests.twin @@ -46,13 +46,25 @@ Module ShiftTests End Sub [TestCase] - Public Sub ShiftLeft_NegativeAmountDoesNotShiftRight() + Public Sub ShiftLeft_NegativeAmountRaisesError5OrShiftsRight() + ' Either convention is correct: an error, as Python's int, or a shift to the right, as + ' Java's and .NET's BigInteger. Expect.Begin Dim a As New BigNumber Dim r As New BigNumber + Dim e As Long a.ValueString = "1000" + r.ValueString = "7" + On Error Resume Next r.AssignShiftLeft a, -1 - Expect.IsTrue r.ValueString <> "500", "1000 << -1 is not 1000 >> 1, but it gave " & r.ValueString + e = Err.Number + Err.Clear + If e = 0 Then + Expect.AreEqual "500", r.ValueString, "1000 << -1 raised no error; ValueString" + Else + Expect.AreEqual 5, e, "the error 1000 << -1 raised" + Expect.AreEqual "7", r.ValueString, "a number that held 7, after 1000 << -1 raised an error" + End If Expect.Done End Sub diff --git a/test/package-tests/BigNumberLib/expect.json b/test/package-tests/BigNumberLib/expect.json index 4859acbc9..e0e36431b 100644 --- a/test/package-tests/BigNumberLib/expect.json +++ b/test/package-tests/BigNumberLib/expect.json @@ -1,98 +1,108 @@ { - "version": "1.0.2.0", + "version": "1.0.4.0", "cases": { - "GcdLcmTests.Gcd_NegativeFirstOperandKeepsItsValue": { - "fails": "1 of 2 checks failed: ValueString of the first operand after gcd(-12, 18): expected \"-12\", got \"12\"" - }, - "GcdLcmTests.Gcd_NegativeSecondOperandKeepsItsValue": { - "fails": "1 of 2 checks failed: ValueString of the second operand after gcd(12, -18): expected \"-18\", got \"18\"" - }, - "GcdLcmTests.Gcd_NegativeOperandStillAddsCorrectly": { - "fails": "2 of 2 checks failed: the first operand of gcd(-12, 18) plus 1: expected \"-11\", got \"11\"; the first operand of gcd(-12, 18) is less than 1: expected True, got False" - }, "GcdLcmTests.Lcm_OfTwoZeros_64Bit": { "win32": "pass", "win64": { "fails": "1 of 1 checks failed: lcm(0, 0) of a number that held 99: expected \"0\", got \"99\"" } }, - "GcdLcmTests.Lcm_NegativeFirstOperandKeepsItsValue": { - "fails": "1 of 2 checks failed: ValueString of the first operand after lcm(-4, 6): expected \"-4\", got \"4\"" - }, - "GcdLcmTests.Lcm_NegativeSecondOperandKeepsItsValue": { - "fails": "1 of 2 checks failed: ValueString of the second operand after lcm(4, -6): expected \"-6\", got \"6\"" - }, - "GcdLcmTests.Lcm_NegativeOperandStillAddsCorrectly": { - "fails": "1 of 1 checks failed: the first operand of lcm(-4, 6) plus 1: expected \"-3\", got \"3\"" - }, - "InverseTests.Inverse_ZeroValueOddModulus_RaisesError5": { - "hangs": true - }, - "InverseTests.Inverse_NegativeOddModulus_RaisesError5": { - "hangs": true - }, - "ModulusTests.AssignModulus_NegativeDivisor_ZeroResultIsNotNegative": { - "fails": "1 of 2 checks failed: IsNegative of 6 Mod -3: expected False, got True" - }, - "ModulusTests.AssignModulus_NegativeDivisor_ZeroResultEqualsZero": { - "fails": "2 of 2 checks failed: 6 Mod -3 IsEqualTo a zero read from \"0\": expected True, got False; 6 Mod -3 IsLessThan a zero read from \"0\": expected False, got True" - }, - "OverflowTests.Overflow_ShiftLeftBeyondTheLibrary_RaisesErrorOrIsRight": { - "fails": "1 of 1 checks failed: 1 << 6000 raised no error; ValueBinary: expected \"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"... (6001 characters), got \"0\"" + "OverflowTests.Overflow_SubtractionBeyondTheLibrary_RaisesErrorOrIsRight": { + "win32": { + "fails": "1 of 1 checks failed: 2^4351 - (-2^4351) raised no error; ValueBinary: expected \"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"... (4353 characters), got \"0\"" + }, + "win64": { + "fails": "1 of 1 checks failed: 2^4607 - (-2^4607) raised no error; ValueBinary: expected \"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"... (4609 characters), got \"0\"" + } }, - "OverflowTests.Overflow_MultiplicationBeyondTheLibrary_RaisesErrorOrIsRight": { - "fails": "1 of 1 checks failed: 2^3000 * 2^3000 raised no error; ValueBinary: expected \"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"... (6001 characters), got \"0\"" + "OverflowTests.Overflow_SquareBeyondTheLibrary_RaisesErrorOrIsRight": { + "fails": "1 of 1 checks failed: (2^3000)^2 raised no error; ValueBinary: expected \"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"... (6001 characters), got \"0\"" }, - "OverflowTests.Overflow_AdditionBeyondTheLibrary_RaisesErrorOrIsRight": { + "OverflowTests.Overflow_SquareOneBitOverTheLibrary_RaisesErrorOrIsRight": { "win32": { - "fails": "1 of 1 checks failed: (2^4352 - 1) * 2 raised no error; ValueBinary: expected \"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\"... (4353 characters), got \"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\"... (4352 characters)" + "fails": "1 of 1 checks failed: (2^2176)^2, a power of two of 4353 bits, raised no error; ValueBinary: expected \"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"... (4353 characters), got \"0\"" }, "win64": { - "fails": "1 of 1 checks failed: (2^4608 - 1) * 2 raised no error; ValueBinary: expected \"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\"... (4609 characters), got \"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\"... (4608 characters)" + "fails": "1 of 1 checks failed: (2^2304)^2, a power of two of 4609 bits, raised no error; ValueBinary: expected \"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"... (4609 characters), got \"0\"" } }, - "OverflowTests.Overflow_ValueStringWithTooManyDigits_RaisesErrorOrIsRight": { + "OverflowTests.Overflow_ValueOctalWithTooManyDigits_RaisesErrorOrIsRight": { "win32": { - "fails": "1 of 1 checks failed: ValueString of 1,600 nines raised no error; read back: expected \"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\"... (1600 characters), got \"4286452832310585597233729070503425569902306886885523889489200741297515745171908463685529577272257134\"... (1310 characters)" + "fails": "1 of 1 checks failed: ValueOctal of 2,000 sevens (6,000 bits) raised no error; read back: expected \"7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777\"... (2000 characters), got \"3777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777\"... (1451 characters)" }, "win64": { - "fails": "1 of 1 checks failed: ValueString of 1,600 nines raised no error; read back: expected \"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\"... (1600 characters), got \"9008938760588959665641366052989158261445202088243123331546110814618818177382341717365057548908500041\"... (1387 characters)" + "fails": "1 of 1 checks failed: ValueOctal of 2,000 sevens (6,000 bits) raised no error; read back: expected \"7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777\"... (2000 characters), got \"7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777\"... (1536 characters)" } }, - "OverflowTests.Overflow_ValueHexWithTooManyDigits_RaisesErrorOrIsRight": { + "OverflowTests.Overflow_ValueBinaryWithTooManyDigits_RaisesErrorOrIsRight": { "win32": { - "fails": "1 of 1 checks failed: ValueHex of 1,300 F digits raised no error; read back: expected \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\"... (1300 characters), got \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\"... (1088 characters)" + "fails": "1 of 1 checks failed: ValueBinary of 6,000 one digits raised no error; read back: expected \"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\"... (6000 characters), got \"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\"... (4352 characters)" }, "win64": { - "fails": "1 of 1 checks failed: ValueHex of 1,300 F digits raised no error; read back: expected \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\"... (1300 characters), got \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\"... (1152 characters)" + "fails": "1 of 1 checks failed: ValueBinary of 6,000 one digits raised no error; read back: expected \"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\"... (6000 characters), got \"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\"... (4608 characters)" } }, - "SignTests.IsNegative_SetTrueShowsMinusSign": { - "fails": "1 of 2 checks failed: ValueString of 5 after IsNegative = True: expected \"-5\", got \"5\"" + "OverflowTests.Overflow_MultiplicationOneBitOverTheLibrary_RaisesErrorOrIsRight": { + "win32": { + "fails": "1 of 1 checks failed: (2^2176 - 1) * (2^2177 - 1), a product of 4353 bits, raised no error and gave a wrong value" + }, + "win64": { + "fails": "1 of 1 checks failed: (2^2304 - 1) * (2^2305 - 1), a product of 4609 bits, raised no error and gave a wrong value" + } }, - "SignTests.IsNegative_SetTrueShowsMinusSignInEveryBase": { - "fails": "3 of 3 checks failed: ValueHex of 255 after IsNegative = True: expected \"-FF\", got \"FF\"; ValueOctal of 255 after IsNegative = True: expected \"-377\", got \"377\"; ValueBinary of 255 after IsNegative = True: expected \"-11111111\", got \"11111111\"" + "OverflowTests.Overflow_MultiplicationOfUnequalSizesOneBitOverTheLibrary_RaisesErrorOrIsRight": { + "win32": { + "fails": "1 of 1 checks failed: (2^100 - 1) * (2^4253 - 1), a product of 4353 bits, raised no error and gave a wrong value" + }, + "win64": { + "fails": "1 of 1 checks failed: (2^100 - 1) * (2^4509 - 1), a product of 4609 bits, raised no error and gave a wrong value" + } }, - "SignTests.IsNegative_SetTrueMakesArithmeticRight": { - "fails": "2 of 2 checks failed: 5 with IsNegative = True, plus 3: expected \"-2\", got \"2\"; 5 with IsNegative = True, times 3: expected \"-15\", got \"15\"" + "OverflowTests.Overflow_ProductOfExactlyTheLibraryBits_RaisesErrorOrIsRight": { + "win32": { + "fails": "1 of 1 checks failed: (2^2176 - 1) * (2^2176 - 1), a product of 4352 bits, raised no error and gave a wrong value" + }, + "win64": { + "fails": "1 of 1 checks failed: (2^2304 - 1) * (2^2304 - 1), a product of 4608 bits, raised no error and gave a wrong value" + } }, - "SignTests.IsNegative_SetTrueMakesNumberLessThanZero": { - "fails": "1 of 1 checks failed: 5 with IsNegative = True IsLessThan 0: expected True, got False" + "OverflowTests.Overflow_MultiplicationModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight": { + "win32": { + "fails": "1 of 1 checks failed: (a * b) mod 1000003 for a of 3,000 one bits and b of 2,900 one bits, whose product has 5,900 bits, raised no error; ValueString: expected \"102459\", got \"280374\"" + }, + "win64": { + "fails": "1 of 1 checks failed: (a * b) mod 1000003 for a of 3,000 one bits and b of 2,900 one bits, whose product has 5,900 bits, raised no error; ValueString: expected \"102459\", got \"836210\"" + } }, - "SignTests.AssignFromLong_Zero_IsNotNegative": { - "fails": "1 of 1 checks failed: IsNegative after AssignFromLong 0: expected False, got True" + "OverflowTests.Overflow_SquaredModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight": { + "win32": { + "fails": "1 of 1 checks failed: (a * a) mod 1000003 for a of 3,000 one bits, whose square has 6,000 bits, raised no error; ValueString: expected \"352069\", got \"97107\"" + }, + "win64": { + "fails": "1 of 1 checks failed: (a * a) mod 1000003 for a of 3,000 one bits, whose square has 6,000 bits, raised no error; ValueString: expected \"352069\", got \"652943\"" + } }, - "SignTests.AssignFromLong_Zero_EqualsZeroFromString": { - "fails": "2 of 2 checks failed: AssignFromLong 0 IsEqualTo a zero read from \"0\": expected True, got False; a zero read from \"0\" IsEqualTo AssignFromLong 0: expected True, got False" + "OverflowTests.Overflow_AdditionModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight": { + "win32": { + "fails": "1 of 1 checks failed: (a + a) mod 1000003 for a of 4352 one bits, whose sum has one bit more, raised no error; ValueString: expected \"218265\", got \"325980\"" + }, + "win64": { + "fails": "1 of 1 checks failed: (a + a) mod 1000003 for a of 4608 one bits, whose sum has one bit more, raised no error; ValueString: expected \"204708\", got \"408045\"" + } }, - "SignTests.AssignFromLong_Zero_IsNotLessThanZeroFromString": { - "fails": "2 of 3 checks failed: AssignFromLong 0 IsLessThan a zero read from \"0\": expected False, got True; AssignFromLong 0 IsGreaterThanOrEqualTo a zero read from \"0\": expected True, got False" + "OverflowTests.Overflow_ModulusOfANumberThatFillsTheLibrary_RaisesErrorOrIsRight": { + "hangs": true }, - "SignTests.AssignSquared_Zero_IsNotNegative": { - "fails": "1 of 2 checks failed: IsNegative of 0 squared: expected False, got True" + "OverflowTests.Overflow_AdditionModulusWhoseSumFillsTheLibrary_RaisesErrorOrIsRight": { + "hangs": true }, - "SignTests.AssignSquared_Zero_EqualsZeroFromString": { - "fails": "2 of 2 checks failed: 0 squared IsEqualTo a zero read from \"0\": expected True, got False; 0 squared IsLessThan a zero read from \"0\": expected False, got True" + "OverflowTests.Overflow_SubtractionModulusIntermediateBeyondTheLibrary_RaisesErrorOrIsRight": { + "win32": { + "fails": "1 of 1 checks failed: (a - (-a)) mod 1000003 for a of 4352 one bits, whose difference has one bit more, raised no error; ValueString: expected \"218265\", got \"325980\"" + }, + "win64": { + "fails": "1 of 1 checks failed: (a - (-a)) mod 1000003 for a of 4608 one bits, whose difference has one bit more, raised no error; ValueString: expected \"204708\", got \"408045\"" + } } } } diff --git a/test/shots/building/ax/Settings b/test/shots/building/ax/Settings new file mode 100644 index 000000000..6df7001b1 --- /dev/null +++ b/test/shots/building/ax/Settings @@ -0,0 +1,30 @@ +{ + "configuration.inherits": "Defaults", + "project.appTitle": "ShotActiveX", + "project.buildPath": "${SourcePath}\\Build\\${ProjectName}_${Architecture}.${FileExtension}", + "project.buildType": "ActiveX DLL", + "project.description": "An ActiveX DLL", + "project.dllRegisterLocalMachine": false, + "project.exportPathIsV2": true, + "project.id": "{EAEAEAEA-EAEA-EAEA-EAEA-EAEAEAEAEA00}", + "project.name": "ShotActiveX", + "project.optionExplicit": true, + "project.references": [ + { + "id": "{00020430-0000-0000-C000-000000000046}", + "lcid": 0, + "name": "OLE Automation", + "path32": "C:\\Windows\\SysWOW64\\stdole2.tlb", + "path64": "C:\\Windows\\System32\\stdole2.tlb", + "versionMajor": 2, + "versionMinor": 0 + } + ], + "project.settingsVersion": 1, + "project.useProjectIdForTypeLibraryId": true, + "project.warnings": { + "errors": [], + "ignored": [] + }, + "runtime.useUnicodeStandardLibrary": true +} diff --git a/test/shots/building/ax/Sources/MyClass.twin b/test/shots/building/ax/Sources/MyClass.twin new file mode 100644 index 000000000..45ac0fb3d --- /dev/null +++ b/test/shots/building/ax/Sources/MyClass.twin @@ -0,0 +1,8 @@ +[ClassId("B01D0000-0000-4000-8000-00000000B001")] +[InterfaceId("B01D0000-0000-4000-8000-00000000B002")] +[EventInterfaceId("B01D0000-0000-4000-8000-00000000B003")] +Class MyClass + Public Function Hello() As String + Return "hello" + End Function +End Class diff --git a/test/shots/building/exe/Settings b/test/shots/building/exe/Settings new file mode 100644 index 000000000..c3640c85d --- /dev/null +++ b/test/shots/building/exe/Settings @@ -0,0 +1,31 @@ +{ + "configuration.inherits": "Defaults", + "project.appTitle": "Program", + "project.buildPath": "${SourcePath}\\Build\\${ProjectName}_${Architecture}.${FileExtension}", + "project.buildType": "Standard EXE", + "project.description": "Program", + "project.exportPathIsV2": true, + "project.id": "{EAEAEAEA-EAEA-EAEA-EAEA-EAEAEAEAEA00}", + "project.name": "Program", + "project.optionExplicit": true, + "project.references": [ + { + "id": "{00020430-0000-0000-C000-000000000046}", + "lcid": 0, + "name": "OLE Automation", + "path32": "C:\\Windows\\SysWOW64\\stdole2.tlb", + "path64": "C:\\Windows\\System32\\stdole2.tlb", + "versionMajor": 2, + "versionMinor": 0 + } + ], + "project.settingsVersion": 1, + "project.startupObject": "Sub Main", + "project.versionMajor": 1, + "project.versionMinor": 0, + "project.warnings": { + "errors": [], + "ignored": [] + }, + "runtime.useUnicodeStandardLibrary": true +} diff --git a/test/shots/building/exe/Sources/MainMod.twin b/test/shots/building/exe/Sources/MainMod.twin new file mode 100644 index 000000000..570f0f881 --- /dev/null +++ b/test/shots/building/exe/Sources/MainMod.twin @@ -0,0 +1,11 @@ +Module MainMod + Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As Long) + + ' Runs for a minute at most, so that a second build finds its file in use. + Public Sub Main() + Dim i As Long + For i = 1 To 600 + Sleep 100 + Next + End Sub +End Module diff --git a/test/shots/building/pkg/Settings b/test/shots/building/pkg/Settings new file mode 100644 index 000000000..f96836aa7 --- /dev/null +++ b/test/shots/building/pkg/Settings @@ -0,0 +1,29 @@ +{ + "configuration.inherits": "Defaults", + "project.buildPath": "${SourcePath}\\Build\\${ProjectName}_${Architecture}.${FileExtension}", + "project.buildType": "Package TWINPACK", + "project.description": "Greeting functions", + "project.id": "{EAEAEAEA-EAEA-EAEA-EAEA-EAEAEAEAEA00}", + "project.licence": "MIT", + "project.name": "MyPackage", + "project.optionExplicit": true, + "project.references": [ + { + "id": "{00020430-0000-0000-C000-000000000046}", + "lcid": 0, + "name": "OLE Automation", + "path32": "C:\\Windows\\SysWOW64\\stdole2.tlb", + "path64": "C:\\Windows\\System32\\stdole2.tlb", + "versionMajor": 2, + "versionMinor": 0 + } + ], + "project.versionMajor": 1, + "project.versionMinor": 0, + "project.warnings": { + "errors": [], + "ignored": [] + }, + "runtime.useUnicodeStandardLibrary": true, + "project.packageVisibility": "PRIVATE" +} diff --git a/test/shots/building/pkg/Sources/HelloWorldModule.twin b/test/shots/building/pkg/Sources/HelloWorldModule.twin new file mode 100644 index 000000000..bd1284ba3 --- /dev/null +++ b/test/shots/building/pkg/Sources/HelloWorldModule.twin @@ -0,0 +1,7 @@ +Module HelloWorldModule + + Public Function Hello() As String + Return "Hello world!" + End Function + +End Module