Termlib: fixed endian bug while reading terminfo file
[senf.git] / senf / Utils / Termlib / Terminfo.hh
1 // $Id$
2 //
3 // Copyright (C) 2009
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
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
10 //
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.
14 //
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.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
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.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief Terminfo public header */
30
31 #ifndef HH_SENF_Utils_Termlib_Terminfo_
32 #define HH_SENF_Utils_Termlib_Terminfo_ 1
33
34 // Custom includes
35 #include <string>
36 #include <vector>
37 #include <map>
38 #include <iostream>
39 #include <boost/cstdint.hpp>
40 #include <boost/array.hpp>
41 #include <senf/Utils/Exception.hh>
42
43 //#include "Terminfo.mpp"
44 //-/////////////////////////////////////////////////////////////////////////////////////////////////
45
46 namespace senf {
47 namespace term {
48
49     /** \defgroup terminfo_group Terminfo
50
51         This facility provides access to the terminfo database. It partially re-implements the
52         terminfo suppoprt in \c libncurses.
53
54         \li The senf::term::Terminfo class provides basic terminfo property access and supports terminfo string
55             formatting
56         \li The senf::term::KeyParser class uses the properties found in a Terminfo instance to
57             parser keyboard escape sequences into key codes
58
59         The terminfo implementation is based on the \c utio library by Mike Sharov
60         <msharov@users.sourceforge.net> found at http://sourceforge.net/projects/utio.
61      */
62
63     /** \brief Terminfo database entry
64
65         This class reads a single terminfo database entry and allows to access the terminfo
66         properties.
67
68         \ingroup terminfo_group
69      */
70     class Terminfo
71     {
72     public:
73         //-////////////////////////////////////////////////////////////////////////
74         // Types
75
76         /** \brief NoValue constant
77             This value represents the absence of a numeric property value */
78         enum { NoValue = -1 };
79
80         /** \brief Terminfo property constants
81
82             This class provides a namespace for all Terminfo property constants
83          */
84         struct properties
85         {
86             /** \brief Boolean terminfo properties */
87             enum Boolean {
88                 AutoLeftMargin, AutoRightMargin, NoEscCtlc, CeolStandoutGlitch, EatNewlineGlitch,
89                 EraseOverstrike, GenericType, HardCopy, HasMetaKey, HasStatusLine, InsertNullGlitch,
90                 MemoryAbove, MemoryBelow, MoveInsertMode, MoveStandoutMode, OverStrike,
91                 StatusLineEscOk, DestTabsMagicSmso, TildeGlitch, TransparentUnderline, XonXoff,
92                 NeedsXonXoff, PrtrSilent, HardCursor, NonRevRmcup, NoPadChar, NonDestScrollRegion,
93                 CanChange, BackColorErase, HueLightnessSaturation, ColAddrGlitch,
94                 CrCancelsMicroMode, HasPrintWheel, RowAddrGlitch, SemiAutoRightMargin,
95                 CpiChangesRes, LpiChangesRes, BackspacesWithBs, CrtNoScrolling,
96                 NoCorrectlyWorkingCr, GnuHasMetaKey, LinefeedIsNewline, HasHardwareTabs,
97                 ReturnDoesClrEol };
98
99             /** \brief Boolean property names
100                 \hideinitializer */
101             static char const * const BooleanNames[];
102
103             /** \brief Numeric terminfo properties */
104             enum Numeric {
105                 Columns, InitTabs, Lines, LinesOfMemory, MagicCookieGlitch, PaddingBaudRate,
106                 VirtualTerminal, WidthStatusLine, NumLabels, LabelHeight, LabelWidth, MaxAttributes,
107                 MaximumWindows, MaxColors, MaxPairs, NoColorVideo, BufferCapacity, DotVertSpacing,
108                 DotHorzSpacing, MaxMicroAddress, MaxMicroJump, MicroColSize, MicroLineSize,
109                 NumberOfPins, OutputResChar, OutputResLine, OutputResHorzInch, OutputResVertInch,
110                 PrintRate, WideCharSize, Buttons, BitImageEntwining, BitImageType,
111                 MagicCookieGlitchUl, CarriageReturnDelay, NewLineDelay, BackspaceDelay,
112                 HorizontalTabDelay, NumberOfFunctionKeys };
113
114             /** \brief Numeric property names
115                 \hideinitializer */
116             static char const * const NumericNames[];
117
118             /** \brief String terminfo properties */
119             enum String {
120                 BackTab, Bell, CarriageReturn, ChangeScrollRegion, ClearAllTabs, ClearScreen,
121                 ClrEol, ClrEos, ColumnAddress, CommandCharacter, CursorAddress, CursorDown,
122                 CursorHome, CursorInvisible, CursorLeft, CursorMemAddress, CursorNormal,
123                 CursorRight, CursorToLl, CursorUp, CursorVisible, DeleteCharacter, DeleteLine,
124                 DisStatusLine, DownHalfLine, EnterAltCharsetMode, EnterBlinkMode, EnterBoldMode,
125                 EnterCaMode, EnterDeleteMode, EnterDimMode, EnterInsertMode, EnterSecureMode,
126                 EnterProtectedMode, EnterReverseMode, EnterStandoutMode, EnterUnderlineMode,
127                 EraseChars, ExitAltCharsetMode, ExitAttributeMode, ExitCaMode, ExitDeleteMode,
128                 ExitInsertMode, ExitStandoutMode, ExitUnderlineMode, FlashScreen, FormFeed,
129                 FromStatusLine, Init1string, Init2string, Init3string, InitFile, InsertCharacter,
130                 InsertLine, InsertPadding, KeyBackspace, KeyCatab, KeyClear, KeyCtab, KeyDc, KeyDl,
131                 KeyDown, KeyEic, KeyEol, KeyEos, KeyF0, KeyF1, KeyF10, KeyF2, KeyF3, KeyF4, KeyF5,
132                 KeyF6, KeyF7, KeyF8, KeyF9, KeyHome, KeyIc, KeyIl, KeyLeft, KeyLl, KeyNpage,
133                 KeyPpage, KeyRight, KeySf, KeySr, KeyStab, KeyUp, KeypadLocal, KeypadXmit, LabF0,
134                 LabF1, LabF10, LabF2, LabF3, LabF4, LabF5, LabF6, LabF7, LabF8, LabF9, MetaOff,
135                 MetaOn, Newline, PadChar, ParmDch, ParmDeleteLine, ParmDownCursor, ParmIch,
136                 ParmIndex, ParmInsertLine, ParmLeftCursor, ParmRightCursor, ParmRindex,
137                 ParmUpCursor, PkeyKey, PkeyLocal, PkeyXmit, PrintScreen, PrtrOff, PrtrOn,
138                 RepeatChar, Reset1string, Reset2string, Reset3string, ResetFile, RestoreCursor,
139                 RowAddress, SaveCursor, ScrollForward, ScrollReverse, SetAttributes, SetTab,
140                 SetWindow, Tab, ToStatusLine, UnderlineChar, UpHalfLine, InitProg, KeyA1, KeyA3,
141                 KeyB2, KeyC1, KeyC3, PrtrNon, CharPadding, AcsChars, PlabNorm, KeyBtab,
142                 EnterXonMode, ExitXonMode, EnterAmMode, ExitAmMode, XonCharacter, XoffCharacter,
143                 EnaAcs, LabelOn, LabelOff, KeyBeg, KeyCancel, KeyClose, KeyCommand, KeyCopy,
144                 KeyCreate, KeyEnd, KeyEnter, KeyExit, KeyFind, KeyHelp, KeyMark, KeyMessage,
145                 KeyMove, KeyNext, KeyOpen, KeyOptions, KeyPrevious, KeyPrint, KeyRedo, KeyReference,
146                 KeyRefresh, KeyReplace, KeyRestart, KeyResume, KeySave, KeySuspend, KeyUndo,
147                 KeySbeg, KeyScancel, KeyScommand, KeyScopy, KeyScreate, KeySdc, KeySdl, KeySelect,
148                 KeySend, KeySeol, KeySexit, KeySfind, KeyShelp, KeyShome, KeySic, KeySleft,
149                 KeySmessage, KeySmove, KeySnext, KeySoptions, KeySprevious, KeySprint, KeySredo,
150                 KeySreplace, KeySright, KeySrsume, KeySsave, KeySsuspend, KeySundo, ReqForInput,
151                 KeyF11, KeyF12, KeyF13, KeyF14, KeyF15, KeyF16, KeyF17, KeyF18, KeyF19, KeyF20,
152                 KeyF21, KeyF22, KeyF23, KeyF24, KeyF25, KeyF26, KeyF27, KeyF28, KeyF29, KeyF30,
153                 KeyF31, KeyF32, KeyF33, KeyF34, KeyF35, KeyF36, KeyF37, KeyF38, KeyF39, KeyF40,
154                 KeyF41, KeyF42, KeyF43, KeyF44, KeyF45, KeyF46, KeyF47, KeyF48, KeyF49, KeyF50,
155                 KeyF51, KeyF52, KeyF53, KeyF54, KeyF55, KeyF56, KeyF57, KeyF58, KeyF59, KeyF60,
156                 KeyF61, KeyF62, KeyF63, ClrBol, ClearMargins, SetLeftMargin, SetRightMargin,
157                 LabelFormat, SetClock, DisplayClock, RemoveClock, CreateWindow, GotoWindow, Hangup,
158                 DialPhone, QuickDial, Tone, Pulse, FlashHook, FixedPause, WaitTone, User0, User1,
159                 User2, User3, User4, User5, User6, User7, User8, User9, OrigPair, OrigColors,
160                 InitializeColor, InitializePair, SetColorPair, SetForeground, SetBackground,
161                 ChangeCharPitch, ChangeLinePitch, ChangeResHorz, ChangeResVert, DefineChar,
162                 EnterDoublewideMode, EnterDraftQuality, EnterItalicsMode, EnterLeftwardMode,
163                 EnterMicroMode, EnterNearLetterQuality, EnterNormalQuality, EnterShadowMode,
164                 EnterSubscriptMode, EnterSuperscriptMode, EnterUpwardMode, ExitDoublewideMode,
165                 ExitItalicsMode, ExitLeftwardMode, ExitMicroMode, ExitShadowMode, ExitSubscriptMode,
166                 ExitSuperscriptMode, ExitUpwardMode, MicroColumnAddress, MicroDown, MicroLeft,
167                 MicroRight, MicroRowAddress, MicroUp, OrderOfPins, ParmDownMicro, ParmLeftMicro,
168                 ParmRightMicro, ParmUpMicro, SelectCharSet, SetBottomMargin, SetBottomMarginParm,
169                 SetLeftMarginParm, SetRightMarginParm, SetTopMargin, SetTopMarginParm,
170                 StartBitImage, StartCharSetDef, StopBitImage, StopCharSetDef, SubscriptCharacters,
171                 SuperscriptCharacters, TheseCauseCr, ZeroMotion, CharSetNames, KeyMouse, MouseInfo,
172                 ReqMousePos, GetMouse, SetAForeground, SetABackground, PkeyPlab, DeviceType,
173                 CodeSetInit, Set0DesSeq, Set1DesSeq, Set2DesSeq, Set3DesSeq, SetLrMargin,
174                 SetTbMargin, BitImageRepeat, BitImageNewline, BitImageCarriageReturn, ColorNames,
175                 DefineBitImageRegion, EndBitImageRegion, SetColorBand, SetPageLength, DisplayPcChar,
176                 EnterPcCharsetMode, ExitPcCharsetMode, EnterScancodeMode, ExitScancodeMode,
177                 PcTermOptions, ScancodeEscape, AltScancodeEsc, EnterHorizontalHlMode,
178                 EnterLeftHlMode, EnterLowHlMode, EnterRightHlMode, EnterTopHlMode,
179                 EnterVerticalHlMode, SetAAttributes, SetPglenInch, TermcapInit2, TermcapReset,
180                 LinefeedIfNotLf, BackspaceIfNotBs, OtherNonFunctionKeys, ArrowKeyMap, AcsUlcorner,
181                 AcsLlcorner, AcsUrcorner, AcsLrcorner, AcsLtee, AcsRtee, AcsBtee, AcsTtee, AcsHline,
182                 AcsVline, AcsPlus, MemoryLock, MemoryUnlock, BoxChars1 };
183
184             /** \brief String property names
185                 \hideinitializer */
186             static char const * const StringNames[];
187         };
188
189         typedef boost::int16_t number_t; ///< Numeric terminfo property type
190         typedef char const* string_t;   ///< String terminfo property type
191
192         //-////////////////////////////////////////////////////////////////////////
193
194         Terminfo();
195         explicit Terminfo(std::string const & term); ///< Load terminfo entry \a term
196         void load(std::string const & term); ///< Load terminfo entry \a term
197
198         bool getFlag(properties::Boolean p) const; ///< Get boolean property value
199         number_t getNumber(properties::Numeric p) const; ///< Get numeric property value
200         string_t getString(properties::String p) const; ///< Get string property value
201                                         /**< If the property does not exist, 0 is returned */
202         bool hasProperty(properties::Boolean p) const; ///< \c true, if boolean property \a p exists
203         bool hasProperty(properties::Numeric p ) const; ///< \c true, if numeric property \a p exists
204         bool hasProperty(properties::String p ) const; ///< \c true, if string property \a p exists
205
206         std::string formatString(properties::String p,
207                                  number_t arg1=NoValue, number_t arg2=NoValue,
208                                  number_t arg3=NoValue, number_t arg4=NoValue,
209                                  number_t arg5=NoValue, number_t arg6=NoValue,
210                                  number_t arg7=NoValue, number_t arg8=NoValue,
211                                  number_t arg9=NoValue) const;
212                                         ///< Format string property value
213                                         /**< Formats the string property \a p containing special
214                                              terminfo codes. Terminfo supports up to 9 parameters. */
215
216         //-////////////////////////////////////////////////////////////////////////
217
218         void dump(std::ostream & os) const; ///< Dump a description of the terminfo entry
219
220         /** \brief Invalid, incomplete or non-existent terminfo entry exception */
221         struct InvalidTerminfoException : public senf::Exception {
222             InvalidTerminfoException(std::string const & term = "");
223         };
224
225     private:
226         typedef std::vector<bool> BoolVec;
227         typedef std::vector<number_t> NumberVec;
228         typedef std::vector<string_t> StringVec;
229         typedef std::vector<char> StringPool;
230
231         static std::string findTerminfo(std::string const & name);
232         void load(std::istream & is);
233
234         std::string name_;
235         BoolVec booleans_;
236         NumberVec numbers_;
237         StringVec strings_;
238         StringPool stringPool_;
239     };
240
241     /** \brief Parse key escape sequences
242
243         The KeyParser will read the relevant properties from a terminfo entry and then provides
244         functions to parser keyboard escape sequences.
245
246         All keys are returned as keyboard code's. Values 0 to 255 represent ordinary ASCII
247         characters, larger values are special keys taken from the KeyCode \c enum
248
249         \ingroup terminfo_group
250      */
251     class KeyParser
252     {
253     public:
254         //-////////////////////////////////////////////////////////////////////////
255         // Types
256
257         /** \brief Special keyboard key codes */
258         enum KeyCode {
259             Space = ' ', Tab = '\t', Return = '\r', First = 0xE000, Esc = First, Backspace, Backtab,
260             Begin, CATab, CTab, Cancel, Center, Clear, ClearToEOL, ClearToEOS, Close, Command, Copy,
261             Create, Delete, DeleteLine, Down, DownLeft, DownRight, End, Enter, Exit, F0, F1, F2, F3,
262             F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22,
263             F23, F24, F25, F26, F27, F28, F29, F30, F31, F32, F33, F34, F35, F36, F37, F38, F39,
264             F40, F41, F42, F43, F44, F45, F46, F47, F48, F49, F50, F51, F52, F53, F54, F55, F56,
265             F57, F58, F59, F60, F61, F62, F63, Find, Help, Home, Insert, InsertLine, Left, Mark,
266             Message, Mouse, Move, Next, Open, Options, PageDown, PageUp, Previous, Print, Redo,
267             Reference, Refresh, Replace, Restart, Resume, Right, Save, Select, ShiftBegin,
268             ShiftCancel, ShiftCommand, ShiftCopy, ShiftCreate, ShiftDelete, ShiftDeleteLine,
269             ShiftEnd, ShiftClearToEOL, ShiftExit, ShiftFind, ShiftHelp, ShiftHome, ShiftInsert,
270             ShiftLeft, ShiftMessage, ShiftMove, ShiftNext, ShiftOptions, ShiftPrevious, ShiftPrint,
271             ShiftRedo, ShiftReplace, ShiftResume, ShiftRight, ShiftSave, ShiftSuspend, ShiftTab,
272             ShiftUndo, Suspend, Undo, Up, UpLeft, UpRight, Incomplete = 0xE0FF };
273
274         /** \brief Special key code names
275             \hideinitializer */
276         static char const * const KeyNames[];
277
278         typedef wchar_t keycode_t;      ///< Key code data type
279         typedef std::string::size_type size_type; ///< String length type
280
281         /** \brief Helper to convert uppercase char to Control key code */
282         static keycode_t Ctrl(char ch) { return ch-'@'; }
283
284         //-////////////////////////////////////////////////////////////////////////
285
286         KeyParser();
287         explicit KeyParser(Terminfo const & ti); ///< Load keymap information from \a ti
288         void load(Terminfo const & ti); ///< Load keymap information from \a ti
289
290         std::pair<keycode_t, size_type> lookup(std::string const & key) const;
291                                         ///< Lookup up string \a key
292                                         /**< This call will look up the string in \a key in the
293                                              keymap. The return value is a pair.
294                                              \li the first value is the key code
295                                              \li the second value is the number of characters in \a
296                                                  key which have been interpreted and returned in the
297                                                  first value
298
299                                              If \a key is not a complete key sequence, the return
300                                              key code will be the \c Invalid value and the returned
301                                              escape sequence size will be 0.
302
303                                              If \a key does not start with an escape sequence, the
304                                              returned key code will be the first character from \a
305                                              key and the escape sequence size will be 1.
306
307                                              Otherwise \a key starts with a complete escape
308                                              sequence. The returned key code will be a value from
309                                              the KeyCode enum and the escape sequence size will be
310                                              returned accordingly. */
311         static std::string describe(keycode_t key); ///< Return descriptive, printable key name
312
313         void dump(std::ostream & os) const; ///< Dump keymap for debug purposes
314
315     private:
316         typedef std::map<std::string, KeyCode> Keytable;
317
318         Keytable table_;
319     };
320
321 }}
322
323 //-/////////////////////////////////////////////////////////////////////////////////////////////////
324 //#include "Terminfo.cci"
325 //#include "Terminfo.ct"
326 //#include "Terminfo.cti"
327 #endif
328
329 \f
330 // Local Variables:
331 // mode: c++
332 // fill-column: 100
333 // comment-column: 40
334 // c-file-style: "senf"
335 // indent-tabs-mode: nil
336 // ispell-local-dictionary: "american"
337 // compile-command: "scons -u test"
338 // End: