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 }