]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - historic/selection/selection.c
1 /* implement copying and pasting in Linux virtual consoles */
2 /* Andrew Haylett, 17th June 1993 */
3 /* Wed Feb 15 09:33:16 1995, faith@cs.unc.edu changed tty0 to console, since
4 most systems don't have a tty0 any more. */
13 #include <sys/ioctl.h>
18 extern int ms_copy_button
, ms_paste_button
;
20 static const int SCALE
= 10;
21 static const long CLICK_INTERVAL
= 250; /* msec */
22 static const char *console
= "/dev/console";
24 typedef enum { character
= 0, word
= 1, line
= 2 } sel_mode
;
26 static int open_console(const int mode
);
27 static void set_sel(const int xs
, const int ys
, const int xe
,
28 const int ye
, const sel_mode mode
);
29 static void paste(void);
30 static long interval(const struct timeval
*t1
, const struct timeval
*t2
);
31 static int check_mode(void);
34 main(int argc
, char *argv
[])
38 struct timeval tv1
, tv2
;
39 int xs
, ys
, xe
, ye
, x1
, y1
, fd
, clicks
= 0;
42 fd
= open_console(O_RDONLY
);
43 ioctl(fd
, TIOCGWINSZ
, &win
);
45 if (! win
.ws_col
|| ! win
.ws_row
)
47 fprintf(stderr
, "selection: zero screen dimension, assuming 80x25.\n");
52 ms_params(argc
, argv
);
54 if (ms_init(win
.ws_col
* SCALE
- 1, win
.ws_row
* SCALE
- 1))
61 gettimeofday(&tv1
, (struct timezone
*)NULL
);
68 if (get_ms_event(&ev
))
70 if (ev
.ev_butstate
== ms_copy_button
)
73 gettimeofday(&tv2
, (struct timezone
*)NULL
);
74 xs
= ev
.ev_x
/ SCALE
+ 1;
75 ys
= ev
.ev_y
/ SCALE
+ 1;
76 if (interval(&tv1
, &tv2
) < CLICK_INTERVAL
&& clicks
== 1)
79 set_sel(xs
, ys
, xs
, ys
, mode
);
81 else if (interval(&tv1
, &tv2
) < CLICK_INTERVAL
&& clicks
== 2)
84 set_sel(xs
, ys
, xs
, ys
, mode
);
90 do /* wait for left button up */
94 if (get_ms_event(&ev
))
96 } while (ev
.ev_butstate
);
98 do /* track start selection until left button down */
100 xs
= ev
.ev_x
/ SCALE
+ 1;
101 ys
= ev
.ev_y
/ SCALE
+ 1;
102 if (xs
!= x1
|| ys
!= y1
)
104 set_sel(xs
, ys
, xs
, ys
, mode
);
109 if (get_ms_event(&ev
))
111 } while (ev
.ev_butstate
!= ms_copy_button
);
114 gettimeofday(&tv1
, (struct timezone
*)NULL
);
115 do /* track end selection until left button up */
117 xe
= ev
.ev_x
/ SCALE
+ 1;
118 ye
= ev
.ev_y
/ SCALE
+ 1;
119 if (xe
!= x1
|| ye
!= y1
)
121 set_sel(xs
, ys
, xe
, ye
, mode
);
126 if (get_ms_event(&ev
))
128 } while (ev
.ev_butstate
== ms_copy_button
);
129 } else if (ev
.ev_butstate
== ms_paste_button
)
130 { /* paste selection */
132 do /* wait for right button up */
136 if (get_ms_event(&ev
))
138 } while (ev
.ev_butstate
);
139 gettimeofday(&tv1
, (struct timezone
*)NULL
);
145 /* We have to keep opening and closing the console because (a) /dev/tty0
146 changed its behaviour at some point such that the current VC is fixed
147 after the open(), rather than being re-evaluated at each write(), and (b)
148 because we seem to lose our grip on /dev/tty? after someone logs in if
149 this is run from /etc/rc. */
152 open_console(const int mode
)
156 if ((fd
= open(console
, mode
)) < 0)
158 perror("selection: open_console()");
164 /* mark selected text on screen. */
166 set_sel(const int xs
, const int ys
,
167 const int xe
, const int ye
, const sel_mode mode
)
169 unsigned char buf
[sizeof(char) + 5 * sizeof(short)];
170 unsigned short *arg
= (unsigned short *)(buf
+ 1);
181 fd
= open_console(O_WRONLY
);
182 if (ioctl(fd
, TIOCLINUX
, buf
) < 0)
184 perror("selection: ioctl(..., TIOCLINUX, ...)");
190 /* paste contents of selection buffer into console. */
197 fd
= open_console(O_WRONLY
);
198 if (ioctl(fd
, TIOCLINUX
, &c
) < 0)
200 perror("selection: ioctl(..., TIOCLINUX, ...)");
206 /* evaluate interval between times. */
208 interval(const struct timeval
*t1
, const struct timeval
*t2
)
210 return (t2
->tv_sec
- t1
->tv_sec
) * 1000
211 + (t2
->tv_usec
- t1
->tv_usec
) / 1000;
214 /* Check whether console is in graphics mode; if so, wait until it isn't. */
223 fd
= open_console(O_RDONLY
);
224 if (ioctl(fd
, KDGETMODE
, &kd_mode
) < 0)
226 perror("selection: ioctl(..., KDGETMODE, ...)");
230 if (kd_mode
!= KD_TEXT
)
235 } while (kd_mode
!= KD_TEXT
);