at v3.7 151 lines 3.8 kB view raw
1#include <linux/slab.h> /* for kmalloc */ 2#include <linux/consolemap.h> 3#include <linux/interrupt.h> 4#include <linux/sched.h> 5#include <linux/selection.h> 6 7#include "speakup.h" 8 9/* ------ cut and paste ----- */ 10/* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */ 11#define ishardspace(c) ((c) == ' ') 12 13unsigned short xs, ys, xe, ye; /* our region points */ 14 15/* Variables for selection control. */ 16/* must not be disallocated */ 17struct vc_data *spk_sel_cons; 18/* cleared by clear_selection */ 19static int sel_start = -1; 20static int sel_end; 21static int sel_buffer_lth; 22static char *sel_buffer; 23 24static unsigned char sel_pos(int n) 25{ 26 return inverse_translate(spk_sel_cons, 27 screen_glyph(spk_sel_cons, n), 0); 28} 29 30void speakup_clear_selection(void) 31{ 32 sel_start = -1; 33} 34 35/* does screen address p correspond to character at LH/RH edge of screen? */ 36static int atedge(const int p, int size_row) 37{ 38 return !(p % size_row) || !((p + 2) % size_row); 39} 40 41/* constrain v such that v <= u */ 42static unsigned short limit(const unsigned short v, const unsigned short u) 43{ 44 return (v > u) ? u : v; 45} 46 47int speakup_set_selection(struct tty_struct *tty) 48{ 49 int new_sel_start, new_sel_end; 50 char *bp, *obp; 51 int i, ps, pe; 52 struct vc_data *vc = vc_cons[fg_console].d; 53 54 xs = limit(xs, vc->vc_cols - 1); 55 ys = limit(ys, vc->vc_rows - 1); 56 xe = limit(xe, vc->vc_cols - 1); 57 ye = limit(ye, vc->vc_rows - 1); 58 ps = ys * vc->vc_size_row + (xs << 1); 59 pe = ye * vc->vc_size_row + (xe << 1); 60 61 if (ps > pe) { 62 /* make sel_start <= sel_end */ 63 int tmp = ps; 64 ps = pe; 65 pe = tmp; 66 } 67 68 if (spk_sel_cons != vc_cons[fg_console].d) { 69 speakup_clear_selection(); 70 spk_sel_cons = vc_cons[fg_console].d; 71 dev_warn(tty->dev, 72 "Selection: mark console not the same as cut\n"); 73 return -EINVAL; 74 } 75 76 new_sel_start = ps; 77 new_sel_end = pe; 78 79 /* select to end of line if on trailing space */ 80 if (new_sel_end > new_sel_start && 81 !atedge(new_sel_end, vc->vc_size_row) && 82 ishardspace(sel_pos(new_sel_end))) { 83 for (pe = new_sel_end + 2; ; pe += 2) 84 if (!ishardspace(sel_pos(pe)) || 85 atedge(pe, vc->vc_size_row)) 86 break; 87 if (ishardspace(sel_pos(pe))) 88 new_sel_end = pe; 89 } 90 if ((new_sel_start == sel_start) && (new_sel_end == sel_end)) 91 return 0; /* no action required */ 92 93 sel_start = new_sel_start; 94 sel_end = new_sel_end; 95 /* Allocate a new buffer before freeing the old one ... */ 96 bp = kmalloc((sel_end-sel_start)/2+1, GFP_ATOMIC); 97 if (!bp) { 98 dev_warn(tty->dev, "selection: kmalloc() failed\n"); 99 speakup_clear_selection(); 100 return -ENOMEM; 101 } 102 kfree(sel_buffer); 103 sel_buffer = bp; 104 105 obp = bp; 106 for (i = sel_start; i <= sel_end; i += 2) { 107 *bp = sel_pos(i); 108 if (!ishardspace(*bp++)) 109 obp = bp; 110 if (!((i + 2) % vc->vc_size_row)) { 111 /* strip trailing blanks from line and add newline, 112 unless non-space at end of line. */ 113 if (obp != bp) { 114 bp = obp; 115 *bp++ = '\r'; 116 } 117 obp = bp; 118 } 119 } 120 sel_buffer_lth = bp - sel_buffer; 121 return 0; 122} 123 124/* TODO: move to some helper thread, probably. That'd fix having to check for 125 * in_atomic(). */ 126int speakup_paste_selection(struct tty_struct *tty) 127{ 128 struct vc_data *vc = (struct vc_data *) tty->driver_data; 129 int pasted = 0, count; 130 DECLARE_WAITQUEUE(wait, current); 131 add_wait_queue(&vc->paste_wait, &wait); 132 while (sel_buffer && sel_buffer_lth > pasted) { 133 set_current_state(TASK_INTERRUPTIBLE); 134 if (test_bit(TTY_THROTTLED, &tty->flags)) { 135 if (in_atomic()) 136 /* if we are in an interrupt handler, abort */ 137 break; 138 schedule(); 139 continue; 140 } 141 count = sel_buffer_lth - pasted; 142 count = min_t(int, count, tty->receive_room); 143 tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted, 144 NULL, count); 145 pasted += count; 146 } 147 remove_wait_queue(&vc->paste_wait, &wait); 148 current->state = TASK_RUNNING; 149 return 0; 150} 151