Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

htsearch.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      htsearch.cc
00004  *
00005  *      Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 /* FIXME: get rid of global vars */
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;                      // SC_*
00052         UINT search_mode_mask;          // SEARCHMODE_*
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  *      CLASS ht_fxbin_search_request
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  *      CLASS ht_regex_search_request
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  *      CLASS ht_regex_search_request
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  *      CLASS ht_expr_search_request
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  *      binary search
00462  */
00463 
00464 /* FIXME: put somewhere else */
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  *      CLASS ht_hexascii_search_form
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 /* ascii string */
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 /* ascii string label */
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 /* hex string */
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 /* hex string label */
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 /* range start */
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 /* range start label */
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 /* range end */
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 /* range end label */
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 /* options */
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  *      CLASS ht_evalstr_search_form
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 /* string */
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 /* string label */
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 /* hint */
00664 /*      c.x=0;
00665         c.y=2;
00666         c.w=b->w-2;
00667         c.h=1;
00668         ht_statictext *hint=new ht_statictext();
00669         hint->init(&c, "(example: \"hello\\n\\0\\077\\xd\" 'ho',011b,66o)", 0);
00670         insert(hint);*/
00671 
00672 /* range start */
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 /* range start label */
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 /* range end */
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 /* range end label */
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 /* options */
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  *      CLASS ht_vregex_search_form
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 /* string */
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 /* string label */
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 /* range start */
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 /* range start label */
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 /* range end */
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 /* range end label */
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 /* options */
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  *      CLASS ht_expr_search_form
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 /* string */
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 /* string label */
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 /* hint */
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 /* range start */
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 /* range start label */
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 /* range end */
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 /* range end label */
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 /* options */
00858 /*      c.w=35;
00859         c.y=8;
00860         c.h=2;
00861         ht_string_list *opts=new ht_string_list();
00862         opts->init();
00863         option_boxes=new ht_checkboxes();
00864         option_boxes->init(&c, opts);
00865         ht_checkboxes_data d;
00866         d.state=options;
00867         option_boxes->databuf_set(&d);
00868         insert(option_boxes);*/
00869 }
00870 
00871 /*
00872  *      CLASS ht_replace_hexascii_search_form
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 /* ascii string */
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 /* ascii string label */
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 /* hex string */
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 /* hex string label */
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 /* create history entry */
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 /* create request */
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 /* create history entry */
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 /* search */
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 /* grow */
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 /* shrink */
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  *      CLASS ht_search_dialog
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  *      CLASS ht_replace_dialog
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 //              focus(replace_mode_xgroup);
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 //      focus(rmodes[rmodeidx].view);
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                 /* create result */
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  

Generated on Fri May 7 21:15:37 2004 by doxygen 1.3.5