// ------------------------------------------------------------------ // 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 #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 }; // ------------------------------------------------------------------ // 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()) { if(B->msgbase()) return sepfirst?-1:1; } else if(B->isseparator()) { if(A->msgbase()) return sepfirst?1:-1; } else if((cmp = compare_two(A->msgbase(), B->msgbase())) != 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; 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; 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) { __extension__ char buf[DESC_LEN+3]; *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; } // ------------------------------------------------------------------