"Fossies" - the Fresh Open Source Software Archive 
Member "xterm-379/cursor.c" (23 Sep 2022, 13933 Bytes) of package /linux/misc/xterm-379.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "cursor.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
372_vs_373.
1 /* $XTermId: cursor.c,v 1.83 2022/09/23 08:13:43 tom Exp $ */
2
3 /*
4 * Copyright 2002-2021,2022 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 */
67 void
68 CursorSet(TScreen *screen, int row, int col, unsigned flags)
69 {
70 int use_row = row;
71 int use_col = col;
72 int max_col = screen->max_col;
73 int max_row = screen->max_row;
74
75 if (flags & ORIGIN) {
76 use_col += screen->lft_marg;
77 max_col = screen->rgt_marg;
78 }
79 use_col = (use_col < 0 ? 0 : use_col);
80 set_cur_col(screen, (use_col <= max_col ? use_col : max_col));
81
82 if (flags & ORIGIN) {
83 use_row += screen->top_marg;
84 max_row = screen->bot_marg;
85 }
86 use_row = (use_row < 0 ? 0 : use_row);
87 set_cur_row(screen, (use_row <= max_row ? use_row : max_row));
88
89 ResetWrap(screen);
90
91 TRACE(("CursorSet(%d,%d) margins V[%d..%d] H[%d..%d] -> %d,%d %s\n",
92 row, col,
93 screen->top_marg,
94 screen->bot_marg,
95 screen->lft_marg,
96 screen->rgt_marg,
97 screen->cur_row,
98 screen->cur_col,
99 ((flags & ORIGIN) ? "origin" : "normal")));
100 }
101
102 /*
103 * moves the cursor left n, no wrap around
104 */
105 void
106 CursorBack(XtermWidget xw, int n)
107 {
108 #define WRAP_MASK (REVERSEWRAP | WRAPAROUND)
109 TScreen *screen = TScreenOf(xw);
110 int rev;
111 int left = ScrnLeftMargin(xw);
112 int before = screen->cur_col;
113
114 if ((rev = ((xw->flags & WRAP_MASK) == WRAP_MASK)) != 0
115 && screen->do_wrap) {
116 n--;
117 }
118
119 /* if the cursor is already before the left-margin, we have to let it go */
120 if (before < left)
121 left = 0;
122
123 if ((screen->cur_col -= n) < left) {
124 if (rev) {
125 int in_row = ScrnRightMargin(xw) - left + 1;
126 int offset = (in_row * screen->cur_row) + screen->cur_col - left;
127 if ((before == left) &&
128 ScrnIsColInMargins(screen, before) &&
129 ScrnIsRowInMargins(screen, screen->cur_row) &&
130 screen->cur_row == screen->top_marg) {
131 offset = (screen->bot_marg + 1) * in_row - 1;
132 } else if (offset < 0) {
133 int length = in_row * MaxRows(screen);
134 offset += ((-offset) / length + 1) * length;
135 }
136 set_cur_row(screen, (offset / in_row));
137 set_cur_col(screen, (offset % in_row) + left);
138 do_xevents(xw);
139 } else {
140 set_cur_col(screen, left);
141 }
142 }
143 ResetWrap(screen);
144 }
145
146 /*
147 * moves the cursor forward n, no wraparound
148 */
149 void
150 CursorForward(XtermWidget xw, int n)
151 {
152 TScreen *screen = TScreenOf(xw);
153 #if OPT_DEC_CHRSET
154 LineData *ld = getLineData(screen, screen->cur_row);
155 #endif
156 int next = screen->cur_col + n;
157 int max;
158
159 if (IsLeftRightMode(xw)) {
160 max = screen->rgt_marg;
161 if (screen->cur_col > max)
162 max = screen->max_col;
163 } else {
164 max = LineMaxCol(screen, ld);
165 }
166
167 if (next > max)
168 next = max;
169
170 set_cur_col(screen, next);
171 ResetWrap(screen);
172 }
173
174 /*
175 * moves the cursor down n, no scrolling.
176 * Won't pass bottom margin or bottom of screen.
177 */
178 void
179 CursorDown(TScreen *screen, int n)
180 {
181 int max;
182 int next = screen->cur_row + n;
183
184 max = (screen->cur_row > screen->bot_marg ?
185 screen->max_row : screen->bot_marg);
186 if (next > max)
187 next = max;
188 if (next > screen->max_row)
189 next = screen->max_row;
190
191 set_cur_row(screen, next);
192 ResetWrap(screen);
193 }
194
195 /*
196 * moves the cursor up n, no linestarving.
197 * Won't pass top margin or top of screen.
198 */
199 void
200 CursorUp(TScreen *screen, int n)
201 {
202 int min;
203 int next = screen->cur_row - n;
204
205 min = ((screen->cur_row < screen->top_marg)
206 ? 0
207 : screen->top_marg);
208 if (next < min)
209 next = min;
210 if (next < 0)
211 next = 0;
212
213 set_cur_row(screen, next);
214 ResetWrap(screen);
215 }
216
217 /*
218 * Moves cursor down amount lines, scrolls if necessary.
219 * Won't leave scrolling region. No carriage return.
220 */
221 void
222 xtermIndex(XtermWidget xw, int amount)
223 {
224 TScreen *screen = TScreenOf(xw);
225
226 /*
227 * indexing when below scrolling region is cursor down.
228 * if cursor high enough, no scrolling necessary.
229 */
230 if (screen->cur_row > screen->bot_marg
231 || screen->cur_row + amount <= screen->bot_marg
232 || (IsLeftRightMode(xw)
233 && !ScrnIsColInMargins(screen, screen->cur_col))) {
234 CursorDown(screen, amount);
235 } else {
236 int j;
237 CursorDown(screen, j = screen->bot_marg - screen->cur_row);
238 xtermScroll(xw, amount - j);
239 }
240 }
241
242 /*
243 * Moves cursor up amount lines, reverse scrolls if necessary.
244 * Won't leave scrolling region. No carriage return.
245 */
246 void
247 RevIndex(XtermWidget xw, int amount)
248 {
249 TScreen *screen = TScreenOf(xw);
250
251 /*
252 * reverse indexing when above scrolling region is cursor up.
253 * if cursor low enough, no reverse indexing needed
254 */
255 if (screen->cur_row < screen->top_marg
256 || screen->cur_row - amount >= screen->top_marg
257 || (IsLeftRightMode(xw)
258 && !ScrnIsColInMargins(screen, screen->cur_col))) {
259 CursorUp(screen, amount);
260 } else {
261 RevScroll(xw, amount - (screen->cur_row - screen->top_marg));
262 CursorUp(screen, screen->cur_row - screen->top_marg);
263 }
264 }
265
266 /*
267 * Moves Cursor To First Column In Line
268 * (Note: xterm doesn't implement SLH, SLL which would affect use of this)
269 */
270 void
271 CarriageReturn(XtermWidget xw)
272 {
273 TScreen *screen = TScreenOf(xw);
274 int left = ScrnLeftMargin(xw);
275 int col;
276
277 if (xw->flags & ORIGIN) {
278 col = left;
279 } else if (screen->cur_col >= left) {
280 col = left;
281 } else {
282 /*
283 * If origin-mode is not active, it is possible to use cursor
284 * addressing outside the margins. In that case we will go to the
285 * first column rather than following the margin.
286 */
287 col = 0;
288 }
289
290 set_cur_col(screen, col);
291 ResetWrap(screen);
292 do_xevents(xw);
293 }
294
295 /*
296 * When resizing the window, if we're showing the alternate screen, we still
297 * have to adjust the saved cursor from the normal screen to account for
298 * shifting of the saved-line region in/out of the viewable window.
299 */
300 void
301 AdjustSavedCursor(XtermWidget xw, int adjust)
302 {
303 TScreen *screen = TScreenOf(xw);
304
305 if (screen->whichBuf) {
306 SavedCursor *sc = &screen->sc[0];
307
308 if (adjust > 0) {
309 TRACE(("AdjustSavedCursor %d -> %d\n", sc->row, sc->row - adjust));
310 sc->row += adjust;
311 }
312 }
313 }
314
315 /*
316 * Save Cursor and Attributes
317 */
318 void
319 CursorSave2(XtermWidget xw, SavedCursor * sc)
320 {
321 TScreen *screen = TScreenOf(xw);
322
323 sc->saved = True;
324 sc->row = screen->cur_row;
325 sc->col = screen->cur_col;
326 sc->flags = xw->flags;
327 sc->curgl = screen->curgl;
328 sc->curgr = screen->curgr;
329 sc->wrap_flag = screen->do_wrap;
330 #if OPT_ISO_COLORS
331 sc->cur_foreground = xw->cur_foreground;
332 sc->cur_background = xw->cur_background;
333 sc->sgr_foreground = xw->sgr_foreground;
334 sc->sgr_38_xcolors = xw->sgr_38_xcolors;
335 #endif
336 saveCharsets(screen, sc->gsets);
337 }
338
339 void
340 CursorSave(XtermWidget xw)
341 {
342 TScreen *screen = TScreenOf(xw);
343 CursorSave2(xw, &screen->sc[screen->whichBuf]);
344 }
345
346 /*
347 * We save/restore all visible attributes, plus wrapping, origin mode, and the
348 * selective erase attribute.
349 *
350 * This is documented, but some of the documentation is incorrect.
351 *
352 * Page 270 of the VT420 manual (2nd edition) says that DECSC saves these
353 * items:
354 *
355 * Cursor position
356 * * Character attributes set by the SGR command
357 * * Character sets (G0, G1, G2, or G3) currently in GL and GR
358 * * Wrap flag (autowrap or no autowrap)
359 * * State of origin mode (DECOM)
360 * * Selective erase attribute
361 * * Any single shift 2 (SS2) or single shift 3 (SS3) functions sent
362 *
363 * The VT520 manual has the same information (page 5-120).
364 *
365 * However, DEC 070 (29-June-1990), pages 5-186 to 5-191, describes
366 * save/restore operations, but makes no mention of "wrap".
367 *
368 * Mattias EngdegÄrd, who has investigated wrapping behavior of different
369 * terminals,
370 *
371 * https://github.com/mattiase/wraptest
372 *
373 * states
374 * The LCF is saved/restored by the Save/Restore Cursor (DECSC/DECRC)
375 * control sequences. The DECAWM flag is not included in the state
376 * managed by these operations.
377 *
378 * DEC 070 does mention the ANSI color text extension saying that it, too, is
379 * saved/restored.
380 */
381 #define ALL_FLAGS (IFlags)(~0)
382 #define DECSC_FLAGS (ATTRIBUTES|ORIGIN|PROTECTED)
383
384 /*
385 * Restore Cursor and Attributes
386 */
387 static void
388 CursorRestoreFlags(XtermWidget xw, SavedCursor * sc, IFlags our_flags)
389 {
390 TScreen *screen = TScreenOf(xw);
391
392 /* Restore the character sets, unless we never did a save-cursor op.
393 * In that case, we'll reset the character sets.
394 */
395 if (sc->saved) {
396 restoreCharsets(screen, sc->gsets);
397 screen->curgl = sc->curgl;
398 screen->curgr = sc->curgr;
399 } else {
400 resetCharsets(screen);
401 }
402
403 UIntClr(xw->flags, our_flags);
404 UIntSet(xw->flags, sc->flags & our_flags);
405 if ((xw->flags & ORIGIN)) {
406 CursorSet(screen,
407 sc->row - screen->top_marg,
408 ((xw->flags & LEFT_RIGHT)
409 ? sc->col - screen->lft_marg
410 : sc->col),
411 xw->flags);
412 } else {
413 CursorSet(screen, sc->row, sc->col, xw->flags);
414 }
415 screen->do_wrap = sc->wrap_flag; /* after CursorSet/ResetWrap */
416
417 #if OPT_ISO_COLORS
418 xw->sgr_foreground = sc->sgr_foreground;
419 xw->sgr_38_xcolors = sc->sgr_38_xcolors;
420 SGR_Foreground(xw, (xw->flags & FG_COLOR) ? sc->cur_foreground : -1);
421 SGR_Background(xw, (xw->flags & BG_COLOR) ? sc->cur_background : -1);
422 #endif
423 }
424
425 /*
426 * Use this entrypoint for the status-line.
427 */
428 void
429 CursorRestore2(XtermWidget xw, SavedCursor * sc)
430 {
431 CursorRestoreFlags(xw, sc, ALL_FLAGS);
432 }
433
434 /*
435 * Use this entrypoint for the VT100 window.
436 */
437 void
438 CursorRestore(XtermWidget xw)
439 {
440 TScreen *screen = TScreenOf(xw);
441 CursorRestoreFlags(xw, &screen->sc[screen->whichBuf], DECSC_FLAGS);
442 }
443
444 /*
445 * Move the cursor to the first column of the n-th next line.
446 */
447 void
448 CursorNextLine(XtermWidget xw, int count)
449 {
450 TScreen *screen = TScreenOf(xw);
451
452 CursorDown(screen, count < 1 ? 1 : count);
453 CarriageReturn(xw);
454 do_xevents(xw);
455 }
456
457 /*
458 * Move the cursor to the first column of the n-th previous line.
459 */
460 void
461 CursorPrevLine(XtermWidget xw, int count)
462 {
463 TScreen *screen = TScreenOf(xw);
464
465 CursorUp(screen, count < 1 ? 1 : count);
466 CarriageReturn(xw);
467 do_xevents(xw);
468 }
469
470 /*
471 * Return col/row values which can be passed to CursorSet() preserving the
472 * current col/row, e.g., accounting for DECOM.
473 */
474 int
475 CursorCol(XtermWidget xw)
476 {
477 TScreen *screen = TScreenOf(xw);
478 int result = screen->cur_col;
479 if (xw->flags & ORIGIN) {
480 result -= ScrnLeftMargin(xw);
481 if (result < 0)
482 result = 0;
483 }
484 return result;
485 }
486
487 int
488 CursorRow(XtermWidget xw)
489 {
490 TScreen *screen = TScreenOf(xw);
491 int result = screen->cur_row;
492 if (xw->flags & ORIGIN) {
493 result -= screen->top_marg;
494 if (result < 0)
495 result = 0;
496 }
497 return result;
498 }
499
500 #if OPT_TRACE
501 int
502 set_cur_row(TScreen *screen, int value)
503 {
504 TRACE(("set_cur_row %d vs %d\n", value, screen ? LastRowNumber(screen) : -1));
505
506 assert(screen != 0);
507 assert(value >= 0);
508 assert(value <= LastRowNumber(screen));
509 if_STATUS_LINE(screen, {
510 value = LastRowNumber(screen);
511 });
512 screen->cur_row = value;
513 return value;
514 }
515
516 int
517 set_cur_col(TScreen *screen, int value)
518 {
519 TRACE(("set_cur_col %d vs %d\n", value, screen ? screen->max_col : -1));
520
521 assert(screen != 0);
522 assert(value >= 0);
523 assert(value <= screen->max_col);
524 screen->cur_col = value;
525 return value;
526 }
527 #endif /* OPT_TRACE */
528 /*
529 * vile:cmode fk=utf-8
530 */