diff --git a/platform/x11/x11_main.c b/platform/x11/x11_main.c
index edbb9fa8..f6bde414 100644
--- a/platform/x11/x11_main.c
+++ b/platform/x11/x11_main.c
@@ -17,6 +17,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 #include <signal.h>
+#include <zlib.h>
 
 #define mupdf_icon_bitmap_16_width 16
 #define mupdf_icon_bitmap_16_height 16
@@ -351,10 +352,69 @@ void wincopyfile(char *source, char *target)
 	fclose(in);
 }
 
+void savestate(pdfapp_t *app)
+{
+  FILE *f;
+  char fn[80];
+  uint32_t crc;
+  uint32_t tmp;
+  int32_t pos;
+
+  strcpy(fn,"");
+  strcat(fn,getenv("HOME"));
+  strcat(fn,"/.mupdfstate.dat");
+  crc = crc32(0, (const void *)filename, strlen(filename));
+
+  f = fopen(fn, "ab+");
+  fclose(f);
+
+  f = fopen(fn, "r+");
+  if(NULL == f) return;
+  while (fread(&tmp, 4, 1, f)) {
+    if (tmp == crc) {
+      fseek(f,-4,SEEK_CUR);
+      break;
+    }
+    fseek(f,4,SEEK_CUR);
+  }
+
+  pos = ftell(f);
+  fseek(f, pos, SEEK_SET);
+  fwrite(&crc, 4, 1, f);
+  fwrite(&app->pageno, 4, 1, f);
+
+  fclose(f);
+}
+
+void loadstate(pdfapp_t *app)
+{ 
+  FILE *f;
+  char fn[80];
+  uint32_t crc;
+  uint32_t tmp;
+  strcpy(fn,"");
+  strcat(fn,getenv("HOME"));
+  strcat(fn,"/.mupdfstate.dat");
+  crc = crc32(0, (const void *)filename, strlen(filename));
+
+  f = fopen(fn, "rb");
+  if(NULL == f) return;
+  while (fread(&tmp, 4, 1, f)) {
+    if (tmp == crc) {
+      fread(&app->pageno, 4, 1, f);
+      break;
+    }
+    fseek(f,4,SEEK_CUR);
+  }
+  fclose(f); 
+}
+
 void cleanup(pdfapp_t *app)
 {
 	fz_context *ctx = app->ctx;
 
+        savestate(app);
+
 	pdfapp_close(app);
 
 	XDestroyWindow(xdpy, xwin);
@@ -923,6 +983,8 @@ int main(int argc, char **argv)
 	gapp.scrh = DisplayHeight(xdpy, xscr);
 	gapp.resolution = resolution;
 	gapp.pageno = pageno;
+        
+        loadstate(&gapp);
 
 	tmo_at.tv_sec = 0;
 	tmo_at.tv_usec = 0;
