1 // ----------------------------------------------------------------------------
2 //  Font_Browser.cpp      v 0.0.3                        2007-04-21
3 //
4 //         for the Fast Light Tool Kit (FLTK) 1.1.x .
5 //
6 //    David Freese, w1hkj@w1hkj.com
7 //    based on similar widget by Mariwan Jalal
8 //
9 // This file is part of FLAMP.
10 //
11 // This is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This software is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 //
24 // ----------------------------------------------------------------------------
25 
26 #include <config.h>
27 
28 #include <string>
29 #include <cstdlib>
30 #include <cstring>
31 #include <cstdio>
32 #include <stdint.h>
33 
34 #include <FL/Fl.H>
35 #include <FL/Fl_Color_Chooser.H>
36 #include <FL/fl_draw.H>
37 
38 #include "font_browser.h"
39 #include "flslider2.h"
40 #include "util.h"
41 #include "gettext.h"
42 
43 using namespace std;
44 
45 Font_Browser* font_browser;
46 
47 // Font Color selected
48 
ColorSelect()49 void Font_Browser::ColorSelect()
50 {
51 	unsigned char r, g, b;
52 	Fl::get_color(fontcolor, r, g, b);
53 	if (fl_color_chooser(_("Font color"), r, g, b) == 0)
54 		return;
55 	fontcolor = fl_rgb_color(r, g, b);
56 	btn_Color->color(fontcolor);
57 }
58 
fb_callback(Fl_Widget * w,void * arg)59 void Font_Browser::fb_callback(Fl_Widget* w, void* arg)
60 {
61 	Font_Browser* fb = reinterpret_cast<Font_Browser*>(arg);
62 
63 	if (w == fb->btn_Cancel)
64 		fb->hide();
65 	else if (w == fb->btn_OK) {
66 		if (fb->callback_)
67 			(*fb->callback_)(fb, fb->data_);
68 	}
69 	else if (w == fb->btn_Color)
70 		fb->ColorSelect();
71 	else if (w == fb->lst_Font)
72 		fb->FontNameSelect();
73 	else {
74 		if (w == fb->lst_Size)
75 			fb->txt_Size->value(strtol(fb->lst_Size->text(fb->lst_Size->value()), NULL, 10));
76 		fb->fontsize = static_cast<int>(fb->txt_Size->value());
77 	}
78 	fb->box_Example->SetFont(fb->fontnbr, fb->fontsize, fb->fontcolor);
79 }
80 
81 // Sort the font list
FontSort()82 void Font_Browser::FontSort()
83 {
84 	int size = lst_Font->size();
85 	for ( int t = 1; t <= size - 1; t++ )
86 		for ( int r = t+1; r <= size; r++ )
87 			if ( strcasecmp(lst_Font->text(t), lst_Font->text(r)) > 0 )
88 				lst_Font->swap(t,r);
89 }
90 
91 // Font Name changed callback
FontNameSelect()92 void Font_Browser::FontNameSelect()
93 {
94 	int fn = lst_Font->value();
95 	if (!fn)
96 		return;
97 
98 	fontnbr = (Fl_Font)reinterpret_cast<intptr_t>(lst_Font->data(fn));
99 
100 	// get sizes and fill browser; skip first element if it is zero
101 	lst_Size->clear();
102 	int nsizes, *sizes;
103 	size_t szt;
104 	char buf[4];
105 	nsizes = Fl::get_font_sizes(fontnbr, sizes);
106 	//
107 	for (int i = !*sizes; i < nsizes; i++)
108 		if ((size_t)snprintf(buf, sizeof(buf), "%d", sizes[i]) < sizeof(buf)) {
109 			szt = sizes[i];
110 			lst_Size->add(buf, (void*)szt);//sizes[i]);
111 		}
112 
113 	// scalable font with no suggested sizes
114 	if (!lst_Size->size()) {
115 		for (int i = 1; i <= 48; i++) {
116 			snprintf(buf, sizeof(buf), "%d", i);
117 			szt = i;
118 			lst_Size->add(buf, (void*)szt);
119 		}
120 	}
121 	fontSize(fontsize);
122 }
123 
Font_Browser(int x,int y,int w,int h,const char * lbl)124 Font_Browser::Font_Browser(int x, int y, int w, int h, const char *lbl )
125 : Fl_Window(x, y, w, h, lbl)
126 {
127 	lst_Font = new Fl_Browser(5, 15, 280, 125, _("Font:"));
128 	lst_Font->align(FL_ALIGN_TOP_LEFT);
129 	lst_Font->type(FL_HOLD_BROWSER);
130 	lst_Font->callback(fb_callback, this);
131 
132 	txt_Size = new Fl_Value_Input2(290, 15, 50, 22, _("Size:"));
133 	txt_Size->align(FL_ALIGN_TOP_LEFT);
134 	txt_Size->range(1.0, 48.0);
135 	txt_Size->step(1.0);
136 	txt_Size->callback(fb_callback, this);
137 
138 	lst_Size = new Fl_Browser(290, 40, 50, 100);
139 	lst_Size->type(FL_HOLD_BROWSER);
140 	lst_Size->callback(fb_callback, this);
141 
142 	btn_OK = new Fl_Return_Button(345, 40, 80, 25, _("&OK"));
143 	btn_OK->shortcut(0x8006f);
144 	btn_OK->callback(fb_callback, this);
145 
146 	btn_Cancel = new Fl_Button(345, 70, 80, 25, _("Cancel"));
147 	btn_Cancel->labelsize(12);
148 	btn_Cancel->callback(fb_callback, this);
149 
150 	btn_Color = new Fl_Button(345, 100, 80, 25, _("Color"));
151 	btn_Color->down_box(FL_BORDER_BOX);
152 	btn_Color->color(FL_FOREGROUND_COLOR);
153 	btn_Color->callback(fb_callback, this);
154 
155 	box_Example = new Preview_Box(5, 145, 420, 75, _("That crazy fox jumped over the dog again!\n"
156 													 "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789\n"
157 													 "!\"#$%&'()*+,-./:;<=>?@@[\\]^_`{|}~"));
158 	box_Example->box(FL_DOWN_BOX);
159 	box_Example->align(FL_ALIGN_WRAP|FL_ALIGN_CLIP|FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
160 	resizable(box_Example);
161 
162 	set_modal();
163 	end();
164 
165 	// Initializations
166 
167 	this->callback_ = 0;  // Initialize Widgets callback
168 	this->data_ = 0;      // And the data
169 
170 	numfonts =   Fl::set_fonts(0); // Nr of fonts available on the server
171 
172 	const char* name;
173 	size_t szt;
174 	for(int i = 0; i < numfonts; i++) {
175 		name = Fl::get_font_name((Fl_Font)i);
176 		if (isalpha(*name)) {
177 			szt = i;
178 			lst_Font->add(name, (void *)szt);
179 		}
180 	}
181 	FontSort();
182 
183 	fontnbr = FL_HELVETICA;;
184 	fontsize = FL_NORMAL_SIZE; // Font Size to be used
185 	fontcolor = FL_FOREGROUND_COLOR;
186 	filter = ALL_TYPES;
187 
188 	lst_Font->value(1);
189 	FontNameSelect();
190 
191 	//!    Fl::focus(lst_Font);
192 
193 	xclass(PACKAGE_NAME);
194 }
195 
fontNumber(Fl_Font n)196 void Font_Browser::fontNumber(Fl_Font n)
197 {
198 	fontnbr = n;
199 	lst_Font->value(1);
200 	int s = lst_Font->size();
201 	for (int i = 1; i < s; i++ ) {
202 		if ((Fl_Font)reinterpret_cast<intptr_t>(lst_Font->data(i)) == n) {
203 			lst_Font->value(i);
204 			FontNameSelect();
205 			break;
206 		}
207 	}
208 }
209 
fontSize(int s)210 void Font_Browser::fontSize(int s)
211 {
212 	fontsize = s;
213 	int n = lst_Size->size();
214 	for (int i = 1; i < n; i++) {
215 		if ((intptr_t)lst_Size->data(i) == fontsize) {
216 			lst_Size->value(i);
217 			break;
218 		}
219 	}
220 	txt_Size->value(s);
221 }
222 
fontColor(Fl_Color c)223 void Font_Browser::fontColor(Fl_Color c)
224 {
225 	btn_Color->color(fontcolor = c);
226 	box_Example->SetFont(fontnbr, fontsize, fontcolor);
227 	box_Example->redraw();
228 }
229 
fontName(const char * n)230 void Font_Browser::fontName(const char* n)
231 {
232 	int s = lst_Font->size();
233 	for (int i = 1; i < s; i++) {
234 		if (!strcmp(lst_Font->text(i), n)) {
235 			lst_Font->value(i);
236 			FontNameSelect();
237 		}
238 	}
239 }
240 
fixed_width(Fl_Font f)241 bool Font_Browser::fixed_width(Fl_Font f)
242 {
243 	fl_font(f, FL_NORMAL_SIZE);
244 	return fl_width('X') == fl_width('i');
245 }
246 
247 #include <vector>
248 #include <FL/Fl_Double_Window.H>
249 #include <FL/Fl_Progress.H>
250 
251 class Progress_Window : public Fl_Double_Window
252 {
253 public:
Progress_Window(float min=0.0f,float max=100.0f,const char * l=0)254 	Progress_Window(float min = 0.0f, float max = 100.0f, const char* l = 0)
255 	: Fl_Double_Window(200, 34), ps(5, 5, 190, 24, l)
256 	{
257 		end();
258 
259 		range(min, max);
260 		ps.align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
261 		ps.selection_color(FL_SELECTION_COLOR);
262 		set_modal();
263 		callback(nop);
264 
265 		if (l && *l) {
266 			fl_font(FL_HELVETICA, FL_NORMAL_SIZE);
267 			int s = (int)(fl_width(l) + fl_width('W'));
268 			if (s > ps.w()) {
269 				ps.size(s, ps.h());
270 				size(ps.w() + 10, h());
271 			}
272 		}
273 		position(Fl::event_x_root() - w() / 2, Fl::event_y_root() - h());
274 
275 		xclass(PACKAGE_TARNAME);
276 		show();
277 	}
range(float min,float max)278 	void range(float min, float max) { ps.minimum(min); ps.maximum(max); }
value(float val)279 	void value(float val) { ps.value(val); }
nop(Fl_Widget *,void *)280 	static void nop(Fl_Widget*, void*) { }
281 private:
282 	Fl_Progress ps;
283 };
284 
fontFilter(filter_t filter)285 void Font_Browser::fontFilter(filter_t filter)
286 {
287 	if (this->filter == filter)
288 		return;
289 
290 	int s = lst_Font->size();
291 
292 	static vector<bool> fixed;
293 	if (fixed.empty()) {
294 		Progress_Window pw(1, s, _("Reading fonts..."));
295 		fixed.resize(s);
296 		for (int i = 1; i < s; i++) {
297 			fixed[i] = fixed_width((Fl_Font)(intptr_t)(lst_Font->data(i)));
298 			pw.value(i);
299 			Fl::check();
300 		}
301 	}
302 
303 	switch (this->filter = filter) {
304 		case FIXED_WIDTH:
305 			for (int i = 1; i < s; i++) {
306 				if (fixed[i])
307 					lst_Font->show(i);
308 				else
309 					lst_Font->hide(i);
310 			}
311 			break;
312 		case VARIABLE_WIDTH:
313 			for (int i = 1; i < s; i++) {
314 				if (!fixed[i])
315 					lst_Font->show(i);
316 				else
317 					lst_Font->hide(i);
318 			}
319 			break;
320 		case ALL_TYPES:
321 			for (int i = 1; i < s; i++)
322 				lst_Font->show(i);
323 			break;
324 	}
325 	lst_Font->topline(lst_Font->value());
326 }
327 
328 //////////////////////////////////////////////////////////////////////
329 
Preview_Box(int x,int y,int w,int h,const char * l)330 Preview_Box::Preview_Box(int x, int y, int w, int h, const char* l)
331 : Fl_Widget(x, y, w, h, l)
332 {
333 	fontName = 1;
334 	fontSize = FL_NORMAL_SIZE;
335 	box(FL_DOWN_BOX);
336 	color(FL_BACKGROUND2_COLOR);
337 	fontColor = FL_FOREGROUND_COLOR;
338 }
339 
draw()340 void Preview_Box::draw()
341 {
342 	draw_box();
343 	fl_font((Fl_Font)fontName, fontSize);
344 	fl_color(fontColor);
345 	fl_draw(label(), x()+3, y()+3, w()-6, h()-6, align());
346 }
347 
SetFont(int fontname,int fontsize,Fl_Color c)348 void Preview_Box::SetFont(int fontname, int fontsize, Fl_Color c)
349 {
350 	fontName = fontname;
351 	fontSize = fontsize;
352 	fontColor = c;
353 	redraw();
354 }
355