summaryrefslogtreecommitdiff
path: root/src/window.h
blob: 7893e86c94055963c336a314c0d95c5076a562d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
/***************************************************************************
 *   Copyright (C) 2008-2012 by Andrzej Rybczak                            *
 *   electricityispower@gmail.com                                          *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.              *
 ***************************************************************************/

#ifndef _WINDOW_H
#define _WINDOW_H

#include "config.h"

#ifdef USE_PDCURSES
# define NCURSES_MOUSE_VERSION 1
#endif

#include "curses.h"
#include "gcc.h"

#include <functional>
#include <list>
#include <stack>
#include <vector>
#include <string>
#include <queue>

// define some Ctrl-? keys
#define KEY_CTRL_A 1
#define KEY_CTRL_B 2
#define KEY_CTRL_C 3
#define KEY_CTRL_D 4
#define KEY_CTRL_E 5
#define KEY_CTRL_F 6
#define KEY_CTRL_G 7
#define KEY_CTRL_H 8
#define KEY_CTRL_I 9
#define KEY_CTRL_J 10
#define KEY_CTRL_K 11
#define KEY_CTRL_L 12
#define KEY_CTRL_M 13
#define KEY_CTRL_N 14
#define KEY_CTRL_O 15
#define KEY_CTRL_P 16
#define KEY_CTRL_Q 17
#define KEY_CTRL_R 18
#define KEY_CTRL_S 19
#define KEY_CTRL_T 20
#define KEY_CTRL_U 21
#define KEY_CTRL_V 22
#define KEY_CTRL_W 23
#define KEY_CTRL_X 24
#define KEY_CTRL_Y 25
#define KEY_CTRL_Z 26

// define F? keys
#define KEY_F1 265
#define KEY_F2 266
#define KEY_F3 267
#define KEY_F4 268
#define KEY_F5 269
#define KEY_F6 270
#define KEY_F7 271
#define KEY_F8 272
#define KEY_F9 273
#define KEY_F10 274
#define KEY_F11 275
#define KEY_F12 276

// other handy keys
#define KEY_SHIFT_TAB 353
#define KEY_SPACE 32
#define KEY_TAB 9

// define alternative KEY_BACKSPACE (used in some terminal emulators)
#define KEY_BACKSPACE_2 127

// KEY_ENTER is 343, which doesn't make any sense. This makes it useful.
#undef KEY_ENTER
#define KEY_ENTER 10

// undefine scroll macro as it collides with Window::scroll
#undef scroll

#ifndef USE_PDCURSES
// NOTICE: redefine BUTTON2_PRESSED as it doesn't always work, I noticed
// that it sometimes returns 134217728 (2^27) instead of expected mask, so the
// modified define does it right but is rather experimental.
# undef BUTTON2_PRESSED
# define BUTTON2_PRESSED (NCURSES_MOUSE_MASK(2, NCURSES_BUTTON_PRESSED) | (1U << 27))
#endif // USE_PDCURSES

// workaraund for win32
#ifdef WIN32
# define wcwidth(x) int(!iscntrl(x))
#endif

