@socketsecurity/cli-with-sentry 0.14.137 → 0.14.139

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 (109) hide show
  1. package/dist/blessed/LICENSE +20 -0
  2. package/dist/blessed/lib/alias.js +519 -0
  3. package/dist/blessed/lib/blessed.js +32 -0
  4. package/dist/blessed/lib/colors.js +490 -0
  5. package/dist/blessed/lib/events.js +195 -0
  6. package/dist/blessed/lib/gpmclient.js +245 -0
  7. package/dist/blessed/lib/helpers.js +170 -0
  8. package/dist/blessed/lib/keys.js +512 -0
  9. package/dist/blessed/lib/program.js +4530 -0
  10. package/dist/blessed/lib/tput.js +3111 -0
  11. package/dist/blessed/lib/unicode.js +912 -0
  12. package/dist/blessed/lib/widget.js +60 -0
  13. package/dist/blessed/lib/widgets/ansiimage.js +173 -0
  14. package/dist/blessed/lib/widgets/bigtext.js +170 -0
  15. package/dist/blessed/lib/widgets/box.js +34 -0
  16. package/dist/blessed/lib/widgets/button.js +62 -0
  17. package/dist/blessed/lib/widgets/checkbox.js +95 -0
  18. package/dist/blessed/lib/widgets/element.js +2871 -0
  19. package/dist/blessed/lib/widgets/filemanager.js +223 -0
  20. package/dist/blessed/lib/widgets/form.js +301 -0
  21. package/dist/blessed/lib/widgets/image.js +71 -0
  22. package/dist/blessed/lib/widgets/input.js +34 -0
  23. package/dist/blessed/lib/widgets/layout.js +249 -0
  24. package/dist/blessed/lib/widgets/line.js +59 -0
  25. package/dist/blessed/lib/widgets/list.js +652 -0
  26. package/dist/blessed/lib/widgets/listbar.js +452 -0
  27. package/dist/blessed/lib/widgets/listtable.js +265 -0
  28. package/dist/blessed/lib/widgets/loading.js +88 -0
  29. package/dist/blessed/lib/widgets/log.js +82 -0
  30. package/dist/blessed/lib/widgets/message.js +145 -0
  31. package/dist/blessed/lib/widgets/node.js +314 -0
  32. package/dist/blessed/lib/widgets/overlayimage.js +794 -0
  33. package/dist/blessed/lib/widgets/progressbar.js +166 -0
  34. package/dist/blessed/lib/widgets/prompt.js +127 -0
  35. package/dist/blessed/lib/widgets/question.js +129 -0
  36. package/dist/blessed/lib/widgets/radiobutton.js +62 -0
  37. package/dist/blessed/lib/widgets/radioset.js +36 -0
  38. package/dist/blessed/lib/widgets/screen.js +2485 -0
  39. package/dist/blessed/lib/widgets/scrollablebox.js +415 -0
  40. package/dist/blessed/lib/widgets/scrollabletext.js +35 -0
  41. package/dist/blessed/lib/widgets/table.js +383 -0
  42. package/dist/blessed/lib/widgets/terminal.js +452 -0
  43. package/dist/blessed/lib/widgets/text.js +35 -0
  44. package/dist/blessed/lib/widgets/textarea.js +376 -0
  45. package/dist/blessed/lib/widgets/textbox.js +79 -0
  46. package/dist/blessed/lib/widgets/video.js +130 -0
  47. package/dist/blessed/usr/fonts/AUTHORS +1 -0
  48. package/dist/blessed/usr/fonts/LICENSE +94 -0
  49. package/dist/blessed/usr/fonts/README +340 -0
  50. package/dist/blessed/usr/fonts/ter-u14b.json +17826 -0
  51. package/dist/blessed/usr/fonts/ter-u14n.json +17826 -0
  52. package/dist/blessed/usr/linux +0 -0
  53. package/dist/blessed/usr/windows-ansi +0 -0
  54. package/dist/blessed/usr/xterm +0 -0
  55. package/dist/blessed/usr/xterm-256color +0 -0
  56. package/dist/blessed/usr/xterm.termcap +243 -0
  57. package/dist/blessed/usr/xterm.terminfo +1977 -0
  58. package/dist/blessed/vendor/tng.js +1876 -0
  59. package/dist/blessed-contrib/LICENSE.md +21 -0
  60. package/dist/blessed-contrib/lib/layout/carousel.js +82 -0
  61. package/dist/blessed-contrib/lib/layout/grid.js +46 -0
  62. package/dist/blessed-contrib/lib/server-utils.js +83 -0
  63. package/dist/blessed-contrib/lib/utils.js +73 -0
  64. package/dist/blessed-contrib/lib/widget/canvas.js +52 -0
  65. package/dist/blessed-contrib/lib/widget/charts/bar.js +99 -0
  66. package/dist/blessed-contrib/lib/widget/charts/line.js +311 -0
  67. package/dist/blessed-contrib/lib/widget/charts/stacked-bar.js +245 -0
  68. package/dist/blessed-contrib/lib/widget/donut.js +183 -0
  69. package/dist/blessed-contrib/lib/widget/gauge-list.js +111 -0
  70. package/dist/blessed-contrib/lib/widget/gauge.js +127 -0
  71. package/dist/blessed-contrib/lib/widget/lcd.js +497 -0
  72. package/dist/blessed-contrib/lib/widget/log.js +32 -0
  73. package/dist/blessed-contrib/lib/widget/map.js +97 -0
  74. package/dist/blessed-contrib/lib/widget/markdown.js +68 -0
  75. package/dist/blessed-contrib/lib/widget/picture.js +61 -0
  76. package/dist/blessed-contrib/lib/widget/sparkline.js +66 -0
  77. package/dist/blessed-contrib/lib/widget/table.js +141 -0
  78. package/dist/blessed-contrib/lib/widget/tree.js +179 -0
  79. package/dist/blessed-contrib/node_modules/ansi-regex/index.js +6 -0
  80. package/dist/blessed-contrib/node_modules/ansi-regex/license +21 -0
  81. package/dist/blessed-contrib/node_modules/ansi-regex/package.json +64 -0
  82. package/dist/blessed-contrib/node_modules/ansi-regex/readme.md +39 -0
  83. package/dist/blessed-contrib/node_modules/ansi-styles/index.js +67 -0
  84. package/dist/blessed-contrib/node_modules/ansi-styles/license +21 -0
  85. package/dist/blessed-contrib/node_modules/ansi-styles/package.json +50 -0
  86. package/dist/blessed-contrib/node_modules/ansi-styles/readme.md +86 -0
  87. package/dist/blessed-contrib/node_modules/chalk/index.js +118 -0
  88. package/dist/blessed-contrib/node_modules/chalk/license +21 -0
  89. package/dist/blessed-contrib/node_modules/chalk/package.json +70 -0
  90. package/dist/blessed-contrib/node_modules/chalk/readme.md +213 -0
  91. package/dist/blessed-contrib/node_modules/escape-string-regexp/index.js +13 -0
  92. package/dist/blessed-contrib/node_modules/escape-string-regexp/license +21 -0
  93. package/dist/blessed-contrib/node_modules/escape-string-regexp/package.json +41 -0
  94. package/dist/blessed-contrib/node_modules/escape-string-regexp/readme.md +27 -0
  95. package/dist/blessed-contrib/node_modules/strip-ansi/index.js +8 -0
  96. package/dist/blessed-contrib/node_modules/strip-ansi/license +21 -0
  97. package/dist/blessed-contrib/node_modules/strip-ansi/package.json +57 -0
  98. package/dist/blessed-contrib/node_modules/strip-ansi/readme.md +33 -0
  99. package/dist/blessed-contrib/node_modules/supports-color/index.js +52 -0
  100. package/dist/blessed-contrib/node_modules/supports-color/license +21 -0
  101. package/dist/blessed-contrib/node_modules/supports-color/package.json +49 -0
  102. package/dist/blessed-contrib/node_modules/supports-color/readme.md +36 -0
  103. package/dist/cli.js +9 -8
  104. package/dist/cli.js.map +1 -1
  105. package/dist/instrument-with-sentry.js +2 -2
  106. package/dist/instrument-with-sentry.js.map +1 -1
  107. package/dist/shadow-npm-inject.js +2 -2
  108. package/dist/shadow-npm-inject.js.map +1 -1
  109. package/package.json +4 -4
