2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
9 static char sccsid
[] = "$Id: util.c,v 8.32 1993/12/10 16:30:09 bostic Exp $ (Berkeley) $Date: 1993/12/10 16:30:09 $";
12 #include <sys/types.h>
13 #include <sys/ioctl.h>
36 msgq(SCR
*sp
, enum msgtype mt
, const char *fmt
, ...)
38 msgq(sp
, mt
, fmt
, va_alist
)
55 * It's possible to enter msg when there's no screen to hold
56 * the message. Always check sp before using it, and, if it's
57 * NULL, use __global_list.
61 if (sp
!= NULL
&& !O_ISSET(sp
, O_VERBOSE
)) {
62 F_SET(sp
, S_BELLSCHED
);
68 if (sp
!= NULL
&& !O_ISSET(sp
, O_VERBOSE
))
73 if (F_ISSET(sp
, S_EXSILENT
))
83 /* Length is the min length of the message or the buffer. */
85 if (sp
->if_name
!= NULL
)
86 len
= snprintf(msgbuf
, sizeof(msgbuf
),
87 "Error: %s, %d: %s%s%s.", sp
->if_name
, sp
->if_lno
,
88 fmt
== NULL
? "" : fmt
, fmt
== NULL
? "" : ": ",
91 len
= snprintf(msgbuf
, sizeof(msgbuf
),
93 fmt
== NULL
? "" : fmt
, fmt
== NULL
? "" : ": ",
96 len
= sp
->if_name
== NULL
? 0 : snprintf(msgbuf
, sizeof(msgbuf
),
97 "%s, %d: ", sp
->if_name
, sp
->if_lno
);
98 len
+= vsnprintf(msgbuf
+ len
, sizeof(msgbuf
) - len
, fmt
, ap
);
102 * If len >= the size, some characters were discarded.
103 * Ignore trailing nul.
105 if (len
>= sizeof(msgbuf
))
106 len
= sizeof(msgbuf
) - 1;
108 msg_app(__global_list
, sp
, mt
== M_ERR
? 1 : 0, msgbuf
, len
);
113 * Append a message into the queue. This can fail, but there's
114 * nothing we can do if it does.
117 msg_app(gp
, sp
, inv_video
, p
, len
)
124 static int reenter
; /* STATIC: Re-entrancy check. */
128 * It's possible to reenter msg when it allocates space.
129 * We're probably dead anyway, but no reason to drop core.
136 * Find an empty structure, or allocate a new one. Use the
137 * screen structure if possible, otherwise the global one.
140 if ((mp
= sp
->msgq
.lh_first
) == NULL
) {
141 CALLOC(sp
, mp
, MSG
*, 1, sizeof(MSG
));
144 LIST_INSERT_HEAD(&sp
->msgq
, mp
, q
);
147 } else if ((mp
= gp
->msgq
.lh_first
) == NULL
) {
148 CALLOC(sp
, mp
, MSG
*, 1, sizeof(MSG
));
151 LIST_INSERT_HEAD(&gp
->msgq
, mp
, q
);
154 while (!F_ISSET(mp
, M_EMPTY
) && mp
->q
.le_next
!= NULL
)
156 if (!F_ISSET(mp
, M_EMPTY
)) {
157 CALLOC(sp
, nmp
, MSG
*, 1, sizeof(MSG
));
160 LIST_INSERT_AFTER(mp
, nmp
, q
);
164 /* Get enough memory for the message. */
165 store
: if (len
> mp
->blen
&& binc(sp
, &mp
->mbuf
, &mp
->blen
, len
))
168 /* Store the message. */
169 memmove(mp
->mbuf
, p
, len
);
171 mp
->flags
= inv_video
? M_INV_VIDEO
: 0;
178 * Report on the lines that changed.
181 * Historic vi documentation (USD:15-8) claimed that "The editor will also
182 * always tell you when a change you make affects text which you cannot see."
183 * This isn't true -- edit a large file and do "100d|1". We don't implement
184 * this semantic as it would require that we track each line that changes
185 * during a command instead of just keeping count.
188 msg_rpt(sp
, is_message
)
192 static const char *const action
[] = {
193 "added", "changed", "copied", "deleted", "joined", "moved",
194 "put", "left shifted", "right shifted", "yanked", NULL
,
200 const char *const *ap
;
201 char *bp
, *p
, number
[40];
203 if (F_ISSET(sp
, S_EXSILENT
))
206 if ((rval
= O_VAL(sp
, O_REPORT
)) == 0)
209 GET_SPACE_RET(sp
, bp
, blen
, 512);
213 for (ap
= action
, cnt
= 0, first
= 1; *ap
!= NULL
; ++ap
, ++cnt
)
214 if (sp
->rptlines
[cnt
] != 0) {
215 total
+= sp
->rptlines
[cnt
];
216 len
= snprintf(number
, sizeof(number
),
217 "%s%lu line%s %s", first
? "" : "; ",
219 sp
->rptlines
[cnt
] > 1 ? "s" : "", *ap
);
220 memmove(p
, number
, len
);
226 * If nothing to report, return. Note that the number of lines
227 * must be > than the user's value, not >=. This is historic
228 * practice and means that users cannot report on single line
235 msgq(sp
, M_INFO
, "%s", bp
);
237 ex_printf(EXCOOKIE
, "%s\n", bp
);
240 FREE_SPACE(sp
, bp
, blen
);
242 /* Clear after each report. */
243 norpt
: memset(sp
->rptlines
, 0, sizeof(sp
->rptlines
));
249 * Increase the size of a buffer.
252 binc(sp
, argp
, bsizep
, min
)
253 SCR
*sp
; /* MAY BE NULL */
260 /* If already larger than the minimum, just return. */
262 if (min
&& csize
>= min
)
265 csize
+= MAX(min
, 256);
266 bpp
= *(char **)argp
;
268 /* For non-ANSI C realloc implementations. */
270 bpp
= malloc(csize
* sizeof(CHAR_T
));
272 bpp
= realloc(bpp
, csize
* sizeof(CHAR_T
));
274 msgq(sp
, M_SYSERR
, NULL
);
278 *(char **)argp
= bpp
;
285 * Set the column number of the first non-blank character
286 * including or after the starting column. On error, set
287 * the column to 0, it's safest.
290 nonblank(sp
, ep
, lno
, cnop
)
297 size_t cnt
, len
, off
;
304 if ((p
= file_gline(sp
, ep
, lno
, &len
)) == NULL
) {
305 if (file_lline(sp
, ep
, &lno
))
309 GETLINE_ERR(sp
, lno
);
313 /* Set the offset. */
314 if (len
== 0 || off
>= len
)
317 for (cnt
= off
, p
= &p
[off
],
318 len
-= off
; len
&& isblank(*p
); ++cnt
, ++p
, --len
);
320 /* Set the return. */
321 *cnop
= len
? cnt
: cnt
- 1;
327 * Return tail of a path.
335 if ((p
= strrchr(path
, '/')) == NULL
)
342 * Set the window size, the row may be provided as an argument.
345 set_window_size(sp
, set_row
, ign_env
)
357 * Get the screen rows and columns. If the values are wrong, it's
358 * not a big deal -- as soon as the user sets them explicitly the
359 * environment will be set and the screen package will use the new
365 if (ioctl(STDERR_FILENO
, TIOCGWINSZ
, &win
) != -1) {
370 /* If TIOCGWINSZ failed, or had entries of 0, try termcap. */
371 if (row
== 0 || col
== 0) {
373 if (F_ISSET(&sp
->opts
[O_TERM
], OPT_SET
))
374 s
= O_STR(sp
, O_TERM
);
377 if (s
!= NULL
&& tgetent(buf
, s
) == 1) {
384 /* If nothing else, well, it's probably a VT100. */
391 * POSIX 1003.2 requires the environment to override, however,
392 * if we're here because of a signal, we don't want to use the
396 if ((s
= getenv("ROWS")) != NULL
)
397 row
= strtol(s
, NULL
, 10);
398 if ((s
= getenv("COLUMNS")) != NULL
)
399 col
= strtol(s
, NULL
, 10);
402 /* But, if we got an argument for the rows, use it. */
413 * Tell the options code that the screen size has changed.
414 * Since the user didn't do the set, clear the set bits.
416 user_set
= F_ISSET(&sp
->opts
[O_LINES
], OPT_SET
);
417 a
.len
= snprintf(buf
, sizeof(buf
), "lines=%u", row
);
418 if (opts_set(sp
, argv
))
421 F_CLR(&sp
->opts
[O_LINES
], OPT_SET
);
422 user_set
= F_ISSET(&sp
->opts
[O_COLUMNS
], OPT_SET
);
423 a
.len
= snprintf(buf
, sizeof(buf
), "columns=%u", col
);
424 if (opts_set(sp
, argv
))
427 F_CLR(&sp
->opts
[O_COLUMNS
], OPT_SET
);
433 * Set the alternate file name.
435 * Swap the alternate file name. It's a routine because I wanted some place
436 * to hang this comment. The alternate file name (normally referenced using
437 * the special character '#' during file expansion) is set by many
438 * operations. In the historic vi, the commands "ex", and "edit" obviously
439 * set the alternate file name because they switched the underlying file.
440 * Less obviously, the "read", "file", "write" and "wq" commands set it as
441 * well. In this implementation, some new commands have been added to the
442 * list. Where it gets interesting is that the alternate file name is set
443 * multiple times by some commands. If an edit attempt fails (for whatever
444 * reason, like the current file is modified but as yet unwritten), it is
445 * set to the file name that the user was unable to edit. If the edit
446 * succeeds, it is set to the last file name that was edited. Good fun.
448 * If the user edits a temporary file, there are time when there isn't an
449 * alternative file name. A name argument of NULL turns it off.
452 set_alt_name(sp
, name
)
456 if (sp
->alt_name
!= NULL
)
457 FREE(sp
->alt_name
, strlen(sp
->alt_name
) + 1);
460 else if ((sp
->alt_name
= strdup(name
)) == NULL
)
461 msgq(sp
, M_SYSERR
, NULL
);
466 * Return the baud rate using the standard defines.
474 switch (v
= cfgetospeed(&sp
->gp
->original_termios
)) {
499 case B0
: /* Hangup -- ignore. */
508 * EXTA and EXTB aren't required by POSIX 1003.1, and
509 * are almost certainly the same as some of the above
510 * values, so they can't be part of the case statement.
520 msgq(sp
, M_ERR
, "Unknown terminal baud rate %u.\n", v
);
527 * Strdup for wide character strings with an associated length.
530 v_strdup(sp
, str
, len
)
537 MALLOC(sp
, copy
, CHAR_T
*, len
);
540 memmove(copy
, str
, len
* sizeof(CHAR_T
));