"render-lines" also understands that there is a need to map between
location in the document and locations on the display.
-"doc:render-line" can be asked to only convert up to some location into
-a string, rather than the whole line. This can be used to determine
-where in the markup the cursor should appear.
+"doc:render-line" can be asked to track when conversion reaches some
+mark, and to report the offset in the rendered string corresponding to
+this point. This can be used to determine where in the markup the
+cursor should appear.
As "render-lines" collects these marked-up strings, it creates sub-panes
using "renderline" as described below to draw the marked-up string onto
- "doc:render-line"
+ mark - start of the line to be rendered. Line continues until
first '\n' or until 'num2' chars have been examined and no '\n'
- found. 'mark' will be mvoe to the end of the range that was
+ found. 'mark' will be moved to the end of the range that was
rendered (often to the end of line line / start of next line).
- + mark2 - if num == -1, location not to render beyond. This is
- typically set to the current "point", and the cursor will be
- drawn where the returned string ends.
+ + mark2 - location of interested to be reported as offset in the
+ rendering. This is typically set to the current "point", and the
+ cursor will be drawn where the returned string ends.
+ num - if >= 0, maximum number of result character to return
before aborting. 'mark' will be moved to the location that would
draw at or beyond this place on the screen. This can be used to
convert a screen location (from a mouse click) back to a document
location.
- If num == -1, rendering stops when mark reaches mark2. This
- allows the cursor to be found, and action to be taken if it is
- off-screen.
- If num == NO_NUMERIC rendering continues to end-of-line.
- + comm2 - a callback used to return the rendered string in "str1".
+ If num < 0 rendering continues to end-of-line.
+ + comm2 - a callback used to return the rendered string in "str1",
+ and the offset of mark2 (if given) in "num".
The string will be freed after the callback returns, so it must
be duplicated if later access is needed.
or until 'num2' chars have been examined with no '\n' found
mark will be moved to the end of the range that was rendered (often
the end of the line)
- mark2: if num==-1, location not to render beyond. This is typically set
+ mark2: location or record and report offset of. This is typically set
to the current "point", and a cursor will be drawn where the returned
string end.
num: if >= 0, max number of result characters to return before
at or beyond this place on the screen. This can be used to
convert a screen location (from a mouse click) back to a document
location.
- if == -1, Rendering stops when mark reaches mark2. This allows the
- cursor to be found, and action to be taken if it is off-screen
- if == NO_NUMERIC, ignored.
+ if < 0, ignored.
comm2: a callback used to return the rendered string in "str". The string
will be freed after the callback returns, so it must duplicate it if
later access is needed.
return Enoarg;
m = mark_dup(ci->mark);
call("doc:EOL", ci->home->parent, 1, m, NULL, 1);
+ /* Passing '0' is deliberate. We don't want to render
+ * anything, just see if there is anything tha could be rendered.
+ */
if (call("doc:render-line", ci->focus, 0, m) < 0 ||
m->ref.p == NULL) {
mark_free(m);
char *path safe);
static bool cond_append(struct buf *b safe, char *txt safe, char *tag safe,
- int offset, int *cp safe)
+ int offset, int *pos safe)
{
char *tagf = "active-tag:email-";
int prelen = 1 + strlen(tagf) + strlen(tag) + 1 + 1;
int postlen = 1 + 3;
int len = prelen + strlen(txt) + postlen;
- if (offset != NO_NUMERIC && offset >= 0 && offset <= b->len + len)
+ if (offset >= 0 && offset <= b->len + len)
return False;
buf_concat(b, "<");
buf_concat(b, tagf);
buf_concat(b, tag);
buf_concat(b, ">[");
- if (*cp == 0)
- return False;
- if (*cp > 0)
- *cp -= 1;
+ *pos = b->len;
buf_concat(b, txt);
buf_concat(b, "]</>");
return True;
struct mark *pm = ci->mark2;
int o = ci->num;
int cp = -1;
+ int ret_pos = 0;
char *attr;
int ret;
bool ok = True;
attr = "hide";
while (ok && attr && *attr) {
+ int pos = 0;
char *a = strchr(attr, ':');
if (a)
*a = 0;
if (is_attr("hide", attr))
ok = cond_append(&b, visible ? "HIDE" : "SHOW", attr,
- o, &cp);
+ o, &pos);
else if (is_attr("full", attr))
ok = cond_append(&b, orig ? "BRIEF" : "FULL", attr,
- o, &cp);
+ o, &pos);
else if (is_attr("extras", attr))
ok = cond_append(&b, extras ? "-" : "EXTRAS", attr,
- o, &cp);
+ o, &pos);
else
- ok = cond_append(&b, attr, attr, o, &cp);
+ ok = cond_append(&b, attr, attr, o, &pos);
if (ok)
doc_next(ci->focus, m);
+ if (cp >= 0) {
+ cp -= 1;
+ ret_pos = pos;
+ }
attr = a;
if (attr)
*attr++ = ':';
* if cp > 0, we haven't reached cursor yet, so don't stop
* if cp == 0, this is cursor pos, so stop.
*/
- if (ok && cp != 0 && ((o < 0 || o == NO_NUMERIC))) {
+ if (ok && o < 0) {
wint_t wch;
buf_concat(&b, "</>");
attr = pane_mark_attr(ci->focus, m,
buf_concat(&b, " file=");
buf_concat(&b, attr);
}
+ if (cp >= 0)
+ ret_pos = b.len;
buf_concat(&b, "\n");
+ if (cp >= 1)
+ ret_pos = b.len;
while ((wch = doc_next(ci->focus, m)) &&
wch != '\n' && wch != WEOF)
;
}
- ret = comm_call(ci->comm2, "callback:render", ci->focus, 0, NULL,
+ ret = comm_call(ci->comm2, "callback:render", ci->focus, ret_pos, NULL,
buf_final(&b));
free(b.b);
return ret;
char *c = NULL;
int p;
int ret;
+ int retlen = 0;
int i;
struct xy scale;
struct mark *point = ci->mark2;
c[max_chars] = '\0';
for (i = 0; i < 9 ; i++) {
- if (point && mark_ordered_or_same(point, ci->mark)) {
- c[map_start + i] = 0;
- break;
- }
+ if (point && mark_ordered_or_same(point, ci->mark))
+ retlen = map_start + i;
if (max_chars >= 0 && map_start + i >= max_chars)
break;
doc_next(ci->focus, ci->mark);
}
ret = comm_call(ci->comm2, "callback:render", ci->focus,
- 0, NULL, c);
+ retlen, NULL, c);
free(c);
return ret;
}
struct filter_data *fd;
int keep, cmp;
const char *str;
+ int cursor_offset;
};
DEF_CB(rlcb)
/* Want the original with markup */
strcpy(c, ci->str);
cb->str = c;
+ cb->cursor_offset = ci->num;
} else
free(c);
return 1;
ci->num, ci->mark, NULL, 0, m2) < 0)
return Efail;
- ret = comm_call(ci->comm2, "callback:render", ci->focus, 0, NULL, cb.str);
+ ret = comm_call(ci->comm2, "callback:render", ci->focus,
+ cb.cursor_offset, NULL, cb.str);
free((void*)cb.str);
- if (ci->num != NO_NUMERIC)
+ if (m2)
/* Was rendering to find a cursor, don't need to skip */
return ret;
/* Need to continue over other non-matching lines */
mark_to_mark(end, m);
}
- if (call("doc:render-line", ci->focus, NO_NUMERIC, end) > 0)
+ if (call("doc:render-line", ci->focus, -1, end) > 0)
found_one = True;
m = mark_dup(end);
struct call_return cr;
cr.c = eol_cb;
if (home_call(ci->home, "doc:render-line",
- ci->focus, NO_NUMERIC, ci->mark, NULL,
+ ci->focus, -1, ci->mark, NULL,
0, NULL, NULL, 0,0, &cr.c) <= 0)
line = 1;
line -= 1;
struct mark *boundary, *start_boundary = NULL;
struct mark *doc_boundary;
int o = ci->num;
+ int pm_offset = -1;
wint_t ch;
int chars = 0;
int ret;
char *noret;
char *attr;
- if (o == NO_NUMERIC)
- o = -1;
-
ar.rtn = text_attr_callback;
ar.fwd = text_attr_forward;
ar.ast = ar.tmpst = NULL;
if (o >= 0 && b.len >= o)
break;
- if (pm && mark_same(m, pm))
- break;
+ if (pm && mark_same(m, pm) && pm_offset < 0)
+ pm_offset = b.len;
if (ar.ast && ar.min_end <= chars) {
int depth = find_finished(ar.ast, chars, &ar.min_end);
mark_free(doc_boundary);
- ret = comm_call(ci->comm2, "callback:render", focus, 0, NULL,
+ if (pm && pm_offset < 0)
+ pm_offset = b.len;
+
+ ret = comm_call(ci->comm2, "callback:render", focus, pm_offset, NULL,
buf_final(&b));
free(b.b);
free(ar.insert.b);
def markup_header(self, key, focus, num, mark, mark2, comm2, **a):
"handle:compose:markup-header"
- # Display cursor at start or end, anything else should be suppressed.
- if num == 0 or (mark2 and mark2 == mark):
- # appear at the start of the line
- return comm2("cb", focus, "<fg:red>")
# at least go to end of line
self.parent.call("doc:EOL", 1, mark)
m = self.vmark_at_or_before(self.view, mark)
info = m['compose-info']
if info:
markup += ' - ' + info
- if (num == edlib.NO_NUMERIC or num < 0) and (not mark2 or mark2 > mark):
+ if num < 0:
# normal render - go past eol
self.parent.next(mark)
markup += "</>\n"
- return comm2("cb", focus, markup)
+ # return num==0 to display cursor at start or end, anything else
+ # should be suppressed.
+ return comm2("cb", focus, 0, markup)
def handle_clone(self, key, focus, **a):
"handle:Clone"
return edlib.Efallthrough
mark.to_mark(p.next())
eol="\n"
- if mark2 or num > 0 and num < 2000:
+ if num > 0 and num < 2000:
# don't show eol
self.prev(mark)
eol = ""
if comm2:
- comm2("cb", focus, "<fg:yellow,bg:blue+30>%d quoted lines</>%s" % (int(p['quote-length']), eol))
+ comm2("cb", focus, 0, "<fg:yellow,bg:blue+30>%d quoted lines</>%s" % (int(p['quote-length']), eol))
return 1
def handle_render_line_prev(self, key, focus, num, mark, comm2, **a):
return Enoarg;
m = mark_dup(ci->mark);
- line = call_ret(str, ci->key, ci->home->parent, NO_NUMERIC, m);
+ line = call_ret(str, ci->key, ci->home->parent, -1, m);
if (!line) {
mark_free(m);
return Efail;
startlen = 0;
else
startlen = start - line;
- if (ci->num >= 0 && ci->num != NO_NUMERIC) {
+ if (ci->num >= 0) {
/* Only want 'num' bytes from start, with ->mark positioned.
* So need to find how many bytes of 'line' produce num bytes
* of highlighted line.
mark_free(m);
line = call_ret(str, ci->key, ci->home->parent,
num, ci->mark);
- } else if (ci->mark2) {
+ } else if (ci->mark2) { //FIXME
/* Only want up-to the cursor, which might be in the middle of
* the highlighted region. Now we know where that is, we can
* highlight whatever part is still visible.
/* Go to start of line */
home_call(ci->home, "doc:render-line-prev", ci->home, 0, ci->mark);
home_call(ci->home, "doc:render-line",
- ci->home, NO_NUMERIC, ci->mark, NULL, 0, NULL,
+ ci->home, -1, ci->mark, NULL, 0, NULL,
NULL, 0,0, &cr.c);
if (!cr.s)
return 1;
if (pm && !mark_same(pm, m))
pm = NULL;
- if (ci->num == NO_NUMERIC || ci->num < 0)
+ if (ci->num < 0)
len = -1;
else
len = ci->num;
ret = do_format(ci->focus, ci->mark, pm, len, 1);
- if (!pm && len < 0)
+ if (len < 0)
doc_next(ci->focus, m);
rv = comm_call(ci->comm2, "callback:render", ci->focus, 0, NULL, ret);
free(ret);
struct mark *m = NULL;
struct mark *pm = ci->mark2;
int pos;
+ int pm_offset = -1;
int i;
char buf[30];
int rv;
wint_t ch;
struct mark *m2 = ci->mark;
- if (pm && mark_same(m2, pm))
- goto done;
- if (ci->num >= 0 && ci->num != NO_NUMERIC &&
- ci->num <= ret.len)
+ if (pm && mark_same(m2, pm) && pm_offset < 0)
+ pm_offset = ret.len;
+ if (ci->num >= 0 && ci->num <= ret.len)
goto done;
ch = doc_next(ci->focus, m2);
done:
if (m)
mark_free(m);
- rv = comm_call(ci->comm2, "callback:render", ci->focus, 0, NULL,
+ rv = comm_call(ci->comm2, "callback:render", ci->focus, pm_offset, NULL,
buf_final(&ret));
free(ret.b);
return rv ?: 1;
* This takes a mark and moves it to the end of the rendered line
* so that another call will produce another line.
* "doc:render-line" must always return a full line including '\n'
- * unless the result would be bigger than the 'max' passed in ->num or,
- * when ->num==-1, unless the rendering would go beyond the location in
- * ->mark2. In these cases it can stop before a '\n'. In each case,
+ * unless the result would be bigger than the 'max' passed in ->num or
+ * ->num < 0. In these cases it can stop before a '\n'. In each case,
* the mark is moved to the end of the region that was rendered;
- * This allows a mark to be found for a given character position, or a display
- * position found for a given mark.
+ * This allows a mark to be found for a given character position.
+ * If mark2 is given, the offset in the rendering when mark2 is reached
+ * is reported as ->num in the callback.
* For the standard 'render the whole line' functionality, ->num should
- * be NO_NUMERIC
+ * be negative.
*
* The document or filter must also provide "doc:render-line-prev" which
* moves mark to a start-of-line. If num is 0, then don't skip over any
}
s = "";
} else
- s = call_ret(strsave, "doc:render-line", p, NO_NUMERIC, m);
+ s = call_ret(strsave, "doc:render-line", p, -1, m);
if (!mark_valid(start)) {
mark_free(m);
return m;
}
-DEF_CMD(get_len)
+DEF_CMD(get_offset)
{
- if (ci->str) {
- int l = strlen(ci->str);
- while (l >=4 && strncmp(ci->str+l-3, "</>", 3) == 0 &&
- ci->str[l-4] != '<')
- l -= 3;
- return l + 1;
- } else
+ if (ci->num < 0)
return 1;
+ else
+ return ci->num + 1;
}
static int call_render_line_to_point(struct pane *p safe, struct mark *pm safe,
int len;
struct mark *m = mark_dup_view(start);
- len = call_comm("doc:render-line", p, &get_len, -1, m, NULL, 0, pm);
+ len = call_comm("doc:render-line", p, &get_offset, -1, m, NULL, 0, pm);
mark_free(m);
if (len <= 0)
return 0;