Browse Source

Go inside folders

rexim 2 years ago
parent
commit
e9e7126b6a
8 changed files with 148 additions and 18 deletions
  1. 21 0
      src/common.c
  2. 12 4
      src/common.h
  3. 13 5
      src/editor.c
  4. 49 0
      src/file_browser.c
  5. 4 0
      src/file_browser.h
  6. 39 9
      src/main.c
  7. 6 0
      src/simple_renderer.c
  8. 4 0
      src/simple_renderer.h

+ 21 - 0
src/common.c

@@ -8,6 +8,9 @@
 #    include <minirent.h>
 #else
 #    include <dirent.h>
+#    include <sys/types.h>
+#    include <sys/stat.h>
+#    include <unistd.h>
 #endif // _WIN32
 
 #include "common.h"
@@ -124,3 +127,21 @@ Vec4f hex_to_vec4f(uint32_t color)
     result.w = a/255.0f;
     return result;
 }
+
+Errno type_of_file(const char *file_path, File_Type *ft)
+{
+#ifdef _WIN32
+#error "TODO: type_of_file() is not implemented for Windows"
+#else
+    struct stat sb = {0};
+    if (stat(file_path, &sb) < 0) return errno;
+    if (S_ISREG(sb.st_mode)) {
+        *ft = FT_REGULAR;
+    } else if (S_ISDIR(sb.st_mode)) {
+        *ft = FT_DIRECTORY;
+    } else {
+        *ft = FT_OTHER;
+    }
+#endif
+    return 0;
+}

+ 12 - 4
src/common.h

@@ -68,10 +68,11 @@ typedef struct {
 } String_Builder;
 
 #define sb_append_buf da_append_many
