summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-02-13 15:47:30 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2021-02-13 15:47:30 -0500
commite9357bfd982b37672ed9c319956af32bf3db7856 (patch)
treeebc8d3d514725b9402f8316f92aafe2fe14fb22c
parentcdca3cc10dceda9580b2d87c2105c0654aa084fc (diff)
view-only mode
-rw-r--r--buffer.c18
-rw-r--r--colors.h6
-rw-r--r--filesystem-posix.c8
-rw-r--r--filesystem-win.c2
-rw-r--r--filesystem.h8
-rw-r--r--main.c3
-rw-r--r--node.c19
-rw-r--r--ted.cfg2
-rw-r--r--ted.h2
9 files changed, 59 insertions, 9 deletions
diff --git a/buffer.c b/buffer.c
index 7bf1c74..332a8a2 100644
--- a/buffer.c
+++ b/buffer.c
@@ -1196,6 +1196,8 @@ static Status buffer_insert_lines(TextBuffer *buffer, u32 where, u32 number) {
// inserts the given text, returning the position of the end of the text
BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32 str) {
+ if (buffer->view_only)
+ return pos;
if (str.len > U32_MAX) {
buffer_seterr(buffer, "Inserting too much text (length: %zu).", str.len);
BufferPos ret = {0,0};
@@ -1407,11 +1409,13 @@ static void buffer_delete_lines(TextBuffer *buffer, u32 first_line_idx, u32 nlin
}
void buffer_delete_chars_at_pos(TextBuffer *buffer, BufferPos pos, i64 nchars_) {
+ if (buffer->view_only) return;
if (nchars_ < 0) {
buffer_seterr(buffer, "Deleting negative characters (specifically, " I64_FMT ").", nchars_);
return;
}
if (nchars_ <= 0) return;
+
if (nchars_ > U32_MAX) nchars_ = U32_MAX;
u32 nchars = (u32)nchars_;
@@ -1839,6 +1843,10 @@ Status buffer_load_file(TextBuffer *buffer, char const *filename) {
buffer->lines_capacity = lines_capacity;
buffer->filename = filename_copy;
buffer->last_write_time = time_last_modified(buffer->filename);
+ if (!(fs_path_permission(filename) & FS_PERMISSION_WRITE)) {
+ // can't write to this file; make the buffer view only.
+ buffer->view_only = true;
+ }
}
}
} else {
@@ -1908,6 +1916,11 @@ void buffer_new_file(TextBuffer *buffer, char const *filename) {
bool buffer_save(TextBuffer *buffer) {
Settings const *settings = buffer_settings(buffer);
if (!buffer->is_line_buffer && buffer->filename) {
+ if (buffer->view_only) {
+ buffer_seterr(buffer, "Can't save view-only file.");
+ return false;
+ }
+
FILE *out = fopen(buffer->filename, "wb");
if (out) {
if (settings->auto_add_newline) {
@@ -2120,7 +2133,7 @@ void buffer_render(TextBuffer *buffer, Rect r) {
V2((float)n_columns_highlighted * char_width, char_height)
);
buffer_clip_rect(buffer, &hl_rect);
- gl_geometry_rect(hl_rect, colors[COLOR_SELECTION_BG]);
+ gl_geometry_rect(hl_rect, colors[buffer->view_only ? COLOR_VIEW_ONLY_SELECTION_BG : COLOR_SELECTION_BG]);
}
index1 = 0;
}
@@ -2257,7 +2270,8 @@ void buffer_render(TextBuffer *buffer, Rect r) {
if (is_on) {
if (buffer_clip_rect(buffer, &cursor_rect)) {
- gl_geometry_rect(cursor_rect, colors[COLOR_CURSOR]);
+ // draw cursor
+ gl_geometry_rect(cursor_rect, colors[buffer->view_only ? COLOR_VIEW_ONLY_CURSOR : COLOR_CURSOR]);
}
}
gl_geometry_draw();
diff --git a/colors.h b/colors.h
index 43becf1..a5139c7 100644
--- a/colors.h
+++ b/colors.h
@@ -7,11 +7,13 @@ ENUM_U16 {
COLOR_HL,
COLOR_CURSOR,
COLOR_CURSOR_LINE_BG,
+ COLOR_SELECTION_BG,
+ COLOR_VIEW_ONLY_CURSOR,
+ COLOR_VIEW_ONLY_SELECTION_BG,
COLOR_MATCHING_BRACKET_HL,
COLOR_BORDER,
COLOR_TEXT_FOLDER,
COLOR_TEXT_OTHER,
- COLOR_SELECTION_BG,
COLOR_MENU_BACKDROP,
COLOR_MENU_BG,
COLOR_MENU_HL,
@@ -54,6 +56,8 @@ static ColorName const color_names[COLOR_COUNT] = {
{COLOR_HL, "hl"},
{COLOR_CURSOR, "cursor"},
{COLOR_CURSOR_LINE_BG, "cursor-line-bg"},
+ {COLOR_VIEW_ONLY_CURSOR, "view-only-cursor"},
+ {COLOR_VIEW_ONLY_SELECTION_BG, "view-only-selection-bg"},
{COLOR_MATCHING_BRACKET_HL, "matching-bracket-hl"},
{COLOR_BORDER, "border"},
{COLOR_TEXT_FOLDER, "text-folder"},
diff --git a/filesystem-posix.c b/filesystem-posix.c
index ebf1407..8af0bf2 100644
--- a/filesystem-posix.c
+++ b/filesystem-posix.c
@@ -16,6 +16,14 @@ FsType fs_path_type(char const *path) {
return FS_OTHER;
}
+FsPermission fs_path_permission(char const *path) {
+ int bits = access(path, R_OK | W_OK);
+ FsPermission perm = 0;
+ if (!(bits & R_OK)) perm |= FS_PERMISSION_READ;
+ if (!(bits & W_OK)) perm |= FS_PERMISSION_WRITE;
+ return perm;
+}
+
bool fs_file_exists(char const *path) {
return fs_path_type(path) == FS_FILE;
}
diff --git a/filesystem-win.c b/filesystem-win.c
index f27fe82..8d7a95a 100644
--- a/filesystem-win.c
+++ b/filesystem-win.c
@@ -13,6 +13,8 @@ FsType fs_path_type(char const *path) {
return FS_OTHER;
}
+#error "TODO: fs_path_permission"
+
bool fs_file_exists(char const *path) {
return fs_path_type(path) == FS_FILE;
}
diff --git a/filesystem.h b/filesystem.h
index 2e561cd..6325bd7 100644
--- a/filesystem.h
+++ b/filesystem.h
@@ -8,8 +8,15 @@ typedef enum {
FS_OTHER
} FsType;
+enum {
+ FS_PERMISSION_READ = 0x01,
+ FS_PERMISSION_WRITE = 0x02,
+};
+typedef u8 FsPermission;
+
// returns what kind of thing this is.
FsType fs_path_type(char const *path);
+FsPermission fs_path_permission(char const *path);
// Does this file exist? Returns false for directories.
bool fs_file_exists(char const *path);
// Returns a NULL-terminated array of the files/directories in this directory, or NULL if the directory does not exist.
@@ -29,5 +36,6 @@ int fs_mkdir(char const *path);
// -1 if we can't get the cwd for whatever reason.
int fs_get_cwd(char *buf, size_t buflen);
+
#endif // FILESYSTEM_H_
diff --git a/main.c b/main.c
index 772a8b3..5cbbb79 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,5 @@
// @TODO:
+// - open file in view-only mode menu
// - split
// - completion
// - view-only
@@ -657,6 +658,8 @@ int main(int argc, char **argv) {
print("Frame (noswap): %.1f ms\n", (frame_end_noswap - frame_start) * 1000);
}
#endif
+
+ SDL_SetWindowTitle(window, ted->window_title);
SDL_GL_SwapWindow(window);
PROFILE_TIME(frame_end);
diff --git a/node.c b/node.c
index 3e2c117..7ca4843 100644
--- a/node.c
+++ b/node.c
@@ -135,21 +135,28 @@ static void node_frame(Ted *ted, Node *node, Rect r) {
// tab border
gl_geometry_rect_border(tab_rect, border_thickness, colors[COLOR_BORDER]);
- if (i == node->active_tab) {
- // highlight active tab
- gl_geometry_rect(tab_rect, colors[is_active ? COLOR_ACTIVE_TAB_HL : COLOR_HL]);
- }
// tab title
{
- char const *surround = buffer_unsaved_changes(buffer) ? "*" : "";
- strbuf_printf(tab_title, "%s%s%s", surround, filename, surround);
+ if (buffer_unsaved_changes(buffer))
+ strbuf_printf(tab_title, "*%s*", filename);
+ else if (buffer->view_only)
+ strbuf_printf(tab_title, "VIEW %s", filename);
+ else
+ strbuf_printf(tab_title, "%s", filename);
}
text_state.max_x = rect_x2(tab_rect);
rgba_u32_to_floats(colors[COLOR_TEXT], text_state.color);
text_state.x = tab_rect.pos.x;
text_state.y = tab_rect.pos.y;
text_utf8_with_state(font, &text_state, tab_title);
+
+ if (i == node->active_tab) {
+ // highlight active tab
+ gl_geometry_rect(tab_rect, colors[is_active ? COLOR_ACTIVE_TAB_HL : COLOR_HL]);
+ // set window title to active tab's title
+ strbuf_printf(ted->window_title, "ted %s", tab_title);
+ }
}
gl_geometry_draw();
diff --git a/ted.cfg b/ted.cfg
index 69b2aa4..f89e7aa 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -119,6 +119,8 @@ cursor = #3ff
# color to highlight matching brackets with
matching-bracket-hl = #fda8
selection-bg = #36aa
+view-only-cursor = #0d0
+view-only-selection-bg = #0a05
hl = #ccc
text = #fff
# less prominent text color
diff --git a/ted.h b/ted.h
index 15a2dca..a1150f3 100644
--- a/ted.h
+++ b/ted.h
@@ -136,6 +136,7 @@ typedef struct {
bool modified;
bool will_chain_edits;
bool chaining_edits; // are we chaining undo events together?
+ bool view_only;
float x1, y1, x2, y2;
u32 nlines;
u32 lines_capacity;
@@ -248,6 +249,7 @@ typedef struct Ted {
Node nodes[TED_MAX_NODES];
bool buffers_used[TED_MAX_BUFFERS];
TextBuffer buffers[TED_MAX_BUFFERS];
+ char window_title[256];
char error[512];
char error_shown[512]; // error display in box on screen
} Ted;