Index: bindings.doc
==================================================================
--- bindings.doc
+++ bindings.doc
@@ -99,10 +99,15 @@
   will receive the move list (in the same format as above) on stdin.
 
 
 === Editor commands ===
 
+'^N'
+  Add a new level (after the last one). The new level has the same
+  dimensions as the current level, but contains no objects or strings,
+  and the title is set to "New Level".
+
 '^S'
   Save level.
 
 '^a' <location>
   Add an object with the current MRU values to that location, if there

Index: default.heromeshrc
==================================================================
--- default.heromeshrc
+++ default.heromeshrc
@@ -139,14 +139,15 @@
 ?.editKey.up: select 'mR',-1;
 ?.editKey.down: select 'mR',+1;
 ?.editKey.C: select 'lc',:level_code where :level_code=cast(:level_code as int);
 ?.editKey.F: with n(n) as (select 65 union all select n+1 h from n where h<=64*pfheight()+65) select '^a',n from n;
 ?.editKey.R: select 're',substr(:resize,1,instr(:resize,'x')-1),substr(:resize,instr(:resize,'x')+1) where length(:resize);
-?.editKey.ctrl.X: select 're',pfwidth(),pfheight();
+?.editKey.ctrl.N: ^N
 ?.editKey.ctrl.P: ^P
 ?.editKey.ctrl.Q: ^Q
 ?.editKey.ctrl.S: ^S
+?.editKey.ctrl.X: select 're',pfwidth(),pfheight();
 ?.editKey.space: ^c
 ?.editKey.return: ^e
 ?.editKey.f1: select 'im',:Import_Level;
 ?.editKey.f2: select 'ex',:Export_Level;
 ?.editClick.left: ^a

Index: edit.c
==================================================================
--- edit.c
+++ edit.c
@@ -167,10 +167,25 @@
       sqlite3_str_appendchar(s,1,o->misc3.u&0xFF);
       sqlite3_str_appendchar(s,1,o->misc3.u>>8);
     }
   }
 }
+
+static void update_level_index(void) {
+  Uint8*data;
+  int i;
+  if(level_ord>level_nindex) {
+    level_index=realloc(level_index,++level_nindex*sizeof(Uint16));
+    if(!level_index) fatal("Allocation failed\n");
+    level_index[level_ord-1]=level_id;
+  }
+  data=malloc(level_nindex<<1);
+  if(!data) fatal("Allocation failed\n");
+  for(i=0;i<level_nindex;i++) data[i+i]=level_index[i]&255,data[i+i+1]=level_index[i]>>8;
+  write_lump(FIL_LEVEL,LUMP_LEVEL_IDX,2*level_nindex,data);
+  free(data);
+}
 
 static void save_level(void) {
   /*
    Format of objects:
      * bit flags (or 0xFF for end):
@@ -228,13 +243,16 @@
   // Done
   sz=sqlite3_str_length(str);
   if(i=sqlite3_str_errcode(str)) fatal("SQL string error (%d)\n",i);
   data=sqlite3_str_finish(str);
   if(!data) fatal("Allocation failed\n");
+  sqlite3_exec(userdb,"BEGIN;",0,0,0);
   write_lump(FIL_LEVEL,level_id,sz,data);
   sqlite3_free(data);
+  if(level_ord==level_nindex+1) update_level_index();
   rewrite_class_def();
+  sqlite3_exec(userdb,"COMMIT;",0,0,0);
 }
 
 static void redraw_editor(void) {
   char buf[32];
   SDL_Rect r;
@@ -972,10 +990,35 @@
   done:
   free(buf);
   pclose(fp);
   generation_number_inc=0;
 }
+
+static void new_level(void) {
+  sqlite3_stmt*st;
+  int i;
+  if(i=sqlite3_prepare_v2(userdb,"SELECT COALESCE(MAX(`LEVEL`),-1)+1 FROM `USERCACHEDATA` WHERE `FILE` = LEVEL_CACHEID();",-1,&st,0)) {
+    screen_message(sqlite3_errmsg(userdb));
+    return;
+  }
+  i=sqlite3_step(st);
+  if(i!=SQLITE_ROW) {
+    sqlite3_finalize(st);
+    screen_message(sqlite3_errmsg(userdb));
+    return;
+  }
+  i=sqlite3_column_int(st,0);
+  sqlite3_finalize(st);
+  if(i>0xFFFE) return;
+  annihilate();
+  level_id=i;
+  free(level_title);
+  level_title=strdup("New Level");
+  if(!level_title) fatal("Allocation failed\n");
+  level_changed=level_version=level_code=0;
+  level_ord=level_nindex+1;
+}
 
 static int editor_command(int prev,int cmd,int number,int argc,sqlite3_stmt*args,void*aux) {
   int x,y;
   switch(cmd) {
     case '^a': // Add object (no duplicates)
@@ -990,10 +1033,14 @@
       return 0;
     case '^u': // Add object (allow duplicates)
       if(prev) return prev;
       add_object_at(number&63?:64,number/64?:64,mru+curmru,0);
       return 0;
+    case '^N': // New level
+      if(level_nindex>0xFFFE) return 0;
+      new_level();
+      return 1;
     case '^P': // Play
       return -2;
     case '^Q': // Quit
       return -1;
     case '^S': // Save level