/* * 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 #include #include #include #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; }