Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

Commit 52d5659f authored by rswindell's avatar rswindell

More UTF-8 goodness:

- Export all FIDOCTRL (other FTN kludge lines) to the QWK HEADERS.DAT file.
  These should already be imported if they exist, but were never added during
  export, so untested/new behavior. The control paragraph (kludge line) of
  specific interest here is the "CHRS" (charset) kludge we need for UTF-8.

- Don't use the QWK "newline" character (0xE3) when the message is UTF-8.
  Use bare-LF's instead. This is pretty untested at this point as I will need
  another QWKnet board to post or receive UTF-8 encoded messages to test,
  getting the code into CVS is the first step. At least for now, there's no
  opt-in/out for this behavior. If your BBS has UTF-8 encoded messages, some
  QWK nodes or offline readers may have trouble with packets which include
  those messages. Or they may work fine (but likely display garbage CP437
  chars in-place of the proper Unicode codepoint glyph).

- The beginning of UTF-8 input support in getstr() - which needs more work,
  particularly around character and word deletion and insertion.
- The internal message editor now supports UTF-8 messages and kind of somewhat
  supports inputting UTF-8 characters in message text.

New put/print text flag: P_AUTO_UTF8 which can auto-detect UTF8 strings and
do the "right thing" for the user's terminal. New associated sbbs_t method:
auto_utf8() which automatically sets P_UTF8 for any stirng that begins with
a UTF-8 BOM (ZWNBSP). Else, if the P_AUTO_UTF8 mode flag is set, then
it checks to see if the string contains invalid US-ASCII chars but valid UTF-8
sequences and then sets P_UTF8 accordingly. Used by putmsg() and bputs().

