fixed dia_image_rgb_data() for non-alpha images
[dia.git] / app / recent_files.c
blob2344da4779c6a8d63bc1f8f6dfe5627043f2877e
1 /* -*- Mode: C; c-basic-offset: 4 -*- */
2 /* Dia -- an diagram creation/manipulation program
3 * Copyright (C) 1998-2000 Alexander Larsson
5 * recent_files.c: recent files menu dia
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #ifdef GNOME
27 #include <gnome.h>
28 #else
29 #include <gdk/gdkkeysyms.h>
30 #endif
32 #include <glib.h>
33 #include <gtk/gtk.h>
34 #include <stdio.h>
35 #include <string.h>
37 #include "dia_dirs.h"
38 #include "recent_files.h"
39 #include "menus.h"
40 #include "diagram.h"
41 #include "display.h"
42 #include "interface.h"
43 #include "layer_dialog.h"
44 #include "preferences.h"
45 #include "../lib/filter.h"
46 #include "../lib/intl.h"
47 #include "message.h"
49 static GList *recent_files = NULL;
50 static guint recent_files_length = 0;
51 static guint recent_files_menuitem_offset = 0;
52 static GtkTooltips *tooltips = 0;
54 /* file and import filter name */
55 typedef struct _RecentFileData
57 gchar *filename;
58 gchar *importfilterdescription;
59 } RecentFileData;
61 static void open_recent_file_callback (GtkWidget *widget, RecentFileData *file);
62 void recent_file_history_remove (const char *fname);
64 static RecentFileData *
65 recent_file_filedata_new(const char *fname, DiaImportFilter *ifilter)
67 RecentFileData *filedata;
69 filedata = g_new(RecentFileData, 1);
70 filedata->filename = g_strdup(fname);
72 if (ifilter)
73 filedata->importfilterdescription
74 = g_strdup(ifilter->description);
75 else
76 filedata->importfilterdescription = NULL;
78 return (filedata);
81 static void
82 recent_file_menuitem_create(GtkWidget *menu,
83 RecentFileData *filedata, guint pos)
85 gchar *basename, *label;
86 GtkWidget *item;
87 GtkAccelGroup *accel_group;
89 basename = g_strdup(g_basename(filedata->filename));
90 basename = g_strdelimit(basename, "_", '\\');
91 basename = g_strescape(basename, NULL);
92 basename = g_strdelimit(basename, "\\", '_');
94 label = g_strdup_printf("%d. %s", pos, basename);
95 item = gtk_menu_item_new_with_label(label);
97 gtk_menu_insert(GTK_MENU(menu), item,
98 pos + recent_files_menuitem_offset);
100 gtk_signal_connect(GTK_OBJECT(item), "activate",
101 GTK_SIGNAL_FUNC(open_recent_file_callback),filedata);
103 gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), item,
104 filedata->filename, NULL);
106 if (pos < 10)
108 accel_group = gtk_accel_group_new();
109 gtk_window_add_accel_group(GTK_WINDOW(
110 interface_get_toolbox_shell()),
111 accel_group);
112 gtk_widget_add_accelerator(item, "activate", accel_group,
113 GDK_1 + pos - 1,
114 GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
117 gtk_widget_show(item);
119 g_free(basename);
120 /* gtk_label_set_text() g_strdup's our label, so... */
121 g_free(label);
124 static gint
125 recent_file_compare_fnames(gconstpointer element, gconstpointer userdata)
127 /* no g_strcmp() in GLib */
128 return strcmp(((RecentFileData *)element)->filename, userdata);
131 static GtkWidget *
132 recent_file_filemenu_get(void)
134 /* Use the Plugins menu item to get a pointer to the File menu,
135 but any item on the File menu will do */
137 return GTK_WIDGET(menus_get_item_from_path(N_("<Toolbox>/File/Plugins"),
138 NULL))->parent;
141 void
142 recent_file_history_add(const char *fname, DiaImportFilter *ifilter,
143 guint is_initial_load)
145 GtkWidget *file_menu;
146 RecentFileData *filedata;
147 guint i, number_of_items;
148 GList *menu_items, *item, *next;
150 file_menu = recent_file_filemenu_get();
152 /* An initial load places filename items in natural order 1, 2, 3,...
153 but new items get inserted in position 1, forcing other items down */
155 if (is_initial_load)
157 filedata = recent_file_filedata_new(fname, ifilter);
158 recent_files = g_list_append(recent_files, filedata);
160 i = g_list_length(recent_files);
162 if (i <= recent_files_length)
163 recent_file_menuitem_create(file_menu, filedata, i);
165 else
167 /* Since the recent filenames on the menu have positional
168 text and accellerators, delete the existing recent file
169 menu items; start fresh each time */
171 menu_items = GTK_MENU_SHELL(file_menu)->children;
172 item = g_list_first(menu_items);
174 for (i = 0; i <= recent_files_menuitem_offset; i++)
175 item = g_list_next(item);
177 number_of_items = MIN(g_list_length(recent_files),
178 recent_files_length);
180 for (i = 0; i < number_of_items; i++)
182 next = g_list_next(item);
184 /* Unlink first, then destroy */
186 menu_items = g_list_remove_link(menu_items, item);
187 gtk_widget_destroy(item->data);
188 g_list_free_1(item);
190 item = next;
193 /* Three (3) cases:
195 a) The filename is not in the 'recent_files' list--
196 insert it in position 1;
197 b) The filename is in the 'recent_files' list but not
198 displayed because it is clipped by 'recent_files_length'--
199 move it to position 1;
200 c) The filename is displayed on the menu--leave it in place.
203 item = g_list_find_custom(recent_files, (gpointer)fname,
204 recent_file_compare_fnames);
205 if (item)
207 i = g_list_position(recent_files, item);
209 /* if (i >= recent_files_length) */
211 recent_files = g_list_remove_link(recent_files,
212 item);
213 recent_files = g_list_concat(item,
214 recent_files);
217 else
219 filedata = recent_file_filedata_new(fname, ifilter);
220 recent_files = g_list_prepend(recent_files, filedata);
223 number_of_items = MIN(g_list_length(recent_files),
224 recent_files_length);
226 item = g_list_first(recent_files);
228 for (i = 1; i <= number_of_items; i++)
230 recent_file_menuitem_create(file_menu, item->data, i);
231 item = g_list_next(item);
236 /* load the recent file history */
237 void
238 recent_file_history_init() {
239 FILE *fp;
240 char *buffer, *history_filename, *filename;
241 DiaImportFilter *ifilter;
242 GtkWidget *file_menu;
243 GtkMenuItem *menu_item;
244 GList *list_item;
246 /* should be ~/.dia/history */
247 history_filename = dia_config_filename("history");
248 if((fp = fopen(history_filename, "r")) == NULL ) {
249 g_free(history_filename);
250 return;
253 /* Must restart dia to use new prefs value */
255 prefs.recent_documents_list_size =
256 CLAMP(prefs.recent_documents_list_size, 0, 16);
257 recent_files_length = prefs.recent_documents_list_size;
259 menu_item = menus_get_item_from_path(N_("<Toolbox>/File/Quit"), NULL);
261 file_menu = recent_file_filemenu_get();
263 list_item = g_list_find(GTK_MENU_SHELL(file_menu)->children,
264 (gpointer)menu_item);
266 recent_files_menuitem_offset
267 = g_list_position(GTK_MENU_SHELL(file_menu)->children,
268 list_item) - 2; /* fudge factor */
270 tooltips = gtk_tooltips_new();
272 buffer = g_new(char, 16000);
273 while (fgets(buffer, 16000, fp)!=NULL) {
274 filename = g_strchomp(buffer);
275 ifilter = filter_guess_import_filter(filename);
276 recent_file_history_add(filename, ifilter, 1);
278 fclose(fp);
280 g_free(buffer);
281 g_free(history_filename);
284 /*save the recent file history */
285 void
286 recent_file_history_write() {
287 GList *recent_list_pointer;
288 FILE *fp;
289 gchar *history_filename;
290 RecentFileData *filedata;
292 /* should be ~/.dia/history */
293 history_filename = dia_config_filename("history");
294 if((fp = fopen(history_filename,"w")) == NULL) {
295 message_error(N_("Can't open history file for writing."));
296 return;
298 recent_list_pointer = g_list_first(recent_files);
299 while(recent_list_pointer != NULL) {
300 filedata = (RecentFileData *)recent_list_pointer->data;
301 fprintf(fp, "%s\n", filedata->filename);
302 if(filedata) {
303 if(filedata->filename)g_free(filedata->filename);
304 if(filedata->importfilterdescription)g_free(filedata->importfilterdescription);
305 g_free(filedata);
307 recent_list_pointer = g_list_next(recent_list_pointer);
309 fclose(fp);
310 g_list_free(recent_files);
313 /* remove a broken file from the history and update menu accordingly
314 * Xing Wang, 2002.06 */
315 void
316 recent_file_history_remove (const char *fname)
318 GtkWidget *file_menu;
319 guint j, i, number_of_items;
320 GList *file, *next, *item, *menu_items;
322 number_of_items = MIN(g_list_length(recent_files),
323 recent_files_length);
325 file = g_list_first (recent_files);
327 for (j = 0; j < number_of_items; j++) {
328 next = g_list_next (file);
329 if (strcmp (((RecentFileData *)file->data)->filename, fname) == 0) {
330 file_menu = recent_file_filemenu_get ();
331 menu_items = GTK_MENU_SHELL(file_menu)->children;
333 /* remove all menu items after THIS ONE */
335 item = g_list_nth (menu_items,
336 recent_files_menuitem_offset + j + 1);
337 for (i = j; i < number_of_items; i++) {
338 next = g_list_next(item);
340 /* Unlink first, then destroy */
342 menu_items = g_list_remove_link(menu_items, item);
343 gtk_widget_destroy(item->data);
344 g_list_free_1(item);
346 item = next;
349 recent_files = g_list_delete_link (recent_files, file);
351 /* recreate all menu items after THIS ONE */
353 number_of_items = MIN(g_list_length(recent_files),
354 recent_files_length);
355 item = g_list_nth (recent_files, j);
356 for (i = j + 1; i <= number_of_items; i++) {
357 recent_file_menuitem_create(file_menu, item->data, i);
358 item = g_list_next(item);
360 return;
362 file = next;
366 static void
367 open_recent_file_callback (GtkWidget *widget, RecentFileData *file) {
368 GList *import_filters;
369 DiaImportFilter *ifilter = NULL;
370 Diagram *diagram = NULL;
372 /* find the import filter */
373 if(file->importfilterdescription != NULL) {
374 import_filters = filter_get_import_filters();
375 do {
376 if(strcmp(((DiaImportFilter *) import_filters->data)->description,
377 file->importfilterdescription) == 0) {
378 ifilter = import_filters->data;
379 break;
382 while((import_filters = g_list_next(import_filters)) != NULL);
384 diagram = diagram_load(file->filename, ifilter);
385 if (diagram != NULL) {
386 diagram_update_extents(diagram);
387 layer_dialog_set_diagram(diagram);
388 new_display(diagram);
389 } else
390 recent_file_history_remove (file->filename);