?? htsearch.cc
字號(hào):
/* * HT Editor * htsearch.cc * * Copyright (C) 1999-2002 Stefan Weyergraf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "atom.h"#include "cmds.h"#include "htctrl.h"#include "hthist.h"#include "htiobox.h"#include "keyb.h"#include "htsearch.h"#include "strtools.h"#include "htprocess.h"#include "snprintf.h"extern "C" {#include "evalx.h"}union search_pos { FileOfs offset; viewer_pos pos;};/* FIXME: get rid of global vars */uint lastsearchmodeid = 0;uint lastreplacemodeid = 0;typedef ht_search_request* (*create_request_func)(search_pos *ret_start, search_pos *ret_end, ht_view *form, ht_format_viewer *format, uint search_class);typedef Object* (*create_replace_context_func)(File *file, FileOfs ofs, FileOfs len, ht_view *form, FileOfs *return_repllen);struct ht_search_method { const char *name; uint search_class; // SC_* uint search_mode_mask; // SEARCHMODE_* uint histid; create_form_func create_form; create_request_func create_request; create_desc_func create_desc;};struct ht_replace_method { const char *name; uint histid; create_form_func create_form; create_replace_context_func create_replace_context; process_func replace_process;};#include <stdlib.h>#include <string.h>static bool test_str_to_ofs(FileOfs *ofs, byte *str, uint strlen, ht_format_viewer *format, const char *desc){#define TEST_STR_TO_OFS_MAXSTRLEN 128 if (strlen > TEST_STR_TO_OFS_MAXSTRLEN) { throw MsgfException("%s: expression too long (len %d, max %d)", desc, strlen, TEST_STR_TO_OFS_MAXSTRLEN); return false; } if (strlen > 0) { char s[TEST_STR_TO_OFS_MAXSTRLEN+1]; bin2str(s, str, strlen); if (!format->string_to_offset(s, ofs)) { throw MsgfException("%s: invalid expression: '%s'", desc, s); return false; } } return true;}static bool test_str_to_pos(viewer_pos *pos, byte *str, uint strlen, ht_format_viewer *format, const char *desc){#define TEST_STR_TO_POS_MAXSTRLEN 128 if (strlen > TEST_STR_TO_POS_MAXSTRLEN) { throw MsgfException("%s: expression too long (len %d, max %d)", desc, strlen, TEST_STR_TO_POS_MAXSTRLEN); } if (strlen > 0) { char s[TEST_STR_TO_POS_MAXSTRLEN+1]; bin2str(s, str, strlen); if (!format->string_to_pos(s, pos)) { throw MsgfException("%s: invalid expression: '%s'", desc, s); } } return true;}/* * CLASS ht_fxbin_search_request */ht_view* create_form_hexascii(Bounds *b, uint histid){ ht_hexascii_search_form *form = new ht_hexascii_search_form(); form->init(b, 0, (List*)getAtomValue(histid)); return form;}ht_search_request* create_request_hexascii(search_pos *start, search_pos *end, ht_view *f, ht_format_viewer *format, uint search_class){ ht_hexascii_search_form *form = (ht_hexascii_search_form*)f; ht_hexascii_search_form_data d; ViewDataBuf vdb(form, &d, sizeof d); ht_fxbin_search_request *request; if (!d.str.textlen) { throw MsgfException("%s: string is empty", "hex/ascii"); } if (test_str_to_ofs(&start->offset, d.start.text, d.start.textlen, format, "start-offset") && test_str_to_ofs(&end->offset, d.end.text, d.end.textlen, format, "end-offset")) { request = new ht_fxbin_search_request(search_class, d.options.state & 1 ? SF_FXBIN_CASEINSENSITIVE: 0, d.str.textlen, d.str.text); } else { request = NULL; } return request;}void create_desc_hexascii(char *buf, int buflen, ht_view *f){ ht_hexascii_search_form *form=(ht_hexascii_search_form*)f; ht_hexascii_search_form_data d; ViewDataBuf vdb(form, &d, sizeof d); if (!d.str.textlen) { throw MsgfException("%s: string is empty", "hex/ascii"); } char *b = buf; b += escape_special(b, buflen, d.str.text, d.str.textlen, NULL, false); strncat(b, " (", buflen-(b-buf)); if (d.options.state & 1) { strncat(b, "case-insensitive", buflen-(b-buf)); } else { strncat(b, "case-sensitive", buflen-(b-buf)); } if (d.start.textlen) { strncat(b, ", start=", buflen-(b-buf)); if (b-buf<buflen) b+=strlen(b); b += escape_special(b, buflen-(b-buf), d.start.text, d.start.textlen); } if (d.end.textlen) { strncat(b, ", end=", buflen-(b-buf)); if (b-buf<buflen) b+=strlen(b); b += escape_special(b, buflen-(b-buf), d.end.text, d.end.textlen); } strncat(b, ")", buflen-(b-buf));}/***/ht_view* create_form_evalstr(Bounds *b, uint histid){ ht_evalstr_search_form *form=new ht_evalstr_search_form(); form->init(b, 0, (List*)getAtomValue(histid)); return form;}ht_search_request* create_request_evalstr(search_pos *start, search_pos *end, ht_view *f, ht_format_viewer *format, uint search_class){#define EVALSTR_MAXSTRLEN 256 ht_evalstr_search_form *form=(ht_evalstr_search_form*)f; ht_evalstr_search_form_data d; ViewDataBuf vdb(form, &d, sizeof d); ht_fxbin_search_request *request = NULL; if (!d.str.textlen) { throw MsgfException("%s: string is empty", "eval str"); } else if (d.str.textlen<=EVALSTR_MAXSTRLEN) { char strbuf[EVALSTR_MAXSTRLEN+1]; bin2str(strbuf, d.str.text, d.str.textlen); eval_scalar r; eval_str s; if (eval(&r, strbuf, NULL, NULL, NULL)) { scalar_context_str(&r, &s); scalar_destroy(&r); if (test_str_to_ofs(&start->offset, d.start.text, d.start.textlen, format, "start-offset") && test_str_to_ofs(&end->offset, d.end.text, d.end.textlen, format, "end-offset")) { request = new ht_fxbin_search_request(search_class, d.options.state & 1 ? SF_FXBIN_CASEINSENSITIVE: 0, s.len, (byte*)s.value); } } else { const char *str; int pos; get_eval_error(&str, &pos); throw MsgfException("eval error at pos %d: %s", pos, str); } } else { throw MsgfException("%s: expression too long (len %d, max %d)", "eval str", d.str.textlen, EVALSTR_MAXSTRLEN); } return request;}void create_desc_evalstr(char *buf, int buflen, ht_view *f){ ht_evalstr_search_form *form=(ht_evalstr_search_form*)f; ht_evalstr_search_form_data d; ViewDataBuf vdb(form, &d, sizeof d); if (!d.str.textlen) { throw MsgfException("%s: string is empty", "eval str"); } char *b = buf; b += escape_special(b, buflen, d.str.text, d.str.textlen, NULL, false); strncat(b, " (", buflen-(b-buf)); if (d.options.state & 1) { strncat(b, "case-insensitive", buflen-(b-buf)); } else { strncat(b, "case-sensitive", buflen-(b-buf)); } if (d.start.textlen) { strncat(b, ", start=", buflen-(b-buf)); if (b-buf<buflen) b+=strlen(b); b+=escape_special(b, buflen-(b-buf), d.start.text, d.start.textlen); } if (d.end.textlen) { strncat(b, ", end=", buflen-(b-buf)); if (b-buf<buflen) b+=strlen(b); b+=escape_special(b, buflen-(b-buf), d.end.text, d.end.textlen); } strncat(b, ")", buflen-(b-buf));}/***/ht_fxbin_search_request::ht_fxbin_search_request(uint search_class, uint flags, uint ds, byte *d) : ht_search_request(search_class, ST_FXBIN, flags){ data_size = ds; data = ht_malloc(data_size); memcpy(data, d, data_size);}ht_fxbin_search_request::~ht_fxbin_search_request(){ free(data);}ht_fxbin_search_request *ht_fxbin_search_request::clone() const{ return new ht_fxbin_search_request(search_class, flags, data_size, data);}/* * CLASS ht_regex_search_request */ ht_view* create_form_vregex(Bounds *b, uint histid){ ht_vregex_search_form *form=new ht_vregex_search_form(); form->init(b, 0, (List*)getAtomValue(histid)); return form;}ht_search_request* create_request_vregex(search_pos *start, search_pos *end, ht_view *f, ht_format_viewer *format, uint search_class){#define VREGEX_MAXSTRLEN 256 ht_vregex_search_form *form=(ht_vregex_search_form*)f; ht_vregex_search_form_data d; ViewDataBuf vdb(form, &d, sizeof d); ht_regex_search_request *request=NULL; if (!d.str.textlen) { throw MsgfException("%s: string is empty", "regex"); } else if (d.str.textlen <= VREGEX_MAXSTRLEN) { char strbuf[VREGEX_MAXSTRLEN+1]; bin2str(strbuf, d.str.text, d.str.textlen); if (test_str_to_pos(&start->pos, d.start.text, d.start.textlen, format, "start-address") && test_str_to_pos(&end->pos, d.end.text, d.end.textlen, format, "end-address")) { request = new ht_regex_search_request(search_class, d.options.state & 1 ? SF_REGEX_CASEINSENSITIVE : 0, strbuf); } } else { throw MsgfException("%s: expression too long (size %d, max %d)", "regex", strlen, VREGEX_MAXSTRLEN); } return request;}void create_desc_vregex(char *buf, int buflen, ht_view *f){ ht_vregex_search_form *form=(ht_vregex_search_form*)f; ht_vregex_search_form_data d; ViewDataBuf vdb(form, &d, sizeof d); if (!d.str.textlen) { throw MsgfException("%s: string is empty", "regex"); } char *b = buf; b += escape_special(b, buflen, d.str.text, d.str.textlen, NULL, false); strncat(b, " (", buflen-(b-buf)); if (d.options.state & 1) { strncat(b, "case-insensitive", buflen-(b-buf)); } else { strncat(b, "case-sensitive", buflen-(b-buf)); } if (d.start.textlen) { strncat(b, ", start=", buflen-(b-buf)); if (b-buf<buflen) b+=strlen(b); b+=escape_special(b, buflen-(b-buf), d.start.text, d.start.textlen); } if (d.end.textlen) { strncat(b, ", end=", buflen-(b-buf)); if (b-buf<buflen) b+=strlen(b); b+=escape_special(b, buflen-(b-buf), d.end.text, d.end.textlen); } strncat(b, ")", buflen-(b-buf));}/***/ht_regex_search_request::ht_regex_search_request(uint search_class, uint flags, char *regex) : ht_search_request(search_class, ST_REGEX, flags){ rx_str = ht_strdup(regex); int r = regcomp(&rx, rx_str, REG_EXTENDED | ((flags & SF_REGEX_CASEINSENSITIVE) ? REG_ICASE : 0)); if (r) throw ht_regex_search_exception(r, &rx);}ht_regex_search_request::~ht_regex_search_request(){ regfree(&rx); free(rx_str);}ht_regex_search_request *ht_regex_search_request::clone() const{ return new ht_regex_search_request(search_class, flags, rx_str);}/* * CLASS ht_regex_search_request */ ht_regex_search_exception::ht_regex_search_exception(int e, regex_t *r){ char s[128]; regerror(e, r, s, sizeof s); ht_snprintf(rxerr, sizeof rxerr, "error compiling regex: %s", s);} String &ht_regex_search_exception::reason(String &s) const{ return s = rxerr;}/* * CLASS ht_expr_search_request */ht_view* create_form_expr(Bounds *b, uint histid){ ht_expr_search_form *form = new ht_expr_search_form(); form->init(b, 0, (List*)getAtomValue(histid)); return form;}ht_search_request* create_request_expr(search_pos *start, search_pos *end, ht_view *f, ht_format_viewer *format, uint search_class){#define EXPR_MAXSTRLEN 256 ht_expr_search_form *form=(ht_expr_search_form*)f; ht_expr_search_form_data d; ViewDataBuf vdb(form, &d, sizeof d); ht_expr_search_request *request = NULL; if (!d.str.textlen) { throw MsgfException("%s: string is empty", "expr"); } else if (d.str.textlen <= EXPR_MAXSTRLEN) { char strbuf[EXPR_MAXSTRLEN+1]; bin2str(strbuf, d.str.text, d.str.textlen); if (test_str_to_ofs(&start->offset, d.start.text, d.start.textlen, format, "start-offset") && test_str_to_ofs(&end->offset, d.end.text, d.end.textlen, format, "end-offset")) { request = new ht_expr_search_request(search_class, 0, strbuf); } } else { throw MsgfException("%s: expression too long (size %d, max %d)", "expr", strlen, EXPR_MAXSTRLEN); } return request;}void create_desc_expr(char *buf, int buflen, ht_view *f){ ht_vregex_search_form *form=(ht_vregex_search_form*)f; ht_vregex_search_form_data d; ViewDataBuf vdb(form, &d, sizeof d); if (!d.str.textlen) { throw MsgfException("%s: string is empty", "expr"); } char *b = buf; b += escape_special(b, buflen, d.str.text, d.str.textlen, NULL, false); strncat(b, " (", buflen-(b-buf)); if (d.options.state & 1) { strncat(b, "case-insensitive", buflen-(b-buf)); } else { strncat(b, "case-sensitive", buflen-(b-buf)); } if (d.start.textlen) { strncat(b, ", start=", buflen-(b-buf)); if (b-buf<buflen) b+=strlen(b); b+=escape_special(b, buflen-(b-buf), d.start.text, d.start.textlen); } if (d.end.textlen) { strncat(b, ", end=", buflen-(b-buf)); if (b-buf<buflen) b+=strlen(b); b+=escape_special(b, buflen-(b-buf), d.end.text, d.end.textlen); } strncat(b, ")", buflen-(b-buf));}/***/ht_expr_search_request::ht_expr_search_request(uint search_class, uint flags, char *Expr) : ht_search_request(search_class, ST_EXPR, flags){ expr = ht_strdup(Expr);}ht_expr_search_request::~ht_expr_search_request(){ free(expr);}ht_expr_search_request *ht_expr_search_request::clone() const{ return new ht_expr_search_request(search_class, flags, expr);}/* * binary search *//* FIXME: put somewhere else */void bufdowncase(byte *buf, uint32 len){ for (uint32 i=0; i<len; i++) { if (buf[i] >= 'A' && buf[i] <= 'Z') buf[i] += 32; }}#define SEARCH_BUF_SIZE 256*1024ht_search_bin_context::~ht_search_bin_context(){ free(buf); free(pat);}Object* create_search_bin_context(File *file, FileOfs ofs, FileOfs len, byte *pat, uint patlen, uint flags, FileOfs *return_ofs, bool *return_success){ if (patlen > SEARCH_BUF_SIZE) return NULL; ht_search_bin_context *ctx = new ht_search_bin_context(); ctx->file = file; ctx->file_end = false; ctx->ofs = ofs; ctx->flags = flags; ctx->len = len; ctx->pat = ht_malloc(patlen); memcpy(ctx->pat, pat, patlen); ctx->patlen = patlen; ctx->o = ofs; if (ctx->flags & SFBIN_CASEINSENSITIVE) bufdowncase(ctx->pat, ctx->patlen); ctx->buf = ht_malloc(SEARCH_BUF_SIZE); ctx->return_ofs = return_ofs; ctx->return_success = return_success; file->seek(ctx->o); ctx->c = file->read(ctx->buf, SEARCH_BUF_SIZE); ctx->bufptr = ctx->buf; ctx->file_end = (ctx->c != SEARCH_BUF_SIZE); if (ctx->flags & SFBIN_CASEINSENSITIVE) bufdowncase(ctx->buf, ctx->c); return ctx;}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -