source: text.c @ 19b2766

release-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 19b2766 was ebbeb39, checked in by Anders Kaseorg <andersk@mit.edu>, 15 years ago
owl_text_quote: Don’t leak a kretch-sized buffer. Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • Property mode set to 100644
File size: 7.1 KB
Line 
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4#include <ctype.h>
5#include "owl.h"
6
7void owl_text_indent(char *out, const char *in, int n)
8{
9  const char *ptr1, *ptr2, *last;
10  int i;
11
12  strcpy(out, "");
13
14  last=in+strlen(in)-1;
15  ptr1=in;
16  while (ptr1<=last) {
17    for (i=0; i<n; i++) {
18      strcat(out, " ");
19    }
20    ptr2=strchr(ptr1, '\n');
21    if (!ptr2) {
22      strcat(out, ptr1);
23      break;
24    } else {
25      strncat(out, ptr1, ptr2-ptr1+1);
26    }
27    ptr1=ptr2+1;
28  }
29}
30
31int owl_text_num_lines(const char *in)
32{
33  int lines, i;
34
35  lines=0;
36  for (i=0; in[i]!='\0'; i++) {
37    if (in[i]=='\n') lines++;
38  }
39
40  /* if the last char wasn't a \n there's one more line */
41  if (i>0 && in[i-1]!='\n') lines++;
42
43  return(lines);
44}
45
46
47/* caller must free the return */
48char *owl_text_htmlstrip(const char *in)
49{
50  const char *ptr1, *end, *ptr2, *ptr3;
51  char *out, *out2;
52
53  out=owl_malloc(strlen(in)+30);
54  strcpy(out, "");
55
56  ptr1=in;
57  end=in+strlen(in);
58 
59  while(ptr1<end) {
60    /* look for an open bracket */
61    ptr2=strchr(ptr1, '<');
62
63    /* if none, copy in from here to end and exit */
64    if (ptr2==NULL) {
65      strcat(out, ptr1);
66      break;
67    }
68
69    /* otherwise copy in everything before the open bracket */
70    if (ptr2>ptr1) {
71      strncat(out, ptr1, ptr2-ptr1);
72    }
73
74    /* find the close bracket */
75    ptr3=strchr(ptr2, '>');
76   
77    /* if there is no close, copy as you are and exit */
78    if (!ptr3) {
79      strcat(out, ptr2);
80      break;
81    }
82
83    /* look for things we know */
84    if (!strncasecmp(ptr2, "<BODY", 5) ||
85        !strncasecmp(ptr2, "<FONT", 5) ||
86        !strncasecmp(ptr2, "<HTML", 5) ||
87        !strncasecmp(ptr2, "</FONT", 6) ||
88        !strncasecmp(ptr2, "</HTML", 6) ||
89        !strncasecmp(ptr2, "</BODY", 6)) {
90
91      /* advance to beyond the angle brakcet and go again */
92      ptr1=ptr3+1;
93      continue;
94    }
95    if (!strncasecmp(ptr2, "<BR>", 4)) {
96      strcat(out, "\n");
97      ptr1=ptr3+1;
98      continue;
99    }
100
101    /* if it wasn't something we know, copy to the > and  go again */
102    strncat(out, ptr2, ptr3-ptr2+1);
103    ptr1=ptr3+1;
104  }
105
106  out2=owl_text_substitute(out, "&lt;", "<");
107  owl_free(out);
108  out=owl_text_substitute(out2, "&gt;", ">");
109  owl_free(out2);
110  out2=owl_text_substitute(out, "&amp;", "&");
111  owl_free(out);
112  out=owl_text_substitute(out2, "&quot;", "\"");
113  owl_free(out2);
114  out2=owl_text_substitute(out, "&nbsp;", " ");
115  owl_free(out);
116  out=owl_text_substitute(out2, "&ensp;", "  ");
117  owl_free(out2);
118  out2=owl_text_substitute(out, "&emsp;", "   ");
119  owl_free(out);
120  out=owl_text_substitute(out2, "&endash;", "--");
121  owl_free(out2);
122  out2=owl_text_substitute(out, "&emdash;", "---");
123  owl_free(out);
124
125  return(out2);
126}
127
128#define OWL_TAB_WIDTH 8
129
130/* Caller must free return */
131char *owl_text_expand_tabs(const char *in)
132{
133  int ntabs = 0;
134  const char *p = in;
135  char *ret, *out;
136  int col;
137
138  while(*p) {
139    if (*(p++) == '\t') ntabs++;
140  }
141
142  ret = owl_malloc(strlen(in) + 1 + OWL_TAB_WIDTH * ntabs);
143
144  p = in;
145  out = ret;
146
147  col = 0;
148  while(*p) {
149    switch(*p) {
150    case '\t':
151      do {*(out++) = ' '; col++; } while (col % OWL_TAB_WIDTH);
152      break;
153    case '\n':
154      col = -1;
155    default:
156      col++;
157      *(out++) = *p;
158    }
159    p++;
160  }
161
162  *out = 0;
163
164  return ret;
165}
166
167/* caller must free the return */
168char *owl_text_wordwrap(const char *in, int col)
169{
170  char *out;
171  int cur, lastspace, len, lastnewline;
172
173  out=owl_strdup(in);
174  len=strlen(in);
175  cur=0;
176  lastspace=-1;
177  lastnewline=-1;
178
179  while (cur<(len-1)) {
180    if (out[cur]==' ') {
181      lastspace=cur;
182      cur++;
183      continue;
184    } else if (out[cur]=='\n') {
185      lastnewline=cur;
186      cur++;
187      continue;
188    }
189
190    /* do we need to wrap? */
191    if ( (cur-(lastnewline+1)) > col ) {
192      if (lastspace==-1 ||
193          (lastnewline>0 && (lastspace<=lastnewline))) {
194        /* we can't help, sorry */
195        cur++;
196        continue;
197      }
198
199      /* turn the last space into a newline */
200      out[lastspace]='\n';
201      lastnewline=lastspace;
202      lastspace=-1;
203      cur++;
204      continue;
205    }
206
207    cur++;
208    continue;
209  }
210  return(out);
211}
212
213/* this modifies 'in' */
214void owl_text_wordunwrap(char *in)
215{
216  int i, j;
217
218  j=strlen(in);
219  for (i=0; i<j; i++) {
220    if ( (in[i]=='\n') &&
221         ((i>0) && (i<(j-1))) &&
222         (in[i-1]!='\n') &&
223         (in[i+1]!='\n') )
224      in[i]=' ';
225  }
226}
227
228/* return 1 if a string is only whitespace, otherwise 0 */
229int only_whitespace(const char *s)
230{
231  if (g_utf8_validate(s,-1,NULL)) {
232    const char *p;
233    for(p = s; p[0]; p=g_utf8_next_char(p)) {
234      if (!g_unichar_isspace(g_utf8_get_char(p))) return 0;
235    }
236  }
237  else {
238    int i;
239    for (i=0; s[i]; i++) {
240      if (!isspace((int) s[i])) return(0);
241    }
242  }
243  return(1);
244}
245
246const char *owl_getquoting(const char *line)
247{
248  if (line[0]=='\0') return("'");
249  if (strchr(line, '\'')) return("\"");
250  if (strchr(line, '"')) return("'");
251  if (strchr(line, ' ')) return("'");
252  return("");
253}
254
255/* Return a string with any occurances of 'from' replaced with 'to'.
256 * Does not currently handle backslash quoting, but may in the future.
257 * Caller must free returned string.
258 */
259char *owl_text_substitute(const char *in, const char *from, const char *to)
260{
261 
262  char *out;
263  int   outlen, tolen, fromlen, inpos=0, outpos=0;
264
265  if (!*from) return owl_strdup(in);
266
267  outlen = strlen(in)+1;
268  tolen  = strlen(to);
269  fromlen  = strlen(from);
270  out = owl_malloc(outlen);
271
272  while (in[inpos]) {
273    if (!strncmp(in+inpos, from, fromlen)) {
274      outlen += tolen;
275      out = owl_realloc(out, outlen);
276      strcpy(out+outpos, to);
277      inpos += fromlen;
278      outpos += tolen;
279    } else {
280      out[outpos] = in[inpos];
281      inpos++; outpos++;
282    }
283  }
284  out[outpos] = '\0';
285  return(out);
286}
287
288/* replace all instances of character a in buff with the character
289 * b.  buff must be null terminated.
290 */
291void owl_text_tr(char *buff, char a, char b)
292{
293  int i;
294
295  owl_function_debugmsg("In: %s", buff);
296  for (i=0; buff[i]!='\0'; i++) {
297    if (buff[i]==a) buff[i]=b;
298  }
299  owl_function_debugmsg("Out: %s", buff);
300}
301
302/* Return a string which is like 'in' except that every instance of
303 * any character in 'toquote' found in 'in' is preceeded by the string
304 * 'quotestr'.  For example, owl_text_quote(in, "+*.", "\") would
305 * place a backslash before every '+', '*' or '.' in 'in'.  It is
306 * permissable for a character in 'quotestr' to be in 'toquote'.
307 * On success returns the string, on error returns NULL.
308 */
309char *owl_text_quote(const char *in, const char *toquote, const char *quotestr)
310{
311  int i, x, r, place, escape;
312  int in_len, toquote_len, quotestr_len;
313  char *out;
314
315  in_len=strlen(in);
316  toquote_len=strlen(toquote);
317  quotestr_len=strlen(quotestr);
318  place=0;
319  escape = 0;
320  for (i=0; i<in_len; i++) {
321    if(strchr(toquote, in[i]) != NULL)
322      escape++;
323  }
324  out = owl_malloc(in_len + quotestr_len*escape+1);
325  for (i=0; i<in_len; i++) {
326
327    /* check if it's a character that needs quoting */
328    for (x=0; x<toquote_len; x++) {
329      if (in[i]==toquote[x]) {
330        /* quote it */
331        for (r=0; r<quotestr_len; r++) {
332          out[place+r]=quotestr[r];
333        }
334        place+=quotestr_len;
335        break;
336      }
337    }
338
339    /* either way, we now copy over the character */
340    out[place]=in[i];
341    place++;
342  }
343  out[place]='\0';
344  return(out);
345}
Note: See TracBrowser for help on using the repository browser.