This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-goldedplus/golded3/gecarb.cpp

485 lines
14 KiB
C++
Raw Normal View History

2000-02-25 11:04:07 +00:00
// ------------------------------------------------------------------
// 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$
// ------------------------------------------------------------------
// Carbon Copy.
// ------------------------------------------------------------------
#include <golded.h>
// ------------------------------------------------------------------
void AddCCList(const char *ptr, bool cchide, GMsg* msg, GMsg** carbon, int &cc, Area* A, Area* AA, int &xc2to)
{
Addr addr;
char name[256];
addr.reset_fast();
strtrim(strcpy(name, strskip_wht(ptr)));
(*carbon) = (GMsg*)throw_realloc((*carbon), sizeof(GMsg)*(cc+2));
(*carbon)[cc] = *msg;
(*carbon)[cc].dest.reset_fast();
(*carbon)[cc].odest.reset_fast();
(*carbon)[cc].attr.nwm1();
if(strchr(name, ':')) {
char* d = strchr(name, '@');
if(d) *d = NUL;
}
if(strchr(name, '@')) {
ParseInternetAddr(name, (*carbon)[cc].realto, (*carbon)[cc].iaddr);
strxcpy((*carbon)[cc].to, (*carbon)[cc].iaddr, sizeof(Name));
}
else {
(*carbon)[cc].iaddr[0] = NUL;
strxcpy((*carbon)[cc].to, name, sizeof(Name));
}
HeaderView->Use(AA, &(*carbon)[cc]);
HeaderView->Paint();
if(AA->isnet()) {
gsetaddr toname, toaddr, fromaddr;
IAdr addr1, addr2;
addr = (*carbon)[cc].orig;
toname.buf = name; toname.update = false;
toaddr.buf = addr1; toaddr.update = false; *addr1 = NUL;
fromaddr.buf = addr2; fromaddr.update = false; *addr2 = NUL;
if(set_to_address(&(*carbon)[cc], &toname, &toaddr, &fromaddr, NULL, 6, LNG->DestinationCC, true))
addr.net = 0;
else
addr.set(addr1, (*carbon)[cc].odom);
}
else
addr = AA->Aka().addr;
update_statusline(LNG->ProcessCC);
if(addr.net or AA->islocal()) {
// Create a CC if either address or name is different than the original.
if(memcmp(&addr, &msg->dest, sizeof(Addr)) or stricmp(name, msg->to) or (A != AA and not xc2to++)) {
(*carbon)[cc].odest = addr;
(*carbon)[cc].dest = addr;
if(cchide)
(*carbon)[cc].attr.tou0();
else
(*carbon)[cc].attr.tou1();
strxcpy((*carbon)[cc].to, name, sizeof(Name));
cc++;
}
}
}
// ------------------------------------------------------------------
int DoCarboncopy(GMsg* msg, GMsg** carbon) {
int n, cc = 0;
2000-03-22 17:59:18 +00:00
const char* ptr;
2000-02-25 11:04:07 +00:00
Attr attr;
bool cchide;
bool ignorecc = false;
char buf[256], buf2[256];
Line* line;
Line* newline;
Line* ccline = NULL;
int margintext;
if(AA->isinternet() and CFG->soupexportmargin <= CFG->dispmargin)
margintext = CFG->soupexportmargin;
else
margintext = CFG->dispmargin;
// Insert empty line at the top first for practical purposes
2000-10-24 05:02:25 +00:00
newline = new Line();
2000-03-22 17:59:18 +00:00
throw_xnew(newline);
2000-02-25 11:04:07 +00:00
msg->lin = newline = line = InsertLine(newline, msg->lin, DIR_PREV);
// Deal with carbon copies
Area* A = AA;
if(AA->isecho()) {
AA = AL.AreaEchoToPtr(AA->Areareplyto());
if(AA and (AA != A)) {
AA->Open();
}
else
AA = A;
}
attr = msg->attr;
if(not AA->isecho() and line) {
bool ask = true;
int xc2to = 0;
do {
2000-03-22 17:59:18 +00:00
ptr = newline->txt.c_str();
if(strnieql(ptr, "CC:", 3)) {
2000-02-25 11:04:07 +00:00
if(not ignorecc) {
if(ask) {
msg->attr.nwm1();
AttrAdd(&msg->attr, &CFG->attribscc);
HeaderView->Use(AA, msg);
HeaderView->Paint();
GMenuCarbon MenuCarbon;
ignorecc = MenuCarbon.Run(msg) ? false : true;
if(ignorecc) // Do not process carbon copies
2000-02-25 11:04:07 +00:00
break;
if(newline)
ccline = newline->prev; // Store the position of first line
else
ccline = NULL;
ask = false;
}
update_statusline(LNG->ProcessCC);
gstrarray xposts;
tokenize(xposts, ptr+3, ",");
for(int i=0; i < xposts.size(); i++) {
ptr = strskip_wht(strcpy(buf, xposts[i].c_str()));
if(*ptr == '#') {
++ptr;
cchide = true;
}
else
cchide = false;
if(*ptr == '@') {
FILE* fp = fsopen(AddPath(CFG->goldpath, ++ptr), "rt", CFG->sharemode);
if(fp) {
gstrarray fc;
while(fgets(buf, sizeof(buf), fp))
tokenize(fc, buf, ",\n");
fclose(fp);
for(int j = 0; j < fc.size(); j++)
if(fc[j][0] != '@') // we don't like nesting!
AddCCList(fc[j].c_str(), cchide, msg, carbon, cc, A, AA, xc2to);
}
}
else
AddCCList(ptr, cchide, msg, carbon, cc, A, AA, xc2to);
}
if(CFG->carboncopylist != CC_KEEP) {
newline = DeleteLine(newline); // Now at the next line
if(newline and newline->prev)
newline = newline->prev; // Go back one line
}
}
}
newline = newline->next;
} while(newline != NULL);
// Fix the CC list in the message
if(not ignorecc and cc and ccline) {
std::string temp;
2000-02-25 11:04:07 +00:00
switch(CFG->carboncopylist) {
case CC_REMOVE:
// No list
break;
case CC_KEEP:
// Keep list as it was entered
break;
case CC_HIDDEN:
2000-10-20 11:14:13 +00:00
ccline = msg->lin;
2000-02-25 11:04:07 +00:00
if(A == AA) {
sprintf(buf, "\001CC: %s %s", msg->To(), msg->dest.make_string(temp).c_str());
ccline = AddKludge(ccline, buf);
}
for(n=0; n<cc; n++) {
if((*carbon)[n].attr.tou()) {
sprintf(buf, "\001CC: %s %s", (*carbon)[n].To(), (*carbon)[n].dest.make_string(temp).c_str());
ccline = AddKludge(ccline, buf);
2001-11-13 11:35:21 +00:00
(*carbon)[n].attr.tou0();
2000-02-25 11:04:07 +00:00
}
}
break;
case CC_VISIBLE:
sprintf(buf2, LNG->CCTo, LNG->ListCC);
if(A == AA) {
sprintf(buf, buf2, msg->To(), msg->dest.make_string(temp).c_str());
ccline = AddLine(ccline, buf);
}
for(n=0; n<cc; n++) {
if((*carbon)[n].attr.tou()) {
sprintf(buf, buf2, (*carbon)[n].To(), (*carbon)[n].dest.make_string(temp).c_str());
ccline = AddLine(ccline, buf);
2001-11-13 11:35:21 +00:00
(*carbon)[n].attr.tou0();
2000-02-25 11:04:07 +00:00
}
}
break;
case CC_NAMES:
// Expand in line
{
std::string hline = "";
2000-02-25 11:04:07 +00:00
int line_items = 0;
2001-12-23 10:55:01 +00:00
margintext -= strlen(LNG->CCTo) - 2; // - "%s"
2000-02-25 11:04:07 +00:00
if(A == AA) {
hline += msg->To();
++line_items;
}
2001-11-13 11:35:21 +00:00
for(n=0; n < cc; n++) {
2000-02-25 11:04:07 +00:00
if((*carbon)[n].attr.tou()) {
const char *user = (*carbon)[n].To();
if((hline.length() + strlen(user) + 2 > margintext) and line_items) {
sprintf(buf, LNG->CCTo, hline.c_str());
ccline = AddLine(ccline, buf);
line_items = 0;
hline = "";
}
if(line_items != 0)
hline += ", ";
hline += user;
++line_items;
2001-11-13 11:35:21 +00:00
(*carbon)[n].attr.tou0();
2000-02-25 11:04:07 +00:00
}
2001-11-13 11:35:21 +00:00
}
2000-02-25 11:04:07 +00:00
if(line_items) {
sprintf(buf, LNG->CCTo, hline.c_str());
ccline = AddLine(ccline, buf);
}
}
break;
}
}
}
// Reset line pointer
msg->lin = DeleteLine(msg->lin); // Delete the empty top line again
msg->attr = attr;
if(*carbon and not cc)
throw_release(*carbon);
if(A != AA) {
AA->Close();
AA = A;
}
return cc;
}
// ------------------------------------------------------------------
static bool AddXCAreas(const char* mask, bool attr, std::vector<int> &postareas, std::vector<bool> &postareas_attrs, int local_xps) {
2000-02-25 11:04:07 +00:00
bool rv = false;
for(int j=0; j < AL.size(); j++) {
if(not AL[j]->isseparator() and strwild(AL[j]->echoid(), mask)) {
if(strieql(AA->echoid(), AL[j]->echoid()))
rv = attr;
else {
int i;
// We don't want twice crossposting to same echo...
for(i=local_xps; i < postareas.size(); i++)
if(postareas[i] == j)
break;
if(i == postareas.size()) {
postareas.push_back(j);
postareas_attrs.push_back(attr);
}
}
}
}
return rv;
}
// ------------------------------------------------------------------
void DoCrosspost(GMsg* msg, std::vector<int> &postareas) {
2000-02-25 11:04:07 +00:00
if(CFG->crosspost == NO)
return;
char buf[256];
2000-03-22 17:59:18 +00:00
const char *ptr;
2000-02-25 11:04:07 +00:00
bool ignorexc = false;
Line* newline;
Line* xcline = NULL;
int margintext;
bool xphide;
int local_xps = postareas.size();
std::vector<bool> postareas_attrs(local_xps);
2000-02-25 11:04:07 +00:00
bool hideoriginal = false;
// Insert empty line at the top first for practical purposes
2000-10-24 05:02:25 +00:00
newline = new Line();
2000-03-22 17:59:18 +00:00
throw_xnew(newline);
2000-02-25 11:04:07 +00:00
msg->lin = newline = InsertLine(newline, msg->lin, DIR_PREV);
// Deal with carbon copies
if(AA->isinternet() and CFG->soupexportmargin <= CFG->dispmargin)
margintext = CFG->soupexportmargin;
else
margintext = CFG->dispmargin;
// Next line is invalid if someone uses format chars like %-20s
// but we couldn't predict everything...
margintext -= strlen(LNG->Crosspostedin) - 2;
if(newline) {
bool ask = true;
do {
if(not (newline->type & (GLINE_KLUDGE|GLINE_TEAR|GLINE_ORIG))) {
2000-03-22 17:59:18 +00:00
ptr = newline->txt.c_str();
if(not ignorexc and (strnieql(ptr, "XC:", 3) or strnieql(ptr, "XP:", 3))) {
2000-02-25 11:04:07 +00:00
if(ask) {
GMenuCross MenuCross;
ignorexc = (CFG->crosspost != ASK) or MenuCross.Run(msg) ? false : true;
if(ignorexc) // Do not process crossposting
break;
if(newline)
xcline = newline->prev; // Store the position of first line
else
xcline = NULL;
ask = false;
}
gstrarray xposts;
tokenize(xposts, ptr+3);
for(int i=0; i < xposts.size(); i++) {
ptr = strcpy(buf, xposts[i].c_str());
if(*ptr == '#') {
++ptr;
xphide = true;
}
else
xphide = false;
if(*ptr == '@') {
FILE* fp = fsopen(AddPath(CFG->goldpath, ++ptr), "rt", CFG->sharemode);
if(fp) {
gstrarray fc;
while(fgets(buf, sizeof(buf), fp))
tokenize(fc, buf, ", \n");
fclose(fp);
for(int j = 0; j < fc.size(); j++)
if(fc[j][0] != '@') // we don't like nesting!
hideoriginal = AddXCAreas(fc[j].c_str(), xphide, postareas, postareas_attrs, local_xps) or hideoriginal;
}
}
else
hideoriginal = AddXCAreas(ptr, xphide, postareas, postareas_attrs, local_xps) or hideoriginal;
}
if(CFG->crosspostlist != CC_KEEP) {
newline = DeleteLine(newline); // Now at the next line
if(newline and newline->prev)
newline = newline->prev; // Go back one line
}
}
}
newline = newline->next;
} while(newline != NULL);
// Fix the XC list in the message, ignore crossposting to itself only
if(not ignorexc and (local_xps < postareas.size()+1) and xcline) {
2000-02-25 11:04:07 +00:00
switch(CFG->crosspostlist) {
case CC_REMOVE:
// No list
break;
case CC_KEEP:
// Keep list as it was entered
break;
case CC_VISIBLE:
// Expand in line
{
if(not hideoriginal) {
sprintf(buf, LNG->Originallyin, AA->echoid());
xcline = AddLine(xcline, buf);
}
std::string hline = "";
2000-02-25 11:04:07 +00:00
int line_items = 0;
for(int i=local_xps; i < postareas.size(); i++) {
const char *echoid = AL[postareas[i]]->echoid();
if(postareas_attrs[i] or strieql(AA->echoid(), echoid))
continue;
if((hline.length() + strlen(echoid) + 2 > margintext) and line_items) {
sprintf(buf, LNG->Crosspostedin, hline.c_str());
xcline = AddLine(xcline, buf);
line_items = 0;
hline = "";
}
if(line_items != 0)
hline += ", ";
hline += echoid;
++line_items;
}
if(line_items) {
sprintf(buf, LNG->Crosspostedin, hline.c_str());
xcline = AddLine(xcline, buf);
}
}
break;
case CC_NAMES:
// Expand in column
if(not hideoriginal) {
sprintf(buf, LNG->Originallyin, AA->echoid());
xcline = AddLine(xcline, buf);
}
2000-02-25 11:04:07 +00:00
for(int i=local_xps; i < postareas.size(); i++) {
const char *echoid = AL[postareas[i]]->echoid();
if(postareas_attrs[i] or strieql(AA->echoid(), echoid))
continue;
sprintf(buf, LNG->Crosspostedin, echoid);
xcline = AddLine(xcline, buf);
2000-02-25 11:04:07 +00:00
}
break;
2000-02-25 11:04:07 +00:00
}
}
}
// Reset line pointer
msg->lin = DeleteLine(msg->lin); // Delete the empty top line again
}
// ------------------------------------------------------------------