quickwin 1.2.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/README.en.md +3 -3
  2. package/README.md +21 -24
  3. package/examples/PdfCanvas.js +8 -37
  4. package/examples/PdfCanvas.tsx +11 -41
  5. package/examples/exec_server.js +20054 -1423
  6. package/examples/exec_server.tsx +489 -0
  7. package/examples/exec_server_worker.js +383 -33
  8. package/examples/exec_server_worker.ts +408 -30
  9. package/examples/pdf_preview2.js +31 -73
  10. package/examples/pdf_preview2.ts +33 -76
  11. package/examples/pdf_viewer.js +1496 -616
  12. package/examples/pdf_viewer.tsx +23 -64
  13. package/examples/setres.js +22 -47
  14. package/examples/setres.ts +23 -57
  15. package/examples/test_gallery.js +1491 -525
  16. package/examples/test_react_lazy.js +1455 -500
  17. package/examples/test_react_listbox.js +1454 -499
  18. package/examples/test_root_window.js +1450 -495
  19. package/examples/test_tab.js +1455 -500
  20. package/lib/abort.js +70 -0
  21. package/lib/abort.ts +69 -0
  22. package/lib/certs.js +214 -0
  23. package/lib/certs.ts +224 -0
  24. package/lib/exec-log.js +15 -0
  25. package/lib/exec-log.ts +30 -0
  26. package/lib/fetch.js +37 -4
  27. package/lib/fetch.ts +35 -4
  28. package/lib/ffi/bind.js +352 -0
  29. package/lib/ffi/bind.ts +442 -0
  30. package/lib/ffi/ctype.js +168 -0
  31. package/lib/ffi/ctype.ts +331 -0
  32. package/lib/ffi/index.js +6 -0
  33. package/lib/ffi/index.ts +6 -0
  34. package/lib/ffi/struct.js +412 -0
  35. package/lib/ffi/struct.ts +664 -0
  36. package/lib/http-common.js +43 -5
  37. package/lib/http-common.ts +48 -6
  38. package/lib/http-server.js +187 -29
  39. package/lib/http-server.ts +177 -26
  40. package/lib/react-qw/components/DateTimePicker.js +20 -33
  41. package/lib/react-qw/components/Input.js +3 -10
  42. package/lib/react-qw/components/Link.js +7 -22
  43. package/lib/react-qw/components/ListView.js +80 -141
  44. package/lib/react-qw/components/PathPicker.js +36 -80
  45. package/lib/react-qw/components/ScrollView.js +15 -8
  46. package/lib/react-qw/components/Slider.js +2 -1
  47. package/lib/react-qw/components/Tab.js +15 -20
  48. package/lib/react-qw/components/Tooltip.js +21 -20
  49. package/lib/react-qw/components/TreeView.js +14 -47
  50. package/lib/react-qw/index.js +4 -2
  51. package/lib/react-qw/index.ts +4 -2
  52. package/lib/react-qw/nmhdr.js +5 -0
  53. package/lib/react-qw/nmhdr.ts +7 -0
  54. package/lib/react-qw/props.js +7 -2
  55. package/lib/react-qw/props.ts +7 -3
  56. package/lib/react-qw/reconciler.js +23 -13
  57. package/lib/react-qw/reconciler.ts +22 -13
  58. package/lib/text-measure.js +18 -35
  59. package/lib/text-measure.ts +20 -37
  60. package/lib/websocket.js +12 -2
  61. package/lib/websocket.ts +15 -2
  62. package/lib/windows/comctl32.js +18 -0
  63. package/lib/windows/comctl32.ts +20 -0
  64. package/lib/windows/comdlg32.js +7 -0
  65. package/lib/windows/comdlg32.ts +9 -0
  66. package/lib/windows/gdi32.js +90 -0
  67. package/lib/windows/gdi32.ts +97 -0
  68. package/lib/windows/kernel32.js +66 -0
  69. package/lib/windows/kernel32.ts +76 -0
  70. package/lib/windows/ntdll.js +8 -0
  71. package/lib/windows/ntdll.ts +10 -0
  72. package/lib/windows/ole32.js +7 -0
  73. package/lib/windows/ole32.ts +9 -0
  74. package/lib/windows/shell32.js +11 -0
  75. package/lib/windows/shell32.ts +14 -0
  76. package/lib/windows/structs.js +384 -0
  77. package/lib/windows/structs.ts +422 -0
  78. package/lib/windows/user32.js +469 -0
  79. package/lib/windows/user32.ts +502 -0
  80. package/package.json +1 -1
  81. package/quickwin.d.ts +22 -33
  82. package/quickwin_const.d.ts +1 -0
  83. package/qwin-nowasm-x86.exe +0 -0
  84. package/qwin-nowasm.exe +0 -0
  85. package/qwin-x86.exe +0 -0
  86. package/qwin.exe +0 -0
  87. package/test/bench_ffi_callraw.js +236 -0
  88. package/test/bench_ffi_callraw.ts +236 -0
  89. package/test/bench_ffi_overhead.js +139 -0
  90. package/test/bench_ffi_overhead.ts +141 -0
  91. package/test/bench_sendmessage.js +104 -0
  92. package/test/bench_sendmessage.ts +100 -0
  93. package/test/bench_sendmessage_nonnull.js +187 -0
  94. package/test/bench_sendmessage_nonnull.ts +188 -0
  95. package/test/run.js +14 -4
  96. package/test/run.ts +15 -5
  97. package/test/test_basic_fetch.js +8 -0
  98. package/test/test_basic_fetch.ts +9 -0
  99. package/test/test_ffi.js +33 -47
  100. package/test/test_ffi.ts +41 -60
  101. package/test/test_ffi_abi.js +235 -0
  102. package/test/test_ffi_abi.ts +218 -0
  103. package/test/test_ffi_bind.js +572 -0
  104. package/test/test_ffi_bind.ts +597 -0
  105. package/test/test_ffi_struct.js +745 -0
  106. package/test/test_ffi_struct.ts +798 -0
  107. package/test/test_ffi_struct_layout.js +495 -0
  108. package/test/test_ffi_struct_layout.ts +543 -0
  109. package/test/test_ffi_user32.js +103 -0
  110. package/test/test_ffi_user32.ts +113 -0
  111. package/test/test_ffi_windows.js +101 -0
  112. package/test/test_ffi_windows.ts +113 -0
  113. package/test/test_helper.js +8 -1
  114. package/test/test_helper.ts +9 -1
  115. package/test/test_http_import.js +18 -0
  116. package/test/test_http_import.ts +19 -0
  117. package/test/test_http_server.js +73 -1
  118. package/test/test_http_server.ts +75 -1
  119. package/test/test_ipv6.js +2 -2
  120. package/test/test_ipv6.ts +2 -2
  121. package/test/test_net_fetch.js +70 -8
  122. package/test/test_net_fetch.ts +69 -7
  123. package/test/test_net_websocket.js +1 -1
  124. package/test/test_net_websocket.ts +1 -1
  125. package/test/test_react_complex.js +1465 -510
  126. package/test/test_react_counter.js +1455 -500
  127. package/test/test_react_flex.js +1475 -513
  128. package/test/test_react_hidden.js +1458 -503
  129. package/test/test_react_listview_link.js +1455 -500
  130. package/test/test_react_notify.js +18534 -0
  131. package/test/test_react_render.js +1455 -500
  132. package/test/test_wolfssl_read.js +3 -2
  133. package/test/test_wolfssl_read.ts +3 -1
  134. package/test/test_worker_net.js +35 -17
  135. package/test/test_worker_net.ts +27 -15
  136. package/tsconfig.json +1 -1
  137. package/examples/exec_server.ts +0 -80
