Browse Source

File Dialog directories beyond FreeOberon dir

Arthur Yefimov 3 years ago
parent
commit
a303ba22b6
2 changed files with 70 additions and 25 deletions
  1. 9 0
      src/Dir.Mod
  2. 61 25
      src/Editor.Mod

+ 9 - 0
src/Dir.Mod

@@ -92,4 +92,13 @@ END Rewind;
 PROCEDURE IsDir*(name: ARRAY OF CHAR): BOOLEAN;
 RETURN (name = '') OR Platform.DirExists(name) END IsDir;
 
+PROCEDURE GetCwd*(VAR dir: ARRAY OF CHAR);
+VAR i: INTEGER;
+BEGIN i := 0;
+  WHILE (Platform.CWD[i] # 0X) & (i < LEN(dir) - 1) DO
+    dir[i] := Platform.CWD[i]; INC(i)
+  END;
+  dir[i] := 0X
+END GetCwd;
+
 END Dir.

+ 61 - 25
src/Editor.Mod

@@ -54,7 +54,8 @@ TYPE
     type*: INTEGER; (* open or save *)
     edtFilename*: OV.Edit;
     btnOk*, btnCancel*: OV.Button;
-    path*: ARRAY 1024 OF CHAR;
+    path*: ARRAY 1024 OF CHAR; (* full path to current chosen dir *)
+    home*: ARRAY 1024 OF CHAR; (* i.e. 'C:/FreeOberon/Programs' *)
     colFiles*: OV.ColumnList;
     onFileOk*: PROCEDURE (c: OV.Control; fname: ARRAY OF CHAR)
   END;
@@ -87,58 +88,88 @@ PROCEDURE FileDialogUpdateFileList*(c: FileDialog);
 VAR L: StrList.List;
   r: Dir.Rec;
   s: ARRAY 512 OF CHAR;
+  first: BOOLEAN;
+  n: INTEGER;
 BEGIN L := c.colFiles.items;
   StrList.Clear(L);
-  Dir.First(r, c.path);
+  Dir.First(r, c.path); first := TRUE;
   WHILE ~r.eod DO
-    IF ~r.isDir THEN StrList.Append(L, r.name)
-    ELSIF r.name # '.' THEN
-      s := r.name$;
-      Strings.Insert('[', 0, s); Strings.Append(']', s);
-      StrList.Append(L, s)
+    IF r.name # '.' THEN s := r.name$;
+      IF r.isDir THEN
+        IF first THEN n := Strings.Length(s);
+          s[n] := '/'; s[n + 1] := 0X;
+          OV.EditSetCaption(c.edtFilename, s);
+          s[n] := ']'; Strings.Insert('[', 0, s)
+        ELSE Strings.Insert('[', 0, s); Strings.Append(']', s)
+        END
+      ELSIF first THEN OV.EditSetCaption(c.edtFilename, s)
+      END;
+      StrList.Append(L, s); first := FALSE
     END;
     Dir.Next(r)
   END;
   StrList.Sort(L, FileNamesCmp);
   OV.ColumnListSetCur(c.colFiles, 0);
-  OV.EditSetCaption(c.edtFilename, '../');
   OV.NeedRedraw(c.app)
 END FileDialogUpdateFileList;
 
 PROCEDURE FileDialogApplyDir*(c: FileDialog; s: ARRAY OF CHAR);
-VAR L, i: INTEGER;
+VAR i: INTEGER;
   path: ARRAY 1024 OF CHAR;
 BEGIN
   IF (s[0] = '/') OR (* Asbolute path *)
      ('A' <= CAP(s[0])) & (CAP(s[0]) <= 'Z') & (s[1] = ':')
   THEN path := s$
-  ELSE path := c.path$; L := Strings.Length(s);
-    WHILE (s[0] = '.') & (s[1] = '.') & (s[2] = '/') DO
-      Strings.Delete(s, 0, 3); i := Strings.Length(path) - 2;
+  ELSE path := c.path$;
+    WHILE (s[0] = '.') & (s[1] = '.') & (s[2] = '/') &
+          ~((path[1] = ':') & (path[2] = '/') & (path[3] = 0X))
+    DO Strings.Delete(s, 0, 3); i := Strings.Length(path) - 2;
       WHILE (i >= 0) & (path[i] # '/') DO DEC(i) END;
       IF i >= 0 THEN path[i + 1] := 0X ELSE path := '' END
     END;
-    IF s # '' THEN Strings.Append(s, path) END
+    IF ~((s[0] = '.') & (s[1] = '.') & (s[2] = '/')) THEN
+      Strings.Append(s, path)
+    END
   END;
   IF Dir.IsDir(path) THEN c.path := path$ END
 END FileDialogApplyDir;
 
+PROCEDURE Match(IN what, where: ARRAY OF CHAR; off: INTEGER): BOOLEAN;
+VAR i, j: INTEGER;
+BEGIN i := 0; j := off;
+  WHILE (i < LEN(what)) & (what[i] # 0X) &
+        (j < LEN(where)) & (where[j] # 0X) &
+        (what[i] = where[j])
+  DO INC(i); INC(j)
+  END ;
+RETURN (i < LEN(what)) & (j < LEN(where)) & (what[i] = 0X) END Match;
+
 PROCEDURE FileDialogOkClick*(c: OV.Control);
 VAR w: FileDialog;
   s, full: ARRAY 257 OF CHAR;
-  L: INTEGER;
-BEGIN w := c.parent(FileDialog);
-  s := w.edtFilename.caption$;
+  i, L: INTEGER;
+BEGIN w := c.parent(FileDialog); s := w.edtFilename.caption$;
   (* Replace all \ with / and set L to length of s *)
   L := 0; WHILE s[L] # 0X DO IF s[L] = '\' THEN s[L] := '/' END; INC(L) END;
   IF L > 0 THEN
-    IF s[L - 1] = '/' THEN
-      FileDialogApplyDir(w, s);
-      FileDialogUpdateFileList(w)
-    ELSE OV.CloseCurWindow(c);
-      IF w.onFileOk # NIL THEN
-        full := w.path$; Strings.Append(s, full);
-        w.onFileOk(c, full)
+    IF (s[L - 1] = '/') OR (s[0] = '/') THEN
+      IF s[L - 1] # '/' THEN s[L] := '/'; INC(L); s[L] := 0X END;
+      FileDialogApplyDir(w, s); FileDialogUpdateFileList(w)
+    ELSE full := w.path$;
+      WHILE (s[0] = '.') & (s[1] = '.') & (s[2] = '/') &
+            ~((full[1] = ':') & (full[2] = '/') & (full[3] = 0X))
+      DO Strings.Delete(s, 0, 3); i := Strings.Length(full) - 2;
+        WHILE (i >= 0) & (full[i] # '/') DO DEC(i) END;
+        IF i >= 0 THEN full[i + 1] := 0X ELSE full := '' END
+      END;
+      IF ~((s[0] = '.') & (s[1] = '.') & (s[2] = '/')) THEN
+        Strings.Append(s, full);
+        IF Match(w.home, full, 0) THEN
+          Strings.Delete(full, 0, Strings.Length(w.home));
+          Strings.Insert(stdPath, 0, full)
+        END;
+        OV.CloseCurWindow(c);
+        IF w.onFileOk # NIL THEN w.onFileOk(c, full) END
       END
     END
   END
@@ -176,6 +207,7 @@ BEGIN C := c(OV.ColumnList); w := C.parent(FileDialog);
 END FileDialogListChange;
 
 PROCEDURE InitFileDialog*(c: FileDialog; type: INTEGER);
+VAR L: INTEGER;
 BEGIN OV.InitWindow(c); c.do := fileDialogMethod; c.type := type;
   IF type = open THEN c.caption := 'Open a File'
   ELSE c.caption := 'Save File As'
@@ -186,7 +218,6 @@ BEGIN OV.InitWindow(c); c.do := fileDialogMethod; c.type := type;
   c.edtFilename := OV.NewEdit();
   c.edtFilename.do.resize(c.edtFilename, 3, 3, c.w - 18, 1);
   OV.Add(c, c.edtFilename);
-  OV.EditSetCaption(c.edtFilename, '../');
 
   (* Open/Save (Ok) button *)
   IF type = open THEN c.btnOk := OV.NewButton('&Open')
@@ -205,7 +236,12 @@ BEGIN OV.InitWindow(c); c.do := fileDialogMethod; c.type := type;
   c.btnCancel.do.resize(c.btnCancel, c.w - 13, 11, 9, 1);
   OV.Add(c, c.btnCancel);
 
-  c.path := stdPath;
+  Dir.GetCwd(c.home); L := 0;
+  WHILE c.home[L] # 0X DO (* Replace \ with /, set L to length of c.home *)
+    IF c.home[L] = '\' THEN c.home[L] := '/' END; INC(L)
+  END; (* L = length of c.home; append / if it is not in the end *)
+  IF c.home[L - 1] # '/' THEN c.home[L] := '/'; INC(L); c.home[L] := 0X END;
+  Strings.Append(stdPath, c.home); c.path := c.home$;
 
   (* ColumnList *)
   c.colFiles := OV.NewColumnList();