💾 Archived View for gemini.rmf-dev.com › repo › Vaati › cwm › files › f80536018f4a743a7753172d6c99fe… captured on 2023-03-20 at 18:16:14. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

🚧 View Differences

-=-=-=-=-=-=-

0 /*

1 * calmwm - the calm window manager

2 *

3 * Copyright (c) 2004 Martin Murray <mmurray@monkey.org>

4 *

5 * Permission to use, copy, modify, and distribute this software for any

6 * purpose with or without fee is hereby granted, provided that the above

7 * copyright notice and this permission notice appear in all copies.

8 *

9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES

10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF

11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR

12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES

13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN

14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF

15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

16 *

17 * $OpenBSD$

18 */

19

20 #include <sys/types.h>

21 #include <sys/queue.h>

22 #include <sys/stat.h>

23

24 #include <dirent.h>

25 #include <err.h>

26 #include <errno.h>

27 #include <limits.h>

28 #include <paths.h>

29 #include <signal.h>

30 #include <stdio.h>

31 #include <stdlib.h>

32 #include <string.h>

33 #include <unistd.h>

34

35 #include "calmwm.h"

36

37 #define HASH_MARKER "|1|"

38

39 extern sig_atomic_t cwm_status;

40

41 static void kbfunc_amount(int, int, int *, int *);

42 static void kbfunc_client_move_kb(void *, struct cargs *);

43 static void kbfunc_client_move_mb(void *, struct cargs *);

44 static void kbfunc_client_resize_kb(void *, struct cargs *);

45 static void kbfunc_client_resize_mb(void *, struct cargs *);

46

47 void

48 kbfunc_cwm_status(void *ctx, struct cargs *cargs)

49 {

50 cwm_status = cargs->flag;

51 }

52

53 static void

54 kbfunc_amount(int flags, int amt, int *mx, int *my)

55 {

56 #define CWM_FACTOR 10

57

58 if (flags & CWM_BIGAMOUNT)

59 amt *= CWM_FACTOR;

60

61 switch (flags & (CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT)) {

62 case CWM_UP:

63 *my -= amt;

64 break;

65 case CWM_DOWN:

66 *my += amt;

67 break;

68 case CWM_RIGHT:

69 *mx += amt;

70 break;

71 case CWM_LEFT:

72 *mx -= amt;

73 break;

74 }

75 }

76

77 void

78 kbfunc_ptrmove(void *ctx, struct cargs *cargs)

79 {

80 struct screen_ctx *sc = ctx;

81 int x, y;

82 int mx = 0, my = 0;

83

84 kbfunc_amount(cargs->flag, Conf.mamount, &mx, &my);

85

86 xu_ptr_get(sc->rootwin, &x, &y);

87 xu_ptr_set(sc->rootwin, x + mx, y + my);

88 }

89

90 void

91 kbfunc_client_move(void *ctx, struct cargs *cargs)

92 {

93 if (cargs->xev == CWM_XEV_BTN)

94 kbfunc_client_move_mb(ctx, cargs);

95 else

96 kbfunc_client_move_kb(ctx, cargs);

97 }

98

99 void

100 kbfunc_client_resize(void *ctx, struct cargs *cargs)

101 {

102 if (cargs->xev == CWM_XEV_BTN)

103 kbfunc_client_resize_mb(ctx, cargs);

104 else

105 kbfunc_client_resize_kb(ctx, cargs);

106 }

107

108 static void

109 kbfunc_client_move_kb(void *ctx, struct cargs *cargs)

