4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief Terminfo non-inline non-template implementation */
31 #include "Terminfo.hh"
32 //#include "Terminfo.ih"
37 #include <boost/filesystem/operations.hpp>
38 #include <senf/config.hh>
39 #include <senf/Utils/hexdump.hh>
43 //#include "Terminfo.mpp"
45 //-/////////////////////////////////////////////////////////////////////////////////////////////////
47 char const * const senf::term::Terminfo::properties::BooleanNames [] = {
48 "AutoLeftMargin", "AutoRightMargin", "NoEscCtlc", "CeolStandoutGlitch", "EatNewlineGlitch",
49 "EraseOverstrike", "GenericType", "HardCopy", "HasMetaKey", "HasStatusLine", "InsertNullGlitch",
50 "MemoryAbove", "MemoryBelow", "MoveInsertMode", "MoveStandoutMode", "OverStrike",
51 "StatusLineEscOk", "DestTabsMagicSmso", "TildeGlitch", "TransparentUnderline", "XonXoff",
52 "NeedsXonXoff", "PrtrSilent", "HardCursor", "NonRevRmcup", "NoPadChar", "NonDestScrollRegion",
53 "CanChange", "BackColorErase", "HueLightnessSaturation", "ColAddrGlitch", "CrCancelsMicroMode",
54 "HasPrintWheel", "RowAddrGlitch", "SemiAutoRightMargin", "CpiChangesRes", "LpiChangesRes",
55 "BackspacesWithBs", "CrtNoScrolling", "NoCorrectlyWorkingCr", "GnuHasMetaKey",
56 "LinefeedIsNewline", "HasHardwareTabs", "ReturnDoesClrEol" };
58 char const * const senf::term::Terminfo::properties::NumericNames[] = {
59 "Columns", "InitTabs", "Lines", "LinesOfMemory", "MagicCookieGlitch", "PaddingBaudRate",
60 "VirtualTerminal", "WidthStatusLine", "NumLabels", "LabelHeight", "LabelWidth", "MaxAttributes",
61 "MaximumWindows", "MaxColors", "MaxPairs", "NoColorVideo", "BufferCapacity", "DotVertSpacing",
62 "DotHorzSpacing", "MaxMicroAddress", "MaxMicroJump", "MicroColSize", "MicroLineSize",
63 "NumberOfPins", "OutputResChar", "OutputResLine", "OutputResHorzInch", "OutputResVertInch",
64 "PrintRate", "WideCharSize", "Buttons", "BitImageEntwining", "BitImageType",
65 "MagicCookieGlitchUl", "CarriageReturnDelay", "NewLineDelay", "BackspaceDelay",
66 "HorizontalTabDelay", "NumberOfFunctionKeys" };
68 char const * const senf::term::Terminfo::properties::StringNames[] = {
69 "BackTab", "Bell", "CarriageReturn", "ChangeScrollRegion", "ClearAllTabs", "ClearScreen",
70 "ClrEol", "ClrEos", "ColumnAddress", "CommandCharacter", "CursorAddress", "CursorDown",
71 "CursorHome", "CursorInvisible", "CursorLeft", "CursorMemAddress", "CursorNormal",
72 "CursorRight", "CursorToLl", "CursorUp", "CursorVisible", "DeleteCharacter", "DeleteLine",
73 "DisStatusLine", "DownHalfLine", "EnterAltCharsetMode", "EnterBlinkMode", "EnterBoldMode",
74 "EnterCaMode", "EnterDeleteMode", "EnterDimMode", "EnterInsertMode", "EnterSecureMode",
75 "EnterProtectedMode", "EnterReverseMode", "EnterStandoutMode", "EnterUnderlineMode",
76 "EraseChars", "ExitAltCharsetMode", "ExitAttributeMode", "ExitCaMode", "ExitDeleteMode",
77 "ExitInsertMode", "ExitStandoutMode", "ExitUnderlineMode", "FlashScreen", "FormFeed",
78 "FromStatusLine", "Init1string", "Init2string", "Init3string", "InitFile", "InsertCharacter",
79 "InsertLine", "InsertPadding", "KeyBackspace", "KeyCatab", "KeyClear", "KeyCtab", "KeyDc",
80 "KeyDl", "KeyDown", "KeyEic", "KeyEol", "KeyEos", "KeyF0", "KeyF1", "KeyF10", "KeyF2", "KeyF3",
81 "KeyF4", "KeyF5", "KeyF6", "KeyF7", "KeyF8", "KeyF9", "KeyHome", "KeyIc", "KeyIl", "KeyLeft",
82 "KeyLl", "KeyNpage", "KeyPpage", "KeyRight", "KeySf", "KeySr", "KeyStab", "KeyUp",
83 "KeypadLocal", "KeypadXmit", "LabF0", "LabF1", "LabF10", "LabF2", "LabF3", "LabF4", "LabF5",
84 "LabF6", "LabF7", "LabF8", "LabF9", "MetaOff", "MetaOn", "Newline", "PadChar", "ParmDch",
85 "ParmDeleteLine", "ParmDownCursor", "ParmIch", "ParmIndex", "ParmInsertLine", "ParmLeftCursor",
86 "ParmRightCursor", "ParmRindex", "ParmUpCursor", "PkeyKey", "PkeyLocal", "PkeyXmit",
87 "PrintScreen", "PrtrOff", "PrtrOn", "RepeatChar", "Reset1string", "Reset2string",
88 "Reset3string", "ResetFile", "RestoreCursor", "RowAddress", "SaveCursor", "ScrollForward",
89 "ScrollReverse", "SetAttributes", "SetTab", "SetWindow", "Tab", "ToStatusLine", "UnderlineChar",
90 "UpHalfLine", "InitProg", "KeyA1", "KeyA3", "KeyB2", "KeyC1", "KeyC3", "PrtrNon", "CharPadding",
91 "AcsChars", "PlabNorm", "KeyBtab", "EnterXonMode", "ExitXonMode", "EnterAmMode", "ExitAmMode",
92 "XonCharacter", "XoffCharacter", "EnaAcs", "LabelOn", "LabelOff", "KeyBeg", "KeyCancel",
93 "KeyClose", "KeyCommand", "KeyCopy", "KeyCreate", "KeyEnd", "KeyEnter", "KeyExit", "KeyFind",
94 "KeyHelp", "KeyMark", "KeyMessage", "KeyMove", "KeyNext", "KeyOpen", "KeyOptions",
95 "KeyPrevious", "KeyPrint", "KeyRedo", "KeyReference", "KeyRefresh", "KeyReplace", "KeyRestart",
96 "KeyResume", "KeySave", "KeySuspend", "KeyUndo", "KeySbeg", "KeyScancel", "KeyScommand",
97 "KeyScopy", "KeyScreate", "KeySdc", "KeySdl", "KeySelect", "KeySend", "KeySeol", "KeySexit",
98 "KeySfind", "KeyShelp", "KeyShome", "KeySic", "KeySleft", "KeySmessage", "KeySmove", "KeySnext",
99 "KeySoptions", "KeySprevious", "KeySprint", "KeySredo", "KeySreplace", "KeySright", "KeySrsume",
100 "KeySsave", "KeySsuspend", "KeySundo", "ReqForInput", "KeyF11", "KeyF12", "KeyF13", "KeyF14",
101 "KeyF15", "KeyF16", "KeyF17", "KeyF18", "KeyF19", "KeyF20", "KeyF21", "KeyF22", "KeyF23",
102 "KeyF24", "KeyF25", "KeyF26", "KeyF27", "KeyF28", "KeyF29", "KeyF30", "KeyF31", "KeyF32",
103 "KeyF33", "KeyF34", "KeyF35", "KeyF36", "KeyF37", "KeyF38", "KeyF39", "KeyF40", "KeyF41",
104 "KeyF42", "KeyF43", "KeyF44", "KeyF45", "KeyF46", "KeyF47", "KeyF48", "KeyF49", "KeyF50",
105 "KeyF51", "KeyF52", "KeyF53", "KeyF54", "KeyF55", "KeyF56", "KeyF57", "KeyF58", "KeyF59",
106 "KeyF60", "KeyF61", "KeyF62", "KeyF63", "ClrBol", "ClearMargins", "SetLeftMargin",
107 "SetRightMargin", "LabelFormat", "SetClock", "DisplayClock", "RemoveClock", "CreateWindow",
108 "GotoWindow", "Hangup", "DialPhone", "QuickDial", "Tone", "Pulse", "FlashHook", "FixedPause",
109 "WaitTone", "User0", "User1", "User2", "User3", "User4", "User5", "User6", "User7", "User8",
110 "User9", "OrigPair", "OrigColors", "InitializeColor", "InitializePair", "SetColorPair",
111 "SetForeground", "SetBackground", "ChangeCharPitch", "ChangeLinePitch", "ChangeResHorz",
112 "ChangeResVert", "DefineChar", "EnterDoublewideMode", "EnterDraftQuality", "EnterItalicsMode",
113 "EnterLeftwardMode", "EnterMicroMode", "EnterNearLetterQuality", "EnterNormalQuality",
114 "EnterShadowMode", "EnterSubscriptMode", "EnterSuperscriptMode", "EnterUpwardMode",
115 "ExitDoublewideMode", "ExitItalicsMode", "ExitLeftwardMode", "ExitMicroMode", "ExitShadowMode",
116 "ExitSubscriptMode", "ExitSuperscriptMode", "ExitUpwardMode", "MicroColumnAddress", "MicroDown",
117 "MicroLeft", "MicroRight", "MicroRowAddress", "MicroUp", "OrderOfPins", "ParmDownMicro",
118 "ParmLeftMicro", "ParmRightMicro", "ParmUpMicro", "SelectCharSet", "SetBottomMargin",
119 "SetBottomMarginParm", "SetLeftMarginParm", "SetRightMarginParm", "SetTopMargin",
120 "SetTopMarginParm", "StartBitImage", "StartCharSetDef", "StopBitImage", "StopCharSetDef",
121 "SubscriptCharacters", "SuperscriptCharacters", "TheseCauseCr", "ZeroMotion", "CharSetNames",
122 "KeyMouse", "MouseInfo", "ReqMousePos", "GetMouse", "SetAForeground", "SetABackground",
123 "PkeyPlab", "DeviceType", "CodeSetInit", "Set0DesSeq", "Set1DesSeq", "Set2DesSeq", "Set3DesSeq",
124 "SetLrMargin", "SetTbMargin", "BitImageRepeat", "BitImageNewline", "BitImageCarriageReturn",
125 "ColorNames", "DefineBitImageRegion", "EndBitImageRegion", "SetColorBand", "SetPageLength",
126 "DisplayPcChar", "EnterPcCharsetMode", "ExitPcCharsetMode", "EnterScancodeMode",
127 "ExitScancodeMode", "PcTermOptions", "ScancodeEscape", "AltScancodeEsc",
128 "EnterHorizontalHlMode", "EnterLeftHlMode", "EnterLowHlMode", "EnterRightHlMode",
129 "EnterTopHlMode", "EnterVerticalHlMode", "SetAAttributes", "SetPglenInch", "TermcapInit2",
130 "TermcapReset", "LinefeedIfNotLf", "BackspaceIfNotBs", "OtherNonFunctionKeys", "ArrowKeyMap",
131 "AcsUlcorner", "AcsLlcorner", "AcsUrcorner", "AcsLrcorner", "AcsLtee", "AcsRtee", "AcsBtee",
132 "AcsTtee", "AcsHline", "AcsVline", "AcsPlus", "MemoryLock", "MemoryUnlock", "BoxChars1" };
134 //-/////////////////////////////////////////////////////////////////////////////////////////////////
135 // senf::term::Terminfo
137 prefix_ senf::term::Terminfo::InvalidTerminfoException::InvalidTerminfoException(std::string const & term)
138 : senf::Exception("Unreadable terminfo file")
141 append( ": " + term);
144 prefix_ senf::term::Terminfo::Terminfo()
147 prefix_ senf::term::Terminfo::Terminfo(std::string const & term)
152 prefix_ void senf::term::Terminfo::load(std::string const & term)
154 std::string filename (findTerminfo(term));
155 if (filename.empty()) throw InvalidTerminfoException(term);
156 std::ifstream is (filename.c_str());
157 if (!is) throw InvalidTerminfoException(filename);
160 } catch (InvalidTerminfoException & ex) {
161 ex << ": " << filename;
166 prefix_ bool senf::term::Terminfo::getFlag(properties::Boolean p)
169 if (BoolVec::size_type(p) >= booleans_.size())
174 prefix_ senf::term::Terminfo::number_t senf::term::Terminfo::getNumber(properties::Numeric p)
177 if (NumberVec::size_type(p) >= numbers_.size())
182 prefix_ senf::term::Terminfo::string_t senf::term::Terminfo::getString(properties::String p)
185 if (StringVec::size_type(p) >= strings_.size())
190 prefix_ bool senf::term::Terminfo::hasProperty(properties::Boolean p)
196 prefix_ bool senf::term::Terminfo::hasProperty(properties::Numeric p)
199 return getNumber(p) != NoValue;
202 prefix_ bool senf::term::Terminfo::hasProperty(properties::String p)
205 return getString(p) != 0;
212 std::vector<senf::term::Terminfo::number_t> stack;
214 void push(senf::term::Terminfo::number_t v)
219 senf::term::Terminfo::number_t pop()
224 senf::term::Terminfo::number_t v (stack.back());
230 senf::term::Terminfo::number_t popNonzero()
232 senf::term::Terminfo::number_t v (pop());
239 // The following code is taken directly from utio. As far as I understand it is buggy
240 // and/or only partially implements the string format language. But seems to be enough for
241 // all the common terminal types ...
242 prefix_ std::string senf::term::Terminfo::formatString(properties::String p,
243 number_t arg1, number_t arg2,
244 number_t arg3, number_t arg4,
245 number_t arg5, number_t arg6,
246 number_t arg7, number_t arg8,
250 char const * fmt_p (getString(p));
254 std::string const prgstr (fmt_p);
256 bool bCondValue (false);
259 for (std::string::const_iterator i (prgstr.begin()); i != prgstr.end(); ++i) {
264 int width = 0, base = 0;
266 case '%': result += *i; break;
267 case 'i': ++arg1; ++arg2; break;
268 case 'c': result += char(stack.pop()); break;
269 case 'x': base = 16; continue;
270 case '0': if (!base) base = 8;
271 case '1': case '2': case '3': case '4':
272 case '5': case '6': case '7': case '8':
273 case '9': if (!base) base = 10;
274 width = width * base + (*i - '0');
278 case '\'': if (*(i - 1) == '%') {
279 if (*(i + 1) != '\\')
283 case '}': stack.push(width); break;
284 // Binary operands are in infix (reversed) order
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.popNonzero()); break;
289 case 'm': stack.push(stack.pop() % stack.popNonzero()); break;
290 case '|': stack.push(stack.pop() | stack.pop()); break;
291 case '&': stack.push(stack.pop() & stack.pop()); break;
292 case '^': stack.push(stack.pop() ^ stack.pop()); break;
293 case '>': stack.push(stack.pop() < stack.pop()); break;
294 case '<': stack.push(stack.pop() > stack.pop()); break;
295 case '=': stack.push(stack.pop() == stack.pop()); break;
296 case 'A': stack.push(stack.pop() && stack.pop()); break;
297 case 'O': stack.push(stack.pop() || stack.pop()); break;
298 case '!': stack.push(!stack.pop()); break;
299 case '~': stack.push(~stack.pop()); break;
300 case 't': bCondValue = stack.pop();
301 case 'e': if ((bCondValue = !bCondValue)) // this also supports elsif
302 --(i = prgstr.begin() + std::min (prgstr.find ("%e", i-prgstr.begin()),
303 prgstr.find ("%;", i-prgstr.begin())));
308 case '1': stack.push(arg1); break;
309 case '2': stack.push(arg2); break;
310 case '3': stack.push(arg3); break;
311 case '4': stack.push(arg4); break;
312 case '5': stack.push(arg5); break;
313 case '6': stack.push(arg6); break;
314 case '7': stack.push(arg7); break;
315 case '8': stack.push(arg8); break;
316 case '9': stack.push(arg9); break;
320 number_t n = stack.pop();
321 const std::string::size_type iSize = result.size();
323 result += std::string::value_type('0' + (n % 10));
324 } while ((n /= 10) || --width > 0);
325 reverse (result.begin() + iSize, result.end());
333 prefix_ void senf::term::Terminfo::dump(std::ostream & os)
336 os << "Terminfo entry: " << name_ << "\n";
337 os << "Booleans: " << booleans_.size() << "\n";
338 os << "Numbers: " << numbers_.size() << "\n";
339 os << "Strings: " << strings_.size() << "\n";
340 os << "String pool size: " << stringPool_.size() << "\n";
345 BoolVec::const_iterator i (booleans_.begin());
346 BoolVec::const_iterator const i_end (booleans_.end());
347 for (; i != i_end; ++i, ++n)
348 if (*i && n < sizeof(properties::BooleanNames)/sizeof(properties::BooleanNames[0]))
349 os << " " << properties::BooleanNames[n] << "\n";
355 NumberVec::const_iterator i (numbers_.begin());
356 NumberVec::const_iterator const i_end (numbers_.end());
357 for (; i != i_end; ++i, ++n)
359 && n < sizeof(properties::NumericNames)/sizeof(properties::NumericNames[0]))
360 os << " " << properties::NumericNames[n] << " = " << *i << "\n";
366 StringVec::const_iterator i (strings_.begin());
367 StringVec::const_iterator const i_end (strings_.end());
368 for (; i != i_end; ++i, ++n)
369 if (*i && n < sizeof(properties::StringNames)/sizeof(properties::StringNames[0])) {
370 os << " " << std::setw(32) << properties::StringNames[n] << " = ";
371 hexdump(*i, *i + strlen(*i), os, 32);
377 prefix_ std::string senf::term::Terminfo::findTerminfo(std::string const & name)
379 if (name.empty()) return "";
380 boost::filesystem::path subdir (name.substr(0,1)); subdir /= name;
381 boost::filesystem::path tientry;
384 char const * tivar (::getenv("TERMINFO"));
386 tientry = boost::filesystem::path(tivar) / subdir;
387 if (boost::filesystem::exists(tientry)) return tientry.string();
391 tientry = boost::filesystem::path("/etc/terminfo") / subdir;
392 if (boost::filesystem::exists(tientry)) return tientry.string();
394 tientry = boost::filesystem::path("/lib/terminfo") / subdir;
395 if (boost::filesystem::exists(tientry)) return tientry.string();
397 tientry = boost::filesystem::path("/usr/share/terminfo") / subdir;
398 if (boost::filesystem::exists(tientry)) return tientry.string();
405 boost::uint16_t const TerminfoMagic = 0x011A;
407 struct TerminfoHeader {
408 boost::uint16_t magic;
409 boost::uint16_t namesSz;
410 boost::uint16_t nBooleans;
411 boost::uint16_t nNumbers;
412 boost::uint16_t nStrings;
413 boost::uint16_t stringPoolSz;
416 magic = le16toh(magic);
417 namesSz = le16toh(namesSz);
418 nBooleans = le16toh(nBooleans);
419 nNumbers = le16toh(nNumbers);
420 nStrings = le16toh(nStrings);
421 stringPoolSz = le16toh(stringPoolSz);
427 prefix_ void senf::term::Terminfo::load(std::istream & is)
430 is.read(static_cast<char*>(static_cast<void*>(&h)), sizeof(h));
432 if (!is || h.magic != TerminfoMagic) throw InvalidTerminfoException(
433 "invalid magic number (") << h.magic << "!=" << TerminfoMagic << ")";
435 name_.resize(h.namesSz);
436 is.read(&(name_[0]), name_.size());
437 if (!is) throw InvalidTerminfoException();
438 if (name_.size() & 1)
441 std::string::size_type n (name_.find('\0'));
442 if (n != std::string::npos)
446 booleans_.resize(h.nBooleans);
447 for (BoolVec::iterator i (booleans_.begin()); i != booleans_.end(); ++i) {
449 is.read(&v, sizeof(v));
450 if (!is) throw InvalidTerminfoException();
453 if (booleans_.size() & 1)
456 numbers_.resize(h.nNumbers);
457 for (NumberVec::iterator i (numbers_.begin()); i != numbers_.end(); ++i) {
459 is.read(static_cast<char*>(static_cast<void*>(&v)), sizeof(v));
460 if (!is) throw InvalidTerminfoException();
464 typedef std::vector<number_t> OffsetVec;
466 offsets.resize (h.nStrings);
467 for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i) {
469 is.read(static_cast<char*>(static_cast<void*>(&v)), sizeof(v));
470 if (!is) throw InvalidTerminfoException();
474 stringPool_.resize(h.stringPoolSz);
475 is.read(&(stringPool_[0]), stringPool_.size());
476 if (!is) throw InvalidTerminfoException();
478 strings_.resize(offsets.size());
479 StringVec::iterator j (strings_.begin());
480 for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i, ++j)
481 if (*i != NoValue && *i >= 0 && unsigned(*i) < stringPool_.size())
482 *j = &(stringPool_[0]) + *i;
487 //-/////////////////////////////////////////////////////////////////////////////////////////////////
488 // senf::term::KeyParser
490 char const * const senf::term::KeyParser::KeyNames[] = {
491 "Esc", "Backspace", "Backtab", "Begin", "CATab", "CTab", "Cancel", "Center", "Clear",
492 "ClearToEOL", "ClearToEOS", "Close", "Command", "Copy", "Create", "Delete", "DeleteLine",
493 "Down", "DownLeft", "DownRight", "End", "Enter", "Exit", "F0", "F1", "F2", "F3", "F4", "F5",
494 "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19",
495 "F20", "F21", "F22", "F23", "F24", "F25", "F26", "F27", "F28", "F29", "F30", "F31", "F32",
496 "F33", "F34", "F35", "F36", "F37", "F38", "F39", "F40", "F41", "F42", "F43", "F44", "F45",
497 "F46", "F47", "F48", "F49", "F50", "F51", "F52", "F53", "F54", "F55", "F56", "F57", "F58",
498 "F59", "F60", "F61", "F62", "F63", "Find", "Help", "Home", "Insert", "InsertLine", "Left",
499 "Mark", "Message", "Mouse", "Move", "Next", "Open", "Options", "PageDown", "PageUp", "Previous",
500 "Print", "Redo", "Reference", "Refresh", "Replace", "Restart", "Resume", "Right", "Save",
501 "Select", "ShiftBegin", "ShiftCancel", "ShiftCommand", "ShiftCopy", "ShiftCreate",
502 "ShiftDelete", "ShiftDeleteLine", "ShiftEnd", "ShiftClearToEOL", "ShiftExit", "ShiftFind",
503 "ShiftHelp", "ShiftHome", "ShiftInsert", "ShiftLeft", "ShiftMessage", "ShiftMove", "ShiftNext",
504 "ShiftOptions", "ShiftPrevious", "ShiftPrint", "ShiftRedo", "ShiftReplace", "ShiftResume",
505 "ShiftRight", "ShiftSave", "ShiftSuspend", "ShiftTab", "ShiftUndo", "Suspend", "Undo", "Up",
506 "UpLeft", "UpRight" };
508 prefix_ senf::term::KeyParser::KeyParser()
511 prefix_ senf::term::KeyParser::KeyParser(Terminfo const & ti)
516 prefix_ void senf::term::KeyParser::load(Terminfo const & ti)
518 static Terminfo::properties::String keyStrings [] = {
519 Terminfo::properties::KeyCommand, Terminfo::properties::KeyBackspace,
520 Terminfo::properties::KeyBtab, Terminfo::properties::KeyBeg, Terminfo::properties::KeyCatab,
521 Terminfo::properties::KeyCtab, Terminfo::properties::KeyCancel, Terminfo::properties::KeyB2,
522 Terminfo::properties::KeyClear, Terminfo::properties::KeyEol, Terminfo::properties::KeyEos,
523 Terminfo::properties::KeyClose, Terminfo::properties::KeyCommand,
524 Terminfo::properties::KeyCopy, Terminfo::properties::KeyCreate, Terminfo::properties::KeyDc,
525 Terminfo::properties::KeyDl, Terminfo::properties::KeyDown, Terminfo::properties::KeyC1,
526 Terminfo::properties::KeyC3, Terminfo::properties::KeyEnd, Terminfo::properties::KeyEnter,
527 Terminfo::properties::KeyExit, Terminfo::properties::KeyF0, Terminfo::properties::KeyF1,
528 Terminfo::properties::KeyF2, Terminfo::properties::KeyF3, Terminfo::properties::KeyF4,
529 Terminfo::properties::KeyF5, Terminfo::properties::KeyF6, Terminfo::properties::KeyF7,
530 Terminfo::properties::KeyF8, Terminfo::properties::KeyF9, Terminfo::properties::KeyF10,
531 Terminfo::properties::KeyF11, Terminfo::properties::KeyF12, Terminfo::properties::KeyF13,
532 Terminfo::properties::KeyF14, Terminfo::properties::KeyF15, Terminfo::properties::KeyF16,
533 Terminfo::properties::KeyF17, Terminfo::properties::KeyF18, Terminfo::properties::KeyF19,
534 Terminfo::properties::KeyF20, Terminfo::properties::KeyF21, Terminfo::properties::KeyF22,
535 Terminfo::properties::KeyF23, Terminfo::properties::KeyF24, Terminfo::properties::KeyF25,
536 Terminfo::properties::KeyF26, Terminfo::properties::KeyF27, Terminfo::properties::KeyF28,
537 Terminfo::properties::KeyF29, Terminfo::properties::KeyF30, Terminfo::properties::KeyF31,
538 Terminfo::properties::KeyF32, Terminfo::properties::KeyF33, Terminfo::properties::KeyF34,
539 Terminfo::properties::KeyF35, Terminfo::properties::KeyF36, Terminfo::properties::KeyF37,
540 Terminfo::properties::KeyF38, Terminfo::properties::KeyF39, Terminfo::properties::KeyF40,
541 Terminfo::properties::KeyF41, Terminfo::properties::KeyF42, Terminfo::properties::KeyF43,
542 Terminfo::properties::KeyF44, Terminfo::properties::KeyF45, Terminfo::properties::KeyF46,
543 Terminfo::properties::KeyF47, Terminfo::properties::KeyF48, Terminfo::properties::KeyF49,
544 Terminfo::properties::KeyF50, Terminfo::properties::KeyF51, Terminfo::properties::KeyF52,
545 Terminfo::properties::KeyF53, Terminfo::properties::KeyF54, Terminfo::properties::KeyF55,
546 Terminfo::properties::KeyF56, Terminfo::properties::KeyF57, Terminfo::properties::KeyF58,
547 Terminfo::properties::KeyF59, Terminfo::properties::KeyF60, Terminfo::properties::KeyF61,
548 Terminfo::properties::KeyF62, Terminfo::properties::KeyF63, Terminfo::properties::KeyFind,
549 Terminfo::properties::KeyHelp, Terminfo::properties::KeyHome, Terminfo::properties::KeyIc,
550 Terminfo::properties::KeyIl, Terminfo::properties::KeyLeft, Terminfo::properties::KeyMark,
551 Terminfo::properties::KeyMessage, Terminfo::properties::KeyMouse,
552 Terminfo::properties::KeyMove, Terminfo::properties::KeyNext, Terminfo::properties::KeyOpen,
553 Terminfo::properties::KeyOptions, Terminfo::properties::KeyNpage,
554 Terminfo::properties::KeyPpage, Terminfo::properties::KeyPrevious,
555 Terminfo::properties::KeyPrint, Terminfo::properties::KeyRedo,
556 Terminfo::properties::KeyReference, Terminfo::properties::KeyRefresh,
557 Terminfo::properties::KeyReplace, Terminfo::properties::KeyRestart,
558 Terminfo::properties::KeyResume, Terminfo::properties::KeyRight,
559 Terminfo::properties::KeySave, Terminfo::properties::KeySelect,
560 Terminfo::properties::KeySbeg, Terminfo::properties::KeyScancel,
561 Terminfo::properties::KeyScommand, Terminfo::properties::KeyScopy,
562 Terminfo::properties::KeyScreate, Terminfo::properties::KeySdc,
563 Terminfo::properties::KeySdl, Terminfo::properties::KeySend, Terminfo::properties::KeySeol,
564 Terminfo::properties::KeySexit, Terminfo::properties::KeySfind,
565 Terminfo::properties::KeyShelp, Terminfo::properties::KeyShome,
566 Terminfo::properties::KeySic, Terminfo::properties::KeySleft,
567 Terminfo::properties::KeySmessage, Terminfo::properties::KeySmove,
568 Terminfo::properties::KeySnext, Terminfo::properties::KeySoptions,
569 Terminfo::properties::KeySprevious, Terminfo::properties::KeySprint,
570 Terminfo::properties::KeySredo, Terminfo::properties::KeySreplace,
571 Terminfo::properties::KeySrsume, Terminfo::properties::KeySright,
572 Terminfo::properties::KeySsave, Terminfo::properties::KeySsuspend,
573 Terminfo::properties::KeyStab, Terminfo::properties::KeySundo,
574 Terminfo::properties::KeySuspend, Terminfo::properties::KeyUndo,
575 Terminfo::properties::KeyUp, Terminfo::properties::KeyA1, Terminfo::properties::KeyA3 };
578 for (unsigned i (0); i < sizeof(keyStrings)/sizeof(keyStrings[0]); ++i) {
579 char const * key (ti.getString(keyStrings[i]));
581 table_.insert(std::make_pair(key, KeyCode(i+First)));
585 prefix_ std::pair<senf::term::KeyParser::keycode_t, std::string::size_type>
586 senf::term::KeyParser::lookup(std::string const & key)
590 return std::make_pair(KeyCode(0), 0);
592 // There are several cases:
593 // a) 'key' is an incomplete key sequence. In this case, 'key' will precede all completions in
594 // the key table. The first possible completion is found by 'upper_bound'
595 // b) 'key' is a complete key sequence. This is the key sequence *preceding* the 'upper_bound'
596 // c) 'key' is a complete key sequence with additional trailing characters. In this case, 'key'
597 // will follow the correct entry in the key table. Again, the correct key sequence is
598 // the one preceding the 'upper_bound'
600 Keytable::const_iterator i (table_.upper_bound(key));
601 if (i != table_.end() && i->first.substr(0, key.size()) == key)
602 return std::make_pair(Incomplete, key.size());
603 if (i == table_.begin())
604 return std::make_pair(keycode_t(key[0]), 1);
606 if (key.substr(0, i->first.size()) == i->first)
607 return std::make_pair(i->second, i->first.size());
608 return std::make_pair(keycode_t(key[0]), 1);
611 prefix_ std::string senf::term::KeyParser::describe(keycode_t key)
613 if (key < keycode_t(' '))
614 return "^" + std::string(1, '@' + key);
616 return std::string(1, char(key));
617 if (key >= keycode_t(First) && key < keycode_t(First + sizeof(KeyNames) / sizeof(KeyNames[0])))
618 return std::string(KeyNames[key-First]);
620 return "<" + boost::lexical_cast<std::string>(unsigned(key)) + ">";
623 prefix_ void senf::term::KeyParser::dump(std::ostream & os)
627 for (Keytable::const_iterator i (table_.begin()); i != table_.end(); ++i) {
628 unsigned index (i->second - First);
629 if (index < sizeof(KeyNames)/sizeof(KeyNames[0])) {
630 std::cout << " " << std::setw(32) << KeyNames[index] << ": ";
631 hexdump(i->first.begin(), i->first.end(), os);
636 //-/////////////////////////////////////////////////////////////////////////////////////////////////
638 //#include "Terminfo.mpp"
644 // comment-column: 40
645 // c-file-style: "senf"
646 // indent-tabs-mode: nil
647 // ispell-local-dictionary: "american"
648 // compile-command: "scons -u test"