#include "proto.h"
#include <string.h>
#include <ctype.h>
void do_first_line(void)
{
const filestruct *current_save = openfile->current;
size_t pww_save = openfile->placewewant;
openfile->current = openfile->fileage;
openfile->current_x = 0;
openfile->placewewant = 0;
edit_redraw(current_save, pww_save);
}
void do_last_line(void)
{
const filestruct *current_save = openfile->current;
size_t pww_save = openfile->placewewant;
openfile->current = openfile->filebot;
openfile->current_x = strlen(openfile->filebot->data);
openfile->placewewant = xplustabs();
openfile->current_y = editwinrows - 1;
edit_redraw(current_save, pww_save);
}
void do_page_up(void)
{
int i;
if (openfile->current->lineno <= editwinrows - 2) {
do_first_line();
return;
}
#ifndef NANO_TINY
if (!ISSET(SMOOTH_SCROLL)) {
#endif
openfile->current = openfile->edittop;
openfile->placewewant = 0;
#ifndef NANO_TINY
}
#endif
for (i = editwinrows - 2; i > 0 && openfile->current !=
openfile->fileage; i--)
openfile->current = openfile->current->prev;
openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant);
edit_scroll(UP_DIR, editwinrows - 2);
}
void do_page_down(void)
{
int i;
if (openfile->current->lineno + editwinrows - 2 >=
openfile->filebot->lineno) {
do_last_line();
return;
}
#ifndef NANO_TINY
if (!ISSET(SMOOTH_SCROLL)) {
#endif
openfile->current = openfile->edittop;
openfile->placewewant = 0;
#ifndef NANO_TINY
}
#endif
for (i = editwinrows - 2; i > 0 && openfile->current !=
openfile->filebot; i--)
openfile->current = openfile->current->next;
openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant);
edit_scroll(DOWN_DIR, editwinrows - 2);
}
#ifndef DISABLE_JUSTIFY
void do_para_begin(bool allow_update)
{
const filestruct *current_save = openfile->current;
const size_t pww_save = openfile->placewewant;
if (openfile->current != openfile->fileage) {
do {
openfile->current = openfile->current->prev;
openfile->current_y--;
} while (!begpar(openfile->current));
}
openfile->current_x = 0;
openfile->placewewant = 0;
if (allow_update)
edit_redraw(current_save, pww_save);
}
void do_para_begin_void(void)
{
do_para_begin(TRUE);
}
void do_para_end(bool allow_update)
{
const filestruct *const current_save = openfile->current;
const size_t pww_save = openfile->placewewant;
while (openfile->current != openfile->filebot &&
!inpar(openfile->current))
openfile->current = openfile->current->next;
while (openfile->current != openfile->filebot &&
inpar(openfile->current->next) &&
!begpar(openfile->current->next)) {
openfile->current = openfile->current->next;
openfile->current_y++;
}
if (openfile->current != openfile->filebot) {
openfile->current = openfile->current->next;
openfile->current_x = 0;
openfile->placewewant = 0;
} else {
openfile->current_x = strlen(openfile->current->data);
openfile->placewewant = xplustabs();
}
if (allow_update)
edit_redraw(current_save, pww_save);
}
void do_para_end_void(void)
{
do_para_end(TRUE);
}
#endif
#ifndef NANO_TINY
bool do_next_word(bool allow_punct, bool allow_update)
{
size_t pww_save = openfile->placewewant;
const filestruct *current_save = openfile->current;
char *char_mb;
int char_mb_len;
bool end_line = FALSE, started_on_word = FALSE;
assert(openfile->current != NULL && openfile->current->data != NULL);
char_mb = charalloc(mb_cur_max());
while (!end_line) {
char_mb_len = parse_mbchar(openfile->current->data +
openfile->current_x, char_mb, NULL);
if (!is_word_mbchar(char_mb, allow_punct))
break;
started_on_word = TRUE;
if (openfile->current->data[openfile->current_x] == '\0')
end_line = TRUE;
else
openfile->current_x += char_mb_len;
}
if (openfile->current->data[openfile->current_x] == '\0')
end_line = TRUE;
else
openfile->current_x += char_mb_len;
for (; openfile->current != NULL;
openfile->current = openfile->current->next) {
while (!end_line) {
char_mb_len = parse_mbchar(openfile->current->data +
openfile->current_x, char_mb, NULL);
if (is_word_mbchar(char_mb, allow_punct))
break;
if (openfile->current->data[openfile->current_x] == '\0')
end_line = TRUE;
else
openfile->current_x += char_mb_len;
}
if (!end_line)
break;
if (openfile->current != openfile->filebot) {
end_line = FALSE;
openfile->current_x = 0;
}
}
free(char_mb);
if (openfile->current == NULL)
openfile->current = openfile->filebot;
openfile->placewewant = xplustabs();
if (allow_update)
edit_redraw(current_save, pww_save);
return started_on_word;
}
void do_next_word_void(void)
{
do_next_word(ISSET(WORD_BOUNDS), TRUE);
}
bool do_prev_word(bool allow_punct, bool allow_update)
{
size_t pww_save = openfile->placewewant;
const filestruct *current_save = openfile->current;
char *char_mb;
int char_mb_len;
bool begin_line = FALSE, started_on_word = FALSE;
assert(openfile->current != NULL && openfile->current->data != NULL);
char_mb = charalloc(mb_cur_max());
while (!begin_line) {
char_mb_len = parse_mbchar(openfile->current->data +
openfile->current_x, char_mb, NULL);
if (!is_word_mbchar(char_mb, allow_punct))
break;
started_on_word = TRUE;
if (openfile->current_x == 0)
begin_line = TRUE;
else
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
}
if (openfile->current_x == 0)
begin_line = TRUE;
else
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
for (; openfile->current != NULL;
openfile->current = openfile->current->prev) {
while (!begin_line) {
char_mb_len = parse_mbchar(openfile->current->data +
openfile->current_x, char_mb, NULL);
if (is_word_mbchar(char_mb, allow_punct))
break;
if (openfile->current_x == 0)
begin_line = TRUE;
else
openfile->current_x =
move_mbleft(openfile->current->data,
openfile->current_x);
}
if (!begin_line)
break;
if (openfile->current != openfile->fileage) {
begin_line = FALSE;
openfile->current_x = strlen(openfile->current->prev->data);
}
}
if (openfile->current == NULL)
openfile->current = openfile->fileage;
else if (!begin_line) {
if (openfile->current_x == 0)
begin_line = TRUE;
else
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
while (!begin_line) {
char_mb_len = parse_mbchar(openfile->current->data +
openfile->current_x, char_mb, NULL);
if (!is_word_mbchar(char_mb, allow_punct))
break;
if (openfile->current_x == 0)
begin_line = TRUE;
else
openfile->current_x =
move_mbleft(openfile->current->data,
openfile->current_x);
}
if (!begin_line)
openfile->current_x += char_mb_len;
}
free(char_mb);
openfile->placewewant = xplustabs();
if (allow_update)
edit_redraw(current_save, pww_save);
return started_on_word;
}
void do_prev_word_void(void)
{
do_prev_word(ISSET(WORD_BOUNDS), TRUE);
}
#endif
void do_home(void)
{
size_t pww_save = openfile->placewewant;
#ifndef NANO_TINY
if (ISSET(SMART_HOME)) {
size_t current_x_save = openfile->current_x;
openfile->current_x = indent_length(openfile->current->data);
if (openfile->current_x == current_x_save ||
openfile->current->data[openfile->current_x] == '\0')
openfile->current_x = 0;
openfile->placewewant = xplustabs();
} else {
#endif
openfile->current_x = 0;
openfile->placewewant = 0;
#ifndef NANO_TINY
}
#endif
if (need_horizontal_update(pww_save))
update_line(openfile->current, openfile->current_x);
}
void do_end(void)
{
size_t pww_save = openfile->placewewant;
openfile->current_x = strlen(openfile->current->data);
openfile->placewewant = xplustabs();
if (need_horizontal_update(pww_save))
update_line(openfile->current, openfile->current_x);
}
void do_up(
#ifndef NANO_TINY
bool scroll_only
#else
void
#endif
)
{
if (openfile->current == openfile->fileage
#ifndef NANO_TINY
|| (scroll_only && openfile->edittop == openfile->fileage)
#endif
)
return;
assert(openfile->current_y == openfile->current->lineno - openfile->edittop->lineno);
openfile->current = openfile->current->prev;
openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant);
if (openfile->current_y == 0
#ifndef NANO_TINY
|| scroll_only
#endif
)
edit_scroll(UP_DIR,
#ifndef NANO_TINY
(ISSET(SMOOTH_SCROLL) || scroll_only) ? 1 :
#endif
editwinrows / 2);
if (openfile->current_y > 0) {
if (need_vertical_update(0))
update_line(openfile->current->next, 0);
update_line(openfile->current, openfile->current_x);
}
}
void do_up_void(void)
{
do_up(
#ifndef NANO_TINY
FALSE
#endif
);
}
#ifndef NANO_TINY
void do_scroll_up(void)
{
do_up(TRUE);
}
#endif
void do_down(
#ifndef NANO_TINY
bool scroll_only
#else
void
#endif
)
{
if (openfile->current == openfile->filebot)
return;
assert(openfile->current_y == openfile->current->lineno - openfile->edittop->lineno);
openfile->current = openfile->current->next;
openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant);
if (openfile->current_y == editwinrows - 1
#ifndef NANO_TINY
|| scroll_only
#endif
)
edit_scroll(DOWN_DIR,
#ifndef NANO_TINY
(ISSET(SMOOTH_SCROLL) || scroll_only) ? 1 :
#endif
editwinrows / 2);
if (openfile->current_y < editwinrows - 1) {
if (need_vertical_update(0))
update_line(openfile->current->prev, 0);
update_line(openfile->current, openfile->current_x);
}
}
void do_down_void(void)
{
do_down(
#ifndef NANO_TINY
FALSE
#endif
);
}
#ifndef NANO_TINY
void do_scroll_down(void)
{
do_down(TRUE);
}
#endif
void do_left(void)
{
size_t pww_save = openfile->placewewant;
if (openfile->current_x > 0)
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
else if (openfile->current != openfile->fileage) {
do_up_void();
openfile->current_x = strlen(openfile->current->data);
}
openfile->placewewant = xplustabs();
if (need_horizontal_update(pww_save))
update_line(openfile->current, openfile->current_x);
}
void do_right(void)
{
size_t pww_save = openfile->placewewant;
assert(openfile->current_x <= strlen(openfile->current->data));
if (openfile->current->data[openfile->current_x] != '\0')
openfile->current_x = move_mbright(openfile->current->data,
openfile->current_x);
else if (openfile->current != openfile->filebot) {
do_down_void();
openfile->current_x = 0;
}
openfile->placewewant = xplustabs();
if (need_horizontal_update(pww_save))
update_line(openfile->current, openfile->current_x);
}