110 {

111 struct client_ctx *cc = ctx;

112 struct screen_ctx *sc = cc->sc;

113 struct geom area;

114 int mx = 0, my = 0;

115

116 if (cc->flags & CLIENT_FREEZE)

117 return;

118

119 kbfunc_amount(cargs->flag, Conf.mamount, &mx, &my);

120

121 cc->geom.x += mx;

122 if (cc->geom.x < -(cc->geom.w + cc->bwidth - 1))

123 cc->geom.x = -(cc->geom.w + cc->bwidth - 1);

124 if (cc->geom.x > (sc->view.w - cc->bwidth - 1))

125 cc->geom.x = sc->view.w - cc->bwidth - 1;

126 cc->geom.y += my;

127 if (cc->geom.y < -(cc->geom.h + cc->bwidth - 1))

128 cc->geom.y = -(cc->geom.h + cc->bwidth - 1);

129 if (cc->geom.y > (sc->view.h - cc->bwidth - 1))

130 cc->geom.y = sc->view.h - cc->bwidth - 1;

131

132 area = screen_area(sc,

133 cc->geom.x + cc->geom.w / 2,

134 cc->geom.y + cc->geom.h / 2, 1);

135 cc->geom.x += client_snapcalc(cc->geom.x,

136 cc->geom.x + cc->geom.w + (cc->bwidth * 2),

137 area.x, area.x + area.w, sc->snapdist);

138 cc->geom.y += client_snapcalc(cc->geom.y,

139 cc->geom.y + cc->geom.h + (cc->bwidth * 2),

140 area.y, area.y + area.h, sc->snapdist);

141

142 client_move(cc);

143 client_ptr_inbound(cc, 1);

144 XSync(X_Dpy, True);

145 }

146

147 static void

148 kbfunc_client_move_mb(void *ctx, struct cargs *cargs)

149 {

150 struct client_ctx *cc = ctx;

151 XEvent ev;

152 Time ltime = 0;

153 struct screen_ctx *sc = cc->sc;

154 struct geom area;

155 int move = 1;

156

157 client_raise(cc);

158

159 if (cc->flags & CLIENT_FREEZE)

160 return;

161

162 client_ptr_inbound(cc, 1);

163

164 if (XGrabPointer(X_Dpy, cc->win, False, MOUSEMASK,

165 GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_MOVE],

166 CurrentTime) != GrabSuccess)

167 return;

168

169 screen_prop_win_create(sc, cc->win);

170 screen_prop_win_draw(sc, "%+5d%+5d", cc->geom.x, cc->geom.y);

171 while (move) {

172 XMaskEvent(X_Dpy, MOUSEMASK, &ev);

173 switch (ev.type) {

174 case MotionNotify:

175 /* not more than 60 times / second */

176 if ((ev.xmotion.time - ltime) <= (1000 / 60))

177 continue;

178 ltime = ev.xmotion.time;

179

180 cc->geom.x = ev.xmotion.x_root - cc->ptr.x - cc->bwidth;

181 cc->geom.y = ev.xmotion.y_root - cc->ptr.y - cc->bwidth;

182

183 area = screen_area(sc,

184 cc->geom.x + cc->geom.w / 2,

185 cc->geom.y + cc->geom.h / 2, 1);

186 cc->geom.x += client_snapcalc(cc->geom.x,

187 cc->geom.x + cc->geom.w + (cc->bwidth * 2),

188 area.x, area.x + area.w, sc->snapdist);

189 cc->geom.y += client_snapcalc(cc->geom.y,

190 cc->geom.y + cc->geom.h + (cc->bwidth * 2),

191 area.y, area.y + area.h, sc->snapdist);

192 client_move(cc);

193 screen_prop_win_draw(sc,

194 "%+5d%+5d", cc->geom.x, cc->geom.y);

195 break;

196 case ButtonRelease:

197 move = 0;

198 break;

199 }

200 }

201 if (ltime)

202 client_move(cc);

203 screen_prop_win_destroy(sc);

204 XUngrabPointer(X_Dpy, CurrentTime);

205 }

206

207 static void

208 kbfunc_client_resize_kb(void *ctx, struct cargs *cargs)