/// NC namespace provides set of easy-to-use
/// wrappers over original curses library
namespace NC {//

/// Colors used by NCurses
enum Color { clDefault, clBlack, clRed, clGreen, clYellow, clBlue, clMagenta, clCyan, clWhite, clEnd };

/// Format flags used by NCurses
enum Format {
	fmtNone = clEnd+1,
	fmtBold, fmtBoldEnd,
	fmtUnderline, fmtUnderlineEnd,
	fmtReverse, fmtReverseEnd,
	fmtAltCharset, fmtAltCharsetEnd
};

/// Available border colors for window
enum Border { brNone, brBlack, brRed, brGreen, brYellow, brBlue, brMagenta, brCyan, brWhite };

/// This indicates how much the window has to be scrolled
enum Where { wUp, wDown, wPageUp, wPageDown, wHome, wEnd };

/// Helper function that is invoked each time one will want
/// to obtain string from Window::getString() function
/// @see Window::getString()
typedef std::function<bool(const std::wstring &)> GetStringHelper;

/// Initializes curses screen and sets some additional attributes
/// @param window_title title of the window (has an effect only if pdcurses lib is used)
/// @param enable_colors enables colors
void initScreen(const char *window_title, bool enable_colors);

/// Destroys the screen
void destroyScreen();

/// Struct used to set color of both foreground and background of window
/// @see Window::operator<<()
struct Colors
{
	Colors(Color one, Color two = clDefault) : fg(one), bg(two) { }
	Color fg;
	Color bg;
};

/// Struct used for going to given coordinates
/// @see Window::operator<<()
struct XY
{
	XY(int xx, int yy) : x(xx), y(yy) { }
	int x;
	int y;
};

/// Main class of NCurses namespace, used as base for other specialized windows
struct Window
{
	Window() : m_window(0), m_border_window(0), m_history(0) { }
	
	/// Constructs an empty window with given parameters
	/// @param startx X position of left upper corner of constructed window
	/// @param starty Y position of left upper corner of constructed window
	/// @param width width of constructed window
	/// @param height height of constructed window
	/// @param title title of constructed window
	/// @param color base color of constructed window
	/// @param border border of constructed window
	Window(size_t startx, size_t starty, size_t width, size_t height,
			const std::string &title, Color color, Border border);
	
	Window(const Window &rhs);
	Window(Window &&rhs);
	Window &operator=(Window w);
	
	virtual ~Window();
	
	/// Allows for direct access to internal WINDOW pointer in case there
	/// is no wrapper for a function from curses library one may want to use
	/// @return internal WINDOW pointer
	WINDOW *raw() const { return m_window; }
	
	/// @return window's width
	size_t getWidth() const;
	
	/// @return window's height
	size_t getHeight() const;
	
	/// @return X position of left upper window's corner
	size_t getStartX() const;
	
	/// @return Y position of left upper window's corner
	size_t getStarty() const;
	
	/// @return window's title
	const std::string &getTitle() const;
	
	/// @return current window's color
	Color getColor() const;
	
	/// @return current window's border
	Border getBorder() const;
	
	/// @return current window's timeout
	int getTimeout() const;
	
	/// Reads the string from standard input. Note that this is much more complex
	/// function than getstr() from curses library. It allows for moving through
	/// letters with arrows, supports scrolling if string's length is bigger than
	/// given area, supports history of previous strings and each time it receives
	/// an input from the keyboard or the timeout is reached, it calls helper function
	/// (if it's set) that takes as an argument currently edited string.
	/// @param base base string that has to be edited
	/// @param length max length of string, unlimited by default
	/// @param width width of area that entry field can take. if it's reached, string
	/// will be scrolled. if value is 0, field will be from cursor position to the end
	/// of current line wide.
	/// @param encrypted if set to true, '*' characters will be displayed instead of
	/// actual text.
	/// @return edited string
	///
	/// @see setGetStringHelper()
	/// @see SetTimeout()
	/// @see CreateHistory()
	std::string getString(const std::string &base, size_t length_ = -1,
	                      size_t width = 0, bool encrypted = 0);
	
	/// Wrapper for above function that doesn't take base string (it will be empty).
	/// Taken parameters are the same as for above.
	std::string getString(size_t length_ = -1, size_t width = 0, bool encrypted = 0)
	{
		return getString("", length_, width, encrypted);
	}
	
	/// Moves cursor to given coordinates
	/// @param x given X position
	/// @param y given Y position
	void goToXY(int x, int y);
	
	/// @return x window coordinate
	int getX();
	
	/// @return y windows coordinate
	int getY();
	
	/// Used to indicate whether given coordinates of main screen lies within
	/// window area or not and if they do, transform them into in-window coords.
	/// Otherwise function doesn't modify its arguments.
	/// @param x X position of main screen to be checked
	/// @param y Y position of main screen to be checked
	/// @return true if it transformed variables, false otherwise
	bool hasCoords(int &x, int &y);
	