-#define sb_append_cstr(sb, cstr)     \
-    do {                             \
-        size_t n = strlen(cstr);     \
-        da_append_many(sb, cstr, n); \
+#define sb_append_cstr(sb, cstr)  \
+    do {                          \
+        const char *s = (cstr);   \
+        size_t n = strlen(s);     \
+        da_append_many(sb, s, n); \
     } while (0)
 #define sb_append_null(sb) da_append_many(sb, "", 1)
 
@@ -81,6 +82,13 @@ typedef struct {
     size_t capacity;
 } Files;
 
+typedef enum {
+    FT_REGULAR,
+    FT_DIRECTORY,
+    FT_OTHER,
+} File_Type;
+
+Errno type_of_file(const char *file_path, File_Type *ft);
 Errno read_entire_file(const char *file_path, String_Builder *sb);
 Errno write_entire_file(const char *file_path, const char *buf, size_t buf_size);
 Errno read_entire_dir(const char *dir_path, Files *files);

+ 13 - 5
src/editor.c

@@ -53,6 +53,8 @@ Errno editor_save(const Editor *e)
 
 Errno editor_load_from_file(Editor *e, const char *file_path)
 {
+    printf("Loading %s\n", file_path);
+
     e->data.count = 0;
     Errno err = read_entire_file(file_path, &e->data);
     if (err != 0) return err;
@@ -308,20 +310,26 @@ void editor_render(SDL_Window *window, Free_Glyph_Atlas *atlas, Simple_Renderer
 
     // Update camera
     {
-        float target_scale = 3.0f;
         if (max_line_len > 1000.0f) {
             max_line_len = 1000.0f;
         }
-        if (max_line_len > 0.0f) {
-            target_scale = SCREEN_WIDTH / max_line_len;
-        }
+
+        // TODO: SCREEN_WIDTH has to be variable cause window my resize
+        float target_scale = SCREEN_WIDTH / max_line_len;
+
+        Vec2f target = cursor_pos;
+        float offset = 0.0f;
 
         if (target_scale > 3.0f) {
             target_scale = 3.0f;
+        } else {
+            offset = cursor_pos.x - SCREEN_WIDTH/sr->camera_scale;
+            if (offset < 0.0f) offset = 0.0f;
+            target = vec2f(SCREEN_WIDTH/sr->camera_scale + offset, cursor_pos.y);
         }
 
         sr->camera_vel = vec2f_mul(
-                             vec2f_sub(cursor_pos, sr->camera_pos),
+                             vec2f_sub(target, sr->camera_pos),
                              vec2fs(2.0f));
         sr->camera_scale_vel = (target_scale - sr->camera_scale) * 2.0f;
 

+ 49 - 0
src/file_browser.c

@@ -17,6 +17,39 @@ Errno fb_open_dir(File_Browser *fb, const char *dir_path)
         return err;
     }
     qsort(fb->files.items, fb->files.count, sizeof(*fb->files.items), file_cmp);
+
+    fb->dir_path.count = 0;
+    sb_append_cstr(&fb->dir_path, dir_path);
+    sb_append_null(&fb->dir_path);
+
+    return 0;
+}
+
+Errno fb_change_dir(File_Browser *fb)
+{
+    assert(fb->dir_path.count > 0 && "You need to call fb_open_dir() before fb_change_dir()");
+    assert(fb->dir_path.items[fb->dir_path.count - 1] == '\0');
+
+    if (fb->cursor >= fb->files.count) return 0;
+
+    const char *dir_name = fb->files.items[fb->cursor];
+
+    fb->dir_path.count -= 1;
+
+    // TODO: fb_change_dir() does not support .. and . properly
+    sb_append_cstr(&fb->dir_path, "/");
+    sb_append_cstr(&fb->dir_path, dir_name);
+    sb_append_null(&fb->dir_path);
+
+    fb->files.count = 0;
+    fb->cursor = 0;
+    Errno err = read_entire_dir(fb->dir_path.items, &fb->files);
+
+    if (err != 0) {
+        return err;
+    }
+    qsort(fb->files.items, fb->files.count, sizeof(*fb->files.items), file_cmp);
+
     return 0;
 }
 
@@ -81,3 +114,19 @@ void fb_render(const File_Browser *fb, SDL_Window *window, Free_Glyph_Atlas *atl
         sr->camera_scale = sr->camera_scale + sr->camera_scale_vel * DELTA_TIME;
     }
 }
+
+const char *fb_file_path(File_Browser *fb)
+{
+    assert(fb->dir_path.count > 0 && "You need to call fb_open_dir() before fb_file_path()");
+    assert(fb->dir_path.items[fb->dir_path.count - 1] == '\0');
+
+    if (fb->cursor >= fb->files.count) return NULL;
+
+    fb->file_path.count = 0;
+    sb_append_buf(&fb->file_path, fb->dir_path.items, fb->dir_path.count - 1);
+    sb_append_buf(&fb->file_path, "/", 1);
+    sb_append_cstr(&fb->file_path, fb->files.items[fb->cursor]);
+    sb_append_null(&fb->file_path);
+
+    return fb->file_path.items;
+}

+ 4 - 0
src/file_browser.h

@@ -9,9 +9,13 @@
 typedef struct {
     Files files;
     size_t cursor;
+    String_Builder dir_path;
+    String_Builder file_path;
 } File_Browser;
 
 Errno fb_open_dir(File_Browser *fb, const char *dir_path);
+Errno fb_change_dir(File_Browser *fb);
 void fb_render(const File_Browser *fb, SDL_Window *window, Free_Glyph_Atlas *atlas, Simple_Renderer *sr);
+const char *fb_file_path(File_Browser *fb);
 
 #endif // FILE_BROWSER_H_

+ 39 - 9
src/main.c

@@ -50,7 +50,7 @@ static Editor editor = {0};
 static File_Browser fb = {0};
 
 // TODO: display errors reported via flash_error right in the text editor window somehow
-#define flash_error(...) fprintf(stderr, __VA_ARGS__)
+#define flash_error(...) do { fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); } while(0)
 
 int main(int argc, char **argv)
 {
@@ -197,16 +197,42 @@ int main(int argc, char **argv)
                     break;
 
                     case SDLK_RETURN: {
-                        if (fb.cursor < fb.files.count) {
-                            // TODO: go inside folders
-                            const char *file_path = fb.files.items[fb.cursor];
-                            // TODO: before opening a new file make sure you don't have unsaved changes
-                            // And if you do, annoy the user about it. (just like all the other editors do)
-                            err = editor_load_from_file(&editor, file_path);
+                        const char *file_path = fb_file_path(&fb);
+                        if (file_path) {
+                            File_Type ft;
+                            err = type_of_file(file_path, &ft);
                             if (err != 0) {
-                                flash_error("Could not open file %s: %s", file_path, strerror(err));
+                                flash_error("Could not determine type of file %s: %s", file_path, strerror(err));
                             } else {
-                                file_browser = false;
+                                switch (ft) {
+                                case FT_DIRECTORY: {
+                                    err = fb_change_dir(&fb);
+                                    if (err != 0) {
+                                        flash_error("Could not change directory to %s: %s", file_path, strerror(err));
+                                    }
+                                }
+                                break;
+
+                                case FT_REGULAR: {
+                                    // TODO: before opening a new file make sure you don't have unsaved changes
+                                    // And if you do, annoy the user about it. (just like all the other editors do)
+                                    err = editor_load_from_file(&editor, file_path);
+                                    if (err != 0) {
+                                        flash_error("Could not open file %s: %s", file_path, strerror(err));
+                                    } else {
+                                        file_browser = false;
+                                    }
+                                }
+                                break;
+
+                                case FT_OTHER: {
+                                    flash_error("%s is neither a regular file nor a directory. We can't open it.", file_path);
+                                }
+                                break;
+
+                                default:
+                                    UNREACHABLE("unknown File_Type");
+                                }
                             }
                         }
                     }
@@ -335,3 +361,7 @@ int main(int argc, char **argv)
 
     return 0;
 }
+
+// TODO: ability to search within file browser
+// Very useful when you have a lot of files
+// TODO: ability to search with the text editor

+ 6 - 0
src/simple_renderer.c

@@ -208,8 +208,14 @@ void simple_renderer_init(Simple_Renderer *sr)
 // simple_renderer_vertex() for a potentially large amount of verticies in the first place.
 void simple_renderer_vertex(Simple_Renderer *sr, Vec2f p, Vec4f c, Vec2f uv)
 {
+#if 1
     // TODO: flush the renderer on vertex buffer overflow instead firing the assert
+    if (sr->verticies_count >= SIMPLE_VERTICIES_CAP) simple_renderer_flush(sr);
+#else
+    // NOTE: it is better to just crash the app in this case until the culling described
+    // above is sorted out.
     assert(sr->verticies_count < SIMPLE_VERTICIES_CAP);
+#endif
     Simple_Vertex *last = &sr->verticies[sr->verticies_count];
     last->position = p;
     last->color    = c;

+ 4 - 0
src/simple_renderer.h

@@ -1,6 +1,8 @@
 #ifndef SIMPLE_RENDERER_H_
 #define SIMPLE_RENDERER_H_
 
+#include <assert.h>
+
 #define GLEW_STATIC
 #include <GL/glew.h>
 
@@ -31,6 +33,8 @@ typedef struct {
 
 #define SIMPLE_VERTICIES_CAP (3*640*1000)
 
+static_assert(SIMPLE_VERTICIES_CAP%3 == 0, "Simple renderer vertex capacity must be divisible by 3. We are rendring triangles after all.");
+
 typedef enum {
     SHADER_FOR_COLOR = 0,
     SHADER_FOR_IMAGE,