209 {

210 struct client_ctx *cc = ctx;

211 int mx = 0, my = 0;

212 int amt = 1;

213

214 if (cc->flags & CLIENT_FREEZE)

215 return;

216

217 if (!(cc->hint.flags & PResizeInc))

218 amt = Conf.mamount;

219

220 kbfunc_amount(cargs->flag, amt, &mx, &my);

221

222 if ((cc->geom.w += mx * cc->hint.incw) < cc->hint.minw)

223 cc->geom.w = cc->hint.minw;

224 if ((cc->geom.h += my * cc->hint.inch) < cc->hint.minh)

225 cc->geom.h = cc->hint.minh;

226 if (cc->geom.x + cc->geom.w + cc->bwidth - 1 < 0)

227 cc->geom.x = -(cc->geom.w + cc->bwidth - 1);

228 if (cc->geom.y + cc->geom.h + cc->bwidth - 1 < 0)

229 cc->geom.y = -(cc->geom.h + cc->bwidth - 1);

230

231 client_resize(cc, 1);

232 client_ptr_inbound(cc, 1);

233 XSync(X_Dpy, True);

234 }

235

236 static void

237 kbfunc_client_resize_mb(void *ctx, struct cargs *cargs)

238 {

239 struct client_ctx *cc = ctx;

240 XEvent ev;

241 Time ltime = 0;

242 struct screen_ctx *sc = cc->sc;

243 int resize = 1;

244

245 if (cc->flags & CLIENT_FREEZE)

246 return;

247

248 client_raise(cc);

249 client_ptr_save(cc);

250

251 xu_ptr_set(cc->win, cc->geom.w, cc->geom.h);

252

253 if (XGrabPointer(X_Dpy, cc->win, False, MOUSEMASK,

254 GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_RESIZE],

255 CurrentTime) != GrabSuccess)

256 return;

257

258 screen_prop_win_create(sc, cc->win);

259 screen_prop_win_draw(sc, "%4d x %-4d", cc->dim.w, cc->dim.h);

260 while (resize) {

261 XMaskEvent(X_Dpy, MOUSEMASK, &ev);

262 switch (ev.type) {

263 case MotionNotify:

264 /* not more than 60 times / second */

265 if ((ev.xmotion.time - ltime) <= (1000 / 60))

266 continue;

267 ltime = ev.xmotion.time;

268

269 cc->geom.w = ev.xmotion.x;

270 cc->geom.h = ev.xmotion.y;

271 client_apply_sizehints(cc);

272 client_resize(cc, 1);

273 screen_prop_win_draw(sc,

274 "%4d x %-4d", cc->dim.w, cc->dim.h);

275 break;

276 case ButtonRelease:

277 resize = 0;

278 break;

279 }

280 }

281 if (ltime)

282 client_resize(cc, 1);

283 screen_prop_win_destroy(sc);

284 XUngrabPointer(X_Dpy, CurrentTime);

285

286 /* Make sure the pointer stays within the window. */

287 client_ptr_inbound(cc, 0);

288 }

289

290 void

291 kbfunc_client_snap(void *ctx, struct cargs *cargs)

292 {

293 struct client_ctx *cc = ctx;

294 struct screen_ctx *sc = cc->sc;

295 struct geom area;

296 int flags;

297

298 area = screen_area(sc,

299 cc->geom.x + cc->geom.w / 2,

300 cc->geom.y + cc->geom.h / 2, 1);

301

302 flags = cargs->flag;

303 while (flags) {

304 if (flags & CWM_UP) {

305 cc->geom.y = area.y;

306 flags &= ~CWM_UP;

307 }

308 if (flags & CWM_LEFT) {

309 cc->geom.x = area.x;

310 flags &= ~CWM_LEFT;

311 }

312 if (flags & CWM_RIGHT) {

313 cc->geom.x = area.x + area.w - cc->geom.w -

314 (cc->bwidth * 2);

315 flags &= ~CWM_RIGHT;

316 }

317 if (flags & CWM_DOWN) {

318 cc->geom.y = area.y + area.h - cc->geom.h -

319 (cc->bwidth * 2);

320 flags &= ~CWM_DOWN;

321 }

322 }

323 client_move(cc);

324 client_ptr_inbound(cc, 1);

325 }

326

327 void

328 kbfunc_client_close(void *ctx, struct cargs *cargs)

329 {

330 client_close(ctx);

331 }

332

333 void

334 kbfunc_client_lower(void *ctx, struct cargs *cargs)

