home *** CD-ROM | disk | FTP | other *** search
- /*
- * BUFMSG.C - Message Buffering
- *
- * Msged/Q message editor for QuickBBS Copyright 1990 by P.J. Muller
- *
- */
-
- /*#define TIMING*/ /* for optimization info */
-
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #ifdef TIMING
- #include <time.h>
- #include <stdio.h>
- #endif
-
- #include "msged.h"
-
- #ifdef TIMING
- static void watch(int chk)
- {
- static clock_t start;
-
- if (chk != 0) {
- clock_t dif = clock()-start;
- fprintf(stderr,"%-3d %ld\n", chk, dif);
- } /* else */
- if (chk == -1)
- do {} while (getchar() != '\n');
-
- start = clock();
- } /* watch */
- #else
- # define watch(dummy)
- #endif
-
- void clearbuffer(BUFFER *buf)
- {
- LINE *curline;
-
- if ((curline = buf->first) != NULL) {
-
- while (curline->next != NULL) {
- curline = curline->next;
- ptrfree(curline->prev->text);
- curline->prev->next = NULL;
- ptrfree(curline->prev);
- curline->prev = NULL;
- }
-
- if (curline->text)
- ptrfree(curline->text);
-
- curline->text = NULL;
- ptrfree(curline);
- curline = NULL;
- buf->first = NULL;
- buf->last = NULL;
- }
- }
-
- #if ZAPTHISOUT /* OLD NEW VERSION */
- static void normalize(char *s);
-
- BUFFER buffer(char **ss)
- {
- char *tmp, *t, *t1, *s;
- LINE *p;
- BUFFER buf;
- int i;
- int column;
-
- /* init the buffer variables */
-
- buf.first = buf.last = NULL;
-
- clearbuffer(); /* clear global buffer (bad code) */
- watch(0);
- normalize(*ss); /* remove soft \r, convert \r\n to \n */
- watch(2);
- if ((*ss = (char *) realloc(*ss, strlen(*ss) + 1)) == NULL)
- return buf;
-
- s = *ss;
-
- /* wrap the text into the buffer */
-
- if ((t = (char *) calloc(1, (rm + rm/2))) == NULL)
- return buf;
-
- if ((tmp = (char *) calloc(1, (rm + rm/2))) == NULL) {
- ptrfree(t);
- return buf;
- }
-
- i = 0;
-
- buf.first = NULL;
- column = 0;
-
- while (*s != EOS) {
- column++;
-
- if (*s == '\t') {
- s++;
- *(t + i) = ' ';
- while (column % tabsize) {
- i++;
- *(t + i) = ' ';
- column++;
- }
- }
- else
- *(t + i) = *s++;
-
- /* if ((strlen(t) > rm) || (*(t + i) == '\n')) */
- /* if (strlen(t) > rm) */
-
- if ((i >= rm) || (*(t + i) == '\n')) {
- if ((workcount++ & 31) == 0)
- working(TRUE);
-
- column = 0;
- if (i >= rm) {
- memset(tmp, 0, (rm + rm/2));
- t1 = t + i;
-
- while (!isspace(*t1) && (t1 > t))
- t1--;
-
- if (t1 <= t) {
- t1 = t + i;
- while (!ispunct(*t1) && (t1 > t))
- t1--;
- }
-
- if (t1 <= t)
- t1 = t + i - 1;
-
- while (isspace(*t1))
- t1++;
-
- strcpy(tmp, t1);
- *t1 = '\0';
- }
- else
- memset(tmp, 0, (rm + rm/2));
-
- if ((p = (LINE *) calloc(1, sizeof(LINE))) == NULL) {
- ptrfree(t);
- ptrfree(tmp);
- return buf;
- }
-
- if ((p->text = strdup(t)) == NULL) {
- ptrfree(p);
- ptrfree(t);
- ptrfree(tmp);
- return buf;
- }
-
- if (*p->text == '\01')
- p->hide = 1;
-
- { register char *otmp = strchr(p->text,'>');
- if ((otmp != NULL) && (otmp - p->text < GUTTER))
- p->quote = 1;
- } /* island */
-
- if (buf.first == NULL) {
- buf.first = p;
- buf.last = p;
- p->next = NULL;
- p->prev = NULL;
- memset(t, 0, (rm + rm/2));
- strcpy(t, tmp);
- i = strlen(t);
- continue;
- }
-
- p->next = buf.last->next;
- buf.last->next = p;
- p->prev = buf.last;
- buf.last = p;
-
- memset(t, 0, (rm + rm/2));
- strcpy(t, tmp);
- i = strlen(t);
- }
- else
- i++;
- } /* while */
- watch(3);
-
- if (strlen(t) > 0) {
- if ((p = (LINE *) calloc(1, sizeof(LINE))) == NULL) {
- ptrfree(tmp);
- ptrfree(t);
- return buf;
- }
-
- if ((p->text = strdup(t)) == NULL) {
- ptrfree(p);
- ptrfree(t);
- ptrfree(tmp);
- return buf;
- }
-
- if (buf.first == NULL) {
- buf.first = p;
- buf.last = p;
- p->next = NULL;
- p->prev = NULL;
- }
- else {
- p->next = buf.last ->next;
- buf.last->next = p;
- p->prev = buf.last;
- buf.last = p;
- }
-
- if (*p->text == '\01')
- p->hide = 1;
-
- if (((strchr(p->text,'>') - p->text) < GUTTER) && (strchr(p->text,'>')))
- p->quote = 1;
- }
- watch(-1);
- ptrfree(tmp);
- ptrfree(t);
- if (buf.first != NULL)
- buf.first->prev = NULL;
- if (buf.last != NULL)
- buf.last->next = NULL;
- working(FALSE);
-
- return buf;
- } /* buffer */
-
- static void normalize(char *s)
- {
- char *tmp = s;
- char *org = s;
-
- while (*s != EOS) {
- switch (*s) {
- case (char) 0x8d:
- case (char) 0x0a:
- s++;
- continue;
- case (char) 0x0d:
- s++;
- *tmp = '\n';
- break;
- default:
- *tmp = *s++;
- break;
- }
- tmp++;
- }
- *tmp = EOS;
-
- if (rot13 != 0)
- for (s = org; *s != EOS; s++)
- *s = dorot13(*s);
- }
- #endif
-
- /*
- * Copy lookahead characters to line buffer
- * s is start, scol is col at start
- * p is end (inclusive)
- * *d is destination and is updated and zero-terminated
- * returns pointer p+1
- */
-
- static char *copychars(int *scol, char *s, char *p, char **d)
- {
- int c;
-
- while (s <= p) {
- switch (*s) {
- case '\n':
- case (char)0x8d:
- ++s;
- break;
-
- case '\t':
- c = tabsize-(*scol % tabsize); /* spaces to skip */
- *scol += c;
- while (c--)
- *(*d)++ = ' ';
- ++s;
- break;
-
- case '\r':
- *(*d)++ = '\n'; ++s;
- ++(*scol);
- break;
-
- default:
- *(*d)++ = *s++;
- ++(*scol);
- break;
- } /* switch */
- }
-
- *(*d) = EOS;
- return s;
- } /* copychars */
-
- static BOOLEAN addline(BUFFER *buf, char *text)
- {
- static int workcount = 0; /* slow down working indicator */
- LINE *p;
- char *grin;
-
- if ((workcount++ & 31) == 0)
- working(TRUE);
-
- if ((p = insertline(buf, NULL, text)) == NULL)
- return FALSE;
-
- if (text[0] == '\01')
- p->hide = 1;
-
- text = strchr(p->text, '>');
- grin = strchr(p->text, '<'); /* don't quote "<grin>" at start */
- if ((text != NULL) && (text - p->text < GUTTER) &&
- ((grin == NULL) || (grin > text)))
- p->quote = 1;
-
- return TRUE;
- } /* addline */
-
- BUFFER buffer(char **ss) /* NEW(est) version */
- {
- register char *s, *p;
- int scol, pcol;
- char *d, *text;
- BUFFER buf;
-
- buf.first = buf.last = NULL;
- clearbuffer(&msgbuf); /* clear global (yuck) buffer */
-
- text = (char *)malloc(rm + rm/2); /* add some fudge for taste */
- if (text == NULL) return buf; /* sorry pal */
-
- if (rot13 != 0) /* do rotation pass */
- for (s = *ss; *s != EOS; s++)
- *s = dorot13(*s);
-
- p = s = *ss; pcol = scol = 0; /* s is source, p is peek */
- d = text; *d = EOS; /* d is dest */
-
- for (;;) { /* loop over p by 1 (sometimes backtrack to checkpoint) */
- /* pcol is col at p (increases or stays same) */
- /* s is last checkpoint */
- /* scol is col at s */
- /* d is destination inside text */
-
- /* if at end of buffer, finish current line and exit */
-
- if (*p == EOS) { /* end of text */
- if (p > s) { /* we still have sometime left */
- (void)copychars(&scol, s, p-1, &d);
- (void)addline(&buf, text);
- } /* if */
- break; /* end of buffer */
-
- /* if at/past margin, start new line or smash current line (break badly) */
-
- } else if (pcol >= rm) { /* at margin */
- if (scol == 0) { /* bad break! */
- p = s = copychars(&scol, s, p, &d);
- pcol = scol = 0;
- if (!addline(&buf, text))
- break;
-
- } else { /* freeze line at last checkpoint */
- if (!addline(&buf, text))
- break;
- p = s; pcol = scol = 0; /* start over at last checkpoint */
-
- } /* else */
- d = text; *d = EOS;
-
- } else if (*p == '\r') { /* end of line */
- p = s = copychars(&scol, s, p, &d);
- pcol = scol = 0;
- if (!addline(&buf, text))
- break;
- d = text; *d = EOS;
-
- /* can break line here */
- } else if ((*p == ' ') || (*p == '\t') || (*p == '-')) {
- p = s = copychars(&scol, s, p, &d); /* 'checkpoint' */
- pcol = scol;
-
- } else if ((*p == '\n') || (*p == (char)0x8d)) { /* ignore */
- ++p;
-
- } else { /* all other characters */
- ++pcol;
- ++p;
- } /* else */
-
- } /* endless */
-
- ptrfree(text);
- working(FALSE); /* remove indicator */
-
- return buf;
- } /* buffer */