SCREEN *scr;
FILE *scr_file;
int is_xterm;
- char *noclose;
struct col_hash *col_hash;
int report_position;
long last_event;
current_screen = NULL;
return;
}
- dd = &p->data;
+ dd = p->data;
current_dd = dd;
if (!dd)
return;
static bool parse_event(struct pane *p safe);
static bool prepare_recrep(struct pane *p safe)
{
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
char *name;
name = getenv("EDLIB_RECORD");
static void close_recrep(struct pane *p safe)
{
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
if (dd->log) {
fprintf(dd->log, "Close %d\n", dd->clears);
static void record_key(struct pane *p safe, char *key safe)
{
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
char q;
if (!dd->log)
static void record_mouse(struct pane *p safe, char *key safe, int x, int y)
{
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
char q;
if (!dd->log)
return;
static void record_screen(struct pane *p safe)
{
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
struct md5_state ctx;
uint16_t buf[CCHARW_MAX+5];
char out[MD5_DIGEST_SIZE*2+1];
static bool parse_event(struct pane *p safe)
{
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
char line[80];
line[79] = 0;
REDEF_CMD(next_evt)
{
struct pane *p = ci->home;
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
int button = 0, type = 0;
dd->input_sleeping = 0;
{
/* If this is only display, then refuse to close this one */
struct call_return cr;
- struct display_data *dd = &ci->home->data;
+ char *nc = pane_attr_get(ci->home, "no-close");
- if (dd->noclose) {
- call("Message", ci->focus, 0, NULL, dd->noclose);
+ if (nc) {
+ call("Message", ci->focus, 0, NULL, nc);
return 1;
}
return 1;
}
-DEF_CMD(nc_set_noclose)
-{
- struct display_data *dd = &ci->home->data;
-
- free(dd->noclose);
- dd->noclose = NULL;
- if (ci->str)
- dd->noclose = strdup(ci->str);
- return 1;
-}
-
static int nc_putc(int ch)
{
if (current_dd)
DEF_CB(ns_resume)
{
- struct display_data *dd = &ci->home->data;
+ struct display_data *dd = ci->home->data;
if (dd->suspended) {
dd->suspended = False;
DEF_CMD(nc_external_viewer)
{
struct pane *p = ci->home;
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
char *disp = pane_attr_get(p, "DISPLAY");
char *disp_auth = pane_attr_get(p, "XAUTHORITY");
char *remote = pane_attr_get(p, "REMOTE_SESSION");
static void ncurses_stop(struct pane *p safe)
{
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
if (dd->is_xterm) {
/* disable bracketed-paste */
static void ncurses_end(struct pane *p safe)
{
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
if (dd->did_close)
return;
}
static int cvt_attrs(struct pane *p safe, struct pane *home safe,
- const char *attrs, int *pairp safe, bool use_parent)
+ const char *attrs, int *pairp safe)
{
- struct display_data *dd = &home->data;
+ struct display_data *dd = home->data;
int attr = 0;
const char *a, *v;
char *col = NULL;
int bg = COLOR_WHITE+8;
set_screen(home);
- do {
+ while (p->parent != p &&(pan = pane_panel(p, NULL)) == NULL)
p = p->parent;
- } while (p->parent != p &&(pan = pane_panel(p, NULL)) == NULL);
- if (pan && use_parent) {
+ if (pan) {
/* Get 'default colours for this pane - set at clear */
int at = getbkgd(panel_window(pan));
int pair = PAIR_NUMBER(at);
DEF_CMD(nc_notify_display)
{
- struct display_data *dd = &ci->home->data;
+ struct display_data *dd = ci->home->data;
comm_call(ci->comm2, "callback:display", ci->home, dd->last_event);
return 1;
}
-DEF_CMD(nc_close)
+DEF_CMD_CLOSED(nc_close)
{
struct pane *p = ci->home;
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
ncurses_end(p);
hash_free(dd);
fclose(dd->scr_file);
DEF_CMD(nc_clear)
{
struct pane *p = ci->home;
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
cchar_t cc = {};
int pair = 0;
- int attr = cvt_attrs(ci->focus, p, ci->str, &pair, ci->str == NULL);
+ /* default come from parent when clearing pane */
+ int attr = cvt_attrs(ci->focus->parent, p, ci->str, &pair);
PANEL *panel;
WINDOW *win;
int w, h;
{
struct pane *p = ci->home;
int pair = 0;
- int attr = cvt_attrs(ci->focus, p, ci->str2, &pair, True);
+ int attr = cvt_attrs(ci->focus, p, ci->str2, &pair);
int cursor_offset = ci->num;
short x = ci->x, y = ci->y;
const char *str = ci->str;
return 1;
}
+struct di_info {
+ struct command c;
+ MagickWand *wd safe;
+ int x,y,w,h;
+ int xo, yo;
+ struct pane *p safe;
+};
+
+DEF_CB(nc_draw_image_cb)
+{
+ struct di_info *dii = container_of(ci->comm, struct di_info, c);
+ struct display_data *dd = dii->p->data;
+ int i, j;
+ unsigned char *buf;
+
+ switch (ci->key[0]) {
+ case 'w': /* width */
+ return MagickGetImageWidth(dii->wd);
+ case 'h': /* height */
+ return MagickGetImageHeight(dii->wd);
+ case 's': /* scale */
+ MagickResizeImage(dii->wd, ci->num, ci->num2, BoxFilter, 1.0);
+ return 1;
+ case 'c': /* crop or cursor */
+ if (ci->key[1] != 'u') {
+ /* crop */
+ dii->x = ci->x;
+ dii->y = ci->y;
+ dii->w = ci->num;
+ dii->h = ci->num2;
+ return 1;
+ } else {
+ /* cursor */
+ /* FIXME this doesn't work because
+ * render-line knows too much and gets it wrong.
+ */
+ ncurses_text(ci->focus, dii->p, 'X', 0,
+ to_pair(dd, 0, 0),
+ ci->x + dii->xo,
+ (ci->y + dii->xo)/2, 1);
+ return 1;
+ }
+ case 'd': /* draw */
+ if (dii->w <= 0 || dii->h <= 0)
+ return Efail;
+ buf = malloc(dii->h * dii->w * 4);
+
+ MagickExportImagePixels(dii->wd, dii->x, dii->y,
+ dii->w, dii->h,
+ "RGBA", CharPixel, buf);
+
+ for (i = 0; i < dii->h; i+= 2) {
+ static const wint_t hilo = 0x2580; /* L'▀' */
+ static unsigned char blk[4] = "\0\0\0";
+ for (j = 0; j < dii->w ; j+= 1) {
+ unsigned char *p1 = buf + i*dii->w*4 + j*4;
+ unsigned char *p2 = i + 1 < dii->h ?
+ buf + (i+1)*dii->w*4 + j*4 : blk;
+ int rgb1[3] = { p1[0]*1000/255, p1[1]*1000/255,
+ p1[2]*1000/255 };
+ int rgb2[3] = { p2[0]*1000/255, p2[1]*1000/255,
+ p2[2]*1000/255 };
+ int fg = find_col(dd, rgb1);
+ int bg = find_col(dd, rgb2);
+
+ if (p1[3] < 128 || p2[3] < 128) {
+ /* transparent */
+ cchar_t cc;
+ short f,b;
+ struct pane *pn2 = ci->focus;
+ PANEL *pan = pane_panel(pn2, NULL);
+
+ while (!pan && pn2->parent != pn2) {
+ pn2 = pn2->parent;
+ pan = pane_panel(pn2, NULL);
+ }
+ if (pan) {
+ wgetbkgrnd(panel_window(pan), &cc);
+ if (cc.ext_color == 0)
+ /* default. This is light
+ * gray rather then white,
+ * but I think it is a good
+ * result.
+ */
+ b = COLOR_WHITE;
+ else
+ pair_content(cc.ext_color, &f, &b);
+ if (p1[3] < 128)
+ fg = b;
+ if (p2[3] < 128)
+ bg = b;
+ }
+ }
+ ncurses_text(ci->focus, dii->p, hilo, 0,
+ to_pair(dd, fg, bg),
+ ci->num + dii->xo + j,
+ (ci->num2 + dii->yo + i)/2,
+ 0);
+ }
+ }
+ free(buf);
+ return 1;
+ default:
+ return Efail;
+ }
+}
+
DEF_CMD(nc_draw_image)
{
/* 'str' identifies the image. Options are:
* file:filename - load file from fs
* comm:command - run command collecting bytes
- * 'num' is '16' if image should be stretched to fill pane
- * Otherwise it is the 'or' of
- * 0,1,2 for left/middle/right in x direction
- * 0,4,8 for top/middle/bottom in y direction
- * only one of these can be used as image will fill pane
- * in other direction.
- * If 'x' and 'y' are both positive, draw cursor box at
- * p->cx, p->cy of a size so that 'x' will fit across and
- * 'y' will fit down.
+ * 'str2' and numbers are handled by Draw:scale-image.
*/
struct pane *p = ci->home;
- struct display_data *dd = &p->data;
- int x = 0, y = 0;
- bool stretch = ci->num & 16;
- int pos = ci->num;
- int w = ci->focus->w, h = ci->focus->h * 2;
- int cx = -1, cy = -1;
MagickBooleanType status;
- MagickWand *wd;
- unsigned char *buf;
- int i, j;
+ MagickWand *wd = NULL;
+ struct di_info dii;
if (!ci->str)
return Enoarg;
} else if (strstarts(ci->str, "comm:")) {
struct call_return cr;
wd = NewMagickWand();
- cr = call_ret(bytes, ci->str+5, ci->focus, 0, NULL, ci->str2);
+ cr = call_ret(bytes, ci->str+5, ci->focus);
if (!cr.s) {
DestroyMagickWand(wd);
return Efail;
DestroyMagickWand(wd);
return Efail;
}
- } else
+ }
+
+ if (!wd)
return Einval;
MagickAutoOrientImage(wd);
- if (!stretch) {
- int ih = MagickGetImageHeight(wd);
- int iw = MagickGetImageWidth(wd);
-
- if (iw <= 0 || iw <= 0) {
- DestroyMagickWand(wd);
- return Efail;
- }
- if (iw * h > ih * w) {
- /* Image is wider than space, use less height */
- ih = ih * w / iw;
- switch(pos & (8+4)) {
- case 4: /* center */
- y = (h - ih) / 2; break;
- case 8: /* bottom */
- y = h - ih; break;
- }
- /* Keep 'h' even! */
- h = ((ih+1)/2) * 2;
- } else {
- /* image is too tall, use less width */
- iw = iw * h / ih;
- switch (pos & (1+2)) {
- case 1: /* center */
- x = (w - iw) / 2; break;
- case 2: /* right */
- x = w - iw ; break;
- }
- w = iw;
- }
- }
- MagickAdaptiveResizeImage(wd, w, h);
- buf = malloc(h * w * 4);
- MagickExportImagePixels(wd, 0, 0, w, h, "RGBA", CharPixel, buf);
-
- if (ci->x > 0 && ci->y > 0 && ci->focus->cx >= 0) {
- /* We want a cursor */
- cx = x + ci->focus->cx;
- cy = y + ci->focus->cy;
- }
- for (i = 0; i < h; i+= 2) {
- static const wint_t hilo = 0x2580; /* L'▀' */
- for (j = 0; j < w ; j+= 1) {
- unsigned char *p1 = buf + i*w*4 + j*4;
- unsigned char *p2 = buf + (i+1)*w*4 + j*4;
- int rgb1[3] = { p1[0]*1000/255, p1[1]*1000/255, p1[2]*1000/255 };
- int rgb2[3] = { p2[0]*1000/255, p2[1]*1000/255, p2[2]*1000/255 };
- int fg = find_col(dd, rgb1);
- int bg = find_col(dd, rgb2);
-
- if (p1[3] < 128 || p2[3] < 128) {
- /* transparent */
- cchar_t cc;
- short f,b;
- struct pane *pn2 = ci->focus;
- PANEL *pan = pane_panel(pn2, NULL);
-
- while (!pan && pn2->parent != pn2) {
- pn2 = pn2->parent;
- pan = pane_panel(pn2, NULL);
- }
- if (pan) {
- wgetbkgrnd(panel_window(pan), &cc);
- if (cc.ext_color == 0)
- /* default. This is light
- * gray rather then white,
- * but I think it is a good
- * result.
- */
- b = COLOR_WHITE;
- else
- pair_content(cc.ext_color, &f, &b);
- if (p1[3] < 128)
- fg = b;
- if (p2[3] < 128)
- bg = b;
- }
- }
- /* FIXME this doesn't work because
- * render-line knows too much and gets it wrong.
- */
- if (cx == x+j && cy == y + (i/2))
- ncurses_text(ci->focus, p, 'X', 0,
- to_pair(dd, 0, 0),
- x+j, y+(i/2), 1);
- else
- ncurses_text(ci->focus, p, hilo, 0,
- to_pair(dd, fg, bg),
- x+j, y+(i/2), 0);
-
- }
- }
- free(buf);
+ dii.c = nc_draw_image_cb;
+ dii.wd = wd;
+ dii.p = p;
+ dii.w = dii.h = dii.x = dii.y = dii.xo = dii.yo = 0;
+ call("Draw:scale-image", ci->focus,
+ ci->num, NULL, NULL, ci->num2, NULL, ci->str2,
+ ci->x, ci->y, &dii.c);
DestroyMagickWand(wd);
} else if (strstarts(ci->str, "comm:")) {
struct call_return cr;
wd = NewMagickWand();
- cr = call_ret(bytes, ci->str+5, ci->focus, 0, NULL, ci->str2);
+ cr = call_ret(bytes, ci->str+5, ci->focus);
if (!cr.s) {
DestroyMagickWand(wd);
return Efail;
DEF_CMD(nc_refresh_post)
{
struct pane *p = ci->home;
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
struct pane *p1;
PANEL *pan, *pan2;
dest.y, dest.x, destend.y-1, destend.x-1, 0);
}
/* place the cursor */
- p1 = pane_leaf(p);
+ p1 = pane_focus(p);
pan = NULL;
while (p1 != p && (pan = pane_panel(p1, NULL)) == NULL)
p1 = p1->parent;
static void ncurses_start(struct pane *p safe)
{
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
int rows, cols;
start_color();
p = pane_register(ed, 1, &ncurses_handle.c);
if (!p)
return NULL;
- dd = &p->data;
+ dd = p->data;
dd->scr = scr;
dd->scr_file = f;
dd->is_xterm = (term && strstarts(term, "xterm"));
+ attr_set_str(&p->attrs, "Display:pixels", "1x2");
+
set_screen(p);
ncurses_start(p);
REDEF_CMD(handle_winch)
{
struct pane *p = ci->home;
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
struct winsize size;
ioctl(fileno(dd->scr_file), TIOCGWINSZ, &size);
set_screen(p);
ncurses_start(p);
clearok(curscr, 1);
+ pane_damaged(p, DAMAGED_POSTORDER);
return 1;
}
static void send_key(int keytype, wint_t c, int alt, struct pane *p safe)
{
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
char *n;
char buf[100];/* FIXME */
char t[5];
int button, char *mod, int type)
{
int ret;
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
record_mouse(p, cmd, x, y);
ret = call("Mouse-event", p, button, NULL, cmd, type, NULL, mod, x, y);
static void send_mouse(MEVENT *mev safe, struct pane *p safe)
{
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
int x = mev->x;
int y = mev->y;
int b;
static void paste_start(struct pane *home safe)
{
- struct display_data *dd = &home->data;
+ struct display_data *dd = home->data;
dd->paste_start = time(NULL);
buf_init(&dd->paste_buf);
static void paste_flush(struct pane *home safe)
{
- struct display_data *dd = &home->data;
+ struct display_data *dd = home->data;
if (!dd->paste_start)
return;
static bool paste_recv(struct pane *home safe, int is_keycode, wint_t ch)
{
- struct display_data *dd = &home->data;
+ struct display_data *dd = home->data;
time_t now;
if (dd->paste_start == 0)
return False;
DEF_CMD(nc_get_paste)
{
- struct display_data *dd = &ci->home->data;
+ struct display_data *dd = ci->home->data;
comm_call(ci->comm2, "cb", ci->focus,
dd->paste_start, NULL, dd->paste_latest);
REDEF_CMD(input_handle)
{
struct pane *p = ci->home;
- struct display_data *dd = &p->data;
+ struct display_data *dd = p->data;
static const char paste_seq[] = "\e[200~";
wint_t c;
int is_keycode;
if (!term)
term = "xterm-256color";
- p = ncurses_init(ed, tty, term);
- if (p)
- p = call_ret(pane, "editor:activate-display", p);
- if (p && ci->focus != ed)
- /* Assume ci->focus is a document */
- p = home_call_ret(pane, ci->focus, "doc:attach-view", p, 1);
+ p = call_ret(pane, "attach-window-core", ed);
+ if (!p)
+ return Efail;
+
+ p = ncurses_init(p, tty, term);
if (p)
return comm_call(ci->comm2, "callback:display", p);
"attach-display-ncurses");
nc_map = key_alloc();
- key_add(nc_map, "Display:refresh", &force_redraw);
- key_add(nc_map, "Display:close", &nc_close_display);
- key_add(nc_map, "Display:set-noclose", &nc_set_noclose);
- key_add(nc_map, "Display:external-viewer", &nc_external_viewer);
+ key_add(nc_map, "Window:refresh", &force_redraw);
+ key_add(nc_map, "Window:close", &nc_close_display);
+ key_add(nc_map, "Window:external-viewer", &nc_external_viewer);
key_add(nc_map, "Close", &nc_close);
key_add(nc_map, "Draw:clear", &nc_clear);
key_add(nc_map, "Draw:text-size", &nc_text_size);