25 #include <boost/filesystem/operations.hpp> 26 #include <senf/config.hh> 31 # include <byteswap.h> 32 # include <arpa/inet.h> 33 # define le16toh(x) (ntohs(bswap_16(x))) 41 "AutoLeftMargin",
"AutoRightMargin",
"NoEscCtlc",
"CeolStandoutGlitch",
"EatNewlineGlitch",
42 "EraseOverstrike",
"GenericType",
"HardCopy",
"HasMetaKey",
"HasStatusLine",
"InsertNullGlitch",
43 "MemoryAbove",
"MemoryBelow",
"MoveInsertMode",
"MoveStandoutMode",
"OverStrike",
44 "StatusLineEscOk",
"DestTabsMagicSmso",
"TildeGlitch",
"TransparentUnderline",
"XonXoff",
45 "NeedsXonXoff",
"PrtrSilent",
"HardCursor",
"NonRevRmcup",
"NoPadChar",
"NonDestScrollRegion",
46 "CanChange",
"BackColorErase",
"HueLightnessSaturation",
"ColAddrGlitch",
"CrCancelsMicroMode",
47 "HasPrintWheel",
"RowAddrGlitch",
"SemiAutoRightMargin",
"CpiChangesRes",
"LpiChangesRes",
48 "BackspacesWithBs",
"CrtNoScrolling",
"NoCorrectlyWorkingCr",
"GnuHasMetaKey",
49 "LinefeedIsNewline",
"HasHardwareTabs",
"ReturnDoesClrEol" };
52 "Columns",
"InitTabs",
"Lines",
"LinesOfMemory",
"MagicCookieGlitch",
"PaddingBaudRate",
53 "VirtualTerminal",
"WidthStatusLine",
"NumLabels",
"LabelHeight",
"LabelWidth",
"MaxAttributes",
54 "MaximumWindows",
"MaxColors",
"MaxPairs",
"NoColorVideo",
"BufferCapacity",
"DotVertSpacing",
55 "DotHorzSpacing",
"MaxMicroAddress",
"MaxMicroJump",
"MicroColSize",
"MicroLineSize",
56 "NumberOfPins",
"OutputResChar",
"OutputResLine",
"OutputResHorzInch",
"OutputResVertInch",
57 "PrintRate",
"WideCharSize",
"Buttons",
"BitImageEntwining",
"BitImageType",
58 "MagicCookieGlitchUl",
"CarriageReturnDelay",
"NewLineDelay",
"BackspaceDelay",
59 "HorizontalTabDelay",
"NumberOfFunctionKeys" };
62 "BackTab",
"Bell",
"CarriageReturn",
"ChangeScrollRegion",
"ClearAllTabs",
"ClearScreen",
63 "ClrEol",
"ClrEos",
"ColumnAddress",
"CommandCharacter",
"CursorAddress",
"CursorDown",
64 "CursorHome",
"CursorInvisible",
"CursorLeft",
"CursorMemAddress",
"CursorNormal",
65 "CursorRight",
"CursorToLl",
"CursorUp",
"CursorVisible",
"DeleteCharacter",
"DeleteLine",
66 "DisStatusLine",
"DownHalfLine",
"EnterAltCharsetMode",
"EnterBlinkMode",
"EnterBoldMode",
67 "EnterCaMode",
"EnterDeleteMode",
"EnterDimMode",
"EnterInsertMode",
"EnterSecureMode",
68 "EnterProtectedMode",
"EnterReverseMode",
"EnterStandoutMode",
"EnterUnderlineMode",
69 "EraseChars",
"ExitAltCharsetMode",
"ExitAttributeMode",
"ExitCaMode",
"ExitDeleteMode",
70 "ExitInsertMode",
"ExitStandoutMode",
"ExitUnderlineMode",
"FlashScreen",
"FormFeed",
71 "FromStatusLine",
"Init1string",
"Init2string",
"Init3string",
"InitFile",
"InsertCharacter",
72 "InsertLine",
"InsertPadding",
"KeyBackspace",
"KeyCatab",
"KeyClear",
"KeyCtab",
"KeyDc",
73 "KeyDl",
"KeyDown",
"KeyEic",
"KeyEol",
"KeyEos",
"KeyF0",
"KeyF1",
"KeyF10",
"KeyF2",
"KeyF3",
74 "KeyF4",
"KeyF5",
"KeyF6",
"KeyF7",
"KeyF8",
"KeyF9",
"KeyHome",
"KeyIc",
"KeyIl",
"KeyLeft",
75 "KeyLl",
"KeyNpage",
"KeyPpage",
"KeyRight",
"KeySf",
"KeySr",
"KeyStab",
"KeyUp",
76 "KeypadLocal",
"KeypadXmit",
"LabF0",
"LabF1",
"LabF10",
"LabF2",
"LabF3",
"LabF4",
"LabF5",
77 "LabF6",
"LabF7",
"LabF8",
"LabF9",
"MetaOff",
"MetaOn",
"Newline",
"PadChar",
"ParmDch",
78 "ParmDeleteLine",
"ParmDownCursor",
"ParmIch",
"ParmIndex",
"ParmInsertLine",
"ParmLeftCursor",
79 "ParmRightCursor",
"ParmRindex",
"ParmUpCursor",
"PkeyKey",
"PkeyLocal",
"PkeyXmit",
80 "PrintScreen",
"PrtrOff",
"PrtrOn",
"RepeatChar",
"Reset1string",
"Reset2string",
81 "Reset3string",
"ResetFile",
"RestoreCursor",
"RowAddress",
"SaveCursor",
"ScrollForward",
82 "ScrollReverse",
"SetAttributes",
"SetTab",
"SetWindow",
"Tab",
"ToStatusLine",
"UnderlineChar",
83 "UpHalfLine",
"InitProg",
"KeyA1",
"KeyA3",
"KeyB2",
"KeyC1",
"KeyC3",
"PrtrNon",
"CharPadding",
84 "AcsChars",
"PlabNorm",
"KeyBtab",
"EnterXonMode",
"ExitXonMode",
"EnterAmMode",
"ExitAmMode",
85 "XonCharacter",
"XoffCharacter",
"EnaAcs",
"LabelOn",
"LabelOff",
"KeyBeg",
"KeyCancel",
86 "KeyClose",
"KeyCommand",
"KeyCopy",
"KeyCreate",
"KeyEnd",
"KeyEnter",
"KeyExit",
"KeyFind",
87 "KeyHelp",
"KeyMark",
"KeyMessage",
"KeyMove",
"KeyNext",
"KeyOpen",
"KeyOptions",
88 "KeyPrevious",
"KeyPrint",
"KeyRedo",
"KeyReference",
"KeyRefresh",
"KeyReplace",
"KeyRestart",
89 "KeyResume",
"KeySave",
"KeySuspend",
"KeyUndo",
"KeySbeg",
"KeyScancel",
"KeyScommand",
90 "KeyScopy",
"KeyScreate",
"KeySdc",
"KeySdl",
"KeySelect",
"KeySend",
"KeySeol",
"KeySexit",
91 "KeySfind",
"KeyShelp",
"KeyShome",
"KeySic",
"KeySleft",
"KeySmessage",
"KeySmove",
"KeySnext",
92 "KeySoptions",
"KeySprevious",
"KeySprint",
"KeySredo",
"KeySreplace",
"KeySright",
"KeySrsume",
93 "KeySsave",
"KeySsuspend",
"KeySundo",
"ReqForInput",
"KeyF11",
"KeyF12",
"KeyF13",
"KeyF14",
94 "KeyF15",
"KeyF16",
"KeyF17",
"KeyF18",
"KeyF19",
"KeyF20",
"KeyF21",
"KeyF22",
"KeyF23",
95 "KeyF24",
"KeyF25",
"KeyF26",
"KeyF27",
"KeyF28",
"KeyF29",
"KeyF30",
"KeyF31",
"KeyF32",
96 "KeyF33",
"KeyF34",
"KeyF35",
"KeyF36",
"KeyF37",
"KeyF38",
"KeyF39",
"KeyF40",
"KeyF41",
97 "KeyF42",
"KeyF43",
"KeyF44",
"KeyF45",
"KeyF46",
"KeyF47",
"KeyF48",
"KeyF49",
"KeyF50",
98 "KeyF51",
"KeyF52",
"KeyF53",
"KeyF54",
"KeyF55",
"KeyF56",
"KeyF57",
"KeyF58",
"KeyF59",
99 "KeyF60",
"KeyF61",
"KeyF62",
"KeyF63",
"ClrBol",
"ClearMargins",
"SetLeftMargin",
100 "SetRightMargin",
"LabelFormat",
"SetClock",
"DisplayClock",
"RemoveClock",
"CreateWindow",
101 "GotoWindow",
"Hangup",
"DialPhone",
"QuickDial",
"Tone",
"Pulse",
"FlashHook",
"FixedPause",
102 "WaitTone",
"User0",
"User1",
"User2",
"User3",
"User4",
"User5",
"User6",
"User7",
"User8",
103 "User9",
"OrigPair",
"OrigColors",
"InitializeColor",
"InitializePair",
"SetColorPair",
104 "SetForeground",
"SetBackground",
"ChangeCharPitch",
"ChangeLinePitch",
"ChangeResHorz",
105 "ChangeResVert",
"DefineChar",
"EnterDoublewideMode",
"EnterDraftQuality",
"EnterItalicsMode",
106 "EnterLeftwardMode",
"EnterMicroMode",
"EnterNearLetterQuality",
"EnterNormalQuality",
107 "EnterShadowMode",
"EnterSubscriptMode",
"EnterSuperscriptMode",
"EnterUpwardMode",
108 "ExitDoublewideMode",
"ExitItalicsMode",
"ExitLeftwardMode",
"ExitMicroMode",
"ExitShadowMode",
109 "ExitSubscriptMode",
"ExitSuperscriptMode",
"ExitUpwardMode",
"MicroColumnAddress",
"MicroDown",
110 "MicroLeft",
"MicroRight",
"MicroRowAddress",
"MicroUp",
"OrderOfPins",
"ParmDownMicro",
111 "ParmLeftMicro",
"ParmRightMicro",
"ParmUpMicro",
"SelectCharSet",
"SetBottomMargin",
112 "SetBottomMarginParm",
"SetLeftMarginParm",
"SetRightMarginParm",
"SetTopMargin",
113 "SetTopMarginParm",
"StartBitImage",
"StartCharSetDef",
"StopBitImage",
"StopCharSetDef",
114 "SubscriptCharacters",
"SuperscriptCharacters",
"TheseCauseCr",
"ZeroMotion",
"CharSetNames",
115 "KeyMouse",
"MouseInfo",
"ReqMousePos",
"GetMouse",
"SetAForeground",
"SetABackground",
116 "PkeyPlab",
"DeviceType",
"CodeSetInit",
"Set0DesSeq",
"Set1DesSeq",
"Set2DesSeq",
"Set3DesSeq",
117 "SetLrMargin",
"SetTbMargin",
"BitImageRepeat",
"BitImageNewline",
"BitImageCarriageReturn",
118 "ColorNames",
"DefineBitImageRegion",
"EndBitImageRegion",
"SetColorBand",
"SetPageLength",
119 "DisplayPcChar",
"EnterPcCharsetMode",
"ExitPcCharsetMode",
"EnterScancodeMode",
120 "ExitScancodeMode",
"PcTermOptions",
"ScancodeEscape",
"AltScancodeEsc",
121 "EnterHorizontalHlMode",
"EnterLeftHlMode",
"EnterLowHlMode",
"EnterRightHlMode",
122 "EnterTopHlMode",
"EnterVerticalHlMode",
"SetAAttributes",
"SetPglenInch",
"TermcapInit2",
123 "TermcapReset",
"LinefeedIfNotLf",
"BackspaceIfNotBs",
"OtherNonFunctionKeys",
"ArrowKeyMap",
124 "AcsUlcorner",
"AcsLlcorner",
"AcsUrcorner",
"AcsLrcorner",
"AcsLtee",
"AcsRtee",
"AcsBtee",
125 "AcsTtee",
"AcsHline",
"AcsVline",
"AcsPlus",
"MemoryLock",
"MemoryUnlock",
"BoxChars1" };
147 std::string filename (findTerminfo(term));
149 std::ifstream is (filename.c_str());
154 ex <<
": " << filename;
162 if (BoolVec::size_type(p) >= booleans_.size())
170 if (NumberVec::size_type(p) >= numbers_.size())
178 if (StringVec::size_type(p) >= strings_.size())
205 std::vector<senf::term::Terminfo::number_t> stack;
247 std::string
const prgstr (fmt_p);
249 bool bCondValue (
false);
252 for (std::string::const_iterator i (prgstr.begin()); i != prgstr.end(); ++i) {
257 int width = 0, base = 0;
259 case '%': result += *i;
break;
260 case 'i': ++arg1; ++arg2;
break;
261 case 'c': result += char(stack.pop());
break;
262 case 'x': base = 16;
continue;
263 case '0':
if (!base) base = 8;
264 case '1':
case '2':
case '3':
case '4':
265 case '5':
case '6':
case '7':
case '8':
266 case '9':
if (!base) base = 10;
267 width = width * base + (*i -
'0');
271 case '\'':
if (*(i - 1) ==
'%') {
272 if (*(i + 1) !=
'\\')
276 case '}': stack.push(width);
break;
278 case '+': stack.push(stack.pop() + stack.pop());
break;
279 case '-': stack.push(-stack.pop() + stack.pop());
break;
280 case '*': stack.push(stack.pop() * stack.pop());
break;
281 case '/': stack.push(stack.pop() / stack.popNonzero());
break;
282 case 'm': stack.push(stack.pop() % stack.popNonzero());
break;
283 case '|': stack.push(stack.pop() | stack.pop());
break;
284 case '&': stack.push(stack.pop() & stack.pop());
break;
285 case '^': stack.push(stack.pop() ^ stack.pop());
break;
286 case '>': stack.push(stack.pop() < stack.pop());
break;
287 case '<': stack.push(stack.pop() > stack.pop());
break;
288 case '=': stack.push(stack.pop() == stack.pop());
break;
289 case 'A': stack.push(stack.pop() && stack.pop());
break;
290 case 'O': stack.push(stack.pop() || stack.pop());
break;
291 case '!': stack.push(!stack.pop());
break;
292 case '~': stack.push(~stack.pop());
break;
293 case 't': bCondValue = stack.pop();
294 case 'e':
if ((bCondValue = !bCondValue))
295 --(i = prgstr.begin() + std::min (prgstr.find (
"%e", i-prgstr.begin()),
296 prgstr.find (
"%;", i-prgstr.begin())));
301 case '1': stack.push(arg1);
break;
302 case '2': stack.push(arg2);
break;
303 case '3': stack.push(arg3);
break;
304 case '4': stack.push(arg4);
break;
305 case '5': stack.push(arg5);
break;
306 case '6': stack.push(arg6);
break;
307 case '7': stack.push(arg7);
break;
308 case '8': stack.push(arg8);
break;
309 case '9': stack.push(arg9);
break;
314 const std::string::size_type iSize = result.size();
316 result += std::string::value_type(
'0' + (n % 10));
317 }
while ((n /= 10) || --width > 0);
318 reverse (result.begin() + iSize, result.end());
329 os <<
"Terminfo entry: " << name_ <<
"\n";
330 os <<
"Booleans: " << booleans_.size() <<
"\n";
331 os <<
"Numbers: " << numbers_.size() <<
"\n";
332 os <<
"Strings: " << strings_.size() <<
"\n";
333 os <<
"String pool size: " << stringPool_.size() <<
"\n";
338 BoolVec::const_iterator i (booleans_.begin());
339 BoolVec::const_iterator
const i_end (booleans_.end());
340 for (; i != i_end; ++i, ++n)
348 NumberVec::const_iterator i (numbers_.begin());
349 NumberVec::const_iterator
const i_end (numbers_.end());
350 for (; i != i_end; ++i, ++n)
359 StringVec::const_iterator i (strings_.begin());
360 StringVec::const_iterator
const i_end (strings_.end());
361 for (; i != i_end; ++i, ++n)
364 hexdump(*i, *i + strlen(*i), os, 32);
370 prefix_ std::string senf::term::Terminfo::findTerminfo(std::string
const &
name)
372 if (name.empty())
return "";
373 boost::filesystem::path subdir (name.substr(0,1)); subdir /= name;
374 boost::filesystem::path tientry;
377 char const * tivar (::getenv(
"TERMINFO"));
379 tientry = boost::filesystem::path(tivar) / subdir;
380 if (boost::filesystem::exists(tientry))
return tientry.string();
384 tientry = boost::filesystem::path(
"/etc/terminfo") / subdir;
385 if (boost::filesystem::exists(tientry))
return tientry.string();
387 tientry = boost::filesystem::path(
"/lib/terminfo") / subdir;
388 if (boost::filesystem::exists(tientry))
return tientry.string();
390 tientry = boost::filesystem::path(
"/usr/share/terminfo") / subdir;
391 if (boost::filesystem::exists(tientry))
return tientry.string();
398 boost::uint16_t
const TerminfoMagic = 0x011A;
400 struct TerminfoHeader {
401 boost::uint16_t magic;
402 boost::uint16_t namesSz;
403 boost::uint16_t nBooleans;
404 boost::uint16_t nNumbers;
405 boost::uint16_t nStrings;
406 boost::uint16_t stringPoolSz;
411 nBooleans =
le16toh(nBooleans);
414 stringPoolSz =
le16toh(stringPoolSz);
423 is.read(static_cast<char*>(static_cast<void*>(&h)),
sizeof(h));
426 "invalid magic number (") << h.magic <<
"!=" << TerminfoMagic <<
")";
428 name_.resize(h.namesSz);
429 is.read(&(name_[0]), name_.size());
431 if (name_.size() & 1)
434 std::string::size_type n (name_.find(
'\0'));
435 if (n != std::string::npos)
439 booleans_.resize(h.nBooleans);
440 for (BoolVec::iterator i (booleans_.begin()); i != booleans_.end(); ++i) {
442 is.read(&v,
sizeof(v));
446 if (booleans_.size() & 1)
449 numbers_.resize(h.nNumbers);
450 for (NumberVec::iterator i (numbers_.begin()); i != numbers_.end(); ++i) {
452 is.read(static_cast<char*>(static_cast<void*>(&v)),
sizeof(v));
457 typedef std::vector<number_t> OffsetVec;
459 offsets.resize (h.nStrings);
460 for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i) {
462 is.read(static_cast<char*>(static_cast<void*>(&v)),
sizeof(v));
467 stringPool_.resize(h.stringPoolSz);
468 is.read(&(stringPool_[0]), stringPool_.size());
471 strings_.resize(offsets.size());
472 StringVec::iterator j (strings_.begin());
473 for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i, ++j)
474 if (*i !=
NoValue && *i >= 0 &&
unsigned(*i) < stringPool_.size())
475 *j = &(stringPool_[0]) + *i;
484 "Esc",
"Backspace",
"Backtab",
"Begin",
"CATab",
"CTab",
"Cancel",
"Center",
"Clear",
485 "ClearToEOL",
"ClearToEOS",
"Close",
"Command",
"Copy",
"Create",
"Delete",
"DeleteLine",
486 "Down",
"DownLeft",
"DownRight",
"End",
"Enter",
"Exit",
"F0",
"F1",
"F2",
"F3",
"F4",
"F5",
487 "F6",
"F7",
"F8",
"F9",
"F10",
"F11",
"F12",
"F13",
"F14",
"F15",
"F16",
"F17",
"F18",
"F19",
488 "F20",
"F21",
"F22",
"F23",
"F24",
"F25",
"F26",
"F27",
"F28",
"F29",
"F30",
"F31",
"F32",
489 "F33",
"F34",
"F35",
"F36",
"F37",
"F38",
"F39",
"F40",
"F41",
"F42",
"F43",
"F44",
"F45",
490 "F46",
"F47",
"F48",
"F49",
"F50",
"F51",
"F52",
"F53",
"F54",
"F55",
"F56",
"F57",
"F58",
491 "F59",
"F60",
"F61",
"F62",
"F63",
"Find",
"Help",
"Home",
"Insert",
"InsertLine",
"Left",
492 "Mark",
"Message",
"Mouse",
"Move",
"Next",
"Open",
"Options",
"PageDown",
"PageUp",
"Previous",
493 "Print",
"Redo",
"Reference",
"Refresh",
"Replace",
"Restart",
"Resume",
"Right",
"Save",
494 "Select",
"ShiftBegin",
"ShiftCancel",
"ShiftCommand",
"ShiftCopy",
"ShiftCreate",
495 "ShiftDelete",
"ShiftDeleteLine",
"ShiftEnd",
"ShiftClearToEOL",
"ShiftExit",
"ShiftFind",
496 "ShiftHelp",
"ShiftHome",
"ShiftInsert",
"ShiftLeft",
"ShiftMessage",
"ShiftMove",
"ShiftNext",
497 "ShiftOptions",
"ShiftPrevious",
"ShiftPrint",
"ShiftRedo",
"ShiftReplace",
"ShiftResume",
498 "ShiftRight",
"ShiftSave",
"ShiftSuspend",
"ShiftTab",
"ShiftUndo",
"Suspend",
"Undo",
"Up",
499 "UpLeft",
"UpRight" };
571 for (
unsigned i (0); i <
sizeof(keyStrings)/
sizeof(keyStrings[0]); ++i) {
572 char const * key (ti.
getString(keyStrings[i]));
574 table_.insert(std::make_pair(key,
KeyCode(i+First)));
578 prefix_ std::pair<senf::term::KeyParser::keycode_t, std::string::size_type>
583 return std::make_pair(
KeyCode(0), 0);
593 Keytable::const_iterator i (table_.upper_bound(key));
594 if (i != table_.end() && i->first.substr(0, key.size()) == key)
595 return std::make_pair(Incomplete, key.size());
596 if (i == table_.begin())
597 return std::make_pair(
keycode_t(key[0]), 1);
599 if (key.substr(0, i->first.size()) == i->first)
600 return std::make_pair(i->second, i->first.size());
601 return std::make_pair(
keycode_t(key[0]), 1);
607 return "^" + std::string(1,
'@' + key);
609 return std::string(1,
char(key));
610 if (key >=
keycode_t(First) && key <
keycode_t(First +
sizeof(KeyNames) /
sizeof(KeyNames[0])))
611 return std::string(KeyNames[key-First]);
613 return "<" + boost::lexical_cast<std::string>(unsigned(key)) +
">";
620 for (Keytable::const_iterator i (table_.begin()); i != table_.end(); ++i) {
621 unsigned index (i->second - First);
622 if (index <
sizeof(KeyNames)/
sizeof(KeyNames[0])) {
623 os <<
" " << std::setw(32) << KeyNames[index] <<
": ";
624 hexdump(i->first.begin(), i->first.end(), os);
void hexdump(Iterator i, Iterator i_end, std::ostream &stream, unsigned block_size=16)
char const * string_t
String terminfo property type.
KeyCode
Special keyboard key codes.
void load(std::string const &term)
Load terminfo entry term.
std::pair< keycode_t, size_type > lookup(std::string const &key) const
Lookup up string key.
wchar_t keycode_t
Key code data type.
boost::int16_t number_t
Numeric terminfo property type.
number_t getNumber(properties::Numeric p) const
Get numeric property value.
static char const *const KeyNames[]
Special key code names.
bool hasProperty(properties::Boolean p) const
true, if boolean property p exists
static std::string describe(keycode_t key)
Return descriptive, printable key name.
bool getFlag(properties::Boolean p) const
Get boolean property value.
Numeric
Numeric terminfo properties.
static char const *const NumericNames[]
Numeric property names.
InvalidTerminfoException(std::string const &term="")
Invalid, incomplete or non-existent terminfo entry exception.
string_t getString(properties::String p) const
Get string property value.
void dump(std::ostream &os) const
Dump keymap for debug purposes.
void dump(std::ostream &os) const
Dump a description of the terminfo entry.
String
String terminfo properties.
void append(std::string text)
Boolean
Boolean terminfo properties.
static char const *const StringNames[]
String property names.
unspecified_keyword_type name
std::string formatString(properties::String p, number_t arg1=NoValue, number_t arg2=NoValue, number_t arg3=NoValue, number_t arg4=NoValue, number_t arg5=NoValue, number_t arg6=NoValue, number_t arg7=NoValue, number_t arg8=NoValue, number_t arg9=NoValue) const
Format string property value.
void load(Terminfo const &ti)
Load keymap information from ti.
static char const *const BooleanNames[]
Boolean property names.