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(screen_word(sel_cons, n, 1) & 0xff)
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)
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 xs = get_user(args++) - 1;
126 ys = get_user(args++) - 1;
127 xe = get_user(args++) - 1;
128 ye = get_user(args++) - 1;
129 sel_mode = get_user(args);
130
131 xs = limit(xs, video_num_columns - 1);
132 ys = limit(ys, video_num_lines - 1);
133 xe = limit(xe, video_num_columns - 1);
134 ye = limit(ye, video_num_lines - 1);
135 ps = ys * video_size_row + (xs << 1);
136 pe = ye * video_size_row + (xe << 1);
137
138 if (sel_mode == 4) {
139
140 clear_selection();
141 return 0;
142 }
143
144 if (mouse_reporting() && (sel_mode & 16)) {
145 mouse_report(tty, sel_mode & 15, xs, ys);
146 return 0;
147 }
148 }
149
150 if (ps > pe)
151 {
152 int tmp = ps;
153 ps = pe;
154 pe = tmp;
155 }
156
157 if (sel_cons != fg_console) {
158 clear_selection();
159 sel_cons = fg_console;
160 }
161
162 switch (sel_mode)
163 {
164 case 0:
165 new_sel_start = ps;
166 new_sel_end = pe;
167 break;
168 case 1:
169 spc = isspace(sel_pos(ps));
170 for (new_sel_start = ps; ; ps -= 2)
171 {
172 if ((spc && !isspace(sel_pos(ps))) ||
173 (!spc && !inword(sel_pos(ps))))
174 break;
175 new_sel_start = ps;
176 if (!(ps % video_size_row))
177 break;
178 }
179 spc = isspace(sel_pos(pe));
180 for (new_sel_end = pe; ; pe += 2)
181 {
182 if ((spc && !isspace(sel_pos(pe))) ||
183 (!spc && !inword(sel_pos(pe))))
184 break;
185 new_sel_end = pe;
186 if (!((pe + 2) % video_size_row))
187 break;
188 }
189 break;
190 case 2:
191 new_sel_start = ps - ps % video_size_row;
192 new_sel_end = pe + video_size_row
193 - pe % video_size_row - 2;
194 break;
195 case 3:
196 highlight_pointer(pe);
197 return 0;
198 default:
199 return -EINVAL;
200 }
201
202
203 highlight_pointer(-1);
204
205
206 if (new_sel_end > new_sel_start &&
207 !atedge(new_sel_end) && isspace(sel_pos(new_sel_end))) {
208 for (pe = new_sel_end + 2; ; pe += 2)
209 if (!isspace(sel_pos(pe)) || atedge(pe))
210 break;
211 if (isspace(sel_pos(pe)))
212 new_sel_end = pe;
213 }
214 if (sel_start == -1)
215 highlight(new_sel_start, new_sel_end);
216 else if (new_sel_start == sel_start)
217 {
218 if (new_sel_end == sel_end)
219 return 0;
220 else if (new_sel_end > sel_end)
221 highlight(sel_end + 2, new_sel_end);
222 else
223 highlight(new_sel_end + 2, sel_end);
224 }
225 else if (new_sel_end == sel_end)
226 {
227 if (new_sel_start < sel_start)
228 highlight(new_sel_start, sel_start - 2);
229 else
230 highlight(sel_start, new_sel_start - 2);
231 }
232 else
233 {
234 clear_selection();
235 highlight(new_sel_start, new_sel_end);
236 }
237 sel_start = new_sel_start;
238 sel_end = new_sel_end;
239
240 if (sel_buffer)
241 kfree(sel_buffer);
242 sel_buffer = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL);
243 if (!sel_buffer) {
244 printk("selection: kmalloc() failed\n");
245 clear_selection();
246 return -ENOMEM;
247 }
248
249 obp = bp = sel_buffer;
250 for (i = sel_start; i <= sel_end; i += 2) {
251 *bp = sel_pos(i);
252 if (!isspace(*bp++))
253 obp = bp;
254 if (! ((i + 2) % video_size_row)) {
255
256
257 if (obp != bp) {
258 bp = obp;
259 *bp++ = '\r';
260 }
261 obp = bp;
262 }
263 }
264 sel_buffer_lth = bp - sel_buffer;
265 return 0;
266 }
267
268
269
270 int paste_selection(struct tty_struct *tty)
271 {
272 struct wait_queue wait = { current, NULL };
273 char *bp = sel_buffer;
274 int c = sel_buffer_lth;
275 int l;
276 struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
277
278 if (!bp || !c)
279 return 0;
280 do_unblank_screen();
281 current->state = TASK_INTERRUPTIBLE;
282 add_wait_queue(&vt->paste_wait, &wait);
283 while (c) {
284 if (test_bit(TTY_THROTTLED, &tty->flags)) {
285 schedule();
286 continue;
287 }
288 l = MIN(c, tty->ldisc.receive_room(tty));
289 tty->ldisc.receive_buf(tty, bp, 0, l);
290 c -= l;
291 bp += l;
292 }
293 current->state = TASK_RUNNING;
294 return 0;
295 }