1 /*
2     This file is part of Kismet
3 
4     Kismet is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     Kismet is distributed in the hope that it will be useful,
10       but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with Kismet; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 
19 #ifndef __KIS_PANEL_WIDGETS_H__
20 #define __KIS_PANEL_WIDGETS_H__
21 
22 #include "config.h"
23 
24 // Panel has to be here to pass configure, so just test these
25 #if (defined(HAVE_LIBNCURSES) || defined (HAVE_LIBCURSES))
26 
27 #ifdef HAVE_LIBCURSES
28 #include <curses.h>
29 #else
30 #include <ncurses.h>
31 #endif
32 #include <panel.h>
33 #undef erase
34 #undef clear
35 #undef move
36 
37 #include <stdio.h>
38 #include <string>
39 #include <vector>
40 #include <list>
41 
42 #include "pollable.h"
43 #include "messagebus.h"
44 
45 // Some standard filters we'd use on input
46 #define FILTER_ALPHA   	"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
47 	"abcdefghijklmnopqrstuvwxyz" \
48 	"0123456789"
49 #define FILTER_NUM      "0123456789"
50 #define FILTER_ALPHANUM	FILTER_ALPHA FILTER_NUM " "
51 #define FILTER_ALPHANUMSYM FILTER_ALPHA FILTER_NUM \
52 	" .,~!@#$%^&*()_-+/\\:="
53 
54 class Kis_Panel;
55 class KisPanelInterface;
56 
57 // Functor-style handler for special text.  Provides an alternate to the
58 // printstr mvwaddnstr which does color and type formating.
59 //
60 // Special string formatting:
61 // \s .. \S  - Standout
62 // \u .. \U  - Underline
63 // \r .. \R  - Reverse
64 // \d .. \D  - Dim
65 // \b .. \B  - Bold
66 class Kis_Panel_Specialtext {
67 public:
68 	static void Mvwaddnstr(WINDOW *win, int y, int x, string str, int n,
69 						   Kis_Panel *panel, int colorpair = 0);
70 	static unsigned int Strlen(string str);
71 };
72 
73 class Kis_Panel_Color {
74 public:
75 	Kis_Panel_Color();
76 
77 	int AddColor(string color, string pref);
78 
79 	// Remap all instances using a color
80 	void RemapAllColors(string oldcolor, string newcolor, ConfigFile *conf);
81 
82 	struct color_rec {
83 		string pref;
84 		string color[2];
85 		int colorindex;
86 	};
87 protected:
88 	int nextindex;
89 	map<string, Kis_Panel_Color::color_rec> color_index_map;
90 };
91 
92 // Callback parameters - the component that activated, the status/return
93 // code it activated with (retval from mouse/kb event)
94 #define COMPONENT_CALLBACK_PARMS Kis_Panel_Component *component, int status, \
95 	void *aux, GlobalRegistry *globalreg
96 // Component is now active (most things won't need to use this since it ought
97 // to be handled by the panel level key/mouse handlers
98 #define COMPONENT_CBTYPE_SWITCH		0
99 // Component was activated - for whatever activated means for that widget.
100 // Text fields would return activated on enter, buttons on click/enter,
101 // etc.
102 #define COMPONENT_CBTYPE_ACTIVATED	1
103 
104 // Basic component super-class that handles drawing a group of items of
105 // some sort
106 class Kis_Panel_Component {
107 public:
Kis_Panel_Component()108 	Kis_Panel_Component() {
109 		fprintf(stderr, "FATAL OOPS:  Component called without globalreg\n");
110 		exit(1);
111 	}
112 
113 	Kis_Panel_Component(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
~Kis_Panel_Component()114 	virtual ~Kis_Panel_Component() { };
115 
116 	// Show/hide
Show()117 	virtual void Show() {
118 		if (visible == 0)
119 			layout_dirty = 1;
120 		visible = 1;
121 	}
Hide()122 	virtual void Hide() {
123 		if (visible)
124 			layout_dirty = 1;
125 		visible = 0;
126 	}
127 
GetVisible()128 	virtual int GetVisible() {
129 		return visible;
130 	}
131 
SetName(string in_name)132 	virtual void SetName(string in_name) {
133 		name = in_name;
134 	}
135 
GetName()136 	virtual string GetName() {
137 		return name;
138 	}
139 
Debug()140 	virtual void Debug() {
141 		fprintf(stderr, "debug - widget %p sx %d sy %d ex %d ey %d lx %d "
142 				"ly %d px %d py %d\n", this, sx, sy, ex, ey, lx, ly, px, py);
143 	}
144 
145 	// Set the position inside a window (start x, y, and width, height)
SetPosition(int isx,int isy,int iex,int iey)146 	virtual void SetPosition(int isx, int isy, int iex, int iey) {
147 		sx = isx;
148 		sy = isy;
149 		ex = iex;
150 		ey = iey;
151 		lx = ex - sx;
152 		ly = ey - sy;
153 		layout_dirty = 1;
154 	}
155 
SetPreferredSize(int ipx,int ipy)156 	virtual void SetPreferredSize(int ipx, int ipy) {
157 		px = ipx;
158 		py = ipy;
159 		layout_dirty = 1;
160 	}
161 
SetMinSize(int imx,int imy)162 	virtual void SetMinSize(int imx, int imy) {
163 		mx = imx;
164 		my = imy;
165 		layout_dirty = 1;
166 	}
167 
GetMinX()168 	virtual int GetMinX() {
169 		return mx;
170 	}
171 
GetMinY()172 	virtual int GetMinY() {
173 		return my;
174 	}
175 
GetPrefX()176 	virtual int GetPrefX() {
177 		return px;
178 	}
179 
GetPrefY()180 	virtual int GetPrefY() {
181 		return py;
182 	}
183 
GetLayoutDirty()184 	virtual int GetLayoutDirty() {
185 		return layout_dirty;
186 	}
187 
SetLayoutDirty(int d)188 	virtual void SetLayoutDirty(int d) {
189 		layout_dirty = d;
190 	}
191 
192 	// Draw the component
193 	virtual void DrawComponent() = 0;
194 	// Activate the component (and target a specific sub-component if we have
195 	// some reason to, like a specific menu)
Activate(int subcomponent)196 	virtual void Activate(int subcomponent) {
197 		active = 1;
198 
199 		if (cb_switch != NULL)
200 			(*cb_switch)(this, 1, cb_switch_aux, globalreg);
201 	}
202 
203 	// Deactivate the component (this could cause closing of a menu, for example)
Deactivate()204 	virtual void Deactivate() {
205 		active = 0;
206 
207 		if (cb_switch != NULL)
208 			(*cb_switch)(this, 0, cb_switch_aux, globalreg);
209 	}
210 
211 	// Handle a key press
212 	virtual int KeyPress(int in_key) = 0;
213 
214 	// Handle a mouse event (default: Ignore)
MouseEvent(MEVENT * mevent)215 	virtual int MouseEvent(MEVENT *mevent) {
216 		return 0;
217 	}
218 
219 	virtual void SetCallback(int cbtype, int (*cb)(COMPONENT_CALLBACK_PARMS),
220 							 void *aux);
221 	virtual void ClearCallback(int cbtype);
222 
SetColorPrefs(string in_active,string in_inactive)223 	virtual void SetColorPrefs(string in_active, string in_inactive) {
224 		color_active_pref = in_active;
225 		color_inactive_pref = in_inactive;
226 	}
227 
228 protected:
229 	// Silly function to pick the right color - give it the color you want,
230 	// and it gives you the inactive color if the widget is inactive
SetTransColor(int want_color)231 	inline int SetTransColor(int want_color) {
232 		if (active) {
233 			wattrset(window, want_color);
234 			return want_color;
235 		} else {
236 			wattrset(window, color_inactive);
237 			return color_inactive;
238 		}
239 	}
240 
241 	GlobalRegistry *globalreg;
242 
243 	// Primary colors
244 	int color_active;
245 	int color_inactive;
246 
247 	string color_active_pref, color_inactive_pref;
248 
249 	// Callbacks
250 	int (*cb_switch)(COMPONENT_CALLBACK_PARMS);
251 	void *cb_switch_aux;
252 
253 	int (*cb_activate)(COMPONENT_CALLBACK_PARMS);
254 	void *cb_activate_aux;
255 
256 	// Are we even visible?
257 	int visible;
258 
259 	// Panel we're in
260 	Kis_Panel *parent_panel;
261 
262 	// Widow we render to
263 	WINDOW *window;
264 
265 	// Position within the window (start xy, size xy)
266 	int sx, sy, ex, ey, lx, ly, mx, my, px, py;
267 
268 	int layout_dirty;
269 
270 	// Are we active?
271 	int active;
272 
273 	// Name
274 	string name;
275 };
276 
277 class Kis_Panel_Packbox : public Kis_Panel_Component {
278 public:
279 	class packbox_details {
280 	public:
281 		Kis_Panel_Component *widget;
282 		int fill;
283 		int padding;
284 	};
285 
Kis_Panel_Packbox()286 	Kis_Panel_Packbox() {
287 		fprintf(stderr, "FATAL OOPS: Kis_Panel_Packbox() called\n");
288 		exit(1);
289 	}
290 
291 	Kis_Panel_Packbox(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
292 	virtual ~Kis_Panel_Packbox();
293 
294 	// Pack to head, end, before or after a named item, or remove from the pack list
295 	virtual void Pack_Start(Kis_Panel_Component *in_widget, int fill, int padding);
296 	virtual void Pack_End(Kis_Panel_Component *in_widget, int in_fill, int padding);
297 
298 	virtual void Pack_Before_Named(string in_name, Kis_Panel_Component *in_widget,
299 								   int fill, int padding);
300 	virtual void Pack_After_Named(string in_name, Kis_Panel_Component *in_widget,
301 								  int fill, int padding);
302 
303 	virtual void Pack_Remove(Kis_Panel_Component *in_widget);
304 
305 	// Homogenous spacing (all elements fit in the same size)
SetHomogenous(int in_homog)306 	virtual void SetHomogenous(int in_homog) {
307 		homogenous = in_homog;
308 		layout_dirty = 1;
309 	}
310 
311 	// Set the spacing between elements (but not trailing): WWWSWWW
SetSpacing(int in_space)312 	virtual void SetSpacing(int in_space) {
313 		spacing = in_space;
314 		layout_dirty = 1;
315 	}
316 
SetCenter(int in_cent)317 	virtual void SetCenter(int in_cent) {
318 		center = in_cent;
319 		layout_dirty = 1;
320 	}
321 
322 	// Are we packing vertical or horizontal?
SetPackH()323 	virtual void SetPackH() {
324 		packing = 0;
325 		layout_dirty = 1;
326 	}
327 
SetPackV()328 	virtual void SetPackV() {
329 		packing = 1;
330 		layout_dirty = 1;
331 	}
332 
KeyPress(int in_key)333 	virtual int KeyPress(int in_key) {
334 		return -1;
335 	}
336 
337 	virtual int GetVisible();
338 
339 	virtual void DrawComponent();
340 
341 protected:
342 	list<Kis_Panel_Packbox::packbox_details> packed_items;
343 
344 	virtual void Pack_Widgets();
345 
346 	int homogenous, packing, spacing, center;
347 };
348 
349 #define MENUITEM_CB_PARMS	GlobalRegistry *globalreg, int menuitem, void *auxptr
350 typedef void (*kis_menuitem_cb)(MENUITEM_CB_PARMS);
351 
352 class Kis_Menu : public Kis_Panel_Component {
353 public:
Kis_Menu()354 	Kis_Menu() {
355 		fprintf(stderr, "FATAL OOPS: Kis_Menu called without globalreg\n");
356 		exit(1);
357 	}
358 	Kis_Menu(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
359 	virtual ~Kis_Menu();
360 
361 	// Refresh drawing the menu bar in its current state
362 	virtual void DrawComponent();
363 
364 	// Activate a specific menu (using the #*100+item scheme)
365 	virtual void Activate(int subcomponent);
366 	virtual void Deactivate();
367 
368 	// menu# * 100 + item#
369 	virtual int KeyPress(int in_key);
370 	virtual int MouseEvent(MEVENT *mevent);
371 
372 	// Add a menu & the hilighted character offset
373 	virtual int AddMenu(string in_text, int targ_char);
374 	// We can't delete, but we can hide a menu
375 	virtual void SetMenuVis(int in_menu, int in_vis);
376 
377 	// Add an item to a menu ID
378 	virtual int AddMenuItem(string in_text, int menuid, char extra);
379 	// Add a submenu item to a menu ID, returns a menu we can add things
380 	// to for them to show up in the submenu
381 	virtual int AddSubMenuItem(string in_text, int menuid, char extra);
382 	// Set an item checkable
383 	virtual void SetMenuItemChecked(int in_item, int in_checked);
384 	// We can't delete, again, but we can hide
385 	virtual void SetMenuItemVis(int in_item, int in_vis);
386 
387 	// Set a menu color
388 	virtual void SetMenuItemColor(int in_item, string in_color);
389 
390 	// Set a menu item symbol (radio vs check vs ...)
391 	virtual void SetMenuItemCheckSymbol(int in_item, char in_symbol);
392 
393 	// Set a menu item callback
394 	virtual void SetMenuItemCallback(int in_item, kis_menuitem_cb in_cb, void *in_aux);
395 	virtual void ClearMenuItemCallback(int in_item);
396 
397 	virtual int FindMenu(string in_menu);
398 
399 	// Delete all the menus
400 	virtual void ClearMenus();
401 
402 	virtual void EnableMenuItem(int in_item);
403 	virtual void DisableMenuItem(int in_item);
404 
405 	virtual void EnableAllItems(int in_menu);
406 	virtual void DisableAllItems(int in_menu);
407 
408 	struct _menuitem {
409 		int parentmenu;
410 		string text;
411 		char extrachar;
412 		int id;
413 		int enabled;
414 		int submenu;
415 		int visible;
416 		int checked;
417 		int colorpair;
418 		char checksymbol;
419 
420 		kis_menuitem_cb callback;
421 		void *auxptr;
422 	};
423 
424 	struct _menu {
425 		string text;
426 		int targchar;
427 		vector<Kis_Menu::_menuitem *> items;
428 		int width;
429 		int id;
430 		int submenu;
431 		int visible;
432 		int checked;
433 	};
434 
435 protected:
436 	// Menu helper window
437 	WINDOW *menuwin;
438 	WINDOW *submenuwin;
439 	// Menu bar
440 	vector<Kis_Menu::_menu *> menubar;
441 	// Selected items...  When a sub menu is selected, the current menu gets put
442 	// into the sub menu record, and operations continue on the current menu.
443 	// Draw ops treat cur and sub as both "active" menus
444 	int cur_menu;
445 	int cur_item;
446 	int sub_menu;
447 	int sub_item;
448 	int mouse_triggered;
449 
450 	int text_color, border_color, disable_color;
451 
452 	virtual void FindNextEnabledItem();
453 	virtual void FindPrevEnabledItem();
454 
455 	virtual void DrawMenu(_menu *menu, WINDOW *win, int hpos, int vpos);
456 };
457 
458 // TODO - fix this.  Pop menus don't quite work right yet
459 class Kis_Pop_Menu : public Kis_Menu {
460 public:
Kis_Pop_Menu()461 	Kis_Pop_Menu() {
462 		fprintf(stderr, "FATAL OOPS: Kis_Pop_Menu called without globalreg\n");
463 		exit(1);
464 	}
465 	Kis_Pop_Menu(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
466 	virtual ~Kis_Pop_Menu();
467 
468 	virtual int KeyPress(int in_key);
469 	virtual void DrawComponent();
470 protected:
471 	virtual void DrawMenu(_menu *menu, WINDOW *win, int hpos, int vpos);
472 };
473 
474 // A scrollable list of fields
475 class Kis_Field_List : public Kis_Panel_Component {
476 public:
Kis_Field_List()477 	Kis_Field_List() {
478 		fprintf(stderr, "FATAL OOPS: Kis_Field_List called without globalreg\n");
479 		exit(1);
480 	}
481 	Kis_Field_List(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
482 	virtual ~Kis_Field_List();
483 
484 	virtual void DrawComponent();
485 
486 	virtual int KeyPress(int in_key);
487 
488 	// Add a row
489 	virtual int AddData(string in_field, string in_data);
490 	virtual int ModData(unsigned int in_row, string in_field, string in_data);
491 
492 protected:
493 	// Data
494 	vector<string> field_vec;
495 	vector<string> data_vec;
496 
497 	// Width of field column and scrolling position
498 	unsigned int field_w;
499 	int scroll_pos;
500 };
501 
502 // A scrollable freetext field
503 class Kis_Free_Text : public Kis_Panel_Component {
504 public:
Kis_Free_Text()505 	Kis_Free_Text() {
506 		fprintf(stderr, "FATAL OOPS: Kis_Free_Text() called w/out globalreg\n");
507 		exit(1);
508 	}
509 	Kis_Free_Text(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
510 	virtual ~Kis_Free_Text();
511 
512 	virtual void DrawComponent();
513 
514 	virtual int KeyPress(int in_key);
515 
516 	virtual void SetText(string in_text);
517 	virtual void SetText(vector<string> in_text);
GetText()518 	virtual vector<string> GetText() {
519 		return text_vec;
520 	}
521 	virtual void AppendText(string in_text);
SetMaxText(int in_max)522 	virtual void SetMaxText(int in_max) { max_text = in_max; }
523 
524 	// Follow the end of the text unless we're scrolled differently
SetFollowTail(int in_set)525 	virtual void SetFollowTail(int in_set) {
526 		follow_tail = in_set;
527 	}
528 
SetAlignment(int in_alignment)529 	virtual void SetAlignment(int in_alignment) {
530 		alignment = in_alignment;
531 	}
532 
533 protected:
534 	vector<string> text_vec;
535 
536 	int scroll_pos;
537 	int alignment;
538 	int max_text;
539 	int follow_tail;
540 };
541 
542 class KisStatusText_Messageclient : public MessageClient {
543 public:
KisStatusText_Messageclient(GlobalRegistry * in_globalreg,void * in_aux)544 	KisStatusText_Messageclient(GlobalRegistry *in_globalreg, void *in_aux) :
545 		MessageClient(in_globalreg, in_aux) { };
~KisStatusText_Messageclient()546 	virtual ~KisStatusText_Messageclient() { }
547 	void ProcessMessage(string in_msg, int in_flags);
548 };
549 
550 // Status message field
551 class Kis_Status_Text : public Kis_Panel_Component {
552 public:
Kis_Status_Text()553 	Kis_Status_Text() {
554 		fprintf(stderr, "FATAL OOPS: Kis_Status_Text() called w/out globalreg\n");
555 		exit(1);
556 	}
557 	Kis_Status_Text(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
558 	virtual ~Kis_Status_Text();
559 
560 	virtual void DrawComponent();
561 
562 	virtual int KeyPress(int in_key);
563 
564 	virtual void AddLine(string in_line, int headeroffset = 0);
565 
566 protected:
567 	vector<string> text_vec;
568 
569 	int scroll_pos;
570 
571 	int status_color_normal;
572 };
573 
574 class Kis_Scrollable_Table : public Kis_Panel_Component {
575 public:
Kis_Scrollable_Table()576 	Kis_Scrollable_Table() {
577 		fprintf(stderr, "FATAL OOPS: Kis_Scrollable_Table called w/out globalreg\n");
578 		exit(1);
579 	}
580 	Kis_Scrollable_Table(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
581 	virtual ~Kis_Scrollable_Table();
582 
583 	virtual void DrawComponent();
584 
585 	virtual int KeyPress(int in_key);
586 
587 	// Title format data
588 	struct title_data {
589 		int width;
590 		int draw_width;
591 		string title;
592 		int alignment;
593 	};
594 
595 	// Set the titles based on format data
596 	virtual int AddTitles(vector<Kis_Scrollable_Table::title_data> in_titles);
597 
598 	// Add a row of data keyed to an int
599 	virtual int AddRow(int in_key, vector<string> in_fields);
600 	// Delete a keyed row
601 	virtual int DelRow(int in_key);
602 	// Replace a keyed row
603 	virtual int ReplaceRow(int in_key, vector<string> in_fields);
604 	// Get a rows data
605 	virtual vector<string> GetRow(int in_key);
606 	// Get the selected key
607 	virtual int GetSelected();
608 	// Get the selected row data
609 	virtual vector<string> GetSelectedData();
610 	// Set a selected row
611 	virtual int SetSelected(int in_key);
612 	// Clear all raws
613 	virtual void Clear();
614 
615 	// Highlight the selected row
SetHighlightSelected(int in_set)616 	virtual void SetHighlightSelected(int in_set) {
617 		draw_highlight_selected = in_set;
618 	}
619 
620 	// Lock scrolling to the top of the table, ie keep the bottom
621 	// visible all the time
SetLockScrollTop(int in_set)622 	virtual void SetLockScrollTop(int in_set) {
623 		draw_lock_scroll_top = in_set;
624 	}
625 
SetDrawTitles(int in_set)626 	virtual void SetDrawTitles(int in_set) {
627 		draw_titles = in_set;
628 	}
629 
630 	struct row_data {
631 		int key;
632 		vector<string> data;
633 	};
634 
635 protected:
636 	vector<title_data> title_vec;
637 	vector<row_data *> data_vec;
638 	map<int, int> key_map;
639 
640 	int scroll_pos;
641 	int hscroll_pos;
642 	int selected;
643 
644 	int draw_lock_scroll_top, draw_highlight_selected, draw_titles;
645 };
646 
647 enum KisWidget_LabelPos {
648 	LABEL_POS_NONE = -1,
649 	LABEL_POS_TOP = 0,
650 	LABEL_POS_LEFT = 1,
651 	LABEL_POS_BOT = 2,
652 	LABEL_POS_RIGHT = 3,
653 	LABEL_POS_BORDER = 4
654 };
655 
656 // Single line input
657 class Kis_Single_Input : public Kis_Panel_Component {
658 public:
Kis_Single_Input()659 	Kis_Single_Input() {
660 		fprintf(stderr, "FATAL OOPS:  Kis_Single_Input called w/out globalreg\n");
661 		exit(1);
662 	}
663 	Kis_Single_Input(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
664 	virtual ~Kis_Single_Input();
665 
666 	virtual void DrawComponent();
667 
668 	virtual int KeyPress(int in_key);
669 	virtual int MouseEvent(MEVENT *mevent);
670 
671 	// Allowed characters filter (mandatory)
672 	virtual void SetCharFilter(string in_charfilter);
673 	// Set the label and position
674 	virtual void SetLabel(string in_label, KisWidget_LabelPos in_pos);
675 	// Set the length of the text we want (can be more than the size of the
676 	// widget) (mandatory)
677 	virtual void SetTextLen(int in_len);
678 
679 	// Pre-stock the widget text
680 	virtual void SetText(string in_text, int dpos, int ipos);
681 	// Get the text from the widget
682 	virtual string GetText();
683 
684 protected:
685 	// Label, position (0 = top, 1 = left)
686 	string label;
687 	KisWidget_LabelPos label_pos;
688 
689 	// Maximum length (may be more than the size of the widget)
690 	int max_len;
691 
692 	// Characters we allow
693 	map<char, int> filter_map;
694 
695 	/* text itself */
696 	string text;
697 	/* Position of the start of the displayed text */
698 	int curs_pos;
699 	/* Position of the input character */
700 	int inp_pos;
701 	/* drawing length of the text field */
702 	int draw_len;
703 };
704 
705 // A button
706 class Kis_Button : public Kis_Panel_Component {
707 public:
Kis_Button()708 	Kis_Button() {
709 		fprintf(stderr, "FATAL OOPS: Kis_Button() called w/out globalreg\n");
710 		exit(1);
711 	}
712 	Kis_Button(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
713 	virtual ~Kis_Button();
714 
715 	virtual void DrawComponent();
716 
717 	virtual int KeyPress(int in_key);
718 	virtual int MouseEvent(MEVENT *mevent);
719 
SetLabel(string in_text)720 	virtual void SetLabel(string in_text) { SetText(in_text); }
721 	virtual void SetText(string in_text);
722 
723 protected:
724 	string text;
725 };
726 
727 // A checkbox
728 class Kis_Checkbox : public Kis_Panel_Component {
729 public:
Kis_Checkbox()730 	Kis_Checkbox() {
731 		fprintf(stderr, "FATAL OOPS: Kis_Checkbox() called w/out globalreg\n");
732 		exit(1);
733 	}
734 	Kis_Checkbox(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
735 	virtual ~Kis_Checkbox();
736 
737 	virtual void DrawComponent();
738 	virtual void Activate(int subcomponent);
739 	virtual void Deactivate();
740 
741 	virtual int KeyPress(int in_key);
742 	virtual int MouseEvent(MEVENT *mevent);
743 
SetLabel(string in_text)744 	virtual void SetLabel(string in_text) { SetText(in_text); }
745 	virtual void SetText(string in_text);
746 
747 	virtual int GetChecked();
748 	virtual void SetChecked(int in_check);
749 
750 protected:
751 	string text;
752 
753 	int checked;
754 };
755 
756 class Kis_Radiobutton : public Kis_Panel_Component {
757 public:
Kis_Radiobutton()758 	Kis_Radiobutton() {
759 		fprintf(stderr, "FATAL OOPS: Kis_Radiobutton() called w/out globalreg\n");
760 		exit(1);
761 	}
762 	Kis_Radiobutton(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
763 	virtual ~Kis_Radiobutton();
764 
765 	virtual void DrawComponent();
766 	virtual void Activate(int subcomponent);
767 	virtual void Deactivate();
768 
769 	virtual int KeyPress(int in_key);
770 	virtual int MouseEvent(MEVENT *mevent);
771 
772 	virtual void SetText(string in_text);
773 
774 	virtual int GetChecked();
775 	virtual void SetChecked(int in_check);
776 
777 	virtual void LinkRadiobutton(Kis_Radiobutton *in_button);
778 
779 protected:
780 	string text;
781 
782 	int checked;
783 
784 	vector<Kis_Radiobutton *> linked_vec;
785 };
786 
787 // Scaling interpolated graph
788 class Kis_IntGraph : public Kis_Panel_Component {
789 public:
790 	struct graph_label {
791 		string label;
792 		int position;
793 		// Used on markers
794 		int endposition;
795 	};
796 
797 	struct graph_source {
798 		int layer;
799 		string colorpref;
800 		string colordefault;
801 		int colorval;
802 		char line[2];
803 		char fill[2];
804 		vector<int> *data;
805 		string name;
806 		int overunder;
807 	};
808 
Kis_IntGraph()809 	Kis_IntGraph() {
810 		fprintf(stderr, "FATAL OOPS: Kis_IntGraph() called w/out globalreg\n");
811 		exit(1);
812 	}
Kis_IntGraph(GlobalRegistry * in_globalreg,Kis_Panel * in_panel)813 	Kis_IntGraph(GlobalRegistry *in_globalreg, Kis_Panel *in_panel) :
814 		Kis_Panel_Component(in_globalreg, in_panel) {
815 		globalreg = in_globalreg;
816 		active = 0;
817 		graph_mode = 0;
818 		color_fw = 0;
819 		maxlabel = 0;
820 		xgraph_size = 0;
821 		label_x_graphref = -1;
822 		draw_scale = 1;
823 		draw_layers = 1;
824 		min_y = 0;
825 		max_y = 0;
826 	}
~Kis_IntGraph()827 	virtual ~Kis_IntGraph() { };
828 
829 	virtual void DrawComponent();
830 
831 	virtual int KeyPress(int in_key);
832 
833 	// Min/max values
SetScale(int in_miny,int in_maxy)834 	virtual void SetScale(int in_miny, int in_maxy) {
835 		min_y = in_miny;
836 		max_y = in_maxy;
837 	}
838 
839 	// Interpolate graph to fit?
SetInterpolation(int in_x)840 	virtual void SetInterpolation(int in_x) {
841 		inter_x = in_x;
842 	}
843 
SetXLabels(vector<graph_label> in_xl,string graphname)844 	virtual void SetXLabels(vector<graph_label> in_xl, string graphname) {
845 		label_x = in_xl;
846 
847 		// Figure out which graph we reference
848 		label_x_graphref = -1;
849 		for (unsigned int x = 0; x < data_vec.size(); x++) {
850 			if (data_vec[x].name == graphname) {
851 				label_x_graphref = x;
852 				break;
853 			}
854 		}
855 
856 		// Figure out the # of lines we need to save on the graph
857 		xgraph_size = 0;
858 		for (unsigned int x = 0; x < label_x.size(); x++) {
859 			if (xgraph_size < (int) label_x[x].label.size())
860 				xgraph_size = (int) label_x[x].label.size() + 1;
861 		}
862 	}
863 
SetMode(int mode)864 	virtual void SetMode(int mode) {
865 		graph_mode = mode;
866 	}
867 
SetDrawScale(int in_draw_scale)868 	virtual void SetDrawScale(int in_draw_scale) {
869 		draw_scale = in_draw_scale;
870 	}
871 
SetDrawLayers(int in_draw_layers)872 	virtual void SetDrawLayers(int in_draw_layers) {
873 		draw_layers = in_draw_layers;
874 	}
875 
876 	// Add a data vector at a layer with a color preference, representation
877 	// character, over/under (1 over, 0 n/a, -1 under), and external vector.
878 	// All data sources must share a common min/max representation
879 	virtual void AddExtDataVec(string name, int layer, string colorpref,
880 							   string colordefault, char line, char fill,
881 							   int overunder, vector<int> *in_dv);
882 protected:
883 	// Graph coordinates
884 	int min_y, max_y;
885 	// Interpolation
886 	int inter_x;
887 
888 	int color_fw;
889 
890 	// Graph mode
891 	// 0 = normal
892 	// 1 = over/under
893 	int graph_mode;
894 
895 	int draw_scale, draw_layers;
896 
897 	// Graph source vector
898 	vector<graph_source> data_vec;
899 
900 	// Max label length
901 	unsigned int maxlabel;
902 
903 	// Labels
904 	vector<graph_label> label_x;
905 	int xgraph_size, label_x_graphref;
906 };
907 
908 #if 0
909 
910 // Polar graph
911 class Kis_PolarGraph : public Kis_Panel_Component {
912 public:
913 	struct graph_point {
914 		int id;
915 
916 		string colorpref;
917 		string colordefault;
918 		int colorval;
919 
920 		string name;
921 
922 		double r, theta;
923 	};
924 
925 	Kis_PolarGraph() {
926 		fprintf(stderr, "FATAL OOPS: Kis_PolarGraph() called w/out globalreg\n");
927 		exit(1);
928 	}
929 
930 	Kis_PolarGraph(GlobalRegistry *in_globalreg, Kis_Panel *in_panel) :
931 		Kis_Panel_Component(in_globalreg, in_panel) {
932 
933 		globalreg = in_globalreg;
934 		active = 0;
935 		color_fw = 0;
936 
937 		maxr = 0;
938 	}
939 	virtual ~Kis_PolarGraph() { };
940 
941 	virtual void DrawComponent();
942 
943 	virtual int KeyPress(int in_key);
944 
945 	virtual void AddPoint(int id, graph_point gp);
946 	virtual void DelPoint(int id);
947 	virtual void ClearPoints();
948 
949 protected:
950 	int color_fw;
951 	double maxr;
952 
953 	vector<Kis_PolarGraph::graph_point> point_vec;
954 };
955 
956 // File picker widget, derivation of the scrollable table
957 // Due to widget tabbing structure, can't easily nest multiple widgets into a
958 // virtual packbox so directory changing has to be an external text box
959 class Kis_Filepicker : public Kis_Scrollable_Table {
960 public:
961 	Kis_Filepicker() { fprintf(stderr, "FATAL OOPS: Kis_Filepicker();\n"); exit(1); }
962 
963 	Kis_Filepicker(GlobalRegistry *in_globalreg, Kis_Panel *in_panel);
964 	virtual ~Kis_Filepicker();
965 
966 	virtual void SetDirectory(string in_dir);
967 	virtual void SetFile(string in_file);
968 	virtual string GetDirectory() { return cur_directory; }
969 
970 	virtual int KeyPress(int in_key);
971 
972 protected:
973 	string cur_directory, set_file;
974 };
975 
976 #endif
977 
978 class Kis_Panel {
979 public:
Kis_Panel()980 	Kis_Panel() {
981 		fprintf(stderr, "FATAL OOPS: Kis_Panel() called w/out globalreg\n");
982 		exit(1);
983 	}
984 	Kis_Panel(GlobalRegistry *in_globalreg, KisPanelInterface *kpinterface);
985 	virtual ~Kis_Panel();
986 
ShowPanel()987 	virtual void ShowPanel() { show_panel(pan); }
988 	virtual void Position(int in_sy, int in_sx, int in_y, int in_x);
989 
FetchSy()990 	virtual int FetchSy() { return sy; }
FetchSx()991 	virtual int FetchSx() { return sx; }
FetchSzy()992 	virtual int FetchSzy() { return sizey; }
FetchSzx()993 	virtual int FetchSzx() { return sizex; }
994 
995 	virtual int Poll();
996 
ClearPanel()997 	virtual void ClearPanel() {
998 		wclear(win);
999 	}
1000 
DrawPanel()1001 	virtual void DrawPanel() {
1002 		ColorFromPref(text_color, "panel_text_color");
1003 		ColorFromPref(border_color, "panel_border_color");
1004 
1005 		wbkgdset(win, text_color);
1006 		werase(win);
1007 
1008 		DrawTitleBorder();
1009 		DrawComponentVec();
1010 		wmove(win, 0, 0);
1011 	}
1012 
1013 	virtual int KeyPress(int in_key);
1014 	virtual int MouseEvent(MEVENT *mevent);
1015 
1016 	virtual void SetTitle(string in_title);
1017 
FetchDrawWindow()1018 	virtual WINDOW *FetchDrawWindow() { return win; }
FetchPanelInterface()1019 	virtual KisPanelInterface *FetchPanelInterface() { return kpinterface; }
1020 
FetchMenu()1021 	virtual Kis_Menu *FetchMenu() { return menu; }
1022 
1023 	// Map a color pair out of preferences
1024 	virtual void InitColorPref(string in_prefname, string in_def);
1025 	virtual void ColorFromPref(int &clr, string in_prefname);
1026 	virtual void RemapAllColors(string oldcolor, string newcolor);
1027 	virtual int AddColor(string in_color);
1028 
1029 	void AddComponentVec(Kis_Panel_Component *in_comp, int in_flags);
1030 	void DelComponentVec(Kis_Panel_Component *in_comp);
1031 
1032 	void SetActiveComponent(Kis_Panel_Component *in_comp);
1033 
1034 protected:
1035 	// Bit values of what components expect to happen
1036 	// COMP_DRAW - issue a draw command to this component during panel draw
1037 	//             components inside a packbox get called by the packbox and
1038 	//             don't need an explicit draw
1039 	// COMP_TAB  - Include in the list of components we tab to and activate,
1040 	//             gets an activate event and becomes the focus for keyboard
1041 	//             input
1042 	// COMP_EVT  - Generates events when triggered but may not necessarily be
1043 	// 			   tabable (menus gets COMP_EVT only)
1044 	// COMP_STATIC Is not freed when the panel is destroyed, used for widgets
1045 	//             managed outside the panel itself
1046 #define KIS_PANEL_COMP_DRAW			1
1047 #define KIS_PANEL_COMP_TAB			2
1048 #define KIS_PANEL_COMP_EVT			4
1049 #define KIS_PANEL_COMP_STATIC		8
1050 	struct component_entry {
1051 		int comp_flags;
1052 		Kis_Panel_Component *comp;
1053 	};
1054 
1055 	void DrawComponentVec();
1056 
1057 	vector<component_entry> pan_comp_vec;
1058 
1059 	GlobalRegistry *globalreg;
1060 	KisPanelInterface *kpinterface;
1061 
1062 	virtual void DrawTitleBorder();
1063 
1064 	WINDOW *win;
1065 	PANEL *pan;
1066 
1067 	string title;
1068 
1069 	// Menus get treated specially because they have to be drawn last
1070 	Kis_Menu *menu;
1071 
1072 	int tab_pos;
1073 
1074 	// Component which gets the keypress we didn't filter
1075 	Kis_Panel_Component *active_component;
1076 
1077 	int sx, sy, sizex, sizey;
1078 
1079 	int text_color, border_color;
1080 
1081 	// Main component sized to the full window (usually a packbox)
1082 	Kis_Panel_Component *main_component;
1083 
1084 	int last_key;
1085 	struct timeval last_key_time;
1086 
1087 	int escape_timer;
1088 };
1089 
1090 // Pollable supersystem for handling panels and input
1091 class PanelInterface : public Pollable {
1092 public:
1093 	PanelInterface();
1094 	PanelInterface(GlobalRegistry *in_globalreg);
1095 	virtual ~PanelInterface();
1096 
1097 	virtual int MergeSet(int in_max_fd, fd_set *out_rset, fd_set *out_wset);
1098 
1099 	virtual int Poll(fd_set& in_rset, fd_set& in_wset);
1100 
1101 	virtual int DrawInterface();
1102 	virtual void ResizeInterface();
1103 
1104 	virtual void AddPanel(Kis_Panel *in_panel);
1105 	virtual void KillPanel(Kis_Panel *in_panel);
1106 protected:
1107 	vector<Kis_Panel *> live_panels;
1108 	int draweventid;
1109 	vector<Kis_Panel *> dead_panels;
1110 	int hsize, vsize;
1111 };
1112 
1113 #endif // panel
1114 #endif // header
1115 
1116