335 {

336 client_ptr_save(ctx);

337 client_lower(ctx);

338 }

339

340 void

341 kbfunc_client_raise(void *ctx, struct cargs *cargs)

342 {

343 client_raise(ctx);

344 }

345

346 void

347 kbfunc_client_hide(void *ctx, struct cargs *cargs)

348 {

349 client_hide(ctx);

350 }

351

352 void

353 kbfunc_client_toggle_freeze(void *ctx, struct cargs *cargs)

354 {

355 client_toggle_freeze(ctx);

356 }

357

358 void

359 kbfunc_client_toggle_sticky(void *ctx, struct cargs *cargs)

360 {

361 client_toggle_sticky(ctx);

362 }

363

364 void

365 kbfunc_client_toggle_fullscreen(void *ctx, struct cargs *cargs)

366 {

367 client_toggle_fullscreen(ctx);

368 }

369

370 void

371 kbfunc_client_toggle_maximize(void *ctx, struct cargs *cargs)

372 {

373 client_toggle_maximize(ctx);

374 }

375

376 void

377 kbfunc_client_toggle_hmaximize(void *ctx, struct cargs *cargs)

378 {

379 client_toggle_hmaximize(ctx);

380 }

381

382 void

383 kbfunc_client_toggle_vmaximize(void *ctx, struct cargs *cargs)

384 {

385 client_toggle_vmaximize(ctx);

386 }

387

388 void

389 kbfunc_client_htile(void *ctx, struct cargs *cargs)

390 {

391 client_htile(ctx);

392 }

393

394 void

395 kbfunc_client_vtile(void *ctx, struct cargs *cargs)

396 {

397 client_vtile(ctx);

398 }

399

400 void

401 kbfunc_client_cycle(void *ctx, struct cargs *cargs)

402 {

403 struct screen_ctx *sc = ctx;

404 struct client_ctx *newcc, *oldcc, *prevcc;

405 int again = 1, flags = cargs->flag;

406

407 /* For X apps that ignore/steal events. */

408 if (cargs->xev == CWM_XEV_KEY)

409 XGrabKeyboard(X_Dpy, sc->rootwin, True,

410 GrabModeAsync, GrabModeAsync, CurrentTime);

411

412 if (TAILQ_EMPTY(&sc->clientq))

413 return;

414

415 prevcc = TAILQ_FIRST(&sc->clientq);

416 oldcc = client_current(sc);

417 if (oldcc == NULL)

418 oldcc = (flags & CWM_CYCLE_REVERSE) ?

419 TAILQ_LAST(&sc->clientq, client_q) :

420 TAILQ_FIRST(&sc->clientq);

421

422 newcc = oldcc;

423 while (again) {

424 again = 0;

425

426 newcc = (flags & CWM_CYCLE_REVERSE) ? client_prev(newcc) :

427 client_next(newcc);

428

429 /* Only cycle visible and non-ignored windows. */

430 if ((newcc->flags & (CLIENT_SKIP_CYCLE)) ||

431 ((flags & CWM_CYCLE_INGROUP) &&

432 (newcc->gc != oldcc->gc)))

433 again = 1;

434

435 /* Is oldcc the only non-hidden window? */

436 if (newcc == oldcc) {

437 if (again)

438 return; /* No windows visible. */

439 break;

440 }

441 }

442

443 /* Reset when cycling mod is released. XXX I hate this hack */

444 sc->cycling = 1;

445 client_ptr_save(oldcc);

446 client_raise(prevcc);

447 client_raise(newcc);

448 if (!client_inbound(newcc, newcc->ptr.x, newcc->ptr.y)) {

449 newcc->ptr.x = newcc->geom.w / 2;

450 newcc->ptr.y = newcc->geom.h / 2;

451 }

452

453 /* When no client is active, warp pointer to last active. */

454 if (oldcc->flags & (CLIENT_ACTIVE))

455 client_ptr_warp(newcc);

456 else if (oldcc->flags & (CLIENT_SKIP_CYCLE))

457 client_ptr_warp(newcc);

458 else {

459 client_raise(oldcc);

460 client_ptr_warp(oldcc);

461 }

462 }

