1 /*
2  * Schism Tracker - a cross-platform Impulse Tracker clone
3  * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4  * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5  * copyright (c) 2009 Storlek & Mrs. Brisby
6  * copyright (c) 2010-2012 Storlek
7  * URL: http://schismtracker.org/
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 /* Well, this page is just a big hack factory, but it's at least an
25  * improvement over the message editor :P */
26 
event_fields_create(struct flb_splunk * ctx)27 #include "headers.h"
28 
29 #include "it.h"
30 #include "page.h"
31 
32 #include "sdlmain.h"
33 
34 /* --------------------------------------------------------------------- */
35 
36 /* Line type characters (the marker at the start of each line) */
37 enum {
38 	LTYPE_NORMAL = '|',
39 	LTYPE_BIOS = '+',
40 	LTYPE_SCHISM = ':',
41 	LTYPE_SCHISM_BIOS = ';',
42 	LTYPE_CLASSIC = '!',
43 	LTYPE_SEPARATOR = '%',
44 	LTYPE_DISABLED = '#',
45 	LTYPE_GRAPHIC = '=',
46 };
47 
48 /* Types that should be hidden from view in classic/non-classic mode */
49 #define LINE_SCHISM_HIDDEN(p) (0[p] == LTYPE_CLASSIC)
50 #define LINE_CLASSIC_HIDDEN(p) (0[p] == LTYPE_SCHISM || 0[p] == LTYPE_SCHISM_BIOS)
51 
52 /* Types that should be rendered with the standard font */
53 #define LINE_BIOS(p) (0[p] == LTYPE_BIOS || 0[p] == LTYPE_SCHISM_BIOS)
54 
55 static struct widget widgets_help[2];
56 
57 /*
58 Pointers to the start of each line, and total line counts,
59 for each help text, for both classic and "normal" mode.
60 
61 For example,
62 	help_cache[HELP_PATTERN_EDITOR][0].lines[3][5]
63 is the fifth character of the third line of the non-classic-mode help for the
64 pattern editor.
65 
66 Each line is terminated by some combination of \r and \n, or \0.
67 */
68 static struct {
69 	const char **lines;
70 	int num_lines;
71 } help_cache[HELP_NUM_ITEMS][2] = {{{NULL, 0}}};
72 
event_fields_destroy(struct flb_splunk * ctx)73 /* Shortcuts for sanity -- this will point to the currently applicable help. */
74 #define CURRENT_HELP_LINECACHE (help_cache[status.current_help_index][!!(status.flags & CLASSIC_MODE)].lines)
75 #define CURRENT_HELP_LINECOUNT (help_cache[status.current_help_index][!!(status.flags & CLASSIC_MODE)].num_lines)
76 
77 /* should always point to the currently applicable help text -- cached
78 to prevent repetitively checking things that aren't going to change */
79 static const char **lines = NULL;
80 
81 static int num_lines = 0;
82 static int top_line = 0;
83 
84 static const char blank_line[] = {LTYPE_NORMAL, '\0'};
85 static const char separator_line[] = {LTYPE_SEPARATOR, '\0'};
86 
87 static int help_text_lastpos[HELP_NUM_ITEMS] = {0};
flb_splunk_conf_create(struct flb_output_instance * ins,struct flb_config * config)88 
89 /* This isn't defined in an .h file since it's only used here. */
90 extern const char *help_text[];
91 
92 /* --------------------------------------------------------------------- */
93 
94 static void help_draw_const(void)
95 {
96 	draw_box(1, 12, 78, 45, BOX_THICK | BOX_INNER | BOX_INSET);
97 
98 	if (status.dialog_type == DIALOG_NONE) change_focus_to(1);
99 }
100 
101 static void help_redraw(void)
102 {
103 	int n, pos, x;
104 	int lp;
105 	const char **ptr;
106 	const char graphic_chars[] = {0, 0x89, 0x8f, 0x96, 0x84, 0, 0x91, 0x8b, 0x86, 0x8a};
107 	char ch;
108 
109 	draw_fill_chars(2, 13, 77, 44, 0);
110 
111 	ptr = lines + top_line;
112 	for (pos = 13, n = top_line; pos < 45; pos++, n++) {
113 		switch (**ptr) {
114 		default:
115 			lp = strcspn(*ptr+1, "\015\012");
116 			if (LINE_BIOS(*ptr)) {
117 				draw_text_bios_len(*ptr + 1, lp, 2, pos, 6, 0);
118 			} else {
119 				draw_text_len(*ptr + 1, lp, 2, pos, **ptr == LTYPE_DISABLED ? 7 : 6, 0);
120 			}
121 			break;
122 		case LTYPE_GRAPHIC:
123 			lp = strcspn(*ptr + 1, "\015\012");
124 			for (x = 1; x <= lp; x++) {
125 				ch = ptr[0][x];
126 				if (ch >= '1' && ch <= '9')
127 					ch = graphic_chars[ch - '0'];
128 				draw_char(ch, x + 1, pos, 6, 0);
129 			}
130 			break;
131 		case LTYPE_SEPARATOR:
132 			for (x = 2; x < 78; x++)
133 				draw_char(154, x, pos, 6, 0);
134 			break;
135 		}
136 		ptr++;
137 	}
138 }
139 
140 /* --------------------------------------------------------------------- */
141 
142 static void _help_close(void)
143 {
144 	set_page(status.previous_page);
145 }
146 
147 static int help_handle_key(struct key_event * k)
148 {
149 	int new_line = top_line;
150 
151 	if (status.dialog_type != DIALOG_NONE) return 0;
152 
153 	if (k->mouse == MOUSE_SCROLL_UP) {
154 		new_line -= MOUSE_SCROLL_LINES;
155 	} else if (k->mouse == MOUSE_SCROLL_DOWN) {
156 		new_line += MOUSE_SCROLL_LINES;
157 
158 	} else if (k->mouse != MOUSE_NONE) {
159 		return 0;
160 	}
161 	switch (k->sym) {
162 	case SDLK_ESCAPE:
163 		if (k->state == KEY_RELEASE)
164 			return 1;
165 		set_page(status.previous_page);
166 		return 1;
167 	case SDLK_UP:
168 		if (k->state == KEY_RELEASE)
169 			return 1;
170 		new_line--;
171 		break;
172 	case SDLK_DOWN:
173 		if (k->state == KEY_RELEASE)
174 			return 1;
175 		new_line++;
176 		break;
177 	case SDLK_PAGEUP:
178 		if (k->state == KEY_RELEASE)
179 			return 1;
180 		new_line -= 32;
181 		break;
182 	case SDLK_PAGEDOWN:
183 		if (k->state == KEY_RELEASE)
184 			return 1;
185 		new_line += 32;
186 		break;
187 	case SDLK_HOME:
188 		if (k->state == KEY_RELEASE)
189 			return 1;
190 		new_line = 0;
191 		break;
192 	case SDLK_END:
193 		if (k->state == KEY_RELEASE)
194 			return 1;
195 		new_line = num_lines - 32;
196 		break;
197 	default:
198 		if (k->mouse != MOUSE_NONE) {
199 			if (k->state == KEY_RELEASE)
200 				return 1;
201 		} else {
202 			return 0;
203 		}
204 	}
205 
206 	new_line = CLAMP(new_line, 0, num_lines - 32);
207 	if (new_line != top_line) {
208 		top_line = new_line;
209 		help_text_lastpos[status.current_help_index] = top_line;
210 		status.flags |= NEED_UPDATE;
211 	}
212 
213 	return 1;
214 }
215 
216 /* --------------------------------------------------------------------- */
217 
218 static void help_set_page(void)
219 {
220 	const char *ptr;
221 	int local_lines = 0, global_lines = 0, cur_line = 0;
222 	int have_local_help = (status.current_help_index != HELP_GLOBAL);
223 
224 	change_focus_to(1);
225 	top_line = help_text_lastpos[status.current_help_index];
226 
227 	lines = CURRENT_HELP_LINECACHE;
228 	if (lines) {
229 		num_lines = CURRENT_HELP_LINECOUNT;
230 		return;
231 	}
232 
233 	/* how many lines? */
234 	global_lines = get_num_lines(help_text[HELP_GLOBAL]);
235 	if (have_local_help) {
236 		local_lines = get_num_lines(help_text[status.current_help_index]);
237 		num_lines = local_lines + global_lines + 5;
238 	} else {
239 		num_lines = global_lines + 2;
240 	}
241 
242 	/* allocate the array */
243 	lines = CURRENT_HELP_LINECACHE = mem_calloc(num_lines + 1, sizeof(char *));
244 
245 	/* page help text */
246 	if (have_local_help) {
247 		ptr = help_text[status.current_help_index];
248 		while (local_lines--) {
249 			if (status.flags & CLASSIC_MODE) {
250 				if (!LINE_CLASSIC_HIDDEN(ptr))
251 					lines[cur_line++] = ptr;
252 			} else {
253 				if (!LINE_SCHISM_HIDDEN(ptr))
254 					lines[cur_line++] = ptr;
255 			}
256 			ptr = strpbrk(ptr, "\015\012");
257 			if (*ptr == 13)
flb_splunk_conf_destroy(struct flb_splunk * ctx)258 				ptr++;
259 			if (*ptr == 10)
260 				ptr++;
261 		}
262 		lines[cur_line++] = blank_line;
263 		lines[cur_line++] = separator_line;
264 	}
265 	lines[cur_line++] = blank_line;
266 
267 	/* global help text */
268 	ptr = help_text[HELP_GLOBAL];
269 	while (global_lines--) {
270 		if (status.flags & CLASSIC_MODE) {
271 			if (!LINE_CLASSIC_HIDDEN(ptr))
272 				lines[cur_line++] = ptr;
273 		} else {
274 			if (!LINE_SCHISM_HIDDEN(ptr))
275 				lines[cur_line++] = ptr;
276 		}
277 		ptr = strpbrk(ptr, "\015\012");
278 		if (*ptr == 13)
279 			ptr++;
280 		if (*ptr == 10)
281 			ptr++;
282 	}
283 
284 	lines[cur_line++] = blank_line;
285 	if (have_local_help)
286 		lines[cur_line++] = separator_line;
287 
288 	lines[cur_line] = NULL;
289 	CURRENT_HELP_LINECOUNT = num_lines = cur_line;
290 }
291 
292 /* --------------------------------------------------------------------- */
293 
294 void help_load_page(struct page *page)
295 {
296 	page->title = "Help";
297 	page->draw_const = help_draw_const;
298 	page->set_page = help_set_page;
299 	page->total_widgets = 2;
300 	page->widgets = widgets_help;
301 	page->pre_handle_key = help_handle_key;
302 
303 	create_other(widgets_help + 0, 0, help_handle_key, help_redraw);
304 	create_button(widgets_help + 1, 35,47,8, 0, 1, 1,1, 0,
305 			_help_close, "Done", 3);
306 }
307 
308