summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buffer.c54
-rw-r--r--command.c7
-rw-r--r--main.c2
-rw-r--r--node.c12
-rw-r--r--ted.h7
5 files changed, 70 insertions, 12 deletions
diff --git a/buffer.c b/buffer.c
index 7ad8921..94cebff 100644
--- a/buffer.c
+++ b/buffer.c
@@ -6,8 +6,6 @@
#include <sys/stat.h>
-#define BUFFER_UNTITLED "Untitled" // what to call untitled buffers
-
/// A single line in a buffer
typedef struct Line Line;
@@ -252,8 +250,56 @@ const char *buffer_get_path(TextBuffer *buffer) {
return buffer->path;
}
-const char *buffer_display_filename(TextBuffer *buffer) {
- return buffer->path ? path_filename(buffer->path) : BUFFER_UNTITLED;
+void buffer_display_filename(TextBuffer *buffer, char *filename, size_t filename_size) {
+ if (!buffer->path) {
+ str_cpy(filename, filename_size, "Untitled");
+ return;
+ }
+
+ // this stuff here is to disambiguate between files, so if you have
+ // two files open called
+ // /foo/bar/x/a.c
+ // and /abc/def/x/a.c
+ // their display names will be "bar/x/a.c" and "def/x/a.c"
+
+ int suffix_needed = 0;
+ Ted *ted = buffer->ted;
+ int buffer_path_len = (int)strlen(buffer->path);
+ arr_foreach_ptr(ted->buffers, const TextBufferPtr, p_other) {
+ TextBuffer *other = *p_other;
+ if (!other->path) continue;
+ if (streq(other->path, buffer->path)) continue;
+
+ int other_path_len = (int)strlen(other->path);
+ if (str_has_suffix(buffer->path, other->path)) {
+ // special case
+ suffix_needed = other_path_len + 1;
+ continue;
+ }
+
+ // find longest common suffix of buffer->path, other->path
+ for (int i = 1; i <= buffer_path_len && i <= other_path_len; ++i) {
+ if (i > suffix_needed)
+ suffix_needed = i;
+ if (buffer->path[buffer_path_len - i] != other->path[other_path_len - i]) {
+ break;
+ }
+ }
+ }
+
+ // go to last path separator
+ while (suffix_needed < buffer_path_len &&
+ buffer->path[buffer_path_len - suffix_needed] != PATH_SEPARATOR) {
+ ++suffix_needed;
+ }
+
+ // don't actually include the path separator
+ if (suffix_needed > 0)
+ --suffix_needed;
+
+ assert(suffix_needed > 0 && suffix_needed <= buffer_path_len);
+
+ str_cpy(filename, filename_size, &buffer->path[buffer_path_len - suffix_needed]);
}
// add this edit to the undo history
diff --git a/command.c b/command.c
index b6b5324..07d3856 100644
--- a/command.c
+++ b/command.c
@@ -452,8 +452,9 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen
arr_foreach_ptr(ted->buffers, TextBufferPtr, pbuffer) {
buffer = *pbuffer;
if (buffer_unsaved_changes(buffer)) {
- const char *path = buffer_display_filename(buffer);
- strbuf_catf(ted->warn_unsaved_names, "%s%s", first ? "" : ", ", path);
+ char name[TED_PATH_MAX];
+ buffer_display_filename(buffer, name, sizeof name);
+ strbuf_catf(ted->warn_unsaved_names, "%s%s", first ? "" : ", ", name);
first = false;
}
}
@@ -579,7 +580,7 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen
if (argument != 2 && buffer_unsaved_changes(buffer)) {
// there are unsaved changes!
ted->warn_unsaved = CMD_TAB_CLOSE;
- strbuf_printf(ted->warn_unsaved_names, "%s", buffer_display_filename(buffer));
+ buffer_display_filename(buffer, ted->warn_unsaved_names, sizeof ted->warn_unsaved_names);
menu_open(ted, MENU_WARN_UNSAVED);
} else {
node_tab_close(ted, node, tab_idx);
diff --git a/main.c b/main.c
index 642639e..86d3b86 100644
--- a/main.c
+++ b/main.c
@@ -818,7 +818,7 @@ int main(int argc, char **argv) {
if (buffer_settings(active_buffer)->auto_reload)
buffer_reload(active_buffer);
else {
- strbuf_cpy(ted->ask_reload, buffer_display_filename(active_buffer));
+ buffer_display_filename(active_buffer, ted->ask_reload, sizeof ted->ask_reload);
menu_open(ted, MENU_ASK_RELOAD);
}
}
diff --git a/node.c b/node.c
index 3d8d4b4..ee99883 100644
--- a/node.c
+++ b/node.c
@@ -371,7 +371,8 @@ void node_frame(Ted *ted, Node *node, Rect r) {
for (u16 i = 0; i < ntabs; ++i) {
TextBuffer *buffer = node->tabs[i];
char tab_title[256];
- const char *filename = buffer_display_filename(buffer);
+ char filename[TED_PATH_MAX];
+ buffer_display_filename(buffer, filename, sizeof filename);
Rect tab_rect = rect_xywh(r.pos.x + tab_width * i, r.pos.y, tab_width, tab_bar_height);
if (i > 0) {
@@ -398,9 +399,16 @@ void node_frame(Ted *ted, Node *node, Rect r) {
else
strbuf_printf(tab_title, "%s", filename);
}
+ float title_width = text_get_size_vec2(font, tab_title).x;
+ float title_xpos = tab_rect.pos.x;
+ if (title_width > tab_rect.size.x) {
+ // full tab title doesn't fit in tab -- only show the right end of it
+ title_xpos = tab_rect.pos.x + tab_rect.size.x - title_width;
+ }
+ text_state.min_x = rect_x1(tab_rect);
text_state.max_x = rect_x2(tab_rect);
settings_color_floats(settings, COLOR_TEXT, text_state.color);
- text_state.x = tab_rect.pos.x;
+ text_state.x = title_xpos;
text_state.y = tab_rect.pos.y;
text_state_break_kerning(&text_state);
text_utf8_with_state(font, &text_state, tab_title);
diff --git a/ted.h b/ted.h
index 77f556b..d35fd74 100644
--- a/ted.h
+++ b/ted.h
@@ -386,8 +386,11 @@ u32 buffer_last_line_on_screen(TextBuffer *buffer);
Rect buffer_rect(TextBuffer *buffer);
/// is this buffer empty?
bool buffer_empty(TextBuffer *buffer);
-/// returns the buffer's filename (not full path), or "Untitled" if this buffer is untitled.
-const char *buffer_display_filename(TextBuffer *buffer);
+/// returns the buffer's display filename (not full path) into `filename`
+///
+/// if the buffer is an untitled buffer, returns "Untitled".
+/// `filename` is guaranteed to be null-terminated after calling this.
+void buffer_display_filename(TextBuffer *buffer, char *filename, size_t filename_size);
/// does this buffer contained a named file (i.e. not a line buffer, not the build buffer, not untitled)
bool buffer_is_named_file(TextBuffer *buffer);
/// does this buffer have unsaved changes?