// ------------------------------------------------------------------ // 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$ // ------------------------------------------------------------------ // Reader secondary functions // ------------------------------------------------------------------ #include #include #include #include #include #define PROTOTYPES #include // ------------------------------------------------------------------ // Global data from GEREAD extern GMsg* reader_msg; extern bool reader_msglistfirst; // ------------------------------------------------------------------ void ChangeAttributes() { if(reader_msg->msgno) { // Reload if hexdumped if(AA->attr().hex()) { AA->attr().hex0(); AA->LoadMsg(reader_msg, reader_msg->msgno, CFG->dispmargin-(int)CFG->switches.get(disppagebar)); } GMsg* msg = (GMsg*)throw_malloc(sizeof(GMsg)); memcpy(msg, reader_msg, sizeof(GMsg)); AskAttributes(reader_msg); if(memcmp(msg, reader_msg, sizeof(GMsg))) { msg->charsetlevel = LoadCharset(CFG->xlatlocalset, msg->charset); DoKludges(MODE_CHANGE, reader_msg, GKLUD_FLAGS); reader_msg->LinesToText(); AA->SaveMsg(GMSG_UPDATE, reader_msg); } throw_free(msg); } } // ------------------------------------------------------------------ void DecMargin() { if(CFG->dispmargin > (MAXCOL/3)) CFG->dispmargin--; else { SayBibi(); reader_keyok = YES; } } // ------------------------------------------------------------------ void IncMargin() { if(CFG->dispmargin < MAXCOL) CFG->dispmargin++; else { SayBibi(); reader_keyok = YES; } } // ------------------------------------------------------------------ void ToggleMark() { uint tmp = AA->Mark.Find(reader_msg->msgno); if(tmp) AA->Mark.DelReln(tmp); else AA->Mark.Add(reader_msg->msgno); HeaderView->Use(AA, reader_msg); HeaderView->Paint(); reader_keyok = YES; } // ------------------------------------------------------------------ void ToggleBookMark() { if(AA->bookmark == reader_msg->msgno) AA->bookmark = 0; else AA->bookmark = reader_msg->msgno; HeaderView->Use(AA, reader_msg); HeaderView->Paint(); reader_keyok = YES; } // ------------------------------------------------------------------ void ToggleHiddKlud() { AA->ToggleViewhidden(); AA->ToggleViewkludge(); MsgLineReIndex(reader_msg); reader_topline = 0; reader_keyok = YES; } // ------------------------------------------------------------------ void ToggleKludge() { AA->ToggleViewkludge(); MsgLineReIndex(reader_msg); reader_topline = 0; reader_keyok = YES; } // ------------------------------------------------------------------ void ToggleHidden() { AA->ToggleViewhidden(); MsgLineReIndex(reader_msg); reader_topline = 0; reader_keyok = YES; } // ------------------------------------------------------------------ void ToggleStripHTML() { AA->ToggleStripHTML(); MsgLineReIndex(reader_msg); reader_topline = 0; } // ------------------------------------------------------------------ void ToggleQuote() { AA->ToggleViewquote(); MsgLineReIndex(reader_msg); reader_topline = 0; reader_keyok = YES; } // ------------------------------------------------------------------ void ToggleROT13() { if(AA->Msgn.Count()) { reader_msg->attr.rotX(); Rot13(reader_msg); reader_keyok = YES; } } // ------------------------------------------------------------------ void TogglePageBar() { CFG->switches.set(disppagebar, not CFG->switches.get(disppagebar)); } // ------------------------------------------------------------------ void ToggleRealMsgno() { CFG->switches.set(disprealmsgno, not CFG->switches.get(disprealmsgno)); HeaderView->Use(AA, reader_msg); HeaderView->Paint(); reader_keyok = YES; } // ------------------------------------------------------------------ void ToggleTwits() { gkey k; do { switch(AA->Twitmode()) { case TWIT_SHOW: AA->SetTwitmode(TWIT_BLANK); w_info(LNG->TwitBlanked); break; case TWIT_BLANK: AA->SetTwitmode(TWIT_SKIP); w_info(LNG->TwitSkipped); break; case TWIT_SKIP: AA->SetTwitmode(TWIT_IGNORE); w_info(LNG->TwitIgnoreSkip); break; case TWIT_IGNORE: AA->SetTwitmode(TWIT_KILL); w_info(LNG->TwitKilled); break; case TWIT_KILL: AA->SetTwitmode(TWIT_SHOW); w_info(LNG->TwitDisplayed); break; } k = waitkeyt(3000); } while(k and k != Key_Ent and k != Key_Esc); w_info(NULL); if(k == Key_Esc) AA->SetTwitmode(CFG->twitmode); else CFG->twitmode = AA->Twitmode(); } // ------------------------------------------------------------------ void ToggleStyles() { gkey k; int setting = AA->adat->usestylies + AA->adat->hidestylies*2; do { switch(setting) { case 2: case 0: w_info(LNG->StylecodesYes); setting = 1; break; case 1: w_info(LNG->StylecodesHide); setting = 3; break; case 3: w_info(LNG->StylecodesNo); setting = 0; break; } k = waitkeyt(3000); } while (k and k != Key_Ent and k != Key_Esc); w_info(NULL); if(k != Key_Esc) { AA->adat->usestylies = make_bool(setting & 1); AA->adat->hidestylies = make_bool(setting & 2); } } // ------------------------------------------------------------------ void GotoMsgno() { if(AA->Msgn.Count()) { // Set the active window int lastwh = whandle(); int inhdr = AA->Msglistheader() or not _in_msglist; if(reader_keycode < KK_Macro) if(gkbd.kbuf == NULL) kbput(reader_keycode); // Put back the key char buf[150]; char* ptr = buf; int list_max = reader_msg->link.list_max(); uint32_t* replies = (uint32_t*)throw_calloc(list_max+1, sizeof(uint32_t)); uint32_t replyto, replynext; if(CFG->switches.get(disprealmsgno)) { ptr += sprintf(ptr, " %-5.5s: %s %u", LNG->MsgReal, LNG->of, AA->Msgn.Count()); replyto = reader_msg->link.to(); replies[0] = reader_msg->link.first(); replynext = reader_msg->link.next(); for(int replyn=1; replynlink.list(replyn-1); } else { ptr += sprintf(ptr, " %-5.5s: %s %u", LNG->Msg, LNG->of, AA->Msgn.Count()); replyto = AA->Msgn.ToReln(reader_msg->link.to()); replies[0] = AA->Msgn.ToReln(reader_msg->link.first()); replynext = AA->Msgn.ToReln(reader_msg->link.next()); for(int replyn=1; replynMsgn.ToReln(reader_msg->link.list(replyn-1)); } if(replyto) ptr += sprintf(ptr, " -%u", replyto); for(int replyn=0,plus=0; replynwindow.activate_quick(); } else { wopen_(0, 0, 3, strlen(buf)+3, W_BHEAD, C_HEADB, C_HEADW); w_shadow(); wtitle(LNG->EnterMsgno, TCENTER, C_HEADT); } int wrow = inhdr ? 1 : 0; wprints(wrow, 0, C_HEADW, buf); *buf = NUL; gwindow iwindow(whandle()); std::string fbuf = buf; gwinput2 iform(iwindow); iform.setup(C_HEADW, C_HEADW, C_HEADI, _box_table(W_BHEAD, 13), true); iform.add_field(0, wrow, 8, 5, fbuf, 20, gwinput::cvt_none, gwinput::entry_new); vcurshow(); iform.run(H_InputMsgno); vcurhide(); if(iform.dropped) fbuf = ""; long active = AA->Msgn.Count(); long msgno = atol(fbuf.c_str()); if(CFG->switches.get(disprealmsgno)) if(msgno > 0) msgno = AA->Msgn.ToReln(msgno); if((msgno < 0) and ((active+msgno) > 0)) msgno = active + msgno; if(RngV(msgno, 1L, active)) AA->set_lastread((uint)msgno); if(inhdr) wactiv_(lastwh); else wclose(); throw_free(replies); } } // ------------------------------------------------------------------ void PrevArea() { AA->attr().hex0(); AA->Close(); int currarea = AL.AreaIdToNo(CurrArea); int testarea = currarea; while(testarea > 0) { testarea--; if(not AL[testarea]->isseparator()) { currarea = testarea; break; } } if(currarea == testarea) { AL.SetActiveAreaNo(currarea); OrigArea = CurrArea; } else HandleGEvent(EVTT_ENDOFMSGS); AA->Open(); AA->RandomizeData(); AA->SetBookmark(AA->lastread()); if (CFG->disppmfirst && AA->PMrk.Tags()) { AA->isreadpm = false; ToggleMarkRead(); } } // ------------------------------------------------------------------ void NextArea() { AA->attr().hex0(); AA->Close(); uint currarea = AL.AreaIdToNo(CurrArea); uint testarea = currarea; while(testarea < (AL.size()-1)) { testarea++; if(not AL[testarea]->isseparator()) { currarea = testarea; break; } } if(currarea == testarea) { AL.SetActiveAreaNo(currarea); OrigArea = CurrArea; } else HandleGEvent(EVTT_ENDOFMSGS); AA->Open(); AA->RandomizeData(); AA->SetBookmark(AA->lastread()); if (CFG->disppmfirst && AA->PMrk.Tags()) { AA->isreadpm = false; ToggleMarkRead(); } } // ------------------------------------------------------------------ void QuitNow() { AA->attr().hex0(); reader_finished = YES; reader_done = YES; } // ------------------------------------------------------------------ void ExitAsk() { AA->attr().hex0(); GMenuQuit MenuQuit; reader_done = reader_finished = MenuQuit.Run(); } // ------------------------------------------------------------------ void NewArea(bool jumpnext) { AA->attr().hex0(); if(AA->isopen()) AA->Close(); int newarea = CurrArea; if(jumpnext) { uint idx = AL.AreaIdToNo(CurrArea); uint oidx = idx; do { idx++; // Wrap around if(idx >= AL.size()) idx = 0; // Exit loop if no area with new mail found if(idx == oidx) { newarea = AreaPick(LNG->NewArea, 0, &newarea); if(newarea != -1) idx = AL.AreaIdToNo(newarea); break; } } while(AL.AreaNoToPtr(idx)->unread == 0); CurrArea = AL.AreaNoToId(idx); } else { newarea = AreaPick(LNG->NewArea, 0, &newarea); if(newarea != -1) CurrArea = newarea; } AL.Sort(); reader_done = YES; if(gkbd.quitall) QuitNow(); else { AL.SetActiveAreaId(CurrArea); OrigArea = CurrArea; strcpy(stecho, AA->echoid()); AA->RandomizeData(); if (AA->Msglistfirst() && (kbput(KK_ReadMessageList) != -1)) reader_msglistfirst = true; else reader_msglistfirst = false; } } // ------------------------------------------------------------------ void DosShell() { ShellToDos(getenv(GOLD_SHELL_ENV), LNG->DOS_Shell, LGREY_|_BLACK, YES); } // ------------------------------------------------------------------ void TouchNetscan(int popup) { gfile fp(AddPath(CFG->areapath, CFG->semaphore.netscan), "wb", CFG->sharemode); if (fp.isopen()) { if (popup) { w_infof(" %s ", CFG->semaphore.netscan); HandleGEvent(EVTT_JOBDONE); waitkeyt(10000); w_info(NULL); } } } // ------------------------------------------------------------------ int ExternUtil(GMsg *msg, const ExtUtil &extutil) { Path editorfile, tmpfile, buf; std::string cmdline = extutil.cmdline; int mode = (extutil.options & EXTUTIL_KEEPCTRL) ? MODE_SAVE : MODE_SAVENOCTRL; if(striinc("@tmpfile", cmdline.c_str())) { if( (*CFG->temppath == NUL ) or is_dir(CFG->temppath) ) { mktemp(strcpy(tmpfile, AddPath(CFG->temppath, "GDXXXXXX"))); SaveLines(mode, tmpfile, msg, 79); strcpy(buf, tmpfile); strchg(buf, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); strischg(cmdline, "@tmpfile", buf); } else { w_info(LNG->TMPinvalidpath); SayBibi(); waitkeyt(10000); w_info(""); return NO; } } else tmpfile[0] = NUL; strxcpy(editorfile, AddPath(CFG->goldpath, EDIT->File()), sizeof(Path)); SaveLines(mode, editorfile, msg, 79); strcpy(buf, editorfile); strchg(buf, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); strischg(cmdline, "@file", buf); strcpy(buf, CFG->goldpath); strchg(buf, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); strischg(cmdline, "@path", buf); TokenXlat(MODE_NEW, cmdline, msg, msg, CurrArea); int pauseval = 0; if(extutil.options & EXTUTIL_PAUSEONERROR) pauseval = -1; if(extutil.options & EXTUTIL_PAUSE) pauseval = 1; ShellToDos(cmdline.c_str(), "", extutil.options & EXTUTIL_CLS ? LGREY_|_BLACK : BLACK_|_BLACK, extutil.options & EXTUTIL_CURSOR, pauseval ); if(extutil.options & EXTUTIL_RELOAD) { if(not (extutil.options & EXTUTIL_KEEPCTRL)) { if (*msg->tearline or *msg->origin) { gfile fp(editorfile, "at"); if (fp.isopen()) { if (*msg->tearline) fp.Printf("--- %s\n", msg->tearline); if (*msg->origin) fp.Printf(" * Origin: %s\n", msg->origin); } } } bool hardlines = EDIT->HardLines(); EDIT->HardLines(false); LoadText(msg, editorfile); EDIT->HardLines(hardlines); if(not strstr(msg->txt, "\001CHRS:") and not strstr(msg->txt, "\001CHARSET:")) { // Prepend "@CHRS: XLATLOCALSET 2\n" to force proper encoding const char *charset = AA->Viewkludge() ? msg->charset : CFG->xlatlocalset; char *msg_txt_chrs = (char *)throw_malloc(strlen(msg->txt)+strlen(charset)+sizeof("\001CHRS: 2\r")+16); sprintf(msg_txt_chrs, "\001CHRS: %s 2\r%s", charset, msg->txt); throw_free(msg->txt); msg->txt = msg_txt_chrs; } // Ignore any kludge address found msg->TextToLines(CFG->dispmargin-(int)CFG->switches.get(disppagebar), false); if(AA->Viewkludge()) { // Try to convert to the original codepage char *inpcharset = msg->charset; int level = LoadCharset(CFG->xlatlocalset, IsQuotedPrintable(inpcharset) ? ExtractPlainCharset(inpcharset) : inpcharset); if(level) { // do recode char *msg_txt_chrs = (char *)throw_malloc(strlen(msg->txt)*3+16); XlatStr(msg_txt_chrs, msg->txt, level, CharTable); throw_free(msg->txt); msg->txt = (char *)throw_realloc(msg_txt_chrs, strlen(msg_txt_chrs)+16); } } msg->charsetlevel = LoadCharset(msg->charset, CFG->xlatlocalset); } if(extutil.options & EXTUTIL_WIPE) WipeFile(editorfile, 0); if(tmpfile[0] != NUL) WipeFile(tmpfile, 0); return YES; } // ------------------------------------------------------------------ int ExternUtil(GMsg *msg, uint32_t utilno) { std::vector::iterator it = CFG->externutil.begin(); std::vector::iterator end = CFG->externutil.end(); for (; it != end; it++) { if (it->utilno != utilno) continue; return ExternUtil(msg, *it); } SayBibi(); return YES; } // ------------------------------------------------------------------ void ExternUtilMenu(GMsg* msg) { static int startat = 0; static char cmdline[1024] = ""; gstrarray Listi; Listi.push_back(LNG->EnterCmdLine); std::vector::iterator it = CFG->externutil.begin(); std::vector::iterator end = CFG->externutil.end(); for (; it != end; it++) { char buf[100]; sprintf(buf, " %02d %.59s%s ", it->utilno, it->cmdline.c_str(), (it->cmdline.length() > 59) ? ">" : "" ); Listi.push_back(buf); } size_t n = MinV(Listi.size(), (MAXROW-10)); set_title(LNG->ExternUtil, TCENTER, C_ASKT); update_statusline(LNG->SelectExternUtil); whelppcat(H_ReadExternUtil); n = wpickstr(6, 0, 6+n+1, -1, W_BASK, C_ASKB, C_ASKW, C_ASKS, Listi, startat, title_shadow); whelpop(); if (n != -1) { if (n == 0) { if (edit_string(cmdline, sizeof(cmdline), LNG->ExecCmdLine, H_ReadExternUtil)) { ExtUtil extutil; extutil.utilno = 0; extutil.cmdline = cmdline; extutil.options = CFG->externoptions; reader_keyok = ExternUtil(msg, extutil); } } else { reader_keyok = ExternUtil(msg, CFG->externutil[n-1]); } } } // ------------------------------------------------------------------ static bool PeekURLCmp(const std::string &a, const std::string b) { return stricmp(a.c_str(), b.c_str()) < 0; } // ------------------------------------------------------------------ void ReadPeekURLs(GMsg* msg) { w_info(LNG->Wait); // Scan the current msg for urls int tline = reader_topline; if (CFG->peekurloptions & PEEK_FROMTOP) tline = 0; Line **lin = msg->line; std::vector urls; for (int n = tline; n < msg->lines; n++) { const char *ptr = lin[n]->txt.c_str(); while (*ptr) { const char *urlBegin = url_begin(ptr); if (urlBegin and not strneql(ptr, "mailto:", 7)) { const char *urlEnd = urlBegin + strcspn(urlBegin, " \t\"\'<>()[]"); if (ispunct(urlEnd[-1]) and (urlEnd[-1] != '/')) --urlEnd; if (urlBegin < urlEnd) { char* bufurl=(char*)throw_malloc(urlEnd - ptr + 3); bufurl[0] = ' '; strxcpy(bufurl + 1, ptr, (urlEnd - ptr) + 1); strcat(bufurl, " "); std::vector::iterator it = urls.begin(); std::vector::iterator end = urls.end(); for (; it != end; it++) { if (strieql(*it, bufurl)) break; } if (it == end) urls.push_back(bufurl); else throw_free(bufurl); ptr = urlEnd - 1; } } ptr++; } } w_info(NULL); if (not urls.empty()) { gstrarray Listi; std::vector::iterator it = urls.begin(); std::vector::iterator end = urls.end(); for (; it != end; it++) { Listi.push_back(*it); } // Sort list if requested if (CFG->peekurloptions & FREQ_SORT) std::sort(Listi.begin(), Listi.end(), PeekURLCmp); // Run the picker size_t n = MinV(urls.size(), (MAXROW-10)); set_title(LNG->PeekURLMenuTitle, TCENTER, C_ASKT); update_statusline(LNG->PeekURLStat); whelppcat(H_PeekURL); n = wpickstr(6, 0, 6 + n + 1, -1, W_BASK, C_ASKB, C_ASKW, C_ASKS, Listi, 0, title_shadow); whelpop(); if(n != -1) { std::vector::iterator it = CFG->urlhandler.begin(); std::vector::iterator end = CFG->urlhandler.end(); #if 0 // will be implemented later for (; it != end; it++) { if (it->scheme.match(Listi[n].c_str(), gregex::extended | gregex::icase)) break; } #else it = end; #endif if (it == end) it = CFG->urlhandler.begin(); std::string cmdline = it->handler.cmdline; std::string buf = "\"" + strtrim(strltrim(Listi[n])) + "\""; strischg(cmdline, "@url", buf.c_str()); buf = CFG->goldpath; strchg(buf, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); strischg(cmdline, "@path", buf.c_str()); TokenXlat(MODE_NEW, cmdline, msg, msg, CurrArea); int pauseval = 0; if (it->handler.options & EXTUTIL_PAUSEONERROR) pauseval = -1; if (it->handler.options & EXTUTIL_PAUSE) pauseval = 1; ShellToDos(cmdline.c_str(), "", it->handler.options & EXTUTIL_CLS ? LGREY_|_BLACK : BLACK_|_BLACK, it->handler.options & EXTUTIL_CURSOR, pauseval ); } } else { w_info(LNG->PeekInfoNoURLs); waitkeyt(10000); w_info(NULL); } } // ------------------------------------------------------------------ void UUDecode(GMsg* msg) { Path infile, outfile; bool ok = false; if( not ((*CFG->temppath == NUL ) or is_dir(CFG->temppath)) ) { w_info(LNG->TMPinvalidpath); SayBibi(); waitkeyt(10000); w_info(""); return; } if((*CFG->uudecodepath == NUL) or is_dir(CFG->uudecodepath)) { mktemp(strcpy(infile, AddPath(CFG->temppath, "GDXXXXXX"))); strcpy(outfile, CFG->uudecodepath); GMenuDomarks MenuDomarks; int source = AA->Mark.Count() ? MenuDomarks.Run(LNG->Decode) : WRITE_CURRENT; bool overwrite = true; if(source == WRITE_QUIT) return; bool old_quotespacing = CFG->switches.get(quotespacing); CFG->switches.set(quotespacing, false); if(source == WRITE_MARKED) { for(uint n=0; nMark.Count(); n++) { if(overwrite and n) overwrite = false; // Overwrite only the first time w_progress(MODE_UPDATE, C_INFOW, n+1, AA->Mark.Count(), LNG->Preparing); AA->LoadMsg(msg, AA->Mark[n], 79); SaveLines(overwrite ? MODE_WRITE : MODE_APPEND, infile, msg, 79); } if(AA->Mark.Count()) w_progress(MODE_QUIT, BLACK_|_BLACK, 0, 0, NULL); } else if(source == WRITE_CURRENT) { AA->LoadMsg(msg, msg->msgno, 79); SaveLines(MODE_WRITE, infile, msg, 79); } CFG->switches.set(quotespacing, old_quotespacing); uulist* item; int i, res; w_info(LNG->WaitUUdecoding); UUInitialize(); UUSetOption(UUOPT_SAVEPATH, 0, outfile); if((res = UULoadFile(infile, NULL, 0)) == UURET_OK) { for (i=0; (item=UUGetFileListItem(i)) != NULL; i++) { if ((item->state & UUFILE_OK) == 0) continue; if ((res = UUDecodeFile(item, NULL)) == UURET_OK) { ok = true; w_infof(LNG->CompletedUUdecode, item->filename); } } } UUCleanUp (); remove(infile); if(not ok) w_info(LNG->NotUUencoded); } else w_info(LNG->UUEinvalidpath); if(not ok) waitkeyt(10000); w_info(NULL); } // ------------------------------------------------------------------ void Make_Userlist(const char* userlist) { word* crclist; word crc, crcs=0; uint n, x; char userline[80], adrs[40]; GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); crclist = (word*)throw_calloc(AA->Msgn.Count()+1, sizeof(word)); gfile fp(userlist, "ab", CFG->sharemode); if (fp.isopen()) { w_progress(MODE_NEW, C_INFOW, 0, AA->Msgn.Count(), LNG->GenUserlist); for(n=AA->Msgn.Count(); n; n--) { update_statuslinef(LNG->ReadingMsg, "ST_READINGMSG", n, AA->Msgn.Count()); w_progress(MODE_UPDATE, C_INFOW, (AA->Msgn.Count()-n)+1, AA->Msgn.Count(), NULL); AA->LoadMsg(msg, AA->Msgn.CvtReln(n), CFG->dispmargin); crc = strCrc16(msg->by, false); for(x=0; x= crcs) { crclist[crcs++] = crc; strrevname(userline, msg->by); msg->orig.make_string(adrs); fp.Printf("%-36.36s%24.24s\r\n", userline, adrs); } } throw_free(crclist); w_progress(MODE_QUIT, BLACK_|_BLACK, 0, 0, NULL); } ResetMsg(msg); throw_free(msg); } // ------------------------------------------------------------------ void MakeUserList() { if(AA->Msgn.Count()) { uint temp = AA->lastread(); if(not edit_pathname(CFG->userlistfile, sizeof(Path), LNG->UserlistName, 0)) return; Make_Userlist(AddPath(CFG->goldpath, CFG->userlistfile)); AA->set_lastread(temp); } } // ------------------------------------------------------------------ void TouchSemaphore() { Path file; *file = NUL; if(edit_string(file, sizeof(Path), LNG->TouchSemaphore, 0)) TouchFile(file); } // ------------------------------------------------------------------ void make_pathreport(const char* reportfile) { gfile fp(reportfile, "wt"); if (fp.isopen()) { std::string path; ftn_addr address; std::vector alist; GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg)); w_progress(MODE_NEW, C_INFOW, 0, AA->Msgn.Count(), "Generating PATH report"); for(int n=AA->Msgn.Count(); n>=AA->lastread(); n--) { update_statuslinef(LNG->ReadingMsg, "ST_READINGMSG", n, AA->Msgn.Count()); w_progress(MODE_UPDATE, C_INFOW, n, AA->Msgn.Count(), NULL); AA->LoadMsg(msg, AA->Msgn.CvtReln(n), CFG->dispmargin-(int)CFG->switches.get(disppagebar)); address = msg->orig; int x; for(x=0; x= alist.size()) { alist.push_back(address); INam buf; strcpy(buf, msg->By()); strchg(buf, ' ', '_'); std::string temp; fp.Printf("%s %s ", buf, address.make_string(temp).c_str()); path = ""; Line* line = msg->lin; while(line) { if(line->kludge == GKLUD_PATH) path += line->txt.c_str() + 6; line = line->next; } if(path.length()) { gstrarray links; tokenize(links, path.c_str(), " "); for(int i=0; iMsgn.Count()) { uint temp = AA->lastread(); if(not edit_pathname(CFG->pathreportfile, sizeof(Path), LNG->Pathreport, 0)) return; make_pathreport(AddPath(CFG->goldpath, CFG->pathreportfile)); AA->set_lastread(temp); } } // ------------------------------------------------------------------