463

464 void

465 kbfunc_client_toggle_group(void *ctx, struct cargs *cargs)

466 {

467 struct client_ctx *cc = ctx;

468

469 /* For X apps that ignore/steal events. */

470 if (cargs->xev == CWM_XEV_KEY)

471 XGrabKeyboard(X_Dpy, cc->win, True,

472 GrabModeAsync, GrabModeAsync, CurrentTime);

473

474 group_toggle_membership(cc);

475 }

476

477 void

478 kbfunc_client_movetogroup(void *ctx, struct cargs *cargs)

479 {

480 group_movetogroup(ctx, cargs->flag);

481 }

482

483 void

484 kbfunc_group_only(void *ctx, struct cargs *cargs)

485 {

486 group_only(ctx, cargs->flag);

487 }

488

489 void

490 kbfunc_group_last(void *ctx, struct cargs *cargs)

491 {

492 struct screen_ctx *sc = ctx;

493

494 group_only(ctx, sc->group_last->num);

495 }

496

497 void

498 kbfunc_group_toggle(void *ctx, struct cargs *cargs)

499 {

500 group_toggle(ctx, cargs->flag);

501 }

502

503 void

504 kbfunc_group_toggle_all(void *ctx, struct cargs *cargs)

505 {

506 group_toggle_all(ctx);

507 }

508

509 void

510 kbfunc_group_close(void *ctx, struct cargs *cargs)

511 {

512 group_close(ctx, cargs->flag);

513 }

514

515 void

516 kbfunc_group_cycle(void *ctx, struct cargs *cargs)

517 {

518 group_cycle(ctx, cargs->flag);

519 }

520

521 void

522 kbfunc_menu_client(void *ctx, struct cargs *cargs)

523 {

524 struct screen_ctx *sc = ctx;

525 struct client_ctx *cc, *old_cc;

526 struct menu *mi;

527 struct menu_q menuq;

528 int mflags = 0;

529

530 if (cargs->xev == CWM_XEV_BTN)

531 mflags |= CWM_MENU_LIST;

532

533 TAILQ_INIT(&menuq);

534 TAILQ_FOREACH(cc, &sc->clientq, entry) {

535 if ((cargs->flag & CWM_MENU_WINDOW_ALL) ||

536 (cc->flags & CLIENT_HIDDEN))

537 menuq_add(&menuq, cc, NULL);

538 }

539

540 if ((mi = menu_filter(sc, &menuq, "window", NULL, mflags,

541 search_match_client, search_print_client)) != NULL) {

542 cc = (struct client_ctx *)mi->ctx;

543 client_show(cc);

544 if ((old_cc = client_current(sc)) != NULL)

545 client_ptr_save(old_cc);

546 client_ptr_warp(cc);

547 }

548

549 menuq_clear(&menuq);

550 }

551

552 void

553 kbfunc_menu_cmd(void *ctx, struct cargs *cargs)

554 {

555 struct screen_ctx *sc = ctx;

556 struct cmd_ctx *cmd;

557 struct menu *mi;

558 struct menu_q menuq;

559 int mflags = 0;

560

561 if (cargs->xev == CWM_XEV_BTN)

562 mflags |= CWM_MENU_LIST;

563

564 TAILQ_INIT(&menuq);

565 TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {

566 if ((strcmp(cmd->name, "lock") == 0) ||

567 (strcmp(cmd->name, "term") == 0))

568 continue;

569 menuq_add(&menuq, cmd, NULL);

570 }

571

572 if ((mi = menu_filter(sc, &menuq, "application", NULL, mflags,

573 search_match_cmd, search_print_cmd)) != NULL) {

574 cmd = (struct cmd_ctx *)mi->ctx;

575 u_spawn(cmd->path);

576 }

577

578 menuq_clear(&menuq);

579 }

580

581 void

582 kbfunc_menu_group(void *ctx, struct cargs *cargs)