	/// Sets helper function used in getString()
	/// @param helper pointer to function that matches getStringHelper prototype
	/// @see getString()
	void setGetStringHelper(GetStringHelper helper) { m_get_string_helper = helper; }
	
	/// Sets window's base color
	/// @param fg foregound base color
	/// @param bg background base color
	void setBaseColor(Color fg, Color bg = clDefault);
	
	/// Sets window's border
	/// @param border new window's border
	void setBorder(Border border);
	
	/// Sets window's timeout
	/// @param timeout window's timeout
	void setTimeout(int timeout);
	
	/// Sets window's title
	/// @param new_title new title for window
	void setTitle(const std::string &new_title);
	
	/// Creates internal container that stores all previous
	/// strings that were edited using this window.
	void createHistory();
	
	/// Deletes container with all previous history entries
	void deleteHistory();
	
	/// Refreshed whole window and its border
	/// @see refresh()
	void display();
	
	/// Refreshes whole window, but not the border
	/// @see display()
	virtual void refresh();
	
	/// Moves the window to new coordinates
	/// @param new_x new X position of left upper corner of window
	/// @param new_y new Y position of left upper corner of window
	virtual void moveTo(size_t new_x, size_t new_y);
	
	/// Resizes the window
	/// @param new_width new window's width
	/// @param new_height new window's height
	virtual void resize(size_t new_width, size_t new_height);
	
	/// Cleares the window
	virtual void clear();
	
	/// Adds given file descriptor to the list that will be polled in
	/// ReadKey() along with stdin and callback that will be invoked
	/// when there is data waiting for reading in it
	/// @param fd file descriptor
	/// @param callback callback
	void addFDCallback(int fd, void (*callback)());
	
	/// Clears list of file descriptors and their callbacks
	void clearFDCallbacksList();
	
	/// Checks if list of file descriptors is empty
	/// @return true if list is empty, false otherwise
	bool FDCallbacksListEmpty() const;
	
	/// Reads key from standard input (or takes it from input queue)
	/// and writes it into read_key variable
	int readKey();
	
	/// Push single character into input queue, so it can get consumed by ReadKey
	void pushChar(int ch);
	
	/// @return const reference to internal input queue
	const std::queue<int> &inputQueue() { return m_input_queue; }
	
	/// Scrolls the window by amount of lines given in its parameter
	/// @param where indicates how many lines it has to scroll
	virtual void scroll(Where where);
	
	/// Applies function of compatible prototype to internal WINDOW pointer
	/// The mostly used function in this case seem to be wclrtoeol(), which
	/// clears the window from current cursor position to the end of line.
	/// Note that delwin() also matches that prototype, but I wouldn't
	/// recommend anyone passing this pointer here ;)
	/// @param f pointer to function to call with internal WINDOW pointer
	/// @return reference to itself
	Window &operator<<(int (*f)(WINDOW *));
	
	/// Applies foreground and background colors to window
	/// @param colors struct that holds new colors information
	/// @return reference to itself
	Window &operator<<(Colors colors);
	
	/// Applies foregound color to window. Note that colors applied
	/// that way are stacked, i.e if you applied clRed, then clGreen
	/// and clEnd, current color would be clRed. If you want to discard
	/// all colors and fall back to base one, pass clDefault.
	/// @param color new color value
	/// @return reference to itself
	Window &operator<<(Color color);
	
	/// Applies format flag to window. Note that these attributes are
	/// also stacked, so if you applied fmtBold twice, to get rid of
	/// it you have to pass fmtBoldEnd also twice.
	/// @param format format flag
	/// @return reference to itself
	Window &operator<<(Format format);
	
	/// Moves current cursor position to given coordinates.
	/// @param coords struct that holds information about new coordinations
	/// @return reference to itself
	Window &operator<<(XY coords);
	
	/// Prints string to window
	/// @param s const pointer to char array to be printed
	/// @return reference to itself
	Window &operator<<(const char *s);
	
