diff --git a/golded3/Makefile b/golded3/Makefile new file mode 100644 index 0000000..c59acf3 --- /dev/null +++ b/golded3/Makefile @@ -0,0 +1,20 @@ +# -*- makefile -*- + +TOP=.. +SHORTTARGET=ged +TARGET=golded3 +GLIBS=gmb3 gall gcfg uulib +INCS=-I. -I$(TOP)/goldlib/gall -I$(TOP)/goldlib/gcfg -I$(TOP)/goldlib/gmb3 -I$(TOP)/goldlib/uulib + +ifeq ($(findstring EMX, $(PATH)), EMX) +STDLIBS=-los2me -lstdcpp +GLIBS+=glibc +else +ifeq ($(TERM),cygwin) +STDLIBS=-luser32 -lwinmm +GLIBS+=glibc +endif +endif + +include $(TOP)/GNUmakef.inc +include $(TOP)/GNUmakef.prg diff --git a/golded3/gcalst.cpp b/golded3/gcalst.cpp new file mode 100644 index 0000000..5b4566f --- /dev/null +++ b/golded3/gcalst.cpp @@ -0,0 +1,441 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Arealist configuration and other one-time stuff. +// ------------------------------------------------------------------ + +#include +#include +#include +#include + +// FTS-0001 is FTS so leave it anyway :-) +#include +#ifndef GMB_NOEZY +#include +#endif +#if not defined(GMB_NOHUDS) and not defined(GMB_NOGOLD) +#include +#endif +#ifndef GMB_NOJAM +#include +#endif +#ifndef GMB_NOSQSH +#include +#endif +#ifndef GMB_NOPCB +#include +#endif +#ifndef GMB_NOWCAT +#include +#endif +#ifndef GMB_NOXBBS +#include +#endif +#ifndef GMB_NOSMB +#include +#endif + +// ------------------------------------------------------------------ +// Arealist constructor + +AreaList::AreaList() : idx() { + + item = idx.begin(); + *sortspec = NUL; + + for(uint i = 0; i < 16; i++) + *alistselections[0] = NUL; +} + + +// ------------------------------------------------------------------ +// Arealist destructor + +AreaList::~AreaList() { + + Reset(); +} + + +// ------------------------------------------------------------------ + +void AreaList::SetDefaultMarks() { + + strcpy(alistselections[0], LNG->ArealistSelections1); + + for(uint i = 1; i < 16; i++) + strcpy(alistselections[i], LNG->ArealistSelections2); +} + + +// ------------------------------------------------------------------ +// Arealist deallocate and reset data + +void AreaList::Reset() { + + ListScan.Reset(); + while(not idx.empty()) { + delete idx.back(); + idx.pop_back(); + } +} + + +// ------------------------------------------------------------------ +// Return a new'ed area of the specified format + +Area* AreaList::NewArea(int msgbase) { + + gmo_area* ap = NULL; + switch(msgbase) { + case MT_SEPARATOR: ap = new SepArea; break; + case MT_FTS1: + case MT_OPUS: ap = new FidoArea; break; + #ifndef GMB_NOEZY + case MT_EZYCOM: ap = new EzycomArea; break; + #endif + #ifndef GMB_NOGOLD + case MT_GOLDBASE: ap = new GoldArea; break; + #endif + #ifndef GMB_NOHUDS + case MT_HUDSON: ap = new HudsArea; break; + #endif + #ifndef GMB_NOJAM + case MT_JAM: ap = new JamArea; break; + #endif + #ifndef GMB_NOPCB + case MT_PCBOARD: ap = new PcbArea; break; + #endif + #ifndef GMB_NOSQSH + case MT_SQUISH: ap = new SquishArea; break; + #endif + #ifndef GMB_NOWCAT + case MT_WILDCAT: ap = new WCatArea; break; + #endif + #ifndef GMB_NOXBBS + case MT_ADEPTXBBS: ap = new XbbsArea; break; + #endif + #ifndef GMB_NOSMB + case MT_SMB: ap = new SMBArea; break; + #endif + } + return new Area(ap); +} + + +// ------------------------------------------------------------------ +// Write lastreads for the next session + +void AreaList::WriteGoldLast() { + + word GOLDLAST_VER = CUR_GOLDLAST_VER; + gfile fp; + ggoldlast entry; + Path lst; + + strcpy(lst, AddPath(CFG->goldpath, CFG->goldlast)); + + fp.fopen(lst, "wb", CFG->sharemode); + if(fp.isopen()) { + + fp.setvbuf(NULL, _IOFBF, 8192); + fp.fwrite(&GOLDLAST_VER, sizeof(word)); + fp.fwrite(AL.alistselections, sizeof(AL.alistselections)); + + for(area_iterator ap = idx.begin(); ap != idx.end(); ap++) { + + if((*ap)->isscanned and not (*ap)->isseparator()) { + + // Write fixed header + entry.crcechoid = strCrc32((*ap)->echoid(), false); + entry.lastread = (*ap)->lastread(); + entry.msgncount = (*ap)->Msgn.Count(); + entry.unread = (*ap)->unread; + entry.marks = (*ap)->marks; + entry.flags = 0; + if((*ap)->isscanned) + entry.flags |= 1; + if((*ap)->isvalidchg) + entry.flags |= 2; + if((*ap)->isunreadchg) + entry.flags |= 4; + + fp.fwrite(&entry, sizeof(entry)); + + // Write variable length extensions + (*ap)->Mark.Save(fp); + (*ap)->PMrk.Save(fp); + } + } + + fp.fclose(); + } +} + + +// ------------------------------------------------------------------ +// Read the lastreads from the last session + +void AreaList::ReadGoldLast() { + + word GOLDLAST_VER; + gfile fp; + ggoldlast entry; + + fp.fopen(AddPath(CFG->goldpath, CFG->goldlast), "rb", CFG->sharemode); + if(fp.isopen()) { + + fp.setvbuf(NULL, _IOFBF, 8192); + fp.fread(&GOLDLAST_VER, sizeof(word)); + + if(GOLDLAST_VER != CUR_GOLDLAST_VER) { + fp.close(); + return; + } + + fp.fread(AL.alistselections, sizeof(AL.alistselections)); + + while(fp.fread(&entry, sizeof(entry))) { + + bool found = false; + + for(area_iterator ap = idx.begin(); ap != idx.end(); ap++) { + if(strCrc32((*ap)->echoid(), false) == entry.crcechoid) { + + (*ap)->set_lastread(entry.lastread); + (*ap)->Msgn.count = entry.msgncount; + (*ap)->unread = entry.unread; + (*ap)->marks = entry.marks; + (*ap)->isscanned = (entry.flags & 1) ? true : false; + (*ap)->isvalidchg = (entry.flags & 2) ? true : false; + (*ap)->UpdateAreadata(); + (*ap)->isunreadchg = (entry.flags & 4) ? true : false; + + (*ap)->Mark.Load(fp); + (*ap)->PMrk.Load(fp); + + found = true; + break; + } + } + + if(not found) { + // skip stored message marks + dword dw; + fp.fread(&dw, sizeof(dword)); + fp.fseek(dw*sizeof(dword), SEEK_CUR); + fp.fread(&dw, sizeof(dword)); + fp.fseek(dw*sizeof(dword), SEEK_CUR); + } + } + + fp.fclose(); + } +} + + +// ------------------------------------------------------------------ +// Write all areas to GOLDAREA.INC in AREADEF format + +void AreaList::WriteAreaDef(const char* file) { + + int tmp; + FILE* fp; + Path path; + char groupid[10], echoid[sizeof(Echo)+2]; + int maxechoid=0, maxdesc=0, maxgroupid=0, maxpath=0, maxaddr=0, maxattr=0; + char desc[sizeof(Desc)+2], type[6], msgbase[7], addr[40], attr[150], origin[163]; + + fp = fsopen(file, "wt", CFG->sharemode); + if(fp) { + + area_iterator aa; + for(aa = idx.begin(); aa != idx.end(); aa++) { + tmp = strlen((*aa)->echoid()); + if(strchr((*aa)->echoid(), ' ')) + tmp += 2; + maxechoid = MaxV(maxechoid, tmp); + tmp = strlen((*aa)->desc())+2; + maxdesc = MaxV(maxdesc, tmp); + tmp = strlen((*aa)->path()); + if(strchr((*aa)->path(), ' ')) + tmp += 2; + maxpath = MaxV(maxpath, tmp); + if((*aa)->groupid() & 0x8000u) + sprintf(groupid, "#%u", (*aa)->groupid()&0x7FFF); + else if(isupper((*aa)->groupid())) + *groupid = (char)(*aa)->groupid(), groupid[1] = NUL; + else + *groupid = '0', groupid[1] = NUL; + tmp = strlen(groupid); + maxgroupid = MaxV(maxgroupid, tmp); + if(memcmp(&(*aa)->aka(), &CFG->aka[0], sizeof(Addr))) + (*aa)->aka().make_string(addr); + else + strcpy(addr, "."); + tmp = strlen(addr); + maxaddr = MaxV(maxaddr, tmp); + tmp = strlen(MakeAttrStr(attr, &(*aa)->attr())); + maxattr = MaxV(maxattr, tmp+2); + } + + for(aa = idx.begin(); aa != idx.end(); aa++) { + sprintf(desc, "\"%s\"", (*aa)->desc()); + if((*aa)->groupid() & 0x8000u) + sprintf(groupid, "#%u", (*aa)->groupid()&0x7FFF); + else if(isupper((*aa)->groupid())) + *groupid = (char)(*aa)->groupid(), groupid[1] = NUL; + else + *groupid = '0', groupid[1] = NUL; + if((*aa)->isemail()) + strcpy(type, "EMail"); + else if((*aa)->isnewsgroup()) + strcpy(type, "News "); + else if((*aa)->isnet()) + strcpy(type, "Net "); + else if((*aa)->isecho()) + strcpy(type, "Echo "); + else if((*aa)->islocal()) + strcpy(type, "Local"); + switch((*aa)->msgbase()) { + case MT_OPUS: strcpy(msgbase, "Opus "); break; + case MT_FTS1: strcpy(msgbase, "Fts1 "); break; + #ifndef GMB_NOHUDS + case MT_HUDSON: strcpy(msgbase, "Hudson"); break; + #endif + #ifndef GMB_NOGOLD + case MT_GOLDBASE: strcpy(msgbase, "Gold "); break; + #endif + #ifndef GMB_NOSQSH + case MT_SQUISH: strcpy(msgbase, "Squish"); break; + #endif + #ifndef GMB_NOEZY + case MT_EZYCOM: strcpy(msgbase, "Ezycom"); break; + #endif + #ifndef GMB_NOJAM + case MT_JAM: strcpy(msgbase, "Jam "); break; + #endif + #ifndef GMB_NOPCB + case MT_PCBOARD: strcpy(msgbase, "Pcb "); break; + #endif + #ifndef GMB_NOWCAT + case MT_WILDCAT: strcpy(msgbase, "WCat "); break; + #endif + #ifndef GMB_NOXBBS + case MT_ADEPTXBBS: strcpy(msgbase, "XBBS "); break; + #endif + #ifndef GMB_NOSMB + case MT_SMB: strcpy(msgbase, "SMB "); break; + #endif + } + if(strchr((*aa)->echoid(), ' ')) + sprintf(echoid, "\"%s\"", (*aa)->echoid()); + else + strcpy(echoid, (*aa)->echoid()); + if((*aa)->isseparator()) { + fprintf(fp, "AREASEP %-*s %-*s %*s %s\n", + maxechoid, echoid, + maxdesc, desc, + maxgroupid, groupid, + strtrim(type) + ); + } + else { + if(strchr((*aa)->path(), ' ')) + sprintf(path, "\"%s\"", (*aa)->path()); + else + strcpy(path, (*aa)->path()); + if(memcmp(&(*aa)->aka(), &CFG->aka[0], sizeof(Addr))) + (*aa)->aka().make_string(addr); + else + strcpy(addr, "."); + *attr = '('; /*)*/ + MakeAttrStr(attr+1, &(*aa)->attr()); + strcat(attr, /*(*/ ")"); + if((*aa)->originno()) + sprintf(origin, " \"%.*s\"", (int)sizeof(origin)-4, CFG->origin[(*aa)->originno()].c_str()); + else + *origin = NUL; + fprintf(fp, "AREADEF %-*s %-*s %*s %s %s %-*s %-*s %-*s%s\n", + maxechoid, echoid, + maxdesc, desc, + maxgroupid, groupid, + type, + msgbase, + maxpath, path, + maxaddr, addr, + maxattr, attr, + origin + ); + } + } + + fclose(fp); + } +} + + +// ------------------------------------------------------------------ + +void SetAreaDesc(char* echoid, char* desc) { + + AL.SetAreaDesc(echoid, desc); +} + + +// ------------------------------------------------------------------ + +void AreaList::SetAreaDesc(char* echoid, char* desc) { + + for(area_iterator ap = idx.begin(); ap != idx.end(); ap++) { + if(strieql(echoid, (*ap)->echoid())) { + (*ap)->set_desc(desc); + break; + } + } +} + + +// ------------------------------------------------------------------ + +void PcbAdjustArea(uint rec, const char* msgfile) { + + for(uint n=0; nispcboard()) { + if((a->board() == rec) and (*a->path() == NUL)) { + a->set_path(msgfile); + break; + } + else if(strieql(a->path(), msgfile)) { + a->set_board(rec); + break; + } + } + } +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gcarea.cpp b/golded3/gcarea.cpp new file mode 100644 index 0000000..70fe35b --- /dev/null +++ b/golded3/gcarea.cpp @@ -0,0 +1,1119 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Common code for the area compile. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ +// Fix up the echoid and make default if none specified + +void FixEchoid(char* echoid, int type) { + + static uint netnum = 1; + static uint echonum = 1; + static uint localnum = 1; + + if(*echoid == NUL) { + const char* t = CFG->areaautoid == AUTOID_LONG ? "MAIL" : ""; + if(type & AT_NET) + sprintf(echoid, "NET%s%03u", t, netnum++); + else if(type & AT_ECHO) + sprintf(echoid, "ECHO%s%03u", t, echonum++); + else if(type & AT_LOCAL) + sprintf(echoid, "LOCAL%03u", localnum++); + } +} + + +// ------------------------------------------------------------------ +// Sort a group of areas + +void AreaList::SortAreaGroup(const char* options, int beginarea, int endarea) { + + if(beginarea != endarea) { + const char* ptr = striinc("-S", options); + if(ptr) { + ptr += 2; + if(*ptr == '=') + ptr++; + Sort(ptr, beginarea, endarea); + } + } +} + + +// ------------------------------------------------------------------ +// Rename an echoid + +void RenameArea(char* echoid) { + + vector::iterator n; + for(n = CFG->arearename.begin(); n != CFG->arearename.end(); n++) { + if(strieql(echoid, n->from.c_str())) { + strxcpy(echoid, n->to.c_str(), sizeof(Echo)); + break; + } + } +} + + +// ------------------------------------------------------------------ +// Check if the echoid is on the exclusion list + +bool CheckExcl(char* echoid) { + + gstrarray::iterator n, x; + for(n = CFG->areaexcl.begin(); n != CFG->areaexcl.end(); n++) { + if(strwild(echoid, n->c_str())) { + + // Found excl, now check for incl + for(x = CFG->areaincl.begin(); x != CFG->areaincl.end(); x++) + if(strwild(echoid, x->c_str())) + return false; + + return true; // Echoid is excluded + } + } + return false; +} + + +// ------------------------------------------------------------------ +// Check if the echo is email or news + +void CheckEMailOrNews(char* echoid, uint& type) { + + gstrarray::iterator i; + + for(i = CFG->areaisemail.begin(); i != CFG->areaisemail.end(); i++) { + if(strwild(echoid, i->c_str())) { + type = AT_EMAIL | AT_NET; + break; + } + } + + for(i = CFG->areaisnews.begin(); i != CFG->areaisnews.end(); i++) { + if(strwild(echoid, i->c_str())) { + type = AT_NEWSGROUP | AT_ECHO; + break; + } + } +} + + +// ------------------------------------------------------------------ +// Add or update area data + +void AddNewArea(AreaCfg* aa) { + + AL.AddNewArea(aa); +} + + +// ------------------------------------------------------------------ +// Add or update area data + +void AddNewArea(AreaCfg& aa) { + + AL.AddNewArea(&aa); +} + + +// ------------------------------------------------------------------ +// Add or update area data + +void AreaList::AddNewArea(AreaCfg* aa) { + + if(veryverbose) { + string temp; + cout << " fmt=" << aa->msgbase << ", eid=\"" << aa->echoid << + "\", pth=\"" << aa->path << "\", brd=" << aa->board << + ", gid=" << aa->groupid << ", aka=" << aa->aka.make_string(temp); + cout << " " << aa->attr.make_string(temp) << endl; + } + + Desc desc; + char buf[256]; + bool newarea = true; + static int serial = 0; + static int net1st = false; + + *desc = NUL; + + // Make sure the path field is 100% correct for the msgbase + switch(aa->msgbase) { + case MT_FTS1: + case MT_OPUS: + if(*aa->path == NUL) + return; + MapPath(aa->path); + AddBackslash(aa->path); + strschg_environ(aa->path); + break; + #ifndef GMB_NOHUDS + case MT_HUDSON: + if((aa->board < 1) or (aa->board > 200)) // Ignore areas with invalid numbers + return; + sprintf(aa->path, "%u", aa->board); + break; + #endif + #ifndef GMB_NOGOLD + case MT_GOLDBASE: + if((aa->board < 1) or (aa->board > 500)) // Ignore areas with invalid numbers + return; + sprintf(aa->path, "%u", aa->board); + break; + #endif + #ifndef GMB_NOEZY + case MT_EZYCOM: + // Ignore areas with invalid numbers + if((aa->board < 1) or (aa->board > 1536)) + return; + sprintf(aa->path, "%u", aa->board); + break; + #endif + #ifndef GMB_NOWCAT + case MT_WILDCAT: + if(*aa->path == NUL) + return; + MapPath(aa->path); + StripBackslash(aa->path); + strschg_environ(aa->path); + break; + #endif + #ifndef GMB_NOXBBS + case MT_ADEPTXBBS: + #if not defined(__OS2__) + return; + #else + if(*aa->path == NUL) + return; + MapPath(aa->path); + StripBackslash(aa->path); + strschg_environ(aa->path); + break; + #endif + #endif + #ifndef GMB_NOSQSH + case MT_SQUISH: + #endif + #ifndef GMB_NOJAM + case MT_JAM: + #endif + #if not defined(GMB_NOJAM) or not defined(GMB_NOSQSH) + if(*aa->path == NUL) + return; + MapPath(aa->path); + StripBackslash(aa->path); + strschg_environ(aa->path); + break; + #endif + #ifndef GMB_NOPCB + case MT_PCBOARD: + MapPath(aa->path); + StripBackslash(aa->path); + strschg_environ(aa->path); + break; + #endif + #ifndef GMB_NOSMB + case MT_SMB: + if(*aa->path == NUL) + return; + MapPath(aa->path); + StripBackslash(aa->path); + strschg_environ(aa->path); + break; + #endif + case MT_SEPARATOR: + break; + default: + return; + } + + // Note msgbase type + msgbases |= aa->msgbase; + + // Things to do for real areas only + if(not aa->isseparator()) { + + // If the echoid is missing, try to find it in the echolist + if(strblank(aa->echoid)) + AFILE->echolist.FindEcho(aa->echoid, aa->path, aa->desc); + + // Fix up the echoid + FixEchoid(aa->echoid, aa->type); + + // Rename the echoid if necessary + RenameArea(aa->echoid); + + // Do not accept excluded areas + if(CheckExcl(aa->echoid)) + return; + + // Fix description + if(strblank(aa->desc)) + strxcpy(aa->desc, aa->echoid, sizeof(aa->desc)); + } + + // Check if it's email or news + CheckEMailOrNews(aa->echoid, aa->type); + + // Give each area a unique serial number + aa->areaid = serial++; + + // Check if we already have the area (dup echoid or path) + int _currarea = 0; + area_iterator ap; + for(ap = idx.begin(); ap != idx.end(); ap++) { + ++_currarea; + if(not (*ap)->isseparator()) { + int eq_echoid = strieql(aa->echoid, (*ap)->echoid()); + int eq_path = strieql(aa->path, (*ap)->path()); + int eq_board = (aa->board == (*ap)->board()); + int eq_msgbase = (aa->msgbase == (*ap)->msgbase()); + int eq_isfido = (aa->isfido() and (*ap)->isfido()); + if(eq_echoid or (eq_path and eq_board and (eq_msgbase or eq_isfido))) { + // We had it already, so override with the new data + newarea = false; + if(strblank((*ap)->desc())) + strcpy(desc, aa->desc); + break; + } + } + } + + // If first netmail area, set default for AREAFREQTO and AREAREPLYTO + if((aa->isnet() and not aa->isseparator()) and not net1st) { + net1st = true; + if(not *CFG->areafreqto) + strcpy(CFG->areafreqto, aa->echoid); + if(not *CFG->areareplyto) + strcpy(CFG->areareplyto, aa->echoid); + } + + // Increase area index size if new area + if(newarea) { + idx.push_back(NewArea(aa->msgbase)); + throw_new(idx[_currarea]); + ap = idx.end(); --ap; + } + + // Add aka if not found + if(aa->aka.net) { + bool found = false; + for(vector::iterator i = CFG->aka.begin(); i != CFG->aka.end(); i++) + if(aa->aka == i->addr) { + found = true; + break; + } + if(not found) // Then add it + CfgAddress(aa->aka.make_string(buf)); // Add the aka + } + else { + // If address is missing, use main address + if(not CFG->aka.empty()) + aa->aka = CFG->aka[0].addr; + } + + // Copy the data + if(newarea) { + (*ap)->set_echoid(aa->echoid); + (*ap)->set_path(aa->path); + (*ap)->set_board(aa->board); + (*ap)->set_msgbase(aa->msgbase); + } + (*ap)->set_desc(newarea or strblank(desc) ? aa->desc : desc); + (*ap)->set_areaid(aa->areaid); + (*ap)->set_groupid(aa->groupid); + (*ap)->set_type(aa->type); + (*ap)->set_aka(aa->aka); + (*ap)->set_originno(aa->originno); + (*ap)->set_attr(aa->attr); + (*ap)->set_scan(aa->scan); + (*ap)->set_scanexcl(aa->scanexcl); + (*ap)->set_scanincl(aa->scanincl); + (*ap)->set_pmscan(aa->pmscan); + (*ap)->set_pmscanexcl(aa->pmscanexcl); + (*ap)->set_pmscanincl(aa->pmscanincl); +} + + +// ------------------------------------------------------------------ +// Get areas from other programs + +void AreaList::GetAreafile(char* value) { + + const word CRC_ECHOLIST = 0xCE70; + + word crcval; + char* keyword; + char* options; + int beginarea, endarea; + + crcval = getkeyvalcrc(&keyword, &value); + options = throw_strdup(value); + + beginarea = idx.size(); + + if(crcval == CRC_ECHOLIST) + ReadEcholist(value); + else { + AFILE->quiet = quiet; + AFILE->sharemode = CFG->sharemode; + AFILE->fidomsgtype = CFG->fidomsgtype; + AFILE->ra2usersbbs = CFG->ra2usersbbs; + AFILE->squishuserno = CFG->squishuserno; + + if(not CFG->aka.empty()) + AFILE->primary_aka = CFG->aka[0].addr; + else + AFILE->primary_aka = 0; + + AFILE->attribsnet = CFG->attribsnet; + AFILE->attribsecho = CFG->attribsecho; + AFILE->attribsnews = CFG->attribsnews; + AFILE->attribsemail = CFG->attribsemail; + AFILE->attribslocal = CFG->attribslocal; + + AFILE->areapath = CFG->areapath; + AFILE->adeptxbbspath = CFG->adeptxbbspath; + AFILE->jampath = CFG->jampath; + AFILE->squishuserpath = CFG->squishuserpath; + AFILE->hudsonpath = CFG->hudsonpath; + AFILE->goldbasepath = CFG->goldbasepath; + AFILE->pcboardpath = CFG->pcboardpath; + AFILE->ezycom_msgbasepath = CFG->ezycom.msgbasepath; + AFILE->ezycom_userbasepath = CFG->ezycom.userbasepath; + AFILE->fidolastread = CFG->fidolastread; + + AFILE->ReadAreafile(crcval, value); + + CFG->ra2usersbbs = AFILE->ra2usersbbs; + CFG->squishuserno = AFILE->squishuserno; + } + + endarea = idx.size(); + SortAreaGroup(options, beginarea, endarea); + + throw_free(options); +} + + +// ------------------------------------------------------------------ +// Get area definition + +void AreaList::GetArea(char* def) { + + AreaCfg aa; + char* ptr; + char* tag; + char* desc; + char* base; + char* loc; + char* attr; + + if(strnieql(def, "-FILE ", 6)) // Check for alternate formats + GetAreafile(def+6); + else { + tag = def; + desc = strskip_txt(tag); + *desc = NUL; + + aa.reset(); + + // Split up the string definition + desc = strskip_wht(desc+1); + switch(*desc) { + case '\"': + base = strskip_to(desc+1, '\"')+1; + break; + case '\'': + base = strskip_to(desc+1, '\'')+1; + break; + default: + base = strskip_txt(desc); + } + *base = NUL; + base = strskip_wht(base+1); + loc = strskip_txt(base); + *loc = NUL; + loc = strskip_wht(loc+1); + attr = strpbrk(loc, " \t"); + if(attr and *attr) { + *attr = NUL; + attr = strskip_wht(attr+1); + } + + // Parse the individual parts + + aa.setechoid(tag); // Copy the echotag + + StripQuotes(desc); // Copy description, stripping quotes ("") + aa.setdesc(desc); + + switch(toupper(*base)) { // Store area info + + case '-': + aa.msgbase = MT_SEPARATOR; + break; + + case 'M': + aa.msgbase = MT_SQUISH; + aa.setpath(loc); + break; + + case 'Y': + aa.msgbase = MT_SMB; + aa.setpath(loc); + break; + + case 'H': + case 'R': + case 'Q': + aa.msgbase = MT_HUDSON; + aa.board = (uint) atoi(loc); + break; + + case 'G': + aa.msgbase = MT_GOLDBASE; + aa.board = (uint) atoi(loc); + break; + + case 'E': + aa.msgbase = MT_EZYCOM; + aa.board = (uint) atoi(loc); + break; + + case 'J': + aa.msgbase = MT_JAM; + aa.setpath(loc); + break; + + case 'P': + aa.msgbase = MT_PCBOARD; + aa.setpath(loc); + break; + + case 'W': + aa.msgbase = MT_WILDCAT; + aa.setpath(loc); + break; + + case 'X': + aa.msgbase = MT_ADEPTXBBS; + aa.setpath(loc); + break; + + case 'S': + aa.msgbase = MT_FTS1; + aa.setpath(loc); + break; + + case 'F': + case 'O': + default: + aa.msgbase = MT_OPUS; + aa.setpath(loc); + } + + aa.type = AT_ECHO; + aa.attr = CFG->attribsecho; + strupr(base); + if(strchr(base, 'N')) { + aa.type = AT_NET; + aa.attr = CFG->attribsnet; + } + if(strchr(base, 'L')) { + aa.type = AT_LOCAL; + aa.attr = CFG->attribslocal; + } + if(strchr(base, 'E')) { + aa.type = AT_ECHO; + aa.attr = CFG->attribsecho; + } + if(attr) { // Get attributes and AKAs + GetAttribstr(&aa.attr, attr); + if((ptr = strpbrk(attr, "0123456789")) != NULL) { + int n = atoi(ptr); + if((n < 0) or ((uint) n >= CFG->aka.size())) + n = 0; + if(not CFG->aka.empty()) + aa.aka = CFG->aka[n].addr; // Found AKA number + } + } + + if(not aa.aka.net and not CFG->aka.empty()) + aa.aka = CFG->aka[0].addr; + + AddNewArea(&aa); + } +} + + +// ------------------------------------------------------------------ +// Get area definition (new) +// +// Syntax of AREADEF keyword: +// +// AREADEF <"desc"> <(attrs)> ["origin"] +// +// Examples: +// +// AREADEF NET.ALL "Netmail, Line 1" N Net Opus R:\NETMAIL\ 2:231/77 (PVT K/S) +// AREADEF TEST "Testing..." D Echo Hudson 67 . () +// AREADEF 1LOCAL "Sysop <-> Users" L Local Squish R:\MAX\MSG\LOC\1LOCAL . (PVT) "Your Sysop * The Goldware BBS Line 1" +// AREADEF DANEINFO "DaneNet Info" D Echo Squish R:\MAX\MSG\231\DANEINFO . (R/O) + +bool AreaList::GetAreaFirstPart(AreaCfg& aa, char*& key, char*& val) { + + const word CRC_NET = 0xEC5E; + const word CRC_ECHO = 0xC2D1; + const word CRC_LOCAL = 0x4CD5; + const word CRC_EMAIL = 0x9C64; + const word CRC_NEWS = 0x61F1; + + // Get echoid + getkeyval(&key, &val); + aa.setechoid(key); + + // Get description + getkeyval(&key, &val); + aa.setdesc(key); + + // Get group (letter) + getkeyval(&key, &val); + if(*key == '#') + aa.groupid = atoi(key+1)+0x8000u; + else + aa.groupid = (isupper(*key) ? *key : 0); + + // Get type + word crc = getkeyvalcrc(&key, &val); + switch(crc) { + case CRC_NET: + aa.type = AT_NET; + aa.attr = CFG->attribsnet; + break; + case CRC_ECHO: + aa.type = AT_ECHO; + aa.attr = CFG->attribsecho; + break; + case CRC_LOCAL: + aa.type = AT_LOCAL; + aa.attr = CFG->attribslocal; + break; + case CRC_EMAIL: + aa.type = AT_EMAIL | AT_NET; + aa.attr = CFG->attribsnet; + break; + case CRC_NEWS: + aa.type = AT_NEWSGROUP | AT_ECHO; + aa.attr = CFG->attribsecho; + break; + default: + return false; + } + + return true; +} + + +// ------------------------------------------------------------------ + +void AreaList::GetAreaSep(char* val) { + + char* key; + AreaCfg aa; + + aa.reset(); + aa.msgbase = MT_SEPARATOR; + + if(not GetAreaFirstPart(aa, key, val)) + return; + + AddNewArea(&aa); +} + + +// ------------------------------------------------------------------ + +void AreaList::GetAreaDef(char* val) { + + const word CRC_SEP = 0x2FC6; + const word CRC_FIDO = 0x3AC8; + const word CRC_OPUS = 0x1254; + const word CRC_SDMSG = 0xAEC0; + const word CRC_FTS1 = 0xEE2A; + const word CRC_FTSC = 0xEE58; + const word CRC_QBBS = 0x175B; + const word CRC_HUDSON = 0xBAB1; + const word CRC_SQUISH = 0xFCF6; + const word CRC_EZYCOM = 0xC81B; + const word CRC_JAM = 0xA8C3; + const word CRC_GOLD = 0x6134; + const word CRC_GOLDBASE = 0x560D; + const word CRC_PCB = 0x19B7; + const word CRC_PCBOARD = 0x84EC; + const word CRC_WCAT = 0xAEDB; + const word CRC_WILDCAT = 0x7F3A; + const word CRC_XBBS = 0xADC3; + const word CRC_SMB = 0x27D4; + + char* key; + AreaCfg aa; + + aa.reset(); + + if(not GetAreaFirstPart(aa, key, val)) + return; + + // Get format + word crc = getkeyvalcrc(&key, &val); + getkeyval(&key, &val); // Get path/board + switch(crc) { + case CRC_SEP: + aa.msgbase = MT_SEPARATOR; + break; + case CRC_FIDO: + case CRC_OPUS: + case CRC_SDMSG: + aa.msgbase = MT_OPUS; + aa.setpath(key); + break; + case CRC_FTS1: + case CRC_FTSC: + aa.msgbase = MT_FTS1; + aa.setpath(key); + break; + case CRC_QBBS: + case CRC_HUDSON: + aa.msgbase = MT_HUDSON; + aa.board = (uint) atoi(key); + if((aa.board < 1) or (aa.board > 200)) { + return; + } + break; + case CRC_GOLD: + case CRC_GOLDBASE: + aa.msgbase = MT_GOLDBASE; + aa.board = atoi(key); + if((aa.board < 1) or (aa.board > 500)) { + return; + } + break; + case CRC_SQUISH: + aa.msgbase = MT_SQUISH; + aa.setpath(key); + break; + case CRC_SMB: + aa.msgbase = MT_SMB; + aa.setpath(key); + break; + case CRC_EZYCOM: + aa.msgbase = MT_EZYCOM; + aa.board = atoi(key); + break; + case CRC_JAM: + aa.msgbase = MT_JAM; + aa.setpath(key); + break; + case CRC_PCB: + case CRC_PCBOARD: + aa.msgbase = MT_PCBOARD; + aa.setpath(key); + break; + case CRC_WCAT: + case CRC_WILDCAT: + aa.msgbase = MT_WILDCAT; + aa.setpath(key); + break; + case CRC_XBBS: + aa.msgbase = MT_ADEPTXBBS; + aa.setpath(key); + break; + default: + return; + } + + // Get aka + getkeyval(&key, &val); + if(not CFG->aka.empty()) // Seed aka with main address + aa.aka = CFG->aka[0].addr; + + aa.aka.set(key); + + // Get attributes + getkeyval(&key, &val); + GetAttribstr(&aa.attr, key); + + // Get origin (optional) + getkeyval(&key, &val); + aa.setorigin(key); + + // Add to arealist + AddNewArea(&aa); +} + + +// ------------------------------------------------------------------ + +void ReadEcholist(char* val) { + + AL.ReadEcholist(val); +} + + +// ------------------------------------------------------------------ + +void getdztoken(char** key, char** val) { + + char* p = *val; + + *key = p; + p = strskip_to(p, ','); + if(*p == ',') + *p++ = NUL; + *val = p; +} + + +// ------------------------------------------------------------------ + +void AreaList::ReadEcholist(char* val) { + + FILE* fp; + char* key; + Path file; + char buf[256], options[80]; + bool is_sqafix = false; + bool is_dz = false; + + // Get filename or options + *file = NUL; + *options = NUL; + while(*val) { + getkeyval(&key, &val); + if(*key == '-') { + // Get option + if(strieql(key+1, "SQAFIX")) + is_sqafix = true; + else if(strieql(key+1, "DZ")) + is_dz = true; + else { + strcat(options, key); + strcat(options, " "); + } + continue; + } + strcpy(file, key); + } + + if(*file) { + + fp = fsopen(file, "rt", CFG->sharemode); + if(fp) { + + void (*tok)(char**, char**); + + if(is_dz) + tok = getdztoken; + else + tok = getkeyval; + + if(not quiet) + cout << "* Reading " << file << endl; + + while(fgets((val=buf), sizeof(buf), fp)) { + + // Get echoid + if(is_sqafix) { + tok(&key, &val); + if(not strieql(key, "EchoArea")) + continue; + } + else if(is_dz) { + if(not isalpha(*val) and (*val != ',')) + continue; + tok(&key, &val); + } + tok(&key, &val); + if(*key and (*key != ';') and (*key != '%')) { + if(is_sqafix) { + char *grp, *desc; + tok(&grp, &val); + if((desc = strchr(val, '\"')) != NULL) { + char *p = strchr(++desc, '\"'); + if(p) + *p = NUL; + else + desc = NULL; + } + for(area_iterator ap = idx.begin(); ap != idx.end(); ap++) { + if(strieql(key, (*ap)->echoid())) { + (*ap)->set_groupid(toupper(*grp)); + if(desc) + (*ap)->set_desc(desc); + break; + } + } + } + else { + char *desc; + if(is_dz) + tok(&desc, &val); + else + desc = val; + for(area_iterator ap = idx.begin(); ap != idx.end(); ap++) { + if(strieql(key, (*ap)->echoid())) { + (*ap)->set_desc(desc); + break; + } + } + } + } + } + + fclose(fp); + } + } +} + + +// ------------------------------------------------------------------ + +void AreaList::GetAreaDesc(char* val) { + + char* key; + Area* aa = NULL; + + // Get echoid and find area + getkeyval(&key, &val); + for(area_iterator ap = idx.begin(); ap != idx.end(); ap++) { + if(strieql(key, (*ap)->echoid())) { + aa = *ap; + break; + } + } + if(aa == NULL) // Not found, ignore + return; + + // Get description + getkeyval(&key, &val); + aa->set_desc(key); + + // Get group letter (optional) + getkeyval(&key, &val); + if(*key) { + if(*key != '-') { + if(*key == '#') + aa->set_groupid(atoi(key+1)+0x8000u); + else + aa->set_groupid(toupper(*key)); + } + + // Get aka (optional) + getkeyval(&key, &val); + if(*key) { + + if(*key != '-') { + ftn_addr aka; + if(not CFG->aka.empty()) // Seed aka with main address + aka = CFG->aka[0].addr; + + aka.set(key); + aa->set_aka(aka); + } + + // Get attributes (optional) + getkeyval(&key, &val); + if(*key) { + + if(*key != '-') { + Attr attr; + GetAttribstr(&attr, key); + aa->set_attr(attr); + } + + // Get origin (optional) + getkeyval(&key, &val); + if(*key) + aa->set_origin(key); + } + } + } +} + + +// ------------------------------------------------------------------ +// Reset area data + +void AreaCfg::reset() { + + *echoid = *desc = *path = NUL; + origin = ""; + areaid = 0; + groupid = 0; + originno = 0; + board = 0; + msgbase = 0; + aka.reset(); + type = 0; + scan = 0; + scanexcl = 0; + scanincl = 0; + pmscan = 0; + pmscanexcl = 0; + pmscanincl = 0; + attr.reset(); +} + + +// ------------------------------------------------------------------ +// Set area description + +const char* AreaCfg::setdesc(const char* _desc) { + + return strxcpy(desc, _desc, sizeof(Desc)); +} + + +// ------------------------------------------------------------------ +// Set area echoid + +const char* AreaCfg::setautoid(const char* _echoid) { + + return strxcpy(echoid, CFG->areaautoid ? "" : _echoid, sizeof(Echo)); +} + + +// ------------------------------------------------------------------ +// Set area echoid + +const char* AreaCfg::setechoid(const char* _echoid) { + + return strxcpy(echoid, _echoid, sizeof(Echo)); +} + + +// ------------------------------------------------------------------ +// Set area path/filename + +const char* AreaCfg::setpath(const char* _path) { + + return StripQuotes(strxcpy(path, _path, sizeof(Path))); +} + + +// ------------------------------------------------------------------ +// Set area origin + +int AreaCfgBase::setorigin(string& _origin) { + + if(not strblank(_origin.c_str())) { + + // Check if it already exists + gstrarray::iterator n; + for(n = CFG->origin.begin(), originno = 0; n != CFG->origin.end(); originno++, n++) + if(*n == _origin) + return originno; + + // Not found, so add it + CfgOrigin(_origin.c_str()); + // originno = CFG->origin.size()-1; + } + + return originno; +} + + +// ------------------------------------------------------------------ + +Area::Area(gmo_area* a) { + + throw_new(a); + + area = a; + adat = NULL; + bookmark = 0; + marks = 0; + unread = 0; + isvalidchg = false; + isunreadchg = false; + isreadmark = false; + isreadpm = false; + isscanned = false; + ispmscanned = false; + istossed = false; +} + + +// ------------------------------------------------------------------ + +Area::~Area() { + + throw_delete(area); +} + + +// ------------------------------------------------------------------ + +char* MapPath(char* map, bool reverse) { + + Path buf,cmap; + + strxcpy(cmap, map, sizeof(Path)); + if(reverse) + strchg(cmap, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); + + vector< pair >::iterator i; + for(i = CFG->mappath.begin(); i < CFG->mappath.end(); i++) { + const char* p = reverse ? i->second.c_str() : i->first.c_str(); + const char* q = reverse ? i->first.c_str() : i->second.c_str(); + if(strnieql(cmap, p, strlen(p))) { + strxcpy(buf, map, sizeof(Path)); + strxmerge(map, sizeof(Path), map, q, buf+strlen(p), NULL); + + char sl1, sl2; + char* ptr; + + ptr = strpbrk(p, "/\\"); + sl1 = ptr ? *ptr : NUL; + ptr = strpbrk(q, "/\\"); + sl2 = ptr ? *ptr : NUL; + + if(sl1 and sl2) + strchg(map, sl1, sl2); + + break; + } + } + return map; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gccfgg.cpp b/golded3/gccfgg.cpp new file mode 100644 index 0000000..079ab75 --- /dev/null +++ b/golded3/gccfgg.cpp @@ -0,0 +1,881 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Main GOLDED.CFG compiler. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern char v7nodeflags[16][9]; +extern char v7modemtype[8][9]; + + +// ------------------------------------------------------------------ +// Read GOLDED.CFG + +bool ReadGoldedCfg(int& force) { + + gfile fp; + + CfgInit2(); + + Path golded_cfg; + strcpy(golded_cfg, AddPath(CFG->goldpath, CFG->goldcfg)); + if(ReadCfg(golded_cfg)) { + + // Unallocate echolist + AFILE->echolist.FreeAll(); + + // Set default paths + + if(*CFG->temppath == NUL) strcpy(CFG->temppath, CFG->goldpath); + if(*CFG->areapath == NUL) strcpy(CFG->areapath, CFG->goldpath); + if(*CFG->inboundpath == NUL) strcpy(CFG->inboundpath, CFG->goldpath); + if(*CFG->soundpath == NUL) strcpy(CFG->soundpath, CFG->goldpath); + if(*CFG->cookiepath == NUL) strcpy(CFG->cookiepath, CFG->goldpath); + if(*CFG->templatepath == NUL) strcpy(CFG->templatepath, CFG->goldpath); + + if(*CFG->squishuserpath == NUL) { + char* ptr = getenv("MAXIMUS"); + if(ptr) { + if(is_dir(ptr)) + AddBackslash(strcpy(CFG->squishuserpath, ptr)); + } + else { + ptr = getenv("SQUISH"); + if(ptr) + AddBackslash(strcpy(CFG->squishuserpath, ptr)); + else + strcpy(CFG->squishuserpath, CFG->areapath); + } + } + + if(*CFG->hudsonpath == NUL) strcpy(CFG->hudsonpath, CFG->goldpath); + if(*CFG->hudsonsyspath == NUL) strcpy(CFG->hudsonsyspath, CFG->hudsonpath); + if(*CFG->goldbasepath == NUL) strcpy(CFG->goldbasepath, CFG->hudsonpath); + if(*CFG->goldbasesyspath == NUL) strcpy(CFG->goldbasesyspath, CFG->goldbasepath); + if(*CFG->jampath == NUL) strcpy(CFG->jampath, CFG->hudsonpath); + + MakePathname(CFG->goldcfg, CFG->goldpath, CFG->goldcfg); + MakePathname(CFG->helpcfg.fn, CFG->goldpath, CFG->helpcfg.fn); + MakePathname(CFG->helpged, CFG->goldpath, CFG->helpged); + MakePathname(CFG->keyscfg, CFG->goldpath, CFG->keyscfg); + MakePathname(CFG->langcfg, CFG->goldpath, CFG->langcfg); + MakePathname(CFG->xlatged, CFG->goldpath, CFG->xlatged); + + MakePathname(CFG->confirmfile, CFG->goldpath, CFG->confirmfile); + MakePathname(CFG->logfile, CFG->goldpath, CFG->logfile); + MakePathname(CFG->userlistfile, CFG->nodepath, CFG->userlistfile); + MakePathname(CFG->outputfile, CFG->goldpath, CFG->outputfile); + MakePathname(CFG->inputfile, CFG->goldpath, CFG->inputfile); + + if(*CFG->souptosslog) + MakePathname(CFG->souptosslog, CFG->goldpath, CFG->souptosslog); + + vector::iterator t; + for(t = CFG->tpl.begin(); t != CFG->tpl.end(); t++) + MakePathname(t->file, CFG->templatepath, t->file); + + MakePathname(CFG->semaphore.importlist, CFG->areapath, CFG->semaphore.importlist); + MakePathname(CFG->semaphore.exportlist, CFG->areapath, CFG->semaphore.exportlist); + MakePathname(CFG->semaphore.echoscan, CFG->areapath, CFG->semaphore.echoscan); + MakePathname(CFG->semaphore.netscan, CFG->areapath, CFG->semaphore.netscan); + + MakePathname(CFG->semaphore.scanall, CFG->goldpath, CFG->semaphore.scanall); + MakePathname(CFG->semaphore.scanthis, CFG->goldpath, CFG->semaphore.scanthis); + MakePathname(CFG->semaphore.scannetmail,CFG->goldpath, CFG->semaphore.scannetmail); + MakePathname(CFG->semaphore.pmscanall, CFG->goldpath, CFG->semaphore.pmscanall); + MakePathname(CFG->semaphore.pmscanthis, CFG->goldpath, CFG->semaphore.pmscanthis); + MakePathname(CFG->semaphore.pmscannetmail, CFG->goldpath, CFG->semaphore.pmscannetmail); + + MakePathname(CFG->semaphore.qwkimport, CFG->goldpath, CFG->semaphore.qwkimport); + MakePathname(CFG->semaphore.qwkexport, CFG->goldpath, CFG->semaphore.qwkexport); + MakePathname(CFG->semaphore.soupimport, CFG->goldpath, CFG->semaphore.soupimport); + MakePathname(CFG->semaphore.soupexport, CFG->goldpath, CFG->semaphore.soupexport); + MakePathname(CFG->semaphore.exitnow, CFG->goldpath, CFG->semaphore.exitnow); + + strschg_environ(CFG->jampath); + strschg_environ(CFG->semaphore.importlist); + strschg_environ(CFG->semaphore.exportlist); + strschg_environ(CFG->semaphore.echoscan); + strschg_environ(CFG->semaphore.netscan); + + if(strieql(CFG->semaphore.exportlist, AddPath(CFG->jampath, "echomail.jam"))) { + cout << "* Warning: SEMAPHORE EXPORTLIST must not be the same as ECHOMAIL.JAM!" << endl; + SayBibi(); + cfgerrors++; + } + } + + // Set default xlatimport + if(*CFG->xlatimport == NUL) + strcpy(CFG->xlatimport, CFG->xlatlocalset); + + ReadXlatTables(); + + // Free all mapfile name allocations + vector::iterator xlt; + for(xlt = CFG->xlatescset.begin(); xlt != CFG->xlatescset.end(); xlt++) + throw_release(xlt->mapfile); + for(xlt = CFG->xlatcharset.begin(); xlt != CFG->xlatcharset.end(); xlt++) + throw_release(xlt->mapfile); + + return true; +} + + +// ------------------------------------------------------------------ +// Write GOLDED.GED + +void WriteGoldGed() { + + // Mark areas according to scan/pmscan in/excludes + for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++) { + + gstrarray::iterator i; + + // Check scan in/excludes + for(i = CFG->areascan.begin(); i != CFG->areascan.end(); i++) { + if(strwild((*AL.item)->echoid(), i->c_str())) { + (*AL.item)->set_scan(true); + break; + } + } + for(i = CFG->areascanexcl.begin(); i != CFG->areascanexcl.end(); i++) { + if(strwild((*AL.item)->echoid(), i->c_str())) { + (*AL.item)->set_scanexcl(true); + break; + } + } + for(i = CFG->areascanincl.begin(); i != CFG->areascanincl.end(); i++) { + if(strwild((*AL.item)->echoid(), i->c_str())) { + (*AL.item)->set_scanincl(true); + break; + } + } + + // Check pmscan in/excludes + for(i = CFG->areapmscan.begin(); i != CFG->areapmscan.end(); i++) { + if(strwild((*AL.item)->echoid(), i->c_str())) { + (*AL.item)->set_pmscan(true); + break; + } + } + for(i = CFG->areapmscanexcl.begin(); i != CFG->areapmscanexcl.end(); i++) { + if(strwild((*AL.item)->echoid(), i->c_str())) { + (*AL.item)->set_pmscanexcl(true); + break; + } + } + for(i = CFG->areapmscanincl.begin(); i != CFG->areapmscanincl.end(); i++) { + if(strwild((*AL.item)->echoid(), i->c_str())) { + (*AL.item)->set_pmscanincl(true); + break; + } + } + } + + // Release lists memory + CFG->areaexcl.clear(); + CFG->areaincl.clear(); + CFG->areaisemail.clear(); + CFG->areaisnews.clear(); + CFG->areascan.clear(); + CFG->areascanexcl.clear(); + CFG->areascanincl.clear(); + CFG->arearename.clear(); + CFG->areapmscan.clear(); + CFG->areapmscanexcl.clear(); + CFG->areapmscanincl.clear(); +} + + +// ------------------------------------------------------------------ + +static int EnterString(char* prompt, char* string, uint length) { + + cout << prompt << endl << "> " << flush; + + *string = NUL; + char* ptr = string; + uint pos = 0; + gkey k; + while(1) { + k = kbxget(); + if(k == Key_BS) { + if(pos) { + cout << "\b \b" << flush; + pos--; + *(--ptr) = NUL; + } + } + else if(k == Key_Esc) { + cout << endl; + *string = NUL; + return -1; + } + else if(k == Key_Ent) { + cout << endl; + *ptr = NUL; + break; + } + else { + if(pos < length) { + char c = (char)k; + if(c) { + cout << c << flush; + *ptr++ = c; + pos++; + } + } + } + } + if(*string == NUL) + return 1; + return 0; +} + + +// ------------------------------------------------------------------ + +struct AF_entry { + char* env; + char* configname; + char* name; +}; + +struct AF_entry idetect[] = { + { "DUTCHIE", "dutchie.are", "Dutchie" }, + { "EZY", "constant.ezy", "Ezycom" }, + { "FASTECHO", "fastecho.cfg", "Fastecho" }, + { "FIDOPCB", "fidopcb.cfg", "FidoPCB" }, + { "FMAIL", "fmail.cfg", "FMail" }, + { "IMAIL", "imail.cf", "IMAIL" }, + { "PCBOARD", "pcboard.dat", "PCBoard" }, + { "POPCMDLINE", "portal.are", "Portal" }, + { "RA", "config.pro", "ProBoard" }, + { "QFRONT", "qechos.dat", "QFront" }, + { "RAECHO", "areas.rae", "RA-ECHO" }, + { "RA", "config.ra", "RemoteAccess" }, + { "TIMED", "timed.cfg", "timEd" }, + { "TM", "tm.cfg", "Termail" }, + { "WMAIL", "wmail.prm", "WMail" }, + { "XM", "xmail.cfg", "XMail" }, + { "FD", "areafile.fd", "TosScan" }, + { "GE", "setup.ge", "GEcho" }, + { "FD", "setup.fd", "FrontDoor" }, + { "FD", "fd.sys", "FrontDoor" }, + { "OPUS", "sysmsg.dat", "Opus" }, + { "LORA", "sysmsg.dat", "LoraBBS" }, + { "LORABBS", "sysmsg.dat", "LoraBBS" }, + { "FIDOCONFIG", "", "Fidoconfig" }, + { "DB", "dbridge.prm", "D\'Bridge" }, + { "DBRIDGE", "dbridge.prm", "D\'Bridge" }, + { "SUPERBBS", "sconfig.bbs", "SuperBBS" }, + { "SBBS", "sconfig.bbs", "SuperBBS" }, + { "QUICKBBS", "quickcfg.dat", "QuickBBS" }, + { "QBBS", "quickcfg.dat", "QuickBBS" }, + { "QUICKBBS", "config.bbs", "QuickBBS" }, + { "QBBS", "config.bbs", "QuickBBS" }, + { "SQUISH", "squish.cfg", "Squish" } +}; + + +void InstallDetect(char* path) { + + // Create GOLDED.BAK file if there is an existing GOLDED.CFG + if(fexist(CFG->goldcfg)) { + Path cmdlinecfgbak; + replaceextension(cmdlinecfgbak, CFG->goldcfg, ".bak"); + if(fexist(cmdlinecfgbak)) + remove(cmdlinecfgbak); + rename(CFG->goldcfg, cmdlinecfgbak); + cout << "WARNING: Existing config backed up to " << cmdlinecfgbak << "!!!" << endl; + } + + cout << "Please wait while GoldED+ is detecting your software." << endl; + + FILE* fp = fopen(CFG->goldcfg, "wt"); + if(fp) { + + if(*path) { + PathCopy(CFG->areapath, path); + fprintf(fp, "AREAPATH %s\n", path); + } + + Path pth; + char* ptr; + bool gotareasbbs = false; + bool gotsquish = false; + bool detected = false; + + // simple detection + for(uint i = 0; i < sizeof(idetect)/sizeof(struct AF_entry); i++) { + strcpy(pth, CFG->areapath); + ptr = getenv(idetect[i].env); + if(ptr) { + PathCopy(pth, ptr); + // skip additional information + ptr = strchr(pth, ' '); + if(ptr) + *ptr = NUL; + } + if(fexist(AddPath(pth, idetect[i].configname))) { + fprintf(fp, "AREAFILE %s %s\n", idetect[i].name, pth); + cout << "Found " << idetect[i].name << (ptr ? "." : " (unreliable).") << endl; + if(streql(idetect[i].name, "Squish")) + gotsquish = true; + detected = true; + } + } + + // Detect InterMail + strcpy(pth, CFG->areapath); + ptr = getenv("IM"); + if(ptr) + PathCopy(pth, ptr); + if(fexist(AddPath(pth, "im.exe")) or fexist(AddPath(pth, "intrecho.exe"))) { + fprintf(fp, "AREAFILE InterMail %s\n", pth); + cout << "Found InterMail and/or InterEcho." << endl; + detected = true; + } + + // Detect Maximus + strcpy(pth, CFG->areapath); + ptr = getenv("MAXIMUS"); + if(ptr) { + if(is_dir(ptr)) + PathCopy(pth, ptr); + else + extractdirname(pth, pth); + } + if(fexist(AddPath(pth, "max.prm"))) { + fprintf(fp, "AREAFILE Maximus %s\n", pth); + cout << "Found Maximus." << endl; + detected = true; + } + if(not gotsquish and fexist(AddPath(pth, "squish.cfg"))) { + fprintf(fp, "AREAFILE Squish %s\n", pth); + cout << "Found Squish." << endl; + detected = true; + } + + // Detect ME2 + strcpy(pth, CFG->areapath); + if(fexist(AddPath(pth, "areadesc.me2"))) { + fprintf(fp, "AREAFILE ME2 %sareadesc.me2 %sareas.bbs\n", pth, pth); + cout << "Found ME2." << endl; + gotareasbbs = true; + detected = true; + } + + // Detect AREAS.BBS + if(not gotareasbbs) { + strcpy(pth, CFG->areapath); + if(fexist(AddPath(pth, "areas.bbs"))) { + fprintf(fp, "AREAFILE AreasBBS %sareas.bbs\n", pth); + cout << "Found AREAS.BBS." << endl; + detected = true; + } + } + + if(not detected) + cout << "Sorry, could not find any supported software. Try another path." << endl; + + fclose(fp); + } +} + + +// ------------------------------------------------------------------ + +int InstallFinish() { + + FILE* fp = fopen(CFG->goldcfg, "at"); + if(fp) { + + char buf[77]; + + // Check what we have + + if(CFG->username.empty()) { + if(EnterString("Please enter your name:", buf, sizeof(buf))) + goto install_terminated; + fprintf(fp, "USERNAME %s\n", buf); + CfgUsername(buf); + } + if(CFG->aka.empty()) { + if(EnterString("Please enter your FidoNet address:", buf, sizeof(buf))) + goto install_terminated; + fprintf(fp, "ADDRESS %s\n", buf); + CfgAddress(buf); + } + if(AL.msgbases == 0) { + if(EnterString("Please enter the path to your *.msg netmail area:", buf, sizeof(buf))) + return -1; + fprintf(fp, "AREADEF NETMAIL \"Netmail\" 0 Net Opus %s\n", buf); + AreaCfg aa; + aa.reset(); + aa.setdesc("Netmail"); + aa.setechoid("NETMAIL"); + aa.msgbase = MT_OPUS; + aa.type = AT_NET; + aa.setpath(buf); + aa.attr = CFG->attribsnet; + AL.AddNewArea(&aa); + if(EnterString("Please enter the path *and* filename of your areas.bbs file:", buf, sizeof(buf))) + goto install_terminated; + fprintf(fp, "AREAFILE AreasBBS %s\n", buf); + char buf2[200]="AreasBBS "; + strcat(buf2, buf); + AL.GetAreafile(buf2); + } + #ifndef GMB_NOHUDS + if((AL.msgbases & MT_HUDSON) and (*CFG->hudsonpath == NUL)) { + if(EnterString("Please enter the path to your Hudson msgbase files:", buf, sizeof(buf))) + goto install_terminated; + fprintf(fp, "HUDSONPATH %s\n", buf); + PathCopy(CFG->hudsonpath, buf); + } + #endif + #ifndef GMB_NOGOLD + if((AL.msgbases & MT_GOLDBASE) and (*CFG->goldbasepath == NUL)) { + if(EnterString("Please enter the path to your Goldbase msgbase files:", buf, sizeof(buf))) + goto install_terminated; + fprintf(fp, "GOLDBASEPATH %s\n", buf); + PathCopy(CFG->goldbasepath, buf); + } + #endif + #ifndef GMB_NOJAM + if((AL.msgbases & MT_JAM) and (*CFG->jampath == NUL)) { + if(EnterString("Please enter the path where net/echomail.jam can be placed:", buf, sizeof(buf))) + goto install_terminated; + fprintf(fp, "JAMPATH %s\n", buf); + PathCopy(CFG->jampath, buf); + } + #endif + #ifndef GMB_NOPCB + if((AL.msgbases & MT_PCBOARD) and (*CFG->pcboardpath == NUL)) { + if(EnterString("Please enter the path to PCBoard:", buf, sizeof(buf))) + goto install_terminated; + fprintf(fp, "PCBOARDPATH %s\n", buf); + PathCopy(CFG->pcboardpath, buf); + } + #endif + + fclose(fp); + return 0; + } + +install_terminated: + fclose(fp); + return -1; +} + + +// ------------------------------------------------------------------ + +GoldedCfgEdit::GoldedCfgEdit() { + + memset(&cfg, 0, sizeof(cfg)); + + // Set Boolean values + AutoAttach(true); + AutoSave(30); + ChangeDate(true); + CharPara(' '); + CharSpace(' '); + FieldClear(true); + HardLines(true); + HdrNamePos(8); + HdrNameLen(36); + HdrNodePos(44); + HdrNodeLen(36); + HeaderAttrs(true); + HeaderFirst(EDITHEADERFIRST_YES); + Internal(true); + Menu(true); + MsgSize(512000L); + QuoteMargin(75); + SaveMenu(true); + UnDelete(50); + + str.push_back(""); cfg.external = str.size()-1; + str.push_back("golded.msg"); cfg.file = str.size()-1; + str.push_back("<<"); cfg.hardline = str.size()-1; + str.push_back(""); cfg.spellchecker = str.size()-1; +} + + +// ------------------------------------------------------------------ + +CfgGed::CfgGed() { + + // pathes + strcpy(goldcfg, "golded.cfg"); + strcpy(helpcfg.fn, "goldhelp.cfg"); helpcfg.ft = 0; + replaceextension(helpged, helpcfg.fn, __gver_cfgext__); + strcpy(keyscfg, "goldkeys.cfg"); + strcpy(langcfg, "goldlang.cfg"); + strcpy(goldlast, "goldlast.lst"); + strcpy(golduser, "golduser.lst"); + strcpy(confirmfile, "golded.cfm"); + strxmerge(xlatged, sizeof(xlatged), "goldxlat", __gver_cfgext__, NULL); + strcpy(fidolastread, "lastread"); + strcpy(logfile, "golded.log"); + strcpy(namesfile, "names.fd"); + strcpy(userlistfile, "golded.lst"); + *adeptxbbspath = 0; + *areapath = 0; + *attachpath = 0; + *cookiepath = 0; + *ezycom.msgbasepath = 0; + *ezycom.userbasepath = 0; + *fidouserlist = 0; + *goldbasepath = 0; + *goldbasesyspath = 0; + *goldpath = 0; + *hudsonpath = 0; + *hudsonsyspath = 0; + *inboundpath = 0; + *inputfile = 0; + *jampath = 0; + *loadlanguage = 0; + *nodepath = 0; + *nodepathfd = 0; + *nodepathv7 = 0; + *outboundpath = 0; + *outputfile = 0; + *pathreportfile = 0; + *pcboardpath = 0; + *quotebuffile = 0; + *soundpath = 0; + *soupexportpath = 0; + *soupimportpath = 0; + *soupnewsrcfile = 0; + *soupreplylinker = 0; + *souptosslog = 0; + *squishuserpath = 0; + *templatepath = 0; + *temppath = 0; + *uudecodepath = 0; + *xlatpath = 0; + + // vectors + // cmdkey.clear(); + // macro.clear(); + // addressmacro.clear(); + // aka.clear(); + // akamatch.clear(); + // areaexcl.clear(); + // areaincl.clear(); + // areaisemail.clear(); + // areaisnews.clear(); + // areapmscan.clear(); + // areapmscanexcl.clear(); + // areapmscanincl.clear(); + // arearename.clear(); + // areascan.clear(); + // areascanexcl.clear(); + // areascanincl.clear(); + // event.clear(); + // externutil.clear(); + // filealias.clear(); + // frqext.clear(); + // frqnodemap.clear(); + // kludge.clear(); + // mailinglist.clear(); + // mappath.clear(); + // origin.clear(); + // robotname.clear(); + // tagline.clear(); + // tpl.clear(); + // twitname.clear(); + // twitsubj.clear(); + // username.clear(); + // xlatcharset.clear(); + // xlatescset.clear(); + + // echotags + *areacfmreplyto = 0; + *areacopyto = 0; + *areafreqto = 0; + *areareplyto = 0; + *areastart = 0; + *areayouwroteto = 0; + *soupbadmsgs = 0; + *soupemail = 0; + *soupreplyto = 0; + + // strings + strcpy(arealistformat, "AM D CPUN E G "); + strcpy(arealistsort, "FYTUE"); + strcpy(areascansort, "XZBE"); + strcpy(importbegin, "=== Cut ==="); + *importend = 0; + *internetaddress = 0; + *internetdomain = 0; + *keybstack = 0; + *nickname = 0; + *organization = 0; + #ifdef __UNIX__ + strcpy(printdevice, "/usr/bin/lpr > /dev/null 2>&1"); + #else + strcpy(printdevice, "PRN"); + #endif + *printinit = 0; + *printreset = 0; + *quotechars = 0; + strcpy(quotestring, " FL> "); + *searchfor = 0; + strcpy(stylecodepunct, " !?\"$%&()+,.:;<=>@[\\]^`{|}~\n\r\t"); + *stylecodestops = 0; + sprintf(tasktitle, "%s%s%s%s", __gver_prename__, __gver_name__, + __gver_postname__, __gver_platform__); + strcpy(tearline, "@longpid @version"); + strcpy(whoto, "All"); + *xlatexport = 0; + *xlatimport = 0; + #ifdef __UNIX__ + strcpy(xlatlocalset, "LATIN-1"); + #else + strcpy(xlatlocalset, "IBMPC"); + #endif + + // variables & switches + adeptxbbsuserno = 0; + addressbookadd = YES; + addresslookupfirst = false; + areaautoid = AUTOID_VERBOSE; + areacopydirect = false; + areacopyaddid = false; + areaforwarddirect = false; + areafilegroups = YES; + areafreqdirect = false; + arealistechomax = 0; + arealisttype = AL_TOTNEW; + areareadonly = READONLY_SOFT; + areareplydirect = false; + beepfactor = 1000; + beepyourmail = true; + carboncopylist = CC_NAMES; + cfgdispmargin = NO; + cfgeditquotemargin = 75; + cfgquotemargin = 70; + confirmresponse = ASK; + crosspost = ASK; + crosspostlist = CC_NAMES; + ctrlinfoecho = CI_TAGL|CI_TEAR|CI_ORIG; + ctrlinfoemail = 0; + ctrlinfolocal = CI_TAGL; + ctrlinfonet = CI_TAGL|CI_TEAR; + ctrlinfonews = 0; + dispareano = true; + dispattachsize = ATTACH_KBYTES; + displistcursor = NO; + dispmargin = NO; + dispmsgsize = DISPMSGSIZE_BYTES; + disptabsize = 4; + encodeemailheaders = true; + externoptions = EXTUTIL_CLS | EXTUTIL_SWAP | EXTUTIL_CURSOR | EXTUTIL_RELOAD | EXTUTIL_PAUSEONERROR | EXTUTIL_KEEPCTRL; + ezycomuserno = 0; + fidomsgtype = MT_OPUS; + fidouserno = 0; + forcetemplate = false; + frqoptions = FREQ_FROMTOP; + gedhandshake = true; + goldbaseuserno = 0; + happybirthday = 0; + hidestylies = true; + hudsonsizewarn = 16000000L; + hudsonuserno = 0; + ignorecharset = false; + intensecolors = false; + internetmsgid = false; + internetrfcbody = false; + keybmode = KEYB_POLL; + logformat = 0; + menumarked = MODE_DONT; + msglistdate = MSGLISTDATE_WRITTEN; + msglistfast = true; + msglistfirst = false; + msglistheader = false; + msglistwidesubj = false; + originno = 0; + pcboarduserno = 0; + personalmail = 0; + printlength = 60; + printmargin = 80; + quotebufmode = QBUF_ASK; + quotectrl = CI_TEAR|CI_ORIG; + quotemargin = 70; + quotewraphard = true; + ra2usersbbs = 0; + replylink = 0; + replylinklist = 0; + screenblanker = 180; + screenblankertype = BLANK_SLIDEWIN; + screenmaxcol = 0; + screenmaxrow = 0; + screensize = 0; + sharemode = cmdlinesharemode; + showdeleted = false; + soupexportmargin = 76; + squishscan = 2; // SQS_QUICK + squishuserno = 0; + statuslinehelp = 0; + taglineno = 0; + taglinechar = '.'; + taglinesupport = true; + titlestatus = true; + tplno = 0; + templatematch = false; + timeout = 0; + twitmode = TWIT_BLANK; + usecharset = true; + usefwd = false; + useintl = true; + usepid = true; + usernameno = 0; + usestylies = true; + usetzutc = false; + viewhidden = false; + viewkludge = false; + viewquote = true; + wildcatuserno = 0; + zonegating = ASK; + + // classes + attribsattach.loc1(); + attribscc.loc1(); + attribscfm.loc1(); + attribsecho.loc1(); + // attribsemail.reset(); + attribsfrq.loc1(); + attribslocal.loc1(); + attribsnet.loc1(); + // attribsnews.reset(); + switches.set(akamatchnet, true); + switches.set(areaautonext, true); + switches.set(areacatchupread, true); + switches.set(areakeeplast, true); + switches.set(arealistgroupid, true); + switches.set(arealistpagebar, true); + switches.set(askdelorig, true); + switches.set(beepcomment, true); + switches.set(beepnoises, true); + switches.set(dispautonext, true); + switches.set(displocalhigh, true); + switches.set(disppagebar, true); + switches.set(dispstatusline, true); + switches.set(dosprompt, true); + switches.set(filelistpagebar, true); + switches.set(internetreply, true); + switches.set(keybdefaults, true); + switches.set(keybext, true); + switches.set(kludgechrs, true); + switches.set(lookupnet, true); + switches.set(msglistpagebar, true); + switches.set(msglistviewsubj, true); + switches.set(nodelistwarn, true); + switches.set(printformfeed, true); + switches.set(screenshadows, true); + switches.set(statuslineclock, true); + switches.set(timeoutsavemsg, true); + switches.set(useflags, true); + switches.set(usemsgid, true); + switches.set(rcvdisablescfm, true); + + // screen configuration + disphdrdateset.len = 20; + disphdrdateset.pos = -20; + disphdrnameset.len = 36; + disphdrnameset.pos = 8; + disphdrnodeset.len = 16; + disphdrnodeset.pos = 44; + + // unsorted structures + areatypeorder[AT_NET] = 1; + areatypeorder[AT_NET|AT_EMAIL] = 2; + areatypeorder[AT_ECHO] = 3; + areatypeorder[AT_ECHO|AT_NEWSGROUP] = 4; + areatypeorder[AT_LOCAL] = 5; + if(gvid->adapter & V_MONO) + memcpy(color, gold_mono1, sizeof(color)); + else + memcpy(color, gold_color1, sizeof(color)); + *internetgate.name = 0; + // internetgate.addr.reset(); + *internetserver.nntp.server = 0; + *internetserver.smtp.server = 0; + *internetserver.pop3.server = 0; + *internetserver.pop3.username = 0; + *internetserver.pop3.password = 0; + invalidate.origin.first = " * Origin: "; + invalidate.origin.second = " + Origin: "; + invalidate.seenby.first = "SEEN-BY"; + invalidate.seenby.second = "SEEN+BY"; + invalidate.tearline.first = "---"; + invalidate.tearline.second = "-+-"; + invalidate.cc.first = "CC:"; + invalidate.cc.second = "!CC:"; + invalidate.xc.first = "XC:"; + invalidate.xc.second = "!XC:"; + invalidate.xp.first = "XP:"; + invalidate.xp.second = "!XP:"; + play.type = 0; + play.effectno = 0; + *play.file = 0; + for(int n=0; n<16; n++) + screenpalette[n] = -1; + *semaphore.netscan = 0; + *semaphore.echoscan = 0; + *semaphore.exportlist = 0; + *semaphore.importlist = 0; + *semaphore.scanall = 0; + *semaphore.scanthis = 0; + *semaphore.scannetmail = 0; + *semaphore.pmscanall = 0; + *semaphore.pmscanthis = 0; + *semaphore.pmscannetmail = 0; + *semaphore.qwkimport = 0; + *semaphore.qwkexport = 0; + *semaphore.soupimport = 0; + *semaphore.soupexport = 0; + *semaphore.exitnow = 0; + semaphore.idletime = 0; +} + + +// ------------------------------------------------------------------ + +CfgGed::~CfgGed() { + +} + + +// ------------------------------------------------------------------ diff --git a/golded3/gccfgg.h b/golded3/gccfgg.h new file mode 100644 index 0000000..741fca4 --- /dev/null +++ b/golded3/gccfgg.h @@ -0,0 +1,395 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// CRC16 values for all standard configuration keywords. +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ + +const word CRC_ADDRESS = 0xFDD6; +const word CRC_ADDRESSBOOKADD = 0xFF55; +const word CRC_ADDRESSLOOKUPFIRST=0x2137; +const word CRC_ADDRESSMACRO = 0xDA5F; +const word CRC_ADEPTXBBSPATH = 0x25D6; +const word CRC_ADEPTXBBSUSERNO = 0x0E98; +const word CRC_AKA = 0x13A4; +const word CRC_AKAMATCH = 0xF237; +const word CRC_AKAMATCHECHO = 0xF0C1; +const word CRC_AKAMATCHING = 0x869A; +const word CRC_AKAMATCHLOCAL = 0x4AC4; +const word CRC_AKAMATCHNET = 0xFD6E; +const word CRC_AREA = 0x010B; +const word CRC_AREAAUTOID = 0x365D; +const word CRC_AREAAUTONEXT = 0xF589; +const word CRC_AREACATCHUPREAD = 0xDAFF; +const word CRC_AREACFMREPLYTO = 0x0755; +const word CRC_AREACOPYADDID = 0xAE1E; +const word CRC_AREACOPYDIRECT = 0xDB3D; +const word CRC_AREACOPYTO = 0xFCAF; +const word CRC_AREADEF = 0xA6CC; +const word CRC_AREADESC = 0x0C6F; +const word CRC_AREAEXCL = 0xECCD; +const word CRC_AREAFILE = 0xB487; +const word CRC_AREAFILEGROUPS = 0xF0E7; +const word CRC_AREAFORWARDDIRECT= 0x1E6C; +const word CRC_AREAFREQDIRECT = 0x155A; +const word CRC_AREAFREQTO = 0x3C56; +const word CRC_AREAINCL = 0xDB57; +const word CRC_AREAISEMAIL = 0xB054; +const word CRC_AREAISNEWS = 0x52DB; +const word CRC_AREAKEEPLAST = 0x5876; +const word CRC_AREALISTECHOMAX = 0x944D; +const word CRC_AREALISTFORMAT = 0x9080; +const word CRC_AREALISTGROUPID = 0x1F75; +const word CRC_AREALISTNOS = 0x5FD7; +const word CRC_AREALISTPAGEBAR = 0x6C37; +const word CRC_AREALISTSCAN = 0xDAF7; +const word CRC_AREALISTSORT = 0x0861; +const word CRC_AREALISTTYPE = 0xE110; +const word CRC_AREAPATH = 0x8457; +const word CRC_AREAPMSCAN = 0xE19D; +const word CRC_AREAPMSCANEXCL = 0xA2BE; +const word CRC_AREAPMSCANINCL = 0x9524; +const word CRC_AREAREADONLY = 0xE4F3; +const word CRC_AREARENAME = 0xFC32; +const word CRC_AREAREPLYDIRECT = 0x7570; +const word CRC_AREAREPLYTO = 0x7157; +const word CRC_AREASCAN = 0xE440; +const word CRC_AREASCANEXCL = 0x393E; +const word CRC_AREASCANINCL = 0x0EA4; +const word CRC_AREASCANSORT = 0xE325; +const word CRC_AREASEP = 0xC40C; +const word CRC_AREASTART = 0x7B1A; +const word CRC_AREATYPEORDER = 0xFD13; +const word CRC_AREAYOUWROTETO = 0xC87F; +const word CRC_ASKDELORIG = 0x26DD; +const word CRC_ASSIGNTO = 0xD095; +const word CRC_ATTACHPATH = 0x1400; +const word CRC_ATTRIBSATTACH = 0xAC4F; +const word CRC_ATTRIBSCC = 0xD698; +const word CRC_ATTRIBSCFM = 0x36F6; +const word CRC_ATTRIBSECHO = 0x5FD9; +const word CRC_ATTRIBSEMAIL = 0xC670; +const word CRC_ATTRIBSFRQ = 0x724F; +const word CRC_ATTRIBSLOCAL = 0x16C1; +const word CRC_ATTRIBSNET = 0xE442; +const word CRC_ATTRIBSNEWS = 0xFCF9; +const word CRC_ATTRIBUTES = 0xFD98; +const word CRC_BEEPCOMMENT = 0xC49E; +const word CRC_BEEPFACTOR = 0x8F3A; +const word CRC_BEEPLOCALMSG = 0x984C; +const word CRC_BEEPNOISES = 0x84D5; +const word CRC_BEEPYOURMAIL = 0x0F72; +const word CRC_CARBONCOPYLIST = 0x8290; +const word CRC_COLOR = 0x9F15; +const word CRC_COLORSET = 0x874C; +const word CRC_CONFIRMFILE = 0x1963; +const word CRC_CONFIRMRESPONSE = 0x3D82; +const word CRC_COOKIEPATH = 0x5280; +const word CRC_CROSSPOST = 0x8792; +const word CRC_CROSSPOSTLIST = 0x5854; +const word CRC_CTRLINFO = 0x904A; +const word CRC_CTRLINFOECHO = 0xDE22; +const word CRC_CTRLINFOEMAIL = 0xBCD9; +const word CRC_CTRLINFOLOCAL = 0x6C68; +const word CRC_CTRLINFONET = 0x7660; +const word CRC_CTRLINFONEWS = 0x7D02; +const word CRC_CTRLSEARCH = 0x471F; +const word CRC_DISPAREANO = 0x68CE; +const word CRC_DISPATTACHSIZE = 0x7BB4; +const word CRC_DISPAUTONEXT = 0x52D9; +const word CRC_DISPHDRDATESET = 0x65A5; +const word CRC_DISPHDRNAMESET = 0xFEF9; +const word CRC_DISPHDRNODESET = 0xC232; +const word CRC_DISPLISTCURSOR = 0x8B82; +const word CRC_DISPLISTWRAP = 0xB36D; +const word CRC_DISPLOCALHIGH = 0x1D8B; +const word CRC_DISPMARGIN = 0xC0EC; +const word CRC_DISPMSGSIZE = 0xB0E2; +const word CRC_DISPPAGEBAR = 0x60A4; +const word CRC_DISPREALMSGNO = 0xE30F; +const word CRC_DISPREPLIESMODE = 0x0099; +const word CRC_DISPSOFTCR = 0x85E9; +const word CRC_DISPSTATUSLINE = 0x3FCF; +const word CRC_DISPTABSIZE = 0x01FB; +const word CRC_DOSPROMPT = 0xD983; +const word CRC_EDITAUTOATTACH = 0x62C8; +const word CRC_EDITAUTOSAVE = 0x351B; +const word CRC_EDITCHANGEDATE = 0x847F; +const word CRC_EDITCHARPARA = 0x6CFC; +const word CRC_EDITCHARSPACE = 0x182F; +const word CRC_EDITCOMMENT = 0x662C; +const word CRC_EDITCOMPLETION = 0xDA45; +const word CRC_EDITCRLFTERM = 0x0461; +const word CRC_EDITFIELDCLEAR = 0xC3C4; +const word CRC_EDITHARDLINE = 0xAD88; +const word CRC_EDITHARDLINES = 0xEC14; +const word CRC_EDITHARDTERM = 0xFAD6; +const word CRC_EDITHDRNAMESET = 0x4AB4; +const word CRC_EDITHDRNODESET = 0x767F; +const word CRC_EDITHEADERATTRS = 0x74FD; +const word CRC_EDITHEADERFIRST = 0xE583; +const word CRC_EDITINTERNAL = 0xC2EA; +const word CRC_EDITMENU = 0x833E; +const word CRC_EDITMIXCASE = 0x5814; +const word CRC_EDITMSGSIZE = 0xCF31; +const word CRC_EDITOR = 0xF1C3; +const word CRC_EDITORFILE = 0xA49C; +const word CRC_EDITQUOTEMARGIN = 0xACC7; +const word CRC_EDITREPLYRE = 0x5D23; +const word CRC_EDITSAVEMENU = 0x7BC2; +const word CRC_EDITSAVEUTIL = 0xF411; +const word CRC_EDITSOFTCRXLAT = 0xA49A; +const word CRC_EDITSPELLCHECK = 0xE167; +const word CRC_EDITUNDELETE = 0x4C34; +const word CRC_EMPTYTEARLINE = 0x8D0A; +const word CRC_ENCODEEMAILHEADERS=0xA843; +const word CRC_ENDGROUP = 0x4F27; +const word CRC_EVENT = 0x0471; +const word CRC_EXCLUDENODES = 0x0BFF; +const word CRC_EXTERNOPTIONS = 0xECF5; +const word CRC_EXTERNUTIL = 0xBFD6; +const word CRC_EZYCOMMSGBASE = 0x1A58; +const word CRC_EZYCOMUSERBASE = 0x23D3; +const word CRC_EZYCOMUSERNO = 0x53F6; +const word CRC_FIDOHWMARKS = 0x7E07; +const word CRC_FIDOLASTREAD = 0xB5C3; +const word CRC_FIDOLASTREADNO = 0x4698; +const word CRC_FIDOMSGTYPE = 0x069B; +const word CRC_FIDONULLFIX = 0x4F38; +const word CRC_FIDOUSERLIST = 0xDA02; +const word CRC_FIDOUSERNO = 0x903A; +const word CRC_FILEALIAS = 0xEC23; +const word CRC_FILELISTPAGEBAR = 0x58AA; +const word CRC_FORCETEMPLATE = 0xC8FB; +const word CRC_FORMFEEDSEPARATOR= 0xDBD6; +const word CRC_FREEAREA = 0x93CF; +const word CRC_FRQEXT = 0x0410; +const word CRC_FRQNODEMAP = 0x4684; +const word CRC_FRQOPTIONS = 0x0AD3; +const word CRC_FRQWAZOO = 0xE49C; +const word CRC_GEDHANDSHAKE = 0x344F; +const word CRC_GERMANKEYBOARD = 0x0604; +const word CRC_GOLDBASEPATH = 0x12E1; +const word CRC_GOLDBASESYSPATH = 0x7DD1; +const word CRC_GOLDBASEUSERNO = 0xD42E; +const word CRC_GOLDHELP = 0xE657; +const word CRC_GOLDLANG = 0x6800; +const word CRC_GOLDPATH = 0x3411; +const word CRC_GOLDXLAT = 0x7909; +const word CRC_GROUP = 0x1C9B; +const word CRC_HAPPYBIRTHDAY = 0x7279; +const word CRC_HIGHLIGHTUNREAD = 0x45DA; +const word CRC_HUDSONPATH = 0x52A7; +const word CRC_HUDSONSIZEWARN = 0x111A; +const word CRC_HUDSONSYSPATH = 0xC716; +const word CRC_HUDSONUSERNO = 0xF1E0; +const word CRC_IGNORE = 0xC07B; +const word CRC_IGNORECHARSET = 0x894C; +const word CRC_IMPORTBEGIN = 0x66D7; +const word CRC_IMPORTEND = 0xD9C3; +const word CRC_INBOUNDPATH = 0xDE04; +const word CRC_INCLUDE = 0x379B; +const word CRC_INCLUDENODES = 0xE5F7; +const word CRC_INPUTFILE = 0x7013; +const word CRC_INTENSECOLORS = 0x5F70; +const word CRC_INTERNETADDRESS = 0xA4D3; +const word CRC_INTERNETDOMAIN = 0x50d7; +const word CRC_INTERNETGATE = 0xF6C0; +const word CRC_INTERNETLOOKUP = 0x0E22; +const word CRC_INTERNETMSGID = 0xC31F; +const word CRC_INTERNETREPLY = 0x6253; +const word CRC_INTERNETRFCBODY = 0x9390; +const word CRC_INTERNETSERVER = 0xA01B; +const word CRC_INVALIDATE = 0x69CB; +const word CRC_JAMHARDDELETE = 0xE2D5; +const word CRC_JAMPATH = 0x1200; +const word CRC_KEYBCLEAR = 0xD407; +const word CRC_KEYBDEFAULTS = 0x9FAE; +const word CRC_KEYBEXT = 0xC48A; +const word CRC_KEYBMODE = 0xE8F2; +const word CRC_KEYBSTACK = 0x5F23; +const word CRC_KLUDGE = 0xA600; +const word CRC_KLUDGECHRS = 0x0EEF; +const word CRC_LOADLANGUAGE = 0x9F1B; +const word CRC_LOGFILE = 0x8ACE; +const word CRC_LOGFORMAT = 0x9E51; +const word CRC_LOGLEVEL = 0xCF59; +const word CRC_LOOKUPECHO = 0xB787; +const word CRC_LOOKUPLOCAL = 0x34E7; +const word CRC_LOOKUPNET = 0x7359; +const word CRC_LOOKUPUSERBASE = 0x5852; +const word CRC_MAILINGLIST = 0x08CD; +const word CRC_MAILTOSS = 0x424E; +const word CRC_MAPPATH = 0x74E6; +const word CRC_MEMBER = 0xF703; +const word CRC_MENUDROPMSG = 0x9645; +const word CRC_MENUMARKED = 0x7198; +const word CRC_MOUSE = 0x1B1B; +const word CRC_MSGLISTDATE = 0xBFF5; +const word CRC_MSGLISTFAST = 0xDE86; +const word CRC_MSGLISTFIRST = 0x326F; +const word CRC_MSGLISTHEADER = 0x8B8E; +const word CRC_MSGLISTPAGEBAR = 0x8041; +const word CRC_MSGLISTVIEWSUBJ = 0xED92; +const word CRC_MSGLISTWIDESUBJ = 0xF385; +const word CRC_NAMESFILE = 0x1743; +const word CRC_NICKNAME = 0x70D8; +const word CRC_NODELIST = 0x0E0A; +const word CRC_NODELISTWARN = 0xF818; +const word CRC_NODEPATH = 0xCE00; +const word CRC_NODEPATHFD = 0x731F; +const word CRC_NODEPATHIM = 0x7C16; +const word CRC_NODEPATHV7 = 0x636C; +const word CRC_NODEV7FLAGS = 0x6BEE; +const word CRC_NODEV7MODEM = 0x9CF7; +const word CRC_ORGANIZATION = 0x8ADC; +const word CRC_ORIGIN = 0x4CE5; +const word CRC_OUTBOUNDPATH = 0xB089; +const word CRC_OUTPUTFILE = 0xA697; +const word CRC_PATHREPORTFILE = 0x8700; +const word CRC_PCBOARDPATH = 0xC08B; +const word CRC_PCBOARDUSERNO = 0x6A87; +const word CRC_PERSONALMAIL = 0xD340; +const word CRC_PLAY = 0xC6AE; +const word CRC_PRINTDEVICE = 0xA4C3; +const word CRC_PRINTFORMFEED = 0x59FB; +const word CRC_PRINTINIT = 0xB195; +const word CRC_PRINTLENGTH = 0x5D19; +const word CRC_PRINTMARGIN = 0xAC75; +const word CRC_PRINTRESET = 0xEFBD; +const word CRC_QUOTEBLANK = 0xD3BB; +const word CRC_QUOTEBUFFILE = 0xDE2A; +const word CRC_QUOTEBUFMODE = 0x6A16; +const word CRC_QUOTECHARS = 0x3457; +const word CRC_QUOTECTRL = 0x4CC7; +const word CRC_QUOTEMARGIN = 0x13E6; +const word CRC_QUOTESPACING = 0xB403; +const word CRC_QUOTESTRING = 0xE44F; +const word CRC_QUOTEWRAPHARD = 0x6BD4; +const word CRC_QWKBADMSGS = 0x0C2D; +const word CRC_QWKCONFMAP = 0xEAE1; +const word CRC_QWKEXPORTPATH = 0xB3AB; +const word CRC_QWKIMPORTPATH = 0xECC0; +const word CRC_QWKOPTIONS = 0x155E; +const word CRC_QWKREPLYLINKER = 0x2A06; +const word CRC_QWKTOSSLOG = 0x6AED; +const word CRC_RA2USERSBBS = 0x1916; +const word CRC_RCVDISABLESCFM = 0xD3B2; +const word CRC_REGISTERKEY = 0xF428; +const word CRC_REGISTERNAME = 0x2CAF; +const word CRC_REPLYLINK = 0x88A1; +const word CRC_REPLYLINKLIST = 0x104F; +const word CRC_ROBOTNAME = 0x7393; +const word CRC_SCREENBLANKER = 0x5CF7; +const word CRC_SCREENMAXCOL = 0xFFFC; +const word CRC_SCREENMAXROW = 0xFDF7; +const word CRC_SCREENPALETTE = 0x49CA; +const word CRC_SCREENSHADOWS = 0x8543; +const word CRC_SCREENSIZE = 0xC3A5; +const word CRC_SCREENUSEANSI = 0x7A70; +const word CRC_SCREENUSEBIOS = 0x43DE; +const word CRC_SEARCHFOR = 0x9FA6; +const word CRC_SEMAPHORE = 0x02FB; +const word CRC_SERIALNO = 0x6EDE; +const word CRC_SHAREMODE = 0x068E; +const word CRC_SHOWDELETED = 0xA9CE; +const word CRC_SOUNDDEVICE = 0x831D; +const word CRC_SOUNDPATH = 0xA4DA; +const word CRC_SOUPBADMSGS = 0x372E; +const word CRC_SOUPEMAIL = 0x423C; +const word CRC_SOUPEXPORTMARGIN = 0x0434; +const word CRC_SOUPEXPORTPATH = 0xD3AC; +const word CRC_SOUPIMPORTPATH = 0x8CC7; +const word CRC_SOUPNEWSRCFILE = 0x6961; +const word CRC_SOUPREPLYLINKER = 0x41A0; +const word CRC_SOUPREPLYTO = 0xE741; +const word CRC_SOUPTOSSLOG = 0x51EE; +const word CRC_SQUISHDIRECT = 0x7C35; +const word CRC_SQUISHSCAN = 0xE388; +const word CRC_SQUISHUSERNO = 0x60AD; +const word CRC_SQUISHUSERPATH = 0xFA97; +const word CRC_STATUSLINECLOCK = 0x9C8A; +const word CRC_STATUSLINEHELP = 0xA150; +const word CRC_STYLECODES = 0x4CB0; +const word CRC_STYLECODEPUNCT = 0x9D15; +const word CRC_STYLECODESTOPS = 0xF452; +const word CRC_TAGLINE = 0xC328; +const word CRC_TAGLINECHAR = 0xD71E; +const word CRC_TAGLINEINTERNAL = 0x0B41; +const word CRC_TAGLINESUPPORT = 0x1F4D; +const word CRC_TASKTITLE = 0xECEC; +const word CRC_TEARLINE = 0xB385; +const word CRC_TEMPLATE = 0x09DF; +const word CRC_TEMPLATEMATCH = 0xECA9; +const word CRC_TEMPLATEPATH = 0xB8C0; +const word CRC_TEMPPATH = 0x4FCC; +const word CRC_TIMEOUT = 0x4065; +const word CRC_TIMEOUTSAVEMSG = 0xF644; +const word CRC_TIMESLICE = 0x3EFF; +const word CRC_TIMESREAD = 0xDD0E; +const word CRC_TITLESTATUS = 0x5ABA; +const word CRC_TWITMODE = 0x9DC8; +const word CRC_TWITNAME = 0x2055; +const word CRC_TWITSUBJ = 0x08C0; +const word CRC_TWITTO = 0x9DFE; +const word CRC_USECHARSET = 0xE1B9; +const word CRC_USEFLAGS = 0xE2B6; +const word CRC_USEFWD = 0x439F; +const word CRC_USEINTL = 0x64CD; +const word CRC_USEMSGID = 0x6FDB; +const word CRC_USEPID = 0x2F68; +const word CRC_USERLIST = 0xE81A; +const word CRC_USERLISTFILE = 0xB749; +const word CRC_USERNAME = 0x1161; +const word CRC_USETZUTC = 0x27C5; +const word CRC_UUDECODEPATH = 0x82A2; +const word CRC_VIEWHIDDEN = 0x021D; +const word CRC_VIEWKLUDGE = 0x4078; +const word CRC_VIEWQUOTE = 0x0AB3; +const word CRC_WHOTO = 0xB25F; +const word CRC_WILDCATUSERNO = 0xC2FE; +const word CRC_XLATCHARSET = 0xA860; +const word CRC_XLATESCSET = 0x4BA7; +const word CRC_XLATEXPORT = 0x29CB; +const word CRC_XLATIMPORT = 0xCE6A; +const word CRC_XLATLOCALSET = 0x7180; +const word CRC_XLATPATH = 0x7FA1; +const word CRC_ZONEGATING = 0x956C; + +const word CRC_IF = 0x4946; +const word CRC_ELIF = 0x3237; +const word CRC_ELSE = 0x2834; +const word CRC_ELSEIF = 0xB0DE; +const word CRC_ENDIF = 0x9998; +const word CRC_REM = 0x3FFA; + + +// ------------------------------------------------------------------ + +const word CRC_LAST_CRC = 0xFFFF; + + +// ------------------------------------------------------------------ + diff --git a/golded3/gccfgg0.cpp b/golded3/gccfgg0.cpp new file mode 100644 index 0000000..bd65eac --- /dev/null +++ b/golded3/gccfgg0.cpp @@ -0,0 +1,869 @@ + +// ------------------------------------------------------------------ +// GoldED+ +// Copyright (C) 1998-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$ +// ------------------------------------------------------------------ +// Configuration functions, part 0. +// ------------------------------------------------------------------ + +#include +#include +#include + + +// ------------------------------------------------------------------ + +bool cfgingroup = false; +char* val; + + +// ------------------------------------------------------------------ + +struct tglobalbool { + word crc_token; +}; + +// it must be sorted by value +tglobalbool globalbool[gswitches_last] = { + { CRC_INTERNETLOOKUP }, // 0x0E22; + { CRC_KLUDGECHRS }, // 0x0EEF; + { CRC_MOUSE }, // 0x1B1B; + { CRC_DISPLOCALHIGH }, // 0x1D8B; + { CRC_AREALISTGROUPID }, // 0x1F75; + { CRC_ASKDELORIG }, // 0x26DD; + { CRC_LOOKUPLOCAL }, // 0x34E7; + { CRC_DISPSTATUSLINE }, // 0x3FCF; + { CRC_SCREENUSEBIOS }, // 0x43DE; + { CRC_HIGHLIGHTUNREAD }, // 0x45DA; + { CRC_AKAMATCHLOCAL }, // 0x4AC4; + { CRC_FIDONULLFIX }, // 0x4F38; + { CRC_DISPAUTONEXT }, // 0x52D9; + { CRC_LOOKUPUSERBASE }, // 0x5852; + { CRC_AREAKEEPLAST }, // 0x5876; + { CRC_FILELISTPAGEBAR }, // 0x58AA; + { CRC_PRINTFORMFEED }, // 0x59FB; + { CRC_AREALISTNOS }, // 0x5FD7; + { CRC_DISPPAGEBAR }, // 0x60A4; + { CRC_INTERNETREPLY }, // 0x6253; + { CRC_AREALISTPAGEBAR }, // 0x6C37; + { CRC_USEMSGID }, // 0x6FDB; + { CRC_LOOKUPNET }, // 0x7359; + { CRC_SQUISHDIRECT }, // 0x7C35; + { CRC_FIDOHWMARKS }, // 0x7E07; + { CRC_MSGLISTPAGEBAR }, // 0x8041; + { CRC_BEEPNOISES }, // 0x84D5; + { CRC_SCREENSHADOWS }, // 0x8543; + { CRC_DISPSOFTCR }, // 0x85E9; + { CRC_EMPTYTEARLINE }, // 0x8D0A; + { CRC_MENUDROPMSG }, // 0x9645; + { CRC_BEEPLOCALMSG }, // 0x984C; + { CRC_STATUSLINECLOCK }, // 0x9C8A; + { CRC_TWITTO }, // 0x9DFE; + { CRC_KEYBDEFAULTS }, // 0x9FAE; + { CRC_DISPLISTWRAP }, // 0xB36D; + { CRC_QUOTESPACING }, // 0xB403; + { CRC_LOOKUPECHO }, // 0xB787; + { CRC_KEYBEXT }, // 0xC48A; + { CRC_BEEPCOMMENT }, // 0xC49E; + { CRC_RCVDISABLESCFM }, // 0xD3B2; + { CRC_QUOTEBLANK }, // 0xD3BB; + { CRC_KEYBCLEAR }, // 0xD407; + { CRC_DOSPROMPT }, // 0xD983; + { CRC_AREACATCHUPREAD }, // 0xDAFF; + { CRC_FORMFEEDSEPARATOR }, // 0xDBD6; + { CRC_USEFLAGS }, // 0xE2B6; + { CRC_JAMHARDDELETE }, // 0xE2D5; + { CRC_DISPREALMSGNO }, // 0xE30F; + { CRC_FRQWAZOO }, // 0xE49C; + { CRC_MSGLISTVIEWSUBJ }, // 0xED92; + { CRC_AKAMATCHECHO }, // 0xF0C1; + { CRC_AREAFILEGROUPS }, // 0xF0E7; + { CRC_AREAAUTONEXT }, // 0xF589; + { CRC_TIMEOUTSAVEMSG }, // 0xF644; + { CRC_NODELISTWARN }, // 0xF818; + { CRC_AKAMATCHNET }, // 0xFD6E; +}; + +bool gswitches::handle(word crc, const char* value) { + + uint left,right,middle; + word cur; + + left = 0; + right = gswitches_last - 1; + + if((crc < globalbool[left].crc_token) or (crc > globalbool[right].crc_token)) + return false; + + do { + middle = (left + right)/2; + + cur = globalbool[middle].crc_token; + + if(crc < cur) { + right = middle - 1; + } else if(crc > cur) { + left = middle + 1; + } + else { + cfg[middle] = GetYesno(value); + return true; + } + } while(left <= right); + + return false; +} + +// ------------------------------------------------------------------ + +int SwitchCfg(word crc, char k, char* v) { + + val = v; + bool found = true; + + if(CFG->switches.handle(crc,v)) + return true; + + // Switch the first letter of the keyword + switch(toupper(k)) { + case 'A': goto SwitchA; + case 'B': goto SwitchB; + case 'C': goto SwitchC; + case 'D': goto SwitchD; + case 'E': goto SwitchE; + case 'F': goto SwitchF; + case 'G': goto SwitchG; + case 'H': goto SwitchH; + case 'I': goto SwitchI; + case 'J': goto SwitchJ; + case 'K': goto SwitchK; + case 'L': goto SwitchL; + case 'M': goto SwitchM; + case 'N': goto SwitchN; + case 'O': goto SwitchO; + case 'P': goto SwitchP; + case 'Q': goto SwitchQ; + case 'R': goto SwitchR; + case 'S': goto SwitchS; + case 'T': goto SwitchT; + case 'U': goto SwitchU; + case 'V': goto SwitchV; + case 'W': goto SwitchW; + case 'X': goto SwitchX; + case 'Y': goto SwitchY; + case 'Z': goto SwitchZ; + default: found = false; + } + goto End; + +SwitchA: + switch(crc) { + case CRC_ADDRESS : CfgAddress (); break; + case CRC_ADDRESSBOOKADD : CfgAddressbookadd (); break; + case CRC_ADDRESSLOOKUPFIRST: CfgAddresslookupfirst(); break; + case CRC_ADDRESSMACRO : CfgAddressmacro (); break; + case CRC_ADEPTXBBSPATH : CfgAdeptxbbspath (); break; + case CRC_ADEPTXBBSUSERNO : CfgAdeptxbbsuserno (); break; + case CRC_AKA : CfgAddress (); break; + case CRC_AKAMATCH : CfgAkamatch (); break; + case CRC_AKAMATCHING : CfgAkamatching (); break; + case CRC_AREA : CfgArea (); break; + case CRC_AREAAUTOID : CfgAreaautoid (); break; + case CRC_AREACFMREPLYTO : CfgAreacfmreplyto (); break; + case CRC_AREACOPYADDID : CfgAreacopyaddid (); break; + case CRC_AREACOPYDIRECT : CfgAreacopydirect (); break; + case CRC_AREACOPYTO : CfgAreacopyto (); break; + case CRC_AREADEF : CfgAreadef (); break; + case CRC_AREADESC : CfgAreadesc (); break; + case CRC_AREAEXCL : CfgAreaexcl (); break; + case CRC_AREAFORWARDDIRECT: CfgAreaforwarddirect(); break; + case CRC_AREAFREQDIRECT : CfgAreafreqdirect (); break; + case CRC_AREAFREQTO : CfgAreafreqto (); break; + case CRC_AREAINCL : CfgAreaincl (); break; + case CRC_AREAISEMAIL : CfgAreaisemail (); break; + case CRC_AREAISNEWS : CfgAreaisnews (); break; + case CRC_AREALISTECHOMAX : CfgArealistechomax (); break; + case CRC_AREALISTFORMAT : CfgArealistformat (); break; + case CRC_AREALISTSCAN : CfgArealistscan (); break; + case CRC_AREALISTSORT : CfgArealistsort (); break; + case CRC_AREALISTTYPE : CfgArealisttype (); break; + case CRC_AREAPATH : CfgAreapath (); break; + case CRC_AREAPMSCAN : CfgAreapmscan (); break; + case CRC_AREAPMSCANEXCL : CfgAreapmscanexcl (); break; + case CRC_AREAPMSCANINCL : CfgAreapmscanincl (); break; + case CRC_AREAREADONLY : CfgAreareadonly (); break; + case CRC_AREARENAME : CfgArearename (); break; + case CRC_AREAREPLYDIRECT : CfgAreareplydirect (); break; + case CRC_AREAREPLYTO : CfgAreareplyto (); break; + case CRC_AREASCAN : CfgAreascan (); break; + case CRC_AREASCANEXCL : CfgAreascanexcl (); break; + case CRC_AREASCANINCL : CfgAreascanincl (); break; + case CRC_AREASCANSORT : CfgAreascansort (); break; + case CRC_AREASEP : CfgAreasep (); break; + case CRC_AREASTART : CfgAreastart (); break; + case CRC_AREATYPEORDER : CfgAreatypeorder (); break; + case CRC_AREAYOUWROTETO : CfgAreayouwroteto (); break; + case CRC_ATTACHPATH : CfgAttachpath (); break; + case CRC_ATTRIBSATTACH : CfgAttribsattach (); break; + case CRC_ATTRIBSCC : CfgAttribscc (); break; + case CRC_ATTRIBSCFM : CfgAttribscfm (); break; + case CRC_ATTRIBSECHO : CfgAttribsecho (); break; + case CRC_ATTRIBSEMAIL : CfgAttribsemail (); break; + case CRC_ATTRIBSFRQ : CfgAttribsfrq (); break; + case CRC_ATTRIBSLOCAL : CfgAttribslocal (); break; + case CRC_ATTRIBSNET : CfgAttribsnet (); break; + case CRC_ATTRIBSNEWS : CfgAttribsnews (); break; + case CRC_ATTRIBUTES : CfgAttributes (); break; + default : found = false; + } + goto End; + +SwitchB: + switch(crc) { + case CRC_BEEPFACTOR : CfgBeepfactor (); break; + case CRC_BEEPYOURMAIL : CfgBeepyourmail (); break; + default : found = false; + } + goto End; + +SwitchC: + switch(crc) { + case CRC_CARBONCOPYLIST : CfgCarboncopylist (); break; + case CRC_COLOR : CfgColor (); break; + case CRC_COLORSET : CfgColorset (); break; + case CRC_CONFIRMFILE : CfgConfirmfile (); break; + case CRC_CONFIRMRESPONSE : CfgConfirmresponse (); break; + case CRC_COOKIEPATH : CfgCookiepath (); break; + case CRC_CROSSPOST : CfgCrosspost (); break; + case CRC_CROSSPOSTLIST : CfgCrosspostlist (); break; + case CRC_CTRLINFO : CfgCtrlinfo (); break; + case CRC_CTRLINFOECHO : CfgCtrlinfoecho (); break; + case CRC_CTRLINFOEMAIL : CfgCtrlinfoemail (); break; + case CRC_CTRLINFOLOCAL : CfgCtrlinfolocal (); break; + case CRC_CTRLINFONET : CfgCtrlinfonet (); break; + case CRC_CTRLINFONEWS : CfgCtrlinfonews (); break; + default : found = false; + } + goto End; + +SwitchD: + switch(crc) { + case CRC_DISPAREANO : CfgDispareano (); break; + case CRC_DISPATTACHSIZE : CfgDispattachsize (); break; + case CRC_DISPHDRDATESET : CfgDisphdrdateset (); break; + case CRC_DISPHDRNAMESET : CfgDisphdrnameset (); break; + case CRC_DISPHDRNODESET : CfgDisphdrnodeset (); break; + case CRC_DISPLISTCURSOR : CfgDisplistcursor (); break; + case CRC_DISPMARGIN : CfgDispmargin (); break; + case CRC_DISPMSGSIZE : CfgDispmsgsize (); break; + case CRC_DISPTABSIZE : CfgDisptabsize (); break; + default : found = false; + } + goto End; + +SwitchE: + switch(crc) { + case CRC_EDITAUTOATTACH : CfgEditautoattach (); break; + case CRC_EDITAUTOSAVE : CfgEditautosave (); break; + case CRC_EDITCHANGEDATE : CfgEditchangedate (); break; + case CRC_EDITCHARPARA : CfgEditcharpara (); break; + case CRC_EDITCHARSPACE : CfgEditcharspace (); break; + case CRC_EDITCOMMENT : CfgEditcomment (); break; + case CRC_EDITCOMPLETION : CfgEditcompletion (); break; + case CRC_EDITCRLFTERM : CfgEditcrlfterm (); break; + case CRC_EDITFIELDCLEAR : CfgEditfieldclear (); break; + case CRC_EDITHARDLINE : CfgEdithardline (); break; + case CRC_EDITHARDLINES : CfgEdithardlines (); break; + case CRC_EDITHARDTERM : CfgEdithardterm (); break; + case CRC_EDITHDRNAMESET : CfgEdithdrnameset (); break; + case CRC_EDITHDRNODESET : CfgEdithdrnodeset (); break; + case CRC_EDITHEADERATTRS : CfgEditheaderattrs (); break; + case CRC_EDITHEADERFIRST : CfgEditheaderfirst (); break; + case CRC_EDITINTERNAL : CfgEditinternal (); break; + case CRC_EDITMENU : CfgEditmenu (); break; + case CRC_EDITMIXCASE : CfgEditmixcase (); break; + case CRC_EDITMSGSIZE : CfgEditmsgsize (); break; + case CRC_EDITOR : CfgEditor (); break; + case CRC_EDITORFILE : CfgEditorfile (); break; + case CRC_EDITQUOTEMARGIN : CfgEditquotemargin (); break; + case CRC_EDITREPLYRE : CfgEditreplyre (); break; + case CRC_EDITSAVEMENU : CfgEditsavemenu (); break; + case CRC_EDITSAVEUTIL : CfgEditsaveutil (); break; + case CRC_EDITSOFTCRXLAT : CfgEditsoftcrxlat (); break; + case CRC_EDITSPELLCHECK : CfgEditspellcheck (); break; + case CRC_EDITUNDELETE : CfgEditundelete (); break; + case CRC_ENDGROUP : CfgEndgroup (); break; + case CRC_ENCODEEMAILHEADERS: CfgEncodeemailheaders(); break; + case CRC_EVENT : CfgEvent (); break; + case CRC_EXCLUDENODES : CfgExcludenodes (); break; + case CRC_EXTERNOPTIONS : CfgExternoptions (); break; + case CRC_EXTERNUTIL : CfgExternutil (); break; + case CRC_EZYCOMMSGBASE : CfgEzycommsgbase (); break; + case CRC_EZYCOMUSERBASE : CfgEzycomuserbase (); break; + case CRC_EZYCOMUSERNO : CfgEzycomuserno (); break; + default : found = false; + } + goto End; + +SwitchF: + switch(crc) { + case CRC_FIDOLASTREAD : CfgFidolastread (); break; + case CRC_FIDOMSGTYPE : CfgFidomsgtype (); break; + case CRC_FIDOUSERLIST : CfgFidouserlist (); break; + case CRC_FIDOUSERNO : CfgFidouserno (); break; + case CRC_FILEALIAS : CfgFilealias (); break; + case CRC_FORCETEMPLATE : CfgForcetemplate (); break; + case CRC_FRQEXT : CfgFrqext (); break; + case CRC_FRQNODEMAP : CfgFrqnodemap (); break; + case CRC_FRQOPTIONS : CfgFrqoptions (); break; + default : found = false; + } + goto End; + +SwitchG: + switch(crc) { + case CRC_GEDHANDSHAKE : CfgGedhandshake (); break; + case CRC_GERMANKEYBOARD : CfgGermankeyboard (); break; + case CRC_GOLDBASEPATH : CfgGoldbasepath (); break; + case CRC_GOLDBASESYSPATH : CfgGoldbasesyspath (); break; + case CRC_GOLDBASEUSERNO : CfgGoldbaseuserno (); break; + case CRC_GOLDPATH : CfgGoldpath (); break; + case CRC_GROUP : CfgGroup (); break; + default : found = false; + } + goto End; + +SwitchH: + switch(crc) { + case CRC_HAPPYBIRTHDAY : CfgHappybirthday (); break; + case CRC_HUDSONPATH : CfgHudsonpath (); break; + case CRC_HUDSONSIZEWARN : CfgHudsonsizewarn (); break; + case CRC_HUDSONSYSPATH : CfgHudsonsyspath (); break; + case CRC_HUDSONUSERNO : CfgHudsonuserno (); break; + default : found = false; + } + goto End; + +SwitchI: + switch(crc) { + case CRC_IGNORECHARSET : CfgIgnorecharset (); break; + case CRC_IMPORTBEGIN : CfgImportbegin (); break; + case CRC_IMPORTEND : CfgImportend (); break; + case CRC_INBOUNDPATH : CfgInboundpath (); break; + case CRC_INCLUDENODES : CfgIncludenodes (); break; + case CRC_INPUTFILE : CfgInputfile (); break; + case CRC_INTENSECOLORS : CfgIntensecolors (); break; + case CRC_INTERNETADDRESS : CfgInternetaddress (); break; + case CRC_INTERNETDOMAIN : CfgInternetdomain (); break; + case CRC_INTERNETGATE : CfgInternetgate (); break; + case CRC_INTERNETMSGID : CfgInternetmsgid (); break; + case CRC_INTERNETRFCBODY : CfgInternetrfcbody (); break; + case CRC_INTERNETSERVER : CfgInternetserver (); break; + case CRC_INVALIDATE : CfgInvalidate (); break; + default : found = false; + } + goto End; + +SwitchJ: + switch(crc) { + case CRC_JAMPATH : CfgJampath (); break; + default : found = false; + } + goto End; + +SwitchK: + switch(crc) { + case CRC_KEYBMODE : CfgKeybmode (); break; + case CRC_KEYBSTACK : CfgKeybstack (); break; + case CRC_KLUDGE : CfgKludge (); break; + default : found = false; + } + goto End; + +SwitchL: + switch(crc) { + case CRC_LOADLANGUAGE : CfgLoadlanguage (); break; + case CRC_LOGFILE : CfgLogfile (); break; + case CRC_LOGFORMAT : CfgLogformat (); break; + default : found = false; + } + goto End; + +SwitchM: + switch(crc) { + case CRC_MAILINGLIST : CfgMailinglist (); break; + case CRC_MAILTOSS : CfgMailtoss (); break; + case CRC_MAPPATH : CfgMappath (); break; + case CRC_MEMBER : CfgMember (); break; + case CRC_MENUMARKED : CfgMenumarked (); break; + case CRC_MSGLISTDATE : CfgMsglistdate (); break; + case CRC_MSGLISTFAST : CfgMsglistfast (); break; + case CRC_MSGLISTFIRST : CfgMsglistfirst (); break; + case CRC_MSGLISTHEADER : CfgMsglistheader (); break; + case CRC_MSGLISTWIDESUBJ : CfgMsglistwidesubj (); break; + default : found = false; + } + goto End; + +SwitchN: + switch(crc) { + case CRC_NAMESFILE : CfgNamesfile (); break; + case CRC_NICKNAME : CfgNickname (); break; + case CRC_NODELIST : CfgNodelist (); break; + case CRC_NODEPATH : CfgNodepath (); break; + case CRC_NODEPATHFD : CfgNodepathfd (); break; + case CRC_NODEPATHIM : CfgNodepathfd (); break; + case CRC_NODEPATHV7 : CfgNodepathv7 (); break; + case CRC_NODEV7FLAGS : CfgNodev7flags (); break; + case CRC_NODEV7MODEM : CfgNodev7modem (); break; + default : found = false; + } + goto End; + +SwitchO: + switch(crc) { + case CRC_ORGANIZATION : CfgOrganization (); break; + case CRC_ORIGIN : CfgOrigin (); break; + case CRC_OUTBOUNDPATH : CfgOutboundpath (); break; + case CRC_OUTPUTFILE : CfgOutputfile (); break; + default : found = false; + } + goto End; + +SwitchP: + switch(crc) { + case CRC_PCBOARDPATH : CfgPcboardpath (); break; + case CRC_PCBOARDUSERNO : CfgPcboarduserno (); break; + case CRC_PERSONALMAIL : CfgPersonalmail (); break; + case CRC_PLAY : CfgPlay (); break; + case CRC_PRINTDEVICE : CfgPrintdevice (); break; + case CRC_PRINTINIT : CfgPrintinit (); break; + case CRC_PRINTLENGTH : CfgPrintlength (); break; + case CRC_PRINTMARGIN : CfgPrintmargin (); break; + case CRC_PRINTRESET : CfgPrintreset (); break; + default : found = false; + } + goto End; + +SwitchQ: + switch(crc) { + case CRC_QUOTEBUFFILE : CfgQuotebuffile (); break; + case CRC_QUOTEBUFMODE : CfgQuotebufmode (); break; + case CRC_QUOTECHARS : CfgQuotechars (); break; + case CRC_QUOTECTRL : CfgQuotectrl (); break; + case CRC_QUOTEMARGIN : CfgQuotemargin (); break; + case CRC_QUOTESTRING : CfgQuotestring (); break; + case CRC_QUOTEWRAPHARD : CfgQuotewraphard (); break; + case CRC_QWKBADMSGS : CfgQwkbadmsgs (); break; + case CRC_QWKCONFMAP : CfgQwkconfmap (); break; + case CRC_QWKEXPORTPATH : CfgQwkexportpath (); break; + case CRC_QWKIMPORTPATH : CfgQwkimportpath (); break; + case CRC_QWKOPTIONS : CfgQwkoptions (); break; + case CRC_QWKREPLYLINKER : CfgQwkreplylinker (); break; + case CRC_QWKTOSSLOG : CfgQwktosslog (); break; + default : found = false; + } + goto End; + +SwitchR: + switch(crc) { + case CRC_RA2USERSBBS : CfgRa2usersbbs (); break; + case CRC_REGISTERKEY : break; + case CRC_REGISTERNAME : break; + case CRC_REPLYLINK : CfgReplylink (); break; + case CRC_REPLYLINKLIST : CfgReplylinklist (); break; + case CRC_ROBOTNAME : CfgRobotname (); break; + default : found = false; + } + goto End; + +SwitchS: + switch(crc) { + case CRC_SCREENBLANKER : CfgScreenblanker (); break; + case CRC_SCREENMAXCOL : CfgScreenmaxcol (); break; + case CRC_SCREENMAXROW : CfgScreenmaxrow (); break; + case CRC_SCREENPALETTE : CfgScreenpalette (); break; + case CRC_SCREENSIZE : CfgScreensize (); break; + case CRC_SEARCHFOR : CfgSearchfor (); break; + case CRC_SEMAPHORE : CfgSemaphore (); break; + case CRC_SERIALNO : break; + case CRC_SHAREMODE : CfgSharemode (); break; + case CRC_SHOWDELETED : CfgShowdeleted (); break; + case CRC_SOUNDPATH : CfgSoundpath (); break; + case CRC_SOUPBADMSGS : CfgSoupbadmsgs (); break; + case CRC_SOUPEMAIL : CfgSoupemail (); break; + case CRC_SOUPEXPORTMARGIN : CfgSoupexportmargin (); break; + case CRC_SOUPEXPORTPATH : CfgSoupexportpath (); break; + case CRC_SOUPIMPORTPATH : CfgSoupimportpath (); break; + case CRC_SOUPNEWSRCFILE : CfgSoupnewsrcfile (); break; + case CRC_SOUPREPLYLINKER : CfgSoupreplylinker (); break; + case CRC_SOUPREPLYTO : CfgSoupreplyto (); break; + case CRC_SOUPTOSSLOG : CfgSouptosslog (); break; + case CRC_SQUISHSCAN : CfgSquishscan (); break; + case CRC_SQUISHUSERNO : CfgSquishuserno (); break; + case CRC_SQUISHUSERPATH : CfgSquishuserpath (); break; + case CRC_STATUSLINEHELP : CfgStatuslinehelp (); break; + case CRC_STYLECODEPUNCT : CfgStylecodepunct (); break; + case CRC_STYLECODES : CfgStylecodes (); break; + case CRC_STYLECODESTOPS : CfgStylecodestops (); break; + default : found = false; + } + goto End; + +SwitchT: + switch(crc) { + case CRC_TAGLINE : CfgTagline (); break; + case CRC_TAGLINECHAR : CfgTaglinechar (); break; + case CRC_TAGLINESUPPORT : CfgTaglinesupport (); break; + case CRC_TASKTITLE : CfgTasktitle (); break; + case CRC_TEARLINE : CfgTearline (); break; + case CRC_TEMPLATE : CfgTemplate (); break; + case CRC_TEMPLATEMATCH : CfgTemplatematch (); break; + case CRC_TEMPLATEPATH : CfgTemplatepath (); break; + case CRC_TEMPPATH : CfgTemppath (); break; + case CRC_TIMEOUT : CfgTimeout (); break; + case CRC_TITLESTATUS : CfgTitlestatus (); break; + case CRC_TWITMODE : CfgTwitmode (); break; + case CRC_TWITNAME : CfgTwitname (); break; + case CRC_TWITSUBJ : CfgTwitsubj (); break; + default : found = false; + } + goto End; + +SwitchU: + switch(crc) { + case CRC_USECHARSET : CfgUsecharset (); break; + case CRC_USEFWD : CfgUsefwd (); break; + case CRC_USEINTL : CfgUseintl (); break; + case CRC_USEPID : CfgUsepid (); break; + case CRC_USERLIST : CfgUserlist (); break; + case CRC_USERLISTFILE : CfgUserlistfile (); break; + case CRC_USERNAME : CfgUsername (); break; + case CRC_USETZUTC : CfgUsetzutc (); break; + case CRC_UUDECODEPATH : CfgUudecodepath (); break; + default : found = false; + } + goto End; + +SwitchV: + switch(crc) { + case CRC_VIEWHIDDEN : CfgViewhidden (); break; + case CRC_VIEWKLUDGE : CfgViewkludge (); break; + case CRC_VIEWQUOTE : CfgViewquote (); break; + default : found = false; + } + goto End; + +SwitchW: + switch(crc) { + case CRC_WHOTO : CfgWhoto (); break; + case CRC_WILDCATUSERNO : CfgWildcatuserno (); break; + default : found = false; + } + goto End; + +SwitchX: + switch(crc) { + case CRC_XLATCHARSET : CfgXlatcharset (); break; + case CRC_XLATESCSET : CfgXlatescset (); break; + case CRC_XLATEXPORT : CfgXlatexport (); break; + case CRC_XLATIMPORT : CfgXlatimport (); break; + case CRC_XLATLOCALSET : CfgXlatlocalset (); break; + case CRC_XLATPATH : CfgXlatpath (); break; + default : found = false; + } + goto End; + +SwitchY: + switch(crc) { + default : found = false; + } + goto End; + +SwitchZ: + switch(crc) { + case CRC_ZONEGATING : CfgZonegating (); break; + default : found = false; + } + goto End; + +End: + if(found) + return true; + +// if(cmdlineoldkeyw == false) + return false; +} + + +// ------------------------------------------------------------------ + +static int do_if(char* val) { + + if(strieql(val, "OS/2") or strieql(val, "OS2")) { + #ifdef __OS2__ + return true; + #else + return false; + #endif + } + else if(strieql(val, "NT") or strieql(val, "W32") or strieql(val, "WIN32")) { + #ifdef __WIN32__ + return true; + #else + return false; + #endif + } + else if(strieql(val, "386") or strieql(val, "DOS")) { + #ifdef __MSDOS__ + return true; + #else + return false; + #endif + } + else if(strieql(val, "LINUX") or strieql(val, "UNIX")) { + #ifdef __UNIX__ + return true; + #else + return false; + #endif + } + else if(strieql(val, "FIREBIRD")) + return true; + else if(strieql(val, "ASA") or strieql(val, "PLUS")) + return true; + else if(strieql(val, "YES") or strieql(val, "TRUE") or strieql(val, "ON")) + return true; + return !!atoi(val); +} + + +// ------------------------------------------------------------------ +// Compile a GoldED text config file + +int ReadCfg(const char* cfgfile, int ignoreunknown) { + + const word CRC_APP = 0x08B5; + + FILE* fp; + Path cfg; + char buf[1024]; + static int inuse = 0; + static int in_if = false; + static int in_else = false; + static int if_status = false; + char* val; + char* key; + char* cfgname; + word crc; + int cfgignore=NO, line=0; + + // Open the file + strcpy(cfg, cfgfile); + MakePathname(cfg, CFG->goldpath, cfg); + + fp = fsopen(cfg, "rt", CFG->sharemode); + if(fp) { + + cfgname = strrchr(cfg, '\\'); + cfgname = cfgname ? cfgname+1 : cfg; + inuse++; + + if(not quiet) + cout << "* Reading " << cfg << endl; + + // Assign file buffer + setvbuf(fp, NULL, _IOFBF, 8192); + + // Read each line + while(fgets((val=buf), sizeof(buf), fp)) { + + line++; + + // Replace TABs with SPACEs + strchg(val, '\t', ' '); + + val = strskip_wht(val); + + if(isalpha(*val)) { + + // Extract key and val + crc = getkeyvalcrc(&key, &val); + + int _gotcond = true; + switch(crc) { + case CRC_IF: + if(in_if) { + cout << "* " << cfgname << ": Misplaced IF at line " << line << ". IF's cannot be nested." << endl; + cfgerrors++; + } + in_if = true; + if_status = do_if(val); + cfgignore = not if_status; + break; + case CRC_ELIF: + case CRC_ELSEIF: + if(not in_if or in_else) { + cout << "* " << cfgname << ": Misplaced ELIF/ELSEIF at line " << line << "." << endl; + cfgerrors++; + } + if(if_status) + cfgignore = true; + else { + if_status = do_if(val); + cfgignore = not if_status; + } + break; + case CRC_ELSE: + if(not in_if or in_else) { + cout << "* " << cfgname << ": Misplaced ELSE at line " << line << "." << endl; + cfgerrors++; + } + in_else = true; + if_status ^= true; + cfgignore = not if_status; + break; + case CRC_ENDIF: + if(not in_if) { + cout << "* " << cfgname << ": Misplaced ENDIF at line " << line << "." << endl; + cfgerrors++; + } + cfgignore = false; + in_if = in_else = false; + break; + case CRC_IGNORE: + cfgignore ^= true; + break; + default: + _gotcond = false; + } + + // Tell the world what we found + if(veryverbose) + cout << " " << (cfgignore ? '-' : '+') << setw(4) << setfill('0') << line << setfill(' ') << ": " << key << " " << val << endl; + + // Call switch function to act on the key + if(not cfgignore) { + if(not _gotcond) { + switch(crc) { + case CRC_INCLUDE: + if(not quiet) + cout << "* Including " << val << endl; + ReadCfg(val); // NOTE! This is a recursive call! + if(not quiet) + cout << "* Resuming " << cfg << endl; + break; + case CRC_AREAFILE: + if(not quiet) + cout << "* Handling " << key << " " << val << endl; + AL.GetAreafile(val); + if(not quiet) + cout << "* Resuming " << cfg << endl; + break; + case CRC_APP: + // Ignore 3rd party application lines + break; + case CRC_REM: + // Ignore remark lines + break; + default: + if(not SwitchCfg(crc, *key, val)) { + if(not ignoreunknown) { + cout << "* " << cfgname << ": Unknown keyword \"" << key << "\" at line " << line << "." << endl; + SayBibi(); + cfgerrors++; + } + } + } + } + } + } + } + + // Close and return all OK + fclose(fp); + inuse--; + + // When the final cfg is compiled + if(inuse == 0) { + + // Mark all areas listed in the NEWSRC file as newsgroups + gfile gfp; + gfp.fopen(CFG->soupnewsrcfile, "rt"); + if(gfp.isopen()) { + char buf2[512]; + while(gfp.fgets(buf2, sizeof(buf2))) { + char* ptr = strpbrk(buf2, ":! "); + if(ptr) { + *ptr = NUL; + Area* ap = AL.AreaEchoToPtr(buf2); + if(ap) + ap->set_type(ap->isnet() ? AT_SOUP|AT_EMAIL|AT_NET : AT_SOUP|AT_NEWSGROUP|AT_ECHO); + } + } + gfp.fclose(); + } + + if(*CFG->soupemail) { + Area* ap = AL.AreaEchoToPtr(buf); + if(ap) + ap->set_type(AT_SOUP|AT_EMAIL|AT_NET); + } + + vector::iterator z; + for(z = CFG->mailinglist.begin(); z != CFG->mailinglist.end(); z++) { + Area* ap = AL.AreaEchoToPtr(z->echoid); + if(ap) + ap->set_type(AT_SOUP|AT_EMAIL|AT_NET); + } + + // Mark all QWK areas + if(QWK->FirstBBS()) { + do { + if(QWK->FirstConf()) { + do { + Area* ap = AL.AreaEchoToPtr(buf); + if(ap) + ap->set_type(ap->type() | AT_QWK); + } while(QWK->NextConf()); + } + } while(QWK->NextBBS()); + } + } + + return 1; + } + else { + + LOG.ErrOpen(); + LOG.printf("! Unable to open configuration file."); + LOG.printf(": %s", cfg); + LOG.ErrOSInfo(); + OpenErrorExit(); + } + + // Error opening file + return 0; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gccfgg1.cpp b/golded3/gccfgg1.cpp new file mode 100644 index 0000000..1ebb7c0 --- /dev/null +++ b/golded3/gccfgg1.cpp @@ -0,0 +1,406 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Configuration functions, part 1. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern char* val; + + +// ------------------------------------------------------------------ + +void CfgAddress() { CfgAddress(val); } +void CfgAddress(char* v) { + + if(not strblank(v)) { + + if(veryverbose) + cout << " CfgAddress(" << v << ")" << endl; + + gaka aka; + aka.domain[0] = NUL; + aka.pointnet = 0; + + char* ptr = strchr(v, ','); + if(ptr) { + aka.pointnet = atow(ptr+1); + *ptr = NUL; + } + if(not CFG->aka.empty()) { + aka.addr = CFG->aka[0].addr; + strcpy(aka.domain, CFG->aka[0].domain); + } + aka.addr.set(v, aka.domain); + + if(cfgingroup) + CFG->grp.AddItm(GRP_AKA, &aka, sizeof(gaka)); + + int gotaka = GetAkaNo(aka.addr); + if(gotaka == -1) + CFG->aka.push_back(aka); + } +} + +// ------------------------------------------------------------------ + +void CfgAddressbookadd() { + + CFG->addressbookadd = GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgAddresslookupfirst(){ + + if(strieql(val, "MSGID")) + CFG->addresslookupfirst = YES; + else + CFG->addresslookupfirst = NO; +} + +// ------------------------------------------------------------------ + +void CfgAddressmacro(char* v) { val = v; CfgAddressmacro(); } +void CfgAddressmacro() { + + AddrMacro tmp; + tmp.attr.reset(); + int subjwasquoted = NO; + char* ptr = val; + char* ptr2 = strchr(ptr, ','); // macro^,name,address,subj,attribs + if(ptr2) { + // Got macroname + *ptr2++ = NUL; + strxcpy(tmp.macro, ptr, 20); + ptr = strskip_wht(ptr2); + ptr2 = strchr(ptr, ','); // macro,name^,address,subj,attribs + if(ptr2) { + // Got real name + *ptr2++ = NUL; + strxcpy(tmp.name, ptr, sizeof(IAdr)); + ptr = strskip_wht(ptr2); + ptr2 = strchr(ptr, ','); // macro,name,address^,subj,attribs + if(ptr2) + *ptr2++ = NUL; + // Got address + if(not CFG->aka.empty()) + tmp.addr = CFG->aka[0].addr; + tmp.addr.set(ptr); + if(ptr2) { + // Got subject + ptr = strskip_wht(ptr2); + if((*ptr == '\"') or (*ptr == '\'')) { + ptr2 = strchr(ptr+1, *ptr); + if(ptr2) { + subjwasquoted = YES; + *ptr2++ = NUL; + ptr++; + } + } + strxcpy(tmp.subj, ptr, sizeof(Subj)); + + // Got quoted subj, so look for attribs + if(subjwasquoted) { + ptr2 = strchr(ptr2, ','); // macro,name,address,subj^,attribs + if(ptr2) + GetAttribstr(&tmp.attr, ptr2+1); + } + } + else + tmp.subj[0] = NUL; + CFG->addressmacro.push_back(tmp); + } + } +} + +// ------------------------------------------------------------------ + +void CfgAdeptxbbspath() { + + PathCopy(CFG->adeptxbbspath, val); +} + +// ------------------------------------------------------------------ + +void CfgAdeptxbbsuserno() { + + CFG->adeptxbbsuserno = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgAkamatch() { + + char* key; + getkeyval(&key, &val); + + AkaMatchG akamatchg; + akamatchg.mask.set_all(GFTN_ALL); + akamatchg.mask.set(key); + akamatchg.aka.reset(val); + CFG->akamatch.push_back(akamatchg); +} + +// ------------------------------------------------------------------ + +void CfgAkamatching() { + + if(cfgingroup) { + bool flag = GetYesno(val); + CFG->grp.AddItm(GRP_AKAMATCHING, flag); + } +} + +// ------------------------------------------------------------------ + +void CfgArea() { + + AL.GetArea(val); +} + +// ------------------------------------------------------------------ + +void CfgAreaautoid() { + + if(striinc("VERBOSE", val)) + CFG->areaautoid = AUTOID_VERBOSE; + else if(striinc("SHORT", val)) + CFG->areaautoid = AUTOID_SHORT; + else if(striinc("LONG", val)) + CFG->areaautoid = AUTOID_LONG; +} + +// ------------------------------------------------------------------ + +void CfgAreacfmreplyto() { + + strxcpy(CFG->areacfmreplyto, val, sizeof(Echo)); +} + +// ------------------------------------------------------------------ + +void CfgAreacopydirect() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_AREACOPYDIRECT, flag); + else + CFG->areacopydirect = flag; +} + +// ------------------------------------------------------------------ + +void CfgAreacopyto() { + + Echo buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_AREACOPYTO, buf, strlen(buf)+1); + else + strcpy(CFG->areacopyto, buf); +} + +// ------------------------------------------------------------------ + +void CfgAreacopyaddid() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_AREACOPYADDID, flag); + else + CFG->areacopyaddid = flag; +} + +// ------------------------------------------------------------------ + +void CfgAreadef() { + + AL.GetAreaDef(val); +} + +// ------------------------------------------------------------------ + +void CfgAreadesc() { + + AL.GetAreaDesc(val); +} + +// ------------------------------------------------------------------ + +void CfgAreaexcl() { + + tokenize(CFG->areaexcl, val); +} + + +// ------------------------------------------------------------------ + +void CfgAreaforwarddirect() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_AREAFORWARDDIRECT, flag); + else + CFG->areaforwarddirect = flag; +} + +// ------------------------------------------------------------------ + +void CfgAreafreqdirect() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_AREAFREQDIRECT, flag); + else + CFG->areafreqdirect = flag; +} + +// ------------------------------------------------------------------ + +void CfgAreafreqto() { + + Echo buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_AREAFREQTO, buf, strlen(buf)+1); + else + strcpy(CFG->areafreqto, buf); +} + +// ------------------------------------------------------------------ + +void CfgAreaincl() { + + tokenize(CFG->areaincl, val); +} + +// ------------------------------------------------------------------ + +void CfgAreaisemail() { + + tokenize(CFG->areaisemail, val); +} + +// ------------------------------------------------------------------ + +void CfgAreaisnews() { + + tokenize(CFG->areaisnews, val); +} + +// ------------------------------------------------------------------ + +void CfgArealistechomax() { + + CFG->arealistechomax = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgArealistformat() { + + strcpy(CFG->arealistformat, StripQuotes(val)); +} + + +// ------------------------------------------------------------------ + +void CfgArealistscan() { + + char* _key; + getkeyval(&_key, &val); + AL.ListScan.Add(pair(StripQuotes(_key), val)); +} + +// ------------------------------------------------------------------ + +void CfgArealistsort() { + + strupr(strxcpy(CFG->arealistsort, val, sizeof(CFG->arealistsort))); +} + +// ------------------------------------------------------------------ + +void CfgArealisttype() { + + if(strieql(val, "New")) + CFG->arealisttype = AL_TOTNEW; + else if(strieql(val, "Last")) + CFG->arealisttype = AL_TOTLST; +} + +// ------------------------------------------------------------------ + +void CfgAreapath() { + + PathCopy(CFG->areapath, val); +} + +// ------------------------------------------------------------------ + +void CfgAreapmscan() { + + tokenize(CFG->areapmscan, val); +} + +// ------------------------------------------------------------------ + +void CfgAreapmscanexcl() { + + tokenize(CFG->areapmscanexcl, val); +} + +// ------------------------------------------------------------------ + +void CfgAreapmscanincl() { + + tokenize(CFG->areapmscanincl, val); +} + +// ------------------------------------------------------------------ + +void CfgAreareadonly() { + + if(strieql(val, "Soft")) + CFG->areareadonly = READONLY_SOFT; + else if(strieql(val, "Hard")) + CFG->areareadonly = READONLY_HARD; +} + +// ------------------------------------------------------------------ + +void CfgArearename() { + + char* key; + getkeyval(&key, &val); + CFG->arearename.push_back(EchoRen(key, strtrim(val))); +} + +// ------------------------------------------------------------------ + diff --git a/golded3/gccfgg2.cpp b/golded3/gccfgg2.cpp new file mode 100644 index 0000000..4940ed3 --- /dev/null +++ b/golded3/gccfgg2.cpp @@ -0,0 +1,489 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Configuration functions, part 2. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern char* val; + + +// ------------------------------------------------------------------ + +void CfgAreareplydirect() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_AREAREPLYDIRECT, flag); + else + CFG->areareplydirect = flag; +} + +// ------------------------------------------------------------------ + +void CfgAreareplyto() { + + Echo buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_AREAREPLYTO, buf, strlen(buf)+1); + else + strcpy(CFG->areareplyto, buf); +} + +// ------------------------------------------------------------------ + +void CfgAreascan() { + + tokenize(CFG->areascan, val); +} + +// ------------------------------------------------------------------ + +void CfgAreascanexcl() { + + tokenize(CFG->areascanexcl, val); +} + +// ------------------------------------------------------------------ + +void CfgAreascanincl() { + + tokenize(CFG->areascanincl, val); +} + +// ------------------------------------------------------------------ + +void CfgAreascansort() { + + strupr(strxcpy(CFG->areascansort, val, sizeof(CFG->areascansort))); +} + +// ------------------------------------------------------------------ + +void CfgAreasep() { + + AL.GetAreaSep(val); +} + +// ------------------------------------------------------------------ + +void CfgAreastart() { + + strupr(strxcpy(CFG->areastart, val, sizeof(Echo))); +} + +// ------------------------------------------------------------------ + +void CfgAreatypeorder() { + + const word CRC_NET = 0xEC5E; + const word CRC_ECHO = 0xC2D1; + const word CRC_LOCAL = 0x4CD5; + const word CRC_EMAIL = 0x9C64; + const word CRC_NEWS = 0x61F1; + + GTok t; + int order = 1; + if(t.First(val)) { + do { + switch(strCrc16(t.Token())) { + case CRC_NET: CFG->areatypeorder[AT_NET] = order; break; + case CRC_EMAIL: CFG->areatypeorder[AT_NET|AT_EMAIL] = order; break; + case CRC_ECHO: CFG->areatypeorder[AT_ECHO] = order; break; + case CRC_NEWS: CFG->areatypeorder[AT_ECHO|AT_NEWSGROUP] = order; break; + case CRC_LOCAL: CFG->areatypeorder[AT_LOCAL] = order; break; + } + order++; + } while(t.Next()); + } +} + +// ------------------------------------------------------------------ + +void CfgAreayouwroteto() { + + Echo buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_AREAYOUWROTETO, buf, strlen(buf)+1); + else + strcpy(CFG->areayouwroteto, buf); +} + +// ------------------------------------------------------------------ + +void CfgAttachpath() { + + PathCopy(CFG->attachpath, val); +} + +// ------------------------------------------------------------------ + +void CfgAttribsattach() { + + GetAttribstr(&CFG->attribsattach, val); +} + +// ------------------------------------------------------------------ + +void CfgAttribscc() { + + GetAttribstr(&CFG->attribscc, val); +} + +// ------------------------------------------------------------------ + +void CfgAttribscfm() { + + GetAttribstr(&CFG->attribscfm, val); +} + +// ------------------------------------------------------------------ + +void CfgAttribsecho() { + + GetAttribstr(&CFG->attribsecho, val); +} + +// ------------------------------------------------------------------ + +void CfgAttribsemail() { + + GetAttribstr(&CFG->attribsemail, val); +} + +// ------------------------------------------------------------------ + +void CfgAttribsfrq() { + + GetAttribstr(&CFG->attribsfrq, val); +} + +// ------------------------------------------------------------------ + +void CfgAttribslocal() { + + GetAttribstr(&CFG->attribslocal, val); +} + +// ------------------------------------------------------------------ + +void CfgAttribsnet() { + + GetAttribstr(&CFG->attribsnet, val); +} + +// ------------------------------------------------------------------ + +void CfgAttribsnews() { + + GetAttribstr(&CFG->attribsnews, val); +} + +// ------------------------------------------------------------------ + +void CfgAttributes() { + + char buf[256]; + strxcpy(buf, val, 256); + if(cfgingroup) + CFG->grp.AddItm(GRP_ATTRIBUTES, buf, strlen(buf)+1); +} + +// ------------------------------------------------------------------ + +void CfgBeepfactor() { + + CFG->beepfactor = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgBeepyourmail() { + + CFG->beepyourmail = GetYesno(val); +} + +// ------------------------------------------------------------------ + +#define CRC_REMOVE 0xFAF0 +#define CRC_HIDDEN 0xE465 +#define CRC_VISIBLE 0xD155 +#define CRC_NAMES 0xE46B +#define CRC_KEEP 0x8C07 + +void CfgCarboncopylist() { + + switch(strCrc16(val)) { + case CRC_REMOVE: CFG->carboncopylist = CC_REMOVE; break; + case CRC_HIDDEN: CFG->carboncopylist = CC_HIDDEN; break; + case CRC_VISIBLE: CFG->carboncopylist = CC_VISIBLE; break; + case CRC_NAMES: CFG->carboncopylist = CC_NAMES; break; + case CRC_KEEP: CFG->carboncopylist = CC_KEEP; break; + default: + CFG->carboncopylist = GetYesno(val) ? CC_KEEP : CC_REMOVE; + } +} + +// ------------------------------------------------------------------ + +void CfgColor() { + + GetColors(val); +} + +// ------------------------------------------------------------------ + +void CfgColorset() { + + if(strieql(val, "Normal")) { + memcpy(CFG->color, gold_color1, sizeof(Win)*16); + } + else if(strieql(val, "Intense")) { + CFG->intensecolors = true; + memcpy(CFG->color, gold_color2, sizeof(Win)*16); + } + else if(strieql(val, "Mono")) { + memcpy(CFG->color, gold_mono1, sizeof(Win)*16); + } +} + +// ------------------------------------------------------------------ + +void CfgConfirmresponse() { + + CFG->confirmresponse = GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgConfirmfile() { + + strcpy(CFG->confirmfile, val); +} + +// ------------------------------------------------------------------ + +void CfgCookiepath() { + + PathCopy(CFG->cookiepath, val); +} + +// ------------------------------------------------------------------ + +void CfgCrosspost() { + + CFG->crosspost = GetYesno(val); +} + +// ------------------------------------------------------------------ + +#define CRC_NONE 0xD9AD +#define CRC_RAW 0x3BE0 +#define CRC_VERBOSE 0xBB00 + +void CfgCrosspostlist() { + + switch(strCrc16(val)) { + case CRC_NONE: CFG->crosspostlist = CC_REMOVE; break; + case CRC_VERBOSE: CFG->crosspostlist = CC_NAMES; break; + case CRC_RAW: CFG->crosspostlist = CC_KEEP; break; + default: + CFG->crosspostlist = GetYesno(val) ? CC_VISIBLE : CC_REMOVE; + } +} + +// ------------------------------------------------------------------ + +void CfgCtrlinfo() { + + if(cfgingroup) { + int ctrlinfo = CI_NONE; + if(striinc("NO", val)) + ctrlinfo = CI_NONE; + else if(striinc("YES", val)) + ctrlinfo = CI_TEAR|CI_ORIG; + else { + if(striinc("TEARLINE", val)) + ctrlinfo |= CI_TEAR; + if(striinc("ORIGIN", val)) + ctrlinfo |= CI_ORIG; + } + CFG->grp.AddItm(GRP_CTRLINFO, ctrlinfo); + } +} + +// ------------------------------------------------------------------ + +void CfgCtrlinfoecho() { + + CFG->ctrlinfoecho = CI_NONE; + if(striinc("NO", val)) + CFG->ctrlinfoecho = CI_NONE; + else if(striinc("YES", val)) + CFG->ctrlinfoecho = CI_TEAR|CI_ORIG; + else { + if(striinc("TEARLINE", val)) + CFG->ctrlinfoecho |= CI_TEAR; + if(striinc("ORIGIN", val)) + CFG->ctrlinfoecho |= CI_ORIG; + } +} + +// ------------------------------------------------------------------ + +void CfgCtrlinfoemail() { + + CFG->ctrlinfoemail = CI_NONE; + if(striinc("NO", val)) + CFG->ctrlinfoemail = CI_NONE; + else if(striinc("YES", val)) + CFG->ctrlinfoemail = CI_TEAR|CI_ORIG; + else { + if(striinc("TEARLINE", val)) + CFG->ctrlinfoemail |= CI_TEAR; + if(striinc("ORIGIN", val)) + CFG->ctrlinfoemail |= CI_ORIG; + } +} + +// ------------------------------------------------------------------ + +void CfgCtrlinfolocal() { + + CFG->ctrlinfolocal = CI_NONE; + if(striinc("NO", val)) + CFG->ctrlinfolocal = CI_NONE; + else if(striinc("YES", val)) + CFG->ctrlinfolocal = CI_TEAR|CI_ORIG; + else { + if(striinc("TEARLINE", val)) + CFG->ctrlinfolocal |= CI_TEAR; + if(striinc("ORIGIN", val)) + CFG->ctrlinfolocal |= CI_ORIG; + } +} + +// ------------------------------------------------------------------ + +void CfgCtrlinfonet() { + + CFG->ctrlinfonet = CI_NONE; + if(striinc("NO", val)) + CFG->ctrlinfonet &= ~CI_ORIG; + else if(striinc("YES", val)) + CFG->ctrlinfonet = CI_TEAR|CI_ORIG; + else { + if(striinc("TEARLINE", val)) + CFG->ctrlinfonet |= CI_TEAR; + if(striinc("ORIGIN", val)) + CFG->ctrlinfonet |= CI_ORIG; + } +} + +// ------------------------------------------------------------------ + +void CfgCtrlinfonews() { + + CFG->ctrlinfonews = CI_NONE; + if(striinc("NO", val)) + CFG->ctrlinfonews = CI_NONE; + else if(striinc("YES", val)) + CFG->ctrlinfonews = CI_TEAR|CI_ORIG; + else { + if(striinc("TEARLINE", val)) + CFG->ctrlinfonews |= CI_TEAR; + if(striinc("ORIGIN", val)) + CFG->ctrlinfonews |= CI_ORIG; + } +} + +// ------------------------------------------------------------------ + +void CfgDispattachsize() { + + if(strieql("NO", val)) + CFG->dispattachsize = NO; + else if(strieql("BYTES", val)) + CFG->dispattachsize = ATTACH_BYTES; + else if(strieql("KBYTES", val)) + CFG->dispattachsize = ATTACH_KBYTES; +} + +// ------------------------------------------------------------------ + +void CfgDisphdrdateset() { + + char* key; + getkeyval(&key, &val); + CFG->disphdrdateset.pos = atoi(key); + getkeyval(&key, &val); + CFG->disphdrdateset.len = atoi(key); +} + +// ------------------------------------------------------------------ + +void CfgDisphdrnameset() { + + char* key; + getkeyval(&key, &val); + CFG->disphdrnameset.pos = atoi(key); + getkeyval(&key, &val); + CFG->disphdrnameset.len = atoi(key); +} + +// ------------------------------------------------------------------ + +void CfgDisphdrnodeset() { + + char* key; + getkeyval(&key, &val); + CFG->disphdrnodeset.pos = atoi(key); + getkeyval(&key, &val); + CFG->disphdrnodeset.len = atoi(key); +} + +// ------------------------------------------------------------------ + +void CfgDisplistcursor() { + + if(strieql(val, "TOP")) + CFG->displistcursor = LIST_TOP; + else if(strieql(val, "NEARTOP")) + CFG->displistcursor = LIST_NEARTOP; + else if(strieql(val, "MIDDLE")) + CFG->displistcursor = LIST_MIDDLE; + else if(strieql(val, "NEARBOTTOM")) + CFG->displistcursor = LIST_NEARBOTTOM; + else if(strieql(val, "BOTTOM")) + CFG->displistcursor = LIST_BOTTOM; +} + +// ------------------------------------------------------------------ + diff --git a/golded3/gccfgg3.cpp b/golded3/gccfgg3.cpp new file mode 100644 index 0000000..98e9151 --- /dev/null +++ b/golded3/gccfgg3.cpp @@ -0,0 +1,372 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Configuration functions, part 3. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern char* val; + +// ------------------------------------------------------------------ + +void CfgDispmargin() { + + CFG->cfgdispmargin = atoi(val); + CFG->dispmargin = CFG->cfgdispmargin; +} + +// ------------------------------------------------------------------ + +void CfgDispmsgsize() { + + if(strieql("NO", val)) + CFG->dispmsgsize = NO; + else if(strieql("BYTES", val)) + CFG->dispmsgsize = DISPMSGSIZE_BYTES; + else if(strieql("KBYTES", val)) + CFG->dispmsgsize = DISPMSGSIZE_KBYTES; + else if(strieql("LINES", val)) + CFG->dispmsgsize = DISPMSGSIZE_KBYTES+1; +} + +// ------------------------------------------------------------------ + +void CfgDispareano() { + + CFG->dispareano = GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgDisptabsize() { + + CFG->disptabsize = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgEditautoattach() { + + EDIT->AutoAttach(GetYesno(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditautosave() { + + EDIT->AutoSave(atoi(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditchangedate() { + + EDIT->ChangeDate(GetYesno(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditcharpara() { + + char ch = *StripQuotes(val); + if(ch) + EDIT->CharPara(ch); +} + +// ------------------------------------------------------------------ + +void CfgEditcharspace() { + + char ch = *StripQuotes(val); + if(ch) + EDIT->CharSpace(ch); +} + +// ------------------------------------------------------------------ + +void CfgEditcomment() { + + char* key; + getkeyval(&key, &val); + StripQuotes(key); + StripQuotes(val); + EDIT->Comment.Add(key, val); +} + +// ------------------------------------------------------------------ + +void CfgEditcompletion() { + + char* key; + getkeyval(&key, &val); + StripQuotes(key); + StripQuotes(val); + EDIT->Completion.Add(key, val); +} + +// ------------------------------------------------------------------ + +void CfgEditcrlfterm() { + + EDIT->CrLfTerm(GetYesno(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditfieldclear() { + + EDIT->FieldClear(GetYesno(val)); +} + +// ------------------------------------------------------------------ + +void CfgEdithardline() { + + EDIT->HardLine(StripQuotes(val)); +} + +// ------------------------------------------------------------------ + +void CfgEdithardlines() { + + EDIT->HardLines(GetYesno(val)); +} + +// ------------------------------------------------------------------ + +void CfgEdithardterm() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_EDITHARDTERM, flag); + else + EDIT->HardTerm(flag); +} + +// ------------------------------------------------------------------ + +void CfgEdithdrnameset() { + + char* key; + getkeyval(&key, &val); + EDIT->HdrNamePos(atoi(key)); + EDIT->HdrNameLen(atoi(val)); +} + +// ------------------------------------------------------------------ + +void CfgEdithdrnodeset() { + + char* key; + getkeyval(&key, &val); + EDIT->HdrNodePos(atoi(key)); + EDIT->HdrNodeLen(atoi(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditheaderattrs() { + + EDIT->HeaderAttrs(GetYesno(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditheaderfirst() { + + int v = EDITHEADERFIRST_NO; + GTok t; + if(t.First(val)) { + do { + if(strieql("NEW", t.Token())) + v |= EDITHEADERFIRST_NEW; + else if(strieql("CHANGES", t.Token())) + v |= EDITHEADERFIRST_CHANGES; + else if(strieql("REPLIES", t.Token())) + v |= EDITHEADERFIRST_REPLIES; + else if(strieql("FORWARDS", t.Token())) + v |= EDITHEADERFIRST_FORWARDS; + else + v = GetYesno(t.Token()) ? EDITHEADERFIRST_YES : EDITHEADERFIRST_NO; + } while(t.Next()); + } + EDIT->HeaderFirst(v); +} + +// ------------------------------------------------------------------ + +void CfgEditinternal() { + + EDIT->Internal(GetYesno(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditmenu() { + + EDIT->Menu(GetYesno(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditmixcase() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_EDITMIXCASE, flag); + else + EDIT->MixCase(flag); +} + +// ------------------------------------------------------------------ + +void CfgEditmsgsize() { + + EDIT->MsgSize(atol(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditor() { + + EDIT->External(val); +} + +// ------------------------------------------------------------------ + +void CfgEditorfile() { + + EDIT->File(val); +} + +// ------------------------------------------------------------------ + +void CfgEditquotemargin() { + + EDIT->QuoteMargin(atoi(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditreplyre() { + + int replyre; + if(strieql(val, "NUMERIC")) + replyre = REPLYRE_NUMERIC; + else + replyre = GetYesno(val) ? REPLYRE_YES : REPLYRE_NO; + + if(cfgingroup) + CFG->grp.AddItm(GRP_EDITREPLYRE, replyre); + else + EDIT->ReplyRe(replyre); +} + +// ------------------------------------------------------------------ + +void CfgEditsavemenu() { + + EDIT->SaveMenu(GetYesno(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditsaveutil() { + + char* _key; + getkeyval(&_key, &val); + int n = atoi(_key); + EDIT->SaveUtil.Add(n, StripQuotes(val)); +} + +// ------------------------------------------------------------------ + +void CfgEditsoftcrxlat() { + + EDIT->SoftCrXlat(*val); +} + +// ------------------------------------------------------------------ + +void CfgEditspellcheck() { + + EDIT->SpellChecker(val); +} + +// ------------------------------------------------------------------ + +void CfgEditundelete() { + + EDIT->UnDelete(atoi(val)); +} + +// ------------------------------------------------------------------ + +void CfgEncodeemailheaders() { + + CFG->encodeemailheaders = GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgEndgroup() { + + cfgingroup = false; +} + +// ------------------------------------------------------------------ + +void CfgEvent(char* v) { val = v; CfgEvent(); } +void CfgEvent() { + + char* key; + word x; + vector::iterator n; + GEvent tmp; + + x = getkeyvalcrc(&key, &val); + + for(n = CFG->event.begin(); n != CFG->event.end(); n++) + if(x == n->type) + break; + + tmp.type = x; + getkeyval(&key, &val); + if(strieql(key, "PLAY")) { + tmp.command = EVTC_PLAY; + FileToGPlay(&tmp.play, val); + } + + if(n == CFG->event.end()) + CFG->event.push_back(tmp); + else + *n = tmp; +} + +// ------------------------------------------------------------------ + diff --git a/golded3/gccfgg4.cpp b/golded3/gccfgg4.cpp new file mode 100644 index 0000000..4454192 --- /dev/null +++ b/golded3/gccfgg4.cpp @@ -0,0 +1,348 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Configuration functions, part 4. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern char* val; + + +// ------------------------------------------------------------------ + +void CfgExcludenodes() { + + // Only used by GoldNODE +} + +// ------------------------------------------------------------------ + +void CfgExternoptions() { + + const word CRC_CLS = 0x34F4; + const word CRC_CURSOR = 0x0D67; + const word CRC_RELOAD = 0xDEC0; + const word CRC_PAUSE = 0x3926; + const word CRC_PAUSEONERROR = 0xD99A; + const word CRC_WIPE = 0x1E80; + const word CRC_KEEPCTRL = 0x0738; + const word CRC_NOCLS = 0x2FAA; + const word CRC_NOCURSOR = 0x9345; + const word CRC_NORELOAD = 0x40E2; + const word CRC_NOPAUSE = 0x5D94; + const word CRC_NOPAUSEONERROR = 0xDBAA; + const word CRC_NOWIPE = 0xE3DA; + const word CRC_NOKEEPCTRL = 0x38FC; + + // Handle options + while(*val) { + + if(*val == '-') + val++; + + char* _key; + word _crc = getkeyvalcrc(&_key, &val); + + switch(_crc) { + + case CRC_CLS: + CFG->externoptions |= EXTUTIL_CLS; + break; + case CRC_CURSOR: + CFG->externoptions |= EXTUTIL_CURSOR; + break; + case CRC_RELOAD: + CFG->externoptions |= EXTUTIL_RELOAD; + break; + case CRC_PAUSE: + CFG->externoptions |= EXTUTIL_PAUSE; + break; + case CRC_PAUSEONERROR: + CFG->externoptions |= EXTUTIL_PAUSEONERROR; + break; + case CRC_WIPE: + CFG->externoptions |= EXTUTIL_WIPE; + break; + case CRC_KEEPCTRL: + CFG->externoptions |= EXTUTIL_KEEPCTRL; + break; + case CRC_NOCLS: + CFG->externoptions &= ~EXTUTIL_CLS; + break; + case CRC_NOCURSOR: + CFG->externoptions &= ~EXTUTIL_CURSOR; + break; + case CRC_NORELOAD: + CFG->externoptions &= ~EXTUTIL_RELOAD; + break; + case CRC_NOPAUSE: + CFG->externoptions &= ~EXTUTIL_PAUSE; + break; + case CRC_NOPAUSEONERROR: + CFG->externoptions &= ~EXTUTIL_PAUSEONERROR; + break; + case CRC_NOWIPE: + CFG->externoptions &= ~EXTUTIL_WIPE; + break; + case CRC_NOKEEPCTRL: + CFG->externoptions &= ~EXTUTIL_KEEPCTRL; + break; + } + } +} + + +// ------------------------------------------------------------------ + +void CfgExternutil() { + + ExtUtil extutil; + + // Get util number + char* _key; + char* _val = val; + getkeyval(&_key, &_val); + extutil.utilno = atoi(_key); + + // Get options + int _optbak = CFG->externoptions; + while(strchr("-", *_val)) { + getkeyval(&_key, &_val); + val = _key; + CfgExternoptions(); + } + extutil.options = CFG->externoptions; + CFG->externoptions = _optbak; + + // Get commandline + strxcpy(extutil.cmdline, _val, sizeof(extutil.cmdline)); + + // Count it + CFG->externutil.push_back(extutil); +} + +// ------------------------------------------------------------------ + +void CfgEzycommsgbase() { + + PathCopy(CFG->ezycom.msgbasepath, val); +} + +// ------------------------------------------------------------------ + +void CfgEzycomuserbase() { + + PathCopy(CFG->ezycom.userbasepath, val); +} + +// ------------------------------------------------------------------ + +void CfgEzycomuserno() { + + CFG->ezycomuserno = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgFidolastread() { + + strcpy(CFG->fidolastread, val); +} + +// ------------------------------------------------------------------ + +void CfgFidomsgtype() { + + if(striinc("FTS", val)) + CFG->fidomsgtype = MT_FTS1; + else + CFG->fidomsgtype = MT_OPUS; +} + +// ------------------------------------------------------------------ + +void CfgFidouserlist() { + + strcpy(CFG->fidouserlist, val); +} + +// ------------------------------------------------------------------ + +void CfgFidouserno() { + + CFG->fidouserno = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgFilealias() { + + char* ptr = strskip_txt(val); + if(*ptr) { + *ptr++ = NUL; + ptr = strskip_wht(ptr); + FileAlias tmp; + strxcpy(tmp.alias, val, sizeof(tmp.alias)); + strxcpy(tmp.file, ptr, sizeof(Path)); + CFG->filealias.push_back(tmp); + } +} + +// ------------------------------------------------------------------ + +void CfgForcetemplate() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_FORCETEMPLATE, flag); + else + CFG->forcetemplate = flag; +} + +// ------------------------------------------------------------------ + +void CfgFrqext(const char* v) { + + char* ptr = val = throw_strdup(v); + CfgFrqext(); + throw_free(ptr); +} + +void CfgFrqext() { + + tokenize(CFG->frqext, val); +} + +// ------------------------------------------------------------------ + +void CfgFrqnodemap() { + + char* key; + FrqNodeMap fnm; + getkeyval(&key, &val); + fnm.to.reset(key); + getkeyval(&key, &val); + fnm.from.reset(key); + + CFG->frqnodemap.push_back(fnm); +} + +// ------------------------------------------------------------------ + +void CfgFrqoptions() { + + if(striinc("SORT", val)) + CFG->frqoptions |= FREQ_SORT; + if(striinc("FROMTOP", val)) + CFG->frqoptions |= FREQ_FROMTOP; + if(striinc("NOFILES", val)) + CFG->frqoptions |= FREQ_NOFILES; + if(striinc("FAST", val)) + CFG->frqoptions |= FREQ_FAST; + if(striinc("NOWAZOOMSG", val)) + CFG->frqoptions |= FREQ_NOWAZOOMSG; + if(striinc("NOTFROMTOP", val)) + CFG->frqoptions &= ~FREQ_FROMTOP; +} + +// ------------------------------------------------------------------ + +void CfgGedhandshake() { + + CFG->gedhandshake = GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgGermankeyboard() { + + right_alt_same_as_left = not GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgGoldbasepath() { + + PathCopy(CFG->goldbasepath, val); +} + +// ------------------------------------------------------------------ + +void CfgGoldbasesyspath() { + + PathCopy(CFG->goldbasesyspath, val); +} + +// ------------------------------------------------------------------ + +void CfgGoldbaseuserno() { + + CFG->goldbaseuserno = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgGoldhelp() { + + strxcpy(CFG->helpcfg.fn, val, sizeof(Path)); + replaceextension(CFG->helpged, CFG->helpcfg.fn, __gver_cfgext__); +} + +// ------------------------------------------------------------------ + +void CfgGoldlang() { + + strxcpy(CFG->langcfg, val, sizeof(Path)); +} + +// ------------------------------------------------------------------ + +void CfgGoldpath() { + + PathCopy(CFG->goldpath, val); +} + +// ------------------------------------------------------------------ + +void CfgGoldxlat() { + + replaceextension(CFG->xlatged, val, __gver_cfgext__); +} + +// ------------------------------------------------------------------ + +void CfgGroup() { + + char* _key; + getkeyval(&_key, &val); + CFG->grp.AddGrp(_key); + cfgingroup = true; +} + +// ------------------------------------------------------------------ + diff --git a/golded3/gccfgg5.cpp b/golded3/gccfgg5.cpp new file mode 100644 index 0000000..135348c --- /dev/null +++ b/golded3/gccfgg5.cpp @@ -0,0 +1,442 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Configuration functions, part 5. +// ------------------------------------------------------------------ + +#include +#include +#include + + +// ------------------------------------------------------------------ + +extern char* val; + + +// ------------------------------------------------------------------ + +void CfgHappybirthday() { + + if(strieql(val, "FRIEND")) + CFG->happybirthday = true; +} + +// ------------------------------------------------------------------ + +void CfgHudsonpath() { + + PathCopy(CFG->hudsonpath, val); +} + +// ------------------------------------------------------------------ + +void CfgHudsonsizewarn() { + + CFG->hudsonsizewarn = atol(val); +} + +// ------------------------------------------------------------------ + +void CfgHudsonsyspath() { + + PathCopy(CFG->hudsonsyspath, val); +} + +// ------------------------------------------------------------------ + +void CfgHudsonuserno() { + + CFG->hudsonuserno = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgIgnorecharset() { + + CFG->ignorecharset = GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgImportbegin() { + + strxcpy(CFG->importbegin, StripQuotes(val), sizeof(CFG->importbegin)); +} + +// ------------------------------------------------------------------ + +void CfgImportend() { + + strxcpy(CFG->importend, StripQuotes(val), sizeof(CFG->importend)); +} + +// ------------------------------------------------------------------ + +void CfgInboundpath() { + + PathCopy(CFG->inboundpath, val); +} + +// ------------------------------------------------------------------ + +void CfgIncludenodes() { + + // Only used by GoldNODE +} + +// ------------------------------------------------------------------ + +void CfgInputfile() { + + Path buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_INPUTFILE, buf, strlen(buf)+1); + else + strcpy(CFG->inputfile, buf); +} + +// ------------------------------------------------------------------ + +void CfgIntensecolors() { + + CFG->intensecolors = GetYesno(val); + if(CFG->intensecolors) + memcpy(CFG->color, gold_color2, sizeof(CFG->color)); +} + +// ------------------------------------------------------------------ + +void CfgInternetaddress() { + + IAdr buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_INTERNETADDRESS, buf, strlen(buf)+1); + else + strcpy(CFG->internetaddress, buf); +} + +// ------------------------------------------------------------------ + +void CfgInternetdomain() { + + strxcpy(CFG->internetdomain, val, sizeof(CFG->internetdomain)); +} + +// ------------------------------------------------------------------ + +void CfgInternetgate() { + + Node tmp; + char* ptr = strchr(val, ','); + if(ptr) { + *ptr++ = NUL; + strxcpy(tmp.name, strtrim(val), sizeof(Name)); + } + else { + ptr = val; + tmp.name[0] = NUL; + } + if(not CFG->aka.empty()) + tmp.addr = CFG->aka[0].addr; + tmp.addr.set(strskip_wht(ptr)); + if(cfgingroup) + CFG->grp.AddItm(GRP_INTERNETGATE, &tmp, sizeof(Node)); + else + CFG->internetgate = tmp; +} + +// ------------------------------------------------------------------ + +void CfgInternetmsgid() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_INTERNETMSGID, flag); + else + CFG->internetmsgid = flag; +} + +// ------------------------------------------------------------------ + +void CfgInternetrfcbody() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_INTERNETRFCBODY, flag); + else + CFG->internetrfcbody = flag; +} + +// ------------------------------------------------------------------ + +void CfgInternetserver() { + + GTok t; + if(t.First(val)) { + int server = 0; + if(strieql(t.Token(), "NNTP")) + server = 1; + else if(strieql(t.Token(), "SMTP")) + server = 2; + else if(strieql(t.Token(), "POP3")) + server = 3; + int parameter = 1; + while(t.Next()) { + if(server == 1) + strxcpy(CFG->internetserver.nntp.server, t.Token(), sizeof(CFG->internetserver.nntp.server)); + else if(server == 2) + strxcpy(CFG->internetserver.smtp.server, t.Token(), sizeof(CFG->internetserver.smtp.server)); + else if(server == 3) { + if(parameter == 1) + strxcpy(CFG->internetserver.pop3.server, t.Token(), sizeof(CFG->internetserver.pop3.server)); + else if(parameter == 2) + strxcpy(CFG->internetserver.pop3.username, t.Token(), sizeof(CFG->internetserver.pop3.username)); + else if(parameter == 3) + strxcpy(CFG->internetserver.pop3.password, t.Token(), sizeof(CFG->internetserver.pop3.password)); + } + parameter++; + } + } +} + +// ------------------------------------------------------------------ + +void CfgInvalidate() { + + const word CRC_SEENBY = 0x01D0; + const word CRC_CC = 0x4343; + const word CRC_XC = 0x5843; + const word CRC_XP = 0x5850; + + char* key; + + switch(getkeyvalcrc(&key, &val)) { + case CRC_TEARLINE: + getkeyval(&key, &val); + CFG->invalidate.tearline.first = StripQuotes(key); + CFG->invalidate.tearline.second = StripQuotes(val); + break; + case CRC_ORIGIN: + getkeyval(&key, &val); + CFG->invalidate.origin.first = StripQuotes(key); + CFG->invalidate.origin.second = StripQuotes(val); + break; + case CRC_SEENBY: + getkeyval(&key, &val); + CFG->invalidate.seenby.first = StripQuotes(key); + CFG->invalidate.seenby.second = StripQuotes(val); + break; + case CRC_CC: + getkeyval(&key, &val); + CFG->invalidate.cc.first = StripQuotes(key); + CFG->invalidate.cc.second = StripQuotes(val); + break; + case CRC_XC: + getkeyval(&key, &val); + CFG->invalidate.xc.first = StripQuotes(key); + CFG->invalidate.xc.second = StripQuotes(val); + break; + case CRC_XP: + getkeyval(&key, &val); + CFG->invalidate.xp.first = StripQuotes(key); + CFG->invalidate.xp.second = StripQuotes(val); + break; + } +} + +// ------------------------------------------------------------------ + +void CfgJampath() { + + PathCopy(CFG->jampath, val); +} + +// ------------------------------------------------------------------ + +void CfgKeybmode() { + + if(strnieql(val, "Poll", 4)) + CFG->keybmode = KEYB_POLL; + else if(strnieql(val, "Block", 5)) + CFG->keybmode = KEYB_BLOCK; +} + +// ------------------------------------------------------------------ + +void CfgKeybstack() { + + strcat(CFG->keybstack, val); +} + +// ------------------------------------------------------------------ + +void CfgKludge() { + + StripQuotes(val); + if(*val == CTRL_A) + val++; + CFG->kludge.push_back(val); +} + +// ------------------------------------------------------------------ + +void CfgLoadlanguage() { + + Path buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_LOADLANGUAGE, buf, strlen(buf)+1); + else + strcpy(CFG->loadlanguage, buf); +} + +// ------------------------------------------------------------------ + +void CfgLogfile() { + + strcpy(CFG->logfile, val); +} + +// ------------------------------------------------------------------ + +void CfgLogformat() { + + if(strieql(val, "FD")) + CFG->logformat = GLOG_FD; + else if(strieql(val, "MAX")) + CFG->logformat = GLOG_MAX; + else if(strieql(val, "BINK")) + CFG->logformat = GLOG_BINK; + else if(strieql(val, "QBBS")) + CFG->logformat = GLOG_QBBS; + else if(strieql(val, "DB")) + CFG->logformat = GLOG_DB; +} + +// ------------------------------------------------------------------ + +void CfgMailinglist() { + + char* key; + MailList mlst; + mlst.sender_is_pattern = false; + getkeyval(&key, &val); + strxcpy(mlst.echoid, key, sizeof(Echo)); + getkeyval(&key, &val); + strxcpy(mlst.sender, key, sizeof(IAdr)); + getkeyval(&key, &val); + strxcpy(mlst.contribution, key, sizeof(IAdr)); + CFG->mailinglist.push_back(mlst); +} + +// ------------------------------------------------------------------ + +void CfgMailtoss() { + + char* key; + MailList mlst; + mlst.sender_is_pattern = true; + getkeyval(&key, &val); + strxcpy(mlst.echoid, key, sizeof(Echo)); + getkeyval(&key, &val); + strxcpy(mlst.contribution, key, sizeof(IAdr)); + strxcpy(mlst.sender, val, sizeof(IAdr)); + CFG->mailinglist.push_back(mlst); +} + +// ------------------------------------------------------------------ + +void CfgMappath() { + + char* key; + pair mapentry; + + getkeyval(&key, &val); + + mapentry.first = key; + mapentry.second = val; + CFG->mappath.push_back(mapentry); +} + +// ------------------------------------------------------------------ + +void CfgMember() { + + if(cfgingroup) { + val = strtok(val, ", \t"); + while(val) { + CFG->grp.AddMbr(val); + val = strtok(NULL, ", \t"); + } + } +} + +// ------------------------------------------------------------------ + +void CfgMenumarked() { + + if(strieql(val, "Marked")) + CFG->menumarked = MODE_MARKED; + else if(strieql(val, "Current")) + CFG->menumarked = MODE_CURRENT; + else if(strieql(val, "Previous")) + CFG->menumarked = MODE_PREVIOUS; + else + CFG->menumarked = MODE_DONT; +} + +// ------------------------------------------------------------------ + +void CfgMsglistdate() { + + int flag; + if(strieql(val, "Written")) + flag = MSGLISTDATE_WRITTEN; + else if(strieql(val, "Arrived")) + flag = MSGLISTDATE_ARRIVED; + else if(strieql(val, "Received")) + flag = MSGLISTDATE_RECEIVED; + else + flag = GetYesno(val) ? MSGLISTDATE_WRITTEN : MSGLISTDATE_NONE; + if(cfgingroup) + CFG->grp.AddItm(GRP_MSGLISTDATE, flag); + else + CFG->msglistdate = flag; +} + +// ------------------------------------------------------------------ + +void CfgMsglistfast() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_MSGLISTFAST, flag); + else + CFG->msglistfast = flag; +} + +// ------------------------------------------------------------------ + diff --git a/golded3/gccfgg6.cpp b/golded3/gccfgg6.cpp new file mode 100644 index 0000000..c384416 --- /dev/null +++ b/golded3/gccfgg6.cpp @@ -0,0 +1,373 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Configuration functions, part 6. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern char* val; + + +// ------------------------------------------------------------------ + +void CfgMsglistfirst() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_MSGLISTFIRST, flag); + else + CFG->msglistfirst = flag; +} + +// ------------------------------------------------------------------ + +void CfgMsglistheader() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_MSGLISTHEADER, flag); + else + CFG->msglistheader = flag; +} + +// ------------------------------------------------------------------ + +void CfgMsglistwidesubj() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_MSGLISTWIDESUBJ, flag); + else + CFG->msglistwidesubj = flag; +} + +// ------------------------------------------------------------------ + +void CfgNamesfile() { + + strcpy(CFG->namesfile, val); +} + +// ------------------------------------------------------------------ + +void CfgNickname() { + + Name buf; + + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_NICKNAME, buf, strlen(buf)+1); + else + strcpy(CFG->nickname, buf); +} + +// ------------------------------------------------------------------ + +void CfgNodelist() { + + // Only used by GoldNODE +} + +// ------------------------------------------------------------------ + +void CfgNodepath() { + + PathCopy(CFG->nodepath, val); +} + +// ------------------------------------------------------------------ + +void CfgNodepathfd() { + + PathCopy(CFG->nodepathfd, val); +} + +// ------------------------------------------------------------------ + +void CfgNodepathv7() { + + PathCopy(CFG->nodepathv7, val); +} + +// ------------------------------------------------------------------ + +extern char v7nodeflags[16][9]; + +void CfgNodev7flags() { + + GTok t; + char* flagstring = t.First(val); + char* flagvals = t.Next(); + uint flagval; + if(tolower(*flagvals) == 'b') + flagval = atoi(flagvals+1); + else { + flagval = atoi(flagvals); + switch(flagval) { + case 32: flagval = 5; break; + case 64: flagval = 6; break; + case 128: flagval = 7; break; + case 256: flagval = 8; break; + case 512: flagval = 9; break; + case 1024: flagval = 10; break; + case 2048: flagval = 11; break; + case 8192: flagval = 13; break; + case 16384: flagval = 14; break; + default: flagval = 0; + } + } + if(flagval) + strcpy(stpcpy(v7nodeflags[flagval], flagstring), ","); +} + +// ------------------------------------------------------------------ + +extern char v7modemtype[8][9]; + +void CfgNodev7modem() { + + GTok t; + char* modemstring = t.First(val); + char* modemvals = t.Next(); + int modemval; + if(tolower(*modemvals) == 'b') + modemval = atoi(modemvals+1); + else { + modemval = atoi(modemvals); + switch(modemval) { + case 1: modemval = 0; break; + case 2: modemval = 1; break; + case 4: modemval = 2; break; + case 8: modemval = 3; break; + case 16: modemval = 4; break; + case 32: modemval = 5; break; + case 64: modemval = 6; break; + case 128: modemval = 7; break; + default: modemval = -1; + } + } + if(modemval >= 0) + strcat(stpcpy(v7modemtype[modemval], modemstring), ","); +} + +// ------------------------------------------------------------------ + +void CfgOrganization() { + + INam buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_ORGANIZATION, buf, strlen(buf)+1); + else + strcpy(CFG->organization, buf); +} + +// ------------------------------------------------------------------ + +void CfgOrigin(const char* v) { char buf[256]; val = strxcpy(buf, v, sizeof(buf)); CfgOrigin(); } +void CfgOrigin() { + + if(not strblank(val)) { + StripQuotes(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_ORIGIN, val, strlen(val)+1); + else + CFG->origin.push_back(val); + } +} + +// ------------------------------------------------------------------ + +void CfgOutboundpath() { + + PathCopy(CFG->outboundpath, val); +} + +// ------------------------------------------------------------------ + +void CfgOutputfile() { + + Path buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_OUTPUTFILE, buf, strlen(buf)+1); + else + strcpy(CFG->outputfile, buf); +} + +void CfgPathreportfile() { + + PathCopy(CFG->pathreportfile, val); +} + +// ------------------------------------------------------------------ + +void CfgPcboardpath() { + + PathCopy(CFG->pcboardpath, val); +} + +// ------------------------------------------------------------------ + +void CfgPcboarduserno() { + + CFG->pcboarduserno = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgPersonalmail() { + + if(striinc("STARTUP", val)) + CFG->personalmail |= PM_STARTUP; + if(striinc("NOTSTARTUP", val)) + CFG->personalmail &= ~PM_STARTUP; + if(striinc("ALLNAMES", val)) + CFG->personalmail |= PM_ALLNAMES; + if(striinc("NOTALLNAMES", val)) + CFG->personalmail &= ~PM_ALLNAMES; + if(striinc("LISTONLY", val)) + CFG->personalmail |= PM_LISTONLY; + if(striinc("NOTLISTONLY", val)) + CFG->personalmail &= ~PM_LISTONLY; +} + +// ------------------------------------------------------------------ + +void CfgPlay() { + + Path buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_PLAY, buf, strlen(buf)+1); + else + FileToGPlay(&CFG->play, buf); +} + +// ------------------------------------------------------------------ + +void CfgPrintdevice() { + + strcpy(CFG->printdevice, val); +} + +// ------------------------------------------------------------------ + +void CfgPrintinit() { + + CvtPrnstr(CFG->printinit, val); +} + +// ------------------------------------------------------------------ + +void CfgPrintlength() { + + CFG->printlength = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgPrintmargin() { + + CFG->printmargin = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgPrintreset() { + + CvtPrnstr(CFG->printreset, val); +} + +// ------------------------------------------------------------------ + +void CfgQuotebuffile() { + + Path buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_QUOTEBUFFILE, buf, strlen(buf)+1); + else + strcpy(CFG->quotebuffile, buf); +} + +// ------------------------------------------------------------------ + +void CfgQuotebufmode() { + + if(strieql(val, "ASK")) + CFG->quotebufmode = QBUF_ASK; + else if(strieql(val, "APPEND")) + CFG->quotebufmode = QBUF_APPEND; + else if(strieql(val, "OVERWRITE")) + CFG->quotebufmode = QBUF_OVERWRITE; +} + +// ------------------------------------------------------------------ + +void CfgQuotechars() { + + char buf[11]; + strxcpy(buf, StripQuotes(val), sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_QUOTECHARS, buf, strlen(buf)+1); + else + strcpy(CFG->quotechars, buf); +} + +// ------------------------------------------------------------------ + +void CfgQuotectrl() { + + int ctrlinfo = CI_NONE; + if(striinc("NO", val)) + ctrlinfo = CI_NONE; + else if(striinc("YES", val)) + ctrlinfo = CI_TEAR|CI_ORIG; + else { + if(striinc("TEARLINE", val)) + ctrlinfo |= CI_TEAR; + if(striinc("ORIGIN", val)) + ctrlinfo |= CI_ORIG; + } + if(cfgingroup) + CFG->grp.AddItm(GRP_QUOTECTRL, ctrlinfo); + else + CFG->quotectrl = ctrlinfo; +} + +// ------------------------------------------------------------------ + +void CfgQuotemargin() { + + CFG->cfgquotemargin = atoi(val); + CFG->quotemargin = CFG->cfgquotemargin; +} + +// ------------------------------------------------------------------ + diff --git a/golded3/gccfgg7.cpp b/golded3/gccfgg7.cpp new file mode 100644 index 0000000..a337d9b --- /dev/null +++ b/golded3/gccfgg7.cpp @@ -0,0 +1,428 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Configuration functions, part 7. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern char* val; + + +// ------------------------------------------------------------------ + +void CfgQuotestring() { + + char buf[10]; + strxcpy(buf, StripQuotes(val), sizeof(buf)); + if(*buf == NUL) + strcpy(buf, " > "); + else { + if(buf[strlen(buf)-1] != ' ') + strcat(buf, " "); + } + if(cfgingroup) + CFG->grp.AddItm(GRP_QUOTESTRING, buf, strlen(buf)+1); + else + strcpy(CFG->quotestring, buf); +} + +// ------------------------------------------------------------------ + +void CfgQuotewraphard() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_QUOTEWRAPHARD, flag); + else + CFG->quotewraphard = flag; +} + +// ------------------------------------------------------------------ + +void CfgQwkbadmsgs() { + + QWK->BadMsgs(val); +} + +// ------------------------------------------------------------------ + +void CfgQwkconfmap() { + + char* bbsid; + getkeyval(&bbsid, &val); + + char* confname; + getkeyval(&confname, &val); + strtrim(StripQuotes(confname)); + + char* echoid; + getkeyval(&echoid, &val); + + QWK->AddMap(bbsid, echoid, confname); +} + +// ------------------------------------------------------------------ + +void CfgQwkexportpath() { + + QWK->ExportPath(val); +} + +// ------------------------------------------------------------------ + +void CfgQwkimportpath() { + + QWK->ImportPath(val); +} + +// ------------------------------------------------------------------ + +void CfgQwkoptions() { + + char* bbsid; + getkeyval(&bbsid, &val); + QWK->FindAddBBS(bbsid); + val = strtok(val, ", \t"); + while(val) { + if(strieql(val, "KLUDGES")) + QWK->KludgesAllowed(true); + else if(strieql(val, "NOKLUDGES")) + QWK->KludgesAllowed(false); + else if(strieql(val, "MIXCASE")) + QWK->MixCaseAllowed(true); + else if(strieql(val, "NOMIXCASE")) + QWK->MixCaseAllowed(false); + else if(strieql(val, "RECEIPT")) + QWK->ReceiptAllowed(true); + else if(strieql(val, "NORECEIPT")) + QWK->ReceiptAllowed(false); + else if(strnieql(val, "MAXLINES=", 9)) + QWK->MaxLines(atoi(val+9)); + val = strtok(NULL, ", \t"); + } +} + +// ------------------------------------------------------------------ + +void CfgQwkreplylinker() { + + QWK->ReplyLinker(val); +} + +// ------------------------------------------------------------------ + +void CfgQwktosslog() { + + QWK->TossLog(val); +} + +// ------------------------------------------------------------------ + +void CfgRa2usersbbs() { + + CFG->ra2usersbbs = GetYesno(val) ? 2 : 1; +} + +// ------------------------------------------------------------------ + +void CfgReplylink() { + + if(strieql(val, "Chain")) + CFG->replylink = REPLYLINK_CHAIN; + else if(strieql(val, "Direct")) + CFG->replylink = REPLYLINK_DIRECT; +} + +// ------------------------------------------------------------------ + +void CfgReplylinklist() { + + if(strieql(val, "Fast")) + CFG->replylinklist = REPLYLINKLIST_FAST; + else if(strieql(val, "Full")) + CFG->replylinklist = REPLYLINKLIST_FULL; +} + +// ------------------------------------------------------------------ + +void CfgRobotname(const char* v) { + + char* ptr = val = throw_strdup(v); + CfgRobotname(); + throw_free(ptr); +} + +void CfgRobotname() { + + tokenize(CFG->robotname, val); +} + +// ------------------------------------------------------------------ + +void CfgScreenblanker() { + + GTok t; + if(t.First(val)) { + do { + val = t.Token(); + if(isdigit(*val)) + CFG->screenblanker = atoi(val); + else if(striinc("BLACK", val)) + CFG->screenblankertype = BLANK_ALLBLACK; + } while(t.Next()); + } +} + +// ------------------------------------------------------------------ + +void CfgScreenmaxcol() { + + CFG->screenmaxcol = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgScreenmaxrow() { + + CFG->screenmaxrow = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgScreenpalette() { + + // Syntax: + // + // SCREENPALETTE or + // SCREENPALETTE (red green blue) + + char* key; + getkeyval(&key, &val); + + int palreg = atoi(key); + if(palreg >= 0 and palreg <= 15) { + if(*val != '(') + CFG->screenpalette[palreg] = atoi(val); + else { + val = strskip_wht(val+1); + int redval = atoi(val); // 0 .. 3 + val = strskip_wht(strskip_txt(val)); + int greenval = atoi(val); // 0 .. 3 + val = strskip_wht(strskip_txt(val)); + int blueval = atoi(val); // 0 .. 3 + + // Construct the rgbRGB color val (nuts!) + CFG->screenpalette[palreg] = + ((redval & 2) ? 0x04 : 0x00)| + ((redval & 1) ? 0x20 : 0x00)| + ((greenval & 2) ? 0x02 : 0x00)| + ((greenval & 1) ? 0x10 : 0x00)| + ((blueval & 2) ? 0x01 : 0x00)| + ((blueval & 1) ? 0x08 : 0x00); + } + CFG->screenpalette[16] = true; // Indicate that changes were made + } +} + +// ------------------------------------------------------------------ + +void CfgScreensize() { + + CFG->screensize = atoi(val); + if(CFG->screensize == 4350) { + CFG->screensize = 50; + } + else if(CFG->screensize == 0) { + if(strnieql(val, "Mode", 4)) { + sscanf(val+4, " %x", &CFG->screensize); + CFG->screensize <<= 8; + } + } +} + + +// ------------------------------------------------------------------ + +void CfgSearchfor() { + + INam buf; + strxcpy(buf, StripQuotes(val), sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_SEARCHFOR, buf, strlen(buf)+1); + else + strcpy(CFG->searchfor, buf); +} + +// ------------------------------------------------------------------ + +#define CRC_NETSCAN 0xEC12 +#define CRC_ECHOSCAN 0x6E6D +#define CRC_EXPORTLIST 0x1B14 +#define CRC_IMPORTLIST 0x447F +#define CRC_SCANALL 0x1E57 +#define CRC_SCANTHIS 0x1DAE +#define CRC_SCANNETMAIL 0x74D6 +#define CRC_PMSCANALL 0xD093 +#define CRC_PMSCANTHIS 0xE12C +#define CRC_PMSCANNETMAIL 0x9F1F +#define CRC_QWKIMPORT 0x3063 +#define CRC_QWKEXPORT 0xD7C2 +#define CRC_SOUPIMPORT 0x5564 +#define CRC_SOUPEXPORT 0xB2C5 +#define CRC_EXITNOW 0x65DD +#define CRC_IDLETIME 0x3BBC + +void CfgSemaphore() { + + char* key; + word crc = getkeyvalcrc(&key, &val); + + switch(crc) { + case CRC_NETSCAN: strcpy(CFG->semaphore.netscan, val); break; + case CRC_ECHOSCAN: strcpy(CFG->semaphore.echoscan, val); break; + case CRC_EXPORTLIST: strcpy(CFG->semaphore.exportlist, val); break; + case CRC_IMPORTLIST: strcpy(CFG->semaphore.importlist, val); break; + case CRC_SCANALL: strcpy(CFG->semaphore.scanall, val); break; + case CRC_SCANTHIS: strcpy(CFG->semaphore.scanthis, val); break; + case CRC_SCANNETMAIL: strcpy(CFG->semaphore.scannetmail, val); break; + case CRC_PMSCANALL: strcpy(CFG->semaphore.pmscanall, val); break; + case CRC_PMSCANTHIS: strcpy(CFG->semaphore.pmscanthis, val); break; + case CRC_PMSCANNETMAIL: strcpy(CFG->semaphore.pmscannetmail, val); break; + case CRC_QWKIMPORT: strcpy(CFG->semaphore.qwkimport, val); break; + case CRC_QWKEXPORT: strcpy(CFG->semaphore.qwkexport, val); break; + case CRC_SOUPIMPORT: strcpy(CFG->semaphore.soupimport, val); break; + case CRC_SOUPEXPORT: strcpy(CFG->semaphore.soupexport, val); break; + case CRC_EXITNOW: strcpy(CFG->semaphore.exitnow, val); break; + case CRC_IDLETIME: CFG->semaphore.idletime = atoi(val); break; + default: + return; + } +} + +// ------------------------------------------------------------------ + +void CfgSharemode() { + + if(atoi(val)) + CFG->sharemode = atoi(val); + else + CFG->sharemode = GetYesno(val) ? SH_DENYNO : SH_COMPAT; +} + +// ------------------------------------------------------------------ + +void CfgShowdeleted() { + + CFG->showdeleted = GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgSoundpath() { + + PathCopy(CFG->soundpath, val); +} + +// ------------------------------------------------------------------ + +void CfgSoupbadmsgs() { + + strupr(strxcpy(CFG->soupbadmsgs, val, sizeof(Echo))); +} + +// ------------------------------------------------------------------ + +void CfgSoupemail() { + + strupr(strxcpy(CFG->soupemail, val, sizeof(Echo))); +} + +// ------------------------------------------------------------------ + +void CfgSoupexportmargin() { + + CFG->soupexportmargin = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgSoupexportpath() { + + PathCopy(CFG->soupexportpath, val); +} + +// ------------------------------------------------------------------ + +void CfgSoupimportpath() { + + PathCopy(CFG->soupimportpath, val); +} + +// ------------------------------------------------------------------ + +void CfgSoupnewsrcfile() { + + strcpy(CFG->soupnewsrcfile, val); +} + +// ------------------------------------------------------------------ + +void CfgSoupreplylinker() { + + strcpy(CFG->soupreplylinker, val); +} + +// ------------------------------------------------------------------ + +void CfgSoupreplyto() { + + strxcpy(CFG->soupreplyto, val, sizeof(CFG->soupreplyto)); +} + +// ------------------------------------------------------------------ + +void CfgSouptosslog() { + + strcpy(CFG->souptosslog, val); +} + +// ------------------------------------------------------------------ + +void CfgSquishscan() { + + const int SQS_API = 1; + const int SQS_QUICK = 2; + + if(strieql(val, "API")) + CFG->squishscan = SQS_API; + else if(strieql(val, "QUICK")) + CFG->squishscan = SQS_QUICK; +} + +// ------------------------------------------------------------------ + diff --git a/golded3/gccfgg8.cpp b/golded3/gccfgg8.cpp new file mode 100644 index 0000000..2b16412 --- /dev/null +++ b/golded3/gccfgg8.cpp @@ -0,0 +1,528 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Configuration functions, part 8. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern char* val; + + +// ------------------------------------------------------------------ + +void CfgSquishuserno() { + + CFG->squishuserno = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgSquishuserpath() { + + PathCopy(CFG->squishuserpath, val); +} + +// ------------------------------------------------------------------ + +void CfgStatuslinehelp() { + + CFG->statuslinehelp = strieql(val, "NOLOGO") ? -1 : GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgStylecodepunct() { + + char* key; + getkeyval(&key, &val); + strxcpy(CFG->stylecodepunct, strcvtc(key), sizeof(CFG->stylecodepunct)); +} + +// ------------------------------------------------------------------ + +void CfgStylecodes() { + + if(strieql(val, "HIDE")) { + CFG->hidestylies = true; + CFG->usestylies = true; + } + else { + CFG->hidestylies = false; + CFG->usestylies = GetYesno(val); + } +} + +// ------------------------------------------------------------------ + +void CfgStylecodestops() { + + char* key; + getkeyval(&key, &val); + strxcpy(CFG->stylecodestops, strcvtc(key), sizeof(CFG->stylecodestops)); +} + +// ------------------------------------------------------------------ + +void CfgTagline() { + + char buf[76]; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_TAGLINE, buf, strlen(buf)+1); + else + CFG->tagline.push_back(buf); +} + +// ------------------------------------------------------------------ + +void CfgTaglinechar() { + + StripQuotes(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_TAGLINECHAR, *val); + else + CFG->taglinechar = *val; +} + +// ------------------------------------------------------------------ + +void CfgTaglinesupport() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_TAGLINESUPPORT, flag); + else + CFG->taglinesupport = flag; +} + +// ------------------------------------------------------------------ + +void CfgTasktitle(){ + + strxcpy(CFG->tasktitle, val,sizeof(CFG->tasktitle)); +} + +// ------------------------------------------------------------------ + +void CfgTearline() { + + StripQuotes(val); + Tear buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_TEARLINE, buf, strlen(buf)+1); + else + strcpy(CFG->tearline, buf); +} + +// ------------------------------------------------------------------ + +void CfgTemplate() { + + if(cfgingroup) { + Path buf; + strxcpy(buf, val, sizeof(buf)); + CFG->grp.AddItm(GRP_TEMPLATE, buf, strlen(buf)+1); + } + else { + char* key; + Tpl tp; + *tp.name = NUL; + tp.match.reset(); + getkeyval(&key, &val); + strcpy(tp.file, key); + if((*val == '\'') or (*val == '\"')) { + getkeyval(&key, &val); + strcpy(tp.name, key); + if(*val) + tp.match.set(val); + } + else if(*val) + tp.match.set(val); + if(not *tp.name) + strcpy(tp.name, tp.file); + CFG->tpl.push_back(tp); + } +} + +// ------------------------------------------------------------------ + +void CfgTemplatematch() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_TEMPLATEMATCH, flag); + else + CFG->templatematch = flag; +} + + +// ------------------------------------------------------------------ + +void CfgTemplatepath() { + + PathCopy(CFG->templatepath, val); +} + +// ------------------------------------------------------------------ + +void CfgTemppath() { + + PathCopy(CFG->temppath, val); +} + +// ------------------------------------------------------------------ + +void CfgTimeout() { + + CFG->timeout = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgTitlestatus(){ + + CFG->titlestatus = GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgTwitmode() { + + int tmp = TWIT_SHOW; + if(strieql(val, "Skip")) tmp = TWIT_SKIP; + else if(strieql(val, "Blank")) tmp = TWIT_BLANK; + else if(strieql(val, "Show")) tmp = TWIT_SHOW; + else if(strieql(val, "Ignore")) tmp = TWIT_IGNORE; + else if(strieql(val, "Kill")) tmp = TWIT_KILL; + else tmp = GetYesno(val) ? TWIT_SHOW : TWIT_BLANK; + + if(cfgingroup) + CFG->grp.AddItm(GRP_TWITMODE, tmp); + else + CFG->twitmode = tmp; +} + +// ------------------------------------------------------------------ + +void CfgTwitname() { + + Node tn; + tn.addr.zone = GFTN_ALL; + tn.addr.net = GFTN_ALL; + tn.addr.node = GFTN_ALL; + tn.addr.point = GFTN_ALL; + char* ptr = strrchr(val, ' '); + if(ptr == NULL) + ptr = val; + ptr = strskip_wht(ptr); + if(isdigit(*ptr)) { + if(not CFG->aka.empty()) + tn.addr = CFG->aka[0].addr; + tn.addr.set(ptr); + if(tn.addr.net) { + // Address was given + *ptr = NUL; + strbtrim(val); + } + } + strcpy(tn.name, val); + CFG->twitname.push_back(tn); +} + +// ------------------------------------------------------------------ + +void CfgTwitsubj() { + + CFG->twitsubj.push_back(StripQuotes(val)); +} + +// ------------------------------------------------------------------ + +void CfgUsecharset() { + + CFG->usecharset = GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgUsefwd() { + + int flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_USEFWD, flag); + else + CFG->usefwd = flag; +} + +// ------------------------------------------------------------------ + +void CfgUseintl() { + + CFG->useintl = GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgUsepid() { + + CFG->usepid = GetYesno(val); +} + +// ------------------------------------------------------------------ + +void CfgUserlist() { + + // Only used by GoldNODE +} + +// ------------------------------------------------------------------ + +void CfgUserlistfile() { + + strcpy(CFG->userlistfile, val); +} + +// ------------------------------------------------------------------ + +void CfgUsername(char* v) { val = v; CfgUsername(); } +void CfgUsername() { + + StripQuotes(val); + if(not strblank(val)) { + if(cfgingroup) { + char buf[256]; + strxcpy(buf, val, sizeof(buf)); + CFG->grp.AddItm(GRP_USERNAME, buf, strlen(buf)+1); + } + else { + Node tmp; + + char* aptr = strrchr(val, ','); + if(not aptr) + aptr = strrchr(val, ' '); + + if(aptr) { + char* p = strskip_wht(aptr+1); + tmp.addr.reset(p); + if(not tmp.addr.valid()) + aptr = NULL; + else { + *aptr = NUL; + aptr = p; + } + } + + tmp.addr.set_all(GFTN_ALL); + if(aptr) { + if(not CFG->aka.empty()) + tmp.addr = CFG->aka[0].addr; + tmp.addr.set(aptr); + if(CFG->aka.empty() and tmp.addr.zone != GFTN_ALL + and tmp.addr.net != GFTN_ALL + and tmp.addr.node != GFTN_ALL + and tmp.addr.point != GFTN_ALL) + CfgAddress(tmp.addr.make_string(tmp.name)); // tmp.name is temp-var + } + + strxcpy(tmp.name, strbtrim(val), sizeof(Name)); + + // Check if we have it already + vector::iterator u; + for(u = CFG->username.begin(); u != CFG->username.end(); u++) + if(strieql(tmp.name, u->name)) + return; + + CFG->username.push_back(tmp); + } + } +} + +// ------------------------------------------------------------------ + +void CfgUsetzutc() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_USETZUTC, flag); + else + CFG->usetzutc = flag; +} + +// ------------------------------------------------------------------ + +void CfgUudecodepath() { + + PathCopy(CFG->uudecodepath, val); +} + +// ------------------------------------------------------------------ + +void CfgViewhidden() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_VIEWHIDDEN, flag); + else + CFG->viewhidden = flag; +} + +// ------------------------------------------------------------------ + +void CfgViewkludge() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_VIEWKLUDGE, flag); + else + CFG->viewkludge = flag; +} + +// ------------------------------------------------------------------ + +void CfgViewquote() { + + bool flag = GetYesno(val); + if(cfgingroup) + CFG->grp.AddItm(GRP_VIEWQUOTE, flag); + else + CFG->viewquote = flag; +} + +// ------------------------------------------------------------------ + +void CfgWhoto() { + + Name buf; + strxcpy(buf, val, sizeof(buf)); + if(cfgingroup) + CFG->grp.AddItm(GRP_WHOTO, buf, strlen(buf)+1); + else + strcpy(CFG->whoto, buf); +} + +// ------------------------------------------------------------------ + +void CfgWildcatuserno() { + + CFG->wildcatuserno = atoi(val); +} + +// ------------------------------------------------------------------ + +void CfgXlatcharset() { + + Map xlt; + char* ptr = strtok(val, " \t\n\r"); + if(ptr) { + strchg(strupr(strcpy(xlt.imp, ptr)), '_', ' '); + ptr = strtok(NULL, " \t\n\r"); + if(ptr) { + strchg(strupr(strcpy(xlt.exp, ptr)), '_', ' '); + ptr = strtok(NULL, " \t\n\r"); + if(ptr) { + if(*CFG->xlatpath == NUL) + strcpy(CFG->xlatpath, CFG->goldpath); + MakePathname(ptr, CFG->xlatpath, ptr); + xlt.mapfile = throw_strdup(ptr); + CFG->xlatcharset.push_back(xlt); + } + } + } +} + +// ------------------------------------------------------------------ + +void CfgXlatescset() { + + Map xlt; + char* ptr = strtok(val, " \t\n\r"); + if(ptr) { + strchg(strupr(strcpy(xlt.imp, ptr)), '_', ' '); + ptr = strtok(NULL, " \t\n\r"); + if(ptr) { + strchg(strupr(strcpy(xlt.exp, ptr)), '_', ' '); + ptr = strtok(NULL, " \t\n\r"); + if(ptr) { + if(*CFG->xlatpath == NUL) + strcpy(CFG->xlatpath, CFG->goldpath); + MakePathname(ptr, CFG->xlatpath, ptr); + xlt.mapfile = throw_strdup(ptr); + CFG->xlatescset.push_back(xlt); + } + } + } +} + +// ------------------------------------------------------------------ + +void CfgXlatexport() { + + XlatName buf; + strchg(strupr(strxcpy(buf, val, sizeof(buf))), '_', ' '); + if(cfgingroup) + CFG->grp.AddItm(GRP_XLATEXPORT, buf, strlen(buf)+1); + else + strcpy(CFG->xlatexport, buf); +} + +// ------------------------------------------------------------------ + +void CfgXlatimport() { + + XlatName buf; + strchg(strupr(strxcpy(buf, val, sizeof(buf))), '_', ' '); + if(cfgingroup) + CFG->grp.AddItm(GRP_XLATIMPORT, buf, strlen(buf)+1); + else + strcpy(CFG->xlatimport, buf); +} + +// ------------------------------------------------------------------ + +void CfgXlatlocalset() { + + strupr(strxcpy(CFG->xlatlocalset, val, sizeof(CFG->xlatlocalset))); +} + +// ------------------------------------------------------------------ + +void CfgXlatpath() { + + PathCopy(CFG->xlatpath, val); +} + +// ------------------------------------------------------------------ + +void CfgZonegating() { + + CFG->zonegating = GetYesno(val); +} + +// ------------------------------------------------------------------ + diff --git a/golded3/gckeys.cpp b/golded3/gckeys.cpp new file mode 100644 index 0000000..5e016f3 --- /dev/null +++ b/golded3/gckeys.cpp @@ -0,0 +1,1060 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Keyboard configuration compile. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +CmdKey DefaultKeyset[] = { + + { Key_A_A , KK_AreaAbort , KT_A }, + { Key_A_X , KK_AreaAskExit , KT_A }, + { Key_Esc , KK_AreaAskExit , KT_A }, + { Key_A_F10 , KK_AreaAskExit , KT_A }, + { Key_A_B , KK_AreaBoardnos , KT_A }, + { Key_A_C , KK_AreaCatchUp , KT_A }, + { Key_A_O , KK_AreaDosShell , KT_A }, + { Key_C_M , KK_AreaDropMsgMarks , KT_A }, + { Key_A_H , KK_AreaHeat , KT_A }, + { Key_A_J , KK_AreaJump , KT_A }, + { Key_C_Lft , KK_AreaJump , KT_A }, + { Key_C_Rgt , KK_AreaJump , KT_A }, + { Key_Tab , KK_AreaJumpNextMatch , KT_A }, + { Key_C_Ent , KK_AreaJumpNextMatch , KT_A }, + { Key_C_Q , KK_AreaQuitNow , KT_A }, + { Key_A_S , KK_AreaScan , KT_A }, + { Key_A_P , KK_AreaScanPM , KT_A }, + { Key_Ent , KK_AreaSelect , KT_A }, + { Key_Rgt , KK_AreaSelect , KT_A }, + { Key_A_R , KK_AreaSelectMarks , KT_A }, + { Key_A_F8 , KK_AreaShowDel , KT_R }, + { Key_A_T , KK_AreaToggle , KT_A }, + { Key_Ins , KK_AreaToggle , KT_A }, + { Key_C_Z , KK_AreaTouchNetscan , KT_A }, + { Key_A_W , KK_AreaWriteGoldlast , KT_A }, + { Key_A_Z , KK_AreaZap , KT_A }, + + { Key_Esc , KK_EditAbort , KT_E }, + { Key_A_A , KK_EditAnchor , KT_E }, + { Key_A_X , KK_EditAskExit , KT_E }, + { Key_A_F4 , KK_EditAskExit , KT_E }, + { Key_A_F5 , KK_EditClearDeleteBuf , KT_E }, + { Key_A_F6 , KK_EditClearPasteBuf , KT_E }, + { Key_A_C , KK_EditCopy , KT_E }, + { Key_C_Min , KK_EditCopyAboveChar , KT_E }, + { Key_A_M , KK_EditCut , KT_E }, + { Key_Del , KK_EditDelChar , KT_E }, + { Key_A_K , KK_EditDeleteEOL , KT_E }, + { Key_A_Y , KK_EditDeleteEOL , KT_E }, + { Key_BS , KK_EditDelLeft , KT_E }, + { Key_A_D , KK_EditDelLine , KT_E }, + { Key_C_Y , KK_EditDelLine , KT_E }, + { Key_C_BS , KK_EditDelLtWord , KT_E }, + { Key_C_F5 , KK_EditDelLtWord , KT_E }, + { Key_C_T , KK_EditDelRtWord , KT_E }, + { Key_C_F6 , KK_EditDelRtWord , KT_E }, + { Key_A_O , KK_EditDosShell , KT_E }, + { Key_F4 , KK_EditDupLine , KT_E }, + { Key_A_W , KK_EditExportText , KT_E }, + { Key_Home , KK_EditGoBegLine , KT_E }, + { Key_C_PgDn , KK_EditGoBotLine , KT_E }, + { Key_C_End , KK_EditGoBotMsg , KT_E }, + { Key_Dwn , KK_EditGoDown , KT_E }, + { Key_A_Dwn , KK_EditGoDown , KT_E }, + { Key_C_Dwn , KK_EditGoDown , KT_E }, + { Key_End , KK_EditGoEOL , KT_E }, + { Key_Lft , KK_EditGoLeft , KT_E }, + { Key_A_Lft , KK_EditGoLeft , KT_E }, + { Key_PgDn , KK_EditGoPgDn , KT_E }, + { Key_PgUp , KK_EditGoPgUp , KT_E }, + { Key_Rgt , KK_EditGoRight , KT_E }, + { Key_A_Rgt , KK_EditGoRight , KT_E }, + { Key_C_PgUp , KK_EditGoTopLine , KT_E }, + { Key_C_Home , KK_EditGoTopMsg , KT_E }, + { Key_Up , KK_EditGoUp , KT_E }, + { Key_A_Up , KK_EditGoUp , KT_E }, + { Key_C_Up , KK_EditGoUp , KT_E }, + { Key_C_Lft , KK_EditGoWordLeft , KT_E }, + { Key_C_Rgt , KK_EditGoWordRight , KT_E }, + { Key_A_H , KK_EditHeader , KT_E }, + { Key_A_Q , KK_EditImportQuotebuf , KT_E }, + { Key_A_I , KK_EditImportText , KT_E }, + { Key_A_R , KK_EditImportText , KT_E }, + { Key_F3 , KK_EditImportText , KT_E }, + { Key_F8 , KK_EditLoadFile , KT_E }, + { Key_A_L , KK_EditLookupCursor , KT_E }, + { Key_S_F10 , KK_EditLookupDest , KT_E }, + { Key_F10 , KK_EditLookupOrig , KT_E }, + { Key_Ent , KK_EditNewline , KT_E }, + { Key_A_P , KK_EditPaste , KT_E }, + { Key_C_Q , KK_EditQuitNow , KT_E }, + { Key_A_B , KK_EditReflow , KT_E }, + { Key_F7 , KK_EditSaveFile , KT_E }, + { Key_A_S , KK_EditSaveMsg , KT_E }, + { Key_C_Z , KK_EditSaveMsg , KT_E }, + { Key_F2 , KK_EditSaveMsg , KT_E }, + { Key_F9 , KK_EditSpellCheck , KT_E }, + { Key_Tab , KK_EditTab , KT_E }, + { Key_S_Tab , KK_EditTabReverse , KT_E }, + { Key_A_3 , KK_EditToggleCase , KT_E }, + { Key_Ins , KK_EditToggleInsert , KT_E }, + { Key_A_2 , KK_EditToLower , KT_E }, + { Key_A_1 , KK_EditToUpper , KT_E }, + { Key_C_U , KK_EditUnDelete , KT_E }, + { Key_A_BS , KK_EditUndo , KT_E }, + { Key_A_Z , KK_EditZapQuoteBelow , KT_E }, +#if not defined(__UNIX__) or defined(__USE_NCURSES__) + { Key_C_Ins , KK_EditCopy , KT_E }, + { Key_S_Del , KK_EditCut , KT_E }, + { Key_C_Del , KK_EditDelete , KT_E }, + { Key_S_Ins , KK_EditPaste , KT_E }, + { Key_S_PgUp , KK_EditBlockPgUp , KT_E }, + { Key_S_PgDn , KK_EditBlockPgDn , KT_E }, + { Key_S_Home , KK_EditBlockHome , KT_E }, + { Key_S_End , KK_EditBlockEnd , KT_E }, + { Key_S_Up , KK_EditBlockUp , KT_E }, + { Key_S_Dwn , KK_EditBlockDown , KT_E }, + { Key_S_Lft , KK_EditBlockLeft , KT_E }, + { Key_S_Rgt , KK_EditBlockRight , KT_E }, +#endif + + { Key_Esc , KK_FileAbort , KT_F }, + { Key_A_X , KK_FileAskExit , KT_F }, + { Key_A_F4 , KK_FileAskExit , KT_F }, + { Key_A_O , KK_FileDosShell , KT_F }, + { Key_Ins , KK_FileMark , KT_F }, + { Key_Plus , KK_FileMark , KT_F }, + { Key_C_Ent , KK_FileMarkAll , KT_F }, + { Key_C_Home , KK_FileMarkAll , KT_F }, + { Key_C_Q , KK_FileQuitNow , KT_F }, + { Key_Ent , KK_FileSelect , KT_F }, + { Key_Space , KK_FileToggleMark , KT_F }, + { Key_Multi , KK_FileToggleMarkAll , KT_F }, + { Key_Del , KK_FileUnMark , KT_F }, + { Key_Minus , KK_FileUnMark , KT_F }, + { Key_C_End , KK_FileUnMarkAll , KT_F }, + + { Key_Esc , KK_ListAbort , KT_M }, + { Key_A_X , KK_ListAskExit , KT_M }, + { Key_A_F4 , KK_ListAskExit , KT_M }, + { Key_A_O , KK_ListDosShell , KT_M }, + { Key_S_Tab , KK_ListGotoBookMark , KT_M }, + { Key_BS , KK_ListGotoBookMark , KT_M }, + { Key_S , KK_ListMarkingOptions , KT_M }, + { Key_A_S , KK_ListMarkingOptions , KT_M }, + { Key_A_F9 , KK_ListMarkingOptions , KT_R }, + { Key_C_Q , KK_ListQuitNow , KT_M }, + { Key_Ent , KK_ListSelect , KT_M }, + { Key_Tab , KK_ListToggleBookMark , KT_M }, + { Key_C_D , KK_ListToggleDate , KT_M }, + { Key_Space , KK_ListToggleMark , KT_M }, + { Key_C_B , KK_ListToggleWideSubj , KT_M }, + + { Key_Esc , KK_NodeAbort , KT_N }, + { Key_A_X , KK_NodeAskExit , KT_N }, + { Key_A_F4 , KK_NodeAskExit , KT_N }, + { Key_A_O , KK_NodeDosShell , KT_N }, + { Key_C_Q , KK_NodeQuitNow , KT_N }, + { Key_Ent , KK_NodeSelect , KT_N }, + + { Key_C_B , KK_ReadAddressbookAdd , KT_R }, + { Key_X , KK_ReadAskExit , KT_R }, + { Key_A_X , KK_ReadAskExit , KT_R }, + { Key_A_F4 , KK_ReadAskExit , KT_R }, + { Key_C_A , KK_ReadChangeAka , KT_R }, + { Key_C_S , KK_ReadChangeAttrs , KT_R }, + { Key_C , KK_ReadChangeMsg , KT_R }, + { Key_A_C , KK_ReadChangeMsg , KT_R }, + { Key_F2 , KK_ReadChangeMsg , KT_R }, + { Key_C_O , KK_ReadChangeOrigin , KT_R }, + { Key_C_I , KK_ReadChangeTagline , KT_R }, + { Key_C_T , KK_ReadChangeTemplate , KT_R }, + { Key_C_U , KK_ReadChangeUsername , KT_R }, + { Key_C_J , KK_ReadChangeXlatImport , KT_R }, + { Key_G , KK_ReadCommentMsg , KT_R }, + { Key_A_G , KK_ReadCommentMsg , KT_R }, + { Key_M , KK_ReadCopyMoveForward , KT_R }, + { Key_A_M , KK_ReadCopyMoveForward , KT_R }, + { Key_S_F8 , KK_ReadCopyMoveForward , KT_R }, + { Key_D , KK_ReadDeleteMsg , KT_R }, + { Key_A_D , KK_ReadDeleteMsg , KT_R }, + { Key_Del , KK_ReadDeleteMsg , KT_R }, + { Key_O , KK_ReadDosShell , KT_R }, + { Key_A_O , KK_ReadDosShell , KT_R }, + { Key_C_F10 , KK_ReadDosShell , KT_R }, + { Key_C_R , KK_ReadFidoRenumber , KT_R }, + { Key_S_F4 , KK_ReadFidoRenumber , KT_R }, + { Key_C_F , KK_ReadFileRequest , KT_R }, + { Key_F , KK_ReadFindAll , KT_R }, + { Key_A_F , KK_ReadFindAll , KT_R }, + { Key_S_F6 , KK_ReadFindAll , KT_R }, + { Key_Z , KK_ReadFindHeader , KT_R }, + { Key_A_Z , KK_ReadFindHeader , KT_R }, + { Key_F6 , KK_ReadFindHeader , KT_R }, + { Key_S_Tab , KK_ReadGotoBookMark , KT_R }, + { Key_BS , KK_ReadGotoBookMark , KT_R }, + { Key_Lsr , KK_ReadGotoFirstMsg , KT_R }, + { Key_C_Home , KK_ReadGotoFirstMsg , KT_R }, + { Key_Gtr , KK_ReadGotoLastMsg , KT_R }, + { Key_C_End , KK_ReadGotoLastMsg , KT_R }, + { Key_C_G , KK_ReadGotoMsgno , KT_R }, + { Key_C_N , KK_ReadGotoNextArea , KT_R }, + { Key_Rgt , KK_ReadGotoNextMsg , KT_R }, + { Key_A_Rgt , KK_ReadGotoNextUnread , KT_R }, + { Key_A_U , KK_ReadGotoNextUnread , KT_R }, + { Key_C_P , KK_ReadGotoPrevArea , KT_R }, + { Key_Lft , KK_ReadGotoPrevMsg , KT_R }, + { Key_A_Lft , KK_ReadGotoPrevUnread , KT_R }, + { Key_Plus , KK_ReadGotoReplies , KT_R }, + { Key_C_Rgt , KK_ReadGotoReplies , KT_R }, + { Key_Multi , KK_ReadGotoReplyNext , KT_R }, + { Key_Minus , KK_ReadGotoReplyPrev , KT_R }, + { Key_C_Lft , KK_ReadGotoReplyPrev , KT_R }, + { Key_S_F10 , KK_ReadLookupDest , KT_R }, + { Key_F10 , KK_ReadLookupOrig , KT_R }, + { Key_C_L , KK_ReadMakeUserlist , KT_R }, + { Key_C_K , KK_ReadMakePathreport , KT_R }, + { Key_S , KK_ReadMarkingOptions , KT_R }, + { Key_A_S , KK_ReadMarkingOptions , KT_R }, + { Key_A_F9 , KK_ReadMarkingOptions , KT_R }, + { Key_A_L , KK_ReadMessageList , KT_R }, + { Key_F9 , KK_ReadMessageList , KT_R }, + { Key_L , KK_ReadMessageList , KT_R }, + { Key_B , KK_ReadMoveCommentMsg , KT_R }, + { Key_A_B , KK_ReadMoveCommentMsg , KT_R }, + { Key_N , KK_ReadMoveQuoteMsg , KT_R }, + { Key_A_N , KK_ReadMoveQuoteMsg , KT_R }, + { Key_F5 , KK_ReadMoveQuoteMsg , KT_R }, + { Key_Ent , KK_ReadMsgContinue , KT_R }, + { Key_End , KK_ReadMsgEnd , KT_R }, + { Key_Home , KK_ReadMsgHome , KT_R }, + { Key_Dwn , KK_ReadMsgLineDown , KT_R }, + { Key_C_Dwn , KK_ReadMsgLineDown , KT_R }, + { Key_Up , KK_ReadMsgLineUp , KT_R }, + { Key_C_Up , KK_ReadMsgLineUp , KT_R }, + { Key_PgDn , KK_ReadMsgPgDn , KT_R }, + { Key_PgUp , KK_ReadMsgPgUp , KT_R }, + { Key_A , KK_ReadNewArea , KT_R }, + { Key_A_A , KK_ReadNewArea , KT_R }, + { Key_Esc , KK_ReadNewArea , KT_R }, + { Key_C_F1 , KK_ReadNewArea , KT_R }, + { Key_E , KK_ReadNewMsg , KT_R }, + { Key_A_E , KK_ReadNewMsg , KT_R }, + { Key_Ins , KK_ReadNewMsg , KT_R }, + { Key_C_Q , KK_ReadQuitNow , KT_R }, + { Key_C_W , KK_ReadQuoteBuf , KT_R }, + { Key_Q , KK_ReadQuoteMsg , KT_R }, + { Key_A_Q , KK_ReadQuoteMsg , KT_R }, + { Key_F4 , KK_ReadQuoteMsg , KT_R }, + { Key_R , KK_ReadReplyMsg , KT_R }, + { Key_A_R , KK_ReadReplyMsg , KT_R }, + { Key_F3 , KK_ReadReplyMsg , KT_R }, + { Key_S_3 , KK_ReadThreadtree , KT_R }, + { Key_Tab , KK_ReadToggleBookMark , KT_R }, + { Key_I , KK_ReadToggleHexdump , KT_R }, + { Key_A_I , KK_ReadToggleHexdump , KT_R }, + { Key_C_F9 , KK_ReadToggleHexdump , KT_R }, + { Key_H , KK_ReadToggleHidden , KT_R }, + { Key_A_H , KK_ReadToggleHidden , KT_R }, + { Key_C_F7 , KK_ReadToggleHidden , KT_R }, + { Key_V , KK_ReadToggleHiddKlud , KT_R }, + { Key_A_V , KK_ReadToggleHiddKlud , KT_R }, + { Key_C_F5 , KK_ReadToggleHiddKlud , KT_R }, + { Key_K , KK_ReadToggleKludge , KT_R }, + { Key_A_K , KK_ReadToggleKludge , KT_R }, + { Key_C_F6 , KK_ReadToggleKludge , KT_R }, + { Key_Space , KK_ReadToggleMark , KT_R }, + { Key_J , KK_ReadToggleMarkRead , KT_R }, + { Key_A_J , KK_ReadToggleMarkRead , KT_R }, + { Key_P , KK_ReadTogglePageBar , KT_R }, + { Key_A_P , KK_ReadTogglePageBar , KT_R }, + { Key_C_F8 , KK_ReadTogglePageBar , KT_R }, + { Key_C_V , KK_ReadToggleQuote , KT_R }, + { Key_Y , KK_ReadToggleRealMsgno , KT_R }, + { Key_A_Y , KK_ReadToggleRealMsgno , KT_R }, + { Key_C_F4 , KK_ReadToggleRealMsgno , KT_R }, + { Key_U , KK_ReadToggleROT13 , KT_R }, + { Key_C_F3 , KK_ReadToggleROT13 , KT_R }, + { Key_C_H , KK_ReadToggleStyles , KT_R }, + { Key_T , KK_ReadToggleTwits , KT_R }, + { Key_A_T , KK_ReadToggleTwits , KT_R }, + { Key_C_Z , KK_ReadTouchNetscan , KT_R }, + { Key_A_F10 , KK_ReadUserbase , KT_R }, + { Key_C_X , KK_ReadUUDecode , KT_R }, + { Key_W , KK_ReadWriteMsg , KT_R }, + { Key_A_W , KK_ReadWriteMsg , KT_R }, + { Key_F7 , KK_ReadWriteMsg , KT_R }, + + { 0xFFFF , 0xFFFF , 0xFF } +}; + + +// ------------------------------------------------------------------ + +// must be sorted by crc_token +tglobalkey globalkeys[] = { + { CRC_READLOOKUPDEST , KK_ReadLookupDest , KT_R }, // 0x0023 + { CRC_READADDRESSBOOKADD , KK_ReadAddressbookAdd , KT_R }, // 0x00FA + { CRC_LISTDOSSHELL , KK_ListDosShell , KT_M }, // 0x0130 + { CRC_EDITGOLEFT , KK_EditGoLeft , KT_E }, // 0x043B + { CRC_READTOGGLEHIDDEN , KK_ReadToggleHidden , KT_R }, // 0x04CE + { CRC_EDITIMPORTTEXT , KK_EditImportText , KT_E }, // 0x0586 +#if not defined(__UNIX__) or defined(__USE_NCURSES__) + { CRC_K_SEND , Key_S_End , 0 }, // 0x0590 +#endif + { CRC_READGOTOPREVMSG , KK_ReadGotoPrevMsg , KT_R }, // 0x06D9 + { CRC_K_STAB , Key_S_Tab , 0 }, // 0x0886 + { CRC_EDITLOADFILE , KK_EditLoadFile , KT_A }, // 0x0931 + { CRC_READFILEREQUEST , KK_ReadFileRequest , KT_R }, // 0x0A07 + { CRC_AREASELECTMARKS , KK_AreaSelectMarks , KT_A }, // 0x0AC3 + { CRC_K_ALEFT , Key_A_Lft , 0 }, // 0x0B39 + { CRC_READCHANGECHARSIN , KK_ReadChangeCharsIn , KT_R }, // 0x0B87 + { CRC_K_AF4 , Key_A_F4 , 0 }, // 0x0EF0 + { CRC_K_AF5 , Key_A_F5 , 0 }, // 0x0EF1 + { CRC_K_AF6 , Key_A_F6 , 0 }, // 0x0EF2 + { CRC_K_AF7 , Key_A_F7 , 0 }, // 0x0EF3 + { CRC_K_AF1 , Key_A_F1 , 0 }, // 0x0EF5 + { CRC_K_AF2 , Key_A_F2 , 0 }, // 0x0EF6 + { CRC_K_AF3 , Key_A_F3 , 0 }, // 0x0EF7 + { CRC_K_AF8 , Key_A_F8 , 0 }, // 0x0EFC + { CRC_K_AF9 , Key_A_F9 , 0 }, // 0x0EFD + { CRC_K_BSPACE , Key_BS , 0 }, // 0x0F07 + { CRC_LISTGOTOBOOKMARK , KK_ListGotoBookMark , KT_M }, // 0x0F08 + { CRC_EDITDELETEEOL , KK_EditDeleteEOL , KT_E }, // 0x1143 + { CRC_FILEUNMARKALL , KK_FileUnMarkAll , KT_F }, // 0x121A + { CRC_K_SPACE , Key_Space , 0 }, // 0x1281 + { CRC_EDITREFLOW , KK_EditReflow , KT_E }, // 0x13F9 + { CRC_K_AF12 , Key_A_F12 , 0 }, // 0x14FC + { CRC_K_AF10 , Key_A_F10 , 0 }, // 0x14FE + { CRC_K_AF11 , Key_A_F11 , 0 }, // 0x14FF + { CRC_LISTGOTONEXT , KK_ListGotoNext , KT_M }, // 0x1641 + { CRC_K_LEFT , Key_Lft , 0 }, // 0x1694 + { CRC_READREPLYMSG , KK_ReadReplyMsg , KT_R }, // 0x172F + { CRC_AREAGOTOLAST , KK_AreaGotoLast , KT_A }, // 0x177A + { CRC_READINCREASEMARGIN , KK_ReadIncreaseMargin , KT_R }, // 0x1797 + { CRC_EDITEXITMSG , KK_EditExitMsg , KT_E }, // 0x1813 + { CRC_READTOGGLEPAGEBAR , KK_ReadTogglePageBar , KT_R }, // 0x18E4 + { CRC_K_F12 , Key_F12 , 0 }, // 0x1930 + { CRC_K_F10 , Key_F10 , 0 }, // 0x1932 + { CRC_K_F11 , Key_F11 , 0 }, // 0x1933 + { CRC_READGOTOREPLIES , KK_ReadGotoReplies , KT_R }, // 0x1A6B + { CRC_READMOVEQUOTEMSG , KK_ReadMoveQuoteMsg , KT_R }, // 0x1B41 + { CRC_EDITGOEOL , KK_EditGoEOL , KT_E }, // 0x1CC6 + { CRC_K_AUP , Key_A_Up , 0 }, // 0x1D94 + { CRC_AREAABORT , KK_AreaAbort , KT_A }, // 0x1E02 + { CRC_READTOGGLEMARK , KK_ReadToggleMark , KT_R }, // 0x1E64 + { CRC_READFIDORENUMBER , KK_ReadFidoRenumber , KT_R }, // 0x1E7C +#if not defined(__UNIX__) or defined(__USE_NCURSES__) + { CRC_K_SDEL , Key_S_Del , 0 }, // 0x1EB9 +#endif + { CRC_EDITCOPY , KK_EditCopy , KT_E }, // 0x1F77 + { CRC_READEXTERNUTILMENU , KK_ReadExternUtilMenu , KT_R }, // 0x2000 + { CRC_READCHANGEAKA , KK_ReadChangeAka , KT_R }, // 0x2015 + { CRC_EDITGOWORDRIGHT , KK_EditGoWordRight , KT_E }, // 0x20D0 + { CRC_K_CRIGHT , Key_C_Rgt , 0 }, // 0x20EC + { CRC_EDITBLOCKRIGHT , KK_EditBlockRight , KT_E }, // 0x20F9 + { CRC_AREAJUMP , KK_AreaJump , KT_A }, // 0x2342 + { CRC_K_CPGUP , Key_C_PgUp , 0 }, // 0x2603 + { CRC_READGOTOPREVUNREAD , KK_ReadGotoPrevUnread , KT_R }, // 0x27EA + { CRC_READTOGGLEREALMSGNO , KK_ReadToggleRealMsgno , KT_R }, // 0x2A3B + { CRC_AREADOSSHELL , KK_AreaDosShell , KT_A }, // 0x2DED + { CRC_K_DOWN , Key_Dwn , 0 }, // 0x2F6D + { CRC_READNEWMSG , KK_ReadNewMsg , KT_R }, // 0x30CA + { CRC_NODEGOTOFIRST , KK_NodeGotoFirst , KT_N }, // 0x321B + { CRC_READUNDEFINE , KK_ReadUndefine , KT_R }, // 0x329D + { CRC_K_ADOWN , Key_A_Dwn , 0 }, // 0x32C0 + { CRC_K_CF12 , Key_C_F12 , 0 }, // 0x3480 + { CRC_K_CF10 , Key_C_F10 , 0 }, // 0x3482 + { CRC_K_CF11 , Key_C_F11 , 0 }, // 0x3483 + { CRC_K_CHOME , Key_C_Home , 0 }, // 0x35C4 + { CRC_K_CPGDN , Key_C_PgDn , 0 }, // 0x371D + { CRC_EDITCOPYABOVECHAR , KK_EditCopyAboveChar , KT_E }, // 0x380C + { CRC_LISTSELECT , KK_ListSelect , KT_M }, // 0x3829 + { CRC_READGOTOFIRSTMSG , KK_ReadGotoFirstMsg , KT_R }, // 0x392F + { CRC_AREAGOTONEXT , KK_AreaGotoNext , KT_A }, // 0x3A9C + { CRC_EDITDELLTWORD , KK_EditDelLtWord , KT_E }, // 0x3B67 + { CRC_LISTGOTOLAST , KK_ListGotoLast , KT_M }, // 0x3BA7 + { CRC_LISTTOGGLEWIDESUBJ , KK_ListToggleWideSubj , KT_M }, // 0x3C76 + { CRC_READMENU , KK_ReadMenu , KT_R }, // 0x3D0A + { CRC_EDITGODOWN , KK_EditGoDown , KT_E }, // 0x3DC2 + { CRC_K_A0 , Key_A_0 , 0 }, // 0x4030 + { CRC_K_A1 , Key_A_1 , 0 }, // 0x4031 + { CRC_K_A2 , Key_A_2 , 0 }, // 0x4032 + { CRC_K_A3 , Key_A_3 , 0 }, // 0x4033 + { CRC_K_A4 , Key_A_4 , 0 }, // 0x4034 + { CRC_K_A5 , Key_A_5 , 0 }, // 0x4035 + { CRC_K_A6 , Key_A_6 , 0 }, // 0x4036 + { CRC_K_A7 , Key_A_7 , 0 }, // 0x4037 + { CRC_K_A8 , Key_A_8 , 0 }, // 0x4038 + { CRC_K_A9 , Key_A_9 , 0 }, // 0x4039 + { CRC_K_AA , Key_A_A , 0 }, // 0x4041 + { CRC_K_AB , Key_A_B , 0 }, // 0x4042 + { CRC_K_AC , Key_A_C , 0 }, // 0x4043 + { CRC_K_AD , Key_A_D , 0 }, // 0x4044 + { CRC_K_AE , Key_A_E , 0 }, // 0x4045 + { CRC_K_AF , Key_A_F , 0 }, // 0x4046 + { CRC_K_AG , Key_A_G , 0 }, // 0x4047 + { CRC_K_AH , Key_A_H , 0 }, // 0x4048 + { CRC_K_AI , Key_A_I , 0 }, // 0x4049 + { CRC_K_AJ , Key_A_J , 0 }, // 0x404A + { CRC_K_AK , Key_A_K , 0 }, // 0x404B + { CRC_K_AL , Key_A_L , 0 }, // 0x404C + { CRC_K_AM , Key_A_M , 0 }, // 0x404D + { CRC_K_AN , Key_A_N , 0 }, // 0x404E + { CRC_K_AO , Key_A_O , 0 }, // 0x404F + { CRC_K_AP , Key_A_P , 0 }, // 0x4050 + { CRC_K_AQ , Key_A_Q , 0 }, // 0x4051 + { CRC_K_AR , Key_A_R , 0 }, // 0x4052 + { CRC_K_AS , Key_A_S , 0 }, // 0x4053 + { CRC_K_AT , Key_A_T , 0 }, // 0x4054 + { CRC_K_AU , Key_A_U , 0 }, // 0x4055 + { CRC_K_AV , Key_A_V , 0 }, // 0x4056 + { CRC_K_AW , Key_A_W , 0 }, // 0x4057 + { CRC_K_AX , Key_A_X , 0 }, // 0x4058 + { CRC_K_AY , Key_A_Y , 0 }, // 0x4059 + { CRC_K_AZ , Key_A_Z , 0 }, // 0x405A + { CRC_K_ADEL , Key_A_Del , 0 }, // 0x40C0 + { CRC_NODEMACRO , KK_NodeMacro , KT_N }, // 0x4129 +#if not defined(__UNIX__) or defined(__USE_NCURSES__) + { CRC_K_SUP , Key_S_Up , 0 }, // 0x4151 +#endif + { CRC_AREAGOTOFIRST , KK_AreaGotoFirst , KT_A }, // 0x41CB + { CRC_LISTABORT , KK_ListAbort , KT_M }, // 0x4313 + { CRC_READGOTOBOOKMARK , KK_ReadGotoBookMark , KT_R }, // 0x4383 + { CRC_READMSGCONTINUE , KK_ReadMsgContinue , KT_R }, // 0x4511 + { CRC_K_F1 , Key_F1 , 0 }, // 0x4631 + { CRC_K_F2 , Key_F2 , 0 }, // 0x4632 + { CRC_K_F3 , Key_F3 , 0 }, // 0x4633 + { CRC_K_F4 , Key_F4 , 0 }, // 0x4634 + { CRC_K_F5 , Key_F5 , 0 }, // 0x4635 + { CRC_K_F6 , Key_F6 , 0 }, // 0x4636 + { CRC_K_F7 , Key_F7 , 0 }, // 0x4637 + { CRC_K_F8 , Key_F8 , 0 }, // 0x4638 + { CRC_K_F9 , Key_F9 , 0 }, // 0x4639 + { CRC_READTOGGLEKLUDGE , KK_ReadToggleKludge , KT_R }, // 0x46AB + { CRC_READCHANGEATTRS , KK_ReadChangeAttrs , KT_R }, // 0x47F8 + { CRC_READSEARCH , KK_ReadSearch , KT_R }, // 0x48EF + { CRC_READMSGPGDN , KK_ReadMsgPgDn , KT_R }, // 0x4908 + { CRC_LISTGOTOPREV , KK_ListGotoPrev , KT_M }, // 0x49E9 + { CRC_READQUOTEBUF , KK_ReadQuoteBuf , KT_R }, // 0x49EE + { CRC_EDITDELETE , KK_EditDelete , KT_E }, // 0x4A37 + { CRC_K_SF12 , Key_S_F12 , 0 }, // 0x4A85 + { CRC_K_SF11 , Key_S_F11 , 0 }, // 0x4A86 + { CRC_K_SF10 , Key_S_F10 , 0 }, // 0x4A87 + { CRC_READMAKEPATHREPORT , KK_ReadMakePathreport , KT_R }, // 0x4AA6 + { CRC_K_ESC , Key_Esc , 0 }, // 0x4B22 + { CRC_READMSGHOME , KK_ReadMsgHome , KT_R }, // 0x4BD1 + { CRC_KK_MACRO , Key_Macro , 0 }, // 0x4BE9 + { CRC_READTOUCHNETSCAN , KK_ReadTouchNetscan , KT_R }, // 0x4BF3 + { CRC_EDITUNDELETE , KK_EditUnDelete , KT_E }, // 0x4C34 + { CRC_K_DEL , Key_Del , 0 }, // 0x4D0C + { CRC_READCHANGECHARSOUT , KK_ReadChangeCharsOut , KT_R }, // 0x4DF9 + { CRC_READUUDECODE , KK_ReadUUDecode , KT_R }, // 0x4F0B + { CRC_FILEUNDEFINE , KK_FileUndefine , KT_F }, // 0x502B + { CRC_K_CENTER , Key_C_Ent , 0 }, // 0x50DC + { CRC_AREAZAP , KK_AreaZap , KT_A }, // 0x5125 + { CRC_K_SF1 , Key_S_F1 , 0 }, // 0x5230 + { CRC_K_SF3 , Key_S_F3 , 0 }, // 0x5232 + { CRC_K_SF2 , Key_S_F2 , 0 }, // 0x5233 + { CRC_K_SF5 , Key_S_F5 , 0 }, // 0x5234 + { CRC_K_SF4 , Key_S_F4 , 0 }, // 0x5235 + { CRC_K_SF7 , Key_S_F7 , 0 }, // 0x5236 + { CRC_K_SF6 , Key_S_F6 , 0 }, // 0x5237 + { CRC_K_SF9 , Key_S_F9 , 0 }, // 0x5238 + { CRC_K_SF8 , Key_S_F8 , 0 }, // 0x5239 + { CRC_K_CLEFT , Key_C_Lft , 0 }, // 0x535B + { CRC_K_UP , Key_Up , 0 }, // 0x5550 + { CRC_K_END , Key_End , 0 }, // 0x5625 + { CRC_K_ATAB , Key_A_Tab , 0 }, // 0x56FF + { CRC_READMSGPGUP , KK_ReadMsgPgUp , KT_R }, // 0x5816 + { CRC_AREATOUCHNETSCAN , KK_AreaTouchNetscan , KT_A }, // 0x58C1 + { CRC_EDITNEWLINE , KK_EditNewline , KT_E }, // 0x59F3 + { CRC_K_CBSPACE , Key_C_BS , 0 }, // 0x5A72 + { CRC_EDITEXPORTTEXT , KK_EditExportText , KT_E }, // 0x5AED + { CRC_EDITLOOKUPORIG , KK_EditLookupOrig , KT_E }, // 0x5AFB + { CRC_AREAHEAT , KK_AreaHeat , KT_A }, // 0x5B15 +#if not defined(__UNIX__) or defined(__USE_NCURSES__) + { CRC_K_SRIGHT , Key_S_Rgt , 0 }, // 0x5B1F +#endif + { CRC_READGOTONEXTAREA , KK_ReadGotoNextArea , KT_R }, // 0x5B23 + { CRC_K_TAB , Key_Tab , 0 }, // 0x5B33 + { CRC_K_AEND , Key_A_End , 0 }, // 0x5BE9 + { CRC_FILEMACRO , KK_FileMacro , KT_F }, // 0x5D48 + { CRC_READMSGLINEDOWN , KK_ReadMsgLineDown , KT_R }, // 0x5DB2 + { CRC_K_CMINUS , Key_C_Min , 0 }, // 0x5E2D + { CRC_NODEUNDEFINE , KK_NodeUndefine , KT_N }, // 0x5E32 + { CRC_K_CA , Key_C_A , 0 }, // 0x5E41 + { CRC_K_CB , Key_C_B , 0 }, // 0x5E42 + { CRC_K_CC , Key_C_C , 0 }, // 0x5E43 + { CRC_K_CD , Key_C_D , 0 }, // 0x5E44 + { CRC_K_CE , Key_C_E , 0 }, // 0x5E45 + { CRC_K_CF , Key_C_F , 0 }, // 0x5E46 + { CRC_K_CG , Key_C_G , 0 }, // 0x5E47 + { CRC_K_CH , Key_C_H , 0 }, // 0x5E48 + { CRC_K_CI , Key_C_I , 0 }, // 0x5E49 + { CRC_K_CJ , Key_C_J , 0 }, // 0x5E4A + { CRC_K_CK , Key_C_K , 0 }, // 0x5E4B + { CRC_K_CL , Key_C_L , 0 }, // 0x5E4C + { CRC_K_CM , Key_C_M , 0 }, // 0x5E4D + { CRC_K_CN , Key_C_N , 0 }, // 0x5E4E + { CRC_K_CO , Key_C_O , 0 }, // 0x5E4F + { CRC_K_CP , Key_C_P , 0 }, // 0x5E50 + { CRC_K_CQ , Key_C_Q , 0 }, // 0x5E51 + { CRC_K_CR , Key_C_R , 0 }, // 0x5E52 + { CRC_K_CS , Key_C_S , 0 }, // 0x5E53 + { CRC_K_CT , Key_C_T , 0 }, // 0x5E54 + { CRC_K_CU , Key_C_U , 0 }, // 0x5E55 + { CRC_K_CV , Key_C_V , 0 }, // 0x5E56 + { CRC_K_CW , Key_C_W , 0 }, // 0x5E57 + { CRC_K_CX , Key_C_X , 0 }, // 0x5E58 + { CRC_K_CY , Key_C_Y , 0 }, // 0x5E59 + { CRC_K_CZ , Key_C_Z , 0 }, // 0x5E5A + { CRC_READCOMMENTMSG , KK_ReadCommentMsg , KT_R }, // 0x5E89 + { CRC_READTOGGLETWITS , KK_ReadToggleTwits , KT_R }, // 0x5FD1 + { CRC_EDITGOPGDN , KK_EditGoPgDn , KT_E }, // 0x607D + { CRC_K_CDEL , Key_C_Del , 0 }, // 0x60BC + { CRC_KK_AUTO , Key_Auto , 0 }, // 0x60E2 + { CRC_READFINDHEADER , KK_ReadFindHeader , KT_R }, // 0x6343 + { CRC_K_PGUP , Key_PgUp , 0 }, // 0x63CC + { CRC_EDITABORT , KK_EditAbort , KT_E }, // 0x6468 + { CRC_EDITSAVEFILE , KK_EditSaveFile , KT_E }, // 0x64A4 + { CRC_AREAGOTOPREV , KK_AreaGotoPrev , KT_A }, // 0x6534 + { CRC_EDITDELLEFT , KK_EditDelLeft , KT_E }, // 0x6552 + { CRC_EDITSAVEMSG , KK_EditSaveMsg , KT_E }, // 0x660C + { CRC_K_CGMUL , Key_C_StrG , 0 }, // 0x66CA + { CRC_NODESELECT , KK_NodeSelect , KT_N }, // 0x6A64 + { CRC_K_CDOWN , Key_C_Dwn , 0 }, // 0x6AA2 + { CRC_EDITGORIGHT , KK_EditGoRight , KT_E }, // 0x6AFE + { CRC_READTOUCHSEMAPHORE , KK_ReadTouchSemaphore , KT_R }, // 0x6B1D + { CRC_EDITGOTOPMSG , KK_EditGoTopMsg , KT_E }, // 0x6BD3 + { CRC_READCHANGETEMPLATE , KK_ReadChangeTemplate , KT_R }, // 0x6C86 + { CRC_FILEUNMARK , KK_FileUnMark , KT_F }, // 0x6D1B + { CRC_EDITTOLOWER , KK_EditToLower , KT_E }, // 0x6D85 + { CRC_K_AHOME , Key_A_Home , 0 }, // 0x6DA6 + { CRC_LISTTOGGLEDATE , KK_ListToggleDate , KT_M }, // 0x6F1F + { CRC_K_APGDN , Key_A_PgDn , 0 }, // 0x6F7F + { CRC_K_HOME , Key_Home , 0 }, // 0x700B + { CRC_EDITGOPGUP , KK_EditGoPgUp , KT_E }, // 0x7163 + { CRC_READMSGLINEUP , KK_ReadMsgLineUp , KT_R }, // 0x7238 + { CRC_EDITHEADER , KK_EditHeader , KT_E }, // 0x726F + { CRC_K_PGDN , Key_PgDn , 0 }, // 0x72D2 + { CRC_READWRITEMSG , KK_ReadWriteMsg , KT_R }, // 0x73AC + { CRC_READGOTOMSGNO , KK_ReadGotoMsgno , KT_R }, // 0x73F7 + { CRC_READCHANGEUSERNAME , KK_ReadChangeUsername , KT_R }, // 0x7438 + { CRC_READSTEALTAGLINE , KK_ReadStealTagline , KT_R }, // 0x7480 + { CRC_EDITUNDEFINE , KK_EditUndefine , KT_E }, // 0x7873 + { CRC_LISTGOTOFIRST , KK_ListGotoFirst , KT_M }, // 0x7925 + { CRC_K_CEND , Key_C_End , 0 }, // 0x7B95 + { CRC_K_APGUP , Key_A_PgUp , 0 }, // 0x7E61 + { CRC_EDITQUITNOW , KK_EditQuitNow , KT_E }, // 0x80BA + { CRC_AREASHOWDEL , KK_AreaShowDel , KT_R }, // 0x80C4 + { CRC_LISTMARKINGOPTIONS , KK_ListMarkingOptions , KT_M }, // 0x8138 + { CRC_EDITZAPQUOTEBELOW , KK_EditZapQuoteBelow , KT_E }, // 0x814F + { CRC_EDITDUPLINE , KK_EditDupLine , KT_E }, // 0x816A + { CRC_EDITDELRTWORD , KK_EditDelRtWord , KT_E }, // 0x829A + { CRC_EDITMENU , KK_EditMenu , KT_E }, // 0x833E + { CRC_AREAUNDEFINE , KK_AreaUndefine , KT_A }, // 0x835B + { CRC_READGOTOREPLYNEXT , KK_ReadGotoReplyNext , KT_R }, // 0x844F + { CRC_EDITMACRO , KK_EditMacro , KT_E }, // 0x85CD + { CRC_K_ENTER , Key_Ent , 0 }, // 0x87BD + { CRC_EDITGOTOPLINE , KK_EditGoTopLine , KT_E }, // 0x87C2 + { CRC_EDITBLOCKPGDN , KK_EditBlockPgDn , KT_E }, // 0x895B + { CRC_EDITASKEXIT , KK_EditAskExit , KT_E }, // 0x89AF + { CRC_EDITBLOCKHOME , KK_EditBlockHome , KT_E }, // 0x8B82 + { CRC_READDELETEMSG , KK_ReadDeleteMsg , KT_R }, // 0x8BCE + { CRC_EDITTAB , KK_EditTab , KT_E }, // 0x8C26 + { CRC_K_KEY5 , Key_5 , 0 }, // 0x9062 + { CRC_EDITPASTE , KK_EditPaste , KT_E }, // 0x90C4 + { CRC_EDITGOBOTLINE , KK_EditGoBotLine , KT_E }, // 0x92DD + { CRC_EXTERNUTIL18 , KK_ExternUtil18 , KT_R }, // 0x94B0 + { CRC_EXTERNUTIL19 , KK_ExternUtil19 , KT_R }, // 0x94B1 + { CRC_READMAINMENU , KK_ReadMainMenu , KT_R }, // 0x94B3 + { CRC_EXTERNUTIL10 , KK_ExternUtil10 , KT_R }, // 0x94B8 + { CRC_EXTERNUTIL11 , KK_ExternUtil11 , KT_R }, // 0x94B9 + { CRC_EXTERNUTIL12 , KK_ExternUtil12 , KT_R }, // 0x94BA + { CRC_EXTERNUTIL13 , KK_ExternUtil13 , KT_R }, // 0x94BB + { CRC_EXTERNUTIL14 , KK_ExternUtil14 , KT_R }, // 0x94BC + { CRC_EXTERNUTIL15 , KK_ExternUtil15 , KT_R }, // 0x94BD + { CRC_EXTERNUTIL16 , KK_ExternUtil16 , KT_R }, // 0x94BE + { CRC_EXTERNUTIL17 , KK_ExternUtil17 , KT_R }, // 0x94BF + { CRC_EXTERNUTIL08 , KK_ExternUtil08 , KT_R }, // 0x95B0 + { CRC_EXTERNUTIL09 , KK_ExternUtil09 , KT_R }, // 0x95B1 + { CRC_EXTERNUTIL01 , KK_ExternUtil01 , KT_R }, // 0x95B9 + { CRC_EXTERNUTIL02 , KK_ExternUtil02 , KT_R }, // 0x95BA + { CRC_EXTERNUTIL03 , KK_ExternUtil03 , KT_R }, // 0x95BB + { CRC_EXTERNUTIL04 , KK_ExternUtil04 , KT_R }, // 0x95BC + { CRC_EXTERNUTIL05 , KK_ExternUtil05 , KT_R }, // 0x95BD + { CRC_EXTERNUTIL06 , KK_ExternUtil06 , KT_R }, // 0x95BE + { CRC_EXTERNUTIL07 , KK_ExternUtil07 , KT_R }, // 0x95BF + { CRC_AREABOARDNOS , KK_AreaBoardnos , KT_A }, // 0x96EA + { CRC_EXTERNUTIL20 , KK_ExternUtil20 , KT_R }, // 0x97B8 + { CRC_EXTERNUTIL21 , KK_ExternUtil21 , KT_R }, // 0x97B9 + { CRC_EXTERNUTIL22 , KK_ExternUtil22 , KT_R }, // 0x97BA + { CRC_EXTERNUTIL23 , KK_ExternUtil23 , KT_R }, // 0x97BB + { CRC_EXTERNUTIL24 , KK_ExternUtil24 , KT_R }, // 0x97BC + { CRC_K_INS , Key_Ins , 0 }, // 0x97BE + { CRC_READTHREADTREE , KK_ReadThreadtree , KT_R }, // 0x9827 + { CRC_EDITBLOCKPGUP , KK_EditBlockPgUp , KT_E }, // 0x9842 + { CRC_K_ARIGHT , Key_A_Rgt , 0 }, // 0x9911 + { CRC_LISTMENU , KK_ListMenu , KT_M }, // 0x99AA + { CRC_K_AINS , Key_A_Ins , 0 }, // 0x9A72 + { CRC_EDITGOBOTMSG , KK_EditGoBotMsg , KT_E }, // 0x9B29 + { CRC_READDOSSHELL , KK_ReadDosShell , KT_R }, // 0x9C2B + { CRC_READGOTOLASTMSG , KK_ReadGotoLastMsg , KT_R }, // 0x9E72 + { CRC_NODEABORT , KK_NodeAbort , KT_N }, // 0xA08C + { CRC_READTOGGLEHIDDKLUD , KK_ReadToggleHiddKlud , KT_R }, // 0xA24F + { CRC_AREASELECT , KK_AreaSelect , KT_A }, // 0xA271 + { CRC_LISTMACRO , KK_ListMacro , KT_M }, // 0xA2B6 + { CRC_EDITDELCHAR , KK_EditDelChar , KT_E }, // 0xA3C7 + { CRC_AREAASKEXIT , KK_AreaAskExit , KT_A }, // 0xA3D1 + { CRC_READLOOKUPORIG , KK_ReadLookupOrig , KT_R }, // 0xA41C + { CRC_FILEMENU , KK_FileMenu , KT_F }, // 0xA4B2 + { CRC_READASKEXIT , KK_ReadAskExit , KT_R }, // 0xA500 + { CRC_AREAJUMPNEXTMATCH , KK_AreaJumpNextMatch , KT_A }, // 0xA556 + { CRC_READTOGGLEBOOKMARK , KK_ReadToggleBookMark , KT_R }, // 0xA7E2 + { CRC_EDITSOUNDKILL , KK_EditSoundkill , KT_E }, // 0xA9A7 + { CRC_AREAQUITNOW , KK_AreaQuitNow , KT_A }, // 0xAAC4 + { CRC_READNEWAREA , KK_ReadNewArea , KT_R }, // 0xAB5E + { CRC_AREAMENU , KK_AreaMenu , KT_A }, // 0xABE1 + { CRC_READQUITNOW , KK_ReadQuitNow , KT_R }, // 0xAC15 + { CRC_EDITDELLINE , KK_EditDelLine , KT_E }, // 0xACCF +#if not defined(__UNIX__) or defined(__USE_NCURSES__) + { CRC_K_SPGDN , Key_S_PgDn , 0 }, // 0xAD44 +#endif + { CRC_READSOUNDKILL , KK_ReadSoundkill , KT_R }, // 0xAE29 + { CRC_LISTUNDEFINE , KK_ListUndefine , KT_M }, // 0xAF86 +#if not defined(__UNIX__) or defined(__USE_NCURSES__) + { CRC_K_SHOME , Key_S_Home , 0 }, // 0xAF9D +#endif + { CRC_READTOGGLEQUOTE , KK_ReadToggleQuote , KT_R }, // 0xB293 + { CRC_EDITUNDO , KK_EditUndo , KT_E }, // 0xB295 + { CRC_FILETOGGLEMARK , KK_FileToggleMark , KT_F }, // 0xB431 + { CRC_FILEGOTOPREV , KK_FileGotoPrev , KT_F }, // 0xB644 + { CRC_EDITLOOKUPCURSOR , KK_EditLookupCursor , KT_E }, // 0xB7CC + { CRC_NODEGOTOPREV , KK_NodeGotoPrev , KT_N }, // 0xB85D + { CRC_AREADROPMSGMARKS , KK_AreaDropMsgMarks , KT_A }, // 0xB90C + { CRC_K_CINS , Key_C_Ins , 0 }, // 0xBA0E + { CRC_READGOTONEXTUNREAD , KK_ReadGotoNextUnread , KT_R }, // 0xBA34 +#if not defined(__UNIX__) or defined(__USE_NCURSES__) + { CRC_K_SPGUP , Key_S_PgUp , 0 }, // 0xBC5A +#endif + { CRC_FILEABORT , KK_FileAbort , KT_F }, // 0xBCED + { CRC_READCHANGETAGLINE , KK_ReadChangeTagline , KT_R }, // 0xBDD2 + { CRC_READQUOTEMSG , KK_ReadQuoteMsg , KT_R }, // 0xBE00 + { CRC_READCOPYMOVEFORWARD , KK_ReadCopyMoveForward , KT_R }, // 0xBFAF + { CRC_READTOGGLEROT13 , KK_ReadToggleROT13 , KT_R }, // 0xC157 + { CRC_EDITTOGGLECASE , KK_EditToggleCase , KT_E }, // 0xC282 + { CRC_FILEGOTOLAST , KK_FileGotoLast , KT_F }, // 0xC40A +#if not defined(__UNIX__) or defined(__USE_NCURSES__) + { CRC_K_SINS , Key_S_Ins , 0 }, // 0xC40B +#endif + { CRC_AREASCANPM , KK_AreaScanPM , KT_A }, // 0xC4FF + { CRC_READMSGEND , KK_ReadMsgEnd , KT_R }, // 0xC5AD + { CRC_AREATOGGLE , KK_AreaToggle , KT_A }, // 0xC734 +#if not defined(__UNIX__) or defined(__USE_NCURSES__) + { CRC_K_SLEFT , Key_S_Lft , 0 }, // 0xC902 +#endif + { CRC_NODEGOTOLAST , KK_NodeGotoLast , KT_N }, // 0xCA13 + { CRC_FILEGOTOFIRST , KK_FileGotoFirst , KT_F }, // 0xCAD5 + { CRC_LISTTOGGLEBOOKMARK , KK_ListToggleBookMark , KT_M }, // 0xCFA0 + { CRC_READTOGGLEMARKREAD , KK_ReadToggleMarkRead , KT_R }, // 0xCFAE + { CRC_LISTQUITNOW , KK_ListQuitNow , KT_M }, // 0xD037 + { CRC_FILEMARKALL , KK_FileMarkAll , KT_F }, // 0xD115 + { CRC_AREAWRITEGOLDLAST , KK_AreaWriteGoldlast , KT_A }, // 0xD353 + { CRC_LISTTOGGLEMARK , KK_ListToggleMark , KT_M }, // 0xD389 + { CRC_EDITTOUPPER , KK_EditToUpper , KT_E }, // 0xD3DD + { CRC_FILEASKEXIT , KK_FileAskExit , KT_F }, // 0xD40C + { CRC_EDITBLOCKDOWN , KK_EditBlockDown , KT_E }, // 0xD4E4 + { CRC_READMESSAGELIST , KK_ReadMessageList , KT_R }, // 0xD5D8 + { CRC_EDITGOUP , KK_EditGoUp , KT_E }, // 0xD6BA + { CRC_EDITDOSSHELL , KK_EditDosShell , KT_E }, // 0xD6C5 + { CRC_EDITTOGGLEINSERT , KK_EditToggleInsert , KT_E }, // 0xD732 + { CRC_EDITKILLQUOTES , KK_EditKillQuotes , KT_E }, // 0xD821 + { CRC_FILESELECT , KK_FileSelect , KT_F }, // 0xD8D9 + { CRC_READDECREASEMARGIN , KK_ReadDecreaseMargin , KT_R }, // 0xD8EA + { CRC_LISTASKEXIT , KK_ListAskExit , KT_M }, // 0xD922 + { CRC_AREACATCHUP , KK_AreaCatchUp , KT_A }, // 0xDA5C + { CRC_READGOTOREPLYPREV , KK_ReadGotoReplyPrev , KT_R }, // 0xDBE7 + { CRC_EDITANCHOR , KK_EditAnchor , KT_E }, // 0xDC07 + { CRC_FILEQUITNOW , KK_FileQuitNow , KT_F }, // 0xDD19 + { CRC_AREAINFO , KK_AreaInfo , KT_A }, // 0xDE54 + { CRC_EDITMAINMENU , KK_EditMainMenu , KT_E }, // 0xDE5D + { CRC_AREASOUNDKILL , KK_AreaSoundkill , KT_A }, // 0xDFD3 + { CRC_EDITBLOCKUP , KK_EditBlockUp , KT_E }, // 0xE004 + { CRC_EDITGOBEGLINE , KK_EditGoBegLine , KT_E }, // 0xE045 + { CRC_READGOTONEXTMSG , KK_ReadGotoNextMsg , KT_R }, // 0xE0F1 + { CRC_EDITSPELLCHECK , KK_EditSpellCheck , KT_E }, // 0xE167 + { CRC_NODEMENU , KK_NodeMenu , KT_N }, // 0xE1B6 + { CRC_AREASCAN , KK_AreaScan , KT_A }, // 0xE440 + { CRC_EDITGOWORDLEFT , KK_EditGoWordLeft , KT_E }, // 0xE48C + { CRC_READMOVECOMMENTMSG , KK_ReadMoveCommentMsg , KT_R }, // 0xE4E7 + { CRC_READGOTOREPLY1ST , KK_ReadGotoReply1st , KT_R }, // 0xE54F + { CRC_READTOGGLEHEXDUMP , KK_ReadToggleHexdump , KT_R }, // 0xE6D5 + { CRC_NODEQUITNOW , KK_NodeQuitNow , KT_N }, // 0xE780 + { CRC_NODEGOTONEXT , KK_NodeGotoNext , KT_N }, // 0xE7F5 + { CRC_READMAKEUSERLIST , KK_ReadMakeUserlist , KT_R }, // 0xE8C6 + { CRC_EDITCLEARPASTEBUF , KK_EditClearPasteBuf , KT_E }, // 0xE8E4 + { CRC_K_AENTER , Key_A_Ent , 0 }, // 0xE921 + { CRC_READMARKINGOPTIONS , KK_ReadMarkingOptions , KT_R }, // 0xE97A + { CRC_FILEGOTONEXT , KK_FileGotoNext , KT_F }, // 0xE9EC + { CRC_EDITBLOCKLEFT , KK_EditBlockLeft , KT_E }, // 0xED1D + { CRC_K_CUP , Key_C_Up , 0 }, // 0xEE6B + { CRC_NODEASKEXIT , KK_NodeAskExit , KT_N }, // 0xEE95 + { CRC_READGOTOPREVAREA , KK_ReadGotoPrevArea , KT_R }, // 0xEECB + { CRC_READFINDALL , KK_ReadFindAll , KT_R }, // 0xEF19 + { CRC_NODEDOSSHELL , KK_NodeDosShell , KT_N }, // 0xF084 +#if not defined(__UNIX__) or defined(__USE_NCURSES__) + { CRC_K_SDOWN , Key_S_Dwn , 0 }, // 0xF0FB +#endif + { CRC_READCHANGEXLATIMPORT , KK_ReadChangeXlatImport , KT_R }, // 0xF169 + { CRC_READTOGGLESTYLES , KK_ReadToggleStyles , KT_R }, // 0xF47E + { CRC_EDITBLOCKEND , KK_EditBlockEnd , KT_E }, // 0xF55B + { CRC_EDITTABREVERSE , KK_EditTabReverse , KT_E }, // 0xF5B6 + { CRC_READUSERBASE , KK_ReadUserbase , KT_R }, // 0xF736 + { CRC_K_RIGHT , Key_Rgt , 0 }, // 0xF78D + { CRC_EDITIMPORTQUOTEBUF , KK_EditImportQuotebuf , KT_E }, // 0xF797 + { CRC_READMACRO , KK_ReadMacro , KT_R }, // 0xF7D8 + { CRC_NODEMAINMENU , KK_NodeMainMenu , KT_N }, // 0xF81C + { CRC_FILEMARK , KK_FileMark , KT_F }, // 0xF828 + { CRC_EDITCLEARDELETEBUF , KK_EditClearDeleteBuf , KT_E }, // 0xF8DE + { CRC_READCHANGEMSG , KK_ReadChangeMsg , KT_R }, // 0xF99F + { CRC_K_ABSPACE , Key_A_BS , 0 }, // 0xF9D7 + { CRC_EDITCUT , KK_EditCut , KT_E }, // 0xFAE6 + { CRC_K_CF9 , Key_C_F9 , 0 }, // 0xFD02 + { CRC_K_CF8 , Key_C_F8 , 0 }, // 0xFD03 + { CRC_K_CF3 , Key_C_F3 , 0 }, // 0xFD08 + { CRC_K_CF2 , Key_C_F2 , 0 }, // 0xFD09 + { CRC_K_CF1 , Key_C_F1 , 0 }, // 0xFD0A + { CRC_K_CF7 , Key_C_F7 , 0 }, // 0xFD0C + { CRC_K_CF6 , Key_C_F6 , 0 }, // 0xFD0D + { CRC_K_CF5 , Key_C_F5 , 0 }, // 0xFD0E + { CRC_K_CF4 , Key_C_F4 , 0 }, // 0xFD0F + { CRC_READCHANGEORIGIN , KK_ReadChangeOrigin , KT_R }, // 0xFD2C + { CRC_FILEDOSSHELL , KK_FileDosShell , KT_F }, // 0xFE9D + { CRC_EDITLOOKUPDEST , KK_EditLookupDest , KT_E }, // 0xFEC4 + { CRC_AREAMACRO , KK_AreaMacro , KT_A }, // 0xFFA7 +}; + + +// ------------------------------------------------------------------ + +static gkey SwitchKeyDefs(word crc, int* type) { + + uint left,right,middle; + word cur; + + *type = 0; + left = 0; + right = (sizeof(globalkeys)/sizeof(tglobalkey))-1; + + if((crc < globalkeys[left].crc_token) or (crc > globalkeys[right].crc_token)) + return 0; + + do { + middle = (left + right)/2; + + cur = globalkeys[middle].crc_token; + + if(crc < cur) + right = middle - 1; + else if(crc > cur) + left = middle + 1; + else { + *type = globalkeys[middle].keytype; + return globalkeys[middle].keyval; + } + + } while(left <= right); + + return 0; +} + + +// ------------------------------------------------------------------ + +void KeyCmdAdd(gkey keycmd, gkey keyval, int keytype) { + + if(keyval <= 0xFF) + keyval |= (gkey)(scancode(keyval) << 8); + + list::iterator tmp = CFG->cmdkey.begin(); + if(CFG->switches.get(keybdefaults)) { + while(tmp != CFG->cmdkey.end()) { + if(tmp->type == keytype) { + if(tmp->key == keyval) { + tmp->cmd = keycmd; + return; + } + } + tmp++; + } + } + + CmdKey tmp2; + tmp2.key = keyval; + tmp2.cmd = keycmd; + tmp2.type = keytype; + CFG->cmdkey.push_back(tmp2); +} + + +// ------------------------------------------------------------------ + +void RunMacro(Macro* m) { + + gkey* mac = m->buf; + while(*mac) { + kbput(*mac); + mac++; + } +} + + +// ------------------------------------------------------------------ + +static void PlayMacro() { + + RunMacro(&CFG->macro[0xFFFF-gkbd.curronkey->pass]); +} + + +// ------------------------------------------------------------------ + +static void SetKeybDefaults() { + + // Setup default keyset + CmdKey* tmp = DefaultKeyset; + int keys = (sizeof(DefaultKeyset) / sizeof(CmdKey)) - 1; + int k = 0; + while(k < keys) { + if(tmp->key < 0xFF) + tmp->key = (gkey)tolower(tmp->key); + KeyCmdAdd(tmp->cmd, tmp->key, tmp->type); + tmp++; + k++; + } +} + + +// ------------------------------------------------------------------ + +bool CmdKeyCmp(CmdKey a, CmdKey b) { + + int cmp = CmpV(a.type, b.type); + if(cmp != 0) + return (cmp < 0); + return (CmpV(a.key, b.key) < 0); +} + + +// ------------------------------------------------------------------ + +int ReadKeysCfg(int force) { + + byte ch; + gkey* mac; + FILE *ifp; + char* ptr; + char* ptr2; + int keytype; + int n; + char buf[1024]; + gkey keyval=0, keycmd; + uint line=0; + + const char* cfg = AddPath(CFG->goldpath, CFG->keyscfg); + ifp = fsopen(cfg, "rt", CFG->sharemode); + if(ifp) { + + const char* cfgname = strrchr(cfg, '\\'); + cfgname = cfgname ? cfgname+1 : cfg; + + if(not quiet) + cout << "* Reading " << cfg << endl; + + CFG->macro.clear(); + CFG->cmdkey.clear(); + if(CFG->switches.get(keybdefaults)) + SetKeybDefaults(); + + while(fgets(buf, sizeof(buf), ifp)) { + line++; + ptr = strskip_wht(buf); + if(*ptr == ';' or strblank(ptr)) + continue; + ptr2 = ptr; + ptr = strskip_txt(ptr); + *ptr++ = NUL; + keycmd = SwitchKeyDefs(strCrc16(strupr(ptr2)), &keytype); + if(keycmd) { + if(keytype) { + cout << "* " << cfgname << ": Invalid key \"" << ptr2 << "\" in line " << line << "." << endl; + SayBibi(); + cfgerrors++; + continue; + } + keyval = keycmd; + } + else { // Either straight Key or $Key + if(*ptr2 == '$') { + uint _keyval = 0; + sscanf(ptr2+1, "%4x", &_keyval); + keyval = (gkey)_keyval; + } + else if(strlen(ptr2) == 1) + keyval = (gkey)tolower(*ptr2); // Always convert to lowercase internally + else { + cout << "* " << cfgname << ": Invalid key \"" << ptr2 << "\" in line " << line << "." << endl; + SayBibi(); + cfgerrors++; + continue; + } + } + ptr = strskip_wht(ptr); + ptr2 = ptr; + ptr = strskip_txt(ptr); + *ptr++ = 0; + keycmd = SwitchKeyDefs(strCrc16(strupr(ptr2)), &keytype); + if(keycmd) { + if((keycmd >= KK_Macro) and (keycmd <= KK_ReadMacro)) { + Macro tmp2; + memset(&tmp2, 0, sizeof(Macro)); + n = 0; + ptr = strskip_wht(ptr); + while(*ptr) { + if(*ptr == '\"') { // Start of literal string + ptr++; + while(*ptr != '\"' and n < 79) { + ch = *ptr++; + tmp2.buf[n++] = (gkey)(ch | (scancode(ch) << 8)); + } + *ptr++ = NUL; + } + else { + ptr2 = ptr; + ptr = strskip_txt(ptr); + *ptr++ = NUL; + int tmpkt; + keycmd = SwitchKeyDefs(strCrc16(strupr(ptr2)), &tmpkt); + if(keycmd) { + if(n < 79) + tmp2.buf[n++] = (gkey)keycmd; + } + else { + cout << "* " << cfgname << ": Invalid key \"" << ptr2 << "\" in line " << line << "." << endl; + SayBibi(); + cfgerrors++; + continue; + } + } + ptr = strskip_wht(ptr); + } + if(keyval <= 0xFF) + keyval |= (gkey)(scancode(keyval) << 8); + tmp2.key = (gkey)keyval; + tmp2.type = keytype; + CFG->macro.push_back(tmp2); + + // delete overlayed (non-macro) key definition + list::iterator tmp = CFG->cmdkey.begin(); + while(tmp != CFG->cmdkey.end()) { + if(tmp->type == keytype) { + if(tmp->key == keyval) { + // delete it by setting type to an invalid value + tmp->type = 0xFF; + break; + } + } + tmp++; + } + } + else if(keytype) + KeyCmdAdd(keycmd, keyval, keytype); + else { + cout << "* " << cfgname << ": Invalid key \"" << ptr2 << "\" in line " << line << "." << endl; + SayBibi(); + cfgerrors++; + continue; + } + } + else { + cout << "* " << cfgname << ": Invalid key \"" << ptr2 << "\" in line " << line << "." << endl; + SayBibi(); + cfgerrors++; + continue; + } + } + fclose(ifp); + } + + // Setup default keyset when no keys are defined + if(CFG->cmdkey.empty()) + SetKeybDefaults(); + + // Prepare keyboard and macro tables for binary searching + CFG->cmdkey.sort(CmdKeyCmp); + + // Count keys + list::iterator ck = CFG->cmdkey.begin(); + while(ck != CFG->cmdkey.end()) { + switch(ck->type) { + case KT_A: AreaKeys++; if(AreaKeys == 1) AreaKey = ck; break; + case KT_E: EditKeys++; if(EditKeys == 1) EditKey = ck; break; + case KT_F: FileKeys++; if(FileKeys == 1) FileKey = ck; break; + case KT_G: break; + case KT_M: ListKeys++; if(ListKeys == 1) ListKey = ck; break; + case KT_N: NodeKeys++; if(NodeKeys == 1) NodeKey = ck; break; + case KT_R: ReadKeys++; if(ReadKeys == 1) ReadKey = ck; break; + } + ck++; + } + + // Assign global macros + vector::iterator k; + for(k=CFG->macro.begin(), n=0; k != CFG->macro.end(); k++, n++) { + if(k->type == 0) { + if((k->key == KK_Auto) or (k->key == 0x0300)) { + // Start automacro + mac = k->buf; + while(*mac) { + kbput(*mac); + mac++; + } + } + else { + setonkey(k->key, PlayMacro, (gkey)(0xFFFF-n)); + } + } + } + + return true; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gckeys.h b/golded3/gckeys.h new file mode 100644 index 0000000..9f9a06b --- /dev/null +++ b/golded3/gckeys.h @@ -0,0 +1,486 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// CRC16 value for keyboard definitions. +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ +// CRC16 value for keyboard definitions + +const word CRC_AREAABORT = 0x1E02; +const word CRC_AREAASKEXIT = 0xA3D1; +const word CRC_AREABOARDNOS = 0x96EA; +const word CRC_AREACATCHUP = 0xDA5C; +const word CRC_AREADOSSHELL = 0x2DED; +const word CRC_AREADROPMSGMARKS = 0xB90C; +const word CRC_AREAGOTOFIRST = 0x41CB; +const word CRC_AREAGOTOLAST = 0x177A; +const word CRC_AREAGOTONEXT = 0x3A9C; +const word CRC_AREAGOTOPREV = 0x6534; +const word CRC_AREAHEAT = 0x5B15; +const word CRC_AREAINFO = 0xDE54; +const word CRC_AREAJUMP = 0x2342; +const word CRC_AREAJUMPNEXTMATCH = 0xA556; +const word CRC_AREAMACRO = 0xFFA7; +const word CRC_AREAMENU = 0xABE1; +const word CRC_AREAQUITNOW = 0xAAC4; +const word CRC_AREASCAN = 0xE440; +const word CRC_AREASCANPM = 0xC4FF; +const word CRC_AREASELECT = 0xA271; +const word CRC_AREASELECTMARKS = 0x0AC3; +const word CRC_AREASOUNDKILL = 0xDFD3; +const word CRC_AREATOGGLE = 0xC734; +const word CRC_AREATOUCHNETSCAN = 0x58C1; +const word CRC_AREAUNDEFINE = 0x835B; +const word CRC_AREAWRITEGOLDLAST = 0xD353; +const word CRC_AREAZAP = 0x5125; +const word CRC_AREASHOWDEL = 0x80C4; + +const word CRC_EDITABORT = 0x6468; +const word CRC_EDITANCHOR = 0xDC07; +const word CRC_EDITASKEXIT = 0x89AF; +const word CRC_EDITBLOCKDOWN = 0xD4E4; +const word CRC_EDITBLOCKEND = 0xF55B; +const word CRC_EDITBLOCKHOME = 0x8B82; +const word CRC_EDITBLOCKLEFT = 0xED1D; +const word CRC_EDITBLOCKPGUP = 0x9845; +const word CRC_EDITBLOCKPGDN = 0x895B; +const word CRC_EDITBLOCKRIGHT = 0x20F9; +const word CRC_EDITBLOCKUP = 0xE004; +const word CRC_EDITCLEARDELETEBUF = 0xF8DE; +const word CRC_EDITCLEARPASTEBUF = 0xE8E4; +const word CRC_EDITCOPY = 0x1F77; +const word CRC_EDITCOPYABOVECHAR = 0x380C; +const word CRC_EDITCUT = 0xFAE6; +const word CRC_EDITDELCHAR = 0xA3C7; +const word CRC_EDITDELETE = 0x4A37; +const word CRC_EDITDELETEEOL = 0x1143; +const word CRC_EDITDELLEFT = 0x6552; +const word CRC_EDITDELLINE = 0xACCF; +const word CRC_EDITDELLTWORD = 0x3B67; +const word CRC_EDITDELRTWORD = 0x829A; +const word CRC_EDITDOSSHELL = 0xD6C5; +const word CRC_EDITDUPLINE = 0x816A; +const word CRC_EDITEXITMSG = 0x1813; +const word CRC_EDITEXPORTTEXT = 0x5AED; +const word CRC_EDITGOBEGLINE = 0xE045; +const word CRC_EDITGOBOTLINE = 0x92DD; +const word CRC_EDITGOBOTMSG = 0x9B29; +const word CRC_EDITGODOWN = 0x3DC2; +const word CRC_EDITGOEOL = 0x1CC6; +const word CRC_EDITGOLEFT = 0x043B; +const word CRC_EDITGOPGDN = 0x607D; +const word CRC_EDITGOPGUP = 0x7163; +const word CRC_EDITGORIGHT = 0x6AFE; +const word CRC_EDITGOTOPLINE = 0x87C2; +const word CRC_EDITGOTOPMSG = 0x6BD3; +const word CRC_EDITGOUP = 0xD6BA; +const word CRC_EDITGOWORDLEFT = 0xE48C; +const word CRC_EDITGOWORDRIGHT = 0x20D0; +const word CRC_EDITHEADER = 0x726F; +const word CRC_EDITIMPORTQUOTEBUF = 0xF797; +const word CRC_EDITIMPORTTEXT = 0x0586; +const word CRC_EDITKILLQUOTES = 0xD821; +const word CRC_EDITLOADFILE = 0x0931; +const word CRC_EDITLOOKUPCURSOR = 0xB7CC; +const word CRC_EDITLOOKUPDEST = 0xFEC4; +const word CRC_EDITLOOKUPORIG = 0x5AFB; +const word CRC_EDITMACRO = 0x85CD; +const word CRC_EDITMAINMENU = 0xDE5D; +const word CRC_EDITMENU = 0x833E; +const word CRC_EDITNEWLINE = 0x59F3; +const word CRC_EDITPASTE = 0x90C4; +const word CRC_EDITQUITNOW = 0x80BA; +const word CRC_EDITREFLOW = 0x13F9; +const word CRC_EDITSAVEFILE = 0x64A4; +const word CRC_EDITSAVEMSG = 0x660C; +const word CRC_EDITSOUNDKILL = 0xA9A7; +const word CRC_EDITSPELLCHECK = 0xE167; +const word CRC_EDITTAB = 0x8C26; +const word CRC_EDITTABREVERSE = 0xF5B6; +const word CRC_EDITTOGGLECASE = 0xC282; +const word CRC_EDITTOGGLEINSERT = 0xD732; +const word CRC_EDITTOLOWER = 0x6D85; +const word CRC_EDITTOUPPER = 0xD3DD; +const word CRC_EDITUNDEFINE = 0x7873; +const word CRC_EDITUNDELETE = 0x4C34; +const word CRC_EDITUNDO = 0xB295; +const word CRC_EDITZAPQUOTEBELOW = 0x814F; + +const word CRC_FILEABORT = 0xBCED; +const word CRC_FILEASKEXIT = 0xD40C; +const word CRC_FILEDOSSHELL = 0xFE9D; +const word CRC_FILEGOTOFIRST = 0xCAD5; +const word CRC_FILEGOTOLAST = 0xC40A; +const word CRC_FILEGOTONEXT = 0xE9EC; +const word CRC_FILEGOTOPREV = 0xB644; +const word CRC_FILEMACRO = 0x5D48; +const word CRC_FILEMARK = 0xF828; +const word CRC_FILEMARKALL = 0xD115; +const word CRC_FILEMENU = 0xA4B2; +const word CRC_FILEQUITNOW = 0xDD19; +const word CRC_FILESELECT = 0xD8D9; +const word CRC_FILETOGGLEMARK = 0xB431; +const word CRC_FILEUNDEFINE = 0x502B; +const word CRC_FILEUNMARK = 0x6D1B; +const word CRC_FILEUNMARKALL = 0x121A; + +const word CRC_LISTABORT = 0x4313; +const word CRC_LISTASKEXIT = 0xD922; +const word CRC_LISTDOSSHELL = 0x0130; +const word CRC_LISTGOTOBOOKMARK = 0x0F08; +const word CRC_LISTGOTOFIRST = 0x7925; +const word CRC_LISTGOTOLAST = 0x3BA7; +const word CRC_LISTGOTONEXT = 0x1641; +const word CRC_LISTGOTOPREV = 0x49E9; +const word CRC_LISTMACRO = 0xA2B6; +const word CRC_LISTMARKINGOPTIONS = 0x8138; +const word CRC_LISTMENU = 0x99AA; +const word CRC_LISTQUITNOW = 0xD037; +const word CRC_LISTSELECT = 0x3829; +const word CRC_LISTTOGGLEBOOKMARK = 0xCFA0; +const word CRC_LISTTOGGLEDATE = 0x6F1F; +const word CRC_LISTTOGGLEMARK = 0xD389; +const word CRC_LISTTOGGLEWIDESUBJ = 0x3C76; +const word CRC_LISTUNDEFINE = 0xAF86; + +const word CRC_EXTERNUTIL01 = 0x95B9; +const word CRC_EXTERNUTIL02 = 0x95BA; +const word CRC_EXTERNUTIL03 = 0x95BB; +const word CRC_EXTERNUTIL04 = 0x95BC; +const word CRC_EXTERNUTIL05 = 0x95BD; +const word CRC_EXTERNUTIL06 = 0x95BE; +const word CRC_EXTERNUTIL07 = 0x95BF; +const word CRC_EXTERNUTIL08 = 0x95B0; +const word CRC_EXTERNUTIL09 = 0x95B1; +const word CRC_EXTERNUTIL10 = 0x94B8; +const word CRC_EXTERNUTIL11 = 0x94B9; +const word CRC_EXTERNUTIL12 = 0x94BA; +const word CRC_EXTERNUTIL13 = 0x94BB; +const word CRC_EXTERNUTIL14 = 0x94BC; +const word CRC_EXTERNUTIL15 = 0x94BD; +const word CRC_EXTERNUTIL16 = 0x94BE; +const word CRC_EXTERNUTIL17 = 0x94BF; +const word CRC_EXTERNUTIL18 = 0x94B0; +const word CRC_EXTERNUTIL19 = 0x94B1; +const word CRC_EXTERNUTIL20 = 0x97B8; +const word CRC_EXTERNUTIL21 = 0x97B9; +const word CRC_EXTERNUTIL22 = 0x97BA; +const word CRC_EXTERNUTIL23 = 0x97BB; +const word CRC_EXTERNUTIL24 = 0x97BC; + +const word CRC_NODEABORT = 0xA08C; +const word CRC_NODEASKEXIT = 0xEE95; +const word CRC_NODEDOSSHELL = 0xF084; +const word CRC_NODEGOTOFIRST = 0x321B; +const word CRC_NODEGOTOLAST = 0xCA13; +const word CRC_NODEGOTONEXT = 0xE7F5; +const word CRC_NODEGOTOPREV = 0xB85D; +const word CRC_NODEMACRO = 0x4129; +const word CRC_NODEMAINMENU = 0xF81C; +const word CRC_NODEMENU = 0xE1B6; +const word CRC_NODEQUITNOW = 0xE780; +const word CRC_NODESELECT = 0x6A64; +const word CRC_NODEUNDEFINE = 0x5E32; + +const word CRC_READADDRESSBOOKADD = 0x00FA; +const word CRC_READASKEXIT = 0xA500; +const word CRC_READCHANGEAKA = 0x2015; +const word CRC_READCHANGEATTRS = 0x47F8; +const word CRC_READCHANGECHARSIN = 0x0B87; +const word CRC_READCHANGECHARSOUT = 0x4DF9; +const word CRC_READCHANGEMSG = 0xF99F; +const word CRC_READCHANGEORIGIN = 0xFD2C; +const word CRC_READCHANGETAGLINE = 0xBDD2; +const word CRC_READCHANGETEMPLATE = 0x6C86; +const word CRC_READCHANGEUSERNAME = 0x7438; +const word CRC_READCHANGEXLATIMPORT = 0xF169; +const word CRC_READCOMMENTMSG = 0x5E89; +const word CRC_READCOPYMOVEFORWARD = 0xBFAF; +const word CRC_READDECREASEMARGIN = 0xD8EA; +const word CRC_READDELETEMSG = 0x8BCE; +const word CRC_READDOSSHELL = 0x9C2B; +const word CRC_READEXTERNUTILMENU = 0x2000; +const word CRC_READFIDORENUMBER = 0x1E7C; +const word CRC_READFILEREQUEST = 0x0A07; +const word CRC_READFINDALL = 0xEF19; +const word CRC_READFINDHEADER = 0x6343; +const word CRC_READGOTOBOOKMARK = 0x4383; +const word CRC_READGOTOFIRSTMSG = 0x392F; +const word CRC_READGOTOLASTMSG = 0x9E72; +const word CRC_READGOTOMSGNO = 0x73F7; +const word CRC_READGOTONEXTAREA = 0x5B23; +const word CRC_READGOTONEXTMSG = 0xE0F1; +const word CRC_READGOTONEXTUNREAD = 0xBA34; +const word CRC_READGOTOPREVAREA = 0xEECB; +const word CRC_READGOTOPREVMSG = 0x06D9; +const word CRC_READGOTOPREVUNREAD = 0x27EA; +const word CRC_READGOTOREPLIES = 0x1A6B; +const word CRC_READGOTOREPLY1ST = 0xE54F; +const word CRC_READGOTOREPLYNEXT = 0x844F; +const word CRC_READGOTOREPLYPREV = 0xDBE7; +const word CRC_READINCREASEMARGIN = 0x1797; +const word CRC_READLOOKUPDEST = 0x0023; +const word CRC_READLOOKUPORIG = 0xA41C; +const word CRC_READMACRO = 0xF7D8; +const word CRC_READMAINMENU = 0x94B3; +const word CRC_READMAKEUSERLIST = 0xE8C6; +const word CRC_READMAKEPATHREPORT = 0x4AA6; +const word CRC_READMARKINGOPTIONS = 0xE97A; +const word CRC_READMENU = 0x3D0A; +const word CRC_READMESSAGELIST = 0xD5D8; +const word CRC_READMOVECOMMENTMSG = 0xE4E7; +const word CRC_READMOVEQUOTEMSG = 0x1B41; +const word CRC_READMSGCONTINUE = 0x4511; +const word CRC_READMSGEND = 0xC5AD; +const word CRC_READMSGHOME = 0x4BD1; +const word CRC_READMSGLINEDOWN = 0x5DB2; +const word CRC_READMSGLINEUP = 0x7238; +const word CRC_READMSGPGDN = 0x4908; +const word CRC_READMSGPGUP = 0x5816; +const word CRC_READNEWAREA = 0xAB5E; +const word CRC_READNEWMSG = 0x30CA; +const word CRC_READQUITNOW = 0xAC15; +const word CRC_READQUOTEBUF = 0x49EE; +const word CRC_READQUOTEMSG = 0xBE00; +const word CRC_READREPLYMSG = 0x172F; +const word CRC_READSEARCH = 0x48EF; +const word CRC_READSOUNDKILL = 0xAE29; +const word CRC_READSTEALTAGLINE = 0x7480; +const word CRC_READTHREADTREE = 0x9827; +const word CRC_READTOGGLEBOOKMARK = 0xA7E2; +const word CRC_READTOGGLEHEXDUMP = 0xE6D5; +const word CRC_READTOGGLEHIDDEN = 0x04CE; +const word CRC_READTOGGLEHIDDKLUD = 0xA24F; +const word CRC_READTOGGLESTYLES = 0xF47E; +const word CRC_READTOGGLEKLUDGE = 0x46AB; +const word CRC_READTOGGLEMARK = 0x1E64; +const word CRC_READTOGGLEMARKREAD = 0xCFAE; +const word CRC_READTOGGLEPAGEBAR = 0x18E4; +const word CRC_READTOGGLEQUOTE = 0xB293; +const word CRC_READTOGGLEREALMSGNO = 0x2A3B; +const word CRC_READTOGGLEROT13 = 0xC157; +const word CRC_READTOGGLETWITS = 0x5FD1; +const word CRC_READTOUCHNETSCAN = 0x4BF3; +const word CRC_READTOUCHSEMAPHORE = 0x6B1D; +const word CRC_READUNDEFINE = 0x329D; +const word CRC_READUSERBASE = 0xF736; +const word CRC_READUUDECODE = 0x4F0B; +const word CRC_READWRITEMSG = 0x73AC; + +const word CRC_K_F1 = 0x4631; +const word CRC_K_F2 = 0x4632; +const word CRC_K_F3 = 0x4633; +const word CRC_K_F4 = 0x4634; +const word CRC_K_F5 = 0x4635; +const word CRC_K_F6 = 0x4636; +const word CRC_K_F7 = 0x4637; +const word CRC_K_F8 = 0x4638; +const word CRC_K_F9 = 0x4639; +const word CRC_K_F10 = 0x1932; +const word CRC_K_F11 = 0x1933; +const word CRC_K_F12 = 0x1930; + +const word CRC_K_SF1 = 0x5230; +const word CRC_K_SF2 = 0x5233; +const word CRC_K_SF3 = 0x5232; +const word CRC_K_SF4 = 0x5235; +const word CRC_K_SF5 = 0x5234; +const word CRC_K_SF6 = 0x5237; +const word CRC_K_SF7 = 0x5236; +const word CRC_K_SF8 = 0x5239; +const word CRC_K_SF9 = 0x5238; +const word CRC_K_SF10 = 0x4A87; +const word CRC_K_SF11 = 0x4A86; +const word CRC_K_SF12 = 0x4A85; + +const word CRC_K_AF1 = 0x0EF5; +const word CRC_K_AF2 = 0x0EF6; +const word CRC_K_AF3 = 0x0EF7; +const word CRC_K_AF4 = 0x0EF0; +const word CRC_K_AF5 = 0x0EF1; +const word CRC_K_AF6 = 0x0EF2; +const word CRC_K_AF7 = 0x0EF3; +const word CRC_K_AF8 = 0x0EFC; +const word CRC_K_AF9 = 0x0EFD; +const word CRC_K_AF10 = 0x14FE; +const word CRC_K_AF11 = 0x14FF; +const word CRC_K_AF12 = 0x14FC; + +const word CRC_K_CF1 = 0xFD0A; +const word CRC_K_CF2 = 0xFD09; +const word CRC_K_CF3 = 0xFD08; +const word CRC_K_CF4 = 0xFD0F; +const word CRC_K_CF5 = 0xFD0E; +const word CRC_K_CF6 = 0xFD0D; +const word CRC_K_CF7 = 0xFD0C; +const word CRC_K_CF8 = 0xFD03; +const word CRC_K_CF9 = 0xFD02; +const word CRC_K_CF10 = 0x3482; +const word CRC_K_CF11 = 0x3483; +const word CRC_K_CF12 = 0x3480; + +const word CRC_K_A0 = 0x4030; +const word CRC_K_A1 = 0x4031; +const word CRC_K_A2 = 0x4032; +const word CRC_K_A3 = 0x4033; +const word CRC_K_A4 = 0x4034; +const word CRC_K_A5 = 0x4035; +const word CRC_K_A6 = 0x4036; +const word CRC_K_A7 = 0x4037; +const word CRC_K_A8 = 0x4038; +const word CRC_K_A9 = 0x4039; + +const word CRC_K_AA = 0x4041; +const word CRC_K_AB = 0x4042; +const word CRC_K_AC = 0x4043; +const word CRC_K_AD = 0x4044; +const word CRC_K_AE = 0x4045; +const word CRC_K_AF = 0x4046; +const word CRC_K_AG = 0x4047; +const word CRC_K_AH = 0x4048; +const word CRC_K_AI = 0x4049; +const word CRC_K_AJ = 0x404A; +const word CRC_K_AK = 0x404B; +const word CRC_K_AL = 0x404C; +const word CRC_K_AM = 0x404D; +const word CRC_K_AN = 0x404E; +const word CRC_K_AO = 0x404F; +const word CRC_K_AP = 0x4050; +const word CRC_K_AQ = 0x4051; +const word CRC_K_AR = 0x4052; +const word CRC_K_AS = 0x4053; +const word CRC_K_AT = 0x4054; +const word CRC_K_AU = 0x4055; +const word CRC_K_AV = 0x4056; +const word CRC_K_AW = 0x4057; +const word CRC_K_AX = 0x4058; +const word CRC_K_AY = 0x4059; +const word CRC_K_AZ = 0x405A; + +const word CRC_K_CA = 0x5E41; +const word CRC_K_CB = 0x5E42; +const word CRC_K_CC = 0x5E43; +const word CRC_K_CD = 0x5E44; +const word CRC_K_CE = 0x5E45; +const word CRC_K_CF = 0x5E46; +const word CRC_K_CG = 0x5E47; +const word CRC_K_CH = 0x5E48; +const word CRC_K_CI = 0x5E49; +const word CRC_K_CJ = 0x5E4A; +const word CRC_K_CK = 0x5E4B; +const word CRC_K_CL = 0x5E4C; +const word CRC_K_CM = 0x5E4D; +const word CRC_K_CN = 0x5E4E; +const word CRC_K_CO = 0x5E4F; +const word CRC_K_CP = 0x5E50; +const word CRC_K_CQ = 0x5E51; +const word CRC_K_CR = 0x5E52; +const word CRC_K_CS = 0x5E53; +const word CRC_K_CT = 0x5E54; +const word CRC_K_CU = 0x5E55; +const word CRC_K_CV = 0x5E56; +const word CRC_K_CW = 0x5E57; +const word CRC_K_CX = 0x5E58; +const word CRC_K_CY = 0x5E59; +const word CRC_K_CZ = 0x5E5A; +const word CRC_K_CMINUS = 0x5E2D; + +const word CRC_K_ESC = 0x4B22; + +const word CRC_K_TAB = 0x5B33; +const word CRC_K_STAB = 0x0886; +const word CRC_K_ATAB = 0x56FF; + +const word CRC_K_BSPACE = 0x0F07; +const word CRC_K_ABSPACE = 0xF9D7; +const word CRC_K_CBSPACE = 0x5A72; + +const word CRC_K_ENTER = 0x87BD; +const word CRC_K_AENTER = 0xE921; +const word CRC_K_CENTER = 0x50DC; + +const word CRC_K_INS = 0x97BE; +const word CRC_K_CINS = 0xBA0E; +const word CRC_K_AINS = 0x9A72; + +const word CRC_K_DEL = 0x4D0C; +const word CRC_K_CDEL = 0x60BC; +const word CRC_K_ADEL = 0x40C0; + +const word CRC_K_HOME = 0x700B; +const word CRC_K_CHOME = 0x35C4; +const word CRC_K_AHOME = 0x6DA6; + +const word CRC_K_END = 0x5625; +const word CRC_K_CEND = 0x7B95; +const word CRC_K_AEND = 0x5BE9; + +const word CRC_K_PGUP = 0x63CC; +const word CRC_K_CPGUP = 0x2603; +const word CRC_K_APGUP = 0x7E61; + +const word CRC_K_PGDN = 0x72D2; +const word CRC_K_CPGDN = 0x371D; +const word CRC_K_APGDN = 0x6F7F; + +const word CRC_K_LEFT = 0x1694; +const word CRC_K_CLEFT = 0x535B; +const word CRC_K_ALEFT = 0x0B39; + +const word CRC_K_RIGHT = 0xF78D; +const word CRC_K_CRIGHT = 0x20EC; +const word CRC_K_ARIGHT = 0x9911; + +const word CRC_K_UP = 0x5550; +const word CRC_K_CUP = 0xEE6B; +const word CRC_K_AUP = 0x1D94; + +const word CRC_K_DOWN = 0x2F6D; +const word CRC_K_CDOWN = 0x6AA2; +const word CRC_K_ADOWN = 0x32C0; + +const word CRC_K_CGMUL = 0x66CA; + +const word CRC_K_KEY5 = 0x9062; +const word CRC_K_SPACE = 0x1281; + +const word CRC_KK_MACRO = 0x4BE9; +const word CRC_KK_AUTO = 0x60E2; + +#if not defined(__UNIX__) or defined(__USE_NCURSES__) +const word CRC_K_SINS = 0xC40B; +const word CRC_K_SDEL = 0x1EB9; +const word CRC_K_SHOME = 0xAF9D; +const word CRC_K_SEND = 0x0590; +const word CRC_K_SPGUP = 0xBC5A; +const word CRC_K_SPGDN = 0xAD44; +const word CRC_K_SLEFT = 0xC902; +const word CRC_K_SRIGHT = 0x5B1F; +const word CRC_K_SUP = 0x4151; +const word CRC_K_SDOWN = 0xF0FB; +#endif + +// ------------------------------------------------------------------ + diff --git a/golded3/gclang.cpp b/golded3/gclang.cpp new file mode 100644 index 0000000..d3e2833 --- /dev/null +++ b/golded3/gclang.cpp @@ -0,0 +1,722 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Language compiler +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ +// Structure of language crc list + +struct LangCrc { + word crc; + char** langptr; + char* langdef; +}; + + +// ------------------------------------------------------------------ +// Language CRC16/Pointer/Default list + +static LangCrc LangCrcs[] = { + + { CRC_MS_SWSUN , NULL , "Sun" }, + { CRC_MS_SWMON , NULL , "Mon" }, + { CRC_MS_SWTUE , NULL , "Tue" }, + { CRC_MS_SWWED , NULL , "Wed" }, + { CRC_MS_SWTHU , NULL , "Thu" }, + { CRC_MS_SWFRI , NULL , "Fri" }, + { CRC_MS_SWSAT , NULL , "Sat" }, + + { CRC_MS_LWSUNDAY , NULL , "Sunday" }, + { CRC_MS_LWMONDAY , NULL , "Monday" }, + { CRC_MS_LWTUESDAY , NULL , "Tuesday" }, + { CRC_MS_LWWEDNESDAY , NULL , "Wednesday" }, + { CRC_MS_LWTHURSDAY , NULL , "Thursday" }, + { CRC_MS_LWFRIDAY , NULL , "Friday" }, + { CRC_MS_LWSATURDAY , NULL , "Saturday" }, + + { CRC_MS_SMJAN , NULL , "Jan" }, + { CRC_MS_SMFEB , NULL , "Feb" }, + { CRC_MS_SMMAR , NULL , "Mar" }, + { CRC_MS_SMAPR , NULL , "Apr" }, + { CRC_MS_SMMAY , NULL , "May" }, + { CRC_MS_SMJUN , NULL , "Jun" }, + { CRC_MS_SMJUL , NULL , "Jul" }, + { CRC_MS_SMAUG , NULL , "Aug" }, + { CRC_MS_SMSEP , NULL , "Sep" }, + { CRC_MS_SMOCT , NULL , "Oct" }, + { CRC_MS_SMNOV , NULL , "Nov" }, + { CRC_MS_SMDEC , NULL , "Dec" }, + + { CRC_MS_LMJANUARY , NULL , "January" }, + { CRC_MS_LMFEBRUARY , NULL , "February" }, + { CRC_MS_LMMARCH , NULL , "March" }, + { CRC_MS_LMAPRIL , NULL , "April" }, + { CRC_MS_LMMAY , NULL , "May" }, + { CRC_MS_LMJUNE , NULL , "June" }, + { CRC_MS_LMJULY , NULL , "July" }, + { CRC_MS_LMAUGUST , NULL , "August" }, + { CRC_MS_LMSEPTEMBER , NULL , "September" }, + { CRC_MS_LMOCTOBER , NULL , "October" }, + { CRC_MS_LMNOVEMBER , NULL , "November" }, + { CRC_MS_LMDECEMBER , NULL , "December" }, + + { CRC_ST_IMPORTFILE , NULL , "Import File" }, + { CRC_WT_IMPORTWHICHFILE , NULL , " Import which file? " }, + { CRC_WT_IMPORTPICK , NULL , " Import " }, + { CRC_WT_IMPORTTXT , NULL , " Import " }, + { CRC_MI_IMPORTTXTTEXT , NULL , "T File as Text " }, + { CRC_MI_IMPORTTXTQUOTE , NULL , "Q File as Quote " }, + { CRC_MI_IMPORTTXTUUE , NULL , "U Binary as UUE " }, + { CRC_MI_IMPORTTXTMIME , NULL , "M Binary as MIME " }, + { CRC_MI_IMPORTTXTCLIP , NULL , "C From Clipboard " }, + { CRC_MI_IMPORTTXTXLAT , NULL , "s Use Charset.. " }, + { CRC_MI_IMPORTTXTQUIT , NULL , "N Nothing / Quit " }, + { CRC_ST_IMPORTSTATUS , NULL , "Importing from %s" }, + { CRC_ST_EXPORTFILE , NULL , "Export File" }, + { CRC_WT_EXPORTWHATFILE , NULL , " Export to what file? " }, + { CRC_ST_EXPORTSTATUS , NULL , "Exporting to %s" }, + { CRC_ST_EDITSTATUS , NULL , "Edit %i,%i. %s" }, + { CRC_ST_SELECTFILES , NULL , "Select Files" }, + { CRC_WL_SELECTEDFILES , NULL , "Selected Files " }, + { CRC_WL_SELECTEDBYTES , NULL , " Bytes " }, + { CRC_WL_TOTALFILES , NULL , "Total Files " }, + { CRC_WL_TOTALBYTES , NULL , " Bytes " }, + { CRC_WL_SCANNINGDIRECTORY , NULL , " Scanning Directory " }, + { CRC_WL_NOFILESFOUND , NULL , " * NO FILES FOUND * " }, + { CRC_ST_FILESPRESSKEY , NULL , "Press any key to continue" }, + { CRC_WT_AREA , NULL , "Area" }, + { CRC_WT_DESCRIPTION , NULL , "Description" }, + { CRC_WT_MSGS , NULL , "Msgs" }, + { CRC_WT_LAST , NULL , "Last" }, + { CRC_WT_ECHOID , NULL , "EchoID" }, + { CRC_ST_UNREAD , NULL , "unread" }, + { CRC_WT_SCANAREAS , NULL , " Scan Areas " }, + { CRC_MI_SCANALL , NULL , "A Scan All " }, + { CRC_MI_SCANMARKED , NULL , "M Scan Marked " }, + { CRC_MI_SCANCURRENT , NULL , "C Scan Current " }, + { CRC_MI_SCANMATCHING , NULL , "t Scan Matching " }, + { CRC_MI_SCANUNSCANNED , NULL , "U Scan Unscanned " }, + { CRC_MI_NOSCAN , NULL , "N No Scan / ESC " }, + { CRC_WT_HEATAREAS , NULL , " Heat Areas " }, + { CRC_MI_HEATALL , NULL , "A Heat All " }, + { CRC_MI_HEATMARKED , NULL , "M Heat Marked " }, + { CRC_MI_HEATCURRENT , NULL , "C Heat Current " }, + { CRC_MI_NOHEAT , NULL , "N No Heat / ESC " }, + { CRC_WT_ZAPAREAS , NULL , " Zap Areas " }, + { CRC_MI_ZAPALL , NULL , "A Zap All " }, + { CRC_MI_ZAPMARKED , NULL , "M Zap Marked " }, + { CRC_MI_ZAPCURRENT , NULL , "C Zap Current " }, + { CRC_MI_NOZAP , NULL , "N No Zap / ESC " }, + { CRC_MS_DOS_SHELL , NULL , "GoldED Shell. Type EXIT To Return." }, + { CRC_IL_SCANNINGAREA , NULL , " Scanning Area:" }, + { CRC_IL_SEARCHINGFOR , NULL , " Searching for" }, + { CRC_ST_READINGMSG , NULL , "Reading Msg %u of %u" }, + { CRC_ER_OUTOFMEM , NULL , "Out of memory!" }, + { CRC_MS_HEXDUMPHEAD , NULL , "Hexdump of message header:" }, + { CRC_MS_HEXDUMPTEXT , NULL , "Hexdump of message text:" }, + { CRC_ST_RENUMBERING , NULL , "Renumbering" }, + { CRC_ST_LOCKED , NULL , " (locked)" }, + { CRC_ST_RENUMBERED , NULL , "Messages Renumbered - Press Key" }, + { CRC_WL_BLANKMSG , NULL , "" }, + { CRC_WL_WAIT , NULL , " Wait " }, + { CRC_IL_GENHEXDUMP , NULL , " Generating Hexdump - Please Wait " }, + { CRC_ST_PROCESSCC , NULL , "Processing Carbon Copies" }, + { CRC_ST_STATUSCC , NULL , "CC: %s of %s" }, + { CRC_ST_DESTINATIONCC , NULL , "Select Carbon Copy Destination" }, + { CRC_MS_LISTCC , NULL , "%s %s" }, + { CRC_WT_DELORIG , NULL , " Delete Original? " }, + { CRC_MI_DELORIGYES , NULL , "Y Yes Please. " }, + { CRC_MI_DELORIGNO , NULL , "N No! " }, + { CRC_WT_DROPMSG , NULL , " Drop This Msg? " }, + { CRC_MI_DROPMSGYES , NULL , "Y Yes Please. " }, + { CRC_MI_DROPMSGNO , NULL , "N No! " }, + { CRC_WT_ZONEGATE , NULL , " Send via ZoneGate? " }, + { CRC_MI_ZONEGATEYES , NULL , "Y Yes Please. " }, + { CRC_MI_ZONEGATENO , NULL , "N No! " }, + { CRC_ST_QUOTEPCT , NULL , "Your Msg Contains %i%% Quotes%s" }, + { CRC_WT_SAVEMSG , NULL , " Save these %i lines? " }, + { CRC_MI_YESGREAT , NULL , "Y Yes, it's great stuff " }, + { CRC_MI_KICKIT , NULL , "N No, drop it.. / ESC " }, + { CRC_MI_CONTINUE , NULL , "C Continue writing " }, + { CRC_MI_ROT13 , NULL , "R ROT13 Crypting " }, + { CRC_MI_ATTRS , NULL , "A Change Attributes " }, + { CRC_MI_ORIGS , NULL , "O Change Origin " }, + { CRC_MI_VIEW , NULL , "V View the message " }, + { CRC_ST_SELECTDESTNODE , NULL , "Select Destination Node" }, + { CRC_WT_ATTACHFILES , NULL , " Attach Files " }, + { CRC_WT_UPDREQFILES , NULL , " Update Request Files " }, + { CRC_ST_EDITHEADER , NULL , "Edit Header Data" }, + { CRC_WT_EDITING , NULL , " Editing " }, + { CRC_MI_INTERNALED , NULL , "I Internal Editor " }, + { CRC_MI_EXTERNALED , NULL , "E External Editor " }, + { CRC_MI_SAVEMESSAGE , NULL , "S Save Message " }, + { CRC_MI_ATTRO , NULL , "A Attributes " }, + { CRC_MI_TEMPLATE , NULL , "T Templates " }, + { CRC_MI_ORIGIN , NULL , "O Origins " }, + { CRC_MI_QUITMESSAGE , NULL , "Q Quit / ESC " }, + { CRC_ST_TEMPLATES , NULL , " Templates " }, + { CRC_WT_CHANGETEMPLATES , NULL , "Change Default Template" }, + { CRC_WT_CARBONCOPY , NULL , " Carbon Copy " }, + { CRC_MI_CCPROCESS , NULL , "P Process CC's " }, + { CRC_MI_CCIGNORE , NULL , "I Ignore CC's " }, + { CRC_MI_CCATTRIBS , NULL , "C Change Attrs " }, + { CRC_MI_CCLISTFMT , NULL , "L List Format " }, + { CRC_WT_CCLIST , NULL , " CC List " }, + { CRC_MI_CCLISTKEEP , NULL , "K Keep " }, + { CRC_MI_CCLISTNAMES , NULL , "N Names only " }, + { CRC_MI_CCLISTVISIBLE , NULL , "V Visible " }, + { CRC_MI_CCLISTHIDDEN , NULL , "H Hidden " }, + { CRC_MI_CCLISTREMOVE , NULL , "R Remove " }, + { CRC_WT_ATTRTITLE , NULL , " Attributes " }, + { CRC_MI_ATTR01 , NULL , " Private Archive/Sent " }, + { CRC_MI_ATTR02 , NULL , " Crash Direct " }, + { CRC_MI_ATTR03 , NULL , " Received Zonegate " }, + { CRC_MI_ATTR04 , NULL , " Sent Hub/Host-Route " }, + { CRC_MI_ATTR05 , NULL , " File Attach Immediate " }, + { CRC_MI_ATTR06 , NULL , " Transit Xmail " }, + { CRC_MI_ATTR07 , NULL , " Orphan Erase File/Sent " }, + { CRC_MI_ATTR08 , NULL , " Kill/Sent Trunc File/Sent " }, + { CRC_MI_ATTR09 , NULL , " Local Locked " }, + { CRC_MI_ATTR10 , NULL , " Hold Confirm Rcpt Request " }, + { CRC_MI_ATTR11 , NULL , " File Request FTS1 Reserved " }, + { CRC_MI_ATTR12 , NULL , " Return Rcpt Request QBBS Reserved, Net " }, + { CRC_MI_ATTR13 , NULL , " Return Rcpt QBBS Reserved, Echo " }, + { CRC_MI_ATTR14 , NULL , " Audit Request Squish Scanned " }, + { CRC_MI_ATTR15 , NULL , " File Update Request Zap all attribs " }, + { CRC_HD_FROM , NULL , " From : " }, + { CRC_HD_TO , NULL , " To : " }, + { CRC_HD_SUBJ , NULL , " Subj : " }, + { CRC_HD_FILE , NULL , " File : " }, + { CRC_MS_EMPTYMSG , NULL , "\r" }, + { CRC_MS_AUTOATTACHMSG , NULL , "\r" }, + { CRC_MS_AUTOREQUESTMSG , NULL , "\r" }, + { CRC_MS_AUTOUPDREQMSG , NULL , "\r" }, + { CRC_WT_FILEATTACH , NULL , " File Attach " }, + { CRC_WT_FILEREQUEST , NULL , " File Request " }, + { CRC_WT_FILEUPDREQ , NULL , " Update Request " }, + { CRC_ST_FILEATTACHING , NULL , "File Attaching [%i/%i] to %u:%u/%u.%u" }, + { CRC_ST_FILEREQUESTING , NULL , "File Requesting [%i/%i] from %u:%u/%u.%u" }, + { CRC_ST_FILEUPDREQING , NULL , "Update Requesting [%i/%i] from %u:%u/%u.%u" }, + { CRC_ST_READMARKED , NULL , "Read Marked - Msg %u of %u (%u left)" }, + { CRC_ST_READALL , NULL , "Read All - Msg %u of %u (%u left)" }, + { CRC_ST_NOQRENUM , NULL , "This area cannot be renumbered" }, + { CRC_MS_HIDINGTWIT , NULL , "This is a Twit Message - Press to read."}, + { CRC_HD_VIA , NULL , "via" }, + { CRC_WT_CHANGEATTRS , NULL , "Change Message Attributes" }, + { CRC_WT_HEADERTEXT , NULL , " Enter Searchstring (Header+Text) " }, + { CRC_WT_HEADERONLY , NULL , " Enter Searchstring (Header Only) " }, + { CRC_WT_NEWAREA , NULL , ">>Pick New Area: " }, + { CRC_WT_REPLYAREA , NULL , ">>Answer In Area: " }, + { CRC_WT_COPYAREA , NULL , ">>Copy To Area: " }, + { CRC_WT_MOVEAREA , NULL , ">>Move To Area: " }, + { CRC_WT_FORWARDAREA , NULL , ">>Forward To Area: " }, + { CRC_WT_FREQAREA , NULL , ">>Filerequest In Area: " }, + { CRC_WT_FREQMENUTITLE , NULL , "Requestable files" }, + { CRC_ST_FREQSTAT , NULL , "Pick files to request" }, + { CRC_IL_FREQINFONOFILES , NULL , " No requestable files were found in this msg! " }, + { CRC_WT_COPY , NULL , " Copy " }, + { CRC_WT_MOVE , NULL , " Move " }, + { CRC_WT_COPYING , NULL , " Copying " }, + { CRC_WT_MOVING , NULL , " Moving " }, + { CRC_ST_COPYINGMSG , NULL , "Copying Msg %u of %u to %s" }, + { CRC_ST_MOVINGMSG , NULL , "Moving Msg %u of %u to %s" }, + { CRC_WT_DELETE , NULL , " Delete " }, + { CRC_WT_DELETING , NULL , " Deleting " }, + { CRC_ST_DELETINGMSG , NULL , "Deleting Msg %u of %u" }, + { CRC_WT_WRITE , NULL , " Write " }, + { CRC_WT_WRITEMSGS , NULL , " Write Msg(s) to File " }, + { CRC_WT_WRITING , NULL , " Writing " }, + { CRC_ST_WRITINGMSG , NULL , "Writing Msg %u of %u" }, + { CRC_WT_WRITINGFILE , NULL , " Writing Msg(s) to File %s " }, + { CRC_WT_WRITINGPRN , NULL , " Writing Msg(s) to Print Device " }, + { CRC_IL_READONLYWARN , NULL , " This area is READ ONLY! " }, + { CRC_WT_ISREADONLY , NULL , " Write msg anyway? " }, + { CRC_MI_READONLYYES , NULL , "Y Yes Please. " }, + { CRC_MI_READONLYNO , NULL , "N No! " }, + { CRC_IL_CHANGEWARN , NULL , " This msg is NOT from you! " }, + { CRC_WT_CHANGE , NULL , " Change this msg? " }, + { CRC_MI_CHANGEYES , NULL , "Y Yes Please. " }, + { CRC_MI_CHANGENO , NULL , "N No! " }, + { CRC_WT_DELETETHIS , NULL , " Delete this msg? " }, + { CRC_MI_DELETEYES , NULL , "Y Yes Please. " }, + { CRC_MI_DELETENO , NULL , "N No! " }, + { CRC_MI_DELETENOASK , NULL , "D Don't ask.. " }, + { CRC_WT_GOTONEXT , NULL , " Goto Next Area? " }, + { CRC_MI_GOTONEXTYES , NULL , "Y Yes Please. " }, + { CRC_MI_GOTONEXTNO , NULL , "N No! " }, + { CRC_MI_GOTONEXTNEW , NULL , "U Yes, Next Unread Area. " }, + { CRC_WT_FORWARD , NULL , " Use FWD kludges? " }, + { CRC_MI_FORWARDYES , NULL , "Y Yes Please. " }, + { CRC_MI_FORWARDNO , NULL , "N No! " }, + { CRC_WT_MSG , NULL , "Msg" }, + { CRC_WT_MSGREAL , NULL , "Msg#" }, + { CRC_WT_FROML , NULL , "From" }, + { CRC_WT_TOL , NULL , "To" }, + { CRC_WT_SUBJL , NULL , "Subj" }, + { CRC_ST_MSGLISTER , NULL , "Lister - Msg %u of %u (%u left)" }, + { CRC_ST_COPYMOVEFORWARD , NULL , "Copy, Move or Forward this message" }, + { CRC_WT_SELECTACTION , NULL , " Action " }, + { CRC_MI_FORWARDMESSAGE , NULL , "F Forward Msg " }, + { CRC_MI_MOVEMESSAGE , NULL , "M Move Msg " }, + { CRC_MI_COPYMESSAGE , NULL , "C Copy Msg " }, + { CRC_MI_QUITCMF , NULL , "Q Quit / ESC " }, + { CRC_ST_ARE , NULL , "messages are" }, + { CRC_ST_IS , NULL , "message is" }, + { CRC_ST_MARKED , NULL , "marked" }, + { CRC_MI_MARKEDMSG , NULL , "M Marked Msgs " }, + { CRC_MI_CURRENTMSG , NULL , "C Current Msg " }, + { CRC_MI_QUITMSGS , NULL , "Q Quit / ESC " }, + { CRC_ST_WRITEMSGSTO , NULL , "Write Msg(s) to File or Printer" }, + { CRC_WT_WRITETO , NULL , " Write To: " }, + { CRC_MI_DISKFILE , NULL , "D Disk File " }, + { CRC_MI_PRINTER , NULL , "P Print device " }, + { CRC_MI_QUITWRITE , NULL , "Q Quit / ESC " }, + { CRC_ST_MARKINGOPTIONS , NULL , "Message Marking" }, + { CRC_WT_MARKWHAT , NULL , " Mark What? " }, + { CRC_MI_YOURMAIL , NULL , "Y Your personal mail " }, + { CRC_MI_FROMTOSUBJ , NULL , "H Header (From/To/Subj) " }, + { CRC_MI_TEXTHDR , NULL , "T Text and header " }, + { CRC_MI_THREAD , NULL , "R Reply thread " }, + { CRC_MI_NEWMSGS , NULL , "N New msgs >current " }, + { CRC_MI_OLDMSGS , NULL , "O Old msgs to ignore" }, + { CRC_IL_READINGECHOLIST , NULL , "Reading Echolist Files" }, + { CRC_IL_READINGADDRMACROS , NULL , "Reading Address Macros" }, + { CRC_IL_CHECKINGNODELISTS , NULL , "Checking Nodelists" }, + { CRC_ST_CROSSPOSTING , NULL , "Crossposting in %s" }, + { CRC_IL_TWITBLANKED , NULL , " Twit Msgs Blanked " }, + { CRC_IL_TWITSKIPPED , NULL , " Twit Msgs Skipped " }, + { CRC_IL_TWITIGNORESKIP , NULL , " Twit Msgs Ignored and Skipped " }, + { CRC_IL_TWITDISPLAYED , NULL , " Twit Msgs Displayed " }, + { CRC_IL_TWITKILLED , NULL , " Twit Msgs Killed " }, + { CRC_IL_STYLECODESNO , NULL , " Stylecodes disabled " }, + { CRC_IL_STYLECODESYES , NULL , " Stylecodes enabled " }, + { CRC_IL_STYLECODESHIDE , NULL , " Stylecodes enabled and stripped " }, + { CRC_ST_GENCFMRECEIPT , NULL , "Generating Confirmation Receipt" }, + { CRC_WT_NEW , NULL , "New" }, + { CRC_ST_LOOKUPINFO , NULL , "Nodelist Lookup Information" }, + { CRC_MS_DATETIMEFMT , NULL , "%d %b %y %H:%M:%S" }, + { CRC_MS_DATEFMT , NULL , "%d %b %y" }, + { CRC_MS_TIMEFMT , NULL , "%H:%M" }, + { CRC_MS_ORIGINALLYIN , NULL , "* Originally in %s" }, + { CRC_MS_CROSSPOSTEDIN , NULL , "* Crossposted in %s" }, + { CRC_MS_CCTO , NULL , "* Carbon copied to %s" }, + { CRC_ST_STATUSLINEHELP , NULL , "F1 Help" }, + { CRC_HD_OF , NULL , "of" }, + { CRC_MS_ROBOTMSG , NULL , "\r--- @longpid @version\r" }, + { CRC_ST_STATUSLINETIMEFMT , NULL , "%H:%M:%S" }, + + { CRC_WT_REPLIES , NULL , " Replies " }, + { CRC_ST_SELECTREPLY , NULL , "Select the reply you want to see" }, + { CRC_IL_WAITOREXIT , NULL , " At this point you must either wait or exit GoldED entirely - Sorry! " }, + { CRC_WT_REALLYEXIT , NULL , " Really exit? " }, + { CRC_MI_TAGLINES , NULL , "T Change Tagline" }, + { CRC_MI_HEADEREDIT , NULL , "H Edit Header" }, + { CRC_MI_SCANGROUP , NULL , "G Scan Group" }, + { CRC_WT_QWKPACKET , NULL , " QWK Packet " }, + { CRC_MI_SCANQWK , NULL , "Q QWK Packet" }, + { CRC_WT_SOUPPACKET , NULL , " SOUP Packet " }, + { CRC_MI_SCANSOUP , NULL , "S SOUP Packet" }, + { CRC_MI_SCANIMPORT , NULL , "I Import" }, + { CRC_MI_SCANEXPORT , NULL , "E Export" }, + { CRC_WT_SCANPM , NULL , " Scan PM " }, + { CRC_MI_TAGLINE , NULL , "g Taglines" }, + { CRC_WT_CONFIRM , NULL , " Honor receipt request? " }, + { CRC_MI_CONFIRMYES , NULL , "Y Yes, send a receipt msg " }, + { CRC_MI_CONFIRMNO , NULL , "N No, ignore the request " }, + { CRC_IL_CONFIRMINFO , NULL , " The sender of this message requests confirmation of receipt (CFM) " }, + { CRC_ST_MSG , NULL , "msg" }, + { CRC_ST_MSGS , NULL , "msgs" }, + { CRC_ST_PERSONAL , NULL , "personal" }, + { CRC_WT_GRP , NULL , "Grp" }, + { CRC_IL_FOUNDPERSONAL , NULL , " Found %u personal mail%s in %u area%s " }, + { CRC_IL_NOPERSONAL , NULL , " No personal mail found " }, + { CRC_ST_ESCORCONTINUE , NULL , "ESC exits. Other keys: Tries to continue" }, + { CRC_MS_SPELLCHECKER , NULL , "SpellChecker: %s" }, + { CRC_WT_INS , NULL , " Ins " }, + { CRC_MI_FILELISTFROM , NULL , "Filelist from %s" }, + { CRC_ST_INITIALIZING , NULL , "Initializing ..." }, + { CRC_ST_CHECKING , NULL , "Checking" }, + { CRC_ST_LOCKSHARECAP , NULL , "%s Lock/Share Capability" }, + { CRC_WT_ATTRTURNOFF , NULL , " Press Alt-F1 to turn off this window " }, + { CRC_WT_TAGLINES , NULL , " Taglines " }, + { CRC_ST_CHANGETAGLINE , NULL , "Change Default Tagline" }, + { CRC_IL_NOTAGLINE , NULL , " No taglines defined. Press key " }, + { CRC_WT_CHARSETS , NULL , " Charsets " }, + { CRC_ST_CHANGEXLATIMP , NULL , "Change Default Import Charset" }, + { CRC_MI_CHARSETAUTO , NULL , "Auto" }, + { CRC_IL_NOXLATIMPORT , NULL , " No XLATIMPORT's defined. Press key " }, + { CRC_WT_N_A , NULL , "n/a" }, + { CRC_WT_WRITTEN , NULL , "Written" }, + { CRC_WT_ARRIVED , NULL , "Arrived" }, + { CRC_WT_RECEIVED , NULL , "Received" }, + { CRC_IL_NONODELIST , NULL , " Unable to access the nodelist or index files " }, + { CRC_IL_NODELISTMISSING , NULL , "Nodelist missing:" }, + { CRC_IL_NODELISTOUTDATED , NULL , "Nodelist out of date:" }, + { CRC_MS_REPLYLINKER , NULL , "Replylinker: %s" }, + { CRC_WT_ENTERMSGNO , NULL , " Enter msgno " }, + { CRC_IL_WAITUUDECODING , NULL , " Wait - uudecoding " }, + { CRC_IL_COMPLETEDUUDECODE , NULL , " Completed uudecode of %s " }, + { CRC_IL_NOTUUENCODED , NULL , " Could not find anything to uudecode " }, + { CRC_IL_UUEINVALIDPATH , NULL , " Invalid path for uudecoding - file not written " }, + { CRC_IL_PATHREPORT , NULL , " Generating PATH report " }, + { CRC_IL_ERRORINSOUP , NULL , " Error in SOUP file %s " }, + { CRC_IL_WARNALREADYSENT , NULL , " WARNING: This message is already sent! " }, + { CRC_IL_WAITLOCKED , NULL , " Wait: %s is locked " }, + { CRC_ST_RETRYORESC , NULL , "%s retry (%lu). Press ESC to exit GoldED." }, + { CRC_ST_RETRYLOCK , NULL , "Lock" }, + { CRC_ST_RETRYOPEN , NULL , "Open" }, + { CRC_WT_TOUCHSEMAPHORE , NULL , " Enter name of semaphore file to touch " }, + { CRC_MI_WRITETOHDRNO , NULL , "H Use Header: NO " }, + { CRC_MI_WRITETOHDRYES , NULL , "H Use Header: YES "}, + { CRC_MI_WRITETOHDRONLY , NULL , "H Use Header: ONLY "}, + { CRC_MI_CLIPBOARD , NULL , "C Clipboard "}, + { CRC_WT_SELECTMARKS , NULL , " Select Mark " }, + { CRC_WT_SELECTMARKSEDIT , NULL , " Edit Mark Description " }, + { CRC_IL_DROPMARKSINFO , NULL , " %s Messages Are Marked " }, + { CRC_WT_DROPMARKS , NULL , " Drop Msg Marks " }, + { CRC_MI_DROPALL , NULL , "A Drop All " }, + { CRC_MI_DROPMARKED , NULL , "M Drop Marked " }, + { CRC_MI_DROPCURRENT , NULL , "C Drop Current " }, + { CRC_MI_NODROP , NULL , "N No Drop / ESC " }, + { CRC_WT_CATCHAREAS , NULL , " Catch-Up Areas " }, + { CRC_MI_CATCHALL , NULL , "A Catch All " }, + { CRC_MI_CATCHMARKED , NULL , "M Catch Marked " }, + { CRC_MI_CATCHCURRENT , NULL , "C Catch Current " }, + { CRC_MI_NOCATCH , NULL , "N No Catch / ESC " }, + { CRC_WT_CROSSPOST , NULL , " Crosspost " }, + { CRC_MI_XCPROCESS , NULL , "P Process XC's " }, + { CRC_MI_XCIGNORE , NULL , "I Ignore XC's " }, + { CRC_MI_XCLISTFMT , NULL , "L List Format " }, + { CRC_WT_XCLIST , NULL , " XC List " }, + { CRC_MI_XCLISTRAW , NULL , "K Keep " }, + { CRC_MI_XCLISTVERBOSE , NULL , "V Verbose " }, + { CRC_MI_XCLISTLINE , NULL , "L Line " }, + { CRC_MI_XCLISTREMOVE , NULL , "R Remove " }, + + { CRC_WT_ADDRESSBOOK , NULL , " Addressbook " }, + { CRC_WT_ADVANCEDSEARCH , NULL , " Advanced Search " }, + { CRC_IL_NOMOREMATCHES , NULL , " No more matches found " }, + { CRC_WT_HEADEREDITHELP1 , NULL , " #F10: Nodelist " }, + { CRC_WT_HEADEREDITHELP2 , NULL , " F10: Addressbook " }, + { CRC_WT_THREADLISTTITLE , NULL , " Message Thread List " }, + { CRC_WT_ADVANCEDMARKING , NULL , " Advanced Marking " }, + { CRC_ST_USERSTATUSLINE , NULL , "GoldED's Address Book - %d of %d (%d left)" }, + { CRC_WT_USERHEADERNAME , NULL , "Name" }, + { CRC_WT_USERHEADERORG , NULL , "Organization" }, + { CRC_WT_USERHEADERAKA , NULL , "Address" }, + { CRC_IL_USERWAIT , NULL , " Wait - Browsing Address Book... " }, + + { CRC_MI_ALSELECTIONS1 , NULL , "Mark Areas with New Mail" }, + { CRC_MI_ALSELECTIONS2 , NULL , "(unused)" }, + { CRC_IL_DECODE , NULL , "Decode" }, + { CRC_IL_PREPARING , NULL , "Preparing" }, + + { CRC_LAST_CRC , NULL , NULL } +}; + + +// ------------------------------------------------------------------ +// Compare two crcs + +static int CmpLangCrc(LangCrc* a, LangCrc* b) { + + return((a->crc > b->crc) ? 1 : ((a->crc < b->crc) ? -1 : 0)); +} + + +// ------------------------------------------------------------------ +// Call the function matching the keyword + +static bool SwitchLanguage(word crc, char* str) { + + LangCrc* lptr; + LangCrc lkey; + + lkey.crc = crc; + + lptr = (LangCrc*)bsearch(&lkey, LangCrcs, sizeof(LangCrcs)/sizeof(LangCrc), sizeof(LangCrc), (StdCmpCP)CmpLangCrc); + if(lptr != NULL) { + if(lptr->langptr != NULL) { + throw_xfree(*(lptr->langptr)); + *(lptr->langptr) = throw_strdup(StripQuotes(str)); + } + return 0; + } else + return -1; +} + + +// ------------------------------------------------------------------ +// Unallocate all language strings + +static void LangReset(void) { + + LangCrc* lngptr = LangCrcs; + + for(; lngptr->crc < CRC_LAST_CRC; lngptr++) + if(lngptr->langptr != NULL) + throw_xfree(*(lngptr->langptr)); + + throw_release(LNG); + + int n; + for(n=0; n<7; n++) + gsweekday[n] = NULL; + for(n=0; n<7; n++) + glweekday[n] = NULL; + for(n=0; n<12; n++) + gsmonth[n] = NULL; + for(n=0; n<12; n++) + glmonth[n] = NULL; +} + + +// ------------------------------------------------------------------ +// Initialize language + +void LangInit() { + + LNG = (LangGed*)throw_calloc(1, sizeof(LangGed)); + LNG->Outofmem = throw_strdup("Out of memory!"); + + // Init LangCrc pointers to LNG + char** lptr = (char**)LNG; + for(LangCrc* lngptr = LangCrcs; lngptr->crc != CRC_LAST_CRC; lngptr++, lptr++) + lngptr->langptr = lptr; + + // Sort the crc list + qsort(LangCrcs, sizeof(LangCrcs)/sizeof(LangCrc), sizeof(LangCrc), (StdCmpCP)CmpLangCrc); + + atexit(LangReset); +} + + +// ------------------------------------------------------------------ +// Assign weekday/month names + +void AssignDateNames() { + + gsweekday[0] = LNG->SWSun; + gsweekday[1] = LNG->SWMon; + gsweekday[2] = LNG->SWTue; + gsweekday[3] = LNG->SWWed; + gsweekday[4] = LNG->SWThu; + gsweekday[5] = LNG->SWFri; + gsweekday[6] = LNG->SWSat; + + glweekday[0] = LNG->LWSunday; + glweekday[1] = LNG->LWMonday; + glweekday[2] = LNG->LWTuesday; + glweekday[3] = LNG->LWWednesday; + glweekday[4] = LNG->LWThursday; + glweekday[5] = LNG->LWFriday; + glweekday[6] = LNG->LWSaturday; + + gsmonth[0] = LNG->SMJan; + gsmonth[1] = LNG->SMFeb; + gsmonth[2] = LNG->SMMar; + gsmonth[3] = LNG->SMApr; + gsmonth[4] = LNG->SMMay; + gsmonth[5] = LNG->SMJun; + gsmonth[6] = LNG->SMJul; + gsmonth[7] = LNG->SMAug; + gsmonth[8] = LNG->SMSep; + gsmonth[9] = LNG->SMOct; + gsmonth[10] = LNG->SMNov; + gsmonth[11] = LNG->SMDec; + + glmonth[0] = LNG->LMJanuary; + glmonth[1] = LNG->LMFebruary; + glmonth[2] = LNG->LMMarch; + glmonth[3] = LNG->LMApril; + glmonth[4] = LNG->LMMay; + glmonth[5] = LNG->LMJune; + glmonth[6] = LNG->LMJuly; + glmonth[7] = LNG->LMAugust; + glmonth[8] = LNG->LMSeptember; + glmonth[9] = LNG->LMOctober; + glmonth[10] = LNG->LMNovember; + glmonth[11] = LNG->LMDecember; +} + + +// ------------------------------------------------------------------ +// Load a GoldED language file + +void LoadLanguage(const char* file) { + + FILE* fp; + char* ptr; + char* str; + int line = 0; + char buf[256]; + + fp = fsopen(AddPath(CFG->goldpath, file), "rt", CFG->sharemode); + if(fp) { + setvbuf(fp, NULL, _IOFBF, 8192); + while(fgets((ptr=buf), sizeof(buf), fp)) { + line++; + ptr = strskip_wht(ptr); + if(isalpha(*ptr)) { + str = ptr; + strtrim(str); + str = strskip_txt(str); + if(*str) { + *str++ = NUL; + str = strskip_wht(str); + strschg(str, "\\n", "\n"); + strschg(str, "\\r", "\r"); + strschg(str, "\\\"", "\""); + } + if(SwitchLanguage(strCrc16(strupr(ptr)), str)) { + if(cmdlineoldkeyw == false) { + w_infof(" %s line %u: \"%s\" is obsolete or unknown ", file, line, ptr); + SayBibi(); + waitkeyt(10000); + w_info(NULL); + cfgerrors++; + } + } + } + } + fclose(fp); + + // Assign weekday/month names + AssignDateNames(); + } +} + + +// ------------------------------------------------------------------ +// Read the main language definition file + +bool ReadLangCfg(int force) { + + FILE *fpi; + char* ptr; + char* str; + long size; + char buf[1024]; + LangCrc* lngptr; + int line = 0; + + // Read the GOLDLANG.CFG if there is one + const char* cfgname = AddPath(CFG->goldpath, CFG->langcfg); + fpi = fsopen(cfgname, "rt", CFG->sharemode); + if(fpi) { + setvbuf(fpi, NULL, _IOFBF, 8192); + + if(not quiet) + cout << "* Reading " << cfgname << endl; + + cfgname = CleanFilename(cfgname); + + while(fgets((ptr=buf), sizeof(buf), fpi)) { + line++; + ptr = strskip_wht(ptr); + if(isalpha(*ptr)) { + str = ptr; + strtrim(str); + str = strskip_txt(str); + if(*str) { + *str++ = NUL; + str = strskip_wht(str); + strschg(str, "\\n", "\n"); + strschg(str, "\\r", "\r"); + strschg(str, "\\\"", "\""); + } + if(SwitchLanguage(strCrc16(strupr(ptr)), str)) { + if(cmdlineoldkeyw == false) { + cout << "* " << cfgname << " line " << line << ": \"" << ptr << "\" is obsolete or unknown." << endl; + SayBibi(); + cfgerrors++; + } + } + } + } + fclose(fpi); + } + + // Fill in the defaults if there are "holes" + size = 0; + lngptr = LangCrcs; + for(; lngptr->crc < CRC_LAST_CRC; lngptr++) { + if(lngptr->langptr != NULL) { + if(*(lngptr->langptr) == NULL) + *(lngptr->langptr) = throw_strdup(lngptr->langdef); + size += strlen(*(lngptr->langptr)) + 1; + } + } + + AssignDateNames(); + + return true; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gclang.h b/golded3/gclang.h new file mode 100644 index 0000000..fadeb27 --- /dev/null +++ b/golded3/gclang.h @@ -0,0 +1,494 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// CRC values for language items. +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ +// CRC values for language items + +const word CRC_MS_SWSUN = 0xD108; +const word CRC_MS_SWMON = 0x38F7; +const word CRC_MS_SWTUE = 0xA1E4; +const word CRC_MS_SWWED = 0x8186; +const word CRC_MS_SWTHU = 0xBCF4; +const word CRC_MS_SWFRI = 0x949B; +const word CRC_MS_SWSAT = 0xC512; + +const word CRC_MS_LWSUNDAY = 0x4D93; +const word CRC_MS_LWMONDAY = 0x70CC; +const word CRC_MS_LWTUESDAY = 0x4F54; +const word CRC_MS_LWWEDNESDAY = 0x9D11; +const word CRC_MS_LWTHURSDAY = 0x3684; +const word CRC_MS_LWFRIDAY = 0xF676; +const word CRC_MS_LWSATURDAY = 0x96AC; + +const word CRC_MS_SMJAN = 0xAAA8; +const word CRC_MS_SMFEB = 0x6F28; +const word CRC_MS_SMMAR = 0xDA53; +const word CRC_MS_SMAPR = 0x0ADF; +const word CRC_MS_SMMAY = 0xDA58; +const word CRC_MS_SMJUN = 0xBEA8; +const word CRC_MS_SMJUL = 0xBEAA; +const word CRC_MS_SMAUG = 0x0FCA; +const word CRC_MS_SMSEP = 0x2DAE; +const word CRC_MS_SMOCT = 0xF817; +const word CRC_MS_SMNOV = 0xE434; +const word CRC_MS_SMDEC = 0x4F6B; + +const word CRC_MS_LMJANUARY = 0xD084; +const word CRC_MS_LMFEBRUARY = 0xE186; +const word CRC_MS_LMMARCH = 0xB291; +const word CRC_MS_LMAPRIL = 0xFDB6; +const word CRC_MS_LMMAY = 0xB50A; +const word CRC_MS_LMJUNE = 0x2119; +const word CRC_MS_LMJULY = 0x2305; +const word CRC_MS_LMAUGUST = 0x532D; +const word CRC_MS_LMSEPTEMBER = 0x4AFE; +const word CRC_MS_LMOCTOBER = 0x51C9; +const word CRC_MS_LMNOVEMBER = 0x107D; +const word CRC_MS_LMDECEMBER = 0x7733; + +const word CRC_ST_IMPORTFILE = 0x027D; +const word CRC_WT_IMPORTWHICHFILE = 0xF718; +const word CRC_WT_IMPORTTXT = 0xB5DB; +const word CRC_MI_IMPORTTXTTEXT = 0xDCC1; +const word CRC_MI_IMPORTTXTQUOTE = 0x41E1; +const word CRC_MI_IMPORTTXTUUE = 0x36B6; +const word CRC_MI_IMPORTTXTMIME = 0xB1B7; +const word CRC_MI_IMPORTTXTCLIP = 0xC608; +const word CRC_MI_IMPORTTXTXLAT = 0x1185; +const word CRC_MI_IMPORTTXTQUIT = 0x2005; +const word CRC_WT_IMPORTPICK = 0xF5E1; +const word CRC_ST_IMPORTSTATUS = 0x4E97; +const word CRC_ST_EXPORTFILE = 0x5D16; +const word CRC_WT_EXPORTWHATFILE = 0xACAE; +const word CRC_ST_EXPORTSTATUS = 0x8DDB; +const word CRC_ST_EDITSTATUS = 0xB76C; +const word CRC_ST_SELECTFILES = 0xB2B4; +const word CRC_WL_SELECTEDFILES = 0x8C0E; +const word CRC_WL_SELECTEDBYTES = 0xC084; +const word CRC_WL_TOTALFILES = 0x92AE; +const word CRC_WL_TOTALBYTES = 0xDE24; +const word CRC_WL_SCANNINGDIRECTORY = 0xED57; +const word CRC_WL_NOFILESFOUND = 0x9013; +const word CRC_ST_FILESPRESSKEY = 0x472E; +const word CRC_WT_AREA = 0xBED8; +const word CRC_WT_DESCRIPTION = 0x3F38; +const word CRC_WT_MSGS = 0xE986; +const word CRC_WT_LAST = 0xFCC3; +const word CRC_WT_ECHOID = 0x1703; +const word CRC_ST_MESSAGE = 0x3CCE; +const word CRC_ST_MESSAGES = 0x398C; +const word CRC_ST_UNREAD = 0xCAC1; +const word CRC_WT_SCANAREAS = 0x8270; +const word CRC_MI_SCANALL = 0xFD54; +const word CRC_MI_SCANMARKED = 0xF28C; +const word CRC_MI_SCANCURRENT = 0xEE1C; +const word CRC_MI_SCANMATCHING = 0x4229; +const word CRC_MI_SCANUNSCANNED = 0x42C5; +const word CRC_MI_NOSCAN = 0xFA80; +const word CRC_WT_HEATAREAS = 0x00C9; +const word CRC_MI_HEATALL = 0xDED0; +const word CRC_MI_HEATMARKED = 0xFA46; +const word CRC_MI_HEATCURRENT = 0xA514; +const word CRC_MI_HEATMATCHING = 0xB386; +const word CRC_MI_NOHEAT = 0x45D5; +const word CRC_WT_ZAPAREAS = 0x3A1D; +const word CRC_MI_ZAPALL = 0x48C4; +const word CRC_MI_ZAPMARKED = 0xFF68; +const word CRC_MI_ZAPCURRENT = 0xDBB1; +const word CRC_MI_ZAPMATCHING = 0x89DF; +const word CRC_MI_NOZAP = 0x9D23; +const word CRC_MS_DOS_SHELL = 0xF73E; +const word CRC_IL_SCANNINGAREA = 0x38E0; +const word CRC_IL_SEARCHINGFOR = 0xDED6; +const word CRC_ST_READINGMSG = 0x24BD; +const word CRC_ER_OUTOFMEM = 0x60C7; +const word CRC_MS_HEXDUMPF = 0x3E18; +const word CRC_MS_HEXDUMPHEAD = 0x2E54; +const word CRC_MS_HEXDUMPTEXT = 0x715A; +const word CRC_ST_RENUMBERING = 0x0D0E; +const word CRC_ST_LOCKED = 0xC0AD; +const word CRC_ST_RENUMBERED = 0x639A; +const word CRC_WL_BLANKMSG = 0x441A; +const word CRC_WL_WAIT = 0xA72E; +const word CRC_IL_GENHEXDUMP = 0xF0CE; +const word CRC_ST_PROCESSCC = 0xC1DB; +const word CRC_ST_STATUSCC = 0xE5ED; +const word CRC_ST_DESTINATIONCC = 0xFCA4; +const word CRC_MS_LISTCC = 0x5915; +const word CRC_WT_DELORIG = 0x9EC3; +const word CRC_MI_DELORIGYES = 0xE51D; +const word CRC_MI_DELORIGNO = 0x911E; +const word CRC_WT_DROPMSG = 0x678A; +const word CRC_MI_DROPMSGYES = 0x2F8A; +const word CRC_MI_DROPMSGNO = 0xE1AA; +const word CRC_WT_ZONEGATE = 0x399C; +const word CRC_MI_ZONEGATEYES = 0xDC92; +const word CRC_MI_ZONEGATENO = 0xF8DA; +const word CRC_ST_QUOTEPCT = 0x55A1; +const word CRC_WT_SAVEMSG = 0xA50B; +const word CRC_MI_YESGREAT = 0x8336; +const word CRC_MI_KICKIT = 0x7E04; +const word CRC_MI_CONTINUE = 0x1BFF; +const word CRC_MI_ROT13 = 0x3A8C; +const word CRC_MI_ATTRS = 0x9C56; +const word CRC_MI_ORIGS = 0xFB6D; +const word CRC_MI_VIEW = 0xE7A5; +const word CRC_ST_SELECTDESTNODE = 0x7166; +const word CRC_WT_ATTACHFILES = 0xA67C; +const word CRC_WT_UPDREQFILES = 0xA04A; +const word CRC_ST_EDITHEADER = 0xC4B7; +const word CRC_WT_EDITING = 0xD205; +const word CRC_MI_INTERNALED = 0xC48B; +const word CRC_MI_EXTERNALED = 0x4362; +const word CRC_MI_SAVEMESSAGE = 0x15BC; +const word CRC_MI_ATTRO = 0x9C4A; +const word CRC_MI_TEMPLATE = 0xC792; +const word CRC_MI_ORIGIN = 0x293A; +const word CRC_MI_QUITMESSAGE = 0x03B4; +const word CRC_ST_TEMPLATES = 0x9B57; +const word CRC_WT_CHANGETEMPLATES = 0xD420; +const word CRC_WT_CARBONCOPY = 0x1FBB; +const word CRC_MI_CCPROCESS = 0x7B4C; +const word CRC_MI_CCIGNORE = 0x557C; +const word CRC_MI_CCATTRIBS = 0xA182; +const word CRC_MI_CCLISTFMT = 0x7307; +const word CRC_WT_CCLIST = 0x8688; +const word CRC_MI_CCLISTKEEP = 0xAFF0; +const word CRC_MI_CCLISTNAMES = 0x076A; +const word CRC_MI_CCLISTVISIBLE = 0x8495; +const word CRC_MI_CCLISTHIDDEN = 0x2828; +const word CRC_MI_CCLISTREMOVE = 0x36BD; +const word CRC_WT_ATTRTITLE = 0x0CA9; +const word CRC_MI_ATTR01 = 0x7704; +const word CRC_MI_ATTR02 = 0x7707; +const word CRC_MI_ATTR03 = 0x7706; +const word CRC_MI_ATTR04 = 0x7701; +const word CRC_MI_ATTR05 = 0x7700; +const word CRC_MI_ATTR06 = 0x7703; +const word CRC_MI_ATTR07 = 0x7702; +const word CRC_MI_ATTR08 = 0x770D; +const word CRC_MI_ATTR09 = 0x770C; +const word CRC_MI_ATTR10 = 0x7605; +const word CRC_MI_ATTR11 = 0x7604; +const word CRC_MI_ATTR12 = 0x7607; +const word CRC_MI_ATTR13 = 0x7606; +const word CRC_MI_ATTR14 = 0x7601; +const word CRC_MI_ATTR15 = 0x7600; +const word CRC_HD_MSGNO = 0x2C95; +const word CRC_HD_MSGNUM = 0x6AA3; +const word CRC_HD_MSGNOS = 0x70BD; +const word CRC_HD_MSGNUMS = 0x6EBF; +const word CRC_HD_FROM = 0x5747; +const word CRC_HD_TO = 0x8A51; +const word CRC_HD_SUBJ = 0xD621; +const word CRC_HD_FILE = 0xF715; +const word CRC_MS_EMPTYMSG = 0xF2BA; +const word CRC_MS_TEMPLATE = 0x6B5A; +const word CRC_MS_AUTOATTACHMSG = 0xA68A; +const word CRC_MS_AUTOREQUESTMSG = 0x21F2; +const word CRC_MS_AUTOUPDREQMSG = 0xD9FC; +const word CRC_WT_FILEATTACH = 0x7798; +const word CRC_WT_FILEREQUEST = 0x4E3E; +const word CRC_WT_FILEUPDREQ = 0x5D36; +const word CRC_ST_FILEATTACHING = 0xA6D5; +const word CRC_ST_FILEREQUESTING = 0x2C2E; +const word CRC_ST_FILEUPDREQING = 0xD9A3; +const word CRC_ER_NOTOPENQ = 0x4452; +const word CRC_ER_NOUSER = 0x0C80; +const word CRC_ER_NOLRQUSER = 0x9D9B; +const word CRC_ST_SCANBASE = 0xBA50; +const word CRC_MS_HEXDUMPQ = 0x3E0F; +const word CRC_ST_REBUILDMSGINFO = 0xBE11; +const word CRC_ST_READMARKED = 0x483E; +const word CRC_ST_READALL = 0xE183; +const word CRC_ST_NOQRENUM = 0x2669; +const word CRC_MS_HIDINGTWIT = 0x922C; +const word CRC_HD_VIA = 0x47C1; +const word CRC_WT_CHANGEATTRS = 0x03C1; +const word CRC_WT_HEADERTEXT = 0x7C39; +const word CRC_WT_HEADERONLY = 0x06D6; +const word CRC_WT_NEWAREA = 0x44F6; +const word CRC_WT_REPLYAREA = 0x2EB5; +const word CRC_WT_COPYAREA = 0x7DF5; +const word CRC_WT_MOVEAREA = 0xECCD; +const word CRC_WT_FORWARDAREA = 0xE927; +const word CRC_WT_FREQAREA = 0x1597; +const word CRC_WT_FREQMENUTITLE = 0x6ED6; +const word CRC_ST_FREQSTAT = 0x88BA; +const word CRC_IL_FREQINFONOFILES = 0x3EEF; +const word CRC_WT_COPY = 0x0E3E; +const word CRC_WT_MOVE = 0x2B2D; +const word CRC_WT_COPYING = 0xAA31; +const word CRC_WT_MOVING = 0xA018; +const word CRC_ST_COPYINGMSG = 0xD790; +const word CRC_ST_MOVINGMSG = 0x505D; +const word CRC_WT_DELETE = 0xA398; +const word CRC_WT_DELETING = 0xC557; +const word CRC_ST_DELETINGMSG = 0x9DD5; +const word CRC_WT_WRITE = 0xBB1F; +const word CRC_WT_WRITEMSGS = 0xD6C9; +const word CRC_WT_WRITING = 0xAEE2; +const word CRC_ST_WRITINGMSG = 0x4B24; +const word CRC_WT_WRITINGFILE = 0xB4BF; +const word CRC_WT_WRITINGPRN = 0xD8F6; +const word CRC_IL_READONLYWARN = 0xF595; +const word CRC_WT_ISREADONLY = 0x925C; +const word CRC_MI_READONLYYES = 0xD147; +const word CRC_MI_READONLYNO = 0x8A89; +const word CRC_IL_CHANGEWARN = 0xEAFE; +const word CRC_WT_CHANGE = 0x64D3; +const word CRC_MI_CHANGEYES = 0x84CA; +const word CRC_MI_CHANGENO = 0xA509; +const word CRC_WT_DELETETHIS = 0xE2D6; +const word CRC_MI_DELETEYES = 0xF69B; +const word CRC_MI_DELETENO = 0xD365; +const word CRC_MI_DELETENOASK = 0xC3B5; +const word CRC_WT_GOTONEXT = 0x2F9B; +const word CRC_MI_GOTONEXTYES = 0xB4C6; +const word CRC_MI_GOTONEXTNO = 0x21E8; +const word CRC_WT_MSG = 0x72B7; +const word CRC_WT_MSGREAL = 0xE582; +const word CRC_WT_FROML = 0xB683; +const word CRC_WT_TOL = 0xEDA4; +const word CRC_WT_SUBJL = 0x512A; +const word CRC_WT_DATEL = 0x2599; +const word CRC_ST_MSGLISTER = 0x8C5E; +const word CRC_ST_COPYMOVEFORWARD = 0xC024; +const word CRC_WT_SELECTACTION = 0xF7C0; +const word CRC_MI_FORWARDMESSAGE = 0x644C; +const word CRC_MI_MOVEMESSAGE = 0xAB24; +const word CRC_MI_COPYMESSAGE = 0x6811; +const word CRC_MI_QUITCMF = 0xE1B8; +const word CRC_ST_ARE = 0x78C8; +const word CRC_ST_IS = 0x27AC; +const word CRC_ST_MARKED = 0x9D5A; +const word CRC_MI_MARKEDMSG = 0xB19D; +const word CRC_MI_CURRENTMSG = 0x77E2; +const word CRC_MI_QUITMSGS = 0x84AC; +const word CRC_ST_WRITEMSGSTO = 0xAE7F; +const word CRC_WT_WRITETO = 0x7566; +const word CRC_MI_DISKFILE = 0x2A91; +const word CRC_MI_PRINTER = 0x9CBE; +const word CRC_MI_QUITWRITE = 0x2C14; +const word CRC_ST_MARKINGOPTIONS = 0x0CA8; +const word CRC_WT_MARKWHAT = 0xEC2E; +const word CRC_MI_YOURMAIL = 0x1143; +const word CRC_MI_FROMTOSUBJ = 0x52FC; +const word CRC_MI_TEXTHDR = 0x1564; +const word CRC_MI_THREAD = 0x5FE1; +const word CRC_MI_NEWMSGS = 0x6211; +const word CRC_MI_OLDMSGS = 0x2104; +const word CRC_MI_ALLMSGS = 0x470D; +const word CRC_MI_UNMARK = 0xDB33; +const word CRC_MI_RANGE = 0xDC8E; +const word CRC_MI_MARKSTOGGLE = 0x40C2; +const word CRC_MI_QUITMARKS = 0x42DA; +const word CRC_WT_ENTERMARKSTRING = 0xF300; +const word CRC_ST_SEARCHINGMSG = 0xC878; +const word CRC_WT_USERLISTNAME = 0x459B; +const word CRC_IL_GENUSERLIST = 0x95DE; +const word CRC_WT_FILEEXISTS = 0x984F; +const word CRC_MI_APPEND = 0x7BA3; +const word CRC_MI_OVERWRITE = 0x4BB5; +const word CRC_MI_QUITEXIST = 0xE9CD; +const word CRC_WT_UNSENT = 0x3726; +const word CRC_IL_WARNUNSENT = 0xB1EB; +const word CRC_ST_CHANGEORIGIN = 0xC9C1; +const word CRC_WT_ORIGINS = 0xFEA1; +const word CRC_ST_CHANGEUSERNAME = 0x91EA; +const word CRC_WT_USERNAMES = 0x1B5B; +const word CRC_ST_CHANGEAKA = 0xB94E; +const word CRC_WT_AKAS = 0x39D2; +const word CRC_WT_LOOKUP = 0x5412; +const word CRC_WL_PHONE = 0xAE86; +const word CRC_WT_QUITGOLDED = 0x4D56; +const word CRC_MI_QUITYES = 0x5AD6; +const word CRC_MI_QUITNO = 0x3004; +const word CRC_MS_EDITCMD = 0xC5C0; +const word CRC_IL_NOORIGDEFINED = 0x4CFB; +const word CRC_IL_NOUSERDEFINED = 0xBCA0; +const word CRC_IL_NOAKADEFINED = 0x7FBD; +const word CRC_IL_NOTPLDEFINED = 0x38A0; +const word CRC_MS_SKIPPINGTWIT = 0x1139; +const word CRC_MS_KILLINGTWIT = 0x477B; +const word CRC_IL_WRITINGCFG = 0x3637; +const word CRC_IL_COULDNOTOPEN = 0xC54F; +const word CRC_MS_PROMPT = 0x6803; +const word CRC_IL_UNFINISHEDMSG = 0x4FB3; +const word CRC_ST_LOADUNFINISHED = 0x6A0B; +const word CRC_IL_READINGECHOLIST = 0x7CBE; +const word CRC_ER_NOAREAS = 0xFE4D; +const word CRC_IL_READINGADDRMACROS = 0xC038; +const word CRC_IL_CHECKINGNODELISTS = 0x6412; +const word CRC_ST_CROSSPOSTING = 0xA937; +const word CRC_IL_ACCESSWAIT = 0x7247; +const word CRC_ST_ACCESSRETRY = 0x2685; +const word CRC_IL_NEWMSGSCAN = 0x6F97; +const word CRC_IL_NEWMSGSSCANNED = 0x771B; +const word CRC_IL_BASEIDXMISMATCH = 0x5413; +const word CRC_IL_BASETOIDXMISMATCH = 0xC555; +const word CRC_ST_REBUILDINGMSGBASE = 0xE64B; +const word CRC_IL_TWITBLANKED = 0x12ED; +const word CRC_IL_TWITSKIPPED = 0xC74C; +const word CRC_IL_TWITIGNORESKIP = 0x7BF4; +const word CRC_IL_TWITDISPLAYED = 0x9D1E; +const word CRC_IL_TWITKILLED = 0xC10B; +const word CRC_ST_GENCFMRECEIPT = 0xFB57; +const word CRC_WT_NEW = 0x54C4; +const word CRC_ST_LOOKUPINFO = 0x9B9F; +const word CRC_MS_HEXDUMPSQ = 0xDACC; +const word CRC_MS_DATETIMEFMT = 0xA85F; +const word CRC_MS_DATEFMT = 0xB211; +const word CRC_MS_TIMEFMT = 0xEE7A; +const word CRC_MS_ORIGINALLYIN = 0xA76F; +const word CRC_MS_CROSSPOSTEDIN = 0x1559; +const word CRC_MS_CCTO = 0xD87D; +const word CRC_ST_STATUSLINEHELP = 0xBB2D; +const word CRC_HD_OF = 0x9158; +const word CRC_MS_ROBOTMSG = 0x57FD; +const word CRC_ST_STATUSLINETIMEFMT = 0x1017; + +const word CRC_WT_REPLIES = 0x9B03; +const word CRC_ST_SELECTREPLY = 0xB2CD; +const word CRC_IL_WAITOREXIT = 0x027E; +const word CRC_WT_REALLYEXIT = 0x3384; +const word CRC_MI_TAGLINES = 0x0F31; +const word CRC_MI_HEADEREDIT = 0x06F7; +const word CRC_MI_SCANGROUP = 0x8803; +const word CRC_WT_QWKPACKET = 0xD46E; +const word CRC_MI_SCANQWK = 0xF462; +const word CRC_WT_SOUPPACKET = 0x2EEE; +const word CRC_MI_SCANSOUP = 0x2690; +const word CRC_MI_SCANIMPORT = 0x7CEA; +const word CRC_MI_SCANEXPORT = 0x9B4B; +const word CRC_WT_SCANPM = 0x988D; +const word CRC_MI_TAGLINE = 0x202B; +const word CRC_WT_CONFIRM = 0xFD14; +const word CRC_MI_CONFIRMYES = 0xAB96; +const word CRC_MI_CONFIRMNO = 0x74FD; +const word CRC_IL_CONFIRMINFO = 0xB10C; +const word CRC_ST_MSG = 0xB846; +const word CRC_ST_MSGS = 0x6080; +const word CRC_ST_PERSONAL = 0xADC6; +const word CRC_WT_GRP = 0xD2EA; +const word CRC_IL_FOUNDPERSONAL = 0xA039; +const word CRC_IL_NOPERSONAL = 0x2813; +const word CRC_ST_ESCORCONTINUE = 0x4800; +const word CRC_MS_SPELLCHECKER = 0x69B4; +const word CRC_WT_INS = 0x2F27; +const word CRC_MI_FILELISTFROM = 0xB710; +const word CRC_ST_INITIALIZING = 0x4C6B; +const word CRC_ST_CHECKING = 0xE219; +const word CRC_ST_LOCKSHARECAP = 0x4A28; +const word CRC_WT_ATTRTURNOFF = 0x06F5; +const word CRC_WT_TAGLINES = 0xD887; +const word CRC_ST_CHANGETAGLINE = 0x2605; +const word CRC_IL_NOTAGLINE = 0x2C24; +const word CRC_WT_CHARSETS = 0x9116; +const word CRC_ST_CHANGEXLATIMP = 0xAFC7; +const word CRC_MI_CHARSETAUTO = 0x897D; +const word CRC_IL_NOXLATIMPORT = 0x0707; +const word CRC_WT_N_A = 0x4ED2; +const word CRC_WT_WRITTEN = 0x6677; +const word CRC_WT_ARRIVED = 0x495D; +const word CRC_WT_RECEIVED = 0x1B2E; +const word CRC_IL_NONODELIST = 0x0ECB; +const word CRC_IL_NODELISTMISSING = 0x07F9; +const word CRC_IL_NODELISTOUTDATED = 0x229E; +const word CRC_MS_REPLYLINKER = 0x63CE; +const word CRC_WT_ENTERMSGNO = 0x18B0; +const word CRC_IL_WAITUUDECODING = 0x76F6; +const word CRC_IL_COMPLETEDUUDECODE = 0xD504; +const word CRC_IL_NOTUUENCODED = 0x4733; +const word CRC_IL_ERRORINSOUP = 0xF66D; +const word CRC_IL_WARNALREADYSENT = 0x5594; +const word CRC_IL_WAITLOCKED = 0x1C74; +const word CRC_ST_RETRYORESC = 0xE5FA; +const word CRC_ST_RETRYLOCK = 0x00B1; +const word CRC_ST_RETRYOPEN = 0xB039; +const word CRC_WT_TOUCHSEMAPHORE = 0x157D; +const word CRC_MI_WRITETOHDRNO = 0xB417; +const word CRC_MI_WRITETOHDRYES = 0x98DA; +const word CRC_MI_WRITETOHDRONLY = 0xDF56; +const word CRC_MI_CLIPBOARD = 0xB9AE; +const word CRC_MI_GOTONEXTNEW = 0xD614; +const word CRC_WT_FORWARD = 0x5902; +const word CRC_MI_FORWARDYES = 0x631F; +const word CRC_MI_FORWARDNO = 0xD7B0; +const word CRC_IL_UUEINVALIDPATH = 0x8aDB; +const word CRC_IL_PATHREPORT = 0x7F52; +const word CRC_IL_STYLECODESNO = 0xE43B; +const word CRC_IL_STYLECODESYES = 0xEE2F; +const word CRC_IL_STYLECODESHIDE = 0xD56B; +const word CRC_IL_WARNLOCKED = 0x87A6; +const word CRC_IL_NOTHREADLIST = 0x9193; +const word CRC_WT_SELECTMARKS = 0x3BC7; +const word CRC_WT_SELECTMARKSEDIT = 0x22BC; +const word CRC_IL_DROPMARKSINFO = 0x51F7; +const word CRC_WT_DROPMARKS = 0xCEA9; +const word CRC_MI_DROPALL = 0xC8B4; +const word CRC_MI_DROPMARKED = 0xCC6B; +const word CRC_MI_DROPCURRENT = 0xDE81; +const word CRC_MI_NODROP = 0x6C6A; +const word CRC_WT_CATCHAREAS = 0xC515; +const word CRC_MI_CATCHALL = 0xBA7F; +const word CRC_MI_CATCHMARKED = 0xB0AD; +const word CRC_MI_CATCHCURRENT = 0xA79A; +const word CRC_MI_NOCATCH = 0xA488; +const word CRC_WT_CROSSPOST = 0xFF8A; +const word CRC_MI_XCPROCESS = 0x0718; +const word CRC_MI_XCIGNORE = 0x8C5A; +const word CRC_MI_XCLISTFMT = 0x0F53; +const word CRC_WT_XCLIST = 0x8330; +const word CRC_MI_XCLISTRAW = 0x51E5; +const word CRC_MI_XCLISTVERBOSE = 0x6189; +const word CRC_MI_XCLISTLINE = 0x17E5; +const word CRC_MI_XCLISTREMOVE = 0x59AF; + +const word CRC_WT_ADDRESSBOOK = 0xFEF8; +const word CRC_WT_ADVANCEDSEARCH = 0xA8C9; +const word CRC_IL_NOMOREMATCHES = 0xD6CC; +const word CRC_WT_HEADEREDITHELP1 = 0x27A8; +const word CRC_WT_HEADEREDITHELP2 = 0x27AB; +const word CRC_WT_THREADLISTTITLE = 0x07CF; +const word CRC_WT_ADVANCEDMARKING = 0xF834; +const word CRC_ST_USERSTATUSLINE = 0x67D9; +const word CRC_WT_USERHEADERNAME = 0x54CD; +const word CRC_WT_USERHEADERORG = 0x83EE; +const word CRC_WT_USERHEADERAKA = 0x7B26; +const word CRC_IL_USERWAIT = 0xB687; + +const word CRC_MI_ALSELECTIONS1 = 0xBFEC; +const word CRC_MI_ALSELECTIONS2 = 0xBFEF; +const word CRC_IL_DECODE = 0x10D9; +const word CRC_IL_PREPARING = 0x2CD6; + +const word CRC_LAST_CRC = 0xFFFF; + + +// ------------------------------------------------------------------ + diff --git a/golded3/gcmisc.cpp b/golded3/gcmisc.cpp new file mode 100644 index 0000000..71d819f --- /dev/null +++ b/golded3/gcmisc.cpp @@ -0,0 +1,820 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Compilers for help, screen and xlat. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +int ReadHelpCfg(int force) { + + char* ptr; + long offset; + char buf[1024]; + FILE* ifp; + FILE* ofp; + Hlpr* HlpL; + int count; + int counter; + int comment; + + if((force > 1) or (FiletimeCmp(CFG->helpcfg.fn, CFG->helpged) > 0)) { + + ifp = fsopen(AddPath(CFG->goldpath, CFG->helpcfg.fn), "rb", CFG->sharemode); + if(ifp) { + setvbuf(ifp, NULL, _IOFBF, 8192); + ofp = fsopen(AddPath(CFG->goldpath, CFG->helpged), "wb", CFG->sharemode); + if(ofp) { + offset = 0L; + CFG->helpcfg.ft = GetFiletime(AddPath(CFG->goldpath, CFG->helpcfg.fn)); + + if(not quiet) + cout << "* Reading " << AddPath(CFG->goldpath, CFG->helpcfg.fn) << endl; + + setvbuf(ofp, NULL, _IOFBF, 8192); + + count = 0; + rewind(ifp); + + while(fgets(buf, sizeof(buf), ifp)) { + if(strnieql(buf, "*B ", 3)) + count++; + } + + HlpL = (Hlpr*)throw_calloc(count+2, sizeof(Hlpr)); + + rewind(ifp); + fputs("*I\r\n", ofp); + fwrite(HlpL, count+1, sizeof(Hlpr), ofp); + fputs("\r\n\r\n", ofp); + offset += 4 + ((count+1)*sizeof(Hlpr)) + 4; + + counter = 0; + comment = YES; + while(fgets(buf, sizeof(buf), ifp)) { + if(strnieql(buf, "*B ", 3)) { + comment = NO; + HlpL[counter].help = atow(buf+3); + ptr = strchr(buf, ','); + strbtrim(strcpy(HlpL[counter].category, ptr ? ptr+1 : "")); + HlpL[counter].offset = offset + strlen(buf); + counter++; + } + if(not comment) { + fputs(buf, ofp); + offset += strlen(buf); + } + if(strnieql(buf, "*E", 2)) + comment = YES; + } + HlpL[counter].offset = -1L; + + fseek(ofp, 0L, SEEK_SET); + fputs("*I\r\n", ofp); + fwrite(HlpL, count+1, sizeof(Hlpr), ofp); + + throw_free(HlpL); + fclose(ofp); + } + + fclose(ifp); + } + } + + // Init the help system + whelpdef(CFG->helpged, Key_F1, C_HELPB, C_HELPW, C_HELPQ, C_HELPS, NULL); + whelpwin(0, 0, MAXROW-2, MAXCOL-1, W_BHELP, NO); + whelpcat(H_General); + + return 0; +} + + +// ------------------------------------------------------------------ +// Window parts + +const word CRC_BLOCK = 0xC10C; +const word CRC_BORDER = 0x97A7; +const word CRC_BTYPE = 0x2A2F; +const word CRC_CURSOR = 0x0D67; +const word CRC_EDIT = 0xB32D; +const word CRC_HEADER = 0x6EED; +const word CRC_HIGHLIGHT = 0x5EBF; +const word CRC_INPUT = 0xA25E; +const word CRC_KLUDHIDD = 0x222E; +const word CRC_NOSELECT = 0x950C; +const word CRC_QUOTE = 0x75DA; +const word CRC_SELECTOR = 0x5604; +const word CRC_STATUS = 0x1D36; +const word CRC_TEARORIG = 0x428E; +const word CRC_TITLE = 0x636E; +const word CRC_WINDOW = 0xCEFE; + +const word CRC_FROM = 0x9290; +const word CRC_TO = 0x544F; +const word CRC_SUBJECT = 0xF861; +const word CRC_KLUDGE = 0xA600; +const word CRC_HIDDEN = 0xE465; +const word CRC_TAGLINE = 0xC328; +const word CRC_TEARLINE = 0xB385; +const word CRC_ORIGIN = 0x4CE5; +const word CRC_PAGEBAR = 0x4ECA; +const word CRC_UNREAD = 0xFE2A; +const word CRC_UNSENT = 0xC20B; +const word CRC_UNREADHIGH = 0x66D0; +const word CRC_UNSENTHIGH = 0xB4FD; +const word CRC_QUOTE2 = 0xF400; +const word CRC_SIGNATURE = 0x1A6E; + + +const word CRC_B = 0x0042; +const word CRC_I = 0x0049; +const word CRC_BI = 0x4249; +const word CRC_U = 0x0055; +const word CRC_BU = 0x4255; +const word CRC_IU = 0x4955; +const word CRC_BIU = 0x21D3; +const word CRC_R = 0x0052; +const word CRC_RB = 0x5242; +const word CRC_RI = 0x5249; +const word CRC_RBI = 0x38FE; +const word CRC_RU = 0x5255; +const word CRC_RBU = 0x38E2; +const word CRC_RIU = 0x33E2; +const word CRC_RBIU = 0x490E; +const word CRC_ALL = 0x14A9; + + +// ------------------------------------------------------------------ +// Colors + +const word CRC_BLACK = 0x20C2; +const word CRC_BLUE = 0xB7A3; +const word CRC_BROWN = 0xF575; +const word CRC_CYAN = 0xD20D; +const word CRC_DARKGRAY = 0x0D32; +const word CRC_DARKGREY = 0x0932; +const word CRC_DGRAY = 0x6ED8; +const word CRC_DGREY = 0x6AD8; +const word CRC_GREEN = 0xADCF; +const word CRC_LBLUE = 0xDF6F; +const word CRC_LCYAN = 0xBAC1; +const word CRC_LGRAY = 0xC779; +const word CRC_LGREEN = 0x8C61; +const word CRC_LGREY = 0xC379; +const word CRC_LIGHTBLUE = 0x053B; +const word CRC_LIGHTCYAN = 0x6095; +const word CRC_LIGHTGRAY = 0x1D2D; +const word CRC_LIGHTGREEN = 0xB256; +const word CRC_LIGHTGREY = 0x192D; +const word CRC_LIGHTMAGENTA = 0xBEA8; +const word CRC_LIGHTRED = 0xAED2; +const word CRC_LMAGENTA = 0xDE86; +const word CRC_LRED = 0x7752; +const word CRC_MAGENTA = 0xBF75; +const word CRC_NORMAL = 0x4DA2; +const word CRC_RED = 0x3FF3; +const word CRC_REVERSE = 0xB4CD; +const word CRC_UNDERLINE = 0xDC93; +const word CRC_WHITE = 0xD293; +const word CRC_YELLOW = 0xFEAF; + + +// ------------------------------------------------------------------ +// Window areas + +const word CRC_AREA = 0x010B; +const word CRC_ASK = 0x0BAE; +const word CRC_BACKGROUND = 0x1365; +const word CRC_BRAG = 0x505E; +const word CRC_HELP = 0xD054; +const word CRC_INFO = 0x5811; +const word CRC_MENU = 0x2DA4; +const word CRC_READER = 0x1DE1; +const word CRC_SHADOW = 0x2301; +const word CRC_STYLECODE = 0x8B6C; +const word CRC_STYLECODES = 0x4CB0; + + +// ------------------------------------------------------------------ +// Get color value + +int GetColor(char* ink) { + + word crc; + int color=0; + + crc = strCrc16(strupr(ink)); + switch(crc) { + // Black is the default + case CRC_BLACK: + color = 0; + break; + case CRC_BLUE: + color = 1; + break; + case CRC_GREEN: + color = 2; + break; + case CRC_CYAN: + color = 3; + break; + case CRC_RED: + color = 4; + break; + case CRC_MAGENTA: + color = 5; + break; + case CRC_BROWN: + color = 6; + break; + case CRC_LGRAY: + case CRC_LGREY: + case CRC_LIGHTGRAY: + case CRC_LIGHTGREY: + color = 7; + break; + case CRC_DGRAY: + case CRC_DGREY: + case CRC_DARKGRAY: + case CRC_DARKGREY: + color = 8; + break; + case CRC_LBLUE: + case CRC_LIGHTBLUE: + color = 9; + break; + case CRC_LGREEN: + case CRC_LIGHTGREEN: + color = 10; + break; + case CRC_LCYAN: + case CRC_LIGHTCYAN: + color = 11; + break; + case CRC_LRED: + case CRC_LIGHTRED: + color = 12; + break; + case CRC_LMAGENTA: + case CRC_LIGHTMAGENTA: + color = 13; + break; + case CRC_YELLOW: + color = 14; + break; + case CRC_WHITE: + color = 15; + break; + case CRC_UNDERLINE: + color = UNDERLINE; + break; + case CRC_NORMAL: + color = NORMAL; + break; + case CRC_HIGHLIGHT: + color = HIGHLIGHT; + break; + case CRC_REVERSE: + color = REVERSE; + break; + } + return(color); +} + + +// ------------------------------------------------------------------ +// Evaluates a color string + +int MakeColor(char* colors) { + + static int paper=0; + int ink=0, blink; + char* ink_; + char* paper_; + + #if defined(__UNIX__) or defined(__USE_NCURSES__) + blink = 0; + #else + blink = (stridela("blinking", colors) ? 128 : 0); + #endif + + ink_ = strtok(colors, " \t"); // Get the Ink color + if(ink_) { + ink = GetColor(ink_); + paper_ = strtok(NULL, " \t"); // Skip the "On" + if(paper_) { + paper_ = strtok(NULL, " \t"); // Get the Paper color + if(paper_) + paper = GetColor(paper_); + } + } + + if(paper > 7) + CFG->intensecolors = true; + + return ink | paper*16 | blink; +} + + +// ------------------------------------------------------------------ +// Get color values + +void GetColors(char* value) { + + word crc; + Win* wptr; + int attr; + char buf[256]; + char* win; + char* colors; + char* part=NULL; + + *buf = NUL; + if((win = strtok(value, " \t")) == NULL) + return; + + if(stricmp(win, "shadow")) { + part = strtok(NULL, " \t"); + if(part == NULL) + return; + } + + do { + colors = strtok(NULL, " \t\n"); + if(colors != NULL) { + strcat(buf, colors); + strcat(buf, " "); + } + } while(colors != NULL); + + crc = strCrc16(strupr(win)); + attr = MakeColor(buf); + switch(crc) { + case CRC_SHADOW: + C_SHADOW = attr; + return; + case CRC_BACKGROUND: + wptr = &GC_BACK_; + break; + case CRC_STATUS: + wptr = &GC_STAT_; + break; + case CRC_BRAG: + wptr = &GC_BRAG_; + break; + case CRC_AREA: + wptr = &GC_AREA_; + break; + case CRC_READER: + wptr = &GC_READ_; + break; + case CRC_HEADER: + wptr = &GC_HEAD_; + break; + case CRC_ASK: + wptr = &GC_ASK__; + break; + case CRC_MENU: + wptr = &GC_MENU_; + break; + case CRC_HELP: + wptr = &GC_HELP_; + break; + case CRC_INFO: + wptr = &GC_INFO_; + break; + case CRC_STYLECODE: + case CRC_STYLECODES: + wptr = &GC_STYLE_; + break; + default: + return; + } + + crc = strCrc16(strupr(part)); + switch(crc) { + case CRC_WINDOW: + wptr->_Window = attr; + if(wptr == &GC_HEAD_) { + wptr->_From = attr; + wptr->_To = attr; + wptr->_Subject = attr; + } + if(wptr == &GC_READ_) { + wptr->_Tagline = attr; + GC_STYLE_._Bold = attr; + GC_STYLE_._Italic = attr; + GC_STYLE_._BoldItalic = attr; + GC_STYLE_._Underscore = attr; + GC_STYLE_._BoldUnderscore = attr; + GC_STYLE_._ItalicUnderscore = attr; + GC_STYLE_._BoldItalicUnderscore = attr; + GC_STYLE_._Reverse = attr; + GC_STYLE_._ReverseBold = attr; + GC_STYLE_._ReverseItalic = attr; + GC_STYLE_._ReverseBoldItalic = attr; + GC_STYLE_._ReverseUnderscore = attr; + GC_STYLE_._ReverseBoldUnderscore = attr; + GC_STYLE_._ReverseItalicUnderscore = attr; + GC_STYLE_._ReverseBoldItalicUnderscore = attr; + } + break; + case CRC_BORDER: + wptr->_Border = attr; + wptr->_Pagebar = attr; + break; + case CRC_BTYPE: + wptr->btype = atoi(buf); + break; + case CRC_TITLE: + wptr->_Title = attr; + break; + case CRC_SELECTOR: + wptr->_Selector = attr; + break; + case CRC_HIGHLIGHT: + wptr->_Highlight = attr; + break; + case CRC_NOSELECT: + wptr->_Noselect = attr; + break; + case CRC_QUOTE: + wptr->_Quote = attr; + break; + case CRC_CURSOR: + wptr->_Cursor = attr; + break; + case CRC_KLUDHIDD: + wptr->_Kludge = attr; + wptr->_Hidden = attr; + break; + case CRC_TEARORIG: + wptr->_Tearline = attr; + wptr->_Origin = attr; + break; + case CRC_EDIT: + wptr->_Edit = attr; + break; + case CRC_BLOCK: + wptr->_Block = attr; + break; + case CRC_INPUT: + wptr->_Input = attr; + break; + case CRC_FROM: + wptr->_From = attr; + break; + case CRC_TO: + wptr->_To = attr; + break; + case CRC_SUBJECT: + wptr->_Subject = attr; + break; + case CRC_KLUDGE: + wptr->_Kludge = attr; + break; + case CRC_HIDDEN: + wptr->_Hidden = attr; + break; + case CRC_TAGLINE: + wptr->_Tagline = attr; + break; + case CRC_TEARLINE: + wptr->_Tearline = attr; + break; + case CRC_ORIGIN: + wptr->_Origin = attr; + break; + case CRC_PAGEBAR: + wptr->_Pagebar = attr; + break; + case CRC_UNREAD: + wptr->_WindowUnread = attr; + break; + case CRC_UNSENT: + wptr->_WindowUnsent = attr; + break; + case CRC_UNREADHIGH: + wptr->_HighlightUnread = attr; + break; + case CRC_QUOTE2: + if(wptr == &GC_READ_) + GC_READ2_._Quote2 = attr; + break; + case CRC_SIGNATURE: + if(wptr == &GC_READ_) + GC_READ2_._Signature = attr; + break; + case CRC_UNSENTHIGH: + wptr->_HighlightUnsent = attr; + break; + case CRC_B: wptr->_Bold = attr; break; + case CRC_I: wptr->_Italic = attr; break; + case CRC_BI: wptr->_BoldItalic = attr; break; + case CRC_U: wptr->_Underscore = attr; break; + case CRC_BU: wptr->_BoldUnderscore = attr; break; + case CRC_IU: wptr->_ItalicUnderscore = attr; break; + case CRC_BIU: wptr->_BoldItalicUnderscore = attr; break; + case CRC_R: wptr->_Reverse = attr; break; + case CRC_RB: wptr->_ReverseBold = attr; break; + case CRC_RI: wptr->_ReverseItalic = attr; break; + case CRC_RBI: wptr->_ReverseBoldItalic = attr; break; + case CRC_RU: wptr->_ReverseUnderscore = attr; break; + case CRC_RBU: wptr->_ReverseBoldUnderscore = attr; break; + case CRC_RIU: wptr->_ReverseItalicUnderscore = attr; break; + case CRC_RBIU: wptr->_ReverseBoldItalicUnderscore = attr; break; + case CRC_ALL: + if(wptr == &GC_STYLE_) { + wptr->_Bold = attr; + wptr->_Italic = attr; + wptr->_BoldItalic = attr; + wptr->_Underscore = attr; + wptr->_BoldUnderscore = attr; + wptr->_ItalicUnderscore = attr; + wptr->_BoldItalicUnderscore = attr; + wptr->_Reverse = attr; + wptr->_ReverseBold = attr; + wptr->_ReverseItalic = attr; + wptr->_ReverseBoldItalic = attr; + wptr->_ReverseUnderscore = attr; + wptr->_ReverseBoldUnderscore = attr; + wptr->_ReverseItalicUnderscore = attr; + wptr->_ReverseBoldItalicUnderscore = attr; + } + break; + default: + return; + } +} + + +// ------------------------------------------------------------------ +// Compare escape table items + +static int CmpEsc(const char* a, const char* b) { + + return strncmp(a, b, 5); +} + + +// ------------------------------------------------------------------ +// Read the translation tables + +void ReadXlatTables() { + + if(not CFG->xlatcharset.empty() or not CFG->xlatescset.empty()) { + + Esc EscTable; + Chs ChsTable; + char buf[256]; + char* ptr; + char* ptr2; + FILE *ifp, *ofp; + int line, n, x, y, ch=0; + + ofp = fsopen(AddPath(CFG->goldpath, CFG->xlatged), "wb", CFG->sharemode); + if(ofp) { + + // Compile CHARSET tables + vector::iterator xlt; + for(xlt = CFG->xlatcharset.begin(); xlt != CFG->xlatcharset.end(); xlt++) { + + // Assign table defaults + memset(&ChsTable, 0, sizeof(Chs)); + for(n=0; n<256; n++) { + ChsTable.t[n][0] = 1; + ChsTable.t[n][1] = (unsigned char)n; // The character + } + strcpy(buf, AddPath(CFG->xlatpath, xlt->mapfile)); + ifp = fsopen(buf, "rb", CFG->sharemode); + if(ifp) { + + if(not quiet) + cout << "* Reading " << buf << endl; + + // Read the definition file + line = 1; + while(fgets(buf, sizeof(buf), ifp)) { + ptr = buf; + if(*ptr != ';' and not strblank(ptr)) { + if((ptr2 = strchr(ptr+2, ';')) != NULL) + *ptr2 = NUL; + strtrim(ptr); + if(line < 6) { + switch(line) { + case 1: + ChsTable.id = atol(ptr); + break; + case 2: + ChsTable.version = atoi(ptr); + break; + case 3: + ChsTable.level = atoi(ptr); + if((ChsTable.level == 1) or (ChsTable.id > 65535L)) + ch = 0; + else + ch = 128; + break; + case 4: + strcpy(ChsTable.imp, strbtrim(ptr)); + break; + case 5: + if(ChsTable.level) + sprintf(ChsTable.exp, "%s %d", strbtrim(ptr), ChsTable.level); + else + strcpy(ChsTable.exp, strbtrim(ptr)); + break; + } + } + else { + ptr = strskip_wht(ptr); + if(ch > 255 or strieql(ptr, "END")) // End of table reached + break; + x = 0; + ChsTable.t[ch][0] = (byte)x; + while(*ptr and x < 3) { + if(*ptr == '\\') { + ptr++; + switch(*ptr) { + case '\\': + ChsTable.t[ch][++x] = (byte)'\\'; + ChsTable.t[ch][0] = (byte)x; + ptr = strskip_txt(ptr); + break; + case 'd': + y = (unsigned char)atoi(ptr+1); + ChsTable.t[ch][++x] = (byte)y; + ChsTable.t[ch][0] = (byte)x; + ptr = strskip_txt(ptr); + break; + case 'x': + y = (unsigned char)atox(ptr+1); + ChsTable.t[ch][++x] = (byte)y; + ChsTable.t[ch][0] = (byte)x; + ptr = strskip_txt(ptr); + break; + case '0': + ptr = strskip_txt(ptr); + break; + } + } + else { + ChsTable.t[ch][++x] = (byte)*ptr++; + ChsTable.t[ch][0] = (byte)x; + } + ptr = strskip_wht(ptr); + } + ch++; + } + line++; + } + } + fclose(ifp); + } + + fwrite(&ChsTable, sizeof(Chs), 1, ofp); + } + + // Compile ESCSET tables + for(xlt = CFG->xlatescset.begin(); xlt != CFG->xlatescset.end(); xlt++) { + + // Assign defaults + memset(&EscTable, 0, sizeof(Esc)); + strcpy(buf, AddPath(CFG->xlatpath, xlt->mapfile)); + ifp = fsopen(buf, "rb", CFG->sharemode); + if(ifp) { + + if(not quiet) + cout << "* Reading " << buf << endl; + + // Read the definition file + line = 1; + while(fgets(buf, sizeof(buf), ifp)) { + ptr = buf; + if(*ptr != ';' and not strblank(ptr)) { + if((ptr2 = strchr(ptr+2, ';')) != NULL) + *ptr2 = NUL; + strtrim(ptr); + if(line < 2) { + switch(line) { + case 1: + strcpy(EscTable.exp, strbtrim(ptr)); + break; + } + } + else { + n = EscTable.size; + if(n > 255 or strieql(ptr, "END")) // End of table reached + break; + EscTable.t[n][0] = ptr[0]; + EscTable.t[n][1] = ptr[1]; + x = 2; + ptr += 2; + ptr = strskip_wht(ptr); + while(*ptr and x < 5) { + if(*ptr == '\\') { + ptr++; + switch(*ptr) { + case '\\': + EscTable.t[n][x++] = '\\'; + ptr = strskip_txt(ptr); + break; + case 'd': + EscTable.t[n][x++] = (unsigned char)atoi(ptr+1); + ptr = strskip_txt(ptr); + break; + case 'x': + EscTable.t[n][x++] = (unsigned char)atox(ptr+1); + ptr = strskip_txt(ptr); + break; + case '0': + EscTable.t[n][x++] = NUL; + ptr = strskip_txt(ptr); + break; + } + } + else { + EscTable.t[n][x++] = *ptr++; + } + ptr = strskip_wht(ptr); + } + EscTable.size++; + } + line++; + } + } + + qsort(EscTable.t, EscTable.size, 5, (StdCmpCP)CmpEsc); + + fclose(ifp); + } + + fwrite(&EscTable, sizeof(Esc), 1, ofp); + } + + fclose(ofp); + } + } +} + + +// ------------------------------------------------------------------ + +void CookieIndex(char* textfile, char* indexfile) { + + FILE* ifp = fsopen(textfile, "rb", CFG->sharemode); + if(ifp) { + setvbuf(ifp, NULL, _IOFBF, 32000); + FILE* ofp = fsopen(indexfile, "wb", CFG->sharemode); + if(ofp) { + setvbuf(ofp, NULL, _IOFBF, 16000); + char buf[256]; + long fpos = 0; + long tpos = 0; + bool was_blank = false; + while(fgets(buf, sizeof(buf), ifp)) { + if(strblank(buf)) { + fwrite(&fpos, sizeof(long), 1, ofp); + fpos = tpos + strlen(buf); + was_blank = true; + } + else { + was_blank = false; + } + tpos += strlen(buf); + } + if(not was_blank) + fwrite(&fpos, sizeof(long), 1, ofp); + fclose(ofp); + } + fclose(ifp); + } +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gcprot.h b/golded3/gcprot.h new file mode 100644 index 0000000..dd450c1 --- /dev/null +++ b/golded3/gcprot.h @@ -0,0 +1,371 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Prototypes for the configuration keyword functions. +// ------------------------------------------------------------------ + + +#ifndef __GCPROT_H +#define __GCPROT_H + + +// ------------------------------------------------------------------ + +void CfgAddress (); +void CfgAddressbookadd (); +void CfgAddresslookupfirst(); +void CfgAddressmacro (); +void CfgAdeptxbbspath (); +void CfgAdeptxbbsuserno (); +void CfgAkamatch (); +void CfgAkamatchecho (); +void CfgAkamatching (); +void CfgAkamatchlocal (); +void CfgAkamatchnet (); +void CfgArea (); +void CfgAreaautoid (); +void CfgAreaautonext (); +void CfgAreacfmreplyto (); +void CfgAreacopyaddid (); +void CfgAreacopydirect (); +void CfgAreacopyto (); +void CfgAreadef (); +void CfgAreadesc (); +void CfgAreaexcl (); +void CfgAreafilegroups (); +void CfgAreaforwarddirect(); +void CfgAreafreqdirect (); +void CfgAreafreqto (); +void CfgAreaincl (); +void CfgAreaisemail (); +void CfgAreaisnews (); +void CfgAreakeeplast (); +void CfgArealistechomax (); +void CfgArealistformat (); +void CfgArealistgroupid (); +void CfgArealistnos (); +void CfgArealistpagebar (); +void CfgArealistscan (); +void CfgArealistsort (); +void CfgArealisttype (); +void CfgAreapath (); +void CfgAreapmscan (); +void CfgAreapmscanexcl (); +void CfgAreapmscanincl (); +void CfgAreareadonly (); +void CfgArearename (); +void CfgAreareplydirect (); +void CfgAreareplyto (); +void CfgAreascan (); +void CfgAreascanexcl (); +void CfgAreascanincl (); +void CfgAreascansort (); +void CfgAreasep (); +void CfgAreastart (); +void CfgAreatypeorder (); +void CfgAreayouwroteto (); +void CfgAskdelorig (); +void CfgAttachpath (); +void CfgAttribsattach (); +void CfgAttribscc (); +void CfgAttribscfm (); +void CfgAttribsecho (); +void CfgAttribsemail (); +void CfgAttribsfrq (); +void CfgAttribslocal (); +void CfgAttribsnet (); +void CfgAttribsnews (); +void CfgAttributes (); +void CfgBeepcomment (); +void CfgBeeplocalmsg (); +void CfgBeepnoises (); +void CfgBeepfactor (); +void CfgBeepyourmail (); +void CfgCarboncopylist (); +void CfgColor (); +void CfgColorset (); +void CfgColor (); +void CfgConfirmfile (); +void CfgConfirmresponse (); +void CfgCookiepath (); +void CfgCrosspost (); +void CfgCrosspostlist (); +void CfgCtrlinfo (); +void CfgCtrlinfoecho (); +void CfgCtrlinfoemail (); +void CfgCtrlinfolocal (); +void CfgCtrlinfonet (); +void CfgCtrlinfonews (); +void CfgDispareano (); +void CfgDispattachsize (); +void CfgDispautonext (); +void CfgDisphdrdateset (); +void CfgDisphdrnameset (); +void CfgDisphdrnodeset (); +void CfgDisplistcursor (); +void CfgDisplistwrap (); +void CfgDisplocalhigh (); +void CfgDispmargin (); +void CfgDispmsgsize (); +void CfgDisppagebar (); +void CfgDisprealmsgno (); +void CfgDispsoftcr (); +void CfgDispstatusline (); +void CfgDisptabsize (); +void CfgDosprompt (); +void CfgEditautoattach (); +void CfgEditautosave (); +void CfgEditchangedate (); +void CfgEditcharpara (); +void CfgEditcharspace (); +void CfgEditcomment (); +void CfgEditcompletion (); +void CfgEditcrlfterm (); +void CfgEditfieldclear (); +void CfgEdithardline (); +void CfgEdithardlines (); +void CfgEdithardterm (); +void CfgEdithdrnameset (); +void CfgEdithdrnodeset (); +void CfgEditheaderattrs (); +void CfgEditheaderfirst (); +void CfgEditinternal (); +void CfgEditmenu (); +void CfgEditmixcase (); +void CfgEditmsgsize (); +void CfgEditor (); +void CfgEditorfile (); +void CfgEditquotemargin (); +void CfgEditreplyre (); +void CfgEditsavemenu (); +void CfgEditsaveutil (); +void CfgEditsoftcrxlat (); +void CfgEditspellcheck (); +void CfgEditundelete (); +void CfgEmptytearline (); +void CfgEncodeemailheaders(); +void CfgEndgroup (); +void CfgEvent (); +void CfgExcludenodes (); +void CfgExternoptions (); +void CfgExternutil (); +void CfgEzycommsgbase (); +void CfgEzycomuserbase (); +void CfgEzycomuserno (); +void CfgFidohwmarks (); +void CfgFidolastread (); +void CfgFidomsgtype (); +void CfgFidonullfix (); +void CfgFidouserlist (); +void CfgFidouserno (); +void CfgFilealias (); +void CfgFilelistpagebar (); +void CfgFollowupto (); +void CfgForcetemplate (); +void CfgFrqext (); +void CfgFrqnodemap (); +void CfgFrqoptions (); +void CfgFrqwazoo (); +void CfgGedhandshake (); +void CfgGermankeyboard (); +void CfgGoldbasepath (); +void CfgGoldbasesyspath (); +void CfgGoldbaseuserno (); +void CfgGoldpath (); +void CfgGroup (); +void CfgHappybirthday (); +void CfgHighlightunread (); +void CfgHudsonpath (); +void CfgHudsonsizewarn (); +void CfgHudsonsyspath (); +void CfgHudsonuserno (); +void CfgIgnorecharset (); +void CfgImportbegin (); +void CfgImportend (); +void CfgInboundpath (); +void CfgIncludenodes (); +void CfgInputfile (); +void CfgIntensecolors (); +void CfgInternetaddress (); +void CfgInternetdomain (); +void CfgInternetgate (); +void CfgInternetlookup (); +void CfgInternetmsgid (); +void CfgInternetreply (); +void CfgInternetrfcbody (); +void CfgInternetserver (); +void CfgInvalidate (); +void CfgJamharddelete (); +void CfgJampath (); +void CfgKeybclear (); +void CfgKeybdefaults (); +void CfgKeybext (); +void CfgKeybmode (); +void CfgKeybstack (); +void CfgKludge (); +void CfgKludgechrs (); +void CfgLoadlanguage (); +void CfgLogfile (); +void CfgLogformat (); +void CfgLookupecho (); +void CfgLookuplocal (); +void CfgLookupnet (); +void CfgLookupuserbase (); +void CfgMailinglist (); +void CfgMailtoss (); +void CfgMappath (); +void CfgMember (); +void CfgMenudropmsg (); +void CfgMenumarked (); +void CfgMouse (); +void CfgMsglistdate (); +void CfgMsglistfast (); +void CfgMsglistfirst (); +void CfgMsglistheader (); +void CfgMsglistpagebar (); +void CfgMsglistviewsubj (); +void CfgMsglistwidesubj (); +void CfgNamesfile (); +void CfgNewsgroups (); +void CfgNickname (); +void CfgNodelist (); +void CfgNodelistwarn (); +void CfgNodepath (); +void CfgNodepathfd (); +void CfgNodepathfd (); +void CfgNodepathv7 (); +void CfgNodev7flags (); +void CfgNodev7modem (); +void CfgOrganization (); +void CfgOrigin (); +void CfgOutboundpath (); +void CfgOutputfile (); +void CfgPathreportfile (); +void CfgPcboardpath (); +void CfgPcboarduserno (); +void CfgPersonalmail (); +void CfgPlay (); +void CfgPrintdevice (); +void CfgPrintinit (); +void CfgPrintlength (); +void CfgPrintmargin (); +void CfgPrintreset (); +void CfgQuoteblank (); +void CfgQuotectrl (); +void CfgQuotebuffile (); +void CfgQuotebufmode (); +void CfgQuotechars (); +void CfgQuotemargin (); +void CfgQuotespacing (); +void CfgQuotestring (); +void CfgQuotewraphard (); +void CfgQwkbadmsgs (); +void CfgQwkconfmap (); +void CfgQwkexportpath (); +void CfgQwkimportpath (); +void CfgQwkoptions (); +void CfgQwkreplylinker (); +void CfgQwktosslog (); +void CfgRa2usersbbs (); +void CfgReplylink (); +void CfgReplylinklist (); +void CfgReplyto (); +void CfgRobotname (); +void CfgScreenblanker (); +void CfgScreenmaxcol (); +void CfgScreenmaxrow (); +void CfgScreenpalette (); +void CfgScreenshadows (); +void CfgScreensize (); +void CfgScreenusebios (); +void CfgSearchfor (); +void CfgSemaphore (); +void CfgSharemode (); +void CfgShowdeleted (); +void CfgSounddevice (); +void CfgSoundpath (); +void CfgSoupbadmsgs (); +void CfgSoupemail (); +void CfgSoupexportmargin (); +void CfgSoupexportpath (); +void CfgSoupimportpath (); +void CfgSoupnewsrcfile (); +void CfgSoupreplylinker (); +void CfgSoupreplyto (); +void CfgSouptosslog (); +void CfgSquishdirect (); +void CfgSquishscan (); +void CfgSquishuserno (); +void CfgSquishuserpath (); +void CfgStatuslineclock (); +void CfgStatuslinehelp (); +void CfgStylecodes (); +void CfgStylecodepunct (); +void CfgStylecodestops (); +void CfgTagline (); +void CfgTaglinechar (); +void CfgTaglinesupport (); +void CfgTasktitle (); +void CfgTearline (); +void CfgTemplate (); +void CfgTemplatematch (); +void CfgTemplatepath (); +void CfgTemppath (); +void CfgTimeout (); +void CfgTimeoutsavemsg (); +void CfgTitlestatus (); +void CfgTwitmode (); +void CfgTwitname (); +void CfgTwitsubj (); +void CfgTwitto (); +void CfgUsecharset (); +void CfgUseflags (); +void CfgUsefwd (); +void CfgUseintl (); +void CfgUsemsgid (); +void CfgUsepid (); +void CfgUserlist (); +void CfgUserlistfile (); +void CfgUsername (); +void CfgUsetzutc (); +void CfgUudecodepath (); +void CfgViewhidden (); +void CfgViewkludge (); +void CfgViewquote (); +void CfgWhoto (); +void CfgWildcatuserno (); +void CfgXlatcharset (); +void CfgXlatescset (); +void CfgXlatexport (); +void CfgXlatimport (); +void CfgXlatlocalset (); +void CfgXlatpath (); +void CfgZonegating (); + + +// ------------------------------------------------------------------ + +#endif + +// ------------------------------------------------------------------ + diff --git a/golded3/geall.h b/golded3/geall.h new file mode 100644 index 0000000..e4a8000 --- /dev/null +++ b/golded3/geall.h @@ -0,0 +1,1052 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Definition of system-wide sizes and structures. +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ + +#if defined(GOLD_CANPACK) +#pragma pack(1) +#endif + + +// ------------------------------------------------------------------ +// General data/list size limits + +const uint MAX_COMM = 25; // Editor comments +const uint MAX_FIND = 10; // Max number of search strings + + +// ------------------------------------------------------------------ +// Header attach size types + +const int ATTACH_BYTES = 1; +const int ATTACH_KBYTES = 2; + + +// ------------------------------------------------------------------ +// Control info types + +const int CI_NONE = 0x0000; +const int CI_TEAR = 0x0001; +const int CI_ORIG = 0x0002; +const int CI_TAGL = 0x0004; + + +// ------------------------------------------------------------------ +// Misc mode types (ACK!! these need cleaning up!) + +const int MODE_AREACONF = 100; +const int MODE_CONFIRM = 101; +const int MODE_COPY = 102; +const int MODE_FORWARD = 103; +const int MODE_MOVE = 108; +const int MODE_QUOTE = 109; +const int MODE_QUOTEBUF = 110; +const int MODE_REPLY = 111; +const int MODE_REPLYCOMMENT = 112; +const int MODE_SAVE = 114; +const int MODE_SAVENOCTRL = 115; +const int MODE_VIEW = 116; +const int MODE_WRITE = 117; +const int MODE_PRINT = 118; +const int MODE_APPEND = 119; + +const int MODE_NEW = 0x0100; +const int MODE_CHANGE = 0x0200; +const int MODE_UPDATE = 0x0400; +const int MODE_QUIT = 0x0800; + +const int MODE_PREVIOUS = 2; +const int MODE_MARKED = 1; +const int MODE_CURRENT = 0; +const int MODE_DONT = -1; + + +// ------------------------------------------------------------------ +// Scanning constants + +const int SCAN_STARTUP = 0; +const int SCAN_ALL = 1; +const int SCAN_MARKED = 2; +const int SCAN_CURRENT = 3; +const int SCAN_MATCHING = 4; +const int SCAN_UNSCANNED = 5; +const int SCAN_EXPORTQWK = 6; +const int SCAN_IMPORTQWK = 7; +const int SCAN_EXPORTSOUP = 8; +const int SCAN_IMPORTSOUP = 9; +const int SCAN_LIST = 10; +const int SCAN_GROUP = 11; +const int SCAN_NETMAIL = 12; +const int SCAN_QUIT = 99; + + +// ------------------------------------------------------------------ +// Exit errorcodes + +const int EXIT_OK = 0x00; +const int EXIT_LOCAL = 0x01; +const int EXIT_NET = 0x02; +const int EXIT_ECHO = 0x04; +const int EXIT_NONAME = 0x20; +const int EXIT_CFGERR = 0x21; +const int EXIT_ERRORS = 0x22; + + +// ------------------------------------------------------------------ +// Direction defines + +const int DIR_PREV = -1; +const int DIR_NEXT = 1; + +const int DIR_ABOVE = DIR_PREV; +const int DIR_BELOW = DIR_NEXT; + + +// ------------------------------------------------------------------ +// Misc screen limits + +#define MINROW 6 +#define MAXCOL gvid->numcols +#define MAXROW gvid->numrows +#define MAXMSGLINES (MAXROW-MINROW-1) + + +// ------------------------------------------------------------------ +// Message marking + +const char MMRK_MARK = '\x10'; +const char MMRK_BOOK = '\x11'; + + +// ------------------------------------------------------------------ +// Twit options + +const int NOT_TWIT = 0; +const int TWIT_SHOW = 1; +const int TWIT_BLANK = 2; +const int TWIT_SKIP = 3; +const int TWIT_IGNORE = 4; +const int TWIT_KILL = 5; + + +// ------------------------------------------------------------------ +// CC list options + +const int CC_REMOVE = 0; +const int CC_HIDDEN = 1; +const int CC_VISIBLE = 2; +const int CC_NAMES = 3; +const int CC_KEEP = 4; + + +// ------------------------------------------------------------------ +// Arealist types + +const int AL_TOTLST = 0; +const int AL_TOTNEW = 1; + + +// ------------------------------------------------------------------ +// Area R/O modes + +const int READONLY_SOFT = 1; +const int READONLY_HARD = 2; + + +// ------------------------------------------------------------------ +// Colorset types + +const int CS_NORMAL = 0; +const int CS_INTENSE = 1; +const int CS_MONO = 2; + + +// ------------------------------------------------------------------ +// Lookup types + +const int LOOK_DEST = 0; +const int LOOK_ORIG = 1; +const int LOOK_NAME = 2; + + +// ------------------------------------------------------------------ +// Squish scanning types + +//const int SQS_API = 1; +//const int SQS_QUICK = 2; + + +// ------------------------------------------------------------------ +// Quotebuffer modes + +const int QBUF_ASK = 1; +const int QBUF_APPEND = 2; +const int QBUF_OVERWRITE = 3; + + +// ------------------------------------------------------------------ +// Screenblanker types + +const int BLANK_ALLBLACK = 0; +const int BLANK_SLIDEWIN = 1; + + +// ------------------------------------------------------------------ +// DISPMSGSIZE types + +const int DISPMSGSIZE_BYTES = 1; +const int DISPMSGSIZE_KBYTES = 2; + + +// ------------------------------------------------------------------ +// Replylink types + +const int REPLYLINK_CHAIN = 0; +const int REPLYLINK_DIRECT = 1; + +const int REPLYLINKLIST_FAST = 0; +const int REPLYLINKLIST_FULL = 1; + + +// ------------------------------------------------------------------ + +#define GSWAP_ENABLED 0x8000 +#define GSWAP_DISK (GSWAP_ENABLED|USE_FILE) +#define GSWAP_EMS (GSWAP_ENABLED|USE_EMS) +#define GSWAP_XMS (GSWAP_ENABLED|USE_XMS) +#define GSWAP_ALL (GSWAP_ENABLED|USE_ALL) +#define GSWAP_NONE 0 +#define GSWAP_EMS_FIRST EMS_FIRST +#define GSWAP_XMS_FIRST XMS_FIRST +#define GSWAP_HIDE_FILE HIDE_FILE +#define GSWAP_NO_PREALLOC NO_PREALLOC +#define GSWAP_CHECK_NET CHECK_NET + + +// ------------------------------------------------------------------ + +const int KEYB_BLOCK = 0; +const int KEYB_POLL = 1; + + +// ------------------------------------------------------------------ +// Registration key valid OS + +const int GKEY_VALID_DOS = 0x0001; +const int GKEY_VALID_OS2 = 0x0002; +const int GKEY_VALID_W32 = 0x0004; +const int GKEY_VALID_LNX = 0x0008; +const int GKEY_VALID_WIN = 0x0010; +const int GKEY_VALID_OPM = 0x0020; +const int GKEY_VALID_XWN = 0x0040; + + +// ------------------------------------------------------------------ +// File request options + +const int FREQ_SORT = 0x0001; +const int FREQ_FROMTOP = 0x0002; +const int FREQ_NOFILES = 0x0004; +const int FREQ_FAST = 0x0008; +const int FREQ_NOWAZOOMSG = 0x0010; +const int FREQ_USEFLOWFILE = 0x0020; + + +// ------------------------------------------------------------------ +// Automatic echoid names + +const int AUTOID_VERBOSE = 0; +const int AUTOID_SHORT = 1; +const int AUTOID_LONG = 2; + + +// ------------------------------------------------------------------ +// Values for EDITHEADERFIRST + +const int EDITHEADERFIRST_NO = 0x0000; +const int EDITHEADERFIRST_NEW = 0x0001; +const int EDITHEADERFIRST_CHANGES = 0x0002; +const int EDITHEADERFIRST_REPLIES = 0x0004; +const int EDITHEADERFIRST_FORWARDS = 0x0008; +const int EDITHEADERFIRST_YES = 0x000F; + + +// ------------------------------------------------------------------ +// Values for MSGLISTDATE + +const int MSGLISTDATE_NONE = 0; +const int MSGLISTDATE_WRITTEN = 1; +const int MSGLISTDATE_ARRIVED = 2; +const int MSGLISTDATE_RECEIVED = 3; + + +// ------------------------------------------------------------------ +// Write constants + +const int WRITE_CURRENT = 0; +const int WRITE_MARKED = 1; +const int WRITE_QUIT = -1; +const int WRITE_FILE = 1; +const int WRITE_PRINTER = 2; +const int WRITE_CLIPBRD = 4; +const int WRITE_NO_HEADER = 8; +const int WRITE_ONLY_HEADER = 16; + + +// ------------------------------------------------------------------ +// Values for REPLYRE + +const int REPLYRE_NO = 0; +const int REPLYRE_YES = 1; +const int REPLYRE_NUMERIC = 2; + + +// ------------------------------------------------------------------ +// Name typedefs + +typedef char Name[36]; + + +// ------------------------------------------------------------------ +// Combined name/address structure + +struct Node { + Name name; + Addr addr; + Node& operator=(const Node& a) { strcpy(name, a.name); addr=a.addr; return *this; } +}; + + +// ------------------------------------------------------------------ +// Tearline typedefs + +typedef char Tear[77]; + + +// ------------------------------------------------------------------ +// Subject typedefs + +typedef char Subj[128]; + + +// ------------------------------------------------------------------ +// Internet address typedefs + +typedef char IAdr[128]; + + +// ------------------------------------------------------------------ +// Internet subject typedefs + +typedef char XlatName[17]; + + +// ------------------------------------------------------------------ +// Template typedefs + +struct Tpl { + Path file; + Desc name; + Addr match; +}; + + +// ------------------------------------------------------------------ +// Echo rename struct + +class EchoRen { +public: + string from; + string to; + EchoRen() {} + EchoRen(const char *_from, const char *_to) { from = _from; to = _to; } + ~EchoRen() {} + EchoRen& operator=(const EchoRen& a) { from = a.from; to = a.to; return *this; } +}; + + +// ------------------------------------------------------------------ +// Filename aliases + +struct FileAlias { + char alias[9]; + Path file; + FileAlias& operator=(const FileAlias& a) { + strxcpy(alias, a.alias, sizeof(alias)); + strxcpy(file, a.file, sizeof(Path)); + return *this; + } +}; + + +// ------------------------------------------------------------------ +// Address macro record + +struct AddrMacro { + char macro[20]; + IAdr name; + Addr addr; + Subj subj; + Attr attr; +}; + + +// ------------------------------------------------------------------ +// Sound effect defines + +const int SND_THEEND = 0; +const int SND_GOTIT = 1; +const int SND_TOOBAD = 2; +const int SND_TOYOU = 3; +const int SND_S_O_S = 4; +const int SND_SAYBIBI = 5; + + +// ------------------------------------------------------------------ +// Event command "Play". Types and structure + +const byte PLAY_NO = 0; // * No sound +const byte PLAY_DOS = 1; // + DOS beeping and effects +const byte PLAY_VOC = 2; // * Creative Technology Voice samples +const byte PLAY_CMF = 3; // + Creative Technology FM songs +const byte PLAY_WAV = 4; // + MPIDS (Multimedia) WAVE samples +const byte PLAY_SAM = 5; // + Raw sample without any header +const byte PLAY_MID = 6; // - MIDI songs +const byte PLAY_ROL = 7; // - Adlib songs +const byte PLAY_SNG = 8; // - Sequencer plus Jr. songs +const byte PLAY_MOD = 9; // - ProTracker MOD songs +const byte PLAY_STM = 10; // - ScreamTracker STM/STX songs + // + // * = Supported in the current version + // + = Planned for support "soon" + // - = Will probably not be supported any time soon + +struct GPlay { + byte type; + int effectno; // For the DOS sound effects SND_xxx + Path file; + int Play() const; +}; + + +// ------------------------------------------------------------------ +// Event types (CRC16 values), commands and structure + +const word EVTT_AREALIST = 0x445D; +const word EVTT_ASKYESNO = 0xB26C; +const word EVTT_ATTENTION = 0x0F21; +const word EVTT_BLANKEROFF = 0x16EF; +const word EVTT_BLANKERON = 0x819F; +const word EVTT_DOSSHELL = 0x2111; +const word EVTT_EDITCOMMENT = 0x662C; +const word EVTT_EDITCOMPLETION = 0xDA45; +const word EVTT_ENDOFMSGS = 0x95BC; +const word EVTT_ERRORFATAL = 0xE9C1; +const word EVTT_EXIT = 0x6090; +const word EVTT_JOBDONE = 0xA81F; +const word EVTT_JOBFAILED = 0xCC9A; +const word EVTT_MSGCOMMENT = 0x0761; +const word EVTT_MSGCOPYING = 0x087B; +const word EVTT_MSGDELETING = 0x1AFF; +const word EVTT_MSGFROMYOU = 0xBACB; +const word EVTT_MSGISLOCAL = 0x2BD6; +const word EVTT_MSGISTWIT = 0xC466; +const word EVTT_MSGLIST = 0x84D0; +const word EVTT_MSGMOVING = 0xAA1B; +const word EVTT_MSGNEW = 0x2882; +const word EVTT_MSGPRINTING = 0x29E0; +const word EVTT_MSGREPLY = 0x3439; +const word EVTT_MSGTOYOU = 0xFB77; +const word EVTT_MSGWRITING = 0x0CA8; +const word EVTT_NODEBROWSE = 0xB6B5; +const word EVTT_SAYBIBI = 0xD39D; +const word EVTT_SEARCHFAILED = 0xEB54; +const word EVTT_SEARCHSUCCESS = 0x2EB2; +const word EVTT_STARTUP = 0x494B; +const word EVTT_TIMEOUT = 0x4065; + +const word EVTT_BREAKLOOP = 0xFFFF; +const word EVTT_STOPVOICE = 0xFFFE; +const word EVTT_REMOVEVOCBUF = 0xFFFD; +const word EVTT_INITCARD = 0xFFFC; + +const int EVTC_DO_NOTHING = 0; +const int EVTC_PLAY = 1; + +struct GEvent { + word type; // EVTT crc value + int command; // EVTC value + union { + GPlay play; + // Other event command structures can be added here + }; + GEvent& operator=(const GEvent& a) { + type = a.type; + command = a.command; + switch(command) { + case EVTC_PLAY: + memcpy(&play, &a.play, sizeof(play)); + break; + } + return *this; + } +}; + + +// ------------------------------------------------------------------ +// Sound device structure + +const int SNDDEV_NONE = 0; +const int SNDDEV_DOS = 1; +const int SNDDEV_CARD = 2; + +struct SoundDos { + int type; + // Doesn't need more data.. +}; + + +// ------------------------------------------------------------------ +// Enums for the marking menu (GEMENU etc) + +enum { + TAG_MARKYOURMAIL=100, + TAG_MARKHEADER, + TAG_MARKTXTHDR, + TAG_MARKTHREAD, + TAG_MARKNEWMSGS, + TAG_MARKOLDMSGS, + TAG_MARKALLMSGS, + TAG_MARKUNMARK, + TAG_MARKRANGE, + TAG_MARKTOGGLE, + TAG_MARKQUIT +}; + + +// ------------------------------------------------------------------ +// The Message Browser + +struct MLst { + ulong msgno; + byte high; + char num[8]; + char marks[3]; + char by[sizeof(Name)+20]; + char to[sizeof(Name)+20]; + Subj re; + time_t written; + time_t arrived; + time_t received; + char goldmark; +}; + + +// ------------------------------------------------------------------ +// Structure for GOLDNODE.IXL + +struct NodeIxl { + + // Nodelists + int nodelists; + Stamp* nodelist; + + // Index files + Path addrindex; + Path nodeindex; + +}; + + +// ------------------------------------------------------------------ +// GEUSER + +struct infoLookup { + char* attr; + char* node; + char* system; + char* location; + char* name; + char* phone; + char* baud; + char* flags; +}; + + +// ------------------------------------------------------------------ +// Structures and constants for external utilities + +const int EXTUTIL_CLS = 0x0001; +const int EXTUTIL_SWAP = 0x0002; +const int EXTUTIL_CURSOR = 0x0004; +const int EXTUTIL_RELOAD = 0x0008; +const int EXTUTIL_PAUSE = 0x0010; +const int EXTUTIL_PAUSEONERROR = 0x0020; +const int EXTUTIL_WIPE = 0x0040; +const int EXTUTIL_KEEPCTRL = 0x0080; + +struct ExtUtil { + int utilno; + int options; + char cmdline[256]; +}; + +struct SaveUtil { + int utilno; + char menutext[41]; +}; + + +// ------------------------------------------------------------------ +// Window areas + +#define GC_BACK_ CFG->color[0] +#define GC_STAT_ CFG->color[1] +#define GC_BRAG_ CFG->color[2] +#define GC_AREA_ CFG->color[3] +#define GC_READ_ CFG->color[4] +#define GC_HEAD_ CFG->color[5] +#define GC_ASK__ CFG->color[6] +#define GC_MENU_ CFG->color[7] +#define GC_HELP_ CFG->color[8] +#define GC_CFG_ CFG->color[9] +#define GC_INFO_ CFG->color[10] +#define GC_CFGB_ CFG->color[11] +#define GC_STYLE_ CFG->color[12] +#define GC_SHAD_ CFG->color[13] +#define GC_READ2_ CFG->color[14] + + +// ------------------------------------------------------------------ +// Window parts + +#define _Window c[0] +#define _Border c[1] +#define _Title c[2] +#define _Cursor c[2] +#define _Selector c[3] +#define _Quote c[3] +#define _Subject c[3] +#define _Highlight c[4] +#define _Noselect c[5] +#define _Kludge c[5] +#define _Tearline c[6] +#define _Edit c[6] +#define _Signature c[6] +#define _Block c[7] +#define _Input c[7] +#define _Quote2 c[7] +#define _Shadow c[7] +#define _Origin c[8] +#define _To c[8] +#define _From c[9] +#define _Tagline c[9] +#define _Hidden c[10] +#define _Pagebar c[11] + +#define _WindowUnsent c[6] +#define _WindowUnread c[7] +#define _HighlightUnsent c[8] +#define _HighlightUnread c[9] + +#define _Bold c[1] +#define _Italic c[2] +#define _BoldItalic c[3] +#define _Underscore c[4] +#define _BoldUnderscore c[5] +#define _ItalicUnderscore c[6] +#define _BoldItalicUnderscore c[7] +#define _Reverse c[8] +#define _ReverseBold c[9] +#define _ReverseItalic c[10] +#define _ReverseBoldItalic c[11] +#define _ReverseUnderscore c[12] +#define _ReverseBoldUnderscore c[13] +#define _ReverseItalicUnderscore c[14] +#define _ReverseBoldItalicUnderscore c[15] + + +// ------------------------------------------------------------------ +// Window part colors + +#define C_BACKW GC_BACK_._Window +#define C_BACKB GC_BACK_._Border + +#define C_STATW GC_STAT_._Window +#define C_STATB GC_STAT_._Border + +#define C_BRAGW GC_BRAG_._Window +#define C_BRAGB GC_BRAG_._Border +#define C_BRAGT GC_BRAG_._Title +#define C_BRAGH GC_BRAG_._Highlight +#define C_BRAGA GC_BRAG_._Block + +#define C_AREAW GC_AREA_._Window +#define C_AREAB GC_AREA_._Border +#define C_AREAT GC_AREA_._Title +#define C_AREAS GC_AREA_._Selector +#define C_AREAQ GC_AREA_._Highlight +#define C_AREAPB GC_AREA_._Pagebar + +#define C_READW GC_READ_._Window +#define C_READB GC_READ_._Border +#define C_READQ GC_READ_._Quote +#define C_READK GC_READ_._Kludge +#define C_READKH GC_READ_._Hidden +#define C_READC GC_READ_._Cursor +#define C_READA GC_READ_._Block +#define C_READH GC_READ_._Highlight +#define C_READG GC_READ_._Tagline +#define C_READT GC_READ_._Tearline +#define C_READO GC_READ_._Origin +#define C_READPB GC_READ_._Pagebar +#define C_READQ2 GC_READ2_._Quote2 +#define C_READS GC_READ2_._Signature +#define C_HEADW GC_HEAD_._Window +#define C_HEADB GC_HEAD_._Border +#define C_HEADT GC_HEAD_._Title +#define C_HEADE GC_HEAD_._Edit +#define C_HEADI GC_HEAD_._Input +#define C_HEADQ GC_HEAD_._Highlight +#define C_HEADBY GC_HEAD_._From +#define C_HEADTO GC_HEAD_._To +#define C_HEADRE GC_HEAD_._Subject + +#define C_ASKW GC_ASK__._Window +#define C_ASKB GC_ASK__._Border +#define C_ASKT GC_ASK__._Title +#define C_ASKS GC_ASK__._Selector +#define C_ASKQ GC_ASK__._Highlight +#define C_ASKN GC_ASK__._Noselect +#define C_ASKPB GC_ASK_._Pagebar + +#define C_MENUW GC_MENU_._Window +#define C_MENUB GC_MENU_._Border +#define C_MENUT GC_MENU_._Title +#define C_MENUS GC_MENU_._Selector +#define C_MENUQ GC_MENU_._Highlight +#define C_MENUN GC_MENU_._Noselect +#define C_MENUPB GC_MENU_._Pagebar +#define C_MENUW_UNREAD GC_MENU_._WindowUnread +#define C_MENUQ_UNREADHIGH GC_MENU_._HighlightUnread +#define C_MENUW_UNSENT GC_MENU_._WindowUnsent +#define C_MENUQ_UNSENTHIGH GC_MENU_._HighlightUnsent + +#define C_HELPW GC_HELP_._Window +#define C_HELPB GC_HELP_._Border +#define C_HELPT GC_HELP_._Title +#define C_HELPS GC_HELP_._Selector +#define C_HELPQ GC_HELP_._Highlight +#define C_HELPPB GC_HELP_._Pagebar + +#define C_INFOW GC_INFO_._Window +#define C_INFOB GC_INFO_._Border +#define C_INFOT GC_INFO_._Title +#define C_INFOPB GC_INFO_._Pagebar + +#define C_CFGW GC_CFG_._Window +#define C_CFGB GC_CFG_._Border +#define C_CFGT GC_CFG_._Title +#define C_CFGS GC_CFG_._Selector +#define C_CFGQ GC_CFG_._Highlight +#define C_CFGN GC_CFG_._Noselect +#define C_CFGPB GC_CFG_._Pagebar + +#define C_CFGBW GC_CFGB_._Window +#define C_CFGBB GC_CFGB_._Border +#define C_CFGBT GC_CFGB_._Title +#define C_CFGBS GC_CFGB_._Selector +#define C_CFGBQ GC_CFGB_._Highlight +#define C_CFGBN GC_CFGB_._Noselect +#define C_CFGBPB GC_CFGB_._Pagebar + +#define C_SHADOW GC_SHAD_._Shadow + +#define C_STYLE GC_STYLE_.c +#define C_STYLE___B GC_STYLE_._Bold +#define C_STYLE__I_ GC_STYLE_._Italic +#define C_STYLE__IB GC_STYLE_._BoldItalic +#define C_STYLE_U__ GC_STYLE_._Underscore +#define C_STYLE_U_B GC_STYLE_._BoldUnderscore +#define C_STYLE_UI_ GC_STYLE_._ItalicUnderscore +#define C_STYLE_UIB GC_STYLE_._BoldItalicUnderscore +#define C_STYLER___ GC_STYLE_._Reverse +#define C_STYLER__B GC_STYLE_._ReverseBold +#define C_STYLER_I_ GC_STYLE_._ReverseItalic +#define C_STYLER_IB GC_STYLE_._ReverseBoldItalic +#define C_STYLERU__ GC_STYLE_._ReverseUnderscore +#define C_STYLERU_B GC_STYLE_._ReverseBoldUnderscore +#define C_STYLERUI_ GC_STYLE_._ReverseItalicUnderscore +#define C_STYLERUIB GC_STYLE_._ReverseBoldItalicUnderscore + + +// ------------------------------------------------------------------ +// Window handles + +#define W_BACK GC_BACK_.w +#define W_STAT GC_STAT_.w +#define W_BRAG GC_BRAG_.w +#define W_AREA GC_AREA_.w +#define W_READ GC_READ_.w +#define W_HEAD GC_READ_.w +#define W_ASK GC_ASK__.w +#define W_MENU GC_MENU_.w +#define W_INFO GC_INFO_.w + + +// ------------------------------------------------------------------ +// Window offsets + +#define W_XBACK GC_BACK_.x +#define W_XSTAT GC_STAT_.x +#define W_XBRAG GC_BRAG_.x +#define W_XAREA GC_AREA_.x +#define W_XREAD GC_READ_.x +#define W_XHEAD GC_READ_.x +#define W_XASK GC_ASK__.x +#define W_XMENU GC_MENU_.x +#define W_XINFO GC_INFO_.x + +#define W_YBACK GC_BACK_.y +#define W_YSTAT GC_STAT_.y +#define W_YBRAG GC_BRAG_.y +#define W_YAREA GC_AREA_.y +#define W_YREAD GC_READ_.y +#define W_YHEAD GC_READ_.y +#define W_YASK GC_ASK__.y +#define W_YMENU GC_MENU_.y +#define W_YINFO GC_INFO_.y + + +// ------------------------------------------------------------------ +// Window border types + +#define W_BBACK GC_BACK_.btype +#define W_BSTAT GC_STAT_.btype +#define W_BBRAG GC_BRAG_.btype +#define W_BAREA GC_AREA_.btype +#define W_BREAD GC_READ_.btype +#define W_BHEAD GC_READ_.btype +#define W_BASK GC_ASK__.btype +#define W_BMENU GC_MENU_.btype +#define W_BHELP GC_HELP_.btype +#define W_BINFO GC_INFO_.btype +#define W_BCFG GC_CFG_.btype +#define W_BCFGB GC_CFGB_.btype + + +// ------------------------------------------------------------------ +// Window structure + +struct Win { + int btype; // Border type + int c[12]; // Colors + int w; // Window handle +}; + +// ------------------------------------------------------------------ +// Charset translation table structure + +typedef byte ChsTab[4]; + +struct Chs { + long id; + int version; + int level; + XlatName imp; // From Charset + XlatName exp; // To Charset + ChsTab t[256]; // The Translation Table +}; + + +// ------------------------------------------------------------------ +// Escaped characters table structure + +typedef byte EscTab[5]; + +struct Esc { + XlatName exp; // To Charset + byte esc; // Escape character + int pos1; // Relative position of first character + int pos2; // Relative position of last character + uint size; // Number of escaped chars in table + EscTab t[256]; // The Escaped Characters Table +}; + + +// ------------------------------------------------------------------ +// Charset mapping files + +struct Map { + XlatName imp; // From Charset + XlatName exp; // To Charset + char* mapfile; // Mapping file and timestamp +}; + + +// ------------------------------------------------------------------ + +struct PosLen { + int pos; + int len; +}; + + +// ------------------------------------------------------------------ + +struct Ezycom { + Path msgbasepath; + Path userbasepath; +}; + + +// ------------------------------------------------------------------ + +struct Invalidate { + pair origin, seenby, tearline, cc, xc, xp; +}; + + +// ------------------------------------------------------------------ + +struct Semaphore { + Path netscan; + Path echoscan; + Path exportlist; + Path importlist; + Path scanall; + Path scanthis; + Path scannetmail; + Path pmscanall; + Path pmscanthis; + Path pmscannetmail; + Path qwkimport; + Path qwkexport; + Path soupimport; + Path soupexport; + Path exitnow; + + uint idletime; +}; + + +// ------------------------------------------------------------------ + +struct AkaMatchG { + Addr mask; + Addr aka; +}; + + +// ------------------------------------------------------------------ + +struct MailList { + Echo echoid; + IAdr sender; + IAdr contribution; + bool sender_is_pattern; +}; + + +// ------------------------------------------------------------------ + +struct FrqNodeMap { + Addr from; + Addr to; +}; + + +// ------------------------------------------------------------------ + +struct InetServers { + struct { + char server[61]; + } nntp; + struct { + char server[61]; + } smtp; + struct { + char server[61]; + char username[61]; + char password[61]; + } pop3; +}; + + +// ------------------------------------------------------------------ + +typedef char BarList[45]; + +struct FFblk { + int year; + int month; + int day; + int hour; + int minute; + int second; + long size; + Path name; + bool selected; // Extra - YES/NO +}; + +struct FileSpec { + Path path; // Path to file(s) + char password[20]; // File Password + int files; // Number of files + bool delsent; // Kill files after sent + FFblk* fblk; // Filenames +}; + + +// ------------------------------------------------------------------ +// Message written by/to me/you ? + +const uint TO_ME = 1; +const uint BY_ME = 2; +const uint TO_YOU = 4; +const uint BY_YOU = 8; +const uint TO_ALL = 16; + +// ------------------------------------------------------------------ + +#if defined(GOLD_CANPACK) +#pragma pack() +#endif + + +// ------------------------------------------------------------------ +// Include various GoldED structures + +#include +#include +#include +#include +#include + + +// ------------------------------------------------------------------ + diff --git a/golded3/gealst.cpp b/golded3/gealst.cpp new file mode 100644 index 0000000..8a17bc7 --- /dev/null +++ b/golded3/gealst.cpp @@ -0,0 +1,403 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Arealist functions. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +AreaList AL; + +int AreaTypeOrder[17] = { + 0, + 1, // AT_NET + 2, // AT_EMAIL + 3, // AT_NET | AT_EMAIL + 4, // AT_ECHO + 5, + 6, + 7, + 8, // AT_NEWSGROUP + 9, + 10, + 11, + 12, // AT_ECHO | AT_NEWSGROUP + 13, + 14, + 15, + 16 // AT_LOCAL +}; + + +// ------------------------------------------------------------------ +// Arealist compare + +extern "C" int AreaListCmp(const Area** __a, const Area** __b) { + + const Area* a = *__a; + const Area* b = *__b; + const Area* A = a; + const Area* B = b; + int cmp = 0; + int aunread; + int bunread; + + bool rev = false; + char* ptr = AL.sortspec; + + while(*ptr) { + switch(toupper(*ptr)) { + case '-': + rev = true; + A = b; B = a; + break; + case '+': + rev = false; + A = a; B = b; + break; + case 'A': + if((cmp = A->aka().compare(B->aka())) != 0) + return cmp; + break; + case 'B': + if((cmp = compare_two(A->board(), B->board())) != 0) + return cmp; + break; + case 'D': + if((cmp = stricmp(A->desc(), B->desc())) != 0) + return cmp; + break; + case 'E': + if((cmp = stricmp(A->echoid(), B->echoid())) != 0) + return cmp; + break; + case 'F': + if(*area_maybe) { + if(striinc(area_maybe, A->echoid()) and not striinc(area_maybe, B->echoid())) + return -1; + if(striinc(area_maybe, B->echoid()) and not striinc(area_maybe, A->echoid())) + return 1; + } + break; + case 'G': + { + int ga = A->groupid(); + int gb = B->groupid(); + + char* p = strpbrk(AL.sortspec, "tT"); + bool groupfirst = p > ptr; + bool ignoretype = p == NULL or groupfirst; + + if(ga == 0 and ((not A->isseparator()^rev) or ignoretype)) + ga = INT_MAX; + if(gb == 0 and ((not B->isseparator()^rev) or ignoretype)) + gb = INT_MAX; + + if((A->isseparator() or B->isseparator()) and ga == gb) { + if(groupfirst and (cmp = compare_two(CFG->areatypeorder[A->type()&0xFF], CFG->areatypeorder[B->type()&0xFF])) != 0) + return cmp; + if((cmp = compare_two(b->isseparator(), a->isseparator())) != 0) + return cmp; + } + else { + if((cmp = compare_two(ga, gb)) != 0) + return cmp; + } + } + break; + case 'M': + if(A->ismarked() and not B->ismarked()) + return -1; + if(B->ismarked() and not A->ismarked()) + return 1; + break; + case 'P': + if((cmp = compare_two(B->PMrk.Count()?1:0, A->PMrk.Count()?1:0)) != 0) + return cmp; + break; + case 'O': + if((cmp = compare_two(A->areaid(), B->areaid())) != 0) + return cmp; + break; + case 'T': + if((cmp = compare_two(CFG->areatypeorder[A->type()&0xFF], CFG->areatypeorder[B->type()&0xFF])) != 0) + return cmp; + break; + case 'U': + aunread = A->Msgn.Count() - A->lastread(); + bunread = B->Msgn.Count() - B->lastread(); + if(rev) + cmp = compare_two(aunread, bunread); + else + cmp = compare_two(aunread ? aunread : INT_MAX, bunread ? bunread : INT_MAX); + if(cmp != 0) + return cmp; + break; + case 'X': + if((cmp = compare_two(A->msgbase(), A->msgbase())) != 0) + return cmp; + break; + case 'Y': + aunread = A->Msgn.Count() - A->lastread(); + bunread = B->Msgn.Count() - B->lastread(); + if(aunread and not bunread) + return -1; + if(bunread and not aunread) + return 1; + break; + case 'Z': + if((cmp = stricmp(A->path(), B->path())) != 0) + return cmp; + break; + } + ptr++; + } + + return cmp; +} + +// ------------------------------------------------------------------ +// Arealist sort areas + +void AreaList::Sort(const char* specs, int first, int last) { + + if(specs) + strcpy(sortspec, specs); + else + strcpy(sortspec, CFG->arealistsort); + if(last == -1) + last = idx.size(); + if(*sortspec) + qsort(&idx[first], last-first, sizeof(Area *), (StdCmpCP)AreaListCmp); +} + + +// ------------------------------------------------------------------ + +int AreaList::AreaEchoToNo(const char* echoid) { + + for(uint n=0; nechoid())) + return n; + return -1; +} + + +// ------------------------------------------------------------------ + +Area* AreaList::AreaEchoToPtr(const char* echoid) { + + for(uint n=0; nechoid())) + return idx[n]; + return NULL; +} + + +// ------------------------------------------------------------------ + +int AreaList::AreaNoToId(int __areano) { + + if(in_range(__areano, 0, int(idx.size()-1))) + return idx[__areano]->areaid(); + else { + LOG.ErrIndex(); + LOG.printf("! Arealist index out of bounds."); + LOG.printf(": Tried to access record %i, but the range was only 0 - %u.", __areano, (uint)(idx.size()-1)); + LOG.printf("+ Advice: Report this to the author."); + IndexErrorExit(); + return 0; + } +} + + +// ------------------------------------------------------------------ + +Area* AreaList::AreaNoToPtr(int __areano) { + + if(in_range(__areano, 0, int(idx.size()-1))) + return idx[__areano]; + else { + LOG.ErrIndex(); + LOG.printf("! Arealist index out of bounds."); + LOG.printf(": Tried to access record %i, but the range was only 0 - %u.", __areano, (uint)(idx.size()-1)); + LOG.printf("+ Advice: Report this to the author."); + IndexErrorExit(); + return 0; + } +} + + +// ------------------------------------------------------------------ + +int AreaList::AreaIdToNo(int __areaid) { + + uint _areano = 0; + while(_areano < idx.size()) { + if(idx[_areano]->areaid() == __areaid) + return _areano; + _areano++; + } + return -1; +} + + +// ------------------------------------------------------------------ + +Area* AreaList::AreaIdToPtr(int __areaid) { + + int _areano = AreaIdToNo(__areaid); + if(_areano != -1) + return idx[_areano]; + return NULL; +} + + +// ------------------------------------------------------------------ + +int AreaList::SetActiveAreaId(int __areaid) { + + int _areano = AreaIdToNo(__areaid); + SetActiveAreaNo(_areano); + return _areano; // Return the areano +} + + +// ------------------------------------------------------------------ + +class SelMaskPick : public gwinpick { + + gwindow window; + + void open(); // Called after window is opened + void close(); // Called after window is closed + void print_line(uint idx, uint pos, bool isbar); + bool handle_key(); // Handles keypress + +public: + + void Run(); + +}; + +void SelMaskPick::open() { + + window.openxy(ypos, xpos, ylen+2, xlen+2, btype, battr, 7); + window.title(title, tattr); + window.shadow(C_SHADOW); + update(); +} + +void SelMaskPick::close() { + + window.close(); + +} + +void SelMaskPick::print_line(uint idx, uint pos, bool isbar) { + + char buf[sizeof(Desc)+3]; + + *buf = ' '; strcpy(buf+1, AL.alistselections[idx]); + window.printns(pos, 0, isbar ? sattr : wattr, buf, xlen); +} + +bool SelMaskPick::handle_key() { + + switch(key) { + case Key_Esc: + aborted = true; + + /// Drop through + case Key_Ent: + return false; + + case Key_Tick: + break; + + default: + if(key < KK_Commands) { + kbput(key); + edit_string(AL.alistselections[index], sizeof(Desc)-1, LNG->SelectMarksEdit, H_SelectMarks); + display_bar(); + } + break; + } + + return true; +} + +void SelMaskPick::Run() { + + ypos = (MAXROW-18)/2; + xpos = (MAXCOL-sizeof(Desc)-4)/2-1; + ylen = 16; + xlen = sizeof(Desc)+2; + btype = W_BMENU; + battr = C_MENUB; + wattr = C_MENUW; + tattr = C_MENUT; + sattr = C_MENUS; + hattr = C_MENUQ; + + title = LNG->SelectMarks; + helpcat = H_SelectMarks; + listwrap = true; + + maximum_index = 15; + maximum_position = 16; + + index = position = AL.mask; + + run_picker(); + + if(not aborted) + AL.mask = (byte)index; + +}; + + +void AreaList::Select_Mask() { + + SelMaskPick& SelMask = *new SelMaskPick; + throw_new(&SelMask); + + SelMask.Run(); + + extern bool in_arealist; + extern GPickArealist* PickArealist; + + if(in_arealist) { + PickArealist->update(); + PickArealist->do_delayed(); + } + + delete &SelMask; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gearea.cpp b/golded3/gearea.cpp new file mode 100644 index 0000000..d88f2ea --- /dev/null +++ b/golded3/gearea.cpp @@ -0,0 +1,915 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Arealister and other area-specific code +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern int arealistnumgrps; + +bool in_arealist = false; + +GPickArealist* PickArealist; + +Echo area_maybe; +int areaswithgroupid = 0; +uint* areanumbers = NULL; + +// 111111111122222222223333333333444444444455555555556666666666777777777 +// 0123456789012345678901234567890123456789012345678901234567890123456789012345678 +// ÚÄAreaÄDescriptionÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄMsgsÄÄÄNewÄÄEchoIDÄÄÄÄÄÄÄÄÄÄÄÄÄÄGrpÄ¿ +// ³ 1> NET FidoNet Z3/4/5/6 118+ 3* NET.FIDOZX A ³ + +// AREALISTFORMAT "AM D CPUN E G" + +int area_pos = -1; +int area_width = 4; +int marked_pos = -1; +int marked_width = 1; +const char marked_char = MMRK_MARK; +int desc_pos = -1; +int desc_width = -1; +int count_pos = -1; +int count_width = 6; +int pmark_pos = -1; +int pmark_width = 1; +const char pmark_char = '+'; +int unread_pos = -1; +int unread_width = 6; +int changed_pos = -1; +int changed_width = 1; +const char changed_char = '*'; +int echoid_pos = -1; +int echoid_width = 0; +int groupid_pos = -1; +int groupid_width = 0; + + +// ------------------------------------------------------------------ + +GPickArealist::GPickArealist() { + + areawin1 = 0; + areawin2 = 0; + tempwin1 = 0; + tempwin2 = 0; + + pmails = 0; + pmareas = 0; + pmscan = false; + + area_fuzidx = 0; + +}; + + +// ------------------------------------------------------------------ + +void GPickArealist::AreasRenumber() { + + for(int n=0,a=1,t=AL.size(); nisseparator() ? 0 : a++; +} + + +// ------------------------------------------------------------------ + +bool GPickArealist::is_selectable(uint idx) { + + Area* area = AL.AreaNoToPtr(idx); + return (not area->isseparator()); + +} + + +// ------------------------------------------------------------------ + +void GPickArealist::do_delayed() { + + Area* area = AL.AreaNoToPtr(index); + + char buf[256], tmp[200]; + + strcpy(tmp, area->echoid()); + update_statuslinef("%s: %u %s, %u %s, %u %s", tmp, area->Msgn.Count(), (area->Msgn.Count() == 1 ? LNG->msg : LNG->msgs), area->unread, LNG->unread, area->PMrk.Count(), LNG->personal); + + strcpy(stpcpy(buf, title), area_maybe); + strsetsz(strcpy(tmp, buf), MAXCOL); + wwprintstr(tempwin, 0, 0, wattr, tmp); + + if(CFG->switches.get(arealistpagebar)) + wscrollbar(W_VERT, maximum_index+1, maximum_index, index); +} + + +// ------------------------------------------------------------------ + +void GPickArealist::close_all() { + + if(areawin1) + wunlink(areawin1); + if(areawin2) + wunlink(areawin2); + if(tempwin1) + wunlink(tempwin1); + if(tempwin2) + wunlink(tempwin2); +} + + +// ------------------------------------------------------------------ + +void GPickArealist::dispbuf(char* buf, int areano) { + + Area* area = AL.AreaNoToPtr(areano); + + memset(buf, ' ', MAXCOL-2); + buf[MAXCOL-2] = NUL; + + char areabuf[33]; + sprintf(areabuf, "%u", CFG->switches.get(arealistnos) ? area->board() : areanumbers[areano]); + int areawidth = strlen(areabuf); + + char markedbuf[2] = { " " }; + *markedbuf = area->ismarked() ? marked_char : ' '; + int markedwidth = 1; + + char descbuf[100]; + int descwidth = strlen(strcpy(descbuf, area->desc())); + + char countbuf[33]; + if(area->isscanned) + sprintf(countbuf, "%u", (uint)area->Msgn.Count()); + else + strcpy(countbuf, "-"); + int countwidth = strlen(countbuf); + + char pmarkbuf[2] = { " " }; + *pmarkbuf = area->PMrk.Count() ? pmark_char : ' '; + int pmarkwidth = 1; + + char unreadbuf[33]; + if(area->isscanned) + sprintf(unreadbuf, "%u", (uint)(CFG->arealisttype ? area->unread : area->lastread())); + else + strcpy(unreadbuf, "-"); + int unreadwidth = strlen(unreadbuf); + + char changedbuf[2] = { " " }; + *changedbuf = area->isunreadchg ? changed_char : ' '; + int changedwidth = 1; + + char echoidbuf[100]; + int echoidwidth = strlen(strcpy(echoidbuf, area->echoid())); + + char groupidbuf[10] = { "" }; + if(groupid_width) { + if(area->groupid() & 0x8000u) { + if(groupid_width > 2) + sprintf(groupidbuf, "%u", area->groupid()&0x7FFF); + } + else if(isupper(area->groupid())) + sprintf(groupidbuf, "%c", (char)area->groupid()); + } + int groupidwidth = strlen(groupidbuf); + + areawidth = MinV(areawidth, area_width); + markedwidth = MinV(markedwidth, marked_width); + descwidth = MinV(descwidth, desc_width); + countwidth = MinV(countwidth, count_width); + pmarkwidth = MinV(pmarkwidth, pmark_width); + unreadwidth = MinV(unreadwidth, unread_width); + changedwidth = MinV(changedwidth, changed_width); + echoidwidth = MinV(echoidwidth, echoid_width); + groupidwidth = MinV(groupidwidth, groupid_width); + + memcpy(buf+area_pos+area_width-areawidth, areabuf, areawidth); + memcpy(buf+marked_pos, markedbuf, markedwidth); + memcpy(buf+desc_pos, descbuf, descwidth); + memcpy(buf+count_pos+count_width-countwidth, countbuf, countwidth); + memcpy(buf+pmark_pos, pmarkbuf, pmarkwidth); + memcpy(buf+unread_pos+unread_width-unreadwidth, unreadbuf, unreadwidth); + memcpy(buf+changed_pos, changedbuf, changedwidth); + memcpy(buf+echoid_pos, echoidbuf, echoidwidth); + memcpy(buf+groupid_pos+groupid_width-groupidwidth, groupidbuf, groupidwidth); +} + +// ------------------------------------------------------------------ + +void GPickArealist::center() { + + uint room, toproom, botroom; + + toproom = index; + botroom = maximum_index - index; + if(toproom > maximum_position/2) { + if(botroom > maximum_position/2) + room = maximum_position/2; + else if(botroom) + room = maximum_position - botroom; + else + room = maximum_position; + } + else + room = toproom; + + position = room; + display_page(); +} + + +// ------------------------------------------------------------------ + +void GPickArealist::jump_to() { + + uint n = index+1; + bool found = false; + // Search for next marked area, wrapping 'round if needed + for(; n<=maximum_index; n++) { + if(not AL[n]->isseparator() and AL[n]->ismarked()) { + found = true; + break; + } + } + + if(not found) { + for(n = minimum_index; n <= index; n++) { + if(not AL[n]->isseparator() and AL[n]->ismarked()) + break; + } + } + + if(n > maximum_index) + n = minimum_index; + + while(AL[n]->isseparator()) { + if((++n) > maximum_index) + n = minimum_index; + } + + index = n; + center(); +} + + +// ------------------------------------------------------------------ + +void GPickArealist::jumpmatch() { + + uint n = index+1; + bool found = false; + // Search for next marked area, wrapping 'round if needed + for(; n<=maximum_index; n++) { + if(not AL[n]->isseparator() and (strnieql(area_maybe, AL[n]->echoid(), area_fuzidx) or striinc(area_maybe, AL[n]->echoid()))) { + found = true; + break; + } + } + + if(not found) { + for(n = minimum_index; n <= index; n++) { + if(not AL[n]->isseparator() and (strnieql(area_maybe, AL[n]->echoid(), area_fuzidx) or striinc(area_maybe, AL[n]->echoid()))) + break; + } + } + + if(n > maximum_index) + n = minimum_index; + + while(AL[n]->isseparator()) { + if((++n) > maximum_index) + n = minimum_index; + } + + index = n; + center(); + +} + + +// ------------------------------------------------------------------ + +void GPickArealist::open() { + + int active=NO; + + #if defined(GUTLOS_FUNCS) + g_set_ostitle_name("Arealist",0); + #endif + + if(ypos) { + if(tempwin1) { + tempwin = tempwin1; + areawin = areawin1; + active = YES; + } + } + else { + if(tempwin2) { + tempwin = tempwin2; + areawin = areawin2; + active = YES; + } + } + + if(active) { + wunhide(tempwin); + wprints(0,0, wattr, title); + wunhide(areawin); + } + else { + tempwin = wopen_(ypos, xpos, 1, MAXCOL, 5, battr, wattr, sbattr); + wprints(0,0, wattr, title); + areawin = wopen_(ypos+1, xpos, ylen+2, MAXCOL, btype, battr, wattr, sbattr); + + if(ypos) { + tempwin1 = tempwin; + areawin1 = areawin; + } + else { + tempwin2 = tempwin; + areawin2 = areawin; + } + + if(area_width) + wmessage(LNG->Area, TP_BORD, 1+area_pos+(marked_pos==area_pos+area_width?1:0), tattr); + if(desc_width) + wmessage(LNG->Description, TP_BORD, 1+desc_pos, tattr); + if(count_width) + wmessage(LNG->Msgs, TP_BORD, 1+count_pos+count_width-strlen(LNG->Msgs), tattr); + if(unread_width) { + if(CFG->arealisttype == AL_TOTLST) + wmessage(LNG->Last, TP_BORD, 1+unread_pos+unread_width-strlen(LNG->Last), tattr); + else if(CFG->arealisttype == AL_TOTNEW) + wmessage(LNG->New, TP_BORD, 1+unread_pos+unread_width-strlen(LNG->New), tattr); + } + if(echoid_width) + wmessage(LNG->EchoID, TP_BORD, 1+echoid_pos, tattr); + if(groupid_width) { + char grpbuf[40]; + if(groupid_width > 2) + strcpy(grpbuf, LNG->Grp); + else { + *grpbuf = *(LNG->Grp); + grpbuf[1] = NUL; + } + wmessage(grpbuf, TP_BORD, 1+groupid_pos, tattr); + } + + } + if(CFG->switches.get(areaautonext) and ypos == 0 and index >= minimum_index and not AL[index]->ismarked()) { + jump_to(); + } + else + center(); +} + + +// ------------------------------------------------------------------ + +void GPickArealist::close() { + + whide(); + whide(); +} + +// ------------------------------------------------------------------ + +void GPickArealist::precursor() { + + *area_maybe = 0; + area_fuzidx = 0; +} + + +// ------------------------------------------------------------------ + +void GPickArealist::print_line(uint idx, uint pos, bool isbar) { + + vchar vbuf[256]; + char buf[256]; + + if(AL[idx]->isseparator()) { + Area* area = AL.AreaNoToPtr(idx); + + int sep_pos = (desc_pos != -1) ? desc_pos : echoid_pos; + + for(int c = 0; c < sep_pos; c++) + vbuf[c] = _box_table(btype, 1); + vbuf[sep_pos] = NUL; + wprintvs(pos, 0, battr|ACSET, vbuf); + wprints(pos, sep_pos, tattr, area->desc()); + + int l = strlen(area->desc()); + int n = MAXCOL-2-sep_pos-l; + + for(int c = 0; c < n; c++) + vbuf[c] = _box_table(btype,1); + vbuf[n] = NUL; + wprintvs(pos, sep_pos+l, battr|ACSET, vbuf); + } + else { + dispbuf(buf, idx); + wprints(pos, 0, isbar ? sattr : wattr, buf); + if(AL[idx]->ismarked()) + wprintc(pos, marked_pos, isbar ? sattr : hattr, marked_char); + } + +} + + +// ------------------------------------------------------------------ + +void GPickArealist::AreaCatchUp(uint n) { + + GMenuAreaCatchup MenuAreaCatchup; + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + int mode = MenuAreaCatchup.Run(); + + if(mode != SCAN_QUIT) { + for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++) { + + if((mode == SCAN_MARKED and (*AL.item)->ismarked()) or mode == SCAN_ALL or (mode == SCAN_CURRENT and (*AL.item) == AL[n])) { + + if((*AL.item)->isseparator()) + continue; + + update_statuslinef("%s ...", (*AL.item)->echoid()); + + AA = (*AL.item); + AA->Open(); + + if(CFG->switches.get(highlightunread) and CFG->switches.get(areacatchupread)) { + w_info(LNG->Wait); + for(uint i=AA->lastread()+1; i <= AA->Msgn.Count(); i++) { + AA->LoadHdr(msg, AA->Msgn.CvtReln(i)); + if(msg->timesread++ == 0) + AA->UpdateTimesread(msg); + } + w_info(NULL); + } + + AA->set_lastread(AA->Msgn.Count()); + AA->isvalidchg = false; + AA->Close(); + } + } + } + throw_free(msg); +} + + +// ------------------------------------------------------------------ + +void GPickArealist::AreaDropMsgMarks(uint n) { + + GMenuAreaDropMarks MenuAreaDropMarks; + + uint nummarks = 0; + + for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++) + nummarks += (*AL.item)->Mark.Count(); + + char buf[256]; + sprintf(buf, LNG->DropMarksInfo, longdotstr(nummarks)); + + w_info(buf); + int mode = MenuAreaDropMarks.Run(); + w_info(NULL); + + if(mode != SCAN_QUIT) { + for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++) { + if((mode == SCAN_MARKED and (*AL.item)->ismarked()) or mode == SCAN_ALL or (mode == SCAN_CURRENT and (*AL.item) == AL[n])) { + + if((*AL.item)->isseparator()) + continue; + + (*AL.item)->Mark.ResetAll(); + } + } + } +} + + +// ------------------------------------------------------------------ + +bool GPickArealist::handle_key() { + + uint n; + uint x; + const char* adesc; + char buf[256], tmp[256]; + + int mode, changed, currno; + + gkey kk; + + if(key < KK_Commands) { + key = key_tolower(key); + if((key == Key_Esc) and esc_abort) + key = KK_AreaAbort; + else { + kk = SearchKey(key, AreaKey, AreaKeys); + if(kk) + key = kk; + } + } + + + switch(key) { + + case KK_AreaDropMsgMarks: + AreaDropMsgMarks(index); + break; + + case KK_AreaSelectMarks: + AL.Select_Mask(); + break; + + case KK_AreaAskExit: + { + GMenuQuit MenuQuit; + aborted = gkbd.quitall = (MenuQuit.Run()!=0); + if(gkbd.quitall) { + precursor(); + return false; + } + } + break; + + case KK_AreaAbort: + aborted = true; + // Drop Through + + case KK_AreaSelect: + if(AL[index]->isseparator()) { + if(not PlayMacro(key, KT_A)) + SayBibi(); + break; + } + precursor(); + return false; + + case KK_AreaQuitNow: + aborted = gkbd.quitall = true; + precursor(); + return false; + + case KK_AreaToggle: + AL[index]->set_marked(not AL[index]->ismarked()); + display_bar(); + precursor(); + cursor_down(); + break; + + case KK_AreaBoardnos: + CFG->switches.set(arealistnos, not CFG->switches.get(arealistnos)); + update(); + break; + + case KK_AreaCatchUp: + AreaCatchUp(index); + update(); + break; + + case KK_AreaJumpNextMatch: + jumpmatch(); + break; + + case KK_AreaJump: + { + precursor(); + jump_to(); + } + break; + + case KK_AreaDosShell: + DosShell(); + break; + + case KK_AreaGotoPrev: precursor(); cursor_up(); break; + case KK_AreaGotoNext: precursor(); cursor_down(); break; + case KK_AreaGotoFirst: precursor(); cursor_first(); break; + case KK_AreaGotoLast: precursor(); cursor_last(); break; + + case KK_AreaSoundkill: + HandleGEvent(EVTT_STOPVOICE); + break; + + case KK_AreaTouchNetscan: + TouchNetscan(); + break; + + case KK_AreaHeat: + { + GMenuAreaHeat MenuAreaHeat; + mode = MenuAreaHeat.Run(); + if(mode != SCAN_QUIT) { + for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++) { + if((mode == SCAN_MARKED and (*AL.item)->ismarked()) or mode == SCAN_ALL or (mode == SCAN_CURRENT and (*AL.item) == AL[index-1])) { + update_statuslinef("%s %s", 1+LNG->ScanningArea, (*AL.item)->echoid()); + (*AL.item)->SetHighwaterMark(); + } + } + } + } + break; + + case KK_AreaZap: + { + GMenuAreaZap MenuAreaZap; + mode = MenuAreaZap.Run(); + if(mode != SCAN_QUIT) { + for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++) { + if((mode == SCAN_MARKED and (*AL.item)->ismarked()) or mode == SCAN_ALL or (mode == SCAN_CURRENT and (*AL.item) == AL[index-1])) { + update_statuslinef("%s %s", 1+LNG->ScanningArea, (*AL.item)->echoid()); + (*AL.item)->ResetHighwaterMark(); + } + } + } + } + break; + + case KK_AreaScanPM: + pmscan = true; + pmails = 0; + pmareas = 0; + // DROP THROUGH // + + case KK_AreaScan: + { + currno = index; + GMenuAreaScan MenuAreaScan; + mode = MenuAreaScan.Run(pmscan); + if(mode != SCAN_QUIT) { + + w_info(LNG->Wait); + + strcpy(stecho, AL[index]->echoid()); + + if(mode == SCAN_IMPORTQWK) + changed = ImportQWK(); + else if(mode == SCAN_EXPORTQWK) + changed = ExportQWK(); + else if(mode == SCAN_IMPORTSOUP) + changed = ImportSOUP(); + else if(mode == SCAN_EXPORTSOUP) + changed = ExportSOUP(); + else { + if(cmdlinedebughg) + LOG.printf("- AreaScan from arealist"); + changed = AL.AreaScan(mode, currno, pmscan, pmails, pmareas); + } + + w_info(); + + AL.SetActiveAreaNo(currno); + if(changed) { + AL.Sort(); + AreasRenumber(); + index = AL.AreaEchoToNo(stecho); + center(); + } + + if(pmscan) { + if(pmails) { + w_infof(LNG->FoundPersonal, + pmails, (pmails==1?"":"s"), + pmareas, (pmareas==1?"":"s") + ); + } + else { + w_info(LNG->NoPersonal); + } + waitkeyt(10000); + w_info(); + } + } + pmscan = false; + } + break; + + case Key_Tick: + CheckTick(KK_AreaQuitNow); + break; + + case KK_AreaUndefine: + break; + + case KK_AreaWriteGoldlast: + w_info(LNG->Wait); + AL.WriteGoldLast(); + w_info(); + break; + + default: + if(key < KK_Macro) { + n = toupper(key & 0xFF); + if((area_fuzidx < area_maxfuz) or key == Key_BS) { + + // Incremental search in the echoids + if(not (n < ' ') or key == Key_BS) { + if(n == ' ') + n = '_'; + if(key != Key_BS) + area_maybe[area_fuzidx++] = (char)n; + else if(area_fuzidx) + area_fuzidx--; + area_maybe[area_fuzidx] = NUL; + strcpy(stpcpy(buf, title), area_maybe); + strsetsz(strcpy(tmp, buf), MAXCOL); + wwprintstr(tempwin, 0, 0, wattr, tmp); + if(area_fuzidx) { + + x = atoi(area_maybe); + if(x) { + if(CFG->switches.get(arealistnos) and (isdigit(area_maybe[1]) or (area_maybe[1] == NUL))) { + for(n=0; nboard() == x) { + x = n; + goto RedrawAreas; + } + } + x = 0; // No match found + } + else { + for(n=0; n= 1 and x<=AL.size()) { + { + for(int a=0, at=AL.size(); aisseparator()) { + x++; + if(x > maximum_index) + x = minimum_index; + } + if(x != index) + display_line(); + #define _topidx (index-position) // Shorthand.. + #define _botidx (index+(maximum_position-position)) // Shorthand.. + if((_topidx <= x) and (x <= _botidx)) { + position += (x-index); + index = x; + display_page(); /////////// NEW + } + else { + index = x; + center(); + } + break; + } + else { + // Regular search + for(n=0; nechoid(); + if(strnicmp(area_maybe, adesc, area_fuzidx) == 0) { + AL.Sort(); + AreasRenumber(); + x = AL.AreaEchoToNo(adesc); + goto RedrawAreas; + } + } + // Search inside + for(n=0; nechoid(); + if(striinc(area_maybe, adesc)) { + AL.Sort(); + AreasRenumber(); + x = AL.AreaEchoToNo(adesc); + goto RedrawAreas; + } + } + } + } + else { + adesc = AL[index]->echoid(); + AL.Sort(); + AreasRenumber(); + index = AL.AreaEchoToNo(adesc); + center(); + } + break; + } + } + } + if(not PlayMacro(key, KT_A)) + SayBibi(); + } + + return true; +} + +// ------------------------------------------------------------------ + +int GPickArealist::Run(const char* _title, int wpos, int& idx) { + + HandleGEvent(EVTT_AREALIST); + + xpos = 0; // Window starting coloumn + ypos = wpos; // Window starting row + xlen = MAXCOL-2; // Window ending coloumn + ylen = MAXROW-wpos-4; // Window ending row + title = _title; // Window title + btype = W_BAREA; // Window border type + battr = C_AREAB; // Window border attributes + wattr = C_AREAW; // Window Color + tattr = C_AREAT; // Window Title Color + sattr = C_AREAS; // Window Selection Bar Color + hattr = C_AREAQ; // Window Highlight Color + sbattr = C_AREAPB; // Window Scrollbar Color + helpcat = H_Area; // Window Help Category + + maximum_index = AL.size() - 1; // List Entries - 1 + maximum_position = MinV((size_t)ylen-1, AL.size()-1); // Display Pos + index = AL.AreaIdToNo(idx); // List Index + listwrap = CFG->switches.get(displistwrap); // True if wrap-around is supported + esc_abort = (wpos!=0); + area_maxfuz = MinV(sizeof(Echo), MAXCOL-strlen(title)-1); + + goldmark = ' '; + + areanumbers = (uint*)throw_calloc(AL.size(), sizeof(uint)); + AreasRenumber(); + + run_picker(); + + throw_release(areanumbers); + + if(not aborted) + return AL[index]->areaid(); + + idx = AL[index]->areaid(); + + return -1; +} + + +// ------------------------------------------------------------------ + +int AreaPick(char* title, int wpos, int* idx) { + + GPickArealist p; + int new_area; + + if(gkbd.quitall) + return -1; + + PickArealist = &p; + + in_arealist = true; + new_area = p.Run(title, wpos, *idx); + in_arealist = false; + + PickArealist = NULL; + + return new_area; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gecarb.cpp b/golded3/gecarb.cpp new file mode 100644 index 0000000..398ea84 --- /dev/null +++ b/golded3/gecarb.cpp @@ -0,0 +1,475 @@ + +// ------------------------------------------------------------------ +// 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 + +// ------------------------------------------------------------------ + +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; + char* ptr; + 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 + + newline = (Line*)throw_xcalloc(1, sizeof(Line)); + 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 { + ptr = newline->text; + if(ptr and strnieql(ptr, "CC:", 3)) { + 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 carcon copies + 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); + + string temp; + // Fix the CC list in the message + if(cc and ccline) { + switch(CFG->carboncopylist) { + case CC_REMOVE: + // No list + break; + case CC_KEEP: + // Keep list as it was entered + break; + case CC_HIDDEN: + if(A == AA) { + sprintf(buf, "\001CC: %s %s", msg->To(), msg->dest.make_string(temp).c_str()); + ccline = AddKludge(ccline, buf); + } + for(n=0; nCCTo, LNG->ListCC); + if(A == AA) { + sprintf(buf, buf2, msg->To(), msg->dest.make_string(temp).c_str()); + ccline = AddLine(ccline, buf); + } + for(n=0; nTo(); + ++line_items; + } + for(n=0; n < cc; n++) + 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; + } + 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, vector &postareas, vector &postareas_attrs, int local_xps) { + + 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, vector &postareas) { + + if(CFG->crosspost == NO) + return; + char buf[256]; + char *ptr; + bool ignorexc = false; + Line* newline; + Line* xcline = NULL; + int margintext; + bool xphide; + int local_xps = postareas.size(); + vector postareas_attrs(local_xps); + bool hideoriginal = false; + + // Insert empty line at the top first for practical purposes + + newline = (Line*)throw_xcalloc(1, sizeof(Line)); + 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))) { + + ptr = newline->text; + if(not ignorexc and ptr and (strnieql(ptr, "XC:", 3) or strnieql(ptr, "XP:", 3))) { + 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((local_xps < postareas.size()+1) and xcline) { + 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); + } + + string hline = ""; + 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); + } + + 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); + } + } + } + } + } + + // Reset line pointer + + msg->lin = DeleteLine(msg->lin); // Delete the empty top line again +} + + +// ------------------------------------------------------------------ diff --git a/golded3/gecfgg.h b/golded3/gecfgg.h new file mode 100644 index 0000000..159be42 --- /dev/null +++ b/golded3/gecfgg.h @@ -0,0 +1,527 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// The main GoldED configuration structure. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +enum en_gswitches { + internetlookup, + kludgechrs, + mouse, + displocalhigh, + arealistgroupid, + askdelorig, + lookuplocal, + dispstatusline, + screenusebios, + highlightunread, + akamatchlocal, + fidonullfix, + dispautonext, + lookupuserbase, + areakeeplast, + filelistpagebar, + printformfeed, + arealistnos, + disppagebar, + internetreply, + arealistpagebar, + usemsgid, + lookupnet, + squishdirect, + fidohwmarks, + msglistpagebar, + beepnoises, + screenshadows, + dispsoftcr, + emptytearline, + menudropmsg, + beeplocalmsg, + statuslineclock, + twitto, + keybdefaults, + displistwrap, + quotespacing, + lookupecho, + keybext, + beepcomment, + rcvdisablescfm, + quoteblank, + keybclear, + dosprompt, + areacatchupread, + formfeedseparator, + useflags, + jamharddelete, + disprealmsgno, + frqwazoo, + msglistviewsubj, + akamatchecho, + areafilegroups, + areaautonext, + timeoutsavemsg, + nodelistwarn, + akamatchnet, + + gswitches_last +}; + +class gswitches { + +public: + + inline bool get(en_gswitches what) { return cfg[what]; } + inline void set(en_gswitches what, bool value) { cfg[what] = value; } + + bool handle(word crc, const char* value); + + gswitches() { for(uint i=0; i cmdkey; + vector macro; + + int addressbookadd; + int addresslookupfirst; + vector addressmacro; + Path adeptxbbspath; + int adeptxbbsuserno; + vector aka; + vector akamatch; + int areaautoid; + Echo areacfmreplyto; + bool areacopydirect; + Echo areacopyto; + bool areacopyaddid; + gstrarray areaexcl; + bool areaforwarddirect; + int areafilegroups; // areausegroups; + bool areafreqdirect; + Echo areafreqto; + gstrarray areaincl; + gstrarray areaisemail; + gstrarray areaisnews; + int arealistechomax; + char arealistformat[80]; + char arealistsort[20]; // areasort[10]; + int arealisttype; + Path areapath; + gstrarray areapmscan; + gstrarray areapmscanexcl; + gstrarray areapmscanincl; + int areareadonly; + vector arearename; + bool areareplydirect; + Echo areareplyto; + gstrarray areascan; + gstrarray areascanexcl; + gstrarray areascanincl; + char areascansort[20]; + Echo areastart; // startecho; + int areatypeorder[17]; + Echo areayouwroteto; + Path attachpath; + Attr attribsattach; + Attr attribscc; // ccattrib; + Attr attribscfm; // cfmattrib; + Attr attribsecho; // echoattrib; + Attr attribsemail; + Attr attribsfrq; + Attr attribslocal; // localattrib; + Attr attribsnet; // netattrib; + Attr attribsnews; + int beepfactor; + int beepyourmail; + int carboncopylist; // cclist; + Win color[16]; + Path confirmfile; // goldedcfm; + int confirmresponse; + Path cookiepath; + int crosspost; + int crosspostlist; // xplist; + int ctrlinfoecho; + int ctrlinfoemail; + int ctrlinfolocal; + int ctrlinfonet; + int ctrlinfonews; + int dispareano; + int dispattachsize; + PosLen disphdrdateset; + PosLen disphdrnameset; + PosLen disphdrnodeset; + int displistcursor; + int dispmargin; // rightmargin; + int dispmsgsize; + uint disptabsize; // tabsize; + bool encodeemailheaders; + vector event; + int externoptions; + vector externutil; + Ezycom ezycom; + int ezycomuserno; + Path fidolastread; // lastread; + int fidomsgtype; + Path fidouserlist; + int fidouserno; // lastreaduser; + vector filealias; + bool forcetemplate; + gstrarray frqext; + vector frqnodemap; + int frqoptions; + bool gedhandshake; + Path goldbasepath; + Path goldbasesyspath; + int goldbaseuserno; + Path goldpath; + int happybirthday; + bool hidestylies; + Path hudsonpath; + long hudsonsizewarn; + Path hudsonsyspath; + int hudsonuserno; + bool ignorecharset; + char importbegin[80]; + char importend[80]; + Path inboundpath; + Path inputfile; + bool intensecolors; + IAdr internetaddress; + char internetdomain[96]; + Node internetgate; + bool internetmsgid; + bool internetrfcbody; + InetServers internetserver; + Invalidate invalidate; + Path jampath; + int keybmode; + char keybstack[80]; // keybuf[80]; + gstrarray kludge; + Path loadlanguage; + Path logfile; // goldedlog; + int logformat; + vector mailinglist; + vector< pair > mappath; + int menumarked; + int msglistdate; + bool msglistfast; + bool msglistfirst; + bool msglistheader; + bool msglistwidesubj; + Path namesfile; + Name nickname; + Path nodepath; + Path nodepathfd; + Path nodepathv7; + INam organization; + gstrarray origin; + int originno; + Path outboundpath; + Path outputfile; + Path pathreportfile; + Path pcboardpath; + int pcboarduserno; + int personalmail; + GPlay play; + Path printdevice; // p_device; + char printinit[80]; // p_init[80]; + int printlength; // p_length; + int printmargin; // p_margin; + char printreset[80]; // p_reset[80]; + Path quotebuffile; + int quotebufmode; + char quotechars[11]; + uint quotectrl; + int quotemargin; + char quotestring[10]; + bool quotewraphard; + int ra2usersbbs; // RA2; + int replylink; + int replylinklist; + gstrarray robotname; + int screenblanker; // blanktime; + int screenblankertype; + int screenmaxcol; // maxcols; + int screenmaxrow; // maxrows; + int screenpalette[17]; + int screensize; + INam searchfor; + Semaphore semaphore; + int sharemode; // share; + bool showdeleted; + Path soundpath; + Echo soupbadmsgs; + Echo soupemail; + int soupexportmargin; + Path soupexportpath; + Path soupimportpath; + Path soupnewsrcfile; + Path soupreplylinker; + char soupreplyto[60]; + Path souptosslog; + int squishscan; + int squishuserno; + Path squishuserpath; + int statuslinehelp; + char stylecodepunct[41]; + char stylecodestops[41]; + gstrarray tagline; + int taglineno; + char taglinechar; + bool taglinesupport; + char tasktitle[60]; + Tear tearline; + bool titlestatus; + vector tpl; + int tplno; + bool templatematch; + Path templatepath; + Path temppath; + int timeout; + int twitmode; // showtwits; + vector twitname; + gstrarray twitsubj; + bool usecharset; + int usefwd; + bool useintl; + bool usepid; + Path userlistfile; // goldedlst; + vector username; + int usernameno; + bool usestylies; + bool usetzutc; + Path uudecodepath; + bool viewhidden; + bool viewkludge; + bool viewquote; + Name whoto; + int wildcatuserno; + vector xlatcharset; + vector xlatescset; + char xlatexport[17]; // exportcharset[17]; + char xlatimport[17]; // localcharset[17]; + char xlatlocalset[17]; + Path xlatpath; + int zonegating; + + gswitches switches; +}; + + + +// ------------------------------------------------------------------ + +class GSaveUtil : public GStrBag2 { + +public: + + void Add(int n, char* s) { GStrBag2::Add((void*)&n, sizeof(n), s); } + + int Number() { return *(int*)Current1(); } + const char* Text() { return Current2(); } + + int Number(int i) { return *(int*)Index1(i); } + const char* Text(int i) { return Index2(i); } +}; + + +// ------------------------------------------------------------------ + +class GEditTrigger : public GStrBag2 { + +public: + + const char* Trigger() { return Current1(); } + const char* Text() { return Current2(); } + + const char* Trigger(int i) { return Index1(i); } + const char* Text(int i) { return Index2(i); } +}; + + +// ------------------------------------------------------------------ + +class GoldedCfgEdit { + +protected: + + // ----------------------------------------------------------------- + // Configuration data + + struct { + + // Boolean values + uint autoattach : 1; + uint crlfterm : 1; + uint fieldclear : 1; + uint hardlines : 1; + uint hardterm : 1; + uint headerattrs : 1; + uint internal : 1; + uint menu : 1; + uint mixcase : 1; + uint savemenu : 1; + + // Multi values + uint changedate; + int autosave; + char charpara; + char charspace; + int hdrnamepos; + int hdrnamelen; + int hdrnodepos; + int hdrnodelen; + int headerfirst; + long msgsize; + int quotemargin; + int replyre; + char softcrxlat; + int undelete; + + // String handles + int external; + int file; + int hardline; + int spellchecker; + } cfg; + + // ----------------------------------------------------------------- + // String bag + + gstrarray str; + +public: + + // ----------------------------------------------------------------- + // Configuration data + + GEditTrigger Comment; + GEditTrigger Completion; + GSaveUtil SaveUtil; + + + // ----------------------------------------------------------------- + // Constructor/destructor + + GoldedCfgEdit(); + + // ----------------------------------------------------------------- + // Return values + + bool AutoAttach() { return cfg.autoattach; } + int AutoSave() { return cfg.autosave; } + int ChangeDate() { return cfg.changedate; } + char CharPara() { return cfg.charpara; } + char CharSpace() { return cfg.charspace; } + bool CrLfTerm() { return cfg.crlfterm; } + const char* External() { return str[cfg.external].c_str(); } + bool FieldClear() { return cfg.fieldclear; } + const char* File() { return str[cfg.file].c_str(); } + const char* HardLine() { return str[cfg.hardline].c_str(); } + bool HardLines() { return cfg.hardlines; } + bool HardTerm() { return cfg.hardterm; } + int HdrNamePos() { return cfg.hdrnamepos; } + int HdrNameLen() { return cfg.hdrnamelen; } + int HdrNodePos() { return cfg.hdrnodepos; } + int HdrNodeLen() { return cfg.hdrnodelen; } + bool HeaderAttrs() { return cfg.headerattrs; } + int HeaderFirst() { return cfg.headerfirst; } + bool Internal() { return cfg.internal; } + bool Menu() { return cfg.menu; } + bool MixCase() { return cfg.mixcase; } + long MsgSize() { return cfg.msgsize; } + int QuoteMargin() { return cfg.quotemargin; } + int ReplyRe() { return cfg.replyre; } + bool SaveMenu() { return cfg.savemenu; } + char SoftCrXlat() { return cfg.softcrxlat; } + const char* SpellChecker() { return str[cfg.spellchecker].c_str(); } + int UnDelete() { return cfg.undelete; } + + // ----------------------------------------------------------------- + // Set values + + void AutoAttach(bool s) { cfg.autoattach = s; } + void AutoSave(int s) { cfg.autosave = s; } + void ChangeDate(int s) { cfg.changedate = s; } + void CharPara(char s) { cfg.charpara = s; } + void CharSpace(char s) { cfg.charspace = s; } + void CrLfTerm(bool s) { cfg.crlfterm = s; } + void External(char* s) { str[cfg.external] = s; } + void FieldClear(bool s) { cfg.fieldclear = s; } + void File(char* s) { str[cfg.file] = s; } + void HardLine(char* s) { str[cfg.hardline] = s; } + void HardLines(bool s) { cfg.hardlines = s; } + void HardTerm(bool s) { cfg.hardterm = s; } + void HdrNamePos(int p) { cfg.hdrnamepos = p; } + void HdrNameLen(int l) { cfg.hdrnamelen = l; } + void HdrNodePos(int p) { cfg.hdrnodepos = p; } + void HdrNodeLen(int l) { cfg.hdrnodelen = l; } + void HeaderAttrs(bool s) { cfg.headerattrs = s; } + void HeaderFirst(int s) { cfg.headerfirst = s; } + void Internal(bool s) { cfg.internal = s; } + void Menu(bool s) { cfg.menu = s; } + void MixCase(bool s) { cfg.mixcase = s; } + void MsgSize(long s) { cfg.msgsize = s; } + void QuoteMargin(int s) { cfg.quotemargin = s; } + void ReplyRe(int s) { cfg.replyre = s; } + void SaveMenu(bool s) { cfg.savemenu = s; } + void SoftCrXlat(char s) { cfg.softcrxlat = s; } + void SpellChecker(char* s) { str[cfg.spellchecker] = s; } + void UnDelete(int s) { cfg.undelete = s; } +}; + + +// ------------------------------------------------------------------ + diff --git a/golded3/gecmfd.cpp b/golded3/gecmfd.cpp new file mode 100644 index 0000000..9748b81 --- /dev/null +++ b/golded3/gecmfd.cpp @@ -0,0 +1,590 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Copy, Move, Forward and Delete. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ +// Global data from GEREAD + +extern GMsg* reader_msg; + + +// ------------------------------------------------------------------ + +void Area::DeleteMsg(GMsg* msg, int direction) { + + ulong replyto=0, reply1st=0, lread; + + GMsg* uplink = (GMsg*)throw_calloc(1, sizeof(GMsg)); + GMsg* downlink = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + if(msg->msgno) { + + // Fix the lastread pointer + lread = Msgn.CvtReln(lastread()); + if(msg->msgno == lread) { + uint l = lastread(); + if(direction == DIR_PREV) { + if(l-1) { + l--; + } + else if((l+1) <= Msgn.Count()) + l++; + else + l = 0; + } + else { + if((l+1) <= Msgn.Count()) + l++; + else if(l-1) + l--; + else + l = 0; + } + set_lastread(l); + lread = Msgn.CvtReln(lastread()); + } + + // Get reply links + if(Msgn.ToReln(msg->link.to())) { + replyto = msg->link.to(); + } + if(Msgn.ToReln(msg->link.first())) { + reply1st = msg->link.first(); + } + if(replyto) { + if(not LoadHdr(downlink, replyto)) + downlink->link.first_set(0); + } + if(reply1st) { + if(not LoadHdr(uplink, reply1st)) + uplink->link.to_set(0); + } + + // -------------------------------------------------------------- + // Diagram of splicing the links of a deleted msg + // -------------------------------------------------------------- + // Reply1st Replyto + // ÚÄÄÄÄÄÄÄÄÄÄ¿ + // Downlink --> Deleted --> Uplink + // ÀÄÄÄÄÄÄÄÄÄÄÄÙ + // Reply1st Replyto Confused ? :-) + // -------------------------------------------------------------- + + // Only update the up/downlinks if they are pointing to this msg + if(replyto) { + if(downlink->link.first() == msg->msgno) { + downlink->link.first_set(reply1st); + SaveHdr(GMSG_UPDATE, downlink); + } + else { + replyto = 0; + } + } + if(reply1st) { + if(uplink->link.to() == msg->msgno) { + uplink->link.to_set(replyto); + SaveHdr(GMSG_UPDATE, uplink); + } + } + + // Delete the message + msg->attr.del1(); + DelMsg(msg); + + // Update scanning files + if(isnet() and isfido()) + TouchNetscan(false); + + // Remove message from internal table + Msgn.Del(msg->msgno); + + // Update lastreads + if(Msgn.Count()) + set_lastread(Msgn.ToReln(lread)); + else + set_lastread(0); + msg->msgno = lread; + UpdateAreadata(); + } + + ResetMsg(downlink); + throw_free(downlink); + + ResetMsg(uplink); + throw_free(uplink); +} + + +// ------------------------------------------------------------------ + +void Area::DelMsgs(GMsg* msg) { + + GFTRK("DelMsgs"); + + uint n, x; + int topline=0; + bool delask=true, dellocked=false; + + n = 0; + if(Mark.Count()) { + GMenuDomarks MenuDomarks; + n = MenuDomarks.Run(LNG->Delete); + if(n == 1) { + HandleGEvent(EVTT_MSGDELETING); + w_progress(MODE_NEW, C_INFOW, 0, Mark.Count(), LNG->Deleting); + Lock(); + int escaped = false; + for(n=0; nDeletingMsg, x+1, Mark.Count()); + w_progress(MODE_UPDATE, C_INFOW, x+1, Mark.Count(), LNG->Deleting); + ulong msgno = Mark[x]; + if(Msgn.ToReln(msgno)) { + if(LoadHdr(msg, msgno)) { + bool deletethis = false; + if(delask) { + if(msg->attr.uns() and not (msg->attr.rcv() or msg->attr.del())) { + AA->LoadMsg(msg, msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + w_progress(MODE_QUIT, 0, 0, 0, NULL); + HeaderView->Use(AA, msg); + HeaderView->Paint(); + BodyView->Use(AA, msg, topline); + BodyView->Paint(); + GMenuDelete MenuDelete; + switch(MenuDelete.Run(YES, msg)) { + case YES: // Yes, delete + deletethis = true; + break; + case NO: // No, dont delete + continue; + default: // Delete without asking + delask = false; + if(msg->attr.lok()) + dellocked = true; + } + } + } + if(msg->attr.lok() and not dellocked and not deletethis) { + AA->LoadMsg(msg, msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + w_progress(MODE_QUIT, 0, 0, 0, NULL); + HeaderView->Use(AA, msg); + HeaderView->Paint(); + BodyView->Use(AA, msg, topline); + BodyView->Paint(); + GMenuDelete MenuDelete; + switch(MenuDelete.Run(YES, msg)) { + case YES: // Yes, delete + break; + case NO: // No, dont delete + continue; + default: // Delete without asking + dellocked = true; + } + } + DeleteMsg(msg, DIR_PREV); + PMrk.Del(msg->msgno); + } + } + } + Unlock(); + if(not escaped) { + isreadmark = false; + Mark.ResetAll(); + } + w_progress(MODE_QUIT, 0, 0, 0, NULL); + } + } + if(n == 0) { + Mark.Del(msg->msgno); + PMrk.Del(msg->msgno); + GMenuDelete MenuDelete; + if(Mark.Count() or MenuDelete.Run(NO, msg)) { + HandleGEvent(EVTT_MSGDELETING); + DeleteMsg(msg, reader_direction); + } + } + + HandleGEvent(EVTT_BREAKLOOP); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void TwitDeleteMsg(GMsg* msg) { + + GFTRK("TwitDeleteMsg"); + + HandleGEvent(EVTT_MSGDELETING); + AA->Mark.Del(msg->msgno); + AA->PMrk.Del(msg->msgno); + AA->DeleteMsg(msg, reader_direction); + HandleGEvent(EVTT_BREAKLOOP); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void Area::DelMsg() { + + if(Msgn.Count()) + DelMsgs(reader_msg); +} + + +// ------------------------------------------------------------------ + +void CmfMsgs(GMsg* msg) { + + // Select action + GMenuCMF MenuCMF; + int cmf = MenuCMF.Run(); + if(cmf == -1) + return; + + // Set language strings + char* pickstr = NULL; + char* markstr = NULL; + char* progstr = NULL; + char* statstr = NULL; + int loadmode = GMSG_UNS_NOT_RCV; + switch(cmf) { + case MODE_COPY: + GFTRK("CopyMsgs"); + pickstr = LNG->CopyArea; + markstr = LNG->Copy; + progstr = LNG->Copying; + statstr = LNG->CopyingMsg; + loadmode |= GMSG_COPY; + break; + case MODE_MOVE: + GFTRK("MoveMsgs"); + pickstr = LNG->MoveArea; + markstr = LNG->Move; + progstr = LNG->Moving; + statstr = LNG->MovingMsg; + loadmode |= GMSG_MOVE; + break; + case MODE_FORWARD: + GFTRK("ForwardMsgs"); + pickstr = LNG->ForwardArea; + break; + } + + // Do with current or marked msgs? + int do_mode = MODE_CURRENT; + if(cmf != MODE_FORWARD) { + if(AA->Mark.Count()) { + GMenuDomarks MenuDomarks; + do_mode = MenuDomarks.Run(markstr); + if(do_mode == MODE_DONT) { + GFTRK(NULL); + return; + } + } + } + + // Pick the destination area + int destarea = CurrArea; + const char* cmfptr = cmf == MODE_FORWARD ? AA->Areareplyto() : AA->Areacopyto(); + if(*cmfptr) { + int a = AL.AreaEchoToNo(cmfptr); + if(a != -1) + destarea = AL.AreaNoToId(a); + } + if(cmf == MODE_FORWARD ? not AA->Areaforwarddirect() : not AA->Areacopydirect()) + destarea = AreaPick(pickstr, 6, &destarea); + if(destarea == -1) { + GFTRK(NULL); + return; + } + + AL.SetActiveAreaId(OrigArea); + AreaData* orig_adat = AA->adat; + AA->adat = (AreaData*)throw_calloc(1, sizeof(AreaData)); + memcpy(AA->adat, orig_adat, sizeof(AreaData)); + AL.SetActiveAreaId(destarea); + Area* AAdest = AA; + + // Is it readonly? + if(AA->attr().r_o()) { + GMenuReadonly MenuReadonly; + if(not MenuReadonly.Run()) { + AL.SetActiveAreaId(OrigArea); + throw_free(AA->adat); + AA->adat = orig_adat; + GFTRK(NULL); + return; + } + } + + // Handle a forward + if(cmf == MODE_FORWARD) { + extern int _use_fwd; + _use_fwd = orig_adat->usefwd; + if(_use_fwd == ASK) { + GMenuForward MenuForward; + _use_fwd = MenuForward.Run(); + } + if(CurrArea != OrigArea) + AA->Open(); + MakeMsg(MODE_FORWARD, msg); + AL.SetActiveAreaId(OrigArea); + throw_free(AA->adat); + AA->adat = orig_adat; + GFTRK(NULL); + return; + } + + // Popup wait window + w_info(progstr); + + // Open destination area and lock it + AA->Open(); + AA->Lock(); + AA->RandomizeData(); + + // Re-activeate original area and lock that too + AL.SetActiveAreaId(OrigArea); + AA->Lock(); + + // Setup some variables for the loop + Area* AAorig = AA; + const char* echoid = AAdest->echoid(); + ulong loadmsgno = msg->msgno; + ulong* mrkp = AA->Mark.tag; + int mrks = AA->Mark.Count(); + int mrk = 0; + + // Copy/move loop + do { + + // Check for escape key + if(kbxhit()) { + if(kbxget() == Key_Esc) { + HandleGEvent(EVTT_JOBFAILED); + break; + } + } + + // Show progress and load the marked msg + if(do_mode == MODE_MARKED) { + update_statuslinef(statstr, mrk+1, mrks, echoid); + loadmsgno = *mrkp++; + } + + int mode = 0; + ulong msgno = 0; + if(AA->LoadMsg(msg, loadmsgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar), loadmode)) { + + // Handle unsent msgs + mode = cmf; + if((cmf == MODE_MOVE) and (loadmode & GMSG_UNS_NOT_RCV) and (msg->attr.uns() and not msg->attr.rcv())) { + + // Axe the popup wait window + w_info(NULL); + + // Display header and message + int top = 0; + HeaderView->Use(AA, msg); + HeaderView->Paint(); + BodyView->Use(AA, msg, top); + BodyView->Paint(); + + // Ask if it should be deleted + GMenuDelete MenuDelete; + switch(MenuDelete.Run(YES, msg)) { + case YES: break; + case NO: mode = MODE_COPY; break; + default: loadmode &= ~GMSG_UNS_NOT_RCV; + } + + // Put up the wait window again + w_info(progstr); + } + + // Switch to destination area + AA = AAdest; + + // Change things in the header to match the destination area + msg->attr.del0(); // Allows deleted msgs to be undeleted + msg->board = AA->board(); + msg->link.reset(); + + // Fake Scn-Attribute if copied to squisharea + if(AA->issquish() and not AAorig->issquish()) + if(msg->attr.loc() and msg->attr.snt()) + msg->attr.scn1(); + + if(AA->Areacopyaddid() and not AA->isnet()) { + char* ptr = msg->txt + (*msg->txt == CTRL_A); + if(not strnieql(ptr, "AREA:", 5)) { + uint elen = 6 + strlen(AAorig->echoid()) + 1; + uint mlen = strlen(msg->txt)+1; + msg->txt = (char*)throw_realloc(msg->txt, elen+mlen); + memmove(msg->txt+elen, msg->txt, mlen); + sprintf(msg->txt, "\001AREA:%s", AAorig->echoid()); + msg->txt[elen-1] = CR; + } + } + + bool need_netmail_kludges = not AAorig->isnet() and AAdest->isnet(); + bool need_fmpt = true; + bool need_topt = true; + + if(not need_netmail_kludges and AAorig->issquish() and not AAdest->issquish() and AAdest->isnet() and AAorig->isnet()) { + if(msg->orig.point and not strstr(msg->txt, "\001FMPT")) + need_netmail_kludges = true; + else + need_fmpt = false; + if(msg->dest.point and not strstr(msg->txt, "\001TOPT")) + need_netmail_kludges = true; + else + need_topt = false; + } + + if(need_netmail_kludges) { + char buf[256] = ""; + + if(not strstr(msg->txt, "\001INTL")) + // The INTL kludge for zone crossing + if(CFG->useintl and (CFG->useintl == YES or (msg->dest.zone != msg->orig.zone))) { + sprintf(buf, "\001INTL %u:%u/%u %u:%u/%u%c", + msg->dest.zone ? msg->dest.zone : AA->Aka().addr.zone, + msg->dest.net, msg->dest.node, + msg->orig.zone ? msg->orig.zone : AA->Aka().addr.zone, + msg->orig.net, msg->orig.node, CR + ); + } + + if(not strstr(msg->txt, "\001TOPT") or not strstr(msg->txt, "\001FMPT")) { + // The FMPT and TOPT kludges for point addressing + if(msg->dest.point and need_topt) + sprintf(buf+strlen(buf), "\001TOPT %u%c", msg->dest.point, CR); + if(msg->orig.point and msg->orig.net == msg->oorig.net and msg->orig.node == msg->oorig.node and need_fmpt) + sprintf(buf+strlen(buf), "\001FMPT %u%c", msg->orig.point, CR); + } + + uint alen = strlen(buf); + if(alen) { + uint mlen = strlen(msg->txt)+1; + msg->txt = (char*)throw_realloc(msg->txt, alen+mlen); + memmove(msg->txt+alen, msg->txt, mlen); + memmove(msg->txt, buf, alen); + } + } + else if(AA->isecho() and not AAorig->isecho()) { + + char* kl = strstr(msg->txt, "\001INTL"); + char* p; + if(kl and (p = strchr(kl, CR)) != NULL) + memmove(kl, p, strlen(p)+1); + kl = strstr(msg->txt, "\001TOPT"); + if(kl and (p = strchr(kl, CR)) != NULL) + memmove(kl, p, strlen(p)+1); + kl = strstr(msg->txt, "\001FMPT"); + if(kl and (p = strchr(kl, CR)) != NULL) + memmove(kl, p, strlen(p)+1); + } + + // Save the new msg to the destination area + msgno = msg->msgno; + AA->SaveMsg(GMSG_NEW|GMSG_NOLSTUPD, msg); + + // Switch back to original area + AA = AAorig; + } + + // Delete original msg if moved + if(mode == MODE_MOVE) { + msg->msgno = msgno; + AA->DeleteMsg(msg, DIR_PREV); + AA->PMrk.Del(msg->msgno); + } + + } while((do_mode == MODE_MARKED) and ((++mrk) < mrks)); + + kbput(Key_Tick); + + // Unlock and close destination area + AL.SetActiveAreaId(destarea); + AA->UpdateAreadata(); + AA->Unlock(); + AA->Close(); + + // Return to original area and unlock it + AL.SetActiveAreaId(OrigArea); + throw_free(AA->adat); + AA->adat = orig_adat; + AA->Unlock(); + + if(do_mode == MODE_MARKED) { + if(cmf == MODE_MOVE) + AA->Mark.ResetAll(); + } + else { + if(cmf == MODE_MOVE) { + AA->Mark.Del(msg->msgno); + AA->PMrk.Del(msg->msgno); + } + } + + w_info(NULL); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void CopyMoveForward() { + + ulong lastread = reader_msg->msgno; + + AA->set_lastread(AA->Msgn.ToReln(lastread, AA->lastread())); + + AA->attr().hex0(); + if(AA->Msgn.Count()) + CmfMsgs(reader_msg); + + AA->set_lastread(AA->Msgn.ToReln(lastread, AA->lastread())); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gectnr.cpp b/golded3/gectnr.cpp new file mode 100644 index 0000000..a82c4ba --- /dev/null +++ b/golded3/gectnr.cpp @@ -0,0 +1,128 @@ + +// ------------------------------------------------------------------ +// 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" + + +// ------------------------------------------------------------------ + +inline int isstylechar(char c) { return (c == '*') or (c == '/') or (c == '_') or (c == '#'); } + +void Container::StyleCodeHighlight(char* text, int row, int col, bool dohide, int color) { + + uint sclen = 0; + char* txptr = text; + char buf[200]; + 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 = ' '; + + if(dohide or CFG->usestylies) { + while(*ptr) { + if(isstylechar(*ptr)) { + if(strchr(punctchars, prevchar)) { + int bb = 0, bi = 0, bu = 0, br = 0; + 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) { + char* beginword = ptr; // _/*>another*/_ + char endchar = NUL; + char* end = ptr; + do { + end = strpbrk(++end, punctchars); + } while ((end) and not isstylechar(*(end-1))); + if(end) + endchar = *end; + else + end = ptr+strlen(ptr); + *end = NUL; + char* endstyle = end-1; // _/*another*/>_ + if(isstylechar(*endstyle) and not strchr(stylemargins, *beginword)) { + 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)) { + char endwordchar = *endword; + *endword = NUL; + char* style_stops_present = strpbrk(beginword, stylestopchars); + *endword = endwordchar; + 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; + } + } + } + } + *end = endchar; + ptr = end-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); + } +} + + +// ------------------------------------------------------------------ diff --git a/golded3/gectnr.h b/golded3/gectnr.h new file mode 100644 index 0000000..b4badfb --- /dev/null +++ b/golded3/gectnr.h @@ -0,0 +1,42 @@ + +// ------------------------------------------------------------------ +// 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. +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ + +class Container { + + virtual void prints(int, int, int, char*) = 0; + +public: + + virtual ~Container() { } + + void StyleCodeHighlight(char* text, int row, int col, bool dohide, int color); +}; + + +// ------------------------------------------------------------------ diff --git a/golded3/gectrl.cpp b/golded3/gectrl.cpp new file mode 100644 index 0000000..6882dfe --- /dev/null +++ b/golded3/gectrl.cpp @@ -0,0 +1,652 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Random system and control info handling. +// ------------------------------------------------------------------ + +#include +#include +#include +#include + + +// ------------------------------------------------------------------ + +int _use_fwd = true; + + +// ------------------------------------------------------------------ + +char* MakeOrigin(GMsg* msg, const char* orig) { + + char buf[256]; + char origin[100]; + + strxcpy(origin, orig, sizeof(origin)); + + if(msg->orig.net) + msg->orig.make_string(buf); + else + AA->Aka().addr.make_string(buf); + + if(*origin == '@') + GetRandomLine(origin, sizeof(origin), origin+1); + + sprintf(msg->origin, "%.*s (%s)", (int)(79 - 11 - 2 - strlen(buf) - 1), origin, buf); + return msg->origin; +} + + +// ------------------------------------------------------------------ + +char* MakeTearline(GMsg* msg, char* buf) { + + if(*msg->tearline == '@') + GetRandomLine(msg->tearline, sizeof(msg->tearline), msg->tearline+1); + + strcpy(stpcpy(buf, "--- "), strbtrim(msg->tearline)); + + return strtrim(buf); +} + + +// ------------------------------------------------------------------ + +void MakeFlags(GMsg* msg, Line** line, char* buf) { + + // The FrontDoor FLAGS netmail kludge + if(CFG->switches.get(useflags)) { + sprintf(buf, "\001FLAGS "); + if(AA->ishudson()) { + if(msg->attr.hld()) + strcat(buf, "HLD "); + if(msg->attr.frq()) + strcat(buf, "FRQ "); + } + if(msg->attr.imm()) + strcat(buf, "IMM "); + if(msg->attr.dir()) + strcat(buf, "DIR "); + if(msg->attr.tfs()) + strcat(buf, "TFS "); + if(msg->attr.kfs()) + strcat(buf, "KFS "); + if(msg->attr.lok()) + strcat(buf, "LOK "); + if(msg->attr.a_s()) + strcat(buf, "A/S "); + if(msg->attr.zon()) + strcat(buf, "ZON "); + if(msg->attr.hub()) + strcat(buf, "HUB "); + if(msg->attr.xma()) + strcat(buf, "XMA "); + if(msg->attr.cfm()) + strcat(buf, "CFM "); + if(msg->attr.hir()) + strcat(buf, "HIR "); + if(msg->attr.cov()) + strcat(buf, "COV "); + if(msg->attr.sig()) + strcat(buf, "SIG "); + if(msg->attr.let()) + strcat(buf, "LET "); + if(msg->attr.fax()) + strcat(buf, "FAX "); + if(strlen(buf) > 7) { + buf[strlen(buf)-1] = 0; + *line = AddKludge(*line, buf); + (*line)->kludge = GKLUD_FLAGS; + } + } +} + + +// ------------------------------------------------------------------ + +char* mime_header_encode(char* dest, const char* source, GMsg* msg) { + + bool inmime = false; + const char* s = source; + char* bp = dest; + const char* lp; + char* temp_src = (char*)throw_malloc(4096); + + if(*msg->charset) { + if((msg->charsetlevel&3) and ChsTP) { + char chln, *d = temp_src; + + for(uint len = 0; *s; s++) { + char* tptr = (char*)ChsTP[(byte)*s]; + chln = *tptr++; + while(chln-- and (len < 4096)) { + *(d++) = *tptr++; + ++len; + } + if(len == 4096) + break; + } + *d = NUL; + s = temp_src; + } + } + + if(CFG->encodeemailheaders) { + + lp = s + strlen(s); + + while((lp>s) and in_range((char)(*lp-1), (char)' ', (char)'\x7F')) + lp--; + + for(const char* ptr = s; *ptr and (ptr<=lp); ptr++) { + if((*ptr < ' ') or (*ptr > '\x7F') or (inmime and strchr(" =?", *ptr))) { + if(not inmime) { + if(msg->charset) { + strcpy(bp, "=?"); + bp += 2; + strcpy(bp, strlword(msg->charset)); + strlwr(bp); + bp += strlen(bp); + strcpy(bp, "?Q?"); + bp += 3; + } + else { + strcpy(bp, "=?iso-8859-1?Q?"); + bp += 15; + } + inmime = true; + } + sprintf(bp, "=%Xc", *ptr); + bp += 3; + } + else + *bp++ = *ptr; + } + + if(inmime) { + strcpy(bp, "?="); + bp += 2; + } + } + else + lp = s; + + strcpy(bp, lp); + throw_free(temp_src); + + return bp; +} + + +// ------------------------------------------------------------------ + +char* get_informative_string(char* buf) { + + sprintf(buf, "%s%s%s %s%i.%i.%i%s (%s)", + __gver_prename__, __gver_name__, __gver_postname__, + __gver_preversion__, __gver_major__, __gver_minor__, + __gver_release__, __gver_postversion__, ggetosstring()); + return buf; +} + + +// ------------------------------------------------------------------ + +void DoKludges(int mode, GMsg* msg, bool attronly) { + + char* buf = (char*)throw_malloc(4096); + char buf2[356]; + Line* line = msg->lin; + Line* newline; + + int __tzoffset = tzoffset(); + + // Insert empty line at the top for practical purposes + + newline = (Line*)throw_xcalloc(1, sizeof(Line)); + newline = line = InsertLine(newline, line, DIR_PREV); + + // Strip all the kludges we insert ourselves + + while(line) { + + int stripkludges = attronly ? GKLUD_FLAGS : (GKLUD_RFC|GKLUD_FWD|GKLUD_INTL|GKLUD_FMPT|GKLUD_TOPT|GKLUD_FLAGS|GKLUD_AREA|GKLUD_MSGID|GKLUD_REPLY|GKLUD_PID|GKLUD_CHARSET|GKLUD_KNOWN|(mode==MODE_FORWARD?(GKLUD_PATH|GKLUD_SEENBY):0)); + + if(line->kludge & stripkludges) { + bool waswrapped; + do { + waswrapped = (line->type & GLINE_WRAP) ? true : false; + line = DeleteLine(line); + } while(line and waswrapped); + } + else { + line = line->next; + } + } + + line = newline; + + if(attronly) { + if(AA->isnet()) + MakeFlags(msg, &line, buf); + } + else { + + if(not AA->isnet() and msg->areakludgeid) { + sprintf(buf, "\001AREA:%s", msg->areakludgeid); + line = AddKludge(line, buf); + line->kludge = GKLUD_AREA; + } + + if(AA->isnet()) { + + // The INTL kludge for zone crossing + if(CFG->useintl and (CFG->useintl == YES or (msg->dest.zone != msg->orig.zone))) { + sprintf(buf, "\001INTL %u:%u/%u %u:%u/%u", + msg->dest.zone ? msg->dest.zone : AA->Aka().addr.zone, + msg->dest.net, msg->dest.node, + msg->orig.zone ? msg->orig.zone : AA->Aka().addr.zone, + msg->orig.net, msg->orig.node + ); + line = AddKludge(line, buf); + line->kludge = GKLUD_INTL; + } + + // The FMPT and TOPT kludges for point addressing + if(msg->dest.point) { + sprintf(buf, "\001TOPT %u", msg->dest.point); + line = AddKludge(line, buf); + line->kludge = GKLUD_TOPT; + } + if(msg->orig.point and msg->orig.net == msg->oorig.net and msg->orig.node == msg->oorig.node) { + sprintf(buf, "\001FMPT %u", msg->orig.point); + line = AddKludge(line, buf); + line->kludge = GKLUD_FMPT; + } + + MakeFlags(msg, &line, buf); + } + + // The REPLY: kludge for Receiver identification + if(CFG->switches.get(usemsgid) and *msg->replys) { + sprintf(buf, "\001REPLY: %s", msg->replys); + line = AddKludge(line, buf); + line->kludge = GKLUD_REPLY; + } + + // The MSGID: kludge for Origination identification + if(AA->Internetmsgid() and *msg->iorig and AA->isinternet()) { + // User configured Internetdomain, use it + if(*CFG->internetdomain) { + strcpy(buf, CFG->internetdomain); + } + else { + // Fallback method. Yes, its "Crosspoint"-style. Yes, it's not + // Son-Of-RFC1036-compatible. Yes, I don't care. + // '%' in domain name activates some braindead spamfilters, so + // don't use it. I've had to realize that myself (Dirk). + strcpy(buf, msg->iorig); + strchg(buf, '@', '.'); + } + sprintf(buf2, "", time(NULL)+(msgcount++), buf); + throw_release(msg->messageid); + msg->messageid = throw_strdup(buf2); + CvtMessageIDtoMSGID(buf2, buf, AA->echoid(), "MSGID"); + strcpy(msg->msgids, buf+8); + } + else { + msg->orig.make_string(buf2, msg->odom); + sprintf(msg->msgids, "%s %08lx", buf2, time(NULL)+(msgcount++)); + } + if(CFG->switches.get(usemsgid) and not AA->ispcboard()) { + sprintf(buf, "\001MSGID: %s", msg->msgids); + line = AddKludge(line, buf); + line->kludge = GKLUD_MSGID; + } + + // The PID: (Product ID code) kludge + strcpy(msg->pid, __gver_shortpid__); + + if(CFG->usepid and (CFG->switches.get(emptytearline) or not (striinc(__gver_longpid__, msg->tearline)))) { + + sprintf(buf, "\001PID: %s", msg->pid); + line = AddKludge(line, strtrim(buf)); + line->kludge = GKLUD_PID; + } + + // The CHARSET kludge + if(CFG->usecharset and *msg->charset) { + *buf = NUL; + if(strieql(msg->charset, "I51")) + strcpy(buf, "\001I51"); + else if(not strieql(msg->charset, "COMPOSED")) + sprintf(buf, "\001%s: %s", CFG->switches.get(kludgechrs) ? "CHRS" : "CHARSET", msg->charset); + if(*buf) { + line = AddKludge(line, buf); + line->kludge = GKLUD_CHARSET; + } + } + + // The TZUTC kludge for timezone info + if(AA->Usetzutc()) { + sprintf(buf, "\001TZUTC: %0*d", (__tzoffset < 0) ? 5 : 4, __tzoffset); + line = AddKludge(line, buf); + line->kludge = GKLUD_KNOWN; + } + + // The FWD* kludges + if(_use_fwd) { + if(*msg->fwdfrom) { + sprintf(buf, "\001FWDFROM %s", msg->fwdfrom); + line = AddKludge(line, buf); + line->kludge = GKLUD_FWD; + } + if(msg->fwdorig.net) { + sprintf(buf, "\001FWDORIG %s", msg->fwdorig.make_string(buf2)); + line = AddKludge(line, buf); + line->kludge = GKLUD_FWD; + } + if(*msg->fwdto) { + sprintf(buf, "\001FWDTO %s", msg->fwdto); + line = AddKludge(line, buf); + line->kludge = GKLUD_FWD; + } + if(msg->fwddest.net) { + sprintf(buf, "\001FWDDEST %s", msg->fwddest.make_string(buf2)); + line = AddKludge(line, buf); + line->kludge = GKLUD_FWD; + } + if(*msg->fwdsubj) { + sprintf(buf, "\001FWDSUBJ %s", msg->fwdsubj); + line = AddKludge(line, buf); + line->kludge = GKLUD_FWD; + } + if(*msg->fwdarea) { + sprintf(buf, "\001FWDAREA %s", msg->fwdarea); + line = AddKludge(line, buf); + line->kludge = GKLUD_FWD; + } + if(*msg->fwdmsgid) { + sprintf(buf, "\001FWDMSGID %s", msg->fwdmsgid); + line = AddKludge(line, buf); + line->kludge = GKLUD_FWD; + } + } + + if(AA->isinternet()) { + + const char* rfc = AA->Internetrfcbody() ? "" : "\001"; + + char to_buf[256]; + *to_buf = NUL; + + if(*msg->idest or strchr(msg->to, '@')) { + char* ptr = *msg->idest ? msg->idest : msg->to; + sprintf(to_buf, "%s%sTo: %s", rfc, AA->isnewsgroup() ? "X-" : "", ptr); + if(not strieql(ptr, msg->realto) and *msg->realto) { + mime_header_encode(buf, msg->realto, msg); + sprintf(buf2, " (%s)", buf); + strcat(to_buf, buf2); + } + } + + if(*to_buf and AA->isemail()) { + line = AddKludge(line, to_buf); + line->kludge = GKLUD_RFC; + } + + if(*msg->iorig) { + mime_header_encode(buf2, msg->By(), msg); + sprintf(buf, "%sFrom: %s (%s)", rfc, msg->iorig, buf2); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + if(AA->isnewsgroup()) { + sprintf(buf, "%sNewsgroups: %s", rfc, strlwr(strcpy(buf2, AA->echoid()))); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + if(*msg->re) { + mime_header_encode(buf2, msg->re, msg); + sprintf(buf, "%sSubject: %s", rfc, buf2); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + struct tm* tm = gmtime(&msg->written); + sprintf(buf, "%sDate: %s, %02d %s %04d %02d:%02d:%02d", rfc, + __gsweekday[tm->tm_wday], + tm->tm_mday, __gsmonth[tm->tm_mon], 1900+tm->tm_year, + tm->tm_hour, tm->tm_min, tm->tm_sec + ); + if(AA->Usetzutc()) + sprintf(buf + strlen(buf), " %+05d", __tzoffset); + + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + + if(msg->messageid) { + sprintf(buf, "%sMessage-ID: %s", rfc, msg->messageid); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + if(msg->references) { + sprintf(buf, "%sReferences: %s", rfc, msg->references); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + if(msg->inreplyto) { + sprintf(buf, "%sIn-Reply-To: %s", rfc, msg->inreplyto); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + if(*msg->organization) { + sprintf(buf, "%sOrganization: %s", rfc, msg->organization); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + if(striinc("LATIN-1", msg->charset) or striinc("LATIN1QP", msg->charset) or striinc("ASCII", msg->charset)) { + sprintf(buf, "%sMIME-Version: 1.0", rfc); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + sprintf(buf, "%sContent-Type: text/plain; charset=%s", rfc, striinc("ASCII", msg->charset) ? "us-ascii" : "iso-8859-1"); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + sprintf(buf, "%sContent-Transfer-Encoding: %s", rfc, striinc("LATIN1QP", msg->charset) ? "quoted-printable" : striinc("ASCII", msg->charset) ? "7bit" : "8bit"); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + if(*to_buf and AA->isnewsgroup()) { + line = AddKludge(line, to_buf); + line->kludge = GKLUD_RFC; + } + + if(*msg->iorig) { + mime_header_encode(buf2, msg->By(), msg); + sprintf(buf, "%sSender: %s (%s)", rfc, msg->iorig, buf2); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + if((*msg->ireplyto or *CFG->soupreplyto) and (not streql(*msg->ireplyto ? msg->ireplyto : CFG->soupreplyto, msg->iorig))) { + sprintf(buf, "%sReply-To: %s", rfc, *msg->ireplyto ? msg->ireplyto : CFG->soupreplyto); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + if(striinc("MNEMONIC", msg->charset)) { + sprintf(buf, "%sX-Charset: ISO_8859-1", rfc); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + sprintf(buf, "%sX-Char-Esc: 29", rfc); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + if(AA->isnewsgroup() or AA->isemail()) { + sprintf(buf, "%sX-%s: %s", rfc, AA->isnewsgroup() ? "Newsreader" : "Mailer", get_informative_string(buf2)); + line = AddKludge(line, buf); + line->kludge = GKLUD_RFC; + } + + if(AA->Internetrfcbody() and line->next and not strblank(line->next->text)) { + line = AddKludge(line, ""); + line->kludge = GKLUD_RFC; + } + } + + if(AA->isnet()) { + Line* firstline = FirstLine(line); + firstline = firstline->next; + // 123456789012345678901234567 + if(strneql(firstline->text, "-----BEGIN PGP MESSAGE-----", 27)) { + line = AddKludge(line, "\001ENC: PGP"); + } + + if(*msg->iaddr and not AA->isinternet()) { + if(*msg->To() and (strpbrk(msg->iaddr, "<>()\"") == NULL) and not strieql(msg->To(), *AA->Internetgate().name ? AA->Internetgate().name : "UUCP")) { + Name name; + strcpy(name, msg->To()); + sprintf(buf, "To: \"%s\" <%s>\r", StripQuotes(name), msg->iaddr); + } + else + sprintf(buf, "To: %s\r", msg->iaddr); + line = AddKludge(line, buf); + } + } + } + + // Reset line pointer + msg->lin = DeleteLine(FirstLine(line)); + + MsgLineReIndex(msg, YES, YES, YES); + + throw_free(buf); +} + + +// ------------------------------------------------------------------ + +void DoTearorig(int mode, GMsg* msg) { + + uint ctrlinfo; + char buf[256]; + char* ptr; + Line* line = msg->lin; + Line* newline; + string origin; + + origin = AA->Origin(); + + if(AA->Taglinesupport()) { + if(*msg->tagline == '@') + GetRandomLine(msg->tagline, sizeof(msg->tagline), msg->tagline+1); + TokenXlat(mode, msg->tagline, msg, msg, CurrArea); + strbtrim(msg->tagline); + } + + TokenXlat(mode, msg->tearline, msg, msg, CurrArea); + + ctrlinfo = AA->Ctrlinfo(); + + if(not *msg->origin) + MakeOrigin(msg, origin.c_str()); + + // Delete current tag-, tear- and originlines + int deltypes = GLINE_TEAR|GLINE_ORIG; + if(AA->Taglinesupport()) + deltypes |= GLINE_TAGL; + while(line) { + if(line->type & deltypes) { + if(line == msg->lin) + msg->lin = NULL; + newline = line; + Line* nextline = newline->next; + line = DeleteLine(line); + if(nextline == NULL) + line = NULL; + } + else + line = line->next; + } + + // Make sure there is a blank line at the bottom, just before the tearline + // Unless the line is a tagline (..., ___ etc). + line = LastLine(msg->lin); + if(line == NULL) + msg->lin = line = AddLine(NULL, ""); + else { + ptr = line->text; + if(not strblank(ptr)) + if(not ((ptr[0] == ptr[1]) and (ptr[1] == ptr[2]))) + line = AddLine(line, ""); + } + + // Check and fix originline + if(*msg->origin) { + ptr = strrchr(msg->origin, '(' /*)*/ ); + if(ptr) { + + if(ptr != msg->origin) + *((ptr++)-1) = NUL; + else + *ptr++ = NUL; + + origin = msg->origin; + } + else + origin = msg->origin; + } + MakeOrigin(msg, origin.c_str()); + + TokenXlat(mode, msg->tagline, msg, msg, CurrArea); + TokenXlat(mode, msg->tearline, msg, msg, CurrArea); + TokenXlat(mode, msg->origin, msg, msg, CurrArea); + + // Add the tagline, tearline and origin as defined + if(AA->Taglinesupport() and *msg->tagline) { + sprintf(buf, "%c%c%c %s", AA->Taglinechar(), AA->Taglinechar(), AA->Taglinechar(), msg->tagline); + strtrim(buf); + line = AddLine(line, buf); + line->type |= GLINE_TAGL; + } + if(ctrlinfo & CI_TEAR) { + line = AddLine(line, MakeTearline(msg, buf)); + line->type |= GLINE_TEAR; + } + if(ctrlinfo & CI_ORIG) { + sprintf(buf, " * Origin: %s", msg->origin); + line = AddLine(line, buf); + line->type |= GLINE_ORIG; + } +} + + +// ------------------------------------------------------------------ diff --git a/golded3/ged2.ico b/golded3/ged2.ico new file mode 100644 index 0000000..276b9dd Binary files /dev/null and b/golded3/ged2.ico differ diff --git a/golded3/gedcyg.rc b/golded3/gedcyg.rc new file mode 100644 index 0000000..77a73b2 --- /dev/null +++ b/golded3/gedcyg.rc @@ -0,0 +1,3 @@ +#define ICON_1 1 + +ICON_1 ICON "gedw.ico" diff --git a/golded3/gedemx.rc b/golded3/gedemx.rc new file mode 100644 index 0000000..d303458 --- /dev/null +++ b/golded3/gedemx.rc @@ -0,0 +1,3 @@ +#include + +ICON 1 PRELOAD ged2.ico diff --git a/golded3/gedoit.cpp b/golded3/gedoit.cpp new file mode 100644 index 0000000..6d7bc03 --- /dev/null +++ b/golded3/gedoit.cpp @@ -0,0 +1,455 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Various major job handling funcs +// ------------------------------------------------------------------ + +#include +#include + +// ------------------------------------------------------------------ + +static FILE* prnfp; +static int prnmargin; +static int prnheader; + + +// ------------------------------------------------------------------ + +void SaveLines(int mode, const char* savefile, GMsg* msg, bool clip) { + + int prn=NO; + char fnam[GMAXPATH]; + char* prnacc; + + if(mode == MODE_SAVE or mode == MODE_SAVENOCTRL) + prnacc = "wt"; + else if(mode == MODE_APPEND) { + prnacc = "at"; + mode = MODE_WRITE; + } + else + prnacc = "wt"; + + strcpy(fnam, "PRN"); + if(mode == MODE_WRITE and streql(savefile, "\001PRN")) { + prn = YES; + #ifdef __UNIX__ + if(prnfp == NULL) + prnfp = popen(fnam, "w"); + #else + if(prnfp == NULL) + prnfp = fsopen(fnam, prnacc, CFG->sharemode); + #endif + } + else { + strcpy(fnam, savefile); + strschg_environ(fnam); + prnfp = fsopen(fnam, prnacc, CFG->sharemode); + } + int lines=0; + if(prnfp) { + if(mode == MODE_WRITE) { + if(prnheader) + DispHeader(msg, prn, prnfp, prnmargin); + if(prn) + lines = 6; + } + int n = 0; + Line** lin = msg->line; + if(lin and not (prnheader & WRITE_ONLY_HEADER)) { + Line* line = lin[n]; + while(line) { + if(line->text) { + uint lineisctrl = line->type & (GLINE_TEAR|GLINE_ORIG|GLINE_KLUDGE); + if(not ((mode == MODE_SAVENOCTRL) and lineisctrl)) { + char* ptr = line->text; + while(*ptr) { + if(mode == MODE_WRITE) { + // Replace control codes, except the ANSI escape code + if(*ptr < ' ') { + // only allow ESC in file write + if(prn or (*ptr != '\x1B')) { + *ptr = (*ptr == CTRL_A) ? '@' : '.'; + } + } + } + ptr++; + } + ptr = line->text; + fwrite(ptr, strlen(ptr), 1, prnfp); + if(mode == MODE_NEW) { + if(EDIT->HardLines()) { + if(line->type & GLINE_HARD) { + if(not ((line->type & (GLINE_TEAR|GLINE_ORIG|GLINE_KLUDGE|GLINE_QUOT)) or strblank(ptr))) { + fwrite(EDIT->HardLine(), strlen(EDIT->HardLine()), 1, prnfp); + } + } + } + } + fwrite(prn ? NL : "\n", prn ? sizeof(NL) : 1, 1, prnfp); + if(prn) { + lines++; + if(lines%CFG->printlength == 0 and CFG->switches.get(printformfeed)) { + fwrite("\f", 1, 1, prnfp); + } + } + } + } + line = lin[++n]; + } + } + // Add an empty line and formfeed at the bottom + if(mode == MODE_WRITE) { + fwrite(prn ? NL : "\n", prn ? sizeof(NL) : 1, 1, prnfp); + } + // Add formfeed if requested + if((prn and CFG->switches.get(printformfeed)) or + (not prn and not clip and CFG->switches.get(formfeedseparator))) { + fwrite("\f", 1, 1, prnfp); + } + if(not prn) + fclose(prnfp); + } + else { + char buf[256]; + sprintf(buf, LNG->CouldNotOpen, fnam); + w_info(buf); + waitkeyt(10000); + w_info(NULL); + } +} + + +// ------------------------------------------------------------------ + +void WriteMsgs(GMsg* msg) { + + if(AA->Msgn.Tags() == 0) + return; + + GFTRK("WriteMsgs"); + + char buf[256]; + char fname[GMAXPATH], ofname[GMAXPATH]; + + int overwrite = NO; + + prnfp = NULL; + + GMenuDomarks MenuDomarks; + int source = AA->Mark.Count() ? MenuDomarks.Run(LNG->Write) : WRITE_CURRENT; + + if(source != WRITE_QUIT) { + + GMenuWriteMsg MenuWriteMsg; + int target = MenuWriteMsg.Run(); + + if(target != WRITE_QUIT) { + + prnheader = (target & (WRITE_NO_HEADER|WRITE_ONLY_HEADER)) ^ WRITE_NO_HEADER; + + if(target & WRITE_PRINTER) + prnmargin = CFG->printmargin; + else + prnmargin = 79; + + if(source == WRITE_MARKED) { + if(target & WRITE_FILE) { + do { + overwrite = NO; + strcpy(CFG->outputfile, AA->Outputfile()); + if(not edit_pathname(CFG->outputfile, sizeof(Path), LNG->WriteMsgs, H_WriteMessage)) + goto Finish; + if(is_dir(CFG->outputfile)) { + AddBackslash(CFG->outputfile); + strcat(CFG->outputfile, "golded.txt"); + } + AA->SetOutputfile(CFG->outputfile); + w_infof(" %s ", AA->Outputfile()); + if(stricmp(AA->Outputfile(), "PRN") and strnicmp(AA->Outputfile(), "LPT", 3)) + if(fexist(AA->Outputfile())) { + GMenuOverwrite MenuOverwrite; + overwrite = MenuOverwrite.Run(); + } + } while(overwrite == -1); + } + else if(target & WRITE_PRINTER) { + #ifdef __UNIX__ + prnfp = popen(CFG->printdevice, "w"); + #else + prnfp = fsopen(CFG->printdevice, "wt", CFG->sharemode); + #endif + if(prnfp) + fwrite(CFG->printinit+1, CFG->printinit[0], 1, prnfp); + } + else if(target & WRITE_CLIPBRD) { + overwrite = YES; + strcpy(ofname, AA->Outputfile()); + mktemp(strcpy(fname, AddPath(CFG->goldpath, "GDXXXXXX"))); + AA->SetOutputfile(fname); + } + w_info(NULL); + w_progress(MODE_NEW, C_INFOW, 0, AA->Mark.Count(), LNG->Writing); + for(uint n=0; nMark.Count(); n++) { + if(overwrite and n) + overwrite = NO; // Overwrite only the first time + if(kbxhit()) { + if(kbxget() == Key_Esc) { + HandleGEvent(EVTT_JOBFAILED); + break; + } + } + update_statuslinef(LNG->WritingMsg, n+1, AA->Mark.Count()); + w_progress(MODE_UPDATE, C_INFOW, n+1, AA->Mark.Count(), LNG->Writing); + AA->LoadMsg(msg, AA->Mark[n], prnmargin); + if(target & WRITE_PRINTER) { + if(prnfp) + SaveLines(MODE_WRITE, "\001PRN", msg); + } + else { + SaveLines(overwrite ? MODE_WRITE : MODE_APPEND, AA->Outputfile(), msg, (target & WRITE_CLIPBRD) ? true : false); + } + } + if(prnfp) + fwrite(CFG->printreset+1, CFG->printreset[0], 1, prnfp); + if(target & WRITE_CLIPBRD) { + AA->SetOutputfile(ofname); + + gclipbrd clipbrd; + gfile fp; + + if(fp.fopen(fname, "rb")) { + + long len = fp.filelength(); + char* buf = (char*) throw_malloc(len+1); + buf[len] = NUL; + fp.fread(buf, 1, len); + + clipbrd.writeclipbrd(buf); + + throw_free(buf); + + fp.close(); + } + + remove(fname); + } + w_progress(MODE_QUIT, 0, 0, 0, NULL); + } + else if(source == WRITE_CURRENT) { + if(target & WRITE_FILE) { + do { + overwrite = NO; + strcpy(CFG->outputfile, AA->Outputfile()); + if(edit_pathname(CFG->outputfile, sizeof(Path), LNG->WriteMsgs, H_WriteMessage)) { + if(is_dir(CFG->outputfile)) { + AddBackslash(CFG->outputfile); + strcat(CFG->outputfile, "golded.txt"); + } + AA->SetOutputfile(CFG->outputfile); + w_infof(" %s ", AA->Outputfile()); + if(stricmp(AA->Outputfile(), "PRN") and strnicmp(AA->Outputfile(), "LPT", 3)) { + if(fexist(AA->Outputfile())) { + GMenuOverwrite MenuOverwrite; + overwrite = MenuOverwrite.Run(); + if(overwrite == -1) // Escape was hit + continue; + } + } + sprintf(buf, LNG->WritingFile, AA->Outputfile()); + w_info(buf); + AA->LoadMsg(msg, msg->msgno, prnmargin); + SaveLines(overwrite ? MODE_WRITE : MODE_APPEND, AA->Outputfile(), msg); + w_info(NULL); + } + } while(overwrite == -1); + } + else if(target & WRITE_PRINTER) { + w_info(LNG->WritingPRN); + AA->LoadMsg(msg, msg->msgno, prnmargin); + #ifdef __UNIX__ + prnfp = popen(CFG->printdevice, "w"); + #else + prnfp = fsopen(CFG->printdevice, "wt", CFG->sharemode); + #endif + if(prnfp) { + fwrite(CFG->printinit+1, CFG->printinit[0], 1, prnfp); + SaveLines(MODE_WRITE, "\001PRN", msg); + fwrite(CFG->printreset+1, CFG->printreset[0], 1, prnfp); + } + w_info(NULL); + } + else if(target & WRITE_CLIPBRD) { + w_info(LNG->Wait); + + mktemp(strcpy(fname, AddPath(CFG->goldpath, "GDXXXXXX"))); + + AA->LoadMsg(msg, msg->msgno, prnmargin); + SaveLines(MODE_WRITE, fname, msg, true); + + gclipbrd clipbrd; + gfile fp; + + if(fp.fopen(fname, "rb")) { + + long len = fp.filelength(); + char* buf = (char*) throw_malloc(len+1); + buf[len] = NUL; + fp.fread(buf, 1, len); + + clipbrd.writeclipbrd(buf); + + throw_free(buf); + + fp.close(); + } + + remove(fname); + w_info(NULL); + } + } + } + } + +Finish: + + w_info(NULL); + + if(prnfp) { + #ifdef __UNIX__ + pclose(prnfp); + #else + fclose(prnfp); + #endif + prnfp = NULL; + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void WriteMsg(GMsg* msg) { + + if(AA->Msgn.Count()) + WriteMsgs(msg); +} + + +// ------------------------------------------------------------------ +// Get name of current quotebuffer filename + +char* GetCurrQuotebuf(char* quotebuf) { + + if(*AA->Quotebuffile()) { + strcpy(quotebuf, AA->Quotebuffile()); + MakePathname(quotebuf, CFG->goldpath, quotebuf); + } + else { + if(AA->isezycom()) + sprintf(quotebuf, "%sgld%05u.qbf", CFG->ezycom.msgbasepath, AA->board()); + else if(AA->isfido()) + sprintf(quotebuf, "%s%s", AA->path(), "golded.qbf"); + else if(AA->isgoldbase()) + sprintf(quotebuf, "%sgoldg%03u.qbf", CFG->goldbasepath, AA->board()); + else if(AA->ishudson()) + sprintf(quotebuf, "%sgoldh%03u.qbf", CFG->hudsonpath, AA->board()); + else + sprintf(quotebuf, "%s%s", AA->path(), ".qbf"); + } + + return quotebuf; +} + + +// ------------------------------------------------------------------ + +void QuoteBuf(GMsg* msg) { + + if(AA->Msgn.Count()) { + + Path quotebuf; + char openmode[4]; + + TemplateToText(MODE_QUOTEBUF, msg, msg, AA->Tpl(), CurrArea); + msg->attr.tou1(); + msg->TextToLines(-CFG->quotemargin); + msg->attr.tou0(); + msg->charsetlevel = LoadCharset(CFG->xlatlocalset, CFG->xlatlocalset); + msg->LinesToText(); + + GetCurrQuotebuf(quotebuf); + w_infof(" %s ", quotebuf); + + switch(CFG->quotebufmode) { + + case QBUF_ASK: + *openmode = NUL; + if(fexist(quotebuf)) { + GMenuOverwrite MenuOverwrite; + switch(MenuOverwrite.Run()) { + case true: + strcpy(openmode, "wt"); + break; + case false: + strcpy(openmode, "at"); + break; + default: + *openmode = NUL; + } + } + else { + strcpy(openmode, "wt"); + } + break; + + case QBUF_APPEND: + strcpy(openmode, "at"); + break; + + case QBUF_OVERWRITE: + strcpy(openmode, "wt"); + break; + } + + if(*openmode) { + + FILE* fp = fsopen(quotebuf, openmode, CFG->sharemode); + if(fp) { + strchg(msg->txt, 0x0D, 0x0A); + fputs(msg->txt, fp); + fclose(fp); + } + + HandleGEvent(EVTT_JOBDONE); + waitkeyt(1000); + } + w_info(NULL); + } +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gedoss.cpp b/golded3/gedoss.cpp new file mode 100644 index 0000000..dbab58a --- /dev/null +++ b/golded3/gedoss.cpp @@ -0,0 +1,499 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// DOS Shell, cleanup, errorhandling etc. +// ------------------------------------------------------------------ + + +#include +#include +#include +#ifdef __UNIX__ +#include +#endif + + +// ------------------------------------------------------------------ + +extern GPickArealist* PickArealist; +extern bool in_arealist; + +// ------------------------------------------------------------------ +// Clean up the screen, memory and files before exiting to DOS + +void Cleanup(void) { + + if(CFG) { + + if(CFG->switches.get(areakeeplast) and startupscan_success) + AL.WriteGoldLast(); + + #ifndef GMB_NOXBBS + if(AL.msgbases & MT_ADEPTXBBS) + XbbsExit(); + #endif + #ifndef GMB_NOEZY + if(AL.msgbases & MT_EZYCOM) + EzycomExit(); + #endif + if(AL.msgbases & MT_FIDO) + FidoExit(); + #ifndef GMB_NOGOLD + if(AL.msgbases & MT_GOLDBASE) + GoldExit(); + #endif + #ifndef GMB_NOHUDS + if(AL.msgbases & MT_HUDSON) + HudsExit(); + #endif + #ifndef GMB_NOJAM + if(AL.msgbases & MT_JAM) + JamExit(); + #endif + #ifndef GMB_NOPCB + if(AL.msgbases & MT_PCBOARD) + PcbExit(); + #endif + #ifndef GMB_NOSQSH + if(AL.msgbases & MT_SQUISH) + SquishExit(); + #endif + #ifndef GMB_NOWCAT + if(AL.msgbases & MT_WILDCAT) + WCatExit(); + #endif + #ifndef GMB_NOSMB + if(AL.msgbases & MT_SMB) + SMBExit(); + #endif + + SearchExit(); + + // Free area data + AL.Reset(); + + // Free various lists + CFG->addressmacro.clear(); + CFG->aka.clear(); + CFG->akamatch.clear(); + CFG->event.clear(); + CFG->externutil.clear(); + CFG->filealias.clear(); + CFG->frqext.clear(); + CFG->frqnodemap.clear(); + CFG->kludge.clear(); + CFG->mailinglist.clear(); + CFG->mappath.clear(); + CFG->origin.clear(); + CFG->robotname.clear(); + CFG->tagline.clear(); + CFG->tpl.clear(); + CFG->twitname.clear(); + CFG->twitsubj.clear(); + CFG->username.clear(); + CFG->xlatcharset.clear(); + CFG->xlatescset.clear(); + CFG->cmdkey.clear(); + CFG->macro.clear(); + + // Free misc data + throw_xrelease(CharTable); + throw_xrelease(CompTable); + throw_xrelease(MNETable); + throw_xrelease(I51Table); + + throw_delete(QWK); + + if(errorlevel != EXIT_CFGERR) { + if(netpost) + TouchFile(AddPath(CFG->areapath, CFG->semaphore.netscan)); + if(echopost) + TouchFile(AddPath(CFG->areapath, CFG->semaphore.echoscan)); + } + + // Reset border color + if(C_BACKB != 0) + gvid->setoverscan(gvid->orig.color.overscan); + + wcloseall(); // Close all windows + if(in_arealist) + PickArealist->close_all(); // Unlink hidden area windows + whelpundef(); // Disengage the help system + kbclear(); // Clear CXL keyboard buffer + freonkey(); // Free all onkeys (macros) + FreePastebuf(); // Free the internal editor cut'n'paste buffer + + #if not defined(__UNIX__) and not defined(__USE_NCURSES__) + if(CFG->screenpalette[16]) + gvid->setpalette(gvid->orig.color.palette); + + if(gvid->curr.screen.mode != gvid->orig.screen.mode) + gvid->setmode(gvid->orig.screen.mode); + if(gvid->curr.screen.rows != gvid->orig.screen.rows) + gvid->setrows(gvid->orig.screen.rows); + + if(oldscreen) { + vrestore(oldscreen); + throw_xrelease(oldscreen); + } + if(CFG->intensecolors) + gvid->setintensity(gvid->orig.color.intensity); + vcurset(gvid->orig.cursor.start, gvid->orig.cursor.end); + #endif + + #ifndef __WIN32__ + vposset(gvid->orig.cursor.row, 0); + vputx(gvid->orig.cursor.row, 0, gvid->orig.color.textattr, ' ', gvid->orig.screen.columns); + #endif + + vposset(gvid->orig.cursor.row-1, 0); + vcurshow(); + } + throw_xdelete(BodyView); + throw_xdelete(HeaderView); + throw_xdelete(gvid); + + int smax = MinV((int)GLOG_STORELINES, LOG.storelines); + for(int s=0; s GLOG_STORELINES) + cout << "(See also " << CFG->logfile << ")" << endl; + if(errorlevel > EXIT_NONAME) + MakeNoise(SND_S_O_S); + + #if defined(GUTLOS_FUNCS) + g_deinit_os(); + #endif + + // Back to default Ctrl-Break handler + signal(SIGINT, SIG_DFL); +} + + +// ------------------------------------------------------------------ +// Multipurpose DOS shell function + +int ShellToDos(char* command, char* message, int cls, int cursor, int swap, int pause) { + + NW(swap); + + int error = 0; + + #if defined(GUTLOS_FUNCS) + char ge_temptitle[GMAXTITLE]; + #endif + + #ifndef __UNIX__ + if(strlen(command) > 125) { + w_info(" Warning: Command line longer than 125 characters! "); + waitkeyt(10000); + w_info(NULL); + } + #endif + + // Put up a wait window + if(shellvid) + w_info(LNG->Wait); + + #if defined(GUTLOS_FUNCS) + g_get_ostitle_name(ge_temptitle); + g_set_ostitle_name("OS Shell",0); + #endif + + // Close msgbase files + int _wasopen = AA->isopen(); + if(_wasopen) + AA->Suspend(); + + HandleGEvent(EVTT_DOSSHELL); + + // Change the prompt + #ifndef __UNIX__ + static char prompt[256]; + static char oldprompt[256]; + + if(CFG->switches.get(dosprompt)) { + #ifdef __DJGPP__ + const char* p = getenv("PROMPT"); + if(p) { + strcpy(oldprompt, p); + strcpy(stpcpy(prompt, LNG->Prompt), p); + setenv("PROMPT", prompt, true); + } + #else + int envn = 0; + while(environ[envn] and *environ[envn]) { + if(strnieql(environ[envn], "PROMPT=", 7)) { + strcpy(oldprompt, environ[envn]); + sprintf(prompt, "PROMPT=%s%s", LNG->Prompt, *oldprompt ? oldprompt+7 : ""); + environ[envn] = prompt; + break; + } + envn++; + } + #endif + } + #endif + + // Store the screen + vatch* scrnbuf = vsave(); + + // Store current drive/dir + Path orgdir; + getcwd(orgdir, sizeof(Path)); + + // Set cursor position + if(gvid->curr.screen.rows != gvid->orig.screen.rows) + gvid->setrows(gvid->orig.screen.rows); + if(gvid->curr.screen.mode != gvid->orig.screen.mode) + gvid->setmode(gvid->orig.screen.mode); + + // Clear screen + if(cls) + vclrscr(cls); + + // Reset border color + if(C_BACKB != 0) + gvid->setoverscan(gvid->orig.color.overscan); + + // Turn on the blinking attributes + gvid->setintensity(gvid->orig.color.intensity); + + // Restore original palette during the shell + if(CFG->screenpalette[16]) + gvid->setpalette(gvid->orig.color.palette); + + #ifdef __UNIX__ + gkbd_tty_reset(); + #endif + + #ifdef __USE_NCURSES__ + savetty(); + reset_shell_mode(); + #endif + + // Write message on screen + if(*message) + puts(message); + + // Turn on cursor + int yy, xx; + if(cursor) { + vposget(&yy, &xx); + vcurset(gvid->orig.cursor.start, gvid->orig.cursor.end); + vcurshow(); + } + + HandleGEvent(EVTT_BREAKLOOP); + + // Shell return value + int status = -1; + + // Shell using the regular RTL function + #ifndef __CYGWIN__ + status = system(command); + #else + // Get executable and parameters + char* _arg_v[3]; + + char* _pars = ""; + char _xfn[256] = ""; // Call command interpreter + if(strnieql(command, "/c", 2)) + _pars = strskip_wht(command+2); + else { + _pars = strpbrk(command, " \t"); + if(_pars) { + ++_pars++; + strxcpy(_xfn, command, _pars-command); + _pars = strskip_wht(_pars); + } + else + _xfn = command; + } + _arg_v[0] = _xfn; + _arg_v[1] = _pars; + _arg_v[2] = NULL; + status = spawnvpe(P_WAIT, _xfn, _arg_v, environ); + #endif + + if(status == -1) + error = errno; + + if(status != -1) + status = 0; + + // Restore keyboard settings + gkbd.Init(); + + #ifdef __USE_NCURSES__ + clearok(stdscr, TRUE); + resetty(); + #endif + + // Pause if needed + if(pause) { + if((pause > 0) or (status != 0)) + kbxget(); + } + + // Restore current directory + gchdir(orgdir); + + // Restore video mode and rows + if(CFG->screensize > 0xFF) + gvid->setmode(CFG->screensize >> 8); + else if(CFG->screensize) + gvid->setrows(CFG->screensize); + + // Restore cursor position and form + if(cursor) { + vposset(yy+1, xx); + vcurhide(); + } + + // Restore screen + if(scrnbuf) { + vrestore(scrnbuf); + throw_xrelease(scrnbuf); + } else + vclrscr(); + + // Restore screen intensity + gvid->setintensity(CFG->intensecolors); + + // Restore border color + if(C_BACKB != 0) + gvid->setoverscan(C_BACKB); + + // Set palette if changes were specified + if(CFG->screenpalette[16]) + gvid->setpalette(CFG->screenpalette); + + // Restore prompt + #ifndef __UNIX__ + if(CFG->switches.get(dosprompt)) { + #ifdef __DJGPP__ + setenv("PROMPT", oldprompt, true); + #else + int envn = 0; + while(environ[envn] and *environ[envn]) { + if(strnieql(environ[envn], "PROMPT=", 7)) { + environ[envn] = oldprompt; + break; + } + envn++; + } + #endif + } + #endif + + // Re-open msgbase + if(_wasopen) + AA->Resume(); + + // Remove the wait window + if(shellvid) + w_info(NULL); + + // Popup error message + if(error) { + switch(errno) { + case E2BIG: w_info("Argument list too long!"); break; + case EACCES: w_info("Permission denied!"); break; + case EAGAIN: w_info("Ressource temporarily unavailable!"); break; + case EBADF: w_info("Bad file descriptor!"); break; + case EBUSY: w_info("Resource busy!"); break; + case ECHILD: w_info("No child processes!"); break; + case EEXIST: w_info("File exists!"); break; + case EFAULT: w_info("Bad address!"); break; + case EFBIG: w_info("File too large!"); break; + case EINTR: w_info("Interrupted system call!"); break; + case EINVAL: w_info("Invalid argument!"); break; + case EISDIR: w_info("Is a directory!"); break; + case EMFILE: w_info("Too many open files!"); break; + case ENFILE: w_info("Too many open files in system!"); break; + case ENOENT: w_info("No such file or directory!"); break; + case ENOEXEC: w_info("Unable to execute file!"); break; + case ENOMEM: w_info("Not enough memory!"); break; + default: + w_info("error during shelling"); + } + waitkeyt(10000); + w_info(NULL); + } + + // Reset tick values to avoid triggering screenblanker or timeout + gkbdtickpressreset(); + gkbdtickvaluereset(); + + #if defined(GUTLOS_FUNCS) + g_set_ostitle_name(ge_temptitle, 1); + g_set_osicon(); + #endif + + return status; +} + + +// ------------------------------------------------------------------ +// Error exit function + +void ErrorExit(int type) { + + static int in_error_exit = false; + + if(not in_error_exit++) { + + error_exit = type; + + if(type) { + + HandleGEvent(EVTT_ERRORFATAL); + + if(_in_editor) { + LOG.printf("+ TIP: If you were writing a msg and want to recover it,"); + LOG.printf("+ try looking in the %s file.", AddPath(CFG->goldpath, EDIT->File())); + } + + // Dump the function tracker log + #if defined(GFTRK_ENABLE) + __gftrk_log(); + #endif + + if(type != 9) + errorlevel = EXIT_ERRORS; + else if(type == 5) + errorlevel = 100; + else + errorlevel = EXIT_CFGERR; + + exit(errorlevel); + } + + exit(EXIT_OK); + } +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gedw.ico b/golded3/gedw.ico new file mode 100644 index 0000000..81a2087 Binary files /dev/null and b/golded3/gedw.ico differ diff --git a/golded3/geedit.cpp b/golded3/geedit.cpp new file mode 100644 index 0000000..15c0d94 --- /dev/null +++ b/golded3/geedit.cpp @@ -0,0 +1,2740 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// The Internal Editor (IE), part 1. +// ------------------------------------------------------------------ + +#ifdef __GNUG__ +#pragma implementation "geedit.h" +#endif + +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ +// Globals + +int CFG__editquotewrap = YES; + +Line* Edit__killbuf = NULL; +Line* Edit__pastebuf = NULL; + +Path Edit__exportfilename = {""}; + +UndoItem** UndoItem::last_item; + + +// ------------------------------------------------------------------ + +#ifndef NDEBUG + +void IEclass::debugtest(char* __test, int __a, int __b, char* __file, int __line, int __values) { + + #if defined(GFTRK_ENABLE) + int _tmp = __gftrk_on; + __gftrk_on = false; + #endif + + savefile(MODE_UPDATE); + + #if defined(GFTRK_ENABLE) + __gftrk_on = _tmp; + #endif + + if(__values) + w_infof(" Range check: (%s) <%i,%i> [%s,%u] ", __test, __a, __b, __file, __line); + else + w_infof(" Range check: (%s) [%s,%u] ", __test, __file, __line); + update_statusline(LNG->EscOrContinue); + SayBibi(); + while(kbxhit()) + kbxget(); + gkey _key = kbxget(); + w_info(NULL); + if(_key == Key_Esc) { + LOG.errtest(__file, __line); + LOG.printf("! An internal editor range check failed."); + if(__values) + LOG.printf(": Details: (%s) <%i,%i>.", __test, __a, __b); + else + LOG.printf(": Details: (%s).", __test); + LOG.printf(": Details: r%u,c%u,mr%u,mc%u,i%u,dm%u,qm%u,eqm%u.", + row, col, maxrow, maxcol, insert, + CFG->dispmargin, CFG->quotemargin, EDIT->QuoteMargin() + ); + LOG.printf("+ Advice: Report to the Author."); + TestErrorExit(); + } +} + +#endif + + +// ------------------------------------------------------------------ +// Make sure line type is correct + +void IEclass::setlinetype(Line* __line) { + + _test_halt(__line == NULL); + _test_halt(__line->text == NULL); + + __line->type &= ~GLINE_ALL; + __line->type |= is_quote(__line->text) ? GLINE_QUOT : (*__line->text == CTRL_A) ? GLINE_HIDD : 0; +} + + +// ------------------------------------------------------------------ +// Insert character in string at position + +void IEclass::strinschr(char*& __string, char __ch, uint __position) { + + _test_halt(__string == NULL); + + // 0123456789 _position = 2 + // 1234567890 length = 4 + // helo< < = nul + // he lo< + // hello< + + // Get string length + uint _length = strlen(__string); + + // Is position beyond the nul-terminator in the string? + _test_haltab(__position > _length, __position, _length); + + // Reallocate string to make room for the char (3=nul+newchar+possible space) + __string = (char*)throw_realloc(__string, _length+3); + + // Make room for the char to insert + memmove(__string+__position+1, __string+__position, _length-__position+1); + THROW_CHECKPTR(__string); + + // Put in the char + __string[__position] = __ch; + THROW_CHECKPTR(__string); + if((__string[__position+1] == NUL) and (__ch != ' ') and (__ch != '\n')) { + __string[__position+1] = ' '; + __string[__position+2] = NUL; + THROW_CHECKPTR(__string); + } +} + + +// ------------------------------------------------------------------ +// Delete character in string at position + +void IEclass::strdelchr(char* __string, uint __position) { + + _test_halt(__string == NULL); + + // 0123456789 _position = 1 + // 1234567890 length = 5 + // hello< < = nul + // hllo< + + uint _length = strlen(__string); + + // Is position at or beyond the nul-terminator in the string? + _test_haltab(__position >= _length, __position, _length); + + // Delete the character + memmove(__string+__position, __string+__position+1, _length-__position); + THROW_CHECKPTR(__string); +} + + +// ------------------------------------------------------------------ +// Zero-based + +int IEclass::dispchar(vchar __ch, int attr) { + + if(__ch != '\n') { + if(__ch == ' ') + __ch = EDIT->CharSpace(); + } + else { + __ch = EDIT->CharPara(); + } + + int atr; + vchar chr; + editwin.getc(crow, ccol, &atr, &chr); + editwin.printc(crow, ccol, attr == -1 ? atr : attr, __ch); + return atr; +} + + +// ------------------------------------------------------------------ + +void IEclass::cursoroff() { + + vcurhide(); +} + + +// ------------------------------------------------------------------ + +void IEclass::cursoron() { + + vcurshow(); +} + + +// ------------------------------------------------------------------ +// Zero-based + +void IEclass::scrollup(int __scol, int __srow, int __ecol, int __erow, int __lines) { + + editwin.scroll_box_up(__srow, __scol, __erow, __ecol, __lines); +} + + +// ------------------------------------------------------------------ +// Zero-based + +void IEclass::scrolldown(int __scol, int __srow, int __ecol, int __erow, int __lines) { + + editwin.scroll_box_down(__srow, __scol, __erow, __ecol, __lines); +} + + +// ------------------------------------------------------------------ +// Zero-based + +void IEclass::prints(int wrow, int wcol, int atr, char* str) { + + editwin.prints(wrow, wcol, atr, str); +} + + +// ------------------------------------------------------------------ + +Line* IEclass::findfirstline() { + + GFTRK("Editfindfirstline"); + + if(not currline) + return NULL; + + // Rewind to the first line + Line* _firstline = currline; + while(_firstline->prev) + _firstline = _firstline->prev; + + GFTRK(NULL); + + return _firstline; +} + + +// ------------------------------------------------------------------ +// Find out what number the current line is and put it in "thisrow" + +void IEclass::getthisrow(Line* __currline) { + + GFTRK("Editgetthisrow"); + + Line* _templine = findfirstline(); + + thisrow = 0; + while((_templine != __currline) and _templine->next) { + _templine = _templine->next; + thisrow++; + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ +// Zero-based + +void IEclass::gotorowcol(uint __col, uint __row) { + + GFTRK("Editgotorowcol"); + + _test_haltab(__col > maxcol, __col, maxcol); + _test_haltab(__row > maxrow, __row, maxrow); + + editwin.move_cursor(__row, __col); + + ccol = __col; + crow = __row; + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::dispstring(char* __string, uint __row, int attr, Line* line) { + + GFTRK("Editdispstring"); + + _test_halt(__string == NULL); + _test_haltab(__row > maxrow, __row, maxrow); + + // Get string length + uint _length = strlen(__string); + + // String longer than window width? + _test_haltab(_length > (maxcol+1), _length, (maxcol+1)); + _length = MinV(_length, (maxcol+1)); + + // Buffer for translation to visual representation + char _buf[EDIT_BUFLEN]; + + // Space-pad and nul-terminate the buffer + memset(_buf, ' ', maxcol+1); + _buf[maxcol+1] = NUL; + + // Copy/translate string into buffer + if(attr == -1) { + char* _bufptr = _buf; + uint _position = 0; + char* __str = __string; + while(_position < _length) { + switch(*__str) { + case ' ': *_bufptr = EDIT->CharSpace(); break; + case '\n': *_bufptr = EDIT->CharPara(); break; + default: *_bufptr = *__str; + } + _position++; + _bufptr++; + __str++; + } + } + else { + memcpy(_buf, __string, _length); + } + + // mark selected block + if(line and (blockcol != -1)) { + int selected = 0; + for(Line *ln = findfirstline(); ln and ln != line; ln = ln->next) { + if(ln == currline) + selected ^= 1; + if(ln->type & GLINE_BLOK) + selected ^= 1; + } + if((line->type & GLINE_BLOK) and (line == currline)) { + int begblock = ((col < blockcol) ? col : blockcol) - mincol; + int endblock = ((col > blockcol) ? col : blockcol) - mincol; + + char savechar = _buf[begblock]; + _buf[begblock] = NUL; + StyleCodeHighlight(_buf, __row, mincol, false, attr); + _buf[begblock] = savechar; + + savechar = _buf[endblock]; + _buf[endblock] = NUL; + StyleCodeHighlight(_buf+begblock, __row, mincol+begblock, false, C_READA); + _buf[endblock] = savechar; + StyleCodeHighlight(_buf+endblock, __row, mincol+endblock, false, attr); + } + else if((line->type & GLINE_BLOK) or (line == currline)) { + int blockmark = ((line->type & GLINE_BLOK) ? blockcol : col) - mincol; + + char savechar = _buf[blockmark]; + _buf[blockmark] = NUL; + StyleCodeHighlight(_buf, __row, mincol, false, selected ? C_READA : attr); + _buf[blockmark] = savechar; + StyleCodeHighlight(_buf+blockmark, __row, mincol+blockmark, false, selected ? attr : C_READA); + } + else + StyleCodeHighlight(_buf, __row, mincol, false, selected ? C_READA : attr); + } + else + StyleCodeHighlight(_buf, __row, mincol, false, attr); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::setcolor(Line* __line) { + + // Set window attribute + if(__line->type & GLINE_HIDD) + editwin.text_color(C_READKH); + else if(__line->type & GLINE_KLUD) + editwin.text_color(C_READK); + else if(__line->type & GLINE_TAGL) + editwin.text_color(C_READG); + else if(__line->type & GLINE_TEAR) + editwin.text_color(C_READT); + else if(__line->type & GLINE_ORIG) + editwin.text_color(C_READO); + else if(__line->type & GLINE_QUOT) + editwin.text_color(quotecolor(__line->text)); + else if(__line->type & GLINE_SIGN) + editwin.text_color(C_READS); + else + editwin.text_color(C_READW); + +} + + +// ------------------------------------------------------------------ +// Zero-based + +void IEclass::displine(Line* __line, uint __row) { + + GFTRK("Editdispline"); + + _test_halt(__line == NULL); + _test_halt(__line->text == NULL); + _test_haltab(__row > maxrow, __row, maxrow); + + // Display line + setcolor(__line); + dispstring(__line->text, __row, -1, __line); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ +// Zero-based + +void IEclass::clreol(int __col, int __row) { + + GFTRK("Editclreol"); + + if(__col == -1) + __col = ccol; + + if(__row == -1) + __row = crow; + + if((uint)__col <= maxcol) + editwin.fill(__row, __col, __row, maxcol, ' ', C_READW); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ +// Zero-based + +void IEclass::refresh(Line* __currline, uint __row) { + + GFTRK("Editrefresh"); + + _test_halt(__currline == NULL); + + cursoroff(); + + // Display as many lines as we can + while(__currline and (__row <= maxrow)) { + displine(__currline, __row++); + __currline = __currline->next; + } + + // If we ran out of lines, blank the rest + if(__row <= maxrow) { + vchar vbuf[256]; + for(int c = 0; c < maxcol+1; c++) + vbuf[c] = _box_table(W_BREAD, 1); + vbuf[maxcol+1] = NUL; + wprintvs(__row++, mincol, C_READB|ACSET, vbuf); + while(__row <= maxrow) + dispstring("", __row++); + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +Line* IEclass::insertlinebelow(Line* __currline, char* __text, long __batch_mode) { + + GFTRK("Editinsertlinebelow"); + + Line* _nextline = (Line*)throw_xcalloc(1, sizeof(Line)); + _nextline->text = __text ? throw_strdup(__text) : (char*)NULL; + + if(__currline) { + + _nextline->prev = __currline; + _nextline->next = __currline->next; + if(_nextline->next) + _nextline->next->prev = _nextline; + __currline->next = _nextline; + } + + Undo->PushItem(EDIT_UNDO_NEW_LINE|batch_mode|__batch_mode, _nextline); + + GFTRK(NULL); + + return _nextline; +} + + +// ------------------------------------------------------------------ +// Zero-based + +int IEclass::downoneline(uint __row) { + + GFTRK("Editdownoneline"); + + _test_haltab(__row > maxrow, __row, maxrow); + + thisrow++; + + if(__row == maxrow) + scrollup(mincol, minrow, maxcol, maxrow); + else + __row++; + + gotorowcol(mincol, __row); + + GFTRK(NULL); + + return __row; +} + + +// ------------------------------------------------------------------ + +void IEclass::GoEOL() { + + GFTRK("EditGoEOL"); + + // Move cursor to the last char on the line + col = strlen(currline->text); + if(col) + col--; + + // String must not be longer than the window width + _test_haltab(col > maxcol, col, maxcol); + + if(blockcol != -1) + displine(currline, row); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::GoUp() { + + GFTRK("EditGoUp"); + + _test_haltab(row < minrow, row, minrow); + + if(currline->prev) { + + currline = currline->prev; + thisrow--; + + if(row == minrow) { + scrolldown(mincol, row, maxcol, maxrow); + if(blockcol != -1) + displine(currline->next, row+1); + displine(currline, row); + } + else { + row--; + if(blockcol != -1) { + displine(currline->next, row+1); + displine(currline, row); + } + } + + if((col+1) > strlen(currline->text)) + GoEOL(); + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::GoDown() { + + GFTRK("EditGoDown"); + + _test_haltab(row > maxrow, row, maxrow); + + if(currline->next) { + + currline = currline->next; + thisrow++; + + if(row == maxrow) { + scrollup(mincol, minrow, maxcol, maxrow); + if(blockcol != -1) + displine(currline->prev, row-1); + displine(currline,row); + } + else { + row++; + if(blockcol != -1) { + displine(currline->prev, row-1); + displine(currline, row); + } + } + + if((col+1) > strlen(currline->text)) + GoEOL(); + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::GoLeft() { + + GFTRK("EditGoLeft"); + + _test_haltab(col < mincol, col, mincol); + + if(col == mincol) { + if(currline->prev) { + GoUp(); + GoEOL(); + } + } + else + col--; + + if(blockcol != -1) + displine(currline, row); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::GoRight() { + + GFTRK("EditGoRight"); + + _test_haltab(col > maxcol, col, maxcol); + + char _cursorchar = currline->text[col]; + + if((col == maxcol) or (_cursorchar == '\n') or (_cursorchar == NUL)) { + if(currline->next != NULL) { + GoDown(); + col = mincol; + } + } + else + col++; + + if(blockcol != -1) + displine(currline, row); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +Line* IEclass::wrapit(Line** __currline, uint* __curr_col, uint* __curr_row, int __display) { + + _test_halt(__currline == NULL); + _test_halt(*__currline == NULL); + + uint _quotelen; + char _quotebuf[100]; + + uint _curscol = *__curr_col; + uint _cursrow = *__curr_row; + + uint _thisrow = *__curr_row; + Line* _thisline = *__currline; + Line* _lastadded = _thisline; + + bool _wrapped_above = false; + + // Start wrapping from the current line onwards + while(_thisline) { + + // Length of this line + uint _thislen = strlen(_thisline->text); + + uint _wrapmargin = (_thisline->type & GLINE_QUOT) ? marginquotes : margintext; + + // Does this line need wrapping? + if(_thislen > _wrapmargin or (_thislen == _wrapmargin and not isspace(_thisline->text[_thislen-1]))) { + + // Reset quote string length + _quotelen = 0; + + // Is this line quoted? + if((_thisline->type & GLINE_QUOT) and CFG__editquotewrap) { + + // Get quote string and length + GetQuotestr(_thisline->text, _quotebuf, &_quotelen); + } + + // wrapmargin = 40 + // 1111111111222222222233333333334444444444 + // 01234567890123456789012345678901234567890123456789 + // -------------------------------------------------- + // v- wrapptr + // Case 1: this is another test with a bit of text to wrap. + // Case 2: this is a test with a line that need wrapping. + // Case 3: thisxisxaxtestxwithxaxlinexthatxneedxwrapping. + // Case 4: >thisxisxaxtestxwithxaxlinexthatxneedxwrapping. + + // Point to the last char inside the margin + char* _wrapptr = _thisline->text + _wrapmargin - 1; + + // Locate the word to be wrapped + + // Did we find a space? + if(*_wrapptr == ' ') { + + // Case 1: A space was found as the last char inside the margin + // + // Now we must locate the first word outside the margin. + // NOTE: Leading spaces to this word will be nulled out! + + // Begin at the first char outside the margin + _wrapptr++; + } + else { + + // Case 2: A non-space was found as the last char inside the margin + // + // Now we must locate the beginning of the word we found. + + // Keep copy of original pointer + char* _atmargin = _wrapptr; + + // Search backwards until a space or the beginning of the line is found + while((_wrapptr > _thisline->text) and (*(_wrapptr-1) != ' ')) + _wrapptr--; + + // Check if we hit leading spaces + char* _spaceptr = _wrapptr; + if(_spaceptr > _thisline->text) { + _spaceptr--; + while((_spaceptr > _thisline->text) and (*_spaceptr == ' ')) + _spaceptr--; + } + + // Did we search all the way back to the beginning of the line? + if((_wrapptr == _thisline->text) or (_wrapptr == (_thisline->text+_quotelen)) or (*_spaceptr == ' ')) { + + // Case 3: There are no spaces within the margin or we hit leading spaces + + // We have to break it up at the margin + _wrapptr = _atmargin; + } + } + + // The wrapptr now points to the location to be wrapped or NUL + + // Get length of the wrapped part + uint _wraplen = strlen(_wrapptr); + + // Is the line hard-terminated? + if(strchr(_wrapptr, '\n')) { + + // The line is hard-terminated. + // + // The wrapped part must be placed on a new line below. + + Line* _wrapline = _lastadded = insertlinebelow(_thisline, NULL, BATCH_MODE); + // Allocate space for the new line + _wrapline->text = (char*)throw_malloc(_quotelen + _wraplen + 1); + + // Copy the quote string, if any, to the new line first + if(_quotelen) { + strcpy(_wrapline->text, _quotebuf); + THROW_CHECKPTR(_wrapline->text); + } + else { + *_wrapline->text = NUL; + THROW_CHECKPTR(_wrapline->text); + } + + // Copy/append the wrapped part to the new line + strcat(_wrapline->text, _wrapptr); + THROW_CHECKPTR(_wrapline->text); + + // Saves pointer to a line where from the wrapped part was copied, its begining + // and length. While in Undo, appends the copied part to previous line and deletes + // it on current, moving the rest over deleted. + Undo->PushItem(EDIT_UNDO_WRAP_TEXT|BATCH_MODE, _wrapline, _quotelen, _wraplen); + + _wrapline->type = _thisline->type; + // Make sure the type of the line is correct + setlinetype(_wrapline); + + if(__display) { + + // Is there at least one line below this one? + if(_thisrow < maxrow) { + + // Scroll the lines below to make room for the new line + scrolldown(mincol, _thisrow+1, maxcol, maxrow); + + // Display the new line + if(strlen(_wrapline->text) <= (maxcol+1)) + displine(_wrapline, _thisrow+1); + } + } + } + else { + + // The line is not hard-terminated + // + // The wrapped part must be inserted into the next line + + // Indicate that one or more lines were wrapped in this way + _wrapped_above = true; + + // Pointer to the next line + Line* _nextline = _thisline->next; + + // Flag to indicate if a new line was added below + bool _line_added_below = false; + + // Is there no next line or is the next line quoted? + if((_nextline == NULL) or (_nextline->type & GLINE_QUOT)) { + + // The wrapped part must be placed on a new line below + _lastadded = _nextline = insertlinebelow(_thisline, "", BATCH_MODE); + _line_added_below = true; + } + + // Get length of the text of next line + uint _nextlen = _nextline->text ? strlen(_nextline->text) : 0; + + // Reallocate next line's text to make room for the wrapped part + _nextline->text = (char*)throw_realloc(_nextline->text, _quotelen+_wraplen+_nextlen+1); + + // Move the next line's text to make room for the wrapped part and the quote string, if any + memmove(_nextline->text+_quotelen+_wraplen, _nextline->text, _nextlen+1); + THROW_CHECKPTR(_nextline->text); + + // Copy the wrapped part + memmove(_nextline->text+_quotelen, _wrapptr, _wraplen); + THROW_CHECKPTR(_nextline->text); + + // Was this line quoted? + if(_quotelen) { + + // Copy the quote string + memmove(_nextline->text, _quotebuf, _quotelen); + THROW_CHECKPTR(_nextline->text); + + Undo->PushItem(EDIT_UNDO_INS_TEXT|BATCH_MODE, _nextline, 0, _quotelen); + } + + Undo->PushItem(EDIT_UNDO_WRAP_TEXT|BATCH_MODE, _nextline, _quotelen, _wraplen); + + // Make sure the type of the line is correct + setlinetype(_nextline); + + if(__display) { + + // Is there at least one line below this one? + if(_line_added_below and (_thisrow < maxrow)) { + + // Scroll the lines below to make room for the new line + scrolldown(mincol, _thisrow+1, maxcol, maxrow); + } + + // Display the new/wrapped line + if((_thisrow+1) <= maxrow and strlen(_nextline->text) <= (maxcol+1)) + displine(_nextline, _thisrow+1); + } + } + + // Nul-terminate at the wrapping location + *_wrapptr = NUL; + THROW_CHECKPTR(_thisline->text); + + // Was this line quoted? + if(_quotelen) { + + // Trim spaces off the end of the line + char* _trimptr = _wrapptr - 1; + if(*_trimptr == ' ') { + while(*(_trimptr-1) == ' ') + _trimptr--; + if(_quotelen and _trimptr-_thisline->text < _quotelen) + _trimptr++; + Undo->PushItem(EDIT_UNDO_OVR_CHAR|BATCH_MODE, _thisline, _trimptr - _thisline->text); + Undo->PushItem(EDIT_UNDO_OVR_CHAR|BATCH_MODE, _thisline, _trimptr - _thisline->text + 1); + *_trimptr = NUL; + } + else + Undo->PushItem(EDIT_UNDO_OVR_CHAR|BATCH_MODE, _thisline, _wrapptr - _thisline->text); + + // Append a new linefeed + strcat(_thisline->text, "\n"); + THROW_CHECKPTR(_thisline->text); + } + + // Make sure the line type still is correct + setlinetype(_thisline); + + if(__display) { + + // Display this line after wrapping + if(_thisrow <= maxrow) + displine(_thisline, _thisrow); + } + + // If we are on the cursor line, check if the cursor char was wrapped + if(_thisrow == *__curr_row and strlen(_thisline->text) <= *__curr_col) { + char* _colptr = _thisline->text + *__curr_col; + _curscol = _quotelen + ((_colptr > _wrapptr) ? _colptr - _wrapptr : 0); + _cursrow++, thisrow++; + UndoItem* i = Undo->last_item; + do { i = i->prev; } while(i->action & BATCH_MODE); + if(i->col.num >= strlen(i->line->text)) { + i->action |= PREV_LINE; + i->col.sav = i->col.num; + i->col.num = _curscol; + } + } + } + + // If this line is hard-terminated, we have finished wrapping + // Unless the next line has grown too large + if(strchr(_thisline->text, '\n')) { + if(_thisline->next == NULL) + break; + _wrapmargin = (_thisline->next->type & GLINE_QUOT) ? marginquotes : margintext; + if(strlen(_thisline->next->text) <= _wrapmargin) + break; + } + + // Go to the next line + _thisline = _thisline->next; + _thisrow++; + } + + if(__display) { + + // Display the current line after wrapping + if(*__curr_row <= maxrow) + displine(*__currline, *__curr_row); + + // Was the line or lines above wrapped? + if(_wrapped_above) { + + // Display the last line in the paragraph + if((_thisrow <= maxrow) and _thisline) + displine(_thisline, _thisrow); + } + } + + // Move to the next line if the cursor was wrapped + if(_cursrow != *__curr_row) { + *__currline = (*__currline)->next; + if(_cursrow > maxrow) { + _cursrow = maxrow; + scrollup(mincol, minrow, maxcol, maxrow); + displine(*__currline, row); + } + } + + // Update cursor position + *__curr_row = _cursrow; + *__curr_col = _curscol; + //thisrow = _cursrow; + + GFTRK(NULL); + + return _lastadded; +} + + +// ------------------------------------------------------------------ + +Line* IEclass::wrapdel(Line** __currline, uint* __curr_col, uint* __curr_row, int __display) { + + GFTRK("Editwrapdel"); + + Line *tmp = wrapit(__currline, __curr_col, __curr_row, __display); + + GFTRK(NULL); + + return tmp; +} + + +// ------------------------------------------------------------------ + +Line* IEclass::wrapins(Line** __currline, uint* __curr_col, uint* __curr_row, int __display) { + + GFTRK("Editwrapins"); + + Line *tmp = wrapit(__currline, __curr_col, __curr_row, __display); + + GFTRK(NULL); + + return tmp; +} + + +// ------------------------------------------------------------------ + +void IEclass::insertchar(char __ch) { + + GFTRK("Editinsertchar"); + + // Insert or overwrite the char, replacing the block if any + if((selecting ? (BlockCut(true), batch_mode = BATCH_MODE) : false) or + (currline->text[col] == '\n') or (currline->text[col] == NUL) or insert) { + Undo->PushItem(EDIT_UNDO_INS_CHAR|batch_mode); + strinschr(currline->text, __ch, col); + } else { +#ifndef NDEBUG + uint _currline_len = strlen(currline->text); + _test_haltab(col > _currline_len, col, _currline_len); +#endif + Undo->PushItem(EDIT_UNDO_OVR_CHAR|batch_mode); + currline->text[col] = __ch; + THROW_CHECKPTR(currline->text); + } + batch_mode = BATCH_MODE; + + // Make sure the line type still is correct + setlinetype(currline); + + // Move cursor + col++; + + wrapins(&currline, &col, &row); + + // Adjust cursor position and display if necessary + if(col > maxcol) { + if(currline->next) { + currline = currline->next; + col = mincol; + row++; + if(row > maxrow) { + row = maxrow; + scrollup(mincol, minrow, maxcol, maxrow); + displine(currline, row); + } + } + else { + col = maxcol; + } + } + + gotorowcol(col, row); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::DelChar() { + + GFTRK("EditDelChar"); + + Line* _thisline = currline; + Line* _nextline = currline->next; + uint _thislen = strlen(_thisline->text); + + // Cannot delete at or beyond the nul-terminator + if(col < _thislen) { + Undo->PushItem(EDIT_UNDO_DEL_CHAR|batch_mode); + strdelchr(_thisline->text, col); + batch_mode = BATCH_MODE; + } + + // Did we delete the last char on the line or + // was the cursor at or beyond the nul-terminator? + // And is there a next line at all? + if(((col+1) >= _thislen) and _nextline) { + + // Join the next line to this line + + // Is the next line quoted? + // And is the cursor column non-zero? + uint _quotelen = 0; + if((_nextline->type & GLINE_QUOT) and CFG__editquotewrap and col) { + + // Get quote string length + char _dummybuf[100]; + GetQuotestr(_nextline->text, _dummybuf, &_quotelen); + } + + // Reallocate this line's text to make room for the next + _thisline->text = (char*)throw_realloc(_thisline->text, _thislen + strlen(_nextline->text) - _quotelen + 1); + + // Copy the next line's text to this line + // Skip past the next line's quote string and blanks, if any + char* _nextptr = _nextline->text+_quotelen; + if(not ((_nextline->type & GLINE_QUOT) and (col == 0))) { + while(*_nextptr == ' ') + _nextptr++; + } + strcat(_thisline->text, _nextptr); + THROW_CHECKPTR(_thisline->text); + + Undo->PushItem(EDIT_UNDO_CUT_TEXT|batch_mode, _thisline, col); + + // Relink this line + _thisline->next = _nextline->next; + if(_thisline->next) + _thisline->next->prev = _thisline; + + Undo->PushItem(EDIT_UNDO_DEL_LINE|BATCH_MODE, _nextline); + } + batch_mode = BATCH_MODE; + + // Make sure the line type still is correct + setlinetype(_thisline); + + // Rewrap this line + wrapdel(&currline, &col, &row); + + refresh(currline, row); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::DelLeft() { + + GFTRK("EditDelLeft"); + + // Cannot backspace from the first column on the first line in the msg + if(currline->prev == NULL) + if(col == mincol) { + GFTRK(NULL); + return; + } + + // Go left(/up) and delete the character there + GoLeft(); + DelChar(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::GoWordLeft() { + + GFTRK("EditGoWordLeft"); + + if(col == 0) { + if(currline->prev) { + GoUp(); + GoEOL(); + } + } + else { + + col--; + + if(not isxalnum(currline->text[col])) { + while(not isxalnum(currline->text[col]) and (col > 0)) + col--; + while(isxalnum(currline->text[col]) and (col > 0)) + col--; + } + else { + while(isxalnum(currline->text[col]) and (col > 0)) + col--; + } + + if(col != 0) + col++; + + if(blockcol != -1) + displine(currline, row); + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::GoWordRight() { + + GFTRK("EditGoWordRight"); + + if((currline->text[col] == NUL) or (currline->text[col] == '\n')) { + if(currline->next) { + GoDown(); + col = 0; + } + } + else { + if(not isxalnum(currline->text[col])) { + while(not isxalnum(currline->text[col]) and ((col+1) <= strlen(currline->text))) + col++; + } + else { + while(isxalnum(currline->text[col]) and ((col+1) <= strlen(currline->text))) + col++; + while(not isxalnum(currline->text[col]) and ((col+1) <= strlen(currline->text))) + col++; + } + + if(currline->text[col-1] == '\n') + col--; + + if(currline->text[col] == NUL) { + if(currline->next) { + GoDown(); + col = 0; + } + else + col--; + } + + if(blockcol != -1) + displine(currline, row); + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::Newline() { + + GFTRK("EditNewline"); + + char* _text = currline->text; + + // If the line is not hard-terminated, make room for it + if(not strchr(_text, '\n') and (_text[col] == NUL)) + _text = currline->text = (char*)throw_realloc(_text, strlen(_text)+3); + + // Pointer to the split position + char* _splitptr = _text + col; + + // Buffer for the second part of the split line + char* _splitbuf = (char*)throw_malloc(EDIT_BUFLEN); + *_splitbuf = NUL; + + // If the split line was quoted, get the quotestring + // But do not get it if the cursor points to a linefeed or is + uint _quotelen = 0; + if(is_quote(_text)) { + GetQuotestr(_text, _splitbuf, &_quotelen); + THROW_CHECKPTR(_splitbuf); + } + + // Eliminate the quotestring if + // - the cursor points to a linefeed or + // - the cursor is located inside the quotestring + if(_quotelen and ((*_splitptr == '\n') or (*_splitptr == NUL) or (col < _quotelen))) + *_splitbuf = _quotelen = 0; + + // Append the second part to the split buffer + strcat(_splitbuf, _splitptr); + THROW_CHECKPTR(_splitbuf); + + Undo->PushItem(EDIT_UNDO_INS_TEXT|batch_mode, currline, col, 1); + batch_mode = BATCH_MODE; + + // Copy linefeed+nul to the split position + strcpy(_splitptr, "\n"); + THROW_CHECKPTR(currline->text); + + // Re-type and display the split line + setlinetype(currline); + displine(currline, row); + + // Insert a new line below, set the line text to the split-off part + currline = insertlinebelow(currline, _splitbuf); + + // --v-- + // This line would be wrapped + // This line would be + // wrapped + + Undo->PushItem(EDIT_UNDO_WRAP_TEXT|BATCH_MODE, currline, _quotelen, strlen(_splitbuf) - _quotelen); + + setlinetype(currline); + throw_free(_splitbuf); + + // Move down the cursor + col = 0; + row = downoneline(row); + + // Scroll the remaining lines if necessary + if(row < maxrow) + scrolldown(mincol, row, maxcol, maxrow); + + // Rewrap the split-off line + wrapdel(&currline, &col, &row); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::CopyAboveChar() { + + GFTRK("EditCopyAboveChar"); + + char _ch = ' '; + if(currline->prev) { + char* _ptr = currline->prev->text; + uint _len = strlen(_ptr); + if(_len and _len > col) + _ch = _ptr[col]; + if(_ch == '\n') + _ch = ' '; + } + insertchar(_ch); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::DupLine() { + + GFTRK("EditDupLine"); + + Undo->PushItem(EDIT_UNDO_VOID); + + Line* _nextline = insertlinebelow(currline, currline->text, BATCH_MODE); + _nextline->type = currline->type & ~GLINE_BLOK; + _nextline->color = currline->color; + _nextline->kludge = currline->kludge; + refresh(currline, row); + GoDown(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ +// PageUp behavior: +// +// ... The top line becomes the bottom line. +// ... Always remain at cursor row, except if we can't page up. +// ... If we can't page up, move the cursor row to the top line. + +void IEclass::GoPgUp() { + + GFTRK("EditGoPgUp"); + + // Not at the first line in msg? + if(currline->prev) { + + // Count lines + int _count = row; + + // Move to the top line currently displayed + Line* _topline = currline; + while(_count and _topline->prev) { + _topline = _topline->prev; + _count--; + } + + // The count must be zero at this point! + _test_haltab(_count, _count, _count); + + // At we already fully at the top? + if(_topline->prev == NULL) { + + // Yes, so move the cursor row to the top line + row = minrow; + currline = _topline; + if(blockcol != -1) + refresh(currline, row); + } + else { + + // We are not at the top, so continue with paging + + // Move a full page of lines, if possible + _count = maxrow; + while(_count and _topline->prev) { + _topline = _topline->prev; + _count--; + } + + // Set the current line + _count = row; + currline = _topline; + while(_count--) + currline = currline->next; + + // Refresh display + refresh(_topline, minrow); + } + } + else { + GoTopMsg(); + } + + if((col+1) > strlen(currline->text)) + GoEOL(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ +// PageDown behavior: +// +// ... The bottom line becomes the top line. +// ... Always remain at cursor row, except if at the last line. +// ... If at the last line, move cursor to the last window line and +// display the lines above. +// ... If there are too few lines to display after the page down, the +// rest are displayed blank. + +void IEclass::GoPgDn() { + + GFTRK("EditGoPgDn"); + + // Not at the last line in the msg? + if(currline->next) { + + // Go down to the last displayed line in the window + uint _newrow = row, _oldrow = row; + Line *oldcurrline = currline; + while((_newrow < maxrow) and currline->next) { + currline = currline->next; + _newrow++; + } + + // If there are more lines after the last line, start displaying from the top + if(currline->next) { + Line *_topline = currline; + + // Set current line + _newrow = 0; + while((_newrow < row) and currline->next) { + currline = currline->next; + _newrow++; + } + + // Move cursor row if necessary + if(_newrow < row) + row = _newrow; + + refresh(_topline, minrow); + } + else { + row = _newrow; + refresh(oldcurrline, _oldrow); + } + } + else { + GoBotMsg(); + } + + if((col+1) > strlen(currline->text)) + GoEOL(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::Tab() { + + GFTRK("EditTab"); + + int tabsz = CFG->disptabsize ? CFG->disptabsize : 1; + + // Move to the next tab position + do { + if(insert) + insertchar(' '); + else if(currline->text[col] != '\n') + GoRight(); + else + break; + } while(col % tabsz); + + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::ReTab() { + + GFTRK("EditTabReverse") + + int tabsz = CFG->disptabsize ? CFG->disptabsize : 1; + + // Move to the next tab position + do { + if(not col) + break; + + if(insert) + DelLeft(); + else + GoLeft(); + } while(col % tabsz); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::DeleteEOL() { + + GFTRK("EditDeleteEOL"); + + bool _has_linefeed = strchr(currline->text, '\n') ? true : false; + + Undo->PushItem(EDIT_UNDO_DEL_TEXT, currline); + + currline->text[col] = NUL; + THROW_CHECKPTR(currline->text); + + if(_has_linefeed) { + strcat(currline->text, "\n"); + THROW_CHECKPTR(currline->text); + } + + clreol(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::deleteline(bool zapquotesbelow) { + + GFTRK("Editdeleteline"); + + bool done = false; + + do { + + // Break if need to zap quotes, but the current line is not quote and is not empty + if(zapquotesbelow and not ((currline->type & GLINE_QUOT) or strblank(currline->text))) + break; + + // Pointer to the deleted line + Line* _deletedline = currline; + + // If last line to be deleted delete to EOL and exit + if(currline->next == NULL) { + if(currline->text[0] == NUL) + break; + insertlinebelow(currline, "", batch_mode); + batch_mode = BATCH_MODE; + done = true; + } + + // Pointers to the previous and next lines + Line* _prevline = currline->prev; + Line* _nextline = currline->next; + + Undo->PushItem(EDIT_UNDO_PUSH_LINE|batch_mode); + + // Set the new current line to the next line (which may be NULL!) + currline = _nextline; + + if(currline == NULL) { + currline = _prevline; + currline->next = NULL; + _prevline = _prevline ? _prevline->prev : NULL; + } + + // Link the new current line to the previous line + currline->prev = _prevline; + + // Link the previous line to this line + if(_prevline) + _prevline->next = currline; + + if(_deletedline->type & GLINE_BLOK) { + blockcol = -1; + _deletedline->type &= ~GLINE_BLOK; + } + + // Link the deleted line to the killbuffer + if(Edit__killbuf) { + Edit__killbuf->next = _deletedline; + _deletedline->prev = Edit__killbuf; + Edit__killbuf = _deletedline; + } + else { + Edit__killbuf = _deletedline; + Edit__killbuf->prev = NULL; + } + Edit__killbuf->next = NULL; + + // Move the cursor to EOL if necessary + if((col+1) > strlen(currline->text)) + GoEOL(); + + if(not zapquotesbelow) + break; + + batch_mode = BATCH_MODE; + + } while(not done); + + // Refresh display from cursor row + refresh(currline, row); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::UnDelete(bool before) { + + GFTRK("EditUnDelete"); + + // If there are deleted lines + if(Edit__killbuf) { + + Line* _prevline = Edit__killbuf->prev; + bool down = false; + + if(before) { + Edit__killbuf->prev = currline ? currline->prev : NULL; + Edit__killbuf->next = currline; + } + else { + Edit__killbuf->prev = currline; + Edit__killbuf->next = currline ? currline->next : NULL; + if(row == maxrow) + down = true; + else if((row < maxrow) and currline) + row++; + } + + if(Edit__killbuf->prev) + Edit__killbuf->prev->next = Edit__killbuf; + if(Edit__killbuf->next) + Edit__killbuf->next->prev = Edit__killbuf; + currline = Edit__killbuf; + Edit__killbuf = _prevline; + if(Edit__killbuf) + Edit__killbuf->next = NULL; + + Undo->PushItem(EDIT_UNDO_POP_LINE); + + // Move the cursor to EOL if necessary + if((col+1) > strlen(currline->text)) + GoEOL(); + + if(down) + GoDown(); + else + refresh(currline, row); + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::ZapQuoteBelow() { + + GFTRK("ZapQuoteBelow"); + + if(currline->prev) + Undo->PushItem(EDIT_UNDO_VOID|PREV_LINE|batch_mode, currline->prev); + else + Undo->PushItem(EDIT_UNDO_VOID|batch_mode, currline); + batch_mode = BATCH_MODE; + + deleteline(true); + if(row) { + GoUp(); + GoEOL(); + Newline(); + } + else { + UndoItem* i = Undo->last_item; + do { i = i->prev; } while(i->action & BATCH_MODE); + i->line = currline; + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +Line* IEclass::findtopline() { + + GFTRK("Editfindtopline"); + + uint _toprow = row; + Line* _topline = currline; + + while(_topline->prev and (_toprow > minrow)) { + _topline = _topline->prev; + _toprow--; + } + + GFTRK(NULL); + + return _topline; +} + + +// ------------------------------------------------------------------ + +void IEclass::savefile(int __status) { + + Subj statbak; + + GFTRK("Editsavefile"); + + // Turn off cursor and put up a wait window + int wascursoron = not vcurhidden(); + cursoroff(); + + strcpy(statbak, information); + update_statusline(LNG->Wait+1); + + // Open the save file + const char* editorfile = AddPath(CFG->goldpath, EDIT->File()); + remove(editorfile); + FILE* _fp = fsopen(editorfile, "wb", CFG->sharemode); + if(_fp) { + + // Find the first line + Line* _saveline = findfirstline(); + + // First save the "unfinished" identifier + if(__status == MODE_UPDATE) { + fputs(unfinished, _fp); + fputs("\r\n", _fp); + } + + // Save as whole paragraphs + while(_saveline) { + + // Copy the line to a buffer + char _buf[EDIT_BUFLEN]; + strcpy(_buf, _saveline->text); + + // If a LF was found, replace it with a CR/LF combo + char* _lfptr = strchr(_buf, '\n'); + if(_lfptr) + strcpy(_lfptr, "\r\n"); + + // Save the line + fputs(_buf, _fp); + + // Continue with the next line + _saveline = _saveline->next; + } + + // Close save file and remove wait window + fclose(_fp); + } + + update_statusline(statbak); + + if(wascursoron) + cursoron(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::SaveFile() { + + GFTRK("EditSaveFile"); + + savefile(MODE_UPDATE); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::SaveMsg() { + + GFTRK("EditSaveMsg"); + + done = MODE_SAVE; + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +int IEclass::isempty(Line* __line) { + + if(__line == NULL) + __line = currline; + + return (*__line->text == '\n') or (*__line->text == NUL); +} + + +// ------------------------------------------------------------------ + +int IEclass::reflowok(char* __qstr) { + + // Stop reflow if there is no next line + if(currline->next == NULL) + return false; + + // Stop reflow if the next line is empty + if(isempty(currline->next)) + return false; + + // Stop reflow if the next line is a control line + if(currline->next->type & (GLINE_KLUDGE|GLINE_TEAR|GLINE_ORIG|GLINE_TAGL)) + return false; + + // Stop reflow if the quotestring on the next line is not the same + uint _qlen2; + char _qstr2[100]; + GetQuotestr(currline->next->text, _qstr2, &_qlen2); + if(not strieql(__qstr, _qstr2)) + return false; + + return true; +} + + +// ------------------------------------------------------------------ + +void IEclass::Reflow() { + + GFTRK("EditReflow"); + + // Skip empty lines + while(isempty()) { + if(currline->next) + GoDown(); + else { + GFTRK(NULL); + return; + } + } + + // Get the first quotestring + uint _qlen1; + char _qstr1[100]; + GetQuotestr(currline->text, _qstr1, &_qlen1); + char* _qlenptr = currline->text + _qlen1; + + // Strip leading spaces from the first line + char* ptr = strskip_wht(_qlenptr); + if(ptr != _qlenptr) { + Undo->PushItem(EDIT_UNDO_DEL_TEXT, currline, _qlen1, ptr-_qlenptr); + memmove(_qlenptr, ptr, strlen(ptr) + 1); + } + + // Perform the reflow + while(reflowok(_qstr1)) { + + // Work on the current line until it is done + Line* _thisline = currline; + while(_thisline == currline) { + + // Stop reflow? + if(not reflowok(_qstr1)) + break; + + // Go to the EOL, insert a space and delete the LF + GoEOL(); + if(col+1 < maxcol) { + insertchar(' '); + DelChar(); + } + else { + GoDown(); + col = mincol; + } + } + } + + // Go to the next line + displine(currline,row); + GoDown(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::ExitMsg() { + + GFTRK("EditExitMsg"); + + done = MODE_QUIT; + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::DelLine() { + + GFTRK("EditDelLine"); + + cursoroff(); + deleteline(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::ToUpper() { + + GFTRK("EditToUpper"); + + Undo->PushItem(EDIT_UNDO_OVR_CHAR); + currline->text[col] = toupper(currline->text[col]); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::ToLower() { + + GFTRK("EditToLower"); + + Undo->PushItem(EDIT_UNDO_OVR_CHAR); + currline->text[col] = tolower(currline->text[col]); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::ToggleCase() { + + GFTRK("EditToggleCase"); + + Undo->PushItem(EDIT_UNDO_OVR_CHAR); + if(toupper(currline->text[col]) == currline->text[col]) + currline->text[col] = tolower(currline->text[col]); + else + currline->text[col] = toupper(currline->text[col]); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::LookupCursor() { + + GFTRK("EditLookupCursor"); + + LookupNode(msgptr, currline->text+col, LOOK_NAME); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::LookupDest() { + + GFTRK("EditLookupDest"); + + LookupNode(msgptr, "", LOOK_DEST); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::LookupOrig() { + + GFTRK("EditLookupOrig"); + + LookupNode(msgptr, "", LOOK_ORIG); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::Soundkill() { + + HandleGEvent(EVTT_STOPVOICE); +} + + +// ------------------------------------------------------------------ + +void IEclass::statusline() { + + if(chartyped) { + if(EDIT->Completion.First()) { + do { + const char* trig = EDIT->Completion.Trigger(); + uint tlen = strlen(trig); + if(col >= tlen) { + if(strneql(trig, currline->text+col-tlen, tlen)) { + uint n; + for(n=0; nCompletion.Text(); + uint clen = strlen(cptr); + for(n=0; nCompletion.Next()); + } + } + + char _buf[EDIT_BUFLEN]; + *_buf = NUL; + + if(EDIT->Comment.First()) { + do { + const char* trig = EDIT->Comment.Trigger(); + uint tlen = strlen(trig); + if(col >= tlen) { + if(strnieql(trig, currline->text+col-tlen, tlen)) { + strcpy(_buf, EDIT->Comment.Text()); + break; + } + } + } while(EDIT->Comment.Next()); + } + + update_statuslinef(LNG->EditStatus, 1+thisrow, 1+col, _buf); + if(*_buf and CFG->switches.get(beepcomment)) { + HandleGEvent(EVTT_EDITCOMMENT); + } +} + + +// ------------------------------------------------------------------ + +int IEclass::handlekey(gkey __key) { + + int rc = YES; + + switch(__key) { + case KK_EditBlockRight: __key = KK_EditGoRight; break; + case KK_EditBlockLeft: __key = KK_EditGoLeft; break; + case KK_EditBlockUp: __key = KK_EditGoUp; break; + case KK_EditBlockDown: __key = KK_EditGoDown; break; + case KK_EditBlockHome: __key = KK_EditGoBegLine; break; + case KK_EditBlockEnd: __key = KK_EditGoEOL; break; + case KK_EditBlockPgDn: __key = KK_EditGoPgDn; break; + case KK_EditBlockPgUp: __key = KK_EditGoPgUp; break; + + case KK_EditCopy: + case KK_EditCut: + case KK_EditDelete: goto noselecting; + + case KK_EditDelChar: + case KK_EditDelLeft: + case KK_EditPaste: + if(selecting) { + BlockCut(true); + batch_mode = BATCH_MODE; + if(__key != KK_EditPaste) + __key = KK_EditUndefine; + } + goto noselecting; + break; + + default: + if(selecting) { + Line *_line; + selecting = NO; + blockcol = -1; + for(_line = findfirstline(); _line; _line = _line->next) + _line->type &= ~GLINE_BLOK; + // refresh screen + int r = row; + for(_line = currline; _line and r; _line = _line->prev) + r--; + refresh(_line, minrow); + } + goto noselecting; + } + + if(not selecting) { + Line *_line; + for(_line = findfirstline(); _line; _line = _line->next) + _line->type &= ~GLINE_BLOK; + currline->type |= GLINE_BLOK; + selecting = YES; + blockcol = col; + // refresh screen + int r = row; + for(_line = currline; _line and r; _line = _line->prev) + r--; + refresh(_line, minrow); + } + +noselecting: + + switch(__key) { + case KK_EditAbort: Abort(); break; + case KK_EditAskExit: AskExit(); break; + case KK_EditClearDeleteBuf: ClearDeleteBuf(); break; + case KK_EditClearPasteBuf: ClearPasteBuf(); break; + case KK_EditCopyAboveChar: CopyAboveChar(); break; + case KK_EditDelChar: DelChar(); break; + case KK_EditDeleteEOL: DeleteEOL(); break; + case KK_EditDelLeft: DelLeft(); break; + case KK_EditDelLine: DelLine(); break; + case KK_EditDelLtWord: DelLtWord(); break; + case KK_EditDelRtWord: DelRtWord(); break; + case KK_EditDosShell: DosShell(); break; + case KK_EditDupLine: DupLine(); break; + case KK_EditExitMsg: ExitMsg(); break; + case KK_EditExportText: ExportText(); break; + case KK_EditGoBegLine: GoBegLine(); break; + case KK_EditGoBotLine: GoBotLine(); break; + case KK_EditGoBotMsg: GoBotMsg(); break; + case KK_EditGoDown: GoDown(); break; + case KK_EditGoEOL: GoEOL(); break; + case KK_EditGoLeft: GoLeft(); break; + case KK_EditGoPgDn: GoPgDn(); break; + case KK_EditGoPgUp: GoPgUp(); break; + case KK_EditGoRight: GoRight(); break; + case KK_EditGoTopLine: GoTopLine(); break; + case KK_EditGoTopMsg: GoTopMsg(); break; + case KK_EditGoUp: GoUp(); break; + case KK_EditGoWordLeft: GoWordLeft(); break; + case KK_EditGoWordRight: GoWordRight(); break; + case KK_EditHeader: Header(); break; + case KK_EditImportQuotebuf: ImportQuotebuf(); break; + case KK_EditImportText: ImportText(); break; + case KK_EditLoadFile: LoadFile(); break; + case KK_EditLookupCursor: LookupCursor(); break; + case KK_EditLookupDest: LookupDest(); break; + case KK_EditLookupOrig: LookupOrig(); break; + case KK_EditNewline: Newline(); break; + case KK_EditQuitNow: QuitNow(); break; + case KK_EditReflow: Reflow(); break; + case KK_EditSaveFile: SaveFile(); break; + case KK_EditSaveMsg: SaveMsg(); break; + case KK_EditSoundkill: Soundkill(); break; + case KK_EditSpellCheck: SpellCheck(); break; + case KK_EditTab: Tab(); break; + case KK_EditTabReverse: ReTab(); break; + case KK_EditToggleCase: ToggleCase(); break; + case KK_EditToggleInsert: ToggleInsert(); break; + case KK_EditToLower: ToLower(); break; + case KK_EditToUpper: ToUpper(); break; + case KK_EditUndefine: break; + case KK_EditUnDelete: UnDelete(); break; + case KK_EditUndo: Undo->PlayItem(); break; + case KK_EditZapQuoteBelow: ZapQuoteBelow(); break; + + // Block functions + case KK_EditAnchor: BlockAnchor(); break; + case KK_EditCopy: BlockCopy(); break; + case KK_EditCut: BlockCut(); break; + case KK_EditDelete: BlockCut(true); break; + case KK_EditPaste: BlockPaste(); break; + + default: + rc = PlayMacro(__key, KT_E); + } + + if(__key != KK_EditUndo) + undo_ready = NO; + + return rc; +} + + +// ------------------------------------------------------------------ + +int IEclass::Start(int __mode, uint* __position, GMsg* __msg) { + + GFTRK("EditStart"); + + thisrow = 0; + quitnow = NO; + col = mincol; + row = minrow; + msgptr = __msg; + msgmode = __mode; + currline = __msg->lin; + + if(AA->isinternet() and CFG->soupexportmargin <= CFG->dispmargin) + margintext = CFG->soupexportmargin; + else + margintext = CFG->dispmargin; + + marginquotes = EDIT->QuoteMargin(); + if(marginquotes > margintext) + marginquotes = margintext; + + whelppcat(H_Editor); + + if(currline == NULL) { + currline = (Line*)throw_xcalloc(1, sizeof(Line)); + currline->text = throw_strdup("\n"); + } + + // Check if there is an unfinished backup message + FILE* _fp = fsopen(AddPath(CFG->goldpath, EDIT->File()), "rt", CFG->sharemode); + if(_fp) { + char _buf[EDIT_BUFLEN]; + fgets(_buf, sizeof(_buf), _fp); + fclose(_fp); + if(striinc(unfinished, _buf)) { + w_info(LNG->UnfinishedMsg); + update_statusline(LNG->LoadUnfinished); + HandleGEvent(EVTT_ATTENTION); + gkey _ch = getxch(); + w_info(NULL); + if(_ch != Key_Esc) { + LoadFile(); + *__position = 0; + remove(AddPath(CFG->goldpath, EDIT->File())); + } + } + } + + if(*__position) { + for(uint _posrow=0; _posrow < *__position; _posrow++) { + if(currline->next) { + currline = currline->next; + row++; + } + } + thisrow = row; + } + + done = NO; + + // If the starting line is outside the first screenful + if(*__position >= (maxrow+1)) { + refresh(currline->prev, minrow); + row = 1; + } + else { + refresh(findfirstline(), minrow); + } + + gotorowcol(mincol, minrow); + dispins(); + + time_t _lasttime = time(NULL); + + while(not done) { + + statusline(); + + gotorowcol(col, row); + batch_mode = 0; + + int backattr = 0; + if(blockcol == -1) { + backattr = dispchar(currline->text[col], C_READC); + gotorowcol(col, row); + } + + cursoron(); + if(insert) + vcursmall(); + else + vcurlarge(); + + gkey _ch; + + do { + _ch = getxchtick(); + + if(EDIT->AutoSave()) { + time_t _thistime = time(NULL); + if(_thistime >= (_lasttime+EDIT->AutoSave())) { + _lasttime = _thistime; + SaveFile(); + } + } + + if(_ch == Key_Tick) + CheckTick(KK_EditQuitNow); + + } while(_ch == Key_Tick); + + pcol = col; getthisrow(currline); prow = thisrow; + + int ismacro = false; + gkey _kk = SearchKey(_ch, EditKey, EditKeys); + if(_kk) { + _ch = _kk; + } + else { + ismacro = IsMacro(_ch, KT_E); + } + + if(blockcol == -1) + dispchar(currline->text[col], backattr); + + chartyped = false; + if((_ch < KK_Commands) and (_ch & 0xFF) and not ismacro) { + chartyped = true; + _ch &= 0xFF; + insertchar((char)_ch); + undo_ready = YES; + } + else if(handlekey(_ch)) { + getthisrow(currline); + } + } + + cursoroff(); + + msgptr->lin = findfirstline(); + savefile(quitnow ? MODE_UPDATE : MODE_SAVE); + whelpop(); + + // Prune killbuffer + if(Edit__killbuf) { + Line *__line = Edit__killbuf; + + int _count = EDIT->UnDelete(); + while(__line and _count--) + __line = __line->prev; + + if(__line) + if(__line->next) + __line->next->prev = NULL; + + while(__line) { + if(Undo->FixPushLine(__line)) { + if(__line->prev) { + __line = __line->prev; + __line->next = NULL; + } + else { + __line = NULL; + } + } + else { + throw_release(__line->text); + if(__line->prev) { + __line = __line->prev; + throw_xrelease(__line->next); + } + else { + throw_xrelease(__line); + } + } + } + } + + *__position = 1 + thisrow; + + GFTRK(NULL); + + return done; +} + + +// ------------------------------------------------------------------ + +UndoStack::UndoStack(IEclass* this_editor) : + + editor(this_editor), + row(editor->row), + col(editor->col), + pcol(editor->pcol), + prow(editor->prow), + minrow(editor->minrow), + maxrow(editor->maxrow), + thisrow(editor->thisrow), + currline(editor->currline), + undo_ready(editor->undo_ready) { + UndoItem::last_item = &last_item; + last_item = NULL; + undo_enabled = YES; +} + + +// ------------------------------------------------------------------ + +UndoStack::~UndoStack() { + + while(last_item) { + switch(last_item->action & EDIT_UNDO_ACTION) { + case EDIT_UNDO_DEL_TEXT: + case EDIT_UNDO_WRAP_TEXT: + delete last_item->data.text_ptr; + break; + case EDIT_UNDO_DEL_LINE: + if(last_item->data.line_ptr->isallocated()) + throw_release(last_item->data.line_ptr->text); + throw_xfree(last_item->data.line_ptr); + } + delete last_item; + } +} + + +// ------------------------------------------------------------------ + +bool UndoStack::FixPushLine(Line* __line) { + + UndoItem* item = last_item; + + while(item) { + if(((item->action & EDIT_UNDO_ACTION) == EDIT_UNDO_PUSH_LINE) and (item->data.line_ptr == __line)) { + item->action &= ~EDIT_UNDO_ACTION; + item->action |= EDIT_UNDO_ORPHAN_LINE; + return true; + } + item = item->prev; + } + return false; +} + + +// ------------------------------------------------------------------ + +void UndoStack::PushItem(uint action, Line* __line, uint __col, uint __len) { + + if(undo_enabled) { + + throw_new(last_item = new UndoItem); + last_item->col.num = (__col != NO_VALUE) ? __col : col; + last_item->col.sav = 0; + last_item->action = action; + last_item->pcol = pcol; + last_item->prow = prow; + + switch(action & EDIT_UNDO_ACTION) { + case EDIT_UNDO_VOID: + case EDIT_UNDO_INS_CHAR: + last_item->line = __line ? __line : currline; + break; + case EDIT_UNDO_DEL_CHAR: + case EDIT_UNDO_OVR_CHAR: + last_item->line = __line ? __line : currline; + last_item->data.char_int = last_item->line->text[last_item->col.num]; + break; + case EDIT_UNDO_DEL_TEXT: + last_item->line = __line; + if(__len == NO_VALUE) + __len = strlen(__line->text + __col) + 1; + throw_new(last_item->data.text_ptr = new(__len) text_item(__col, __len)); + memcpy(last_item->data.text_ptr->text, __line->text + __col, __len); + break; + case EDIT_UNDO_CUT_TEXT: + last_item->line = __line; + break; + case EDIT_UNDO_INS_TEXT: + last_item->line = __line; + goto save_item; + case EDIT_UNDO_WRAP_TEXT: + last_item->line = __line->prev; + save_item: + throw_new(last_item->data.text_ptr = new text_item(__col, __len)); + break; + case EDIT_UNDO_NEW_LINE: + last_item->line = last_item->data.line_ptr = __line; + break; + case EDIT_UNDO_DEL_LINE: + last_item->line = __line->prev ? __line->prev : __line->next; + last_item->data.line_ptr = __line; + break; + case EDIT_UNDO_PUSH_LINE: + if(currline->next) + last_item->line = currline->next; + else { + last_item->action |= LAST_LINE; + last_item->line = currline->prev; + } + last_item->data.line_ptr = currline; + break; + case EDIT_UNDO_POP_LINE: + last_item->line = currline; + } + } +} + + +// ------------------------------------------------------------------ + +void UndoStack::PlayItem() { + + if(last_item) { + + UndoItem* item; + + // Don't save any new items while in Undo function + undo_enabled = NO; + + // Find first of the batch items + for(item = last_item; item->action & BATCH_MODE; item = item->prev); + + uint curr_row_num = thisrow; + uint curr_col_num = col; + currline = (item->action & PREV_LINE) ? item->line->next : item->line; + editor->getthisrow(currline); + col = item->col.num; + + if(curr_row_num != thisrow) { + + // Let user to see the position before performing Undo, unless it's a + // neighbour line and the same column. + undo_ready = (abs(int(curr_row_num - thisrow)) < 2 and (curr_col_num == col or col+1 > strlen(currline->text))); + + // Move cursor up or down depending on where the undo line is, + // then refresh window if the line is invisible. + do { + if(curr_row_num > thisrow) { + if(row > minrow) + curr_row_num--, row--; + else { + editor->refresh(currline, row); + break; + } + } + else { + if(row < maxrow) + curr_row_num++, row++; + else { + Line* l = currline; + for(uint r = row; r; l = l->prev, r--) {} + editor->refresh(l, minrow); + break; + } + } + } while(curr_row_num != thisrow); + } + else + undo_ready = (abs(int(curr_col_num - col)) < 2 or col+1 > strlen(currline->text)); + + uint _pcol = item->pcol; + uint _prow = item->prow; + + if(undo_ready) { + + bool in_batch; + + // Keep undoing until item with no BATCH_MODE flag is reached. + do { + + uint undo_type = last_item->action & EDIT_UNDO_TYPE; + uint undo_action = last_item->action & EDIT_UNDO_ACTION; + in_batch = last_item->action & BATCH_MODE; + currline = last_item->line; + + if(last_item->action & PREV_LINE) { + col = last_item->col.num = last_item->col.sav; + if(row > minrow) + row--; + } + + switch(undo_type) { + + case EDIT_UNDO_CHAR: + switch(undo_action) { + case EDIT_UNDO_INS_CHAR: + editor->strdelchr(currline->text, last_item->col.num); + break; + case EDIT_UNDO_DEL_CHAR: + editor->strinschr(currline->text, last_item->data.char_int, last_item->col.num); + break; + case EDIT_UNDO_OVR_CHAR: + currline->text[last_item->col.num] = last_item->data.char_int; + break; + } + editor->setlinetype(currline); + break; + + case EDIT_UNDO_TEXT: { + text_item* text_data = last_item->data.text_ptr; + char *dest_ptr, *from_ptr, *thistext = currline->text; + switch(undo_action) { + case EDIT_UNDO_DEL_TEXT: + thistext = currline->text = (char*)throw_realloc(thistext, strlen(thistext) + text_data->len + 1); + memmove(thistext + text_data->col + text_data->len, thistext + text_data->col, strlen(thistext + text_data->col) + 1); + memcpy(thistext + text_data->col, text_data->text, text_data->len); + delete text_data; + break; + case EDIT_UNDO_CUT_TEXT: + thistext[last_item->col.num] = NUL; + break; + case EDIT_UNDO_WRAP_TEXT: + thistext = currline->text = (char*)throw_realloc(thistext, strlen(thistext) + text_data->len + 1); + strncat(thistext, currline->next->text + text_data->col, text_data->len); + thistext = currline->next->text; + // fall through... + case EDIT_UNDO_INS_TEXT: + dest_ptr = thistext + text_data->col; + from_ptr = dest_ptr + text_data->len; + memmove(dest_ptr, from_ptr, strlen(from_ptr) + 1); + delete text_data; + break; + } + editor->setlinetype(currline); + break; + } + + case EDIT_UNDO_LINE: { + Line* thisline = last_item->data.line_ptr; + switch(undo_action) { + case EDIT_UNDO_NEW_LINE: + if(thisline->next) + thisline->next->prev = thisline->prev; + if(thisline->prev) { + thisline->prev->next = thisline->next; + currline = thisline->prev; + } + else + currline = thisline->next; + throw_release(thisline->text); + throw_xfree(thisline); + break; + case EDIT_UNDO_ORPHAN_LINE: + if(last_item->action & LAST_LINE) { + thisline->prev = currline; + thisline->next = currline ? currline->next : NULL; + /*if(row == maxrow) + down = true; + else*/ if((row < maxrow) and currline) + row++; + } + else { + thisline->prev = currline ? currline->prev : NULL; + thisline->next = currline; + } + // fall through... + case EDIT_UNDO_DEL_LINE: + if(thisline->prev) + thisline->prev->next = thisline; + if(thisline->next) + thisline->next->prev = thisline; + currline = thisline; + break; + case EDIT_UNDO_PUSH_LINE: + editor->UnDelete((last_item->action & LAST_LINE) ? false : true); + break; + case EDIT_UNDO_POP_LINE: + editor->DelLine(); + break; + } + } + } + + _pcol = last_item->pcol; + _prow = last_item->prow; + delete last_item; + + } while(last_item and in_batch); + + editor->refresh(currline, row); + undo_enabled = YES; + editor->getthisrow(currline); + uint temprow = thisrow, posrow; + + Line *templine = editor->findfirstline(); + if(templine) { + for(posrow=0; posrow < _prow; posrow++) + if(templine->next) + templine = templine->next; + thisrow = posrow; col = _pcol; + currline = templine; + + if(not in_range(thisrow-temprow, minrow, maxrow)) { + do { + if(thisrow > temprow) { + if(row > minrow) + temprow--, row--; + else { + editor->refresh(templine, row); + break; + } + } + else { + if(row < maxrow) + temprow++, row++; + else { + editor->refresh(templine, row = minrow); + break; + } + } + } while(temprow != thisrow); + } + else { + row += thisrow-temprow; + editor->refresh(templine, row); + } + } + } + // Move the cursor to EOL if necessary + else if((col+1) > strlen(currline->text)) + editor->GoEOL(); + undo_ready = YES; + } +} + + +// ------------------------------------------------------------------ diff --git a/golded3/geedit.h b/golded3/geedit.h new file mode 100644 index 0000000..807f900 --- /dev/null +++ b/golded3/geedit.h @@ -0,0 +1,421 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// The Internal Editor (IE). +// ------------------------------------------------------------------ + +#ifdef __GNUG__ +#pragma interface "geedit.h" +#endif + + +// ------------------------------------------------------------------ +// Screen coordinate models +// ------------------------------------------------------------------ +// +// 00 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ 01 +// 01 Msg# : 02 +// 02 From : 03 +// 03 To : 04 +// 04 Subj : 05 +// 05 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ 06 +// 06 00 EDIT_MINROW 07 EDIT_MIN_ROW +// 07 01 08 +// 08 02 09 +// 09 03 10 +// 10 04 11 +// 11 05 12 +// 12 06 13 +// 13 07 14 +// 14 08 15 +// 15 09 16 +// 16 10 17 +// 17 11 18 +// 18 12 19 +// 19 13 10 +// 10 14 21 +// 21 15 22 +// 22 16 23 +// 23 17 EDIT_MAXROW 24 EDIT_MAX_ROW +// 24 ÛGoldED xxxx (statusline) 25 +// ³ ³ ³ +// ³ ³ ÀÄÄÄÄ one-based old-style coord +// ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ editor window corrdinates +// ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ actual screen coordinates +// +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ +// Defines + +#define EDIT_BUFLEN 256 +#define EDIT_PARABUFLEN 2048 + +#define EDIT_UNDO_CHAR 0x00000010U +#define EDIT_UNDO_INS_CHAR 0x00000011U +#define EDIT_UNDO_DEL_CHAR 0x00000012U +#define EDIT_UNDO_OVR_CHAR 0x00000014U + +#define EDIT_UNDO_TEXT 0x00001000U +#define EDIT_UNDO_DEL_TEXT 0x00001100U +#define EDIT_UNDO_CUT_TEXT 0x00001200U +#define EDIT_UNDO_INS_TEXT 0x00001400U +#define EDIT_UNDO_WRAP_TEXT 0x00001800U + +#define EDIT_UNDO_LINE 0x00100000U +#define EDIT_UNDO_DEL_LINE 0x00110000U +#define EDIT_UNDO_NEW_LINE 0x00120000U +#define EDIT_UNDO_PUSH_LINE 0x00140000U +#define EDIT_UNDO_POP_LINE 0x00180000U +#define EDIT_UNDO_ORPHAN_LINE 0x00190000U + +#define EDIT_UNDO_VOID 0x00000000U + +#define EDIT_UNDO_TYPE 0x00101010U +#define EDIT_UNDO_ACTION 0x001F1F1FU + +#define LAST_LINE 0x20000000U +#define PREV_LINE 0x40000000U +#define BATCH_MODE 0x80000000U +#define NO_VALUE 0xFFFFFFFFU + + +// ------------------------------------------------------------------ +// Globals + +extern int CFG__editquotewrap; + +extern Line* Edit__killbuf; +extern Line* Edit__pastebuf; + +extern Path Edit__exportfilename; + + +// ------------------------------------------------------------------ +// Reality check define and function + +#ifdef NDEBUG +#define _test_halt(__t) +#define _test_haltab(__t, __a, __b) +#else +#define _test_halt(__t) if(__t) { debugtest(#__t, 0, 0, __FILE__, __LINE__, false); } +#define _test_haltab(__t, __a, __b) if(__t) { debugtest(#__t, __a, __b, __FILE__, __LINE__, true); } +#endif + + +// ------------------------------------------------------------------ +// Undo data structures + +class text_item { + +public: + + uint col; // Begining offset in the .text string + uint len; // Text length + __extension__ char text[0]; // Text string itself + + text_item(uint __col, uint __len) : col(__col), len(__len) { } + void* operator new(size_t size, uint text_len = 0) { return malloc(sizeof(text_item) + size + text_len); } + void operator delete(void* ptr) { free(ptr); } +}; + +// ---------------------------------------------------------------- + +union data_rec { + + text_item* text_ptr; + Line* line_ptr; + void* void_ptr; + char char_int; +}; + +struct col_rec { + + uint num; + uint sav; +}; + +// ---------------------------------------------------------------- + +class UndoItem { + + static UndoItem** last_item; + + friend class UndoStack; + +public: + + UndoItem* prev; + + Line* line; // Cursor line + col_rec col; // Cursor column + uint pcol; // After undo move cursor to pcol, prow + uint prow; // + uint action; // Undo action + data_rec data; // Undo data + + UndoItem() { this->prev = *last_item; } + ~UndoItem() { *last_item = this->prev; } +}; + +// ---------------------------------------------------------------- + +class IEclass; + +class UndoStack { + + IEclass* editor; + + uint& row; + uint& col; + uint& pcol; + uint& prow; + uint& minrow; + uint& maxrow; + uint& thisrow; + Line*& currline; + bool& undo_ready; + +public: + + UndoItem* last_item; + bool undo_enabled; + + UndoStack(IEclass* this_editor); + ~UndoStack(); + + bool FixPushLine(Line* __line); + void PushItem(uint action, Line* __line = NULL, uint __col = NO_VALUE, uint __len = NO_VALUE); + void PlayItem(); +}; + + +// ------------------------------------------------------------------ +// Internal Editor Class + +class IEclass : public Container { + +public: + + gwindow editwin; // window + +protected: + + // ---------------------------------------------------------------- + // Editor window data + + int win_mincol; // First column + int win_minrow; // First row + int win_maxcol; // Last column + int win_maxrow; // Last row + int win_border; // Border type + int win_hasborder; // 1 == window has a border, 0 == no border + + + // ---------------------------------------------------------------- + // Window-relative minimum/maximum values + + uint mincol; + uint minrow; + uint maxcol; + uint maxrow; + + + // ---------------------------------------------------------------- + // Cursor coordinates + + uint col; + uint row; + uint pcol; + uint prow; + uint ccol; + uint crow; + + + // ---------------------------------------------------------------- + // Undo stuff + + friend class UndoStack; + + UndoStack* Undo; + long batch_mode; + bool undo_ready; + + + // ---------------------------------------------------------------- + // Misc. + + int chartyped; + Line* currline; + int done; + int insert; + int marginquotes; + int margintext; + int msgmode; + GMsg* msgptr; + int quitnow; + uint thisrow; + char* unfinished; + int blockcol; + int selecting; + + + // ---------------------------------------------------------------- + // Internal helper functions + + void clreol (int __col=-1, int __row=-1); + void cursoroff (); + void cursoron (); + void deleteline (bool zapquotesbelow = false); + int dispchar (vchar __ch, int attr=-1); + void dispins (); + void displine (Line* __line, uint __row); + void dispstring (char* __string, uint __row, int attr=-1, Line* line=NULL); + int downoneline (uint __row); + void editexport (Line* __exportline, int __endat); + Line* findanchor (); + Line* findfirstline (); + Line* findtopline (); + void getthisrow (Line* __currline); + void gotorowcol (uint __col, uint __row); + int handlekey (gkey __key); + void editimport (Line* __line, char* __filename, bool imptxt = false); + void imptxt (char* __filename, bool imptxt = false); + void insertchar (char __ch); + Line* insertlinebelow (Line* __currline, char* __text = NULL, long __batch_mode = 0); + int isempty (Line* __line=NULL); + void killkillbuf (); + void killpastebuf (); + void prints (int wrow, int wcol, int atr, char* str); + int reflowok (char* __qstr); + void refresh (Line* __currline, uint __row); + void savefile (int __status); + void scrolldown (int __scol, int __srow, int __ecol, int __erow, int __lines=1); + void scrollup (int __scol, int __srow, int __ecol, int __erow, int __lines=1); + void setcolor (Line* __line); + void setlinetype (Line* __line); + void statusline (); + void strdelchr (char* __string, uint __position); + void strinschr (char*& __string, char __ch, uint __position); + void windowclose (); + void windowopen (); + Line* wrapit (Line** __currline, uint* __curr_col, uint* __curr_row, int __display=YES); + Line* wrapdel (Line** __currline, uint* __curr_col, uint* __curr_row, int __display=YES); + Line* wrapins (Line** __currline, uint* __curr_col, uint* __curr_row, int __display=YES); + + #ifndef NDEBUG + void debugtest (char* __test, int __a, int __b, char* __file, int __line, int __values); + #endif + + void Buf2Clip (); + void Clip2Buf (); + + +public: + + // ---------------------------------------------------------------- + // Constructor and destructor + + IEclass(int __scol, int __ecol, int __srow, int __erow, int __border); + ~IEclass(); + + + // ---------------------------------------------------------------- + // Function to start the editor + + int Start(int __mode, uint* __position, GMsg* __msg); + + + // ---------------------------------------------------------------- + // User key functions + + void Abort (); + void AskExit (); + void BlockAnchor (); + void BlockCopy (); + void BlockCut (bool just_delete = false); + void BlockPaste (); + void BlockDel (Line* _anchor); + void ClearDeleteBuf (); + void ClearPasteBuf (); + void CopyAboveChar (); + void DelChar (); + void DeleteEOL (); + void DelLeft (); + void DelLine (); + void DelLtWord (); + void DelRtWord (); + void DosShell (); + void DupLine (); + void ExitMsg (); + void ExportText (); + void GoBegLine (); + void GoBotLine (); + void GoBotMsg (); + void GoDown (); + void GoEOL (); + void GoLeft (); + void GoPgDn (); + void GoPgUp (); + void GoRight (); + void GoTopLine (); + void GoTopMsg (); + void GoUp (); + void GoWordLeft (); + void GoWordRight (); + void Header (); + void ImportQuotebuf (); + void ImportText (); + void LoadFile (); + void LookupCursor (); + void LookupDest (); + void LookupOrig (); + void Newline (); + void QuitNow (); + void Reflow (); + void ReTab (); + void SaveFile (); + void SaveMsg (); + void Soundkill (); + void SpellCheck (); + void Tab (); + void ToggleCase (); + void ToggleInsert (); + void ToLower (); + void ToUpper (); + void UnDelete (bool before=true); + void ZapQuoteBelow (); + + + // ---------------------------------------------------------------- +}; + +// ------------------------------------------------------------------ + +void Edit__killpastebuf(void); + +inline void IEclass::killpastebuf() { Edit__killpastebuf(); } + +// ------------------------------------------------------------------ + diff --git a/golded3/geedit2.cpp b/golded3/geedit2.cpp new file mode 100644 index 0000000..b2def88 --- /dev/null +++ b/golded3/geedit2.cpp @@ -0,0 +1,1432 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// The Internal Editor (IE), part 2. +// ------------------------------------------------------------------ + +#include +#include +#include +#include + + +// ------------------------------------------------------------------ +// Constructor + +IEclass::IEclass(int __scol, int __ecol, int __srow, int __erow, int __border) { + + win_mincol = __scol; + win_minrow = __srow; + win_maxcol = __ecol; + win_maxrow = __erow; + win_border = __border; + + win_hasborder = (win_border == 5) ? 0 : 1; + + mincol = 0; + minrow = 0; + maxcol = win_maxcol - win_mincol - (2*win_hasborder); + maxrow = win_maxrow - win_minrow - (2*win_hasborder); + + col = 0; + row = 0; + ccol = 0; + crow = 0; + + chartyped = false; + currline = NULL; + done = NO; + insert = YES; + marginquotes = 0; + margintext = 0; + msgmode = 0; + msgptr = NULL; + quitnow = NO; + thisrow = 0; + unfinished = "+$!$+ GoldED Internal Editor: Unfinished Message!"; + blockcol = -1; + selecting = NO; + + throw_new(Undo = new UndoStack(this)); + windowopen(); +} + + +// ------------------------------------------------------------------ +// Destructor + +IEclass::~IEclass() { + + throw_delete(Undo); + windowclose(); +} + + +// ------------------------------------------------------------------ + +void IEclass::windowopen() { + + // Open editor window without clearing the window area + #define STYLE_NOCLEAR -1 + int _tmp = gwin.style; + gwin.style = STYLE_NOCLEAR; + editwin.open(win_minrow, win_mincol, win_maxrow, win_maxcol, 5, C_READB, C_READW, C_READPB); + gwin.style = _tmp; +} + + +// ------------------------------------------------------------------ + +void IEclass::windowclose() { + + // Close editor window without removing the window itself + editwin.unlink(); +} + + +// ------------------------------------------------------------------ + +void Edit__killpastebuf() { + + while(Edit__pastebuf) { + throw_release(Edit__pastebuf->text); + if(Edit__pastebuf->next) { + Edit__pastebuf = Edit__pastebuf->next; + throw_xrelease(Edit__pastebuf->prev); + } + else { + throw_xrelease(Edit__pastebuf); + } + } +} + + +// ------------------------------------------------------------------ + +void Edit__killkillbuf() { + + while(Edit__killbuf) { + throw_release(Edit__killbuf->text); + if(Edit__killbuf->prev) { + Edit__killbuf = Edit__killbuf->prev; + throw_xrelease(Edit__killbuf->next); + } + else { + throw_xrelease(Edit__killbuf); + } + } +} + + +// ------------------------------------------------------------------ + +void IEclass::killkillbuf() { + + while(Edit__killbuf) { + if(Undo->FixPushLine(Edit__killbuf)) { + if(Edit__killbuf->prev) { + Edit__killbuf = Edit__killbuf->prev; + Edit__killbuf->next = NULL; + } + else { + Edit__killbuf = NULL; + } + } + else { + throw_release(Edit__killbuf->text); + if(Edit__killbuf->prev) { + Edit__killbuf = Edit__killbuf->prev; + throw_xrelease(Edit__killbuf->next); + } + else { + throw_xrelease(Edit__killbuf); + } + } + } +} + + +// ------------------------------------------------------------------ + +void FreePastebuf() { + + Edit__killpastebuf(); + Edit__killkillbuf(); +} + + +// ------------------------------------------------------------------ + +void IEclass::ClearDeleteBuf() { + + GFTRK("EditClearDeleteBuf"); + + killkillbuf(); + HandleGEvent(EVTT_JOBDONE); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::ClearPasteBuf() { + + GFTRK("EditClearPasteBuf"); + + killpastebuf(); + HandleGEvent(EVTT_JOBDONE); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::GoBegLine() { + + GFTRK("EditGoBegLine"); + + col = mincol; + + if(blockcol != -1) + displine(currline, row); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::DelLtWord() { + + GFTRK("EditDelLtWord"); + + char* _ptr; + char* _ptr2; + char* _bptr; + + if(col == 0) { + DelLeft(); + GFTRK(NULL); + return; + } + + _bptr = currline->text; + _ptr = _ptr2 = currline->text + col; + _ptr--; + + // test test test test test test test test + // test test test test , test test test test + // test test test test ,, test test test test + + if(*_ptr == ' ') { + while((*_ptr == ' ') and (_bptr < _ptr)) + _ptr--; + if(*_ptr != ' ') + _ptr++; + } + else if(isxalnum(*_ptr)) { + while(isxalnum(*_ptr) and (_bptr < _ptr)) + _ptr--; + while((*_ptr == ' ') and (_bptr < _ptr)) + _ptr--; + if((*_ptr != ' ') and (_bptr < _ptr)) + _ptr++; + } + else { + DelLeft(); + GFTRK(NULL); + return; + } + + col -= (int)(_ptr2-_ptr); + + Undo->PushItem(EDIT_UNDO_DEL_TEXT, currline, col, _ptr2-_ptr); + memmove(_ptr, _ptr2, strlen(_ptr2)+1); + THROW_CHECKPTR(currline->text); + + wrapdel(&currline, &col, &row); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::DelRtWord() { + + GFTRK("EditDelRtWord"); + + char* _ptr; + char* _ptr2; + + if((currline->text[col+1] == NUL) or (currline->text[col+1] == '\n')) { + DelChar(); + GFTRK(NULL); + return; + } + + _ptr = _ptr2 = currline->text + col; + + // test test test test, test test test test + // test test test test, test test test test + + if(*_ptr == ' ') { + while((*_ptr == ' ') and (*_ptr != '\n') and *_ptr) + _ptr++; + } + else if(isxalnum(*_ptr)) { + // Delete word + while(isxalnum(*_ptr) and (*_ptr != '\n') and *_ptr) + _ptr++; + // Delete spaces after word + while((*_ptr == ' ') and (*_ptr != '\n') and *_ptr) + _ptr++; + } + else { + DelChar(); + GFTRK(NULL); + return; + } + + Undo->PushItem(EDIT_UNDO_DEL_TEXT, currline, col, _ptr-_ptr2); + memmove(_ptr2, _ptr, strlen(_ptr2)+1); + THROW_CHECKPTR(currline->text); + + wrapdel(&currline, &col, &row); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::GoTopMsg() { + + GFTRK("EditGoTopMsg"); + + currline = findfirstline(); + col = mincol; + row = minrow; + thisrow = 0; + refresh(currline, minrow); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::GoBotMsg() { + + GFTRK("EditGoBotMsg"); + + col = mincol; + thisrow = 0; + currline = findfirstline(); + + // Go to the last line in the msg + while(currline->next) { + currline = currline->next; + thisrow++; + } + + // Pointer to the line to display at the top of the window + Line* _topline = currline; + + // The new cursor row + row = MinV(thisrow, maxrow); + + // How many lines to go back to get the top line + int _count = row; + + // Go back to get the top line + while(_count-- and _topline->prev) + _topline = _topline->prev; + + // Refresh the display + refresh(_topline, minrow); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::GoTopLine() { + + GFTRK("EditGoTopLine"); + + int _count = row; + + while(_count-- and currline->prev) { + currline = currline->prev; + thisrow--; + } + + col = mincol; + row = minrow; + + if(blockcol != -1) + refresh(currline, minrow); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::GoBotLine() { + + GFTRK("EditGoBotLine"); + + Line *_oldcurrline = currline; + int _oldrow = row; + + while((row < maxrow) and currline->next) { + currline = currline->next; + thisrow++; + row++; + } + + col = mincol; + + if(blockcol != -1) + refresh(_oldcurrline, _oldrow); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +Line* IEclass::findanchor() { + + GFTRK("Editfindanchor"); + + // Rewind to the first line + Line* _anchor = findfirstline(); + + // Search all lines to find the anchor (a line with a block mark) + while(not (_anchor->type & GLINE_BLOK) and _anchor->next) + _anchor = _anchor->next; + + GFTRK(NULL); + + // Return pointer to the anchor line or NULL if no anchor was found + return (_anchor->type & GLINE_BLOK) ? _anchor : (Line*)NULL; +} + + +// ------------------------------------------------------------------ + +void IEclass::BlockAnchor() { + + GFTRK("EditBlockAnchor"); + + Line* _anchor = findanchor(); + + // Is there an anchor already? + if(_anchor) { + + // Yes, so replace it with the current line + + // Remove block mark + _anchor->type &= ~GLINE_BLOK; + blockcol = -1; + + // Is the old anchor different from the current line? + if(_anchor != currline) { + + // Set the new anchor + _anchor = currline; + _anchor->type |= GLINE_BLOK; + blockcol = col; + + // Find the line at the top + Line* _topline = findtopline(); + + // Refresh display to remove the block color on the old anchor line + // Just in case the old anchor line is visible + refresh(_topline, minrow); + } + + // Remove the old contents of the paste buffer + killpastebuf(); + } + else { + + for(Line* _line = findfirstline(); _line; _line = _line->next) + _line->type &= ~GLINE_BLOK; + + // There was no anchor, so mark the current line as the new anchor + currline->type |= GLINE_BLOK; + blockcol = col; + + // Refresh the display + Line* _topline = findtopline(); + refresh(_topline, minrow); + } + + displine(currline, row); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::BlockCopy() { + + GFTRK("EditBlockCopy"); + + // Find the anchor, if any + Line* _anchor = findanchor(); + + // Did we find the anchor? + if(_anchor) { + + Line* _firstcopyline = currline; + Line* _lastcopyline = currline; + int firstcol = col, lastcol = col; + + // Search below to find the anchor line + while(_lastcopyline->next and (_lastcopyline != _anchor)) + _lastcopyline = _lastcopyline->next; + + // Was the anchor line above or on the current line? + if(_lastcopyline != _anchor) { + + // The last copy line is the current line + _lastcopyline = currline; + + // Search above to find the anchor line + while(_firstcopyline->prev and (_firstcopyline != _anchor)) + _firstcopyline = _firstcopyline->prev; + firstcol = blockcol; + } + else { + if(currline != _anchor or blockcol > col) + lastcol = blockcol; + else + firstcol = blockcol; + } + + // The _firstcopyline and _lastcopyline pointers + // are now pointing where they should + + // Remove the old paste buffer + killpastebuf(); + + // Pointer to the previous line in the paste buffer + Line* _prevline = NULL; + + // Copy lines to the paste buffer + while(1) { + + // Allocate a new line + Line* _copyline = (Line*)throw_xcalloc(1, sizeof(Line)); + + // Copy text and type + if(_prevline == NULL) + _copyline->text = throw_strdup(_firstcopyline->text + firstcol); + else + _copyline->text = throw_strdup(_firstcopyline->text); + if(_firstcopyline == _lastcopyline) { + if(_prevline) + _copyline->text[lastcol] = NUL; + else + _copyline->text[lastcol-firstcol] = NUL; + } + _copyline->type = _firstcopyline->type & ~GLINE_BLOK; + + // Link in the new line + _copyline->prev = _prevline; + if(_prevline) + _prevline->next = _copyline; + _copyline->next = NULL; + + // Point the paste buffer to the first line of the copy + if(Edit__pastebuf == NULL) + Edit__pastebuf = _copyline; + + // Break out of the loop if the last line was copied + if(_firstcopyline == _lastcopyline) + break; + + // Keep pointer to the new line + _prevline = _copyline; + + // Continue with the next line + _firstcopyline = _firstcopyline->next; + } + + selecting = NO; + blockcol = -1; + for(Line* _line = findfirstline(); _line; _line = _line->next) + _line->type &= ~GLINE_BLOK; + + // Refresh display to remove the block color + Line* _topline = findtopline(); + refresh(_topline, minrow); + + Buf2Clip(); + } + killpastebuf(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::BlockDel(Line* anchor) { + + GFTRK("EditBlockDel"); + + Line* firstcutline = currline; + Line* lastcutline = currline; + uint firstcutlinerow = row; + uint lastcutlinerow = row; + int firstcol = col, lastcol = col; + + // Search below to find the anchor line + while(lastcutline->next and (lastcutline != anchor)) { + lastcutline = lastcutline->next; + lastcutlinerow++; + } + + // Was the anchor line above or on the current line? + if(lastcutline != anchor) { + + // The last cut line is the current line + lastcutline = currline; + lastcutlinerow = row; + + // Search above to find the anchor line + while(firstcutline->prev and (firstcutline != anchor)) { + firstcutline = firstcutline->prev; + if(firstcutlinerow) + firstcutlinerow--; + } + firstcol = blockcol; + } + else { + if(currline != anchor or blockcol > col) + lastcol = blockcol; + else + firstcol = blockcol; + } + + // The firstcutline and lastcutline pointers + // are now pointing where they should + + Undo->PushItem(EDIT_UNDO_DEL_TEXT, firstcutline, firstcol); + char *newtext = (char *)throw_malloc(firstcol+strlen(lastcutline->text)-lastcol+1); + strxcpy(newtext, firstcutline->text, firstcol+1); + strcat(newtext, lastcutline->text+lastcol); + throw_free(firstcutline->text); + firstcutline->text = newtext; + setlinetype(firstcutline); + firstcutline->type &= ~GLINE_BLOK; + blockcol = -1; + currline = firstcutline; + row = firstcutlinerow; + col = firstcol; + if(firstcutline != lastcutline) { + do { + Undo->PushItem(EDIT_UNDO_DEL_LINE|BATCH_MODE, firstcutline = firstcutline->next); + } while(firstcutline != lastcutline); + + currline->next = lastcutline->next; + if(lastcutline->next) + lastcutline->next->prev = currline; + } + + // Refresh the display + if(not RngV(row, minrow, maxrow)) { + row = minrow; + wrapdel(&currline, &col, &row, YES); + refresh(currline, minrow); + } + else { + row = MaxV(firstcutlinerow, minrow); + Line* topline = findtopline(); + wrapdel(&currline, &col, &row, NO); + refresh(topline, minrow); + } + + Line* line; + for(line = findfirstline(); line; line = line->next) + line->type &= ~GLINE_BLOK; + + selecting = NO; + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::BlockCut(bool just_delete) { + + GFTRK("EditBlockCut"); + + // Find the anchor, if any + Line* _anchor = findanchor(); + + // Did we find the anchor? + if(_anchor) { + + int _blockcol = blockcol; + + if(not just_delete) + BlockCopy(); + + blockcol = _blockcol; + + BlockDel(_anchor); + } + else + killpastebuf(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::BlockPaste() { + + GFTRK("EditBlockPaste"); + + killpastebuf(); + Clip2Buf(); + + if(Edit__pastebuf) { + + Line* _pasteline = Edit__pastebuf; + + if(not batch_mode) + Undo->PushItem(EDIT_UNDO_VOID); + + // For each of the lines in the paste buffer + while(_pasteline) { + + uint curlen = strlen(currline->text); + uint pastelen = strlen(_pasteline->text); + char *newtext = NULL; + + if(col > curlen) + col = curlen; + + if(strchr(_pasteline->text, '\n')) { + // append to current line + Undo->PushItem(EDIT_UNDO_DEL_TEXT|BATCH_MODE, currline, col); + Line* _newline = insertlinebelow(currline, currline->text + col, BATCH_MODE); + currline->text = (char*)throw_realloc(currline->text, pastelen + col + 1); + strcpy(currline->text+col, _pasteline->text); + setlinetype(currline); + col = strlen(currline->text); + wrapins(&currline, &col, &row, NO); + currline = _newline; + col = 0; + if(row < maxrow) + row++; + } + else { + // insert into current line + newtext = (char*)throw_malloc(curlen + pastelen + 1); + strxcpy(newtext, currline->text, col+1); + strcpy(stpcpy(newtext+col, _pasteline->text), currline->text + col); + throw_free(currline->text); + currline->text = newtext; + Undo->PushItem(EDIT_UNDO_INS_TEXT|BATCH_MODE, currline, col, pastelen); + col += strlen(_pasteline->text); + wrapins(&currline, &col, &row, NO); + } + + setlinetype(currline); + + // Continue with the next line in the paste buffer + _pasteline = _pasteline->next; + } + + selecting = NO; + blockcol = -1; + for(Line* _line = findfirstline(); _line; _line = _line->next) + _line->type &= ~GLINE_BLOK; + + // Refresh the display + Line* _topline = findtopline(); + refresh(_topline, minrow); + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::LoadFile() { + + GFTRK("EditLoadFile"); + + // Open the file to load + FILE* _fp = fsopen(AddPath(CFG->goldpath, EDIT->File()), "rb", CFG->sharemode); + if(_fp) { + + // Pop up a wait window + cursoroff(); + w_info(LNG->Wait); + + throw_delete(Undo); + + // Find the first line + Line* _line = findfirstline(); + + // Remove all lines + while(_line) { + Line* _nextline = _line->next; + throw_release(_line->text); + throw_xfree(_line); + _line = _nextline; + } + + // Remove message text and reset pointers + throw_release(msgptr->txt); + currline = msgptr->lin = NULL; + + // Allocate space for new message text + msgptr->txt = (char*)throw_calloc(1, (uint)(fsize(_fp)+256)); + + // Eat the backup marking line + char _buf[EDIT_BUFLEN]; + fgets(_buf, sizeof(_buf), _fp); + if(not striinc(unfinished, _buf)) + rewind(_fp); + + // Load the file and close it + fread(msgptr->txt, 1, (uint)fsize(_fp), _fp); + fclose(_fp); + + // Index message text + msgptr->TextToLines(margintext-1); + _line = currline = msgptr->lin; + + // Change lines to internal editor format + while(_line) { + strtrim(_line->text); + if(_line->type & GLINE_HARD) { + strcat(_line->text, "\n"); + THROW_CHECKPTR(_line->text); + } + else { + strcat(_line->text, " "); + THROW_CHECKPTR(_line->text); + } + _line = _line->next; + } + + // Remove the wait window + w_info(NULL); + + // Display the loaded message + Line* l = findfirstline(); + uint i; + + for(i=0; l->next and inext; + + refresh(l, minrow); + + for(i=0; l->next and inext; + + currline = l; + col = mincol; + + throw_new(Undo = new UndoStack(this)); + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +inline char uuencode_enc(int c) { return (char)(c ? (c & 077) + ' ': '`'); } + +void IEclass::editimport(Line* __line, char* __filename, bool imptxt) { + + GFTRK("Editimport"); + + // Save the unfinished msg first of all + savefile(MODE_UPDATE); + + update_statusline(LNG->ImportFile); + + // Set initial import filename or wildcards + if(__filename) { + AA->SetInputfile(__filename); + } + else { + if(*AA->Inputfile() == NUL) + AA->SetInputfile("*"); + } + + strcpy(CFG->inputfile, AA->Inputfile()); + + int ImportMode; + + if(imptxt) + ImportMode = 0; + else { + + GMenuImportTxt MenuImportTxt; + + ImportMode = MenuImportTxt.Run(); + } + + Path filenamebuf; + char* _filenameptr = filenamebuf; + char* _selectedfile = NULL; + + // Should the imported text be quoted or uuencoded? + #define quoteit (ImportMode == 1) + #define uuencode (ImportMode == 2) + #define base64 (ImportMode == 3) + #define getclip (ImportMode == 4) + #define binary (uuencode or base64) + + if(in_range(ImportMode, 0, 3) and edit_pathname(CFG->inputfile, sizeof(Path), LNG->ImportWhichFile, H_ImportFile)) { + + AA->SetInputfile(CFG->inputfile); + + // Pointer to the filename string + _filenameptr = strcpy(filenamebuf, AA->Inputfile()); + + // Check for wildcards + // Is the filename a directory? + if(is_dir(_filenameptr)) { + + // Does the filename contain wildcards? + if(not strpbrk(_filenameptr, "*?")) { + + // Add match-all wildcards + strcat(AddBackslash(_filenameptr), "*"); + } + } + + // Pointer to selected filename or NULL if no file is selected + _selectedfile = _filenameptr; + + // Does the filename contain wildcards? + if(strpbrk(_filenameptr, "*?")) { + + // Set selection window title and statusline + set_title(LNG->ImportTitle, TCENTER, C_MENUT); + update_statuslinef(LNG->ImportStatus, _filenameptr); + + // Copy filename with wildcards to a temp buffer + Path _filenamebuf; + strcpy(_filenamebuf, _filenameptr); + + // Start the file picker + _selectedfile = wpickfile( + win_minrow, + win_mincol, + win_maxrow, + win_maxcol, + W_BMENU, + C_MENUB, + C_MENUW, + C_MENUS, + NO, + _filenamebuf, + _filenameptr, + maketitle + ); + + // If a file was selected, copy the filename + if(_selectedfile) + strcpy(_filenameptr, _selectedfile); + } + } + + if(_selectedfile or getclip) { + + // Open the file/clipboard + FILE* fp = NULL; + gclipbrd clipbrd; + + if(getclip) + _filenameptr = strcpy(filenamebuf, CLIP_NAME); + + if(getclip ? clipbrd.openread() : + (fp = fsopen(_filenameptr, binary ? "rb" : "rt", CFG->sharemode))!=NULL) { + + update_statuslinef(LNG->ImportStatus, _filenameptr); + + // Allocate paragraph read buffer + char* _parabuf = (char*)throw_malloc(EDIT_PARABUFLEN); + + if(__line->prev) + Undo->PushItem(EDIT_UNDO_VOID|PREV_LINE|batch_mode, __line->prev); + else + Undo->PushItem(EDIT_UNDO_VOID|batch_mode, __line); + batch_mode = BATCH_MODE; + + // Add import begin text, if any + if(*CFG->importbegin) { + sprintf(_parabuf, "%s\n", CFG->importbegin); + strischg(_parabuf, "@file", getclip ? _filenameptr : CleanFilename(_filenameptr)); + _parabuf[margintext] = NUL; + __line = insertlinebelow(__line, _parabuf); + setlinetype(__line); + } + + if(uuencode) { + + sprintf(_parabuf, "begin 644 %s\n", CleanFilename(_filenameptr)); + __line = insertlinebelow(__line, _parabuf); + setlinetype(__line); + + while(1) { + char ibuf[80]; + char* iptr = ibuf; + char* optr = _parabuf; + int n = fread(ibuf, 1, 45, fp); + if(n < 45) + memset(ibuf+n, 0, 45-n); + *optr++ = uuencode_enc(n); + for(int i=0; i> 2); + *optr++ = uuencode_enc(((*iptr << 4) & 060) | ((iptr[1] >> 4) & 017)); + *optr++ = uuencode_enc(((iptr[1] << 2) & 074) | ((iptr[2] >> 6) & 03)); + *optr++ = uuencode_enc(iptr[2] & 077); + } + *optr++ = '\n'; + *optr = NUL; + __line = insertlinebelow(__line, _parabuf); + // set type to text + __line->type &= ~GLINE_ALL; + if(n <= 0) + break; + } + + __line = insertlinebelow(__line, "end\n"); + setlinetype(__line); + } + else if(base64) { + + base64_engine b64; + + sprintf(_parabuf, "Content-type: application/octet-stream; name=\"%s\"\n", CleanFilename(_filenameptr)); + __line = insertlinebelow(__line, _parabuf); + setlinetype(__line); + sprintf(_parabuf, "Content-transfer-encoding: base64\n"); + __line = insertlinebelow(__line, _parabuf); + setlinetype(__line); + + sprintf(_parabuf, "\n"); + __line = insertlinebelow(__line, _parabuf); + setlinetype(__line); + + for(;;) { + char ibuf[80]; + char* optr = _parabuf; + int n = fread(ibuf, 1, 54, fp); + optr = b64.encode(optr, ibuf, n); + *optr++ = '\n'; + *optr = NUL; + __line = insertlinebelow(__line, _parabuf); + setlinetype(__line); + if(n <= 0) + break; + } + } + else { + + int tabsz = CFG->disptabsize ? CFG->disptabsize : 1; + __extension__ char spaces[tabsz+1]; + memset(spaces, ' ', tabsz); + spaces[tabsz] = NUL; + int level = LoadCharset(AA->Xlatimport(), CFG->xlatlocalset); + char* buf = (char*) throw_malloc(EDIT_PARABUFLEN); + Line* saveline = __line->next; + __line->next = NULL; + + // Read paragraphs + while(getclip ? clipbrd.read(_parabuf, EDIT_PARABUFLEN-7) : fgets(_parabuf, EDIT_PARABUFLEN-7, fp)) { + + XlatStr(buf, _parabuf, level, CharTable); + + if(not quoteit) { + // Invalidate tearline + if(not CFG->invalidate.tearline.first.empty()) + doinvalidate(buf, CFG->invalidate.tearline.first.c_str(), CFG->invalidate.tearline.second.c_str(), true); + + // Invalidate originline + if(not CFG->invalidate.origin.first.empty()) + doinvalidate(buf, CFG->invalidate.origin.first.c_str(), CFG->invalidate.origin.second.c_str()); + + // Invalidate SEEN-BY's + if(not CFG->invalidate.seenby.first.empty()) + doinvalidate(buf, CFG->invalidate.seenby.first.c_str(), CFG->invalidate.seenby.second.c_str()); + + // Invalidate CC's + if(not CFG->invalidate.cc.first.empty()) + doinvalidate(buf, CFG->invalidate.cc.first.c_str(), CFG->invalidate.cc.second.c_str()); + + // Invalidate XC's + if(not CFG->invalidate.xc.first.empty()) + doinvalidate(buf, CFG->invalidate.xc.first.c_str(), CFG->invalidate.xc.second.c_str()); + + // Invalidate XP's + if(not CFG->invalidate.xp.first.empty()) + doinvalidate(buf, CFG->invalidate.xp.first.c_str(), CFG->invalidate.xp.second.c_str()); + } + + // Insert a quotestring if asked + if(quoteit) + strins(" > ", buf, 0); + + // Replace tabs + char *ht = buf; + while((ht = strchr(ht, '\t')) != NULL) { + int rposn = ht-buf; + int rstart = rposn%tabsz+1; + *ht = ' '; + if(tabsz > rstart) + strins(spaces+rstart, buf, rposn); + } + + // Copy the paragraph to the new line and retype it + Line* _newline = __line = insertlinebelow(__line, buf); + setlinetype(_newline); + + // If the paragraph is longer than one line + uint _wrapmargin = (_newline->type & GLINE_QUOT) ? marginquotes : margintext; + if(strlen(_newline->text) >= _wrapmargin) { + + // Wrap it + uint _tmpcol = 0; + uint _tmprow = 0; + _newline = wrapins(&_newline, &_tmpcol, &_tmprow, NO); + } + + __line = _newline; + } + + while(__line->next and __line->next->text) + __line = __line->next; + if(__line->text and __line->text[0] and (__line->text[strlen(__line->text)-1] != '\n')) { + Undo->PushItem(EDIT_UNDO_INS_CHAR|BATCH_MODE, __line, strlen(__line->text)); + strinschr(__line->text, '\n', strlen(__line->text)); + // Wrap it + uint _tmpcol = 0; + uint _tmprow = 0; + __line = wrapins(&__line, &_tmpcol, &_tmprow, NO); + } + __line->next = saveline; + + throw_free(buf); + } + + // Add import end text, if any + if(*CFG->importend or *CFG->importbegin) { + sprintf(_parabuf, "%s\n", *CFG->importend ? CFG->importend : CFG->importbegin); + strischg(_parabuf, "@file", getclip ? _filenameptr : CleanFilename(_filenameptr)); + _parabuf[margintext] = NUL; + __line = insertlinebelow(__line, _parabuf); + setlinetype(__line); + } + + throw_free(_parabuf); + + if(getclip) + clipbrd.close(); + else + fclose(fp); + } + else { + w_infof(LNG->CouldNotOpen, _filenameptr); + waitkeyt(10000); + w_info(NULL); + } + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::imptxt(char* __filename, bool imptxt) { + + GFTRK("Editimptxt"); + + msgptr->lin = findfirstline(); + editimport(currline, __filename, imptxt); + refresh(currline, row); + col = mincol; + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::ImportText() { + + GFTRK("EditImportText"); + + imptxt(NULL); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::ImportQuotebuf() { + + GFTRK("EditImportQuotebuf"); + + Path _quotebuf; + + GetCurrQuotebuf(_quotebuf); + imptxt(_quotebuf, true); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::editexport(Line* __exportline, int __endat) { + + GFTRK("Editexport"); + + update_statusline(LNG->ExportFile); + + if(edit_string(Edit__exportfilename, sizeof(Path), LNG->ExportWhatFile, H_ExportFile)) { + + // Pointer to export filename + char* _filenameptr = Edit__exportfilename; + + // Is append requested? + if(*_filenameptr == '+') + _filenameptr++; + + FILE* _fp = fsopen(_filenameptr, (*Edit__exportfilename == '+') ? "at" : "wt", CFG->sharemode); + if(_fp) { + + update_statuslinef(LNG->ExportStatus, Edit__exportfilename); + fputc('\n', _fp); + + while((__endat ? __exportline != currline : 1) and __exportline) { + fputs(__exportline->text, _fp); + if(not strchr(__exportline->text, '\n')) + fputc('\n', _fp); + __exportline = __exportline->next; + } + + fclose(_fp); + } + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::SpellCheck() { + + GFTRK("EditSpellCheck"); + + char _buf[EDIT_BUFLEN]; + char _buf2[EDIT_BUFLEN]; + + savefile(MODE_SAVE); + strcpy(_buf, EDIT->SpellChecker()); + strcpy(_buf2, AddPath(CFG->goldpath, EDIT->File())); + strchg(_buf2, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); + strischg(_buf, "@file", _buf2); + sprintf(_buf2, LNG->SpellChecker, _buf); + ShellToDos(_buf, _buf2, LGREY|_BLACK, YES); + LoadFile(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::ExportText() { + + GFTRK("EditExportText"); + + int endat = NO; + Line* exportline = Edit__pastebuf; + + if(not exportline) { + exportline = findanchor(); + if(exportline) + endat = YES; + else + exportline = findfirstline(); + } + + editexport(exportline, endat); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::DosShell() { + + GFTRK("EditDosShell"); + + ShellToDos(getenv(GOLD_SHELL_ENV), LNG->DOS_Shell, LGREY|_BLACK, YES); + cursoron(); + cursoroff(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::dispins() { + + GFTRK("Editdispins"); + + if(insert) + HeaderView->window.prints(5, MAXCOL-6, C_HEADT, LNG->Ins); + else { + vchar _lbuf[6]; + for(int c = 0; c < 5; c++) + _lbuf[c] = _box_table(W_BHEAD,1); + _lbuf[5] = NUL; + HeaderView->window.printvs(5, MAXCOL-6, C_HEADB|ACSET, _lbuf); + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::ToggleInsert() { + + GFTRK("EditToggleInsert"); + + insert = not insert; + dispins(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::Header() { + + GFTRK("EditHeader"); + + windowclose(); + EditHeaderinfo(msgmode, *HeaderView); + windowopen(); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::Abort() { + + GFTRK("EditAbort"); + + cursoroff(); + GMenuDropmsg MenuDropmsg; + if(MenuDropmsg.Run()) { + done = MODE_QUIT; + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::AskExit() { + + GFTRK("EditAskExit"); + + cursoroff(); + GMenuQuit MenuQuit; + gkbd.quitall = MenuQuit.Run(); + if(gkbd.quitall) { + GMenuDropmsg MenuDropmsg; + if(MenuDropmsg.Run()) + done = MODE_QUIT; + else + done = MODE_SAVE; + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void IEclass::QuitNow() { + + GFTRK("EditQuitNow"); + + quitnow = CFG->switches.get(timeoutsavemsg) ? NO : YES; + done = CFG->switches.get(timeoutsavemsg) ? MODE_SAVE : MODE_QUIT; + gkbd.quitall = YES; + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +int EditMsg(int __mode, uint* __position, GMsg* __msg) { + + IEclass Editor(0, MAXCOL-1, MINROW, MAXROW-2, 5); + return Editor.Start(__mode, __position, __msg); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/geedit3.cpp b/golded3/geedit3.cpp new file mode 100644 index 0000000..30edb73 --- /dev/null +++ b/golded3/geedit3.cpp @@ -0,0 +1,110 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// OS/2 clipboard to/from edit paste buffer. +// ------------------------------------------------------------------ + +#include +#include +#include + +void IEclass::Clip2Buf() { + + gclipbrd clipbrd; + + if(not clipbrd.openread()) + return; + + int tabsz = CFG->disptabsize ? CFG->disptabsize : 1; + __extension__ char spaces[tabsz+1]; + memset(spaces, ' ', tabsz); + spaces[tabsz] = NUL; + + // Allocate paragraph read buffer + char *buf = (char *)throw_malloc(EDIT_PARABUFLEN); + Line *__line = NULL; + + Undo->undo_enabled = NO; + + // Read paragraphs + while(clipbrd.read(buf, EDIT_PARABUFLEN-6)) { + + // Replace tabs + char *ht = buf; + while((ht = strchr(ht, '\t')) != NULL) { + int rposn = ht-buf; + int rstart = rposn%tabsz+1; + *ht = ' '; + if(tabsz > rstart) + strins(spaces+rstart, buf, rposn); + } + + // Copy the paragraph to the new line and retype it + Line* _newline = __line = insertlinebelow(__line, buf); + if(Edit__pastebuf == NULL) + Edit__pastebuf = _newline; + setlinetype(_newline); + + // If the paragraph is longer than one line + uint _wrapmargin = (_newline->type & GLINE_QUOT) ? marginquotes : margintext; + if(strlen(_newline->text) >= _wrapmargin) { + + // Wrap it + uint _tmpcol = 0; + uint _tmprow = 0; + _newline = wrapins(&_newline, &_tmpcol, &_tmprow, NO); + } + + __line = _newline; + } + Undo->undo_enabled = YES; + throw_free(buf); + clipbrd.close(); +} + + +void IEclass::Buf2Clip() { + + gclipbrd clipbrd; + int buflen = 0; + Line *_bufline; + + for(_bufline = Edit__pastebuf; _bufline; _bufline = _bufline->next) + buflen += strlen(_bufline->text) + 1; + + char *clipdata = (char *)throw_malloc(buflen); + + char *curptr = clipdata; + *curptr = NUL; + for(_bufline = Edit__pastebuf; _bufline; _bufline = _bufline->next) { + strcpy(curptr, _bufline->text); + if(*curptr) { + curptr += strlen(curptr) - 1; + if(*curptr == '\n') strcpy(curptr, "\r\n"); + } + curptr += strlen(curptr); + } + + clipbrd.writeclipbrd(clipdata); + throw_free(clipdata); +} diff --git a/golded3/gefile.cpp b/golded3/gefile.cpp new file mode 100644 index 0000000..0261360 --- /dev/null +++ b/golded3/gefile.cpp @@ -0,0 +1,1002 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// File handling. +// ------------------------------------------------------------------ + +#include +#include +#include +#include + + +// ------------------------------------------------------------------ + +char CFG__frqinvfilechars[40] = { "\"()+,.\\/:;<=>[]| \xff@" }; +char CFG__frqskipwordchars[40] = { "0123456789-[" }; + +inline char* invalidfilechar(char ch) { return strchr(CFG__frqinvfilechars, ch); } + + +// ------------------------------------------------------------------ + +int fspecs = 0; +int specfiles = 0; +FileSpec* fspec = NULL; + +static FFblk* fblk; +static int selfiles; +static int totfiles; +static long selbytes; +static long totbytes; + + +// ------------------------------------------------------------------ + +static int cmp_ffb(const FFblk* a, const FFblk* b) { + + return stricmp(a->name, b->name); +} + + +// ------------------------------------------------------------------ + +static int cmp_ffbs(const FFblk* a, const FFblk* b) { + + int cmp; + + if((cmp = b->selected - a->selected) != 0) // Selected first + return cmp; + + return stricmp(a->name, b->name); +} + +class gfileselect : public gwinpick { + + gwindow window; + GMsg* msg; + + void open(); + void close(); + void do_delayed(); + void print_line(uint idx, uint pos, bool isbar); + void scroll(int where); + bool handle_key(); + +public: + + void run(GMsg* cmsg); +}; + + +// ------------------------------------------------------------------ + +void gfileselect::open() { + + display_page(); + +} + + +// ------------------------------------------------------------------ + +void gfileselect::close() { + +} + + +// ------------------------------------------------------------------ + +void gfileselect::scroll(int where) { + + wscrollbox(0, 0, maximum_position, xlen-1, 1, where); +} + + +// ------------------------------------------------------------------ + +void gfileselect::do_delayed() { + + char buf[200]; + char tmp[80]; + + sprintf(buf, "%s %10s", LNG->SelectedFiles, longdotstr(tmp, selfiles)); + wprints(ylen-4, MAXCOL-34, wattr, buf); + sprintf(buf, "%s %10s", LNG->SelectedBytes, longdotstr(tmp, selbytes)); + wprints(ylen-3, MAXCOL-34, wattr, buf); + + sprintf(buf, "%s %10s", LNG->TotalFiles, longdotstr(tmp, totfiles)); + wprints(ylen-2, MAXCOL-34, wattr, buf); + sprintf(buf, "%s %10s", LNG->TotalBytes, longdotstr(tmp, totbytes)); + wprints(ylen-1, MAXCOL-34, wattr, buf); + + if(CFG->switches.get(filelistpagebar)) + wscrollbar(W_VERT, maximum_index+1, maximum_index, index); + +} + + +// ------------------------------------------------------------------ + +void gfileselect::print_line(uint idx, uint pos, bool isbar) { + + char buf[200]; + + FFblk& fb = fblk[idx]; + + sprintf(buf, "%c%-*.*s %8lu %2d-%02d-%02d %2d:%02d ", + fb.selected ? MMRK_MARK : ' ', + MAXCOL-62, (int)MAXCOL-62, + fb.name, + fb.size, + fb.day, + fb.month, + fb.year % 100, + fb.hour, + fb.minute + ); + + wprints(pos, 0, isbar ? sattr : wattr, buf); + wprintc(pos, 0, isbar ? sattr : (*buf == ' ' ? wattr : hattr), *buf); + +} + + +// ------------------------------------------------------------------ + +bool gfileselect::handle_key() { + + gkey kk; + uint n; + + if(key < KK_Commands) { + key = key_tolower(key); + kk = SearchKey(key, FileKey, FileKeys); + if(kk) + key = kk; + } + + switch(key) { + case KK_FileUnMarkAll: + selfiles = 0; + selbytes = 0; + for(n=0; n<=maximum_index; n++) + fblk[n].selected = false; + + update(); + + break; + + case KK_FileMarkAll: + + selfiles = totfiles; + selbytes = totbytes; + + for(n=0; n<=maximum_index; n++) + fblk[n].selected = true; + + update(); + + break; + + case KK_FileAskExit: + { + GMenuQuit MenuQuit; + if(not MenuQuit.Run()) + break; + } + ////////////// Drop through + + case KK_FileQuitNow: + gkbd.quitall = true; + ////////////// Drop through + + case KK_FileAbort: + + for(n=0; n<=maximum_index; n++) + fblk[n].selected = false; + + selfiles = 0; + selbytes = 0; + + aborted = true; + + return false; + + case KK_FileSelect: + + if(not selfiles) { // If no files selected, select cursor file + fblk[index].selected = true; + selbytes += fblk[index].size; + selfiles++; + } + + return false; + + case KK_FileToggleMark: + key = fblk[index].selected ? KK_FileUnMark : KK_FileMark; + + /////////// Drop through + case KK_FileUnMark: + case KK_FileMark: + + if(key == KK_FileMark) { + if(not fblk[index].selected) { + fblk[index].selected = true; + selbytes += fblk[index].size; + selfiles++; + } + } + else { + if(fblk[index].selected) { + fblk[index].selected = false; + selbytes -= fblk[index].size; + selfiles--; + } + } + precursor(); display_bar(); cursor_down(); + break; + case KK_FileGotoPrev: precursor(); cursor_up(); break; + case KK_FileGotoNext: precursor(); cursor_down(); break; + case KK_FileGotoFirst: precursor(); cursor_first(); break; + case KK_FileGotoLast: precursor(); cursor_last(); break; + + case KK_FileDosShell: + DosShell(); + break; + + case Key_Tick: + CheckTick(KK_FileQuitNow); + break; + + case KK_FileUndefine: + break; + + default: + if(not PlayMacro(key, KT_F)) + SayBibi(); + } + + return true; +} + + +// ------------------------------------------------------------------ + +void gfileselect::run(GMsg* cmsg) { + + ypos = 6; // Window Starting Row + xpos = 0; // Window Starting Column + ylen = MAXROW - 9; // Window Height + xlen = MAXCOL - 36; // Window Width + btype = W_BMENU; // Window Border Type + battr = C_MENUB; // Window Border Color + wattr = C_MENUW; // Window Color + tattr = C_MENUW; // Window Title Color + sattr = C_MENUS; // Window Selection Bar Color + hattr = C_MENUQ; // Window Highlight Color + sbattr = C_MENUB; // Window Scrollbar Color + title = " title "; // Window Title + helpcat = H_FileSelect; // Window Help Category + msg = cmsg; + + maximum_index = totfiles - 1; // List Entries - 1 + minimum_index = 0; // Minimum index in the list + maximum_position = MinV(ylen-1,(uint) totfiles);// Display Pos + index = 0; // List Index + position = 0; // Display Pos + aborted = false; // True if aborted + listwrap = CFG->switches.get(displistwrap); // True if wrap-around is supported + + run_picker(); + +}; + + + +// ------------------------------------------------------------------ + +void FileSelect(GMsg* msg, char* title, FileSpec* fspec) { + + gfileselect* p = new gfileselect; + throw_new(p); + + char buf[256]; + Path fbuf; + uint MIN_POS=0, MAX_POS=MIN_POS+MAXROW-10; + bool done, winop = false; + + selfiles = totfiles = 0; + selbytes = totbytes = 0; + + strcpy(fbuf, fspec->path); + MapPath(fbuf); + + Path fullpath; + extractdirname(fullpath, fbuf); + const char* wildlistname = (isslash(fbuf[strlen(fbuf)-1]) or is_dir(fbuf)) ? "*" : CleanFilename(fbuf); + gposixdir f(fullpath); + const gdirentry *de; + for(done = false; (de = f.nextentry(wildlistname)) != NULL and not done; ) + if(de->is_file()) + done = true; + + if((strpbrk(fbuf, "*?")) or done) { + winop = true; + ChgAttrs(NO, msg); + vcurhide(); + wopen_(6,0, MAX_POS+3, MAXCOL, W_BMENU, C_MENUB, C_MENUW, C_MENUPB); + + wvline(0, MAXCOL-36, MAX_POS+1, W_BMENU, C_MENUB); + whline(MAX_POS-4, MAXCOL-36, 36, W_BMENU, C_MENUB); + + sprintf(buf, " %s ", strtrim(fbuf)); + wmessage(buf, TP_BORD, 1, C_MENUT); + wmessage(title, TP_BORD, MAXCOL-34, C_MENUT); + + update_statusline(LNG->SelectFiles); + + wprints(MAX_POS/2, 0, C_MENUW, LNG->ScanningDirectory); + } + + fblk = NULL; + + f.rewind(); + while((de = f.nextentry(wildlistname)) != NULL) { + if(not de->is_file()) + continue; + FFblk* fb; + fblk = (FFblk*)throw_realloc(fblk, (totfiles+1)*sizeof(FFblk)); + fb = fblk + totfiles; + strcpy(fb->name, de->name.c_str()); + fb->selected = false; + FFTime ftm; + dword _ftm = GetFiletime(fb->name); + memcpy(&ftm, &_ftm, sizeof(FFTime)); + fb->year = ftm.ft_year + 1980; + fb->month = ftm.ft_month; + fb->day = ftm.ft_day; + fb->hour = ftm.ft_hour; + fb->minute = ftm.ft_min; + fb->second = ftm.ft_tsec * 2; + fb->size = de->stat_info.st_size; + totbytes += fb->size; + totfiles++; + } + + if(totfiles) { + if(totfiles > 1) { + qsort(fblk, totfiles, sizeof(FFblk), (StdCmpCP)cmp_ffb); + p->run(msg); + } + else { + selfiles = 1; + fblk[0].selected = YES; + } + + if(p->aborted or selfiles == 0) { + fspec->fblk = NULL; + fspec->files = 0; + throw_release(fblk); + } + else { + // Realloc to include only the selected files + qsort(fblk, totfiles, sizeof(FFblk), (StdCmpCP)cmp_ffbs); + fspec->fblk = fblk = (FFblk*)throw_realloc(fblk, (selfiles+1)*sizeof(FFblk)); + AddBackslash(strcpy(fspec->path, f.fullpath())); + fspec->files = selfiles; + fblk = NULL; + } + } + else { + wprints(MAX_POS/2, 0, C_MENUW, LNG->NoFilesFound); + update_statusline(LNG->FilesPressKey); + throw_release(fblk); + waitkeyt(10000); + } + + if(winop) { + wclose(); + ChgAttrs(YES, msg); + vcurshow(); + } + + delete p; +} + + +// ------------------------------------------------------------------ + +void CreateFileAddr(GMsg* msg) { + + // Create message + char* _txt; + if(msg->attr.att()) + _txt = LNG->AutoAttachMsg; + else if(msg->attr.frq()) + _txt = LNG->AutoRequestMsg; + else if(msg->attr.urq()) + _txt = LNG->AutoUpdreqMsg; + else + _txt = LNG->EmptyMsg; + msg->txt = (char*)throw_realloc(msg->txt, strlen(_txt)+256); + strcpy(msg->txt, _txt); + TokenXlat(MODE_NEW, msg->txt, msg, msg, CurrArea); +} + + +// ------------------------------------------------------------------ + +void WriteFMsgs(int msgsdone, GMsg* msg, Attr o_attr, int modex, int mode, char* buf) { + + if(msgsdone) { + modex = GMSG_NEW; + AA->NewMsgno(msg); + + throw_release(msg->txt); + msg->attr = o_attr; // copy attributes from original + CreateFileAddr(msg); + msg->TextToLines(CFG->dispmargin); + if(AA->isecho()) + DoTearorig(mode, msg); + } + + DoKludges(mode, msg); + + strtrim(strcpy(msg->re, buf)); + HeaderView->Use(AA, msg); + HeaderView->Paint(); + msg->LinesToText(); + AA->SaveMsg(modex, msg); +} + + +// ------------------------------------------------------------------ + +void CreateFileMsgs(int mode, GMsg* msg) { + + char* ptr; + Attr o_attr; + int m, n, x; + int modex, msgsdone=0; + ISub buf, subj; + + char* LNG_File = NULL; + char* LNG_Fileing = NULL; + + if(msg->attr.att()) { + LNG_File = LNG->File_Attach; + LNG_Fileing = LNG->FileAttaching; + } + else if(msg->attr.frq()) { + LNG_File = LNG->File_Request; + LNG_Fileing = LNG->FileRequesting; + } + else if(msg->attr.urq()) { + LNG_File = LNG->File_Updreq; + LNG_Fileing = LNG->FileUpdreqing; + } + + *buf = NUL; + *subj = NUL; + + o_attr = msg->attr; + + if(specfiles > 1) + w_progress(MODE_NEW, C_INFOW, 1, specfiles, LNG_File); + + // Do ZoneGating + if(CFG->zonegating and (msg->dest.zone != msg->orig.zone)) { + GMenuZonegate MenuZonegate; + if(CFG->zonegating == YES or MenuZonegate.Run()) + ZonegateIt(msg->odest, msg->orig, msg->dest); + } + + if(msg->odest.net == 0) + msg->odest = msg->dest; + + *buf = NUL; + ptr = throw_strdup(msg->txt); // Keep a copy of the original + modex = (mode == MODE_CHANGE) ? GMSG_UPDATE : GMSG_NEW; + + for(n=0,x=0; x 1) { + w_progress(MODE_UPDATE, C_INFOW, n+1, specfiles, LNG_File); + update_statuslinef(LNG_Fileing, n+1, specfiles, + msg->dest.zone, msg->dest.net, msg->dest.node, msg->dest.point + ); + } + sprintf(subj, "%s%s%s%s%s ", fspec[x].delsent ? "^" : "", fspec[x].path, fspec[x].fblk ? (fspec[x].fblk[m].name ? fspec[x].fblk[m].name : "") : "", *fspec[x].password ? " " : "", fspec[x].password); + strupr(subj); + + if((strlen(buf) + strlen(subj)) > 71) { + + WriteFMsgs(msgsdone, msg, o_attr, modex, mode, buf); + + msgsdone++; + strcpy(buf, subj); + } + else { + strcat(buf, subj); + } + } + } + + if(not strblank(buf)) + WriteFMsgs(msgsdone, msg, o_attr, modex, mode, buf); + + throw_release(msg->txt); + msg->txt = ptr; + msg->TextToLines(CFG->dispmargin); + + if(specfiles > 1) + w_progress(MODE_QUIT, 0, 0, 0, NULL); +} + + +// ------------------------------------------------------------------ + +static int FreqCmp(const char** a, const char** b) { + + return stricmp(*a, *b); +} + + +// ------------------------------------------------------------------ + +static int frqchkdesc(char* desc) { + + char* ptr = desc; + + if(*desc == NUL) + strcpy(desc, " "); + else { + while(*ptr) { + if(isalnum(*ptr)) + break; + ptr++; + } + if(*ptr == NUL) { + *desc = NUL; + return true; + } + } + ptr = desc + strlen(desc) - 1; + while(((*ptr < '!') or (*ptr > '\x7F')) and (ptr>desc)) + *ptr-- = NUL; + + return false; +} + + +// ------------------------------------------------------------------ + +static int frqgetfile(char* file, char* desc, char* filesize, char* txt) { + + char* ptr = txt; + + // Scan filename for first invalid char (.extension) + while(*ptr and not invalidfilechar(*ptr)) + ptr++; + + // General file extension finder + if(*ptr++ == '.') { + if(not invalidfilechar(*ptr) and ((ptr - txt) > 1)) { + + // Find end of extension + while(*ptr and (*ptr != ' ')) + ptr++; + + // Strip invalid chars from the end of the extension + while(invalidfilechar(*(ptr-1))) + ptr--; + + // Copy the filename + strxcpy(file, txt, (uint)(ptr-txt)+1); + + // Get description + if(desc) { + if(*ptr) { + if(not isspace(*ptr)) + ptr = strskip_txt(ptr); + ptr = strskip_wht(ptr); + + bool skipped = false; + while(strchr(CFG__frqskipwordchars, *ptr) and *ptr) { + if(not *filesize) { + // is a file-size given? + char* p = ptr; + while(strchr(".,0123456789bBkKmMgG", *p)) + p++; + + // Check for the following cases, as they're not valid + // 01/01/98 or 01/01/1998 or 1998/01/01 + // 01-01-98 or 01-01-1998 or 1998-01-01 + // 01.01.98 or 01.01.1998 or 1998.01.01 + if(p-ptr>1 and not strchr("-/.", *p)) { + p = strxcpy(filesize, ptr, MinV((int) (p-ptr+1), 9)); + if(strlen(p)>=6 and p[2] == p[5] and strchr("-/.", p[2])) + *filesize = NUL; + } + } + ptr = strskip_wht(strskip_txt(ptr)); + skipped = true; + } + if(not *ptr and skipped) + strcpy(desc, " "); + else + strcpy(desc, ptr); + } + + return frqchkdesc(desc); + } + } + } + + return false; +} + + +// ------------------------------------------------------------------ + +void FileRequest(GMsg* msg) { + + GFTRK("FileRequest"); + + int oldtopline = reader_topline; + + if(AA->Msgn.Count() and msg->line and msg->lines) { + + char buf[256]; + char* ptr; + char* ptr1; + char* ptr2; + char* txtptr; + char** freqfile = NULL; + int gotticket = false; + int getnextdesc = false; + Line** lin = msg->line; + char file[GMAXPATH], desc[200], filesize[10]; + int freqfiles = 0; + bool esc = true; + int n; + byte numlines = 0; + + *desc = *file = *filesize = NUL; + + w_info(LNG->Wait); + + // Scan the current msg for file announcements + int tline = reader_topline; + if(CFG->frqoptions & FREQ_FROMTOP) + tline = 0; + for(n=tline; nlines; n++) { + + // Don't look in control info for files + if(lin[n]->type & (GLINE_KLUDGE|GLINE_TEAR|GLINE_ORIG)) + continue; + + ptr = txtptr = lin[n]->text; + + // Skip past whitespace and highbit junk + while(((*ptr < '!') or (*ptr > '\x7F')) and *ptr) + ptr++; + + // Get description if Ticket was detected in the previous line + if(gotticket) { + strxcpy(desc, strskip_wht(strskip_txt(ptr)), sizeof(desc)); + if(*desc == NUL) + strcpy(desc, " "); + gotticket = false; + } + + // Get description from file of previous line + if(getnextdesc) { + strxcpy(desc, ptr, sizeof(desc)); + getnextdesc = frqchkdesc(desc); + } + + // Get filename from typical announcement formats + if(not *file and (strnieql(ptr, "File", 4) or strnieql(ptr, "Name", 4))) { + ptr1 = strskip_txt(ptr); + ptr2 = strskip_wht(ptr1); + if((*(ptr1-1) == ':') or (*ptr2 == ':')) { + if(*ptr2 == ':') + ptr1 = strskip_wht(ptr2+1); + else + ptr1 = ptr2; + ptr2 = strskip_txt(ptr1); + *ptr2 = NUL; + frqgetfile(file, desc, filesize, ptr1); + *desc = NUL; // Description never comes before filename + continue; + } + } + + // Get description from typical announcement formats + if(not *desc and (strnieql(ptr, "Desc", 4) or strnieql(ptr, "Note", 4))) { + ptr1 = strskip_txt(ptr); + ptr2 = strskip_wht(ptr1); + if((*(ptr1-1) == ':') or (*ptr2 == ':')) { + if(*ptr2 == ':') + ptr1 = strskip_wht(ptr2+1); + else + ptr1 = ptr2; + strxcpy(desc, ptr1, sizeof(desc)); + getnextdesc = frqchkdesc(desc); + } + } + + // Check for announcement format "Area:" and skip it if found + if(strnieql(ptr, "Area", 4)) { + ptr1 = strskip_txt(ptr); + ptr2 = strskip_wht(ptr1); + if((*(ptr1-1) == ':') or (*ptr2 == ':')) { + continue; + } + } + + // Get filename from Ticket announcement if detected + if(not *file and (strlen(txtptr) >= 54)) { + if(strneql(txtptr+45, " Origin: ", 9)) { + if(/*(*/ strstr(txtptr+25, " Bytes) ")) { + if(txtptr[16] == '/' and txtptr[19] == '/' and txtptr[24] == '(' /*)*/) { + ptr1 = strskip_wht(txtptr); + ptr2 = strskip_txt(ptr1); + *ptr2 = NUL; + frqgetfile(file, desc, filesize, ptr1); + *desc = NUL; // Description never comes before filename + gotticket = true; + continue; + } + } + } + } + + // Handle blank lines + if(strblank(ptr)) { + if(*file) + strcpy(desc, " "); + if(*desc and strblank(file)) + *desc = NUL; + } + + // Get file based on extension (general algorithm) + if(not *file) { + if((ptr-txtptr) <= 4) { + getnextdesc = frqgetfile(file, desc, filesize, ptr); + if((ptr2 = strrchr(file,'.'))!=NULL and strlen(ptr2)>4) { + *file = *desc = *filesize = NUL; + getnextdesc = false; + } + } + } + + // Get file based on FRQEXT list + if(not *file) { + int gotone = false; + ptr2 = strchr(ptr, '.'); + while(ptr2) { + gstrarray::iterator e; + for(e = CFG->frqext.begin(); e != CFG->frqext.end(); e++) { + if(strnicmpw(e->c_str(), ptr2, MinV(e->length(), strlen(ptr2))) == 0) { + // Find beginning of filename + char* ptr3 = ptr2-1; + while((ptr3 > ptr) and not invalidfilechar(*ptr3)) + ptr3--; + if(invalidfilechar(*ptr3)) + ptr3++; + getnextdesc = frqgetfile(file, desc, filesize, ptr3); + if(*file) + gotone = true; + break; + } + } + if(gotone) + break; + ptr2 = strchr(ptr2+1, '.'); + } + } + + // Do we have a complete announcement? + if(*file and *desc) { + + // Yes, so add it to the list + freqfile = (char**)throw_realloc(freqfile, (freqfiles+3)*sizeof(char*)); + sprintf(buf, " %-12s %8s %s", file, filesize, desc); + strsetsz(buf, 76); + freqfile[freqfiles] = throw_strdup(buf); + *desc = *file = *filesize = NUL; + numlines = 0; + freqfiles++; + } + + // Maybe there was a false match, so re-initialize if + // more than 3 lines are checked. + if(*file and not *desc) { + if(numlines++ > 2) { + *desc = *file = *filesize = NUL; + numlines = 0; + } + } + } + + // Add the filelist + if(not (CFG->frqoptions & FREQ_NOFILES)) { + strcpy(file, "FILES"); + sprintf(desc, LNG->FilelistFrom, msg->By()); + freqfile = (char**)throw_realloc(freqfile, (freqfiles+3)*sizeof(char*)); + sprintf(buf, " %-12.12s %-52.52s ", file, desc); + freqfile[freqfiles] = throw_strdup(buf); + *desc = *file = NUL; + freqfiles++; + } + + w_info(NULL); + + // Let user select the file(s) to be requested + if(freqfile) { + + // NULL terminate list + freqfile[freqfiles] = NULL; + + // Sort list if requested + if(CFG->frqoptions & FREQ_SORT) + qsort(freqfile, freqfiles, sizeof(char*), (StdCmpCP)FreqCmp); + + // Run the picker + int items = MinV(freqfiles, (MAXROW-10)); + set_title(LNG->FreqMenuTitle, TCENTER, C_ASKT); + update_statusline(LNG->FreqStat); + whelppcat(H_FileRequest); + wpickstr_tag = '+'; + int crsr = wpickstr(6, 0, 6+items+1, -1, W_BASK, C_ASKB, C_ASKW, C_ASKS, freqfile, 0, title_shadow); + wpickstr_tag = false; + int freqs = 0; + esc = ((crsr == -1) and (gwin.werrno == W_ESCPRESS)); + whelpop(); + + if(not esc) { + + // Open a FILES.BBS in the INBOUNDPATH + const char* fbfn = AddPath(CFG->inboundpath, "files.bbs"); + int fh = sopen(fbfn, O_RDWR|O_CREAT|O_APPEND|O_TEXT, CFG->sharemode, S_STDRW); + if(fh == -1) { + w_infof(LNG->CouldNotOpen, fbfn); + waitkeyt(10000); + w_info(NULL); + } + + // Handle picked files + msg->re[0] = NUL; + for(n=0; nattr.frq1(); + ptr = freqfile[n]+1; // 01234567890123456 + ptr2 = strskip_txt(ptr); + *ptr2++ = NUL; + ptr2 = strskip_wht(ptr2); + if((strlen(msg->re) + strlen(ptr)) < sizeof(ISub)) { // We can only fill one subject line in this version... + strcat(msg->re, ptr); + strcat(msg->re, " "); + if(fh != -1) { + sprintf(buf, "%-12s %s\n", ptr, ptr2); + write(fh, buf, strlen(buf)); + } + freqs++; + } + } + } + if(freqs == 0) { + // AARRRGGGHH!! More bloody duplicate code :-(( + msg->attr.frq1(); + ptr = freqfile[crsr]+1; // 01234567890123456 + ptr2 = strskip_txt(ptr); + *ptr2++ = NUL; + ptr2 = strskip_wht(ptr2); + if((strlen(msg->re) + strlen(ptr)) < sizeof(ISub)) { // We can only fill one subject line in this version... + strcat(msg->re, ptr); + strcat(msg->re, " "); + if(fh != -1) { + sprintf(buf, "%-12s %s\n", ptr, ptr2); + write(fh, buf, strlen(buf)); + } + freqs++; + } + } + strtrim(msg->re); + + // Close the FILES.BBS + if(fh != -1) + close(fh); + } + } + else { + w_info(LNG->FreqInfoNoFiles); + gkey key = waitkeyt(10000); + w_info(NULL); + if(key == Key_Ent) { + msg->attr.frq1(); + esc = false; + } + } + + if(not esc) { + + // Pick area and put the msg in it + int destarea = CurrArea; + reader_topline = 0; + AA->attr().hex0(); + if(*AA->Areafreqto()) { + for(n=0; (uint) nechoid(), AA->Areafreqto())) { + destarea = AL[n]->areaid(); + break; + } + } + } + if(not AA->Areafreqdirect()) + destarea = AreaPick(LNG->FreqArea, 6, &destarea); + if(destarea != -1) { + AL.SetActiveAreaId(destarea); + if(CurrArea != OrigArea) + AA->Open(); + if(CFG->frqoptions & FREQ_FAST) + savedirect = true; + vector::iterator fnm; + for(fnm = CFG->frqnodemap.begin(); fnm != CFG->frqnodemap.end(); fnm++) { + if(fnm->from.equals(msg->orig)) { + msg->orig = fnm->to; + break; + } + } + ReplyMsg(); + savedirect = false; + if(CurrArea != OrigArea) { + AA->Close(); + AL.SetActiveAreaId(OrigArea); + } + } + } + + if(freqfile) { + for(n=0; ndispmargin-(int)CFG->switches.get(disppagebar)); + reader_topline = oldtopline; + reader_keyok = YES; + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gefind.cpp b/golded3/gefind.cpp new file mode 100644 index 0000000..aa8bf55 --- /dev/null +++ b/golded3/gefind.cpp @@ -0,0 +1,173 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Search functions. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +void SearchExit() { } + + +// ------------------------------------------------------------------ + +void FindAll(GMsg* msg, int& topline, int& keyok) { + + if(AA->Msgn.Count()) { + topline = 0; + AA->attr().hex0(); + strcpy(CFG->searchfor, AA->Searchfor()); + if(edit_string(CFG->searchfor, sizeof(INam), LNG->HeaderText, H_FindString)) { + AA->SetSearchfor(CFG->searchfor); + if(FindString(msg, AA->Searchfor(), GFIND_HDRTXT)) + keyok = true; + } + } +} + + +// ------------------------------------------------------------------ + +void FindHdr(GMsg* msg, int& topline, int& keyok) { + + if(AA->Msgn.Count()) { + topline = 0; + AA->attr().hex0(); + strcpy(CFG->searchfor, AA->Searchfor()); + if(edit_string(CFG->searchfor, sizeof(INam), LNG->HeaderOnly, H_FindString)) { + AA->SetSearchfor(CFG->searchfor); + if(FindString(msg, AA->Searchfor(), GFIND_HDR)) + keyok = true; + } + } +} + + +// ------------------------------------------------------------------ + +bool SearchHighlight(const Line*, int, int, int) { + + return false; +} + + +// ------------------------------------------------------------------ + +bool FindString(GMsg* msg, const char* prompt, int what) { + + GFTRK("FindString"); + + static ulong lastfound = 0; + bool result = false; + bool breakloop = true; + + golded_search_manager srchmgr; + srchmgr.prepare_from_string(prompt, what); + + uint last = AA->lastread(); + + lastfound = AA->Msgn.CvtReln(AA->lastread()); + w_progress(MODE_NEW, C_INFOW, AA->lastread(), AA->Msgn.Count(), LNG->AdvancedSearch); + + ulong tmpmsgno; + + int margin = CFG->dispmargin-(int)CFG->switches.get(disppagebar); + + do { + + update_statuslinef(LNG->ReadingMsg, AA->lastread(), AA->Msgn.Count()); + w_progress(MODE_UPDATE, C_INFOW, AA->lastread(), AA->Msgn.Count(), LNG->AdvancedSearch); + + if(AA->LoadMsg(msg, AA->Msgn.CvtReln(AA->lastread()), margin)) { + + bool success; + // If hit, search again current mail without shortcircuit evaluation + success = srchmgr.search(msg, false, true); + if(success) + srchmgr.search(msg, false, false); + + if((srchmgr.reverse ? not success : success) and (lastfound != msg->msgno)) { + bool istwitto, istwitsubj; + if(MsgIsTwit(msg, istwitto, istwitsubj) != TWIT_SKIP) { + HandleGEvent(EVTT_SEARCHSUCCESS); + lastfound = msg->msgno; + AA->set_lastread(AA->Msgn.ToReln(msg->msgno)); + result = true; + breakloop = false; + break; + } + } + } + + if(kbxhit() and (kbxget() == Key_Esc)) { + breakloop = false; + break; + } + + tmpmsgno = msg->msgno; + switch(srchmgr.direction) { + case DIR_PREV: + if(AA->Msgn.ToReln(msg->msgno) > 1) + msg->msgno = AA->Msgn.CvtReln(AA->Msgn.ToReln(msg->msgno)-1); + else + msg->msgno = 0; + break; + case DIR_NEXT: + if(AA->Msgn.ToReln(msg->msgno) < AA->Msgn.Count()) + msg->msgno = AA->Msgn.CvtReln(AA->Msgn.ToReln(msg->msgno)+1); + else + msg->msgno = 0; + break; + } + if(msg->msgno != 0) + AA->set_lastread(AA->Msgn.ToReln(msg->msgno)); + + } while((msg->msgno != 0) and (msg->msgno != tmpmsgno)); + + if(not result) { + HandleGEvent(EVTT_SEARCHFAILED); + AA->set_lastread(last); + } + + w_progress(MODE_QUIT, 0, 0, 0, NULL); + + if(breakloop) + HandleGEvent(EVTT_BREAKLOOP); + + if(not result) { + w_info(LNG->NoMoreMatches); + waitkeyt(5000); + w_info(NULL); + } + + GFTRK(NULL); + return result; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gefn.h b/golded3/gefn.h new file mode 100644 index 0000000..f1163e4 --- /dev/null +++ b/golded3/gefn.h @@ -0,0 +1,33 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Standart filenames. +// ------------------------------------------------------------------ + + +#ifndef __GEFN_H__ +#define __GEFN_H__ + + +#endif + diff --git a/golded3/geglob.cpp b/golded3/geglob.cpp new file mode 100644 index 0000000..671e59d --- /dev/null +++ b/golded3/geglob.cpp @@ -0,0 +1,290 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Global data. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ +// Various global data + +glog LOG; + +gareafile* AFILE = NULL; +CfgGed* CFG = NULL; +LangGed* LNG = NULL; +NodeIxl* NODE = NULL; +Qwk* QWK = NULL; +GoldedCfgEdit* EDIT = NULL; + +uint locpost=0, netpost=0, echopost=0; + +Subj information = ""; + +Area* AA = NULL; + +char m_title[80]; // Menu title string +int m_titlepos; // Menu title position +int m_titleattr; // Menu title color + +char* tconv; + +int AreaKeys = 0; +int ReadKeys = 0; +int ListKeys = 0; +int NodeKeys = 0; +int EditKeys = 0; +int FileKeys = 0; +list::iterator AreaKey, ReadKey, ListKey, NodeKey, EditKey, FileKey; + +int inforow = 18; + +char goldmark = ' '; + +int startecho = -1; +Echo stecho; + +int fieldupd = 2; // State of field mode in winpdef() + +int CurrArea = 0; +int OrigArea = 0; + +Esc* MNETable = NULL; +Esc* I51Table = NULL; +Esc* CompTable = NULL; +Chs* CharTable = NULL; +EscTab* CompTP = NULL; +EscTab* I51TP = NULL; +EscTab* MNETP = NULL; +ChsTab* ChsTP = NULL; + +bool quiet = true; +bool ignore = false; +int cfgerrors = 0; +bool veryverbose = false; +bool shellvid = true; +word* oldscreen = NULL; + +bool disablesound = false; + +int _in_editor = NO; +int _in_msglist = NO; +int savedirect = NO; + +void(*SIGINT_OldHandler)(void) = NULL; + +int arealistnumgrps = false; + +int startupscan_success = false; + + +// ------------------------------------------------------------------ +// 0 1 2 3 4 5 6 7 8 9 10 11 + +Win gold_color1[16] = { + {5, { 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0}, 2}, // Back 0 + {5, { 31, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, 1}, // Stat 1 + {0, { 15, 14, 14, 7, 12, 7, 7, 9, 7, 7, 7, 14}, 0}, // Brag 2 + {0, { 7, 9, 14, 31, 15, 7, 7, 7, 7, 7, 7, 9}, 0}, // Area 3 + {0, { 7, 7, 15, 14, 113, 8, 15, 79, 15, 15, 8, 7}, 5}, // Read 4 + {0, { 7, 9, 14, 7, 15, 7, 15, 113, 7, 7, 7, 9}, 0}, // Head 5 + {0, { 7, 12, 14, 31, 15, 8, 7, 7, 7, 7, 7, 12}, 0}, // Ask 6 + {0, { 7, 12, 14, 31, 15, 8, 7, 2, 12, 15, 7, 12}, 0}, // Menu 7 + {0, { 7, 14, 7, 79, 15, 7, 7, 7, 7, 7, 7, 14}, 0}, // Help 8 + {3, { 7, 12, 14, 31, 15, 8, 7, 7, 7, 7, 7, 12}, 0}, // Cfg 9 + {0, { 15, 12, 14, 7, 7, 7, 7, 7, 7, 7, 7, 12}, 0}, // Info 10 + {3, { 7, 12, 14, 31, 15, 8, 7, 7, 7, 7, 7, 12}, 0}, // Cfgb 11 + {0, { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, 0}, // Style 12 + {0, { 7, 7, 7, 7, 7, 7, 7, 8, 7, 7, 7, 7}, 0}, // Shad 13 + {0, { 0, 0, 0, 0, 0, 0, 8, 15, 0, 0, 0, 0}, 0}, // Read2 14 +}; + + +// ------------------------------------------------------------------ +// 0 1 2 3 4 5 6 7 8 9 + +Win gold_color2[16] = { + {5, { 240, 15, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15}, 2}, // Back 0 + {5, { 143, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, 1}, // Stat 1 + {0, { 15, 14, 14, 7, 12, 7, 7, 9, 7, 7, 7, 14}, 0}, // Brag 2 + {0, { 240, 241, 244, 143, 244, 7, 7, 7, 7, 7, 7, 241}, 0}, // Area 3 + {0, { 241, 240, 242, 244, 64, 248, 240, 64, 240, 240, 248, 240}, 5}, // Read 4 + {0, { 135, 142, 142, 135, 143, 7, 143, 64, 135, 135, 7, 142}, 0}, // Head 5 + {0, { 224, 230, 232, 143, 228, 231, 7, 7, 7, 7, 7, 230}, 0}, // Ask 6 + {0, { 112, 126, 116, 143, 126, 120, 117, 113, 125, 121, 7, 126}, 0}, // Menu 7 + {0, { 135, 142, 7, 228, 143, 7, 7, 7, 7, 7, 7, 142}, 0}, // Help 8 + {3, { 224, 230, 232, 143, 228, 231, 7, 7, 7, 7, 7, 230}, 0}, // Cfg 9 + {0, { 15, 12, 14, 7, 7, 7, 7, 7, 7, 7, 7, 12}, 0}, // Info 10 + {3, { 240, 241, 244, 143, 244, 7, 7, 7, 7, 7, 7, 241}, 0}, // Cfgb 11 + {0, { 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249}, 0}, // Style 12 + {0, { 7, 7, 7, 7, 7, 7, 7, 8, 7, 7, 7, 7}, 0}, // Shad 13 + {0, { 0, 0, 0, 0, 0, 0, 248, 241, 0, 0, 0, 0}, 0}, // Read2 14 +}; + + +// ------------------------------------------------------------------ +// 0 1 2 3 4 5 6 7 8 9 + +Win gold_mono1[16] = { + {5, { 15, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0}, 2}, // Back 0 + {5, { 112, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, 1}, // Stat 1 + {0, { 15, 7, 15, 7, 15, 7, 7, 7, 7, 7, 7, 7}, 0}, // Brag 2 + {0, { 7, 7, 15, 112, 15, 7, 7, 7, 7, 7, 7, 7}, 0}, // Area 3 + {0, { 7, 7, 15, 15, 112, 15, 7, 7, 7, 7, 15, 7}, 5}, // Read 4 + {0, { 7, 7, 15, 7, 15, 7, 112, 15, 7, 7, 7, 7}, 0}, // Head 5 + {0, { 112, 112, 112, 15, 15, 7, 7, 7, 7, 7, 7, 112}, 0}, // Ask 6 + {0, { 7, 7, 112, 112, 15, 7, 15, 15, 15, 15, 7, 7}, 0}, // Menu 7 + {0, { 112, 112, 7, 15, 112, 7, 7, 7, 7, 7, 7, 112}, 0}, // Help 8 + {3, { 7, 7, 112, 112, 15, 7, 7, 7, 7, 7, 7, 7}, 0}, // Cfg 9 + {0, { 15, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, 0}, // Info A + {3, { 7, 7, 112, 112, 15, 7, 7, 7, 7, 7, 7, 7}, 0}, // Cfgb B + {0, { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, 0}, // Style C + {0, { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, 0}, // Shad F + {0, { 0, 0, 0, 0, 0, 0, 7, 15, 0, 0, 0, 0}, 0}, // Read2 14 +}; + + +// ------------------------------------------------------------------ +// Deallocate CFG at exit + +static void CfgReset(void) { + + throw_delete(QWK); + throw_delete(EDIT); + throw_delete(AFILE); + + if(NODE) + throw_xrelease(NODE->nodelist); + throw_xrelease(NODE); + throw_delete(CFG); +} + + +// ------------------------------------------------------------------ +// Assign default CFG values + +void CfgInit() { + + atexit(CfgReset); + + CFG = new CfgGed; + throw_new(CFG); + + NODE = (NodeIxl*)throw_calloc(1, sizeof(NodeIxl)); + + AFILE = new gareafile; + throw_new(AFILE); + + EDIT = new GoldedCfgEdit; + throw_new(EDIT); + + QWK = new Qwk; + throw_new(QWK); + + LangInit(); +} + + +// ------------------------------------------------------------------ +// Assign default CFG values before reading the .CFG's + +void CfgInit2() { + + // ---------------------------------------------------------------- + // Set some default robotnames + + CfgRobotname("AreaFix, AreaMgr, FileFix, AreaLink, SqaFix, AllFix, SqaFixHost, Raid, GEcho"); + + + // ---------------------------------------------------------------- + // Set some default filerequest extensions + + CfgFrqext(".ARC .ARJ .EXE .LHA .LZH .PAK .RUN .SDA .SDN .ZIP .ZOO .DOC .TXT .GIF .RAR .PNG .JPG .HA"); + + + // ---------------------------------------------------------------- + // Setup the standard beeping effects + + static char Attention[] = "Attention PLAY ToYou"; + CfgEvent(Attention); + static char EditComment[] = "EditComment PLAY ToYou"; + CfgEvent(EditComment); + static char EndOfMsgs[] = "EndOfMsgs PLAY TheEnd"; + CfgEvent(EndOfMsgs); + static char JobDone[] = "JobDone PLAY GotIt"; + CfgEvent(JobDone); + static char JobFailed[] = "JobFailed PLAY TooBad"; + CfgEvent(JobFailed); + static char MsgIsLocal[] = "MsgIsLocal PLAY ToYou"; + CfgEvent(MsgIsLocal); + static char MsgToYou[] = "MsgToYou PLAY ToYou"; + CfgEvent(MsgToYou); + static char SayBiBi[] = "SayBiBi PLAY SayBiBi"; + CfgEvent(SayBiBi); + static char SearchFailed[] = "SearchFailed PLAY TooBad"; + CfgEvent(SearchFailed); + static char SearchSuccess[] = "SearchSuccess PLAY GotIt"; + CfgEvent(SearchSuccess); + + + // ---------------------------------------------------------------- +} + + +// ------------------------------------------------------------------ + +int IsMacro(gkey key, int type) { + + vector::iterator m = CFG->macro.begin(); + while(m != CFG->macro.end()) { + if((key == m->key) and (type == m->type)) + return true; + m++; + } + + return false; +} + + +// ------------------------------------------------------------------ + +int PlayMacro(gkey key, int type) { + + vector::iterator m = CFG->macro.begin(); + while(m != CFG->macro.end()) { + if((key == m->key) and (type == m->type)) { + RunMacro(m); + return true; + } + m++; + } + + return false; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/geglob.h b/golded3/geglob.h new file mode 100644 index 0000000..41b1e66 --- /dev/null +++ b/golded3/geglob.h @@ -0,0 +1,193 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Global data. +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ + +extern glog LOG; + +extern gareafile* AFILE; +extern CfgGed* CFG; +extern LangGed* LNG; +extern NodeIxl* NODE; +extern Qwk* QWK; +extern GoldedCfgEdit* EDIT; + +// GCCFGG.CPP +extern bool cfgingroup; + +// GCKEYS.CPP +extern CmdKey DefaultKeyset[]; + +// GEAREA.CPP +extern int area_pos; +extern int area_width; +extern int marked_pos; +extern int marked_width; +extern const char marked_char; +extern int desc_pos; +extern int desc_width; +extern int count_pos; +extern int count_width; +extern int pmark_pos; +extern int pmark_width; +extern const char pmark_char; +extern int unread_pos; +extern int unread_width; +extern int changed_pos; +extern int changed_width; +extern const char changed_char; +extern int echoid_pos; +extern int echoid_width; +extern int groupid_pos; +extern int groupid_width; + +// GEFILE.CPP +extern int fspecs; +extern int specfiles; +extern FileSpec* fspec; + +// GEMENU.CPP +extern GMsg* MenuMsgPtr; + +// GEPOST.CPP +extern uint position; +extern ulong msgcount; + +// GEREAD.CPP +extern int reader_finished; +extern int reader_done; +extern int reader_topline; +extern int reader_keyok; +extern int reader_direction; +extern int reader_rcv_noise; +extern gkey reader_keycode; +extern GMsgHeaderView *HeaderView; +extern GMsgBodyView *BodyView; + +// Other + +extern uint locpost, netpost, echopost; + +extern Subj information; + +extern Area* AA; + +extern char m_title[]; +extern int m_titlepos; +extern int m_titleattr; + +extern char* tconv; + +extern int AreaKeys, ReadKeys, ListKeys, NodeKeys, EditKeys, FileKeys; +extern list::iterator AreaKey, ReadKey, ListKey, NodeKey, EditKey, FileKey; + +extern int inforow; + +extern char goldmark; + +extern int startecho; +extern Echo stecho; + +extern int fieldupd; + +extern int CurrArea; +extern int OrigArea; + +extern Esc* MNETable; +extern Esc* I51Table; +extern Esc* CompTable; +extern Chs* CharTable; +extern EscTab* CompTP; +extern EscTab* I51TP; +extern EscTab* MNETP; +extern ChsTab* ChsTP; + +//extern char gversion[]; + +extern bool quiet; +extern bool ignore; +extern int cfgerrors; +extern bool veryverbose; +extern bool shellvid; +extern word* oldscreen; + +extern int keysread; + +extern bool disablesound; + +extern int _in_editor; +extern int _in_msglist; +extern int savedirect; + +extern void(*SIGINT_OldHandler)(void); + +extern bool cmdlinedebughg; +extern bool cmdlineimportsoup; +extern bool cmdlineoldkeyw; +extern int cmdlinesharemode; + +extern Win gold_color1[]; +extern Win gold_color2[]; +extern Win gold_mono1[]; + +extern Echo area_maybe; + +extern int blanked; + +extern int startupscan_success; + + +// ------------------------------------------------------------------ +// Global compile constants + +extern const char* __gver_vendor_name__; +extern const char* __gver_vendor_fido__; +extern const char* __gver_vendor_email__; +extern const char* __gver_prename__; +extern const char* __gver_preshortname__; +extern const char* __gver_name__; +extern const char* __gver_shortname__; +extern const char* __gver_shortlogname__; +extern const char* __gver_postshortname__; +extern const char* __gver_postname__; +extern const char* __gver_platform__; +extern const char* __gver_shortplatform__; +extern const char* __gver_cfgext__; +extern const char* __gver_preversion__; +extern const char* __gver_postversion__; +extern int __gver_major__; +extern int __gver_minor__; +extern int __gver_release__; +extern const char* __gver_releasename__; +extern const char* __gver_date__; +extern const char* __gver_time__; +extern const char* __gver_longpid__; +extern const char* __gver_shortpid__; + + +// ------------------------------------------------------------------ + diff --git a/golded3/gehdre.cpp b/golded3/gehdre.cpp new file mode 100644 index 0000000..ede42a5 --- /dev/null +++ b/golded3/gehdre.cpp @@ -0,0 +1,545 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Header edit. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +class GMsgHeaderEdit : public gwinput2 { + +public: + + enum { + id_from_name, + id_from_addr, + id_to_name, + id_to_addr, + id_subject + }; + + GMsgHeaderView &view; + + GMsgHeaderEdit(GMsgHeaderView &v) : gwinput2(v.window), view(v) { msg = view.msg; } + + GMsg* msg; + bool lookup; + + bool handle_other_keys(uint& key); + bool validate(); +}; + + +// ------------------------------------------------------------------ + +bool GMsgHeaderEdit::handle_other_keys(uint& key) { + + switch(key) { + case Key_F10: + vcurhide(); + ChgAttrs(NO, msg); + lookup_addressbook(msg, get_field(id_to_name)->buf, get_field(id_to_addr)->buf, true); + ChgAttrs(YES, msg); + get_field(id_to_name)->draw(); + get_field(id_to_addr)->draw(); + current->update(); + vcurshow(); + break; + case Key_S_F10: + { + Addr addr,addr2; + INam buf; + field* p; + + addr.set_all(65535u); + addr2.set_all(65535u); + addr.set(get_field(id_to_addr)->buf); + strcpy(buf, strtrim(get_field(id_to_name)->buf)); + + if(addr != addr2) + addr.make_string(buf); + + addr2 = addr; + + Lookup(msg, &addr, buf, -6, LNG->SelectDestNode); + vcurshow(); + + if(addr != addr2 and addr.valid()) { + p = get_field(id_to_addr); + + addr.make_string(p->buf); + p->buf_end_pos = strlen(buf); + p->buf_pos = p->buf_end_pos; + + if(current->id == id_to_addr) + p->update(); + else + p->draw(); + + p = get_field(id_to_name); + strcpy(p->buf, buf); + + if(current->id == id_to_name) + p->update(); + else + p->draw(); + } + } + return true; + default: + if(PlayMacro(key, 0)) + return true; + } + return false; +} + + +// ------------------------------------------------------------------ + +bool set_to_address(GMsg* msg, gsetaddr* toname, gsetaddr* toaddr, gsetaddr* fromaddr, gsetaddr* subj, int pos, char* lng_lookup, bool lookup) { + + INam buf, buf1, buf2; + char* ptr = toname->buf; + strcpy(buf, ptr); + + if(not CFG->addressmacro.empty()) { + vector::iterator n; + for(n=CFG->addressmacro.begin(); n != CFG->addressmacro.end(); n++) { + if(strieql(buf, n->macro)) { + ptr = strcpy(buf1, n->name); + if(*buf1 == '@') { + // UUCP/INTERNET addressing + ptr = strchr(buf1, '/'); + if(ptr) { + *ptr++ = NUL; + strcpy(msg->idest, ptr); + strcpy(msg->realto, buf1+1); + if(*AA->Internetgate().name) { + strcpy(msg->iaddr, ptr); + ptr = strcpy(buf1, AA->Internetgate().name); + } + else + strcpy(buf1, ptr); + } + else { + strcpy(msg->idest, buf1+1); + if(*AA->Internetgate().name) { + strcpy(msg->iaddr, buf1+1); + ptr = strcpy(buf1, AA->Internetgate().name); + } + else { + strcpy(buf2, buf1+1); + ptr = strcpy(buf1, buf2); + } + } + } + else if(AA->isinternet()) { + ParseInternetAddr(buf1, buf2, buf); + ptr = buf2; + strcpy(buf1, buf2); + strcpy(msg->idest, buf); + } + else { + *msg->iaddr = NUL; + *msg->realto = NUL; + } + strcpy(toname->buf, ptr); + toname->update = true; + strcpy(msg->to, buf1); + if(AA->isinternet()) { + strcpy(toaddr->buf, msg->idest); + if(n->addr.net) + msg->dest = msg->odest = n->addr; + else + msg->dest = msg->odest = AA->Internetgate().addr; + } + else { + n->addr.make_string(toaddr->buf); + } + toaddr->update = true; + if(*n->subj and subj) { + strcpy(subj->buf, n->subj); + subj->update = true; + } + + AttrAdd(&msg->attr, &n->attr); + + if(lookup or AA->isnet()) + return false; + + return true; + } + } + } + + if(lookup_addressbook(msg, toname->buf, toaddr->buf, false)) { + if(lookup or AA->isnet()) + return false; + return true; + } + + // Internet gating + if(not AA->isinternet()) { + if(strchr(toname->buf, '@') and AA->Internetgate().addr.net) { + if(*AA->Internetgate().name) { + strcpy(msg->iaddr, toname->buf); + strcpy(msg->to, AA->Internetgate().name); + strcpy(toname->buf, msg->to); + toname->update = true; + } + AA->Internetgate().addr.make_string(toaddr->buf); + toaddr->update = true; + if(lookup or AA->isnet()) + return false; + return true; + } + + if(lookup) { + strcpy(buf1, toname->buf); + strcpy(buf2, msg->to); + if(strblank(toaddr->buf) or strblank(buf1) or strcmp(buf1, buf2)) { + if(strblank(toname->buf)) + strcpy(buf, toaddr->buf); + else + strcpy(buf, toname->buf); + strtrim(buf); + if(*buf == NUL) + strcpy(buf, " "); + *msg->iaddr = NUL; + *msg->realto = NUL; + + if(*buf) { + Addr addr; + addr.reset(fromaddr->buf); // Get the orig address to base lookup on + Lookup(msg, &addr, buf, pos, lng_lookup); + if(striinc("Sysop", buf) or strieql(AA->Whoto(), buf)) { + if(addr.net == 0) { + if(not AA->isnet()) + return false; + return true; + } + } + int robotchk = false; + for(gstrarray::iterator n = CFG->robotname.begin(); n != CFG->robotname.end(); n++) + if(striinc(n->c_str(), buf)) { + robotchk = true; + break; + } + if(robotchk) { + EDIT->HardLines(false); + if(addr.net == 0) + return true; + } + if(addr.net) { + addr.make_string(toaddr->buf); + toaddr->update = true; + strcpy(msg->to, buf); + strcpy(toname->buf, buf); + toname->update = true; + return false; + } + else { + HandleGEvent(EVTT_SEARCHFAILED); + return true; + } + } + } + } + else { + if(strpbrk(buf, "*?")) { + if(CFG->switches.get(lookupuserbase)) { + if(AA->UserLookup(buf)) { + strcpy(msg->to, buf); + *msg->iaddr = NUL; + *msg->realto = NUL; + toname->update = true; + return true; + } + } + } + } + } + return true; +} + + +// ------------------------------------------------------------------ + +bool GMsgHeaderEdit::validate() { + + if(current->id == id_to_name) { + + field* ffromaddr = get_field(id_from_addr); + field* ftoaddr = get_field(id_to_addr); + field* fsubj = get_field(id_subject); + gsetaddr toname, toaddr, fromaddr, subj; + + toname.buf = current->buf; toname.update = false; + toaddr.buf = ftoaddr->buf; toaddr.update = false; + fromaddr.buf = ffromaddr->buf; fromaddr.update = false; + subj.buf = fsubj->buf; subj.update = false; + + bool res = set_to_address(msg, &toname, &toaddr, &fromaddr, &subj, 0, LNG->SelectDestNode, lookup); + + vcurshow(); + char bot2[200]; + MakeAttrStr(bot2, &msg->attr); + strsetsz(bot2, EDIT->HdrNodeLen()); + window.prints(1, EDIT->HdrNodePos(), C_HEADW, bot2); + + if(toname.update) current->update(); + if(toaddr.update) ftoaddr->update(); + if(fromaddr.update) ffromaddr->update(); + if(subj.update) fsubj->update(); + + if(res) + return true; + else + go_next_field(); + } + else if(current->id == id_subject) { + CheckSubject(msg, current->buf); + current->update(); + } + + return true; +} + + +// ------------------------------------------------------------------ + +int EditHeaderinfo(int mode, GMsgHeaderView &view) { + + GMsgHeaderEdit hedit(view); + GMsg *msg = view.msg; + + string from_name, to_name, subject; + string from_addr, to_addr, orig_from_addr; + + from_name = msg->By(); + if(AA->isinternet()) { + from_addr = msg->iorig; + } + else { + if(msg->orig.net) + msg->orig.make_string(from_addr, msg->odom); + } + orig_from_addr = from_addr; + if(AA->isinternet()) { + to_name = msg->To(); + to_addr = msg->idest; + } + else { + to_name = (*msg->iaddr and not *msg->igate) ? msg->iaddr : msg->to; + if(msg->dest.net) + msg->dest.make_string(to_addr, msg->ddom); + } + subject = msg->re; + + if(AA->isnet()) + hedit.lookup = CFG->switches.get(lookupnet); + else if(AA->isecho()) + hedit.lookup = CFG->switches.get(lookupecho); + else + hedit.lookup = CFG->switches.get(lookuplocal); + + int from_name_pos = EDIT->HdrNamePos(); + int from_name_len = EDIT->HdrNameLen(); + int from_addr_pos = EDIT->HdrNodePos(); + int from_addr_len = EDIT->HdrNodeLen(); + int to_name_pos = from_name_pos; + int to_name_len = from_name_len; + int to_addr_pos = from_addr_pos; + int to_addr_len = hedit.lookup or AA->isnet() ? from_addr_len : 0; + int subject_pos = 8; + int subject_len = MAXCOL - subject_pos; + int name_cvt = AA->Editmixcase() ? GMsgHeaderEdit::cvt_mixedcase : GMsgHeaderEdit::cvt_none; + int addr_cvt = GMsgHeaderEdit::cvt_none; + int subj_cvt = GMsgHeaderEdit::cvt_none; + + hedit.setup(C_HEADW, C_HEADW, C_HEADE, _box_table(W_BHEAD,13), true); + + hedit.add_field(GMsgHeaderEdit::id_from_name, 2, from_name_pos, from_name_len, from_name, sizeof(INam), name_cvt); + hedit.add_field(GMsgHeaderEdit::id_from_addr, 2, from_addr_pos, from_addr_len, from_addr, sizeof(IAdr), addr_cvt); + hedit.add_field(GMsgHeaderEdit::id_to_name, 3, to_name_pos, to_name_len, to_name, sizeof(INam), name_cvt); + hedit.add_field(GMsgHeaderEdit::id_to_addr, 3, to_addr_pos, to_addr_len, to_addr, sizeof(IAdr), addr_cvt); + hedit.add_field(GMsgHeaderEdit::id_subject, 4, subject_pos, subject_len, subject, sizeof(ISub), subj_cvt); + + hedit.start_id = GMsgHeaderEdit::id_to_name; + switch(mode) { + case MODE_REPLYCOMMENT: + if(not (msg->dest.net or not AA->isnet())) + break; + // else drop through ... + case MODE_REPLY: + case MODE_QUOTE: + case MODE_CHANGE: + hedit.start_id = GMsgHeaderEdit::id_subject; + break; + } + + int help = gwin.help; + + ChgAttrs(true, msg); + + whelpdef(CFG->helpged, Key_F1, C_HELPB, C_HELPW, C_HELPQ, C_HELPS, NULL); + vcurshow(); + if(not (hedit.lookup or AA->isnet())) { + char date2[25] = {""}; + strsetsz(date2, view.width - CFG->disphdrdateset.pos); + view.window.prints(3, CFG->disphdrdateset.pos, view.to_color, date2); + } + + view.window.prints(5, view.width-strlen(LNG->HeaderEditHelp1)-1, view.title_color, LNG->HeaderEditHelp1); + view.window.prints(5, view.width-strlen(LNG->HeaderEditHelp1)-strlen(LNG->HeaderEditHelp2)-3, view.title_color, LNG->HeaderEditHelp2); + + hedit.run(H_Header); + vcurhide(); + + ChgAttrs(false, msg); + + whelpcat(help); + + if(not hedit.dropped and not gkbd.quitall) { + + strcpy(msg->by, from_name.c_str()); + strcpy(msg->re, subject.c_str()); + + INam tmp_to_name; + strxcpy(tmp_to_name, *msg->igate ? to_name.c_str() : msg->iaddr, sizeof(INam)); + if(lookup_addressbook(msg, tmp_to_name, NULL)) + to_name = tmp_to_name; + + if(AA->isinternet()) { + strcpy(msg->to, to_name.c_str()); + strcpy(msg->realby, msg->by); + strcpy(msg->realto, msg->to); + strcpy(msg->iorig, from_addr.c_str()); + strcpy(msg->idest, to_addr.c_str()); + strcpy(msg->ifrom, msg->iorig); + strcpy(msg->ito, msg->idest); + if(msg->orig.net == 0) + msg->orig = msg->oorig = AA->Aka().addr; + if(msg->dest.net == 0) + msg->dest = msg->odest = AA->Internetgate().addr; + } + else { + if(strchr(to_name.c_str(), '@')) { + if(*AA->Internetgate().name) + strcpy(msg->iaddr, to_name.c_str()); + else { + if(strlen(to_name.c_str()) > 34) { + strcpy(msg->to, *AA->Internetgate().name ? AA->Internetgate().name : "UUCP"); + strcpy(msg->iaddr, to_name.c_str()); + } + else + strcpy(msg->to, to_name.c_str()); + } + } + else + strcpy(msg->to, to_name.c_str()); + + Addr address; + address = AA->Aka().addr; + + if(from_addr.length()) { + address.set(from_addr.c_str(), msg->odom); + msg->orig.zone = address.zone; + msg->orig.net = address.net; + msg->orig.node = address.node; + msg->orig.point = address.point; + } + + if(to_addr.empty()) { + // Set destination to yourself or the Boss node + address = msg->orig; + address.point = 0; + address.make_string(to_addr); + } + + address = AA->Aka().addr; + const char* domain = address.set(to_addr); + msg->odest.zone = msg->dest.zone = address.zone; + msg->odest.net = msg->dest.net = address.net; + msg->odest.node = msg->dest.node = address.node; + msg->odest.point = msg->dest.point = address.point; + + if(*domain) { + address.reset(); + address.zone = msg->orig.zone; + address.set(domain); + if(address.net) { + msg->odest.zone = address.zone; + msg->odest.net = address.net; + msg->odest.node = address.node; + msg->odest.point = address.point; + } + else { + msg->odest.zone = msg->dest.zone; + msg->odest.net = msg->dest.net; + msg->odest.node = msg->dest.node; + msg->odest.point = msg->dest.point; + } + } + + // Try to match akas with the dest address, but only if the orig address was NOT changed + vector::iterator i; + for(i = CFG->aka.begin(); i != CFG->aka.end(); i++) { + if(memcmp(&msg->orig, i, sizeof(Addr)) == 0) + break; // Found one of our own akas. + } + + // Try to match akas with the dest address, but only if the orig address was NOT changed + if(i != CFG->aka.end()) { + // ... and only if the orig aka was already one of our own + if(strieql(orig_from_addr.c_str(), from_addr.c_str())) { + // ... and only if we did NOT change aka manually + if(AA->Aka().addr.equals(AA->aka())) { + + // Do aka matching + if(AA->Akamatching()) { + strcpy(msg->odom, CFG->aka[AkaMatch(&msg->orig, &msg->dest)].domain); + } + } + } + } + } + } + else { + for(int n=0; n + + +// ------------------------------------------------------------------ + +char* strconv(char* str, char* conv) { + + char* s=str; + char* p = str; + + NW(conv); // Dummy + + while(*str) { + if((*str < ' ') and (*str != '\n') and (*str != '\r')) // Control codes + *p++ = '.'; + else + *p++ = *str; + str++; + } + return(s); +} + + +// ------------------------------------------------------------------ + +void DispHeader(GMsg* msg, bool prn, FILE* fp, int width) { + + int namewidth = CFG->disphdrnodeset.pos - CFG->disphdrnameset.pos; + int nodewidth = CFG->disphdrdateset.pos - CFG->disphdrnodeset.pos; + int datewidth = width - CFG->disphdrdateset.pos; + + char headerline[200]; + memset(headerline, _box_table(W_BHEAD,1), width); + headerline[width] = NUL; + + INam whofrom; + if(*msg->ifrom and *msg->realby) + sprintf(whofrom, "%s <%s>", msg->realby, msg->iorig); + else if(*msg->ifrom and *msg->iorig) + strcpy(whofrom, msg->iorig); + else + strcpy(whofrom, msg->By()); + strsetsz(whofrom, (AA->isinternet() or *msg->ifrom) ? (namewidth+nodewidth) : namewidth); + + INam whoto; + if(*msg->ito and *msg->realto) + sprintf(whoto, "%s <%s>", msg->realto, msg->idest); + else if(*msg->ito and *msg->idest) + strcpy(whoto, msg->idest); + else + strcpy(whoto, msg->To()); + strsetsz(whoto, (AA->isinternet() or *msg->ito) ? (namewidth+nodewidth) : namewidth); + + // Generate top line fields + char buf[256]; + char top1[200]; + strtrim(strcpy(buf, AA->desc())); + if((CFG->dispareano == ALWAYS) or (CFG->dispareano and AA->board())) + sprintf(top1, " [%u] %s ", AA->board(), buf); + else + sprintf(top1, " %s ", buf); + strtrim(top1); + strcat(top1, " (" /*)*/); + if(AA->isinternet()) + strcpy(buf, AA->Internetaddress()); + else + AA->Aka().addr.make_string(buf); + strcat(top1, buf); + strcat(top1, /*(*/ ") "); + + char top2[200]; + if(msg->areakludgeid) + sprintf(top2, " %s (%s) ", AA->echoid(), msg->areakludgeid); + else + sprintf(top2, " %s ", AA->echoid()); + + // Generate message attributes string + char bot2[200]; + MakeAttrStr(bot2, &msg->attr); + int len2 = strlen(bot2); + if(len2 > width-CFG->disphdrnodeset.pos) { + len2 = width-CFG->disphdrnodeset.pos; + strsetsz(bot2, len2); + } + + // Generate message number and reply links string + char bot1[200]; + char* ptr = bot1; + int list_max = msg->link.list_max(); + ulong* replies = (ulong*)throw_calloc(list_max+1, sizeof(ulong)); + ulong replyto, replynext; + if(CFG->switches.get(disprealmsgno)) { + ptr += sprintf(ptr, " %-5.5s: #%lu [%u]", LNG->Msg, msg->msgno, AA->Msgn.Count()+(msg->attr.nwm() ? 1 : 0)); + replyto = msg->link.to(); + replies[0] = msg->link.first(); + replynext = msg->link.next(); + for(int replyn=1; replynlink.list(replyn-1); + } + else { + uint active = AA->Msgn.Count() + (msg->attr.nwm() ? 1 : 0); + ptr += sprintf(ptr, " %-5.5s: %u %s %u", LNG->Msg, msg->attr.nwm() ? active : AA->Msgn.ToReln(msg->msgno), LNG->of, active); + replyto = AA->Msgn.ToReln(msg->link.to()); + replies[0] = AA->Msgn.ToReln(msg->link.first()); + replynext = AA->Msgn.ToReln(msg->link.next()); + for(int replyn=1; replynMsgn.ToReln(msg->link.list(replyn-1)); + } + if(replyto) + ptr += sprintf(ptr, " -%lu", replyto); + for(int replyn=0,plus=0; replyndisphdrnameset.pos + len1) > CFG->disphdrnodeset.pos) { + if(8 + len1 + len2 > width) { + strsetsz(bot1, width-len2-1); + strtrim(bot1); + } + strcat(bot1, " "); + strcat(bot1, bot2); + *bot2 = NUL; + } + else { + strsetsz(bot1, namewidth+8); + strcat(bot1, bot2); + *bot2 = NUL; + } + strsetsz(bot1, width); + throw_free(replies); + + // Generate orig node data + char node1[200]; + if(msg->orig.net) + msg->orig.make_string(node1); + else + *node1 = NUL; + strsetsz(node1, nodewidth); + + char date1[25] = ""; + if(msg->written) + strftimei(date1, CFG->disphdrdateset.len, LNG->DateTimeFmt, gmtime(&msg->written)); + strsetsz(date1, datewidth); + + // Generate dest node data + char node2[200]; + if(msg->dest.net and AA->isnet()) { + msg->dest.make_string(node2); + if(msg->odest.net) { + if(msg->odest.net != msg->dest.net or msg->odest.node != msg->dest.node) { + sprintf(buf, " %s %u/%u", LNG->Via, msg->odest.net, msg->odest.node); + strcat(node2, buf); + } + } + } + else + *node2 = NUL; + strsetsz(node2, nodewidth); + + char date2[25] = ""; + if(msg->arrived) + strftimei(date2, CFG->disphdrdateset.len, LNG->DateTimeFmt, gmtime(&msg->arrived)); + strsetsz(date2, datewidth); + + // Generate subjectline + char subj[200], lngsubj[10]; + strcpy(lngsubj, (msg->attr.att() or msg->attr.frq() or msg->attr.urq()) ? LNG->File : LNG->Subj); + strxcpy(subj, msg->re, sizeof(subj)); + strsetsz(subj, width-strlen(lngsubj)); + + // Write the total header to a file + strcpy(stpcpy(buf, headerline), prn ? NL : "\n"); + strncpy(buf+1, top1, strlen(top1)); + strncpy(buf+width-strlen(top2)-1, top2, strlen(top2)); + strconv(buf, tconv); + fwrite(buf, strlen(buf), 1, fp); + + strcpy(stpcpy(buf, bot1), bot2); + strtrim(buf); + strcat(buf, prn ? NL : "\n"); + strconv(buf, tconv); + fwrite(buf, strlen(buf), 1, fp); + + sprintf(buf, "%s%s%s%s", + LNG->From, whofrom, + ((not (*msg->ifrom and (*msg->realby or *msg->iorig))) and not AA->isinternet()) ? node1 : "", + date1 + ); + strtrim(buf); + strcat(buf, prn ? NL : "\n"); + strconv(buf, tconv); + fwrite(buf, strlen(buf), 1, fp); + + sprintf(buf, "%s%s%s%s", LNG->To, whoto, + ((not (*msg->ito and (*msg->realto or *msg->idest))) and not AA->isinternet()) ? node2 : "", + date2 + ); + strtrim(buf); + strcat(buf, prn ? NL : "\n"); + strconv(buf, tconv); + fwrite(buf, strlen(buf), 1, fp); + + strcpy(stpcpy(buf, lngsubj), subj); + strtrim(buf); + strcat(buf, prn ? NL : "\n"); + strconv(buf, tconv); + fwrite(buf, strlen(buf), 1, fp); + + strcpy(stpcpy(buf, headerline), prn ? NL : "\n"); + strconv(buf, tconv); + fwrite(buf, strlen(buf), 1, fp); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gehelp.h b/golded3/gehelp.h new file mode 100644 index 0000000..8061868 --- /dev/null +++ b/golded3/gehelp.h @@ -0,0 +1,130 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Help Categories. +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ +// Help Categories + + +// ------------------------------------------------------------------ +// General + +#define H_General 1000 +#define H_AskDropMsg 1001 +#define H_AskExit 1002 +#define H_AskOverWrite 1003 +#define H_Attributes 1004 +#define H_ChangeAka 1005 +#define H_ChangeOrigin 1006 +#define H_ChangeTemplate 1007 +#define H_ChangeUsername 1008 +#define H_ChangeTagline 1009 +#define H_ChangeXlatImport 1010 + + +// ------------------------------------------------------------------ +// Area + +#define H_Area 2000 +#define H_AreaMark 2001 +#define H_ScanAreas 2002 +#define H_AreaSelection 2003 +#define H_HeatAreas 2004 +#define H_ZapAreas 2005 +#define H_SelectMarks 2006 +#define H_AreaDropMarks 2007 +#define H_AreaCatchUp 2008 + +// ------------------------------------------------------------------ +// Reader Menus + +#define H_Reader 3000 +#define H_AskChange 3001 +#define H_AskDelete 3002 +#define H_AskDoMarks 3003 +#define H_AskNextArea 3004 +#define H_CopyMoveForward 3005 +#define H_FindString 3006 +#define H_InputMsgno 3007 +#define H_MarkMessages 3008 +#define H_MarkString 3009 +#define H_MessageBrowser 3010 +#define H_WriteMessage 3011 +#define H_EditCryptKey 3012 +#define H_FileRequest 3013 +#define H_MenuConfirm 3014 +#define H_GotoReplies 3015 +#define H_ReplyThread 3016 + + +// ------------------------------------------------------------------ +// Header Menus + +#define H_Header 4000 +#define H_AskDelOrig 4001 +#define H_AskReadOnly 4002 +#define H_AskZoneGate 4003 +#define H_CarbonCopy 4004 +#define H_FileSelect 4005 +#define H_Message 4006 +#define H_NodelistBrowser 4007 +#define H_SaveMsg 4008 +#define H_AskForward 4009 +#define H_Crosspost 4010 + + +// ------------------------------------------------------------------ +// Editor Menus + +#define H_Editor 5000 +#define H_ExportFile 5001 +#define H_ImportFile 5002 +#define H_ImportTxt 5003 + + +// ------------------------------------------------------------------ +// Userbase Menus + +#define H_Userbase 6000 +#define H_EditAdrEntry 6001 + + +// ------------------------------------------------------------------ +// Error messages + +#define H_EOutOfMemory 9001 +#define H_EWarnMsgtxt 9002 +#define H_ENodelist 9003 +#define H_EBetaVersion 9004 +#define H_EOpenQbase 9005 +#define H_ENoUser 9006 +#define H_ECtrlBreak 9007 +#define H_EQbaseRebuild 9008 +#define H_EMemoryWarning 9009 + + +// ------------------------------------------------------------------ + diff --git a/golded3/geinit.cpp b/golded3/geinit.cpp new file mode 100644 index 0000000..3562224 --- /dev/null +++ b/golded3/geinit.cpp @@ -0,0 +1,1111 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// System initializing. +// ------------------------------------------------------------------ + +#include +#include +#include +#include +#include +#ifdef __WIN32__ +#include +#endif + +// ------------------------------------------------------------------ +// Handle commandline parameters + +#if defined(GFTRK_ENABLE) +static int gftrk_set_max = -1; +extern int __gftrk_statusline; +#endif + +#ifdef __OS2__ +extern bool gmem_check_overrun; +#endif + +static string keybuf; + +static Path cmdlinecfg = ""; + bool cmdlinedebughg = false; +static int cmdlineforce = 0; +static bool cmdlinehelp = false; + bool cmdlinenoscan = false; + bool cmdlineexportsoup = false; + bool cmdlineimportsoup = false; +static bool cmdlineinstall = false; +static Path cmdlineinstpath = ""; + bool cmdlineoldkeyw = true; + bool cmdlinepriority = false; + int cmdlinesharemode = SH_DENYNO; + int cmdlinetimeout = -1; +static bool cmdlinewriteareas = false; + + +// ------------------------------------------------------------------ + +static void InitCmdline(char* val) { + + char* key; + char* trueval; + + if(strchr("-/", *val)) { + val++; + getkeyvaleql(&key, &val, true); + trueval = val; + if(*val == NUL) + val = key+1; + switch(toupper(*key)) { + case 'C': // Use another Configfile + if(*val) + strcpy(cmdlinecfg, val); + else + cout << "Warning: configuration filename missed for -C option, ignored." << endl; + break; + case 'D': + cmdlineoldkeyw = (*val == '-') ? true : false; + break; + case 'E': + if(strieql(key, "EXPORTSOUP")) + cmdlineexportsoup = true; + else + strxcpy(stecho, val, sizeof(stecho)); + break; + case 'F': + cmdlineforce = (*val == '-') ? false : true; + if(toupper(key[1]) == 'F') + cmdlineforce++; + break; + case '?': + case 'H': + cmdlinehelp = true; + break; + case 'I': + if(strieql(key, "INSTALL")) { + cmdlineinstall = true; + cmdlineforce = 1; + if(*trueval) + PathCopy(cmdlineinstpath, trueval); + } + else if(strieql(key, "IMPORTSOUP")) + cmdlineimportsoup = true; + break; + case 'M': + disablesound = (*val == '-') ? false : true; + break; + case 'N': + if(strieql(key, "NOSCAN")) + cmdlinenoscan = true; + else + cmdlinesharemode = SH_COMPAT; + break; + case 'P': + cmdlinepriority = (*val == '-') ? false : true; + break; + case 'Q': + quiet = true; + break; + case 'S': + strcpy(AL.sortspec, val); + break; + case 'T': + cmdlinetimeout = atoi(val); + break; + case 'V': + quiet = false; + veryverbose = (toupper(key[1]) == 'V') ? true : false; + break; + case 'W': + cmdlinewriteareas = (*val == '-') ? false : true; + break; + case 'Y': + cmdlinedebughg = (*val == '-') ? false : true; + break; + #if defined(GFTRK_ENABLE) + case 'X': + __gftrk_statusline = (*val == '-') ? false : true; + break; + case 'Z': + gftrk_set_max = atoi(val); + if(gftrk_set_max == 0) { + cout << "Warning: Invalid parameter for -Z option, fixed." << endl; + gftrk_set_max = 1; + } + break; + #endif + } + } + else { + keybuf += val; + keybuf += ' '; + } +} + + +// ------------------------------------------------------------------ + +static void ReadEcholists() { + + Echo* echoin = (Echo*)throw_calloc(1, sizeof(Echo)); + + // Read the import taglist + FILE* fp = fsopen(AddPath(CFG->areapath, CFG->semaphore.importlist), "rt", CFG->sharemode); + + if(fp) { + char buf[256]; + int echonums = 0; + update_statusline(LNG->ReadingEcholist); + while(fgets(buf, sizeof(buf), fp)) { + if(not strblank(buf)) { + echonums++; + echoin = (Echo*)throw_realloc(echoin, (echonums+2)*sizeof(Echo)); + strcpy(echoin[echonums-1], strtrim(strsetsz(buf, sizeof(Echo)-1))); + } + } + *echoin[echonums] = 0; // Mark end + fclose(fp); + } + + // Mark the areas from the import taglist + for(uint n=0; nechoid()); + int x = SearchTaglist(echoin, buf); + if(*echoin[x]) + AL[n]->set_marked(true); + } + + throw_free(echoin); +} + + +// ------------------------------------------------------------------ + +static void ReadEscsets() { + + FILE* fp; + + vector::iterator x; + int n; + for(n = 0, x = CFG->xlatescset.begin(); x != CFG->xlatescset.end(); x++, n++) { + if(strieql(x->imp, "Composed")) { + fp = fsopen(AddPath(CFG->goldpath, CFG->xlatged), "rb", CFG->sharemode); + if(fp) { + CompTable = (Esc*)throw_realloc(CompTable, sizeof(Esc)); + fseek(fp, ((long)CFG->xlatcharset.size()*(long)sizeof(Chs)) + ((long)n*(long)sizeof(Esc)), SEEK_SET); + fread(CompTable, sizeof(Esc), 1, fp); + CompTP = CompTable->t; + fclose(fp); + } + } + else if(strieql(x->imp, "I51")) { + fp = fsopen(AddPath(CFG->goldpath, CFG->xlatged), "rb", CFG->sharemode); + if(fp) { + I51Table = (Esc*)throw_realloc(I51Table, sizeof(Esc)); + fseek(fp, ((long)CFG->xlatcharset.size()*(long)sizeof(Chs)) + ((long)n*(long)sizeof(Esc)), SEEK_SET); + fread(I51Table, sizeof(Esc), 1, fp); + I51TP = I51Table->t; + fclose(fp); + } + } + else if(strieql(x->imp, "MNEMONIC")) { + fp = fsopen(AddPath(CFG->goldpath, CFG->xlatged), "rb", CFG->sharemode); + if(fp) { + MNETable = (Esc*)throw_realloc(MNETable, sizeof(Esc)); + fseek(fp, ((long)CFG->xlatcharset.size()*(long)sizeof(Chs)) + ((long)n*(long)sizeof(Esc)), SEEK_SET); + fread(MNETable, sizeof(Esc), 1, fp); + MNETP = MNETable->t; + fclose(fp); + } + } + } +} + + +// ------------------------------------------------------------------ + +static void ReadAddrMacros() { + + FILE* fp; + char* ptr; + char buf[256], path[GMAXPATH]; + + ptr = getenv("FD"); + if(ptr) + AddBackslash(strcpy(path, ptr)); + else + strcpy(path, CFG->goldpath); + + MakePathname(CFG->namesfile, path, CFG->namesfile); + + if(fexist(CFG->namesfile)) { + fp = fsopen(CFG->namesfile, "rt", CFG->sharemode); + if(fp) { + update_statusline(LNG->ReadingAddrMacros); + while(fgets(buf, sizeof(buf), fp)) { + strbtrim(buf); + if(*buf != ';' and *buf) + CfgAddressmacro(buf); + } + fclose(fp); + } + } +} + + +// ------------------------------------------------------------------ + +static void kbputc_(char c) { + + kbput((gkey)((scancode(c) << 8) | c)); +} + + +// ------------------------------------------------------------------ + +static void kbputstr(const char* buf) { + + gkey xkey; + int n, x; + + x = strlen(buf); + + for(n=0; n", __gver_vendor_name__, + __gver_vendor_fido__, + __gver_vendor_email__); + wcenters(MAXROW-9, C_BRAGW, buf); + sprintf(buf, "Compiled on %s %s", __gver_date__, __gver_time__); + wcenters(MAXROW-8, C_BRAGW, buf); + + update_statusline(LNG->Initializing); +} + + +// ------------------------------------------------------------------ + +static bool ExistCfg(char* path, char* file) { + + bool found = fexist(AddPath(path, file)); + if(found) + strcat(path, file); + return found; +} + +// ------------------------------------------------------------------ + +static bool FindCfg(char* path) { + + bool found = false; + + if(!is_dir(path)) { + if(fexist(path)) + return true; + else + return false; + } + AddBackslash(path); + #if defined(__OS2__) + found = ExistCfg(path, "ged2.cfg"); + #elif defined(__WIN32__) + found = ExistCfg(path, "gedw32.cfg"); + #endif + if(not found) + found = ExistCfg(path, "golded.cfg"); + return found; +} + + +// ------------------------------------------------------------------ + +#ifdef __WIN32__ +BOOL WINAPI GoldedCtrlHandler(DWORD dwCtrlType) { + + switch(dwCtrlType) { + case CTRL_BREAK_EVENT: + return true; + case CTRL_CLOSE_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + break; + default: + return false; + } + + Cleanup(); + ExitProcess(errorlevel); + return true; +} +#endif + + +// ------------------------------------------------------------------ +// Initialize defaults and generally get the system up and running + +void Initialize(int argc, char* argv[]) { + + char* ptr; + char* ptr2; + bool dbedit = false; + bool found = false, compiled; + string truepathtmp; + + throw_init(); + #if defined(GTHROW_LOG) + throw_log = &LOG; + #endif + // First inits + tzset(); + // set locale + setlocale(LC_CTYPE, ""); + // and get it's name + char* lc = setlocale(LC_CTYPE, ""); + if(lc and not (strstr(lc, "German_") or strstr(lc, "Polish_"))) + right_alt_same_as_left = true; + #if defined(GUTLOS_FUNCS) + g_init_os(1); + #endif + srand((unsigned)time(NULL)); + + // Display startup banner + cout << __gver_longpid__ << endl; + + // Check environment commandline + ptr = getenv("GEDCMD"); + if(ptr) { + ptr = strskip_wht(ptr); + if(*ptr) { + char *v = throw_strdup(ptr); + ptr2 = v; + for(;;) { + getkeyval(&ptr, &ptr2); + if(*ptr) + InitCmdline(ptr); + else + break; + } + throw_free(v); + } + } + + // Check if we have been renamed to replace the D'Bridge Editor + if(striinc("DBEDIT.EXE", argv[0])) { + for(int a=1; a 1 and not dbedit) { + for(int i = 1; i < argc; i++) { + char *v = throw_strdup(argv[i]); + InitCmdline(v); + throw_free(v); + } + } + + // Print commandline help and exit if requested + if(cmdlinehelp) { + + cout << + "Copyright (C) 1990-1999 Odinn Sorensen" << endl << + "Copyright (C) 1999-2000 Alexander S. Aganichev" << endl << + "-------------------------------------------------------------------------------" << endl << + endl << + "Invocation: " << argv[0] << " [-options] [keystacking]" << endl << + endl << + "-C Use a different configuration file." << endl << + "-D Disable old obsolete configuration keywords." << endl << + "-E Start directly in the specified mail area." << endl << + "-EXPORTSOUP Export SOUP packets during startup." << endl << + "-F or -FF Force recompile of most (or all with -FF) configuration files." << endl << + "-INSTALL[=path] Start the quick install procedure. Look in path, if given." << endl << + "-IMPORTSOUP Import SOUP packets during startup." << endl << + "-M Mute sounds. Disables all noises in GoldED+." << endl << + "-N Disable share-compatible file opens during startup." << endl << + "-NOSCAN Temporarily disable area scan during startup." << endl << + #if defined(GUTLOS_FUNCS) and not defined(__MSDOS__) + "-P Increase program priority to run faster." << endl << + #endif + "-S Sorts all mail areas according to the sort specs." << endl << + "-T Set a timeout value. GoldED+ will auto-exit after timeout." << endl << + "-V or -VV Verbose or Very verbose (-VV) config compile. Use -VV to debug." << endl << + "-W Write a GOLDAREA.INC file with AREADEF's of all mail areas." << endl << + "-X, -Y, -Z Reserved for debugging purposes." << endl << + endl << + "Any non-option parameter is stuffed into the keyboard buffer." << endl; + + exit(0); + } + + gvid = new GVid; + throw_new(gvid); + CfgInit(); + GFTrkInit(gftrk_set_max); + + // Register exit cleanup functions + atexit(Cleanup); + signal(SIGINT, SIG_IGN); + + #ifdef __WIN32__ + SetConsoleCtrlHandler(GoldedCtrlHandler, true); + #endif + + if(*cmdlinecfg) + found = true; + + if(not found) { + + // Look for configfilename in the environment + #if defined(__OS2__) + ptr = getenv("GED2"); + #elif defined(__WIN32__) + ptr = getenv("GEDW32"); + #else + ptr = NULL; + #endif + if(not(ptr and *ptr)) + ptr = getenv("GOLDED"); + if(not(ptr and *ptr)) + ptr = getenv("GED"); + if(ptr and *ptr) { + strxcpy(cmdlinecfg, ptr, sizeof(cmdlinecfg)); + found = FindCfg(cmdlinecfg); + } + + // Get it in current directory + if(not found) { + getcwd(cmdlinecfg, sizeof(cmdlinecfg)); + found = FindCfg(cmdlinecfg); + } + + // Get it where the the .EXE file is + if(not found) { + extractdirname(cmdlinecfg, argv[0]); + found = FindCfg(cmdlinecfg); + + // If we still could not find config name... + if(not found) + strcat(cmdlinecfg, "golded.cfg"); + } + } + extractdirname(CFG->goldpath, cmdlinecfg); + truepathtmp = CFG->goldpath; + maketruepath(truepathtmp); + strxcpy(CFG->goldpath, truepathtmp.c_str(), sizeof(CFG->goldpath)-1); + strxmerge(CFG->goldpath, sizeof(Path), truepathtmp.c_str(), "/", NULL); + strxmerge(CFG->goldcfg, sizeof(Path), CFG->goldpath, CleanFilename(cmdlinecfg), NULL); + + // Call install detect procedure + if(cmdlineinstall) + InstallDetect(cmdlineinstpath); + + if(not fexist(CFG->goldcfg)) { + cout << "*** Cannot start: " << CFG->goldcfg << " not found! ***" << endl; + errorlevel = EXIT_NONAME; + exit(0); + } + + // Read/compile the config files + compiled = ReadGoldedCfg(cmdlineforce); + + // Call install finish procedure + if(cmdlineinstall) { + if(InstallFinish()) { + cout << "*** INSTALL NOT COMPLETED ***" << endl; + remove(CFG->goldcfg); + errorlevel = EXIT_NONAME; + exit(0); + } + } + + HeaderView = new GMsgHeaderView; + throw_new(HeaderView); + BodyView = new GMsgBodyView; + throw_new(BodyView); + + if((CFG->screensize == 50) and (gvid->adapter & V_EGA)) + CFG->screensize = 43; + + #if defined(GUTLOS_FUNCS) + g_init_title(CFG->tasktitle, CFG->titlestatus); + g_set_ostitle_name(CFG->tasktitle, 1); + g_set_osicon(); + if(cmdlinepriority) + g_increase_priority(); + #endif + + // Mouse support + #ifdef GOLD_MOUSE + if(CFG->mouse) { + gmou.Init(); + gmou.SetLevel(GMOU_LEVEL_CURS); + } + #endif + + // Start the log + LOG.open(CFG->logfile, __gver_longpid__, __gver_shortlogname__, CFG->logformat); + + // Read/compile various configs + compiled |= ReadLangCfg(cmdlineforce); + compiled |= ReadKeysCfg(cmdlineforce); + compiled |= ReadHelpCfg(cmdlineforce); + + // Initialize sound system + InitSound(); + + // Handle extended keyboard + if(not CFG->switches.get(keybext)) + gkbd.extkbd = CFG->switches.get(keybext); + + // Report detected multitasker + if(not quiet) { + if(gmtsk.detected) + cout << "* Running under " << gmtsk.name << "." << endl; + } + + if(cfgerrors) { + cout << "* Total CFG errors found: " << cfgerrors + << ". Press almost any key to continue." << endl; + clearkeys(); + kbclear(); + kbxget(); + } + + if(CFG->switches.get(keybclear)) { + clearkeys(); + kbclear(); + if(*CFG->keybstack) // The config keys + kbputstr(CFG->keybstack); + } + else if(not keybuf.empty()) { // The commandline keys + kbputstr(keybuf.c_str()); + keybuf.erase(); + } else if(*CFG->keybstack) // The config keys + kbputstr(CFG->keybstack); + + fieldupd = EDIT->FieldClear() ? 2 : 1; + + vposget(&gvid->orig.cursor.row, &gvid->orig.cursor.column); + + #ifndef __UNIX__ + oldscreen = vsave(); + #endif + + if(CFG->screensize > 0xFF) { + gvid->setmode(CFG->screensize >> 8); // Set video mode + } + else if(CFG->screensize) { + gvid->setrows(CFG->screensize); // Just set rows + } + + gvid->setintensity(CFG->intensecolors); + + if(C_BACKB != 0) + gvid->setoverscan(C_BACKB); + + vcurhide(); + + if(CFG->screenmaxrow >= 10) + MAXROW = CFG->screenmaxrow; + + if(CFG->screenmaxcol >= 80) + MAXCOL = CFG->screenmaxcol; + + CFG->dispmargin = CFG->cfgdispmargin; + if(CFG->dispmargin <= 0) + CFG->dispmargin += MAXCOL; + + if(CFG->dispmargin > MAXCOL) + CFG->dispmargin = MAXCOL; + + CFG->quotemargin = CFG->cfgquotemargin; + if(CFG->quotemargin <= 0) + CFG->quotemargin += MAXCOL; + + if(EDIT->QuoteMargin() <= 0) + EDIT->QuoteMargin(EDIT->QuoteMargin()+MAXCOL); + + #ifdef __MSDOS__ + if(CFG->switches.get(screenusebios)) + gvid->setdevice(GVID_BIO); + else + gvid->setdevice(GVID_DMA); + #endif + + // Set palette if changes were specified + if(CFG->screenpalette[16]) + gvid->setpalette(CFG->screenpalette); + + // Set window opening style + wsetstyle(STYLE_NORMAL); + + // If keyboard polling is enabled + if(CFG->keybmode == KEYB_POLL) { + + // Switch to keyboard polling instead of blocking + gkbd.polling = true; + gkbd.tickinterval = 5; // Tick twice per second + gkbd.tickvalue = gclock(); // Reset starting tick + kbdsettickfunc(update_statuslines); + } + + inforow = ((MAXROW-1)/2)+6; + + bool areasdefined = false; + + // Do checking for an area and unknown aka's in area + // config at once. + for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++) { + if(not (*AL.item)->isseparator()) + areasdefined = true; + + if(not CFG->aka.empty() and (not (*AL.item)->aka().valid())) + (*AL.item)->set_aka(CFG->aka[0].addr); + } + + if(not areasdefined) { + LOG.ErrConfig(); + LOG.printf("! There do not seem to be any mail areas defined."); + LOG.printf("+ Advice: Check your setup of mail areas."); + ConfigErrorExit(); + } + + if(CFG->username.empty()) { + LOG.ErrConfig(); + LOG.printf("! There do not seem to be any USERNAME's defined."); + LOG.printf("+ Advice: Check your setup of USERNAME's."); + ConfigErrorExit(); + } + + if(CFG->cmdkey.empty()) { + LOG.ErrConfig(); + LOG.printf("! There do not seem to be any command keys defined."); + LOG.printf("+ Advice: Check your key setup in goldkeys.cfg."); + ConfigErrorExit(); + } + + if(CFG->origin.empty()) { + static char orig[] = ""; + CfgOrigin(orig); + } + + w_back(); // Open a nice background window + w_brag(); // Display Brag Window + + HandleGEvent(EVTT_STARTUP); + + // Write the binary config if any of the cfgs were compiled. + if(compiled) + WriteGoldGed(); + + // Override timeout from commandline + if(cmdlinetimeout != -1) + CFG->timeout = cmdlinetimeout; + + // Adjust header item sizes if negative + if(CFG->disphdrnameset.pos < 0) CFG->disphdrnameset.pos += MAXCOL; + if(CFG->disphdrnodeset.pos < 0) CFG->disphdrnodeset.pos += MAXCOL; + if(CFG->disphdrdateset.pos < 0) CFG->disphdrdateset.pos += MAXCOL; + if(CFG->disphdrnameset.len < 0) CFG->disphdrnameset.len += MAXCOL; + if(CFG->disphdrnodeset.len < 0) CFG->disphdrnodeset.len += MAXCOL; + if(CFG->disphdrdateset.len < 0) CFG->disphdrdateset.len += MAXCOL; + + if(EDIT->HdrNamePos() < 0) EDIT->HdrNamePos(EDIT->HdrNamePos()+MAXCOL); + if(EDIT->HdrNameLen() < 0) EDIT->HdrNameLen(EDIT->HdrNameLen()+MAXCOL); + if(EDIT->HdrNodePos() < 0) EDIT->HdrNodePos(EDIT->HdrNodePos()+MAXCOL); + if(EDIT->HdrNodeLen() < 0) EDIT->HdrNodeLen(EDIT->HdrNodeLen()+MAXCOL); + + // Set default marks names + AL.SetDefaultMarks(); + + // Read the lastreads from the last session + if(CFG->switches.get(areakeeplast)) + AL.ReadGoldLast(); + + // Setup start echo + if(not *stecho) + strcpy(stecho, CFG->areastart); + + // Sort the areas + if(*AL.sortspec) + strcpy(CFG->arealistsort, AL.sortspec); + AL.Sort(); + + // Write GOLDAREA.INC if told + if(cmdlinewriteareas) + AL.WriteAreaDef(AddPath(CFG->goldpath, "goldarea.inc")); + + // Get the global max length of echoids (for the arealist) + extern int arealistnumgrps; + extern int areaswithgroupid; + for(uint n=0; nechoid()); + if(echoid_width < _tmp) + echoid_width = _tmp; + if(AL[n]->groupid()) { + areaswithgroupid++; + if(AL[n]->groupid() & 0x8000u) + arealistnumgrps = true; + } + } + if(CFG->arealistechomax) { + if(CFG->arealistechomax > (int)(sizeof(Echo)-1)) + CFG->arealistechomax = sizeof(Echo)-1; + if(CFG->arealistechomax < 0) + echoid_width += CFG->arealistechomax; + else + echoid_width = CFG->arealistechomax; + } + if(areaswithgroupid and CFG->switches.get(arealistgroupid)) + groupid_width = arealistnumgrps ? 3 : 1; + + int spaces = 0; + bool area_found = false; + bool marked_found = false; + bool desc_found = false; + bool count_found = false; + bool pmark_found = false; + bool unread_found = false; + bool changed_found = false; + bool echoid_found = false; + bool groupid_found = false; + for(int pass=1; pass<=2; pass++) { + if(pass == 2) { + if(not area_found) area_width = 0; + if(not marked_found) marked_width = 0; + if(not desc_found) desc_width = 0; + if(not count_found) count_width = 0; + if(not pmark_found) pmark_width = 0; + if(not unread_found) unread_width = 0; + if(not changed_found) changed_width = 0; + if(not echoid_found) echoid_width = 0; + if(not groupid_found) groupid_width = 0; + if(desc_width == -1) { + desc_width = + MAXCOL - 2 - spaces - area_width - marked_width - + count_width - pmark_width - unread_width - changed_width - + echoid_width - groupid_width; + } + } + int pos = 0; + char* p = CFG->arealistformat; + while(*p) { + char c = (char)toupper(*p); + char d = *(++p); + int w = atoi(p); + while(isdigit(*p)) + p++; + if(pass == 1) { + if(isalpha(c)) { + switch(c) { + case 'A': area_found = true; if(isdigit(d)) area_width = w; break; + case 'M': marked_found = true; if(isdigit(d)) marked_width = w; break; + case 'D': desc_found = true; if(isdigit(d)) desc_width = w; break; + case 'C': count_found = true; if(isdigit(d)) count_width = w; break; + case 'P': pmark_found = true; if(isdigit(d)) pmark_width = w; break; + case 'U': unread_found = true; if(isdigit(d)) unread_width = w; break; + case 'N': changed_found = true; if(isdigit(d)) changed_width = w; break; + case 'E': echoid_found = true; if(isdigit(d)) echoid_width = w; break; + case 'G': groupid_found = true; if(isdigit(d)) groupid_width = w; break; + } + } + else { + spaces++; + } + } + else { + switch(c) { + case 'A': area_pos = pos; pos += area_width; break; + case 'M': marked_pos = pos; pos += marked_width; break; + case 'D': desc_pos = pos; pos += desc_width; break; + case 'C': count_pos = pos; pos += count_width; break; + case 'P': pmark_pos = pos; pos += pmark_width; break; + case 'U': unread_pos = pos; pos += unread_width; break; + case 'N': changed_pos = pos; pos += changed_width; break; + case 'E': echoid_pos = pos; pos += echoid_width; break; + case 'G': groupid_pos = pos; pos += groupid_width; break; + default: pos++; + } + } + } + } + + update_statuslines(); + ReadEcholists(); // Read the Confmail compatible echotag lists + update_statuslines(); + ReadAddrMacros(); // Read the address macro file + update_statuslines(); + ReadEscsets(); // Read the escape tables + update_statuslines(); + + // Initialize the messagebases + update_statuslinef(LNG->LockShareCap, LNG->Checking); + WideLog = &LOG; + WideDebug = cmdlinedebughg; + WideMsgSize = EDIT->MsgSize(); + WideCanLock = CFG->sharemode ? TestLockPath(CFG->goldpath) : false; + WideSharemode = CFG->sharemode; + WideUsernames = CFG->username.size(); + WideUsername = new const char*[WideUsernames]; + vector::iterator i; + int w; + for(w = 0, i = CFG->username.begin(); w < WideUsernames; w++, i++) + WideUsername[w] = i->name; + WidePersonalmail = CFG->personalmail; + WideDispsoftcr = CFG->switches.get(dispsoftcr); + if(AL.msgbases & MT_FIDO) { + update_statuslinef("%s Fido", LNG->Checking); + FidoInit(CFG->fidolastread, CFG->switches.get(fidohwmarks), CFG->switches.get(fidonullfix), CFG->fidouserno, CFG->squishuserpath); + } + #ifndef GMB_NOEZY + if(AL.msgbases & MT_EZYCOM) { + update_statuslinef("%s Ezycom", LNG->Checking); + EzycomInit(CFG->ezycom.msgbasepath, CFG->ezycom.userbasepath, CFG->ezycomuserno); + } + #endif + #ifndef GMB_NOGOLD + if(AL.msgbases & MT_GOLDBASE) { + update_statuslinef("%s Goldbase", LNG->Checking); + GoldInit(CFG->goldbasepath, CFG->goldbasesyspath, CFG->goldbaseuserno); + } + #endif + #ifndef GMB_NOHUDS + if(AL.msgbases & MT_HUDSON) { + update_statuslinef("%s Hudson", LNG->Checking); + HudsInit(CFG->hudsonpath, CFG->hudsonsyspath, CFG->hudsonuserno, CFG->hudsonsizewarn, CFG->ra2usersbbs); + } + #endif + #ifndef GMB_NOJAM + if(AL.msgbases & MT_JAM) { + update_statuslinef("%s JAM", LNG->Checking); + JamInit(CFG->jampath, CFG->switches.get(jamharddelete)); + } + #endif + #ifndef GMB_NOPCB + if(AL.msgbases & MT_PCBOARD) { + update_statuslinef("%s PCBoard", LNG->Checking); + PcbInit(CFG->pcboardpath, CFG->pcboarduserno); + } + #endif + #ifndef GMB_NOSQSH + if(AL.msgbases & MT_SQUISH) { + update_statuslinef("%s Squish", LNG->Checking); + SquishInit(CFG->squishuserpath, CFG->squishuserno, CFG->switches.get(squishdirect), true, CFG->squishscan); + } + #endif + #ifndef GMB_NOWCAT + if(AL.msgbases & MT_WILDCAT) { + update_statuslinef("%s WildCat!", LNG->Checking); + WCatInit(CFG->wildcatuserno); + } + #endif + #ifndef GMB_NOXBBS + if(AL.msgbases & MT_ADEPTXBBS) { + update_statuslinef("%s AdeptXBBS", LNG->Checking); + XbbsInit(CFG->adeptxbbspath, CFG->adeptxbbsuserno); + } + #endif + #ifndef GMB_NOSMB + if(AL.msgbases & MT_SMB) { + update_statuslinef("%s Synchronet", LNG->Checking); + SMBInit(); + } + #endif + update_statuslinef("..."); + + // Delete the D'Bridge "mail waiting" semaphore files + if(dbedit) { + remove(AddPath(CFG->areapath, "DBRIDGE.NMW")); + remove(AddPath(CFG->areapath, "DBRIDGE.EMW")); + } + + // Unlink windows + wunlink(W_READ); + + THROW_CHECK(); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gekeys.h b/golded3/gekeys.h new file mode 100644 index 0000000..100e50a --- /dev/null +++ b/golded3/gekeys.h @@ -0,0 +1,361 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Keyboard system. +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ +// +// The keyboard system in GoldED +// +// Keycodes in the range 0x0000-0xFDFF are normal keys. +// Keycodes in the range 0xFE00-0xFE7F are macro numbers. +// Keycodes in the range 0xFE80-0xFFFE are command numbers. +// +// The global variable cmdkeys holds a list of all commands and +// the keys or macro numbers, sorted by key/macro. +// +// The global variable macros holds all the macros, sorted by key. +// The global variable totmacros contains the total number of macros. +// +// The macro list is searched first, then the command list, thus +// allowing macros that override commands. +// +// ------------------------------------------------------------------ + +const gkey KK_Auto = 0xFD00; +const gkey KK_Macro = 0xFE00; +const gkey KK_AreaMacro = 0xFE01; +const gkey KK_EditMacro = 0xFE02; +const gkey KK_FileMacro = 0xFE03; +const gkey KK_ListMacro = 0xFE04; +const gkey KK_NodeMacro = 0xFE05; +const gkey KK_ReadMacro = 0xFE06; + +const gkey KK_Commands = 0xFE80; +const gkey KK_ExternUtil01 = 0xFE81; +const gkey KK_ExternUtil02 = 0xFE82; +const gkey KK_ExternUtil03 = 0xFE83; +const gkey KK_ExternUtil04 = 0xFE84; +const gkey KK_ExternUtil05 = 0xFE85; +const gkey KK_ExternUtil06 = 0xFE86; +const gkey KK_ExternUtil07 = 0xFE87; +const gkey KK_ExternUtil08 = 0xFE88; +const gkey KK_ExternUtil09 = 0xFE89; +const gkey KK_ExternUtil10 = 0xFE8A; +const gkey KK_ExternUtil11 = 0xFE8B; +const gkey KK_ExternUtil12 = 0xFE8C; +const gkey KK_ExternUtil13 = 0xFE8D; +const gkey KK_ExternUtil14 = 0xFE8E; +const gkey KK_ExternUtil15 = 0xFE8F; +const gkey KK_ExternUtil16 = 0xFE90; +const gkey KK_ExternUtil17 = 0xFE91; +const gkey KK_ExternUtil18 = 0xFE92; +const gkey KK_ExternUtil19 = 0xFE93; +const gkey KK_ExternUtil20 = 0xFE94; +const gkey KK_ExternUtil21 = 0xFE95; +const gkey KK_ExternUtil22 = 0xFE96; +const gkey KK_ExternUtil23 = 0xFE97; +const gkey KK_ExternUtil24 = 0xFE98; +const gkey KK_ExternUtil25 = 0xFE99; + +const gkey KK_AreaAbort = 0xFEA0; +const gkey KK_AreaAskExit = 0xFEA1; +const gkey KK_AreaBoardnos = 0xFEA2; +const gkey KK_AreaCatchUp = 0xFEA3; +const gkey KK_AreaDosShell = 0xFEA4; +const gkey KK_AreaDropMsgMarks = 0xFEA5; +const gkey KK_AreaGotoFirst = 0xFEA6; +const gkey KK_AreaGotoLast = 0xFEA7; +const gkey KK_AreaGotoNext = 0xFEA8; +const gkey KK_AreaGotoPrev = 0xFEA9; +const gkey KK_AreaHeat = 0xFEAA; +const gkey KK_AreaInfo = 0xFEAB; +const gkey KK_AreaJump = 0xFEAC; +const gkey KK_AreaJumpNextMatch = 0xFEAD; +const gkey KK_AreaMainMenu = 0xFEAE; +const gkey KK_AreaMenu = 0xFEAF; +const gkey KK_AreaQuitNow = 0xFEB0; +const gkey KK_AreaScan = 0xFEB1; +const gkey KK_AreaScanPM = 0xFEB2; +const gkey KK_AreaSelect = 0xFEB3; +const gkey KK_AreaSelectMarks = 0xFEB4; +const gkey KK_AreaSoundkill = 0xFEB5; +const gkey KK_AreaToggle = 0xFEB6; +const gkey KK_AreaTouchNetscan = 0xFEB7; +const gkey KK_AreaWriteGoldlast = 0xFEB8; +const gkey KK_AreaZap = 0xFEB9; +const gkey KK_AreaShowDel = 0xFEBA; + +const gkey KK_EditAbort = 0xFEC0; +const gkey KK_EditAnchor = 0xFEC1; +const gkey KK_EditAskExit = 0xFEC2; +const gkey KK_EditClearDeleteBuf = 0xFEC3; +const gkey KK_EditClearPasteBuf = 0xFEC4; +const gkey KK_EditCopy = 0xFEC5; +const gkey KK_EditCopyAbove = 0xFEC6; +const gkey KK_EditCopyAboveChar = 0xFEC7; +const gkey KK_EditCut = 0xFEC8; +const gkey KK_EditDelChar = 0xFEC9; +const gkey KK_EditDeleteEOL = 0xFECA; +const gkey KK_EditDelLeft = 0xFECB; +const gkey KK_EditDelLine = 0xFECC; +const gkey KK_EditDelLtWord = 0xFECD; +const gkey KK_EditDelRtWord = 0xFECE; +const gkey KK_EditDosShell = 0xFECF; +const gkey KK_EditDupLine = 0xFED0; +const gkey KK_EditExitMsg = 0xFED1; +const gkey KK_EditExportText = 0xFED2; +const gkey KK_EditGoBegLine = 0xFED3; +const gkey KK_EditGoBotLine = 0xFED4; +const gkey KK_EditGoBotMsg = 0xFED5; +const gkey KK_EditGoDown = 0xFED6; +const gkey KK_EditGoEOL = 0xFED7; +const gkey KK_EditGoLeft = 0xFED8; +const gkey KK_EditGoPgDn = 0xFED9; +const gkey KK_EditGoPgUp = 0xFEDA; +const gkey KK_EditGoRight = 0xFEDB; +const gkey KK_EditGoTopLine = 0xFEDC; +const gkey KK_EditGoTopMsg = 0xFEDD; +const gkey KK_EditGoUp = 0xFEDE; +const gkey KK_EditGoWordLeft = 0xFEDF; +const gkey KK_EditGoWordRight = 0xFEE0; +const gkey KK_EditHeader = 0xFEE1; +const gkey KK_EditImportQuotebuf = 0xFEE2; +const gkey KK_EditImportText = 0xFEE3; +const gkey KK_EditKillQuotes = 0xFEE4; +const gkey KK_EditLoadFile = 0xFEE5; +const gkey KK_EditLookupCursor = 0xFEE6; +const gkey KK_EditLookupDest = 0xFEE7; +const gkey KK_EditLookupOrig = 0xFEE8; +const gkey KK_EditMainMenu = 0xFEE9; +const gkey KK_EditMenu = 0xFEEA; +const gkey KK_EditNewline = 0xFEEB; +const gkey KK_EditPaste = 0xFEEC; +const gkey KK_EditQuitNow = 0xFEED; +const gkey KK_EditReflow = 0xFEEE; +const gkey KK_EditSaveFile = 0xFEEF; +const gkey KK_EditSaveMsg = 0xFEF0; +const gkey KK_EditSoundkill = 0xFEF1; +const gkey KK_EditSpellCheck = 0xFEF2; +const gkey KK_EditTab = 0xFEF3; +const gkey KK_EditTabReverse = 0xFEF4; +const gkey KK_EditToggleCase = 0xFEF5; +const gkey KK_EditToggleInsert = 0xFEF6; +const gkey KK_EditToLower = 0xFEF7; +const gkey KK_EditToUpper = 0xFEF8; +const gkey KK_EditUnDelete = 0xFEF9; +const gkey KK_EditZapQuoteBelow = 0xFEFA; +const gkey KK_EditBlockRight = 0xFEFB; +const gkey KK_EditBlockLeft = 0xFEFC; +const gkey KK_EditBlockUp = 0xFEFD; +const gkey KK_EditBlockDown = 0xFEFE; +const gkey KK_EditBlockHome = 0xFEFF; +const gkey KK_EditBlockEnd = 0xFF00; +const gkey KK_EditBlockPgDn = 0xFF01; +const gkey KK_EditBlockPgUp = 0xFF02; +const gkey KK_EditDelete = 0xFF03; +const gkey KK_EditUndo = 0xFF04; + +const gkey KK_FileAbort = 0xFF10; +const gkey KK_FileAskExit = 0xFF11; +const gkey KK_FileDosShell = 0xFF12; +const gkey KK_FileGotoFirst = 0xFF13; +const gkey KK_FileGotoLast = 0xFF14; +const gkey KK_FileGotoNext = 0xFF15; +const gkey KK_FileGotoPrev = 0xFF16; +const gkey KK_FileMark = 0xFF17; +const gkey KK_FileMarkAll = 0xFF18; +const gkey KK_FileMenu = 0xFF19; +const gkey KK_FileQuitNow = 0xFF1A; +const gkey KK_FileSelect = 0xFF1B; +const gkey KK_FileToggleMark = 0xFF1C; +const gkey KK_FileToggleMarkAll = 0xFF1D; +const gkey KK_FileUnMark = 0xFF1E; +const gkey KK_FileUnMarkAll = 0xFF1F; + +const gkey KK_ListAbort = 0xFF20; +const gkey KK_ListAskExit = 0xFF21; +const gkey KK_ListDosShell = 0xFF22; +const gkey KK_ListGotoBookMark = 0xFF23; +const gkey KK_ListGotoFirst = 0xFF24; +const gkey KK_ListGotoLast = 0xFF25; +const gkey KK_ListGotoNext = 0xFF26; +const gkey KK_ListGotoPrev = 0xFF27; +const gkey KK_ListMainMenu = 0xFF28; +const gkey KK_ListMarkingOptions = 0xFF29; +const gkey KK_ListMenu = 0xFF2A; +const gkey KK_ListQuitNow = 0xFF2B; +const gkey KK_ListSelect = 0xFF2C; +const gkey KK_ListToggleBookMark = 0xFF2D; +const gkey KK_ListToggleDate = 0xFF2E; +const gkey KK_ListToggleMark = 0xFF2F; +const gkey KK_ListToggleWideSubj = 0xFF30; + +const gkey KK_NodeAbort = 0xFF40; +const gkey KK_NodeAskExit = 0xFF41; +const gkey KK_NodeDosShell = 0xFF42; +const gkey KK_NodeGotoFirst = 0xFF43; +const gkey KK_NodeGotoLast = 0xFF44; +const gkey KK_NodeGotoNext = 0xFF45; +const gkey KK_NodeGotoPrev = 0xFF46; +const gkey KK_NodeMainMenu = 0xFF47; +const gkey KK_NodeMenu = 0xFF48; +const gkey KK_NodeQuitNow = 0xFF49; +const gkey KK_NodeSelect = 0xFF4A; + +const gkey KK_ReadAddressbookAdd = 0xFF50; +const gkey KK_ReadAskExit = 0xFF51; +const gkey KK_ReadChangeAka = 0xFF52; +const gkey KK_ReadChangeAttrs = 0xFF53; +const gkey KK_ReadChangeCharsIn = 0xFF54; +const gkey KK_ReadChangeCharsOut = 0xFF55; +const gkey KK_ReadChangeMsg = 0xFF56; +const gkey KK_ReadChangeOrigin = 0xFF57; +const gkey KK_ReadChangeTagline = 0xFF58; +const gkey KK_ReadChangeTemplate = 0xFF59; +const gkey KK_ReadChangeUsername = 0xFF5A; +const gkey KK_ReadChangeXlatImport = 0xFF5B; +const gkey KK_ReadCommentMsg = 0xFF5C; +const gkey KK_ReadCopyMoveForward = 0xFF5D; +const gkey KK_ReadDecreaseMargin = 0xFF5E; +const gkey KK_ReadDeleteMsg = 0xFF5F; +const gkey KK_ReadDosShell = 0xFF60; +const gkey KK_ReadExternUtilMenu = 0xFF61; +const gkey KK_ReadFidoRenumber = 0xFF62; +const gkey KK_ReadFileRequest = 0xFF63; +const gkey KK_ReadFindAll = 0xFF64; +const gkey KK_ReadFindHeader = 0xFF65; +const gkey KK_ReadGotoBookMark = 0xFF66; +const gkey KK_ReadGotoFirstMsg = 0xFF67; +const gkey KK_ReadGotoLastMsg = 0xFF68; +const gkey KK_ReadGotoMsgno = 0xFF69; +const gkey KK_ReadGotoNextArea = 0xFF6A; +const gkey KK_ReadGotoNextMsg = 0xFF6B; +const gkey KK_ReadGotoNextUnread = 0xFF6C; +const gkey KK_ReadGotoPrevArea = 0xFF6D; +const gkey KK_ReadGotoPrevMsg = 0xFF6E; +const gkey KK_ReadGotoPrevUnread = 0xFF6F; +const gkey KK_ReadGotoReplies = 0xFF70; +const gkey KK_ReadGotoReply1st = 0xFF71; +const gkey KK_ReadGotoReplyNext = 0xFF72; +const gkey KK_ReadGotoReplyPrev = 0xFF73; +const gkey KK_ReadIncreaseMargin = 0xFF74; +const gkey KK_ReadLookupDest = 0xFF75; +const gkey KK_ReadLookupOrig = 0xFF76; +const gkey KK_ReadMainMenu = 0xFF77; +const gkey KK_ReadMakeUserlist = 0xFF78; +const gkey KK_ReadMarkingOptions = 0xFF79; +const gkey KK_ReadMenu = 0xFF7A; +const gkey KK_ReadMessageList = 0xFF7B; +const gkey KK_ReadMakePathreport = 0xFF7C; +const gkey KK_ReadMoveCommentMsg = 0xFF7D; +const gkey KK_ReadMoveQuoteMsg = 0xFF7E; +const gkey KK_ReadMsgContinue = 0xFF7F; +const gkey KK_ReadMsgEnd = 0xFF80; +const gkey KK_ReadMsgHome = 0xFF81; +const gkey KK_ReadMsgLineDown = 0xFF82; +const gkey KK_ReadMsgLineUp = 0xFF83; +const gkey KK_ReadMsgPgDn = 0xFF84; +const gkey KK_ReadMsgPgUp = 0xFF85; +const gkey KK_ReadNewArea = 0xFF86; +const gkey KK_ReadNewMsg = 0xFF87; +const gkey KK_ReadQuitNow = 0xFF88; +const gkey KK_ReadQuoteBuf = 0xFF89; +const gkey KK_ReadQuoteMsg = 0xFF8A; +const gkey KK_ReadReplyMsg = 0xFF8B; +const gkey KK_ReadSearch = 0xFF8C; +const gkey KK_ReadSoundkill = 0xFF8D; +const gkey KK_ReadStealTagline = 0xFF8E; +const gkey KK_ReadThreadtree = 0xFF8F; +const gkey KK_ReadToggleBookMark = 0xFF90; +const gkey KK_ReadToggleHexdump = 0xFF91; +const gkey KK_ReadToggleHidden = 0xFF92; +const gkey KK_ReadToggleHiddKlud = 0xFF93; +const gkey KK_ReadToggleKludge = 0xFF94; +const gkey KK_ReadToggleMark = 0xFF95; +const gkey KK_ReadToggleMarkRead = 0xFF96; +const gkey KK_ReadTogglePageBar = 0xFF97; +const gkey KK_ReadToggleQuote = 0xFF98; +const gkey KK_ReadToggleRealMsgno = 0xFF99; +const gkey KK_ReadToggleROT13 = 0xFF9A; +const gkey KK_ReadToggleStyles = 0xFF9B; +const gkey KK_ReadToggleTwits = 0xFF9C; +const gkey KK_ReadTouchNetscan = 0xFF9D; +const gkey KK_ReadTouchSemaphore = 0xFF9E; +const gkey KK_ReadUserbase = 0xFF9F; +const gkey KK_ReadUUDecode = 0xFFA0; +const gkey KK_ReadWriteMsg = 0xFFA1; + +const gkey KK_AreaUndefine = 0xFFB0; +const gkey KK_EditUndefine = 0xFFB1; +const gkey KK_FileUndefine = 0xFFB2; +const gkey KK_ListUndefine = 0xFFB3; +const gkey KK_NodeUndefine = 0xFFB4; +const gkey KK_ReadUndefine = 0xFFB5; +const gkey KK_ZzzzLast = 0xFFB6; + + +// ------------------------------------------------------------------ +// Key groups (type of key) + +const int KT_A = 1; // Arealist +const int KT_E = 2; // Editor +const int KT_G = 4; // General (not used) +const int KT_M = 8; // Msg lister +const int KT_N = 16; // Node browser +const int KT_R = 32; // Reader (+ external utils) +const int KT_F = 64; // File browser + + +// ------------------------------------------------------------------ +// Key command + +struct CmdKey { + gkey key; // Associated key or macro number + gkey cmd; // Command number + int type; // Type of key +}; + + +// ------------------------------------------------------------------ +// Macro + +struct Macro { + int type; // Type of key + gkey key; // Associated key + gkey buf[128]; // Actual keys/commands +}; + + +// ------------------------------------------------------------------ + +struct tglobalkey { + word crc_token; + gkey keyval; + word keytype; +}; + +// ------------------------------------------------------------------ + diff --git a/golded3/gelang.h b/golded3/gelang.h new file mode 100644 index 0000000..00894be --- /dev/null +++ b/golded3/gelang.h @@ -0,0 +1,473 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Language pointer structure. +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ +// Language pointer structure + +struct LangGed { + + char* SWSun; // MS_SWSUN + char* SWMon; // MS_SWMON + char* SWTue; // MS_SWTUE + char* SWWed; // MS_SWWED + char* SWThu; // MS_SWTHU + char* SWFri; // MS_SWFRI + char* SWSat; // MS_SWSAT + + char* LWSunday; // MS_LWSUNDAY + char* LWMonday; // MS_LWMONDAY + char* LWTuesday; // MS_LWTUESDAY + char* LWWednesday; // MS_LWWEDNESDAY + char* LWThursday; // MS_LWTHURSDAY + char* LWFriday; // MS_LWFRIDAY + char* LWSaturday; // MS_LWSATURDAY + + char* SMJan; // MS_SMJAN + char* SMFeb; // MS_SMFEB + char* SMMar; // MS_SMMAR + char* SMApr; // MS_SMAPR + char* SMMay; // MS_SMMAY + char* SMJun; // MS_SMJUN + char* SMJul; // MS_SMJUL + char* SMAug; // MS_SMAUG + char* SMSep; // MS_SMSEP + char* SMOct; // MS_SMOCT + char* SMNov; // MS_SMNOV + char* SMDec; // MS_SMDEC + + char* LMJanuary; // MS_LMJANUARY + char* LMFebruary; // MS_LMFEBRUARY + char* LMMarch; // MS_LMMARCH + char* LMApril; // MS_LMAPRIL + char* LMMay; // MS_LMMAY + char* LMJune; // MS_LMJUNE + char* LMJuly; // MS_LMJULY + char* LMAugust; // MS_LMAUGUST + char* LMSeptember; // MS_LMSEPTEMBER + char* LMOctober; // MS_LMOCTOBER + char* LMNovember; // MS_LMNOVEMBER + char* LMDecember; // MS_LMDECEMBER + + char* ImportFile; // ST_IMPORTFILE + char* ImportWhichFile; // WT_IMPORTWHICHFILE + char* ImportTitle; // WT_IMPORTPICK + char* ImportTxt; // WT_IMPORTTXT + char* ImportTxtText; // MI_IMPORTTXTTEXT + char* ImportTxtQuote; // MI_IMPORTTXTQUOTE + char* ImportTxtUue; // MI_IMPORTTXTUUE + char* ImportTxtMime; // MI_IMPORTTXTMIME + char* ImportTxtClip; // MI_IMPORTTXTCLIP + char* ImportTxtXlat; // MI_IMPORTTXTXLAT + char* ImportTxtQuit; // MI_IMPORTTXTQUIT + char* ImportStatus; // ST_IMPORTSTATUS + char* ExportFile; // ST_EXPORTFILE + char* ExportWhatFile; // WT_EXPORTWHATFILE + char* ExportStatus; // ST_EXPORTSTATUS + char* EditStatus; // ST_EDITSTATUS + char* SelectFiles; // ST_SELECTFILES + char* SelectedFiles; // WL_SELECTEDFILES + char* SelectedBytes; // WL_SELECTEDBYTES + char* TotalFiles; // WL_TOTALFILES + char* TotalBytes; // WL_TOTALBYTES + char* ScanningDirectory; // WL_SCANNINGDIRECTORY + char* NoFilesFound; // WL_NOFILESFOUND + char* FilesPressKey; // ST_FILESPRESSKEY + char* Area; // WT_AREA + char* Description; // WT_DESCRIPTION + char* Msgs; // WT_MSGS + char* Last; // WT_LAST + char* EchoID; // WT_ECHOID + char* unread; // ST_UNREAD + char* Scan_Areas; // WT_SCANAREAS + char* Scan_All; // MI_SCANALL + char* Scan_Marked; // MI_SCANMARKED + char* Scan_Current; // MI_SCANCURRENT + char* Scan_Matching; // MI_SCANMATCHING + char* Scan_Unscanned; // MI_SCANUNSCANNED + char* No_Scan; // MI_NOSCAN + char* Heat_Areas; // WT_HEATAREAS + char* Heat_All; // MI_HEATALL + char* Heat_Marked; // MI_HEATMARKED + char* Heat_Current; // MI_HEATCURRENT + char* No_Heat; // MI_NOHEAT + char* Zap_Areas; // WT_ZAPAREAS + char* Zap_All; // MI_ZAPALL + char* Zap_Marked; // MI_ZAPMARKED + char* Zap_Current; // MI_ZAPCURRENT + char* No_Zap; // MI_NOZAP + char* DOS_Shell; // MS_DOS_SHELL + char* ScanningArea; // IL_SCANNINGAREA + char* SearchingFor; // IL_SEARCHINGFOR + char* ReadingMsg; // ST_READINGMSG + char* Outofmem; // ER_OUTOFMEM + char* Hexdumphead; // MS_HEXDUMPHEAD + char* Hexdumptext; // MS_HEXDUMPTEXT + char* Renumbering; // ST_RENUMBERING + char* Locked; // ST_LOCKED + char* Renumbered; // ST_RENUMBERED + char* BlankMsg; // WL_BLANKMSG + char* Wait; // WL_WAIT + char* GenHexdump; // IL_GENHEXDUMP + char* ProcessCC; // ST_PROCESSCC + char* StatusCC; // ST_STATUSCC + char* DestinationCC; // ST_DESTINATIONCC + char* ListCC; // MS_LISTCC + char* DelOrig; // WT_DELORIG + char* DelOrigYes; // MI_DELORIGYES + char* DelOrigNo; // MI_DELORIGNO + char* DropMsg; // WT_DROPMSG + char* DropMsgYes; // MI_DROPMSGYES + char* DropMsgNo; // MI_DROPMSGNO + char* ZoneGate; // WT_ZONEGATE + char* ZoneGateYes; // MI_ZONEGATEYES + char* ZoneGateNo; // MI_ZONEGATENO + char* Quotepct; // ST_QUOTEPCT + char* SaveMsg; // WT_SAVEMSG + char* YesGreat; // MI_YESGREAT + char* Kickit; // MI_KICKIT + char* Continue; // MI_CONTINUE + char* Rot13; // MI_ROT13 + char* AttribS; // MI_ATTRS + char* OriginS; // MI_ORIGS + char* View; // MI_VIEW + char* SelectDestNode; // ST_SELECTDESTNODE + char* AttachFiles; // WT_ATTACHFILES + char* UpdreqFiles; // WT_UPDREQFILES + char* EditHeader; // ST_EDITHEADER + char* MsgOptions; // WT_EDITING + char* InternalEd; // MI_INTERNALED + char* ExternalEd; // MI_EXTERNALED + char* SaveNoEdit; // MI_SAVEMESSAGE + char* AttrO; // MI_ATTRO + char* Template; // MI_TEMPLATE + char* Origin; // MI_ORIGIN + char* QuitMessage; // MI_QUITMESSAGE + char* Templates; // ST_TEMPLATES + char* ChangeTemplate; // WT_CHANGETEMPLATES + char* CarbonCopy; // WT_CARBONCOPY + char* CCProcess; // MI_CCPROCESS + char* CCIgnore; // MI_CCIGNORE + char* CCAttribs; // MI_CCATTRIBS + char* CCListFmt; // MI_CCLISTFMT + char* CCList; // WT_CCLIST + char* CCListKeep; // MI_CCLISTKEEP + char* CCListNames; // MI_CCLISTNAMES + char* CCListVisible; // MI_CCLISTVISIBLE + char* CCListHidden; // MI_CCLISTHIDDEN + char* CCListRemove; // MI_CCLISTREMOVE + char* AttrTitle; // WT_ATTRTITLE + char* AttrPvt; // MI_ATTR01 + char* AttrRcv; // MI_ATTR02 + char* AttrSnt; // MI_ATTR03 + char* AttrCrs; // MI_ATTR04 + char* AttrHld; // MI_ATTR05 + char* AttrFil; // MI_ATTR06 + char* AttrFrq; // MI_ATTR07 + char* AttrUpd; // MI_ATTR08 + char* AttrKS; // MI_ATTR09 + char* AttrKfs; // MI_ATTR10 + char* AttrTfs; // MI_ATTR11 + char* AttrDir; // MI_ATTR12 + char* AttrImm; // MI_ATTR13 + char* AttrLok; // MI_ATTR14 + char* AttrZap; // MI_ATTR15 + char* From; // HD_FROM + char* To; // HD_TO + char* Subj; // HD_SUBJ + char* File; // HD_FILE + char* EmptyMsg; // MS_EMPTYMSG + char* AutoAttachMsg; // MS_AUTOATTACHMSG + char* AutoRequestMsg; // MS_AUTOREQUESTMSG + char* AutoUpdreqMsg; // MS_AUTOUPDREQMSG + char* File_Attach; // WT_FILEATTACH + char* File_Request; // WT_FILEREQUEST + char* File_Updreq; // WT_FILEUPDREQ + char* FileAttaching; // ST_FILEATTACHING + char* FileRequesting; // ST_FILEREQUESTING + char* FileUpdreqing; // ST_FILEUPDREQING + char* ReadMarked; // ST_READMARKED + char* ReadAll; // ST_READALL + char* NoRenum; // ST_NOQRENUM + char* HidingTwit; // MS_HIDINGTWIT + char* Via; // HD_VIA + char* ChangeAttrs; // WT_CHANGEATTRS + char* HeaderText; // WT_HEADERTEXT + char* HeaderOnly; // WT_HEADERONLY + char* NewArea; // WT_NEWAREA + char* ReplyArea; // WT_REPLYAREA + char* CopyArea; // WT_COPYAREA + char* MoveArea; // WT_MOVEAREA + char* ForwardArea; // WT_FORWARDAREA + char* FreqArea; // WT_FREQAREA + char* FreqMenuTitle; // WT_FREQMENUTITLE + char* FreqStat; // ST_FREQSTAT + char* FreqInfoNoFiles; // IL_FREQINFONOFILES + char* Copy; // WT_COPY + char* Move; // WT_MOVE + char* Copying; // WT_COPYING + char* Moving; // WT_MOVING + char* CopyingMsg; // ST_COPYINGMSG + char* MovingMsg; // ST_MOVINGMSG + char* Delete; // WT_DELETE + char* Deleting; // WT_DELETING + char* DeletingMsg; // ST_DELETINGMSG + char* Write; // WT_WRITE + char* WriteMsgs; // WT_WRITEMSGS + char* Writing; // WT_WRITING + char* WritingMsg; // ST_WRITINGMSG + char* WritingFile; // WT_WRITINGFILE + char* WritingPRN; // WT_WRITINGPRN + char* ReadOnlyWarn; // IL_READONLYWARN + char* IsReadOnly; // WT_ISREADONLY + char* ReadOnlyYes; // MI_READONLYYES + char* ReadOnlyNo; // MI_READONLYNO + char* ChangeWarn; // IL_CHANGEWARN + char* Change; // WT_CHANGE + char* ChangeYes; // MI_CHANGEYES + char* ChangeNo; // MI_CHANGENO + char* DeleteThis; // WT_DELETETHIS + char* DeleteYes; // MI_DELETEYES + char* DeleteNo; // MI_DELETENO + char* DeleteNoAsk; // MI_DELETENOASK + char* GotoNext; // WT_GOTONEXT + char* GotoNextYes; // MI_GOTONEXTYES + char* GotoNextNo; // MI_GOTONEXTNO + char* GotoNextNew; // MI_GOTONEXTNEW + char* Forward; // WT_FORWARD + char* ForwardYes; // MI_FORWARDYES + char* ForwardNo; // MI_FORWARDNO + char* Msg; // WT_MSG + char* MsgReal; // WT_MSGREAL + char* FromL; // WT_FROML + char* ToL; // WT_TOL + char* SubjL; // WT_SUBJL + char* MsgLister; // ST_MSGLISTER + char* CopyMoveForward; // ST_COPYMOVEFORWARD + char* SelectAction; // WT_SELECTACTION + char* ForwardMessage; // MI_FORWARDMESSAGE + char* MoveMessage; // MI_MOVEMESSAGE + char* CopyMessage; // MI_COPYMESSAGE + char* QuitCMF; // MI_QUITCMF + char* are; // ST_ARE + char* is; // ST_IS + char* marked; // ST_MARKED + char* MarkedMsg; // MI_MARKEDMSG + char* CurrentMsg; // MI_CURRENTMSG + char* QuitMsgs; // MI_QUITMSGS + char* WriteMsgsTo; // ST_WRITEMSGSTO + char* WriteTo; // WT_WRITETO + char* Diskfile; // MI_DISKFILE + char* Printer; // MI_PRINTER + char* QuitWrite; // MI_QUITWRITE + char* MarkingOptions; // ST_MARKINGOPTIONS + char* MarkWhat; // WT_MARKWHAT + char* Yourmail; // MI_YOURMAIL + char* FromToSubj; // MI_FROMTOSUBJ + char* TextHdr; // MI_TEXTHDR + char* Thread; // MI_THREAD + char* NewMsgs; // MI_NEWMSGS + char* OldMsgs; // MI_OLDMSGS + char* AllMsgs; // MI_ALLMSGS + char* Unmark; // MI_UNMARK + char* Range; // MI_RANGE + char* Markstoggle; // MI_MARKSTOGGLE + char* QuitMarks; // MI_QUITMARKS + char* EnterMarkString; // WT_ENTERMARKSTRING + char* SearchingMsg; // ST_SEARCHINGMSG + char* UserlistName; // WT_USERLISTNAME + char* GenUserlist; // IL_GENUSERLIST + char* FileExists; // WT_FILEEXISTS + char* Append; // MI_APPEND + char* OverWrite; // MI_OVERWRITE + char* QuitExist; // MI_QUITEXIST + char* WarnUnsent; // IL_WARNUNSENT + char* WarnLocked; // IL_WARNLOCKED + char* ChangeOrigin; // ST_CHANGEORIGIN + char* Origins; // WT_ORIGINS + char* ChangeUsername; // ST_CHANGEUSERNAME + char* Usernames; // WT_USERNAMES + char* ChangeAka; // ST_CHANGEAKA + char* Akas; // WT_AKAS + char* Lookup; // WT_LOOKUP + char* Phone; // WL_PHONE + char* QuitGoldED; // WT_QUITGOLDED + char* QuitYes; // MI_QUITYES + char* QuitNo; // MI_QUITNO + char* EditCmd; // MS_EDITCMD + char* NoOrigDefined; // IL_NOORIGDEFINED + char* NoUserDefined; // IL_NOUSERDEFINED + char* NoAkaDefined; // IL_NOAKADEFINED + char* NoTplDefined; // IL_NOTPLDEFINED + char* NoThreadlist; // IL_NOTHREADLIST + char* SkippingTwit; // MS_SKIPPINGTWIT + char* KillingTwit; // MS_KILLINGTWIT + char* WritingCfg; // IL_WRITINGCFG + char* CouldNotOpen; // IL_COULDNOTOPEN + char* Prompt; // MS_PROMPT + char* UnfinishedMsg; // IL_UNFINISHEDMSG + char* LoadUnfinished; // ST_LOADUNFINISHED + char* ReadingEcholist; // IL_READINGECHOLIST + char* ReadingAddrMacros; // IL_READINGADDRMACROS + char* CheckingNodelists; // IL_CHECKINGNODELISTS + char* Crossposting; // ST_CROSSPOSTING + char* TwitBlanked; // IL_TWITBLANKED + char* TwitSkipped; // IL_TWITSKIPPED + char* TwitIgnoreSkip; // IL_TWITIGNORESKIP + char* TwitDisplayed; // IL_TWITDISPLAYED + char* TwitKilled; // IL_TWITKILLED + char* StylecodesNo; // IL_STYLECODESNO + char* StylecodesYes; // IL_STYLECODESYES + char* StylecodesHide; // IL_STYLECODESHIDE + char* GenCfmReceipt; // ST_GENCFMRECEIPT + char* New; // WT_NEW + char* LookupInfo; // ST_LOOKUPINFO + char* DateTimeFmt; // MS_DATETIMEFMT + char* DateFmt; // MS_DATEFMT + char* TimeFmt; // MS_TIMEFMT + char* Originallyin; // MS_ORIGINALLYIN + char* Crosspostedin; // MS_CROSSPOSTEDIN + char* CCTo; // MS_CCTO + char* StatusLineHelp; // ST_STATUSLINEHELP + char* of; // HD_OF + char* RobotMsg; // MS_ROBOTMSG + char* StatusLineTimeFmt; // ST_STATUSLINETIMEFMT + + char* Replies; // WT_REPLIES + char* SelectReply; // ST_SELECTREPLY + char* WaitOrExit; // IL_WAITOREXIT + char* ReallyExit; // WT_REALLYEXIT + char* TaglineS; // MI_TAGLINES + char* HeaderEdit; // MI_HEADEREDIT + char* ScanGroup; // MI_SCANGROUP + char* QWKPacket; // WT_QWKPACKET + char* ScanQWK; // MI_SCANQWK + char* SoupPacket; // WT_SOUPPACKET + char* ScanSoup; // MI_SCANSOUP + char* ScanImport; // MI_SCANIMPORT + char* ScanExport; // MI_SCANEXPORT + char* ScanPM; // WT_SCANPM + char* Tagline; // MI_TAGLINE + char* Confirm; // WT_CONFIRM + char* ConfirmYes; // MI_CONFIRMYES + char* ConfirmNo; // MI_CONFIRMNO + char* ConfirmInfo; // IL_CONFIRMINFO + char* msg; // ST_MSG + char* msgs; // ST_MSGS + char* personal; // ST_PERSONAL + char* Grp; // WT_GRP + char* FoundPersonal; // IL_FOUNDPERSONAL + char* NoPersonal; // IL_NOPERSONAL + char* EscOrContinue; // ST_ESCORCONTINUE + char* SpellChecker; // MS_SPELLCHECKER + char* Ins; // WT_INS + char* FilelistFrom; // MI_FILELISTFROM + char* Initializing; // ST_INITIALIZING + char* Checking; // ST_CHECKING + char* LockShareCap; // ST_LOCKSHARECAP + char* AttrTurnOff; // WT_ATTRTURNOFF + char* Taglines; // WT_TAGLINES + char* ChangeTagline; // ST_CHANGETAGLINE + char* NoTagline; // IL_NOTAGLINE + char* Charsets; // WT_CHARSETS + char* ChangeXlatImp; // ST_CHANGEXLATIMP + char* CharsetAuto; // MI_CHARSETAUTO + char* NoXlatImport; // IL_NOXLATIMPORT + char* n_a; // WT_N_A + char* Written; // WT_WRITTEN + char* Arrived; // WT_ARRIVED + char* Received; // WT_RECEIVED + char* NoNodelist; // IL_NONODELIST + char* NodelistMissing; // IL_NODELISTMISSING + char* NodelistOutdated; // IL_NODELISTOUTDATED + char* Replylinker; // MS_REPLYLINKER + char* EnterMsgno; // WT_ENTERMSGNO + char* WaitUUdecoding; // IL_WAITUUDECODING + char* CompletedUUdecode; // IL_COMPLETEDUUDECODE + char* NotUUencoded; // IL_NOTUUENCODED + char* UUEinvalidpath; // IL_UUEINVALIDPATH + char* Pathreport; // IL_PATHREPORT + char* ErrorInSoup; // IL_ERRORINSOUP + char* WarnAlreadySent; // IL_WARNALREADYSENT + char* WaitLocked; // IL_WAITLOCKED + char* RetryOrESC; // ST_RETRYORESC + char* RetryLock; // ST_RETRYLOCK + char* RetryOpen; // ST_RETRYOPEN + char* TouchSemaphore; // WT_TOUCHSEMAPHORE + char* WriteToHdrNO; // MI_WRITETOHDRNO + char* WriteToHdrYES; // MI_WRITETIHDRYES + char* WriteToHdrONLY; // MI_WRITETIHDRONLY + char* Clipboard; // MI_CLIPBOARD + char* SelectMarks; // WT_SELECTMARKS + char* SelectMarksEdit; // WT_SELECTMARKSEDIT + char* DropMarksInfo; // IL_DROPMARKSINFO + char* DropMarks; // WT_DROPMARKS + char* DropAll; // MI_DROPALL + char* DropMarked; // MI_DROPMARKED + char* DropCurrent; // MI_DROPCURRENT + char* NoDrop; // MI_NODROP + char* CatchAreas; // WT_CATCHAREAS + char* CatchAll; // MI_CATCHALL + char* CatchMarked; // MI_CATCHMARKED + char* CatchCurrent; // MI_CATCHCURRENT + char* NoCatch; // MI_NOCATCH + char* Crosspost; // WT_CROSSPOST + char* XCProcess; // MI_XCPROCESS + char* XCIgnore; // MI_XCIGNORE + char* XCListFmt; // MI_XCLISTFMT + char* XCList; // WT_XCLIST + char* XCListKeep; // MI_XCLISTRAW + char* XCListNames; // MI_XCLISTVERBOSE + char* XCListVisible; // MI_XCLISTLINE + char* XCListRemove; // MI_XCLISTREMOVE + + char* Addressbook; // WT_ADDRESSBOOK + char* AdvancedSearch; // WT_ADVANCEDSEARCH + char* NoMoreMatches; // IL_NOMOREMATCHES + char* HeaderEditHelp1; // WT_HEADEREDITHELP1 + char* HeaderEditHelp2; // WT_HEADEREDITHELP2 + char* ThreadlistTitle; // WT_THREADLISTTITLE + char* AdvancedMarking; // WT_ADVANCEDMARKING + char* UserStatusline; // ST_USERSTATUSLINE + char* UserHeaderName; // WT_USERHEADERNAME + char* UserHeaderOrg; // WT_USERHEADERORG + char* UserHeaderAka; // WT_USERHEADERAKA + char* UserWait; // IL_USERWAIT + + char* ArealistSelections1;// MI_ALSELECTIONS1 + char* ArealistSelections2;// MI_ALSELECTIONS2 + char* Decode; // IL_DECODE + char* Preparing; // MI_PREPARING + + + + char* EndLanguage; // LAST_CRC + +}; + + +// ------------------------------------------------------------------ + diff --git a/golded3/geline.cpp b/golded3/geline.cpp new file mode 100644 index 0000000..510a501 --- /dev/null +++ b/golded3/geline.cpp @@ -0,0 +1,3035 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Conversion of a raw message to a linked list of lines. +// ------------------------------------------------------------------ + +#include +#include +#include +#include +#include + + +// ------------------------------------------------------------------ + +#ifdef __UNIX__ +#define GOLDMARK '\xB2' +#else +#define GOLDMARK '\xFD' +#endif + + +// ------------------------------------------------------------------ + +const int BODYLINE = 0; +const int HEADERLINE = 1; +const int USERDEFINED = 2; +const int RFC_X = 3; + +enum { + MASK_FTS = 0x1000, + FTS_AREA, + FTS_INTL, + FTS_FMPT, + FTS_TOPT, + FTS_MSGID, + FTS_REPLY, + FTS_SEENBY, + FTS_PATH, + FTS_ZZZZ +}; + +enum { + MASK_FSC = 0x2000, + FSC_CHARSET, + FSC_CHRC, + FSC_CHRS, + FSC_DOMAIN, + FSC_EID, + FSC_ENC, + FSC_ENCLFILE, + FSC_FLAGS, + FSC_FWDFROM, + FSC_FWDORIG, + FSC_FWDTO, + FSC_FWDDEST, + FSC_FWDSUBJ, + FSC_FWDAREA, + FSC_FWDMSGID, + FSC_I51, + FSC_MSGTO, + FSC_PID, + FSC_PTH, + FSC_REPLYADDR, + FSC_REPLYTO, + FSC_SPLIT, + FSC_SPTH, + FSC_TID, + FSC_ZZZZ +}; + +enum { + MASK_XXX = 0x8000, + XXX_ACUPDATE, + XXX_CODEPAGE, + XXX_DESTADDR, + XXX_ENCRYPTION, + XXX_EOT, + XXX_GATECHK, + XXX_GID, + XXX_GIF, + XXX_GMD, + XXX_GROUP, + XXX_MOOD, + XXX_MSGSEQ, + XXX_NOTE, + XXX_ORIGID, + XXX_ORIGINAL, + XXX_ORIGREF, + XXX_RECD, + XXX_RFC, + XXX_RFD, + XXX_RID, + XXX_ROUTE, + XXX_SN, + XXX_SOT, + XXX_TCL1, + XXX_TCL2, + XXX_TZUTCINFO, + XXX_TZUTC, + XXX_TZ, + XXX_VIA, + XXX_XID, + XXX_ZZZZ +}; + +enum { + MASK_RFC = 0x4000, + RFC_ALSO_CONTROL, + RFC_APPARENTLY_TO, + RFC_APPROVED, + RFC_ARTICLE_NAMES, + RFC_ARTICLE_UPDATES, + RFC_BCC, + RFC_CC, + RFC_COMMENT, + RFC_COMMENTS, + RFC_CONTENT_DESCRIPTION, + RFC_CONTENT_DISPOSITION, + RFC_CONTENT_ID, + RFC_CONTENT_LENGTH, + RFC_CONTENT_TRANSFER_ENCODING, + RFC_CONTENT_TYPE, + RFC_CONTROL, + RFC_DATE, + RFC_DELIVERED_TO, + RFC_DELIVERY_DATE, + RFC_DISTRIBUTION, + RFC_ENCRYPTED, + RFC_ERRORS_TO, + RFC_EXPIRES, + RFC_FOLLOWUP_TO, + RFC_FROM, + RFC_FROMX, + RFC_IN_REPLY_TO, + RFC_KEYWORDS, + RFC_LINES, + RFC_MAILING_LIST, // This one is actually _not_ RFC + RFC_MESSAGE_ID, + RFC_MIME_VERSION, + RFC_NEWSGROUPS, + RFC_NEWS_SOFTWARE, + RFC_NNTP_POSTING_HOST, + RFC_NNTP_POSTING_USER, + RFC_OLD_DATE, + RFC_ORGANIZATION, + RFC_ORIGINATOR, + RFC_PATH, + RFC_PRECEDENCE, + RFC_PRIORITY, + RFC_RECEIVED, + RFC_REFERENCES, + RFC_REPLY_TO, + RFC_RETURN_PATH, + RFC_RETURN_RECEIPT_TO, + RFC_SEE_ALSO, + RFC_SENDER, + RFC_STATUS, + RFC_SUBJECT, + RFC_SUMMARY, + RFC_SUPERSEDES, + RFC_TO, + RFC_VERSION, + RFC_XREF, + RFC_X_CHARSET, + RFC_X_CHAR_ESC, + RFC_X_FTN_TO, + RFC_X_MAILER, + RFC_X_NEWSREADER, + RFC_X_TO, + RFC_RNEWS, + RFC_ZZZZ +}; + +#define MASK_ALL (MASK_FTS|MASK_FSC|MASK_RFC|MASK_XXX) + + +// ------------------------------------------------------------------ + +struct Kludges { + char* key; + uint num; + byte req; +}; + + +// ------------------------------------------------------------------ + +const byte KCRQ_NONE = 0x0000; +const byte KCRQ_COLON = 0x0001; +const byte KCRQ_CASE = 0x0002; + + +// ------------------------------------------------------------------ + +static Kludges fts_list[] = { + + { "AREA" , FTS_AREA , KCRQ_CASE }, + { "INTL" , FTS_INTL , KCRQ_CASE }, + { "FMPT" , FTS_FMPT , KCRQ_CASE }, + { "TOPT" , FTS_TOPT , KCRQ_CASE }, + { "MSGID" , FTS_MSGID , KCRQ_CASE }, + { "REPLY" , FTS_REPLY , KCRQ_CASE }, + { "SEEN-BY" , FTS_SEENBY , KCRQ_CASE }, + { "PATH" , FTS_PATH , KCRQ_CASE }, + { "" , FTS_ZZZZ , KCRQ_NONE }, +}; + + +// ------------------------------------------------------------------ + +static Kludges fsc_list[] = { + + { "CHARSET" , FSC_CHARSET , KCRQ_CASE }, + { "CHRC" , FSC_CHRC , KCRQ_CASE }, + { "CHRS" , FSC_CHRS , KCRQ_CASE }, + { "DOMAIN" , FSC_DOMAIN , KCRQ_CASE }, + { "EID" , FSC_EID , KCRQ_CASE }, + { "ENC" , FSC_ENC , KCRQ_CASE }, + { "ENCLFILE" , FSC_ENCLFILE , KCRQ_CASE }, + { "FLAGS" , FSC_FLAGS , KCRQ_CASE }, + { "FWDFROM" , FSC_FWDFROM , KCRQ_CASE }, + { "FWDORIG" , FSC_FWDORIG , KCRQ_CASE }, + { "FWDTO" , FSC_FWDTO , KCRQ_CASE }, + { "FWDDEST" , FSC_FWDDEST , KCRQ_CASE }, + { "FWDSUBJ" , FSC_FWDSUBJ , KCRQ_CASE }, + { "FWDAREA" , FSC_FWDAREA , KCRQ_CASE }, + { "FWDMSGID" , FSC_FWDMSGID , KCRQ_CASE }, + { "I51" , FSC_I51 , KCRQ_CASE }, + { "MSGTO" , FSC_MSGTO , KCRQ_CASE }, + { "PID" , FSC_PID , KCRQ_CASE }, + { "PTH" , FSC_PTH , KCRQ_CASE }, + { "REPLYADDR" , FSC_REPLYADDR , KCRQ_CASE }, + { "REPLYTO" , FSC_REPLYTO , KCRQ_CASE }, + { "SPLIT" , FSC_SPLIT , KCRQ_CASE }, + { "SPTH" , FSC_SPTH , KCRQ_CASE }, + { "TID" , FSC_TID , KCRQ_CASE }, + { "" , FSC_ZZZZ , KCRQ_NONE }, +}; + + +// ------------------------------------------------------------------ + +static Kludges xxx_list[] = { + + { "ACUPDATE" , XXX_ACUPDATE , KCRQ_CASE }, + { "CODEPAGE" , XXX_CODEPAGE , KCRQ_CASE }, + { "DESTADDR" , XXX_DESTADDR , KCRQ_CASE }, + { "ENCRYPTION" , XXX_ENCRYPTION , KCRQ_CASE }, + { "EOT" , XXX_EOT , KCRQ_CASE }, + { "GATECHK" , XXX_GATECHK , KCRQ_CASE }, + { "GID" , XXX_GID , KCRQ_CASE }, + { "GIF" , XXX_GIF , KCRQ_CASE }, + { "GMD" , XXX_GMD , KCRQ_CASE }, + { "GROUP" , XXX_GROUP , KCRQ_CASE }, + { "MOOD" , XXX_MOOD , KCRQ_CASE }, + { "MSGSEQ" , XXX_MSGSEQ , KCRQ_CASE }, + { "NOTE" , XXX_NOTE , KCRQ_CASE }, + { "ORIGID" , XXX_ORIGID , KCRQ_CASE }, + { "Original" , XXX_ORIGINAL , KCRQ_NONE }, + { "ORIGREF" , XXX_ORIGREF , KCRQ_CASE }, + { "Recd" , XXX_RECD , KCRQ_CASE }, + { "RFC" , XXX_RFC , KCRQ_CASE }, + { "RFD" , XXX_RFD , KCRQ_CASE }, + { "RID" , XXX_RID , KCRQ_CASE }, + { "#ROUTE" , XXX_ROUTE , KCRQ_CASE }, + { "SN" , XXX_SN , KCRQ_CASE }, + { "SOT" , XXX_SOT , KCRQ_CASE }, + { "TCL1" , XXX_TCL1 , KCRQ_CASE }, + { "TCL2" , XXX_TCL2 , KCRQ_CASE }, + { "TZUTCINFO" , XXX_TZUTCINFO , KCRQ_CASE }, + { "TZUTC" , XXX_TZUTC , KCRQ_CASE }, + { "TZ" , XXX_TZ , KCRQ_CASE }, + { "Via" , XXX_VIA , KCRQ_NONE }, + { "XID" , XXX_XID , KCRQ_CASE }, + { "" , XXX_ZZZZ , KCRQ_NONE } +}; + + +// ------------------------------------------------------------------ + +static Kludges rfc_list[] = { + + { "Also-Control" , RFC_ALSO_CONTROL , KCRQ_COLON }, + { "Apparently-To" , RFC_APPARENTLY_TO , KCRQ_COLON }, + { "Approved" , RFC_APPROVED , KCRQ_COLON }, + { "Article-Names" , RFC_ARTICLE_NAMES , KCRQ_COLON }, + { "Article-Updates" , RFC_ARTICLE_UPDATES , KCRQ_COLON }, + { "Bcc" , RFC_BCC , KCRQ_COLON }, + { "Cc" , RFC_CC , KCRQ_COLON }, + { "Comment" , RFC_COMMENT , KCRQ_COLON }, + { "Comments" , RFC_COMMENTS , KCRQ_COLON }, + { "Content-Description" , RFC_CONTENT_DESCRIPTION , KCRQ_COLON }, + { "Content-Disposition" , RFC_CONTENT_DISPOSITION , KCRQ_COLON }, + { "Content-ID" , RFC_CONTENT_ID , KCRQ_COLON }, + { "Content-Length" , RFC_CONTENT_LENGTH , KCRQ_COLON }, + { "Content-Transfer-Encoding" , RFC_CONTENT_TRANSFER_ENCODING , KCRQ_COLON }, + { "Content-Type" , RFC_CONTENT_TYPE , KCRQ_COLON }, + { "Control" , RFC_CONTROL , KCRQ_COLON }, + { "Date" , RFC_DATE , KCRQ_COLON }, + { "Delivered-To" , RFC_DELIVERED_TO , KCRQ_COLON }, + { "Delivery-Date" , RFC_DELIVERY_DATE , KCRQ_COLON }, + { "Distribution" , RFC_DISTRIBUTION , KCRQ_COLON }, + { "Encrypted" , RFC_ENCRYPTED , KCRQ_COLON }, + { "Errors-To" , RFC_ERRORS_TO , KCRQ_COLON }, + { "Expires" , RFC_EXPIRES , KCRQ_COLON }, + { "Followup-To" , RFC_FOLLOWUP_TO , KCRQ_COLON }, + { "From" , RFC_FROM , KCRQ_COLON }, + { "From" , RFC_FROMX , KCRQ_NONE }, + { "In-Reply-To" , RFC_IN_REPLY_TO , KCRQ_COLON }, + { "Keywords" , RFC_KEYWORDS , KCRQ_COLON }, + { "Lines" , RFC_LINES , KCRQ_COLON }, + { "Message-ID" , RFC_MESSAGE_ID , KCRQ_COLON }, + { "Mailing-List" , RFC_MAILING_LIST , KCRQ_COLON }, + { "MIME-Version" , RFC_MIME_VERSION , KCRQ_COLON }, + { "Newsgroups" , RFC_NEWSGROUPS , KCRQ_COLON }, + { "News-Software" , RFC_NEWS_SOFTWARE , KCRQ_COLON }, + { "NNTP-Posting-Host" , RFC_NNTP_POSTING_HOST , KCRQ_COLON }, + { "NNTP-Posting-User" , RFC_NNTP_POSTING_USER , KCRQ_COLON }, + { "Old-Date" , RFC_OLD_DATE , KCRQ_COLON }, + { "Organization" , RFC_ORGANIZATION , KCRQ_COLON }, + { "Originator" , RFC_ORIGINATOR , KCRQ_COLON }, + { "Path" , RFC_PATH , KCRQ_COLON }, + { "Precedence" , RFC_PRECEDENCE , KCRQ_COLON }, + { "Priority" , RFC_PRIORITY , KCRQ_COLON }, + { "Received" , RFC_RECEIVED , KCRQ_COLON }, + { "References" , RFC_REFERENCES , KCRQ_COLON }, + { "Reply-To" , RFC_REPLY_TO , KCRQ_COLON }, + { "Return-Path" , RFC_RETURN_PATH , KCRQ_COLON }, + { "Return-Receipt-To" , RFC_RETURN_RECEIPT_TO , KCRQ_COLON }, + { "See-Also" , RFC_SEE_ALSO , KCRQ_COLON }, + { "Sender" , RFC_SENDER , KCRQ_COLON }, + { "Status" , RFC_STATUS , KCRQ_COLON }, + { "Subject" , RFC_SUBJECT , KCRQ_COLON }, + { "Summary" , RFC_SUMMARY , KCRQ_COLON }, + { "Supersedes" , RFC_SUPERSEDES , KCRQ_COLON }, + { "To" , RFC_TO , KCRQ_COLON }, + { "Version" , RFC_VERSION , KCRQ_COLON }, + { "Xref" , RFC_XREF , KCRQ_COLON }, + { "X-Charset" , RFC_X_CHARSET , KCRQ_COLON }, + { "X-Char-Esc" , RFC_X_CHAR_ESC , KCRQ_COLON }, + { "X-FTN-To" , RFC_X_FTN_TO , KCRQ_COLON }, + { "X-Mailer" , RFC_X_MAILER , KCRQ_COLON }, + { "X-Newsreader" , RFC_X_NEWSREADER , KCRQ_COLON }, + { "X-To" , RFC_X_TO , KCRQ_COLON }, + { "#!" , RFC_RNEWS , KCRQ_NONE }, + { "" , RFC_ZZZZ , KCRQ_NONE }, +}; + + +char* mime_header_decode(char* decoded, const char* encoded, char *charset) { + + char dbuf[200], cbuf[100], ebuf[50], tbuf[200]; + char* dptr = decoded; + const char* eptr = encoded; + if(charset) *charset = NUL; + while(*eptr) { + if(*eptr == '=') { + const char* mptr = mime_crack_encoded_word(eptr, cbuf, ebuf, tbuf); + if(mptr) { // and strieql(cbuf, "ISO-8859-1")) { + if(charset) { + strxcpy(charset, cbuf, 100); + charset = NULL; + } + bool okay = false; + strchg(tbuf, '_', ' '); + if(strieql(ebuf, "Q")) { + quoted_printable_engine qb; + qb.decode(dbuf, tbuf); + dptr = stpcpy(dptr, dbuf); + okay = true; + } + else if(strieql(ebuf, "B")) { + base64_engine b64; + b64.decode(dbuf, tbuf); + dptr = stpcpy(dptr, dbuf); + okay = true; + } + if(okay) { + eptr = mptr; + mptr = strskip_lwsp(mptr); + if(mime_crack_encoded_word(mptr, cbuf, ebuf, tbuf)) + eptr = mptr; + continue; + } + } + } + *dptr++ = *eptr++; + } + *dptr = NUL; + + return decoded; +} + + +// ------------------------------------------------------------------ + +char* strxmimecpy(char* dest, const char* source, int level, int size, bool detect) { + + char buf[500], buf2[500], charset[100]; + bool need_reload; + int table = -1; + + strxcpy(buf, source, sizeof(buf)); + mime_header_decode(buf2, buf, charset); + + need_reload = (detect and *charset); + if(need_reload) { + table = LoadCharset(NULL, NULL, 1); + level = LoadCharset(charset, CFG->xlatlocalset); + } + + XlatStr(buf, buf2, level, CharTable); + + if(need_reload) + if(table == -1) + LoadCharset(CFG->xlatimport, CFG->xlatlocalset); + else + LoadCharset(CFG->xlatcharset[table].imp, CFG->xlatcharset[table].exp); + + strxcpy(dest, buf, size); + return dest; +} + + +// ------------------------------------------------------------------ + +void KludgeAREA(GMsg* msg, char* echoid) { + + Area* ap = AL.AreaEchoToPtr(echoid); + if(ap) + msg->areakludgeid = ap->echoid(); +} + + +// ------------------------------------------------------------------ + +void KludgeINTL(GMsg* msg, char* ptr) { + + char buf1[201], buf2[201]; + word fmpt = msg->orig.point; + word topt = msg->dest.point; + sscanf(ptr, "%s %s", buf1, buf2); + msg->dest.set(buf1); + msg->orig.set(buf2); + msg->orig.point = fmpt; + msg->dest.point = topt; +} + + +// ------------------------------------------------------------------ + +void KludgeFMPT(GMsg* msg, char* ptr) { + + msg->orig.point = atow(ptr); +} + + +// ------------------------------------------------------------------ + +void KludgeTOPT(GMsg* msg, char* ptr) { + + msg->dest.point = atow(ptr); +} + + +// ------------------------------------------------------------------ + +void KludgeMSGID(GMsg* msg, char* ptr) { + + strxcpy(msg->msgids, ptr, sizeof(msg->msgids)); + msg->msgid.reset(msg->msgids, msg->odom); +} + + +// ------------------------------------------------------------------ + +void KludgeREPLY(GMsg* msg, char* ptr) { + + strxcpy(msg->replys, ptr, sizeof(msg->replys)); +} + + +// ------------------------------------------------------------------ + +void KludgeDOMAIN(GMsg* msg, char* ptr) { + + char buf1[201], buf2[201]; + sscanf(ptr, "%s %s %s %s", msg->ddom, buf1, msg->odom, buf2); + msg->dest.reset(buf1); + msg->orig.reset(buf2); +} + + +// ------------------------------------------------------------------ + +void KludgeFLAGS(GMsg* msg, char* ptr) { + + GetAttribstr(&msg->attr, ptr); +} + + +// ------------------------------------------------------------------ + +void KludgeMSGTO(GMsg* msg, char* ptr) { + + msg->dest.reset(ptr, msg->ddom); +} + + +// ------------------------------------------------------------------ + +void KludgePID(GMsg* msg, char* ptr) { + + strxcpy(msg->pid, ptr, sizeof(msg->pid)); + + if(CFG->gedhandshake) { + // Recognize another GoldED msg + if(striinc(__gver_name__, ptr) or striinc(__gver_shortname__, ptr)) + goldmark = GOLDMARK; + } +} + + +// ------------------------------------------------------------------ + +void KludgeREPLYADDR(GMsg* msg, char* ptr) { + + Name name; + name[0] = NUL; + char *buf=throw_strdup(ptr); + ParseInternetAddr(buf, *msg->realby ? name : msg->realby, msg->iaddr); + if(*name) + strxcpy(msg->realby, name, sizeof(Name)); + throw_free(buf); +} + + +// ------------------------------------------------------------------ + +void KludgeREPLYTO(GMsg* msg, char* ptr) { + + strcpy(msg->igate, ptr); +} + + +// ------------------------------------------------------------------ + +void KludgeFROM(GMsg* msg, char* ptr) { + + INam fromname; + IAdr fromaddr; + strxmimecpy(msg->ifrom, ptr, msg->charsetlevel, sizeof(INam)); + ParseInternetAddr(msg->ifrom, fromname, fromaddr); + if(*fromaddr) + strcpy(msg->iorig, fromaddr); + if(*fromname) + strxcpy(msg->realby, fromname, sizeof(msg->realby)); +} + + +// ------------------------------------------------------------------ + +void KludgeTO(GMsg* msg, char* ptr) { + + INam _toname; + IAdr _toaddr; + char* buf = throw_strdup(ptr); + strxcpy(msg->ito, buf, sizeof(msg->ito)); + ParseInternetAddr(buf, _toname, _toaddr); + throw_free(buf); + if(*_toaddr) + strcpy(msg->idest, _toaddr); + if(*_toname) + strxcpy(msg->realto, _toname, sizeof(msg->realto)); +} + + +// ------------------------------------------------------------------ + +void KludgeBCC(GMsg* msg, char* ptr) { + + char* ibcc = msg->ibcc; + char* buf = (char*)throw_malloc(strlen(ibcc) + strlen(ptr) + 3); + strcpy(stpcpy(stpcpy(buf, ibcc), *ibcc ? ", " : ""), ptr); + strxcpy(ibcc, buf, sizeof(msg->ibcc)); + throw_free(buf); +} + + +// ------------------------------------------------------------------ + +void KludgeCC(GMsg* msg, char* ptr) { + + char* icc = msg->icc; + char* buf = (char*)throw_malloc(strlen(icc) + strlen(ptr) + 3); + strcpy(stpcpy(stpcpy(buf, icc), *icc ? ", " : ""), ptr); + strxcpy(icc, buf, sizeof(msg->icc)); + throw_free(buf); +} + + +// ------------------------------------------------------------------ + +void KludgeREPLY_TO(GMsg* msg, char* ptr) { + + INam _rtname; + IAdr _rtaddr; + char *buf=throw_strdup(ptr); + ParseInternetAddr(buf, _rtname, _rtaddr); + throw_free(buf); + if(*_rtaddr) + strcpy(msg->ireplyto, _rtaddr); +} + + +// ------------------------------------------------------------------ + +void KludgeSUBJECT(GMsg* msg, char* ptr) { + + char* buf = throw_strdup(ptr); + if(not msg->attr.att()) + strxcpy(msg->re, buf, sizeof(msg->re)); + throw_free(buf); +} + + +// ------------------------------------------------------------------ + +void KludgeTZUTC(GMsg* msg, char* ptr) { + + msg->tzutc = atoi(ptr); +} + + +// ------------------------------------------------------------------ + +void KludgeDATE(GMsg* msg, char* ptr) { + + // RFC822 Date: BNF + // + // date-time = [ day "," ] date time ; dd mm yy + // ; hh:mm:ss zzz + // + // day = "Mon" / "Tue" / "Wed" / "Thu" + // / "Fri" / "Sat" / "Sun" + // + // date = 1*2DIGIT month 2DIGIT ; day month year + // ; e.g. 20 Jun 82 + // + // month = "Jan" / "Feb" / "Mar" / "Apr" + // / "May" / "Jun" / "Jul" / "Aug" + // / "Sep" / "Oct" / "Nov" / "Dec" + // + // time = hour zone ; ANSI and Military + // + // hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] + // ; 00:00:00 - 23:59:59 + // + // zone = "UT" / "GMT" ; Universal Time + // ; North American : UT + // / "EST" / "EDT" ; Eastern: - 5/ - 4 + // / "CST" / "CDT" ; Central: - 6/ - 5 + // / "MST" / "MDT" ; Mountain: - 7/ - 6 + // / "PST" / "PDT" ; Pacific: - 8/ - 7 + // / 1ALPHA ; Military: Z = UT; + // ; A:-1; (J not used) + // ; M:-12; N:+1; Y:+12 + // / ( ("+" / "-") 4DIGIT ) ; Local differential + // ; hours+min. (HHMM) + + bool date_ok = false; + int year=0, month=0, day=0; + int hour=0, minute=0, second=0; + + ptr = strskip_wht(ptr); + if(not isdigit(*ptr)) { + // Skip past weekday string + ptr = strskip_wht(strskip_txt(ptr)); + } + if(*ptr) { + if(isdigit(*ptr)) { + day = atoi(ptr); + ptr = strskip_wht(strskip_txt(ptr)); + if(isalpha(*ptr)) { + month = str2mon(ptr); + if(month) { + ptr = strskip_wht(strskip_txt(ptr)); + if(isdigit(*ptr)) { + year = atoi(ptr); + ptr = strskip_wht(strskip_txt(ptr)); + if(isdigit(*ptr)) { + hour = atoi(ptr); + ptr = strskip_digits(ptr); + if(*ptr and isdigit(ptr[1])) { + minute = atoi(++ptr); + date_ok = true; + // The seconds part is optional + ptr = strskip_digits(ptr); + if(*ptr and isdigit(ptr[1])) { + second = atoi(++ptr); + // Setting timezone + ptr = strskip_wht(strskip_digits(ptr)); + if(*ptr) { + if(*ptr == '(' /*)*/ ) { + char* p; + if((p = strskip_to(++ptr, /*(*/ ')')) != NULL) *p = 0; + } + msg->tzutc = atoi(ptr); + } + } + } + } + } + } + } + } + } + + if(date_ok) { + struct tm t; + t.tm_year = (year < 80) ? (year+100) : (year > 1900) ? (year-1900) : year; + t.tm_mon = month - 1; + t.tm_mday = day; + t.tm_hour = hour; + t.tm_min = minute; + t.tm_sec = second; + t.tm_isdst = -1; + time_t a = mktime(&t); + time_t b = mktime(gmtime(&a)); + msg->written = a + a - b; + } +} + + +// ------------------------------------------------------------------ + +void KludgeMESSAGE_ID(GMsg* msg, char* ptr) { + + char buf[201]; + throw_free(msg->messageid); + msg->messageid = throw_strdup(ptr); + CvtMessageIDtoMSGID(ptr, buf, AA->echoid(), "MSGID"); + strcpy(msg->msgids, buf+8); +} + + +// ------------------------------------------------------------------ + +void KludgeREFERENCES(GMsg* msg, char* ptr) { + + throw_free(msg->references); + msg->references = throw_strdup(ptr); +} + + +// ------------------------------------------------------------------ + +void KludgeIN_REPLY_TO(GMsg* msg, char* ptr) { + + throw_free(msg->inreplyto); + msg->inreplyto = throw_strdup(ptr); +} + + +// ------------------------------------------------------------------ + +void KludgeORGANIZATION(GMsg* msg, char* ptr) { + + strxcpy(msg->organization, ptr, sizeof(msg->organization)); +} + + +// ------------------------------------------------------------------ + +void KludgeX_FTN_TO(GMsg* msg, char* ptr) { + + strxcpy(msg->realto, ptr, sizeof(msg->realto)); +} + + +// ------------------------------------------------------------------ + +void KludgeFWDFROM(GMsg* msg, char* ptr) { + + strxcpy(msg->fwdfrom, ptr, sizeof(msg->fwdfrom)); +} + + +// ------------------------------------------------------------------ + +void KludgeFWDORIG(GMsg* msg, char* ptr) { + + msg->fwdorig.reset(ptr); +} + + +// ------------------------------------------------------------------ + +void KludgeFWDTO(GMsg* msg, char* ptr) { + + strxcpy(msg->fwdto, ptr, sizeof(msg->fwdto)); +} + + +// ------------------------------------------------------------------ + +void KludgeFWDDEST(GMsg* msg, char* ptr) { + + msg->fwddest.reset(ptr); +} + + +// ------------------------------------------------------------------ + +void KludgeFWDSUBJ(GMsg* msg, char* ptr) { + + strxcpy(msg->fwdsubj, ptr, sizeof(msg->fwdsubj)); +} + + +// ------------------------------------------------------------------ + +void KludgeFWDAREA(GMsg* msg, char* ptr) { + + strxcpy(msg->fwdarea, ptr, sizeof(msg->fwdarea)); +} + + +// ------------------------------------------------------------------ + +void KludgeFWDMSGID(GMsg* msg, char* ptr) { + + strxcpy(msg->fwdmsgid, ptr, sizeof(msg->fwdmsgid)); +} + + +// ------------------------------------------------------------------ + +char* UnwrapLine(Line* line, char* ptr, int addspace = false) { + + if(line->type & GLINE_WRAP) { + uint len = strlen(ptr); + char* uptr = throw_strdup(ptr); + while(line and (line->type & GLINE_WRAP)) { + if(line->next) { + uint nextlen = strlen(line->next->text); + uptr = (char*)throw_realloc(uptr, len+nextlen+2); + if(addspace and len and (uptr[len-1] != ' ')) { + strcat(uptr, " "); + len++; + } + strcpy(uptr+len, line->next->text); + len += nextlen; + } + line = line->next; + } + return uptr; + } + + return NULL; +} + + +// ------------------------------------------------------------------ + +int HandleKludges(GMsg* msg, Line* line, int kludgenum, char* ptr, int getvalue) { + + switch(kludgenum) { + + case FTS_AREA: + line->kludge = GKLUD_AREA; + if(getvalue) + KludgeAREA(msg, ptr); + return true; + + case FTS_INTL: + line->kludge = GKLUD_INTL; + if(getvalue) + KludgeINTL(msg, ptr); + return true; + + case FTS_FMPT: + line->kludge = GKLUD_FMPT; + if(getvalue) + KludgeFMPT(msg, ptr); + return true; + + case FTS_TOPT: + line->kludge = GKLUD_TOPT; + if(getvalue) + KludgeTOPT(msg, ptr); + return true; + + case FTS_MSGID: + line->kludge = GKLUD_MSGID; + if(getvalue) { + char* tmp = UnwrapLine(line, ptr); + KludgeMSGID(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + } + return true; + + case FTS_REPLY: + line->kludge = GKLUD_REPLY; + if(getvalue) { + char* tmp = UnwrapLine(line, ptr); + KludgeREPLY(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + } + return true; + + case FTS_SEENBY: + line->kludge = GKLUD_SEENBY; + return true; + + case FTS_PATH: + line->kludge = GKLUD_PATH; + return true; + + //////////////////////////////////////////////////////////// + + case FSC_CHARSET: + line->kludge = GKLUD_CHARSET; + return true; + + case FSC_CHRS: + line->kludge = GKLUD_CHARSET; + return true; + + case FSC_DOMAIN: + //line->kludge = GKLUD_DOMAIN; + if(getvalue) + KludgeDOMAIN(msg, ptr); + return true; + + case FSC_ENCLFILE: + if(getvalue) + strxcpy(msg->re, ptr, sizeof(msg->re)); + return true; + + case FSC_FLAGS: + line->kludge = GKLUD_FLAGS; + if(getvalue) + KludgeFLAGS(msg, ptr); + return true; + + case FSC_I51: + line->kludge = GKLUD_CHARSET; + msg->i51 = true; + return true; + + case FSC_MSGTO: + //line->kludge = GKLUD_MSGTO; + if(getvalue) + KludgeMSGTO(msg, ptr); + return true; + + case FSC_PID: + line->kludge = GKLUD_PID; + if(getvalue) + KludgePID(msg, ptr); + return true; + + case FSC_REPLYADDR: + line->kludge = GKLUD_REPLYADDR; + if(getvalue) + KludgeREPLYADDR(msg, ptr); + return true; + + case FSC_REPLYTO: + line->kludge = GKLUD_REPLYTO; + if(getvalue) + KludgeREPLYTO(msg, ptr); + return true; + + case FSC_FWDFROM: + line->kludge = GKLUD_FWD; + if(getvalue) + KludgeFWDFROM(msg, ptr); + return true; + + case FSC_FWDORIG: + line->kludge = GKLUD_FWD; + if(getvalue) + KludgeFWDORIG(msg, ptr); + return true; + + case FSC_FWDTO: + line->kludge = GKLUD_FWD; + if(getvalue) + KludgeFWDTO(msg, ptr); + return true; + + case FSC_FWDDEST: + line->kludge = GKLUD_FWD; + if(getvalue) + KludgeFWDDEST(msg, ptr); + return true; + + case FSC_FWDSUBJ: + line->kludge = GKLUD_FWD; + if(getvalue) + KludgeFWDSUBJ(msg, ptr); + return true; + + case FSC_FWDAREA: + line->kludge = GKLUD_FWD; + if(getvalue) + KludgeFWDAREA(msg, ptr); + return true; + + case FSC_FWDMSGID: + line->kludge = GKLUD_FWD; + if(getvalue) + KludgeFWDMSGID(msg, ptr); + return true; + + case FSC_CHRC: + case FSC_EID: + case FSC_ENC: + case FSC_PTH: + case FSC_SPLIT: + case FSC_SPTH: + case FSC_TID: + // Recognized but not processed + return true; + + //////////////////////////////////////////////////////////// + + case XXX_DESTADDR: + //line->kludge = GKLUD_DESTADDR; + if(getvalue) + KludgeMSGTO(msg, ptr); + return true; + + case XXX_TZUTCINFO: + case XXX_TZUTC: + line->kludge = GKLUD_KNOWN; + if(getvalue) + KludgeTZUTC(msg, ptr); + return true; + + case XXX_ACUPDATE: + case XXX_CODEPAGE: + case XXX_ENCRYPTION: + case XXX_EOT: + case XXX_GATECHK: + case XXX_GID: + case XXX_GIF: + case XXX_GMD: + case XXX_GROUP: + case XXX_MOOD: + case XXX_MSGSEQ: + case XXX_NOTE: + case XXX_ORIGID: + case XXX_ORIGINAL: + case XXX_ORIGREF: + case XXX_RECD: + case XXX_RFC: + case XXX_RFD: + case XXX_RID: + case XXX_ROUTE: + case XXX_SN: + case XXX_SOT: + case XXX_TCL1: + case XXX_TCL2: + case XXX_TZ: + case XXX_VIA: + case XXX_XID: + // Recognized but not processed + return true; + } + + return false; +} + + +// ------------------------------------------------------------------ + +int HandleRFCs(GMsg* msg, Line* line, int kludgenum, char* ptr, int getvalue) { + + switch(kludgenum) { + + case RFC_FROM: + line->kludge = GKLUD_RFC; + if(getvalue) { + char* tmp = UnwrapLine(line, ptr); + KludgeFROM(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + } + return true; + + case RFC_TO: + case RFC_X_TO: + line->kludge = GKLUD_RFC; + if(getvalue) { + char* tmp = UnwrapLine(line, ptr); + KludgeTO(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + } + return true; + + case RFC_BCC: + line->kludge = GKLUD_RFC; + if(getvalue) { + char* tmp = UnwrapLine(line, ptr); + KludgeBCC(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + } + return true; + + case RFC_CC: + line->kludge = GKLUD_RFC; + if(getvalue) { + char* tmp = UnwrapLine(line, ptr); + KludgeCC(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + } + return true; + + case RFC_DATE: + line->kludge = GKLUD_RFC; + if(getvalue) + KludgeDATE(msg, ptr); + return true; + + case RFC_SUBJECT: + line->kludge = GKLUD_RFC; + if(getvalue) { + char* tmp = UnwrapLine(line, ptr); + KludgeSUBJECT(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + } + return true; + + case RFC_REPLY_TO: + line->kludge = GKLUD_RFC; + if(getvalue) { + char* tmp = UnwrapLine(line, ptr); + KludgeREPLY_TO(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + } + return true; + + case RFC_MESSAGE_ID: + line->kludge = GKLUD_RFC; + if(getvalue) { + char* tmp = UnwrapLine(line, ptr); + KludgeMESSAGE_ID(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + } + return true; + + case RFC_REFERENCES: + line->kludge = GKLUD_RFC; + if(getvalue) { + char* tmp = UnwrapLine(line, ptr); + KludgeREFERENCES(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + } + return true; + + case RFC_IN_REPLY_TO: + line->kludge = GKLUD_RFC; + if(getvalue) { + char* tmp = UnwrapLine(line, ptr); + KludgeIN_REPLY_TO(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + } + return true; + + case RFC_ORGANIZATION: + line->kludge = GKLUD_RFC; + if(getvalue) + KludgeORGANIZATION(msg, ptr); + return true; + + case RFC_X_FTN_TO: + line->kludge = GKLUD_RFC; + if(getvalue) + KludgeX_FTN_TO(msg, ptr); + return true; + + case RFC_X_MAILER: + line->kludge = GKLUD_RFC; + if(getvalue) + KludgePID(msg, ptr); + return true; + + case RFC_X_NEWSREADER: + line->kludge = GKLUD_RFC; + if(getvalue) + KludgePID(msg, ptr); + return true; + + case RFC_NEWSGROUPS: + case RFC_SENDER: + case RFC_CONTENT_TRANSFER_ENCODING: + case RFC_CONTENT_TYPE: + case RFC_MIME_VERSION: + case RFC_X_CHARSET: + case RFC_X_CHAR_ESC: + // Mark RFC's that we add ourselves + line->kludge = GKLUD_RFC; + return true; + + case RFC_ALSO_CONTROL: + case RFC_APPARENTLY_TO: + case RFC_APPROVED: + case RFC_ARTICLE_NAMES: + case RFC_ARTICLE_UPDATES: + case RFC_COMMENT: + case RFC_COMMENTS: + case RFC_CONTENT_DESCRIPTION: + case RFC_CONTENT_DISPOSITION: + case RFC_CONTENT_ID: + case RFC_CONTENT_LENGTH: + case RFC_CONTROL: + case RFC_DELIVERED_TO: + case RFC_DELIVERY_DATE: + case RFC_DISTRIBUTION: + case RFC_ENCRYPTED: + case RFC_ERRORS_TO: + case RFC_EXPIRES: + case RFC_FOLLOWUP_TO: + case RFC_FROMX: + case RFC_KEYWORDS: + case RFC_LINES: + case RFC_MAILING_LIST: + case RFC_NEWS_SOFTWARE: + case RFC_NNTP_POSTING_HOST: + case RFC_NNTP_POSTING_USER: + case RFC_OLD_DATE: + case RFC_ORIGINATOR: + case RFC_PATH: + case RFC_PRECEDENCE: + case RFC_PRIORITY: + case RFC_RECEIVED: + case RFC_RETURN_PATH: + case RFC_RETURN_RECEIPT_TO: + case RFC_SEE_ALSO: + case RFC_STATUS: + case RFC_SUMMARY: + case RFC_SUPERSEDES: + case RFC_VERSION: + case RFC_XREF: + case RFC_RNEWS: + // Recognized but not processed + return true; + } + + return false; +} + + +// ------------------------------------------------------------------ + +int ScanCtrlList(Kludges* k, char* kludge, char endchar) { + + while(*k->key) { + if((k->req & KCRQ_CASE) ? streql(kludge, k->key) : strieql(kludge, k->key)) { + if(k->req & KCRQ_COLON) { + if(endchar == ':') + return k->num; + } + else { + return k->num; + } + } + k++; + } + + return 0; +} + + +// ------------------------------------------------------------------ + +int ScanLine(GMsg* msg, Line* line, char* ptr, int getvalue, int mask) { + + // Kludge number + int kludgenum = 0; + + // Pointer to kludge id + char* kludge = ptr; + + // Skip past "RFC" string, if any + if(strnieql(kludge, "RFC", 3) and (kludge[3] != ':')) { + kludge += 3; + if(not isalpha(*kludge)) + kludge++; + } + + // Keep copy of id terminating char + while((*ptr != ' ') and (*ptr != ':') and *ptr) + ptr++; + char endchar = *ptr; + *ptr = NUL; + + // Search for it in the known kludges list + if(*kludge) { + Kludges* k; + while(1) { + if(mask & MASK_FTS) { + k = fts_list; + kludgenum = ScanCtrlList(k, kludge, endchar); + if(kludgenum) + break; + } + if(mask & MASK_FSC) { + k = fsc_list; + kludgenum = ScanCtrlList(k, kludge, endchar); + if(kludgenum) + break; + } + if(mask & MASK_RFC) { + k = rfc_list; + kludgenum = ScanCtrlList(k, kludge, endchar); + if(kludgenum) + break; + } + if(mask & MASK_XXX) { + k = xxx_list; + kludgenum = ScanCtrlList(k, kludge, endchar); + if(kludgenum) + break; + } + break; + } + } + + // Restore terminating char + *ptr = endchar; + if(*ptr != ' ') + ptr++; + + if(kludgenum) { + ptr = strskip_wht(ptr); + line->type |= GLINE_KLUD; + if(kludgenum & (MASK_FTS|MASK_FSC|MASK_XXX)) + HandleKludges(msg, line, kludgenum, ptr, getvalue); + else if(kludgenum & MASK_RFC) + HandleRFCs(msg, line, kludgenum, ptr, getvalue); + } + else { + gstrarray::iterator k; + for(k = CFG->kludge.begin(); k != CFG->kludge.end(); k++) { + if(strnieql(kludge, k->c_str(), k->length())) { + line->type |= GLINE_KLUD; + kludgenum = USERDEFINED; + break; + } + } + if(not (line->type & GLINE_KLUD)) + if((strnieql(kludge, "X-", 2) or strnieql(kludge, "Resent-", 7)) and (endchar == ':') and (mask & MASK_RFC)) { + line->type |= GLINE_KLUD; + kludgenum = RFC_X; + } + if(not (line->type & GLINE_KLUD)) + kludgenum = (endchar == ':') ? HEADERLINE : BODYLINE; + } + + return kludgenum; +} + + +// ------------------------------------------------------------------ + +Line* next_non_empty(Line *line) { + Line* nl = line; + + while(nl) { + if(nl->text and not *nl->text) + nl = nl->next; + else + break; + } + return nl; +} + +// ------------------------------------------------------------------ + +void ScanKludges(GMsg* msg, int getvalue) { + + char* ptr; + int tearlineno = INT_MAX; + int originlineno = INT_MAX; + int gotorig=NO, gottear=NO, gottag=NO; + + // Scan for kludge-, tear- and originlines + + msg->tzutc = -32767; // Default value, means TZUTC kludge was not found + + if(getvalue) + goldmark = ' '; // Reset the "recognizer" code + + int lineno = 0; + Line* line = LastLine(msg->lin); + + do { + ptr = line->text; + if(*ptr == CTRL_A) { + + // Set kludge/hidden color + line->color = C_READK; + + int kludgenum = ScanLine(msg, line, ptr+1, getvalue, MASK_ALL); + if((kludgenum == BODYLINE) or (kludgenum == HEADERLINE)) { + line->type |= GLINE_HIDD; + line->color = C_READKH; + } + } + else { + + if(strneql(ptr, "AREA:", 5) and ((line->prev == NULL) or line->prev->text[0] == CTRL_A)) { + line->color = C_READK; + line->kludge = GKLUD_AREA; + line->type |= GLINE_KLUD; + char* areakludgeptr = ptr+5; // Extract echoid from kludge + areakludgeptr = strskip_wht(areakludgeptr); + Area* ap = AL.AreaEchoToPtr(areakludgeptr); + if(ap) + msg->areakludgeid = ap->echoid(); + } + + if(not (line->type & GLINE_KLUD)) { + + // Check if it is a tagline + if(not gottag and (strneql("...", ptr, 3) or strneql("___", ptr, 3))) { + + // It's only a tagline if it's just above the tearline or origin. + // Or if it's the last line in the message. + if(not lineno or ((lineno-1) == tearlineno) or ((lineno-1) == originlineno)) { + gottag = YES; + line->type |= GLINE_TAGL; + line->color = C_READG; + if(AA->Taglinesupport()) + strbtrim(strcpy(msg->tagline, ptr+3)); + } + } + + // Check if it's a tearline + else if(not (gottear or gottag) and strneql("---", ptr, 3) and (ptr[3] == ' ' or ptr[3] == NUL)) { + + Line* nnel = next_non_empty(line->next); + if(not lineno or ((lineno-1) == originlineno) or not nnel or nnel->type & GLINE_KLUDGE) { + // Found Tearline + gottear = YES; + tearlineno = lineno; + line->type |= GLINE_TEAR; + line->color = C_READT; + strbtrim(strcpy(msg->tearline, ptr+3)); + + if(getvalue and CFG->gedhandshake) { + char* tearid[] = { + "GoldED", + " GED ", + " GED2 ", + " GED3 ", + " GED386 ", + " GED/2 ", + " GED/386 ", + " GEDP16 ", + " GEDP32 ", + " GEDW32 ", + " GEDLNX ", + " GED/W32 ", + NULL + }; + int n = 0; + while(tearid[n]) { + if(striinc(tearid[n], ptr)) { + goldmark = GOLDMARK; // Recognize another GoldED msg + break; + } + n++; + } + } + } + } + + // Check if it's an originline + else if(not (gotorig or gottear or gottag) and strneql(" * Origin: ", ptr, 11)) { + + // Found Origin line + bool cnd = line->next and line->next->text; + Line* nnel = next_non_empty(line->next); + bool nextkl = cnd ? not nnel or nnel->type & GLINE_KLUDGE : false; + nnel = cnd ? next_non_empty(line->next->next) : NULL; + bool nextor = cnd ? (not nnel or nnel->type & GLINE_KLUDGE) and strchr(line->next->text, ')') : false; + if(not line->next or nextkl or nextor) { + + gotorig = YES; + originlineno = lineno; + line->type |= GLINE_ORIG; + line->color = C_READO; + strcpy(msg->origin, line->text+11); + if(nextor) { // Get the next line too + strcat(msg->origin, line->next->text); + line->next->color = C_READO; + line->next->type |= GLINE_ORIG; // Mark next line as Origin too + } + } + } + + else if(strneql(ptr, "SEEN-BY:", 8)) { + line->kludge = GKLUD_SEENBY; + line->color = C_READK; + line->type |= GLINE_KLUD; + } + + // Check if it's a signature indicator + else if(AA->isinternet()) { + if(streql(ptr, "-- ")) { + for(Line* q = line; q; q = q->next) { + if((q->type & (GLINE_KLUDGE|GLINE_ORIG|GLINE_TEAR)) == 0) { + q->color = C_READS; + q->type |= GLINE_SIGN; + if(q != line) + q->type |= GLINE_HARD; + if(q->text and strneql("----", q->text, 4)) + break; + } + } + } + } + } + } + if(line->type & GLINE_WRAP) { + Line* linep = line; + while(linep and (linep->type & GLINE_WRAP)) { + if(linep->next) { + linep->next->type |= linep->type & GLINE_KLUDGE; + linep->next->kludge = linep->kludge; + linep->next->color = linep->color; + } + linep = linep->next; + } + } + + lineno++; + + } while((line = line->prev) != NULL); + + for(line = msg->lin; line; line = line->next) + if(line->type & GLINE_KLUDGE) + continue; + else if(line->text) { + if(strnieql(line->text, "From:", 5)) { + char* ptr = line->text + 5; + ptr = strskip_wht(ptr); + char* tmp = UnwrapLine(line, ptr); + KludgeFROM(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + if(not AA->isinternet()) + *msg->ifrom = NUL; + } + else if(strnieql(line->text, "To:", 3)) { + char* ptr = line->text + 3; + ptr = strskip_wht(ptr); + char* tmp = UnwrapLine(line, ptr); + KludgeTO(msg, tmp ? tmp : ptr); + if(tmp) + throw_free(tmp); + if(not AA->isinternet()) + *msg->ito = NUL; + } + else + break; + } + else + break; + + if(not gottag) + *msg->tagline = NUL; + if(not gottear) + *msg->tearline = NUL; + if(not gotorig) + *msg->origin = NUL; + + if(getvalue) { + // This is the new code (experimental) + // It looks for an Origin before taking MSGID + // Trust msg->orig if valid and we're in netmail area. + // (msg->orig is already merged with INTL/FMPT/TOPT) + + if(not (AA->isnet() and msg->orig.valid())) { + if(CFG->addresslookupfirst and msg->msgid.valid()) + msg->orig = msg->msgid; + else if((ptr = strrchr(msg->origin, '(' /*)*/ )) != NULL) { + while(not isdigit(*ptr) and *ptr) + ptr++; + msg->orig.reset(ptr); + } + else if(msg->msgid.valid()) + msg->orig = msg->msgid; + } + + if(msg->orig.zone == 0) + msg->orig.zone = msg->msgid.zone ? msg->msgid.zone : AA->Aka().addr.zone; + + if(msg->dest.zone == 0) + msg->dest.zone = msg->orig.zone; + } +} + + +// ------------------------------------------------------------------ + +char* XlatStr(char* dest, char* src, int level, Chs* chrtbl, int qpencoded, bool i51) { + + if(not chrtbl) + return stpcpy(dest, src); + + uint n; + int clen; + int translated; + char* tptr; + char* escp; + char* sptr = src; + char* dptr = dest; + char dochar; + ChsTab* chrs = chrtbl ? chrtbl->t : (ChsTab*)NULL; + + while(*sptr) { + switch(*sptr) { + case 0x02: + if(i51 and I51Table) { + for(n=0; nsize; n++) { + tptr = (char*)I51TP[n]; + if(*(sptr+1) == tptr[0]) { + if(*(sptr+2) == tptr[1]) { + escp = &tptr[2]; + if(*escp) { + *dptr++ = *escp++; + if(*escp) { + *dptr++ = *escp++; + if(*escp) { + *dptr++ = *escp; + } + } + } + sptr += 2; + n = (uint)-1; + break; + } + } + } + if(n != (uint)-1) // I51 char not found, use fallback method + sptr++; + } + sptr++; + break; + + case 29: + if(MNETable) { + for(n=0; nsize; n++) { + tptr = (char*)MNETP[n]; + if(*(sptr+1) == tptr[0]) { + if(*(sptr+2) == tptr[1]) { + escp = &tptr[2]; + if(*escp) { + *dptr++ = *escp++; + if(*escp) { + *dptr++ = *escp++; + if(*escp) { + *dptr++ = *escp; + } + } + } + sptr += 2; + n = (uint)-1; + break; + } + } + } + if(n != (uint)-1) // MNEMONIC char not found, use fallback method + sptr++; + } + sptr++; + break; + + case SOFTCR: + translated = false; + if(CompTable and not CFG->switches.get(dispsoftcr)) { + if(sptr > src) { + if(not (isspace(*(sptr-1)) or isspace(*(sptr+1)))) { + for(n=0; nsize; n++) { + tptr = (char*)CompTP[n]; + if(*(sptr-1) == tptr[0]) { + if(*(sptr+1) == tptr[1]) { + escp = &tptr[2]; + if(*escp) { + dptr--; + *dptr++ = *escp++; + if(*escp) { + *dptr++ = *escp++; + if(*escp) { + *dptr++ = *escp; + translated = true; + } + } + } + sptr += 2; + break; + } + } + } + } + } + } + else if(CFG->switches.get(dispsoftcr)) + goto defaultchardo; + if(not translated) + *dptr++ = *sptr++; + break; + + case '=': + if(qpencoded) { + if(isxdigit(sptr[1]) and isxdigit(sptr[2])) { + dochar = (char)((xtoi(sptr[1]) << 4) | xtoi(sptr[2])); + sptr += 3; + goto chardo; + } + } + goto defaultchardo; + + default: + defaultchardo: + dochar = *sptr++; + chardo: + if((level&3) and chrs) { // Translate level 1 and 2 + tptr = (char*)chrs[(byte)dochar]; + clen = *tptr++; + while(clen--) + *dptr++ = *tptr++; + } + else { + *dptr++ = dochar; + } + } + } + *dptr = NUL; + return dptr; +} + + +// ------------------------------------------------------------------ + +static int cmp_quotes(char* q1, char* q2) { + + q1--; + q2--; + + do { + q1 = spanspaces(++q1); + q2 = spanspaces(++q2); + if(*q2 == 0) + return YES; + if(*q1 != *q2) + return NO; + } while(*q1 and *q2); + + return *q1 == *q2; +} + + +// ------------------------------------------------------------------ + +void GMsg::TextToLines(int __line_width, bool header_recode) { + + line_width = __line_width; + + MakeLineIndex(this, line_width, header_recode); +} + + +// ------------------------------------------------------------------ + +bool check_multipart(const char* ptr, const char* keptr, char* boundary) { + + if(striinc("multipart", ptr)) { + const char* boundptr = striinc("boundary=", ptr); + if(not boundptr) + boundptr = striinc("boundary=", keptr+1); + if(boundptr) { + boundptr += 9; + const char* boundend; + if(*boundptr == '"') { + boundptr++; + boundend = strchr(boundptr, '"'); + } + else { + boundend = strpbrk(boundptr, " \r\n"); + } + if(boundend) { + strxcpy(boundary, boundptr, 1+boundend-boundptr); + return true; + } + } + } + return false; +} + + +// ------------------------------------------------------------------ + +void MakeLineIndex(GMsg* msg, int margin, bool header_recode) { + + uint idx=0; + uint len; + int level=0; + uint n; + char ch, chln = 0, dochar; + Line* line; + Line* nextline=NULL; + Line* prevline=NULL; + char* bp; + char* btmp=NULL; + char* tptr; + char* escp; + char* bptr; + char buf[256], qbuf[500], qbuf2[500], chsbuf[100]; + char* ptr; + char* qptr; + char* tmp=NULL; + char* linetmp=NULL; + uint qlen=0, qlen2=0; + int wraps=0, para=0, reflow=NO, quoteflag=NO, chslev; + int getvalue = not msg->attr.tou(); + bool quotewraphard = AA->Quotewraphard(); + int qpencoded = strieql(AA->Xlatimport(), "LATIN1QP") ? true : false; + int gotmime = false; + int firstemptyline = false; + bool gotmultipart = false; + bool inheader = false; + char boundary[100]; + + *buf = *qbuf = *qbuf2 = NUL; + + if(margin < 0) { + margin = -margin; + quoteflag = YES; + } + + // Free all previously allocated lines + line = msg->lin; + while(line) { + nextline = line->next; + throw_release(line->text); + throw_xfree(line); + line = nextline; + } + + msg->lines = 0; + msg->lin = NULL; + + if(AA->attr().hex()) { + + // Make a complete hexdump as a list of message lines + w_info(LNG->GenHexdump); + throw_release(msg->txt); + line = AA->MakeDumpMsg(msg, LNG->Hexdumphead); + if(line and msg->txt) { + line = AddLine(line, ""); + line = AddLine(line, LNG->Hexdumptext); + line = AddLine(line, ""); + ptr = msg->txt; + uint _size = strlen(msg->txt); + for(idx=0; idx < _size; ptr+=16,idx+=16) { + sprintf(buf, "%04X ", idx+(AA->isfido()?190:0)); + HexDump16(buf+7, ptr, MinV((int)(_size-idx), 16), HEX_DUMP2); + line = AddLine(line, buf); + } + } + + w_info(NULL); + } + else { // Convert the message text to a list of separately allocated lines + + char prev_ptr[3] = {"\xFF\xFF"}; + + ptr = msg->txt; + + // Set default conversion table for area + if(getvalue) { + if(not strieql(AA->Xlatimport(), CFG->xlatlocalset)) { + memset(msg->charset, 0, sizeof(msg->charset)); + strcpy(msg->charset, AA->Xlatimport()); + level = msg->charsetlevel = LoadCharset(msg->charset, CFG->xlatlocalset); + } + } + + line = msg->lin = (Line*)throw_xcalloc(1, sizeof(Line)); + + ptr = spanfeeds(ptr); + + if(*ptr == NUL) { + throw_xrelease(msg->lin); + } + else { + // Alloc space for one line + linetmp = (char*)throw_calloc(1, margin+512); + while(*ptr) { + + bptr = linetmp; + bp = bptr; + len = 0; + + // Link previous line to this one + + if(line->prev) { + line->prev->next = line; + if((line->prev->type & (GLINE_HARD|GLINE_WRAP|GLINE_QUOT)) == (GLINE_HARD|GLINE_WRAP)) { + line->prev->type ^= GLINE_HARD; + line->type |= GLINE_HARD; + } + } + + // Reflow quotes + + if(reflow) { + len = qlen; + qptr = qbuf; + reflow = NO; + // Insert previous quotestring + for(n=0; ntype |= GLINE_QUOT|GLINE_HARD; + } + + // Get type of line + + if(wraps == 0) { + + if(gotmultipart) { + if(*ptr == '-' and ptr[1] == '-' and strneql(ptr+2, boundary, strlen(boundary))) + inheader = true; + else if(*ptr == '\n' or *ptr == '\r') + inheader = false; + } + + if(inheader and (*ptr != '-')) + line->type |= GLINE_HIDD; + + para = 0; + if(*ptr == CTRL_A or inheader) { // Found kludge/hidden line + line->type |= GLINE_HARD; + if(getvalue and not CFG->ignorecharset) { + tptr = ptr; + char* kludge = ptr + (*ptr == CTRL_A ? 1 : 0); + if(strnieql(kludge, "RFC", 3)) { + kludge += 3; + if(not isalpha(*kludge)) + kludge++; + } + while((*ptr != ' ') and (*ptr != ':') and *ptr) + ptr++; + char endchar = *ptr; + *ptr = NUL; + int kludgetype = -1; + if(strieql(kludge, "I51")) + kludgetype = FSC_I51; + else if(strieql(kludge, "CHRS") or strieql(kludge, "CHARSET")) + kludgetype = FSC_CHARSET; + else if(strieql(kludge, "Content-Type")) + kludgetype = RFC_CONTENT_TYPE; + else if(strieql(kludge, "Content-Transfer-Encoding")) + kludgetype = RFC_CONTENT_TRANSFER_ENCODING; + else if(strieql(kludge, "X-Charset")) + kludgetype = RFC_X_CHARSET; + else if(strieql(kludge, "X-Char-Esc")) + kludgetype = RFC_X_CHAR_ESC; + *ptr = endchar; + if(*ptr != ' ') + ptr++; + ptr = strskip_wht(ptr); + char* keptr = strpbrk(ptr, "\r\n"); + if(keptr) { + endchar = *keptr; + *keptr = NUL; + } + if(kludgetype == FSC_I51) { + msg->i51 = true; + if(getvalue) { + // Convert FSC-0051.003 to FSC-0054.003 + strcpy(chsbuf, "LATIN-1"); + chslev = LoadCharset(chsbuf, CFG->xlatlocalset); + if(chslev) { + level = msg->charsetlevel = chslev; + strcpy(msg->charset, chsbuf); + } + } + } + else if(kludgetype == FSC_CHARSET) { + if(getvalue) { + *chsbuf = NUL; + qpencoded = striinc("LATIN1QP", ptr) ? true : false; + strxcpy(chsbuf, qpencoded ? "LATIN-1" : ptr, sizeof(chsbuf)); + // Workaround for buggy mailreaders which stores '_' in charset name + strchg(chsbuf,'_',' '); + chslev = LoadCharset(chsbuf, CFG->xlatlocalset); + if(chslev) { + level = msg->charsetlevel = chslev; + strcpy(msg->charset, chsbuf); + } + } + } + else if(kludgetype == RFC_CONTENT_TYPE) { + if(getvalue) { + if(striinc("iso-8859-1", ptr)) { + strcpy(chsbuf, "LATIN-1"); + chslev = LoadCharset(chsbuf, CFG->xlatlocalset); + if(chslev) { + level = msg->charsetlevel = chslev; + strcpy(msg->charset, chsbuf); + } + gotmime = true; + } + if(check_multipart(ptr, keptr, boundary)) { + gotmultipart = true; + gotmime = true; + } + } + } + else if(kludgetype == RFC_CONTENT_TRANSFER_ENCODING) { + if(getvalue) { + if(striinc("quoted-printable", ptr)) { + qpencoded = true; + msg->charsetencoding |= GCHENC_QP; + if(striinc("LATIN-1", msg->charset)) { + strcpy(chsbuf, "LATIN1QP"); + chslev = LoadCharset("LATIN-1", CFG->xlatlocalset); + if(chslev) { + level = msg->charsetlevel = chslev; + strcpy(msg->charset, chsbuf); + } + } + } + } + } + else if(kludgetype == RFC_X_CHARSET) { + if(getvalue) { + if(not gotmime) { + strcpy(chsbuf, (striinc("8859-1", ptr) or striinc("Latin1", ptr)) ? "LATIN-1" : CFG->xlatlocalset); + chslev = LoadCharset(chsbuf, CFG->xlatlocalset); + if(chslev) { + level = msg->charsetlevel = chslev; + strcpy(msg->charset, chsbuf); + } + } + } + } + else if(kludgetype == RFC_X_CHAR_ESC) { + if(getvalue) + if(not gotmime) + msg->charsetencoding |= GCHENC_MNE; + } + if(keptr) + *keptr = endchar; + ptr = tptr; + } + } + else if(is_quote(ptr)) { + para = GLINE_QUOT; + line->type |= GLINE_QUOT|GLINE_HARD; + GetQuotestr(ptr, qbuf, &qlen); + } + } + + // Get one line + + ch = 0; + tmp = NULL; + while(*ptr and (len < (uint)margin)) { + switch(*ptr) { + case CR: + do_cr: + ptr++; + ch = CR; + ptr = spanfeeds(ptr); + if(wraps and not ((line->type & GLINE_HARD) and not (line->type & GLINE_QUOT))) { + if(para != GLINE_QUOT) { + if(quoteflag) { + if(prevline and prevline->text[0] == CTRL_A and prevline->type & GLINE_WRAP) { + wraps = 0; + break; + } + if(*ptr == CR or is_quote(ptr) or *ptr == CTRL_A) { + wraps = 0; + break; + } + if(((ptr[0] == ptr[1]) and (ptr[0] == ptr[2])) or strneql(ptr, " * Origin: ", 11)) { + wraps = 0; + break; + } + if(strneql(ptr, "SEEN-BY:", 8)) { + wraps = 0; + break; + } + if((ptr[0] == prev_ptr[0]) and (ptr[1] == prev_ptr[1])) { + wraps = 0; + break; + } + char* lp = ptr; + while(*lp == ' ') + lp++; + if(*lp == CR) { + wraps = 0; + break; + } + else { + ptr = lp; + } + if(*ptr != ' ' and *ptr != '\t' and *bp != ' ') { + *(++bp) = ' '; + len++; + } + ch = 0; + continue; + } + else { + wraps=0; + break; + } + } + else { + GetQuotestr(ptr, qbuf2, &qlen2); + if(*ptr == CR) { + wraps = 0; + para = 0; + break; + } + else if(cmp_quotes(qbuf2, qbuf)) { + char* lp = ptr + qlen2; + if(is_quote(lp)) { + wraps = 0; + para = 0; + break; + } + else { + ptr = lp; + para = GLINE_QUOT; + if(*ptr != ' ' and *bp != ' ') { + *(++bp) = ' '; + len++; + } + ch = 0; + continue; + } + } + else { + wraps = 0; + para = 0; + break; + } + } + } + break; + case 0x02: // The I51 escape character + if(msg->i51 and I51Table) { + for(n=0; nsize; n++) { + tptr = (char*)I51TP[n]; + if(*(ptr+1) == tptr[0]) { + if(*(ptr+2) == tptr[1]) { + escp = &tptr[2]; + if(*escp) { + *(++bp) = *escp++; + if(*escp) { + *(++bp) = *escp++; + len++; + if(*escp) { + *(++bp) = *escp; + len++; + } + } + } + ptr += 2; + n = (uint)-1; + break; + } + } + } + if(n != (uint)-1) // I51 char not found, use fallback method + ptr++; + } + ptr++; + break; + case 29: // The MNE escape character + if(MNETable) { + for(n=0; nsize; n++) { + tptr = (char*)MNETP[n]; + if(*(ptr+1) == tptr[0]) { + if(*(ptr+2) == tptr[1]) { + escp = &tptr[2]; + if(*escp) { + *(++bp) = *escp++; + if(*escp) { + *(++bp) = *escp++; + len++; + if(*escp) { + *(++bp) = *escp; + len++; + } + } + } + ptr += 2; + n = (uint)-1; + break; + } + } + } + if(n != (uint)-1) // MNE char not found, use fallback method + ptr++; + } + ptr++; + break; + case SOFTCR: + if(CFG->switches.get(dispsoftcr)) + goto defaultchardo; + else { + if(CompTable) { + if(not (isspace(*(ptr-1)) or isspace(*(ptr+1)))) { + for(n=0; nsize; n++) { + tptr = (char*)CompTP[n]; + if(*(ptr-1) == tptr[0]) { + if(*(ptr+1) == tptr[1]) { + escp = &tptr[2]; + if(*escp) { + *(bp) = *escp++; + if(*escp) { + *(++bp) = *escp++; + len++; + if(*escp) { + *(++bp) = *escp; + len++; + } + } + } + ptr++; + break; + } + } + } + } + else if(para == GLINE_QUOT) { + *ptr-- = CR; // Fake a CR + } + } + else if(para == GLINE_QUOT) { + *ptr-- = CR; // Fake a CR + } + ptr++; + } + break; + case LF: + ptr++; + break; + case CTRL_A: + *(++bp) = *ptr++; + ++len; + break; + case '\t': + ptr++; + do_ht: + if(CFG->disptabsize) { + int llen = (int)(bp-linetmp); + for(n=0; n<(CFG->disptabsize-(llen%CFG->disptabsize)); n++) { + *(++bp) = ' '; + len++; + } + } + else { + *(++bp) = ' '; + len++; + } + break; + case '=': + if(qpencoded) { + if(isxdigit(ptr[1]) and isxdigit(ptr[2])) { + // Decode the character + dochar = (char)((xtoi(ptr[1]) << 4) | xtoi(ptr[2])); + ptr += 3; + if(dochar == '\t') + goto do_ht; + else if(dochar == CR) + goto do_cr; + goto chardo; + } + else if((ptr[1] == CR) or (ptr[1] == LF)) { + // Skip soft line break + ptr++; + while((*ptr == CR) or (*ptr == LF)) + ptr++; + break; + } + } + goto defaultchardo; + case ' ': + if(len >= qlen) { + tmp = ptr; + btmp = bp; + } + default: + defaultchardo: + dochar = *ptr++; + chardo: + if((level&3) and ChsTP) { // Translate level 1 and 2 + tptr = (char*)ChsTP[(byte)dochar]; + chln = *tptr++; + while(chln--) { + *(++bp) = *tptr++; + ++len; + } + } + else { + *(++bp) = dochar; + ++len; + } + break; + } + if(ch == CR) + break; + } + + if(len == (uint)margin) { + if(*ptr == CR) { + line->type |= GLINE_HARD; + wraps = 0; + ptr++; + } + else { + wraps++; + if(para == GLINE_QUOT) + reflow = quotewraphard; + line->type |= GLINE_WRAP; + ptr = spanfeeds(ptr); + if(*bp == ' ' or isspace(*ptr)) + ptr = spanspaces(ptr); + else { + if(tmp) { + bp = btmp+1; + ptr = tmp+1; + } + } + } + } + else + line->type |= GLINE_HARD; + + *(bp+1) = NUL; + + // Get line length + uint tmplinelength = (uint)((long)bp-(long)bptr); + if(tmplinelength > (uint)(margin + 512)) { + LOG.ErrPointer(); + LOG.printf("! A message line length (%u bytes) exceeded an internal buffer limit of %u bytes", tmplinelength, margin+512); + LOG.printf(": Message line text: %s", bptr+1); + PointerErrorExit(); + } + + // Store line + if(line->isallocated()) + throw_free(line->text); + line->text = (char*)throw_malloc(tmplinelength+10); + line->type &= ~GLINE_NOAL; + memcpy(line->text, linetmp+1, tmplinelength+5); + prev_ptr[0] = line->text[0]; + prev_ptr[1] = line->text[1]; + + // Set line color and type + if((line->type & GLINE_QUOT) and not is_quote(line->text)) + line->type ^= GLINE_QUOT; + if(line->type & GLINE_QUOT) + line->color = quotecolor(line->text); + else if(inheader) + line->color = C_READT; + else + line->color = C_READW; + + // Scan msg body top for RFC headerlines + if((*line->text == NUL) and not firstemptyline) { + firstemptyline = true; + if(AA->Internetrfcbody()) { + Line* linep = FirstLine(line); + int headerlines = 0; + while(linep) { + char* tptr = linep->text; + if(*tptr) { + if(*tptr != CTRL_A) { + int kludgetype = ScanLine(msg, linep, tptr, getvalue, MASK_RFC); + if(kludgetype) { + tptr = strchr(tptr, ' '); + if(tptr) { + tptr = strskip_wht(tptr); + if(kludgetype == RFC_CONTENT_TYPE) { + if(getvalue) { + if(striinc("iso-8859-1", tptr)) { + strcpy(chsbuf, "LATIN-1"); + chslev = LoadCharset(chsbuf, CFG->xlatlocalset); + if(chslev) { + level = msg->charsetlevel = chslev; + strcpy(msg->charset, chsbuf); + } + gotmime = true; + } + else { + const char* keptr = linep->next ? linep->next->text : " "; + if(check_multipart(ptr, keptr, boundary)) { + gotmultipart = true; + gotmime = true; + } + } + } + } + else if(kludgetype == RFC_CONTENT_TRANSFER_ENCODING) { + if(getvalue) { + if(striinc("quoted-printable", tptr)) { + qpencoded = true; + msg->charsetencoding |= GCHENC_QP; + if(striinc("LATIN-1", msg->charset)) { + strcpy(chsbuf, "LATIN1QP"); + chslev = LoadCharset("LATIN-1", CFG->xlatlocalset); + if(chslev) { + level = msg->charsetlevel = chslev; + strcpy(msg->charset, chsbuf); + } + } + } + } + } + else if(kludgetype == RFC_X_CHARSET) { + if(getvalue) { + if(not gotmime) { + strcpy(chsbuf, (striinc("8859-1", tptr) or striinc("Latin1", tptr)) ? "LATIN-1" : CFG->xlatlocalset); + chslev = LoadCharset(chsbuf, CFG->xlatlocalset); + if(chslev) { + level = msg->charsetlevel = chslev; + strcpy(msg->charset, chsbuf); + } + } + } + } + else if(kludgetype == RFC_X_CHAR_ESC) { + if(getvalue) + if(not gotmime) + msg->charsetencoding |= GCHENC_MNE; + } + else if(kludgetype == HEADERLINE) { + linep->type |= GLINE_HIDD; + } + } + headerlines++; + if(linep->type == GLINE_HIDD) + linep->color = C_READKH; + else + linep->color = C_READK; + if(linep->next) { + char lwsp = *linep->next->text; + while((lwsp == ' ') or (lwsp == '\t') or (linep->type & GLINE_WRAP)) { + linep = linep->next; + linep->type |= linep->prev->type; + linep->color = linep->prev->color; + if(linep->next) + lwsp = *linep->next->text; + else + break; + } + } + } + else + break; + } + } + else { + if(headerlines) { + linep->type |= GLINE_KLUD; + linep->color = C_READK; + } + break; + } + if(linep->type & GLINE_WRAP) { + while(linep and (linep->type & GLINE_WRAP)) + linep = linep->next; + } + if(linep) + linep = linep->next; + } + } + } + + prevline = line; + line = (Line*)throw_xcalloc(1, sizeof(Line)); + line->prev = prevline; + + ptr = spanfeeds(ptr); + } + + throw_release(linetmp); + if(line->isallocated()) + throw_free(line->text); + throw_xfree(line); + + // Scan for kludge-, tear- and originlines + ScanKludges(msg, getvalue); + + // Charset translate header fields + if(header_recode) { + strxmimecpy(msg->realby, msg->realby, level, sizeof(INam)); + strxmimecpy(msg->realto, msg->realto, level, sizeof(INam)); + strxmimecpy(msg->by , msg->by , level, sizeof(INam)); + strxmimecpy(msg->to , msg->to , level, sizeof(INam)); + + if(not (msg->attr.frq() or msg->attr.att() or msg->attr.urq())) + strxmimecpy(msg->re , msg->re , level, sizeof(ISub), true); + } + } + } + + // Make the index to the line index as allowed by config + MsgLineReIndex(msg); +} + + +// ------------------------------------------------------------------ + +void MsgLineReIndex(GMsg* msg, int viewhidden, int viewkludge, int viewquote) { + + if(viewhidden == -1) + viewhidden = AA->Viewhidden(); + if(viewkludge == -1) + viewkludge = AA->Viewkludge(); + if(viewquote == -1) + viewquote = AA->Viewquote(); + + int x; + Line* line; + + throw_xrelease(msg->line); + line = msg->lin; + msg->lines = 0; + while(line) { + msg->lines++; + if(line->next) { + if(line->type & GLINE_QUOT) { + if(not (line->next->type & GLINE_QUOT) and not strblank(line->next->text)) { + if(CFG->switches.get(quotespacing)) { + line = AddLine(line, ""); + msg->lines++; + } + } + } + else { + if(msg->attr.pos()) + if(strischg(line->text, "@position", "")) + line->type |= GLINE_POSI; + if((line->next->type & GLINE_QUOT) and not strblank(line->text)) { + if(CFG->switches.get(quotespacing)) { + line = AddLine(line, ""); + msg->lines++; + } + } + } + } + line = line->next; + } + + msg->line = (Line**)throw_xcalloc(msg->lines+2, sizeof(Line*)); + + x = 0; + msg->lines = 0; + line = msg->lin; + + char qbuf[50]; + char qbuf0[50]; + uint qlen = 0; + int qmatches = 0; + + *qbuf0 = NUL; + while(line) { + if(line->type & GLINE_KLUD) { + *qbuf0 = NUL; + qmatches = 0; + if(not viewkludge) { + line = line->next; + continue; + } + } + else if(line->type & GLINE_HIDD) { + *qbuf0 = NUL; + qmatches = 0; + if(not viewhidden) { + line = line->next; + continue; + } + } + else if(line->type & GLINE_QUOT) { + if(not viewquote) { + GetQuotestr(line->text, qbuf, &qlen); + strtrim(qbuf); + if(strieql(qbuf0, qbuf)) { + if(strpbrk(line->text+qlen, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) + qmatches++; + } + else { + strcpy(qbuf0, qbuf); + if(strpbrk(line->text+qlen, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) + qmatches = 1; + else + qmatches = 0; + } + if(qmatches != 1) { + line = line->next; + continue; + } + } + } + else { + *qbuf0 = NUL; + qmatches = 0; + } + msg->line[x++] = line; + msg->lines++; + line = line->next; + } + + msg->line[x] = NULL; // Mark end of index + + // Calculate quote percent + int quotes = 0, nonquotes = 0; + + line = msg->lin; + while(line) { + if(not (line->type & (GLINE_KLUDGE|GLINE_TEAR|GLINE_ORIG))) { + if(line->text) { + int n = strlen(line->text); + nonquotes += n; + if(line->type & GLINE_QUOT) + quotes += n; + } + } + line = line->next; + } + msg->quotepct = 100-Pct(nonquotes, quotes); +} + + +// ------------------------------------------------------------------ + +int LoadCharset(const char* imp, const char* exp, int query) { + + static int current_table = -1; + FILE* fp; + int n; + + switch(query) { + case 1: + return current_table; + default: + break; + } + + // Find and load charset table + vector::iterator xlt; + for(n = 0, xlt = CFG->xlatcharset.begin(); xlt != CFG->xlatcharset.end(); xlt++, n++) { + if(striinc(xlt->imp, imp) and striinc(xlt->exp, exp)) { + // Already loaded? + if(CharTable and CharTable->level!=0 and n==current_table) + return CharTable->level; + fp = fsopen(AddPath(CFG->goldpath, CFG->xlatged), "rb", CFG->sharemode); + if(fp) { + if(not CharTable) + CharTable = (Chs*)throw_calloc(1, sizeof(Chs)); + fseek(fp, ((long)n*(long)sizeof(Chs)), SEEK_SET); + fread(CharTable, sizeof(Chs), 1, fp); + fclose(fp); + ChsTP = CharTable->t; + current_table = n; + + // Disable softcr translation unless DISPSOFTCR is enabled + if(not CFG->switches.get(dispsoftcr)) { + char* tptr = (char*)ChsTP[SOFTCR]; + *tptr++ = 1; + *tptr = SOFTCR; + } + return CharTable->level; + } + } + } + + // No matching table found + throw_release(CharTable); + ChsTP = NULL; + current_table = -1; + return 0; +} + + +// ------------------------------------------------------------------ + +Line* DeleteLine(Line* line) { + + Line* nextline = NULL; + + // Link next and previous lines and release this line + + if(line) { + if(line->prev) { + line->prev->next = line->next; + nextline = line->prev; + } + if(line->next) { + line->next->prev = line->prev; + nextline = line->next; + } + throw_release(line->text); + throw_xfree(line); + } + + return nextline; +} + + +// ------------------------------------------------------------------ + +Line* InsertLine(Line* newline, Line* oldline, int pos) { + + if(oldline) { + if(pos >= DIR_BELOW) { + newline->prev = oldline; + newline->next = oldline->next; + if(oldline->next) + oldline->next->prev = newline; + oldline->next = newline; + } + else { + newline->prev = oldline->prev; + newline->next = oldline; + if(oldline->prev) + oldline->prev->next = newline; + oldline->prev = newline; + } + } + return newline; +} + + +// ------------------------------------------------------------------ + +Line* FirstLine(Line* line) { + + if(line) + while(line->prev) + line = line->prev; + return line; +} + + +// ------------------------------------------------------------------ + +Line* LastLine(Line* line) { + + if(line) + while(line->next) + line = line->next; + return line; +} + + +// ------------------------------------------------------------------ + +Line* AddLine(Line* line, char* buf, int where) { + + Line* newline; + + newline = (Line*)throw_xcalloc(1, sizeof(Line)); + newline->type = GLINE_HARD; + newline->text = (char*)throw_malloc(strlen(buf)+10); + newline->color = C_READW; + strcpy(newline->text, buf); + + return InsertLine(newline, line, where); +} + + +// ------------------------------------------------------------------ + +Line* AddLine(Line* line, char* buf) { + + return AddLine(line, buf, DIR_BELOW); +} + + +// ------------------------------------------------------------------ + +Line* AddLineFast(Line* oldline, char* text) { + + Line* newline = (Line*)throw_xcalloc(1, sizeof(Line)); + newline->type = GLINE_HARD|GLINE_NOAL; + newline->text = text; + newline->color = C_READW; + newline->prev = oldline; + newline->next = oldline->next; + if(oldline->next) + oldline->next->prev = newline; + oldline->next = newline; + return newline; +} + + +// ------------------------------------------------------------------ + +Line* AddKludge(Line* line, char* buf, int where) { + + Line* newline; + + newline = (Line*)throw_xcalloc(1, sizeof(Line)); + newline->type = GLINE_HARD|GLINE_KLUD; + newline->text = (char*)throw_malloc(strlen(buf)+10); + newline->color = C_READK; + strcpy(newline->text, buf); + + return InsertLine(newline, line, where); +} + + +// ------------------------------------------------------------------ + +Line* AddLineF(Line*& line, const char* format, ...) { + + char buf[256]; + va_list argptr; + va_start(argptr, format); + vsprintf(buf, format, argptr); + va_end(argptr); + line = AddLine(line, buf); + return line; +} + + +// ------------------------------------------------------------------ + +Line* AddHexdump(Line*& line, void* data, size_t datalen) { + + char buf[256]; + uint pos = 0; + char* ptr = (char*)data; + + while(pos < datalen) { + + uint dataleft = datalen - pos; + sprintf(buf, "%04X ", pos); + HexDump16(buf+7, ptr, (dataleft < 16) ? dataleft : 16, HEX_DUMP2); + line = AddLine(line, buf); + ptr += 16; + pos += 16; + } + + return line; +} + + +// ------------------------------------------------------------------ + +char* ParseInternetAddr(char* __string, char* __name, char* __addr) { + + *__name = *__addr = NUL; + char* name = __name; + char* addr = __addr; + char* commaptr = NULL; + + if(strchr(__string, ',')) { + bool inquotes = false; + commaptr = __string; + while(commaptr) { + if(*commaptr == '\"') + inquotes = not inquotes; + else if((*commaptr == ',') and not inquotes) { + *commaptr = NUL; + break; + } + if(not *commaptr) + commaptr = NULL; + else + commaptr++; + } + } + + char* p; + if((p = strrchr(__string, '>')) != NULL) + *(++p) = NUL; + + char* endchar = __string + strlen(__string) - 1; + if(*endchar == /*(*/ ')') { + char* begchar = endchar; + int pcnt = 0; + while(begchar > __string) { + if(*begchar == /*(*/ ')') + pcnt++; + else if(*begchar == '(' /*)*/) + pcnt--; + if(pcnt == 0) + break; + begchar--; + } + if(*begchar == '(' /*)*/) + begchar++; + if(not strchr(__string, '@') and strchr(begchar, '@')) { + name = __addr; + addr = __name; + } + strbtrim(strxcpy(name, begchar, (uint)(endchar-begchar)+1)); + strbtrim(strxcpy(addr, __string, (uint)(begchar-__string))); + } + else if(*endchar == '>') { + char* endaddr = endchar; + while(*endchar != '<' and endchar > __string) + endchar--; + char* begaddr = endchar; + if(*endchar == '<') { + begaddr++; + endchar--; + } + __string = strskip_wht(__string); + if(not strchr(begaddr, '@') and strchr(__string, '@')) { + name = __addr; + addr = __name; + } + strbtrim(strxcpy(name, __string, (uint)(endchar-__string)+1)); + strbtrim(strxcpy(addr, begaddr, (uint)(endaddr-begaddr)+1)); + } + else { + strcpy(__addr, __string); + } + + if(*__addr == '@') { + char* ptr = strchr(__addr, ':'); + if(ptr) + memmove(__addr, ptr+1, strlen(ptr)); + } + + if(commaptr) + *commaptr = ','; + + StripQuotes(__name); + + return __name; +} + + +// ------------------------------------------------------------------ + +void InvalidateControlInfo(GMsg* msg) { + + Line* line = msg->lin; + char buf[256]; + + // This required if we change tearline / origin lines + ScanKludges(msg, 0); + + while(line) { + + if(line->text and not (line->type & (GLINE_TEAR | GLINE_ORIG))) { + + strcpy(buf, line->text); + + // Invalidate tearline + if(not CFG->invalidate.tearline.first.empty()) + doinvalidate(buf, CFG->invalidate.tearline.first.c_str(), CFG->invalidate.tearline.second.c_str(), true); + else + doinvalidate(buf, "---", "-+-", true); + + // Invalidate originline + if(not CFG->invalidate.origin.first.empty()) + doinvalidate(buf, CFG->invalidate.origin.first.c_str(), CFG->invalidate.origin.second.c_str()); + else + doinvalidate(buf, " * Origin: ", " + Origin: "); + + // Invalidate SEEN-BY's + if(not CFG->invalidate.seenby.first.empty()) + doinvalidate(buf, CFG->invalidate.seenby.first.c_str(), CFG->invalidate.seenby.second.c_str()); + else + doinvalidate(buf, "SEEN-BY: ", "SEEN+BY: "); + + if(stricmp(buf, line->text)) { + line->type &= ~GLINE_KLUDGE; + throw_release(line->text); + line->text = (char*)throw_malloc(strlen(buf)+10); + strcpy(line->text, buf); + } + + } + line = line->next; + } +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gelmsg.cpp b/golded3/gelmsg.cpp new file mode 100644 index 0000000..4a87016 --- /dev/null +++ b/golded3/gelmsg.cpp @@ -0,0 +1,122 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Load message or header. Save header. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +void ResetMsg(GMsg* msg) { + + throw_xfree(msg->references); + throw_xfree(msg->inreplyto); + throw_xfree(msg->messageid); + throw_xfree(msg->txt); + throw_xfree(msg->line); + Line* line = msg->lin; + while(line) { + Line* nextline = line->next; + if(line->isallocated()) + throw_free(line->text); + throw_xfree(line); + line = nextline; + } + memset(msg, 0, sizeof(GMsg)); +} + + +// ------------------------------------------------------------------ + +int Area::LoadHdr(GMsg* msg, ulong msgno) { + + ResetMsg(msg); + msg->msgno = msgno; + int retval = area->load_hdr(msg); + + // Don't translate charsets if we don't know charset + // Currently, it only mime-decodes, so it's okay. + if(retval) { + // Charset translate header fields + strxmimecpy(msg->realby, msg->realby, msg->charsetlevel, sizeof(INam)); + strxmimecpy(msg->realto, msg->realto, msg->charsetlevel, sizeof(INam)); + strxmimecpy(msg->by , msg->by , msg->charsetlevel, sizeof(INam)); + strxmimecpy(msg->to , msg->to , msg->charsetlevel, sizeof(INam)); + + if(not (msg->attr.frq() or msg->attr.att() or msg->attr.urq())) + strxmimecpy(msg->re , msg->re , msg->charsetlevel, sizeof(ISub), true); + } + return retval; +} + + +// ------------------------------------------------------------------ + +int Area::LoadMsg(GMsg* msg, ulong msgno, int margin, int mode) { + + ResetMsg(msg); + msg->msgno = msgno; + if(msgno and area->load_msg(msg)) { + if(mode & (GMSG_COPY|GMSG_MOVE)) { + if(not ((mode & GMSG_MOVE) and (mode & GMSG_UNS_NOT_RCV))) + return true; + if(not (msg->attr.uns() and not msg->attr.rcv())) + return true; + } + else { + // We can't rely on the destination address unless we are in netmail + if(not AA->isnet()) { + msg->dest.reset_fast(); + msg->odest.reset_fast(); + } + } + msg->attr.tou0(); + msg->TextToLines(margin); + return true; + } + return false; +} + + +// ------------------------------------------------------------------ + +void Area::SaveHdr(int mode, GMsg* msg) { + + // Translate softcr to configured char + if(EDIT->SoftCrXlat()) { + strchg(msg->by, SOFTCR, EDIT->SoftCrXlat()); + strchg(msg->to, SOFTCR, EDIT->SoftCrXlat()); + strchg(msg->realby, SOFTCR, EDIT->SoftCrXlat()); + strchg(msg->realto, SOFTCR, EDIT->SoftCrXlat()); + if(not (msg->attr.frq() or msg->attr.att() or msg->attr.urq())) + strchg(msg->re, SOFTCR, EDIT->SoftCrXlat()); + } + area->save_hdr(mode, msg); + UpdateAreadata(); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gemain.cpp b/golded3/gemain.cpp new file mode 100644 index 0000000..b7af9ad --- /dev/null +++ b/golded3/gemain.cpp @@ -0,0 +1,42 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Main entry point and overlay size setting function. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ +// Main function + +int main(int argc, char *argv[]) { + + Initialize(argc, argv); + Reader(); + return errorlevel; +} + + +// ------------------------------------------------------------------ diff --git a/golded3/gemenu.cpp b/golded3/gemenu.cpp new file mode 100644 index 0000000..fc35bbb --- /dev/null +++ b/golded3/gemenu.cpp @@ -0,0 +1,843 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Menus. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +GMsg* MenuMsgPtr; + + +// ------------------------------------------------------------------ + +void DispHeadAttrs(GMsg* msg) { + + char atrs[200]; + MakeAttrStr(atrs, &msg->attr); + strsetsz(atrs, MAXCOL-CFG->disphdrnodeset.pos); + + HeaderView->window.prints(1, CFG->disphdrnodeset.pos, HeaderView->window_color, atrs); + HeaderView->window.prints(4, 0, HeaderView->window_color, (msg->attr.att() or msg->attr.frq() or msg->attr.urq()) ? LNG->File : LNG->Subj); +} + + +// ------------------------------------------------------------------ + +static void DispHeadAttrs() { + + DispHeadAttrs(MenuMsgPtr); +} + + +// ------------------------------------------------------------------ + +static void toggle_pvt() { + + MenuMsgPtr->attr.pvtX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_received() { + + MenuMsgPtr->attr.rcvX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_crash() { + + MenuMsgPtr->attr.craX(); + if(MenuMsgPtr->attr.cra()) + MenuMsgPtr->attr.hld0(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_hold() { + + MenuMsgPtr->attr.hldX(); + if(MenuMsgPtr->attr.hld()) { + MenuMsgPtr->attr.cra0(); + MenuMsgPtr->attr.imm0(); + } + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_file() { + + MenuMsgPtr->attr.attX(); + if(MenuMsgPtr->attr.att()) { + AttrAdd(&MenuMsgPtr->attr, &CFG->attribsattach); + MenuMsgPtr->attr.urq0(); + MenuMsgPtr->attr.frq0(); + } + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_freq() { + + MenuMsgPtr->attr.frqX(); + if(MenuMsgPtr->attr.frq()) { + MenuMsgPtr->attr.att0(); + MenuMsgPtr->attr.urq0(); + } + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_updreq() { + + MenuMsgPtr->attr.urqX(); + if(MenuMsgPtr->attr.urq()) { + MenuMsgPtr->attr.att0(); + MenuMsgPtr->attr.frq0(); + } + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_kill() { + + MenuMsgPtr->attr.k_sX(); + if(MenuMsgPtr->attr.k_s()) + MenuMsgPtr->attr.a_s0(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_sent() { + + MenuMsgPtr->attr.sntX(); + if(MenuMsgPtr->attr.snt()) { + MenuMsgPtr->attr.uns0(); + MenuMsgPtr->attr.scn1(); + } + else { + MenuMsgPtr->attr.uns1(); + MenuMsgPtr->attr.scn0(); + MenuMsgPtr->attr.loc1(); + } + + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_trunc() { + + MenuMsgPtr->attr.tfsX(); + if(MenuMsgPtr->attr.tfs()) + MenuMsgPtr->attr.kfs0(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_delsent() { + + MenuMsgPtr->attr.kfsX(); + if(MenuMsgPtr->attr.kfs()) + MenuMsgPtr->attr.tfs0(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_direct() { + + MenuMsgPtr->attr.dirX(); + if(MenuMsgPtr->attr.dir()) { + MenuMsgPtr->attr.zon0(); + MenuMsgPtr->attr.hub0(); + } + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_imm() { + + MenuMsgPtr->attr.immX(); + if(MenuMsgPtr->attr.imm()) + MenuMsgPtr->attr.hld0(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_locked() { + + MenuMsgPtr->attr.lokX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_reserved() { + + MenuMsgPtr->attr.rsvX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_groupmsg() { + + MenuMsgPtr->attr.grpX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_arcsent() { + + MenuMsgPtr->attr.a_sX(); + if(MenuMsgPtr->attr.a_s()) + MenuMsgPtr->attr.k_s0(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_zonegate() { + + MenuMsgPtr->attr.zonX(); + if(MenuMsgPtr->attr.zon()) { + MenuMsgPtr->attr.dir0(); + MenuMsgPtr->attr.hub0(); + } + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_transit() { + + MenuMsgPtr->attr.trsX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_retrecreq() { + + MenuMsgPtr->attr.rrqX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_retrec() { + + MenuMsgPtr->attr.rrcX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_orphan() { + + MenuMsgPtr->attr.orpX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_audit() { + + MenuMsgPtr->attr.arqX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_hubhost() { + + MenuMsgPtr->attr.hubX(); + if(MenuMsgPtr->attr.hub()) { + MenuMsgPtr->attr.dir0(); + MenuMsgPtr->attr.zon0(); + } + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_local() { + + MenuMsgPtr->attr.locX(); + if(MenuMsgPtr->attr.loc()) + MenuMsgPtr->attr.trs0(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_xmail() { + + MenuMsgPtr->attr.xmaX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_cfmrecreq() { + + MenuMsgPtr->attr.cfmX(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void toggle_scanned() { + + MenuMsgPtr->attr.scnX(); + if(MenuMsgPtr->attr.scn()) { + MenuMsgPtr->attr.snt1(); + MenuMsgPtr->attr.uns0(); + } + else { + MenuMsgPtr->attr.snt0(); + MenuMsgPtr->attr.uns1(); + MenuMsgPtr->attr.loc1(); + } + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void clear_attrib() { + + MenuMsgPtr->attr.reset(); + DispHeadAttrs(); +} + + +// ------------------------------------------------------------------ + +static void DispAttrWindow(int show=-1) { + + static int wh_background = -1; + static int wh_attributes = -1; + + if(show == -1) + show = wh_attributes == -1; + + if(show) { + wh_background = whandle(); + int wide = MaxV(strlen(LNG->AttrTitle)+2, strlen(LNG->AttrPvt)+2); + wide = MinV(wide, MAXCOL-4); + wh_attributes = wopen_(6, 0, 17, wide, W_BMENU, C_MENUB, C_MENUW); + set_title(LNG->AttrTitle, TCENTER, C_MENUT); + if(*LNG->AttrTurnOff) + wtitle(LNG->AttrTurnOff, TCENTER|TBOTTOM, C_MENUT); + title_shadow(); + int n = 0; + wide -= 2; + wprintns(n++, 0, C_MENUW, LNG->AttrPvt, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrRcv, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrSnt, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrCrs, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrHld, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrFil, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrFrq, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrUpd, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrKS , wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrKfs, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrTfs, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrDir, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrImm, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrLok, wide, ' ', C_MENUW); + wprintns(n++, 0, C_MENUW, LNG->AttrZap, wide, ' ', C_MENUW); + wactiv_(wh_background); + } + else if(wh_attributes != -1) { + wactiv_(wh_attributes); + wclose(); + wactiv_(wh_background); + wh_attributes = -1; + } +} + + +// ------------------------------------------------------------------ + +static void toggle_dispattrwindow() { + + DispAttrWindow(); +} + + +// ------------------------------------------------------------------ + +void ChgAttrs(int mode, GMsg* __msg) { + + static KBnd* k1; + + if(mode) { + MenuMsgPtr = __msg; + + if(EDIT->HeaderAttrs() or (mode == ALWAYS)) + DispAttrWindow(true); + k1 = chgonkey(NULL); + setonkey(Key_A_F1, toggle_dispattrwindow, 0); + setonkey(Key_A_1, toggle_reserved , 0); + setonkey(Key_A_2, toggle_groupmsg , 0); + setonkey(Key_A_4, toggle_scanned , 0); + setonkey(Key_A_A, toggle_file , 0); + setonkey(Key_A_B, toggle_arcsent , 0); + setonkey(Key_A_C, toggle_crash , 0); + setonkey(Key_A_D, toggle_direct , 0); + setonkey(Key_A_E, toggle_delsent , 0); + setonkey(Key_A_F, toggle_freq , 0); + setonkey(Key_A_G, toggle_zonegate , 0); + setonkey(Key_A_H, toggle_hold , 0); + setonkey(Key_A_I, toggle_imm , 0); + setonkey(Key_A_J, toggle_transit , 0); + setonkey(Key_A_K, toggle_kill , 0); + setonkey(Key_A_L, toggle_locked , 0); + setonkey(Key_A_M, toggle_retrecreq , 0); + setonkey(Key_A_N, toggle_retrec , 0); + setonkey(Key_A_O, toggle_orphan , 0); + setonkey(Key_A_P, toggle_pvt , 0); + setonkey(Key_A_Q, toggle_audit , 0); + setonkey(Key_A_R, toggle_received , 0); + setonkey(Key_A_S, toggle_sent , 0); + setonkey(Key_A_T, toggle_trunc , 0); + setonkey(Key_A_U, toggle_updreq , 0); + setonkey(Key_A_V, toggle_hubhost , 0); + setonkey(Key_A_W, toggle_local , 0); + setonkey(Key_A_X, toggle_xmail , 0); + setonkey(Key_A_Y, toggle_cfmrecreq , 0); + setonkey(Key_A_Z, clear_attrib , 0); + } + else { + DispAttrWindow(false); + freonkey(); + chgonkey(k1); + } +} + + +// ------------------------------------------------------------------ + +void AskAttributes(GMsg* __msg) { + + ChgAttrs(ALWAYS, __msg); + update_statusline(LNG->ChangeAttrs); + whelpdef(CFG->helpged, Key_F1, C_HELPB, C_HELPW, C_HELPQ, C_HELPS, NULL); + whelppcat(H_Attributes); + getxch(); + whelpop(); + ChgAttrs(false, __msg); +} + + +// ------------------------------------------------------------------ + +int SelectFromFile(const char* file, char* selection, const char* title, const char* nolines) { + + char buf[256]; + int n; + bool retval=false; + char** Listi; + int lines = 0; + + FILE* fp = fsopen(AddPath(CFG->goldpath, file), "rt", CFG->sharemode); + if(fp) { + while(fgets(buf, sizeof(buf), fp)) + lines++; + } + + if(lines) { + Listi = (char**)throw_calloc(lines+1, sizeof(char*)); + rewind(fp); + for(n=0; n MAXCOL-2-2) + buf[MAXCOL-2-2] = NUL; + Listi[n] = throw_strdup(buf); + } + n = MinV(n, (MAXROW-10)); + set_title(title, TCENTER, C_ASKT); + n = wpickstr(6, 0, 6+n+1, -1, W_BASK, C_ASKB, C_ASKW, C_ASKS, Listi, 0, title_shadow); + if(n != -1) { + strcpy(selection, Listi[n]); + retval = true; + } + for(n=0; ntagline.empty()) { + Listi = (char**)throw_calloc(CFG->tagline.size()+1, sizeof(char*)); + gstrarray::iterator i; + for(n = 0, i = CFG->tagline.begin(); i != CFG->tagline.end(); i++, n++) { + if((*i)[0] == '@') + strxmerge(buf, MAXCOL-2-2, " [", CleanFilename(i->c_str()+1), "] ", NULL); + else + strxmerge(buf, MAXCOL-2-2, " ", i->c_str(), " ", NULL); + Listi[n] = throw_strdup(buf); + } + n = MinV(n, (MAXROW-10)); + set_title(LNG->Taglines, TCENTER, C_ASKT); + update_statusline(LNG->ChangeTagline); + whelppcat(H_ChangeTagline); + n = wpickstr(6, 0, 6+n+1, -1, W_BASK, C_ASKB, C_ASKW, C_ASKS, Listi, CFG->taglineno, title_shadow); + if(n != -1) { + const char *tagl = CFG->tagline[n].c_str(); + if(tagl[0] == '@') { + strxmerge(buf, MAXCOL-2-2, LNG->Taglines, " [", CleanFilename(tagl+1), "] ", NULL); + if(SelectFromFile(tagl+1, buf, LNG->Taglines, LNG->NoTagline)) { + AA->SetTagline(buf); + retval = true; + } + } + else { + CFG->taglineno = n; + AA->SetTagline(CFG->tagline[n].c_str()); + retval = true; + } + } + for(n=CFG->tagline.size(); n; n--) + throw_free(Listi[n-1]); + throw_free(Listi); + whelpop(); + } + else { + w_info(LNG->NoTagline); + waitkeyt(10000); + w_info(NULL); + } + return(retval); +} + + +// ------------------------------------------------------------------ + +int ChangeOrigin() { + + char buf[256]; + int n; + bool retval=false; + char** Listi; + + if(not CFG->origin.empty()) { + Listi = (char**)throw_calloc(CFG->origin.size()+1, sizeof(char*)); + gstrarray::iterator i; + for(n = 0, i = CFG->origin.begin(); i != CFG->origin.end(); n++, i++) { + if((*i)[0] == '@') + strxmerge(buf, MAXCOL-2-2, " [", CleanFilename(i->c_str()+1), "] ", NULL); + else + strxmerge(buf, MAXCOL-2-2, " ", i->c_str(), " ", NULL); + Listi[n] = throw_strdup(buf); + } + n = MinV(n, (MAXROW-10)); + set_title(LNG->Origins, TCENTER, C_ASKT); + update_statusline(LNG->ChangeOrigin); + whelppcat(H_ChangeOrigin); + n = wpickstr(6, 0, 6+n+1, -1, W_BASK, C_ASKB, C_ASKW, C_ASKS, Listi, CFG->originno, title_shadow); + if(n != -1) { + const char *orig = CFG->origin[n].c_str(); + if(orig[0] == '@') { + strxmerge(buf, MAXCOL-2-2, LNG->Origins, " [", CleanFilename(orig+1), "] ", NULL); + if(SelectFromFile(orig+1, buf, LNG->Origins, LNG->NoOrigDefined)) { + AA->SetOrigin(buf); + retval = true; + } + } + else { + CFG->originno = n; + AA->SetOrigin(orig); + retval = true; + } + } + for(n = CFG->origin.size(); n; n--) + throw_free(Listi[n-1]); + throw_free(Listi); + whelpop(); + } + else { + w_info(LNG->NoOrigDefined); + waitkeyt(10000); + w_info(NULL); + } + return(retval); +} + + +// ------------------------------------------------------------------ + +int ChangeUsername() { + + char buf[256], adrs[40]; + int n; + char** Listi; + + if(not CFG->username.empty()) { + Listi = (char**)throw_calloc(CFG->username.size()+1, sizeof(char*)); + vector::iterator i; + for(n = 0, i = CFG->username.begin(); i != CFG->username.end(); n++, i++) { + i->addr.make_string(adrs); + sprintf(buf, " %-35s %s ", i->name, adrs); + Listi[n] = throw_strdup(buf); + } + n = MinV(n, (MAXROW-10)); + set_title(LNG->Usernames, TCENTER, C_ASKT); + update_statusline(LNG->ChangeUsername); + whelppcat(H_ChangeUsername); + n = wpickstr(6, 0, 6+n+1, -1, W_BASK, C_ASKB, C_ASKW, C_ASKS, Listi, CFG->usernameno, title_shadow); + if(n != -1) { + CFG->usernameno = n; + AA->SetUsername(CFG->username[n]); + for(vector::iterator a = CFG->aka.begin(); a != CFG->aka.end(); a++) { + if(AA->Username().addr.match(a->addr)) { + AA->SetAka(a->addr); + break; + } + } + } + for(n = CFG->username.size(); n; n--) + throw_free(Listi[n-1]); + throw_free(Listi); + whelpop(); + } + else { + w_info(LNG->NoUserDefined); + waitkeyt(10000); + w_info(NULL); + } + return(YES); +} + + +// ------------------------------------------------------------------ + +int ChangeTemplate() { + + char buf[256], adrs[40]; + int n; + int selected=-1; + char** Listi; + + if(not CFG->tpl.empty()) { + Listi = (char**)throw_calloc(CFG->tpl.size()+1, sizeof(char*)); + vector::iterator t; + for(n = 0, t = CFG->tpl.begin(); t != CFG->tpl.end(); n++, t++) { + t->match.make_string(adrs); + sprintf(buf, " %-45s %s ", t->name, adrs); + Listi[n] = throw_strdup(buf); + } + n = MinV(n, (MAXROW-10)); + set_title(LNG->Templates, TCENTER, C_ASKT); + update_statusline(LNG->ChangeTemplate); + whelppcat(H_ChangeTemplate); + n = wpickstr(6, 0, 6+n+1, -1, W_BASK, C_ASKB, C_ASKW, C_ASKS, Listi, CFG->tplno, title_shadow); + whelpop(); + if(n != -1) { + AA->SetTpl(CFG->tpl[n].file); + CFG->tplno = n; + } + selected = n; + for(n = CFG->tpl.size(); n; n--) + throw_free(Listi[n-1]); + throw_free(Listi); + } + else { + w_info(LNG->NoTplDefined); + waitkeyt(10000); + w_info(NULL); + } + return selected; +} + + +// ------------------------------------------------------------------ + +int ChangeAka() { + int n; + vector::iterator i; + int startat = 0; + char** Listi; + char addr[100], buf[100]; + + if(CFG->aka.size() > 1) { + Listi = (char**)throw_calloc(CFG->aka.size()+1, sizeof(char*)); + for(i = CFG->aka.begin(), n=0; i != CFG->aka.end(); n++, i++) { + i->addr.make_string(addr, i->domain); + sprintf(buf, " %s ", addr); + Listi[n] = throw_strdup(buf); + if(AA->Aka().addr.equals(i->addr)) + startat = n; + } + n = MinV(n, (MAXROW-10)); + set_title(LNG->Akas, TCENTER, C_ASKT); + update_statusline(LNG->ChangeAka); + whelppcat(H_ChangeAka); + n = wpickstr(6, 0, 6+n+1, -1, W_BASK, C_ASKB, C_ASKW, C_ASKS, Listi, startat, title_shadow); + whelpop(); + if(n != -1) + AA->SetAka(CFG->aka[n].addr); + for(n=CFG->aka.size(); n; n--) + throw_free(Listi[n-1]); + throw_free(Listi); + } + else { + w_info(LNG->NoAkaDefined); + waitkeyt(10000); + w_info(NULL); + } + return(YES); +} + + +// ------------------------------------------------------------------ + +int ChangeXlatImport() { + + int n, startat = 0; + int xlatimports = 1; + int maximport = 0; + int maxexport = 0; + char** Listi; + char buf[100]; + + if(not CFG->xlatcharset.empty()) { + Listi = (char**)throw_calloc(CFG->xlatcharset.size()+2, sizeof(char*)); + vector::iterator xlt; + for(xlt = CFG->xlatcharset.begin(); xlt != CFG->xlatcharset.end(); xlt++) { + if(strieql(xlt->exp, CFG->xlatlocalset)) { + maximport = MaxV(maximport, (int)strlen(xlt->imp)); + maxexport = MaxV(maxexport, (int)strlen(xlt->exp)); + if(strieql(xlt->imp, AA->Xlatimport())) + startat = xlatimports; + xlatimports++; + } + } + Listi[0] = throw_strdup(LNG->CharsetAuto); + xlatimports = 1; + for(xlt = CFG->xlatcharset.begin(); xlt != CFG->xlatcharset.end(); xlt++) { + if(strieql(xlt->exp, CFG->xlatlocalset)) { + sprintf(buf, " %*.*s -> %-*.*s ", + maximport, maximport, xlt->imp, + maxexport, maxexport, xlt->exp + ); + Listi[xlatimports++] = throw_strdup(buf); + } + } + n = MinV(xlatimports, (MAXROW-10)); + set_title(LNG->Charsets, TCENTER, C_ASKT); + update_statusline(LNG->ChangeXlatImp); + whelppcat(H_ChangeXlatImport); + n = wpickstr(6, 0, 6+n+1, -1, W_BASK, C_ASKB, C_ASKW, C_ASKS, Listi, startat, title_shadow); + whelpop(); + if(n == 0) { + CFG->ignorecharset = false; + } + else if(n != -1) { + CFG->ignorecharset = true; + AA->SetXlatimport(strtok(Listi[n], " ")); + } + for(n=0; nNoXlatImport); + waitkeyt(10000); + w_info(NULL); + } + return true; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gemlst.cpp b/golded3/gemlst.cpp new file mode 100644 index 0000000..75e62c2 --- /dev/null +++ b/golded3/gemlst.cpp @@ -0,0 +1,1294 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Message lister. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +extern GMsg* reader_msg; + +static GMsg* MLstMsgPtr; +static GMsg* mlstmsg = NULL; +static uint msgmark2; +static MLst* mlst; +static int mlst_bysiz; +static int mlst_tosiz; +static int mlst_resiz; +static int fldadd1; +static int fldadd2; + + +// ------------------------------------------------------------------ + +const byte MLST_HIGH_FROM = 1; +const byte MLST_HIGH_TO = 2; +const byte MLST_HIGH_BOOK = 4; +const byte MLST_HIGH_MARK = 8; +const byte MLST_HIGH_UNREAD = 16; +const byte MLST_HIGH_UNSENT = 32; + + +// ------------------------------------------------------------------ + +inline void mlst_with_date(int with_date) { + + if(with_date) { + mlst_bysiz = 19; + mlst_tosiz = 19; + mlst_resiz = 20; + } + else { + mlst_bysiz = 19+3; + mlst_tosiz = 19+3; + mlst_resiz = 20+4; + } +} + + +// ------------------------------------------------------------------ + +static void mlst_dodelayed(PInf* p) { + + // Update header and statusline + + if(AA->Msglistheader()) { + AA->LoadMsg(MLstMsgPtr, mlst[p->pos].msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + mlst[p->pos].goldmark = goldmark; + int mlstwh = whandle(); + HeaderView->Use(AA, MLstMsgPtr); + HeaderView->Paint(); + wactiv_(mlstwh); + } + + if(CFG->switches.get(msglistviewsubj)) + wtitle(mlst[p->pos].re, TCENTER|TBOTTOM, p->tattr); + + if(CFG->switches.get(msglistpagebar)) + wscrollbar(W_VERT, p->maxidx+1, p->maxidx, p->idx); + + update_statuslinef(LNG->MsgLister, p->idx+1, p->maxidx+1, p->maxidx-p->idx); +} + + +// ------------------------------------------------------------------ + +static void mlst_dispbuf(char* abuf, MLst* ml) { + + int bysiz = mlst_bysiz + fldadd1; + int tosiz = mlst_tosiz + fldadd1; + int resiz = mlst_resiz + fldadd2; + + if(AA->Msglistwidesubj()) { + resiz += tosiz + 1; + tosiz = 0; + } + + char nbuf[33], dbuf[20]; + strcpy(dbuf, LNG->n_a); + + time_t dt = 0; + switch(AA->Msglistdate()) { + case MSGLISTDATE_WRITTEN: dt = ml->written; break; + case MSGLISTDATE_ARRIVED: dt = ml->arrived; break; + case MSGLISTDATE_RECEIVED: dt = ml->received; break; + } + if(dt) + strftimei(dbuf, 20, "%d %b %y", gmtime(&dt)); + if(AA->Msglistdate()) + strsetsz(dbuf, 10); + else + *dbuf = NUL; + sprintf(nbuf, "%5lu", CFG->switches.get(disprealmsgno) ? ml->msgno : AA->Msgn.ToReln(ml->msgno)); + sprintf(abuf, "%-5.5s%s%-*.*s %-*.*s%s%-*.*s %s", + nbuf, ml->marks, + bysiz, bysiz, ml->by, + tosiz, tosiz, ml->to, + (tosiz ? " " : ""), + resiz, resiz, ml->re, + dbuf + ); +} + + +// ------------------------------------------------------------------ + +static void mlst_dispit(PInf* p, uint pos, int type) { + + int bycol = 7; + int tocol = bycol + mlst_bysiz + 1 + fldadd1; + int bysiz = mlst_bysiz + fldadd1; + int tosiz = mlst_tosiz + fldadd1; + + MLst* ml = &mlst[pos]; + + int wattr, hattr, mattr=p->hattr; + if(type == PICK_BAR) { + wattr = p->sattr; + hattr = p->sattr; + mattr = p->sattr; + } + else if(ml->high & MLST_HIGH_UNSENT) { + wattr = C_MENUW_UNSENT; + hattr = C_MENUQ_UNSENTHIGH; + } + else if(ml->high & MLST_HIGH_UNREAD) { + wattr = C_MENUW_UNREAD; + hattr = C_MENUQ_UNREADHIGH; + } + else { + wattr = p->wattr; + hattr = p->hattr; + } + + char buf[256]; + mlst_dispbuf(buf, ml); + wprints(pos, 0, wattr, buf); + + if(ml->high & (MLST_HIGH_BOOK|MLST_HIGH_MARK)) + wprints(pos, 5, mattr, ml->marks); + if(ml->high & MLST_HIGH_FROM) + wprintns(pos, bycol, hattr, ml->by, bysiz); + if((ml->high & MLST_HIGH_TO) and not AA->Msglistwidesubj()) + wprintns(pos, tocol, hattr, ml->to, tosiz); + + goldmark = ml->goldmark; +} + + +// ------------------------------------------------------------------ + +static void mlst_disp(PInf* p) { + + mlst_dispit(p, p->pos, p->type); +} + + +// ------------------------------------------------------------------ + +static void mlst_get_mlst(MLst* ml, PInf* p, int n) { + + GMsg* msg = mlstmsg; + + ml->high = 0; + + strcpy(ml->marks, " "); + + ml->msgno = AA->Msgn.CvtReln(p->idx + n + 1); + + if(AA->bookmark == AA->Msgn.CvtReln(p->idx + n + 1)) { + ml->marks[0] = MMRK_BOOK; + ml->high |= MLST_HIGH_BOOK; + } + + if(AA->Mark.Count()) { + if(AA->Mark.Find(ml->msgno)) { + ml->marks[1] = MMRK_MARK; + ml->high |= MLST_HIGH_MARK; + } + } + + if(AA->Msglistfast()) { + AA->LoadHdr(msg, ml->msgno); + } + else { + AA->LoadMsg(msg, ml->msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + } + ml->goldmark = goldmark; + + for(vector::iterator x = CFG->username.begin(); x != CFG->username.end(); x++) { + if(strieql(msg->By(), x->name)) { + ml->high |= MLST_HIGH_FROM; + msg->attr.fmu1(); + } + if(strieql(msg->to, x->name)) { + ml->high |= MLST_HIGH_TO; + msg->attr.tou1(); + } + } + if(strieql(msg->to, AA->Internetaddress())) { + ml->high |= MLST_HIGH_TO; + msg->attr.tou1(); + } + + // Highlight FROM if local + if(CFG->switches.get(displocalhigh) and msg->attr.loc()) + ml->high |= MLST_HIGH_FROM; + + // Highlight if unread + if(msg->timesread == 0 and CFG->switches.get(highlightunread)) + ml->high |= MLST_HIGH_UNREAD; + + // Highlight if unsent + if(msg->attr.uns()and not msg->attr.rcv() and not msg->attr.del()) + ml->high |= MLST_HIGH_UNSENT; + + ml->written = msg->written; + ml->arrived = msg->arrived; + ml->received = msg->received; + strcpy(ml->by, msg->By()); + strcpy(ml->to, msg->To()); + strcpy(ml->re, msg->re); +} + + +// ------------------------------------------------------------------ + +static void mlst_page(PInf* p) { + + char linebuf[200]; + vchar vlinebuf[200]; + uint m, n; + + if(not AA->Msglistfast()) + w_info(LNG->Wait); + + p->idx -= p->pos; + m = p->maxidx - p->idx; + + for(n=0; n<=p->maxpos and n<=m; n++) + mlst_get_mlst(&mlst[n], p, n); + + if(not AA->Msglistfast()) + w_info(NULL); + + for(n=0; n<=p->maxpos and n<=m; n++) + mlst_dispit(p, n, (n==p->pos) ? PICK_BAR : PICK_DISP); + + for(int c = 0; c < MAXCOL-2; c++) + vlinebuf[c] = _box_table(p->btype, 1); + vlinebuf[MAXCOL-2] = NUL; + + if(n <= p->maxpos or (p->maxpos == p->maxidx and p->maxpos < (p->height-3))) + wprintvs(n, 0, p->wattr|ACSET, vlinebuf); + + memset(linebuf, ' ', MAXCOL-2); + linebuf[MAXCOL-2] = NUL; + + for(++n; n<=p->height-2; n++) + wprints(n, 0, p->wattr, linebuf); + p->idx += p->pos; +} + + +// ------------------------------------------------------------------ + +static void mlst_center(PInf* p) { + + uint botroom = p->maxidx - p->idx; + + switch(CFG->displistcursor) { + case LIST_TOP: + if(botroom > p->maxpos) + p->pos = 0; + else + p->pos = p->maxpos - botroom; + break; + case LIST_NEARTOP: + { + uint room; + uint toproom = p->idx; + if(toproom > (p->maxpos/4)) { + if(botroom > (p->maxpos/4)) + room = p->maxpos/4; + else if(botroom) + room = p->maxpos - botroom; + else + room = p->maxpos; + } + else + room = toproom; + p->pos = room; + } + break; + case LIST_MIDDLE: + { + uint room; + uint toproom = p->idx; + if(toproom > (p->maxpos/2)) { + if(botroom > (p->maxpos/2)) + room = p->maxpos/2; + else if(botroom) + room = p->maxpos - botroom; + else + room = p->maxpos; + } + else + room = toproom; + p->pos = room; + } + break; + case LIST_NEARBOTTOM: + { + uint room; + uint toproom = p->idx; + if(toproom > 3*(p->maxpos/4)) { + if(botroom > 3*(p->maxpos/4)) + room = 3*(p->maxpos/4); + else if(botroom) + room = p->maxpos - botroom; + else + room = p->maxpos; + } + else + room = toproom; + p->pos = room; + } + break; + case LIST_BOTTOM: + p->pos = p->maxpos; + break; + } + mlst_page(p); +} + + +// ------------------------------------------------------------------ + +static void mlst_scroll(PInf* p, int direction) { + + if(direction == SUP) { + memmove(&mlst[0], &mlst[1], p->maxpos*sizeof(MLst)); + mlst_get_mlst(&mlst[p->maxpos], p, 0); + } + else { + memmove(&mlst[1], &mlst[0], p->maxpos*sizeof(MLst)); + mlst_get_mlst(&mlst[0], p, 0); + } + wscroll(1, direction); +} + + +// ------------------------------------------------------------------ + +static void mlst_title(PInf* p) { + + int bycol = 8; + int tocol = bycol + mlst_bysiz + 1 + fldadd1; + int recol = tocol + mlst_tosiz + 1 + fldadd1; + int dtcol = recol + mlst_resiz + 1 + fldadd2; + if(AA->Msglistwidesubj()) + recol = tocol; + + wtitle(NULL, TCENTER, p->tattr); + wmessage(CFG->switches.get(disprealmsgno) ? LNG->MsgReal : LNG->Msg, TP_BORD, 3, p->tattr); + wmessage(LNG->FromL, TP_BORD, bycol, p->tattr); + if(not AA->Msglistwidesubj()) + wmessage(LNG->ToL, TP_BORD, tocol, p->tattr); + wmessage(LNG->SubjL, TP_BORD, recol, p->tattr); + switch(AA->Msglistdate()) { + case MSGLISTDATE_WRITTEN: wmessage(LNG->Written, TP_BORD, dtcol, p->tattr); break; + case MSGLISTDATE_ARRIVED: wmessage(LNG->Arrived, TP_BORD, dtcol, p->tattr); break; + case MSGLISTDATE_RECEIVED: wmessage(LNG->Received, TP_BORD, dtcol, p->tattr); break; + } +} + + +// ------------------------------------------------------------------ + +static void mlst_open(PInf* p) { + + wopen_(p->row, p->column, p->height, p->width, p->btype, p->battr, p->wattr, p->sbattr); + mlst_title(p); + mlst_center(p); +} + + +// ------------------------------------------------------------------ + +static void mlst_close(PInf* p) { + + NW(p); + wclose(); +} + + +// ------------------------------------------------------------------ + +static int mlst_dokey(PInf* p, gkey* keycode) { + + int tpos; + gkey key, kk; + uint temp, tmpmsgno; + + key = *keycode; + *keycode = 0; + + if(key < KK_Commands) { + key = key_tolower(key); + kk = SearchKey(key, ListKey, ListKeys); + if(kk) + key = kk; + } + + // See if it's a listkey + switch(key) { + case KK_ListGotoPrev: + case KK_ListGotoNext: + case KK_ListGotoFirst: + case KK_ListGotoLast: + case KK_ListAskExit: + case KK_ListQuitNow: + case KK_ListAbort: + case KK_ListSelect: + case KK_ListToggleMark: + case KK_ListToggleBookMark: + case KK_ListGotoBookMark: + case KK_ListMarkingOptions: + case KK_ListDosShell: + case KK_ListMacro: + case Key_0: + case Key_1: + case Key_2: + case Key_3: + case Key_4: + case Key_5: + case Key_6: + case Key_7: + case Key_8: + case Key_9: + break; + + // If not a listkey, see if it matches a readkey + default: + if(not IsMacro(key, KT_M)) { + kk = SearchKey(key, ReadKey, ReadKeys); + if(kk) + key = kk; + } + } + + switch(key) { + case KK_ListGotoPrev: + *keycode = Key_Up; + break; + + case KK_ListGotoNext: + *keycode = Key_Dwn; + break; + + case KK_ListGotoFirst: + *keycode = Key_Home; + break; + + case KK_ListGotoLast: + *keycode = Key_End; + break; + + case KK_ListAskExit: + { + GMenuQuit MenuQuit; + p->aborted = gkbd.quitall = (MenuQuit.Run()); + if(gkbd.quitall) { + AA->bookmark = AA->Msgn.CvtReln(msgmark2); + return NO; + } + } + break; + + case KK_ListQuitNow: + p->aborted = gkbd.quitall = true; + AA->bookmark = AA->Msgn.CvtReln(msgmark2); + return NO; + + case KK_ListAbort: + AA->bookmark = AA->Msgn.CvtReln(msgmark2); + p->aborted = YES; + ///////////////// Drop Through + + case KK_ListSelect: + return NO; + + case KK_ListToggleMark: + temp = AA->Mark.Find(mlst[p->pos].msgno); + if(temp) { + AA->Mark.DelReln(temp); + mlst[p->pos].marks[1] = ' '; + mlst[p->pos].high &= ~MLST_HIGH_MARK; + } + else { + AA->Mark.Add(mlst[p->pos].msgno); + mlst[p->pos].marks[1] = MMRK_MARK; + mlst[p->pos].high |= MLST_HIGH_MARK; + } + if(p->idx < p->maxidx) { + mlst_disp(p); + *keycode = Key_Dwn; + } + break; + + case KK_ListToggleBookMark: + if(AA->bookmark == mlst[p->pos].msgno) { + mlst[p->pos].marks[0] = ' '; + AA->bookmark = 0; + mlst[p->pos].high &= ~MLST_HIGH_BOOK; + mlst_disp(p); + } + else { + temp = AA->Msgn.ToReln(AA->bookmark-1); + AA->bookmark = mlst[p->pos].msgno; + mlst[p->pos].marks[0] = MMRK_BOOK; + mlst[p->pos].high |= MLST_HIGH_BOOK; + mlst_disp(p); + if(temp) { + tpos = p->pos; + p->pos += (temp - p->idx); + if(p->pos <= p->maxpos) { + mlst[p->pos].marks[0] = ' '; + mlst[p->pos].high &= ~MLST_HIGH_BOOK; + mlst_disp(p); + } + p->pos = tpos; + } + } + break; + + case KK_ListGotoBookMark: + if(AA->bookmark) { + tpos = p->pos + ((AA->Msgn.ToReln(AA->bookmark-1)) - p->idx); + temp = p->idx + 1; + p->idx = AA->Msgn.ToReln(AA->bookmark-1); + AA->bookmark = AA->Msgn.CvtReln(temp); + if(tpos >= 0 and (uint)tpos <= p->maxpos) { + mlst[tpos].marks[0] = ' '; + mlst[tpos].high &= ~MLST_HIGH_BOOK; + mlst[p->pos].marks[0] = MMRK_BOOK; + mlst[p->pos].high |= MLST_HIGH_BOOK; + mlst_disp(p); + p->pos = tpos; + mlst_disp(p); + } + else + mlst_center(p); + } + else + SayBibi(); + break; + + case KK_ListMarkingOptions: + { + uint lrbak = AA->lastread(); + AA->set_lastread(p->idx + 1); + MLstMsgPtr->msgno = AA->Msgn.CvtReln(AA->lastread()); + MarkMsgs(MLstMsgPtr); + AA->set_lastread(lrbak); + mlst_page(p); + } + break; + + case KK_ListDosShell: + DosShell(); + break; + + case KK_ListToggleWideSubj: + AA->ToggleMsglistwidesubj(); + mlst_title(p); + mlst_page(p); + break; + + case KK_ListToggleDate: + AA->NextMsglistdate(); + mlst_with_date(AA->Msglistdate()); + mlst_title(p); + mlst_page(p); + break; + + case Key_0: + case Key_1: + case Key_2: + case Key_3: + case Key_4: + case Key_5: + case Key_6: + case Key_7: + case Key_8: + case Key_9: + case KK_ReadGotoMsgno: + tmpmsgno = p->idx; + reader_keycode = key; + GotoMsgno(); + if(AA->lastread()-1 != tmpmsgno) { + p->idx = AA->lastread()-1; + mlst_center(p); + } + break; + + case KK_ReadMessageList: + mlst_center(p); + break; + + case Key_Tick: + CheckTick(KK_ListQuitNow); + break; + + case KK_ListUndefine: + break; + + default: + if(not PlayMacro(key, KT_M)) { + switch(key) { + case KK_ReadNewArea: + p->aborted = true; + } + if(gkbd.kbuf == NULL) + kbput(key); + return NO; + } + } + return YES; +} + + +// ------------------------------------------------------------------ + +uint MsgBrowser(GMsg* msg) { + + GFTRK("MsgBrowser"); + + Pick pick; + PInf p; + + memset(&p, 0, sizeof(PInf)); + memset(&pick, 0, sizeof(Pick)); + p.btype = W_BMENU; + p.battr = C_MENUB; + p.wattr = C_MENUW; + p.sattr = C_MENUS; + p.tattr = C_MENUT; + p.hattr = C_MENUQ; + p.sbattr = C_MENUPB; + p.row = AA->Msglistheader() ? 6 : 1; + p.height = MAXROW-p.row-1; + p.width = MAXCOL; + p.helpcat = H_MessageBrowser; + p.delay = 150; // milliseconds + p.listwrap = CFG->switches.get(displistwrap); + + pick.open = mlst_open; + pick.close = mlst_close; + pick.disp = mlst_disp; + pick.page = mlst_page; + pick.scroll = mlst_scroll; + pick.dokey = mlst_dokey; + pick.dodelayed = mlst_dodelayed; + + p.maxidx = AA->Msgn.Count()-1; + p.maxpos = MinV((uint)(p.height-3), p.maxidx); + p.aborted = NO; + + p.idx = AA->Msgn.ToReln(msg->msgno)-1; + msgmark2 = AA->Msgn.ToReln(AA->bookmark); + + MLstMsgPtr = msg; + + mlst = (MLst*)throw_calloc(p.maxpos+2, sizeof(MLst)); + mlstmsg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + if(AA->Msglistdate() != MSGLISTDATE_NONE) { + if(AA->Msglistdate() != MSGLISTDATE_WRITTEN) { + if(AA->ishudson() or AA->isgoldbase() or AA->ispcboard()) + AA->SetMsglistdate(MSGLISTDATE_WRITTEN); + else if((AA->isezycom() or AA->isfido()) and (AA->Msglistdate() == MSGLISTDATE_RECEIVED)) + AA->SetMsglistdate(MSGLISTDATE_WRITTEN); + } + } + + mlst_with_date(AA->Msglistdate()); + + fldadd1 = (MAXCOL-80)/3; + fldadd2 = (MAXCOL-80) - (fldadd1*2); + + _in_msglist = true; + + Picker(&p, &pick); + + _in_msglist = false; + + ResetMsg(mlstmsg); + throw_release(mlstmsg); + throw_release(mlst); + + GFTRK(NULL); + + if(not p.aborted) + return p.idx+1; + + return 0; +} + + +// ------------------------------------------------------------------ + +void MessageBrowse() { + + if(AA->Msgn.Count()) { + uint temp = AA->lastread(); + AA->set_lastread(MsgBrowser(reader_msg)); + if(AA->lastread() == 0) + AA->set_lastread(temp); + if(AA->PMrk.Tags() == 0) + AA->isreadpm = false; + if(AA->Mark.Count() == 0) + AA->isreadmark = false; + if(gkbd.quitall) + QuitNow(); + } +} + + +// ------------------------------------------------------------------ + +#include + +class ThreadEntry { + +public: + ulong msgno; + ulong replyto; + ulong reply1st; + ulong replynext; +}; + +#define MAX_LEVEL 20 + +class GThreadlist : public gwinpick { + +private: + + gwindow window; + GMsg msg; + vector list; + ThreadEntry t; + uint h_offset; + + void BuildThreadIndex(dword msgno); + void recursive_build(ulong msgn, ulong rn); + void GenTree(char* buf2, int idx); + void update_title(); + bool NextThread(bool next); + +public: + + void open(); // Called after window is opened + void close(); // Called after window is closed + void print_line(uint idx, uint pos, bool isbar); + void do_delayed(); + bool handle_key(); // Handles keypress + + void Run(); + + GThreadlist() { memset(&msg, 0, sizeof(GMsg)); }; + ~GThreadlist() { ResetMsg(&msg); }; + +}; + + +// ------------------------------------------------------------------ + +void GThreadlist::open() { + + window.openxy(ypos, xpos, ylen+2, xlen+2, btype, battr, 7); + update_title(); + + center(CFG->displistcursor); +} + + +// ------------------------------------------------------------------ + +void GThreadlist::update_title() { + + window.title(title, tattr); + window.message(CFG->switches.get(disprealmsgno) ? LNG->MsgReal : LNG->Msg, TP_BORD, 3, tattr); + + switch(AA->Msglistdate()) { + case MSGLISTDATE_WRITTEN: window.message(LNG->Written, TP_BORD, xlen-9, tattr); break; + case MSGLISTDATE_ARRIVED: window.message(LNG->Arrived, TP_BORD, xlen-9, tattr); break; + case MSGLISTDATE_RECEIVED: window.message(LNG->Received, TP_BORD, xlen-9, tattr); break; + } +} + + +// ------------------------------------------------------------------ + +void GThreadlist::do_delayed() { + + // Update header and statusline + if(AA->Msglistheader()) { + AA->LoadMsg(&msg, list[index].msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + int mlstwh = whandle(); + HeaderView->Use(AA, &msg); + HeaderView->Paint(); + wactiv_(mlstwh); + } + + if(CFG->switches.get(msglistviewsubj)) + wtitle(msg.re, TCENTER|TBOTTOM, tattr); + + if(CFG->switches.get(msglistpagebar)) + wscrollbar(W_VERT, maximum_index+1, maximum_index, index); + + update_statuslinef(LNG->MsgLister, index+1, maximum_index+1, maximum_index-index); +} + + +// ------------------------------------------------------------------ + +void GThreadlist::close() { + + window.close(); + ResetMsg(&msg); +} + + +// ------------------------------------------------------------------ + +void GThreadlist::GenTree(char* buf, int idx) { + + t = list[idx]; + + uint level = 0; + char* q = &buf[1000]; + + *q-- = NUL; + *q-- = ' '; + *q-- = (t.replynext) ? 'Ã' : 'À'; + + while(t.replyto) { + for(uint i=0; iMsglistdate() == MSGLISTDATE_NONE) ? 8 : 18); + + AA->LoadHdr(&msg, t.msgno); + + if(msg.attr.uns() and not msg.attr.rcv() and not msg.attr.del()) { + attrw = C_MENUW_UNSENT; + attrh = C_MENUQ_UNSENTHIGH; + } + else if(CFG->switches.get(highlightunread) and (msg.timesread == 0)) { + attrh = C_MENUQ_UNREADHIGH; + attrw = C_MENUW_UNREAD; + } + else { + attrw = wattr; + attrh = hattr; + } + + GenTree(buf2, idx); + + #if defined(__UNIX__) and not defined(__USE_NCURSES__) + gvid_boxcvt(buf2); + #endif + + char marks[3]; + + strcpy(marks, " "); + + if(AA->bookmark == t.msgno) + marks[0] = MMRK_BOOK; + + if(AA->Mark.Count()) { + if(AA->Mark.Find(t.msgno)) + marks[1] = MMRK_MARK; + } + + sprintf(buf, "%6lu %*c", CFG->switches.get(disprealmsgno) ? t.msgno : AA->Msgn.ToReln(t.msgno), tdlen, ' '); + + if(AA->Msglistdate() != MSGLISTDATE_NONE) { + char dbuf[11]; + time_t dt = 0; + + memset(dbuf, ' ', 10); + dbuf[10] = NUL; + strncpy(dbuf, LNG->n_a, strlen(LNG->n_a)); + + switch(AA->Msglistdate()) { + case MSGLISTDATE_WRITTEN: dt = msg.written; break; + case MSGLISTDATE_ARRIVED: dt = msg.arrived; break; + case MSGLISTDATE_RECEIVED: dt = msg.received; break; + } + + if(dt) + strftimei(dbuf, 20, "%d %b %y", gmtime(&dt)); + strcat(buf, dbuf); + } + + window.prints(pos, 0, isbar ? sattr : attrw, buf); + window.prints(pos, 6, isbar ? sattr : hattr, marks); + + if(strlen(buf2) > h_offset) { + strxcpy(buf, &buf2[h_offset], tdlen); + window.prints(pos, 8, isbar ? (sattr|ACSET) : (wattr|ACSET), buf); + } + + int attr = attrw; + + for(vector::iterator x = CFG->username.begin(); x != CFG->username.end(); x++) + if(strieql(msg.By(), x->name)) { + attr = attrh; + break; + } + + if((strlen(buf2) > h_offset) and (strlen(&buf2[h_offset]) < tdlen)) { + strxcpy(buf, msg.By(), tdlen - strlen(&buf2[h_offset])); + window.prints(pos, 8+strlen(&buf2[h_offset]), isbar ? sattr : attr, buf); + } +} + + +// ------------------------------------------------------------------ + +void GThreadlist::recursive_build(ulong msgn, ulong rn) { + + ulong oldmsgno = msg.msgno; + + if(AA->Msgn.ToReln(msgn) and AA->LoadHdr(&msg, msgn)) { + + t.msgno = msgn; + t.replyto = msg.link.to(); + t.reply1st = msg.link.first(); + t.replynext = rn; + + if(not AA->Msgn.ToReln(t.replyto)) + t.replyto = 0; + if(not AA->Msgn.ToReln(t.reply1st)) + t.reply1st = 0; + if(not AA->Msgn.ToReln(t.replynext)) + t.replynext = 0; + + uint j; + bool found = false; + for(j=0; jLoadHdr(&msg, oldmsgno); + } +} + + +// ------------------------------------------------------------------ + +void GThreadlist::BuildThreadIndex(dword msgn) { + + w_info(LNG->Wait); + + index = maximum_index = position = maximum_position = 0; + list.clear(); + + AA->LoadHdr(&msg, msgn); + + ulong msgno = msg.link.to(); + + // Search backwards + while(AA->Msgn.ToReln(msgno)) { + + if(not AA->LoadHdr(&msg, msgno)) + msg.link.to_set(0); + + msgno = msg.link.to(); + } + + recursive_build(msg.msgno, 0); + + w_info(NULL); + + minimum_index = 0; + maximum_index = list.size() - 1; + maximum_position = MinV((uint) list.size() - 1, (uint) ylen - 1); + index = 0; + h_offset = 0; + + for(uint i = 0; iMsgn.ToReln(reader_msg->msgno)-1; + next ? m < AA->Msgn.Count() : m; + next ? m++ : m--) { + + dword msgn = AA->Msgn[m]; + bool found = false; + + for(uint i = 0; imsgno = msgn; + AA->set_lastread(AA->Msgn.ToReln(msgn)); + + BuildThreadIndex(msgn); + return true; + } + } + return true; +} + +// ------------------------------------------------------------------ + + +bool GThreadlist::handle_key() { + + gkey kk; + + if(key < KK_Commands) { + key = key_tolower(key); + kk = SearchKey(key, ListKey, ListKeys); + if(kk) + key = kk; + } + + // See if it's a listkey + switch(key) { + case KK_ListGotoPrev: + case KK_ListGotoNext: + case KK_ListGotoFirst: + case KK_ListGotoLast: + case KK_ListAskExit: + case KK_ListQuitNow: + case KK_ListAbort: + case KK_ListSelect: + case KK_ListToggleMark: + case KK_ListToggleBookMark: + case KK_ListGotoBookMark: + case KK_ListMarkingOptions: + case KK_ListDosShell: + case Key_0: + case Key_1: + case Key_2: + case Key_3: + case Key_4: + case Key_5: + case Key_6: + case Key_7: + case Key_8: + case Key_9: + break; + + // If not a listkey, see if it matches a readkey + default: + if(not IsMacro(key, KT_M)) { + kk = SearchKey(key, ReadKey, ReadKeys); + if(kk) + key = kk; + } + } + + switch(key) { + case Key_C_PgUp: + case Key_C_PgDn: + NextThread((key == Key_C_PgDn)); + if(list.size() <= 1) + return false; + center(CFG->displistcursor); + break; + case KK_ListGotoPrev: + case KK_ListGotoNext: + NextThread((key == KK_ListGotoNext)); + if(list.size() <= 1) + return false; + center(CFG->displistcursor); + break; + case KK_ListGotoFirst: precursor(); cursor_first(); break; + case KK_ListGotoLast: precursor(); cursor_last(); break; + + case KK_ListAskExit: + { + GMenuQuit MenuQuit; + aborted = gkbd.quitall = (MenuQuit.Run()); + } + break; + + case KK_ListQuitNow: + gkbd.quitall = true; + ///////////////// Drop Through + + case KK_ListAbort: + aborted = true; + ///////////////// Drop Through + + case KK_ListSelect: + return false; + + case KK_ListToggleMark: + { + ulong temp = AA->Mark.Find(list[index].msgno); + if(temp) { + AA->Mark.DelReln(temp); + } + else { + AA->Mark.Add(list[index].msgno); + } + + if(index < maximum_index) + cursor_down(); + else + display_bar(); + break; + } + + case KK_ListDosShell: + DosShell(); + break; + + case KK_ListToggleDate: + AA->NextMsglistdate(); + mlst_with_date(AA->Msglistdate()); + update_title(); + update(); + break; + + case Key_Tick: + CheckTick(KK_ListQuitNow); + break; + + case KK_ListUndefine: + break; + + default: + if(not PlayMacro(key, KT_M)) { + if(gkbd.kbuf == NULL) + kbput(key); + switch(key) { + case KK_ListAbort: + case KK_ReadNewArea: + aborted = true; + } + return NO; + } + } + return true; +} + + +// ------------------------------------------------------------------ + +void GThreadlist::Run() { + + ypos = AA->Msglistheader() ? 6 : 1; // Window Starting Row + xpos = 0; // Window Starting Column + ylen = MAXROW-3-ypos; // Window Height + xlen = MAXCOL-2; // Window Width + btype = W_BMENU; // Window Border Type + battr = C_MENUB; // Window Border Color + wattr = C_MENUW; // Window Color + tattr = C_MENUT; // Window Title Color + sattr = C_MENUS; // Window Selection Bar Color + hattr = C_MENUQ; // Window Highlight Color + sbattr = C_MENUPB; // Window Scrollbar Color + title = LNG->ThreadlistTitle; // Window Title + helpcat = H_ReplyThread; // Window Help Category + listwrap = CFG->switches.get(displistwrap); + + BuildThreadIndex(reader_msg->msgno); + + if(list.size() > 1) + run_picker(); + + if(list.size() <= 1) { + w_info(LNG->NoThreadlist); + waitkeyt(5000); + w_info(NULL); + aborted = true; + } + + if(not aborted) + AA->set_lastread(AA->Msgn.ToReln(list[index].msgno)); +} + + +// ------------------------------------------------------------------ + +void MsgThreadlist() { + + GThreadlist p; + + p.Run(); + +} + + +// ------------------------------------------------------------------ diff --git a/golded3/gemnus.cpp b/golded3/gemnus.cpp new file mode 100644 index 0000000..bd6f2b7 --- /dev/null +++ b/golded3/gemnus.cpp @@ -0,0 +1,1078 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// More menus. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +void GMnuAsk::AskInit(int __row, int __col, char* __title, int __help) { + + Init(); + SetColor(C_ASKW, C_ASKQ, C_ASKN, C_ASKS, CFG->switches.get(screenshadows) ? C_SHADOW : -1); + SetTitle(__title, C_ASKT); + SetBorder(W_BASK, C_ASKB); + SetPos(__row, __col); + SetMask(M_CLOSE); + SetHelp(__help); +} + + +// ------------------------------------------------------------------ + +int GMnuYesNo::YesNo(int __row, int __col, char* __title, char* __yes, char* __no, int __help, int __yesno) { + + enum { TAG_ASKYES=100, TAG_ASKNO }; + + HandleGEvent(EVTT_ASKYESNO); + + AskInit(__row, __col, __title, __help); + + Begin(); + Item(TAG_ASKYES, __yes); + Item(TAG_ASKNO, __no); + SetTag(__yesno ? TAG_ASKYES : TAG_ASKNO); + End(); + + Start(); + + return (finaltag == TAG_ASKYES) ? YES : NO; +} + + +// ------------------------------------------------------------------ + +int GMenuQuit::Run() { + + int _yn = YesNo(1, 2, LNG->QuitGoldED, LNG->QuitYes, LNG->QuitNo, H_AskExit); + return _yn ? MODE_QUIT : NO; +} + + +// ------------------------------------------------------------------ + +int GMenuReadonly::Run() { + + int _yn = NO; + w_info(LNG->ReadOnlyWarn); + if(CFG->areareadonly == READONLY_SOFT) + _yn = YesNo(6, 0, LNG->IsReadOnly, LNG->ReadOnlyYes, LNG->ReadOnlyNo, H_AskReadOnly); + else + waitkeyt(10000); + w_info(NULL); + return _yn; +} + + +// ------------------------------------------------------------------ + +int GMenuChange::Run(char* info) { + + w_info(info); + int _yn = YesNo(6, 0, LNG->Change, LNG->ChangeYes, LNG->ChangeNo, H_AskChange); + w_info(NULL); + return _yn; +} + + +// ------------------------------------------------------------------ + +int GMenuLockLoop::Run() { + + w_info(LNG->WaitOrExit); + int _yn = YesNo(6, 0, LNG->ReallyExit, LNG->QuitYes, LNG->QuitNo, H_AskExit); + w_info(NULL); + return _yn; +} + + +// ------------------------------------------------------------------ + +int GMenuDelorig::Run() { + + return YesNo(6, 0, LNG->DelOrig, LNG->DelOrigYes, LNG->DelOrigNo, H_AskDelOrig); +} + + +// ------------------------------------------------------------------ + +int GMenuDropmsg::Run() { + + return YesNo(6, 0, LNG->DropMsg, LNG->DropMsgYes, LNG->DropMsgNo, H_AskDropMsg, CFG->switches.get(menudropmsg)); +} + + +// ------------------------------------------------------------------ + +int GMenuZonegate::Run() { + + return YesNo(6, 0, LNG->ZoneGate, LNG->ZoneGateYes, LNG->ZoneGateNo, H_AskZoneGate); +} + + +// ------------------------------------------------------------------ + +int GMenuForward::Run() { + + return YesNo(6, 0, LNG->Forward, LNG->ForwardYes, LNG->ForwardNo, H_AskForward); +} + + +// ------------------------------------------------------------------ + +int GMenuOverwrite::Run() { + + enum {TAG_APPEND=100, TAG_OVERWRITE, TAG_QUIT }; + + HandleGEvent(EVTT_ASKYESNO); + + AskInit(6, 0, LNG->FileExists, H_AskOverWrite); + + Begin(); + Item(TAG_APPEND, LNG->Append); + Item(TAG_OVERWRITE, LNG->OverWrite); + Item(TAG_QUIT, LNG->QuitExist); + End(); + + Start(); + + switch(finaltag) { + case TAG_OVERWRITE: + return YES; + case TAG_APPEND: + return NO; + } + + return -1; +} + + +// ------------------------------------------------------------------ + +int GMenuDelete::Run(int all, GMsg* __msg) { + + enum { TAG_YES=100, TAG_NO, TAG_NOASK }; + + HandleGEvent(EVTT_ASKYESNO); + + const char* _info = (__msg->attr.uns() and not __msg->attr.rcv()) ? LNG->WarnUnsent : ""; + if(__msg->attr.lok()) + _info = LNG->WarnLocked; + + if(*_info) + w_info(_info); + + AskInit(6, 0, LNG->DeleteThis, H_AskDelete); + + Begin(); + Item(TAG_YES, LNG->DeleteYes); + Item(TAG_NO, LNG->DeleteNo); + if(all) + Item(TAG_NOASK, LNG->DeleteNoAsk); + End(); + + Start(); + + if(*_info) + w_info(NULL); + + switch(finaltag) { + case TAG_YES: + return YES; + case TAG_NOASK: + return ALWAYS; + } + + return NO; +} + + +// ------------------------------------------------------------------ + +static void PressY() { if(gkbd.kbuf == NULL) kbput(*LNG->GotoNextYes); } +static void PressN() { if(gkbd.kbuf == NULL) kbput(*LNG->GotoNextNo); } + +int GMenuNewarea::Run() { + + enum { TAG_NO=100, TAG_YES, TAG_JUMP }; + + HandleGEvent(EVTT_ENDOFMSGS); + + uint _temp = AA->lastread(); + gkey _yeskey = Key_Rgt; + gkey _nokey = Key_Lft; + + if(AA->isreadmark) + _temp = AA->Mark.Find(AA->Msgn.CvtReln(AA->lastread())); + + if(_temp <= 1) { + _yeskey = Key_Rgt; + _nokey = Key_Lft; + } + + AskInit(6, 0, LNG->GotoNext, H_AskNextArea); + + Begin(); + Item(TAG_YES, LNG->GotoNextYes, M_CLOSE, PressY, _yeskey); + Item(TAG_NO, LNG->GotoNextNo, M_CLOSE, PressN, _nokey); + Item(TAG_JUMP, LNG->GotoNextNew); + SetTag(TAG_YES); + // Dirk: YES must be default for backward comp. Make it configurable. + End(); + + Start(); + + // Get the extra character from PressY/N + if(finaltag != -1 and finaltag != TAG_JUMP) + getxch(); + + if(finaltag == -1) + finaltag = TAG_NO; + + return (int) (finaltag - TAG_NO); +} + + +// ------------------------------------------------------------------ + +int GMenuCMF::Run() { + + enum { TAG_COPY=100, TAG_MOVE, TAG_FORWARD, TAG_QUIT }; + + static int _prevtag = TAG_FORWARD; + + update_statusline(LNG->CopyMoveForward); + + AskInit(6, 0, LNG->SelectAction, H_CopyMoveForward); + + Begin(); + Item(TAG_FORWARD, LNG->ForwardMessage); + Item(TAG_MOVE, LNG->MoveMessage); + Item(TAG_COPY, LNG->CopyMessage); + Item(TAG_QUIT, LNG->QuitCMF); + SetTag(_prevtag); + End(); + + Start(); + + _prevtag = finaltag; + switch(finaltag) { + case TAG_FORWARD: return MODE_FORWARD; + case TAG_MOVE: return MODE_MOVE; + case TAG_COPY: return MODE_COPY; + } + _prevtag = TAG_FORWARD; + return -1; +} + + +// ------------------------------------------------------------------ + +int GMenuDomarks::Run(char* dowhat) { + + enum { TAG_MARKED=100, TAG_CURRENT, TAG_QUIT }; + + static int _prevtag = TAG_CURRENT; + if(CFG->menumarked == MODE_MARKED) + _prevtag = TAG_MARKED; + else if(CFG->menumarked == MODE_CURRENT) + _prevtag = TAG_CURRENT; + else if(CFG->menumarked == MODE_DONT) + _prevtag = AA->Mark.Count() ? TAG_MARKED : TAG_CURRENT; + + update_statuslinef("%i %s %s", AA->Mark.Count(), AA->Mark.Count() == 1 ? LNG->is : LNG->are, LNG->marked); + + AskInit(6, 0, dowhat, H_AskDoMarks); + + Begin(); + Item(TAG_MARKED, LNG->MarkedMsg); + Item(TAG_CURRENT, LNG->CurrentMsg); + Item(TAG_QUIT, LNG->QuitMsgs); + SetTag(_prevtag); + End(); + + Start(); + + _prevtag = finaltag; + switch(finaltag) { + case TAG_CURRENT: return MODE_CURRENT; + case TAG_MARKED: return MODE_MARKED; + } + return MODE_DONT; +} + + +// ------------------------------------------------------------------ + +static int gmwm_usehdr = 1; + +void do_togglehdr() { + ++gmwm_usehdr; gmwm_usehdr %= 3; + gwin.cmenu->citem->str = (gmwm_usehdr == 1 ? LNG->WriteToHdrYES : gmwm_usehdr == 2 ? LNG->WriteToHdrONLY : LNG->WriteToHdrNO)+1; + gwin.cmenu->citem->redisp = true; +} + +int GMenuWriteMsg::Run() { + + enum { + TAG_DISKFILE=100, + TAG_PRINTER, + TAG_CLIPBRD, + TAG_TOGGLEHDR, + TAG_QUIT + }; + + static int _prevtag = TAG_DISKFILE; + + update_statusline(LNG->WriteMsgsTo); + + AskInit(6, 0, LNG->WriteTo, H_WriteMessage); + Begin(); + Item(TAG_DISKFILE, LNG->Diskfile); + Item(TAG_PRINTER, LNG->Printer); + Item(TAG_CLIPBRD, LNG->Clipboard); + Item(TAG_TOGGLEHDR, (gmwm_usehdr == 1 ? LNG->WriteToHdrYES : gmwm_usehdr == 2 ? LNG->WriteToHdrONLY : LNG->WriteToHdrNO), 0, do_togglehdr); + Item(TAG_QUIT, LNG->QuitWrite); + SetTag(_prevtag); + End(); + + Start(); + + _prevtag = finaltag; + int header = gmwm_usehdr == 1 ? 0 : gmwm_usehdr == 2 ? WRITE_ONLY_HEADER : WRITE_NO_HEADER; + switch(finaltag) { + case TAG_DISKFILE: return WRITE_FILE|header; + case TAG_PRINTER: return WRITE_PRINTER|header; + case TAG_CLIPBRD: return WRITE_CLIPBRD|header; + } + _prevtag = TAG_DISKFILE; + return -1; +} + + +// ------------------------------------------------------------------ + +static void do_changexlatimport() { ChangeXlatImport(); wmenuinext(100); } + +int GMenuImportTxt::Run() { + + enum { + TAG_TEXT = 100, + TAG_QUOTE, + TAG_BINUUE, + TAG_BINMIME, + TAG_CLIPBRD, + TAG_XLAT, + TAG_QUIT + }; + + // Dirk: Don't put a menu in the middle of the screen. + // AskInit((MAXROW-8)/2+3, (MAXCOL-strlen(LNG->ImportTxtText))/2, LNG->ImportTxt, H_ImportTxt); + AskInit(6, 0, LNG->ImportTxt, H_ImportTxt); + Begin(); + Item(TAG_TEXT , LNG->ImportTxtText); + Item(TAG_QUOTE , LNG->ImportTxtQuote); + Item(TAG_BINUUE , LNG->ImportTxtUue); + Item(TAG_BINMIME, LNG->ImportTxtMime); + Item(TAG_CLIPBRD, LNG->ImportTxtClip); + + if(not CFG->xlatcharset.empty()) + Item(TAG_XLAT , LNG->ImportTxtXlat, 0, do_changexlatimport); + + Item(TAG_QUIT , LNG->ImportTxtQuit); + End(); + + vcurhide(); + Start(); + vcurshow(); + + return finaltag - TAG_TEXT; +}; + + +// ------------------------------------------------------------------ + +int GMenuMarkMsgs::Run() { + + static int _prevtag = TAG_MARKYOURMAIL; + + update_statusline(LNG->MarkingOptions); + + AskInit(6, 0, LNG->MarkWhat, H_MarkMessages); + Begin(); + Item(TAG_MARKYOURMAIL, LNG->Yourmail); + Item(TAG_MARKHEADER, LNG->FromToSubj); + Item(TAG_MARKTXTHDR, LNG->TextHdr); + Item(TAG_MARKTHREAD, LNG->Thread); + Item(TAG_MARKNEWMSGS, LNG->NewMsgs); + Item(TAG_MARKOLDMSGS, LNG->OldMsgs); + Item(TAG_MARKALLMSGS, LNG->AllMsgs); + Item(TAG_MARKUNMARK, LNG->Unmark); + Item(TAG_MARKRANGE, LNG->Range); + Item(TAG_MARKTOGGLE, LNG->Markstoggle); + Item(TAG_MARKQUIT, LNG->QuitMarks); + SetTag(_prevtag); + End(); + + Start(); + + if(finaltag == -1) + return -1; + else + _prevtag = finaltag; + + return _prevtag; +} + + +// ------------------------------------------------------------------ + +static void _ask_attributes() { + + AskAttributes(MenuMsgPtr); +} + + +// ------------------------------------------------------------------ + +int GMenuEditfile::Run(GMsg* __msg) { + + if(not EDIT->SaveMenu()) + return MODE_SAVE; + + enum { + TAG_YES = 100, + TAG_NO, + TAG_CONTINUE, + TAG_ROT13, + TAG_ATTRS, + TAG_TAGLINE, + TAG_ORIGIN, + TAG_VIEW, + TAG_HEADER, + TAG_UTILS = 1000 + }; + + MenuMsgPtr = __msg; + + int _topline = 0; + + for(;;) { + + update_statuslinef(LNG->Quotepct, __msg->quotepct, __msg->quotepct > 80 ? "!!!" : ""); + + char _title[80]; + sprintf(_title, LNG->SaveMsg, __msg->lines); + AskInit(6, 0, _title, H_SaveMsg); + + Begin(); + Item(TAG_YES, LNG->YesGreat); + Item(TAG_NO, LNG->Kickit); + Item(TAG_CONTINUE, LNG->Continue); + Item(TAG_ROT13, LNG->Rot13, M_CLOSE); + Item(TAG_ATTRS, LNG->AttribS, _ask_attributes, 0); + if(not CFG->tagline.empty()) + Item(TAG_TAGLINE, LNG->TaglineS); + Item(TAG_ORIGIN, LNG->OriginS); + Item(TAG_VIEW, LNG->View); + Item(TAG_HEADER, LNG->HeaderEdit); + if(EDIT->SaveUtil.First()) { + int n = 0; + do { + Item(TAG_UTILS+(n++), (char*)EDIT->SaveUtil.Text()); // WARNING!!! + } while(EDIT->SaveUtil.Next()); + } + End(); + + Start(); + + switch(finaltag) { + + case TAG_YES: + return MODE_SAVE; + + case -1: + case TAG_NO: + { + GMenuDropmsg MenuDropmsg; + if(MenuDropmsg.Run()) + return MODE_QUIT; + } + break; + + case TAG_CONTINUE: + return MODE_CHANGE; + + case TAG_ROT13: + Rot13(__msg); + BodyView->Use(AA, __msg, _topline); + BodyView->Paint(); + break; + + case TAG_TAGLINE: + if(ChangeTagline()) { + char _buf[256]; + strcpy(_buf, AA->Tagline()); + if(*_buf == '@') + GetRandomLine(_buf, sizeof(_buf), _buf+1); + strcpy(__msg->tagline, _buf); + Line* _line = __msg->lin; + while(_line) { + if(_line->type & GLINE_TAGL) { + throw_release(_line->text); + sprintf(_buf, "%c%c%c %s ", AA->Taglinechar(), AA->Taglinechar(), AA->Taglinechar(), __msg->tagline); + _line->text = throw_strdup(_buf); + strtrim(_line->text); + break; + } + _line = _line->next; + } + } + BodyView->Use(AA, __msg, _topline); + BodyView->Paint(); + break; + + case TAG_ORIGIN: + if(ChangeOrigin()) { + char _buf[256]; + strcpy(_buf, AA->Origin()); + if(*_buf == '@') + GetRandomLine(_buf, sizeof(_buf), _buf+1); + MakeOrigin(__msg, _buf); + Line* _line = __msg->lin; + while(_line) { + if(_line->type & GLINE_ORIG) { + throw_release(_line->text); + sprintf(_buf, " * Origin: %s ", __msg->origin); + _line->text = throw_strdup(_buf); + strtrim(_line->text); + break; + } + _line = _line->next; + } + } + BodyView->Use(AA, __msg, _topline); + BodyView->Paint(); + break; + + case TAG_VIEW: + return MODE_VIEW; + + case TAG_HEADER: + EditHeaderinfo(MODE_CHANGE, *HeaderView); + break; + + default: + if(finaltag >= TAG_UTILS) { + ExternUtil(__msg, EDIT->SaveUtil.Number(finaltag-TAG_UTILS)); + BodyView->Use(AA, __msg, _topline); + BodyView->Paint(); + } + } + } + + return MODE_SAVE; +} + + +// ------------------------------------------------------------------ + +enum { + TAG_CCPROCESS = 100, + TAG_CCIGNORE, + TAG_CCATTRS, + TAG_CCLIST, + TAG_CCLISTKEEP, + TAG_CCLISTNAMES, + TAG_CCLISTVISIBLE, + TAG_CCLISTHIDDEN, + TAG_CCLISTREMOVE +}; + +static void SetCCListKeep() { CFG->carboncopylist = CC_KEEP; } +static void SetCCListNames() { CFG->carboncopylist = CC_NAMES; } +static void SetCCListVisible() { CFG->carboncopylist = CC_VISIBLE; } +static void SetCCListHidden() { CFG->carboncopylist = CC_HIDDEN; } +static void SetCCListRemove() { CFG->carboncopylist = CC_REMOVE; } + +int GMenuCarbon::Run(GMsg* __msg) { + + MenuMsgPtr = __msg; + + int _listtag = TAG_CCLISTKEEP; + switch(CFG->carboncopylist) { + case CC_KEEP: _listtag = TAG_CCLISTKEEP; break; + case CC_NAMES: _listtag = TAG_CCLISTNAMES; break; + case CC_VISIBLE: _listtag = TAG_CCLISTVISIBLE; break; + case CC_HIDDEN: _listtag = TAG_CCLISTHIDDEN; break; + case CC_REMOVE: _listtag = TAG_CCLISTREMOVE; break; + } + + AskInit(6, 0, LNG->CarbonCopy, H_CarbonCopy); + + Begin(); + Item(TAG_CCPROCESS, LNG->CCProcess); + Item(TAG_CCIGNORE, LNG->CCIgnore); + Item(TAG_CCATTRS, LNG->CCAttribs, _ask_attributes, 0); + Item(TAG_CCLIST, LNG->CCListFmt); + SetTitle(LNG->CCList); + Begin(); + Item(TAG_CCLISTKEEP, LNG->CCListKeep, SetCCListKeep); + Item(TAG_CCLISTNAMES, LNG->CCListNames, SetCCListNames); + Item(TAG_CCLISTVISIBLE, LNG->CCListVisible, SetCCListVisible); + Item(TAG_CCLISTHIDDEN, LNG->CCListHidden, SetCCListHidden); + Item(TAG_CCLISTREMOVE, LNG->CCListRemove, SetCCListRemove); + SetTag(_listtag); + End(); + End(); + + SetEsc(false); + + Start(); + + return finaltag == TAG_CCPROCESS; +} + + +// ------------------------------------------------------------------ + +static void SetXCListKeep() { CFG->crosspostlist = CC_KEEP; } +static void SetXCListNames() { CFG->crosspostlist = CC_NAMES; } +static void SetXCListVisible() { CFG->crosspostlist = CC_VISIBLE; } +static void SetXCListRemove() { CFG->crosspostlist = CC_REMOVE; } + +int GMenuCross::Run(GMsg* __msg) { + + MenuMsgPtr = __msg; + + int _listtag = TAG_CCLISTKEEP; + switch(CFG->crosspostlist) { + case CC_KEEP: _listtag = TAG_CCLISTKEEP; break; + case CC_NAMES: _listtag = TAG_CCLISTNAMES; break; + case CC_VISIBLE: _listtag = TAG_CCLISTVISIBLE; break; + case CC_REMOVE: _listtag = TAG_CCLISTREMOVE; break; + } + + AskInit(6, 0, LNG->Crosspost, H_Crosspost); + + Begin(); + Item(TAG_CCPROCESS, LNG->XCProcess); + Item(TAG_CCIGNORE, LNG->XCIgnore); + Item(TAG_CCLIST, LNG->XCListFmt); + SetTitle(LNG->XCList); + Begin(); + Item(TAG_CCLISTKEEP, LNG->XCListKeep, SetXCListKeep); + Item(TAG_CCLISTNAMES, LNG->XCListNames, SetXCListNames); + Item(TAG_CCLISTVISIBLE, LNG->XCListVisible, SetXCListVisible); + Item(TAG_CCLISTREMOVE, LNG->XCListRemove, SetXCListRemove); + SetTag(_listtag); + End(); + End(); + + SetEsc(false); + + Start(); + + return finaltag == TAG_CCPROCESS; +} + + +// ------------------------------------------------------------------ + +int GMnuAreaDo::With(char* __title, char* __all, char* __marked, char* __current, int __full, char* __no, int __help) { + + enum { + TAG_ALL=100, + TAG_MARKED, + TAG_CURRENT, + TAG_MATCHING, + TAG_UNSCANNED, + TAG_GROUP, + TAG_QWK, + TAG_IMPORTQWK, + TAG_EXPORTQWK, + TAG_SOUP, + TAG_EXPORTSOUP, + TAG_IMPORTSOUP, + TAG_NO, + TAG_LIST = 1000 + }; + + AskInit(1,2, __title, __help); + + Begin(); + Item(TAG_ALL, __all); + Item(TAG_MARKED, __marked); + Item(TAG_CURRENT, __current); + if(__full) { + Item(TAG_MATCHING, LNG->Scan_Matching); + Item(TAG_UNSCANNED, LNG->Scan_Unscanned); + Item(TAG_GROUP, LNG->ScanGroup); + if(AL.ListScan.First()) { + int count = 0; + do { + Item(TAG_LIST+count, (char*)AL.ListScan.MenuText()); // WARNING!!! + count++; + } while(AL.ListScan.Next()); + } + if(*QWK->ImportPath()) { + Item(TAG_QWK, LNG->ScanQWK); + SetTitle(LNG->QWKPacket); + Begin(); + Item(TAG_IMPORTQWK, LNG->ScanImport, M_CLALL); + Item(TAG_EXPORTQWK, LNG->ScanExport, M_CLALL); + End(); + } + if(*CFG->soupimportpath) { + Item(TAG_SOUP, LNG->ScanSoup); + SetTitle(LNG->SoupPacket); + Begin(); + Item(TAG_IMPORTSOUP, LNG->ScanImport, M_CLALL); + Item(TAG_EXPORTSOUP, LNG->ScanExport, M_CLALL); + End(); + } + if(*area_maybe) + SetTag(TAG_MATCHING); + } + else + SetTag(TAG_CURRENT); + + Item(TAG_NO, __no); + End(); + + Start(); + + if(finaltag >= TAG_LIST) { + AL.ListScan.CurrNo(finaltag-TAG_LIST); + return SCAN_LIST; + } + + switch(finaltag) { + case TAG_ALL: return SCAN_ALL; + case TAG_GROUP: return SCAN_GROUP; + case TAG_MARKED: return SCAN_MARKED; + case TAG_CURRENT: return SCAN_CURRENT; + case TAG_MATCHING: return SCAN_MATCHING; + case TAG_UNSCANNED: return SCAN_UNSCANNED; + case TAG_EXPORTQWK: return SCAN_EXPORTQWK; + case TAG_IMPORTQWK: return SCAN_IMPORTQWK; + case TAG_EXPORTSOUP: return SCAN_EXPORTSOUP; + case TAG_IMPORTSOUP: return SCAN_IMPORTSOUP; + } + + return SCAN_QUIT; +} + + +// ------------------------------------------------------------------ + +int GMenuAreaScan::Run(int pmscan) { + + return With((pmscan ? LNG->ScanPM : LNG->Scan_Areas), LNG->Scan_All, LNG->Scan_Marked, LNG->Scan_Current, true, LNG->No_Scan, H_ScanAreas); +} + + +// ------------------------------------------------------------------ + +int GMenuAreaHeat::Run() { + + return With(LNG->Heat_Areas, LNG->Heat_All, LNG->Heat_Marked, LNG->Heat_Current, false, LNG->No_Heat, H_HeatAreas); +} + + +// ------------------------------------------------------------------ + +int GMenuAreaZap::Run() { + + return With(LNG->Zap_Areas, LNG->Zap_All, LNG->Zap_Marked, LNG->Zap_Current, false, LNG->No_Zap, H_ZapAreas); +} + + +// ------------------------------------------------------------------ + +int GMenuAreaCatchup::Run() { + + return With(LNG->CatchAreas, LNG->CatchAll, LNG->CatchMarked, LNG->CatchCurrent, false, LNG->NoCatch, H_AreaCatchUp); +} + + +// ------------------------------------------------------------------ + +int GMenuAreaDropMarks::Run() { + + return With(LNG->DropMarks, LNG->DropAll, LNG->DropMarked, LNG->DropCurrent, false, LNG->NoDrop, H_AreaDropMarks); +} + + +// ------------------------------------------------------------------ + +int GMenuEditHeader::Run(int mode, GMsg* msg) { + + enum { + TAG_INTERNAL = 100, + TAG_EXTERNAL, + TAG_SAVE, + TAG_ATTRS, + TAG_TEMPLATE, + TAG_TAGLINE, + TAG_ORIGIN, + TAG_QUIT + }; + + HeaderView->Use(AA, msg); + HeaderView->Paint(); + + int _tag; + bool _again; + + int doedithdr = EDIT->HeaderFirst(); + if(doedithdr) { + switch(mode) { + case MODE_NEW: + doedithdr &= EDITHEADERFIRST_NEW; + break; + case MODE_CHANGE: + doedithdr &= EDITHEADERFIRST_CHANGES; + break; + case MODE_FORWARD: + doedithdr &= EDITHEADERFIRST_FORWARDS; + break; + default: + doedithdr &= EDITHEADERFIRST_REPLIES; + } + } + + do { + + update_statusline(LNG->EditHeader); + + if(doedithdr) { + _tag = EditHeaderinfo(mode, *HeaderView); + if((_tag == W_ESCPRESS) or gkbd.quitall) + break; + } + + do { + + _again = false; + + _tag = (EDIT->Internal() ? TAG_INTERNAL : (*EDIT->External() ? TAG_EXTERNAL : TAG_INTERNAL)); + + if(EDIT->Menu()) { + + Init(); + SetColor(C_MENUW, C_MENUQ, C_MENUN, C_MENUS, CFG->switches.get(screenshadows) ? C_SHADOW : -1); + SetTitle(LNG->MsgOptions, C_MENUT); + SetBorder(W_BMENU, C_MENUB); + SetPos(6, 0); + SetMask(0); + SetHelp(H_Message); + + Begin(); + Item(TAG_INTERNAL, LNG->InternalEd); + if(*EDIT->External()) + Item(TAG_EXTERNAL, LNG->ExternalEd); + Item(TAG_SAVE, LNG->SaveNoEdit); + Item(TAG_ATTRS, LNG->AttrO); + Item(TAG_TEMPLATE, LNG->Template); + if(not CFG->tagline.empty()) + Item(TAG_TAGLINE, LNG->Tagline); + Item(TAG_ORIGIN, LNG->Origin); + Item(TAG_QUIT, LNG->QuitMessage); + SetTag(_tag); + End(); + Start(); + _tag = finaltag; + } + if(_tag == -1) + _tag = W_ESCPRESS; + else { + switch(_tag) { + case TAG_ATTRS: + AskAttributes(msg); + CheckSubject(msg, msg->re); + HeaderView->Use(AA, msg); + HeaderView->Paint(); + _again = true; + break; + case TAG_ORIGIN: + if(ChangeOrigin()) { + if(*AA->Origin() == '@') { + char o[128]; + GetRandomLine(o, sizeof(o), AA->Origin()+1); + AA->SetOrigin(o); + } + strxcpy(msg->origin, AA->Origin(), sizeof(msg->origin)); + } + _again = true; + break; + case TAG_TAGLINE: + if(ChangeTagline()) { + if(*AA->Tagline() == '@') { + char t[76]; + GetRandomLine(t, sizeof(t), AA->Tagline()+1); + AA->SetTagline(t); + } + strcpy(msg->tagline, AA->Tagline()); + } + _again = true; + break; + case TAG_TEMPLATE: + if(ChangeTemplate() != -1) + AA->SetTpl(CFG->tpl[CFG->tplno].file); + _again = true; + break; + } + } + update_statusline(LNG->EditHeader); + } while(_again); + } while((_tag == W_ESCPRESS) and doedithdr); + + HeaderView->Use(AA, msg); + HeaderView->Paint(); + + if(not gkbd.quitall) { + switch(_tag) { + case W_ESCPRESS: + case TAG_QUIT: + return MODE_QUIT; + case TAG_EXTERNAL: + EDIT->Internal(false); + return MODE_CHANGE; + case TAG_INTERNAL: + EDIT->Internal(true); + return MODE_CHANGE; + case TAG_SAVE: + return NO; + } + } + return MODE_QUIT; +} + + +// ------------------------------------------------------------------ + +int GMenuNavigate::Run() { + + enum { + TAG_MAIN = 100, + TAG_MAIN_SHELL = (int)KK_ReadDosShell, + TAG_MAIN_QUIT = (int)KK_ReadQuitNow, + TAG_EDIT = 101, + TAG_EDIT_ENTER = (int)KK_ReadNewMsg, + TAG_EDIT_QUOTE = (int)KK_ReadQuoteMsg, + TAG_EDIT_COMMENT = (int)KK_ReadCommentMsg, + TAG_EDIT_OTHER = 1010, + TAG_EDIT_OTHER_QUOTE = (int)KK_ReadMoveQuoteMsg, + TAG_EDIT_OTHER_COMMENT = (int)KK_ReadMoveCommentMsg, + TAG_SEL = 102, + TAG_SEL_ORIGIN = (int)KK_ReadChangeOrigin, + TAG_SEL_USERNAME = (int)KK_ReadChangeUsername, + TAG_SEL_AKA = (int)KK_ReadChangeAka, + TAG_SEL_ATTRS = (int)KK_ReadChangeAttrs, + TAG_SEL_TEMPLATE = (int)KK_ReadChangeTemplate, + TAG_UTIL = 103, + TAG_UTIL_CMF = (int)KK_ReadCopyMoveForward, + TAG_UTIL_LIST = (int)KK_ReadMessageList, + TAG_UTIL_WRITE = (int)KK_ReadWriteMsg, + TAG_UTIL_FREQ = (int)KK_ReadFileRequest, + TAG_HELP = 104, + TAG_HELP_GENERAL, + TAG_HELP_ABOUT, + TAG_SEPARATOR, + TAG_END + }; + + Init(); + SetColor(C_ASKW, C_ASKQ, C_ASKN, C_ASKS); + SetTitle(NULL, C_ASKT); + SetBorder(5, C_ASKB); + SetPos(6, 0, MAXCOL, 1); + SetMask(M_CLALL); + SetHelp(9999); + + Begin(M_HORZ); + SetBorder(W_BASK, C_ASKB); + SetColor(C_ASKW, C_ASKQ, C_ASKN, C_ASKS, CFG->switches.get(screenshadows) ? C_SHADOW : -1); + Item(TAG_MAIN, "M Main "); + BeginPullDown(); + Item(TAG_MAIN_SHELL, "S Shell to OS "); + Item(TAG_MAIN_QUIT, "Q Quit GoldED "); + End(); + Item(TAG_EDIT, "E Edit "); + BeginPullDown(); + Item(TAG_EDIT_ENTER, "E Enter new msg "); + Item(TAG_EDIT_QUOTE, "Q Quote-reply "); + Item(TAG_EDIT_COMMENT, "C Comment-reply "); + Item(TAG_EDIT_OTHER, "O Other area reply >"); + SetTitle(" Other Area "); + Begin(); + Item(TAG_EDIT_OTHER_QUOTE, "Q Quote-reply "); + Item(TAG_EDIT_OTHER_COMMENT, "C Comment-reply "); + End(); + End(); + Item(TAG_SEL, "C Change "); + BeginPullDown(); + Item(TAG_SEL_ORIGIN, "O Origin "); + Item(TAG_SEL_USERNAME, "U Username "); + Item(TAG_SEL_AKA, "A Aka "); + Item(TAG_SEL_ATTRS, "M Msg attrs "); + Item(TAG_SEL_TEMPLATE, "T Template "); + End(); + Item(TAG_UTIL, "U Util "); + BeginPullDown(); + Item(TAG_UTIL_CMF, "C Copy/Move/Forward "); + Item(TAG_UTIL_LIST, "L List messages "); + Item(TAG_UTIL_WRITE, "W Write to disk/printer "); + Item(TAG_UTIL_FREQ, "F File request "); + End(); + Item(TAG_UTIL, "H Help "); + BeginPullDown(); + Item(TAG_HELP_GENERAL, "G General "); + Item(TAG_SEPARATOR, "----------", M_NOSEL); + Item(TAG_HELP_ABOUT, "A About "); + End(); + End(); + Start(); + if((finaltag >= TAG_MAIN) and (finaltag < (TAG_END*10))) + finaltag = -1; + return finaltag; +} + + +// ------------------------------------------------------------------ + +int GMenuConfirm::Run() { + + w_info(LNG->ConfirmInfo); + int _yn = YesNo(6, 0, LNG->Confirm, LNG->ConfirmYes, LNG->ConfirmNo, H_MenuConfirm); + w_info(NULL); + return _yn; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gemnus.h b/golded3/gemnus.h new file mode 100644 index 0000000..e827d4b --- /dev/null +++ b/golded3/gemnus.h @@ -0,0 +1,306 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Derived menu classes. +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ +// General menu with ASK colors + +class GMnuAsk : public GMnu { + +public: + void AskInit(int __row, int __col, char* __title, int __help); +}; + + +// ------------------------------------------------------------------ +// General YES/NO selection menu + +class GMnuYesNo : public GMnuAsk { + +public: + int YesNo(int __row, int __col, char* __title, char* __yes, char* __no, int __help, int __yesno=YES); +}; + + +// ------------------------------------------------------------------ + +class GMenuQuit : public GMnuYesNo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuReadonly : public GMnuYesNo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuChange : public GMnuYesNo { + +public: + int Run(char* info); +}; + + +// ------------------------------------------------------------------ + +class GMenuLockLoop : public GMnuYesNo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuDelorig : public GMnuYesNo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuDropmsg : public GMnuYesNo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuZonegate : public GMnuYesNo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuForward : public GMnuYesNo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuOverwrite : public GMnuAsk { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuDelete : public GMnuAsk { + +public: + int Run(int all, GMsg* __msg); +}; + + +// ------------------------------------------------------------------ + +class GMenuNewarea : public GMnuAsk { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuCMF : public GMnuAsk { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuDomarks : public GMnuAsk { + +public: + int Run(char* dowhat); +}; + + +// ------------------------------------------------------------------ + +class GMenuWriteMsg : public GMnuAsk { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuImportTxt : public GMnuAsk { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuMarkMsgs : public GMnuAsk { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuEditfile : public GMnuAsk { + +public: + int Run(GMsg* __msg); +}; + + +// ------------------------------------------------------------------ + +class GMenuCarbon : public GMnuAsk { + +public: + int Run(GMsg* __msg); +}; + + +// ------------------------------------------------------------------ + +class GMenuCross : public GMnuAsk { + +public: + int Run(GMsg* __msg); +}; + + +// ------------------------------------------------------------------ + +class GMnuAreaDo : public GMnuAsk { + +public: + int With(char* __title, char* __all, char* __marked, char* __current, int __full, char* __no, int __help); +}; + + +// ------------------------------------------------------------------ + +class GMenuAreaScan : public GMnuAreaDo { + +public: + int Run(int pmscan); +}; + + +// ------------------------------------------------------------------ + +class GMenuAreaHeat : public GMnuAreaDo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuAreaZap : public GMnuAreaDo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuAreaCatchup : public GMnuAreaDo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuAreaDropMarks : public GMnuAreaDo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuEditHeader : public GMnu { + +public: + int Run(int mode, GMsg* msg); +}; + + +// ------------------------------------------------------------------ + +class GMenuConfirm : public GMnuYesNo { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + +class GMenuNavigate : public GMnu { + +public: + int Run(); +}; + + +// ------------------------------------------------------------------ + diff --git a/golded3/gemrks.cpp b/golded3/gemrks.cpp new file mode 100644 index 0000000..3246fa5 --- /dev/null +++ b/golded3/gemrks.cpp @@ -0,0 +1,357 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Msg marks handling. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern GMsg* reader_msg; + + +// ------------------------------------------------------------------ + +int NextMarkedmsg(int direction, GMsg* msg) { + + GTag& tag = AA->isreadpm ? AA->PMrk : AA->Mark; + + if(tag.Count()) { + uint n; + ulong msgno = 0; + if(direction == DIR_NEXT) { + if(msg->msgno != tag[tag.Count()-1]) { + for(n=0; n msg->msgno) { + break; + } + } + if(n >= tag.Count()) + n = tag.Count()-1; + msgno = n+1; + } + else { + n = tag.Count()-1; + } + AA->set_lastread(AA->Msgn.ToReln(tag[n])); + } + else { + if(msg->msgno != tag[0]) { + n = tag.Count(); + do { + if(tag[--n] < msg->msgno) + break; + } while(n); + msgno = n+1; + } + else { + n = 0; + } + AA->set_lastread(AA->Msgn.ToReln(tag[n])); + } + return msgno ? 1 : 0; + } + return 0; +} + + +// ------------------------------------------------------------------ + +void MarkMsgs_Unmark() { + + AA->Mark.ResetAll(); + AA->isreadmark = false; +} + + +// ------------------------------------------------------------------ + +void MarkMsgs_Toggle() { + + GTag tmp; + + // Transplant current marks + tmp.SetCount(AA->Mark.Count()); + tmp.tag = AA->Mark.tag; + tmp.allocated = AA->Mark.allocated; + + // Reset marks + AA->Mark.SetCount(0); + AA->Mark.tag = NULL; + AA->Mark.allocated = 0; + AA->isreadmark = false; + + if(tmp.Count()) { + AA->Mark.Resize(AA->Msgn.Count()-tmp.Count()); + uint m=0, x=0; + for(uint n = 0; n < AA->Msgn.Count(); n++) { + if(tmp.tag[x] != AA->Msgn[n]) + AA->Mark[m++] = AA->Msgn[n]; + else + x++; + } + } + + tmp.Reset(); +} + + +// ------------------------------------------------------------------ + +void MarkMsgs_All() { + + AA->Mark.Resize(AA->Msgn.Count()); + memcpy(AA->Mark.tag, AA->Msgn.tag, AA->Msgn.Count()*sizeof(ulong)); +} + + +// ------------------------------------------------------------------ + +void MarkMsgs_New() { + + uint oldmarks = AA->Mark.Count(); + AA->Mark.Resize(AA->Mark.Count()+(AA->Msgn.Count() - AA->lastread())); + memcpy(AA->Mark.tag+oldmarks, AA->Msgn.tag+AA->lastread(), (AA->Msgn.Count()-AA->lastread())*sizeof(ulong)); + AA->Mark.Sort(); + AA->Mark.ElimDups(); +} + + +// ------------------------------------------------------------------ + +void MarkMsgs_Old() { + + uint oldmarks = AA->Mark.Count(); + AA->Mark.Resize(AA->Mark.Count() + (AA->lastread() - 1)); + memcpy(AA->Mark.tag+oldmarks, AA->Msgn.tag, (AA->lastread()-1)*sizeof(ulong)); + AA->Mark.Sort(); + AA->Mark.ElimDups(); +} + + +// ------------------------------------------------------------------ + +void MarkMsgs_Range() { + + uint markstart = AA->Msgn.ToReln(AA->bookmark); + uint markstop = AA->lastread(); + uint temp = MinV(markstart, markstop); + uint mrks = (MaxV(markstart, markstop) - MinV(markstart, markstop)) + 1; + uint oldmarks = AA->Mark.Count(); + AA->Mark.Resize(AA->Mark.Count() + mrks); + for(uint n=0; nMark[oldmarks+n] = AA->Msgn[temp+n-1]; + AA->Mark.Sort(); + AA->Mark.ElimDups(); +} + + +// ------------------------------------------------------------------ + +void MarkMsgs_Txt(int item, char* markstring) { + + if(item == TAG_MARKHEADER or item == TAG_MARKTXTHDR) { + if(not edit_string(markstring, sizeof(INam), LNG->EnterMarkString, H_MarkString)) + return; + } + + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + golded_search_manager srchmgr; + srchmgr.prepare_from_string(markstring, (item == TAG_MARKTXTHDR) ? GFIND_HDRTXT : GFIND_HDR); + + w_progress(MODE_NEW, C_INFOW, 0, AA->Msgn.Count(), LNG->AdvancedMarking); + + uint n; + int marked=0; + for(n=AA->lastread(); srchmgr.direction == DIR_NEXT ? (n<=AA->Msgn.Count()) : (n>=1); srchmgr.direction == DIR_NEXT ? n++ : n--) { + if(kbxhit()) { + if(kbxget() == Key_Esc) { + HandleGEvent(EVTT_SEARCHFAILED); + break; + } + } + + update_statuslinef(LNG->SearchingMsg, n, AA->Msgn.Count(), marked); + w_progress(MODE_UPDATE, C_INFOW, n, AA->Msgn.Count(), NULL); + + if(AA->LoadMsg(msg, AA->Msgn[n-1], CFG->dispmargin-(int)CFG->switches.get(disppagebar))) { + + bool success = srchmgr.search(msg, false, true); + + if(srchmgr.reverse ? not success : success) { + AA->Mark.Add(msg->msgno); + update_statuslinef(LNG->SearchingMsg, n, AA->Msgn.Count(), ++marked); + } + } + } + + w_progress(MODE_QUIT, 0, 0, 0, NULL); + + ResetMsg(msg); + throw_free(msg); +} + + +// ------------------------------------------------------------------ + +static void recursive_mark(GMsg* msg, ulong msgno) { + + int i; + gmsg_links templink; + + if(AA->Msgn.ToReln(msgno) and AA->LoadHdr(msg, msgno)) { + + templink = msg->link; + + if(templink.first()) + AA->Mark.Add(templink.first()); + + for(i = 0; i < templink.list_max(); i++) { + if(templink.list(i)) { + AA->Mark.Add(templink.list(i)); + } + } + + if(templink.first()) + recursive_mark(msg, templink.first()); + + for(i = 0; i < templink.list_max(); i++) { + if(templink.list(i)) { + recursive_mark(msg, templink.list(i)); + } + } + } +} + + +// ------------------------------------------------------------------ + +void MarkMsgs_Thread(GMsg* msg) { + + GMsg* tempmsg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + tempmsg->msgno = msg->msgno; + + w_info(LNG->Wait); + + AA->Mark.Add(msg->msgno); + + ulong msgno = msg->link.to(); + while(AA->Msgn.ToReln(msgno)) { // Search backwards + AA->Mark.Add(msgno); + + if(not AA->LoadHdr(tempmsg, msgno)) + tempmsg->link.to_set(0); + msgno = tempmsg->link.to(); + } + + recursive_mark(tempmsg, tempmsg->msgno); + + w_info(NULL); + + ResetMsg(tempmsg); + throw_free(tempmsg); +} + + +// ------------------------------------------------------------------ + +void MarkMsgs(GMsg* msg) { + + GFTRK("MarkMsgs"); + + static INam markstring; + + GMenuMarkMsgs MenuMarkMsgs; + int item = MenuMarkMsgs.Run(); + + switch(item) { + + // --------------------------------------------------------------- + case TAG_MARKUNMARK: + MarkMsgs_Unmark(); + break; + + // --------------------------------------------------------------- + case TAG_MARKTOGGLE: + MarkMsgs_Toggle(); + break; + + // --------------------------------------------------------------- + case TAG_MARKALLMSGS: + MarkMsgs_All(); + break; + + // --------------------------------------------------------------- + case TAG_MARKNEWMSGS: + MarkMsgs_New(); + break; + + // --------------------------------------------------------------- + case TAG_MARKOLDMSGS: + MarkMsgs_Old(); + break; + + // --------------------------------------------------------------- + case TAG_MARKRANGE: + MarkMsgs_Range(); + break; + + // --------------------------------------------------------------- + case TAG_MARKYOURMAIL: + sprintf(markstring, "\"%s\"", AA->Username().name); + // Drop through! + + // --------------------------------------------------------------- + case TAG_MARKHEADER: + // Drop through! + + // --------------------------------------------------------------- + case TAG_MARKTXTHDR: + MarkMsgs_Txt(item, markstring); + break; + + // --------------------------------------------------------------- + case TAG_MARKTHREAD: + MarkMsgs_Thread(msg); + break; + } + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + +void MarkingOptions() { + + if(AA->Msgn.Count()) + MarkMsgs(reader_msg); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gemsgs.cpp b/golded3/gemsgs.cpp new file mode 100644 index 0000000..075e0f2 --- /dev/null +++ b/golded3/gemsgs.cpp @@ -0,0 +1,608 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Misc. msg handling. +// ------------------------------------------------------------------ + +#include +#include +#include + + +// ------------------------------------------------------------------ + +static bool tokenxchg(char*& dst, char* tok, const char* src, int len = 0, int cnt = 0, ...) { + + uint toklen = strlen(tok); + char buf[100]; + bool use; + + if(*dst != *tok) + return false; + if(not strnieql(dst, tok, toklen)) { + if(len and *dst and (*(dst+1) == '_') and *(dst+2)) { + if(not strnieql(dst+2, tok+1, toklen-1)) + return false; + else + toklen++; + } + else + return false; + } + else + len = 0; + + va_list a; + va_start(a, cnt); + for(int i = 0; i < cnt; i ++) { + use = va_arg(a, bool); + if(dst[toklen] == '{') { + char *p = strchr(dst+toklen, '}'); + if(p) { + uint len = p-dst-toklen-1; + if(use && len) { + strxcpy (buf, dst+toklen+1, len+1); + src = buf; + } + toklen = p-dst+1; + } + } + } + va_end(a); + + uint sl = strlen(src); + uint srclen = (len == 0) ? sl : len; + memmove(dst+srclen, dst+toklen, strlen(dst+toklen)+1); + memset(dst, ' ', srclen); + memcpy(dst, src, sl); + dst += srclen; + return true; +} + + +// ------------------------------------------------------------------ + +char* TokenXlat(int mode, char* input, GMsg* msg, GMsg* oldmsg, int __origarea) { + + char longpid[100]; + sprintf(longpid, "%s%s%s%s", __gver_prename__, __gver_name__, __gver_postname__, __gver_platform__); + + char shortpid[100]; + sprintf(shortpid, "%s%s", __gver_shortname__, __gver_shortplatform__); + + char longverbuf[100]; + sprintf(longverbuf, "%s%i.%i.%i%s", __gver_preversion__, __gver_major__, __gver_minor__, __gver_release__, __gver_postversion__); + + char verbuf[100]; + sprintf(verbuf, "%i.%i.%i", __gver_major__, __gver_minor__, __gver_release__); + + char revbuf[100]; + sprintf(revbuf, "%02d%02d", str2mon(__gver_date__), atoi(&__gver_date__[4])); + + char xmailer[356]; + get_informative_string(xmailer); + + struct tm* written_tm = gmtime(&msg->written); + char cdate[32]; + strftimei(cdate, 32, LNG->DateFmt, written_tm); + char ctime[32]; + strftimei(ctime, 32, LNG->TimeFmt, written_tm); + written_tm = gmtime(&oldmsg->written); + char odate[32]; + strftimei(odate, 32, LNG->DateFmt, written_tm); + char otime[32]; + strftimei(otime, 32, LNG->TimeFmt, written_tm); + + const char* osslashbuf = __gver_platform__; + + const char* origareaid = AL.AreaIdToPtr(__origarea)->echoid(); + bool origareaisinet = AL.AreaIdToPtr(__origarea)->isinternet(); + bool currareaisinet = AA->isinternet(); + char* modereptr = oldmsg->re; + + if(mode == MODE_QUOTE or mode == MODE_REPLYCOMMENT or mode == MODE_REPLY) { + if(AL.AreaIdToPtr(__origarea)->Areareplydirect() and oldmsg->areakludgeid) + origareaid = oldmsg->areakludgeid; + } + else if(mode != MODE_FORWARD) + modereptr = msg->re; + + char buf[100]; + char* dst = input; + + while(*dst) { + while((*dst != '@') and (*dst != LF) and *dst) + dst++; + if(*dst == LF) + *dst++ = CR; + else if(*dst == '@') { + if(dst[1] == '@') { + memmove(dst, dst+1, strlen(dst+1)+1); + dst++; + } + else { + if(tokenxchg(dst, "@cecho", AA->echoid())) + continue; + if(tokenxchg(dst, "@cdesc", AA->desc())) + continue; + if(tokenxchg(dst, "@oecho", origareaid)) + continue; + if(tokenxchg(dst, "@odesc", AL.AreaEchoToPtr(origareaid)->desc())) + continue; + if(origareaisinet) { + if(tokenxchg(dst, "@oaddr", oldmsg->iorig, 19)) + continue; + } + else { + if(tokenxchg(dst, "@oaddr", oldmsg->orig.make_string(buf, oldmsg->odom), 19)) + continue; + if(strnieql(dst, "@o3daddr", 8)) { + ftn_addr boss = oldmsg->orig; + boss.point = 0; + tokenxchg(dst, "@o3daddr", boss.make_string(buf, oldmsg->odom), 19); + continue; + } + } + if(tokenxchg(dst, "@oname", strbtrim(strtmp(oldmsg->By())), 34, 2, + msg->by_me(), msg->by_you())) + continue; + if(tokenxchg(dst, "@ofname", strlword(oldmsg->By()), 0, 2, + msg->by_me(), msg->by_you())) + continue; + if(tokenxchg(dst, "@olname", strrword(oldmsg->By()), 0, 2, + msg->by_me(), msg->by_you())) + continue; + if(tokenxchg(dst, "@odate", odate)) + continue; + if(tokenxchg(dst, "@otime", otime)) + continue; + if(tokenxchg(dst, "@otzoffset", (oldmsg->tzutc == -32767) ? "" : (sprintf(buf, " %+05d", oldmsg->tzutc), buf))) + continue; + if(tokenxchg(dst, "@ofrom", oldmsg->ifrom)) + continue; + if(tokenxchg(dst, "@oto", oldmsg->ito)) + continue; + if(tokenxchg(dst, "@omessageid", oldmsg->messageid ? oldmsg->messageid : "")) + continue; + if(origareaisinet) { + if(tokenxchg(dst, "@daddr", oldmsg->iaddr, 19)) + continue; + } + else { + if(tokenxchg(dst, "@daddr", oldmsg->dest.make_string(buf, oldmsg->ddom), 19)) + continue; + if(strnieql(dst, "@d3daddr", 8)) { + ftn_addr boss = oldmsg->dest; + boss.point = 0; + tokenxchg(dst, "@d3daddr", boss.make_string(buf, oldmsg->ddom), 19); + continue; + } + } + if(tokenxchg(dst, "@dname", strbtrim(strtmp(oldmsg->To())), 34, 3, + msg->to_me(), msg->to_you(), oldmsg->to_all())) + continue; + if(tokenxchg(dst, "@dfname", strlword(oldmsg->To()), 0, 3, + msg->to_me(), msg->to_you(), oldmsg->to_all())) + continue; + if(tokenxchg(dst, "@dlname", strrword(oldmsg->To()), 0, 3, + msg->to_me(), msg->to_you(), oldmsg->to_all())) + continue; + if(currareaisinet) { + if(tokenxchg(dst, "@taddr", msg->iaddr, 19)) + continue; + } + else { + if(tokenxchg(dst, "@taddr", msg->dest.make_string(buf, msg->ddom), 19)) + continue; + if(strnieql(dst, "@t3daddr", 8)) { + ftn_addr boss = msg->dest; + boss.point = 0; + tokenxchg(dst, "@t3daddr", boss.make_string(buf, msg->ddom), 19); + continue; + } + } + if(tokenxchg(dst, "@tname", strbtrim(strtmp(msg->To())), 34, 3, + false, false, msg->to_all())) + continue; + if(tokenxchg(dst, "@tfname", strlword(msg->To()), 0, 3, + false, false, msg->to_all())) + continue; + if(tokenxchg(dst, "@tlname", strrword(msg->To()), 0, 3, + false, false, msg->to_all())) + continue; + if(currareaisinet) { + if(tokenxchg(dst, "@caddr", AA->Internetaddress(), 19)) + continue; + } + else { + if(tokenxchg(dst, "@caddr", AA->Aka().addr.make_string(buf), 19)) + continue; + if(strnieql(dst, "@c3daddr", 8)) { + ftn_addr boss = AA->Aka().addr; + boss.point = 0; + tokenxchg(dst, "@c3daddr", boss.make_string(buf), 19); + continue; + } + } + if(tokenxchg(dst, "@cname", AA->Username().name, 34)) + continue; + if(tokenxchg(dst, "@cfname", strlword(strcpy(buf, AA->Username().name)))) + continue; + if(tokenxchg(dst, "@clname", strrword(strcpy(buf, AA->Username().name)))) + continue; + if(tokenxchg(dst, "@cdate", cdate)) + continue; + if(tokenxchg(dst, "@ctime", ctime)) + continue; + if(tokenxchg(dst, "@ctzoffset", AA->Usetzutc() ? (sprintf(buf, " %+05d", tzoffset()), buf) : "")) + continue; + if(currareaisinet) { + if(tokenxchg(dst, "@faddr", msg->iorig, 19)) + continue; + } + else { + if(tokenxchg(dst, "@faddr", msg->orig.make_string(buf, msg->odom), 19)) + continue; + if(strnieql(dst, "@f3daddr", 8)) { + ftn_addr boss = msg->orig; + boss.point = 0; + tokenxchg(dst, "@f3daddr", boss.make_string(buf, msg->odom), 19); + continue; + } + } + if(tokenxchg(dst, "@fname", strbtrim(strtmp(msg->By())), 34)) + continue; + if(tokenxchg(dst, "@ffname", strlword(msg->By()))) + continue; + if(tokenxchg(dst, "@flname", strrword(msg->By()))) + continue; + if(strnieql(dst, "@dpseudo", 8)) { + if(*(oldmsg->pseudoto) == NUL) + build_pseudo(oldmsg); + tokenxchg(dst, "@dpseudo", oldmsg->pseudoto, 0, 3, msg->to_me(), msg->to_you(), oldmsg->to_all()); + continue; + } + if(strnieql(dst, "@opseudo", 8)) { + if(*(oldmsg->pseudofrom) == NUL) + build_pseudo(oldmsg, false); + tokenxchg(dst, "@opseudo", oldmsg->pseudofrom, 0, 2, msg->by_me(), msg->by_you()); + continue; + } + if(strnieql(dst, "@tpseudo", 8)) { + if(*(msg->pseudoto) == NUL) + build_pseudo(msg); + tokenxchg(dst, "@tpseudo", msg->pseudoto, 0, 3, false, false, msg->to_all()); + continue; + } + // Same as above (just for backward compatibility) + if(strnieql(dst, "@pseudo", 7)) { + if(*(msg->pseudoto) == NUL) + build_pseudo(msg); + tokenxchg(dst, "@pseudo", msg->pseudoto, 0, 3, false, false, msg->to_all()); + continue; + } + if(strnieql(dst, "@fpseudo", 8)) { + if(*(msg->pseudofrom) == NUL) + build_pseudo(msg, false); + tokenxchg(dst, "@fpseudo", msg->pseudofrom); + continue; + } + if(tokenxchg(dst, "@cpseudo", *AA->Nickname() ? AA->Nickname() : strlword(strcpy(buf, AA->Username().name)))) + continue; + if(tokenxchg(dst, "@version", longverbuf)) + continue; + if(tokenxchg(dst, "@ver", verbuf)) + continue; + if(tokenxchg(dst, "@rev", revbuf)) + continue; + if(tokenxchg(dst, "@pid", shortpid)) + continue; + if(tokenxchg(dst, "@longpid", longpid)) + continue; + if(tokenxchg(dst, "@widepid", xmailer)) + continue; + if(tokenxchg(dst, "@serialno", "")) + continue; + if(tokenxchg(dst, "@os2slash", osslashbuf)) + continue; + if(tokenxchg(dst, "@osslash", osslashbuf)) + continue; + if(tokenxchg(dst, "@subject", modereptr)) + continue; + if(tokenxchg(dst, "@tagline", + HandleRandomLine(strxcpy(buf, AA->Tagline(), sizeof(buf)), sizeof(buf)))) + continue; + if(tokenxchg(dst, "@tearline", + HandleRandomLine(strxcpy(buf, AA->Tearline(), sizeof(buf)), sizeof(buf)))) + continue; + if(tokenxchg(dst, "@origin", + HandleRandomLine(strxcpy(buf, AA->Origin(), sizeof(buf)), sizeof(buf)))) + continue; + dst++; + } + } + } + + return input; +} + + +// ------------------------------------------------------------------ +// ROT13 De/crypting function + +void Rot13(GMsg* msg) { + + char c; + char* ptr; + int n; + Line* line; + static char rot13_table[256]; + static char done = NO; + #define ROT13_DECODE(c) (((c) & 0x80) ? (c) : rot13_table[c]) + + if(not done) { + for(n=0; n<256; n++) { + c = (char)n; + if (c >= 'a' and c <= 'm') c += '\xD'; + else if(c >= 'n' and c <= 'z') c -= '\xD'; + else if(c >= 'A' and c <= 'M') c += '\xD'; + else if(c >= 'N' and c <= 'Z') c -= '\xD'; + rot13_table[n] = c; + } + done = YES; + } + + line = msg->lin; + while(line) { + if(not (line->type & (GLINE_KLUDGE|GLINE_TEAR|GLINE_ORIG))) { + ptr = line->text; + while((c = *ptr) != NUL) + *ptr++ = ROT13_DECODE(c); + } + line = line->next; + } +} + + +// ------------------------------------------------------------------ + +void LoadText(GMsg* msg, const char* textfile) { + + FILE* fp; + uint size; + char* buf; + char* ptr; + char* txtptr; + int hardcr = NO, hardlen; + char hardline[20], tabspaces[9]; + + strcpy(tabspaces, " "); + #define PBUFSIZE 4096 // Allow a 4k long paragraph + + buf = (char*)throw_malloc(PBUFSIZE); + + fp = fsopen(textfile, "rt", CFG->sharemode); + if(fp) { + uint tlen = (uint)(fsize(fp)+512); + msg->txt = txtptr = (char*)throw_realloc(msg->txt, tlen); + memset(msg->txt, NUL, tlen); + + tabspaces[CFG->disptabsize] = NUL; + if(EDIT->HardLines()) + strcpy(hardline, EDIT->HardLine()); + else + *hardline = NUL; + strcat(hardline, "\n"); + hardlen = strlen(hardline); + *txtptr = NUL; + + while(fgets(buf, PBUFSIZE, fp)) { + strsrep(buf, "\t", tabspaces); // Expand tabs + if(strneql(buf, hardline, hardlen)) { + hardcr = not hardcr; + if(*txtptr == LF) + *txtptr = CR; + if(*txtptr) + txtptr++; + strcpy(buf, "\r"); + } + else { + ptr = buf; + while(*ptr == ' ') // Skip leading spaces + ptr++; + if(*ptr != LF) { + strsrep(buf, hardline, "\r"); + if(hardcr or *buf == CTRL_A) { + buf[strlen(buf)-1] = CR; + if(*txtptr == LF) + *txtptr = CR; + } + else if(is_quote(buf)) { + buf[strlen(buf)-1] = CR; + if(*txtptr == LF) + *txtptr = CR; + } + else if((buf[0] == buf[1]) and (buf[0] == buf[2])) { + buf[strlen(buf)-1] = CR; + if(*txtptr == LF) + *txtptr = CR; + } + else if(strnieql(buf, " * Origin: ", 11)) { + buf[strlen(buf)-1] = CR; + if(*txtptr == LF) + *txtptr = CR; + } + else if(strnieql(ptr, "CC:", 3)) { + buf[strlen(buf)-1] = CR; + if(*txtptr == LF) + *txtptr = CR; + } + else if(strnieql(ptr, "XC:", 3)) { + buf[strlen(buf)-1] = CR; + if(*txtptr == LF) + *txtptr = CR; + } + else if(strnieql(buf, "SEEN-BY: ", 9)) { + buf[strlen(buf)-1] = CR; + if(*txtptr == LF) + *txtptr = CR; + } + if(*txtptr == LF) { + if(*(txtptr-1) != ' ' and *ptr != ' ') + *txtptr++ = ' '; + } + else if(*txtptr != 0) + txtptr++; + } + else { + if(*txtptr == LF) + *txtptr = CR; + if(*txtptr) + txtptr++; + strcpy(buf, "\r"); + } + } + if(*(txtptr-1) == CR or *txtptr == NUL) { + ptr = buf; + size = strlen(ptr); + memcpy(txtptr, ptr, size); + txtptr += size-1; + } + } + if(*txtptr != CR) + *(++txtptr) = CR; + *(++txtptr) = NUL; + fclose(fp); + } + throw_free(buf); +} + + +// ------------------------------------------------------------------ + +void GMsg::LinesToText() { + + // Allow paragraphs up to 64k-1 long in the transfer buffer + int bufsize = 65535; + char* _buf = (char*)throw_malloc(bufsize); + + Chs* _xlat_table = CharTable; + int _xlat_level = _xlat_table ? (_xlat_table->level ? _xlat_table->level : 2) : 0; + + XlatStr(_buf, realby, _xlat_level, _xlat_table); + strxcpy(realby, _buf, sizeof(INam)); + XlatStr(_buf, realto, _xlat_level, _xlat_table); + strxcpy(realto, _buf, sizeof(INam)); + XlatStr(_buf, by, _xlat_level, _xlat_table); + strxcpy(by, _buf, sizeof(INam)); + XlatStr(_buf, to, _xlat_level, _xlat_table); + strxcpy(to, _buf, sizeof(INam)); + if(not (attr.frq() or attr.att() or attr.urq())) { + XlatStr(_buf, re, _xlat_level, _xlat_table); + strxcpy(re, _buf, sizeof(ISub)); + } + + int _lfterm = EDIT->CrLfTerm() and not AA->ispcboard(); + int _hardterm = AA->Edithardterm() or AA->ispcboard() or AA->iswildcat(); + int _isezycom = AA->isezycom(); + + uint _alloc_size = 1024; + Line* _line = lin; + uint _lines = 0; + + // Approximate the size of the text + while(_line) { + _alloc_size += strlen(_line->text); + _line = _line->next; + _lines++; + } + _alloc_size += _lines * (_lfterm ? 2 : 1); + + // Allocate the text + txt = (char*)throw_realloc(txt, _alloc_size); + + // Setup variables for the loop + _line = lin; + uint _size = 0; + char* _ptr = txt; + + // Build the text from the lines + + while(_line) { + *_buf = NUL; + char* _bptr; + bool _hterm = true; + if(_line->isheader()) { + _bptr = stpcpy(_buf, _line->text); + while(_line->next and _line->iswrapped()) { + _line = _line->next; + _bptr = stpcpy(_bptr, _line->text); + if((_bptr-_buf) > (bufsize-256)) { + int bptrlen = (int)(_bptr - _buf); + bufsize += 4096; + _buf = (char*)throw_realloc(_buf, bufsize); + _bptr = _buf + bptrlen; + } + } + } + else { + _bptr = XlatStr(_buf, _line->text, _xlat_level, _xlat_table); + if(*_buf and not _line->ishard()) { + if(_line->next) { + if(_line->next->text) { + if((*(_bptr-1) != ' ') and (*_line->next->text != ' ')) + if(_isezycom or not _hardterm) + *_bptr++ = ' '; + if(not _hardterm) { + if(_isezycom and not CFG->switches.get(dispsoftcr)) + *_bptr++ = SOFTCR; + _hterm = false; + } + } + } + } + } + if(_hterm) { + *_bptr++ = CR; + if(_lfterm) + *_bptr++ = LF; + } + if(*_buf) { + uint _buflen = (uint)(_bptr-_buf); + _size += _buflen; + if(_size >= _alloc_size) { + _alloc_size += 1024; + txt = (char*)throw_realloc(txt, _alloc_size); + } + _ptr = txt + _size; + memcpy(_ptr-_buflen, _buf, _buflen); + } + _line = _line->next; + } + *_ptr = NUL; + + throw_free(_buf); +} + + +// ------------------------------------------------------------------ diff --git a/golded3/genode.cpp b/golded3/genode.cpp new file mode 100644 index 0000000..f7b9727 --- /dev/null +++ b/golded3/genode.cpp @@ -0,0 +1,1189 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Nodelist lookup and browser. +// ------------------------------------------------------------------ + +#include +#include +#include +#include +#include + + +// ------------------------------------------------------------------ + +typedef char ListStr[160]; + + +// ------------------------------------------------------------------ +// Static data for the browser and associated functions + +static ftn_nodelist_index_base* NLP = NULL; +static ftn_nodelist_entry entry; + + +// ------------------------------------------------------------------ + +class NodelistBrowser { + +public: + + int ypos; // Window Starting Row + int xpos; // Window Starting Column + int ylen; // Window Height + int xlen; // Window Width + int btype; // Window Border Type + int battr; // Window Border Color + int wattr; // Window Color + int tattr; // Window Title Color + int sattr; // Window Selection Bar Color + int hattr; // Window Highlight Color + int loattr; // Window LoAttr Color + int sbattr; // Window Scrollbar Color + char* title; // Window Title + int helpcat; // Window Help Category + + int pos; // Display Pos (1 to maxpos) + int maxpos; // Display Pos + + int aborted; // True if aborted + int listwrap; // True if wrap-around is supported + + ftn_nodelist_entry* entries; + ListStr* liststr; + gwindow nodewin; + gwindow listwin; + char user_maybe[45]; + char titlet[80]; + int user_fuzidx; + int newmaybe; + int firstkey; + + NodelistBrowser(); + ~NodelistBrowser(); + + void Open(); + void Close(); + + void BeforeCursor(); + void AfterCursor(); + + void InitDisplay(); + + void DisplayBar(); + void DisplayLine(int line=-1); + void DisplayPage(); + + void Home(); + void End(); + + void Up(); + void Down(); + + void PageUp(); + void PageDown(); + + void Center(); + + int Run(); + + void BuildListString(int line); + + void ScrollUp(); + void ScrollDown(); + + int DoKey(gkey& keycode); +}; + + +// ------------------------------------------------------------------ + +NodelistBrowser::NodelistBrowser() { + + // Not implemented yet +} + + +// ------------------------------------------------------------------ + +NodelistBrowser::~NodelistBrowser() { + + throw_release(liststr); + throw_release(entries); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::Open() { + + maxpos = ylen - 4; + + vcurhide(); + nodewin.openxy(ypos, xpos, 2, xlen, 5, battr, wattr, sbattr); + listwin.openxy(ypos+2, xpos, ylen-2, xlen, btype, battr, wattr, sbattr); + + entries = (ftn_nodelist_entry*)throw_calloc(maxpos, sizeof(ftn_nodelist_entry)); + liststr = (ListStr*)throw_calloc(maxpos, sizeof(ListStr)); + + InitDisplay(); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::Close() { + + listwin.close(); + nodewin.close(); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::BeforeCursor() { + + // Nothing to do +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::AfterCursor() { + + char buf[200], line1[200], line2[200]; + + ftn_nodelist_entry* entryp = entries + (pos - 1); + + sprintf(line1, " %s%s%s%s%s%s ", + entryp->name, + (*entryp->system ? ", " : ""), entryp->system, + (*entryp->status ? " <" : ""), entryp->status, + (*entryp->status ? ">" : "") + ); + sprintf(buf, "%s %s", LNG->Phone, *entryp->phone ? entryp->phone : "-Unpublished-"); + strrjust(strsetsz(buf, MAXCOL-strlen(line1)-1)); + strcat(line1, buf); + strcat(line1, " "); + + sprintf(line2, " %s%s%s", + entryp->location, + (*entryp->location ? ", " : ""), entryp->address + ); + sprintf(buf, "%s%s%s%s", + entryp->baud, + (*entryp->baud ? " Bps" : ""), + ((*entryp->baud and *entryp->flags) ? ", " : ""), entryp->flags + ); + strrjust(strsetsz(buf, MAXCOL-strlen(line2)-1)); + strcat(line2, buf); + strcat(line2, " "); + nodewin.prints(0,0, wattr, line1); + nodewin.prints(1,0, wattr, line2); + + Path nlname; + *nlname = NUL; + if(NLP->index_name() and NLP->nodelist_name()) + sprintf(nlname, " %s / %s ", NLP->index_name(), NLP->nodelist_name()); + else if(NLP->index_name()) + sprintf(nlname, " %s ", NLP->index_name()); + if(*nlname) + listwin.title(nlname, tattr, TCENTER|TBOTTOM); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::InitDisplay() { + + sprintf(titlet, LNG->Lookup, user_maybe); + listwin.title(titlet, tattr, TCENTER); + + Center(); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::DisplayBar() { + + listwin.prints(pos-1, 0, sattr, liststr[pos-1]); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::DisplayLine(int line) { + + if(line == -1) + line = pos; + listwin.prints(line-1, 0, wattr, liststr[line-1]); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::BuildListString(int line) { + + int x1 = (MAXCOL-80)/3; + int x2 = x1; + int x3 = (MAXCOL-80) - (x1+x2); + + ftn_nodelist_entry* entryp = entries + (line - 1); + *entryp = NLP->entry(); + + if(NLP->browsing_names()) + sprintf(liststr[line-1], " %-*.*s %-*.*s %-*.*s ", 24+x1, 24+x1, entryp->name, 21+x2, 21+x2, entryp->address, 29+x3, 29+x3, entryp->system); + else + sprintf(liststr[line-1], " %-*.*s %-*.*s %-*.*s ", 21+x2, 21+x2, entryp->address, 24+x1, 24+x1, entryp->name, 29+x3, 29+x3, entryp->system); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::DisplayPage() { + + w_info(LNG->Wait); + + int line = 0; + while(line < maxpos) + entries[line++].addr.net = 0; + + NLP->push_state(); + + // Get entries above and including current entry + line = pos; + do { + BuildListString(line--); + } while(line and NLP->previous()); + + NLP->pop_state(); + NLP->push_state(); + + // Get entries below current entry + line = pos + 1; + while((line <= maxpos) and NLP->next()) + BuildListString(line++); + + NLP->pop_state(); + + w_info(NULL); + + line = 1; + char linebuf[200]; + linebuf[MAXCOL-2] = NUL; + + // Display blank lines if necessary + memset(linebuf, ' ', MAXCOL-2); + while(line <= maxpos) { + if(entries[line-1].addr.net) + break; + // Display separator line if necessary + if(entries[line].addr.net) + memset(linebuf, _box_table(btype, 1), MAXCOL-2); + listwin.prints(line-1, 0, wattr|ACSET, linebuf); + line++; + } + + // Display entry lines + while((line <= maxpos) and entries[line-1].addr.net) { + if(line == pos) + DisplayBar(); + else + DisplayLine(line); + line++; + } + + // Display separator line if necessary + memset(linebuf, _box_table(btype, 1), MAXCOL-2); + if(line <= maxpos) { + listwin.prints(line-1, 0, wattr|ACSET, linebuf); + line++; + } + + // Display blank lines if necessary + memset(linebuf, ' ', MAXCOL-2); + while(line <= maxpos) { + listwin.prints(line-1, 0, wattr, linebuf); + line++; + } +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::Home() { + + pos = 1; + NLP->first(); + DisplayPage(); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::End() { + + pos = maxpos; + NLP->last(); + DisplayPage(); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::ScrollUp() { + + memmove(entries, entries+1, (maxpos-1)*sizeof(ftn_nodelist_entry)); + memmove(liststr, liststr+1, (maxpos-1)*sizeof(ListStr)); + BuildListString(maxpos); + listwin.scroll_up(); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::ScrollDown() { + + memmove(entries+1, entries, (maxpos-1)*sizeof(ftn_nodelist_entry)); + memmove(liststr+1, liststr, (maxpos-1)*sizeof(ListStr)); + BuildListString(1); + listwin.scroll_down(); +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::Up() { + + if(NLP->previous()) { + if(pos > 1) { + DisplayLine(); + pos--; + } + else { + DisplayLine(); + ScrollDown(); + } + } + else if(listwrap) { + End(); + } +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::Down() { + + if(NLP->next()) { + if(pos < maxpos) { + DisplayLine(); + pos++; + } + else { + DisplayLine(); + ScrollUp(); + } + } + else if(listwrap) { + Home(); + } +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::PageUp() { + + if(pos > 1) { + DisplayLine(); + do { + if(not NLP->previous()) + break; + } while(--pos > 1); + } + else { + int count = 1; + while(count < maxpos) { + if(not NLP->previous()) + break; + count++; + } + DisplayPage(); + } +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::PageDown() { + + if(pos < maxpos) { + DisplayLine(); + do { + if(not NLP->next()) + break; + } while(++pos < maxpos); + } + else { + int count = 1; + while(count < maxpos) { + if(not NLP->next()) + break; + count++; + } + DisplayPage(); + } +} + + +// ------------------------------------------------------------------ + +void NodelistBrowser::Center() { + + switch(CFG->displistcursor) { + case LIST_TOP: + pos = 1; + break; + case LIST_NEARTOP: + pos = (maxpos / 4) + 1; + break; + case LIST_MIDDLE: + pos = (maxpos / 2) + 1; + break; + case LIST_NEARBOTTOM: + pos = (3 * (maxpos / 4)) + 1; + break; + case LIST_BOTTOM: + pos = maxpos; + break; + } + DisplayPage(); +} + + +// ------------------------------------------------------------------ + +int NodelistBrowser::Run() { + + int keyok; + gkey newkey; + gkey keycode; + + #ifdef GOLD_MOUSE + gmou.HideCursor(); + #endif + + Open(); + if(helpcat) + whelppcat(helpcat); + + do { + + listwin.move_cursor(pos-1, 0); + DisplayBar(); + AfterCursor(); + #ifdef GOLD_MOUSE + gmou.ShowCursor(); + #endif + keyok = YES; + + do { + newkey = keycode = getxchtick(); + if(newkey == Key_Tick) + DoKey(keycode); + } while(newkey == Key_Tick); + + do { + newkey = 0; + #ifdef GOLD_MOUSE + gmou.HideCursor(); + #endif + switch(keycode) { + case Key_Up: + BeforeCursor(); + Up(); + break; + case Key_Dwn: + BeforeCursor(); + Down(); + break; + case Key_PgUp: + BeforeCursor(); + PageUp(); + break; + case Key_PgDn: + BeforeCursor(); + PageDown(); + break; + case Key_Home: + BeforeCursor(); + Home(); + break; + case Key_End: + BeforeCursor(); + End(); + break; + default: + keyok = DoKey(keycode); + newkey = keycode; + } + if(newkey) + keycode = newkey; + } while(newkey); + } while(keyok); + + #ifdef GOLD_MOUSE + gmou.HideCursor(); + #endif + + if(helpcat) + whelpop(); + Close(); + + #ifdef GOLD_MOUSE + gmou.ShowCursor(); + #endif + + return aborted; +} + + +// ------------------------------------------------------------------ + +int NodelistBrowser::DoKey(gkey& keycode) { + + gkey key = keycode; + keycode = 0; + if(key < KK_Commands) { + gkey tmpkey = key_tolower(key); + gkey kk = SearchKey(tmpkey, NodeKey, NodeKeys); + if(kk) + key = kk; + } + + switch(key) { + case KK_NodeAskExit: + { + GMenuQuit MenuQuit; + if(MenuQuit.Run()) + keycode = KK_NodeQuitNow; + } + break; + + case KK_NodeQuitNow: + gkbd.quitall = YES; + if(gkbd.kbuf == NULL) + kbput(Key_Esc); + // Drop through + + case KK_NodeAbort: + newmaybe = NO; + aborted = YES; + // Drop Through + + case KK_NodeSelect: + if(newmaybe) { + newmaybe = NO; + firstkey = YES; + Addr matchaddr; + matchaddr.set_all(0xFFFF); + matchaddr.set(user_maybe); + bool gotzone = false; + bool gotnet = false; + bool gotnode = false; + bool gotpoint = false; + if(matchaddr.zone != 0xFFFF) + gotzone = true; + else + matchaddr.zone = 0; + if(matchaddr.net != 0xFFFF) + gotnet = true; + else + matchaddr.net = 0; + if(matchaddr.node != 0xFFFF) + gotnode = true; + else + matchaddr.node = 0; + if(matchaddr.point != 0xFFFF) + gotpoint = true; + else + matchaddr.point = 0; + if(gotzone or gotnet or gotnode or gotpoint) { + if(not gotzone) + matchaddr.zone = AA->Aka().addr.zone; + if(not gotnet) + matchaddr.net = AA->Aka().addr.net; + if(gotpoint and not gotnode) + matchaddr.node = AA->Aka().addr.node; + if(matchaddr.point >= GFTN_FIRST) + matchaddr.point = 0; + if(matchaddr.node >= GFTN_FIRST) + matchaddr.node = 0; + if(matchaddr.net >= GFTN_FIRST) + matchaddr.net = 0; + if(matchaddr.zone >= GFTN_FIRST) + matchaddr.zone = 0; + } + + if(matchaddr.net) + NLP->find(matchaddr); + else + NLP->find(user_maybe); + InitDisplay(); + } + else { + BeforeCursor(); + return NO; + } + break; + + case Key_Tab: + if(NLP->browsing_names() and NLP->can_browse_address()) { + strcpy(user_maybe, NLP->address()); + NLP->find(NLP->addrs()); + } + else if(NLP->browsing_addresses() and NLP->can_browse_name()) { + strcpy(user_maybe, NLP->name()); + NLP->find(NLP->name()); + } + user_fuzidx = strlen(user_maybe); + InitDisplay(); + break; + + case KK_NodeGotoPrev: + keycode = Key_Up; + firstkey = YES; + break; + + case KK_NodeGotoNext: + keycode = Key_Dwn; + firstkey = YES; + break; + + case KK_NodeGotoFirst: + keycode = Key_Home; + firstkey = YES; + break; + + case KK_NodeGotoLast: + keycode = Key_End; + firstkey = YES; + break; + + case KK_NodeDosShell: + DosShell(); + break; + + case Key_Tick: + CheckTick(KK_NodeQuitNow); + break; + + case KK_NodeUndefine: + break; + + default: + if(not PlayMacro(key, KT_N)) { + int n = key & 0xFF; + if((user_fuzidx < 41) or (key == Key_BS)) { + if(firstkey) { + if((key != Key_BS) and not isspace(n)) { + *user_maybe = 0; + user_fuzidx = 0; + } + } + firstkey = NO; + if((n >= ' ') or (key == Key_BS)) { + newmaybe = YES; + if(key != Key_BS) + user_maybe[user_fuzidx++] = (char)n; + else if(user_fuzidx) + user_maybe[--user_fuzidx] = 0; + user_maybe[user_fuzidx] = 0; + sprintf(titlet, LNG->Lookup, user_maybe); + listwin.title(titlet, tattr, TCENTER); + } + } + } + } + + return YES; +} + + +// ------------------------------------------------------------------ + +static int browse_nodelist(GMsg* msg, char* title, int topline) { + + w_info(NULL); + + NodelistBrowser* browser = new NodelistBrowser; + throw_new(browser); + + if(topline == 0) + ChgAttrs(NO, msg); // Close the attributes menu + + browser->btype = W_BMENU; + browser->battr = C_MENUB; + browser->wattr = C_MENUW; + browser->sattr = C_MENUS; + browser->tattr = C_MENUT; + browser->hattr = C_MENUQ; + browser->sbattr = C_MENUPB; + browser->helpcat = H_NodelistBrowser; + browser->ypos = topline; + browser->xpos = 0; + browser->ylen = MAXROW-browser->ypos-1; + browser->xlen = MAXCOL; + browser->listwrap = CFG->switches.get(displistwrap); + browser->firstkey = YES; + browser->newmaybe = NO; + browser->aborted = NO; + strxcpy(browser->user_maybe, title, sizeof(browser->user_maybe)); + browser->user_fuzidx = strlen(browser->user_maybe); + + int aborted = browser->Run(); + if(not aborted) + entry = browser->entries[browser->pos-1]; + + delete browser; + + if(topline == 0) + ChgAttrs(YES, msg); // Turn on the attributes menu again + + return (not aborted); +} + + +// ------------------------------------------------------------------ + +static bool NLP_open() { + + if(*CFG->nodepathv7) { + NLP = new ftn_version7_nodelist_index; + throw_new(NLP); + NLP->set_path(CFG->nodepathv7); + } + else if(*CFG->nodepathfd) { + NLP = new ftn_frontdoor_nodelist_index; + throw_new(NLP); + NLP->set_path(CFG->nodepathfd); + } + else if(*CFG->fidouserlist) { + NLP = new ftn_fidouser_nodelist_index; + throw_new(NLP); + NLP->set_path(CFG->fidouserlist); + } + else { + CheckNodelists(); + NLP = new ftn_golded_nodelist_index; + throw_new(NLP); + NLP->set_path(CFG->nodepath); + } + + return NLP->open(); +} + + +// ------------------------------------------------------------------ + +static void NLP_close() { + + NLP->close(); + throw_delete(NLP); +} + + +// ------------------------------------------------------------------ + +static Name nlname; + +const char *lookup_nodelist(ftn_addr* addr) { + + const char *r = NULL; + + if(NLP_open()) { + + NLP->find(*addr); + if(NLP->found()) { + strcpy(nlname, NLP->entry().name); + r = nlname; + } + } + NLP_close(); + return r; +} + + +// ------------------------------------------------------------------ + +void Lookup(GMsg* msg, Addr* addr, char* name, int topline, char* status) { + + char* ptr; + INam buf, buf1, tmpname; + bool found = false; + int robotchk; + bool dolookup = true; + bool namelookup = true; + Addr matchaddr; + bool exactmatch = true; + + strtrim(name); + if(*name == NUL) { + matchaddr = AA->Aka().addr; + namelookup = false; + exactmatch = false; + } + strcpy(tmpname, name); + + if(not CFG->addressmacro.empty()) { + vector::iterator n; + ptr = name; + strcpy(buf, ptr); + for(n=CFG->addressmacro.begin(); n != CFG->addressmacro.end(); n++) { + if(strieql(ptr, n->macro)) { + strcpy(buf1, n->name); + ptr = buf1; + if(*buf1 == '@') { + // UUCP/INTERNET addressing + ptr = strchr(buf1, '/'); + if(ptr) { + *ptr++ = NUL; + strcpy(msg->iaddr, ptr); + strcpy(msg->idest, ptr); + ptr = buf1+1; + } + else { + strcpy(msg->iaddr, buf1+1); + strcpy(msg->idest, buf1+1); + ptr = strcpy(buf1, *AA->Internetgate().name ? AA->Internetgate().name : "UUCP"); + } + } + strcpy(name, ptr); + if(n->addr.net) + *addr = n->addr; + else + *addr = AA->Internetgate().addr; + strtrim(name); + if(topline >= 0) + return; + } + } + } + + // Automatic internet gating + if(strchr(name, '@') and AA->Internetgate().addr.net) { + strcpy(msg->idest, name); + if(*AA->Internetgate().name) { + strcpy(msg->iaddr, name); + strcpy(msg->to, AA->Internetgate().name); + strcpy(name, msg->to); + } + *addr = AA->Internetgate().addr; + namelookup = false; + if(topline >= 0) + return; + } + + // Check if name is really an address + if(*tmpname) { + matchaddr.set_all(0xFFFF); + matchaddr.set(name); + bool gotzone = false; + bool gotnet = false; + bool gotnode = false; + bool gotpoint = false; + if(matchaddr.zone != 65535u) + gotzone = true; + else + matchaddr.zone = 0; + if(matchaddr.net != 65535u) + gotnet = true; + else + matchaddr.net = 0; + if(matchaddr.node != 65535u) + gotnode = true; + else + matchaddr.node = 0; + if(matchaddr.point != 65535u) + gotpoint = true; + else + matchaddr.point = 0; + if(gotzone or gotnet or gotnode or gotpoint) { + *addr = matchaddr; + if(not gotzone) + addr->zone = AA->Aka().addr.zone; + if(not gotnet) + addr->net = AA->Aka().addr.net; + if(gotpoint and not gotnode) + addr->node = AA->Aka().addr.node; + matchaddr = *addr; + namelookup = false; + if(matchaddr.point >= GFTN_FIRST) { + matchaddr.point = 0; + exactmatch = false; + } + if(matchaddr.node >= GFTN_FIRST) { + matchaddr.node = 0; + exactmatch = false; + } + if(matchaddr.net >= GFTN_FIRST) { + matchaddr.net = 0; + exactmatch = false; + } + if(matchaddr.zone >= GFTN_FIRST) { + matchaddr.zone = 0; + exactmatch = false; + } + } + } + + if(namelookup) { + ptr = strrchr(name, ' '); + if(ptr != NULL) { + addr->reset(); + addr->set(ptr+1); + if(addr->net) { + // Address was given + *ptr = NUL; + strtrim(name); + if(topline >= 0) + return; + } + } + } + + robotchk = NO; + if(striinc("Sysop", name) or strieql(AA->Whoto(), name)) + robotchk = YES; + else { + for(gstrarray::iterator n = CFG->robotname.begin(); n != CFG->robotname.end(); n++) + if(striinc(n->c_str(), name)) { + robotchk = YES; + break; + } + } + + if(robotchk) { + addr->reset(); + if(topline >= 0) + return; + } + + if(topline >= 0) { + dolookup = NO; + if(AA->isnet() and CFG->switches.get(lookupnet)) + dolookup = YES; + else if(AA->isecho() and CFG->switches.get(lookupecho)) + dolookup = YES; + else if(AA->islocal() and CFG->switches.get(lookuplocal)) + dolookup = YES; + } + + if(dolookup) { + + if(NLP_open()) { + + if(namelookup) + NLP->find(name); + else + NLP->find(matchaddr); + + found = (exactmatch and NLP->found()) ? true : false; + if(found) { + NLP->push_state(); + if(NLP->next()) + if(NLP->found()) + found = false; + NLP->pop_state(); + } + entry = NLP->entry(); + + if(not found or (topline < 0)) { + strcpy(buf, information); + update_statusline(status); + found = browse_nodelist(msg, tmpname, abs(topline)); + update_statusline(buf); + } + } + else { + w_info(LNG->NoNodelist); + waitkeyt(10000); + w_info(NULL); + } + + NLP_close(); + } + + if(found) { + strcpy(name, entry.name); + *addr = entry.addr; + } + else { + addr->reset(); + } + + if(topline >= 0) { + if(CFG->switches.get(internetlookup)) { + if(*entry.system and strchr(entry.system, '@') and AA->Internetgate().addr.net) { + strcpy(msg->iaddr, entry.system); + strcpy(msg->idest, entry.system); + if(*AA->Internetgate().name) + strcpy(msg->to, AA->Internetgate().name); + else if(strlen(entry.system) >= sizeof(Name)) + strcpy(msg->to, *AA->Internetgate().name ? AA->Internetgate().name : "UUCP"); + else { + strcpy(msg->to, entry.system); + *msg->iaddr = NUL; + *msg->idest = NUL; + } + strcpy(name, msg->to); + *addr = AA->Internetgate().addr; + } + } + } +} + + +// ------------------------------------------------------------------ +// Lookup and display info about the node + +void LookupNode(GMsg* msg, char* name, int what) { + + Subj statuslinebak; + strcpy(statuslinebak, information); + + vcurhide(); + w_info(LNG->Wait); + + Addr addr; + char buf[256]; + char* ptr = buf; + + switch(what) { + case LOOK_DEST: + if(AA->isnet()) { + addr = msg->dest; + if(addr.zone == 0) + addr.zone = AA->Aka().addr.zone; + addr.make_string(buf); + } + else { + addr.reset(); + strcpy(buf, msg->to); + } + break; + case LOOK_ORIG: + addr = msg->orig; + if(addr.zone == 0) + addr.zone = AA->Aka().addr.zone; + addr.make_string(buf); + break; + case LOOK_NAME: + addr = msg->orig; + strcpy(buf, strskip_wht(name)); + strtok(buf, " \t\n\r"); // Only lookup first word + break; + } + Lookup(msg, &addr, ptr, -6, LNG->LookupInfo); + + update_statusline(statuslinebak); + + w_info(NULL); +} + + +// ------------------------------------------------------------------ + +void CheckNodelists() { + + // Copy of previous timestamp + static long oldft = 0; + + // Get timestamp of the .GXL file + Path file; + strcpy(file, AddPath(CFG->nodepath, "goldnode.gxl")); + long ft = GetFiletime(file); + + // Check nodelists if timestamp changed + if(ft != oldft) { + + // Keep copy of timestamp for later lookups + oldft = ft; + + strcpy(NODE->addrindex, AddPath(CFG->nodepath, "goldnode.gxa")); + strcpy(NODE->nodeindex, AddPath(CFG->nodepath, "goldnode.gxn")); + + Subj statuslinebak; + strcpy(statuslinebak, information); + + update_statusline(LNG->CheckingNodelists); + + FILE* fp = fsopen(file, "rt", CFG->sharemode); + if(fp) { + + // Read the list index + char buf[256]; + NODE->nodelists = 0; + while(fgets(buf, sizeof(buf), fp)) { + NODE->nodelist = (Stamp*)throw_realloc(NODE->nodelist, (NODE->nodelists+1)*sizeof(Stamp)); + char* key; + char* val=buf; + getkeyval(&key, &val); + key = strxcpy(NODE->nodelist[NODE->nodelists].fn, strbtrim(key), sizeof(Path)); + MakePathname(key, CFG->nodepath, key); + NODE->nodelist[NODE->nodelists].ft = atol(val); + NODE->nodelists++; + } + fclose(fp); + + // Check the files + if(CFG->switches.get(nodelistwarn)) { + for(int n=0; nnodelists; n++) { + if(not fexist(MapPath(NODE->nodelist[n].fn))) { + w_infof(" %s %s ", LNG->NodelistMissing, NODE->nodelist[n].fn); + HandleGEvent(EVTT_ATTENTION); + waitkeyt(10000); + w_info(NULL); + } + else if(abs(long(GetFiletime(NODE->nodelist[n].fn)-NODE->nodelist[n].ft))>1) { + w_infof(" %s %s ", LNG->NodelistOutdated, NODE->nodelist[n].fn); + HandleGEvent(EVTT_ATTENTION); + waitkeyt(10000); + w_info(NULL); + } + } + } + } + + update_statusline(statuslinebak); + } + + throw_release(NODE->nodelist); + NODE->nodelists = 0; +} + +// ------------------------------------------------------------------ + diff --git a/golded3/geplay.cpp b/golded3/geplay.cpp new file mode 100644 index 0000000..81bb19d --- /dev/null +++ b/golded3/geplay.cpp @@ -0,0 +1,312 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Functions related to sound. +// ------------------------------------------------------------------ + +#define GOLD_SOUNDSUPPORT 1 +#include +#include +#ifdef GOLD_SOUNDSUPPORT +#include +#endif + + +// ------------------------------------------------------------------ + +#ifdef GOLD_SOUNDSUPPORT +gsound* snd = NULL; +#endif + + +// ------------------------------------------------------------------ + +#if defined(__MSDOS__) +#define Beep(A,B) { sound(A); usleep(B*CFG->beepfactor+1); } +#define Sleep(A) { usleep(A*CFG->beepfactor+1); } +#define NoSound() { nosound(); } +#elif defined(__OS2__) +#define Beep(A,B) { DosBeep(A, B*CFG->beepfactor/1000+1); } +#define Sleep(A) { usleep(A*CFG->beepfactor+1); } +#define NoSound() { } +#elif defined(__WIN32__) +#define Beep(A,B) { (Beep)(A, B*CFG->beepfactor/1000+1); } +#define Sleep(A) { usleep(A*CFG->beepfactor+1); } +#define NoSound() { } +#else +#define Beep(A,B) { } +#define Sleep(A) { } +#define NoSound() { } +#endif + + +// ------------------------------------------------------------------ + +void ResetSound(void) { + + #ifdef GOLD_SOUNDSUPPORT + if(snd->is_installed()) { + while(snd->is_playing()) { + if(kbxhit()) { + if(kbxget() == Key_Esc) { + snd->stop(); + break; + } + } + } + } + delete snd; + snd = NULL; + #endif +} + + +// ------------------------------------------------------------------ + +void InitSound() { + + // Find out if there are any sound files to be played + #ifdef GOLD_SOUNDSUPPORT + vector::iterator n; + for(n = CFG->event.begin(); n != CFG->event.end(); n++) { + if(n->play.type == PLAY_VOC) { + snd = new gsound; + if(snd->is_installed()) { + if(not quiet) + printf("\n* Soundcard support was successfully initialized."); + atexit(ResetSound); + } + else { + if(not quiet) + printf("\n* Soundcard support could NOT be initialized!"); + ResetSound(); + } + break; + } + } + #endif +} + + +// ------------------------------------------------------------------ +// Fill out a GPlay struct using a filename + +void FileToGPlay(GPlay* playbuf, char* filename) { + + if(strchr(CleanFilename(filename), '.') != NULL) + playbuf->type = PLAY_VOC; + else { + playbuf->type = PLAY_DOS; + if(strieql(filename, "TheEnd")) + playbuf->effectno = SND_THEEND; + else if(strieql(filename, "GotIt")) + playbuf->effectno = SND_GOTIT; + else if(strieql(filename, "TooBad")) + playbuf->effectno = SND_TOOBAD; + else if(strieql(filename, "ToYou")) + playbuf->effectno = SND_TOYOU; + else if(strieql(filename, "SayBiBi")) + playbuf->effectno = SND_SAYBIBI; + else if(strieql(filename, "SOS")) + playbuf->effectno = SND_S_O_S; + else + playbuf->effectno = 0xFFFF; + } + + strcpy(playbuf->file, filename); +} + + +// ------------------------------------------------------------------ +// Handle event + +int HandleGEvent(uint event) { + + int retval = -1; // Event could not be handled + + if(event == EVTT_BREAKLOOP) { + #ifdef GOLD_SOUNDSUPPORT + if(snd) { + while(snd->is_playing()) { + if(kbxhit()) { + if(kbxget() == Key_Esc) { + snd->stop(); + break; + } + } + } + } + #endif + return 0; + } + + if(event == EVTT_STOPVOICE) { + #ifdef GOLD_SOUNDSUPPORT + if(snd) + snd->stop(); + #endif + return 0; + } + + if(event == EVTT_REMOVEVOCBUF) { + #ifdef GOLD_SOUNDSUPPORT + if(snd) { + if(not snd->is_playing()) + snd->unload(); + } + #endif + return 0; + } + + if(CFG) { + vector::iterator n; + for(n = CFG->event.begin(); n != CFG->event.end(); n++) { + if(event == n->type) { + switch(n->command) { + case EVTC_PLAY: + n->play.Play(); + retval = 0; // Event was found and handled + break; + } + break; + } + } + } + else { + MakeNoise(SND_S_O_S); + } + + return retval; +} + + +// ------------------------------------------------------------------ +// Make infernal noises + +int MakeNoise(int type) { + + int n; + + if((CFG and CFG->switches.get(beepnoises)) and not disablesound) { + + switch(type) { + + case SND_SAYBIBI: + Beep(440, 111); + NoSound(); + break; + + case SND_TOYOU: + for(n=100; n<800; n+=400) + Beep(n, 18); + for(; n>100; n-=400) + Beep(n, 18); + NoSound(); + break; + + case SND_THEEND: + Beep(220, 111); + Beep(110, 167); + NoSound(); + break; + + case SND_GOTIT: + Beep(110, 56); + Beep(220, 56); + Beep(110, 56); + Beep(220, 111); + NoSound(); + break; + + case SND_TOOBAD: + Beep(440, 111); + Beep(220, 111); + Beep(110, 167); + NoSound(); + break; + + case SND_S_O_S: + Beep(1000, 56); + Sleep(111); + Beep(1000, 56); + Sleep(111); + Beep(1000, 56); + Sleep(222); + Beep(1000, 167); + Sleep(167); + Beep(1000, 167); + Sleep(167); + Beep(1000, 167); + Sleep(222); + Beep(1000, 56); + Sleep(111); + Beep(1000, 56); + Sleep(111); + Beep(1000, 56); + NoSound(); + break; + } + } + return(type); +} + + +// ------------------------------------------------------------------ +// Play a file + +int GPlay::Play() const { + + switch(type) { + + case PLAY_DOS: + MakeNoise(effectno); + break; + + case PLAY_VOC: + if(not disablesound) { + #ifdef GOLD_SOUNDSUPPORT + if(snd) { + snd->load(AddPath(CFG->soundpath, file)); + snd->play(); + } + #endif + } + break; + } + + return 0; +} + + +// ------------------------------------------------------------------ +// Say a simple bibi + +void SayBibi() { + + if(CFG and CFG->switches.get(beepnoises)) + HandleGEvent(EVTT_SAYBIBI); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gepost.cpp b/golded3/gepost.cpp new file mode 100644 index 0000000..cb4fb5b --- /dev/null +++ b/golded3/gepost.cpp @@ -0,0 +1,1204 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Mega-functions to handle creation of msgs :-( +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +vector post_xparea; +uint position; +ulong msgcount = 0; + + +// ------------------------------------------------------------------ + +const char* get_subject_re_info(const char* s, ulong& n) { + + if(toupper(*s) == 'R' and tolower(s[1]) == 'e') { + + if(s[2] == ':') { + n = 1; + return s + 3; + } + else if(s[2] == '^' and isdigit(s[3])) { + const char* d = s + 4; + while(isdigit(*d)) + d++; + if(*d == ':') { + n = (ulong)atol(s + 3); + return d + 1; + } + } + } + + n = 0; + return NULL; +} + + +// ------------------------------------------------------------------ + +void CheckSubject(GMsg* msg, char* subj) { + + for(int n=0; nisnet()) { + if(EDIT->AutoAttach()) { + // If the subject was changed + if(not strieql(subj, msg->re)) { + // Check if the subj begins with drive spec + if(not (msg->attr.frq() or msg->attr.att() or msg->attr.urq())) { + char* ptr = subj; + if(*ptr == '^') + ptr++; + #ifdef __UNIX__ + if((*ptr == '/') and not strchr(ptr, ':')) { /* } */ + #else + if((in_range((char)tolower(*ptr), (char)'c', (char)'z') and (ptr[1] == ':')) or ((*ptr == '\\') and (ptr[1] == '\\'))) { + #endif + // Autoattach + msg->attr.att1(); + AttrAdd(&msg->attr, &CFG->attribsattach); + DispHeadAttrs(msg); + } + } + } + } + + if(msg->attr.frq()) { + // Handle File Requests + if(*subj) { + ISub buf; + strcpy(buf, subj); + char* ptr = strtok(buf, " "); + while(ptr) { + if(*ptr == '!') { // Store password + if(fspecs) + strcpy(fspec[fspecs-1].password, ptr); + } + else { + fspec = (FileSpec*)throw_realloc(fspec, (fspecs+1)*sizeof(FileSpec)); + memset(fspec+fspecs, 0, sizeof(FileSpec)); + fspec[fspecs].files = 1; + strcpy(fspec[fspecs].path, ptr); + specfiles++; + fspecs++; + } + ptr = strtok(NULL, " "); + } + } + } + else if(msg->attr.att()) { + // Handle File Attaching + ISub buf; + if(strblank(subj)) { + if(*CFG->attachpath) + strcpy(subj, CFG->attachpath); + else + strcpy(subj, CFG->goldpath); + } + strcpy(buf, subj); + char* ptr = strtok(buf, " "); + while(ptr) { + fspec = (FileSpec*)throw_realloc(fspec, (fspecs+1)*sizeof(FileSpec)); + memset(fspec+fspecs, 0, sizeof(FileSpec)); + if(*ptr == '^') { + fspec[fspecs].delsent = YES; + ptr++; + } + strcpy(fspec[fspecs].path, ptr); + FileSelect(msg, LNG->AttachFiles, &fspec[fspecs]); + specfiles += fspec[fspecs].files; + if(fspec[fspecs].files) + fspecs++; + ptr = strtok(NULL, " "); + } + } + else if(msg->attr.urq()) { + // Handle Update Requests + ISub buf; + if(not *subj) + strcpy(subj, "."); + strcpy(buf, subj); + char* ptr = strtok(buf, " "); + while(ptr) { + if(*ptr == '!') { // Store password + if(fspecs) + strcpy(fspec[fspecs-1].password, ptr); + } + else { + fspec = (FileSpec*)throw_realloc(fspec, (fspecs+1)*sizeof(FileSpec)); + memset(fspec+fspecs, 0, sizeof(FileSpec)); + strcpy(fspec[fspecs].path, ptr); + FileSelect(msg, LNG->UpdreqFiles, &fspec[fspecs]); + specfiles += fspec[fspecs].files; + if(fspec[fspecs].files) + fspecs++; + } + ptr = strtok(NULL, " "); + } + } + + // Generate the (first) processed subject line + if(specfiles) { + ISub buf; + *buf = NUL; + for(int x=0,n=0; x 71) { + n++; + break; + } + else + strcat(buf, subject); + } + if(n) + break; + } + strtrim(strcpy(subj, buf)); + } + } +} + + +// ------------------------------------------------------------------ + +static bool have_origin(GMsg *msg) { + + Line* line = msg->lin; + + while(line) + if(line->type & GLINE_ORIG) + return true; + else + line = line->next; + return false; +} + +// ------------------------------------------------------------------ + +static void MakeMsg3(int& mode, GMsg* msg) { + + int n; + vector::iterator u; + + msg->charsetlevel = 0; + if(*AA->Xlatexport()) { + msg->charsetlevel = LoadCharset(CFG->xlatlocalset, AA->Xlatexport()); + if(msg->charsetlevel) + sprintf(msg->charset, "%s %d", AA->Xlatexport(), msg->charsetlevel); + else + sprintf(msg->charset, "%s 2", CFG->xlatlocalset); + } + + // Do Timefields + if(msg->attr.fmu()) { + time_t a = time(NULL); + time_t b = mktime(gmtime(&a)); + a += a - b; + if(AA->isjam() or AA->iswildcat()) + msg->received = a; + else + msg->arrived = a; + } + + GMsg* carbon=NULL; + int cc = DoCarboncopy(msg, &carbon); + + if(AA->isecho() or have_origin(msg)) + DoTearorig(mode, msg); + + // Do FakeNets + msg->oorig = msg->orig; + if(AA->isnet() and msg->orig.point) { + for(u = CFG->aka.begin(); u != CFG->aka.end(); u++) { + if(not memcmp(u, &msg->orig, sizeof(Addr))) { + // Use fakenet to everybody + if(u->pointnet) { + msg->oorig.net = u->pointnet; // Create fake address + msg->oorig.node = msg->orig.point; + msg->oorig.point = 0; + } + break; + } + } + } + + DoKludges(mode, msg); + + if(cc) { + string temp; + update_statuslinef(LNG->StatusCC, msg->to, msg->dest.make_string(temp).c_str()); + } + + msg->LinesToText(); + + if(AA->isnet() and (msg->attr.frq() or msg->attr.att() or msg->attr.urq()) and specfiles >= 1) + CreateFileMsgs(mode, msg); + else { + HeaderView->Use(AA, msg); + HeaderView->Paint(); + + // Do zoneGating + if(AA->isnet() and CFG->zonegating and (msg->dest.zone != msg->orig.zone)) { + if(not (msg->attr.dir() or msg->attr.cra() or msg->attr.hld())) { + GMenuZonegate MenuZonegate; + if(CFG->zonegating == YES or MenuZonegate.Run()) + ZonegateIt(msg->odest, msg->orig, msg->dest); + } + } + + if(msg->odest.net == 0) + msg->odest = msg->dest; + + HeaderView->Use(AA, msg); + HeaderView->Paint(); + w_info(LNG->Wait); + AA->SaveMsg((mode == MODE_CHANGE) ? GMSG_UPDATE : GMSG_NEW, msg); + if(not (AA->isecho() and mode == MODE_REPLYCOMMENT)) + update_addressbook(msg); + w_info(NULL); + } + + if(AL.AreaEchoToNo(AA->Areayouwroteto())>=0) { + Area* A = AL.AreaEchoToPtr(AA->Areayouwroteto()); + if(AA != A and (mode != MODE_CHANGE)) { + char* back = NULL; + uint mlen = 0; + + msg->link.reset(); + char* ptr = msg->txt + (*msg->txt == CTRL_A); + if(not strnieql(ptr, "AREA:", 5)) { + uint elen = 6 + strlen(AA->echoid()) + 1; + mlen = strlen(msg->txt)+1; + msg->txt = (char*)throw_realloc(msg->txt, elen+mlen); + back = msg->txt+elen; + memmove(back, msg->txt, mlen); + strcpy(msg->txt, "\001AREA:"); + strcpy(msg->txt+6, AA->echoid()); + msg->txt[elen-1] = CR; + } + AA->Close(); + A->Open(); + ulong oldmsgno = msg->msgno; + A->NewMsgno(msg); + A->SaveMsg(GMSG_NEW|GMSG_NOLSTUPD, msg); + A->Close(); + AA->Open(); + if(back) + memmove(msg->txt, back, mlen); + msg->msgno = oldmsgno; + } + } + + if(cc) { + + Area* A = AA; + + if(AA->isecho()) { + AA = AL.AreaEchoToPtr(AA->Areareplyto()); + if(AA and (AA != A)) { + AA->Open(); + AA->RandomizeData(mode); + } + else + AA = A; + } + + for(n=0; ntxt = msg->txt; + cmsg->lin = msg->lin; + cmsg->line = msg->line; + cmsg->lines = msg->lines; + cmsg->messageid = msg->messageid; + cmsg->inreplyto = msg->inreplyto; + cmsg->references = msg->references; + AA->NewMsgno(cmsg); + { + string temp; + update_statuslinef(LNG->StatusCC, cmsg->to, cmsg->dest.make_string(temp).c_str()); + } + + // Do aka matching + if(AA->Akamatching()) { + int newaka = AkaMatch(&cmsg->orig, &cmsg->dest); + cmsg->orig = CFG->aka[newaka].addr; + } + + // Do FakeNets + cmsg->oorig = cmsg->orig; + if(AA->isnet() and cmsg->orig.point) { + for(u = CFG->aka.begin(); u != CFG->aka.end(); u++) { + if(not memcmp(u, &cmsg->orig, sizeof(Addr))) { + // Use fakenet to everybody + if(u->pointnet) { + cmsg->oorig.net = u->pointnet; // Create fake address + cmsg->oorig.node = cmsg->orig.point; + cmsg->oorig.point = 0; + } + break; + } + } + } + + // remove unnessesary To: line from message if present + for(Line* line = cmsg->lin; line; line = line->next) + if(line->text) { + if(strnieql(line->text, "To:", 3)) { + line = DeleteLine(line); + if(line and not line->text) + line = DeleteLine(line); + } + else if(line->type & GLINE_KLUDGE) + continue; + else + break; + } + else + break; + + DoKludges(mode, cmsg); + + if(have_origin(cmsg)) + DoTearorig(mode, cmsg); + + cmsg->LinesToText(); + msg->txt = cmsg->txt; + msg->lin = cmsg->lin; + msg->line = cmsg->line; + msg->lines = cmsg->lines; + msg->messageid = cmsg->messageid; + msg->inreplyto = cmsg->inreplyto; + msg->references = cmsg->references; + if(AA->isnet() and (cmsg->attr.frq() or cmsg->attr.att() or cmsg->attr.urq())) { + CreateFileMsgs(MODE_NEW, cmsg); + msg->txt = cmsg->txt; + msg->lin = cmsg->lin; + msg->line = cmsg->line; + msg->lines = cmsg->lines; + msg->messageid = cmsg->messageid; + msg->inreplyto = cmsg->inreplyto; + msg->references = cmsg->references; + } + else { + HeaderView->Use(AA, cmsg); + HeaderView->Paint(); + + // Do zoneGating + if(AA->isnet() and CFG->zonegating and (cmsg->dest.zone != cmsg->orig.zone)) { + if(not cmsg->attr.dir()) { + GMenuZonegate MenuZonegate; + if(CFG->zonegating == YES or MenuZonegate.Run()) + ZonegateIt(cmsg->odest, cmsg->orig, cmsg->dest); + } + } + + if(cmsg->odest.net == 0) + cmsg->odest = cmsg->dest; + + HeaderView->Use(AA, cmsg); + HeaderView->Paint(); + w_info(LNG->Wait); + AA->SaveMsg(GMSG_NEW, cmsg); + w_info(NULL); + update_addressbook(cmsg); + msg->txt = cmsg->txt; + msg->lin = cmsg->lin; + msg->line = cmsg->line; + msg->lines = cmsg->lines; + msg->messageid = cmsg->messageid; + msg->inreplyto = cmsg->inreplyto; + msg->references = cmsg->references; + } + } + throw_release(carbon); + + if(A != AA) { + AA->Close(); + AA = A; + AA->RandomizeData(); + } + AA->UpdateAreadata(); + } +} + + +// ------------------------------------------------------------------ + +static void MakeMsg2(int& mode, int& status, int& forwstat, int& topline, GMsg* msg, GMsg* oldmsg, GMsg* cmpmsg) { + + uint n; + char buf[256], buf2[256]; + Line* line; + Line* newline; + + if(status == MODE_CHANGE or (mode == MODE_FORWARD and status == MODE_SAVE)) { + if(mode == MODE_CHANGE) { + if(stricmp(msg->By(), AA->Username().name)) { + vector::iterator x; + for(n = 0, x = CFG->username.begin(); x != CFG->username.end(); n++, x++) { + if(strieql(x->name, msg->By())) { + n = 0; + break; + } + } + if(n) + status = MODE_SAVE; + } + } + w_info(LNG->Wait); + if(mode != MODE_CHANGE) { + if(not CFG->switches.get(emptytearline)) + strcpy(msg->tearline, AA->Tearline()); + + if(AA->Taglinesupport()) + strcpy(msg->tagline, AA->Tagline()); + + DoTearorig(mode, msg); + + strcpy(msg->organization, AA->Organization()); + } + if(mode != MODE_CHANGE or status == MODE_SAVE) { + if(TemplateToText(mode, msg, oldmsg, AA->Tpl(), OrigArea)) { + HeaderView->Use(AA, msg); + HeaderView->Paint(); + } + msg->attr.tou1(); // Ignore any kludge address found + msg->attr.pos1(); + msg->TextToLines(CFG->dispmargin-1); + msg->attr.tou0(); + msg->attr.pos0(); + } + uint lineno = position = reader_topline+1; + line = msg->lin; + while(line) { + if(not (line->type & GLINE_QUOT)) + if(line->type & GLINE_POSI) + position = lineno; + lineno++; + line = line->next; + } + if(*EDIT->External() and not EDIT->Internal()) { + SaveLines(MODE_SAVE, AddPath(CFG->goldpath, EDIT->File()), msg); + } + int loop = 0; + w_info(NULL); + do { + if(loop) { + status = MODE_SAVE; + forwstat = NO; + } + if(mode == MODE_FORWARD) + status = MODE_SAVE; + if(*EDIT->External() and forwstat == NO and not EDIT->Internal()) { + strcpy(buf, EDIT->External()); + sprintf(buf2, "%u", position); + strischg(buf, "@line", buf2); + strcpy(buf2, AddPath(CFG->goldpath, EDIT->File())); + strchg(buf2, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); + strischg(buf, "@file", buf2); + long ftbefore = GetFiletime(AddPath(CFG->goldpath, EDIT->File())); + sprintf(buf2, LNG->EditCmd, buf); + ShellToDos(buf, buf2, LGREY|_BLACK, YES); + long ftafter = GetFiletime(AddPath(CFG->goldpath, EDIT->File())); + if(status != MODE_SAVE) { + status = MODE_SAVE; + if(ftbefore == ftafter) { + if(streql(msg->by, cmpmsg->by)) + if(streql(msg->to, cmpmsg->to)) + if(streql(msg->re, cmpmsg->re)) + if(not memcmp(&msg->attr, &cmpmsg->attr, sizeof(Attr))) + status = MODE_QUIT; + } + } + } + else if(forwstat == NO and (EDIT->Internal() or not *EDIT->External())) { + w_info(LNG->Wait); + status = MODE_SAVE; + newline = line = msg->lin; + while(line) { + newline = line; + if(((line->type & GLINE_HIDD) and not AA->Viewhidden()) or ((line->type & GLINE_KLUD) and not AA->Viewkludge())) + newline = line = DeleteLine(line); + else { + strtrim(line->text); + if(line->type & GLINE_HARD) + strcat(line->text, "\n"); + else + strcat(line->text, " "); + line = line->next; + } + } + msg->lin = FirstLine(newline); + + w_info(NULL); + if(position) + position--; + if(not savedirect) + status = EditMsg(mode, &position, msg); + _in_editor = NO; + w_info(LNG->Wait); + + if(status != MODE_QUIT) { + line = msg->lin; + while(line) { + if(line->text) { + if(strchr(line->text, LF)) + line->type = GLINE_HARD; + else if(line->next and (line->next->type & GLINE_QUOT)) + line->type = GLINE_HARD; + else + line->type = 0; + strtrim(line->text); + if(AA->isinternet()) { + // Check for signature indicator + if(streql(line->text, "--")) { + if(line->isallocated()) + throw_free(line->text); + line->text = throw_strdup("-- "); + line->type = GLINE_HARD; + } + } + } + line = line->next; + } + LoadCharset("N/A", "N/A"); + strcpy(stpcpy(msg->charset, CFG->xlatlocalset), " 2"); + msg->charsetlevel = 2; + msg->LinesToText(); + } + w_info(NULL); + } + if(status == MODE_SAVE) { + + if(*EDIT->External() and not EDIT->Internal()) + LoadText(msg, AddPath(CFG->goldpath, EDIT->File())); + if(mode == MODE_FORWARD) + msg->attr.pos1(); + msg->attr.tou1(); // ignore any kludge address found + msg->TextToLines(CFG->dispmargin-1); + msg->attr.tou0(); + msg->attr.pos0(); + + MsgLineReIndex(msg); + + if(not savedirect) { + HeaderView->Use(AA, msg); + HeaderView->Paint(); + BodyView->Use(AA, msg, topline); + BodyView->Paint(); + do { + if(gkbd.quitall) + status = MODE_SAVE; + else { + GMenuEditfile MenuEditfile; + status = MenuEditfile.Run(msg); + } + if(status == MODE_VIEW) { + BodyView->Use(AA, msg, topline); + BodyView->Paint(); + ViewMessage(); + } + } while(status == MODE_VIEW); + } + + InvalidateControlInfo(msg); + + if(status == MODE_SAVE) + DoCrosspost(msg, post_xparea); + } + loop++; + if(status == MODE_CHANGE) { + _in_editor = YES; + HeaderView->Use(AA, msg); + HeaderView->Paint(); + } + } while(status == MODE_CHANGE); + } +} + + +// ------------------------------------------------------------------ + +static void GetLastLink(GMsg* msg, ulong& msgno) { + + GMsg* uplink = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + uplink->msgno = msg->msgno; + uplink->link.first_set(msg->link.first()); + + if(uplink->link.first()) { + while(AA->Msgn.ToReln(uplink->link.first())) { + if(not AA->LoadHdr(uplink, uplink->link.first())) + uplink->msgno = 0; + } + } + + // Return msgno of the last link + msgno = uplink->msgno; + + ResetMsg(uplink); + throw_free(uplink); +} + + +// ------------------------------------------------------------------ + +void MakeMsg(int mode, GMsg* omsg) { + + GFTRK("MakeMsg"); + + // Tell DispHeader not to show msg size + _in_editor = YES; + + // Allocate some msgs + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + GMsg* reply = (GMsg*)throw_calloc(1, sizeof(GMsg)); + GMsg* cmpmsg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + ulong reply_msgno = 0; + + // Keep copy of original aka for later restoration + Addr origaka = AL.AreaIdToPtr(OrigArea)->aka(); + + // Force template choice if necessary + if(AA->Forcetemplate() and (mode != MODE_CHANGE)) + ChangeTemplate(); + + // Random System + AA->RandomizeData(); + + // Prepare confirmation receipts + int confirm = NO; + if(mode == MODE_CONFIRM) { + confirm = YES; + mode = MODE_REPLY; + } + + // Prepare crossposting + int crosspost = NO; + post_xparea.clear(); + + do { + if(post_xparea.size()) { + mode = MODE_COPY; + AL.SetActiveAreaNo(post_xparea.back()); + if(CurrArea != OrigArea) { + AA->Open(); + AA->RandomizeData(mode); + } + + msg->attr.tou0(); + msg->TextToLines(CFG->dispmargin-1); + msg->orig = AA->Aka().addr; + msg->charsetlevel = LoadCharset(CFG->xlatlocalset, AA->Xlatexport()); + if(msg->charsetlevel!=0 and CharTable and not strblank(CharTable->exp)) + strcpy(msg->charset, CharTable->exp); + strcpy(msg->odom, CFG->aka[AkaMatch(&msg->orig, &AA->Aka().addr)].domain); + if(AA->isecho() or have_origin(msg)) + DoTearorig(mode, msg); + DoKludges(mode, msg); + msg->LinesToText(); + post_xparea.pop_back(); + } + + int status = MODE_SAVE; + int hardlines = EDIT->HardLines(); + int topline = 0; + fspecs = specfiles = 0; + fspec = (FileSpec*)throw_realloc(fspec, sizeof(FileSpec)); + memset(fspec, 0, sizeof(FileSpec)); + + // Get msg number and reset/copy msg data + if(mode != MODE_COPY) + ResetMsg(msg); + switch(mode) { + case MODE_FORWARD: + memcpy(msg, omsg, sizeof(GMsg)); + msg->txt = (char*)throw_strdup(msg->txt); + msg->lin = NULL; + msg->line = NULL; + msg->messageid = NULL; + msg->inreplyto = NULL; + msg->references = NULL; + msg->attr.tou0(); + msg->TextToLines(CFG->dispmargin-1, false); + *msg->iorig = NUL; + *msg->idest = NUL; + *msg->ireplyto = NUL; + *msg->iaddr = NUL; + *msg->igate = NUL; + *msg->ifrom = NUL; + *msg->ito = NUL; + *msg->organization = NUL; + *msg->realby = NUL; + *msg->realto = NUL; + *msg->origin = NUL; + // Drop through ... + case MODE_COPY: + AA->NewMsgno(msg); + msg->link.reset(); + break; + case MODE_CHANGE: + memcpy(msg, omsg, sizeof(GMsg)); + msg->txt = (char*)throw_strdup(msg->txt); + msg->lin = NULL; + msg->line = NULL; + msg->messageid = NULL; + msg->inreplyto = NULL; + msg->references = NULL; + msg->attr.tou0(); + msg->TextToLines(CFG->dispmargin-1, false); + break; + case MODE_NEW: + wfill(MINROW, 0, MAXROW-2, MAXCOL-1, ' ', C_READW); + case MODE_QUOTE: + case MODE_REPLY: + case MODE_REPLYCOMMENT: + AA->NewMsgno(msg); + msg->timesread = 1; + } + + msg->oorig = msg->orig; + msg->board = AA->board(); + msg->odest = msg->dest; + + if(mode != MODE_COPY) { + + // Set msg date and time + bool dochgdate = true; + if(mode == MODE_CHANGE) { + dochgdate = EDIT->ChangeDate(); + if(dochgdate and not msg->attr.fmu()) + dochgdate = false; + } + if(dochgdate) { + time_t a = time(NULL); + time_t b = mktime(gmtime(&a)); + a += a - b; + msg->received = msg->arrived = msg->written = a; + } + + // Prepare msg header + + if(mode != MODE_CHANGE) + msg->attr = AA->Attributes(); // Set default attributes + + switch(mode) { + case MODE_QUOTE: + case MODE_REPLYCOMMENT: + omsg->attr.tou0(); + omsg->TextToLines(-CFG->quotemargin, false); + if(omsg->attr.rot()) + Rot13(omsg); + // Drop through + case MODE_REPLY: + if(confirm) + msg->attr = CFG->attribscfm; + if(omsg->attr.pvt() & !AA->isecho()) + msg->attr.pvt1(); // Set Pvt attr in response to Pvt in orig + if(omsg->attr.frq() and (mode == MODE_REPLY) and (not confirm)) { + msg->attr = CFG->attribsfrq; + msg->attr.frq1(); // Special case for the file request function + } + + // Change header data if replying to a forwarded message + if((mode == MODE_REPLYCOMMENT) and omsg->fwdorig.net) { + strcpy(omsg->by, omsg->fwdfrom); + strcpy(omsg->realby, omsg->fwdfrom); + omsg->oorig = omsg->orig = omsg->fwdorig; + strcpy(omsg->to, omsg->fwdto); + strcpy(omsg->realto, omsg->fwdto); + omsg->odest = omsg->dest = omsg->fwddest; + strcpy(omsg->re, omsg->fwdsubj); + *omsg->ireplyto = *omsg->iorig = NUL; + } + + // Do aka matching + { + if(AA->Akamatching()) { + // ... but only if we did NOT change aka manually + if(AA->Aka().addr.equals(AA->aka())) { + Addr aka_addr = AA->Aka().addr; + AkaMatch(&aka_addr, &omsg->orig); + AA->SetAka(aka_addr); + } + } + } + + if((mode == MODE_REPLYCOMMENT) and not omsg->fwdorig.net) { + strcpy(msg->to, omsg->to); + strcpy(msg->realto, omsg->realto); + msg->dest = omsg->dest; + strcpy(msg->idest, omsg->idest); + } + else { + strcpy(msg->to, omsg->By()); + strcpy(msg->realto, omsg->realby); + msg->dest = omsg->orig; + strcpy(msg->idest, *omsg->ireplyto ? omsg->ireplyto : omsg->iorig); + } + strcpy(msg->re, omsg->re); + + if(AA->Replyre() or AA->isinternet()) { + + ulong number; + const char* r = get_subject_re_info(msg->re, number); + if(r) { + if(AA->Replyre() == REPLYRE_NUMERIC and not AA->isinternet()) { + ISub subj; + sprintf(subj, "Re^%lu:%s", ((number+1) > number) ? (number+1) : number, r); + strcpy(msg->re, subj); + } + } + else if(not msg->attr.frq() and not msg->attr.urq()) { + memmove(msg->re+4, msg->re, sizeof(ISub)-5); + memmove(msg->re, "Re: ", 4); + } + } + else { + char* r; + ulong number; + char* ptr = msg->re; + do { + r = (char*)get_subject_re_info(ptr, number); + if(r) + ptr = strskip_wht(r); + } while(r); + strcpy(msg->re, ptr); + } + strcpy(msg->ddom, omsg->odom); + if((mode == MODE_REPLYCOMMENT) and omsg->fwdorig.net) + strcpy(msg->replys, omsg->fwdmsgid); + else + strcpy(msg->replys, omsg->msgids); + if(AA->isnet()) { + if(omsg->messageid) { + throw_free(msg->inreplyto); + msg->inreplyto = throw_strdup(omsg->messageid); + } + if(CFG->switches.get(internetreply) or (*omsg->iaddr and (strlen(omsg->iaddr) >= sizeof(Name)))) { + strcpy(msg->iaddr, omsg->iaddr); + strcpy(msg->igate, omsg->igate); + if(*msg->igate) { + msg->dest.set(msg->igate); + char* ptr = strchr(msg->igate, ' '); + if(ptr) { + strcpy(msg->realto, msg->to); + strcpy(msg->to, strskip_wht(ptr)); + } + } + } + else if(*omsg->iaddr and (strlen(omsg->iaddr) < sizeof(Name))) { + strcpy(msg->realto, msg->to); + strcpy(msg->to, omsg->iaddr); + } + } + else { + int reflen = omsg->references ? strlen(omsg->references) : 0; + int midlen = omsg->messageid ? strlen(omsg->messageid) : 0; + msg->references = (char*)throw_calloc(1, reflen+1+midlen+1); + if(omsg->references) + strcpy(msg->references, omsg->references); + if(omsg->messageid) { + if(reflen) + strcat(msg->references, " "); + strcat(msg->references, omsg->messageid); + } + if(*msg->references == NUL) + throw_release(msg->references); + } + if(CurrArea == OrigArea) { + if((CFG->replylink == REPLYLINK_DIRECT) or AA->isjam()) + reply_msgno = omsg->msgno; + else if(CFG->replylink == REPLYLINK_CHAIN) + GetLastLink(omsg, reply_msgno); + msg->link.to_set(reply_msgno); + if(msg->link.to() == omsg->msgno) + omsg->link.first_set(msg->msgno); + } + + /////////// + /////////// Drop through + /////////// + + case MODE_FORWARD: + if(mode == MODE_FORWARD) { + if(msg->fwdorig.net == 0) { + strcpy(msg->fwdfrom, msg->By()); + msg->fwdorig = msg->orig; + strcpy(msg->fwdto, msg->To()); + msg->fwddest = msg->dest; + strxcpy(msg->fwdsubj, msg->re, sizeof(msg->fwdsubj)); + Area* fwdarea = AL.AreaIdToPtr(OrigArea); + strcpy(msg->fwdarea, fwdarea->isecho() ? fwdarea->echoid() : ""); + strcpy(msg->fwdmsgid, msg->msgids); + } + } + + /////////// + /////////// Drop through + /////////// + + case MODE_NEW: + strcpy(msg->by, AA->Username().name); + msg->attr.nwm1(); + if(not AA->islocal()) + msg->attr.uns1(); + strcpy(msg->odom, CFG->aka[AkaMatch(&msg->orig, &AA->Aka().addr)].domain); + break; + + case MODE_CHANGE: + if(not AA->islocal()) + msg->attr.uns1(); + msg->attr.snt0(); + msg->attr.rcv0(); + break; + } + + // Get random items + + switch(mode) { + case MODE_NEW: + case MODE_FORWARD: + *msg->replys = NUL; + throw_release(msg->references); + throw_release(msg->inreplyto); + if(AA->isnet()) { + strcpy(msg->to, ""); + msg->dest.reset_fast(); + msg->odest.reset_fast(); + } + if(not AA->isnet() or (AA->isemail() and strchr(AA->Whoto(), '@'))) + strcpy(msg->to, AA->Whoto()); + + /////// + /////// Drop through + /////// + + case MODE_REPLYCOMMENT: + case MODE_QUOTE: + case MODE_REPLY: + case MODE_CHANGE: + AA->RandomizeData(mode); + if(mode != MODE_CHANGE) { + msg->orig = AA->Aka().addr; + if(AA->isinternet()) + strcpy(msg->iorig, AA->Internetaddress()); + if(not strblank(AA->Username().name)) + strcpy(msg->by, AA->Username().name); + if(CFG->switches.get(emptytearline)) + *msg->tearline = NUL; + } + break; + } + + int forwstat = NO; + if(msg->odest.net == 0) + msg->odest = msg->dest; + status = NO; + if(not confirm) { + strcpy(cmpmsg->by, msg->by); + strcpy(cmpmsg->to, msg->to); + strcpy(cmpmsg->re, msg->re); + cmpmsg->attr = msg->attr; + if(savedirect) { + CheckSubject(msg, msg->re); + } + else { + GMenuEditHeader MenuEditHeader; + while((status = MenuEditHeader.Run(mode, msg)) == YES); + } + } + + if(status == NO) { + if(mode == MODE_CHANGE or mode == MODE_FORWARD) { + status = MODE_SAVE; + if(mode == MODE_FORWARD) + forwstat = YES; + } + else { + if(confirm) { + throw_release(msg->txt); + FILE* fp = fsopen(AddPath(CFG->goldpath, CFG->confirmfile), "rt", CFG->sharemode); + if(fp) { + LoadText(msg, AddPath(CFG->goldpath, CFG->confirmfile)); + fclose(fp); + } + if(msg->txt == NULL) + msg->txt = throw_strdup("\r\rConfirmation Receipt\r\r"); + TokenXlat(mode, msg->txt, msg, omsg, CurrArea); + } + else + CreateFileAddr(msg); + msg->TextToLines(CFG->dispmargin-1); + status = MODE_SAVE; + } + } + MakeMsg2(mode, status, forwstat, topline, msg, omsg, cmpmsg); + } + + if(status != MODE_SAVE) { + post_xparea.clear(); + crosspost = NO; + } + + if(status == MODE_SAVE) { + + if(*msg->iorig and (strlen(msg->iorig) < sizeof(Name))) { + strcpy(msg->realby, msg->by); + strcpy(msg->by, msg->iorig); + } + + if(mode == MODE_COPY) + AA->SaveMsg(GMSG_NEW, msg); + else + MakeMsg3(mode, msg); + + // If message is a reply, update the links on the original + if(CurrArea == OrigArea and (mode == MODE_QUOTE or mode == MODE_REPLYCOMMENT or mode == MODE_REPLY)) { + if(AA->Msgn.ToReln(reply_msgno)) { + if(AA->LoadHdr(reply, reply_msgno)) { + ulong replynext; + bool ok2save = false; + if(AA->issquish()) { + if(reply->link.first()) { + for(int r=0; rlink.list_max()-1; r++) { + if(reply->link.list(r) == 0) { + reply->link.list_set(r, msg->msgno); + ok2save = true; + break; + } + } + } + else { + reply->link.first_set(msg->msgno); + ok2save = true; + } + } + else if(AA->isjam()) { + if(reply->link.first()) { + replynext = reply->link.first(); + do { + reply_msgno = replynext; + if(not AA->LoadHdr(reply, reply_msgno)) + break; + replynext = reply->link.next(); + } while(reply->link.next()); + if(reply->link.next() == 0) { + reply->link.next_set(msg->msgno); + ok2save = true; + } + } + else { + reply->link.first_set(msg->msgno); + ok2save = true; + } + } + else { + reply->link.first_set(msg->msgno); + ok2save = true; + } + if(ok2save) { + reply->pcboard.reply_written = msg->written; + AA->SaveHdr(GMSG_UPDATE, reply); + } + } + } + } + + // Ask if the original msg should be deleted while we're at it + if(CurrArea == OrigArea and CFG->switches.get(askdelorig) and not confirm) { + switch(mode) { + case MODE_REPLY: + case MODE_QUOTE: + case MODE_REPLYCOMMENT: + if(not AA->isecho()) { + topline = 0; + omsg->TextToLines(CFG->dispmargin-1); + if(omsg->attr.rot()) + Rot13(omsg); + HeaderView->Use(AA, omsg); + HeaderView->Paint(); + BodyView->Use(AA, omsg, topline); + BodyView->Paint(); + GMenuDelorig MenuDelorig; + if(MenuDelorig.Run()) { + AA->Mark.Del(omsg->msgno); + AA->PMrk.Del(omsg->msgno); + AA->DeleteMsg(omsg, DIR_PREV); + } + } + break; + } + } + } + + if(CurrArea != OrigArea) { + AA->UpdateAreadata(); + AA->Close(); + AL.SetActiveAreaId(OrigArea); + AA->RandomizeData(); + } + AA->UpdateAreadata(); + EDIT->HardLines(hardlines); + for(int n=0; nCrossposting, AL[post_xparea.back()]->echoid()); + } while(post_xparea.size()); + + _in_editor = NO; + + // Restore original aka + AA->SetAka(origaka); + + ResetMsg(omsg); + ResetMsg(cmpmsg); + ResetMsg(reply); + ResetMsg(msg); + + throw_free(cmpmsg); + throw_free(reply); + throw_free(msg); + + LoadLanguage(AA->Loadlanguage()); + + GFTRK(NULL); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/geprot.h b/golded3/geprot.h new file mode 100644 index 0000000..5511c57 --- /dev/null +++ b/golded3/geprot.h @@ -0,0 +1,449 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Collective header for GE*.CPP source files. +// ------------------------------------------------------------------ + + +#ifndef __GEHDRS_H +#define __GEHDRS_H + + +// ------------------------------------------------------------------ +// GCAREA prototypes + +void FixEchoid(char* echoid, int type); + + +// ------------------------------------------------------------------ +// GCCFGG prototypes + +void CfgAddress(char* value); +void CfgAddressmacro(char* value); +void CfgEvent(char* value); +void CfgFrqext(const char* value); +void CfgRobotname(const char* value); +void CfgUsername(char* value); + +int SwitchCfgAtoG(word crc, char* val); +int SwitchCfgHtoZ(word crc, char* val); + +int ReadGoldCfg(int force); +bool ReadGoldedCfg(int& force); +void WriteGoldGed(); + +void InstallDetect(char* path); +int InstallFinish(); + + +// ------------------------------------------------------------------ +// GCKEYS prototypes + +int ReadKeysCfg(int force); +void KeyCmdAdd(gkey cmd, gkey val, int type); +void RunMacro(Macro* m); + + +// ------------------------------------------------------------------ +// GCLANG prototypes + +void LangInit(); +bool ReadLangCfg(int force); +void LoadLanguage(const char* file); + + +// ------------------------------------------------------------------ +// GCMISC prototypes + +int ReadHelpCfg(int force); +int GetColor(char* ink); +int MakeColor(char* colors); +void GetColors(char* value); +void ReadXlatTables(); + + +// ------------------------------------------------------------------ +// GEAREA prototypes + +int AreaPick(char* title, int wpos, int* idx); +void a_closeall(); +void GetAreaconf(); + + +// ------------------------------------------------------------------ +// GECTRL prototypes + +char* MakeOrigin(GMsg* msg, const char* _origin); +char* MakeTearline(GMsg* msg, char* buf); +void DoKludges(int mode, GMsg* msg, bool attronly = false); +void DoTearorig(int mode, GMsg* msg); +void GetRandom(int mode, GMsg* msg); +char* GetRandomLine(char* __buf, size_t __bufsize, const char* __file); +char* HandleRandomLine(char* buf, size_t bufsize); +char* get_informative_string(char* buf); + + +// ------------------------------------------------------------------ +// GEDOIT prototypes + +void CmfMsgs(GMsg* msg); +void LoadText(GMsg* msg, const char* textfile); +void SaveLines(int mode, const char* savefile, GMsg* msg, bool clip=false); +void WriteMsgs(GMsg* msg); + + +// ------------------------------------------------------------------ +// GEDOSS prototypes + +void Cleanup(void); +int ShellToDos(char* command, char* message, int cls, int cursor, int swap=YES, int pause=NO); + + +// ------------------------------------------------------------------ +// GEEDIT prototypes + +int EditMsg(int mode, uint* position, GMsg* msg); +void FreePastebuf(); + + +// ------------------------------------------------------------------ +// GEFILE prototypes + +void CreateFileAddr(GMsg* msg); +void CreateFileMsgs(int mode, GMsg* msg); +void FileSelect(GMsg* msg, char* title, FileSpec* fspec); + + +// ------------------------------------------------------------------ +// GEFIND prototypes + +bool FindString(GMsg* msg, const char* prompt, int what); +void FindAll(GMsg* msg, int& topline, int& keyok); +void FindHdr(GMsg* msg, int& topline, int& keyok); +bool SearchHighlight(const Line* line, int row, int width, int highlight_color); +void SearchExit(); +void AdvancedSearch(GMsg* msg, int& topline, int& keyok); + + +// ------------------------------------------------------------------ +// GEGLOB prototypes + +void CfgInit(); +void CfgInit2(); +int PlayMacro(gkey key, int type); +int IsMacro(gkey key, int type); + + +// ------------------------------------------------------------------ +// GEINIT prototypes + +void Initialize(int argc, char* argv[]); + + +// ------------------------------------------------------------------ +// GELINE prototypes + +int LoadCharset(const char* imp, const char* exp, int query = 0); +Line* AddKludge(Line* line, char* buf, int where=DIR_BELOW); +Line* AddLineFast(Line* line, char* text); +Line* DeleteLine(Line* line); +Line* FirstLine(Line* line); +Line* InsertLine(Line* newline, Line* oldline, int pos); +Line* LastLine(Line* line); +void MakeLineIndex(GMsg* msg, int rmargin, bool header_recode = true); +void MsgLineReIndex(GMsg* msg, int viewhidden=-1, int viewkludge=-1, int viewquote=-1); +char* XlatStr(char* dest, char* src, int level, Chs* chrtbl, int qpencoded=false, bool i51=false); +char* mime_header_decode(char* decoded, const char* encoded, char* charset = NULL); +char* strxmimecpy(char* dest, const char* source, int level, int size, bool detect = false); +void InvalidateControlInfo(GMsg *msg); + + +// ------------------------------------------------------------------ +// GEMENU prototypes + +void DispHeadAttrs(GMsg* msg); +void AskAttributes(GMsg* msg); +void ChgAttrs(int mode, GMsg* msg); +int ChangeAka(); +int ChangeCharsIn(); +int ChangeCharsOut(); +int ChangeTagline(); +int ChangeOrigin(); +int ChangeTemplate(); +int ChangeUsername(); +int ChangeXlatImport(); + + +// ------------------------------------------------------------------ +// GEMLST prototypes + +uint MsgBrowser(GMsg* msg); +void MsgThreadlist(); + + +// ------------------------------------------------------------------ +// GEMRKS prototypes + +void MarkMsgs(GMsg* msg); +int NextMarkedmsg(int direction, GMsg* msg); + + +// ------------------------------------------------------------------ +// GEMSGS prototypes + +char* TokenXlat(int mode, char* input, GMsg* msg, GMsg* oldmsg, int origarea); +void Rot13(GMsg* msg); +void ResetMsg(GMsg* msg); +int DoCarboncopy(GMsg* msg, GMsg** carbon); +void DoCrosspost(GMsg* msg, vector &postareas); +char* ParseInternetAddr(char* __string, char* __name, char* __addr); + + +// ------------------------------------------------------------------ +// GENODE prototypes + +void Lookup(GMsg* msg, ftn_addr* addr, char* name, int topline, char* status); +bool Lookup2(Addr& addr, char* name, int topline, const char* status); + +const char *lookup_nodelist(ftn_addr* addr); + +void LookupNode(GMsg* msg, char* name, int what); +void CheckNodelists(); + + +// ------------------------------------------------------------------ +// GEPLAY prototypes + +void InitSound(); +void FileToGPlay(GPlay* playbuf, char* filename); +int HandleGEvent(uint event); +int MakeNoise(int type); +void SayBibi(); + + +// ------------------------------------------------------------------ +// GEHDRE prototypes + +typedef struct { + char *buf; + bool update; +} gsetaddr; + +bool set_to_address(GMsg* msg, gsetaddr* toname, gsetaddr* toaddr, gsetaddr* fromaddr, gsetaddr* subj, int pos, char* lng_lookup, bool lookup=true); + + +// ------------------------------------------------------------------ +// GEPOST prototypes + +void MakeMsg(int mode, GMsg* oldmsg); +int EditHeaderinfo(int mode, GMsgHeaderView &view); +void CheckSubject(GMsg* msg, char* subj); + + +// ------------------------------------------------------------------ +// GEQWKS prototypes + +int ImportQWK(); +int ExportQWK(); + + +// ------------------------------------------------------------------ +// GEREAD prototypes + +char* GetCurrQuotebuf(char* quotebuf); +int MsgIsTwit(GMsg* msg, bool& istwitto, bool& istwitsubj); +ulong MsgHasReplies(GMsg* msg); +gkey ViewMessage(int istwit=NOT_TWIT); +int LoadMessage(GMsg* msg, int margin); +void DispHeader(GMsg* msg, bool prn, FILE* fp=NULL, int width=-1); +void LoadRawMsg(GMsg* msg, int margin); + +void make_pathreport(char* reportfile); +void NextArea(); +void PrevArea(); +void Reader(); +void UpdateArea(GMsg* msg); +int ExternUtil(GMsg* __msg, int __utilno); +void ExternUtilMenu(); +uint next_msg(int direction); + +void ChangeAttributes(); +void ChangeMsg(); +void CommentMsg(); +void ConfirmMsg(); +void CopyMoveForward(); +void DecMargin(); +void DosShell(); +void ExitAsk(); +void FileRequest(GMsg* __msg); +void GotoBookMark(); +void GotoFirstMsg(); +void GotoLastMsg(); +void GotoMsgno(); +void GotoNextMsg(); +void GotoPrevMsg(); +void GotoNextUnread(); +void GotoPrevUnread(); +void GotoReplies(); +void GotoReply1st(); +void GotoReplyNext(); +void GotoReplyPrev(); +void IncMargin(); +void MakeUserList(); +void MakePathreport(); +void MarkingOptions(); +void MessageBrowse(); +void NewArea(bool jumpnext = false); +void NewMsg(); +void OtherAreaQuoteMsg(); +void OtherAreaCommentMsg(); +void QuitNow(); +void QuoteBuf(GMsg* msg); +void QuoteMsg(); +void RenumberArea(); +void ReplyMsg(); +void ToggleBookMark(); +void ToggleHidden(); +void ToggleHiddKlud(); +void ToggleKludge(); +void ToggleMark(); +void ToggleMarkRead(); +void TogglePageBar(); +void ToggleQuote(); +void ToggleRealMsgno(); +void ToggleROT13(); +void ToggleTwits(); +void ToggleStyles(); +void ToggleXlat(); +void TouchNetscan(int __popup=true); +void UUDecode(GMsg* msg); +void WriteMsg(GMsg* msg); +void TouchSemaphore(); + + +// ------------------------------------------------------------------ +// GESCAN prototypes + +void CheckSemaphores(); + + +// ------------------------------------------------------------------ +// GESOUP prototypes + +char* CvtMSGIDtoMessageID(char* midbuf, char* msgid, ftn_addr* addr, char* domain, char* from, char* to, char* subject, struct tm* datetime); +char* CvtMessageIDtoMSGID(char* mptr, char* msgidbuf, const char* echoid, char* kludge); + +int ImportSOUP(); +int ExportSOUP(); + + +// ------------------------------------------------------------------ +// GETPLS prototypes + +void CookieIndex(char* textfile, char* indexfile); +int TemplateToText(int mode, GMsg* msg, GMsg* oldmsg, const char* tpl, int origarea); +bool is_user(const char* name); + + +// ------------------------------------------------------------------ +// GEUTIL prototypes + +void ScreenBlankIdle(); +void IdleCheckSemaphores(); +int AkaMatch(ftn_addr* __match, const ftn_addr* __addr); +void call_help(); +void CheckTick(gkey quitkey); +char* CvtName(char* inp); +int edit_string(char* buf, int buf_size, char* title, int helpcat); +bool edit_pathname(char* buf, int buf_size, char* title, int helpcat); +int GetAkaNo(const ftn_addr& __aka); +int GetQuotestr(const char* ptr, char* qbuf, uint* qlen); +int is_quote(const char* ptr); +int IsQuoteChar(const char* s); +void maketitle(); +void ProgMeter(int mode, int xx, int yy, long len, long barlen, int attr, long pos, long size); +int ReadCfg(const char* cfg, int ignoreunknown=false); +void ScanMsgTxtForAddr(GMsg* msg); +gkey SearchKey(gkey key, list::iterator keys, int totkeys); +int SearchTaglist(Echo* taglist, char* tag); +void set_title(const char* t, int p, int a); +char* strconv(char* str, char* conv); +void title_shadow(); +void update_statusline(const char* info); +void update_statuslinef(const char* format, ...) __attribute__ ((format (printf, 1, 2))); +void update_statuslines(); +void w_info(const char* info=NULL); +void w_infof(const char* format, ...) __attribute__ ((format (printf, 1, 2))); +void w_progress(int mode, int attr, long pos, long size, const char* title); +void w_shadow(); +void ZonegateIt(ftn_addr& gate, ftn_addr& orig, ftn_addr& dest); +char* strtmp(const char* str); +int quotecolor(const char* line); +void doinvalidate(char* text, const char* find, const char* replace, bool is_tearline = false); + + +// ------------------------------------------------------------------ +// GEUSRBSE prototypes + +bool lookup_addressbook(GMsg* msg, char* name, char* aka, bool browser = false); +void build_pseudo(GMsg* msg, bool direction = true); +void update_addressbook(GMsg* msg, bool reverse = false, bool force = false); +void edit_addressbook(GMsg* msg); + + +// ------------------------------------------------------------------ +// SOFTCR management + +inline bool issoftcr(char c) { + return (c == SOFTCR) and not CFG->switches.get(dispsoftcr); +} + + +inline char *spanspaces(const char *str) { + if(CFG->switches.get(dispsoftcr)) + while(isspace(*str)) + str++; + else + while(isspace(*str) or (*str == SOFTCR)) + str++; + return (char *)str; +} + + +inline char *spanfeeds(const char *str) { + if(CFG->switches.get(dispsoftcr)) + while(*str == LF) + str++; + else + while((*str == LF) or (*str == SOFTCR)) + str++; + return (char *)str; +} + + +// ------------------------------------------------------------------ + +#endif + +// ------------------------------------------------------------------ + diff --git a/golded3/geqwks.cpp b/golded3/geqwks.cpp new file mode 100644 index 0000000..77ab42d --- /dev/null +++ b/golded3/geqwks.cpp @@ -0,0 +1,943 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// QWK packet handling. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +static void ReadGldFile() { + + if(QWK->FoundBBS()) { + + gfile fp; + Path gldfile; + + QWK->ResetConfNo(); + + sprintf(gldfile, "%s%s.GLD", CFG->goldpath, QWK->BbsID()); + fp.fopen(gldfile, "rt"); + if(fp.isopen()) { + char* key; + char* val; + char buf[256]; + while(fp.fgets(buf, sizeof(buf))) { + val = strtrim(buf); + getkeyval(&key, &val); + strtrim(StripQuotes(val)); + if(QWK->FindEcho(val)) + QWK->ConfNo(atoi(key)); + } + fp.fclose(); + } + } +} + + +// ------------------------------------------------------------------ + +int ImportQWK() { + + if(not *QWK->ImportPath()) + return 0; + + gfile fp; + gfile fpb; // For BBSID.GLD + Path file; + Path gldfile; + char bbsid[9] = {""}; + + // Parse the control file + strcpy(file, AddPath(QWK->ImportPath(), "CONTROL.DAT")); + fp.fopen(file, "rt"); + if(fp.isopen()) { + char buf[256]; + int line = 0; + int confno = 0; + int confcnt = 0; + int confnos = 0; + while(fp.fgets(buf, sizeof(buf))) { + + line++; + strtrim(buf); + + if((line >= 12) and (confcnt < confnos)) { + if(line % 2) { + if(fpb.isopen()) + fpb.printf("%u \"%s\"\n", confno, buf); + confcnt++; + } + else + confno = atoi(buf); + } + else if(line == 5) { + char* ptr = strchr(buf, ','); + if(ptr) { + strxcpy(bbsid, strskip_wht(ptr+1), 9); + sprintf(gldfile, "%s%s.GLD", CFG->goldpath, bbsid); + fpb.fopen(gldfile, "wt"); + } + } + else if(line == 11) + confnos = atoi(buf) + 1; + } + if(fpb.isopen()) + fpb.fclose(); + fp.fclose(); + remove(file); + } + + if(strblank(bbsid)) + return 0; + + QWK->FindBBS(bbsid); + ReadGldFile(); + + int imported = 0; + + OrigArea = CurrArea = -1; + + strcpy(file, AddPath(QWK->ImportPath(), "MESSAGES.DAT")); + fp.fopen(file, "rb"); + if(fp.isopen()) { + + // Skip past product info header + fp.fseekset(sizeof(QWKHdr)); + + QWKHdr hdr; + + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + // Read each message, header first + int tosstobadmsgs = false; + int lastconfno = -1; + int more; + do { + + ResetMsg(msg); + + memset(&hdr, 0, sizeof(QWKHdr)); + more = 1 == fp.fread(&hdr, sizeof(QWKHdr)); + if(more) { + + char blocks[7]; + strxcpy(blocks, hdr.blocks, 7); + uint msglen = atoi(blocks); + if(msglen == 0) { + break; + } + msglen = (msglen-1)*128; + + if(hdr.confno != lastconfno) { + lastconfno = hdr.confno; + if(QWK->FindEcho(hdr.confno)) { + int areano = AL.AreaEchoToNo(QWK->EchoID()); + if(areano != -1) { + CurrArea = AL.AreaNoToId(areano); + tosstobadmsgs = false; + } + } + else { + int areano = AL.AreaEchoToNo(QWK->BadMsgs()); + if(areano != -1) { + CurrArea = AL.AreaNoToId(areano); + tosstobadmsgs = true; + } + else { + tosstobadmsgs = -1; + fp.fseek(msglen, SEEK_CUR); + } + } + } + + if(tosstobadmsgs != -1) { + + if(OrigArea != CurrArea) { + if(AA->isopen()) { + AA->Unlock(); + AA->Close(); + } + AL.SetActiveAreaId(CurrArea); + OrigArea = CurrArea; + AA->Open(); + AA->Lock(); + AA->RandomizeData(); + } + + // Convert header + msg->orig = msg->oorig = AA->aka(); + msg->dest = msg->odest = AA->aka(); + msg->attr.pvt(hdr.status == '*' or hdr.status == '+'); + msg->attr.rcv(hdr.status == '+' or hdr.status == '-' or hdr.status == '`' or hdr.status == '^' or hdr.status == '#'); + msg->attr.del(hdr.activestatus == 226); + strtrim(strxcpy(msg->by, hdr.from, 26)); + strtrim(strxcpy(msg->to, hdr.to, 26)); + strtrim(strxcpy(msg->re, hdr.subject, 26)); + int _year, _month, _day, _hour, _minute; + sscanf(hdr.date, "%d%*c%d%*c%2d", &_month, &_day, &_year); + sscanf(hdr.time, "%d%*c%2d", &_hour, &_minute); + struct tm _tm; + _tm.tm_year = (_year < 80) ? (_year+100) : _year; + _tm.tm_mon = _month - 1; + _tm.tm_mday = _day; + _tm.tm_hour = _hour; + _tm.tm_min = _minute; + _tm.tm_sec = 0; + _tm.tm_isdst = -1; + time_t a = mktime(&_tm); + time_t b = mktime(gmtime(&a)); + msg->written = a + a - b; + a = time(NULL); + b = mktime(gmtime(&a)); + msg->arrived = a + a - b; + + // Read message text + char* txtptr = msg->txt = (char*)throw_calloc(1, msglen+128); + if(tosstobadmsgs) { + sprintf(msg->txt, "AREA:%s_%u\r", bbsid, hdr.confno); + txtptr += strlen(msg->txt); + } + fp.fread(txtptr, msglen); + strtrim(txtptr); + strchg(txtptr, 0xE3, 0x0D); + + imported++; + AA->istossed = true; + update_statuslinef("%s: %u", AA->echoid(), imported); + + msg->attr.tou0(); + msg->TextToLines(CFG->dispmargin-1); + if(msg->messageid or msg->references or msg->inreplyto or *msg->ifrom) { + char kbuf[256]; + uint txtlen = strlen(msg->txt); + if(*msg->ifrom) { + INam _fromname; + IAdr _fromaddr; + ParseInternetAddr(msg->ifrom, _fromname, _fromaddr); + if(AA->Internetgate().addr.net) { + char abuf[40]; + sprintf(kbuf, "\x1""REPLYTO %s %s\r""\x1""REPLYADDR %s\r", + AA->Internetgate().addr.make_string(abuf), + *AA->Internetgate().name ? AA->Internetgate().name : "UUCP", + _fromaddr + ); + uint addlen = strlen(kbuf); + msg->txt = (char*)throw_realloc(msg->txt, txtlen+addlen+1); + memmove(msg->txt+addlen, msg->txt, txtlen+1); + memcpy(msg->txt, kbuf, addlen); + txtlen += addlen; + } + } + if(msg->references) { + char* mptr = msg->references; + char* sptr = mptr; + while(*mptr) { + if(not strnieql(mptr, "echoid(), "REPLY"); + strcat(kbuf, "\r"); + uint addlen = strlen(kbuf); + msg->txt = (char*)throw_realloc(msg->txt, txtlen+addlen+1); + memmove(msg->txt+addlen, msg->txt, txtlen+1); + memcpy(msg->txt, kbuf, addlen); + txtlen += addlen; + } + mptr = sptr; + } + } + if(msg->inreplyto) { + if(not strnieql(msg->inreplyto, "inreplyto, kbuf, AA->echoid(), "REPLY"); + strcat(kbuf, "\r"); + uint addlen = strlen(kbuf); + msg->txt = (char*)throw_realloc(msg->txt, txtlen+addlen+1); + memmove(msg->txt+addlen, msg->txt, txtlen+1); + memcpy(msg->txt, kbuf, addlen); + txtlen += addlen; + } + } + if(msg->messageid) { + if(not strnieql(msg->messageid, "messageid, kbuf, AA->echoid(), "MSGID"); + strcat(kbuf, "\r"); + uint addlen = strlen(kbuf); + msg->txt = (char*)throw_realloc(msg->txt, txtlen+addlen+1); + memmove(msg->txt+addlen, msg->txt, txtlen+1); + memcpy(msg->txt, kbuf, addlen); + } + } + } + + if(*msg->realto and (strieql(msg->to, AA->Whoto()) or not *msg->to)) + strcpy(msg->to, msg->realto); + + AA->SaveMsg(GMSG_NEW, msg); + } + } + } while(more); + + if(AA->isopen()) { + AA->Unlock(); + AA->Close(); + } + + ResetMsg(msg); + throw_free(msg); + + fp.fclose(); + remove(file); + + if(*QWK->TossLog()) { + fp.fopen(QWK->TossLog(), "at"); + if(fp.isopen()) { + uint na = 0; + while(na < AL.size()) { + if(AL[na]->istossed) { + AL[na]->istossed = false; + AL[na]->isunreadchg = true; + fp.printf("%s\n", AL[na]->echoid()); + } + na++; + } + fp.fclose(); + } + } + + if(imported and *QWK->ReplyLinker()) { + char buf[256]; + sprintf(buf, LNG->Replylinker, QWK->ReplyLinker()); + ShellToDos(QWK->ReplyLinker(), buf, LGREY|_BLACK, YES); + } + } + + if(imported) + startupscan_success = true; + + return imported; +} + + +// ------------------------------------------------------------------ + +int ExportQwkMsg(GMsg* msg, gfile& fp, int confno, int& pktmsgno) { + + // Prepare for Return Receipt Request + char msg__re[26]; + if(QWK->ReceiptAllowed() and msg->attr.rrq()) + sprintf(msg__re, "RRR%-22.22s", msg->re); + else + strxcpy(msg__re, msg->re, 26); + + // Build QWK header + QWKHdr hdr; + char buf[26]; + int tolen = strlen(msg->to); tolen = MinV(25,tolen); + int bylen = strlen(msg->by); bylen = MinV(25,bylen); + int relen = strlen(msg__re); relen = MinV(25,relen); + memset(&hdr, ' ', sizeof(QWKHdr)); + hdr.status = msg->attr.pvt() ? '*' : ' '; + sprintf(buf, "%u", confno); + memcpy(hdr.msgno, buf, strlen(buf)); + struct tm* _tm = gmtime(&msg->written); + int _year = _tm->tm_year % 100; + sprintf(buf, "%02d-%02d-%02d", _tm->tm_mon+1, _tm->tm_mday, _year); + memcpy(hdr.date, buf, 8); + sprintf(buf, "%02d:%02d", _tm->tm_hour, _tm->tm_min); + memcpy(hdr.time, buf, 5); + strxcpy(buf, msg->to, tolen+1); + if(not QWK->MixCaseAllowed()) + strupr(buf); + memcpy(hdr.to, buf, tolen); + strxcpy(buf, msg->by, bylen+1); + if(not QWK->MixCaseAllowed()) + strupr(buf); + memcpy(hdr.from, buf, bylen); + memcpy(hdr.subject, msg__re, relen); + hdr.activestatus = '\xE1'; + hdr.confno = (word)confno; + hdr.pktmsgno = (word)++pktmsgno; + + // Write preliminary header + fp.fwrite(&hdr, sizeof(QWKHdr)); + + // Write body + int level = 0; + if(CharTable) + level = CharTable->level ? CharTable->level : 2; + + char mbuf[512]; + uint msglen = 0; + + if(msg->charsetencoding & GCHENC_MNE) { + if(not striinc("MNEMONIC", CharTable->exp)) + LoadCharset(CFG->xlatlocalset, "MNEMONIC"); + } + else if(striinc("LATIN1QP", msg->charset)) { + if(not striinc("LATIN1QP", CharTable->exp)) + LoadCharset(CFG->xlatlocalset, "LATIN1QP"); + } + else if(striinc("LATIN-1", msg->charset)) { + if(not striinc("LATIN-1", CharTable->exp)) + LoadCharset(CFG->xlatlocalset, "LATIN-1"); + } + + char qwkterm = '\xE3'; + + // Process kludges and write header lines + Line* line = msg->lin; + while(line) { + if(line->type & GLINE_KLUDGE) { + if(AA->isinternet()) { + if((line->kludge == GKLUD_RFC) or (line->kludge == 0)) { + XlatStr(mbuf, line->text, level, CharTable); + msglen += fp.printf("%s%c", mbuf, qwkterm); + } + else if(line->type & GLINE_WRAP) { + while(line->next and (line->type & GLINE_WRAP)) + line = line->next; + } + } + else { + if((line->type & GLINE_KLUDGE) and QWK->KludgesAllowed()) { + XlatStr(mbuf, line->text, level, CharTable); + msglen += fp.printf("%s%c", mbuf, qwkterm); + } + } + } + line = line->next; + } + + // Write blank line after header lines + if(AA->Internetrfcbody()) { + msglen += fp.printf("%c", qwkterm); + } + + // Write all message lines + line = msg->lin; + while(line) { + if(not (line->type & GLINE_KLUDGE)) { + XlatStr(mbuf, line->text, level, CharTable); + msglen += fp.printf("%s%c", mbuf, qwkterm); + } + line = line->next; + } + + // Calculate blocks + uint endlen = msglen % 128; + uint blocks = 1+(msglen/128)+(endlen?1:0); + sprintf(buf, "%u", blocks); + memcpy(hdr.blocks, buf, strlen(buf)); + + // Write padding spaces at the end if necessary + if(endlen) { + char padding[128]; + memset(padding, ' ', 128); + fp.fwrite(padding, 128-endlen); + } + + // Re-write the header + fp.fseek(-(blocks*128), SEEK_CUR); + fp.fwrite(&hdr, sizeof(QWKHdr)); + fp.fseek((blocks-1)*128, SEEK_CUR); + + // Mark msg as sent + msg->attr.snt1(); + msg->attr.scn1(); + msg->attr.uns0(); + AA->SaveHdr(GMSG_UPDATE, msg); + + return 1; +} + + +// ------------------------------------------------------------------ + +int ExportQwkArea(int areano, gfile& fp, int confno, int& pktmsgno) { + + int exported = 0; + + AL.SetActiveAreaNo(areano); + + AA->Open(); + AA->Lock(); + AA->RandomizeData(); + + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + for(uint n=0; nExpo.Count(); n++) { + if(AA->LoadMsg(msg, AA->Expo[n], 80)) { + if(msg->attr.uns()) { + exported += ExportQwkMsg(msg, fp, confno, pktmsgno); + update_statuslinef("%s: %u", AA->echoid(), exported); + } + } + } + + ResetMsg(msg); + throw_free(msg); + + AA->Unlock(); + AA->Close(); + + AA->Expo.ResetAll(); + + return exported; +} + + +// ------------------------------------------------------------------ + +int ExportQWK() { + + if(not *QWK->ExportPath()) + return 0; + + int exported = 0; + + gfile fp; + Path scanfile; + + // Get the scan list + strcpy(scanfile, AddPath(CFG->goldpath, "GOLDQWK.LST")); + fp.fopen(scanfile, "rt"); + if(fp.isopen()) { + char buf[256]; + while(fp.fgets(buf, sizeof(buf))) { + char* ptr = strchr(buf, ' '); + if(ptr) { + *ptr++ = NUL; + int a = AL.AreaEchoToNo(buf); + if(a != -1 and AL[a]->isqwk()) + AL[a]->Expo.Add(atol(ptr)); + } + } + fp.fclose(); + } + + // Export from the QWK areas + if(QWK->FirstBBS()) { + do { + ReadGldFile(); + Path replyfile; + int pktmsgno = 0; + if(QWK->FirstConf()) { + sprintf(replyfile, "%s%s.MSG", QWK->ExportPath(), QWK->BbsID()); + fp.fopen(replyfile, "wb"); + if(fp.isopen()) { + char firstrec[128]; + memset(firstrec, ' ', 128); + memcpy(firstrec, QWK->BbsID(), strlen(QWK->BbsID())); + fp.fwrite(firstrec, 128); + pktmsgno = 0; + } + do { + int a = AL.AreaEchoToNo(QWK->EchoID()); + if(a != -1 and AL[a]->Expo.Count()) { + if(QWK->ConfNo() != -1) + exported += ExportQwkArea(a, fp, QWK->ConfNo(), pktmsgno); + } + } while(QWK->NextConf()); + } + if(fp.isopen()) { + fp.fclose(); + if(pktmsgno == 0) + remove(replyfile); + } + } while(QWK->NextBBS()); + } + + // Delete the scanfile + remove(scanfile); + + return exported; +} + + +// ------------------------------------------------------------------ + +Qwk::Qwk() { + + bbs = bbsp = NULL; + mapp = NULL; + bbss = 0; +} + + +// ------------------------------------------------------------------ + +Qwk::~Qwk() { + + Reset(); +} + + +// ------------------------------------------------------------------ + +void Qwk::Reset() { + + for(int n=0; nbbsid, bbsid, sizeof(bbsp->bbsid)); + bbsp->kludges = false; + bbsp->mixcase = false; + bbsp->receipt = false; + bbsp->maxlines = -1; + bbsp->map = NULL; + bbsp->maps = 0; + mapp = NULL; +} + + +// ------------------------------------------------------------------ + +void Qwk::AddMap(char* bbsid, char* echoid, char* confname, int confno) { + + FindAddBBS(bbsid); + bbsp->map = (QwkMap*)throw_realloc(bbsp->map, (bbsp->maps+1)*sizeof(QwkMap)); + mapp = bbsp->map + bbsp->maps++; + strxcpy(mapp->confname, confname, sizeof(mapp->confname)); + strxcpy(mapp->echoid, echoid, sizeof(mapp->echoid)); + mapp->confno = confno; +} + + +// ------------------------------------------------------------------ + +int Qwk::FindBBS(char* bbsid) { + + bbsp = bbs; + for(int n=0; nbbsid)) { + mapp = bbsp->map; + return true; + } + } + mapp = NULL; + return false; +} + + +// ------------------------------------------------------------------ + +void Qwk::FindAddBBS(char* bbsid) { + + if(not FindBBS(bbsid)) + AddBBS(bbsid); +} + + +// ------------------------------------------------------------------ + +int Qwk::FirstBBS() { + + if(bbs) { + bbsp = bbs; + bbsn = 1; + return true; + } + + bbsp = NULL; + bbsn = 0; + return false; +} + + +// ------------------------------------------------------------------ + +int Qwk::NextBBS() { + + if(bbsp and (bbsn < bbss)) { + bbsp++; + bbsn++; + return true; + } + + bbsp = NULL; + bbsn = 0; + return false; +} + + +// ------------------------------------------------------------------ + +int Qwk::FindConf(char* echoid) { + + if(bbsp) { + mapp = bbsp->map; + for(int n=0; nmaps; n++,mapp++) + if(strieql(echoid, mapp->echoid)) + return true; + } + + mapp = NULL; + return false; +} + + +// ------------------------------------------------------------------ + +int Qwk::FindEcho(char* confname) { + + if(bbsp) { + mapp = bbsp->map; + for(int n=0; nmaps; n++,mapp++) + if(strieql(confname, mapp->confname)) + return true; + } + + mapp = NULL; + return false; +} + + +// ------------------------------------------------------------------ + +int Qwk::FindEcho(int confno) { + + if(bbsp) { + mapp = bbsp->map; + for(int n=0; nmaps; n++,mapp++) + if(confno == mapp->confno) + return true; + } + + mapp = NULL; + return false; +} + + +// ------------------------------------------------------------------ + +int Qwk::FirstConf() { + + if(bbsp and bbsp->map) { + mapp = bbsp->map; + mapn = 1; + return true; + } + + mapp = NULL; + mapn = 0; + return false; +} + + +// ------------------------------------------------------------------ + +int Qwk::NextConf() { + + if(mapp and (mapn < bbsp->maps)) { + mapp++; + mapn++; + return true; + } + + mapp = NULL; + mapn = 0; + return false; +} + + +// ------------------------------------------------------------------ + +const char* Qwk::BbsID() { + + return bbsp ? bbsp->bbsid : ""; +} + + +// ------------------------------------------------------------------ + +const char* Qwk::ConfName() { + + return mapp ? mapp->confname : ""; +} + + +// ------------------------------------------------------------------ + +int Qwk::ConfNo(int set) { + + if(mapp) { + if(set != -2) + mapp->confno = set; + return mapp->confno; + } + return -1; +} + + +// ------------------------------------------------------------------ + +const char* Qwk::EchoID() { + + return mapp ? mapp->echoid : ""; +} + + +// ------------------------------------------------------------------ + +int Qwk::KludgesAllowed(int set) { + + if(bbsp) { + if(set != -1) + bbsp->kludges = set; + return bbsp->kludges; + } + + return false; +} + + +// ------------------------------------------------------------------ + +int Qwk::MixCaseAllowed(int set) { + + if(bbsp) { + if(set != -1) + bbsp->mixcase = set; + return bbsp->mixcase; + } + + return false; +} + + +// ------------------------------------------------------------------ + +int Qwk::ReceiptAllowed(int set) { + + if(bbsp) { + if(set != -1) + bbsp->receipt = set; + return bbsp->receipt; + } + + return false; +} + + +// ------------------------------------------------------------------ + +int Qwk::MaxLines(int set) { + + if(bbsp) { + if(set != -1) + bbsp->maxlines = set; + return bbsp->maxlines; + } + + return 0; +} + + +// ------------------------------------------------------------------ + +void Qwk::ResetConfNo(int set) { + + if(bbsp) { + mapp = bbsp->map; + for(int n=0; nmaps; n++,mapp++) + mapp->confno = set; + } +} + + +// ------------------------------------------------------------------ + +char* Qwk::BadMsgs(char* set) { + + if(set) + strxcpy(cfg.badmsgs, set, sizeof(Echo)); + + return cfg.badmsgs; +} + + +// ------------------------------------------------------------------ + +char* Qwk::ExportPath(char* set) { + + if(set) + PathCopy(cfg.exportpath, set); + + return cfg.exportpath; +} + + +// ------------------------------------------------------------------ + +char* Qwk::ImportPath(char* set) { + + if(set) + PathCopy(cfg.importpath, set); + + return cfg.importpath; +} + + +// ------------------------------------------------------------------ + +char* Qwk::ReplyLinker(char* set) { + + if(set) + strxcpy(cfg.replylinker, set, sizeof(Path)); + + return cfg.replylinker; +} + + +// ------------------------------------------------------------------ + +char* Qwk::TossLog(char* set) { + + if(set) + strxcpy(cfg.tosslog, set, sizeof(Path)); + + return cfg.tosslog; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/geqwks.h b/golded3/geqwks.h new file mode 100644 index 0000000..86f4786 --- /dev/null +++ b/golded3/geqwks.h @@ -0,0 +1,117 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// QWK Implementation Structures and Classes. +// ------------------------------------------------------------------ + + +// ------------------------------------------------------------------ + +struct QwkCfg { + Echo badmsgs; + Path exportpath; + Path importpath; + Path replylinker; + Path tosslog; +}; + + +// ------------------------------------------------------------------ + +struct QwkMap { + char confname[21]; + int confno; + Echo echoid; +}; + + +// ------------------------------------------------------------------ + +struct QwkBbs { + char bbsid[9]; + int kludges : 1; // TRUE if allowed to export kludges + int mixcase : 1; // TRUE if mixed case is allowed + int receipt : 1; // TRUE if return receipts are supported + int maxlines; + QwkMap* map; + int maps; +}; + + +// ------------------------------------------------------------------ + +class Qwk { + + QwkCfg cfg; // Global QWK configuration + QwkBbs* bbs; // Collection of BBS data + int bbss; // Number of BBS'es stored + QwkBbs* bbsp; // Pointer to current BBS + int bbsn; // Number of current BBS + QwkMap* mapp; // Pointer to current conference map + int mapn; // Number of current conference map + +public: + + Qwk(); + ~Qwk(); + + void Reset(); + + void AddBBS(char* bbsid); + void AddMap(char* bbsid, char* echoid, char* confname, int confno=-1); + + int FindBBS(char* bbsid); + void FindAddBBS(char* bbsid); + int FoundBBS() { return !!bbsp; } + int FirstBBS(); + int NextBBS(); + + int FindConf(char* echoid); + int FindEcho(char* confname); + int FindEcho(int confno); + int FoundConf() { return !!mapp; } + int FirstConf(); + int NextConf(); + + const char* BbsID(); + const char* ConfName(); + int ConfNo(int set=-2); + const char* EchoID(); + + int KludgesAllowed(int set=-1); + int MixCaseAllowed(int set=-1); + int ReceiptAllowed(int set=-1); + int MaxLines(int set=-1); + + void ResetConfNo(int set=-1); + + char* BadMsgs(char* set=NULL); + char* ExportPath(char* set=NULL); + char* ImportPath(char* set=NULL); + char* ReplyLinker(char* set=NULL); + char* TossLog(char* set=NULL); +}; + + +// ------------------------------------------------------------------ + diff --git a/golded3/gerand.cpp b/golded3/gerand.cpp new file mode 100644 index 0000000..f78960b --- /dev/null +++ b/golded3/gerand.cpp @@ -0,0 +1,381 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Random system and control info handling. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +char* GetRandomLine(char* __buf, size_t __bufsize, const char* __file) { + + Path indexfile; + + replaceextension(indexfile, __file, ".sdx"); + + FILE* fp = fsopen(AddPath(CFG->goldpath, __file), "rb", CFG->sharemode); + if(fp) { + + // Check if index exists or if it is older than the textfile + const char* idxfile = AddPath(CFG->goldpath, indexfile); + int idxexist = fexist(idxfile); + if(idxexist) + if(FiletimeCmp(__file, idxfile) > 0) + idxexist = false; + + FILE* fpi = fsopen(idxfile, idxexist ? "rb" : "wb+", CFG->sharemode); + if(fpi) { + + // Create index if one was missing + if(not idxexist) { + setvbuf(fp, NULL, _IOFBF, 32000); + setvbuf(fpi, NULL, _IOFBF, 16000); + long fpos = 0; + char buf[512]; + while(fgets(buf, sizeof(buf), fp)) { + fwrite(&fpos, sizeof(long), 1, fpi); + fpos += strlen(buf); + } + } + + // Get random line if there is at least one + int _lines = (int)(fsize(fpi)/sizeof(long)); + if(_lines > 0) { + + // Select a random line + long _offset = 0; + long _ourline = rand() % _lines; + fseek(fpi, _ourline*(long)sizeof(long), SEEK_SET); + fread(&_offset, sizeof(long), 1, fpi); + + // Get it + char buf[512]; + fseek(fp, _offset, SEEK_SET); + fgets(buf, sizeof(buf), fp); + StripQuotes(strbtrim(buf)); + strxcpy(__buf, buf, __bufsize); + } + fclose(fpi); + } + fclose(fp); + } + + return __buf; +} + + +// ------------------------------------------------------------------ + +char* HandleRandomLine(char* buf, size_t bufsize) { + + if(*buf == '@') + GetRandomLine(buf, bufsize, buf+1); + + return buf; +} + + +// ------------------------------------------------------------------ + +void Area::InitData() { + + // Set defaults + adat->aka = CFG->aka[GetAkaNo(aka())]; + adat->akamatching = (CFG->switches.get(akamatchnet) and isnet()) or + (CFG->switches.get(akamatchecho) and isecho()) or + (CFG->switches.get(akamatchlocal) and islocal()); + adat->attributes = attr(); + adat->areacopyaddid = CFG->areacopyaddid; + adat->areacopydirect = CFG->areacopydirect; + strcpy(adat->areacopyto, CFG->areacopyto); + adat->areaforwarddirect = CFG->areaforwarddirect; + adat->areafreqdirect = CFG->areafreqdirect; + strcpy(adat->areafreqto, CFG->areafreqto); + adat->areareplydirect = CFG->areareplydirect; + strcpy(adat->areareplyto, CFG->areareplyto); + strcpy(adat->areayouwroteto, CFG->areayouwroteto); + if(isemail()) + adat->ctrlinfo = CFG->ctrlinfoemail; + else if(isnewsgroup()) + adat->ctrlinfo = CFG->ctrlinfonews; + else if(isnet()) + adat->ctrlinfo = CFG->ctrlinfonet; + else if(isecho()) + adat->ctrlinfo = CFG->ctrlinfoecho; + else + adat->ctrlinfo = CFG->ctrlinfolocal; + adat->edithardterm = EDIT->HardTerm(); + adat->editmixcase = EDIT->MixCase(); + adat->forcetemplate = CFG->forcetemplate; + strcpy(adat->inputfile, CFG->inputfile); + strcpy(adat->internetaddress, CFG->internetaddress); + memcpy(&adat->internetgate, &CFG->internetgate, sizeof(Node)); + adat->internetmsgid = CFG->internetmsgid; + adat->internetrfcbody = CFG->internetrfcbody; + strcpy(adat->loadlanguage, CFG->loadlanguage); + adat->msglistdate = CFG->msglistdate; + adat->msglistfast = CFG->msglistfast; + adat->msglistfirst = CFG->msglistfirst; + adat->msglistheader = CFG->msglistheader; + adat->msglistwidesubj = CFG->msglistwidesubj; + strcpy(adat->organization, CFG->organization); + strxcpy(adat->origin, CFG->origin.empty() ? "" : CFG->origin[CFG->originno].c_str(), sizeof(adat->origin)); + strcpy(adat->outputfile, CFG->outputfile); + memcpy(&adat->play, &CFG->play, sizeof(GPlay)); + strcpy(adat->quotebuffile, CFG->quotebuffile); + strcpy(adat->quotechars, CFG->quotechars); + adat->quotectrl = CFG->quotectrl; + strcpy(adat->quotestring, CFG->quotestring); + adat->quotewraphard = CFG->quotewraphard; + adat->replyre = EDIT->ReplyRe(); + if(*CFG->searchfor) + strcpy(adat->searchfor, CFG->searchfor); + strcpy(adat->tagline, CFG->tagline.empty() ? "" : CFG->tagline[CFG->taglineno].c_str()); + adat->taglinechar = CFG->taglinechar; + adat->taglinesupport = CFG->taglinesupport; + strcpy(adat->tearline, CFG->tearline); + strcpy(adat->tpl, (CFG->tplno and (CFG->tplno < CFG->tpl.size())) ? CFG->tpl[CFG->tplno].file : ""); + adat->templatematch = CFG->templatematch; + adat->twitmode = CFG->twitmode; + adat->usefwd = CFG->usefwd; + strcpy(adat->username.name, CFG->username.empty() ? "" : CFG->username[CFG->usernameno].name); + adat->username.addr = adat->aka.addr; + adat->usetzutc = CFG->usetzutc; + adat->viewhidden = CFG->viewhidden; + adat->viewkludge = CFG->viewkludge; + adat->viewquote = CFG->viewquote; + strcpy(adat->nickname, CFG->nickname); + strcpy(adat->whoto, CFG->whoto); + strcpy(adat->xlatexport, CFG->xlatexport); + strcpy(adat->xlatimport, CFG->xlatimport); + + LoadLanguage(adat->loadlanguage); +} + + +// ------------------------------------------------------------------ +// Get data from the Random System + +void Area::RandomizeData(int mode) { + + if(not adat) { + adat = (AreaData*)throw_calloc(1, sizeof(AreaData)); + InitData(); + } + else { // reset to global defaults + strcpy(adat->tpl, (CFG->tplno and (CFG->tplno < CFG->tpl.size())) ? CFG->tpl[CFG->tplno].file : ""); + } + + char _groupid[10]; + if(CFG->areafilegroups and groupid()) { + if(groupid() & 0x8000u) + sprintf(_groupid, "#%u", groupid() & 0x7FFF); + else { + _groupid[0] = (char)(isalpha(groupid()) ? groupid() : NUL); + _groupid[1] = NUL; + } + } + else { + *_groupid = NUL; + } + + Echo _echoid; + strcpy(_echoid, echoid()); + + const char* found = CFG->grp.SetGrp(_echoid); + int curgrp = CFG->grp.currgrpno; + if(*_groupid) { + found = CFG->grp.SetGrp(_groupid); + if(found and (strieql(found, "*") or ((curgrp >= 0) and (curgrp < CFG->grp.currgrpno)))) + found = NULL; + if(not found) + found = CFG->grp.SetGrp(_echoid); + } + + if(found) { + char buf[256]; + + if(CFG->grp.GetItm(GRP_AKA, &adat->aka, sizeof(gaka))) + SetAka(adat->aka.addr); + + CFG->grp.GetItm(GRP_AKAMATCHING, adat->akamatching); + + if(CFG->grp.GetItm(GRP_ATTRIBUTES, buf, sizeof(buf))) { + if(isnet()) + adat->attributes = CFG->attribsnet; + else if(isecho()) + adat->attributes = CFG->attribsecho; + else + adat->attributes = CFG->attribslocal; + GetAttribstr(&adat->attributes, buf); + } + + CFG->grp.GetItm(GRP_AREACOPYADDID, adat->areacopyaddid); + CFG->grp.GetItm(GRP_AREACOPYDIRECT, adat->areacopydirect); + CFG->grp.GetItm(GRP_AREACOPYTO, adat->areacopyto, sizeof(adat->areacopyto)); + CFG->grp.GetItm(GRP_AREAFORWARDDIRECT, adat->areaforwarddirect); + CFG->grp.GetItm(GRP_AREAFREQDIRECT, adat->areafreqdirect); + CFG->grp.GetItm(GRP_AREAFREQTO, adat->areafreqto, sizeof(adat->areareplyto)); + CFG->grp.GetItm(GRP_AREAREPLYDIRECT, adat->areareplydirect); + CFG->grp.GetItm(GRP_AREAREPLYTO, adat->areareplyto, sizeof(adat->areareplyto)); + CFG->grp.GetItm(GRP_AREAYOUWROTETO, adat->areayouwroteto, sizeof(adat->areayouwroteto)); + CFG->grp.GetItm(GRP_CTRLINFO, adat->ctrlinfo); + CFG->grp.GetItm(GRP_EDITHARDTERM, adat->edithardterm); + CFG->grp.GetItm(GRP_EDITMIXCASE, adat->editmixcase); + CFG->grp.GetItm(GRP_EDITREPLYRE, adat->replyre); + CFG->grp.GetItm(GRP_FORCETEMPLATE, adat->forcetemplate); + CFG->grp.GetItm(GRP_INPUTFILE, adat->inputfile, sizeof(adat->inputfile)); + CFG->grp.GetItm(GRP_INTERNETADDRESS, adat->internetaddress, sizeof(adat->internetaddress)); + CFG->grp.GetItm(GRP_INTERNETGATE, &adat->internetgate, sizeof(Node)); + CFG->grp.GetItm(GRP_INTERNETMSGID, adat->internetmsgid); + CFG->grp.GetItm(GRP_INTERNETRFCBODY, adat->internetrfcbody); + + if(CFG->grp.GetItm(GRP_LOADLANGUAGE, adat->loadlanguage, sizeof(adat->loadlanguage))) + LoadLanguage(adat->loadlanguage); + + CFG->grp.GetItm(GRP_MSGLISTDATE, adat->msglistdate); + CFG->grp.GetItm(GRP_MSGLISTFAST, adat->msglistfast); + CFG->grp.GetItm(GRP_MSGLISTFIRST, adat->msglistfirst); + CFG->grp.GetItm(GRP_MSGLISTHEADER, adat->msglistheader); + CFG->grp.GetItm(GRP_MSGLISTWIDESUBJ, adat->msglistwidesubj); + CFG->grp.GetItm(GRP_ORGANIZATION, adat->organization, sizeof(adat->organization)); + + if(CFG->grp.GetItm(GRP_ORIGIN, buf, sizeof(buf))) + strxcpy(adat->origin, buf, sizeof(adat->origin)); + + CFG->grp.GetItm(GRP_OUTPUTFILE, adat->outputfile, sizeof(adat->outputfile)); + CFG->grp.GetItm(GRP_QUOTEBUFFILE, adat->quotebuffile, sizeof(adat->quotebuffile)); + CFG->grp.GetItm(GRP_QUOTECHARS, adat->quotechars, sizeof(adat->quotechars)); + CFG->grp.GetItm(GRP_QUOTECTRL, adat->quotectrl); + CFG->grp.GetItm(GRP_QUOTESTRING, adat->quotestring, sizeof(adat->quotestring)); + CFG->grp.GetItm(GRP_QUOTEWRAPHARD, adat->quotewraphard); + + if(CFG->grp.GetItm(GRP_PLAY, buf, sizeof(buf))) { + if(*buf == '@') + GetRandomLine(buf, sizeof(buf), buf+1); + FileToGPlay(&adat->play, buf); + } + + CFG->grp.GetItm(GRP_SEARCHFOR, adat->searchfor, sizeof(adat->searchfor)); + + if(CFG->grp.GetItm(GRP_TAGLINE, buf, sizeof(buf))) + strxcpy(adat->tagline, buf, sizeof(adat->tagline)); + + CFG->grp.GetItm(GRP_TAGLINECHAR, adat->taglinechar); + CFG->grp.GetItm(GRP_TAGLINESUPPORT, adat->taglinesupport); + + if(CFG->grp.GetItm(GRP_TEARLINE, buf, sizeof(buf))) + strxcpy(adat->tearline, buf, sizeof(adat->tearline)); + + if(not adat->forcetemplate) { + if(CFG->tplno and (CFG->tplno < CFG->tpl.size())) + strxcpy(adat->tpl, CFG->tpl[CFG->tplno].file, sizeof(adat->tpl)); + else + if(CFG->grp.GetItm(GRP_TEMPLATE, buf, sizeof(buf))) { + if(*buf == '@') + GetRandomLine(buf, sizeof(buf), buf+1); + strxcpy(adat->tpl, buf, sizeof(adat->tpl)); + } + } + + CFG->grp.GetItm(GRP_TEMPLATEMATCH, adat->templatematch); + CFG->grp.GetItm(GRP_TWITMODE, adat->twitmode); + CFG->grp.GetItm(GRP_USEFWD, adat->usefwd); + + if(CFG->grp.GetItm(GRP_USERNAME, buf, sizeof(buf))) { + if(*buf == '@') + GetRandomLine(buf, sizeof(buf), buf+1); + Addr tmp; + tmp.reset(); + switch(mode) { + case MODE_NEW: + case MODE_QUOTE: + case MODE_REPLY: + case MODE_REPLYCOMMENT: + case MODE_FORWARD: + char* aptr = strrchr(buf, ','); + if(aptr) { + *aptr++ = NUL; + aptr = strskip_wht(aptr); + } + else { + aptr = strrchr(buf, ' '); + if(aptr) { + aptr++; + tmp.set(aptr); + if(tmp.net == 0) + aptr = NULL; + else + *aptr++ = NUL; + } + } + if(aptr) { + tmp = adat->aka.addr; + tmp.set(aptr); + if(tmp.net != 0) + *aptr = NUL; + } + strbtrim(buf); + break; + } + if(tmp.net == 0) + tmp = adat->aka.addr; + strxcpy(adat->username.name, buf, sizeof(adat->username.name)); + adat->username.addr = tmp; + SetAka(tmp); + } + + CFG->grp.GetItm(GRP_USETZUTC, adat->usetzutc); + + if(not mode) { + CFG->grp.GetItm(GRP_VIEWHIDDEN, adat->viewhidden); + CFG->grp.GetItm(GRP_VIEWKLUDGE, adat->viewkludge); + CFG->grp.GetItm(GRP_VIEWQUOTE, adat->viewquote); + } + + if(CFG->grp.GetItm(GRP_NICKNAME, buf, sizeof(buf))) + strxcpy(adat->nickname, buf, sizeof(adat->nickname)); + + if(CFG->grp.GetItm(GRP_WHOTO, buf, sizeof(buf))) { + if(*buf == '@') + GetRandomLine(buf, sizeof(buf), buf+1); + strxcpy(adat->whoto, buf, sizeof(adat->whoto)); + } + + CFG->grp.GetItm(GRP_XLATEXPORT, adat->xlatexport, sizeof(adat->xlatexport)); + CFG->grp.GetItm(GRP_XLATIMPORT, adat->xlatimport, sizeof(adat->xlatimport)); + } + + vector::iterator z; + for(z = CFG->mailinglist.begin(); z != CFG->mailinglist.end(); z++) + if(strieql(echoid(), z->echoid)) { + strcpy(adat->whoto, *z->contribution ? z->contribution : z->sender); + break; + } +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/geread.cpp b/golded3/geread.cpp new file mode 100644 index 0000000..8aa363e --- /dev/null +++ b/golded3/geread.cpp @@ -0,0 +1,1316 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Main reader and function key dispatcher. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ +// Global data + +extern bool cmdlinenoscan; +extern bool cmdlineexportsoup; + +GMsg* reader_msg; +int reader_gen_confirm = false; +int reader_finished; +int reader_done = false; +int reader_topline; +int reader_keyok; +int reader_direction; +int reader_rcv_noise = false; +gkey reader_keycode; +gkey reader_lastcode = 0; + +GMsgHeaderView *HeaderView; +GMsgBodyView *BodyView; + +void TwitDeleteMsg(GMsg* msg); +void GoNextMsg(); + + +// ------------------------------------------------------------------ + +gkey ReaderGetKey() { + + gkey keycode; + do { + keycode = getxchtick(); + if(keycode == Key_Tick) + CheckTick(KK_ReadQuitNow); + } while(keycode == Key_Tick); + if(keycode < KK_Commands) { + keycode = key_tolower(keycode); + gkey kk = SearchKey(keycode, ReadKey, ReadKeys); + if(kk) + keycode = kk; + } + return keycode; +} + + +// ------------------------------------------------------------------ + +gkey ViewMessage(int istwit) { + + gkey keycode; + int keyok; + + do { + + keycode = ReaderGetKey(); + keyok = true; + + switch(keycode) { + case KK_ReadMsgLineUp: + if(istwit <= TWIT_SHOW) + BodyView->LineUp(); + break; + + case KK_ReadMsgLineDown: + if(istwit <= TWIT_SHOW) + BodyView->LineDown(); + break; + + case KK_ReadMsgPgUp: + if(istwit <= TWIT_SHOW) + BodyView->PageUp(); + break; + + case KK_ReadMsgPgDn: + if(istwit <= TWIT_SHOW) + BodyView->PageDown(); + break; + + case KK_ReadMsgContinue: + if((istwit > TWIT_SHOW) or not BodyView->Continue()) + keyok = false; + break; + + case KK_ReadMsgHome: + BodyView->Top(istwit > TWIT_SHOW); + istwit = NOT_TWIT; + break; + + case KK_ReadMsgEnd: + BodyView->Bottom(); + istwit = NOT_TWIT; + break; + + default: + keyok = false; + } + + update_statuslines(); + + } while(keyok); + + return keycode; +} + + +// ------------------------------------------------------------------ + +void Reader() { + + int istwit; + bool istwitto, istwitsubj; + char buf[256], buf2[200]; + + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + reader_finished = false; + reader_msg = msg; + + // Sort all areas by the given sort order before scanning + AL.Sort(); + + int personalmails = 0; + int pmareas = 0; + int pmscan = CFG->personalmail & PM_STARTUP; + if(not cmdlinenoscan) { + if(cmdlinedebughg) + LOG.printf("- AreaScan during startup"); + AL.AreaScan(SCAN_STARTUP, 0, pmscan, personalmails, pmareas); + startupscan_success = true; + } + + CheckSemaphores(); + + if(cmdlineimportsoup) + ImportSOUP(); + + if(cmdlineexportsoup) + ExportSOUP(); + + AL.Sort(); + startecho = *stecho ? AL.AreaEchoToNo(stecho) : -1; + + inforow = (MAXROW-1)/2; + wclear(); + + // Reset tick values to avoid triggering screenblanker or timeout + gkbdtickpressreset(); + gkbdtickvaluereset(); + + if(startecho == -1) { + int i = 0; + do { + AL.SetActiveAreaNo(i++); + } while(AA->isseparator()); + NewArea(); + } + else { + AL.SetActiveAreaNo(startecho); + AA->RandomizeData(); + if(AA->Msglistfirst()) + kbput(KK_ReadMessageList); + } + + if(not reader_finished) { + + // Open the editor/reader window + + HeaderView->width = MAXCOL; + HeaderView->height = 6; + HeaderView->border_color = C_HEADB; + HeaderView->window_color = C_HEADW; + HeaderView->title_color = C_HEADT; + HeaderView->highlight_color = C_HEADQ; + HeaderView->from_color = C_HEADBY; + HeaderView->to_color = C_HEADTO; + HeaderView->subject_color = C_HEADRE; + HeaderView->Create(); + + BodyView->at_row = 6; + BodyView->width = MAXCOL; + BodyView->height = MAXROW - 6 - 1; + BodyView->border_color = C_READB; + BodyView->window_color = C_READW; + BodyView->scrollbar_color = C_READPB; + BodyView->highlight_color = C_READH; + BodyView->Create(); + + do { + + AA->isreadpm = false; + AA->isreadmark = false; + reader_direction = DIR_NEXT; + reader_msg->msgno = 0; + CFG->tplno = 0; + AL.SetActiveAreaId(CurrArea); + OrigArea = CurrArea; + + AA->Open(); + + AA->RandomizeData(); + if(AA->Play().type) + AA->Play().Play(); + + // Jump to next message. Go to personal mail if any. + if(AA->PMrk.Tags()) { + AA->SetBookmark(AA->lastread()); + AA->isreadpm = false; + ToggleMarkRead(); + } + else { + if(CFG->switches.get(dispautonext) or (AA->lastread() == 0)) + next_msg(DIR_NEXT); + AA->SetBookmark(AA->lastread()); + } + + // Main message reader loop + do { + + // Set the default help for this window + whelpcat(H_Reader); + + if(not AA->attr().hex()) + reader_topline = 0; + + if(AA->Msgn.Count() and not AA->lastread()) + AA->set_lastread(1); + + if(LoadMessage(msg, CFG->dispmargin-(int)CFG->switches.get(disppagebar))) { + + do { + + HeaderView->Use(AA, msg); + + HeaderView->Paint(); + + if(AA->isreadmark or AA->isreadpm) { + GTag& tag = AA->isreadpm ? AA->PMrk : AA->Mark; + uint mtemp = tag.Find(msg->msgno); + sprintf(buf2, "%s [%s%s%s]", + LNG->ReadMarked, + AA->Viewhidden() ? "H" : "", + AA->Viewkludge() ? "K" : "", + AA->Twitmode() == TWIT_IGNORE ? "Ti" : AA->Twitmode() == TWIT_SKIP ? "Ts" : AA->Twitmode() == TWIT_BLANK ? "Tb" : AA->Twitmode() == TWIT_KILL ? "Tk" : "" + ); + sprintf(buf, buf2, + mtemp, tag.Count(), tag.Count()-mtemp + ); + } + else { + sprintf(buf2, "%s [%s%s%s]", + LNG->ReadAll, + AA->Viewhidden() ? "H" : "", + AA->Viewkludge() ? "K" : "", + AA->Twitmode() == TWIT_IGNORE ? "Ti" : AA->Twitmode() == TWIT_SKIP ? "Ts" : AA->Twitmode() == TWIT_BLANK ? "Tb" : AA->Twitmode() == TWIT_KILL ? "Tk" : "" + ); + sprintf(buf, buf2, + AA->lastread(), AA->Msgn.Count(), AA->Msgn.Count()-AA->lastread() + ); + } + update_statusline(buf); + + reader_done = false; + reader_keyok = false; + + // Do some updating first + AA->set_lastread(AA->Msgn.ToReln(msg->msgno)); + AA->UpdateAreadata(); + + // Determine if the message is of the "twit" type + istwit = MsgIsTwit(msg, istwitto, istwitsubj); + + if(istwit) + HandleGEvent(EVTT_MSGISTWIT); + + if((istwit == TWIT_SKIP) or (not CFG->showdeleted and msg->attr.del())) { + if(reader_direction == DIR_NEXT) { + if(AA->lastread() < AA->Msgn.Count()) { + if(gkbd.kbuf == NULL) { + switch(reader_lastcode) { + case KK_ReadGotoReplies: + case KK_ReadGotoReply1st: + case KK_ReadGotoReplyNext: + if(MsgHasReplies(msg)) { + kbput(KK_ReadGotoReplies); + } + else { + SayBibi(); + kbput(KK_ReadGotoReplyPrev); + } + break; + default: + kbput(KK_ReadGotoNextMsg); + } + } + } + } + else { + if(AA->lastread() > 1) { + if(gkbd.kbuf == NULL) { + if(reader_lastcode == KK_ReadGotoReplyPrev) { + if(AA->Msgn.ToReln(msg->link.to())) + kbput(KK_ReadGotoReplyPrev); + else { + SayBibi(); + kbput(KK_ReadGotoReplies); + } + } + else + kbput(KK_ReadGotoPrevMsg); + } + } + } + } + + BodyView->Use(AA, msg, reader_topline); + if(istwit > TWIT_SHOW) { + BodyView->window.clear(); + if(istwit == TWIT_SKIP) + BodyView->window.prints(1, 0, C_READW, LNG->SkippingTwit); + else if(istwit == TWIT_KILL) + BodyView->window.prints(1, 0, C_READW, LNG->KillingTwit); + else { + BodyView->window.prints(1, 0, C_READW, LNG->HidingTwit); + } + } + else { + BodyView->Paint(); + } + + if(reader_rcv_noise) { + if(CFG->beepyourmail == ALWAYS) + HandleGEvent(EVTT_MSGTOYOU); + else if(reader_rcv_noise > 1 and CFG->beepyourmail == true) + HandleGEvent(EVTT_MSGTOYOU); + reader_rcv_noise = false; + } + else { + if(msg->attr.fmu()) + HandleGEvent(EVTT_MSGFROMYOU); + } + + if(msg->attr.loc() and CFG->switches.get(beeplocalmsg)) + HandleGEvent(EVTT_MSGISLOCAL); + + if(AA->Msgn.Count() and CFG->switches.get(highlightunread) and (msg->orig_timesread == 0)) + AA->UpdateTimesread(msg); + + switch(istwit) { + case TWIT_KILL: + TwitDeleteMsg(msg); + continue; + case TWIT_SKIP: + reader_keycode = ReaderGetKey(); + break; + default: + reader_keycode = ViewMessage(istwit); + } + + reader_topline = BodyView->UpperLine(); + + if(reader_gen_confirm) + ConfirmMsg(); + + reader_gen_confirm = false; + reader_lastcode = reader_keycode; + + switch(reader_keycode) { + + case KK_ReadMainMenu: + { + GMenuNavigate MenuNavigate; + int finaltag = MenuNavigate.Run(); + if((finaltag != W_ESCPRESS) and (finaltag != -1)) + kbput((gkey)finaltag); + } + break; + + case KK_ReadSoundkill: + HandleGEvent(EVTT_STOPVOICE); + break; + + case KK_ReadChangeAttrs: + ChangeAttributes(); + break; + + case KK_ReadChangeAka: + ChangeAka(); + break; + + case KK_ReadChangeTagline: + ChangeTagline(); + break; + + case KK_ReadChangeOrigin: + ChangeOrigin(); + break; + + case KK_ReadChangeUsername: + ChangeUsername(); + break; + + case KK_ReadChangeTemplate: + ChangeTemplate(); + break; + + case KK_ReadChangeXlatImport: + ChangeXlatImport(); + break; + + case KK_ReadLookupDest: + LookupNode(msg, "", LOOK_DEST); + reader_keyok = true; + break; + + case KK_ReadLookupOrig: + LookupNode(msg, "", LOOK_ORIG); + reader_keyok = true; + break; + + case KK_ReadFidoRenumber: + RenumberArea(); + break; + + case KK_ReadDecreaseMargin: + DecMargin(); + break; + + case KK_ReadIncreaseMargin: + IncMargin(); + break; + + case KK_ReadToggleStyles: + ToggleStyles(); + break; + + case KK_ReadToggleHexdump: + AA->attr().hexX(); + break; + + case KK_ReadToggleTwits: + ToggleTwits(); + break; + + case KK_ReadToggleMarkRead: + ToggleMarkRead(); + break; + + case KK_ReadToggleMark: + ToggleMark(); + break; + + case KK_ReadToggleBookMark: + ToggleBookMark(); + break; + + case KK_ReadGotoBookMark: + GotoBookMark(); + break; + + case KK_ReadGotoPrevMsg: + GotoPrevMsg(); + break; + + case KK_ReadGotoNextMsg: + case KK_ReadMsgContinue: + GotoNextMsg(); + break; + + case KK_ReadGotoFirstMsg: + GotoFirstMsg(); + break; + + case KK_ReadGotoLastMsg: + GotoLastMsg(); + break; + + case KK_ReadGotoReplies: + GotoReplies(); + break; + + case KK_ReadGotoReply1st: + GotoReply1st(); + break; + + case KK_ReadGotoReplyNext: + GotoReplyNext(); + break; + + case KK_ReadGotoReplyPrev: + GotoReplyPrev(); + break; + + case KK_ReadGotoNextUnread: + GotoNextUnread(); + break; + + case KK_ReadGotoPrevUnread: + GotoPrevUnread(); + break; + + case KK_ReadToggleHiddKlud: + ToggleHiddKlud(); + break; + + case KK_ReadToggleKludge: + ToggleKludge(); + break; + + case KK_ReadToggleHidden: + ToggleHidden(); + break; + + case KK_ReadToggleQuote: + ToggleQuote(); + break; + + case KK_ReadToggleROT13: + ToggleROT13(); + break; + + case KK_ReadTogglePageBar: + TogglePageBar(); + break; + + case KK_ReadToggleRealMsgno: + ToggleRealMsgno(); + break; + + case Key_0: + case Key_1: + case Key_2: + case Key_3: + case Key_4: + case Key_5: + case Key_6: + case Key_7: + case Key_8: + case Key_9: + case KK_ReadGotoMsgno: + GotoMsgno(); + break; + + case KK_ReadMessageList: + MessageBrowse(); + break; + + case KK_ReadThreadtree: + MsgThreadlist(); + break; + + case KK_ReadDosShell: + DosShell(); + reader_keyok = YES; + break; + + case KK_ReadFindAll: + FindAll(msg, reader_topline, reader_keyok); + break; + + case KK_ReadFindHeader: + FindHdr(msg, reader_topline, reader_keyok); + break; + + case KK_ReadSearch: + AdvancedSearch(msg, reader_topline, reader_keyok); + break; + + case KK_ReadFileRequest: + FileRequest(msg); + break; + + case KK_ReadNewMsg: + NewMsg(); + break; + + case KK_ReadMoveQuoteMsg: + OtherAreaQuoteMsg(); + break; + + case KK_ReadMoveCommentMsg: + OtherAreaCommentMsg(); + break; + + case KK_ReadQuoteBuf: + QuoteBuf(msg); + break; + + case KK_ReadQuoteMsg: + QuoteMsg(); + break; + + case KK_ReadCommentMsg: + CommentMsg(); + break; + + case KK_ReadReplyMsg: + ReplyMsg(); + break; + + case KK_ReadChangeMsg: + ChangeMsg(); + break; + + case KK_ReadCopyMoveForward: + CopyMoveForward(); + break; + + case KK_ReadDeleteMsg: + AA->DelMsg(); + break; + + case KK_ReadMakeUserlist: + MakeUserList(); + break; + + case KK_ReadMakePathreport: + MakePathreport(); + break; + + case KK_ReadWriteMsg: + WriteMsg(msg); + break; + + case KK_ReadMarkingOptions: + MarkingOptions(); + break; + + case KK_ReadGotoPrevArea: + PrevArea(); + break; + + case KK_ReadGotoNextArea: + NextArea(); + break; + + case KK_ReadQuitNow: + QuitNow(); + break; + + case KK_ReadAskExit: + ExitAsk(); + break; + + case KK_ReadNewArea: + NewArea(); + break; + + case KK_ReadTouchNetscan: + TouchNetscan(); + reader_keyok = true; + break; + + case KK_ReadTouchSemaphore: + TouchSemaphore(); + reader_keyok = true; + break; + + case KK_ReadExternUtilMenu: + ExternUtilMenu(); + break; + + case KK_ReadAddressbookAdd: + { + GMenuDomarks MenuDomarks; + + int source = AA->Mark.Count() ? MenuDomarks.Run(LNG->Addressbook) : WRITE_CURRENT; + if(source != WRITE_QUIT) { + if(source == WRITE_MARKED) { + for(uint n=0; nMark.Count(); n++) { + AA->LoadMsg(msg, AA->Mark[n], CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + update_addressbook(msg, true, true); + } + } + else // Write current + update_addressbook(msg, true, true); + } + } + break; + + case KK_ReadUserbase: + edit_addressbook(msg); + break; + + case KK_ReadUUDecode: + UUDecode(msg); + break; + + case KK_ExternUtil01: reader_keyok = ExternUtil(msg, 1); break; + case KK_ExternUtil02: reader_keyok = ExternUtil(msg, 2); break; + case KK_ExternUtil03: reader_keyok = ExternUtil(msg, 3); break; + case KK_ExternUtil04: reader_keyok = ExternUtil(msg, 4); break; + case KK_ExternUtil05: reader_keyok = ExternUtil(msg, 5); break; + case KK_ExternUtil06: reader_keyok = ExternUtil(msg, 6); break; + case KK_ExternUtil07: reader_keyok = ExternUtil(msg, 7); break; + case KK_ExternUtil08: reader_keyok = ExternUtil(msg, 8); break; + case KK_ExternUtil09: reader_keyok = ExternUtil(msg, 9); break; + case KK_ExternUtil10: reader_keyok = ExternUtil(msg, 10); break; + case KK_ExternUtil11: reader_keyok = ExternUtil(msg, 11); break; + case KK_ExternUtil12: reader_keyok = ExternUtil(msg, 12); break; + case KK_ExternUtil13: reader_keyok = ExternUtil(msg, 13); break; + case KK_ExternUtil14: reader_keyok = ExternUtil(msg, 14); break; + case KK_ExternUtil15: reader_keyok = ExternUtil(msg, 15); break; + case KK_ExternUtil16: reader_keyok = ExternUtil(msg, 16); break; + case KK_ExternUtil17: reader_keyok = ExternUtil(msg, 17); break; + case KK_ExternUtil18: reader_keyok = ExternUtil(msg, 18); break; + case KK_ExternUtil19: reader_keyok = ExternUtil(msg, 19); break; + case KK_ExternUtil20: reader_keyok = ExternUtil(msg, 20); break; + case KK_ExternUtil21: reader_keyok = ExternUtil(msg, 21); break; + case KK_ExternUtil22: reader_keyok = ExternUtil(msg, 22); break; + case KK_ExternUtil23: reader_keyok = ExternUtil(msg, 23); break; + case KK_ExternUtil24: reader_keyok = ExternUtil(msg, 24); break; + + case KK_AreaShowDel: + CFG->showdeleted = not CFG->showdeleted; + reader_keyok = true; + break; + + case KK_ReadUndefine: + reader_keyok = true; + break; + + default: + if(not PlayMacro(reader_keycode, KT_R)) { + SayBibi(); + reader_keyok = true; + } + } + } while(reader_keyok); + } + + if(gkbd.quitall) + break; + + } while(not reader_done); + + if(AA->isopen()) + AA->Close(); + + } while(not reader_finished and not gkbd.quitall); + + HeaderView->Destroy(); + BodyView->Destroy(); + } + + ResetMsg(msg); + throw_free(msg); + + HandleGEvent(EVTT_EXIT); +} + + +// ------------------------------------------------------------------ +// Determine if the message has replies + +ulong MsgHasReplies(GMsg* msg) { + + if(msg->link.first()) + return msg->link.first(); + + for(int n=0; nlink.list_max(); n++) + if(msg->link.list(n)) + return msg->link.list(n); + + if(msg->link.next()) + return msg->link.next(); + + return 0; +} + + +// ------------------------------------------------------------------ +// Determine if the message is of the "twit" type + +int MsgIsTwit(GMsg* msg, bool& istwitto, bool& istwitsubj) { + + bool istwit = false; + istwitto = istwitsubj = false; + + // Check for twit names + vector::iterator tn; + for(tn = CFG->twitname.begin(); tn != CFG->twitname.end(); tn++) { + if(msg->orig.match(tn->addr)) { + if(*tn->name == NUL or strwild(msg->By(), tn->name)) { + istwit = true; + break; + } + } + if(CFG->switches.get(twitto)) { + if(msg->dest.match(tn->addr)) { + if(*tn->name == NUL or strwild(msg->To(), tn->name)) { + istwitto = true; + istwit = true; + break; + } + } + } + } + + // Check for twit subjects + if(not istwit) { + gstrarray::iterator n; + for(n = CFG->twitsubj.begin(); n != CFG->twitsubj.end(); n++) { + if(striinc(n->c_str(), msg->re)) { + istwitsubj = true; + istwit = true; + break; + } + } + } + + if(not istwit) + return NOT_TWIT; + + if(AA->Twitmode() == TWIT_BLANK) + return TWIT_BLANK; + + if(AA->Twitmode() == TWIT_KILL) + return TWIT_KILL; + + if(AA->Twitmode() == TWIT_IGNORE) + return TWIT_SKIP; + + if((AA->Twitmode() == TWIT_SKIP) and not msg->attr.tou()) + return TWIT_SKIP; + + return TWIT_SHOW; +} + + +// ------------------------------------------------------------------ + +int LoadMessage(GMsg* msg, int margin) { + + GFTRK("LoadMessage"); + + if(AA->LoadMsg(msg, AA->Msgn.CvtReln(AA->lastread()), margin)) { + + // Mark message as received, if it is for us + if(msg->msgno and not AA->attr().hex()) { + for(vector::iterator n = CFG->username.begin(); n != CFG->username.end(); n++) { + // Check TO: + if(msg->dest.match(n->addr)) { + if(strieql(n->name, msg->To())) { + if(n->addr.net != GFTN_ALL or msg->dest.net == 0 or not AA->isnet()) + msg->attr.tou1(); // Set highlight mark + else { + for(vector::iterator x = CFG->aka.begin(); x != CFG->aka.end(); x++) { + if(msg->dest.match(x->addr)) { + msg->attr.tou1(); // Set highlight mark + break; + } + } + } + } + } + + // Check FROM: + if(msg->orig.match(n->addr)) { + if(strieql(n->name, msg->by)) { + if(n->addr.net != GFTN_ALL or msg->orig.net == 0 or not AA->isnet()) + msg->attr.fmu1(); // Set highlight mark + else { + for(vector::iterator x = CFG->aka.begin(); x != CFG->aka.end(); x++) { + if(msg->orig.match(x->addr)) { + msg->attr.fmu1(); // Set highlight mark + break; + } + } + } + } + } + } + + if(*AA->Internetaddress()) { + if(strieql(msg->to, AA->Internetaddress()) or strieql(msg->idest, AA->Internetaddress())) + msg->attr.tou1(); + } + + if(msg->attr.tou()) { + reader_rcv_noise = 1; + if(not msg->attr.rcv()) { // Have we seen it? + time_t a = time(NULL); + time_t b = mktime(gmtime(&a)); + msg->received = a + a - b; // Get current date + msg->attr.rcv1(); // Mark as received + reader_rcv_noise++; + } + else if(not CFG->switches.get(rcvdisablescfm)) + reader_rcv_noise++; + } + + // Touch the msg if it's the first time received + if(reader_rcv_noise > 1) + msg->attr.upd1(); // Tell SaveHdr to "touch" the time stamp of the *.MSG file + + // Update the "Times Read" field + msg->orig_timesread = msg->timesread++; + + if(reader_rcv_noise > 1) + AA->SaveHdr(GMSG_UPDATE, msg); + + msg->attr.upd0(); + + if((reader_rcv_noise > 1) and AA->isnet() and (msg->attr.cfm() or msg->attr.rrq())) + reader_gen_confirm = true; + } + } + else { + msg->txt = throw_strdup(""); + } + + GFTRK(NULL); + return true; +} + + +// ------------------------------------------------------------------ + +uint next_msg(int direction) { + + uint relno = 0; + + if(direction == DIR_NEXT) { + if(AA->lastread() < AA->Msgn.Count()) { + AA->set_lastread(AA->lastread()+1); + relno = AA->lastread(); + } + } + else { + if(1 < AA->lastread()) { + AA->set_lastread(AA->lastread()-1); + relno = AA->lastread(); + } + } + return relno; +} + + +// ------------------------------------------------------------------ + +void ToggleMarkRead() { + + if(AA->PMrk.Tags()) { + AA->isreadpm = not AA->isreadpm; + if(AA->isreadpm) { + bool is_marked = false; + if(AA->PMrk.Find(reader_msg->msgno)) + is_marked = true; + if(not is_marked) + NextMarkedmsg(reader_direction, reader_msg); + } + } + else if(AA->Mark.Count()) { + AA->isreadmark = not AA->isreadmark; + if(AA->isreadmark) { + bool is_marked = false; + if(AA->Mark.Find(reader_msg->msgno)) + is_marked = true; + if(not is_marked) + NextMarkedmsg(reader_direction, reader_msg); + } + } + else if(AA->isreadmark) + AA->isreadmark = false; + else + reader_keyok = true; +} + + +// ------------------------------------------------------------------ + +void GotoBookMark() { + + if(AA->bookmark) { + ulong temp = reader_msg->msgno; + AA->set_lastread(AA->Msgn.ToReln(AA->bookmark)); + AA->bookmark = temp; + } + else { + reader_keyok = true; + SayBibi(); + } +} + + +// ------------------------------------------------------------------ + +void GoNextMsg() { + + GMenuNewarea MenuNewarea; + int mode; + + if(AA->isreadmark or AA->isreadpm) { + if(not NextMarkedmsg(reader_direction, reader_msg)) { + if((mode = MenuNewarea.Run()) != 0) { + NewArea(mode == 2); + return; + } + reader_keyok = true; + } + } + else if(not next_msg(reader_direction)) { + if((mode = MenuNewarea.Run())!=0) { + if(AA->Msgn.ToReln(reader_msg->msgno) == 1) + if(reader_direction == DIR_PREV) + AA->set_lastread(0); + NewArea(mode == 2); + return; + } + reader_keyok = true; + } +} + + +// ------------------------------------------------------------------ + +void GotoPrevMsg() { + + reader_direction = DIR_PREV; + GoNextMsg(); +} + + +// ------------------------------------------------------------------ + +void GotoNextMsg() { + + reader_direction = DIR_NEXT; + GoNextMsg(); +} + + +// ------------------------------------------------------------------ + +void GotoFirstMsg() { + + reader_direction = DIR_NEXT; + if(AA->isreadpm) + AA->set_lastread(AA->PMrk.ToReln(AA->PMrk[0])); + else if(AA->isreadmark) + AA->set_lastread(AA->Msgn.ToReln(AA->Mark[0])); + else + AA->set_lastread(AA->Msgn.Count() ? 1 : 0); +} + + +// ------------------------------------------------------------------ + +void GotoLastMsg() { + + reader_direction = DIR_PREV; + if(AA->isreadpm) + AA->set_lastread(AA->Msgn.ToReln(AA->PMrk[AA->PMrk.Tags()-1])); + else if(AA->isreadmark) + AA->set_lastread(AA->Msgn.ToReln(AA->Mark[AA->Mark.Count()-1])); + else + AA->set_lastread(AA->Msgn.Count()); +} + + +// ------------------------------------------------------------------ + +struct ReplySel { + uint reln; + char isread; + char msgno[12]; + Name name; + Name addr; + char written[25]; +}; + + +// ------------------------------------------------------------------ + +void GotoReplies() { + + reader_direction = DIR_NEXT; + + GMsg* msg = reader_msg; + const int list_max = msg->link.list_max(); + + char buf[200]; + int replies = 0; + int cursorbar = -1; + uint maxname = 0; + uint maxaddr = 0; + uint gotolink = 0; + uint maxmsgno = 0; + uint maxwritten = 0; + + GMsg* rmsg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + ReplySel* rlist = (ReplySel*)throw_calloc(list_max+3, sizeof(ReplySel)); + + for(int n=0; nlink.list(n-1) : msg->link.next()) : msg->link.first(); + uint reln = AA->Msgn.ToReln(msgn); + if(reln) { + if(CFG->replylinklist == REPLYLINKLIST_FULL) + AA->LoadMsg(rmsg, msgn, CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + else + AA->LoadHdr(rmsg, msgn); + rlist[replies].isread = ((0 == rmsg->timesread) and CFG->switches.get(highlightunread)) ? '\x10' : ' '; + if((cursorbar == -1) and (0 == rmsg->timesread) and (CFG->switches.get(highlightunread))) + cursorbar = replies; + rlist[replies].msgno[0] = (n==list_max+1) ? '*' : '+'; + ulong msgno = CFG->switches.get(disprealmsgno) ? msgn : reln; + sprintf(rlist[replies].msgno+1, "%lu", msgno); + maxmsgno = MaxV(maxmsgno, (uint)strlen(rlist[replies].msgno+1)); + strcpy(rlist[replies].name, rmsg->by); + maxname = MaxV(maxname, (uint)strlen(rlist[replies].name)); + if(not AA->isinternet()) { + rmsg->orig.make_string(buf); + if(*buf) + sprintf(rlist[replies].addr, " (%s) ", buf); + } + maxaddr = MaxV(maxaddr, (uint)strlen(rlist[replies].addr)); + strftimei(rlist[replies].written, CFG->disphdrdateset.len, LNG->DateTimeFmt, gmtime(&rmsg->written)); + maxwritten = MaxV(maxwritten, (uint)strlen(rlist[replies].written)); + rlist[replies].reln = reln; + replies++; + if(gotolink == 0) + gotolink = reln; + } + } + ResetMsg(rmsg); + throw_free(rmsg); + + int selected = 0; + if(replies > 1) { + uint maxname2 = MAXCOL-16-maxmsgno-maxaddr-maxwritten; + maxname = MinV(maxname, maxname2); + char** listr = (char**)throw_calloc(list_max+3, sizeof(char*)); + int n; + for(n=0; nReplies, TCENTER, C_ASKT); + update_statusline(LNG->SelectReply); + whelppcat(H_GotoReplies); + int pick_max = MinV(replies, (MAXROW-10)); + if(cursorbar < 0) + cursorbar = 0; + selected = wpickstr(6, 0, 6+pick_max+1, -1, W_BASK, C_ASKB, C_ASKW, C_ASKS, listr, cursorbar, title_shadow); + whelpop(); + gotolink = (selected != -1) ? rlist[selected].reln : 0; + for(n=0; nset_lastread(gotolink); + else { + if(selected != -1) + SayBibi(); + reader_keyok = true; + } +} + + +// ------------------------------------------------------------------ + +void GotoReply1st() { + + reader_direction = DIR_NEXT; + uint gotolink = AA->Msgn.ToReln(reader_msg->link.first()); + if(gotolink) + AA->set_lastread(gotolink); + else { + SayBibi(); + reader_keyok = true; + } +} + + +// ------------------------------------------------------------------ + +void GotoReplyNext() { + + reader_direction = DIR_NEXT; + uint gotolink = AA->Msgn.ToReln(reader_msg->link.next()); + if(gotolink) + AA->set_lastread(gotolink); + else { + SayBibi(); + reader_keyok = true; + } +} + + +// ------------------------------------------------------------------ + +void GotoReplyPrev() { + + reader_direction = DIR_PREV; + uint gotolink = AA->Msgn.ToReln(reader_msg->link.to()); + if(gotolink) + AA->set_lastread(gotolink); + else { + SayBibi(); + reader_keyok = true; + } +} + + +// ------------------------------------------------------------------ + +void GotoPrevUnread() { + + reader_direction = DIR_PREV; + w_info(LNG->Wait); + + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + bool found = false; + int prev = AA->lastread(); + while(1 < prev) { + prev--; + AA->LoadHdr(msg, AA->Msgn.CvtReln(prev)); + if(msg->timesread == 0) { + AA->set_lastread(prev); + found = true; + break; + } + } + + ResetMsg(msg); + throw_free(msg); + + if(not found) { + SayBibi(); + reader_keyok = true; + } + w_info(NULL); +} + + +// ------------------------------------------------------------------ + +void GotoNextUnread() { + + w_info(LNG->Wait); + reader_direction = DIR_NEXT; + + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + bool found = false; + int count = AA->Msgn.Count(); + int next = AA->lastread(); + while(next < count) { + next++; + AA->LoadHdr(msg, AA->Msgn.CvtReln(next)); + if(msg->timesread == 0) { + AA->set_lastread(next); + found = true; + break; + } + } + + ResetMsg(msg); + throw_free(msg); + + if(not found) { + SayBibi(); + reader_keyok = true; + } + w_info(NULL); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/geread2.cpp b/golded3/geread2.cpp new file mode 100644 index 0000000..e662755 --- /dev/null +++ b/golded3/geread2.cpp @@ -0,0 +1,814 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Reader secondary functions +// ------------------------------------------------------------------ + +#include +#include +#include +#include +#define PROTOTYPES +#include + + +// ------------------------------------------------------------------ +// Global data from GEREAD + +extern GMsg* reader_msg; + + +// ------------------------------------------------------------------ + +void ChangeAttributes() { + + if(reader_msg->msgno) { + + // Reload if hexdumped + if(AA->attr().hex()) { + AA->attr().hex0(); + AA->LoadMsg(reader_msg, reader_msg->msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + } + + GMsg* msg = (GMsg*)throw_malloc(sizeof(GMsg)); + memcpy(msg, reader_msg, sizeof(GMsg)); + AskAttributes(reader_msg); + if(memcmp(msg, reader_msg, sizeof(GMsg))) { + msg->charsetlevel = LoadCharset(CFG->xlatlocalset, msg->charset); + DoKludges(MODE_CHANGE, reader_msg, true); + reader_msg->LinesToText(); + AA->SaveMsg(GMSG_UPDATE, reader_msg); + } + throw_free(msg); + } +} + + +// ------------------------------------------------------------------ + +void DecMargin() { + + if(CFG->dispmargin > (MAXCOL/3)) + CFG->dispmargin--; + else { + SayBibi(); + reader_keyok = YES; + } +} + + +// ------------------------------------------------------------------ + +void IncMargin() { + + if(CFG->dispmargin < MAXCOL) + CFG->dispmargin++; + else { + SayBibi(); + reader_keyok = YES; + } +} + +// ------------------------------------------------------------------ + +void ToggleMark() { + + uint tmp = AA->Mark.Find(reader_msg->msgno); + if(tmp) + AA->Mark.DelReln(tmp); + else + AA->Mark.Add(reader_msg->msgno); + HeaderView->Use(AA, reader_msg); + HeaderView->Paint(); + reader_keyok = YES; +} + + +// ------------------------------------------------------------------ + +void ToggleBookMark() { + + if(AA->bookmark == reader_msg->msgno) + AA->bookmark = 0; + else + AA->bookmark = reader_msg->msgno; + HeaderView->Use(AA, reader_msg); + HeaderView->Paint(); + reader_keyok = YES; +} + + +// ------------------------------------------------------------------ + +void ToggleHiddKlud() { + + AA->ToggleViewhidden(); + AA->ToggleViewkludge(); + MsgLineReIndex(reader_msg); + reader_topline = 0; + reader_keyok = YES; +} + + +// ------------------------------------------------------------------ + +void ToggleKludge() { + + AA->ToggleViewkludge(); + MsgLineReIndex(reader_msg); + reader_topline = 0; + reader_keyok = YES; +} + + +// ------------------------------------------------------------------ + +void ToggleHidden() { + + AA->ToggleViewhidden(); + MsgLineReIndex(reader_msg); + reader_topline = 0; + reader_keyok = YES; +} + + +// ------------------------------------------------------------------ + +void ToggleQuote() { + + AA->ToggleViewquote(); + MsgLineReIndex(reader_msg); + reader_topline = 0; + reader_keyok = YES; +} + + +// ------------------------------------------------------------------ + +void ToggleROT13() { + + if(AA->Msgn.Count()) { + reader_msg->attr.rotX(); + Rot13(reader_msg); + reader_keyok = YES; + } +} + + +// ------------------------------------------------------------------ + +void TogglePageBar() { + + CFG->switches.set(disppagebar, not CFG->switches.get(disppagebar)); +} + + +// ------------------------------------------------------------------ + +void ToggleRealMsgno() { + + CFG->switches.set(disprealmsgno, not CFG->switches.get(disprealmsgno)); + HeaderView->Use(AA, reader_msg); + HeaderView->Paint(); + reader_keyok = YES; +} + + +// ------------------------------------------------------------------ + +void ToggleTwits() { + + gkey k; + + do { + switch(AA->Twitmode()) { + case TWIT_SHOW: + AA->SetTwitmode(TWIT_BLANK); + w_info(LNG->TwitBlanked); + break; + case TWIT_BLANK: + AA->SetTwitmode(TWIT_SKIP); + w_info(LNG->TwitSkipped); + break; + case TWIT_SKIP: + AA->SetTwitmode(TWIT_IGNORE); + w_info(LNG->TwitIgnoreSkip); + break; + case TWIT_IGNORE: + AA->SetTwitmode(TWIT_KILL); + w_info(LNG->TwitKilled); + break; + case TWIT_KILL: + AA->SetTwitmode(TWIT_SHOW); + w_info(LNG->TwitDisplayed); + break; + } + + k = waitkeyt(3000); + + } while(k and k != Key_Ent and k != Key_Esc); + + w_info(NULL); + + if(k == Key_Esc) + AA->SetTwitmode(CFG->twitmode); + else + CFG->twitmode = AA->Twitmode(); +} + + +// ------------------------------------------------------------------ + +void ToggleStyles() { + + gkey k; + int setting = CFG->usestylies + CFG->hidestylies*2; + + do { + switch(setting) { + case 2: + case 0: w_info(LNG->StylecodesYes); setting = 1; break; + case 1: w_info(LNG->StylecodesHide); setting = 3; break; + case 3: w_info(LNG->StylecodesNo); setting = 0; break; + } + k = waitkeyt(3000); + } while (k and k != Key_Ent and k != Key_Esc); + w_info(NULL); + + if(k != Key_Esc) { + CFG->usestylies = (setting & 1) ? true : false; + CFG->hidestylies = (setting & 2) ? true : false; + } +} + + +// ------------------------------------------------------------------ + +void GotoMsgno() { + + if(AA->Msgn.Count()) { + + // Set the active window + int lastwh = whandle(); + int inhdr = AA->Msglistheader() or not _in_msglist; + + if(reader_keycode < KK_Macro) + if(gkbd.kbuf == NULL) + kbput(reader_keycode); // Put back the key + + char buf[150]; + char* ptr = buf; + int list_max = reader_msg->link.list_max(); + ulong* replies = (ulong*)throw_calloc(list_max+1, sizeof(ulong)); + ulong replyto, replynext; + if(CFG->switches.get(disprealmsgno)) { + ptr += sprintf(ptr, " %-5.5s: %s %u", LNG->MsgReal, LNG->of, AA->Msgn.Count()); + replyto = reader_msg->link.to(); + replies[0] = reader_msg->link.first(); + replynext = reader_msg->link.next(); + for(int replyn=1; replynlink.list(replyn-1); + } + else { + ptr += sprintf(ptr, " %-5.5s: %s %u", LNG->Msg, LNG->of, AA->Msgn.Count()); + replyto = AA->Msgn.ToReln(reader_msg->link.to()); + replies[0] = AA->Msgn.ToReln(reader_msg->link.first()); + replynext = AA->Msgn.ToReln(reader_msg->link.next()); + for(int replyn=1; replynMsgn.ToReln(reader_msg->link.list(replyn-1)); + } + if(replyto) + ptr += sprintf(ptr, " -%lu", replyto); + for(int replyn=0,plus=0; replynwindow.activate_quick(); + } + else { + wopen_(0, 0, 3, strlen(buf)+3, W_BHEAD, C_HEADB, C_HEADW); + w_shadow(); + wtitle(LNG->EnterMsgno, TCENTER, C_HEADT); + } + + int wrow = inhdr ? 1 : 0; + wprints(wrow, 0, C_HEADW, buf); + *buf = NUL; + + gwindow iwindow(whandle()); + + string fbuf = buf; + gwinput2 iform(iwindow); + iform.setup(C_HEADW, C_HEADW, C_HEADI, _box_table(W_BHEAD, 13), true); + iform.add_field(0, wrow, 8, 5, fbuf, 20, gwinput::cvt_none, gwinput::entry_new); + vcurshow(); + iform.run(H_InputMsgno); + vcurhide(); + if(iform.dropped) + fbuf = ""; + + long active = AA->Msgn.Count(); + long msgno = atol(fbuf.c_str()); + + if(CFG->switches.get(disprealmsgno)) + if(msgno > 0) + msgno = AA->Msgn.ToReln(msgno); + + if((msgno < 0) and ((active+msgno) > 0)) + msgno = active + msgno; + + if(RngV(msgno, 1L, active)) + AA->set_lastread((uint)msgno); + + if(inhdr) + wactiv_(lastwh); + else + wclose(); + + throw_free(replies); + } +} + + +// ------------------------------------------------------------------ + +void PrevArea() { + + AA->attr().hex0(); + AA->Close(); + int currarea = AL.AreaIdToNo(CurrArea); + int testarea = currarea; + while(testarea > 0) { + testarea--; + if(not AL[testarea]->isseparator()) { + currarea = testarea; + break; + } + } + if(currarea == testarea) { + AL.SetActiveAreaNo(currarea); + OrigArea = CurrArea; + } + else + HandleGEvent(EVTT_ENDOFMSGS); + AA->Open(); + AA->RandomizeData(); + AA->SetBookmark(AA->lastread()); + if(AA->PMrk.Tags()) { + AA->isreadpm = false; + ToggleMarkRead(); + } +} + + +// ------------------------------------------------------------------ + +void NextArea() { + + AA->attr().hex0(); + AA->Close(); + uint currarea = AL.AreaIdToNo(CurrArea); + uint testarea = currarea; + while(testarea < (AL.size()-1)) { + testarea++; + if(not AL[testarea]->isseparator()) { + currarea = testarea; + break; + } + } + if(currarea == testarea) { + AL.SetActiveAreaNo(currarea); + OrigArea = CurrArea; + } + else + HandleGEvent(EVTT_ENDOFMSGS); + AA->Open(); + AA->RandomizeData(); + AA->SetBookmark(AA->lastread()); + if(AA->PMrk.Tags()) { + AA->isreadpm = false; + ToggleMarkRead(); + } + +} + + +// ------------------------------------------------------------------ + +void QuitNow() { + + AA->attr().hex0(); + reader_finished = YES; + reader_done = YES; +} + + +// ------------------------------------------------------------------ + +void ExitAsk() { + + AA->attr().hex0(); + GMenuQuit MenuQuit; + reader_done = reader_finished = MenuQuit.Run(); +} + + +// ------------------------------------------------------------------ + +void NewArea(bool jumpnext) { + + AA->attr().hex0(); + if(AA->isopen()) + AA->Close(); + + int newarea = CurrArea; + + if(jumpnext) { + uint idx = AL.AreaIdToNo(CurrArea); + uint oidx = idx; + + do { + idx++; + + // Wrap around + if(idx >= AL.size()) + idx = 0; + + // Exit loop if no area with new mail found + if(idx == oidx) { + newarea = AreaPick(LNG->NewArea, 0, &newarea); + if(newarea != -1) + idx = AL.AreaIdToNo(newarea); + break; + } + + } while(AL.AreaNoToPtr(idx)->unread == 0); + + CurrArea = AL.AreaNoToId(idx); + } + else { + newarea = AreaPick(LNG->NewArea, 0, &newarea); + if(newarea != -1) + CurrArea = newarea; + } + + AL.Sort(); + reader_done = YES; + + if(gkbd.quitall) + QuitNow(); + else { + AL.SetActiveAreaId(CurrArea); + OrigArea = CurrArea; + strcpy(stecho, AA->echoid()); + AA->RandomizeData(); + if(AA->Msglistfirst()) + kbput(KK_ReadMessageList); + } +} + + +// ------------------------------------------------------------------ + +void DosShell() { + + ShellToDos(getenv(GOLD_SHELL_ENV), LNG->DOS_Shell, LGREY|_BLACK, YES); +} + + +// ------------------------------------------------------------------ + +void TouchNetscan(int popup) { + + FILE* fp = fsopen(AddPath(CFG->areapath, CFG->semaphore.netscan), "wb", CFG->sharemode); + if(fp) { + fclose(fp); + if(popup) { + w_infof(" %s ", CFG->semaphore.netscan); + HandleGEvent(EVTT_JOBDONE); + waitkeyt(10000); + w_info(NULL); + } + } +} + + +// ------------------------------------------------------------------ + +int ExternUtil(GMsg* msg, int utilno) { + + Path editorfile, tmpfile; + strcpy(editorfile, AddPath(CFG->goldpath, EDIT->File())); + mktemp(strcpy(tmpfile, AddPath(CFG->goldpath, "GDXXXXXX"))); + + vector::iterator extutil = CFG->externutil.begin(); + + for(int utlno=0; extutil != CFG->externutil.end(); utlno++, extutil++) { + + if(extutil->utilno == utilno) { + + char cmdline[256], buf[256]; + strcpy(cmdline, extutil->cmdline); + + int mode = (extutil->options & EXTUTIL_KEEPCTRL) ? MODE_SAVE : MODE_SAVENOCTRL; + SaveLines(mode, editorfile, msg); + if(striinc("@tmpfile", cmdline)) + SaveLines(mode, tmpfile, msg); + + strcpy(buf, CFG->goldpath); + strchg(buf, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); + strischg(cmdline, "@path", buf); + strcpy(buf, editorfile); + strchg(buf, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); + strischg(cmdline, "@file", buf); + strcpy(buf, tmpfile); + strchg(buf, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); + strischg(cmdline, "@tmpfile", buf); + TokenXlat(MODE_NEW, cmdline, msg, msg, CurrArea); + + int pauseval = 0; + if(extutil->options & EXTUTIL_PAUSEONERROR) + pauseval = -1; + if(extutil->options & EXTUTIL_PAUSE) + pauseval = 1; + + ShellToDos(cmdline, "", + extutil->options & EXTUTIL_CLS ? LGREY|_BLACK : 0, + extutil->options & EXTUTIL_CURSOR, + extutil->options & EXTUTIL_SWAP, + pauseval + ); + + if(extutil->options & EXTUTIL_RELOAD) { + + if(not (extutil->options & EXTUTIL_KEEPCTRL)) { + if(*msg->tearline or *msg->origin) { + gfile fp; + fp.fopen(editorfile, "at"); + if(fp.isopen()) { + if(*msg->tearline) + fp.printf("--- %s\n", msg->tearline); + if(*msg->origin) + fp.printf(" * Origin: %s\n", msg->origin); + fp.fclose(); + } + } + } + + int hardlines = EDIT->HardLines(); + EDIT->HardLines(false); + LoadText(msg, editorfile); + if(extutil->options & EXTUTIL_WIPE) + WipeFile(editorfile, 0); + WipeFile(tmpfile, 0); + + EDIT->HardLines(hardlines); + msg->attr.tou1(); // Ignore any kludge address found + msg->TextToLines(CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + msg->attr.tou0(); + } + + return YES; + } + } + + SayBibi(); + return YES; +} + + +// ------------------------------------------------------------------ + +void ExternUtilMenu() { + + // Not implemented yet +} + + +// ------------------------------------------------------------------ + +void UUDecode(GMsg* msg) { + + Path infile, outfile; + bool ok = false; + + if((*CFG->uudecodepath == NUL) or is_dir(CFG->uudecodepath)) { + + mktemp(strcpy(infile, AddPath(CFG->goldpath, "GDXXXXXX"))); + strcpy(outfile, CFG->uudecodepath); + + GMenuDomarks MenuDomarks; + + int source = AA->Mark.Count() ? MenuDomarks.Run(LNG->Decode) : WRITE_CURRENT; + bool overwrite = true; + + if(source == WRITE_QUIT) + return; + + if(source == WRITE_MARKED) { + for(uint n=0; nMark.Count(); n++) { + if(overwrite and n) + overwrite = false; // Overwrite only the first time + w_progress(MODE_UPDATE, C_INFOW, n+1, AA->Mark.Count(), LNG->Preparing); + AA->LoadMsg(msg, AA->Mark[n], 79); + SaveLines(overwrite ? MODE_WRITE : MODE_APPEND, infile, msg); + } + if(AA->Mark.Count()) + w_progress(MODE_QUIT, 0, 0, 0, NULL); + } + else if(source == WRITE_CURRENT) + SaveLines(MODE_WRITE, infile, msg); + + uulist* item; + int i, res; + + w_info(LNG->WaitUUdecoding); + + UUInitialize(); + UUSetOption(UUOPT_SAVEPATH, 0, outfile); + if((res = UULoadFile(infile, NULL, 0)) == UURET_OK) { + + for (i=0; (item=UUGetFileListItem(i)) != NULL; i++) { + if ((item->state & UUFILE_OK) == 0) + continue; + if ((res = UUDecodeFile(item, NULL)) == UURET_OK) { + ok = true; + w_infof(LNG->CompletedUUdecode, item->filename); + } + } + } + UUCleanUp (); + + remove(infile); + + if(not ok) + w_info(LNG->NotUUencoded); + } + else + w_info(LNG->UUEinvalidpath); + + if(not ok) + waitkeyt(10000); + + w_info(NULL); +} + + +// ------------------------------------------------------------------ + +void Make_Userlist(const char* userlist) { + + FILE* fp; + word* crclist; + word crc, crcs=0; + uint n, x; + char userline[80], adrs[40]; + + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + crclist = (word*)throw_calloc(AA->Msgn.Count()+1, sizeof(word)); + fp = fsopen(userlist, "ab", CFG->sharemode); + if(fp) { + w_progress(MODE_NEW, C_INFOW, 0, AA->Msgn.Count(), LNG->GenUserlist); + for(n=AA->Msgn.Count(); n; n--) { + update_statuslinef(LNG->ReadingMsg, n, AA->Msgn.Count()); + w_progress(MODE_UPDATE, C_INFOW, (AA->Msgn.Count()-n)+1, AA->Msgn.Count(), NULL); + AA->LoadMsg(msg, AA->Msgn.CvtReln(n), CFG->dispmargin); + crc = strCrc16(msg->by, false); + for(x=0; x= crcs) { + crclist[crcs++] = crc; + strrevname(userline, msg->by); + msg->orig.make_string(adrs); + fprintf(fp, "%-36.36s%24.24s\r\n", userline, adrs); + } + } + throw_free(crclist); + w_progress(MODE_QUIT, 0, 0, 0, NULL); + fclose(fp); + } + + ResetMsg(msg); + throw_free(msg); +} + + +// ------------------------------------------------------------------ + +void MakeUserList() { + + if(AA->Msgn.Count()) { + uint temp = AA->lastread(); + if(not edit_pathname(CFG->userlistfile, sizeof(Path), LNG->UserlistName, 0)) + return; + Make_Userlist(AddPath(CFG->goldpath, CFG->userlistfile)); + AA->set_lastread(temp); + } +} + + +// ------------------------------------------------------------------ + +void TouchSemaphore() { + + Path file; + *file = NUL; + if(edit_string(file, sizeof(Path), LNG->TouchSemaphore, 0)) + TouchFile(file); +} + + +// ------------------------------------------------------------------ + +void make_pathreport(const char* reportfile) { + + gfile fp; + fp.fopen(reportfile, "wt"); + if(fp) { + string path; + ftn_addr address; + vector alist; + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + w_progress(MODE_NEW, C_INFOW, 0, AA->Msgn.Count(), "Generating PATH report"); + for(int n=AA->Msgn.Count(); n>=AA->lastread(); n--) { + update_statuslinef(LNG->ReadingMsg, n, AA->Msgn.Count()); + w_progress(MODE_UPDATE, C_INFOW, n, AA->Msgn.Count(), NULL); + AA->LoadMsg(msg, AA->Msgn.CvtReln(n), CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + address = msg->orig; + int x; + for(x=0; x= alist.size()) { + alist.push_back(address); + INam buf; + strcpy(buf, msg->By()); + strchg(buf, ' ', '_'); + string temp; + fp.printf("%s %s ", buf, address.make_string(temp).c_str()); + path = ""; + Line* line = msg->lin; + while(line) { + if(line->kludge == GKLUD_PATH) + path += line->text + 6; + line = line->next; + } + if(path.length()) { + gstrarray links; + tokenize(links, path.c_str(), " "); + for(int i=0; iMsgn.Count()) { + uint temp = AA->lastread(); + if(not edit_pathname(CFG->pathreportfile, sizeof(Path), LNG->Pathreport, 0)) + return; + make_pathreport(AddPath(CFG->goldpath, CFG->pathreportfile)); + AA->set_lastread(temp); + } +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gescan.cpp b/golded3/gescan.cpp new file mode 100644 index 0000000..d630c54 --- /dev/null +++ b/golded3/gescan.cpp @@ -0,0 +1,361 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Area scanning functions. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern bool in_arealist; +extern GPickArealist* PickArealist; + +// ------------------------------------------------------------------ + +void Area::UpdateAreadata() { + + if(isscanned) { + + uint _unread = Msgn.Count() - lastread(); + if(not isvalidchg) { + unread = _unread; + isvalidchg = true; + } + isunreadchg = (bool)(unread != _unread); + unread = _unread; + word oldmask = AL.mask; + AL.mask = 0; + set_marked(_unread); + AL.mask = oldmask; + } +} + + +// ------------------------------------------------------------------ + +void Area::ScanArea() { + + if(cmdlinedebughg) + LOG.printf("- ScanArea: %s", echoid()); + + area->Msgn = &Msgn; + area->PMrk = &PMrk; + + area->scan_area(); + + isscanned = true; + + UpdateAreadata(); +} + + +// ------------------------------------------------------------------ + +void Area::ScanAreaPM() { + + if(cmdlinedebughg) + LOG.printf("- ScanAreaPM: %s", echoid()); + + area->Msgn = &Msgn; + area->PMrk = &PMrk; + + area->scan_area_pm(); + + isscanned = true; + ispmscanned = true; + + UpdateAreadata(); +} + + +// ------------------------------------------------------------------ + +int AreaList::SetActiveAreaNo(int __areano) { + + AA = idx[__areano]; + CurrArea = AA->areaid(); + CFG->originno = AA->originno(); + + return CurrArea; // Return the areaid +} + + +// ------------------------------------------------------------------ + +int AreaList::AreaScan(int mode, uint currno, int pmscan, int& pmails, int& pmareas, const char* file) { + + gstrarray bag; + int groupid = -1; + + // Load scan list into a string bag + if(mode == SCAN_LIST) { + gfile fp; + Path tmp; + strcpy(tmp, file ? file : ListScan.File()); + char* listfile; + char* option=tmp; + getkeyval(&listfile, &option); + fp.fopen(AddPath(CFG->goldpath, listfile), "rt"); + if(fp.isopen()) { + char buf[512]; + while(fp.fgets(buf, sizeof(buf))) { + strbtrim(buf); + char* val = strtok(buf, ", \t"); + while(val) { + bag.push_back(val); + val = strtok(NULL, ", \t"); + } + } + fp.fclose(); + if(((*option == '-') or (*option == '/')) and strieql(option+1, "delete")) + remove(listfile); + } + } + else if(mode == SCAN_GROUP) { + groupid = idx[currno]->groupid(); + } + + int currid = AreaNoToId(currno); + + int scanned = false; + + // For optimized overlay usage, sort arealist by msgbase type, path, board and echoid + if(*CFG->areascansort) { + Sort(CFG->areascansort); + scanned = true; + } + + currno = AreaIdToNo(currid); + + #ifndef GMB_NOPCB + if(AL.msgbases & MT_PCBOARD) PcbWideOpen(); + #endif + #ifndef GMB_NOGOLD + if(AL.msgbases & MT_GOLDBASE) GoldWideOpen(); + #endif + #ifndef GMB_NOHUDS + if(AL.msgbases & MT_HUDSON) HudsWideOpen(); + #endif + #ifndef GMB_NOXBBS + if(AL.msgbases & MT_ADEPTXBBS) XbbsWideOpen(); + #endif + + for(uint n=0; nisseparator()) { + + int scanit = false; + + int dopmscan = pmscan and AA->pmscan(); + int dopmscanexcl = pmscan and AA->pmscanexcl(); + int dopmscanincl = pmscan and AA->pmscanincl(); + + int doscan = AA->scan() or dopmscan; + //if Area is excluded from pm-scanning, scan it instead + int doscanexcl = AA->scanexcl(); + int doscanincl = AA->scanincl() or dopmscanincl or (dopmscanexcl and doscan); + + if(mode != SCAN_STARTUP and pmscan) + dopmscan = true; + + switch(mode) { + case SCAN_STARTUP: + if(doscan and (not doscanexcl or doscanincl)) + scanit = true; + break; + case SCAN_ALL: + if(not doscanexcl or doscanincl) + scanit = true; + break; + case SCAN_CURRENT: + scanit = n == currno; + break; + case SCAN_MARKED: + if(AA->ismarked()) + scanit = true; + break; + case SCAN_MATCHING: + if(striinc(area_maybe, AA->echoid())) + scanit = true; + break; + case SCAN_UNSCANNED: + scanit = not (pmscan ? AA->ispmscanned : AA->isscanned); + break; + case SCAN_GROUP: + scanit = AA->groupid() == groupid; + break; + case SCAN_NETMAIL: + scanit = AA->isnet(); + break; + case SCAN_LIST: + { + gstrarray::iterator i; + for(i = bag.begin(); i != bag.end(); i++) + if(strwild(AA->echoid(), i->c_str())) { + scanit = true; + break; + } + } + break; + } + + if(scanit) { + if(not AA->isopen()) { + AA->Msgn.Reset(); + AA->Mark.ResetAll(); + AA->PMrk.ResetAll(); + } + scanned = YES; + if(not blanked) + update_statuslinef("%s %s", 1+LNG->ScanningArea, AA->echoid()); + if(dopmscan and (not dopmscanexcl or dopmscanincl)) { + AA->ScanAreaPM(); + uint count = AA->PMrk.Count(); + if(count) { + pmails += count; + pmareas++; + } + if(CFG->personalmail & PM_LISTONLY) + AA->PMrk.Reset(); + } + else { + AA->ScanArea(); + } + } + } + } + + #ifndef GMB_NOXBBS + if(AL.msgbases & MT_ADEPTXBBS) XbbsWideClose(); + #endif + #ifndef GMB_NOHUDS + if(AL.msgbases & MT_HUDSON) HudsWideClose(); + #endif + #ifndef GMB_NOGOLD + if(AL.msgbases & MT_GOLDBASE) GoldWideClose(); + #endif + #ifndef GMB_NOPCB + if(AL.msgbases & MT_PCBOARD) PcbWideClose(); + #endif + + return scanned; +} + + +// ------------------------------------------------------------------ + +void CheckSemaphores() { + + Path file; + int scanned = 0; + int pmareas = 0; + int pmails = 0; + + if(fexist(CFG->semaphore.qwkimport)) { + ImportQWK(); + remove(CFG->semaphore.qwkimport); + scanned++; + } + + if(fexist(CFG->semaphore.qwkexport)) { + ExportQWK(); + remove(CFG->semaphore.qwkexport); + } + + if(fexist(CFG->semaphore.soupimport)) { + ImportSOUP(); + remove(CFG->semaphore.soupimport); + scanned++; + } + + if(fexist(CFG->semaphore.soupexport)) { + ExportSOUP(); + remove(CFG->semaphore.soupexport); + } + + if(fexist(CFG->semaphore.exitnow) and in_arealist) { + gkbd.quitall = YES; + kbput(KK_AreaAbort); + remove(CFG->semaphore.exitnow); + } + else { + + if(fexist(CFG->semaphore.scanall)) { + scanned += AL.AreaScan(SCAN_ALL, 0, false, pmails, pmareas); + remove(CFG->semaphore.scanall); + } + + if(fexist(CFG->semaphore.scanthis)) { + sprintf(file, "%s -delete", CFG->semaphore.scanthis); + scanned += AL.AreaScan(SCAN_LIST, 0, false, pmails, pmareas, file); + } + + if(fexist(CFG->semaphore.scannetmail)) { + scanned += AL.AreaScan(SCAN_NETMAIL, 0, false, pmails, pmareas); + remove(CFG->semaphore.scannetmail); + } + + if(fexist(CFG->semaphore.pmscanall)) { + scanned += AL.AreaScan(SCAN_ALL, 0, true, pmails, pmareas); + remove(CFG->semaphore.pmscanall); + } + + if(fexist(CFG->semaphore.pmscanthis)) { + sprintf(file, "%s -delete", CFG->semaphore.pmscanthis); + scanned += AL.AreaScan(SCAN_LIST, 0, true, pmails, pmareas, file); + } + + if(fexist(CFG->semaphore.pmscannetmail)) { + scanned += AL.AreaScan(SCAN_NETMAIL, 0, true, pmails, pmareas); + remove(CFG->semaphore.pmscannetmail); + } + } + + if(scanned) { + AL.Sort(); + if(in_arealist and not blanked) { + PickArealist->update(); // update arealist-display + PickArealist->do_delayed(); // update statusline + } + AL.WriteGoldLast(); + } +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gesoup.cpp b/golded3/gesoup.cpp new file mode 100644 index 0000000..b4e9f05 --- /dev/null +++ b/golded3/gesoup.cpp @@ -0,0 +1,814 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Internet SOUP packet handling. +// ------------------------------------------------------------------ + +#include +#include +#include + + +// ------------------------------------------------------------------ + +void KludgeDATE(GMsg* msg, char* ptr); + +// ------------------------------------------------------------------ + +char* CvtMessageIDtoMSGID(char* mptr, char* msgidbuf, const char* echoid, char* kludge) { + + sprintf(msgidbuf, "\x1""%s: ", kludge); + char* bptr = msgidbuf + strlen(msgidbuf); + + if(strnieql(mptr, "isemail()) { + vector::iterator z; + for(z = CFG->mailinglist.begin(); z != CFG->mailinglist.end(); z++) + if(z->sender_is_pattern) { + golded_search_manager srchmgr; + srchmgr.prepare_from_string(z->sender, GFIND_HDRTXT); + bool success = srchmgr.search(msg, true, true); + if(srchmgr.reverse ? not success : success) { + int areano = AL.AreaEchoToNo(z->echoid); + if(areano != -1) + return AL.AreaNoToId(areano); + } + } + } + return current; +} + + +// ------------------------------------------------------------------ + +int CheckMailinglists(const char* what, int current) { + + if(AA->isemail()) { + vector::iterator z; + for(z = CFG->mailinglist.begin(); z != CFG->mailinglist.end(); z++) + if(not z->sender_is_pattern and strieql(what, z->sender)) { + int areano = AL.AreaEchoToNo(z->echoid); + if(areano != -1) + return AL.AreaNoToId(areano); + } + } + return current; +} + + +// ------------------------------------------------------------------ + +bool MatchRFC(char*& p, const char* what) { + + bool match = strnieql(p, what, strlen(what)); + + if(match) + p = strskip_wht(p + strlen(what) - 1); + + return match; +} + + +// ------------------------------------------------------------------ + +void ProcessSoupMsg(char* lbuf, GMsg* msg, int& msgs, char* areaname, int tosstobadmsgs) { + + int entryCurrArea = CurrArea; + + if(msg->txt) { + + msgs++; + + msg->orig = msg->oorig = CFG->internetgate.addr.net ? CFG->internetgate.addr : AA->aka(); + msg->dest = msg->odest = AA->aka(); + time_t a = time(NULL); + time_t b = mktime(gmtime(&a)); + msg->arrived = a + a - b; + + Line* line = NULL; + Line* fline = NULL; + int lineno = 0; + int inhdr = true; + char* mptr = msg->txt; + char smsgid[2010]; *smsgid = NUL; + char sreply[2010]; *sreply= NUL; + + if(tosstobadmsgs) + AddLineF(line, "AREA:%s", areaname); + + while(*mptr) { + + char* eptr = mptr; + do { + eptr = strskip_to(eptr, '\n'); + if(*eptr) { + char lwsp = eptr[1]; + if(inhdr and (mptr != eptr) and ((lwsp == ' ') or (lwsp == '\t'))) { + *eptr = lwsp; + } + else { + *eptr++ = NUL; + break; + } + } + } while(*eptr); + + strchg(mptr, '\t', ' '); + + if(inhdr) { + if(*mptr == NUL) { + inhdr = false; + + CurrArea = CheckMailinglists(msg, CurrArea); + + const char* echo_id = AL.AreaIdToPtr(CurrArea)->echoid(); + fline = FirstLine(line); + char buf[2010]; + + if(*smsgid) { + CvtMessageIDtoMSGID(smsgid, buf, echo_id, "MSGID"); + fline = AddKludge(fline, buf); + } + if(*sreply) { + CvtMessageIDtoMSGID(sreply, buf, echo_id, "REPLY"); + fline = AddKludge(fline, buf); + } + } + else { + + int addkludge = true; + *lbuf = CTRL_A; + strcpy(lbuf+1, mptr); + + if(MatchRFC(mptr, "From: ")) { + INam fromname; + IAdr fromaddr; + ParseInternetAddr(mptr, fromname, fromaddr); + strxcpy(msg->by, *fromname ? fromname : fromaddr, sizeof(msg->by)); + if(AA->Internetgate().addr.net) { + char abuf[40]; + char kbuf[2048]; + sprintf(kbuf, "\x1""REPLYTO %s %s", + AA->Internetgate().addr.make_string(abuf), + *AA->Internetgate().name ? AA->Internetgate().name : "UUCP" + ); + line = AddKludge(line, kbuf); + sprintf(kbuf, "\x1""REPLYADDR %s", fromaddr); + line = AddKludge(line, kbuf); + } + CurrArea = CheckMailinglists(fromaddr, CurrArea); + } + else if(MatchRFC(mptr, "To: ")) { + strxcpy(msg->ito, mptr, sizeof(msg->ito)); + INam toname; + IAdr toaddr; + ParseInternetAddr(mptr, toname, toaddr); + strxcpy(msg->to, *toname ? toname : toaddr, sizeof(msg->to)); + } + else if(MatchRFC(mptr, "Cc: ")) { + char* ccbuf = (char*)throw_malloc(strlen(msg->icc) + strlen(mptr) + 3); + strcpy(stpcpy(stpcpy(ccbuf, msg->icc), *msg->icc ? ", " : ""), mptr); + strxcpy(msg->icc, ccbuf, sizeof(msg->icc)); + throw_free(ccbuf); + } + else if(MatchRFC(mptr, "Bcc: ")) { + char* bccbuf = (char*)throw_malloc(strlen(msg->ibcc) + strlen(mptr) + 3); + strcpy(stpcpy(stpcpy(bccbuf, msg->ibcc), *msg->ibcc ? ", " : ""), mptr); + strxcpy(msg->ibcc, bccbuf, sizeof(msg->ibcc)); + throw_free(bccbuf); + } + else if(MatchRFC(mptr, "X-To: ")) { + INam toname; + IAdr toaddr; + ParseInternetAddr(mptr, toname, toaddr); + strxcpy(msg->to, *toname ? toname : toaddr, sizeof(msg->to)); + } + else if(MatchRFC(mptr, "Subject: ")) { + strxcpy(msg->re, mptr, sizeof(msg->re)); + } + else if(MatchRFC(mptr, "Date: ")) { + KludgeDATE(msg, mptr); + } + else if(MatchRFC(mptr, "Organization: ")) { + // not used + } + else if(MatchRFC(mptr, "Message-ID: ")) { + if(not strnieql(mptr, "to) + strcpy(msg->to, "All"); + + msg->lin = FirstLine(line); + + if(OrigArea != CurrArea) { + AA->Unlock(); + AA->Close(); + AL.SetActiveAreaId(CurrArea); + OrigArea = CurrArea; + AA->Open(); + AA->Lock(); + AA->RandomizeData(); + } + + if(lineno) { + + AA->istossed = true; + update_statuslinef("%s: %u", AA->echoid(), msgs); + + msg->LinesToText(); + AA->SaveMsg(GMSG_NEW, msg); + } + + ResetMsg(msg); + + CurrArea = entryCurrArea; + } +} + + +// ------------------------------------------------------------------ + +dword swapendian(dword n) { + + byte* c = (byte*)&n; + n = ((c[0]*256 + c[1])*256 + c[2])*256 + c[3]; + return n; +} + + +// ------------------------------------------------------------------ + +int ImportSOUP() { + + int imported = 0; + + if(*CFG->soupimportpath) { + + const int MBUF_SIZE = 65535; + const int LBUF_SIZE = 65535; + + gfile fpa; // For AREAS file + gfile fpm; // For *.MSG files + + int importedmsgs = 0; + + Path areasfile; + strcpy(areasfile, AddPath(CFG->soupimportpath, "AREAS")); + fpa.fopen(areasfile, "rt"); + if(fpa.isopen()) { + + char buf[2048]; + + LoadCharset("N/A", "N/A"); + + char* mbuf = (char*)throw_malloc(MBUF_SIZE); + char* lbuf = (char*)throw_malloc(LBUF_SIZE); + + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + while(fpa.fgets(buf, sizeof(buf))) { + + char* delim = "\t\n"; + char* prefix = strtok(buf, delim); + char* areaname = strtok(NULL, delim); + char* encoding = strtok(NULL, delim); + + char msgfmt = *encoding++; + char idxfmt = (char)(*encoding ? *encoding++ : 0); + char kind = (char)(*encoding ? *encoding : 0); + + int isemail = false; + int isnews = false; + switch(msgfmt) { + case 'M': + // not supported yet + break; + case 'm': + case 'b': + isemail = true; + break; + case 'u': + if(kind == 'm') { + isemail = true; + break; + } + case 'B': + isnews = true; + break; + } + + Path msgfile, idxfile; + strcpy(stpcpy(msgfile, prefix), ".msg"); + strcpy(msgfile, AddPath(CFG->soupimportpath, msgfile)); + if(idxfmt) { + strcpy(stpcpy(idxfile, prefix), ".idx"); + strcpy(idxfile, AddPath(CFG->soupimportpath, idxfile)); + } + + strupr(areaname); + int tosstobadmsgs = false; + if(isemail) + areaname = CFG->soupemail; + int areano = AL.AreaEchoToNo(areaname); + if(areano == -1) { + areano = AL.AreaEchoToNo(CFG->soupbadmsgs); + tosstobadmsgs = true; + } + + if((areano != -1) and (isemail or isnews)) { + + AL.SetActiveAreaNo(areano); + OrigArea = CurrArea; + + fpm.fopen(msgfile, "rb"); + if(fpm.isopen()) { + + imported++; + + int msgs = 0; + + AA->Open(); + AA->Lock(); + AA->RandomizeData(); + + uint txtlen = 0; + char* txtptr = NULL; + uint allocated_len = 0; + + if((msgfmt == 'b') or (msgfmt == 'B')) { + + // Get binary formats + + dword msglen = 0; + while(fpm.fread(&msglen, 4) == 1) { + + msglen = swapendian(msglen); + uint msglensz = (uint)msglen; + if(msglen != msglensz) + msglensz--; + msg->txt = (char*)throw_calloc(1, msglensz+1); + fpm.fread(msg->txt, msglensz); + if(msglen != msglensz) + fpm.fseek(msglen-msglensz, SEEK_CUR); + ProcessSoupMsg(lbuf, msg, msgs, areaname, tosstobadmsgs); + } + } + else { + + // Get non-binary formats + + while(fpm.fgets(mbuf, MBUF_SIZE)) { + + if(msgfmt == 'u') { + if(strneql(mbuf, "#! rnews ", 9)) { + dword msglen = atol(mbuf+9); + uint msglensz = (uint)msglen; + if(msglen != msglensz) + msglensz--; + msg->txt = (char*)throw_calloc(1, msglensz+1); + fpm.fread(msg->txt, msglensz); + if(msglen != msglensz) + fpm.fseek(msglen-msglensz, SEEK_CUR); + ProcessSoupMsg(lbuf, msg, msgs, areaname, tosstobadmsgs); + } + else { + w_infof(LNG->ErrorInSoup, msgfile); + waitkeyt(10000); + w_info(NULL); + break; + } + } + else if(msgfmt == 'm') { + if(strneql(mbuf, "From ", 5)) { + msg->txt = txtptr; + txtptr = NULL; + txtlen = 0; + allocated_len = 0; + ProcessSoupMsg(lbuf, msg, msgs, areaname, tosstobadmsgs); + } + uint len = strlen(mbuf); + if((txtlen+len+1) > allocated_len) { + if(allocated_len) + allocated_len *= 2; + else + allocated_len = (txtlen+len+1) * 100; + txtptr = (char*)throw_realloc(txtptr, allocated_len); + } + strcpy(txtptr+txtlen, mbuf); + txtlen += len; + } + else if(msgfmt == 'M') { + // Not supported yet + } + } + + if(msgfmt == 'm') { + if(txtptr) { + msg->txt = txtptr; + txtptr = NULL; + ProcessSoupMsg(lbuf, msg, msgs, areaname, tosstobadmsgs); + } + } + } + + throw_free(txtptr); + + AA->Unlock(); + AA->Close(); + + if(msgs) + importedmsgs += msgs; + + fpm.fclose(); + } + } + + remove(msgfile); + if(idxfmt) + remove(idxfile); + } + + ResetMsg(msg); + throw_free(msg); + + throw_free(lbuf); + throw_free(mbuf); + + fpa.fclose(); + remove(areasfile); + + if(*CFG->souptosslog) + fpa.fopen(CFG->souptosslog, "at"); + + for(uint na = 0; na < AL.size(); na++) { + if(AL[na]->istossed) { + AL[na]->istossed = false; + AL[na]->isunreadchg = true; + if(fpa.isopen()) + fpa.printf("%s\n", AL[na]->echoid()); + } + } + + if(fpa.isopen()) + fpa.fclose(); + + if(importedmsgs and *CFG->soupreplylinker) { + sprintf(buf, LNG->Replylinker, CFG->soupreplylinker); + ShellToDos(CFG->soupreplylinker, buf, LGREY|_BLACK, YES); + } + } + } + + if(imported) + startupscan_success = true; + + return imported; +} + + +// ------------------------------------------------------------------ + +int ExportSoupMsg(GMsg* msg, char* msgfile, gfile& fp, int ismail) { + + NW(ismail); + + if(not fp.isopen()) { + fp.open(AddPath(CFG->soupexportpath, msgfile), O_RDWR|O_CREAT|O_BINARY, "rb+"); + if(fp.isopen()) + fp.fseek(0, SEEK_END); + } + + if(fp.isopen()) { + + int level = 0; + if(CharTable) + level = CharTable->level ? CharTable->level : 2; + + char mbuf[1030]; + + // Write placeholder for message length + dword msglen = 0xFFFFFFFFL; + fp.fwrite(&msglen, 4); + msglen = 0; + + bool qp = false; + if(msg->charsetencoding & GCHENC_MNE) { + if(not CharTable or not striinc("MNEMONIC", CharTable->exp)) + LoadCharset(CFG->xlatlocalset, "MNEMONIC"); + } + else if(striinc("LATIN1QP", msg->charset)) { + qp = true; + if(not CharTable or not striinc("LATIN1QP", CharTable->exp)) + LoadCharset(CFG->xlatlocalset, "LATIN1QP"); + } + else { + if(not CharTable or not striinc(msg->charset, CharTable->exp)) + LoadCharset(CFG->xlatlocalset, msg->charset); + } + + // Process kludges and write header lines + Line* line = msg->lin; + while(line) { + if(line->type & GLINE_KLUDGE) { + if((line->kludge == GKLUD_RFC) or (line->kludge == 0)) { + strcpy(mbuf, (*line->text == CTRL_A) ? line->text+1 : line->text); + msglen += fp.printf("%s%s", mbuf, (line->type & GLINE_WRAP) ? "" : "\n"); + } + else if(line->type & GLINE_WRAP) { + while(line->next and (line->type & GLINE_WRAP)) + line = line->next; + } + } + line = line->next; + } + + // Write blank line after header lines + msglen += fp.printf("\n"); + + // Write all message lines + line = msg->lin; + while(line) { + if(not (line->type & (GLINE_KLUDGE|GLINE_TEAR|GLINE_ORIG))) { + XlatStr(mbuf, line->text, level, CharTable); + char* mptr = mbuf; + if(qp and strlen(mptr) > 76) { + // 12345v7890 + // =FF - back one + // =FF - back two + // =FF - okay + do { + char* mbeg = mptr; + mptr += 75; + if(*(mptr-2) == '=') + mptr -= 2; + else if(*(mptr-1) == '=') + mptr--; + int mlen = (int)(mptr - mbeg); + msglen += fp.printf("%*.*s=\n", mlen, mlen, mbeg); + } while(strlen(mptr) > 76); + } + msglen += fp.printf("%s\n", mptr); + } + line = line->next; + } + + // Re-write the correct message length + fp.fseek(-(msglen+4), SEEK_CUR); + dword be_msglen = swapendian(msglen); + fp.fwrite(&be_msglen, 4); + fp.fseek(msglen, SEEK_CUR); + + msg->attr.snt1(); + msg->attr.scn1(); + msg->attr.uns0(); + time_t a = time(NULL); + time_t b = mktime(gmtime(&a)); + msg->arrived = a + a - b; + AA->SaveHdr(GMSG_UPDATE, msg); + if(msg->attr.k_s()) + AA->DeleteMsg(msg, DIR_NEXT); + + return 1; + } + + return 0; +} + + +// ------------------------------------------------------------------ + +int ExportSoupArea(int areano, char* msgfile, gfile& fp, int ismail) { + + int exported = 0; + + AL.SetActiveAreaNo(areano); + + AA->Open(); + AA->Lock(); + AA->RandomizeData(); + + GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); + + for(uint n=0; nExpo.Count(); n++) { + if(AA->LoadMsg(msg, AA->Expo[n], CFG->soupexportmargin)) { + if(msg->attr.uns() and not (msg->attr.del() or msg->attr.lok())) { + exported += ExportSoupMsg(msg, msgfile, fp, ismail); + update_statuslinef("%s: %u", AA->echoid(), exported); + } + } + } + + ResetMsg(msg); + throw_free(msg); + + AA->Unlock(); + AA->Close(); + + AA->Expo.ResetAll(); + + return exported; +} + + +// ------------------------------------------------------------------ + +int ExportSOUP() { + + int mailexported = 0; + int newsexported = 0; + + if(*CFG->soupexportpath) { + + Path scanfile; + gfile fp, mfp, nfp; + + // Get the scan list + strcpy(scanfile, AddPath(CFG->goldpath, "goldsoup.lst")); + fp.fopen(scanfile, "rt"); + if(fp.isopen()) { + char buf[256]; + while(fp.fgets(buf, sizeof(buf))) { + char* ptr = strchr(buf, ' '); + if(ptr) { + *ptr++ = NUL; + int a = AL.AreaEchoToNo(buf); + if(a != -1) + AL[a]->Expo.Add(atol(ptr)); + } + } + fp.fclose(); + } + + // Export from the e-mail and newsgroup areas + for(uint na = 0; na < AL.size(); na++) { + Area* ap = AL[na]; + if(ap->isemail() and ap->Expo.Count()) + mailexported += ExportSoupArea(na, "GOLDMAIL.MSG", mfp, true); + else if(ap->isnewsgroup() and ap->Expo.Count()) + newsexported += ExportSoupArea(na, "GOLDNEWS.MSG", nfp, false); + } + + // Close any open SOUP files + if(mfp.isopen()) + mfp.fclose(); + if(nfp.isopen()) + nfp.fclose(); + + // Update the REPLIES file + fp.open(AddPath(CFG->soupexportpath, "REPLIES"), O_RDWR|O_CREAT|O_BINARY, "rb+"); + if(fp.isopen()) { + char buf[512]; + int hasmail = false; + int hasnews = false; + while(fp.fgets(buf, sizeof(buf))) { + strtok(buf, "\t\n"); + if(strieql(buf, "GOLDMAIL")) + hasmail = true; + else if(strieql(buf, "GOLDNEWS")) + hasnews = true; + } + if(mailexported and not hasmail) + fp.printf("GOLDMAIL\tmail\tbn\n"); + if(newsexported and not hasnews) + fp.printf("GOLDNEWS\tnews\tBn\n"); + fp.fclose(); + } + + // Delete the scanfile + remove(scanfile); + } + + return mailexported + newsexported; +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gesrch.cpp b/golded3/gesrch.cpp new file mode 100644 index 0000000..dbab06e --- /dev/null +++ b/golded3/gesrch.cpp @@ -0,0 +1,567 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Advanced search functions. +// ------------------------------------------------------------------ + +#include +#include +#include +#include + + +// ------------------------------------------------------------------ + +golded_search_manager::golded_search_manager() { + +} + + +// ------------------------------------------------------------------ + +golded_search_manager::~golded_search_manager() { + +} + + +// ------------------------------------------------------------------ + +inline void search_item_option(bool& a, const char* s) { + + if(s[1] == '^') + a = not a; + else + a = s[1] != '\''; +} + + +// ------------------------------------------------------------------ + +const char* search_item_set(search_item& item, const char* s) { + + while(*s) { + switch(*s) { + case '!': search_item_option(item.reverse, s); break; + case '<': search_item_option(item.where.from, s); break; + case '>': search_item_option(item.where.to, s); break; + case ':': search_item_option(item.where.subject, s); break; + case '#': search_item_option(item.where.body, s); break; + case '.': search_item_option(item.where.tagline, s); break; + case '_': search_item_option(item.where.tearline, s); break; + case '*': search_item_option(item.where.origin, s); break; + case '@': search_item_option(item.where.signature, s); break; + case '%': search_item_option(item.where.kludges, s); break; + case '=': search_item_option(item.case_sensitive, s); break; + case '?': + s++; + switch(tolower(*s)) { + case 'r': item.type = gsearch::regex; break; + case 'w': item.type = gsearch::wildcard; break; + case 'p': item.type = gsearch::plain; break; + case 'f': + item.type = gsearch::fuzzy; + if(isdigit(s[1])) { + item.fuzzydegree = atoi(s+1); + while(isdigit(s[1])) + s++; + } + break; + } + break; + case '^': + case '\'': + break; + default: + return s; + } + s++; + } + + return s; +} + + +// ------------------------------------------------------------------ + +void golded_search_manager::prepare_from_string(const char* prompt, int what) { + + // Get defaults + reverse = false; + direction = DIR_NEXT; + search_item default_item; + const char* p = prompt; + + if(*p == '-' or *p == '+') { + direction = (*p == '-') ? DIR_PREV : DIR_NEXT; + p++; + } + p = search_item_set(default_item, p); + if(default_item.reverse) { + default_item.reverse = false; + reverse = true; + } + + if(what == GFIND_HDR or what == GFIND_HDRTXT) { + if(not (default_item.where.from or default_item.where.to or default_item.where.subject)) { + default_item.where.from = true; + default_item.where.to = true; + default_item.where.subject = true; + } + if(what == GFIND_HDRTXT) + default_item.where.body = true; + } + + char buf[256]; + char* b = buf; + bool item_complete = false; + search_item item = default_item; + + p = search_item_set(item, strskip_wht(p)); + + do { + + switch(*p) { + + // Logic AND + case '&': + item.logic = search_item::logic_and; + item_complete = true; + p++; + break; + + // Logic OR + case '|': + item.logic = search_item::logic_or; + item_complete = true; + p++; + break; + + // Get quoted string + case '\"': + case '\'': + { + char q = *p++; + while(*p) { + if(*p == q) { + p++; + break; + } + switch(*p) { + case '\\': + if(*(++p)) + *b++ = *p++; + break; + default: + *b++ = *p++; + } + } + } + break; + + // Get literal escaped character + case '\\': + if(*(++p)) + *b++ = *p++; + break; + + // Skip whitespace + case ' ': + p++; + + case NUL: + break; + + default: + *b++ = *p++; + } + + if(item_complete or (*p == NUL)) { + item_complete = false; + *b = NUL; + if(*buf != NUL) { + item.pattern = buf; + items.push_back(item); + } + if(*p == NUL) + break; + item = default_item; + p = search_item_set(item, strskip_wht(p)); + b = buf; + } + + } while(*p); +} + + +// ------------------------------------------------------------------ + +bool golded_search_manager::search(GMsg* msg, bool quick, bool shortcircuit) { + + search_item* item = items.begin(); + bool exit = false; + bool and_cycle = false; + bool or_cycle = false; + + for(int i=0; ilogic == search_item::logic_and) { + if(not and_cycle) { + if(exit) + return true; + } + else + if(not exit) + continue; + and_cycle = true; + } + else { + if(and_cycle) { + and_cycle = (item->logic == search_item::logic_and); + if(not exit) + continue; + } else { + and_cycle = (item->logic == search_item::logic_and); + if(exit) + return true; + } + or_cycle = (item->logic == search_item::logic_or); + } + } + + int found = 0; + if(item->where.from) { + if(item->search(*msg->ifrom ? msg->ifrom : msg->By())) { + msg->foundwhere |= GFIND_FROM; + found++; + if(quick) + goto quick_found; + } + } + if(item->where.to) { + if(item->search(*msg->ito ? msg->ito : msg->to)) { + msg->foundwhere |= GFIND_TO; + found++; + if(quick) + goto quick_found; + } + else if(*msg->icc and item->search(msg->icc)) { + msg->foundwhere |= GFIND_TO; + found++; + if(quick) + goto quick_found; + } + else if(*msg->ibcc and item->search(msg->ibcc)) { + msg->foundwhere |= GFIND_TO; + found++; + if(quick) + goto quick_found; + } + } + if(item->where.subject) { + if(item->search(msg->re)) { + msg->foundwhere |= GFIND_SUBJECT; + found++; + if(quick) + goto quick_found; + } + } + if(item->where.body or item->where.tagline or item->where.tearline or item->where.origin or item->where.signature or item->where.kludges) { + Line* line = msg->lin; + while(line) { + uint type = line->type; + bool search_this_line = false; + if(item->where.body and not (type & (GLINE_TAGL|GLINE_TEAR|GLINE_ORIG|GLINE_SIGN|GLINE_KLUDGE))) + search_this_line = true; + if(item->where.tagline and (type & GLINE_TAGL)) + search_this_line = true; + if(item->where.tearline and (type & GLINE_TEAR)) + search_this_line = true; + if(item->where.origin and (type & GLINE_ORIG)) + search_this_line = true; + if(item->where.signature and (type & GLINE_SIGN)) + search_this_line = true; + if(item->where.kludges and (type & GLINE_KLUDGE)) + search_this_line = true; + if(search_this_line) { + if(item->search(line->text)) { + line->type |= GLINE_HIGH; + if(type & (GLINE_TAGL|GLINE_TEAR|GLINE_ORIG|GLINE_SIGN|GLINE_KLUDGE)) { + if(type & GLINE_TAGL) + msg->foundwhere |= GFIND_TAGLINE; + else if(type & GLINE_TEAR) + msg->foundwhere |= GFIND_TEARLINE; + else if(type & GLINE_ORIG) + msg->foundwhere |= GFIND_ORIGIN; + else if(type & GLINE_SIGN) + msg->foundwhere |= GFIND_SIGNATURE; + else if(type & GLINE_KLUDGE) + msg->foundwhere |= GFIND_KLUDGES; + } + else { + msg->foundwhere |= GFIND_BODY; + } + found++; + if(quick) + goto quick_found; + } + } + line = line->next; + } + } + + quick_found: + + if(item->reverse) + found = not found; + + // Perform short-circuit logic analysis + if(shortcircuit) { + exit = found ? true : false; + if(item == items.end()-1) + return exit; + } + // else save success/failure as score + else { + item->score = found ? 1 : 0; + } + } + + if(not shortcircuit) { + gevalhum logic; + if(items.size()) { + for(int i=0; irow; + int scol = window.start_column + current->column; + + if((current->id < id_direction) and ((current->id % 3) == 2)) + scol -= 20; + + GMnu m; + m.Init(); + m.SetColor(7, 7, 7, 112, 8); + m.SetTitle(title, 14); + m.SetBorder(0, 7); + m.SetPos(srow, scol); + m.SetMask(0); + m.Begin(); + for(int i=0; iid < id_direction) and ((current->id % 3) == 2))) { + strbtrim(strcpy(current->buf, menu[m.FinalTag()].c_str()+1)); + current->update(); + } + } +} + + +// ------------------------------------------------------------------ + +bool search_mgr_form::validate() { + + gstrarray menu; + + if(current->id >= id_direction) { + switch(current->id) { + case id_direction: + menu.insert(menu.end(), "F Forward"); + menu.insert(menu.end(), "B Backward "); + select(menu, "Direction"); + break; + case id_messages: + menu.insert(menu.end(), "N New"); + menu.insert(menu.end(), "U Unread "); + menu.insert(menu.end(), "A All"); + select(menu, "Messages"); + break; + case id_action: + menu.insert(menu.end(), "R Read"); + menu.insert(menu.end(), "T Tag"); + menu.insert(menu.end(), "D Delete "); + menu.insert(menu.end(), "W Write"); + menu.insert(menu.end(), "C Copy"); + menu.insert(menu.end(), "M Move"); + select(menu, "Action"); + break; + case id_areas: + menu.insert(menu.end(), "C Current "); + menu.insert(menu.end(), "A All"); + menu.insert(menu.end(), "T Tagged"); + select(menu, "Areas"); + break; + } + } + else if((current->id % 3) == 1) { + menu.insert(menu.end(), "a and "); + menu.insert(menu.end(), "o or"); + select(menu, "Logic"); + } + else if((current->id % 3) == 2) { + menu.insert(menu.end(), " Plain "); + menu.insert(menu.end(), " Regex "); + menu.insert(menu.end(), " Wildcard "); + menu.insert(menu.end(), " Fuzzy "); + menu.insert(menu.end(), " Success if not found "); + menu.insert(menu.end(), " Case sensitive "); + menu.insert(menu.end(), " Search \"from\" "); + menu.insert(menu.end(), " Search \"to\" "); + menu.insert(menu.end(), " Search \"subject\" "); + menu.insert(menu.end(), " Search msg body "); + menu.insert(menu.end(), " Search tagline "); + menu.insert(menu.end(), " Search tearline "); + menu.insert(menu.end(), " Search origin "); + menu.insert(menu.end(), " Search signature "); + menu.insert(menu.end(), " Search kludges "); + select(menu, "Options"); + } + + return true; +} + + +// ------------------------------------------------------------------ + +void AdvancedSearch(GMsg*, int&, int&) { + + int patterns = 9; + int width = 77; + int height = patterns+11; + int widths[3] = { 55, 5, 7 }; + int field_widths[3] = { 100, 5, 7 }; + int border_type = BT_SINGLE; + int title_color = YELLOW | _BLUE; + int heading_color = YELLOW | _BLUE; + int window_color = LGREY | _BLUE; + int border_color = LBLUE | _BLUE; + int edit_color = YELLOW | _BLUE; + int idle_color = LGREY | _BLUE; + int active_color = WHITE | _BLUE; + int shadow_color = DGREY | _BLACK; + + widths[0] = width - 3*2 - 2 - 5 - 7 - 2; + + gwindow window; + + window.openxy(1, ((MAXCOL-width)/2), height, width, + border_type, border_color, window_color); + window.shadow(shadow_color); + + window.horizontal_line( 1, 0, width-2, border_type, border_color); + window.horizontal_line(patterns+2, 0, width-2, border_type, border_color); + + window.vertical_line(0, widths[0]+2, patterns+3, border_type, border_color); + window.vertical_line(0, widths[0]+widths[1]+5, patterns+3, border_type, border_color); + + window.title(" Advanced Search Manager ", title_color); + + window.prints(0, 1, heading_color, "Pattern"); + window.prints(0, widths[0]+4, heading_color, "Logic"); + window.prints(0, widths[0]+widths[1]+7, heading_color, "Options"); + + window.prints(patterns+3, 1, heading_color, "Direction : "); + window.prints(patterns+4, 1, heading_color, "Messages : "); + window.prints(patterns+5, 1, heading_color, "Action : "); + window.prints(patterns+6, 1, heading_color, "Areas : "); + window.prints(patterns+7, 1, heading_color, "Destination : "); + window.prints(patterns+8, 1, heading_color, "Identifier : "); + + search_mgr_form iform(window); + + iform.setup(idle_color, active_color, edit_color, _box_table(border_type, 13), true); + + string buffers[9*3 + 6]; + + int i = 0; + for(int r=0; r<9; r++) { + int cs = 1; + for(int c=0; c<3; c++,i++) { + char z[80]; + sprintf(z, "%i,%i", r+1, c+1); + buffers[i] = z; + iform.add_field(i, r+2, cs, widths[c], buffers[i], field_widths[c]); + cs += widths[c] + 3; + } + } + + buffers[i+0] = "Forward"; + buffers[i+1] = "New"; + buffers[i+2] = "Read"; + buffers[i+3] = "Current"; + buffers[i+4] = "C:\\TEMP\\DUMPFILE.TXT"; + buffers[i+5] = "Testing"; + + for(int y=0; y<6; y++,i++) + iform.add_field(100+y, patterns+3+y, 15, width-15-3, buffers[i], width-15-3, gwinput::cvt_none, y>=4 ? gwinput::entry_conditional : gwinput::entry_noedit); + + iform.run(0); + + window.close(); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gesrch.h b/golded3/gesrch.h new file mode 100644 index 0000000..d707d45 --- /dev/null +++ b/golded3/gesrch.h @@ -0,0 +1,76 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Advanced search functions. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +class golded_search_manager : public search_manager { + +public: + + bool reverse; + int direction; + + golded_search_manager(); + ~golded_search_manager(); + + void prepare_from_string(const char* prompt, int what); + + bool search(GMsg* msg, bool quick, bool shortcircuit); + +}; + + +// ------------------------------------------------------------------ + +class search_mgr_form : public gwinput2 { + +public: + + enum { + id_direction = 100, + id_messages, + id_action, + id_areas + }; + + search_mgr_form(gwindow& w) : gwinput2(w) { } + virtual ~search_mgr_form() { } + + bool validate(); + + void select(gstrarray& menu, const char* title); + + void before(); + void after(); +}; + + +// ------------------------------------------------------------------ + diff --git a/golded3/getpls.cpp b/golded3/getpls.cpp new file mode 100644 index 0000000..2e5a433 --- /dev/null +++ b/golded3/getpls.cpp @@ -0,0 +1,1109 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Template handling. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +extern GMsg* reader_msg; +extern int reader_gen_confirm; + + +// ------------------------------------------------------------------ + +bool is_user(const char* name) { + + if(strieql(name, AA->Username().name)) + return true; + // We should check all misspells too + for(vector:: iterator u = CFG->username.begin(); u != CFG->username.end(); u++) + if(strieql(name, u->name)) + return true; + return false; +} + + +// ------------------------------------------------------------------ + +inline int IsInitial(char c) { + + return isalpha(c) or (c > 127); +} + + +// ------------------------------------------------------------------ + +int TemplateToText(int mode, GMsg* msg, GMsg* oldmsg, const char* tpl, int origarea) { + + FILE* fp; + long fpos; + Path tplfile; + int n; + int x; + FILE *tfp; + FILE *ifp; + char* tptr; + char* ptr; + char* ptr2; + char* quote; + uint size = 0; + uint pos = 0; + uint ctrlinfo; + char textfile[GMAXPATH]; + char indexfile[GMAXPATH]; + char buf[256]; + char initials[10]; + char quotestr[100]; + char qbuf[100]; + int chg; + uint len; + int y; + int tmptpl = NO; + int robotchk = NO; + int disphdr = NO; + int quotebufline; + + enum TPL_TOKEN_IDS { + TPLTOKEN_FORWARD, + TPLTOKEN_CHANGED, + TPLTOKEN_NET, + TPLTOKEN_ECHO, + TPLTOKEN_LOCAL, + TPLTOKEN_MOVED, + TPLTOKEN_NEW, + TPLTOKEN_REPLY, + TPLTOKEN_QUOTED, + TPLTOKEN_COMMENT, + TPLTOKEN_QUOTEBUF, + TPLTOKEN_ATTRIB, + TPLTOKEN_SPELLCHECKER, + TPLTOKEN_SETSUBJ, + TPLTOKEN_SETFROM, + TPLTOKEN_SETTO, + TPLTOKEN_FORCESUBJ, + TPLTOKEN_FORCEFROM, + TPLTOKEN_FORCETO, + TPLTOKEN_XLATEXPORT, + TPLTOKEN_LOADLANGUAGE, + TPLTOKEN_RANDOM, + TPLTOKEN_QUOTE, + TPLTOKEN_INCLUDE, + TPLTOKEN_MESSAGE, + TPLTOKEN_MODERATOR + }; + + #define CSTR_COMMA_SIZEOF_CSTR(s) s, (sizeof(s)-1) + + struct tpl_token { + char* token; + int length; + }; + + tpl_token token_list[] = { + { CSTR_COMMA_SIZEOF_CSTR("forward") }, + { CSTR_COMMA_SIZEOF_CSTR("changed") }, + { CSTR_COMMA_SIZEOF_CSTR("net") }, + { CSTR_COMMA_SIZEOF_CSTR("echo") }, + { CSTR_COMMA_SIZEOF_CSTR("local") }, + { CSTR_COMMA_SIZEOF_CSTR("moved") }, + { CSTR_COMMA_SIZEOF_CSTR("new") }, + { CSTR_COMMA_SIZEOF_CSTR("reply") }, + { CSTR_COMMA_SIZEOF_CSTR("quoted") }, + { CSTR_COMMA_SIZEOF_CSTR("comment") }, + { CSTR_COMMA_SIZEOF_CSTR("quotebuf") }, + { CSTR_COMMA_SIZEOF_CSTR("attrib") }, + { CSTR_COMMA_SIZEOF_CSTR("spellchecker") }, + { CSTR_COMMA_SIZEOF_CSTR("setsubj") }, + { CSTR_COMMA_SIZEOF_CSTR("setfrom") }, + { CSTR_COMMA_SIZEOF_CSTR("setto") }, + { CSTR_COMMA_SIZEOF_CSTR("forcesubj") }, + { CSTR_COMMA_SIZEOF_CSTR("forcefrom") }, + { CSTR_COMMA_SIZEOF_CSTR("forceto") }, + { CSTR_COMMA_SIZEOF_CSTR("xlatexport") }, + { CSTR_COMMA_SIZEOF_CSTR("loadlanguage") }, + { CSTR_COMMA_SIZEOF_CSTR("random") }, + { CSTR_COMMA_SIZEOF_CSTR("quote") }, + { CSTR_COMMA_SIZEOF_CSTR("include") }, + { CSTR_COMMA_SIZEOF_CSTR("message") }, + { CSTR_COMMA_SIZEOF_CSTR("moderator") } + }; + + int end_token = sizeof(token_list) / sizeof(tpl_token); + + *initials = NUL; + + // Check for msg to AreaFix + if(AA->isnet() and mode == MODE_NEW) { + for(gstrarray::iterator r = CFG->robotname.begin(); r != CFG->robotname.end(); r++) + if(striinc(r->c_str(), msg->to)) { + robotchk = YES; + break; + } + if(robotchk) { + EDIT->HardLines(false); + msg->txt = (char*)throw_realloc(msg->txt, 256); + strcpy(msg->txt, LNG->RobotMsg); + TokenXlat(mode, msg->txt, msg, oldmsg, origarea); + return 0; + } + } + + strcpy(tplfile, tpl); + + if(AA->Templatematch() and not (CFG->tplno or AA->isnewsgroup() or AA->isemail())) { + if(not ((mode == MODE_NEW or mode == MODE_REPLYCOMMENT or mode == MODE_FORWARD) + and (AA->isecho() or AA->islocal()))) { + vector::iterator tp; + for(tp = CFG->tpl.begin(); tp != CFG->tpl.end(); tp++) + if(tp->match.net and msg->dest.match(tp->match)) { + strcpy(tplfile, tp->file); + break; + } + } + } + + if(tplfile == CleanFilename(tplfile)) + strcpy(tplfile, AddPath(CFG->templatepath, tplfile)); + + if(not fexist(tplfile) and not CFG->tpl.empty()) + strcpy(tplfile, AddPath(CFG->templatepath, CFG->tpl[CFG->tplno].file)); + if(not fexist(tplfile) or CFG->tpl.empty()) { + tmptpl = YES; // Create a temporary template + mktemp(strcpy(tplfile, AddPath(CFG->templatepath, "GDXXXXXX"))); + fp = fsopen(tplfile, "wt", CFG->sharemode); + if(fp) { + fputs("@moved* Replying to a msg in @oecho (@odesc)\n@moved\n", fp); + fputs("@changed* Changed by @cname (@caddr), @cdate @ctime.\n@changed\n", fp); + fputs("@forward* Forwarded from @oecho by @fname (@faddr).\n", fp); + fputs("@forward* Originally by: @oname (@oaddr), @odate @otime.\n", fp); + fputs("@forward* Originally to: @dname{}{}{all}.\n", fp); + fputs("@forward\n", fp); + fputs("@message\n", fp); + fputs("@forward\n", fp); + fputs("Hello @pseudo{}{}{everybody}.\n", fp); + fputs("@new\n", fp); + fputs("@position\n", fp); + fputs("@replyReplying to a msg dated @odate @otime, from @oname{I}{you} to @dname{me}{you}{all}.\n", fp); + fputs("@reply@position\n", fp); + fputs("@quoted@odate @otime, @oname{I}{you} wrote to @dname{me}{you}{all}:\n", fp); + fputs("@quoted@position\n", fp); + fputs("@comment@odate @otime, @oname{I}{you} wrote to @dname{me}{you}{all}:\n", fp); + fputs("@comment@position\n", fp); + fputs("@quotebuf\n", fp); + fputs("@quotebuf@odate @otime, @oname{I}{you} wrote to @dname{me}{you}{all}:\n", fp); + fputs("@quotebuf\n", fp); + fputs("@quote\n\n", fp); + fputs("@cfname\n\n", fp); + fclose(fp); + } + } + + fp = fsopen(tplfile, "rt", CFG->sharemode); + if(fp == NULL) { + LOG.ErrOpen(); + LOG.printf("! A template file could not be opened."); + LOG.printf(": %s", tplfile); + LOG.ErrOSInfo(); + OpenErrorExit(); + } + + oldmsg->you_and_I = msg->you_and_I = 0; + + if (strieql(msg->By(), oldmsg->By()) or is_user (oldmsg->By())) + msg->you_and_I |= BY_ME; + if (strieql(msg->By(), oldmsg->to) or is_user (oldmsg->to)) + msg->you_and_I |= TO_ME; + + if (not msg->by_me() and strieql(msg->to, oldmsg->By())) + msg->you_and_I |= BY_YOU; + if (not msg->to_me() and strieql(msg->to, oldmsg->to)) + msg->you_and_I |= TO_YOU; + + if(not msg->to_me() and strieql(AA->Whoto(), oldmsg->to)) + oldmsg->you_and_I |= TO_ALL; + + if(strieql(AA->Whoto(), msg->to)) + msg->you_and_I |= TO_ALL; + + // build @tpseudo + if(is_user(msg->to)) + strcpy(msg->pseudoto, *AA->Nickname() ? AA->Nickname() : strlword(msg->to)); + else + *(msg->pseudoto) = NUL; + + // build @fpseudo + if(is_user(msg->By())) + strcpy(msg->pseudofrom, *AA->Nickname() ? AA->Nickname() : strlword(msg->By())); + else + *(msg->pseudofrom) = NUL; + + // build @dpseudo + if(msg->to_me()) + strcpy(oldmsg->pseudoto, msg->pseudofrom); + else if(msg->to_you()) + strcpy(oldmsg->pseudoto, msg->pseudoto); + else + *(oldmsg->pseudoto) = NUL; + + // build @opseudo + if(msg->by_me()) + strcpy(oldmsg->pseudofrom, msg->pseudofrom); + else if(msg->by_you()) + strcpy(oldmsg->pseudofrom, msg->pseudoto); + else + *(oldmsg->pseudofrom) = NUL; + + throw_release(msg->txt); + + *buf = NUL; + msg->txt = throw_strdup(buf); + + len = strlen(msg->txt); + size += len; + pos += len; + + while(fgets(buf, sizeof(buf), fp)) { + ptr = strskip_wht(buf); + if(*ptr != ';') { + chg = NO; + quotebufline = NO; + ptr = buf; + int token = end_token; + do { + do { + // Find next '@' or NUL + while(*ptr and (*ptr != '@')) + ptr++; + // Skip past double '@'s + if(*ptr and (ptr[1] == '@')) + ptr += 2; + } while(*ptr and (*ptr != '@')); + if(*ptr) { + ptr++; + for(token=0; tokenisnet()) + goto loop_next; + token = end_token; + break; + + case TPLTOKEN_ECHO: + if(not AA->isecho()) + goto loop_next; + token = end_token; + break; + + case TPLTOKEN_LOCAL: + if(not AA->islocal()) + goto loop_next; + token = end_token; + break; + + case TPLTOKEN_MOVED: + if(CurrArea == origarea) + goto loop_next; + if(mode == MODE_FORWARD) + goto loop_next; + if(AL.AreaIdToPtr(origarea)->Areareplydirect() and oldmsg->areakludgeid and strieql(oldmsg->areakludgeid, AA->echoid())) + goto loop_next; + if(strieql(oldmsg->fwdarea, AA->echoid())) + goto loop_next; + token = end_token; + break; + + case TPLTOKEN_NEW: + if(mode != MODE_NEW) + goto loop_next; + token = end_token; + break; + + case TPLTOKEN_REPLY: + if(mode != MODE_REPLY) + goto loop_next; + token = end_token; + break; + + case TPLTOKEN_QUOTED: + if(mode != MODE_QUOTE) + goto loop_next; + token = end_token; + break; + + case TPLTOKEN_COMMENT: + if(mode != MODE_REPLYCOMMENT) + goto loop_next; + token = end_token; + break; + + case TPLTOKEN_QUOTEBUF: + if(mode != MODE_QUOTEBUF) + goto loop_next; + quotebufline = YES; + token = end_token; + break; + + case TPLTOKEN_MODERATOR: + if(not striinc("moderator", msg->By())) + goto loop_next; + token = end_token; + break; + } + } + + } while(*ptr and (token>=end_token)); + + if(token < end_token) { + TokenXlat(mode, buf, msg, oldmsg, origarea); + + switch(token) { + + case TPLTOKEN_ATTRIB: + if(mode != MODE_QUOTEBUF) { + GetAttribstr(&msg->attr, ptr); + disphdr = YES; + } + continue; + + case TPLTOKEN_SPELLCHECKER: + if(mode != MODE_QUOTEBUF) + EDIT->SpellChecker(strskip_wht(ptr)); + continue; + + case TPLTOKEN_SETSUBJ: + case TPLTOKEN_FORCESUBJ: + if(mode != MODE_QUOTEBUF) { + if(strblank(msg->re) or (token == TPLTOKEN_FORCESUBJ)) { + strbtrim(ptr); + StripQuotes(ptr); + strcpy(msg->re, ptr); + disphdr = YES; + } + } + continue; + + case TPLTOKEN_SETFROM: + case TPLTOKEN_FORCEFROM: + if(mode != MODE_QUOTEBUF) { + if(strblank(msg->by) or (token == TPLTOKEN_FORCEFROM)) { + strbtrim(ptr); + StripQuotes(ptr); + strcpy(msg->by, ptr); + disphdr = YES; + } + } + continue; + + case TPLTOKEN_SETTO: + case TPLTOKEN_FORCETO: + if(mode != MODE_QUOTEBUF) { + if(strblank(msg->to) or (token == TPLTOKEN_FORCETO)) { + strbtrim(ptr); + StripQuotes(ptr); + strcpy(msg->to, ptr); + disphdr = YES; + } + } + continue; + + case TPLTOKEN_XLATEXPORT: + if(mode != MODE_QUOTEBUF) + AA->SetXlatexport(strbtrim(ptr)); + continue; + + case TPLTOKEN_LOADLANGUAGE: + strbtrim(ptr); + LoadLanguage(ptr); // Load a GoldED language file + disphdr = YES; + continue; + + case TPLTOKEN_RANDOM: + if(mode != MODE_QUOTEBUF) { + strtrim(ptr); + ptr = strskip_wht(strskip_txt(ptr)); + if(*ptr) { + tptr = ptr; + ptr = strskip_txt(ptr); + if(*ptr) { + *ptr++ = NUL; + strcpy(textfile, tptr); + ptr = strskip_wht(ptr); + if(*ptr) { + tptr = ptr; + ptr = strskip_txt(ptr); + *ptr = NUL; + strcpy(indexfile, tptr); + } + } + else { + strcpy(textfile, tptr); + } + } + else { + strcpy(textfile, "random.txt"); + } + + replaceextension(indexfile, textfile, ".mdx"); + + MakePathname(textfile, CFG->cookiepath, textfile); + MakePathname(indexfile, CFG->cookiepath, indexfile); + + // Check if index exists or if it is older than the textfile + int idxexist = fexist(indexfile); + if(idxexist) + if(FiletimeCmp(textfile, indexfile) > 0) + idxexist = false; + + // If index file is missing, make one + if(not idxexist) + CookieIndex(textfile, indexfile); + + // Get a random cookie + tfp = fsopen(textfile, "rt", CFG->sharemode); + if(tfp) { + ifp = fsopen(indexfile, "rb", CFG->sharemode); + if(ifp) { + fseek(ifp, 0L, SEEK_END); + int idxs = (int)(ftell(ifp)/4L); + if(idxs) { + fseek(ifp, (long)(rand()%idxs)*4L, SEEK_SET); + fread(&fpos, sizeof(long), 1, ifp); + fseek(tfp, fpos, SEEK_SET); + while(fgets(buf, 255, tfp)) { + strtrim(buf); + if(*buf) { + if(*buf == '+' and buf[1] == NUL) + *buf = ' '; + TokenXlat(mode, buf, msg, oldmsg, origarea); + strtrim(buf); + strcat(buf, "\r"); + len = strlen(buf); + size += len; + msg->txt = (char*)throw_realloc(msg->txt, size+10); + strcpy(&(msg->txt[pos]), buf); + pos += len; + } + else + break; + } + } + fclose(ifp); + } + fclose(tfp); + } + } + continue; + + case TPLTOKEN_INCLUDE: + if(mode != MODE_QUOTEBUF) { + strbtrim(ptr); + strcpy(textfile, ptr); + MakePathname(textfile, CFG->templatepath, textfile); + tfp = fsopen(textfile, "rt", CFG->sharemode); + if(tfp) { + while(fgets(buf, 255, tfp)) { + TokenXlat(mode, buf, msg, oldmsg, origarea); + strtrim(buf); + strcat(buf, "\r"); + len = strlen(buf); + size += len; + msg->txt = (char*)throw_realloc(msg->txt, size+10); + strcpy(&(msg->txt[pos]), buf); + pos += len; + } + fclose(tfp); + } + } + continue; + + case TPLTOKEN_QUOTE: + if(mode == MODE_QUOTE or mode == MODE_REPLYCOMMENT or mode == MODE_QUOTEBUF) { + y = 0; + ptr = strskip_wht(oldmsg->By()); + while(*ptr) { + while(not IsInitial(*ptr) and (*ptr != '@') and *ptr) + ptr++; + if(*ptr == '@') + break; + if(*ptr) { + initials[y++] = *ptr; + if(y == 9) + break; + ptr++; + } + while(IsInitial(*ptr) and *ptr) + ptr++; + } + + initials[y] = NUL; + *buf = NUL; + if(y > 2) { + for(x=1; x<(y-1); x++) + buf[x-1] = initials[x]; + buf[x-1] = NUL; + } + for(n=0,x=0; nQuotestring()); n++) { + switch(AA->Quotestring()[n]) { + case 'F': + case 'f': + if(*initials) { + quotestr[x++] = *initials; + quotestr[x] = NUL; + } + break; + case 'M': + case 'm': + strcat(quotestr, buf); + x += strlen(buf); + break; + case 'L': + case 'l': + if(y > 1) { + quotestr[x++] = initials[y-1]; + quotestr[x] = NUL; + } + break; + default: + quotestr[x++] = AA->Quotestring()[n]; + quotestr[x] = NUL; + } + } + ptr = strskip_wht(quotestr); + y = (int)((long)ptr-(long)quotestr); + n = 0; + *buf = NUL; + while(oldmsg->line[n]) { + quote = strtrim(oldmsg->line[n]->text); + if(oldmsg->line[n]->type & GLINE_TEAR) { + // Invalidate tearline + oldmsg->line[n]->type &= ~GLINE_TEAR; + if(not (AA->Quotectrl() & CI_TEAR)) { + n++; + continue; + } + } + else if(oldmsg->line[n]->type & GLINE_ORIG) { + // Invalidate originline + oldmsg->line[n]->type &= ~GLINE_ORIG; + if(not (AA->Quotectrl() & CI_ORIG)) { + n++; + continue; + } + } + + // Invalidate kludge chars + strchg(quote, CTRL_A, '@'); + + if(is_quote(oldmsg->line[n]->text)) { + quote += GetQuotestr(quote, qbuf, &len); + strbtrim(qbuf); + ptr = qbuf; + if(not IsQuoteChar(ptr)) { + ptr = qbuf+strlen(qbuf); + while(ptr >= qbuf) { + if(IsQuoteChar(ptr)) + break; + ptr--; + } + } + x = (int)((dword)ptr-(dword)qbuf); + sprintf(buf, "%*.*s%*.*s>%s %s", + y, y, quotestr, x, x, qbuf, qbuf+x, quote + ); + } + else if((not strblank(quote)) or CFG->switches.get(quoteblank)) + sprintf(buf, "%s%s", quotestr, quote); + else + *buf = NUL; + n++; + strtrim(buf); + strcat(buf, "\r"); + len = strlen(buf); + size += len; + msg->txt = (char*)throw_realloc(msg->txt, size+10); + strcpy(&(msg->txt[pos]), buf); + pos += len; + } + } + continue; + + case TPLTOKEN_MESSAGE: + if(mode == MODE_FORWARD or mode == MODE_CHANGE) { + n = 0; + while(oldmsg->line[n]) { + if(oldmsg->line[n]->text) { + strcpy(buf, oldmsg->line[n]->text); + if(mode == MODE_FORWARD) { + // Invalidate tearline + if(not CFG->invalidate.tearline.first.empty()) + doinvalidate(buf, CFG->invalidate.tearline.first.c_str(), CFG->invalidate.tearline.second.c_str(), true); + // Invalidate originline + if(not CFG->invalidate.origin.first.empty()) + doinvalidate(buf, CFG->invalidate.origin.first.c_str(), CFG->invalidate.origin.second.c_str()); + // Invalidate SEEN-BY's + if(not CFG->invalidate.seenby.first.empty()) + doinvalidate(buf, CFG->invalidate.seenby.first.c_str(), CFG->invalidate.seenby.second.c_str()); + // Invalidate CC's + if(not CFG->invalidate.cc.first.empty()) + doinvalidate(buf, CFG->invalidate.cc.first.c_str(), CFG->invalidate.cc.second.c_str()); + // Invalidate XC's + if(not CFG->invalidate.xc.first.empty()) + doinvalidate(buf, CFG->invalidate.xc.first.c_str(), CFG->invalidate.xc.second.c_str()); + // Invalidate XP's + if(not CFG->invalidate.xp.first.empty()) + doinvalidate(buf, CFG->invalidate.xp.first.c_str(), CFG->invalidate.xp.second.c_str()); + // Invalidate kludge chars + strchg(buf, CTRL_A, '@'); + } + len = strlen(buf); + size += len; + msg->txt = (char*)throw_realloc(msg->txt, size+10); + strcpy(&(msg->txt[pos]), buf); + pos += len; + if(oldmsg->line[n]->type & GLINE_HARD) { + msg->txt[pos++] = CR; + size++; + } + else { + if(oldmsg->line[n+1]) { + if(oldmsg->line[n+1]->text) { + if(msg->txt[pos-1] != ' ' and *oldmsg->line[n+1]->text != ' ') { + msg->txt[pos++] = ' '; + size++; + } + } + } + } + } + n++; + } + } + continue; + } + } + + if(mode == MODE_CHANGE) + if(chg == NO) + continue; + if((mode == MODE_QUOTEBUF) and not quotebufline) + continue; + TokenXlat(mode, buf, msg, oldmsg, origarea); + len = strlen(buf); + size += len; + msg->txt = (char*)throw_realloc(msg->txt, size+10); + strcpy(&(msg->txt[pos]), buf); + pos += len; + } + loop_next: + ; + } + fclose(fp); + + if((mode != MODE_CHANGE) and (mode != MODE_QUOTEBUF)) { + ctrlinfo = AA->Ctrlinfo(); + ctrlinfo |= CI_TAGL; + if(ctrlinfo & (CI_TAGL|CI_TEAR|CI_ORIG)) { + do { + if((ctrlinfo & CI_ORIG) and not (ctrlinfo & CI_TEAR) and not (ctrlinfo & CI_TAGL)) { + sprintf(buf, " * Origin: %s", msg->origin); + ctrlinfo &= ~CI_ORIG; + } + if((ctrlinfo & CI_TEAR) and not (ctrlinfo & CI_TAGL)) { + MakeTearline(msg, buf); + ctrlinfo &= ~CI_TEAR; + } + if(ctrlinfo & CI_TAGL) { + strbtrim(msg->tagline); + if(AA->Taglinesupport() and *msg->tagline) + sprintf(buf, "%c%c%c %s", AA->Taglinechar(), AA->Taglinechar(), AA->Taglinechar(), msg->tagline); + else + *buf = NUL; + ctrlinfo &= ~CI_TAGL; + } + strtrim(buf); + if(*buf) { + strcat(buf, "\n"); + TokenXlat(mode, buf, msg, oldmsg, origarea); + len = strlen(buf); + size += len; + msg->txt = (char*)throw_realloc(msg->txt, size+10); + strcpy(&(msg->txt[pos]), buf); + pos += len; + } + } while(ctrlinfo & (CI_TAGL|CI_TEAR|CI_ORIG)); + } + } + msg->txt[pos] = NUL; + + if(tmptpl) + remove(tplfile); + + return disphdr; +} + + +// ------------------------------------------------------------------ + +void ChangeMsg() { + + int changemsg=NO; + + if(AA->Msgn.Count()) { + + reader_keyok = YES; + + if(AA->attr().hex()) { + AA->attr().hex0(); + AA->LoadMsg(reader_msg, reader_msg->msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + } + + for(vector:: iterator u = CFG->username.begin(); u != CFG->username.end(); u++) + // Check FROM: + if(reader_msg->orig.match(u->addr)) { + if(strieql(u->name, reader_msg->By())) { + if(u->addr.net != GFTN_ALL or reader_msg->orig.net == 0 or not AA->isnet()) + reader_keyok = NO; + else { + for(vector::iterator x = CFG->aka.begin(); x != CFG->aka.begin(); x++) { + if(reader_msg->orig.match(x->addr)) { + reader_keyok = NO; + break; + } + } + } + } + } + + if(reader_keyok == YES) { + GMenuChange MenuChange; + reader_keyok = not MenuChange.Run(LNG->ChangeWarn); + if(reader_keyok == NO) + changemsg = true; + } + else + changemsg = true; + + if(changemsg) { + if(reader_msg->attr.loc() and not AA->islocal()) { + if(reader_msg->attr.snt() or not reader_msg->attr.uns()) { + GMenuChange MenuChange; + reader_keyok = not MenuChange.Run(LNG->WarnAlreadySent); + } + } + if(reader_keyok == NO) + MakeMsg(MODE_CHANGE, reader_msg); + } + } +} + + +// ------------------------------------------------------------------ + +void NewMsg() { + + reader_topline = 0; + AA->attr().hex0(); + if(AA->attr().r_o()) { + GMenuReadonly MenuReadonly; + reader_keyok = not MenuReadonly.Run(); + } + if(not reader_keyok) + MakeMsg(MODE_NEW, reader_msg); +} + + +// ------------------------------------------------------------------ + +void ConfirmMsg() { + + int doit = CFG->confirmresponse; + if(CFG->confirmresponse == ASK) { + GMenuConfirm MenuConfirm; + doit = MenuConfirm.Run(); + } + + reader_gen_confirm = NO; + if(doit and AA->isnet() and (reader_msg->attr.cfm() or reader_msg->attr.rrq())) { + int a = AL.AreaEchoToNo(CFG->areacfmreplyto); + if(a != -1) { + AL.SetActiveAreaNo(a); + if(CurrArea != OrigArea) + AA->Open(); + } + reader_topline = 0; + AA->attr().hex0(); + update_statusline(LNG->GenCfmReceipt); + MakeMsg(MODE_CONFIRM, reader_msg); + reader_topline = 0; + LoadMessage(reader_msg, CFG->dispmargin-(int)CFG->switches.get(disppagebar)); + if(CurrArea != OrigArea) { + AA->Close(); + AL.SetActiveAreaId(OrigArea); + } + } + if(not CFG->switches.get(rcvdisablescfm)) { + GMsg* msg = (GMsg*)throw_malloc(sizeof(GMsg)); + memcpy(msg, reader_msg, sizeof(GMsg)); + reader_msg->attr.rrq0(); + reader_msg->attr.cfm0(); + reader_msg->attr.upd1(); + msg->charsetlevel = LoadCharset(CFG->xlatlocalset, msg->charset); + DoKludges(MODE_CHANGE, reader_msg, true); + reader_msg->LinesToText(); + AA->SaveMsg(GMSG_UPDATE, reader_msg); + throw_free(msg); + } +} + + +// ------------------------------------------------------------------ + +bool _allow_pick = true; + +void ReplyMsg() { + + if(CurrArea == OrigArea) { + if(AA->Areareplydirect() and reader_msg->areakludgeid) { + int a = AL.AreaEchoToNo(reader_msg->areakludgeid); + if(a != -1) { + CurrArea = AL.AreaNoToId(a); + if(CurrArea != OrigArea) { + _allow_pick = false; + OtherAreaQuoteMsg(); + _allow_pick = true; + return; + } + } + } + } + + if(AA->Msgn.Count() or (CurrArea != OrigArea)) { + reader_topline = 0; + AA->attr().hex0(); + if(AA->attr().r_o()) { + GMenuReadonly MenuReadonly; + reader_keyok = not MenuReadonly.Run(); + } + if(not reader_keyok) + MakeMsg(MODE_REPLY, reader_msg); + } +} + + +// ------------------------------------------------------------------ + +void QuoteMsg() { + + if(CurrArea == OrigArea) { + if(AA->Areareplydirect() and reader_msg->areakludgeid) { + int a = AL.AreaEchoToNo(reader_msg->areakludgeid); + if(a != -1) { + CurrArea = AL.AreaNoToId(a); + if(CurrArea != OrigArea) { + _allow_pick = false; + OtherAreaQuoteMsg(); + _allow_pick = true; + return; + } + } + } + } + + if(AA->Msgn.Count() or (CurrArea != OrigArea)) { + reader_topline = 0; + AA->attr().hex0(); + if(AA->attr().r_o()) { + GMenuReadonly MenuReadonly; + reader_keyok = not MenuReadonly.Run(); + } + if(not reader_keyok) + MakeMsg(MODE_QUOTE, reader_msg); + } +} + + +// ------------------------------------------------------------------ + +void CommentMsg() { + + if(CurrArea == OrigArea) { + if(AA->Areareplydirect() and reader_msg->areakludgeid) { + int a = AL.AreaEchoToNo(reader_msg->areakludgeid); + if(a != -1) { + CurrArea = AL.AreaNoToId(a); + if(CurrArea != OrigArea) { + _allow_pick = false; + OtherAreaCommentMsg(); + _allow_pick = true; + return; + } + } + } + } + + if(AA->Msgn.Count() or (CurrArea != OrigArea)) { + reader_topline = 0; + AA->attr().hex0(); + if(AA->attr().r_o()) { + GMenuReadonly MenuReadonly; + reader_keyok = not MenuReadonly.Run(); + } + if(not reader_keyok) + MakeMsg(MODE_REPLYCOMMENT, reader_msg); + } +} + + +// ------------------------------------------------------------------ + +void OtherAreaQuoteMsg() { + + if(AA->Msgn.Count()) { + int destarea = CurrArea; + if(CurrArea == OrigArea) { + if(*AA->Areareplyto()) { + int a = AL.AreaEchoToNo(AA->Areareplyto()); + if(a != -1) + destarea = AL.AreaNoToId(a); + } + reader_topline = 0; + AA->attr().hex0(); + const char* destinationecho = *reader_msg->fwdarea ? reader_msg->fwdarea : reader_msg->areakludgeid; + if(destinationecho and *destinationecho) { + for(uint n=0; nechoid(), destinationecho)) { + destarea = AL[n]->areaid(); + break; + } + } + } + if(_allow_pick or not AA->Areareplydirect()) + destarea = AreaPick(LNG->ReplyArea, 6, &destarea); + } + if(destarea != -1) { + int adat_viewhidden = AA->adat->viewhidden; + int adat_viewkludge = AA->adat->viewkludge; + int adat_viewquote = AA->adat->viewquote; + AL.SetActiveAreaId(destarea); + if(CurrArea != OrigArea) { + AA->Open(); + if(CurrArea != OrigArea) { + AA->adat->viewhidden = adat_viewhidden; + AA->adat->viewkludge = adat_viewkludge; + AA->adat->viewquote = adat_viewquote; + } + } + QuoteMsg(); + if(CurrArea != OrigArea) { + AA->Close(); + AL.SetActiveAreaId(OrigArea); + } + } + } +} + + +// ------------------------------------------------------------------ + +void OtherAreaCommentMsg() { + + if(AA->Msgn.Count()) { + + int destarea = CurrArea; + if(*AA->Areareplyto()) { + int a = AL.AreaEchoToNo(AA->Areareplyto()); + if(a != -1) + destarea = AL.AreaNoToId(a); + } + reader_topline = 0; + AA->attr().hex0(); + const char* destinationecho = *reader_msg->fwdarea ? reader_msg->fwdarea : reader_msg->areakludgeid; + if(destinationecho and *destinationecho) { + for(uint n=0; nechoid(), destinationecho)) { + destarea = AL[n]->areaid(); + break; + } + } + } + if(_allow_pick or not AA->Areareplydirect()) + destarea = AreaPick(LNG->ReplyArea, 6, &destarea); + if(destarea != -1) { + int adat_viewhidden = AA->adat->viewhidden; + int adat_viewkludge = AA->adat->viewkludge; + int adat_viewquote = AA->adat->viewquote; + AL.SetActiveAreaId(destarea); + if(CurrArea != OrigArea) { + AA->Open(); + if(CurrArea != OrigArea) { + AA->adat->viewhidden = adat_viewhidden; + AA->adat->viewkludge = adat_viewkludge; + AA->adat->viewquote = adat_viewquote; + } + } + CommentMsg(); + if(CurrArea != OrigArea) { + AA->Close(); + AL.SetActiveAreaId(OrigArea); + } + } + } +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/geusrbse.cpp b/golded3/geusrbse.cpp new file mode 100644 index 0000000..23325e1 --- /dev/null +++ b/golded3/geusrbse.cpp @@ -0,0 +1,927 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Userbase (Addressbook) functions. +// ------------------------------------------------------------------ + +#include +#include +#include +#include +#include + + +// ------------------------------------------------------------------ + +guserbase::guserbase() { + + long tries = 0; + + strcpy(fname, AddPath(CFG->goldpath, CFG->golduser)); + + do { + usrbase.open(fname, O_RDWR|O_CREAT|O_BINARY, SH_DENYNO, S_STDRW); + if(not usrbase) { + if((errno != EACCES) or (not PopupLocked(++tries, false, fname))) { + WideLog->ErrOpen(); + WideLog->printf("! GoldED's Addressbook cannot be opened."); + WideLog->printf(": %s", fname); + WideLog->ErrOSInfo(); + OpenErrorExit(); + } + } + } while(not usrbase); + + if(tries) + PopupLocked(0, 0, NULL); + + if((uint) usrbase.filelength() < sizeof(gusrbaseheader) + sizeof(gusrbaseentry)) { + + header.version = 0; + + strcpy(entry.macro, "_asa_"); + strcpy(entry.name, "Alexander S. Aganichev"); + entry.fidoaddr.reset(); + entry.fidoaddr.zone = 2; + entry.fidoaddr.net = 5049; + entry.fidoaddr.node = 49; + entry.fidoaddr.point = 50; + strcpy(entry.iaddr, "asa@eed.miee.ru"); + entry.prefer_internet = YES; + entry.is_deleted = NO; + strcpy(entry.pseudo, "As\'ka"); + strcpy(entry.organisation, "[unemployed]"); + strcpy(entry.snail1, "Zelenograd"); + strcpy(entry.snail2, "Moscow"); + strcpy(entry.snail3, "Russia"); + entry.dataphone[0] = NUL; + entry.voicephone[0] = NUL; + entry.faxphone[0] = NUL; + entry.firstdate = entry.lastdate = entry.times = 0; + strcpy(entry.homepage, "http://asa.i-connect.ru"); + entry.group = 0; + strcpy(entry.comment1, "GoldED+ Maintainer"); + entry.comment2[0] = NUL; + entry.comment3[0] = NUL; + + usrbase.lseek(0, SEEK_SET); + usrbase.write(&header.version, sizeof(header.version)); + write_entry(0); + } + + index = 0; + read_time = 0; // Indicate that we're should reread timestamp + refresh_maximum_index(); + need_update = false; +} + + +// ------------------------------------------------------------------ + +guserbase::~guserbase() { + + usrbase.close(); +} + + +// ------------------------------------------------------------------ + +void guserbase::refresh_maximum_index() { + + // Are we doing it for the first time? + if(not read_time) { + usrbase.getftime(&read_time); + need_update = true; + } + else { + dword tmp; + usrbase.getftime(&tmp); + if(read_time != tmp) { + read_time = tmp; + need_update = true; + } + } + if(need_update) + maximum_index = (usrbase.filelength()-sizeof(gusrbaseheader)) / sizeof(gusrbaseentry) - 1; + if(index > maximum_index) + index = maximum_index; +} + + +// ------------------------------------------------------------------ + +void guserbase::lock() { + + if(WideCanLock) { + + long tries = 0; + + do { + usrbase.lock(0, 1); + if(not usrbase.okay()) { + if(not PopupLocked(++tries, false, fname)) { + WideLog->ErrLock(); + WideLog->printf("! GoldED's Addressbook could not be locked."); + WideLog->printf(": %s", fname); + WideLog->ErrOSInfo(); + LockErrorExit(); + } + } + } while(not usrbase.okay()); + if(tries) + PopupLocked(0, 0, NULL); + } +} + + +// ------------------------------------------------------------------ + +void guserbase::unlock() { + + if(WideCanLock) + usrbase.unlock(0, 1); +} + + +// ------------------------------------------------------------------ + +void guserbase::open() { + + window.openxy(ypos, xpos, ylen+2, xlen+2, btype, battr, 7); + cwidth = (xlen-28) / 2; + + window.message(LNG->UserHeaderName, TP_BORD, 3, tattr); + window.message(LNG->UserHeaderOrg, TP_BORD, 4+cwidth, tattr); + window.message(LNG->UserHeaderAka, TP_BORD, 5+(cwidth*2)/3 + cwidth, tattr); + + center(CFG->displistcursor); +} + + +// ------------------------------------------------------------------ + +void guserbase::close() { + + window.close(); +} + + +// ------------------------------------------------------------------ + +void guserbase::do_delayed() { + + wscrollbar(W_VERT, maximum_index+1, maximum_index, index); + update_statuslinef(LNG->UserStatusline, index+1, maximum_index+1, maximum_index-index); +} + + +// ------------------------------------------------------------------ + +void guserbase::print_line(uint idx, uint pos, bool isbar) { + + char buf[200]; + char buf2[100]; + + read_entry(idx); + + *buf2 = NUL; + + if(AA->isinternet() or not entry.fidoaddr.valid()) { + if(*entry.iaddr) { + strcat(buf2, "<"); + strcat(buf2, entry.iaddr); + strcat(buf2, ">"); + } + } + else { + if(entry.fidoaddr.valid()) { + *buf2 = '('; + entry.fidoaddr.make_string(buf2+1); + strcat(buf2, ")"); + } + } + + sprintf(buf, "%c %-*.*s %-*.*s %s ", + entry.is_deleted ? 'D' : ' ', + cwidth, (int)cwidth, entry.name, + (cwidth*2)/3, (int)(cwidth*2)/3, entry.organisation, + buf2); + + strsetsz(buf, xlen); + window.prints(pos, 0, isbar ? sattr : wattr, buf); +} + + +// ------------------------------------------------------------------ + +addressbook_form::~addressbook_form() { } +addressbook_form::addressbook_form(gwindow& w) : gwinput2(w) { }; +void addressbook_form::after() { gwinput2::after(); }; +void addressbook_form::before() { gwinput2::before(); }; + + +// ------------------------------------------------------------------ + +bool addressbook_form::validate() { + + if(current->id == id_name) { + if(g->find_entry(current->buf)) { + LoadForm(); + reload_all(); + go_next_field(); + } + } + return true; +} + + +// ------------------------------------------------------------------ + +void addressbook_form::LoadForm() { + + gusrbaseentry& entry = g->entry; + + entry.fidoaddr.make_string(fidoaddr); + name = entry.name; + macro = entry.macro; + pseudo = entry.pseudo; + iaddr = entry.iaddr; + organisation = entry.organisation; + voicephone= entry.voicephone; + faxphone = entry.faxphone; + dataphone = entry.dataphone; + snail1 = entry.snail1; + snail2 = entry.snail2; + snail3 = entry.snail3; + comment1 = entry.comment1; + comment2 = entry.comment2; + comment3 = entry.comment3; + homepage = entry.homepage; +} + + +// ------------------------------------------------------------------ + +void addressbook_form::SaveForm() { + + gusrbaseentry& entry = g->entry; + entry.fidoaddr.reset(); + entry.fidoaddr.set(fidoaddr); + strcpy(entry.name, name.c_str()); + strcpy(entry.macro, macro.c_str()); + strcpy(entry.pseudo, pseudo.c_str()); + strcpy(entry.iaddr, iaddr.c_str()); + strcpy(entry.organisation, organisation.c_str()); + strcpy(entry.voicephone, voicephone.c_str()); + strcpy(entry.faxphone, faxphone.c_str()); + strcpy(entry.dataphone, dataphone.c_str()); + strcpy(entry.snail1, snail1.c_str()); + strcpy(entry.snail2, snail2.c_str()); + strcpy(entry.snail3, snail3.c_str()); + strcpy(entry.comment1, comment1.c_str()); + strcpy(entry.comment2, comment2.c_str()); + strcpy(entry.comment3, comment3.c_str()); + strcpy(entry.homepage, homepage.c_str()); +} + + +// ------------------------------------------------------------------ + +bool guserbase::edit_entry(uint idx) { + + gwindow window; + char tbuf[50]; + + const int width = 75; + const int height = 16; + + window.openxy((MAXROW-height)/2, (MAXCOL-width)/2, height, width, btype, battr, wattr); + window.shadow(C_SHADOW); + + sprintf(tbuf, " Record <%d> ", idx+1); + window.title(tbuf, tattr); + + window.prints( 0, 1, wattr, "Full Name :"); + window.prints( 1, 1, wattr, "Macro Name:"); + window.prints( 1,34, wattr, "Nick Name :"); + window.prints( 2, 1, wattr, "Fidonet :"); + window.prints( 2,34, wattr, "Internet :"); + window.prints( 3, 1, wattr, "Organisat.:"); + window.horizontal_line(4, 0, width-2, btype, battr); + + window.prints( 5, 1, wattr, "Voice Num.:"); + window.prints( 6, 1, wattr, "Fax Number:"); + window.prints( 7, 1, wattr, "Data Num. :"); + window.prints( 5,34, wattr, "Address(1):"); + window.prints( 6,34, wattr, "Address(2):"); + window.prints( 7,34, wattr, "Address(3):"); + window.prints( 8, 1, wattr, "Group :"); + window.prints( 8,34, wattr, "Homepage :"); + window.prints( 9, 1, wattr, "Comment(1):"); + window.prints(10, 1, wattr, "Comment(2):"); + window.prints(11, 1, wattr, "Comment(3):"); + window.horizontal_line(12, 0, width-2, btype, battr); + + window.prints(13, 1, wattr, "First Used:"); + window.prints(13, 27, wattr, "Last Used:"); + window.prints(13, 53, wattr, "Times Used:"); + + char dbuf[16]; + time_t dt = entry.firstdate; + if(dt) + window.prints(13, 13, wattr, strftimei(dbuf, 16, "%d %b %y", gmtime(&dt))); + dt = entry.lastdate; + if(dt) + window.prints(13, 38, wattr, strftimei(dbuf, 16, "%d %b %y", gmtime(&dt))); + + sprintf(dbuf, "%8ld", entry.times); + window.prints(13, width-11, wattr, dbuf); + + addressbook_form form(window); + form.g = this; + form.setup(C_HEADW, C_HEADW, C_HEADE, _box_table(W_BHEAD, 13), true); + + read_entry(idx); + form.LoadForm(); + + form.add_field(addressbook_form::id_name, 0, 13, 59, form.name, sizeof(entry.name)); + form.add_field(addressbook_form::id_macro, 1, 13, 20, form.macro, sizeof(entry.macro)); + form.add_field(addressbook_form::id_pseudo, 1, 46, 26, form.pseudo, sizeof(entry.pseudo)); + form.add_field(addressbook_form::id_fidoaddr, 2, 13, 20, form.fidoaddr, 24); + form.add_field(addressbook_form::id_iaddr, 2, 46, 26, form.iaddr, sizeof(entry.iaddr)); + form.add_field(addressbook_form::id_organisation, 3, 13, 59, form.organisation, sizeof(entry.organisation)); + form.add_field(addressbook_form::id_voicephone, 5, 13, 20, form.voicephone, sizeof(entry.voicephone)); + form.add_field(addressbook_form::id_faxphone, 6, 13, 20, form.faxphone, sizeof(entry.faxphone)); + form.add_field(addressbook_form::id_dataphone, 7, 13, 20, form.dataphone, sizeof(entry.dataphone)); + form.add_field(addressbook_form::id_snail1, 5, 46, 26, form.snail1, sizeof(entry.snail1)); + form.add_field(addressbook_form::id_snail2, 6, 46, 26, form.snail2, sizeof(entry.snail2)); + form.add_field(addressbook_form::id_snail3, 7, 46, 26, form.snail3, sizeof(entry.snail3)); + form.add_field(addressbook_form::id_homepage , 8, 46, 26, form.homepage, sizeof(entry.homepage)); + form.add_field(addressbook_form::id_comment1, 9, 13, 59, form.comment1, sizeof(entry.comment1)); + form.add_field(addressbook_form::id_comment2, 10, 13, 59, form.comment2, sizeof(entry.comment2)); + form.add_field(addressbook_form::id_comment3, 11, 13, 59, form.comment3, sizeof(entry.comment3)); + + form.run(H_EditAdrEntry); + window.close(); + + if(not form.dropped) + form.SaveForm(); + + return not form.dropped; +} + + +// ------------------------------------------------------------------ + +bool guserbase::find_entry(char* name, bool lookup) { + + gusrbaseentry ent; + + if(not strblank(name)) { + refresh_maximum_index(); + usrbase.lseek(sizeof(gusrbaseheader), SEEK_SET); + for(uint i=0; i<=maximum_index; i++) { + read_entry(i, &ent); + + if(strieql(name, ent.name) or (lookup and strieql(name, ent.macro))) { + strcpy(entry.macro, ent.macro); + strcpy(entry.name, ent.name); + entry.fidoaddr = ent.fidoaddr; + strcpy(entry.iaddr, ent.iaddr); + entry.prefer_internet = ent.prefer_internet; + entry.is_deleted = ent.is_deleted; + strcpy(entry.pseudo, ent.pseudo); + strcpy(entry.organisation, ent.organisation); + strcpy(entry.snail1, ent.snail1); + strcpy(entry.snail2, ent.snail2); + strcpy(entry.snail3, ent.snail3); + strcpy(entry.dataphone, ent.dataphone); + strcpy(entry.voicephone, ent.voicephone); + strcpy(entry.faxphone, ent.faxphone); + entry.firstdate = ent.firstdate; + entry.lastdate = ent.lastdate; + entry.times = ent.times; + strcpy(entry.homepage, ent.homepage); + entry.group = ent.group; + strcpy(entry.comment1, ent.comment1); + strcpy(entry.comment2, ent.comment1); + strcpy(entry.comment3, ent.comment1); + index = i; + return true; + } + } + } + + return false; +} + + +// ------------------------------------------------------------------ + +void guserbase::write_entry(uint idx, bool updateit) { + + if(updateit and not entry.is_deleted) { + time_t a = time(NULL); + time_t b = mktime(gmtime(&a)); + entry.lastdate = a + a - b; + if(not entry.firstdate) + entry.firstdate = entry.lastdate; + + entry.times++; + } + + usrbase.lseek(sizeof(gusrbaseheader) + sizeof(gusrbaseentry)*(idx+1)-1, SEEK_SET); + char z = 0; + usrbase.write(&z, 1); // adjust entry size first... + usrbase.lseek(sizeof(gusrbaseheader) + sizeof(gusrbaseentry)*idx, SEEK_SET); + usrbase.write(entry.macro, sizeof(entry.macro)); + usrbase.write(entry.name, sizeof(entry.name)); + usrbase.write(&entry.fidoaddr.zone, sizeof(entry.fidoaddr.zone)); + usrbase.write(&entry.fidoaddr.net, sizeof(entry.fidoaddr.net)); + usrbase.write(&entry.fidoaddr.node, sizeof(entry.fidoaddr.node)); + usrbase.write(&entry.fidoaddr.point, sizeof(entry.fidoaddr.point)); + usrbase.write(entry.iaddr, sizeof(entry.iaddr)); + usrbase.write(&entry.prefer_internet, sizeof(entry.prefer_internet)); + usrbase.write(&entry.is_deleted, sizeof(entry.is_deleted)); + usrbase.write(entry.pseudo, sizeof(entry.pseudo)); + usrbase.write(entry.organisation, sizeof(entry.organisation)); + usrbase.write(entry.snail1, sizeof(entry.snail1)); + usrbase.write(entry.snail2, sizeof(entry.snail2)); + usrbase.write(entry.snail3, sizeof(entry.snail3)); + usrbase.write(entry.dataphone, sizeof(entry.dataphone)); + usrbase.write(entry.voicephone, sizeof(entry.voicephone)); + usrbase.write(entry.faxphone, sizeof(entry.faxphone)); + usrbase.write(&entry.firstdate, sizeof(entry.firstdate)); + usrbase.write(&entry.lastdate, sizeof(entry.lastdate)); + usrbase.write(&entry.times, sizeof(entry.times)); + usrbase.write(entry.homepage, sizeof(entry.homepage)); + usrbase.write(&entry.group, sizeof(entry.group)); + usrbase.write(entry.comment1, sizeof(entry.comment1)); + usrbase.write(entry.comment2, sizeof(entry.comment1)); + usrbase.write(entry.comment3, sizeof(entry.comment1)); +} + +// ------------------------------------------------------------------ + +void guserbase::clear_entry(gusrbaseentry *ent) { + + ent->macro[0] = NUL; + ent->name[0] = NUL; + ent->fidoaddr.reset(); + ent->iaddr[0] = NUL; + ent->prefer_internet = NO; + ent->is_deleted = NO; + ent->pseudo[0] = NUL; + ent->organisation[0] = NUL; + ent->snail1[0] = NUL; + ent->snail2[0] = NUL; + ent->snail3[0] = NUL; + ent->dataphone[0] = NUL; + ent->voicephone[0] = NUL; + ent->faxphone[0] = NUL; + ent->firstdate = ent->lastdate = ent->times = 0; + ent->homepage[0] = NUL; + ent->group = 0; + ent->comment1[0] = NUL; + ent->comment2[0] = NUL; + ent->comment3[0] = NUL; +} + +// ------------------------------------------------------------------ + +bool guserbase::read_entry(uint idx, gusrbaseentry *ent) { + + if(ent == NULL) + ent = &entry; + refresh_maximum_index(); + if(idx > maximum_index) { + clear_entry(ent); + return false; + } + else { + usrbase.lseek(idx*sizeof(gusrbaseentry)+sizeof(gusrbaseheader), SEEK_SET); + usrbase.read(ent->macro, sizeof(ent->macro)); + usrbase.read(ent->name, sizeof(ent->name)); + usrbase.read(&ent->fidoaddr.zone, sizeof(ent->fidoaddr.zone)); + usrbase.read(&ent->fidoaddr.net, sizeof(ent->fidoaddr.net)); + usrbase.read(&ent->fidoaddr.node, sizeof(ent->fidoaddr.node)); + usrbase.read(&ent->fidoaddr.point, sizeof(ent->fidoaddr.point)); + usrbase.read(ent->iaddr, sizeof(ent->iaddr)); + usrbase.read(&ent->prefer_internet, sizeof(ent->prefer_internet)); + usrbase.read(&ent->is_deleted, sizeof(ent->is_deleted)); + usrbase.read(ent->pseudo, sizeof(ent->pseudo)); + usrbase.read(ent->organisation, sizeof(ent->organisation)); + usrbase.read(ent->snail1, sizeof(ent->snail1)); + usrbase.read(ent->snail2, sizeof(ent->snail2)); + usrbase.read(ent->snail3, sizeof(ent->snail3)); + usrbase.read(ent->dataphone, sizeof(ent->dataphone)); + usrbase.read(ent->voicephone, sizeof(ent->voicephone)); + usrbase.read(ent->faxphone, sizeof(ent->faxphone)); + usrbase.read(&ent->firstdate, sizeof(ent->firstdate)); + usrbase.read(&ent->lastdate, sizeof(ent->lastdate)); + usrbase.read(&ent->times, sizeof(ent->times)); + usrbase.read(ent->homepage, sizeof(ent->homepage)); + usrbase.read(&ent->group, sizeof(ent->group)); + usrbase.read(ent->comment1, sizeof(ent->comment1)); + usrbase.read(ent->comment2, sizeof(ent->comment1)); + usrbase.read(ent->comment3, sizeof(ent->comment1)); + return true; + } +} + + +// ------------------------------------------------------------------ + +void guserbase::pack_addressbook() { + + long tries = 0; + + lock(); + refresh_maximum_index(); + uint nidx = 0; + uint nindex = index; + for(uint idx = 0; idx <= maximum_index; idx++) { + read_entry(idx); + if(not entry.is_deleted) { + if(nidx != idx) + write_entry(nidx); + ++nidx; + } + else if(idx < index) + --nindex; + } + index = nindex; + // zap + maximum_index = nidx; + // At least one record should present + if(maximum_index) + --maximum_index; + usrbase.chsize((maximum_index + 1) * sizeof(gusrbaseentry) + sizeof(gusrbaseheader)); + usrbase.close(); + + do { + usrbase.open(fname, O_RDWR|O_CREAT|O_BINARY, SH_DENYNO, S_STDRW); + if(not usrbase) { + if((errno != EACCES) or (not PopupLocked(++tries, false, fname))) { + WideLog->ErrOpen(); + WideLog->printf("! GoldED's Addressbook cannot be opened."); + WideLog->printf(": %s", fname); + WideLog->ErrOSInfo(); + OpenErrorExit(); + } + } + } while(not usrbase); + + if(tries) + PopupLocked(0, 0, NULL); + + unlock(); +} + + +// ------------------------------------------------------------------ + +void guserbase::update_screen(bool force) { + + refresh_maximum_index(); + if(force or need_update) { + if(position > index) + center(CFG->displistcursor); + update(); + do_delayed(); + need_update = false; + } +} + + +// ------------------------------------------------------------------ + +bool guserbase::handle_key() { + + switch(key) { + case Key_Esc: + aborted = true; + return false; + case Key_Ins: // Add new entry + { + clear_entry(&entry); + lock(); + refresh_maximum_index(); + uint nidx = maximum_index + 1; + if(edit_entry(nidx)) { + if(nidx == maximum_index + 1) { + maximum_index++; + if(maximum_position < ylen-1) + maximum_position = maximum_index; + } + write_entry(nidx); + index = nidx; + } + unlock(); + center(CFG->displistcursor); + } + break; + case Key_Ent: // Select/Edit entry + if(not select_list) { + if(not entry.is_deleted) { + lock(); + if(edit_entry(index)) { + write_entry(index); + display_bar(); + } + unlock(); + } + break; + } + else { + aborted = false; + return false; + } + case Key_Del: // Soft-Delete Entry + lock(); + refresh_maximum_index(); + read_entry(index); + entry.is_deleted = not entry.is_deleted; + write_entry(index); + unlock(); + update_screen(); + break; + case Key_A_P: // Pack Addressbook + pack_addressbook(); + index = position = 0; + update_screen(); + break; + + case Key_Tick: + CheckTick(0); // KK_UserQuitNow ??? + break; + default: + SayBibi(); + } + return true; +} + + +// ------------------------------------------------------------------ + +bool guserbase::run(GMsg* msg, bool selectonly) { + + select_list = selectonly; + + ypos = selectonly ? 6 : 1; + xpos = 0; + ylen = MAXROW-3-ypos; + xlen = MAXCOL-2; + btype = W_BMENU; + battr = C_MENUB; + wattr = C_MENUW; + tattr = C_MENUT; + sattr = C_MENUS; + hattr = C_MENUQ; + sbattr = C_MENUPB; + helpcat = H_Userbase; + listwrap = CFG->switches.get(displistwrap); + maximum_position = MinV(maximum_index, ylen - 1); + + if(not select_list) + find_entry(msg->By(), false); + + run_picker(); + + if(not aborted) { + read_entry(index); + + // other stuff not yet implemented + } + + return not aborted; +} + + +// ------------------------------------------------------------------ + +void guserbase::update_addressbook(GMsg* msg, bool reverse, bool force) { + + Addr fidoaddr; + IAdr iaddr; + INam name; + + strcpy(name, (reverse ? msg->By() : msg->To())); + strcpy(iaddr, (reverse ? msg->iorig : msg->idest)); + fidoaddr = (reverse ? msg->orig : msg->dest); + + if(not strblank(name)) { + if(find_entry(name)) { + if(not force) + if((CFG->addressbookadd == NO) or ((CFG->addressbookadd == YES) and not (AA->isnet() or AA->isemail()))) + return; + } + else { + + if(not force) { + + // Don't automatically add the user if... + // 1. It's not allowed + if((CFG->addressbookadd == NO) or ((CFG->addressbookadd == YES) and not (AA->isnet() or AA->isemail()))) + return; + + // 2. It's a robotname + for(gstrarray::iterator n = CFG->robotname.begin(); n != CFG->robotname.end(); n++) + if(striinc(n->c_str(), name)) + return; + + // 3. It's a username + if(is_user(name)) + return; + + // 4. It's a WHOTO name + if(strieql(AA->Whoto(), name)) + return; + + // 5. It's the mailinglist's sender address + if(AA->isemail()) { + vector::iterator z; + for(z = CFG->mailinglist.begin(); z != CFG->mailinglist.end(); z++) + if(strieql(z->sender, name) or strieql(z->sender, iaddr)) + return; + } + + // 6. If it is already an email address + if(AA->isemail() and strchr(name, '@')) + return; + + + // 7. User listed in nodelist + const char *nlname = lookup_nodelist(&fidoaddr); + if(nlname and strieql(nlname, name)) + return; + + } + + // Ok, let's add it... + clear_entry(&entry); + + strxcpy(entry.name, name, sizeof(entry.name)); + + refresh_maximum_index(); + index = ++maximum_index; + } + + if((AA->isinternet() and strblank(iaddr)) or (not AA->isinternet() and not fidoaddr.valid())) + return; + + // Update address + if(AA->isinternet()) + strxcpy(entry.iaddr, iaddr, sizeof(entry.iaddr)); + else + entry.fidoaddr = fidoaddr; + + lock(); + write_entry(index, not force); + unlock(); + } +} + + +// ------------------------------------------------------------------ + +bool guserbase::lookup_addressbook(GMsg* msg, char* name, char* aka, bool browser) { + + bool found = false; + + if(not strblank(name) or browser) { + w_info(LNG->UserWait); + + if((find_entry(name, true) and not entry.is_deleted) or browser) { + + if(browser) { + if(not run(msg, true)) { + w_info(NULL); + return false; + } + } + + found = true; + + strcpy(name, entry.name); + if(not strblank(entry.pseudo)) + strcpy(msg->pseudoto, entry.pseudo); + + if(aka) { + *aka = NUL; + if(AA->isinternet()) + strcpy(aka, entry.iaddr); + else { + entry.fidoaddr.make_string(aka); + if(strblank(aka) and not strblank(entry.iaddr)) { + // do UUCP addressing + strcpy(msg->realto, entry.name); + strcpy(name, entry.iaddr); + strcpy(msg->iaddr, entry.iaddr); + } + } + } + } + w_info(NULL); + return found ? (aka ? not strblank(aka) : true) : false; + } + return false; +} + + +// ------------------------------------------------------------------ + +void guserbase::build_pseudo(GMsg* msg, char* name, char* aka, bool direction) { + + strcpy(direction ? msg->pseudoto : msg->pseudofrom, strlword(name)); + + if(find_entry(name, true) and not entry.is_deleted) { + + if(not strblank(entry.pseudo)) { + + if(AA->isinternet()) { + if(strcmp(aka, entry.iaddr)) + return; + } + else { + Addr AKA = aka; + if(entry.fidoaddr != AKA) + return; + } + + strcpy(direction ? msg->pseudoto : msg->pseudofrom, entry.pseudo); + + } + } +} + + +// ------------------------------------------------------------------ + +void update_addressbook(GMsg* msg, bool reverse, bool force) { + + guserbase p; + + p.update_addressbook(msg, reverse, force); +} + + +// ------------------------------------------------------------------ + +bool lookup_addressbook(GMsg* msg, char* name, char* aka, bool browser) { + + guserbase p; + + bool result = p.lookup_addressbook(msg, name, aka, browser); + + return result; +} + + +// ------------------------------------------------------------------ + +void build_pseudo(GMsg* msg, bool direction) { + + guserbase p; + char buf[128]; + + if(direction) + p.build_pseudo(msg, strbtrim(msg->To()), msg->dest.make_string(buf)); + else + p.build_pseudo(msg, strbtrim(msg->By()), msg->orig.make_string(buf), false); +} + + +// ------------------------------------------------------------------ + +void edit_addressbook(GMsg* msg) { + + guserbase p; + + p.run(msg, false); + +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/geusrbse.h b/golded3/geusrbse.h new file mode 100644 index 0000000..75919e5 --- /dev/null +++ b/golded3/geusrbse.h @@ -0,0 +1,196 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// GEUSRBSE header file. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +#if defined(GOLD_CANPACK) +#pragma pack(1) +#endif + +struct gusrbaseheader { + word version; + byte reserved[4094]; +}; + + +struct gusrbaseentry { + + char macro[20]; + IAdr name; + ftn_addr fidoaddr; + IAdr iaddr; + byte prefer_internet; + byte is_deleted; + + char pseudo[40]; + char organisation[78]; + char snail1[78]; + char snail2[78]; + char snail3[78]; + + char dataphone[40]; + char voicephone[40]; + char faxphone[40]; + + ulong firstdate; + ulong lastdate; + ulong times; + + char homepage[128]; + byte group; + + char comment1[78]; + char comment2[78]; + char comment3[78]; + + byte reserved[915]; +}; + + +#if defined(GOLD_CANPACK) +#pragma pack() +#endif + + +// ------------------------------------------------------------------ + +class guserbase; + +class addressbook_form : public gwinput2 { + + string macro; + string name; + string fidoaddr; + string iaddr; + string pseudo; + string organisation; + string snail1; + string snail2; + string snail3; + string dataphone; + string voicephone; + string faxphone; + string homepage; + string comment1; + string comment2; + string comment3; + + bool validate(); + void before(); + void after(); + + void LoadForm(); + void SaveForm(); + + enum { + id_macro, + id_name, + id_fidoaddr, + id_iaddr, + id_prefer_internet, + id_pseudo, + id_organisation, + id_snail1, + id_snail2, + id_snail3, + id_dataphone, + id_voicephone, + id_faxphone, + id_firstdate, + id_lastdate, + id_times, + id_homepage, + id_group, + id_comment1, + id_comment2, + id_comment3 + }; + + friend class guserbase; + +public: + guserbase* g; + + addressbook_form(gwindow& w); + virtual ~addressbook_form(); + + void select(); +}; + + +// ------------------------------------------------------------------ + +class guserbase : public gwinpick { + +private: + + gwindow window; + gfile usrbase; + gusrbaseheader header; + gusrbaseentry entry; + uint cwidth; + bool select_list; + bool need_update; + dword read_time; + Path fname; + + void open(); + void close(); + void lock(); + void unlock(); + void refresh_maximum_index(); + void print_line(uint idx, uint pos, bool isbar); + void do_delayed(); + bool handle_key(); + + bool edit_entry(uint idx); + void clear_entry(gusrbaseentry *ent); + bool read_entry(uint idx, gusrbaseentry *ent=NULL); + void write_entry(uint idx, bool updateit = false); + bool find_entry(char* name, bool lookup = false); + void pack_addressbook(); + void update_screen(bool force = true); + + friend class addressbook_form; + +public: + + bool lookup_addressbook(GMsg* msg, char* name, char* aka, bool browser); + void build_pseudo(GMsg* msg, char* name, char* aka, bool direction = true); + void update_addressbook(GMsg* msg, bool reverse = false, bool force = false); + bool run(GMsg* msg, bool selectonly); + + + guserbase(); + ~guserbase(); +}; + + +// ------------------------------------------------------------------ diff --git a/golded3/geutil.cpp b/golded3/geutil.cpp new file mode 100644 index 0000000..fa65d9c --- /dev/null +++ b/golded3/geutil.cpp @@ -0,0 +1,566 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Global utility functions (not overlayed in 16-bit DOS). +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +extern bool in_arealist; +extern GPickArealist* PickArealist; + + +// ------------------------------------------------------------------ + +void update_statuslines() { + + char buf[200]; + static char old_status_line[200] = ""; + static int called = NO; + + HandleGEvent(EVTT_REMOVEVOCBUF); + + if(CFG->switches.get(dispstatusline) or not called) { + + called = YES; + + vchar sep = _box_table(W_BSTAT, 3); + char help[200], meminfo[200], clkinfo[200]; + *clkinfo = NUL; + *meminfo = NUL; + *help = NUL; + + if(CFG->switches.get(statuslineclock)) { + time_t t = time(NULL); + sprintf(clkinfo, " %c %s", sep, strftimei(help, 40, LNG->StatusLineTimeFmt, localtime(&t))); + } + + if(CFG->statuslinehelp == -1) + *help = NUL; + else if(CFG->statuslinehelp) + sprintf(help, "%s %c ", LNG->StatusLineHelp, sep); + else + sprintf(help, "%s%s%s%s%c%s%i.%i.%i%s %c ", + __gver_prename__, + __gver_name__, + __gver_postname__, + __gver_platform__, + goldmark, + __gver_preversion__, + __gver_major__, + __gver_minor__, + __gver_release__, + __gver_postversion__, + sep + ); + + int len = MAXCOL-strlen(help)-strlen(meminfo)-strlen(clkinfo)-2; + sprintf(buf, " %s%-*.*s%s%s ", help, len, len, information, meminfo, clkinfo); + + if(streql(old_status_line, buf)) + return; + strcpy(old_status_line, buf); + + #ifdef GOLD_MOUSE + gmou.GetStatus(); + if(gmou.Row() == MAXROW-1) + gmou.HideCursor(); + #endif + int row, col; + vposget(&row, &col); + wwprintstr(W_STAT, 0,0, C_STATW, buf); + vposset(row, col); + #ifdef GOLD_MOUSE + if(gmou.Row() == MAXROW-1) + gmou.ShowCursor(); + #endif + } +} + + +// ------------------------------------------------------------------ + +void update_statusline(const char* info) { + + strxcpy(information, info, sizeof(Subj)); + update_statuslines(); +} + + +// ------------------------------------------------------------------ + +void update_statuslinef(const char* format, ...) { + + va_list argptr; + va_start(argptr, format); + vsprintf(information, format, argptr); + va_end(argptr); + update_statuslines(); +} + + +// ------------------------------------------------------------------ + +void w_shadow() { + + if(CFG->switches.get(screenshadows)) + wshadow(C_SHADOW); +} + + +// ------------------------------------------------------------------ + +void w_info(const char* info) { + + static int wh=-1; + static int srow; + static int scol; + static int erow; + static int ecol; + static int len; + static char buf[150] = { "" }; + char* buf2 = NULL; + + int prev_wh = whandle(); + if(wh != -1) + wactiv_(wh); + + if(info) { + int tmp = strlen(info); + if(tmp > MAXCOL-5) { + buf2 = (char *)throw_malloc(MAXCOL-5); + strxcpy(buf2, info, MAXCOL-5); + info = buf2; + tmp = MAXCOL-6; + } + if(wh == -1) { + len = tmp; + srow = inforow; + erow = srow+3-1; + scol = ((MAXCOL-len)/2)-1; + ecol = scol+len+1; + wh = wopen(srow, scol, erow, ecol, W_BINFO, C_INFOB, C_INFOW); + w_shadow(); + } + else { + if(len != tmp) { + len = tmp; + scol = ((MAXCOL-len)/2)-1; + ecol = scol+len+1; + wclose(); + wh = wopen(srow, scol, erow, ecol, W_BINFO, C_INFOB, C_INFOW); + w_shadow(); + } + } + if(not streql(buf, info)) { + strcpy(buf, info); + wprints(0, 0, C_INFOW, buf); + } + } + else { + if(wh != -1) { + *buf = NUL; + wclose(); + wh = -1; + } + } + + wactiv_(prev_wh); + + if(buf2) + throw_free(buf2); +} + + +// ------------------------------------------------------------------ + + +void w_infof(const char* format, ...) { + + char winfobuf[350]; + va_list argptr; + va_start(argptr, format); + vsprintf(winfobuf, format, argptr); + va_end(argptr); + w_info(winfobuf); +} + + +// ------------------------------------------------------------------ + +void w_progress(int mode, int attr, long pos, long size, const char* title) { + + static int wh = -1; + + int prev_wh = whandle(); + if(wh != -1) + wactiv_(wh); + + switch(mode) { + case MODE_NEW: + oops: + if(wh == -1) { + wh = wopen_(inforow, ((MAXCOL-63)/2)-1, 3, 63, W_BINFO, C_INFOB, C_INFOW); + set_title(title, TCENTER, C_INFOT); + title_shadow(); + } + case MODE_UPDATE: + if(wh == -1) + goto oops; // Oops, someone forgot to open the window.. + wpropbar(PROP_BARGRAPH, 1, 0, -59, 1, attr, pos, size); + break; + case MODE_QUIT: + if(wh != -1) { + wclose(); + wunlink(wh); + wh = -1; + } + break; + } + + wactiv_(prev_wh); +} + + +// ------------------------------------------------------------------ + +void maketitle() { + + wtitle(m_title, m_titlepos, m_titleattr); +} + + +// ------------------------------------------------------------------ + +void set_title(const char* t, int p, int a) { + + strcpy(m_title, t); + m_titlepos = p; + m_titleattr = a; +} + + +// ------------------------------------------------------------------ + +void title_shadow() { + + maketitle(); + w_shadow(); +} + + +// ------------------------------------------------------------------ + +int IsQuoteChar(const char* s) { + + if(*s) { + if(*s == '>') + return true; + if(*AA->Quotechars()) + if(strchr(AA->Quotechars(), *s)) + return true; + } + return false; +} + + +// ------------------------------------------------------------------ + +int is_quote(const char* ptr) { + + const char* endptr = ptr + 11; + + // Skip leading whitespace + while((*ptr == ' ') or (*ptr == LF) or issoftcr(*ptr)) + ptr++; + + // Check for empty string + if((*ptr == NUL) or (ptr >= endptr)) + return false; + + // Check for userdefined quotechars after first whitespace + if(IsQuoteChar(ptr)) + return true; + + int spaces = 0; + while((ptr < endptr) and *ptr) { + + if(*ptr == LF or issoftcr(*ptr)) { + // Ignore LF's and SOFTCR's and extend check zone if found + endptr++; + } + else if(*ptr == '>') { + // Found true quote char + return true; + } + else if(*ptr == ' ') { + spaces++; + if(spaces > 1) + return false; + } + else if((*ptr < ' ') or strchr("<\"\'-", *ptr)) { + // Found a char that cannot occur in a quotestring + return false; + } + ptr++; + } + + return false; +} + + +// ------------------------------------------------------------------ + +int quotecolor(const char* line) { + + char buf[100]; + uint len; + + GetQuotestr(line, buf, &len); + uint qc = 0; + + for(uint i=0; ixxxx>" and ">xxxx:" + lp++; + while(isspace(*lp) or issoftcr(*lp)) + lp++; + if(is_quote(lp)) + goto MoreQuotes; + if(not (IsQuoteChar(lp-1) or (*(lp-1) == ':'))) { + while(not IsQuoteChar(lp)) + lp--; + lp++; + } + } + else { // Type 2: "xxxx>" + while(not (IsQuoteChar(lp) and not IsQuoteChar(lp+1)) and *lp != CR and *lp) + ++lp; + if(is_quote(lp)) + goto MoreQuotes; + if(*lp) + lp++; + } + + // lp now points to the character after the quotestring + + *qlen = (int)((dword)lp - (dword)ptr); + if(isspace(*lp) or issoftcr(*lp)) + (*qlen)++; + + for(x=*qlen,n=0,tmp=ptr,qptr=qbuf; n 40) + *qlen = 40; + } + else { + *qbuf = NUL; + *qlen = 0; + } + + return *qlen; +} + + +// ------------------------------------------------------------------ + +static int KeyCmp(const gkey* a, const gkey* b) { + + return CmpV(*a, *b); +} + + +// ------------------------------------------------------------------ + +gkey SearchKey(gkey key, list::iterator keys, int totkeys) { + + list::iterator kmin; + int again = 0; + + do { + kmin = keys; + int tkeys=totkeys; + while(tkeys > 0) { + int j = KeyCmp(&key, &(kmin->key)); + if(j == 0) + return(kmin->cmd); + else if(j < 0) + break; + else { + kmin++; + tkeys--; + } + } + + // Key not found. Try again, this time without the scancode. + key &= 0x00FF; + } while(not again++ and key); + + return 0; +} + + +// ------------------------------------------------------------------ + +static void call_func_geutil(VfvCP func) { + + struct _menu_t* menu; + int row, col; + + bool hidden = vcurhidden(); + vposget(&row, &col); + menu = gwin.cmenu; + (*func)(); + gwin.cmenu = menu; + vposset(row, col); + if(hidden) + vcurhide(); + else + vcurshow(); +} + + +// ------------------------------------------------------------------ + +void call_help() { + + // search through onkey linked list for a + // matching defined onkey. if one is found, + // then save the current environment, call the + // onkey's function, and restore the environment. + + KBnd* onkey = gkbd.onkey; + while(onkey != NULL) { + if(onkey->keycode == Key_F1) { + call_func_geutil(onkey->func); + break; + } + onkey = onkey->prev; + } +} + + +// ------------------------------------------------------------------ + +void CheckTick(gkey quitkey) { + + Clock idle_secs = (gkbd.tickvalue - gkbd.tickpress) / 10L; + + if(CFG->timeout) { + if(idle_secs >= CFG->timeout) { + kbput(quitkey); + return; + } + } + + IdleCheckSemaphores(); + + if(CFG->screenblanker) { + if(idle_secs >= CFG->screenblanker) { + + blanked = true; + ScreenBlankIdle(); + kbdsettickfunc(ScreenBlankIdle); + + getxch(); + + blanked = false; + ScreenBlankIdle(); + kbdsettickfunc(update_statuslines); + + //maybe we've scanned areas while in screenblanker, so + //update screen + if(in_arealist) { + PickArealist->update(); + PickArealist->do_delayed(); + } + } + } +} + + +// ------------------------------------------------------------------ + +void IdleCheckSemaphores() { + + // I don't like this solution either... :( + static Clock last_secs = 0; + Clock idle_secs = (gkbd.tickvalue - gkbd.tickpress) / 10L; + + // Make sure the stuff below is only run once in a second + if(not idle_secs or (idle_secs - last_secs == 0)) + return ; + + if(in_arealist) { + if(CFG->semaphore.idletime) { + if((idle_secs % CFG->semaphore.idletime) == 0) + CheckSemaphores(); + } + } + + last_secs = idle_secs; +} + + +// ------------------------------------------------------------------ + +char* strtmp(const char* str) { + + static INam tmp; + return strxcpy(tmp, str, sizeof(tmp)); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/geutil2.cpp b/golded3/geutil2.cpp new file mode 100644 index 0000000..6f8b1ee --- /dev/null +++ b/golded3/geutil2.cpp @@ -0,0 +1,321 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Global utility functions. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +int edit_string(char* buf, int buf_size, char* title, int helpcat) { + + gwindow window; + + window.openxy(inforow,((MAXCOL-63)/2)-1,3,63,W_BASK,C_ASKB,C_ASKW); + window.title(title, C_ASKT); + if(CFG->switches.get(screenshadows)) + window.shadow(C_SHADOW); + + gwinput2 iform(window); + + string buf2 = buf; + iform.setup(C_ASKW, C_ASKW, C_ASKQ, _box_table(W_BASK, 13), true); + iform.add_field(0, 0, 1, 59, buf2, buf_size, gwinput::cvt_none, fieldupd); + vcurshow(); + iform.run(helpcat); + vcurhide(); + + window.close(); + + if(iform.dropped) + return false; + + size_t len = buf2.length(); + while(len and ('!' > buf2[--len])) + buf2.erase(len, 1); + strcpy(buf, buf2.c_str()); + return *buf ? true : false; +} + + +// ------------------------------------------------------------------ + +bool edit_pathname(char* buf, int buf_size, char* title, int helpcat) { + + if(not edit_string(buf, buf_size, title, helpcat)) + return false; + + vector::iterator z; + for(z = CFG->filealias.begin(); z != CFG->filealias.end(); z++) { + if(strieql(buf, z->alias)) { + strcpy(buf, z->file); + break; + } + } + + strschg_environ(buf); + return true; +} + + +// ------------------------------------------------------------------ + +int PopupLocked(long tries, int isopen, const char* file) { + + // Close popup window if requested + if(tries == 0) { + w_info(NULL); + return true; + } + + // Tell the world + char buf[200]; + if((uint) strlen(file) > (uint) (MAXCOL-25)) + sprintf(buf, "[..]%*.*s", MAXCOL-30, MAXCOL-30, file); + else + strcpy(buf, file); + w_infof(LNG->WaitLocked, buf); + update_statuslinef(LNG->RetryOrESC, isopen ? LNG->RetryLock : LNG->RetryOpen , tries); + + // Check for keypress + if(kbxhit()) { + + // Return fail value if Escape was pressed + gkey keyval = kbxget(); + if(keyval == Key_Esc) { + GMenuLockLoop MenuLockLoop; + if(MenuLockLoop.Run()) { + w_info(NULL); + return false; + } + } + } + + // Pause approx 1 second before trying again + usleep(1000); + + // Try again + return true; +} + + +// ------------------------------------------------------------------ +// Build zonegate address from orig/dest address + +void ZonegateIt(ftn_addr& gate, ftn_addr& orig, ftn_addr& dest) { + + gate.zone = orig.zone; // Send to the local zoneGate + gate.net = orig.zone; + gate.node = dest.zone; + gate.point = 0; +} + + +// ------------------------------------------------------------------ + +int GetAkaNo(const ftn_addr& aka) { + + int akano = 0; + while(akano < CFG->aka.size()) { + if(CFG->aka[akano].addr.equals(aka)) + return akano; + akano++; + } + return -1; +} + + +// ------------------------------------------------------------------ + +void doinvalidate(char* text, const char* find, const char* replace, bool is_tearline) { + + int n = strlen(find); + if(strnieql(text, find, n) and (not is_tearline or (text[n] == NUL) or isspace(text[n]))) { + char buf[256]; + + strcpy(buf, text); + strcpy(stpcpy(text, replace), &buf[n]); + } +} + + +// ------------------------------------------------------------------ + +int AkaMatchOne(const ftn_addr* mask, const ftn_addr* addr) { + + int match = 0; + + // Count matching parts + if((mask->zone == 0) or (addr->zone == 0) or (mask->zone == GFTN_ALL) or (mask->zone == addr->zone)) { + match++; + if((mask->net == GFTN_ALL) or (mask->net == addr->net)) { + match++; + if((mask->node == GFTN_ALL) or (mask->node == addr->node)) { + match++; + if((mask->point == GFTN_ALL) or (mask->point == addr->point)) { + match++; + } + } + } + } + + return match; +} + + +// ------------------------------------------------------------------ + +int AkaMatch(ftn_addr* match, const ftn_addr* addr) { + + int aka; + + for(vector::iterator am = CFG->akamatch.begin(), aka=0; am != CFG->akamatch.end(); am++, aka++) { + if(addr->match(am->mask)) { + int akano = GetAkaNo(am->aka); + if(akano != -1) { + *match = CFG->aka[akano].addr; + return akano; + } + } + } + + int bestaka = -1; + int bestmatch = 0; + int matchaka = 0; + vector::iterator a; + + for(a = CFG->aka.begin(), aka = 0; a != CFG->aka.end(); aka++, a++) { + + if(match->equals(a->addr)) + matchaka = aka; + + // Ignore fakenet addresses + if(a->addr.net != a->pointnet) { + + int match = AkaMatchOne(&a->addr, addr); + + // Note if we found a better match + if(match > bestmatch) { + bestmatch = match; + bestaka = aka; + } + } + } + + // If there was no matching aka, use the aka + if(bestaka == -1) + bestaka = matchaka; + else { + // If the current address matches at least as good as the best match, don't change it + if(bestmatch <= AkaMatchOne(match, addr)) { + int akano = GetAkaNo(*match); + if(akano != -1) + return akano; + } + } + + *match = CFG->aka[bestaka].addr; + return bestaka; +} + + +// ------------------------------------------------------------------ + +void ScreenBlankIdle() { + + static int whb = -1; + static int whh = -1; + static int wascurhid = false; + static Clock lastmoved = 0; + int windowheight = 4; + + IdleCheckSemaphores(); + + char blankmsg1[80]; + char blankmsg2[80]; + time_t t = time(NULL); + sprintf(blankmsg1, " %s %s ", __gver_longpid__, strftimei(blankmsg2, 40, LNG->StatusLineTimeFmt, localtime(&t))); + sprintf(blankmsg2, " %s ", LNG->BlankMsg); + if(strblank(blankmsg2)) { + *blankmsg2 = NUL; + windowheight--; + } + int b1 = strlen(blankmsg1); + int b2 = strlen(blankmsg2); + int blankmsglen = MaxV(b1,b2); + int ry = rand() % (MAXROW-windowheight); + int rx = rand() % ((MAXCOL-blankmsglen)-2); + + if(blanked and (whb == -1)) { + wascurhid = vcurhidden(); + vcurhide(); + if(C_BACKB != 0) + gvid->setoverscan(0); + whb = wopen(0,0,MAXROW-1,MAXCOL-1, 5, 7, 7); + if(CFG->screenblankertype == BLANK_SLIDEWIN) + whh = wopen_(ry, rx, windowheight, blankmsglen+2, W_BINFO, C_INFOB, C_INFOW); + lastmoved = gkbd.tickvalue; + } + + if(not blanked and (whb != -1)) { + if(CFG->screenblankertype == BLANK_SLIDEWIN) { + wactiv_(whh); + wclose(); + whh = -1; + } + wactiv_(whb); + wclose(); + whb = -1; + if(C_BACKB != 0) + gvid->setoverscan(C_BACKB); + if(wascurhid) + vcurhide(); + else + vcurshow(); + return; + } + + if(gkbd.tickvalue > (lastmoved+50L)) { + lastmoved = gkbd.tickvalue; + if(CFG->screenblankertype == BLANK_SLIDEWIN) + wslide(ry, rx); + } + + if(CFG->screenblankertype == BLANK_SLIDEWIN) { + wcenters(0, C_INFOW, blankmsg1); + if(*blankmsg2) + wcenters(1, C_INFOW, blankmsg2); + } + + // If timed out, exit screenblanker + if(CFG->timeout) + if(gkbd.tickvalue >= (gkbd.tickpress+(CFG->timeout*10L))) + kbput(Key_Tick); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/geview.cpp b/golded3/geview.cpp new file mode 100644 index 0000000..4dd2e33 --- /dev/null +++ b/golded3/geview.cpp @@ -0,0 +1,657 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Message viewer class implementation. +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ + +GMsgHeaderView::GMsgHeaderView() { + + alive = false; + at_row = at_column = width = height = 0; + border_type = gwindow::bordertype_none; + window_color = from_color = to_color = subject_color = BLUE|_LGREY; + title_color = highlight_color = RED|_LGREY; + border_color = YELLOW|_LGREY; +} + + +// ------------------------------------------------------------------ + +GMsgHeaderView::~GMsgHeaderView() { + + Destroy(); +} + + +// ------------------------------------------------------------------ + +void GMsgHeaderView::Create() { + + alive = true; + + window.openxy( + at_row, + at_column, + height, + width, + border_type, + border_color, + window_color + ); +} + + +// ------------------------------------------------------------------ + +void GMsgHeaderView::Destroy() { + + if(alive) + window.close(); + else + alive = false; +} + + +// ------------------------------------------------------------------ + +void GMsgHeaderView::Use(Area *areaptr, GMsg *msgptr) { + + area = areaptr; + msg = msgptr; +} + + +// ------------------------------------------------------------------ + +void GMsgHeaderView::Paint() { + + int namewidth = CFG->disphdrnodeset.pos - CFG->disphdrnameset.pos; + int nodewidth = CFG->disphdrdateset.pos - CFG->disphdrnodeset.pos; + int datewidth = width - CFG->disphdrdateset.pos; + + vchar headerline[200]; + for(int c = 0; c < width; c++) + headerline[c] = _box_table(W_BHEAD, 1); + headerline[width] = NUL; + + INam whofrom; + if(*msg->ifrom and *msg->realby) + sprintf(whofrom, "%s <%s>", msg->realby, msg->iorig); + else if(*msg->ifrom and *msg->iorig) + strcpy(whofrom, msg->iorig); + else + strcpy(whofrom, msg->By()); + strsetsz(whofrom, (area->isinternet() or *msg->ifrom) ? (namewidth+nodewidth) : namewidth); + + INam whoto; + if(*msg->ito and *msg->realto) + sprintf(whoto, "%s <%s>", msg->realto, msg->idest); + else if(*msg->ito and *msg->idest) + strcpy(whoto, msg->idest); + else + strcpy(whoto, msg->To()); + strsetsz(whoto, (area->isinternet() or *msg->ito) ? (namewidth+nodewidth) : namewidth); + + // Generate top line fields + ISub buf; + char top1[200]; + strtrim(strcpy(buf, area->desc())); + if((CFG->dispareano == ALWAYS) or (CFG->dispareano and area->board())) + sprintf(top1, " [%u] %s ", area->board(), buf); + else + sprintf(top1, " %s ", buf); + strtrim(top1); + strcat(top1, " (" /*)*/); + if(area->isinternet()) + strcpy(buf, area->Internetaddress()); + else + area->Aka().addr.make_string(buf); + strcat(top1, buf); + strcat(top1, /*(*/ ") "); + + char top2[200]; + if(msg->areakludgeid) + sprintf(top2, " %s (%s) ", area->echoid(), msg->areakludgeid); + else + sprintf(top2, " %s ", area->echoid()); + + #if defined(GUTLOS_FUNCS) + g_set_ostitle_name(struplow(strtmp(area->echoid())), 0); + #endif + + // Get marks + int bookmark = (area->bookmark == msg->msgno); + int markmark = (area->Mark.Count() ? (area->Mark.Find(msg->msgno) ? 1 : 0) : NO); + + // Generate message attributes string + char bot2[200]; + MakeAttrStr(bot2, &msg->attr); + int len2 = strlen(bot2); + if(len2 > width-CFG->disphdrnodeset.pos) { + len2 = width-CFG->disphdrnodeset.pos; + strsetsz(bot2, len2); + } + + // Generate message number and reply links string + char bot1[200]; + char* ptr = bot1; + int list_max = msg->link.list_max(); + ulong* replies = (ulong*)throw_calloc(list_max+1, sizeof(ulong)); + ulong replyto, replynext; + if(CFG->switches.get(disprealmsgno)) { + ptr += sprintf(ptr, " %-5.5s: #%lu [%u]", LNG->Msg, msg->msgno, area->Msgn.Count()+(msg->attr.nwm() ? 1 : 0)); + replyto = msg->link.to(); + replies[0] = msg->link.first(); + replynext = msg->link.next(); + for(int replyn=1; replynlink.list(replyn-1); + } + else { + uint active = area->Msgn.Count() + (msg->attr.nwm() ? 1 : 0); + ptr += sprintf(ptr, " %-5.5s: %u %s %u", LNG->Msg, msg->attr.nwm() ? active : area->Msgn.ToReln(msg->msgno), LNG->of, active); + replyto = area->Msgn.ToReln(msg->link.to()); + replies[0] = area->Msgn.ToReln(msg->link.first()); + replynext = area->Msgn.ToReln(msg->link.next()); + for(int replyn=1; replynMsgn.ToReln(msg->link.list(replyn-1)); + } + if(replyto) + ptr += sprintf(ptr, " -%lu", replyto); + for(int replyn=0,plus=0; replyndisphdrnameset.pos + len1) > CFG->disphdrnodeset.pos) { + if(8 + len1 + len2 > width) { + strsetsz(bot1, width-len2-1); + strtrim(bot1); + } + strcat(bot1, " "); + strcat(bot1, bot2); + *bot2 = NUL; + } + else { + strsetsz(bot1, namewidth+8); + strcat(bot1, bot2); + *bot2 = NUL; + } + strsetsz(bot1, width); + throw_free(replies); + + // Generate orig node data + char node1[200]; + if(msg->orig.net) + msg->orig.make_string(node1); + else + *node1 = NUL; + strsetsz(node1, nodewidth); + + char date1[25] = ""; + if(msg->written) + strftimei(date1, CFG->disphdrdateset.len, LNG->DateTimeFmt, gmtime(&msg->written)); + strsetsz(date1, datewidth); + + // Generate dest node data + char node2[200]; + if(msg->dest.net and area->isnet()) { + msg->dest.make_string(node2); + if(msg->odest.net) { + if(msg->odest.net != msg->dest.net or msg->odest.node != msg->dest.node) { + sprintf(buf, " %s %u/%u", LNG->Via, msg->odest.net, msg->odest.node); + strcat(node2, buf); + } + } + } + else + *node2 = NUL; + strsetsz(node2, nodewidth); + + char date2[25] = ""; + if(msg->arrived) + strftimei(date2, CFG->disphdrdateset.len, LNG->DateTimeFmt, gmtime(&msg->arrived)); + strsetsz(date2, datewidth); + + // Generate subjectline + char subj[200], lngsubj[10]; + strcpy(lngsubj, (msg->attr.att() or msg->attr.frq() or msg->attr.urq()) ? LNG->File : LNG->Subj); + strxcpy(subj, msg->re, sizeof(subj)); + strsetsz(subj, width-strlen(lngsubj)); + + // Paint the total header in the window + vchar borderchar[2] = { (vchar)' ', 0 }; + *borderchar = window.boxchar_upper_horizontal_line(); + window.printvs(0, 0, border_color|ACSET, borderchar); + window.prints(0, 1, title_color, top1); + window.printvs(0, strlen(top1)+1, border_color|ACSET, headerline+strlen(top1)+strlen(top2)-2); + window.prints(0, width-strlen(top2)-1, title_color, top2); + window.printvs(0, width-1, border_color|ACSET, borderchar); + window.printvs(5, 0, border_color|ACSET, headerline); + window.prints(1, 0, window_color, bot1); + if(bookmark) + window.prints(1, 5, highlight_color, "\x11"); + if(markmark) + window.prints(1, 7, highlight_color, "\x10"); + if(*bot2) + window.prints(1, CFG->disphdrnodeset.pos, window_color, bot2); + window.prints(2, 0, window_color, LNG->From); + window.prints(2, CFG->disphdrnameset.pos, ((msg->foundwhere&GFIND_FROM) or msg->attr.fmu() or (msg->attr.loc() and CFG->switches.get(displocalhigh))) ? highlight_color : from_color, whofrom); + window.prints(3, 0, window_color, LNG->To); + window.prints(3, CFG->disphdrnameset.pos, ((msg->foundwhere&GFIND_TO) or msg->attr.tou()) ? highlight_color : to_color, whoto); + if(not area->isinternet()) { + if(not (*msg->ifrom and (*msg->realby or *msg->iorig))) + window.prints(2, CFG->disphdrnodeset.pos, from_color, node1); + if(not (*msg->ito and (*msg->realto or *msg->idest))) + window.prints(3, CFG->disphdrnodeset.pos, to_color, node2); + } + window.prints(2, CFG->disphdrdateset.pos, from_color, date1); + window.prints(3, CFG->disphdrdateset.pos, to_color, date2); + window.prints(4, 0, window_color, lngsubj); + window.prints(4, strlen(lngsubj), (msg->foundwhere&GFIND_SUBJECT) ? highlight_color : subject_color, subj); + + // Calculate attach file sizes + if(msg->attr.att()) { + if(CFG->dispattachsize) { + char buf2[GMAXPATH]; + int begpos = strlen(LNG->File); + strcpy(buf, msg->re); + char* ptr = strtok(buf, " "); + while(ptr) { + if(*ptr == '^') + ptr++; + if((isalpha(*ptr) and (ptr[1] == ':')) or ((ptr[0] == '\\') and (ptr[1] == '\\'))) + strcpy(buf2, ptr); + else + sprintf(buf2, "%s%s", CFG->inboundpath, ptr); + long sz = GetFilesize(MapPath(buf2)); + if(sz == -1) + sprintf(subj, " %s ", LNG->n_a); + else { + switch(CFG->dispattachsize) { + case ATTACH_BYTES: + sprintf(subj, " %li ", sz); + break; + case ATTACH_KBYTES: + sprintf(subj, " %lik ", (sz+512L)/1024L); + break; + } + } + window.prints(5, begpos+int(ptr-buf)-1, title_color, subj); + ptr = strtok(NULL, " "); + } + } + } + + if(CFG->dispmsgsize and msg->txt and not _in_editor) { + uint len = strlen(msg->txt); + switch(CFG->dispmsgsize) { + case DISPMSGSIZE_BYTES: + sprintf(subj, "%u", len); + break; + case DISPMSGSIZE_KBYTES: + sprintf(subj, "%uk", (len+512)/1024); + break; + case DISPMSGSIZE_KBYTES+1: + sprintf(subj, "%u", msg->lines); + break; + default: + *subj = NUL; + } + if(*subj) + window.prints(5, 1, title_color, subj); + } +} + + +// ------------------------------------------------------------------ + +GMsgBodyView::GMsgBodyView() { + + alive = false; + scrollbar_visible = false; + at_row = at_column = width = height = visible_width = 0; + border_type = gwindow::bordertype_none; + window_color = BLACK|_LGREY; + highlight_color = WHITE|_RED; + scrollbar_color = DGREY|_LGREY; + border_color = YELLOW|_LGREY; +} + + +// ------------------------------------------------------------------ + +GMsgBodyView::~GMsgBodyView() { + + Destroy(); +} + + +// ------------------------------------------------------------------ + +void GMsgBodyView::Create() { + + alive = true; + + window.openxy( + at_row, + at_column, + height, + width, + border_type, + border_color, + window_color, + scrollbar_color + ); + + dummy_line.text = ""; + dummy_line.type = 0; + dummy_line.color = window_color; + + visible_width = width - (CFG->switches.get(disppagebar) ? 1 : 0); +} + + +// ------------------------------------------------------------------ + +void GMsgBodyView::Destroy() { + + if(alive) + window.close(); + else + alive = false; +} + + +// ------------------------------------------------------------------ + +void GMsgBodyView::Use(Area *areaptr, GMsg *msgptr, int startline) { + + area = areaptr; + msg = msgptr; + + // Find the first highlighted line and go to it + if(msg->foundwhere & GFIND_BODY) { + for(startline=0; startlinelines; startline++) { + if(msg->line[startline]->type & GLINE_HIGH) + break; + } + // Adjust position in window + startline -= height / 3; + if(startline < 0) + startline = 0; + else if((startline + height - 1) >= msg->lines) + startline = msg->lines - height; + } + + if(startline >= msg->lines) + startline = msg->lines - 1; + + if(startline < 0) + startline = 0; + + upperline = startline; + lowerline = upperline + height - 1; + can_pagedown = lowerline < (msg->lines-1); + + scrollbar_visible = CFG->switches.get(disppagebar) ? (msg->lines > height) : false; + visible_width = scrollbar_visible ? width-1 : width; + window.set_scrollbar_color(scrollbar_visible ? scrollbar_color : -1); +} + + +// ------------------------------------------------------------------ + +void GMsgBodyView::PaintLine(int row, Line *line) { + + // Calculate effective coordinates for vputs + int vrow = gwin.active->srow + row; + uint llen = strlen(line->text); + + int color = (line->type & GLINE_HIGH) ? highlight_color : line->color; + + // Trim line if it longer than should be. This actually happens in very rare + // cases, but always when hex dump displayed. + if(llen > visible_width) { + llen = visible_width; + line->text[llen] = NUL; + } + + // Print it + if(not SearchHighlight(line, vrow, visible_width, highlight_color)) { + if(line->type & GLINE_ORIG and strneql(line->text, " * Origin: ", 11)) { + vputs(vrow, 0, color, " * Origin: "); + StyleCodeHighlight(line->text+11, vrow, 11, not AA->attr().hex() and CFG->hidestylies, color); + } + else + StyleCodeHighlight(line->text, vrow, 0, not AA->attr().hex() and CFG->hidestylies, color); + int tlen = strlen(line->text); + vputns(vrow, tlen, color, "", visible_width-tlen); + } + else + vputns(vrow, 0, color, line->text, visible_width); +} + + +// ------------------------------------------------------------------ + +void GMsgBodyView::Paint() { + + window.activate_quick(); + + Line* dummy_index = NULL; + Line** line_index = msg->line ? (msg->line + upperline) : &dummy_index; + + for(int row=0; rowlines > height)) { + can_pagedown = true; + upperline = 0; + lowerline = height - 1; + Paint(); + return true; + } + + return false; +} + + +// ------------------------------------------------------------------ + +int GMsgBodyView::Bottom() { + + if(msg->lines > height) { + if(msg->lines <= height) { + can_pagedown = true; + upperline = 0; + } + else { + can_pagedown = false; + upperline = msg->lines - height; + } + lowerline = upperline + height - 1; + Paint(); + return true; + } + + return false; +} + + +// ------------------------------------------------------------------ + +int GMsgBodyView::PageUp() { + + if(msg->lines > height) { + can_pagedown = true; + if(upperline) { + upperline -= height - 1; + if(upperline < 0) + upperline = 0; + lowerline = upperline + height - 1; + Paint(); + return true; + } + } + + return false; +} + + +// ------------------------------------------------------------------ + +int GMsgBodyView::PageDown() { + + if(msg->lines > height) { + if(can_pagedown) { + if(lowerline < msg->lines-1) { + lowerline += height - 1; + if(lowerline >= msg->lines-1) + can_pagedown = false; + upperline = lowerline - height + 1; + Paint(); + return true; + } + } + } + + return false; +} + + +// ------------------------------------------------------------------ + +int GMsgBodyView::LineUp() { + + if(msg->lines > height) { + if(upperline) { + window.scroll_down(); + upperline--; + lowerline--; + #ifdef GOLD_MOUSE + gmou.HideCursor(); + #endif + PaintLine(0, msg->line[upperline]); + #ifdef GOLD_MOUSE + gmou.ShowCursor(); + #endif + can_pagedown = lowerline < (msg->lines-1); + UpdateScrollbar(); + return true; + } + } + return false; +} + + +// ------------------------------------------------------------------ + +int GMsgBodyView::LineDown() { + + if(msg->lines > height) { + if(lowerline < (msg->lines-1)) { + window.scroll_up(); + upperline++; + lowerline++; + #ifdef GOLD_MOUSE + gmou.HideCursor(); + #endif + PaintLine(height-1, msg->line[lowerline]); + #ifdef GOLD_MOUSE + gmou.ShowCursor(); + #endif + can_pagedown = lowerline < (msg->lines-1); + UpdateScrollbar(); + return true; + } + } + + return false; +} + + +// ------------------------------------------------------------------ + +int GMsgBodyView::Continue() { + + if(can_pagedown) + return PageDown(); + + return false; +} + + +// ------------------------------------------------------------------ + +int GMsgBodyView::ThumbTrack(int pos) { + + return ThumbPosition(pos); +} + + +// ------------------------------------------------------------------ + +int GMsgBodyView::ThumbPosition(int pos) { + + upperline = pos; + lowerline = upperline + height - 1; + can_pagedown = lowerline < (msg->lines-1); + Paint(); + return true; +} + + +// ------------------------------------------------------------------ + +void GMsgBodyView::UpdateScrollbar() { + + if(CFG->switches.get(disppagebar) and scrollbar_visible) + window.vscrollbar(msg->lines, msg->lines-height, upperline); +} + + +// ------------------------------------------------------------------ + +void GMsgBodyView::prints(int wrow, int wcol, int atr, char* str) { + + vputs(wrow, wcol, atr, str); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/geview.h b/golded3/geview.h new file mode 100644 index 0000000..8add093 --- /dev/null +++ b/golded3/geview.h @@ -0,0 +1,134 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Message viewer classes. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +class GMsgHeaderView { + + int alive; + +protected: + +public: + + Area *area; + GMsg *msg; + gwindow window; + + GMsgHeaderView(); + ~GMsgHeaderView(); + + // Window setup + int at_row; + int at_column; + int width; + int height; + int border_type; + int border_color; + int window_color; + int title_color; + + int highlight_color; + int from_color; + int to_color; + int subject_color; + + void Use(Area *areaptr, GMsg *msgptr); + + void Create(); + void Destroy(); + + void Paint(); +}; + + +// ------------------------------------------------------------------ + +class GMsgBodyView : public Container { + + int alive; + +protected: + + // View data + int visible_width; + int scrollbar_visible; + Line dummy_line; + int can_pagedown; + int upperline; + int lowerline; + + void PaintLine(int row, Line *line); + void UpdateScrollbar(); + void prints(int wrow, int wcol, int atr, char* str); + +public: + + Area *area; + GMsg *msg; + gwindow window; + + GMsgBodyView(); + ~GMsgBodyView(); + + // Window setup + int at_row; + int at_column; + int width; + int height; + int border_type; + int border_color; + int window_color; + int scrollbar_color; + + int highlight_color; + + void Use(Area *areaptr, GMsg *msgptr, int startline=0); + + int UpperLine() { return upperline; } + + void Create(); + void Destroy(); + + void Paint(); + + int Top(int redraw=false); + int Bottom(); + int PageUp(); + int PageDown(); + int LineUp(); + int LineDown(); + int Continue(); + int ThumbTrack(int pos); + int ThumbPosition(int pos); +}; + + +// ------------------------------------------------------------------ + diff --git a/golded3/gmarea.cpp b/golded3/gmarea.cpp new file mode 100644 index 0000000..39b4f43 --- /dev/null +++ b/golded3/gmarea.cpp @@ -0,0 +1,351 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Area functions. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +int SearchTaglist(Echo* taglist, char* tag) { + + int n = 0; + + while(*taglist[n]) { + if(strieql(taglist[n], tag)) + break; + n++; + } + return(n); +} + + +// ------------------------------------------------------------------ +// Update exportlist scanning file + +void WriteNoDupes(const char* file, const char* line) { + + gfile fp; + Path buf; + + bool found = false; + long tries = 0; + + do { + fp.fopen(file, "at+", SH_DENYRW); + + if(not fp.isopen()) { + if((errno != EACCES) or (PopupLocked(++tries, false, file) == false)) { + LOG.ErrOpen(); + LOG.printf("! A semaphore file could not be opened."); + LOG.printf(": %s", file); + LOG.ErrOSInfo(); + OpenErrorExit(); + } + } + } while(not fp.isopen()); + + if(tries) + PopupLocked(0, 0, NULL); + + fp.fseek(0, SEEK_SET); + while(fp.fgets(buf, sizeof(buf))) { + if(strieql(strtrim(buf), line)) { + found = true; + break; + } + } + + if(not found) { + fp.fseek(0, SEEK_END); + fp.printf("%s\n", line); + } + fp.fclose(); +} + + +// ------------------------------------------------------------------ + +void FreqWaZOO(const char* files, const Addr& dest, const Attr& attr) { + + char* buf = throw_strdup(files); + Path filename, outbound, tmp; + + StripBackslash(strcpy(outbound, CFG->outboundpath)); + strcpy(filename, outbound); + + if(dest.zone != CFG->aka[0].addr.zone) { + sprintf(tmp, ".%03X", dest.zone); + strcat(filename, tmp); + if(not is_dir(filename)) + mkdir(filename, S_IWUSR); + } + + AddBackslash(filename); + sprintf(tmp, "%04X%04X", dest.net, dest.node); + strcat(filename, tmp); + + if(dest.point) { + strcat(filename, ".pnt"); + if(not is_dir(filename)) + mkdir(filename, S_IWUSR); + AddBackslash(filename); + sprintf(tmp, "%08X", dest.point); + strcat(filename, tmp); + } + + strcpy(tmp, filename); + + // filename now contains everything but the extension, and we are sure + // that the directory exists + + strcat(tmp, ".req"); + + int i = 0; + while(buf[i]) { + if(buf[i] == ' ') { + if(buf[i+1] != '!' and buf[i+1] != '$') + buf[i] = '\n'; + } + i++; + } + + FILE* fcs = fopen(tmp, "at"); + if(fcs) { + fprintf(fcs, "%s\n", buf); + fclose(fcs); + } + + strcpy(tmp, filename); + + char m; + if(attr.imm()) + m = 'I'; + else if(attr.cra()) + m = 'C'; + else if(attr.dir()) + m = 'D'; + else if(attr.hld()) + m = 'H'; + else + m = 'F'; + + char buf2[5]; + sprintf(buf2, ".%clo", m); + strcat(tmp, buf2); + + if(*tmp) + TouchFile(tmp); + + throw_free(buf); +} + + +// ------------------------------------------------------------------ + +void RenumberArea() { + + if(not AA->Renumber()) { + HandleGEvent(EVTT_JOBFAILED); + update_statusline(LNG->NoRenum); + waitkeyt(5000); + reader_keyok = YES; + } + else { + + AA->Mark.ResetAll(); + AA->Expo.ResetAll(); + + // Touch the netmail rescan semaphore + if(AA->isnet()) + TouchFile(AddPath(CFG->areapath, CFG->semaphore.netscan)); + + // Tell user we are finished + update_statuslinef("%u %s", AA->Msgn.Count(), LNG->Renumbered); + waitkeyt(5000); + } +} + + +// ------------------------------------------------------------------ + +void Area::Open() { + + if(not adat) { + adat = (AreaData*)throw_calloc(1, sizeof(AreaData)); + InitData(); + } + + area->Msgn = &Msgn; + area->PMrk = &PMrk; + + area->open(); + + isscanned = true; + UpdateAreadata(); +} + + +// ------------------------------------------------------------------ + +void Area::Close() { + + if(isreadpm) { + set_lastread(Msgn.ToReln(lastreadentry())); + isreadpm = false; + } + PMrk.ResetAll(); + + isreadmark = false; + + area->close(); + + UpdateAreadata(); + + throw_release(adat); +} + + +// ------------------------------------------------------------------ + +void Area::Scan() { + + if(cmdlinedebughg) + LOG.printf("- Scan: %s", echoid()); + + scan(); + + isscanned = true; + UpdateAreadata(); +} + + +// ------------------------------------------------------------------ + +void Area::SaveMsg(int mode, GMsg* msg) { + + if(CFG->switches.get(frqwazoo) and msg->attr.frq()) { + FreqWaZOO(msg->re, msg->dest, msg->attr); + if(CFG->frqoptions & FREQ_NOWAZOOMSG) + return; + msg->attr.frq0(); + } + + if(isinternet()) { // Adjust fields for compatibility + if(*msg->realby) + strcpy(msg->by, msg->realby); + if(*msg->realto) + strcpy(msg->to, msg->realto); + } + + // Translate softcr to configured char + if(EDIT->SoftCrXlat()) { + strchg(msg->by, SOFTCR, EDIT->SoftCrXlat()); + strchg(msg->to, SOFTCR, EDIT->SoftCrXlat()); + strchg(msg->realby, SOFTCR, EDIT->SoftCrXlat()); + strchg(msg->realto, SOFTCR, EDIT->SoftCrXlat()); + if(not (msg->attr.frq() or msg->attr.att() or msg->attr.urq())) + strchg(msg->re, SOFTCR, EDIT->SoftCrXlat()); + strchg(msg->txt, SOFTCR, EDIT->SoftCrXlat()); + } + area->save_msg(mode, msg); + + if(not (mode & GMSG_NOLSTUPD) or msg->attr.uns()) { + UpdateAreadata(); + if(msg->attr.uns()) { + Path file, line; + + if(islocal()) { + errorlevel |= EXIT_LOCAL; + locpost++; + } + else if(isnet()) { + errorlevel |= EXIT_NET; + netpost++; + } + else { + errorlevel |= EXIT_ECHO; + echopost++; + } + + if(isjam() and (isecho() or isnet())) { + Path p; + + sprintf(file, "%s%smail.jam", CFG->jampath, isecho() ? "echo" : "net"); + sprintf(line, "%s %lu", ReMapPath(strcpy(p, path())), msg->msgno); + WriteNoDupes(file, line); + } + if(isqwk()) { + strcpy(file, AddPath(CFG->goldpath, "goldqwk.lst")); + sprintf(line, "%s %lu", echoid(), msg->msgno); + WriteNoDupes(file, line); + + } + else if(isinternet()) { + strcpy(file, AddPath(CFG->goldpath, "goldsoup.lst")); + sprintf(line, "%s %lu", echoid(), msg->msgno); + WriteNoDupes(file, line); + } + else { + if(not strblank(CFG->semaphore.exportlist)) { + strcpy(file, AddPath(CFG->areapath, CFG->semaphore.exportlist)); + sprintf(line, "%s", echoid()); + WriteNoDupes(file, line); + } + } + } + } +} + + +// ------------------------------------------------------------------ + +void HudsSizewarn() { + + whelpcat(H_EWarnMsgtxt); + call_help(); + whelpcat(H_General); +} + + +// ------------------------------------------------------------------ + +void HGWarnRebuild() { + + whelpcat(H_EQbaseRebuild); + call_help(); +} + + +// ------------------------------------------------------------------ + +void FidoRenumberProgress(const char* s) { + + update_statusline(s); +} + + +// ------------------------------------------------------------------ + diff --git a/golded3/gmarea.h b/golded3/gmarea.h new file mode 100644 index 0000000..0dc57c1 --- /dev/null +++ b/golded3/gmarea.h @@ -0,0 +1,715 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Area structures and classes. +// ------------------------------------------------------------------ + +#ifndef __gmoarea_h +#define __gmoarea_h + + +// ------------------------------------------------------------------ + +#include +#include + + +// ------------------------------------------------------------------ +// Internal GoldED message header + +class GMsg : public gmsg { + +public: + + IAdr iorig; // Internet "From:" header address + IAdr idest; // Internet "To:" header address + IAdr ireplyto; // Internet "Reply-To:" header address + IAdr iaddr; // Internet destination address (from ^aREPLYADDR) + IAdr igate; // Internet gate FTN-address and gatename (from ^aREPLYTO) + INam ifrom; // Internet "From:" header + char ito[512]; // Internet "To:" header + char icc[512]; // Internet "Cc:" header + char ibcc[512]; // Internet "Bcc:" header + INam organization; // Internet "Organization:" header + + INam realby; // Real from-name + INam realto; // Real to-name + INam pseudoto; // Pseudo to-name + INam pseudofrom; // Pseudo from-name + uint you_and_I; // Mail was to/from me/you + + INam fwdfrom; // FWDFROM kludge + ftn_addr fwdorig; // FWDORIG kludge + INam fwdto; // FWDTO kludge + ftn_addr fwddest; // FWDDEST kludge + Subj fwdsubj; // FWDSUBJ kludge + Echo fwdarea; // FWDAREA kludge + char fwdmsgid[201]; // FWDMSGID kludge + + bool i51; // true if I51 kludge was found + char charset[100]; // Charset type + int charsetlevel; // Charset level + int charsetencoding; // Charset encoding format (GCHENC_*) + + int tzutc; // TZUTC kludge + + char tagline[80]; // Tagline for msg + char tearline[80]; // Tearline for msg + char origin[160]; // Origin for msg + + Line* lin; // Index of the lines + Line** line; // Index of the viewable lines + int lines; // Total number of lines + + int quotepct; // Quote/text percentage + + uint foundwhere; // Where searched string was found (GFIND_*) + int foundtopline; // First line where a searched string was found + + uint orig_timesread; + + char* messageid; // Internet Message-ID (allocated) + char* inreplyto; // Internet In-Reply-To (allocated) + char* references; // Internet References (allocated) + + int line_width; // Line width used + + const char* areakludgeid; // Echoid from AREA: kludge or NULL + + char* By() { return *realby ? realby : by; } + char* To() { return *realto ? realto : to; } + + bool to_me() { return (you_and_I & TO_ME); } + bool to_all() { return (you_and_I & TO_ALL); } + bool by_me() { return (you_and_I & BY_ME); } + bool to_you() { return (you_and_I & TO_YOU); } + bool by_you() { return (you_and_I & BY_YOU); } + + void TextToLines(int __line_width, bool header_recode = true); + void LinesToText(); +}; + + +// ------------------------------------------------------------------ + +class GAreaListScan { + +private: + + vector< pair > container; + vector< pair >::iterator currposn; + +public: + + inline GAreaListScan() { currposn = container.end(); } + inline ~GAreaListScan() {} + + inline void Add(pair p) { container.push_back(p); currposn = container.end(); } + + inline void Reset() { container.clear(); currposn = container.end(); } + + inline bool First() { currposn = container.begin(); return currposn != container.end(); } + inline bool Next() { currposn++; return currposn != container.end(); } + + inline void CurrNo(int posn) { First(); while(posn--) if(not Next()) break; } + + inline const char* MenuText() { return currposn != container.end() ? currposn->first.c_str() : ""; } + inline const char* File() { return currposn != container.end() ? currposn->second.c_str() : ""; } + + inline const char* MenuText(int i) { return i < container.size() ? container[i].first.c_str() : ""; } + inline const char* File(int i) { return i < container.size() ? container[i].second.c_str() : ""; } +}; + + +// ------------------------------------------------------------------ + +const word CUR_GOLDLAST_VER = 0x1A02; + +#if defined(GOLD_CANPACK) +#pragma pack(1) +#endif + +struct ggoldlast { + dword crcechoid; + dword lastread; + dword msgncount; + dword unread; + word marks; + + byte flags; +}; + +#if defined(GOLD_CANPACK) +#pragma pack() +#endif + + +// ------------------------------------------------------------------ +// Arealist class + +class Area; + +typedef vector::iterator area_iterator; + +class AreaList { + +private: + + Desc alistselections[16]; + byte mask; + + friend class Area; + friend class SelMaskPick; + +public: + + // Index of areas in the list + vector idx; + + // Area pointer + area_iterator item; + + // Sort specs (for external compare func) + char sortspec[20]; + + // Active msgbases (bitmap of MT_* contants) + uint msgbases; + + // Additional items to the area scan menu + GAreaListScan ListScan; + + void Set_Mask(word value = 1) { mask = value; } + void Select_Mask(void); + + // Con/destructor + AreaList(); + ~AreaList(); + + // Subscript operator, returns pointer to area + inline Area* operator[](size_t n) { return (n < idx.size()) ? idx[n] : (Area*)NULL; } + inline size_t size() { return idx.size(); } + + // Allocate and initialize data + void Init(); + + // Deallocate and reset data + void Reset(); + + // Return pointer to a new'd area of the specified format + Area* NewArea(int msgbase); + + // Sort areas + void Sort(const char* specs=NULL, int first=0, int last=-1); + + // Default marks names + void SetDefaultMarks(); + + // Read/write GOLDLAST.LST + void ReadGoldLast(); + void WriteGoldLast(); + + // Miscellaneous + void AddNewArea(AreaCfg* aa); + int AreaIdToNo(int __areaid); + Area* AreaIdToPtr(int __areaid); + int AreaNoToId(int __areano); + Area* AreaNoToPtr(int __areano); + int AreaScan(int mode, uint currno, int pmscan, int& pmails, int& pmareas, const char* file=NULL); + int AreaEchoToNo(const char* echoid); + Area* AreaEchoToPtr(const char* echoid); + void GetAreafile(char* val); + void GetArea(char* val); + bool GetAreaFirstPart(AreaCfg& aa, char*& key, char*& val); + void GetAreaDef(char* val); + void GetAreaSep(char* val); + void GetAreaDesc(char* val); + void ReadEcholist(char* val); + int SetActiveAreaId(int __areaid); + int SetActiveAreaNo(int __areano); + void SetAreaDesc(char* echoid, char* desc); + void SortAreaGroup(const char* options, int beginarea, int endarea); + void WriteAreaDef(const char* file); +}; + + +// ------------------------------------------------------------------ +// Msgbase function prototypes + +int AreaCmp(const Area** __a, const Area** __b); + + +// ------------------------------------------------------------------ +// Area data (collected from global/Random System) + +struct AreaData { + + // Area + gaka aka; + bool akamatching; + Attr attributes; + bool areacopyaddid; + bool areacopydirect; + Echo areacopyto; + bool areaforwarddirect; + bool areafreqdirect; + Echo areafreqto; + bool areareplydirect; + Echo areareplyto; + Echo areayouwroteto; + int ctrlinfo; + bool edithardterm; + bool editmixcase; + bool forcetemplate; + IAdr internetaddress; + Node internetgate; + bool internetmsgid; + bool internetrfcbody; + Path loadlanguage; + int msglistdate; + bool msglistfast; + bool msglistfirst; + bool msglistheader; + bool msglistwidesubj; + Name nickname; + INam organization; + char origin[160]; + Path quotebuffile; + char quotechars[11]; + int quotectrl; + char quotestring[10]; + bool quotewraphard; + GPlay play; + int replyre; + char tagline[76]; + char taglinechar; + bool taglinesupport; + Tear tearline; + Path tpl; + bool templatematch; + int usefwd; + Node username; + bool usetzutc; + IAdr whoto; + XlatName xlatexport; + XlatName xlatimport; + + // Reader + Path inputfile; + Path outputfile; + INam searchfor; + int twitmode; + bool viewhidden; + bool viewkludge; + bool viewquote; +}; + +// ------------------------------------------------------------------ + +extern AreaList AL; + + +// ------------------------------------------------------------------ +// Area information structures + +class Area { + +private: + + word marks; // storing 16 different marks + + friend class AreaList; + +public: + + // ---------------------------------------------------------------- + // Config data + + gmo_area* area; + AreaData* adat; + + + // ---------------------------------------------------------------- + // Constructor and destructor + + Area(gmo_area* a); + virtual ~Area(); + + + // ---------------------------------------------------------------- + // Data members + + GTag Msgn; // Message numbers + GTag Mark; // Message marks + GTag PMrk; // Personal mail marks + GTag Expo; // Messages to be exported + + ulong bookmark; // Current bookmark message number + + uint unread; // Number of unread messages at last scan + + uint lastread() const; // Number of last message read + ulong lastreadentry() const; // Lastread message number at entry to area + + void set_lastread(uint lr); + + bool isopen() { return area->isopen; } + + bool isunreadchg : 1; // TRUE if unread was changed since last scan + bool isreadmark : 1; // TRUE if in read marked mode + bool isreadpm : 1; // TRUE if in read personal mail mode + bool isvalidchg : 1; // TRUE if isunreadchg is valid + bool isscanned : 1; // TRUE if scanned + bool ispmscanned : 1; // TRUE if pmscanned + bool istossed : 1; // TRUE if msgs were tossed to this area + + + // ---------------------------------------------------------------- + // Access config data + + int areaid() const { return area->areaid(); } + int groupid() const { return area->groupid(); } + uint type() const { return area->type(); } + uint msgbase() const { return area->msgbase(); } + uint board() const { return area->board(); } + const ftn_addr& aka() const { return area->aka(); } + int originno() const { return area->originno(); } + Attr& attr() { return area->attr(); } + + bool scan() { return area->ascan(); } + bool scanexcl() { return area->ascanexcl(); } + bool scanincl() { return area->ascanincl(); } + bool pmscan() { return area->pmscan(); } + bool pmscanexcl() { return area->pmscanexcl(); } + bool pmscanincl() { return area->pmscanincl(); } + bool ismarked() const { return (marks & (1<echoid(); } + const char* desc() const { return area->desc(); } + const char* path() const { return area->path(); } + + void set_marked(bool value) { if(value) marks |= (word)(1<set_areaid(a); } + void set_groupid(int g) { area->set_groupid(g); } + void set_type(uint t) { area->set_type(t); } + void set_msgbase(uint m) { area->set_msgbase(m); } + void set_board(uint b) { area->set_board(b); } + void set_aka(ftn_addr& a) { area->set_aka(a); } + void set_originno(int o) { area->set_originno(o); } + void set_attr(Attr& a) { area->set_attr(a); } + void set_origin(char* o) { area->set_origin(o); } + + void set_scan(bool s) { area->set_scan(s); } + void set_scanexcl(bool s) { area->set_scanexcl(s); } + void set_scanincl(bool s) { area->set_scanincl(s); } + void set_pmscan(bool s) { area->set_pmscan(s); } + void set_pmscanexcl(bool s) { area->set_pmscanexcl(s); } + void set_pmscanincl(bool s) { area->set_pmscanincl(s); } + + void set_echoid(const char* s) { area->set_echoid(s); } + void set_desc(const char* s) { area->set_desc(s); } + void set_path(const char* s) { area->set_path(s); } + + + // ---------------------------------------------------------------- + // Determine msgbase format + + int isfts1() const; + int isopus() const; + int isezycom() const; + int isfido() const; + int isgoldbase() const; + int ishudson() const; + int isjam() const; + int ispcboard() const; + int issquish() const; + int iswildcat() const; + int isadeptxbbs() const; + int isseparator() const; + + + // ---------------------------------------------------------------- + // Determine area type + + int isnet() const; + int isecho() const; + int islocal() const; + int isemail() const; + int isnewsgroup() const; + int isinternet() const; + int isqwk() const; + int issoup() const; + + + // ---------------------------------------------------------------- + // Miscellaneous + + void SetBookmark(uint __relno); + void DeleteMsg(GMsg* msg, int direction); + void DelMsg(); + void DelMsgs(GMsg* msg); + void SigExportlistUpdate(); + void UpdateAreadata(); + + void SetHighwaterMark(); + void ResetHighwaterMark(); + + + // ---------------------------------------------------------------- + // High-level messagebase member functions + + void Open(); + void Close(); + + void Suspend(); + void Resume(); + + void Lock(); + void Unlock(); + + void Scan(); + void ScanArea(); + void ScanAreaPM(); + + int LoadHdr(GMsg* msg, ulong msgno); + int LoadMsg(GMsg* msg, ulong msgno, int margin, int mode=0); + + void SaveHdr(int mode, GMsg* msg); + void SaveMsg(int mode, GMsg* msg); + + void DelMsg(GMsg* msg); + + void NewMsgno(GMsg* msg); + char* UserLookup(char* lookfor); + int Renumber(); + + Line* MakeDumpMsg(GMsg* msg, char* lng_head); + + void UpdateTimesread(GMsg* msg); + + + // ---------------------------------------------------------------- + // Random System access functions + + void InitData(); + void RandomizeData(int mode=0); + + const ftn_aka& Aka() const { return adat->aka; } + bool Akamatching() const { return adat->akamatching; } + const Attr& Attributes() const { return adat->attributes; } + bool Areacopyaddid() const { return adat->areacopyaddid; } + bool Areacopydirect() const { return adat->areacopydirect; } + const char* Areacopyto() const { return adat->areacopyto; } + bool Areaforwarddirect() const{ return adat->areaforwarddirect; } + bool Areafreqdirect() const { return adat->areafreqdirect; } + const char* Areafreqto() const { return adat->areafreqto; } + bool Areareplydirect() const { return adat->areareplydirect; } + const char* Areareplyto() const { return adat->areareplyto; } + const char* Areayouwroteto() const { return adat->areayouwroteto; } + int Ctrlinfo() const { return adat->ctrlinfo; } + bool Edithardterm() const { return adat->edithardterm; } + bool Editmixcase() const { return adat->editmixcase; } + bool Forcetemplate() const { return adat->forcetemplate; } + const char* Inputfile() const { return adat->inputfile; } + const char* Internetaddress() const { return adat->internetaddress; } + const Node& Internetgate() const { return adat->internetgate; } + bool Internetmsgid() const { return adat->internetmsgid; } + bool Internetrfcbody() const { return adat->internetrfcbody; } + const char* Loadlanguage() const { return adat->loadlanguage; } + int Msglistdate() const { return adat->msglistdate; } + bool Msglistfast() const { return adat->msglistfast; } + bool Msglistfirst() const { return adat->msglistfirst; } + bool Msglistheader() const { return adat->msglistheader; } + bool Msglistwidesubj() const { return adat->msglistwidesubj; } + const char* Nickname() const { return adat->nickname; } + const char* Organization() const { return adat->organization; } + const char* Origin() const { return adat->origin; } + const char* Outputfile() const { return adat->outputfile; } + const char* Quotebuffile() const { return adat->quotebuffile; } + const char* Quotechars() const { return adat->quotechars; } + int Quotectrl() const { return adat->quotectrl; } + const char* Quotestring() const { return adat->quotestring; } + bool Quotewraphard() const { return adat->quotewraphard; } + const GPlay& Play() const { return adat->play; } + const int Replyre() const { return adat->replyre; } + const char* Searchfor() const { return adat->searchfor; } + const char* Tagline() const { return adat->tagline; } + char Taglinechar() const { return adat->taglinechar; } + bool Taglinesupport() const { return adat->taglinesupport; } + const char* Tearline() const { return adat->tearline; } + const char* Tpl() const { return adat->tpl; } + bool Templatematch() const { return adat->templatematch; } + int Twitmode() const { return adat->twitmode; } + int Usefwd() const { return adat->usefwd; } + const Node& Username() const { return adat->username; } + bool Usetzutc() const { return adat->usetzutc; } + bool Viewhidden() const { return adat->viewhidden; } + bool Viewkludge() const { return adat->viewkludge; } + bool Viewquote() const { return adat->viewquote; } + const char* Whoto() const { return adat->whoto; } + const char* Xlatexport() const { return adat->xlatexport; } + const char* Xlatimport() const { return adat->xlatimport; } + + int NextMsglistdate() { adat->msglistdate++; if(adat->msglistdate > MSGLISTDATE_RECEIVED) adat->msglistdate = MSGLISTDATE_NONE; return adat->msglistdate; } + const ftn_aka& SetAka(const ftn_addr& a) { adat->aka.addr = a; return adat->aka; } + const char* SetInputfile(const char* i) { return strcpy(adat->inputfile, i); } + int SetMsglistdate(int m) { adat->msglistdate = m; return adat->msglistdate; } + const char* SetOrigin(const char* o) { return strxcpy(adat->origin, o, sizeof(adat->origin)); } + const char* SetOutputfile(const char* o) { return strxcpy(adat->outputfile, o, sizeof(adat->outputfile)); } + const char* SetSearchfor(const char* s) { return strxcpy(adat->searchfor, s, sizeof(adat->searchfor)); } + const char* SetTagline(const char* t) { return strxcpy(adat->tagline, t, sizeof(adat->tagline)); } + const char* SetTpl(const char* t) { return strxcpy(adat->tpl, t, sizeof(adat->tpl)); } + int SetTwitmode(int m) { adat->twitmode = m; return adat->twitmode; } + const Node& SetUsername(const Node& n) { adat->username = n; return adat->username; } + const char* SetXlatexport(const char* x) { return strcpy(adat->xlatexport, x); } + const char* SetXlatimport(const char* x) { return strcpy(adat->xlatimport, x); } + int ToggleMsglistwidesubj() { adat->msglistwidesubj = not adat->msglistwidesubj; return adat->msglistwidesubj; } + int ToggleViewhidden() { adat->viewhidden = not adat->viewhidden; return adat->viewhidden; } + int ToggleViewkludge() { adat->viewkludge = not adat->viewkludge; return adat->viewkludge; } + int ToggleViewquote() { adat->viewquote = not adat->viewquote; return adat->viewquote; } + +}; + + +// ------------------------------------------------------------------ +// Inline implementations + +inline int Area::isfts1() const { return area->isfts1(); } +inline int Area::isopus() const { return area->isopus(); } +inline int Area::isezycom() const { return area->isezycom(); } +inline int Area::isfido() const { return area->isfido(); } +inline int Area::isgoldbase() const { return area->isgoldbase(); } +inline int Area::ishudson() const { return area->ishudson(); } +inline int Area::isjam() const { return area->isjam(); } +inline int Area::ispcboard() const { return area->ispcboard(); } +inline int Area::issquish() const { return area->issquish(); } +inline int Area::iswildcat() const { return area->iswildcat(); } +inline int Area::isadeptxbbs() const { return area->isadeptxbbs(); } +inline int Area::isseparator() const { return area->isseparator(); } + +inline int Area::isnet() const { return area->isnet(); } +inline int Area::isecho() const { return area->isecho(); } +inline int Area::islocal() const { return area->islocal(); } +inline int Area::isemail() const { return area->isemail(); } +inline int Area::isnewsgroup() const { return area->isnewsgroup(); } +inline int Area::isinternet() const { return area->isinternet(); } +inline int Area::isqwk() const { return area->isqwk(); } +inline int Area::issoup() const { return area->issoup(); } + +inline uint Area::lastread() const { return area->lastread; } +inline ulong Area::lastreadentry() const { return area->lastreadentry; } +inline void Area::set_lastread(uint lr) { area->lastread = lr; } + +inline void Area::SetBookmark(uint __relno) { bookmark = Msgn.CvtReln(__relno); /*Book.Add(bookmark);*/ } + +inline void Area::Suspend() { area->suspend(); } +inline void Area::Resume() { area->resume(); } + +inline void Area::Lock() { area->lock(); } +inline void Area::Unlock() { area->unlock(); } + +inline void Area::DelMsg(GMsg* msg) { area->del_msg(msg); } + +inline void Area::NewMsgno(GMsg* msg) { area->new_msgno(msg); } +inline char* Area::UserLookup(char* lookfor) { return area->user_lookup(lookfor); } +inline int Area::Renumber() { return area->renumber(); } + +inline Line* Area::MakeDumpMsg(GMsg* msg, char* lng_head) { return area->make_dump_msg(msg->lin, msg, lng_head); } + +inline void Area::SetHighwaterMark() { area->set_highwater_mark(); } +inline void Area::ResetHighwaterMark() { area->reset_highwater_mark(); } + +inline void Area::UpdateTimesread(GMsg* msg) { area->update_timesread(msg); } + + +// ------------------------------------------------------------------ + +class MsgbaseManager { + +public: + + void Init(); + void Exit(); + + void WideScanBegin(); + void WideScanEnd(); + + +}; + + +// ------------------------------------------------------------------ +// Arealist picker class + +class GPickArealist : public gwinpick { + +private: + + int areawin; + int tempwin; + int tempwin1; + int areawin1; + int areawin2; + int tempwin2; + uint area_fuzidx; + + int pmails; + int pmareas; + bool pmscan; + + void jump_to(); + void jumpmatch(); + void center(); + void AreasRenumber(); + void AreaCatchUp(uint n); + void AreaDropMsgMarks(uint n); + void dispbuf(char* buf, int areano); + +protected: + +public: + + uint area_maxfuz; + bool esc_abort; + + void open(); // Called after window is opened + void close(); // Called after window is closed + void precursor(); // Called before any cursor movement + void do_delayed(); // Called after a delay + void print_line(uint idx, uint pos, bool isbar); + bool handle_key(); // Handles keypress + bool is_selectable(uint idx); // is not separator ? + + void close_all(); + void update() { display_page(); display_bar(); } + + int Run(const char* _title, int wpos, int& idx); + + GPickArealist(); + +}; + + +// ------------------------------------------------------------------ + +#endif // __gmoarea_h diff --git a/golded3/golded.h b/golded3/golded.h new file mode 100644 index 0000000..efa27f0 --- /dev/null +++ b/golded3/golded.h @@ -0,0 +1,100 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Main include file. (For precompiled headers) +// ------------------------------------------------------------------ + +#ifndef __GOLDED_H +#define __GOLDED_H + + +// ------------------------------------------------------------------ +// Compiler dependencies + +#include + + +// ------------------------------------------------------------------ +// Standard library headers + +#include +#include +#include +#include +// Wrappers for certain mostly DOS/Borland headers +#include + + +// ------------------------------------------------------------------ +// Goldware Library headers + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// ------------------------------------------------------------------ +// GoldED specific headers + +#include +#include +#include +#include +#include +#include +#include +#include + + +// ------------------------------------------------------------------ + +#endif + +// ------------------------------------------------------------------ diff --git a/golded3/golded3.all b/golded3/golded3.all new file mode 100644 index 0000000..33cb846 --- /dev/null +++ b/golded3/golded3.all @@ -0,0 +1,87 @@ + +## ------------------------------------------------------------------ +## 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$ +## ------------------------------------------------------------------ +## Master build file. +## ------------------------------------------------------------------ + +gcalst cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gcarea cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gccfgg cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gccfgg0 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gccfgg1 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gccfgg2 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gccfgg3 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gccfgg4 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gccfgg5 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gccfgg6 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gccfgg7 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gccfgg8 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gckeys cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gclang cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gcmisc cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gealst cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gearea cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gecarb cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gecmfd cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gectnr cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gectrl cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gedoit cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gedoss cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geedit cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geedit2 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geedit3 cpp all nov bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gefile cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gefind cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geglob cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gehdre cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gehdrs cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geinit cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geline cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gelmsg cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gemain cpp all nov bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gemenu cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gemlst cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gemnus cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gemrks cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gemsgs cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +genode cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geplay cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gepost cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geqwks cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gerand cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geread cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geread2 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gescan cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gesrch cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gesoup cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +getpls cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geusrbse cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geutil cpp all nov bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geutil2 cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +geview cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gmarea cpp all ovl bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +golded3 cpp all nov bcd bco bcx djg emx lnx rsx wcn wco wcx cyg +gedcyg rc cyg +gedemx rc emx + +## ------------------------------------------------------------------ diff --git a/golded3/golded3.cpp b/golded3/golded3.cpp new file mode 100644 index 0000000..59df3fd --- /dev/null +++ b/golded3/golded3.cpp @@ -0,0 +1,152 @@ + +// ------------------------------------------------------------------ +// 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$ +// ------------------------------------------------------------------ +// Product name and version stuff. +// ------------------------------------------------------------------ + +#include + + +// ------------------------------------------------------------------ + +#define __GVER_PID__(A,B,C,SIZE) __GVER_PRE##SIZE##NAME__ __GVER_##SIZE##NAME__ __GVER_POST##SIZE##NAME__ __GVER_##SIZE##PLATFORM__ " " \ + __GVER_PREVERSION__ #A "." #B "." #C __GVER_POSTVERSION__ + +#define __GVER__(__GVER_MAJOR__,__GVER_MINOR__,__GVER_RELEASE__) \ +int __gver_major__ = __GVER_MAJOR__; \ +int __gver_minor__ = __GVER_MINOR__; \ +int __gver_release__ = __GVER_RELEASE__; \ +const char* __gver_longpid__ = __GVER_PID__(__GVER_MAJOR__,__GVER_MINOR__,__GVER_RELEASE__,); \ +const char* __gver_shortpid__ = __GVER_PID__(__GVER_MAJOR__,__GVER_MINOR__,__GVER_RELEASE__,SHORT); + + +// ------------------------------------------------------------------ +// Product name. + +#define __GVER_NAME__ "GoldED" +#define __GVER_SHORTNAME__ "GED" + + +// ------------------------------------------------------------------ +// Vendor data displayed on the startup screen. +// Define in "mygolded.h" if you want. + +#define __GVER_VENDOR_NAME__ "Anonymous" +#define __GVER_VENDOR_FIDO__ "" +#define __GVER_VENDOR_EMAIL__ "" +#define __GVER_RELEASENAME__ "" + + +// ------------------------------------------------------------------ +// Strings prepended and appended to the product name. +// Define in "mygolded.h" if you want. + +#define __GVER_PRENAME__ "" +#define __GVER_POSTNAME__ "" +#define __GVER_PRESHORTNAME__ "" +#define __GVER_POSTSHORTNAME__ "" + + +// ------------------------------------------------------------------ +// Strings prepended and appened to the version numbers. +// Define in "mygolded.h" if you want. + +#define __GVER_PREVERSION__ "" +#define __GVER_POSTVERSION__ "" + + +// ------------------------------------------------------------------ +// Platform specific strings. + +#if defined(__MSDOS__) +#define __GVER_PLATFORM__ "/386" +#define __GVER_SHORTPLATFORM__ "386" +#define __GVER_SHORTLOGNAME__ "X" +#define __GVER_CFGEXT__ ".gex" +#elif defined(__EMX__) +#define __GVER_PLATFORM__ "/EMX" +#define __GVER_SHORTPLATFORM__ "2" +#define __GVER_SHORTLOGNAME__ "2" +#define __GVER_CFGEXT__ ".geo" +#elif defined(__OS2__) +#define __GVER_PLATFORM__ "/2" +#define __GVER_SHORTPLATFORM__ "2" +#define __GVER_SHORTLOGNAME__ "2" +#define __GVER_CFGEXT__ ".geo" +#elif defined(__WIN32__) +#define __GVER_PLATFORM__ "/W32" +#define __GVER_SHORTPLATFORM__ "W32" +#define __GVER_SHORTLOGNAME__ "W" +#define __GVER_CFGEXT__ ".gew" +#elif defined(__linux__) +#define __GVER_PLATFORM__ "/LNX" +#define __GVER_SHORTPLATFORM__ "LNX" +#define __GVER_SHORTLOGNAME__ "L" +#define __GVER_CFGEXT__ ".gel" +#elif defined(__FreeBSD__) or defined(__OpenBSD__) +#define __GVER_PLATFORM__ "/BSD" +#define __GVER_SHORTPLATFORM__ "BSD" +#define __GVER_SHORTLOGNAME__ "B" +#define __GVER_CFGEXT__ ".geb" +#elif defined(__UNIX__) +#define __GVER_PLATFORM__ "/UNX" +#define __GVER_SHORTPLATFORM__ "UNX" +#define __GVER_SHORTLOGNAME__ "U" +#define __GVER_CFGEXT__ ".geu" +#else +#define __GVER_PLATFORM__ "" +#define __GVER_SHORTPLATFORM__ "" +#define __GVER_SHORTLOGNAME__ "D" +#define __GVER_CFGEXT__ ".ged" +#endif + +// ------------------------------------------------------------------ + +// Include your personalized strings here: +#include + + +// ------------------------------------------------------------------ +// Global variables + +const char* __gver_vendor_name__ = __GVER_VENDOR_NAME__; +const char* __gver_vendor_fido__ = __GVER_VENDOR_FIDO__; +const char* __gver_vendor_email__ = __GVER_VENDOR_EMAIL__; +const char* __gver_prename__ = __GVER_PRENAME__; +const char* __gver_preshortname__ = __GVER_PRESHORTNAME__; +const char* __gver_name__ = __GVER_NAME__; +const char* __gver_shortname__ = __GVER_SHORTNAME__; +const char* __gver_shortlogname__ = __GVER_SHORTNAME__ __GVER_SHORTLOGNAME__; +const char* __gver_postshortname__ = __GVER_POSTSHORTNAME__; +const char* __gver_postname__ = __GVER_POSTNAME__; +const char* __gver_platform__ = __GVER_PLATFORM__; +const char* __gver_shortplatform__ = __GVER_SHORTPLATFORM__; +const char* __gver_cfgext__ = __GVER_CFGEXT__; +const char* __gver_preversion__ = __GVER_PREVERSION__; +const char* __gver_postversion__ = __GVER_POSTVERSION__; +const char* __gver_releasename__ = __GVER_RELEASENAME__; +const char* __gver_date__ = __DATE__; +const char* __gver_time__ = __TIME__; + + +// ------------------------------------------------------------------ diff --git a/golded3/mygolded.__h b/golded3/mygolded.__h new file mode 100644 index 0000000..5fa5b12 --- /dev/null +++ b/golded3/mygolded.__h @@ -0,0 +1,53 @@ + +// ------------------------------------------------------------------ +// GoldED+ +// Personalized strings. +// ------------------------------------------------------------------ +// $Id$ +// ------------------------------------------------------------------ +// Please do not modify this file. It's just a template for your +// local "mygolded.h" settings file. So please change your copy only. + +// ------------------------------------------------------------------ +// Please edit these fields to match your real name + +#undef __GVER_VENDOR_NAME__ +#define __GVER_VENDOR_NAME__ "Put in your full name here" +#undef __GVER_VENDOR_FIDO__ +#define __GVER_VENDOR_FIDO__ "your Fidonet-AKA" +#undef __GVER_VENDOR_EMAIL__ +#define __GVER_VENDOR_EMAIL__ "your email@address" + + +// ------------------------------------------------------------------ +// If you have an important message every user should read, put it +// here in. If you don't, leave it as default. ;-) + +#undef __GVER_RELEASENAME__ +#define __GVER_RELEASENAME__ __GVER_VENDOR_NAME__"\'s personal edition" + + +// ------------------------------------------------------------------ +// It is highly recommended to leave these fields unchanged. +// They are reserved for future use. + +#undef __GVER_PRENAME__ +#define __GVER_PRENAME__ "" +#undef __GVER_POSTNAME__ +#define __GVER_POSTNAME__ "+" +#undef __GVER_PRESHORTNAME__ +#define __GVER_PRESHORTNAME__ "" +#undef __GVER_POSTSHORTNAME__ +#define __GVER_POSTSHORTNAME__ "+" + + +// ------------------------------------------------------------------ +// Version numbers. + +#undef __GVER_PREVERSION__ +#define __GVER_PREVERSION__ "" +#undef __GVER_POSTVERSION__ +#define __GVER_POSTVERSION__ ".3" +__GVER__(1,1,4) + +// ------------------------------------------------------------------