-
Notifications
You must be signed in to change notification settings - Fork 2
/
dline.c
317 lines (237 loc) · 6.64 KB
/
dline.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
/*
* Library of display line routines.
*
* Robert W. Baldwin, December 1984.
*/
#include <stdio.h>
#include "window.h"
#include "specs.h"
/* After clrdline is called the routines assume that there is
* a null character terminating the string at index w->wwidth.
* That is, the length of the display string is always equal
* the the (fixed) width of the line.
* The dl_length field behaves like the apparent string length.
* It is the column location of the last non-blank character.
* That is, an all blank line has a length of zero.
*/
/* Forward declarations */
void dlright(displine *dline);
/* INTERNAL PROCEDURES */
/* Set the range of positions between firstcol and lastcol (inclusive) to
* the given string. The string is padded on the right with spaces
* or truncated to make it fill the interval.
*/
void setarange(displine *line, char *str, int firstcol, int lastcol)
{
int i;
line->dl_length = 0;
for (i = firstcol-1 ; i < lastcol ; i++) {
if (*str == 0) break;
if (*str != ' ') line->dl_length = i+1;
line->dl_chars[i] = *str++;
}
for ( ; i < lastcol ; i++) {
line->dl_chars[i] = ' ';
}
line->dl_chars[i] = '\000';
}
/* PUBLIC PROCEDURES */
/* Set the line from column, col, onward to the given string,
* padding with blanks if needed. Note col = 1, set the whole line.
* This cannot be used to initialize a display line. It does not
* set the character preceeding col.
*/
void setnadline(displine *line, char *str, int col)
{
setarange(line, str, col, line->wwidth);
}
/* Blank out all the characters in a displine.
*/
void clrdline(displine *line)
{
line->dl_length = 0;
setarange(line, "", 1, line->wwidth);
}
/* Set the entire displine to the given string, padding with blanks.
* This fills in the null termination, so it can be used to initialize
* a display line.
*/
void setadline(displine *line, char *str)
{
line->dl_length = 0;
setarange(line, str, 1, line->wwidth);
}
/* Set characters in the given range to the string, truncating
* if necessary. Do not pad with blanks, just avoid overflowing
* the range.
*/
void setrange(displine *line, char *str, int firstcol, int lastcol)
{
int i;
int newlength;
newlength = 0;
for (i = firstcol-1 ; i < lastcol ; i++) {
if (*str == 0) return;
if (*str != ' ') newlength = i+1;
line->dl_chars[i] = *str++;
}
if (newlength > line->dl_length) line->dl_length = newlength;
}
/* Starting at column, col, set the characters in the display line, line,
* to the given string, str.
* This differs from setnadline because it does not pad the line with blanks.
* Overflows are avoided by truncation.
* Note that col is a one-based position, not zero-based as strings are.
* This cannot be used to initialize a line, since it does not set the
* characters before column col.
*/
void setndline(displine *line, char *str, int col)
{
setrange(line, str, col, line->wwidth);
}
/* Set the variable part of the line (between min and max_col) to
* the given string. Pad with blanks.
*/
void dlsetvar(displine *line, char *str)
{
setarange(line, str, line->dl_min_col, line->dl_max_col);
}
/* Fill the given buffer from the given range of column positions.
* Trailing blanks are not removed.
*/
void getrange(displine *line, char *buf, int firstcol, int lastcol)
{
int i;
for (i = firstcol-1 ; i < lastcol ; i++) {
*buf++ = line->dl_chars[i];
}
*buf = '\000';
}
/* Fill the given character buffer with a null terminated string
* corresponding to the part of the dline between the min and max
* column positions. Trailing blanks are not removed.
*/
void dlgetvar(displine *line, char *buf)
{
getrange(line, buf, line->dl_min_col, line->dl_max_col);
}
/* EDITING PROCEDURES */
/* Insert the given character at the current cursor position.
* Do nothing if the line would become too long.
* Do nothing if the character is not printable.
* The cursor moves to the right one column, provided it doesn't
* move past dl_max_col.
*/
void dlinsert(displine *line, key k)
{
char restbuf[MAXWIDTH+1]; /* Char from cursor to end. */
char insbuf[2]; /* Char to insert. */
if (line->dl_length >= line->wwidth) return;
if (!printable(k)) return;
getrange(line, restbuf, line->wcur_col, line->wwidth);
insbuf[0] = k;
insbuf[1] = '\000';
setrange(line, insbuf, line->wcur_col, line->wcur_col);
setrange(line, restbuf, line->wcur_col+1, line->wwidth);
dlright(line);
}
/* Delete the character at the current cursor position and
* shuffle down the rest of the line.
* The cursor doesn't move.
* The non-blank length is correctly maintained.
*/
void dldelete(displine *line)
{
char *p;
char linebuf[MAXWIDTH+1]; /* Rebuild whole line here. */
getrange(line, linebuf, 1, line->wcur_col-1);
for (p = linebuf ; *p != '\000' ; p++); /* p pts to end of line. */
getrange(line, p, line->wcur_col+1, line->wwidth);
setadline(line, linebuf);
}
/* Move the cursor right within min and max column.
*/
void dlright(displine *line)
{
if (line->wcur_col+1 <= line->dl_max_col)
line->wcur_col++;
}
/* Move the cursor left within min and max column.
*/
void dlleft(displine *line)
{
if (line->wcur_col-1 >= line->dl_min_col)
line->wcur_col--;
}
/* DISPLAY UPDATING PROCEDURES */
/* Redraw routine for a display line.
*/
int wl_dldraw(displine *dline)
{
int oldcolumn;
oldcolumn = dline->wcur_col;
wl_setcur(dline, 1, 1);
plstring(dline->dl_chars);
wl_setcur(dline, 1, oldcolumn);
return 0;
}
/* Insert a character an redisplay the line.
*/
void wl_dlinsert(displine *line, key k)
{
dlinsert(line, k);
wl_dldraw(line);
}
/* Delete the current character an redisplay the line.
*/
void wl_dlfdel(displine *line)
{
dldelete(line);
wl_dldraw(line);
}
/* Delete the previous character an redisplay the line.
* The cursor moves backwards one position.
*/
void wl_dlbdel(displine *line)
{
if (line->wcur_col == line->dl_min_col) return;
dlleft(line);
dldelete(line);
wl_dldraw(line);
}
/* Move cursor right and update display.
*/
void wl_dlright(displine *line)
{
dlright(line);
wl_rcursor(line);
}
/* Move cursor left and update display.
*/
void wl_dlleft(displine *line)
{
dlleft(line);
wl_rcursor(line);
}
/* Clear the variable part of the display line and update the display.
*/
void wl_dlclr(displine *line)
{
dlsetvar(line, "");
line->wcur_col = line->dl_min_col;
wl_dldraw(line);
}
/* Scan for the first argument place holder, '%',
* position the cursor there, and delete it.
* Do nothing if the line doesn't contain a '%'.
*/
void wl_nxtarg(displine *line)
{
int i;
for (i = line->dl_min_col-1 ; i < line->dl_max_col ; i++) {
if (line->dl_chars[i] != '%') continue;
wl_setcur(line, 1, i+1);
wl_dlfdel(line);
break;
}
}