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 ///////////////////////////////cc.p////////////////////////////////////////
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 std::ifstream is (filename.c_str());
145 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 boost::filesystem::path subdir (name.substr(0,1)); subdir /= name;
363 boost::filesystem::path tientry, tipath;
366 char const * tivar (::getenv("TERMINFO"));
369 tientry = tipath / subdir;
370 if (boost::filesystem::exists(tientry)) return tientry.native_file_string();
374 tipath = "/etc/terminfo";
375 tientry = tipath / subdir;
376 if (boost::filesystem::exists(tientry)) return tientry.native_file_string();
378 tipath = "/lib/terminfo";
379 tientry = tipath / subdir;
380 if (boost::filesystem::exists(tientry)) return tientry.native_file_string();
382 tipath = "/usr/share/terminfo";
383 tientry = tipath / subdir;
384 if (boost::filesystem::exists(tientry)) return tientry.native_file_string();
391 boost::uint16_t const TerminfoMagic = 0x011A;
393 struct TerminfoHeader {
394 boost::uint16_t magic;
395 boost::uint16_t namesSz;
396 boost::uint16_t nBooleans;
397 boost::uint16_t nNumbers;
398 boost::uint16_t nStrings;
399 boost::uint16_t stringPoolSz;
404 prefix_ void senf::term::Terminfo::load(std::istream & is)
407 is.read(static_cast<char*>(static_cast<void*>(&h)), sizeof(h));
408 if (h.magic != TerminfoMagic)
409 throw InvalidTerminfoException();
411 name_.resize(h.namesSz);
412 is.read(&(name_[0]), name_.size());
414 std::string::size_type n (name_.find('\0'));
415 if (n != std::string::npos)
419 booleans_.resize(h.nBooleans);
420 for (BoolVec::iterator i (booleans_.begin()); i != booleans_.end(); ++i) {
422 is.read(&v, sizeof(v));
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));
435 typedef std::vector<number_t> OffsetVec;
437 offsets.resize (h.nStrings);
438 for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i) {
440 is.read(static_cast<char*>(static_cast<void*>(&v)), sizeof(v));
444 stringPool_.resize(h.stringPoolSz);
445 is.read(&(stringPool_[0]), stringPool_.size());
447 strings_.resize(offsets.size());
448 StringVec::iterator j (strings_.begin());
449 for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i, ++j)
451 *j = &(stringPool_[0]) + *i;
454 ///////////////////////////////////////////////////////////////////////////
455 // senf::term::KeyParser
457 char const * const senf::term::KeyParser::KeyNames[] = {
458 "Esc", "Backspace", "Backtab", "Begin", "CATab", "CTab", "Cancel", "Center", "Clear",
459 "ClearToEOL", "ClearToEOS", "Close", "Command", "Copy", "Create", "Delete", "DeleteLine",
460 "Down", "DownLeft", "DownRight", "End", "Enter", "Exit", "F0", "F1", "F2", "F3", "F4", "F5",
461 "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19",
462 "F20", "F21", "F22", "F23", "F24", "F25", "F26", "F27", "F28", "F29", "F30", "F31", "F32",
463 "F33", "F34", "F35", "F36", "F37", "F38", "F39", "F40", "F41", "F42", "F43", "F44", "F45",
464 "F46", "F47", "F48", "F49", "F50", "F51", "F52", "F53", "F54", "F55", "F56", "F57", "F58",
465 "F59", "F60", "F61", "F62", "F63", "Find", "Help", "Home", "Insert", "InsertLine", "Left",
466 "Mark", "Message", "Mouse", "Move", "Next", "Open", "Options", "PageDown", "PageUp", "Previous",
467 "Print", "Redo", "Reference", "Refresh", "Replace", "Restart", "Resume", "Right", "Save",
468 "Select", "ShiftBegin", "ShiftCancel", "ShiftCommand", "ShiftCopy", "ShiftCreate",
469 "ShiftDelete", "ShiftDeleteLine", "ShiftEnd", "ShiftClearToEOL", "ShiftExit", "ShiftFind",
470 "ShiftHelp", "ShiftHome", "ShiftInsert", "ShiftLeft", "ShiftMessage", "ShiftMove", "ShiftNext",
471 "ShiftOptions", "ShiftPrevious", "ShiftPrint", "ShiftRedo", "ShiftReplace", "ShiftResume",
472 "ShiftRight", "ShiftSave", "ShiftSuspend", "ShiftTab", "ShiftUndo", "Suspend", "Undo", "Up",
473 "UpLeft", "UpRight" };
475 prefix_ senf::term::KeyParser::KeyParser()
478 prefix_ senf::term::KeyParser::KeyParser(Terminfo const & ti)
483 prefix_ void senf::term::KeyParser::load(Terminfo const & ti)
485 static Terminfo::properties::String keyStrings [] = {
486 Terminfo::properties::KeyCommand, Terminfo::properties::KeyBackspace,
487 Terminfo::properties::KeyBtab, Terminfo::properties::KeyBeg, Terminfo::properties::KeyCatab,
488 Terminfo::properties::KeyCtab, Terminfo::properties::KeyCancel, Terminfo::properties::KeyB2,
489 Terminfo::properties::KeyClear, Terminfo::properties::KeyEol, Terminfo::properties::KeyEos,
490 Terminfo::properties::KeyClose, Terminfo::properties::KeyCommand,
491 Terminfo::properties::KeyCopy, Terminfo::properties::KeyCreate, Terminfo::properties::KeyDc,
492 Terminfo::properties::KeyDl, Terminfo::properties::KeyDown, Terminfo::properties::KeyC1,
493 Terminfo::properties::KeyC3, Terminfo::properties::KeyEnd, Terminfo::properties::KeyEnter,
494 Terminfo::properties::KeyExit, Terminfo::properties::KeyF0, Terminfo::properties::KeyF1,
495 Terminfo::properties::KeyF2, Terminfo::properties::KeyF3, Terminfo::properties::KeyF4,
496 Terminfo::properties::KeyF5, Terminfo::properties::KeyF6, Terminfo::properties::KeyF7,
497 Terminfo::properties::KeyF8, Terminfo::properties::KeyF9, Terminfo::properties::KeyF10,
498 Terminfo::properties::KeyF11, Terminfo::properties::KeyF12, Terminfo::properties::KeyF13,
499 Terminfo::properties::KeyF14, Terminfo::properties::KeyF15, Terminfo::properties::KeyF16,
500 Terminfo::properties::KeyF17, Terminfo::properties::KeyF18, Terminfo::properties::KeyF19,
501 Terminfo::properties::KeyF20, Terminfo::properties::KeyF21, Terminfo::properties::KeyF22,
502 Terminfo::properties::KeyF23, Terminfo::properties::KeyF24, Terminfo::properties::KeyF25,
503 Terminfo::properties::KeyF26, Terminfo::properties::KeyF27, Terminfo::properties::KeyF28,
504 Terminfo::properties::KeyF29, Terminfo::properties::KeyF30, Terminfo::properties::KeyF31,
505 Terminfo::properties::KeyF32, Terminfo::properties::KeyF33, Terminfo::properties::KeyF34,
506 Terminfo::properties::KeyF35, Terminfo::properties::KeyF36, Terminfo::properties::KeyF37,
507 Terminfo::properties::KeyF38, Terminfo::properties::KeyF39, Terminfo::properties::KeyF40,
508 Terminfo::properties::KeyF41, Terminfo::properties::KeyF42, Terminfo::properties::KeyF43,
509 Terminfo::properties::KeyF44, Terminfo::properties::KeyF45, Terminfo::properties::KeyF46,
510 Terminfo::properties::KeyF47, Terminfo::properties::KeyF48, Terminfo::properties::KeyF49,
511 Terminfo::properties::KeyF50, Terminfo::properties::KeyF51, Terminfo::properties::KeyF52,
512 Terminfo::properties::KeyF53, Terminfo::properties::KeyF54, Terminfo::properties::KeyF55,
513 Terminfo::properties::KeyF56, Terminfo::properties::KeyF57, Terminfo::properties::KeyF58,
514 Terminfo::properties::KeyF59, Terminfo::properties::KeyF60, Terminfo::properties::KeyF61,
515 Terminfo::properties::KeyF62, Terminfo::properties::KeyF63, Terminfo::properties::KeyFind,
516 Terminfo::properties::KeyHelp, Terminfo::properties::KeyHome, Terminfo::properties::KeyIc,
517 Terminfo::properties::KeyIl, Terminfo::properties::KeyLeft, Terminfo::properties::KeyMark,
518 Terminfo::properties::KeyMessage, Terminfo::properties::KeyMouse,
519 Terminfo::properties::KeyMove, Terminfo::properties::KeyNext, Terminfo::properties::KeyOpen,
520 Terminfo::properties::KeyOptions, Terminfo::properties::KeyNpage,
521 Terminfo::properties::KeyPpage, Terminfo::properties::KeyPrevious,
522 Terminfo::properties::KeyPrint, Terminfo::properties::KeyRedo,
523 Terminfo::properties::KeyReference, Terminfo::properties::KeyRefresh,
524 Terminfo::properties::KeyReplace, Terminfo::properties::KeyRestart,
525 Terminfo::properties::KeyResume, Terminfo::properties::KeyRight,
526 Terminfo::properties::KeySave, Terminfo::properties::KeySelect,
527 Terminfo::properties::KeySbeg, Terminfo::properties::KeyScancel,
528 Terminfo::properties::KeyScommand, Terminfo::properties::KeyScopy,
529 Terminfo::properties::KeyScreate, Terminfo::properties::KeySdc,
530 Terminfo::properties::KeySdl, Terminfo::properties::KeySend, Terminfo::properties::KeySeol,
531 Terminfo::properties::KeySexit, Terminfo::properties::KeySfind,
532 Terminfo::properties::KeyShelp, Terminfo::properties::KeyShome,
533 Terminfo::properties::KeySic, Terminfo::properties::KeySleft,
534 Terminfo::properties::KeySmessage, Terminfo::properties::KeySmove,
535 Terminfo::properties::KeySnext, Terminfo::properties::KeySoptions,
536 Terminfo::properties::KeySprevious, Terminfo::properties::KeySprint,
537 Terminfo::properties::KeySredo, Terminfo::properties::KeySreplace,
538 Terminfo::properties::KeySrsume, Terminfo::properties::KeySright,
539 Terminfo::properties::KeySsave, Terminfo::properties::KeySsuspend,
540 Terminfo::properties::KeyStab, Terminfo::properties::KeySundo,
541 Terminfo::properties::KeySuspend, Terminfo::properties::KeyUndo,
542 Terminfo::properties::KeyUp, Terminfo::properties::KeyA1, Terminfo::properties::KeyA3 };
545 for (unsigned i (0); i < sizeof(keyStrings)/sizeof(keyStrings[0]); ++i) {
546 char const * key (ti.getString(keyStrings[i]));
548 table_.insert(std::make_pair(key, KeyCode(i+First)));
552 prefix_ std::pair<senf::term::KeyParser::keycode_t, std::string::size_type>
553 senf::term::KeyParser::lookup(std::string const & key)
557 return std::make_pair(KeyCode(0), 0);
559 // There are several cases:
560 // a) 'key' is an incomplete key sequence. In this case, 'key' will precede all completions in
561 // the key table. The first possible completion is found by 'upper_bound'
562 // b) 'key' is a complete key sequence. This is the key sequence *preceding* the 'upper_bound'
563 // c) 'key' is a complete key sequence with additional trailing characters. In this case, 'key'
564 // will follow the correct entry in the key table. Again, the correct key sequence is
565 // the one preceding the 'upper_bound'
567 Keytable::const_iterator i (table_.upper_bound(key));
568 if (i != table_.end() && i->first.substr(0, key.size()) == key)
569 return std::make_pair(Incomplete, key.size());
570 if (i == table_.begin())
571 return std::make_pair(keycode_t(key[0]), 1);
573 if (key.substr(0, i->first.size()) == i->first)
574 return std::make_pair(i->second, i->first.size());
575 return std::make_pair(keycode_t(key[0]), 1);
578 prefix_ std::string senf::term::KeyParser::describe(keycode_t key)
580 if (key < keycode_t(' '))
581 return "^" + std::string(1, '@' + key);
583 return std::string(1, char(key));
584 if (key >= keycode_t(First) && key < keycode_t(First + sizeof(KeyNames) / sizeof(KeyNames[0])))
585 return std::string(KeyNames[key-First]);
587 return "<" + boost::lexical_cast<std::string>(unsigned(key)) + ">";
590 prefix_ void senf::term::KeyParser::dump(std::ostream & os)
594 for (Keytable::const_iterator i (table_.begin()); i != table_.end(); ++i) {
595 unsigned index (i->second - First);
596 if (index < sizeof(KeyNames)/sizeof(KeyNames[0])) {
597 std::cout << " " << std::setw(32) << KeyNames[index] << ": ";
598 hexdump(i->first.begin(), i->first.end(), os);
603 ///////////////////////////////cc.e////////////////////////////////////////
605 //#include "Terminfo.mpp"
611 // comment-column: 40
612 // c-file-style: "senf"
613 // indent-tabs-mode: nil
614 // ispell-local-dictionary: "american"
615 // compile-command: "scons -u test"