199e242abSchristos /* $OpenBSD$ */ 2698d5317Sjmmv 3698d5317Sjmmv /* 4f26e8bc9Schristos * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> 5698d5317Sjmmv * 6698d5317Sjmmv * Permission to use, copy, modify, and distribute this software for any 7698d5317Sjmmv * purpose with or without fee is hereby granted, provided that the above 8698d5317Sjmmv * copyright notice and this permission notice appear in all copies. 9698d5317Sjmmv * 10698d5317Sjmmv * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11698d5317Sjmmv * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12698d5317Sjmmv * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13698d5317Sjmmv * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14698d5317Sjmmv * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15698d5317Sjmmv * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16698d5317Sjmmv * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17698d5317Sjmmv */ 18698d5317Sjmmv 19698d5317Sjmmv #include <sys/types.h> 20c7e17de0Schristos #include <sys/wait.h> 21f26e8bc9Schristos #include <sys/uio.h> 22698d5317Sjmmv 2361fba46bSchristos #include <stdlib.h> 24698d5317Sjmmv #include <string.h> 25698d5317Sjmmv #include <time.h> 26698d5317Sjmmv #include <unistd.h> 27698d5317Sjmmv 28698d5317Sjmmv #include "tmux.h" 29698d5317Sjmmv 30e9a2d6faSchristos static void server_destroy_session_group(struct session *); 31698d5317Sjmmv 32698d5317Sjmmv void 33698d5317Sjmmv server_redraw_client(struct client *c) 34698d5317Sjmmv { 350a274e86Schristos c->flags |= CLIENT_ALLREDRAWFLAGS; 36698d5317Sjmmv } 37698d5317Sjmmv 38698d5317Sjmmv void 39698d5317Sjmmv server_status_client(struct client *c) 40698d5317Sjmmv { 410a274e86Schristos c->flags |= CLIENT_REDRAWSTATUS; 42698d5317Sjmmv } 43698d5317Sjmmv 44698d5317Sjmmv void 45698d5317Sjmmv server_redraw_session(struct session *s) 46698d5317Sjmmv { 47698d5317Sjmmv struct client *c; 48698d5317Sjmmv 4999e242abSchristos TAILQ_FOREACH(c, &clients, entry) { 50698d5317Sjmmv if (c->session == s) 51698d5317Sjmmv server_redraw_client(c); 52698d5317Sjmmv } 53698d5317Sjmmv } 54698d5317Sjmmv 55698d5317Sjmmv void 56698d5317Sjmmv server_redraw_session_group(struct session *s) 57698d5317Sjmmv { 58698d5317Sjmmv struct session_group *sg; 59698d5317Sjmmv 60e9a2d6faSchristos if ((sg = session_group_contains(s)) == NULL) 61698d5317Sjmmv server_redraw_session(s); 62698d5317Sjmmv else { 63698d5317Sjmmv TAILQ_FOREACH(s, &sg->sessions, gentry) 64698d5317Sjmmv server_redraw_session(s); 65698d5317Sjmmv } 66698d5317Sjmmv } 67698d5317Sjmmv 68698d5317Sjmmv void 69698d5317Sjmmv server_status_session(struct session *s) 70698d5317Sjmmv { 71698d5317Sjmmv struct client *c; 72698d5317Sjmmv 7399e242abSchristos TAILQ_FOREACH(c, &clients, entry) { 74698d5317Sjmmv if (c->session == s) 75698d5317Sjmmv server_status_client(c); 76698d5317Sjmmv } 77698d5317Sjmmv } 78698d5317Sjmmv 79698d5317Sjmmv void 80698d5317Sjmmv server_status_session_group(struct session *s) 81698d5317Sjmmv { 82698d5317Sjmmv struct session_group *sg; 83698d5317Sjmmv 84e9a2d6faSchristos if ((sg = session_group_contains(s)) == NULL) 85698d5317Sjmmv server_status_session(s); 86698d5317Sjmmv else { 87698d5317Sjmmv TAILQ_FOREACH(s, &sg->sessions, gentry) 88698d5317Sjmmv server_status_session(s); 89698d5317Sjmmv } 90698d5317Sjmmv } 91698d5317Sjmmv 92698d5317Sjmmv void 93698d5317Sjmmv server_redraw_window(struct window *w) 94698d5317Sjmmv { 95698d5317Sjmmv struct client *c; 96698d5317Sjmmv 9799e242abSchristos TAILQ_FOREACH(c, &clients, entry) { 9899e242abSchristos if (c->session != NULL && c->session->curw->window == w) 99698d5317Sjmmv server_redraw_client(c); 100698d5317Sjmmv } 101698d5317Sjmmv } 102698d5317Sjmmv 103698d5317Sjmmv void 104698d5317Sjmmv server_redraw_window_borders(struct window *w) 105698d5317Sjmmv { 106698d5317Sjmmv struct client *c; 107698d5317Sjmmv 10899e242abSchristos TAILQ_FOREACH(c, &clients, entry) { 10999e242abSchristos if (c->session != NULL && c->session->curw->window == w) 1100a274e86Schristos c->flags |= CLIENT_REDRAWBORDERS; 111698d5317Sjmmv } 112698d5317Sjmmv } 113698d5317Sjmmv 114698d5317Sjmmv void 115698d5317Sjmmv server_status_window(struct window *w) 116698d5317Sjmmv { 117698d5317Sjmmv struct session *s; 118698d5317Sjmmv 119698d5317Sjmmv /* 120698d5317Sjmmv * This is slightly different. We want to redraw the status line of any 121698d5317Sjmmv * clients containing this window rather than anywhere it is the 122698d5317Sjmmv * current window. 123698d5317Sjmmv */ 124698d5317Sjmmv 125698d5317Sjmmv RB_FOREACH(s, sessions, &sessions) { 12699e242abSchristos if (session_has(s, w)) 127698d5317Sjmmv server_status_session(s); 128698d5317Sjmmv } 129698d5317Sjmmv } 130698d5317Sjmmv 131698d5317Sjmmv void 132698d5317Sjmmv server_lock(void) 133698d5317Sjmmv { 134698d5317Sjmmv struct client *c; 135698d5317Sjmmv 13699e242abSchristos TAILQ_FOREACH(c, &clients, entry) { 13799e242abSchristos if (c->session != NULL) 138698d5317Sjmmv server_lock_client(c); 139698d5317Sjmmv } 140698d5317Sjmmv } 141698d5317Sjmmv 142698d5317Sjmmv void 143698d5317Sjmmv server_lock_session(struct session *s) 144698d5317Sjmmv { 145698d5317Sjmmv struct client *c; 146698d5317Sjmmv 14799e242abSchristos TAILQ_FOREACH(c, &clients, entry) { 14899e242abSchristos if (c->session == s) 149698d5317Sjmmv server_lock_client(c); 150698d5317Sjmmv } 151698d5317Sjmmv } 152698d5317Sjmmv 153698d5317Sjmmv void 154698d5317Sjmmv server_lock_client(struct client *c) 155698d5317Sjmmv { 156698d5317Sjmmv const char *cmd; 15761fba46bSchristos 15861fba46bSchristos if (c->flags & CLIENT_CONTROL) 15961fba46bSchristos return; 160698d5317Sjmmv 161698d5317Sjmmv if (c->flags & CLIENT_SUSPENDED) 162698d5317Sjmmv return; 163698d5317Sjmmv 164f26e8bc9Schristos cmd = options_get_string(c->session->options, "lock-command"); 165fe99a117Schristos if (*cmd == '\0' || strlen(cmd) + 1 > MAX_IMSGSIZE - IMSG_HEADER_SIZE) 166698d5317Sjmmv return; 167698d5317Sjmmv 168698d5317Sjmmv tty_stop_tty(&c->tty); 169698d5317Sjmmv tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_SMCUP)); 170698d5317Sjmmv tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_CLEAR)); 17161fba46bSchristos tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_E3)); 172698d5317Sjmmv 173698d5317Sjmmv c->flags |= CLIENT_SUSPENDED; 174fe99a117Schristos proc_send(c->peer, MSG_LOCK, -1, cmd, strlen(cmd) + 1); 175698d5317Sjmmv } 176698d5317Sjmmv 177698d5317Sjmmv void 178c7e17de0Schristos server_kill_pane(struct window_pane *wp) 179c7e17de0Schristos { 180c7e17de0Schristos struct window *w = wp->window; 181c7e17de0Schristos 182c7e17de0Schristos if (window_count_panes(w) == 1) { 183e271dbb8Schristos server_kill_window(w, 1); 184c7e17de0Schristos recalculate_sizes(); 185c7e17de0Schristos } else { 186c7e17de0Schristos server_unzoom_window(w); 187e271dbb8Schristos server_client_remove_pane(wp); 188c7e17de0Schristos layout_close_pane(wp); 189c7e17de0Schristos window_remove_pane(w, wp); 190c7e17de0Schristos server_redraw_window(w); 191c7e17de0Schristos } 192c7e17de0Schristos } 193c7e17de0Schristos 194c7e17de0Schristos void 195e271dbb8Schristos server_kill_window(struct window *w, int renumber) 196698d5317Sjmmv { 197e271dbb8Schristos struct session *s, *s1; 198698d5317Sjmmv struct winlink *wl; 199698d5317Sjmmv 200e271dbb8Schristos RB_FOREACH_SAFE(s, sessions, &sessions, s1) { 20199e242abSchristos if (!session_has(s, w)) 202698d5317Sjmmv continue; 203e271dbb8Schristos 20499e242abSchristos server_unzoom_window(w); 205698d5317Sjmmv while ((wl = winlink_find_by_window(&s->windows, w)) != NULL) { 206698d5317Sjmmv if (session_detach(s, wl)) { 207698d5317Sjmmv server_destroy_session_group(s); 208698d5317Sjmmv break; 209f844e94eSwiz } 210698d5317Sjmmv server_redraw_session_group(s); 211698d5317Sjmmv } 21261fba46bSchristos 213e271dbb8Schristos if (renumber) 214e271dbb8Schristos server_renumber_session(s); 215e271dbb8Schristos } 216e271dbb8Schristos recalculate_sizes(); 217e271dbb8Schristos } 218e271dbb8Schristos 219e271dbb8Schristos void 220e271dbb8Schristos server_renumber_session(struct session *s) 221e271dbb8Schristos { 222e271dbb8Schristos struct session_group *sg; 223e271dbb8Schristos 224f26e8bc9Schristos if (options_get_number(s->options, "renumber-windows")) { 225e9a2d6faSchristos if ((sg = session_group_contains(s)) != NULL) { 226e271dbb8Schristos TAILQ_FOREACH(s, &sg->sessions, gentry) 227e271dbb8Schristos session_renumber_windows(s); 22861fba46bSchristos } else 22961fba46bSchristos session_renumber_windows(s); 230698d5317Sjmmv } 231698d5317Sjmmv } 232e271dbb8Schristos 233e271dbb8Schristos void 234e271dbb8Schristos server_renumber_all(void) 235e271dbb8Schristos { 236e271dbb8Schristos struct session *s; 237e271dbb8Schristos 238e271dbb8Schristos RB_FOREACH(s, sessions, &sessions) 239e271dbb8Schristos server_renumber_session(s); 24061fba46bSchristos } 241698d5317Sjmmv 242698d5317Sjmmv int 243698d5317Sjmmv server_link_window(struct session *src, struct winlink *srcwl, 24499e242abSchristos struct session *dst, int dstidx, int killflag, int selectflag, 24599e242abSchristos char **cause) 246698d5317Sjmmv { 247698d5317Sjmmv struct winlink *dstwl; 248698d5317Sjmmv struct session_group *srcsg, *dstsg; 249698d5317Sjmmv 250e9a2d6faSchristos srcsg = session_group_contains(src); 251e9a2d6faSchristos dstsg = session_group_contains(dst); 252698d5317Sjmmv if (src != dst && srcsg != NULL && dstsg != NULL && srcsg == dstsg) { 253698d5317Sjmmv xasprintf(cause, "sessions are grouped"); 254698d5317Sjmmv return (-1); 255698d5317Sjmmv } 256698d5317Sjmmv 257698d5317Sjmmv dstwl = NULL; 258698d5317Sjmmv if (dstidx != -1) 259698d5317Sjmmv dstwl = winlink_find_by_index(&dst->windows, dstidx); 260698d5317Sjmmv if (dstwl != NULL) { 261698d5317Sjmmv if (dstwl->window == srcwl->window) { 262698d5317Sjmmv xasprintf(cause, "same index: %d", dstidx); 263698d5317Sjmmv return (-1); 264698d5317Sjmmv } 265698d5317Sjmmv if (killflag) { 266698d5317Sjmmv /* 267698d5317Sjmmv * Can't use session_detach as it will destroy session 268698d5317Sjmmv * if this makes it empty. 269698d5317Sjmmv */ 270e9a2d6faSchristos notify_session_window("window-unlinked", dst, 271e9a2d6faSchristos dstwl->window); 272698d5317Sjmmv dstwl->flags &= ~WINLINK_ALERTFLAGS; 273698d5317Sjmmv winlink_stack_remove(&dst->lastw, dstwl); 274698d5317Sjmmv winlink_remove(&dst->windows, dstwl); 275698d5317Sjmmv 276698d5317Sjmmv /* Force select/redraw if current. */ 277698d5317Sjmmv if (dstwl == dst->curw) { 278698d5317Sjmmv selectflag = 1; 279698d5317Sjmmv dst->curw = NULL; 280698d5317Sjmmv } 281698d5317Sjmmv } 282698d5317Sjmmv } 283698d5317Sjmmv 284698d5317Sjmmv if (dstidx == -1) 285f26e8bc9Schristos dstidx = -1 - options_get_number(dst->options, "base-index"); 286698d5317Sjmmv dstwl = session_attach(dst, srcwl->window, dstidx, cause); 287698d5317Sjmmv if (dstwl == NULL) 288698d5317Sjmmv return (-1); 289698d5317Sjmmv 290698d5317Sjmmv if (selectflag) 291698d5317Sjmmv session_select(dst, dstwl->idx); 292698d5317Sjmmv server_redraw_session_group(dst); 293698d5317Sjmmv 294698d5317Sjmmv return (0); 295698d5317Sjmmv } 296698d5317Sjmmv 297698d5317Sjmmv void 298698d5317Sjmmv server_unlink_window(struct session *s, struct winlink *wl) 299698d5317Sjmmv { 300698d5317Sjmmv if (session_detach(s, wl)) 301698d5317Sjmmv server_destroy_session_group(s); 302698d5317Sjmmv else 303698d5317Sjmmv server_redraw_session_group(s); 304698d5317Sjmmv } 305698d5317Sjmmv 306698d5317Sjmmv void 307e9a2d6faSchristos server_destroy_pane(struct window_pane *wp, int notify) 308698d5317Sjmmv { 309698d5317Sjmmv struct window *w = wp->window; 31061fba46bSchristos struct screen_write_ctx ctx; 31161fba46bSchristos struct grid_cell gc; 312e271dbb8Schristos int remain_on_exit; 31346548964Swiz const char *s; 31446548964Swiz char *expanded; 31546548964Swiz u_int sx = screen_size_x(&wp->base); 31646548964Swiz u_int sy = screen_size_y(&wp->base); 317698d5317Sjmmv 318698d5317Sjmmv if (wp->fd != -1) { 31999e242abSchristos #ifdef HAVE_UTEMPTER 32099e242abSchristos utempter_remove_record(wp->fd); 32199e242abSchristos #endif 322698d5317Sjmmv bufferevent_free(wp->event); 3230a274e86Schristos wp->event = NULL; 32461fba46bSchristos close(wp->fd); 325698d5317Sjmmv wp->fd = -1; 326698d5317Sjmmv } 327698d5317Sjmmv 328e271dbb8Schristos remain_on_exit = options_get_number(wp->options, "remain-on-exit"); 329e271dbb8Schristos if (remain_on_exit != 0 && (~wp->flags & PANE_STATUSREADY)) 330698d5317Sjmmv return; 331e271dbb8Schristos switch (remain_on_exit) { 332e271dbb8Schristos case 0: 333e271dbb8Schristos break; 334e271dbb8Schristos case 2: 335e271dbb8Schristos if (WIFEXITED(wp->status) && WEXITSTATUS(wp->status) == 0) 336e271dbb8Schristos break; 337e271dbb8Schristos /* FALLTHROUGH */ 338e271dbb8Schristos case 1: 339c7e17de0Schristos if (wp->flags & PANE_STATUSDRAWN) 340c7e17de0Schristos return; 341c7e17de0Schristos wp->flags |= PANE_STATUSDRAWN; 342c7e17de0Schristos 34346548964Swiz gettimeofday(&wp->dead_time, NULL); 344e9a2d6faSchristos if (notify) 345e9a2d6faSchristos notify_pane("pane-died", wp); 346e9a2d6faSchristos 34746548964Swiz s = options_get_string(wp->options, "remain-on-exit-format"); 34846548964Swiz if (*s != '\0') { 349e271dbb8Schristos screen_write_start_pane(&ctx, wp, &wp->base); 35046548964Swiz screen_write_scrollregion(&ctx, 0, sy - 1); 35146548964Swiz screen_write_cursormove(&ctx, 0, sy - 1, 0); 352fe99a117Schristos screen_write_linefeed(&ctx, 1, 8); 35361fba46bSchristos memcpy(&gc, &grid_default_cell, sizeof gc); 354c7e17de0Schristos 35546548964Swiz expanded = format_single(NULL, s, NULL, NULL, NULL, wp); 35646548964Swiz format_draw(&ctx, &gc, sx, expanded, NULL, 0); 35746548964Swiz free(expanded); 358c7e17de0Schristos 35961fba46bSchristos screen_write_stop(&ctx); 36046548964Swiz } 36146548964Swiz wp->base.mode &= ~MODE_CURSOR; 36246548964Swiz 36361fba46bSchristos wp->flags |= PANE_REDRAW; 36461fba46bSchristos return; 36561fba46bSchristos } 366698d5317Sjmmv 367e9a2d6faSchristos if (notify) 368e9a2d6faSchristos notify_pane("pane-exited", wp); 369e9a2d6faSchristos 37061fba46bSchristos server_unzoom_window(w); 371e271dbb8Schristos server_client_remove_pane(wp); 372698d5317Sjmmv layout_close_pane(wp); 373698d5317Sjmmv window_remove_pane(w, wp); 374698d5317Sjmmv 375698d5317Sjmmv if (TAILQ_EMPTY(&w->panes)) 376e271dbb8Schristos server_kill_window(w, 1); 377698d5317Sjmmv else 378698d5317Sjmmv server_redraw_window(w); 379698d5317Sjmmv } 380698d5317Sjmmv 381e9a2d6faSchristos static void 382698d5317Sjmmv server_destroy_session_group(struct session *s) 383698d5317Sjmmv { 384698d5317Sjmmv struct session_group *sg; 38561fba46bSchristos struct session *s1; 386698d5317Sjmmv 387f844e94eSwiz if ((sg = session_group_contains(s)) == NULL) { 388698d5317Sjmmv server_destroy_session(s); 389f844e94eSwiz session_destroy(s, 1, __func__); 390f844e94eSwiz } else { 39161fba46bSchristos TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) { 392698d5317Sjmmv server_destroy_session(s); 39330744affSchristos session_destroy(s, 1, __func__); 39461fba46bSchristos } 395698d5317Sjmmv } 396698d5317Sjmmv } 397698d5317Sjmmv 398e9a2d6faSchristos static struct session * 399f844e94eSwiz server_find_session(struct session *s, 400f844e94eSwiz int (*f)(struct session *, struct session *)) 401698d5317Sjmmv { 402e271dbb8Schristos struct session *s_loop, *s_out = NULL; 403698d5317Sjmmv 404698d5317Sjmmv RB_FOREACH(s_loop, sessions, &sessions) { 405f844e94eSwiz if (s_loop != s && (s_out == NULL || f(s_loop, s_out))) 406698d5317Sjmmv s_out = s_loop; 407698d5317Sjmmv } 408698d5317Sjmmv return (s_out); 409698d5317Sjmmv } 410698d5317Sjmmv 411f844e94eSwiz static int 412f844e94eSwiz server_newer_session(struct session *s_loop, struct session *s_out) 413e271dbb8Schristos { 414*890b6d91Swiz return (timercmp(&s_loop->activity_time, &s_out->activity_time, >)); 415e271dbb8Schristos } 416f844e94eSwiz 417f844e94eSwiz static int 418f844e94eSwiz server_newer_detached_session(struct session *s_loop, struct session *s_out) 419f844e94eSwiz { 420f844e94eSwiz if (s_loop->attached) 421f844e94eSwiz return (0); 422f844e94eSwiz return (server_newer_session(s_loop, s_out)); 423e271dbb8Schristos } 424e271dbb8Schristos 425698d5317Sjmmv void 426698d5317Sjmmv server_destroy_session(struct session *s) 427698d5317Sjmmv { 428698d5317Sjmmv struct client *c; 429f844e94eSwiz struct session *s_new = NULL; 430e271dbb8Schristos int detach_on_destroy; 431698d5317Sjmmv 432e271dbb8Schristos detach_on_destroy = options_get_number(s->options, "detach-on-destroy"); 433e271dbb8Schristos if (detach_on_destroy == 0) 434f844e94eSwiz s_new = server_find_session(s, server_newer_session); 435e271dbb8Schristos else if (detach_on_destroy == 2) 436f844e94eSwiz s_new = server_find_session(s, server_newer_detached_session); 437f844e94eSwiz else if (detach_on_destroy == 3) 438f844e94eSwiz s_new = session_previous_session(s); 439f844e94eSwiz else if (detach_on_destroy == 4) 440f844e94eSwiz s_new = session_next_session(s); 441f844e94eSwiz if (s_new == s) 442698d5317Sjmmv s_new = NULL; 44399e242abSchristos TAILQ_FOREACH(c, &clients, entry) { 44499e242abSchristos if (c->session != s) 445698d5317Sjmmv continue; 446f844e94eSwiz c->session = NULL; 447f844e94eSwiz c->last_session = NULL; 44846548964Swiz server_client_set_session(c, s_new); 44946548964Swiz if (s_new == NULL) 450698d5317Sjmmv c->flags |= CLIENT_EXIT; 451698d5317Sjmmv } 452698d5317Sjmmv recalculate_sizes(); 453698d5317Sjmmv } 454698d5317Sjmmv 455698d5317Sjmmv void 456698d5317Sjmmv server_check_unattached(void) 457698d5317Sjmmv { 458698d5317Sjmmv struct session *s; 459f844e94eSwiz struct session_group *sg; 460698d5317Sjmmv 461698d5317Sjmmv /* 462698d5317Sjmmv * If any sessions are no longer attached and have destroy-unattached 463698d5317Sjmmv * set, collect them. 464698d5317Sjmmv */ 465698d5317Sjmmv RB_FOREACH(s, sessions, &sessions) { 4660a274e86Schristos if (s->attached != 0) 467698d5317Sjmmv continue; 468f844e94eSwiz switch (options_get_number(s->options, "destroy-unattached")) { 469f844e94eSwiz case 0: /* off */ 470f844e94eSwiz continue; 471f844e94eSwiz case 1: /* on */ 472f844e94eSwiz break; 473f844e94eSwiz case 2: /* keep-last */ 474f844e94eSwiz sg = session_group_contains(s); 475f844e94eSwiz if (sg == NULL || session_group_count(sg) <= 1) 476f844e94eSwiz continue; 477f844e94eSwiz break; 478f844e94eSwiz case 3: /* keep-group */ 479f844e94eSwiz sg = session_group_contains(s); 480f844e94eSwiz if (sg != NULL && session_group_count(sg) == 1) 481f844e94eSwiz continue; 482f844e94eSwiz break; 483f844e94eSwiz } 48430744affSchristos session_destroy(s, 1, __func__); 485698d5317Sjmmv } 486698d5317Sjmmv } 487698d5317Sjmmv 48861fba46bSchristos void 48961fba46bSchristos server_unzoom_window(struct window *w) 49061fba46bSchristos { 491*890b6d91Swiz if (window_unzoom(w, 1) == 0) 49261fba46bSchristos server_redraw_window(w); 49399e242abSchristos } 494