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);
*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.
*/
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)
;
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);
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.
{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"},
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++) {
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)
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()
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")
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);
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:
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
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")
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:
n.to_mark(next)
next.unlink()
pm['next-valid'] = 'yes'
+ pm = None
else:
if self.marks_same(next, pm.next()):
pm['next-valid'] = 'yes'
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
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']
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'
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()
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)
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 {
int ret = 0;
int twidth = 0;
int center = 0;
+ int margin;
/* Temporary hack (I hope) */
if (strncmp(line, "<image", 6) == 0) {
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;
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)
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
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) {
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,
struct mark *top;
int pagesize = rl->line_height;
int scale = get_scale(p);
+ int ret;
top = vmark_first(p, rl->typenum);
if (!top)
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) {
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)
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)