@mudlet/mudlet-web 0.4.5 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. package/README.md +1 -1
  2. package/dist-lib/analytics.d.ts +27 -0
  3. package/dist-lib/assets/fonts/Vera.woff2 +0 -0
  4. package/dist-lib/assets/fonts/VeraBI.woff2 +0 -0
  5. package/dist-lib/assets/fonts/VeraBd.woff2 +0 -0
  6. package/dist-lib/assets/fonts/VeraIt.woff2 +0 -0
  7. package/dist-lib/assets/mapParser.worker-DrVZ3wg_.js +9 -0
  8. package/dist-lib/backupImport-wt8r7JXI.js +233 -0
  9. package/dist-lib/branding.d.ts +111 -13
  10. package/dist-lib/db/sqliteClient.d.ts +195 -7
  11. package/dist-lib/hooks/useAutoReconnect.d.ts +61 -0
  12. package/dist-lib/hooks/useDocumentFullscreen.d.ts +23 -0
  13. package/dist-lib/hooks/useKeyboardShortcuts.d.ts +37 -0
  14. package/dist-lib/hooks/useRecordLastPlayed.d.ts +10 -0
  15. package/dist-lib/import/applyMudletProfile.d.ts +35 -9
  16. package/dist-lib/import/backupImport.d.ts +118 -0
  17. package/dist-lib/import/collectProfileExport.d.ts +33 -2
  18. package/dist-lib/import/defaultPackages.d.ts +57 -14
  19. package/dist-lib/import/defaults/CF-loader/CF-loader.mpackage +0 -0
  20. package/dist-lib/import/defaults/MedBootstrap/MedBootstrap.mpackage +0 -0
  21. package/dist-lib/import/defaults/deleteOldProfiles/deleteOldProfiles.mpackage +0 -0
  22. package/dist-lib/import/defaults/echo/echo.mpackage +0 -0
  23. package/dist-lib/import/defaults/enable-accessibility/enable-accessibility.mpackage +0 -0
  24. package/dist-lib/import/defaults/generic_mapper/generic_mapper.mpackage +0 -0
  25. package/dist-lib/import/defaults/gui-drop/gui-drop.mpackage +0 -0
  26. package/dist-lib/import/defaults/icesus-loader/icesus-loader.mpackage +0 -0
  27. package/dist-lib/import/defaults/mg-loader/mg-loader.mpackage +0 -0
  28. package/dist-lib/import/defaults/mudlet-base-ui/mudlet-base-ui.mpackage +0 -0
  29. package/dist-lib/import/defaults/mudlet-mapper.xml +1215 -389
  30. package/dist-lib/import/mudletControlChars.d.ts +14 -0
  31. package/dist-lib/import/mudletHost.d.ts +73 -10
  32. package/dist-lib/import/mudletLink.d.ts +53 -2
  33. package/dist-lib/import/mudletProfileExport.d.ts +38 -5
  34. package/dist-lib/import/mudletProfileImport.d.ts +110 -12
  35. package/dist-lib/import/mudletVariables.d.ts +4 -3
  36. package/dist-lib/import/mudletWriteback.d.ts +15 -1
  37. package/dist-lib/import/mudletXmlImport.d.ts +46 -0
  38. package/dist-lib/import/packageFonts.d.ts +33 -0
  39. package/dist-lib/import/packageInstaller.d.ts +111 -7
  40. package/dist-lib/import/qtProfileData.d.ts +10 -0
  41. package/dist-lib/import/remotePackageInstall.d.ts +23 -7
  42. package/dist-lib/import/zipEntries.d.ts +45 -0
  43. package/dist-lib/index.d.ts +7 -3
  44. package/dist-lib/index.js +50660 -29735
  45. package/dist-lib/logging/SessionLogger.d.ts +75 -15
  46. package/dist-lib/map/MapSelectionOverlay.d.ts +2 -2
  47. package/dist-lib/map/MapStore.d.ts +432 -59
  48. package/dist-lib/map/MudletHighlightOverlay.d.ts +2 -2
  49. package/dist-lib/map/{MudixMapReader.d.ts → MudletMapReader.d.ts} +2 -2
  50. package/dist-lib/map/areaGraph.d.ts +120 -0
  51. package/dist-lib/map/environmentKit.d.ts +36 -0
  52. package/dist-lib/map/labelPixmap.d.ts +90 -0
  53. package/dist-lib/map/mapImageExport.d.ts +36 -2
  54. package/dist-lib/map/mapStyle.d.ts +11 -0
  55. package/dist-lib/map/mapVersion.d.ts +66 -0
  56. package/dist-lib/map/pathfinding.d.ts +2 -2
  57. package/dist-lib/mud/CharLoginController.d.ts +230 -0
  58. package/dist-lib/mud/ItemIdSequence.d.ts +1 -1
  59. package/dist-lib/mud/MudSession.d.ts +279 -22
  60. package/dist-lib/mud/PatternEngine.d.ts +153 -14
  61. package/dist-lib/mud/aliases/AliasEngine.d.ts +55 -9
  62. package/dist-lib/mud/autoLogin.d.ts +59 -0
  63. package/dist-lib/mud/commandSplit.d.ts +9 -0
  64. package/dist-lib/mud/connection/LineAssembler.d.ts +38 -11
  65. package/dist-lib/mud/connection/MudClient.d.ts +291 -53
  66. package/dist-lib/mud/connection/SubnegotiationRepair.d.ts +24 -0
  67. package/dist-lib/mud/connection/TelnetNegotiator.d.ts +208 -68
  68. package/dist-lib/mud/connection/telnetDebug.d.ts +8 -8
  69. package/dist-lib/mud/events.d.ts +102 -23
  70. package/dist-lib/mud/games/bundledGames.d.ts +12 -7
  71. package/dist-lib/mud/games/gameLinks.d.ts +40 -0
  72. package/dist-lib/mud/games/icons/3Kingdoms.png +0 -0
  73. package/dist-lib/mud/games/icons/3Scapes.png +0 -0
  74. package/dist-lib/mud/games/icons/achaea.png +0 -0
  75. package/dist-lib/mud/games/icons/aetolia.png +0 -0
  76. package/dist-lib/mud/games/icons/banner_astaria.png +0 -0
  77. package/dist-lib/mud/games/icons/banner_darkmists.png +0 -0
  78. package/dist-lib/mud/games/icons/banner_dreamland.png +0 -0
  79. package/dist-lib/mud/games/icons/banner_petria.jpg +0 -0
  80. package/dist-lib/mud/games/icons/banner_ropmud.png +0 -0
  81. package/dist-lib/mud/games/icons/blackmud.png +0 -0
  82. package/dist-lib/mud/games/icons/carrionfields.png +0 -0
  83. package/dist-lib/mud/games/icons/dragonfire_icon.png +0 -0
  84. package/dist-lib/mud/games/icons/fed2-logo.png +0 -0
  85. package/dist-lib/mud/games/icons/icesus_480x120.png +0 -0
  86. package/dist-lib/mud/games/icons/imperian.png +0 -0
  87. package/dist-lib/mud/games/icons/infinity_480x120.png +0 -0
  88. package/dist-lib/mud/games/icons/lusternia.png +0 -0
  89. package/dist-lib/mud/games/icons/morgengrauen_480x120.png +0 -0
  90. package/dist-lib/mud/games/icons/mudlet-tutorial.png +0 -0
  91. package/dist-lib/mud/games/icons/phoenixmud_480x120.png +0 -0
  92. package/dist-lib/mud/games/icons/starmourn.png +0 -0
  93. package/dist-lib/mud/games/icons/voidmud_icon.png +0 -0
  94. package/dist-lib/mud/games/icons/wotmudicon.png +0 -0
  95. package/dist-lib/mud/games/websiteLinks.d.ts +21 -0
  96. package/dist-lib/mud/keybindings/KeyEngine.d.ts +110 -4
  97. package/dist-lib/mud/keybindings/browserReservedKeys.d.ts +2 -2
  98. package/dist-lib/mud/keybindings/keyEventTarget.d.ts +61 -0
  99. package/dist-lib/mud/keybindings/qtKeys.d.ts +91 -12
  100. package/dist-lib/mud/protocol/atcp.d.ts +19 -0
  101. package/dist-lib/mud/protocol/byteString.d.ts +24 -0
  102. package/dist-lib/mud/protocol/charLoginFlow.d.ts +243 -16
  103. package/dist-lib/mud/protocol/charset.d.ts +111 -46
  104. package/dist-lib/mud/protocol/codePages.d.ts +10 -0
  105. package/dist-lib/mud/protocol/constants.d.ts +17 -10
  106. package/dist-lib/mud/protocol/echo.d.ts +23 -27
  107. package/dist-lib/mud/protocol/gmcp.d.ts +36 -6
  108. package/dist-lib/mud/protocol/index.d.ts +3 -2
  109. package/dist-lib/mud/protocol/luaLiteral.d.ts +12 -0
  110. package/dist-lib/mud/protocol/mccp.d.ts +83 -1
  111. package/dist-lib/mud/protocol/mnes.d.ts +41 -58
  112. package/dist-lib/mud/protocol/msdp.d.ts +11 -4
  113. package/dist-lib/mud/protocol/msp.d.ts +3 -2
  114. package/dist-lib/mud/protocol/mssp.d.ts +9 -4
  115. package/dist-lib/mud/protocol/multiByte.d.ts +51 -0
  116. package/dist-lib/mud/protocol/multiByteEncode.d.ts +42 -0
  117. package/dist-lib/mud/protocol/mxp.d.ts +193 -14
  118. package/dist-lib/mud/protocol/oauthClientFlow.d.ts +128 -0
  119. package/dist-lib/mud/protocol/qtCodePages.generated.d.ts +1 -0
  120. package/dist-lib/mud/protocol/tlsCodes.d.ts +40 -3
  121. package/dist-lib/mud/replay/ReplayPlayer.d.ts +16 -1
  122. package/dist-lib/mud/replay/replayFormat.d.ts +29 -2
  123. package/dist-lib/mud/text/Console.d.ts +255 -49
  124. package/dist-lib/mud/text/FormatState.d.ts +137 -14
  125. package/dist-lib/mud/text/ansiEscapes.d.ts +32 -16
  126. package/dist-lib/mud/text/colorParsers.d.ts +14 -2
  127. package/dist-lib/mud/text/colorSpaceId.d.ts +2 -0
  128. package/dist-lib/mud/text/colors.d.ts +17 -10
  129. package/dist-lib/mud/text/controlCharacterMode.d.ts +1 -1
  130. package/dist-lib/mud/text/hyperlinkVisibility.d.ts +1 -1
  131. package/dist-lib/mud/text/lineBreak.d.ts +5 -0
  132. package/dist-lib/mud/text/serverWrap.d.ts +2 -2
  133. package/dist-lib/mud/text/textAnalyzer.d.ts +79 -0
  134. package/dist-lib/mud/text/unicodeRuns.d.ts +11 -0
  135. package/dist-lib/mud/text/unicodeTables.generated.d.ts +3 -0
  136. package/dist-lib/mud/text/wcwidth.d.ts +27 -22
  137. package/dist-lib/mud/timers/TimerEngine.d.ts +163 -11
  138. package/dist-lib/mud/timers/workerClock.d.ts +67 -0
  139. package/dist-lib/mud/triggers/TriggerEngine.d.ts +449 -47
  140. package/dist-lib/mud/triggers/legacyColorPatterns.d.ts +58 -0
  141. package/dist-lib/mud/triggers/pcre/Pcre2.d.ts +83 -1
  142. package/dist-lib/oauth-callback.html +94 -0
  143. package/dist-lib/pcre2Wasm.d.ts +54 -0
  144. package/dist-lib/pcre2Wasm.js +241 -0
  145. package/dist-lib/scripting/EngineHost.d.ts +54 -21
  146. package/dist-lib/scripting/IScriptingRuntime.d.ts +103 -27
  147. package/dist-lib/scripting/MxpFrameManager.d.ts +10 -1
  148. package/dist-lib/scripting/ScriptingAPI.d.ts +1039 -213
  149. package/dist-lib/scripting/ScriptingEngine.d.ts +753 -103
  150. package/dist-lib/scripting/StopwatchManager.d.ts +97 -36
  151. package/dist-lib/scripting/http/HttpService.d.ts +9 -1
  152. package/dist-lib/scripting/http/userUrl.d.ts +41 -0
  153. package/dist-lib/scripting/lua/LuaRuntime.d.ts +352 -77
  154. package/dist-lib/scripting/lua/argContracts.d.ts +71 -0
  155. package/dist-lib/scripting/lua/bindings/automation.d.ts +1 -1
  156. package/dist-lib/scripting/lua/bindings/commands.d.ts +13 -0
  157. package/dist-lib/scripting/lua/bindings/context.d.ts +20 -2
  158. package/dist-lib/scripting/lua/bindings/diagnostics.d.ts +1 -1
  159. package/dist-lib/scripting/lua/bindings/map.d.ts +1 -1
  160. package/dist-lib/scripting/lua/bindings/media.d.ts +2 -2
  161. package/dist-lib/scripting/lua/bindings/output.d.ts +1 -1
  162. package/dist-lib/scripting/lua/bindings/session.d.ts +2 -2
  163. package/dist-lib/scripting/lua/bindings/textEdit.d.ts +1 -1
  164. package/dist-lib/scripting/lua/bindings/userWindows.d.ts +1 -1
  165. package/dist-lib/scripting/lua/byteArmor.d.ts +36 -0
  166. package/dist-lib/scripting/lua/imageSize.d.ts +7 -0
  167. package/dist-lib/scripting/lua/rex.d.ts +4 -2
  168. package/dist-lib/scripting/lua/sqlRowEncoder.d.ts +6 -1
  169. package/dist-lib/scripting/lua/utf8CaseMap.d.ts +1 -0
  170. package/dist-lib/scripting/lua/utf8Patterns.d.ts +21 -1
  171. package/dist-lib/scripting/lua/wellFormedStrings.d.ts +40 -0
  172. package/dist-lib/scripting/lua/yajl.d.ts +43 -5
  173. package/dist-lib/scripting/profilesPresence.d.ts +20 -2
  174. package/dist-lib/scripting/vfs/ProfileVFS.d.ts +164 -10
  175. package/dist-lib/scripting/vfs/fsErrors.d.ts +28 -0
  176. package/dist-lib/scripting/vfs/idbCommit.d.ts +20 -0
  177. package/dist-lib/storage/appStore.d.ts +24 -9
  178. package/dist-lib/storage/hooks.d.ts +5 -1
  179. package/dist-lib/storage/index.d.ts +2 -2
  180. package/dist-lib/storage/mapStorage.d.ts +2 -0
  181. package/dist-lib/storage/persistentStorage.d.ts +3 -1
  182. package/dist-lib/storage/profileStorage.d.ts +15 -0
  183. package/dist-lib/storage/profileVfsData.d.ts +3 -3
  184. package/dist-lib/storage/schema.d.ts +521 -44
  185. package/dist-lib/storage/storageMigration.d.ts +82 -0
  186. package/dist-lib/storage-g5V1b-c1.js +2039 -0
  187. package/dist-lib/styles.css +1 -1
  188. package/dist-lib/ui/AboutModal.d.ts +1 -1
  189. package/dist-lib/ui/BrandLoginFields.d.ts +1 -1
  190. package/dist-lib/ui/BrowserSignInModal.d.ts +23 -0
  191. package/dist-lib/ui/CharLoginModal.d.ts +24 -15
  192. package/dist-lib/ui/CmdLineMenuRegistry.d.ts +14 -5
  193. package/dist-lib/ui/CommandBar.d.ts +8 -8
  194. package/dist-lib/ui/ConnectionFormModal.d.ts +25 -1
  195. package/dist-lib/ui/ConnectionScreen.d.ts +9 -1
  196. package/dist-lib/ui/GameLinkPrompt.d.ts +28 -0
  197. package/dist-lib/ui/HelpModal.d.ts +5 -1
  198. package/dist-lib/ui/MapSymbolUsageModal.d.ts +32 -0
  199. package/dist-lib/ui/MouseEventRegistry.d.ts +31 -4
  200. package/dist-lib/ui/NotepadModal.d.ts +22 -0
  201. package/dist-lib/ui/ResizableModal.d.ts +16 -1
  202. package/dist-lib/ui/SettingsModal.d.ts +10 -1
  203. package/dist-lib/ui/TlsAlertBanner.d.ts +3 -1
  204. package/dist-lib/ui/Toolbar.d.ts +22 -1
  205. package/dist-lib/ui/VaultManageButton.d.ts +20 -0
  206. package/dist-lib/ui/VaultModal.d.ts +5 -0
  207. package/dist-lib/ui/VaultUnlockPrompt.d.ts +15 -0
  208. package/dist-lib/ui/buttons/ButtonsBar.d.ts +3 -1
  209. package/dist-lib/ui/buttons/inactiveButtons.d.ts +25 -0
  210. package/dist-lib/ui/cmdline/CommandLineManager.d.ts +19 -0
  211. package/dist-lib/ui/cmdline/plainText.d.ts +16 -0
  212. package/dist-lib/ui/cmdline/subCommandLine.d.ts +78 -0
  213. package/dist-lib/ui/cmdline/useCmdLineSelection.d.ts +26 -0
  214. package/dist-lib/ui/cmdline/useSubCommandLineKeys.d.ts +33 -0
  215. package/dist-lib/ui/codemirror/lineParagraphMarks.d.ts +19 -0
  216. package/dist-lib/ui/codemirror/luaHover.d.ts +7 -0
  217. package/dist-lib/ui/codemirror/options.d.ts +33 -0
  218. package/dist-lib/ui/codemirror/theme.d.ts +29 -5
  219. package/dist-lib/ui/commands/addonCommands.d.ts +134 -0
  220. package/dist-lib/ui/commands/appShortcuts.d.ts +86 -0
  221. package/dist-lib/ui/commands/hostCommands.d.ts +88 -0
  222. package/dist-lib/ui/commands/keyMatch.d.ts +20 -0
  223. package/dist-lib/ui/commands/keySequence.d.ts +57 -0
  224. package/dist-lib/ui/components/ContextMenu.d.ts +21 -1
  225. package/dist-lib/ui/components/FontPicker.d.ts +5 -1
  226. package/dist-lib/ui/components/useModalFocus.d.ts +13 -1
  227. package/dist-lib/ui/helpTopics.d.ts +15 -0
  228. package/dist-lib/ui/labels/LabelManager.d.ts +172 -9
  229. package/dist-lib/ui/labels/LabelOverlay.d.ts +19 -0
  230. package/dist-lib/ui/labels/backgroundImageSize.d.ts +19 -0
  231. package/dist-lib/ui/labels/labelModel.d.ts +64 -0
  232. package/dist-lib/ui/labels/qColor.d.ts +13 -0
  233. package/dist-lib/ui/labels/qtCss.d.ts +12 -4
  234. package/dist-lib/ui/landmarks.d.ts +9 -0
  235. package/dist-lib/ui/launcher/ActionMenu.d.ts +19 -0
  236. package/dist-lib/ui/launcher/GameDetails.d.ts +21 -0
  237. package/dist-lib/ui/launcher/GameSection.d.ts +18 -0
  238. package/dist-lib/ui/launcher/LauncherSearch.d.ts +23 -0
  239. package/dist-lib/ui/launcher/ProfileArt.d.ts +20 -0
  240. package/dist-lib/ui/launcher/ProfileSection.d.ts +43 -0
  241. package/dist-lib/ui/launcher/launcherModel.d.ts +72 -0
  242. package/dist-lib/ui/layout/overlayLayerOrder.d.ts +2 -2
  243. package/dist-lib/ui/menu/MenuBar.d.ts +31 -0
  244. package/dist-lib/ui/menu/SplitButton.d.ts +39 -0
  245. package/dist-lib/ui/menu/anchoredPopup.d.ts +74 -0
  246. package/dist-lib/ui/menu/appMenus.d.ts +65 -0
  247. package/dist-lib/ui/menu/menuModel.d.ts +88 -0
  248. package/dist-lib/ui/menu/toolbarModel.d.ts +56 -0
  249. package/dist-lib/ui/notepad.d.ts +76 -0
  250. package/dist-lib/ui/openSignInPage.d.ts +14 -0
  251. package/dist-lib/ui/output/OutputContextMenu.d.ts +14 -1
  252. package/dist-lib/ui/output/OutputRenderer.d.ts +5 -0
  253. package/dist-lib/ui/output/OutputSearchBar.d.ts +5 -1
  254. package/dist-lib/ui/output/StickyOutputPanel.d.ts +17 -3
  255. package/dist-lib/ui/output/TextAnalyzerModal.d.ts +25 -0
  256. package/dist-lib/ui/output/caretMode.d.ts +3 -2
  257. package/dist-lib/ui/output/clearSplit.d.ts +11 -0
  258. package/dist-lib/ui/output/outputCopy.d.ts +41 -2
  259. package/dist-lib/ui/output/outputRows.d.ts +43 -0
  260. package/dist-lib/ui/output/selectionGesture.d.ts +35 -0
  261. package/dist-lib/ui/output/wordSelection.d.ts +33 -0
  262. package/dist-lib/ui/search/matcher.d.ts +14 -4
  263. package/dist-lib/ui/settings/SettingsShell.d.ts +91 -0
  264. package/dist-lib/ui/settings/ShortcutEditor.d.ts +13 -0
  265. package/dist-lib/ui/sound/SoundManager.d.ts +210 -44
  266. package/dist-lib/ui/sound/closedCaption.d.ts +4 -1
  267. package/dist-lib/ui/sound/mediaDirection.d.ts +35 -0
  268. package/dist-lib/ui/tabCompletion.d.ts +53 -0
  269. package/dist-lib/ui/textedit/TextEditManager.d.ts +11 -2
  270. package/dist-lib/ui/useOpenProfiles.d.ts +1 -1
  271. package/dist-lib/ui/useVaultSaver.d.ts +26 -0
  272. package/dist-lib/ui/video/VideoManager.d.ts +7 -0
  273. package/dist-lib/ui/windows/WindowManager.d.ts +452 -37
  274. package/dist-lib/ui/windows/panels/ScriptEditorPanel.d.ts +14 -0
  275. package/dist-lib/ui/windows/panels/ScriptSearch.d.ts +6 -1
  276. package/dist-lib/ui/windows/panels/TextPanel.d.ts +4 -1
  277. package/dist-lib/ui/windows/panels/VariablesView.d.ts +37 -7
  278. package/dist-lib/ui/windows/panels/WindowCmdLine.d.ts +4 -2
  279. package/dist-lib/ui/windows/panels/aliasLoop.d.ts +24 -0
  280. package/dist-lib/ui/windows/panels/editorClipboard.d.ts +45 -0
  281. package/dist-lib/ui/windows/panels/editorUndo.d.ts +79 -0
  282. package/dist-lib/ui/windows/panels/mapAreaChange.d.ts +10 -0
  283. package/dist-lib/utils/appShellCache.d.ts +25 -0
  284. package/dist-lib/utils/fontFamilyName.d.ts +13 -0
  285. package/dist-lib/utils/fontLoader.d.ts +31 -0
  286. package/dist-lib/utils/formatBytes.d.ts +4 -0
  287. package/dist-lib/utils/mustBeOneOf.d.ts +9 -0
  288. package/dist-lib/utils/profileLock.d.ts +1 -1
  289. package/dist-lib/utils/storedCredentials.d.ts +31 -0
  290. package/dist-lib/utils/systemTheme.d.ts +24 -0
  291. package/dist-lib/utils/timeZone.d.ts +10 -0
  292. package/dist-lib/vault/CredentialVault.d.ts +197 -0
  293. package/dist-lib/vault/deviceUnlock.d.ts +47 -0
  294. package/dist-lib/vault/passkeyPrf.d.ts +56 -0
  295. package/dist-lib/vault/useVault.d.ts +8 -0
  296. package/dist-lib/vault/vaultAccess.d.ts +80 -0
  297. package/dist-lib/vault/vaultCrypto.d.ts +56 -0
  298. package/dist-lib/vault/vaultHelpTopic.d.ts +9 -0
  299. package/dist-lib/vault/vaultRecord.d.ts +92 -0
  300. package/dist-lib/vfs-sw.js +220 -11
  301. package/dist-lib/vite.d.ts +1 -1
  302. package/dist-lib/vite.js +66 -43
  303. package/package.json +22 -14
  304. package/dist-lib/assets/mapParser.worker-t-3rd1zR.js +0 -9
  305. package/dist-lib/mud/connection/PingTracker.d.ts +0 -41
  306. package/dist-lib/ui/BundledGameGrid.d.ts +0 -21
  307. package/dist-lib/ui/ConnectionGrid.d.ts +0 -21
  308. package/dist-lib/ui/bufferWords.d.ts +0 -38
