cursor.c revision 5104ee6e
15104ee6eSmrg/* $XTermId: cursor.c,v 1.96 2025/01/04 00:58:54 tom Exp $ */ 2d522f475Smrg 3d522f475Smrg/* 45104ee6eSmrg * Copyright 2002-2024,2025 by Thomas E. Dickey 54419d26bSmrg * 6d522f475Smrg * All Rights Reserved 74419d26bSmrg * 8d522f475Smrg * Permission is hereby granted, free of charge, to any person obtaining a 9d522f475Smrg * copy of this software and associated documentation files (the 10d522f475Smrg * "Software"), to deal in the Software without restriction, including 11d522f475Smrg * without limitation the rights to use, copy, modify, merge, publish, 12d522f475Smrg * distribute, sublicense, and/or sell copies of the Software, and to 13d522f475Smrg * permit persons to whom the Software is furnished to do so, subject to 14d522f475Smrg * the following conditions: 154419d26bSmrg * 16d522f475Smrg * The above copyright notice and this permission notice shall be included 17d522f475Smrg * in all copies or substantial portions of the Software. 184419d26bSmrg * 19d522f475Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20d522f475Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21d522f475Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22d522f475Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 23d522f475Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24d522f475Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25d522f475Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 264419d26bSmrg * 27d522f475Smrg * Except as contained in this notice, the name(s) of the above copyright 28d522f475Smrg * holders shall not be used in advertising or otherwise to promote the 29d522f475Smrg * sale, use or other dealings in this Software without prior written 30d522f475Smrg * authorization. 314419d26bSmrg * 32d522f475Smrg * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 33d522f475Smrg * 34d522f475Smrg * All Rights Reserved 35d522f475Smrg * 36d522f475Smrg * Permission to use, copy, modify, and distribute this software and its 37d522f475Smrg * documentation for any purpose and without fee is hereby granted, 38d522f475Smrg * provided that the above copyright notice appear in all copies and that 39d522f475Smrg * both that copyright notice and this permission notice appear in 40d522f475Smrg * supporting documentation, and that the name of Digital Equipment 41d522f475Smrg * Corporation not be used in advertising or publicity pertaining to 42d522f475Smrg * distribution of the software without specific, written prior permission. 43d522f475Smrg * 44d522f475Smrg * 45d522f475Smrg * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 46d522f475Smrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 47d522f475Smrg * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 48d522f475Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 49d522f475Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 50d522f475Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 51d522f475Smrg * SOFTWARE. 52d522f475Smrg */ 53d522f475Smrg 54d522f475Smrg/* cursor.c */ 55d522f475Smrg 56d522f475Smrg#include <xterm.h> 57d522f475Smrg#include <data.h> 58d522f475Smrg#include <menu.h> 59d522f475Smrg 60d522f475Smrg#include <assert.h> 61d522f475Smrg 62d522f475Smrg/* 63d522f475Smrg * Moves the cursor to the specified position, checking for bounds. 64d522f475Smrg * (this includes scrolling regions) 65d522f475Smrg * The origin is considered to be 0, 0 for this procedure. 66d522f475Smrg */ 67d522f475Smrgvoid 682e4f8982SmrgCursorSet(TScreen *screen, int row, int col, unsigned flags) 69d522f475Smrg{ 70d522f475Smrg int use_row = row; 710bd37d32Smrg int use_col = col; 720bd37d32Smrg int max_col = screen->max_col; 730bd37d32Smrg int max_row = screen->max_row; 740bd37d32Smrg 750bd37d32Smrg if (flags & ORIGIN) { 760bd37d32Smrg use_col += screen->lft_marg; 770bd37d32Smrg max_col = screen->rgt_marg; 780bd37d32Smrg } 790bd37d32Smrg use_col = (use_col < 0 ? 0 : use_col); 800bd37d32Smrg set_cur_col(screen, (use_col <= max_col ? use_col : max_col)); 81d522f475Smrg 82d522f475Smrg if (flags & ORIGIN) { 83d522f475Smrg use_row += screen->top_marg; 84d522f475Smrg max_row = screen->bot_marg; 85d522f475Smrg } 86d522f475Smrg use_row = (use_row < 0 ? 0 : use_row); 87d522f475Smrg set_cur_row(screen, (use_row <= max_row ? use_row : max_row)); 88d522f475Smrg 890bd37d32Smrg ResetWrap(screen); 900bd37d32Smrg 910bd37d32Smrg TRACE(("CursorSet(%d,%d) margins V[%d..%d] H[%d..%d] -> %d,%d %s\n", 92d522f475Smrg row, col, 93d522f475Smrg screen->top_marg, 94d522f475Smrg screen->bot_marg, 950bd37d32Smrg screen->lft_marg, 960bd37d32Smrg screen->rgt_marg, 97d522f475Smrg screen->cur_row, 98d522f475Smrg screen->cur_col, 992e4f8982Smrg ((flags & ORIGIN) ? "origin" : "normal"))); 100d522f475Smrg} 101d522f475Smrg 102d522f475Smrg/* 1035307cd1aSmrg * Unlike VT100, xterm allows reverse wrapping of the cursor. This feature was 1045307cd1aSmrg * introduced in X10R4 (December 1986), but did not modify the comment which 1055307cd1aSmrg * said "moves the cursor left n, no wrap around". However, this reverse 1065307cd1aSmrg * wrapping allowed the cursor to wrap around to the end of the screen. 1075307cd1aSmrg * 1085307cd1aSmrg * xterm added VT420-compatible left/right margin support in 2012. If the 1095307cd1aSmrg * cursor starts off within the margins, the reverse wrapping result will be 1105307cd1aSmrg * within the margins. 1115307cd1aSmrg * 1125307cd1aSmrg * Wrapping to the end of the screen did not appear to be the original intent. 11304b94745Smrg * That was revised in 2023, using private mode 45 for movement within the 11404b94745Smrg * current (wrapped) line, and 1045 for movement to "any" line. 115d522f475Smrg */ 116d522f475Smrgvoid 117d522f475SmrgCursorBack(XtermWidget xw, int n) 118d522f475Smrg{ 1190bd37d32Smrg#define WRAP_MASK (REVERSEWRAP | WRAPAROUND) 12004b94745Smrg#define WRAP_MASK2 (REVERSEWRAP2 | WRAPAROUND) 12120d2c4d2Smrg TScreen *screen = TScreenOf(xw); 12204b94745Smrg /* *INDENT-EQLS* */ 12304b94745Smrg int rev = (((xw->flags & WRAP_MASK) == WRAP_MASK) != 0); 12404b94745Smrg int rev2 = (((xw->flags & WRAP_MASK2) == WRAP_MASK2) != 0); 12504b94745Smrg int left = ScrnLeftMargin(xw); 12604b94745Smrg int right = ScrnRightMargin(xw); 1270bd37d32Smrg int before = screen->cur_col; 12804b94745Smrg int top = ScrnTopMargin(xw); 12904b94745Smrg int bottom = ScrnBottomMargin(xw); 13004b94745Smrg int col = screen->cur_col; 13104b94745Smrg int row = screen->cur_row; 132d522f475Smrg 1335307cd1aSmrg int count; 13404b94745Smrg CLineData *ld; 1355307cd1aSmrg 13604b94745Smrg TRACE(("CursorBack(%d) current %d,%d rev=%d/%d margins H[%d..%d] V[%d..%d]\n", 13704b94745Smrg n, 13804b94745Smrg screen->cur_row, screen->cur_col, 13904b94745Smrg rev, rev2, 14004b94745Smrg left, right, 14104b94745Smrg top, bottom)); 1420bd37d32Smrg 1430bd37d32Smrg /* if the cursor is already before the left-margin, we have to let it go */ 1440bd37d32Smrg if (before < left) 1450bd37d32Smrg left = 0; 1460bd37d32Smrg 1475307cd1aSmrg ld = NULL; 14804b94745Smrg if ((count = n) > 0) { 14904b94745Smrg if ((rev || rev2) && screen->do_wrap) { 15004b94745Smrg --count; 15104b94745Smrg } else { 15204b94745Smrg --col; 15304b94745Smrg } 15404b94745Smrg } 1555307cd1aSmrg 1565307cd1aSmrg for (;;) { 1575307cd1aSmrg if (col < left) { 15804b94745Smrg if (rev2) { 15904b94745Smrg col = right; 16004b94745Smrg if (row == top) 16104b94745Smrg row = bottom + 1; 16204b94745Smrg } else { 16304b94745Smrg if (!rev) { 16404b94745Smrg col = left; 16504b94745Smrg break; 16604b94745Smrg } 16704b94745Smrg if (row <= top) { 16804b94745Smrg col = left; 16904b94745Smrg row = top; 17004b94745Smrg break; 17104b94745Smrg } 172d522f475Smrg } 1735307cd1aSmrg ld = NULL; /* try a reverse-wrap */ 1745104ee6eSmrg if (--row <= 0) { 1755104ee6eSmrg row = (top == 0) ? bottom : screen->max_row; 1765104ee6eSmrg } 177d522f475Smrg } 1785307cd1aSmrg if (ld == NULL) { 1795307cd1aSmrg ld = getLineData(screen, ROW2INX(screen, row)); 1805307cd1aSmrg if (ld == NULL) 1815307cd1aSmrg break; /* should not happen */ 1825307cd1aSmrg if (row != screen->cur_row) { 18304b94745Smrg if (!rev2 && !LineTstWrapped(ld)) { 1845307cd1aSmrg ++row; /* reverse-wrap failed */ 1855307cd1aSmrg col = left; 1865307cd1aSmrg break; 1875307cd1aSmrg } 1885307cd1aSmrg col = right; 1895307cd1aSmrg } 1905307cd1aSmrg } 1915307cd1aSmrg 1925307cd1aSmrg if (--count <= 0) 1935307cd1aSmrg break; 1945307cd1aSmrg --col; 195d522f475Smrg } 1965307cd1aSmrg set_cur_row(screen, row); 1975307cd1aSmrg set_cur_col(screen, col); 1985307cd1aSmrg do_xevents(xw); 1995307cd1aSmrg 2000bd37d32Smrg ResetWrap(screen); 201d522f475Smrg} 202d522f475Smrg 203d522f475Smrg/* 204d522f475Smrg * moves the cursor forward n, no wraparound 205d522f475Smrg */ 206d522f475Smrgvoid 2070bd37d32SmrgCursorForward(XtermWidget xw, int n) 208d522f475Smrg{ 2090bd37d32Smrg TScreen *screen = TScreenOf(xw); 210956cc18dSsnj#if OPT_DEC_CHRSET 211956cc18dSsnj LineData *ld = getLineData(screen, screen->cur_row); 212956cc18dSsnj#endif 213d522f475Smrg int next = screen->cur_col + n; 2140bd37d32Smrg int max; 2150bd37d32Smrg 2160bd37d32Smrg if (IsLeftRightMode(xw)) { 2170bd37d32Smrg max = screen->rgt_marg; 2180bd37d32Smrg if (screen->cur_col > max) 2190bd37d32Smrg max = screen->max_col; 2200bd37d32Smrg } else { 2210bd37d32Smrg max = LineMaxCol(screen, ld); 2220bd37d32Smrg } 223d522f475Smrg 224d522f475Smrg if (next > max) 225d522f475Smrg next = max; 226d522f475Smrg 227d522f475Smrg set_cur_col(screen, next); 2280bd37d32Smrg ResetWrap(screen); 229d522f475Smrg} 230d522f475Smrg 231d522f475Smrg/* 232d522f475Smrg * moves the cursor down n, no scrolling. 233d522f475Smrg * Won't pass bottom margin or bottom of screen. 234d522f475Smrg */ 235d522f475Smrgvoid 2362e4f8982SmrgCursorDown(TScreen *screen, int n) 237d522f475Smrg{ 238d522f475Smrg int max; 239d522f475Smrg int next = screen->cur_row + n; 240d522f475Smrg 241d522f475Smrg max = (screen->cur_row > screen->bot_marg ? 242d522f475Smrg screen->max_row : screen->bot_marg); 243d522f475Smrg if (next > max) 244d522f475Smrg next = max; 245d522f475Smrg if (next > screen->max_row) 246d522f475Smrg next = screen->max_row; 247d522f475Smrg 248d522f475Smrg set_cur_row(screen, next); 2490bd37d32Smrg ResetWrap(screen); 250d522f475Smrg} 251d522f475Smrg 252d522f475Smrg/* 253d522f475Smrg * moves the cursor up n, no linestarving. 254d522f475Smrg * Won't pass top margin or top of screen. 255d522f475Smrg */ 256d522f475Smrgvoid 2572e4f8982SmrgCursorUp(TScreen *screen, int n) 258d522f475Smrg{ 259d522f475Smrg int min; 260d522f475Smrg int next = screen->cur_row - n; 261d522f475Smrg 262d522f475Smrg min = ((screen->cur_row < screen->top_marg) 263d522f475Smrg ? 0 264d522f475Smrg : screen->top_marg); 265d522f475Smrg if (next < min) 266d522f475Smrg next = min; 267d522f475Smrg if (next < 0) 268d522f475Smrg next = 0; 269d522f475Smrg 270d522f475Smrg set_cur_row(screen, next); 2710bd37d32Smrg ResetWrap(screen); 272d522f475Smrg} 273d522f475Smrg 274d522f475Smrg/* 275d522f475Smrg * Moves cursor down amount lines, scrolls if necessary. 276d522f475Smrg * Won't leave scrolling region. No carriage return. 277d522f475Smrg */ 278d522f475Smrgvoid 279d522f475SmrgxtermIndex(XtermWidget xw, int amount) 280d522f475Smrg{ 28120d2c4d2Smrg TScreen *screen = TScreenOf(xw); 282d522f475Smrg 283d522f475Smrg /* 284d522f475Smrg * indexing when below scrolling region is cursor down. 285d522f475Smrg * if cursor high enough, no scrolling necessary. 286d522f475Smrg */ 287d522f475Smrg if (screen->cur_row > screen->bot_marg 2880bd37d32Smrg || screen->cur_row + amount <= screen->bot_marg 2890bd37d32Smrg || (IsLeftRightMode(xw) 2900bd37d32Smrg && !ScrnIsColInMargins(screen, screen->cur_col))) { 291d522f475Smrg CursorDown(screen, amount); 2920bd37d32Smrg } else { 2932e4f8982Smrg int j; 2940bd37d32Smrg CursorDown(screen, j = screen->bot_marg - screen->cur_row); 2950bd37d32Smrg xtermScroll(xw, amount - j); 296d522f475Smrg } 297d522f475Smrg} 298d522f475Smrg 299d522f475Smrg/* 300d522f475Smrg * Moves cursor up amount lines, reverse scrolls if necessary. 301d522f475Smrg * Won't leave scrolling region. No carriage return. 302d522f475Smrg */ 303d522f475Smrgvoid 304d522f475SmrgRevIndex(XtermWidget xw, int amount) 305d522f475Smrg{ 30620d2c4d2Smrg TScreen *screen = TScreenOf(xw); 307d522f475Smrg 308d522f475Smrg /* 309d522f475Smrg * reverse indexing when above scrolling region is cursor up. 310d522f475Smrg * if cursor low enough, no reverse indexing needed 311d522f475Smrg */ 312d522f475Smrg if (screen->cur_row < screen->top_marg 3130bd37d32Smrg || screen->cur_row - amount >= screen->top_marg 3140bd37d32Smrg || (IsLeftRightMode(xw) 3150bd37d32Smrg && !ScrnIsColInMargins(screen, screen->cur_col))) { 316d522f475Smrg CursorUp(screen, amount); 3170bd37d32Smrg } else { 3180bd37d32Smrg RevScroll(xw, amount - (screen->cur_row - screen->top_marg)); 3190bd37d32Smrg CursorUp(screen, screen->cur_row - screen->top_marg); 320d522f475Smrg } 321d522f475Smrg} 322d522f475Smrg 323d522f475Smrg/* 324d522f475Smrg * Moves Cursor To First Column In Line 325d522f475Smrg * (Note: xterm doesn't implement SLH, SLL which would affect use of this) 326d522f475Smrg */ 327d522f475Smrgvoid 3280bd37d32SmrgCarriageReturn(XtermWidget xw) 329d522f475Smrg{ 3300bd37d32Smrg TScreen *screen = TScreenOf(xw); 3310bd37d32Smrg int left = ScrnLeftMargin(xw); 3320bd37d32Smrg int col; 3330bd37d32Smrg 3340bd37d32Smrg if (xw->flags & ORIGIN) { 3350bd37d32Smrg col = left; 336e0a2b6dfSmrg } else if (screen->cur_col >= left) { 3370bd37d32Smrg col = left; 3380bd37d32Smrg } else { 3390bd37d32Smrg /* 3400bd37d32Smrg * If origin-mode is not active, it is possible to use cursor 3410bd37d32Smrg * addressing outside the margins. In that case we will go to the 3420bd37d32Smrg * first column rather than following the margin. 3430bd37d32Smrg */ 3440bd37d32Smrg col = 0; 3450bd37d32Smrg } 3460bd37d32Smrg 3470bd37d32Smrg set_cur_col(screen, col); 3480bd37d32Smrg ResetWrap(screen); 34904b94745Smrg if (screen->jumpscroll && !screen->fastscroll) 35004b94745Smrg do_xevents(xw); 351d522f475Smrg} 352d522f475Smrg 353d522f475Smrg/* 354d522f475Smrg * When resizing the window, if we're showing the alternate screen, we still 355d522f475Smrg * have to adjust the saved cursor from the normal screen to account for 356d522f475Smrg * shifting of the saved-line region in/out of the viewable window. 357d522f475Smrg */ 358d522f475Smrgvoid 359d522f475SmrgAdjustSavedCursor(XtermWidget xw, int adjust) 360d522f475Smrg{ 36120d2c4d2Smrg TScreen *screen = TScreenOf(xw); 362d522f475Smrg 363956cc18dSsnj if (screen->whichBuf) { 364956cc18dSsnj SavedCursor *sc = &screen->sc[0]; 365d522f475Smrg 366d522f475Smrg if (adjust > 0) { 367d522f475Smrg TRACE(("AdjustSavedCursor %d -> %d\n", sc->row, sc->row - adjust)); 368d522f475Smrg sc->row += adjust; 369d522f475Smrg } 370d522f475Smrg } 371d522f475Smrg} 372d522f475Smrg 373d522f475Smrg/* 374d522f475Smrg * Save Cursor and Attributes 375d522f475Smrg */ 376d522f475Smrgvoid 3774419d26bSmrgCursorSave2(XtermWidget xw, SavedCursor * sc) 378d522f475Smrg{ 37920d2c4d2Smrg TScreen *screen = TScreenOf(xw); 380d522f475Smrg 381d522f475Smrg sc->saved = True; 382d522f475Smrg sc->row = screen->cur_row; 383d522f475Smrg sc->col = screen->cur_col; 384d522f475Smrg sc->flags = xw->flags; 385d522f475Smrg sc->curgl = screen->curgl; 386d522f475Smrg sc->curgr = screen->curgr; 387913cc679Smrg sc->wrap_flag = screen->do_wrap; 388d522f475Smrg#if OPT_ISO_COLORS 389d522f475Smrg sc->cur_foreground = xw->cur_foreground; 390d522f475Smrg sc->cur_background = xw->cur_background; 391d522f475Smrg sc->sgr_foreground = xw->sgr_foreground; 392f2e35a3aSmrg sc->sgr_38_xcolors = xw->sgr_38_xcolors; 393d522f475Smrg#endif 394f2e35a3aSmrg saveCharsets(screen, sc->gsets); 395d522f475Smrg} 396d522f475Smrg 3974419d26bSmrgvoid 3984419d26bSmrgCursorSave(XtermWidget xw) 3994419d26bSmrg{ 4004419d26bSmrg TScreen *screen = TScreenOf(xw); 4014419d26bSmrg CursorSave2(xw, &screen->sc[screen->whichBuf]); 4024419d26bSmrg} 4034419d26bSmrg 404d522f475Smrg/* 405d522f475Smrg * We save/restore all visible attributes, plus wrapping, origin mode, and the 406d522f475Smrg * selective erase attribute. 4074419d26bSmrg * 4084419d26bSmrg * This is documented, but some of the documentation is incorrect. 4094419d26bSmrg * 4104419d26bSmrg * Page 270 of the VT420 manual (2nd edition) says that DECSC saves these 4114419d26bSmrg * items: 4124419d26bSmrg * 4134419d26bSmrg * Cursor position 4144419d26bSmrg * * Character attributes set by the SGR command 4154419d26bSmrg * * Character sets (G0, G1, G2, or G3) currently in GL and GR 4164419d26bSmrg * * Wrap flag (autowrap or no autowrap) 4174419d26bSmrg * * State of origin mode (DECOM) 4184419d26bSmrg * * Selective erase attribute 4194419d26bSmrg * * Any single shift 2 (SS2) or single shift 3 (SS3) functions sent 4204419d26bSmrg * 4214419d26bSmrg * The VT520 manual has the same information (page 5-120). 4224419d26bSmrg * 4234419d26bSmrg * However, DEC 070 (29-June-1990), pages 5-186 to 5-191, describes 4244419d26bSmrg * save/restore operations, but makes no mention of "wrap". 4254419d26bSmrg * 4264419d26bSmrg * Mattias Engdegård, who has investigated wrapping behavior of different 4274419d26bSmrg * terminals, 4284419d26bSmrg * 4294419d26bSmrg * https://github.com/mattiase/wraptest 4304419d26bSmrg * 4314419d26bSmrg * states 4325104ee6eSmrg * The LCF is saved/restored by the Save/Restore Cursor (DECSC/DECRC) 4335104ee6eSmrg * control sequences. The DECAWM flag is not included in the state 4344419d26bSmrg * managed by these operations. 4354419d26bSmrg * 4364419d26bSmrg * DEC 070 does mention the ANSI color text extension saying that it, too, is 4374419d26bSmrg * saved/restored. 438d522f475Smrg */ 4395307cd1aSmrg#define ALL_FLAGS (IFlags)(~0) 440913cc679Smrg#define DECSC_FLAGS (ATTRIBUTES|ORIGIN|PROTECTED) 441d522f475Smrg 442d522f475Smrg/* 443d522f475Smrg * Restore Cursor and Attributes 444d522f475Smrg */ 4455307cd1aSmrgstatic void 4465307cd1aSmrgCursorRestoreFlags(XtermWidget xw, SavedCursor * sc, IFlags our_flags) 447d522f475Smrg{ 44820d2c4d2Smrg TScreen *screen = TScreenOf(xw); 449d522f475Smrg 450d522f475Smrg /* Restore the character sets, unless we never did a save-cursor op. 451d522f475Smrg * In that case, we'll reset the character sets. 452d522f475Smrg */ 453d522f475Smrg if (sc->saved) { 454f2e35a3aSmrg restoreCharsets(screen, sc->gsets); 455d522f475Smrg screen->curgl = sc->curgl; 456d522f475Smrg screen->curgr = sc->curgr; 457d522f475Smrg } else { 458d522f475Smrg resetCharsets(screen); 459d522f475Smrg } 460d522f475Smrg 4615307cd1aSmrg UIntClr(xw->flags, our_flags); 4625307cd1aSmrg UIntSet(xw->flags, sc->flags & our_flags); 463f2e35a3aSmrg if ((xw->flags & ORIGIN)) { 464f2e35a3aSmrg CursorSet(screen, 465f2e35a3aSmrg sc->row - screen->top_marg, 466f2e35a3aSmrg ((xw->flags & LEFT_RIGHT) 467f2e35a3aSmrg ? sc->col - screen->lft_marg 468f2e35a3aSmrg : sc->col), 469f2e35a3aSmrg xw->flags); 470f2e35a3aSmrg } else { 471f2e35a3aSmrg CursorSet(screen, sc->row, sc->col, xw->flags); 472f2e35a3aSmrg } 473913cc679Smrg screen->do_wrap = sc->wrap_flag; /* after CursorSet/ResetWrap */ 474d522f475Smrg 475d522f475Smrg#if OPT_ISO_COLORS 476d522f475Smrg xw->sgr_foreground = sc->sgr_foreground; 477f2e35a3aSmrg xw->sgr_38_xcolors = sc->sgr_38_xcolors; 4782e4f8982Smrg SGR_Foreground(xw, (xw->flags & FG_COLOR) ? sc->cur_foreground : -1); 4792e4f8982Smrg SGR_Background(xw, (xw->flags & BG_COLOR) ? sc->cur_background : -1); 480d522f475Smrg#endif 481d522f475Smrg} 482d522f475Smrg 4835307cd1aSmrg/* 4845307cd1aSmrg * Use this entrypoint for the status-line. 4855307cd1aSmrg */ 4865307cd1aSmrgvoid 4875307cd1aSmrgCursorRestore2(XtermWidget xw, SavedCursor * sc) 4885307cd1aSmrg{ 4895307cd1aSmrg CursorRestoreFlags(xw, sc, ALL_FLAGS); 4905307cd1aSmrg} 4915307cd1aSmrg 4925307cd1aSmrg/* 4935307cd1aSmrg * Use this entrypoint for the VT100 window. 4945307cd1aSmrg */ 4954419d26bSmrgvoid 4964419d26bSmrgCursorRestore(XtermWidget xw) 4974419d26bSmrg{ 4984419d26bSmrg TScreen *screen = TScreenOf(xw); 4995307cd1aSmrg CursorRestoreFlags(xw, &screen->sc[screen->whichBuf], DECSC_FLAGS); 5004419d26bSmrg} 5014419d26bSmrg 502d522f475Smrg/* 503d522f475Smrg * Move the cursor to the first column of the n-th next line. 504d522f475Smrg */ 505d522f475Smrgvoid 5060bd37d32SmrgCursorNextLine(XtermWidget xw, int count) 507d522f475Smrg{ 5080bd37d32Smrg TScreen *screen = TScreenOf(xw); 5090bd37d32Smrg 510d522f475Smrg CursorDown(screen, count < 1 ? 1 : count); 5110bd37d32Smrg CarriageReturn(xw); 512d522f475Smrg} 513d522f475Smrg 514d522f475Smrg/* 515d522f475Smrg * Move the cursor to the first column of the n-th previous line. 516d522f475Smrg */ 517d522f475Smrgvoid 5180bd37d32SmrgCursorPrevLine(XtermWidget xw, int count) 519d522f475Smrg{ 5200bd37d32Smrg TScreen *screen = TScreenOf(xw); 5210bd37d32Smrg 522d522f475Smrg CursorUp(screen, count < 1 ? 1 : count); 5230bd37d32Smrg CarriageReturn(xw); 524d522f475Smrg} 525d522f475Smrg 5260bd37d32Smrg/* 5270bd37d32Smrg * Return col/row values which can be passed to CursorSet() preserving the 5280bd37d32Smrg * current col/row, e.g., accounting for DECOM. 5290bd37d32Smrg */ 5300bd37d32Smrgint 5310bd37d32SmrgCursorCol(XtermWidget xw) 5320bd37d32Smrg{ 5330bd37d32Smrg TScreen *screen = TScreenOf(xw); 5340bd37d32Smrg int result = screen->cur_col; 5350bd37d32Smrg if (xw->flags & ORIGIN) { 5360bd37d32Smrg result -= ScrnLeftMargin(xw); 5370bd37d32Smrg if (result < 0) 5380bd37d32Smrg result = 0; 5390bd37d32Smrg } 5400bd37d32Smrg return result; 5410bd37d32Smrg} 5420bd37d32Smrg 5430bd37d32Smrgint 5440bd37d32SmrgCursorRow(XtermWidget xw) 5450bd37d32Smrg{ 5460bd37d32Smrg TScreen *screen = TScreenOf(xw); 5470bd37d32Smrg int result = screen->cur_row; 5480bd37d32Smrg if (xw->flags & ORIGIN) { 5490bd37d32Smrg result -= screen->top_marg; 5500bd37d32Smrg if (result < 0) 5510bd37d32Smrg result = 0; 5520bd37d32Smrg } 5530bd37d32Smrg return result; 5540bd37d32Smrg} 5550bd37d32Smrg 556d522f475Smrg#if OPT_TRACE 557d522f475Smrgint 5582e4f8982Smrgset_cur_row(TScreen *screen, int value) 559d522f475Smrg{ 5604419d26bSmrg TRACE(("set_cur_row %d vs %d\n", value, screen ? LastRowNumber(screen) : -1)); 561956cc18dSsnj 5625104ee6eSmrg assert(screen != NULL); 563d522f475Smrg assert(value >= 0); 5644419d26bSmrg assert(value <= LastRowNumber(screen)); 5654419d26bSmrg if_STATUS_LINE(screen, { 5664419d26bSmrg value = LastRowNumber(screen); 5674419d26bSmrg }); 568d522f475Smrg screen->cur_row = value; 569d522f475Smrg return value; 570d522f475Smrg} 571d522f475Smrg 572d522f475Smrgint 5732e4f8982Smrgset_cur_col(TScreen *screen, int value) 574d522f475Smrg{ 575956cc18dSsnj TRACE(("set_cur_col %d vs %d\n", value, screen ? screen->max_col : -1)); 576956cc18dSsnj 5775104ee6eSmrg assert(screen != NULL); 578d522f475Smrg assert(value >= 0); 579d522f475Smrg assert(value <= screen->max_col); 580d522f475Smrg screen->cur_col = value; 581d522f475Smrg return value; 582d522f475Smrg} 583d522f475Smrg#endif /* OPT_TRACE */ 5844419d26bSmrg/* 5854419d26bSmrg * vile:cmode fk=utf-8 5864419d26bSmrg */ 587