]> git.neil.brown.name Git - edlib.git/blobdiff - display-ncurses.c
TODO: clean out done items.
[edlib.git] / display-ncurses.c
index 07c3dab5dd1d52c8038bbc0ba9b4e1fd8380989f..86995cd44e86ca57bb051f9bc26729dd389e127e 100644 (file)
@@ -995,32 +995,124 @@ DEF_CMD(nc_draw_text)
        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;
@@ -1034,7 +1126,7 @@ DEF_CMD(nc_draw_image)
        } 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;
@@ -1045,103 +1137,19 @@ DEF_CMD(nc_draw_image)
                        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);
 
@@ -1168,7 +1176,7 @@ DEF_CMD(nc_image_size)
        } 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;
@@ -1347,6 +1355,8 @@ static struct pane *ncurses_init(struct pane *ed safe,
        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);
@@ -1396,6 +1406,7 @@ DEF_CMD(force_redraw)
        ncurses_start(p);
 
        clearok(curscr, 1);
+       pane_damaged(p, DAMAGED_POSTORDER);
        return 1;
 }
 
@@ -1792,12 +1803,11 @@ DEF_CMD(display_ncurses)
        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);
 
@@ -1810,9 +1820,9 @@ void edlib_init(struct pane *ed safe)
                  "attach-display-ncurses");
 
        nc_map = key_alloc();
-       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, "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);