cursor.c revision d522f475
1/* $XTermId: cursor.c,v 1.45 2008/04/20 21:06:22 tom Exp $ */ 2 3/* $XFree86: xc/programs/xterm/cursor.c,v 3.20 2006/02/13 01:14:58 dickey Exp $ */ 4 5/* 6 * Copyright 2002-2007,2008 by Thomas E. Dickey 7 * 8 * All Rights Reserved 9 * 10 * Permission is hereby granted, free of charge, to any person obtaining a 11 * copy of this software and associated documentation files (the 12 * "Software"), to deal in the Software without restriction, including 13 * without limitation the rights to use, copy, modify, merge, publish, 14 * distribute, sublicense, and/or sell copies of the Software, and to 15 * permit persons to whom the Software is furnished to do so, subject to 16 * the following conditions: 17 * 18 * The above copyright notice and this permission notice shall be included 19 * in all copies or substantial portions of the Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 25 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 * 29 * Except as contained in this notice, the name(s) of the above copyright 30 * holders shall not be used in advertising or otherwise to promote the 31 * sale, use or other dealings in this Software without prior written 32 * authorization. 33 * 34 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 35 * 36 * All Rights Reserved 37 * 38 * Permission to use, copy, modify, and distribute this software and its 39 * documentation for any purpose and without fee is hereby granted, 40 * provided that the above copyright notice appear in all copies and that 41 * both that copyright notice and this permission notice appear in 42 * supporting documentation, and that the name of Digital Equipment 43 * Corporation not be used in advertising or publicity pertaining to 44 * distribution of the software without specific, written prior permission. 45 * 46 * 47 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 48 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 49 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 50 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 51 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 52 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 53 * SOFTWARE. 54 */ 55 56/* cursor.c */ 57 58#include <xterm.h> 59#include <data.h> 60#include <menu.h> 61 62#include <assert.h> 63 64/* 65 * Moves the cursor to the specified position, checking for bounds. 66 * (this includes scrolling regions) 67 * The origin is considered to be 0, 0 for this procedure. 68 */ 69void 70CursorSet(TScreen * screen, int row, int col, unsigned flags) 71{ 72 int use_row = row; 73 int max_row; 74 75 col = (col < 0 ? 0 : col); 76 set_cur_col(screen, (col <= screen->max_col ? col : screen->max_col)); 77 max_row = screen->max_row; 78 if (flags & ORIGIN) { 79 use_row += screen->top_marg; 80 max_row = screen->bot_marg; 81 } 82 use_row = (use_row < 0 ? 0 : use_row); 83 set_cur_row(screen, (use_row <= max_row ? use_row : max_row)); 84 screen->do_wrap = 0; 85 86 TRACE(("CursorSet(%d,%d) margins [%d..%d] -> %d,%d %s\n", 87 row, col, 88 screen->top_marg, 89 screen->bot_marg, 90 screen->cur_row, 91 screen->cur_col, 92 (flags & ORIGIN ? "origin" : "normal"))); 93} 94 95/* 96 * moves the cursor left n, no wrap around 97 */ 98void 99CursorBack(XtermWidget xw, int n) 100{ 101 TScreen *screen = &xw->screen; 102 int i, j, k, rev; 103 104 if ((rev = (xw->flags & (REVERSEWRAP | WRAPAROUND)) == 105 (REVERSEWRAP | WRAPAROUND)) != 0 106 && screen->do_wrap) 107 n--; 108 if ((screen->cur_col -= n) < 0) { 109 if (rev) { 110 if ((i = ((j = MaxCols(screen)) 111 * screen->cur_row) + screen->cur_col) < 0) { 112 k = j * MaxRows(screen); 113 i += ((-i) / k + 1) * k; 114 } 115 set_cur_row(screen, i / j); 116 set_cur_col(screen, i % j); 117 do_xevents(); 118 } else { 119 set_cur_col(screen, 0); 120 } 121 } 122 screen->do_wrap = 0; 123} 124 125/* 126 * moves the cursor forward n, no wraparound 127 */ 128void 129CursorForward(TScreen * screen, int n) 130{ 131 int next = screen->cur_col + n; 132 int max = CurMaxCol(screen, screen->cur_row); 133 134 if (next > max) 135 next = max; 136 137 set_cur_col(screen, next); 138 screen->do_wrap = 0; 139} 140 141/* 142 * moves the cursor down n, no scrolling. 143 * Won't pass bottom margin or bottom of screen. 144 */ 145void 146CursorDown(TScreen * screen, int n) 147{ 148 int max; 149 int next = screen->cur_row + n; 150 151 max = (screen->cur_row > screen->bot_marg ? 152 screen->max_row : screen->bot_marg); 153 if (next > max) 154 next = max; 155 if (next > screen->max_row) 156 next = screen->max_row; 157 158 set_cur_row(screen, next); 159 screen->do_wrap = 0; 160} 161 162/* 163 * moves the cursor up n, no linestarving. 164 * Won't pass top margin or top of screen. 165 */ 166void 167CursorUp(TScreen * screen, int n) 168{ 169 int min; 170 int next = screen->cur_row - n; 171 172 min = ((screen->cur_row < screen->top_marg) 173 ? 0 174 : screen->top_marg); 175 if (next < min) 176 next = min; 177 if (next < 0) 178 next = 0; 179 180 set_cur_row(screen, next); 181 screen->do_wrap = 0; 182} 183 184/* 185 * Moves cursor down amount lines, scrolls if necessary. 186 * Won't leave scrolling region. No carriage return. 187 */ 188void 189xtermIndex(XtermWidget xw, int amount) 190{ 191 TScreen *screen = &xw->screen; 192 int j; 193 194 /* 195 * indexing when below scrolling region is cursor down. 196 * if cursor high enough, no scrolling necessary. 197 */ 198 if (screen->cur_row > screen->bot_marg 199 || screen->cur_row + amount <= screen->bot_marg) { 200 CursorDown(screen, amount); 201 return; 202 } 203 204 CursorDown(screen, j = screen->bot_marg - screen->cur_row); 205 xtermScroll(xw, amount - j); 206} 207 208/* 209 * Moves cursor up amount lines, reverse scrolls if necessary. 210 * Won't leave scrolling region. No carriage return. 211 */ 212void 213RevIndex(XtermWidget xw, int amount) 214{ 215 TScreen *screen = &xw->screen; 216 217 /* 218 * reverse indexing when above scrolling region is cursor up. 219 * if cursor low enough, no reverse indexing needed 220 */ 221 if (screen->cur_row < screen->top_marg 222 || screen->cur_row - amount >= screen->top_marg) { 223 CursorUp(screen, amount); 224 return; 225 } 226 227 RevScroll(xw, amount - (screen->cur_row - screen->top_marg)); 228 CursorUp(screen, screen->cur_row - screen->top_marg); 229} 230 231/* 232 * Moves Cursor To First Column In Line 233 * (Note: xterm doesn't implement SLH, SLL which would affect use of this) 234 */ 235void 236CarriageReturn(TScreen * screen) 237{ 238 set_cur_col(screen, 0); 239 screen->do_wrap = 0; 240 do_xevents(); 241} 242 243/* 244 * When resizing the window, if we're showing the alternate screen, we still 245 * have to adjust the saved cursor from the normal screen to account for 246 * shifting of the saved-line region in/out of the viewable window. 247 */ 248void 249AdjustSavedCursor(XtermWidget xw, int adjust) 250{ 251 TScreen *screen = &xw->screen; 252 253 if (screen->alternate) { 254 SavedCursor *sc = &screen->sc[screen->alternate == False]; 255 256 if (adjust > 0) { 257 TRACE(("AdjustSavedCursor %d -> %d\n", sc->row, sc->row - adjust)); 258 sc->row += adjust; 259 } 260 } 261} 262 263/* 264 * Save Cursor and Attributes 265 */ 266void 267CursorSave(XtermWidget xw) 268{ 269 TScreen *screen = &xw->screen; 270 SavedCursor *sc = &screen->sc[screen->alternate != False]; 271 272 sc->saved = True; 273 sc->row = screen->cur_row; 274 sc->col = screen->cur_col; 275 sc->flags = xw->flags; 276 sc->curgl = screen->curgl; 277 sc->curgr = screen->curgr; 278#if OPT_ISO_COLORS 279 sc->cur_foreground = xw->cur_foreground; 280 sc->cur_background = xw->cur_background; 281 sc->sgr_foreground = xw->sgr_foreground; 282#endif 283 memmove(sc->gsets, screen->gsets, sizeof(screen->gsets)); 284} 285 286/* 287 * We save/restore all visible attributes, plus wrapping, origin mode, and the 288 * selective erase attribute. 289 */ 290#define DECSC_FLAGS (ATTRIBUTES|ORIGIN|WRAPAROUND|PROTECTED) 291 292/* 293 * Restore Cursor and Attributes 294 */ 295void 296CursorRestore(XtermWidget xw) 297{ 298 TScreen *screen = &xw->screen; 299 SavedCursor *sc = &screen->sc[screen->alternate != False]; 300 301 /* Restore the character sets, unless we never did a save-cursor op. 302 * In that case, we'll reset the character sets. 303 */ 304 if (sc->saved) { 305 memmove(screen->gsets, sc->gsets, sizeof(screen->gsets)); 306 screen->curgl = sc->curgl; 307 screen->curgr = sc->curgr; 308 } else { 309 resetCharsets(screen); 310 } 311 312 xw->flags &= ~DECSC_FLAGS; 313 xw->flags |= sc->flags & DECSC_FLAGS; 314 CursorSet(screen, 315 ((xw->flags & ORIGIN) 316 ? sc->row - screen->top_marg 317 : sc->row), 318 sc->col, xw->flags); 319 320#if OPT_ISO_COLORS 321 xw->sgr_foreground = sc->sgr_foreground; 322 SGR_Foreground(xw, xw->flags & FG_COLOR ? sc->cur_foreground : -1); 323 SGR_Background(xw, xw->flags & BG_COLOR ? sc->cur_background : -1); 324#endif 325 update_autowrap(); 326} 327 328/* 329 * Move the cursor to the first column of the n-th next line. 330 */ 331void 332CursorNextLine(TScreen * screen, int count) 333{ 334 CursorDown(screen, count < 1 ? 1 : count); 335 CarriageReturn(screen); 336 do_xevents(); 337} 338 339/* 340 * Move the cursor to the first column of the n-th previous line. 341 */ 342void 343CursorPrevLine(TScreen * screen, int count) 344{ 345 CursorUp(screen, count < 1 ? 1 : count); 346 CarriageReturn(screen); 347 do_xevents(); 348} 349 350#if OPT_TRACE 351int 352set_cur_row(TScreen * screen, int value) 353{ 354 assert(screen != 0); 355 assert(value >= 0); 356 assert(value <= screen->max_row); 357 screen->cur_row = value; 358 return value; 359} 360 361int 362set_cur_col(TScreen * screen, int value) 363{ 364 assert(screen != 0); 365 assert(value >= 0); 366 assert(value <= screen->max_col); 367 screen->cur_col = value; 368 return value; 369} 370#endif /* OPT_TRACE */ 371