@@ -2,9 +2,10 @@ import type { MudSession, ScriptLogSource } from '../mud/MudSession';
2
2
  import type { AliasEngine } from '../mud/aliases/AliasEngine';
3
3
  import type { TriggerEngine } from '../mud/triggers/TriggerEngine';
4
4
  import type { TimerEngine } from '../mud/timers/TimerEngine';
5
- import type { KeyEngine } from '../mud/keybindings/KeyEngine';
5
+ import type { KeyEngine, KeyNode } from '../mud/keybindings/KeyEngine';
6
6
  import type { WindowHandle, WindowOpenOptions } from '../ui/windows/types';
7
- import type { LabelManager, LabelCreateOptions, LabelMouseEvent, LabelWheelEvent } from '../ui/labels/LabelManager';
7
+ import type { LabelManager, LabelCreateOptions, LabelMouseEvent, LabelWheelEvent, LabelLiveRegion } from '../ui/labels/LabelManager';
8
+ import { AddonCommandRegistry } from '../ui/commands/addonCommands';
8
9
  import type { CommandLineManager } from '../ui/cmdline/CommandLineManager';
9
10
  import type { ScrollBoxManager } from '../ui/scrollbox/ScrollBoxManager';
10
11
  import { TextEditManager } from '../ui/textedit/TextEditManager';
