[BACK]Return to wsdisplay.c CVS log [TXT][DIR] Up to [local] / sys / dev / wscons

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