This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-goldedplus/golded3/gealst.cpp
2005-10-04 23:32:38 +00:00

572 lines
13 KiB
C++

// ------------------------------------------------------------------
// GoldED+
// Copyright (C) 1990-1999 Odinn Sorensen
// Copyright (C) 1999-2000 Alexander S. Aganichev
// ------------------------------------------------------------------
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston,
// MA 02111-1307 USA
// ------------------------------------------------------------------
// $Id$
// ------------------------------------------------------------------
// Arealist functions.
// ------------------------------------------------------------------
#if defined(__MINGW32__) || defined(_MSC_VER)
#include <malloc.h>
#endif
#if defined(_MSC_VER)
/* C4786: 'identifier' : identifier was truncated to 'number'
characters in the debug information
*/
#pragma warning(disable: 4786)
#endif
#include <algorithm>
#include <golded.h>
// ------------------------------------------------------------------
AreaList AL;
int AreaTypeOrder[17] = {
0,
1, // GMB_NET
2, // GMB_EMAIL
3, // GMB_NET | GMB_EMAIL
4, // GMB_ECHO
5,
6,
7,
8, // GMB_NEWSGROUP
9,
10,
11,
12, // GMB_ECHO | GMB_NEWSGROUP
13,
14,
15,
16 // GMB_LOCAL
};
// ------------------------------------------------------------------
// Areagroups compare
int compare_groups(int _ga, int _gb)
{
register int ga = _ga ? _ga : INT_MAX;
register int gb = _gb ? _gb : INT_MAX;
const char *gap = NULL;
const char *gbp = NULL;
const char *g;
for(g = CFG->arealistgrouporder; *g != NUL;) {
int gr = getgroup(g);
if(gr == ga)
gap = g;
if(gr == gb)
gbp = g;
if(*g == '#') {
do {
g++;
} while(isdigit(*g));
}
else
g++;
}
if(gap == NULL) {
if(gbp != NULL)
return 1;
else
return compare_two(ga, gb);
}
else {
if(gbp == NULL)
return -1;
else
return compare_two(gap, gbp);
}
}
// ------------------------------------------------------------------
// 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;
bool sepfirst = false;
bool rev = false;
char* ptr = AL.sortspec;
while(*ptr) {
switch(*ptr) {
case '-':
rev = true;
A = b; B = a;
break;
case '+':
rev = false;
A = a; B = b;
break;
case 'A':
case 'a':
sepfirst = true;
if((cmp = A->aka().compare(B->aka())) != 0)
return cmp;
break;
case 'B':
case 'b':
if(A->isseparator() and B->isseparator())
break;
else if(A->isseparator()) {
if(B->board())
return sepfirst?-1:1;
}
else if(B->isseparator()) {
if(A->board())
return sepfirst?1:-1;
}
else if((cmp = compare_two(A->board(), B->board())) != 0)
return cmp;
break;
case 'D':
case 'd':
if((cmp = stricmp(A->desc(), B->desc())) != 0)
return cmp;
break;
case 'E':
case 'e':
if((cmp = stricmp(A->echoid(), B->echoid())) != 0)
return cmp;
break;
case 'F':
case 'f':
if(*area_maybe) {
register bool amay = striinc(area_maybe, A->echoid()) ? true : false;
register bool bmay = striinc(area_maybe, B->echoid()) ? true : false;
if((cmp = compare_two(bmay, amay)) != 0)
return cmp;
}
break;
case 'G':
case 'g':
sepfirst = true;
if((cmp = compare_groups(A->groupid(), B->groupid())) != 0)
return cmp;
break;
case 'M':
case 'm':
if(A->isseparator() and B->isseparator())
break;
else if(A->isseparator()) {
if(B->ismarked())
return sepfirst?-1:1;
}
else if(B->isseparator()) {
if(A->ismarked())
return sepfirst?1:-1;
}
else if((cmp = compare_two(B->ismarked(), A->ismarked())) != 0)
return cmp;
break;
case 'P':
if(A->isseparator() and B->isseparator())
break;
else if(A->isseparator()) {
if(B->PMrk.Count())
return sepfirst?-1:1;
}
else if(B->isseparator()) {
if(A->PMrk.Count())
return sepfirst?1:-1;
}
else {
register int aunread = A->PMrk.Count();
register int bunread = B->PMrk.Count();
aunread = (rev or aunread) ? aunread : INT_MAX;
bunread = (rev or bunread) ? bunread : INT_MAX;
if((cmp = compare_two(aunread, bunread)) != 0)
return cmp;
}
break;
case 'p':
if(A->isseparator() and B->isseparator())
break;
else if(A->isseparator()) {
if(B->PMrk.Count())
return sepfirst?-1:1;
}
else if(B->isseparator()) {
if(A->PMrk.Count())
return sepfirst?1:-1;
}
else if((cmp = compare_two(B->PMrk.Count()?1:0, A->PMrk.Count()?1:0)) != 0)
return cmp;
break;
case 'O':
case 'o':
if((cmp = compare_two(A->areaid(), B->areaid())) != 0)
return cmp;
break;
case 'T':
case 't':
sepfirst = true;
if((cmp = compare_two(CFG->areatypeorder[A->type()&0xFF], CFG->areatypeorder[B->type()&0xFF])) != 0)
return cmp;
break;
case 'U':
if(A->isseparator() and B->isseparator())
break;
else if(A->isseparator()) {
if(B->unread)
return sepfirst?-1:1;
}
else if(B->isseparator()) {
if(A->unread)
return sepfirst?1:-1;
}
else {
register int aunread = A->unread;
register int bunread = B->unread;
aunread = (rev or aunread) ? aunread : INT_MAX;
bunread = (rev or bunread) ? bunread : INT_MAX;
if((cmp = compare_two(aunread, bunread)) != 0)
return cmp;
}
break;
case 'u':
if(A->isseparator() and B->isseparator())
break;
else if(A->isseparator()) {
if(B->unread)
return sepfirst?-1:1;
}
else if(B->isseparator()) {
if(A->unread)
return sepfirst?1:-1;
}
else if((cmp = compare_two(B->unread?1:0, A->unread?1:0)) != 0)
return cmp;
break;
case 'X':
case 'x':
if(A->isseparator() and B->isseparator())
break;
else if(A->isseparator()) {
return sepfirst?-1:1;
}
else if(B->isseparator()) {
return sepfirst?1:-1;
}
else if((cmp = strcmp(A->basetype(), B->basetype())) != 0)
return cmp;
break;
case 'Y':
case 'y':
if(A->isseparator() and B->isseparator())
break;
else if(A->isseparator()) {
if(B->isnewmail())
return sepfirst?-1:1;
}
else if(B->isseparator()) {
if(A->isnewmail())
return sepfirst?1:-1;
}
else if((cmp = compare_two(B->isnewmail(), A->isnewmail())) != 0)
return cmp;
break;
case 'Z':
case 'z':
if(A->isseparator() and B->isseparator())
break;
else if(A->isseparator())
return sepfirst?-1:1;
else if(B->isseparator())
return sepfirst?1:-1;
else if((cmp = stricmp(A->path(), B->path())) != 0)
return cmp;
break;
case 'S':
case 's':
if((cmp = compare_two(B->isseparator(), A->isseparator())) != 0)
return cmp;
break;
}
ptr++;
}
if(cmp == 0) {
cmp = compare_two(B->isseparator(), A->isseparator());
}
return cmp;
}
static bool AreaListCmp2(const Area* a, const Area* b) {
return AreaListCmp(&a, &b) < 0;
}
// ------------------------------------------------------------------
// 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) {
std::sort(idx.begin()+first, idx.begin()+last, AreaListCmp2);
}
}
// ------------------------------------------------------------------
int AreaList::AreaEchoToNo(const char* echoid) {
for(uint n=0; n<idx.size(); n++)
if(strieql(echoid, idx[n]->echoid()))
return n;
return -1;
}
// ------------------------------------------------------------------
Area* AreaList::AreaEchoToPtr(const char* echoid) {
for(uint n=0; n<idx.size(); n++)
if(strieql(echoid, idx[n]->echoid()))
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;
int DESC_LEN;
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) {
#if defined(__WIN32__)
char *buf = (char*)alloca(DESC_LEN+3);
#else
__extension__ char buf[DESC_LEN+3];
#endif
*buf = ' '; strxcpy(buf+1, AL.alistselections[idx], DESC_LEN);
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], DESC_LEN-1, LNG->SelectMarksEdit, H_SelectMarks);
display_bar();
}
break;
}
return true;
}
void SelMaskPick::Run() {
DESC_LEN = (sizeof(Desc) > (MAXCOL-6)) ? MAXCOL-6 : sizeof(Desc);
ypos = (MAXROW-18)/2;
xpos = (MAXCOL-DESC_LEN-4)/2-1;
ylen = 16;
xlen = DESC_LEN+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;
}
// ------------------------------------------------------------------