232 lines
7.9 KiB
C++
232 lines
7.9 KiB
C++
|
|
// ------------------------------------------------------------------
|
|
// GoldED+
|
|
// Copyright (C) 1990-1999 Odinn Sorensen
|
|
// Copyright (C) 1999-2000 Alexander S. Aganichev
|
|
// ------------------------------------------------------------------
|
|
// 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., 59 Temple Place, Suite 330, Boston,
|
|
// MA 02111-1307 USA
|
|
// ------------------------------------------------------------------
|
|
// $Id$
|
|
// ------------------------------------------------------------------
|
|
// Container class.
|
|
// ------------------------------------------------------------------
|
|
|
|
#include "golded.h"
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
static bool strncont(const char *beginword, const char *stylestopchars, int n)
|
|
{
|
|
for(; (n > 0) and (*beginword != NUL); n--, beginword++) {
|
|
if(strchr(stylestopchars, *beginword) != NULL)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
static bool in_ftn_domained_address(const char *ptr, const char *txt) {
|
|
|
|
while((ptr != txt) and (not isspace(*ptr) and not isalpha(*ptr))) {
|
|
if(isdigit(ptr[0]) and ((ptr[1] == ':') or (ptr[1] == '/')) and isdigit(ptr[2]))
|
|
return true;
|
|
--ptr;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
const char *url_begin(const char *ptr) {
|
|
|
|
if(strnieql(ptr, "http://", 7))
|
|
return ptr+7;
|
|
if(strnieql(ptr, "https://", 8))
|
|
return ptr+8;
|
|
if(strnieql(ptr, "ftp://", 6))
|
|
return ptr+6;
|
|
if(strnieql(ptr, "www.", 4))
|
|
return ptr+4;
|
|
if(strnieql(ptr, "ftp.", 4))
|
|
return ptr+4;
|
|
if(strnieql(ptr, "mailto:", 7))
|
|
return ptr+7;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
inline bool isstylechar(char c) {
|
|
|
|
if(strchr(CFG->stylecodestops, c) != NULL)
|
|
return false;
|
|
return (c == '*') or (c == '/') or (c == '_') or (c == '#');
|
|
}
|
|
|
|
void Container::StyleCodeHighlight(const char* text, int row, int col, bool dohide, int color) {
|
|
|
|
uint sclen = 0;
|
|
const char* txptr = text;
|
|
char buf[200];
|
|
const char* ptr = text;
|
|
const char* stylemargins = " -|\\"; // we probably have to make a keyword for it
|
|
char* punctchars = CFG->stylecodepunct;
|
|
char* stylestopchars = CFG->stylecodestops;
|
|
char prevchar = ' ';
|
|
bool usestylies = dohide or CFG->usestylies;
|
|
|
|
if(usestylies or CFG->highlighturls) {
|
|
while(*ptr) {
|
|
if(usestylies and isstylechar(*ptr)) {
|
|
if(strchr(punctchars, prevchar)) {
|
|
int bb = 0, bi = 0, bu = 0, br = 0;
|
|
const char* beginstyle = ptr;
|
|
while(isstylechar(*ptr)) {
|
|
switch(*ptr) {
|
|
case '*': bb++; break;
|
|
case '/': bi++; break;
|
|
case '_': bu++; break;
|
|
case '#': br++; break;
|
|
}
|
|
ptr++;
|
|
}
|
|
if((bb <= 1) and (bi <= 1) and (br <= 1) and (bu <= 1) and *ptr) {
|
|
const char* beginword = ptr; // _/*>another*/_
|
|
const char* end = ptr;
|
|
do {
|
|
end = strpbrk(++end, punctchars);
|
|
} while ((end != NULL) and not isstylechar(*(end-1)));
|
|
if(end == NULL)
|
|
end = ptr+strlen(ptr);
|
|
const char* endstyle = end-1; // _/*another*/>_
|
|
if(isstylechar(*endstyle) and not strchr(stylemargins, *beginword)) {
|
|
const char* endword = endstyle;
|
|
int eb = 0, ei = 0, eu = 0, er = 0;
|
|
while(isstylechar(*endword)) {
|
|
switch(*endword) {
|
|
case '*': eb++; break;
|
|
case '/': ei++; break;
|
|
case '_': eu++; break;
|
|
case '#': er++; break;
|
|
}
|
|
endword--;
|
|
} // _/*anothe>r*/_
|
|
if(endword >= beginword and not strchr(stylemargins, *endword)) {
|
|
if((bb == eb) and (bi == ei) and (bu == eu) and (br == er)) {
|
|
bool style_stops_present = strncont(beginword, stylestopchars, endword-beginword);
|
|
if(not style_stops_present) {
|
|
int colorindex = (bb ? 1 : 0) | (bi ? 2 : 0) | (bu ? 4 : 0) | (br ? 8 : 0);
|
|
strxcpy(buf, txptr, (uint)(beginstyle-txptr)+1);
|
|
prints(row, col+sclen, color, buf);
|
|
sclen += strlen(buf);
|
|
if(dohide)
|
|
strxcpy(buf, beginword, (uint)(endword-beginword)+2);
|
|
else
|
|
strxcpy(buf, beginstyle, (uint)(endstyle-beginstyle)+2);
|
|
prints(row, col+sclen, C_STYLE[colorindex], buf);
|
|
sclen += strlen(buf);
|
|
txptr = end;
|
|
ptr = end-1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(CFG->highlighturls) {
|
|
const char *begin;
|
|
|
|
if((begin = url_begin(ptr)) != NULL) {
|
|
const char *end = begin+strcspn(begin, " \t\"\'<>()[]");
|
|
|
|
if(ispunct(end[-1]) and (end[-1] != '/'))
|
|
--end;
|
|
if(begin < end) {
|
|
strxcpy(buf, txptr, (uint)(ptr-txptr)+1);
|
|
prints(row, col+sclen, color, buf);
|
|
sclen += strlen(buf);
|
|
strxcpy(buf, ptr, (uint)(end-ptr)+1);
|
|
prints(row, col+sclen, C_READU, buf);
|
|
sclen += strlen(buf);
|
|
txptr = end;
|
|
ptr = end-1;
|
|
}
|
|
}
|
|
else if(((ptr == text) or not in_ftn_domained_address(ptr, text)) and
|
|
(isascii(*ptr) and not isspace(*ptr) and not ispunct(*ptr) and
|
|
((ptr == text) or (not isxalnum(ptr[-1]) and (ptr[-1] != '@'))))) {
|
|
// try to guess e-mail address...
|
|
const char *commerce_at = NULL;
|
|
|
|
if(*ptr == '\"') {
|
|
const char *pair_quote = strchr(ptr+1, '\"');
|
|
if(pair_quote != NULL) {
|
|
commerce_at = pair_quote+1;
|
|
}
|
|
}
|
|
else {
|
|
commerce_at = strpbrk(ptr, " \t:/@");
|
|
}
|
|
if((commerce_at != NULL) and (*commerce_at == '@')) {
|
|
int dots_found = 0;
|
|
++commerce_at;
|
|
while((*commerce_at != NUL) and (isalnum(*commerce_at) or (*commerce_at == '.') or (*commerce_at == '-'))) {
|
|
if(*commerce_at == '.')
|
|
++dots_found;
|
|
++commerce_at;
|
|
}
|
|
while((commerce_at[-1] == '.') or (commerce_at[-1] == '-')) {
|
|
--commerce_at;
|
|
if(*commerce_at == '.')
|
|
--dots_found;
|
|
}
|
|
if(dots_found) {
|
|
strxcpy(buf, txptr, (uint)(ptr-txptr)+1);
|
|
prints(row, col+sclen, color, buf);
|
|
sclen += strlen(buf);
|
|
strxcpy(buf, ptr, (uint)(commerce_at-ptr)+1);
|
|
prints(row, col+sclen, C_READU, buf);
|
|
sclen += strlen(buf);
|
|
txptr = commerce_at;
|
|
ptr = commerce_at-1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(*ptr)
|
|
prevchar = *ptr++;
|
|
}
|
|
}
|
|
if(*txptr) {
|
|
prints(row, col+sclen, color, txptr);
|
|
sclen += strlen(txptr);
|
|
}
|
|
uint splen = strlen(text) - sclen;
|
|
if(splen) {
|
|
memset(buf, ' ', splen); buf[splen] = NUL;
|
|
prints(row, col+sclen, color, buf);
|
|
}
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|