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/gemlst.cpp

1235 lines
30 KiB
C++
Raw Normal View History

2000-02-25 11:04:07 +00:00
// ------------------------------------------------------------------
// GoldED+
// Copyright (C) 1990-1999 Odinn Sorensen
// Copyright (C) 1999-2000 Alexander S. Aganichev
// ------------------------------------------------------------------
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston,
// MA 02111-1307 USA
// ------------------------------------------------------------------
// $Id$
// ------------------------------------------------------------------
// Message lister.
// ------------------------------------------------------------------
#include <golded.h>
2001-10-07 08:24:26 +00:00
#include <gcharset.h>
2001-10-07 14:49:47 +00:00
#include <iostream>
#include <iomanip>
2000-02-25 11:04:07 +00:00
2005-10-11 01:54:40 +00:00
#if defined(__USE_ALLOCA__)
#include <malloc.h>
#endif
2000-02-25 11:04:07 +00:00
// ------------------------------------------------------------------
extern GMsg* reader_msg;
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;
}
}
// ------------------------------------------------------------------
2001-03-17 21:17:57 +00:00
class GMsgList : public gwinpick {
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
gwindow window;
GMsg msg;
2001-04-15 19:24:44 +00:00
MLst **mlst;
2001-03-17 21:17:57 +00:00
uint msgmark2;
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
void open(); // Called after window is opened
void close(); // Called after window is closed
void update_title();
void do_delayed();
void print_line(uint idx, uint pos, bool isbar);
bool handle_key(); // Handles keypress
2001-04-24 10:40:54 +00:00
void update_marks(MLst *ml);
2001-03-17 21:17:57 +00:00
void ReadMlst(int n);
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
public:
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
void Run();
2000-02-25 11:04:07 +00:00
2001-04-15 19:24:44 +00:00
GMsgList() {
memset(&msg, 0, sizeof(GMsg));
mlst = NULL;
maximum_index = AA->Msgn.Count()-1;
};
~GMsgList() {
ResetMsg(&msg);
if(mlst) {
for(uint i=0; i<= maximum_index; i++)
throw_xdelete(mlst[i]);
throw_free(mlst);
}
};
2001-03-17 21:17:57 +00:00
};
2000-02-25 11:04:07 +00:00
// ------------------------------------------------------------------
2001-03-17 21:17:57 +00:00
void GMsgList::open() {
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
window.openxy(ypos, xpos, ylen+2, xlen+2, btype, battr, wattr, sbattr);
update_title();
center(CFG->displistcursor);
2000-02-25 11:04:07 +00:00
}
// ------------------------------------------------------------------
2001-03-17 21:17:57 +00:00
void GMsgList::close() {
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
window.close();
2000-02-25 11:04:07 +00:00
}
// ------------------------------------------------------------------
2001-04-24 10:40:54 +00:00
void GMsgList::update_marks(MLst *ml) {
2001-04-15 19:24:44 +00:00
ml->high &= ~(MLST_HIGH_BOOK|MLST_HIGH_MARK);
2000-02-25 11:04:07 +00:00
strcpy(ml->marks, " ");
2001-04-24 10:40:54 +00:00
if(AA->bookmark == ml->msgno) {
2000-02-25 11:04:07 +00:00
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;
}
}
2001-04-24 10:40:54 +00:00
}
// ------------------------------------------------------------------
void GMsgList::ReadMlst(int n) {
MLst* ml = mlst[n];
if(ml != NULL)
return;
ml = mlst[n] = new MLst;
throw_new(ml);
ml->msgno = AA->Msgn.CvtReln(n + 1);
ml->high = 0;
2001-04-24 10:40:54 +00:00
update_marks(ml);
2000-02-25 11:04:07 +00:00
if(AA->Msglistfast()) {
2001-03-17 21:17:57 +00:00
AA->LoadHdr(&msg, ml->msgno);
2000-02-25 11:04:07 +00:00
}
else {
2001-03-17 21:17:57 +00:00
AA->LoadMsg(&msg, ml->msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar));
2000-02-25 11:04:07 +00:00
}
ml->goldmark = goldmark;
for(std::vector<Node>::iterator x = CFG->username.begin(); x != CFG->username.end(); x++) {
2001-03-17 21:17:57 +00:00
if(strieql(msg.By(), x->name)) {
2000-02-25 11:04:07 +00:00
ml->high |= MLST_HIGH_FROM;
2001-03-17 21:17:57 +00:00
msg.attr.fmu1();
2000-02-25 11:04:07 +00:00
}
2001-03-17 21:17:57 +00:00
if(strieql(msg.to, x->name)) {
2000-02-25 11:04:07 +00:00
ml->high |= MLST_HIGH_TO;
2001-03-17 21:17:57 +00:00
msg.attr.tou1();
2000-02-25 11:04:07 +00:00
}
}
2001-03-17 21:17:57 +00:00
if(strieql(msg.to, AA->Internetaddress())) {
2000-02-25 11:04:07 +00:00
ml->high |= MLST_HIGH_TO;
2001-03-17 21:17:57 +00:00
msg.attr.tou1();
2000-02-25 11:04:07 +00:00
}
// Highlight FROM if local
2001-03-17 21:17:57 +00:00
if(CFG->switches.get(displocalhigh) and msg.attr.loc())
2000-02-25 11:04:07 +00:00
ml->high |= MLST_HIGH_FROM;
// Highlight if unread
2001-04-15 19:24:44 +00:00
if((msg.timesread == 0) and CFG->switches.get(highlightunread))
2000-02-25 11:04:07 +00:00
ml->high |= MLST_HIGH_UNREAD;
// Highlight if unsent
2001-04-15 19:24:44 +00:00
if(msg.attr.uns() and not msg.attr.rcv() and not msg.attr.del())
2000-02-25 11:04:07 +00:00
ml->high |= MLST_HIGH_UNSENT;
2001-03-17 21:17:57 +00:00
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);
2000-02-25 11:04:07 +00:00
}
// ------------------------------------------------------------------
2001-03-17 21:17:57 +00:00
void GMsgList::do_delayed() {
2001-03-17 21:17:57 +00:00
// Update header and statusline
if(AA->Msglistheader()) {
ReadMlst(index);
2001-04-15 19:24:44 +00:00
AA->LoadMsg(&msg, mlst[index]->msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar));
mlst[index]->goldmark = goldmark;
if(mlst[index]->high & MLST_HIGH_FROM)
msg.attr.fmu1();
if(mlst[index]->high & MLST_HIGH_TO)
msg.attr.tou1();
2001-03-17 21:17:57 +00:00
int mlstwh = whandle();
HeaderView->Use(AA, &msg);
HeaderView->Paint();
wactiv_(mlstwh);
2000-02-25 11:04:07 +00:00
}
2001-04-08 08:02:01 +00:00
if(CFG->switches.get(msglistviewsubj)) {
ReadMlst(index);
2001-04-15 19:24:44 +00:00
wtitle(mlst[index]->re, TCENTER|TBOTTOM, tattr);
2001-04-08 08:02:01 +00:00
}
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
if(CFG->switches.get(msglistpagebar))
wscrollbar(W_VERT, maximum_index+1, maximum_index, index);
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
update_statuslinef(LNG->MsgLister, index+1, maximum_index+1, maximum_index-index);
2000-02-25 11:04:07 +00:00
}
// ------------------------------------------------------------------
2001-03-17 21:17:57 +00:00
void GMsgList::update_title() {
2000-02-25 11:04:07 +00:00
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;
2001-03-17 21:17:57 +00:00
window.title(NULL, tattr, TCENTER);
window.message(CFG->switches.get(disprealmsgno) ? LNG->MsgReal : LNG->Msg, TP_BORD, 3, tattr);
window.message(LNG->FromL, TP_BORD, bycol, tattr);
2000-02-25 11:04:07 +00:00
if(not AA->Msglistwidesubj())
2001-03-17 21:17:57 +00:00
window.message(LNG->ToL, TP_BORD, tocol, tattr);
window.message(LNG->SubjL, TP_BORD, recol, tattr);
2000-02-25 11:04:07 +00:00
switch(AA->Msglistdate()) {
2001-03-17 21:17:57 +00:00
case MSGLISTDATE_WRITTEN: window.message(LNG->Written, TP_BORD, dtcol, tattr); break;
case MSGLISTDATE_ARRIVED: window.message(LNG->Arrived, TP_BORD, dtcol, tattr); break;
case MSGLISTDATE_RECEIVED: window.message(LNG->Received, TP_BORD, dtcol, tattr); break;
2000-02-25 11:04:07 +00:00
}
}
// ------------------------------------------------------------------
2001-03-17 21:17:57 +00:00
void GMsgList::print_line(uint idx, uint pos, bool isbar) {
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
int bycol = 7;
int tocol = bycol + mlst_bysiz + 1 + fldadd1;
int bysiz = mlst_bysiz + fldadd1;
int tosiz = mlst_tosiz + fldadd1;
int resiz = mlst_resiz + fldadd2;
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
ReadMlst(idx);
2001-04-15 19:24:44 +00:00
MLst* ml = mlst[idx];
2000-02-25 11:04:07 +00:00
2001-05-22 20:56:11 +00:00
update_marks(ml);
2001-03-17 21:17:57 +00:00
int wattr_, hattr_, mattr_;
if(isbar) {
wattr_ = sattr;
hattr_ = sattr;
mattr_ = sattr;
}
else if(ml->high & MLST_HIGH_UNSENT) {
wattr_ = C_MENUW_UNSENT;
hattr_ = C_MENUQ_UNSENTHIGH;
mattr_ = hattr;
}
else if(ml->high & MLST_HIGH_UNREAD) {
wattr_ = C_MENUW_UNREAD;
hattr_ = C_MENUQ_UNREADHIGH;
mattr_ = hattr;
}
else {
wattr_ = wattr;
hattr_ = hattr;
mattr_ = hattr;
}
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
char buf[256];
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
if(AA->Msglistwidesubj()) {
resiz += tosiz + 1;
tosiz = 0;
}
char nbuf[33], dbuf[20];
strcpy(dbuf, LNG->n_a);
2005-10-20 21:10:42 +00:00
time32_t dt = 0;
2001-03-17 21:17:57 +00:00
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", ggmtime(&dt));
2001-03-17 21:17:57 +00:00
if(AA->Msglistdate())
strsetsz(dbuf, 10);
else
*dbuf = NUL;
2005-10-27 19:49:46 +00:00
sprintf(nbuf, "%5lu", long(CFG->switches.get(disprealmsgno) ? ml->msgno : AA->Msgn.ToReln(ml->msgno)));
2001-03-17 21:17:57 +00:00
sprintf(buf, "%-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
);
window.prints(pos, 0, wattr_, buf);
if(ml->high & (MLST_HIGH_BOOK|MLST_HIGH_MARK))
window.prints(pos, 5, mattr_, ml->marks);
if(ml->high & MLST_HIGH_FROM)
window.printns(pos, bycol, hattr_, ml->by, bysiz);
if((ml->high & MLST_HIGH_TO) and not AA->Msglistwidesubj())
window.printns(pos, tocol, hattr_, ml->to, tosiz);
goldmark = ml->goldmark;
2000-02-25 11:04:07 +00:00
}
// ------------------------------------------------------------------
2001-03-17 21:17:57 +00:00
bool GMsgList::handle_key() {
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
gkey kk;
2000-02-25 11:04:07 +00:00
if(key < KK_Commands) {
2001-03-17 21:17:57 +00:00
// See if it's a listkey
2000-02-25 11:04:07 +00:00
kk = SearchKey(key, ListKey, ListKeys);
if(kk)
key = kk;
2001-03-17 21:17:57 +00:00
else {
// If not a listkey, see if it matches a readkey
2000-02-25 11:04:07 +00:00
if(not IsMacro(key, KT_M)) {
kk = SearchKey(key, ReadKey, ReadKeys);
if(kk)
key = kk;
}
2001-03-17 21:17:57 +00:00
}
2000-02-25 11:04:07 +00:00
}
2001-03-17 21:17:57 +00:00
ReadMlst(index);
2000-02-25 11:04:07 +00:00
switch(key) {
case KK_ListGotoPrev:
2001-03-17 21:17:57 +00:00
key = Key_Up;
default_handle_key();
2000-02-25 11:04:07 +00:00
break;
case KK_ListGotoNext:
2001-03-17 21:17:57 +00:00
key = Key_Dwn;
default_handle_key();
2000-02-25 11:04:07 +00:00
break;
case KK_ListGotoFirst:
2001-03-17 21:17:57 +00:00
key = Key_Home;
default_handle_key();
2000-02-25 11:04:07 +00:00
break;
case KK_ListGotoLast:
2001-03-17 21:17:57 +00:00
key = Key_End;
default_handle_key();
2000-02-25 11:04:07 +00:00
break;
case KK_ListAskExit:
{
GMenuQuit MenuQuit;
2005-10-22 02:45:18 +00:00
aborted = gkbd.quitall = make_bool(MenuQuit.Run());
if(gkbd.quitall) {
2000-02-25 11:04:07 +00:00
AA->bookmark = AA->Msgn.CvtReln(msgmark2);
return false;
}
2000-02-25 11:04:07 +00:00
}
break;
case KK_ListQuitNow:
2001-03-17 21:17:57 +00:00
gkbd.quitall = true;
///////////////// Drop Through
2000-02-25 11:04:07 +00:00
case KK_ListAbort:
2001-03-17 21:17:57 +00:00
aborted = true;
2000-02-25 11:04:07 +00:00
AA->bookmark = AA->Msgn.CvtReln(msgmark2);
///////////////// Drop Through
case KK_ListSelect:
2001-03-17 21:17:57 +00:00
return false;
2000-02-25 11:04:07 +00:00
2003-06-09 05:47:39 +00:00
case KK_ListMark:
{
2005-10-20 21:41:32 +00:00
uint32_t temp = AA->Mark.Find(mlst[index]->msgno);
2003-06-09 05:47:39 +00:00
if(not temp) {
AA->Mark.Add(mlst[index]->msgno);
update_marks(mlst[index]);
}
}
if(index < maximum_index)
cursor_down();
else
display_bar();
break;
case KK_ListUnmark:
{
2005-10-20 21:41:32 +00:00
uint32_t temp = AA->Mark.Find(mlst[index]->msgno);
2003-06-09 05:47:39 +00:00
if(temp) {
AA->Mark.DelReln(temp);
update_marks(mlst[index]);
}
}
if(index < maximum_index)
cursor_down();
else
display_bar();
break;
2000-02-25 11:04:07 +00:00
case KK_ListToggleMark:
2001-03-17 21:17:57 +00:00
{
2005-10-20 21:41:32 +00:00
uint32_t temp = AA->Mark.Find(mlst[index]->msgno);
2001-03-17 21:17:57 +00:00
if(temp) {
AA->Mark.DelReln(temp);
}
else {
2001-04-15 19:24:44 +00:00
AA->Mark.Add(mlst[index]->msgno);
2001-03-17 21:17:57 +00:00
}
2001-04-24 10:40:54 +00:00
update_marks(mlst[index]);
2000-02-25 11:04:07 +00:00
}
2001-03-27 20:51:40 +00:00
if(index < maximum_index)
cursor_down();
else
display_bar();
break;
2000-02-25 11:04:07 +00:00
case KK_ListToggleBookMark:
2001-04-15 19:24:44 +00:00
if(AA->bookmark == mlst[index]->msgno) {
mlst[index]->marks[0] = ' ';
2000-02-25 11:04:07 +00:00
AA->bookmark = 0;
2001-04-15 19:24:44 +00:00
mlst[index]->high &= ~MLST_HIGH_BOOK;
2001-03-17 21:17:57 +00:00
display_bar();
2000-02-25 11:04:07 +00:00
}
else {
2001-03-17 21:17:57 +00:00
long prevbm = AA->Msgn.ToReln(AA->bookmark-1);
long newbm = index;
2001-04-15 19:24:44 +00:00
AA->bookmark = mlst[index]->msgno;
mlst[index]->marks[0] = MMRK_BOOK;
mlst[index]->high |= MLST_HIGH_BOOK;
2001-03-17 21:17:57 +00:00
display_bar();
if(prevbm) {
if(in_range((long)position + prevbm - newbm, 0l, (long)maximum_position)) {
ReadMlst(prevbm);
2001-04-15 19:24:44 +00:00
mlst[prevbm]->marks[0] = ' ';
mlst[prevbm]->high &= ~MLST_HIGH_BOOK;
2001-03-17 21:17:57 +00:00
index = prevbm;
position += prevbm - newbm;
display_line();
index = newbm;
position -= prevbm - newbm;
2000-02-25 11:04:07 +00:00
}
}
}
break;
case KK_ListGotoBookMark:
if(AA->bookmark) {
2001-03-17 21:17:57 +00:00
long prevbm = AA->Msgn.ToReln(AA->bookmark-1);
long newbm = index;
index = prevbm;
2001-04-15 19:24:44 +00:00
AA->bookmark = mlst[newbm]->msgno;
2001-03-17 21:17:57 +00:00
if(in_range((long)position + prevbm - newbm, 0l, (long)maximum_position)) {
2001-04-15 19:24:44 +00:00
mlst[newbm]->marks[0] = MMRK_BOOK;
mlst[newbm]->high |= MLST_HIGH_BOOK;
2001-03-17 21:17:57 +00:00
index = newbm;
display_line();
index = prevbm;
ReadMlst(index);
2001-04-15 19:24:44 +00:00
mlst[index]->marks[0] = ' ';
mlst[index]->high &= ~MLST_HIGH_BOOK;
2001-03-17 21:17:57 +00:00
position += prevbm - newbm;
display_bar();
2000-02-25 11:04:07 +00:00
}
else
2001-03-17 21:17:57 +00:00
center(CFG->displistcursor);
2000-02-25 11:04:07 +00:00
}
else
SayBibi();
break;
case KK_ListMarkingOptions:
{
uint lrbak = AA->lastread();
2001-03-17 21:17:57 +00:00
AA->set_lastread(index + 1);
msg.msgno = AA->Msgn.CvtReln(AA->lastread());
MarkMsgs(&msg);
2000-02-25 11:04:07 +00:00
AA->set_lastread(lrbak);
2001-03-17 21:17:57 +00:00
update();
2000-02-25 11:04:07 +00:00
}
break;
case KK_ListDosShell:
DosShell();
break;
2003-06-09 05:47:39 +00:00
case KK_ListWideSubj:
if(not AA->Msglistwidesubj()) {
AA->ToggleMsglistwidesubj();
update_title();
update();
}
break;
case KK_ListNarrowSubj:
if(AA->Msglistwidesubj()) {
AA->ToggleMsglistwidesubj();
update_title();
update();
}
break;
2000-02-25 11:04:07 +00:00
case KK_ListToggleWideSubj:
AA->ToggleMsglistwidesubj();
2001-03-17 21:17:57 +00:00
update_title();
update();
2000-02-25 11:04:07 +00:00
break;
case KK_ListToggleDate:
AA->NextMsglistdate();
mlst_with_date(AA->Msglistdate());
2001-03-17 21:17:57 +00:00
update_title();
update();
2000-02-25 11:04:07 +00:00
break;
case KK_ReadMessageList:
2001-03-17 21:17:57 +00:00
center(CFG->displistcursor);
2000-02-25 11:04:07 +00:00
break;
case Key_Tick:
CheckTick(KK_ListQuitNow);
break;
case KK_ListUndefine:
break;
default:
if(not PlayMacro(key, KT_M)) {
2001-03-17 21:17:57 +00:00
if(gkbd.kbuf == NULL)
kbput(key);
2000-02-25 11:04:07 +00:00
switch(key) {
2001-03-17 21:17:57 +00:00
case KK_ListAbort:
2000-02-25 11:04:07 +00:00
case KK_ReadNewArea:
2001-03-17 21:17:57 +00:00
aborted = true;
2000-02-25 11:04:07 +00:00
}
2001-03-17 21:17:57 +00:00
return false;
2000-02-25 11:04:07 +00:00
}
}
2001-03-17 21:17:57 +00:00
return true;
2000-02-25 11:04:07 +00:00
}
// ------------------------------------------------------------------
2001-03-17 21:17:57 +00:00
void GMsgList::Run() {
2000-02-25 11:04:07 +00:00
2001-04-15 19:24:44 +00:00
if(maximum_index == 0) {
aborted = true;
return;
}
2002-08-30 06:01:33 +00:00
if(AA->Msgn.ToReln(reader_msg->msgno) != 0)
index = AA->Msgn.ToReln(reader_msg->msgno)-1;
else
index = 0;
2001-04-15 19:24:44 +00:00
minimum_index = 0;
msgmark2 = AA->Msgn.ToReln(AA->bookmark);
2001-03-17 21:17:57 +00:00
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_MessageBrowser; // Window Help Category
listwrap = CFG->switches.get(displistwrap);
2000-02-25 11:04:07 +00:00
2003-12-10 08:35:16 +00:00
if((AA->Msglistdate() == MSGLISTDATE_RECEIVED) and not AA->havereceivedstamp())
AA->SetMsglistdate(MSGLISTDATE_WRITTEN);
else if((AA->Msglistdate() == MSGLISTDATE_ARRIVED) and not AA->havearrivedstamp())
AA->SetMsglistdate(MSGLISTDATE_WRITTEN);
2000-02-25 11:04:07 +00:00
mlst_with_date(AA->Msglistdate());
fldadd1 = (MAXCOL-80)/3;
fldadd2 = (MAXCOL-80) - (fldadd1*2);
2001-04-15 19:24:44 +00:00
mlst = (MLst **)throw_malloc(sizeof(MLst *) * (maximum_index + 1));
2000-02-25 11:04:07 +00:00
2001-03-20 10:55:09 +00:00
for(uint i=0; i<= maximum_index; i++)
2001-04-15 19:24:44 +00:00
mlst[i] = NULL;
2000-02-25 11:04:07 +00:00
2001-03-20 10:55:09 +00:00
maximum_position = MinV((uint)maximum_index, (uint)ylen - 1);
2000-02-25 11:04:07 +00:00
2001-04-15 19:24:44 +00:00
run_picker();
2000-02-25 11:04:07 +00:00
2001-03-17 21:17:57 +00:00
if(not aborted) {
ReadMlst(index);
2001-04-15 19:24:44 +00:00
AA->set_lastread(AA->Msgn.ToReln(mlst[index]->msgno));
2001-03-17 21:17:57 +00:00
}
2000-02-25 11:04:07 +00:00
}
// ------------------------------------------------------------------
void MessageBrowse() {
if(AA->Msgn.Count()) {
2001-03-17 21:17:57 +00:00
GMsgList p;
_in_msglist = true;
p.Run();
_in_msglist = false;
2000-02-25 11:04:07 +00:00
if(AA->PMrk.Tags() == 0)
AA->isreadpm = false;
if(AA->Mark.Count() == 0)
AA->isreadmark = false;
if(gkbd.quitall)
QuitNow();
}
}
// ------------------------------------------------------------------
class ThreadEntry {
public:
2005-10-20 21:41:32 +00:00
uint32_t msgno;
uint32_t replyto;
uint32_t reply1st;
uint32_t replynext;
uint32_t replytoindex;
uint32_t level;
2000-02-25 11:04:07 +00:00
};
#define MAX_LEVEL 20
class GThreadlist : public gwinpick {
private:
gwindow window;
GMsg msg;
std::vector<ThreadEntry> list;
2000-02-25 11:04:07 +00:00
ThreadEntry t;
void BuildThreadIndex(dword msgno);
2005-10-20 21:41:32 +00:00
void recursive_build(uint32_t msgn, uint32_t rn, uint32_t level);
void GenTree(char* buf2, int idx, uint32_t maxlev);
2000-02-25 11:04:07 +00:00
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)); replylinkfloat = CFG->replylinkfloat; };
2000-02-25 11:04:07 +00:00
~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() {
2000-02-25 11:04:07 +00:00
// Update header and statusline
if(AA->Msglistheader()) {
AA->LoadMsg(&msg, list[index].msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar));
for(std::vector<Node>::iterator x = CFG->username.begin(); x != CFG->username.end(); x++) {
if(strieql(msg.By(), x->name)) {
msg.attr.fmu1();
}
if(strieql(msg.to, x->name)) {
msg.attr.tou1();
}
}
if(strieql(msg.to, AA->Internetaddress())) {
msg.attr.tou1();
}
2000-02-25 11:04:07 +00:00
int mlstwh = whandle();
HeaderView->Use(AA, &msg);
HeaderView->Paint();
wactiv_(mlstwh);
}
2001-05-09 20:45:13 +00:00
if(CFG->switches.get(msglistviewsubj)) {
// Reload message if not sure that just reread
if(not AA->Msglistheader()) {
t = list[index];
if(AA->Msglistfast()) {
AA->LoadHdr(&msg, t.msgno);
}
else {
AA->LoadMsg(&msg, t.msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar));
}
}
2000-02-25 11:04:07 +00:00
wtitle(msg.re, TCENTER|TBOTTOM, tattr);
2001-05-09 20:45:13 +00:00
}
2000-02-25 11:04:07 +00:00
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);
}
// ------------------------------------------------------------------
2005-10-20 21:41:32 +00:00
void GThreadlist::GenTree(char* buf, int idx, uint32_t maxlev) {
2000-02-25 11:04:07 +00:00
2001-01-27 11:52:13 +00:00
#ifdef KOI8
static char graph[4]="<EFBFBD><EFBFBD><EFBFBD>";
#else
static char graph_ibmpc[4]="<EFBFBD><EFBFBD><EFBFBD>";
2001-02-19 22:53:24 +00:00
static char graph[4]="";
2001-01-27 11:52:13 +00:00
if(graph[0] == NUL) {
int table = LoadCharset(NULL, NULL, 1);
2001-10-07 08:24:26 +00:00
int level = LoadCharset(get_dos_charset(CFG->xlatlocalset), CFG->xlatlocalset);
2001-01-27 11:52:13 +00:00
XlatStr(graph, graph_ibmpc, level, CharTable);
if(table == -1)
LoadCharset(CFG->xlatimport, CFG->xlatlocalset);
else
LoadCharset(CFG->xlatcharset[table].imp, CFG->xlatcharset[table].exp);
}
#endif
2001-10-07 14:49:47 +00:00
ThreadEntry te = list[idx];
2000-02-25 11:04:07 +00:00
2001-10-07 14:49:47 +00:00
buf[0] = ' ';
2000-02-25 11:04:07 +00:00
2001-10-07 14:49:47 +00:00
if(te.level == 0) {
buf[1] = NUL;
return;
2000-02-25 11:04:07 +00:00
}
2001-10-07 14:49:47 +00:00
if(te.level < maxlev) {
buf[(te.level-1)*2+1] = (te.replynext) ? graph[0] : graph[1];
buf[(te.level-1)*2+2] = ' ';
buf[(te.level-1)*2+3] = NUL;
2000-02-25 11:04:07 +00:00
}
2001-10-07 14:49:47 +00:00
while(te.replyto) {
te = list[te.replytoindex];
if((te.level != 0) and (te.level < maxlev)) {
buf[(te.level-1)*2+1] = (te.replynext) ? graph[2] : ' ';
buf[(te.level-1)*2+2] = ' ';
}
2000-02-25 11:04:07 +00:00
}
2001-10-07 14:49:47 +00:00
buf[maxlev*2+1] = NUL;
2000-02-25 11:04:07 +00:00
}
// ------------------------------------------------------------------
void GThreadlist::print_line(uint idx, uint pos, bool isbar) {
char buf[256];
2005-10-20 21:41:32 +00:00
uint32_t maxlev = (100*window.width()+h_offset+1)/2;
2005-10-11 01:54:40 +00:00
#if defined(__USE_ALLOCA__)
char *buf2 = (char*)alloca(maxlev*2+2);
#else
2001-10-07 14:49:47 +00:00
__extension__ char buf2[maxlev*2+2];
#endif
2000-02-25 11:04:07 +00:00
int attrh, attrw;
uint tdlen;
t = list[idx];
tdlen = xlen - ((AA->Msglistdate() == MSGLISTDATE_NONE) ? 8 : 18);
2001-05-09 20:45:13 +00:00
if(AA->Msglistfast()) {
AA->LoadHdr(&msg, t.msgno);
}
else {
AA->LoadMsg(&msg, t.msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar));
}
2000-02-25 11:04:07 +00:00
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;
}
2001-10-07 14:49:47 +00:00
GenTree(buf2, idx, maxlev);
2001-04-15 19:24:44 +00:00
#if defined(__UNIX__) && !defined(__USE_NCURSES__)
2000-02-25 11:04:07 +00:00
gvid_boxcvt(buf2);
#endif
2000-02-25 11:04:07 +00:00
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;
}
2005-10-27 19:49:46 +00:00
sprintf(buf, "%6lu %*c", long(CFG->switches.get(disprealmsgno) ? t.msgno : AA->Msgn.ToReln(t.msgno)), tdlen, ' ');
2000-02-25 11:04:07 +00:00
if(AA->Msglistdate() != MSGLISTDATE_NONE) {
char dbuf[11];
2005-10-20 21:10:42 +00:00
time32_t dt = 0;
2000-02-25 11:04:07 +00:00
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", ggmtime(&dt));
2000-02-25 11:04:07 +00:00
strcat(buf, dbuf);
}
strcat(buf, " ");
2000-02-25 11:04:07 +00:00
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(std::vector<Node>::iterator x = CFG->username.begin(); x != CFG->username.end(); x++)
2000-02-25 11:04:07 +00:00
if(strieql(msg.By(), x->name)) {
attr = attrh;
break;
}
if (CFG->replylinkfloat && isbar)
{
int l1 = strlen(buf2);
int l2 = strlen(msg.By());
if ((l1 + l2) > tdlen)
new_hoffset = (l1 + l2)-tdlen+1;
else
new_hoffset = 0;
}
2000-02-25 11:04:07 +00:00
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);
}
}
// ------------------------------------------------------------------
2005-10-20 21:41:32 +00:00
void GThreadlist::recursive_build(uint32_t msgn, uint32_t rn, uint32_t level) {
2000-02-25 11:04:07 +00:00
2005-10-20 21:41:32 +00:00
uint32_t oldmsgno = msg.msgno;
2000-02-25 11:04:07 +00:00
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;
2001-10-07 14:49:47 +00:00
t.level = level;
t.replytoindex = 0;
2000-02-25 11:04:07 +00:00
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, list_size = list.size();
2000-02-25 11:04:07 +00:00
bool found = false;
for(j=0; j<list_size; j++) {
2000-02-25 11:04:07 +00:00
if(list[j].msgno == t.replyto) {
2001-10-07 14:49:47 +00:00
t.replytoindex = j;
2000-02-25 11:04:07 +00:00
found = true;
break;
}
}
if(found or (list_size == 0))
2000-02-25 11:04:07 +00:00
list.push_back(t);
2001-10-07 14:49:47 +00:00
recursive_build(msg.link.first(), msg.link.list(0), level+1);
2000-02-25 11:04:07 +00:00
for(int n=0; n < msg.link.list_max()-1; n++) {
if(msg.link.list(n)) {
2001-10-07 14:49:47 +00:00
recursive_build(msg.link.list(n), msg.link.list(n+1), level+1);
2000-02-25 11:04:07 +00:00
} else
break;
}
AA->LoadHdr(&msg, oldmsgno);
}
}
// ------------------------------------------------------------------
void GThreadlist::BuildThreadIndex(dword msgn) {
w_info(LNG->Wait);
index = maximum_index = position = maximum_position = 0;
list.clear();
AA->LoadHdr(&msg, msgn);
2005-10-20 21:41:32 +00:00
uint32_t msgno = msg.link.to();
uint32_t prevmsgno = msgn;
2000-02-25 11:04:07 +00:00
// Search backwards
while(AA->Msgn.ToReln(msgno)) {
if(not AA->LoadHdr(&msg, msgno)) {
2000-02-25 11:04:07 +00:00
msg.link.to_set(0);
msgno = prevmsgno;
AA->LoadHdr(&msg, msgno);
break;
}
2000-02-25 11:04:07 +00:00
prevmsgno = msgno;
2000-02-25 11:04:07 +00:00
msgno = msg.link.to();
}
2001-10-07 14:49:47 +00:00
recursive_build(msg.msgno, 0, 0);
2000-02-25 11:04:07 +00:00
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;
new_hoffset = 0;
2000-02-25 11:04:07 +00:00
for(uint i = 0; i<list.size(); i++) {
if(list[i].msgno == msgn)
index = i;
}
}
// ------------------------------------------------------------------
bool GThreadlist::NextThread(bool next) {
2002-08-30 06:01:33 +00:00
uint m = AA->Msgn.ToReln(reader_msg->msgno);
for(m = m ? m-1 : 0;
next ? m < AA->Msgn.Count() : m!=-1;
2000-02-25 11:04:07 +00:00
next ? m++ : m--) {
dword msgn = AA->Msgn[m];
bool found = false;
for(uint i = 0; i<list.size(); i++) {
if(list[i].msgno == msgn) {
found = true;
break;
}
}
if(not found) {
reader_msg->msgno = 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);
2001-03-17 21:17:57 +00:00
// See if it's a listkey
2000-02-25 11:04:07 +00:00
kk = SearchKey(key, ListKey, ListKeys);
if(kk)
key = kk;
2001-03-17 21:17:57 +00:00
else {
// If not a listkey, see if it matches a readkey
2000-02-25 11:04:07 +00:00
if(not IsMacro(key, KT_M)) {
kk = SearchKey(key, ReadKey, ReadKeys);
if(kk)
key = kk;
}
2001-03-17 21:17:57 +00:00
}
2000-02-25 11:04:07 +00:00
}
switch(key) {
case KK_ListGotoPrev:
case KK_ListGotoNext:
NextThread((key == KK_ListGotoNext));
if (!CFG->replylinkshowalways && (list.size() <= 1))
2000-02-25 11:04:07 +00:00
return false;
center(CFG->displistcursor);
break;
2001-03-17 21:17:57 +00:00
case KK_ListGotoFirst:
key = Key_Home;
default_handle_key();
break;
case KK_ListGotoLast:
key = Key_End;
default_handle_key();
break;
2000-02-25 11:04:07 +00:00
case KK_ListAskExit:
{
GMenuQuit MenuQuit;
2005-10-22 02:45:18 +00:00
aborted = gkbd.quitall = make_bool(MenuQuit.Run());
if(gkbd.quitall)
return false;
2000-02-25 11:04:07 +00:00
}
break;
case KK_ListQuitNow:
gkbd.quitall = true;
///////////////// Drop Through
case KK_ListAbort:
aborted = true;
///////////////// Drop Through
case KK_ListSelect:
return false;
case KK_ListToggleMark:
{
2005-10-20 21:41:32 +00:00
uint32_t temp = AA->Mark.Find(list[index].msgno);
2000-02-25 11:04:07 +00:00
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;
}
2001-03-17 21:17:57 +00:00
return false;
2000-02-25 11:04:07 +00:00
}
}
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(CFG->replylinkshowalways || (list.size() > 1))
2000-02-25 11:04:07 +00:00
run_picker();
2001-03-17 21:17:57 +00:00
else {
2000-02-25 11:04:07 +00:00
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();
}
// ------------------------------------------------------------------