source: text.c @ 72db971

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