чување 7838a238c0c2881c9255d54f60d4b9743393407e
родитељ 09af6e83d20285dfb10b80561efada734e9de5f3
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Sat, 22 Jun 2024 20:46:10 +0200
New function: wrap_para (C-J); use ssize_t instead of size_t
Diffstat:
| M | config.def.h | | | 2 | ++ |
| M | draw.c | | | 47 | ++++++++++++++++++++++++++--------------------- |
| M | draw.h | | | 31 | ++++++++++++++++--------------- |
| M | sled.c | | | 440 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- |
| M | sled.h | | | 4 | +++- |
| M | util.c | | | 15 | +++++++++++++++ |
| M | util.h | | | 10 | ++++++---- |
измењених датотека: 7, додавања: 387(+), брисања: 162(-)
diff --git a/config.def.h b/config.def.h
@@ -88,6 +88,8 @@ static const struct Key global_keys[] = {
.callback = move_end },
{ .ev = { .key = TB_KEY_CTRL_F, .mod = TB_MOD_CTRL },
.callback = move_page_down },
+ { .ev = { .key = TB_KEY_CTRL_J, .mod = TB_MOD_CTRL },
+ .callback = wrap_para },
{ .ev = { .key = TB_KEY_CTRL_K, .mod = TB_MOD_CTRL },
.callback = erase_to_end },
{ .ev = { .key = TB_KEY_CTRL_L, .mod = TB_MOD_CTRL },
diff --git a/draw.c b/draw.c
@@ -68,10 +68,12 @@ const char* errors[] = {
[ERR_CANT_OPEN] = "Cannot read file",
[ERR_CANT_COPY] = "Cannot create the backup file",
[ERR_INPUT_NONNUM] = "Input must be numerical",
- [ERR_INVALID_NUM] = "Invalid input"};
+ [ERR_INVALID_NUM] = "Invalid input",
+ [ERR_NOT_IMP] = "Function not implemented/configured"};
const char* actions[] = {
[ACT_WRITING] = "Writing...",
- [ACT_READING] = "Reading..."
+ [ACT_READING] = "Reading...",
+ [ACT_WRAPPING] = "Wrapping..."
};
const char* go_to_dialog_title = "Go to line";
const char* replace_dialog_title = "Replace with";
@@ -94,12 +96,15 @@ assign_coord(struct Coord* dest, const struct Coord src)
/* Calculates buffer length from a display length.
* max_index = the display index up to which the length is calculated
*/
-size_t
-buffer_length(uint32_t* buffer, const size_t max_index)
+ssize_t
+buffer_length(uint32_t* buffer, const ssize_t max_index)
{
- size_t len = 0;
+ ssize_t len = 0;
uint32_t* pbuf = buffer;
- size_t i = 0;
+ ssize_t i = 0;
+
+ if (!pbuf)
+ return 0;
for (i = 0; *pbuf && len < max_index; i++)
{
@@ -129,16 +134,16 @@ calculate_input_dialog_width(const struct DrawState* state)
/* Calculates display length of a buffer line.
* max_index = the buffer index up to which the length is calculated
*/
-size_t
-display_length(uint32_t* buffer, const size_t max_index)
+ssize_t
+display_length(uint32_t* buffer, const ssize_t max_index)
{
- size_t len = 0;
+ ssize_t len = 0;
uint32_t* pbuf = buffer;
if (!buffer)
return len;
- for (size_t i = 0; *pbuf && i < max_index; i++)
+ for (ssize_t i = 0; *pbuf && i < max_index; i++)
{
pbuf = buffer + i;
if (*pbuf == '\t')
@@ -322,7 +327,7 @@ draw_screen(const struct DrawState* state)
max_screen_lines = state->maxy - 1;
i = state->first_shown.row;
- while (((size_t)i < state->rows_count) && (cy < max_screen_lines))
+ while (((ssize_t)i < state->rows_count) && (cy < max_screen_lines))
{
current = state->buffer + i;
@@ -368,7 +373,7 @@ int
draw_status(const struct DrawState* state)
{
char* buf = NULL;
- size_t seg_size;
+ ssize_t seg_size;
int current_start = 0;
const struct StatusSegment* pseg;
@@ -422,7 +427,7 @@ draw_status(const struct DrawState* state)
seg_size = state->maxx - 1 - current_start;
if (draw_string(current_start, state->maxy - 1,
pseg->fg, pseg->bg, buf,
- MIN(seg_size, strlen(buf) + 2),
+ MIN(seg_size, (ssize_t)(strlen(buf) + 2)),
last ? seg_size + 1 : seg_size, 1, 1,
pseg->alignment, 0, 1, NULL, 0, 0, 0, 0, 0,
0))
@@ -472,8 +477,8 @@ draw_string(const int x, const int y, const uint16_t fg, const uint16_t bg,
}
void
-format_filename(char* result, size_t result_size, const char* format,
- const size_t seg_size, const struct DrawState* state)
+format_filename(char* result, ssize_t result_size, const char* format,
+ const ssize_t seg_size, const struct DrawState* state)
{
char* basename = NULL;
if (!result || seg_size < 4)
@@ -481,7 +486,7 @@ format_filename(char* result, size_t result_size, const char* format,
basename = strdup(u8_basename(state->filename));
- if (u8_strlen(basename) + 2 >= seg_size)
+ if ((ssize_t)(u8_strlen(basename) + 2) >= seg_size)
{
if (state->dirty)
basename[seg_size - 4] = 0;
@@ -497,8 +502,8 @@ format_filename(char* result, size_t result_size, const char* format,
}
void
-format_mode(char* result, size_t result_size, const char* format,
- const size_t seg_size, const struct DrawState* state)
+format_mode(char* result, ssize_t result_size, const char* format,
+ const ssize_t seg_size, const struct DrawState* state)
{
const char* mode_label = mode_labels[UNKNOWN_MODE];
UNUSED(seg_size);
@@ -526,8 +531,8 @@ format_print:
}
void
-format_position(char* result, size_t result_size, const char* format,
- const size_t seg_size, const struct DrawState* state)
+format_position(char* result, ssize_t result_size, const char* format,
+ const ssize_t seg_size, const struct DrawState* state)
{
UNUSED(seg_size);
if (!result)
@@ -555,7 +560,7 @@ free_bufferline(struct BufferLine* bl, const int free_text)
void
free_drawstate(struct DrawState* state, int skip_paste_free)
{
- size_t row = 0;
+ ssize_t row = 0;
for (row = 0; row < state->buffer_size; row++)
free_bufferline(state->buffer + row, 1);
free(state->backup_filename);
diff --git a/draw.h b/draw.h
@@ -2,6 +2,7 @@
* any later version. Copyright (C) 2022-2024 Страхиња Радић.
* See the file LICENSE for exact copyright and license details. */
#include <stddef.h>
+#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include <wchar.h>
@@ -42,8 +43,8 @@ struct Coord {
struct BufferLine {
uint32_t* text;
- size_t length; /* both in uint32_t units */
- size_t size;
+ ssize_t length; /* both in uint32_t units */
+ ssize_t size;
uint16_t fg;
uint16_t bg;
};
@@ -60,21 +61,21 @@ struct DrawState {
uint32_t* search;
int chain_dialog; /* show input dialogs in sequence? */
struct BufferLine* buffer;
- size_t buffer_size; /* buffer parameter */
+ ssize_t buffer_size; /* buffer parameter */
struct Coord coord; /* buffer coordinates */
struct Coord first_shown; /* display coordinates */
int input_first_shown_column; /* display coordinate */
int input_display_column; /* display coordinate */
int input_column; /* buffer coordinates */
char* input_title;
- size_t rows_count; /* buffer parameter */
+ ssize_t rows_count; /* buffer parameter */
int display_column; /* display coordinate */
int saved_column; /* display coordinate */
int help_width; /* display parameter */
int input_dialog_width; /* display parameter */
struct BufferLine* paste;
- size_t paste_count;
- size_t paste_size;
+ ssize_t paste_count;
+ ssize_t paste_size;
int (*prompt_callback)(struct DrawState*, struct tb_event*);
int (*input_callback)(struct DrawState*);
int (*input_update_callback)(struct DrawState*);
@@ -97,7 +98,7 @@ struct Key {
struct StatusSegment {
const char* format;
- void (*callback)(char*, size_t, const char*, const size_t,
+ void (*callback)(char*, ssize_t, const char*, const ssize_t,
const struct DrawState*);
uint16_t fg;
uint16_t bg;
@@ -105,10 +106,10 @@ struct StatusSegment {
};
void assign_coord(struct Coord* dest, const struct Coord src);
-size_t buffer_length(uint32_t* buffer, const size_t max_index);
+ssize_t buffer_length(uint32_t* buffer, const ssize_t max_index);
int calculate_help_width(const struct DrawState* state);
int calculate_input_dialog_width(const struct DrawState* state);
-size_t display_length(uint32_t* buffer, const size_t max_index);
+ssize_t display_length(uint32_t* buffer, const ssize_t max_index);
int draw(const struct DrawState* state);
void draw_box(const int startx, const int endx, const int starty,
const int endy, const uint16_t fg, const uint16_t bg);
@@ -124,12 +125,12 @@ int draw_string(const int x, const int y, const uint16_t fg, const uint16_t bg,
const int ds, const int fill, const uint32_t* srch, const uint16_t sfg,
const uint16_t sbg, const int ssi, const int sei, const uint16_t slfg,
const uint16_t slbg);
-void format_filename(char* result, size_t result_size, const char* format,
- const size_t seg_size, const struct DrawState* state);
-void format_mode(char* result, size_t result_size, const char* format,
- const size_t seg_size, const struct DrawState* state);
-void format_position(char* result, size_t result_size, const char* format,
- const size_t seg_size, const struct DrawState* state);
+void format_filename(char* result, ssize_t result_size, const char* format,
+ const ssize_t seg_size, const struct DrawState* state);
+void format_mode(char* result, ssize_t result_size, const char* format,
+ const ssize_t seg_size, const struct DrawState* state);
+void format_position(char* result, ssize_t result_size, const char* format,
+ const ssize_t seg_size, const struct DrawState* state);
void free_bufferline(struct BufferLine* bl, const int free_text);
void free_drawstate(struct DrawState* state, int skip_paste_free);
void init_bufferline(struct BufferLine* bl);
diff --git a/sled.c b/sled.c
@@ -179,7 +179,7 @@ create_file(struct DrawState* state)
state->running = 0;
return LOAD_ERR_CANT_ALLOC;
}
- for (size_t row = 0; row < ALLOC_DELTA; row++)
+ for (ssize_t row = 0; row < ALLOC_DELTA; row++)
{
init_bufferline(newchunk + row);
newtext = calloc(LINE_DEFAULT, sizeof(uint32_t));
@@ -211,7 +211,7 @@ cut_to_paste(struct DrawState* state)
}
static char*
-dirname(char* dir, char* path, const size_t dir_size)
+dirname(char* dir, char* path, const ssize_t dir_size)
{
char* p = NULL;
@@ -247,17 +247,17 @@ do_search_replace(struct DrawState* state)
uint32_t* buf = NULL;
uint32_t* temp = NULL;
/* minimum size is LINE_DEFAULT to avoid 0-allocation */
- size_t bufsize = LINE_DEFAULT; /* size in uint32_t units */
- size_t buflen = 0;
- size_t old_buflen = 0;
- size_t search_len = u32_strlen(state->search);
- size_t input_len = u32_strlen(state->input);
- size_t after_len = 0;
- int start_row = 0;
- int end_row = state->rows_count;
- uint32_t* before = NULL;
- uint32_t* found = NULL;
- uint32_t* after = NULL;
+ ssize_t bufsize = LINE_DEFAULT; /* size in uint32_t units */
+ ssize_t buflen = 0;
+ ssize_t old_buflen = 0;
+ ssize_t search_len = u32_strlen(state->search);
+ ssize_t input_len = u32_strlen(state->input);
+ ssize_t after_len = 0;
+ int start_row = 0;
+ int end_row = state->rows_count;
+ uint32_t* before = NULL;
+ uint32_t* found = NULL;
+ uint32_t* after = NULL;
if (SEL_NOT_EMPTY(state))
get_selection(&start_row, NULL, &end_row, NULL, state);
@@ -359,7 +359,7 @@ erase_backwards(struct DrawState* state)
if (state->coord.col > 0)
{
- size_t i = state->coord.col;
+ ssize_t i = state->coord.col;
do
{
buffer_line->text[i - 1] = buffer_line->text[i];
@@ -394,7 +394,7 @@ erase_forward(struct DrawState* state)
if (buffer_line->text[state->coord.col])
{
- size_t i = state->coord.col;
+ ssize_t i = state->coord.col;
while (i + 2 < buffer_line->size && buffer_line->text[i + 1])
{
buffer_line->text[i] = buffer_line->text[i + 1];
@@ -404,7 +404,7 @@ erase_forward(struct DrawState* state)
buffer_line->length--;
state->dirty = 1;
}
- else if ((size_t)(state->coord.row + 1) < state->rows_count)
+ else if ((state->coord.row + 1) < state->rows_count)
simple_join_lines(state);
return 0;
}
@@ -420,7 +420,7 @@ erase_line(struct DrawState* state)
return 0;
}
free(state->buffer[state->coord.row].text);
- for (size_t row = state->coord.row; row < state->rows_count - 1; row++)
+ for (ssize_t row = state->coord.row; row < state->rows_count - 1; row++)
{
current = state->buffer + row;
current->text = state->buffer[row + 1].text;
@@ -428,7 +428,7 @@ erase_line(struct DrawState* state)
current->length = state->buffer[row + 1].length;
}
free_bufferline(&state->buffer[state->rows_count - 1], 0);
- if ((size_t)(state->coord.row + 1) == state->rows_count)
+ if ((state->coord.row + 1) == state->rows_count)
state->coord.row--;
position_to(state, state->coord.row, 0);
state->rows_count--;
@@ -455,7 +455,7 @@ erase_prev_word(struct DrawState* state)
d = state->coord.col - i;
- for (size_t j = i; j + d < current->length; j++)
+ for (ssize_t j = i; j + d < current->length; j++)
current->text[j] = current->text[j + d];
current->length -= d;
@@ -475,11 +475,11 @@ erase_selection(struct DrawState* state)
int ssr = 0;
int ssc = 0;
/* Selection end row/col */
- int ser = 0;
- int sec = 0;
- uint32_t* buf = NULL;
- size_t bufsize = state->buffer[ser].size;
- uint32_t* temp = NULL;
+ int ser = 0;
+ int sec = 0;
+ uint32_t* buf = NULL;
+ ssize_t bufsize = state->buffer[ser].size;
+ uint32_t* temp = NULL;
buf = calloc(bufsize, sizeof(uint32_t));
if (!buf)
@@ -496,7 +496,7 @@ erase_selection(struct DrawState* state)
if (ssr != ser)
{
- for (size_t row = 0; ser + row + 1 < state->rows_count;
+ for (ssize_t row = 0; ser + row + 1 < state->rows_count;
row++)
{
U32_MEMCCPY(state->buffer[ssr + row + 1].text,
@@ -505,7 +505,7 @@ erase_selection(struct DrawState* state)
state->buffer[ssr + row + 1].length
= state->buffer[ser + row + 1].length;
}
- for (size_t row = state->rows_count - (ser - ssr);
+ for (ssize_t row = state->rows_count - (ser - ssr);
row < state->rows_count; row++)
{
*state->buffer[row].text = 0;
@@ -542,9 +542,9 @@ erase_to_end(struct DrawState* state)
static int
erase_to_start(struct DrawState* state)
{
- size_t i = state->coord.col;
+ ssize_t i = state->coord.col;
struct BufferLine* buffer_line = &state->buffer[state->coord.row];
- size_t len = buffer_line->length;
+ ssize_t len = buffer_line->length;
if (SEL_NOT_EMPTY(state))
{
@@ -636,8 +636,8 @@ get_selection(int* ssr, int* ssc, int* ser, int* sec,
static int
go_to_line_callback(struct DrawState* state)
{
- size_t lineno = 0;
- size_t len = 0;
+ ssize_t lineno = 0;
+ ssize_t len = 0;
char* u8_input = NULL;
char* temp = NULL;
@@ -846,7 +846,7 @@ input_erase_backwards(struct DrawState* state)
{
if (state->input_column > 0)
{
- size_t i = state->input_column;
+ ssize_t i = state->input_column;
do
{
state->input[i - 1] = state->input[i];
@@ -865,7 +865,7 @@ input_erase_forward(struct DrawState* state)
{
if (state->input)
{
- size_t i = state->input_column;
+ ssize_t i = state->input_column;
while (i + 2 < MAXINPUT && state->input[i + 1])
{
state->input[i] = state->input[i + 1];
@@ -893,8 +893,8 @@ input_erase_to_end(struct DrawState* state)
static int
input_erase_to_start(struct DrawState* state)
{
- size_t i = state->input_column;
- size_t len = u32_strlen(state->input);
+ ssize_t i = state->input_column;
+ ssize_t len = u32_strlen(state->input);
do
{
@@ -911,12 +911,12 @@ input_erase_to_start(struct DrawState* state)
static int
input_insert_char(struct DrawState* state, uint32_t ch)
{
- size_t len = u32_strlen(state->input);
+ ssize_t len = u32_strlen(state->input);
if (state->input_column + 1 < MAXINPUT)
{
- size_t i = len + 1;
+ ssize_t i = len + 1;
int add_null = state->input[state->input_column] == 0;
- while (i + 2 < MAXINPUT && i > (size_t)state->input_column)
+ while (i + 2 < MAXINPUT && i > state->input_column)
{
state->input[i] = state->input[i - 1];
i--;
@@ -964,11 +964,11 @@ input_move_next_word(struct DrawState* state)
{
int i = state->input_column;
uint32_t* pline = state->input;
- size_t len = u32_strlen(state->input);
+ ssize_t len = u32_strlen(state->input);
- while ((size_t)i < len && !u32_is_word_boundary(pline[i], 0))
+ while (i < len && !u32_is_word_boundary(pline[i], 0))
i++;
- while ((size_t)i < len && u32_is_word_boundary(pline[i], 0))
+ while (i < len && u32_is_word_boundary(pline[i], 0))
i++;
input_position_to(state, i);
return 0;
@@ -1008,10 +1008,10 @@ input_move_start(struct DrawState* state)
static void
input_position_to(struct DrawState* state, const int column)
{
- size_t len = u32_strlen(state->input);
+ ssize_t len = u32_strlen(state->input);
state->input_column = column;
- if ((size_t)state->input_column > len)
+ if (state->input_column > len)
state->input_column = len;
state->input_display_column
= display_length(state->input, state->input_column);
@@ -1027,10 +1027,9 @@ static int
insert_char(struct DrawState* state, uint32_t ch)
{
struct BufferLine* buffer_line = NULL;
- size_t i;
- int add_null;
- size_t len;
- size_t size;
+ ssize_t i;
+ ssize_t len;
+ ssize_t size;
uint32_t* ptext = NULL;
ENSURE_SIZE(state->buffer[state->coord.row].text, ptext,
@@ -1047,23 +1046,21 @@ insert_char(struct DrawState* state, uint32_t ch)
}
buffer_line = &state->buffer[state->coord.row];
- add_null = buffer_line->text[state->coord.col] == 0;
len = buffer_line->length;
size = buffer_line->size;
- i = len + 1;
+ i = len;
if (!IN(state->mode, M_OVERWRITE))
- while (i + 1 < size && i > (size_t)state->coord.col)
+ while (i + 1 < size && i > state->coord.col)
{
buffer_line->text[i] = buffer_line->text[i - 1];
i--;
}
buffer_line->text[state->coord.col] = ch;
- if ((size_t)state->coord.col == len || !IN(state->mode, M_OVERWRITE))
+ if (state->coord.col == len || !IN(state->mode, M_OVERWRITE))
buffer_line->length++;
position_to(state, state->coord.row, state->coord.col + 1);
- if (add_null)
- buffer_line->text[state->coord.col] = 0;
+ buffer_line->text[buffer_line->length] = 0;
#ifdef ENABLE_WRAP
while (state->display_column >= WRAP_WIDTH)
@@ -1178,7 +1175,7 @@ join_lines(struct DrawState* state)
ser = state->coord.row;
}
- if ((size_t)(ssr + 1) == state->rows_count)
+ if ((ssr + 1) == state->rows_count)
return 0;
for (int row = ssr; row <= ser; row++)
@@ -1224,8 +1221,8 @@ load_file(struct DrawState* state)
struct BufferLine* line = NULL;
FILE* input = NULL;
char* input_line = NULL;
- size_t input_size = limits[L_LINE_MAX];
- size_t input_len = 0;
+ ssize_t input_size = limits[L_LINE_MAX];
+ ssize_t input_len = 0;
uint32_t* newtext = NULL;
uint32_t* ptext = NULL;
char* temp = NULL;
@@ -1242,7 +1239,7 @@ load_file(struct DrawState* state)
state->running = 0;
goto load_file_alloc_error;
}
- for (size_t row = 0; row < ALLOC_DELTA; row++)
+ for (ssize_t row = 0; row < ALLOC_DELTA; row++)
{
init_bufferline(newchunk + row);
newtext = calloc(LINE_DEFAULT, sizeof(uint32_t));
@@ -1287,7 +1284,7 @@ load_file(struct DrawState* state)
goto load_file_alloc_error;
}
state->buffer = newchunk;
- for (size_t row = state->buffer_size - ALLOC_DELTA;
+ for (ssize_t row = state->buffer_size - ALLOC_DELTA;
row < state->buffer_size; row++)
{
init_bufferline(state->buffer + row);
@@ -1360,11 +1357,11 @@ move_next_word(struct DrawState* state)
{
int i = state->coord.col;
uint32_t* pline = state->buffer[state->coord.row].text;
- size_t len = state->buffer[state->coord.row].length;
+ ssize_t len = state->buffer[state->coord.row].length;
- while ((size_t)i < len && !u32_is_word_boundary(pline[i], 0))
+ while (i < len && !u32_is_word_boundary(pline[i], 0))
i++;
- while ((size_t)i < len && u32_is_word_boundary(pline[i], 0))
+ while (i < len && u32_is_word_boundary(pline[i], 0))
i++;
position_to(state, state->coord.row, i);
return 0;
@@ -1373,7 +1370,7 @@ move_next_word(struct DrawState* state)
static int
move_page_down(struct DrawState* state)
{
- if ((size_t)(state->coord.row + state->maxy) < state->rows_count + 2)
+ if ((state->coord.row + state->maxy) < state->rows_count + 2)
position_to(state, state->coord.row + state->maxy - 2,
state->coord.col);
else
@@ -1419,11 +1416,11 @@ move_right(struct DrawState* state)
static int
move_screen_bottom(struct DrawState* state)
{
- if (state->rows_count + 2 < (size_t)state->maxy)
+ if (state->rows_count + 2 < state->maxy)
position_to(state, state->rows_count - 1, state->coord.col);
else
{
- if ((size_t)(state->first_shown.row + state->maxy)
+ if ((state->first_shown.row + state->maxy)
< state->rows_count + 2)
position_to(state,
state->first_shown.row + state->maxy - 2,
@@ -1435,12 +1432,12 @@ move_screen_bottom(struct DrawState* state)
static int
move_screen_middle(struct DrawState* state)
{
- if (state->rows_count + 2 < (size_t)state->maxy)
+ if (state->rows_count + 2 < state->maxy)
position_to(state, state->rows_count / 2, state->coord.col);
else
{
int row = state->first_shown.row + (state->maxy - 2) / 2;
- if (state->rows_count < (size_t)(row + (state->maxy - 2) / 2))
+ if (state->rows_count < (row + (state->maxy - 2) / 2))
row = state->rows_count - (state->maxy - 2) / 2;
position_to(state, row, state->coord.col);
}
@@ -1481,17 +1478,17 @@ next_match(struct DrawState* state)
{
struct BufferLine* current = NULL;
const uint32_t* found = NULL;
- size_t idelta;
+ ssize_t idelta;
if (!state->search || !*state->search)
return 0;
*state->error = 0;
- for (size_t row = state->coord.row; row < state->rows_count; row++)
+ for (ssize_t row = state->coord.row; row < state->rows_count; row++)
{
current = state->buffer + row;
found = current->text;
- if (row == (size_t)state->coord.row)
+ if (row == state->coord.row)
found += state->coord.col + 1;
found = u32_strstr(found, state->search);
if (found)
@@ -1514,11 +1511,11 @@ paste_from_paste(struct DrawState* state)
{
uint32_t* newtext = NULL;
uint32_t* ptext = NULL;
- size_t newsize = 0;
+ ssize_t newsize = 0;
struct BufferLine* line = NULL;
struct BufferLine* newbuf = NULL;
uint32_t* rest = NULL;
- size_t rest_size = 0;
+ ssize_t rest_size = 0;
struct Coord newpos;
char* temp = NULL;
@@ -1536,13 +1533,13 @@ paste_from_paste(struct DrawState* state)
{
if (state->rows_count + state->paste_count > state->buffer_size)
{
- size_t old_size = state->buffer_size;
+ ssize_t old_size = state->buffer_size;
while (state->rows_count + state->paste_count
> state->buffer_size)
state->buffer_size += ALLOC_DELTA;
newbuf = realloc(state->buffer,
state->buffer_size * sizeof(struct BufferLine));
- for (size_t row = old_size; row < state->buffer_size;
+ for (ssize_t row = old_size; row < state->buffer_size;
row++)
{
init_bufferline(newbuf + row);
@@ -1599,7 +1596,7 @@ paste_from_paste(struct DrawState* state)
U32_SAFE_COPY(line->text, ptext, line->size, newtext, newsize,
paste_from_paste_cleanup);
line->length = u32_strlen(line->text);
- for (size_t row = state->rows_count - state->coord.row
+ for (ssize_t row = state->rows_count - state->coord.row
- (state->paste_count - 2) - 1;
row > 0; row--)
{
@@ -1617,7 +1614,7 @@ paste_from_paste(struct DrawState* state)
U32_SAFE_COPY(line->text, ptext, line->size, newtext, newsize,
paste_from_paste_cleanup);
line->length = u32_strlen(line->text);
- for (size_t row = 1; row < state->paste_count - 1; row++)
+ for (ssize_t row = 1; row < state->paste_count - 1; row++)
{
line = state->buffer + state->coord.row + row;
U32_SAFE_COPY(line->text, ptext, line->size,
@@ -1662,12 +1659,12 @@ paste_from_paste_cleanup:
static void
position_to(struct DrawState* state, const int row, const int column)
{
- size_t dlen;
+ ssize_t dlen;
if (row != state->coord.row)
{
state->coord.row = row;
- if ((size_t)(state->coord.row + 1) > state->rows_count)
+ if ((state->coord.row + 1) > state->rows_count)
state->coord.row = state->rows_count - 1;
if (state->first_shown.row > state->coord.row)
state->first_shown.row = state->coord.row;
@@ -1693,7 +1690,7 @@ position_to(struct DrawState* state, const int row, const int column)
= state->buffer[state->coord.row].length;
dlen = display_length(state->buffer[state->coord.row].text,
state->coord.col);
- if (dlen < (size_t)state->saved_column)
+ if (dlen < state->saved_column)
state->display_column = dlen;
else
state->display_column = state->saved_column;
@@ -1712,10 +1709,10 @@ position_to(struct DrawState* state, const int row, const int column)
else
state->coord.col = 0;
}
- else if ((size_t)state->coord.col
+ else if (state->coord.col
> state->buffer[state->coord.row].length)
{
- if ((size_t)(state->coord.row + 1) < state->rows_count)
+ if ((state->coord.row + 1) < state->rows_count)
{
state->coord.row++;
state->coord.col = 0;
@@ -1740,6 +1737,24 @@ position_to(struct DrawState* state, const int row, const int column)
}
static int
+position_to_selection_end(struct DrawState* state)
+{
+ if (SEL_NOT_EMPTY(state))
+ {
+ int ser = 0;
+ int sec = 0;
+
+ get_selection(NULL, NULL, &ser, &sec, state);
+
+ state->saved_column
+ = display_length(state->buffer[ser].text, sec);
+ position_to(state, ser, sec);
+ state->saved_column = state->display_column;
+ }
+ return 0;
+}
+
+static int
position_to_selection_start(struct DrawState* state)
{
if (SEL_NOT_EMPTY(state))
@@ -1762,8 +1777,8 @@ prev_match(struct DrawState* state)
{
struct BufferLine* current = NULL;
const uint32_t* found = NULL;
- size_t idelta;
- size_t row;
+ ssize_t idelta;
+ ssize_t row;
if (!state->search || !*state->search)
return 0;
@@ -1771,14 +1786,14 @@ prev_match(struct DrawState* state)
*state->error = 0;
row = state->coord.row;
- while (row >= 0)
+ while (1)
{
const uint32_t* save_found;
current = state->buffer + row;
found = current->text;
if (!found)
return 0;
- if (row == (size_t)state->coord.row)
+ if (row == state->coord.row)
found += state->coord.col;
else
found += current->length;
@@ -1896,10 +1911,10 @@ reread_or_callback(struct DrawState* state)
static int
save_file(struct DrawState* state)
{
- FILE* output = NULL;
- char* buf = NULL;
- char* pbuf = NULL;
- size_t bufsize = LINE_DEFAULT;
+ FILE* output = NULL;
+ char* buf = NULL;
+ char* pbuf = NULL;
+ ssize_t bufsize = LINE_DEFAULT;
#ifdef CREATE_BACKUPS
struct stat st;
#endif
@@ -2009,7 +2024,7 @@ save_skip_backup_symlink:
if (state->rows_count == 1 && state->buffer[0].length == 0)
goto save_file_cleanup;
- for (size_t row = 0; row < state->rows_count; row++)
+ for (ssize_t row = 0; row < state->rows_count; row++)
{
ENSURE_SIZE(buf, pbuf, bufsize,
UTF8REPMAX * state->buffer[row].length + 1,
@@ -2229,7 +2244,7 @@ simple_insert_line(struct DrawState* state)
return;
}
state->buffer = newchunk;
- for (size_t row = state->buffer_size - ALLOC_DELTA;
+ for (ssize_t row = state->buffer_size - ALLOC_DELTA;
row < state->buffer_size; row++)
{
line = state->buffer + row;
@@ -2240,23 +2255,25 @@ simple_insert_line(struct DrawState* state)
}
}
state->rows_count++;
- for (size_t i = state->rows_count - 1;
- i > (size_t)(state->coord.row + 1); i--)
+ for (ssize_t i = state->rows_count - 1; i > (state->coord.row + 1); i--)
{
U32_SAFE_COPY(state->buffer[i].text, ptext,
state->buffer[i].size, state->buffer[i - 1].text,
state->buffer[i - 1].size, simple_insert_line_error);
- state->buffer[i].length = u32_strlen(state->buffer[i].text);
+ state->buffer[i].length = state->buffer[i - 1].length;
}
U32_SAFE_COPY(state->buffer[state->coord.row + 1].text, ptext,
state->buffer[state->coord.row + 1].size,
state->buffer[state->coord.row].text + state->coord.col,
state->buffer[state->coord.row].size, simple_insert_line_error);
+
state->buffer[state->coord.row + 1].length
- = u32_strlen(state->buffer[state->coord.row + 1].text);
+ = state->buffer[state->coord.row].length - state->coord.col;
+
state->buffer[state->coord.row].text[state->coord.col] = 0;
state->buffer[state->coord.row].length = state->coord.col;
- state->dirty = 1;
+
+ state->dirty = 1;
return;
simple_insert_line_error:
@@ -2266,29 +2283,24 @@ simple_insert_line_error:
static void
simple_join_lines(struct DrawState* state)
{
- size_t first_line = state->coord.row;
- uint32_t* ptext = NULL;
+ struct BufferLine* first_line = NULL;
+ struct BufferLine* next_line = NULL;
+ uint32_t* ptext = NULL;
- if (first_line == state->rows_count - 1)
+ if ((state->coord.row + 1) == state->rows_count)
return;
- ENSURE_SIZE(state->buffer[first_line].text, ptext,
- state->buffer[first_line].size,
- state->buffer[first_line].length
- + state->buffer[first_line + 1].length + 1,
- state->buffer[first_line].length
- + state->buffer[first_line + 1].length + 1,
+ first_line = &state->buffer[state->coord.row];
+ next_line = &state->buffer[state->coord.row + 1];
+ ENSURE_SIZE(first_line->text, ptext, first_line->size,
+ first_line->length + next_line->length + 1,
+ first_line->length + next_line->length + LINE_ALLOC_DELTA,
simple_join_lines_error, uint32_t);
- U32_MEMCCPY((state->buffer[first_line].text
- + state->buffer[first_line].length),
- state->buffer[first_line + 1].text,
- state->buffer[first_line].size
- - state->buffer[first_line + 1].length,
- ptext);
- state->buffer[first_line].length
- = u32_strlen(state->buffer[first_line].text);
- //+= state->buffer[first_line + 1].length;
- for (size_t i = first_line + 1; i < state->rows_count - 1; i++)
+ U32_MEMCCPY((first_line->text + first_line->length), next_line->text,
+ next_line->length + 1, ptext);
+ first_line->length = u32_strlen(first_line->text);
+ /* i <- i+1 */
+ for (ssize_t i = state->coord.row + 1; i + 1 < state->rows_count; i++)
{
U32_SAFE_COPY(state->buffer[i].text, ptext,
state->buffer[i].size, state->buffer[i + 1].text,
@@ -2314,7 +2326,7 @@ simple_yank(struct DrawState* state)
int ser = 0;
int sec = 0;
struct BufferLine* newbuf = NULL;
- size_t initialize_start;
+ ssize_t initialize_start;
uint32_t* ptext = NULL;
if (!SEL_NOT_EMPTY(state))
@@ -2348,7 +2360,7 @@ simple_yank(struct DrawState* state)
}
else
newbuf = state->paste;
- for (size_t row = initialize_start; row < state->paste_size; row++)
+ for (ssize_t row = initialize_start; row < state->paste_size; row++)
{
init_bufferline(newbuf + row);
ENSURE_SIZE(newbuf[row].text, ptext, newbuf[row].size,
@@ -2359,20 +2371,20 @@ simple_yank(struct DrawState* state)
if (state->paste_count == 1)
{
U32_SAFE_COPY(state->paste[0].text, ptext, state->paste[0].size,
- state->buffer[ssr].text + ssc, (size_t)(sec - ssc + 1),
+ state->buffer[ssr].text + ssc, (sec - ssc + 1),
simple_yank_alloc_error);
state->paste[0].length = sec - ssc;
}
else
{
- size_t first_line_len = state->buffer[ssr].length - ssc;
+ ssize_t first_line_len = state->buffer[ssr].length - ssc;
U32_SAFE_COPY(state->paste[0].text, ptext, state->paste[0].size,
state->buffer[ssr].text + ssc, first_line_len + 1,
simple_yank_alloc_error);
state->paste[0].length = first_line_len;
- for (size_t row = 1; row < state->paste_count - 1; row++)
+ for (ssize_t row = 1; row < state->paste_count - 1; row++)
{
U32_SAFE_COPY(state->paste[row].text, ptext,
state->paste[row].size,
@@ -2385,7 +2397,7 @@ simple_yank(struct DrawState* state)
U32_SAFE_COPY(state->paste[state->paste_count - 1].text, ptext,
state->paste[state->paste_count - 1].size,
- state->buffer[ser].text, (size_t)(sec + 1),
+ state->buffer[ser].text, (sec + 1),
simple_yank_alloc_error);
state->paste[state->paste_count - 1].length = sec;
}
@@ -2440,6 +2452,192 @@ toggle_selection(struct DrawState* state)
return 0;
}
+/*
+ * Not ideal (todo). In extreme cases (files generated by the testsuite, with a
+ * huge block of full lines with no spaces), becomes unresponsive and has to be
+ * killed. But in most "normal" cases, behaves acceptably.
+ */
+static int
+wrap_para(struct DrawState* state)
+{
+ char* temp = NULL;
+#ifdef ENABLE_WRAP
+ struct BufferLine* current = NULL;
+ struct BufferLine* next = NULL;
+ uint32_t* ptext = NULL;
+ int sel = SEL_NOT_EMPTY(state);
+ int start_row;
+ int end_row;
+ int cur_row;
+ int bcol;
+ int dlen;
+ int col;
+
+ MEMCCPY(state->action, actions[ACT_WRAPPING], LINE_DEFAULT, temp);
+ redraw_status(state);
+
+ if (sel)
+ get_selection(&start_row, NULL, &end_row, NULL, state);
+ else
+ {
+ start_row = state->coord.row;
+ end_row = start_row;
+ for (cur_row = start_row; cur_row > 0; cur_row--)
+ if (state->buffer[cur_row - 1].length == 0
+ || !u32_has_nonblanks(
+ state->buffer[cur_row - 1].text))
+ {
+ start_row = cur_row;
+ break;
+ }
+ if (cur_row == 0)
+ start_row = cur_row;
+ for (cur_row = state->coord.row; cur_row < state->rows_count;
+ cur_row++)
+ if (state->buffer[cur_row].length == 0
+ || !u32_has_nonblanks(
+ state->buffer[cur_row].text))
+ {
+ end_row = cur_row - 1;
+ break;
+ }
+ }
+
+ cur_row = start_row;
+wrap_next_line:
+ state->coord.col = 0;
+ current = &state->buffer[cur_row];
+ next = &state->buffer[cur_row + 1];
+ bcol = buffer_length(current->text, WRAP_WIDTH);
+ state->coord.row = cur_row;
+
+ dlen = display_length(current->text, current->length);
+ while (dlen < WRAP_WIDTH && u32_has_nonblanks(next->text))
+ {
+ /* Insert space to avoid joining ending and beginning words */
+ if (!u32_is_word_boundary(current->text[current->length - 1], 1))
+ {
+ ENSURE_SIZE(current->text, ptext, current->size,
+ current->length + 2, current->length + 2,
+ wrap_alloc_error, uint32_t);
+ current->length++;
+ current->text[current->length - 1] = L' ';
+ current->text[current->length] = 0;
+ }
+
+ simple_join_lines(state);
+
+ if (sel)
+ {
+ state->sel_end.row--;
+ state->sel_end.col
+ = state->buffer[state->sel_end.row].length;
+ }
+ end_row--;
+ dlen = display_length(current->text, current->length);
+ }
+
+ while (dlen >= WRAP_WIDTH)
+ {
+ bcol = buffer_length(current->text, WRAP_WIDTH);
+ while (bcol > 0
+ && !u32_is_word_boundary(current->text[bcol - 1], 1))
+ bcol--;
+ if (bcol == 0)
+ break;
+ ENSURE_SIZE(current->text, ptext, current->size,
+ current->length + 1, current->length + LINE_ALLOC_DELTA,
+ wrap_alloc_error, uint32_t);
+ state->coord.col = bcol - 1;
+
+ simple_insert_line(state);
+
+ cur_row++;
+ state->coord.row++;
+ current = &state->buffer[cur_row];
+
+ /* Remove the space between the two words at split */
+ if (u32_is_word_boundary(current->text[0], 1))
+ {
+ *current->text = 0;
+ for (col = 0; col < current->length; col++)
+ current->text[col] = current->text[col + 1];
+ current->length--;
+ }
+
+ if (sel)
+ {
+ state->sel_end.row++;
+ state->sel_end.col
+ = state->buffer[state->sel_end.row].length;
+ }
+ end_row++;
+ if (cur_row == state->rows_count)
+ break;
+
+ /* If the line in block is < WRAP_WIDTH, join it with next */
+ next = &state->buffer[cur_row + 1];
+ if (u32_has_nonblanks(next->text)
+ && display_length(current->text, current->length)
+ < WRAP_WIDTH)
+ {
+ /* Add space if needed to avoid joining words */
+ if (!u32_is_word_boundary(current->text[current->length
+ - 1],
+ 1))
+ {
+ ENSURE_SIZE(current->text, ptext, current->size,
+ current->length + 2,
+ current->length + 2, wrap_alloc_error,
+ uint32_t);
+ current->length++;
+ current->text[current->length - 1] = L' ';
+ current->text[current->length] = 0;
+ }
+
+ simple_join_lines(state);
+
+ if (sel)
+ {
+ state->sel_end.row--;
+ state->sel_end.col
+ = state->buffer[state->sel_end.row]
+ .length;
+ }
+ end_row--;
+ }
+
+ if (cur_row == MIN((end_row + 1), state->rows_count))
+ break;
+
+ bcol = buffer_length(current->text, WRAP_WIDTH);
+ while (bcol > 0
+ && !u32_is_word_boundary(current->text[bcol - 1], 1))
+ bcol--;
+ if (bcol == 0)
+ break;
+ dlen = display_length(current->text, current->length);
+ }
+ cur_row++;
+ if (cur_row < MIN((end_row + 1), state->rows_count))
+ goto wrap_next_line;
+
+ if (sel)
+ position_to_selection_end(state);
+ else
+ position_to(state, cur_row, 0);
+
+ *state->action = 0;
+
+#else
+ MEMCCPY(state->error, errors[ERR_NOT_IMP], LINE_DEFAULT, temp);
+#endif
+ return 0;
+
+wrap_alloc_error:
+ return 1;
+}
+
static int
write_file(struct DrawState* state)
{
@@ -2498,8 +2696,8 @@ main(int argc, char** argv)
char action[LINE_DEFAULT];
char prompt[LINE_DEFAULT];
struct DrawState state;
- char* filename = NULL;
- size_t filename_size = 0;
+ char* filename = NULL;
+ ssize_t filename_size = 0;
struct stat st;
int result;
int dir_access;
diff --git a/sled.h b/sled.h
@@ -7,7 +7,7 @@ static int clear_selection(struct DrawState* state);
static int cp(const char* from, const char* to);
static int create_file(struct DrawState* dstate);
static int cut_to_paste(struct DrawState* state);
-static char* dirname(char* dir, char* path, const size_t path_size);
+static char* dirname(char* dir, char* path, const ssize_t path_size);
static int do_search_replace(struct DrawState* state);
static int enter_command_mode(struct DrawState* state);
static int enter_insert_mode(struct DrawState* state);
@@ -64,6 +64,7 @@ static int next_match(struct DrawState* state);
static int paste_from_paste(struct DrawState* state);
static void position_to(struct DrawState* state, const int row,
const int column);
+static int position_to_selection_end(struct DrawState* state);
static int position_to_selection_start(struct DrawState* state);
static int prev_match(struct DrawState* state);
static int print_error(const int code, const char* msg, ...);
@@ -87,5 +88,6 @@ static void simple_yank(struct DrawState* state);
static int suspend_program(struct DrawState* state);
static int toggle_overwrite(struct DrawState* state);
static int toggle_selection(struct DrawState* state);
+static int wrap_para(struct DrawState* state);
static int write_file(struct DrawState* state);
static int yank_to_paste(struct DrawState* state);
diff --git a/util.c b/util.c
@@ -62,6 +62,21 @@ unicode_string_to_u8(char* s, const uint32_t* us, const size_t max)
return added;
}
+int
+u32_has_nonblanks(const uint32_t* s)
+{
+ const uint32_t* ps = s;
+ if (!s)
+ return 0;
+ while (*ps)
+ {
+ if (!u32_is_word_boundary(*ps, 1))
+ return 1;
+ ps++;
+ }
+ return 0;
+}
+
uint32_t*
u32_memccpy(uint32_t* dst, const uint32_t* src, uint32_t c, size_t len)
{
diff --git a/util.h b/util.h
@@ -74,7 +74,7 @@
* - Make sure the size of the destination string is large enough to copy, and
* copy
* - Sizes are in bytes
- * - We explicitly use fromsize in u8_strncpy, because we ensured that tosize is
+ * - We explicitly use fromsize in MEMCCPY, because we ensured that tosize is
* at least as big, and to allow a subset of from to be copied
*/
#define U8_SAFE_COPY(to, temp, tosize, from, fromsize, label) \
@@ -87,7 +87,7 @@
* - Make sure the size of the destination string is large enough to copy, and
* copy
* - Sizes are in uint32_t units
- * - We explicitly use fromsize in u32_strncpy, because we ensured that tosize
+ * - We explicitly use fromsize in U32_MEMCCPY, because we ensured that tosize
* is at least as big, and to allow a subset of from to be copied
*/
#define U32_SAFE_COPY(to, temp, tosize, from, fromsize, label) \
@@ -109,15 +109,17 @@ enum {
ERR_CANT_OPEN,
ERR_CANT_COPY,
ERR_INPUT_NONNUM,
- ERR_INVALID_NUM
+ ERR_INVALID_NUM,
+ ERR_NOT_IMP
};
-enum { ACT_WRITING, ACT_READING };
+enum { ACT_WRITING, ACT_READING, ACT_WRAPPING };
#define TB_KEY_CTRL_SPACE 0x00
size_t u8_string_to_unicode(uint32_t* us, const char* s, const size_t max);
size_t unicode_string_to_u8(char* s, const uint32_t* us, const size_t max);
+int u32_has_nonblanks(const uint32_t* s);
uint32_t* u32_memccpy(uint32_t* dst, const uint32_t* src, uint32_t c,
size_t len);
uint32_t* u32_u8_memccpy(uint32_t* dst, const char* src, uint32_t c, size_t len);