summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--command.c8
-rw-r--r--command.h2
-rw-r--r--main.c3
-rw-r--r--math.c3
-rw-r--r--menu.c18
-rw-r--r--ted.cfg1
-rw-r--r--ted.h4
-rw-r--r--ui.c78
8 files changed, 81 insertions, 36 deletions
diff --git a/command.c b/command.c
index 2364442..a2c424d 100644
--- a/command.c
+++ b/command.c
@@ -123,6 +123,11 @@ void command_execute(Ted *ted, Command c, i64 argument) {
case CMD_SAVE:
if (buffer) buffer_save(buffer);
break;
+ case CMD_SAVE_AS:
+ if (buffer && !buffer->is_line_buffer) {
+ menu_open(ted, MENU_SAVE_AS);
+ }
+ break;
case CMD_UNDO:
if (buffer) buffer_undo(buffer, argument);
break;
@@ -173,7 +178,8 @@ void command_execute(Ted *ted, Command c, i64 argument) {
case MENU_NONE:
assert(0);
break;
- case MENU_OPEN: {
+ case MENU_OPEN:
+ case MENU_SAVE_AS: {
ted->file_selector.submitted = true;
} break;
}
diff --git a/command.h b/command.h
index 2372e37..79d8a1d 100644
--- a/command.h
+++ b/command.h
@@ -36,6 +36,7 @@ ENUM_U16 {
CMD_OPEN, // open a file
CMD_SAVE, // save current buffer
+ CMD_SAVE_AS,
CMD_UNDO,
CMD_REDO,
CMD_COPY,
@@ -88,6 +89,7 @@ static CommandName const command_names[CMD_COUNT] = {
{"delete-word", CMD_DELETE_WORD},
{"open", CMD_OPEN},
{"save", CMD_SAVE},
+ {"save-as", CMD_SAVE_AS},
{"undo", CMD_UNDO},
{"redo", CMD_REDO},
{"copy", CMD_COPY},
diff --git a/main.c b/main.c
index 142942b..747c95f 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,8 @@
// @TODO:
// - save as
+// - warn on:
+// - overwrite (from save as menu)
+// - unsaved changes
// - auto-indent
// - Windows installation
#include "base.h"
diff --git a/math.c b/math.c
index 9d72aa2..78f1ecc 100644
--- a/math.c
+++ b/math.c
@@ -771,8 +771,11 @@ static float rects_intersect(Rect r1, Rect r2) {
// returns whether or not there is any of the clipped rectangle left
static bool rect_clip_to_rect(Rect *clipped, Rect clipper) {
+ v2 start_pos = clipped->pos;
clipped->pos.x = maxf(clipped->pos.x, clipper.pos.x);
clipped->pos.y = maxf(clipped->pos.y, clipper.pos.y);
+ clipped->size = v2_add(clipped->size, v2_sub(start_pos, clipped->pos));
+
clipped->size.x = clampf(clipped->size.x, 0, clipper.pos.x + clipper.size.x - clipped->pos.x);
clipped->size.y = clampf(clipped->size.y, 0, clipper.pos.y + clipper.size.y - clipped->pos.y);
return clipped->size.x > 0 && clipped->size.y > 0;
diff --git a/menu.c b/menu.c
index c98fbc8..40742cf 100644
--- a/menu.c
+++ b/menu.c
@@ -8,6 +8,10 @@ static void menu_open(Ted *ted, Menu menu) {
case MENU_OPEN:
ted->active_buffer = &ted->line_buffer;
break;
+ case MENU_SAVE_AS:
+ ted->active_buffer = &ted->line_buffer;
+ ted->file_selector.create_menu = true;
+ break;
}
}
@@ -39,6 +43,18 @@ static Rect menu_rect(Ted *ted) {
static void menu_update(Ted *ted, Menu menu) {
switch (menu) {
case MENU_NONE: break;
+ case MENU_SAVE_AS: {
+ char *selected_file = file_selector_update(ted, &ted->file_selector);
+ if (selected_file) {
+ TextBuffer *buffer = ted->prev_active_buffer;
+ if (buffer) {
+ buffer_save_as(buffer, selected_file);
+ menu_close(ted, true);
+ file_selector_free(&ted->file_selector);
+ }
+ free(selected_file);
+ }
+ } break;
case MENU_OPEN: {
char *selected_file = file_selector_update(ted, &ted->file_selector);
if (selected_file) {
@@ -65,7 +81,7 @@ static void menu_render(Ted *ted, Menu menu) {
glEnd();
- if (menu == MENU_OPEN) {
+ if (menu == MENU_OPEN || menu == MENU_SAVE_AS) {
float padding = settings->padding;
Rect rect = menu_rect(ted);
float menu_x1, menu_y1, menu_x2, menu_y2;
diff --git a/ted.cfg b/ted.cfg
index 8660f04..8abc633 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -59,6 +59,7 @@ Ctrl+PageDown = 10 :page-down
Ctrl+o = :open
Ctrl+s = :save
+Ctrl+Shift+s = :save-as
Ctrl+z = :undo
Ctrl+Shift+z = :redo
Ctrl+c = :copy
diff --git a/ted.h b/ted.h
index bdc2f60..e1f6498 100644
--- a/ted.h
+++ b/ted.h
@@ -76,7 +76,8 @@ typedef struct {
ENUM_U16 {
MENU_NONE,
- MENU_OPEN
+ MENU_OPEN,
+ MENU_SAVE_AS
} ENUM_U16_END(Menu);
// file entries for file selectors
@@ -95,6 +96,7 @@ typedef struct {
char cwd[TED_PATH_MAX];
bool open; // is the file selector on screen?
bool submitted; // set to true if the line buffer was just submitted this frame.
+ bool create_menu; // this is for creating files, not opening files
} FileSelector;
typedef struct Ted {
diff --git a/ui.c b/ui.c
index 7cabdc6..0619e21 100644
--- a/ui.c
+++ b/ui.c
@@ -271,7 +271,6 @@ static char *file_selector_update(Ted *ted, FileSelector *fs) {
bool submitted = fs->submitted;
fs->submitted = false;
- bool on_screen = true;
for (u32 i = 0; i < fs->n_entries; ++i) {
Rect r = {0};
FileEntry *entry = &fs->entries[i];
@@ -279,7 +278,7 @@ static char *file_selector_update(Ted *ted, FileSelector *fs) {
FsType type = entry->type;
// check if this entry was clicked on
- if (on_screen && file_selector_entry_pos(ted, fs, i, &r)) {
+ if (file_selector_entry_pos(ted, fs, i, &r)) {
for (u32 c = 0; c < ted->nmouse_clicks[SDL_BUTTON_LEFT]; ++c) {
if (rect_contains_point(r, ted->mouse_clicks[SDL_BUTTON_LEFT][c])) {
// this option was selected
@@ -296,23 +295,32 @@ static char *file_selector_update(Ted *ted, FileSelector *fs) {
}
}
}
- } else on_screen = false;
+ }
}
// user pressed enter in search bar
- if (submitted && fs->selected < fs->n_entries) {
- FileEntry *entry = &fs->entries[fs->selected];
- switch (entry->type) {
- case FS_FILE:
+ if (submitted) {
+ if (fs->create_menu) {
+ char path[TED_PATH_MAX];
+ strbuf_printf(path, "%s%s%s", cwd, cwd[strlen(cwd)-1] == PATH_SEPARATOR ? "" : PATH_SEPARATOR_STR, search_term);
free(search_term);
- if (entry->path) return str_dup(entry->path);
- break;
- case FS_DIRECTORY:
- file_selector_cd(ted, fs, entry->name);
- buffer_clear(line_buffer); // clear search term
- break;
- default: break;
+ return str_dup(path);
+ } else {
+ if (fs->selected && fs->selected < fs->n_entries) {
+ FileEntry *entry = &fs->entries[fs->selected];
+ switch (entry->type) {
+ case FS_FILE:
+ free(search_term);
+ if (entry->path) return str_dup(entry->path);
+ break;
+ case FS_DIRECTORY:
+ file_selector_cd(ted, fs, entry->name);
+ buffer_clear(line_buffer); // clear search term
+ break;
+ default: break;
+ }
+ }
}
}
@@ -418,15 +426,18 @@ static void file_selector_render(Ted *ted, FileSelector *fs) {
y1 += line_buffer_height;
+ Rect text_bounds = rect4(x1, y1, x2, y2);
for (u32 i = 0; i < n_entries; ++i) {
// highlight entry user is hovering over/selecting
Rect r;
- if (!file_selector_entry_pos(ted, fs, i, &r)) break;
- if (rect_contains_point(r, ted->mouse_pos) || fs->selected == i) {
- glBegin(GL_QUADS);
- gl_color_rgba(colors[COLOR_MENU_HL]);
- rect_render(r);
- glEnd();
+ if (file_selector_entry_pos(ted, fs, i, &r)) {
+ rect_clip_to_rect(&r, text_bounds);
+ if (rect_contains_point(r, ted->mouse_pos) || fs->selected == i) {
+ glBegin(GL_QUADS);
+ gl_color_rgba(colors[COLOR_MENU_HL]);
+ rect_render(r);
+ glEnd();
+ }
}
}
@@ -434,20 +445,21 @@ static void file_selector_render(Ted *ted, FileSelector *fs) {
// render file names themselves
for (u32 i = 0; i < n_entries; ++i) {
Rect r;
- if (!file_selector_entry_pos(ted, fs, i, &r)) break;
- float x = r.pos.x, y = r.pos.y;
- switch (entries[i].type) {
- case FS_FILE:
- gl_color_rgba(colors[COLOR_TEXT]);
- break;
- case FS_DIRECTORY:
- gl_color_rgba(colors[COLOR_TEXT_FOLDER]);
- break;
- default:
- gl_color_rgba(colors[COLOR_TEXT_OTHER]);
- break;
+ if (file_selector_entry_pos(ted, fs, i, &r)) {
+ float x = r.pos.x, y = r.pos.y;
+ switch (entries[i].type) {
+ case FS_FILE:
+ gl_color_rgba(colors[COLOR_TEXT]);
+ break;
+ case FS_DIRECTORY:
+ gl_color_rgba(colors[COLOR_TEXT_FOLDER]);
+ break;
+ default:
+ gl_color_rgba(colors[COLOR_TEXT_OTHER]);
+ break;
+ }
+ text_render_with_state(font, &text_render_state, entries[i].name, x, y);
}
- text_render_with_state(font, &text_render_state, entries[i].name, x, y);
}
}