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