/* * MusicMUD Daemon, version 1.0 * Copyright (C) 1998-2003 Abigail Brady * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include <string.h> #include <stdlib.h> #include <stdio.h> #include "wordwrap.h" #include "vsprintf.h" #include "charset.h" #include "colour.h" static bool newline(char a) { return a=='\n' || a=='\v'; } static int wordlength(const char *w2) { int length = 0; int intag = 0; int lasth = 0; int lastamp = 0; while (*w2) { if (length) { if(!intag && (*w2 == ' ') || newline(*w2) || lasth) { return length; } } if (*w2=='-' && !lastamp) lasth=1; if (*w2=='\3') intag=1; if (*w2=='\4') intag=0; lastamp = *w2 == '&'; if(*w2) w2++; length++; } return length; } string wordwrap(const char *source, int width, int indent, const colourinfo_t &cs, int *col) { // char *dp = dest; const char *sp = source, *wp; // source, dest, and start of source word pointers const char *sp = source, *wp; bool isstart = true; /* whether this is the first word on the line */ int bytes, spaces, n; signed int xleft = width-1; /* number of columns left on the line. * don't use the last column. */ if (col) { xleft -= *col; if (*col) isstart = 0; } string dbuf; while(*sp) { bytes = wordlength(sp); spaces = colour_strlenof(sp, bytes, cs); /* Spaces is the actual APPARENT WIDTH -- needs to be renamed, yes */ if((!isstart) && (spaces > xleft) && (spaces <= width)) { /* So here, if its TOO WIDE to fit in the remaining space, we reset to the beginning of the line. */ isstart = 1; xleft = width-1; dbuf += '\v'; /* change this to a soft-newline, if we want to go that route */ while (*sp==' ') sp++; if (*sp == ' ' || newline(*sp)) sp++; /* And here we have an inexplicable indent bit */ if(*sp && !(sp > source && newline(sp[-1]))) { for(n = 0; n < indent; n++) { dbuf += ' '; xleft--; } } continue; } /* Bytes is the number of actual CHARACTERS. Includes the first character, including ' ' and '\n' */ wp = sp; for(n = 0; (n < bytes) && *sp; n++) { /* This is where the actual word gets put in there */ dbuf += *sp++; if(newline(*(sp-1))) { isstart = 1; xleft = width-1; spaces-=2; /* so that we don't count \n as a character? */ indent=0; goto blah; } else if ((sp>=(source+2)) && (*(sp-2) == '^') && (*(sp-1) == 'Z')) { if ((indent = ((width-xleft)-1) + colour_strlenof(wp, n-1, cs)) < 0) indent = 0; if (indent > 2*width/3) indent = 2*width/3; } } xleft -= spaces; isstart = 0; blah: ; } /* xleft will be (width-1)-column */ if (col) *col = (width-1)-xleft; return dbuf; } void unwordwrap(char *dest, const char *source, int bufsize) { char *dp = dest; const char *sp = source; int length=1; if(bufsize < 1) { *dest = '\0'; } dest[bufsize-1] = '\0'; while(*sp && (length < bufsize)) { if(*sp == '\n') { if(*(sp+1) == '\n') { while(*sp == '\n') { *dp++ = '\n'; if(!(++length < bufsize)) return; sp++; } } else { if(*(++sp)) { *dp++ = ' '; } else { *dp++ = '\n'; } if(!(++length < bufsize)) return; } } else { *dp++ = *sp++; if(!(++length < bufsize)) return; } } *dp = '\0'; return; }