struct logbuf *b;
unsigned int o;
};
+struct log;
#define DOC_DATA_TYPE struct log
+#define DOC_NEXT log_next
+#define DOC_PREV log_prev
#include "core.h"
#include "internal.h"
return 1;
}
-static int log_step(struct pane *home safe, struct mark *mark safe, int num, int num2)
+static inline wint_t log_next(struct log *log safe, struct doc_ref *r safe, bool bytes)
{
- struct log *log = &home->doc_data;
- struct mark *m = mark;
- bool forward = num;
- bool move = num2;
- struct doc_ref ref;
wint_t ret;
- ref = m->ref;
- if (forward) {
- if (!ref.b)
- ret = WEOF;
- else {
- const char *s = &ref.b->text[ref.o];
-
- ret = get_utf8(&s, ref.b->text + ref.b->end);
- ref.o = s - ref.b->text;
- if (ref.o >= ref.b->end) {
- if (ref.b == list_last_entry(&log->log,
- struct logbuf, h))
- ref.b = NULL;
- else
- ref.b = list_next_entry(ref.b, h);
- ref.o = 0;
- }
- }
- } else {
- if (list_empty(&log->log))
- ret = WEOF;
- else if (!ref.b) {
- ref.b = list_last_entry(&log->log, struct logbuf, h);
- ref.o = utf8_round_len(ref.b->text, ref.b->end - 1);
- } else if (ref.o == 0) {
- if (ref.b != list_first_entry(&log->log,
- struct logbuf, h)) {
- ref.b = list_prev_entry(ref.b, h);
- ref.o = utf8_round_len(ref.b->text,
- ref.b->end - 1);
- } else
- ret = WEOF;
- } else
- ref.o = utf8_round_len(ref.b->text, ref.o - 1);
- if ((ref.b != m->ref.b || ref.o != m->ref.o) && ref.b) {
- const char *s = ref.b->text + ref.o;
- ret = get_utf8(&s, ref.b->text + ref.b->end);
+ if (!r->b)
+ ret = WEOF;
+ else {
+ const char *s = &r->b->text[r->o];
+
+ if (bytes)
+ ret = *s++;
+ else
+ ret = get_utf8(&s, r->b->text + r->b->end);
+ r->o = s - r->b->text;
+ if (r->o >= r->b->end) {
+ if (r->b == list_last_entry(&log->log,
+ struct logbuf, h))
+ r->b = NULL;
+ else
+ r->b = list_next_entry(r->b, h);
+ r->o = 0;
}
}
- if (move) {
- mark_step(m, forward);
- m->ref = ref;
+ return ret;
+}
+
+static inline wint_t log_prev(struct log *log safe, struct doc_ref *r safe, bool bytes)
+{
+ const char *s;
+
+ if (list_empty(&log->log))
+ return WEOF;
+ else if (!r->b) {
+ r->b = list_last_entry(&log->log, struct logbuf, h);
+ r->o = r->b->end;
+ } else if (r->o == 0) {
+ if (r->b != list_first_entry(&log->log,
+ struct logbuf, h)) {
+ r->b = list_prev_entry(r->b, h);
+ r->o = r->b->end;
+ } else
+ return WEOF;
}
- return CHAR_RET(ret);
+ if (bytes)
+ r->o -= 1;
+ else
+ r->o = utf8_round_len(r->b->text, r->o - 1);
+ s = r->b->text + r->o;
+ if (bytes)
+ return *s;
+ else
+ return get_utf8(&s, r->b->text + r->b->end);
}
DEF_CMD(log_char)
{
- struct mark *m = ci->mark;
- struct mark *end = ci->mark2;
- int steps = ci->num;
- int forward = steps > 0;
- int ret = Einval;
-
- if (!m)
- return Enoarg;
- if (end && mark_same(m, end))
- return 1;
- if (end && (end->seq < m->seq) != (steps < 0))
- /* Can never cross 'end' */
- return Einval;
- while (steps && ret != CHAR_RET(WEOF) && (!end || !mark_same(m, end))) {
- ret = log_step(ci->home, m, forward, 1);
- steps -= forward*2 - 1;
- }
- if (end)
- return 1 + (forward ? ci->num - steps : steps - ci->num);
- if (ret == CHAR_RET(WEOF) || ci->num2 == 0)
- return ret;
- if (ci->num && (ci->num2 < 0) == forward)
- return ret;
- /* Want the 'next' char */
- return log_step(ci->home, m, ci->num2 > 0, 0);
+ return do_char_byte(ci);
}
DEF_CMD(log_val_marks)
}
return ret;
}
+
+#if defined(PRIVATE_DOC_REF) && defined(DOC_DATA_TYPE) && defined(DOC_NEXT)
+static inline wint_t DOC_NEXT(DOC_DATA_TYPE *doc safe, struct doc_ref *r safe, bool byte);
+static inline wint_t DOC_PREV(DOC_DATA_TYPE *doc safe, struct doc_ref *r safe, bool byte);
+static inline int do_char_byte(const struct cmd_info *ci safe)
+{
+ struct mark *m = ci->mark;
+ struct mark *end = ci->mark2;
+ DOC_DATA_TYPE *doc = &ci->home->doc_data;
+ struct doc_ref r;
+ int steps = ci->num;
+ int forward = steps > 0;
+ wint_t ret = ' ';
+ int byte = strcmp(ci->key, "doc:byte") == 0;
+
+ if (!m)
+ return Enoarg;
+ if (end && mark_same(m, end))
+ return 1;
+ if (end && (end->seq < m->seq) != (steps < 0))
+ /* Can never cross 'end' */
+ return Einval;
+ while (steps && ret != CHAR_RET(WEOF) && (!end || !mark_same(m, end))) {
+ #ifdef DOC_SHARESREF
+ mark_step_sharesref(m, forward);
+ #else
+ mark_step(m, forward);
+ #endif
+ if (forward)
+ ret = DOC_NEXT(doc, &m->ref, byte);
+ else
+ ret = DOC_PREV(doc, &m->ref, byte);
+ steps -= forward*2 - 1;
+ }
+ if (end)
+ return 1 + (forward ? ci->num - steps : steps - ci->num);
+ if (ret == WEOF || ci->num2 == 0)
+ return CHAR_RET(ret);
+ if (ci->num && (ci->num2 < 0) == forward)
+ return CHAR_RET(ret);
+ /* Want the 'next' char */
+ r = m->ref;
+ if (ci->num2 > 0)
+ ret = DOC_NEXT(doc, &r, byte);
+ else
+ ret = DOC_PREV(doc, &r, byte);
+ return CHAR_RET(ret);
+}
+#endif
struct dir_ent *d;
unsigned int ignore;
};
-
+#define DOC_SHARESREF
#define DOC_DATA_TYPE struct directory
+struct directory;
+#define DOC_NEXT dir_next
+#define DOC_PREV dir_prev
#include "core.h"
struct dir_ent {
return 1;
}
-static int dir_step(struct pane *home safe, struct mark *mark safe,
- int num, int num2)
+static inline wint_t dir_next(struct directory *dr safe, struct doc_ref *r safe, bool bytes)
{
- struct mark *m = mark;
- bool forward = num;
- bool move = num2;
- struct directory *dr = &home->doc_data;
- struct dir_ent *d;
- wint_t ret = '\n';
+ struct dir_ent *d = r->d;
- if (!mark_valid(mark))
- /* FIXME this might be needed after deleting lots
- * of dir entries, and refreshing.
- */
+ if (d == NULL)
return WEOF;
- d = m->ref.d;
- if (forward) {
- if (d == NULL)
- ret = WEOF;
- else {
- if (d == list_last_entry(&dr->ents,
- struct dir_ent, lst))
- d = NULL;
- else
- d = list_next_entry(d, lst);
- }
- } else {
- if (d == list_first_entry(&dr->ents, struct dir_ent, lst))
+ else {
+ if (d == list_last_entry(&dr->ents,
+ struct dir_ent, lst))
d = NULL;
- else if (d == NULL)
- d = list_last_entry(&dr->ents, struct dir_ent, lst);
else
- d = list_prev_entry(d, lst);
- if (!d) {
- ret = WEOF;
- d = m->ref.d;
- }
- }
- if (move) {
- mark_step_sharesref(m, forward);
- m->ref.d = d;
+ d = list_next_entry(d, lst);
}
- /* return value must be +ve, so use high bits to ensure this. */
- return CHAR_RET(ret);
+ r->d = d;
+ return '\n';
}
-DEF_CMD(dir_char)
+static inline wint_t dir_prev(struct directory *dr safe, struct doc_ref *r safe, bool bytes)
{
- struct mark *m = ci->mark;
- struct mark *end = ci->mark2;
- int steps = ci->num;
- int forward = steps > 0;
- int ret = Einval;
+ struct dir_ent *d = r->d;
- if (!m)
- return Enoarg;
- if (end && mark_same(m, end))
- return 1;
- if (end && (end->seq < m->seq) != (steps < 0))
- /* Can never cross 'end' */
- return Einval;
- while (steps && ret != CHAR_RET(WEOF) && (!end || !mark_same(m, end))) {
- ret = dir_step(ci->home, m, forward, 1);
- steps -= forward*2 - 1;
- }
- if (end)
- return 1 + (forward ? ci->num - steps : steps - ci->num);
- if (ret == CHAR_RET(WEOF) || ci->num2 == 0)
- return ret;
- if (ci->num && (ci->num2 < 0) == forward)
- return ret;
- /* Want the 'next' char */
- return dir_step(ci->home, m, ci->num2 > 0, 0);
+ if (d == list_first_entry(&dr->ents, struct dir_ent, lst))
+ d = NULL;
+ else if (d == NULL)
+ d = list_last_entry(&dr->ents, struct dir_ent, lst);
+ else
+ d = list_prev_entry(d, lst);
+ if (!d)
+ return WEOF;
+
+ r->d = d;
+ return '\n';
+}
+
+DEF_CMD(dir_char)
+{
+ return do_char_byte(ci);
}
DEF_CMD(dir_set_ref)
unsigned int i;
};
+#define DOC_SHARESREF
#define DOC_DATA_TYPE struct list
+struct list;
+#define DOC_NEXT list_next
+#define DOC_PREV list_prev
#include "core.h"
#include "misc.h"
};
#include "core-pane.h"
-DEF_CMD(list_char)
+static inline wint_t list_next(struct list *l safe, struct doc_ref *r safe, bool bytes)
{
- struct list *l = &ci->home->doc_data;
- struct mark *m = ci->mark;
- struct mark *end = ci->mark2;
- int steps = ci->num;
- int forward = steps > 0;
- int ret = Einval;
+ if (r->p == NULL)
+ return WEOF;
- if (!m)
- return Enoarg;
+ if (r->p == list_last_entry(&l->content, struct elmnt, list))
+ r->p = NULL;
+ else
+ r->p = list_next_entry(r->p, list);
+ return ' ';
+}
- if (end && mark_same(m, end))
- return 1;
- if (end && (end->seq < m->seq) != (steps < 0))
- /* Can never cross 'end' */
- return Einval;
- while (steps && ret != CHAR_RET(WEOF) &&
- (!end || !mark_same(m, end))) {
- if (forward) {
- if (m->ref.p == NULL)
- ret = CHAR_RET(WEOF);
- else {
- ret = CHAR_RET(' ');
- mark_step_sharesref(m, 1);
- if (m->ref.p == list_last_entry(&l->content, struct elmnt, list))
- m->ref.p = NULL;
- else
- m->ref.p = list_next_entry(m->ref.p, list);
- steps -= 1;
- }
- } else {
- if (m->ref.p == list_first_entry_or_null(&l->content, struct elmnt, list))
- ret = CHAR_RET(WEOF);
- else {
- ret = CHAR_RET(' ');
- mark_step_sharesref(m, 0);
- if (m->ref.p == NULL)
- m->ref.p = list_last_entry(&l->content, struct elmnt, list);
- else
- m->ref.p = list_prev_entry(m->ref.p, list);
- steps += 1;
- }
- }
- }
- if (end)
- return 1 + (forward ? ci->num - steps : steps - ci->num);
- if (ret == CHAR_RET(WEOF) || ci->num2 == 0)
- return ret;
- if (ci->num && (ci->num2 < 0) == forward)
- return ret;
- /* Want the 'next' char */
- if (ci->num2 > 0 && m->ref.p == NULL)
- return CHAR_RET(WEOF);
- if (ci->num2 < 0 && m->ref.p ==
- list_first_entry_or_null(&l->content, struct elmnt, list))
- return CHAR_RET(WEOF);
- return CHAR_RET(' ');
+static inline wint_t list_prev(struct list *l safe, struct doc_ref *r safe, bool bytes)
+{
+ if (r->p == list_first_entry_or_null(&l->content, struct elmnt, list))
+ return WEOF;
+
+ if (r->p == NULL)
+ r->p = list_last_entry(&l->content, struct elmnt, list);
+ else
+ r->p = list_prev_entry(r->p, list);
+ return ' ';
+}
+
+DEF_CMD(list_char)
+{
+ return do_char_byte(ci);
}
DEF_CMD(list_set_ref)
struct text_chunk *c;
unsigned int o;
};
+struct text;
#define DOC_DATA_TYPE struct text
+#define DOC_NEXT text_next
+#define DOC_PREV text_prev
#include "core.h"
#include "misc.h"
;
}
-static wint_t text_next(struct text *t safe, struct doc_ref *r safe, bool bytes)
+static inline wint_t text_next(struct text *t safe, struct doc_ref *r safe, bool bytes)
{
wint_t ret = WERR;
const char *c;
return ret;
}
-static wint_t text_prev(struct text *t safe, struct doc_ref *r safe, bool bytes)
+static inline wint_t text_prev(struct text *t safe, struct doc_ref *r safe, bool bytes)
{
wint_t ret;
const char *c;
return ret;
}
-static int text_step(struct pane *home safe, struct mark *mark safe,
- int num, int num2)
+DEF_CMD(text_char_byte)
{
- struct mark *m = mark;
- bool forward = num;
- bool move = num2;
- struct text *t = &home->doc_data;
- struct doc_ref r;
- wint_t ret;
-
- ASSERT(m->owner == home);
-
- r = m->ref;
- if (forward)
- ret = text_next(t, &r, 0);
- else
- ret = text_prev(t, &r, 0);
-
- if (move) {
- mark_step(m, forward);
- m->ref = r;
- }
- /* return value must be +ve, so use high bits to ensure this. */
- return CHAR_RET(ret);
+ return do_char_byte(ci);
}
-
-DEF_CMD(text_char)
-{
- struct mark *m = ci->mark;
- struct mark *end = ci->mark2;
- int steps = ci->num;
- int forward = steps > 0;
- int ret = Einval;
-
- if (!m)
- return Enoarg;
- if (end && mark_same(m, end))
- return 1;
- if (end && (end->seq < m->seq) != (steps < 0))
- /* Can never cross 'end' */
- return Einval;
- while (steps && ret != CHAR_RET(WEOF) && (!end || !mark_same(m, end))) {
- ret = text_step(ci->home, m, forward, 1);
- steps -= forward*2 - 1;
- }
- if (end)
- return 1 + (forward ? ci->num - steps : steps - ci->num);
- if (ret == CHAR_RET(WEOF) || ci->num2 == 0)
- return ret;
- if (ci->num && (ci->num2 < 0) == forward)
- return ret;
- /* Want the 'next' char */
- return text_step(ci->home, m, ci->num2 > 0, 0);
-}
-
-static int text_step_bytes(struct pane *home safe, struct mark *mark safe,
- int num, int num2)
-{
- struct mark *m = mark;
- bool forward = num;
- bool move = num2;
- struct text *t = &home->doc_data;
- struct doc_ref r;
- wint_t ret;
-
- if (!m)
- return Enoarg;
-
- ASSERT(m->owner == home);
-
- r = m->ref;
- if (forward)
- ret = text_next(t, &r, 1);
- else
- ret = text_prev(t, &r, 1);
-
- if (move) {
- mark_step(m, forward);
- m->ref = r;
- }
- /* return value must be +ve, so use high bits to ensure this. */
- return CHAR_RET(ret);
-}
-
-DEF_CMD(text_byte)
-{
- struct mark *m = ci->mark;
- struct mark *end = ci->mark2;
- int steps = ci->num;
- int forward = steps > 0;
- int ret = Einval;
-
- if (!m)
- return Enoarg;
- if (end && mark_same(m, end))
- return 1;
- if (end && (end->seq < m->seq) != (steps < 0))
- /* Can never cross 'end' */
- return Einval;
- while (steps && ret != CHAR_RET(WEOF) && (!end || !mark_same(m, end))) {
- ret = text_step_bytes(ci->home, m, forward, 1);
- steps -= forward*2 - 1;
- }
- if (end)
- return 1 + (forward ? ci->num - steps : steps - ci->num);
- if (ret == CHAR_RET(WEOF) || ci->num2 == 0)
- return ret;
- if (ci->num && (ci->num2 < 0) == forward)
- return ret;
- /* Want the 'next' char */
- return text_step_bytes(ci->home, m, ci->num2 > 0, 0);
-}
-
static bool _text_ref_same(struct text *t safe, struct doc_ref *r1 safe,
struct doc_ref *r2 safe)
{
key_add(text_map, "doc:set-attr", &text_set_attr);
key_add(text_map, "doc:get-attr", &text_doc_get_attr);
key_add(text_map, "doc:replace", &text_replace);
- key_add(text_map, "doc:char", &text_char);
- key_add(text_map, "doc:byte", &text_byte);
+ key_add(text_map, "doc:char", &text_char_byte);
+ key_add(text_map, "doc:byte", &text_char_byte);
key_add(text_map, "doc:modified", &text_modified);
key_add(text_map, "doc:set:readonly", &text_readonly);
key_add(text_map, "doc:notify:doc:revisit", &text_revisited);