1 /*
2  *  STFL - The Structured Terminal Forms Language/Library
3  *  Copyright (C) 2006, 2007  Clifford Wolf <clifford@clifford.at>
4  *  Copyright (C) 2006  Andreas Krennmair <ak@synflood.at>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 3 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *  MA 02110-1301 USA
20  *
21  *  wt_textview.c: Widget type 'textview'
22  */
23 
24 #include "stfl_internals.h"
25 
26 #include <string.h>
27 #include <stdlib.h>
28 
29 #if 0
30 static void fix_offset_pos(struct stfl_widget *w)
31 {
32 	int offset = stfl_widget_getkv_int(w, "offset", 0);
33 	int pos = stfl_widget_getkv_int(w, "pos", 0);
34 
35 	int orig_offset = offset;
36 	int orig_pos = pos;
37 
38 	while (pos < offset)
39 		offset--;
40 
41 	if (w->h > 0)
42 		while (pos >= offset+w->h)
43 			offset++;
44 
45 	int maxpos = -1;
46 	struct stfl_widget *c = w->first_child;
47 	while (c) {
48 		maxpos++;
49 		c = c->next_sibling;
50 	}
51 
52 	if (maxpos >= 0 && pos > maxpos)
53 		pos = maxpos;
54 
55 	if (offset != orig_offset)
56 		stfl_widget_setkv_int(w, "offset", offset);
57 
58 	if (pos != orig_pos)
59 		stfl_widget_setkv_int(w, "pos", pos);
60 }
61 #endif
62 
wt_textview_prepare(struct stfl_widget * w,struct stfl_form * f)63 static void wt_textview_prepare(struct stfl_widget *w, struct stfl_form *f)
64 {
65 	struct stfl_widget *c = w->first_child;
66 
67 	w->min_w = 1;
68 	w->min_h = 5;
69 
70 	if (c)
71 		w->allow_focus = 1;
72 
73 	while (c) {
74 		const wchar_t * text = stfl_widget_getkv_str(c, L"text", L"");
75 		int len = wcswidth(text, wcslen(text));
76 		w->min_w = len > w->min_w ? len : w->min_w;
77 		c = c->next_sibling;
78 	}
79 }
80 
81 
82 
wt_textview_draw(struct stfl_widget * w,struct stfl_form * f,WINDOW * win)83 static void wt_textview_draw(struct stfl_widget *w, struct stfl_form *f, WINDOW *win)
84 {
85 	//fix_offset_pos(w);
86 
87 	int offset = stfl_widget_getkv_int(w, L"offset", 0);
88 	int is_richtext = stfl_widget_getkv_int(w, L"richtext", 0);
89 
90 	const wchar_t *style_normal = stfl_widget_getkv_str(w, L"style_normal", L"");
91 	const wchar_t *style_end = stfl_widget_getkv_str(w, L"style_end", L"");
92 
93 	struct stfl_widget *c;
94 	int i;
95 
96 	stfl_style(win, style_normal);
97 	for (i=0, c=w->first_child; c && i < offset+w->h; i++, c=c->next_sibling)
98 	{
99 		const wchar_t *text = stfl_widget_getkv_str(c, L"text", L"");
100 
101 		if (i < offset) {
102 			if (is_richtext)
103 				stfl_print_richtext(w, win, w->y, w->x, text, 0, style_normal, 0);
104 			continue;
105 		}
106 
107 		if (is_richtext) {
108 			stfl_print_richtext(w, win, w->y+i-offset, w->x, text, w->w, style_normal, 0);
109 		} else {
110 			mvwaddnwstr(win, w->y+i-offset, w->x, text, w->w);
111 		}
112 	}
113 
114 	stfl_style(win, style_end);
115 	while (i<offset+w->h) {
116 		mvwaddnwstr(win,w->y+i-offset,w->x,L"~",w->w);
117 		++i;
118 	}
119 
120 	if (f->current_focus_id == w->id)
121 		f->root->cur_x = f->root->cur_y = f->cursor_x = f->cursor_y = -1;
122 }
123 
wt_textview_process(struct stfl_widget * w,struct stfl_widget * fw,struct stfl_form * f,wchar_t ch,int isfunckey)124 static int wt_textview_process(struct stfl_widget *w, struct stfl_widget *fw, struct stfl_form *f, wchar_t ch, int isfunckey)
125 {
126 	//int pos = stfl_widget_getkv_int(w, "pos", 0);
127 	int offset = stfl_widget_getkv_int(w,L"offset",0);
128 	int maxoffset = -1;
129 
130 	struct stfl_widget *c = w->first_child;
131 	while (c) {
132 		maxoffset++;
133 		c = c->next_sibling;
134 	}
135 
136 	if (offset > 0 && stfl_matchbind(w, ch, isfunckey, L"up", L"UP")) {
137 		stfl_widget_setkv_int(w, L"offset", offset-1);
138 
139 		//fix_offset_pos(w);
140 		return 1;
141 	}
142 
143 	if (offset < maxoffset && stfl_matchbind(w, ch, isfunckey, L"down", L"DOWN")) {
144 		stfl_widget_setkv_int(w, L"offset", offset+1);
145 		//fix_offset_pos(w);
146 		return 1;
147 	}
148 
149 	if (stfl_matchbind(w, ch, isfunckey, L"page_up", L"PPAGE")) {
150 		if ((offset - w->h + 1) > 0) { // XXX: first page handling won't work with that
151 			stfl_widget_setkv_int(w, L"offset", offset - w->h + 1);
152 		} else {
153 			stfl_widget_setkv_int(w, L"offset", 0);
154 		}
155 		return 1;
156 	}
157 
158 	if (stfl_matchbind(w, ch, isfunckey, L"page_down", L"NPAGE")) {
159 		if ((offset + w->h - 1) < maxoffset) { // XXX: last page handling won't work with that
160 			stfl_widget_setkv_int(w, L"offset", offset + w->h - 1);
161 		} else {
162 			stfl_widget_setkv_int(w, L"offset", maxoffset);
163 		}
164 		return 1;
165 	}
166 
167 	if (stfl_matchbind(w, ch, isfunckey, L"home", L"HOME")) {
168 		stfl_widget_setkv_int(w, L"offset", 0);
169 		return 1;
170 	}
171 
172 	if (stfl_matchbind(w, ch, isfunckey, L"end", L"END")) {
173 		stfl_widget_setkv_int(w, L"offset", (maxoffset - w->h + 2) < 0 ? 0 : maxoffset - w->h + 2);
174 		return 1;
175 	}
176 
177 	return 0;
178 }
179 
180 struct stfl_widget_type stfl_widget_type_textview = {
181 	L"textview",
182 	0, // f_init
183 	0, // f_done
184 	0, // f_enter
185 	0, // f_leave
186 	wt_textview_prepare,
187 	wt_textview_draw,
188 	wt_textview_process,
189 };
190 
191