1 /*
2  * Copyright (c) 2008-2010 Lu, Chao-Ming (Tetralet).  All rights reserved.
3  *
4  * This file is part of LilyTerm.
5  *
6  * LilyTerm is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * LilyTerm 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with LilyTerm.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "font.h"
21 
22 // extern GtkWidget *current_vte;
23 extern GtkWidget *menu_active_window;
24 
set_vte_font(GtkWidget * widget,Font_Set_Type type)25 void set_vte_font(GtkWidget *widget, Font_Set_Type type)
26 {
27 #ifdef DETAIL
28 	g_debug("! Launch set_vte_font() with type = %d", type);
29 #endif
30 #ifdef SAFEMODE
31 	if (menu_active_window==NULL) return;
32 #endif
33 
34 	// GtkWidget *vte = current_vte;
35 	struct Window *win_data = (struct Window *)g_object_get_data(G_OBJECT(menu_active_window), "Win_Data");
36 #ifdef SAFEMODE
37 	if (win_data==NULL) return;
38 #endif
39 	GtkWidget *vte = win_data->current_vte;
40 	gchar *new_font_name = NULL;
41 
42 	// type 0, FONT_RESET: reset current page's font size
43 	// type 1, FONT_INCREASE: increase current page's font size
44 	// type 2, FONT_DECREASE: decrease current page's font size
45 	// type 3, FONT_ZOOM_OUT: increase window size & font size for every vte
46 	// type 4, FONT_ZOOM_IN: decrease window size & font size for every vte
47 	// type 5, FONT_RESET_DEFAULT: reset window size & font size to default for every vte
48 	// type 6, FONT_RESET_SYSTEM: reset window size & font size to system for every vte
49 	// type 7, FONT_SET_TO_SELECTED: change every vte to the selected font name
50 
51 	switch (type)
52 	{
53 		case FONT_RESET:		// 0
54 			// reset current page's font size
55 			new_font_name = get_resize_font(vte, FONT_NAME_RESTORE);
56 			reset_vte_size(vte, new_font_name, RESET_CURRENT_TAB_FONT);
57 			break;
58 		case FONT_INCREASE:		// 1
59 			// increase current page's font size
60 			new_font_name = get_resize_font(vte, FONT_NAME_INCREASE);
61 			reset_vte_size(vte, new_font_name, RESET_CURRENT_TAB_FONT);
62 			break;
63 		case FONT_DECREASE:		// 2
64 			// decrease current page's font size
65 			new_font_name = get_resize_font(vte, FONT_NAME_DECREASE);
66 			reset_vte_size(vte, new_font_name, RESET_CURRENT_TAB_FONT);
67 			break;
68 		case FONT_ZOOM_OUT:		// 3
69 			// increase window size & font size for every vte
70 			new_font_name = get_resize_font(vte, FONT_NAME_ZOOM_OUT);
71 			reset_vte_size(vte, new_font_name, RESET_ALL_TO_CURRENT_TAB);
72 			break;
73 		case FONT_ZOOM_IN:		// 4
74 			// decrease window size & font size for every vte
75 			new_font_name = get_resize_font(vte, FONT_NAME_ZOOM_IN);
76 			reset_vte_size(vte, new_font_name, RESET_ALL_TO_CURRENT_TAB);
77 			break;
78 		case FONT_RESET_DEFAULT:	// 5
79 			// reset window size & font size to default for every vte
80 			new_font_name = get_resize_font(vte, FONT_NAME_DEFAULT);
81 			reset_vte_size(vte, new_font_name, RESET_ALL_TO_DEFAULT);
82 			break;
83 		case FONT_RESET_SYSTEM:		// 6
84 			// reset window size & font size to system for every vte
85 			new_font_name = get_resize_font(vte, FONT_NAME_SYSTEM);
86 			reset_vte_size(vte, new_font_name, RESET_ALL_TO_SYSTEM);
87 			break;
88 		case FONT_SET_TO_SELECTED:	// 7
89 			// change every vte to the selected font name
90 			new_font_name = get_resize_font(vte, FONT_NAME_UPDATE);
91 			reset_vte_size(vte, new_font_name, RESET_ALL_TO_CURRENT_TAB);
92 			break;
93 		default:
94 #ifdef FATAL
95 			print_switch_out_of_range_error_dialog("set_vte_font", "type", type);
96 #endif
97 			break;
98 	}
99 	g_free(new_font_name);
100 }
101 
102 // it will update the new_font_name and page_data->font_name
get_resize_font(GtkWidget * vte,Font_Name_Type type)103 gchar *get_resize_font(GtkWidget *vte, Font_Name_Type type)
104 {
105 #ifdef DETAIL
106 	g_debug("! Launch get_resize_font() for vte %p with type %d", vte, type);
107 #endif
108 #ifdef SAFEMODE
109 	if (vte==NULL) return NULL;
110 #endif
111 	// we must insure that vte!=NULL
112 	struct Page *page_data = (struct Page *)g_object_get_data(G_OBJECT(vte), "Page_Data");
113 #ifdef SAFEMODE
114 	if (page_data==NULL) return NULL;
115 #endif
116 	struct Window *win_data = (struct Window *)g_object_get_data(G_OBJECT(page_data->window), "Win_Data");
117 #ifdef SAFEMODE
118 	if (win_data==NULL) return NULL;
119 #endif
120 	// g_debug("Get win_data = %d when get resize font!", win_data);
121 	// type 0, FONT_NAME_DEFAULT: restore font to default_font_name
122 	// type 1, FONT_NAME_SYSTEM: restore font to system_font_name
123 	// type 2, FONT_NAME_RESTORE: restore font to restore_font_name
124 	// type 3, FONT_NAME_UPDATE: do nothing but only update new_font_name
125 	// type 4, FONT_NAME_ZOOM_OUT: increase window by *1.1 or +1
126 	// type 5, FONT_NAME_ZOOM_IN: decrease window by /1.1 or -1
127 	// type 6, FONT_NAME_INCREASE: increase font by *1.1 or +1
128 	// type 7, FONT_NAME_DECREASE: decrease font by /1.1 or -1
129 
130 	if (win_data->restore_font_name == NULL)
131 	{
132 		// win_data->restore_font_name = g_strdup(page_data->font_name);
133 		win_data->restore_font_name = g_strdup(win_data->default_font_name);
134 		// g_debug("Restore the font to %s!", win_data->restore_font_name);
135 		if (type==FONT_NAME_RESTORE)
136 			return g_strdup(page_data->font_name);
137 	}
138 
139 	switch (type)
140 	{
141 		case FONT_NAME_DEFAULT:
142 		case FONT_NAME_SYSTEM:
143 		case FONT_NAME_RESTORE:
144 			g_free(page_data->font_name);
145 			break;
146 		default:
147 			break;
148 	}
149 
150 	// we use font_size to save current font size
151 	// font_size = (the size in font_name) * PANGO_SCALE
152 	// if font_size == 0 -> use the data in font_name
153 
154 	switch (type)
155 	{
156 		case FONT_NAME_DEFAULT:
157 			// restore font to default_font_name
158 			page_data->font_name = g_strdup(win_data->default_font_name);
159 			page_data->font_size = 0;
160 			break;
161 		case FONT_NAME_SYSTEM:
162 			// restore font to default_font_name
163 			page_data->font_name = g_strdup(SYSTEM_FONT_NAME);
164 			page_data->font_size = 0;
165 			break;
166 		case FONT_NAME_RESTORE:
167 			// restore font to default_font_name
168 			page_data->font_name = g_strdup(win_data->restore_font_name);
169 			page_data->font_size = 0;
170 			break;
171 		case FONT_NAME_UPDATE:
172 			break;
173 		case FONT_NAME_ZOOM_OUT:
174 		case FONT_NAME_ZOOM_IN:
175 		case FONT_NAME_INCREASE:
176 		case FONT_NAME_DECREASE:
177 		{
178 #ifdef SAFEMODE
179 			if (page_data->font_name==NULL) break;
180 #endif
181 			gint oldfontsize=0, fontsize=0;
182 
183 			// g_debug("old font name: %s", page_data->font_name);
184 			PangoFontDescription *font_desc = pango_font_description_from_string(
185 								page_data->font_name);
186 			// increase/decrease font
187 			oldfontsize = (pango_font_description_get_size(font_desc)/PANGO_SCALE);
188 			if (page_data->font_size==0)
189 				page_data->font_size = pango_font_description_get_size(font_desc);
190 
191 			switch (type)
192 			{
193 				// g_debug("window_resize_ratio = %f",  win_data->window_resize_ratio);
194 				case FONT_NAME_ZOOM_OUT:
195 					if (win_data->window_resize_ratio)
196 						page_data->font_size = page_data->font_size *
197 								       win_data->window_resize_ratio +
198 								       0.5;
199 					else
200 						page_data->font_size = page_data->font_size + PANGO_SCALE;
201 					break;
202 				case FONT_NAME_ZOOM_IN:
203 					if (win_data->window_resize_ratio)
204 						page_data->font_size = page_data->font_size /
205 								       win_data->window_resize_ratio +
206 								       0.5;
207 					else
208 						page_data->font_size = page_data->font_size - PANGO_SCALE;
209 					break;
210 				case FONT_NAME_INCREASE:
211 					if (win_data->font_resize_ratio)
212 						page_data->font_size = page_data->font_size *
213 								       win_data->font_resize_ratio +
214 								       0.5;
215 					else
216 						page_data->font_size = page_data->font_size + PANGO_SCALE;
217 					break;
218 				case FONT_NAME_DECREASE:
219 					if (win_data->font_resize_ratio)
220 						page_data->font_size = page_data->font_size /
221 								       win_data->font_resize_ratio +
222 								       0.5;
223 					else
224 						page_data->font_size = page_data->font_size - PANGO_SCALE;
225 					break;
226 				default:
227 					break;
228 			}
229 			// g_debug("font_size = %d", page_data->font_size);
230 			fontsize = (page_data->font_size)/PANGO_SCALE;
231 
232 			// to avoid the fontsize is unchanged or = 0
233 			switch (type)
234 			{
235 				case FONT_NAME_ZOOM_OUT:
236 				case FONT_NAME_INCREASE:
237 					if (oldfontsize==fontsize)
238 						fontsize++;
239 					break;
240 				case FONT_NAME_ZOOM_IN:
241 				case FONT_NAME_DECREASE:
242 					if (oldfontsize==fontsize)
243 						fontsize--;
244 					if (fontsize<1)
245 						fontsize=1;
246 					break;
247 				default:
248 					break;
249 			}
250 
251 			// g_debug("Trying to change the font size to %d.", fontsize);
252 			pango_font_description_set_size(font_desc, fontsize*PANGO_SCALE);
253 			g_free(page_data->font_name);
254 			page_data->font_name = pango_font_description_to_string(font_desc);
255 			pango_font_description_free(font_desc);
256 			break;
257 		default:
258 #ifdef FATAL
259 			print_switch_out_of_range_error_dialog("get_resize_font", "type", type);
260 #endif
261 			return NULL;
262 		}
263 	}
264 
265 	// g_debug("new font name: %s", page_data->font_name);
266 
267 	switch (type)
268 	{
269 		case FONT_NAME_DEFAULT:
270 		case FONT_NAME_SYSTEM:
271 		case FONT_NAME_UPDATE:
272 		case FONT_NAME_ZOOM_OUT:
273 		case FONT_NAME_ZOOM_IN:
274 			// if not using <Ctrl><+ - enter> to change the font size.
275 			g_free(win_data->restore_font_name);
276 			win_data->restore_font_name = g_strdup(page_data->font_name);
277 			break;
278 		case FONT_NAME_INCREASE:
279 		case FONT_NAME_DECREASE:
280 			// Check if we can specify page_data->font_size = 0
281 			if ( ! compare_strings(page_data->font_name, win_data->restore_font_name, TRUE))
282 			{
283 				page_data->font_size = 0;
284 				// g_debug("The font is restored to win_data->restore_font_name");
285 			}
286 			break;
287 		default:
288 			break;
289 	}
290 	return g_strdup(page_data->font_name);
291 }
292 
reset_vte_size(GtkWidget * vte,gchar * new_font_name,Font_Reset_Type type)293 void reset_vte_size(GtkWidget *vte, gchar *new_font_name, Font_Reset_Type type)
294 {
295 #ifdef DETAIL
296 	g_debug("! Launch reset_vte_size() with vte = %p, new_font_name = %s, type = %d",
297 		vte, new_font_name, type);
298 #endif
299 #ifdef SAFEMODE
300 	if ((vte==NULL) || (new_font_name==NULL)) return;
301 #endif
302 
303 	// type 0, RESET_CURRENT_TAB_FONT: change current page's font
304 	// type 1, RESET_ALL_TO_CURRENT_TAB: apply current column & row to every vte
305 	// type 2, RESET_ALL_TO_DEFAULT: apply default column & row to every vte
306 	// type 3, RESET_ALL_TO_SYSTEM: apply system column & row to every vte
307 
308 	struct Page *page_data = (struct Page *)g_object_get_data(G_OBJECT(vte), "Page_Data");
309 #ifdef SAFEMODE
310 	if (page_data==NULL) return;
311 #endif
312 	struct Window *win_data = (struct Window *)g_object_get_data(G_OBJECT(page_data->window), "Win_Data");
313 #ifdef SAFEMODE
314 	if (win_data==NULL) return;
315 #endif
316 	// g_debug("Get win_data = %d when reset vte size!", win_data);
317 
318 	switch (type)
319 	{
320 		case RESET_CURRENT_TAB_FONT:
321 			// We need to apply a new font to a single vte.
322 			// so that we should insure that this won't change the size of window.
323 			// g_debug("Trying to apply font %s to vte", current_font_name);
324 			vte_terminal_set_font_from_string_full( VTE_TERMINAL(vte),
325 								new_font_name,
326 								win_data->font_anti_alias);
327 			// g_debug("reset_vte_size(): call window_resizable() with run_once = %d", win_data->update_hints);
328 			// g_debug("reset_vte_size(): launch update_window_hint()!");
329 			update_window_hint(win_data, page_data);
330 			break;
331 		case RESET_ALL_TO_CURRENT_TAB:
332 			// increase/decrease window size & font size for every vte
333 			// g_debug("Trying to apply font %s to every vte", current_font_name);
334 			// struct Page *page_data = (struct Page *)g_object_get_data(G_OBJECT(current_vte), "Page_Data");
335 			apply_font_to_every_vte( page_data->window, new_font_name,
336 						 vte_terminal_get_column_count(VTE_TERMINAL(win_data->current_vte)),
337 						 vte_terminal_get_row_count(VTE_TERMINAL(win_data->current_vte)));
338 			break;
339 		case RESET_ALL_TO_DEFAULT:
340 			// reset window size & font size for every vte
341 			// g_debug("Trying to apply font %s to every vte", current_font_name);
342 			apply_font_to_every_vte(page_data->window, new_font_name,
343 						win_data->default_column, win_data->default_row);
344 			break;
345 		case RESET_ALL_TO_SYSTEM:
346 			// reset window size & font size for every vte
347 			// g_debug("Trying to apply font %s to every vte", current_font_name);
348 			apply_font_to_every_vte(page_data->window, new_font_name,
349 						SYSTEM_COLUMN, SYSTEM_ROW);
350 			break;
351 		default:
352 #ifdef FATAL
353 			print_switch_out_of_range_error_dialog("reset_vte_size", "type", type);
354 #endif
355 			break;
356 	}
357 }
358 
apply_font_to_every_vte(GtkWidget * window,gchar * new_font_name,glong column,glong row)359 void apply_font_to_every_vte(GtkWidget *window, gchar *new_font_name, glong column, glong row)
360 {
361 #ifdef DETAIL
362 	g_debug("! Launch apply_font_to_every_vte() with window = %p, new_font_name = %s,"
363 		" column = %ld, row = %ld", window, new_font_name, column, row);
364 #endif
365 #ifdef SAFEMODE
366 	if ((window==NULL) || (new_font_name==NULL) || (column<1) || (row<1)) return;
367 #endif
368 	struct Window *win_data = (struct Window *)g_object_get_data(G_OBJECT(window), "Win_Data");
369 	// g_debug("Get win_data = %d when apply font to every vte!", win_data);
370 #ifdef SAFEMODE
371 	if (win_data==NULL) return;
372 #endif
373 
374 	struct Page *page_data = NULL;
375 	gint i;
376 
377 	// g_debug("Trying to apply every vte to %dx%d!", column, row);
378 	// g_debug("Trying to apply font %s to every vte!", new_font_name);
379 
380 	for (i=0; i<gtk_notebook_get_n_pages(GTK_NOTEBOOK(win_data->notebook)); i++)
381 	{
382 		page_data = get_page_data_from_nth_page(win_data, i);
383 #ifdef SAFEMODE
384 		if (page_data==NULL) continue;
385 #endif
386 #ifdef USE_GTK3_GEOMETRY_METHOD
387 		save_current_vte_geometry(win_data, page_data->vte);
388 #endif
389 		// g_debug("The default font for %d page is: %s (%s)", i, page_data->font_name, new_font_name);
390 		vte_terminal_set_font_from_string_full(VTE_TERMINAL(page_data->vte),
391 						       new_font_name,
392 						       win_data->font_anti_alias);
393 		vte_terminal_set_size(VTE_TERMINAL(page_data->vte), column, row);
394 #ifdef USE_GTK3_GEOMETRY_METHOD
395 		page_data->column = column;
396 		page_data->row = row;
397 #  ifdef GEOMETRY
398 		g_debug("@ apply_font_to_every_vte (for %p): Trying set the geometry to %ld x %ld",
399 			window, column, row);
400 #  endif
401 #endif
402 		g_free(page_data->font_name);
403 		page_data->font_name = g_strdup(new_font_name);
404 
405 		// g_debug("The new font for %d page is: %s (%s)", i, page_data->font_name, new_font_name);
406 	}
407 
408 	// g_debug("Set hints to FALSE!");
409 	win_data->update_hints = 1;
410 	// win_data->keep_vte_size |= 0x30;
411 	// g_debug("window_resizable in apply_font_to_every_vte!");
412 	// window_resizable(window, page_data->vte, 2, 1);
413 	// g_debug("apply_font_to_every_vte(): launch keep_window_size()!");
414 #ifdef USE_GTK2_GEOMETRY_METHOD
415 #  ifdef GEOMETRY
416 	g_debug("@ apply_font_to_every_vte(): Call keep_gtk2_window_size() with win_data->unfullscreen = %d",
417 		win_data->unfullscreen);
418 #  endif
419 	// Don't need to call keep_gtk2_window_size() when fullscreen
420 	switch (win_data->unfullscreen)
421 	{
422 		case 0:
423 		case 2:
424 #  ifdef GEOMETRY
425 			g_debug("@ apply_font_to_every_vte(): Call keep_gtk2_window_size() with keep_vte_size = %x",
426 				win_data->keep_vte_size);
427 #  endif
428 			keep_gtk2_window_size (win_data, page_data->vte, 0x380);
429 			break;
430 	}
431 #endif
432 #ifdef USE_GTK3_GEOMETRY_METHOD
433 	win_data->keep_vte_size += 2;
434 #  ifdef GEOMETRY
435 	g_debug("@ apply_font_to_every_vte(for %p): Set win_data->keep_vte_size to %d",
436 		win_data->window, win_data->keep_vte_size);
437 #  endif
438 #endif
439 }
440 
check_if_every_vte_is_using_restore_font_name(struct Window * win_data)441 gboolean check_if_every_vte_is_using_restore_font_name(struct Window *win_data)
442 {
443 #ifdef DETAIL
444 	g_debug("! Launch check_if_every_vte_is_using_restore_font_name() with win_data = %p", win_data);
445 #endif
446 #ifdef SAFEMODE
447 	if ((win_data==NULL) || (win_data->notebook==NULL)) return FALSE;
448 #endif
449 	if (win_data->restore_font_name == NULL)
450 	//	win_data->restore_font_name = g_strdup(page_data->font_name);
451 		win_data->restore_font_name = g_strdup(win_data->default_font_name);
452 
453 	gint i;
454 	struct Page *page_data = NULL;
455 	gboolean return_value = TRUE;
456 	for (i=0; i<gtk_notebook_get_n_pages(GTK_NOTEBOOK(win_data->notebook)); i++)
457 	{
458 		page_data = get_page_data_from_nth_page(win_data, i);
459 #ifdef SAFEMODE
460 		if (page_data==NULL) continue;
461 #endif
462 		if (compare_strings(page_data->font_name, win_data->restore_font_name, TRUE))
463 		{
464 			return_value = FALSE;
465 			break;
466 		}
467 	}
468 	return return_value;
469 }
470 
471