@@ -1,67 +1,26 @@
1
+ import { PtrArrayBuffer } from '../lib/ffi/ctype.js'
1
2
  import '../lib/polyfill.js'
2
3
  import * as std from 'std'
3
4
  import * as gui from 'gui'
4
- import * as win from 'win'
5
- import * as ffi from 'ffi'
6
5
  import type { Document, Page, Pixmap } from '../vendor/mupdf-wasm/mupdf.js'
7
6
  import { assertNonNullable } from '../lib/assert.js'
8
-
9
- const FFI_PTR = ffi.FFI_TYPE_POINTER
10
- const FFI_U32 = ffi.FFI_TYPE_UINT32
11
- const FFI_S32 = ffi.FFI_TYPE_SINT32
12
-
13
- const _user32 = win.LoadLibrary('user32.dll')
14
- const _gdi32 = win.LoadLibrary('gdi32.dll')
15
- const _comdlg32 = win.LoadLibrary('comdlg32.dll')
7
+ import { WCHAR } from '../lib/ffi/bind.js'
8
+ import { BITMAPINFOHEADER, OPENFILENAMEW } from '../lib/windows/structs.js'
9
+ import { GetOpenFileName } from '../lib/windows/comdlg32.js'
10
+ import { GetDC, ReleaseDC } from '../lib/windows/user32.js'
11
+ import { PatBlt, SetDIBitsToDevice } from '../lib/windows/gdi32.js'
16
12
 
