/*
* AREAS.C
*
* Written by jim nutt, John Dennis and released into the public domain
* by John Dennis in 1994.
*
* This file contains the routines to select one of the areas specified
* in the config files. It pops up a list with all the areas and lets
* the user choose.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include "addr.h"
#include "nedit.h"
#include "msged.h"
#include "winsys.h"
#include "menu.h"
#include "main.h"
#include "misc.h"
#include "memextra.h"
#include "specch.h"
#include "keys.h"
#include "unused.h"
#include "help.h"
#include "version.h"
#include "strextra.h"
#include "areas.h"
#include "group.h"
char **alist = NULL;
char **alist2 = NULL;
static int AreaBox(char **Itms, int y1, int real_y2, int len, int def, WND * hPrev, WND * hWnd, int Sel, int Norm, int indent);
void BuildList(char ***lst)
{
int i;
AREA *a;
char line[181];
unsigned long unread, last;
int areano;
*lst = xcalloc(SW->groupareas + 2 ,sizeof(char *));
for (i = 0; i < SW->groupareas; i++)
{
areano = group_getareano(i);
if (areano>=0)
{
a = arealist + areano;
memset(line, ' ', sizeof line);
if (a->scanned)
{
last = a->lastread;
if (last > a->messages)
{
last = a->messages;
}
unread = a->messages - a->lastread;
if (unread > a->messages)
{
unread = a->messages;
}
/* F_ALTERNATE for SC14 is set in SelShowItem */
sprintf(line, "%c%-*.*s", unread ? (SC14) : ' ',
maxx - 25, maxx - 25, a->description);
line[strlen(line)] = ' ';
sprintf(line + maxx - 23, "%6lu%6lu%6lu",
a->messages, unread, last);
}
else
{
sprintf(line, " %-*.*s", maxx - 25, maxx - 25, a->description);
line[strlen(line)] = ' ';
sprintf(line + maxx - 19, " - - -");
}
}
else
{
memset(line, '=', sizeof line);
sprintf(line + 2, " Group: %s ", group_getname(-areano));
line[strlen(line)]='=';
line[sizeof(line) - 1] = '\0';
}
(*lst)[i] = xstrdup(line);
}
(*lst)[i] = NULL;
}
static void SelShowItem(char *text, int y, int len, int Attr, int indent)
{
char line[256];
memset(line, ' ', sizeof(line));
if (strlen(text) + indent > sizeof(line) - 1)
{
strcpy(line,"<--- internal buffer overflow --->");
}
strcpy(line + indent, text);
line[sizeof(line)-1] = 0;
if (indent)
{
WndPutsn(1, y, indent, Attr, line);
}
WndPutsn(1 + indent, y, 1, Attr | F_ALTERNATE, line + indent);
if (len > (indent + 1))
{
WndPutsn(2 + indent, y, len - (indent + 1), Attr, line+indent+1);
}
}
static void SelShowPage(char **text, int top, int bot, int len, int pos, int Attr, int indent)
{
int i, y;
y = top;
for (i = pos; text[i] != NULL; i++)
{
if (y > bot)
{
break;
}
SelShowItem(text[i], y++, len, Attr, indent);
}
if (y <= bot)
{
while (y <= bot)
{
SelShowItem(" ", y++, len, Attr, indent);
}
}
}
static void CalcDef(int max, int cur, int *top, int miny, int maxy, int *y)
{
int dif;
unused(cur);
dif = (maxy - 1) - miny;
if ((max - 1) - *top < dif && max > dif)
{
*y = maxy;
*top = (max - 1) - dif;
}
}
static void setup_areabox_coordinates(int *currItem, int *curY,
int *Top, int *y2, int *page,
int y1, int real_y2, int itemCnt)
{
*y2=min(real_y2, itemCnt);
*page = *y2 - y1;
*curY = y1;
*Top = *currItem;
if (*currItem + y1 < y1)
{
*curY = y1 + *currItem;
*Top = 0;
}
else
{
if ((itemCnt - *currItem) <= (*y2 - y1))
{
(*Top) -= ((*y2 - y1 + 1) - (itemCnt - *Top));
*curY = y1 + (*currItem - *Top);
if (*Top < 0)
{
*Top = 0;
(*curY)--;
}
}
}
}
static int AreaBoxCurItem;
static int AreaBox(char **Itms, int y1, int real_y2, int len, int def,
WND * hPrev, WND * hWnd, int Sel, int Norm, int indent)
{
EVT e;
char find[30];
int itemCnt, Stuff, done, curY, Msg, currItem, Top, page, i, y2;
int real_areano;
itemCnt = 0;
Stuff = 0;
for (i = 0; Itms[i] != NULL; i++)
{
itemCnt++;
}
currItem = def;
setup_areabox_coordinates(&currItem, &curY, &Top, &y2, &page,
y1, real_y2, itemCnt);
done = 0;
TTBeginOutput();
SelShowPage(Itms, y1, y2, len, Top, Norm, indent);
SelShowItem(Itms[currItem], curY, len, Sel, indent);
TTEndOutput();
TTClearQue(); /* clear input queue */
memset(find, '\0', sizeof find);
while (!done)
{
if (!*find)
{
WndCurr(hPrev);
WndClear(16, 0, maxx - 36, 0, cm[MN_NTXT]);
WndWriteStr(0, 0, cm[MN_NTXT], ">>Pick New Area:");
WndCurr(hWnd);
}
if (!Stuff)
{
Msg = MnuGetMsg(&e, hWnd->wid);
}
else
{
e.msgtype = WND_WM_CHAR;
Msg = Stuff;
Stuff = 0;
}
switch (e.msgtype)
{
case WND_WM_RESIZE:
maxx = term.NCol;
maxy = term.NRow;
AreaBoxCurItem = currItem;
return -2; /* leave the list so it can be rebuilt with
the proper window dimensions */
case WND_WM_MOUSE:
switch (Msg)
{
case RMOU_CLCK:
case MOU_RBTUP:
return -1;
case LMOU_RPT:
case MOU_LBTDN:
case LMOU_CLCK:
{
int x, y;
WndGetRel(e.x, e.y, &x, &y);
if (y >= y1 && y <= y2) /* in window */
{
Stuff = 0;
if (x >= 0 && x < len)
{
if (y == curY)
{
if (Msg == LMOU_CLCK || Msg == MOU_LBTUP)
{
if (group_getareano(currItem) >= 0)
return currItem;
}
else
{
continue;
}
}
SelShowItem(Itms[currItem], curY, len, Norm, indent);
if (y > curY)
{
currItem += y - curY;
}
else
{
currItem -= curY - y;
}
curY = y;
SelShowItem(Itms[currItem], curY, len, Sel, indent);
if (Msg == LMOU_CLCK || Msg == MOU_LBTUP)
{
if (group_getareano(currItem) >= 0)
return currItem;
}
}
}
else
{
if (Msg != LMOU_CLCK)
{
if (y < y1)
{
Stuff = Key_Up;
}
else
{
Stuff = Key_Dwn;
}
}
}
}
memset(find, '\0', sizeof find);
break;
default:
break;
}
break;
case WND_WM_CHAR:
switch (Msg)
{
case Key_Home:
if (!currItem)
{
break;
}
TTBeginOutput();
SelShowItem(Itms[currItem], curY, len, Norm, indent);
currItem = 0;
Top = 0;
curY = y1;
SelShowPage(Itms, y1, y2, len, Top, Norm, indent);
SelShowItem(Itms[currItem], curY, len, Sel, indent);
TTEndOutput();
memset(find, '\0', sizeof find);
break;
case Key_A_H:
case Key_F1:
if (ST->helpfile != NULL)
{
DoHelp(3);
}
break;
case Key_End:
if (currItem == itemCnt - 1)
{
break;
}
TTBeginOutput();
SelShowItem(Itms[currItem], curY, len, Norm, indent);
currItem = itemCnt - 1;
while (currItem && currItem >= (itemCnt - page))
{
currItem--;
}
Top = currItem;
currItem = itemCnt - 1;
curY = currItem - Top + y1;
CalcDef(itemCnt, currItem, &Top, y1, y2, &curY);
SelShowPage(Itms, y1, y2, len, Top, Norm, indent);
SelShowItem(Itms[currItem], curY, len, Sel, indent);
TTEndOutput();
memset(find, '\0', sizeof find);
break;
case Key_Dwn:
if (currItem == itemCnt - 1)
{
break;
}
SelShowItem(Itms[currItem], curY, len, Norm, indent);
currItem++;
if (curY == y2)
{
WndScroll(1, y1, len, y2, 1);
Top++;
}
else
{
curY++;
}
SelShowItem(Itms[currItem], curY, len, Sel, indent);
memset(find, '\0', sizeof find);
break;
case Key_Up:
if (!currItem)
{
break;
}
SelShowItem(Itms[currItem], curY, len, Norm, indent);
currItem--;
if (curY == y1)
{
WndScroll(1, y1, len, y2, 0);
if (Top)
{
Top--;
}
}
else
{
curY--;
}
SelShowItem(Itms[currItem], curY, len, Sel, indent);
memset(find, '\0', sizeof find);
break;
case Key_PgUp:
if (!currItem)
{
break;
}
TTBeginOutput();
SelShowItem(Itms[currItem], curY, len, Norm, indent);
if ((currItem -= page) < 0)
{
currItem = 0;
}
Top = currItem;
curY = y1;
SelShowPage(Itms, y1, y2, len, Top, Norm, indent);
SelShowItem(Itms[currItem], curY, len, Sel, indent);
TTEndOutput();
memset(find, '\0', sizeof find);
break;
case Key_PgDn:
if (currItem == itemCnt - 1)
{
break;
}
TTBeginOutput();
SelShowItem(Itms[currItem], curY, len, Norm, indent);
Top = currItem;
if ((currItem += page) > itemCnt - 1)
{
currItem = itemCnt - 1;
if (currItem > page)
{
Top = currItem - page;
}
else
{
Top = 0;
}
}
curY = currItem - Top + y1;
CalcDef(itemCnt, currItem, &Top, y1, y2, &curY);
SelShowPage(Itms, y1, y2, len, Top, Norm, indent);
SelShowItem(Itms[currItem], curY, len, Sel, indent);
TTEndOutput();
memset(find, '\0', sizeof find);
break;
case Key_Ent:
case Key_Rgt:
if (group_getareano(currItem) >= 0)
{
size_t i;
i = (size_t) (((char *)(strchr(Itms[currItem] + 1, ' '))) - Itms[currItem]);
i--;
if (i > 28)
{
i = 28;
}
strncpy(find, Itms[currItem] + 1, i);
*(find + i) = '\0';
strupr(find);
WndCurr(hPrev);
WndWriteStr(17, 0, cm[MN_NTXT], find);
WndCurr(hWnd);
return currItem;
}
break;
case Key_Esc:
if (SW->confirmations)
{
if (confirm("Exit " PROG "?"))
{
return -1;
}
}
else
{
return -1;
}
memset(find, '\0', sizeof find);
break;
case Key_A_X:
return -1;
case '*':
case '#':
case Key_A_S:
case Key_A_T:
arealist_area_scan(Msg == '*' || Msg == Key_A_T);
for (i = 0; i < SW->groupareas; i++)
{
xfree(alist[i]);
}
xfree(alist);
BuildList(&alist);
Itms = alist;
TTBeginOutput();
SelShowPage(Itms, y1, y2, len, Top, Norm, indent);
SelShowItem(Itms[currItem], curY, len, Sel, indent);
TTEndOutput();
memset(find, '\0', sizeof find);
break;
case Key_A_1:
case Key_A_2:
case Key_A_3:
case Key_A_4:
case Key_A_5:
case Key_A_6:
case Key_A_7:
case Key_A_8:
case Key_A_9:
case Key_A_0:
case Key_A_G:
case Key_C_G:
real_areano = group_getareano(currItem);
i = 1;
switch(Msg)
{
case Key_C_G:
i = sel_group();
break;
case Key_A_1:
group_set_group(1);
break;
case Key_A_2:
group_set_group(2);
break;
case Key_A_3:
group_set_group(3);
break;
case Key_A_4:
group_set_group(4);
break;
case Key_A_5:
group_set_group(5);
break;
case Key_A_6:
group_set_group(6);
break;
case Key_A_7:
group_set_group(7);
break;
case Key_A_8:
group_set_group(8);
break;
case Key_A_9:
group_set_group(9);
break;
case Key_A_0:
group_set_group(0);
break;
}
if (i)
{
/* group has changed ... we have quite some work! */
/* find the new position of the currently selected group */
currItem = group_getareano(0) < 0 ? 1 : 0;
for (i = 0; i < SW->groupareas; i++)
{
if (group_getareano(i) == real_areano)
{
currItem = i;
break;
}
}
/* delete the old area list */
for (i = 0; alist[i] != NULL; i++)
{
xfree(alist[i]);
}
xfree(alist);
/* Build a new area list */
BuildList(&alist);
Itms = alist;
itemCnt = 0;
for (i = 0; Itms[i] != NULL; i++)
{
itemCnt++;
}
/* Do coordinate arithmetics */
y2 = min(maxy - 4, SW->groupareas);
setup_areabox_coordinates(&currItem, &curY, &Top,
&y2, &page,
y1, real_y2, itemCnt);
/* Redraw everything */
TTBeginOutput();
SelShowPage(Itms, y1, y2, len, Top, Norm, indent);
SelShowItem(Itms[currItem], curY, len, Sel, indent);
if (y2 < real_y2)
{
WndClear(1, y2 + 1, len, real_y2, Norm);
}
TTEndOutput();
memset(find, '\0', sizeof find);
}
break;
default:
if (Msg > 32 && Msg < 127)
{
if (strlen(find) >= 28)
{
break;
}
*(find + strlen(find)) = (char)toupper((char)Msg);
WndCurr(hPrev);
WndWriteStr(17, 0, cm[MN_NTXT], find);
WndCurr(hWnd);
i = currItem;
while (i < itemCnt)
{
if (SW->arealistexactmatch)
{
if (stristr(Itms[i] + 1, find) == Itms[i] + 1)
{
break;
}
}
else
{
if (stristr(Itms[i] + 1, find) != NULL)
{
break;
}
}
i++;
}
if (i == itemCnt)
{
for (i = 0; i < currItem; i++)
{
if (SW->arealistexactmatch)
{
if (stristr(Itms[i] + 1, find) == Itms[i] + 1)
{
break;
}
}
else
{
if (stristr(Itms[i] + 1, find) != NULL)
{
break;
}
}
}
if (i == currItem)
{
i = itemCnt;
}
}
if ((i != currItem) && (i != itemCnt))
{
SelShowItem(Itms[currItem], curY, len, Norm, indent);
currItem = i;
curY = y1;
Top = currItem;
if ((itemCnt - 1) - currItem < y2 - y1)
{
if (currItem > y2 - y1)
{
curY = y2;
Top = currItem - (y2 - y1);
}
else
{
curY = currItem + y1;
Top = 0;
}
}
SelShowPage(Itms, y1, y2, len, Top, Norm, indent);
SelShowItem(Itms[currItem], curY, len, Sel, indent);
}
}
else if (Msg == '\b' && *find)
{
*(find + strlen(find) - 1) = '\0';
WndCurr(hPrev);
WndClear(17 + strlen(find), 0, maxx - 36, 0, cm[CM_NINF]);
WndCurr(hWnd);
}
else
{
memset(find, '\0', sizeof find);
}
break;
}
break;
}
}
return -1;
}
int mainArea(void)
{
WND *hCurr, *hWnd;
int ret = -1, wid, dep, i;
do
{
msgederr = 0;
wid = maxx - 1;
dep = maxy - 2;
TTBeginOutput();
WndClearLine(0, cm[MN_NTXT]);
WndClearLine(maxy - 1, cm[MN_NTXT]);
hCurr = WndTop();
hWnd = WndOpen(0, 1, wid, dep, NBDR | NOSAVE, 0, cm[MN_BTXT]);
WndBox(0, 0, maxx - 1, maxy - 3, cm[MN_BTXT], SBDR);
WndWriteStr(3, 0, cm[LS_TTXT], "EchoID");
WndWriteStr(maxx - 19, 0, cm[LS_TTXT], "Msgs");
WndWriteStr(maxx - 12, 0, cm[LS_TTXT], "New");
WndWriteStr(maxx - 7, 0, cm[LS_TTXT], "Last");
TTEndOutput();
BuildList(&alist);
ret = AreaBox(alist, 1, dep - 2, wid - 1,
(ret == -2) ? AreaBoxCurItem : SW->grouparea,
hCurr, hWnd, cm[MN_STXT], cm[MN_NTXT], 1);
for (i = 0; alist[i] != NULL; i++)
{
xfree(alist[i]);
}
xfree(alist);
if (ret == -1)
{
msgederr = 1;
}
if (ret == -2)
{
/* returncode -2 means that the list should be restarted;
it did only exit because it had to be rebuild because
of a terminal window resize operation */
window_resized = 1;
}
WndClose(hWnd);
WndCurr(hCurr);
/* returncode -3 means rebuild because group has changed */
} while (ret == -2 || ret == -3);
return ret;
}
int selectarea(char *topMsg, int def)
{
WND *hCurr, *hWnd;
int ret, wid, dep, i;
msgederr = 0;
wid = maxx - 1;
dep = maxy - 2;
WndClearLine(0, cm[MN_NTXT]);
WndClearLine(maxy - 1, cm[MN_NTXT]);
hCurr = WndTop();
hWnd = WndOpen(0, 1, wid, dep, NBDR, 0, cm[MN_BTXT]);
WndBox(0, 0, maxx - 1, maxy - 3, cm[MN_BTXT], SBDR);
WndCurr(hCurr);
WndClear(0, 0, maxx - 36, 0, cm[CM_NINF]);
WndCurr(hWnd);
WndWriteStr(3, 0, cm[LS_TTXT], "EchoID");
WndWriteStr(maxx - 21, 0, cm[LS_TTXT], "Msgs");
WndWriteStr(maxx - 13, 0, cm[LS_TTXT], "New");
WndWriteStr(maxx - 7, 0, cm[LS_TTXT], "Last");
BuildList(&alist2);
do
{
ret = SelBox(alist2, 1, dep - 2, wid - 1, def, hCurr, hWnd,
cm[MN_STXT], cm[MN_NTXT], SELBOX_REPLYOTH, topMsg);
} while (ret != -1 && group_getareano(ret) < 0);
/* don't allow group separators
as selection */
for (i = 0; i < SW->groupareas; i++)
{
xfree(alist2[i]);
}
xfree(alist2);
if (ret < 0)
{
msgederr = 1;
}
WndClose(hWnd);
WndCurr(hCurr);
if (ret < 0)
{
return def;
}
return ret;
}
syntax highlighted by Code2HTML, v. 0.9.1