source: text.c @ f82e233

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