17
13
  type MuPdf = typeof import('../vendor/mupdf-wasm/mupdf.js')
18
- if (!(_user32 && _gdi32 && _comdlg32)) std.exit(0)
19
-
20
- function loadProc(lib: win.HMODULE, name: string): number {
21
- const ptr = win.GetProcAddress(lib, name)
22
- if (!ptr) { std.printf('Error: cannot load %s\n', name); std.exit(1) }
23
- return ptr
24
- }
25
14
 
26
- const GetOpenFileNameW = loadProc(_comdlg32, 'GetOpenFileNameW')
27
- const SetDIBitsToDevice = loadProc(_gdi32, 'SetDIBitsToDevice')
28
- const GetDC = loadProc(_user32, 'GetDC')
29
- const ReleaseDC = loadProc(_user32, 'ReleaseDC')
30
- const PatBlt = loadProc(_gdi32, 'PatBlt')
31
15
  const WHITENESS = 0x00FF0062
32
16
 
33
- function makeBitmapInfo(w: number, h: number): ArrayBuffer {
34
- const bmi = new ArrayBuffer(40)
35
- const bv = new DataView(bmi)
36
- bv.setUint32(0, 40, true)
37
- bv.setInt32(4, w, true)
38
- bv.setInt32(8, -h, true)
39
- bv.setUint16(12, 1, true)
40
- bv.setUint16(14, 24, true)
41
- return bmi
42
- }
43
-
44
- function strToWide(str: string): ArrayBuffer {
45
- return new TextEncoder('utf-16le').encode(str + '\0').buffer
46
- }
47
-
48
- function wideToStr(buf: ArrayBuffer): string {
49
- const dv = new DataView(buf)
50
- const chars: number[] = []
51
- for (let i = 0; i < buf.byteLength; i += 2) {
52
- const c = dv.getUint16(i, true); if (c === 0) break
53
- chars.push(c)
54
- }
55
- return String.fromCharCode(...chars)
56
- }
57
-
58
- function setPtr(dv: DataView, off: number, ptr: number): void {
59
- dv.setUint32(off, ptr & 0xFFFFFFFF, true)
60
- dv.setUint32(off + 4, Math.floor(ptr / 0x100000000), true)
17
+ function makeBitmapInfo(w: number, h: number) {
18
+ // biHeight 负 = 自顶向下(DIB 原点左上);biCompression 缺省 0 = BI_RGB 无压缩
19
+ return BITMAPINFOHEADER.encode({ biSize: BITMAPINFOHEADER.size, biWidth: w, biHeight: -h, biPlanes: 1, biBitCount: 24 })
61
20
  }
62
21
 
63
22
  interface PixmapInfo {
64
- data: ArrayBuffer; w: number; h: number
23
+ data: PtrArrayBuffer<string>; w: number; h: number
65
24
  }
66
25
 
67
26
  let hwndMain: gui.HWND | null = null
@@ -117,7 +76,8 @@ function renderPdfPage(mupdf: MuPdf, filePath: string, pageIndex: number): Pixma
117
76
  const srcStride = pixmap.getStride()
118
77
  const w = pixmap.getWidth(), h = pixmap.getHeight()
119
78
  const dibStride = Math.floor((w * 3 + 3) / 4) * 4
120
- const dib = new Uint8Array(h * dibStride)
79
+ const dibBuffer = new PtrArrayBuffer(h * dibStride)
80
+ const dib = new Uint8Array(dibBuffer)
121
81
  for (let y = 0; y < h; y++) {
122
82
  const srcOff = y * srcStride, dstOff = y * dibStride
123
83
  for (let x = 0; x < w; x++) {
@@ -126,25 +86,27 @@ function renderPdfPage(mupdf: MuPdf, filePath: string, pageIndex: number): Pixma
126
86
  }
127
87
  }
128
88
  const totalPages = cachedDoc.countPages()
129
- return { data: dib.buffer, w, h, totalPages }
89
+ return { data: dibBuffer, w, h, totalPages }
130
90
  } catch (e) { std.printf('Error rendering: %s\n', String(e)); clearCachedDoc(); return null }
131
91
  finally { if (pixmap) try { pixmap.destroy() } catch {}; if (page) try { page.destroy() } catch {} }
132
92
  }
133
93
 