583 {

584 struct screen_ctx *sc = ctx;

585 struct group_ctx *gc;

586 struct menu *mi;

587 struct menu_q menuq;

588 int mflags = 0;

589

590 if (cargs->xev == CWM_XEV_BTN)

591 mflags |= CWM_MENU_LIST;

592

593 TAILQ_INIT(&menuq);

594 TAILQ_FOREACH(gc, &sc->groupq, entry) {

595 if (group_holds_only_sticky(gc))

596 continue;

597 menuq_add(&menuq, gc, NULL);

598 }

599

600 if ((mi = menu_filter(sc, &menuq, "group", NULL, mflags,

601 search_match_group, search_print_group)) != NULL) {

602 gc = (struct group_ctx *)mi->ctx;

603 (group_holds_only_hidden(gc)) ?

604 group_show(gc) : group_hide(gc);

605 }

606

607 menuq_clear(&menuq);

608 }

609

610 void

611 kbfunc_menu_wm(void *ctx, struct cargs *cargs)

612 {

613 struct screen_ctx *sc = ctx;

614 struct cmd_ctx *wm;

615 struct menu *mi;

616 struct menu_q menuq;

617 int mflags = 0;

618

619 if (cargs->xev == CWM_XEV_BTN)

620 mflags |= CWM_MENU_LIST;

621

622 TAILQ_INIT(&menuq);

623 TAILQ_FOREACH(wm, &Conf.wmq, entry)

624 menuq_add(&menuq, wm, NULL);

625

626 if ((mi = menu_filter(sc, &menuq, "wm", NULL, mflags,

627 search_match_wm, search_print_wm)) != NULL) {

628 wm = (struct cmd_ctx *)mi->ctx;

629 free(Conf.wm_argv);

630 Conf.wm_argv = xstrdup(wm->path);

631 cwm_status = CWM_EXEC_WM;

632 }

633

634 menuq_clear(&menuq);

635 }

636

637 void

638 kbfunc_menu_exec(void *ctx, struct cargs *cargs)

639 {

640 #define NPATHS 256

641 struct screen_ctx *sc = ctx;

642 char **ap, *paths[NPATHS], *path, *pathcpy;

643 char tpath[PATH_MAX];

644 struct stat sb;

645 DIR *dirp;

646 struct dirent *dp;

647 struct menu *mi;

648 struct menu_q menuq;

649 int l, i;

650 int mflags = (CWM_MENU_DUMMY | CWM_MENU_FILE);

651

652 TAILQ_INIT(&menuq);

653

654 if ((path = getenv("PATH")) == NULL)

655 path = _PATH_DEFPATH;

656 pathcpy = path = xstrdup(path);

657

658 for (ap = paths; ap < &paths[NPATHS - 1] &&

659 (*ap = strsep(&pathcpy, ":")) != NULL;) {

660 if (**ap != '\0')

661 ap++;

662 }

663 *ap = NULL;

664 for (i = 0; i < NPATHS && paths[i] != NULL; i++) {

665 if ((dirp = opendir(paths[i])) == NULL)

666 continue;

667

668 while ((dp = readdir(dirp)) != NULL) {

669 (void)memset(tpath, '\0', sizeof(tpath));

670 l = snprintf(tpath, sizeof(tpath), "%s/%s", paths[i],

671 dp->d_name);

672 if (l == -1 || l >= sizeof(tpath))

673 continue;

674 /* Skip everything but regular files and symlinks. */

675 if (dp->d_type != DT_REG && dp->d_type != DT_LNK) {

676 /* lstat(2) in case d_type isn't supported. */

677 if (lstat(tpath, &sb) == -1)

678 continue;

679 if (!S_ISREG(sb.st_mode) &&

680 !S_ISLNK(sb.st_mode))

681 continue;

682 }

683 if (access(tpath, X_OK) == 0)

684 menuq_add(&menuq, NULL, "%s", dp->d_name);

685 }

686 (void)closedir(dirp);

687 }

688 free(path);

689

690 if ((mi = menu_filter(sc, &menuq, "exec", NULL, mflags,

691 search_match_exec, search_print_text)) != NULL) {

692 if (mi->text[0] == '\0')

693 goto out;

694 u_spawn(mi->text);

695 }

696 out:

697 if (mi != NULL && mi->dummy)

698 free(mi);

699 menuq_clear(&menuq);

700 }

