]> git.neil.brown.name Git - edlib.git/commitdiff
devel
authorNeilBrown <neil@brown.name>
Tue, 2 Feb 2016 02:47:49 +0000 (13:47 +1100)
committerNeilBrown <neil@brown.name>
Tue, 2 Feb 2016 02:47:49 +0000 (13:47 +1100)
core-doc.c
doc-text.c
edlib.c
lib-messageline.c
mode-emacs.c
python/display-pygtk.py
python/render-present.py
render-lines.c

index 5b0461761408cdd5f66b5c00e5676d720fb8d1a4..f6ffff085d36ba67d1355d203d6617652a9bf779 100644 (file)
@@ -411,6 +411,14 @@ DEF_CMD(doc_handle)
                pane_add_notify(ci->focus, dd->doc->home, "Notify:Replace");
                return 1;
        }
+       if (strcmp(ci->key, "Request:Notify:Recentre") == 0) {
+               pane_add_notify(ci->focus, dd->doc->home, "Notify:Recentre");
+               return 1;
+       }
+       if (strcmp(ci->key, "doc:Recentre") == 0) {
+               pane_notify(dd->doc->home, "Notify:Recentre", ci->mark, NULL);
+               return 1;
+       }
 
        if (strcmp(ci->key, "Clone") == 0) {
                struct pane *p = doc_attach(ci->focus, dd->doc);
index ae0acf15717ea2f0b296800ecac65ece957270a4..f4bf75c1af1d8332f98edcd0cb657d643c0ebfe0 100644 (file)
@@ -578,6 +578,10 @@ static int text_update_following_after_change(struct text *t, struct doc_ref *po
                *pos = *epos;
                return 1;
        }
+       /* HACK? */
+       if (text_ref_same(t, pos, epos))
+               /* KEep going*/
+               return 1;
        /* This is beyond the change point and no deletion or split
         * happened here, so all done.
         */
diff --git a/edlib.c b/edlib.c
index f1d9664a71c227c9201f55b6d4f143c3926ad555..f513a8658efeefd980761a32d80fc729e1b30cf0 100644 (file)
--- a/edlib.c
+++ b/edlib.c
@@ -129,9 +129,8 @@ int main(int argc, char *argv[])
                        global = pane_attach(global, "global-keymap", NULL, NULL);
                        call5("global-set-keymap", global, 0, NULL, "mode-emacs", 0);
                        b = pane_attach(global, "tile", NULL, NULL);
-                       p = doc_from_text(b, "*Welcome*", WelcomeText);
+                       p = doc_attach_view(b, pane2ed(b)->docs->home, NULL);
                }
-
                pane_refresh(&ed->root);
                while (call3("event:run", vroot, 0, NULL) == 1)
                        ;
index 7722aad54e45bb6419a3b9ec52658e68dbabf9a7..0b40711987eb888c330b38ba353f98f036d9b7ee 100644 (file)
@@ -79,7 +79,7 @@ DEF_CMD(messageline_handle)
                        else
                                pane_resize(ci->home, 0, ci->home->parent->h - mli->height,
                                            ci->home->parent->w, mli->height);
-                       pane_clear(mli->line, "bg:cyan");
+                       pane_clear(mli->line, "bg:white");
                        if (mli->message)
                                pane_str(mli->line, mli->message, "bold,fg:red,bg:cyan",
                                         0, 0 + mli->ascent);
index cf8d1ca0a02785e3715c5ff91c079197b4f8924a..16dc71f94c08213aa4cbf7756a76e671ba79e531 100644 (file)
@@ -82,7 +82,7 @@ REDEF_CMD(emacs_move)
        if (!ret)
                return 0;
 
