@xincli/opentui-core 0.4.6 → 0.4.7

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 (619) hide show
  1. package/LICENSE +21 -0
  2. package/NativeSpanFeed.d.ts +52 -0
  3. package/README.md +0 -0
  4. package/Renderable.d.ts +346 -0
  5. package/animation/Timeline.d.ts +126 -0
  6. package/ansi.d.ts +17 -0
  7. package/audio.d.ts +89 -0
  8. package/buffer.d.ts +113 -0
  9. package/console.d.ts +146 -0
  10. package/edit-buffer.d.ts +97 -0
  11. package/editor-view.d.ts +72 -0
  12. package/index-m1y9e40w.js +10045 -0
  13. package/index-m1y9e40w.js.map +32 -0
  14. package/index-sqk4ajdf.js +16121 -0
  15. package/index-sqk4ajdf.js.map +58 -0
  16. package/index.d.ts +24 -0
  17. package/index.js +11709 -0
  18. package/index.js.map +35 -0
  19. package/lib/KeyHandler.d.ts +61 -0
  20. package/lib/RGBA.d.ts +42 -0
  21. package/lib/ascii.font.d.ts +508 -0
  22. package/lib/border.d.ts +51 -0
  23. package/lib/bunfs.d.ts +7 -0
  24. package/lib/clipboard.d.ts +15 -0
  25. package/lib/clock.d.ts +15 -0
  26. package/lib/data-paths.d.ts +26 -0
  27. package/lib/debounce.d.ts +42 -0
  28. package/lib/detect-links.d.ts +6 -0
  29. package/lib/env.d.ts +42 -0
  30. package/lib/extmarks-history.d.ts +17 -0
  31. package/lib/extmarks.d.ts +90 -0
  32. package/lib/hast-styled-text.d.ts +17 -0
  33. package/lib/index.d.ts +22 -0
  34. package/lib/keybinding.internal.d.ts +33 -0
  35. package/lib/objects-in-viewport.d.ts +24 -0
  36. package/lib/output.capture.d.ts +24 -0
  37. package/lib/parse.keypress-kitty.d.ts +3 -0
  38. package/lib/parse.keypress.d.ts +27 -0
  39. package/lib/parse.mouse.d.ts +30 -0
  40. package/lib/paste.d.ts +7 -0
  41. package/lib/queue.d.ts +15 -0
  42. package/lib/render-geometry.d.ts +8 -0
  43. package/lib/renderable.validations.d.ts +12 -0
  44. package/lib/scroll-acceleration.d.ts +43 -0
  45. package/lib/selection.d.ts +64 -0
  46. package/lib/singleton.d.ts +8 -0
  47. package/lib/stdin-parser.d.ts +90 -0
  48. package/lib/styled-text.d.ts +63 -0
  49. package/lib/terminal-capability-detection.d.ts +32 -0
  50. package/lib/terminal-palette.d.ts +65 -0
  51. package/lib/tree-sitter/assets/update.d.ts +12 -0
  52. package/lib/tree-sitter/client.d.ts +65 -0
  53. package/lib/tree-sitter/default-parsers.d.ts +2 -0
  54. package/lib/tree-sitter/download-utils.d.ts +21 -0
  55. package/lib/tree-sitter/index.d.ts +7 -0
  56. package/lib/tree-sitter/parser.worker.d.ts +1 -0
  57. package/lib/tree-sitter/parsers-config.d.ts +53 -0
  58. package/lib/tree-sitter/resolve-ft.d.ts +5 -0
  59. package/lib/tree-sitter/types.d.ts +185 -0
  60. package/lib/tree-sitter/update-assets.d.ts +3 -0
  61. package/lib/tree-sitter/update-assets.js +379 -0
  62. package/lib/tree-sitter/update-assets.js.map +12 -0
  63. package/lib/tree-sitter-styled-text.d.ts +16 -0
  64. package/lib/validate-dir-name.d.ts +1 -0
  65. package/lib/yoga.options.d.ts +32 -0
  66. package/native-event-worker-repro.worker.d.ts +1 -0
  67. package/package.json +52 -74
  68. package/parser.worker.js +1399 -0
  69. package/parser.worker.js.map +20 -0
  70. package/platform/ffi.d.ts +129 -0
  71. package/platform/runtime.d.ts +14 -0
  72. package/platform/test.d.ts +12 -0
  73. package/platform/worker.d.ts +26 -0
  74. package/platform/worker.node-test.d.ts +1 -0
  75. package/plugins/core-slot.d.ts +72 -0
  76. package/plugins/registry.d.ts +42 -0
  77. package/plugins/types.d.ts +34 -0
  78. package/post/effects.d.ts +147 -0
  79. package/post/filters.d.ts +65 -0
  80. package/post/matrices.d.ts +20 -0
  81. package/renderables/ASCIIFont.d.ts +52 -0
  82. package/renderables/Box.d.ts +85 -0
  83. package/renderables/Code.d.ts +97 -0
  84. package/renderables/Diff.d.ts +147 -0
  85. package/renderables/EditBufferRenderable.d.ts +238 -0
  86. package/renderables/FrameBuffer.d.ts +16 -0
  87. package/renderables/Input.d.ts +72 -0
  88. package/renderables/LineNumberRenderable.d.ts +78 -0
  89. package/renderables/Markdown.d.ts +255 -0
  90. package/renderables/ScrollBar.d.ts +77 -0
  91. package/renderables/ScrollBox.d.ts +128 -0
  92. package/renderables/Select.d.ts +122 -0
  93. package/renderables/Slider.d.ts +47 -0
  94. package/renderables/TabSelect.d.ts +98 -0
  95. package/renderables/Text.d.ts +36 -0
  96. package/renderables/TextBufferRenderable.d.ts +107 -0
  97. package/renderables/TextNode.d.ts +92 -0
  98. package/renderables/TextTable.d.ts +154 -0
  99. package/renderables/Textarea.d.ts +65 -0
  100. package/renderables/TimeToFirstDraw.d.ts +24 -0
  101. package/renderables/__tests__/renderable-test-utils.d.ts +12 -0
  102. package/renderables/composition/VRenderable.d.ts +16 -0
  103. package/renderables/composition/constructs.d.ts +35 -0
  104. package/renderables/composition/vnode.d.ts +46 -0
  105. package/renderables/index.d.ts +23 -0
  106. package/renderables/markdown-parser.d.ts +11 -0
  107. package/renderer-theme-mode.d.ts +29 -0
  108. package/renderer.d.ts +601 -0
  109. package/runtime-plugin-support-configure.d.ts +4 -0
  110. package/runtime-plugin-support-configure.js +36 -0
  111. package/runtime-plugin-support-configure.js.map +1 -0
  112. package/runtime-plugin-support-configure.node.js +15 -0
  113. package/runtime-plugin-support.d.ts +3 -0
  114. package/runtime-plugin-support.js +5 -0
  115. package/runtime-plugin-support.js.map +1 -0
  116. package/runtime-plugin-support.node.js +15 -0
  117. package/runtime-plugin.d.ts +16 -0
  118. package/runtime-plugin.js +473 -0
  119. package/runtime-plugin.js.map +1 -0
  120. package/runtime-plugin.node.js +15 -0
  121. package/syntax-style.d.ts +61 -0
  122. package/testing/bun-test-node.d.ts +87 -0
  123. package/testing/manual-clock.d.ts +17 -0
  124. package/testing/mock-keys.d.ts +81 -0
  125. package/testing/mock-mouse.d.ts +38 -0
  126. package/testing/mock-tree-sitter-client.d.ts +27 -0
  127. package/testing/spy.d.ts +7 -0
  128. package/testing/terminal-capabilities.d.ts +7 -0
  129. package/testing/test-recorder.d.ts +61 -0
  130. package/testing/test-renderer.d.ts +54 -0
  131. package/testing/test-streams.d.ts +12 -0
  132. package/testing.d.ts +8 -0
  133. package/testing.js +1004 -0
  134. package/testing.js.map +18 -0
  135. package/tests/yoga-upstream/tools/MeasureCounter.d.ts +16 -0
  136. package/tests/yoga-upstream/tools/utils.d.ts +11 -0
  137. package/text-buffer-view.d.ts +42 -0
  138. package/text-buffer.d.ts +66 -0
  139. package/types.d.ts +175 -0
  140. package/utils.d.ts +14 -0
  141. package/yoga.d.ts +437 -0
  142. package/yoga.js +193 -0
  143. package/yoga.js.map +9 -0
  144. package/zig-structs.d.ts +256 -0
  145. package/zig.d.ts +496 -0
  146. package/dev/keypress-debug-renderer.ts +0 -148
  147. package/dev/keypress-debug.ts +0 -43
  148. package/dev/print-env-vars.ts +0 -32
  149. package/dev/test-tmux-graphics-334.sh +0 -68
  150. package/dev/test-tmux-theme-queries.sh +0 -151
  151. package/dev/thai-debug-test.ts +0 -68
  152. package/dev/theme-mode.ts +0 -290
  153. package/docs/development.md +0 -144
  154. package/prebuilt/aarch64-android/libopentui.so +0 -0
  155. package/scripts/build-android.ts +0 -226
  156. package/scripts/build-native-termux.sh +0 -525
  157. package/scripts/build.ts +0 -530
  158. package/scripts/dist-test.ts +0 -312
  159. package/scripts/package-prebuilt.ts +0 -110
  160. package/scripts/publish.ts +0 -60
  161. package/scripts/test-node-hook.mjs +0 -16
  162. package/scripts/test-node.ts +0 -241
  163. package/scripts/vendor-deps.sh +0 -73
  164. package/src/NativeSpanFeed.ts +0 -375
  165. package/src/Renderable.ts +0 -1878
  166. package/src/__snapshots__/buffer.test.ts.snap +0 -28
  167. package/src/animation/Timeline.test.ts +0 -2709
  168. package/src/animation/Timeline.ts +0 -598
  169. package/src/ansi.ts +0 -22
  170. package/src/audio.ts +0 -479
  171. package/src/benchmark/attenuation-benchmark.ts +0 -81
  172. package/src/benchmark/audio-playback-benchmark.ts +0 -344
  173. package/src/benchmark/box-draw-benchmark.ts +0 -1042
  174. package/src/benchmark/colormatrix-benchmark.ts +0 -123
  175. package/src/benchmark/gain-benchmark.ts +0 -80
  176. package/src/benchmark/latest-all-bench-run.json +0 -707
  177. package/src/benchmark/latest-async-bench-run.json +0 -336
  178. package/src/benchmark/latest-default-bench-run.json +0 -657
  179. package/src/benchmark/latest-large-bench-run.json +0 -707
  180. package/src/benchmark/latest-quick-bench-run.json +0 -207
  181. package/src/benchmark/layout-benchmark.ts +0 -2547
  182. package/src/benchmark/markdown-benchmark.ts +0 -1796
  183. package/src/benchmark/native-span-feed-async-benchmark.ts +0 -355
  184. package/src/benchmark/native-span-feed-benchmark.md +0 -56
  185. package/src/benchmark/native-span-feed-benchmark.ts +0 -596
  186. package/src/benchmark/native-span-feed-compare.ts +0 -280
  187. package/src/benchmark/render-traversal-benchmark.ts +0 -928
  188. package/src/benchmark/text-buffer-render-benchmark.ts +0 -874
  189. package/src/benchmark/text-table-benchmark.ts +0 -948
  190. package/src/buffer.test.ts +0 -292
  191. package/src/buffer.ts +0 -564
  192. package/src/console.test.ts +0 -629
  193. package/src/console.ts +0 -1253
  194. package/src/edit-buffer.test.ts +0 -1852
  195. package/src/edit-buffer.ts +0 -417
  196. package/src/editor-view.test.ts +0 -1056
  197. package/src/editor-view.ts +0 -290
  198. package/src/index.ts +0 -25
  199. package/src/lib/KeyHandler.integration.test.ts +0 -292
  200. package/src/lib/KeyHandler.stopPropagation.test.ts +0 -289
  201. package/src/lib/KeyHandler.test.ts +0 -662
  202. package/src/lib/KeyHandler.ts +0 -222
  203. package/src/lib/RGBA.test.ts +0 -60
  204. package/src/lib/RGBA.ts +0 -343
  205. package/src/lib/ascii.font.ts +0 -330
  206. package/src/lib/border.test.ts +0 -83
  207. package/src/lib/border.ts +0 -170
  208. package/src/lib/bunfs.test.ts +0 -27
  209. package/src/lib/bunfs.ts +0 -18
  210. package/src/lib/clipboard.test.ts +0 -63
  211. package/src/lib/clipboard.ts +0 -41
  212. package/src/lib/clock.ts +0 -35
  213. package/src/lib/data-paths.test.ts +0 -133
  214. package/src/lib/data-paths.ts +0 -109
  215. package/src/lib/debounce.ts +0 -106
  216. package/src/lib/detect-links.test.ts +0 -98
  217. package/src/lib/detect-links.ts +0 -56
  218. package/src/lib/env.test.ts +0 -228
  219. package/src/lib/env.ts +0 -209
  220. package/src/lib/extmarks-history.ts +0 -51
  221. package/src/lib/extmarks-multiwidth.test.ts +0 -324
  222. package/src/lib/extmarks.test.ts +0 -3547
  223. package/src/lib/extmarks.ts +0 -861
  224. package/src/lib/fonts/block.json +0 -405
  225. package/src/lib/fonts/grid.json +0 -265
  226. package/src/lib/fonts/huge.json +0 -741
  227. package/src/lib/fonts/pallet.json +0 -314
  228. package/src/lib/fonts/shade.json +0 -591
  229. package/src/lib/fonts/slick.json +0 -321
  230. package/src/lib/fonts/tiny.json +0 -69
  231. package/src/lib/hast-styled-text.ts +0 -59
  232. package/src/lib/index.ts +0 -22
  233. package/src/lib/keybinding.internal.test.ts +0 -342
  234. package/src/lib/keybinding.internal.ts +0 -182
  235. package/src/lib/objects-in-viewport.test.ts +0 -789
  236. package/src/lib/objects-in-viewport.ts +0 -153
  237. package/src/lib/output.capture.ts +0 -58
  238. package/src/lib/parse.keypress-kitty.protocol.test.ts +0 -347
  239. package/src/lib/parse.keypress-kitty.test.ts +0 -712
  240. package/src/lib/parse.keypress-kitty.ts +0 -470
  241. package/src/lib/parse.keypress.test.ts +0 -2020
  242. package/src/lib/parse.keypress.ts +0 -480
  243. package/src/lib/parse.mouse.test.ts +0 -552
  244. package/src/lib/parse.mouse.ts +0 -232
  245. package/src/lib/paste.ts +0 -18
  246. package/src/lib/queue.ts +0 -65
  247. package/src/lib/render-geometry.ts +0 -36
  248. package/src/lib/renderable.validations.test.ts +0 -87
  249. package/src/lib/renderable.validations.ts +0 -83
  250. package/src/lib/scroll-acceleration.ts +0 -98
  251. package/src/lib/selection.ts +0 -261
  252. package/src/lib/singleton.ts +0 -34
  253. package/src/lib/stdin-parser.test.ts +0 -2439
  254. package/src/lib/stdin-parser.ts +0 -2007
  255. package/src/lib/styled-text.ts +0 -178
  256. package/src/lib/terminal-capability-detection.test.ts +0 -226
  257. package/src/lib/terminal-capability-detection.ts +0 -98
  258. package/src/lib/terminal-palette.test.ts +0 -954
  259. package/src/lib/terminal-palette.ts +0 -441
  260. package/src/lib/tree-sitter/assets/README.md +0 -119
  261. package/src/lib/tree-sitter/assets/update.ts +0 -360
  262. package/src/lib/tree-sitter/assets.d.ts +0 -9
  263. package/src/lib/tree-sitter/cache.test.ts +0 -291
  264. package/src/lib/tree-sitter/client.test.ts +0 -1434
  265. package/src/lib/tree-sitter/client.ts +0 -847
  266. package/src/lib/tree-sitter/default-parsers.ts +0 -133
  267. package/src/lib/tree-sitter/download-utils.ts +0 -148
  268. package/src/lib/tree-sitter/index.ts +0 -75
  269. package/src/lib/tree-sitter/parser.worker.ts +0 -1098
  270. package/src/lib/tree-sitter/parsers-config.ts +0 -81
  271. package/src/lib/tree-sitter/resolve-ft.test.ts +0 -55
  272. package/src/lib/tree-sitter/resolve-ft.ts +0 -189
  273. package/src/lib/tree-sitter/types.ts +0 -132
  274. package/src/lib/tree-sitter/update-assets.ts +0 -10
  275. package/src/lib/tree-sitter-styled-text.test.ts +0 -1253
  276. package/src/lib/tree-sitter-styled-text.ts +0 -314
  277. package/src/lib/validate-dir-name.ts +0 -55
  278. package/src/lib/yoga.options.test.ts +0 -628
  279. package/src/lib/yoga.options.ts +0 -346
  280. package/src/native-event-worker-repro.test.ts +0 -48
  281. package/src/native-event-worker-repro.worker.ts +0 -9
  282. package/src/native-handle.test.ts +0 -221
  283. package/src/platform/ffi.test.ts +0 -516
  284. package/src/platform/ffi.ts +0 -653
  285. package/src/platform/runtime.test.ts +0 -52
  286. package/src/platform/runtime.ts +0 -121
  287. package/src/platform/test.ts +0 -45
  288. package/src/platform/worker-handler-cleanup.fixture.ts +0 -12
  289. package/src/platform/worker-onmessage-startup.fixture.ts +0 -10
  290. package/src/platform/worker-startup.fixture.ts +0 -9
  291. package/src/platform/worker.node-test.ts +0 -153
  292. package/src/platform/worker.ts +0 -425
  293. package/src/plugins/core-slot.ts +0 -579
  294. package/src/plugins/registry.ts +0 -402
  295. package/src/plugins/types.ts +0 -46
  296. package/src/post/effects.ts +0 -948
  297. package/src/post/filters.ts +0 -512
  298. package/src/post/matrices.ts +0 -288
  299. package/src/renderables/ASCIIFont.ts +0 -219
  300. package/src/renderables/Box.test.ts +0 -474
  301. package/src/renderables/Box.ts +0 -353
  302. package/src/renderables/Code.test.ts +0 -2388
  303. package/src/renderables/Code.ts +0 -555
  304. package/src/renderables/Diff.regression.test.ts +0 -381
  305. package/src/renderables/Diff.test.ts +0 -3212
  306. package/src/renderables/Diff.ts +0 -1278
  307. package/src/renderables/EditBufferRenderable.test.ts +0 -288
  308. package/src/renderables/EditBufferRenderable.ts +0 -1152
  309. package/src/renderables/FrameBuffer.ts +0 -47
  310. package/src/renderables/Input.test.ts +0 -1310
  311. package/src/renderables/Input.ts +0 -273
  312. package/src/renderables/LineNumberRenderable.ts +0 -725
  313. package/src/renderables/Markdown.ts +0 -2144
  314. package/src/renderables/ScrollBar.ts +0 -423
  315. package/src/renderables/ScrollBox.ts +0 -903
  316. package/src/renderables/Select.test.ts +0 -1134
  317. package/src/renderables/Select.ts +0 -535
  318. package/src/renderables/Slider.test.ts +0 -456
  319. package/src/renderables/Slider.ts +0 -342
  320. package/src/renderables/TabSelect.test.ts +0 -238
  321. package/src/renderables/TabSelect.ts +0 -447
  322. package/src/renderables/Text.selection-buffer.test.ts +0 -118
  323. package/src/renderables/Text.test.ts +0 -2662
  324. package/src/renderables/Text.ts +0 -147
  325. package/src/renderables/TextBufferRenderable.ts +0 -504
  326. package/src/renderables/TextNode.test.ts +0 -1137
  327. package/src/renderables/TextNode.ts +0 -379
  328. package/src/renderables/TextTable.test.ts +0 -1411
  329. package/src/renderables/TextTable.ts +0 -1434
  330. package/src/renderables/Textarea.ts +0 -425
  331. package/src/renderables/TimeToFirstDraw.ts +0 -89
  332. package/src/renderables/__snapshots__/Code.test.ts.snap +0 -13
  333. package/src/renderables/__snapshots__/Diff.test.ts.snap +0 -785
  334. package/src/renderables/__snapshots__/Text.test.ts.snap +0 -421
  335. package/src/renderables/__snapshots__/TextTable.test.ts.snap +0 -215
  336. package/src/renderables/__tests__/Code.test.ts +0 -55
  337. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +0 -144
  338. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +0 -827
  339. package/src/renderables/__tests__/LineNumberRenderable.test.ts +0 -1906
  340. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +0 -85
  341. package/src/renderables/__tests__/Markdown.code-colors.test.ts +0 -288
  342. package/src/renderables/__tests__/Markdown.test.ts +0 -4175
  343. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +0 -87
  344. package/src/renderables/__tests__/Textarea.buffer.test.ts +0 -683
  345. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +0 -675
  346. package/src/renderables/__tests__/Textarea.editing.test.ts +0 -2120
  347. package/src/renderables/__tests__/Textarea.error-handling.test.ts +0 -35
  348. package/src/renderables/__tests__/Textarea.events.test.ts +0 -738
  349. package/src/renderables/__tests__/Textarea.highlights.test.ts +0 -590
  350. package/src/renderables/__tests__/Textarea.keybinding.test.ts +0 -3275
  351. package/src/renderables/__tests__/Textarea.paste.test.ts +0 -357
  352. package/src/renderables/__tests__/Textarea.rendering.test.ts +0 -1927
  353. package/src/renderables/__tests__/Textarea.scroll.test.ts +0 -733
  354. package/src/renderables/__tests__/Textarea.selection.test.ts +0 -1589
  355. package/src/renderables/__tests__/Textarea.stress.test.ts +0 -670
  356. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +0 -383
  357. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +0 -310
  358. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +0 -221
  359. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +0 -89
  360. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +0 -457
  361. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +0 -158
  362. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +0 -387
  363. package/src/renderables/__tests__/markdown-parser.test.ts +0 -241
  364. package/src/renderables/__tests__/renderable-test-utils.ts +0 -60
  365. package/src/renderables/composition/README.md +0 -8
  366. package/src/renderables/composition/VRenderable.ts +0 -32
  367. package/src/renderables/composition/constructs.ts +0 -127
  368. package/src/renderables/composition/vnode.ts +0 -277
  369. package/src/renderables/index.ts +0 -23
  370. package/src/renderables/markdown-parser.ts +0 -79
  371. package/src/renderer-theme-mode.ts +0 -199
  372. package/src/renderer.ts +0 -4975
  373. package/src/runtime-plugin-support-configure.ts +0 -63
  374. package/src/runtime-plugin-support.ts +0 -13
  375. package/src/runtime-plugin.ts +0 -626
  376. package/src/specs/terminal-startup.md +0 -64
  377. package/src/syntax-style.test.ts +0 -841
  378. package/src/syntax-style.ts +0 -274
  379. package/src/testing/README.md +0 -219
  380. package/src/testing/bun-test-node.ts +0 -880
  381. package/src/testing/capture-spans.test.ts +0 -216
  382. package/src/testing/integration.test.ts +0 -276
  383. package/src/testing/manual-clock.ts +0 -117
  384. package/src/testing/mock-keys.test.ts +0 -1378
  385. package/src/testing/mock-keys.ts +0 -457
  386. package/src/testing/mock-mouse.test.ts +0 -218
  387. package/src/testing/mock-mouse.ts +0 -247
  388. package/src/testing/mock-tree-sitter-client.ts +0 -81
  389. package/src/testing/spy.ts +0 -13
  390. package/src/testing/terminal-capabilities.ts +0 -47
  391. package/src/testing/test-recorder.test.ts +0 -410
  392. package/src/testing/test-recorder.ts +0 -133
  393. package/src/testing/test-renderer.ts +0 -375
  394. package/src/testing/test-renderer.wait.test.ts +0 -278
  395. package/src/testing/test-streams.ts +0 -31
  396. package/src/testing.ts +0 -9
  397. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +0 -481
  398. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +0 -19
  399. package/src/tests/__snapshots__/scrollbox.test.ts.snap +0 -29
  400. package/src/tests/absolute-positioning.snapshot.test.ts +0 -638
  401. package/src/tests/allocator-stats.test.ts +0 -53
  402. package/src/tests/audio.test.ts +0 -303
  403. package/src/tests/destroy-during-render.test.ts +0 -200
  404. package/src/tests/destroy-on-exit.fixture.ts +0 -36
  405. package/src/tests/destroy-on-exit.test.ts +0 -62
  406. package/src/tests/ffi-borrowed-pointer-callsites.test.ts +0 -153
  407. package/src/tests/hover-cursor.test.ts +0 -98
  408. package/src/tests/native-backed-measurement-lifecycle.test.ts +0 -133
  409. package/src/tests/native-backed-measurement-parity.test.ts +0 -322
  410. package/src/tests/native-span-feed-async.test.ts +0 -173
  411. package/src/tests/native-span-feed-close.test.ts +0 -120
  412. package/src/tests/native-span-feed-coverage.test.ts +0 -227
  413. package/src/tests/native-span-feed-edge-cases.test.ts +0 -384
  414. package/src/tests/native-span-feed-use-after-free.test.ts +0 -45
  415. package/src/tests/opacity.test.ts +0 -123
  416. package/src/tests/renderable.snapshot.test.ts +0 -524
  417. package/src/tests/renderable.test.ts +0 -1851
  418. package/src/tests/renderer.clock.test.ts +0 -270
  419. package/src/tests/renderer.console-startup.test.ts +0 -2151
  420. package/src/tests/renderer.control.test.ts +0 -458
  421. package/src/tests/renderer.core-slot-binding.test.ts +0 -962
  422. package/src/tests/renderer.cursor.test.ts +0 -26
  423. package/src/tests/renderer.custom-stdout.test.ts +0 -1112
  424. package/src/tests/renderer.destroy-during-render.test.ts +0 -147
  425. package/src/tests/renderer.focus-restore.test.ts +0 -257
  426. package/src/tests/renderer.focus.test.ts +0 -329
  427. package/src/tests/renderer.idle.test.ts +0 -219
  428. package/src/tests/renderer.input.test.ts +0 -2615
  429. package/src/tests/renderer.kitty-flags.test.ts +0 -195
  430. package/src/tests/renderer.lifecycle.test.ts +0 -34
  431. package/src/tests/renderer.mouse.test.ts +0 -1315
  432. package/src/tests/renderer.notifications.test.ts +0 -27
  433. package/src/tests/renderer.palette.test.ts +0 -1199
  434. package/src/tests/renderer.remote.test.ts +0 -247
  435. package/src/tests/renderer.render-stats.test.ts +0 -146
  436. package/src/tests/renderer.scrollback-surface.test.ts +0 -474
  437. package/src/tests/renderer.selection.test.ts +0 -138
  438. package/src/tests/renderer.slot-registry.test.ts +0 -684
  439. package/src/tests/renderer.tracker.test.ts +0 -202
  440. package/src/tests/renderer.useMouse.test.ts +0 -83
  441. package/src/tests/runtime-plugin-node-modules-cycle.fixture.ts +0 -76
  442. package/src/tests/runtime-plugin-node-modules-import-like-string.fixture.ts +0 -48
  443. package/src/tests/runtime-plugin-node-modules-mjs.fixture.ts +0 -43
  444. package/src/tests/runtime-plugin-node-modules-no-bare-rewrite.fixture.ts +0 -67
  445. package/src/tests/runtime-plugin-node-modules-package-type-cache.fixture.ts +0 -72
  446. package/src/tests/runtime-plugin-node-modules-runtime-specifier.fixture.ts +0 -44
  447. package/src/tests/runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts +0 -85
  448. package/src/tests/runtime-plugin-path-alias.fixture.ts +0 -43
  449. package/src/tests/runtime-plugin-resolve-roots.fixture.ts +0 -65
  450. package/src/tests/runtime-plugin-support-configure.fixture.ts +0 -31
  451. package/src/tests/runtime-plugin-support-late-addition.fixture.ts +0 -17
  452. package/src/tests/runtime-plugin-support.fixture.ts +0 -11
  453. package/src/tests/runtime-plugin-support.test.ts +0 -54
  454. package/src/tests/runtime-plugin-windows-file-url.fixture.ts +0 -30
  455. package/src/tests/runtime-plugin.fixture.ts +0 -40
  456. package/src/tests/runtime-plugin.test.ts +0 -369
  457. package/src/tests/scrollbox-culling-bug.test.ts +0 -114
  458. package/src/tests/scrollbox-hitgrid-resize.test.ts +0 -136
  459. package/src/tests/scrollbox-hitgrid.test.ts +0 -909
  460. package/src/tests/scrollbox.test.ts +0 -1895
  461. package/src/tests/wrap-resize-perf.test.ts +0 -276
  462. package/src/tests/yoga-api-coverage.test.ts +0 -409
  463. package/src/tests/yoga-callback-stress.test.ts +0 -122
  464. package/src/tests/yoga-ffi.test.ts +0 -117
  465. package/src/tests/yoga-setters.test.ts +0 -921
  466. package/src/tests/yoga-upstream/YGAlignBaselineTest.test.ts +0 -124
  467. package/src/tests/yoga-upstream/YGComputedBorderTest.test.ts +0 -27
  468. package/src/tests/yoga-upstream/YGComputedMarginTest.test.ts +0 -27
  469. package/src/tests/yoga-upstream/YGComputedPaddingTest.test.ts +0 -27
  470. package/src/tests/yoga-upstream/YGDirtiedTest.test.ts +0 -157
  471. package/src/tests/yoga-upstream/YGErrataTest.test.ts +0 -40
  472. package/src/tests/yoga-upstream/YGFlexBasisAuto.test.ts +0 -23
  473. package/src/tests/yoga-upstream/YGHasNewLayout.test.ts +0 -81
  474. package/src/tests/yoga-upstream/YGMeasureCacheTest.test.ts +0 -31
  475. package/src/tests/yoga-upstream/YGMeasureTest.test.ts +0 -70
  476. package/src/tests/yoga-upstream/generated/YGAbsolutePositionTest.test.ts +0 -1864
  477. package/src/tests/yoga-upstream/generated/YGAlignContentTest.test.ts +0 -5829
  478. package/src/tests/yoga-upstream/generated/YGAlignItemsTest.test.ts +0 -2444
  479. package/src/tests/yoga-upstream/generated/YGAlignSelfTest.test.ts +0 -293
  480. package/src/tests/yoga-upstream/generated/YGAndroidNewsFeed.test.ts +0 -315
  481. package/src/tests/yoga-upstream/generated/YGAspectRatioTest.test.ts +0 -231
  482. package/src/tests/yoga-upstream/generated/YGAutoTest.test.ts +0 -347
  483. package/src/tests/yoga-upstream/generated/YGBorderTest.test.ts +0 -256
  484. package/src/tests/yoga-upstream/generated/YGBoxSizingTest.test.ts +0 -2747
  485. package/src/tests/yoga-upstream/generated/YGDimensionTest.test.ts +0 -129
  486. package/src/tests/yoga-upstream/generated/YGDisplayContentsTest.test.ts +0 -109
  487. package/src/tests/yoga-upstream/generated/YGDisplayTest.test.ts +0 -1097
  488. package/src/tests/yoga-upstream/generated/YGFlexDirectionTest.test.ts +0 -4562
  489. package/src/tests/yoga-upstream/generated/YGFlexTest.test.ts +0 -677
  490. package/src/tests/yoga-upstream/generated/YGFlexWrapTest.test.ts +0 -2071
  491. package/src/tests/yoga-upstream/generated/YGGapTest.test.ts +0 -3303
  492. package/src/tests/yoga-upstream/generated/YGIntrinsicSizeTest.test.ts +0 -582
  493. package/src/tests/yoga-upstream/generated/YGJustifyContentTest.test.ts +0 -2150
  494. package/src/tests/yoga-upstream/generated/YGMarginTest.test.ts +0 -1963
  495. package/src/tests/yoga-upstream/generated/YGMinMaxDimensionTest.test.ts +0 -1446
  496. package/src/tests/yoga-upstream/generated/YGPaddingTest.test.ts +0 -354
  497. package/src/tests/yoga-upstream/generated/YGPercentageTest.test.ts +0 -1760
  498. package/src/tests/yoga-upstream/generated/YGRoundingTest.test.ts +0 -1161
  499. package/src/tests/yoga-upstream/generated/YGSizeOverflowTest.test.ts +0 -207
  500. package/src/tests/yoga-upstream/generated/YGStaticPositionTest.test.ts +0 -6338
  501. package/src/tests/yoga-upstream/tools/MeasureCounter.ts +0 -54
  502. package/src/tests/yoga-upstream/tools/utils.ts +0 -81
  503. package/src/text-buffer-view.test.ts +0 -722
  504. package/src/text-buffer-view.ts +0 -193
  505. package/src/text-buffer.test.ts +0 -512
  506. package/src/text-buffer.ts +0 -250
  507. package/src/types.ts +0 -199
  508. package/src/utils.ts +0 -88
  509. package/src/yoga.ts +0 -1146
  510. package/src/zig/ansi.zig +0 -502
  511. package/src/zig/audio.zig +0 -1206
  512. package/src/zig/bench/README.md +0 -50
  513. package/src/zig/bench/buffer-color-blending_bench.zig +0 -350
  514. package/src/zig/bench/buffer-draw-box_bench.zig +0 -786
  515. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +0 -894
  516. package/src/zig/bench/edit-buffer_bench.zig +0 -476
  517. package/src/zig/bench/editor-view_bench.zig +0 -169
  518. package/src/zig/bench/native-span-feed_bench.zig +0 -107
  519. package/src/zig/bench/rope-markers_bench.zig +0 -713
  520. package/src/zig/bench/rope_bench.zig +0 -514
  521. package/src/zig/bench/styled-text_bench.zig +0 -476
  522. package/src/zig/bench/text-buffer-coords_bench.zig +0 -362
  523. package/src/zig/bench/text-buffer-view_bench.zig +0 -459
  524. package/src/zig/bench/text-chunk-graphemes_bench.zig +0 -272
  525. package/src/zig/bench/utf8_bench.zig +0 -799
  526. package/src/zig/bench-utils.zig +0 -431
  527. package/src/zig/bench.zig +0 -223
  528. package/src/zig/buffer-methods.zig +0 -215
  529. package/src/zig/buffer.zig +0 -2515
  530. package/src/zig/build.zig +0 -700
  531. package/src/zig/build.zig.zon +0 -19
  532. package/src/zig/edit-buffer.zig +0 -900
  533. package/src/zig/editor-view.zig +0 -812
  534. package/src/zig/event-bus.zig +0 -28
  535. package/src/zig/event-emitter.zig +0 -65
  536. package/src/zig/file-logger.zig +0 -92
  537. package/src/zig/grapheme.zig +0 -838
  538. package/src/zig/handles.zig +0 -267
  539. package/src/zig/lib.zig +0 -2813
  540. package/src/zig/link.zig +0 -349
  541. package/src/zig/logger.zig +0 -43
  542. package/src/zig/mem-registry.zig +0 -126
  543. package/src/zig/miniaudio_shim.c +0 -21
  544. package/src/zig/native-renderable.zig +0 -112
  545. package/src/zig/native-span-feed-bench-lib.zig +0 -7
  546. package/src/zig/native-span-feed.zig +0 -747
  547. package/src/zig/renderer-output.zig +0 -677
  548. package/src/zig/renderer.zig +0 -2106
  549. package/src/zig/rope.zig +0 -1220
  550. package/src/zig/split-scrollback.zig +0 -88
  551. package/src/zig/syntax-style.zig +0 -174
  552. package/src/zig/terminal.zig +0 -1652
  553. package/src/zig/test.zig +0 -82
  554. package/src/zig/tests/README.md +0 -18
  555. package/src/zig/tests/ansi_test.zig +0 -18
  556. package/src/zig/tests/audio_test.zig +0 -439
  557. package/src/zig/tests/buffer-methods_test.zig +0 -1111
  558. package/src/zig/tests/buffer_test.zig +0 -2926
  559. package/src/zig/tests/edit-buffer-history_test.zig +0 -299
  560. package/src/zig/tests/edit-buffer_test.zig +0 -1688
  561. package/src/zig/tests/editor-view_test.zig +0 -3454
  562. package/src/zig/tests/event-emitter_test.zig +0 -249
  563. package/src/zig/tests/grapheme_test.zig +0 -1329
  564. package/src/zig/tests/handles_test.zig +0 -123
  565. package/src/zig/tests/link_test.zig +0 -220
  566. package/src/zig/tests/mem-registry_test.zig +0 -473
  567. package/src/zig/tests/memory_leak_regression_test.zig +0 -234
  568. package/src/zig/tests/native-renderable_test.zig +0 -16
  569. package/src/zig/tests/native-span-feed_test.zig +0 -1266
  570. package/src/zig/tests/renderer_test.zig +0 -2604
  571. package/src/zig/tests/rope-nested_test.zig +0 -712
  572. package/src/zig/tests/rope_fuzz_test.zig +0 -238
  573. package/src/zig/tests/rope_test.zig +0 -2362
  574. package/src/zig/tests/segment-merge.test.zig +0 -148
  575. package/src/zig/tests/split-scrollback_test.zig +0 -70
  576. package/src/zig/tests/syntax-style_test.zig +0 -558
  577. package/src/zig/tests/terminal_test.zig +0 -1489
  578. package/src/zig/tests/test-renderer.zig +0 -126
  579. package/src/zig/tests/text-buffer-drawing_test.zig +0 -3291
  580. package/src/zig/tests/text-buffer-highlights_test.zig +0 -706
  581. package/src/zig/tests/text-buffer-iterators_test.zig +0 -776
  582. package/src/zig/tests/text-buffer-segment_test.zig +0 -320
  583. package/src/zig/tests/text-buffer-selection_test.zig +0 -1056
  584. package/src/zig/tests/text-buffer-selection_viewport_test.zig +0 -358
  585. package/src/zig/tests/text-buffer-view_test.zig +0 -3672
  586. package/src/zig/tests/text-buffer_test.zig +0 -2191
  587. package/src/zig/tests/unicode-width-map.zon +0 -3909
  588. package/src/zig/tests/utf8_no_zwj_test.zig +0 -260
  589. package/src/zig/tests/utf8_test.zig +0 -4060
  590. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +0 -267
  591. package/src/zig/tests/utf8_wcwidth_test.zig +0 -357
  592. package/src/zig/tests/word-wrap-editing_test.zig +0 -498
  593. package/src/zig/tests/wrap-cache-perf_test.zig +0 -113
  594. package/src/zig/tests/yoga_test.zig +0 -65
  595. package/src/zig/text-buffer-iterators.zig +0 -496
  596. package/src/zig/text-buffer-segment.zig +0 -403
  597. package/src/zig/text-buffer-view.zig +0 -1428
  598. package/src/zig/text-buffer.zig +0 -1272
  599. package/src/zig/utf8.zig +0 -1954
  600. package/src/zig/utils.zig +0 -12
  601. package/src/zig/uucode-stub.zig +0 -76
  602. package/src/zig/vendor/miniaudio/miniaudio.h +0 -93468
  603. package/src/zig/yoga.zig +0 -658
  604. package/src/zig-structs.ts +0 -381
  605. package/src/zig.ts +0 -5260
  606. package/tsconfig.build.json +0 -17
  607. package/tsconfig.json +0 -27
  608. package/tsconfig.node-test.json +0 -138
  609. /package/{src/lib/tree-sitter/assets → assets}/javascript/highlights.scm +0 -0
  610. /package/{src/lib/tree-sitter/assets → assets}/javascript/tree-sitter-javascript.wasm +0 -0
  611. /package/{src/lib/tree-sitter/assets → assets}/markdown/highlights.scm +0 -0
  612. /package/{src/lib/tree-sitter/assets → assets}/markdown/injections.scm +0 -0
  613. /package/{src/lib/tree-sitter/assets → assets}/markdown/tree-sitter-markdown.wasm +0 -0
  614. /package/{src/lib/tree-sitter/assets → assets}/markdown_inline/highlights.scm +0 -0
  615. /package/{src/lib/tree-sitter/assets → assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  616. /package/{src/lib/tree-sitter/assets → assets}/typescript/highlights.scm +0 -0
  617. /package/{src/lib/tree-sitter/assets → assets}/typescript/tree-sitter-typescript.wasm +0 -0
  618. /package/{src/lib/tree-sitter/assets → assets}/zig/highlights.scm +0 -0
  619. /package/{src/lib/tree-sitter/assets → assets}/zig/tree-sitter-zig.wasm +0 -0
package/src/zig/lib.zig DELETED
@@ -1,2813 +0,0 @@
1
- const std = @import("std");
2
- const build_options = @import("build_options");
3
- const Allocator = std.mem.Allocator;
4
-
5
- const ansi = @import("ansi.zig");
6
- const buffer = @import("buffer.zig");
7
- const renderer = @import("renderer.zig");
8
- const gp = @import("grapheme.zig");
9
- const link = @import("link.zig");
10
- const text_buffer = @import("text-buffer.zig");
11
- const text_buffer_view = @import("text-buffer-view.zig");
12
- const text_buffer_iterators = @import("text-buffer-iterators.zig");
13
- const edit_buffer_mod = @import("edit-buffer.zig");
14
- const editor_view = @import("editor-view.zig");
15
- const syntax_style = @import("syntax-style.zig");
16
- const terminal = @import("terminal.zig");
17
- const utf8 = @import("utf8.zig");
18
- const logger = @import("logger.zig");
19
- const event_bus = @import("event-bus.zig");
20
- const native_span_feed = @import("native-span-feed.zig");
21
- const native_audio = @import("audio.zig");
22
- const native_renderable = @import("native-renderable.zig");
23
- const buffer_effects = @import("buffer-methods.zig");
24
- const handles = @import("handles.zig");
25
- const native_yoga = @import("yoga.zig");
26
-
27
- pub const OptimizedBuffer = buffer.OptimizedBuffer;
28
- pub const CliRenderer = renderer.CliRenderer;
29
- pub const Terminal = terminal.Terminal;
30
- pub const RGBA = buffer.RGBA;
31
- pub const NativeHandle = handles.Handle;
32
-
33
- const INVALID_HANDLE: NativeHandle = 0;
34
- const EMPTY_U8 = [_]u8{0};
35
- const EMPTY_U32 = [_]u32{0};
36
-
37
- fn ptrToRGBA(color: [*]const u16) RGBA {
38
- return .{ color[0], color[1], color[2], color[3] };
39
- }
40
-
41
- fn optionalPtrToRGBA(color: ?[*]const u16) ?RGBA {
42
- if (color) |packed_color| {
43
- return ptrToRGBA(packed_color);
44
- }
45
-
46
- return null;
47
- }
48
-
49
- fn erasePtr(ptr_value: anytype) *anyopaque {
50
- return @ptrCast(ptr_value);
51
- }
52
-
53
- fn acquireRenderer(handle: NativeHandle) ?*renderer.CliRenderer {
54
- return handles.acquire(handle, .renderer, renderer.CliRenderer);
55
- }
56
-
57
- fn acquireBuffer(handle: NativeHandle) ?*buffer.OptimizedBuffer {
58
- return handles.acquire(handle, .optimized_buffer, buffer.OptimizedBuffer);
59
- }
60
-
61
- fn acquireTextBuffer(handle: NativeHandle) ?*text_buffer.UnifiedTextBuffer {
62
- return handles.acquire(handle, .text_buffer, text_buffer.UnifiedTextBuffer);
63
- }
64
-
65
- fn acquireTextBufferView(handle: NativeHandle) ?*text_buffer_view.UnifiedTextBufferView {
66
- return handles.acquire(handle, .text_buffer_view, text_buffer_view.UnifiedTextBufferView);
67
- }
68
-
69
- fn acquireEditBuffer(handle: NativeHandle) ?*edit_buffer_mod.EditBuffer {
70
- return handles.acquire(handle, .edit_buffer, edit_buffer_mod.EditBuffer);
71
- }
72
-
73
- fn acquireEditorView(handle: NativeHandle) ?*editor_view.EditorView {
74
- return handles.acquire(handle, .editor_view, editor_view.EditorView);
75
- }
76
-
77
- fn acquireSyntaxStyle(handle: NativeHandle) ?*syntax_style.SyntaxStyle {
78
- return handles.acquire(handle, .syntax_style, syntax_style.SyntaxStyle);
79
- }
80
-
81
- fn acquireEventSink(handle: NativeHandle) ?*event_bus.EventSink {
82
- return handles.acquire(handle, .event_sink, event_bus.EventSink);
83
- }
84
-
85
- fn acquireAudioEngine(handle: NativeHandle) ?*native_audio.Engine {
86
- return handles.acquire(handle, .audio_engine, native_audio.Engine);
87
- }
88
-
89
- fn acquireNativeRenderable(handle: NativeHandle) ?*native_renderable.NativeRenderable {
90
- return handles.acquire(handle, .native_renderable, native_renderable.NativeRenderable);
91
- }
92
-
93
- fn emptyLineInfo(outPtr: *ExternalLineInfo) void {
94
- outPtr.* = .{
95
- .start_cols_ptr = EMPTY_U32[0..].ptr,
96
- .start_cols_len = 0,
97
- .width_cols_ptr = EMPTY_U32[0..].ptr,
98
- .width_cols_len = 0,
99
- .sources_ptr = EMPTY_U32[0..].ptr,
100
- .sources_len = 0,
101
- .wraps_ptr = EMPTY_U32[0..].ptr,
102
- .wraps_len = 0,
103
- .width_cols_max = 0,
104
- };
105
- }
106
-
107
- fn sliceFromPtrLen(ptr: ?[*]const u8, len: u32) []const u8 {
108
- if (len == 0) {
109
- return "";
110
- }
111
-
112
- return ptr.?[0..@as(usize, len)];
113
- }
114
-
115
- inline fn selectionStyle(bg: ?RGBA, fg: ?RGBA) text_buffer_view.SelectionStyle {
116
- return .{
117
- .bgColor = bg,
118
- .fgColor = fg,
119
- };
120
- }
121
-
122
- comptime {
123
- _ = native_span_feed;
124
- _ = native_audio;
125
- _ = native_renderable;
126
- _ = native_yoga;
127
- }
128
-
129
- export fn setLogCallback(callback: ?*const fn (level: u8, msgPtr: [*]const u8, msgLen: u32) callconv(.c) void) void {
130
- logger.setLogCallback(callback);
131
- }
132
-
133
- export fn createEventSink(callback: ?event_bus.EventCallback) NativeHandle {
134
- const sink = event_bus.createEventSink(globalAllocator, callback orelse return INVALID_HANDLE) catch return INVALID_HANDLE;
135
- return handles.insert(.event_sink, erasePtr(sink)) catch {
136
- event_bus.destroyEventSink(globalAllocator, sink);
137
- return INVALID_HANDLE;
138
- };
139
- }
140
-
141
- fn clearEditBufferEventSinkRefs(sink: *event_bus.EventSink) void {
142
- var cursor: usize = 1;
143
- while (handles.nextByKind(.edit_buffer, &cursor)) |edit_handle| {
144
- const token = handles.pause(edit_handle, .edit_buffer, edit_buffer_mod.EditBuffer) orelse continue;
145
- if (token.ptr.event_sink == sink) {
146
- token.ptr.event_sink = null;
147
- }
148
- handles.unpause(token.handle);
149
- }
150
- }
151
-
152
- export fn createNativeRenderable() NativeHandle {
153
- const renderable = globalAllocator.create(native_renderable.NativeRenderable) catch return INVALID_HANDLE;
154
- renderable.* = .{};
155
- return handles.insert(.native_renderable, erasePtr(renderable)) catch {
156
- globalAllocator.destroy(renderable);
157
- return INVALID_HANDLE;
158
- };
159
- }
160
-
161
- export fn destroyNativeRenderable(native_renderable_handle: NativeHandle) void {
162
- const token = handles.beginDestroy(native_renderable_handle, .native_renderable, native_renderable.NativeRenderable) orelse return;
163
- token.ptr.deinit();
164
- globalAllocator.destroy(token.ptr);
165
- handles.finishDestroy(token.handle);
166
- }
167
-
168
- export fn nativeRenderableAttachYogaNode(native_renderable_handle: NativeHandle, node: native_yoga.YGNodeRef) bool {
169
- // Temporary bridge: JS-created Renderables still own Yoga nodes, so native
170
- // renderables borrow and attach them after construction. This should go away
171
- // when the renderable tree and Yoga ownership move native-side.
172
- const renderable = acquireNativeRenderable(native_renderable_handle) orelse return false;
173
- if (node == null) return false;
174
- renderable.attachYogaNode(node);
175
- return true;
176
- }
177
-
178
- export fn nativeRenderableSetMeasureTarget(
179
- native_renderable_handle: NativeHandle,
180
- kind: u32,
181
- target_handle: NativeHandle,
182
- ) bool {
183
- const renderable = acquireNativeRenderable(native_renderable_handle) orelse return false;
184
-
185
- // Resolve handles once at setup time. The Yoga measure callback then uses raw
186
- // native pointers and does not pay handle-registry lookup cost on the hot path.
187
- // Kind `none` clears the measure target; unknown kinds are rejected.
188
- const measure_kind: native_renderable.MeasureTargetKind = switch (kind) {
189
- @intFromEnum(native_renderable.MeasureTargetKind.none) => .none,
190
- @intFromEnum(native_renderable.MeasureTargetKind.text_buffer_view) => .text_buffer_view,
191
- @intFromEnum(native_renderable.MeasureTargetKind.editor_view) => .editor_view,
192
- else => return false,
193
- };
194
-
195
- const target: native_renderable.MeasureTarget = switch (measure_kind) {
196
- .none => .none,
197
- .text_buffer_view => .{ .text_buffer_view = acquireTextBufferView(target_handle) orelse return false },
198
- .editor_view => .{ .editor_view = acquireEditorView(target_handle) orelse return false },
199
- };
200
-
201
- renderable.setMeasureTarget(target);
202
- return true;
203
- }
204
-
205
- export fn destroyEventSink(sink_handle: NativeHandle) void {
206
- const token = handles.beginDestroy(sink_handle, .event_sink, event_bus.EventSink) orelse return;
207
- clearEditBufferEventSinkRefs(token.ptr);
208
- event_bus.destroyEventSink(globalAllocator, token.ptr);
209
- handles.finishDestroy(token.handle);
210
- }
211
-
212
- var gpa: std.heap.GeneralPurposeAllocator(.{
213
- .enable_memory_limit = build_options.gpa_safe_stats,
214
- .safety = build_options.gpa_safe_stats,
215
- }) = .{};
216
- const globalAllocator = gpa.allocator();
217
- var arena = std.heap.ArenaAllocator.init(globalAllocator);
218
- const globalArena = arena.allocator();
219
-
220
- pub const ExternalBuildOptions = extern struct {
221
- gpa_safe_stats: bool,
222
- gpa_memory_limit_tracking: bool,
223
- };
224
-
225
- pub const ExternalAllocatorStats = extern struct {
226
- total_requested_bytes: u64,
227
- active_allocations: u64,
228
- small_allocations: u64,
229
- large_allocations: u64,
230
- requested_bytes_valid: bool,
231
- };
232
-
233
- pub const ExternalRenderStats = extern struct {
234
- last_frame_time: f64,
235
- average_frame_time: f64,
236
- render_time: f64,
237
- // ABI names keep stdout terminology for compatibility; the value is the
238
- // backend output write time for stdout, memory, or feed output.
239
- stdout_write_time: f64,
240
- frame_count: u64,
241
- cells_updated: u32,
242
- average_cells_updated: u32,
243
- render_time_valid: bool,
244
- stdout_write_time_valid: bool,
245
- };
246
-
247
- fn toNonNegativeU64(value: anytype) u64 {
248
- const ValueType = @TypeOf(value);
249
-
250
- return switch (@typeInfo(ValueType)) {
251
- .int => |int_info| if (int_info.signedness == .signed) blk: {
252
- const signed_value: i64 = @intCast(value);
253
- if (signed_value <= 0) break :blk 0;
254
- break :blk @intCast(signed_value);
255
- } else @intCast(value),
256
- .comptime_int => blk: {
257
- if (value <= 0) break :blk 0;
258
- break :blk @intCast(value);
259
- },
260
- else => 0,
261
- };
262
- }
263
-
264
- const RequestedBytesInfo = struct {
265
- bytes: u64,
266
- valid: bool,
267
- };
268
-
269
- fn sanitizeRequestedBytes(value: u64) RequestedBytesInfo {
270
- const signed_value: i64 = @bitCast(value);
271
- if (signed_value < 0) {
272
- return .{ .bytes = 0, .valid = false };
273
- }
274
-
275
- return .{ .bytes = @intCast(signed_value), .valid = true };
276
- }
277
-
278
- fn queryStatsField(comptime field_names: []const []const u8) ?u64 {
279
- if (!@hasDecl(@TypeOf(gpa), "queryStats")) {
280
- return null;
281
- }
282
-
283
- const stats = gpa.queryStats();
284
- const StatsType = @TypeOf(stats);
285
-
286
- inline for (field_names) |field_name| {
287
- if (@hasField(StatsType, field_name)) {
288
- return toNonNegativeU64(@field(stats, field_name));
289
- }
290
- }
291
-
292
- return null;
293
- }
294
-
295
- fn getTotalRequestedBytesInfo() RequestedBytesInfo {
296
- if (!build_options.gpa_safe_stats) {
297
- return .{ .bytes = 0, .valid = false };
298
- }
299
-
300
- if (queryStatsField(&.{"total_requested_bytes"})) |value| {
301
- return sanitizeRequestedBytes(value);
302
- }
303
-
304
- if (@hasField(@TypeOf(gpa), "total_requested_bytes")) {
305
- if (@TypeOf(gpa.total_requested_bytes) == void) {
306
- return .{ .bytes = 0, .valid = false };
307
- }
308
-
309
- return sanitizeRequestedBytes(toNonNegativeU64(gpa.total_requested_bytes));
310
- }
311
-
312
- return .{ .bytes = 0, .valid = false };
313
- }
314
-
315
- fn getSmallAllocationCount() u64 {
316
- if (queryStatsField(&.{ "small_allocations", "small_allocation_count" })) |value| {
317
- return value;
318
- }
319
-
320
- var total: u64 = 0;
321
- for (gpa.buckets) |bucket_head| {
322
- var current = bucket_head;
323
- while (current) |bucket| {
324
- const allocated: u64 = @intCast(bucket.allocated_count);
325
- const freed: u64 = @intCast(bucket.freed_count);
326
- if (allocated >= freed) {
327
- total += allocated - freed;
328
- }
329
- current = bucket.next;
330
- }
331
- }
332
-
333
- return total;
334
- }
335
-
336
- fn getLargeAllocationCount() u64 {
337
- if (queryStatsField(&.{ "large_allocations", "large_allocation_count" })) |value| {
338
- return value;
339
- }
340
-
341
- return @intCast(gpa.large_allocations.count());
342
- }
343
-
344
- export fn createNativeSpanFeed(options_ptr: ?*const native_span_feed.Options) ?*native_span_feed.Stream {
345
- return native_span_feed.createNativeSpanFeedWithAllocator(globalAllocator, options_ptr);
346
- }
347
-
348
- export fn createAudioEngine(options_ptr: ?*const native_audio.CreateOptions) NativeHandle {
349
- const engine = native_audio.create(globalAllocator, options_ptr) orelse return INVALID_HANDLE;
350
- return handles.insert(.audio_engine, erasePtr(engine)) catch {
351
- native_audio.destroy(engine);
352
- return INVALID_HANDLE;
353
- };
354
- }
355
-
356
- export fn destroyAudioEngine(engine_handle: NativeHandle) void {
357
- const token = handles.beginDestroy(engine_handle, .audio_engine, native_audio.Engine) orelse return;
358
- native_audio.destroy(token.ptr);
359
- handles.finishDestroy(token.handle);
360
- }
361
-
362
- export fn audioRefreshPlaybackDevices(engine_handle: NativeHandle) i32 {
363
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
364
- return native_audio.refreshPlaybackDevices(object_ptr);
365
- }
366
-
367
- export fn audioGetPlaybackDeviceCount(engine_handle: NativeHandle) u32 {
368
- const object_ptr = acquireAudioEngine(engine_handle) orelse return 0;
369
- return native_audio.getPlaybackDeviceCount(object_ptr);
370
- }
371
-
372
- export fn audioGetPlaybackDeviceName(engine_handle: NativeHandle, index: u32, out_ptr: [*]u8, max_len: u32) u32 {
373
- const object_ptr = acquireAudioEngine(engine_handle) orelse return 0;
374
- return @intCast(native_audio.getPlaybackDeviceName(object_ptr, index, out_ptr, @as(usize, max_len)));
375
- }
376
-
377
- export fn audioIsPlaybackDeviceDefault(engine_handle: NativeHandle, index: u32) bool {
378
- const object_ptr = acquireAudioEngine(engine_handle) orelse return false;
379
- return native_audio.isPlaybackDeviceDefault(object_ptr, index);
380
- }
381
-
382
- export fn audioSelectPlaybackDevice(engine_handle: NativeHandle, index: u32) i32 {
383
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
384
- return native_audio.selectPlaybackDevice(object_ptr, index);
385
- }
386
-
387
- export fn audioClearPlaybackDeviceSelection(engine_handle: NativeHandle) void {
388
- const object_ptr = acquireAudioEngine(engine_handle) orelse return;
389
- native_audio.clearPlaybackDeviceSelection(object_ptr);
390
- }
391
-
392
- export fn audioStart(engine_handle: NativeHandle, options_ptr: ?*const native_audio.StartOptions) i32 {
393
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
394
- return native_audio.start(object_ptr, options_ptr);
395
- }
396
-
397
- export fn audioStartMixer(engine_handle: NativeHandle) i32 {
398
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
399
- return native_audio.startMixer(object_ptr);
400
- }
401
-
402
- export fn audioStop(engine_handle: NativeHandle) i32 {
403
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
404
- return native_audio.stop(object_ptr);
405
- }
406
-
407
- export fn audioLoad(engine_handle: NativeHandle, data_ptr: ?[*]const u8, data_len: u32, out_sound_id: ?*u32) i32 {
408
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
409
- return native_audio.load(object_ptr, data_ptr, @as(usize, data_len), out_sound_id);
410
- }
411
-
412
- export fn audioUnload(engine_handle: NativeHandle, sound_id: u32) i32 {
413
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
414
- return native_audio.unload(object_ptr, sound_id);
415
- }
416
-
417
- export fn audioPlay(engine_handle: NativeHandle, sound_id: u32, options_ptr: ?*const native_audio.VoiceOptions, out_voice_id: ?*u32) i32 {
418
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
419
- return native_audio.play(object_ptr, sound_id, options_ptr, out_voice_id);
420
- }
421
-
422
- export fn audioStopVoice(engine_handle: NativeHandle, voice_id: u32) i32 {
423
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
424
- return native_audio.stopVoice(object_ptr, voice_id);
425
- }
426
-
427
- export fn audioSetVoiceGroup(engine_handle: NativeHandle, voice_id: u32, group_id: u32) i32 {
428
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
429
- return native_audio.setVoiceGroup(object_ptr, voice_id, group_id);
430
- }
431
-
432
- export fn audioCreateGroup(engine_handle: NativeHandle, name_ptr: ?[*]const u8, name_len: u32, out_group_id: ?*u32) i32 {
433
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
434
- return native_audio.createGroup(object_ptr, name_ptr, @as(usize, name_len), out_group_id);
435
- }
436
-
437
- export fn audioSetGroupVolume(engine_handle: NativeHandle, group_id: u32, volume: f32) i32 {
438
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
439
- return native_audio.setGroupVolume(object_ptr, group_id, volume);
440
- }
441
-
442
- export fn audioSetMasterVolume(engine_handle: NativeHandle, volume: f32) i32 {
443
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
444
- return native_audio.setMasterVolume(object_ptr, volume);
445
- }
446
-
447
- export fn audioMixToBuffer(engine_handle: NativeHandle, out_ptr: ?[*]f32, frame_count: u32, channels: u8) i32 {
448
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
449
- return native_audio.mixToBuffer(object_ptr, out_ptr, frame_count, channels);
450
- }
451
-
452
- export fn audioEnableTap(engine_handle: NativeHandle, enabled: bool, capacity_frames: u32) i32 {
453
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
454
- return native_audio.enableTap(object_ptr, enabled, capacity_frames);
455
- }
456
-
457
- export fn audioReadTap(engine_handle: NativeHandle, out_ptr: ?[*]f32, frame_count: u32, channels: u8, out_frames_read: ?*u32) i32 {
458
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
459
- return native_audio.readTap(object_ptr, out_ptr, frame_count, channels, out_frames_read);
460
- }
461
-
462
- export fn audioGetStats(engine_handle: NativeHandle, out_stats: ?*native_audio.Stats) i32 {
463
- const object_ptr = acquireAudioEngine(engine_handle) orelse return native_audio.Status.err_invalid;
464
- return native_audio.getStats(object_ptr, out_stats);
465
- }
466
-
467
- export fn getArenaAllocatedBytes() u64 {
468
- return @intCast(arena.queryCapacity());
469
- }
470
-
471
- export fn getBuildOptions(out_ptr: *ExternalBuildOptions) void {
472
- out_ptr.* = .{
473
- .gpa_safe_stats = build_options.gpa_safe_stats,
474
- .gpa_memory_limit_tracking = build_options.gpa_safe_stats,
475
- };
476
- }
477
-
478
- export fn getAllocatorStats(out_ptr: *ExternalAllocatorStats) void {
479
- const small_allocations = getSmallAllocationCount();
480
- const large_allocations = getLargeAllocationCount();
481
- const active_allocations = small_allocations + large_allocations;
482
- const requested_bytes = getTotalRequestedBytesInfo();
483
-
484
- out_ptr.* = .{
485
- .total_requested_bytes = requested_bytes.bytes,
486
- .active_allocations = active_allocations,
487
- .small_allocations = small_allocations,
488
- .large_allocations = large_allocations,
489
- .requested_bytes_valid = requested_bytes.valid,
490
- };
491
- }
492
-
493
- /// Create a renderer.
494
- ///
495
- /// Output transport selection:
496
- /// - `feedPtr != null`: writes go to the provided NativeSpanFeed stream
497
- /// (FeedBackend), which the TS side pipes onward to a user-supplied Writable
498
- /// - `feedPtr == null`: writes go through a buffered backend selected by
499
- /// `bufferedDestinationKind` (0 = process stdout, 1 = memory)
500
- ///
501
- /// `remoteModeValue` is 0 = auto, 1 = local, 2 = remote. The TS side decides
502
- /// the appropriate default for process stdout, memory output, and feed output.
503
- fn registerRendererBufferHandles(renderer_handle: NativeHandle, rendererPtr: *renderer.CliRenderer) bool {
504
- _ = handles.getOrInsertBorrowed(.optimized_buffer, erasePtr(rendererPtr.getCurrentBuffer()), renderer_handle) catch return false;
505
- _ = handles.getOrInsertBorrowed(.optimized_buffer, erasePtr(rendererPtr.getNextBuffer()), renderer_handle) catch return false;
506
- return true;
507
- }
508
-
509
- export fn createRenderer(
510
- width: u32,
511
- height: u32,
512
- bufferedDestinationKind: u8,
513
- remoteModeValue: u8,
514
- feedPtr: ?*native_span_feed.Stream,
515
- ) NativeHandle {
516
- if (width == 0 or height == 0) {
517
- logger.warn("Invalid renderer dimensions: {}x{}", .{ width, height });
518
- return INVALID_HANDLE;
519
- }
520
-
521
- const remote_mode: terminal.Terminal.RemoteMode = switch (remoteModeValue) {
522
- 0 => .auto,
523
- 1 => .local,
524
- 2 => .remote,
525
- else => .local,
526
- };
527
-
528
- const pool = gp.initGlobalPool(globalArena);
529
- _ = link.initGlobalLinkPool(globalArena);
530
- const output_target: renderer.CliRenderer.OutputTarget = if (feedPtr) |feed|
531
- .{ .feed = feed }
532
- else switch (bufferedDestinationKind) {
533
- 0 => .stdout,
534
- 1 => .memory,
535
- else => {
536
- logger.warn("Invalid buffered destination kind: {}", .{bufferedDestinationKind});
537
- return INVALID_HANDLE;
538
- },
539
- };
540
-
541
- const rendererPtr = renderer.CliRenderer.createWithOptions(globalAllocator, width, height, pool, .{
542
- .remote_mode = remote_mode,
543
- .output = output_target,
544
- }) catch |err| {
545
- logger.err("Failed to create renderer: {}", .{err});
546
- return INVALID_HANDLE;
547
- };
548
-
549
- const renderer_handle = handles.insert(.renderer, erasePtr(rendererPtr)) catch {
550
- rendererPtr.destroy();
551
- return INVALID_HANDLE;
552
- };
553
- if (!registerRendererBufferHandles(renderer_handle, rendererPtr)) {
554
- if (handles.beginDestroy(renderer_handle, .renderer, renderer.CliRenderer)) |token| {
555
- handles.invalidateChildren(token.handle);
556
- rendererPtr.destroy();
557
- handles.finishDestroy(token.handle);
558
- }
559
- return INVALID_HANDLE;
560
- }
561
-
562
- return renderer_handle;
563
- }
564
-
565
- export fn setTerminalEnvVar(renderer_handle: NativeHandle, keyPtr: ?[*]const u8, keyLen: u32, valuePtr: ?[*]const u8, valueLen: u32) bool {
566
- const object_ptr = acquireRenderer(renderer_handle) orelse return false;
567
- const key = sliceFromPtrLen(keyPtr, keyLen);
568
- const value = sliceFromPtrLen(valuePtr, valueLen);
569
- return object_ptr.setTerminalEnvVar(key, value);
570
- }
571
-
572
- export fn setUseThread(renderer_handle: NativeHandle, useThread: bool) void {
573
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
574
- object_ptr.setUseThread(useThread);
575
- }
576
-
577
- export fn setClearOnShutdown(renderer_handle: NativeHandle, clear: bool) void {
578
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
579
- object_ptr.setClearOnShutdown(clear);
580
- }
581
-
582
- export fn destroyRenderer(renderer_handle: NativeHandle) void {
583
- const token = handles.beginDestroy(renderer_handle, .renderer, renderer.CliRenderer) orelse return;
584
- handles.invalidateChildren(token.handle);
585
- token.ptr.destroy();
586
- handles.finishDestroy(token.handle);
587
- }
588
-
589
- export fn setBackgroundColor(renderer_handle: NativeHandle, color: [*]const u16) void {
590
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
591
- object_ptr.setBackgroundColor(ptrToRGBA(color));
592
- }
593
-
594
- export fn setRenderOffset(renderer_handle: NativeHandle, offset: u32) void {
595
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
596
- object_ptr.setRenderOffset(offset);
597
- }
598
-
599
- export fn resetSplitScrollback(renderer_handle: NativeHandle, seedRows: u32, pinnedRenderOffset: u32) u32 {
600
- const object_ptr = acquireRenderer(renderer_handle) orelse return 0;
601
- return object_ptr.resetSplitScrollback(seedRows, pinnedRenderOffset);
602
- }
603
-
604
- export fn syncSplitScrollback(renderer_handle: NativeHandle, pinnedRenderOffset: u32) u32 {
605
- const object_ptr = acquireRenderer(renderer_handle) orelse return 0;
606
- return object_ptr.syncSplitScrollback(pinnedRenderOffset);
607
- }
608
-
609
- export fn getSplitOutputOffset(renderer_handle: NativeHandle, surfaceOffset: u32) u32 {
610
- const object_ptr = acquireRenderer(renderer_handle) orelse return 0;
611
- return object_ptr.getSplitOutputOffset(surfaceOffset);
612
- }
613
-
614
- export fn setPendingSplitFooterTransition(
615
- renderer_handle: NativeHandle,
616
- mode: u8,
617
- sourceTopLine: u32,
618
- sourceHeight: u32,
619
- targetTopLine: u32,
620
- targetHeight: u32,
621
- scrollLines: u32,
622
- ) void {
623
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
624
- object_ptr.setPendingSplitFooterTransition(
625
- @enumFromInt(mode),
626
- sourceTopLine,
627
- sourceHeight,
628
- targetTopLine,
629
- targetHeight,
630
- scrollLines,
631
- );
632
- }
633
-
634
- export fn clearPendingSplitFooterTransition(renderer_handle: NativeHandle) void {
635
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
636
- object_ptr.clearPendingSplitFooterTransition();
637
- }
638
-
639
- export fn updateStats(renderer_handle: NativeHandle, time: f64, fps: u32, frameCallbackTime: f64) void {
640
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
641
- object_ptr.updateStats(time, fps, frameCallbackTime);
642
- }
643
-
644
- export fn updateMemoryStats(renderer_handle: NativeHandle, heapUsed: u32, heapTotal: u32, arrayBuffers: u32) void {
645
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
646
- object_ptr.updateMemoryStats(heapUsed, heapTotal, arrayBuffers);
647
- }
648
-
649
- export fn getRenderStats(renderer_handle: NativeHandle, outPtr: *ExternalRenderStats) void {
650
- const object_ptr = acquireRenderer(renderer_handle) orelse {
651
- outPtr.* = std.mem.zeroes(ExternalRenderStats);
652
- return;
653
- };
654
- const stats = object_ptr.getRenderStats();
655
-
656
- outPtr.* = .{
657
- .last_frame_time = stats.lastFrameTime,
658
- .average_frame_time = stats.averageFrameTime,
659
- .render_time = stats.renderTime orelse 0,
660
- .stdout_write_time = stats.outputWriteTime orelse 0,
661
- .frame_count = stats.frameCount,
662
- .cells_updated = stats.cellsUpdated,
663
- .average_cells_updated = stats.averageCellsUpdated,
664
- .render_time_valid = stats.renderTime != null,
665
- .stdout_write_time_valid = stats.outputWriteTime != null,
666
- };
667
- }
668
-
669
- export fn getNextBuffer(renderer_handle: NativeHandle) NativeHandle {
670
- const object_ptr = acquireRenderer(renderer_handle) orelse return INVALID_HANDLE;
671
- return handles.getOrInsertBorrowed(.optimized_buffer, erasePtr(object_ptr.getNextBuffer()), renderer_handle) catch INVALID_HANDLE;
672
- }
673
-
674
- export fn getCurrentBuffer(renderer_handle: NativeHandle) NativeHandle {
675
- const object_ptr = acquireRenderer(renderer_handle) orelse return INVALID_HANDLE;
676
- return handles.getOrInsertBorrowed(.optimized_buffer, erasePtr(object_ptr.getCurrentBuffer()), renderer_handle) catch INVALID_HANDLE;
677
- }
678
-
679
- export fn setHyperlinksCapability(renderer_handle: NativeHandle, enabled: bool) void {
680
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
681
- object_ptr.terminal.caps.hyperlinks = enabled;
682
- }
683
-
684
- export fn clearGlobalLinkPool() void {
685
- link.deinitGlobalLinkPool();
686
- }
687
-
688
- export fn getBufferWidth(buffer_handle: NativeHandle) u32 {
689
- const object_ptr = acquireBuffer(buffer_handle) orelse return 0;
690
- return object_ptr.width;
691
- }
692
-
693
- export fn getBufferHeight(buffer_handle: NativeHandle) u32 {
694
- const object_ptr = acquireBuffer(buffer_handle) orelse return 0;
695
- return object_ptr.height;
696
- }
697
-
698
- fn packRenderResult(result: renderer.RenderResult) u64 {
699
- return @as(u64, result.renderOffset) | (@as(u64, @intFromEnum(result.status)) << 32);
700
- }
701
-
702
- fn packFailedRenderResult() u64 {
703
- return packRenderResult(.{ .renderOffset = 0, .status = .failed });
704
- }
705
-
706
- export fn render(renderer_handle: NativeHandle, force: bool) u8 {
707
- const object_ptr = acquireRenderer(renderer_handle) orelse return @intFromEnum(renderer.RenderStatus.failed);
708
- return @intFromEnum(object_ptr.render(force));
709
- }
710
-
711
- export fn repaintSplitFooter(
712
- renderer_handle: NativeHandle,
713
- pinnedRenderOffset: u32,
714
- force: bool,
715
- ) u64 {
716
- const object_ptr = acquireRenderer(renderer_handle) orelse return packFailedRenderResult();
717
- return packRenderResult(object_ptr.repaintSplitFooter(pinnedRenderOffset, force));
718
- }
719
-
720
- export fn commitSplitFooterSnapshot(
721
- renderer_handle: NativeHandle,
722
- snapshot_buffer_handle: NativeHandle,
723
- rowColumns: u32,
724
- startOnNewLine: bool,
725
- trailingNewline: bool,
726
- pinnedRenderOffset: u32,
727
- force: bool,
728
- beginFrame: bool,
729
- finalizeFrame: bool,
730
- ) u64 {
731
- const renderer_ptr = acquireRenderer(renderer_handle) orelse return packFailedRenderResult();
732
- const snapshot_ptr = acquireBuffer(snapshot_buffer_handle) orelse return packFailedRenderResult();
733
-
734
- // JS passes rowColumns/startOnNewLine/trailingNewline per commit from
735
- // writeToScrollback or captured stdout chunking. This entrypoint is the ABI
736
- // boundary where that metadata enters the native split append algorithm.
737
- // Route all commits through the batched renderer path so sync/cursor framing
738
- // happens exactly once per JS flush cycle.
739
- if (beginFrame and finalizeFrame) {
740
- return packRenderResult(renderer_ptr.commitSplitFooterSnapshotBatched(
741
- snapshot_ptr,
742
- rowColumns,
743
- startOnNewLine,
744
- trailingNewline,
745
- pinnedRenderOffset,
746
- force,
747
- true,
748
- true,
749
- ));
750
- }
751
-
752
- return packRenderResult(renderer_ptr.commitSplitFooterSnapshotBatched(
753
- snapshot_ptr,
754
- rowColumns,
755
- startOnNewLine,
756
- trailingNewline,
757
- pinnedRenderOffset,
758
- force,
759
- beginFrame,
760
- finalizeFrame,
761
- ));
762
- }
763
-
764
- export fn createOptimizedBuffer(width: u32, height: u32, respectAlpha: bool, widthMethod: u8, idPtr: ?[*]const u8, idLen: u32) NativeHandle {
765
- if (width == 0 or height == 0) {
766
- logger.warn("Invalid buffer dimensions: {}x{}", .{ width, height });
767
- return INVALID_HANDLE;
768
- }
769
-
770
- const pool = gp.initGlobalPool(globalArena);
771
- const link_pool = link.initGlobalLinkPool(globalArena);
772
- const wMethod: utf8.WidthMethod = if (widthMethod == 0) .wcwidth else .unicode;
773
- const id = sliceFromPtrLen(idPtr, idLen);
774
-
775
- const bufferPtr = buffer.OptimizedBuffer.init(globalAllocator, width, height, .{
776
- .respectAlpha = respectAlpha,
777
- .pool = pool,
778
- .width_method = wMethod,
779
- .id = id,
780
- .link_pool = link_pool,
781
- }) catch |err| {
782
- logger.err("Failed to create optimized buffer: {}", .{err});
783
- return INVALID_HANDLE;
784
- };
785
-
786
- return handles.insert(.optimized_buffer, erasePtr(bufferPtr)) catch {
787
- bufferPtr.deinit();
788
- return INVALID_HANDLE;
789
- };
790
- }
791
-
792
- export fn destroyOptimizedBuffer(buffer_handle: NativeHandle) void {
793
- const token = handles.beginDestroy(buffer_handle, .optimized_buffer, buffer.OptimizedBuffer) orelse return;
794
- token.ptr.deinit();
795
- handles.finishDestroy(token.handle);
796
- }
797
-
798
- export fn destroyFrameBuffer(frame_buffer_handle: NativeHandle) void {
799
- destroyOptimizedBuffer(frame_buffer_handle);
800
- }
801
-
802
- export fn drawFrameBuffer(target_handle: NativeHandle, destX: i32, destY: i32, frame_buffer_handle: NativeHandle, sourceX: u32, sourceY: u32, sourceWidth: u32, sourceHeight: u32) void {
803
- const target_ptr = acquireBuffer(target_handle) orelse return;
804
- const frame_ptr = acquireBuffer(frame_buffer_handle) orelse return;
805
- const srcX = if (sourceX == 0) null else sourceX;
806
- const srcY = if (sourceY == 0) null else sourceY;
807
- const srcWidth = if (sourceWidth == 0) null else sourceWidth;
808
- const srcHeight = if (sourceHeight == 0) null else sourceHeight;
809
-
810
- target_ptr.drawFrameBuffer(destX, destY, frame_ptr, srcX, srcY, srcWidth, srcHeight);
811
- }
812
-
813
- export fn setCursorPosition(renderer_handle: NativeHandle, x: i32, y: i32, visible: bool) void {
814
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
815
- object_ptr.terminal.setCursorPosition(@intCast(@max(1, x)), @intCast(@max(1, y)), visible);
816
- }
817
-
818
- pub const ExternalCapabilities = extern struct {
819
- kitty_keyboard: bool,
820
- kitty_graphics: bool,
821
- rgb: bool,
822
- ansi256: bool,
823
- unicode: u8, // 0 = wcwidth, 1 = unicode
824
- sgr_pixels: bool,
825
- color_scheme_updates: bool,
826
- explicit_width: bool,
827
- scaled_text: bool,
828
- sixel: bool,
829
- focus_tracking: bool,
830
- sync: bool,
831
- bracketed_paste: bool,
832
- hyperlinks: bool,
833
- osc52: bool,
834
- notifications: bool,
835
- explicit_cursor_positioning: bool,
836
- remote: bool,
837
- multiplexer: u8,
838
- term_name_ptr: [*]const u8,
839
- term_name_len: usize,
840
- term_version_ptr: [*]const u8,
841
- term_version_len: usize,
842
- term_from_xtversion: bool,
843
- osc52_support: u8,
844
- };
845
-
846
- export fn getTerminalCapabilities(renderer_handle: NativeHandle, capsPtr: *ExternalCapabilities) void {
847
- const object_ptr = acquireRenderer(renderer_handle) orelse {
848
- capsPtr.* = std.mem.zeroes(ExternalCapabilities);
849
- capsPtr.term_name_ptr = EMPTY_U8[0..].ptr;
850
- capsPtr.term_version_ptr = EMPTY_U8[0..].ptr;
851
- return;
852
- };
853
- const caps = object_ptr.getTerminalCapabilities();
854
- const term = &object_ptr.terminal;
855
-
856
- capsPtr.* = .{
857
- .kitty_keyboard = caps.kitty_keyboard,
858
- .kitty_graphics = caps.kitty_graphics,
859
- .rgb = caps.rgb,
860
- .ansi256 = caps.ansi256,
861
- .unicode = if (caps.unicode == .wcwidth) 0 else 1,
862
- .sgr_pixels = caps.sgr_pixels,
863
- .color_scheme_updates = caps.color_scheme_updates,
864
- .explicit_width = caps.explicit_width,
865
- .scaled_text = caps.scaled_text,
866
- .sixel = caps.sixel,
867
- .focus_tracking = caps.focus_tracking,
868
- .sync = caps.sync,
869
- .bracketed_paste = caps.bracketed_paste,
870
- .hyperlinks = caps.hyperlinks,
871
- .osc52 = caps.osc52,
872
- .osc52_support = @intFromEnum(term.osc52_support),
873
- .notifications = caps.notifications,
874
- .explicit_cursor_positioning = caps.explicit_cursor_positioning,
875
- .remote = caps.remote,
876
- .multiplexer = @intFromEnum(term.multiplexer),
877
- .term_name_ptr = &term.term_info.name,
878
- .term_name_len = term.term_info.name_len,
879
- .term_version_ptr = &term.term_info.version,
880
- .term_version_len = term.term_info.version_len,
881
- .term_from_xtversion = term.term_info.from_xtversion,
882
- };
883
- }
884
-
885
- export fn processCapabilityResponse(renderer_handle: NativeHandle, responsePtr: ?[*]const u8, responseLen: u32) void {
886
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
887
- const response = sliceFromPtrLen(responsePtr, responseLen);
888
- object_ptr.processCapabilityResponse(response);
889
- }
890
-
891
- export fn setCursorColor(renderer_handle: NativeHandle, color: [*]const u16) void {
892
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
893
- object_ptr.terminal.setCursorColor(ptrToRGBA(color));
894
- }
895
-
896
- export fn rendererSetPaletteState(
897
- renderer_handle: NativeHandle,
898
- palettePtr: [*]const u16,
899
- paletteLen: u32,
900
- defaultFgPtr: [*]const u16,
901
- defaultBgPtr: [*]const u16,
902
- paletteEpoch: u32,
903
- ) void {
904
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
905
- if (paletteLen < 256) return;
906
-
907
- var palette: [256]renderer.RGBA = undefined;
908
- var index: usize = 0;
909
- while (index < palette.len) : (index += 1) {
910
- const base = index * 4;
911
- palette[index] = .{ palettePtr[base], palettePtr[base + 1], palettePtr[base + 2], palettePtr[base + 3] };
912
- }
913
-
914
- object_ptr.setPaletteState(palette[0..], ptrToRGBA(defaultFgPtr), ptrToRGBA(defaultBgPtr), paletteEpoch);
915
- }
916
-
917
- pub const CursorStyleOptions = extern struct {
918
- style: u8,
919
- blinking: u8,
920
- color: ?[*]const u16,
921
- cursor: u8,
922
- };
923
-
924
- export fn setCursorStyleOptions(renderer_handle: NativeHandle, options: *const CursorStyleOptions) void {
925
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
926
- const current = object_ptr.terminal.getCursorStyle();
927
-
928
- const style = if (options.style <= 3) @as(terminal.CursorStyle, @enumFromInt(options.style)) else current.style;
929
- const blinking = if (options.blinking <= 1) options.blinking == 1 else current.blinking;
930
-
931
- if (options.style <= 3 or options.blinking <= 1) {
932
- object_ptr.terminal.setCursorStyle(style, blinking);
933
- }
934
- if (options.color) |rgba| {
935
- object_ptr.terminal.setCursorColor(ptrToRGBA(rgba));
936
- }
937
- if (options.cursor <= 5) {
938
- object_ptr.terminal.setMousePointerStyle(@enumFromInt(options.cursor));
939
- }
940
- }
941
-
942
- pub const ExternalCursorState = extern struct {
943
- x: u32,
944
- y: u32,
945
- visible: bool,
946
- style: u8,
947
- blinking: bool,
948
- r: f32,
949
- g: f32,
950
- b: f32,
951
- a: f32,
952
- };
953
-
954
- export fn getCursorState(renderer_handle: NativeHandle, outPtr: *ExternalCursorState) void {
955
- const object_ptr = acquireRenderer(renderer_handle) orelse {
956
- outPtr.* = std.mem.zeroes(ExternalCursorState);
957
- return;
958
- };
959
- const pos = object_ptr.terminal.getCursorPosition();
960
- const style = object_ptr.terminal.getCursorStyle();
961
- const color = object_ptr.terminal.getCursorColor();
962
-
963
- const styleTag: u8 = switch (style.style) {
964
- .block => 0,
965
- .line => 1,
966
- .underline => 2,
967
- .default => 3,
968
- };
969
-
970
- outPtr.* = .{
971
- .x = pos.x,
972
- .y = pos.y,
973
- .visible = pos.visible,
974
- .style = styleTag,
975
- .blinking = style.blinking,
976
- .r = ansi.redF(color),
977
- .g = ansi.greenF(color),
978
- .b = ansi.blueF(color),
979
- .a = ansi.alphaF(color),
980
- };
981
- }
982
-
983
- export fn setDebugOverlay(renderer_handle: NativeHandle, enabled: bool, corner: u8) void {
984
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
985
- const cornerEnum: renderer.DebugOverlayCorner = switch (corner) {
986
- 0 => .topLeft,
987
- 1 => .topRight,
988
- 2 => .bottomLeft,
989
- else => .bottomRight,
990
- };
991
-
992
- object_ptr.setDebugOverlay(enabled, cornerEnum);
993
- }
994
-
995
- export fn clearTerminal(renderer_handle: NativeHandle) void {
996
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
997
- object_ptr.clearTerminal();
998
- }
999
-
1000
- export fn setTerminalTitle(renderer_handle: NativeHandle, titlePtr: ?[*]const u8, titleLen: u32) void {
1001
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1002
- const title = sliceFromPtrLen(titlePtr, titleLen);
1003
- object_ptr.setTerminalTitle(title);
1004
- }
1005
-
1006
- export fn copyToClipboardOSC52(renderer_handle: NativeHandle, target: u8, text_ptr: ?[*]const u8, text_len: u32) bool {
1007
- const object_ptr = acquireRenderer(renderer_handle) orelse return false;
1008
- const targetEnum = std.meta.intToEnum(terminal.ClipboardTarget, target) catch .clipboard;
1009
- const text_utf8 = sliceFromPtrLen(text_ptr, text_len);
1010
- return object_ptr.copyToClipboardOSC52(targetEnum, text_utf8);
1011
- }
1012
-
1013
- export fn clearClipboardOSC52(renderer_handle: NativeHandle, target: u8) bool {
1014
- const object_ptr = acquireRenderer(renderer_handle) orelse return false;
1015
- const targetEnum = std.meta.intToEnum(terminal.ClipboardTarget, target) catch .clipboard;
1016
- return object_ptr.clearClipboardOSC52(targetEnum);
1017
- }
1018
-
1019
- export fn triggerNotification(renderer_handle: NativeHandle, messagePtr: [*]const u8, messageLen: u32, titlePtr: ?[*]const u8, titleLen: u32) bool {
1020
- const object_ptr = acquireRenderer(renderer_handle) orelse return false;
1021
- const message = messagePtr[0..@as(usize, messageLen)];
1022
- const title = if (titlePtr) |ptr| ptr[0..@as(usize, titleLen)] else null;
1023
- return object_ptr.triggerNotification(message, title);
1024
- }
1025
-
1026
- // Buffer functions
1027
- export fn bufferClear(buffer_handle: NativeHandle, bg: [*]const u16) void {
1028
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1029
- object_ptr.clear(ptrToRGBA(bg), null);
1030
- }
1031
-
1032
- export fn bufferGetCharPtr(buffer_handle: NativeHandle) ?[*]u32 {
1033
- const object_ptr = acquireBuffer(buffer_handle) orelse return null;
1034
- return object_ptr.getCharPtr();
1035
- }
1036
-
1037
- export fn bufferGetFgPtr(buffer_handle: NativeHandle) ?[*]RGBA {
1038
- const object_ptr = acquireBuffer(buffer_handle) orelse return null;
1039
- return object_ptr.getFgPtr();
1040
- }
1041
-
1042
- export fn bufferGetBgPtr(buffer_handle: NativeHandle) ?[*]RGBA {
1043
- const object_ptr = acquireBuffer(buffer_handle) orelse return null;
1044
- return object_ptr.getBgPtr();
1045
- }
1046
-
1047
- export fn bufferGetAttributesPtr(buffer_handle: NativeHandle) ?[*]u32 {
1048
- const object_ptr = acquireBuffer(buffer_handle) orelse return null;
1049
- return object_ptr.getAttributesPtr();
1050
- }
1051
-
1052
- export fn bufferGetRespectAlpha(buffer_handle: NativeHandle) bool {
1053
- const object_ptr = acquireBuffer(buffer_handle) orelse return false;
1054
- return object_ptr.getRespectAlpha();
1055
- }
1056
-
1057
- export fn bufferSetRespectAlpha(buffer_handle: NativeHandle, respectAlpha: bool) void {
1058
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1059
- object_ptr.setRespectAlpha(respectAlpha);
1060
- }
1061
-
1062
- export fn bufferGetId(buffer_handle: NativeHandle, outPtr: ?[*]u8, maxLen: u32) u32 {
1063
- const object_ptr = acquireBuffer(buffer_handle) orelse return 0;
1064
- if (maxLen == 0) return 0;
1065
-
1066
- const out = outPtr orelse return 0;
1067
- const id = object_ptr.getId();
1068
- const copyLen = @min(id.len, @as(usize, maxLen));
1069
- @memcpy(out[0..copyLen], id[0..copyLen]);
1070
- return @intCast(copyLen);
1071
- }
1072
-
1073
- export fn bufferGetRealCharSize(buffer_handle: NativeHandle) u32 {
1074
- const object_ptr = acquireBuffer(buffer_handle) orelse return 0;
1075
- return object_ptr.getRealCharSize();
1076
- }
1077
-
1078
- export fn bufferWriteResolvedChars(buffer_handle: NativeHandle, outputPtr: ?[*]u8, outputLen: u32, addLineBreaks: bool) u32 {
1079
- const object_ptr = acquireBuffer(buffer_handle) orelse return 0;
1080
- if (outputLen == 0) return 0;
1081
-
1082
- const output = outputPtr orelse return 0;
1083
- const output_slice = output[0..@as(usize, outputLen)];
1084
- return object_ptr.writeResolvedChars(output_slice, addLineBreaks) catch 0;
1085
- }
1086
-
1087
- export fn bufferDrawText(buffer_handle: NativeHandle, text: ?[*]const u8, textLen: u32, x: u32, y: u32, fg: [*]const u16, bg: ?[*]const u16, attributes: u32) void {
1088
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1089
- object_ptr.drawText(
1090
- sliceFromPtrLen(text, textLen),
1091
- x,
1092
- y,
1093
- ptrToRGBA(fg),
1094
- optionalPtrToRGBA(bg),
1095
- attributes,
1096
- ) catch {};
1097
- }
1098
-
1099
- export fn bufferSetCellWithAlphaBlending(buffer_handle: NativeHandle, x: u32, y: u32, char: u32, fg: [*]const u16, bg: [*]const u16, attributes: u32) void {
1100
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1101
- object_ptr.setCellWithAlphaBlending(x, y, char, ptrToRGBA(fg), ptrToRGBA(bg), attributes);
1102
- }
1103
-
1104
- export fn bufferSetCell(buffer_handle: NativeHandle, x: u32, y: u32, char: u32, fg: [*]const u16, bg: [*]const u16, attributes: u32) void {
1105
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1106
- object_ptr.set(x, y, .{
1107
- .char = char,
1108
- .fg = ptrToRGBA(fg),
1109
- .bg = ptrToRGBA(bg),
1110
- .attributes = attributes,
1111
- });
1112
- }
1113
-
1114
- export fn bufferFillRect(buffer_handle: NativeHandle, x: u32, y: u32, width: u32, height: u32, bg: [*]const u16) void {
1115
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1116
- object_ptr.fillRect(x, y, width, height, ptrToRGBA(bg));
1117
- }
1118
-
1119
- export fn bufferColorMatrix(buffer_handle: NativeHandle, matrixPtr: [*]const f32, cellMaskPtr: [*]const f32, cellMaskCount: u32, strength: f32, target: u8) void {
1120
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1121
- if (cellMaskCount == 0) return;
1122
- const matrix = matrixPtr[0..16];
1123
- const len = @as(usize, cellMaskCount) * 3;
1124
- const cellMask = cellMaskPtr[0..len];
1125
- const targetEnum: buffer_effects.ColorTarget = @enumFromInt(target);
1126
- buffer_effects.colorMatrix(object_ptr, matrix, cellMask, strength, targetEnum);
1127
- }
1128
-
1129
- export fn bufferColorMatrixUniform(buffer_handle: NativeHandle, matrixPtr: [*]const f32, strength: f32, target: u8) void {
1130
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1131
- const matrix = matrixPtr[0..16];
1132
- const targetEnum: buffer_effects.ColorTarget = @enumFromInt(target);
1133
- buffer_effects.colorMatrixUniform(object_ptr, matrix, strength, targetEnum);
1134
- }
1135
-
1136
- export fn bufferDrawPackedBuffer(buffer_handle: NativeHandle, data: [*]const u8, dataLen: u32, posX: u32, posY: u32, terminalWidthCells: u32, terminalHeightCells: u32) void {
1137
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1138
- object_ptr.drawPackedBuffer(data, dataLen, posX, posY, terminalWidthCells, terminalHeightCells);
1139
- }
1140
-
1141
- export fn bufferDrawGrayscaleBuffer(buffer_handle: NativeHandle, posX: i32, posY: i32, intensities: [*]const f32, srcWidth: u32, srcHeight: u32, fg: ?[*]const u16, bg: ?[*]const u16) void {
1142
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1143
- object_ptr.drawGrayscaleBuffer(
1144
- posX,
1145
- posY,
1146
- intensities,
1147
- srcWidth,
1148
- srcHeight,
1149
- optionalPtrToRGBA(fg),
1150
- optionalPtrToRGBA(bg),
1151
- );
1152
- }
1153
-
1154
- export fn bufferDrawGrayscaleBufferSupersampled(buffer_handle: NativeHandle, posX: i32, posY: i32, intensities: [*]const f32, srcWidth: u32, srcHeight: u32, fg: ?[*]const u16, bg: ?[*]const u16) void {
1155
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1156
- object_ptr.drawGrayscaleBufferSupersampled(
1157
- posX,
1158
- posY,
1159
- intensities,
1160
- srcWidth,
1161
- srcHeight,
1162
- optionalPtrToRGBA(fg),
1163
- optionalPtrToRGBA(bg),
1164
- );
1165
- }
1166
-
1167
- export fn bufferPushScissorRect(buffer_handle: NativeHandle, x: i32, y: i32, width: u32, height: u32) void {
1168
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1169
- object_ptr.pushScissorRect(x, y, width, height) catch {};
1170
- }
1171
-
1172
- export fn bufferPopScissorRect(buffer_handle: NativeHandle) void {
1173
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1174
- object_ptr.popScissorRect();
1175
- }
1176
-
1177
- export fn bufferClearScissorRects(buffer_handle: NativeHandle) void {
1178
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1179
- object_ptr.clearScissorRects();
1180
- }
1181
-
1182
- // Opacity stack functions
1183
- export fn bufferPushOpacity(buffer_handle: NativeHandle, opacity: f32) void {
1184
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1185
- object_ptr.pushOpacity(opacity) catch {};
1186
- }
1187
-
1188
- export fn bufferPopOpacity(buffer_handle: NativeHandle) void {
1189
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1190
- object_ptr.popOpacity();
1191
- }
1192
-
1193
- export fn bufferGetCurrentOpacity(buffer_handle: NativeHandle) f32 {
1194
- const object_ptr = acquireBuffer(buffer_handle) orelse return 1;
1195
- return object_ptr.getCurrentOpacity();
1196
- }
1197
-
1198
- export fn bufferClearOpacity(buffer_handle: NativeHandle) void {
1199
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1200
- object_ptr.clearOpacity();
1201
- }
1202
-
1203
- export fn bufferDrawSuperSampleBuffer(buffer_handle: NativeHandle, x: u32, y: u32, pixelData: [*]const u8, len: u32, format: u8, alignedBytesPerRow: u32) void {
1204
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1205
- object_ptr.drawSuperSampleBuffer(x, y, pixelData, len, format, alignedBytesPerRow);
1206
- }
1207
-
1208
- export fn linkAlloc(urlPtr: ?[*]const u8, urlLen: u32) u32 {
1209
- const url = sliceFromPtrLen(urlPtr, urlLen);
1210
- const link_pool = link.initGlobalLinkPool(globalArena);
1211
- return link_pool.alloc(url) catch 0;
1212
- }
1213
-
1214
- export fn linkGetUrl(id: u32, outPtr: ?[*]u8, maxLen: u32) u32 {
1215
- if (maxLen == 0) return 0;
1216
-
1217
- const out = outPtr orelse return 0;
1218
- const link_pool = link.initGlobalLinkPool(globalArena);
1219
- const url_bytes = link_pool.get(id) catch return 0;
1220
- const copyLen = @min(url_bytes.len, @as(usize, maxLen));
1221
- @memcpy(out[0..copyLen], url_bytes[0..copyLen]);
1222
- return @intCast(copyLen);
1223
- }
1224
-
1225
- export fn attributesWithLink(baseAttributes: u32, linkId: u32) u32 {
1226
- return ansi.TextAttributes.setLinkId(baseAttributes, linkId);
1227
- }
1228
-
1229
- export fn attributesGetLinkId(attributes: u32) u32 {
1230
- return ansi.TextAttributes.getLinkId(attributes);
1231
- }
1232
-
1233
- pub const ExternalGridDrawOptions = extern struct {
1234
- draw_inner: bool,
1235
- draw_outer: bool,
1236
- };
1237
-
1238
- export fn bufferDrawGrid(
1239
- buffer_handle: NativeHandle,
1240
- borderChars: [*]const u32,
1241
- borderFg: [*]const u16,
1242
- borderBg: [*]const u16,
1243
- columnOffsets: [*]const i32,
1244
- columnCount: u32,
1245
- rowOffsets: [*]const i32,
1246
- rowCount: u32,
1247
- options: *const ExternalGridDrawOptions,
1248
- ) void {
1249
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1250
- object_ptr.drawGrid(
1251
- borderChars,
1252
- ptrToRGBA(borderFg),
1253
- ptrToRGBA(borderBg),
1254
- columnOffsets,
1255
- columnCount,
1256
- rowOffsets,
1257
- rowCount,
1258
- options.draw_inner,
1259
- options.draw_outer,
1260
- );
1261
- }
1262
-
1263
- export fn bufferDrawBox(
1264
- buffer_handle: NativeHandle,
1265
- x: i32,
1266
- y: i32,
1267
- width: u32,
1268
- height: u32,
1269
- borderChars: [*]const u32,
1270
- packedOptions: u32,
1271
- borderColor: [*]const u16,
1272
- backgroundColor: [*]const u16,
1273
- titleColor: [*]const u16,
1274
- title: ?[*]const u8,
1275
- titleLen: u32,
1276
- bottomTitle: ?[*]const u8,
1277
- bottomTitleLen: u32,
1278
- ) void {
1279
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1280
- const borderSides: buffer.BorderSides = .{
1281
- .top = (packedOptions & 0b1000) != 0,
1282
- .right = (packedOptions & 0b0100) != 0,
1283
- .bottom = (packedOptions & 0b0010) != 0,
1284
- .left = (packedOptions & 0b0001) != 0,
1285
- };
1286
-
1287
- const shouldFill = ((packedOptions >> 4) & 1) != 0;
1288
- const titleAlignment = @as(u8, @intCast((packedOptions >> 5) & 0b11));
1289
- const bottomTitleAlignment = @as(u8, @intCast((packedOptions >> 7) & 0b11));
1290
- const titleSlice = if (title) |t| t[0..titleLen] else null;
1291
-
1292
- const bottomTitleSlice = if (bottomTitle) |bt| bt[0..bottomTitleLen] else null;
1293
-
1294
- object_ptr.drawBox(
1295
- x,
1296
- y,
1297
- width,
1298
- height,
1299
- borderChars,
1300
- borderSides,
1301
- ptrToRGBA(borderColor),
1302
- ptrToRGBA(backgroundColor),
1303
- ptrToRGBA(titleColor),
1304
- shouldFill,
1305
- titleSlice,
1306
- titleAlignment,
1307
- bottomTitleSlice,
1308
- bottomTitleAlignment,
1309
- ) catch {};
1310
- }
1311
-
1312
- export fn bufferResize(buffer_handle: NativeHandle, width: u32, height: u32) void {
1313
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
1314
- object_ptr.resize(width, height) catch {};
1315
- }
1316
-
1317
- export fn resizeRenderer(renderer_handle: NativeHandle, width: u32, height: u32) void {
1318
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1319
- object_ptr.resize(width, height) catch {};
1320
- }
1321
-
1322
- export fn addToHitGrid(renderer_handle: NativeHandle, x: i32, y: i32, width: u32, height: u32, id: u32) void {
1323
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1324
- object_ptr.addToHitGrid(x, y, width, height, id);
1325
- }
1326
-
1327
- export fn clearCurrentHitGrid(renderer_handle: NativeHandle) void {
1328
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1329
- object_ptr.clearCurrentHitGrid();
1330
- }
1331
-
1332
- export fn hitGridPushScissorRect(renderer_handle: NativeHandle, x: i32, y: i32, width: u32, height: u32) void {
1333
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1334
- object_ptr.hitGridPushScissorRect(x, y, width, height);
1335
- }
1336
-
1337
- export fn hitGridPopScissorRect(renderer_handle: NativeHandle) void {
1338
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1339
- object_ptr.hitGridPopScissorRect();
1340
- }
1341
-
1342
- export fn hitGridClearScissorRects(renderer_handle: NativeHandle) void {
1343
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1344
- object_ptr.hitGridClearScissorRects();
1345
- }
1346
-
1347
- export fn addToCurrentHitGridClipped(renderer_handle: NativeHandle, x: i32, y: i32, width: u32, height: u32, id: u32) void {
1348
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1349
- object_ptr.addToCurrentHitGridClipped(x, y, width, height, id);
1350
- }
1351
-
1352
- export fn checkHit(renderer_handle: NativeHandle, x: u32, y: u32) u32 {
1353
- const object_ptr = acquireRenderer(renderer_handle) orelse return 0;
1354
- return object_ptr.checkHit(x, y);
1355
- }
1356
-
1357
- export fn getHitGridDirty(renderer_handle: NativeHandle) bool {
1358
- const object_ptr = acquireRenderer(renderer_handle) orelse return false;
1359
- return object_ptr.getHitGridDirty();
1360
- }
1361
-
1362
- export fn dumpHitGrid(renderer_handle: NativeHandle) void {
1363
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1364
- object_ptr.dumpHitGrid();
1365
- }
1366
-
1367
- export fn dumpBuffers(renderer_handle: NativeHandle, timestamp: i64) void {
1368
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1369
- object_ptr.dumpBuffers(timestamp);
1370
- }
1371
-
1372
- export fn dumpOutputBuffer(renderer_handle: NativeHandle, timestamp: i64) void {
1373
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1374
- object_ptr.dumpOutputBuffer(timestamp);
1375
- }
1376
-
1377
- export fn restoreTerminalModes(renderer_handle: NativeHandle) void {
1378
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1379
- object_ptr.restoreTerminalModes();
1380
- }
1381
-
1382
- export fn enableMouse(renderer_handle: NativeHandle, enableMovement: bool) void {
1383
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1384
- object_ptr.enableMouse(enableMovement);
1385
- }
1386
-
1387
- export fn disableMouse(renderer_handle: NativeHandle) void {
1388
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1389
- object_ptr.disableMouse();
1390
- }
1391
-
1392
- export fn queryPixelResolution(renderer_handle: NativeHandle) void {
1393
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1394
- object_ptr.queryPixelResolution();
1395
- }
1396
-
1397
- export fn queryThemeColors(renderer_handle: NativeHandle) void {
1398
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1399
- object_ptr.queryThemeColors();
1400
- }
1401
-
1402
- export fn enableKittyKeyboard(renderer_handle: NativeHandle, flags: u8) void {
1403
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1404
- object_ptr.enableKittyKeyboard(flags);
1405
- }
1406
-
1407
- export fn disableKittyKeyboard(renderer_handle: NativeHandle) void {
1408
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1409
- object_ptr.disableKittyKeyboard();
1410
- }
1411
-
1412
- export fn setKittyKeyboardFlags(renderer_handle: NativeHandle, flags: u8) void {
1413
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1414
- object_ptr.setKittyKeyboardFlags(flags);
1415
- }
1416
-
1417
- export fn getKittyKeyboardFlags(renderer_handle: NativeHandle) u8 {
1418
- const object_ptr = acquireRenderer(renderer_handle) orelse return 0;
1419
- return object_ptr.getKittyKeyboardFlags();
1420
- }
1421
-
1422
- export fn setupTerminal(renderer_handle: NativeHandle, useAlternateScreen: bool) void {
1423
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1424
- object_ptr.setupTerminal(useAlternateScreen);
1425
- }
1426
-
1427
- export fn suspendRenderer(renderer_handle: NativeHandle) void {
1428
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1429
- object_ptr.suspendRenderer();
1430
- }
1431
-
1432
- export fn resumeRenderer(renderer_handle: NativeHandle) void {
1433
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1434
- object_ptr.resumeRenderer();
1435
- }
1436
-
1437
- export fn writeOut(renderer_handle: NativeHandle, dataPtr: ?[*]const u8, dataLen: u32) void {
1438
- const object_ptr = acquireRenderer(renderer_handle) orelse return;
1439
- const data = sliceFromPtrLen(dataPtr, dataLen);
1440
- if (data.len == 0) return;
1441
- object_ptr.writeOut(data);
1442
- }
1443
-
1444
- fn destroyTextBufferViewHandle(view_handle: NativeHandle) void {
1445
- const token = handles.beginDestroy(view_handle, .text_buffer_view, text_buffer_view.UnifiedTextBufferView) orelse return;
1446
- token.ptr.deinit();
1447
- handles.finishDestroy(token.handle);
1448
- }
1449
-
1450
- fn destroyTextBufferViewChildren(owner: NativeHandle) void {
1451
- while (handles.findChild(owner, .text_buffer_view)) |view_handle| {
1452
- destroyTextBufferViewHandle(view_handle);
1453
- }
1454
- }
1455
-
1456
- export fn createTextBuffer(widthMethod: u8) NativeHandle {
1457
- const pool = gp.initGlobalPool(globalArena);
1458
- const link_pool = link.initGlobalLinkPool(globalArena);
1459
- const wMethod: utf8.WidthMethod = if (widthMethod == 0) .wcwidth else .unicode;
1460
-
1461
- const tb = text_buffer.UnifiedTextBuffer.init(globalAllocator, pool, link_pool, wMethod) catch {
1462
- return INVALID_HANDLE;
1463
- };
1464
- return handles.insert(.text_buffer, erasePtr(tb)) catch {
1465
- tb.deinit();
1466
- return INVALID_HANDLE;
1467
- };
1468
- }
1469
-
1470
- export fn destroyTextBuffer(tb_handle: NativeHandle) void {
1471
- const token = handles.beginDestroy(tb_handle, .text_buffer, text_buffer.UnifiedTextBuffer) orelse return;
1472
- destroyTextBufferViewChildren(token.handle);
1473
- token.ptr.deinit();
1474
- handles.finishDestroy(token.handle);
1475
- }
1476
-
1477
- export fn textBufferGetLength(tb_handle: NativeHandle) u32 {
1478
- const object_ptr = acquireTextBuffer(tb_handle) orelse return 0;
1479
- return object_ptr.getLength();
1480
- }
1481
-
1482
- export fn textBufferGetByteSize(tb_handle: NativeHandle) u32 {
1483
- const object_ptr = acquireTextBuffer(tb_handle) orelse return 0;
1484
- return object_ptr.getByteSize();
1485
- }
1486
-
1487
- export fn textBufferReset(tb_handle: NativeHandle) void {
1488
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1489
- object_ptr.reset();
1490
- }
1491
-
1492
- export fn textBufferClear(tb_handle: NativeHandle) void {
1493
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1494
- object_ptr.clear();
1495
- }
1496
-
1497
- export fn textBufferSetDefaultFg(tb_handle: NativeHandle, fg: ?[*]const u16) void {
1498
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1499
- object_ptr.setDefaultFg(optionalPtrToRGBA(fg));
1500
- }
1501
-
1502
- export fn textBufferSetDefaultBg(tb_handle: NativeHandle, bg: ?[*]const u16) void {
1503
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1504
- object_ptr.setDefaultBg(optionalPtrToRGBA(bg));
1505
- }
1506
-
1507
- export fn textBufferSetDefaultAttributes(tb_handle: NativeHandle, attr: ?[*]const u32) void {
1508
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1509
- const attributes = if (attr) |a| a[0] else null;
1510
- object_ptr.setDefaultAttributes(attributes);
1511
- }
1512
-
1513
- export fn textBufferResetDefaults(tb_handle: NativeHandle) void {
1514
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1515
- object_ptr.resetDefaults();
1516
- }
1517
-
1518
- export fn textBufferGetTabWidth(tb_handle: NativeHandle) u8 {
1519
- const object_ptr = acquireTextBuffer(tb_handle) orelse return 0;
1520
- return object_ptr.tabWidth();
1521
- }
1522
-
1523
- export fn textBufferSetTabWidth(tb_handle: NativeHandle, width: u8) void {
1524
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1525
- object_ptr.setTabWidth(width);
1526
- }
1527
-
1528
- export fn textBufferRegisterMemBuffer(tb_handle: NativeHandle, dataPtr: ?[*]const u8, dataLen: u32, owned: bool) u16 {
1529
- const object_ptr = acquireTextBuffer(tb_handle) orelse return 0xFFFF;
1530
- const data = sliceFromPtrLen(dataPtr, dataLen);
1531
- const mem_id = object_ptr.registerMemBuffer(data, owned) catch return 0xFFFF;
1532
- return @intCast(mem_id);
1533
- }
1534
-
1535
- export fn textBufferReplaceMemBuffer(tb_handle: NativeHandle, id: u8, dataPtr: ?[*]const u8, dataLen: u32, owned: bool) bool {
1536
- const object_ptr = acquireTextBuffer(tb_handle) orelse return false;
1537
- const data = sliceFromPtrLen(dataPtr, dataLen);
1538
- object_ptr.replaceMemBuffer(id, data, owned) catch return false;
1539
- return true;
1540
- }
1541
-
1542
- export fn textBufferClearMemRegistry(tb_handle: NativeHandle) void {
1543
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1544
- object_ptr.clearMemRegistry();
1545
- }
1546
-
1547
- export fn textBufferSetTextFromMem(tb_handle: NativeHandle, id: u8) void {
1548
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1549
- object_ptr.setTextFromMemId(id) catch {};
1550
- }
1551
-
1552
- export fn textBufferAppend(tb_handle: NativeHandle, dataPtr: ?[*]const u8, dataLen: u32) void {
1553
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1554
- const data = sliceFromPtrLen(dataPtr, dataLen);
1555
- object_ptr.append(data) catch {};
1556
- }
1557
-
1558
- export fn textBufferAppendFromMemId(tb_handle: NativeHandle, id: u8) void {
1559
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1560
- object_ptr.appendFromMemId(id) catch {};
1561
- }
1562
-
1563
- export fn textBufferLoadFile(tb_handle: NativeHandle, pathPtr: ?[*]const u8, pathLen: u32) bool {
1564
- const object_ptr = acquireTextBuffer(tb_handle) orelse return false;
1565
- const path = sliceFromPtrLen(pathPtr, pathLen);
1566
- object_ptr.loadFile(path) catch return false;
1567
- return true;
1568
- }
1569
-
1570
- export fn textBufferSetStyledText(
1571
- tb_handle: NativeHandle,
1572
- chunksPtr: ?[*]const text_buffer.StyledChunk,
1573
- chunkCount: u32,
1574
- ) void {
1575
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
1576
- if (chunkCount == 0) return;
1577
- const chunks = chunksPtr.?[0..@as(usize, chunkCount)];
1578
- object_ptr.setStyledText(chunks) catch {};
1579
- }
1580
-
1581
- export fn textBufferGetLineCount(tb_handle: NativeHandle) u32 {
1582
- const object_ptr = acquireTextBuffer(tb_handle) orelse return 0;
1583
- return object_ptr.getLineCount();
1584
- }
1585
-
1586
- export fn textBufferGetPlainText(tb_handle: NativeHandle, outPtr: ?[*]u8, maxLen: u32) u32 {
1587
- const object_ptr = acquireTextBuffer(tb_handle) orelse return 0;
1588
- if (maxLen == 0) return 0;
1589
-
1590
- const out = outPtr orelse return 0;
1591
- const outBuffer = out[0..@as(usize, maxLen)];
1592
- return @intCast(object_ptr.getPlainTextIntoBuffer(outBuffer));
1593
- }
1594
-
1595
- // TextBufferView functions (Array-based for backward compatibility)
1596
- export fn createTextBufferView(tb_handle: NativeHandle) NativeHandle {
1597
- if (!handles.isOwned(tb_handle, .text_buffer)) return INVALID_HANDLE;
1598
-
1599
- const object_ptr = acquireTextBuffer(tb_handle) orelse return INVALID_HANDLE;
1600
- const view = text_buffer_view.UnifiedTextBufferView.init(globalAllocator, object_ptr) catch {
1601
- return INVALID_HANDLE;
1602
- };
1603
- return handles.insertOwnedChild(.text_buffer_view, erasePtr(view), tb_handle) catch {
1604
- view.deinit();
1605
- return INVALID_HANDLE;
1606
- };
1607
- }
1608
-
1609
- export fn destroyTextBufferView(view_handle: NativeHandle) void {
1610
- destroyTextBufferViewHandle(view_handle);
1611
- }
1612
-
1613
- export fn textBufferViewSetSelection(view_handle: NativeHandle, start: u32, end: u32, bgColor: ?[*]const u16, fgColor: ?[*]const u16) void {
1614
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1615
- object_ptr.setSelectionStyle(start, end, selectionStyle(optionalPtrToRGBA(bgColor), optionalPtrToRGBA(fgColor)));
1616
- }
1617
-
1618
- export fn textBufferViewResetSelection(view_handle: NativeHandle) void {
1619
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1620
- object_ptr.resetSelection();
1621
- }
1622
-
1623
- export fn textBufferViewGetSelectionInfo(view_handle: NativeHandle) u64 {
1624
- const object_ptr = acquireTextBufferView(view_handle) orelse return std.math.maxInt(u64);
1625
- return object_ptr.packSelectionInfo();
1626
- }
1627
-
1628
- export fn textBufferViewSetLocalSelection(view_handle: NativeHandle, anchorX: i32, anchorY: i32, focusX: i32, focusY: i32, bgColor: ?[*]const u16, fgColor: ?[*]const u16) bool {
1629
- const object_ptr = acquireTextBufferView(view_handle) orelse return false;
1630
- return object_ptr.setLocalSelectionStyle(anchorX, anchorY, focusX, focusY, selectionStyle(optionalPtrToRGBA(bgColor), optionalPtrToRGBA(fgColor)));
1631
- }
1632
-
1633
- export fn textBufferViewUpdateSelection(view_handle: NativeHandle, end: u32, bgColor: ?[*]const u16, fgColor: ?[*]const u16) void {
1634
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1635
- object_ptr.updateSelectionStyle(end, selectionStyle(optionalPtrToRGBA(bgColor), optionalPtrToRGBA(fgColor)));
1636
- }
1637
-
1638
- export fn textBufferViewUpdateLocalSelection(view_handle: NativeHandle, anchorX: i32, anchorY: i32, focusX: i32, focusY: i32, bgColor: ?[*]const u16, fgColor: ?[*]const u16) bool {
1639
- const object_ptr = acquireTextBufferView(view_handle) orelse return false;
1640
- return object_ptr.updateLocalSelectionStyle(anchorX, anchorY, focusX, focusY, selectionStyle(optionalPtrToRGBA(bgColor), optionalPtrToRGBA(fgColor)));
1641
- }
1642
-
1643
- export fn textBufferViewResetLocalSelection(view_handle: NativeHandle) void {
1644
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1645
- object_ptr.resetLocalSelection();
1646
- }
1647
-
1648
- export fn textBufferViewSetWrapWidth(view_handle: NativeHandle, width: u32) void {
1649
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1650
- object_ptr.setWrapWidth(if (width == 0) null else width);
1651
- }
1652
-
1653
- export fn textBufferViewSetWrapMode(view_handle: NativeHandle, mode: u8) void {
1654
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1655
- const wrapMode: text_buffer.WrapMode = switch (mode) {
1656
- 0 => .none,
1657
- 1 => .char,
1658
- 2 => .word,
1659
- else => .none,
1660
- };
1661
- object_ptr.setWrapMode(wrapMode);
1662
- }
1663
-
1664
- export fn textBufferViewSetFirstLineOffset(view_handle: NativeHandle, offset: u32) void {
1665
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1666
- object_ptr.setFirstLineOffset(offset);
1667
- }
1668
-
1669
- export fn textBufferViewSetViewportSize(view_handle: NativeHandle, width: u32, height: u32) void {
1670
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1671
- object_ptr.setViewportSize(width, height);
1672
- }
1673
-
1674
- export fn textBufferViewSetViewport(view_handle: NativeHandle, x: u32, y: u32, width: u32, height: u32) void {
1675
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1676
- object_ptr.setViewport(.{
1677
- .x = x,
1678
- .y = y,
1679
- .width = width,
1680
- .height = height,
1681
- });
1682
- }
1683
-
1684
- export fn textBufferViewGetVirtualLineCount(view_handle: NativeHandle) u32 {
1685
- const object_ptr = acquireTextBufferView(view_handle) orelse return 0;
1686
- return object_ptr.getVirtualLineCount();
1687
- }
1688
-
1689
- export fn textBufferViewGetLineInfoDirect(view_handle: NativeHandle, outPtr: *ExternalLineInfo) void {
1690
- const object_ptr = acquireTextBufferView(view_handle) orelse {
1691
- emptyLineInfo(outPtr);
1692
- return;
1693
- };
1694
- const line_info = object_ptr.getCachedLineInfo();
1695
-
1696
- outPtr.* = .{
1697
- .start_cols_ptr = line_info.line_start_cols.ptr,
1698
- .start_cols_len = @intCast(line_info.line_start_cols.len),
1699
- .width_cols_ptr = line_info.line_width_cols.ptr,
1700
- .width_cols_len = @intCast(line_info.line_width_cols.len),
1701
- .sources_ptr = line_info.line_sources.ptr,
1702
- .sources_len = @intCast(line_info.line_sources.len),
1703
- .wraps_ptr = line_info.line_wraps.ptr,
1704
- .wraps_len = @intCast(line_info.line_wraps.len),
1705
- .width_cols_max = line_info.line_width_cols_max,
1706
- };
1707
- }
1708
-
1709
- export fn textBufferViewGetLogicalLineInfoDirect(view_handle: NativeHandle, outPtr: *ExternalLineInfo) void {
1710
- const object_ptr = acquireTextBufferView(view_handle) orelse {
1711
- emptyLineInfo(outPtr);
1712
- return;
1713
- };
1714
- const line_info = object_ptr.getLogicalLineInfo();
1715
-
1716
- outPtr.* = .{
1717
- .start_cols_ptr = line_info.line_start_cols.ptr,
1718
- .start_cols_len = @intCast(line_info.line_start_cols.len),
1719
- .width_cols_ptr = line_info.line_width_cols.ptr,
1720
- .width_cols_len = @intCast(line_info.line_width_cols.len),
1721
- .sources_ptr = line_info.line_sources.ptr,
1722
- .sources_len = @intCast(line_info.line_sources.len),
1723
- .wraps_ptr = line_info.line_wraps.ptr,
1724
- .wraps_len = @intCast(line_info.line_wraps.len),
1725
- .width_cols_max = line_info.line_width_cols_max,
1726
- };
1727
- }
1728
-
1729
- export fn textBufferViewGetSelectedText(view_handle: NativeHandle, outPtr: ?[*]u8, maxLen: u32) u32 {
1730
- const object_ptr = acquireTextBufferView(view_handle) orelse return 0;
1731
- if (maxLen == 0) return 0;
1732
-
1733
- const out = outPtr orelse return 0;
1734
- const outBuffer = out[0..@as(usize, maxLen)];
1735
- return @intCast(object_ptr.getSelectedTextIntoBuffer(outBuffer));
1736
- }
1737
-
1738
- export fn textBufferViewGetPlainText(view_handle: NativeHandle, outPtr: ?[*]u8, maxLen: u32) u32 {
1739
- const object_ptr = acquireTextBufferView(view_handle) orelse return 0;
1740
- if (maxLen == 0) return 0;
1741
-
1742
- const out = outPtr orelse return 0;
1743
- const outBuffer = out[0..@as(usize, maxLen)];
1744
- return @intCast(object_ptr.getPlainTextIntoBuffer(outBuffer));
1745
- }
1746
-
1747
- export fn textBufferViewSetTabIndicator(view_handle: NativeHandle, indicator: u32) void {
1748
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1749
- object_ptr.setTabIndicator(indicator);
1750
- }
1751
-
1752
- export fn textBufferViewSetTabIndicatorColor(view_handle: NativeHandle, color: [*]const u16) void {
1753
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1754
- object_ptr.setTabIndicatorColor(ptrToRGBA(color));
1755
- }
1756
-
1757
- export fn textBufferViewSetTruncate(view_handle: NativeHandle, truncate: bool) void {
1758
- const object_ptr = acquireTextBufferView(view_handle) orelse return;
1759
- object_ptr.setTruncate(truncate);
1760
- }
1761
-
1762
- pub const ExternalMeasureResult = extern struct {
1763
- line_count: u32,
1764
- width_cols_max: u32,
1765
- };
1766
-
1767
- export fn textBufferViewMeasureForDimensions(view_handle: NativeHandle, width: u32, height: u32, outPtr: *ExternalMeasureResult) bool {
1768
- const object_ptr = acquireTextBufferView(view_handle) orelse {
1769
- outPtr.* = std.mem.zeroes(ExternalMeasureResult);
1770
- return false;
1771
- };
1772
- const result = object_ptr.measureForDimensions(width, height) catch return false;
1773
- outPtr.* = .{
1774
- .line_count = result.line_count,
1775
- .width_cols_max = result.width_cols_max,
1776
- };
1777
- return true;
1778
- }
1779
-
1780
- // ===== EditBuffer Exports =====
1781
-
1782
- fn destroyEditorViewHandle(view_handle: NativeHandle) void {
1783
- const token = handles.beginDestroy(view_handle, .editor_view, editor_view.EditorView) orelse return;
1784
- handles.invalidateChildren(token.handle);
1785
- token.ptr.deinit();
1786
- handles.finishDestroy(token.handle);
1787
- }
1788
-
1789
- fn destroyEditorViewChildren(owner: NativeHandle) void {
1790
- while (handles.findChild(owner, .editor_view)) |view_handle| {
1791
- destroyEditorViewHandle(view_handle);
1792
- }
1793
- }
1794
-
1795
- export fn createEditBuffer(widthMethod: u8, event_sink_handle: NativeHandle) NativeHandle {
1796
- const pool = gp.initGlobalPool(globalArena);
1797
- const link_pool = link.initGlobalLinkPool(globalArena);
1798
- const wMethod: utf8.WidthMethod = if (widthMethod == 0) .wcwidth else .unicode;
1799
- const event_sink_ptr = if (event_sink_handle == INVALID_HANDLE) null else acquireEventSink(event_sink_handle);
1800
- const event_sink = if (event_sink_ptr) |object_ptr| object_ptr else null;
1801
-
1802
- const edit_buffer = edit_buffer_mod.EditBuffer.init(
1803
- globalAllocator,
1804
- pool,
1805
- link_pool,
1806
- wMethod,
1807
- event_sink,
1808
- ) catch return INVALID_HANDLE;
1809
-
1810
- const edit_handle = handles.insert(.edit_buffer, erasePtr(edit_buffer)) catch {
1811
- edit_buffer.deinit();
1812
- return INVALID_HANDLE;
1813
- };
1814
- _ = handles.getOrInsertBorrowed(.text_buffer, erasePtr(edit_buffer.getTextBuffer()), edit_handle) catch {
1815
- if (handles.beginDestroy(edit_handle, .edit_buffer, edit_buffer_mod.EditBuffer)) |token| {
1816
- token.ptr.deinit();
1817
- handles.finishDestroy(token.handle);
1818
- }
1819
- return INVALID_HANDLE;
1820
- };
1821
- return edit_handle;
1822
- }
1823
-
1824
- export fn destroyEditBuffer(edit_handle: NativeHandle) void {
1825
- const token = handles.beginDestroy(edit_handle, .edit_buffer, edit_buffer_mod.EditBuffer) orelse return;
1826
- destroyEditorViewChildren(token.handle);
1827
- handles.invalidateChildren(token.handle);
1828
- token.ptr.deinit();
1829
- handles.finishDestroy(token.handle);
1830
- }
1831
-
1832
- export fn editBufferGetTextBuffer(edit_handle: NativeHandle) NativeHandle {
1833
- const object_ptr = acquireEditBuffer(edit_handle) orelse return INVALID_HANDLE;
1834
- return handles.getOrInsertBorrowed(.text_buffer, erasePtr(object_ptr.getTextBuffer()), edit_handle) catch INVALID_HANDLE;
1835
- }
1836
-
1837
- export fn editBufferInsertText(edit_handle: NativeHandle, textPtr: ?[*]const u8, textLen: u32) void {
1838
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1839
- const text = sliceFromPtrLen(textPtr, textLen);
1840
- object_ptr.insertText(text) catch {};
1841
- }
1842
-
1843
- export fn editBufferDeleteRange(edit_handle: NativeHandle, start_row: u32, start_col: u32, end_row: u32, end_col: u32) void {
1844
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1845
- const start: edit_buffer_mod.Cursor = .{ .row = start_row, .col = start_col };
1846
- const end: edit_buffer_mod.Cursor = .{ .row = end_row, .col = end_col };
1847
- object_ptr.deleteRange(start, end) catch {};
1848
- }
1849
-
1850
- export fn editBufferDeleteCharBackward(edit_handle: NativeHandle) void {
1851
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1852
- object_ptr.backspace() catch {};
1853
- }
1854
-
1855
- export fn editBufferDeleteChar(edit_handle: NativeHandle) void {
1856
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1857
- object_ptr.deleteForward() catch {};
1858
- }
1859
-
1860
- export fn editBufferMoveCursorLeft(edit_handle: NativeHandle) void {
1861
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1862
- object_ptr.moveLeft();
1863
- }
1864
-
1865
- export fn editBufferMoveCursorRight(edit_handle: NativeHandle) void {
1866
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1867
- object_ptr.moveRight();
1868
- }
1869
-
1870
- export fn editBufferMoveCursorUp(edit_handle: NativeHandle) void {
1871
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1872
- object_ptr.moveUp();
1873
- }
1874
-
1875
- export fn editBufferMoveCursorDown(edit_handle: NativeHandle) void {
1876
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1877
- object_ptr.moveDown();
1878
- }
1879
-
1880
- export fn editBufferGetCursor(edit_handle: NativeHandle, outRow: *u32, outCol: *u32) void {
1881
- const object_ptr = acquireEditBuffer(edit_handle) orelse {
1882
- outRow.* = 0;
1883
- outCol.* = 0;
1884
- return;
1885
- };
1886
- const cursor = object_ptr.getPrimaryCursor();
1887
- outRow.* = cursor.row;
1888
- outCol.* = cursor.col;
1889
- }
1890
-
1891
- export fn editBufferSetCursor(edit_handle: NativeHandle, row: u32, col: u32) void {
1892
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1893
- object_ptr.setCursor(row, col) catch {};
1894
- }
1895
-
1896
- export fn editBufferSetCursorToLineCol(edit_handle: NativeHandle, row: u32, col: u32) void {
1897
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1898
- object_ptr.setCursor(row, col) catch {};
1899
- }
1900
-
1901
- export fn editBufferSetCursorByOffset(edit_handle: NativeHandle, offset: u32) void {
1902
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1903
- object_ptr.setCursorByOffset(offset) catch {};
1904
- }
1905
-
1906
- export fn editBufferGetNextWordBoundary(edit_handle: NativeHandle, outPtr: *ExternalLogicalCursor) void {
1907
- const object_ptr = acquireEditBuffer(edit_handle) orelse {
1908
- outPtr.* = std.mem.zeroes(ExternalLogicalCursor);
1909
- return;
1910
- };
1911
- const cursor = object_ptr.getNextWordBoundary();
1912
- outPtr.* = .{
1913
- .row = cursor.row,
1914
- .col = cursor.col,
1915
- .offset = cursor.offset,
1916
- };
1917
- }
1918
-
1919
- export fn editBufferGetPrevWordBoundary(edit_handle: NativeHandle, outPtr: *ExternalLogicalCursor) void {
1920
- const object_ptr = acquireEditBuffer(edit_handle) orelse {
1921
- outPtr.* = std.mem.zeroes(ExternalLogicalCursor);
1922
- return;
1923
- };
1924
- const cursor = object_ptr.getPrevWordBoundary();
1925
- outPtr.* = .{
1926
- .row = cursor.row,
1927
- .col = cursor.col,
1928
- .offset = cursor.offset,
1929
- };
1930
- }
1931
-
1932
- export fn editBufferGetEOL(edit_handle: NativeHandle, outPtr: *ExternalLogicalCursor) void {
1933
- const object_ptr = acquireEditBuffer(edit_handle) orelse {
1934
- outPtr.* = std.mem.zeroes(ExternalLogicalCursor);
1935
- return;
1936
- };
1937
- const cursor = object_ptr.getEOL();
1938
- outPtr.* = .{
1939
- .row = cursor.row,
1940
- .col = cursor.col,
1941
- .offset = cursor.offset,
1942
- };
1943
- }
1944
-
1945
- export fn editBufferOffsetToPosition(edit_handle: NativeHandle, offset: u32, outPtr: *ExternalLogicalCursor) bool {
1946
- const object_ptr = acquireEditBuffer(edit_handle) orelse {
1947
- outPtr.* = std.mem.zeroes(ExternalLogicalCursor);
1948
- return false;
1949
- };
1950
- const coords = text_buffer_iterators.offsetToCoords(object_ptr.tb.rope(), offset) orelse return false;
1951
- outPtr.* = .{
1952
- .row = coords.row,
1953
- .col = coords.col,
1954
- .offset = offset,
1955
- };
1956
- return true;
1957
- }
1958
-
1959
- export fn editBufferPositionToOffset(edit_handle: NativeHandle, row: u32, col: u32) u32 {
1960
- const object_ptr = acquireEditBuffer(edit_handle) orelse return 0;
1961
- return text_buffer_iterators.coordsToOffset(object_ptr.tb.rope(), row, col) orelse 0;
1962
- }
1963
-
1964
- export fn editBufferGetLineStartOffset(edit_handle: NativeHandle, row: u32) u32 {
1965
- const object_ptr = acquireEditBuffer(edit_handle) orelse return 0;
1966
- return text_buffer_iterators.coordsToOffset(object_ptr.tb.rope(), row, 0) orelse 0;
1967
- }
1968
-
1969
- export fn editBufferGetTextRange(edit_handle: NativeHandle, start_offset: u32, end_offset: u32, outPtr: ?[*]u8, maxLen: u32) u32 {
1970
- const object_ptr = acquireEditBuffer(edit_handle) orelse return 0;
1971
- if (maxLen == 0) return 0;
1972
-
1973
- const out = outPtr orelse return 0;
1974
- const outBuffer = out[0..@as(usize, maxLen)];
1975
- return @intCast(object_ptr.getTextRange(start_offset, end_offset, outBuffer) catch 0);
1976
- }
1977
-
1978
- export fn editBufferGetTextRangeByCoords(edit_handle: NativeHandle, start_row: u32, start_col: u32, end_row: u32, end_col: u32, outPtr: ?[*]u8, maxLen: u32) u32 {
1979
- const object_ptr = acquireEditBuffer(edit_handle) orelse return 0;
1980
- if (maxLen == 0) return 0;
1981
-
1982
- const out = outPtr orelse return 0;
1983
- const outBuffer = out[0..@as(usize, maxLen)];
1984
- return @intCast(object_ptr.getTextRangeByCoords(start_row, start_col, end_row, end_col, outBuffer));
1985
- }
1986
-
1987
- export fn editBufferSetText(edit_handle: NativeHandle, textPtr: ?[*]const u8, textLen: u32) void {
1988
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1989
- const text = sliceFromPtrLen(textPtr, textLen);
1990
- object_ptr.setText(text) catch {};
1991
- }
1992
-
1993
- export fn editBufferSetTextFromMem(edit_handle: NativeHandle, mem_id: u8) void {
1994
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
1995
- object_ptr.setTextFromMemId(mem_id) catch {};
1996
- }
1997
-
1998
- export fn editBufferReplaceText(edit_handle: NativeHandle, textPtr: ?[*]const u8, textLen: u32) void {
1999
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
2000
- const text = sliceFromPtrLen(textPtr, textLen);
2001
- object_ptr.replaceText(text) catch {};
2002
- }
2003
-
2004
- export fn editBufferReplaceTextFromMem(edit_handle: NativeHandle, mem_id: u8) void {
2005
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
2006
- object_ptr.replaceTextFromMemId(mem_id) catch {};
2007
- }
2008
-
2009
- export fn editBufferGetText(edit_handle: NativeHandle, outPtr: ?[*]u8, maxLen: u32) u32 {
2010
- const object_ptr = acquireEditBuffer(edit_handle) orelse return 0;
2011
- if (maxLen == 0) return 0;
2012
-
2013
- const out = outPtr orelse return 0;
2014
- const outBuffer = out[0..@as(usize, maxLen)];
2015
- return @intCast(object_ptr.getText(outBuffer));
2016
- }
2017
-
2018
- export fn editBufferInsertChar(edit_handle: NativeHandle, charPtr: ?[*]const u8, charLen: u32) void {
2019
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
2020
- const text = sliceFromPtrLen(charPtr, charLen);
2021
- object_ptr.insertText(text) catch {};
2022
- }
2023
-
2024
- export fn editBufferNewLine(edit_handle: NativeHandle) void {
2025
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
2026
- object_ptr.insertText("\n") catch {};
2027
- }
2028
-
2029
- export fn editBufferDeleteLine(edit_handle: NativeHandle) void {
2030
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
2031
- object_ptr.deleteLine() catch {};
2032
- }
2033
-
2034
- export fn editBufferGotoLine(edit_handle: NativeHandle, line: u32) void {
2035
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
2036
- object_ptr.gotoLine(line) catch {};
2037
- }
2038
-
2039
- export fn editBufferGetCursorPosition(edit_handle: NativeHandle, outPtr: *ExternalLogicalCursor) void {
2040
- const object_ptr = acquireEditBuffer(edit_handle) orelse {
2041
- outPtr.* = std.mem.zeroes(ExternalLogicalCursor);
2042
- return;
2043
- };
2044
- const pos = object_ptr.getCursorPosition();
2045
- outPtr.* = .{
2046
- .row = pos.line,
2047
- .col = pos.visual_col,
2048
- .offset = pos.offset,
2049
- };
2050
- }
2051
-
2052
- export fn editBufferGetId(edit_handle: NativeHandle) u16 {
2053
- const object_ptr = acquireEditBuffer(edit_handle) orelse return 0;
2054
- return object_ptr.getId();
2055
- }
2056
-
2057
- export fn editBufferDebugLogRope(edit_handle: NativeHandle) void {
2058
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
2059
- object_ptr.debugLogRope();
2060
- }
2061
-
2062
- export fn editBufferUndo(edit_handle: NativeHandle, outPtr: ?[*]u8, maxLen: u32) u32 {
2063
- const object_ptr = acquireEditBuffer(edit_handle) orelse return 0;
2064
- if (maxLen == 0) return 0;
2065
-
2066
- const out = outPtr orelse return 0;
2067
- const prev_meta = object_ptr.undo() catch return 0;
2068
- const copyLen = @min(prev_meta.len, @as(usize, maxLen));
2069
- @memcpy(out[0..copyLen], prev_meta[0..copyLen]);
2070
- return @intCast(copyLen);
2071
- }
2072
-
2073
- export fn editBufferRedo(edit_handle: NativeHandle, outPtr: ?[*]u8, maxLen: u32) u32 {
2074
- const object_ptr = acquireEditBuffer(edit_handle) orelse return 0;
2075
- if (maxLen == 0) return 0;
2076
-
2077
- const out = outPtr orelse return 0;
2078
- const next_meta = object_ptr.redo() catch return 0;
2079
- const copyLen = @min(next_meta.len, @as(usize, maxLen));
2080
- @memcpy(out[0..copyLen], next_meta[0..copyLen]);
2081
- return @intCast(copyLen);
2082
- }
2083
-
2084
- export fn editBufferCanUndo(edit_handle: NativeHandle) bool {
2085
- const object_ptr = acquireEditBuffer(edit_handle) orelse return false;
2086
- return object_ptr.canUndo();
2087
- }
2088
-
2089
- export fn editBufferCanRedo(edit_handle: NativeHandle) bool {
2090
- const object_ptr = acquireEditBuffer(edit_handle) orelse return false;
2091
- return object_ptr.canRedo();
2092
- }
2093
-
2094
- export fn editBufferClearHistory(edit_handle: NativeHandle) void {
2095
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
2096
- object_ptr.clearHistory();
2097
- }
2098
-
2099
- export fn editBufferClear(edit_handle: NativeHandle) void {
2100
- const object_ptr = acquireEditBuffer(edit_handle) orelse return;
2101
- object_ptr.clear() catch {};
2102
- }
2103
-
2104
- // ===== EditorView Exports =====
2105
-
2106
- export fn createEditorView(edit_handle: NativeHandle, viewport_width: u32, viewport_height: u32) NativeHandle {
2107
- const object_ptr = acquireEditBuffer(edit_handle) orelse return INVALID_HANDLE;
2108
- const view = editor_view.EditorView.init(globalArena, object_ptr, viewport_width, viewport_height) catch return INVALID_HANDLE;
2109
- const view_handle = handles.insertOwnedChild(.editor_view, erasePtr(view), edit_handle) catch {
2110
- view.deinit();
2111
- return INVALID_HANDLE;
2112
- };
2113
- _ = handles.getOrInsertBorrowed(.text_buffer_view, erasePtr(view.getTextBufferView()), view_handle) catch {
2114
- if (handles.beginDestroy(view_handle, .editor_view, editor_view.EditorView)) |token| {
2115
- token.ptr.deinit();
2116
- handles.finishDestroy(token.handle);
2117
- }
2118
- return INVALID_HANDLE;
2119
- };
2120
- return view_handle;
2121
- }
2122
-
2123
- export fn destroyEditorView(view_handle: NativeHandle) void {
2124
- destroyEditorViewHandle(view_handle);
2125
- }
2126
-
2127
- export fn editorViewSetViewport(view_handle: NativeHandle, x: u32, y: u32, width: u32, height: u32, moveCursor: bool) void {
2128
- const object_ptr = acquireEditorView(view_handle) orelse return;
2129
- object_ptr.setViewport(.{ .x = x, .y = y, .width = width, .height = height }, moveCursor);
2130
- }
2131
-
2132
- export fn editorViewClearViewport(view_handle: NativeHandle) void {
2133
- const object_ptr = acquireEditorView(view_handle) orelse return;
2134
- object_ptr.setViewport(null, false);
2135
- }
2136
-
2137
- export fn editorViewGetViewport(view_handle: NativeHandle, outX: *u32, outY: *u32, outWidth: *u32, outHeight: *u32) bool {
2138
- const object_ptr = acquireEditorView(view_handle) orelse {
2139
- outX.* = 0;
2140
- outY.* = 0;
2141
- outWidth.* = 0;
2142
- outHeight.* = 0;
2143
- return false;
2144
- };
2145
- if (object_ptr.getViewport()) |vp| {
2146
- outX.* = vp.x;
2147
- outY.* = vp.y;
2148
- outWidth.* = vp.width;
2149
- outHeight.* = vp.height;
2150
- return true;
2151
- }
2152
- return false;
2153
- }
2154
-
2155
- export fn editorViewSetScrollMargin(view_handle: NativeHandle, margin: f32) void {
2156
- const object_ptr = acquireEditorView(view_handle) orelse return;
2157
- object_ptr.setScrollMargin(margin);
2158
- }
2159
-
2160
- export fn editorViewGetVirtualLineCount(view_handle: NativeHandle) u32 {
2161
- const object_ptr = acquireEditorView(view_handle) orelse return 0;
2162
- // TODO: There is a getter for that directly, no?
2163
- return @intCast(object_ptr.getVirtualLines().len);
2164
- }
2165
-
2166
- export fn editorViewGetTotalVirtualLineCount(view_handle: NativeHandle) u32 {
2167
- const object_ptr = acquireEditorView(view_handle) orelse return 0;
2168
- return object_ptr.getTotalVirtualLineCount();
2169
- }
2170
-
2171
- export fn editorViewGetLineInfoDirect(view_handle: NativeHandle, outPtr: *ExternalLineInfo) void {
2172
- const object_ptr = acquireEditorView(view_handle) orelse {
2173
- emptyLineInfo(outPtr);
2174
- return;
2175
- };
2176
- const line_info = object_ptr.getCachedLineInfo();
2177
- outPtr.* = .{
2178
- .start_cols_ptr = line_info.line_start_cols.ptr,
2179
- .start_cols_len = @intCast(line_info.line_start_cols.len),
2180
- .width_cols_ptr = line_info.line_width_cols.ptr,
2181
- .width_cols_len = @intCast(line_info.line_width_cols.len),
2182
- .sources_ptr = line_info.line_sources.ptr,
2183
- .sources_len = @intCast(line_info.line_sources.len),
2184
- .wraps_ptr = line_info.line_wraps.ptr,
2185
- .wraps_len = @intCast(line_info.line_wraps.len),
2186
- .width_cols_max = line_info.line_width_cols_max,
2187
- };
2188
- }
2189
-
2190
- export fn editorViewGetTextBufferView(view_handle: NativeHandle) NativeHandle {
2191
- const object_ptr = acquireEditorView(view_handle) orelse return INVALID_HANDLE;
2192
- return handles.getOrInsertBorrowed(.text_buffer_view, erasePtr(object_ptr.getTextBufferView()), view_handle) catch INVALID_HANDLE;
2193
- }
2194
-
2195
- export fn editorViewGetLogicalLineInfoDirect(view_handle: NativeHandle, outPtr: *ExternalLineInfo) void {
2196
- const object_ptr = acquireEditorView(view_handle) orelse {
2197
- emptyLineInfo(outPtr);
2198
- return;
2199
- };
2200
- const line_info = object_ptr.getLogicalLineInfo();
2201
- outPtr.* = .{
2202
- .start_cols_ptr = line_info.line_start_cols.ptr,
2203
- .start_cols_len = @intCast(line_info.line_start_cols.len),
2204
- .width_cols_ptr = line_info.line_width_cols.ptr,
2205
- .width_cols_len = @intCast(line_info.line_width_cols.len),
2206
- .sources_ptr = line_info.line_sources.ptr,
2207
- .sources_len = @intCast(line_info.line_sources.len),
2208
- .wraps_ptr = line_info.line_wraps.ptr,
2209
- .wraps_len = @intCast(line_info.line_wraps.len),
2210
- .width_cols_max = line_info.line_width_cols_max,
2211
- };
2212
- }
2213
-
2214
- export fn editorViewSetViewportSize(view_handle: NativeHandle, width: u32, height: u32) void {
2215
- const object_ptr = acquireEditorView(view_handle) orelse return;
2216
- object_ptr.setViewportSize(width, height);
2217
- }
2218
-
2219
- export fn editorViewSetWrapMode(view_handle: NativeHandle, mode: u8) void {
2220
- const object_ptr = acquireEditorView(view_handle) orelse return;
2221
- const wrapMode: text_buffer.WrapMode = switch (mode) {
2222
- 0 => .none,
2223
- 1 => .char,
2224
- 2 => .word,
2225
- else => .none,
2226
- };
2227
- object_ptr.setWrapMode(wrapMode);
2228
- }
2229
-
2230
- // EditorView selection methods - delegate to TextBufferView
2231
- export fn editorViewSetSelection(view_handle: NativeHandle, start: u32, end: u32, bgColor: ?[*]const u16, fgColor: ?[*]const u16) void {
2232
- const object_ptr = acquireEditorView(view_handle) orelse return;
2233
- object_ptr.text_buffer_view.setSelectionStyle(start, end, selectionStyle(optionalPtrToRGBA(bgColor), optionalPtrToRGBA(fgColor)));
2234
- }
2235
-
2236
- export fn editorViewResetSelection(view_handle: NativeHandle) void {
2237
- const object_ptr = acquireEditorView(view_handle) orelse return;
2238
- object_ptr.text_buffer_view.resetSelection();
2239
- }
2240
-
2241
- export fn editorViewGetSelection(view_handle: NativeHandle) u64 {
2242
- const object_ptr = acquireEditorView(view_handle) orelse return std.math.maxInt(u64);
2243
- return object_ptr.text_buffer_view.packSelectionInfo();
2244
- }
2245
-
2246
- export fn editorViewSetLocalSelection(view_handle: NativeHandle, anchorX: i32, anchorY: i32, focusX: i32, focusY: i32, bgColor: ?[*]const u16, fgColor: ?[*]const u16, updateCursor: bool, followCursor: bool) bool {
2247
- const object_ptr = acquireEditorView(view_handle) orelse return false;
2248
- object_ptr.setSelectionFollowCursor(followCursor);
2249
- const changed = object_ptr.text_buffer_view.setLocalSelectionStyle(anchorX, anchorY, focusX, focusY, selectionStyle(optionalPtrToRGBA(bgColor), optionalPtrToRGBA(fgColor)));
2250
- if (changed and updateCursor) {
2251
- object_ptr.syncCursorToSelectionFocus();
2252
- }
2253
- return changed;
2254
- }
2255
-
2256
- export fn editorViewUpdateSelection(view_handle: NativeHandle, end: u32, bgColor: ?[*]const u16, fgColor: ?[*]const u16) void {
2257
- const object_ptr = acquireEditorView(view_handle) orelse return;
2258
- object_ptr.text_buffer_view.updateSelectionStyle(end, selectionStyle(optionalPtrToRGBA(bgColor), optionalPtrToRGBA(fgColor)));
2259
- }
2260
-
2261
- export fn editorViewUpdateLocalSelection(view_handle: NativeHandle, anchorX: i32, anchorY: i32, focusX: i32, focusY: i32, bgColor: ?[*]const u16, fgColor: ?[*]const u16, updateCursor: bool, followCursor: bool) bool {
2262
- const object_ptr = acquireEditorView(view_handle) orelse return false;
2263
- object_ptr.setSelectionFollowCursor(followCursor);
2264
- const changed = object_ptr.text_buffer_view.updateLocalSelectionStyle(anchorX, anchorY, focusX, focusY, selectionStyle(optionalPtrToRGBA(bgColor), optionalPtrToRGBA(fgColor)));
2265
- if (changed and updateCursor) {
2266
- object_ptr.syncCursorToSelectionFocus();
2267
- }
2268
- return changed;
2269
- }
2270
-
2271
- export fn editorViewResetLocalSelection(view_handle: NativeHandle) void {
2272
- const object_ptr = acquireEditorView(view_handle) orelse return;
2273
- object_ptr.setSelectionFollowCursor(false);
2274
- object_ptr.text_buffer_view.resetLocalSelection();
2275
- }
2276
-
2277
- export fn editorViewGetSelectedTextBytes(view_handle: NativeHandle, outPtr: ?[*]u8, maxLen: u32) u32 {
2278
- const object_ptr = acquireEditorView(view_handle) orelse return 0;
2279
- if (maxLen == 0) return 0;
2280
-
2281
- const out = outPtr orelse return 0;
2282
- const outBuffer = out[0..@as(usize, maxLen)];
2283
- return @intCast(object_ptr.text_buffer_view.getSelectedTextIntoBuffer(outBuffer));
2284
- }
2285
-
2286
- // EditorView cursor and text methods
2287
- export fn editorViewGetCursor(view_handle: NativeHandle, outRow: *u32, outCol: *u32) void {
2288
- const object_ptr = acquireEditorView(view_handle) orelse {
2289
- outRow.* = 0;
2290
- outCol.* = 0;
2291
- return;
2292
- };
2293
- const cursor = object_ptr.getPrimaryCursor();
2294
- outRow.* = cursor.row;
2295
- outCol.* = cursor.col;
2296
- }
2297
-
2298
- export fn editorViewGetText(view_handle: NativeHandle, outPtr: ?[*]u8, maxLen: u32) u32 {
2299
- const object_ptr = acquireEditorView(view_handle) orelse return 0;
2300
- if (maxLen == 0) return 0;
2301
-
2302
- const out = outPtr orelse return 0;
2303
- const outBuffer = out[0..@as(usize, maxLen)];
2304
- return @intCast(object_ptr.getText(outBuffer));
2305
- }
2306
-
2307
- // ===== EditorView VisualCursor Exports =====
2308
-
2309
- export fn editorViewGetVisualCursor(view_handle: NativeHandle, outPtr: *ExternalVisualCursor) void {
2310
- const object_ptr = acquireEditorView(view_handle) orelse {
2311
- outPtr.* = std.mem.zeroes(ExternalVisualCursor);
2312
- return;
2313
- };
2314
- const vcursor = object_ptr.getVisualCursor();
2315
- outPtr.* = .{
2316
- .visual_row = vcursor.visual_row,
2317
- .visual_col = vcursor.visual_col,
2318
- .logical_row = vcursor.logical_row,
2319
- .logical_col = vcursor.logical_col,
2320
- .offset = vcursor.offset,
2321
- };
2322
- }
2323
-
2324
- export fn editorViewMoveUpVisual(view_handle: NativeHandle) void {
2325
- const object_ptr = acquireEditorView(view_handle) orelse return;
2326
- object_ptr.moveUpVisual();
2327
- }
2328
-
2329
- export fn editorViewMoveDownVisual(view_handle: NativeHandle) void {
2330
- const object_ptr = acquireEditorView(view_handle) orelse return;
2331
- object_ptr.moveDownVisual();
2332
- }
2333
-
2334
- export fn editorViewDeleteSelectedText(view_handle: NativeHandle) void {
2335
- const object_ptr = acquireEditorView(view_handle) orelse return;
2336
- object_ptr.deleteSelectedText() catch {};
2337
- }
2338
-
2339
- export fn editorViewSetCursorByOffset(view_handle: NativeHandle, offset: u32) void {
2340
- const object_ptr = acquireEditorView(view_handle) orelse return;
2341
- object_ptr.setCursorByOffset(offset) catch {};
2342
- }
2343
-
2344
- export fn editorViewGetNextWordBoundary(view_handle: NativeHandle, outPtr: *ExternalVisualCursor) void {
2345
- const object_ptr = acquireEditorView(view_handle) orelse {
2346
- outPtr.* = std.mem.zeroes(ExternalVisualCursor);
2347
- return;
2348
- };
2349
- const vcursor = object_ptr.getNextWordBoundary();
2350
- outPtr.* = .{
2351
- .visual_row = vcursor.visual_row,
2352
- .visual_col = vcursor.visual_col,
2353
- .logical_row = vcursor.logical_row,
2354
- .logical_col = vcursor.logical_col,
2355
- .offset = vcursor.offset,
2356
- };
2357
- }
2358
-
2359
- export fn editorViewGetPrevWordBoundary(view_handle: NativeHandle, outPtr: *ExternalVisualCursor) void {
2360
- const object_ptr = acquireEditorView(view_handle) orelse {
2361
- outPtr.* = std.mem.zeroes(ExternalVisualCursor);
2362
- return;
2363
- };
2364
- const vcursor = object_ptr.getPrevWordBoundary();
2365
- outPtr.* = .{
2366
- .visual_row = vcursor.visual_row,
2367
- .visual_col = vcursor.visual_col,
2368
- .logical_row = vcursor.logical_row,
2369
- .logical_col = vcursor.logical_col,
2370
- .offset = vcursor.offset,
2371
- };
2372
- }
2373
-
2374
- export fn editorViewGetEOL(view_handle: NativeHandle, outPtr: *ExternalVisualCursor) void {
2375
- const object_ptr = acquireEditorView(view_handle) orelse {
2376
- outPtr.* = std.mem.zeroes(ExternalVisualCursor);
2377
- return;
2378
- };
2379
- const vcursor = object_ptr.getEOL();
2380
- outPtr.* = .{
2381
- .visual_row = vcursor.visual_row,
2382
- .visual_col = vcursor.visual_col,
2383
- .logical_row = vcursor.logical_row,
2384
- .logical_col = vcursor.logical_col,
2385
- .offset = vcursor.offset,
2386
- };
2387
- }
2388
-
2389
- export fn editorViewGetVisualSOL(view_handle: NativeHandle, outPtr: *ExternalVisualCursor) void {
2390
- const object_ptr = acquireEditorView(view_handle) orelse {
2391
- outPtr.* = std.mem.zeroes(ExternalVisualCursor);
2392
- return;
2393
- };
2394
- const vcursor = object_ptr.getVisualSOL();
2395
- outPtr.* = .{
2396
- .visual_row = vcursor.visual_row,
2397
- .visual_col = vcursor.visual_col,
2398
- .logical_row = vcursor.logical_row,
2399
- .logical_col = vcursor.logical_col,
2400
- .offset = vcursor.offset,
2401
- };
2402
- }
2403
-
2404
- export fn editorViewGetVisualEOL(view_handle: NativeHandle, outPtr: *ExternalVisualCursor) void {
2405
- const object_ptr = acquireEditorView(view_handle) orelse {
2406
- outPtr.* = std.mem.zeroes(ExternalVisualCursor);
2407
- return;
2408
- };
2409
- const vcursor = object_ptr.getVisualEOL();
2410
- outPtr.* = .{
2411
- .visual_row = vcursor.visual_row,
2412
- .visual_col = vcursor.visual_col,
2413
- .logical_row = vcursor.logical_row,
2414
- .logical_col = vcursor.logical_col,
2415
- .offset = vcursor.offset,
2416
- };
2417
- }
2418
-
2419
- export fn editorViewSetPlaceholderStyledText(
2420
- view_handle: NativeHandle,
2421
- chunksPtr: ?[*]const text_buffer.StyledChunk,
2422
- chunkCount: u32,
2423
- ) void {
2424
- const object_ptr = acquireEditorView(view_handle) orelse return;
2425
- if (chunkCount == 0) {
2426
- object_ptr.setPlaceholderStyledText(&[_]text_buffer.StyledChunk{}) catch {};
2427
- return;
2428
- }
2429
- const chunks = chunksPtr.?[0..@as(usize, chunkCount)];
2430
- object_ptr.setPlaceholderStyledText(chunks) catch {};
2431
- }
2432
-
2433
- export fn editorViewSetTabIndicator(view_handle: NativeHandle, indicator: u32) void {
2434
- const object_ptr = acquireEditorView(view_handle) orelse return;
2435
- object_ptr.setTabIndicator(indicator);
2436
- }
2437
-
2438
- export fn editorViewSetTabIndicatorColor(view_handle: NativeHandle, color: [*]const u16) void {
2439
- const object_ptr = acquireEditorView(view_handle) orelse return;
2440
- object_ptr.setTabIndicatorColor(ptrToRGBA(color));
2441
- }
2442
-
2443
- export fn bufferDrawEditorView(
2444
- buffer_handle: NativeHandle,
2445
- view_handle: NativeHandle,
2446
- x: i32,
2447
- y: i32,
2448
- ) void {
2449
- const buffer_ptr = acquireBuffer(buffer_handle) orelse return;
2450
- const view_ptr = acquireEditorView(view_handle) orelse return;
2451
- buffer_ptr.drawEditorView(view_ptr, x, y);
2452
- }
2453
-
2454
- export fn bufferDrawTextBufferView(
2455
- buffer_handle: NativeHandle,
2456
- view_handle: NativeHandle,
2457
- x: i32,
2458
- y: i32,
2459
- ) void {
2460
- const buffer_ptr = acquireBuffer(buffer_handle) orelse return;
2461
- const view_ptr = acquireTextBufferView(view_handle) orelse return;
2462
- buffer_ptr.drawTextBuffer(view_ptr, x, y);
2463
- }
2464
-
2465
- pub const ExternalHighlight = extern struct {
2466
- start: u32,
2467
- end: u32,
2468
- style_id: u32,
2469
- priority: u8,
2470
- hl_ref: u16,
2471
- };
2472
-
2473
- pub const ExternalLogicalCursor = extern struct {
2474
- row: u32,
2475
- col: u32,
2476
- offset: u32,
2477
- };
2478
-
2479
- pub const ExternalVisualCursor = extern struct {
2480
- visual_row: u32,
2481
- visual_col: u32,
2482
- logical_row: u32,
2483
- logical_col: u32,
2484
- offset: u32,
2485
- };
2486
-
2487
- pub const ExternalLineInfo = extern struct {
2488
- start_cols_ptr: [*]const u32,
2489
- start_cols_len: u32,
2490
- width_cols_ptr: [*]const u32,
2491
- width_cols_len: u32,
2492
- sources_ptr: [*]const u32,
2493
- sources_len: u32,
2494
- wraps_ptr: [*]const u32,
2495
- wraps_len: u32,
2496
- width_cols_max: u32,
2497
- };
2498
-
2499
- export fn textBufferAddHighlightByCharRange(
2500
- tb_handle: NativeHandle,
2501
- hl_ptr: [*]const ExternalHighlight,
2502
- ) void {
2503
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
2504
- const hl = hl_ptr[0];
2505
- // For char-range highlights, start/end in the struct are unused (passed as char_start/char_end)
2506
- object_ptr.addHighlightByCharRange(hl.start, hl.end, hl.style_id, hl.priority, hl.hl_ref) catch {};
2507
- }
2508
-
2509
- export fn textBufferAddHighlight(
2510
- tb_handle: NativeHandle,
2511
- line_idx: u32,
2512
- hl_ptr: [*]const ExternalHighlight,
2513
- ) void {
2514
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
2515
- const hl = hl_ptr[0];
2516
- // For line-based highlights, start/end are column offsets
2517
- object_ptr.addHighlight(line_idx, hl.start, hl.end, hl.style_id, hl.priority, hl.hl_ref) catch {};
2518
- }
2519
-
2520
- export fn textBufferRemoveHighlightsByRef(tb_handle: NativeHandle, hl_ref: u16) void {
2521
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
2522
- object_ptr.removeHighlightsByRef(hl_ref);
2523
- }
2524
-
2525
- export fn textBufferClearLineHighlights(tb_handle: NativeHandle, line_idx: u32) void {
2526
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
2527
- object_ptr.clearLineHighlights(line_idx);
2528
- }
2529
-
2530
- export fn textBufferClearAllHighlights(tb_handle: NativeHandle) void {
2531
- const object_ptr = acquireTextBuffer(tb_handle) orelse return;
2532
- object_ptr.clearAllHighlights();
2533
- }
2534
-
2535
- export fn textBufferSetSyntaxStyle(tb_handle: NativeHandle, style_handle: NativeHandle) bool {
2536
- const tb_ptr = acquireTextBuffer(tb_handle) orelse return false;
2537
- if (style_handle == INVALID_HANDLE) {
2538
- tb_ptr.setSyntaxStyle(null);
2539
- return true;
2540
- }
2541
- const style_ptr = acquireSyntaxStyle(style_handle) orelse return false;
2542
- tb_ptr.setSyntaxStyle(style_ptr);
2543
- return tb_ptr.getSyntaxStyle() == style_ptr;
2544
- }
2545
-
2546
- export fn textBufferGetLineHighlightsPtr(
2547
- tb_handle: NativeHandle,
2548
- line_idx: u32,
2549
- out_count: *u32,
2550
- ) ?[*]const ExternalHighlight {
2551
- const object_ptr = acquireTextBuffer(tb_handle) orelse {
2552
- out_count.* = 0;
2553
- return null;
2554
- };
2555
- const highs = object_ptr.getLineHighlightsSlice(@intCast(line_idx));
2556
-
2557
- if (highs.len == 0) {
2558
- out_count.* = 0;
2559
- return null;
2560
- }
2561
-
2562
- var slice = globalAllocator.alloc(ExternalHighlight, highs.len) catch return null;
2563
-
2564
- for (highs, 0..) |hl, i| {
2565
- slice[i] = .{
2566
- .start = hl.col_start,
2567
- .end = hl.col_end,
2568
- .style_id = hl.style_id,
2569
- .priority = hl.priority,
2570
- .hl_ref = hl.hl_ref,
2571
- };
2572
- }
2573
-
2574
- out_count.* = @intCast(highs.len);
2575
- return slice.ptr;
2576
- }
2577
-
2578
- export fn textBufferFreeLineHighlights(ptr: [*]const ExternalHighlight, count: u32) void {
2579
- globalAllocator.free(@constCast(ptr)[0..@as(usize, count)]);
2580
- }
2581
-
2582
- export fn textBufferGetHighlightCount(tb_handle: NativeHandle) u32 {
2583
- const object_ptr = acquireTextBuffer(tb_handle) orelse return 0;
2584
- return object_ptr.getHighlightCount();
2585
- }
2586
-
2587
- export fn textBufferGetTextRange(tb_handle: NativeHandle, start_offset: u32, end_offset: u32, outPtr: ?[*]u8, maxLen: u32) u32 {
2588
- const object_ptr = acquireTextBuffer(tb_handle) orelse return 0;
2589
- if (maxLen == 0) return 0;
2590
-
2591
- const out = outPtr orelse return 0;
2592
- const outBuffer = out[0..@as(usize, maxLen)];
2593
- return @intCast(object_ptr.getTextRange(start_offset, end_offset, outBuffer));
2594
- }
2595
-
2596
- export fn textBufferGetTextRangeByCoords(tb_handle: NativeHandle, start_row: u32, start_col: u32, end_row: u32, end_col: u32, outPtr: ?[*]u8, maxLen: u32) u32 {
2597
- const object_ptr = acquireTextBuffer(tb_handle) orelse return 0;
2598
- if (maxLen == 0) return 0;
2599
-
2600
- const out = outPtr orelse return 0;
2601
- const outBuffer = out[0..@as(usize, maxLen)];
2602
- return @intCast(object_ptr.getTextRangeByCoords(start_row, start_col, end_row, end_col, outBuffer));
2603
- }
2604
-
2605
- // SyntaxStyle functions
2606
- export fn createSyntaxStyle() NativeHandle {
2607
- const style = syntax_style.SyntaxStyle.init(globalAllocator) catch |err| {
2608
- logger.err("Failed to create SyntaxStyle: {}", .{err});
2609
- return INVALID_HANDLE;
2610
- };
2611
- return handles.insert(.syntax_style, erasePtr(style)) catch {
2612
- style.deinit();
2613
- return INVALID_HANDLE;
2614
- };
2615
- }
2616
-
2617
- export fn destroySyntaxStyle(style_handle: NativeHandle) void {
2618
- const token = handles.beginDestroy(style_handle, .syntax_style, syntax_style.SyntaxStyle) orelse return;
2619
- token.ptr.deinit();
2620
- handles.finishDestroy(token.handle);
2621
- }
2622
-
2623
- export fn syntaxStyleRegister(style_handle: NativeHandle, namePtr: ?[*]const u8, nameLen: u32, fg: ?[*]const u16, bg: ?[*]const u16, attributes: u32) u32 {
2624
- const object_ptr = acquireSyntaxStyle(style_handle) orelse return 0;
2625
- const name = sliceFromPtrLen(namePtr, nameLen);
2626
- return object_ptr.registerStyleDefinition(name, .{
2627
- .fg = optionalPtrToRGBA(fg),
2628
- .bg = optionalPtrToRGBA(bg),
2629
- .attributes = attributes,
2630
- }) catch 0;
2631
- }
2632
-
2633
- export fn syntaxStyleResolveByName(style_handle: NativeHandle, namePtr: ?[*]const u8, nameLen: u32) u32 {
2634
- const object_ptr = acquireSyntaxStyle(style_handle) orelse return 0;
2635
- const name = sliceFromPtrLen(namePtr, nameLen);
2636
- return object_ptr.resolveByName(name) orelse 0;
2637
- }
2638
-
2639
- export fn syntaxStyleGetStyleCount(style_handle: NativeHandle) u32 {
2640
- const object_ptr = acquireSyntaxStyle(style_handle) orelse return 0;
2641
- return @intCast(object_ptr.getStyleCount());
2642
- }
2643
-
2644
- // Unicode encoding API
2645
-
2646
- pub const EncodedChar = extern struct {
2647
- width: u8,
2648
- char: u32,
2649
- };
2650
-
2651
- export fn encodeUnicode(
2652
- textPtr: ?[*]const u8,
2653
- textLen: u32,
2654
- outPtr: *?[*]EncodedChar,
2655
- outLenPtr: *usize,
2656
- widthMethod: u8,
2657
- ) bool {
2658
- const text = sliceFromPtrLen(textPtr, textLen);
2659
-
2660
- if (text.len == 0) {
2661
- outPtr.* = @ptrFromInt(0);
2662
- outLenPtr.* = 0;
2663
- return true;
2664
- }
2665
-
2666
- const pool = gp.initGlobalPool(globalArena);
2667
- const wMethod: utf8.WidthMethod = if (widthMethod == 0) .wcwidth else .unicode;
2668
-
2669
- // Check if ASCII only for optimization
2670
- const is_ascii_only = utf8.isAsciiOnly(text);
2671
-
2672
- // Find grapheme info
2673
- var grapheme_list: std.ArrayListUnmanaged(utf8.GraphemeInfo) = .{};
2674
- defer grapheme_list.deinit(globalAllocator);
2675
-
2676
- const tab_width: u8 = 2;
2677
- utf8.findGraphemeInfo(globalAllocator, text, tab_width, is_ascii_only, wMethod, &grapheme_list) catch return false;
2678
- const specials = grapheme_list.items;
2679
-
2680
- // Allocate output array
2681
- const estimated_count = if (is_ascii_only) text.len else text.len * 2;
2682
- var result = globalAllocator.alloc(EncodedChar, estimated_count) catch return false;
2683
- var result_idx: usize = 0;
2684
- var success = false;
2685
- var pending_gid: ?u32 = null; // Track grapheme allocated but not yet stored in result
2686
-
2687
- // Clean up result array and any allocated grapheme IDs on failure
2688
- defer {
2689
- if (!success) {
2690
- // Clean up pending grapheme that wasn't stored yet
2691
- if (pending_gid) |gid| {
2692
- // Try decref first (works if incref was called, refcount >= 1)
2693
- // If that fails (refcount was 0), use freeUnreferenced
2694
- pool.decref(gid) catch {
2695
- pool.freeUnreferenced(gid) catch {};
2696
- };
2697
- }
2698
- // Decref any grapheme IDs we allocated before the failure
2699
- for (result[0..result_idx]) |encoded_char| {
2700
- if (gp.isGraphemeChar(encoded_char.char)) {
2701
- const gid = gp.graphemeIdFromChar(encoded_char.char);
2702
- pool.decref(gid) catch {};
2703
- }
2704
- }
2705
- globalAllocator.free(result);
2706
- }
2707
- }
2708
-
2709
- var byte_offset: u32 = 0;
2710
- var col: u32 = 0;
2711
- var special_idx: usize = 0;
2712
-
2713
- while (byte_offset < text.len) {
2714
- const at_special = special_idx < specials.len and specials[special_idx].col_offset == col;
2715
-
2716
- var grapheme_bytes: []const u8 = undefined;
2717
- var g_width: u8 = undefined;
2718
-
2719
- if (at_special) {
2720
- const g = specials[special_idx];
2721
- grapheme_bytes = text[g.byte_offset .. g.byte_offset + g.byte_len];
2722
- g_width = g.width;
2723
- byte_offset = g.byte_offset + g.byte_len;
2724
- special_idx += 1;
2725
- } else {
2726
- if (byte_offset >= text.len) break;
2727
- grapheme_bytes = text[byte_offset .. byte_offset + 1];
2728
- g_width = 1;
2729
- byte_offset += 1;
2730
- }
2731
-
2732
- const cell_width = utf8.getWidthAt(text, if (at_special) specials[special_idx - 1].byte_offset else byte_offset - 1, tab_width, wMethod);
2733
- if (cell_width == 0) {
2734
- col += g_width;
2735
- continue;
2736
- }
2737
-
2738
- // Encode the character
2739
- var encoded_char: u32 = 0;
2740
- if (grapheme_bytes.len == 1 and cell_width == 1 and grapheme_bytes[0] >= 32) {
2741
- // Simple ASCII character
2742
- encoded_char = @as(u32, grapheme_bytes[0]);
2743
- } else {
2744
- // Multi-byte or special character - allocate in pool
2745
- const gid = pool.alloc(grapheme_bytes) catch return false;
2746
- pending_gid = gid; // Track until stored in result
2747
- encoded_char = gp.packGraphemeStart(gid & gp.GRAPHEME_ID_MASK, cell_width);
2748
-
2749
- // Incref since we're handing this off to the caller
2750
- // Note: incref can only fail if gid is invalid, which shouldn't happen
2751
- // for a freshly allocated gid. If it does fail, the slot leaks but
2752
- // this is an edge case that indicates a bug elsewhere.
2753
- pool.incref(gid) catch return false;
2754
- }
2755
-
2756
- // Ensure we have space
2757
- if (result_idx >= result.len) {
2758
- const new_len = result.len * 2;
2759
- result = globalAllocator.realloc(result, new_len) catch return false;
2760
- }
2761
-
2762
- result[result_idx] = EncodedChar{
2763
- .width = @intCast(cell_width),
2764
- .char = encoded_char,
2765
- };
2766
- pending_gid = null; // Successfully stored, no longer pending
2767
- result_idx += 1;
2768
- col += g_width;
2769
- }
2770
-
2771
- // Trim to actual size
2772
- result = globalAllocator.realloc(result, result_idx) catch result;
2773
-
2774
- outPtr.* = result.ptr;
2775
- outLenPtr.* = result_idx;
2776
- success = true;
2777
- return true;
2778
- }
2779
-
2780
- export fn freeUnicode(charsPtr: ?[*]const EncodedChar, charsLen: u32) void {
2781
- if (charsLen == 0 or charsPtr == null) {
2782
- return;
2783
- }
2784
-
2785
- const chars = charsPtr.?[0..@as(usize, charsLen)];
2786
- const pool = gp.initGlobalPool(globalArena);
2787
-
2788
- for (chars) |encoded_char| {
2789
- const char = encoded_char.char;
2790
-
2791
- // Check if this is a packed grapheme
2792
- if (gp.isGraphemeChar(char)) {
2793
- const gid = gp.graphemeIdFromChar(char);
2794
- pool.decref(gid) catch {};
2795
- }
2796
- }
2797
-
2798
- // Free the array itself
2799
- globalAllocator.free(chars);
2800
- }
2801
-
2802
- export fn bufferDrawChar(
2803
- buffer_handle: NativeHandle,
2804
- char: u32,
2805
- x: u32,
2806
- y: u32,
2807
- fg: [*]const u16,
2808
- bg: [*]const u16,
2809
- attributes: u32,
2810
- ) void {
2811
- const object_ptr = acquireBuffer(buffer_handle) orelse return;
2812
- object_ptr.drawChar(char, x, y, ptrToRGBA(fg), ptrToRGBA(bg), attributes);
2813
- }