-> 1.03
[nvi.git] / vi / vs_relative.c
blobfaef8c4224122400a452078857677b6f035c0c48
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.7 1993/12/29 16:27:20 bostic Exp $ (Berkeley) $Date: 1993/12/29 16:27:20 $";
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 /* Discard logical lines. */
102 cname = sp->gp->cname;
103 listset = O_ISSET(sp, O_LIST);
104 for (scno = 0, p = lp, llen = len; --off;) {
105 for (; len && scno < sp->cols; --len)
106 SCNO_INCREMENT;
107 if (len == 0)
108 return (llen - 1);
109 scno -= sp->cols;
112 /* Step through the line until reach the right character. */
113 while (len--) {
114 SCNO_INCREMENT;
115 if (scno >= sp->rcm) {
116 /* Get the offset of this character. */
117 len = p - lp;
120 * May be the next character, not this one,
121 * so check to see if we've gone too far.
123 if (scno == sp->rcm)
124 return (len < llen - 1 ? len : llen - 1);
125 /* It's this character. */
126 return (len - 1);
129 /* No such character; return start of last character. */
130 return (llen - 1);
134 * svi_chposition --
135 * Return the physical column from the line that will display a
136 * character closest to the specified column.
138 size_t
139 svi_chposition(sp, ep, lno, cno)
140 SCR *sp;
141 EXF *ep;
142 recno_t lno;
143 size_t cno;
145 CHNAME const *cname;
146 size_t len, llen, scno;
147 int ch, listset;
148 char *lp, *p;
150 /* Need the line to go any further. */
151 if ((lp = file_gline(sp, ep, lno, &llen)) == NULL)
152 return (0);
154 /* Empty lines are easy. */
155 if (llen == 0)
156 return (0);
158 /* Step through the line until reach the right character. */
159 cname = sp->gp->cname;
160 listset = O_ISSET(sp, O_LIST);
161 for (scno = 0, len = llen, p = lp; len--;) {
162 SCNO_INCREMENT;
163 if (scno >= cno) {
164 /* Get the offset of this character. */
165 len = p - lp;
168 * May be the next character, not this one,
169 * so check to see if we've gone too far.
171 if (scno == cno)
172 return (len < llen - 1 ? len : llen - 1);
173 /* It's this character. */
174 return (len - 1);
177 /* No such character; return start of last character. */
178 return (llen - 1);