#include <time.h>
#include <stdio.h>
+#define PANE_DATA_TYPE struct window_data
#include "core.h"
#include "internal.h"
int sel_committed;
struct pane *sel_owner_fallback;
};
+#include "core-pane.h"
DEF_CMD(request_notify)
{
- pane_add_notify(ci->focus, ci->home, ksuffix(ci, "window:request:"));
+ pane_add_notify(ci->focus, ci->home, ksuffix(ci, "Window:request:"));
return 1;
}
DEF_CMD(send_notify)
{
- /* window:notify:... */
- return home_pane_notify(ci->home, ksuffix(ci, "window:notify:"),
+ /* Window:notify:... */
+ return home_pane_notify(ci->home, ksuffix(ci, "Window:notify:"),
ci->focus,
ci->num, ci->mark, ci->str,
ci->num2, ci->mark2, ci->str2, ci->comm2);
DEF_CMD(window_set)
{
- const char *val = ksuffix(ci, "window:set:");
+ const char *val = ksuffix(ci, "Window:set:");
if (!*val)
val = ci->str2;
if (!val)
return Enoarg;
- if (ci->str)
- attr_set_str(&ci->home->attrs, val, ci->str);
+ attr_set_str(&ci->home->attrs, val, ci->str);
return 1;
}
/* Don't require exactly same pane for sel_owner,
* but ensure they have the same focus.
*/
- op = pane_leaf(wd->sel_owner);
- fp = pane_leaf(ci->focus);
+ op = pane_focus(wd->sel_owner);
+ fp = pane_focus(ci->focus);
if (fp != op)
return Efalse;
return 1;
}
+DEF_CMD(scale_image)
+{
+ /* This is a helper for Draw:image which interprets str2
+ * with other values and calls comm2 with:
+ * "width" returns image width
+ * "height" returns image height
+ * "scale" num=new width, num2=new height
+ * "crop" x,y is top-left num,num2 - width,height
+ * These numbers apply after scaling.
+ * "draw" num,num2 = offset
+ * "cursor" x,y=pos, num,num2=size
+ *
+ * Inputs are:
+ * 'str2' container 'mode' information.
+ * By default the image is placed centrally in the pane
+ * and scaled to use either fully height or fully width.
+ * Various letters modify this:
+ * 'S' - stretch to use full height *and* full width
+ * 'L' - place on left if full width isn't used
+ * 'R' - place on right if full width isn't used
+ * 'T' - place at top if full height isn't used
+ * 'B' - place at bottom if full height isn't used.
+ *
+ * Also a suffix ":NNxNN" will be parse and the two numbers used
+ * to give number of rows and cols to overlay on the image for
+ * the purpose of cursor positioning. If these are present and
+ * p->cx,cy are not negative, draw a cursor at p->cx,cy highlighting
+ * the relevant cell.
+ *
+ * num,num2, if both positive, override the automatic scaling.
+ * The image is scaled to this many pixels.
+ * x,y is top-left pixel in the scaled image to start display at.
+ * Negative values allow a margin between pane edge and this image.
+ */
+ struct pane *p = ci->focus;
+ const char *mode = ci->str2 ?: "";
+ bool stretch = strchr(mode, 'S');
+ int w, h;
+ int x = 0, y = 0;
+ int pw, ph;
+ int xo = 0, yo = 0;
+ int cix, ciy;
+ const char *pxl;
+ short px, py;
+
+ if (!ci->comm2)
+ return Enoarg;
+
+ pxl = pane_attr_get(p, "Display:pixels");
+ if (sscanf(pxl ?: "1x1", "%hdx%hx", &px, &py) != 2)
+ px = py = 1;
+
+ w = p->w * px;
+ h = p->h * py;
+ if (ci->num > 0 && ci->num2 > 0) {
+ w = ci->num;
+ h = ci->num2;
+ } else if (ci->num > 0) {
+ int iw = comm_call(ci->comm2, "width", p);
+ int ih = comm_call(ci->comm2, "height", p);
+
+ if (iw <= 0 || ih <= 0)
+ return Efail;
+
+ w = iw * ci->num / 1024;
+ h = ih * ci->num / 1024;
+ } else if (!stretch) {
+ int iw = comm_call(ci->comm2, "width", p);
+ int ih = comm_call(ci->comm2, "height", p);
+
+ if (iw <= 0 || ih <= 0)
+ return Efail;
+
+ if (iw * h > ih * w) {
+ /* Image is wider than space, use less height */
+ ih = ih * w / iw;
+ if (strchr(mode, 'B'))
+ /* bottom */
+ y = h - ih;
+ else if (!strchr(mode, 'T'))
+ /* center */
+ y = (h - ih) / 2;
+ /* Round up to pixels-per-cell */
+ h = ((ih + py - 1) / py) * py;
+ } else {
+ /* image is too tall, use less width */
+ iw = iw * h / ih;
+ if (strchr(mode, 'R'))
+ /* right */
+ x = w - iw;
+ else if (!strchr(mode, 'L'))
+ x = (w - iw) / 2;
+ w = ((iw + px - 1) / px) * px;
+ }
+ }
+
+ comm_call(ci->comm2, "scale", p, w, NULL, NULL, h);
+ pw = p->w * px;
+ ph = p->h * py;
+ cix = ci->x;
+ ciy = ci->y;
+ if (cix < 0) {
+ xo -= cix;
+ pw += cix;
+ cix = 0;
+ }
+ if (ciy < 0) {
+ yo -= ciy;
+ ph += ciy;
+ ciy = 0;
+ }
+ if (w - cix <= pw)
+ w -= cix;
+ else
+ w = pw;
+ if (h - ciy <= ph)
+ h -= ciy;
+ else
+ h = ph;
+ comm_call(ci->comm2, "crop", p, w, NULL, NULL, h, NULL, NULL, cix, ciy);
+ comm_call(ci->comm2, "draw", p, x + xo, NULL, NULL, y + yo);
+
+ if (p->cx >= 0) {
+ int rows, cols;
+ char *cl = strchr(mode, ':');
+ if (cl && sscanf(cl, ":%dx%d", &cols, &rows) == 2)
+ comm_call(ci->comm2, "cursor", p,
+ w/cols, NULL, NULL, h/rows, NULL, NULL,
+ p->cx + xo, p->cy + yo);
+ }
+ return 1;
+}
+
+DEF_CMD(window_activate_display)
+{
+ /* Given a display attached to the root, integrate it
+ * into a full initial stack of panes.
+ * The display is the focus of this pane. This doc to
+ * attach there is the focus in the command.
+ */
+ struct pane *disp = ci->home->focus;
+ struct pane *p, *p2;
+ bool display_added = False;
+ char *ip;
+ char *save, *t, *m;
+
+ if (!disp || !list_empty(&disp->children))
+ return Efail;
+ ip = pane_attr_get(disp, "window-initial-panes");
+ if (!ip)
+ return Efail;
+ ip = strdup(ip);
+ p = ci->home;
+
+ for (t = strtok_r(ip, " \t\n", &save);
+ t;
+ t = strtok_r(NULL, " \t\n", &save)) {
+ if (!*t)
+ continue;
+ if (strcmp(t, "DISPLAY") == 0) {
+ if (!display_added) {
+ pane_reparent(disp, p);
+ p = disp;
+ display_added = True;
+ }
+ } else {
+ m = strconcat(NULL, "attach-", t);
+ p2 = call_ret(pane, m, p);
+ free(m);
+ if (p2)
+ p = p2;
+ }
+ }
+ free(ip);
+ if (p && ci->focus != disp)
+ p = home_call_ret(pane, ci->focus, "doc:attach-view", p, 1);
+ if (p)
+ comm_call(ci->comm2, "cb", p);
+ return 1;
+}
+
DEF_CMD(close_notify)
{
struct window_data *wd = ci->home->data;
DEF_CMD(window_attach)
{
- struct window_data *wd;
struct pane *p;
- alloc(wd, pane);
- p = pane_register(ci->focus, 0, &window_handle.c, wd);
- if (!p) {
- unalloc(wd, pane);
+ p = pane_register(pane_root(ci->focus), 0, &window_handle.c);
+ if (!p)
return Efail;
- }
comm_call(ci->comm2, "cb", p);
return 1;
}
{
window_map = key_alloc();
- key_add_prefix(window_map, "window:request:", &request_notify);
- key_add_prefix(window_map, "window:notify:", &send_notify);
+ key_add_prefix(window_map, "Window:request:", &request_notify);
+ key_add_prefix(window_map, "Window:notify:", &send_notify);
- key_add(window_map, "Display:close", &window_close);
+ key_add(window_map, "Window:close", &window_close);
- key_add_prefix(window_map, "window:set:", &window_set);
+ key_add_prefix(window_map, "Window:set:", &window_set);
key_add(window_map, "selection:claim", &selection_claim);
key_add(window_map, "selection:commit", &selection_commit);
key_add(window_map, "selection:discard", &selection_discard);
key_add(window_map, "Notify:Close", &close_notify);
+ key_add(window_map, "Draw:scale-image", &scale_image);
+ key_add(window_map, "Window:activate-display",
+ &window_activate_display);
+
call_comm("global-set-command", ed, &window_attach, 0, NULL,
"attach-window-core");
}