There's a new permuation of bprintf() which accepts a mode argument
(i.e. for P_UTF8) and passes it on to the new mode-capable bputs().
parent 3abfa2de
......@@ -43,8 +43,8 @@
void sbbs_t::redrwstr(char *strin, int i, int l, long mode)
{
cursor_left(i);
if(mode&K_MSG)
bprintf("%-*.*s",l,l,strin);
if(mode)
bprintf(mode, "%-*.*s",l,l,strin);
else
column+=rprintf("%-*.*s",l,l,strin);
cleartoeol();
......
......@@ -40,19 +40,35 @@
#include "petdefs.h"
#include "cp437defs.h"
char* sbbs_t::auto_utf8(const char* str, long* mode)
{
if(strncmp(str, "\xEF\xBB\xBF", 3) == 0) {
*mode |= P_UTF8;
return (char*)(str + 3);
}
if((*mode)&P_AUTO_UTF8) {
if(!str_is_ascii(str) && utf8_str_is_valid(str))
*mode |= P_UTF8;
}
return (char*)str;
}
/****************************************************************************/
/* Outputs a NULL terminated string locally and remotely (if applicable) */
/* Handles ctrl-a codes, Telnet-escaping, column & line count, auto-pausing */
/****************************************************************************/
int sbbs_t::bputs(const char *str)
int sbbs_t::bputs(const char *str, long mode)
{
int i;
ulong l=0;
long term = term_supports();
if(online==ON_LOCAL && console&CON_L_ECHO) /* script running as event */
return(lputs(LOG_INFO, str));
while(str[l] && online) {
str = auto_utf8(str, &mode);
size_t len = strlen(str);
while(l < len && online) {
if(str[l]==CTRL_A && str[l+1]!=0) {
l++;
if(str[l] == 'Z') /* EOF (uppercase 'Z' only) */
......@@ -79,7 +95,18 @@ int sbbs_t::bputs(const char *str)
continue;
}
}
outchar(str[l++]);
if(mode&P_PETSCII) {
if(term&PETSCII)
outcom(str[l++]);
else
petscii_to_ansibbs(str[l++]);
} else if((str[l]&0x80) && (mode&P_UTF8)) {
if(term&UTF8)
outcom(str[l++]);
else
l += utf8_to_cp437(str + l, len - l);
} else
outchar(str[l++]);
}
return(l);
}
......@@ -336,6 +363,23 @@ int sbbs_t::bprintf(const char *fmt, ...)
return(bputs(sbuf));
}
/****************************************************************************/
/* Performs printf() using bbs bputs function (with mode) */
/****************************************************************************/
int sbbs_t::bprintf(long mode, const char *fmt, ...)
{
va_list argptr;
char sbuf[4096];
if(strchr(fmt,'%')==NULL)
return(bputs(fmt, mode));
va_start(argptr,fmt);
vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
sbuf[sizeof(sbuf)-1]=0; /* force termination */
va_end(argptr);
return(bputs(sbuf, mode));
}
/****************************************************************************/
/* Performs printf() using bbs rputs function */
/****************************************************************************/
......
......@@ -46,6 +46,7 @@ char sbbs_t::getkey(long mode)
{
uchar ch,coldkey,c=0,spin=sbbs_random(5);
time_t last_telnet_cmd=0;
long term = term_supports();
if(online==ON_REMOTE && !input_thread_running)
online=FALSE;
......@@ -69,7 +70,7 @@ char sbbs_t::getkey(long mode)
}
if(mode&K_SPIN) {
if(useron.misc&NO_EXASCII) {
if(term&NO_EXASCII) {
switch(c++) {
case 0:
outchar(BS);
......
......@@ -85,7 +85,7 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode, const str_list_t h
i|=(cfg.color[clr_inputline]&0x77)>>4;
attr(i);
}
column+=rputs(str1);
column+=bputs(str1, P_AUTO_UTF8);
if(mode&K_EDIT && !(mode&(K_LINE|K_AUTODEL)))
cleartoeol(); /* destroy to eol */
}
......@@ -258,8 +258,10 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode, const str_list_t h
console|=CON_BACKSPACE;
break;
}
i--;
l--;
do {
i--;
l--;
} while((term&UTF8) && (i > 0) && (str1[i]&0x80) && (str1[i - 1]&0x80));
if(i!=l) { /* Deleting char in middle of line */
outchar(BS);
z=i;
......@@ -511,10 +513,12 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode, const str_list_t h
case TERM_KEY_DELETE: /* Ctrl-BkSpc (DEL) Delete current char */
if(i==l) { /* Backspace if end of line */
if(i) {
i--;
l--;
if(!(mode&K_NOECHO))
backspace();
do {
i--;
l--;
if(!(mode&K_NOECHO))
backspace();
} while((term&UTF8) && (i > 0) && (str1[i]&0x80) && (str1[i - 1]&0x80));
}
break;
}
......@@ -570,7 +574,7 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode, const str_list_t h
if(i<maxlen && ch>=' ') {
if(ch==' ' && (mode&K_TRIM) && i && str1[i-1] == ' ')
continue;
if(mode&K_UPRLWR) {
if((mode&K_UPRLWR) && !(ch&0x80)) {
if(!i || (i && (str1[i-1]==' ' || str1[i-1]=='-'
|| str1[i-1]=='.' || str1[i-1]=='_')))
ch=toupper(ch);
......@@ -592,8 +596,15 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode, const str_list_t h
#endif
}
str1[i++]=ch;
if(!(mode&K_NOECHO))
outchar(ch);
if(!(mode&K_NOECHO)) {
if((term&UTF8) && (ch&0x80)) {
if(i>l)
l=i;
redrwstr(str1, i, l, P_UTF8);
} else {
outchar(ch);
}
}
} else
outchar(BEL); /* Added at Angus McLeod's request */
}
......@@ -612,8 +623,8 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode, const str_list_t h
strcpy(strout,str1);
if(mode&K_TRIM)
truncsp(strout);
if((strip_invalid_attr(strout) || console&CON_INSERT) && !(mode&K_NOECHO))
redrwstr(strout,i,l,K_MSG);
if((strip_invalid_attr(strout) || (console&CON_INSERT)) && !(mode&K_NOECHO))
redrwstr(strout,i,l, P_AUTO_UTF8);
}
else
l=0;
......
......@@ -201,6 +201,12 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, smb_t* smb
fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p);
if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOTID,NULL))!=NULL)
fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p);
/* Misc. FTN-Kludge header fields: */
for(i = 0; i < msg->total_hfields; i++)
if(msg->hfield[i].type == FIDOCTRL)
fprintf(hdrs, "%s: %s\n"
,smb_hfieldtype(msg->hfield[i].type)
,(char*)msg->hfield_dat[i]);
/* Synchronet */
if((p=(char*)smb_get_hfield(msg,hfield_type=SMB_EDITOR,NULL))!=NULL)
......@@ -225,6 +231,17 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, smb_t* smb
fprintf(hdrs,"\n");
}
ulong getmsgtxt_mode = GETMSGTXT_ALL;
if(!(mode&QM_TO_QNET)) // Get just the plain-text portion of MIME-encoded messages
getmsgtxt_mode |= GETMSGTXT_PLAIN;
buf=smb_getmsgtxt(smb, msg, getmsgtxt_mode);
if(!buf)
return(0);
char qwk_newline = QWK_NEWLINE;
if(smb_msg_is_utf8(msg))
qwk_newline = '\n';
fprintf(qwk_fp,"%*s",QWK_BLOCK_LEN,""); /* Init header to space */
SAFECOPY(from,msg->from);
......@@ -244,7 +261,7 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, smb_t* smb
if(msg->hdr.attr&MSG_ANONYMOUS && !SYSOP)
SAFECOPY(from,text[Anonymous]);
else if((mode&QM_EXT) && strlen(from) > QWK_HFIELD_LEN) {
size+=fprintf(qwk_fp,"From: %.128s%c", from, QWK_NEWLINE);
size+=fprintf(qwk_fp,"From: %.128s%c", from, qwk_newline);
SAFECOPY(from,msg->from);
}
......@@ -259,7 +276,7 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, smb_t* smb
if(p) { /* Another hop */
p++;
SAFECOPY(to,"NETMAIL");
size+=fprintf(qwk_fp,"%.128s@%.128s%c",msg->to,p,QWK_NEWLINE);
size+=fprintf(qwk_fp,"%.128s@%.128s%c",msg->to,p,qwk_newline);
}
else
sprintf(to,"%.128s",msg->to);
......@@ -271,46 +288,46 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, smb_t* smb
sprintf(to,"%.128s@%.128s",msg->to,(char*)msg->to_net.addr);
}
if((mode&QM_EXT) && strlen(to) > QWK_HFIELD_LEN) {
size+=fprintf(qwk_fp,"To: %.128s%c", to, QWK_NEWLINE);
size+=fprintf(qwk_fp,"To: %.128s%c", to, qwk_newline);
if(msg->to_net.type==NET_QWK)
SAFECOPY(to,"NETMAIL");
else
SAFECOPY(to,msg->to);
}
if((mode&QM_EXT) && strlen(msg->subj) > QWK_HFIELD_LEN)
size+=fprintf(qwk_fp,"Subject: %.128s%c", msg->subj, QWK_NEWLINE);
size+=fprintf(qwk_fp,"Subject: %.128s%c", msg->subj, qwk_newline);
if(msg->from_net.type==NET_QWK && mode&QM_VIA && !msg->forwarded)
size+=fprintf(qwk_fp,"@VIA: %s%c"
,(char*)msg->from_net.addr,QWK_NEWLINE);
,(char*)msg->from_net.addr,qwk_newline);
if(mode&QM_MSGID && (uint)subnum!=INVALID_SUB) {
size+=fprintf(qwk_fp,"@MSGID: %s%c"
,msgid,QWK_NEWLINE);
,msgid,qwk_newline);
if(msg->reply_id) {
SAFECOPY(tmp,msg->reply_id);
truncstr(tmp," ");
size+=fprintf(qwk_fp,"@REPLY: %s%c"
,tmp,QWK_NEWLINE);
,tmp,qwk_newline);
} else if(msg->hdr.thread_back) {
memset(&remsg,0,sizeof(remsg));
remsg.hdr.number=msg->hdr.thread_back;
if(smb_getmsgidx(smb, &remsg))
size+=fprintf(qwk_fp,"@REPLY: <%s>%c",smb->last_error,QWK_NEWLINE);
size+=fprintf(qwk_fp,"@REPLY: <%s>%c",smb->last_error,qwk_newline);
else
size+=fprintf(qwk_fp,"@REPLY: %s%c"
,get_msgid(&cfg,subnum,&remsg,msgid,sizeof(msgid))
,QWK_NEWLINE);
,qwk_newline);
}
}
if(msg->hdr.when_written.zone && mode&QM_TZ)
size+=fprintf(qwk_fp,"@TZ: %04hx%c",msg->hdr.when_written.zone,QWK_NEWLINE);
size+=fprintf(qwk_fp,"@TZ: %04hx%c",msg->hdr.when_written.zone,qwk_newline);
if(msg->replyto!=NULL && mode&QM_REPLYTO)
size+=fprintf(qwk_fp,"@REPLYTO: %s%c"
,msg->replyto,QWK_NEWLINE);
,msg->replyto,qwk_newline);
p=0;
for(i=0;i<msg->total_hfields;i++) {
......@@ -319,17 +336,10 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, smb_t* smb
if(msg->hfield[i].type==FORWARDED && p) {
size+=fprintf(qwk_fp,"Forwarded from %s on %s%c",p
,timestr(*(time32_t *)msg->hfield_dat[i])
,QWK_NEWLINE);
,qwk_newline);
}
}
ulong getmsgtxt_mode = GETMSGTXT_ALL;
if(!(mode&QM_TO_QNET)) // Get just the plain-text portion of MIME-encoded messages
getmsgtxt_mode |= GETMSGTXT_PLAIN;
buf=smb_getmsgtxt(smb, msg, getmsgtxt_mode);
if(!buf)
return(0);
for(l=0;buf[l];l++) {
ch=buf[l];
......@@ -347,7 +357,7 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, smb_t* smb
else
tearwatch=0;
if(l && buf[l-1]=='\r') /* Replace CRLF with funky char */
ch=QWK_NEWLINE; /* but leave sole LF (soft-NL) alone */
ch=qwk_newline; /* but leave sole LF alone */
fputc(ch,qwk_fp);
size++;
continue;
......@@ -380,7 +390,7 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, smb_t* smb
ch=exascii_to_ascii_char(ch);
}
if(ch==QWK_NEWLINE) /* funky char */
if(ch==qwk_newline) /* funky char */
ch='*';
if(ch==CTRL_A) {
......@@ -471,20 +481,20 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, smb_t* smb
}
free(buf);
if(ch!=QWK_NEWLINE) {
fputc(QWK_NEWLINE,qwk_fp); /* make sure it ends in CRLF */
if(ch!=qwk_newline) {
fputc(qwk_newline,qwk_fp); /* make sure it ends in newline */
size++;
}
if(mode&QM_TAGLINE && !(cfg.sub[subnum]->misc&SUB_NOTAG)) {
if(!tear) /* no tear line */
SAFEPRINTF(str,"\1n---%c",QWK_NEWLINE); /* so add one */
SAFEPRINTF(str,"\1n---%c",qwk_newline); /* so add one */
else
SAFECOPY(str,"\1n");
if(cfg.sub[subnum]->misc&SUB_ASCII) ch='*';
else ch='';
safe_snprintf(tmp,sizeof(tmp)," %c \1g%.10s\1n %c %.127s%c"
,ch,VERSION_NOTICE,ch,cfg.sub[subnum]->tagline,QWK_NEWLINE);
,ch,VERSION_NOTICE,ch,cfg.sub[subnum]->tagline,qwk_newline);
strcat(str,tmp);
if(!(mode&QM_RETCTLA))
remove_ctrl_a(str,str);
......
......@@ -36,6 +36,7 @@
#include "sbbs.h"
#include "wordwrap.h"
#include "utf8.h"
/****************************************************************************/
/* Outputs a NULL terminated string with @-code parsing, */
......@@ -65,10 +66,7 @@ char sbbs_t::putmsg(const char *buf, long mode, long org_cols)
attr(LIGHTGRAY);
if(mode&P_NOPAUSE)
sys_status|=SS_PAUSEOFF;
if(strncmp(str, "\xEF\xBB\xBF", 3) == 0) {
mode |= P_UTF8;
str += 3;
}
str = auto_utf8(str, &mode);
size_t len = strlen(str);
long term = term_supports();
......
......@@ -305,6 +305,10 @@ bool sbbs_t::qwk_import_msg(FILE *qwk_fp, char *hdrblk, ulong blocks
kludges=strListInit();
char qwk_newline = QWK_NEWLINE;
if(smb_msg_is_utf8(msg))
qwk_newline = '\n';
for(k=0;k<(blocks-1)*QWK_BLOCK_LEN;k++) {
if(qwkbuf[k]==0)
continue;
......@@ -314,7 +318,7 @@ bool sbbs_t::qwk_import_msg(FILE *qwk_fp, char *hdrblk, ulong blocks
&& (strnicmp(qwkbuf+k,"To:",3)==0
|| strnicmp(qwkbuf+k,"From:",5)==0
|| strnicmp(qwkbuf+k,"Subject:",8)==0)))) {
if((p=strchr(qwkbuf+k, QWK_NEWLINE))==NULL) {
if((p=strchr(qwkbuf+k, qwk_newline))==NULL) {
body[bodylen++]=qwkbuf[k];
continue;
}
......@@ -332,7 +336,7 @@ bool sbbs_t::qwk_import_msg(FILE *qwk_fp, char *hdrblk, ulong blocks
col++;
continue;
}
if(qwkbuf[k]==QWK_NEWLINE) { /* expand QWK_NEWLINE to crlf */
if(qwkbuf[k]==qwk_newline) { /* expand QWK_NEWLINE to crlf */
if(!bodylen && !taillen) /* Ignore blank lines at top of message */
continue;
if(!taillen && col==3 && bodylen>=3 && body[bodylen-3]=='-'
......@@ -365,7 +369,7 @@ bool sbbs_t::qwk_import_msg(FILE *qwk_fp, char *hdrblk, ulong blocks
if(taillen) taillen--;
else bodylen--;
lastch=0;
continue;
continue;
}
lastch=qwkbuf[k];
if(taillen)
......
......@@ -703,11 +703,16 @@ public:
int bulkmailhdr(smb_t*, smbmsg_t*, uint usernum);
/* con_out.cpp */
int bputs(const char *str); /* BBS puts function */
int bputs(const char *str, long mode = 0); /* BBS puts function */
int rputs(const char *str, size_t len=0); /* BBS raw puts function */
int bprintf(const char *fmt, ...) /* BBS printf function */
#if defined(__GNUC__) // Catch printf-format errors
__attribute__ ((format (printf, 2, 3))); // 1 is 'this'
#endif
;
int bprintf(long mode, const char *fmt, ...)
#if defined(__GNUC__) // Catch printf-format errors
__attribute__ ((format (printf, 3, 4))); // 1 is 'this', 2 is 'mode'
#endif
;
int rprintf(const char *fmt, ...) /* BBS raw printf function */
......@@ -744,6 +749,7 @@ public:
size_t utf8_to_cp437(const char*, size_t);
int attr(int); /* Change text color/attributes */
void ctrl_a(char); /* Performs Ctrl-Ax attribute changes */
char* auto_utf8(const char*, long* mode);
/* getstr.cpp */
size_t getstr_offset;
......
......@@ -760,6 +760,7 @@ typedef enum { /* Values for xtrn_t.event */
#define P_PETSCII (1<<11) /* Message is native PETSCII */
#define P_WRAP (1<<12) /* Wrap/split long-lines, ungracefully */
#define P_UTF8 (1<<13) /* Message is UTF-8 */
#define P_AUTO_UTF8 (1<<14) /* Message may be UTF-8, auto-detect */
/* Bits in 'mode' for listfiles */
#define FL_ULTIME (1<<0) /* List files by upload time */
......
......@@ -162,9 +162,6 @@ bool sbbs_t::unpack_qwk(char *packet,uint hubnum)
blocks=1;
continue;
}
/*********************************/
/* public message on a sub-board */
/*********************************/
n=(uint)block[123]|(((uint)block[124])<<8); /* conference number */
qwk_new_msg(n, &msg,(char*)block,/* offset: */l,headers,/* parse_sender_hfields: */true);
......@@ -271,6 +268,9 @@ bool sbbs_t::unpack_qwk(char *packet,uint hubnum)
smb_stack(&smb,SMB_STACK_POP);
continue;
}
/*********************************/
/* public message on a sub-board */
/*********************************/
if((j = resolve_qwkconf(n, hubnum)) == INVALID_SUB) { /* ignore messages for subs not in config */
eprintf(LOG_NOTICE,"!Message from %s on UNKNOWN QWK CONFERENCE NUMBER: %u"
......
......@@ -389,7 +389,7 @@ bool sbbs_t::writemsg(const char *fname, const char *top, char *subj, long mode,
if(!fgets(str,sizeof(str),stream))
break;
quotestr(str);
bprintf("%3d: %.74s\r\n",i,str);
bprintf(P_AUTO_UTF8, "%4d: %.*s\r\n", i, cols-7, str);
i++;
}
continue;
......@@ -858,6 +858,7 @@ ulong sbbs_t::msgeditor(char *buf, const char *top, char *title)
char strin[TERM_COLS_MAX + 1];
char tmp[512];
str_list_t str;
long pmode = P_SAVEATR | P_NOATCODES | P_AUTO_UTF8;
if(cols < 2) {
errormsg(WHERE, ERR_CHK, "columns", cols);
......@@ -890,9 +891,9 @@ ulong sbbs_t::msgeditor(char *buf, const char *top, char *title)
}
CRLF;
}
putmsg(top,P_SAVEATR|P_NOATCODES);
putmsg(top, pmode);
for(line=0;line<lines && !msgabort();line++) { /* display lines in buf */
putmsg(str[line],P_SAVEATR|P_NOATCODES);
putmsg(str[line], pmode);
cleartoeol(); /* delete to end of line */
CRLF;
}
......@@ -924,7 +925,7 @@ ulong sbbs_t::msgeditor(char *buf, const char *top, char *title)
if(console&CON_BACKSPACE && strin[0] == 0) {
strListRemove(&str, line);
for(i = line; str[i]; i++) {
putmsg(str[i], P_SAVEATR|P_NOATCODES);
putmsg(str[i], pmode);
cleartoeol();
newline();
}
......@@ -1023,7 +1024,7 @@ ulong sbbs_t::msgeditor(char *buf, const char *top, char *title)
strListFreeStrings(str);
line=0;
lines=0;
putmsg(top,P_SAVEATR|P_NOATCODES);
putmsg(top, pmode);
continue;
}
else if(toupper(strin[1])=='L') { /* list message */
......@@ -1032,7 +1033,7 @@ ulong sbbs_t::msgeditor(char *buf, const char *top, char *title)
linenums = !noyes(text[WithLineNumbersQ]);
CRLF;
attr(LIGHTGRAY);
putmsg(top,P_SAVEATR|P_NOATCODES);
putmsg(top, pmode);
if(str[0] == NULL) {
continue;
}
......@@ -1041,10 +1042,10 @@ ulong sbbs_t::msgeditor(char *buf, const char *top, char *title)
while(str[j] != NULL && !msgabort()) {
if(linenums) { /* line numbers */
SAFEPRINTF3(tmp,"%3d: %-.*s", j+1, (int)(cols-6), str[j]);
putmsg(tmp,P_SAVEATR|P_NOATCODES);
putmsg(tmp, pmode);
}
else
putmsg(str[j],P_SAVEATR|P_NOATCODES);
putmsg(str[j], pmode);
cleartoeol(); /* delete to end of line */
CRLF;
j++;
......@@ -1081,7 +1082,7 @@ ulong sbbs_t::msgeditor(char *buf, const char *top, char *title)
line++;
strListInsert(&str, "", line);
for(i = line; str[i]; i++) {
putmsg(str[i], P_SAVEATR|P_NOATCODES);
putmsg(str[i], pmode);
cleartoeol();
newline();
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment