tImprove file handling - ledit - Text editor (WIP) | |
git clone git://lumidify.org/ledit.git (fast, but not encrypted) | |
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow) | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 22ffb413e9e0be6a5764de4bcc951e6a0480bad3 | |
parent b8557a969d0da663fe3175d19269cb2f37eb9e72 | |
Author: lumidify <[email protected]> | |
Date: Fri, 10 Dec 2021 20:23:49 +0100 | |
Improve file handling | |
Diffstat: | |
M buffer.c | 16 ++++++++++++---- | |
M buffer.h | 2 ++ | |
M keys_basic.c | 22 ++++++++++++++-------- | |
M keys_command.c | 81 +++++++++++++++++++++++++----… | |
M ledit.c | 57 +++++++++++++++++++++++++----… | |
M theme_config.h | 1 + | |
M window.c | 96 ++++++++++++++++++++++++-----… | |
M window.h | 14 ++++++++++++++ | |
8 files changed, 231 insertions(+), 58 deletions(-) | |
--- | |
diff --git a/buffer.c b/buffer.c | |
t@@ -191,8 +191,8 @@ buffer_insert_mark(ledit_buffer *buffer, char *mark, size_… | |
} | |
if (marklist->len == marklist->alloc) { | |
size_t new_alloc = marklist->alloc > 0 ? marklist->alloc * 2 :… | |
- marklist->marks = ledit_realloc( | |
- marklist->marks, new_alloc * sizeof(ledit_buffer_mark) | |
+ marklist->marks = ledit_reallocarray( | |
+ marklist->marks, new_alloc, sizeof(ledit_buffer_mark) | |
); | |
marklist->alloc = new_alloc; | |
} | |
t@@ -248,6 +248,7 @@ buffer_create(ledit_common *common) { | |
buffer->marklist = marklist_create(); | |
buffer->filename = NULL; | |
+ memset(&buffer->file_mtime, 0, sizeof(buffer->file_mtime)); | |
buffer->lines = NULL; | |
buffer->lines_num = 0; | |
buffer->lines_cap = 0; | |
t@@ -255,6 +256,7 @@ buffer_create(ledit_common *common) { | |
buffer->views = NULL; | |
buffer->views_num = 0; | |
buffer->hard_line_based = 1; | |
+ buffer->modified = 0; | |
/* add one empty line to buffer */ | |
resize_and_move_line_gap(buffer, 1, 0); | |
t@@ -337,7 +339,6 @@ buffer_recalc_all_views_from_line(ledit_buffer *buffer, si… | |
} | |
} | |
-/* FIXME: don't generate extra blank line at end! */ | |
/* WARNING: errstr must be copied as soon as possible! */ | |
int | |
buffer_load_file(ledit_buffer *buffer, char *filename, size_t line, char **err… | |
t@@ -355,6 +356,7 @@ buffer_load_file(ledit_buffer *buffer, char *filename, siz… | |
if (fseek(file, 0, SEEK_SET)) goto errorclose; | |
ll = buffer_get_line(buffer, line); | |
+ /* FIXME: insert in chunks instead of allocating huge buffer */ | |
file_contents = ledit_malloc(len + 2); | |
/* mimic nvi (or at least the openbsd version) - if the line | |
is empty, insert directly, otherwise insert after the line */ | |
t@@ -367,7 +369,7 @@ buffer_load_file(ledit_buffer *buffer, char *filename, siz… | |
if (ferror(file)) goto errorclose; | |
file_contents[len + off] = '\0'; | |
/* don't generate extra newline at end */ | |
- if (len + off > 1 && file_contents[len + off - 1 == '\n']) { | |
+ if (len + off > 0 && file_contents[len + off - 1] == '\n') { | |
file_contents[len + off - 1] = '\0'; | |
len--; | |
} | |
t@@ -377,6 +379,7 @@ buffer_load_file(ledit_buffer *buffer, char *filename, siz… | |
buffer, line, ll->len, file_contents, len + off, NULL, NULL | |
); | |
free(file_contents); | |
+ buffer->modified = 0; | |
return 0; | |
error: | |
if (*errstr) | |
t@@ -399,6 +402,7 @@ buffer_write_to_file(ledit_buffer *buffer, FILE *file, cha… | |
if (fprintf(file, "%s\n", ll->text) < 0) goto errorclose; | |
} | |
if (fclose(file)) goto error; | |
+ buffer->modified = 0; | |
return 0; | |
error: | |
if (*errstr) | |
t@@ -951,6 +955,7 @@ buffer_undo(ledit_buffer *buffer, enum ledit_mode mode, si… | |
buffer, min_line > 0 ? min_line - 1 : min_line | |
); | |
} | |
+ buffer->modified = 1; | |
} | |
void | |
t@@ -965,6 +970,7 @@ buffer_redo(ledit_buffer *buffer, enum ledit_mode mode, si… | |
buffer, min_line > 0 ? min_line - 1 : min_line | |
); | |
} | |
+ buffer->modified = 1; | |
} | |
void | |
t@@ -989,6 +995,7 @@ buffer_delete_with_undo_base( | |
); | |
if (text_ret == NULL) | |
txtbuf_destroy(buf); | |
+ buffer->modified = 1; | |
} | |
void | |
t@@ -1039,6 +1046,7 @@ buffer_insert_with_undo_base( | |
*line_ret = new_line; | |
if (byte_ret != NULL) | |
*byte_ret = new_byte; | |
+ buffer->modified = 1; | |
} | |
void | |
diff --git a/buffer.h b/buffer.h | |
t@@ -28,6 +28,7 @@ typedef struct { | |
struct ledit_buffer { | |
ledit_common *common; /* common stuff, e.g. display, etc. */ | |
char *filename; /* last opened filename */ | |
+ struct timespec file_mtime; /* last modified time of file */ | |
undo_stack *undo; /* undo manager */ | |
ledit_buffer_marklist *marklist; /* list of mark positions set */ | |
ledit_line *lines; /* array of lines */ | |
t@@ -36,6 +37,7 @@ struct ledit_buffer { | |
size_t lines_cap; /* size of lines array */ | |
size_t lines_gap; /* position of gap for line gap buffe… | |
size_t lines_num; /* number of lines */ | |
+ int modified; /* whether buffer was modified since … | |
int hard_line_based; /* whether operations should work on … | |
Note that this doesn't actually ch… | |
the buffer functions, it is just s… | |
diff --git a/keys_basic.c b/keys_basic.c | |
t@@ -147,8 +147,8 @@ push_key_stack(void) { | |
struct key_stack_elem *e; | |
if (key_stack.len >= key_stack.alloc) { | |
size_t new_alloc = key_stack.alloc > 0 ? key_stack.alloc * 2 :… | |
- key_stack.stack = ledit_realloc( | |
- key_stack.stack, new_alloc * sizeof(struct key_stack_elem) | |
+ key_stack.stack = ledit_reallocarray( | |
+ key_stack.stack, new_alloc, sizeof(struct key_stack_elem) | |
); | |
key_stack.alloc = new_alloc; | |
} | |
t@@ -275,9 +275,9 @@ push_repetition_stack(void) { | |
struct repetition_stack_elem *e; | |
if (repetition_stack.tmp_len >= repetition_stack.tmp_alloc) { | |
size_t new_alloc = repetition_stack.tmp_alloc > 0 ? repetition… | |
- repetition_stack.tmp_stack = ledit_realloc( | |
+ repetition_stack.tmp_stack = ledit_reallocarray( | |
repetition_stack.tmp_stack, | |
- new_alloc * sizeof(struct repetition_stack_elem) | |
+ new_alloc, sizeof(struct repetition_stack_elem) | |
); | |
for (size_t i = repetition_stack.tmp_alloc; i < new_alloc; i++… | |
repetition_stack.tmp_stack[i].key_text = NULL; | |
t@@ -2281,13 +2281,19 @@ basic_key_handler(ledit_view *view, XEvent *event, int… | |
re->key_state = key_state; | |
re->lang_index = lang_index; | |
- /* FIXME: only hide when actually necessary */ | |
- window_hide_message(view->window); | |
+ /* FIXME: figure out when to actually hide message and | |
+ ensure cursor shown */ | |
+ /* FIXME: clean up interface (what has a setter method and what not) */ | |
int found = 0; | |
+ int msg_shown = view->window->message_shown; | |
+ view->window->message_shown = 0; /* FIXME: this is hacky */ | |
struct action act = handle_key(view, buf, (size_t)n, sym, key_state, l… | |
+ if (found && n > 0 && !view->window->message_shown) | |
+ window_hide_message(view->window); | |
+ else | |
+ view->window->message_shown = msg_shown; | |
- /* FIXME: only do this when necessary */ | |
- if (found) | |
+ if (found && n > 0) | |
view_ensure_cursor_shown(view); | |
/* FIXME: maybe show error if not found */ | |
return act; | |
diff --git a/keys_command.c b/keys_command.c | |
t@@ -2,6 +2,8 @@ | |
#include <stdio.h> | |
#include <ctype.h> | |
#include <stdlib.h> | |
+#include <stdint.h> | |
+#include <unistd.h> | |
#include <X11/Xlib.h> | |
#include <X11/Xutil.h> | |
t@@ -109,28 +111,74 @@ static int handle_substitute(ledit_view *view, char *cmd… | |
static int parse_range(ledit_view *view, char *cmd, size_t len, char **cmd_ret… | |
static int handle_cmd(ledit_view *view, char *cmd, size_t len); | |
+/* FIXME: remove command name before passing to handlers */ | |
static int | |
handle_write(ledit_view *view, char *cmd, size_t l1, size_t l2) { | |
- (void)view; | |
- (void)cmd; | |
(void)l1; | |
(void)l2; | |
- /* FIXME: Implement properly; handle error */ | |
+ /* FIXME: allow writing only part of file */ | |
+ char *filename = view->buffer->filename; | |
+ int stored = 1; | |
+ cmd++; /* remove 'w' */ | |
+ int force = 0; | |
+ if (*cmd == '!') { | |
+ force = 1; | |
+ cmd++; | |
+ } | |
+ /* FIXME: string parsing instead of just taking the rest of the line */ | |
+ if (cmd[0] == ' ' && cmd[1] != '\0') { | |
+ filename = cmd + 1; | |
+ stored = 0; | |
+ } | |
+ /* FIXME: file locks */ | |
char *errstr; | |
- if (view->buffer->filename) | |
- buffer_write_to_filename(view->buffer, view->buffer->filename,… | |
+ if (filename) { | |
+ struct stat sb; | |
+ /* There technically is a race between checking stat and actua… | |
+ trying to write the file, but I don't care at the moment. */ | |
+ int ret = 0; | |
+ if (!(ret = stat(filename, &sb)) && !force && stored && | |
+ (sb.st_mtim.tv_sec != view->buffer->file_mtime.tv_sec || | |
+ sb.st_mtim.tv_nsec != view->buffer->file_mtime.tv_nsec)) { | |
+ window_show_message_fmt( | |
+ view->window, | |
+ "%s: file modification time changed; use ! to over… | |
+ filename | |
+ ); | |
+ /* FIXME: I guess the file can still exist if stat returns an … | |
+ but the writing itself will probably fail then as well. */ | |
+ } else if (!ret && !force && !stored) { | |
+ window_show_message_fmt( | |
+ view->window, | |
+ "%s: file exists; use ! to override", | |
+ filename | |
+ ); | |
+ } else if (buffer_write_to_filename(view->buffer, filename, &e… | |
+ window_show_message_fmt(view->window, "Error writing %… | |
+ } else { | |
+ /* FIXME: better message */ | |
+ window_show_message_fmt(view->window, "Wrote file %s",… | |
+ } | |
+ } else { | |
+ window_show_message(view->window, "No file name", -1); | |
+ } | |
return 0; | |
} | |
static int | |
handle_quit(ledit_view *view, char *cmd, size_t l1, size_t l2) { | |
- (void)view; | |
- (void)cmd; | |
(void)l1; | |
(void)l2; | |
- /* FIXME: ask to save changes */ | |
- ledit_cleanup(); | |
- exit(0); | |
+ cmd++; | |
+ int force = 0; | |
+ if (*cmd == '!') | |
+ force = 1; | |
+ if (view->buffer->modified && !force) { | |
+ window_show_message(view->window, "File modified; write or use… | |
+ } else { | |
+ ledit_cleanup(); | |
+ exit(0); | |
+ } | |
return 0; | |
} | |
t@@ -161,11 +209,9 @@ close_view(ledit_view *view, char *cmd, size_t l1, size_t… | |
static int | |
handle_write_quit(ledit_view *view, char *cmd, size_t l1, size_t l2) { | |
- (void)view; | |
- (void)cmd; | |
- (void)l1; | |
- (void)l2; | |
- printf("write quit\n"); | |
+ handle_write(view, cmd + 1, l1, l2); | |
+ ledit_cleanup(); | |
+ exit(0); | |
return 0; | |
} | |
t@@ -633,7 +679,10 @@ edit_submit(ledit_view *view, char *key_text, size_t len)… | |
text += min_pos; | |
} | |
/* FIXME: this is hacky */ | |
- return handle_cmd(view, text, (size_t)textlen); | |
+ char *cmd = ledit_strndup(text, textlen); | |
+ int ret = handle_cmd(view, cmd, (size_t)textlen); | |
+ free(cmd); | |
+ return ret; | |
} | |
static int | |
diff --git a/ledit.c b/ledit.c | |
t@@ -234,21 +234,58 @@ setup(int argc, char *argv[]) { | |
theme = theme_create(&common); | |
buffer = buffer_create(&common); | |
+ buffer_add_view(buffer, theme, NORMAL, 0, 0, 0); | |
+ /* FIXME: don't access view directly here */ | |
+ ledit_view *view = buffer->views[0]; | |
+ view_set_line_cursor_attrs(view, view->cur_line, view->cur_index); | |
/* FIXME: Support multiple buffers/files */ | |
+ /* FIXME: check if file may be binary */ | |
if (argc > 1) { | |
+ /* FIXME: move this to different file */ | |
char *load_err; | |
- if (buffer_load_file(buffer, argv[1], 0, &load_err)) { | |
- fprintf(stderr, "Error opening file '%s': %s\n", argv[… | |
- ledit_cleanup(); | |
- exit(1); | |
+ struct stat sb; | |
+ int newfile = 0; | |
+ int readonly = 0; | |
+ int error = 0; | |
+ /* FIXME: maybe copy vi and open file in /tmp by default? */ | |
+ if (stat(argv[1], &sb)) { | |
+ if (errno == ENOENT) { | |
+ /* note that there may still be a failure | |
+ when trying to write if a directory in | |
+ the path does not exist */ | |
+ newfile = 1; | |
+ } else { | |
+ window_show_message_fmt( | |
+ view->window, "Error opening file '%s': %s… | |
+ argv[1], strerror(errno) | |
+ ); | |
+ error = 1; | |
+ } | |
+ } | |
+ if (access(argv[1], W_OK)) { | |
+ readonly = 1; | |
+ } | |
+ if (!newfile) { | |
+ if (buffer_load_file(buffer, argv[1], 0, &load_err)) { | |
+ window_show_message_fmt( | |
+ view->window, "Error opening file '%s': %s… | |
+ argv[1], load_err | |
+ ); | |
+ error = 1; | |
+ } | |
+ buffer->file_mtime = sb.st_mtim; | |
+ } | |
+ if (!error) { | |
+ buffer->filename = ledit_strdup(argv[1]); | |
+ if (newfile) { | |
+ window_show_message_fmt(view->window, "%s: new… | |
+ } else if (readonly) { | |
+ window_show_message_fmt(view->window, "%s: rea… | |
+ } else { | |
+ window_show_message(view->window, argv[1], -1); | |
+ } | |
} | |
- /* FIXME: encapsulate */ | |
- buffer->filename = ledit_strdup(argv[1]); | |
} | |
- buffer_add_view(buffer, theme, NORMAL, 0, 0, 0); | |
- /* FIXME: don't access view directly here */ | |
- ledit_view *view = buffer->views[0]; | |
- view_set_line_cursor_attrs(view, view->cur_line, view->cur_index); | |
redraw(); | |
} | |
diff --git a/theme_config.h b/theme_config.h | |
t@@ -1,3 +1,4 @@ | |
+/* FIXME: different bg for bottom bar */ | |
/* FIXME: configure font here */ | |
static const int TEXT_SIZE = 12; | |
static const char *TEXT_FG = "#000000"; | |
diff --git a/window.c b/window.c | |
t@@ -3,6 +3,7 @@ | |
#include <math.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
+#include <stdarg.h> | |
#include <X11/Xlib.h> | |
#include <X11/Xatom.h> | |
t@@ -88,16 +89,44 @@ window_get_primary_clipboard_buffer(void) { | |
return xsel.primary; | |
} | |
-/* FIXME static void ensure_cursor_shown(void); */ | |
- | |
/* FIXME: shouldn't window->bottom_text_shown also be true when message_shown?… | |
+/* FIXME: guard against negative width/height */ | |
static void | |
recalc_text_size(ledit_window *window) { | |
int bar_h = window->bb->mode_h; | |
- if ((window->bottom_text_shown || window->message_shown) && window->bb… | |
+ if (window->bottom_text_shown || window->message_shown) | |
bar_h = window->bb->line_h; | |
window->text_w = window->w - window->theme->scrollbar_width; | |
window->text_h = window->h - bar_h; | |
+ if (window->text_w < 0) | |
+ window->text_w = 0; | |
+ if (window->text_h < 0) | |
+ window->text_h = 0; | |
+} | |
+ | |
+static void | |
+resize_line_text(ledit_window *window, int min_size) { | |
+ if (min_size > window->bb->line_alloc || window->bb->line_text == NULL… | |
+ /* FIXME: read up on what the best values are here */ | |
+ /* FIXME: overflow */ | |
+ window->bb->line_alloc = | |
+ window->bb->line_alloc * 2 > min_size ? | |
+ window->bb->line_alloc * 2 : | |
+ min_size; | |
+ window->bb->line_text = ledit_realloc(window->bb->line_text, w… | |
+ } | |
+} | |
+ | |
+static void | |
+redraw_line_text(ledit_window *window) { | |
+ /* FIXME: set_text doesn't really belong here */ | |
+ pango_layout_set_text(window->bb->line, window->bb->line_text, window-… | |
+ pango_layout_get_pixel_size(window->bb->line, &window->bb->line_w, &wi… | |
+ draw_grow(window, window->bb->line_draw, window->bb->line_w, window->b… | |
+ XftDrawRect(window->bb->line_draw->xftdraw, &window->theme->text_bg, 0… | |
+ pango_xft_render_layout(window->bb->line_draw->xftdraw, &window->theme… | |
+ recalc_text_size(window); | |
+ window->redraw = 1; | |
} | |
/* FIXME: allow lines longer than window width to be displayed properly */ | |
t@@ -109,14 +138,7 @@ window_insert_bottom_bar_text(ledit_window *window, char … | |
if (len == -1) | |
len = strlen(text); | |
/* \0 not included in len */ | |
- if (window->bb->line_len + len + 1 > window->bb->line_alloc || window-… | |
- /* FIXME: read up on what the best values are here */ | |
- window->bb->line_alloc = | |
- window->bb->line_alloc * 2 > window->bb->line_len + len + … | |
- window->bb->line_alloc * 2 : | |
- window->bb->line_len + len + 1; | |
- window->bb->line_text = ledit_realloc(window->bb->line_text, w… | |
- } | |
+ resize_line_text(window, window->bb->line_len + len + 1); | |
memmove( | |
window->bb->line_text + window->bb->line_cur_pos + len, | |
window->bb->line_text + window->bb->line_cur_pos, | |
t@@ -125,13 +147,7 @@ window_insert_bottom_bar_text(ledit_window *window, char … | |
memcpy(window->bb->line_text + window->bb->line_cur_pos, text, len); | |
window->bb->line_len += len; | |
window->bb->line_text[window->bb->line_len] = '\0'; | |
- pango_layout_set_text(window->bb->line, window->bb->line_text, window-… | |
- pango_layout_get_pixel_size(window->bb->line, &window->bb->line_w, &wi… | |
- draw_grow(window, window->bb->line_draw, window->bb->line_w, window->b… | |
- XftDrawRect(window->bb->line_draw->xftdraw, &window->theme->text_bg, 0… | |
- pango_xft_render_layout(window->bb->line_draw->xftdraw, &window->theme… | |
- recalc_text_size(window); | |
- window->redraw = 1; | |
+ redraw_line_text(window); | |
} | |
void | |
t@@ -243,12 +259,17 @@ void | |
window_set_bottom_bar_text_shown(ledit_window *window, int shown) { | |
window->bottom_text_shown = shown; | |
window->redraw = 1; | |
+ if (shown) { | |
+ window->message_shown = 0; | |
+ pango_layout_set_width(window->bb->line, -1); | |
+ redraw_line_text(window); | |
+ recalc_text_size(window); | |
+ } | |
} | |
int | |
ledit_window_bottom_bar_text_shown(ledit_window *window) { | |
return window->bottom_text_shown; | |
- window->redraw = 1; | |
} | |
void | |
t@@ -275,6 +296,7 @@ window_get_bottom_bar_text(ledit_window *window) { | |
void | |
window_show_message(ledit_window *window, char *text, int len) { | |
+ pango_layout_set_width(window->bb->line, window->w * PANGO_SCALE); | |
window_set_bottom_bar_text(window, text, len); | |
/* FIXME: rename these */ | |
window->bottom_text_shown = 0; | |
t@@ -282,6 +304,26 @@ window_show_message(ledit_window *window, char *text, int… | |
window->redraw = 1; | |
} | |
+void | |
+window_show_message_fmt(ledit_window *window, char *fmt, ...) { | |
+ va_list args; | |
+ va_start(args, fmt); | |
+ int len = vsnprintf(window->bb->line_text, window->bb->line_alloc, fmt… | |
+ if (len >= window->bb->line_alloc) { | |
+ va_end(args); | |
+ va_start(args, fmt); | |
+ /* +1 because of terminating '\0' */ | |
+ resize_line_text(window, len + 1); | |
+ vsnprintf(window->bb->line_text, window->bb->line_alloc, fmt, … | |
+ } | |
+ window->bb->line_len = len; | |
+ va_end(args); | |
+ pango_layout_set_width(window->bb->line, window->w * PANGO_SCALE); | |
+ window->bottom_text_shown = 0; | |
+ window->message_shown = 1; | |
+ redraw_line_text(window); | |
+} | |
+ | |
int | |
window_message_shown(ledit_window *window) { | |
return window->message_shown; | |
t@@ -291,6 +333,7 @@ void | |
window_hide_message(ledit_window *window) { | |
window->message_shown = 0; | |
window->redraw = 1; | |
+ recalc_text_size(window); | |
} | |
void | |
t@@ -543,6 +586,14 @@ window_create(ledit_common *common, ledit_theme *theme, e… | |
window->bb->mode_draw = draw_create(window, 10, 10); | |
window->bb->line = pango_layout_new(window->context); | |
pango_layout_set_font_description(window->bb->line, window->font); | |
+ pango_layout_set_wrap(window->bb->line, PANGO_WRAP_WORD_CHAR); | |
+ #if PANGO_VERSION_CHECK(1, 44, 0) | |
+ PangoAttrList *pattrs = pango_attr_list_new(); | |
+ PangoAttribute *no_hyphens = pango_attr_insert_hyphens_new(FALSE); | |
+ pango_attr_list_insert(pattrs, no_hyphens); | |
+ pango_layout_set_attributes(window->bb->line, pattrs); | |
+ pango_attr_list_unref(pattrs); | |
+ #endif | |
window->bb->line_draw = draw_create(window, 10, 10); | |
window->bb->line_w = window->bb->line_h = 10; | |
window->bb->line_text = NULL; | |
t@@ -766,7 +817,12 @@ void | |
window_resize(ledit_window *window, int w, int h) { | |
window->w = w; | |
window->h = h; | |
- recalc_text_size(window); | |
+ if (window->message_shown) { | |
+ pango_layout_set_width(window->bb->line, window->w * PANGO_SCA… | |
+ redraw_line_text(window); | |
+ } else { | |
+ recalc_text_size(window); | |
+ } | |
if (window->resize_callback) | |
window->resize_callback(window->resize_cb_data); | |
window->redraw = 1; | |
diff --git a/window.h b/window.h | |
t@@ -5,6 +5,11 @@ | |
* partially here and partially in keys_command, but that's the way it is for … | |
*/ | |
+#ifndef _WINDOW_H_ | |
+#define _WINDOW_H_ | |
+ | |
+#include <stdarg.h> | |
+ | |
typedef struct bottom_bar bottom_bar; | |
typedef struct { | |
t@@ -175,6 +180,13 @@ char *window_get_bottom_bar_text(ledit_window *window); | |
void window_show_message(ledit_window *window, char *text, int len); | |
/* | |
+ * Show a non-editable message that is given as a | |
+ * format string and arguments as interpreted by | |
+ * vsnprintf(3) | |
+ */ | |
+void window_show_message_fmt(ledit_window *window, char *fmt, ...); | |
+ | |
+/* | |
* Hide the non-editable message. | |
*/ | |
void window_hide_message(ledit_window *window); | |
t@@ -323,3 +335,5 @@ void window_clipboard_event(ledit_window *window, XEvent *… | |
* the position that text is being inserted at. | |
*/ | |
void xximspot(ledit_window *window, int x, int y); | |
+ | |
+#endif |