1 /*- 2 * Copyright (c) 1991, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static char sccsid[] = "@(#)util.c 8.74 (Berkeley) 8/17/94"; 36 #endif /* not lint */ 37 38 #include <sys/types.h> 39 #include <sys/queue.h> 40 #include <sys/time.h> 41 42 #include <bitstring.h> 43 #include <limits.h> 44 #include <signal.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <termios.h> 49 #include <unistd.h> 50 51 #include "compat.h" 52 #include <curses.h> 53 #include <db.h> 54 #include <regex.h> 55 56 #include "vi.h" 57 58 /* 59 * binc -- 60 * Increase the size of a buffer. 61 */ 62 void * 63 binc(sp, bp, bsizep, min) 64 SCR *sp; /* sp MAY BE NULL!!! */ 65 void *bp; 66 size_t *bsizep, min; 67 { 68 size_t csize; 69 70 /* If already larger than the minimum, just return. */ 71 if (min && *bsizep >= min) 72 return (bp); 73 74 csize = *bsizep + MAX(min, 256); 75 REALLOC(sp, bp, void *, csize); 76 77 if (bp == NULL) { 78 /* 79 * Theoretically, realloc is supposed to leave any already 80 * held memory alone if it can't get more. Don't trust it. 81 */ 82 *bsizep = 0; 83 return (NULL); 84 } 85 /* 86 * Memory is guaranteed to be zero-filled, various parts of 87 * nvi depend on this. 88 */ 89 memset((char *)bp + *bsizep, 0, csize - *bsizep); 90 *bsizep = csize; 91 return (bp); 92 } 93 94 /* 95 * nonblank -- 96 * Set the column number of the first non-blank character 97 * including or after the starting column. On error, set 98 * the column to 0, it's safest. 99 */ 100 int 101 nonblank(sp, ep, lno, cnop) 102 SCR *sp; 103 EXF *ep; 104 recno_t lno; 105 size_t *cnop; 106 { 107 char *p; 108 size_t cnt, len, off; 109 110 /* Default. */ 111 off = *cnop; 112 *cnop = 0; 113 114 /* Get the line. */ 115 if ((p = file_gline(sp, ep, lno, &len)) == NULL) { 116 if (file_lline(sp, ep, &lno)) 117 return (1); 118 if (lno == 0) 119 return (0); 120 GETLINE_ERR(sp, lno); 121 return (1); 122 } 123 124 /* Set the offset. */ 125 if (len == 0 || off >= len) 126 return (0); 127 128 for (cnt = off, p = &p[off], 129 len -= off; len && isblank(*p); ++cnt, ++p, --len); 130 131 /* Set the return. */ 132 *cnop = len ? cnt : cnt - 1; 133 return (0); 134 } 135 136 /* 137 * tail -- 138 * Return tail of a path. 139 */ 140 char * 141 tail(path) 142 char *path; 143 { 144 char *p; 145 146 if ((p = strrchr(path, '/')) == NULL) 147 return (path); 148 return (p + 1); 149 } 150 151 /* 152 * set_alt_name -- 153 * Set the alternate file name. 154 * 155 * Swap the alternate file name. It's a routine because I wanted some place 156 * to hang this comment. The alternate file name (normally referenced using 157 * the special character '#' during file expansion) is set by many 158 * operations. In the historic vi, the commands "ex", and "edit" obviously 159 * set the alternate file name because they switched the underlying file. 160 * Less obviously, the "read", "file", "write" and "wq" commands set it as 161 * well. In this implementation, some new commands have been added to the 162 * list. Where it gets interesting is that the alternate file name is set 163 * multiple times by some commands. If an edit attempt fails (for whatever 164 * reason, like the current file is modified but as yet unwritten), it is 165 * set to the file name that the user was unable to edit. If the edit 166 * succeeds, it is set to the last file name that was edited. Good fun. 167 * 168 * If the user edits a temporary file, there are time when there isn't an 169 * alternative file name. A name argument of NULL turns it off. 170 */ 171 void 172 set_alt_name(sp, name) 173 SCR *sp; 174 char *name; 175 { 176 if (sp->alt_name != NULL) 177 free(sp->alt_name); 178 if (name == NULL) 179 sp->alt_name = NULL; 180 else if ((sp->alt_name = strdup(name)) == NULL) 181 msgq(sp, M_SYSERR, NULL); 182 } 183 184 /* 185 * v_strdup -- 186 * Strdup for wide character strings with an associated length. 187 */ 188 CHAR_T * 189 v_strdup(sp, str, len) 190 SCR *sp; 191 CHAR_T *str; 192 size_t len; 193 { 194 CHAR_T *copy; 195 196 MALLOC(sp, copy, CHAR_T *, len + 1); 197 if (copy == NULL) 198 return (NULL); 199 memmove(copy, str, len * sizeof(CHAR_T)); 200 copy[len] = '\0'; 201 return (copy); 202 } 203 204 /* 205 * vi_putchar -- 206 * Functional version of putchar, for tputs. 207 */ 208 void 209 vi_putchar(ch) 210 int ch; 211 { 212 (void)putchar(ch); 213 } 214