@@ -37,6 +38,13 @@ declare class ScriptingWindowsAPI {
37
38
  show(id: string): boolean;
38
39
  close(id: string): void;
39
40
  has(id: string): boolean;
41
+ /** The window's record, compared by identity to tell it from one a
42
+ * handler put in its place under the same name. */
43
+ record(id: string): object | undefined;
44
+ /** Whether a mapper has been created this session (see WindowManager.hasMapper). */
45
+ hasMapper(): boolean;
46
+ /** The report the last loadJsonMap wrote for log/errors.txt, once (see WindowManager.takeMapReport). */
47
+ takeMapReport(): string;
40
48
  isVisible(id: string): boolean;
41
49
  isMiniConsole(id: string): boolean;
42
50
  move(id: string, x: number, y: number): void;
@@ -45,6 +53,23 @@ declare class ScriptingWindowsAPI {
45
53
  * Host::openWindow honours the `area` argument on every call, not just
46
54
  * the one that creates the dock widget. 'main' means floating. */
47
55
  setDockArea(id: string, area: string): void;
56
+ /** Whether the window is shown in a dock rather than floating. */
57
+ isDocked(id: string): boolean;
58
+ /**
59
+ * Float a docked user window ahead of a move or resize, as Host::moveWindow
60
+ * and Host::resizeWindow do (`if (!pD->isFloating()) pD->setFloating(true)`)
61
+ * before they move or resize the dock widget — which is also why a docked
62
+ * window's getWindowGeometry reads back what resizeWindow set. Geyser's
63
+ * UserWindow:move documents the same ("is set to floating state if this
64
+ * function is used"). setFloating leaves a hidden dock hidden, so this does
65
+ * too. Miniconsoles have no dock and are left alone.
66
+ */
67
+ floatForGeometryChange(id: string): void;
68
+ /** Commit the window layout synchronously, so the next script line sees the
69
+ * sizes a dock change produced (see WindowManager.settleLayout). */
70
+ settleLayout(): void;
71
+ /** Queue the sysUserWindowResizeEvent a freshly opened user window is owed. */
72
+ announceCreatedSize(id: string): void;
48
73
  bringToFront(id: string): void;
49
74
  sendToBack(id: string): void;
50
75
  resize(id: string, width: number, height: number): void;
@@ -68,6 +93,8 @@ declare class ScriptingWindowsAPI {
68
93
  printCmdLine(id: string, text: string): boolean;
69
94
  appendCmdLine(id: string, text: string): boolean;
70
95
  getCmdLineValue(id: string): string;
96
+ hasCommandLine(id: string): boolean;
97
+ deleteCommandLine(id: string): boolean;
71
98
  }
72
99
  declare class ScriptingLabelsAPI {
73
100
  private readonly manager;
@@ -88,6 +115,11 @@ declare class ScriptingLabelsAPI {
88
115
  htmlRewriter: () => (html: string) => string);
89
116
  create(name: string, opts: LabelCreateOptions): boolean;
90
117
  has(name: string): boolean;
118
+ setSvgTint(name: string, color: string): boolean;
119
+ resetSvgTint(name: string): boolean;
120
+ setSvgRotation(name: string, degrees: number): boolean;
121
+ setSvgShear(name: string, shearX: number, shearY: number): boolean;
122
+ resetSvgTransform(name: string): boolean;
91
123
  /** Whether a movie is installed on this label — the movie functions report
92
124
  * "no movie here" separately from "no such label". */
93
125
  hasMovie(name: string): boolean;
@@ -107,12 +139,20 @@ declare class ScriptingLabelsAPI {
107
139
  b: number;
108
140
  a: number;
109
141
  } | null;
142
+ /** Backs the label branch of the global setFont/getFont — see
143
+ * {@link ScriptingAPI.setFont}. */
144
+ setFont(name: string, family: string): boolean;
145
+ getFont(name: string): string | null;
146
+ /** The label branch of the global setFontSize/getFontSize. */
147
+ setFontSize(name: string, size: number): boolean;
148
+ getFontSize(name: string): number | null;
110
149
  setStyleSheet(name: string, css: string): boolean;
111
150
  getStyleSheet(name: string): string | undefined;
112
151
  /** Pre-rewrite CSS per label, keyed by name — see {@link setStyleSheet}. */
113
152
  private readonly authoredCss;
114
153
  setLinkStyle(name: string, color: string, visitedColor: string, underline: boolean): boolean;
115
154
  resetLinkStyle(name: string): boolean;
155
+ clearVisitedLinks(name: string): boolean;
116
156
  getSizeHint(name: string): {
117
157
  width: number;
118
158
  height: number;
@@ -125,6 +165,12 @@ declare class ScriptingLabelsAPI {
125
165
  setMouseLeaveCallback(name: string, fn: ((e: LabelMouseEvent) => void) | undefined): boolean;
126
166
  setWheelCallback(name: string, fn: ((e: LabelWheelEvent) => void) | undefined): boolean;
127
167
  setTooltip(name: string, text: string | undefined): boolean;
168
+ setAccessibleName(name: string, accessibleName: string): boolean;
169
+ getAccessibleName(name: string): string | undefined;
170
+ setAccessibleButton(name: string, button: boolean | undefined): boolean;
171
+ getAccessibleRole(name: string): string | undefined;
172
+ setLiveRegion(name: string, liveRegion: LabelLiveRegion): boolean;
173
+ getLiveRegion(name: string): LabelLiveRegion | undefined;
128
174
  setClickThrough(name: string, value: boolean): boolean;
129
175
  setCursor(name: string, cursor: string | undefined): boolean;
130
176
  raise(name: string): boolean;
@@ -157,6 +203,32 @@ export declare class ScriptingAPI {
157
203
  private readonly oscLinks;
158
204
  readonly windows: ScriptingWindowsAPI;
159
205
  readonly labels: ScriptingLabelsAPI;
206
+ /** Mudlet's addon commands (addCommand and friends). Per profile, like
207
+ * every other placement a package makes. */
208
+ readonly addonCommands: AddonCommandRegistry;
209
+ /** The package or module whose code the calling frame is, or '' for the
210
+ * profile's own; see ScriptingEngine.packageOfCaller. */
211
+ packageOfCaller(source: string, isMain: boolean, calledFromMain: boolean): string;
212
+ /** A player clicked a command's button. Mudlet raises `sysCommandClicked`
213
+ * with the id as a NUMBER (mudlet.cpp:694-699), which is the id addCommand
214
+ * handed the package — that is what makes the id worth returning. */
215
+ addonCommandClicked(id: number): void;
216
+ /** The `mapperButton` mode a script set this session — Host::mMapperButtonMode. */
217
+ mapperButtonMode(): 'default' | 'scripted' | 'disabled';
218
+ /** Host::interceptMapperButton. Asked by the client's own map button,
219
+ * menu entry and shortcut before they toggle the map: true means a script
220
+ * has claimed the button and the client must leave the map alone —
221
+ * "disabled" swallows the press, "scripted" turns it into
222
+ * `sysMapperButtonAction` so a UI package can show its own map window. */
223
+ interceptMapperButton(): boolean;
224
+ private readonly mapperButtonListeners;
225
+ /** Hear `setConfig("mapperButton", …)`, so the button can grey out while
226
+ * it is "disabled", as desktop disables its mapper action. */
227
+ onMapperButtonModeChange(fn: () => void): () => void;
228
+ /** Values for the `sessionOnly` options in {@link CONFIG_PERSIST_ONLY} —
229
+ * held here rather than in the profile's config bag precisely so they are
230
+ * gone next session. */
231
+ private readonly sessionConfig;
160
232
  readonly cmdLines: CommandLineManager;
161
233
  readonly scrollBoxes: ScrollBoxManager;
162
234
  readonly textEdits: TextEditManager;
@@ -184,6 +256,7 @@ export declare class ScriptingAPI {
184
256
  * the in-flight console partial belongs to flushDeferredEcho and must not
185
257
  * be closed out from under it. */
186
258
  private setDeferringEcho;
259
+ private readonly queueCommandEcho;
187
260
  private echoOnMatchedLine;
188
261
  /** Mudlet `startLogging(state)`. Forwarded to ProfileSession, which owns
189
262
  * the SessionLogger instance (created/torn-down on this hook). */
@@ -191,14 +264,28 @@ export declare class ScriptingAPI {
191
264
  /** Mudlet `appendLog(text)`. Forwarded to the active SessionLogger (wired by
192
265
  * ProfileSession, which owns the logger lifecycle). */
193
266
  private logAppender;
194
- /** Mudlet `closeMudlet()`. mudix maps it to "close the active profile":
267
+ /** Mudlet `closeMudlet()`. Mudlet Web maps it to "close the active profile":
195
268
  * disconnect, then return to the connection screen. Wired by ProfileSession. */
196
269
  private closeProfileCallback;
197
- private selection;
270
+ /** A closeMudlet() is armed and has not run yet (see closeMudlet). */
271
+ private closeMudletArmed;
272
+ /** Set by destroy(): an armed closeMudlet() that outlives the profile
273
+ * has nothing left to close. */
274
+ private destroyed;
275
+ /** One selection per console, keyed by window name ('main' for the main
276
+ * console), the way each desktop TConsole keeps its own P_begin/P_end:
277
+ * selecting or deselecting in one window leaves every other window's
278
+ * selection standing. Each belongs to the line it was made on, as
279
+ * desktop's P_begin/P_end name a line: moving the cursor leaves it there,
280
+ * and deleting the line drops it. */
281
+ private readonly selections;
198
282
  private clipboard;
199
283
  private clipboardText;
200
284
  private buffers;
201
285
  constructor(session: MudSession, aliasEngine: AliasEngine, triggerEngine: TriggerEngine, timerEngine: TimerEngine, keyEngine: KeyEngine, connectionId: string);
286
+ /** Push the persisted `accessibleLabels` setting onto the labels, which
287
+ * Host::setAccessibleLabels does for every label model it holds. */
288
+ private syncAccessibleLabelsFromConfig;
202
289
  /** Push the persisted `muteMediaAPI` / `muteMediaGame` gates onto the live
203
290
  * sound and video managers. Both setters no-op when already in the wanted
204
291
  * state, so this is cheap to call on every config-bag change. */
@@ -234,21 +321,31 @@ export declare class ScriptingAPI {
234
321
  /** Mudlet `sendMSDP(variable, ...values)`. Frames an MSDP subnegotiation
235
322
  * (`IAC SB MSDP MSDP_VAR <var> [MSDP_VAL <val>]... IAC SE`) and sends it. */
236
323
  sendMSDP(variable: string, values: string[]): boolean;
237
- /** Mudlet `sendSocket(data)`. Sends a literal byte-string over the socket
238
- * with no telnet/encoding processing (each char is one byte). */
239
- sendSocket(data: string): boolean;
324
+ /** Mudlet `sendSocket(data [, parseTelnetCodes])`. Sends a literal
325
+ * byte-string over the socket with no telnet/encoding processing (each
326
+ * char is one byte). With `parseTelnetCodes` the `<T_IAC>`-style tags are
327
+ * decoded first, as feedTelnet's are (TLuaInterpreter::parseTelnetCodes). */
328
+ sendSocket(data: string, parseTelnetCodes?: boolean): boolean;
240
329
  /** Mudlet `feedTelnet(data)`. Injects raw server bytes into the inbound
241
330
  * pipeline as if received from the MUD (telnet stripping → ANSI →
242
331
  * triggers → render). */
243
332
  /** Mudlet `feedTelnet(data)` — inject imitation server bytes. Refused while
244
333
  * a socket exists in any state but unconnected, so replayed data can never
245
334
  * interleave with a live stream; the message is returned for the binding to
246
- * shape into Mudlet's `(nil, errMsg)`, and null means it was fed. */
247
- feedTelnet(data: string): string | null;
335
+ * shape into Mudlet's `(nil, errMsg)`, and null means it was fed.
336
+ *
337
+ * The empty string is not data: it asks which version of the byte-tag
338
+ * table this client decodes, and feeds nothing (TLuaInterpreter::feedTelnet
339
+ * answers `true, "feedTelnet: using table version N"` for it). */
340
+ feedTelnet(data: string): string | {
341
+ version: string;
342
+ } | null;
248
343
  /** Mudlet `loadReplay(fileName)` core. Starts playback of a Mudlet binary
249
344
  * replay (.dat). The LuaRuntime binding reads the bytes from the VFS
250
- * before calling here. Returns null on success or the failure reason. */
251
- loadReplay(bytes: Uint8Array): string | null;
345
+ * before calling here, and hands over `readAt` so playback reads each
346
+ * chunk again from the file as it comes up (see MudSession.loadReplayData).
347
+ * Returns null on success or the failure reason. */
348
+ loadReplay(bytes: Uint8Array, readAt?: (position: number, length: number) => Uint8Array): string | null;
252
349
  /** Deliver any replay chunk that has come due. Only the busted pump calls
253
350
  * this — see MudSession.pumpReplay. */
254
351
  pumpReplay(): number;
@@ -260,6 +357,13 @@ export declare class ScriptingAPI {
260
357
  * has elapsed. Same reason again: the runner blocks the event loop the
261
358
  * reveal timer would have fired on. */
262
359
  pumpHyperlinkReveals(): boolean;
360
+ /** Report the size of a user window just opened. Same reason again: the
361
+ * runner blocks the turn that report was queued for. */
362
+ pumpCreatedWindowSizes(): boolean;
363
+ /** Run the map info contributors for a repaint of the map widget that
364
+ * updateMap() or centerview() asked for. Same reason again: the runner
365
+ * blocks the render that paint would have come with. */
366
+ pumpMapPaint(): boolean;
263
367
  /** Mudlet `receiveMSP(text)`. Parses an MSP payload (`!!SOUND(...)` /
264
368
  * `!!MUSIC(...)` tags) as if the server had sent it and dispatches the
265
369
  * resulting sound/music commands through the normal `msp` event path
@@ -269,6 +373,9 @@ export declare class ScriptingAPI {
269
373
  * merely permitted by the profile's `enableMSP` config. Mudlet gates
270
374
  * receiveMSP on this (ctelnet::isMSPEnabled). */
271
375
  isMspNegotiated(): boolean;
376
+ /** Whether the server has taken GMCP up on this connection — Mudlet's
377
+ * `cTelnet::isGMCPEnabled`, which `sendGMCP` is refused without. */
378
+ isGmcpEnabled(): boolean;
272
379
  /** Mudlet `sendATCP(message)`. Frames + sends an ATCP (telnet 200)
273
380
  * subnegotiation; false when the socket isn't open. */
274
381
  sendATCP(message: string): boolean;
@@ -286,14 +393,18 @@ export declare class ScriptingAPI {
286
393
  * inbound stream (default "utf-8"). */
287
394
  getServerEncoding(): string;
288
395
  /** Mudlet `setServerEncoding(name)`. Switch the server stream decoder to
289
- * `name` (one of getServerEncodingsList()); false when unsupported or no
290
- * connection is active. */
291
- setServerEncoding(name: string): boolean;
292
- /** Mudlet `getServerEncodingsList()`. The encodings mudix can decode. */
396
+ * `name` (one of getServerEncodingsList()). Returns true, or the refusal
397
+ * cTelnet::setEncoding gives — the only place a script author is shown
398
+ * every name they could have asked for, so it lists them all, ASCII first
399
+ * as Mudlet does. */
400
+ setServerEncoding(name: string): true | string;
401
+ /** Mudlet `getServerEncodingsList()`. The encodings Mudlet Web can decode. */
293
402
  getServerEncodingsList(): string[];
294
- /** Mudlet `getCharacterName()`. mudix uses one character per profile, so
295
- * this returns the active profile name (same value as getProfileName());
296
- * empty string when unset. */
403
+ /** Mudlet `getCharacterName()` — `Host::getLogin()`, the character name the
404
+ * profile logs in with, *not* the profile name. '' when none is saved; the
405
+ * Lua wrapper reports that as Mudlet's `nil, "no character name set"`.
406
+ * Read through {@link readStoredLogin}, the same source auto-login and the
407
+ * GMCP `Char.Login` reply use, so a branded build's in-memory login counts. */
297
408
  getCharacterName(): string;
298
409
  /**
299
410
  * Mudlet `getProfiles()`. A record keyed by profile name, one entry per
@@ -305,7 +416,8 @@ export declare class ScriptingAPI {
305
416
  * - `connected` — the profile is connected to its game. Own tab: live; other
306
417
  * tabs: their last-announced state (BroadcastChannel presence). Always
307
418
  * false for a profile that isn't loaded.
308
- * - `description` — the connection record's free-text description.
419
+ * - `description` — the connection record's free-text description, or the
420
+ * blurb its bundled game ships with when it has none.
309
421
  * On a duplicate profile name, last-wins (a Lua table can't hold dup keys).
310
422
  */
311
423
  getProfiles(): Record<string, {
@@ -321,16 +433,58 @@ export declare class ScriptingAPI {
321
433
  * version is our own release (see src/version.ts), not the Mudlet API
322
434
  * level — that's what `getMudletVersion()` reports. */
323
435
  getMudletInfo(): void;
324
- /** Mudlet `loadProfile(name) → bool`. Opens the named profile and connects
436
+ /** Mudlet `loadProfile(name)`. Opens the named profile and connects
325
437
  * to it. Each profile lives in its own browser tab (the per-profile lock
326
438
  * keeps it to one tab), so this opens a NEW tab at `?profile=<id>&connect=1`
327
439
  * rather than switching the current one — the calling profile stays open
328
- * alongside, mirroring Mudlet's multi-profile model. Returns false for an
329
- * unknown name, when targeting the profile already open in this tab, or when
330
- * the browser blocks the popup. NOTE: `window.open` needs a user gesture, so
331
- * this works from a key/button/alias but a browser may block it from a
332
- * trigger (no Mudlet equivalent to that limitation). */
333
- loadProfile(name: string): boolean;
440
+ * alongside, mirroring Mudlet's multi-profile model.
441
+ *
442
+ * Returns null on success, or the message for Mudlet's `nil, message`
443
+ * refusal: an unknown name, a profile already open (in this tab or any
444
+ * other — the loaded set is the same one getProfiles() reports), or a popup
445
+ * the browser blocked. `window.open` needs a user gesture and a browser
446
+ * allows one new tab per gesture, so a trigger (no gesture) or the second
447
+ * loadProfile in one alias is refused (mudlet-web#453). That can't be
448
+ * lifted from a page, so a refusal leaves a link in the main console that
449
+ * opens the profile on click — the click is the gesture the call lacked. */
450
+ loadProfile(name: string): string | null;
451
+ /** True when profile `id` is open in this tab or any other. */
452
+ private isProfileLoaded;
453
+ /** Open profile `id` in a new tab and dial it. False when the browser
454
+ * refused the tab. */
455
+ private openProfileTab;
456
+ /** The fallback for a loadProfile the browser refused: a line of its own
457
+ * in the main console carrying a link that opens the profile. A click on
458
+ * it that finds the profile open by then (another link, the user) just
459
+ * says so rather than opening a second tab the lock would park. */
460
+ private echoOpenProfileLink;
461
+ /** A plain line of client feedback in the main console, on a line of its
462
+ * own. */
463
+ private echoInfoLine;
464
+ /** Mudlet `closeProfile(name)`. Closes the named open profile — this one,
465
+ * or one open in another tab, which is asked to close itself over the
466
+ * profiles-presence channel. Closing is what `closeMudlet()` does here:
467
+ * disconnect, then return that tab to the connection screen.
468
+ *
469
+ * Returns null on success, or the message for Mudlet's `nil, message`
470
+ * refusal when no open profile has that name. Like Mudlet, which closes the
471
+ * tab on the next event-loop turn, the close happens after the calling
472
+ * script has returned — so a script closing its own profile still finishes
473
+ * (closeMudlet defers itself). */
474
+ closeProfile(name: string): string | null;
475
+ /** Mudlet `setActiveProfile(name)`: make an open profile the one in front.
476
+ * The name is matched as MudletApp::getCanonicalProfileName matches it —
477
+ * case-insensitively against the profiles, then against the bundled games
478
+ * (a game with no profile is "not loaded").
479
+ *
480
+ * Returns null on success or the refusal message. For this tab's own
481
+ * profile it asks for the window's focus and succeeds. Every other profile
482
+ * has a tab of its own, and a page can't bring another tab forward —
483
+ * browsers only let the user switch tabs — so that is refused rather than
484
+ * reported as done (mudlet-web#453): the target tab is asked to flash its
485
+ * title instead, and the message says so, so a script can tell the user
486
+ * where to look. */
487
+ setActiveProfile(name: string): string | null;
334
488
  /** Mudlet `getCommandSeparator()`. Returns the profile's command separator
335
489
  * (the string that splits one Enter into multiple commands). Defaults to
336
490
  * `;;` when the profile hasn't customised it. */
@@ -339,6 +493,24 @@ export declare class ScriptingAPI {
339
493
  private configBag;
340
494
  /** Shallow-merge a single key into the persisted config bag. */
341
495
  private patchConfigBag;
496
+ /** Shallow-merge several keys into the config bag in one store write, so
497
+ * a watcher sees them change together rather than one at a time. */
498
+ private patchConfigBagFields;
499
+ /**
500
+ * The font the script editor reads code in (Mudlet's editorFont,
501
+ * editorFontSize and editorFontFollowsDisplay). A profile that never chose
502
+ * one follows the main console's font; one that did keeps its own, which a
503
+ * display font moving leaves alone.
504
+ */
505
+ editorFontState(): {
506
+ follows: boolean;
507
+ family: string;
508
+ size: number;
509
+ };
510
+ /** The negotiator flag each profile protocol toggle drives. MCCP is
511
+ * absent on purpose: its handler owns its own switch and isn't part of
512
+ * the negotiator flag set. */
513
+ private static readonly LIVE_PROTOCOL_FLAG;
342
514
  private getProtocol;
343
515
  private setProtocol;
344
516
  private getMapperField;
@@ -363,7 +535,46 @@ export declare class ScriptingAPI {
363
535
  * legacy boolean reading alongside a newer enum — currently `showSentText`.
364
536
  * The no-arg / table forms are handled by the Lua wrapper in Other.lua,
365
537
  * which calls this once per key. */
366
- getConfig(key: string, useStringFormat?: boolean): unknown;
538
+ getConfig(rawKey: string, useStringFormat?: boolean): unknown;
539
+ /**
540
+ * An IRC setting as desktop's TIrcClient readers give it. Each lives in a
541
+ * profile file of its own, as a serialised QString (Host::readProfileData),
542
+ * so a profile linked from or exported to desktop carries it. A value the
543
+ * writers would refuse — one a profile saved before they did may still hold
544
+ * — reads as the default, or for channels is skipped. A profile that kept
545
+ * its settings in the config bag before they moved to files is read from
546
+ * there until something writes them again.
547
+ */
548
+ private readIrcConfig;
549
+ /** Store an IRC setting where {@link readIrcConfig} reads it, as desktop's
550
+ * writeProfileData writes it. The value has been vetted already. With no
551
+ * profile folder to write into it is kept in the config bag instead. */
552
+ private writeIrcConfig;
553
+ /**
554
+ * `getConfig` for the `experiment.*` namespace, or {@link NOT_AN_EXPERIMENT}
555
+ * when the key is not one. Three shapes: `experiment.list` is the names this
556
+ * build knows, `<group>.active` is the suffix of whichever experiment in
557
+ * that group is on (nil when none is), and any other key reads as the
558
+ * on/off flag — FALSE for a name this build has never heard of, rather than
559
+ * a refusal, so a script can feature-test one that does not exist here.
560
+ */
561
+ private readExperimentConfig;
562
+ /** The experiments currently switched on, as stored in the profile bag. */
563
+ private enabledExperiments;
564
+ /**
565
+ * `setConfig` for the `experiment.*` namespace: true on success, or the
566
+ * refusal message. At most one experiment in a group may be on at a time —
567
+ * a group being the first two dot-segments — so enabling one turns off
568
+ * whichever of its siblings was on (Host::setExperimentEnabled).
569
+ */
570
+ private writeExperimentConfig;
571
+ /** The bounds a `num` option accepts, for the refusal Bridge.lua writes.
572
+ * Null when the key is unbounded or names no option. */
573
+ configKeyRange(key: string): readonly [number, number] | null;
574
+ /** The values a string option accepts, for the refusal Bridge.lua writes —
575
+ * the list is the only place a script author is told what the option takes,
576
+ * so it has to reach the message. Null when the key takes no fixed set. */
577
+ configKeyValues(key: string): readonly string[] | null;
367
578
  /**
368
579
  * What kind of value `setConfig(key, …)` takes, or null when the key names
369
580
  * no option at all. Mudlet reads each option with a `getVerified*` helper,
@@ -375,10 +586,24 @@ export declare class ScriptingAPI {
375
586
  * `'readonly'` keys exist for `getConfig` but refuse every write; `'any'`
376
587
  * keys take more than one value type and vet the value themselves.
377
588
  */
378
- configKeyKind(key: string): 'bool' | 'num' | 'str' | 'any' | 'readonly' | null;
589
+ configKeyKind(rawKey: string): 'bool' | 'num' | 'str' | 'any' | 'readonly' | null;
379
590
  /** Mudlet `setConfig(key, value)`. Returns true when the key is known and
380
591
  * writable, false for unknown or read-only keys. */
381
- setConfig(key: string, value: unknown): boolean;
592
+ /**
593
+ * The room symbols the named font has no glyph for, as desktop lists them,
594
+ * or null when it can draw every one the map uses.
595
+ *
596
+ * Measured rather than looked up, because a browser will not say what a
597
+ * font contains: a character with no glyph is drawn as the font's notdef
598
+ * box, and every such character therefore measures the SAME width. So each
599
+ * symbol is compared against a codepoint nothing has a glyph for — the last
600
+ * of Private Use Plane 16 — in the same font at the same size. Equal widths
601
+ * mean both came out as the box.
602
+ */
603
+ private symbolsThisFontCannotDraw;
604
+ /** Returns true, or a string when the option was taken and the caller
605
+ * should be told something about it — see the mapSymbolFont case. */
606
+ setConfig(rawKey: string, value: unknown): boolean | string;
382
607
  /**
383
608
  * The connection a profile-name argument refers to, or null when no profile
384
609
  * has that name. Matching ignores case, as Mudlet's does: it looks the name
@@ -425,7 +650,17 @@ export declare class ScriptingAPI {
425
650
  /** Write every module flagged to sync back out to its own file. Called by
426
651
  * saveProfile — see the note there. */
427
652
  saveSyncedModules(): void;
428
- reloadModule(name: string): boolean;
653
+ /** Write the profile out as a Mudlet-format XML save. The XML half of
654
+ * `saveProfile([location [, saveName]])` — see ScriptingEngine. */
655
+ saveProfileXml(location?: string, saveName?: string): {
656
+ ok: true;
657
+ path: string;
658
+ } | {
659
+ ok: false;
660
+ err: string;
661
+ path?: string;
662
+ };
663
+ reloadModule(name: string): InstallOutcome;
429
664
  enableModuleSync(name: string): void;
430
665
  disableModuleSync(name: string): void;
431
666
  getModuleSync(name: string): boolean;
@@ -433,17 +668,17 @@ export declare class ScriptingAPI {
433
668
  getModulePriority(name: string): number;
434
669
  getModules(): string[];
435
670
  getModuleInfo(name: string): Record<string, unknown> | null;
436
- /** Mudlet `setModuleInfo(name, key, value)`. Stores a custom info field on a
437
- * module (visible via getModuleInfo). Always true. */
438
- setModuleInfo(name: string, key: string, value: string): boolean;
671
+ /** Mudlet `setModuleInfo(name, key, value)`. Stores a custom info field on an
672
+ * installed module (visible via getModuleInfo); the refusal, or null. */
673
+ setModuleInfo(name: string, key: string, value: string): string | null;
439
674
  getModulePath(name: string): string | null;
440
675
  /** Mudlet `getPackageInfo(name)`. Merged info table — the package manifest's
441
676
  * standard fields overlaid with anything set via setPackageInfo. Empty when
442
677
  * the package isn't installed and nothing was set. */
443
678
  getPackageInfo(name: string): Record<string, string>;
444
- /** Mudlet `setPackageInfo(name, key, value)`. Stores a custom info field on a
445
- * package (visible via getPackageInfo). Always true. */
446
- setPackageInfo(name: string, key: string, value: string): boolean;
679
+ /** Mudlet `setPackageInfo(name, key, value)`. Stores a custom info field on an
680
+ * installed package (visible via getPackageInfo); the refusal, or null. */
681
+ setPackageInfo(name: string, key: string, value: string): string | null;
447
682
  /**
448
683
  * Mudlet `setTriggerStayOpen(name, lines)`. Keeps the named trigger's chain
449
684
  * open for `lines` more lines of input for the current run only — it adjusts
@@ -483,37 +718,49 @@ export declare class ScriptingAPI {
483
718
  /** Hook for ProfileSession to close the active profile (return to the
484
719
  * connection screen). */
485
720
  setCloseProfileCallback(fn: (() => void) | null): void;
486
- /** Mudlet `closeMudlet()`. mudix maps it to closing the active profile:
487
- * disconnect, then return to the connection screen. */
721
+ /** Mudlet `closeMudlet()`. Mudlet Web maps it to closing the active profile:
722
+ * raise sysExitEvent, disconnect, then return to the connection screen.
723
+ * The event comes first because on desktop (TMainConsole::closeEvent) the
724
+ * exit handlers run while the profile is still connected, so a goodbye or
725
+ * save command they send reaches the game. The engine's teardown does not
726
+ * raise it a second time.
727
+ *
728
+ * None of that happens inside the call. Desktop's closeMudlet only arms the
729
+ * close (mudlet::armForceClose, a zero-delay single shot), so it returns
730
+ * and the rest of the calling script runs — and its sends go out — before
731
+ * the exit handlers do. A plain timeout rather than the timer queue, so a
732
+ * script pumping events in waitForEvent does not close underneath itself,
733
+ * which desktop's armForceClose also waits out. Calls made while a close
734
+ * is already armed fold into it. */
488
735
  closeMudlet(): void;
489
736
  /** Mudlet `resetProfile()` — reload the entire profile as if just opened:
490
737
  * clear every UI surface, recreate the Lua runtime, and re-run all scripts.
491
738
  * The actual work is deferred by the engine (it closes the Lua VM that is
492
- * currently executing this call), so this returns immediately. */
493
- resetProfile(): void;
739
+ * currently executing this call), so this returns immediately — true once
740
+ * the reset is armed, false when it was refused (Host::resetProfile_phase1). */
741
+ resetProfile(): boolean;
494
742
  /** Mudlet `exportAreaImage(areaID, filePath[, zLevel])` — render the area to a
495
743
  * PNG file in the profile VFS. Returns `[true, absolutePath]` on success or
496
744
  * `[false, errorMessage]` (e.g. the mapper isn't open, or the area is
497
745
  * unknown). The 0-indexed array is unpacked into Mudlet's multi-return by
498
746
  * Bridge.lua. */
499
- exportAreaImage(areaId: number, filePath: string, zLevel?: number): [boolean, string];
747
+ exportAreaImage(areaId: number, filePath: string, zLevel?: number | true): [boolean, string, boolean?];
500
748
  killByName(kind: 'timer' | 'alias' | 'trigger' | 'key', name: string): boolean;
501
749
  installPackage(path: string): InstallOutcome;
502
- uninstallPackage(name: string): boolean;
750
+ /** Lua `uninstallPackage(name)`: the refusal, or null once it is gone. */
751
+ uninstallPackage(name: string): string | null;
503
752
  enableScript(name: string): boolean;
504
753
  disableScript(name: string): boolean;
505
754
  enableTrigger(nameOrId: string | number): boolean;
506
755
  disableTrigger(nameOrId: string | number): boolean;
507
756
  enableTimer(name: string): boolean;
508
757
  disableTimer(name: string): boolean;
758
+ private toggleTimer;
509
759
  enableAlias(nameOrId: string | number): boolean;
510
760
  disableAlias(nameOrId: string | number): boolean;
511
761
  /** The saved keybinding carrying this numeric id, or null. Backs
512
762
  * getKeyCode() for a permanent key referenced by the id permKey returned. */
513
- keyNodeByNumericId(numericId: number): {
514
- key: string;
515
- modifiers: string[];
516
- } | null;
763
+ savedKeyNode(idOrName: number | string): KeyNode | null;
517
764
  enableKey(nameOrId: string | number): boolean;
518
765
  disableKey(nameOrId: string | number): boolean;
519
766
  /**
@@ -582,7 +829,7 @@ export declare class ScriptingAPI {
582
829
  * refuse it differently from "nothing matched". */
583
830
  isKnownItemType(type: string): boolean;
584
831
  /** Mudlet `getProfileStats()`. Per-family total/active counts (+ trigger
585
- * patterns). See ScriptingEngine.getProfileStats for mudix's caveats. */
832
+ * patterns). See ScriptingEngine.getProfileStats for Mudlet Web's caveats. */
586
833
  getProfileStats(): Record<string, unknown>;
587
834
  permScript(name: string, parent: string, code: string): number;
588
835
  permRegexTrigger(name: string, parent: string, regexes: string[], code: string): number;
@@ -621,7 +868,7 @@ export declare class ScriptingAPI {
621
868
  * name exists. */
622
869
  permAlias(name: string, parent: string, pattern: string, code: string): number;
623
870
  /** Mudlet `permTimer(name, parent, seconds, luaCode)`. Creates a
624
- * persistent one-shot timer under the parent group (empty = root).
871
+ * persistent repeating timer under the parent group (empty = root).
625
872
  * Returns the new timer id, or -1 when `parent` is non-empty but no
626
873
  * timer group of that name exists. */
627
874
  permTimer(name: string, parent: string, delay: number, code: string): number;
@@ -642,39 +889,52 @@ export declare class ScriptingAPI {
642
889
  * `source` is the caller's "script:line" captured by the Lua wrapper.
643
890
  */
644
891
  warnReservedTempKey(key: string, modifiers: string[], source?: string): void;
645
- /** Mudlet `tempButton(toolbarName, name, code [, orientation])`. Appends a
646
- * transient button under an existing toolbar group; returns the new id, or
647
- * -1 when the toolbar doesn't exist. `orientation` is Mudlet's int form
648
- * (0=horizontal/1=vertical) — accepted for compat, applied to the
649
- * button row inside the toolbar grid. */
650
- tempButton(toolbar: string, name: string, code: string, orientation: number): number;
651
- /** Mudlet `tempButtonToolbar(name [, orientation [, location]])`. Creates
652
- * a transient toolbar (ButtonNode group). `location` int: 0=top, 1=bottom,
653
- * 2=left, 3=right, 4=floating. Returns the new id or -1 on duplicate
654
- * name. */
892
+ /** Mudlet `tempButton(toolbarName, name, orientation)`. Appends a
893
+ * transient button, with no command or script, under an existing toolbar
894
+ * group; returns the new id, or -1 when the toolbar doesn't exist, -2
895
+ * when it is a plain button, -3 when the name is already taken (the Lua
896
+ * wrapper answers nil and desktop's message for each).
897
+ * `orientation` is Mudlet's int form (0=horizontal/1=vertical). */
898
+ tempButton(toolbar: string, name: string, orientation: number): number;
899
+ /** Mudlet `tempButtonToolbar(name, location, orientation)` core. Creates
900
+ * a transient toolbar (ButtonNode group). `location` is TAction's stored
901
+ * int — 0=top, 1=bottom, 2=left, 3=right, 4=floating — which Bridge.lua
902
+ * derives from the Lua argument. Returns the new id or -1 on duplicate
903
+ * name (the Lua wrapper answers nil and desktop's message then). */
655
904
  tempButtonToolbar(name: string, orientation: number, location: number): number;
656
905
  /** Mudlet `setButtonState(name, state)`. Sets the pressed state of a
657
906
  * two-state (push-down) button by name. Returns false when not found. */
658
- setButtonState(name: string, state: boolean): boolean;
907
+ setButtonState(name: string | number, state: boolean): boolean;
659
908
  /** Mudlet `getButtonState(name)`. Reads the pressed state of a two-state
660
909
  * button. Returns nil when not found. */
661
- getButtonState(name: string): boolean | null;
910
+ getButtonState(name: string | number): boolean | null;
911
+ /**
912
+ * The console's own button state, which no-argument `getButtonState()`
913
+ * reads: 2 when the last clicked button went down, 1 when it came up or
914
+ * was a plain button. Mudlet's TToolBar/TEasyButtonBar write
915
+ * `mpConsole->mButtonState` just before running the button, so it holds
916
+ * the click being handled — ScriptingEngine.executeButton does the same.
917
+ */
918
+ clickedButtonState: 1 | 2;
662
919
  /** Which of Mudlet's button refusals applies to `name` — see
663
920
  * ScriptingEngine.buttonKindByName. */
664
- buttonKind(name: string): 'missing' | 'plain' | 'pushdown';
921
+ buttonKind(name: string | number): 'missing' | 'plain' | 'pushdown';
665
922
  /** Mudlet `setButtonStyleSheet(name, css)`. Stores a CSS string on the
666
923
  * ButtonNode; the renderer applies it inline. Returns false when not
667
924
  * found. */
668
925
  setButtonStyleSheet(name: string, css: string): boolean;
669
926
  /** Mudlet `showToolBar(name)` / `hideToolBar(name)`. Toggles the toolbar's
670
927
  * effective enabled flag — the existing button bar already gates render
671
- * on `isEffectivelyEnabled`, so flipping the group's `enabled` field is
928
+ * on its toolbars being switched on, so flipping the group's `enabled` field is
672
929
  * the show/hide hook. Returns null on success, or why nothing moved. */
673
930
  setToolBarVisibility(name: string, show: boolean): string | null;
674
931
  setScript(name: string, code: string, pos: number): number;
675
932
  /** Removes the script with this numeric id. Backs permScript's rollback
676
933
  * when the new body raises as it is run. True when one was removed. */
677
934
  removeScriptById(id: number): boolean;
935
+ /** Why the body of the script with this numeric id failed when permScript
936
+ * or setScript just ran it, or null when it ran cleanly. */
937
+ scriptLoadError(id: number): string | null;
678
938
  /** Mudlet `getScript(name [, pos]) → code, id`. Returns the source of the
679
939
  * pos-th (1-indexed) script named `name` together with that script's own
680
940
  * numeric id. Null when no script sits at that position, which Bridge.lua
@@ -698,6 +958,45 @@ export declare class ScriptingAPI {
698
958
  */
699
959
  private injectOsc8Docs;
700
960
  echo(text: string): void;
961
+ /**
962
+ * Write `text` to the main console in the current pen, honouring the
963
+ * matched line. During trigger processing Mudlet's echo/cecho appends to
964
+ * the matched line at the output cursor (the line's end); only a `\n`
965
+ * advances to a fresh line. Mudlet Web seeds the matched line into
966
+ * mainConsole.history (beginLine) and defers script echoes, so without this
967
+ * every trigger echo opened a new line — breaking Arkadia's grade/value
968
+ * triggers, which `replace()`/`prefix()` then append text to the same line,
969
+ * and the "add a clickable link after the line" pattern `echoLink` and
970
+ * `echoPopup` are used for. The caller drains.
971
+ */
972
+ private echoMain;
973
+ /** Echo into `con` — through {@link echoMain} when it is the main console,
974
+ * so a link or popup echoed from a trigger lands on the matched line.
975
+ * `state`, when given, is written instead of the console's pen. */
976
+ private echoTo;
977
+ /**
978
+ * The format a link or popup gets when the caller did not ask for the
979
+ * current one — Mudlet's `standardLinkFormat`: the link blue, the console's
980
+ * own background and underline, and nothing else. It replaces the pen
981
+ * outright rather than layering onto it, so bold, italics, a background,
982
+ * strikeout or reverse set beforehand do not carry into the link (and a
983
+ * `cechoLink` with `<b>` inside stays one plain link run, since xEcho
984
+ * passes no format flag to the echoLink calls it makes).
985
+ */
986
+ private standardLinkState;
987
+ /**
988
+ * `TConsole::printCommand` on a miniconsole or user window: what Enter on
989
+ * its own command line (no action bound) prints into it after sending.
990
+ * Gated as desktop's enterCommand/printCommand gate it — never under
991
+ * `showSentText` "never", nor while the server echoes (password entry) —
992
+ * and drawn in that console's command colours, which start as
993
+ * TConsoleModel's (213,195,0) on black and setCommandForegroundColor /
994
+ * setCommandBackgroundColor with its name change.
995
+ */
996
+ printCommandToWindow(win: string, text: string): void;
997
+ /** Per-console command echo colours (TConsole::mCommandFgColor/BgColor),
998
+ * set by setCommandForegroundColor/BackgroundColor with a window name. */
999
+ private readonly windowCommandColors;
701
1000
  echoToWindow(win: string, text: string): void;
702
1001
  /**
703
1002
  * Native fast path for the color-echo family (`decho`/`cecho`/`hecho`).
@@ -714,7 +1013,12 @@ export declare class ScriptingAPI {
714
1013
  * line via a raw, non-ANSI insert the ANSI path can't reproduce),
715
1014
  * - any input the per-kind guard declines ({@link dechoToAnsiFast} /
716
1015
  * {@link cechoToAnsiFast} / {@link hechoToAnsiFast}) — style tags,
717
- * combined fg/bg, backgrounds, unknown color names, unmodeled tokens.
1016
+ * combined fg/bg, backgrounds, unknown color names, unmodeled tokens,
1017
+ * - an ESC anywhere in the text (Mudlet stores it as text; the ANSI this
1018
+ * builds would decode it).
1019
+ * The Lua wrapper also keeps a cecho off this path while any of its tags
1020
+ * names a `color_table` entry a script has changed (see LuaRuntime's
1021
+ * installFastColorEcho).
718
1022
  */
719
1023
  fastColorEcho(kind: string, win: string, str: string): boolean;
720
1024
  /**
@@ -726,11 +1030,24 @@ export declare class ScriptingAPI {
726
1030
  */
727
1031
  echoLink(text: string, cmd: string, tooltip: string, win?: string, useCurrentFormat?: boolean): void;
728
1032
  /**
729
- * Build a {@link FormatHyperlink} whose right-click handler opens a context
730
- * menu listing `cmds` (labelled by `hints`, falling back to the command
731
- * text). Shared by `echoPopup`/`insertPopup`/`setPopup` — those three differ
732
- * only in whether the styled span is appended, inserted at the cursor, or
733
- * applied to the current selection.
1033
+ * Build a {@link FormatHyperlink} for the popup family — shared by
1034
+ * `echoPopup`/`insertPopup`/`setPopup`, which differ only in whether the
1035
+ * styled span is appended, inserted at the cursor, or applied to the
1036
+ * current selection.
1037
+ *
1038
+ * Mudlet keeps links and popups in one link store and decides per click, so
1039
+ * a popup is a link that *also* carries a menu:
1040
+ * - Left-click runs `cmds[0]`, whatever the entry count. `TTextEdit::
1041
+ * mousePressEvent` has no popup branch at all — it executes the first
1042
+ * command of whichever link was hit.
1043
+ * - Right-click opens the menu only when there is more than one command,
1044
+ * or the hints list is longer than the commands list (a leading tooltip
1045
+ * hint marking the rest as menu items). A one-entry popup is therefore
1046
+ * indistinguishable from `echoLink`, which is what scripts calling
1047
+ * `cechoPopup(win, text, {code}, {label}, true)` rely on.
1048
+ * - Right-clicking a link never falls through to the console's own copy
1049
+ * menu (Mudlet sets `mIsCommandPopup` and returns), but that holds for
1050
+ * every link, so the renderer swallows it — see FormatBuffer.toDom.
734
1051
  */
735
1052
  private buildPopupHyperlink;
736
1053
  /**
@@ -744,7 +1061,7 @@ export declare class ScriptingAPI {
744
1061
  * the commands, each sending to the MUD.
745
1062
  * Used by ScriptingEngine when rendering MXP-parsed lines.
746
1063
  */
747
- createMxpHyperlink(kind: 'command' | 'url', payload: string, hint?: string, promptCmds?: string[], promptHints?: string[]): FormatHyperlink;
1064
+ createMxpHyperlink(kind: 'command' | 'url' | 'prompt', payload: string, hint?: string, promptCmds?: string[], promptHints?: string[], isLive?: () => boolean): FormatHyperlink;
748
1065
  /** Execute an OSC 8 link URI — a primary action or a menu item. The scheme
749
1066
  * decides the behaviour (send / prompt / open URL); anything else is a
750
1067
  * no-op (it was already rejected at parse time). */
@@ -774,10 +1091,21 @@ export declare class ScriptingAPI {
774
1091
  * backing buffer is available (empty console / sub-window without a buffer).
775
1092
  */
776
1093
  insertPopup(text: string, cmds: string[], hints: string[], win?: string, useCurrentFormat?: boolean): void;
1094
+ /**
1095
+ * The shared tail of insertLink/insertPopup — Mudlet routes both through
1096
+ * TConsoleModel::insertLink. When the cursor sits on TBuffer::getEndPos()
1097
+ * (the last character of the last line, or column 0 of an empty one) the
1098
+ * span is appended there instead, which is `appendAtEnd`, and the cursor
1099
+ * stays put. Otherwise it goes in at the cursor — padded out to it when the
1100
+ * cursor is past the end of the line — and, outside the trigger engine,
1101
+ * the cursor moves past it so a following insert lands after the link
1102
+ * rather than in front of it.
1103
+ */
1104
+ private insertLinkSpan;
777
1105
  /**
778
1106
  * Mudlet `setPopup([window,] {commands}, {hints})`. Attaches a right-click
779
1107
  * popup menu to the current selection — preserves the selection's existing
780
- * colors/attributes (like `setLink`, unlike the homogenizing color setters).
1108
+ * colors/attributes (like `setLink` and the colour setters).
781
1109
  * `commands` are Lua code strings run when the matching menu entry is
782
1110
  * chosen. Returns false when there is no selection (or it belongs to a
783
1111
  * different window).
@@ -808,8 +1136,8 @@ export declare class ScriptingAPI {
808
1136
  * the full pen state in one call. r1/g1/b1 is BACKGROUND, r2/g2/b2 is
809
1137
  * FOREGROUND (a Mudlet quirk — preserved here for parity). `blinkMode` is
810
1138
  * "none" / "slow" / "fast". Returns false when the named window doesn't
811
- * resolve. Mirrors setFgColor & friends: the pen is updated on the resolved
812
- * console AND applied to the current selection when one is active on it.
1139
+ * resolve. Unlike setFgColor & friends it touches the pen only — a
1140
+ * selection active on the console keeps its formatting, as in Mudlet.
813
1141
  */
814
1142
  setTextFormat(windowName: string | undefined, bg: {
815
1143
  r: number;
@@ -826,9 +1154,17 @@ export declare class ScriptingAPI {
826
1154
  selectString(str: string, occurrence: number, windowName?: string): number;
827
1155
  /**
828
1156
  * Mudlet `selectSection([window,] from, length) → bool`. `from` is 0-indexed.
829
- * Negative `from` is rejected (Mudlet behavior); zero/negative lengths
830
- * register a no-op selection but still report success in Mudlet — we match
831
- * that, but reject when the resolved buffer doesn't exist.
1157
+ *
1158
+ * A selection that does not fit the line is REFUSED, not trimmed to fit:
1159
+ * TConsole::selectSection rejects a negative start, a start past the end of
1160
+ * the line, and a length that runs off it, and leaves the previous selection
1161
+ * standing in each case. Clamping instead — which Mudlet Web did — turned
1162
+ * "selectSection(5, 1)" on a four-character line into a silent selection of
1163
+ * its last character, so a script checking the return value was told its
1164
+ * out-of-range request had succeeded and then styled the wrong text.
1165
+ *
1166
+ * `from == line length` is allowed: that is an empty selection at the end of
1167
+ * the line, not a start past it.
832
1168
  */
833
1169
  selectSection(from: number, length: number, windowName?: string): boolean;
834
1170
  /**
@@ -839,9 +1175,8 @@ export declare class ScriptingAPI {
839
1175
  */
840
1176
  selectCurrentLine(windowName?: string): boolean;
841
1177
  /**
842
- * Mudlet `deselect([windowName])`. With a window name, only clears the
843
- * selection if it belongs to that window — selections in other consoles
844
- * remain intact. Without an arg, clears unconditionally.
1178
+ * Mudlet `deselect([windowName])`. Clears the named console's selection
1179
+ * (main when omitted); selections in other consoles remain intact.
845
1180
  */
846
1181
  deselect(windowName?: string): void;
847
1182
  /**
@@ -855,11 +1190,11 @@ export declare class ScriptingAPI {
855
1190
  text: string;
856
1191
  start: number;
857
1192
  length: number;
858
- } | null;
1193
+ } | string | null;
859
1194
  /**
860
1195
  * Mudlet `getFgColor([window])` / `getBgColor([window])`. Reads the fg/bg
861
1196
  * color at the current selection's start position (Mudlet's P_begin). Each
862
- * console tracks its own selection in Mudlet; mudix has a single global
1197
+ * console tracks its own selection in Mudlet; Mudlet Web has a single global
863
1198
  * selection, so when `window` is given it must match the selection's
864
1199
  * owning window — otherwise we treat it as "no selection in that window"
865
1200
  * and return null (Mudlet's "no values" shape, surfaced as nil/nil/nil in
@@ -877,13 +1212,20 @@ export declare class ScriptingAPI {
877
1212
  * Mudlet `isAnsiFgColor(ansiColor)` / `isAnsiBgColor(ansiColor)`. True when
878
1213
  * the foreground/background color at the current selection's start equals
879
1214
  * ANSI/xterm color index `ansiColor` (0..7 normal, 8..15 bright, 16..255 the
880
- * xterm-256 palette). mudix stores rendered RGB rather than the original
1215
+ * xterm-256 palette). Mudlet Web stores rendered RGB rather than the original
881
1216
  * ANSI index, so the comparison is against the palette entry's RGB — exact
882
1217
  * for the 256 standard slots. Returns false when there's no selection (or it
883
1218
  * belongs to another window) or `ansiColor` is out of range.
884
1219
  */
885
1220
  isAnsiFgColor(ansiColor: number): boolean;
886
1221
  isAnsiBgColor(ansiColor: number): boolean;
1222
+ /**
1223
+ * Whether the main console's selection (or, with none, the cursor line's
1224
+ * first column) is on a character — what isAnsiFgColor/isAnsiBgColor read.
1225
+ * Desktop answers "current selection invalid in window 'main'" when it is
1226
+ * not, ahead of checking the colour number.
1227
+ */
1228
+ hasReadableSelection(): boolean;
887
1229
  private matchesAnsiColor;
888
1230
  /**
889
1231
  * The colour one of `isAnsiFgColor`/`isAnsiBgColor`'s 0..16 codes names.
@@ -896,6 +1238,18 @@ export declare class ScriptingAPI {
896
1238
  * only has to decline to answer.
897
1239
  */
898
1240
  private ansiColorCodeToRgb;
1241
+ /**
1242
+ * The colour Mudlet's getFgColor/getBgColor read: the one at P_begin, the
1243
+ * start of the selection.
1244
+ *
1245
+ * Mudlet has no "no selection" state — deselect() collapses P_begin and
1246
+ * P_end to (0, 0) rather than unsetting them, so the getters go on reading
1247
+ * the first column of the cursor's line. Mudlet Web models the selection as
1248
+ * absent instead, so that case is spelled out here: with nothing selected
1249
+ * the column is zero, and the answer is "nothing at all" only when there is
1250
+ * no character there to read — an empty console, or a line the selection
1251
+ * outlived.
1252
+ */
899
1253
  private readSelectionColor;
900
1254
  /**
901
1255
  * Resolve the rgb of `channel` for the character at `pos` in `buf`, falling
@@ -904,6 +1258,17 @@ export declare class ScriptingAPI {
904
1258
  * (selection or cursor).
905
1259
  */
906
1260
  private readColorAt;
1261
+ /** The colour the character at `pos` carries on `channel` itself (a
1262
+ * link's own style first), or undefined for the console's default. */
1263
+ private cellColorAt;
1264
+ /** The background setBackgroundColor gave a miniconsole or user window,
1265
+ * which its characters with no background of their own are drawn in —
1266
+ * desktop's TBuffer::updateColors() makes it their format's. */
1267
+ private consoleOwnBackground;
1268
+ /** The alpha of the background the character at `pos` is drawn on, as
1269
+ * getTextFormat's `backgroundAlpha` reports it: a decho alpha the
1270
+ * character carries, else its console's own translucent background. */
1271
+ private readBackgroundAlphaAt;
907
1272
  /** The blue a link gets in `windowName` when the caller did not pass a
908
1273
  * format of its own — whichever of Mudlet's two link blues reads better
909
1274
  * against that console's background. */
@@ -921,8 +1286,9 @@ export declare class ScriptingAPI {
921
1286
  *
922
1287
  * `foreground`/`background` resolve through the same logic as getFgColor /
923
1288
  * getBgColor (falling back to the profile defaults for unstyled segments).
924
- * `overline`, `concealed`, and `alternateFont` have no equivalent in mudix's
925
- * FormatState, so they report Mudlet's "off" values (false / 0) for parity.
1289
+ * `alternateFont` is recorded but never rendered — Mudlet Web has no alternate
1290
+ * font to switch to — so a script reads back the number the game asked for
1291
+ * and sees no difference on screen.
926
1292
  */
927
1293
  getTextFormat(windowName?: string): {
928
1294
  bold: boolean;
@@ -937,14 +1303,15 @@ export declare class ScriptingAPI {
937
1303
  blinking: 'none' | 'slow' | 'fast';
938
1304
  foreground: [number, number, number];
939
1305
  background: [number, number, number];
1306
+ backgroundAlpha: number;
940
1307
  } | null;
941
1308
  applyFormatToSelection(state: FormatStateSnapshot): void;
942
1309
  /**
943
1310
  * Mudlet `setLink([windowName], command, hint)`. Applies a clickable
944
1311
  * hyperlink to the current selection — preserves existing colors/attributes
945
- * on each segment (unlike setFgColor & friends which homogenize). `command`
1312
+ * on each segment (as setFgColor & friends do). `command`
946
1313
  * is the Lua code run on click; the Bridge.lua wrapper converts function
947
- * arguments into a `__mudix_call_link(id)` string before reaching here.
1314
+ * arguments into a `__mudlet_call_link(id)` string before reaching here.
948
1315
  * Returns false if there is no selection (or it doesn't belong to `win`).
949
1316
  */
950
1317
  setLink(cmd: string, tooltip: string, win?: string): boolean;
@@ -964,13 +1331,28 @@ export declare class ScriptingAPI {
964
1331
  * flushDeferredEcho() is called.
965
1332
  */
966
1333
  endLine(): void;
1334
+ /** Where the line the innermost trigger pass is running on is now, or -1
1335
+ * outside a pass (or once a trigger deleted it). Followed by the line
1336
+ * itself, as desktop's pass line number is kept up to date across a
1337
+ * deletion or a wrap above it. */
1338
+ private passLineIndex;
1339
+ /**
1340
+ * Run `fn` with the cursor on the line the trigger pass is processing, and
1341
+ * put the script's cursor back after. A trigger's own highlight paints the
1342
+ * line being processed wherever the scripts before it left the cursor
1343
+ * (TTrigger works on the engine's position, not the user cursor) — after
1344
+ * one deleted a line above, say, which moves the pass line up.
1345
+ */
1346
+ onPassLine(fn: () => void): void;
1347
+ /** The lines a network line is stored as once its triggers are done — see
1348
+ * Console.wrapAppendedLine. */
1349
+ wrapNetworkLine(buffer: AnsiAwareBuffer): AnsiAwareBuffer[];
967
1350
  /**
968
1351
  * Mudlet `tempColorTrigger(fg, bg)` colour-scan helper. Walks the
969
1352
  * just-appended line buffer (the one beginLine() seeded mainConsole with)
970
- * and returns true if any segment carries the requested ANSI palette
971
- * indices. `wantFg`/`wantBg` accept -1 as "any colour"; non-indexed
972
- * (RGB) segments never match a positive index, matching Mudlet's
973
- * palette-only semantics.
1353
+ * and returns true if any segment carries the requested ANSI colours.
1354
+ * `wantFg`/`wantBg` accept -1 as "any colour" and -2 as the console's
1355
+ * default; anything else is compared by the RGB it names, as desktop does.
974
1356
  */
975
1357
  currentLineMatchesColor(wantFg: number, wantBg: number, window?: {
976
1358
  start: number;
@@ -981,22 +1363,66 @@ export declare class ScriptingAPI {
981
1363
  * colours, or null when none does. A colour trigger reports that run as
982
1364
  * `matches[1]` — Mudlet matches a contiguous same-coloured run, not the
983
1365
  * whole line — so adjacent segments sharing the colours are joined.
1366
+ */
1367
+ currentLineColorMatch(wantFg: number, wantBg: number, window?: {
1368
+ start: number;
1369
+ length: number;
1370
+ } | null): string | null;
1371
+ /**
1372
+ * Every run on the current line carrying the wanted ANSI colours, in order,
1373
+ * with its offset in the line — at most `limit` of them. A filter parent
1374
+ * matching a colour hands each run to its children separately, as
1375
+ * TTrigger::match_color_pattern collects them all.
984
1376
  *
985
1377
  * Reads the snapshot beginLine took, not the live buffer: an earlier trigger
986
1378
  * may already have recoloured the line, and Mudlet still matches against the
987
1379
  * colours the server sent.
988
1380
  */
989
- currentLineColorMatch(wantFg: number, wantBg: number, window?: {
1381
+ currentLineColorRuns(wantFg: number, wantBg: number, window?: {
990
1382
  start: number;
991
1383
  length: number;
992
- } | null): string | null;
993
- /** Per-segment ANSI palette indices (and text) of each line currently being
994
- * processed, as it arrived — see {@link beginLine}. {@link COLOR_DEFAULT}
995
- * marks a segment left on the console's default colour, which is what a
996
- * trigger asking for `-2` matches; {@link COLOR_UNPALETTED} marks an RGB
997
- * colour outside the palette, which matches nothing. A stack, because a
998
- * trigger can feedTriggers another line. */
1384
+ } | null, limit?: number): {
1385
+ text: string;
1386
+ start: number;
1387
+ }[];
1388
+ /** Per-segment colours (as {@link RgbKey}s) and text of each line currently
1389
+ * being processed, as it arrived — see {@link beginLine}. A segment left
1390
+ * on the console's default colour holds the default's RGB, as a desktop
1391
+ * TChar does. A stack, because a trigger can feedTriggers another line. */
999
1392
  private lineColorSnapshots;
1393
+ /** The live buffer of each line in {@link lineColorSnapshots}, read for
1394
+ * whatever has been written past the snapshot's end. */
1395
+ private lineColorLive;
1396
+ /** `buffer`'s segments from character `from` on, as colour keys. */
1397
+ private colorKeySegments;
1398
+ /** The console's default foreground/background as {@link RgbKey}s — what
1399
+ * uncoloured text is drawn in, and what a `-2` pattern asks for. */
1400
+ private triggerDefaultColorKeys;
1401
+ /**
1402
+ * Keep the colour snapshot aligned with a line a trigger has just edited.
1403
+ *
1404
+ * The snapshot is of the colours the SERVER sent, and a trigger that
1405
+ * merely RECOLOURS the line must not disturb it — that is the whole point
1406
+ * of taking one. But inserting or deleting characters moves the runs: the
1407
+ * text after an insert is at a different offset than it was, and a colour
1408
+ * trigger reading stale offsets matches across the seam. In the spec's
1409
+ * words, red "CCCC" with its first two characters deleted has to match as
1410
+ * "CC" and not as "CCDD", which is what taking four red characters from the
1411
+ * shifted line gives.
1412
+ *
1413
+ * Done per character and re-joined rather than by walking segment
1414
+ * boundaries, because an edit lands wherever it lands — mid-run as often as
1415
+ * not — and a line is short enough that the simple version is the one worth
1416
+ * having.
1417
+ */
1418
+ /** The snapshot's colours at a character offset — what a `keepColor`
1419
+ * replacement inherits. Defaults to the reset pair when the line is
1420
+ * shorter than the offset. */
1421
+ private snapshotColorAt;
1422
+ /** A pen state's colours as {@link RgbKey}s, unset channels resolved to
1423
+ * the console's defaults. */
1424
+ private stateColorKeys;
1425
+ private spliceLineColorSnapshot;
1000
1426
  /** Whether each line currently being processed arrived as a prompt — the
1001
1427
  * fallback isPrompt() reads once a trigger has gagged the line itself. A
1002
1428
  * stack for the same reason {@link lineColorSnapshots} is one. */
@@ -1004,14 +1430,62 @@ export declare class ScriptingAPI {
1004
1430
  /** How many lines are being processed at once — more than one whenever a
1005
1431
  * trigger calls feedTriggers. See beginLine/endLine. */
1006
1432
  private triggerLineDepth;
1433
+ /** TriggerUnit::scmMaxProcessingDepth — see {@link feedTriggers}. */
1434
+ private static readonly MAX_TRIGGER_DEPTH;
1435
+ /** Set when a feed chain hits {@link MAX_TRIGGER_DEPTH}, until it unwinds to the outermost pass. */
1436
+ private runawayFeedStopped;
1437
+ /** Main-console lines the trigger pass's own echoes have completed. Mudlet's
1438
+ * TConsole::echo embeds a trigger echo's newlines in the line being
1439
+ * processed rather than opening lines, so the line count leaves them out
1440
+ * until the pass is over. See {@link getLineCount}. */
1441
+ private triggerEchoLines;
1442
+ /** The main console's last line when the outermost trigger pass began.
1443
+ * The view is not moved on until the pass is over (desktop finalises the
1444
+ * main console only at depth 0), so getScroll() reports no further than
1445
+ * this while it runs, however many lines a trigger feeds in meanwhile. */
1446
+ private passStartLastLine;
1007
1447
  /** Per nested line, the line the outer pass was on. See beginLine. */
1008
1448
  private outerTriggerLines;
1009
1449
  /** Told when text is inserted into the line a trigger is matching, so the
1010
1450
  * runtime can move the capture positions it recorded at match time —
1011
1451
  * otherwise `selectCaptureGroup` after an `insertText` selects the text
1012
- * that has since slid to where the capture used to be. */
1452
+ * that has since slid to where the capture used to be. `replaced` is the
1453
+ * length a `replace` took out at `at`, absent for an insert. */
1013
1454
  private captureShiftHook;
1014
- setCaptureShiftHook(fn: ((at: number, delta: number) => void) | null): void;
1455
+ setCaptureShiftHook(fn: ((at: number, delta: number, replaced?: number) => void) | null): void;
1456
+ /**
1457
+ * What triggers have done to the text of each line being processed, in
1458
+ * the order they did it and each in the columns the line had at the time
1459
+ * (TBuffer::mTriggerPassLineEdits). A stack parallel to
1460
+ * {@link lineColorLive}, as a trigger may feed a line of its own.
1461
+ *
1462
+ * Every trigger matches the line as it ARRIVED, so a later trigger's capture
1463
+ * positions are in the arrived columns; {@link passSpanNow} moves them past
1464
+ * what earlier triggers inserted, deleted or replaced before they are
1465
+ * highlighted, selected or replaced.
1466
+ */
1467
+ private passLineEdits;
1468
+ /**
1469
+ * Record an edit to `buf`'s text against every pass running on that line
1470
+ * (TBuffer::noteTriggerPassLineEdit). A removal followed by an insertion at
1471
+ * the same column is one replacement, so a column inside the removed text
1472
+ * is not pushed past what went in its place (appendTriggerPassLineEdit).
1473
+ */
1474
+ private noteTriggerPassLineEdit;
1475
+ /**
1476
+ * Where a stretch of the innermost pass line, given in the columns the line
1477
+ * arrived with, is now (TBuffer::triggerPassSpanNow). Text replacing part of
1478
+ * the stretch counts as part of it; text put in at either end does not.
1479
+ */
1480
+ passSpanNow(span: {
1481
+ start: number;
1482
+ length: number;
1483
+ }): {
1484
+ start: number;
1485
+ length: number;
1486
+ };
1487
+ /** Whether text triggers earlier in the innermost pass edited its line. */
1488
+ passLineEdited(): boolean;
1015
1489
  /**
1016
1490
  * Flush echo output collected during the just-processed line's trigger run.
1017
1491
  * Called once per line (right after that line is rendered) so a trigger's
@@ -1026,15 +1500,37 @@ export declare class ScriptingAPI {
1026
1500
  */
1027
1501
  flushDeferredEcho(): void;
1028
1502
  /** Raw tail of the last {@link feedTriggers} call that had no trailing
1029
- * newline, carried into the next one — see there. */
1030
- private feedTriggersRemainder;
1031
- /**
1032
- * Feed `text` through the trigger pipeline as if it arrived from the MUD.
1503
+ * newline, held until later data completes it — see feedTriggersText. */
1504
+ private heldFeedText;
1505
+ /** Hand over the held unterminated fed text, for the next batch to lead
1506
+ * with. The server's next lines complete it as well as a later feed does:
1507
+ * Mudlet runs both through the one TBuffer. */
1508
+ takeHeldFeedText(): string;
1509
+ /**
1510
+ * Feed bytes through the trigger pipeline as if they arrived from the MUD.
1033
1511
  * Routes complete lines through ScriptingEngine.processFlushBatch (same
1034
1512
  * code path as network-driven flushLines) so trigger ordering, ANSI carry,
1035
1513
  * and deferred-echo placement match exactly.
1514
+ *
1515
+ * `data` is a byte-string (the Lua binding unarmors it — see byteArmor.ts).
1516
+ * `utf8Encoded` says how to read it, and it is the caller's promise rather
1517
+ * than a guess:
1518
+ *
1519
+ * - true (the default) — the bytes are UTF-8. Mudlet transcodes them into
1520
+ * the game's encoding before display, so text the encoding cannot carry
1521
+ * is REFUSED rather than mangled: a script feeding an accented character
1522
+ * to an ASCII game has made a mistake it needs to hear about, and the
1523
+ * transcode is lossless otherwise, so refusing costs nothing real.
1524
+ * - false — the older form, where the caller has already encoded the bytes
1525
+ * themselves. They pass through untouched, decoded with the game's own
1526
+ * encoding rather than read as UTF-8 and double-encoded.
1527
+ *
1528
+ * Returns null when the text was fed, or the refusal message; the binding
1529
+ * shapes that into Mudlet's `true` / `(nil, errMsg)`.
1036
1530
  */
1037
- feedTriggers(text: string): boolean;
1531
+ feedTriggers(data: string, utf8Encoded?: boolean): string | null;
1532
+ /** The feed itself, once {@link feedTriggers} has settled what the bytes say. */
1533
+ private feedTriggersText;
1038
1534
  /**
1039
1535
  * Mudlet `getCurrentLine([window])`. Returns the text on the cursor's
1040
1536
  * current line, or `null` when the named window doesn't exist — the Lua
@@ -1045,6 +1541,11 @@ export declare class ScriptingAPI {
1045
1541
  getLineNumber(windowName?: string): number;
1046
1542
  getLineCount(windowName?: string): number;
1047
1543
  getLastLineNumber(windowName?: string): number;
1544
+ /** Whether a trigger pass is under way (TriggerUnit::processingDepth). */
1545
+ get triggerPassActive(): boolean;
1546
+ /** Whether `con` is the main console mid trigger pass — the one time it has
1547
+ * no open line past the last complete one. */
1548
+ private inTriggerPass;
1048
1549
  disableScrollBar(windowName?: string): void;
1049
1550
  enableScrollBar(windowName?: string): void;
1050
1551
  disableHorizontalScrollBar(windowName?: string): void;
@@ -1061,26 +1562,42 @@ export declare class ScriptingAPI {
1061
1562
  * this console. True unless disableScrolling was called on it; the main
1062
1563
  * window is always scrollable. */
1063
1564
  scrollingActive(windowName?: string): boolean;
1064
- /** Mudlet getScroll — 0-indexed buffer line at the top of the viewport. In
1065
- * tail mode reports the last line (Mudlet's mCursorY behaviour at end). */
1565
+ /** Mudlet getScroll — the buffer line the console is scrolled to, which
1566
+ * desktop counts as the first line below the scrolled view (its bottom row
1567
+ * plus one), the same edge scrollTo(window, line) puts a line on.
1568
+ * Desktop answers `max(min(mCursorY, getLastLineNumber()), 0)`
1569
+ * (TMainConsole::getWindowScroll), so a console following its output
1570
+ * reports exactly getLastLineNumber() — the comparison scripts use to ask
1571
+ * "am I at the bottom?" — and never a line past it. */
1066
1572
  getScroll(windowName?: string): number;
1067
- /** Mudlet scrollTo. With no line (or a line past end), resume tail mode.
1068
- * Negative line counts back from the buffer end. */
1573
+ /** Mudlet scrollTo. With no line (or a line at or past the last one),
1574
+ * resume tail mode. Negative line counts back from the buffer end. False
1575
+ * only where desktop does nothing (scrolling disabled); Bridge.lua drops
1576
+ * the result either way, as desktop's scrollTo returns nothing. */
1069
1577
  scrollTo(windowName: string | undefined, lineNumber: number | undefined): boolean;
1070
- getLines(from: number, to: number, windowName?: string): string[];
1578
+ /** Whether the console follows its output (desktop's
1579
+ * `windowFollowsNewLines`), which scrollUp/scrollDown count from: while
1580
+ * a trigger runs, getScroll still answers the end as it was before the
1581
+ * packet, but a console at its end scrolls from the end it has now. */
1582
+ windowFollowsNewLines(windowName?: string): boolean;
1583
+ /** Null when the window doesn't exist — the binding answers Mudlet's
1584
+ * `(nil, errMsg)` then, not an empty table a `if not t` check can't see. */
1585
+ getLines(from: number, to: number, windowName?: string): string[] | null;
1071
1586
  /**
1072
1587
  * Mudlet `getTimestamp([window,] lineNumber)` — the wall-clock time the line
1073
- * entered the buffer, formatted "HH:MM:SS.mmm" (Mudlet's "hh:mm:ss.zzz").
1074
- * `lineNumber` is 1-based to match `getLines`; omit it for the current
1075
- * cursor line. Returns null when the window or line doesn't exist — the Lua
1588
+ * entered the buffer, formatted as Mudlet's "hh:mm:ss.zzz " (13 characters,
1589
+ * trailing space included), or "------------ " for a line wrapping continued. `lineNumber` counts
1590
+ * from 0 as getLineNumber() does, 0 itself refused (see
1591
+ * Console.getLineTimestamp); omit it for the current cursor line. Returns null when the window or line doesn't exist — the Lua
1076
1592
  * binding maps that to Mudlet's `(nil, errMsg)` shape.
1077
1593
  */
1078
1594
  getTimestamp(lineNumber?: number, windowName?: string): string | null;
1079
1595
  /**
1080
- * Mudlet `wrapLine([window,] lineNumber)`. Re-displays the line at
1081
- * `lineNumber` (0-indexed, like getLineNumber/getLineCount), re-interpreting
1082
- * its embedded `\n` and re-wrapping to the current width. Returns false when
1083
- * the window or line doesn't exist.
1596
+ * Mudlet `wrapLine([window,] lineNumber)`. Re-wraps the buffer from the line
1597
+ * at `lineNumber` (0-indexed, like getLineNumber/getLineCount) to its end,
1598
+ * re-interpreting embedded `\n` and splitting to the current width, as
1599
+ * TBuffer::wrapLine does. Returns false when the window or line doesn't
1600
+ * exist; the Lua binding returns nothing either way, as desktop does.
1084
1601
  */
1085
1602
  wrapLine(lineNumber: number, windowName?: string): boolean;
1086
1603
  /**
@@ -1129,21 +1646,33 @@ export declare class ScriptingAPI {
1129
1646
  */
1130
1647
  getRowCount(windowName?: string): number;
1131
1648
  /**
1132
- * Mudlet setWindowWrap(name, charsPerLine). Sets the visual wrap width
1133
- * (in monospace columns) for the named window or "main". 0 clears the
1134
- * setting. Returns false when the named window does not exist; main always
1135
- * succeeds (persisted on the active profile).
1649
+ * Mudlet setWindowWrap(name, charsPerLine). Sets the wrap width (in
1650
+ * monospace columns) for the named window, buffer or "main", and re-applies
1651
+ * it to the lines the console stores from then on. 0 clears the setting,
1652
+ * back to the default (100 for main, no wrap for a window); the Lua binding
1653
+ * refuses it as Mudlet does. Returns false when the named window does not
1654
+ * exist; main always succeeds (persisted on the active profile, as Mudlet
1655
+ * keeps it in Host::mWrapAt).
1136
1656
  */
1137
1657
  setWindowWrap(name: string, wrapAt: number): boolean;
1658
+ /** The main console's wrap width: the profile's `outputWrapAt`, which is
1659
+ * Mudlet's Host::mWrapAt (100 unless changed). 0 means the Settings UI
1660
+ * turned character wrapping off. */
1661
+ private mainWrapAt;
1662
+ /** `[wrapAt, indent, hangingIndent]` for a console, 0 meaning off. Main
1663
+ * reads the profile, an on-screen window its WindowManager entry, and a
1664
+ * createBuffer buffer the Console it lives in. */
1665
+ private wrapSettings;
1138
1666
  /** Tell the console the width to break stored lines at, so what `getLines`
1139
1667
  * reports matches what the window shows. Called whenever the wrap width or
1140
- * either indent moves. */
1668
+ * either indent moves, and for main when the API is created. */
1141
1669
  private applyStoredWrap;
1142
1670
  /**
1143
- * Mudlet `getWindowWrap(name) → cols`. Reports the visual wrap width set by
1144
- * setWindowWrap (0 when unset). For "main" reads the profile's stored
1145
- * override; for a named window reads the WindowManager hint. Returns -1 when
1146
- * the named window does not exist (Mudlet's invalid-window sentinel).
1671
+ * Mudlet `getWindowWrap(name) → cols` — TConsole::getWrapAt, the width the
1672
+ * console's buffer wraps at. Main defaults to 100 (Host::mWrapAt) and a
1673
+ * createBuffer buffer to main's width when it was made; a miniconsole or
1674
+ * user window no script has set reports TBuffer's own 99999999. Returns -1
1675
+ * when the named window does not exist (Mudlet's invalid-window sentinel).
1147
1676
  */
1148
1677
  getWindowWrap(name: string): number;
1149
1678
  /**
@@ -1160,7 +1689,7 @@ export declare class ScriptingAPI {
1160
1689
  setWindowWrapHangingIndent(name: string, indent: number): boolean;
1161
1690
  /**
1162
1691
  * Mudlet `setMapWindowTitle(title)`. Sets the dockable map panel's tab
1163
- * title; an empty string resets it to the default ("Map"). Returns false
1692
+ * title; an empty string resets it to the default ("Map - <profile>"). Returns false
1164
1693
  * when the map widget isn't open.
1165
1694
  */
1166
1695
  setMapWindowTitle(title: string): boolean;
@@ -1172,17 +1701,23 @@ export declare class ScriptingAPI {
1172
1701
  * when the cursor isn't on a valid line yet (empty buffer / sub-window
1173
1702
  * without a backing buffer).
1174
1703
  */
1175
- insertText(text: string, windowName?: string): void;
1704
+ insertText(text: string, windowName?: string): boolean;
1176
1705
  /**
1177
1706
  * Mudlet `insertLink([window,] text, cmd, hint, [useCurrentFormat])`.
1178
1707
  * Like `insertText` but the inserted span is a clickable link bound to
1179
- * `cmd`. With `useCurrentFormat=false` (the default) the link inherits
1180
- * Mudlet's built-in style — blue foreground + underline — layered on top
1181
- * of the current pen state. If no buffer is available (empty console,
1708
+ * `cmd`. With `useCurrentFormat=false` (the default) the link gets
1709
+ * Mudlet's standard link format — link blue + underline, nothing of the
1710
+ * current pen ({@link standardLinkState}). If no buffer is available (empty console,
1182
1711
  * sub-window without backing buffer) the call degrades to `echoLink` so
1183
1712
  * the text isn't lost.
1184
1713
  */
1185
1714
  insertLink(text: string, cmd: string, tooltip: string, windowName?: string, useCurrentFormat?: boolean): void;
1715
+ /**
1716
+ * The wrapLine() TConsole::insertText and insertLink run after an insert
1717
+ * that broke the line: what the newline left on each side of it is
1718
+ * wrapped to the console's width, from the line the insert began on.
1719
+ */
1720
+ private rewrapInserted;
1186
1721
  /**
1187
1722
  * Mudlet `moveCursorUp([window,] [lines=1,] [keepHorizontal=false]) → bool`.
1188
1723
  * `keepHorizontal=true` preserves the column across the vertical move; the
@@ -1224,7 +1759,9 @@ export declare class ScriptingAPI {
1224
1759
  * and `DOCK` tab groups. This just owns the manager and satisfies its host
1225
1760
  * interface below. `dest` is the `<DEST>` frame open when the tag was parsed.
1226
1761
  */
1227
- mxpFrame(name: string, attrs: Record<string, string>, dest?: string): void;
1762
+ /** Whether an MXP frame of this name is open for a `<DEST>` to write to. */
1763
+ mxpHasFrame(name: string): boolean;
1764
+ mxpFrame(name: string, attrs: Record<string, string>, dest?: string): boolean;
1228
1765
  /** Tear every MXP frame down. MXP frames are per-connection state in Mudlet
1229
1766
  * (TMxpFrameManager::resetAllFrames), so a reconnect starts from a clean
1230
1767
  * main window rather than inheriting the last session's layout. */
@@ -1235,7 +1772,7 @@ export declare class ScriptingAPI {
1235
1772
  * in the main window, matching Mudlet). `eof` clears the frame first — the
1236
1773
  * status-frame "replace contents" idiom.
1237
1774
  */
1238
- mxpWriteToFrame(name: string, buffer: AnsiAwareBuffer, eof: boolean): boolean;
1775
+ mxpWriteToFrame(name: string, buffer: AnsiAwareBuffer, eof: boolean, eol?: boolean): boolean;
1239
1776
  /** Frames that have been written with `<DEST … EOF>` at least once, i.e. the
1240
1777
  * server treats them as replace-contents panes. Learned rather than
1241
1778
  * declared: MXP has no attribute for it. */
@@ -1251,32 +1788,57 @@ export declare class ScriptingAPI {
1251
1788
  createBuffer(name: string): void;
1252
1789
  /** True when `name` is an off-screen buffer created via createBuffer. */
1253
1790
  isBuffer(name: string): boolean;
1791
+ /** showWindow / hideWindow on a buffer: desktop finds it and flips the
1792
+ * flag windowVisible reads back. False when `name` is no buffer. */
1793
+ setBufferVisible(name: string, visible: boolean): boolean;
1794
+ /** moveWindow on a buffer — kept for getWindowGeometry to report. */
1795
+ moveBuffer(name: string, x: number, y: number): boolean;
1796
+ /** resizeWindow on a buffer — kept for getWindowGeometry to report. */
1797
+ resizeBuffer(name: string, width: number, height: number): boolean;
1254
1798
  /**
1255
1799
  * Mudlet `copy([window])`. Copies the current selection of the resolved
1256
1800
  * console — including all formatting — into the session clipboard, a single
1257
1801
  * rich-text buffer shared with `paste`/`appendBuffer` (Mudlet's host-global
1258
- * mClipboard). No-op when there's no selection, or when `window` is given
1259
- * but doesn't own the active selection.
1260
- */
1261
- copy(windowName?: string): void;
1802
+ * mClipboard).
1803
+ *
1804
+ * Like Host::copyToClipboard it ALWAYS replaces the clipboard with the named
1805
+ * console's selection (main when omitted) — when that console has none
1806
+ * (after a failed selectString, a deselect(), or a selection that belongs to
1807
+ * another window) the clipboard becomes empty, and a following appendBuffer
1808
+ * appends an empty line. Keeping the previous clipboard instead re-appended
1809
+ * stale text. Only an unknown window leaves the clipboard alone (desktop
1810
+ * raises "window not found" there). TBuffer::copy resets a start outside
1811
+ * the line to column 0, which is reproduced too.
1812
+ */
1813
+ copy(windowName?: string): boolean;
1814
+ /** The Lua code of every scripted link the named console's lines hold, for
1815
+ * Bridge.lua to let go of the functions a clear takes off the screen. */
1816
+ consoleLinkCommands(win?: string): string[];
1817
+ /** Of the link `commands` given, the ones some console still shows. */
1818
+ linkCommandsShown(commands: string[]): string[];
1819
+ /** The Lua code of every scripted link in the clipboard, for Bridge.lua to
1820
+ * hold a reference of the clipboard's own to each function a link calls,
1821
+ * as TBuffer's copied TLinkStore does in desktop. */
1822
+ clipboardLinkCommands(): string[];
1262
1823
  /**
1263
1824
  * Mudlet `cut()`. `copy()` and then delete what was copied, so the clipboard
1264
1825
  * holds exactly the text the line lost (TConsole::cut → TBuffer::cut). Takes
1265
1826
  * no window argument in Mudlet — it always acts on the main console — and is
1266
1827
  * a no-op without a selection there.
1267
1828
  */
1268
- cut(): void;
1829
+ cut(windowName?: string): boolean;
1269
1830
  /**
1270
1831
  * Mudlet `appendBuffer([window])`. Appends the clipboard's rich text (from
1271
- * the last `copy()`) as a new line at the end of the named console's buffer.
1272
- * No-op until something has been copied. Mirrors TConsole::appendBuffer.
1832
+ * the last `copy()`) onto the end of the named console's last line, then
1833
+ * ends that line. No-op until something has been copied. Mirrors
1834
+ * TConsole::appendBuffer.
1273
1835
  */
1274
1836
  appendBuffer(windowName?: string): void;
1275
1837
  /**
1276
1838
  * Mudlet `paste([window])`. Inserts the clipboard at the cursor's current
1277
- * column when the cursor sits above the last line; otherwise appends it as
1278
- * a new line at the end (TConsole::paste semantics). No-op without a prior
1279
- * copy().
1839
+ * column when the cursor sits above the last line; otherwise writes it onto
1840
+ * the end of the last line and ends that line (Host::pasteClipboardInto).
1841
+ * No-op without a prior copy().
1280
1842
  */
1281
1843
  paste(windowName?: string): void;
1282
1844
  /**
@@ -1288,7 +1850,7 @@ export declare class ScriptingAPI {
1288
1850
  * MAPPER_WIDGET_ID) so a script or a MUD cannot name a window over them.
1289
1851
  * Both render the same MapStore and stay in sync. Returns true on success.
1290
1852
  */
1291
- createMapper(x: number, y: number, width: number, height: number, parent?: string): boolean;
1853
+ createMapper(x: number, y: number, width: number, height: number, parent?: string): true | string;
1292
1854
  /**
1293
1855
  * Mudlet `setWindow(windowName, name[, x, y, show])` — move an element
1294
1856
  * (label, overlay command line, text edit, scroll box, or a miniconsole /
@@ -1301,10 +1863,15 @@ export declare class ScriptingAPI {
1301
1863
  /**
1302
1864
  * Mudlet `getWindowGeometry(name)` → x, y, width, height. Reads back the
1303
1865
  * stored geometry the move/resizeWindow setters write, following the same
1304
- * routing precedence they use (labels → command lines → text edits →
1305
- * scroll boxes → user windows/miniconsoles). Null when no widget of any
1866
+ * routing precedence they use (labels → scroll boxes → command lines →
1867
+ * text edits → user windows/miniconsoles). Null when no widget of any
1306
1868
  * kind owns the name; `"main"` is deliberately excluded because
1307
1869
  * moveWindow/resizeWindow don't act on it either.
1870
+ *
1871
+ * The scroll box comes before the other overlays for the reason windowType
1872
+ * puts it there: one name can be a scroll box AND a text edit at once, and
1873
+ * every by-name lookup has to give the same answer as the last one until
1874
+ * the scroll box is deleted.
1308
1875
  */
1309
1876
  getWindowGeometry(name: string): {
1310
1877
  x: number;
@@ -1320,7 +1887,8 @@ export declare class ScriptingAPI {
1320
1887
  * visible. Null when the name belongs to no widget, or is `"main"`.
1321
1888
  */
1322
1889
  windowVisible(name: string): boolean | null;
1323
- /** A widget's own visible flag, ignoring ancestors. Null when unknown. */
1890
+ /** A widget's own visible flag, ignoring ancestors. Null when unknown. One
1891
+ * name worn by more than one overlay is the one windowType() names. */
1324
1892
  private ownVisibility;
1325
1893
  /** The name a widget is nested under, or null once the chain reaches a root. */
1326
1894
  private parentOf;
@@ -1330,7 +1898,10 @@ export declare class ScriptingAPI {
1330
1898
  * widget, which Mudlet reports as an error rather than an empty string.
1331
1899
  */
1332
1900
  getLabelText(name: string): string | null;
1333
- setWindow(windowName: string, name: string, x?: number, y?: number, show?: boolean): boolean;
1901
+ /** A move that would make a parent cycle answers desktop's refusal message
1902
+ * (TMainConsole::reparentWindow) rather than false, for Bridge.lua to
1903
+ * return as (nil, message). */
1904
+ setWindow(windowName: string, name: string, x?: number, y?: number, show?: boolean): boolean | string;
1334
1905
  /**
1335
1906
  * Mudlet `replace([win,] with, [keepcolor])`. Default (`keepcolor=false`)
1336
1907
  * applies the resolved console's current pen state (set via
@@ -1347,11 +1918,15 @@ export declare class ScriptingAPI {
1347
1918
  */
1348
1919
  deleteLine(windowName?: string): void;
1349
1920
  appendCmdLine(text: string): void;
1350
- printCmdLine(text: string): void;
1921
+ /** Mudlet printCmdLine, which leaves the caret at the end with nothing
1922
+ * selected (TMainConsole's putTextOnCommandLine); `selectAll` is
1923
+ * sendCmdLine's setCommandLineText, which selects what it put there — the
1924
+ * form a link PROMPT takes on desktop too. */
1925
+ printCmdLine(text: string, selectAll?: boolean): void;
1351
1926
  clearCmdLine(): void;
1352
1927
  /**
1353
1928
  * Mudlet selectCmdLineText([commandLine]). Selects (highlights) all text in
1354
- * the command bar so the next keystroke overtypes it. mudix has a single
1929
+ * the command bar so the next keystroke overtypes it. Mudlet Web has a single
1355
1930
  * main command bar; a named overlay command-line arg is accepted for
1356
1931
  * compatibility but only "main"/omitted is acted upon. The actual DOM
1357
1932
  * selection happens in ProfileSession, which owns the input ref.
@@ -1359,34 +1934,78 @@ export declare class ScriptingAPI {
1359
1934
  selectCmdLineText(name?: string): void;
1360
1935
  /**
1361
1936
  * Mudlet setCommandBackgroundColor([windowName], r, g, b, [transparency]).
1362
- * Recolors the command bar's background. mudix only has the main command
1937
+ * Recolors the command bar's background and the echoed commands
1938
+ * (Host::mCommandBgColor). Mudlet Web only has the main command
1363
1939
  * bar, so a non-"main" windowName is ignored. `a` is Mudlet's 0..255 alpha;
1364
1940
  * the CommandBar reads the `inputBackground` profile field as a CSS color.
1365
1941
  */
1366
1942
  setCommandBackgroundColor(r: number, g: number, b: number, a?: number, name?: string): boolean;
1367
- /** Mudlet setCommandForegroundColor — recolors the command bar text. */
1943
+ /** Mudlet setCommandForegroundColor — recolors the command bar text and
1944
+ * the echoed commands (Host::mCommandFgColor). */
1368
1945
  setCommandForegroundColor(r: number, g: number, b: number, a?: number, name?: string): boolean;
1369
1946
  private cmdLineValue;
1370
1947
  private cmdLineProvider;
1371
1948
  /** Registered by ProfileSession while a command bar is mounted; read only
1372
1949
  * before the first {@link setCmdLineValue} has mirrored anything. */
1373
1950
  setCmdLineProvider(fn: (() => string) | null): void;
1374
- /** Mirror a command-bar edit (user typing, history recall, submit-clear). */
1951
+ /** Mirror a command-bar edit (user typing, history recall, submit-clear).
1952
+ * While the game asks for hidden input the bar is the hidden-input box,
1953
+ * whose text — a password — is no command line's to read. */
1375
1954
  setCmdLineValue(text: string): void;
1376
1955
  getCmdLine(): string;
1956
+ /**
1957
+ * What the main command line holds while the game asks for hidden input
1958
+ * (it has taken the ECHO option), or null when it is not asking. Desktop
1959
+ * lays a separate hidden-input box over the command line for the password:
1960
+ * the command line keeps what was in it — getCmdLine reads that — and what
1961
+ * printCmdLine writes, or the player types, goes into the box, never to be
1962
+ * read back. Mudlet Web draws the box in the command bar itself
1963
+ * (ProfileSession puts the command aside and brings it back), so the
1964
+ * command line is kept here for scripts.
1965
+ */
1966
+ private hiddenInputCommand;
1967
+ beginHiddenInput(command: string): void;
1968
+ endHiddenInput(): void;
1377
1969
  private cmdLineSuggestions;
1378
- addCmdLineSuggestion(suggestion: string): void;
1379
- removeCmdLineSuggestion(suggestion: string): void;
1380
- clearCmdLineSuggestions(): void;
1381
- getCmdLineSuggestions(): string[];
1382
- private emitCmdLineSuggestions;
1383
1970
  private cmdLineBlacklist;
1384
- addCmdLineBlacklist(word: string): void;
1385
- removeCmdLineBlacklist(word: string): void;
1386
- clearCmdLineBlacklist(): void;
1387
- getCmdLineBlacklist(): string[];
1971
+ private completionList;
1972
+ addCmdLineSuggestion(suggestion: string, cmdLine?: string): void;
1973
+ removeCmdLineSuggestion(suggestion: string, cmdLine?: string): void;
1974
+ clearCmdLineSuggestions(cmdLine?: string): void;
1975
+ getCmdLineSuggestions(cmdLine?: string): string[];
1976
+ private emitCmdLineSuggestions;
1977
+ addCmdLineBlacklist(word: string, cmdLine?: string): void;
1978
+ removeCmdLineBlacklist(word: string, cmdLine?: string): void;
1979
+ clearCmdLineBlacklist(cmdLine?: string): void;
1980
+ getCmdLineBlacklist(cmdLine?: string): string[];
1388
1981
  private emitCmdLineBlacklist;
1982
+ /** A deleted command line takes its lists with it; one made later under
1983
+ * the same name starts empty, as a new TCommandLine does. */
1984
+ forgetCmdLineCompletion(cmdLine: string): void;
1985
+ /** The Tab-completion pool for command line `cmdLine` as it stands now:
1986
+ * the main console's last 500 lines, then the line's suggestions, less
1987
+ * its blacklist — what TCommandLine::handleTabCompletion assembles on
1988
+ * every press. Every command line reads the MAIN console's buffer. */
1989
+ cmdLineCompletionWords(cmdLine?: string): string[];
1389
1990
  private saveCommandHistoryFlags;
1991
+ /** Which file each command line's history is kept in. Assigned on creation
1992
+ * and never reused, because two command lines sharing one file would
1993
+ * overwrite each other's history on the next save. */
1994
+ private readonly cmdLineHistoryFiles;
1995
+ private nextHistoryFile;
1996
+ /** Register a command line's history file, returning its name. */
1997
+ noteCommandLineForIni(cmdLineName: string): string;
1998
+ forgetCommandLineForIni(cmdLineName: string): void;
1999
+ /**
2000
+ * The profile's `profile.ini`, in the shape QSettings writes it.
2001
+ *
2002
+ * Mudlet keeps this file open and lets QSettings flush it on the next pass
2003
+ * through the event loop, so what a command line records reaches the disk
2004
+ * without anyone asking for a save. Two things live under [CommandLines]:
2005
+ * which file each one's history goes in, written when it is created, and
2006
+ * whether it saves history at all, written with the end-of-session save.
2007
+ */
2008
+ profileIniContent(): string;
1390
2009
  saveCommandHistoryFor(cmdLineName: string): boolean;
1391
2010
  setSaveCommandHistoryFor(cmdLineName: string, save: boolean): void;
1392
2011
  /**
@@ -1400,7 +2019,7 @@ export declare class ScriptingAPI {
1400
2019
  * the profile-wide save size. Both switches have to be on: the size, and the
1401
2020
  * command line's own flag.
1402
2021
  *
1403
- * Only the main bar has a history to write. mudix's Geyser command lines
2022
+ * Only the main bar has a history to write. Mudlet Web's Geyser command lines
1404
2023
  * keep none, so unlike Mudlet there are no numbered files beside it — the
1405
2024
  * shape is here rather than a bare `saveMainHistory()` so that one gaining a
1406
2025
  * history is a change in this function alone.
@@ -1436,11 +2055,11 @@ export declare class ScriptingAPI {
1436
2055
  /**
1437
2056
  * Get (or create) a `<style>` tag in `document.head` owned by this profile.
1438
2057
  *
1439
- * Every tag mudix installs on a script's behalf is stamped with the owning
1440
- * connection id, both in its element id and in `data-mudix-style-owner`, so
2058
+ * Every tag Mudlet Web installs on a script's behalf is stamped with the owning
2059
+ * connection id, both in its element id and in `data-mudlet-style-owner`, so
1441
2060
  * {@link destroy} can take them all down again. Mudlet's `setAppStyleSheet`
1442
2061
  * is genuinely application-wide (a QApplication stylesheet shared by every
1443
- * open profile), but a mudix tab hosts one profile at a time: leaving a
2062
+ * open profile), but a Mudlet Web tab hosts one profile at a time: leaving a
1444
2063
  * closed profile's CSS installed silently restyled the *next* profile opened
1445
2064
  * in that tab. So all three setters — app, profile and per-window — are
1446
2065
  * profile-local here, and torn down with the profile.
@@ -1450,14 +2069,28 @@ export declare class ScriptingAPI {
1450
2069
  private removeOwnedStyleTags;
1451
2070
  setAppStyleSheet(css: string, tag?: string): boolean;
1452
2071
  setUserWindowStyleSheet(name: string, css: string): boolean;
1453
- /** Mudlet `getUserWindowStyleSheet(name)` — the QSS as it was set. */
2072
+ /** Mudlet `getUserWindowStyleSheet(name)` — the QSS as it was set: the
2073
+ * window's own, or else the profile's, which desktop sets on every dock. */
1454
2074
  getUserWindowStyleSheet(name: string): string;
2075
+ /** A user window was just made (not re-shown): it starts with the profile
2076
+ * stylesheet, not with whatever an earlier window of its name was given. */
2077
+ noteUserWindowOpened(name: string): void;
2078
+ /** Drop a user window's own stylesheet, and the `<style>` tag carrying it. */
2079
+ private forgetUserWindowStyleSheet;
1455
2080
  private readonly userWindowCss;
2081
+ /** What setProfileStyleSheet was last given. */
2082
+ private profileCss;
1456
2083
  /** Mudlet `getCmdLineStyleSheet([name])`. Same story as above: the command
1457
2084
  * line's authored QSS, not the CSS the overlay ends up with. "main" is the
1458
2085
  * default and has no widget of its own to read back from. */
1459
2086
  getCmdLineStyleSheet(name: string): string;
2087
+ /** The stylesheet a sub command line is created with — the profile's command
2088
+ * line background, in the shape Mudlet's TCommandLine builds. */
2089
+ bornCmdLineStyleSheet(): string;
1460
2090
  noteCmdLineStyleSheet(name: string, css: string): void;
2091
+ /** Whether a command line's stylesheet has been recorded at all — born or
2092
+ * set — as opposed to recorded as "". */
2093
+ hasCmdLineStyleSheet(name: string): boolean;
1461
2094
  private readonly cmdLineCss;
1462
2095
  /**
1463
2096
  * Mudlet `setProfileStyleSheet(stylesheet)`. Installs (or replaces) a
@@ -1468,7 +2101,7 @@ export declare class ScriptingAPI {
1468
2101
  *
1469
2102
  * Deliberately raises NO sysAppStyleSheetChange: that event announces an
1470
2103
  * *application*-level change, and a profile sheet is not one. Raising it
1471
- * here (as mudix used to) told every profile-agnostic theme handler to
2104
+ * here (as Mudlet Web used to) told every profile-agnostic theme handler to
1472
2105
  * re-apply itself over a change that was never theirs.
1473
2106
  */
1474
2107
  setProfileStyleSheet(css: string): boolean;
@@ -1487,7 +2120,7 @@ export declare class ScriptingAPI {
1487
2120
  * and return the current mirror synchronously, matching Mudlet's signature.
1488
2121
  */
1489
2122
  getClipboardText(): string;
1490
- centerView(roomId: number): boolean;
2123
+ centerView(roomId: number, viewId?: number): boolean | string;
1491
2124
  /** Mudlet `createMapView([areaID])` → the new view id, or the refusal
1492
2125
  * message when the areaID names no area. */
1493
2126
  createMapView(areaId: number): number | string;
@@ -1508,20 +2141,20 @@ export declare class ScriptingAPI {
1508
2141
  /**
1509
2142
  * Mudlet `getMapZoom([areaID])` — the number of map units visible across the
1510
2143
  * viewport's shorter edge. Mudlet keeps this on the area (TArea's
1511
- * `mLast2DMapZoom`, reached via TRoomDB::get2DMapZoom), so it answers with
1512
- * no mapper mounted and each area remembers its own; mudix stores it the
1513
- * same way. Without an areaID the live renderer's current zoom wins when one
2144
+ * `mLast2DMapZoom`, reached via TRoomDB::get2DMapZoom), so each area
2145
+ * remembers its own; Mudlet Web stores it the same way. Desktop still refuses
2146
+ * the call until a mapper exists ("no active mapper"), whichever area is asked. Without an areaID the live renderer's current zoom wins when one
1514
2147
  * is mounted. Undefined for an areaID that doesn't exist — the binding
1515
2148
  * reports that as `(nil, errMsg)`.
1516
2149
  */
1517
- getMapZoom(areaID?: number): number | undefined;
2150
+ getMapZoom(areaID?: number, viewId?: number): number | undefined | string;
1518
2151
  /**
1519
2152
  * Mudlet `setMapZoom(zoom [, areaID])`. Like Mudlet the zoom must be at
1520
2153
  * least 3.0, and an areaID that doesn't exist is refused. Stored on the area
1521
2154
  * and pushed to the live renderer when one is mounted. Returns the refusal
1522
2155
  * message, or null on success, for the binding to shape.
1523
2156
  */
1524
- setMapZoom(zoom: number, areaID?: number): string | null;
2157
+ setMapZoom(zoom: number, areaID?: number, viewId?: number): string | null;
1525
2158
  /** The area the 2D view is showing — the player's room's area, falling back
1526
2159
  * to the default area when there is no player room yet. */
1527
2160
  private currentMapArea;
@@ -1570,7 +2203,7 @@ export declare class ScriptingAPI {
1570
2203
  * this method only deals in already-decoded bytes. Returns true unless the
1571
2204
  * panel reported a parse failure for the given buffer.
1572
2205
  */
1573
- loadMap(buf?: Uint8Array): boolean;
2206
+ loadMap(buf?: Uint8Array, source?: string): boolean;
1574
2207
  /**
1575
2208
  * Mudlet `saveMap([location])`. Serialises the current MapStore to the
1576
2209
  * Mudlet binary `.dat` format and persists it to the connection's default
@@ -1586,11 +2219,20 @@ export declare class ScriptingAPI {
1586
2219
  loadMapXml(xmlText: string): boolean;
1587
2220
  /** Mudlet `saveJsonMap(path)` backbone — serialises the current MapStore
1588
2221
  * as JSON. The Lua binding writes the result to the supplied VFS path. */
2222
+ /** The map as Mudlet's JSON, carrying the map-level settings that live in
2223
+ * the profile rather than in the map store — Mudlet writes them into the
2224
+ * same file, so a map moved between clients keeps the way it looks. */
1589
2225
  saveJsonMap(): string;
2226
+ /** Desktop's player-room marker settings as saveJsonMap writes them — see
2227
+ * there. Desktop's Host defaults until a file brings its own. */
2228
+ private jsonPlayerRoom;
2229
+ /** The counterpart of the extras {@link saveJsonMap} writes: an imported
2230
+ * file's map-level settings, applied after the rooms have loaded. */
2231
+ applyJsonMapSettings(doc: Record<string, unknown>): void;
1590
2232
  /** Mudlet `loadJsonMap(path)` backbone — parse a JSON payload previously
1591
2233
  * produced by saveJsonMap and reload the map. Returns false when the
1592
2234
  * JSON is malformed or doesn't match the MudletMap shape. */
1593
- loadJsonMap(json: string): boolean;
2235
+ loadJsonMap(json: string, source?: string): boolean;
1594
2236
  /** Mudlet `addSupportedTelnetOption(option)`. Forwarded to the session
1595
2237
  * client so the next IAC WILL/DO from the server can be auto-accepted. */
1596
2238
  addSupportedTelnetOption(option: number): boolean;
@@ -1598,9 +2240,11 @@ export declare class ScriptingAPI {
1598
2240
  * Mudlet `saveWindowLayout()` — capture the current layout (window hints
1599
2241
  * + dock area extents) into a per-connection snapshot in the persisted
1600
2242
  * app store. A later `loadWindowLayout()` re-applies the captured state.
1601
- * Returns true on success, false when no connectionId is bound.
2243
+ * Returns true on success, false when no connectionId is bound or the
2244
+ * layout file cannot be written — what desktop reports when it cannot open
2245
+ * `windowLayout.dat`.
1602
2246
  */
1603
- saveWindowLayout(): boolean;
2247
+ saveWindowLayout(): boolean | string;
1604
2248
  /** Where Mudlet keeps the window layout: beside the profiles folder, not
1605
2249
  * inside one, because the layout is the application's rather than any one
1606
2250
  * profile's. Null when there is no VFS to write into. */
@@ -1612,7 +2256,7 @@ export declare class ScriptingAPI {
1612
2256
  * Mudlet-shaped copy, so a script (or a person poking at the profile
1613
2257
  * filesystem) finds the layout where Mudlet puts it and can read it. It is
1614
2258
  * JSON rather than Mudlet's `QMainWindow::saveState` blob: nothing outside
1615
- * mudix reads it, and those bytes describe Qt dock widgets that have no
2259
+ * Mudlet Web reads it, and those bytes describe Qt dock widgets that have no
1616
2260
  * counterpart here.
1617
2261
  */
1618
2262
  private writeWindowLayoutFile;
@@ -1626,6 +2270,9 @@ export declare class ScriptingAPI {
1626
2270
  * but are not currently mounted. Returns false when no snapshot exists.
1627
2271
  */
1628
2272
  loadWindowLayout(): boolean;
2273
+ /** True while {@link loadWindowLayout} is placing windows — the resize
2274
+ * events it raises run handlers before it returns. */
2275
+ private layoutLoading;
1629
2276
  /**
1630
2277
  * Mudlet `getTime()` — current local time as a record. The Bridge.lua wrapper
1631
2278
  * picks fields off this object for the `{year, month, day, hour, min, sec,
@@ -1641,10 +2288,15 @@ export declare class ScriptingAPI {
1641
2288
  sec: number;
1642
2289
  msec: number;
1643
2290
  wday: number;
2291
+ tzAbbr: string;
2292
+ tzOffset: string;
2293
+ tzOffsetColon: string;
2294
+ tzLong: string;
1644
2295
  };
1645
2296
  /**
1646
- * Mudlet `getNetworkLatency()` — round-trip time of the most recent
1647
- * keep-alive ping. Returns the last measured value (in ms) for as long as
2297
+ * Mudlet `getNetworkLatency()` — the most recent round trip measured,
2298
+ * from a command to the game's next GA/EOR prompt marker (as Mudlet
2299
+ * times it). Returns the last measured value (in ms) for as long as
1648
2300
  * the connection is up; -1 when no measurement has been made yet (mirrors
1649
2301
  * Mudlet's "not yet measured" sentinel — better than a fake 0 which would
1650
2302
  * read as "instant" in scripts charting latency).
@@ -1652,10 +2304,14 @@ export declare class ScriptingAPI {
1652
2304
  getNetworkLatency(): number;
1653
2305
  private lastPingMs;
1654
2306
  getMainWindowSize(): [number, number];
2307
+ /** Mudlet `setMainWindowSize(width, height)`. Sizes the main viewport —
2308
+ * the rectangle {@link getMainWindowSize} reports — since a browser tab
2309
+ * cannot resize itself. See WindowManager.setMainWindowSize. */
2310
+ setMainWindowSize(width: number, height: number): boolean;
1655
2311
  /**
1656
2312
  * Mudlet `hasFocus([window])` → bool. Reports whether the named console (or
1657
2313
  * the main command bar / output area when omitted) currently holds keyboard
1658
- * focus. mudix maps "main"/omitted to the command input, and a named window
2314
+ * focus. Mudlet Web maps "main"/omitted to the command input, and a named window
1659
2315
  * to its registered overlay element. Returns false when nothing matches.
1660
2316
  */
1661
2317
  hasFocus(windowName?: string): boolean;
@@ -1672,17 +2328,24 @@ export declare class ScriptingAPI {
1672
2328
  * Mudlet `getMainConsoleWidth()` — pixel width of the main console's text
1673
2329
  * area. Mudlet computes `averageCharWidth * (wrapAt + 1)`; we mirror that
1674
2330
  * with a canvas-measured monospace cell for the profile's output font, and
1675
- * resolve the wrap column from the profile's `outputWrapAt` override (the
1676
- * value `setWindowWrap("main", n)` writes), falling back to the live
1677
- * measured column count when no explicit wrap is set.
2331
+ * the main wrap column (`outputWrapAt`, 100 by default), falling back to
2332
+ * the live measured column count when the Settings turned wrapping off.
1678
2333
  */
1679
2334
  getMainConsoleWidth(): number;
2335
+ /** The server the last connectToServer() pointed the profile at, with the
2336
+ * dial it asked for — see {@link getConnectionInfo}. */
2337
+ private connectTarget;
1680
2338
  /**
1681
2339
  * Mudlet `getConnectionInfo()` → `host, port, connected`. Mudlet reports the
1682
- * MUD's telnet host/port; mudix reads them off the active connection config.
1683
- * For a `mud`-mode connection those are the stored host/port; for a raw
1684
- * `websocket` connection we parse them out of the endpoint URL (port falls
1685
- * back to the ws/wss default). `connected` reflects the live session status.
2340
+ * MUD's telnet host/port — cTelnet's own, which `connectToServer` replaces
2341
+ * whether or not it saves them, so a script that moved the profile to
2342
+ * another server is told that server from the call on, through a failed
2343
+ * dial and a `reconnect()` (mudlet-web#339). That target holds until a dial
2344
+ * to somewhere else (the Connect button redialling the profile) overtakes
2345
+ * it. Otherwise Mudlet Web reads the active connection config: for a
2346
+ * `mud`-mode connection the stored host/port, for a raw `websocket` one the
2347
+ * endpoint URL's (port falls back to the ws/wss default). `connected`
2348
+ * reflects the live session status.
1686
2349
  */
1687
2350
  getConnectionInfo(): {
1688
2351
  host: string;
@@ -1690,7 +2353,7 @@ export declare class ScriptingAPI {
1690
2353
  connected: boolean;
1691
2354
  };
1692
2355
  /**
1693
- * Mudlet `connectToServer(host, port [, save])`. mudix tunnels MUD traffic
2356
+ * Mudlet `connectToServer(host, port [, save])`. Mudlet Web tunnels MUD traffic
1694
2357
  * through a WebSocket proxy, so this builds the same `proxy?host=&port=` URL
1695
2358
  * the connection screen uses and (re)connects the live session. With `save`,
1696
2359
  * the host/port are persisted onto the active connection (switching it to
@@ -1757,17 +2420,36 @@ export declare class ScriptingAPI {
1757
2420
  */
1758
2421
  setFontSize(size: number, win?: string): boolean;
1759
2422
  /**
1760
- * Mudlet setMiniConsoleFontSize. Strictly targets miniconsoles (created via
1761
- * createMiniConsole / createConsole) — userwindows and labels are rejected
1762
- * the same way Mudlet's CONSOLE-only lookup rejects them.
2423
+ * Desktop's `TConsole::raiseFontChangeEvent`: `sysFontChangeEvent(console,
2424
+ * family, size)`, raised whenever a console's font really changes — a new
2425
+ * miniconsole or user window taking its first font, and every setFont /
2426
+ * setFontSize that lands on something different. Layout code listens for
2427
+ * it to reflow. Main's is raised by the engine, which watches the profile
2428
+ * font whatever changed it.
1763
2429
  */
1764
- setMiniConsoleFontSize(name: string, size: number): boolean;
2430
+ raiseFontChangeEvent(name: string): void;
2431
+ /** Run a font write against a console and raise sysFontChangeEvent if it
2432
+ * changed what the console is drawn in. Only consoles raise it on desktop
2433
+ * (not labels, maps or buffers), and a write that lands on the font already
2434
+ * in use raises nothing — TConsole::setFont compares before it applies. */
2435
+ private withFontChangeEvent;
2436
+ /**
2437
+ * Mudlet setMiniConsoleFontSize. Desktop registers it as another name for
2438
+ * setFontSize, so it reaches every console setFontSize does — main
2439
+ * included, and main when no name is given (mudlet-web#380).
2440
+ */
2441
+ setMiniConsoleFontSize(name: string | undefined, size: number): boolean;
1765
2442
  /**
1766
2443
  * Mudlet getFontSize. Returns the configured font size in pixels for the
1767
2444
  * main window (when no name passed) or for a specific window. Returns null
1768
2445
  * if a named window doesn't exist or has no override.
1769
2446
  */
1770
2447
  getFontSize(win?: string): number | null;
2448
+ /** The point size a user window's style sheet gives its text
2449
+ * (`TTextEdit { font-size: … }`), which is the font its console is drawn
2450
+ * in on desktop — and here, once the sheet is scoped onto the window. One
2451
+ * in pixels is read as points at the CSS 96 dpi. */
2452
+ private userWindowStyleSheetFontSize;
1771
2453
  /**
1772
2454
  * Mudlet setBackgroundColor. With no name (or "main") sets the main window
1773
2455
  * background; otherwise dispatches to the matching label or userwindow/
@@ -1780,6 +2462,16 @@ export declare class ScriptingAPI {
1780
2462
  * fall through here too — their fill color is reported. Returns null when
1781
2463
  * the name doesn't resolve to anything; callers (Lua wrapper) translate that
1782
2464
  * to a 4-tuple of zeros.
2465
+ *
2466
+ * The main window answers from the *preference* when no script has set a
2467
+ * colour, not from nothing. `outputBackgroundColor` is only the override
2468
+ * `setBackgroundColor()` writes; returning null without it meant the Lua
2469
+ * wrapper substituted black, so a package colouring its Geyser UI to match
2470
+ * the user's background — a very common pattern — rendered against black
2471
+ * whatever the user had chosen (issue #71). Desktop reads the
2472
+ * preference-backed model colour for the main window and says why:
2473
+ * "the view's colour is a reference to this one, so read it straight from
2474
+ * the model" (TLuaInterpreterUI.cpp:1217-1243).
1783
2475
  */
1784
2476
  getBackgroundColor(name?: string): {
1785
2477
  r: number;
@@ -1791,25 +2483,42 @@ export declare class ScriptingAPI {
1791
2483
  * Mudlet `setBackgroundImage`. Dispatcher across labels, miniconsoles /
1792
2484
  * userwindows, and the main window — matches Mudlet's overload set:
1793
2485
  *
1794
- * setBackgroundImage(labelName, imageLocation) → label
1795
2486
  * setBackgroundImage(imageLocation, [mode]) → main console
1796
- * setBackgroundImage(windowName, imageLocation, [mode]) → miniconsole / userwindow
2487
+ * setBackgroundImage(name, imageLocation, [mode]) → label, or
2488
+ * miniconsole / userwindow
1797
2489
  *
1798
- * Disambiguation matches Mudlet's C++ semantics — label lookup wins when
1799
- * the named widget is a label; otherwise the call is treated as a console
1800
- * form. `mode` arrives already coerced to a number by the GUIUtils.lua
1801
- * wrapper (string mode like "center" → 2 via `mudlet.BgImageMode`). For
1802
- * label form `imageLocation` is a VFS path, resolved through the same
1803
- * rewriter that powers setLabelStyleSheet so package-bundled images work
1804
- * without scripts knowing about the vfs:// scheme.
1805
- */
1806
- setBackgroundImage(a: string, b?: string | number, c?: number): boolean;
2490
+ * Routing follows Host::setBackgroundImage: "main" is the main console, a
2491
+ * label name wins next whatever the argument count (a label takes no mode
2492
+ * and ignores the one it is given), and anything else is a sub-console.
2493
+ * `mode` arrives already coerced to a number by the GUIUtils.lua wrapper
2494
+ * (string mode like "center" → 2 via `mudlet.BgImageMode`). For the label
2495
+ * form `imageLocation` is a VFS path, resolved through the same rewriter
2496
+ * that powers setLabelStyleSheet so package-bundled images work without
2497
+ * scripts knowing about the vfs:// scheme.
2498
+ *
2499
+ * Returns true, or desktop's refusal message — one wording for a name
2500
+ * nothing answers to and for a label image that cannot be loaded, since
2501
+ * TLuaInterpreter::setBackgroundImage only learns that one of them failed.
2502
+ *
2503
+ * `fullWindow` is the trailing boolean of `(main, path, mode, true)`. The
2504
+ * full-window background is the main console's here, but desktop's
2505
+ * TConsole::setWindowBackgroundImage loads the picture for mode 5 ('cover')
2506
+ * up front and refuses one that will not load, which a script (the starter
2507
+ * UI's background picture) relies on to know it is not showing.
2508
+ */
2509
+ setBackgroundImage(a: string, b?: string | number, c?: number, fullWindow?: unknown): true | string;
2510
+ /** Whether a label could load `path` as an image, as far as can be told
2511
+ * now: a vendored Qt resource, a profile file whose content is an SVG or a
2512
+ * raster format Qt reads (QPixmap judges by content, not by name), or a
2513
+ * remote / inline URL — which cannot be judged synchronously and is taken
2514
+ * on trust. */
2515
+ private labelImageLoads;
1807
2516
  /**
1808
2517
  * Mudlet `resetBackgroundImage([windowName])`. Without a name (or "main")
1809
2518
  * clears the main window background image; otherwise looks up the named
1810
2519
  * label or window and clears its image. Returns true on success.
1811
2520
  */
1812
- resetBackgroundImage(name?: string): boolean;
2521
+ resetBackgroundImage(name?: string, fullWindow?: boolean): true | string;
1813
2522
  /**
1814
2523
  * Mudlet `setLabelCustomCursor(labelName, cursorPath, [hotX, hotY])`. Points
1815
2524
  * the label's mouse cursor at a custom image. The path is run through the
@@ -1818,7 +2527,16 @@ export declare class ScriptingAPI {
1818
2527
  * value. hotX/hotY are the cursor hotspot in pixels (default 0,0). Returns
1819
2528
  * false when the label doesn't exist.
1820
2529
  */
1821
- setLabelCustomCursor(name: string, path: string, hotX?: number, hotY?: number): boolean;
2530
+ /** Mudlet `setLabelCustomCursor(name, path [, hotX, hotY])`. True when the
2531
+ * cursor is set, else the refusal in TMainConsole::setLabelCustomCursor's
2532
+ * words and order: the empty name, the empty location, then — for a label
2533
+ * that exists — an image it cannot load; a missing label last. */
2534
+ setLabelCustomCursor(name: string, path: string, hotX?: number, hotY?: number): true | string;
2535
+ /** Whether an image path names something there to load, as far as can be
2536
+ * told now: a vendored Qt resource, or a profile file that exists. A
2537
+ * remote or inline URL cannot be judged synchronously and is taken on
2538
+ * trust. */
2539
+ private canLoadImage;
1822
2540
  /**
1823
2541
  * Mudlet `setMovie(labelName, path)` — decode the animation at `path`,
1824
2542
  * install it on the label, and start playing (Mudlet starts immediately
@@ -1891,10 +2609,18 @@ export declare class ScriptingAPI {
1891
2609
  * the API is unavailable (Firefox/Safari). */
1892
2610
  getProcessMemoryUsage(): number;
1893
2611
  /** Mudlet `getSubsystemMemoryStats()` → a diagnostic table of heap metrics
1894
- * plus per-subsystem counts. Browser-adapted: heap figures come from
1895
- * `performance.memory` (Chromium; 0 elsewhere); the Lua GC figure
1896
- * (`luaMemoryKb`) is added by the Bridge.lua wrapper via
1897
- * `collectgarbage("count")`. Counts are best-effort snapshots. */
2612
+ * plus per-subsystem counts, under Mudlet's own snake_case key names — the
2613
+ * table is read by key, so a browser-flavoured spelling would just make
2614
+ * every existing diagnostic script read nil.
2615
+ *
2616
+ * Browser-adapted where the C++ figure has no equivalent: the heap sizes
2617
+ * come from `performance.memory` (Chromium only, and left out entirely
2618
+ * elsewhere, as Mudlet leaves them out on a platform whose allocator it
2619
+ * cannot ask); `heap_limit_mb` and `loaded_fonts` are browser-only extras.
2620
+ * `event_handlers` is absent: Other.lua keeps its handler registry in a
2621
+ * local upvalue, with no reachable count. The Lua GC figures
2622
+ * (`lua_heap_kb`/`lua_heap_mb`) are added by the Bridge.lua wrapper.
2623
+ * Counts are best-effort snapshots. */
1898
2624
  getSubsystemMemoryStats(): Record<string, number>;
1899
2625
  private patchBorders;
1900
2626
  private applyBorders;
@@ -1923,10 +2649,27 @@ export declare class ScriptingAPI {
1923
2649
  * • `calcFontSize("WindowName")` — measure the named window/miniconsole
1924
2650
  * using its configured font+size. Use `"main"` for the main output.
1925
2651
  *
2652
+ * The size forms answer the font's average character width, the window
2653
+ * form the width of a "W" — what scripts have long compensated for by hand
2654
+ * — unless `columnWidth` asks for the width a column is drawn in, which is
2655
+ * the average again. All three agree on a monospaced font.
2656
+ *
1926
2657
  * Returns `null` when the size is invalid or the named window doesn't
1927
2658
  * exist; the Lua wrapper turns that into Mudlet's `(nil, errMsg)` shape.
1928
- */
1929
- calcFontSize(arg: number | string, fontName?: string): [number, number] | null;
2659
+ *
2660
+ * Whole pixels, like the `QSize` Mudlet builds out of
2661
+ * `QFontMetrics::averageCharWidth()` and `::height()` — and unlike the
2662
+ * fractional cell {@link measureMonospaceCell} hands this client's own
2663
+ * column arithmetic. The rounding is what makes the number multipliable:
2664
+ * every caller of this one is a script scaling it back up into a widget
2665
+ * size (Geyser resolves a `"20c"` constraint as `20 * calcFontSize(...)`,
2666
+ * GUIUtils sizes a `createConsole` the same way), and widget geometry is
2667
+ * whole pixels in Mudlet and here alike. A fractional cell makes that
2668
+ * product land between pixels, where it is truncated — so the size a script
2669
+ * computed and the size `getWindowGeometry` reports back silently disagree,
2670
+ * by an amount that depends on which fonts the machine happens to have.
2671
+ */
2672
+ calcFontSize(arg: number | string, fontName?: string, columnWidth?: boolean): [number, number] | null;
1930
2673
  /**
1931
2674
  * Mudlet `getAvailableFonts()` — set-style table whose keys are font
1932
2675
  * family names usable from scripts. The browser cannot enumerate the
@@ -1942,6 +2685,25 @@ export declare class ScriptingAPI {
1942
2685
  * call sees the result.
1943
2686
  */
1944
2687
  getAvailableFonts(): Record<string, boolean>;
2688
+ /**
2689
+ * The installed family a requested font name means, or null if none does.
2690
+ *
2691
+ * Mudlet hands the name to QFont, which resolves it three ways before
2692
+ * giving up, and scripts depend on all three: the exact family, the same
2693
+ * family in any casing, and a "Family Style" name whose trailing style word
2694
+ * is a weight/slant request rather than part of the family — "Ubuntu Mono
2695
+ * Bold" is Ubuntu Mono asked for in bold, not a family of that name. The
2696
+ * answer is always spelled the way the font database spells it, because
2697
+ * callers read it straight back (Geyser.Label:setFont stores getFont()'s
2698
+ * reply so what it remembers and what the widget got cannot drift).
2699
+ *
2700
+ * Only weight and slant words are trimmed, never width ones: Qt keeps width
2701
+ * in the family name ("Arial Narrow" is its own family), so trimming those
2702
+ * would resolve a name to a font the caller did not ask for. A trailing word
2703
+ * that is not a style word stops the trim outright, so "Arial Nonsense"
2704
+ * fails rather than quietly becoming Arial.
2705
+ */
2706
+ resolveFontFamily(name: string): string | null;
1945
2707
  /** Flush any buffered partial lines to the main output and all open windows. Called after each event dispatch. */
1946
2708
  flushOutput(): void;
1947
2709
  /** @deprecated use echo() */
@@ -1951,6 +2713,26 @@ export declare class ScriptingAPI {
1951
2713
  * client telling the player something about the line in front of them,
1952
2714
  * not a script's error. */
1953
2715
  postSystemMessage(text: string): void;
2716
+ /**
2717
+ * A notice for the player in the main window — not a script fault, so not
2718
+ * printError, which only reaches main when the profile asked for errors
2719
+ * there and would be missed by exactly the person who needs it.
2720
+ *
2721
+ * Written to the buffer as well as emitted, for the reason
2722
+ * warnIfUnencodable gives: a line the player can read has to be a line
2723
+ * getLines() and the cursor APIs can see.
2724
+ */
2725
+ postInfo(text: string): void;
2726
+ /** Mudlet's `Host::postMessage` for the `[ WARN ]` kind, written the same
2727
+ * way as {@link postInfo}. */
2728
+ postWarning(text: string): void;
2729
+ /** A profile save counts as running until the next pass of the event
2730
+ * loop; see ScriptingEngine.markProfileSaveInFlight. */
2731
+ markProfileSaveInFlight(): void;
2732
+ /** Mudlet's `Host::postMessage` for the `[ ERROR ]` kind: unlike printError
2733
+ * this is client news rather than a script's own fault, so it goes on the
2734
+ * main console whether or not the profile shows script errors there. */
2735
+ postError(text: string): void;
1954
2736
  printError(text: string, source?: ScriptLogSource): void;
1955
2737
  destroy(): void;
1956
2738
  private getConsole;
@@ -1960,12 +2742,56 @@ export declare class ScriptingAPI {
1960
2742
  * all of which back a Console. Used by the read/select methods instead of a
1961
2743
  * bare `windows.has`, which is false for buffers (they have no panel).
1962
2744
  */
2745
+ /** Whether `name` is a console a script can write to (see {@link consoleExists}). */
2746
+ hasConsole(name: string): boolean;
1963
2747
  private consoleExists;
2748
+ /**
2749
+ * The Console a write to `win` goes to, or null when `win` names no console
2750
+ * at all. Mudlet resolves the name and answers a miss with "window not
2751
+ * found" (or, for echo, "console/label does not exist") without creating
2752
+ * anything; going through {@link outputConsole} instead conjured a hidden
2753
+ * console out of the typo, which then showed up as a "userwindow" and
2754
+ * handed its stray text to whatever window was later created under that
2755
+ * name (mudlet-web#280).
2756
+ */
2757
+ private penConsole;
1964
2758
  /** Returns the Console for a window, creating and registering one on demand. */
1965
2759
  private outputConsole;
1966
2760
  private drainWindowConsole;
1967
2761
  private resolveBuffer;
1968
- private selectionMatches;
2762
+ private selectionKey;
2763
+ /** The named console's own selection (main when omitted), or null. */
2764
+ private selectionOf;
2765
+ /** Whether the named console (main when omitted) has a selection, valid or
2766
+ * not. */
2767
+ hasSelection(win?: string): boolean;
2768
+ /** Whether the named console's selection covers any text — what setLink
2769
+ * and setPopup need, since a link on nothing would be one nobody could
2770
+ * click. */
2771
+ hasSelectedText(win?: string): boolean;
2772
+ /** Whether the named console's cursor is where insertLink / insertPopup
2773
+ * can put text (see Console.cursorInText). */
2774
+ cursorInText(win?: string): boolean;
2775
+ /** Selections are made on the cursor's line, and stay with that line. */
2776
+ private setSelection;
2777
+ /**
2778
+ * The line a selection was made on, while its console still holds it —
2779
+ * wherever the lines around it have moved it. Once a clear (or the
2780
+ * scrollback limit) has taken that line away, the selection is desktop's
2781
+ * P_begin/P_end again, a line number: whatever line now has that number,
2782
+ * or null when none has, which leaves the selection standing but no longer
2783
+ * valid.
2784
+ */
2785
+ private selectionBuffer;
2786
+ private clearSelection;
2787
+ /**
2788
+ * The columns a selection covers on `buf`, read as TBuffer::applyFgColor
2789
+ * and the other apply* calls read P_begin/P_end: the end is cut at the end
2790
+ * of the line, and a selection starting at or past it covers nothing. A
2791
+ * selection outlives the text it was made on — replace() keeps it, and the
2792
+ * cursor can move to a shorter line — so it can run off the end.
2793
+ */
2794
+ private selectionSpan;
1969
2795
  private applyStateToSelection;
1970
2796
  private drainMain;
1971
2797
  }