This source file includes following definitions.
- highlight
- highlight_pointer
- clear_selection
- inword
- sel_loadlut
- atedge
- limit
- set_selection
- paste_selection
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include <linux/tty.h>
15 #include <linux/sched.h>
16 #include <linux/mm.h>
17 #include <linux/malloc.h>
18 #include "vt_kern.h"
19 #include "consolemap.h"
20 #include "selection.h"
21
22 #ifndef MIN
23 #define MIN(a,b) ((a) < (b) ? (a) : (b))
24 #endif
25
26
27 #define isspace(c) ((c) == ' ')
28
29
30
31 int sel_cons = 0;
32 static volatile int sel_start = -1;
33 static int sel_end;
34 static int sel_buffer_lth = 0;
35 static char *sel_buffer = NULL;
36
37 #define sel_pos(n) inverse_translate(screen_word(sel_cons, n, 1) & 0xff)
38
39
40
41
42
43 inline static void
44 highlight(const int s, const int e) {
45 invert_screen(sel_cons, s, e-s+2, 1);
46 }
47
48
49 inline static void
50 highlight_pointer(const int where) {
51 complement_pos(sel_cons, where);
52 }
53
54
55
56 void
57 clear_selection(void) {
58 highlight_pointer(-1);
59 if (sel_start != -1) {
60 highlight(sel_start, sel_end);
61 sel_start = -1;
62 }
63 }
64
65
66
67
68
69 static unsigned long inwordLut[8]={
70 0x00000000,
71 0x03FF0000,
72 0x87FFFFFE,
73 0x07FFFFFE,
74 0x00000000,
75 0x00000000,
76 0xFF7FFFFF,
77 0xFF7FFFFF
78 };
79
80 static inline int inword(const unsigned char c) {
81 return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1;
82 }
83
84
85 int sel_loadlut(const int arg)
86 {
87 int i = verify_area(VERIFY_READ, (char *) arg, 36);
88 if (i)
89 return i;
90 memcpy_fromfs(inwordLut, (unsigned long *)(arg+4), 32);
91 return 0;
92 }
93
94
95 static inline int atedge(const int p)
96 {
97 return (!(p % video_size_row) || !((p + 2) % video_size_row));
98 }
99
100
101 static inline unsigned short limit(const unsigned short v, const unsigned short u)
102 {
103
104 if (v > u)
105 return u;
106 return v;
107 }
108
109
110 int set_selection(const int arg, struct tty_struct *tty)
111 {
112 int sel_mode, new_sel_start, new_sel_end, spc;
113 char *bp, *obp;
114 int i, ps, pe;
115
116 do_unblank_screen();
117
118 { unsigned short *args, xs, ys, xe, ye;
119
120 args = (unsigned short *)(arg + 1);
121 xs = get_fs_word(args++) - 1;
122 ys = get_fs_word(args++) - 1;
123 xe = get_fs_word(args++) - 1;
124 ye = get_fs_word(args++) - 1;
125 sel_mode = get_fs_word(args);
126
127 xs = limit(xs, video_num_columns - 1);
128 ys = limit(ys, video_num_lines - 1);
129 xe = limit(xe, video_num_columns - 1);
130 ye = limit(ye, video_num_lines - 1);
131 ps = ys * video_size_row + (xs << 1);
132 pe = ye * video_size_row + (xe << 1);
133
134 if (sel_mode == 4) {
135
136 clear_selection();
137 return 0;
138 }
139
140 if (mouse_reporting() && (sel_mode & 16)) {
141 mouse_report(tty, sel_mode & 15, xs, ys);
142 return 0;
143 }
144 }
145
146 if (ps > pe)
147 {
148 int tmp = ps;
149 ps = pe;
150 pe = tmp;
151 }
152
153 if (sel_cons != fg_console) {
154 clear_selection();
155 sel_cons = fg_console;
156 }
157
158 switch (sel_mode)
159 {
160 case 0:
161 new_sel_start = ps;
162 new_sel_end = pe;
163 break;
164 case 1:
165 spc = isspace(sel_pos(ps));
166 for (new_sel_start = ps; ; ps -= 2)
167 {
168 if ((spc && !isspace(sel_pos(ps))) ||
169 (!spc && !inword(sel_pos(ps))))
170 break;
171 new_sel_start = ps;
172 if (!(ps % video_size_row))
173 break;
174 }
175 spc = isspace(sel_pos(pe));
176 for (new_sel_end = pe; ; pe += 2)
177 {
178 if ((spc && !isspace(sel_pos(pe))) ||
179 (!spc && !inword(sel_pos(pe))))
180 break;
181 new_sel_end = pe;
182 if (!((pe + 2) % video_size_row))
183 break;
184 }
185 break;
186 case 2:
187 new_sel_start = ps - ps % video_size_row;
188 new_sel_end = pe + video_size_row
189 - pe % video_size_row - 2;
190 break;
191 case 3:
192 highlight_pointer(pe);
193 return 0;
194 default:
195 return -EINVAL;
196 }
197
198
199 highlight_pointer(-1);
200
201
202 if (new_sel_end > new_sel_start &&
203 !atedge(new_sel_end) && isspace(sel_pos(new_sel_end))) {
204 for (pe = new_sel_end + 2; ; pe += 2)
205 if (!isspace(sel_pos(pe)) || atedge(pe))
206 break;
207 if (isspace(sel_pos(pe)))
208 new_sel_end = pe;
209 }
210 if (sel_start == -1)
211 highlight(new_sel_start, new_sel_end);
212 else if (new_sel_start == sel_start)
213 {
214 if (new_sel_end == sel_end)
215 return 0;
216 else if (new_sel_end > sel_end)
217 highlight(sel_end + 2, new_sel_end);
218 else
219 highlight(new_sel_end + 2, sel_end);
220 }
221 else if (new_sel_end == sel_end)
222 {
223 if (new_sel_start < sel_start)
224 highlight(new_sel_start, sel_start - 2);
225 else
226 highlight(sel_start, new_sel_start - 2);
227 }
228 else
229 {
230 clear_selection();
231 highlight(new_sel_start, new_sel_end);
232 }
233 sel_start = new_sel_start;
234 sel_end = new_sel_end;
235
236 if (sel_buffer)
237 kfree(sel_buffer);
238 sel_buffer = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL);
239 if (!sel_buffer) {
240 printk("selection: kmalloc() failed\n");
241 clear_selection();
242 return -ENOMEM;
243 }
244
245 obp = bp = sel_buffer;
246 for (i = sel_start; i <= sel_end; i += 2) {
247 *bp = sel_pos(i);
248 if (!isspace(*bp++))
249 obp = bp;
250 if (! ((i + 2) % video_size_row)) {
251
252
253 if (obp != bp) {
254 bp = obp;
255 *bp++ = '\r';
256 }
257 obp = bp;
258 }
259 }
260 sel_buffer_lth = bp - sel_buffer;
261 return 0;
262 }
263
264
265
266 int paste_selection(struct tty_struct *tty)
267 {
268 struct wait_queue wait = { current, NULL };
269 char *bp = sel_buffer;
270 int c = sel_buffer_lth;
271 int l;
272 struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
273
274 if (!bp || !c)
275 return 0;
276 do_unblank_screen();
277 current->state = TASK_INTERRUPTIBLE;
278 add_wait_queue(&vt->paste_wait, &wait);
279 while (c) {
280 if (test_bit(TTY_THROTTLED, &tty->flags)) {
281 schedule();
282 continue;
283 }
284 l = MIN(c, tty->ldisc.receive_room(tty));
285 tty->ldisc.receive_buf(tty, bp, 0, l);
286 c -= l;
287 bp += l;
288 }
289 current->state = TASK_RUNNING;
290 return 0;
291 }