]> git.mxchange.org Git - flightgear.git/commitdiff
Updates from Fred Bouvier:
authorcurt <curt>
Tue, 15 Nov 2005 22:00:41 +0000 (22:00 +0000)
committercurt <curt>
Tue, 15 Nov 2005 22:00:41 +0000 (22:00 +0000)
You'll find attached the modified fgadmin that takes care of
'Objects' and 'Terrain' if they exist. I also implemented the
'Check all' / 'Check none' feature you suggested several months
ago.

utils/fgadmin/src/fgadmin.cxx
utils/fgadmin/src/fgadmin.fl
utils/fgadmin/src/fgadmin.h
utils/fgadmin/src/fgadmin_funcs.cxx

index db4368b69c1ab4637a9a88b85eeb6cb6fdf7f140..afa7407004673a18331d5a1f597397d479af76ce 100644 (file)
@@ -1,4 +1,4 @@
-// generated by Fast Light User Interface Designer (fluid) version 1.0104
+// generated by Fast Light User Interface Designer (fluid) version 1.0106
 
 #include "fgadmin.h"
 #include <FL/fl_ask.H>
@@ -14,7 +14,7 @@ inline void FGAdminUI::cb_quit_b_i(Fl_Button*, void*) {
   quit();
 }
 void FGAdminUI::cb_quit_b(Fl_Button* o, void* v) {
-  ((FGAdminUI*)(o->parent()->user_data()))->cb_quit_b_i(o,v);
+  ((FGAdminUI*)(o->parent()->parent()->user_data()))->cb_quit_b_i(o,v);
 }
 
 inline void FGAdminUI::cb_source_b_i(Fl_Button*, void*) {
@@ -22,7 +22,28 @@ inline void FGAdminUI::cb_source_b_i(Fl_Button*, void*) {
 refresh_lists();
 }
 void FGAdminUI::cb_source_b(Fl_Button* o, void* v) {
-  ((FGAdminUI*)(o->parent()->user_data()))->cb_source_b_i(o,v);
+  ((FGAdminUI*)(o->parent()->parent()->parent()->user_data()))->cb_source_b_i(o,v);
+}
+
+inline void FGAdminUI::cb_install_b_i(Fl_Button*, void*) {
+  install_selected();
+}
+void FGAdminUI::cb_install_b(Fl_Button* o, void* v) {
+  ((FGAdminUI*)(o->parent()->parent()->parent()->user_data()))->cb_install_b_i(o,v);
+}
+
+inline void FGAdminUI::cb_source_sel_all_i(Fl_Button*, void*) {
+  install_box->check_all();
+}
+void FGAdminUI::cb_source_sel_all(Fl_Button* o, void* v) {
+  ((FGAdminUI*)(o->parent()->parent()->parent()->user_data()))->cb_source_sel_all_i(o,v);
+}
+
+inline void FGAdminUI::cb_source_desel_all_i(Fl_Button*, void*) {
+  install_box->check_none();
+}
+void FGAdminUI::cb_source_desel_all(Fl_Button* o, void* v) {
+  ((FGAdminUI*)(o->parent()->parent()->parent()->user_data()))->cb_source_desel_all_i(o,v);
 }
 
 inline void FGAdminUI::cb_dest_b_i(Fl_Button*, void*) {
@@ -30,21 +51,28 @@ inline void FGAdminUI::cb_dest_b_i(Fl_Button*, void*) {
 refresh_lists();
 }
 void FGAdminUI::cb_dest_b(Fl_Button* o, void* v) {
-  ((FGAdminUI*)(o->parent()->user_data()))->cb_dest_b_i(o,v);
-}
-
-inline void FGAdminUI::cb_install_b_i(Fl_Button*, void*) {
-  install_selected();
-}
-void FGAdminUI::cb_install_b(Fl_Button* o, void* v) {
-  ((FGAdminUI*)(o->parent()->user_data()))->cb_install_b_i(o,v);
+  ((FGAdminUI*)(o->parent()->parent()->parent()->user_data()))->cb_dest_b_i(o,v);
 }
 
 inline void FGAdminUI::cb_remove_b_i(Fl_Button*, void*) {
   remove_selected();
 }
 void FGAdminUI::cb_remove_b(Fl_Button* o, void* v) {
-  ((FGAdminUI*)(o->parent()->user_data()))->cb_remove_b_i(o,v);
+  ((FGAdminUI*)(o->parent()->parent()->parent()->user_data()))->cb_remove_b_i(o,v);
+}
+
+inline void FGAdminUI::cb_dest_sel_all_i(Fl_Button*, void*) {
+  remove_box->check_all();
+}
+void FGAdminUI::cb_dest_sel_all(Fl_Button* o, void* v) {
+  ((FGAdminUI*)(o->parent()->parent()->parent()->user_data()))->cb_dest_sel_all_i(o,v);
+}
+
+inline void FGAdminUI::cb_dest_desel_all_i(Fl_Button*, void*) {
+  remove_box->check_none();
+}
+void FGAdminUI::cb_dest_desel_all(Fl_Button* o, void* v) {
+  ((FGAdminUI*)(o->parent()->parent()->parent()->user_data()))->cb_dest_desel_all_i(o,v);
 }
 #include <iostream>
 using std::cout;
@@ -55,35 +83,61 @@ FGAdminUI::FGAdminUI() {
   { Fl_Double_Window* o = main_window = new Fl_Double_Window(465, 435, "FlightGear Admin Wizard");
     w = o;
     o->callback((Fl_Callback*)cb_main_window, (void*)(this));
-    { Fl_Button* o = quit_b = new Fl_Button(360, 405, 85, 25, "Quit");
-      o->callback((Fl_Callback*)cb_quit_b);
-    }
-    { Fl_Button* o = source_b = new Fl_Button(5, 5, 225, 25, "Select Scenery Source ...");
-      o->callback((Fl_Callback*)cb_source_b);
-    }
-    source_text = new Fl_Input(5, 35, 225, 25);
-    { Fl_Button* o = dest_b = new Fl_Button(235, 5, 225, 25, "Select Install Destination ...");
-      o->callback((Fl_Callback*)cb_dest_b);
+    { Fl_Group* o = new Fl_Group(5, 405, 455, 25);
+      { Fl_Button* o = quit_b = new Fl_Button(375, 405, 85, 25, "Quit");
+        o->callback((Fl_Callback*)cb_quit_b);
+      }
+      { Fl_Progress* o = progress = new Fl_Progress(5, 405, 365, 25);
+        o->color(FL_BACKGROUND_COLOR);
+        o->selection_color((Fl_Color)175);
+        Fl_Group::current()->resizable(o);
+      }
+      o->end();
     }
-    dest_text = new Fl_Input(235, 35, 225, 25);
-    { Fl_Group* o = new Fl_Group(5, 65, 455, 270);
-      install_box = new Fl_Check_Browser(5, 65, 225, 270, "Select Files to Install");
-      remove_box = new Fl_Check_Browser(235, 65, 225, 270, "Select Files to Remove");
+    { Fl_Group* o = new Fl_Group(5, 5, 460, 390);
+      { Fl_Group* o = new Fl_Group(5, 5, 225, 390);
+        { Fl_Button* o = source_b = new Fl_Button(5, 5, 225, 25, "Select Scenery Source ...");
+          o->callback((Fl_Callback*)cb_source_b);
+        }
+        source_text = new Fl_Input(5, 35, 225, 25);
+        { Fl_Check_Browser* o = install_box = new Fl_Check_Browser(5, 95, 225, 240, "Select Files to Install");
+          Fl_Group::current()->resizable(o);
+        }
+        { Fl_Button* o = install_b = new Fl_Button(20, 360, 195, 35, "Install Selected Files");
+          o->labelfont(1);
+          o->callback((Fl_Callback*)cb_install_b);
+        }
+        { Fl_Button* o = source_sel_all = new Fl_Button(5, 65, 110, 25, "Select all");
+          o->callback((Fl_Callback*)cb_source_sel_all);
+        }
+        { Fl_Button* o = source_desel_all = new Fl_Button(120, 65, 110, 25, "Deselect all");
+          o->callback((Fl_Callback*)cb_source_desel_all);
+        }
+        o->end();
+      }
+      { Fl_Group* o = new Fl_Group(230, 5, 230, 390);
+        { Fl_Button* o = dest_b = new Fl_Button(235, 5, 225, 25, "Select Install Destination ...");
+          o->callback((Fl_Callback*)cb_dest_b);
+        }
+        dest_text = new Fl_Input(235, 35, 225, 25);
+        { Fl_Check_Browser* o = remove_box = new Fl_Check_Browser(235, 95, 225, 240, "Select Files to Remove");
+          Fl_Group::current()->resizable(o);
+        }
+        { Fl_Button* o = remove_b = new Fl_Button(250, 360, 195, 35, "Remove Selected Files");
+          o->labelfont(1);
+          o->callback((Fl_Callback*)cb_remove_b);
+        }
+        { Fl_Button* o = dest_sel_all = new Fl_Button(235, 65, 110, 25, "Select all");
+          o->callback((Fl_Callback*)cb_dest_sel_all);
+        }
+        { Fl_Button* o = dest_desel_all = new Fl_Button(350, 65, 110, 25, "Deselect all");
+          o->callback((Fl_Callback*)cb_dest_desel_all);
+        }
+        o->end();
+      }
       o->end();
       Fl_Group::current()->resizable(o);
     }
-    { Fl_Button* o = install_b = new Fl_Button(20, 360, 195, 35, "Install Selected Files");
-      o->labelfont(1);
-      o->callback((Fl_Callback*)cb_install_b);
-    }
-    { Fl_Button* o = remove_b = new Fl_Button(250, 360, 195, 35, "Remove Selected Files");
-      o->labelfont(1);
-      o->callback((Fl_Callback*)cb_remove_b);
-    }
-    { Fl_Progress* o = progress = new Fl_Progress(5, 405, 345, 25);
-      o->color(FL_BACKGROUND_COLOR);
-      o->selection_color((Fl_Color)175);
-    }
     o->end();
   }
 }
index d752a46c7701d5fa8846a4e6c577c17ef31c9503..c023ebad94d6e2c4d936b5e65015afabae858758 100644 (file)
@@ -1,5 +1,5 @@
 # data file for the Fltk User Interface Designer (fluid)
-version 1.0104 
+version 1.0106 
 header_name {.h} 
 code_name {.cxx}
 decl {\#include <string>} {public
@@ -25,53 +25,85 @@ class FGAdminUI {open
       callback {fl_alert("Use the Quit button to exit fgadmin");} open
       xywh {500 247 465 435} type Double resizable visible
     } {
-      Fl_Button quit_b {
-        label Quit
-        callback {quit();}
-        xywh {360 405 85 25}
-      }
-      Fl_Button source_b {
-        label {Select Scenery Source ...}
-        callback {select_install_source();
-refresh_lists();}
-        xywh {5 5 225 25}
-      }
-      Fl_Input source_text {
-        xywh {5 35 225 25}
-      }
-      Fl_Button dest_b {
-        label {Select Install Destination ...}
-        callback {select_install_dest();
-refresh_lists();}
-        xywh {235 5 225 25}
-      }
-      Fl_Input dest_text {
-        xywh {235 35 225 25}
-      }
       Fl_Group {} {open
-        xywh {5 65 455 270} resizable
+        xywh {5 405 455 25}
       } {
-        Fl_Check_Browser install_box {
-          label {Select Files to Install}
-          xywh {5 65 225 270}
+        Fl_Button quit_b {
+          label Quit
+          callback {quit();}
+          xywh {375 405 85 25}
         }
-        Fl_Check_Browser remove_box {
-          label {Select Files to Remove}
-          xywh {235 65 225 270}
+        Fl_Progress progress {
+          xywh {5 405 365 25} color 49 selection_color 175 resizable
         }
       }
-      Fl_Button install_b {
-        label {Install Selected Files}
-        callback {install_selected();}
-        xywh {20 360 195 35} labelfont 1
-      }
-      Fl_Button remove_b {
-        label {Remove Selected Files}
-        callback {remove_selected();}
-        xywh {250 360 195 35} labelfont 1
-      }
-      Fl_Progress progress {
-        xywh {5 405 345 25} color 49 selection_color 175
+      Fl_Group {} {open
+        xywh {5 5 460 390} resizable
+      } {
+        Fl_Group {} {open
+          xywh {5 5 225 390}
+        } {
+          Fl_Button source_b {
+            label {Select Scenery Source ...}
+            callback {select_install_source();
+refresh_lists();}
+            xywh {5 5 225 25}
+          }
+          Fl_Input source_text {
+            xywh {5 35 225 25}
+          }
+          Fl_Check_Browser install_box {
+            label {Select Files to Install}
+            xywh {5 95 225 240} resizable
+          }
+          Fl_Button install_b {
+            label {Install Selected Files}
+            callback {install_selected();}
+            xywh {20 360 195 35} labelfont 1
+          }
+          Fl_Button source_sel_all {
+            label {Select all}
+            callback {install_box->check_all();}
+            xywh {5 65 110 25}
+          }
+          Fl_Button source_desel_all {
+            label {Deselect all}
+            callback {install_box->check_none();}
+            xywh {120 65 110 25}
+          }
+        }
+        Fl_Group {} {open
+          xywh {230 5 230 390}
+        } {
+          Fl_Button dest_b {
+            label {Select Install Destination ...}
+            callback {select_install_dest();
+refresh_lists();}
+            xywh {235 5 225 25}
+          }
+          Fl_Input dest_text {
+            xywh {235 35 225 25}
+          }
+          Fl_Check_Browser remove_box {
+            label {Select Files to Remove}
+            xywh {235 95 225 240} resizable
+          }
+          Fl_Button remove_b {
+            label {Remove Selected Files}
+            callback {remove_selected();}
+            xywh {250 360 195 35} labelfont 1
+          }
+          Fl_Button dest_sel_all {
+            label {Select all}
+            callback {remove_box->check_all();}
+            xywh {235 65 110 25}
+          }
+          Fl_Button dest_desel_all {
+            label {Deselect all}
+            callback {remove_box->check_none();} selected
+            xywh {350 65 110 25}
+          }
+        }
       }
     }
   }
@@ -81,7 +113,7 @@ refresh_lists();}
   }
   decl {void show();} {public
   }
-  decl {static void step( void * );} {selected public
+  decl {static void step( void * );} {public
   }
   decl {static void step( void *, int );} {public
   }
@@ -93,6 +125,10 @@ refresh_lists();}
   decl {void update_remove_box();} {}
   decl {void install_selected();} {}
   decl {void remove_selected();} {}
+  decl {void select_all_source();} {}
+  decl {void deselect_all_source();} {}
+  decl {void select_all_dest();} {}
+  decl {void deselect_all_dest();} {}
   decl {Fl_Preferences *prefs;} {}
   decl {string source;} {}
   decl {string dest;} {}
index cff8612781f94094cd8aed6e1b6371da45452531..ecaa762155846fe2440a62f88851ad656283a2a5 100644 (file)
@@ -1,4 +1,4 @@
-// generated by Fast Light User Interface Designer (fluid) version 1.0104
+// generated by Fast Light User Interface Designer (fluid) version 1.0106
 
 #ifndef fgadmin_h
 #define fgadmin_h
@@ -7,11 +7,11 @@
 #include <FL/Fl_Preferences.H>
 using std::string;
 #include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Group.H>
 #include <FL/Fl_Button.H>
+#include <FL/Fl_Progress.H>
 #include <FL/Fl_Input.H>
-#include <FL/Fl_Group.H>
 #include <FL/Fl_Check_Browser.H>
-#include <FL/Fl_Progress.H>
 
 class FGAdminUI {
 public:
@@ -26,31 +26,51 @@ private:
   inline void cb_quit_b_i(Fl_Button*, void*);
   static void cb_quit_b(Fl_Button*, void*);
 public:
+  Fl_Progress *progress;
   Fl_Button *source_b;
 private:
   inline void cb_source_b_i(Fl_Button*, void*);
   static void cb_source_b(Fl_Button*, void*);
 public:
   Fl_Input *source_text;
+  Fl_Check_Browser *install_box;
+  Fl_Button *install_b;
+private:
+  inline void cb_install_b_i(Fl_Button*, void*);
+  static void cb_install_b(Fl_Button*, void*);
+public:
+  Fl_Button *source_sel_all;
+private:
+  inline void cb_source_sel_all_i(Fl_Button*, void*);
+  static void cb_source_sel_all(Fl_Button*, void*);
+public:
+  Fl_Button *source_desel_all;
+private:
+  inline void cb_source_desel_all_i(Fl_Button*, void*);
+  static void cb_source_desel_all(Fl_Button*, void*);
+public:
   Fl_Button *dest_b;
 private:
   inline void cb_dest_b_i(Fl_Button*, void*);
   static void cb_dest_b(Fl_Button*, void*);
 public:
   Fl_Input *dest_text;
-  Fl_Check_Browser *install_box;
   Fl_Check_Browser *remove_box;
-  Fl_Button *install_b;
-private:
-  inline void cb_install_b_i(Fl_Button*, void*);
-  static void cb_install_b(Fl_Button*, void*);
-public:
   Fl_Button *remove_b;
 private:
   inline void cb_remove_b_i(Fl_Button*, void*);
   static void cb_remove_b(Fl_Button*, void*);
 public:
-  Fl_Progress *progress;
+  Fl_Button *dest_sel_all;
+private:
+  inline void cb_dest_sel_all_i(Fl_Button*, void*);
+  static void cb_dest_sel_all(Fl_Button*, void*);
+public:
+  Fl_Button *dest_desel_all;
+private:
+  inline void cb_dest_desel_all_i(Fl_Button*, void*);
+  static void cb_dest_desel_all(Fl_Button*, void*);
+public:
   ~FGAdminUI();
   void init();
   void show();
@@ -65,6 +85,10 @@ private:
   void update_remove_box();
   void install_selected();
   void remove_selected();
+  void select_all_source();
+  void deselect_all_source();
+  void select_all_dest();
+  void deselect_all_dest();
   Fl_Preferences *prefs;
   string source;
   string dest;
index 4fbf0c938023886a639dcb7d6ffa64274d4ad17f..bef89582dfb1c0f821795b092fc781ce9b91c49b 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <iostream>
 #include <string>
-#include <vector>
+#include <set>
 #include <sys/stat.h>
 
 #ifdef _MSC_VER
@@ -40,7 +40,7 @@
 
 using std::cout;
 using std::endl;
-using std::vector;
+using std::set;
 using std::string;
 
 extern string def_install_source;
@@ -137,9 +137,7 @@ static int stringCompare(const void *string1, const void *string2)
 
 
 void FGAdminUI::update_install_box() {
-    int i;
-    vector<string> file_list;
-    file_list.clear();
+    set<string> file_list;
 
     install_box->clear();
 
@@ -183,29 +181,18 @@ void FGAdminUI::update_install_box() {
                 install.append( base );
                 if ( ! fl_filename_isdir( install.c_str() ) ) {
                     // cout << install.str() << " install candidate." << endl;
-                    file_list.push_back( ent->d_name );
+                    file_list.insert( ent->d_name );
                 } else {
                     // cout << install.str() << " exists." << endl;
                 }
             }
         }
-        ulCloseDir( dir );
-
-        // convert to a qsort()'able array
-        string *sort_list = new string[file_list.size()];
-        for ( i = 0; i < file_list.size(); ++i ) {
-            sort_list[i] = fl_filename_name( file_list[i].c_str() );
-        }
-
-        // Sort the file list into display order
-        qsort(sort_list, file_list.size(), sizeof(string), stringCompare);
 
-        for ( int i = 0; i < file_list.size(); ++i ) {
-            install_box->add( sort_list[i].c_str() );
+        ulCloseDir( dir );
+        for ( set<string>::iterator it = file_list.begin(); it != file_list.end(); ++it ) {
+            install_box->add( it->c_str() );
         }
 
-        delete [] sort_list;
-
         install_box->redraw();
     }
 }
@@ -213,43 +200,40 @@ void FGAdminUI::update_install_box() {
 
 // scan the source directory and update the install_box contents
 void FGAdminUI::update_remove_box() {
-    int i;
-    vector<string> dir_list;
-    dir_list.clear();
 
     remove_box->clear();
 
     if ( dest.length() ) {
-        ulDir *dir = ulOpenDir( dest.c_str() ) ;
-        ulDirEnt *ent;
-        while ( dir != 0 && ( ent = ulReadDir( dir ) ) ) {
-            if ( strlen(ent->d_name) != 7 ) {
-                // simple heuristic to ignore non-scenery directories
-            } else if ( ent->d_name[0] != 'e' && ent->d_name[0] != 'w' ) {
-                // further sanity checks on name
-            } else if ( ent->d_name[4] != 'n' && ent->d_name[4] != 's' ) {
-                // further sanity checks on name
-            } else {
-                dir_list.push_back( ent->d_name );
-            }
+        string path[2];
+        path[0] = dest + "/Terrain";
+        path[1] = dest + "/Objects";
+        if ( !fl_filename_isdir( path[0].c_str() ) ) {
+            path[0] = dest;
+            path[1] = "";
+        } else if ( !fl_filename_isdir( path[1].c_str() ) ) {
+            path[1] = "";
         }
-        ulCloseDir( dir );
 
-        // convert to a qsort()'able array
-        string *sort_list = new string[dir_list.size()];
-        for ( i = 0; i < dir_list.size(); ++i ) {
-            sort_list[i] = fl_filename_name( dir_list[i].c_str() );
+        set<string> dir_list;
+        for ( int i = 0; i < 2; i++ ) {
+            if ( !path[i].empty() ) {
+                ulDir *dir = ulOpenDir( path[i].c_str() ) ;
+                ulDirEnt *ent;
+                while ( dir != 0 && ( ent = ulReadDir( dir ) ) ) {
+                    if ( strlen(ent->d_name) == 7 &&
+                            ( ent->d_name[0] == 'e' || ent->d_name[0] == 'w' ) &&
+                            ( ent->d_name[4] == 'n' || ent->d_name[4] == 's' ) ) {
+                        dir_list.insert( ent->d_name );
+                    }
+                }
+                ulCloseDir( dir );
+            }
         }
 
-        // Sort the file list into display order
-        qsort(sort_list, dir_list.size(), sizeof(string), stringCompare);
-
-        for ( int i = 0; i < dir_list.size(); ++i ) {
-            remove_box->add( sort_list[i].c_str() );
+        for ( set<string>::iterator it = dir_list.begin(); it != dir_list.end(); ++it ) {
+            remove_box->add( it->c_str() );
         }
 
-        delete [] sort_list;
-
         remove_box->redraw();
     }
 }
@@ -293,48 +277,70 @@ void FGAdminUI::install_selected() {
 }
 
 
-static unsigned long count_dir( const char *dir_name ) {
-    ulDir *dir = ulOpenDir( dir_name ) ;
-    ulDirEnt *ent;
+static unsigned long count_dir( const char *dir_name, bool top = true ) {
     unsigned long cnt = 0L;
-    while ( ent = ulReadDir( dir ) ) {
-        if ( strcmp( ent->d_name, "." ) == 0 ) {
-            // ignore "."
-        } else if ( strcmp( ent->d_name, ".." ) == 0 ) {
-            // ignore ".."
-        } else if ( ent->d_isdir ) {
-            SGPath child( dir_name );
-            child.append( ent->d_name );
-            cnt += count_dir( child.c_str() );
-        } else {
-            cnt += 1;
+    ulDir *dir = ulOpenDir( dir_name ) ;
+    if ( dir ) {
+        ulDirEnt *ent;
+        while ( ent = ulReadDir( dir ) ) {
+            if ( strcmp( ent->d_name, "." ) == 0 ) {
+                // ignore "."
+            } else if ( strcmp( ent->d_name, ".." ) == 0 ) {
+                // ignore ".."
+            } else if ( ent->d_isdir ) {
+                SGPath child( dir_name );
+                child.append( ent->d_name );
+                cnt += count_dir( child.c_str(), false );
+            } else {
+                cnt += 1;
+            }
         }
+        ulCloseDir( dir );
+    } else if ( top ) {
+        string base = dir_name;
+        size_t pos = base.rfind('/');
+        string file = base.substr( pos );
+        base.erase( pos );
+        string path = base + "/Terrain" + file;
+        cnt = count_dir( path.c_str(), false );
+        path = base + "/Objects" + file;
+        cnt += count_dir( path.c_str(), false );
     }
-    ulCloseDir( dir );
     return cnt;
 }
 
-static void remove_dir( const char *dir_name, void (*step)(void*,int), void *data ) {
+static void remove_dir( const char *dir_name, void (*step)(void*,int), void *data, bool top = true ) {
     ulDir *dir = ulOpenDir( dir_name ) ;
-    ulDirEnt *ent;
-    while ( ent = ulReadDir( dir ) ) {
-        if ( strcmp( ent->d_name, "." ) == 0 ) {
-            // ignore "."
-        } else if ( strcmp( ent->d_name, ".." ) == 0 ) {
-            // ignore ".."
-        } else if ( ent->d_isdir ) {
-            SGPath child( dir_name );
-            child.append( ent->d_name );
-            remove_dir( child.c_str(), step, data );
-        } else {
-            SGPath child( dir_name );
-            child.append( ent->d_name );
-            unlink( child.c_str() );
-            if (step) step( data, 1 );
+    if ( dir ) {
+        ulDirEnt *ent;
+        while ( ent = ulReadDir( dir ) ) {
+            if ( strcmp( ent->d_name, "." ) == 0 ) {
+                // ignore "."
+            } else if ( strcmp( ent->d_name, ".." ) == 0 ) {
+                // ignore ".."
+            } else if ( ent->d_isdir ) {
+                SGPath child( dir_name );
+                child.append( ent->d_name );
+                remove_dir( child.c_str(), step, data, false );
+            } else {
+                SGPath child( dir_name );
+                child.append( ent->d_name );
+                unlink( child.c_str() );
+                if (step) step( data, 1 );
+            }
         }
+        ulCloseDir( dir );
+        rmdir( dir_name );
+    } else if ( top ) {
+        string base = dir_name;
+        size_t pos = base.rfind('/');
+        string file = base.substr( pos );
+        base.erase( pos );
+        string path = base + "/Terrain" + file;
+        remove_dir( path.c_str(), step, data, false );
+        path = base + "/Objects" + file;
+        remove_dir( path.c_str(), step, data, false );
     }
-    ulCloseDir( dir );
-    rmdir( dir_name );
 }