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