| .. | .. |
|---|
| 2 | 2 | /* |
|---|
| 3 | 3 | * This module exports the functions: |
|---|
| 4 | 4 | * |
|---|
| 5 | | - * 'int set_selection(struct tiocl_selection __user *, struct tty_struct *)' |
|---|
| 5 | + * 'int set_selection_user(struct tiocl_selection __user *, |
|---|
| 6 | + * struct tty_struct *)' |
|---|
| 7 | + * 'int set_selection_kernel(struct tiocl_selection *, struct tty_struct *)' |
|---|
| 6 | 8 | * 'void clear_selection(void)' |
|---|
| 7 | 9 | * 'int paste_selection(struct tty_struct *)' |
|---|
| 8 | 10 | * 'int sel_loadlut(char __user *)' |
|---|
| .. | .. |
|---|
| 33 | 35 | /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */ |
|---|
| 34 | 36 | #define isspace(c) ((c) == ' ') |
|---|
| 35 | 37 | |
|---|
| 36 | | -extern void poke_blanked_console(void); |
|---|
| 37 | | - |
|---|
| 38 | 38 | /* FIXME: all this needs locking */ |
|---|
| 39 | | -/* Variables for selection control. */ |
|---|
| 40 | | -/* Use a dynamic buffer, instead of static (Dec 1994) */ |
|---|
| 41 | | -struct vc_data *sel_cons; /* must not be deallocated */ |
|---|
| 42 | | -static int use_unicode; |
|---|
| 43 | | -static volatile int sel_start = -1; /* cleared by clear_selection */ |
|---|
| 44 | | -static int sel_end; |
|---|
| 45 | | -static int sel_buffer_lth; |
|---|
| 46 | | -static char *sel_buffer; |
|---|
| 47 | | -static DEFINE_MUTEX(sel_lock); |
|---|
| 39 | +static struct vc_selection { |
|---|
| 40 | + struct mutex lock; |
|---|
| 41 | + struct vc_data *cons; /* must not be deallocated */ |
|---|
| 42 | + char *buffer; |
|---|
| 43 | + unsigned int buf_len; |
|---|
| 44 | + volatile int start; /* cleared by clear_selection */ |
|---|
| 45 | + int end; |
|---|
| 46 | +} vc_sel = { |
|---|
| 47 | + .lock = __MUTEX_INITIALIZER(vc_sel.lock), |
|---|
| 48 | + .start = -1, |
|---|
| 49 | +}; |
|---|
| 48 | 50 | |
|---|
| 49 | 51 | /* clear_selection, highlight and highlight_pointer can be called |
|---|
| 50 | 52 | from interrupt (via scrollback/front) */ |
|---|
| .. | .. |
|---|
| 52 | 54 | /* set reverse video on characters s-e of console with selection. */ |
|---|
| 53 | 55 | static inline void highlight(const int s, const int e) |
|---|
| 54 | 56 | { |
|---|
| 55 | | - invert_screen(sel_cons, s, e-s+2, 1); |
|---|
| 57 | + invert_screen(vc_sel.cons, s, e-s+2, true); |
|---|
| 56 | 58 | } |
|---|
| 57 | 59 | |
|---|
| 58 | 60 | /* use complementary color to show the pointer */ |
|---|
| 59 | 61 | static inline void highlight_pointer(const int where) |
|---|
| 60 | 62 | { |
|---|
| 61 | | - complement_pos(sel_cons, where); |
|---|
| 63 | + complement_pos(vc_sel.cons, where); |
|---|
| 62 | 64 | } |
|---|
| 63 | 65 | |
|---|
| 64 | 66 | static u32 |
|---|
| 65 | | -sel_pos(int n) |
|---|
| 67 | +sel_pos(int n, bool unicode) |
|---|
| 66 | 68 | { |
|---|
| 67 | | - if (use_unicode) |
|---|
| 68 | | - return screen_glyph_unicode(sel_cons, n / 2); |
|---|
| 69 | | - return inverse_translate(sel_cons, screen_glyph(sel_cons, n), |
|---|
| 70 | | - 0); |
|---|
| 69 | + if (unicode) |
|---|
| 70 | + return screen_glyph_unicode(vc_sel.cons, n / 2); |
|---|
| 71 | + return inverse_translate(vc_sel.cons, screen_glyph(vc_sel.cons, n), 0); |
|---|
| 71 | 72 | } |
|---|
| 72 | 73 | |
|---|
| 73 | 74 | /** |
|---|
| .. | .. |
|---|
| 79 | 80 | void clear_selection(void) |
|---|
| 80 | 81 | { |
|---|
| 81 | 82 | highlight_pointer(-1); /* hide the pointer */ |
|---|
| 82 | | - if (sel_start != -1) { |
|---|
| 83 | | - highlight(sel_start, sel_end); |
|---|
| 84 | | - sel_start = -1; |
|---|
| 83 | + if (vc_sel.start != -1) { |
|---|
| 84 | + highlight(vc_sel.start, vc_sel.end); |
|---|
| 85 | + vc_sel.start = -1; |
|---|
| 85 | 86 | } |
|---|
| 86 | 87 | } |
|---|
| 88 | +EXPORT_SYMBOL_GPL(clear_selection); |
|---|
| 87 | 89 | |
|---|
| 88 | 90 | bool vc_is_sel(struct vc_data *vc) |
|---|
| 89 | 91 | { |
|---|
| 90 | | - return vc == sel_cons; |
|---|
| 92 | + return vc == vc_sel.cons; |
|---|
| 91 | 93 | } |
|---|
| 92 | 94 | |
|---|
| 93 | 95 | /* |
|---|
| .. | .. |
|---|
| 163 | 165 | } |
|---|
| 164 | 166 | |
|---|
| 165 | 167 | /** |
|---|
| 166 | | - * set_selection - set the current selection. |
|---|
| 168 | + * set_selection_user - set the current selection. |
|---|
| 167 | 169 | * @sel: user selection info |
|---|
| 168 | 170 | * @tty: the console tty |
|---|
| 169 | 171 | * |
|---|
| .. | .. |
|---|
| 172 | 174 | * The entire selection process is managed under the console_lock. It's |
|---|
| 173 | 175 | * a lot under the lock but its hardly a performance path |
|---|
| 174 | 176 | */ |
|---|
| 175 | | -static int __set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) |
|---|
| 177 | +int set_selection_user(const struct tiocl_selection __user *sel, |
|---|
| 178 | + struct tty_struct *tty) |
|---|
| 176 | 179 | { |
|---|
| 177 | | - struct vc_data *vc = vc_cons[fg_console].d; |
|---|
| 178 | | - int new_sel_start, new_sel_end, spc; |
|---|
| 179 | 180 | struct tiocl_selection v; |
|---|
| 180 | | - char *bp, *obp; |
|---|
| 181 | | - int i, ps, pe, multiplier; |
|---|
| 182 | | - u32 c; |
|---|
| 183 | | - int mode, ret = 0; |
|---|
| 184 | 181 | |
|---|
| 185 | | - poke_blanked_console(); |
|---|
| 186 | 182 | if (copy_from_user(&v, sel, sizeof(*sel))) |
|---|
| 187 | 183 | return -EFAULT; |
|---|
| 188 | 184 | |
|---|
| 189 | | - v.xs = min_t(u16, v.xs - 1, vc->vc_cols - 1); |
|---|
| 190 | | - v.ys = min_t(u16, v.ys - 1, vc->vc_rows - 1); |
|---|
| 191 | | - v.xe = min_t(u16, v.xe - 1, vc->vc_cols - 1); |
|---|
| 192 | | - v.ye = min_t(u16, v.ye - 1, vc->vc_rows - 1); |
|---|
| 193 | | - ps = v.ys * vc->vc_size_row + (v.xs << 1); |
|---|
| 194 | | - pe = v.ye * vc->vc_size_row + (v.xe << 1); |
|---|
| 185 | + return set_selection_kernel(&v, tty); |
|---|
| 186 | +} |
|---|
| 195 | 187 | |
|---|
| 196 | | - if (v.sel_mode == TIOCL_SELCLEAR) { |
|---|
| 197 | | - /* useful for screendump without selection highlights */ |
|---|
| 198 | | - clear_selection(); |
|---|
| 199 | | - return 0; |
|---|
| 200 | | - } |
|---|
| 201 | | - |
|---|
| 202 | | - if (mouse_reporting() && (v.sel_mode & TIOCL_SELMOUSEREPORT)) { |
|---|
| 203 | | - mouse_report(tty, v.sel_mode & TIOCL_SELBUTTONMASK, v.xs, v.ys); |
|---|
| 204 | | - return 0; |
|---|
| 205 | | - } |
|---|
| 206 | | - |
|---|
| 207 | | - if (ps > pe) /* make sel_start <= sel_end */ |
|---|
| 208 | | - swap(ps, pe); |
|---|
| 209 | | - |
|---|
| 210 | | - if (sel_cons != vc_cons[fg_console].d) { |
|---|
| 211 | | - clear_selection(); |
|---|
| 212 | | - sel_cons = vc_cons[fg_console].d; |
|---|
| 213 | | - } |
|---|
| 214 | | - mode = vt_do_kdgkbmode(fg_console); |
|---|
| 215 | | - if (mode == K_UNICODE) |
|---|
| 216 | | - use_unicode = 1; |
|---|
| 217 | | - else |
|---|
| 218 | | - use_unicode = 0; |
|---|
| 219 | | - |
|---|
| 220 | | - switch (v.sel_mode) |
|---|
| 221 | | - { |
|---|
| 222 | | - case TIOCL_SELCHAR: /* character-by-character selection */ |
|---|
| 223 | | - new_sel_start = ps; |
|---|
| 224 | | - new_sel_end = pe; |
|---|
| 225 | | - break; |
|---|
| 226 | | - case TIOCL_SELWORD: /* word-by-word selection */ |
|---|
| 227 | | - spc = isspace(sel_pos(ps)); |
|---|
| 228 | | - for (new_sel_start = ps; ; ps -= 2) |
|---|
| 229 | | - { |
|---|
| 230 | | - if ((spc && !isspace(sel_pos(ps))) || |
|---|
| 231 | | - (!spc && !inword(sel_pos(ps)))) |
|---|
| 232 | | - break; |
|---|
| 233 | | - new_sel_start = ps; |
|---|
| 234 | | - if (!(ps % vc->vc_size_row)) |
|---|
| 235 | | - break; |
|---|
| 236 | | - } |
|---|
| 237 | | - spc = isspace(sel_pos(pe)); |
|---|
| 238 | | - for (new_sel_end = pe; ; pe += 2) |
|---|
| 239 | | - { |
|---|
| 240 | | - if ((spc && !isspace(sel_pos(pe))) || |
|---|
| 241 | | - (!spc && !inword(sel_pos(pe)))) |
|---|
| 242 | | - break; |
|---|
| 243 | | - new_sel_end = pe; |
|---|
| 244 | | - if (!((pe + 2) % vc->vc_size_row)) |
|---|
| 245 | | - break; |
|---|
| 246 | | - } |
|---|
| 247 | | - break; |
|---|
| 248 | | - case TIOCL_SELLINE: /* line-by-line selection */ |
|---|
| 249 | | - new_sel_start = ps - ps % vc->vc_size_row; |
|---|
| 250 | | - new_sel_end = pe + vc->vc_size_row |
|---|
| 251 | | - - pe % vc->vc_size_row - 2; |
|---|
| 252 | | - break; |
|---|
| 253 | | - case TIOCL_SELPOINTER: |
|---|
| 254 | | - highlight_pointer(pe); |
|---|
| 255 | | - return 0; |
|---|
| 256 | | - default: |
|---|
| 257 | | - return -EINVAL; |
|---|
| 258 | | - } |
|---|
| 259 | | - |
|---|
| 260 | | - /* remove the pointer */ |
|---|
| 261 | | - highlight_pointer(-1); |
|---|
| 262 | | - |
|---|
| 263 | | - /* select to end of line if on trailing space */ |
|---|
| 264 | | - if (new_sel_end > new_sel_start && |
|---|
| 265 | | - !atedge(new_sel_end, vc->vc_size_row) && |
|---|
| 266 | | - isspace(sel_pos(new_sel_end))) { |
|---|
| 267 | | - for (pe = new_sel_end + 2; ; pe += 2) |
|---|
| 268 | | - if (!isspace(sel_pos(pe)) || |
|---|
| 269 | | - atedge(pe, vc->vc_size_row)) |
|---|
| 270 | | - break; |
|---|
| 271 | | - if (isspace(sel_pos(pe))) |
|---|
| 272 | | - new_sel_end = pe; |
|---|
| 273 | | - } |
|---|
| 274 | | - if (sel_start == -1) /* no current selection */ |
|---|
| 275 | | - highlight(new_sel_start, new_sel_end); |
|---|
| 276 | | - else if (new_sel_start == sel_start) |
|---|
| 277 | | - { |
|---|
| 278 | | - if (new_sel_end == sel_end) /* no action required */ |
|---|
| 279 | | - return 0; |
|---|
| 280 | | - else if (new_sel_end > sel_end) /* extend to right */ |
|---|
| 281 | | - highlight(sel_end + 2, new_sel_end); |
|---|
| 282 | | - else /* contract from right */ |
|---|
| 283 | | - highlight(new_sel_end + 2, sel_end); |
|---|
| 284 | | - } |
|---|
| 285 | | - else if (new_sel_end == sel_end) |
|---|
| 286 | | - { |
|---|
| 287 | | - if (new_sel_start < sel_start) /* extend to left */ |
|---|
| 288 | | - highlight(new_sel_start, sel_start - 2); |
|---|
| 289 | | - else /* contract from left */ |
|---|
| 290 | | - highlight(sel_start, new_sel_start - 2); |
|---|
| 291 | | - } |
|---|
| 292 | | - else /* some other case; start selection from scratch */ |
|---|
| 293 | | - { |
|---|
| 294 | | - clear_selection(); |
|---|
| 295 | | - highlight(new_sel_start, new_sel_end); |
|---|
| 296 | | - } |
|---|
| 297 | | - sel_start = new_sel_start; |
|---|
| 298 | | - sel_end = new_sel_end; |
|---|
| 188 | +static int vc_selection_store_chars(struct vc_data *vc, bool unicode) |
|---|
| 189 | +{ |
|---|
| 190 | + char *bp, *obp; |
|---|
| 191 | + unsigned int i; |
|---|
| 299 | 192 | |
|---|
| 300 | 193 | /* Allocate a new buffer before freeing the old one ... */ |
|---|
| 301 | | - multiplier = use_unicode ? 4 : 1; /* chars can take up to 4 bytes */ |
|---|
| 302 | | - bp = kmalloc_array((sel_end - sel_start) / 2 + 1, multiplier, |
|---|
| 303 | | - GFP_KERNEL); |
|---|
| 194 | + /* chars can take up to 4 bytes with unicode */ |
|---|
| 195 | + bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1, |
|---|
| 196 | + GFP_KERNEL | __GFP_NOWARN); |
|---|
| 304 | 197 | if (!bp) { |
|---|
| 305 | 198 | printk(KERN_WARNING "selection: kmalloc() failed\n"); |
|---|
| 306 | 199 | clear_selection(); |
|---|
| 307 | 200 | return -ENOMEM; |
|---|
| 308 | 201 | } |
|---|
| 309 | | - kfree(sel_buffer); |
|---|
| 310 | | - sel_buffer = bp; |
|---|
| 202 | + kfree(vc_sel.buffer); |
|---|
| 203 | + vc_sel.buffer = bp; |
|---|
| 311 | 204 | |
|---|
| 312 | 205 | obp = bp; |
|---|
| 313 | | - for (i = sel_start; i <= sel_end; i += 2) { |
|---|
| 314 | | - c = sel_pos(i); |
|---|
| 315 | | - if (use_unicode) |
|---|
| 206 | + for (i = vc_sel.start; i <= vc_sel.end; i += 2) { |
|---|
| 207 | + u32 c = sel_pos(i, unicode); |
|---|
| 208 | + if (unicode) |
|---|
| 316 | 209 | bp += store_utf8(c, bp); |
|---|
| 317 | 210 | else |
|---|
| 318 | 211 | *bp++ = c; |
|---|
| 319 | 212 | if (!isspace(c)) |
|---|
| 320 | 213 | obp = bp; |
|---|
| 321 | | - if (! ((i + 2) % vc->vc_size_row)) { |
|---|
| 214 | + if (!((i + 2) % vc->vc_size_row)) { |
|---|
| 322 | 215 | /* strip trailing blanks from line and add newline, |
|---|
| 323 | 216 | unless non-space at end of line. */ |
|---|
| 324 | 217 | if (obp != bp) { |
|---|
| .. | .. |
|---|
| 328 | 221 | obp = bp; |
|---|
| 329 | 222 | } |
|---|
| 330 | 223 | } |
|---|
| 331 | | - sel_buffer_lth = bp - sel_buffer; |
|---|
| 224 | + vc_sel.buf_len = bp - vc_sel.buffer; |
|---|
| 332 | 225 | |
|---|
| 333 | | - return ret; |
|---|
| 226 | + return 0; |
|---|
| 334 | 227 | } |
|---|
| 335 | 228 | |
|---|
| 336 | | -int set_selection(const struct tiocl_selection __user *v, struct tty_struct *tty) |
|---|
| 229 | +static int vc_do_selection(struct vc_data *vc, unsigned short mode, int ps, |
|---|
| 230 | + int pe) |
|---|
| 231 | +{ |
|---|
| 232 | + int new_sel_start, new_sel_end, spc; |
|---|
| 233 | + bool unicode = vt_do_kdgkbmode(fg_console) == K_UNICODE; |
|---|
| 234 | + |
|---|
| 235 | + switch (mode) { |
|---|
| 236 | + case TIOCL_SELCHAR: /* character-by-character selection */ |
|---|
| 237 | + new_sel_start = ps; |
|---|
| 238 | + new_sel_end = pe; |
|---|
| 239 | + break; |
|---|
| 240 | + case TIOCL_SELWORD: /* word-by-word selection */ |
|---|
| 241 | + spc = isspace(sel_pos(ps, unicode)); |
|---|
| 242 | + for (new_sel_start = ps; ; ps -= 2) { |
|---|
| 243 | + if ((spc && !isspace(sel_pos(ps, unicode))) || |
|---|
| 244 | + (!spc && !inword(sel_pos(ps, unicode)))) |
|---|
| 245 | + break; |
|---|
| 246 | + new_sel_start = ps; |
|---|
| 247 | + if (!(ps % vc->vc_size_row)) |
|---|
| 248 | + break; |
|---|
| 249 | + } |
|---|
| 250 | + |
|---|
| 251 | + spc = isspace(sel_pos(pe, unicode)); |
|---|
| 252 | + for (new_sel_end = pe; ; pe += 2) { |
|---|
| 253 | + if ((spc && !isspace(sel_pos(pe, unicode))) || |
|---|
| 254 | + (!spc && !inword(sel_pos(pe, unicode)))) |
|---|
| 255 | + break; |
|---|
| 256 | + new_sel_end = pe; |
|---|
| 257 | + if (!((pe + 2) % vc->vc_size_row)) |
|---|
| 258 | + break; |
|---|
| 259 | + } |
|---|
| 260 | + break; |
|---|
| 261 | + case TIOCL_SELLINE: /* line-by-line selection */ |
|---|
| 262 | + new_sel_start = rounddown(ps, vc->vc_size_row); |
|---|
| 263 | + new_sel_end = rounddown(pe, vc->vc_size_row) + |
|---|
| 264 | + vc->vc_size_row - 2; |
|---|
| 265 | + break; |
|---|
| 266 | + case TIOCL_SELPOINTER: |
|---|
| 267 | + highlight_pointer(pe); |
|---|
| 268 | + return 0; |
|---|
| 269 | + default: |
|---|
| 270 | + return -EINVAL; |
|---|
| 271 | + } |
|---|
| 272 | + |
|---|
| 273 | + /* remove the pointer */ |
|---|
| 274 | + highlight_pointer(-1); |
|---|
| 275 | + |
|---|
| 276 | + /* select to end of line if on trailing space */ |
|---|
| 277 | + if (new_sel_end > new_sel_start && |
|---|
| 278 | + !atedge(new_sel_end, vc->vc_size_row) && |
|---|
| 279 | + isspace(sel_pos(new_sel_end, unicode))) { |
|---|
| 280 | + for (pe = new_sel_end + 2; ; pe += 2) |
|---|
| 281 | + if (!isspace(sel_pos(pe, unicode)) || |
|---|
| 282 | + atedge(pe, vc->vc_size_row)) |
|---|
| 283 | + break; |
|---|
| 284 | + if (isspace(sel_pos(pe, unicode))) |
|---|
| 285 | + new_sel_end = pe; |
|---|
| 286 | + } |
|---|
| 287 | + if (vc_sel.start == -1) /* no current selection */ |
|---|
| 288 | + highlight(new_sel_start, new_sel_end); |
|---|
| 289 | + else if (new_sel_start == vc_sel.start) |
|---|
| 290 | + { |
|---|
| 291 | + if (new_sel_end == vc_sel.end) /* no action required */ |
|---|
| 292 | + return 0; |
|---|
| 293 | + else if (new_sel_end > vc_sel.end) /* extend to right */ |
|---|
| 294 | + highlight(vc_sel.end + 2, new_sel_end); |
|---|
| 295 | + else /* contract from right */ |
|---|
| 296 | + highlight(new_sel_end + 2, vc_sel.end); |
|---|
| 297 | + } |
|---|
| 298 | + else if (new_sel_end == vc_sel.end) |
|---|
| 299 | + { |
|---|
| 300 | + if (new_sel_start < vc_sel.start) /* extend to left */ |
|---|
| 301 | + highlight(new_sel_start, vc_sel.start - 2); |
|---|
| 302 | + else /* contract from left */ |
|---|
| 303 | + highlight(vc_sel.start, new_sel_start - 2); |
|---|
| 304 | + } |
|---|
| 305 | + else /* some other case; start selection from scratch */ |
|---|
| 306 | + { |
|---|
| 307 | + clear_selection(); |
|---|
| 308 | + highlight(new_sel_start, new_sel_end); |
|---|
| 309 | + } |
|---|
| 310 | + vc_sel.start = new_sel_start; |
|---|
| 311 | + vc_sel.end = new_sel_end; |
|---|
| 312 | + |
|---|
| 313 | + return vc_selection_store_chars(vc, unicode); |
|---|
| 314 | +} |
|---|
| 315 | + |
|---|
| 316 | +static int vc_selection(struct vc_data *vc, struct tiocl_selection *v, |
|---|
| 317 | + struct tty_struct *tty) |
|---|
| 318 | +{ |
|---|
| 319 | + int ps, pe; |
|---|
| 320 | + |
|---|
| 321 | + poke_blanked_console(); |
|---|
| 322 | + |
|---|
| 323 | + if (v->sel_mode == TIOCL_SELCLEAR) { |
|---|
| 324 | + /* useful for screendump without selection highlights */ |
|---|
| 325 | + clear_selection(); |
|---|
| 326 | + return 0; |
|---|
| 327 | + } |
|---|
| 328 | + |
|---|
| 329 | + v->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1); |
|---|
| 330 | + v->ys = min_t(u16, v->ys - 1, vc->vc_rows - 1); |
|---|
| 331 | + v->xe = min_t(u16, v->xe - 1, vc->vc_cols - 1); |
|---|
| 332 | + v->ye = min_t(u16, v->ye - 1, vc->vc_rows - 1); |
|---|
| 333 | + |
|---|
| 334 | + if (mouse_reporting() && (v->sel_mode & TIOCL_SELMOUSEREPORT)) { |
|---|
| 335 | + mouse_report(tty, v->sel_mode & TIOCL_SELBUTTONMASK, v->xs, |
|---|
| 336 | + v->ys); |
|---|
| 337 | + return 0; |
|---|
| 338 | + } |
|---|
| 339 | + |
|---|
| 340 | + ps = v->ys * vc->vc_size_row + (v->xs << 1); |
|---|
| 341 | + pe = v->ye * vc->vc_size_row + (v->xe << 1); |
|---|
| 342 | + if (ps > pe) /* make vc_sel.start <= vc_sel.end */ |
|---|
| 343 | + swap(ps, pe); |
|---|
| 344 | + |
|---|
| 345 | + if (vc_sel.cons != vc) { |
|---|
| 346 | + clear_selection(); |
|---|
| 347 | + vc_sel.cons = vc; |
|---|
| 348 | + } |
|---|
| 349 | + |
|---|
| 350 | + return vc_do_selection(vc, v->sel_mode, ps, pe); |
|---|
| 351 | +} |
|---|
| 352 | + |
|---|
| 353 | +int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty) |
|---|
| 337 | 354 | { |
|---|
| 338 | 355 | int ret; |
|---|
| 339 | 356 | |
|---|
| 340 | | - mutex_lock(&sel_lock); |
|---|
| 357 | + mutex_lock(&vc_sel.lock); |
|---|
| 341 | 358 | console_lock(); |
|---|
| 342 | | - ret = __set_selection(v, tty); |
|---|
| 359 | + ret = vc_selection(vc_cons[fg_console].d, v, tty); |
|---|
| 343 | 360 | console_unlock(); |
|---|
| 344 | | - mutex_unlock(&sel_lock); |
|---|
| 361 | + mutex_unlock(&vc_sel.lock); |
|---|
| 345 | 362 | |
|---|
| 346 | 363 | return ret; |
|---|
| 347 | 364 | } |
|---|
| 365 | +EXPORT_SYMBOL_GPL(set_selection_kernel); |
|---|
| 348 | 366 | |
|---|
| 349 | 367 | /* Insert the contents of the selection buffer into the |
|---|
| 350 | 368 | * queue of the tty associated with the current console. |
|---|
| .. | .. |
|---|
| 372 | 390 | tty_buffer_lock_exclusive(&vc->port); |
|---|
| 373 | 391 | |
|---|
| 374 | 392 | add_wait_queue(&vc->paste_wait, &wait); |
|---|
| 375 | | - mutex_lock(&sel_lock); |
|---|
| 376 | | - while (sel_buffer && sel_buffer_lth > pasted) { |
|---|
| 393 | + mutex_lock(&vc_sel.lock); |
|---|
| 394 | + while (vc_sel.buffer && vc_sel.buf_len > pasted) { |
|---|
| 377 | 395 | set_current_state(TASK_INTERRUPTIBLE); |
|---|
| 378 | 396 | if (signal_pending(current)) { |
|---|
| 379 | 397 | ret = -EINTR; |
|---|
| 380 | 398 | break; |
|---|
| 381 | 399 | } |
|---|
| 382 | 400 | if (tty_throttled(tty)) { |
|---|
| 383 | | - mutex_unlock(&sel_lock); |
|---|
| 401 | + mutex_unlock(&vc_sel.lock); |
|---|
| 384 | 402 | schedule(); |
|---|
| 385 | | - mutex_lock(&sel_lock); |
|---|
| 403 | + mutex_lock(&vc_sel.lock); |
|---|
| 386 | 404 | continue; |
|---|
| 387 | 405 | } |
|---|
| 388 | 406 | __set_current_state(TASK_RUNNING); |
|---|
| 389 | | - count = sel_buffer_lth - pasted; |
|---|
| 390 | | - count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL, |
|---|
| 407 | + count = vc_sel.buf_len - pasted; |
|---|
| 408 | + count = tty_ldisc_receive_buf(ld, vc_sel.buffer + pasted, NULL, |
|---|
| 391 | 409 | count); |
|---|
| 392 | 410 | pasted += count; |
|---|
| 393 | 411 | } |
|---|
| 394 | | - mutex_unlock(&sel_lock); |
|---|
| 412 | + mutex_unlock(&vc_sel.lock); |
|---|
| 395 | 413 | remove_wait_queue(&vc->paste_wait, &wait); |
|---|
| 396 | 414 | __set_current_state(TASK_RUNNING); |
|---|
| 397 | 415 | |
|---|
| .. | .. |
|---|
| 399 | 417 | tty_ldisc_deref(ld); |
|---|
| 400 | 418 | return ret; |
|---|
| 401 | 419 | } |
|---|
| 420 | +EXPORT_SYMBOL_GPL(paste_selection); |
|---|