Sie sind nicht angemeldet.

Lieber Besucher, herzlich willkommen bei: Ubuntu-Forum & Kubuntu-Forum | www.Ubuntu-Forum.de. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.

  • »ditschi« ist der Autor dieses Themas

Beiträge: 1

Registrierungsdatum: 27.01.2014

Derivat: Kubuntu

Architektur: 64-Bit PC

Desktop: KDE4

  • Nachricht senden

1

27.01.2014, 14:01

Mehrere Patches nacheinander anwenden...

Hallo

Ich möchte mein Xounal um einige Funktionen erweitern: Dazu habe ich mir die zwei Patches (von verschiedenen Personen) Autosave und "Remember Last page seen" von http://sourceforge.net/p/xournal/patches/?page=1 heruntergeladen...

Mein Problem: Wie kann ich BEIDE patches auf den Quellcode anwenden.


Beide Patches scheinen gleiche Dateien zu Modifizieren.

Quellcode

1
 "Reversed (or previously applied) patch detected!  Assume -R? [n}"


Kann ich auf einfache Art sicherstellen dass die Patches sich nicht gegenseitig beeinflussen? (mache das zum ersten Mal :P)


Vielen Dank

Hier noch die beiden Patches:
Remember last Page:

Quellcode

1
diff -rupN xournal-pulito/src/xo-file.c xournal-pulito (copy)//src/xo-file.c--- xournal-pulito/src/xo-file.c	2011-02-26 19:55:18.234366009 +0100+++ xournal-pulito (copy)//src/xo-file.c	2011-03-08 18:53:32.991896005 +0100@@ -92,6 +92,8 @@ gboolean save_journal(const char *filena   gzprintf(f, "<?xml version="1.0" standalone="no"?>\n"      "<xournal version="" VERSION "">\n"      "<title>Xournal document - see http://math.mit.edu/~auroux/software/xournal/</title>\n");+  //save last seen page number in file+  gzprintf(f, "<lastpage number="%d" />\n", ui.pageno);    for (pagelist = journal.pages; pagelist!=NULL; pagelist = pagelist->next) {     pg = (struct Page *)pagelist->data;     gzprintf(f, "<page width="%.2f" height="%.2f">\n", pg->width, pg->height);@@ -246,6 +248,7 @@ struct Layer *tmpLayer; struct Item *tmpItem; char *tmpFilename; struct Background *tmpBg_pdf;+int page_to_load; //NIKO  GError *xoj_invalid(void) {@@ -262,14 +265,27 @@ void xoj_parser_start_element(GMarkupPar   char *tmpbg_filename;   gdouble val;   GtkWidget *dialog;-  -  if (!strcmp(element_name, "title") || !strcmp(element_name, "xournal")) {+  if (!strcmp(element_name, "title") || !strcmp(element_name, "xournal")) {       if (tmpPage != NULL) {       *error = xoj_invalid();       return;     }     // nothing special to do   }+  else if (!strcmp(element_name, "lastpage")) {+  	//handle loading the last seen page by NIKO+  	has_attr=0;+  	while(*attribute_names!=NULL) {+  		if (!strcmp(*attribute_names, "number")) {+  			//printf("pageno\n");+  			//load number from pageno attribute+  			page_to_load = atoi(*attribute_values);+ 		}+ 		//else *error = xoj_invalid();+ 		attribute_names++;+  		attribute_values++;+ 	}+  }	   else if (!strcmp(element_name, "page")) { // start of a page     if (tmpPage != NULL) {       *error = xoj_invalid();@@ -704,6 +720,7 @@ gboolean open_journal(char *filename)   int len;   gchar *tmpfn, *tmpfn2, *p, *q;   gboolean maybe_pdf;+  page_to_load = -1; //by NIKO      tmpfn = g_strdup_printf("%s.xoj", filename);   if (ui.autoload_pdf_xoj && g_file_test(tmpfn, G_FILE_TEST_EXISTS) &&@@ -823,6 +840,10 @@ gboolean open_journal(char *filename)   update_page_stuff();   rescale_bg_pixmaps(); // this requests the PDF pages if need be   gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)), 0);+  //if there is a page number saved in the file, jump to that, by NIKO+  if (page_to_load !=-1) {+  	do_switch_page(page_to_load, TRUE, FALSE);+  }   return TRUE; }



