=== modified file 'font-view.c' --- font-view.c 2007-11-10 01:46:23 +0000 +++ font-view.c 2007-11-10 07:46:41 +0000 @@ -41,6 +41,13 @@ FT_Long face_index, FT_Face *aface); +typedef struct +{ + FT_Face face; + gchar *file; + gchar *title; +} FontInfo; + static const gchar lowercase_text[] = "abcdefghijklmnopqrstuvwxyz"; static const gchar uppercase_text[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static const gchar punctuation_text[] = "0123456789.:,;(*!?')"; @@ -159,7 +166,7 @@ /* calculate size of pixmap to use (with 4 pixels padding) ... */ pixmap_width = 8; pixmap_height = 8; - + font = get_font(xdisplay, face, alpha_size, charset); charset = FcCharSetCopy (font->charset); XftTextExtentsUtf8(xdisplay, font, @@ -367,6 +374,168 @@ return FALSE; } +static GtkWidget* +install_dialog_new(GSList *faces) +{ + GtkWidget *dialog; + GString *fonts; + GSList *face_iter; + FontInfo *face; + + fonts = g_string_sized_new(200); + for (face_iter = faces; face_iter; face_iter = g_slist_next(face_iter)) { + face = face_iter->data; + g_string_prepend(fonts, face->title); + g_string_prepend(fonts, "\n\t"); + } + + dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, + "Install fonts?"); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), + "Do you wish to install the following fonts:%s\nto your personal fonts?", fonts->str); + g_string_free(fonts, TRUE); + + return dialog; +} + +static gint +install_xfer_callback(GnomeVFSXferProgressInfo *info, GSList *faces) +{ + GtkWidget *dialog; + gint result; + FontInfo *font; + char *title; + + switch (info->status) { + case GNOME_VFS_XFER_PROGRESS_STATUS_OK: + return 1; + break; + case GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE: + if ((font = g_slist_nth_data(faces, info->files_total - info->file_index))) + title = font->title; + else + title = info->source_name; + + dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, + "Duplicate file"); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), + "The font %s is already installed.", title); + gtk_dialog_add_buttons(GTK_DIALOG(dialog), + "Replace old font", GNOME_VFS_XFER_OVERWRITE_ACTION_REPLACE, + "Keep old font", GNOME_VFS_XFER_OVERWRITE_ACTION_SKIP, NULL); + result = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + return result; + break; + default: + return GNOME_VFS_XFER_ERROR_ACTION_ABORT; + } +} + +static void +install_fonts(GSList *faces) +{ + FontInfo *font; + GtkWidget *dialog; + gchar *from_uri, *basename, *dirname, *fontsdir; + GError *error; + GList *from_list = NULL, *to_list = NULL; + GSList *face_iter; + GnomeVFSURI *from, *to, *fonts; + GnomeVFSResult result; + + if (!(fonts = gnome_vfs_uri_new("fonts:/"))) { + dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + "Could not open fonts:// folder"); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), + "Gnome was unable to install the selected fonts to your user's font folder."); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + } + + for (face_iter = faces; face_iter; face_iter = g_slist_next(face_iter)) { + font = face_iter->data; + + if (!(from_uri = gnome_vfs_make_uri_from_shell_arg(font->file))) + g_printerr("could not make uri \"%s\"", font->file); + else { + if (!(from = gnome_vfs_uri_new(from_uri))) + g_printerr("could not create new uri \"%s\"", from_uri); + else { + fontsdir = g_strconcat(g_get_home_dir(), G_DIR_SEPARATOR_S, ".fonts", NULL); + dirname = gnome_vfs_uri_extract_dirname(from); + basename = gnome_vfs_uri_extract_short_name(from); + to = gnome_vfs_uri_append_file_name(fonts, basename); + if (g_str_equal(fontsdir, dirname)) + g_printerr("Skipping installation of existing font %s\n", + gnome_vfs_uri_to_string(from, GNOME_VFS_URI_HIDE_PASSWORD)); + else { + from_list = g_list_prepend(from_list, from); + to_list = g_list_prepend(to_list, to); + } + + g_free(fontsdir); + g_free(basename); + g_free(dirname); + } + + g_free(from_uri); + } + } + + if (from_list && to_list) { + result = gnome_vfs_xfer_uri_list(from_list, to_list, GNOME_VFS_XFER_DEFAULT, GNOME_VFS_XFER_ERROR_MODE_QUERY, + GNOME_VFS_XFER_OVERWRITE_MODE_QUERY, (GnomeVFSXferProgressCallback)install_xfer_callback, faces); + switch (result) { + case GNOME_VFS_OK: + g_print("calling fc-cache..."); + if (g_spawn_command_line_async("fc-cache", &error)) + g_print("...done\n"); + else { + dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + "Could not update font cache"); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), + "Gnome was unable to update information about your system's fonts. \ +The fonts were installed, but may not be useable until you log out and log back in."); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + } + break; + case GNOME_VFS_ERROR_FILE_EXISTS: + case GNOME_VFS_ERROR_CANCELLED: + break; + default: + dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + "Could not install fonts"); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), + "Gnome was unable to install the selected fonts to your user's font folder. \ +Error:\n\tgnome_vfs_xfer_uri_list returned \"%s\"", gnome_vfs_result_to_string(result)); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + } + + gnome_vfs_uri_list_free(from_list); + gnome_vfs_uri_list_free(to_list); + } else { + g_printerr("No valid fonts to install!\n"); + } + + gnome_vfs_uri_unref(fonts); +} + +static void +install_fonts_clicked(GSList *faces) +{ + GtkWidget *dialog; + + dialog = install_dialog_new(faces); + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) + install_fonts(faces); + + gtk_widget_destroy(dialog); +} + static void set_icon(GtkWindow *window, const gchar *uri) { @@ -386,15 +555,24 @@ g_free(icon_name); } +static void +usage() +{ + g_printerr("usage: gnome-font-viewer [--install] FONTFILE [FONTFILES...]\n"); +} + + int main(int argc, char **argv) { FT_Error error; FT_Library library; - FT_Face face; - gchar *font_file, *title; - gint row; - GtkWidget *window, *vbox, *table, *swin, *drawing_area; + FontInfo *face = NULL; + GSList *faces = NULL, *face_iter; + gboolean install_only; + gchar *label_text; + gint row, num_faces, i, arg_i; + GtkWidget *window, *wbox, *bar, *install, *vbox, *table, *swin, *drawing_area, *notebook, *label, *close; GdkPixmap *pixmap; GdkColor white = { 0, 0xffff, 0xffff, 0xffff }; @@ -404,8 +582,8 @@ gtk_init(&argc, &argv); - if (argc != 2) { - g_printerr(_("usage: %s fontfile\n"), argv[0]); + if (argc < 2) { + usage(); return 1; } @@ -423,61 +601,134 @@ if (error) { g_printerr("could not initialise freetype\n"); return 1; - } - - font_file = gnome_vfs_make_uri_from_shell_arg (argv[1]); - if (!font_file) { - g_printerr("could not parse argument into a URI\n"); - return 1; - } - - error = FT_New_Face_From_URI(library, font_file, 0, &face); - if (error) { - g_printerr("could not load face '%s'\n", font_file); - return 1; - } - - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - title = g_strconcat(face->family_name, - face->style_name ? ", " : "", - face->style_name, NULL); - gtk_window_set_title(GTK_WINDOW(window), title); - set_icon(GTK_WINDOW(window), font_file); - g_free(title); - gtk_window_set_resizable(GTK_WINDOW(window), TRUE); - - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(window), vbox); - - table = gtk_table_new(1, 2, FALSE); - gtk_container_set_border_width(GTK_CONTAINER(table), 5); - gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, TRUE, 0); - - row = 0; - add_face_info(table, &row, font_file, face); - - gtk_table_set_col_spacings(GTK_TABLE(table), 8); - gtk_table_set_row_spacings(GTK_TABLE(table), 2); - - swin = gtk_scrolled_window_new(NULL, NULL); - gtk_widget_set_size_request(swin, 500, 200); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_box_pack_start(GTK_BOX(vbox), swin, TRUE, TRUE, 0); - - drawing_area = gtk_drawing_area_new(); - gtk_widget_modify_bg(drawing_area, GTK_STATE_NORMAL, &white); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), - drawing_area); - - pixmap = create_text_pixmap(drawing_area, face); - - g_signal_connect(drawing_area, "expose_event", - G_CALLBACK(expose_event), pixmap); - g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); - - gtk_widget_show_all(window); - - gtk_main(); + } + + if (g_str_equal("--install", argv[1])) { + install_only = TRUE; + arg_i = 2; + } else { + install_only = FALSE; + arg_i = 1; + } + + num_faces = 0; + for (i = arg_i; i < argc; i++) { + face = g_slice_new(FontInfo); + if (!face) { + g_printerr("could not allocate font memory\n"); + return 1; + } + + face->file = gnome_vfs_make_uri_from_shell_arg (argv[i]); + if (!face->file) { + g_printerr("could not parse argument into a URI\n"); + continue; + } + + error = FT_New_Face_From_URI(library, face->file, 0, &face->face); + if (error) { + g_printerr("could not load face '%s'\n", face->file); + g_free(face->file); + g_slice_free(FontInfo, face); + continue; + } + + face->title = g_strconcat(face->face->family_name, + face->face->style_name ? ", " : "", + face->face->style_name, NULL); + faces = g_slist_prepend(faces, face); + num_faces++; + } + + if (num_faces < 1) { + usage(); + return 1; + } + + if (install_only) { + window = install_dialog_new(faces); + + if (gtk_dialog_run(GTK_DIALOG(window)) == GTK_RESPONSE_OK) + install_fonts(faces); + + gtk_widget_destroy(window); + } else { + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + notebook = gtk_notebook_new(); + + set_icon(GTK_WINDOW(window), ((FontInfo *)faces->data)->file); + gtk_window_set_resizable(GTK_WINDOW(window), TRUE); + g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); + if (num_faces == 1) { + gtk_window_set_title(GTK_WINDOW(window), ((FontInfo *)faces->data)->title); + label_text = "_Install font"; + + gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE); + gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE); + + } else { + gtk_window_set_title(GTK_WINDOW(window), "Font Viewer"); + label_text = "_Install fonts"; + } + wbox = gtk_vbox_new(FALSE, 0); + bar = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(bar), GTK_BUTTONBOX_END); + install = gtk_button_new_with_mnemonic(label_text); + gtk_button_set_image(GTK_BUTTON(install), + gtk_image_new_from_stock(GTK_STOCK_APPLY, GTK_ICON_SIZE_BUTTON)); + g_signal_connect_swapped(install, "clicked", G_CALLBACK(install_fonts_clicked), faces); + close = gtk_button_new_from_stock(GTK_STOCK_CLOSE); + g_signal_connect(close, "clicked", G_CALLBACK(gtk_main_quit), NULL); + gtk_box_pack_end_defaults(GTK_BOX(bar), install); + gtk_box_pack_end_defaults(GTK_BOX(bar), close); + gtk_box_pack_start(GTK_BOX(wbox), notebook, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(wbox), bar, FALSE, FALSE, 15); + gtk_container_add(GTK_CONTAINER(window), wbox); + + for (face_iter = faces; face_iter; face_iter = g_slist_next(face_iter)) { + face = (FontInfo *)face_iter->data; + vbox = gtk_vbox_new(FALSE, 0); + label = gtk_label_new(face->title); + gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), vbox, label); + + table = gtk_table_new(1, 2, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, TRUE, 0); + + row = 0; + add_face_info(table, &row, face->file, face->face); + + gtk_table_set_col_spacings(GTK_TABLE(table), 8); + gtk_table_set_row_spacings(GTK_TABLE(table), 2); + + swin = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_set_size_request(swin, 500, 200); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(vbox), swin, TRUE, TRUE, 0); + + drawing_area = gtk_drawing_area_new(); + gtk_widget_modify_bg(drawing_area, GTK_STATE_NORMAL, &white); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), + drawing_area); + + pixmap = create_text_pixmap(drawing_area, face->face); + g_signal_connect(drawing_area, "expose_event", + G_CALLBACK(expose_event), pixmap); + } + + gtk_widget_show_all(window); + + gtk_main(); + } + + for (face_iter = faces; face_iter; face_iter = g_slist_next(face_iter)) { + face = (FontInfo *)face_iter->data; + + g_free(face->title); + g_free(face->file); + FT_Done_Face(face->face); + g_slice_free(FontInfo, face); + } return 0; }