1 /**
2 * Consoleur: a package for interaction with character-oriented terminal emulators
3 *
4 * Copyright: Maxim Freck, 2017.
5 * Authors: Maxim Freck <maxim@freck.pp.ru>
6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 */
8 module consoleur.terminfo.posix;
9 version(Posix) {
10
11 import consoleur.terminfo.io;
12
13 /// Terminfo boolean capabilities
14 enum CapFlag: size_t
15 {
16 autoLeftMargin = 0, //Cub1 wraps from column 0 to last column
17 autoRightMargin = 1, //Terminal has automatic margins
18 noEscCtlc = 2, //Beehive (f1=escape, f2=ctrl C)
19 ceolStandoutGlitch = 3, //Standout not erased by overwriting (hp)
20 eatNewlineGlitch = 4, //Newline ignored after 80 columns (Concept)
21 eraseOverstrike = 5, //Can erase overstrikes with a blank
22 genericType = 6, //Generic line type (e.g., dialup, switch)
23 hardCopy = 7, //Hardcopy terminal
24 hasMetaKey = 8, //Has a meta key (shift, sets parity bit)
25 hasStatusLine = 9, //Has extra "status line"
26 insertNullGlitch = 10, //Insert mode distinguishes nulls
27 memoryAbove = 11, //Display may be retained above the screen
28 memoryBelow = 12, //Display may be retained below the screen
29 moveInsertMode = 13, //Safe to move while in insert mode
30 moveStandoutMode = 14, //Safe to move in standout modes
31 overStrike = 15, //Terminal overstrikes on hard-copy terminal
32 statusLineEscOk = 16, //Escape can be used on the status line
33 destTabsMagicSmso = 17, //Destructive tabs, magic smso char (t1061)
34 tildeGlitch = 18, //Hazeltine; can't print tilde (~)
35 transparentUnderline = 19, //Underline character overstrikes
36 xonXoff = 20, //Terminal uses xon/xoff handshaking
37 needsXonXoff = 21, //Padding won't work, xon/xoff required
38 prtrSilent = 22, //Printer won't echo on screen
39 hardCursor = 23, //Cursor is hard to see
40 nonRevRmcup = 24, //smcup does not reverse rmcup
41 noPadChar = 25, //Pad character doesn't exist
42 nonDestScrollRegion = 26, //Scrolling region is nondestructive
43 canChange = 27, //Terminal can re-define existing colour
44 backColorErase = 28, //Screen erased with background colour
45 hueLightnessSaturation = 29, //Terminal uses only HLS colour notation (Tektronix)
46 colAddrGlitch = 30, //Only positive motion for hpa/mhpa caps
47 crCancelsMicroMode = 31, //Using cr turns off micro mode
48 hasPrintWheel = 32, //Printer needs operator to change character set
49 rowAddrGlitch = 33, //Only positive motion for vpa/mvpa caps
50 semiAutoRightMargin = 34, //Printing in last column causes cr
51 cpiChangesRes = 35, //Changing character pitch changes resolution
52 lpiChangesRes = 36, //Changing line pitch changes resolution
53
54 backspacesWithBs = 37,
55 crtNoScrolling = 38,
56 noCorrectlyWorkingCr = 39,
57 gnuHasMetaKey = 40,
58 linefeedIsNewline = 41,
59 hasHardwareTabs = 42,
60 returnDoesClrEol = 43,
61 }
62
63 /// Terminfo short capabilities
64 enum CapShort: size_t
65 {
66 columns = 0, //Number of columns in a line
67 initTabs = 1, //Tabs initially every # spaces
68 lines = 2, //Number of lines on a screen or a page
69 linesOfMemory = 3, //Lines of memory if > lines; 0 means varies
70 magicCookieGlitch = 4, //Number of blank characters left by smso or rmso
71 paddingBaudRate = 5, //Lowest baud rate where padding needed
72 virtualTerminal = 6, //Virtual terminal number
73 widthStatusLine = 7, //Number of columns in status line
74 numLabels = 8, //Number of labels on screen (start at 1)
75 labelHeight = 9, //Number of rows in each label
76 labelWidth = 10, //Number of columns in each label
77 maxAttributes = 11, //Maximum combined video attributes terminal can display
78 maximumWindows = 12, //Maximum number of definable windows
79 maxColors = 13, //Maximum number of colours on the screen
80 maxPairs = 14, //Maximum number of colour-pairs on the screen
81 noColorVideo = 15, //Video attributes that can't be used with colours
82 bufferCapacity = 16, //Number of bytes buffered before printing
83 dotVertSpacing = 17, //Spacing of pins vertically in pins per inch
84 dotHorzSpacing = 18, //Spacing of dots horizontally in dots per inch
85 maxMicroAddress = 19, //Maximum value in micro_..._address
86 maxMicroJump = 20, //Maximum value in parm_..._micro
87 microColSize = 21, //Character step size when in micro mode
88 microLineSize = 22, //Line step size when in micro mode
89 numberOfPins = 23, //Number of pins in print-head
90 outputResChar = 24, //Horizontal resolution in units per character
91 outputResLine = 25, //Vertical resolution in units per line
92 outputResHorzInch = 26, //Horizontal resolution in units per inch
93 outputResVertInch = 27, //Vertical resolution in units per inch
94 printRate = 28, //Print rate in characters per second
95 wideCharSize = 29, //Character step size when in double-wide mode
96 buttons = 30, //Number of buttons on the mouse
97 bitImageEntwining = 31, //Number of passes for each bit-map row
98 bitImageType = 32, //Type of bit image device
99
100 magicCookieGlitchUl = 33,
101 carriageReturnDelay = 34,
102 newLineDelay = 35,
103 backspaceDelay = 36,
104 horizontalTabDelay = 37,
105 numberOfFunctionKeys = 38,
106 }
107
108 /// Terminfo string capabilities
109 enum CapString: size_t
110 {
111 backTab = 0,
112 bell = 1,
113 carriageReturn = 2,
114 changeScrollRegion = 3,
115 clearAllTabs = 4,
116 clearScreen = 5,
117 clrEol = 6,
118 clrEos = 7,
119 columnAddress = 8,
120 commandCharacter = 9,
121 cursorAddress = 10,
122 cursorDown = 11,
123 cursorHome = 12,
124 cursorInvisible = 13,
125 cursorLeft = 14,
126 cursorMemAddress = 15,
127 cursorNormal = 16,
128 cursorRight = 17,
129 cursorToLl = 18,
130 cursorUp = 19,
131 cursorVisible = 20,
132 deleteCharacter = 21,
133 deleteLine = 22,
134 disStatusLine = 23,
135 downHalfLine = 24,
136 enterAltCharsetMode = 25,
137 enterBlinkMode = 26,
138 enterBoldMode = 27,
139 enterCaMode = 28,
140 enterDeleteMode = 29,
141 enterDimMode = 30,
142 enterInsertMode = 31,
143 enterSecureMode = 32,
144 enterProtectedMode = 33,
145 enterReverseMode = 34,
146 enterStandoutMode = 35,
147 enterUnderlineMode = 36,
148 eraseChars = 37,
149 exitAltCharsetMode = 38,
150 exitAttributeMode = 39,
151 exitCaMode = 40,
152 exitDeleteMode = 41,
153 exitInsertMode = 42,
154 exitStandoutMode = 43,
155 exitUnderlineMode = 44,
156 flashScreen = 45,
157 formFeed = 46,
158 fromStatusLine = 47,
159 init1string = 48,
160 init2string = 49,
161 init3string = 50,
162 initFile = 51,
163 insertCharacter = 52,
164 insertLine = 53,
165 insertPadding = 54,
166 keyBackspace = 55,
167 keyCatab = 56,
168 keyClear = 57,
169 keyCtab = 58,
170 keyDc = 59,
171 keyDl = 60,
172 keyDown = 61,
173 keyEic = 62,
174 keyEol = 63,
175 keyEos = 64,
176 keyF0 = 65,
177 keyF1 = 66,
178 keyF10 = 67,
179 keyF2 = 68,
180 keyF3 = 69,
181 keyF4 = 70,
182 keyF5 = 71,
183 keyF6 = 72,
184 keyF7 = 73,
185 keyF8 = 74,
186 keyF9 = 75,
187 keyHome = 76,
188 keyIc = 77,
189 keyIl = 78,
190 keyLeft = 79,
191 keyLl = 80,
192 keyNpage = 81,
193 keyPpage = 82,
194 keyRight = 83,
195 keySf = 84,
196 keySr = 85,
197 keyStab = 86,
198 keyUp = 87,
199 keypadLocal = 88,
200 keypadXmit = 89,
201 labF0 = 90,
202 labF1 = 91,
203 labF10 = 92,
204 labF2 = 93,
205 labF3 = 94,
206 labF4 = 95,
207 labF5 = 96,
208 labF6 = 97,
209 labF7 = 98,
210 labF8 = 99,
211 labF9 = 100,
212 metaOff = 101,
213 metaOn = 102,
214 newline = 103,
215 padChar = 104,
216 parmDch = 105,
217 parmDeleteLine = 106,
218 parmDownCursor = 107,
219 parmIch = 108,
220 parmIndex = 109,
221 parmInsertLine = 110,
222 parmLeftCursor = 111,
223 parmRightCursor = 112,
224 parmRindex = 113,
225 parmUpCursor = 114,
226 pkeyKey = 115,
227 pkeyLocal = 116,
228 pkeyXmit = 117,
229 printScreen = 118,
230 prtrOff = 119,
231 prtrOn = 120,
232 repeatChar = 121,
233 reset1string = 122,
234 reset2string = 123,
235 reset3string = 124,
236 resetFile = 125,
237 restoreCursor = 126,
238 rowAddress = 127,
239 saveCursor = 128,
240 scrollForward = 129,
241 scrollReverse = 130,
242 setAttributes = 131,
243 setTab = 132,
244 setWindow = 133,
245 tab = 134,
246 toStatusLine = 135,
247 underlineChar = 136,
248 upHalfLine = 137,
249 initProg = 138,
250 keyA1 = 139,
251 keyA3 = 140,
252 keyB2 = 141,
253 keyC1 = 142,
254 keyC3 = 143,
255 prtrNon = 144,
256 charPadding = 145,
257 acsChars = 146,
258 plabNorm = 147,
259 keyBtab = 148,
260 enterXonMode = 149,
261 exitXonMode = 150,
262 enterAmMode = 151,
263 exitAmMode = 152,
264 xonCharacter = 153,
265 xoffCharacter = 154,
266 enaAcs = 155,
267 labelOn = 156,
268 labelOff = 157,
269 keyBeg = 158,
270 keyCancel = 159,
271 keyClose = 160,
272 keyCommand = 161,
273 keyCopy = 162,
274 keyCreate = 163,
275 keyEnd = 164,
276 keyEnter = 165,
277 keyExit = 166,
278 keyFind = 167,
279 keyHelp = 168,
280 keyMark = 169,
281 keyMessage = 170,
282 keyMove = 171,
283 keyNext = 172,
284 keyOpen = 173,
285 keyOptions = 174,
286 keyPrevious = 175,
287 keyPrint = 176,
288 keyRedo = 177,
289 keyReference = 178,
290 keyRefresh = 179,
291 keyReplace = 180,
292 keyRestart = 181,
293 keyResume = 182,
294 keySave = 183,
295 keySuspend = 184,
296 keyUndo = 185,
297 keySbeg = 186,
298 keyScancel = 187,
299 keyScommand = 188,
300 keyScopy = 189,
301 keyScreate = 190,
302 keySdc = 191,
303 keySdl = 192,
304 keySelect = 193,
305 keySend = 194,
306 keySeol = 195,
307 keySexit = 196,
308 keySfind = 197,
309 keyShelp = 198,
310 keyShome = 199,
311 keySic = 200,
312 keySleft = 201,
313 keySmessage = 202,
314 keySmove = 203,
315 keySnext = 204,
316 keySoptions = 205,
317 keySprevious = 206,
318 keySprint = 207,
319 keySredo = 208,
320 keySreplace = 209,
321 keySright = 210,
322 keySrsume = 211,
323 keySsave = 212,
324 keySsuspend = 213,
325 keySundo = 214,
326 reqForInput = 215,
327 keyF11 = 216,
328 keyF12 = 217,
329 keyF13 = 218,
330 keyF14 = 219,
331 keyF15 = 220,
332 keyF16 = 221,
333 keyF17 = 222,
334 keyF18 = 223,
335 keyF19 = 224,
336 keyF20 = 225,
337 keyF21 = 226,
338 keyF22 = 227,
339 keyF23 = 228,
340 keyF24 = 229,
341 keyF25 = 230,
342 keyF26 = 231,
343 keyF27 = 232,
344 keyF28 = 233,
345 keyF29 = 234,
346 keyF30 = 235,
347 keyF31 = 236,
348 keyF32 = 237,
349 keyF33 = 238,
350 keyF34 = 239,
351 keyF35 = 240,
352 keyF36 = 241,
353 keyF37 = 242,
354 keyF38 = 243,
355 keyF39 = 244,
356 keyF40 = 245,
357 keyF41 = 246,
358 keyF42 = 247,
359 keyF43 = 248,
360 keyF44 = 249,
361 keyF45 = 250,
362 keyF46 = 251,
363 keyF47 = 252,
364 keyF48 = 253,
365 keyF49 = 254,
366 keyF50 = 255,
367 keyF51 = 256,
368 keyF52 = 257,
369 keyF53 = 258,
370 keyF54 = 259,
371 keyF55 = 260,
372 keyF56 = 261,
373 keyF57 = 262,
374 keyF58 = 263,
375 keyF59 = 264,
376 keyF60 = 265,
377 keyF61 = 266,
378 keyF62 = 267,
379 keyF63 = 268,
380 clrBol = 269,
381 clearMargins = 270,
382 setLeftMargin = 271,
383 setRightMargin = 272,
384 labelFormat = 273,
385 setClock = 274,
386 displayClock = 275,
387 removeClock = 276,
388 createWindow = 277,
389 gotoWindow = 278,
390 hangup = 279,
391 dialPhone = 280,
392 quickDial = 281,
393 tone = 282,
394 pulse = 283,
395 flashHook = 284,
396 fixedPause = 285,
397 waitTone = 286,
398 user0 = 287,
399 user1 = 288,
400 user2 = 289,
401 user3 = 290,
402 user4 = 291,
403 user5 = 292,
404 user6 = 293,
405 user7 = 294,
406 user8 = 295,
407 user9 = 296,
408 origPair = 297,
409 origColors = 298,
410 initializeColor = 299,
411 initializePair = 300,
412 setColorPair = 301,
413 setForeground = 302,
414 setBackground = 303,
415 changeCharPitch = 304,
416 changeLinePitch = 305,
417 changeResHorz = 306,
418 changeResVert = 307,
419 defineChar = 308,
420 enterDoublewideMode = 309,
421 enterDraftQuality = 310,
422 enterItalicsMode = 311,
423 enterLeftwardMode = 312,
424 enterMicroMode = 313,
425 enterNearLetterQuality = 314,
426 enterNormalQuality = 315,
427 enterShadowMode = 316,
428 enterSubscriptMode = 317,
429 enterSuperscriptMode = 318,
430 enterUpwardMode = 319,
431 exitDoublewideMode = 320,
432 exitItalicsMode = 321,
433 exitLeftwardMode = 322,
434 exitMicroMode = 323,
435 exitShadowMode = 324,
436 exitSubscriptMode = 325,
437 exitSuperscriptMode = 326,
438 exitUpwardMode = 327,
439 microColumnAddress = 328,
440 microDown = 329,
441 microLeft = 330,
442 microRight = 331,
443 microRowAddress = 332,
444 microUp = 333,
445 orderOfPins = 334,
446 parmDownMicro = 335,
447 parmLeftMicro = 336,
448 parmRightMicro = 337,
449 parmUpMicro = 338,
450 selectCharSet = 339,
451 setBottomMargin = 340,
452 setBottomMarginParm = 341,
453 setLeftMarginParm = 342,
454 setRightMarginParm = 343,
455 setTopMargin = 344,
456 setTopMarginParm = 345,
457 startBitImage = 346,
458 startCharSetDef = 347,
459 stopBitImage = 348,
460 stopCharSetDef = 349,
461 subscriptCharacters = 350,
462 superscriptCharacters = 351,
463 theseCauseCr = 352,
464 zeroMotion = 353,
465 charSetNames = 354,
466 keyMouse = 355,
467 mouseInfo = 356,
468 reqMousePos = 357,
469 getMouse = 358,
470 setAForeground = 359,
471 setABackground = 360,
472 pkeyPlab = 361,
473 deviceType = 362,
474 codeSetInit = 363,
475 set0DesSeq = 364,
476 set1DesSeq = 365,
477 set2DesSeq = 366,
478 set3DesSeq = 367,
479 setLrMargin = 368,
480 setTbMargin = 369,
481 bitImageRepeat = 370,
482 bitImageNewline = 371,
483 bitImageCarriageReturn = 372,
484 colorNames = 373,
485 defineBitImageRegion = 374,
486 endBitImageRegion = 375,
487 setColorBand = 376,
488 setPageLength = 377,
489 displayPcChar = 378,
490 enterPcCharsetMode = 379,
491 exitPcCharsetMode = 380,
492 enterScancodeMode = 381,
493 exitScancodeMode = 382,
494 pcTermOptions = 383,
495 scancodeEscape = 384,
496 altScancodeEsc = 385,
497 enterHorizontalHlMode = 386,
498 enterLeftHlMode = 387,
499 enterLowHlMode = 388,
500 enterRightHlMode = 389,
501 enterTopHlMode = 390,
502 enterVerticalHlMode = 391,
503 setAAttributes = 392,
504 setPglenInch = 393,
505 termcapInit2 = 394,
506 termcapReset = 395,
507 linefeedIfNotLf = 396,
508 backspaceIfNotBs = 397,
509 otherNonFunctionKeys = 398,
510 arrowKeyMap = 399,
511 acsUlcorner = 400,
512 acsLlcorner = 401,
513 acsUrcorner = 402,
514 acsLrcorner = 403,
515 acsLtee = 404,
516 acsRtee = 405,
517 acsBtee = 406,
518 acsTtee = 407,
519 acsHline = 408,
520 acsVline = 409,
521 acsPlus = 410,
522 memoryLock = 411,
523 memoryUnlock = 412,
524 boxChars1 = 413,
525 }
526
527 /// Terminfo load status
528 enum TerminfoStatus: ubyte {
529 notLoaded = 0,
530 invalidFile,
531 headerLoaded,
532 namesLoaded,
533 flagsLoaded,
534 shortsLoaded,
535 stringsLoaded,
536
537 loaded = 255,
538 }
539
540 /*******
541 * Terminfo file reader
542 */
543 class Terminfo
544 {
545 private string fileName;
546 private TerminfoStatus fileStatus;
547
548 private string[] termNames;
549
550 private bool[CapFlag] flags;
551 private short[CapShort] shorts;
552 private string[CapString] strings;
553
554 /// Constructor
555 public this() @safe
556 {
557 this(determineTermFile());
558 }
559
560 ///ditto
561 public this(string fName) @safe
562 {
563 fileName = fName;
564 fileStatus = TerminfoStatus.notLoaded;
565
566 if (fileName.length > 0) loadTerminfo();
567 }
568
569 protected void loadTerminfo() @trusted
570 {
571 import std.array: split;
572 import std.stdio: File, SEEK_CUR;
573
574 auto f = File(fileName, "rb");
575
576 if (f.get!ushort != 0x011a) {
577 fileStatus = TerminfoStatus.invalidFile;
578 return;
579 }
580
581 auto namesSize = f.get!ushort;
582 auto booleanSize = f.get!ushort;
583 auto shortsSize = f.get!ushort;
584 auto stringOffsetsSize = f.get!ushort;
585 auto stringTableSize = f.get!ushort;
586
587 fileStatus = TerminfoStatus.headerLoaded;
588
589 foreach (name; f.get!char(namesSize)[0..$-1].split("|")) termNames ~= cast(string)(name);
590 fileStatus = TerminfoStatus.namesLoaded;
591
592 auto flgs = f.get!bool(booleanSize);
593 foreach(n; 0 .. flgs.length) {
594 if (flgs[n]) flags[cast(CapFlag)n] = flgs[n];
595 }
596 fileStatus = TerminfoStatus.flagsLoaded;
597
598 //Between the boolean section and the number section,
599 //a null byte will be inserted, if necessary, to ensure
600 //that the number section begins on an even byte.
601 if (f.tell % 2) f.seek(1, SEEK_CUR);
602
603 auto shrts = f.get!short(shortsSize);
604 foreach(n; 0 .. shrts.length ) {
605 if (shrts[n] > 0) shorts[cast(CapShort)n] = shrts[n];
606 }
607
608 fileStatus = TerminfoStatus.shortsLoaded;
609
610 auto offsets = f.get!short(stringOffsetsSize);
611 auto stringtable = f.get!ubyte(stringTableSize);
612 parseStrings(offsets, stringtable);
613 fileStatus = TerminfoStatus.stringsLoaded;
614
615 /+ <TODO>
616 if (f.tell != f.size) {
617 if (f.tell % 2) f.seek(1, SEEK_CUR);
618 readExtendedData(f);
619 }
620 </TODO> +/
621 fileStatus = TerminfoStatus.loaded;
622 }
623
624 protected void parseStrings(short[] offsets, ubyte[] stringtable)
625 {
626 foreach (n; 0..offsets.length) {
627 if (offsets[n] < 0 ) continue;
628 size_t start = offsets[n];
629 size_t end = start;
630 while (end < stringtable.length && stringtable[end]) end++;
631
632 strings[cast(CapString)n] = cast(string)stringtable[start .. end];
633 }
634 }
635
636 /+ <TODO>
637 protected void readExtendedData(File f)
638 {
639 import std.stdio;
640 import std.array: split;
641
642 auto f1 = File("namedump.txt", "wb");
643
644 auto flagsSize = f.get!ushort;
645 auto shortsSize = f.get!ushort;
646 auto stringsSize = f.get!ushort;
647 auto offsetCount = f.get!ushort;
648 auto tableSize = f.get!ushort;
649
650 writefln("Flags size...........%u", flagsSize);
651 writefln("Shorts size..........%u", shortsSize);
652 writefln("String offsets size..%u", stringsSize);
653 writefln("String table size....%u", offsetCount);
654 writefln("Last offset..........%u", tableSize);
655
656 auto flgs = f.get!bool(flagsSize);
657 if (flagsSize % 2) f.seek(1, SEEK_CUR);
658
659 auto shrts = f.get!short(shortsSize);
660 auto offsets = f.get!short(stringsSize);
661
662 auto offsets1 = f.get!short(flagsSize + shortsSize + stringsSize);
663
664 auto stringtable = f.get!char(tableSize);
665
666 string[] stringTable;
667 foreach (str; stringtable.split(0)) if (str.length > 0) stringTable ~= cast(string)str;
668
669 size_t namesSize = flagsSize + shortsSize + stringsSize;
670 auto strings = stringTable[0 .. $ - namesSize];
671 auto names = stringTable[$ - namesSize .. $];
672
673 f1.writeln("Strings");
674 f1.writeln(strings);
675
676 f1.writeln("\nNames");
677 f1.writeln(names);
678
679 size_t id = 0;
680 foreach (b; flgs) {
681 writefln("%s = %s", names[id++], b);
682 }
683
684 foreach (sh; shrts) {
685 writefln("%s = %s", names[id++], sh);
686 }
687
688 foreach (str; strings) {
689 writefln("%s = %s", names[id++], str);
690 }
691 }
692 </TODO> +/
693
694 /*******
695 * Returns: terminfo load status
696 */
697 public nothrow TerminfoStatus getStatus() @safe @nogc
698 {
699 return fileStatus;
700 }
701
702 /*******
703 * Returns: terminfo file name
704 */
705 public nothrow string getFileName() @safe @nogc
706 {
707 return fileName;
708 }
709
710 /*******
711 * Returns: list of terminal names
712 */
713 public nothrow string[] getTermNames() @safe @nogc
714 {
715 return termNames;
716 }
717
718 /*******
719 * Returns: terminfo boolean capability
720 */
721 public nothrow bool get(CapFlag f) @safe @nogc
722 {
723 auto flg = (f in flags);
724 if (flg is null) return false;
725 return *flg;
726 }
727
728 /*******
729 * Returns: terminfo int capability
730 */
731 public nothrow short get(CapShort s) @safe @nogc
732 {
733 auto shrt = (s in shorts);
734 if (shrt is null) return -1;
735 return *shrt;
736 }
737
738 /*******
739 * Returns: terminfo string capability
740 */
741 public nothrow string get(CapString s) @safe @nogc
742 {
743 auto str = (s in strings);
744 if (str is null) return "";
745 return *str;
746 }
747
748 private static Terminfo actual;
749
750 /*******
751 * Returns: terminfo reader depending on $TERM env
752 */
753 public static Terminfo getActual() @safe
754 {
755 if (actual is null) {
756 actual = new Terminfo();
757 }
758 return actual;
759 }
760 }
761
762 }