Chris Allegretta | 11b0011 | 2000-08-06 21:13:45 +0000 | [diff] [blame] | 1 | /* $Id$ */ |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 2 | /************************************************************************** |
| 3 | * utils.c * |
| 4 | * * |
Chris Allegretta | d757e25 | 2003-01-15 19:33:27 +0000 | [diff] [blame] | 5 | * Copyright (C) 1999-2003 Chris Allegretta * |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 6 | * This program is free software; you can redistribute it and/or modify * |
| 7 | * it under the terms of the GNU General Public License as published by * |
Chris Allegretta | 3a24f3f | 2001-10-24 11:33:54 +0000 | [diff] [blame] | 8 | * the Free Software Foundation; either version 2, or (at your option) * |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 9 | * any later version. * |
| 10 | * * |
| 11 | * This program is distributed in the hope that it will be useful, * |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
| 14 | * GNU General Public License for more details. * |
| 15 | * * |
| 16 | * You should have received a copy of the GNU General Public License * |
| 17 | * along with this program; if not, write to the Free Software * |
| 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * |
| 19 | * * |
| 20 | **************************************************************************/ |
| 21 | |
David Lawrence Ramsey | e21adfa | 2002-09-13 18:14:04 +0000 | [diff] [blame] | 22 | #include "config.h" |
| 23 | |
Chris Allegretta | 77777d4 | 2002-03-29 16:31:29 +0000 | [diff] [blame] | 24 | #include <stdio.h> |
Chris Allegretta | f6b1342 | 2000-07-07 04:25:00 +0000 | [diff] [blame] | 25 | #include <unistd.h> |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 26 | #include <stdlib.h> |
| 27 | #include <string.h> |
| 28 | #include <ctype.h> |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 29 | #include <assert.h> |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 30 | #include "proto.h" |
David Lawrence Ramsey | f21cd10 | 2002-06-13 00:40:19 +0000 | [diff] [blame] | 31 | #include "nano.h" |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 32 | |
Chris Allegretta | d845193 | 2003-03-11 03:50:40 +0000 | [diff] [blame] | 33 | #ifdef BROKEN_REGEXEC |
| 34 | #undef regexec |
| 35 | int regexec_safe(const regex_t *preg, const char *string, size_t nmatch, |
| 36 | regmatch_t pmatch[], int eflags) |
| 37 | { |
| 38 | if (string != NULL && *string != '\0') |
| 39 | return regexec(preg, string, nmatch, pmatch, eflags); |
| 40 | return REG_NOMATCH; |
| 41 | } |
| 42 | #define regexec(preg, string, nmatch, pmatch, eflags) regexec_safe(preg, string, nmatch, pmatch, eflags) |
| 43 | #endif |
| 44 | |
Chris Allegretta | cf287c8 | 2002-07-20 13:57:41 +0000 | [diff] [blame] | 45 | int is_cntrl_char(int c) |
| 46 | { |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 47 | return (-128 <= c && c < -96) || (0 <= c && c < 32) || |
| 48 | (127 <= c && c < 160); |
Chris Allegretta | cf287c8 | 2002-07-20 13:57:41 +0000 | [diff] [blame] | 49 | } |
| 50 | |
Chris Allegretta | 48b0670 | 2002-02-22 04:30:50 +0000 | [diff] [blame] | 51 | int num_of_digits(int n) |
| 52 | { |
| 53 | int i = 1; |
| 54 | |
| 55 | if (n < 0) |
David Lawrence Ramsey | 0341b58 | 2002-08-21 16:10:37 +0000 | [diff] [blame] | 56 | n = -n; |
Chris Allegretta | 48b0670 | 2002-02-22 04:30:50 +0000 | [diff] [blame] | 57 | |
| 58 | while (n > 10) { |
| 59 | n /= 10; |
| 60 | i++; |
| 61 | } |
| 62 | |
| 63 | return i; |
| 64 | } |
| 65 | |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 66 | /* Fix the memory allocation for a string. */ |
| 67 | void align(char **strp) |
David Lawrence Ramsey | f21cd10 | 2002-06-13 00:40:19 +0000 | [diff] [blame] | 68 | { |
David Lawrence Ramsey | 70047ee | 2003-06-14 20:41:34 +0000 | [diff] [blame] | 69 | assert(strp != NULL); |
| 70 | if (*strp != NULL) |
| 71 | *strp = charealloc(*strp, strlen(*strp) + 1); |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 72 | } |
| 73 | |
| 74 | /* Null a string at a certain index and align it. */ |
| 75 | void null_at(char **data, size_t index) |
| 76 | { |
| 77 | assert(data != NULL); |
Chris Allegretta | e1e0fd6 | 2003-04-15 01:15:09 +0000 | [diff] [blame] | 78 | *data = charealloc(*data, index + 1); |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 79 | (*data)[index] = '\0'; |
David Lawrence Ramsey | f21cd10 | 2002-06-13 00:40:19 +0000 | [diff] [blame] | 80 | } |
| 81 | |
| 82 | /* For non-null-terminated lines. A line, by definition, shouldn't |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 83 | * normally have newlines in it, so encode its nulls as newlines. */ |
| 84 | void unsunder(char *str, size_t true_len) |
| 85 | { |
| 86 | assert(str != NULL); |
| 87 | for(; true_len > 0; true_len--, str++) |
| 88 | if (*str == '\0') |
| 89 | *str = '\n'; |
| 90 | } |
| 91 | |
| 92 | /* For non-null-terminated lines. A line, by definition, shouldn't |
| 93 | * normally have newlines in it, so decode its newlines into nulls. */ |
David Lawrence Ramsey | f21cd10 | 2002-06-13 00:40:19 +0000 | [diff] [blame] | 94 | void sunder(char *str) |
| 95 | { |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 96 | assert(str != NULL); |
| 97 | for(; *str != '\0'; str++) |
| 98 | if (*str == '\n') |
| 99 | *str = '\0'; |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 100 | } |
| 101 | |
Chris Allegretta | 4f5335d | 2003-08-04 02:51:12 +0000 | [diff] [blame] | 102 | #ifndef HAVE_STRCASECMP |
| 103 | /* This function is equivalent to strcasecmp(). */ |
| 104 | int nstricmp(const char *s1, const char *s2) |
| 105 | { |
| 106 | assert(s1 != NULL && s2 != NULL); |
| 107 | for (; *s1 != '\0' && *s2 != '\0'; s1++, s2++) { |
| 108 | if (tolower(*s1) != tolower(*s2)) |
| 109 | break; |
| 110 | } |
| 111 | return (tolower(*s1) - tolower(*s2)); |
| 112 | } |
| 113 | #endif |
| 114 | |
| 115 | #ifndef HAVE_STRNCASECMP |
| 116 | /* This function is equivalent to strncasecmp(). */ |
| 117 | int nstrnicmp(const char *s1, const char *s2, size_t n) |
| 118 | { |
| 119 | assert(s1 != NULL && s2 != NULL); |
| 120 | for (; n > 0 && *s1 != '\0' && *s2 != '\0'; n--, s1++, s2++) { |
| 121 | if (tolower(*s1) != tolower(*s2)) |
| 122 | break; |
| 123 | } |
| 124 | if (n > 0) |
| 125 | return (tolower(*s1) - tolower(*s2)); |
| 126 | else if (n == 0) |
| 127 | return 0; |
| 128 | else if (n < 0) |
| 129 | return -1; |
| 130 | } |
| 131 | #endif |
| 132 | |
Chris Allegretta | 5f36c37 | 2001-07-16 00:48:53 +0000 | [diff] [blame] | 133 | /* None of this is needed if we're using NANO_SMALL! */ |
| 134 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 0341b58 | 2002-08-21 16:10:37 +0000 | [diff] [blame] | 135 | const char *revstrstr(const char *haystack, const char *needle, |
David Lawrence Ramsey | ad40fdb | 2002-09-06 20:35:28 +0000 | [diff] [blame] | 136 | const char *rev_start) |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 137 | { |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 138 | for(; rev_start >= haystack ; rev_start--) { |
| 139 | const char *r, *q; |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 140 | |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 141 | for (r = rev_start, q = needle ; *q == *r && *q != '\0'; r++, q++) |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 142 | ; |
| 143 | if (*q == '\0') |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 144 | return rev_start; |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 145 | } |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 146 | return NULL; |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 147 | } |
| 148 | |
David Lawrence Ramsey | 0341b58 | 2002-08-21 16:10:37 +0000 | [diff] [blame] | 149 | const char *revstristr(const char *haystack, const char *needle, |
David Lawrence Ramsey | ad40fdb | 2002-09-06 20:35:28 +0000 | [diff] [blame] | 150 | const char *rev_start) |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 151 | { |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 152 | for (; rev_start >= haystack; rev_start--) { |
| 153 | const char *r = rev_start, *q = needle; |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 154 | |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 155 | for (; (tolower(*q) == tolower(*r)) && (*q != '\0') ; r++, q++) |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 156 | ; |
| 157 | if (*q == '\0') |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 158 | return rev_start; |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 159 | } |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 160 | return NULL; |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 161 | } |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 162 | #endif /* !NANO_SMALL */ |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 163 | |
Chris Allegretta | 99afb85 | 2001-05-16 04:20:57 +0000 | [diff] [blame] | 164 | /* This is now mutt's version (called mutt_stristr) because it doesn't |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 165 | * use memory allocation to do a simple search (yuck). */ |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 166 | const char *stristr(const char *haystack, const char *needle) |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 167 | { |
Chris Allegretta | 99afb85 | 2001-05-16 04:20:57 +0000 | [diff] [blame] | 168 | const char *p, *q; |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 169 | |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 170 | if (haystack == NULL) |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 171 | return NULL; |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 172 | if (needle == NULL) |
| 173 | return haystack; |
Chris Allegretta | 99afb85 | 2001-05-16 04:20:57 +0000 | [diff] [blame] | 174 | |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 175 | while (*(p = haystack) != '\0') { |
| 176 | for (q = needle; *p != 0 && *q != 0 && tolower(*p) == tolower(*q); p++, q++) |
Chris Allegretta | 99afb85 | 2001-05-16 04:20:57 +0000 | [diff] [blame] | 177 | ; |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 178 | if (*q == 0) |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 179 | return haystack; |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 180 | haystack++; |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 181 | } |
Chris Allegretta | 99afb85 | 2001-05-16 04:20:57 +0000 | [diff] [blame] | 182 | return NULL; |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 183 | } |
| 184 | |
Chris Allegretta | 9090f2e | 2003-01-26 04:45:05 +0000 | [diff] [blame] | 185 | /* If we are searching backwards, we will find the last match |
| 186 | * that starts no later than rev_start. If we are doing a regexp search, |
| 187 | * then line_pos should be 0 if haystack starts at the beginning of a |
| 188 | * line, and positive otherwise. In the regexp case, we fill in the |
| 189 | * global variable regmatches with at most 9 subexpression matches. Also, |
| 190 | * all .rm_so elements are relative to the start of the whole match, so |
| 191 | * regmatches[0].rm_so == 0. */ |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 192 | const char *strstrwrapper(const char *haystack, const char *needle, |
David Lawrence Ramsey | ad40fdb | 2002-09-06 20:35:28 +0000 | [diff] [blame] | 193 | const char *rev_start, int line_pos) |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 194 | { |
Chris Allegretta | 805c26d | 2000-09-06 13:39:17 +0000 | [diff] [blame] | 195 | #ifdef HAVE_REGEX_H |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 196 | if (ISSET(USE_REGEXP)) { |
Chris Allegretta | 8dbfb5c | 2002-01-28 15:56:15 +0000 | [diff] [blame] | 197 | #ifndef NANO_SMALL |
Chris Allegretta | 9090f2e | 2003-01-26 04:45:05 +0000 | [diff] [blame] | 198 | if (ISSET(REVERSE_SEARCH)) { |
| 199 | /* When doing a backwards search, haystack is a whole line. */ |
| 200 | if (!regexec(&search_regexp, haystack, 1, regmatches, 0) && |
| 201 | haystack + regmatches[0].rm_so <= rev_start) { |
| 202 | const char *retval = haystack + regmatches[0].rm_so; |
Chris Allegretta | 8dbfb5c | 2002-01-28 15:56:15 +0000 | [diff] [blame] | 203 | |
Chris Allegretta | 9090f2e | 2003-01-26 04:45:05 +0000 | [diff] [blame] | 204 | /* Search forward until there is no more match. */ |
| 205 | while (!regexec(&search_regexp, retval + 1, 1, regmatches, |
| 206 | REG_NOTBOL) && |
| 207 | retval + 1 + regmatches[0].rm_so <= rev_start) |
| 208 | retval += 1 + regmatches[0].rm_so; |
| 209 | /* Finally, put the subexpression matches in global |
| 210 | * variable regmatches. The REG_NOTBOL flag doesn't |
| 211 | * matter now. */ |
| 212 | regexec(&search_regexp, retval, 10, regmatches, 0); |
| 213 | return retval; |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 214 | } |
Chris Allegretta | 9090f2e | 2003-01-26 04:45:05 +0000 | [diff] [blame] | 215 | } else |
| 216 | #endif /* !NANO_SMALL */ |
| 217 | if (!regexec(&search_regexp, haystack, 10, regmatches, |
| 218 | line_pos > 0 ? REG_NOTBOL : 0)) { |
| 219 | const char *retval = haystack + regmatches[0].rm_so; |
| 220 | |
| 221 | regexec(&search_regexp, retval, 10, regmatches, 0); |
| 222 | return retval; |
Chris Allegretta | 8dbfb5c | 2002-01-28 15:56:15 +0000 | [diff] [blame] | 223 | } |
Chris Allegretta | 9090f2e | 2003-01-26 04:45:05 +0000 | [diff] [blame] | 224 | return NULL; |
Chris Allegretta | bd9e7c3 | 2000-10-26 01:44:42 +0000 | [diff] [blame] | 225 | } |
Chris Allegretta | 9090f2e | 2003-01-26 04:45:05 +0000 | [diff] [blame] | 226 | #endif /* HAVE_REGEX_H */ |
Chris Allegretta | 5f36c37 | 2001-07-16 00:48:53 +0000 | [diff] [blame] | 227 | #ifndef NANO_SMALL |
Chris Allegretta | e10f389 | 2001-10-02 03:54:40 +0000 | [diff] [blame] | 228 | if (ISSET(CASE_SENSITIVE)) { |
Chris Allegretta | 5f36c37 | 2001-07-16 00:48:53 +0000 | [diff] [blame] | 229 | if (ISSET(REVERSE_SEARCH)) |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 230 | return revstrstr(haystack, needle, rev_start); |
Chris Allegretta | 5f36c37 | 2001-07-16 00:48:53 +0000 | [diff] [blame] | 231 | else |
Chris Allegretta | 9090f2e | 2003-01-26 04:45:05 +0000 | [diff] [blame] | 232 | return strstr(haystack, needle); |
| 233 | } else if (ISSET(REVERSE_SEARCH)) |
| 234 | return revstristr(haystack, needle, rev_start); |
Chris Allegretta | 5f36c37 | 2001-07-16 00:48:53 +0000 | [diff] [blame] | 235 | #endif |
Chris Allegretta | 9090f2e | 2003-01-26 04:45:05 +0000 | [diff] [blame] | 236 | return stristr(haystack, needle); |
Chris Allegretta | a2ea193 | 2000-06-06 05:53:49 +0000 | [diff] [blame] | 237 | } |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 238 | |
Chris Allegretta | 77777d4 | 2002-03-29 16:31:29 +0000 | [diff] [blame] | 239 | /* This is a wrapper for the perror function. The wrapper takes care of |
| 240 | * ncurses, calls perror (which writes to STDERR), then refreshes the |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 241 | * screen. Note that nperror causes the window to flicker once. */ |
David Lawrence Ramsey | ad40fdb | 2002-09-06 20:35:28 +0000 | [diff] [blame] | 242 | void nperror(const char *s) |
| 243 | { |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 244 | /* leave ncurses mode, go to the terminal */ |
Chris Allegretta | 77777d4 | 2002-03-29 16:31:29 +0000 | [diff] [blame] | 245 | if (endwin() != ERR) { |
| 246 | perror(s); /* print the error */ |
| 247 | total_refresh(); /* return to ncurses and repaint */ |
| 248 | } |
| 249 | } |
| 250 | |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 251 | /* Thanks BG, many ppl have been asking for this... */ |
| 252 | void *nmalloc(size_t howmuch) |
Chris Allegretta | 4da1fc6 | 2000-06-21 03:00:43 +0000 | [diff] [blame] | 253 | { |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 254 | void *r = malloc(howmuch); |
Chris Allegretta | 4da1fc6 | 2000-06-21 03:00:43 +0000 | [diff] [blame] | 255 | |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 256 | if (r == NULL && howmuch != 0) |
| 257 | die(_("nano is out of memory!")); |
Chris Allegretta | 8d8e012 | 2001-04-18 04:28:54 +0000 | [diff] [blame] | 258 | |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 259 | return r; |
Chris Allegretta | 8d8e012 | 2001-04-18 04:28:54 +0000 | [diff] [blame] | 260 | } |
| 261 | |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 262 | void *nrealloc(void *ptr, size_t howmuch) |
Chris Allegretta | 4da1fc6 | 2000-06-21 03:00:43 +0000 | [diff] [blame] | 263 | { |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 264 | void *r = realloc(ptr, howmuch); |
Chris Allegretta | 4da1fc6 | 2000-06-21 03:00:43 +0000 | [diff] [blame] | 265 | |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 266 | if (r == NULL && howmuch != 0) |
| 267 | die(_("nano is out of memory!")); |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 268 | |
| 269 | return r; |
| 270 | } |
Robert Siemborski | 63b3d7e | 2000-07-04 22:15:39 +0000 | [diff] [blame] | 271 | |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 272 | /* Copy one malloc()ed string to another pointer. Should be used as: |
| 273 | * dest = mallocstrcpy(dest, src); */ |
| 274 | char *mallocstrcpy(char *dest, const char *src) |
Chris Allegretta | 31925e4 | 2000-11-02 04:40:39 +0000 | [diff] [blame] | 275 | { |
Chris Allegretta | e1ebaf3 | 2001-01-07 05:50:36 +0000 | [diff] [blame] | 276 | if (src == dest) |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 277 | return dest; |
Chris Allegretta | e1ebaf3 | 2001-01-07 05:50:36 +0000 | [diff] [blame] | 278 | |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 279 | if (dest != NULL) |
Chris Allegretta | 31925e4 | 2000-11-02 04:40:39 +0000 | [diff] [blame] | 280 | free(dest); |
| 281 | |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 282 | if (src == NULL) |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 283 | return NULL; |
Chris Allegretta | 5bf51d3 | 2000-11-16 06:01:10 +0000 | [diff] [blame] | 284 | |
Chris Allegretta | 88b0915 | 2001-05-17 11:35:43 +0000 | [diff] [blame] | 285 | dest = charalloc(strlen(src) + 1); |
Chris Allegretta | 31925e4 | 2000-11-02 04:40:39 +0000 | [diff] [blame] | 286 | strcpy(dest, src); |
| 287 | |
| 288 | return dest; |
| 289 | } |
| 290 | |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 291 | /* Append a new magic-line to filebot. */ |
Chris Allegretta | bd9e7c3 | 2000-10-26 01:44:42 +0000 | [diff] [blame] | 292 | void new_magicline(void) |
| 293 | { |
David Lawrence Ramsey | 70047ee | 2003-06-14 20:41:34 +0000 | [diff] [blame] | 294 | filebot->next = (filestruct *)nmalloc(sizeof(filestruct)); |
Chris Allegretta | 88b0915 | 2001-05-17 11:35:43 +0000 | [diff] [blame] | 295 | filebot->next->data = charalloc(1); |
Robert Siemborski | 63b3d7e | 2000-07-04 22:15:39 +0000 | [diff] [blame] | 296 | filebot->next->data[0] = '\0'; |
| 297 | filebot->next->prev = filebot; |
| 298 | filebot->next->next = NULL; |
| 299 | filebot->next->lineno = filebot->lineno + 1; |
| 300 | filebot = filebot->next; |
| 301 | totlines++; |
Chris Allegretta | e51c95f | 2000-12-10 05:54:27 +0000 | [diff] [blame] | 302 | totsize++; |
Robert Siemborski | 63b3d7e | 2000-07-04 22:15:39 +0000 | [diff] [blame] | 303 | } |
Chris Allegretta | 04d848e | 2000-11-05 17:54:41 +0000 | [diff] [blame] | 304 | |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 305 | #ifndef NANO_SMALL |
| 306 | /* Set top_x and bot_x to the top and bottom x-coordinates of the mark, |
| 307 | * respectively, based on the locations of top and bot. */ |
| 308 | void mark_order(const filestruct **top, size_t *top_x, |
| 309 | const filestruct **bot, size_t *bot_x) |
| 310 | { |
| 311 | assert(top != NULL && top_x != NULL && bot != NULL && bot_x != NULL); |
| 312 | if ((current->lineno == mark_beginbuf->lineno && current_x > mark_beginx) |
| 313 | || current->lineno > mark_beginbuf->lineno) { |
| 314 | *top = mark_beginbuf; |
| 315 | *top_x = mark_beginx; |
| 316 | *bot = current; |
| 317 | *bot_x = current_x; |
| 318 | } else { |
| 319 | *bot = mark_beginbuf; |
| 320 | *bot_x = mark_beginx; |
| 321 | *top = current; |
| 322 | *top_x = current_x; |
| 323 | } |
| 324 | } |
| 325 | #endif |
| 326 | |
Rocco Corsi | 06aca1c | 2001-01-11 05:30:31 +0000 | [diff] [blame] | 327 | #ifndef DISABLE_TABCOMP |
Chris Allegretta | 04d848e | 2000-11-05 17:54:41 +0000 | [diff] [blame] | 328 | /* |
| 329 | * Routine to see if a text string is matched by a wildcard pattern. |
| 330 | * Returns TRUE if the text is matched, or FALSE if it is not matched |
| 331 | * or if the pattern is invalid. |
| 332 | * * matches zero or more characters |
| 333 | * ? matches a single character |
| 334 | * [abc] matches 'a', 'b' or 'c' |
| 335 | * \c quotes character c |
| 336 | * Adapted from code written by Ingo Wilken, and |
| 337 | * then taken from sash, Copyright (c) 1999 by David I. Bell |
| 338 | * Permission is granted to use, distribute, or modify this source, |
| 339 | * provided that this copyright notice remains intact. |
| 340 | * Permission to distribute this code under the GPL has been granted. |
| 341 | */ |
| 342 | int check_wildcard_match(const char *text, const char *pattern) |
| 343 | { |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 344 | const char *retrypat; |
| 345 | const char *retrytext; |
Chris Allegretta | 04d848e | 2000-11-05 17:54:41 +0000 | [diff] [blame] | 346 | int ch; |
| 347 | int found; |
| 348 | int len; |
| 349 | |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 350 | retrypat = NULL; |
| 351 | retrytext = NULL; |
Chris Allegretta | 04d848e | 2000-11-05 17:54:41 +0000 | [diff] [blame] | 352 | |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 353 | while (*text != '\0' || *pattern != '\0') { |
Chris Allegretta | 04d848e | 2000-11-05 17:54:41 +0000 | [diff] [blame] | 354 | ch = *pattern++; |
| 355 | |
| 356 | switch (ch) { |
| 357 | case '*': |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 358 | retrypat = pattern; |
| 359 | retrytext = text; |
Chris Allegretta | 04d848e | 2000-11-05 17:54:41 +0000 | [diff] [blame] | 360 | break; |
| 361 | |
| 362 | case '[': |
| 363 | found = FALSE; |
| 364 | |
| 365 | while ((ch = *pattern++) != ']') { |
| 366 | if (ch == '\\') |
| 367 | ch = *pattern++; |
| 368 | |
| 369 | if (ch == '\0') |
| 370 | return FALSE; |
| 371 | |
| 372 | if (*text == ch) |
| 373 | found = TRUE; |
| 374 | } |
| 375 | len = strlen(text); |
| 376 | if (found == FALSE && len != 0) { |
| 377 | return FALSE; |
| 378 | } |
| 379 | if (found == TRUE) { |
| 380 | if (strlen(pattern) == 0 && len == 1) { |
| 381 | return TRUE; |
| 382 | } |
| 383 | if (len != 0) { |
| 384 | text++; |
| 385 | continue; |
| 386 | } |
| 387 | } |
| 388 | |
| 389 | /* fall into next case */ |
| 390 | |
| 391 | case '?': |
| 392 | if (*text++ == '\0') |
| 393 | return FALSE; |
| 394 | |
| 395 | break; |
| 396 | |
| 397 | case '\\': |
| 398 | ch = *pattern++; |
| 399 | |
| 400 | if (ch == '\0') |
| 401 | return FALSE; |
| 402 | |
| 403 | /* fall into next case */ |
| 404 | |
| 405 | default: |
| 406 | if (*text == ch) { |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 407 | if (*text != '\0') |
Chris Allegretta | 04d848e | 2000-11-05 17:54:41 +0000 | [diff] [blame] | 408 | text++; |
| 409 | break; |
| 410 | } |
| 411 | |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 412 | if (*text != '\0') { |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 413 | pattern = retrypat; |
| 414 | text = ++retrytext; |
Chris Allegretta | 04d848e | 2000-11-05 17:54:41 +0000 | [diff] [blame] | 415 | break; |
| 416 | } |
| 417 | |
| 418 | return FALSE; |
| 419 | } |
| 420 | |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 421 | if (pattern == NULL) |
Chris Allegretta | 04d848e | 2000-11-05 17:54:41 +0000 | [diff] [blame] | 422 | return FALSE; |
| 423 | } |
| 424 | |
| 425 | return TRUE; |
| 426 | } |
Chris Allegretta | 09a8084 | 2000-11-30 02:31:13 +0000 | [diff] [blame] | 427 | #endif |