701

702 void

703 kbfunc_menu_ssh(void *ctx, struct cargs *cargs)

704 {

705 struct screen_ctx *sc = ctx;

706 struct cmd_ctx *cmd;

707 struct menu *mi;

708 struct menu_q menuq;

709 FILE *fp;

710 char *buf, *lbuf, *p;

711 char hostbuf[HOST_NAME_MAX+1];

712 char path[PATH_MAX];

713 int l;

714 size_t len;

715 ssize_t slen;

716 int mflags = (CWM_MENU_DUMMY);

717

718 TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {

719 if (strcmp(cmd->name, "term") == 0)

720 break;

721 }

722 TAILQ_INIT(&menuq);

723

724 if ((fp = fopen(Conf.known_hosts, "r")) == NULL) {

725 warn("%s: %s", __func__, Conf.known_hosts);

726 goto menu;

727 }

728

729 lbuf = NULL;

730 len = 0;

731 while ((slen = getline(&lbuf, &len, fp)) != -1) {

732 buf = lbuf;

733 if (buf[slen - 1] == '\n')

734 buf[slen - 1] = '\0';

735

736 /* skip hashed hosts */

737 if (strncmp(buf, HASH_MARKER, strlen(HASH_MARKER)) == 0)

738 continue;

739 for (p = buf; *p != ',' && *p != ' ' && p != buf + slen; p++)

740 ;

741 /* ignore badness */

742 if (p - buf + 1 > sizeof(hostbuf))

743 continue;

744 (void)strlcpy(hostbuf, buf, p - buf + 1);

745 menuq_add(&menuq, NULL, "%s", hostbuf);

746 }

747 free(lbuf);

748 if (ferror(fp))

749 err(1, "%s", path);

750 (void)fclose(fp);

751 menu:

752 if ((mi = menu_filter(sc, &menuq, "ssh", NULL, mflags,

753 search_match_text, search_print_text)) != NULL) {

754 if (mi->text[0] == '\0')

755 goto out;

756 l = snprintf(path, sizeof(path), "%s -T '[ssh] %s' -e ssh %s",

757 cmd->path, mi->text, mi->text);

758 if (l == -1 || l >= sizeof(path))

759 goto out;

760 u_spawn(path);

761 }

762 out:

763 if (mi != NULL && mi->dummy)

764 free(mi);

765 menuq_clear(&menuq);

766 }

767

768 void

769 kbfunc_client_menu_label(void *ctx, struct cargs *cargs)

770 {

771 struct client_ctx *cc = ctx;

772 struct menu *mi;

773 struct menu_q menuq;

774 int mflags = (CWM_MENU_DUMMY);

775

776 TAILQ_INIT(&menuq);

777

778 /* dummy is set, so this will always return */

779 mi = menu_filter(cc->sc, &menuq, "label", cc->label, mflags,

780 search_match_text, search_print_text);

781

782 if (!mi->abort) {

783 free(cc->label);

784 cc->label = xstrdup(mi->text);

785 }

786 free(mi);

787 }

788

789 void

790 kbfunc_exec_cmd(void *ctx, struct cargs *cargs)

791 {

792 u_spawn(cargs->cmd);

793 }

794

795 void

796 kbfunc_exec_term(void *ctx, struct cargs *cargs)

797 {

798 struct cmd_ctx *cmd;

799

800 TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {

801 if (strcmp(cmd->name, "term") == 0)

802 u_spawn(cmd->path);

803 }

804 }

805

806 void

807 kbfunc_exec_lock(void *ctx, struct cargs *cargs)

808 {

809 struct cmd_ctx *cmd;

810

811 TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {

812 if (strcmp(cmd->name, "lock") == 0)

813 u_spawn(cmd->path);

814 }

815 }

816