4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief Terminfo non-inline non-template implementation */
26 #include "Terminfo.hh"
27 //#include "Terminfo.ih"
32 #include <boost/filesystem/operations.hpp>
33 #include <senf/config.hh>
34 #include <senf/Utils/hexdump.hh>
38 //#include "Terminfo.mpp"
40 //-/////////////////////////////////////////////////////////////////////////////////////////////////
42 char const * const senf::term::Terminfo::properties::BooleanNames [] = {
43 "AutoLeftMargin", "AutoRightMargin", "NoEscCtlc", "CeolStandoutGlitch", "EatNewlineGlitch",
44 "EraseOverstrike", "GenericType", "HardCopy", "HasMetaKey", "HasStatusLine", "InsertNullGlitch",
45 "MemoryAbove", "MemoryBelow", "MoveInsertMode", "MoveStandoutMode", "OverStrike",
46 "StatusLineEscOk", "DestTabsMagicSmso", "TildeGlitch", "TransparentUnderline", "XonXoff",
47 "NeedsXonXoff", "PrtrSilent", "HardCursor", "NonRevRmcup", "NoPadChar", "NonDestScrollRegion",
48 "CanChange", "BackColorErase", "HueLightnessSaturation", "ColAddrGlitch", "CrCancelsMicroMode",
49 "HasPrintWheel", "RowAddrGlitch", "SemiAutoRightMargin", "CpiChangesRes", "LpiChangesRes",
50 "BackspacesWithBs", "CrtNoScrolling", "NoCorrectlyWorkingCr", "GnuHasMetaKey",
51 "LinefeedIsNewline", "HasHardwareTabs", "ReturnDoesClrEol" };
53 char const * const senf::term::Terminfo::properties::NumericNames[] = {
54 "Columns", "InitTabs", "Lines", "LinesOfMemory", "MagicCookieGlitch", "PaddingBaudRate",
55 "VirtualTerminal", "WidthStatusLine", "NumLabels", "LabelHeight", "LabelWidth", "MaxAttributes",
56 "MaximumWindows", "MaxColors", "MaxPairs", "NoColorVideo", "BufferCapacity", "DotVertSpacing",
57 "DotHorzSpacing", "MaxMicroAddress", "MaxMicroJump", "MicroColSize", "MicroLineSize",
58 "NumberOfPins", "OutputResChar", "OutputResLine", "OutputResHorzInch", "OutputResVertInch",
59 "PrintRate", "WideCharSize", "Buttons", "BitImageEntwining", "BitImageType",
60 "MagicCookieGlitchUl", "CarriageReturnDelay", "NewLineDelay", "BackspaceDelay",
61 "HorizontalTabDelay", "NumberOfFunctionKeys" };
63 char const * const senf::term::Terminfo::properties::StringNames[] = {
64 "BackTab", "Bell", "CarriageReturn", "ChangeScrollRegion", "ClearAllTabs", "ClearScreen",
65 "ClrEol", "ClrEos", "ColumnAddress", "CommandCharacter", "CursorAddress", "CursorDown",
66 "CursorHome", "CursorInvisible", "CursorLeft", "CursorMemAddress", "CursorNormal",
67 "CursorRight", "CursorToLl", "CursorUp", "CursorVisible", "DeleteCharacter", "DeleteLine",
68 "DisStatusLine", "DownHalfLine", "EnterAltCharsetMode", "EnterBlinkMode", "EnterBoldMode",
69 "EnterCaMode", "EnterDeleteMode", "EnterDimMode", "EnterInsertMode", "EnterSecureMode",
70 "EnterProtectedMode", "EnterReverseMode", "EnterStandoutMode", "EnterUnderlineMode",
71 "EraseChars", "ExitAltCharsetMode", "ExitAttributeMode", "ExitCaMode", "ExitDeleteMode",
72 "ExitInsertMode", "ExitStandoutMode", "ExitUnderlineMode", "FlashScreen", "FormFeed",
73 "FromStatusLine", "Init1string", "Init2string", "Init3string", "InitFile", "InsertCharacter",
74 "InsertLine", "InsertPadding", "KeyBackspace", "KeyCatab", "KeyClear", "KeyCtab", "KeyDc",
75 "KeyDl", "KeyDown", "KeyEic", "KeyEol", "KeyEos", "KeyF0", "KeyF1", "KeyF10", "KeyF2", "KeyF3",
76 "KeyF4", "KeyF5", "KeyF6", "KeyF7", "KeyF8", "KeyF9", "KeyHome", "KeyIc", "KeyIl", "KeyLeft",
77 "KeyLl", "KeyNpage", "KeyPpage", "KeyRight", "KeySf", "KeySr", "KeyStab", "KeyUp",
78 "KeypadLocal", "KeypadXmit", "LabF0", "LabF1", "LabF10", "LabF2", "LabF3", "LabF4", "LabF5",
79 "LabF6", "LabF7", "LabF8", "LabF9", "MetaOff", "MetaOn", "Newline", "PadChar", "ParmDch",
80 "ParmDeleteLine", "ParmDownCursor", "ParmIch", "ParmIndex", "ParmInsertLine", "ParmLeftCursor",
81 "ParmRightCursor", "ParmRindex", "ParmUpCursor", "PkeyKey", "PkeyLocal", "PkeyXmit",
82 "PrintScreen", "PrtrOff", "PrtrOn", "RepeatChar", "Reset1string", "Reset2string",
83 "Reset3string", "ResetFile", "RestoreCursor", "RowAddress", "SaveCursor", "ScrollForward",
84 "ScrollReverse", "SetAttributes", "SetTab", "SetWindow", "Tab", "ToStatusLine", "UnderlineChar",
85 "UpHalfLine", "InitProg", "KeyA1", "KeyA3", "KeyB2", "KeyC1", "KeyC3", "PrtrNon", "CharPadding",
86 "AcsChars", "PlabNorm", "KeyBtab", "EnterXonMode", "ExitXonMode", "EnterAmMode", "ExitAmMode",
87 "XonCharacter", "XoffCharacter", "EnaAcs", "LabelOn", "LabelOff", "KeyBeg", "KeyCancel",
88 "KeyClose", "KeyCommand", "KeyCopy", "KeyCreate", "KeyEnd", "KeyEnter", "KeyExit", "KeyFind",
89 "KeyHelp", "KeyMark", "KeyMessage", "KeyMove", "KeyNext", "KeyOpen", "KeyOptions",
90 "KeyPrevious", "KeyPrint", "KeyRedo", "KeyReference", "KeyRefresh", "KeyReplace", "KeyRestart",
91 "KeyResume", "KeySave", "KeySuspend", "KeyUndo", "KeySbeg", "KeyScancel", "KeyScommand",
92 "KeyScopy", "KeyScreate", "KeySdc", "KeySdl", "KeySelect", "KeySend", "KeySeol", "KeySexit",
93 "KeySfind", "KeyShelp", "KeyShome", "KeySic", "KeySleft", "KeySmessage", "KeySmove", "KeySnext",
94 "KeySoptions", "KeySprevious", "KeySprint", "KeySredo", "KeySreplace", "KeySright", "KeySrsume",
95 "KeySsave", "KeySsuspend", "KeySundo", "ReqForInput", "KeyF11", "KeyF12", "KeyF13", "KeyF14",
96 "KeyF15", "KeyF16", "KeyF17", "KeyF18", "KeyF19", "KeyF20", "KeyF21", "KeyF22", "KeyF23",
97 "KeyF24", "KeyF25", "KeyF26", "KeyF27", "KeyF28", "KeyF29", "KeyF30", "KeyF31", "KeyF32",
98 "KeyF33", "KeyF34", "KeyF35", "KeyF36", "KeyF37", "KeyF38", "KeyF39", "KeyF40", "KeyF41",
99 "KeyF42", "KeyF43", "KeyF44", "KeyF45", "KeyF46", "KeyF47", "KeyF48", "KeyF49", "KeyF50",
100 "KeyF51", "KeyF52", "KeyF53", "KeyF54", "KeyF55", "KeyF56", "KeyF57", "KeyF58", "KeyF59",
101 "KeyF60", "KeyF61", "KeyF62", "KeyF63", "ClrBol", "ClearMargins", "SetLeftMargin",
102 "SetRightMargin", "LabelFormat", "SetClock", "DisplayClock", "RemoveClock", "CreateWindow",
103 "GotoWindow", "Hangup", "DialPhone", "QuickDial", "Tone", "Pulse", "FlashHook", "FixedPause",
104 "WaitTone", "User0", "User1", "User2", "User3", "User4", "User5", "User6", "User7", "User8",
105 "User9", "OrigPair", "OrigColors", "InitializeColor", "InitializePair", "SetColorPair",
106 "SetForeground", "SetBackground", "ChangeCharPitch", "ChangeLinePitch", "ChangeResHorz",
107 "ChangeResVert", "DefineChar", "EnterDoublewideMode", "EnterDraftQuality", "EnterItalicsMode",
108 "EnterLeftwardMode", "EnterMicroMode", "EnterNearLetterQuality", "EnterNormalQuality",
109 "EnterShadowMode", "EnterSubscriptMode", "EnterSuperscriptMode", "EnterUpwardMode",
110 "ExitDoublewideMode", "ExitItalicsMode", "ExitLeftwardMode", "ExitMicroMode", "ExitShadowMode",
111 "ExitSubscriptMode", "ExitSuperscriptMode", "ExitUpwardMode", "MicroColumnAddress", "MicroDown",
112 "MicroLeft", "MicroRight", "MicroRowAddress", "MicroUp", "OrderOfPins", "ParmDownMicro",
113 "ParmLeftMicro", "ParmRightMicro", "ParmUpMicro", "SelectCharSet", "SetBottomMargin",
114 "SetBottomMarginParm", "SetLeftMarginParm", "SetRightMarginParm", "SetTopMargin",
115 "SetTopMarginParm", "StartBitImage", "StartCharSetDef", "StopBitImage", "StopCharSetDef",
116 "SubscriptCharacters", "SuperscriptCharacters", "TheseCauseCr", "ZeroMotion", "CharSetNames",
117 "KeyMouse", "MouseInfo", "ReqMousePos", "GetMouse", "SetAForeground", "SetABackground",
118 "PkeyPlab", "DeviceType", "CodeSetInit", "Set0DesSeq", "Set1DesSeq", "Set2DesSeq", "Set3DesSeq",
119 "SetLrMargin", "SetTbMargin", "BitImageRepeat", "BitImageNewline", "BitImageCarriageReturn",
120 "ColorNames", "DefineBitImageRegion", "EndBitImageRegion", "SetColorBand", "SetPageLength",
121 "DisplayPcChar", "EnterPcCharsetMode", "ExitPcCharsetMode", "EnterScancodeMode",
122 "ExitScancodeMode", "PcTermOptions", "ScancodeEscape", "AltScancodeEsc",
123 "EnterHorizontalHlMode", "EnterLeftHlMode", "EnterLowHlMode", "EnterRightHlMode",
124 "EnterTopHlMode", "EnterVerticalHlMode", "SetAAttributes", "SetPglenInch", "TermcapInit2",
125 "TermcapReset", "LinefeedIfNotLf", "BackspaceIfNotBs", "OtherNonFunctionKeys", "ArrowKeyMap",
126 "AcsUlcorner", "AcsLlcorner", "AcsUrcorner", "AcsLrcorner", "AcsLtee", "AcsRtee", "AcsBtee",
127 "AcsTtee", "AcsHline", "AcsVline", "AcsPlus", "MemoryLock", "MemoryUnlock", "BoxChars1" };
129 //-/////////////////////////////////////////////////////////////////////////////////////////////////
130 // senf::term::Terminfo
132 prefix_ senf::term::Terminfo::Terminfo()
135 prefix_ senf::term::Terminfo::Terminfo(std::string const & term)
140 prefix_ void senf::term::Terminfo::load(std::string const & term)
142 std::string filename (findTerminfo(term));
143 if (filename.empty()) throw InvalidTerminfoException();
144 std::ifstream is (filename.c_str());
145 if (!is) throw InvalidTerminfoException();
149 prefix_ bool senf::term::Terminfo::getFlag(properties::Boolean p)
152 if (BoolVec::size_type(p) >= booleans_.size())
157 prefix_ senf::term::Terminfo::number_t senf::term::Terminfo::getNumber(properties::Numeric p)
160 if (NumberVec::size_type(p) >= numbers_.size())
165 prefix_ senf::term::Terminfo::string_t senf::term::Terminfo::getString(properties::String p)
168 if (StringVec::size_type(p) >= strings_.size())
173 prefix_ bool senf::term::Terminfo::hasProperty(properties::Boolean p)
179 prefix_ bool senf::term::Terminfo::hasProperty(properties::Numeric p)
182 return getNumber(p) != NoValue;
185 prefix_ bool senf::term::Terminfo::hasProperty(properties::String p)
188 return getString(p) != 0;
195 std::vector<senf::term::Terminfo::number_t> stack;
197 void push(senf::term::Terminfo::number_t v)
202 senf::term::Terminfo::number_t pop()
207 senf::term::Terminfo::number_t v (stack.back());
213 senf::term::Terminfo::number_t popNonzero()
215 senf::term::Terminfo::number_t v (pop());
222 // The following code is taken directly from utio. As far as I understand it is buggy
223 // and/or only partially implements the string format language. But seems to be enough for
224 // all the common terminal types ...
225 prefix_ std::string senf::term::Terminfo::formatString(properties::String p,
226 number_t arg1, number_t arg2,
227 number_t arg3, number_t arg4,
228 number_t arg5, number_t arg6,
229 number_t arg7, number_t arg8,
233 char const * fmt_p (getString(p));
237 std::string const prgstr (fmt_p);
239 bool bCondValue (false);
242 for (std::string::const_iterator i (prgstr.begin()); i != prgstr.end(); ++i) {
247 int width = 0, base = 0;
249 case '%': result += *i; break;
250 case 'i': ++arg1; ++arg2; break;
251 case 'c': result += char(stack.pop()); break;
252 case 'x': base = 16; continue;
253 case '0': if (!base) base = 8;
254 case '1': case '2': case '3': case '4':
255 case '5': case '6': case '7': case '8':
256 case '9': if (!base) base = 10;
257 width = width * base + (*i - '0');
261 case '\'': if (*(i - 1) == '%') {
262 if (*(i + 1) != '\\')
266 case '}': stack.push(width); break;
267 // Binary operands are in infix (reversed) order
268 case '+': stack.push(stack.pop() + stack.pop()); break;
269 case '-': stack.push(-stack.pop() + stack.pop()); break;
270 case '*': stack.push(stack.pop() * stack.pop()); break;
271 case '/': stack.push(stack.pop() / stack.popNonzero()); break;
272 case 'm': stack.push(stack.pop() % stack.popNonzero()); break;
273 case '|': stack.push(stack.pop() | stack.pop()); break;
274 case '&': stack.push(stack.pop() & stack.pop()); break;
275 case '^': stack.push(stack.pop() ^ stack.pop()); break;
276 case '>': stack.push(stack.pop() < stack.pop()); break;
277 case '<': stack.push(stack.pop() > stack.pop()); break;
278 case '=': stack.push(stack.pop() == stack.pop()); break;
279 case 'A': stack.push(stack.pop() && stack.pop()); break;
280 case 'O': stack.push(stack.pop() || stack.pop()); break;
281 case '!': stack.push(!stack.pop()); break;
282 case '~': stack.push(~stack.pop()); break;
283 case 't': bCondValue = stack.pop();
284 case 'e': if ((bCondValue = !bCondValue)) // this also supports elsif
285 --(i = prgstr.begin() + std::min (prgstr.find ("%e", i-prgstr.begin()),
286 prgstr.find ("%;", i-prgstr.begin())));
291 case '1': stack.push(arg1); break;
292 case '2': stack.push(arg2); break;
293 case '3': stack.push(arg3); break;
294 case '4': stack.push(arg4); break;
295 case '5': stack.push(arg5); break;
296 case '6': stack.push(arg6); break;
297 case '7': stack.push(arg7); break;
298 case '8': stack.push(arg8); break;
299 case '9': stack.push(arg9); break;
303 number_t n = stack.pop();
304 const std::string::size_type iSize = result.size();
306 result += std::string::value_type('0' + (n % 10));
307 } while ((n /= 10) || --width > 0);
308 reverse (result.begin() + iSize, result.end());
316 prefix_ void senf::term::Terminfo::dump(std::ostream & os)
319 os << "Terminfo entry: " << name_ << "\n";
320 os << "Booleans: " << booleans_.size() << "\n";
321 os << "Numbers: " << numbers_.size() << "\n";
322 os << "Strings: " << strings_.size() << "\n";
323 os << "String pool size: " << stringPool_.size() << "\n";
328 BoolVec::const_iterator i (booleans_.begin());
329 BoolVec::const_iterator const i_end (booleans_.end());
330 for (; i != i_end; ++i, ++n)
331 if (*i && n < sizeof(properties::BooleanNames)/sizeof(properties::BooleanNames[0]))
332 os << " " << properties::BooleanNames[n] << "\n";
338 NumberVec::const_iterator i (numbers_.begin());
339 NumberVec::const_iterator const i_end (numbers_.end());
340 for (; i != i_end; ++i, ++n)
342 && n < sizeof(properties::NumericNames)/sizeof(properties::NumericNames[0]))
343 os << " " << properties::NumericNames[n] << " = " << *i << "\n";
349 StringVec::const_iterator i (strings_.begin());
350 StringVec::const_iterator const i_end (strings_.end());
351 for (; i != i_end; ++i, ++n)
352 if (*i && n < sizeof(properties::StringNames)/sizeof(properties::StringNames[0])) {
353 os << " " << std::setw(32) << properties::StringNames[n] << " = ";
354 hexdump(*i, *i + strlen(*i), os, 32);
360 prefix_ std::string senf::term::Terminfo::findTerminfo(std::string const & name)
362 if (name.empty()) return "";
363 boost::filesystem::path subdir (name.substr(0,1)); subdir /= name;
364 boost::filesystem::path tientry;
367 char const * tivar (::getenv("TERMINFO"));
369 tientry = boost::filesystem::path(tivar) / subdir;
370 if (boost::filesystem::exists(tientry)) return tientry.native_file_string();
374 tientry = boost::filesystem::path("/etc/terminfo") / subdir;
375 if (boost::filesystem::exists(tientry)) return tientry.native_file_string();
377 tientry = boost::filesystem::path("/lib/terminfo") / subdir;
378 if (boost::filesystem::exists(tientry)) return tientry.native_file_string();
380 tientry = boost::filesystem::path("/usr/share/terminfo") / subdir;
381 if (boost::filesystem::exists(tientry)) return tientry.native_file_string();
388 boost::uint16_t const TerminfoMagic = 0x011A;
390 struct TerminfoHeader {
391 boost::uint16_t magic;
392 boost::uint16_t namesSz;
393 boost::uint16_t nBooleans;
394 boost::uint16_t nNumbers;
395 boost::uint16_t nStrings;
396 boost::uint16_t stringPoolSz;
401 prefix_ void senf::term::Terminfo::load(std::istream & is)
404 is.read(static_cast<char*>(static_cast<void*>(&h)), sizeof(h));
405 if (!is || h.magic != TerminfoMagic) throw InvalidTerminfoException();
407 name_.resize(h.namesSz);
408 is.read(&(name_[0]), name_.size());
409 if (!is) throw InvalidTerminfoException();
410 if (name_.size() & 1)
413 std::string::size_type n (name_.find('\0'));
414 if (n != std::string::npos)
418 booleans_.resize(h.nBooleans);
419 for (BoolVec::iterator i (booleans_.begin()); i != booleans_.end(); ++i) {
421 is.read(&v, sizeof(v));
422 if (!is) throw InvalidTerminfoException();
425 if (booleans_.size() & 1)
428 numbers_.resize(h.nNumbers);
429 for (NumberVec::iterator i (numbers_.begin()); i != numbers_.end(); ++i) {
431 is.read(static_cast<char*>(static_cast<void*>(&v)), sizeof(v));
432 if (!is) throw InvalidTerminfoException();
436 typedef std::vector<number_t> OffsetVec;
438 offsets.resize (h.nStrings);
439 for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i) {
441 is.read(static_cast<char*>(static_cast<void*>(&v)), sizeof(v));
442 if (!is) throw InvalidTerminfoException();
446 stringPool_.resize(h.stringPoolSz);
447 is.read(&(stringPool_[0]), stringPool_.size());
448 if (!is) throw InvalidTerminfoException();
450 strings_.resize(offsets.size());
451 StringVec::iterator j (strings_.begin());
452 for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i, ++j)
453 if (*i != NoValue && *i >= 0 && unsigned(*i) < stringPool_.size())
454 *j = &(stringPool_[0]) + *i;
459 //-/////////////////////////////////////////////////////////////////////////////////////////////////
460 // senf::term::KeyParser
462 char const * const senf::term::KeyParser::KeyNames[] = {
463 "Esc", "Backspace", "Backtab", "Begin", "CATab", "CTab", "Cancel", "Center", "Clear",
464 "ClearToEOL", "ClearToEOS", "Close", "Command", "Copy", "Create", "Delete", "DeleteLine",
465 "Down", "DownLeft", "DownRight", "End", "Enter", "Exit", "F0", "F1", "F2", "F3", "F4", "F5",
466 "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19",
467 "F20", "F21", "F22", "F23", "F24", "F25", "F26", "F27", "F28", "F29", "F30", "F31", "F32",
468 "F33", "F34", "F35", "F36", "F37", "F38", "F39", "F40", "F41", "F42", "F43", "F44", "F45",
469 "F46", "F47", "F48", "F49", "F50", "F51", "F52", "F53", "F54", "F55", "F56", "F57", "F58",
470 "F59", "F60", "F61", "F62", "F63", "Find", "Help", "Home", "Insert", "InsertLine", "Left",
471 "Mark", "Message", "Mouse", "Move", "Next", "Open", "Options", "PageDown", "PageUp", "Previous",
472 "Print", "Redo", "Reference", "Refresh", "Replace", "Restart", "Resume", "Right", "Save",
473 "Select", "ShiftBegin", "ShiftCancel", "ShiftCommand", "ShiftCopy", "ShiftCreate",
474 "ShiftDelete", "ShiftDeleteLine", "ShiftEnd", "ShiftClearToEOL", "ShiftExit", "ShiftFind",
475 "ShiftHelp", "ShiftHome", "ShiftInsert", "ShiftLeft", "ShiftMessage", "ShiftMove", "ShiftNext",
476 "ShiftOptions", "ShiftPrevious", "ShiftPrint", "ShiftRedo", "ShiftReplace", "ShiftResume",
477 "ShiftRight", "ShiftSave", "ShiftSuspend", "ShiftTab", "ShiftUndo", "Suspend", "Undo", "Up",
478 "UpLeft", "UpRight" };
480 prefix_ senf::term::KeyParser::KeyParser()
483 prefix_ senf::term::KeyParser::KeyParser(Terminfo const & ti)
488 prefix_ void senf::term::KeyParser::load(Terminfo const & ti)
490 static Terminfo::properties::String keyStrings [] = {
491 Terminfo::properties::KeyCommand, Terminfo::properties::KeyBackspace,
492 Terminfo::properties::KeyBtab, Terminfo::properties::KeyBeg, Terminfo::properties::KeyCatab,
493 Terminfo::properties::KeyCtab, Terminfo::properties::KeyCancel, Terminfo::properties::KeyB2,
494 Terminfo::properties::KeyClear, Terminfo::properties::KeyEol, Terminfo::properties::KeyEos,
495 Terminfo::properties::KeyClose, Terminfo::properties::KeyCommand,
496 Terminfo::properties::KeyCopy, Terminfo::properties::KeyCreate, Terminfo::properties::KeyDc,
497 Terminfo::properties::KeyDl, Terminfo::properties::KeyDown, Terminfo::properties::KeyC1,
498 Terminfo::properties::KeyC3, Terminfo::properties::KeyEnd, Terminfo::properties::KeyEnter,
499 Terminfo::properties::KeyExit, Terminfo::properties::KeyF0, Terminfo::properties::KeyF1,
500 Terminfo::properties::KeyF2, Terminfo::properties::KeyF3, Terminfo::properties::KeyF4,
501 Terminfo::properties::KeyF5, Terminfo::properties::KeyF6, Terminfo::properties::KeyF7,
502 Terminfo::properties::KeyF8, Terminfo::properties::KeyF9, Terminfo::properties::KeyF10,
503 Terminfo::properties::KeyF11, Terminfo::properties::KeyF12, Terminfo::properties::KeyF13,
504 Terminfo::properties::KeyF14, Terminfo::properties::KeyF15, Terminfo::properties::KeyF16,
505 Terminfo::properties::KeyF17, Terminfo::properties::KeyF18, Terminfo::properties::KeyF19,
506 Terminfo::properties::KeyF20, Terminfo::properties::KeyF21, Terminfo::properties::KeyF22,
507 Terminfo::properties::KeyF23, Terminfo::properties::KeyF24, Terminfo::properties::KeyF25,
508 Terminfo::properties::KeyF26, Terminfo::properties::KeyF27, Terminfo::properties::KeyF28,
509 Terminfo::properties::KeyF29, Terminfo::properties::KeyF30, Terminfo::properties::KeyF31,
510 Terminfo::properties::KeyF32, Terminfo::properties::KeyF33, Terminfo::properties::KeyF34,
511 Terminfo::properties::KeyF35, Terminfo::properties::KeyF36, Terminfo::properties::KeyF37,
512 Terminfo::properties::KeyF38, Terminfo::properties::KeyF39, Terminfo::properties::KeyF40,
513 Terminfo::properties::KeyF41, Terminfo::properties::KeyF42, Terminfo::properties::KeyF43,
514 Terminfo::properties::KeyF44, Terminfo::properties::KeyF45, Terminfo::properties::KeyF46,
515 Terminfo::properties::KeyF47, Terminfo::properties::KeyF48, Terminfo::properties::KeyF49,
516 Terminfo::properties::KeyF50, Terminfo::properties::KeyF51, Terminfo::properties::KeyF52,
517 Terminfo::properties::KeyF53, Terminfo::properties::KeyF54, Terminfo::properties::KeyF55,
518 Terminfo::properties::KeyF56, Terminfo::properties::KeyF57, Terminfo::properties::KeyF58,
519 Terminfo::properties::KeyF59, Terminfo::properties::KeyF60, Terminfo::properties::KeyF61,
520 Terminfo::properties::KeyF62, Terminfo::properties::KeyF63, Terminfo::properties::KeyFind,
521 Terminfo::properties::KeyHelp, Terminfo::properties::KeyHome, Terminfo::properties::KeyIc,
522 Terminfo::properties::KeyIl, Terminfo::properties::KeyLeft, Terminfo::properties::KeyMark,
523 Terminfo::properties::KeyMessage, Terminfo::properties::KeyMouse,
524 Terminfo::properties::KeyMove, Terminfo::properties::KeyNext, Terminfo::properties::KeyOpen,
525 Terminfo::properties::KeyOptions, Terminfo::properties::KeyNpage,
526 Terminfo::properties::KeyPpage, Terminfo::properties::KeyPrevious,
527 Terminfo::properties::KeyPrint, Terminfo::properties::KeyRedo,
528 Terminfo::properties::KeyReference, Terminfo::properties::KeyRefresh,
529 Terminfo::properties::KeyReplace, Terminfo::properties::KeyRestart,
530 Terminfo::properties::KeyResume, Terminfo::properties::KeyRight,
531 Terminfo::properties::KeySave, Terminfo::properties::KeySelect,
532 Terminfo::properties::KeySbeg, Terminfo::properties::KeyScancel,
533 Terminfo::properties::KeyScommand, Terminfo::properties::KeyScopy,
534 Terminfo::properties::KeyScreate, Terminfo::properties::KeySdc,
535 Terminfo::properties::KeySdl, Terminfo::properties::KeySend, Terminfo::properties::KeySeol,
536 Terminfo::properties::KeySexit, Terminfo::properties::KeySfind,
537 Terminfo::properties::KeyShelp, Terminfo::properties::KeyShome,
538 Terminfo::properties::KeySic, Terminfo::properties::KeySleft,
539 Terminfo::properties::KeySmessage, Terminfo::properties::KeySmove,
540 Terminfo::properties::KeySnext, Terminfo::properties::KeySoptions,
541 Terminfo::properties::KeySprevious, Terminfo::properties::KeySprint,
542 Terminfo::properties::KeySredo, Terminfo::properties::KeySreplace,
543 Terminfo::properties::KeySrsume, Terminfo::properties::KeySright,
544 Terminfo::properties::KeySsave, Terminfo::properties::KeySsuspend,
545 Terminfo::properties::KeyStab, Terminfo::properties::KeySundo,
546 Terminfo::properties::KeySuspend, Terminfo::properties::KeyUndo,
547 Terminfo::properties::KeyUp, Terminfo::properties::KeyA1, Terminfo::properties::KeyA3 };
550 for (unsigned i (0); i < sizeof(keyStrings)/sizeof(keyStrings[0]); ++i) {
551 char const * key (ti.getString(keyStrings[i]));
553 table_.insert(std::make_pair(key, KeyCode(i+First)));
557 prefix_ std::pair<senf::term::KeyParser::keycode_t, std::string::size_type>
558 senf::term::KeyParser::lookup(std::string const & key)
562 return std::make_pair(KeyCode(0), 0);
564 // There are several cases:
565 // a) 'key' is an incomplete key sequence. In this case, 'key' will precede all completions in
566 // the key table. The first possible completion is found by 'upper_bound'
567 // b) 'key' is a complete key sequence. This is the key sequence *preceding* the 'upper_bound'
568 // c) 'key' is a complete key sequence with additional trailing characters. In this case, 'key'
569 // will follow the correct entry in the key table. Again, the correct key sequence is
570 // the one preceding the 'upper_bound'
572 Keytable::const_iterator i (table_.upper_bound(key));
573 if (i != table_.end() && i->first.substr(0, key.size()) == key)
574 return std::make_pair(Incomplete, key.size());
575 if (i == table_.begin())
576 return std::make_pair(keycode_t(key[0]), 1);
578 if (key.substr(0, i->first.size()) == i->first)
579 return std::make_pair(i->second, i->first.size());
580 return std::make_pair(keycode_t(key[0]), 1);
583 prefix_ std::string senf::term::KeyParser::describe(keycode_t key)
585 if (key < keycode_t(' '))
586 return "^" + std::string(1, '@' + key);
588 return std::string(1, char(key));
589 if (key >= keycode_t(First) && key < keycode_t(First + sizeof(KeyNames) / sizeof(KeyNames[0])))
590 return std::string(KeyNames[key-First]);
592 return "<" + boost::lexical_cast<std::string>(unsigned(key)) + ">";
595 prefix_ void senf::term::KeyParser::dump(std::ostream & os)
599 for (Keytable::const_iterator i (table_.begin()); i != table_.end(); ++i) {
600 unsigned index (i->second - First);
601 if (index < sizeof(KeyNames)/sizeof(KeyNames[0])) {
602 std::cout << " " << std::setw(32) << KeyNames[index] << ": ";
603 hexdump(i->first.begin(), i->first.end(), os);
608 //-/////////////////////////////////////////////////////////////////////////////////////////////////
610 //#include "Terminfo.mpp"
616 // comment-column: 40
617 // c-file-style: "senf"
618 // indent-tabs-mode: nil
619 // ispell-local-dictionary: "american"
620 // compile-command: "scons -u test"