1/* $XTermId: tabs.c,v 1.47 2019/11/13 23:19:01 tom Exp $ */ 2 3/* 4 * Copyright 2000-2018,2019 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 * 33 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 34 * 35 * All Rights Reserved 36 * 37 * Permission to use, copy, modify, and distribute this software and its 38 * documentation for any purpose and without fee is hereby granted, 39 * provided that the above copyright notice appear in all copies and that 40 * both that copyright notice and this permission notice appear in 41 * supporting documentation, and that the name of Digital Equipment 42 * Corporation not be used in advertising or publicity pertaining to 43 * distribution of the software without specific, written prior permission. 44 * 45 * 46 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 47 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 48 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 49 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 50 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 51 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 52 * SOFTWARE. 53 */ 54 55/* tabs.c */ 56 57#include <xterm.h> 58#include <data.h> 59 60#define TAB_INDEX(n) ((n) >> TAB_BITS_SHIFT) 61#define TAB_MASK(n) (1U << ((n) & (TAB_BITS_WIDTH-1))) 62 63#define SET_TAB(tabs,n) UIntSet(tabs[TAB_INDEX(n)], TAB_MASK(n)) 64#define CLR_TAB(tabs,n) UIntClr(tabs[TAB_INDEX(n)], TAB_MASK(n)) 65#define TST_TAB(tabs,n) (tabs[TAB_INDEX(n)] & (unsigned) TAB_MASK(n)) 66 67/* 68 * places tabstops at only every 8 columns 69 */ 70void 71TabReset(Tabs tabs) 72{ 73 int i; 74 75 TabZonk(tabs); 76 77 for (i = 0; i < MAX_TABS; i += 8) 78 TabSet(tabs, i); 79} 80 81/* 82 * places a tabstop at col 83 */ 84void 85TabSet(Tabs tabs, int col) 86{ 87 if (OkTAB(col)) { 88 SET_TAB(tabs, col); 89 } 90} 91 92/* 93 * clears a tabstop at col 94 */ 95void 96TabClear(Tabs tabs, int col) 97{ 98 if (OkTAB(col)) { 99 CLR_TAB(tabs, col); 100 } 101} 102 103/* 104 * returns the column of the next tabstop 105 * (or MAX_TABS - 1 if there are no more). 106 * A tabstop at col is ignored. 107 */ 108static int 109TabNext(XtermWidget xw, Tabs tabs, int col) 110{ 111 TScreen *screen = TScreenOf(xw); 112 113 if (screen->curses && screen->do_wrap && (xw->flags & WRAPAROUND)) { 114 xtermIndex(xw, 1); 115 set_cur_col(screen, 0); 116 col = 0; 117 ResetWrap(screen); 118 } 119 for (++col; col < MAX_TABS; ++col) 120 if (TST_TAB(tabs, col)) 121 return (col); 122 123 return (MAX_TABS - 1); 124} 125 126/* 127 * returns the column of the previous tabstop 128 * (or 0 if there are no more). 129 * A tabstop at col is ignored. 130 */ 131static int 132TabPrev(Tabs tabs, int col) 133{ 134 for (--col; col >= 0; --col) 135 if ((col < MAX_TABS) && TST_TAB(tabs, col)) 136 return (col); 137 138 return (0); 139} 140 141/* 142 * Tab to the next stop, returning true if the cursor moved 143 */ 144Bool 145TabToNextStop(XtermWidget xw) 146{ 147 TScreen *screen = TScreenOf(xw); 148 int saved_column = screen->cur_col; 149 int next = TabNext(xw, xw->tabs, screen->cur_col); 150 int max = LineMaxCol(screen, getLineData(screen, screen->cur_row)); 151 152 if (IsLeftRightMode(xw)) 153 max = TScreenOf(xw)->rgt_marg; 154 if (next > max) 155 next = max; 156 set_cur_col(screen, next); 157 158 return (screen->cur_col > saved_column); 159} 160 161/* 162 * Tab to the previous stop, returning true if the cursor moved 163 */ 164Bool 165TabToPrevStop(XtermWidget xw) 166{ 167 TScreen *screen = TScreenOf(xw); 168 int saved_column = screen->cur_col; 169 int next_column = TabPrev(xw->tabs, screen->cur_col); 170 171 if (xw->flags & ORIGIN) { 172 int left = ScrnLeftMargin(xw); 173 if (next_column < left) 174 next_column = left; 175 } 176 177 set_cur_col(screen, next_column); 178 179 return (screen->cur_col < saved_column); 180} 181 182/* 183 * clears all tabs 184 */ 185void 186TabZonk(Tabs tabs) 187{ 188 memset(tabs, 0, sizeof(*tabs) * TAB_ARRAY_SIZE); 189} 190 191/* 192 * Check if a tab is set for the given column 193 */ 194Bool 195TabIsSet(Tabs tabs, int col) 196{ 197 return TST_TAB(tabs, col) ? True : False; 198} 199