This source file includes following definitions.
- wsscreen_attach
- wsscreen_detach
- wsdisplay_screentype_pick
- wsdisplay_addscreen_print
- wsdisplay_addscreen
- wsdisplay_getscreen
- wsdisplay_closescreen
- wsdisplay_delscreen
- wsdisplay_emul_match
- wsdisplay_emul_attach
- wsdisplay_emul_detach
- wsdisplay_common_detach
- wsemuldisplaydevprint
- wsdisplay_common_attach
- wsdisplay_cnattach
- wsdisplayopen
- wsdisplayclose
- wsdisplayread
- wsdisplaywrite
- wsdisplaytty
- wsdisplayioctl
- wsdisplay_param
- wsdisplay_internal_ioctl
- wsdisplay_cfg_ioctl
- wsdisplaymmap
- wsdisplaypoll
- wsdisplaykqfilter
- wsdisplaystart
- wsdisplaystop
- wsdisplayparam
- wsdisplay_emulbell
- wsdisplay_emulinput
- wsdisplay_kbdinput
- wsdisplay_update_rawkbd
- wsdisplay_switch3
- wsdisplay_switch2
- wsdisplay_switch1
- wsdisplay_switch
- wsdisplay_reset
- wsscreen_attach_sync
- wsscreen_detach_sync
- wsscreen_lookup_sync
- wsdisplay_maxscreenidx
- wsdisplay_screenstate
- wsdisplay_getactivescreen
- wsscreen_switchwait
- wsdisplay_kbdholdscreen
- wsdisplay_set_console_kbd
- wsdisplay_set_kbd
- wsdisplay_cnputc
- wsdisplay_getc_dummy
- wsdisplay_pollc
- wsdisplay_set_cons_kbd
- wsdisplay_unset_cons_kbd
- wsdisplay_switchtoconsole
- wsscrollback
- wsdisplay_burn
- wsdisplay_burner
- wsdisplay_shutdownhook
- wsmoused
- motion_event
- button_event
- ctrl_event
- mouse_moverel
- inverse_char
- inverse_region
- skip_spc_right
- skip_spc_left
- skip_char_right
- skip_char_left
- class_cmp
- mouse_copy_start
- mouse_copy_word
- mouse_copy_line
- mouse_copy_end
- mouse_copy_extend
- mouse_copy_extend_char
- mouse_copy_extend_word
- mouse_copy_extend_line
- mouse_hide
- mouse_copy_extend_after
- remove_selection
- mouse_copy_selection
- mouse_paste
- mouse_zaxis
- allocate_copybuffer
- mouse_remove
- wsmoused_release
- wsmoused_wakeup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
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;
100
101 int scr_flags;
102 #define SCR_OPEN 1
103 #define SCR_WAITACTIVE 2
104 #define SCR_GRAPHICS 4
105 #define SCR_DUMBFB 8
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
120 unsigned short mouse;
121 unsigned short cursor;
122
123 unsigned short cpy_start;
124 unsigned short cpy_end;
125 unsigned short orig_start;
126 unsigned short orig_end;
127 #define MOUSE_VISIBLE (1 << 0)
128 #define SEL_EXISTS (1 << 1)
129 #define SEL_IN_PROGRESS (1 << 2)
130 #define SEL_EXT_AFTER (1 << 3)
131 #define BLANK_TO_EOL (1 << 4)
132
133 #define SEL_BY_CHAR (1 << 5)
134 #define SEL_BY_WORD (1 << 6)
135 #define SEL_BY_LINE (1 << 7)
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;
146 #endif
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;
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;
190
191 #if NWSKBD > 0
192 struct wsevsrc *sc_input;
193 #ifdef WSDISPLAY_COMPAT_RAWKBD
194 int sc_rawkbd;
195 #endif
196 #endif
197
198 #ifdef WSMOUSED_SUPPORT
199 dev_t wsmoused_dev;
200 int wsmoused_sleep;
201 #endif
202 };
203
204 extern struct cfdriver wsdisplay_cd;
205
206
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
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
289
290
291 (void)(*dconf->wsemul->attach)(1, 0, 0, 0, 0, scr, 0);
292 } else {
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;
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
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
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);
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
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
469 for (maj = 0; maj < nchrdev; maj++)
470 if (cdevsw[maj].d_open == wsdisplayopen)
471 break;
472
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
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
509
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
523
524
525
526 if (scr->scr_flags & SCR_WAITACTIVE)
527 wakeup(scr);
528
529
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
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
553
554
555 if (cf->wsemuldisplaydevcf_console != 0 && ap->console != 0)
556 return (10);
557 else
558 return (0);
559 }
560
561
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
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
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
605 if (sc->sc_isconsole)
606 return (EBUSY);
607
608
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);
625
626
627
628
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
642 int
643 wsemuldisplaydevprint(void *aux, const char *pnp)
644 {
645 #if 0
646 struct wsemuldisplaydev_attach_args *ap = aux;
647 #endif
648
649 if (pnp)
650 printf("wsdisplay at %s", pnp);
651 #if 0
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
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
684 if (kbdmux >= 0)
685 printf(" (mux ignored)");
686 #endif
687 #endif
688 #endif
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
730
731
732
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;
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
761
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
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
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 ||
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
862
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
894 s = spltty();
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
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
1032
1033 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1034 if (error >= 0)
1035 return (error);
1036
1037
1038
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
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
1132
1133
1134 wsmoused_release(sc);
1135 #endif
1136
1137 #ifdef BURNER_SUPPORT
1138
1139 if (sc->sc_burnout)
1140 timeout_del(&sc->sc_burner);
1141 #endif
1142 } else {
1143 #ifdef BURNER_SUPPORT
1144
1145 if (!sc->sc_burnman)
1146 wsdisplay_burn(sc, sc->sc_burnflags);
1147 #endif
1148
1149 #ifdef WSMOUSED_SUPPORT
1150
1151
1152
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
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
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
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
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
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
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
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
1422
1423
1424
1425
1426
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
1440 remove_selection(sc);
1441
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
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
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
1508
1509 void
1510 wsdisplay_emulbell(void *v)
1511 {
1512 struct wsscreen *scr = v;
1513
1514 if (scr == NULL)
1515 return;
1516
1517 if (scr->scr_flags & SCR_GRAPHICS)
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)
1531 return;
1532
1533 if (scr->scr_flags & SCR_GRAPHICS)
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
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
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
1650
1651
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
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
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
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
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
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826 if (!(scr->scr_flags & SCR_GRAPHICS) &&
1827 (!(sc->sc_scr[no]->scr_flags & SCR_GRAPHICS))) {
1828
1829
1830
1831
1832 mouse_remove(sc);
1833 }
1834
1835 if (!(scr->scr_flags & SCR_GRAPHICS) &&
1836 (sc->sc_scr[no]->scr_flags & SCR_GRAPHICS)) {
1837
1838
1839
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
1847
1848 wsmoused_wakeup(sc);
1849 }
1850 #endif
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
1860 return (0);
1861 }
1862 } else if (scr->scr_flags & SCR_GRAPHICS) {
1863
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
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
1905
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,
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
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;
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);
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
2047
2048
2049
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
2068 #endif
2069 (*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1);
2070 }
2071
2072 int
2073 wsdisplay_getc_dummy(dev_t dev)
2074 {
2075
2076 return (0);
2077 }
2078
2079 void
2080 wsdisplay_pollc(dev_t dev, int on)
2081 {
2082
2083 wsdisplay_cons_pollmode = on;
2084
2085
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
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
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
2192
2193 void
2194 wsdisplay_shutdownhook(void *arg)
2195 {
2196 wsdisplay_switchtoconsole();
2197 }
2198
2199 #ifdef WSMOUSED_SUPPORT
2200
2201
2202
2203
2204
2205 static struct wsdisplay_softc *sc = NULL;
2206
2207
2208
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
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
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
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:
2270 mouse_copy_end();
2271 mouse_copy_selection();
2272 break;
2273 case 1:
2274 mouse_copy_start();
2275 mouse_copy_selection();
2276 break;
2277 case 2:
2278 mouse_copy_word();
2279 mouse_copy_selection();
2280 break;
2281 case 3:
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:
2293 break;
2294 default:
2295 mouse_paste();
2296 break;
2297 }
2298 break;
2299
2300 case MOUSE_EXTEND_BUTTON:
2301 switch (clicks) {
2302 case 0:
2303 break;
2304 default:
2305 mouse_copy_extend_after();
2306 break;
2307 }
2308 break;
2309
2310 default:
2311 break;
2312 }
2313 }
2314
2315
2316
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
2326 return (1);
2327
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
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
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
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
2399 if (old_mouse != MOUSE) {
2400 if (IS_SEL_IN_PROGRESS(sc->sc_focus)) {
2401
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
2432
2433
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
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
2468
2469
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
2500
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
2523
2524
2525
2526 static const int charClass[256] = {
2527
2528 32, 1, 1, 1, 1, 1, 1, 1,
2529
2530 1, 32, 1, 1, 1, 1, 1, 1,
2531
2532 1, 1, 1, 1, 1, 1, 1, 1,
2533
2534 1, 1, 1, 1, 1, 1, 1, 1,
2535
2536 32, 33, 34, 35, 36, 37, 38, 39,
2537
2538 40, 41, 42, 43, 44, 45, 46, 47,
2539
2540 48, 48, 48, 48, 48, 48, 48, 48,
2541
2542 48, 48, 58, 59, 60, 61, 62, 63,
2543
2544 64, 48, 48, 48, 48, 48, 48, 48,
2545
2546 48, 48, 48, 48, 48, 48, 48, 48,
2547
2548 48, 48, 48, 48, 48, 48, 48, 48,
2549
2550 48, 48, 48, 91, 92, 93, 94, 48,
2551
2552 96, 48, 48, 48, 48, 48, 48, 48,
2553
2554 48, 48, 48, 48, 48, 48, 48, 48,
2555
2556 48, 48, 48, 48, 48, 48, 48, 48,
2557
2558 48, 48, 48, 123, 124, 125, 126, 1,
2559
2560 1, 1, 1, 1, 1, 1, 1, 1,
2561
2562 1, 1, 1, 1, 1, 1, 1, 1,
2563
2564 1, 1, 1, 1, 1, 1, 1, 1,
2565
2566 1, 1, 1, 1, 1, 1, 1, 1,
2567
2568 160, 161, 162, 163, 164, 165, 166, 167,
2569
2570 168, 169, 170, 171, 172, 173, 174, 175,
2571
2572 176, 177, 178, 179, 180, 181, 182, 183,
2573
2574 184, 185, 186, 187, 188, 189, 190, 191,
2575
2576 48, 48, 48, 48, 48, 48, 48, 48,
2577
2578 48, 48, 48, 48, 48, 48, 48, 48,
2579
2580 48, 48, 48, 48, 48, 48, 48, 216,
2581
2582 48, 48, 48, 48, 48, 48, 48, 48,
2583
2584 48, 48, 48, 48, 48, 48, 48, 48,
2585
2586 48, 48, 48, 48, 48, 48, 48, 48,
2587
2588 48, 48, 48, 48, 48, 48, 48, 248,
2589
2590 48, 48, 48, 48, 48, 48, 48, 48
2591 };
2592
2593
2594
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
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
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
2666
2667 void
2668 mouse_copy_start(void)
2669 {
2670 unsigned char right;
2671
2672
2673 if (!Paste_avail)
2674 Paste_avail = 1;
2675
2676
2677
2678 if (IS_SEL_EXISTS(sc->sc_focus))
2679 remove_selection(sc);
2680
2681
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;
2690
2691 right = skip_spc_right(BORDER);
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;
2698 MOUSE_FLAGS &= ~SEL_BY_WORD;
2699 MOUSE_FLAGS &= ~SEL_BY_LINE;
2700 MOUSE_FLAGS &= ~MOUSE_VISIBLE;
2701 }
2702
2703
2704
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;
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
2744 MOUSE_FLAGS &= ~BLANK_TO_EOL;
2745 MOUSE_FLAGS &= ~MOUSE_VISIBLE;
2746 }
2747
2748
2749
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
2776 MOUSE_FLAGS &= ~BLANK_TO_EOL;
2777 MOUSE_FLAGS &= ~MOUSE_VISIBLE;
2778 }
2779
2780
2781
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
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
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
2822
2823
2824
2825 right = skip_spc_right(BORDER);
2826 if (MOUSE > ORIG_START) {
2827
2828
2829
2830
2831
2832 inverse_char(CPY_START);
2833 CPY_START += (right + 1);
2834 CPY_END = CPY_START;
2835 ORIG_START = CPY_START;
2836
2837 inverse_char(CPY_START);
2838 } else {
2839
2840
2841
2842
2843 inverse_char(CPY_START);
2844 ORIG_START += (right + 1);
2845 CPY_START = ORIG_START - 1;
2846 CPY_END = ORIG_START - 1;
2847
2848 inverse_char(CPY_START);
2849 }
2850 MOUSE_FLAGS &= ~ BLANK_TO_EOL;
2851 }
2852
2853 if (MOUSE < ORIG_START && CPY_END >= ORIG_START) {
2854
2855
2856
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
2863
2864
2865
2866 remove_selection(sc);
2867 CPY_START = ORIG_START;
2868 CPY_END = ORIG_START - 1;
2869 }
2870
2871 MOUSE_FLAGS |= SEL_IN_PROGRESS;
2872 MOUSE_FLAGS |= SEL_EXISTS;
2873 }
2874
2875
2876 if (MOUSE >= ORIG_START) {
2877
2878
2879 if (MOUSE > CPY_END) {
2880
2881 inverse_region(CPY_END + 1, MOUSE);
2882 } else {
2883
2884 inverse_region(MOUSE + 1, CPY_END);
2885 }
2886 CPY_END = MOUSE;
2887 } else {
2888
2889 if (MOUSE < CPY_START) {
2890
2891 inverse_region(MOUSE,CPY_START - 1);
2892 } else {
2893
2894 inverse_region(CPY_START,MOUSE - 1);
2895 }
2896 CPY_START = MOUSE;
2897 }
2898
2899 }
2900
2901
2902
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
2913
2914 if (CURSOR != (CPY_END + 1))
2915 inverse_char(CURSOR);
2916
2917
2918
2919 if (MOUSE < ORIG_START && CPY_END >= ORIG_START) {
2920
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
2927 inverse_region(CPY_START, ORIG_START - 1);
2928 CPY_START = ORIG_START;
2929 }
2930 }
2931
2932 if (MOUSE >= ORIG_START) {
2933
2934
2935 if (MOUSE > CPY_END) {
2936
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
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
2952
2953 inverse_region(CPY_END + 1,
2954 old_cpy_end);
2955 }
2956 }
2957 }
2958 } else {
2959
2960 if (MOUSE < CPY_START) {
2961
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
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
2985 CURSOR = MOUSE;
2986 inverse_char(CURSOR);
2987 }
2988 }
2989
2990
2991
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
3003
3004 if (CURSOR != (CPY_END + 1))
3005 inverse_char(CURSOR);
3006
3007
3008
3009 if (MOUSE < ORIG_START && CPY_END >= ORIG_START) {
3010
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
3017 inverse_region(CPY_START, ORIG_START - 1);
3018 CPY_START = ORIG_START;
3019 }
3020 }
3021
3022 if (MOUSE >= ORIG_START) {
3023
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
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
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
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);
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
3085 ORIG_START = MOUSE + 1;
3086
3087 CURSOR = CPY_START;
3088 } else {
3089
3090 ORIG_START = MOUSE;
3091
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
3106
3107 void
3108 remove_selection(struct wsdisplay_softc *sc)
3109 {
3110 if (IS_SEL_EXT_AFTER(sc->sc_focus)) {
3111
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
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;
3141 current++;
3142 if (POS_TO_X(sel_cur) == MAXCOL) {
3143
3144 Copybuffer[blank] = '\r';
3145 current = blank + 1;
3146
3147 blank = current;
3148 }
3149 sel_cur++;
3150 }
3151
3152 Copybuffer[current] = '\0';
3153 }
3154
3155
3156
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
3174
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
3187
3188
3189
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
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
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
3241
3242 if (sc->wsmoused_dev) {
3243
3244
3245 wsms_dev_list = (struct device **) wsmouse_cd.cd_devs;
3246 if (!wsms_dev_list)
3247
3248 return ;
3249
3250
3251
3252
3253 #if NWSMUX > 0
3254
3255
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
3261
3262 wsms_dev = wsms_dev_list[0];
3263 }
3264 #endif
3265
3266
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
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
3281 return;
3282 }
3283
3284
3285 if (wsms_dev != NULL)
3286 wsmouse_input(wsms_dev, 0, 0, 0, 0, 0,
3287 WSMOUSE_INPUT_WSMOUSED_CLOSE);
3288
3289 }
3290 #endif
3291 }
3292
3293
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
3303 }
3304 #endif