source: text.c @ fa00c5c

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