@@ -0,0 +1,2485 @@
1
+ /**
2
+ * screen.js - screen node for blessed
3
+ * Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
4
+ * https://github.com/chjj/blessed
5
+ */
6
+
7
+ /**
8
+ * Modules
9
+ */
10
+
11
+ const path = require('node:path'),
12
+ fs = require('node:fs'),
13
+ cp = require('node:child_process')
14
+
15
+ const colors = require('../colors'),
16
+ program = require('../program'),
17
+ unicode = require('../unicode')
18
+
19
+ const nextTick = global.setImmediate || process.nextTick.bind(process)
20
+
21
+ const Node = require('./node')
22
+
23
+ /**
24
+ * Screen
25
+ */
26
+
27
+ function Screen(options) {
28
+ const self = this
29
+ if (!(this instanceof Node)) {
30
+ return new Screen(options)
31
+ }
32
+
33
+ Screen.bind(this)
34
+
35
+ options = options || {}
36
+ if (options.rsety && options.listen) {
37
+ options = { program: options }
38
+ }
39
+
40
+ this.program = options.program
41
+
42
+ if (!this.program) {
43
+ this.program = program({
44
+ input: options.input,
45
+ output: options.output,
46
+ log: options.log,
47
+ debug: options.debug,
48
+ dump: options.dump,
49
+ terminal: options.terminal || options.term,
50
+ resizeTimeout: options.resizeTimeout,
51
+ forceUnicode: options.forceUnicode,
52
+ tput: true,
53
+ buffer: true,
54
+ zero: true
55
+ })
56
+ } else {
57
+ this.program.setupTput()
58
+ this.program.useBuffer = true
59
+ this.program.zero = true
60
+ this.program.options.resizeTimeout = options.resizeTimeout
61
+ if (options.forceUnicode != null) {
62
+ this.program.tput.features.unicode = options.forceUnicode
63
+ this.program.tput.unicode = options.forceUnicode
64
+ }
65
+ }
66
+
67
+ this.tput = this.program.tput
68
+
69
+ Node.call(this, options)
70
+
71
+ this.autoPadding = options.autoPadding !== false
72
+ this.tabc = Array((options.tabSize || 4) + 1).join(' ')
73
+ this.dockBorders = options.dockBorders
74
+
75
+ this.ignoreLocked = options.ignoreLocked || []
76
+
77
+ this._unicode = this.tput.unicode || this.tput.numbers.U8 === 1
78
+ this.fullUnicode = this.options.fullUnicode && this._unicode
79
+
80
+ this.dattr = (0 << 18) | (0x1ff << 9) | 0x1ff
81
+
82
+ this.renders = 0
83
+ this.position = {
84
+ left: (this.left = this.aleft = this.rleft = 0),
85
+ right: (this.right = this.aright = this.rright = 0),
86
+ top: (this.top = this.atop = this.rtop = 0),
87
+ bottom: (this.bottom = this.abottom = this.rbottom = 0),
88
+ get height() {
89
+ return self.height
90
+ },
91
+ get width() {
92
+ return self.width
93
+ }
94
+ }
95
+
96
+ this.ileft = 0
97
+ this.itop = 0
98
+ this.iright = 0
99
+ this.ibottom = 0
100
+ this.iheight = 0
101
+ this.iwidth = 0
102
+
103
+ this.padding = {
104
+ left: 0,
105
+ top: 0,
106
+ right: 0,
107
+ bottom: 0
108
+ }
109
+
110
+ this.hover = null
111
+ this.history = []
112
+ this.clickable = []
113
+ this.keyable = []
114
+ this.grabKeys = false
115
+ this.lockKeys = false
116
+ this.focused
117
+ this._buf = ''
118
+
119
+ this._ci = -1
120
+
121
+ if (options.title) {
122
+ this.title = options.title
123
+ }
124
+
125
+ options.cursor = options.cursor || {
126
+ artificial: options.artificialCursor,
127
+ shape: options.cursorShape,
128
+ blink: options.cursorBlink,
129
+ color: options.cursorColor
130
+ }
131
+
132
+ this.cursor = {
133
+ artificial: options.cursor.artificial || false,
134
+ shape: options.cursor.shape || 'block',
135
+ blink: options.cursor.blink || false,
136
+ color: options.cursor.color || null,
137
+ _set: false,
138
+ _state: 1,
139
+ _hidden: true
140
+ }
141
+
142
+ this.program.on('resize', function () {
143
+ self.alloc()
144
+ self.render()
145
+ ;(function emit(el) {
146
+ el.emit('resize')
147
+ el.children.forEach(emit)
148
+ })(self)
149
+ })
150
+
151
+ this.program.on('focus', function () {
152
+ self.emit('focus')
153
+ })
154
+
155
+ this.program.on('blur', function () {
156
+ self.emit('blur')
157
+ })
158
+
159
+ this.program.on('warning', function (text) {
160
+ self.emit('warning', text)
161
+ })
162
+
163
+ this.on('newListener', function fn(type) {
164
+ if (type === 'keypress' || type.indexOf('key ') === 0 || type === 'mouse') {
165
+ if (type === 'keypress' || type.indexOf('key ') === 0) {
166
+ self._listenKeys()
167
+ }
168
+ if (type === 'mouse') {
169
+ self._listenMouse()
170
+ }
171
+ }
172
+ if (
173
+ type === 'mouse' ||
174
+ type === 'click' ||
175
+ type === 'mouseover' ||
176
+ type === 'mouseout' ||
177
+ type === 'mousedown' ||
178
+ type === 'mouseup' ||
179
+ type === 'mousewheel' ||
180
+ type === 'wheeldown' ||
181
+ type === 'wheelup' ||
182
+ type === 'mousemove'
183
+ ) {
184
+ self._listenMouse()
185
+ }
186
+ })
187
+
188
+ this.setMaxListeners(Infinity)
189
+
190
+ this.enter()
191
+
192
+ this.postEnter()
193
+ }
194
+
195
+ Screen.global = null
196
+
197
+ Screen.total = 0
198
+
199
+ Screen.instances = []
200
+
201
+ Screen.bind = function (screen) {
202
+ if (!Screen.global) {
203
+ Screen.global = screen
204
+ }
205
+
206
+ if (!~Screen.instances.indexOf(screen)) {
207
+ Screen.instances.push(screen)
208
+ screen.index = Screen.total
209
+ Screen.total++
210
+ }
211
+
212
+ if (Screen._bound) {
213
+ return
214
+ }
215
+ Screen._bound = true
216
+
217
+ process.on(
218
+ 'uncaughtException',
219
+ (Screen._exceptionHandler = function (err) {
220
+ if (process.listeners('uncaughtException').length > 1) {
221
+ return
222
+ }
223
+ Screen.instances.slice().forEach(function (screen) {
224
+ screen.destroy()
225
+ })
226
+ err = err || new Error('Uncaught Exception.')
227
+ console.error(err.stack ? err.stack + '' : err + '')
228
+ nextTick(function () {
229
+ process.exit(1)
230
+ })
231
+ })
232
+ )
233
+
234
+ ;['SIGTERM', 'SIGINT', 'SIGQUIT'].forEach(function (signal) {
235
+ const name = '_' + signal.toLowerCase() + 'Handler'
236
+ process.on(
237
+ signal,
238
+ (Screen[name] = function () {
239
+ if (process.listeners(signal).length > 1) {
240
+ return
241
+ }
242
+ nextTick(function () {
243
+ process.exit(0)
244
+ })
245
+ })
246
+ )
247
+ })
248
+
249
+ process.on(
250
+ 'exit',
251
+ (Screen._exitHandler = function () {
252
+ Screen.instances.slice().forEach(function (screen) {
253
+ screen.destroy()
254
+ })
255
+ })
256
+ )
257
+ }
258
+
259
+ Object.setPrototypeOf(Screen.prototype, Node.prototype)
260
+
261
+ Screen.prototype.type = 'screen'
262
+
263
+ Screen.prototype.__defineGetter__('title', function () {
264
+ return this.program.title
265
+ })
266
+
267
+ Screen.prototype.__defineSetter__('title', function (title) {
268
+ return (this.program.title = title)
269
+ })
270
+
271
+ Screen.prototype.__defineGetter__('terminal', function () {
272
+ return this.program.terminal
273
+ })
274
+
275
+ Screen.prototype.__defineSetter__('terminal', function (terminal) {
276
+ this.setTerminal(terminal)
277
+ return this.program.terminal
278
+ })
279
+
280
+ Screen.prototype.setTerminal = function (terminal) {
281
+ const entered = !!this.program.isAlt
282
+ if (entered) {
283
+ this._buf = ''
284
+ this.program._buf = ''
285
+ this.leave()
286
+ }
287
+ this.program.setTerminal(terminal)
288
+ this.tput = this.program.tput
289
+ if (entered) {
290
+ this.enter()
291
+ }
292
+ }
293
+
294
+ Screen.prototype.enter = function () {
295
+ if (this.program.isAlt) {
296
+ return
297
+ }
298
+ if (!this.cursor._set) {
299
+ if (this.options.cursor.shape) {
300
+ this.cursorShape(this.cursor.shape, this.cursor.blink)
301
+ }
302
+ if (this.options.cursor.color) {
303
+ this.cursorColor(this.cursor.color)
304
+ }
305
+ }
306
+ if (process.platform === 'win32') {
307
+ try {
308
+ cp.execSync('cls', { stdio: 'ignore', timeout: 1000 })
309
+ } catch (e) {}
310
+ }
311
+ this.program.alternateBuffer()
312
+ this.program.put.keypad_xmit()
313
+ this.program.csr(0, this.height - 1)
314
+ this.program.hideCursor()
315
+ this.program.cup(0, 0)
316
+ // We need this for tmux now:
317
+ if (this.tput.strings.ena_acs) {
318
+ this.program._write(this.tput.enacs())
319
+ }
320
+ this.alloc()
321
+ }
322
+
323
+ Screen.prototype.leave = function () {
324
+ if (!this.program.isAlt) {
325
+ return
326
+ }
327
+ this.program.put.keypad_local()
328
+ if (
329
+ this.program.scrollTop !== 0 ||
330
+ this.program.scrollBottom !== this.rows - 1
331
+ ) {
332
+ this.program.csr(0, this.height - 1)
333
+ }
334
+ // XXX For some reason if alloc/clear() is before this
335
+ // line, it doesn't work on linux console.
336
+ this.program.showCursor()
337
+ this.alloc()
338
+ if (this._listenedMouse) {
339
+ this.program.disableMouse()
340
+ }
341
+ this.program.normalBuffer()
342
+ if (this.cursor._set) {
343
+ this.cursorReset()
344
+ }
345
+ this.program.flush()
346
+ if (process.platform === 'win32') {
347
+ try {
348
+ cp.execSync('cls', { stdio: 'ignore', timeout: 1000 })
349
+ } catch (e) {}
350
+ }
351
+ }
352
+
353
+ Screen.prototype.postEnter = function () {
354
+ const self = this
355
+ if (this.options.debug) {
356
+ const Log = require('./log')
357
+ this.debugLog = new Log({
358
+ screen: this,
359
+ parent: this,
360
+ hidden: true,
361
+ draggable: true,
362
+ left: 'center',
363
+ top: 'center',
364
+ width: '30%',
365
+ height: '30%',
366
+ border: 'line',
367
+ label: ' {bold}Debug Log{/bold} ',
368
+ tags: true,
369
+ keys: true,
370
+ vi: true,
371
+ mouse: true,
372
+ scrollbar: {
373
+ ch: ' ',
374
+ track: {
375
+ bg: 'yellow'
376
+ },
377
+ style: {
378
+ inverse: true
379
+ }
380
+ }
381
+ })
382
+
383
+ this.debugLog.toggle = function () {
384
+ if (self.debugLog.hidden) {
385
+ self.saveFocus()
386
+ self.debugLog.show()
387
+ self.debugLog.setFront()
388
+ self.debugLog.focus()
389
+ } else {
390
+ self.debugLog.hide()
391
+ self.restoreFocus()
392
+ }
393
+ self.render()
394
+ }
395
+
396
+ this.debugLog.key(['q', 'escape'], self.debugLog.toggle)
397
+ this.key('f12', self.debugLog.toggle)
398
+ }
399
+
400
+ if (this.options.warnings) {
401
+ this.on('warning', function (text) {
402
+ const Box = require('./box')
403
+ const warning = new Box({
404
+ screen: self,
405
+ parent: self,
406
+ left: 'center',
407
+ top: 'center',
408
+ width: 'shrink',
409
+ padding: 1,
410
+ height: 'shrink',
411
+ align: 'center',
412
+ valign: 'middle',
413
+ border: 'line',
414
+ label: ' {red-fg}{bold}WARNING{/} ',
415
+ content: '{bold}' + text + '{/bold}',
416
+ tags: true
417
+ })
418
+ self.render()
419
+ const timeout = setTimeout(function () {
420
+ warning.destroy()
421
+ self.render()
422
+ }, 1500)
423
+ if (timeout.unref) {
424
+ timeout.unref()
425
+ }
426
+ })
427
+ }
428
+ }
429
+
430
+ Screen.prototype._destroy = Screen.prototype.destroy
431
+ Screen.prototype.destroy = function () {
432
+ this.leave()
433
+
434
+ const index = Screen.instances.indexOf(this)
435
+ if (~index) {
436
+ Screen.instances.splice(index, 1)
437
+ Screen.total--
438
+
439
+ Screen.global = Screen.instances[0]
440
+
441
+ if (Screen.total === 0) {
442
+ Screen.global = null
443
+
444
+ process.removeListener('uncaughtException', Screen._exceptionHandler)
445
+ process.removeListener('SIGTERM', Screen._sigtermHandler)
446
+ process.removeListener('SIGINT', Screen._sigintHandler)
447
+ process.removeListener('SIGQUIT', Screen._sigquitHandler)
448
+ process.removeListener('exit', Screen._exitHandler)
449
+ delete Screen._exceptionHandler
450
+ delete Screen._sigtermHandler
451
+ delete Screen._sigintHandler
452
+ delete Screen._sigquitHandler
453
+ delete Screen._exitHandler
454
+
455
+ delete Screen._bound
456
+ }
457
+
458
+ this.destroyed = true
459
+ this.emit('destroy')
460
+ this._destroy()
461
+ }
462
+
463
+ this.program.destroy()
464
+ }
465
+
466
+ Screen.prototype.log = function () {
467
+ return this.program.log.apply(this.program, arguments)
468
+ }
469
+
470
+ Screen.prototype.debug = function () {
471
+ if (this.debugLog) {
472
+ this.debugLog.log.apply(this.debugLog, arguments)
473
+ }
474
+ return this.program.debug.apply(this.program, arguments)
475
+ }
476
+
477
+ Screen.prototype._listenMouse = function (el) {
478
+ const self = this
479
+
480
+ if (el && !~this.clickable.indexOf(el)) {
481
+ el.clickable = true
482
+ this.clickable.push(el)
483
+ }
484
+
485
+ if (this._listenedMouse) {
486
+ return
487
+ }
488
+ this._listenedMouse = true
489
+
490
+ this.program.enableMouse()
491
+ if (this.options.sendFocus) {
492
+ this.program.setMouse({ sendFocus: true }, true)
493
+ }
494
+
495
+ this.on('render', function () {
496
+ self._needsClickableSort = true
497
+ })
498
+
499
+ this.program.on('mouse', function (data) {
500
+ if (self.lockKeys) {
501
+ return
502
+ }
503
+
504
+ if (self._needsClickableSort) {
505
+ const helpers = require('../helpers')
506
+ self.clickable = helpers.hsort(self.clickable)
507
+ self._needsClickableSort = false
508
+ }
509
+
510
+ let i = 0,
511
+ el,
512
+ set,
513
+ pos
514
+
515
+ for (; i < self.clickable.length; i++) {
516
+ el = self.clickable[i]
517
+
518
+ if (el.detached || !el.visible) {
519
+ continue
520
+ }
521
+
522
+ // if (self.grabMouse && self.focused !== el
523
+ // && !el.hasAncestor(self.focused)) continue;
524
+
525
+ pos = el.lpos
526
+ if (!pos) {
527
+ continue
528
+ }
529
+
530
+ if (
531
+ data.x >= pos.xi &&
532
+ data.x < pos.xl &&
533
+ data.y >= pos.yi &&
534
+ data.y < pos.yl
535
+ ) {
536
+ el.emit('mouse', data)
537
+ if (data.action === 'mousedown') {
538
+ self.mouseDown = el
539
+ } else if (data.action === 'mouseup') {
540
+ ;(self.mouseDown || el).emit('click', data)
541
+ self.mouseDown = null
542
+ } else if (data.action === 'mousemove') {
543
+ if (self.hover && el.index > self.hover.index) {
544
+ set = false
545
+ }
546
+ if (self.hover !== el && !set) {
547
+ if (self.hover) {
548
+ self.hover.emit('mouseout', data)
549
+ }
550
+ el.emit('mouseover', data)
551
+ self.hover = el
552
+ }
553
+ set = true
554
+ }
555
+ el.emit(data.action, data)
556
+ break
557
+ }
558
+ }
559
+
560
+ // Just mouseover?
561
+ if (
562
+ (data.action === 'mousemove' ||
563
+ data.action === 'mousedown' ||
564
+ data.action === 'mouseup') &&
565
+ self.hover &&
566
+ !set
567
+ ) {
568
+ self.hover.emit('mouseout', data)
569
+ self.hover = null
570
+ }
571
+
572
+ self.emit('mouse', data)
573
+ self.emit(data.action, data)
574
+ })
575
+
576
+ // Autofocus highest element.
577
+ // this.on('element click', function(el, data) {
578
+ // var target;
579
+ // do {
580
+ // if (el.clickable === true && el.options.autoFocus !== false) {
581
+ // target = el;
582
+ // }
583
+ // } while (el = el.parent);
584
+ // if (target) target.focus();
585
+ // });
586
+
587
+ // Autofocus elements with the appropriate option.
588
+ this.on('element click', function (el) {
589
+ if (el.clickable === true && el.options.autoFocus !== false) {
590
+ el.focus()
591
+ }
592
+ })
593
+ }
594
+
595
+ Screen.prototype.enableMouse = function (el) {
596
+ this._listenMouse(el)
597
+ }
598
+
599
+ Screen.prototype._listenKeys = function (el) {
600
+ const self = this
601
+
602
+ if (el && !~this.keyable.indexOf(el)) {
603
+ el.keyable = true
604
+ this.keyable.push(el)
605
+ }
606
+
607
+ if (this._listenedKeys) {
608
+ return
609
+ }
610
+ this._listenedKeys = true
611
+
612
+ // NOTE: The event emissions used to be reversed:
613
+ // element + screen
614
+ // They are now:
615
+ // screen + element
616
+ // After the first keypress emitted, the handler
617
+ // checks to make sure grabKeys, lockKeys, and focused
618
+ // weren't changed, and handles those situations appropriately.
619
+ this.program.on('keypress', function (ch, key) {
620
+ if (self.lockKeys && !~self.ignoreLocked.indexOf(key.full)) {
621
+ return
622
+ }
623
+
624
+ const focused = self.focused,
625
+ grabKeys = self.grabKeys
626
+
627
+ if (!grabKeys || ~self.ignoreLocked.indexOf(key.full)) {
628
+ self.emit('keypress', ch, key)
629
+ self.emit('key ' + key.full, ch, key)
630
+ }
631
+
632
+ // If something changed from the screen key handler, stop.
633
+ if (self.grabKeys !== grabKeys || self.lockKeys) {
634
+ return
635
+ }
636
+
637
+ if (focused && focused.keyable) {
638
+ focused.emit('keypress', ch, key)
639
+ focused.emit('key ' + key.full, ch, key)
640
+ }
641
+ })
642
+ }
643
+
644
+ Screen.prototype.enableKeys = function (el) {
645
+ this._listenKeys(el)
646
+ }
647
+
648
+ Screen.prototype.enableInput = function (el) {
649
+ this._listenMouse(el)
650
+ this._listenKeys(el)
651
+ }
652
+
653
+ Screen.prototype._initHover = function () {
654
+ const self = this
655
+
656
+ if (this._hoverText) {
657
+ return
658
+ }
659
+ const Box = require('./box')
660
+ this._hoverText = new Box({
661
+ screen: this,
662
+ left: 0,
663
+ top: 0,
664
+ tags: false,
665
+ height: 'shrink',
666
+ width: 'shrink',
667
+ border: 'line',
668
+ style: {
669
+ border: {
670
+ fg: 'default'
671
+ },
672
+ bg: 'default',
673
+ fg: 'default'
674
+ }
675
+ })
676
+
677
+ this.on('mousemove', function (data) {
678
+ if (self._hoverText.detached) {
679
+ return
680
+ }
681
+ self._hoverText.rleft = data.x + 1
682
+ self._hoverText.rtop = data.y
683
+ self.render()
684
+ })
685
+
686
+ this.on('element mouseover', function (el, data) {
687
+ if (!el._hoverOptions) {
688
+ return
689
+ }
690
+ self._hoverText.parseTags = el.parseTags
691
+ self._hoverText.setContent(el._hoverOptions.text)
692
+ self.append(self._hoverText)
693
+ self._hoverText.rleft = data.x + 1
694
+ self._hoverText.rtop = data.y
695
+ self.render()
696
+ })
697
+
698
+ this.on('element mouseout', function () {
699
+ if (self._hoverText.detached) {
700
+ return
701
+ }
702
+ self._hoverText.detach()
703
+ self.render()
704
+ })
705
+
706
+ // XXX This can cause problems if the
707
+ // terminal does not support allMotion.
708
+ // Workaround: check to see if content is set.
709
+ this.on('element mouseup', function (el) {
710
+ if (!self._hoverText.getContent()) {
711
+ return
712
+ }
713
+ if (!el._hoverOptions) {
714
+ return
715
+ }
716
+ self.append(self._hoverText)
717
+ self.render()
718
+ })
719
+ }
720
+
721
+ Screen.prototype.__defineGetter__('cols', function () {
722
+ return this.program.cols
723
+ })
724
+
725
+ Screen.prototype.__defineGetter__('rows', function () {
726
+ return this.program.rows
727
+ })
728
+
729
+ Screen.prototype.__defineGetter__('width', function () {
730
+ return this.program.cols
731
+ })
732
+
733
+ Screen.prototype.__defineGetter__('height', function () {
734
+ return this.program.rows
735
+ })
736
+
737
+ Screen.prototype.alloc = function (dirty) {
738
+ let x, y
739
+
740
+ this.lines = []
741
+ for (y = 0; y < this.rows; y++) {
742
+ this.lines[y] = []
743
+ for (x = 0; x < this.cols; x++) {
744
+ this.lines[y][x] = [this.dattr, ' ']
745
+ }
746
+ this.lines[y].dirty = !!dirty
747
+ }
748
+
749
+ this.olines = []
750
+ for (y = 0; y < this.rows; y++) {
751
+ this.olines[y] = []
752
+ for (x = 0; x < this.cols; x++) {
753
+ this.olines[y][x] = [this.dattr, ' ']
754
+ }
755
+ }
756
+
757
+ this.program.clear()
758
+ }
759
+
760
+ Screen.prototype.realloc = function () {
761
+ return this.alloc(true)
762
+ }
763
+
764
+ Screen.prototype.render = function () {
765
+ const self = this
766
+
767
+ if (this.destroyed) {
768
+ return
769
+ }
770
+
771
+ this.emit('prerender')
772
+
773
+ this._borderStops = {}
774
+
775
+ // TODO: Possibly get rid of .dirty altogether.
776
+ // TODO: Could possibly drop .dirty and just clear the `lines` buffer every
777
+ // time before a screen.render. This way clearRegion doesn't have to be
778
+ // called in arbitrary places for the sake of clearing a spot where an
779
+ // element used to be (e.g. when an element moves or is hidden). There could
780
+ // be some overhead though.
781
+ // this.screen.clearRegion(0, this.cols, 0, this.rows);
782
+ this._ci = 0
783
+ this.children.forEach(function (el) {
784
+ el.index = self._ci++
785
+ //el._rendering = true;
786
+ el.render()
787
+ //el._rendering = false;
788
+ })
789
+ this._ci = -1
790
+
791
+ if (this.screen.dockBorders) {
792
+ this._dockBorders()
793
+ }
794
+
795
+ this.draw(0, this.lines.length - 1)
796
+
797
+ // XXX Workaround to deal with cursor pos before the screen has rendered and
798
+ // lpos is not reliable (stale).
799
+ if (this.focused && this.focused._updateCursor) {
800
+ this.focused._updateCursor(true)
801
+ }
802
+
803
+ this.renders++
804
+
805
+ this.emit('render')
806
+ }
807
+
808
+ Screen.prototype.blankLine = function (ch, dirty) {
809
+ const out = []
810
+ for (let x = 0; x < this.cols; x++) {
811
+ out[x] = [this.dattr, ch || ' ']
812
+ }
813
+ out.dirty = dirty
814
+ return out
815
+ }
816
+
817
+ Screen.prototype.insertLine = function (n, y, top, bottom) {
818
+ // if (y === top) return this.insertLineNC(n, y, top, bottom);
819
+
820
+ if (
821
+ !this.tput.strings.change_scroll_region ||
822
+ !this.tput.strings.delete_line ||
823
+ !this.tput.strings.insert_line
824
+ ) {
825
+ return
826
+ }
827
+
828
+ this._buf += this.tput.csr(top, bottom)
829
+ this._buf += this.tput.cup(y, 0)
830
+ this._buf += this.tput.il(n)
831
+ this._buf += this.tput.csr(0, this.height - 1)
832
+
833
+ const j = bottom + 1
834
+
835
+ while (n--) {
836
+ this.lines.splice(y, 0, this.blankLine())
837
+ this.lines.splice(j, 1)
838
+ this.olines.splice(y, 0, this.blankLine())
839
+ this.olines.splice(j, 1)
840
+ }
841
+ }
842
+
843
+ Screen.prototype.deleteLine = function (n, y, top, bottom) {
844
+ // if (y === top) return this.deleteLineNC(n, y, top, bottom);
845
+
846
+ if (
847
+ !this.tput.strings.change_scroll_region ||
848
+ !this.tput.strings.delete_line ||
849
+ !this.tput.strings.insert_line
850
+ ) {
851
+ return
852
+ }
853
+
854
+ this._buf += this.tput.csr(top, bottom)
855
+ this._buf += this.tput.cup(y, 0)
856
+ this._buf += this.tput.dl(n)
857
+ this._buf += this.tput.csr(0, this.height - 1)
858
+
859
+ const j = bottom + 1
860
+
861
+ while (n--) {
862
+ this.lines.splice(j, 0, this.blankLine())
863
+ this.lines.splice(y, 1)
864
+ this.olines.splice(j, 0, this.blankLine())
865
+ this.olines.splice(y, 1)
866
+ }
867
+ }
868
+
869
+ // This is how ncurses does it.
870
+ // Scroll down (up cursor-wise).
871
+ // This will only work for top line deletion as opposed to arbitrary lines.
872
+ Screen.prototype.insertLineNC = function (n, y, top, bottom) {
873
+ if (
874
+ !this.tput.strings.change_scroll_region ||
875
+ !this.tput.strings.delete_line
876
+ ) {
877
+ return
878
+ }
879
+
880
+ this._buf += this.tput.csr(top, bottom)
881
+ this._buf += this.tput.cup(top, 0)
882
+ this._buf += this.tput.dl(n)
883
+ this._buf += this.tput.csr(0, this.height - 1)
884
+
885
+ const j = bottom + 1
886
+
887
+ while (n--) {
888
+ this.lines.splice(j, 0, this.blankLine())
889
+ this.lines.splice(y, 1)
890
+ this.olines.splice(j, 0, this.blankLine())
891
+ this.olines.splice(y, 1)
892
+ }
893
+ }
894
+
895
+ // This is how ncurses does it.
896
+ // Scroll up (down cursor-wise).
897
+ // This will only work for bottom line deletion as opposed to arbitrary lines.
898
+ Screen.prototype.deleteLineNC = function (n, y, top, bottom) {
899
+ if (
900
+ !this.tput.strings.change_scroll_region ||
901
+ !this.tput.strings.delete_line
902
+ ) {
903
+ return
904
+ }
905
+
906
+ this._buf += this.tput.csr(top, bottom)
907
+ this._buf += this.tput.cup(bottom, 0)
908
+ this._buf += Array(n + 1).join('\n')
909
+ this._buf += this.tput.csr(0, this.height - 1)
910
+
911
+ const j = bottom + 1
912
+
913
+ while (n--) {
914
+ this.lines.splice(j, 0, this.blankLine())
915
+ this.lines.splice(y, 1)
916
+ this.olines.splice(j, 0, this.blankLine())
917
+ this.olines.splice(y, 1)
918
+ }
919
+ }
920
+
921
+ Screen.prototype.insertBottom = function (top, bottom) {
922
+ return this.deleteLine(1, top, top, bottom)
923
+ }
924
+
925
+ Screen.prototype.insertTop = function (top, bottom) {
926
+ return this.insertLine(1, top, top, bottom)
927
+ }
928
+
929
+ Screen.prototype.deleteBottom = function (top, bottom) {
930
+ return this.clearRegion(0, this.width, bottom, bottom)
931
+ }
932
+
933
+ Screen.prototype.deleteTop = function (top, bottom) {
934
+ // Same as: return this.insertBottom(top, bottom);
935
+ return this.deleteLine(1, top, top, bottom)
936
+ }
937
+
938
+ // Parse the sides of an element to determine
939
+ // whether an element has uniform cells on
940
+ // both sides. If it does, we can use CSR to
941
+ // optimize scrolling on a scrollable element.
942
+ // Not exactly sure how worthwile this is.
943
+ // This will cause a performance/cpu-usage hit,
944
+ // but will it be less or greater than the
945
+ // performance hit of slow-rendering scrollable
946
+ // boxes with clean sides?
947
+ Screen.prototype.cleanSides = function (el) {
948
+ const pos = el.lpos
949
+
950
+ if (!pos) {
951
+ return false
952
+ }
953
+
954
+ if (pos._cleanSides != null) {
955
+ return pos._cleanSides
956
+ }
957
+
958
+ if (pos.xi <= 0 && pos.xl >= this.width) {
959
+ return (pos._cleanSides = true)
960
+ }
961
+
962
+ if (this.options.fastCSR) {
963
+ // Maybe just do this instead of parsing.
964
+ if (pos.yi < 0) {
965
+ return (pos._cleanSides = false)
966
+ }
967
+ if (pos.yl > this.height) {
968
+ return (pos._cleanSides = false)
969
+ }
970
+ if (this.width - (pos.xl - pos.xi) < 40) {
971
+ return (pos._cleanSides = true)
972
+ }
973
+ return (pos._cleanSides = false)
974
+ }
975
+
976
+ if (!this.options.smartCSR) {
977
+ return false
978
+ }
979
+
980
+ // The scrollbar can't update properly, and there's also a
981
+ // chance that the scrollbar may get moved around senselessly.
982
+ // NOTE: In pratice, this doesn't seem to be the case.
983
+ // if (this.scrollbar) {
984
+ // return pos._cleanSides = false;
985
+ // }
986
+
987
+ // Doesn't matter if we're only a height of 1.
988
+ // if ((pos.yl - el.ibottom) - (pos.yi + el.itop) <= 1) {
989
+ // return pos._cleanSides = false;
990
+ // }
991
+
992
+ let yi = pos.yi + el.itop,
993
+ yl = pos.yl - el.ibottom,
994
+ first,
995
+ ch,
996
+ x,
997
+ y
998
+
999
+ if (pos.yi < 0) {
1000
+ return (pos._cleanSides = false)
1001
+ }
1002
+ if (pos.yl > this.height) {
1003
+ return (pos._cleanSides = false)
1004
+ }
1005
+ if (pos.xi - 1 < 0) {
1006
+ return (pos._cleanSides = true)
1007
+ }
1008
+ if (pos.xl > this.width) {
1009
+ return (pos._cleanSides = true)
1010
+ }
1011
+
1012
+ for (x = pos.xi - 1; x >= 0; x--) {
1013
+ if (!this.olines[yi]) {
1014
+ break
1015
+ }
1016
+ first = this.olines[yi][x]
1017
+ for (y = yi; y < yl; y++) {
1018
+ if (!this.olines[y] || !this.olines[y][x]) {
1019
+ break
1020
+ }
1021
+ ch = this.olines[y][x]
1022
+ if (ch[0] !== first[0] || ch[1] !== first[1]) {
1023
+ return (pos._cleanSides = false)
1024
+ }
1025
+ }
1026
+ }
1027
+
1028
+ for (x = pos.xl; x < this.width; x++) {
1029
+ if (!this.olines[yi]) {
1030
+ break
1031
+ }
1032
+ first = this.olines[yi][x]
1033
+ for (y = yi; y < yl; y++) {
1034
+ if (!this.olines[y] || !this.olines[y][x]) {
1035
+ break
1036
+ }
1037
+ ch = this.olines[y][x]
1038
+ if (ch[0] !== first[0] || ch[1] !== first[1]) {
1039
+ return (pos._cleanSides = false)
1040
+ }
1041
+ }
1042
+ }
1043
+
1044
+ return (pos._cleanSides = true)
1045
+ }
1046
+
1047
+ Screen.prototype._dockBorders = function () {
1048
+ let lines = this.lines,
1049
+ stops = this._borderStops,
1050
+ i,
1051
+ y,
1052
+ x,
1053
+ ch
1054
+
1055
+ // var keys, stop;
1056
+ //
1057
+ // keys = Object.keys(this._borderStops)
1058
+ // .map(function(k) { return +k; })
1059
+ // .sort(function(a, b) { return a - b; });
1060
+ //
1061
+ // for (i = 0; i < keys.length; i++) {
1062
+ // y = keys[i];
1063
+ // if (!lines[y]) continue;
1064
+ // stop = this._borderStops[y];
1065
+ // for (x = stop.xi; x < stop.xl; x++) {
1066
+
1067
+ stops = Object.keys(stops)
1068
+ .map(function (k) {
1069
+ return +k
1070
+ })
1071
+ .sort(function (a, b) {
1072
+ return a - b
1073
+ })
1074
+
1075
+ for (i = 0; i < stops.length; i++) {
1076
+ y = stops[i]
1077
+ if (!lines[y]) {
1078
+ continue
1079
+ }
1080
+ for (x = 0; x < this.width; x++) {
1081
+ ch = lines[y][x][1]
1082
+ if (angles[ch]) {
1083
+ lines[y][x][1] = this._getAngle(lines, x, y)
1084
+ lines[y].dirty = true
1085
+ }
1086
+ }
1087
+ }
1088
+ }
1089
+
1090
+ Screen.prototype._getAngle = function (lines, x, y) {
1091
+ let angle = 0,
1092
+ attr = lines[y][x][0],
1093
+ ch = lines[y][x][1]
1094
+
1095
+ if (lines[y][x - 1] && langles[lines[y][x - 1][1]]) {
1096
+ if (!this.options.ignoreDockContrast) {
1097
+ if (lines[y][x - 1][0] !== attr) {
1098
+ return ch
1099
+ }
1100
+ }
1101
+ angle |= 1 << 3
1102
+ }
1103
+
1104
+ if (lines[y - 1] && uangles[lines[y - 1][x][1]]) {
1105
+ if (!this.options.ignoreDockContrast) {
1106
+ if (lines[y - 1][x][0] !== attr) {
1107
+ return ch
1108
+ }
1109
+ }
1110
+ angle |= 1 << 2
1111
+ }
1112
+
1113
+ if (lines[y][x + 1] && rangles[lines[y][x + 1][1]]) {
1114
+ if (!this.options.ignoreDockContrast) {
1115
+ if (lines[y][x + 1][0] !== attr) {
1116
+ return ch
1117
+ }
1118
+ }
1119
+ angle |= 1 << 1
1120
+ }
1121
+
1122
+ if (lines[y + 1] && dangles[lines[y + 1][x][1]]) {
1123
+ if (!this.options.ignoreDockContrast) {
1124
+ if (lines[y + 1][x][0] !== attr) {
1125
+ return ch
1126
+ }
1127
+ }
1128
+ angle |= 1 << 0
1129
+ }
1130
+
1131
+ // Experimental: fixes this situation:
1132
+ // +----------+
1133
+ // | <-- empty space here, should be a T angle
1134
+ // +-------+ |
1135
+ // | | |
1136
+ // +-------+ |
1137
+ // | |
1138
+ // +----------+
1139
+ // if (uangles[lines[y][x][1]]) {
1140
+ // if (lines[y + 1] && cdangles[lines[y + 1][x][1]]) {
1141
+ // if (!this.options.ignoreDockContrast) {
1142
+ // if (lines[y + 1][x][0] !== attr) return ch;
1143
+ // }
1144
+ // angle |= 1 << 0;
1145
+ // }
1146
+ // }
1147
+
1148
+ return angleTable[angle] || ch
1149
+ }
1150
+
1151
+ Screen.prototype.draw = function (start, end) {
1152
+ // this.emit('predraw');
1153
+
1154
+ let x, y, line, out, ch, data, attr, fg, bg, flags
1155
+
1156
+ let main = '',
1157
+ pre,
1158
+ post
1159
+
1160
+ let clr, neq, xx
1161
+
1162
+ let lx = -1,
1163
+ ly = -1,
1164
+ o
1165
+
1166
+ let acs
1167
+
1168
+ if (this._buf) {
1169
+ main += this._buf
1170
+ this._buf = ''
1171
+ }
1172
+
1173
+ for (y = start; y <= end; y++) {
1174
+ line = this.lines[y]
1175
+ o = this.olines[y]
1176
+
1177
+ if (!line.dirty && !(this.cursor.artificial && y === this.program.y)) {
1178
+ continue
1179
+ }
1180
+ line.dirty = false
1181
+
1182
+ out = ''
1183
+ attr = this.dattr
1184
+
1185
+ for (x = 0; x < line.length; x++) {
1186
+ data = line[x][0]
1187
+ ch = line[x][1]
1188
+
1189
+ // Render the artificial cursor.
1190
+ if (
1191
+ this.cursor.artificial &&
1192
+ !this.cursor._hidden &&
1193
+ this.cursor._state &&
1194
+ x === this.program.x &&
1195
+ y === this.program.y
1196
+ ) {
1197
+ const cattr = this._cursorAttr(this.cursor, data)
1198
+ if (cattr.ch) {
1199
+ ch = cattr.ch
1200
+ }
1201
+ data = cattr.attr
1202
+ }
1203
+
1204
+ // Take advantage of xterm's back_color_erase feature by using a
1205
+ // lookahead. Stop spitting out so many damn spaces. NOTE: Is checking
1206
+ // the bg for non BCE terminals worth the overhead?
1207
+ if (
1208
+ this.options.useBCE &&
1209
+ ch === ' ' &&
1210
+ (this.tput.bools.back_color_erase ||
1211
+ (data & 0x1ff) === (this.dattr & 0x1ff)) &&
1212
+ ((data >> 18) & 8) === ((this.dattr >> 18) & 8)
1213
+ ) {
1214
+ clr = true
1215
+ neq = false
1216
+
1217
+ for (xx = x; xx < line.length; xx++) {
1218
+ if (line[xx][0] !== data || line[xx][1] !== ' ') {
1219
+ clr = false
1220
+ break
1221
+ }
1222
+ if (line[xx][0] !== o[xx][0] || line[xx][1] !== o[xx][1]) {
1223
+ neq = true
1224
+ }
1225
+ }
1226
+
1227
+ if (clr && neq) {
1228
+ ;(lx = -1), (ly = -1)
1229
+ if (data !== attr) {
1230
+ out += this.codeAttr(data)
1231
+ attr = data
1232
+ }
1233
+ out += this.tput.cup(y, x)
1234
+ out += this.tput.el()
1235
+ for (xx = x; xx < line.length; xx++) {
1236
+ o[xx][0] = data
1237
+ o[xx][1] = ' '
1238
+ }
1239
+ break
1240
+ }
1241
+
1242
+ // If there's more than 10 spaces, use EL regardless
1243
+ // and start over drawing the rest of line. Might
1244
+ // not be worth it. Try to use ECH if the terminal
1245
+ // supports it. Maybe only try to use ECH here.
1246
+ // //if (this.tput.strings.erase_chars)
1247
+ // if (!clr && neq && (xx - x) > 10) {
1248
+ // lx = -1, ly = -1;
1249
+ // if (data !== attr) {
1250
+ // out += this.codeAttr(data);
1251
+ // attr = data;
1252
+ // }
1253
+ // out += this.tput.cup(y, x);
1254
+ // if (this.tput.strings.erase_chars) {
1255
+ // // Use erase_chars to avoid erasing the whole line.
1256
+ // out += this.tput.ech(xx - x);
1257
+ // } else {
1258
+ // out += this.tput.el();
1259
+ // }
1260
+ // if (this.tput.strings.parm_right_cursor) {
1261
+ // out += this.tput.cuf(xx - x);
1262
+ // } else {
1263
+ // out += this.tput.cup(y, xx);
1264
+ // }
1265
+ // this.fillRegion(data, ' ',
1266
+ // x, this.tput.strings.erase_chars ? xx : line.length,
1267
+ // y, y + 1);
1268
+ // x = xx - 1;
1269
+ // continue;
1270
+ // }
1271
+
1272
+ // Skip to the next line if the
1273
+ // rest of the line is already drawn.
1274
+ // if (!neq) {
1275
+ // for (; xx < line.length; xx++) {
1276
+ // if (line[xx][0] !== o[xx][0] || line[xx][1] !== o[xx][1]) {
1277
+ // neq = true;
1278
+ // break;
1279
+ // }
1280
+ // }
1281
+ // if (!neq) {
1282
+ // attr = data;
1283
+ // break;
1284
+ // }
1285
+ // }
1286
+ }
1287
+
1288
+ // Optimize by comparing the real output
1289
+ // buffer to the pending output buffer.
1290
+ if (data === o[x][0] && ch === o[x][1]) {
1291
+ if (lx === -1) {
1292
+ lx = x
1293
+ ly = y
1294
+ }
1295
+ continue
1296
+ } else if (lx !== -1) {
1297
+ if (this.tput.strings.parm_right_cursor) {
1298
+ out += y === ly ? this.tput.cuf(x - lx) : this.tput.cup(y, x)
1299
+ } else {
1300
+ out += this.tput.cup(y, x)
1301
+ }
1302
+ ;(lx = -1), (ly = -1)
1303
+ }
1304
+ o[x][0] = data
1305
+ o[x][1] = ch
1306
+
1307
+ if (data !== attr) {
1308
+ if (attr !== this.dattr) {
1309
+ out += '\x1b[m'
1310
+ }
1311
+ if (data !== this.dattr) {
1312
+ out += '\x1b['
1313
+
1314
+ bg = data & 0x1ff
1315
+ fg = (data >> 9) & 0x1ff
1316
+ flags = data >> 18
1317
+
1318
+ // bold
1319
+ if (flags & 1) {
1320
+ out += '1;'
1321
+ }
1322
+
1323
+ // underline
1324
+ if (flags & 2) {
1325
+ out += '4;'
1326
+ }
1327
+
1328
+ // blink
1329
+ if (flags & 4) {
1330
+ out += '5;'
1331
+ }
1332
+
1333
+ // inverse
1334
+ if (flags & 8) {
1335
+ out += '7;'
1336
+ }
1337
+
1338
+ // invisible
1339
+ if (flags & 16) {
1340
+ out += '8;'
1341
+ }
1342
+
1343
+ if (bg !== 0x1ff) {
1344
+ bg = this._reduceColor(bg)
1345
+ if (bg < 16) {
1346
+ if (bg < 8) {
1347
+ bg += 40
1348
+ } else if (bg < 16) {
1349
+ bg -= 8
1350
+ bg += 100
1351
+ }
1352
+ out += bg + ';'
1353
+ } else {
1354
+ out += '48;5;' + bg + ';'
1355
+ }
1356
+ }
1357
+
1358
+ if (fg !== 0x1ff) {
1359
+ fg = this._reduceColor(fg)
1360
+ if (fg < 16) {
1361
+ if (fg < 8) {
1362
+ fg += 30
1363
+ } else if (fg < 16) {
1364
+ fg -= 8
1365
+ fg += 90
1366
+ }
1367
+ out += fg + ';'
1368
+ } else {
1369
+ out += '38;5;' + fg + ';'
1370
+ }
1371
+ }
1372
+
1373
+ if (out[out.length - 1] === ';') {
1374
+ out = out.slice(0, -1)
1375
+ }
1376
+
1377
+ out += 'm'
1378
+ }
1379
+ }
1380
+
1381
+ // If we find a double-width char, eat the next character which should be
1382
+ // a space due to parseContent's behavior.
1383
+ if (this.fullUnicode) {
1384
+ // If this is a surrogate pair double-width char, we can ignore it
1385
+ // because parseContent already counted it as length=2.
1386
+ if (unicode.charWidth(line[x][1]) === 2) {
1387
+ // NOTE: At cols=44, the bug that is avoided
1388
+ // by the angles check occurs in widget-unicode:
1389
+ // Might also need: `line[x + 1][0] !== line[x][0]`
1390
+ // for borderless boxes?
1391
+ if (x === line.length - 1 || angles[line[x + 1][1]]) {
1392
+ // If we're at the end, we don't have enough space for a
1393
+ // double-width. Overwrite it with a space and ignore.
1394
+ ch = ' '
1395
+ o[x][1] = '\0'
1396
+ } else {
1397
+ // ALWAYS refresh double-width chars because this special cursor
1398
+ // behavior is needed. There may be a more efficient way of doing
1399
+ // this. See above.
1400
+ o[x][1] = '\0'
1401
+ // Eat the next character by moving forward and marking as a
1402
+ // space (which it is).
1403
+ o[++x][1] = '\0'
1404
+ }
1405
+ }
1406
+ }
1407
+
1408
+ // Attempt to use ACS for supported characters.
1409
+ // This is not ideal, but it's how ncurses works.
1410
+ // There are a lot of terminals that support ACS
1411
+ // *and UTF8, but do not declare U8. So ACS ends
1412
+ // up being used (slower than utf8). Terminals
1413
+ // that do not support ACS and do not explicitly
1414
+ // support UTF8 get their unicode characters
1415
+ // replaced with really ugly ascii characters.
1416
+ // It is possible there is a terminal out there
1417
+ // somewhere that does not support ACS, but
1418
+ // supports UTF8, but I imagine it's unlikely.
1419
+ // Maybe remove !this.tput.unicode check, however,
1420
+ // this seems to be the way ncurses does it.
1421
+ if (
1422
+ this.tput.strings.enter_alt_charset_mode &&
1423
+ !this.tput.brokenACS &&
1424
+ (this.tput.acscr[ch] || acs)
1425
+ ) {
1426
+ // Fun fact: even if this.tput.brokenACS wasn't checked here,
1427
+ // the linux console would still work fine because the acs
1428
+ // table would fail the check of: this.tput.acscr[ch]
1429
+ if (this.tput.acscr[ch]) {
1430
+ if (acs) {
1431
+ ch = this.tput.acscr[ch]
1432
+ } else {
1433
+ ch = this.tput.smacs() + this.tput.acscr[ch]
1434
+ acs = true
1435
+ }
1436
+ } else if (acs) {
1437
+ ch = this.tput.rmacs() + ch
1438
+ acs = false
1439
+ }
1440
+ } else {
1441
+ // U8 is not consistently correct. Some terminfo's
1442
+ // terminals that do not declare it may actually
1443
+ // support utf8 (e.g. urxvt), but if the terminal
1444
+ // does not declare support for ACS (and U8), chances
1445
+ // are it does not support UTF8. This is probably
1446
+ // the "safest" way to do this. Should fix things
1447
+ // like sun-color.
1448
+ // NOTE: It could be the case that the $LANG
1449
+ // is all that matters in some cases:
1450
+ // if (!this.tput.unicode && ch > '~') {
1451
+ if (!this.tput.unicode && this.tput.numbers.U8 !== 1 && ch > '~') {
1452
+ ch = this.tput.utoa[ch] || '?'
1453
+ }
1454
+ }
1455
+
1456
+ out += ch
1457
+ attr = data
1458
+ }
1459
+
1460
+ if (attr !== this.dattr) {
1461
+ out += '\x1b[m'
1462
+ }
1463
+
1464
+ if (out) {
1465
+ main += this.tput.cup(y, 0) + out
1466
+ }
1467
+ }
1468
+
1469
+ if (acs) {
1470
+ main += this.tput.rmacs()
1471
+ acs = false
1472
+ }
1473
+
1474
+ if (main) {
1475
+ pre = ''
1476
+ post = ''
1477
+
1478
+ pre += this.tput.sc()
1479
+ post += this.tput.rc()
1480
+
1481
+ if (!this.program.cursorHidden) {
1482
+ pre += this.tput.civis()
1483
+ post += this.tput.cnorm()
1484
+ }
1485
+
1486
+ // this.program.flush();
1487
+ // this.program._owrite(pre + main + post);
1488
+ this.program._write(pre + main + post)
1489
+ }
1490
+
1491
+ // this.emit('draw');
1492
+ }
1493
+
1494
+ Screen.prototype._reduceColor = function (color) {
1495
+ return colors.reduce(color, this.tput.colors)
1496
+ }
1497
+
1498
+ // Convert an SGR string to our own attribute format.
1499
+ Screen.prototype.attrCode = function (code, cur, def) {
1500
+ let flags = (cur >> 18) & 0x1ff,
1501
+ fg = (cur >> 9) & 0x1ff,
1502
+ bg = cur & 0x1ff,
1503
+ c,
1504
+ i
1505
+
1506
+ code = code.slice(2, -1).split(';')
1507
+ if (!code[0]) {
1508
+ code[0] = '0'
1509
+ }
1510
+
1511
+ for (i = 0; i < code.length; i++) {
1512
+ c = +code[i] || 0
1513
+ switch (c) {
1514
+ case 0: // normal
1515
+ bg = def & 0x1ff
1516
+ fg = (def >> 9) & 0x1ff
1517
+ flags = (def >> 18) & 0x1ff
1518
+ break
1519
+ case 1: // bold
1520
+ flags |= 1
1521
+ break
1522
+ case 22:
1523
+ flags = (def >> 18) & 0x1ff
1524
+ break
1525
+ case 4: // underline
1526
+ flags |= 2
1527
+ break
1528
+ case 24:
1529
+ flags = (def >> 18) & 0x1ff
1530
+ break
1531
+ case 5: // blink
1532
+ flags |= 4
1533
+ break
1534
+ case 25:
1535
+ flags = (def >> 18) & 0x1ff
1536
+ break
1537
+ case 7: // inverse
1538
+ flags |= 8
1539
+ break
1540
+ case 27:
1541
+ flags = (def >> 18) & 0x1ff
1542
+ break
1543
+ case 8: // invisible
1544
+ flags |= 16
1545
+ break
1546
+ case 28:
1547
+ flags = (def >> 18) & 0x1ff
1548
+ break
1549
+ case 39: // default fg
1550
+ fg = (def >> 9) & 0x1ff
1551
+ break
1552
+ case 49: // default bg
1553
+ bg = def & 0x1ff
1554
+ break
1555
+ case 100: // default fg/bg
1556
+ fg = (def >> 9) & 0x1ff
1557
+ bg = def & 0x1ff
1558
+ break
1559
+ default: // color
1560
+ if (c === 48 && +code[i + 1] === 5) {
1561
+ i += 2
1562
+ bg = +code[i]
1563
+ break
1564
+ } else if (c === 48 && +code[i + 1] === 2) {
1565
+ i += 2
1566
+ bg = colors.match(+code[i], +code[i + 1], +code[i + 2])
1567
+ if (bg === -1) {
1568
+ bg = def & 0x1ff
1569
+ }
1570
+ i += 2
1571
+ break
1572
+ } else if (c === 38 && +code[i + 1] === 5) {
1573
+ i += 2
1574
+ fg = +code[i]
1575
+ break
1576
+ } else if (c === 38 && +code[i + 1] === 2) {
1577
+ i += 2
1578
+ fg = colors.match(+code[i], +code[i + 1], +code[i + 2])
1579
+ if (fg === -1) {
1580
+ fg = (def >> 9) & 0x1ff
1581
+ }
1582
+ i += 2
1583
+ break
1584
+ }
1585
+ if (c >= 40 && c <= 47) {
1586
+ bg = c - 40
1587
+ } else if (c >= 100 && c <= 107) {
1588
+ bg = c - 100
1589
+ bg += 8
1590
+ } else if (c === 49) {
1591
+ bg = def & 0x1ff
1592
+ } else if (c >= 30 && c <= 37) {
1593
+ fg = c - 30
1594
+ } else if (c >= 90 && c <= 97) {
1595
+ fg = c - 90
1596
+ fg += 8
1597
+ } else if (c === 39) {
1598
+ fg = (def >> 9) & 0x1ff
1599
+ } else if (c === 100) {
1600
+ fg = (def >> 9) & 0x1ff
1601
+ bg = def & 0x1ff
1602
+ }
1603
+ break
1604
+ }
1605
+ }
1606
+
1607
+ return (flags << 18) | (fg << 9) | bg
1608
+ }
1609
+
1610
+ // Convert our own attribute format to an SGR string.
1611
+ Screen.prototype.codeAttr = function (code) {
1612
+ let flags = (code >> 18) & 0x1ff,
1613
+ fg = (code >> 9) & 0x1ff,
1614
+ bg = code & 0x1ff,
1615
+ out = ''
1616
+
1617
+ // bold
1618
+ if (flags & 1) {
1619
+ out += '1;'
1620
+ }
1621
+
1622
+ // underline
1623
+ if (flags & 2) {
1624
+ out += '4;'
1625
+ }
1626
+
1627
+ // blink
1628
+ if (flags & 4) {
1629
+ out += '5;'
1630
+ }
1631
+
1632
+ // inverse
1633
+ if (flags & 8) {
1634
+ out += '7;'
1635
+ }
1636
+
1637
+ // invisible
1638
+ if (flags & 16) {
1639
+ out += '8;'
1640
+ }
1641
+
1642
+ if (bg !== 0x1ff) {
1643
+ bg = this._reduceColor(bg)
1644
+ if (bg < 16) {
1645
+ if (bg < 8) {
1646
+ bg += 40
1647
+ } else if (bg < 16) {
1648
+ bg -= 8
1649
+ bg += 100
1650
+ }
1651
+ out += bg + ';'
1652
+ } else {
1653
+ out += '48;5;' + bg + ';'
1654
+ }
1655
+ }
1656
+
1657
+ if (fg !== 0x1ff) {
1658
+ fg = this._reduceColor(fg)
1659
+ if (fg < 16) {
1660
+ if (fg < 8) {
1661
+ fg += 30
1662
+ } else if (fg < 16) {
1663
+ fg -= 8
1664
+ fg += 90
1665
+ }
1666
+ out += fg + ';'
1667
+ } else {
1668
+ out += '38;5;' + fg + ';'
1669
+ }
1670
+ }
1671
+
1672
+ if (out[out.length - 1] === ';') {
1673
+ out = out.slice(0, -1)
1674
+ }
1675
+
1676
+ return '\x1b[' + out + 'm'
1677
+ }
1678
+
1679
+ Screen.prototype.focusOffset = function (offset) {
1680
+ const shown = this.keyable.filter(function (el) {
1681
+ return !el.detached && el.visible
1682
+ }).length
1683
+
1684
+ if (!shown || !offset) {
1685
+ return
1686
+ }
1687
+
1688
+ let i = this.keyable.indexOf(this.focused)
1689
+ if (!~i) {
1690
+ return
1691
+ }
1692
+
1693
+ if (offset > 0) {
1694
+ while (offset--) {
1695
+ if (++i > this.keyable.length - 1) {
1696
+ i = 0
1697
+ }
1698
+ if (this.keyable[i].detached || !this.keyable[i].visible) {
1699
+ offset++
1700
+ }
1701
+ }
1702
+ } else {
1703
+ offset = -offset
1704
+ while (offset--) {
1705
+ if (--i < 0) {
1706
+ i = this.keyable.length - 1
1707
+ }
1708
+ if (this.keyable[i].detached || !this.keyable[i].visible) {
1709
+ offset++
1710
+ }
1711
+ }
1712
+ }
1713
+
1714
+ return this.keyable[i].focus()
1715
+ }
1716
+
1717
+ Screen.prototype.focusPrev = Screen.prototype.focusPrevious = function () {
1718
+ return this.focusOffset(-1)
1719
+ }
1720
+
1721
+ Screen.prototype.focusNext = function () {
1722
+ return this.focusOffset(1)
1723
+ }
1724
+
1725
+ Screen.prototype.focusPush = function (el) {
1726
+ if (!el) {
1727
+ return
1728
+ }
1729
+ const old = this.history[this.history.length - 1]
1730
+ if (this.history.length === 10) {
1731
+ this.history.shift()
1732
+ }
1733
+ this.history.push(el)
1734
+ this._focus(el, old)
1735
+ }
1736
+
1737
+ Screen.prototype.focusPop = function () {
1738
+ const old = this.history.pop()
1739
+ if (this.history.length) {
1740
+ this._focus(this.history[this.history.length - 1], old)
1741
+ }
1742
+ return old
1743
+ }
1744
+
1745
+ Screen.prototype.saveFocus = function () {
1746
+ return (this._savedFocus = this.focused)
1747
+ }
1748
+
1749
+ Screen.prototype.restoreFocus = function () {
1750
+ if (!this._savedFocus) {
1751
+ return
1752
+ }
1753
+ this._savedFocus.focus()
1754
+ delete this._savedFocus
1755
+ return this.focused
1756
+ }
1757
+
1758
+ Screen.prototype.rewindFocus = function () {
1759
+ let old = this.history.pop(),
1760
+ el
1761
+
1762
+ while (this.history.length) {
1763
+ el = this.history.pop()
1764
+ if (!el.detached && el.visible) {
1765
+ this.history.push(el)
1766
+ this._focus(el, old)
1767
+ return el
1768
+ }
1769
+ }
1770
+
1771
+ if (old) {
1772
+ old.emit('blur')
1773
+ }
1774
+ }
1775
+
1776
+ Screen.prototype._focus = function (self, old) {
1777
+ // Find a scrollable ancestor if we have one.
1778
+ let el = self
1779
+ while ((el = el.parent)) {
1780
+ if (el.scrollable) {
1781
+ break
1782
+ }
1783
+ }
1784
+
1785
+ // If we're in a scrollable element,
1786
+ // automatically scroll to the focused element.
1787
+ if (el && !el.detached) {
1788
+ // NOTE: This is different from the other "visible" values - it needs the
1789
+ // visible height of the scrolling element itself, not the element within
1790
+ // it.
1791
+ const visible =
1792
+ self.screen.height - el.atop - el.itop - el.abottom - el.ibottom
1793
+ if (self.rtop < el.childBase) {
1794
+ el.scrollTo(self.rtop)
1795
+ self.screen.render()
1796
+ } else if (
1797
+ self.rtop + self.height - self.ibottom >
1798
+ el.childBase + visible
1799
+ ) {
1800
+ // Explanation for el.itop here: takes into account scrollable elements
1801
+ // with borders otherwise the element gets covered by the bottom border:
1802
+ el.scrollTo(self.rtop - (el.height - self.height) + el.itop, true)
1803
+ self.screen.render()
1804
+ }
1805
+ }
1806
+
1807
+ if (old) {
1808
+ old.emit('blur', self)
1809
+ }
1810
+
1811
+ self.emit('focus', old)
1812
+ }
1813
+
1814
+ Screen.prototype.__defineGetter__('focused', function () {
1815
+ return this.history[this.history.length - 1]
1816
+ })
1817
+
1818
+ Screen.prototype.__defineSetter__('focused', function (el) {
1819
+ return this.focusPush(el)
1820
+ })
1821
+
1822
+ Screen.prototype.clearRegion = function (xi, xl, yi, yl, override) {
1823
+ return this.fillRegion(this.dattr, ' ', xi, xl, yi, yl, override)
1824
+ }
1825
+
1826
+ Screen.prototype.fillRegion = function (attr, ch, xi, xl, yi, yl, override) {
1827
+ let lines = this.lines,
1828
+ cell,
1829
+ xx
1830
+
1831
+ if (xi < 0) {
1832
+ xi = 0
1833
+ }
1834
+ if (yi < 0) {
1835
+ yi = 0
1836
+ }
1837
+
1838
+ for (; yi < yl; yi++) {
1839
+ if (!lines[yi]) {
1840
+ break
1841
+ }
1842
+ for (xx = xi; xx < xl; xx++) {
1843
+ cell = lines[yi][xx]
1844
+ if (!cell) {
1845
+ break
1846
+ }
1847
+ if (override || attr !== cell[0] || ch !== cell[1]) {
1848
+ lines[yi][xx][0] = attr
1849
+ lines[yi][xx][1] = ch
1850
+ lines[yi].dirty = true
1851
+ }
1852
+ }
1853
+ }
1854
+ }
1855
+
1856
+ Screen.prototype.key = function () {
1857
+ return this.program.key.apply(this, arguments)
1858
+ }
1859
+
1860
+ Screen.prototype.onceKey = function () {
1861
+ return this.program.onceKey.apply(this, arguments)
1862
+ }
1863
+
1864
+ Screen.prototype.unkey = Screen.prototype.removeKey = function () {
1865
+ return this.program.unkey.apply(this, arguments)
1866
+ }
1867
+
1868
+ Screen.prototype.spawn = function (file, args, options) {
1869
+ if (!Array.isArray(args)) {
1870
+ options = args
1871
+ args = []
1872
+ }
1873
+
1874
+ let screen = this,
1875
+ program = screen.program,
1876
+ spawn = require('node:child_process').spawn,
1877
+ mouse = program.mouseEnabled,
1878
+ ps
1879
+
1880
+ options = options || {}
1881
+
1882
+ options.stdio = options.stdio || 'inherit'
1883
+
1884
+ program.lsaveCursor('spawn')
1885
+ // program.csr(0, program.rows - 1);
1886
+ program.normalBuffer()
1887
+ program.showCursor()
1888
+ if (mouse) {
1889
+ program.disableMouse()
1890
+ }
1891
+
1892
+ const write = program.output.write
1893
+ program.output.write = function () {}
1894
+ program.input.pause()
1895
+ if (program.input.setRawMode) {
1896
+ program.input.setRawMode(false)
1897
+ }
1898
+
1899
+ const resume = function () {
1900
+ if (resume.done) {
1901
+ return
1902
+ }
1903
+ resume.done = true
1904
+
1905
+ if (program.input.setRawMode) {
1906
+ program.input.setRawMode(true)
1907
+ }
1908
+ program.input.resume()
1909
+ program.output.write = write
1910
+
1911
+ program.alternateBuffer()
1912
+ // program.csr(0, program.rows - 1);
1913
+ if (mouse) {
1914
+ program.enableMouse()
1915
+ if (screen.options.sendFocus) {
1916
+ screen.program.setMouse({ sendFocus: true }, true)
1917
+ }
1918
+ }
1919
+
1920
+ screen.alloc()
1921
+ screen.render()
1922
+
1923
+ screen.program.lrestoreCursor('spawn', true)
1924
+ }
1925
+
1926
+ ps = spawn(file, args, options)
1927
+
1928
+ ps.on('error', resume)
1929
+
1930
+ ps.on('exit', resume)
1931
+
1932
+ return ps
1933
+ }
1934
+
1935
+ Screen.prototype.exec = function (file, args, options, callback) {
1936
+ const ps = this.spawn(file, args, options)
1937
+
1938
+ ps.on('error', function (err) {
1939
+ if (!callback) {
1940
+ return
1941
+ }
1942
+ return callback(err, false)
1943
+ })
1944
+
1945
+ ps.on('exit', function (code) {
1946
+ if (!callback) {
1947
+ return
1948
+ }
1949
+ return callback(null, code === 0)
1950
+ })
1951
+
1952
+ return ps
1953
+ }
1954
+
1955
+ Screen.prototype.readEditor = function (options, callback) {
1956
+ if (typeof options === 'string') {
1957
+ options = { editor: options }
1958
+ }
1959
+
1960
+ if (!callback) {
1961
+ callback = options
1962
+ options = null
1963
+ }
1964
+
1965
+ if (!callback) {
1966
+ callback = function () {}
1967
+ }
1968
+
1969
+ options = options || {}
1970
+
1971
+ let self = this,
1972
+ editor = options.editor || process.env.EDITOR || 'vi',
1973
+ name = options.name || process.title || 'blessed',
1974
+ rnd = Math.random().toString(36).split('.').pop(),
1975
+ file = '/tmp/' + name + '.' + rnd,
1976
+ args = [file],
1977
+ opt
1978
+
1979
+ opt = {
1980
+ stdio: 'inherit',
1981
+ env: process.env,
1982
+ cwd: process.env.HOME
1983
+ }
1984
+
1985
+ function writeFile(callback) {
1986
+ if (!options.value) {
1987
+ return callback()
1988
+ }
1989
+ return fs.writeFile(file, options.value, callback)
1990
+ }
1991
+
1992
+ return writeFile(function (err) {
1993
+ if (err) {
1994
+ return callback(err)
1995
+ }
1996
+ return self.exec(editor, args, opt, function (err, success) {
1997
+ if (err) {
1998
+ return callback(err)
1999
+ }
2000
+ return fs.readFile(file, 'utf8', function (err, data) {
2001
+ return fs.unlink(file, function () {
2002
+ if (!success) {
2003
+ return callback(new Error('Unsuccessful.'))
2004
+ }
2005
+ if (err) {
2006
+ return callback(err)
2007
+ }
2008
+ return callback(null, data)
2009
+ })
2010
+ })
2011
+ })
2012
+ })
2013
+ }
2014
+
2015
+ Screen.prototype.displayImage = function (file, callback) {
2016
+ if (!file) {
2017
+ if (!callback) {
2018
+ return
2019
+ }
2020
+ return callback(new Error('No image.'))
2021
+ }
2022
+
2023
+ file = path.resolve(process.cwd(), file)
2024
+
2025
+ if (!~file.indexOf('://')) {
2026
+ file = 'file://' + file
2027
+ }
2028
+
2029
+ const args = ['w3m', '-T', 'text/html']
2030
+
2031
+ const input =
2032
+ '<title>press q to exit</title>' + '<img align="center" src="' + file + '">'
2033
+
2034
+ const opt = {
2035
+ stdio: ['pipe', 1, 2],
2036
+ env: process.env,
2037
+ cwd: process.env.HOME
2038
+ }
2039
+
2040
+ const ps = this.spawn(args[0], args.slice(1), opt)
2041
+
2042
+ ps.on('error', function (err) {
2043
+ if (!callback) {
2044
+ return
2045
+ }
2046
+ return callback(err)
2047
+ })
2048
+
2049
+ ps.on('exit', function (code) {
2050
+ if (!callback) {
2051
+ return
2052
+ }
2053
+ if (code !== 0) {
2054
+ return callback(new Error('Exit Code: ' + code))
2055
+ }
2056
+ return callback(null, code === 0)
2057
+ })
2058
+
2059
+ ps.stdin.write(input + '\n')
2060
+ ps.stdin.end()
2061
+ }
2062
+
2063
+ Screen.prototype.setEffects = function (el, fel, over, out, effects, temp) {
2064
+ if (!effects) {
2065
+ return
2066
+ }
2067
+
2068
+ const tmp = {}
2069
+ if (temp) {
2070
+ el[temp] = tmp
2071
+ }
2072
+
2073
+ if (typeof el !== 'function') {
2074
+ const _el = el
2075
+ el = function () {
2076
+ return _el
2077
+ }
2078
+ }
2079
+
2080
+ fel.on(over, function () {
2081
+ const element = el()
2082
+ Object.keys(effects).forEach(function (key) {
2083
+ const val = effects[key]
2084
+ if (val !== null && typeof val === 'object') {
2085
+ tmp[key] = tmp[key] || {}
2086
+ // element.style[key] = element.style[key] || {};
2087
+ Object.keys(val).forEach(function (k) {
2088
+ const v = val[k]
2089
+ tmp[key][k] = element.style[key][k]
2090
+ element.style[key][k] = v
2091
+ })
2092
+ return
2093
+ }
2094
+ tmp[key] = element.style[key]
2095
+ element.style[key] = val
2096
+ })
2097
+ element.screen.render()
2098
+ })
2099
+
2100
+ fel.on(out, function () {
2101
+ const element = el()
2102
+ Object.keys(effects).forEach(function (key) {
2103
+ const val = effects[key]
2104
+ if (val !== null && typeof val === 'object') {
2105
+ tmp[key] = tmp[key] || {}
2106
+ // element.style[key] = element.style[key] || {};
2107
+ Object.keys(val).forEach(function (k) {
2108
+ if (tmp[key].hasOwnProperty(k)) {
2109
+ element.style[key][k] = tmp[key][k]
2110
+ }
2111
+ })
2112
+ return
2113
+ }
2114
+ if (tmp.hasOwnProperty(key)) {
2115
+ element.style[key] = tmp[key]
2116
+ }
2117
+ })
2118
+ element.screen.render()
2119
+ })
2120
+ }
2121
+
2122
+ Screen.prototype.sigtstp = function (callback) {
2123
+ const self = this
2124
+ this.program.sigtstp(function () {
2125
+ self.alloc()
2126
+ self.render()
2127
+ self.program.lrestoreCursor('pause', true)
2128
+ if (callback) {
2129
+ callback()
2130
+ }
2131
+ })
2132
+ }
2133
+
2134
+ Screen.prototype.copyToClipboard = function (text) {
2135
+ return this.program.copyToClipboard(text)
2136
+ }
2137
+
2138
+ Screen.prototype.cursorShape = function (shape, blink) {
2139
+ const self = this
2140
+
2141
+ this.cursor.shape = shape || 'block'
2142
+ this.cursor.blink = blink || false
2143
+ this.cursor._set = true
2144
+
2145
+ if (this.cursor.artificial) {
2146
+ if (!this.program.hideCursor_old) {
2147
+ const hideCursor = this.program.hideCursor
2148
+ this.program.hideCursor_old = this.program.hideCursor
2149
+ this.program.hideCursor = function () {
2150
+ hideCursor.call(self.program)
2151
+ self.cursor._hidden = true
2152
+ if (self.renders) {
2153
+ self.render()
2154
+ }
2155
+ }
2156
+ }
2157
+ if (!this.program.showCursor_old) {
2158
+ const showCursor = this.program.showCursor
2159
+ this.program.showCursor_old = this.program.showCursor
2160
+ this.program.showCursor = function () {
2161
+ self.cursor._hidden = false
2162
+ if (self.program._exiting) {
2163
+ showCursor.call(self.program)
2164
+ }
2165
+ if (self.renders) {
2166
+ self.render()
2167
+ }
2168
+ }
2169
+ }
2170
+ if (!this._cursorBlink) {
2171
+ this._cursorBlink = setInterval(function () {
2172
+ if (!self.cursor.blink) {
2173
+ return
2174
+ }
2175
+ self.cursor._state ^= 1
2176
+ if (self.renders) {
2177
+ self.render()
2178
+ }
2179
+ }, 500)
2180
+ if (this._cursorBlink.unref) {
2181
+ this._cursorBlink.unref()
2182
+ }
2183
+ }
2184
+ return true
2185
+ }
2186
+
2187
+ return this.program.cursorShape(this.cursor.shape, this.cursor.blink)
2188
+ }
2189
+
2190
+ Screen.prototype.cursorColor = function (color) {
2191
+ this.cursor.color = color != null ? colors.convert(color) : null
2192
+ this.cursor._set = true
2193
+
2194
+ if (this.cursor.artificial) {
2195
+ return true
2196
+ }
2197
+
2198
+ return this.program.cursorColor(colors.ncolors[this.cursor.color])
2199
+ }
2200
+
2201
+ Screen.prototype.cursorReset = Screen.prototype.resetCursor = function () {
2202
+ this.cursor.shape = 'block'
2203
+ this.cursor.blink = false
2204
+ this.cursor.color = null
2205
+ this.cursor._set = false
2206
+
2207
+ if (this.cursor.artificial) {
2208
+ this.cursor.artificial = false
2209
+ if (this.program.hideCursor_old) {
2210
+ this.program.hideCursor = this.program.hideCursor_old
2211
+ delete this.program.hideCursor_old
2212
+ }
2213
+ if (this.program.showCursor_old) {
2214
+ this.program.showCursor = this.program.showCursor_old
2215
+ delete this.program.showCursor_old
2216
+ }
2217
+ if (this._cursorBlink) {
2218
+ clearInterval(this._cursorBlink)
2219
+ delete this._cursorBlink
2220
+ }
2221
+ return true
2222
+ }
2223
+
2224
+ return this.program.cursorReset()
2225
+ }
2226
+
2227
+ Screen.prototype._cursorAttr = function (cursor, dattr) {
2228
+ let attr = dattr || this.dattr,
2229
+ cattr,
2230
+ ch
2231
+
2232
+ if (cursor.shape === 'line') {
2233
+ attr &= ~(0x1ff << 9)
2234
+ attr |= 7 << 9
2235
+ ch = '\u2502'
2236
+ } else if (cursor.shape === 'underline') {
2237
+ attr &= ~(0x1ff << 9)
2238
+ attr |= 7 << 9
2239
+ attr |= 2 << 18
2240
+ } else if (cursor.shape === 'block') {
2241
+ attr &= ~(0x1ff << 9)
2242
+ attr |= 7 << 9
2243
+ attr |= 8 << 18
2244
+ } else if (typeof cursor.shape === 'object' && cursor.shape) {
2245
+ const Element = require('./element')
2246
+ cattr = Element.prototype.sattr.call(cursor, cursor.shape)
2247
+
2248
+ if (
2249
+ cursor.shape.bold ||
2250
+ cursor.shape.underline ||
2251
+ cursor.shape.blink ||
2252
+ cursor.shape.inverse ||
2253
+ cursor.shape.invisible
2254
+ ) {
2255
+ attr &= ~(0x1ff << 18)
2256
+ attr |= ((cattr >> 18) & 0x1ff) << 18
2257
+ }
2258
+
2259
+ if (cursor.shape.fg) {
2260
+ attr &= ~(0x1ff << 9)
2261
+ attr |= ((cattr >> 9) & 0x1ff) << 9
2262
+ }
2263
+
2264
+ if (cursor.shape.bg) {
2265
+ attr &= ~(0x1ff << 0)
2266
+ attr |= cattr & 0x1ff
2267
+ }
2268
+
2269
+ if (cursor.shape.ch) {
2270
+ ch = cursor.shape.ch
2271
+ }
2272
+ }
2273
+
2274
+ if (cursor.color != null) {
2275
+ attr &= ~(0x1ff << 9)
2276
+ attr |= cursor.color << 9
2277
+ }
2278
+
2279
+ return {
2280
+ ch: ch,
2281
+ attr: attr
2282
+ }
2283
+ }
2284
+
2285
+ Screen.prototype.screenshot = function (xi, xl, yi, yl, term) {
2286
+ if (xi == null) {
2287
+ xi = 0
2288
+ }
2289
+ if (xl == null) {
2290
+ xl = this.cols
2291
+ }
2292
+ if (yi == null) {
2293
+ yi = 0
2294
+ }
2295
+ if (yl == null) {
2296
+ yl = this.rows
2297
+ }
2298
+
2299
+ if (xi < 0) {
2300
+ xi = 0
2301
+ }
2302
+ if (yi < 0) {
2303
+ yi = 0
2304
+ }
2305
+
2306
+ let x, y, line, out, ch, data, attr
2307
+
2308
+ const sdattr = this.dattr
2309
+
2310
+ if (term) {
2311
+ this.dattr = term.defAttr
2312
+ }
2313
+
2314
+ let main = ''
2315
+
2316
+ for (y = yi; y < yl; y++) {
2317
+ line = term ? term.lines[y] : this.lines[y]
2318
+
2319
+ if (!line) {
2320
+ break
2321
+ }
2322
+
2323
+ out = ''
2324
+ attr = this.dattr
2325
+
2326
+ for (x = xi; x < xl; x++) {
2327
+ if (!line[x]) {
2328
+ break
2329
+ }
2330
+
2331
+ data = line[x][0]
2332
+ ch = line[x][1]
2333
+
2334
+ if (data !== attr) {
2335
+ if (attr !== this.dattr) {
2336
+ out += '\x1b[m'
2337
+ }
2338
+ if (data !== this.dattr) {
2339
+ let _data = data
2340
+ if (term) {
2341
+ if (((_data >> 9) & 0x1ff) === 257) {
2342
+ _data |= 0x1ff << 9
2343
+ }
2344
+ if ((_data & 0x1ff) === 256) {
2345
+ _data |= 0x1ff
2346
+ }
2347
+ }
2348
+ out += this.codeAttr(_data)
2349
+ }
2350
+ }
2351
+
2352
+ if (this.fullUnicode) {
2353
+ if (unicode.charWidth(line[x][1]) === 2) {
2354
+ if (x === xl - 1) {
2355
+ ch = ' '
2356
+ } else {
2357
+ x++
2358
+ }
2359
+ }
2360
+ }
2361
+
2362
+ out += ch
2363
+ attr = data
2364
+ }
2365
+
2366
+ if (attr !== this.dattr) {
2367
+ out += '\x1b[m'
2368
+ }
2369
+
2370
+ if (out) {
2371
+ main += (y > 0 ? '\n' : '') + out
2372
+ }
2373
+ }
2374
+
2375
+ main = main.replace(/(?:\s*\x1b\[40m\s*\x1b\[m\s*)*$/, '') + '\n'
2376
+
2377
+ if (term) {
2378
+ this.dattr = sdattr
2379
+ }
2380
+
2381
+ return main
2382
+ }
2383
+
2384
+ /**
2385
+ * Positioning
2386
+ */
2387
+
2388
+ Screen.prototype._getPos = function () {
2389
+ return this
2390
+ }
2391
+
2392
+ /**
2393
+ * Angle Table
2394
+ */
2395
+
2396
+ const angles = {
2397
+ '\u2518': true, // '┘'
2398
+ '\u2510': true, // '┐'
2399
+ '\u250c': true, // '┌'
2400
+ '\u2514': true, // '└'
2401
+ '\u253c': true, // '┼'
2402
+ '\u251c': true, // '├'
2403
+ '\u2524': true, // '┤'
2404
+ '\u2534': true, // '┴'
2405
+ '\u252c': true, // '┬'
2406
+ '\u2502': true, // '│'
2407
+ '\u2500': true // '─'
2408
+ }
2409
+
2410
+ const langles = {
2411
+ '\u250c': true, // '┌'
2412
+ '\u2514': true, // '└'
2413
+ '\u253c': true, // '┼'
2414
+ '\u251c': true, // '├'
2415
+ '\u2534': true, // '┴'
2416
+ '\u252c': true, // '┬'
2417
+ '\u2500': true // '─'
2418
+ }
2419
+
2420
+ const uangles = {
2421
+ '\u2510': true, // '┐'
2422
+ '\u250c': true, // '┌'
2423
+ '\u253c': true, // '┼'
2424
+ '\u251c': true, // '├'
2425
+ '\u2524': true, // '┤'
2426
+ '\u252c': true, // '┬'
2427
+ '\u2502': true // '│'
2428
+ }
2429
+
2430
+ const rangles = {
2431
+ '\u2518': true, // '┘'
2432
+ '\u2510': true, // '┐'
2433
+ '\u253c': true, // '┼'
2434
+ '\u2524': true, // '┤'
2435
+ '\u2534': true, // '┴'
2436
+ '\u252c': true, // '┬'
2437
+ '\u2500': true // '─'
2438
+ }
2439
+
2440
+ const dangles = {
2441
+ '\u2518': true, // '┘'
2442
+ '\u2514': true, // '└'
2443
+ '\u253c': true, // '┼'
2444
+ '\u251c': true, // '├'
2445
+ '\u2524': true, // '┤'
2446
+ '\u2534': true, // '┴'
2447
+ '\u2502': true // '│'
2448
+ }
2449
+
2450
+ // var cdangles = {
2451
+ // '\u250c': true // '┌'
2452
+ // };
2453
+
2454
+ // Every ACS angle character can be
2455
+ // represented by 4 bits ordered like this:
2456
+ // [langle][uangle][rangle][dangle]
2457
+ const angleTable = {
2458
+ '0000': '', // ?
2459
+ '0001': '\u2502', // '│' // ?
2460
+ '0010': '\u2500', // '─' // ??
2461
+ '0011': '\u250c', // '┌'
2462
+ '0100': '\u2502', // '│' // ?
2463
+ '0101': '\u2502', // '│'
2464
+ '0110': '\u2514', // '└'
2465
+ '0111': '\u251c', // '├'
2466
+ 1000: '\u2500', // '─' // ??
2467
+ 1001: '\u2510', // '┐'
2468
+ 1010: '\u2500', // '─' // ??
2469
+ 1011: '\u252c', // '┬'
2470
+ 1100: '\u2518', // '┘'
2471
+ 1101: '\u2524', // '┤'
2472
+ 1110: '\u2534', // '┴'
2473
+ 1111: '\u253c' // '┼'
2474
+ }
2475
+
2476
+ Object.keys(angleTable).forEach(function (key) {
2477
+ angleTable[parseInt(key, 2)] = angleTable[key]
2478
+ delete angleTable[key]
2479
+ })
2480
+
2481
+ /**
2482
+ * Expose
2483
+ */
2484
+
2485
+ module.exports = Screen