HACK: 1. try to match RowsetProperties
[wireshark-wip.git] / ui / gtk / font_utils.c
blob02eb079230993a4487dd2c0f8d8c5b2eecca7a36
1 /* font_utils.c
2 * Utilities to use for font manipulation
4 * $Id$
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "config.h"
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
30 #include <gtk/gtk.h>
32 #include <epan/packet.h>
33 #include <epan/prefs.h>
35 #ifdef _WIN32
36 #include <windows.h>
37 #include <tchar.h>
38 #include <wsutil/unicode-utils.h>
39 #endif
41 #include "ui/recent.h"
42 #include "ui/simple_dialog.h"
44 #include "ui/gtk/main.h"
45 #include "ui/gtk/gtkglobals.h"
46 #include "ui/gtk/font_utils.h"
47 #include "ui/gtk/packet_panes.h"
48 #include "ui/gtk/follow_tcp.h"
49 #include "ui/gtk/packet_list.h"
52 static PangoFontDescription *m_r_font;
55 /* Get the regular user font.
57 * @return the regular user font
59 PangoFontDescription *user_font_get_regular(void)
61 return m_r_font;
64 static void
65 set_fonts(PangoFontDescription *regular)
67 /* Yes, assert. The code that loads the font should check
68 * for NULL and provide its own error message. */
69 g_assert(m_r_font);
70 m_r_font = regular;
73 void
74 view_zoom_in_cb(GtkWidget *w _U_, gpointer d _U_)
76 gint save_gui_zoom_level;
78 save_gui_zoom_level = recent.gui_zoom_level;
79 recent.gui_zoom_level++;
80 switch (user_font_apply()) {
82 case FA_SUCCESS:
83 break;
85 case FA_FONT_NOT_RESIZEABLE:
86 /* "font_apply()" popped up an alert box. */
87 recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
88 break;
90 case FA_FONT_NOT_AVAILABLE:
91 /* We assume this means that the specified size isn't available. */
92 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
93 "Your current font isn't available in the next larger size.\n");
94 recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
95 break;
99 void
100 view_zoom_out_cb(GtkWidget *w _U_, gpointer d _U_)
102 gint save_gui_zoom_level;
104 save_gui_zoom_level = recent.gui_zoom_level;
105 recent.gui_zoom_level--;
106 switch (user_font_apply()) {
108 case FA_SUCCESS:
109 break;
111 case FA_FONT_NOT_RESIZEABLE:
112 /* "font_apply()" popped up an alert box. */
113 recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
114 break;
116 case FA_FONT_NOT_AVAILABLE:
117 /* We assume this means that the specified size isn't available. */
118 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
119 "Your current font isn't available in the next smaller size.\n");
120 recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
121 break;
125 void
126 view_zoom_100_cb(GtkWidget *w _U_, gpointer d _U_)
128 gint save_gui_zoom_level;
130 save_gui_zoom_level = recent.gui_zoom_level;
131 recent.gui_zoom_level = 0;
132 switch (user_font_apply()) {
134 case FA_SUCCESS:
135 break;
137 case FA_FONT_NOT_RESIZEABLE:
138 /* "font_apply()" popped up an alert box. */
139 recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
140 break;
142 case FA_FONT_NOT_AVAILABLE:
143 /* We assume this means that the specified size isn't available.
144 XXX - this "shouldn't happen". */
145 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
146 "Your current font couldn't be reloaded at the size you selected.\n");
147 recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
148 break;
154 gboolean
155 user_font_test(gchar *font_name)
157 PangoFontDescription *new_r_font;
159 new_r_font = pango_font_description_from_string(font_name);
160 if (new_r_font == NULL) {
161 /* Oops, that font didn't work.
162 Tell the user, but don't tear down the font selection
163 dialog, so that they can try again. */
164 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
165 "The font you selected can't be loaded.");
167 return FALSE;
170 return TRUE;
175 /* Given a font name, construct the name of a version of that font with
176 the current zoom factor applied. */
177 static char *
178 font_zoom(char *gui_font_name)
180 char *new_font_name;
181 char *font_name_dup;
182 char *font_name_p;
183 long font_point_size_l;
185 if (recent.gui_zoom_level == 0) {
186 /* There is no zoom factor - just return the name, so that if
187 this is GTK+ 1.2[.x] and the font name isn't an XLFD font
188 name, we don't fail. */
189 return g_strdup(gui_font_name);
192 font_name_dup = g_strdup(gui_font_name);
194 /* find the start of the font_size string */
195 font_name_p = strrchr(font_name_dup, ' ');
196 *font_name_p = '\0';
197 font_name_p++;
199 /* calculate the new font size */
200 font_point_size_l = strtol(font_name_p, NULL, 10);
201 font_point_size_l += recent.gui_zoom_level;
203 /* build a new font name */
204 new_font_name = g_strdup_printf("%s %ld", font_name_dup, font_point_size_l);
206 g_free(font_name_dup);
208 return new_font_name;
211 fa_ret_t
212 user_font_apply(void) {
213 char *gui_font_name;
214 PangoFontDescription *new_r_font;
215 PangoFontDescription *old_r_font = NULL;
217 /* convert font name to reflect the zoom level */
218 gui_font_name = font_zoom(prefs.gui_gtk2_font_name);
219 if (gui_font_name == NULL) {
221 * This means the font name isn't an XLFD font name.
222 * We just report that for now as a font not available in
223 * multiple sizes.
225 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
226 "Your current font isn't available in any other sizes.\n");
227 return FA_FONT_NOT_RESIZEABLE;
230 /* load normal font */
231 new_r_font = pango_font_description_from_string(gui_font_name);
232 if (new_r_font == NULL) {
233 g_free(gui_font_name);
235 /* We let our caller pop up a dialog box, as the error message
236 depends on the context (did they zoom in or out, or did they
237 do something else? */
238 return FA_FONT_NOT_AVAILABLE;
241 /* the font(s) seem to be ok */
242 packet_list_set_font(new_r_font);
243 set_ptree_font_all(new_r_font);
244 old_r_font = m_r_font;
245 set_fonts(new_r_font);
247 /* Redraw the packet bytes windows. */
248 redraw_packet_bytes_all();
250 /* Redraw the "Follow TCP Stream" windows. */
251 follow_tcp_redraw_all();
253 /* We're no longer using the old fonts; unreference them. */
254 if (old_r_font != NULL)
255 pango_font_description_free(old_r_font);
256 g_free(gui_font_name);
258 return FA_SUCCESS;
262 #ifdef _WIN32
264 #define NAME_BUFFER_LEN 32
266 static char appfontname[128] = "tahoma 8";
268 static void
269 set_app_font_gtk2(const char *fontname)
271 GtkSettings *settings;
273 if (fontname != NULL && *fontname == 0) return;
275 settings = gtk_settings_get_default();
277 if (fontname == NULL) {
278 g_object_set(G_OBJECT(settings), "gtk-font-name", appfontname, NULL);
279 } else {
280 GtkWidget *w;
281 PangoFontDescription *pfd;
282 PangoContext *pc;
283 PangoFont *pfont;
285 w = gtk_label_new(NULL);
286 pfd = pango_font_description_from_string(fontname);
287 pc = gtk_widget_get_pango_context(w);
288 pfont = pango_context_load_font(pc, pfd);
290 if (pfont != NULL) {
291 g_strlcpy(appfontname, fontname, 128);
292 appfontname[127] = '\0';
293 g_object_set(G_OBJECT(settings), "gtk-font-name", appfontname, NULL);
296 gtk_widget_destroy(w);
297 pango_font_description_free(pfd);
301 static char *default_windows_menu_fontspec_gtk2(void)
303 gchar *fontspec = NULL;
304 NONCLIENTMETRICS ncm;
306 memset(&ncm, 0, sizeof ncm);
307 ncm.cbSize = sizeof ncm;
309 if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0)) {
310 HDC screen = GetDC(0);
311 double y_scale = 72.0 / GetDeviceCaps(screen, LOGPIXELSY);
312 int point_size = (int) (ncm.lfMenuFont.lfHeight * y_scale);
314 if (point_size < 0) point_size = -point_size;
315 fontspec = g_strdup_printf("%s %d", ncm.lfMenuFont.lfFaceName,
316 point_size);
317 ReleaseDC(0, screen);
320 return fontspec;
323 static void try_to_get_windows_font_gtk2(void)
325 gchar *fontspec;
327 fontspec = default_windows_menu_fontspec_gtk2();
329 if (fontspec != NULL) {
330 int match;
331 PangoFontDescription *pfd;
332 PangoFont *pfont;
333 PangoContext *pc;
334 GtkWidget *w;
336 pfd = pango_font_description_from_string(fontspec);
338 w = gtk_label_new(NULL);
339 pc = gtk_widget_get_pango_context(w);
340 pfont = pango_context_load_font(pc, pfd);
341 match = (pfont != NULL);
343 pango_font_description_free(pfd);
344 g_object_unref(G_OBJECT(pc));
345 gtk_widget_destroy(w);
347 if (match) set_app_font_gtk2(fontspec);
348 g_free(fontspec);
351 #endif /* _WIN32 */
354 void font_init(void)
356 #ifdef _WIN32
357 /* try to load the application font for GTK2 */
358 try_to_get_windows_font_gtk2();
359 #endif
361 /* Try to load the regular fixed-width font */
362 m_r_font = pango_font_description_from_string(prefs.gui_gtk2_font_name);
363 if (m_r_font == NULL) {
364 /* XXX - pop this up as a dialog box? no */
365 fprintf(stderr, "wireshark: Warning: font %s not found - defaulting to Monospace 9\n",
366 prefs.gui_gtk2_font_name);
367 if ((m_r_font = pango_font_description_from_string("Monospace 9")) == NULL)
369 fprintf(stderr, "wireshark: Error: font Monospace 9 not found\n");
370 exit(1);
372 g_free(prefs.gui_gtk2_font_name);
373 prefs.gui_gtk2_font_name = g_strdup("Monospace 9");
376 /* Call this for the side-effects that set_fonts() produces */
377 set_fonts(m_r_font);