Annotation of sys/dev/wscons/wsdisplay.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: wsdisplay.c,v 1.81 2007/07/25 23:11:52 art Exp $ */
! 2: /* $NetBSD: wsdisplay.c,v 1.82 2005/02/27 00:27:52 perry Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Christopher G. Demetriou
! 18: * for the NetBSD Project.
! 19: * 4. The name of the author may not be used to endorse or promote products
! 20: * derived from this software without specific prior written permission
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 32: */
! 33:
! 34: #ifndef SMALL_KERNEL
! 35: #define WSMOUSED_SUPPORT
! 36: #define BURNER_SUPPORT
! 37: #define SCROLLBACK_SUPPORT
! 38: #endif
! 39:
! 40: #include <sys/param.h>
! 41: #include <sys/conf.h>
! 42: #include <sys/device.h>
! 43: #include <sys/ioctl.h>
! 44: #include <sys/kernel.h>
! 45: #include <sys/proc.h>
! 46: #include <sys/malloc.h>
! 47: #include <sys/syslog.h>
! 48: #include <sys/systm.h>
! 49: #include <sys/tty.h>
! 50: #include <sys/signalvar.h>
! 51: #include <sys/errno.h>
! 52: #include <sys/fcntl.h>
! 53: #include <sys/vnode.h>
! 54: #include <sys/timeout.h>
! 55: #include <sys/poll.h>
! 56:
! 57: #include <dev/wscons/wsconsio.h>
! 58: #include <dev/wscons/wsdisplayvar.h>
! 59: #include <dev/wscons/wsksymvar.h>
! 60: #include <dev/wscons/wsksymdef.h>
! 61: #include <dev/wscons/wsemulvar.h>
! 62: #include <dev/wscons/wscons_callbacks.h>
! 63: #include <dev/cons.h>
! 64:
! 65: #include "wsdisplay.h"
! 66: #include "wskbd.h"
! 67: #include "wsmouse.h"
! 68: #include "wsmux.h"
! 69:
! 70: #if NWSKBD > 0
! 71: #include <dev/wscons/wseventvar.h>
! 72: #include <dev/wscons/wsmuxvar.h>
! 73: #endif
! 74:
! 75: #if NWSMOUSE > 0
! 76: #include <dev/wscons/wsmousevar.h>
! 77: #endif
! 78:
! 79: #include "wsmoused.h"
! 80:
! 81: #if NWSMOUSE > 0
! 82: extern struct cfdriver wsmouse_cd;
! 83: #endif /* NWSMOUSE > 0 */
! 84:
! 85: struct wsscreen_internal {
! 86: const struct wsdisplay_emulops *emulops;
! 87: void *emulcookie;
! 88:
! 89: const struct wsscreen_descr *scrdata;
! 90:
! 91: const struct wsemul_ops *wsemul;
! 92: void *wsemulcookie;
! 93: };
! 94:
! 95: struct wsscreen {
! 96: struct wsscreen_internal *scr_dconf;
! 97:
! 98: struct tty *scr_tty;
! 99: int scr_hold_screen; /* hold tty output */
! 100:
! 101: int scr_flags;
! 102: #define SCR_OPEN 1 /* is it open? */
! 103: #define SCR_WAITACTIVE 2 /* someone waiting on activation */
! 104: #define SCR_GRAPHICS 4 /* graphics mode, no text (emulation) output */
! 105: #define SCR_DUMBFB 8 /* in use as dumb fb (iff SCR_GRAPHICS) */
! 106:
! 107: #ifdef WSDISPLAY_COMPAT_USL
! 108: const struct wscons_syncops *scr_syncops;
! 109: void *scr_synccookie;
! 110: #endif
! 111:
! 112: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 113: int scr_rawkbd;
! 114: #endif
! 115:
! 116: struct wsdisplay_softc *sc;
! 117:
! 118: #ifdef WSMOUSED_SUPPORT
! 119: /* mouse console support via wsmoused(8) */
! 120: unsigned short mouse; /* mouse cursor position */
! 121: unsigned short cursor; /* selection cursor position (if
! 122: different from mouse cursor pos) */
! 123: unsigned short cpy_start; /* position of the copy start mark*/
! 124: unsigned short cpy_end; /* position of the copy end mark */
! 125: unsigned short orig_start; /* position of the original sel. start*/
! 126: unsigned short orig_end; /* position of the original sel. end */
! 127: #define MOUSE_VISIBLE (1 << 0) /* flag, the mouse cursor is visible */
! 128: #define SEL_EXISTS (1 << 1) /* flag, a selection exists */
! 129: #define SEL_IN_PROGRESS (1 << 2) /* flag, a selection is in progress */
! 130: #define SEL_EXT_AFTER (1 << 3) /* flag, selection is extended after */
! 131: #define BLANK_TO_EOL (1 << 4) /* flag, there are only blanks
! 132: characters to eol */
! 133: #define SEL_BY_CHAR (1 << 5) /* flag, select character by character*/
! 134: #define SEL_BY_WORD (1 << 6) /* flag, select word by word */
! 135: #define SEL_BY_LINE (1 << 7) /* flag, select line by line */
! 136:
! 137: #define IS_MOUSE_VISIBLE(ws) ((ws)->mouse_flags & MOUSE_VISIBLE)
! 138: #define IS_SEL_EXISTS(ws) ((ws)->mouse_flags & SEL_EXISTS)
! 139: #define IS_SEL_IN_PROGRESS(ws) ((ws)->mouse_flags & SEL_IN_PROGRESS)
! 140: #define IS_SEL_EXT_AFTER(ws) ((ws)->mouse_flags & SEL_EXT_AFTER)
! 141: #define IS_BLANK_TO_EOL(ws) ((ws)->mouse_flags & BLANK_TO_EOL)
! 142: #define IS_SEL_BY_CHAR(ws) ((ws)->mouse_flags & SEL_BY_CHAR)
! 143: #define IS_SEL_BY_WORD(ws) ((ws)->mouse_flags & SEL_BY_WORD)
! 144: #define IS_SEL_BY_LINE(ws) ((ws)->mouse_flags & SEL_BY_LINE)
! 145: unsigned char mouse_flags; /* flags, status of the mouse */
! 146: #endif /* WSMOUSED_SUPPORT */
! 147: };
! 148:
! 149: struct wsscreen *wsscreen_attach(struct wsdisplay_softc *, int, const char *,
! 150: const struct wsscreen_descr *, void *, int, int, long);
! 151: void wsscreen_detach(struct wsscreen *);
! 152: int wsdisplay_addscreen(struct wsdisplay_softc *, int, const char *,
! 153: const char *);
! 154: int wsdisplay_getscreen(struct wsdisplay_softc *,
! 155: struct wsdisplay_addscreendata *);
! 156: void wsdisplay_shutdownhook(void *);
! 157: void wsdisplay_addscreen_print(struct wsdisplay_softc *, int, int);
! 158: void wsdisplay_closescreen(struct wsdisplay_softc *, struct wsscreen *);
! 159: int wsdisplay_delscreen(struct wsdisplay_softc *, int, int);
! 160: void wsdisplay_burner(void *v);
! 161:
! 162: struct wsdisplay_softc {
! 163: struct device sc_dv;
! 164:
! 165: const struct wsdisplay_accessops *sc_accessops;
! 166: void *sc_accesscookie;
! 167:
! 168: const struct wsscreen_list *sc_scrdata;
! 169:
! 170: struct wsscreen *sc_scr[WSDISPLAY_MAXSCREEN];
! 171: int sc_focusidx; /* available only if sc_focus isn't null */
! 172: struct wsscreen *sc_focus;
! 173:
! 174: #ifdef BURNER_SUPPORT
! 175: struct timeout sc_burner;
! 176: int sc_burnoutintvl;
! 177: int sc_burninintvl;
! 178: int sc_burnout;
! 179: int sc_burnman;
! 180: int sc_burnflags;
! 181: #endif
! 182:
! 183: struct wsdisplay_font sc_fonts[WSDISPLAY_MAXFONT];
! 184:
! 185: int sc_isconsole;
! 186:
! 187: int sc_flags;
! 188: #define SC_SWITCHPENDING 1
! 189: int sc_screenwanted, sc_oldscreen; /* valid with SC_SWITCHPENDING */
! 190:
! 191: #if NWSKBD > 0
! 192: struct wsevsrc *sc_input;
! 193: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 194: int sc_rawkbd;
! 195: #endif
! 196: #endif /* NWSKBD > 0 */
! 197:
! 198: #ifdef WSMOUSED_SUPPORT
! 199: dev_t wsmoused_dev; /* device opened by wsmoused(8), when active */
! 200: int wsmoused_sleep; /* true when wsmoused(8) is sleeping */
! 201: #endif
! 202: };
! 203:
! 204: extern struct cfdriver wsdisplay_cd;
! 205:
! 206: /* Autoconfiguration definitions. */
! 207: int wsdisplay_emul_match(struct device *, void *, void *);
! 208: void wsdisplay_emul_attach(struct device *, struct device *, void *);
! 209: int wsdisplay_emul_detach(struct device *, int);
! 210:
! 211: struct cfdriver wsdisplay_cd = {
! 212: NULL, "wsdisplay", DV_TTY
! 213: };
! 214:
! 215: struct cfattach wsdisplay_emul_ca = {
! 216: sizeof(struct wsdisplay_softc), wsdisplay_emul_match,
! 217: wsdisplay_emul_attach, wsdisplay_emul_detach
! 218: };
! 219:
! 220: void wsdisplaystart(struct tty *);
! 221: int wsdisplayparam(struct tty *, struct termios *);
! 222:
! 223: /* Internal macros, functions, and variables. */
! 224: #define WSDISPLAYUNIT(dev) (minor(dev) >> 8)
! 225: #define WSDISPLAYSCREEN(dev) (minor(dev) & 0xff)
! 226: #define ISWSDISPLAYCTL(dev) (WSDISPLAYSCREEN(dev) == 255)
! 227: #define WSDISPLAYMINOR(unit, screen) (((unit) << 8) | (screen))
! 228:
! 229: #define WSSCREEN_HAS_TTY(scr) ((scr)->scr_tty != NULL)
! 230:
! 231: void wsdisplay_common_attach(struct wsdisplay_softc *sc,
! 232: int console, int mux, const struct wsscreen_list *,
! 233: const struct wsdisplay_accessops *accessops,
! 234: void *accesscookie, u_int defaultscreens);
! 235: int wsdisplay_common_detach(struct wsdisplay_softc *, int);
! 236:
! 237: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 238: int wsdisplay_update_rawkbd(struct wsdisplay_softc *, struct wsscreen *);
! 239: #endif
! 240:
! 241: int wsdisplay_console_initted;
! 242: struct wsdisplay_softc *wsdisplay_console_device;
! 243: struct wsscreen_internal wsdisplay_console_conf;
! 244:
! 245: int wsdisplay_getc_dummy(dev_t);
! 246: void wsdisplay_pollc(dev_t, int);
! 247:
! 248: int wsdisplay_cons_pollmode;
! 249: void (*wsdisplay_cons_kbd_pollc)(dev_t, int);
! 250:
! 251: struct consdev wsdisplay_cons = {
! 252: NULL, NULL, wsdisplay_getc_dummy, wsdisplay_cnputc,
! 253: wsdisplay_pollc, NULL, NODEV, CN_NORMAL
! 254: };
! 255:
! 256: #ifndef WSDISPLAY_DEFAULTSCREENS
! 257: #define WSDISPLAY_DEFAULTSCREENS 1
! 258: #endif
! 259: int wsdisplay_defaultscreens = WSDISPLAY_DEFAULTSCREENS;
! 260:
! 261: int wsdisplay_switch1(void *, int, int);
! 262: int wsdisplay_switch2(void *, int, int);
! 263: int wsdisplay_switch3(void *, int, int);
! 264:
! 265: int wsdisplay_clearonclose;
! 266:
! 267: #ifdef WSMOUSED_SUPPORT
! 268: char *Copybuffer;
! 269: u_int Copybuffer_size;
! 270: char Paste_avail;
! 271: #endif
! 272:
! 273: struct wsscreen *
! 274: wsscreen_attach(struct wsdisplay_softc *sc, int console, const char *emul,
! 275: const struct wsscreen_descr *type, void *cookie, int ccol, int crow,
! 276: long defattr)
! 277: {
! 278: struct wsscreen_internal *dconf;
! 279: struct wsscreen *scr;
! 280:
! 281: scr = malloc(sizeof(struct wsscreen), M_DEVBUF, M_NOWAIT);
! 282: if (!scr)
! 283: return (NULL);
! 284:
! 285: if (console) {
! 286: dconf = &wsdisplay_console_conf;
! 287: /*
! 288: * Tell the emulation about the callback argument.
! 289: * The other stuff is already there.
! 290: */
! 291: (void)(*dconf->wsemul->attach)(1, 0, 0, 0, 0, scr, 0);
! 292: } else { /* not console */
! 293: dconf = malloc(sizeof(struct wsscreen_internal),
! 294: M_DEVBUF, M_NOWAIT);
! 295: if (dconf == NULL)
! 296: goto fail;
! 297: dconf->emulops = type->textops;
! 298: dconf->emulcookie = cookie;
! 299: if (dconf->emulops == NULL ||
! 300: (dconf->wsemul = wsemul_pick(emul)) == NULL)
! 301: goto fail;
! 302: dconf->wsemulcookie = (*dconf->wsemul->attach)(0, type, cookie,
! 303: ccol, crow, scr, defattr);
! 304: if (dconf->wsemulcookie == NULL)
! 305: goto fail;
! 306: dconf->scrdata = type;
! 307: }
! 308:
! 309: scr->scr_dconf = dconf;
! 310:
! 311: scr->scr_tty = ttymalloc();
! 312: scr->scr_hold_screen = 0;
! 313: scr->scr_flags = 0;
! 314:
! 315: #ifdef WSDISPLAY_COMPAT_USL
! 316: scr->scr_syncops = NULL;
! 317: #endif
! 318:
! 319: scr->sc = sc;
! 320: #ifdef WSMOUSED_SUPPORT
! 321: scr->mouse_flags = 0;
! 322: #endif
! 323: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 324: scr->scr_rawkbd = 0;
! 325: #endif
! 326: return (scr);
! 327:
! 328: fail:
! 329: if (dconf != NULL)
! 330: free(dconf, M_DEVBUF);
! 331: free(scr, M_DEVBUF);
! 332: return (NULL);
! 333: }
! 334:
! 335: void
! 336: wsscreen_detach(struct wsscreen *scr)
! 337: {
! 338: int ccol, crow; /* XXX */
! 339:
! 340: if (WSSCREEN_HAS_TTY(scr)) {
! 341: timeout_del(&scr->scr_tty->t_rstrt_to);
! 342: ttyfree(scr->scr_tty);
! 343: }
! 344: (*scr->scr_dconf->wsemul->detach)(scr->scr_dconf->wsemulcookie,
! 345: &ccol, &crow);
! 346: free(scr->scr_dconf, M_DEVBUF);
! 347: free(scr, M_DEVBUF);
! 348: }
! 349:
! 350: const struct wsscreen_descr *
! 351: wsdisplay_screentype_pick(const struct wsscreen_list *scrdata, const char *name)
! 352: {
! 353: int i;
! 354: const struct wsscreen_descr *scr;
! 355:
! 356: KASSERT(scrdata->nscreens > 0);
! 357:
! 358: if (name == NULL || *name == '\0')
! 359: return (scrdata->screens[0]);
! 360:
! 361: for (i = 0; i < scrdata->nscreens; i++) {
! 362: scr = scrdata->screens[i];
! 363: if (!strncmp(name, scr->name, WSSCREEN_NAME_SIZE))
! 364: return (scr);
! 365: }
! 366:
! 367: return (0);
! 368: }
! 369:
! 370: /*
! 371: * print info about attached screen
! 372: */
! 373: void
! 374: wsdisplay_addscreen_print(struct wsdisplay_softc *sc, int idx, int count)
! 375: {
! 376: printf("%s: screen %d", sc->sc_dv.dv_xname, idx);
! 377: if (count > 1)
! 378: printf("-%d", idx + (count-1));
! 379: printf(" added (%s, %s emulation)\n",
! 380: sc->sc_scr[idx]->scr_dconf->scrdata->name,
! 381: sc->sc_scr[idx]->scr_dconf->wsemul->name);
! 382: }
! 383:
! 384: int
! 385: wsdisplay_addscreen(struct wsdisplay_softc *sc, int idx,
! 386: const char *screentype, const char *emul)
! 387: {
! 388: const struct wsscreen_descr *scrdesc;
! 389: int error;
! 390: void *cookie;
! 391: int ccol, crow;
! 392: long defattr;
! 393: struct wsscreen *scr;
! 394: int s;
! 395:
! 396: if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN)
! 397: return (EINVAL);
! 398: if (sc->sc_scr[idx] != NULL)
! 399: return (EBUSY);
! 400:
! 401: scrdesc = wsdisplay_screentype_pick(sc->sc_scrdata, screentype);
! 402: if (!scrdesc)
! 403: return (ENXIO);
! 404: error = (*sc->sc_accessops->alloc_screen)(sc->sc_accesscookie,
! 405: scrdesc, &cookie, &ccol, &crow, &defattr);
! 406: if (error)
! 407: return (error);
! 408:
! 409: scr = wsscreen_attach(sc, 0, emul, scrdesc,
! 410: cookie, ccol, crow, defattr);
! 411: if (scr == NULL) {
! 412: (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, cookie);
! 413: return (ENXIO);
! 414: }
! 415:
! 416: sc->sc_scr[idx] = scr;
! 417:
! 418: /* if no screen has focus yet, activate the first we get */
! 419: s = spltty();
! 420: if (!sc->sc_focus) {
! 421: (*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
! 422: scr->scr_dconf->emulcookie, 0, 0, 0);
! 423: sc->sc_focusidx = idx;
! 424: sc->sc_focus = scr;
! 425: }
! 426: splx(s);
! 427:
! 428: #ifdef WSMOUSED_SUPPORT
! 429: allocate_copybuffer(sc); /* enlarge the copy buffer is necessary */
! 430: #endif
! 431: return (0);
! 432: }
! 433:
! 434: int
! 435: wsdisplay_getscreen(struct wsdisplay_softc *sc,
! 436: struct wsdisplay_addscreendata *sd)
! 437: {
! 438: struct wsscreen *scr;
! 439:
! 440: if (sd->idx < 0 && sc->sc_focus)
! 441: sd->idx = sc->sc_focusidx;
! 442:
! 443: if (sd->idx < 0 || sd->idx >= WSDISPLAY_MAXSCREEN)
! 444: return (EINVAL);
! 445:
! 446: scr = sc->sc_scr[sd->idx];
! 447: if (scr == NULL)
! 448: return (ENXIO);
! 449:
! 450: strncpy(sd->screentype, scr->scr_dconf->scrdata->name,
! 451: WSSCREEN_NAME_SIZE);
! 452: strncpy(sd->emul, scr->scr_dconf->wsemul->name, WSEMUL_NAME_SIZE);
! 453:
! 454: return (0);
! 455: }
! 456:
! 457: void
! 458: wsdisplay_closescreen(struct wsdisplay_softc *sc, struct wsscreen *scr)
! 459: {
! 460: int maj, mn, idx;
! 461:
! 462: /* hangup */
! 463: if (WSSCREEN_HAS_TTY(scr)) {
! 464: struct tty *tp = scr->scr_tty;
! 465: (*linesw[tp->t_line].l_modem)(tp, 0);
! 466: }
! 467:
! 468: /* locate the major number */
! 469: for (maj = 0; maj < nchrdev; maj++)
! 470: if (cdevsw[maj].d_open == wsdisplayopen)
! 471: break;
! 472: /* locate the screen index */
! 473: for (idx = 0; idx < WSDISPLAY_MAXSCREEN; idx++)
! 474: if (scr == sc->sc_scr[idx])
! 475: break;
! 476: #ifdef DIAGNOSTIC
! 477: if (idx == WSDISPLAY_MAXSCREEN)
! 478: panic("wsdisplay_forceclose: bad screen");
! 479: #endif
! 480:
! 481: /* nuke the vnodes */
! 482: mn = WSDISPLAYMINOR(sc->sc_dv.dv_unit, idx);
! 483: vdevgone(maj, mn, mn, VCHR);
! 484: }
! 485:
! 486: int
! 487: wsdisplay_delscreen(struct wsdisplay_softc *sc, int idx, int flags)
! 488: {
! 489: struct wsscreen *scr;
! 490: int s;
! 491: void *cookie;
! 492:
! 493: if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN)
! 494: return (EINVAL);
! 495: if ((scr = sc->sc_scr[idx]) == NULL)
! 496: return (ENXIO);
! 497:
! 498: if (scr->scr_dconf == &wsdisplay_console_conf ||
! 499: #ifdef WSDISPLAY_COMPAT_USL
! 500: scr->scr_syncops ||
! 501: #endif
! 502: ((scr->scr_flags & SCR_OPEN) && !(flags & WSDISPLAY_DELSCR_FORCE)))
! 503: return (EBUSY);
! 504:
! 505: wsdisplay_closescreen(sc, scr);
! 506:
! 507: /*
! 508: * delete pointers, so neither device entries
! 509: * nor keyboard input can reference it anymore
! 510: */
! 511: s = spltty();
! 512: if (sc->sc_focus == scr) {
! 513: sc->sc_focus = 0;
! 514: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 515: wsdisplay_update_rawkbd(sc, 0);
! 516: #endif
! 517: }
! 518: sc->sc_scr[idx] = 0;
! 519: splx(s);
! 520:
! 521: /*
! 522: * Wake up processes waiting for the screen to
! 523: * be activated. Sleepers must check whether
! 524: * the screen still exists.
! 525: */
! 526: if (scr->scr_flags & SCR_WAITACTIVE)
! 527: wakeup(scr);
! 528:
! 529: /* save a reference to the graphics screen */
! 530: cookie = scr->scr_dconf->emulcookie;
! 531:
! 532: wsscreen_detach(scr);
! 533:
! 534: (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, cookie);
! 535:
! 536: if ((flags & WSDISPLAY_DELSCR_QUIET) == 0)
! 537: printf("%s: screen %d deleted\n", sc->sc_dv.dv_xname, idx);
! 538: return (0);
! 539: }
! 540:
! 541: /*
! 542: * Autoconfiguration functions.
! 543: */
! 544: int
! 545: wsdisplay_emul_match(struct device *parent, void *match, void *aux)
! 546: {
! 547: struct cfdata *cf = match;
! 548: struct wsemuldisplaydev_attach_args *ap = aux;
! 549:
! 550: if (cf->wsemuldisplaydevcf_console != WSEMULDISPLAYDEVCF_CONSOLE_UNK) {
! 551: /*
! 552: * If console-ness of device specified, either match
! 553: * exactly (at high priority), or fail.
! 554: */
! 555: if (cf->wsemuldisplaydevcf_console != 0 && ap->console != 0)
! 556: return (10);
! 557: else
! 558: return (0);
! 559: }
! 560:
! 561: /* If console-ness unspecified, it wins. */
! 562: return (1);
! 563: }
! 564:
! 565: void
! 566: wsdisplay_emul_attach(struct device *parent, struct device *self, void *aux)
! 567: {
! 568: struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self;
! 569: struct wsemuldisplaydev_attach_args *ap = aux;
! 570:
! 571: wsdisplay_common_attach(sc, ap->console,
! 572: sc->sc_dv.dv_cfdata->wsemuldisplaydevcf_mux, ap->scrdata,
! 573: ap->accessops, ap->accesscookie, ap->defaultscreens);
! 574:
! 575: if (ap->console && cn_tab == &wsdisplay_cons) {
! 576: int maj;
! 577:
! 578: /* locate the major number */
! 579: for (maj = 0; maj < nchrdev; maj++)
! 580: if (cdevsw[maj].d_open == wsdisplayopen)
! 581: break;
! 582:
! 583: cn_tab->cn_dev = makedev(maj, WSDISPLAYMINOR(self->dv_unit, 0));
! 584: }
! 585: }
! 586:
! 587: /*
! 588: * Detach a display.
! 589: */
! 590: int
! 591: wsdisplay_emul_detach(struct device *self, int flags)
! 592: {
! 593: struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self;
! 594:
! 595: return (wsdisplay_common_detach(sc, flags));
! 596: }
! 597:
! 598: int
! 599: wsdisplay_common_detach(struct wsdisplay_softc *sc, int flags)
! 600: {
! 601: int i;
! 602: int rc;
! 603:
! 604: /* We don't support detaching the console display yet. */
! 605: if (sc->sc_isconsole)
! 606: return (EBUSY);
! 607:
! 608: /* Delete all screens managed by this display */
! 609: for (i = 0; i < WSDISPLAY_MAXSCREEN; i++)
! 610: if (sc->sc_scr[i] != NULL) {
! 611: if ((rc = wsdisplay_delscreen(sc, i,
! 612: WSDISPLAY_DELSCR_QUIET | (flags & DETACH_FORCE ?
! 613: WSDISPLAY_DELSCR_FORCE : 0))) != 0)
! 614: return (rc);
! 615: }
! 616:
! 617: #ifdef BURNER_SUPPORT
! 618: timeout_del(&sc->sc_burner);
! 619: #endif
! 620:
! 621: #if NWSKBD > 0
! 622: if (sc->sc_input != NULL) {
! 623: #if NWSMUX > 0
! 624: wsmux_detach_sc(sc->sc_input); /* XXX not exactly correct */
! 625: /*
! 626: * XXX
! 627: * If we created a standalone mux (dmux), we should destroy it
! 628: * there, but there is currently no support for this in wsmux.
! 629: */
! 630: #else
! 631: if ((rc = wskbd_set_display((struct device *)sc->sc_input,
! 632: NULL)) != 0)
! 633: return (rc);
! 634: #endif
! 635: }
! 636: #endif
! 637:
! 638: return (0);
! 639: }
! 640:
! 641: /* Print function (for parent devices). */
! 642: int
! 643: wsemuldisplaydevprint(void *aux, const char *pnp)
! 644: {
! 645: #if 0 /* -Wunused */
! 646: struct wsemuldisplaydev_attach_args *ap = aux;
! 647: #endif
! 648:
! 649: if (pnp)
! 650: printf("wsdisplay at %s", pnp);
! 651: #if 0 /* don't bother; it's ugly */
! 652: printf(" console %d", ap->console);
! 653: #endif
! 654:
! 655: return (UNCONF);
! 656: }
! 657:
! 658: void
! 659: wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int kbdmux,
! 660: const struct wsscreen_list *scrdata,
! 661: const struct wsdisplay_accessops *accessops, void *accesscookie,
! 662: u_int defaultscreens)
! 663: {
! 664: static int hookset = 0;
! 665: int i, start = 0;
! 666: #if NWSKBD > 0
! 667: struct wsevsrc *kme;
! 668: #if NWSMUX > 0
! 669: struct wsmux_softc *mux;
! 670:
! 671: if (kbdmux >= 0)
! 672: mux = wsmux_getmux(kbdmux);
! 673: else
! 674: mux = wsmux_create("dmux", sc->sc_dv.dv_unit);
! 675: /* XXX panic()ing isn't nice, but attach cannot fail */
! 676: if (mux == NULL)
! 677: panic("wsdisplay_common_attach: no memory");
! 678: sc->sc_input = &mux->sc_base;
! 679: mux->sc_displaydv = &sc->sc_dv;
! 680: if (kbdmux >= 0)
! 681: printf(" mux %d", kbdmux);
! 682: #else
! 683: #if 0 /* not worth keeping, especially since the default value is not -1... */
! 684: if (kbdmux >= 0)
! 685: printf(" (mux ignored)");
! 686: #endif
! 687: #endif /* NWSMUX > 0 */
! 688: #endif /* NWSKBD > 0 */
! 689:
! 690: sc->sc_isconsole = console;
! 691:
! 692: if (console) {
! 693: KASSERT(wsdisplay_console_initted);
! 694: KASSERT(wsdisplay_console_device == NULL);
! 695:
! 696: sc->sc_scr[0] = wsscreen_attach(sc, 1, 0, 0, 0, 0, 0, 0);
! 697: if (sc->sc_scr[0] == NULL)
! 698: return;
! 699: wsdisplay_console_device = sc;
! 700:
! 701: printf(": console (%s, %s emulation)",
! 702: wsdisplay_console_conf.scrdata->name,
! 703: wsdisplay_console_conf.wsemul->name);
! 704:
! 705: #if NWSKBD > 0
! 706: kme = wskbd_set_console_display(&sc->sc_dv, sc->sc_input);
! 707: if (kme != NULL)
! 708: printf(", using %s", kme->me_dv.dv_xname);
! 709: #if NWSMUX == 0
! 710: sc->sc_input = kme;
! 711: #endif
! 712: #endif
! 713:
! 714: sc->sc_focusidx = 0;
! 715: sc->sc_focus = sc->sc_scr[0];
! 716: start = 1;
! 717: }
! 718: printf("\n");
! 719:
! 720: #if NWSKBD > 0 && NWSMUX > 0
! 721: wsmux_set_display(mux, &sc->sc_dv);
! 722: #endif
! 723:
! 724: sc->sc_accessops = accessops;
! 725: sc->sc_accesscookie = accesscookie;
! 726: sc->sc_scrdata = scrdata;
! 727:
! 728: /*
! 729: * Set up a number of virtual screens if wanted. The
! 730: * WSDISPLAYIO_ADDSCREEN ioctl is more flexible, so this code
! 731: * is for special cases like installation kernels, as well as
! 732: * sane multihead defaults.
! 733: */
! 734: if (defaultscreens == 0)
! 735: defaultscreens = wsdisplay_defaultscreens;
! 736: for (i = start; i < defaultscreens; i++) {
! 737: if (wsdisplay_addscreen(sc, i, 0, 0))
! 738: break;
! 739: }
! 740:
! 741: if (i > start)
! 742: wsdisplay_addscreen_print(sc, start, i-start);
! 743:
! 744: #ifdef BURNER_SUPPORT
! 745: sc->sc_burnoutintvl = (hz * WSDISPLAY_DEFBURNOUT) / 1000;
! 746: sc->sc_burninintvl = (hz * WSDISPLAY_DEFBURNIN ) / 1000;
! 747: sc->sc_burnflags = 0; /* off by default */
! 748: timeout_set(&sc->sc_burner, wsdisplay_burner, sc);
! 749: sc->sc_burnout = sc->sc_burnoutintvl;
! 750: wsdisplay_burn(sc, sc->sc_burnflags);
! 751: #endif
! 752:
! 753: if (hookset == 0)
! 754: shutdownhook_establish(wsdisplay_shutdownhook, NULL);
! 755: hookset = 1;
! 756:
! 757: #if NWSKBD > 0 && NWSMUX == 0
! 758: if (console == 0) {
! 759: /*
! 760: * In the non-wsmux world, always connect wskbd0 and wsdisplay0
! 761: * together.
! 762: */
! 763: extern struct cfdriver wskbd_cd;
! 764:
! 765: if (wskbd_cd.cd_ndevs != 0 && sc->sc_dv.dv_unit == 0) {
! 766: if (wsdisplay_set_kbd(&sc->sc_dv,
! 767: (struct wsevsrc *)wskbd_cd.cd_devs[0]) == 0)
! 768: wskbd_set_display(wskbd_cd.cd_devs[0],
! 769: &sc->sc_dv);
! 770: }
! 771: }
! 772: #endif
! 773: }
! 774:
! 775: void
! 776: wsdisplay_cnattach(const struct wsscreen_descr *type, void *cookie, int ccol,
! 777: int crow, long defattr)
! 778: {
! 779: const struct wsemul_ops *wsemul;
! 780: const struct wsdisplay_emulops *emulops;
! 781:
! 782: KASSERT(!wsdisplay_console_initted);
! 783: KASSERT(type->nrows > 0);
! 784: KASSERT(type->ncols > 0);
! 785: KASSERT(crow < type->nrows);
! 786: KASSERT(ccol < type->ncols);
! 787:
! 788: wsdisplay_console_conf.emulops = emulops = type->textops;
! 789: wsdisplay_console_conf.emulcookie = cookie;
! 790: wsdisplay_console_conf.scrdata = type;
! 791:
! 792: #ifdef WSEMUL_DUMB
! 793: /*
! 794: * If the emulops structure is crippled, force a dumb emulation.
! 795: */
! 796: if (emulops->cursor == NULL ||
! 797: emulops->copycols == NULL || emulops->copyrows == NULL ||
! 798: emulops->erasecols == NULL || emulops->eraserows == NULL)
! 799: wsemul = wsemul_pick("dumb");
! 800: else
! 801: #endif
! 802: wsemul = wsemul_pick("");
! 803: wsdisplay_console_conf.wsemul = wsemul;
! 804: wsdisplay_console_conf.wsemulcookie =
! 805: (*wsemul->cnattach)(type, cookie, ccol, crow, defattr);
! 806:
! 807: cn_tab = &wsdisplay_cons;
! 808:
! 809: wsdisplay_console_initted = 1;
! 810: }
! 811:
! 812: /*
! 813: * Tty and cdevsw functions.
! 814: */
! 815: int
! 816: wsdisplayopen(dev_t dev, int flag, int mode, struct proc *p)
! 817: {
! 818: struct wsdisplay_softc *sc;
! 819: struct tty *tp;
! 820: int unit, newopen, error;
! 821: struct wsscreen *scr;
! 822:
! 823: unit = WSDISPLAYUNIT(dev);
! 824: if (unit >= wsdisplay_cd.cd_ndevs || /* make sure it was attached */
! 825: (sc = wsdisplay_cd.cd_devs[unit]) == NULL)
! 826: return (ENXIO);
! 827:
! 828: if (ISWSDISPLAYCTL(dev))
! 829: return (0);
! 830:
! 831: if (WSDISPLAYSCREEN(dev) >= WSDISPLAY_MAXSCREEN)
! 832: return (ENXIO);
! 833: if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
! 834: return (ENXIO);
! 835:
! 836: if (WSSCREEN_HAS_TTY(scr)) {
! 837: tp = scr->scr_tty;
! 838: tp->t_oproc = wsdisplaystart;
! 839: tp->t_param = wsdisplayparam;
! 840: tp->t_dev = dev;
! 841: newopen = (tp->t_state & TS_ISOPEN) == 0;
! 842: if (newopen) {
! 843: ttychars(tp);
! 844: tp->t_iflag = TTYDEF_IFLAG;
! 845: tp->t_oflag = TTYDEF_OFLAG;
! 846: tp->t_cflag = TTYDEF_CFLAG;
! 847: tp->t_lflag = TTYDEF_LFLAG;
! 848: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
! 849: wsdisplayparam(tp, &tp->t_termios);
! 850: ttsetwater(tp);
! 851: } else if ((tp->t_state & TS_XCLUDE) != 0 &&
! 852: p->p_ucred->cr_uid != 0)
! 853: return (EBUSY);
! 854: tp->t_state |= TS_CARR_ON;
! 855:
! 856: error = ((*linesw[tp->t_line].l_open)(dev, tp));
! 857: if (error)
! 858: return (error);
! 859:
! 860: if (newopen) {
! 861: /* set window sizes as appropriate, and reset
! 862: the emulation */
! 863: tp->t_winsize.ws_row = scr->scr_dconf->scrdata->nrows;
! 864: tp->t_winsize.ws_col = scr->scr_dconf->scrdata->ncols;
! 865: }
! 866: }
! 867:
! 868: scr->scr_flags |= SCR_OPEN;
! 869: return (0);
! 870: }
! 871:
! 872: int
! 873: wsdisplayclose(dev_t dev, int flag, int mode, struct proc *p)
! 874: {
! 875: struct wsdisplay_softc *sc;
! 876: struct tty *tp;
! 877: int unit;
! 878: struct wsscreen *scr;
! 879:
! 880: unit = WSDISPLAYUNIT(dev);
! 881: sc = wsdisplay_cd.cd_devs[unit];
! 882:
! 883: if (ISWSDISPLAYCTL(dev))
! 884: return (0);
! 885:
! 886: if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
! 887: return (ENXIO);
! 888:
! 889: if (WSSCREEN_HAS_TTY(scr)) {
! 890: if (scr->scr_hold_screen) {
! 891: int s;
! 892:
! 893: /* XXX RESET KEYBOARD LEDS, etc. */
! 894: s = spltty(); /* avoid conflict with keyboard */
! 895: wsdisplay_kbdholdscreen((struct device *)sc, 0);
! 896: splx(s);
! 897: }
! 898: tp = scr->scr_tty;
! 899: (*linesw[tp->t_line].l_close)(tp, flag);
! 900: ttyclose(tp);
! 901: }
! 902:
! 903: #ifdef WSDISPLAY_COMPAT_USL
! 904: if (scr->scr_syncops)
! 905: (*scr->scr_syncops->destroy)(scr->scr_synccookie);
! 906: #endif
! 907:
! 908: scr->scr_flags &= ~SCR_GRAPHICS;
! 909: (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie,
! 910: WSEMUL_RESET);
! 911: if (wsdisplay_clearonclose)
! 912: (*scr->scr_dconf->wsemul->reset)
! 913: (scr->scr_dconf->wsemulcookie, WSEMUL_CLEARSCREEN);
! 914:
! 915: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 916: if (scr->scr_rawkbd) {
! 917: int kbmode = WSKBD_TRANSLATED;
! 918: (void) wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE,
! 919: (caddr_t)&kbmode, FWRITE, p);
! 920: }
! 921: #endif
! 922:
! 923: scr->scr_flags &= ~SCR_OPEN;
! 924:
! 925: #ifdef WSMOUSED_SUPPORT
! 926: /* remove the selection at logout */
! 927: if (Copybuffer)
! 928: bzero(Copybuffer, Copybuffer_size);
! 929: Paste_avail = 0;
! 930: #endif
! 931:
! 932: return (0);
! 933: }
! 934:
! 935: int
! 936: wsdisplayread(dev_t dev, struct uio *uio, int flag)
! 937: {
! 938: struct wsdisplay_softc *sc;
! 939: struct tty *tp;
! 940: int unit;
! 941: struct wsscreen *scr;
! 942:
! 943: unit = WSDISPLAYUNIT(dev);
! 944: sc = wsdisplay_cd.cd_devs[unit];
! 945:
! 946: if (ISWSDISPLAYCTL(dev))
! 947: return (0);
! 948:
! 949: if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
! 950: return (ENXIO);
! 951:
! 952: if (!WSSCREEN_HAS_TTY(scr))
! 953: return (ENODEV);
! 954:
! 955: tp = scr->scr_tty;
! 956: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
! 957: }
! 958:
! 959: int
! 960: wsdisplaywrite(dev_t dev, struct uio *uio, int flag)
! 961: {
! 962: struct wsdisplay_softc *sc;
! 963: struct tty *tp;
! 964: int unit;
! 965: struct wsscreen *scr;
! 966:
! 967: unit = WSDISPLAYUNIT(dev);
! 968: sc = wsdisplay_cd.cd_devs[unit];
! 969:
! 970: if (ISWSDISPLAYCTL(dev))
! 971: return (0);
! 972:
! 973: if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
! 974: return (ENXIO);
! 975:
! 976: if (!WSSCREEN_HAS_TTY(scr))
! 977: return (ENODEV);
! 978:
! 979: tp = scr->scr_tty;
! 980: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
! 981: }
! 982:
! 983: struct tty *
! 984: wsdisplaytty(dev_t dev)
! 985: {
! 986: struct wsdisplay_softc *sc;
! 987: int unit;
! 988: struct wsscreen *scr;
! 989:
! 990: unit = WSDISPLAYUNIT(dev);
! 991: sc = wsdisplay_cd.cd_devs[unit];
! 992:
! 993: if (ISWSDISPLAYCTL(dev))
! 994: panic("wsdisplaytty() on ctl device");
! 995:
! 996: if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
! 997: return (NULL);
! 998:
! 999: return (scr->scr_tty);
! 1000: }
! 1001:
! 1002: int
! 1003: wsdisplayioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
! 1004: {
! 1005: struct wsdisplay_softc *sc;
! 1006: struct tty *tp;
! 1007: int unit, error;
! 1008: struct wsscreen *scr;
! 1009:
! 1010: unit = WSDISPLAYUNIT(dev);
! 1011: sc = wsdisplay_cd.cd_devs[unit];
! 1012:
! 1013: #ifdef WSDISPLAY_COMPAT_USL
! 1014: error = wsdisplay_usl_ioctl1(sc, cmd, data, flag, p);
! 1015: if (error >= 0)
! 1016: return (error);
! 1017: #endif
! 1018:
! 1019: if (ISWSDISPLAYCTL(dev))
! 1020: return (wsdisplay_cfg_ioctl(sc, cmd, data, flag, p));
! 1021:
! 1022: if (WSDISPLAYSCREEN(dev) >= WSDISPLAY_MAXSCREEN)
! 1023: return (ENODEV);
! 1024:
! 1025: if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
! 1026: return (ENXIO);
! 1027:
! 1028: if (WSSCREEN_HAS_TTY(scr)) {
! 1029: tp = scr->scr_tty;
! 1030:
! 1031: /* printf("disc\n"); */
! 1032: /* do the line discipline ioctls first */
! 1033: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
! 1034: if (error >= 0)
! 1035: return (error);
! 1036:
! 1037: /* printf("tty\n"); */
! 1038: /* then the tty ioctls */
! 1039: error = ttioctl(tp, cmd, data, flag, p);
! 1040: if (error >= 0)
! 1041: return (error);
! 1042: }
! 1043:
! 1044: #ifdef WSDISPLAY_COMPAT_USL
! 1045: error = wsdisplay_usl_ioctl2(sc, scr, cmd, data, flag, p);
! 1046: if (error >= 0)
! 1047: return (error);
! 1048: #endif
! 1049:
! 1050: error = wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, p);
! 1051: return (error != -1 ? error : ENOTTY);
! 1052: }
! 1053:
! 1054: int
! 1055: wsdisplay_param(struct device *dev, u_long cmd, struct wsdisplay_param *dp)
! 1056: {
! 1057: struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
! 1058:
! 1059: return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd,
! 1060: (caddr_t)dp, 0, NULL));
! 1061: }
! 1062:
! 1063: int
! 1064: wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr,
! 1065: u_long cmd, caddr_t data, int flag, struct proc *p)
! 1066: {
! 1067: int error;
! 1068:
! 1069: #if NWSKBD > 0
! 1070: struct wsevsrc *inp;
! 1071:
! 1072: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 1073: switch (cmd) {
! 1074: case WSKBDIO_SETMODE:
! 1075: if ((flag & FWRITE) == 0)
! 1076: return (EACCES);
! 1077: scr->scr_rawkbd = (*(int *)data == WSKBD_RAW);
! 1078: return (wsdisplay_update_rawkbd(sc, scr));
! 1079: case WSKBDIO_GETMODE:
! 1080: *(int *)data = (scr->scr_rawkbd ?
! 1081: WSKBD_RAW : WSKBD_TRANSLATED);
! 1082: return (0);
! 1083: }
! 1084: #endif
! 1085: inp = sc->sc_input;
! 1086: if (inp != NULL) {
! 1087: error = wsevsrc_display_ioctl(inp, cmd, data, flag, p);
! 1088: if (error >= 0)
! 1089: return (error);
! 1090: }
! 1091: #endif /* NWSKBD > 0 */
! 1092:
! 1093: switch (cmd) {
! 1094: case WSDISPLAYIO_SMODE:
! 1095: case WSDISPLAYIO_USEFONT:
! 1096: #ifdef BURNER_SUPPORT
! 1097: case WSDISPLAYIO_SVIDEO:
! 1098: case WSDISPLAYIO_SBURNER:
! 1099: #endif
! 1100: case WSDISPLAYIO_SETSCREEN:
! 1101: if ((flag & FWRITE) == 0)
! 1102: return (EACCES);
! 1103: }
! 1104:
! 1105: switch (cmd) {
! 1106: case WSDISPLAYIO_GMODE:
! 1107: if (scr->scr_flags & SCR_GRAPHICS) {
! 1108: if (scr->scr_flags & SCR_DUMBFB)
! 1109: *(u_int *)data = WSDISPLAYIO_MODE_DUMBFB;
! 1110: else
! 1111: *(u_int *)data = WSDISPLAYIO_MODE_MAPPED;
! 1112: } else
! 1113: *(u_int *)data = WSDISPLAYIO_MODE_EMUL;
! 1114: return (0);
! 1115:
! 1116: case WSDISPLAYIO_SMODE:
! 1117: #define d (*(int *)data)
! 1118: if (d != WSDISPLAYIO_MODE_EMUL &&
! 1119: d != WSDISPLAYIO_MODE_MAPPED &&
! 1120: d != WSDISPLAYIO_MODE_DUMBFB)
! 1121: return (EINVAL);
! 1122:
! 1123: scr->scr_flags &= ~SCR_GRAPHICS;
! 1124: if (d == WSDISPLAYIO_MODE_MAPPED ||
! 1125: d == WSDISPLAYIO_MODE_DUMBFB) {
! 1126: scr->scr_flags |= SCR_GRAPHICS |
! 1127: ((d == WSDISPLAYIO_MODE_DUMBFB) ? SCR_DUMBFB : 0);
! 1128:
! 1129: #ifdef WSMOUSED_SUPPORT
! 1130: /*
! 1131: * wsmoused cohabitation with X-Window support
! 1132: * X-Window is starting
! 1133: */
! 1134: wsmoused_release(sc);
! 1135: #endif
! 1136:
! 1137: #ifdef BURNER_SUPPORT
! 1138: /* disable the burner while X is running */
! 1139: if (sc->sc_burnout)
! 1140: timeout_del(&sc->sc_burner);
! 1141: #endif
! 1142: } else {
! 1143: #ifdef BURNER_SUPPORT
! 1144: /* reenable the burner after exiting from X */
! 1145: if (!sc->sc_burnman)
! 1146: wsdisplay_burn(sc, sc->sc_burnflags);
! 1147: #endif
! 1148:
! 1149: #ifdef WSMOUSED_SUPPORT
! 1150: /*
! 1151: * wsmoused cohabitation with X-Window support
! 1152: * X-Window is ending
! 1153: */
! 1154: wsmoused_wakeup(sc);
! 1155: #endif
! 1156: }
! 1157:
! 1158: (void)(*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data,
! 1159: flag, p);
! 1160:
! 1161: return (0);
! 1162: #undef d
! 1163:
! 1164: case WSDISPLAYIO_USEFONT:
! 1165: #define d ((struct wsdisplay_font *)data)
! 1166: if (!sc->sc_accessops->load_font)
! 1167: return (EINVAL);
! 1168: d->data = 0;
! 1169: error = (*sc->sc_accessops->load_font)(sc->sc_accesscookie,
! 1170: scr->scr_dconf->emulcookie, d);
! 1171: if (!error)
! 1172: (*scr->scr_dconf->wsemul->reset)
! 1173: (scr->scr_dconf->wsemulcookie, WSEMUL_SYNCFONT);
! 1174: return (error);
! 1175: #undef d
! 1176: #ifdef BURNER_SUPPORT
! 1177: case WSDISPLAYIO_GVIDEO:
! 1178: *(u_int *)data = !sc->sc_burnman;
! 1179: break;
! 1180:
! 1181: case WSDISPLAYIO_SVIDEO:
! 1182: if (*(u_int *)data != WSDISPLAYIO_VIDEO_OFF &&
! 1183: *(u_int *)data != WSDISPLAYIO_VIDEO_ON)
! 1184: return (EINVAL);
! 1185: if (sc->sc_accessops->burn_screen == NULL)
! 1186: return (EOPNOTSUPP);
! 1187: (*sc->sc_accessops->burn_screen)(sc->sc_accesscookie,
! 1188: *(u_int *)data, sc->sc_burnflags);
! 1189: break;
! 1190:
! 1191: case WSDISPLAYIO_GBURNER:
! 1192: #define d ((struct wsdisplay_burner *)data)
! 1193: d->on = sc->sc_burninintvl * 1000 / hz;
! 1194: d->off = sc->sc_burnoutintvl * 1000 / hz;
! 1195: d->flags = sc->sc_burnflags;
! 1196: return (0);
! 1197:
! 1198: case WSDISPLAYIO_SBURNER:
! 1199: if (d->flags & ~(WSDISPLAY_BURN_VBLANK | WSDISPLAY_BURN_KBD |
! 1200: WSDISPLAY_BURN_MOUSE | WSDISPLAY_BURN_OUTPUT))
! 1201: error = EINVAL;
! 1202: else {
! 1203: error = 0;
! 1204: sc->sc_burnflags = d->flags;
! 1205: /* disable timeout if necessary */
! 1206: if ((sc->sc_burnflags & (WSDISPLAY_BURN_OUTPUT |
! 1207: WSDISPLAY_BURN_KBD | WSDISPLAY_BURN_MOUSE)) == 0) {
! 1208: if (sc->sc_burnout)
! 1209: timeout_del(&sc->sc_burner);
! 1210: }
! 1211: }
! 1212: if (d->on) {
! 1213: error = 0;
! 1214: sc->sc_burninintvl = hz * d->on / 1000;
! 1215: if (sc->sc_burnman)
! 1216: sc->sc_burnout = sc->sc_burninintvl;
! 1217: }
! 1218: if (d->off) {
! 1219: error = 0;
! 1220: sc->sc_burnoutintvl = hz * d->off / 1000;
! 1221: if (!sc->sc_burnman) {
! 1222: sc->sc_burnout = sc->sc_burnoutintvl;
! 1223: /* reinit timeout if changed */
! 1224: if ((scr->scr_flags & SCR_GRAPHICS) == 0)
! 1225: wsdisplay_burn(sc, sc->sc_burnflags);
! 1226: }
! 1227: }
! 1228: return (error);
! 1229: #undef d
! 1230: #endif /* BURNER_SUPPORT */
! 1231: case WSDISPLAYIO_GETSCREEN:
! 1232: return (wsdisplay_getscreen(sc,
! 1233: (struct wsdisplay_addscreendata *)data));
! 1234:
! 1235: case WSDISPLAYIO_SETSCREEN:
! 1236: return (wsdisplay_switch((void *)sc, *(int *)data, 1));
! 1237: }
! 1238:
! 1239: /* check ioctls for display */
! 1240: return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data,
! 1241: flag, p));
! 1242: }
! 1243:
! 1244: int
! 1245: wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data,
! 1246: int flag, struct proc *p)
! 1247: {
! 1248: int error;
! 1249: void *buf;
! 1250: size_t fontsz;
! 1251: #if NWSKBD > 0
! 1252: struct wsevsrc *inp;
! 1253: #endif
! 1254:
! 1255: switch (cmd) {
! 1256: #ifdef WSMOUSED_SUPPORT
! 1257: case WSDISPLAYIO_WSMOUSED:
! 1258: error = wsmoused(sc, cmd, data, flag, p);
! 1259: return (error);
! 1260: #endif
! 1261: case WSDISPLAYIO_ADDSCREEN:
! 1262: #define d ((struct wsdisplay_addscreendata *)data)
! 1263: if ((error = wsdisplay_addscreen(sc, d->idx,
! 1264: d->screentype, d->emul)) == 0)
! 1265: wsdisplay_addscreen_print(sc, d->idx, 0);
! 1266: return (error);
! 1267: #undef d
! 1268: case WSDISPLAYIO_DELSCREEN:
! 1269: #define d ((struct wsdisplay_delscreendata *)data)
! 1270: return (wsdisplay_delscreen(sc, d->idx, d->flags));
! 1271: #undef d
! 1272: case WSDISPLAYIO_GETSCREEN:
! 1273: return (wsdisplay_getscreen(sc,
! 1274: (struct wsdisplay_addscreendata *)data));
! 1275: case WSDISPLAYIO_SETSCREEN:
! 1276: return (wsdisplay_switch((void *)sc, *(int *)data, 1));
! 1277: case WSDISPLAYIO_LDFONT:
! 1278: #define d ((struct wsdisplay_font *)data)
! 1279: if (!sc->sc_accessops->load_font)
! 1280: return (EINVAL);
! 1281: if (d->index >= WSDISPLAY_MAXFONT)
! 1282: return (EINVAL);
! 1283: fontsz = d->fontheight * d->stride * d->numchars;
! 1284: if (fontsz > WSDISPLAY_MAXFONTSZ)
! 1285: return (EINVAL);
! 1286:
! 1287: buf = malloc(fontsz, M_DEVBUF, M_WAITOK);
! 1288: error = copyin(d->data, buf, fontsz);
! 1289: if (error) {
! 1290: free(buf, M_DEVBUF);
! 1291: return (error);
! 1292: }
! 1293: d->data = buf;
! 1294: error =
! 1295: (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 0, d);
! 1296: if (error)
! 1297: free(buf, M_DEVBUF);
! 1298: else if (d->index >= 0 || d->index < WSDISPLAY_MAXFONT)
! 1299: sc->sc_fonts[d->index] = *d;
! 1300: return (error);
! 1301:
! 1302: case WSDISPLAYIO_LSFONT:
! 1303: if (d->index < 0 || d->index >= WSDISPLAY_MAXFONT)
! 1304: return (EINVAL);
! 1305: *d = sc->sc_fonts[d->index];
! 1306: return (0);
! 1307:
! 1308: case WSDISPLAYIO_DELFONT:
! 1309: return (EINVAL);
! 1310: #undef d
! 1311:
! 1312: #if NWSKBD > 0
! 1313: case WSMUXIO_ADD_DEVICE:
! 1314: #define d ((struct wsmux_device *)data)
! 1315: if (d->idx == -1 && d->type == WSMUX_KBD)
! 1316: d->idx = wskbd_pickfree();
! 1317: #undef d
! 1318: /* FALLTHROUGH */
! 1319: case WSMUXIO_INJECTEVENT:
! 1320: case WSMUXIO_REMOVE_DEVICE:
! 1321: case WSMUXIO_LIST_DEVICES:
! 1322: inp = sc->sc_input;
! 1323: if (inp == NULL)
! 1324: return (ENXIO);
! 1325: return (wsevsrc_ioctl(inp, cmd, data, flag,p));
! 1326: #endif /* NWSKBD > 0 */
! 1327:
! 1328: }
! 1329: return (EINVAL);
! 1330: }
! 1331:
! 1332: paddr_t
! 1333: wsdisplaymmap(dev_t dev, off_t offset, int prot)
! 1334: {
! 1335: struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)];
! 1336: struct wsscreen *scr;
! 1337:
! 1338: if (ISWSDISPLAYCTL(dev))
! 1339: return (-1);
! 1340:
! 1341: if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
! 1342: return (-1);
! 1343:
! 1344: if (!(scr->scr_flags & SCR_GRAPHICS))
! 1345: return (-1);
! 1346:
! 1347: /* pass mmap to display */
! 1348: return ((*sc->sc_accessops->mmap)(sc->sc_accesscookie, offset, prot));
! 1349: }
! 1350:
! 1351: int
! 1352: wsdisplaypoll(dev_t dev, int events, struct proc *p)
! 1353: {
! 1354: struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)];
! 1355: struct wsscreen *scr;
! 1356:
! 1357: if (ISWSDISPLAYCTL(dev))
! 1358: return (0);
! 1359:
! 1360: if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
! 1361: return (POLLERR);
! 1362:
! 1363: if (!WSSCREEN_HAS_TTY(scr))
! 1364: return (POLLERR);
! 1365:
! 1366: return (ttpoll(dev, events, p));
! 1367: }
! 1368:
! 1369: int
! 1370: wsdisplaykqfilter(dev_t dev, struct knote *kn)
! 1371: {
! 1372: struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)];
! 1373: struct wsscreen *scr;
! 1374:
! 1375: if (ISWSDISPLAYCTL(dev))
! 1376: return (1);
! 1377:
! 1378: if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
! 1379: return (1);
! 1380:
! 1381: if (WSSCREEN_HAS_TTY(scr))
! 1382: return (ttkqfilter(dev, kn));
! 1383: else
! 1384: return (1);
! 1385: }
! 1386:
! 1387: void
! 1388: wsdisplaystart(struct tty *tp)
! 1389: {
! 1390: struct wsdisplay_softc *sc;
! 1391: struct wsscreen *scr;
! 1392: int s, n, unit;
! 1393: u_char *buf;
! 1394:
! 1395: unit = WSDISPLAYUNIT(tp->t_dev);
! 1396: if (unit >= wsdisplay_cd.cd_ndevs ||
! 1397: (sc = wsdisplay_cd.cd_devs[unit]) == NULL)
! 1398: return;
! 1399:
! 1400: s = spltty();
! 1401: if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) {
! 1402: splx(s);
! 1403: return;
! 1404: }
! 1405: if (tp->t_outq.c_cc == 0 && tp->t_wsel.si_selpid == 0)
! 1406: goto low;
! 1407:
! 1408: if ((scr = sc->sc_scr[WSDISPLAYSCREEN(tp->t_dev)]) == NULL) {
! 1409: splx(s);
! 1410: return;
! 1411: }
! 1412: if (scr->scr_hold_screen) {
! 1413: tp->t_state |= TS_TIMEOUT;
! 1414: splx(s);
! 1415: return;
! 1416: }
! 1417: tp->t_state |= TS_BUSY;
! 1418: splx(s);
! 1419:
! 1420: /*
! 1421: * Drain output from ring buffer.
! 1422: * The output will normally be in one contiguous chunk, but when the
! 1423: * ring wraps, it will be in two pieces.. one at the end of the ring,
! 1424: * the other at the start. For performance, rather than loop here,
! 1425: * we output one chunk, see if there's another one, and if so, output
! 1426: * it too.
! 1427: */
! 1428:
! 1429: n = ndqb(&tp->t_outq, 0);
! 1430: buf = tp->t_outq.c_cf;
! 1431:
! 1432: if (!(scr->scr_flags & SCR_GRAPHICS)) {
! 1433: #ifdef BURNER_SUPPORT
! 1434: wsdisplay_burn(sc, WSDISPLAY_BURN_OUTPUT);
! 1435: #endif
! 1436: #ifdef WSMOUSED_SUPPORT
! 1437: if (scr == sc->sc_focus) {
! 1438: if (IS_SEL_EXISTS(sc->sc_focus))
! 1439: /* hide a potential selection */
! 1440: remove_selection(sc);
! 1441: /* hide a potential mouse cursor */
! 1442: mouse_hide(sc);
! 1443: }
! 1444: #endif
! 1445: (*scr->scr_dconf->wsemul->output)(scr->scr_dconf->wsemulcookie,
! 1446: buf, n, 0);
! 1447: }
! 1448: ndflush(&tp->t_outq, n);
! 1449:
! 1450: if ((n = ndqb(&tp->t_outq, 0)) > 0) {
! 1451: buf = tp->t_outq.c_cf;
! 1452:
! 1453: if (!(scr->scr_flags & SCR_GRAPHICS)) {
! 1454: #ifdef BURNER_SUPPORT
! 1455: wsdisplay_burn(sc, WSDISPLAY_BURN_OUTPUT);
! 1456: #endif
! 1457: (*scr->scr_dconf->wsemul->output)
! 1458: (scr->scr_dconf->wsemulcookie, buf, n, 0);
! 1459: }
! 1460: ndflush(&tp->t_outq, n);
! 1461: }
! 1462:
! 1463: s = spltty();
! 1464: tp->t_state &= ~TS_BUSY;
! 1465: /* Come back if there's more to do */
! 1466: if (tp->t_outq.c_cc) {
! 1467: tp->t_state |= TS_TIMEOUT;
! 1468: timeout_add(&tp->t_rstrt_to, (hz > 128) ? (hz / 128) : 1);
! 1469: }
! 1470: if (tp->t_outq.c_cc <= tp->t_lowat) {
! 1471: low:
! 1472: if (tp->t_state & TS_ASLEEP) {
! 1473: tp->t_state &= ~TS_ASLEEP;
! 1474: wakeup((caddr_t)&tp->t_outq);
! 1475: }
! 1476: selwakeup(&tp->t_wsel);
! 1477: }
! 1478: splx(s);
! 1479: }
! 1480:
! 1481: int
! 1482: wsdisplaystop(struct tty *tp, int flag)
! 1483: {
! 1484: int s;
! 1485:
! 1486: s = spltty();
! 1487: if (ISSET(tp->t_state, TS_BUSY))
! 1488: if (!ISSET(tp->t_state, TS_TTSTOP))
! 1489: SET(tp->t_state, TS_FLUSH);
! 1490: splx(s);
! 1491:
! 1492: return (0);
! 1493: }
! 1494:
! 1495: /* Set line parameters. */
! 1496: int
! 1497: wsdisplayparam(struct tty *tp, struct termios *t)
! 1498: {
! 1499:
! 1500: tp->t_ispeed = t->c_ispeed;
! 1501: tp->t_ospeed = t->c_ospeed;
! 1502: tp->t_cflag = t->c_cflag;
! 1503: return (0);
! 1504: }
! 1505:
! 1506: /*
! 1507: * Callbacks for the emulation code.
! 1508: */
! 1509: void
! 1510: wsdisplay_emulbell(void *v)
! 1511: {
! 1512: struct wsscreen *scr = v;
! 1513:
! 1514: if (scr == NULL) /* console, before real attach */
! 1515: return;
! 1516:
! 1517: if (scr->scr_flags & SCR_GRAPHICS) /* can this happen? */
! 1518: return;
! 1519:
! 1520: (void) wsdisplay_internal_ioctl(scr->sc, scr, WSKBDIO_BELL, NULL,
! 1521: FWRITE, NULL);
! 1522: }
! 1523:
! 1524: void
! 1525: wsdisplay_emulinput(void *v, const u_char *data, u_int count)
! 1526: {
! 1527: struct wsscreen *scr = v;
! 1528: struct tty *tp;
! 1529:
! 1530: if (v == NULL) /* console, before real attach */
! 1531: return;
! 1532:
! 1533: if (scr->scr_flags & SCR_GRAPHICS) /* XXX can't happen */
! 1534: return;
! 1535: if (!WSSCREEN_HAS_TTY(scr))
! 1536: return;
! 1537:
! 1538: tp = scr->scr_tty;
! 1539: while (count-- > 0)
! 1540: (*linesw[tp->t_line].l_rint)(*data++, tp);
! 1541: }
! 1542:
! 1543: /*
! 1544: * Calls from the keyboard interface.
! 1545: */
! 1546: void
! 1547: wsdisplay_kbdinput(struct device *dev, keysym_t ks)
! 1548: {
! 1549: struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
! 1550: struct wsscreen *scr;
! 1551: char *dp;
! 1552: int count;
! 1553: struct tty *tp;
! 1554:
! 1555: KASSERT(sc != NULL);
! 1556:
! 1557: scr = sc->sc_focus;
! 1558:
! 1559: if (!scr || !WSSCREEN_HAS_TTY(scr))
! 1560: return;
! 1561:
! 1562: tp = scr->scr_tty;
! 1563:
! 1564: if (KS_GROUP(ks) == KS_GROUP_Ascii)
! 1565: (*linesw[tp->t_line].l_rint)(KS_VALUE(ks), tp);
! 1566: else {
! 1567: count = (*scr->scr_dconf->wsemul->translate)
! 1568: (scr->scr_dconf->wsemulcookie, ks, &dp);
! 1569: while (count-- > 0)
! 1570: (*linesw[tp->t_line].l_rint)(*dp++, tp);
! 1571: }
! 1572: }
! 1573:
! 1574: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 1575: int
! 1576: wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr)
! 1577: {
! 1578: #if NWSKBD > 0
! 1579: int s, raw, data, error;
! 1580: struct wsevsrc *inp;
! 1581:
! 1582: s = spltty();
! 1583:
! 1584: raw = (scr ? scr->scr_rawkbd : 0);
! 1585:
! 1586: if (scr != sc->sc_focus || sc->sc_rawkbd == raw) {
! 1587: splx(s);
! 1588: return (0);
! 1589: }
! 1590:
! 1591: data = raw ? WSKBD_RAW : WSKBD_TRANSLATED;
! 1592: inp = sc->sc_input;
! 1593: if (inp == NULL) {
! 1594: splx(s);
! 1595: return (ENXIO);
! 1596: }
! 1597: error = wsevsrc_display_ioctl(inp, WSKBDIO_SETMODE, &data, FWRITE, 0);
! 1598: if (!error)
! 1599: sc->sc_rawkbd = raw;
! 1600: splx(s);
! 1601: return (error);
! 1602: #else
! 1603: return (0);
! 1604: #endif
! 1605: }
! 1606: #endif
! 1607:
! 1608: int
! 1609: wsdisplay_switch3(void *arg, int error, int waitok)
! 1610: {
! 1611: struct wsdisplay_softc *sc = arg;
! 1612: int no;
! 1613: struct wsscreen *scr;
! 1614:
! 1615: #ifdef WSDISPLAY_COMPAT_USL
! 1616: if (!(sc->sc_flags & SC_SWITCHPENDING)) {
! 1617: printf("wsdisplay_switch3: not switching\n");
! 1618: return (EINVAL);
! 1619: }
! 1620:
! 1621: no = sc->sc_screenwanted;
! 1622: if (no < 0 || no >= WSDISPLAY_MAXSCREEN)
! 1623: panic("wsdisplay_switch3: invalid screen %d", no);
! 1624: scr = sc->sc_scr[no];
! 1625: if (!scr) {
! 1626: printf("wsdisplay_switch3: screen %d disappeared\n", no);
! 1627: error = ENXIO;
! 1628: }
! 1629:
! 1630: if (error) {
! 1631: /* try to recover, avoid recursion */
! 1632:
! 1633: if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) {
! 1634: printf("wsdisplay_switch3: giving up\n");
! 1635: sc->sc_focus = 0;
! 1636: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 1637: wsdisplay_update_rawkbd(sc, 0);
! 1638: #endif
! 1639: sc->sc_flags &= ~SC_SWITCHPENDING;
! 1640: return (error);
! 1641: }
! 1642:
! 1643: sc->sc_screenwanted = sc->sc_oldscreen;
! 1644: sc->sc_oldscreen = WSDISPLAY_NULLSCREEN;
! 1645: return (wsdisplay_switch1(arg, 0, waitok));
! 1646: }
! 1647: #else
! 1648: /*
! 1649: * If we do not have syncops support, we come straight from
! 1650: * wsdisplay_switch2 which has already validated our arguments
! 1651: * and did not sleep.
! 1652: */
! 1653: no = sc->sc_screenwanted;
! 1654: scr = sc->sc_scr[no];
! 1655: #endif
! 1656:
! 1657: sc->sc_flags &= ~SC_SWITCHPENDING;
! 1658:
! 1659: if (!error && (scr->scr_flags & SCR_WAITACTIVE))
! 1660: wakeup(scr);
! 1661: return (error);
! 1662: }
! 1663:
! 1664: int
! 1665: wsdisplay_switch2(void *arg, int error, int waitok)
! 1666: {
! 1667: struct wsdisplay_softc *sc = arg;
! 1668: int no;
! 1669: struct wsscreen *scr;
! 1670:
! 1671: if (!(sc->sc_flags & SC_SWITCHPENDING)) {
! 1672: printf("wsdisplay_switch2: not switching\n");
! 1673: return (EINVAL);
! 1674: }
! 1675:
! 1676: no = sc->sc_screenwanted;
! 1677: if (no < 0 || no >= WSDISPLAY_MAXSCREEN)
! 1678: panic("wsdisplay_switch2: invalid screen %d", no);
! 1679: scr = sc->sc_scr[no];
! 1680: if (!scr) {
! 1681: printf("wsdisplay_switch2: screen %d disappeared\n", no);
! 1682: error = ENXIO;
! 1683: }
! 1684:
! 1685: if (error) {
! 1686: /* try to recover, avoid recursion */
! 1687:
! 1688: if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) {
! 1689: printf("wsdisplay_switch2: giving up\n");
! 1690: sc->sc_focus = 0;
! 1691: sc->sc_flags &= ~SC_SWITCHPENDING;
! 1692: return (error);
! 1693: }
! 1694:
! 1695: sc->sc_screenwanted = sc->sc_oldscreen;
! 1696: sc->sc_oldscreen = WSDISPLAY_NULLSCREEN;
! 1697: return (wsdisplay_switch1(arg, 0, waitok));
! 1698: }
! 1699:
! 1700: sc->sc_focusidx = no;
! 1701: sc->sc_focus = scr;
! 1702:
! 1703: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 1704: (void) wsdisplay_update_rawkbd(sc, scr);
! 1705: #endif
! 1706: /* keyboard map??? */
! 1707:
! 1708: #ifdef WSDISPLAY_COMPAT_USL
! 1709: #define wsswitch_cb3 ((void (*)(void *, int, int))wsdisplay_switch3)
! 1710: if (scr->scr_syncops) {
! 1711: error = (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok,
! 1712: sc->sc_isconsole && wsdisplay_cons_pollmode ?
! 1713: 0 : wsswitch_cb3, sc);
! 1714: if (error == EAGAIN) {
! 1715: /* switch will be done asynchronously */
! 1716: return (0);
! 1717: }
! 1718: }
! 1719: #endif
! 1720:
! 1721: return (wsdisplay_switch3(sc, error, waitok));
! 1722: }
! 1723:
! 1724: int
! 1725: wsdisplay_switch1(void *arg, int error, int waitok)
! 1726: {
! 1727: struct wsdisplay_softc *sc = arg;
! 1728: int no;
! 1729: struct wsscreen *scr;
! 1730:
! 1731: if (!(sc->sc_flags & SC_SWITCHPENDING)) {
! 1732: printf("wsdisplay_switch1: not switching\n");
! 1733: return (EINVAL);
! 1734: }
! 1735:
! 1736: no = sc->sc_screenwanted;
! 1737: if (no == WSDISPLAY_NULLSCREEN) {
! 1738: sc->sc_flags &= ~SC_SWITCHPENDING;
! 1739: if (!error) {
! 1740: sc->sc_focus = 0;
! 1741: }
! 1742: wakeup(sc);
! 1743: return (error);
! 1744: }
! 1745: if (no < 0 || no >= WSDISPLAY_MAXSCREEN)
! 1746: panic("wsdisplay_switch1: invalid screen %d", no);
! 1747: scr = sc->sc_scr[no];
! 1748: if (!scr) {
! 1749: printf("wsdisplay_switch1: screen %d disappeared\n", no);
! 1750: error = ENXIO;
! 1751: }
! 1752:
! 1753: if (error) {
! 1754: sc->sc_flags &= ~SC_SWITCHPENDING;
! 1755: return (error);
! 1756: }
! 1757:
! 1758: #define wsswitch_cb2 ((void (*)(void *, int, int))wsdisplay_switch2)
! 1759: error = (*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
! 1760: scr->scr_dconf->emulcookie, waitok,
! 1761: sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb2, sc);
! 1762: if (error == EAGAIN) {
! 1763: /* switch will be done asynchronously */
! 1764: return (0);
! 1765: }
! 1766:
! 1767: return (wsdisplay_switch2(sc, error, waitok));
! 1768: }
! 1769:
! 1770: int
! 1771: wsdisplay_switch(struct device *dev, int no, int waitok)
! 1772: {
! 1773: struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
! 1774: int s, res = 0;
! 1775: struct wsscreen *scr;
! 1776:
! 1777: if (no != WSDISPLAY_NULLSCREEN) {
! 1778: if (no < 0 || no >= WSDISPLAY_MAXSCREEN)
! 1779: return (EINVAL);
! 1780: if (sc->sc_scr[no] == NULL)
! 1781: return (ENXIO);
! 1782: }
! 1783:
! 1784: s = spltty();
! 1785:
! 1786: if ((sc->sc_focus && no == sc->sc_focusidx) ||
! 1787: (sc->sc_focus == NULL && no == WSDISPLAY_NULLSCREEN)) {
! 1788: splx(s);
! 1789: return (0);
! 1790: }
! 1791:
! 1792: if (sc->sc_flags & SC_SWITCHPENDING) {
! 1793: splx(s);
! 1794: return (EBUSY);
! 1795: }
! 1796:
! 1797: sc->sc_flags |= SC_SWITCHPENDING;
! 1798: sc->sc_screenwanted = no;
! 1799:
! 1800: splx(s);
! 1801:
! 1802: scr = sc->sc_focus;
! 1803: if (!scr) {
! 1804: sc->sc_oldscreen = WSDISPLAY_NULLSCREEN;
! 1805: return (wsdisplay_switch1(sc, 0, waitok));
! 1806: } else
! 1807: sc->sc_oldscreen = sc->sc_focusidx;
! 1808:
! 1809:
! 1810: #ifdef WSMOUSED_SUPPORT
! 1811: /*
! 1812: * wsmoused cohabitation with X-Window support
! 1813: *
! 1814: * Detect switch from a graphic to text console and vice-versa
! 1815: * This only happen when switching from X-Window to text mode and
! 1816: * switching back from text mode to X-Window.
! 1817: *
! 1818: * scr_flags is not yet flagged with SCR_GRAPHICS when X-Window starts
! 1819: * (KD_GRAPHICS ioctl happens after VT_ACTIVATE ioctl in
! 1820: * xf86OpenPcvt()). Conversely, scr_flags is no longer flagged with
! 1821: * SCR_GRAPHICS when X-Window stops. In this case, the first of the
! 1822: * three following 'if' statements is evaluated.
! 1823: * We handle wsmoused(8) events the WSDISPLAYIO_SMODE ioctl.
! 1824: */
! 1825:
! 1826: if (!(scr->scr_flags & SCR_GRAPHICS) &&
! 1827: (!(sc->sc_scr[no]->scr_flags & SCR_GRAPHICS))) {
! 1828: /* switching from a text console to another text console */
! 1829: /* XXX evaluated when the X-server starts or stops, see above */
! 1830:
! 1831: /* remove a potential wsmoused(8) selection */
! 1832: mouse_remove(sc);
! 1833: }
! 1834:
! 1835: if (!(scr->scr_flags & SCR_GRAPHICS) &&
! 1836: (sc->sc_scr[no]->scr_flags & SCR_GRAPHICS)) {
! 1837: /* switching from a text console to a graphic console */
! 1838:
! 1839: /* remote a potential wsmoused(8) selection */
! 1840: mouse_remove(sc);
! 1841: wsmoused_release(sc);
! 1842: }
! 1843:
! 1844: if ((scr->scr_flags & SCR_GRAPHICS) &&
! 1845: !(sc->sc_scr[no]->scr_flags & SCR_GRAPHICS)) {
! 1846: /* switching from a graphic console to a text console */
! 1847:
! 1848: wsmoused_wakeup(sc);
! 1849: }
! 1850: #endif /* WSMOUSED_SUPPORT */
! 1851:
! 1852: #ifdef WSDISPLAY_COMPAT_USL
! 1853: #define wsswitch_cb1 ((void (*)(void *, int, int))wsdisplay_switch1)
! 1854: if (scr->scr_syncops) {
! 1855: res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok,
! 1856: sc->sc_isconsole && wsdisplay_cons_pollmode ?
! 1857: 0 : wsswitch_cb1, sc);
! 1858: if (res == EAGAIN) {
! 1859: /* switch will be done asynchronously */
! 1860: return (0);
! 1861: }
! 1862: } else if (scr->scr_flags & SCR_GRAPHICS) {
! 1863: /* no way to save state */
! 1864: res = EBUSY;
! 1865: }
! 1866: #endif
! 1867:
! 1868: return (wsdisplay_switch1(sc, res, waitok));
! 1869: }
! 1870:
! 1871: void
! 1872: wsdisplay_reset(struct device *dev, enum wsdisplay_resetops op)
! 1873: {
! 1874: struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
! 1875: struct wsscreen *scr;
! 1876:
! 1877: KASSERT(sc != NULL);
! 1878: scr = sc->sc_focus;
! 1879:
! 1880: if (!scr)
! 1881: return;
! 1882:
! 1883: switch (op) {
! 1884: case WSDISPLAY_RESETEMUL:
! 1885: (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie,
! 1886: WSEMUL_RESET);
! 1887: break;
! 1888: case WSDISPLAY_RESETCLOSE:
! 1889: wsdisplay_closescreen(sc, scr);
! 1890: break;
! 1891: }
! 1892: }
! 1893:
! 1894: #ifdef WSDISPLAY_COMPAT_USL
! 1895: /*
! 1896: * Interface for (external) VT switch / process synchronization code
! 1897: */
! 1898: int
! 1899: wsscreen_attach_sync(struct wsscreen *scr, const struct wscons_syncops *ops,
! 1900: void *cookie)
! 1901: {
! 1902: if (scr->scr_syncops) {
! 1903: /*
! 1904: * The screen is already claimed.
! 1905: * Check if the owner is still alive.
! 1906: */
! 1907: if ((*scr->scr_syncops->check)(scr->scr_synccookie))
! 1908: return (EBUSY);
! 1909: }
! 1910: scr->scr_syncops = ops;
! 1911: scr->scr_synccookie = cookie;
! 1912: return (0);
! 1913: }
! 1914:
! 1915: int
! 1916: wsscreen_detach_sync(struct wsscreen *scr)
! 1917: {
! 1918: if (!scr->scr_syncops)
! 1919: return (EINVAL);
! 1920: scr->scr_syncops = 0;
! 1921: return (0);
! 1922: }
! 1923:
! 1924: int
! 1925: wsscreen_lookup_sync(struct wsscreen *scr,
! 1926: const struct wscons_syncops *ops, /* used as ID */
! 1927: void **cookiep)
! 1928: {
! 1929: if (!scr->scr_syncops || ops != scr->scr_syncops)
! 1930: return (EINVAL);
! 1931: *cookiep = scr->scr_synccookie;
! 1932: return (0);
! 1933: }
! 1934: #endif
! 1935:
! 1936: /*
! 1937: * Interface to virtual screen stuff
! 1938: */
! 1939: int
! 1940: wsdisplay_maxscreenidx(struct wsdisplay_softc *sc)
! 1941: {
! 1942: return (WSDISPLAY_MAXSCREEN - 1);
! 1943: }
! 1944:
! 1945: int
! 1946: wsdisplay_screenstate(struct wsdisplay_softc *sc, int idx)
! 1947: {
! 1948: if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN)
! 1949: return (EINVAL);
! 1950: if (!sc->sc_scr[idx])
! 1951: return (ENXIO);
! 1952: return ((sc->sc_scr[idx]->scr_flags & SCR_OPEN) ? EBUSY : 0);
! 1953: }
! 1954:
! 1955: int
! 1956: wsdisplay_getactivescreen(struct wsdisplay_softc *sc)
! 1957: {
! 1958: return (sc->sc_focus ? sc->sc_focusidx : WSDISPLAY_NULLSCREEN);
! 1959: }
! 1960:
! 1961: int
! 1962: wsscreen_switchwait(struct wsdisplay_softc *sc, int no)
! 1963: {
! 1964: struct wsscreen *scr;
! 1965: int s, res = 0;
! 1966:
! 1967: if (no == WSDISPLAY_NULLSCREEN) {
! 1968: s = spltty();
! 1969: while (sc->sc_focus && res == 0) {
! 1970: res = tsleep(sc, PCATCH, "wswait", 0);
! 1971: }
! 1972: splx(s);
! 1973: return (res);
! 1974: }
! 1975:
! 1976: if (no < 0 || no >= WSDISPLAY_MAXSCREEN)
! 1977: return (ENXIO);
! 1978: scr = sc->sc_scr[no];
! 1979: if (!scr)
! 1980: return (ENXIO);
! 1981:
! 1982: s = spltty();
! 1983: if (scr != sc->sc_focus) {
! 1984: scr->scr_flags |= SCR_WAITACTIVE;
! 1985: res = tsleep(scr, PCATCH, "wswait", 0);
! 1986: if (scr != sc->sc_scr[no])
! 1987: res = ENXIO; /* disappeared in the meantime */
! 1988: else
! 1989: scr->scr_flags &= ~SCR_WAITACTIVE;
! 1990: }
! 1991: splx(s);
! 1992: return (res);
! 1993: }
! 1994:
! 1995: void
! 1996: wsdisplay_kbdholdscreen(struct device *dev, int hold)
! 1997: {
! 1998: struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
! 1999: struct wsscreen *scr;
! 2000:
! 2001: scr = sc->sc_focus;
! 2002:
! 2003: if (hold)
! 2004: scr->scr_hold_screen = 1;
! 2005: else {
! 2006: scr->scr_hold_screen = 0;
! 2007: timeout_add(&scr->scr_tty->t_rstrt_to, 0); /* "immediate" */
! 2008: }
! 2009: }
! 2010:
! 2011: #if NWSKBD > 0
! 2012: void
! 2013: wsdisplay_set_console_kbd(struct wsevsrc *src)
! 2014: {
! 2015: if (wsdisplay_console_device == NULL) {
! 2016: src->me_dispdv = NULL;
! 2017: return;
! 2018: }
! 2019: #if NWSMUX > 0
! 2020: if (wsmux_attach_sc((struct wsmux_softc *)
! 2021: wsdisplay_console_device->sc_input, src)) {
! 2022: src->me_dispdv = NULL;
! 2023: return;
! 2024: }
! 2025: #else
! 2026: wsdisplay_console_device->sc_input = src;
! 2027: #endif
! 2028: src->me_dispdv = &wsdisplay_console_device->sc_dv;
! 2029: }
! 2030:
! 2031: #if NWSMUX == 0
! 2032: int
! 2033: wsdisplay_set_kbd(struct device *disp, struct wsevsrc *kbd)
! 2034: {
! 2035: struct wsdisplay_softc *sc = (struct wsdisplay_softc *)disp;
! 2036:
! 2037: if (sc->sc_input != NULL)
! 2038: return (EBUSY);
! 2039:
! 2040: sc->sc_input = kbd;
! 2041:
! 2042: return (0);
! 2043: }
! 2044: #endif
! 2045:
! 2046: #endif /* NWSKBD > 0 */
! 2047:
! 2048: /*
! 2049: * Console interface.
! 2050: */
! 2051: void
! 2052: wsdisplay_cnputc(dev_t dev, int i)
! 2053: {
! 2054: struct wsscreen_internal *dc;
! 2055: char c = i;
! 2056:
! 2057: if (!wsdisplay_console_initted)
! 2058: return;
! 2059:
! 2060: if (wsdisplay_console_device != NULL &&
! 2061: (wsdisplay_console_device->sc_scr[0] != NULL) &&
! 2062: (wsdisplay_console_device->sc_scr[0]->scr_flags & SCR_GRAPHICS))
! 2063: return;
! 2064:
! 2065: dc = &wsdisplay_console_conf;
! 2066: #ifdef BURNER_SUPPORT
! 2067: /*wsdisplay_burn(wsdisplay_console_device, WSDISPLAY_BURN_OUTPUT);*/
! 2068: #endif
! 2069: (*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1);
! 2070: }
! 2071:
! 2072: int
! 2073: wsdisplay_getc_dummy(dev_t dev)
! 2074: {
! 2075: /* panic? */
! 2076: return (0);
! 2077: }
! 2078:
! 2079: void
! 2080: wsdisplay_pollc(dev_t dev, int on)
! 2081: {
! 2082:
! 2083: wsdisplay_cons_pollmode = on;
! 2084:
! 2085: /* notify to fb drivers */
! 2086: if (wsdisplay_console_device != NULL &&
! 2087: wsdisplay_console_device->sc_accessops->pollc != NULL)
! 2088: (*wsdisplay_console_device->sc_accessops->pollc)
! 2089: (wsdisplay_console_device->sc_accesscookie, on);
! 2090:
! 2091: /* notify to kbd drivers */
! 2092: if (wsdisplay_cons_kbd_pollc)
! 2093: (*wsdisplay_cons_kbd_pollc)(dev, on);
! 2094: }
! 2095:
! 2096: void
! 2097: wsdisplay_set_cons_kbd(int (*get)(dev_t), void (*poll)(dev_t, int),
! 2098: void (*bell)(dev_t, u_int, u_int, u_int))
! 2099: {
! 2100: wsdisplay_cons.cn_getc = get;
! 2101: wsdisplay_cons.cn_bell = bell;
! 2102: wsdisplay_cons_kbd_pollc = poll;
! 2103: }
! 2104:
! 2105: void
! 2106: wsdisplay_unset_cons_kbd()
! 2107: {
! 2108: wsdisplay_cons.cn_getc = wsdisplay_getc_dummy;
! 2109: wsdisplay_cons.cn_bell = NULL;
! 2110: wsdisplay_cons_kbd_pollc = 0;
! 2111: }
! 2112:
! 2113: /*
! 2114: * Switch the console display to its first screen.
! 2115: */
! 2116: void
! 2117: wsdisplay_switchtoconsole()
! 2118: {
! 2119: struct wsdisplay_softc *sc;
! 2120: struct wsscreen *scr;
! 2121:
! 2122: if (wsdisplay_console_device != NULL) {
! 2123: sc = wsdisplay_console_device;
! 2124: if ((scr = sc->sc_scr[0]) == NULL)
! 2125: return;
! 2126: (*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
! 2127: scr->scr_dconf->emulcookie, 0, NULL, NULL);
! 2128: }
! 2129: }
! 2130:
! 2131: #ifdef SCROLLBACK_SUPPORT
! 2132: void
! 2133: wsscrollback(void *arg, int op)
! 2134: {
! 2135: struct wsdisplay_softc *sc = arg;
! 2136: int lines;
! 2137:
! 2138: if (op == WSDISPLAY_SCROLL_RESET)
! 2139: lines = 0;
! 2140: else {
! 2141: lines = sc->sc_focus->scr_dconf->scrdata->nrows - 1;
! 2142: if (op == WSDISPLAY_SCROLL_BACKWARD)
! 2143: lines = -lines;
! 2144: }
! 2145:
! 2146: if (sc->sc_accessops->scrollback) {
! 2147: (*sc->sc_accessops->scrollback)(sc->sc_accesscookie,
! 2148: sc->sc_focus->scr_dconf->emulcookie, lines);
! 2149: }
! 2150: }
! 2151: #endif
! 2152:
! 2153: #ifdef BURNER_SUPPORT
! 2154: void
! 2155: wsdisplay_burn(void *v, u_int flags)
! 2156: {
! 2157: struct wsdisplay_softc *sc = v;
! 2158:
! 2159: if ((flags & sc->sc_burnflags & (WSDISPLAY_BURN_OUTPUT |
! 2160: WSDISPLAY_BURN_KBD | WSDISPLAY_BURN_MOUSE)) &&
! 2161: sc->sc_accessops->burn_screen) {
! 2162: if (sc->sc_burnout)
! 2163: timeout_add(&sc->sc_burner, sc->sc_burnout);
! 2164: if (sc->sc_burnman)
! 2165: sc->sc_burnout = 0;
! 2166: }
! 2167: }
! 2168:
! 2169: void
! 2170: wsdisplay_burner(void *v)
! 2171: {
! 2172: struct wsdisplay_softc *sc = v;
! 2173: int s;
! 2174:
! 2175: if (sc->sc_accessops->burn_screen) {
! 2176: (*sc->sc_accessops->burn_screen)(sc->sc_accesscookie,
! 2177: sc->sc_burnman, sc->sc_burnflags);
! 2178: s = spltty();
! 2179: if (sc->sc_burnman) {
! 2180: sc->sc_burnout = sc->sc_burnoutintvl;
! 2181: timeout_add(&sc->sc_burner, sc->sc_burnout);
! 2182: } else
! 2183: sc->sc_burnout = sc->sc_burninintvl;
! 2184: sc->sc_burnman = !sc->sc_burnman;
! 2185: splx(s);
! 2186: }
! 2187: }
! 2188: #endif
! 2189:
! 2190: /*
! 2191: * Switch the console at shutdown.
! 2192: */
! 2193: void
! 2194: wsdisplay_shutdownhook(void *arg)
! 2195: {
! 2196: wsdisplay_switchtoconsole();
! 2197: }
! 2198:
! 2199: #ifdef WSMOUSED_SUPPORT
! 2200: /*
! 2201: * wsmoused(8) support functions
! 2202: */
! 2203:
! 2204: /* pointer to the current screen wsdisplay_softc structure */
! 2205: static struct wsdisplay_softc *sc = NULL;
! 2206:
! 2207: /*
! 2208: * Main function, called from wsdisplay_cfg_ioctl.
! 2209: */
! 2210: int
! 2211: wsmoused(struct wsdisplay_softc *ws_sc, u_long cmd, caddr_t data,
! 2212: int flag, struct proc *p)
! 2213: {
! 2214: int error = -1;
! 2215: struct wscons_event mouse_event = *(struct wscons_event *)data;
! 2216:
! 2217: if (cmd == WSDISPLAYIO_WSMOUSED) {
! 2218: if (IS_MOTION_EVENT(mouse_event.type)) {
! 2219: motion_event(mouse_event.type, mouse_event.value);
! 2220: return (0);
! 2221: }
! 2222: if (IS_BUTTON_EVENT(mouse_event.type)) {
! 2223: /* XXX tv_sec contains the number of clicks */
! 2224: if (mouse_event.type == WSCONS_EVENT_MOUSE_DOWN) {
! 2225: button_event(mouse_event.value,
! 2226: mouse_event.time.tv_sec);
! 2227: } else
! 2228: button_event(mouse_event.value, 0);
! 2229: return (0);
! 2230: }
! 2231: if (IS_CTRL_EVENT(mouse_event.type)) {
! 2232: return (ctrl_event(mouse_event.type, mouse_event.value,
! 2233: ws_sc, p));
! 2234: }
! 2235: }
! 2236: return (error);
! 2237: }
! 2238:
! 2239: /*
! 2240: * Mouse motion events
! 2241: */
! 2242: void
! 2243: motion_event(u_int type, int value)
! 2244: {
! 2245: switch (type) {
! 2246: case WSCONS_EVENT_MOUSE_DELTA_X:
! 2247: mouse_moverel(value, 0);
! 2248: break;
! 2249: case WSCONS_EVENT_MOUSE_DELTA_Y:
! 2250: mouse_moverel(0, 0 - value);
! 2251: break;
! 2252: case WSCONS_EVENT_MOUSE_DELTA_Z:
! 2253: mouse_zaxis(value);
! 2254: break;
! 2255: default:
! 2256: break;
! 2257: }
! 2258: }
! 2259:
! 2260: /*
! 2261: * Button clicks events
! 2262: */
! 2263: void
! 2264: button_event(int button, int clicks)
! 2265: {
! 2266: switch (button) {
! 2267: case MOUSE_COPY_BUTTON:
! 2268: switch (clicks % 4) {
! 2269: case 0: /* button is up */
! 2270: mouse_copy_end();
! 2271: mouse_copy_selection();
! 2272: break;
! 2273: case 1: /* single click */
! 2274: mouse_copy_start();
! 2275: mouse_copy_selection();
! 2276: break;
! 2277: case 2: /* double click */
! 2278: mouse_copy_word();
! 2279: mouse_copy_selection();
! 2280: break;
! 2281: case 3: /* triple click */
! 2282: mouse_copy_line();
! 2283: mouse_copy_selection();
! 2284: break;
! 2285: default:
! 2286: break;
! 2287: }
! 2288: break;
! 2289:
! 2290: case MOUSE_PASTE_BUTTON:
! 2291: switch (clicks) {
! 2292: case 0: /* button is up */
! 2293: break;
! 2294: default: /* paste */
! 2295: mouse_paste();
! 2296: break;
! 2297: }
! 2298: break;
! 2299:
! 2300: case MOUSE_EXTEND_BUTTON:
! 2301: switch (clicks) {
! 2302: case 0: /* button is up */
! 2303: break;
! 2304: default: /* extend the selection */
! 2305: mouse_copy_extend_after();
! 2306: break;
! 2307: }
! 2308: break;
! 2309:
! 2310: default:
! 2311: break;
! 2312: }
! 2313: }
! 2314:
! 2315: /*
! 2316: * Control events
! 2317: */
! 2318: int
! 2319: ctrl_event(u_int type, int value, struct wsdisplay_softc *ws_sc, struct proc *p)
! 2320: {
! 2321: int i, error;
! 2322:
! 2323: if (type == WSCONS_EVENT_WSMOUSED_ON) {
! 2324: if (!ws_sc->sc_accessops->getchar)
! 2325: /* no wsmoused(8) support in the display driver */
! 2326: return (1);
! 2327: /* initialization of globals */
! 2328: sc = ws_sc;
! 2329: allocate_copybuffer(sc);
! 2330: Paste_avail = 0;
! 2331: ws_sc->wsmoused_dev = value;
! 2332: }
! 2333: if (type == WSCONS_EVENT_WSMOUSED_OFF) {
! 2334: Paste_avail = 0;
! 2335: ws_sc->wsmoused_dev = 0;
! 2336: return (0);
! 2337: }
! 2338: if (type == WSCONS_EVENT_WSMOUSED_SLEEP) {
! 2339: /* sleeping until next switch to text mode */
! 2340: ws_sc->wsmoused_sleep = 1;
! 2341: error = 0;
! 2342: while (ws_sc->wsmoused_sleep && error == 0)
! 2343: error = tsleep(&ws_sc->wsmoused_sleep, PPAUSE,
! 2344: "wsmoused_sleep", 0);
! 2345: return (error);
! 2346: }
! 2347: for (i = 0 ; i < WSDISPLAY_DEFAULTSCREENS ; i++)
! 2348: if (sc->sc_scr[i]) {
! 2349: sc->sc_scr[i]->mouse =
! 2350: ((WS_NCOLS(sc->sc_scr[i]) *
! 2351: WS_NROWS(sc->sc_scr[i])) / 2);
! 2352: sc->sc_scr[i]->cursor = sc->sc_scr[i]->mouse;
! 2353: sc->sc_scr[i]->cpy_start = 0;
! 2354: sc->sc_scr[i]->cpy_end = 0;
! 2355: sc->sc_scr[i]->orig_start = 0;
! 2356: sc->sc_scr[i]->orig_end = 0;
! 2357: sc->sc_scr[i]->mouse_flags = 0;
! 2358: }
! 2359: return (0);
! 2360: }
! 2361:
! 2362: void
! 2363: mouse_moverel(char dx, char dy)
! 2364: {
! 2365: unsigned short old_mouse = MOUSE;
! 2366: unsigned char mouse_col = (MOUSE % N_COLS);
! 2367: unsigned char mouse_row = (MOUSE / N_COLS);
! 2368:
! 2369: /* wscons has support for screen saver via the WSDISPLAYIO_{G,S}VIDEO
! 2370: with WSDISPLAY_VIDEO_OFF and WSDISPLAY_VIDEO_ON values.
! 2371: However, none of the pc display driver (pcdisplay.c or vga.c)
! 2372: support this ioctl. Only the alpha display driver (tga.c) support it.
! 2373:
! 2374: When screen saver support is available, /usr/sbin/screenblank can be
! 2375: used with the -m option, so that mice movements stop the screen
! 2376: saver.
! 2377: */
! 2378:
! 2379: /* update position */
! 2380:
! 2381: if (mouse_col + dx >= MAXCOL)
! 2382: mouse_col = MAXCOL;
! 2383: else {
! 2384: if (mouse_col + dx <= 0)
! 2385: mouse_col = 0;
! 2386: else
! 2387: mouse_col += dx;
! 2388: }
! 2389: if (mouse_row + dy >= MAXROW)
! 2390: mouse_row = MAXROW;
! 2391: else {
! 2392: if (mouse_row + dy <= 0)
! 2393: mouse_row = 0;
! 2394: else
! 2395: mouse_row += dy;
! 2396: }
! 2397: MOUSE = XY_TO_POS(mouse_col, mouse_row);
! 2398: /* if we have moved */
! 2399: if (old_mouse != MOUSE) {
! 2400: if (IS_SEL_IN_PROGRESS(sc->sc_focus)) {
! 2401: /* selection in progress */
! 2402: mouse_copy_extend();
! 2403: } else {
! 2404: inverse_char(MOUSE);
! 2405: if (IS_MOUSE_VISIBLE(sc->sc_focus))
! 2406: inverse_char(old_mouse);
! 2407: else
! 2408: MOUSE_FLAGS |= MOUSE_VISIBLE;
! 2409: }
! 2410: }
! 2411: }
! 2412:
! 2413: void
! 2414: inverse_char(unsigned short pos)
! 2415: {
! 2416: struct wsscreen_internal *dconf;
! 2417: struct wsdisplay_charcell cell;
! 2418: int fg, bg, ul;
! 2419: int flags;
! 2420: int tmp;
! 2421: long attr;
! 2422:
! 2423: dconf = sc->sc_focus->scr_dconf;
! 2424:
! 2425: GETCHAR(pos, &cell);
! 2426:
! 2427: (*dconf->emulops->unpack_attr)(dconf->emulcookie, cell.attr, &fg,
! 2428: &bg, &ul);
! 2429:
! 2430: /*
! 2431: * Display the mouse cursor as a color inverted cell whenever
! 2432: * possible. If this is not possible, ask for the video reverse
! 2433: * attribute.
! 2434: */
! 2435: flags = 0;
! 2436: if (dconf->scrdata->capabilities & WSSCREEN_WSCOLORS) {
! 2437: flags |= WSATTR_WSCOLORS;
! 2438: tmp = fg;
! 2439: fg = bg;
! 2440: bg = tmp;
! 2441: } else if (dconf->scrdata->capabilities & WSSCREEN_REVERSE) {
! 2442: flags |= WSATTR_REVERSE;
! 2443: }
! 2444: if ((*dconf->emulops->alloc_attr)(dconf->emulcookie, fg, bg, flags |
! 2445: (ul ? WSATTR_UNDERLINE : 0), &attr) == 0) {
! 2446: cell.attr = attr;
! 2447: PUTCHAR(pos, cell.uc, cell.attr);
! 2448: }
! 2449: }
! 2450:
! 2451: void
! 2452: inverse_region(unsigned short start, unsigned short end)
! 2453: {
! 2454: unsigned short current_pos;
! 2455: unsigned short abs_end;
! 2456:
! 2457: /* sanity check, useful because 'end' can be (0 - 1) = 65535 */
! 2458: abs_end = N_COLS * N_ROWS;
! 2459: if (end > abs_end)
! 2460: return;
! 2461: current_pos = start;
! 2462: while (current_pos <= end)
! 2463: inverse_char(current_pos++);
! 2464: }
! 2465:
! 2466: /*
! 2467: * Return the number of contiguous blank characters between the right margin
! 2468: * if border == 1 or between the next non-blank character and the current mouse
! 2469: * cursor if border == 0
! 2470: */
! 2471: unsigned char
! 2472: skip_spc_right(char border)
! 2473: {
! 2474: struct wsdisplay_charcell cell;
! 2475: unsigned short current = CPY_END;
! 2476: unsigned short mouse_col = (CPY_END % N_COLS);
! 2477: unsigned short limit = current + (N_COLS - mouse_col - 1);
! 2478: unsigned char res = 0;
! 2479:
! 2480: while (GETCHAR(current, &cell) == 0 && cell.uc == ' ' &&
! 2481: current <= limit) {
! 2482: current++;
! 2483: res++;
! 2484: }
! 2485: if (border == BORDER) {
! 2486: if (current > limit)
! 2487: return (res - 1);
! 2488: else
! 2489: return (0);
! 2490: } else {
! 2491: if (res)
! 2492: return (res - 1);
! 2493: else
! 2494: return (res);
! 2495: }
! 2496: }
! 2497:
! 2498: /*
! 2499: * Return the number of contiguous blank characters between the first of the
! 2500: * contiguous blank characters and the current mouse cursor
! 2501: */
! 2502: unsigned char
! 2503: skip_spc_left(void)
! 2504: {
! 2505: struct wsdisplay_charcell cell;
! 2506: short current = CPY_START;
! 2507: unsigned short mouse_col = (MOUSE % N_COLS);
! 2508: unsigned short limit = current - mouse_col;
! 2509: unsigned char res = 0;
! 2510:
! 2511: while (GETCHAR(current, &cell) == 0 && cell.uc == ' ' &&
! 2512: current >= limit) {
! 2513: current--;
! 2514: res++;
! 2515: }
! 2516: if (res)
! 2517: res--;
! 2518: return (res);
! 2519: }
! 2520:
! 2521: /*
! 2522: * Class of characters
! 2523: * Stolen from xterm sources of the Xfree project (see cvs tag below)
! 2524: * $TOG: button.c /main/76 1997/07/30 16:56:19 kaleb $
! 2525: */
! 2526: static const int charClass[256] = {
! 2527: /* NUL SOH STX ETX EOT ENQ ACK BEL */
! 2528: 32, 1, 1, 1, 1, 1, 1, 1,
! 2529: /* BS HT NL VT NP CR SO SI */
! 2530: 1, 32, 1, 1, 1, 1, 1, 1,
! 2531: /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
! 2532: 1, 1, 1, 1, 1, 1, 1, 1,
! 2533: /* CAN EM SUB ESC FS GS RS US */
! 2534: 1, 1, 1, 1, 1, 1, 1, 1,
! 2535: /* SP ! " # $ % & ' */
! 2536: 32, 33, 34, 35, 36, 37, 38, 39,
! 2537: /* ( ) * + , - . / */
! 2538: 40, 41, 42, 43, 44, 45, 46, 47,
! 2539: /* 0 1 2 3 4 5 6 7 */
! 2540: 48, 48, 48, 48, 48, 48, 48, 48,
! 2541: /* 8 9 : ; < = > ? */
! 2542: 48, 48, 58, 59, 60, 61, 62, 63,
! 2543: /* @ A B C D E F G */
! 2544: 64, 48, 48, 48, 48, 48, 48, 48,
! 2545: /* H I J K L M N O */
! 2546: 48, 48, 48, 48, 48, 48, 48, 48,
! 2547: /* P Q R S T U V W */
! 2548: 48, 48, 48, 48, 48, 48, 48, 48,
! 2549: /* X Y Z [ \ ] ^ _ */
! 2550: 48, 48, 48, 91, 92, 93, 94, 48,
! 2551: /* ` a b c d e f g */
! 2552: 96, 48, 48, 48, 48, 48, 48, 48,
! 2553: /* h i j k l m n o */
! 2554: 48, 48, 48, 48, 48, 48, 48, 48,
! 2555: /* p q r s t u v w */
! 2556: 48, 48, 48, 48, 48, 48, 48, 48,
! 2557: /* x y z { | } ~ DEL */
! 2558: 48, 48, 48, 123, 124, 125, 126, 1,
! 2559: /* x80 x81 x82 x83 IND NEL SSA ESA */
! 2560: 1, 1, 1, 1, 1, 1, 1, 1,
! 2561: /* HTS HTJ VTS PLD PLU RI SS2 SS3 */
! 2562: 1, 1, 1, 1, 1, 1, 1, 1,
! 2563: /* DCS PU1 PU2 STS CCH MW SPA EPA */
! 2564: 1, 1, 1, 1, 1, 1, 1, 1,
! 2565: /* x98 x99 x9A CSI ST OSC PM APC */
! 2566: 1, 1, 1, 1, 1, 1, 1, 1,
! 2567: /* - i c/ L ox Y- | So */
! 2568: 160, 161, 162, 163, 164, 165, 166, 167,
! 2569: /* .. c0 ip << _ R0 - */
! 2570: 168, 169, 170, 171, 172, 173, 174, 175,
! 2571: /* o +- 2 3 ' u q| . */
! 2572: 176, 177, 178, 179, 180, 181, 182, 183,
! 2573: /* , 1 2 >> 1/4 1/2 3/4 ? */
! 2574: 184, 185, 186, 187, 188, 189, 190, 191,
! 2575: /* A` A' A^ A~ A: Ao AE C, */
! 2576: 48, 48, 48, 48, 48, 48, 48, 48,
! 2577: /* E` E' E^ E: I` I' I^ I: */
! 2578: 48, 48, 48, 48, 48, 48, 48, 48,
! 2579: /* D- N~ O` O' O^ O~ O: X */
! 2580: 48, 48, 48, 48, 48, 48, 48, 216,
! 2581: /* O/ U` U' U^ U: Y' P B */
! 2582: 48, 48, 48, 48, 48, 48, 48, 48,
! 2583: /* a` a' a^ a~ a: ao ae c, */
! 2584: 48, 48, 48, 48, 48, 48, 48, 48,
! 2585: /* e` e' e^ e: i` i' i^ i: */
! 2586: 48, 48, 48, 48, 48, 48, 48, 48,
! 2587: /* d n~ o` o' o^ o~ o: -: */
! 2588: 48, 48, 48, 48, 48, 48, 48, 248,
! 2589: /* o/ u` u' u^ u: y' P y: */
! 2590: 48, 48, 48, 48, 48, 48, 48, 48
! 2591: };
! 2592:
! 2593: /*
! 2594: * Find the first blank beginning after the current cursor position
! 2595: */
! 2596: unsigned char
! 2597: skip_char_right(unsigned short offset)
! 2598: {
! 2599: struct wsdisplay_charcell cell;
! 2600: unsigned short current = offset;
! 2601: unsigned short limit = current + (N_COLS - (MOUSE % N_COLS) - 1);
! 2602: unsigned char class;
! 2603: unsigned char res = 0;
! 2604:
! 2605: GETCHAR(current, &cell);
! 2606: class = charClass[cell.uc & 0xff];
! 2607: while (GETCHAR(current, &cell) == 0 &&
! 2608: charClass[cell.uc & 0xff] == class && current <= limit) {
! 2609: current++;
! 2610: res++;
! 2611: }
! 2612: if (res)
! 2613: res--;
! 2614: return (res);
! 2615: }
! 2616:
! 2617: /*
! 2618: * Find the first non-blank character before the cursor position
! 2619: */
! 2620: unsigned char
! 2621: skip_char_left(unsigned short offset)
! 2622: {
! 2623: struct wsdisplay_charcell cell;
! 2624: short current = offset;
! 2625: unsigned short limit = current - (MOUSE % N_COLS);
! 2626: unsigned char class;
! 2627: unsigned char res = 0;
! 2628:
! 2629: GETCHAR(current, &cell);
! 2630: class = charClass[cell.uc & 0xff];
! 2631: while (GETCHAR(current, &cell) == 0 &&
! 2632: charClass[cell.uc & 0xff] == class && current >= limit) {
! 2633: current--;
! 2634: res++;
! 2635: }
! 2636: if (res)
! 2637: res--;
! 2638: return (res);
! 2639: }
! 2640:
! 2641: /*
! 2642: * Compare character classes
! 2643: */
! 2644: unsigned char
! 2645: class_cmp(unsigned short first, unsigned short second)
! 2646: {
! 2647: struct wsdisplay_charcell cell;
! 2648: unsigned char first_class;
! 2649: unsigned char second_class;
! 2650:
! 2651: if (GETCHAR(first, &cell) != 0)
! 2652: return (1);
! 2653: first_class = charClass[cell.uc & 0xff];
! 2654: if (GETCHAR(second, &cell) != 0)
! 2655: return (1);
! 2656: second_class = charClass[cell.uc & 0xff];
! 2657:
! 2658: if (first_class != second_class)
! 2659: return (1);
! 2660: else
! 2661: return (0);
! 2662: }
! 2663:
! 2664: /*
! 2665: * Beginning of a copy operation
! 2666: */
! 2667: void
! 2668: mouse_copy_start(void)
! 2669: {
! 2670: unsigned char right;
! 2671: /* if no selection, then that's the first one */
! 2672:
! 2673: if (!Paste_avail)
! 2674: Paste_avail = 1;
! 2675:
! 2676: /* remove the previous selection */
! 2677:
! 2678: if (IS_SEL_EXISTS(sc->sc_focus))
! 2679: remove_selection(sc);
! 2680:
! 2681: /* initial show of the cursor */
! 2682: if (!IS_MOUSE_VISIBLE(sc->sc_focus))
! 2683: inverse_char(MOUSE);
! 2684:
! 2685: CPY_START = MOUSE;
! 2686: CPY_END = MOUSE;
! 2687: ORIG_START = CPY_START;
! 2688: ORIG_END = CPY_END;
! 2689: CURSOR = CPY_END + 1; /* init value */
! 2690:
! 2691: right = skip_spc_right(BORDER); /* useful later, in mouse_copy_extend */
! 2692: if (right)
! 2693: MOUSE_FLAGS |= BLANK_TO_EOL;
! 2694:
! 2695: MOUSE_FLAGS |= SEL_IN_PROGRESS;
! 2696: MOUSE_FLAGS |= SEL_EXISTS;
! 2697: MOUSE_FLAGS |= SEL_BY_CHAR; /* select by char */
! 2698: MOUSE_FLAGS &= ~SEL_BY_WORD;
! 2699: MOUSE_FLAGS &= ~SEL_BY_LINE;
! 2700: MOUSE_FLAGS &= ~MOUSE_VISIBLE; /* cursor hidden in selection */
! 2701: }
! 2702:
! 2703: /*
! 2704: * Copy of the word under the cursor
! 2705: */
! 2706: void
! 2707: mouse_copy_word()
! 2708: {
! 2709: struct wsdisplay_charcell cell;
! 2710: unsigned char right;
! 2711: unsigned char left;
! 2712:
! 2713: if (IS_SEL_EXISTS(sc->sc_focus))
! 2714: remove_selection(sc);
! 2715:
! 2716: if (IS_MOUSE_VISIBLE(sc->sc_focus))
! 2717: inverse_char(MOUSE);
! 2718:
! 2719: CPY_START = MOUSE;
! 2720: CPY_END = MOUSE;
! 2721:
! 2722: if (GETCHAR(MOUSE, &cell) == 0 && IS_ALPHANUM(cell.uc)) {
! 2723: right = skip_char_right(CPY_END);
! 2724: left = skip_char_left(CPY_START);
! 2725: } else {
! 2726: right = skip_spc_right(NO_BORDER);
! 2727: left = skip_spc_left();
! 2728: }
! 2729:
! 2730: CPY_START -= left;
! 2731: CPY_END += right;
! 2732: ORIG_START = CPY_START;
! 2733: ORIG_END = CPY_END;
! 2734: CURSOR = CPY_END + 1; /* init value, never happen */
! 2735: inverse_region(CPY_START, CPY_END);
! 2736:
! 2737: MOUSE_FLAGS |= SEL_IN_PROGRESS;
! 2738: MOUSE_FLAGS |= SEL_EXISTS;
! 2739: MOUSE_FLAGS &= ~SEL_BY_CHAR;
! 2740: MOUSE_FLAGS |= SEL_BY_WORD;
! 2741: MOUSE_FLAGS &= ~SEL_BY_LINE;
! 2742:
! 2743: /* mouse cursor hidden in the selection */
! 2744: MOUSE_FLAGS &= ~BLANK_TO_EOL;
! 2745: MOUSE_FLAGS &= ~MOUSE_VISIBLE;
! 2746: }
! 2747:
! 2748: /*
! 2749: * Copy of the current line
! 2750: */
! 2751: void
! 2752: mouse_copy_line(void)
! 2753: {
! 2754: unsigned char row = MOUSE / N_COLS;
! 2755:
! 2756: if (IS_SEL_EXISTS(sc->sc_focus))
! 2757: remove_selection(sc);
! 2758:
! 2759: if (IS_MOUSE_VISIBLE(sc->sc_focus))
! 2760: inverse_char(MOUSE);
! 2761:
! 2762: CPY_START = row * N_COLS;
! 2763: CPY_END = CPY_START + (N_COLS - 1);
! 2764: ORIG_START = CPY_START;
! 2765: ORIG_END = CPY_END;
! 2766: CURSOR = CPY_END + 1;
! 2767: inverse_region(CPY_START, CPY_END);
! 2768:
! 2769: MOUSE_FLAGS |= SEL_IN_PROGRESS;
! 2770: MOUSE_FLAGS |= SEL_EXISTS;
! 2771: MOUSE_FLAGS &= ~SEL_BY_CHAR;
! 2772: MOUSE_FLAGS &= ~SEL_BY_WORD;
! 2773: MOUSE_FLAGS |= SEL_BY_LINE;
! 2774:
! 2775: /* mouse cursor hidden in the selection */
! 2776: MOUSE_FLAGS &= ~BLANK_TO_EOL;
! 2777: MOUSE_FLAGS &= ~MOUSE_VISIBLE;
! 2778: }
! 2779:
! 2780: /*
! 2781: * End of a copy operation
! 2782: */
! 2783: void
! 2784: mouse_copy_end(void)
! 2785: {
! 2786: MOUSE_FLAGS &= ~(SEL_IN_PROGRESS);
! 2787: if (IS_SEL_BY_WORD(sc->sc_focus) || IS_SEL_BY_LINE(sc->sc_focus)) {
! 2788: if (CURSOR != (CPY_END + 1))
! 2789: inverse_char(CURSOR);
! 2790: CURSOR = CPY_END + 1;
! 2791: }
! 2792: }
! 2793:
! 2794:
! 2795: /*
! 2796: * Generic selection extend function
! 2797: */
! 2798: void
! 2799: mouse_copy_extend(void)
! 2800: {
! 2801: if (IS_SEL_BY_CHAR(sc->sc_focus))
! 2802: mouse_copy_extend_char();
! 2803: if (IS_SEL_BY_WORD(sc->sc_focus))
! 2804: mouse_copy_extend_word();
! 2805: if (IS_SEL_BY_LINE(sc->sc_focus))
! 2806: mouse_copy_extend_line();
! 2807: }
! 2808:
! 2809: /*
! 2810: * Extend a selected region, character by character
! 2811: */
! 2812: void
! 2813: mouse_copy_extend_char()
! 2814: {
! 2815: unsigned char right;
! 2816:
! 2817: if (!IS_SEL_EXT_AFTER(sc->sc_focus)) {
! 2818:
! 2819: if (IS_BLANK_TO_EOL(sc->sc_focus)) {
! 2820: /*
! 2821: * First extension of selection. We handle special
! 2822: * cases of blank characters to eol
! 2823: */
! 2824:
! 2825: right = skip_spc_right(BORDER);
! 2826: if (MOUSE > ORIG_START) {
! 2827: /* the selection goes to the lower part of
! 2828: the screen */
! 2829:
! 2830: /* remove the previous cursor, start of
! 2831: selection is now next line */
! 2832: inverse_char(CPY_START);
! 2833: CPY_START += (right + 1);
! 2834: CPY_END = CPY_START;
! 2835: ORIG_START = CPY_START;
! 2836: /* simulate the initial mark */
! 2837: inverse_char(CPY_START);
! 2838: } else {
! 2839: /* the selection goes to the upper part
! 2840: of the screen */
! 2841: /* remove the previous cursor, start of
! 2842: selection is now at the eol */
! 2843: inverse_char(CPY_START);
! 2844: ORIG_START += (right + 1);
! 2845: CPY_START = ORIG_START - 1;
! 2846: CPY_END = ORIG_START - 1;
! 2847: /* simulate the initial mark */
! 2848: inverse_char(CPY_START);
! 2849: }
! 2850: MOUSE_FLAGS &= ~ BLANK_TO_EOL;
! 2851: }
! 2852:
! 2853: if (MOUSE < ORIG_START && CPY_END >= ORIG_START) {
! 2854: /* we go to the upper part of the screen */
! 2855:
! 2856: /* reverse the old selection region */
! 2857: remove_selection(sc);
! 2858: CPY_END = ORIG_START - 1;
! 2859: CPY_START = ORIG_START;
! 2860: }
! 2861: if (CPY_START < ORIG_START && MOUSE >= ORIG_START) {
! 2862: /* we go to the lower part of the screen */
! 2863:
! 2864: /* reverse the old selection region */
! 2865:
! 2866: remove_selection(sc);
! 2867: CPY_START = ORIG_START;
! 2868: CPY_END = ORIG_START - 1;
! 2869: }
! 2870: /* restore flags cleared in remove_selection() */
! 2871: MOUSE_FLAGS |= SEL_IN_PROGRESS;
! 2872: MOUSE_FLAGS |= SEL_EXISTS;
! 2873: }
! 2874: /* beginning of common part */
! 2875:
! 2876: if (MOUSE >= ORIG_START) {
! 2877:
! 2878: /* lower part of the screen */
! 2879: if (MOUSE > CPY_END) {
! 2880: /* extending selection */
! 2881: inverse_region(CPY_END + 1, MOUSE);
! 2882: } else {
! 2883: /* reducing selection */
! 2884: inverse_region(MOUSE + 1, CPY_END);
! 2885: }
! 2886: CPY_END = MOUSE;
! 2887: } else {
! 2888: /* upper part of the screen */
! 2889: if (MOUSE < CPY_START) {
! 2890: /* extending selection */
! 2891: inverse_region(MOUSE,CPY_START - 1);
! 2892: } else {
! 2893: /* reducing selection */
! 2894: inverse_region(CPY_START,MOUSE - 1);
! 2895: }
! 2896: CPY_START = MOUSE;
! 2897: }
! 2898: /* end of common part */
! 2899: }
! 2900:
! 2901: /*
! 2902: * Extend a selected region, word by word
! 2903: */
! 2904: void
! 2905: mouse_copy_extend_word(void)
! 2906: {
! 2907: unsigned short old_cpy_end;
! 2908: unsigned short old_cpy_start;
! 2909:
! 2910: if (!IS_SEL_EXT_AFTER(sc->sc_focus)) {
! 2911:
! 2912: /* remove cursor in selection (black one) */
! 2913:
! 2914: if (CURSOR != (CPY_END + 1))
! 2915: inverse_char(CURSOR);
! 2916:
! 2917: /* now, switch between lower and upper part of the screen */
! 2918:
! 2919: if (MOUSE < ORIG_START && CPY_END >= ORIG_START) {
! 2920: /* going to the upper part of the screen */
! 2921: inverse_region(ORIG_END + 1, CPY_END);
! 2922: CPY_END = ORIG_END;
! 2923: }
! 2924:
! 2925: if (MOUSE > ORIG_END && CPY_START <= ORIG_START) {
! 2926: /* going to the lower part of the screen */
! 2927: inverse_region(CPY_START, ORIG_START - 1);
! 2928: CPY_START = ORIG_START;
! 2929: }
! 2930: }
! 2931:
! 2932: if (MOUSE >= ORIG_START) {
! 2933: /* lower part of the screen */
! 2934:
! 2935: if (MOUSE > CPY_END) {
! 2936: /* extending selection */
! 2937:
! 2938: old_cpy_end = CPY_END;
! 2939: CPY_END = MOUSE + skip_char_right(MOUSE);
! 2940: inverse_region(old_cpy_end + 1, CPY_END);
! 2941: } else {
! 2942: if (class_cmp(MOUSE, MOUSE + 1)) {
! 2943: /* reducing selection (remove last word) */
! 2944: old_cpy_end = CPY_END;
! 2945: CPY_END = MOUSE;
! 2946: inverse_region(CPY_END + 1, old_cpy_end);
! 2947: } else {
! 2948: old_cpy_end = CPY_END;
! 2949: CPY_END = MOUSE + skip_char_right(MOUSE);
! 2950: if (CPY_END != old_cpy_end) {
! 2951: /* reducing selection, from the end of
! 2952: * next word */
! 2953: inverse_region(CPY_END + 1,
! 2954: old_cpy_end);
! 2955: }
! 2956: }
! 2957: }
! 2958: } else {
! 2959: /* upper part of the screen */
! 2960: if (MOUSE < CPY_START) {
! 2961: /* extending selection */
! 2962: old_cpy_start = CPY_START;
! 2963: CPY_START = MOUSE - skip_char_left(MOUSE);
! 2964: inverse_region(CPY_START, old_cpy_start - 1);
! 2965: } else {
! 2966: if (class_cmp(MOUSE - 1, MOUSE)) {
! 2967: /* reducing selection (remove last word) */
! 2968: old_cpy_start = CPY_START;
! 2969: CPY_START = MOUSE;
! 2970: inverse_region(old_cpy_start,
! 2971: CPY_START - 1);
! 2972: } else {
! 2973: old_cpy_start = CPY_START;
! 2974: CPY_START = MOUSE - skip_char_left(MOUSE);
! 2975: if (CPY_START != old_cpy_start) {
! 2976: inverse_region(old_cpy_start,
! 2977: CPY_START - 1);
! 2978: }
! 2979: }
! 2980: }
! 2981: }
! 2982:
! 2983: if (!IS_SEL_EXT_AFTER(sc->sc_focus)) {
! 2984: /* display new cursor */
! 2985: CURSOR = MOUSE;
! 2986: inverse_char(CURSOR);
! 2987: }
! 2988: }
! 2989:
! 2990: /*
! 2991: * Extend a selected region, line by line
! 2992: */
! 2993: void
! 2994: mouse_copy_extend_line(void)
! 2995: {
! 2996: unsigned short old_row;
! 2997: unsigned short new_row;
! 2998: unsigned short old_cpy_start;
! 2999: unsigned short old_cpy_end;
! 3000:
! 3001: if (!IS_SEL_EXT_AFTER(sc->sc_focus)) {
! 3002: /* remove cursor in selection (black one) */
! 3003:
! 3004: if (CURSOR != (CPY_END + 1))
! 3005: inverse_char(CURSOR);
! 3006:
! 3007: /* now, switch between lower and upper part of the screen */
! 3008:
! 3009: if (MOUSE < ORIG_START && CPY_END >= ORIG_START) {
! 3010: /* going to the upper part of the screen */
! 3011: inverse_region(ORIG_END + 1, CPY_END);
! 3012: CPY_END = ORIG_END;
! 3013: }
! 3014:
! 3015: if (MOUSE > ORIG_END && CPY_START <= ORIG_START) {
! 3016: /* going to the lower part of the screen */
! 3017: inverse_region(CPY_START, ORIG_START - 1);
! 3018: CPY_START = ORIG_START;
! 3019: }
! 3020: }
! 3021:
! 3022: if (MOUSE >= ORIG_START) {
! 3023: /* lower part of the screen */
! 3024: if (CURSOR == (CPY_END + 1))
! 3025: CURSOR = CPY_END;
! 3026: old_row = CURSOR / N_COLS;
! 3027: new_row = MOUSE / N_COLS;
! 3028: old_cpy_end = CPY_END;
! 3029: CPY_END = (new_row * N_COLS) + MAXCOL;
! 3030: if (new_row > old_row)
! 3031: inverse_region(old_cpy_end + 1, CPY_END);
! 3032: else if (new_row < old_row)
! 3033: inverse_region(CPY_END + 1, old_cpy_end);
! 3034: } else {
! 3035: /* upper part of the screen */
! 3036: old_row = CURSOR / N_COLS;
! 3037: new_row = MOUSE / N_COLS;
! 3038: old_cpy_start = CPY_START;
! 3039: CPY_START = new_row * N_COLS;
! 3040: if (new_row < old_row)
! 3041: inverse_region(CPY_START, old_cpy_start - 1);
! 3042: else if (new_row > old_row)
! 3043: inverse_region(old_cpy_start, CPY_START - 1);
! 3044: }
! 3045:
! 3046: if (!IS_SEL_EXT_AFTER(sc->sc_focus)) {
! 3047: /* display new cursor */
! 3048: CURSOR = MOUSE;
! 3049: inverse_char(CURSOR);
! 3050: }
! 3051: }
! 3052:
! 3053: void
! 3054: mouse_hide(struct wsdisplay_softc *sc)
! 3055: {
! 3056: if (IS_MOUSE_VISIBLE(sc->sc_focus)) {
! 3057: inverse_char(MOUSE);
! 3058: MOUSE_FLAGS &= ~MOUSE_VISIBLE;
! 3059: }
! 3060: }
! 3061:
! 3062: /*
! 3063: * Add an extension to a selected region, word by word
! 3064: */
! 3065: void
! 3066: mouse_copy_extend_after(void)
! 3067: {
! 3068: unsigned short start_dist;
! 3069: unsigned short end_dist;
! 3070:
! 3071: if (IS_SEL_EXISTS(sc->sc_focus)) {
! 3072: MOUSE_FLAGS |= SEL_EXT_AFTER;
! 3073: mouse_hide(sc); /* hide current cursor */
! 3074:
! 3075: if (CPY_START > MOUSE)
! 3076: start_dist = CPY_START - MOUSE;
! 3077: else
! 3078: start_dist = MOUSE - CPY_START;
! 3079: if (MOUSE > CPY_END)
! 3080: end_dist = MOUSE - CPY_END;
! 3081: else
! 3082: end_dist = CPY_END - MOUSE;
! 3083: if (start_dist < end_dist) {
! 3084: /* upper part of the screen*/
! 3085: ORIG_START = MOUSE + 1;
! 3086: /* only used in mouse_copy_extend_line() */
! 3087: CURSOR = CPY_START;
! 3088: } else {
! 3089: /* lower part of the screen */
! 3090: ORIG_START = MOUSE;
! 3091: /* only used in mouse_copy_extend_line() */
! 3092: CURSOR = CPY_END;
! 3093: }
! 3094: if (IS_SEL_BY_CHAR(sc->sc_focus))
! 3095: mouse_copy_extend_char();
! 3096: if (IS_SEL_BY_WORD(sc->sc_focus))
! 3097: mouse_copy_extend_word();
! 3098: if (IS_SEL_BY_LINE(sc->sc_focus))
! 3099: mouse_copy_extend_line();
! 3100: mouse_copy_selection();
! 3101: }
! 3102: }
! 3103:
! 3104: /*
! 3105: * Remove a previously selected region
! 3106: */
! 3107: void
! 3108: remove_selection(struct wsdisplay_softc *sc)
! 3109: {
! 3110: if (IS_SEL_EXT_AFTER(sc->sc_focus)) {
! 3111: /* reset the flag indicating an extension of selection */
! 3112: MOUSE_FLAGS &= ~SEL_EXT_AFTER;
! 3113: }
! 3114: inverse_region(CPY_START, CPY_END);
! 3115: MOUSE_FLAGS &= ~SEL_IN_PROGRESS;
! 3116: MOUSE_FLAGS &= ~SEL_EXISTS;
! 3117: }
! 3118:
! 3119: /*
! 3120: * Put the current visual selection in the selection buffer
! 3121: */
! 3122: void
! 3123: mouse_copy_selection(void)
! 3124: {
! 3125: struct wsdisplay_charcell cell;
! 3126: unsigned short current = 0;
! 3127: unsigned short blank = current;
! 3128: unsigned short buf_end = ((N_COLS + 1) * N_ROWS);
! 3129: unsigned short sel_cur;
! 3130: unsigned short sel_end;
! 3131:
! 3132: sel_cur = CPY_START;
! 3133: sel_end = CPY_END;
! 3134:
! 3135: while (sel_cur <= sel_end && current < buf_end - 1) {
! 3136: if (GETCHAR(sel_cur, &cell) != 0)
! 3137: break;
! 3138: Copybuffer[current] = cell.uc;
! 3139: if (!IS_SPACE(Copybuffer[current]))
! 3140: blank = current + 1; /* first blank after non-blank */
! 3141: current++;
! 3142: if (POS_TO_X(sel_cur) == MAXCOL) {
! 3143: /* we are on the last col of the screen */
! 3144: Copybuffer[blank] = '\r'; /* carriage return */
! 3145: current = blank + 1; /* restart just after the carriage
! 3146: return in the buffer */
! 3147: blank = current;
! 3148: }
! 3149: sel_cur++;
! 3150: }
! 3151:
! 3152: Copybuffer[current] = '\0';
! 3153: }
! 3154:
! 3155: /*
! 3156: * Paste the current selection
! 3157: */
! 3158: void
! 3159: mouse_paste(void)
! 3160: {
! 3161: unsigned short len;
! 3162: unsigned char *current = Copybuffer;
! 3163:
! 3164: if (Paste_avail) {
! 3165: for (len = strlen(Copybuffer) ; len > 0; len--) {
! 3166: (*linesw[sc->sc_focus->scr_tty->t_line].l_rint)
! 3167: (*current++, sc->sc_focus->scr_tty);
! 3168: }
! 3169: }
! 3170: }
! 3171:
! 3172: /*
! 3173: * Handle the z axis.
! 3174: * The z axis (roller or wheel) is mapped by default to scrollback.
! 3175: */
! 3176: void
! 3177: mouse_zaxis(int z)
! 3178: {
! 3179: if (z < 0)
! 3180: wsscrollback(sc, WSDISPLAY_SCROLL_BACKWARD);
! 3181: else
! 3182: wsscrollback(sc, WSDISPLAY_SCROLL_FORWARD);
! 3183: }
! 3184:
! 3185: /*
! 3186: * Allocate the copy buffer. The size is:
! 3187: * (cols + 1) * (rows)
! 3188: * (+1 for '\n' at the end of lines),
! 3189: * where cols and rows are the maximum of column and rows of all screens.
! 3190: */
! 3191: void
! 3192: allocate_copybuffer(struct wsdisplay_softc *sc)
! 3193: {
! 3194: int nscreens = sc->sc_scrdata->nscreens;
! 3195: int i,s;
! 3196: const struct wsscreen_descr **screens_list = sc->sc_scrdata->screens;
! 3197: const struct wsscreen_descr *current;
! 3198: unsigned short size = Copybuffer_size;
! 3199:
! 3200: s = spltty();
! 3201: for (i = 0; i < nscreens; i++) {
! 3202: current = *screens_list;
! 3203: if (( (current->ncols + 1) * current->nrows) > size)
! 3204: size = ((current->ncols + 1) * current->nrows);
! 3205: screens_list++;
! 3206: }
! 3207: if ((size != Copybuffer_size) && (Copybuffer_size != 0)) {
! 3208: bzero(Copybuffer, Copybuffer_size);
! 3209: free(Copybuffer, M_DEVBUF);
! 3210: }
! 3211: if ((Copybuffer = (char *)malloc(size, M_DEVBUF, M_NOWAIT)) == NULL) {
! 3212: printf("wscons: copybuffer memory malloc failed\n");
! 3213: Copybuffer_size = 0;
! 3214: }
! 3215: Copybuffer_size = size;
! 3216: splx(s);
! 3217: }
! 3218:
! 3219:
! 3220: /* Remove selection and cursor on current screen */
! 3221: void
! 3222: mouse_remove(struct wsdisplay_softc *sc)
! 3223: {
! 3224: if (IS_SEL_EXISTS(sc->sc_focus))
! 3225: remove_selection(sc);
! 3226:
! 3227: mouse_hide(sc);
! 3228: }
! 3229:
! 3230: /* Send a wscons event to notify wsmoused(8) to release the mouse device */
! 3231: void
! 3232: wsmoused_release(struct wsdisplay_softc *sc)
! 3233: {
! 3234: #if NWSMOUSE > 0
! 3235: struct device *wsms_dev = NULL;
! 3236: struct device **wsms_dev_list;
! 3237: int is_wsmouse = 0;
! 3238: #if NWSMUX > 0
! 3239: int is_wsmux = 0;
! 3240: #endif /* NWSMUX > 0 */
! 3241:
! 3242: if (sc->wsmoused_dev) {
! 3243: /* wsmoused(8) is running */
! 3244:
! 3245: wsms_dev_list = (struct device **) wsmouse_cd.cd_devs;
! 3246: if (!wsms_dev_list)
! 3247: /* no wsmouse device exists */
! 3248: return ;
! 3249:
! 3250: /* test whether device opened by wsmoused(8) is a wsmux device
! 3251: * (/dev/wsmouse) or a wsmouse device (/dev/wsmouse{0..n} */
! 3252:
! 3253: #if NWSMUX > 0
! 3254: /* obtain major of /dev/wsmouse multiplexor device */
! 3255: /* XXX first member of wsmux_softc is of type struct device */
! 3256: if (cdevsw[major(sc->wsmoused_dev)].d_open == wsmuxopen)
! 3257: is_wsmux = 1;
! 3258:
! 3259: if (is_wsmux && (minor(sc->wsmoused_dev) == WSMOUSEDEVCF_MUX)) {
! 3260: /* /dev/wsmouse case */
! 3261: /* XXX at least, wsmouse0 exist */
! 3262: wsms_dev = wsms_dev_list[0];
! 3263: }
! 3264: #endif /* NWSMUX > 0 */
! 3265:
! 3266: /* obtain major of /dev/wsmouse{0..n} devices */
! 3267: if (wsmouse_cd.cd_ndevs > 0) {
! 3268: if (cdevsw[major(sc->wsmoused_dev)].d_open ==
! 3269: wsmouseopen)
! 3270: is_wsmouse = 1;
! 3271: }
! 3272:
! 3273: if (is_wsmouse && (minor(sc->wsmoused_dev) <= NWSMOUSE)) {
! 3274: /* /dev/wsmouseX case */
! 3275: if (minor(sc->wsmoused_dev) < wsmouse_cd.cd_ndevs) {
! 3276: wsms_dev =
! 3277: wsms_dev_list[minor(sc->wsmoused_dev)];
! 3278: }
! 3279: else
! 3280: /* no corresponding /dev/wsmouseX device */
! 3281: return;
! 3282: }
! 3283:
! 3284: /* inject event to notify wsmoused(8) to close mouse device */
! 3285: if (wsms_dev != NULL)
! 3286: wsmouse_input(wsms_dev, 0, 0, 0, 0, 0,
! 3287: WSMOUSE_INPUT_WSMOUSED_CLOSE);
! 3288:
! 3289: }
! 3290: #endif /* NWSMOUSE > 0 */
! 3291: }
! 3292:
! 3293: /* Wakeup wsmoused(8), so that the mouse device can be reopened */
! 3294: void
! 3295: wsmoused_wakeup(struct wsdisplay_softc *sc)
! 3296: {
! 3297: #if NWSMOUSE > 0
! 3298: if (sc->wsmoused_dev) {
! 3299: sc->wsmoused_sleep = 0;
! 3300: wakeup(&sc->wsmoused_sleep);
! 3301: }
! 3302: #endif /* NWSMOUSE > 0 */
! 3303: }
! 3304: #endif /* WSMOUSED_SUPPORT */
CVSweb