@socketsecurity/cli-with-sentry 0.14.67 → 0.14.68

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