--- sbbs/src/sbbs3/str_util.c 2018/04/24 16:41:24 1.1.1.1 +++ sbbs/src/sbbs3/str_util.c 2018/04/24 16:43:48 1.1.1.2 @@ -2,13 +2,13 @@ /* Synchronet string utility routines */ -/* $Id: str_util.c,v 1.1.1.1 2018/04/24 16:41:24 root Exp $ */ +/* $Id: str_util.c,v 1.1.1.2 2018/04/24 16:43:48 root Exp $ */ /**************************************************************************** * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2010 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -38,147 +38,214 @@ #include "sbbs.h" /****************************************************************************/ -/* Removes ctrl-a codes from the string 'instr' */ +/* For all the functions that take a 'dest' argument, pass NULL to have the */ +/* function malloc the buffer for you and return it. */ /****************************************************************************/ -char* DLLCALL remove_ctrl_a(char *instr, char *outstr) + +/****************************************************************************/ +/* Removes ctrl-a codes from the string 'str' */ +/****************************************************************************/ +char* DLLCALL remove_ctrl_a(const char *str, char *dest) { - char str[1024],*p; - uint i,j; + int i,j; - for(i=j=0;instr[i] && j=' ') - tmp[j++]=str[i]; - } - if(i!=j) { - tmp[j]=0; - strcpy(str,tmp); + dest[j++]=str[i]; } - return(str); + dest[j]=0; + return dest; } -char* DLLCALL strip_exascii(char *str) +char* DLLCALL strip_exascii(const char *str, char* dest) { - char tmp[1024]; - int i,j; + int i,j; - for(i=j=0;str[i] && j<(int)sizeof(tmp)-1;i++) + if(dest==NULL && (dest=strdup(str))==NULL) + return NULL; + for(i=j=0;str[i];i++) if(!(str[i]&0x80)) - tmp[j++]=str[i]; - tmp[j]=0; - strcpy(str,tmp); - return(str); + dest[j++]=str[i]; + dest[j]=0; + return dest; } -char* DLLCALL prep_file_desc(char *str) +char* DLLCALL strip_space(const char *str, char* dest) { - char tmp[1024]; - int i,j; + int i,j; + if(dest==NULL && (dest=strdup(str))==NULL) + return NULL; for(i=j=0;str[i];i++) - if(str[i]==CTRL_A && str[i+1]!=0) + if(!isspace((unsigned char)str[i])) + dest[j++]=str[i]; + dest[j]=0; + return dest; +} + +char* DLLCALL prep_file_desc(const char *str, char* dest) +{ + int i,j; + + if(dest==NULL && (dest=strdup(str))==NULL) + return NULL; + for(i=j=0;str[i];i++) + if(str[i]==CTRL_A && str[i+1]!=0) { i++; - else if(j && str[i]<=' ' && tmp[j-1]==' ') + if(toupper(str[i])=='Z') /* EOF */ + break; + /* convert non-destructive backspace to a destructive backspace */ + if(str[i]=='<' && j) + j--; + } + else if(j && str[i]<=' ' && dest[j-1]==' ') continue; - else if(i && !isalnum(str[i]) && str[i]==str[i-1]) + else if(i && !isalnum((unsigned char)str[i]) && str[i]==str[i-1]) continue; else if((uchar)str[i]>=' ') - tmp[j++]=str[i]; + dest[j++]=str[i]; else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF)) - tmp[j++]=' '; - tmp[j]=0; - strcpy(str,tmp); - return(str); + dest[j++]=' '; + dest[j]=0; + return dest; } /****************************************************************************/ -/* Pattern matching string search of 'insearchof' in 'fname'. */ +/* Pattern matching string search of 'insearchof' in 'string'. */ /****************************************************************************/ -BOOL DLLCALL findstr(char* insearchof, char* fname) +BOOL DLLCALL findstr_in_string(const char* insearchof, char* string) { char* p; - char str[128]; + char str[256]; char search[81]; int c; int i; - BOOL found; - FILE* stream; + BOOL found=FALSE; - if((stream=fopen(fname,"r"))==NULL) - return(FALSE); + if(string==NULL || insearchof==NULL) + return(FALSE); SAFECOPY(search,insearchof); strupr(search); + SAFECOPY(str,string); - found=FALSE; + p=str; + SKIP_WHITESPACE(p); - while(!feof(stream) && !ferror(stream) && !found) { - if(!fgets(str,sizeof(str),stream)) - break; - - found=FALSE; + if(*p==';') /* comment */ + return(FALSE); - p=str; - while(*p && *p<=' ') p++; /* Skip white-space */ + if(*p=='!') { /* !match */ + found=TRUE; + p++; + } - if(*p==';') /* comment */ - continue; + truncsp(p); + c=strlen(p); + if(c) { + c--; + strupr(p); + if(p[c]=='~') { + p[c]=0; + if(strstr(search,p)) + found=!found; + } + + else if(p[c]=='^' || p[c]=='*') { + p[c]=0; + if(!strncmp(p,search,c)) + found=!found; + } - if(*p=='!') { /* !match */ - found=TRUE; - p++; + else if(p[0]=='*') { + i=strlen(search); + if(i.can in the TEXT directory for matches */ /* Returns TRUE if found in list, FALSE if not. */ /****************************************************************************/ -BOOL DLLCALL trashcan(scfg_t* cfg, char* insearchof, char* name) +BOOL DLLCALL trashcan(scfg_t* cfg, const char* insearchof, const char* name) { char fname[MAX_PATH+1]; - sprintf(fname,"%s%s.can",cfg->text_dir,name); - return(findstr(insearchof,fname)); + return(findstr(insearchof,trashcan_fname(cfg,name,fname,sizeof(fname)))); +} + +/****************************************************************************/ +char* DLLCALL trashcan_fname(scfg_t* cfg, const char* name, char* fname, size_t maxlen) +{ + safe_snprintf(fname,maxlen,"%s%s.can",cfg->text_dir,name); + return fname; +} + +/****************************************************************************/ +str_list_t DLLCALL trashcan_list(scfg_t* cfg, const char* name) +{ + char fname[MAX_PATH+1]; + FILE* fp; + str_list_t list; + + if((fp=fopen(trashcan_fname(cfg, name, fname, sizeof(fname)),"r"))==NULL) + return NULL; + + list=strListReadFile(fp,NULL,255); + + fclose(fp); + + return list; } /****************************************************************************/ /* Returns the number of characters in 'str' not counting ctrl-ax codes */ /* or the null terminator */ /****************************************************************************/ -int bstrlen(char *str) +size_t bstrlen(const char *str) { - int i=0; + size_t i=0; while(*str) { - if(*str==CTRL_A) + if(*str==CTRL_A) { str++; - else + if(toupper(*str)=='Z') /* EOF */ + break; + if(*str=='[') + i=0; + else if(*str=='<' && i) + i--; + } else i++; if(!(*str)) break; - str++; } + str++; + } return(i); } @@ -228,7 +325,8 @@ char* DLLCALL ultoac(ulong l, char *stri for(k=1;i>-1;k++) { string[j--]=str[i--]; if(j>0 && !(k%3)) - string[j--]=','; } + string[j--]=','; + } return(string); } @@ -268,7 +366,7 @@ char* DLLCALL rot13(char* str) /****************************************************************************/ /* Puts a backslash on path strings if not just a drive letter and colon */ /****************************************************************************/ -void backslashcolon(char *str) +char* backslashcolon(char *str) { int i; @@ -277,12 +375,14 @@ void backslashcolon(char *str) str[i]=PATH_DELIM; str[i+1]=0; } + + return str; } /****************************************************************************/ /* Compares pointers to pointers to char. Used in conjuction with qsort() */ /****************************************************************************/ -int pstrcmp(char **str1, char **str2) +int pstrcmp(const char **str1, const char **str2) { return(strcmp(*str1,*str2)); } @@ -290,7 +390,7 @@ int pstrcmp(char **str1, char **str2) /****************************************************************************/ /* Returns the number of characters that are the same between str1 and str2 */ /****************************************************************************/ -int strsame(char *str1, char *str2) +int strsame(const char *str1, const char *str2) { int i,j=0; @@ -316,7 +416,7 @@ char *hexplus(uint num, char *str) /* Converts an ASCII Hex string into an ulong */ /* by Steve Deppe (Ille Homine Albe) */ /****************************************************************************/ -ulong ahtoul(char *str) +ulong ahtoul(const char *str) { ulong l,val=0; @@ -328,7 +428,7 @@ ulong ahtoul(char *str) /****************************************************************************/ /* Converts hex-plus string to integer */ /****************************************************************************/ -uint hptoi(char *str) +uint hptoi(const char *str) { char tmp[128]; uint i; @@ -342,11 +442,10 @@ uint hptoi(char *str) } /****************************************************************************/ -/* Returns 1 if a is a valid ctrl-a code, 0 if it isn't. */ +/* Returns TRUE if a is a valid ctrl-a "attribute" code, FALSE if it isn't. */ /****************************************************************************/ -BOOL DLLCALL validattr(char a) +BOOL DLLCALL valid_ctrl_a_attr(char a) { - switch(toupper(a)) { case '+': /* push attr */ case '-': /* pop attr */ @@ -357,10 +456,8 @@ BOOL DLLCALL validattr(char a) case 'H': /* high fg */ case 'I': /* blink */ case 'K': /* black fg */ - case 'L': /* cls */ case 'M': /* magenta fg */ case 'N': /* normal */ - case 'P': /* pause */ case 'R': /* red fg */ case 'W': /* white fg */ case 'Y': /* yellow fg */ @@ -378,29 +475,94 @@ BOOL DLLCALL validattr(char a) } /****************************************************************************/ -/* Strips invalid Ctrl-Ax sequences from str */ +/* Returns TRUE if a is a valid QWKnet compatible Ctrl-A code, else FALSE */ +/****************************************************************************/ +BOOL DLLCALL valid_ctrl_a_code(char a) +{ + switch(toupper(a)) { + case 'P': /* Pause */ + case 'L': /* CLS */ + case ',': /* 100ms delay */ + return TRUE; + } + return valid_ctrl_a_attr(a); +} + +/****************************************************************************/ +/****************************************************************************/ +char DLLCALL ctrl_a_to_ascii_char(char a) +{ + switch(toupper(a)) { + case 'L': /* cls */ + return FF; + case '<': /* backspace */ + return '\b'; + case '[': /* CR */ + return '\r'; + case ']': /* LF */ + return '\n'; + } + return 0; +} + +/****************************************************************************/ +/* Strips invalid Ctrl-Ax "attribute" sequences from str */ /* Returns number of ^A's in line */ /****************************************************************************/ -size_t DLLCALL strip_invalid_attr(char *strin) +size_t DLLCALL strip_invalid_attr(char *str) { - char str[1024]; - size_t a,c,d; + char* dest; + size_t a,c,d; - for(a=c=d=0;strin[c] && d