Annotation of src/usr.sbin/wsmoused/selection.c, Revision 1.1
1.1 ! christos 1: /* $NetBSD$ */
! 2:
! 3: /*
! 4: * Copyright (c) 2002 The NetBSD Foundation, Inc.
! 5: * All rights reserved.
! 6: *
! 7: * This code is derived from software contributed to The NetBSD Foundation
! 8: * by Julio Merino.
! 9: *
! 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice, this list of conditions and the following disclaimer.
! 15: * 2. The name authors may not be used to endorse or promote products
! 16: * derived from this software without specific prior written
! 17: * permission.
! 18: *
! 19: * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
! 20: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 21: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 22: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
! 23: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
! 25: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 27: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
! 28: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
! 29: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 30: */
! 31:
! 32: #include <sys/cdefs.h>
! 33:
! 34: #ifndef lint
! 35: __RCSID("$NetBSD$");
! 36: #endif /* not lint */
! 37:
! 38: #include <sys/ioctl.h>
! 39: #include <sys/time.h>
! 40: #include <sys/types.h>
! 41: #include <sys/tty.h>
! 42: #include <dev/wscons/wsconsio.h>
! 43:
! 44: #include <ctype.h>
! 45: #include <fcntl.h>
! 46: #include <err.h>
! 47: #include <errno.h>
! 48: #include <stdio.h>
! 49: #include <stdlib.h>
! 50: #include <string.h>
! 51: #include <unistd.h>
! 52:
! 53: #include "pathnames.h"
! 54: #include "wsmoused.h"
! 55:
! 56: /* This struct holds information about a sel. For now there is
! 57: * only one global instace, but using a structre gives us a place for
! 58: * maintaining all the variables together. Also, someone may want to
! 59: * allow multiple sels, so it is easier this way. */
! 60: static struct selection {
! 61: size_t start_row, start_col;
! 62: size_t end_row, end_col;
! 63: size_t abs_start, abs_end;
! 64: size_t text_size;
! 65: char *text;
! 66: } sel;
! 67:
! 68:
! 69: static void *
! 70: alloc_sel(size_t len)
! 71: {
! 72: void *ptr;
! 73: if ((ptr = malloc(len)) == NULL) {
! 74: warn("Cannot allocate memory for sel %lu",
! 75: (unsigned long)len);
! 76: return NULL;
! 77: }
! 78: return ptr;
! 79: }
! 80:
! 81: static void
! 82: fill_buf(char *ptr, struct mouse *m, size_t row, size_t col, size_t end)
! 83: {
! 84: struct wsdisplay_char ch;
! 85: ch.row = sel.start_row;
! 86: for (ch.col = col; ch.col < end; ch.col++) {
! 87: if (ioctl(m->tty_fd, WSDISPLAYIO_GETWSCHAR, &ch) == -1) {
! 88: warn("ioctl(WSDISPLAYIO_GETWSCHAR) failed");
! 89: *ptr++ = ' ';
! 90: } else {
! 91: *ptr++ = ch.letter;
! 92: }
! 93: }
! 94: }
! 95:
! 96:
! 97: /*
! 98: * This function scans the specified line and checks its
! 99: * length. Characters at the end of it which match isspace() are not
! 100: * counted.
! 101: */
! 102: static size_t
! 103: row_length(struct mouse *m, size_t row)
! 104: {
! 105: struct wsdisplay_char ch;
! 106:
! 107: ch.col = m->max_col;
! 108: ch.row = row;
! 109: do {
! 110: if (ioctl(m->tty_fd, WSDISPLAYIO_GETWSCHAR, &ch) == -1)
! 111: warn("ioctl(WSDISPLAYIO_GETWSCHAR) failed");
! 112: ch.col--;
! 113: } while (isspace((unsigned char)ch.letter));
! 114: return ch.col + 2;
! 115: }
! 116:
! 117: /*
! 118: * This (complex) function copies all the text englobed in the current
! 119: * sel to the sel buffer. It does space trimming at end of
! 120: * lines if it is selected.
! 121: */
! 122: static void
! 123: sel_copy_text(struct mouse *m)
! 124: {
! 125: char *str, *ptr;
! 126: size_t r, l;
! 127:
! 128: if (sel.start_row == sel.end_row) {
! 129: /* Selection is one row */
! 130: l = row_length(m, sel.start_row);
! 131: if (sel.start_col > l)
! 132: /* Selection is after last character,
! 133: * therefore it is empty */
! 134: str = NULL;
! 135: else {
! 136: if (sel.end_col > l)
! 137: sel.end_col = l;
! 138: ptr = str = alloc_sel( sel.end_col - sel.start_col + 1);
! 139: if (ptr == NULL)
! 140: return;
! 141:
! 142: fill_buf(ptr, m, sel.start_row, sel.start_col,
! 143: sel.end_col);
! 144: *ptr = '\0';
! 145: }
! 146: } else {
! 147: /* Selection is multiple rows */
! 148: ptr = str = alloc_sel(sel.abs_end - sel.abs_start + 1);
! 149: if (ptr == NULL)
! 150: return;
! 151:
! 152: /* Calculate and copy first line */
! 153: l = row_length(m, sel.start_row);
! 154: if (sel.start_col < l) {
! 155: fill_buf(ptr, m, sel.start_row, sel.start_col, l);
! 156: *ptr++ = '\r';
! 157: }
! 158:
! 159: /* Copy mid lines if there are any */
! 160: if ((sel.end_row - sel.start_row) > 1) {
! 161: for (r = sel.start_row + 1; r <= sel.end_row - 1; r++) {
! 162: fill_buf(ptr, m, r, 0, row_length(m, r));
! 163: *ptr++ = '\r';
! 164: }
! 165: }
! 166:
! 167: /* Calculate and copy end line */
! 168: l = row_length(m, sel.end_row);
! 169: if (sel.end_col < l)
! 170: l = sel.end_col;
! 171: fill_buf(ptr, m, sel.end_row, 0, l);
! 172: *ptr = '\0';
! 173: }
! 174:
! 175: if (sel.text != NULL) {
! 176: free(sel.text);
! 177: sel.text = NULL;
! 178: }
! 179:
! 180: if (str != NULL) {
! 181: sel.text = str;
! 182: sel.text_size = ptr - str;
! 183: }
! 184: }
! 185:
! 186: /*
! 187: * Initializes sel data. It should be called only once, at
! 188: * wsmoused startup to initialize pointers.
! 189: */
! 190: void
! 191: mouse_sel_init()
! 192: {
! 193: memset(&sel, 0, sizeof(struct selection));
! 194: }
! 195:
! 196: /*
! 197: * Starts a sel (when mouse is pressed).
! 198: */
! 199: void
! 200: mouse_sel_start(struct mouse *m)
! 201: {
! 202: if (sel.text != NULL) {
! 203: free(sel.text);
! 204: sel.text = NULL;
! 205: }
! 206:
! 207: sel.start_row = m->row;
! 208: sel.start_col = m->col;
! 209: mouse_sel_calculate(m);
! 210: m->selecting = 1;
! 211: }
! 212:
! 213: /*
! 214: * Ends a sel. Text is copied to memory for future pasting and
! 215: * highlighted region is returned to normal state.
! 216: */
! 217: void
! 218: mouse_sel_end(struct mouse *m)
! 219: {
! 220: size_t i;
! 221:
! 222: mouse_sel_calculate(m);
! 223:
! 224: /* Invert sel coordinates if needed */
! 225: if (sel.start_col > sel.end_col) {
! 226: i = sel.end_col;
! 227: sel.end_col = sel.start_col;
! 228: sel.start_col = i;
! 229: }
! 230: if (sel.start_row > sel.end_row) {
! 231: i = sel.end_row;
! 232: sel.end_row = sel.start_row;
! 233: sel.start_row = i;
! 234: }
! 235:
! 236: sel_copy_text(m);
! 237: m->selecting = 0;
! 238: }
! 239:
! 240: /*
! 241: * Calculates sel absolute postitions.
! 242: */
! 243: void
! 244: mouse_sel_calculate(struct mouse *m)
! 245: {
! 246: size_t i = m->max_col + 1;
! 247:
! 248: sel.end_row = m->row;
! 249: sel.end_col = m->col;
! 250: sel.abs_start = sel.start_row * i + sel.start_col;
! 251: sel.abs_end = sel.end_row * i + sel.end_col;
! 252:
! 253: if (sel.abs_start > sel.abs_end) {
! 254: i = sel.abs_end;
! 255: sel.abs_end = sel.abs_start;
! 256: sel.abs_start = i;
! 257: }
! 258: }
! 259:
! 260: /*
! 261: * Hides highlighted region, returning it to normal colors.
! 262: */
! 263: void
! 264: mouse_sel_hide(struct mouse *m)
! 265: {
! 266: size_t i;
! 267:
! 268: for (i = sel.abs_start; i <= sel.abs_end; i++)
! 269: char_invert(m, 0, i);
! 270: }
! 271:
! 272: /*
! 273: * Highlights selected region.
! 274: */
! 275: void
! 276: mouse_sel_show(struct mouse *m)
! 277: {
! 278: size_t i;
! 279:
! 280: mouse_sel_calculate(m);
! 281: for (i = sel.abs_start; i <= sel.abs_end; i++)
! 282: char_invert(m, 0, i);
! 283: }
! 284:
! 285:
! 286: /*
! 287: * Pastes selected text into the active console.
! 288: */
! 289: void
! 290: mouse_sel_paste(struct mouse *m)
! 291: {
! 292: size_t i;
! 293:
! 294: if (sel.text == NULL)
! 295: return;
! 296: for (i = 0; i < sel.text_size; i++)
! 297: if (ioctl(m->tty_fd, TIOCSTI, &sel.text[i]) == -1)
! 298: warn("ioctl(TIOCSTI)");
! 299: }
CVSweb <webmaster@jp.NetBSD.org>