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 }