00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "htformat.h"
00022 #include "htsearch.h"
00023
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <time.h>
00027
00028 #include "blockop.h"
00029 #include "cmds.h"
00030 #include "htapp.h"
00031 #include "htatom.h"
00032 #include "htclipboard.h"
00033 #include "htctrl.h"
00034 #include "htendian.h"
00035 #include "hteval.h"
00036 #include "hthist.h"
00037 #include "htiobox.h"
00038 #include "htkeyb.h"
00039 #include "htpal.h"
00040 #include "httag.h"
00041 #include "textedit.h"
00042 #include "textfile.h"
00043 #include "process.h"
00044 #include "snprintf.h"
00045 #include "tools.h"
00046
00047 extern "C" {
00048 #include "evalx.h"
00049 #include "regex.h"
00050 }
00051
00052
00053
00054
00055
00056 void clear_line_id(LINE_ID *l)
00057 {
00058 l->id1 = 0;
00059 l->id2 = 0;
00060 l->id3 = 0;
00061 l->id4 = 0;
00062 l->id5 = 0;
00063 }
00064
00065 bool compeq_line_id(const LINE_ID &a, const LINE_ID &b)
00066 {
00067 return ((a.id1 == b.id1) && (a.id2 == b.id2)
00068 && (a.id3 == b.id3) && (a.id4 == b.id4)
00069 && (a.id5 == b.id5));
00070 }
00071
00072
00073
00074
00075
00076
00077 ht_search_request::ht_search_request(UINT _search_class, UINT _type, UINT _flags)
00078 {
00079 search_class=_search_class;
00080 type=_type;
00081 flags=_flags;
00082 }
00083
00084
00085
00086
00087
00088 ht_search_result::ht_search_result(UINT _search_class)
00089 {
00090 search_class=_search_class;
00091 }
00092
00093
00094
00095
00096
00097
00098 ht_physical_search_result::ht_physical_search_result() :
00099 ht_search_result(SC_PHYSICAL)
00100 {
00101 }
00102
00103
00104
00105
00106
00107
00108 ht_visual_search_result::ht_visual_search_result() :
00109 ht_search_result(SC_VISUAL)
00110 {
00111 }
00112
00113
00114
00115
00116
00117 void ht_format_group::init(bounds *b, int options, const char *desc, ht_streamfile *f, bool own_f, bool editable_f, format_viewer_if **i, ht_format_group *format_group)
00118 {
00119 ht_format_viewer::init(b, desc, 0, f, format_group);
00120 VIEW_DEBUG_NAME("ht_format_group");
00121
00122 xgroup=new ht_xgroup();
00123 xgroup->init(b, options, desc);
00124 xgroup->group=group;
00125
00126 format_views=new ht_clist();
00127 format_views->init();
00128
00129 own_file=own_f;
00130 editable_file=editable_f;
00131 if (i) init_ifs(i);
00132 }
00133
00134 void ht_format_group::done()
00135 {
00136 done_ifs();
00137
00138 format_views->destroy();
00139 delete format_views;
00140
00141 xgroup->done();
00142 delete xgroup;
00143
00144 ht_format_viewer::done();
00145
00146 if (own_file && file) {
00147 file->done();
00148 delete file;
00149 }
00150 }
00151
00152 int ht_format_group::childcount()
00153 {
00154 return xgroup->childcount();
00155 }
00156
00157 bool ht_format_group::done_if(format_viewer_if *i, ht_view *v)
00158 {
00159 remove(v);
00160 if (i->done) i->done(v); else {
00161 v->done();
00162 delete v;
00163 }
00164 return true;
00165 }
00166
00167 void ht_format_group::done_ifs()
00168 {
00169 int j=0;
00170 while (1) {
00171 ht_format_viewer_entry *e=(ht_format_viewer_entry*)format_views->get(j);
00172 if (!(e && e->instance)) break;
00173 done_if(e->interface, e->instance);
00174 j++;
00175 }
00176 }
00177
00178 bool ht_format_group::edit()
00179 {
00180 return (file->get_access_mode() & FAM_WRITE);
00181 }
00182
00183 int ht_format_group::focus(ht_view *view)
00184 {
00185 int r=ht_format_viewer::focus(view);
00186 if (!r) r=xgroup->focus(view);
00187 return r;
00188 }
00189
00190 char *ht_format_group::func(UINT i, bool execute)
00191 {
00192 return ht_format_viewer::func(i, execute);
00193 }
00194
00195 void ht_format_group::getbounds(bounds *b)
00196 {
00197 xgroup->getbounds(b);
00198 }
00199
00200 void *ht_format_group::get_shared_data()
00201 {
00202 return shared_data;
00203 }
00204
00205 ht_view *ht_format_group::getfirstchild()
00206 {
00207 return xgroup->getfirstchild();
00208 }
00209
00210 ht_view *ht_format_group::getselected()
00211 {
00212 return xgroup->getselected();
00213 }
00214
00215 void ht_format_group::get_pindicator_str(char *buf)
00216 {
00217 ht_view *c=xgroup->current;
00218 if (c && (c->options & VO_FORMAT_VIEW)) {
00219 ((ht_format_viewer*)c)->get_pindicator_str(buf);
00220 } else {
00221 *buf=0;
00222 }
00223 }
00224
00225 bool ht_format_group::get_hscrollbar_pos(int *pstart, int *psize)
00226 {
00227 ht_view *c=xgroup->current;
00228 if (c && (c->options & VO_FORMAT_VIEW)) {
00229 return ((ht_format_viewer*)c)->get_hscrollbar_pos(pstart, psize);
00230 }
00231 return false;
00232 }
00233
00234 bool ht_format_group::get_vscrollbar_pos(int *pstart, int *psize)
00235 {
00236 ht_view *c=xgroup->current;
00237 if (c && (c->options & VO_FORMAT_VIEW)) {
00238 return ((ht_format_viewer*)c)->get_vscrollbar_pos(pstart, psize);
00239 }
00240 return false;
00241 }
00242
00243 void ht_format_group::handlemsg(htmsg *msg)
00244 {
00245 switch (msg->msg) {
00246 case msg_keypressed: {
00247 int i=0;
00248 switch (msg->data1.integer) {
00249 case K_F12: i++;
00250 case K_F11: i++;
00251 case K_F10: i++;
00252 case K_F9: i++;
00253 case K_F8: i++;
00254 case K_F7: i++;
00255 case K_F6: i++;
00256 case K_F5: i++;
00257 case K_F4: i++;
00258 case K_F3: i++;
00259 case K_F2: i++;
00260 case K_F1: {
00261 i++;
00262 htmsg m;
00263 m.msg=msg_funcquery;
00264 m.type=mt_empty;
00265 m.data1.integer=i;
00266 sendmsg(&m);
00267 if (m.msg==msg_retval) {
00268 sendmsg(msg_funcexec, i);
00269 clearmsg(msg);
00270 return;
00271 }
00272 break;
00273 }
00274 }
00275 break;
00276 }
00277 }
00278 ht_format_viewer::handlemsg(msg);
00279 xgroup->handlemsg(msg);
00280 switch (msg->msg) {
00281 case msg_funcexec:
00282 if (func(msg->data1.integer, 1)) {
00283 clearmsg(msg);
00284 return;
00285 }
00286 break;
00287 case msg_funcquery: {
00288 char *s=func(msg->data1.integer, 0);
00289 if (s) {
00290 msg->msg=msg_retval;
00291 msg->data1.str=s;
00292 }
00293 break;
00294 }
00295 }
00296 }
00297
00298 bool ht_format_group::init_if(format_viewer_if *i)
00299 {
00300 bounds b;
00301 getbounds(&b);
00302 b.x=0;
00303 b.y=0;
00304 bool r=0;
00305 ht_view *v=0;
00306
00307
00308
00309
00310
00311
00312 if (i->init) {
00313 v=i->init(&b, file, this);
00314 if (v) {
00315 v->sendmsg(msg_complete_init, 0);
00316 insert(v);
00317 r=1;
00318 }
00319 }
00320 ht_format_viewer_entry *e=new ht_format_viewer_entry();
00321 e->interface=i;
00322 e->instance=v;
00323 format_views->insert(e);
00324 return r;
00325 }
00326
00327 void ht_format_group::init_ifs(format_viewer_if **ifs)
00328 {
00329 format_viewer_if **i=ifs;
00330 while (*i) {
00331 init_if(*i);
00332 i++;
00333 }
00334 ifs=i;
00335 }
00336
00337 void ht_format_group::insert(ht_view *view)
00338 {
00339 xgroup->insert(view);
00340 }
00341
00342 void ht_format_group::move(int rx, int ry)
00343 {
00344 ht_format_viewer::move(rx, ry);
00345 xgroup->move(rx, ry);
00346 }
00347
00348 void ht_format_group::receivefocus()
00349 {
00350 xgroup->receivefocus();
00351 }
00352
00353 void ht_format_group::redraw()
00354 {
00355 xgroup->redraw();
00356 }
00357
00358 void ht_format_group::releasefocus()
00359 {
00360 xgroup->releasefocus();
00361 }
00362
00363 void ht_format_group::remove(ht_view *view)
00364 {
00365 xgroup->remove(view);
00366 }
00367
00368 void ht_format_group::resize(int rw, int rh)
00369 {
00370 ht_format_viewer::resize(rw, rh);
00371 xgroup->resize(rw, rh);
00372 }
00373
00374 void ht_format_group::setgroup(ht_group *_group)
00375 {
00376 xgroup->setgroup(_group);
00377 }
00378
00379
00380
00381
00382
00383 void ht_viewer::init(bounds *b, const char *desc, UINT c)
00384 {
00385 ht_view::init(b, VO_OWNBUFFER | VO_BROWSABLE | VO_SELECTABLE | VO_MOVE | VO_RESIZE, desc);
00386 caps = c;
00387
00388 growmode = MK_GM(GMH_FIT, GMV_FIT);
00389 }
00390
00391 void ht_viewer::done()
00392 {
00393 ht_view::done();
00394 }
00395
00396 char *ht_viewer::func(UINT i, bool execute)
00397 {
00398 return 0;
00399 }
00400
00401 void ht_viewer::handlemsg(htmsg *msg)
00402 {
00403 int i=0;
00404 switch (msg->msg) {
00405 case msg_keypressed: {
00406 switch (msg->data1.integer) {
00407 case K_F12: i++;
00408 case K_F11: i++;
00409 case K_F10: i++;
00410 case K_F9: i++;
00411 case K_F8: i++;
00412 case K_F7: i++;
00413 case K_F6: i++;
00414 case K_F5: i++;
00415 case K_F4: i++;
00416 case K_F3: i++;
00417 case K_F2: i++;
00418 case K_F1: {
00419 i++;
00420 htmsg m;
00421 m.msg=msg_funcquery;
00422 m.type=mt_empty;
00423 m.data1.integer=i;
00424 sendmsg(&m);
00425 if (m.msg==msg_retval) {
00426 sendmsg(msg_funcexec, i);
00427 clearmsg(msg);
00428 return;
00429 }
00430 break;
00431 }
00432 }
00433 break;
00434 }
00435 case msg_funcexec:
00436 if (func(msg->data1.integer, 1)) {
00437 clearmsg(msg);
00438 return;
00439 }
00440 break;
00441 case msg_funcquery: {
00442 char *s=func(msg->data1.integer, 0);
00443 if (s) {
00444 msg->msg=msg_retval;
00445 msg->data1.str=s;
00446 }
00447 break;
00448 }
00449 }
00450 ht_view::handlemsg(msg);
00451 }
00452
00453
00454
00455
00456
00457 void ht_format_viewer::init(bounds *b, const char *desc, UINT caps, ht_streamfile *f, ht_format_group *fg)
00458 {
00459 ht_viewer::init(b, desc, caps);
00460 options |= VO_FORMAT_VIEW;
00461 VIEW_DEBUG_NAME("ht_format_viewer");
00462 file = f;
00463 format_group = fg;
00464
00465 last_search_request = NULL;
00466
00467
00468
00469 }
00470
00471 void ht_format_viewer::done()
00472 {
00473 if (last_search_request) delete last_search_request;
00474
00475 ht_view::done();
00476 }
00477
00478 bool ht_format_viewer::pos_to_offset(viewer_pos pos, FILEOFS *ofs)
00479 {
00480 return false;
00481 }
00482
00483 void ht_format_viewer::clear_viewer_pos(viewer_pos *p)
00484 {
00485 }
00486
00487 bool ht_format_viewer::compeq_viewer_pos(viewer_pos *a, viewer_pos *b)
00488 {
00489 return false;
00490 }
00491
00492 bool ht_format_viewer::continue_search()
00493 {
00494 if (last_search_request) {
00495 ht_search_result *r = NULL;
00496 if (last_search_physical) {
00497 FILEOFS o, no;
00498 if (get_current_offset(&o)) {
00499 try {
00500 if (last_search_request->search_class==SC_PHYSICAL) {
00501 if (next_logical_offset(o, &no)) {
00502 r=psearch(last_search_request, no, last_search_end_ofs);
00503 }
00504 }
00505 } catch (ht_exception *e) {
00506 errorbox("error: %s", e->what());
00507 }
00508 }
00509 } else {
00510 viewer_pos a, na;
00511 if (get_current_pos(&a)) {
00512 try {
00513 if (last_search_request->search_class==SC_VISUAL) {
00514 if (next_logical_pos(a, &na)) {
00515 r=vsearch(last_search_request, na, last_search_end_pos);
00516 }
00517 }
00518 } catch (ht_exception *e) {
00519 errorbox("error: %s", e->what());
00520 }
00521 }
00522 }
00523
00524 if (r) return show_search_result(r);
00525 }
00526 return false;
00527 }
00528
00529 int ht_format_viewer::func_handler(eval_scalar *result, char *name, eval_scalarlist *params)
00530 {
00531 return 0;
00532 }
00533
00534 int ht_format_viewer::symbol_handler(eval_scalar *result, char *name)
00535 {
00536 return 0;
00537 }
00538
00539 bool ht_format_viewer::get_current_offset(FILEOFS *ofs)
00540 {
00541 return false;
00542 }
00543
00544 bool ht_format_viewer::get_current_pos(viewer_pos *pos)
00545 {
00546 return false;
00547 }
00548
00549 bool ht_format_viewer::get_current_real_offset(FILEOFS *ofs)
00550 {
00551 return get_current_offset(ofs);
00552 }
00553
00554 ht_streamfile *ht_format_viewer::get_file()
00555 {
00556 return file;
00557 }
00558
00559 void ht_format_viewer::get_pindicator_str(char *buf)
00560 {
00561 *buf=0;
00562 }
00563
00564 bool ht_format_viewer::get_hscrollbar_pos(int *pstart, int *psize)
00565 {
00566 return false;
00567 }
00568
00569 bool ht_format_viewer::get_vscrollbar_pos(int *pstart, int *psize)
00570 {
00571 return false;
00572 }
00573
00574 bool ht_format_viewer::goto_offset(FILEOFS ofs, bool save_vstate)
00575 {
00576 return false;
00577 }
00578
00579 bool ht_format_viewer::goto_pos(viewer_pos pos, bool save_vstate)
00580 {
00581 return false;
00582 }
00583
00584 void ht_format_viewer::handlemsg(htmsg *msg)
00585 {
00586 switch (msg->msg) {
00587 case msg_goto_offset: {
00588 FILEOFS o = (FILEOFS)msg->data1.integer;
00589 if (goto_offset(o, false)) {
00590 clearmsg(msg);
00591 return;
00592 }
00593 break;
00594 }
00595 case msg_vstate_restore:
00596 vstate_restore((Object*)msg->data1.ptr);
00597 clearmsg(msg);
00598 return;
00599 case cmd_file_truncate: {
00600 ht_streamfile *f = (ht_streamfile*)msg->data1.ptr;
00601 FILEOFS o = (FILEOFS)msg->data2.integer;
00602 if (file == f) {
00603 ht_format_loc loc;
00604 loc_enum_start();
00605 while (loc_enum_next(&loc)) {
00606 if (o < loc.start+loc.length) {
00607 if (confirmbox("truncating at %08x will destroy format '%s', continue ? \n(format ranges from %08x to %08x)", o, loc.name, loc.start, loc.start+loc.length) != button_yes) {
00608 clearmsg(msg);
00609 return;
00610 }
00611 break;
00612 }
00613 }
00614 }
00615 break;
00616 }
00617 case cmd_edit_mode_i: {
00618 if (file) {
00619 if (file->set_access_mode(FAM_READ | FAM_WRITE)) {
00620 htmsg m;
00621 m.msg = cmd_edit_mode;
00622 m.type = mt_broadcast;
00623 sendmsg(&m);
00624 } else errorbox("can't open file %s in write mode ! (error %08x)", file->get_filename(), file->get_error());
00625 }
00626 clearmsg(msg);
00627 return;
00628 }
00629 case cmd_view_mode_i:
00630 if (file ) {
00631 UINT size = file->get_size();
00632 file->cntl(FCNTL_MODS_INVD);
00633 if (file->set_access_mode(FAM_READ)) {
00634 htmsg m;
00635 m.msg = cmd_view_mode;
00636 m.type = mt_broadcast;
00637 sendmsg(&m);
00638 } else errorbox("can't (re)open file %s in read mode ! (error %08x)", file->get_filename(), file->get_error());
00639 if (size != file->get_size()) {
00640 htmsg m;
00641 m.msg = msg_filesize_changed;
00642 m.type = mt_broadcast;
00643 sendmsg(&m);
00644 }
00645 }
00646 clearmsg(msg);
00647 return;
00648 }
00649 ht_viewer::handlemsg(msg);
00650 }
00651
00652 void ht_format_viewer::loc_enum_start()
00653 {
00654 }
00655
00656 bool ht_format_viewer::loc_enum_next(ht_format_loc *loc)
00657 {
00658 return false;
00659 }
00660
00661 bool ht_format_viewer::next_logical_pos(viewer_pos pos, viewer_pos *npos)
00662 {
00663 return false;
00664 }
00665
00666 bool ht_format_viewer::next_logical_offset(FILEOFS ofs, FILEOFS *nofs)
00667 {
00668 return false;
00669 }
00670
00671 bool ht_format_viewer::offset_to_pos(FILEOFS ofs, viewer_pos *pos)
00672 {
00673 return false;
00674 }
00675
00676 bool ht_format_viewer::vstate_save()
00677 {
00678 Object *vs = vstate_create();
00679 if (vs) {
00680 htmsg m;
00681 m.msg = msg_vstate_save;
00682 m.type = mt_empty;
00683 m.data1.ptr = vs;
00684 m.data2.ptr = this;
00685 app->sendmsg(&m);
00686 return true;
00687 }
00688 return false;
00689 }
00690
00691 UINT ht_format_viewer::pread(FILEOFS ofs, void *buf, UINT size)
00692 {
00693 if (file->seek(ofs)==0) {
00694 return file->read(buf, size);
00695 }
00696 return 0;
00697 }
00698
00699 ht_search_result *ht_format_viewer::psearch(ht_search_request *search, FILEOFS start, FILEOFS end)
00700 {
00701 return 0;
00702 }
00703
00704 void ht_format_viewer::pselect_add(FILEOFS start, FILEOFS end)
00705 {
00706 }
00707
00708 void ht_format_viewer::pselect_get(FILEOFS *start, FILEOFS *end)
00709 {
00710 }
00711
00712 void ht_format_viewer::pselect_set(FILEOFS start, FILEOFS end)
00713 {
00714 }
00715
00716 UINT ht_format_viewer::pwrite(FILEOFS ofs, void *buf, UINT size)
00717 {
00718 if (file->seek(ofs)==0) {
00719 sendmsg(msg_file_changed);
00720 return file->write(buf, size);
00721 }
00722 return 0;
00723 }
00724
00725 bool ht_format_viewer::qword_to_offset(qword q, FILEOFS *ofs)
00726 {
00727 return false;
00728 }
00729
00730 bool ht_format_viewer::qword_to_pos(qword q, viewer_pos *pos)
00731 {
00732 return false;
00733 }
00734
00735 bool ht_format_viewer::show_search_result(ht_search_result *r)
00736 {
00737 switch (r->search_class) {
00738 case SC_PHYSICAL: {
00739 ht_physical_search_result *s=(ht_physical_search_result*)r;
00740 if (!goto_offset(s->offset, this)) return false;
00741 pselect_set(s->offset, s->offset+s->size);
00742 return true;
00743 }
00744 case SC_VISUAL: {
00745 ht_visual_search_result *s=(ht_visual_search_result*)r;
00746 return goto_pos(s->pos, this);
00747 }
00748 }
00749 return false;
00750 }
00751
00752 static int format_viewer_func_handler(eval_scalar *result, char *name, eval_scalarlist *params)
00753 {
00754 ht_format_viewer *viewer = (ht_format_viewer*)eval_get_context();
00755 return viewer->func_handler(result, name, params);
00756 }
00757
00758 static int format_viewer_symbol_handler(eval_scalar *result, char *name)
00759 {
00760 ht_format_viewer *viewer = (ht_format_viewer*)eval_get_context();
00761 return viewer->symbol_handler(result, name);
00762 }
00763
00764 bool ht_format_viewer::string_to_qword(char *string, qword *q)
00765 {
00766 eval_scalar r;
00767 if (eval(&r, string, format_viewer_func_handler, format_viewer_symbol_handler, this)) {
00768 eval_int i;
00769 scalar_context_int(&r, &i);
00770 scalar_destroy(&r);
00771 *q = i.value;
00772 return true;
00773 } else {
00774 char *s;
00775 int p;
00776 get_eval_error(&s, &p);
00777 ht_snprintf(globalerror, GLOBAL_ERROR_SIZE, "%s at pos %d", s, p);
00778 }
00779 return false;
00780 }
00781
00782 bool ht_format_viewer::string_to_pos(char *string, viewer_pos *pos)
00783 {
00784 qword q;
00785 if (!string_to_qword(string, &q)) return false;
00786 return qword_to_pos(q, pos);
00787 }
00788
00789 bool ht_format_viewer::string_to_offset(char *string, FILEOFS *ofs)
00790 {
00791 qword q;
00792 if (!string_to_qword(string, &q)) return false;
00793 return qword_to_offset(q, ofs);
00794 }
00795
00796 Object *ht_format_viewer::vstate_create()
00797 {
00798 return NULL;
00799 }
00800
00801 void ht_format_viewer::vstate_restore(Object *view_state)
00802 {
00803 }
00804
00805 UINT ht_format_viewer::vread(viewer_pos pos, void *buf, UINT size)
00806 {
00807 FILEOFS o;
00808 if (pos_to_offset(pos, &o)) {
00809 return pread(o, buf, size);
00810 }
00811 return 0;
00812 }
00813
00814 ht_search_result *ht_format_viewer::vsearch(ht_search_request *search, viewer_pos start, viewer_pos end)
00815 {
00816 return NULL;
00817 }
00818
00819 void ht_format_viewer::vselect_add(viewer_pos start, viewer_pos end)
00820 {
00821 FILEOFS so, eo;
00822 if (pos_to_offset(start, &so) && pos_to_offset(end, &eo)) {
00823 return pselect_add(so, eo);
00824 }
00825 }
00826
00827 void ht_format_viewer::vselect_get(viewer_pos *start, viewer_pos *end)
00828 {
00829 HT_ERROR("NYI!");
00830 }
00831
00832 void ht_format_viewer::vselect_set(viewer_pos start, viewer_pos end)
00833 {
00834 FILEOFS so, eo;
00835 if (pos_to_offset(start, &so) && pos_to_offset(end, &eo)) {
00836 return pselect_set(so, eo);
00837 }
00838 }
00839
00840 UINT ht_format_viewer::vwrite(viewer_pos pos, void *buf, UINT size)
00841 {
00842 FILEOFS o;
00843 if (pos_to_offset(pos, &o)) {
00844 return pwrite(o, buf, size);
00845 }
00846 return 0;
00847 }
00848
00849
00850
00851
00852
00853 class ht_uformat_viewer_vstate: public Object {
00854 public:
00855 int edit;
00856 ht_sub *first_sub, *last_sub;
00857
00858 uformat_viewer_pos top;
00859
00860 uformat_viewer_pos cursor;
00861 int cursor_state;
00862 int cursor_ypos;
00863
00864 FILEOFS sel_start;
00865 FILEOFS sel_end;
00866 };
00867
00868 void ht_uformat_viewer::init(bounds *b, const char *desc, int caps, ht_streamfile *file, ht_format_group *format_group)
00869 {
00870 tagpal.data=NULL;
00871 tagpal.size=0;
00872 ht_format_viewer::init(b, desc, caps, file, format_group);
00873 VIEW_DEBUG_NAME("ht_uformat_view");
00874 first_sub=0;
00875 last_sub=0;
00876 clear_viewer_pos(&top);
00877 clear_viewer_pos(&cursor);
00878 xscroll=0;
00879 cursor_ypos=0;
00880 cursor_visual_length=0;
00881 cursor_visual_xpos=0;
00882 cursor_select=0;
00883 cursor_select_start=0xffffffff;
00884 sel_start=0;
00885 sel_end=0;
00886 isdirty_cursor_line=0;
00887
00888 search_caps=SEARCHMODE_VREGEX;
00889
00890 uf_initialized=0;
00891 }
00892
00893 void ht_uformat_viewer::done()
00894 {
00895 edit_end();
00896 clear_subs();
00897 free(tagpal.data);
00898 ht_format_viewer::done();
00899 }
00900
00901 int ht_uformat_viewer::address_input(const char *title, char *result, int limit, dword histid)
00902 {
00903 bounds b;
00904 app->getbounds(&b);
00905 b.x = (b.w - 60) / 2,
00906 b.y = (b.h - 8) / 2;
00907 b.w = 60;
00908 b.h = 8;
00909
00910 ht_dialog *dialog=new ht_dialog();
00911 dialog->init(&b, title, FS_KILLER | FS_TITLE | FS_MOVE | FS_RESIZE);
00912
00913 ht_strinputfield *input;
00914 char *label = "~Address";
00915
00916 bounds b2;
00917 b2.x = 3 + strlen(label);
00918 b2.y = 1;
00919 b2.w = b.w - 3 - b2.x;
00920 b2.h = 1;
00921
00922 ht_clist *hist = 0;
00923 if (histid) hist = (ht_clist*)find_atom(histid);
00924 input = new ht_strinputfield();
00925 input->init(&b2, limit, hist);
00926 ht_inputfield_data d;
00927 d.text = (byte*)result;
00928 d.textlen = strlen((char*)d.text);
00929 input->databuf_set(&d, sizeof d);
00930 dialog->insert(input);
00931
00932 if (label) {
00933 b2.x = 1;
00934 b2.y = 1;
00935 b2.w = 3 + strlen(label) - b2.x;
00936 b2.h = 1;
00937
00938 ht_label *lab = new ht_label();
00939 lab->init(&b2, label, input);
00940 dialog->insert(lab);
00941 }
00942
00943 b2.x = b.w - 45;
00944 b2.y = b.h - 5;
00945 b2.w = 10;
00946 b2.h = 2;
00947
00948 ht_button *bok = new ht_button();
00949 bok->init(&b2, "O~k", button_ok);
00950 dialog->insert(bok);
00951
00952 b2.x += 12;
00953
00954 ht_button *bcancel = new ht_button();
00955 bcancel->init(&b2, "~Cancel", button_cancel);
00956 dialog->insert(bcancel);
00957
00958 b2.x += 12;
00959 b2.w = 14;
00960
00961 ht_button *bhelp = new ht_button();
00962 bhelp->init(&b2, "~Functions", 100);
00963 dialog->insert(bhelp);
00964
00965 int r;
00966 bool run = true;
00967 int retval = button_cancel;
00968 while (run && (r = dialog->run(0)) != button_cancel) {
00969 switch (r) {
00970 case 100: {
00971 dialog_eval_help(format_viewer_func_handler, format_viewer_symbol_handler, this);
00972 break;
00973 }
00974 case button_ok: {
00975 int dsize = input->datasize();
00976 ht_inputfield_data *data = (ht_inputfield_data*)malloc(dsize);
00977 input->databuf_get(data, dsize);
00978 bin2str(result, data->text, data->textlen);
00979 delete data;
00980 if (hist) insert_history_entry(hist, result, 0);
00981 run = false;
00982 retval = button_ok;
00983 break;
00984 }
00985 }
00986 }
00987
00988 dialog->done();
00989 delete dialog;
00990 return retval;
00991 }
00992
00993 void ht_uformat_viewer::adjust_cursor_group()
00994 {
00995 cursorline_get();
00996 int g=tag_count_groups(cursor_line);
00997 if (cursor.tag_group>=g) cursor.tag_group=0;
00998 }
00999
01000 void ht_uformat_viewer::adjust_cursor_idx()
01001 {
01002 cursorline_get();
01003 int c = tag_count_selectable_tags_in_group(cursor_line, cursor.tag_group);
01004 if (cursor.tag_idx > c-1) cursor.tag_idx = c-1;
01005 }
01006
01007 int ht_uformat_viewer::center_view(viewer_pos p)
01008 {
01009 top = p.u;
01010 int r = prev_line(&top, size.h/2);
01011 cursorline_dirty();
01012 return r;
01013 }
01014
01015 void ht_uformat_viewer::check_cursor_visibility()
01016 {
01017 if (cursor_state != cursor_state_disabled) {
01018 if ((cursor_ypos < 0) || (cursor_ypos >= size.h)) {
01019 cursor_state=cursor_state_invisible;
01020 } else {
01021 cursor_state=cursor_state_visible;
01022 }
01023 }
01024 }
01025
01026 void ht_uformat_viewer::complete_init()
01027 {
01028 if (uf_initialized) return;
01029 cursor_state=cursor_state_disabled;
01030 if (!first_sub) {
01031 uf_initialized=1;
01032 return;
01033 }
01034
01035 clear_viewer_pos(&top);
01036 top.sub = first_sub;
01037 top.sub->first_line_id(&top.line_id);
01038
01039 cursor_tag_micropos=0;
01040
01041 uformat_viewer_pos p;
01042 clear_viewer_pos(&p);
01043 p.sub = first_sub;
01044 p.sub->first_line_id(&p.line_id);
01045 char line[1024];
01046 cursor_ypos--;
01047 do {
01048 cursor_ypos++;
01049 if (!p.sub->getline(line, p.line_id)) break;
01050 if (tag_count_selectable_tags(line)) {
01051 if (cursor_ypos<size.h) {
01052 cursor_state=cursor_state_visible;
01053 } else {
01054 cursor_state=cursor_state_invisible;
01055 cursor_ypos=-1;
01056 }
01057 break;
01058 }
01059 } while ((next_line(&p, 1)) && (cursor_ypos<size.h));
01060 p.tag_idx = 0;
01061 p.tag_group = 0;
01062 if (cursor_state == cursor_state_disabled) {
01063 p.sub = first_sub;
01064 p.sub->first_line_id(&p.line_id);
01065 if (p.sub->getline(line, p.line_id)) {
01066 cursor_ypos = -1;
01067 cursor_state = cursor_state_invisible;
01068 }
01069 }
01070 cursor = p;
01071
01072 cursorline_dirty();
01073 cursorline_get();
01074
01075 update_visual_info();
01076
01077 update_misc_info();
01078
01079 uf_initialized=1;
01080 }
01081
01082 int ht_uformat_viewer::cursor_left()
01083 {
01084 if (cursor.tag_idx) {
01085 cursor.tag_idx--;
01086 update_visual_info();
01087 update_misc_info();
01088 return 1;
01089 } else {
01090 if (cursor_up(1)) {
01091 cursor_end();
01092 return 1;
01093 }
01094 }
01095 return 0;
01096 }
01097
01098 int ht_uformat_viewer::cursor_right()
01099 {
01100 cursorline_get();
01101 if (cursor.tag_idx < tag_count_selectable_tags_in_group(cursor_line, cursor.tag_group)-1) {
01102 cursor.tag_idx++;
01103 update_visual_info();
01104 update_misc_info();
01105 return 1;
01106 } else {
01107 if (cursor_down(1)) {
01108 cursor_home();
01109 return 1;
01110 }
01111 }
01112 return 0;
01113 }
01114
01115 int ht_uformat_viewer::cursor_up(int n)
01116 {
01117 switch (cursor_state) {
01118 case cursor_state_invisible:
01119 case cursor_state_visible: {
01120 if ((n==1) && (cursor_state==cursor_state_visible)) {
01121 int r = 0;
01122 uformat_viewer_pos c;
01123 clear_viewer_pos(&c);
01124 c = cursor;
01125 char c_line[1024];
01126 int c_ypos=cursor_ypos;
01127 int c_tag_idx=cursor.tag_idx;
01128 int c_tag_group=cursor.tag_group;
01129 int d_tag_group=cursor.tag_group;
01130
01131 while (prev_line(&c, 1) && (c_ypos>=0)) {
01132 c_ypos--;
01133 c.sub->getline(c_line, c.line_id);
01134 int g=tag_count_groups(c_line);
01135 if (d_tag_group<g) c_tag_group=d_tag_group;
01136 int s;
01137 if (c_tag_group>=g) {
01138 c_tag_group=g-1;
01139 s=tag_count_selectable_tags_in_group(c_line, c_tag_group);
01140 if (s) {
01141 c_tag_idx=s-1;
01142 r = 1;
01143 break;
01144 }
01145 } else {
01146 s=tag_count_selectable_tags_in_group(c_line, c_tag_group);
01147 if (s) {
01148 if (c_tag_idx>=s) c_tag_idx=s-1;
01149 r = 1;
01150 break;
01151 }
01152 }
01153 }
01154 if (r) {
01155 cursor = c;
01156 memmove(cursor_line, c_line, sizeof cursor_line);
01157 cursorline_dirty();
01158 cursor_ypos=c_ypos;
01159 cursor.tag_idx=c_tag_idx;
01160 cursor.tag_group=c_tag_group;
01161 if (cursor_ypos<=-1) scroll_up(-cursor_ypos);
01162 update_misc_info();
01163 update_visual_info();
01164 if (edit()) update_micropos();
01165 } else scroll_up(n);
01166 return r;
01167 } else {
01168 int r=0;
01169 char c_line[1024];
01170 int c_tag_idx=cursor.tag_idx;
01171 int c_tag_group=cursor.tag_group;
01172 int d_tag_group=cursor.tag_group;
01173 uformat_viewer_pos c;
01174 int c_ypos;
01175 if (cursor_state==cursor_state_invisible) {
01176 c = top;
01177 c_ypos=0;
01178 } else {
01179 c = cursor;
01180 c_ypos=cursor_ypos;
01181 }
01182 int nc=prev_line(&c, n);
01183 c_ypos-=nc;
01184
01185 while (nc--) {
01186 c.sub->getline(c_line, c.line_id);
01187 int g=tag_count_groups(c_line);
01188 if (d_tag_group<g) c_tag_group=d_tag_group;
01189 int s;
01190 if (c_tag_group>=g) {
01191 c_tag_group=g-1;
01192 s=tag_count_selectable_tags_in_group(c_line, c_tag_group);
01193 if (s) {
01194 c_tag_idx=s-1;
01195 r=1;
01196 break;
01197 }
01198 }
01199 s=tag_count_selectable_tags_in_group(c_line, c_tag_group);
01200 if (s) {
01201 if (c_tag_idx>=s) c_tag_idx=s-1;
01202 r=1;
01203 break;
01204 }
01205 if (!next_line(&c, 1)) break;
01206 c_ypos++;
01207 }
01208 if (r) {
01209 cursor = c;
01210 memmove(cursor_line, c_line, sizeof cursor_line);
01211 cursorline_dirty();
01212 cursor_ypos=c_ypos;
01213 cursor.tag_idx=c_tag_idx;
01214 cursor.tag_group=c_tag_group;
01215 if (-cursor_ypos+n-nc-1>0) scroll_up(-cursor_ypos+n-nc-1);
01216 update_misc_info();
01217 update_visual_info();
01218 if (edit()) update_micropos();
01219 } else {
01220 if (cursor_state==cursor_state_invisible) cursor_ypos=-0x80000000;
01221 scroll_up(n);
01222 }
01223
01224 return 1;
01225 }
01226 }
01227 case cursor_state_disabled:
01228
01229
01230 break;
01231 }
01232 return 0;
01233 }
01234
01235 int ht_uformat_viewer::cursor_down(int n)
01236 {
01237 switch (cursor_state) {
01238 case cursor_state_invisible:
01239 case cursor_state_visible: {
01240 if ((n==1) && (cursor_state==cursor_state_visible)) {
01241 int r=0;
01242 uformat_viewer_pos c;
01243 c = cursor;
01244 char c_line[1024];
01245 int c_ypos=cursor_ypos;
01246 int c_tag_idx=cursor.tag_idx;
01247 int c_tag_group=cursor.tag_group;
01248 int d_tag_group=cursor.tag_group;
01249 int nls;
01250
01251 while ((nls=next_line(&c, 1)) && (c_ypos<=size.h-1)) {
01252 c_ypos++;
01253 c.sub->getline(c_line, c.line_id);
01254 int g=tag_count_groups(c_line);
01255 if (d_tag_group<g) c_tag_group=d_tag_group;
01256 int s;
01257 if (c_tag_group>=g) {
01258 c_tag_group=g-1;
01259 s=tag_count_selectable_tags_in_group(c_line, c_tag_group);
01260 if (s) {
01261 c_tag_idx=s-1;
01262 r=1;
01263 break;
01264 }
01265 }
01266 s=tag_count_selectable_tags_in_group(c_line, c_tag_group);
01267 if (s) {
01268 if (c_tag_idx>=s) c_tag_idx=s-1;
01269 r=1;
01270 break;
01271 }
01272 }
01273 if (r) {
01274 cursor = c;
01275 memmove(cursor_line, c_line, sizeof cursor_line);
01276 cursorline_dirty();
01277 cursor_ypos=c_ypos;
01278 cursor.tag_idx=c_tag_idx;
01279 cursor.tag_group=c_tag_group;
01280 if (cursor_ypos>=size.h) scroll_down(cursor_ypos-size.h+1);
01281 update_misc_info();
01282 update_visual_info();
01283 if (edit()) update_micropos();
01284 } else if (nls) scroll_down(1);
01285 return r;
01286 } else {
01287 int r=0;
01288 char c_line[1024];
01289 int c_tag_idx=cursor.tag_idx;
01290 int c_tag_group=cursor.tag_group;
01291 int d_tag_group=cursor.tag_group;
01292 uformat_viewer_pos c;
01293 int c_ypos;
01294 if (cursor_state==cursor_state_invisible) {
01295 c = top;
01296 c_ypos = next_line(&c, size.h-1);
01297 } else {
01298 c = cursor;
01299 c_ypos = cursor_ypos;
01300 }
01301
01302 int nc=next_line(&c, n);
01303 int onc=c_ypos+nc-size.h+1;
01304 c_ypos+=nc;
01305
01306 while (nc--) {
01307 c.sub->getline(c_line, c.line_id);
01308 int g=tag_count_groups(c_line);
01309 if (d_tag_group<g) c_tag_group=d_tag_group;
01310 int s;
01311 if (c_tag_group>=g) {
01312 c_tag_group=g-1;
01313 s=tag_count_selectable_tags_in_group(c_line, c_tag_group);
01314 if (s) {
01315 c_tag_idx=s-1;
01316 r=1;
01317 break;
01318 }
01319 } else {
01320 s=tag_count_selectable_tags_in_group(c_line, c_tag_group);
01321 if (s) {
01322 if (c_tag_idx>=s) c_tag_idx=s-1;
01323 r=1;
01324 break;
01325 }
01326 }
01327 if (nc) if (!prev_line(&c, 1)) break;
01328 c_ypos--;
01329 }
01330 if (r) {
01331 cursor = c;
01332 memmove(cursor_line, c_line, sizeof cursor_line);
01333 cursorline_dirty();
01334 cursor_ypos=c_ypos;
01335 cursor.tag_idx=c_tag_idx;
01336 cursor.tag_group=c_tag_group;
01337 if (cursor_ypos-size.h+1>0) scroll_down(cursor_ypos-size.h+1);
01338 update_misc_info();
01339 update_visual_info();
01340 if (edit()) update_micropos();
01341 } else if (onc>0) {
01342 if (cursor_state==cursor_state_invisible) cursor_ypos=-0x80000000;
01343 scroll_down(onc);
01344 }
01345
01346 return 1;
01347 }
01348 }
01349 case cursor_state_disabled:
01350
01351
01352 break;
01353 }
01354 return 0;
01355 }
01356
01357 int ht_uformat_viewer::cursor_home()
01358 {
01359 cursor.tag_idx=0;
01360 if (edit()) cursor_tag_micropos=0;
01361 update_visual_info();
01362 update_misc_info();
01363 return 1;
01364 }
01365
01366 int ht_uformat_viewer::cursor_end()
01367 {
01368 cursorline_get();
01369 int c = tag_count_selectable_tags_in_group(cursor_line, cursor.tag_group);
01370 cursor.tag_idx = c-1;
01371 if (edit()) {
01372 char *e=tag_get_selectable_tag(cursor_line, cursor.tag_idx, cursor.tag_group);
01373 if (e) cursor_tag_micropos=tag_get_microsize(e)-1;
01374 }
01375 update_visual_info();
01376 update_misc_info();
01377 return 1;
01378 }
01379
01380 void ht_uformat_viewer::cursor_tab()
01381 {
01382 cursor.tag_group++;
01383 adjust_cursor_group();
01384 }
01385
01386 void ht_uformat_viewer::cursorline_dirty()
01387 {
01388 isdirty_cursor_line=1;
01389 }
01390
01391 void ht_uformat_viewer::cursorline_get()
01392 {
01393 if (isdirty_cursor_line) {
01394 if (cursor.sub) cursor.sub->getline(cursor_line, cursor.line_id);
01395 isdirty_cursor_line=0;
01396 }
01397 }
01398
01399 int ht_uformat_viewer::cursormicroedit_forward()
01400 {
01401 cursorline_get();
01402 uformat_viewer_pos p;
01403 p = top;
01404 p.tag_group = cursor.tag_group;
01405 UINT cursor_tag_bitidx = 0;
01406
01407 cursorline_get();
01408 char *e=tag_get_selectable_tag(cursor_line, cursor.tag_idx, cursor.tag_group);
01409 if (e) {
01410 if (((byte*)e)[1] == HT_TAG_EDIT_BIT) {
01411 cursor_tag_bitidx = ((ht_tag_edit_bit*)e)->bitidx;
01412 }
01413 }
01414
01415 bool cursor_found = false;
01416 char c_line[1024];
01417 for (int y=0; y<size.h+16; y++) {
01418 if (!p.sub->getline(c_line, p.line_id)) break;
01419 int c=tag_count_selectable_tags_in_group(c_line, p.tag_group);
01420 while (p.tag_idx<c) {
01421 char *t=tag_get_selectable_tag(c_line, p.tag_idx, p.tag_group);
01422 if (t && (tag_get_class(t)==tag_class_edit)) {
01423 if (cursor_found) {
01424 cursor_tag_micropos=0;
01425 set_cursor(p);
01426 cursorline_dirty();
01427 update_misc_info();
01428 update_visual_info();
01429 return 1;
01430 } else if (tag_get_offset(t) == cursor_tag_offset) {
01431 if ( ( (((byte*)t)[1] == HT_TAG_EDIT_BIT) &&
01432 ( ((ht_tag_edit_bit*)t)->bitidx == cursor_tag_bitidx) ) ||
01433 (((byte*)t)[1] != HT_TAG_EDIT_BIT)) {
01434 cursor_found = true;
01435 char *t=tag_get_selectable_tag(c_line, p.tag_idx, p.tag_group);
01436 int s=tag_get_microsize(t);
01437 if (cursor_tag_micropos+1 < s) {
01438 cursor_tag_micropos++;
01439 set_cursor(p);
01440 cursorline_dirty();
01441 update_misc_info();
01442 update_visual_info();
01443 return 1;
01444 }
01445 }
01446 }
01447 }
01448 p.tag_idx++;
01449 }
01450 p.tag_idx=0;
01451 if (!next_line(&p, 1)) break;
01452 }
01453 if (cursor_right()) cursor_tag_micropos=0;
01454 return 0;
01455 }
01456
01457 int ht_uformat_viewer::cursormicro_forward()
01458 {
01459 cursorline_get();
01460 char *t=tag_get_selectable_tag(cursor_line, cursor.tag_idx, cursor.tag_group);
01461 int s=tag_get_microsize(t);
01462 if (cursor_tag_micropos+1>=s) {
01463 if (cursor_right()) cursor_tag_micropos=0; else return 0;
01464 } else cursor_tag_micropos++;
01465 return 1;
01466 }
01467
01468 int ht_uformat_viewer::cursormicro_backward()
01469 {
01470 if (cursor_tag_micropos>0) {
01471 cursor_tag_micropos--;
01472 } else {
01473 if (cursor_left()) {
01474 cursorline_get();
01475 char *t=tag_get_selectable_tag(cursor_line, cursor.tag_idx, cursor.tag_group);
01476 cursor_tag_micropos=tag_get_microsize(t)-1;
01477 } else return 0;
01478 }
01479 return 1;
01480 }
01481
01482 void ht_uformat_viewer::draw()
01483 {
01484 int sdown_count=0;
01485 if (!uf_initialized) HT_ERROR("complete_init() not called !");
01486 restart:
01487 clear(getcolor(palidx_generic_body));
01488 if (!first_sub) return;
01489 uformat_viewer_pos p = top;
01490 uformat_viewer_pos sp;
01491 clear_viewer_pos(&sp);
01492
01493 char line[1024];
01494 bool cursor_in_line;
01495 int cursor_found=-1;
01496 if (focused) hidecursor();
01497 if (!p.sub->getline(line, p.line_id)) {
01498 if (p.sub->closest_line_id(&p.line_id)) {
01499 top = p;
01500 } else return;
01501 if (!p.sub->getline(line, p.line_id)) return;
01502 }
01503 for (int y=0; y<size.h; y++) {
01504 if (y == cursor_ypos) sp = p;
01505 if (!p.sub->getline(line, p.line_id)) break;
01506
01507
01508
01509
01510
01511
01512
01513 if ((cursor_state == cursor_state_visible) && (p.sub == cursor.sub)
01514 && compeq_line_id(p.line_id, cursor.line_id)) {
01515 cursor_found=y;
01516 cursorline_dirty();
01517 update_misc_info();
01518 int c=tag_count_selectable_tags_in_group(line, cursor.tag_group);
01519 if (cursor.tag_idx>=c) cursor.tag_idx = c-1;
01520 if ((cursor_tag_class==tag_class_edit) && (edit())) {
01521 char *t=tag_get_selectable_tag(line, cursor.tag_idx, cursor.tag_group);
01522 int x=cursor_visual_xpos+tag_get_micropos(t, cursor_tag_micropos)-xscroll;
01523 if (focused) if (x>=0) setcursor(x, y);
01524 }
01525 cursor_in_line = true;
01526 } else cursor_in_line = false;
01527 print_tagstring(0, y, size.w, xscroll, line, cursor_in_line);
01528 if (xscroll>0) buf_printchar(0, y, VCP(VC_GREEN, VC_TRANSPARENT), '<');
01529 if (!next_line(&p, 1)) break;
01530 }
01531 if ((cursor_state==cursor_state_visible) && (cursor_found==-1)) {
01532 #if 1
01533 if (!sp.sub) sp = top;
01534 cursor = sp;
01535 #else
01536 top = cursor;
01537 #endif
01538 cursorline_dirty();
01539 update_misc_info();
01540 int c=tag_count_selectable_tags_in_group(line, cursor.tag_group);
01541 if (cursor.tag_idx>c-1) cursor.tag_idx=c-1;
01542
01543 if (sdown_count++ > 0) goto restart;
01544 }
01545 if (cursor_found != -1) cursor_ypos = cursor_found;
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564 }
01565
01566 bool ht_uformat_viewer::edit()
01567 {
01568 return (file && (file->get_access_mode() & FAM_WRITE));
01569 }
01570
01571 bool ht_uformat_viewer::edit_end()
01572 {
01573 if (!edit()) {
01574 hidecursor();
01575 set_cursor(cursor);
01576 #if 0
01577 uformat_viewer_pos p = cursor;
01578 if (find_first_tag(&p, size.h)) {
01579 set_cursor(p);
01580 } else {
01581
01582
01583
01584
01585
01586 }
01587 #endif
01588 cursorline_dirty();
01589 adjust_cursor_idx();
01590 update_visual_info();
01591 update_misc_info();
01592 dirtyview();
01593 return true;
01594 }
01595 return false;
01596 }
01597
01598 bool ht_uformat_viewer::edit_input(byte b)
01599 {
01600 cursorline_get();
01601 char *t=tag_get_selectable_tag(cursor_line, cursor.tag_idx, cursor.tag_group);
01602 switch (t[1]) {
01603 case HT_TAG_EDIT_BYTE:
01604 case HT_TAG_EDIT_WORD_LE:
01605 case HT_TAG_EDIT_DWORD_LE:
01606 case HT_TAG_EDIT_QWORD_LE:
01607 case HT_TAG_EDIT_WORD_BE:
01608 case HT_TAG_EDIT_DWORD_BE:
01609 case HT_TAG_EDIT_QWORD_BE: {
01610 int nibval=edit_input_c2h(b);
01611 if (nibval==-1) break;
01612
01613 int size=0;
01614 bool bigendian = true;
01615 switch (t[1]) {
01616 case HT_TAG_EDIT_BYTE: size=1; break;
01617 case HT_TAG_EDIT_WORD_LE: size=2; bigendian=false; break;
01618 case HT_TAG_EDIT_DWORD_LE: size=4; bigendian=false; break;
01619 case HT_TAG_EDIT_QWORD_LE: size=8; bigendian=false; break;
01620 case HT_TAG_EDIT_WORD_BE: size=2; bigendian=true; break;
01621 case HT_TAG_EDIT_DWORD_BE: size=4; bigendian=true; break;
01622 case HT_TAG_EDIT_QWORD_BE: size=8; bigendian=true; break;
01623 }
01624
01625 int shift=4-(cursor_tag_micropos&1)*4;
01626 int m=~(0xf<<shift), o=nibval<<shift;
01627
01628 int b;
01629 if (bigendian) {
01630 b=(cursor_tag_micropos)/2;
01631 } else {
01632 b=size-(cursor_tag_micropos)/2-1;
01633 }
01634
01635 byte buf;
01636 pread(cursor_tag_offset+b, &buf, 1);
01637 buf&=m;
01638 buf|=o;
01639 pwrite(cursor_tag_offset+b, &buf, 1);
01640 cursormicroedit_forward();
01641 return true;
01642 }
01643 case HT_TAG_EDIT_CHAR: {
01644 if ((char)b>=32) {
01645 pwrite(cursor_tag_offset, &b, 1);
01646 cursormicroedit_forward();
01647 return true;
01648 }
01649 break;
01650 }
01651 case HT_TAG_EDIT_BIT: {
01652 if ((b=='1') || (b=='0') || b==' ') {
01653 byte d;
01654 cursorline_get();
01655 char *t=tag_get_selectable_tag(cursor_line, cursor.tag_idx, cursor.tag_group);
01656 int shift=((ht_tag_edit_bit*)t)->bitidx;
01657 dword mask=1 << (shift%8);
01658 int op=shift/8;
01659 pread(cursor_tag_offset+op, &d, 1);
01660 switch (b) {
01661 case '0':
01662 d&=~mask;
01663 break;
01664 case '1':
01665 d|=mask;
01666 break;
01667 case K_Space:
01668 d^=mask;
01669 break;
01670 }
01671 pwrite(cursor_tag_offset+op, &d, 1);
01672 cursormicroedit_forward();
01673 return true;
01674 }
01675 break;
01676 }
01677 case HT_TAG_EDIT_TIME: {
01678 dword d;
01679 int h = edit_input_c2d(b);
01680
01681 byte buf[4];
01682 if ((pread(cursor_tag_offset, &buf, 4)==4) && (h!=-1)) {
01683 d=(buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0];
01684 tm *t = gmtime((time_t*)&d);
01685 tm q = *t;
01686 int k;
01687 bool worked = false;
01688 #define DEC_MASK(value, mask) ((value) - (value) / (mask) % 10 * (mask))
01689 switch (cursor_tag_micropos) {
01690 case 0:
01691 k = q.tm_hour % 10 + h * 10;
01692 if (k < 24) {
01693 q.tm_hour = k;
01694 worked = true;
01695 }
01696 break;
01697 case 1:
01698 k = q.tm_hour - q.tm_hour % 10 + h;
01699 if (k < 24) {
01700 q.tm_hour = k;
01701 worked = true;
01702 }
01703 break;
01704 case 2:
01705 k = q.tm_min % 10 + h * 10;
01706 if (k < 60) {
01707 q.tm_min = k;
01708 worked = true;
01709 }
01710 break;
01711 case 3:
01712 k = q.tm_min - q.tm_min % 10 + h;
01713 if (k < 60) {
01714 q.tm_min = k;
01715 worked = true;
01716 }
01717 break;
01718 case 4:
01719 k = q.tm_sec % 10 + h * 10;
01720 if (k < 60) {
01721 q.tm_sec = k;
01722 worked = true;
01723 }
01724 break;
01725 case 5:
01726 k = q.tm_sec - q.tm_sec % 10 + h;
01727 if (k < 60) {
01728 q.tm_sec = k;
01729 worked = true;
01730 }
01731 break;
01732 case 6:
01733 k = (q.tm_mday % 10) + h * 10;
01734 if (k <= 31) {
01735 q.tm_mday = k;
01736 worked = true;
01737 }
01738 break;
01739 case 7:
01740 k = q.tm_mday - q.tm_mday % 10 + h;
01741 if (k <= 31) {
01742 q.tm_mday = k;
01743 worked = true;
01744 }
01745 break;
01746 case 8:
01747 k = (q.tm_mon+1) % 10 + h * 10;
01748 if (k <= 12) {
01749 q.tm_mon = k-1;
01750 worked = true;
01751 }
01752 break;
01753 case 9:
01754 k = q.tm_mon - q.tm_mon % 10 + h;
01755 if (k <= 12) {
01756 q.tm_mon = k-1;
01757 worked = true;
01758 }
01759 break;
01760 case 10:
01761 k = DEC_MASK(q.tm_year, 1000) + h * 1000;
01762 if ((k+1900 >= 1970 ) && (k+1900 < 2106)) {
01763 q.tm_year = k;
01764 worked = true;
01765 }
01766 break;
01767 case 11:
01768 k = DEC_MASK(q.tm_year, 100) + h * 100;
01769 if ((k+1900 >= 1970 ) && (k+1900 < 2106)) {
01770 q.tm_year = k;
01771 worked = true;
01772 }
01773 break;
01774 case 12:
01775 k = DEC_MASK(q.tm_year, 10) + h * 10;
01776 if ((k+1900 >= 1970 ) && (k+1900 < 2106)) {
01777 q.tm_year = k;
01778 worked = true;
01779 }
01780 break;
01781 case 13:
01782 k = DEC_MASK(q.tm_year, 1) + h * 1;
01783 if ((k+1900 >= 1970 ) && (k+1900 < 2106)) {
01784 q.tm_year = k;
01785 worked = true;
01786 }
01787 break;
01788 }
01789
01790 if (sizeof(dword) == sizeof(time_t))
01791 if (worked) {
01792
01793 dword tz;
01794 time_t l = time(NULL);
01795 time_t g = l;
01796 struct tm *gtm = gmtime(&g);
01797 g = mktime(gtm);
01798 tz = (dword)difftime(g, l);
01799 *(time_t*)&d = mktime(&q);
01800 d -= tz;
01801 buf[0] = d>>0;
01802 buf[1] = d>>8;
01803 buf[2] = d>>16;
01804 buf[3] = d>>24;
01805 pwrite(cursor_tag_offset, &buf, 4);
01806 cursormicroedit_forward();
01807 return true;
01808 }
01809 }
01810 }
01811 }
01812 return false;
01813 }
01814
01815 int ht_uformat_viewer::edit_input_c2h(byte b)
01816 {
01817 int h=-1;
01818 if ((b>='0') && (b<='9')) {
01819 h=b-'0';
01820 } else if ((b>='a') && (b<='f')) {
01821 h=b-'a'+10;
01822 } else if ((b>='A') && (b<='F')) {
01823 h=b-'A'+10;
01824 }
01825 return h;
01826 }
01827
01828 int ht_uformat_viewer::edit_input_c2d(byte b)
01829 {
01830 int h=-1;
01831 if ((b>='0') && (b<='9')) {
01832 h=b-'0';
01833 }
01834 return h;
01835 }
01836
01837 void ht_uformat_viewer::edit_input_correctpos()
01838 {
01839 uformat_viewer_pos p = top;
01840
01841
01842 char c_line[1024];
01843 int g=cursor.tag_group;
01844 for (int y=0; y<size.h+10; y++) {
01845 if (!p.sub->getline(c_line, p.line_id)) break;
01846 int c=tag_count_selectable_tags_in_group(c_line, cursor.tag_group);
01847 for (int i=0; i<c; i++) {
01848 char *t=tag_get_selectable_tag(c_line, i, cursor.tag_group);
01849 if ((tag_get_class(t)==tag_class_edit) && (tag_get_offset(t)==cursor_tag_offset)) {
01850 set_cursor(p);
01851 cursorline_dirty();
01852 cursor.tag_idx=i;
01853 cursor.tag_group=g;
01854 update_misc_info();
01855 update_visual_info();
01856 return;
01857 }
01858 }
01859 if (!next_line(&p, 1)) break;
01860 }
01861
01862
01863 p = top;
01864 next_line(&p, cursor_ypos);
01865 int ci = cursor.tag_idx;
01866 set_cursor(p);
01867 cursorline_dirty();
01868 cursorline_get();
01869 int x = tag_count_selectable_tags(cursor_line);
01870 if (ci >= x) ci = x-1;
01871 cursor.tag_idx = ci;
01872 update_misc_info();
01873 update_visual_info();
01874 }
01875
01876 bool ht_uformat_viewer::edit_start()
01877 {
01878 if (edit() && cursor.sub) {
01879 cursor_tag_micropos=0;
01880 cursorline_dirty();
01881 adjust_cursor_idx();
01882 update_visual_info();
01883 update_misc_info();
01884 dirtyview();
01885 return true;
01886 }
01887 return false;
01888 }
01889
01890 bool ht_uformat_viewer::edit_update()
01891 {
01892 if (edit()) {
01893 file->cntl(FCNTL_MODS_FLUSH);
01894 dirtyview();
01895 return true;
01896 }
01897 return false;
01898 }
01899
01900 bool ht_uformat_viewer::find_first_tag(uformat_viewer_pos *p, int limit)
01901 {
01902 char line[1024];
01903 int i=0;
01904 uformat_viewer_pos q = *p;
01905 if (!q.sub) return false;
01906 do {
01907 q.sub->getline(line, q.line_id);
01908 if (tag_get_selectable_tag(line, 0, 0)) {
01909 *p = q;
01910 p->tag_idx = 0;
01911 p->tag_group = 0;
01912 return true;
01913 }
01914 } while ((next_line(&q, 1)) && (i++<limit));
01915 return false;
01916 }
01917
01918 bool ht_uformat_viewer::find_first_edit_tag_with_offset(uformat_viewer_pos *p, int limit, FILEOFS offset)
01919 {
01920 char line[1024];
01921 int i=0;
01922 uformat_viewer_pos q = *p;
01923 if (!q.sub) return false;
01924 do {
01925 q.sub->getline(line, q.line_id);
01926 int c=tag_count_selectable_tags(line);
01927 char *t=line;
01928 for (int j=0; j<c; j++) {
01929 t=tag_get_selectable_tag(t, 0, -1);
01930 if ((tag_get_class(t)==tag_class_edit) && (tag_get_offset(t)==offset)) {
01931 *p = q;
01932 p->tag_idx = j;
01933 p->tag_group = 0;
01934
01935 return true;
01936 }
01937 t+=tag_get_len(t);
01938 }
01939 } while ((next_line(&q, 1)) && (i++<limit));
01940 return false;
01941 }
01942
01943 void ht_uformat_viewer::focus_cursor()
01944 {
01945
01946
01947
01948
01949
01950 update_visual_info();
01951 if (cursor_visual_xpos-xscroll <= 1) {
01952 if (cursor_visual_xpos>=1) xscroll = cursor_visual_xpos-1; else
01953 xscroll = 0;
01954 } else if (cursor_visual_xpos+cursor_visual_length-xscroll > size.w-1) {
01955 xscroll = cursor_visual_xpos+cursor_visual_length-size.w+1;
01956 }
01957 }
01958
01959 char *ht_uformat_viewer::func(UINT i, bool execute)
01960 {
01961 switch (i) {
01962 case 2:
01963 if (caps & VC_EDIT) {
01964 if (edit()) {
01965 if (execute) app->sendmsg(cmd_file_save);
01966
01967 return "save";
01968 } else {
01969 return "~save";
01970 }
01971 }
01972 break;
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983 case 4:
01984 if (caps & VC_EDIT) {
01985 if (edit()) {
01986 if (execute) {
01987 UINT size = file->get_size();
01988 bool isdirty = false;
01989 file->cntl(FCNTL_MODS_IS_DIRTY, 0, file->get_size(), &isdirty);
01990 char q[1024];
01991 if (file->get_filename()) {
01992 ht_snprintf(q, sizeof q,
01993 "file %s has been modified, apply changes ?",
01994 file->get_filename());
01995 } else {
01996 ht_snprintf(q, sizeof q,
01997 "untitled file has been modified, apply changes ?");
01998 }
01999 if (isdirty && (confirmbox(q) == button_yes)) {
02000 file->cntl(FCNTL_MODS_FLUSH);
02001 } else {
02002 file->cntl(FCNTL_MODS_INVD);
02003 }
02004 if (size != file->get_size()) {
02005 htmsg m;
02006 m.msg = msg_filesize_changed;
02007 m.type = mt_broadcast;
02008 sendmsg(&m);
02009 }
02010 baseview->sendmsg(cmd_view_mode_i, file, NULL);
02011 }
02012 return "view";
02013 } else {
02014 if (execute) baseview->sendmsg(cmd_edit_mode_i, file, NULL);
02015 return "edit";
02016 }
02017 }
02018 break;
02019 case 5:
02020 if (caps & VC_GOTO) {
02021 if (execute) sendmsg(cmd_file_goto);
02022 return "goto";
02023 }
02024 break;
02025 case 7:
02026 if (caps & VC_SEARCH) {
02027 if (execute) sendmsg(cmd_file_search);
02028 return "search";
02029 }
02030 break;
02031 case 8:
02032 if (caps & VC_RESIZE) {
02033 if (edit()) {
02034 if (execute) sendmsg(cmd_file_resize);
02035 return "resize";
02036 } else {
02037 return "~resize";
02038 }
02039 }
02040 break;
02041 case 9: {
02042 if (execute) {
02043 FILEOFS o;
02044 if (get_current_real_offset(&o)) {
02045 char title[128];
02046 ht_snprintf(title, sizeof title, "view offset %08x in...", o);
02047 ht_view *v = ((ht_app*)app)->popup_view_list(title);
02048 if (v) {
02049 htmsg m;
02050 m.msg = msg_goto_offset;
02051 m.type = mt_empty;
02052 m.data1.integer = o;
02053 v->sendmsg(&m);
02054 if (m.msg == msg_empty) {
02055 vstate_save();
02056 app->focus(v);
02057 } else {
02058 errorbox("offset %08x is not supported/invalid in '%s'", o, v->desc);
02059 }
02060 }
02061 }
02062 }
02063 return "viewin...";
02064 }
02065 }
02066 return ht_format_viewer::func(i, execute);
02067 }
02068
02069 vcp ht_uformat_viewer::getcolor_tag(UINT pal_index)
02070 {
02071 return getcolorv(&tagpal, pal_index);
02072 }
02073
02074 bool ht_uformat_viewer::get_current_offset(FILEOFS *offset)
02075 {
02076 if ((cursor_state!=cursor_state_disabled) && (cursor_tag_class==tag_class_edit)) {
02077 *offset=cursor_tag_offset;
02078 return true;
02079 }
02080 return false;
02081 }
02082
02083 bool ht_uformat_viewer::get_current_pos(viewer_pos *pos)
02084 {
02085 clear_viewer_pos(pos);
02086 pos->u = cursor;
02087 return true;
02088 }
02089
02090 int ht_uformat_viewer::get_current_tag(char **tag)
02091 {
02092 cursorline_get();
02093 char *e=tag_get_selectable_tag(cursor_line, cursor.tag_idx, cursor.tag_group);
02094 if (e) {
02095 *tag=e;
02096 return 1;
02097 }
02098 return 0;
02099 }
02100
02101 int ht_uformat_viewer::get_current_tag_size(dword *size)
02102 {
02103 if (cursor_tag_class==tag_class_edit) {
02104 cursorline_get();
02105 char *e=tag_get_selectable_tag(cursor_line, cursor.tag_idx, cursor.tag_group);
02106 if (e) {
02107 *size=tag_get_size(e);
02108 return 1;
02109 }
02110 }
02111 return 0;
02112 }
02113
02114 void ht_uformat_viewer::handlemsg(htmsg *msg)
02115 {
02116 switch (msg->msg) {
02117 case msg_get_scrollinfo:
02118 switch (msg->data1.integer) {
02119 case gsi_pindicator: {
02120 get_pindicator_str((char*)msg->data2.ptr);
02121 clearmsg(msg);
02122 return;
02123 }
02124 case gsi_hscrollbar: {
02125 gsi_scrollbar_t *p=(gsi_scrollbar_t*)msg->data2.ptr;
02126 if (!get_hscrollbar_pos(&p->pstart, &p->psize)) {
02127 p->pstart = 0;
02128 p->psize = 100;
02129 }
02130 clearmsg(msg);
02131 return;
02132 }
02133 case gsi_vscrollbar: {
02134 gsi_scrollbar_t *p=(gsi_scrollbar_t*)msg->data2.ptr;
02135 if (!get_vscrollbar_pos(&p->pstart, &p->psize)) {
02136 p->pstart = 0;
02137 p->psize = 100;
02138 }
02139 clearmsg(msg);
02140 return;
02141 }
02142 }
02143 break;
02144 case msg_complete_init:
02145 complete_init();
02146 clearmsg(msg);
02147 return;
02148 case msg_keypressed:
02149 switch (msg->data1.integer) {
02150 case K_Alt_S:
02151 if (cursor_select) {
02152 select_mode_off();
02153 } else {
02154 select_mode_on();
02155 }
02156 clearmsg(msg);
02157 dirtyview();
02158 return;
02159 case K_Up:
02160 select_mode_pre();
02161 cursor_up(1);
02162 select_mode_post(0);
02163 clearmsg(msg);
02164 dirtyview();
02165 return;
02166 case K_Down:
02167 select_mode_pre();
02168 cursor_down(1);
02169 select_mode_post(0);
02170 clearmsg(msg);
02171 dirtyview();
02172 return;
02173 case K_PageUp:
02174 select_mode_pre();
02175 cursor_up(size.h);
02176 select_mode_post(0);
02177 clearmsg(msg);
02178 dirtyview();
02179 return;
02180 case K_PageDown:
02181 select_mode_pre();
02182 cursor_down(size.h);
02183 select_mode_post(0);
02184 clearmsg(msg);
02185 dirtyview();
02186 return;
02187 case K_Left:
02188 if (cursor_state!=cursor_state_disabled) {
02189 select_mode_pre();
02190 if (edit()) cursormicro_backward(); else cursor_left();
02191 select_mode_post(0);
02192 focus_cursor();
02193 clearmsg(msg);
02194 dirtyview();
02195 return;
02196 }
02197 break;
02198 case K_Right:
02199 if (cursor_state!=cursor_state_disabled) {
02200 int r;
02201 select_mode_pre();
02202 if (edit()) r=cursormicro_forward(); else r=cursor_right();
02203 select_mode_post(!r);
02204 focus_cursor();
02205 clearmsg(msg);
02206 dirtyview();
02207 return;
02208 }
02209 break;
02210 case K_Return:
02211 switch (cursor_tag_class) {
02212 case tag_class_sel:
02213 ref();
02214 break;
02215 case tag_class_edit:
02216 if (edit()) {
02217 edit_input(msg->data1.integer);
02218 }
02219 break;
02220 }
02221 dirtyview();
02222 clearmsg(msg);
02223 return;
02224 case K_Backspace: {
02225 FILEOFS f;
02226 if (edit() && (cursor_tag_class == tag_class_edit)
02227 && get_current_offset(&f)) {
02228 file->cntl(FCNTL_MODS_CLEAR_DIRTY_RANGE, f, 1);
02229 cursor_left();
02230 focus_cursor();
02231 dirtyview();
02232 clearmsg(msg);
02233 }
02234 return;
02235 }
02236 case K_Tab: {
02237 int c=cursor.tag_group;
02238 cursor_tab();
02239 if (cursor.tag_group!=c) {
02240 focus_cursor();
02241 update_visual_info();
02242 dirtyview();
02243 clearmsg(msg);
02244 return;
02245 }
02246 break;
02247 }
02248 case K_Home:
02249 if (cursor_state==cursor_state_visible) {
02250 select_mode_pre();
02251 cursor_home();
02252 select_mode_post(0);
02253 focus_cursor();
02254 clearmsg(msg);
02255 dirtyview();
02256 return;
02257 }
02258 break;
02259 case K_End:
02260 if (cursor_state==cursor_state_visible) {
02261 select_mode_pre();
02262 cursor_end();
02263 select_mode_post(0);
02264 focus_cursor();
02265 clearmsg(msg);
02266 dirtyview();
02267 return;
02268 }
02269 break;
02270 case K_Control_Left:
02271 xscroll-=2;
02272 if (xscroll<0) xscroll=0;
02273 dirtyview();
02274 clearmsg(msg);
02275 return;
02276 case K_Control_Right:
02277 xscroll+=2;
02278 dirtyview();
02279 clearmsg(msg);
02280 return;
02281 case K_Control_PageUp: {
02282 top.sub = first_sub;
02283 if (top.sub) {
02284 vstate_save();
02285 select_mode_pre();
02286 top.sub->first_line_id(&top.line_id);
02287
02288 uformat_viewer_pos p = top;
02289 p.tag_group = cursor.tag_group;
02290 if (find_first_tag(&p, size.h)) {
02291 set_cursor(p);
02292 } else {
02293 cursor_ypos=0x7fffffff;
02294 update_misc_info();
02295 update_visual_info();
02296 check_cursor_visibility();
02297 }
02298 select_mode_post(0);
02299 }
02300 clearmsg(msg);
02301 dirtyview();
02302 return;
02303 }
02304 case K_Control_PageDown: {
02305 top.sub = last_sub;
02306 if (top.sub) {
02307 vstate_save();
02308 select_mode_pre();
02309 top.sub->last_line_id(&top.line_id);
02310
02311 uformat_viewer_pos p = top;
02312 p.tag_group = cursor.tag_group;
02313 if (find_first_tag(&p, 1)) {
02314 set_cursor(p);
02315 } else {
02316 cursor_ypos=0x7fffffff;
02317 update_misc_info();
02318 update_visual_info();
02319 check_cursor_visibility();
02320 }
02321
02322 cursor_up(size.h);
02323 cursor_down(size.h);
02324
02325 select_mode_post(0);
02326 }
02327 clearmsg(msg);
02328 dirtyview();
02329 return;
02330 }
02331 case K_Shift_Up: {
02332 focus_cursor();
02333 FILEOFS s, e;
02334 dword ts;
02335 if (cursor_tag_class==tag_class_edit)
02336 s=cursor_tag_offset;
02337 else
02338 s=(sel_end>sel_start) ? sel_end : 0xffffffff;
02339 e=get_current_tag_size(&ts) ? s+ts : 0xffffffff;
02340 cursor_up(1);
02341 if (s!=0xffffffff) {
02342 if (cursor_tag_class==tag_class_edit) {
02343 pselect_add(s, cursor_tag_offset);
02344 } else if ((cursor_tag_class==tag_class_sel) && (e!=0xffffffff)) {
02345 pselect_add(s, e);
02346 }
02347 }
02348 clearmsg(msg);
02349 dirtyview();
02350 return;
02351 }
02352 case K_Shift_Down: {
02353 focus_cursor();
02354 FILEOFS s, e;
02355 dword ts;
02356 if (cursor_tag_class==tag_class_edit)
02357 s=cursor_tag_offset;
02358 else
02359 s=(sel_end>sel_start) ? sel_end : 0xffffffff;
02360 e=get_current_tag_size(&ts) ? s+ts : 0xffffffff;
02361 cursor_down(1);
02362 if (s!=0xffffffff) {
02363 if (cursor_tag_class==tag_class_edit) {
02364 pselect_add(s, cursor_tag_offset);
02365 } else if ((cursor_tag_class==tag_class_sel) && (e!=0xffffffff)) {
02366 pselect_add(s, e);
02367 }
02368 }
02369 clearmsg(msg);
02370 dirtyview();
02371 return;
02372 }
02373 case K_Shift_Left: {
02374 focus_cursor();
02375 FILEOFS s, e;
02376 dword ts;
02377 if (cursor_tag_class==tag_class_edit)
02378 s=cursor_tag_offset;
02379 else
02380 s=(sel_end>sel_start) ? sel_end : 0xffffffff;
02381 e=get_current_tag_size(&ts) ? s+ts : 0xffffffff;
02382 int r;
02383 if (edit()) r=cursormicro_backward(); else r=cursor_left();
02384 if ((s!=0xffffffff) & (r)) {
02385 if (cursor_tag_class==tag_class_edit) {
02386 pselect_add(s, cursor_tag_offset);
02387 } else if ((cursor_tag_class==tag_class_sel) && (e!=0xffffffff)) {
02388 pselect_add(s, e);
02389 }
02390 }
02391 clearmsg(msg);
02392 dirtyview();
02393 return;
02394 }
02395 case K_Shift_Right: {
02396 focus_cursor();
02397 FILEOFS s, e;
02398 dword ts;
02399 if (cursor_tag_class==tag_class_edit)
02400 s=cursor_tag_offset;
02401 else
02402 s=(sel_end>sel_start) ? sel_end : 0xffffffff;
02403 e=get_current_tag_size(&ts) ? s+ts : 0xffffffff;
02404 int r;
02405 if (edit()) r=cursormicro_forward(); else r=cursor_right();
02406 if (s!=0xffffffff) {
02407 if (r) {
02408 if (cursor_tag_class==tag_class_edit) {
02409 pselect_add(s, cursor_tag_offset);
02410 } else if ((cursor_tag_class==tag_class_sel) && (e!=0xffffffff)) {
02411 pselect_add(s, e);
02412 }
02413 } else {
02414 if ((cursor_tag_class==tag_class_edit) && (sel_end != e)) {
02415 pselect_add(s, e);
02416 }
02417 }
02418 }
02419 clearmsg(msg);
02420 dirtyview();
02421 return;
02422 }
02423 case K_Shift_PageUp: {
02424 focus_cursor();
02425 FILEOFS s, e;
02426 dword ts;
02427 if (cursor_tag_class==tag_class_edit)
02428 s=cursor_tag_offset;
02429 else
02430 s=(sel_end>sel_start) ? sel_end : 0xffffffff;
02431 e=get_current_tag_size(&ts) ? s+ts : 0xffffffff;
02432 cursor_up(size.h);
02433 if (s!=0xffffffff) {
02434 if (cursor_tag_class==tag_class_edit) {
02435 pselect_add(s, cursor_tag_offset);
02436 } else if ((cursor_tag_class==tag_class_sel) && (e!=0xffffffff)) {
02437 pselect_add(s, e);
02438 }
02439 }
02440 clearmsg(msg);
02441 dirtyview();
02442 return;
02443 }
02444 case K_Shift_PageDown: {
02445 focus_cursor();
02446 FILEOFS s, e;
02447 dword ts;
02448 if (cursor_tag_class==tag_class_edit)
02449 s=cursor_tag_offset;
02450 else
02451 s=(sel_end>sel_start) ? sel_end : 0xffffffff;
02452 e=get_current_tag_size(&ts) ? s+ts : 0xffffffff;
02453 cursor_down(size.h);
02454 if (s!=0xffffffff) {
02455 if (cursor_tag_class==tag_class_edit) {
02456 pselect_add(s, cursor_tag_offset);
02457 } else if ((cursor_tag_class==tag_class_sel) && (e!=0xffffffff)) {
02458 pselect_add(s, e);
02459 }
02460 }
02461 clearmsg(msg);
02462 dirtyview();
02463 return;
02464 }
02465 case K_Shift_Home: {
02466 focus_cursor();
02467 FILEOFS s, e;
02468 dword ts;
02469 if (cursor_tag_class==tag_class_edit)
02470 s=cursor_tag_offset;
02471 else
02472 s=(sel_end>sel_start) ? sel_end : 0xffffffff;
02473 e=get_current_tag_size(&ts) ? s+ts : 0xffffffff;
02474 int r=cursor_home();
02475 if ((s!=0xffffffff) && (r)) {
02476 if (cursor_tag_class==tag_class_edit) {
02477 pselect_add(cursor_tag_offset, s);
02478 } else if ((cursor_tag_class==tag_class_sel) && (e!=0xffffffff)) {
02479 pselect_add(e, s);
02480 }
02481 }
02482 clearmsg(msg);
02483 dirtyview();
02484 return;
02485 }
02486 case K_Shift_End: {
02487 focus_cursor();
02488 FILEOFS s, e;
02489 dword ts;
02490 if (cursor_tag_class==tag_class_edit)
02491 s=cursor_tag_offset;
02492 else
02493 s=(sel_end>sel_start) ? sel_end : 0xffffffff;
02494 e=get_current_tag_size(&ts) ? s+ts : 0xffffffff;
02495 int r=cursor_end();
02496 if ((s!=0xffffffff) && (r)){
02497 if (cursor_tag_class==tag_class_edit) {
02498 pselect_add(s, cursor_tag_offset);
02499 } else if ((cursor_tag_class==tag_class_sel) && (e!=0xffffffff)) {
02500 pselect_add(s, e);
02501 }
02502 }
02503 clearmsg(msg);
02504 dirtyview();
02505 return;
02506 }
02507 case K_Control_F:
02508 if (caps & VC_SEARCH) {
02509 sendmsg(cmd_file_search);
02510 dirtyview();
02511 clearmsg(msg);
02512 return;
02513 }
02514 break;
02515 case K_Control_L:
02516 case K_Shift_F7:
02517 if (caps & VC_SEARCH) {
02518 if (!continue_search()) {
02519 if (last_search_request) {
02520 infobox("no further matches");
02521 } else {
02522 infobox("you must 'search' first !");
02523 }
02524 }
02525 dirtyview();
02526 clearmsg(msg);
02527 return;
02528 }
02529 break;
02530 case K_Alt_C:
02531 case K_Control_Insert:
02532 sendmsg(cmd_edit_copy);
02533 dirtyview();
02534 clearmsg(msg);
02535 return;
02536 case K_Alt_V:
02537 case K_Shift_Insert:
02538 sendmsg(cmd_edit_paste);
02539 dirtyview();
02540 clearmsg(msg);
02541 return;
02542 case K_Escape:
02543 if (caps & VC_EDIT) {
02544 baseview->sendmsg(cmd_view_mode_i, file, NULL);
02545 return;
02546 }
02547 break;
02548 default: {
02549 if (((dword)msg->data1.integer<=255) && (edit())) {
02550 if (cursor_tag_class==tag_class_edit) {
02551 focus_cursor();
02552 if (edit_input(msg->data1.integer)) {
02553 dirtyview();
02554 clearmsg(msg);
02555 return;
02556 }
02557 }
02558 }
02559 }
02560 }
02561 break;
02562 case cmd_edit_copy:
02563 if (sel_end>sel_start) {
02564 char dsc[1024];
02565 ht_snprintf(dsc, sizeof dsc, "%s::%s", file->get_filename(), desc);
02566 clipboard_copy(dsc, file, sel_start, sel_end-sel_start);
02567 }
02568 clearmsg(msg);
02569 return;
02570 case cmd_edit_paste:
02571 FILEOFS ofs;
02572 if (get_current_offset(&ofs)) {
02573 baseview->sendmsg(cmd_edit_mode_i, file, NULL);
02574 if (file->get_access_mode() & FAM_WRITE) {
02575 dword s=clipboard_paste(file, ofs);
02576 if (s) {
02577 pselect_set(ofs, ofs+s);
02578 sendmsg(cmd_edit_mode_i);
02579 }
02580 }
02581 }
02582 dirtyview();
02583 clearmsg(msg);
02584 return;
02585 case cmd_edit_mode:
02586 edit_start();
02587 dirtyview();
02588 return;
02589 case cmd_view_mode:
02590 edit_end();
02591 dirtyview();
02592 return;
02593 case cmd_file_goto: {
02594 char addrstr[1024];
02595 addrstr[0] = 0;
02596 while (address_input("goto", addrstr, sizeof addrstr, HISTATOM_GOTO) != button_cancel) {
02597 if (addrstr[0]) {
02598 viewer_pos pos;
02599 globalerror[0] = 0;
02600 if (string_to_pos(addrstr, &pos) && goto_pos(pos, this)) {
02601 focus_cursor();
02602 break;
02603 }
02604 if (globalerror[0]) {
02605 infobox("error: %s\nin '%s'", globalerror, addrstr);
02606 } else {
02607 infobox("invalid address: '%s'", addrstr);
02608 }
02609 }
02610 }
02611 clearmsg(msg);
02612 dirtyview();
02613 return;
02614 }
02615 case cmd_file_search: {
02616 viewer_pos start_pos, end_pos;
02617 get_current_pos(&start_pos);
02618 clear_viewer_pos(&end_pos);
02619 end_pos.u.sub = last_sub;
02620 end_pos.u.tag_idx = -1;
02621 last_sub->last_line_id(&end_pos.u.line_id);
02622 ht_search_request *request = search_dialog(this, search_caps, &start_pos, &end_pos);
02623 ht_search_result *result = NULL;
02624 if (request) {
02625 switch (request->search_class) {
02626 case SC_PHYSICAL: {
02627 try {
02628 FILEOFS start, end;
02629 if (pos_to_offset(start_pos, &start)
02630 && pos_to_offset(end_pos, &end)) {
02631 result = psearch(request, start, end);
02632 }
02633 } catch (ht_exception *e) {
02634 errorbox("error: %s", e->what());
02635 }
02636 break;
02637 }
02638 case SC_VISUAL: {
02639 try {
02640 result = vsearch(request, start_pos, end_pos);
02641 } catch (ht_exception *e) {
02642 errorbox("error: %s", e->what());
02643 }
02644 break;
02645 }
02646 }
02647 delete request;
02648 if (result) {
02649
02650 if (!show_search_result(result)) infobox("couldn't display result (internal error)");
02651 delete result;
02652 } else infobox("not found");
02653 }
02654 clearmsg(msg);
02655 dirtyview();
02656 return;
02657 }
02658 case cmd_file_replace: {
02659 sendmsg(cmd_edit_mode_i);
02660 if (edit()) {
02661 bool cancel;
02662 UINT s = get_file()->get_size();
02663 UINT repls = replace_dialog(this, search_caps, &cancel);
02664 if (repls) {
02665 if (s != get_file()->get_size()) {
02666 sendmsg(msg_filesize_changed);
02667 }
02668 infobox("%d replacement(s) made", repls);
02669 }
02670 }
02671 clearmsg(msg);
02672 dirtyview();
02673 return;
02674 }
02675 case msg_filesize_changed: {
02676 htmsg m;
02677 m.msg=msg_filesize_changed;
02678 m.type=mt_broadcast;
02679 sendsubmsg(&m);
02680 break;
02681 }
02682 case cmd_file_save: {
02683 if (edit()) edit_update();
02684 clearmsg(msg);
02685 return;
02686 }
02687 case cmd_file_resize: {
02688 FILEOFS o=0;
02689 if (get_current_offset(&o)) {
02690 dword s;
02691 get_current_tag_size(&s);
02692 o+=s;
02693 }
02694
02695 UINT s=file->get_size();
02696
02697 char buf[32];
02698 sprintf(buf, "%d", o);
02699 if (inputbox("resize", "new file size", buf, sizeof buf, 0)==button_ok) {
02700 eval_scalar r;
02701 if (eval(&r, buf, NULL, NULL, NULL)) {
02702 eval_int i;
02703 scalar_context_int(&r, &i);
02704 scalar_destroy(&r);
02705 o=QWORD_GET_INT(i.value);
02706 if (o<s) {
02707
02708 htmsg m;
02709
02710 m.msg=cmd_file_truncate;
02711 m.type=mt_broadcast;
02712 m.data1.ptr=file;
02713 m.data2.integer=o;
02714 baseview->sendmsg(&m);
02715
02716 m.msg=msg_filesize_changed;
02717 m.type=mt_broadcast;
02718 sendsubmsg(&m);
02719 sendmsg(&m);
02720 } else if (o>s) {
02721
02722 htmsg m;
02723
02724 m.msg=cmd_file_extend;
02725 m.type=mt_broadcast;
02726 m.data1.ptr=file;
02727 m.data2.integer=o;
02728 baseview->sendmsg(&m);
02729
02730 m.msg=msg_filesize_changed;
02731 m.type=mt_broadcast;
02732 sendsubmsg(&m);
02733 sendmsg(&m);
02734 }
02735 } else {
02736 char *errmsg="?";
02737 int errpos=0;
02738 get_eval_error(&errmsg, &errpos);
02739 errorbox("eval error: %s at %d\n in '%s'", errmsg, errpos, buf);
02740 }
02741 update_misc_info();
02742 }
02743
02744 clearmsg(msg);
02745 dirtyview();
02746 return;
02747 }
02748 case cmd_file_blockop: {
02749 if (sel_end>sel_start) {
02750 blockop_dialog(this, sel_start, sel_end);
02751 } else {
02752 FILEOFS o=0;
02753 get_current_offset(&o);
02754 blockop_dialog(this, o, file->get_size());
02755 }
02756 clearmsg(msg);
02757 dirtyview();
02758 return;
02759 }
02760 }
02761 ht_format_viewer::handlemsg(msg);
02762 }
02763
02764 void ht_uformat_viewer::insertsub(ht_sub *sub)
02765 {
02766 if (last_sub) last_sub->next=sub;
02767 sub->uformat_viewer=this;
02768 sub->prev=last_sub;
02769 last_sub=sub;
02770 if (!first_sub) first_sub=sub;
02771 }
02772
02773 bool ht_uformat_viewer::goto_offset(FILEOFS offset, bool save_vstate)
02774 {
02775 uformat_viewer_pos p;
02776 p.sub = first_sub;
02777 p.tag_group = cursor.tag_group;
02778 while (p.sub) {
02779 if (p.sub->convert_ofs_to_id(offset, &p.line_id)) {
02780 if (save_vstate) vstate_save();
02781 switch (cursor_state) {
02782 case cursor_state_visible: {
02783 select_mode_pre();
02784
02785 if (!find_first_edit_tag_with_offset(&p, 42, offset)
02786 && !find_first_tag(&p, size.h)) break;
02787 bool r = set_cursor(p);
02788 select_mode_post(false);
02789 return r;
02790 }
02791 case cursor_state_invisible:
02792 select_mode_pre();
02793 p.tag_group = -1;
02794 p.tag_idx = -1;
02795 bool r = set_cursor(p);
02796 select_mode_post(false);
02797 return r;
02798 }
02799 break;
02800 }
02801 p.sub = p.sub->next;
02802 }
02803 return false;
02804 }
02805
02806 bool ht_uformat_viewer::goto_pos(viewer_pos pos, bool save_vstate)
02807 {
02808 if (save_vstate) vstate_save();
02809 select_mode_pre();
02810 set_cursor(pos.u);
02811 select_mode_post(false);
02812 return true;
02813 }
02814
02815 bool ht_uformat_viewer::next_logical_pos(viewer_pos pos, viewer_pos *npos)
02816 {
02817 if (next_line(&pos.u, 1) == 1) {
02818 *npos = pos;
02819 return true;
02820 }
02821 return false;
02822 }
02823
02824 bool ht_uformat_viewer::next_logical_offset(FILEOFS ofs, FILEOFS *nofs)
02825 {
02826 *nofs = ofs + 1;
02827 return true;
02828 }
02829
02830 int ht_uformat_viewer::next_line(uformat_viewer_pos *p, int n)
02831 {
02832 int n0 = n;
02833 while (n) {
02834 if (n -= p->sub->next_line_id(&p->line_id, n)) {
02835 if (!p->sub->next) return n0 - n;
02836 p->sub = p->sub->next;
02837 p->sub->first_line_id(&p->line_id);
02838 p->tag_idx = -1;
02839 n--;
02840 }
02841 }
02842 return n0 - n;
02843 }
02844
02845 int ht_uformat_viewer::prev_line(uformat_viewer_pos *p, int n)
02846 {
02847 int n0 = n;
02848 while (n){
02849 if (n -= p->sub->prev_line_id(&p->line_id, n)) {
02850 if (!p->sub->prev) return n0 - n;
02851 p->sub = p->sub->prev;
02852 p->sub->last_line_id(&p->line_id);
02853 p->tag_idx = -1;
02854 n--;
02855 }
02856 }
02857 return n0 - n;
02858 }
02859
02860 vcp ht_uformat_viewer::get_tag_color_edit(FILEOFS tag_offset, UINT size, bool atcursoroffset, bool iscursor)
02861 {
02862 vcp tag_color = getcolor_tag(palidx_tags_edit_tag);
02863 bool isdirty = false;
02864 file->cntl(FCNTL_MODS_IS_DIRTY, tag_offset, size, &isdirty);
02865 if (isdirty) tag_color=vcp_mix(tag_color, getcolor_tag(palidx_tags_edit_tag_modified));
02866 if ((tag_offset>=sel_start) && (tag_offset<sel_end)) tag_color=vcp_mix(tag_color, getcolor_tag(palidx_tags_edit_tag_selected));
02867 if (iscursor) {
02868 int coloridx;
02869 if (atcursoroffset) {
02870 if (edit()) {
02871 coloridx=palidx_tags_edit_tag_cursor_edit;
02872 } else {
02873 coloridx=palidx_tags_edit_tag_cursor_select;
02874 }
02875 } else {
02876 coloridx=palidx_tags_edit_tag_cursor_unfocused;
02877 }
02878 tag_color=vcp_mix(tag_color, getcolor_tag(coloridx));
02879 }
02880 return tag_color;
02881 }
02882
02883 void ht_uformat_viewer::render_tagstring_desc(char **string, int *length, vcp *tc, char *tag, UINT size, bool bigendian, bool is_cursor)
02884 {
02885 ID id;
02886 vcp tag_color=getcolor_tag(palidx_tags_sel_tag);
02887 if (is_cursor) tag_color=getcolor_tag(palidx_tags_sel_tag_cursor_focused);
02888 *string="?";
02889 *length=1;
02890 *tc=tag_color;
02891 if (tag_get_desc_id(tag, &id)) {
02892 int_hash *tbl;
02893 if ((tbl=(int_hash*)find_atom(id))) {
02894 char *str;
02895 qword q;
02896 q.hi = 0;
02897 q.lo = 0;
02898 FILEOFS tag_offset=tag_get_offset(tag);
02899 byte buf[4];
02900
02901 if (pread(tag_offset, buf, size)==size) {
02902 switch (size) {
02903 case 1:
02904 q.hi = 0;
02905 q.lo = buf[0];
02906 break;
02907 case 2:
02908 q.hi = 0;
02909 if (bigendian) {
02910 q.lo = (buf[0]<<8) | buf[1];
02911 } else {
02912 q.lo = (buf[1]<<8) | buf[0];
02913 }
02914 break;
02915 case 4:
02916 q.hi = 0;
02917 if (bigendian) {
02918 q.lo = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
02919 } else {
02920 q.lo = (buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0];
02921 }
02922 break;
02923 case 8:
02924 if (bigendian) {
02925 q.hi = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
02926 q.lo = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
02927 } else {
02928 q.hi = (buf[7] << 24) | (buf[6] << 16) | (buf[5] << 8) | buf[4];
02929 q.lo = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
02930 }
02931 break;
02932 }
02933
02934 if ((str=matchhash(q.lo, tbl))) {
02935 *string=str;
02936 *length=strlen(*string);
02937 }
02938 } else {
02939 *string="?";
02940 *length=strlen(*string);
02941 }
02942 }
02943 }
02944 }
02945
02946 void ht_uformat_viewer::reloadpalette()
02947 {
02948 ht_format_viewer::reloadpalette();
02949 if (tagpal.data) {
02950 free(tagpal.data);
02951 tagpal.data = NULL;
02952 }
02953 load_pal(palclasskey_tags, palkey_tags_default, &tagpal);
02954 }
02955
02956 UINT ht_uformat_viewer::render_tagstring(char *chars, vcp *colors, UINT maxlen, char *tagstring, bool cursor_in_line)
02957 {
02958 char *n=tagstring;
02959 UINT c=0;
02960 int i=0, g=0;
02961 bool is_cursor;
02962 vcp color_normal=getcolor(palidx_generic_body);
02963 do {
02964 int l=0;
02965 while (n[l] && n[l]!='\e') { l++; }
02966 c+=render_tagstring_single(chars, colors, maxlen, c, n, l, color_normal);
02967
02968 n+=l;
02969 is_cursor=cursor_in_line && (i==cursor.tag_idx);
02970 if (*n=='\e') {
02971 FILEOFS tag_offset;
02972 vcp tag_color;
02973 char str[64];
02974 switch (n[1]) {
02975 case HT_TAG_EDIT_BYTE: {
02976 byte d;
02977
02978 tag_offset=tag_get_offset(n);
02979 tag_color=get_tag_color_edit(tag_offset, 1, focused && (g==cursor.tag_group), is_cursor);
02980
02981 if (pread(tag_offset, &d, 1)==1) {
02982 mkhexb(str, d);
02983 } else {
02984 strcpy(str, "??");
02985 }
02986
02987 c+=render_tagstring_single(chars, colors, maxlen, c, str, 2, tag_color);
02988
02989 n+=HT_TAG_EDIT_BYTE_LEN;
02990 break;
02991 }
02992 case HT_TAG_EDIT_WORD_LE: {
02993 word d;
02994
02995 tag_offset=tag_get_offset(n);
02996 tag_color=get_tag_color_edit(tag_offset, 2, (g==cursor.tag_group), is_cursor);
02997
02998 byte buf[2];
02999 if (pread(tag_offset, &buf, 2)==2) {
03000
03001 d=(buf[1] << 8) | buf[0];
03002 mkhexw(str, d);
03003 } else {
03004 strcpy(str, "????");
03005 }
03006
03007 c+=render_tagstring_single(chars, colors, maxlen, c, str, 4, tag_color);
03008 n+=HT_TAG_EDIT_WORD_LE_LEN;
03009 break;
03010 }
03011 case HT_TAG_EDIT_DWORD_LE: {
03012 dword d;
03013
03014 tag_offset=tag_get_offset(n);
03015 tag_color=get_tag_color_edit(tag_offset, 4, (g==cursor.tag_group), is_cursor);
03016
03017 byte buf[4];
03018 if (pread(tag_offset, &buf, 4)==4) {
03019
03020 d=(buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
03021 mkhexd(str, d);
03022 } else {
03023 strcpy(str, "????????");
03024 }
03025
03026 c+=render_tagstring_single(chars, colors, maxlen, c, str, 8, tag_color);
03027 n+=HT_TAG_EDIT_DWORD_LE_LEN;
03028 break;
03029 }
03030 case HT_TAG_EDIT_QWORD_LE: {
03031 qword q;
03032
03033 tag_offset=tag_get_offset(n);
03034 tag_color=get_tag_color_edit(tag_offset, 8, (g==cursor.tag_group), is_cursor);
03035
03036 byte buf[8];
03037 if (pread(tag_offset, &buf, 8)==8) {
03038
03039 q.hi = (buf[7] << 24) | (buf[6] << 16) | (buf[5] << 8) | buf[4];
03040 q.lo = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
03041 mkhexq(str, q);
03042 } else {
03043 strcpy(str, "????????????????");
03044 }
03045
03046 c+=render_tagstring_single(chars, colors, maxlen, c, str, 16, tag_color);
03047 n+=HT_TAG_EDIT_QWORD_LE_LEN;
03048 break;
03049 }
03050 case HT_TAG_EDIT_WORD_BE: {
03051 word d;
03052
03053 tag_offset=tag_get_offset(n);
03054 tag_color=get_tag_color_edit(tag_offset, 2, (g==cursor.tag_group), is_cursor);
03055
03056 byte buf[2];
03057 if (pread(tag_offset, &buf, 2)==2) {
03058
03059 d=(buf[0] << 8) | buf[1];
03060 mkhexw(str, d);
03061 } else {
03062 strcpy(str, "????");
03063 }
03064
03065 c+=render_tagstring_single(chars, colors, maxlen, c, str, 4, tag_color);
03066 n+=HT_TAG_EDIT_WORD_BE_LEN;
03067 break;
03068 }
03069 case HT_TAG_EDIT_DWORD_BE: {
03070 dword d;
03071
03072 tag_offset=tag_get_offset(n);
03073 tag_color=get_tag_color_edit(tag_offset, 4, (g==cursor.tag_group), is_cursor);
03074
03075 byte buf[4];
03076 if (pread(tag_offset, &buf, 4)==4) {
03077
03078 d=(buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
03079 mkhexd(str, d);
03080 } else {
03081 strcpy(str, "????????");
03082 }
03083 c+=render_tagstring_single(chars, colors, maxlen, c, str, 8, tag_color);
03084 n+=HT_TAG_EDIT_DWORD_BE_LEN;
03085 break;
03086 }
03087 case HT_TAG_EDIT_QWORD_BE: {
03088 qword q;
03089
03090 tag_offset=tag_get_offset(n);
03091 tag_color=get_tag_color_edit(tag_offset, 8, (g==cursor.tag_group), is_cursor);
03092
03093 byte buf[8];
03094 if (pread(tag_offset, &buf, 8)==8) {
03095
03096 q.hi = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
03097 q.lo = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
03098 mkhexq(str, q);
03099 } else {
03100 strcpy(str, "????????????????");
03101 }
03102 c+=render_tagstring_single(chars, colors, maxlen, c, str, 16, tag_color);
03103 n+=HT_TAG_EDIT_QWORD_BE_LEN;
03104 break;
03105 }
03106 case HT_TAG_EDIT_TIME: {
03107 dword d;
03108
03109 tag_offset=tag_get_offset(n);
03110 tag_color=get_tag_color_edit(tag_offset, 4, (g==cursor.tag_group), is_cursor);
03111
03112 byte buf[4];
03113 if (pread(tag_offset, &buf, 4)==4) {
03114 d=(buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0];
03115 tm *t=gmtime((time_t*)&d);
03116 sprintf(str, "%02d:%02d:%02d %02d.%02d.%04d +1900", t->tm_hour, t->tm_min, t->tm_sec, t->tm_mday, t->tm_mon+1, t->tm_year);
03117 } else {
03118 strcpy(str, "?");
03119 }
03120
03121 c+=render_tagstring_single(chars, colors, maxlen, c, str, strlen(str), tag_color);
03122 n+=HT_TAG_EDIT_TIME_LEN;
03123 break;
03124 }
03125 case HT_TAG_EDIT_CHAR: {
03126 char d;
03127
03128 tag_offset=tag_get_offset(n);
03129 tag_color=get_tag_color_edit(tag_offset, 1, (g==cursor.tag_group), is_cursor);
03130
03131 if (pread(tag_offset, &d, 1)!=1) {
03132 d='?';
03133 }
03134
03135 c+=render_tagstring_single(chars, colors, maxlen, c, &d, 1, tag_color);
03136 n+=HT_TAG_EDIT_CHAR_LEN;
03137 break;
03138 }
03139 case HT_TAG_EDIT_BIT: {
03140 int shift=((ht_tag_edit_bit*)n)->bitidx;
03141 int op=shift/8;
03142 byte d;
03143
03144 tag_offset=tag_get_offset(n);
03145 tag_color=getcolor_tag(palidx_tags_edit_tag);
03146 bool isdirty = false;
03147 file->cntl(FCNTL_MODS_IS_DIRTY, tag_offset+op, IS_DIRTY_SINGLEBIT | (shift & 7), &isdirty);
03148 if (isdirty) tag_color=vcp_mix(tag_color, getcolor_tag(palidx_tags_edit_tag_modified));
03149 if ((tag_offset>=sel_start) && (tag_offset<sel_end)) tag_color=vcp_mix(tag_color, getcolor_tag(palidx_tags_edit_tag_selected));
03150 if (is_cursor) tag_color=vcp_mix(tag_color, getcolor_tag(edit() ? palidx_tags_edit_tag_cursor_edit : palidx_tags_edit_tag_cursor_select));
03151
03152 if (pread(tag_offset+op, &d, 1)==1) {
03153 str[0]=(d& (1 << (shift%8))) ? '1' : '0';
03154 str[1]=0;
03155 } else {
03156 strcpy(str, "?");
03157 }
03158
03159 c+=render_tagstring_single(chars, colors, maxlen, c, str, 1, tag_color);
03160 n+=HT_TAG_EDIT_BIT_LEN;
03161 break;
03162 }
03163 case HT_TAG_EDIT_SELVIS: {
03164 tag_offset=tag_get_offset(n);
03165 tag_color=getcolor_tag(palidx_tags_edit_tag);
03166
03167 if ((tag_offset>=sel_start) && (tag_offset<sel_end)) tag_color=vcp_mix(tag_color, getcolor_tag(palidx_tags_edit_tag_selected));
03168
03169 c+=render_tagstring_single(chars, colors, maxlen, c, &((ht_tag_edit_selvis*)n)->ch, 1, tag_color);
03170 n+=HT_TAG_EDIT_SELVIS_LEN;
03171 continue;
03172 }
03173 case HT_TAG_SEL: {
03174 int tag_textlen = tag_get_seltextlen(n);
03175 if (is_cursor) {
03176 tag_color = getcolor_tag(
03177 (focused && (g == cursor.tag_group)) ?
03178 palidx_tags_sel_tag_cursor_focused :
03179 palidx_tags_sel_tag_cursor_unfocused
03180 );
03181 } else {
03182 tag_color = getcolor_tag(palidx_tags_sel_tag);
03183 }
03184 n += HT_TAG_SEL_LEN(0);
03185 c += render_tagstring_single(chars, colors, maxlen, c, n, tag_textlen, tag_color);
03186 n += tag_textlen;
03187 break;
03188 }
03189 case HT_TAG_DESC_BYTE: {
03190 char *str;
03191 int l;
03192 render_tagstring_desc(&str, &l, &tag_color, n, 1, true, is_cursor);
03193 c+=render_tagstring_single(chars, colors, maxlen, c, str, l, tag_color);
03194 n+=HT_TAG_DESC_BYTE_LEN;
03195 break;
03196 }
03197 case HT_TAG_DESC_WORD_LE: {
03198 char *str;
03199 int l;
03200 render_tagstring_desc(&str, &l, &tag_color, n, 2, false, is_cursor);
03201 c+=render_tagstring_single(chars, colors, maxlen, c, str, l, tag_color);
03202 n+=HT_TAG_DESC_WORD_LE_LEN;
03203 break;
03204 }
03205 case HT_TAG_DESC_DWORD_LE: {
03206 char *str;
03207 int l;
03208 render_tagstring_desc(&str, &l, &tag_color, n, 4, false, is_cursor);
03209 c+=render_tagstring_single(chars, colors, maxlen, c, str, l, tag_color);
03210 n+=HT_TAG_DESC_DWORD_LE_LEN;
03211 break;
03212 }
03213 case HT_TAG_DESC_QWORD_LE: {
03214 char *str;
03215 int l;
03216 render_tagstring_desc(&str, &l, &tag_color, n, 8, false, is_cursor);
03217 c+=render_tagstring_single(chars, colors, maxlen, c, str, l, tag_color);
03218 n+=HT_TAG_DESC_QWORD_LE_LEN;
03219 break;
03220 }
03221 case HT_TAG_DESC_WORD_BE: {
03222 char *str;
03223 int l;
03224 render_tagstring_desc(&str, &l, &tag_color, n, 2, true, is_cursor);
03225 c+=render_tagstring_single(chars, colors, maxlen, c, str, l, tag_color);
03226 n+=HT_TAG_DESC_WORD_BE_LEN;
03227 break;
03228 }
03229 case HT_TAG_DESC_DWORD_BE: {
03230 char *str;
03231 int l;
03232 render_tagstring_desc(&str, &l, &tag_color, n, 4, true, is_cursor);
03233 c+=render_tagstring_single(chars, colors, maxlen, c, str, l, tag_color);
03234 n+=HT_TAG_DESC_DWORD_BE_LEN;
03235 break;
03236 }
03237 case HT_TAG_DESC_QWORD_BE: {
03238 char *str;
03239 int l;
03240 render_tagstring_desc(&str, &l, &tag_color, n, 8, true, is_cursor);
03241 c+=render_tagstring_single(chars, colors, maxlen, c, str, l, tag_color);
03242 n+=HT_TAG_DESC_DWORD_BE_LEN;
03243 break;
03244 }
03245 case HT_TAG_FLAGS:
03246 n+=HT_TAG_FLAGS_LEN;
03247 tag_color=getcolor_tag(palidx_tags_sel_tag);
03248 if (is_cursor) tag_color=getcolor_tag(palidx_tags_sel_tag_cursor_focused);
03249 c+=render_tagstring_single(chars, colors, maxlen, c, "details", 7, tag_color);
03250 break;
03251 case HT_TAG_GROUP:
03252 n+=HT_TAG_GROUP_LEN;
03253 g++;
03254 i=0;
03255 continue;
03256 case HT_TAG_COLOR:
03257 color_normal = tag_get_color(n);
03258 if (color_normal == (int)0xffffffff) {
03259 color_normal = getcolor(palidx_generic_body);
03260 }
03261 n+=HT_TAG_COLOR_LEN;
03262 continue;
03263 default: {
03264 assert(0);
03265 }
03266 }
03267 }
03268 i++;
03269 } while (*n);
03270 return c;
03271 }
03272
03273 UINT ht_uformat_viewer::render_tagstring_single(char *chars, vcp *colors, UINT maxlen, UINT offset, char *text, UINT len, vcp color)
03274 {
03275 if (chars) chars+=offset;
03276 if (colors) colors+=offset;
03277 maxlen-=offset;
03278 UINT l=(len<maxlen) ? len : maxlen, r=0;
03279 while (l--) {
03280 if (chars) *(chars++)=*(text++);
03281 if (colors) *(colors++)=color;
03282 r++;
03283 }
03284 return r;
03285 }
03286
03287 #define MAX_PRINT_TAGSTRING_LINELENGTH 256
03288
03289 void ht_uformat_viewer::print_tagstring(int x, int y, int maxlen, int xscroll, char *tagstring, bool cursor_in_line)
03290 {
03291 char text[MAX_PRINT_TAGSTRING_LINELENGTH], *t=text+xscroll;
03292 vcp color[MAX_PRINT_TAGSTRING_LINELENGTH], *c=color+xscroll;
03293 int l=render_tagstring(text, color,
03294 (maxlen+xscroll+1>MAX_PRINT_TAGSTRING_LINELENGTH) ? MAX_PRINT_TAGSTRING_LINELENGTH
03295 : maxlen+xscroll+1, tagstring, cursor_in_line);
03296
03297 if (l>xscroll) {
03298 l-=xscroll;
03299 while (l--) {
03300 if (x>=size.w) {
03301 buf_printchar(x-1, y, VCP(VC_GREEN, VC_TRANSPARENT), '>');
03302 break;
03303 }
03304 buf_printchar(x, y, *c, (unsigned char)*t);
03305 t++;
03306 c++;
03307 x++;
03308 }
03309 }
03310 }
03311
03312 void ht_uformat_viewer::select_mode_off()
03313 {
03314 if (cursor_select) {
03315 cursor_select=0;
03316 }
03317 }
03318
03319 void ht_uformat_viewer::select_mode_on()
03320 {
03321 if (!cursor_select) {
03322 cursor_select=1;
03323 }
03324 }
03325
03326 void ht_uformat_viewer::select_mode_pre()
03327 {
03328 if (cursor_select) {
03329 if (cursor_tag_class==tag_class_edit)
03330 cursor_select_start=cursor_tag_offset;
03331 else
03332 cursor_select_start=(sel_end>sel_start) ? sel_end : 0xffffffff;
03333 if (!get_current_tag_size(&cursor_select_cursor_length)) cursor_select_cursor_length=0xffffffff;
03334 }
03335 }
03336
03337 void ht_uformat_viewer::select_mode_post(bool lastpos)
03338 {
03339 if (cursor_select) {
03340 if (cursor_select_start!=0xffffffff) {
03341 if (cursor_tag_class==tag_class_edit) {
03342 if ((lastpos) && (cursor_select_cursor_length!=0xffffffff)) {
03343 FILEOFS s, e;
03344 pselect_get(&s, &e);
03345 if (e != cursor_tag_offset+cursor_select_cursor_length) {
03346 pselect_add(cursor_select_start, cursor_tag_offset+cursor_select_cursor_length);
03347 }
03348 } else {
03349 pselect_add(cursor_select_start, cursor_tag_offset);
03350 }
03351 } else if ((cursor_tag_class==tag_class_sel) && (cursor_select_cursor_length!=0xffffffff)) {
03352 pselect_add(cursor_select_start, cursor_select_start+cursor_select_cursor_length);
03353 }
03354 }
03355 }
03356 }
03357
03358 UINT ht_uformat_viewer::pwrite(FILEOFS ofs, void *buf, UINT size)
03359 {
03360 cursorline_dirty();
03361 return ht_format_viewer::pwrite(ofs, buf, size);
03362 }
03363
03364 int ht_uformat_viewer::ref()
03365 {
03366 cursorline_get();
03367 char *e=tag_get_selectable_tag(cursor_line, cursor.tag_idx, cursor.tag_group);
03368 if (!e) return 0;
03369 if (tag_get_class(e)==tag_class_sel) {
03370 if (!cursor.sub->ref(&cursor_tag_id.id)) {
03371 switch (e[1]) {
03372 case HT_TAG_SEL:
03373 return ref_sel(&cursor_tag_id.id);
03374 case HT_TAG_FLAGS:
03375 return ref_flags(((ht_tag_flags*)e)->offset, ((ht_tag_flags*)e)->id);
03376 case HT_TAG_DESC_BYTE:
03377 return ref_desc(((ht_tag_desc_byte*)e)->id, ((ht_tag_desc_byte*)e)->offset, 1, true);
03378 case HT_TAG_DESC_WORD_LE:
03379 return ref_desc(((ht_tag_desc_byte*)e)->id, ((ht_tag_desc_byte*)e)->offset, 2, false);
03380 case HT_TAG_DESC_DWORD_LE:
03381 return ref_desc(((ht_tag_desc_byte*)e)->id, ((ht_tag_desc_byte*)e)->offset, 4, false);
03382 case HT_TAG_DESC_QWORD_LE:
03383 return ref_desc(((ht_tag_desc_byte*)e)->id, ((ht_tag_desc_byte*)e)->offset, 8, false);
03384 case HT_TAG_DESC_WORD_BE:
03385 return ref_desc(((ht_tag_desc_byte*)e)->id, ((ht_tag_desc_byte*)e)->offset, 2, true);
03386 case HT_TAG_DESC_DWORD_BE:
03387 return ref_desc(((ht_tag_desc_byte*)e)->id, ((ht_tag_desc_byte*)e)->offset, 4, true);
03388 case HT_TAG_DESC_QWORD_BE:
03389 return ref_desc(((ht_tag_desc_byte*)e)->id, ((ht_tag_desc_byte*)e)->offset, 8, true);
03390 }
03391 }
03392 }
03393 return 0;
03394 }
03395
03396 int ht_uformat_viewer::ref_desc(ID id, FILEOFS offset, UINT size, bool bigendian)
03397 {
03398 endianess end = bigendian ? big_endian : little_endian;
03399 int_hash *desc=(int_hash*)find_atom(id);
03400 if (desc) {
03401 bounds b;
03402 b.w=60;
03403 b.h=14;
03404 b.x=(screen->size.w-b.w)/2;
03405 b.y=(screen->size.h-b.h)/2;
03406 ht_dialog *g=new ht_dialog();
03407 g->init(&b, "desc", FS_KILLER | FS_MOVE);
03408
03409 b.x=0;
03410 b.y=0;
03411 b.w-=2;
03412 b.h-=2;
03413 ht_itext_listbox *l=new ht_itext_listbox();
03414 l->init(&b, 2, 1);
03415
03416 byte buf[4];
03417 int curpos=0, i=0;
03418 int d=0;
03419
03420 if (pread(offset, buf, size)!=size) return 0;
03421
03422 switch (size) {
03423 case 1: d=buf[0]; break;
03424 case 2:
03425 if (bigendian) {
03426 d=(buf[0]<<8) | buf[1];
03427 } else {
03428 d=(buf[1]<<8) | buf[0];
03429 }
03430 break;
03431 case 4:
03432 if (bigendian) {
03433 d=(buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
03434 } else {
03435 d=(buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0];
03436 }
03437 break;
03438 }
03439
03440 int_hash *dsc=desc;
03441 while (dsc->desc) {
03442 char buf[32];
03443 switch (size) {
03444 case 1:
03445 sprintf(buf, "0x%02x", dsc->value);
03446 break;
03447 case 2:
03448 sprintf(buf, "0x%04x", dsc->value);
03449 break;
03450 case 4:
03451 sprintf(buf, "0x%08x", dsc->value);
03452 break;
03453 }
03454 if (dsc->value==d) {
03455 curpos=i;
03456 }
03457 l->insert_str(i, buf, dsc->desc);
03458 dsc++;
03459 i++;
03460 }
03461
03462 l->update();
03463 l->gotoItemByPosition(curpos);
03464
03465 g->insert(l);
03466 g->setpalette(palkey_generic_window_default);
03467
03468 if (g->run(false)==button_ok) {
03469 ht_listbox_data da;
03470 l->databuf_get(&da, sizeof da);
03471 int i = l->getID(da.cursor_ptr);
03472 if (desc[i].value != d) {
03473 baseview->sendmsg(cmd_edit_mode_i, file, NULL);
03474 if (edit()) {
03475 byte buf[4];
03476 uint v = desc[i].value;
03477 create_foreign_int(buf, v, size, end);
03478 pwrite(offset, buf, size);
03479 dirtyview();
03480 }
03481 }
03482 }
03483
03484 g->done();
03485 delete g;
03486 return 1;
03487 }
03488 return 0;
03489 }
03490
03491 int ht_uformat_viewer::ref_flags(ID id, FILEOFS offset)
03492 {
03493 ht_tag_flags_s *flags=(ht_tag_flags_s*)find_atom(id), *fl;
03494 if (flags) {
03495 bounds b;
03496 b.w=60;
03497 b.h=14;
03498 b.x=(screen->size.w-b.w)/2;
03499 b.y=(screen->size.h-b.h)/2;
03500 ht_dialog *d=new ht_dialog();
03501 d->init(&b, (flags->bitidx==-1) ? flags->desc : 0, FS_KILLER | FS_TITLE | FS_MOVE);
03502
03503 b.x=0;
03504 b.y=0;
03505 b.w-=2;
03506 b.h-=2;
03507 ht_uformat_viewer *u=new ht_uformat_viewer();
03508 u->init(&b, 0, VC_EDIT, file, 0);
03509
03510 ht_mask_sub *m=new ht_mask_sub();
03511 m->init(file, 0);
03512 char *t, x[256];
03513
03514 int width=0;
03515 fl=flags;
03516 if (fl->bitidx==-1) fl++;
03517 do {
03518 int l=strlen(fl->desc);
03519 if (l>width) width=l;
03520 fl++;
03521 } while (fl->desc);
03522
03523 width=MAX(width, 25);
03524 width++;
03525
03526 fl=flags;
03527 if (fl->bitidx==-1) fl++;
03528 do {
03529 t=x;
03530 int l=strlen(fl->desc);
03531 memmove(t, fl->desc, l);
03532 t+=l;
03533 while (t<x+width) *(t++)=' ';
03534 t=tag_make_edit_bit(t, offset, fl->bitidx);
03535 *t=0;
03536 m->add_mask(x);
03537 fl++;
03538 } while (fl->desc);
03539
03540
03541 u->insertsub(m);
03542 u->sendmsg(msg_complete_init, 0);
03543 d->insert(u);
03544
03545 d->setpalette(palkey_generic_window_default);
03546
03547 UINT pmode=file->get_access_mode() & FAM_WRITE;
03548
03549 if (d->run(false)==button_ok) u->edit_update();
03550
03551 if (pmode != file->get_access_mode() & FAM_WRITE) {
03552 if (pmode) {
03553 baseview->sendmsg(cmd_view_mode_i, file, NULL);
03554 } else {
03555 baseview->sendmsg(cmd_edit_mode_i, file, NULL);
03556 }
03557 }
03558
03559 d->done();
03560 delete d;
03561 return 1;
03562 }
03563 return 0;
03564 }
03565
03566 int ht_uformat_viewer::ref_sel(LINE_ID *id)
03567 {
03568 return 0;
03569 }
03570
03571 ht_search_result *ht_uformat_viewer::psearch(ht_search_request *request, FILEOFS start, FILEOFS end)
03572 {
03573 if (request != last_search_request) {
03574 if (last_search_request) delete last_search_request;
03575 last_search_request = (ht_search_request*)request->duplicate();
03576 }
03577 last_search_physical = true;
03578 last_search_end_ofs = end;
03579
03580 ht_sub *sub=first_sub;
03581 while (sub) {
03582 ht_search_result *r = sub->search(request, start, end);
03583 if (r) return r;
03584 sub = sub->next;
03585 }
03586 return NULL;
03587 }
03588
03589 ht_search_result *ht_uformat_viewer::vsearch(ht_search_request *request, viewer_pos start, viewer_pos end)
03590 {
03591 if (request != last_search_request) {
03592 if (last_search_request) delete last_search_request;
03593 last_search_request = (ht_search_request*)request->duplicate();
03594 }
03595 last_search_physical = false;
03596 last_search_end_pos = end;
03597
03598 if ((request->search_class==SC_VISUAL) && (request->type==ST_REGEX)) {
03599 if (!cursor.sub) return 0;
03600 ht_regex_search_request *s=(ht_regex_search_request*)request;
03601
03602 bounds b;
03603 get_std_progress_indicator_metrics(&b);
03604 ht_progress_indicator *progress_indicator=new ht_progress_indicator();
03605 progress_indicator->init(&b, "ESC to cancel");
03606 UINT lines=0;
03607
03608 uformat_viewer_pos p = start.u;
03609 while (p.sub) {
03610 do {
03611 char line[1024];
03612 if (!p.sub->getline(line, p.line_id)) assert(0);
03613 char rdrd[256];
03614 int c=render_tagstring(rdrd, 0, 256, line, 0);
03615 rdrd[c]=0;
03616 regmatch_t pos;
03617 if (!regexec(&s->rx, rdrd, 1, &pos, 0)) {
03618 ht_visual_search_result *r=new ht_visual_search_result();
03619 r->pos.u = p;
03620 r->xpos = pos.rm_so;
03621 r->length = pos.rm_eo-pos.rm_so;
03622 progress_indicator->done();
03623 delete progress_indicator;
03624
03625 return r;
03626 }
03627 lines++;
03628 if (lines % 500==0) {
03629 if (ht_keypressed()) {
03630 if (ht_getkey()==K_Escape) goto leave;
03631 }
03632
03633 char text[256];
03634
03635
03636
03637 {
03638 ht_snprintf(text, sizeof text, "searching for '%s'... %d lines", s->rx_str, lines);
03639 }
03640 progress_indicator->settext(text);
03641 progress_indicator->sendmsg(msg_draw, 0);
03642 screen->show();
03643 }
03644 } while (p.sub->next_line_id(&p.line_id, 1));
03645 p.sub = p.sub->next;
03646 if (p.sub) p.sub->first_line_id(&p.line_id);
03647 }
03648 leave:
03649 progress_indicator->done();
03650 delete progress_indicator;
03651 }
03652 return NULL;
03653 }
03654
03655 void ht_uformat_viewer::pselect_add(FILEOFS start, FILEOFS end)
03656 {
03657 bool downward = (start<end);
03658 if (end<start) {
03659 FILEOFS temp=start;
03660 start=end;
03661 end=temp;
03662 }
03663 if ((end==sel_start) && !downward) {
03664 sel_start=start;
03665 } else if ((start==sel_end) && downward) {
03666 sel_end=end;
03667 } else if ((end==sel_end) && !downward) {
03668 sel_end=start;
03669 } else if ((start==sel_start) && downward) {
03670 sel_start=end;
03671 } else {
03672 sel_start=start;
03673 sel_end=end;
03674 }
03675 if (sel_start>sel_end) {
03676 FILEOFS temp=sel_start;
03677 sel_start=sel_end;
03678 sel_end=temp;
03679 }
03680 }
03681
03682 void ht_uformat_viewer::pselect_get(FILEOFS *start, FILEOFS *end)
03683 {
03684 *start=sel_start;
03685 *end=sel_end;
03686 }
03687
03688 void ht_uformat_viewer::pselect_set(FILEOFS start, FILEOFS end)
03689 {
03690 sel_start=start;
03691 sel_end=end;
03692 }
03693
03694 void ht_uformat_viewer::clear_subs()
03695 {
03696 ht_sub *s=first_sub, *t;
03697 while (s) {
03698 t=s->next;
03699 s->done();
03700 delete s;
03701 s=t;
03702 }
03703
03704 uf_initialized=false;
03705 cursor_ypos=0;
03706
03707 clear_viewer_pos(&top);
03708 clear_viewer_pos(&cursor);
03709 first_sub=0;
03710 last_sub=0;
03711 }
03712
03713 void ht_uformat_viewer::clear_viewer_pos(viewer_pos *p)
03714 {
03715 clear_viewer_pos(&p->u);
03716 }
03717
03718 void ht_uformat_viewer::clear_viewer_pos(uformat_viewer_pos *p)
03719 {
03720 p->sub = NULL;
03721 clear_line_id(&p->line_id);
03722 p->tag_idx = 0;
03723 p->tag_group = 0;
03724 }
03725
03726 bool ht_uformat_viewer::compeq_viewer_pos(viewer_pos *a, viewer_pos *b)
03727 {
03728 return compeq_viewer_pos(&a->u, &b->u);
03729 }
03730
03731 bool ht_uformat_viewer::compeq_viewer_pos(uformat_viewer_pos *a, uformat_viewer_pos *b)
03732 {
03733 return ((a->sub == b->sub)
03734 && compeq_line_id(a->line_id, b->line_id)
03735 && (a->tag_idx == b->tag_idx)
03736 && (a->tag_group == b->tag_group));
03737 }
03738
03739 void ht_uformat_viewer::sendsubmsg(int msg)
03740 {
03741 htmsg m;
03742 m.msg = msg;
03743 sendsubmsg(&m);
03744 }
03745
03746 void ht_uformat_viewer::sendsubmsg(htmsg *msg)
03747 {
03748 if (msg->type==mt_broadcast) {
03749 ht_sub *s=first_sub;
03750 while (s) {
03751 s->handlemsg(msg);
03752 s=s->next;
03753 }
03754 } else cursor.sub->handlemsg(msg);
03755 }
03756
03757 bool ht_uformat_viewer::set_cursor(uformat_viewer_pos p)
03758 {
03759 cursorline_dirty();
03760 uformat_viewer_pos t = top;
03761 int ty = 0;
03762
03763
03764
03765 do {
03766
03767 if ((t.sub == p.sub) && compeq_line_id(t.line_id, p.line_id)) {
03768 cursor = p;
03769 if (p.tag_group != -1) cursor.tag_group = p.tag_group;
03770 adjust_cursor_group();
03771 if (p.tag_idx !=-1) cursor.tag_idx = p.tag_idx;
03772 adjust_cursor_idx();
03773 cursor_ypos = ty;
03774 update_misc_info();
03775 update_visual_info();
03776 check_cursor_visibility();
03777 cursorline_dirty();
03778 dirtyview();
03779 return true;
03780 }
03781 } while ((next_line(&t, 1)) && (ty++ < size.h-1));
03782
03783
03784
03785 char line[1024];
03786 char *e;
03787 p.sub->getline(line, p.line_id);
03788 e = tag_get_selectable_tag(line, 0, 0);
03789 if (!e) return 0;
03790 cursor = p;
03791 if (p.tag_group != -1) cursor.tag_group = p.tag_group;
03792 adjust_cursor_group();
03793 if (p.tag_idx != -1) cursor.tag_idx = p.tag_idx;
03794 adjust_cursor_idx();
03795 cursor_ypos=0;
03796
03797 top = p;
03798 update_misc_info();
03799 update_visual_info();
03800 check_cursor_visibility();
03801 cursorline_dirty();
03802 dirtyview();
03803 return true;
03804 }
03805
03806 void ht_uformat_viewer::scroll_up(int n)
03807 {
03808 cursor_ypos += prev_line(&top, n);
03809 cursorline_dirty();
03810 check_cursor_visibility();
03811 }
03812
03813 void ht_uformat_viewer::scroll_down(int n)
03814 {
03815 cursor_ypos -= next_line(&top, n);
03816 cursorline_dirty();
03817 check_cursor_visibility();
03818 }
03819
03820 bool ht_uformat_viewer::qword_to_offset(qword q, FILEOFS *ofs)
03821 {
03822
03823 *ofs = QWORD_GET_INT(q);
03824 return true;
03825 }
03826
03827 void ht_uformat_viewer::update_micropos()
03828 {
03829 cursorline_get();
03830 char *e=tag_get_selectable_tag(cursor_line, cursor.tag_idx, cursor.tag_group);
03831 if (e) {
03832 int s=tag_get_microsize(e);
03833 if (cursor_tag_micropos>=s) cursor_tag_micropos=s-1;
03834 }
03835 }
03836
03837 void ht_uformat_viewer::update_misc_info()
03838 {
03839 cursorline_get();
03840 char *e=tag_get_selectable_tag(cursor_line, cursor.tag_idx, cursor.tag_group);
03841 if (e) {
03842 cursor_tag_class=tag_get_class(e);
03843 switch (cursor_tag_class) {
03844 case tag_class_edit:
03845 cursor_tag_offset=tag_get_offset(e);
03846 break;
03847 case tag_class_sel:
03848 clear_line_id(&cursor_tag_id.id);
03849 tag_get_id(e, &cursor_tag_id.id.id1, &cursor_tag_id.id.id2, &cursor_tag_id.id.id3, &cursor_tag_id.id.id4);
03850 break;
03851 }
03852 }
03853 }
03854
03855 void ht_uformat_viewer::update_visual_info()
03856 {
03857 cursorline_get();
03858 char *s, *t=cursor_line;
03859 int v=0, vl=0;
03860 int i=0, g=0;
03861 while ((s=tag_findnext(t))) {
03862 int cl=tag_get_class(s);
03863 if (s[1]==HT_TAG_GROUP) {
03864 i=0;
03865 g++;
03866 }
03867 v+=s-t;
03868 vl=tag_get_vlen(s);
03869 if ((i==cursor.tag_idx) && (g==cursor.tag_group) && (cl!=tag_class_no)) break;
03870 v+=vl;
03871 t=s+tag_get_len(s);
03872 if (cl!=tag_class_no) i++;
03873 }
03874
03875 if (cursor_tag_micropos > vl-1) cursor_tag_micropos = vl ? vl-1 : 0;
03876 cursor_visual_xpos=v;
03877 cursor_visual_length=vl;
03878 }
03879
03880 void ht_uformat_viewer::update_ypos()
03881 {
03882 uformat_viewer_pos p = top;
03883 int y=0;
03884 while ((next_line(&p, 1)) && (y<size.h)) {
03885 if (compeq_viewer_pos(&p, &cursor)) {
03886 cursor_ypos=y;
03887 break;
03888 }
03889 y++;
03890 }
03891 }
03892
03893 void ht_uformat_viewer::vstate_restore(Object *data)
03894 {
03895 ht_uformat_viewer_vstate *vs = (ht_uformat_viewer_vstate*)data;
03896 first_sub = vs->first_sub;
03897 last_sub = vs->last_sub;
03898
03899 top = vs->top;
03900
03901 cursor = vs->cursor;
03902 cursor_state = vs->cursor_state;
03903 cursor_ypos = vs->cursor_ypos;
03904
03905 sel_start = vs->sel_start;
03906 sel_end = vs->sel_end;
03907
03908 cursorline_dirty();
03909 update_misc_info();
03910 update_visual_info();
03911 }
03912
03913 Object *ht_uformat_viewer::vstate_create()
03914 {
03915 ht_uformat_viewer_vstate *vs = new ht_uformat_viewer_vstate();
03916 vs->first_sub = first_sub;
03917 vs->last_sub = last_sub;
03918
03919 vs->top = top;
03920
03921 vs->cursor = cursor;
03922 vs->cursor_state = cursor_state;
03923 vs->cursor_ypos = cursor_ypos;
03924
03925 vs->sel_start = sel_start;
03926 vs->sel_end = sel_end;
03927
03928 return vs;
03929 }
03930
03931
03932
03933
03934
03935 void ht_sub::init(ht_streamfile *f)
03936 {
03937 Object::init();
03938 uformat_viewer=NULL;
03939 prev=NULL;
03940 next=NULL;
03941 file=f;
03942 }
03943
03944 void ht_sub::done()
03945 {
03946 Object::done();
03947 }
03948
03949 bool ht_sub::closest_line_id(LINE_ID *line_id)
03950 {
03951 first_line_id(line_id);
03952 return true;
03953 }
03954
03955 bool ht_sub::convert_ofs_to_id(const FILEOFS offset, LINE_ID *line_id)
03956 {
03957 return false;
03958 }
03959
03960 bool ht_sub::convert_id_to_ofs(const LINE_ID line_id, FILEOFS *offset)
03961 {
03962 return false;
03963 }
03964
03965 bool ht_sub::getline(char *line, const LINE_ID line_id)
03966 {
03967 return false;
03968 }
03969
03970 void ht_sub::handlemsg(htmsg *msg)
03971 {
03972 }
03973
03974 void ht_sub::first_line_id(LINE_ID *line_id)
03975 {
03976 }
03977
03978 void ht_sub::last_line_id(LINE_ID *line_id)
03979 {
03980 }
03981
03982 int ht_sub::prev_line_id(LINE_ID *line_id, int n)
03983 {
03984 return 0;
03985 }
03986
03987 int ht_sub::next_line_id(LINE_ID *line_id, int n)
03988 {
03989 return 0;
03990 }
03991
03992 bool ht_sub::ref(LINE_ID *id)
03993 {
03994 return false;
03995 }
03996
03997 ht_search_result *ht_sub::search(ht_search_request *search, FILEOFS start, FILEOFS end)
03998 {
03999 return NULL;
04000 }
04001
04002
04003
04004
04005
04006 void ht_linear_sub::init(ht_streamfile *f, FILEOFS ofs, int size)
04007 {
04008 ht_sub::init(f);
04009 fofs=ofs;
04010 fsize=size;
04011 }
04012
04013 void ht_linear_sub::done()
04014 {
04015 ht_sub::done();
04016 }
04017
04018 void ht_linear_sub::handlemsg(htmsg *msg)
04019 {
04020 if (msg->msg==msg_filesize_changed) {
04021 UINT s=file->get_size();
04022 if (fofs>s) {
04023 fsize=0;
04024 } else if (fofs+fsize>s) {
04025 fsize=s-fofs;
04026 }
04027 return;
04028 }
04029 }
04030
04031 int ht_linear_func_readbyte(eval_scalar *result, eval_int *offset)
04032 {
04033 struct context_t {
04034 ht_linear_sub *sub;
04035 ht_format_viewer *fv;
04036 int i, o;
04037 };
04038 ht_format_viewer *f=((context_t*)eval_get_context())->fv;
04039 byte b;
04040 if (f->pread(QWORD_GET_INT(offset->value), &b, 1)!=1) {
04041 set_eval_error("i/o error (requested %d, read %d from ofs %08x)", 1, 0, offset->value);
04042 return 0;
04043 }
04044 scalar_create_int_c(result, b);
04045 return 1;
04046 }
04047
04048 int ht_linear_func_readstring(eval_scalar *result, eval_int *offset, eval_int *len)
04049 {
04050 struct context_t {
04051 ht_linear_sub *sub;
04052 ht_format_viewer *fv;
04053 int i, o;
04054 };
04055 ht_format_viewer *f=((context_t*)eval_get_context())->fv;
04056
04057 UINT l=QWORD_GET_INT(len->value);
04058 void *buf=malloc(l);
04059
04060 if (buf) {
04061 eval_str s;
04062 UINT c=f->pread(QWORD_GET_INT(offset->value), buf, l);
04063 if (c!=l) {
04064 free(buf);
04065 set_eval_error("i/o error (requested %d, read %d from ofs %08x)", l, c, offset->value);
04066 return 0;
04067 }
04068 s.value=(char*)buf;
04069 s.len=l;
04070 scalar_create_str(result, &s);
04071 free(buf);
04072 return 1;
04073 }
04074 set_eval_error("out of memory");
04075 return 0;
04076 }
04077
04078 int ht_linear_func_entropy(eval_scalar *result, eval_str *buf)
04079 {
04080 scalar_create_int_c(result, calc_entropy2((byte *)buf->value, buf->len));
04081 return 1;
04082 }
04083
04084 int ht_linear_func_entropy2(eval_scalar *result, eval_str *buf)
04085 {
04086 scalar_create_float_c(result, calc_entropy((byte *)buf->value, buf->len));
04087 return 1;
04088 }
04089
04090 struct search_expr_eval_context_t {
04091 ht_sub *sub;
04092 ht_format_viewer *fv;
04093 int i, o;
04094 };
04095
04096 int ht_linear_sub_func_handler(eval_scalar *result, char *name, eval_scalarlist *params)
04097 {
04098 eval_func myfuncs[] = {
04099 {"entropy", (void*)&ht_linear_func_entropy, {SCALAR_STR}},
04100 {"entropy2", (void*)&ht_linear_func_entropy2, {SCALAR_STR}},
04101 {"readbyte", (void*)&ht_linear_func_readbyte, {SCALAR_INT}},
04102 {"readstring", (void*)&ht_linear_func_readstring, {SCALAR_INT, SCALAR_INT}},
04103 {NULL}
04104 };
04105 return std_eval_func_handler(result, name, params, myfuncs);
04106 }
04107
04108 int ht_linear_sub_symbol_handler(eval_scalar *result, char *name)
04109 {
04110 search_expr_eval_context_t *context =
04111 (search_expr_eval_context_t*)eval_get_context();
04112 if (strcmp(name, "i")==0) {
04113 scalar_create_int_c(result, context->i);
04114 return 1;
04115 } else if (strcmp(name, "o")==0) {
04116 scalar_create_int_c(result, context->o);
04117 return 1;
04118 } else return 0;
04119 }
04120
04121 class ht_expr_search_pcontext: public Object {
04122 public:
04123
04124 ht_search_request *request;
04125 ht_sub *sub;
04126 ht_format_viewer *fv;
04127 FILEOFS start;
04128 FILEOFS end;
04129 int i;
04130 FILEOFS o;
04131
04132 ht_search_result **result;
04133 };
04134
04135 bool process_search_expr(Object *ctx, ht_text *progress_indicator)
04136 {
04137 #define PROCESS_EXPR_SEARCH_BYTES_PER_CALL 256
04138 ht_expr_search_pcontext *c=(ht_expr_search_pcontext*)ctx;
04139 ht_expr_search_request *s=(ht_expr_search_request*)c->request;
04140
04141 search_expr_eval_context_t context;
04142 context.sub = c->sub;
04143 context.fv = c->fv;
04144 int w=PROCESS_EXPR_SEARCH_BYTES_PER_CALL;
04145 while (c->o < c->end) {
04146 eval_scalar r;
04147 context.i = c->i;
04148 context.o = c->o;
04149 if (eval(&r, s->expr, ht_linear_sub_func_handler, ht_linear_sub_symbol_handler, &context)) {
04150 eval_int i;
04151 scalar_context_int(&r, &i);
04152 if (i.value != to_qword(0)) {
04153 ht_physical_search_result *r=new ht_physical_search_result();
04154 r->offset = c->o;
04155 r->size = 1;
04156 *c->result = r;
04157 return false;
04158 }
04159 } else {
04160 char *str;
04161 int pos;
04162 get_eval_error(&str, &pos);
04163 throw new ht_io_exception("eval error at pos %d: %s", pos, str);
04164 }
04165 c->i++;
04166 c->o++;
04167
04168 if (!--w) {
04169 char text[64];
04170 if (c->end > c->start) {
04171 sprintf(text, "%d %% done", (c->o - c->start) * 100 / (c->end - c->start));
04172 } else {
04173 strcpy(text, "? % done");
04174 }
04175 progress_indicator->settext(text);
04176
04177 return true;
04178 }
04179 }
04180 return false;
04181 }
04182
04183 ht_search_result *linear_expr_search(ht_search_request *search, FILEOFS start, FILEOFS end, ht_sub *sub, ht_uformat_viewer *ufv, FILEOFS fofs, dword fsize)
04184 {
04185 if (start<fofs) start=fofs;
04186 if (end>fofs+fsize) end=fofs+fsize;
04187 if (fsize) {
04188 ht_search_result *r=NULL;
04189 ht_expr_search_pcontext c;
04190 c.request=search;
04191 c.sub=sub;
04192 c.fv=ufv;
04193 c.start=start;
04194 c.end=end;
04195 c.result=&r;
04196 c.i=0;
04197 c.o=start;
04198 if (execute_process(process_search_expr, &c)) return r;
04199 }
04200 return NULL;
04201 }
04202
04203 ht_search_result *ht_linear_sub::search(ht_search_request *search, FILEOFS start, FILEOFS end)
04204 {
04205 ht_search_result *r = NULL;
04206 if ((search->search_class==SC_PHYSICAL) && (search->type==ST_EXPR)) {
04207 r = linear_expr_search(search, start, end, this, uformat_viewer, fofs, fsize);
04208 } else if ((search->search_class==SC_PHYSICAL) && (search->type==ST_FXBIN)) {
04209 r = linear_bin_search(search, start, end, file, fofs, fsize);
04210 }
04211 return r;
04212 }
04213
04214
04215
04216
04217
04218 void ht_hex_sub::init(ht_streamfile *f, FILEOFS ofs, dword size, UINT Line_length, UINT u, dword vinc)
04219 {
04220 line_length = Line_length;
04221 ht_linear_sub::init(f, ofs, size);
04222 vaddrinc=vinc;
04223 balign=ofs % line_length;
04224 uid=u;
04225 }
04226
04227 void ht_hex_sub::done()
04228 {
04229 ht_linear_sub::done();
04230 }
04231
04232 int ht_hex_sub::get_line_length()
04233 {
04234 return line_length;
04235 }
04236
04237 void ht_hex_sub::set_line_length(int Line_length)
04238 {
04239 if (Line_length>0) {
04240 line_length = Line_length;
04241
04242
04243 }
04244 }
04245
04246
04247 bool ht_hex_sub::convert_ofs_to_id(const FILEOFS offset, LINE_ID *line_id)
04248 {
04249 if ((offset>=fofs) && (offset<fofs+fsize)) {
04250 clear_line_id(line_id);
04251 line_id->id1 = (offset - (offset%line_length)) + balign;
04252 line_id->id2 = uid;
04253 return true;
04254 }
04255 return false;
04256 }
04257
04258 bool ht_hex_sub::convert_id_to_ofs(const LINE_ID line_id, FILEOFS *ofs)
04259 {
04260 *ofs = line_id.id1;
04261 return true;
04262 }
04263
04264 bool ht_hex_sub::getline(char *line, const LINE_ID line_id)
04265 {
04266 if (line_id.id2 != uid) return false;
04267 ID ofs = line_id.id1;
04268 uint c = MIN(line_length, (fofs+fsize-ofs));
04269 if (c<=0) return false;
04270 c = MIN(line_length, c+ofs%line_length);
04271 char *l=line;
04272 l=mkhexd(l, ofs+vaddrinc);
04273 *l++=' ';
04274 if (ofs % line_length) ofs -= ofs % line_length;
04275 for (dword i=0; i<line_length; i++) {
04276 if (i<c && ofs+i>=fofs) {
04277 l=tag_make_edit_byte(l, ofs+i);
04278 } else {
04279 *l++=' ';
04280 *l++=' ';
04281 }
04282 if (i+1<c && ofs+i>=fofs) {
04283 if (i%8==7) {
04284 l=tag_make_edit_selvis(l, ofs+i, '-');
04285 } else {
04286 l=tag_make_edit_selvis(l, ofs+i, ' ');
04287 }
04288 } else *l++=' ';
04289 }
04290 l=tag_make_group(l);
04291 *l++='|';
04292 for (dword i=0; i<line_length; i++) {
04293 if (i<c && ofs+i>=fofs) {
04294 l=tag_make_edit_char(l, ofs+i);
04295 } else {
04296 *l++=' ';
04297 }
04298 }
04299 *l++='|';
04300 *l=0;
04301 return true;
04302 }
04303
04304 void ht_hex_sub::handlemsg(htmsg *msg)
04305 {
04306 ht_linear_sub::handlemsg(msg);
04307 }
04308
04309 void ht_hex_sub::first_line_id(LINE_ID *line_id)
04310 {
04311 clear_line_id(line_id);
04312 line_id->id1 = fofs;
04313 line_id->id2 = uid;
04314 }
04315
04316 void ht_hex_sub::last_line_id(LINE_ID *line_id)
04317 {
04318 clear_line_id(line_id);
04319 if (fsize) {
04320 int k = fsize + (fofs % line_length);
04321 line_id->id1 = (k - k%line_length) + (fofs - fofs%line_length);
04322 } else {
04323 line_id->id1 = fofs;
04324 }
04325 line_id->id2 = uid;
04326 }
04327
04328 int ht_hex_sub::prev_line_id(LINE_ID *line_id, int n)
04329 {
04330 if (line_id->id2 != uid) return 0;
04331 int c=0;
04332 while (n--) {
04333 if (!line_id->id1 || line_id->id1 == fofs) break;
04334 if (line_id->id1-line_length>line_id->id1) {
04335 line_id->id1 = 0;
04336 } else {
04337 if (line_id->id1-line_length<fofs) {
04338 line_id->id1 = fofs;
04339 } else {
04340 line_id->id1 -= line_length;
04341 }
04342 }
04343 c++;
04344 }
04345 return c;
04346 }
04347
04348 int ht_hex_sub::next_line_id(LINE_ID *line_id, int n)
04349 {
04350 if (line_id->id2 != uid) return 0;
04351 int c=0;
04352 while (n--) {
04353 if (line_id->id1 % line_length) {
04354 if (line_id->id1+(line_length - line_id->id1 % line_length) >= fofs+fsize) break;
04355 line_id->id1 += line_length- line_id->id1 % line_length;
04356 } else {
04357 if (line_id->id1+line_length>=fofs+fsize) break;
04358 line_id->id1 += line_length;
04359 }
04360 c++;
04361 }
04362 return c;
04363 }
04364
04365
04366
04367
04368
04369 void ht_mask_sub::init(ht_streamfile *f, UINT u)
04370 {
04371 ht_sub::init(f);
04372 masks = new ht_string_list();
04373 masks->init();
04374 uid = u;
04375 }
04376
04377 void ht_mask_sub::done()
04378 {
04379 masks->destroy();
04380 delete masks;
04381 ht_sub::done();
04382 }
04383
04384 void ht_mask_sub::first_line_id(LINE_ID *line_id)
04385 {
04386 clear_line_id(line_id);
04387 line_id->id1 = 0;
04388 line_id->id2 = uid;
04389 }
04390
04391 bool ht_mask_sub::getline(char *line, const LINE_ID line_id)
04392 {
04393 if (line_id.id2 != uid) return false;
04394 char *s=masks->get_string(line_id.id1);
04395 if (s) {
04396 tag_strcpy(line, s);
04397 return true;
04398 }
04399 return false;
04400 }
04401
04402 void ht_mask_sub::last_line_id(LINE_ID *line_id)
04403 {
04404 clear_line_id(line_id);
04405 line_id->id1 = masks->count()-1;
04406 line_id->id2 = uid;
04407 }
04408
04409 int ht_mask_sub::next_line_id(LINE_ID *line_id, int n)
04410 {
04411 int r=n;
04412 if (line_id->id2 != uid) return 0;
04413 int c=masks->count();
04414 ID i1 = line_id->id1;
04415 i1+=n;
04416 if ((int)i1>c-1) {
04417 r-=i1-c+1;
04418 i1=c-1;
04419 }
04420 if (r) line_id->id1=i1;
04421 return r;
04422 }
04423
04424 int ht_mask_sub::prev_line_id(LINE_ID *line_id, int n)
04425 {
04426 int r;
04427 if (line_id->id2!=uid) return 0;
04428 ID i1=line_id->id1;
04429 if (i1<(dword)n) {
04430 r=i1;
04431 i1=0;
04432 } else {
04433 r=n;
04434 i1-=n;
04435 }
04436 if (r) line_id->id1=i1;
04437 return r;
04438 }
04439
04440 void ht_mask_sub::add_mask(char *tagstr)
04441 {
04442 masks->insert(new ht_data_tagstring(tagstr));
04443 }
04444
04445 void ht_mask_sub::add_mask_table(char **tagstr)
04446 {
04447 while (*tagstr) add_mask(*(tagstr++));
04448 }
04449
04450 void ht_mask_sub::add_staticmask(char *statictag_str, FILEOFS reloc, bool std_bigendian)
04451 {
04452 char tag_str[1024];
04453 statictag_to_tag(statictag_str, tag_str, reloc, std_bigendian);
04454 masks->insert(new ht_data_tagstring(tag_str));
04455 }
04456
04457 void ht_mask_sub::add_staticmask_table(char **statictag_table, FILEOFS reloc, bool std_bigendian)
04458 {
04459 while (*statictag_table) add_staticmask(*(statictag_table++), reloc, std_bigendian);
04460 }
04461
04462 #define ht_MASK_STD_INDENT 50
04463
04464 void ht_mask_sub::add_staticmask_ptable(ht_mask_ptable *statictag_ptable, FILEOFS reloc, bool std_bigendian)
04465 {
04466 char s[1024];
04467 while (statictag_ptable->desc || statictag_ptable->fields) {
04468 s[0]=0;
04469 if (statictag_ptable->desc) strcpy(s, statictag_ptable->desc);
04470 int n=strlen(s);
04471 while (n<ht_MASK_STD_INDENT) {
04472 s[n]=' ';
04473 n++;
04474 }
04475 s[n]=0;
04476 if (statictag_ptable->fields) strcat(s, statictag_ptable->fields);
04477
04478 add_staticmask(s, reloc, std_bigendian);
04479
04480 statictag_ptable++;
04481 }
04482 }
04483
04484
04485
04486
04487
04488 void ht_layer_sub::init(ht_streamfile *file, ht_sub *s, bool own_s=1)
04489 {
04490 ht_sub::init(file);
04491 sub=s;
04492 own_sub=own_s;
04493 }
04494
04495 void ht_layer_sub::done()
04496 {
04497 if (own_sub) {
04498 sub->done();
04499 delete sub;
04500 }
04501 ht_sub::done();
04502 }
04503
04504 bool ht_layer_sub::closest_line_id(LINE_ID *line_id)
04505 {
04506 return sub->closest_line_id(line_id);
04507 }
04508
04509 bool ht_layer_sub::convert_ofs_to_id(const FILEOFS offset, LINE_ID *line_id)
04510 {
04511 return sub->convert_ofs_to_id(offset, line_id);
04512 }
04513
04514 bool ht_layer_sub::convert_id_to_ofs(const LINE_ID line_id, FILEOFS *offset)
04515 {
04516 return sub->convert_id_to_ofs(line_id, offset);
04517 }
04518
04519 void ht_layer_sub::first_line_id(LINE_ID *line_id)
04520 {
04521 return sub->first_line_id(line_id);
04522 }
04523
04524 bool ht_layer_sub::getline(char *line, const LINE_ID line_id)
04525 {
04526 return sub->getline(line, line_id);
04527 }
04528
04529 void ht_layer_sub::handlemsg(htmsg *msg)
04530 {
04531 sub->handlemsg(msg);
04532 }
04533
04534 void ht_layer_sub::last_line_id(LINE_ID *line_id)
04535 {
04536 return sub->last_line_id(line_id);
04537 }
04538
04539 int ht_layer_sub::next_line_id(LINE_ID *line_id, int n)
04540 {
04541 return sub->next_line_id(line_id, n);
04542 }
04543
04544 int ht_layer_sub::prev_line_id(LINE_ID *line_id, int n)
04545 {
04546 return sub->prev_line_id(line_id, n);
04547 }
04548
04549 bool ht_layer_sub::ref(LINE_ID *id)
04550 {
04551 return sub->ref(id);
04552 }
04553
04554 ht_search_result *ht_layer_sub::search(ht_search_request *search, FILEOFS start, FILEOFS end)
04555 {
04556 return sub->search(search, start, end);
04557 }
04558
04559
04560
04561
04562
04563 ID ht_collapsable_sub_globalfaddr=0xffffffff;
04564
04565 void ht_collapsable_sub::init(ht_streamfile *file, ht_sub *sub, bool own_sub, char *ns, bool c)
04566 {
04567 ht_layer_sub::init(file, sub, own_sub);
04568 nodestring = ht_strdup(ns);
04569 collapsed = c;
04570 ht_layer_sub::first_line_id(&fid);
04571
04572
04573 clear_line_id(&myfid);
04574 myfid.id1 = 0;
04575 myfid.id2 = ht_collapsable_sub_globalfaddr--;
04576 }
04577
04578 void ht_collapsable_sub::done()
04579 {
04580 if (nodestring) free(nodestring);
04581 ht_layer_sub::done();
04582 }
04583
04584 bool ht_collapsable_sub::convert_ofs_to_id(const FILEOFS offset, LINE_ID *line_id)
04585 {
04586
04587
04588
04589
04590
04591 if (!collapsed) {
04592 return ht_layer_sub::convert_ofs_to_id(offset, line_id);
04593 }
04594 return false;
04595 }
04596
04597 bool ht_collapsable_sub::convert_id_to_ofs(const LINE_ID line_id, FILEOFS *offset)
04598 {
04599 return ht_layer_sub::convert_id_to_ofs(line_id, offset);
04600 }
04601
04602 void ht_collapsable_sub::first_line_id(LINE_ID *line_id)
04603 {
04604 clear_line_id(line_id);
04605 *line_id = myfid;
04606 }
04607
04608 bool ht_collapsable_sub::getline(char *line, const LINE_ID line_id)
04609 {
04610 if (compeq_line_id(line_id, myfid)) {
04611 line+=sprintf(line, "[%c] ", collapsed ? '+' : '-');
04612 line=tag_make_ref(line, myfid.id1, myfid.id2, 0, 0, nodestring);
04613 *line=0;
04614 return true;
04615 } else if (collapsed) return false;
04616 if (ht_layer_sub::getline(line, line_id)) {
04617 memmove(line+2, line, tag_strlen(line)+1);
04618 line[0]=' ';
04619 line[1]=' ';
04620 return true;
04621 }
04622 return false;
04623 }
04624
04625 void ht_collapsable_sub::last_line_id(LINE_ID *line_id)
04626 {
04627 if (collapsed) return first_line_id(line_id); else
04628 return ht_layer_sub::last_line_id(line_id);
04629 }
04630
04631 int ht_collapsable_sub::next_line_id(LINE_ID *line_id, int n)
04632 {
04633 if (collapsed) return 0;
04634 int r=0;
04635 LINE_ID t;
04636 if (compeq_line_id(*line_id, myfid)) {
04637 ht_layer_sub::first_line_id(&t);
04638 n--;
04639 r++;
04640 } else {
04641 t = *line_id;
04642 }
04643 if (n) r+=ht_layer_sub::next_line_id(&t, n);
04644 if (r) {
04645 *line_id = t;
04646 }
04647 return r;
04648 }
04649
04650 int ht_collapsable_sub::prev_line_id(LINE_ID *line_id, int n)
04651 {
04652 if (collapsed) return 0;
04653 if (compeq_line_id(*line_id, myfid)) return 0;
04654 int r=ht_layer_sub::prev_line_id(line_id, n);
04655 if (compeq_line_id(*line_id, fid) && (r<n)) {
04656 *line_id = myfid;
04657 r++;
04658 }
04659 return r;
04660 }
04661
04662 bool ht_collapsable_sub::ref(LINE_ID *id)
04663 {
04664 if (compeq_line_id(*id, myfid)) {
04665 collapsed=!collapsed;
04666 return true;
04667 }
04668 if (!collapsed) return ht_layer_sub::ref(id);
04669 return false;
04670 }
04671
04672 ht_search_result *ht_collapsable_sub::search(ht_search_request *search, FILEOFS start, FILEOFS end)
04673 {
04674 if (collapsed) return NULL;
04675 return ht_layer_sub::search(search, start, end);
04676 }
04677
04678
04679
04680
04681
04682 void ht_group_sub::init(ht_streamfile *file)
04683 {
04684 ht_sub::init(file);
04685 subs=new ht_clist();
04686 subs->init();
04687 }
04688
04689 void ht_group_sub::done()
04690 {
04691 subs->done();
04692 delete subs;
04693 ht_sub::done();
04694 }
04695
04696 bool ht_group_sub::convert_ofs_to_id(const FILEOFS offset, LINE_ID *line_id)
04697 {
04698 return false;
04699 }
04700
04701 bool ht_group_sub::convert_id_to_ofs(const LINE_ID line_id, FILEOFS *offset)
04702 {
04703 return false;
04704 }
04705
04706 void ht_group_sub::first_line_id(LINE_ID *line_id)
04707 {
04708 ht_sub *s = (ht_sub*)subs->get(0);
04709 if (s) s->first_line_id(line_id);
04710 }
04711
04712 bool ht_group_sub::getline(char *line, const LINE_ID line_id)
04713 {
04714 ht_sub *s;
04715 UINT c=subs->count();
04716 for (UINT i=0; i<c; i++) {
04717 s=(ht_sub*)subs->get(i);
04718 if (s->getline(line, line_id)) return true;
04719 }
04720 return false;
04721 }
04722
04723 void ht_group_sub::handlemsg(htmsg *msg)
04724 {
04725 ht_sub::handlemsg(msg);
04726 }
04727
04728 void ht_group_sub::last_line_id(LINE_ID *line_id)
04729 {
04730 ht_sub *s = (ht_sub*)subs->get(subs->count()-1);
04731 if (s) s->last_line_id(line_id);
04732 }
04733
04734 int ht_group_sub::next_line_id(LINE_ID *line_id, int n)
04735 {
04736 ht_sub *s;
04737 UINT c=subs->count();
04738 int on=n;
04739 for (UINT i=0; i<c; i++) {
04740 s=(ht_sub*)subs->get(i);
04741 LINE_ID t;
04742 s->last_line_id(&t);
04743 if (compeq_line_id(t, *line_id)) {
04744 s=(ht_sub*)subs->get(i+1);
04745 if (s) {
04746 s->first_line_id(line_id);
04747 n--;
04748 }
04749 } else {
04750 n-=s->next_line_id(line_id, n);
04751 }
04752 if (!n) break;
04753 }
04754 return on-n;
04755 }
04756
04757 int ht_group_sub::prev_line_id(LINE_ID *line_id, int n)
04758 {
04759 ht_sub *s;
04760 UINT c=subs->count();
04761 int on=n;
04762 for (UINT i=0; i<c; i++) {
04763 s=(ht_sub*)subs->get(i);
04764 LINE_ID t;
04765 s->first_line_id(&t);
04766 if (compeq_line_id(t, *line_id)) {
04767 s=(ht_sub*)subs->get(i-1);
04768 if (s) {
04769 s->last_line_id(line_id);
04770 n--;
04771 }
04772 } else {
04773 n-=s->prev_line_id(line_id, n);
04774 }
04775 if (!n) break;
04776 }
04777 return on-n;
04778 }
04779
04780 bool ht_group_sub::ref(LINE_ID *id)
04781 {
04782 ht_sub *s;
04783 UINT c=subs->count();
04784 for (UINT i=0; i<c; i++) {
04785 s=(ht_sub*)subs->get(i);
04786 if (s->ref(id)) return true;
04787 }
04788 return false;
04789 }
04790
04791 ht_search_result *ht_group_sub::search(ht_search_request *search, FILEOFS start, FILEOFS end)
04792 {
04793 return NULL;
04794 }
04795
04796 void ht_group_sub::insertsub(ht_sub *sub)
04797 {
04798 subs->insert(sub);
04799 }
04800
04801
04802
04803
04804
04805 ht_data_tagstring::ht_data_tagstring(char *tagstr)
04806 : ht_data_string()
04807 {
04808 value=tag_strdup(tagstr);
04809 }
04810
04811 ht_data_tagstring::~ht_data_tagstring()
04812 {
04813 }
04814
04815