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