1 /*
2 ** Copyright 2002-2011, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 
7 #ifndef cursesfield_H
8 #define cursesfield_H
9 
10 #include "mycurses.H"
11 #include "cursesflowedline.H"
12 #include <wchar.h>
13 #include <vector>
14 
15 ///////////////////////////////////////////////////////////////////////////
16 //
17 // An editable field.
18 //
19 
20 class CursesField : public Curses {
21 
22 	editablewidechar text;		// Editable text.
23 
24 	void getbeforeafter(widecharbuf &, widecharbuf &);
25 
26 	void setselectpos();
27 
28 	size_t width;			// Field width
29 	size_t maxlength;		// Maximum text length
30 
31 	size_t shiftoffset;		// First text char shown
32 	size_t selectpos;		// Start of selection position
33 
34 	char32_t passwordChar;	// password overlay character
35 	bool yesnoField;		// True if yes/no field.
36 
37 	std::u32string optionField; // One character list of options
38 
39 	std::vector<std::pair<std::string, std::string> > optionHelp; // Option help keys
40 	// This field is of primary use by cursesstatusbar
41 
42 	bool isUnderlined;
43 protected:
44 	Curses::CursesAttr attribute;
45 public:
46 	static std::u32string yesKeys, noKeys;
47 	static char32_t yankKey, clrEolKey;
48 
49 	static std::list<CursesFlowedLine> cutBuffer; // for cut/paste.
50 
51 	CursesField(CursesContainer *parent,
52 		    size_t widthArg=20,
53 		    size_t maxlengthArg=255,
54 		    std::string initValue="");
55 	~CursesField();
56 
setUnderlined(bool flag)57 	void setUnderlined(bool flag) { isUnderlined=flag; }
58 	void setRow(int row);
59 	void setCol(int col);
60 	void setText(std::string textArg);
61 	void setAttribute(Curses::CursesAttr attr);
62 	void setCursorPos(size_t o);
63 	std::string getText() const;	// Return entered text
64 
65 	int getWidth() const;		// Our width is known
66 	int getHeight() const;		// We're one row high
67 
68 	void setWidth(int);
69 
70 	void setPasswordChar(char32_t ch='*') { passwordChar=ch; }
setYesNo()71 	void setYesNo() { yesnoField=true; }
setOptionField(const std::u32string & vec)72 	void setOptionField(const std::u32string &vec)
73 	{
74 		optionField=vec;
75 	}
76 
77 	void setOptionHelp(const std::vector< std::pair<std::string, std::string> > &help);
78 
getOptionHelp()79 	const std::vector< std::pair<std::string, std::string> > &getOptionHelp() const
80 	{
81 		return optionHelp;
82 	}
83 
84 	void draw();
85 
86 	int getCursorPosition(int &row, int &col);
87 	bool processKeyInFocus(const Key &key);
88 
89 	bool isFocusable();	// Yes we are
90 	void focusGained();	// Select old text automatically at entry.
91 	void focusLost();	// Unselect any selected text at exit.
92 
93 	void erase();
94 private:
95 	void left();
96 	void right();
97 };
98 
99 //////////////////////////////////////////////////////////////////////////
100 //
101 // Instead of subclassing a CursesField, provide a template to make it easier
102 // to have CursesField be a member of another object.  Typical usage:
103 //
104 // class X {
105 //
106 //    CursesFieldRedirect<X> field1;
107 //    CursesFieldRedirect<X> field2;
108 //
109 //    void field1Enter(); // ENTER key pressed in field1
110 //    void field2Enter(); // ENTER key pressed in field2
111 //
112 // };
113 //
114 //
115 // X::X()
116 // {
117 //
118 //       field1=this;
119 //       field2=this;
120 //
121 //       field1= &X::field1Enter;
122 //       field2= &X::field2Enter;
123 // }
124 //
125 
126 template<class T> class CursesFieldRedirect : public CursesField {
127 
128 public:
129 	T *myClass;
130 	void (T::*myMethod)(void);
131 
132 	CursesFieldRedirect(CursesContainer *parent,
133 			    size_t widthArg=20,
134 			    size_t maxlengthArg=255,
135 			    std::string initValue="")
CursesField(parent,widthArg,maxlengthArg,initValue)136 		: CursesField(parent, widthArg, maxlengthArg, initValue),
137 		  myClass(0), myMethod(0)
138 	{
139 	}
140 
~CursesFieldRedirect()141 	~CursesFieldRedirect()
142 	{
143 	}
144 
145 	void operator=(T *p) { myClass=p; }
146 	void operator=( void (T::*p)(void) ) { myMethod=p; }
147 
processKeyInFocus(const Key & key)148 	bool processKeyInFocus(const Key &key)
149 	{
150 		if (key == Key::ENTER && myClass && myMethod)
151 		{
152 			(myClass->*myMethod)();
153 			return true;
154 		}
155 
156 		return CursesField::processKeyInFocus(key);
157 	}
158 };
159 
160 #endif
161