-       if (strcmp(mv->type, "Move-View-Large") == 0 && old_x >= 0) {
+       if (strcmp(mv->type, "Move-View-Large") == 0 && old_x >= 0 && ret != 10) {
                /* Might have lost the cursor - place it at top or
                 * bottom of view, but make sure it moves only in the
                 * right direction.
@@ -167,6 +167,7 @@ static struct str_command {
        {CMD(emacs_str), "WindowOP", "close-others", "emCX-Chr-1"},
        {CMD(emacs_str), "WindowOP", "split-y", "emCX-Chr-2"},
        {CMD(emacs_str), "WindowOP", "split-x", "emCX-Chr-3"},
+       {CMD(emacs_str), "DisplayOP", "new", "emCX5-Chr-2"},
        {CMD(emacs_str), "WindowOP", "close", "emCX-Chr-0"},
        {CMD(emacs_str), "Display", "refresh", "C-Chr-L"},
        {CMD(emacs_str), "Abort", NULL, "C-Chr-G"},
@@ -597,10 +598,12 @@ static void emacs_init(void)
        unsigned i;
        struct command *cx_cmd = key_register_prefix("emCX-");
        struct command *cx4_cmd = key_register_prefix("emCX4-");
+       struct command *cx5_cmd = key_register_prefix("emCX5-");
        struct map *m = key_alloc();
 
        key_add(m, "C-Chr-X", cx_cmd);
        key_add(m, "emCX-Chr-4", cx4_cmd);
+       key_add(m, "emCX-Chr-5", cx5_cmd);
        key_add(m, "ESC", &emacs_meta);
 
        for (i = 0; i < ARRAY_SIZE(move_commands); i++) {
index 6ec876397703bdd95d8ab42ea42938ce6cef6d87..3847a750dec5b909107833dd58a4df4466d04fc1 100644 (file)
@@ -15,6 +15,18 @@ import thread
 import gobject
 import glib
 
+def take(name, place, args, default=None):
+    if name in args:
+        place.append(args[name])
+    else:
+        place.append(default)
+    return 1
+
+def attach(p, mode):
+    pl=[]
+    p.call("attach-%s"%mode, lambda key,**a:take('focus', pl, a))
+    return pl[0]
+
 class EdDisplay(gtk.Window):
     def __init__(self, home):
         gtk.Window.__init__(self)
@@ -30,6 +42,26 @@ class EdDisplay(gtk.Window):
 
     def handle(self, key, **a):
 
+        if key == "M-Chr--" or key == "M-Chr-_":
+            self.pane['scale'] = "%d"%(int(self.pane['scale']) * 100/105)
+            return 1
+        if key == "M-Chr-=" or key == "M-Chr-+":
+            self.pane['scale'] = "%d"%(int(self.pane['scale']) * 105/100)
+            return 1
+
+        if key == "DisplayOP" and a['str'] == "new":
+            pl=[]
+            disp = a['home']
+            while disp.parent:
+                disp = disp.parent
+            disp = EdDisplay(disp)
+            p = attach(disp.pane, "input");
+            p = attach(p, "messageline");
+            p = attach(p, "global-keymap")
+            p.call("global-set-keymap", "mode-emacs");
+            p = attach(p, "tile")
+            return 1
+
         if key == "Window:fullscreen":
             if a['numeric'] > 0:
                 self.fullscreen()
@@ -44,7 +76,6 @@ class EdDisplay(gtk.Window):
         if key == "pane-clear":
             f = a["focus"]
             if "str2" in a:
-                print "CLEAR", a['str2']
                 fg, bg = self.get_colours(a["str2"])
             else:
                 fg, bg = self.get_colours("bg:white")
@@ -117,7 +148,7 @@ class EdDisplay(gtk.Window):
                     if f.parent.focus != f:
                         extra = False
                     f = f.parent
-                print x,cx,y,cy,cw,ch,extra,a['numeric'],len(a['str'])
+                #print x,cx,y,cy,cw,ch,extra,a['numeric'],len(a['str'])
                 if extra:
                     pm.draw_rectangle(self.gc, True, x+cx, y-ascent+cy,
                                       cw, ch);
@@ -164,6 +195,28 @@ class EdDisplay(gtk.Window):
             pm.draw_pixbuf(self.gc, scale, 0, 0, x, y)
             return True
 
+        if key == "image-stretch-display":
+            # 'str' is a file name of an image
+            # xy is location for top/left
+            # numeric/extra are max width/height
+            # I should use a pane-per-image but I'm in a rush
+            fl = a['str']
+            f = a['focus']
+            w = a['numeric']
+            h = a['extra']
+            if h == 0:
+                h = w
+            (x,y) = a['xy']
+            try:
+                pb = gtk.gdk.pixbuf_new_from_file(fl)
+            except:
+                pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, w, h)
+                pb.fill(0xff000000)
+            scale = pb.scale_simple(w, h, gtk.gdk.INTERP_HYPER)
+            pm = self.get_pixmap(f)
+            pm.draw_pixbuf(self.gc, scale, 0, 0, x, y)
+            return True
+
         if key == "Notify:Close":
             f = a["focus"]
             if f and f in self.panes:
@@ -359,12 +412,17 @@ class EdDisplay(gtk.Window):
         t = self.text
         if not self.bg:
             self.bg = t.window.new_gc()
-        self.bg.set_foreground(colour)
+        try:
+            self.bg.set_foreground(colour)
+        except:
+            print 'error colour is', colour, type(colour)
+            pass
         (w,h) = pm.get_size()
         pm.draw_rectangle(self.bg, True, 0, 0, w, h)
 
 def new_display(key, home, comm2, **a):
     disp = EdDisplay(home)
+    disp.pane['scale'] = "1000"
     comm2('callback', disp.pane)
     return 1
 
index a6e69d8189961b78cba810db2f63fe54bbebbde2..bd25ee87bb9c6723943925ab7bacdd56476a8f63 100644 (file)
@@ -143,7 +143,7 @@ class PresenterPane(edlib.Pane):
                     if globals is not None:
                         self.globals = globals
                         if 'background' in globals:
-                            self['background'] = globals['background']
+                            self['background'] = 'call:Present-BG:'+globals['background']
                         if 'scale' in globals:
                             self['scale'] = globals['scale']
                         self.call("render-lines:redraw")
@@ -256,7 +256,7 @@ class PresenterPane(edlib.Pane):
                     pm = None
                     continue
 
-            # pm is the start of this page, just need to check next
+            # pm is the start of a page, just need to check next is vald
             if pm['next-valid'] != 'yes':
                 next = self.find_page(pm)
                 if not next:
@@ -270,6 +270,7 @@ class PresenterPane(edlib.Pane):
                     n.to_mark(next)
                     next.unlink()
                     pm['next-valid'] = 'yes'
+                    pm = None
                 else:
                     if self.marks_same(next, pm.next()):
                         pm['next-valid'] = 'yes'
@@ -331,6 +332,7 @@ class PresenterPane(edlib.Pane):
         la=[]
         self.call("doc:vmark-get", self.attrview, 2, lambda key,**a: take('mark2', la, a))
         line = la[0]
+        line.to_mark(page)
 
         while not next or (line < next and not self.marks_same(line, next)):
             # There is a line there that we care about - unless EOF
@@ -341,32 +343,103 @@ class PresenterPane(edlib.Pane):
             self.annotate(this, l)
         line.unlink()
 
-    def get_local_attr(self, m, attr):
+    def line_reval(self, l, page):
+        while l.prev() is not None and l.prev()['type'] == 'unknown':
+            l2 = l.prev()
+            l.unlink()
+            l = l2
+
+        if l is None:
+            la=[]
+            self.call("doc:vmark-get", self.attrview, 2,
+                      lambda key,**a: take('mark2', la, a))
+            l = la[0]
+            l.to_mark(page)
+        # l is a good starting point.  parse until l.next or page.next
+        end = l.next()
+        if end is None:
+            end = page.next()
+        while not end or (l < end and not self.marks_same(l, end)):
+            # There is a line there that we care about - unless EOF
+            this = l.dup()
+            txt = self.get_line_at(l)
+            if not txt:
+                break
+            self.annotate(this, txt)
+        l.unlink()
+
+    def get_local_attr(self, m, attr, page):
         t = 'attr:' + attr
         l = self.prev_line(m)
         while l:
             if l['type'] == 'unknown':
-                # Ouch - need to re-evaluate.  Just assume still at start-of-line
-                self.annotate(l, self.print_line_at(l))
-                pass
+                self.line_reval(l, page)
+                l = self.prev_line(m)
+                continue
+
             if l['type'] == t:
                 return l['value']
             l = l.prev()
         return None
 
-    para_ptn =  ['# ', '## ', '> ', '- ', '    ', '!',  None, '']
-    para_type = ['H1', 'H2',  'I',  'L1', 'C',    'IM', 'BL', 'P']
+    paras = {
+        '# ' : 'H1',
+        '## ': 'H2',
+        '>'  : 'I',
+        '- ' : 'L1',
+        '!'  : 'IM',
+        ''   : 'P',
+        None : 'BL',
+        '    - ': 'L2',
+        '     ': {'L2':'L2c', 'L2c':'L2c', 'L1':'L1c', 'L1c': 'L1c', None: 'C'},
+        '    ' : {'L2':'L1c', 'L2c':'L1c', 'L1':'L1c', 'L1c': 'L1c', None: 'C'},
+        ' '    : {'L2':'L1c', 'L2c':'L1c', 'L1':'L1c', 'L1c': 'L1c', None: 'P'},
+        }
     defaults = {
-        'H1': 'center,large,family:serif',
-        'H2': 'right:20,fg:red,bold',
-        'I': 'left:5,family:Mufferaw',
+        'H1': 'center,30,family:serif',
+        'H2': 'center,20,fg:red,bold',
+        'I': 'left:50,family:Mufferaw',
         'C': 'family:mono',
-        'L1': 'fg:blue,left:40,family:sans',
+        'L1': 'left:20,family:sans,bullet:#,tab:20',
+        'L1c': 'left:20,family:sans,tab:20',
+        'L2': 'left:40,family:sans,bullet:#,tab:20',
+        'L2c': 'left:40,family:sans,tab:20',
         'P': 'left:30,family:sans,space-below:20',
         'BL': '3',
+        'bullet': 'fg:red',
+        'bold': 'bold',
+        'italic':'italic'
         }
 
+    def get_attr(self, here, mode, page):
+        v = self.get_local_attr(here, mode, page)
+        if not v and mode in self.globals:
+            v = self.globals[mode]
+        if not v and mode in self.defaults:
+            v = self.defaults[mode]
+        if not v:
+            v = ""
+        return v
+
     def handle(self, key, **a):
+        if key == "Present-BG":
+            cmds = a['str'].split(',')
+            f = a['focus']
+            for c in cmds:
+                if c[:6] == 'color:':
+                    f.call('pane-clear', c[6:])
+                if c[:14] == "image-stretch:":
+                    f.call('image-stretch-display', self.w, self.h, c[14:], (0,0))
+                if c[:6] == "image:":
+                    f.call('image-display', self.w, self.h, c[6:], (0,0))
+                if c[:8] == "overlay:":
+                    f.call('image-display', self.w/6, self.h*3/4, c[8:], (self.w*5/6, self.h/4))
+                if c == "page-local":
+                    page = self.find_pages(a['mark'])
+                    cm = self.get_local_attr(a['mark'], "background", page)
+                    if cm:
+                        cmds.extend(cm.split(','))
+            return 1
         if key == "render-line-prev":
             # Go to start of page
             here = a['mark']
@@ -417,30 +490,62 @@ class PresenterPane(edlib.Pane):
                 cb("callback", self)
             else:
                 mode = 'P'
-                for n in range(len(self.para_ptn)):
-                    prefix = self.para_ptn[n]
-                    if prefix == None and line == "":
-                        mode = self.para_type[n]
+                prefix = None
+                for pf in self.paras:
+                    if pf == None and line == "":
+                        mode = self.paras[pf]
                         break
-                    if prefix is not None and prefix == line[0:len(prefix)]:
-                        mode = self.para_type[n]
-                        line = line[len(prefix):]
-                        break
-                v = self.get_local_attr(here, mode)
-                if not v and mode in self.globals:
-                    v = self.globals[mode]
-                if not v and mode in self.defaults:
-                    v = self.defaults[mode]
-                if not v:
-                    v = ""
+                    if (pf and (prefix is None or len(pf) > len(prefix)) and
+                        pf == line[0:len(pf)]):
+                        mode = self.paras[pf]
+                        prefix = pf
+
+                if prefix:
+                    line = line[len(prefix):]
+                if type(mode) == dict:
+                    # look up type of previous line.
+                    pmode = None
+                    if here.prev() is not None:
+                        pmode = here.prev()['mode']
+                    if pmode in mode:
+                        mode = mode[pmode]
+                    else:
+                        mode = mode[None]
+                here['mode'] = mode
+                v = self.get_attr(here, mode, page)
 
                 if mode == 'IM':
-                    cb("callback", self, "<image:"+line+",width=200,height=100>")
+                    width=200; height=100
+                    if len(line) > 1 and line[0].isdigit():
+                        try:
+                            c = line.index(':')
+                            width = int(line[:c])
+                        except:
+                            c = -1
+
+                        line = line[c+1:]
+                        try:
+                            c = line.index(':')
+                            height = int(line[:c])
+                        except:
+                            c = -1
+                        line = line[c+1:]
+
+                    cb("callback", self, "<image:"+line+",width:%d,height:%d>"%(width,height))
                     return 1
 
                 line = re.sub("\*([A-Za-z0-9][^*<]*)\*", "<italic>\\1</>", line)
-                line = re.sub("`([A-Za-z0-9][^*<]*)`", "<family:mono>\\1</>", line)
-                line = "<"+v+">"+ line + "</>"
+                line = re.sub("`([/A-Za-z0-9][^*<]*)`", "<family:mono>\\1</>", line)
+                b = re.match(".*,bullet:([^:,]*)", v)
+                if b:
+                    vb = self.get_attr(here, 'bullet', page)
+                    if vb:
+                        bl = "<%s>%s</>" % (vb, b.group(1))
+                    else:
+                        bl = b.group(1)
+                    line = bl +"<"+v+">"+ line + "</>"
+                else:
+                    line = "<"+v+">"+ line + "</>"
                 line += '\n'
                 if end and (here > end or self.marks_same(here,end)):
                     line += '\f'
@@ -478,6 +583,10 @@ class PresenterPane(edlib.Pane):
                     l['type'] = 'unknown'
             return 1
 
+        if key == "Notify:Recentre":
+            self.call("Move-View-Pos", a['mark'])
+            return 1
+
         if key == "Close":
             # destroy all marks
             self.release()
@@ -528,10 +637,62 @@ def present_attach(key, focus, comm2, **a):
     p = PresenterPane(focus)
     p['render-wrap'] = 'no'
     p['background'] = 'color:yellow'
+    p['hide-cursor'] = 'yes'
 
     p.call("Request:Notify:Replace")
+    p.call("Request:Notify:Recentre")
     p = p.render_attach("lines")
     comm2('callback', p)
     return 1
 
+def get_line_at(focus, m):
+    # call render-line at m
+    line = []
+    focus.call("render-line", m, -1, lambda key, **a: take('str', line, a, ''))
+    return line[0]
+def present_page(key, focus, mark, **a):
+    # Assumming 'mark' is either start-of-file (if 'sof') or the start of
+    # a page, find the start of the next page.  Return an untyped mark
+    # or None if there is no next page.
+    # A page starts with some ":attr:" lines and then a "# " line.
+    # If not 'sof' we first need to skip over the start of 'this' page.
+    if a['numeric'] <= 0:
+        return 0
+    skipping = True
+    start = mark
+    m = start.dup(1)
+    maybe = None
+
+    while True:
+        if not maybe and not skipping:
+            maybe = m.dup()
+        l = get_line_at(focus, m)
+        if not l:
+            # End of document
+            if maybe:
+                maybe.unlink()
+            m.unlink()
+            return 1
+        if l[0] == ':':
+            # attribute - doesn't advance possible start
+            pass
+        elif l[0:2] == "# ":
+            # level-1 heading. This is it if not skipping
+            if skipping:
+                skipping = False
+            else:
+                m.unlink()
+                mark.to_mark(maybe)
+                maybe.unlink()
+                focus.call("doc:Recentre", mark)
+                return 1
+        else:
+            # not part of start-of-page
+            skipping = False
+            if maybe:
+                maybe.unlink()
+            maybe = None
+
+
 editor.call("global-set-command", pane, "render-present-attach", present_attach)
+editor.call("global-set-command", pane, "Presenter-page", present_page)
index 918a19d65bc9db0b3ce28b810d0c05c80f0061a0..28a892fd88acaf088c0e2d60c0581ed9dd7a08a4 100644 (file)
@@ -222,6 +222,9 @@ static void update_line_height(struct pane *p, int *h, int *a, int *w, int *cent
                        if ((c=strstr(buf_final(&attr), ",space-below:")) != NULL) {
                                below = atoi(c+13) * scale/1000;
                        }
+                       if ((c=strstr(buf_final(&attr), ",tab:")) != NULL) {
+                               *w = atoi(c+5) * scale / 1000;
+                       }
                        attr_found = 1;
                        update_line_height_attr(p, h, a, w, buf_final(&attr), "", scale);
                } else {
@@ -310,6 +313,7 @@ static void render_line(struct pane *p, char *line, int *yp, int dodraw, int sca
        int ret = 0;
        int twidth = 0;
        int center = 0;
+       int margin;
 
        /* Temporary hack (I hope) */
        if (strncmp(line, "<image", 6) == 0) {
@@ -334,6 +338,7 @@ static void render_line(struct pane *p, char *line, int *yp, int dodraw, int sca
                x += center;
        if (center < 0)
                x = p->w - x - twidth + center;
+       margin = x;
        rl->line_height = line_height;
        buf_init(&attr);
        buf_append(&attr, ' '); attr.len = 0;
@@ -449,10 +454,17 @@ static void render_line(struct pane *p, char *line, int *yp, int dodraw, int sca
                                        line += 1;
 
                                if (a[0] != '/') {
+                                       int ln = attr.len;
+                                       char *tb;
                                        buf_concat_len(&attr, a, line-a);
                                        /* mark location with ",," */
                                        attr.b[attr.len-1] = ',';
                                        buf_append(&attr, ',');
+                                       tb = strstr(buf_final(&attr)+ln,
+                                                   "tab:");
+                                       if (tb) {
+                                               x = margin + atoi(tb+4) * scale / 1000;
+                                       }
                                } else {
                                        /* strip back to ",," */
                                        if (attr.len > 0)
@@ -673,8 +685,12 @@ static int get_scale(struct pane *p)
        if (!sc)
                return 1000;
 
-       if (sscanf(sc, "x:%d,y:%d", &x, &y) != 2)
+       if (sscanf(sc, "x:%d,y:%d", &x, &y) != 2) {
+               scale = atoi(sc);
+               if (scale > 3)
+                       return scale;
                return 1000;
+       }
 
        /* 'scale' is pixels per point times 1000.
         * ":scale:x" is points across pane, so scale = p->w/x*1000
@@ -837,18 +853,37 @@ static void render(struct mark *pm, struct pane *p)
        char *hdr;
        char *bg;
        int scale = get_scale(p);
+       int hide_cursor = 0;
 
        hdr = pane_attr_get(p, "heading");
        if (hdr && !*hdr)
                hdr = NULL;
+       bg = pane_attr_get(p, "hide-cursor");
+       if (bg && strcmp(bg, "yes") == 0)
+               hide_cursor = 1;
 
 restart:
+       y = 0;
        bg = pane_attr_get(p, "background");
        if (bg && strncmp(bg, "color:", 6) == 0) {
                char *a;
                asprintf(&a, "bg:%s", bg+6);
                pane_clear(p, a);
                free(a);
+       } else if (bg && strncmp(bg, "image:", 6) == 0) {
+               pane_clear(p, "bg:black");
+               call_xy7("image-display", p, p->w, p->h, bg+6, NULL, 0, 0, NULL, NULL);
+       } else if (bg && strncmp(bg, "image-stretch:", 14) == 0) {
+               pane_clear(p, "bg:black");
+               call_xy7("image-stretch-display", p, p->w, p->h, bg+14, NULL, 0, 0, NULL, NULL);
+       } else if (bg && strncmp(bg, "call:", 5) == 0) {
+               char *f, *a;
+               f = strdup(bg+5);
+               a = strchr(f, ':');
+               if (a)
+                       *a++ = 0;
+               call5(f, p, 0, pm, a, 0);
+               free(f);
        } else
                pane_clear(p, NULL);
        if (hdr) {
@@ -868,7 +903,7 @@ restart:
                        call_render_line(p, m);
                }
                m2 = vmark_next(m);
-               if (p->cx <= 0 &&
+               if (!hide_cursor && p->cx <= 0 &&
                    mark_ordered_or_same_pane(p, m, pm) &&
                    (!m2 || mark_ordered_or_same_pane(p, pm, m2))) {
                        int len = call_render_line_to_point(p, pm,
@@ -1006,6 +1041,7 @@ DEF_CMD(render_lines_move)
        struct mark *top;
        int pagesize = rl->line_height;
        int scale = get_scale(p);
+       int ret;
 
        top = vmark_first(p, rl->typenum);
        if (!top)
@@ -1014,6 +1050,14 @@ DEF_CMD(render_lines_move)
                pagesize = p->h - 2 * rl->line_height;
        rpt *= pagesize;
 
+       ret = call3("Presenter-page", p, rpt, ci->mark);
+       if (ret) {
+               rl->ignore_point = 0;
+               find_lines(ci->mark, p);
+               pane_damaged(p, DAMAGED_CONTENT);
+               return 10;
+       }
+
        rl->ignore_point = 1;
 
        if (rpt < 0) {
@@ -1266,6 +1310,15 @@ DEF_CMD(render_lines_redraw)
        return 1;
 }
 
+/* This hack doesn't belong here */
+DEF_CMD(render_lines_display)
+{
+       if (ci->str && strcmp(ci->str, "refresh") == 0) {
+               call3("doc:Recentre", ci->focus, 0, ci->mark);
+       }
+       return 0;
+}
+
 static struct map *rl_map;
 
 DEF_LOOKUP_CMD(render_lines_handle, rl_map)
@@ -1295,6 +1348,8 @@ static void render_lines_register_map(void)
        key_add(rl_map, "render-lines:redraw", &render_lines_redraw);
 
        key_add(rl_map, "Notify:Replace", &render_lines_notify_replace);
+
+       key_add(rl_map, "Display", &render_lines_display);
 }
 
 REDEF_CMD(render_lines_attach)