// ------------------------------------------------------------------ // 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$ // ------------------------------------------------------------------ // Advanced search functions. // ------------------------------------------------------------------ #include #include #include #include // ------------------------------------------------------------------ golded_search_manager::golded_search_manager() { } // ------------------------------------------------------------------ golded_search_manager::~golded_search_manager() { } // ------------------------------------------------------------------ inline void search_item_option(bool& a, const char* s) { if(s[1] == '^') a = not a; else a = s[1] != '\''; } // ------------------------------------------------------------------ const char* search_item_set(search_item& item, const char* s, int what) { bool flag = false; while(*s) { switch(*s) { case ')': search_item_option(item.where.from, s); search_item_option(item.where.to, s); search_item_option(item.where.subject, s); flag = true; break; case '(': search_item_option(item.where.body, s); search_item_option(item.where.tagline, s); search_item_option(item.where.tearline, s); search_item_option(item.where.origin, s); search_item_option(item.where.signature, s); search_item_option(item.where.kludges, s); flag = true; break; case '!': search_item_option(item.reverse, s); break; case '=': search_item_option(item.case_sensitive, s); break; case '<': search_item_option(item.where.from, s); flag = true; break; case '>': search_item_option(item.where.to, s); flag = true; break; case ':': search_item_option(item.where.subject, s); flag = true; break; case '#': search_item_option(item.where.body, s); flag = true; break; case '.': search_item_option(item.where.tagline, s); flag = true; break; case '_': search_item_option(item.where.tearline, s); flag = true; break; case '*': search_item_option(item.where.origin, s); flag = true; break; case '@': search_item_option(item.where.signature, s); flag = true; break; case '%': search_item_option(item.where.kludges, s); flag = true; break; case '?': s++; switch(g_tolower(*s)) { case 'r': item.type = gsearch::regex; break; case 'w': item.type = gsearch::wildcard; break; case 'p': item.type = gsearch::plain; break; case 'f': item.type = gsearch::fuzzy; if(isdigit(s[1])) { item.fuzzydegree = atoi(s+1); while(isdigit(s[1])) s++; } break; } break; case '^': case '\'': break; default: if (isspace(*s)) break; else goto lblLoopExit; } s++; } lblLoopExit: if (what && !flag) { if (what & GFIND_FROM) item.where.from = true; if (what & GFIND_TO) item.where.to = true; if (what & GFIND_SUBJECT) item.where.subject = true; if (what & GFIND_BODY) item.where.body = true; if (what & GFIND_TAGLINE) item.where.tagline = true; if (what & GFIND_TEARLINE) item.where.tearline = true; if (what & GFIND_ORIGIN) item.where.origin = true; if (what & GFIND_KLUDGES) item.where.kludges = true; if (what & GFIND_SIGNATURE) item.where.signature = true; } return s; } // ------------------------------------------------------------------ void golded_search_manager::prepare_from_string(const char* prompt, int what) { // Get defaults reverse = false; direction = DIR_NEXT; const char* p = prompt; if (*p == '-' or *p == '+') { direction = (*p == '-') ? DIR_PREV : DIR_NEXT; p++; } search_item default_item; p = search_item_set(default_item, p, what); search_item item = default_item; default_item.reverse = false; default_item.where.from = false; default_item.where.to = false; default_item.where.subject = false; default_item.where.body = false; default_item.where.tagline = false; default_item.where.tearline = false; default_item.where.origin = false; default_item.where.kludges = false; default_item.where.signature = false; char buf[256]; char* b = buf; bool item_complete = false; do { switch(*p) { // Logic AND case '&': item.logic = search_item::logic_and; item_complete = true; p++; break; // Logic OR case '|': item.logic = search_item::logic_or; item_complete = true; p++; break; // Get quoted string case '\"': case '\'': { char q = *p++; while(*p) { if(*p == q) { p++; break; } switch(*p) { case '\\': if(*(++p)) *b++ = *p++; break; default: *b++ = *p++; } } } break; // Get literal escaped character case '\\': if(*(++p)) *b++ = *p++; break; // Skip whitespace case ' ': p++; case NUL: break; default: *b++ = *p++; } if(item_complete or (*p == NUL)) { item_complete = false; *b = NUL; if(*buf != NUL) { item.pattern = buf; items.push_back(item); } if(*p == NUL) break; item = default_item; p = search_item_set(item, strskip_wht(p), what); b = buf; } } while(*p); } // ------------------------------------------------------------------ bool golded_search_manager::search(GMsg* msg, bool quick, bool shortcircuit) { std::vector::iterator item = items.begin(); bool exit = false; bool and_cycle = false; bool or_cycle = false; for(int i=0; ilogic == search_item::logic_and) { if(not and_cycle) { if(exit) return true; } else if(not exit) continue; and_cycle = true; } else { if(and_cycle) { and_cycle = (item->logic == search_item::logic_and); if(not exit) continue; } else { and_cycle = (item->logic == search_item::logic_and); if(exit) return true; } or_cycle = (item->logic == search_item::logic_or); } } int found = 0; if(item->where.from) { if(item->search(*msg->ifrom ? msg->ifrom : msg->By())) { msg->foundwhere |= GFIND_FROM; found++; if(quick) goto quick_found; } } if(item->where.to) { if(item->search(*msg->ito ? msg->ito : msg->to)) { msg->foundwhere |= GFIND_TO; found++; if(quick) goto quick_found; } else if(*msg->icc and item->search(msg->icc)) { msg->foundwhere |= GFIND_TO; found++; if(quick) goto quick_found; } else if(*msg->ibcc and item->search(msg->ibcc)) { msg->foundwhere |= GFIND_TO; found++; if(quick) goto quick_found; } } if(item->where.subject) { if(item->search(msg->re)) { msg->foundwhere |= GFIND_SUBJECT; found++; if(quick) goto quick_found; } } if(item->where.body or item->where.tagline or item->where.tearline or item->where.origin or item->where.signature or item->where.kludges) { Line* line = msg->lin; while(line) { uint type = line->type; bool search_this_line = false; if(item->where.body and not (type & (GLINE_TAGL|GLINE_TEAR|GLINE_ORIG|GLINE_SIGN|GLINE_KLUDGE))) search_this_line = true; if(item->where.tagline and (type & GLINE_TAGL)) search_this_line = true; if(item->where.tearline and (type & GLINE_TEAR)) search_this_line = true; if(item->where.origin and (type & GLINE_ORIG)) search_this_line = true; if(item->where.signature and (type & GLINE_SIGN)) search_this_line = true; if(item->where.kludges and (type & GLINE_KLUDGE)) search_this_line = true; if(search_this_line) { if(item->search(line->txt.c_str())) { line->type |= GLINE_HIGH; if(type & (GLINE_TAGL|GLINE_TEAR|GLINE_ORIG|GLINE_SIGN|GLINE_KLUDGE)) { if(type & GLINE_TAGL) msg->foundwhere |= GFIND_TAGLINE; else if(type & GLINE_TEAR) msg->foundwhere |= GFIND_TEARLINE; else if(type & GLINE_ORIG) msg->foundwhere |= GFIND_ORIGIN; else if(type & GLINE_SIGN) msg->foundwhere |= GFIND_SIGNATURE; else if(type & GLINE_KLUDGE) msg->foundwhere |= GFIND_KLUDGES; } else { msg->foundwhere |= GFIND_BODY; } found++; if(quick) goto quick_found; } } line = line->next; } } quick_found: if(item->reverse) found = not found; // Perform short-circuit logic analysis if(shortcircuit) { exit = make_bool(found); if(item == items.end()-1) return exit; } // else save success/failure as score else { item->score = found ? 1 : 0; } } if(not shortcircuit) { gevalhum logic; if(items.size()) { for(int i=0; irow; int scol = window.start_column + current->column; if((current->id < id_direction) and ((current->id % 3) == 2)) scol -= 20; GMnu m; m.Init(); m.SetColor(7, 7, 7, 112, 8); m.SetTitle(title, 14); m.SetBorder(0, 7); m.SetPos(srow, scol); m.SetMask(0); m.Begin(); for(int i=0; iid < id_direction) and ((current->id % 3) == 2))) { strbtrim(strcpy(current->buf, menu[m.FinalTag()].c_str()+1)); current->update(); } } } // ------------------------------------------------------------------ bool search_mgr_form::validate() { gstrarray menu; if(current->id >= id_direction) { switch(current->id) { case id_direction: menu.insert(menu.end(), "F Forward"); menu.insert(menu.end(), "B Backward "); select(menu, "Direction"); break; case id_messages: menu.insert(menu.end(), "N New"); menu.insert(menu.end(), "U Unread "); menu.insert(menu.end(), "A All"); select(menu, "Messages"); break; case id_action: menu.insert(menu.end(), "R Read"); menu.insert(menu.end(), "T Tag"); menu.insert(menu.end(), "D Delete "); menu.insert(menu.end(), "W Write"); menu.insert(menu.end(), "C Copy"); menu.insert(menu.end(), "M Move"); select(menu, "Action"); break; case id_areas: menu.insert(menu.end(), "C Current "); menu.insert(menu.end(), "A All"); menu.insert(menu.end(), "T Tagged"); select(menu, "Areas"); break; } } else if((current->id % 3) == 1) { menu.insert(menu.end(), "a and "); menu.insert(menu.end(), "o or"); select(menu, "Logic"); } else if((current->id % 3) == 2) { menu.insert(menu.end(), " Plain "); menu.insert(menu.end(), " Regex "); menu.insert(menu.end(), " Wildcard "); menu.insert(menu.end(), " Fuzzy "); menu.insert(menu.end(), " Success if not found "); menu.insert(menu.end(), " Case sensitive "); menu.insert(menu.end(), " Search \"from\" "); menu.insert(menu.end(), " Search \"to\" "); menu.insert(menu.end(), " Search \"subject\" "); menu.insert(menu.end(), " Search msg body "); menu.insert(menu.end(), " Search tagline "); menu.insert(menu.end(), " Search tearline "); menu.insert(menu.end(), " Search origin "); menu.insert(menu.end(), " Search signature "); menu.insert(menu.end(), " Search kludges "); select(menu, "Options"); } return true; } // ------------------------------------------------------------------ void AdvancedSearch(GMsg*, int&, int&) { int patterns = 9; int width = 77; int height = patterns+11; int widths[3] = { 55, 5, 7 }; int field_widths[3] = { 100, 5, 7 }; int border_type = BT_SINGLE; int title_color = YELLOW | _BLUE; int heading_color = YELLOW | _BLUE; int window_color = LGREY | _BLUE; int border_color = LBLUE | _BLUE; int edit_color = YELLOW | _BLUE; int idle_color = LGREY | _BLUE; int active_color = WHITE | _BLUE; int shadow_color = DGREY | _BLACK; widths[0] = width - 3*2 - 2 - 5 - 7 - 2; gwindow window; window.openxy(1, ((MAXCOL-width)/2), height, width, border_type, border_color, window_color); window.shadow(shadow_color); window.horizontal_line( 1, 0, width-2, border_type, border_color); window.horizontal_line(patterns+2, 0, width-2, border_type, border_color); window.vertical_line(0, widths[0]+2, patterns+3, border_type, border_color); window.vertical_line(0, widths[0]+widths[1]+5, patterns+3, border_type, border_color); window.title(" Advanced Search Manager ", title_color); window.prints(0, 1, heading_color, "Pattern"); window.prints(0, widths[0]+4, heading_color, "Logic"); window.prints(0, widths[0]+widths[1]+7, heading_color, "Options"); window.prints(patterns+3, 1, heading_color, "Direction : "); window.prints(patterns+4, 1, heading_color, "Messages : "); window.prints(patterns+5, 1, heading_color, "Action : "); window.prints(patterns+6, 1, heading_color, "Areas : "); window.prints(patterns+7, 1, heading_color, "Destination : "); window.prints(patterns+8, 1, heading_color, "Identifier : "); search_mgr_form iform(window); iform.setup(idle_color, active_color, edit_color, _box_table(border_type, 13), true); std::string buffers[9*3 + 6]; int i = 0; for(int r=0; r<9; r++) { int cs = 1; for(int c=0; c<3; c++,i++) { char z[80]; sprintf(z, "%i,%i", r+1, c+1); buffers[i] = z; iform.add_field(i, r+2, cs, widths[c], buffers[i], field_widths[c]); cs += widths[c] + 3; } } buffers[i+0] = "Forward"; buffers[i+1] = "New"; buffers[i+2] = "Read"; buffers[i+3] = "Current"; buffers[i+4] = "C:\\TEMP\\DUMPFILE.TXT"; buffers[i+5] = "Testing"; for(int y=0; y<6; y++,i++) iform.add_field(100+y, patterns+3+y, 15, width-15-3, buffers[i], width-15-3, gwinput::cvt_none, y>=4 ? gwinput::entry_conditional : gwinput::entry_noedit); iform.run(0); window.close(); } // ------------------------------------------------------------------