134
94
  function openPdfFileDialog(): string | null {
135
95
  assertNonNullable(hwndMain)
136
- const structBuf = new ArrayBuffer(152), sv = new DataView(structBuf)
137
- const fileBuf = new ArrayBuffer(260 * 2)
138
- const filterWide = strToWide('PDF Files\0*.pdf\0All Files\0*.*\0\0')
139
- sv.setUint32(0, 152, true)
140
- sv.setUint32(8, hwndMain & 0xFFFFFFFF, true)
141
- sv.setUint32(12, Math.floor(hwndMain / 0x100000000), true)
142
- setPtr(sv, 24, ffi.bufferPtr(filterWide))
143
- setPtr(sv, 48, ffi.bufferPtr(fileBuf))
144
- sv.setUint32(56, 260, true)
145
- sv.setUint32(96, 0x1000 | 0x0800 | 0x0004, true)
146
- const ret = ffi.ffiCall(GetOpenFileNameW, [FFI_PTR], [structBuf], FFI_U32)
147
- return ret ? wideToStr(fileBuf) : null
96
+ const fileBuf = WCHAR.alloc(260)
97
+ const filterWide = WCHAR.encode('PDF Files\0*.pdf\0All Files\0*.*\0\0')
98
+ // 缺省字段跳过 = fresh buffer 上留 0
99
+ const ofn: PtrArrayBuffer<'OPENFILENAMEW'> & { __keep?: ArrayBuffer[] } = OPENFILENAMEW.encode({
100
+ lStructSize: OPENFILENAMEW.size,
101
+ hwndOwner: hwndMain,
102
+ lpstrFilter: filterWide.ptr,
103
+ lpstrFile: fileBuf.ptr,
104
+ nMaxFile: 260,
105
+ Flags: 0x1000 | 0x0800 | 0x0004,
106
+ })
107
+ ofn.__keep = [fileBuf, filterWide]
108
+ const ret = GetOpenFileName(ofn)
109
+ return ret ? WCHAR.decode(fileBuf) : null
148
110
  }
149
111
 
150
112
  function updateScrollRange(): void {
@@ -299,15 +261,11 @@ let hwndBtnNext: gui.HWND | null = null
299
261
  gui.DefWindowProc(hwnd, msg, wParam, lParam)
300
262
  const pm = currentPixmap
301
263
  if (!pm) return 0
302
- const hdc = ffi.ffiCall(GetDC, [ffi.FFI_TYPE_UINT64], [hwnd], ffi.FFI_TYPE_UINT64)
264
+ const hdc = GetDC(hwnd)
303
265
  if (hdc) {
304
266
  const bmi = makeBitmapInfo(pm.w, pm.h)
305
- ffi.ffiCall(SetDIBitsToDevice, [
306
- ffi.FFI_TYPE_UINT64, FFI_S32, FFI_S32, FFI_U32, FFI_U32,
307
- FFI_S32, FFI_S32, FFI_U32, FFI_U32,
308
- FFI_PTR, FFI_PTR, FFI_U32
309
- ], [hdc, 0, 0, pm.w, pm.h, 0, 0, 0, pm.h, pm.data, bmi, 0], FFI_S32)
310
- ffi.ffiCall(ReleaseDC, [ffi.FFI_TYPE_UINT64, ffi.FFI_TYPE_UINT64], [hwnd, hdc], FFI_S32)
267
+ SetDIBitsToDevice(hdc, 0, 0, pm.w, pm.h, 0, 0, 0, pm.h, pm.data, bmi, 0)
268
+ ReleaseDC(hwnd, hdc)
311
269
  }
312
270
  return 0
313
271
  }
@@ -321,11 +279,10 @@ let hwndBtnNext: gui.HWND | null = null
321
279
  const cr = gui.GetClientRect(hwnd)
322
280
  if (cr) {
323
281
  const cw = cr.right - cr.left, ch = cr.bottom - cr.top
324
- const hdc = ffi.ffiCall(GetDC, [ffi.FFI_TYPE_UINT64], [hwnd], ffi.FFI_TYPE_UINT64)
282
+ const hdc = GetDC(hwnd)
325
283
  if (hdc) {
326
- ffi.ffiCall(PatBlt, [ffi.FFI_TYPE_UINT64, FFI_S32, FFI_S32, FFI_S32, FFI_S32, FFI_U32],
327
- [hdc, 0, 0, cw, ch, WHITENESS], FFI_U32)
328
- ffi.ffiCall(ReleaseDC, [ffi.FFI_TYPE_UINT64, ffi.FFI_TYPE_UINT64], [hwnd, hdc], FFI_S32)
284
+ PatBlt(hdc, 0, 0, cw, ch, WHITENESS)
285
+ ReleaseDC(hwnd, hdc)
329
286
  }
330
287
  }
331
288
  gui.DefWindowProc(hwnd, msg, wParam, lParam)