Use formatParse split to position input cursor

master
Curtis McEnroe 2018-09-12 22:55:02 -04:00
parent 872608e5c4
commit b36a134702
No known key found for this signature in database
GPG Key ID: CEA2F97ADCFCD77C
4 changed files with 41 additions and 39 deletions

11
chat.h
View File

@ -86,15 +86,12 @@ enum {
struct Format { struct Format {
const wchar_t *str; const wchar_t *str;
size_t len; size_t len;
bool bold; bool split;
bool italic; bool bold, italic, underline, reverse;
bool underline; int fg, bg;
bool reverse;
int fg;
int bg;
}; };
void formatReset(struct Format *format); void formatReset(struct Format *format);
bool formatParse(struct Format *format, const wchar_t *stop); bool formatParse(struct Format *format, const wchar_t *split);
void handle(char *line); void handle(char *line);
void input(struct Tag tag, char *line); void input(struct Tag tag, char *line);

9
edit.c
View File

@ -33,17 +33,10 @@ static struct {
.end = line.buf, .end = line.buf,
}; };
// XXX: editTail must always be called after editHead.
static wchar_t tail;
const wchar_t *editHead(void) { const wchar_t *editHead(void) {
tail = *line.ptr;
*line.ptr = L'\0';
return line.buf; return line.buf;
} }
const wchar_t *editTail(void) { const wchar_t *editTail(void) {
if (tail) *line.ptr = tail;
*line.end = L'\0';
tail = L'\0';
return line.ptr; return line.ptr;
} }
@ -186,4 +179,6 @@ void edit(struct Tag tag, enum Edit op, wchar_t ch) {
break; case EditEnter: accept(); enter(tag); break; case EditEnter: accept(); enter(tag);
} }
*line.end = L'\0';
} }

View File

@ -64,10 +64,11 @@ static const wchar_t Stops[] = {
L'\0', L'\0',
}; };
bool formatParse(struct Format *format, const wchar_t *stop) { bool formatParse(struct Format *format, const wchar_t *split) {
format->str += format->len; format->str += format->len;
if (!format->str[0]) return false; if (!format->str[0]) return false;
const wchar_t *init = format->str;
switch (format->str[0]) { switch (format->str[0]) {
break; case IRCBold: format->str++; format->bold ^= true; break; case IRCBold: format->str++; format->bold ^= true;
break; case IRCItalic: format->str++; format->italic ^= true; break; case IRCItalic: format->str++; format->italic ^= true;
@ -76,14 +77,15 @@ bool formatParse(struct Format *format, const wchar_t *stop) {
break; case IRCColor: format->str++; parseColor(format); break; case IRCColor: format->str++; parseColor(format);
break; case IRCReset: format->str++; formatReset(format); break; case IRCReset: format->str++; formatReset(format);
} }
format->split = (split >= init && split <= format->str);
if (format->str[0] == L' ') { if (format->str[0] == L' ') {
format->len = 1 + wcscspn(&format->str[1], Stops); format->len = 1 + wcscspn(&format->str[1], Stops);
} else { } else {
format->len = wcscspn(format->str, Stops); format->len = wcscspn(format->str, Stops);
} }
if (stop && stop > format->str && stop < &format->str[format->len]) { if (split > format->str && split < &format->str[format->len]) {
format->len = stop - format->str; format->len = split - format->str;
} }
return true; return true;
} }

50
ui.c
View File

@ -239,10 +239,25 @@ static const short IRCColors[] = {
[IRCLightGray] = 0 + COLOR_WHITE, [IRCLightGray] = 0 + COLOR_WHITE,
}; };
static int addIRC(WINDOW *win, const wchar_t *str) { static void addFormat(WINDOW *win, const struct Format *format) {
int lines = 0; attr_t attr = A_NORMAL;
if (format->bold) attr |= A_BOLD;
if (format->italic) attr |= A_ITALIC;
if (format->underline) attr |= A_UNDERLINE;
if (format->reverse) attr |= A_REVERSE;
short pair = -1;
if (format->fg >= 0) pair = IRCColors[format->fg];
if (format->bg >= 0) pair |= IRCColors[format->bg] << 4;
wattr_set(win, attr | attr8(pair), 1 + pair8(pair), NULL);
waddnwstr(win, format->str, format->len);
}
static int addWrap(WINDOW *win, const wchar_t *str) {
struct Format format = { .str = str }; struct Format format = { .str = str };
formatReset(&format); formatReset(&format);
int lines = 0;
while (formatParse(&format, NULL)) { while (formatParse(&format, NULL)) {
int _, x, xMax; int _, x, xMax;
getyx(win, _, x); getyx(win, _, x);
@ -255,19 +270,7 @@ static int addIRC(WINDOW *win, const wchar_t *str) {
waddch(win, '\n'); waddch(win, '\n');
lines++; lines++;
} }
addFormat(win, &format);
attr_t attr = A_NORMAL;
if (format.bold) attr |= A_BOLD;
if (format.italic) attr |= A_ITALIC;
if (format.underline) attr |= A_UNDERLINE;
if (format.reverse) attr |= A_REVERSE;
short pair = -1;
if (format.fg >= 0) pair = IRCColors[format.fg];
if (format.bg >= 0) pair |= IRCColors[format.bg] << 4;
wattr_set(win, attr | attr8(pair), 1 + pair8(pair), NULL);
waddnwstr(win, format.str, format.len);
} }
return lines; return lines;
} }
@ -293,7 +296,7 @@ static void uiStatus(void) {
if (len < 0) err(EX_OSERR, "aswprintf"); if (len < 0) err(EX_OSERR, "aswprintf");
if (view->unread == 1) str[unread] = L'\0'; if (view->unread == 1) str[unread] = L'\0';
addIRC(ui.status, count ? str : &str[1]); addWrap(ui.status, count ? str : &str[1]);
free(str); free(str);
count++; count++;
} }
@ -360,7 +363,7 @@ void uiTopic(struct Tag tag, const char *topic) {
wchar_t *wcs = ambstowcs(topic); wchar_t *wcs = ambstowcs(topic);
if (!wcs) err(EX_DATAERR, "ambstowcs"); if (!wcs) err(EX_DATAERR, "ambstowcs");
wmove(view->topic, 0, 0); wmove(view->topic, 0, 0);
addIRC(view->topic, wcs); addWrap(view->topic, wcs);
wclrtoeol(view->topic); wclrtoeol(view->topic);
free(wcs); free(wcs);
} }
@ -380,7 +383,7 @@ void uiLog(struct Tag tag, enum UIHeat heat, const wchar_t *line) {
} }
uiStatus(); uiStatus();
} }
lines += addIRC(view->log, line); lines += addWrap(view->log, line);
if (view->scroll != LogLines) view->scroll -= lines; if (view->scroll != LogLines) view->scroll -= lines;
} }
@ -545,9 +548,14 @@ void uiRead(void) {
int y, x; int y, x;
wmove(ui.input, 0, 0); wmove(ui.input, 0, 0);
addIRC(ui.input, editHead());
getyx(ui.input, y, x); struct Format format = { .str = editHead() };
addIRC(ui.input, editTail()); formatReset(&format);
while (formatParse(&format, editTail())) {
if (format.split) getyx(ui.input, y, x);
addFormat(ui.input, &format);
}
wclrtoeol(ui.input); wclrtoeol(ui.input);
wmove(ui.input, y, x); wmove(ui.input, y, x);
} }