// ------------------------------------------------------------------ // 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 #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 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 = CFG->usestylies + CFG->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) { CFG->usestylies = (setting & 1) ? true : false; CFG->hidestylies = (setting & 2) ? true : false; } } // ------------------------------------------------------------------ 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(); ulong* replies = (ulong*)throw_calloc(list_max+1, sizeof(ulong)); ulong 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, " -%lu", 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(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(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); reader_msglistfirst = true; } } } // ------------------------------------------------------------------ void DosShell() { ShellToDos(getenv(GOLD_SHELL_ENV), LNG->DOS_Shell, LGREY|_BLACK, YES); } // ------------------------------------------------------------------ void TouchNetscan(int popup) { FILE* fp = fsopen(AddPath(CFG->areapath, CFG->semaphore.netscan), "wb", CFG->sharemode); if(fp) { fclose(fp); if(popup) { w_infof(" %s ", CFG->semaphore.netscan); HandleGEvent(EVTT_JOBDONE); waitkeyt(10000); w_info(NULL); } } } // ------------------------------------------------------------------ int ExternUtil(GMsg *msg, ExtUtil *extutil) { Path editorfile, tmpfile, buf; strxcpy(editorfile, AddPath(CFG->goldpath, EDIT->File()), sizeof(Path)); char cmdline[1024]; strxcpy(cmdline, extutil->cmdline, sizeof(cmdline)); int mode = (extutil->options & EXTUTIL_KEEPCTRL) ? MODE_SAVE : MODE_SAVENOCTRL; SaveLines(mode, editorfile, msg, 79); strcpy(buf, editorfile); strchg(buf, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); strischg(cmdline, "@file", buf); if(striinc("@tmpfile", cmdline)) { 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 tmpfile[0] = NUL; 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, "", extutil->options & EXTUTIL_CLS ? LGREY|_BLACK : 0, extutil->options & EXTUTIL_CURSOR, pauseval ); if(extutil->options & EXTUTIL_RELOAD) { if(not (extutil->options & EXTUTIL_KEEPCTRL)) { if(*msg->tearline or *msg->origin) { gfile fp; fp.fopen(editorfile, "at"); if(fp.isopen()) { if(*msg->tearline) fp.printf("--- %s\n", msg->tearline); if(*msg->origin) fp.printf(" * Origin: %s\n", msg->origin); fp.fclose(); } } } int hardlines = EDIT->HardLines(); EDIT->HardLines(false); LoadText(msg, editorfile); EDIT->HardLines(hardlines); // Prepend "@CHRS: XLATLOCALSET 2\n" to force proper encoding if(not AA->Viewkludge()) { char *msg_txt_chrs = (char *)throw_malloc(strlen(msg->txt)+strlen(CFG->xlatlocalset)+sizeof("\001CHRS: 2\r")+16); sprintf(msg_txt_chrs, "\001CHRS: %s 2\r%s", CFG->xlatlocalset, 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(extutil->options & EXTUTIL_WIPE) WipeFile(editorfile, 0); if(tmpfile[0] != NUL) WipeFile(tmpfile, 0); reader_keyok = true; return YES; } // ------------------------------------------------------------------ int ExternUtil(GMsg *msg, int utilno) { std::vector::iterator extutil = CFG->externutil.begin(); for(int utlno=0; extutil != CFG->externutil.end(); utlno++, extutil++) { if(extutil->utilno == utilno) { return ExternUtil(msg, &(*extutil)); } } SayBibi(); return YES; } // ------------------------------------------------------------------ void ExternUtilMenu(GMsg* msg) { int n; std::vector::iterator i; static int startat = 0; char** Listi; char buf[100]; static char cmdline[1024] = ""; Listi = (char**)throw_calloc(CFG->externutil.size()+2, sizeof(char*)); Listi[0] = throw_strdup(LNG->EnterCmdLine); for(i = CFG->externutil.begin(), n=1; i != CFG->externutil.end(); n++, i++) { sprintf(buf, " %02d %.59s%s ", i->utilno, i->cmdline, strlen(i->cmdline) > 59 ? ">" : "" ); Listi[n] = throw_strdup(buf); } n = MinV(n, (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; strxcpy(extutil.cmdline, cmdline, sizeof(extutil.cmdline)); extutil.options = CFG->externoptions; ExternUtil(msg, &extutil); } } else { ExternUtil(msg, &CFG->externutil[n-1]); } } for(n=CFG->externutil.size()+1; n; n--) throw_free(Listi[n-1]); throw_free(Listi); } // ------------------------------------------------------------------ static int PeekURLCmp(const char** a, const char** b) { return stricmp(*a, *b); } // ------------------------------------------------------------------ void ReadPeekURLs(GMsg* msg) { Line **lin = msg->line; const char *ptr, *end, *begin; char buf[256]; std::vector urls; std::vector::iterator i; int n; w_info(LNG->Wait); // Scan the current msg for urls int tline = reader_topline; if(CFG->peekurloptions & PEEK_FROMTOP) tline = 0; for(n=tline; nlines; n++) { ptr = lin[n]->txt.c_str(); while(*ptr) { if(((begin = url_begin(ptr)) != NULL) and not strneql(ptr, "mailto:", 7)) { end = begin+strcspn(begin, " \t\"\'<>()[]"); if(ispunct(end[-1]) and (end[-1] != '/')) --end; if(begin < end) { buf[0] = ' '; strxcpy(buf+1, ptr, MinV((long)((end-ptr)+1), (long)(MAXCOL-2-2-2))); strcat(buf, " "); for(i = urls.begin(); i != urls.end(); i++) if(strieql(*i, buf)) break; if(i == urls.end()) urls.push_back(throw_strdup(buf)); ptr = end-1; } } ptr++; } } w_info(NULL); if(not urls.empty()) { char** Listi = (char**)throw_calloc(urls.size()+1, sizeof(char*)); for(n = 0, i = urls.begin(); i != urls.end(); i++, n++) Listi[n] = *i; // Sort list if requested if(CFG->peekurloptions & FREQ_SORT) qsort(Listi, urls.size(), sizeof(char*), (StdCmpCP)PeekURLCmp); // Run the picker n = MinV((int)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) { char cmdline[1024]; strxcpy(cmdline, CFG->urlhandler.cmdline, sizeof(cmdline)); strxmerge(buf, sizeof(buf), "\"", strtrim(strltrim(Listi[n])), "\"", NULL); strischg(cmdline, "@url", buf); strxcpy(buf, CFG->goldpath, sizeof(buf)); strchg(buf, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR); strischg(cmdline, "@path", buf); TokenXlat(MODE_NEW, cmdline, msg, msg, CurrArea); int pauseval = 0; if(CFG->urlhandler.options & EXTUTIL_PAUSEONERROR) pauseval = -1; if(CFG->urlhandler.options & EXTUTIL_PAUSE) pauseval = 1; ShellToDos(cmdline, "", CFG->urlhandler.options & EXTUTIL_CLS ? LGREY|_BLACK : 0, CFG->urlhandler.options & EXTUTIL_CURSOR, pauseval ); } for(n = 0, i = urls.begin(); i != urls.end(); i++, n++) throw_free(Listi[n]); throw_free(Listi); } else { w_info(LNG->PeekInfoNoURLs); waitkeyt(10000); w_info(NULL); } } // ------------------------------------------------------------------ void UUDecode(GMsg* msg) { Path infile, outfile; bool ok = false; 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, 0, 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) { FILE* fp; 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)); fp = fsopen(userlist, "ab", CFG->sharemode); if(fp) { w_progress(MODE_NEW, C_INFOW, 0, AA->Msgn.Count(), LNG->GenUserlist); for(n=AA->Msgn.Count(); n; n--) { update_statuslinef(LNG->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); fprintf(fp, "%-36.36s%24.24s\r\n", userline, adrs); } } throw_free(crclist); w_progress(MODE_QUIT, 0, 0, 0, NULL); fclose(fp); } 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; fp.fopen(reportfile, "wt"); if(fp) { 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, 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); } } // ------------------------------------------------------------------