Autosave

Quellcode

1
2
3
4
5
6
7
8
=== modified file 'src/main.c'--- src/main.c	2011-03-10 18:14:21 +0000+++ src/main.c	2011-03-10 18:17:31 +0000@@ -60,6 +60,7 @@   // initialize data   ui.default_page.bg->canvas_item = NULL;   ui.layerbox_length = 0;+  ui.autosave_defers = 0;    if (argc > 2 || (argc == 2 && argv[1][0] == '-')) {     printf(_("Invalid command line parameters.\n"@@ -271,27 +272,6 @@      init_mru(); -  // and finally, open a file specified on the command line-  // (moved here because display parameters weren't initialized yet...)-  -  if (argc == 1) return;-  set_cursor_busy(TRUE);-  if (g_path_is_absolute(argv[1]))-    tmpfn = g_strdup(argv[1]);-  else {-    tmppath = g_get_current_dir();-    tmpfn = g_build_filename(tmppath, argv[1], NULL);-    g_free(tmppath);-  }-  success = open_journal(tmpfn);-  g_free(tmpfn);-  set_cursor_busy(FALSE);-  if (!success) {-    w = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,-       GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), argv[1]);-    gtk_dialog_run(GTK_DIALOG(w));-    gtk_widget_destroy(w);-  } }  @@ -328,6 +308,17 @@   winMain = create_winMain ();      init_stuff (argc, argv);++  if (argc <= 1) {+    // if any autosaves have been restored by spawning child processes, we exit+    // this instance of xournal.+    if (check_and_restore_autosaves (argc, argv))+      return 0;+  }+  else+    open_argv_file_or_its_autosave (argc, argv);++     gtk_window_set_icon(GTK_WINDOW(winMain), create_pixbuf("xournal.png"));      gtk_main ();@@ -336,6 +327,8 @@    save_mru_list();   if (ui.auto_save_prefs) save_config_to_file();++  clear_autosave_entry();      return 0; }
=== modified file 'src/xo-callbacks.c'--- src/xo-callbacks.c	2011-03-10 18:14:21 +0000+++ src/xo-callbacks.c	2011-03-10 18:17:31 +0000@@ -447,7 +447,7 @@   double tmp_x, tmp_y;   gchar *tmpstr;   GnomeCanvasGroup *group;-  +  signal_canvas_changed();   end_text();   if (undo == NULL) return; // nothing to undo!   reset_selection(); // safer@@ -662,6 +662,8 @@   gchar *tmpstr;   GnomeCanvasGroup *group;   +  signal_canvas_changed();+     end_text();   if (redo == NULL) return; // nothing to redo!   reset_selection(); // safer@@ -864,6 +866,7 @@ on_editCut_activate                    (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   selection_to_clip();   selection_delete();@@ -874,6 +877,7 @@ on_editCopy_activate                   (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   selection_to_clip(); }@@ -883,6 +887,7 @@ on_editPaste_activate                  (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   clipboard_paste(); }@@ -892,6 +897,7 @@ on_editDelete_activate                 (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   selection_delete(); }@@ -1059,6 +1065,7 @@ {   struct Page *pg; +  signal_canvas_changed();   end_text();   reset_selection();   pg = new_page(ui.cur_page);@@ -1079,6 +1086,7 @@ {   struct Page *pg; +  signal_canvas_changed();   end_text();   reset_selection();   pg = new_page(ui.cur_page);@@ -1099,6 +1107,7 @@ {   struct Page *pg; +  signal_canvas_changed();   end_text();   reset_selection();   pg = new_page((struct Page *)g_list_last(journal.pages)->data);@@ -1120,6 +1129,7 @@   GList *layerlist, *itemlist;   struct Layer *l; +  signal_canvas_changed();   end_text();   if (journal.npages == 1) return;   reset_selection();  @@ -1155,6 +1165,7 @@ {   struct Layer *l;   +  signal_canvas_changed();   end_text();   reset_selection();   l = g_new(struct Layer, 1);@@ -1183,7 +1194,7 @@                                         gpointer         user_data) {   GList *list;-  +  signal_canvas_changed();   end_text();   if (ui.cur_layer == NULL) return;   reset_selection();@@ -1307,6 +1318,7 @@ on_papercolorWhite_activate            (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   process_papercolor_activate(menuitem, COLOR_WHITE, predef_bgcolors_rgba[COLOR_WHITE]); }@@ -1316,6 +1328,7 @@ on_papercolorYellow_activate           (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   process_papercolor_activate(menuitem, COLOR_YELLOW, predef_bgcolors_rgba[COLOR_YELLOW]); }@@ -1325,6 +1338,7 @@ on_papercolorPink_activate             (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   process_papercolor_activate(menuitem, COLOR_RED, predef_bgcolors_rgba[COLOR_RED]); }@@ -1334,6 +1348,7 @@ on_papercolorOrange_activate           (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   process_papercolor_activate(menuitem, COLOR_ORANGE, predef_bgcolors_rgba[COLOR_ORANGE]); }@@ -1343,6 +1358,7 @@ on_papercolorBlue_activate             (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   process_papercolor_activate(menuitem, COLOR_BLUE, predef_bgcolors_rgba[COLOR_BLUE]); }@@ -1352,6 +1368,7 @@ on_papercolorGreen_activate            (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   process_papercolor_activate(menuitem, COLOR_GREEN, predef_bgcolors_rgba[COLOR_GREEN]); }@@ -1367,6 +1384,7 @@   guint rgba;   GdkColor gdkcolor;   +  signal_canvas_changed();   end_text();   dialog = gtk_color_selection_dialog_new(_("Pick a Paper Color"));   colorsel = GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(dialog)->colorsel);@@ -1387,6 +1405,7 @@ on_paperstylePlain_activate            (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   process_paperstyle_activate(menuitem, RULING_NONE); }@@ -1396,6 +1415,7 @@ on_paperstyleLined_activate            (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   process_paperstyle_activate(menuitem, RULING_LINED); }@@ -1405,6 +1425,7 @@ on_paperstyleRuled_activate            (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   process_paperstyle_activate(menuitem, RULING_RULED); }@@ -1414,6 +1435,7 @@ on_paperstyleGraph_activate            (GtkMenuItem     *menuitem,                                         gpointer         user_data) {+  signal_canvas_changed();   end_text();   process_paperstyle_activate(menuitem, RULING_GRAPH); }@@ -1432,6 +1454,7 @@   char *filename;   gboolean attach;   +  signal_canvas_changed();   end_text();   dialog = gtk_file_chooser_dialog_new(_("Open Background"), GTK_WINDOW (winMain),      GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,@@ -1549,6 +1572,7 @@ {   struct Background *bg;   +  signal_canvas_changed();   end_text();   reset_selection();   gtk_window_iconify(GTK_WINDOW(winMain)); // hide ourselves@@ -1595,7 +1619,7 @@                                         gpointer         user_data) {   gboolean active;-  +  signal_canvas_changed();   end_text();   active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));   if (active == ui.bg_apply_all_pages) return;@@ -1649,6 +1673,7 @@   if (ui.toolno[ui.cur_mapping] == TOOL_PEN) return;    ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)+     end_text();   reset_selection();   ui.toolno[ui.cur_mapping] = TOOL_PEN;@@ -2337,7 +2362,7 @@   // abort any page changes pending in the spin button, and take the focus   gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_COMPONENT("spinPageNo")), ui.pageno+1);   reset_focus();-    +  signal_canvas_changed();   is_core = (event->device == gdk_device_get_core_pointer());   if (!ui.use_xinput && !is_core) return FALSE;   if (ui.use_xinput && is_core && ui.discard_corepointer) return FALSE;@@ -2497,6 +2522,7 @@                                         gpointer         user_data) {   gboolean is_core;+  signal_canvas_changed();    #ifdef INPUT_DEBUG   printf("DEBUG: ButtonRelease (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x\n", @@ -2558,6 +2584,7 @@       gdk_device_set_mode(dev, GDK_MODE_SCREEN);     }   }+  //signal_canvas_changed();   return FALSE; } @@ -2580,6 +2607,7 @@       gdk_device_set_mode(dev, GDK_MODE_DISABLED);     }   }+  signal_canvas_changed();   return FALSE; } @@ -2589,6 +2617,7 @@                                         GdkEventExpose  *event,                                         gpointer         user_data) {+  //signal_canvas_changed();   if (ui.view_continuous && ui.progressive_bg) rescale_bg_pixmaps();   return FALSE; }@@ -2685,7 +2714,7 @@   printf("DEBUG: MotionNotify (%s) (x,y)=(%.2f,%.2f), modifier %x\n",      is_core?"core":"xinput", event->x, event->y, event->state); #endif-  +  ui.block_autosave = TRUE;   looks_wrong = !(event->state & (1<<(7+ui.which_mouse_button)));   if (looks_wrong) {     gdk_device_get_state(ui.stroke_device, event->window, NULL, &mask);@@ -2748,6 +2777,7 @@    if (ui.in_update_page_stuff) return; // avoid a bad retroaction +  signal_canvas_changed();   end_text();    val = gtk_combo_box_get_active(combobox);@@ -2878,6 +2908,7 @@    if (!GTK_WIDGET_HAS_FOCUS(spinbutton))     gtk_widget_grab_focus(GTK_WIDGET(canvas));+  signal_canvas_changed();   end_text();    val = gtk_spin_button_get_value_as_int(spinbutton) - 1;@@ -2901,6 +2932,7 @@   struct Page *pg;   GList *pglist;   +  signal_canvas_changed();   end_text();   reset_selection();   @@ -2937,6 +2969,7 @@ {   if (ui.cur_page->bg->type != BG_SOLID) return;   +  signal_canvas_changed();   end_text();   prepare_new_undo();   undo->type = ITEM_NEW_DEFAULT_BG;@@ -2960,6 +2993,7 @@   int val;   gchar text[20]; +  signal_canvas_changed();   if (papersize_need_init) {     gtk_combo_box_set_active(combobox, papersize_std);     papersize_need_init = FALSE;@@ -2996,6 +3030,7 @@   gchar *ptr;   GtkComboBox *comboStdSizes;   +  signal_canvas_changed();   text = gtk_entry_get_text(GTK_ENTRY(editable));   val = strtod(text, &ptr);   papersize_width_valid = (*ptr == 0 && val > 0.);@@ -3018,6 +3053,7 @@   gchar *ptr;   GtkComboBox *comboStdSizes;   +  signal_canvas_changed();   text = gtk_entry_get_text(GTK_ENTRY(editable));   val = strtod(text, &ptr);   papersize_height_valid = (*ptr == 0 && val > 0.);@@ -3039,6 +3075,7 @@   int val;   gchar text[20]; +  signal_canvas_changed();   val = gtk_combo_box_get_active(combobox);   if (val == -1 || val == papersize_unit) return;   papersize_unit = val;@@ -3094,6 +3131,7 @@      active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));   if (ui.progressive_bg == active) return;+  signal_canvas_changed();   end_text();   ui.progressive_bg = active;   if (!ui.progressive_bg) rescale_bg_pixmaps();@@ -3471,6 +3509,7 @@ {   gchar *str;   +  signal_canvas_changed();   str = g_strdup(gtk_font_button_get_font_name(fontbutton));   process_font_sel(str); }@@ -3528,6 +3567,16 @@ }  void+on_optionsEnableAutoSave_activate      (GtkMenuItem     *menuitem,+                                        gpointer         user_data)+{+  end_text();+  +  ui.enable_autosave = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));+}+++void on_optionsPressureSensitive_activate   (GtkMenuItem     *menuitem,                                         gpointer         user_data) {@@ -3540,6 +3589,19 @@   update_mappings_menu(); } +gboolean+on_autosave_activate_deferred           (gpointer         user_data)+{+  gchar *name;+  // autosaves are not allowed; usually this is because there is a pen+  // stroke or it's during an interval after a stroke+  if (ui.autosave_defers-- != 1) return FALSE;+  if (ui.block_autosave) return FALSE;+  name = get_autosave_filename();+  save_journal(name);+  g_free(name);+  return FALSE;+}  void on_buttonColorChooser_set              (GtkColorButton  *colorbutton,
=== modified file 'src/xo-callbacks.h'--- src/xo-callbacks.h	2011-03-10 18:14:21 +0000+++ src/xo-callbacks.h	2011-03-10 18:17:31 +0000@@ -617,6 +617,9 @@ on_optionsAutoSavePrefs_activate       (GtkMenuItem     *menuitem,                                         gpointer         user_data); +gboolean+on_autosave_activate_deferred          (gpointer         user_data);+ void on_toolsReco_activate                  (GtkMenuItem     *menuitem,                                         gpointer         user_data);
=== modified file 'src/xo-file.c'--- src/xo-file.c	2011-03-10 18:14:21 +0000+++ src/xo-file.c	2011-03-10 18:17:31 +0000@@ -1270,6 +1270,10 @@ void new_mru_entry(char *name) {   int i, j;++  // do not add autosave files to the mru list+  if (g_str_has_suffix (name, AUTOSAVE_SUFFIX))+    return;      for (i=0;i<MRU_SIZE;i++)      if (ui.mru[i]!=NULL && !strcmp(ui.mru[i], name)) {@@ -1343,6 +1347,7 @@   ui.pressure_sensitivity = FALSE;   ui.width_minimum_multiplier = 0.0;   ui.width_maximum_multiplier = 1.25;+  ui.enable_autosave = TRUE;   ui.button_switch_mapping = FALSE;   ui.autoload_pdf_xoj = FALSE;   @@ -1513,7 +1518,9 @@   update_keyval("general", "autosave_prefs",     _(" auto-save preferences on exit (true/false)"),     g_strdup(ui.auto_save_prefs?"true":"false"));-+  update_keyval("general", "enable_autosave",+    _(" automatically save documents for crash recovery"),+    g_strdup(ui.enable_autosave?"true":"false"));   update_keyval("paper", "width",     _(" the default page width, in points (1/72 in)"),     g_strdup_printf("%.2f", ui.default_page.width));@@ -1877,7 +1884,7 @@     if (str!=NULL) { g_free(ui.shorten_menu_items); ui.shorten_menu_items = str; }   parse_keyval_float("general", "highlighter_opacity", &ui.hiliter_opacity, 0., 1.);   parse_keyval_boolean("general", "autosave_prefs", &ui.auto_save_prefs);-  +  parse_keyval_boolean("general", "enable_autosave", &ui.enable_autosave);     parse_keyval_float("paper", "width", &ui.default_page.width, 1., 5000.);   parse_keyval_float("paper", "height", &ui.default_page.height, 1., 5000.);   parse_keyval_enum_color("paper", "color", @@ -1952,3 +1959,289 @@   parse_keyval_float("tools", "default_font_size", &ui.default_font_size, 1., 200.); #endif }++gchar *autosave_filename=NULL;++void+set_autosave_filename(gchar *fn)+{+  if (autosave_filename)+    g_free (autosave_filename);+  +  autosave_filename = g_strdup(fn);++  // make an entry in ~/.xournal/autosaves+  gchar *autosave_table_dir = g_build_filename(g_get_home_dir(), CONFIG_DIR,+                                               AUTOSAVES_DIR,+                                               NULL);+  if(!g_file_test(autosave_table_dir, G_FILE_TEST_EXISTS))+    g_mkdir(autosave_table_dir,0755);++  gint pid = getpid();+  gchar *pid_str = g_strdup_printf("%d", pid);+  gchar *autosave_table_entry_filename = g_build_filename(autosave_table_dir,+                                                          pid_str,+                                                          NULL);+  g_free(pid_str);+  g_free(autosave_table_dir);++  g_file_set_contents(autosave_table_entry_filename, fn, -1, NULL);++  g_free(autosave_table_entry_filename);+}++gchar*+get_autosave_filename()+{+  gchar *default_basename;+  gchar *retval = NULL;+  if(ui.filename == NULL) {+    if(autosave_filename == NULL) {      +      /* if the file has not been saved yet, make a generic autosave name+         in the user's homedir */+      default_basename = g_strdup_printf("xournal-%d.xoj%s", getpid(), AUTOSAVE_SUFFIX, NULL);+      retval = g_build_filename(g_get_home_dir(), default_basename, NULL);     +      g_free(default_basename);+      set_autosave_filename(retval);+    }+    else+      /* return this generic name if it has already been generated */+      retval = g_strdup(autosave_filename);+  } else {+		/* use the filename with .autosave~ suffix if the file has been saved */+    if(autosave_filename != NULL)+			// remove the "generic" autosave in the homedir+      g_unlink(autosave_filename);+    retval = g_strconcat(ui.filename, AUTOSAVE_SUFFIX, NULL);+    set_autosave_filename(retval);+  }+  return retval;+}++void clear_autosave_entry() {+  // remove our entry in ~/.xournal/autosaves+  gchar *autosave_table_dir = g_build_filename(g_get_home_dir(), CONFIG_DIR,+                                                      AUTOSAVES_DIR,+                                                        NULL);+  gint pid = getpid();+  gchar *pid_str = g_strdup_printf("%d", pid);+  gchar *autosave_table_entry_filename = g_build_filename(autosave_table_dir,+                                                          pid_str,+                                                          NULL);+  g_free(pid_str);+  g_free(autosave_table_dir);++  g_unlink(autosave_table_entry_filename);++  g_free(autosave_table_entry_filename);++}++void clear_autosave_entry_by_contents(char *contents) {+  gchar *autosave_table_dir = g_build_filename(g_get_home_dir(), CONFIG_DIR,+                                                      AUTOSAVES_DIR,+                                                        NULL);+  GDir *dir = g_dir_open (autosave_table_dir, 0, NULL);+  const gchar *filename;+  while (filename = g_dir_read_name (dir) ) {+      gchar *full_filename = g_build_filename(autosave_table_dir, filename, NULL);+      gchar *autosave_filename;+      if (g_file_get_contents (full_filename, &autosave_filename, NULL, NULL) ) {+        if(g_strcmp0(autosave_filename, contents) == 0)+          g_unlink(full_filename);+      }+    g_free(full_filename);+    g_free(autosave_filename);+  }+  g_dir_close(dir);+  g_free(autosave_table_dir);+}++// return value: TRUE if any autosaves have been restored by spawning child+// processes. In this case, this instance of xournal should exit.+gboolean check_and_restore_autosaves(int argc, char *argv[]) {+  // check whether ~/.xournal/autosaves contains any entries which have+  // process ids that currently do not correspond to a xournal pid.++  gchar *autosave_table_dir = g_build_filename(g_get_home_dir(), CONFIG_DIR,+                                                      AUTOSAVES_DIR,+                                                        NULL);+  GDir *dir = g_dir_open (autosave_table_dir, 0, NULL);++  // get all PIDs that currently belong to xournal+  gchar *current_pids;+  g_spawn_command_line_sync ("pidof xournal", &current_pids, NULL, NULL, NULL);++  GList *autosave_filenames = NULL;++  const gchar *filename;+  while (filename = g_dir_read_name (dir) ) {+    // check if any of the filenames are not currently xournal PIDs+    if(g_strstr_len (current_pids,-1, filename) == NULL) {+      // if so, open the file. Its contents should be the name of an autosave filename+      gchar *full_filename = g_build_filename(autosave_table_dir, filename, NULL);+      gchar *autosave_filename;+      if (g_file_get_contents (full_filename, &autosave_filename, NULL, NULL) ) {+        // delete the entry in ~/.xournal/autosaves+        g_unlink(full_filename);+        // if the file exists, add the filename to the list+        if (g_file_test (autosave_filename, G_FILE_TEST_EXISTS))+          autosave_filenames = g_list_prepend(autosave_filenames, autosave_filename);+      }+      g_free(full_filename);+    }+  }+  g_free (current_pids);+  g_free(autosave_table_dir);+  g_dir_close (dir);++  // ask user's confirmation before loading+  gint autosave_count = g_list_length(autosave_filenames);+  if(autosave_count != 0) {+    GtkWidget *w = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,+                                          _("Found %d autosave file(s). Do you want to recover these files?"), autosave_count);+    gtk_dialog_add_buttons(GTK_DIALOG(w), _("Recover"), 0, _("Delete"), 1, NULL);+    gint result = gtk_dialog_run(GTK_DIALOG(w));+    gtk_widget_destroy(w);+    if (result == 0) {+      // spawn all child processes+      GList *iter;+      for(iter = g_list_first(autosave_filenames); +          iter;+          iter = iter->next) {+            +        gchar *cmdline = g_strconcat(argv[0], " "", iter->data, """, NULL);+        g_spawn_command_line_async(cmdline, NULL);+        g_free(cmdline);+        g_free(iter->data);+      }+      g_list_free(autosave_filenames);+      return TRUE;+    }+    else if (result == 1) {+      GList *iter;+      for(iter = g_list_first(autosave_filenames); +          iter;+          iter = iter->next) {+        g_unlink(iter->data);+        g_free(iter->data);+              +      }+    }+  }+  g_list_free(autosave_filenames);+  return FALSE;+}++void open_file_and_autosave (gchar *filename, gchar *autosavename)+{+  int success;+  GtkWidget *w;++  set_cursor_busy (TRUE);+  if (autosavename)+    success = open_journal (autosavename);+  else+    success = open_journal (filename);+  signal_canvas_changed ();+  set_cursor_busy (FALSE);+  +  if (!success) {+    if(autosavename)+      w = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,+       GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), autosavename);+    else+      w = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,+       GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), filename);+    +    gtk_dialog_run(GTK_DIALOG(w));+    gtk_widget_destroy(w);+  } else {+    update_file_name(g_strdup(filename));+    if(autosavename) {+      set_autosave_filename(autosavename);+      ui.saved=FALSE;+    }+    else+      ui.saved=TRUE;     +  }+}++void open_argv_file_or_its_autosave (int argc, char *argv[])+{+  gchar *tmpfn, *tmppath, *tmpautofn;+  int success;+  GtkWidget *w;+ +  if(argc<=1) return;++  // make an absolute path+  if (g_path_is_absolute(argv[1]))+    tmpfn = g_strdup(argv[1]);+  else {+    tmppath = g_get_current_dir();+    tmpfn = g_build_filename(tmppath, argv[1], NULL);+    g_free(tmppath);+  }+  /* check if the argument is an autosave file. If it is, this instance of xournal+     was probably spawned by check_and_restore_autosaves() and we do not have to+     ask for user's confirmation */+  if (g_str_has_suffix (tmpfn, AUTOSAVE_SUFFIX)) {+    tmpautofn = g_strdup(tmpfn);+    g_strrstr(tmpfn, AUTOSAVE_SUFFIX)[0] = 0;+    // check if the autosave comes with an 'official' saved version+    if (!g_file_test (tmpfn, G_FILE_TEST_EXISTS)) {+      g_free(tmpfn);+      tmpfn = NULL;+    }+  } else {+    // if it is not, we check if an autosave of this file exists+    tmpautofn = g_strconcat(tmpfn, AUTOSAVE_SUFFIX, NULL);+    if (g_file_test (tmpautofn, G_FILE_TEST_EXISTS)) {+      // we only want to load the autosave file if it is newer+      GFile *tmp = g_file_new_for_path(tmpfn);+      GFile *tmpauto = g_file_new_for_path(tmpautofn);+      GFileInfo *tmp_info = g_file_query_info(tmp, G_FILE_ATTRIBUTE_TIME_MODIFIED,+                                              0, NULL, NULL);+      GFileInfo *tmpauto_info = g_file_query_info(tmpauto, G_FILE_ATTRIBUTE_TIME_MODIFIED,+                                                  0, NULL, NULL);+      +      guint64 tmptime = g_file_info_get_attribute_uint64(tmp_info, G_FILE_ATTRIBUTE_TIME_MODIFIED);+      guint64 tmpautotime = g_file_info_get_attribute_uint64(tmpauto_info, G_FILE_ATTRIBUTE_TIME_MODIFIED);+      g_object_unref(tmp_info);+      g_object_unref(tmpauto_info);+      g_object_unref(tmp);+      g_object_unref(tmpauto);+      if(tmptime < tmpautotime) {+        // take ownership of this autosave+        clear_autosave_entry_by_contents(tmpautofn);++        // ask user's confirmation before loading+        w = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,+                                   _("Found an autosave file for '%s'. Do you want to recover this file?"), tmpfn);+        gtk_dialog_add_buttons(GTK_DIALOG(w), _("Recover"), 0, _("Delete"), 1, NULL);+        gint result = gtk_dialog_run(GTK_DIALOG(w));+        gtk_widget_destroy(w);+        if (result == 1) {+          // otherwise, delete the autosave+          g_unlink(tmpautofn);+          g_free(tmpautofn);+          tmpautofn = NULL;+        }+      } else {+        // if the autosave file is older, then we should just delete the autosave+        g_unlink(tmpautofn);+        g_free(tmpautofn);+        tmpautofn = NULL;+      }+    } else {+      // if it does not exist, there is no autosave to load+      g_free(tmpautofn);+      tmpautofn = NULL;+    }+  }++  open_file_and_autosave(tmpfn, tmpautofn);+  g_free(tmpfn);+  g_free(tmpautofn);+}
=== modified file 'src/xo-file.h'--- src/xo-file.h	2011-03-10 18:14:21 +0000+++ src/xo-file.h	2011-03-10 18:17:31 +0000@@ -36,3 +36,8 @@ void init_config_default(void); void load_config_from_file(void); void save_config_to_file(void);++gchar* get_autosave_filename(void);+void clear_autosave_entry(void);+gboolean check_and_restore_autosaves(int argc, char *argv[]);+void open_argv_file_or_its_autosave(int argc, char *argv[]);\ No newline at end of file
=== modified file 'src/xo-misc.c'--- src/xo-misc.c	2011-03-10 18:14:21 +0000+++ src/xo-misc.c	2011-03-10 18:17:31 +0000@@ -1658,7 +1658,11 @@   GtkWidget *dialog;   GtkResponseType response; -  if (ui.saved) return TRUE;+  if (ui.saved)+  {+     g_unlink(get_autosave_filename());+	 return TRUE;+  }   dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,     GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("Save changes to '%s'?"),     (ui.filename!=NULL) ? ui.filename:_("Untitled"));@@ -1671,6 +1675,7 @@     on_fileSave_activate(NULL, NULL);     if (!ui.saved) return FALSE; // if save failed, then we abort   }+  g_unlink(get_autosave_filename());   return TRUE; } @@ -2176,3 +2181,28 @@   if(GTK_IS_CONTAINER(w))     gtk_container_forall(GTK_CONTAINER(w), install_focus_hooks, data); }++// This function should be called at the beginning of pertinent event handlers.+// If Xournal ever becomes multithreaded, note that we assume 2 seconds is long+// enough for the event handler to do what needs to get done--if this is not+// acceptable you will need to split it up into two functions, the increment+// done at the beginning of the event handler and the registration of the callback+// at the end.+void signal_canvas_changed(void)+{+  if (ui.enable_autosave) {+    ui.block_autosave = FALSE;+    ui.autosave_defers++;++    // If there were no deferrals in the last two seconds:+    //    ui.autosave_defers == 1+    // Otherwise,+    //    ui.autosave_defers == 1  number of deferrals+    // If no deferrals occur in the next two seconds, ui.autosave_defers+    // will equal 1 again.+    //    ui.autosave_defers == 0+    // indicates there are no deferred autosaves pending++    g_timeout_add_seconds(2, on_autosave_activate_deferred, NULL);+  }+}
=== modified file 'src/xo-misc.h'--- src/xo-misc.h	2011-03-10 18:14:21 +0000+++ src/xo-misc.h	2011-03-10 18:17:31 +0000@@ -94,6 +94,7 @@ gboolean is_event_within_textview(GdkEventButton *event);  void hide_unimplemented(void);+void signal_canvas_changed(void);  void do_fullscreen(gboolean active); 
=== modified file 'src/xournal.h'--- src/xournal.h	2011-03-10 18:14:21 +0000+++ src/xournal.h	2011-03-10 18:17:31 +0000@@ -23,6 +23,8 @@ #define MRU_FILE "recent-files" #define MRU_SIZE 8  #define CONFIG_FILE "config"+#define AUTOSAVES_DIR "autosaves"+#define AUTOSAVE_SUFFIX ".autosave~"  // DATA STRUCTURES AND CONSTANTS @@ -282,6 +284,9 @@   gboolean shorten_menus; // shorten menus ?   gchar *shorten_menu_items; // which items to hide   gboolean is_sel_cursor; // displaying a selection-related cursor+  gboolean enable_autosave; // whether or not autosave is allowed+  guint autosave_defers; // number of stacked deferrals+  gboolean block_autosave; // block autosave from occurring when true #if GTK_CHECK_VERSION(2,10,0)   GtkPrintSettings *print_settings; #endif