replace special array lookups with value returned in CH structure
[nvi.git] / vi / vs_relative.c
blobc8445fa955b57fc2b0c2088df07535599aa581de
1 /*-
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: vs_relative.c,v 8.6 1993/11/29 14:15:46 bostic Exp $ (Berkeley) $Date: 1993/11/29 14:15:46 $";
10 #endif /* not lint */
12 #include <sys/types.h>
14 #include <string.h>
16 #include "vi.h"
17 #include "svi_screen.h"
20 * svi_column --
21 * Return the logical column of the cursor.
23 int
24 svi_column(sp, ep, cp)
25 SCR *sp;
26 EXF *ep;
27 size_t *cp;
29 size_t col;
31 col = SVP(sp)->sc_col;
32 if (O_ISSET(sp, O_NUMBER))
33 col -= O_NUMBER_LENGTH;
34 *cp = col;
35 return (0);
39 * svi_relative --
40 * Return the physical column from the line that will display a
41 * character closest to the currently most attractive character
42 * position. If it's not easy, uses the underlying routine that
43 * really figures it out. It's broken into two parts because the
44 * svi_lrelative routine handles "logical" offsets, which nobody
45 * but the screen routines understand.
47 size_t
48 svi_relative(sp, ep, lno)
49 SCR *sp;
50 EXF *ep;
51 recno_t lno;
53 size_t cno;
55 /* First non-blank character. */
56 if (sp->rcmflags == RCM_FNB) {
57 cno = 0;
58 (void)nonblank(sp, ep, lno, &cno);
59 return (cno);
62 /* First character is easy, and common. */
63 if (sp->rcmflags != RCM_LAST && sp->rcm == 0)
64 return (0);
66 return (svi_lrelative(sp, ep, lno, 1));
70 * svi_lrelative --
71 * Return the physical column from the line that will display a
72 * character closest to the currently most attractive character
73 * position. The offset is for the commands that move logical
74 * distances, i.e. if it's a logical scroll the closest physical
75 * distance is based on the logical line, not the physical line.
77 size_t
78 svi_lrelative(sp, ep, lno, off)
79 SCR *sp;
80 EXF *ep;
81 recno_t lno;
82 size_t off;
84 CHNAME const *cname;
85 size_t len, llen, scno;
86 int ch, listset;
87 char *lp, *p;
89 /* Need the line to go any further. */
90 if ((lp = file_gline(sp, ep, lno, &len)) == NULL)
91 return (0);
93 /* Empty lines are easy. */
94 if (len == 0)
95 return (0);
97 /* Last character is easy, and common. */
98 if (sp->rcmflags == RCM_LAST)
99 return (len - 1);
101 /* Set scno to the right initial value. */
102 scno = O_ISSET(sp, O_NUMBER) ? O_NUMBER_LENGTH : 0;
104 /* Discard logical lines. */
105 cname = sp->gp->cname;
106 listset = O_ISSET(sp, O_LIST);
107 for (p = lp, llen = len; --off;) {
108 for (; len && scno < sp->cols; --len)
109 SCNO_INCREMENT;
110 if (len == 0)
111 return (llen - 1);
112 scno -= sp->cols;
115 /* Step through the line until reach the right character. */
116 while (len--) {
117 SCNO_INCREMENT;
118 if (scno >= sp->rcm) {
119 /* Get the offset of this character. */
120 len = p - lp;
123 * May be the next character, not this one,
124 * so check to see if we've gone too far.
126 if (scno == sp->rcm)
127 return (len < llen - 1 ? len : llen - 1);
128 /* It's this character. */
129 return (len - 1);
132 /* No such character; return start of last character. */
133 return (llen - 1);
137 * svi_chposition --
138 * Return the physical column from the line that will display a
139 * character closest to the specified column.
141 size_t
142 svi_chposition(sp, ep, lno, cno)
143 SCR *sp;
144 EXF *ep;
145 recno_t lno;
146 size_t cno;
148 CHNAME const *cname;
149 size_t len, llen, scno;
150 int ch, listset;
151 char *lp, *p;
153 /* Need the line to go any further. */
154 if ((lp = file_gline(sp, ep, lno, &llen)) == NULL)
155 return (0);
157 /* Empty lines are easy. */
158 if (llen == 0)
159 return (0);
161 /* Step through the line until reach the right character. */
162 cname = sp->gp->cname;
163 listset = O_ISSET(sp, O_LIST);
164 for (scno = 0, len = llen, p = lp; len--;) {
165 SCNO_INCREMENT;
166 if (scno >= cno) {
167 /* Get the offset of this character. */
168 len = p - lp;
171 * May be the next character, not this one,
172 * so check to see if we've gone too far.
174 if (scno == cno)
175 return (len < llen - 1 ? len : llen - 1);
176 /* It's this character. */
177 return (len - 1);
180 /* No such character; return start of last character. */
181 return (llen - 1);