	/// Prints single character to window
	/// @param c character to be printed
	/// @return reference to itself
	Window &operator<<(char c);
	
	/// Prints wide string to window
	/// @param ws const pointer to wchar_t array to be printed
	/// @return reference to itself
	Window &operator<<(const wchar_t *ws);
	
	/// Prints single wide character to window
	/// @param wc wide character to be printed
	/// @return reference to itself
	Window &operator<<(wchar_t wc);
	
	/// Prints int to window
	/// @param i integer value to be printed
	/// @return reference to itself
	Window &operator<<(int i);
	
	/// Prints double to window
	/// @param d double value to be printed
	/// @return reference to itself
	Window &operator<<(double d);
	
	/// Prints size_t to window
	/// @param s size value to be printed
	/// @return reference to itself
	Window &operator<<(size_t s);
	
	/// Prints std::string to window
	/// @param s string to be printed
	/// @return reference to itself
	Window &operator<<(const std::string &s);
	
	/// Prints std::wstring to window
	/// @param ws wide string to be printed
	/// @return reference to itself
	Window &operator<<(const std::wstring &ws);
protected:
	/// Sets colors of window (interal use only)
	/// @param fg foregound color
	/// @param bg background color
	///
	void setColor(Color fg, Color bg = clDefault);
	
	/// Refreshes window's border
	///
	void showBorder() const;
	
	/// Changes dimensions of window, called from resize()
	/// @param width new window's width
	/// @param height new window's height
	/// @see resize()
	///
	void adjustDimensions(size_t width, size_t height);
	
	/// Deletes old window and creates new. It's called by resize(),
	/// SetBorder() or setTitle() since internally windows are
	/// handled as curses pads and change in size requires to delete
	/// them and create again, there is no way to change size of pad.
	/// @see SetBorder()
	/// @see setTitle()
	/// @see resize()
	///
	virtual void recreate(size_t width, size_t height);
	
	/// internal WINDOW pointers
	WINDOW *m_window;
	WINDOW *m_border_window;
	
	/// start points and dimensions
	size_t m_start_x;
	size_t m_start_y;
	size_t m_width;
	size_t m_height;
	
	/// window timeout
	int m_window_timeout;
	
	/// current colors
	Color m_color;
	Color m_bg_color;
	
	/// base colors
	Color m_base_color;
	Color m_base_bg_color;
	
	/// current border
	Border m_border;
	
private:
	/// Sets state of bold attribute (internal use only)
	/// @param bold_state state of bold attribute
	///
	void bold(bool bold_state) const;
	
	/// Sets state of underline attribute (internal use only)
	/// @param underline_state state of underline attribute
	///
	void underline(bool underline_state) const;
	
	/// Sets state of reverse attribute (internal use only)
	/// @param reverse_state state of reverse attribute
	///
	void reverse(bool reverse_state) const;
	
	/// Sets state of altcharset attribute (internal use only)
	/// @param altcharset_state state of altcharset attribute
	///
	void altCharset(bool altcharset_state) const;
	
	/// pointer to helper function used by getString()
	/// @see getString()
	///
	GetStringHelper m_get_string_helper;
	
	/// window title
	std::string m_title;
	
	/// stack of colors
	std::stack<Colors> m_color_stack;
	
	/// input queue of a window. you can put characters there using
	/// PushChar and they will be immediately consumed and
	/// returned by ReadKey
	std::queue<int> m_input_queue;
	
	/// containter used for additional file descriptors that have
	/// to be polled in ReadKey() and correspondent callbacks that
	/// are invoked if there is data available in them
	typedef std::vector< std::pair<int, void (*)()> > FDCallbacks;
	FDCallbacks m_fds;
	
	/// pointer to container used as history
	std::list<std::wstring> *m_history;
	
	/// counters for format flags
	int m_bold_counter;
	int m_underline_counter;
	int m_reverse_counter;
	int m_alt_charset_counter;
};

}

#endif