чување 5e5e68678295fe862cc4f84f3f5149a5f9661337
родитељ 9996d67f2c653258ee68ce75c51d07865e7f8343
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Sun, 20 Feb 2022 20:38:36 +0100
Fix: initialize all newly-allocated lines when reallocating; create backup files; draw status message with long operations
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
измењених датотека: 7, додавања: 71(+), брисања: 33(-)
diff --git a/TODO b/TODO
@@ -1,8 +1,6 @@
TODO
====
- [~] Write operation; create backup files
-
[ ] Copy/paste?
[ ] Allow creating files (error out if directory not writeable, only
@@ -16,17 +14,7 @@
[ ] Test for binary when opening?
- [x] Go to line #
-
- [x] Convert to termbox2?
-
- [x] Create a working base by migration from poe
- [x] Implement "inverse vi mode"
- [x] Selections!
- [x] Initial support for selections
- (DrawState.in_selection)
- [x] Selections modify behavior of eg. Delete key
- and inserting characters
+ [x] Write operation; create backup files
< > Search?
diff --git a/config.def.h b/config.def.h
@@ -4,6 +4,8 @@
#define DLG_BG TB_WHITE
#define ERROR_FG TB_WHITE | TB_BOLD
#define ERROR_BG TB_RED
+#define ACTION_FG TB_BLACK
+#define ACTION_BG TB_WHITE
#define INPUT_FG TB_BLACK
#define INPUT_BG TB_WHITE
#define INPUT_EDIT_FG TB_WHITE
diff --git a/config.h b/config.h
@@ -4,6 +4,8 @@
#define DLG_BG TB_WHITE
#define ERROR_FG TB_WHITE | TB_BOLD
#define ERROR_BG TB_RED
+#define ACTION_FG TB_BLACK
+#define ACTION_BG TB_WHITE
#define INPUT_FG TB_BLACK
#define INPUT_BG TB_WHITE
#define INPUT_EDIT_FG TB_WHITE
diff --git a/draw.c b/draw.c
@@ -43,7 +43,7 @@ const char* mode_labels[] = {
[PROMPT_MODE] = "PROMPT",
[SELECTION_MODE] = "SELECTION"
};
-const char* errors[] = {
+const char* errors[] = {
[ERR_UNKNOWN_KEY] = "Unknown key (press F1 for help)",
[ERR_EXIT_KEY] = "Press C-Q to quit",
[ERR_DLG_OPEN] = "Press Esc to close dialog or C-Q to quit",
@@ -54,6 +54,10 @@ const char* errors[] = {
[ERR_CANT_MOVE] = "Cannot move temporary file",
[ERR_INPUT_NONNUM] = "Input must be numerical",
[ERR_INVALID_NUM] = "Invalid input"};
+const char* actions[] = {
+ [ACT_WRITING] = "Writing...",
+ [ACT_READING] = "Reading..."
+};
const char* go_to_dialog_title = "Go to line";
const char* search_dialog_title = "Search text";
const char* program_name = "sled";
@@ -86,10 +90,11 @@ free_bufferline(struct BufferLine* bl)
}
void
-init_drawstate(struct DrawState* state, char* error, char* filename,
- char* prompt)
+init_drawstate(struct DrawState* state, char* error, char* action,
+ char* filename, char* prompt)
{
state->error = error;
+ state->action = action;
state->filename = filename;
state->input = NULL;
state->buffer = NULL;
@@ -652,7 +657,7 @@ draw_status(const struct DrawState* state)
int current_start = 0;
const struct StatusSegment* pseg = status_segments;
- if (state->in_prompt && state->prompt[0])
+ if (state->in_prompt && *state->prompt)
{
if (!draw_string(0, state->maxy - 1, PROMPT_FG, PROMPT_BG,
state->prompt, strlen(state->prompt) + 2,
@@ -660,7 +665,15 @@ draw_status(const struct DrawState* state)
0, 0))
return NULL;
}
- else if (state->error && state->error[0])
+ else if (state->action && *state->action)
+ {
+ if (!draw_string(0, state->maxy - 1, ACTION_FG, ACTION_BG,
+ state->action, strlen(state->action) + 2,
+ state->maxx, 1, 1, CENTER, 0, 1, NULL, 0, 0, 0, 0,
+ 0, 0))
+ return NULL;
+ }
+ else if (state->error && *state->error)
{
if (!draw_string(0, state->maxy - 1, ERROR_FG, ERROR_BG,
state->error, strlen(state->error) + 2, state->maxx,
@@ -696,6 +709,14 @@ draw_status(const struct DrawState* state)
}
const struct DrawState*
+redraw_status(const struct DrawState* state)
+{
+ const struct DrawState* result = draw_status(state);
+ tb_present();
+ return result;
+}
+
+const struct DrawState*
draw(const struct DrawState* state)
{
if (!state)
diff --git a/draw.h b/draw.h
@@ -33,6 +33,7 @@ struct BufferLine {
struct DrawState {
char* error;
char* prompt;
+ char* action;
char* filename;
uint32_t* input;
struct BufferLine* buffer;
@@ -85,8 +86,8 @@ struct StatusSegment {
void init_bufferline(struct BufferLine* bl);
void free_bufferline(struct BufferLine* bl);
-void init_drawstate(struct DrawState* state, char* error, char* filename,
- char* prompt);
+void init_drawstate(struct DrawState* state, char* error, char* action,
+ char* filename, char* prompt);
void free_drawstate(struct DrawState* state);
size_t display_length(const struct DrawState* state, uint32_t* buffer,
const size_t max_index);
@@ -115,4 +116,5 @@ void u32_draw_string(const int x, const int y, const uint16_t fg,
const struct DrawState* draw_help(const struct DrawState* state);
const struct DrawState* draw_screen(const struct DrawState* state);
const struct DrawState* draw_status(const struct DrawState* state);
+const struct DrawState* redraw_status(const struct DrawState* state);
const struct DrawState* draw(const struct DrawState* state);
diff --git a/sled.c b/sled.c
@@ -38,6 +38,7 @@ enum {
};
extern const char* errors[];
+extern const char* actions[];
extern const char* mode_labels[];
extern const char* go_to_dialog_title;
extern const char* search_dialog_title;
@@ -154,7 +155,8 @@ reread_file(struct DrawState* state)
for (row = 0; row < state->paste_rows_count; row++)
free_bufferline(state->paste_buffer + row);
free(state->paste_buffer);
- init_drawstate(state, state->error, state->filename, state->prompt);
+ init_drawstate(state, state->error, state->action, state->filename,
+ state->prompt);
result = load_file(state, &lineno, &col);
switch (result)
@@ -246,6 +248,9 @@ load_file(struct DrawState* state, long* lineno, long* col)
if (!newchunk)
return LOAD_ERR_CANT_ALLOC;
+ strcpy(state->action, actions[ACT_READING]);
+ redraw_status(state);
+
state->buffer = newchunk;
line = state->buffer;
state->buffer_size = ALLOC_DELTA;
@@ -269,17 +274,17 @@ load_file(struct DrawState* state, long* lineno, long* col)
if (line == state->buffer + state->buffer_size)
{
state->buffer_size += ALLOC_DELTA;
- /* TODO: Allocated here */
newchunk = realloc(state->buffer,
state->buffer_size * sizeof(struct BufferLine));
if (!newchunk)
return LOAD_ERR_CANT_ALLOC;
state->buffer = newchunk;
- init_bufferline(state->buffer + state->buffer_size
- - ALLOC_DELTA);
+ for (size_t row = state->buffer_size - ALLOC_DELTA;
+ row < state->buffer_size; row++)
+ init_bufferline(state->buffer + row);
line = state->buffer + state->buffer_size - ALLOC_DELTA;
}
- if (!line->text) /* TODO: Uninitialized value? */
+ if (!line->text)
{
newtext = calloc(MAXBUFLINE, sizeof(uint32_t));
if (!newtext)
@@ -290,6 +295,7 @@ load_file(struct DrawState* state, long* lineno, long* col)
state->rows_count++;
}
fclose(input);
+ *state->action = 0;
return LOAD_ERR_NONE;
}
@@ -297,13 +303,22 @@ load_file(struct DrawState* state, long* lineno, long* col)
int
save_file(struct DrawState* state)
{
- FILE* output = NULL;
- char* buf = NULL;
+ FILE* output = NULL;
+ char* buf = NULL;
+ char* backup_filename = NULL;
if (!(buf = calloc(MAXBUFLINE, 1)))
return SAVE_ERR_CANT_ALLOC;
+ if (!(backup_filename = calloc(MAXPATH, 1)))
+ return SAVE_ERR_CANT_ALLOC;
+
+ strcpy(state->action, actions[ACT_WRITING]);
+ redraw_status(state);
+
+ strcpy(backup_filename, state->filename);
+ strcat(backup_filename, "~");
+ rename(state->filename, backup_filename);
- /* TODO: Create backup! */
if (!(output = fopen(state->filename, "wt")))
return SAVE_ERR_CANT_OPEN_FILE;
@@ -314,7 +329,9 @@ save_file(struct DrawState* state)
}
fclose(output);
+ free(backup_filename);
free(buf);
+ *state->action = 0;
return SAVE_ERR_NONE;
}
@@ -1463,7 +1480,6 @@ erase_selection(struct DrawState* state)
state->buffer[ssr + row + 1].length
= state->buffer[ser + row + 1].length;
}
- /* TODO: Check! */
for (size_t row = state->rows_count - (ser - ssr);
row < state->rows_count; row++)
{
@@ -1596,14 +1612,16 @@ main(int argc, char** argv)
{
struct tb_event ev;
char error[MAXBUFLINE];
+ char action[MAXBUFLINE];
char prompt[MAXBUFLINE];
struct DrawState state;
char filename[MAXPATH];
struct stat st;
- error[0] = 0;
- prompt[0] = 0;
- filename[0] = 0;
+ *error = 0;
+ *action = 0;
+ *prompt = 0;
+ *filename = 0;
if (argc == 1)
return print_error(1, "No filename given");
@@ -1630,7 +1648,7 @@ main(int argc, char** argv)
if (!S_ISREG(st.st_mode))
return print_error(EINVAL, "Is not a regular file");
- init_drawstate(&state, error, filename, prompt);
+ init_drawstate(&state, error, action, filename, prompt);
long lineno = 1;
long col = 1;
diff --git a/util.h b/util.h
@@ -28,6 +28,11 @@ enum {
ERR_INVALID_NUM
};
+enum {
+ ACT_WRITING,
+ ACT_READING
+};
+
#define ALLOC_DELTA 50
#define MAXBUFLINE 4096
#define MAXDATEBUF 80