00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "htatom.h"
00022 #include "cmds.h"
00023 #include "htctrl.h"
00024 #include "hthist.h"
00025 #include "htiobox.h"
00026 #include "htkeyb.h"
00027 #include "htsearch.h"
00028 #include "htstring.h"
00029 #include "process.h"
00030 #include "snprintf.h"
00031
00032 extern "C" {
00033 #include "evalx.h"
00034 }
00035
00036 union search_pos {
00037 FILEOFS offset;
00038 viewer_pos pos;
00039 };
00040
00041
00042 UINT lastsearchmodeid=0;
00043 UINT lastreplacemodeid=0;
00044
00045 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);
00046
00047 typedef Object* (*create_replace_context_func)(ht_streamfile *file, FILEOFS ofs, UINT len, ht_view *form, UINT *return_repllen);
00048
00049 struct ht_search_method {
00050 char *name;
00051 UINT search_class;
00052 UINT search_mode_mask;
00053 HT_ATOM histid;
00054 create_form_func create_form;
00055 create_request_func create_request;
00056 create_desc_func create_desc;
00057 };
00058
00059 struct ht_replace_method {
00060 char *name;
00061 HT_ATOM histid;
00062 create_form_func create_form;
00063 create_replace_context_func create_replace_context;
00064 process_func replace_process;
00065 };
00066
00067 #include <stdlib.h>
00068 #include <string.h>
00069
00070 bool test_str_to_ofs(FILEOFS *ofs, byte *str, UINT strlen, ht_format_viewer *format, char *desc)
00071 {
00072 #define TEST_STR_TO_OFS_MAXSTRLEN 128
00073 if (strlen>TEST_STR_TO_OFS_MAXSTRLEN) {
00074 throw new ht_io_exception("%s: expression too long (len %d, max %d)", desc, strlen, TEST_STR_TO_OFS_MAXSTRLEN);
00075 return false;
00076 }
00077 if (strlen>0) {
00078 char s[TEST_STR_TO_OFS_MAXSTRLEN+1];
00079 bin2str(s, str, strlen);
00080 if (!format->string_to_offset(s, ofs)) {
00081 throw new ht_io_exception("%s: invalid expression: '%s'", desc, s);
00082 return false;
00083 }
00084 }
00085 return true;
00086 }
00087
00088 bool test_str_to_pos(viewer_pos *pos, byte *str, UINT strlen, ht_format_viewer *format, char *desc)
00089 {
00090 #define TEST_STR_TO_POS_MAXSTRLEN 128
00091 if (strlen>TEST_STR_TO_POS_MAXSTRLEN) {
00092 throw new ht_io_exception("%s: expression too long (len %d, max %d)", desc, strlen, TEST_STR_TO_POS_MAXSTRLEN);
00093 return false;
00094 }
00095 if (strlen>0) {
00096 char s[TEST_STR_TO_POS_MAXSTRLEN+1];
00097 bin2str(s, str, strlen);
00098 if (!format->string_to_pos(s, pos)) {
00099 throw new ht_io_exception("%s: invalid expression: '%s'", desc, s);
00100 return false;
00101 }
00102 }
00103 return true;
00104 }
00105
00106
00107
00108
00109
00110 ht_view* create_form_hexascii(bounds *b, HT_ATOM histid)
00111 {
00112 ht_hexascii_search_form *form=new ht_hexascii_search_form();
00113 form->init(b, 0, (ht_list*)find_atom(histid));
00114 return form;
00115 }
00116
00117 ht_search_request* create_request_hexascii(search_pos *start, search_pos *end, ht_view *f, ht_format_viewer *format, UINT search_class)
00118 {
00119 ht_hexascii_search_form *form=(ht_hexascii_search_form*)f;
00120 ht_hexascii_search_form_data d;
00121 form->databuf_get(&d, sizeof d);
00122
00123 ht_fxbin_search_request *request;
00124
00125 if (!d.str.textlen) {
00126 throw new ht_io_exception("%s: string is empty", "hex/ascii");
00127 }
00128 if (test_str_to_ofs(&start->offset, d.start.text, d.start.textlen, format, "start-offset")
00129 && test_str_to_ofs(&end->offset, d.end.text, d.end.textlen, format, "end-offset")) {
00130 request = new ht_fxbin_search_request(search_class,
00131 d.options.state & 1 ? SF_FXBIN_CASEINSENSITIVE: 0,
00132 d.str.textlen, d.str.text);
00133 } else {
00134 request = NULL;
00135 }
00136 return request;
00137 }
00138
00139 void create_desc_hexascii(char *buf, int buflen, ht_view *f)
00140 {
00141 ht_hexascii_search_form *form=(ht_hexascii_search_form*)f;
00142 ht_hexascii_search_form_data d;
00143 form->databuf_get(&d, sizeof d);
00144
00145 if (!d.str.textlen) {
00146 throw new ht_io_exception("%s: string is empty", "hex/ascii");
00147 }
00148
00149 char *b = buf;
00150 b += escape_special(b, buflen, d.str.text, d.str.textlen, NULL, false);
00151 strncat(b, " (", buflen-(b-buf));
00152 if (d.options.state & 1) {
00153 strncat(b, "case-insensitive", buflen-(b-buf));
00154 } else {
00155 strncat(b, "case-sensitive", buflen-(b-buf));
00156 }
00157 if (d.start.textlen) {
00158 strncat(b, ", start=", buflen-(b-buf));
00159 if (b-buf<buflen) b+=strlen(b);
00160 b+=escape_special(b, buflen-(b-buf), d.start.text, d.start.textlen);
00161 }
00162 if (d.end.textlen) {
00163 strncat(b, ", end=", buflen-(b-buf));
00164 if (b-buf<buflen) b+=strlen(b);
00165 b+=escape_special(b, buflen-(b-buf), d.end.text, d.end.textlen);
00166 }
00167 strncat(b, ")", buflen-(b-buf));
00168 }
00169
00170
00171
00172 ht_view* create_form_evalstr(bounds *b, HT_ATOM histid)
00173 {
00174 ht_evalstr_search_form *form=new ht_evalstr_search_form();
00175 form->init(b, 0, (ht_list*)find_atom(histid));
00176 return form;
00177 }
00178
00179 ht_search_request* create_request_evalstr(search_pos *start, search_pos *end, ht_view *f, ht_format_viewer *format, UINT search_class)
00180 {
00181 #define EVALSTR_MAXSTRLEN 256
00182 ht_evalstr_search_form *form=(ht_evalstr_search_form*)f;
00183 ht_evalstr_search_form_data d;
00184 form->databuf_get(&d, sizeof d);
00185
00186 ht_fxbin_search_request *request = NULL;
00187
00188 if (!d.str.textlen) {
00189 throw new ht_io_exception("%s: string is empty", "eval str");
00190 } else if (d.str.textlen<=EVALSTR_MAXSTRLEN) {
00191 char strbuf[EVALSTR_MAXSTRLEN+1];
00192 bin2str(strbuf, d.str.text, d.str.textlen);
00193
00194 eval_scalar r;
00195 eval_str s;
00196 if (eval(&r, strbuf, NULL, NULL, NULL)) {
00197 scalar_context_str(&r, &s);
00198 scalar_destroy(&r);
00199 if (test_str_to_ofs(&start->offset, d.start.text, d.start.textlen, format, "start-offset")
00200 && test_str_to_ofs(&end->offset, d.end.text, d.end.textlen, format, "end-offset")) {
00201 request = new ht_fxbin_search_request(search_class,
00202 d.options.state & 1 ? SF_FXBIN_CASEINSENSITIVE: 0,
00203 s.len, (byte*)s.value);
00204 }
00205 } else {
00206 char *str;
00207 int pos;
00208 get_eval_error(&str, &pos);
00209 throw new ht_io_exception("eval error at pos %d: %s", pos, str);
00210 }
00211 } else {
00212 throw new ht_io_exception("%s: expression too long (len %d, max %d)", "eval str", d.str.textlen, EVALSTR_MAXSTRLEN);
00213 }
00214 return request;
00215 }
00216
00217 void create_desc_evalstr(char *buf, int buflen, ht_view *f)
00218 {
00219 ht_evalstr_search_form *form=(ht_evalstr_search_form*)f;
00220 ht_evalstr_search_form_data d;
00221 form->databuf_get(&d, sizeof d);
00222
00223 if (!d.str.textlen) {
00224 throw new ht_io_exception("%s: string is empty", "eval str");
00225 }
00226
00227 char *b = buf;
00228 b += escape_special(b, buflen, d.str.text, d.str.textlen, NULL, false);
00229 strncat(b, " (", buflen-(b-buf));
00230 if (d.options.state & 1) {
00231 strncat(b, "case-insensitive", buflen-(b-buf));
00232 } else {
00233 strncat(b, "case-sensitive", buflen-(b-buf));
00234 }
00235 if (d.start.textlen) {
00236 strncat(b, ", start=", buflen-(b-buf));
00237 if (b-buf<buflen) b+=strlen(b);
00238 b+=escape_special(b, buflen-(b-buf), d.start.text, d.start.textlen);
00239 }
00240 if (d.end.textlen) {
00241 strncat(b, ", end=", buflen-(b-buf));
00242 if (b-buf<buflen) b+=strlen(b);
00243 b+=escape_special(b, buflen-(b-buf), d.end.text, d.end.textlen);
00244 }
00245 strncat(b, ")", buflen-(b-buf));
00246 }
00247
00248
00249
00250 ht_fxbin_search_request::ht_fxbin_search_request(UINT search_class, UINT flags, UINT ds, byte *d) :
00251 ht_search_request(search_class, ST_FXBIN, flags)
00252 {
00253 data_size = ds;
00254 data = (byte*)malloc(data_size);
00255 memmove(data, d, data_size);
00256 }
00257
00258 ht_fxbin_search_request::~ht_fxbin_search_request()
00259 {
00260 free(data);
00261 }
00262
00263 Object *ht_fxbin_search_request::duplicate()
00264 {
00265 return new ht_fxbin_search_request(search_class, flags, data_size, data);
00266 }
00267
00268
00269
00270
00271
00272 ht_view* create_form_vregex(bounds *b, HT_ATOM histid)
00273 {
00274 ht_vregex_search_form *form=new ht_vregex_search_form();
00275 form->init(b, 0, (ht_list*)find_atom(histid));
00276 return form;
00277 }
00278
00279 ht_search_request* create_request_vregex(search_pos *start, search_pos *end, ht_view *f, ht_format_viewer *format, UINT search_class)
00280 {
00281 #define VREGEX_MAXSTRLEN 256
00282 ht_vregex_search_form *form=(ht_vregex_search_form*)f;
00283 ht_vregex_search_form_data d;
00284 form->databuf_get(&d, sizeof d);
00285
00286 ht_regex_search_request *request=NULL;
00287
00288 if (!d.str.textlen) {
00289 throw new ht_io_exception("%s: string is empty", "regex");
00290 } else if (d.str.textlen <= VREGEX_MAXSTRLEN) {
00291 char strbuf[VREGEX_MAXSTRLEN+1];
00292 bin2str(strbuf, d.str.text, d.str.textlen);
00293
00294 if (test_str_to_pos(&start->pos, d.start.text, d.start.textlen, format, "start-address")
00295 && test_str_to_pos(&end->pos, d.end.text, d.end.textlen, format, "end-address")) {
00296 request = new ht_regex_search_request(search_class, d.options.state & 1 ? SF_REGEX_CASEINSENSITIVE : 0, strbuf);
00297 }
00298 } else {
00299 throw new ht_io_exception("%s: expression too long (size %d, max %d)", "regex", strlen, VREGEX_MAXSTRLEN);
00300 }
00301 return request;
00302 }
00303
00304 void create_desc_vregex(char *buf, int buflen, ht_view *f)
00305 {
00306 ht_vregex_search_form *form=(ht_vregex_search_form*)f;
00307 ht_vregex_search_form_data d;
00308 form->databuf_get(&d, sizeof d);
00309
00310 if (!d.str.textlen) {
00311 throw new ht_io_exception("%s: string is empty", "regex");
00312 }
00313
00314 char *b = buf;
00315 b += escape_special(b, buflen, d.str.text, d.str.textlen, NULL, false);
00316 strncat(b, " (", buflen-(b-buf));
00317 if (d.options.state & 1) {
00318 strncat(b, "case-insensitive", buflen-(b-buf));
00319 } else {
00320 strncat(b, "case-sensitive", buflen-(b-buf));
00321 }
00322 if (d.start.textlen) {
00323 strncat(b, ", start=", buflen-(b-buf));
00324 if (b-buf<buflen) b+=strlen(b);
00325 b+=escape_special(b, buflen-(b-buf), d.start.text, d.start.textlen);
00326 }
00327 if (d.end.textlen) {
00328 strncat(b, ", end=", buflen-(b-buf));
00329 if (b-buf<buflen) b+=strlen(b);
00330 b+=escape_special(b, buflen-(b-buf), d.end.text, d.end.textlen);
00331 }
00332 strncat(b, ")", buflen-(b-buf));
00333 }
00334
00335
00336
00337 ht_regex_search_request::ht_regex_search_request(UINT search_class, UINT flags, char *regex) :
00338 ht_search_request(search_class, ST_REGEX, flags)
00339 {
00340 rx_str = ht_strdup(regex);
00341 int r = regcomp(&rx, rx_str, REG_EXTENDED | ((flags & SF_REGEX_CASEINSENSITIVE) ? REG_ICASE : 0));
00342 if (r) throw new ht_regex_search_exception(r, &rx);
00343 }
00344
00345 ht_regex_search_request::~ht_regex_search_request()
00346 {
00347 regfree(&rx);
00348 free(rx_str);
00349 }
00350
00351 Object *ht_regex_search_request::duplicate()
00352 {
00353 return new ht_regex_search_request(search_class, flags, rx_str);
00354 }
00355
00356
00357
00358
00359
00360 ht_regex_search_exception::ht_regex_search_exception(int e, regex_t *r)
00361 {
00362 errorcode=e;
00363 regex=r;
00364
00365 char s[128];
00366 regerror(errorcode, regex, s, sizeof s);
00367 ht_snprintf(rxerr, sizeof rxerr, "error compiling regex: %s", s);
00368 }
00369
00370 const char* ht_regex_search_exception::what()
00371 {
00372 return rxerr;
00373 }
00374
00375
00376
00377
00378
00379 ht_view* create_form_expr(bounds *b, HT_ATOM histid)
00380 {
00381 ht_expr_search_form *form = new ht_expr_search_form();
00382 form->init(b, 0, (ht_list*)find_atom(histid));
00383 return form;
00384 }
00385
00386 ht_search_request* create_request_expr(search_pos *start, search_pos *end, ht_view *f, ht_format_viewer *format, UINT search_class)
00387 {
00388 #define EXPR_MAXSTRLEN 256
00389 ht_expr_search_form *form=(ht_expr_search_form*)f;
00390 ht_expr_search_form_data d;
00391 form->databuf_get(&d, sizeof d);
00392
00393 ht_expr_search_request *request = NULL;
00394
00395 if (!d.str.textlen) {
00396 throw new ht_io_exception("%s: string is empty", "expr");
00397 } else if (d.str.textlen <= EXPR_MAXSTRLEN) {
00398 char strbuf[EXPR_MAXSTRLEN+1];
00399 bin2str(strbuf, d.str.text, d.str.textlen);
00400
00401 if (test_str_to_ofs(&start->offset, d.start.text, d.start.textlen, format, "start-offset")
00402 && test_str_to_ofs(&end->offset, d.end.text, d.end.textlen, format, "end-offset")) {
00403 request = new ht_expr_search_request(search_class, 0, strbuf);
00404 }
00405 } else {
00406 throw new ht_io_exception("%s: expression too long (size %d, max %d)", "expr", strlen, EXPR_MAXSTRLEN);
00407 }
00408 return request;
00409 }
00410
00411 void create_desc_expr(char *buf, int buflen, ht_view *f)
00412 {
00413 ht_vregex_search_form *form=(ht_vregex_search_form*)f;
00414 ht_vregex_search_form_data d;
00415 form->databuf_get(&d, sizeof d);
00416
00417 if (!d.str.textlen) {
00418 throw new ht_io_exception("%s: string is empty", "expr");
00419 }
00420
00421 char *b = buf;
00422 b += escape_special(b, buflen, d.str.text, d.str.textlen, NULL, false);
00423 strncat(b, " (", buflen-(b-buf));
00424 if (d.options.state & 1) {
00425 strncat(b, "case-insensitive", buflen-(b-buf));
00426 } else {
00427 strncat(b, "case-sensitive", buflen-(b-buf));
00428 }
00429 if (d.start.textlen) {
00430 strncat(b, ", start=", buflen-(b-buf));
00431 if (b-buf<buflen) b+=strlen(b);
00432 b+=escape_special(b, buflen-(b-buf), d.start.text, d.start.textlen);
00433 }
00434 if (d.end.textlen) {
00435 strncat(b, ", end=", buflen-(b-buf));
00436 if (b-buf<buflen) b+=strlen(b);
00437 b+=escape_special(b, buflen-(b-buf), d.end.text, d.end.textlen);
00438 }
00439 strncat(b, ")", buflen-(b-buf));
00440 }
00441
00442
00443
00444 ht_expr_search_request::ht_expr_search_request(UINT search_class, UINT flags, char *Expr) :
00445 ht_search_request(search_class, ST_EXPR, flags)
00446 {
00447 expr = ht_strdup(Expr);
00448 }
00449
00450 ht_expr_search_request::~ht_expr_search_request()
00451 {
00452 if (expr) delete expr;
00453 }
00454
00455 Object *ht_expr_search_request::duplicate()
00456 {
00457 return new ht_expr_search_request(search_class, flags, expr);
00458 }
00459
00460
00461
00462
00463
00464
00465 void bufdowncase(byte *buf, dword len)
00466 {
00467 for (dword i=0; i<len; i++) {
00468 if ((buf[i]>='A') && (buf[i]<='Z')) buf[i]+=32;
00469 }
00470 }
00471
00472 #define SEARCH_BUF_SIZE 256*1024
00473
00474 ht_search_bin_context::~ht_search_bin_context()
00475 {
00476 free(buf);
00477 free(pat);
00478 }
00479
00480 Object* create_search_bin_context(ht_streamfile *file, FILEOFS ofs, UINT len, byte *pat, UINT patlen, UINT flags, UINT *return_ofs, bool *return_success)
00481 {
00482 if (patlen > SEARCH_BUF_SIZE) return NULL;
00483
00484 ht_search_bin_context *ctx = new ht_search_bin_context();
00485 ctx->file = file;
00486 ctx->file_end = false;
00487 ctx->ofs = ofs;
00488 ctx->flags = flags;
00489 ctx->len = len;
00490 ctx->pat = (byte*)malloc(patlen);
00491 memmove(ctx->pat, pat, patlen);
00492 ctx->patlen = patlen;
00493
00494 ctx->o = ofs;
00495
00496 if (ctx->flags & SFBIN_CASEINSENSITIVE) bufdowncase(ctx->pat, ctx->patlen);
00497
00498 ctx->buf = (byte*)malloc(SEARCH_BUF_SIZE);
00499
00500 ctx->return_ofs = return_ofs;
00501 ctx->return_success = return_success;
00502
00503 file->seek(ctx->o);
00504 ctx->c = file->read(ctx->buf, SEARCH_BUF_SIZE);
00505 ctx->bufptr = ctx->buf;
00506 ctx->file_end = (ctx->c != SEARCH_BUF_SIZE);
00507 if (ctx->flags & SFBIN_CASEINSENSITIVE) bufdowncase(ctx->buf, ctx->c);
00508
00509 return ctx;
00510 }
00511
00512 bool search_bin_process(Object *context, ht_text *progress_indicator)
00513 {
00514 ht_search_bin_context *ctx = (ht_search_bin_context*)context;
00515
00516 if (ctx->bufptr - ctx->buf + ctx->patlen > ctx->c) {
00517 if (ctx->file_end) {
00518 *ctx->return_success = false;
00519 return false;
00520 }
00521 ctx->file->seek(ctx->o);
00522 ctx->c = ctx->file->read(ctx->buf, SEARCH_BUF_SIZE);
00523 ctx->bufptr = ctx->buf;
00524 ctx->file_end = (ctx->c != SEARCH_BUF_SIZE);
00525 if (ctx->flags & SFBIN_CASEINSENSITIVE) bufdowncase(ctx->buf, ctx->c);
00526 }
00527
00528 while (ctx->bufptr + ctx->patlen <= ctx->buf + ctx->c) {
00529 if (memcmp(ctx->pat, ctx->bufptr, ctx->patlen) == 0) {
00530 *ctx->return_success = true;
00531 *ctx->return_ofs = ctx->o;
00532 return false;
00533 }
00534 ctx->bufptr++;
00535 ctx->o++;
00536 }
00537 ctx->o -= ctx->patlen-1;
00538
00539 int p = (int)(((double)(ctx->o - ctx->ofs))*100/ctx->len);
00540
00541 char status[64];
00542 ht_snprintf(status, sizeof status, "%d %%", p);
00543 progress_indicator->settext(status);
00544
00545 return true;
00546 }
00547
00548
00549
00550
00551
00552 void ht_hexascii_search_form::init(bounds *b, int options, ht_list *history)
00553 {
00554 ht_group::init(b, VO_SELECTABLE, NULL);
00555 VIEW_DEBUG_NAME("ht_hexascii_search_form");
00556
00557 bounds c;
00558
00559 c.x=6;
00560 c.y=0;
00561 c.w=b->w-6;
00562 c.h=1;
00563 str=new ht_strinputfield();
00564 str->init(&c, 64, history);
00565 insert(str);
00566
00567 c.x=0;
00568 c.w=5;
00569 c.h=1;
00570 ht_label *strlabel=new ht_label();
00571 strlabel->init(&c, "~ascii", str);
00572 insert(strlabel);
00573
00574
00575 c.x=6;
00576 c.y=2;
00577 c.w=b->w-6;
00578 c.h=1;
00579 ht_hexinputfield *hex=new ht_hexinputfield();
00580 hex->init(&c, 64);
00581 hex->attach(str);
00582 insert(hex);
00583
00584 c.x=0;
00585 c.w=5;
00586 c.h=1;
00587 ht_label *hexlabel=new ht_label();
00588 hexlabel->init(&c, "~hex", hex);
00589 insert(hexlabel);
00590
00591
00592 c.x=10;
00593 c.y=4;
00594 c.w=10;
00595 c.h=1;
00596 range_start=new ht_strinputfield();
00597 range_start->init(&c, 10);
00598 insert(range_start);
00599
00600 c.x=0;
00601 c.w=9;
00602 c.h=1;
00603 ht_label *rslabel=new ht_label();
00604 rslabel->init(&c, "~from ofs", range_start);
00605 insert(rslabel);
00606
00607
00608 c.x=10;
00609 c.y=6;
00610 c.w=10;
00611 c.h=1;
00612 range_end=new ht_strinputfield();
00613 range_end->init(&c, 10);
00614 insert(range_end);
00615
00616 c.x=0;
00617 c.w=9;
00618 c.h=1;
00619 ht_label *relabel=new ht_label();
00620 relabel->init(&c, "~to ofs", range_end);
00621 insert(relabel);
00622
00623 c.w=35;
00624 c.y=8;
00625 c.h=2;
00626 ht_string_list *opts = new ht_string_list();
00627 opts->init();
00628 opts->insert_string("case ~insensitive");
00629 option_boxes = new ht_checkboxes();
00630 option_boxes->init(&c, opts);
00631 ht_checkboxes_data d;
00632 d.state = options;
00633 option_boxes->databuf_set(&d, sizeof d);
00634 insert(option_boxes);
00635 }
00636
00637
00638
00639
00640
00641 void ht_evalstr_search_form::init(bounds *b, int options, ht_list *history)
00642 {
00643 ht_group::init(b, VO_SELECTABLE, NULL);
00644 VIEW_DEBUG_NAME("ht_evalstr_search_form");
00645
00646 bounds c;
00647
00648 c.x=0;
00649 c.y=1;
00650 c.w=b->w;
00651 c.h=1;
00652 str=new ht_strinputfield();
00653 str->init(&c, 64, history);
00654 insert(str);
00655
00656 c.x=0;
00657 c.y=0;
00658 c.w=23;
00659 c.h=1;
00660 ht_label *strlabel=new ht_label();
00661 strlabel->init(&c, "s~earch evaluated string", str);
00662 insert(strlabel);
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 c.x=10;
00674 c.y=4;
00675 c.w=10;
00676 c.h=1;
00677 range_start=new ht_strinputfield();
00678 range_start->init(&c, 10);
00679 insert(range_start);
00680
00681 c.x=0;
00682 c.w=9;
00683 c.h=1;
00684 ht_label *rslabel=new ht_label();
00685 rslabel->init(&c, "~from ofs", range_start);
00686 insert(rslabel);
00687
00688
00689 c.x=10;
00690 c.y=6;
00691 c.w=10;
00692 c.h=1;
00693 range_end=new ht_strinputfield();
00694 range_end->init(&c, 10);
00695 insert(range_end);
00696
00697 c.x=0;
00698 c.w=9;
00699 c.h=1;
00700 ht_label *relabel=new ht_label();
00701 relabel->init(&c, "~to ofs", range_end);
00702 insert(relabel);
00703
00704 c.w = 35;
00705 c.y = 8;
00706 c.h = 2;
00707 ht_string_list *opts = new ht_string_list();
00708 opts->init();
00709 opts->insert_string("case ~insensitive");
00710 option_boxes = new ht_checkboxes();
00711 option_boxes->init(&c, opts);
00712 ht_checkboxes_data d;
00713 d.state = options;
00714 option_boxes->databuf_set(&d, sizeof d);
00715 insert(option_boxes);
00716 }
00717
00718
00719
00720
00721
00722 void ht_vregex_search_form::init(bounds *b, int options, ht_list *history)
00723 {
00724 ht_group::init(b, VO_SELECTABLE, NULL);
00725 VIEW_DEBUG_NAME("ht_text_search_form");
00726
00727 bounds c;
00728
00729 c.x=0;
00730 c.y=1;
00731 c.w=b->w;
00732 c.h=1;
00733 str=new ht_strinputfield();
00734 str->init(&c, 64, history);
00735 insert(str);
00736
00737 c.x=0;
00738 c.y=0;
00739 c.w=12;
00740 c.h=1;
00741 ht_label *strlabel=new ht_label();
00742 strlabel->init(&c, "s~earch regex", str);
00743 insert(strlabel);
00744
00745
00746 c.x=10;
00747 c.y=4;
00748 c.w=10;
00749 c.h=1;
00750 range_start=new ht_strinputfield();
00751 range_start->init(&c, 10);
00752 insert(range_start);
00753
00754 c.x=0;
00755 c.w=9;
00756 c.h=1;
00757 ht_label *rslabel=new ht_label();
00758 rslabel->init(&c, "~from addr", range_start);
00759 insert(rslabel);
00760
00761
00762 c.x=10;
00763 c.y=6;
00764 c.w=10;
00765 c.h=1;
00766 range_end=new ht_strinputfield();
00767 range_end->init(&c, 10);
00768 insert(range_end);
00769
00770 c.x=0;
00771 c.w=9;
00772 c.h=1;
00773 ht_label *relabel=new ht_label();
00774 relabel->init(&c, "~to addr", range_end);
00775 insert(relabel);
00776
00777 c.w = 35;
00778 c.y = 8;
00779 c.h = 2;
00780 ht_string_list *opts = new ht_string_list();
00781 opts->init();
00782 opts->insert_string("case ~insensitive");
00783 option_boxes = new ht_checkboxes();
00784 option_boxes->init(&c, opts);
00785 ht_checkboxes_data d;
00786 d.state = options;
00787 option_boxes->databuf_set(&d, sizeof d);
00788 insert(option_boxes);
00789 }
00790
00791
00792
00793
00794
00795 void ht_expr_search_form::init(bounds *b, int options, ht_list *history)
00796 {
00797 ht_group::init(b, VO_SELECTABLE, NULL);
00798 VIEW_DEBUG_NAME("ht_expr_search_form");
00799
00800 bounds c;
00801
00802 c.x=0;
00803 c.y=1;
00804 c.w=b->w;
00805 c.h=1;
00806 str=new ht_strinputfield();
00807 str->init(&c, 256, history);
00808 insert(str);
00809
00810 c.x=0;
00811 c.y=0;
00812 c.w=17;
00813 c.h=1;
00814 ht_label *strlabel=new ht_label();
00815 strlabel->init(&c, "s~earch expression", str);
00816 insert(strlabel);
00817
00818 c.x=0;
00819 c.y=2;
00820 c.w=b->w-2;
00821 c.h=1;
00822 ht_statictext *hint=new ht_statictext();
00823 hint->init(&c, "stops if expression evaluates to non-zero", align_left);
00824 insert(hint);
00825
00826
00827 c.x=10;
00828 c.y=4;
00829 c.w=10;
00830 c.h=1;
00831 range_start=new ht_strinputfield();
00832 range_start->init(&c, 10);
00833 insert(range_start);
00834
00835 c.x=0;
00836 c.w=9;
00837 c.h=1;
00838 ht_label *rslabel=new ht_label();
00839 rslabel->init(&c, "~from ofs", range_start);
00840 insert(rslabel);
00841
00842
00843 c.x=10;
00844 c.y=6;
00845 c.w=10;
00846 c.h=1;
00847 range_end=new ht_strinputfield();
00848 range_end->init(&c, 10);
00849 insert(range_end);
00850
00851 c.x=0;
00852 c.w=9;
00853 c.h=1;
00854 ht_label *relabel=new ht_label();
00855 relabel->init(&c, "~to ofs", range_end);
00856 insert(relabel);
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 }
00870
00871
00872
00873
00874
00875 ht_replace_bin_context::~ht_replace_bin_context()
00876 {
00877 free(repl);
00878 }
00879
00880 ht_view* create_form_replace_hexascii(bounds *b, HT_ATOM histid)
00881 {
00882 ht_replace_hexascii_search_form *form=new ht_replace_hexascii_search_form();
00883 form->init(b, 0, (ht_list*)find_atom(histid));
00884 return form;
00885 }
00886
00887 Object* create_replace_hexascii_context(ht_streamfile *file, FILEOFS ofs, UINT len, ht_view *form, UINT *return_repllen)
00888 {
00889 ht_replace_hexascii_search_form_data d;
00890 form->databuf_get(&d, sizeof d);
00891
00892 ht_replace_bin_context *ctx = (ht_replace_bin_context*)
00893 create_replace_bin_context(file, ofs, len, d.str.text, d.str.textlen, return_repllen);
00894
00895 return ctx;
00896 }
00897
00898 void ht_replace_hexascii_search_form::init(bounds *b, int options, ht_list *history)
00899 {
00900 ht_group::init(b, VO_SELECTABLE, NULL);
00901 VIEW_DEBUG_NAME("ht_replace_hexascii_search_form");
00902
00903 bounds c;
00904
00905 c.x=6;
00906 c.y=0;
00907 c.w=40;
00908 c.h=1;
00909 str=new ht_strinputfield();
00910 str->init(&c, 64, history);
00911 insert(str);
00912
00913 c.x=0;
00914 c.w=5;
00915 c.h=1;
00916 ht_label *strlabel=new ht_label();
00917 strlabel->init(&c, "~ascii", str);
00918 insert(strlabel);
00919
00920
00921 c.x=6;
00922 c.y=2;
00923 c.w=40;
00924 c.h=1;
00925 ht_hexinputfield *hex=new ht_hexinputfield();
00926 hex->init(&c, 64);
00927 hex->attach(str);
00928 insert(hex);
00929
00930 c.x=0;
00931 c.w=5;
00932 c.h=1;
00933 ht_label *hexlabel=new ht_label();
00934 hexlabel->init(&c, "~hex", hex);
00935 insert(hexlabel);
00936 }
00937
00938
00939
00940
00941
00942 static ht_search_method search_methods[] =
00943 {
00944 { "bin: hex/ascii", SC_PHYSICAL, SEARCHMODE_BIN, HISTATOM_SEARCH_BIN,
00945 create_form_hexascii, create_request_hexascii, create_desc_hexascii },
00946 { "bin: eval str", SC_PHYSICAL, SEARCHMODE_EVALSTR, HISTATOM_SEARCH_EVALSTR,
00947 create_form_evalstr, create_request_evalstr, create_desc_evalstr },
00948 { "display: regex", SC_VISUAL, SEARCHMODE_VREGEX, HISTATOM_SEARCH_VREGEX,
00949 create_form_vregex, create_request_vregex, create_desc_vregex },
00950 { "expr non-zero", SC_PHYSICAL, SEARCHMODE_EXPR, HISTATOM_SEARCH_EXPR,
00951 create_form_expr, create_request_expr, create_desc_expr },
00952 { NULL }
00953 };
00954
00955 ht_search_request *search_dialog(ht_format_viewer *format, UINT searchmodes, viewer_pos *start, viewer_pos *end)
00956 {
00957 ht_search_request *result = NULL;
00958 bounds b;
00959 b.w = 50;
00960 b.h = 15;
00961 b.x = (screen->size.w-b.w)/2;
00962 b.y = (screen->size.h-b.h)/2;
00963 ht_search_dialog *dialog = new ht_search_dialog();
00964 dialog->init(&b, "search");
00965
00966 bounds k;
00967 dialog->search_mode_xgroup->getbounds(&k);
00968
00969 k.x = 0;
00970 k.y = 0;
00971
00972 int modes = 0;
00973 int i = 0;
00974 ht_search_method *q = search_methods;
00975 while (q->name) {
00976 if (q->search_mode_mask & searchmodes) {
00977 bounds v = k;
00978 ht_view *form = q->create_form(&v, q->histid);
00979 dialog->insert_search_mode(i, q->name, form);
00980 modes++;
00981 }
00982 q++;
00983 i++;
00984 }
00985
00986 dialog->select_search_mode(lastsearchmodeid);
00987
00988 if (dialog->run(false)) {
00989 int modeid = dialog->get_search_modeid();
00990 lastsearchmodeid = modeid;
00991
00992 ht_search_method *s = &search_methods[modeid];
00993 ht_view *form = dialog->get_search_modeform();
00994
00995 search_pos sstart, send;
00996
00997 try {
00998
00999 if (s->create_desc) {
01000 char hist_desc[1024];
01001 s->create_desc(hist_desc, sizeof hist_desc, form);
01002 insert_history_entry((ht_list*)find_atom(s->histid), hist_desc, form);
01003 }
01004
01005 switch (s->search_class) {
01006 case SC_PHYSICAL:
01007 if (!format->pos_to_offset(*start, &sstart.offset)
01008 || !format->pos_to_offset(*end, &send.offset)) {
01009 throw new ht_io_exception("Internal error: can't convert viewer_pos to offset");
01010 }
01011 break;
01012 case SC_VISUAL:
01013 sstart.pos = *start;
01014 send.pos = *end;
01015 break;
01016 }
01017 result = s->create_request(&sstart, &send, form, format, s->search_class);
01018 switch (s->search_class) {
01019 case SC_PHYSICAL:
01020 if (!format->offset_to_pos(sstart.offset, start)
01021 || !format->offset_to_pos(send.offset, end)) {
01022 throw new ht_io_exception("Internal error: can't convert offset to viewer_pos");
01023 }
01024 break;
01025 case SC_VISUAL:
01026 *start = sstart.pos;
01027 *end = send.pos;
01028 break;
01029 }
01030 } catch (ht_exception *e) {
01031 errorbox("error: %s", e->what());
01032 }
01033 }
01034 dialog->done();
01035 delete dialog;
01036 return result;
01037 }
01038
01039 static ht_replace_method replace_methods[] =
01040 {
01041 { "bin: hex/ascii", 0, create_form_replace_hexascii,
01042 create_replace_hexascii_context, replace_bin_process },
01043 { NULL }
01044 };
01045
01046 UINT replace_dialog(ht_format_viewer *format, UINT searchmodes, bool *cancelled)
01047 {
01048 *cancelled = false;
01049 bounds b;
01050 b.w = 50;
01051 b.h = 22;
01052 b.x = (screen->size.w-b.w)/2;
01053 b.y = (screen->size.h-b.h)/2;
01054 ht_replace_dialog *dialog = new ht_replace_dialog();
01055 dialog->init(&b);
01056
01057 bounds k;
01058 dialog->search_mode_xgroup->getbounds(&k);
01059
01060 k.x = 0;
01061 k.y = 0;
01062
01063 int i;
01064
01065 i = 0;
01066 ht_search_method *q = search_methods;
01067 while (q->name) {
01068 if ((q->search_mode_mask & searchmodes) &&
01069 (q->search_class == SC_PHYSICAL)) {
01070 bounds v = k;
01071 ht_view *form = q->create_form(&v, q->histid);
01072 dialog->insert_search_mode(i, q->name, form);
01073 }
01074 q++;
01075 i++;
01076 }
01077
01078 dialog->replace_mode_xgroup->getbounds(&k);
01079 k.x = 0;
01080 k.y = 0;
01081
01082 i = 0;
01083 ht_replace_method *w = replace_methods;
01084 while (w->name) {
01085 bounds v = k;
01086 ht_view *form = w->create_form(&v, w->histid);
01087 dialog->insert_replace_mode(i, w->name, form);
01088 w++;
01089 i++;
01090 }
01091
01092 dialog->select_search_mode(lastsearchmodeid);
01093 dialog->select_replace_mode(lastreplacemodeid);
01094
01095 UINT repl_count = 0;
01096 if (dialog->run(false)) {
01097 int smodeid = dialog->get_search_modeid();
01098 int rmodeid = dialog->get_replace_modeid();
01099 lastsearchmodeid = smodeid;
01100 lastreplacemodeid = rmodeid;
01101
01102 ht_search_method *s = &search_methods[smodeid];
01103 ht_replace_method *r = &replace_methods[rmodeid];
01104 ht_view *sform = dialog->get_search_modeform();
01105 ht_view *rform = dialog->get_replace_modeform();
01106
01107 search_pos start, end;
01108
01109 ht_search_request *request = NULL;
01110
01111 try {
01112
01113 if (s->create_desc) {
01114 char hist_desc[1024];
01115 s->create_desc(hist_desc, sizeof hist_desc, sform);
01116 insert_history_entry((ht_list*)find_atom(s->histid), hist_desc, sform);
01117 }
01118
01119 start.offset=0;
01120 end.offset=0xffffffff;
01121 format->get_current_offset(&start.offset);
01122
01123 request = s->create_request(&start, &end, sform, format, s->search_class);
01124 } catch (ht_exception *e) {
01125 errorbox("error: %s", e->what());
01126 }
01127
01128 if (request) {
01129 FILEOFS so = start.offset, eo = end.offset;
01130 ht_physical_search_result *result;
01131
01132 format->vstate_save();
01133
01134 try {
01135 bool replace_all = false;
01136 while ((result = (ht_physical_search_result*)format->psearch(request, so, eo))) {
01137 UINT irepllen = 0;
01138 bool do_replace = false;
01139
01140 if (!replace_all) {
01141 bool showed = format->show_search_result(result);
01142 int r = msgbox(btmask_yes+btmask_no+btmask_all+btmask_cancel, "confirmation", 0, align_center, "replace ?");
01143 if (showed) app->sendmsg(cmd_vstate_restore);
01144 switch (r) {
01145 case button_yes:
01146 do_replace = true;
01147 break;
01148 case button_no:
01149 break;
01150 case button_all:
01151 replace_all = true;
01152 break;
01153 }
01154 if (r == button_cancel) {
01155 *cancelled = true;
01156 delete result;
01157 break;
01158 }
01159 }
01160
01161 if (replace_all || do_replace) {
01162 Object *rctx = r->create_replace_context(format->get_file(), result->offset, result->size, rform, &irepllen);
01163 bool p = execute_process(r->replace_process, rctx);
01164 delete rctx;
01165 if (!p) {
01166 delete result;
01167 break;
01168 }
01169
01170 if (irepllen != result->size) {
01171 format->sendmsg(msg_filesize_changed);
01172 }
01173 so = result->offset + irepllen;
01174 repl_count++;
01175 } else {
01176 so = result->offset + result->size;
01177 }
01178 delete result;
01179 }
01180 } catch (ht_exception *e) {
01181 errorbox("error: %s", e->what());
01182 }
01183
01184 app->sendmsg(cmd_vstate_restore);
01185 }
01186
01187 if (request) delete request;
01188 }
01189 dialog->done();
01190 delete dialog;
01191 return repl_count;
01192 }
01193
01194 #define REPLACE_COPY_BUF_SIZE 64*1024
01195 Object* create_replace_bin_context(ht_streamfile *file, FILEOFS ofs, UINT len, byte *repl, UINT repllen, UINT *return_repllen)
01196 {
01197 ht_replace_bin_context *ctx = new ht_replace_bin_context();
01198 ctx->file = file;
01199 ctx->ofs = ofs;
01200 ctx->len = len;
01201 ctx->repl = (byte*)malloc(repllen);
01202 memmove(ctx->repl, repl, repllen);
01203 ctx->repllen = repllen;
01204 if (repllen > len) {
01205 ctx->o = file->get_size();
01206 } else if (len > repllen) {
01207 ctx->o = ofs+len;
01208 }
01209 ctx->z = REPLACE_COPY_BUF_SIZE;
01210 if (len != repllen)
01211 ctx->buf = (byte*)malloc(REPLACE_COPY_BUF_SIZE);
01212 ctx->return_repllen = return_repllen;
01213 return ctx;
01214 }
01215
01216 bool replace_bin_process(Object *context, ht_text *progress_indicator)
01217 {
01218 progress_indicator->settext("replacing...\n");
01219
01220 ht_replace_bin_context *c = (ht_replace_bin_context*)context;
01221 if (c->repllen > c->len) {
01222
01223 UINT size = c->file->get_size();
01224 c->file->extend(size + c->repllen - c->len);
01225
01226 if (c->o > c->z) {
01227 c->o -= c->z;
01228 } else {
01229 c->z = c->o;
01230 c->o = 0;
01231 }
01232 if (c->o < c->ofs+c->len) {
01233 c->z -= c->ofs + c->len - c->o;
01234 c->o = c->ofs + c->len;
01235 }
01236 c->file->seek(c->o);
01237 if (c->file->read(c->buf, c->z) != c->z)
01238 throw new ht_io_exception("cant replace, write error (ofs=%08x)", c->ofs);
01239 c->file->seek(c->o+c->repllen-c->len);
01240 if (c->file->write(c->buf, c->z) != c->z)
01241 throw new ht_io_exception("cant replace, write error (ofs=%08x)", c->ofs);
01242
01243 if (c->o > c->ofs + c->len) return true;
01244
01245 c->file->seek(c->ofs);
01246 if (c->file->write(c->repl, c->repllen) != c->repllen)
01247 throw new ht_io_exception("cant replace, write error (ofs=%08x)", c->ofs);
01248 free(c->buf);
01249 } else if (c->repllen < c->len) {
01250
01251 UINT size = c->file->get_size();
01252 if (c->o == c->ofs + c->len) {
01253 c->file->seek(c->ofs);
01254 if (c->file->write(c->repl, c->repllen) != c->repllen)
01255 throw new ht_io_exception("cant replace, write error (ofs=%08x)", c->ofs);
01256 }
01257
01258 if (c->z > size - c->o) {
01259 c->z = size - c->o;
01260 }
01261 c->file->seek(c->o);
01262 if (c->file->read(c->buf, c->z) != c->z)
01263 throw new ht_io_exception("cant replace, write error (ofs=%08x)", c->ofs);
01264 c->file->seek(c->o - (c->len - c->repllen));
01265 if (c->file->write(c->buf, c->z) != c->z)
01266 throw new ht_io_exception("cant replace, write error (ofs=%08x)", c->ofs);
01267 c->o += REPLACE_COPY_BUF_SIZE;
01268
01269 if (c->z == REPLACE_COPY_BUF_SIZE) return true;
01270
01271 c->file->truncate(size - (c->len - c->repllen));
01272 free(c->buf);
01273 } else {
01274 c->file->seek(c->ofs);
01275 if (c->file->write(c->repl, c->repllen) != c->repllen)
01276 throw new ht_io_exception("cant replace, write error (ofs=%08x)", c->ofs);
01277 }
01278 if (c->return_repllen) *c->return_repllen = c->repllen;
01279 return false;
01280 }
01281
01282
01283
01284
01285
01286 void ht_search_dialog::init(bounds *b, const char *title)
01287 {
01288 ht_dialog::init(b, title, FS_KILLER | FS_TITLE | FS_MOVE);
01289 VIEW_DEBUG_NAME("ht_search_dialog");
01290
01291 smodecount = 0;
01292 smodeidx = -1;
01293
01294 bounds c;
01295 c.x=1;
01296 c.y=1;
01297 c.w=20;
01298 c.h=1;
01299
01300 search_mode_popup = new ht_listpopup();
01301 search_mode_popup->init(&c);
01302 insert(search_mode_popup);
01303
01304 c.x=1;
01305 c.y=0;
01306 c.w=4;
01307 c.h=1;
01308 ht_label *mlabel=new ht_label();
01309 mlabel->init(&c, "~mode", search_mode_popup);
01310 insert(mlabel);
01311
01312 c.x=1;
01313 c.y=3;
01314 c.w=size.w-4;
01315 c.h=MIN(10, size.h-4);
01316 search_mode_xgroup = new ht_xgroup();
01317 search_mode_xgroup->init(&c, VO_SELECTABLE, "modes");
01318 insert(search_mode_xgroup);
01319 }
01320
01321 void ht_search_dialog::done()
01322 {
01323 ht_dialog::done();
01324 }
01325
01326 int ht_search_dialog::find_search_mode(int id)
01327 {
01328 for (int i=0; i<smodecount; i++) {
01329 if (smodes[i].id==id) {
01330 return i;
01331 }
01332 }
01333 return -1;
01334 }
01335
01336 void ht_search_dialog::handlemsg(htmsg *msg)
01337 {
01338 if (msg->msg==msg_keypressed) {
01339 ht_dialog::handlemsg(msg);
01340 ht_listpopup_data data;
01341 search_mode_popup->databuf_get(&data, sizeof data);
01342 if ((int)data.cursor_pos != smodeidx) {
01343 smodeidx = data.cursor_pos;
01344 select_search_mode_bymodeidx();
01345 }
01346 } else ht_dialog::handlemsg(msg);
01347 }
01348
01349 int ht_search_dialog::get_search_modeid()
01350 {
01351 return smodes[smodeidx].id;
01352 }
01353
01354 ht_view *ht_search_dialog::get_search_modeform()
01355 {
01356 return smodes[smodeidx].view;
01357 }
01358
01359 void ht_search_dialog::insert_search_mode(int id, char *desc, ht_view *v)
01360 {
01361 if (smodecount<MAX_SEARCH_DIALOG_MODES) {
01362 search_mode_xgroup->insert(v);
01363 search_mode_popup->insertstring(desc);
01364 smodes[smodecount].id=id;
01365 smodes[smodecount].view=v;
01366 smodecount++;
01367 focus(search_mode_xgroup);
01368 }
01369 }
01370
01371 void ht_search_dialog::select_search_mode(int id)
01372 {
01373 int i=find_search_mode(id);
01374 if (i!=-1) {
01375 smodeidx=i;
01376 select_search_mode_bymodeidx();
01377 }
01378 }
01379
01380 void ht_search_dialog::select_search_mode_bymodeidx()
01381 {
01382 ht_listpopup_data d;
01383 d.cursor_pos = smodeidx;
01384 search_mode_popup->databuf_set(&d, sizeof d);
01385 focus(smodes[smodeidx].view);
01386 sendmsg(msg_dirtyview, 0);
01387 }
01388
01389
01390
01391
01392
01393 void ht_replace_dialog::init(bounds *b)
01394 {
01395 ht_search_dialog::init(b, "replace");
01396
01397 rmodecount=0;
01398
01399 bounds c;
01400 c.x=1;
01401 c.y=15;
01402 c.w=20;
01403 c.h=1;
01404
01405 replace_mode_popup = new ht_listpopup();
01406 replace_mode_popup->init(&c);
01407 insert(replace_mode_popup);
01408
01409 c.x=0;
01410 c.y=13;
01411 c.w=size.w-2;
01412 c.h=1;
01413 ht_hbar *hbar=new ht_hbar();
01414 hbar->init(&c, 0, NULL);
01415 insert(hbar);
01416
01417 c.x=1;
01418 c.y=14;
01419 c.w=4;
01420 c.h=1;
01421 ht_label *mlabel=new ht_label();
01422 mlabel->init(&c, "~replace mode", replace_mode_popup);
01423 insert(mlabel);
01424
01425 c.x=1;
01426 c.y=17;
01427 c.w=size.w-4;
01428 c.h=size.h-c.y;
01429 replace_mode_xgroup = new ht_xgroup();
01430 replace_mode_xgroup->init(&c, VO_SELECTABLE, "replace modes");
01431 insert(replace_mode_xgroup);
01432 }
01433
01434 void ht_replace_dialog::done()
01435 {
01436 ht_dialog::done();
01437 }
01438
01439 int ht_replace_dialog::find_replace_mode(int id)
01440 {
01441 for (int i=0; i<rmodecount; i++) {
01442 if (rmodes[i].id==id) {
01443 return i;
01444 }
01445 }
01446 return -1;
01447 }
01448
01449 void ht_replace_dialog::handlemsg(htmsg *msg)
01450 {
01451 if (msg->msg == msg_keypressed) {
01452 ht_search_dialog::handlemsg(msg);
01453 ht_listpopup_data data;
01454 replace_mode_popup->databuf_get(&data, sizeof data);
01455 if ((int)data.cursor_pos != rmodeidx) {
01456 rmodeidx=data.cursor_pos;
01457 select_replace_mode_bymodeidx();
01458 }
01459 } else ht_search_dialog::handlemsg(msg);
01460 }
01461
01462 int ht_replace_dialog::get_replace_modeid()
01463 {
01464 return rmodes[rmodeidx].id;
01465 }
01466
01467 ht_view *ht_replace_dialog::get_replace_modeform()
01468 {
01469 return rmodes[rmodeidx].view;
01470 }
01471
01472 void ht_replace_dialog::insert_replace_mode(int id, char *desc, ht_view *v)
01473 {
01474 if (rmodecount<MAX_REPLACE_DIALOG_MODES) {
01475 replace_mode_xgroup->insert(v);
01476 replace_mode_popup->insertstring(desc);
01477 rmodes[rmodecount].id=id;
01478 rmodes[rmodecount].view=v;
01479 rmodecount++;
01480
01481 }
01482 }
01483
01484 void ht_replace_dialog::select_replace_mode(int id)
01485 {
01486 int i=find_replace_mode(id);
01487 if (i!=-1) {
01488 rmodeidx=i;
01489 select_replace_mode_bymodeidx();
01490 }
01491 }
01492
01493 void ht_replace_dialog::select_replace_mode_bymodeidx()
01494 {
01495 ht_listpopup_data d;
01496 d.cursor_pos = rmodeidx;
01497 replace_mode_popup->databuf_set(&d, sizeof d);
01498
01499 sendmsg(msg_dirtyview, 0);
01500 }
01501
01502
01503
01504
01505
01506 ht_search_result *linear_bin_search(ht_search_request *search, FILEOFS start, FILEOFS end, ht_streamfile *file, FILEOFS fofs, dword fsize)
01507 {
01508 ht_fxbin_search_request *s=(ht_fxbin_search_request*)search;
01509
01510 int fl=(search->flags & SFBIN_CASEINSENSITIVE) ? SFBIN_CASEINSENSITIVE : 0;
01511 if (start<fofs) start=fofs;
01512 if (end>fofs+fsize) end=fofs+fsize;
01513 if ((fsize) && (start<end)) {
01514
01515 bool search_success = false;
01516 FILEOFS search_ofs;
01517 Object *ctx = create_search_bin_context(file, start, end-start, s->data, s->data_size, fl, &search_ofs, &search_success);
01518 if (execute_process(search_bin_process, ctx)) {
01519 delete ctx;
01520 if (search_success) {
01521 ht_physical_search_result *r=new ht_physical_search_result();
01522 r->offset = search_ofs;
01523 r->size = s->data_size;
01524 return r;
01525 }
01526 } else delete ctx;
01527 }
01528 return NULL;
01529 }
01530
01531