00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "analy.h"
00022 #include "cmds.h"
00023 #include "log.h"
00024 #include "mfile.h"
00025 #include "htapp.h"
00026 #include "htatom.h"
00027 #include "htcfg.h"
00028 #include "htclipboard.h"
00029 #include "htdialog.h"
00030 #include "hteval.h"
00031 #include "hthist.h"
00032 #include "htidle.h"
00033 #include "htinfo.h"
00034 #include "htiobox.h"
00035 #include "htkeyb.h"
00036 #include "htmenu.h"
00037 #include "htpal.h"
00038 #include "htsearch.h"
00039 #include "htstring.h"
00040 #include "htsys.h"
00041 #include "httree.h"
00042 #include "infoview.h"
00043 #include "snprintf.h"
00044 #include "stream.h"
00045 #include "terminal.h"
00046 #include "textedit.h"
00047 #include "textfile.h"
00048 #include "tools.h"
00049
00050 #include "vfsview.h"
00051
00052 #include "formats.h"
00053
00054 #include <errno.h>
00055 #include <stdarg.h>
00056 #include <stdlib.h>
00057 #include <string.h>
00058 #include <sys/stat.h>
00059 #include <sys/types.h>
00060 #include <time.h>
00061 #include <unistd.h>
00062
00063 extern "C" {
00064 #include "regex.h"
00065 }
00066
00067 #define ATOM_HT_APP MAGICD("APP\x00")
00068 #define ATOM_HT_PROJECT MAGICD("APP\x01")
00069 #define ATOM_HT_PROJECT_ITEM MAGICD("APP\x02")
00070 #define ATOM_COMPARE_KEYS_PROJECT_ITEM MAGICD("APP\x10")
00071
00072 #define HT_PROJECT_CONFIG_SUFFIX ".htprj"
00073 #define HT_FILE_CONFIG_SUFFIX ".htcfg"
00074
00075 ht_log *loglines;
00076
00077
00078
00079
00080
00081 class ht_help_window : public ht_window {
00082 public:
00083
00084 virtual void handlemsg(htmsg *msg);
00085 };
00086
00087 void ht_help_window::handlemsg(htmsg *msg)
00088 {
00089 ht_window::handlemsg(msg);
00090 if (msg->msg == msg_keypressed) {
00091 switch (msg->data1.integer) {
00092 case K_Escape: {
00093 htmsg m;
00094 m.msg = cmd_window_close;
00095 ((ht_app*)app)->queuemsg(app, &m);
00096 clearmsg(msg);
00097 return;
00098 }
00099 }
00100 }
00101 }
00102
00103 bool file_new_dialog(UINT *mode)
00104 {
00105 bounds b, c;
00106
00107 app->getbounds(&b);
00108
00109 b.x = (b.w - 40) / 2,
00110 b.y = (b.h - 8) / 2;
00111 b.w = 40;
00112 b.h = 8;
00113
00114 ht_dialog *d=new ht_dialog();
00115 d->init(&b, "create new file", FS_KILLER | FS_TITLE | FS_MOVE | FS_RESIZE);
00116
00117 b.x=0;
00118 b.y=0;
00119
00120
00121 c=b;
00122 c.x=0;
00123 c.y=1;
00124 c.w=b.w-2-c.x;
00125 c.h=b.h-2-c.y;
00126
00127 ht_text_listbox *mode_input=new ht_text_listbox();
00128 mode_input->init(&c);
00129
00130 mode_input->insert_str(FOM_TEXT, "text");
00131 mode_input->insert_str(FOM_BIN, "binary");
00132 mode_input->update();
00133
00134 d->insert(mode_input);
00135
00136
00137 c=b;
00138 c.x=0;
00139 c.y=0;
00140 c.w=12;
00141 c.h=1;
00142
00143 ht_label *mode_text=new ht_label();
00144 mode_text->init(&c, "choose ~type", mode_input);
00145
00146 d->insert(mode_text);
00147
00148 bool retval = false;
00149 if (d->run(false)) {
00150 struct {
00151 ht_listbox_data type;
00152 } data;
00153
00154 d->databuf_get(&data, sizeof data);
00155
00156 *mode = mode_input->getID(data.type.cursor_ptr);
00157
00158 retval = true;
00159 }
00160
00161 d->done();
00162 delete d;
00163 return retval;
00164 }
00165
00166
00167
00168
00169
00170 class FileBrowser;
00171
00172 #define FileBrowserVfsListboxData VfsListboxData
00173
00174 class FileBrowserVfsListbox: public VfsListbox {
00175 protected:
00176 FileBrowser *file_browser;
00177 public:
00178 void init(bounds *b, ht_list *vfs_list, ht_text *show_pos, FileBrowser *file_browser);
00179
00180 virtual void stateChanged();
00181 };
00182
00183
00184
00185
00186
00187 struct FileBrowserData {
00188 ht_strinputfield_data name;
00189 ht_listbox_data listbox;
00190 };
00191
00192 class FileBrowser: public ht_dialog {
00193 protected:
00194 ht_strinputfield *name_input;
00195 FileBrowserVfsListbox *listbox;
00196 public:
00197 virtual void init(bounds *b, bounds *clientarea, const char *title, const char *starturl);
00198
00199 virtual bool extract_url(char *buf);
00200 virtual void listbox_changed();
00201 };
00202
00203
00204 void FileBrowserVfsListbox::init(bounds *b, ht_list *vfs_list, ht_text *show_pos, FileBrowser *fb)
00205 {
00206 file_browser = NULL;
00207 VfsListbox::init(b, vfs_list, show_pos);
00208 file_browser = fb;
00209 }
00210
00211 void FileBrowserVfsListbox::stateChanged()
00212 {
00213 if (file_browser) file_browser->listbox_changed();
00214 VfsListbox::stateChanged();
00215 }
00216
00217
00218 void FileBrowser::init(bounds *n, bounds *clientarea, const char *title, const char *starturl)
00219 {
00220 ht_dialog::init(n, title, FS_KILLER | FS_TITLE | FS_MOVE | FS_RESIZE);
00221 bounds b = *clientarea, c;
00222
00223
00224 c = b;
00225 c.x = 1;
00226 c.y = 1;
00227 c.w -= 2;
00228 c.h = 1;
00229
00230 ht_list *hist=(ht_list*)find_atom(HISTATOM_FILE);
00231
00232 name_input=new ht_strinputfield();
00233 name_input->init(&c, 128, hist);
00234
00235 insert(name_input);
00236
00237
00238 c = b;
00239 c.x = 1;
00240 c.y = 0;
00241 c.w = 9;
00242 c.h = 1;
00243
00244 ht_label *name_text=new ht_label();
00245 name_text->init(&c, "~name", name_input);
00246
00247 insert(name_text);
00248
00249
00250 c = b;
00251 c.x = 1;
00252 c.y = 4;
00253 c.w -= 2;
00254 c.h -= 4;
00255 listbox = new FileBrowserVfsListbox();
00256 listbox->init(&c, virtual_fs_list, NULL, this);
00257 listbox->changeURL(starturl);
00258
00259 insert(listbox);
00260
00261
00262 c = b;
00263 c.x = 1;
00264 c.y = 3;
00265 c.w = 9;
00266 c.h = 1;
00267
00268 ht_label *name_listbox=new ht_label();
00269 name_listbox->init(&c, "~files", listbox);
00270
00271 insert(name_listbox);
00272 }
00273
00274 bool FileBrowser::extract_url(char *buf)
00275 {
00276 ht_strinputfield_data i;
00277 name_input->databuf_get(&i, sizeof i);
00278
00279
00280 Vfs *vfs = listbox->getCurVfs();
00281 if (vfs) {
00282 int buflen = ht_snprintf(buf, VFS_URL_MAX, "%s:", listbox->getCurProto());
00283 char fname[VFS_URL_MAX];
00284 bin2str(fname, i.text, i.textlen);
00285 vfs->canonicalize(buf+buflen, fname, listbox->getCurDir());
00286 return true;
00287 }
00288 return false;
00289 }
00290
00291 void FileBrowser::listbox_changed()
00292 {
00293 FileBrowserVfsListboxData l;
00294 listbox->databuf_get(&l, sizeof l);
00295 ht_text_listbox_item *t = (ht_text_listbox_item*)l.cursor_ptr;
00296 if (t) {
00297 vfs_extra *x = (vfs_extra*)t->extra_data;
00298 ht_strinputfield_data i;
00299 i.textlen = strlen(x->name);
00300 i.text = (byte*)x->name;
00301 name_input->databuf_set(&i, sizeof i);
00302 }
00303 }
00304
00305
00306 bool file_chooser(const char *title, char *buf, int bufsize)
00307 {
00308 bounds b, c;
00309
00310 app->getbounds(&b);
00311
00312 c = b;
00313 b.w = 60;
00314 b.h = 20;
00315 b.x = (c.w - b.w) / 2,
00316 b.y = (c.h - b.h) / 2;
00317
00318 c = b;
00319 c.x = 0;
00320 c.y = 0;
00321 c.w -= 2;
00322 c.h -= 3;
00323
00324
00325 char cwd[HT_NAME_MAX];
00326 strcpy(cwd, "local:");
00327 if (!getcwd(cwd+6, (sizeof cwd)-6)) {
00328 cwd[6] = 0;
00329 }
00330
00331 FileBrowser *d = new FileBrowser();
00332 d->init(&b, &c, title, cwd);
00333
00334 ht_list *hist = (ht_list*)find_atom(HISTATOM_FILE);
00335
00336
00337 if (d->run(false)) {
00338 char b[VFS_URL_MAX];
00339 d->extract_url(b);
00340
00341
00342 if (strncmp(b, "local:", 6) == 0) {
00343 ht_snprintf(buf, bufsize, "%s", b+6);
00344
00345 if (hist) insert_history_entry(hist, buf, 0);
00346
00347 d->done();
00348 delete d;
00349 return true;
00350 }
00351 }
00352 d->done();
00353 delete d;
00354 return false;
00355 }
00356
00357
00358 bool file_open_dialog(char **name, UINT *mode)
00359 {
00360 bounds b, c;
00361
00362 app->getbounds(&b);
00363
00364 c = b;
00365 b.w = 60;
00366 b.h = 20;
00367 b.x = (c.w - b.w) / 2,
00368 b.y = (c.h - b.h) / 2;
00369
00370 c = b;
00371 c.x = 0;
00372 c.y = 0;
00373 c.w -= 2;
00374 c.h -= 5;
00375
00376
00377 char cwd[HT_NAME_MAX];
00378 strcpy(cwd, "local:");
00379 if (!getcwd(cwd+6, (sizeof cwd)-6)) {
00380 cwd[6] = 0;
00381 }
00382
00383 FileBrowser *d = new FileBrowser();
00384 d->init(&b, &c, "open file", cwd);
00385
00386 ht_list *hist = (ht_list*)find_atom(HISTATOM_FILE);
00387
00388
00389 c=b;
00390 c.x=6;
00391 c.y=b.h-4;
00392 c.w=12;
00393 c.h=1;
00394
00395 ht_listpopup *mode_input=new ht_listpopup();
00396 mode_input->init(&c);
00397
00398 mode_input->insertstring("autodetect");
00399 mode_input->insertstring("binary");
00400 mode_input->insertstring("text");
00401
00402 d->insert(mode_input);
00403
00404
00405 c=b;
00406 c.x=1;
00407 c.y=b.h-4;
00408 c.w=9;
00409 c.h=1;
00410
00411 ht_label *mode_text=new ht_label();
00412 mode_text->init(&c, "~mode", mode_input);
00413
00414 d->insert(mode_text);
00415
00416
00417 if (d->run(false)) {
00418 struct {
00419 FileBrowserData browser;
00420 ht_listpopup_data mode;
00421 } data;
00422
00423 d->databuf_get(&data, sizeof data);
00424
00425 char buf[VFS_URL_MAX];
00426 d->extract_url(buf);
00427
00428
00429 if (strncmp(buf, "local:", 6) == 0) {
00430 *name = strdup(buf+6);
00431
00432 if (hist) insert_history_entry(hist, *name, 0);
00433
00434 switch (data.mode.cursor_pos) {
00435 case 0: *mode=FOM_AUTO; break;
00436 case 1: *mode=FOM_BIN; break;
00437 case 2: *mode=FOM_TEXT; break;
00438 }
00439
00440 d->done();
00441 delete d;
00442 return true;
00443 }
00444 }
00445 d->done();
00446 delete d;
00447 return false;
00448 }
00449
00450 UINT autodetect_file_open_mode(char *filename)
00451 {
00452 #define AUTODETECT_SIZE 128
00453 FILE *f=fopen(filename, "rb");
00454 UINT r=FOM_BIN;
00455 if (f) {
00456 byte buf[AUTODETECT_SIZE];
00457 int c=fread(buf, 1, AUTODETECT_SIZE, f);
00458
00459 if (!c) return FOM_TEXT;
00460 bool is_bin=false;
00461 UINT prob_bin_chars=0;
00462 for (int i=0; i<c; i++) {
00463 if (buf[i]==0) {
00464 is_bin=true;
00465 break;
00466 } else if (buf[i]<32) {
00467 prob_bin_chars++;
00468 } else if (buf[i]>0xa9) {
00469 prob_bin_chars++;
00470 }
00471 }
00472 if (c) {
00473 if (prob_bin_chars*100/c>=50) is_bin=true;
00474 } else is_bin=true;
00475 if (!is_bin) r=FOM_TEXT;
00476 fclose(f);
00477 return r;
00478 }
00479 return FOM_BIN;
00480 }
00481
00482 int file_window_load_fcfg_func(ht_object_stream *f, void *context)
00483 {
00484 ht_file_window *w=(ht_file_window*)context;
00485
00486 pstat_t p;
00487 dword oldsize = f->getIntDec(4, "filesize");
00488 dword oldtime = f->getIntDec(4, "filetime");
00489 dword newsize = w->file->get_size();
00490 w->file->pstat(&p);
00491 dword newtime = (p.caps & pstat_mtime) ? p.mtime : 0;
00492
00493 if (f->get_error()) return f->get_error();
00494
00495 if ((newsize != oldsize) || (newtime != oldtime)) {
00496 char s_oldtime[64], s_newtime[64];
00497 struct tm *t;
00498
00499 t=gmtime((time_t*)&newtime);
00500 strftime(s_newtime, sizeof s_newtime, "%X %d %b %Y", t);
00501
00502 t=gmtime((time_t*)&oldtime);
00503 strftime(s_oldtime, sizeof s_oldtime, "%X %d %b %Y", t);
00504
00505 if (confirmbox_c("\ecconfig file applies to different version of file '%s'.\n\n\elcurrent: %10d %s\n\elold: %10d %s\n\n\ecload config file ?", w->file->get_desc(), newsize, s_newtime, oldsize, s_oldtime) != button_yes) {
00506 return f->get_error();
00507 }
00508 }
00509
00510 Analyser *a=(Analyser*)f->getObject("analyser");
00511
00512 if (f->get_error()) return f->get_error();
00513
00514 htmsg m;
00515 m.msg=msg_set_analyser;
00516 m.type=mt_broadcast;
00517 m.data1.ptr=a;
00518 w->sendmsg(&m);
00519
00520 return f->get_error();
00521 }
00522
00523 void file_window_store_fcfg_func(ht_object_stream *f, void *context)
00524 {
00525 ht_file_window *w=(ht_file_window*)context;
00526 htmsg m;
00527 m.msg=msg_get_analyser;
00528 m.type=mt_broadcast;
00529 m.data1.ptr=NULL;
00530 w->sendmsg(&m);
00531 if ((m.msg==msg_retval) && (m.data1.ptr)) {
00532 pstat_t s;
00533 w->file->pstat(&s);
00534 dword t = (s.caps & pstat_mtime) ? s.mtime : 0;;
00535 f->putIntDec(w->file->get_size(), 4, "filesize");
00536 f->putIntDec(t, 4, "filetime");
00537
00538 Analyser *a=(Analyser*)m.data1.ptr;
00539 f->putObject(a, "analyser");
00540 }
00541 }
00542
00543 void file_project_store_fcfg_func(ht_object_stream *f, void *context)
00544 {
00545 f->putObject((ht_project*)project, NULL);
00546 }
00547
00548 int file_project_load_fcfg_func(ht_object_stream *f, void *context)
00549 {
00550 project = f->getObject(NULL);
00551 return f->get_error();
00552 }
00553
00554
00555
00556
00557
00558 int app_stream_error_func(ht_stream *stream)
00559 {
00560 int err=stream->get_error();
00561 const char *name = stream->get_desc();
00562 if (err & STERR_SYSTEM) {
00563 err=err&0xffff;
00564 switch (err) {
00565 case 4: {
00566 #ifdef DJGPP
00567 struct stat sbuf;
00568
00569 stat(name, &sbuf);
00570
00571 if (!(sbuf.st_mode & S_IWUSR)) {
00572 if (msgbox(btmask_yes | btmask_no, "title", 1, align_center, "%s: stream error (Permission denied), seems to be a (DOS) read-only file. Change attribute ?", name)==button_yes) {
00573 if (chmod(name, S_IRUSR | S_IWUSR)) {
00574 errorbox_modal("%s: error (%04x) changing attribute", name, errno & 0xffff);
00575 } else {
00576 stat(name, &sbuf);
00577
00578 if (!(sbuf.st_mode & S_IWUSR)) {
00579 errorbox_modal("%s: error (%04x) changing attribute", name, errno & 0xffff);
00580 } else {
00581 return SERR_RETRY;
00582 }
00583 }
00584 }
00585 }
00586
00587 break;
00588 #endif
00589 }
00590 default:
00591 errorbox_modal("%s: stream error %04x: %s", name, err, strerror(err));
00592 }
00593 } else {
00594 err=err&0xffff;
00595 errorbox_modal("%s: internal stream error %04x", name, err);
00596 }
00597 return SERR_FAIL;
00598 }
00599
00600
00601
00602
00603 void *app_memory_reserve=0;
00604
00605 int app_out_of_memory_proc(int size)
00606 {
00607 if (app_memory_reserve) {
00608 free(app_memory_reserve);
00609 app_memory_reserve = 0;
00610 warnbox_modal("the memory is getting low...");
00611 return OUT_OF_MEMORY_RETRY;
00612 } else {
00613 return OUT_OF_MEMORY_FAIL;
00614 }
00615 }
00616
00617
00618
00619
00620
00621 static int compare_keys_project_item(Object *key_a, Object *key_b)
00622 {
00623 ht_project_item *a=(ht_project_item *)key_a;
00624 ht_project_item *b=(ht_project_item *)key_b;
00625 int c = sys_filename_cmp(a->get_path(), b->get_path());
00626 return (c == 0) ? sys_filename_cmp(a->get_filename(), b->get_filename()) : c;
00627 }
00628
00629 void ht_project::init(char *fn)
00630 {
00631 ht_sorted_list::init(compare_keys_project_item);
00632 filename = strdup(fn);
00633 }
00634
00635 void ht_project::done()
00636 {
00637 free(filename);
00638 ht_sorted_list::done();
00639 }
00640
00641 char *ht_project::get_filename()
00642 {
00643 return filename;
00644 }
00645
00646 int ht_project::load(ht_object_stream *s)
00647 {
00648
00649 filename = strdup(s->get_desc());
00650 return ht_sorted_list::load(s);
00651 }
00652
00653 OBJECT_ID ht_project::object_id() const
00654 {
00655 return ATOM_HT_PROJECT;
00656 }
00657
00658 void ht_project::store(ht_object_stream *s)
00659 {
00660 return ht_sorted_list::store(s);
00661 }
00662
00663
00664
00665
00666
00667 void ht_project_item::init(char *f, char *p)
00668 {
00669 filename = strdup(f);
00670 path = strdup(p);
00671 }
00672
00673 void ht_project_item::done()
00674 {
00675 free(filename);
00676 free(path);
00677 }
00678
00679 const char *ht_project_item::get_filename()
00680 {
00681 return filename;
00682 }
00683
00684 const char *ht_project_item::get_path()
00685 {
00686 return path;
00687 }
00688
00689 int ht_project_item::load(ht_object_stream *s)
00690 {
00691 filename = s->getString(NULL);
00692 path = s->getString(NULL);
00693 return s->get_error();
00694 }
00695
00696 OBJECT_ID ht_project_item::object_id() const
00697 {
00698 return ATOM_HT_PROJECT_ITEM;
00699 }
00700
00701 void ht_project_item::store(ht_object_stream *s)
00702 {
00703 s->putString(filename, NULL);
00704 s->putString(path, NULL);
00705 }
00706
00707
00708
00709
00710
00711 void ht_project_listbox::init(bounds *b, ht_project *p)
00712 {
00713 project = p;
00714 ht_listbox::init(b);
00715 colwidths[0] = 16;
00716 colwidths[1] = 16;
00717 }
00718
00719 int ht_project_listbox::calcCount()
00720 {
00721 return project ? project->count() : 0;
00722 }
00723
00724 void ht_project_listbox::draw()
00725 {
00726 if (project) {
00727 ht_listbox::draw();
00728 } else {
00729
00730 vcp fc = focused ? getcolor(palidx_generic_list_focused_unselected) :
00731 getcolor(palidx_generic_list_unfocused_unselected);
00732
00733 clear(fc);
00734 buf_print(0, 0, fc, "<no project>");
00735 }
00736 }
00737
00738 char *ht_project_listbox::func(UINT i, bool execute)
00739 {
00740 return NULL;
00741 }
00742
00743 void *ht_project_listbox::getFirst()
00744 {
00745 if (project && project->count()) {
00746 return (void*)1;
00747 } else {
00748 return NULL;
00749 }
00750 }
00751
00752 void *ht_project_listbox::getLast()
00753 {
00754 if (project && project->count()) {
00755 return (void*)(project->count());
00756 } else {
00757 return NULL;
00758 }
00759 }
00760
00761 void *ht_project_listbox::getNext(void *entry)
00762 {
00763 UINT e=(UINT)entry;
00764 if (!e) return NULL;
00765 if (project && (e < project->count())) {
00766 return (void*)(e+1);
00767 } else {
00768 return NULL;
00769 }
00770 }
00771
00772 void *ht_project_listbox::getPrev(void *entry)
00773 {
00774 UINT e=(UINT)entry;
00775 if (e > 1) {
00776 return (void*)(e-1);
00777 } else {
00778 return NULL;
00779 }
00780 }
00781
00782 char *ht_project_listbox::getStr(int col, void *entry)
00783 {
00784 static char mybuf[32];
00785 if (project) switch (col) {
00786 case 0:
00787 ht_snprintf(mybuf, sizeof mybuf, "%s", ((ht_project_item*)project->get((int)entry-1))->get_filename());
00788 break;
00789 case 1:
00790 ht_snprintf(mybuf, sizeof mybuf, "%s", ((ht_project_item*)project->get((int)entry-1))->get_path());
00791 break;
00792 default:
00793 strcpy(mybuf, "?");
00794 } else {
00795 strcpy(mybuf, "<no project>");
00796 }
00797 return mybuf;
00798 }
00799
00800 void ht_project_listbox::handlemsg(htmsg *msg)
00801 {
00802 switch (msg->msg) {
00803 case cmd_project_add_item: {
00804 if (project) {
00805 char fn[FILENAME_MAX];
00806 if (file_chooser("Add project item", fn, sizeof fn)) {
00807 char ffn[HT_NAME_MAX];
00808 char dir[HT_NAME_MAX];
00809 if ((sys_common_canonicalize(ffn, fn, NULL, sys_is_path_delim) == 0)
00810 && (sys_basename(fn, ffn) == 0)
00811 && (sys_dirname(dir, ffn) == 0)) {
00812 ht_project_item *p = new ht_project_item();
00813 p->init(fn, dir);
00814 ((ht_project*)project)->insert(p);
00815 app->sendmsg(msg_project_changed);
00816 }
00817 }
00818 }
00819 clearmsg(msg);
00820 return;
00821 }
00822 case cmd_project_remove_item: {
00823 int p = pos;
00824 if (calcCount() && confirmbox("Really remove item '%s' ?", ((ht_project_item*)project->get(p))->get_filename()) == button_ok) {
00825 cursorUp(1);
00826 project->del(p);
00827 update();
00828 if (p) cursorDown(1);
00829 dirtyview();
00830 rearrangeColumns();
00831 }
00832 clearmsg(msg);
00833 return;
00834 }
00835 case msg_keypressed: {
00836 switch (msg->data1.integer) {
00837 case K_Return: {
00838 if (calcCount() && selectEntry(e_cursor)) {
00839 clearmsg(msg);
00840 return;
00841 }
00842 }
00843 }
00844 break;
00845 }
00846 }
00847 ht_listbox::handlemsg(msg);
00848 }
00849
00850 int ht_project_listbox::numColumns()
00851 {
00852 return 2;
00853 }
00854
00855 void *ht_project_listbox::quickfind(char *s)
00856 {
00857 void *item = getFirst();
00858 int slen = strlen(s);
00859 while (item && (ht_strncmp(getStr(0, item), s, slen)!=0)) {
00860 item = getNext(item);
00861 }
00862 return item;
00863 }
00864
00865 char *ht_project_listbox::quickfindCompletition(char *s)
00866 {
00867 void *item = getFirst();
00868 char *res = NULL;
00869 int slen = strlen(s);
00870 while (item) {
00871 if (ht_strncmp(getStr(0, item), s, slen)==0) {
00872 if (!res) {
00873 res = ht_strdup(getStr(0, item));
00874 } else {
00875 int a = strccomm(res, getStr(0, item));
00876 res[a] = 0;
00877 }
00878 }
00879 item = getNext(item);
00880 }
00881 return res;
00882 }
00883
00884 bool ht_project_listbox::selectEntry(void *entry)
00885 {
00886 int p = pos;
00887 ht_project_item *i = (ht_project_item *)project->get(p);
00888 char fn[HT_NAME_MAX];
00889 if (sys_common_canonicalize(fn, i->get_filename(), i->get_path(), sys_is_path_delim)==0) {
00890 ((ht_app*)app)->create_window_file(fn, FOM_AUTO, false);
00891 }
00892 return true;
00893 }
00894
00895 void ht_project_listbox::set_project(ht_project *p)
00896 {
00897 project = p;
00898 update();
00899 }
00900
00901
00902
00903
00904
00905 void ht_project_window::init(bounds *b, char *desc, UINT framestyle, UINT number, ht_project **p)
00906 {
00907 ht_window::init(b, desc, framestyle, number);
00908 project = p;
00909
00910 bounds c = *b;
00911 c.x = 0;
00912 c.y = 0;
00913 c.w -= 2;
00914 c.h -= 2;
00915 plb = new ht_project_listbox();
00916 plb->init(&c, *p);
00917
00918 insert(plb);
00919 sendmsg(msg_project_changed);
00920 }
00921
00922 void ht_project_window::done()
00923 {
00924 ht_window::done();
00925 }
00926
00927 void ht_project_window::handlemsg(htmsg *msg)
00928 {
00929 switch (msg->msg) {
00930 case msg_project_changed: {
00931 char *t = *project ? (*project)->get_filename() : NULL;
00932 if (t) ht_snprintf(wtitle, sizeof wtitle, "project '%s'", t); else strcpy(wtitle, "project window");
00933 settitle(wtitle);
00934 plb->set_project(*project);
00935 break;
00936 }
00937 case msg_contextmenuquery: {
00938 ht_static_context_menu *projects=new ht_static_context_menu();
00939 projects->init("~Project");
00940 projects->insert_entry("~Add item", "Insert", cmd_project_add_item, K_Insert, 1);
00941 projects->insert_entry("~Remove item", "Delete", cmd_project_remove_item, K_Delete, 1);
00942
00943
00944 msg->msg = msg_retval;
00945 msg->data1.ptr = projects;
00946 return;
00947 }
00948 }
00949 ht_window::handlemsg(msg);
00950 }
00951
00952
00953
00954
00955
00956 void ht_status::init(bounds *b)
00957 {
00958 ht_view::init(b, VO_TRANSPARENT_CHARS, 0);
00959 VIEW_DEBUG_NAME("ht_status");
00960 idle_count = 0;
00961 analy_ani = 0;
00962 clear_len = 0;
00963 format = get_config_string("misc/statusline");
00964
00965 if (!format) {
00966 format = strdup(STATUS_DEFAULT_FORMAT);
00967 }
00968
00969 render();
00970 register_idle_object(this);
00971 }
00972
00973 void ht_status::done()
00974 {
00975 unregister_idle_object(this);
00976 if (format) free(format);
00977 ht_view::done();
00978 }
00979
00980 char *ht_status::defaultpalette()
00981 {
00982 return palkey_generic_menu_default;
00983 }
00984
00985 void ht_status::draw()
00986 {
00987 fill(size.w-clear_len, 0, clear_len, 1, getcolor(palidx_generic_text_focused), ' ');
00988 int len=strlen(workbuf);
00989 clear_len = len;
00990 buf_print(size.w-len, 0, getcolor(palidx_generic_text_focused), workbuf);
00991 }
00992
00993 void ht_status::handlemsg(htmsg *msg)
00994 {
00995 switch (msg->msg) {
00996 case msg_config_changed:
00997 if (format) free(format);
00998 format = get_config_string("misc/statusline");
00999 break;
01000 }
01001 ht_view::handlemsg(msg);
01002 }
01003
01004 bool ht_status::idle()
01005 {
01006 if (idle_count % 100 == 0) {
01007 char *oldstatus=ht_strdup(workbuf);
01008 render();
01009 if (strcmp(oldstatus, workbuf)) {
01010 dirtyview();
01011 redraw();
01012 screen->show();
01013 }
01014 free(oldstatus);
01015
01016 analy_ani++;
01017 analy_ani &= 7;
01018 }
01019 idle_count++;
01020 return false;
01021 }
01022
01023 void ht_status::render()
01024 {
01025 char *f = format;
01026 char *buf = workbuf;
01027 if (f)
01028 while (*f) {
01029 if (*f==STATUS_ESCAPE) {
01030 switch (*(++f)) {
01031 case STATUS_ESCAPE:
01032 *(buf++) = STATUS_ESCAPE;
01033 break;
01034 case STATUS_ANALY_ACTIVE:
01035 if (some_analyser_active) {
01036 char *analysers[] = {"Analy", "aNaly", "anAly", "anaLy", "analY", "anaLy", "anAly", "aNaly"};
01037 strcpy(buf, analysers[analy_ani]);
01038 buf += 5;
01039 }
01040 break;
01041 case STATUS_ANALY_LINES:
01042 if (some_analyser_active) {
01043 buf += sprintf(buf, "(%d)", num_ops_parsed);
01044 }
01045 break;
01046 case STATUS_TIME: {
01047 time_t Time;
01048 time(&Time);
01049 tm *t=localtime(&Time);
01050 buf += sprintf(buf, "%02d:%02d", t->tm_hour, t->tm_min);
01051 break;
01052 }
01053 case STATUS_DATE: {
01054 time_t Time;
01055 time(&Time);
01056 tm *t=localtime(&Time);
01057 buf += sprintf(buf, "%02d.%02d.%04d", t->tm_mday, t->tm_mon+1, t->tm_year+1900);
01058 break;
01059 }
01060 }
01061 } else {
01062 *(buf++) = *f;
01063 }
01064 f++;
01065 }
01066 *buf = 0;
01067 }
01068
01069
01070
01071
01072
01073
01074 void ht_keyline::init(bounds *b)
01075 {
01076 ht_view::init(b, 0, 0);
01077 VIEW_DEBUG_NAME("ht_keyline");
01078 }
01079
01080 void ht_keyline::done()
01081 {
01082 ht_view::done();
01083 }
01084
01085 char *ht_keyline::defaultpalette()
01086 {
01087 return palkey_generic_keys_default;
01088 }
01089
01090 void ht_keyline::draw()
01091 {
01092 clear(getcolor(palidx_generic_text_disabled));
01093 int x=0;
01094 for (int i=1; i<=10; i++) {
01095 htmsg msg;
01096 msg.type=mt_empty;
01097 msg.msg=msg_funcquery;
01098 msg.data1.integer=i;
01099 baseview->sendmsg(&msg);
01100 buf_printchar(x, 0, getcolor(palidx_generic_text_shortcut), '0'+i%10);
01101 if (msg.msg==msg_retval) {
01102 char *s=msg.data1.str;
01103 if (s) {
01104 if (s[0]=='~') {
01105 buf_printf(x+1, 0, getcolor(palidx_generic_text_disabled), s+1);
01106 } else {
01107 for (int j=0; j<size.w/10-1; j++) {
01108 buf_printf(x+j+1, 0, getcolor(palidx_generic_text_focused), " ");
01109 }
01110 buf_printf(x+1, 0, getcolor(palidx_generic_text_focused), s);
01111 }
01112 }
01113 }
01114 x+=size.w/10;
01115 }
01116 }
01117
01118 void ht_keyline::handlemsg(htmsg *msg)
01119 {
01120 ht_view::handlemsg(msg);
01121 }
01122
01123
01124
01125
01126
01127 void ht_desktop::init(bounds *b)
01128 {
01129 ht_view::init(b, VO_OWNBUFFER, 0);
01130 VIEW_DEBUG_NAME("ht_desktop");
01131 }
01132
01133 void ht_desktop::done()
01134 {
01135 ht_view::done();
01136 }
01137
01138 char *ht_desktop::defaultpalette()
01139 {
01140 return palkey_generic_desktop_default;
01141 }
01142
01143 void ht_desktop::draw()
01144 {
01145 fill(0, 0, size.w, size.h, getcolor(palidx_generic_body), CHAR_FILLED_M);
01146 }
01147
01148
01149
01150
01151
01152 ht_log_msg::ht_log_msg(vcp Color, char *Msg)
01153 {
01154 color = Color;
01155 msg = ht_strdup(Msg);
01156 }
01157
01158 ht_log_msg::~ht_log_msg()
01159 {
01160 free(msg);
01161 }
01162
01163
01164
01165
01166
01167 void ht_log::init(compare_keys_func_ptr compare_keys)
01168 {
01169 ht_clist::init(compare_keys);
01170 maxlinecount = 128;
01171 }
01172
01173 void ht_log::deletefirstline()
01174 {
01175 del(0);
01176 }
01177
01178 void ht_log::insertline(LogColor color, char *line)
01179 {
01180 if (count() >= maxlinecount) deletefirstline();
01181 vcp c;
01182 switch (color) {
01183 case LOG_NORMAL: c = VCP(VC_WHITE, VC_TRANSPARENT); break;
01184 case LOG_WARN: c = VCP(VC_LIGHT(VC_YELLOW), VC_TRANSPARENT); break;
01185 case LOG_ERROR: c = VCP(VC_LIGHT(VC_RED), VC_TRANSPARENT); break;
01186 default: c = VCP(VC_WHITE, VC_TRANSPARENT); break;
01187 }
01188 insert(new ht_log_msg(c, line));
01189 }
01190
01191 void ht_log::log(LogColor c, char *line)
01192 {
01193 insertline(c, line);
01194 }
01195
01196
01197
01198
01199
01200 void ht_logviewer::init(bounds *b, ht_window *w, ht_log *l, bool ol)
01201 {
01202 ht_viewer::init(b, "log", 0);
01203 VIEW_DEBUG_NAME("ht_logviewer");
01204 ofs = 0;
01205 xofs = 0;
01206 window = w;
01207 lines = l;
01208 own_lines = ol;
01209 update();
01210 }
01211
01212 void ht_logviewer::done()
01213 {
01214 if (own_lines) {
01215 lines->destroy();
01216 delete lines;
01217 }
01218
01219 ht_viewer::done();
01220 }
01221
01222 int ht_logviewer::cursor_up(int n)
01223 {
01224 ofs -= n;
01225 if (ofs < 0) ofs = 0;
01226 return n;
01227 }
01228
01229 int ht_logviewer::cursor_down(int n)
01230 {
01231 int c = lines->count();
01232 if (c >= size.h) {
01233 ofs += n;
01234 if (ofs > c-size.h) ofs = c-size.h;
01235 }
01236 return n;
01237 }
01238
01239 void ht_logviewer::draw()
01240 {
01241 clear(getcolor(palidx_generic_body));
01242 int c = lines->count();
01243 for (int i=0; i < size.h; i++) {
01244 if (i+ofs >= c) break;
01245 ht_log_msg *msg = (ht_log_msg*)lines->get(i+ofs);
01246 int l = strlen(msg->msg);
01247 if (xofs<l) buf_print(0, i, msg->color, msg->msg+xofs);
01248 }
01249 }
01250
01251 bool ht_logviewer::get_vscrollbar_pos(int *pstart, int *psize)
01252 {
01253 return scrollbar_pos(ofs, size.h, lines->count(), pstart, psize);
01254 }
01255
01256
01257 void ht_logviewer::handlemsg(htmsg *msg)
01258 {
01259 switch (msg->msg) {
01260 case msg_get_scrollinfo:
01261 switch (msg->data1.integer) {
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274 case gsi_vscrollbar: {
01275 gsi_scrollbar_t *p=(gsi_scrollbar_t*)msg->data2.ptr;
01276 if (!get_vscrollbar_pos(&p->pstart, &p->psize)) {
01277 p->pstart = 0;
01278 p->psize = 100;
01279 }
01280 clearmsg(msg);
01281 return;
01282 }
01283 }
01284 break;
01285 case msg_log_changed: {
01286 ofs = lines->count()-size.h;
01287 if (ofs < 0) ofs = 0;
01288 update();
01289 clearmsg(msg);
01290 return;
01291 }
01292 case msg_keypressed:
01293 switch (msg->data1.integer) {
01294 case K_Up:
01295 cursor_up(1);
01296 update();
01297 clearmsg(msg);
01298 return;
01299 case K_Down:
01300 cursor_down(1);
01301 update();
01302 clearmsg(msg);
01303 return;
01304 case K_PageUp:
01305 cursor_up(size.h);
01306 update();
01307 clearmsg(msg);
01308 return;
01309 case K_PageDown:
01310 cursor_down(size.h);
01311 update();
01312 clearmsg(msg);
01313 return;
01314 case K_Right: case K_Control_Right:
01315 xofs += 2;
01316 update();
01317 clearmsg(msg);
01318 return;
01319 case K_Left: case K_Control_Left:
01320 if (xofs-2 >= 0) xofs -= 2;
01321 update();
01322 clearmsg(msg);
01323 return;
01324 case K_Control_PageUp:
01325 ofs = 0;
01326 update();
01327 clearmsg(msg);
01328 return;
01329 case K_Control_PageDown:
01330 ofs = lines->count()-size.h;
01331 if (ofs < 0) ofs = 0;
01332 update();
01333 clearmsg(msg);
01334 return;
01335 }
01336 break;
01337 }
01338 ht_viewer::handlemsg(msg);
01339 }
01340
01341 void ht_logviewer::update()
01342 {
01343 dirtyview();
01344 }
01345
01346
01347
01348
01349
01350 ht_app_window_entry::ht_app_window_entry(ht_window *w, UINT n, UINT t, bool m, bool isf, ht_layer_streamfile *l)
01351 {
01352 window=w;
01353 number=n;
01354 type=t;
01355 minimized=m;
01356 isfile=isf;
01357 layer=l;
01358 }
01359
01360 ht_app_window_entry::~ht_app_window_entry()
01361 {
01362 }
01363
01364 static int compare_keys_app_window_entry(Object *key_a, Object *key_b)
01365 {
01366 UINT a=((ht_app_window_entry*)key_a)->number;
01367 UINT b=((ht_app_window_entry*)key_b)->number;
01368 if (a>b) return 1; else if (a<b) return -1;
01369 return 0;
01370 }
01371
01372
01373
01374
01375
01376 static bool doFileChecks(ht_file *file)
01377 {
01378
01379
01380 pstat_t s;
01381 file->pstat(&s);
01382 if (s.caps & pstat_mode_type) {
01383 switch (s.mode & HT_S_IFMT) {
01384 case HT_S_IFREG: return true;
01385 default:
01386 LOG_EX(LOG_WARN, "file is not regular (but device, fifo or something...).");
01387 LOG_EX(LOG_WARN, "Write-access disabled for safety !");
01388 return true;
01389 }
01390 } else {
01391 LOG_EX(LOG_WARN, "can't determine file type (regular, device, directory...) ! assuming non-regular...");
01392 LOG_EX(LOG_WARN, "file is not regular (but device, fifo or something...).");
01393 LOG_EX(LOG_WARN, "Write-access disabled for safety !");
01394 return true;
01395 }
01396 return false;
01397 }
01398
01399
01400
01401
01402 #define AVG_TIMINGS 10
01403 int timings[AVG_TIMINGS];
01404 int cur_timing=0, max_timing=0;
01405 int h0;
01406
01407
01408 void ht_app::init(bounds *pq)
01409 {
01410 ht_dialog::init(pq, 0, 0);
01411 menu = NULL;
01412 setframe(NULL);
01413 VIEW_DEBUG_NAME("ht_app");
01414 exit_program = false;
01415 focused = true;
01416 bounds b;
01417
01418 windows = new ht_sorted_list();
01419 windows->init(compare_keys_app_window_entry);
01420
01421 syntax_lexers = new ht_clist();
01422 ((ht_clist*)syntax_lexers)->init();
01423
01424 ht_c_syntax_lexer *c_lexer = new ht_c_syntax_lexer();
01425 c_lexer->init();
01426
01427 syntax_lexers->insert(c_lexer);
01428
01429 ht_html_syntax_lexer *html_lexer = new ht_html_syntax_lexer();
01430 html_lexer->init();
01431
01432 syntax_lexers->insert(html_lexer);
01433
01434
01435 h0=new_timer();
01436
01437
01438 getbounds(&b);
01439 b.x=0;
01440 b.y=0;
01441 b.h=1;
01442 ht_menu *m=new ht_menu();
01443 m->init(&b);
01444
01445 ht_static_context_menu *file=new ht_static_context_menu();
01446 file->init("~File");
01447 file->insert_entry("~New...", NULL, cmd_file_new, 0, 1);
01448 file->insert_entry("~Open...", "F3", cmd_file_open, 0, 1);
01449 file->insert_entry("~Save", NULL, cmd_file_save, 0, 1);
01450 file->insert_entry("Save ~As...", NULL, cmd_file_saveas, 0, 1);
01451 file->insert_separator();
01452 file->insert_entry("Open/Create ~project...", NULL, cmd_project_open, 0, 1);
01453 file->insert_entry("Close p~roject", NULL, cmd_project_close, 0, 1);
01454 file->insert_separator();
01455 file->insert_entry("~Execute", "Alt+Z", cmd_file_exec_cmd, K_Alt_Z, 1);
01456 file->insert_entry("~Quit", "F10", cmd_quit, 0, 1);
01457 m->insert_menu(file);
01458
01459 ht_static_context_menu *edit=new ht_static_context_menu();
01460 edit->init("~Edit");
01461 edit->insert_entry("Cu~t", "Shift+Del", cmd_edit_cut, 0, 1);
01462 edit->insert_entry("~Delete", "Ctrl+Del", cmd_edit_delete, 0, 1);
01463 edit->insert_entry("~Copy", "Ctrl+Ins", cmd_edit_copy, 0, 1);
01464 edit->insert_entry("~Paste", "Shift+Ins", cmd_edit_paste, 0, 1);
01465 edit->insert_entry("~Show clipboard", 0, cmd_edit_show_clipboard, 0, 1);
01466 edit->insert_entry("C~lear clipboard", 0, cmd_edit_clear_clipboard, 0, 1);
01467 edit->insert_separator();
01468 edit->insert_entry("Copy ~from file...", 0, cmd_edit_copy_from_file, 0, 1);
01469 edit->insert_entry("Paste ~into file...", 0, cmd_edit_paste_into_file, 0, 1);
01470 #ifdef SYS_SUPPORT_NATIVE_CLIPBOARD
01471 edit->insert_separator();
01472 edit->insert_entry("Copy from "SYS_NATIVE_CLIPBOARD_NAME, 0, cmd_edit_copy_native, 0, 1);
01473 edit->insert_entry("Paste into "SYS_NATIVE_CLIPBOARD_NAME, 0, cmd_edit_paste_native, 0, 1);
01474 #endif
01475 edit->insert_separator();
01476 edit->insert_entry("~Evaluate...", 0, cmd_popup_dialog_eval, 0, 1);
01477 m->insert_menu(edit);
01478
01479 ht_static_context_menu *windows=new ht_static_context_menu();
01480 windows->init("~Windows");
01481 windows->insert_entry("~Size/Move", "Alt+F5", cmd_window_resizemove, K_Alt_F5, 1);
01482 windows->insert_entry("~Close", "Alt+F3", cmd_window_close, K_Alt_F3, 1);
01483 windows->insert_entry("~Close (alt)", "Ctrl+W", cmd_window_close, K_Control_W, 1);
01484 windows->insert_entry("~List", "Alt+0", cmd_popup_dialog_window_list, K_Alt_0, 1);
01485 windows->insert_separator();
01486 windows->insert_entry("Lo~g window", NULL, cmd_popup_window_log, 0, 1);
01487 windows->insert_entry("~Options", NULL, cmd_popup_window_options, 0, 1);
01488 windows->insert_entry("~Project", NULL, cmd_popup_window_project, 0, 1);
01489 m->insert_menu(windows);
01490
01491 ht_static_context_menu *help=new ht_static_context_menu();
01492 help->init("~Help");
01493 help->insert_entry("~About "ht_name, "", cmd_about, 0, 1);
01494 help->insert_separator();
01495 help->insert_entry("~Help contents", "F1", cmd_popup_window_help, 0, 1);
01496 help->insert_entry("~Open info file...", NULL, cmd_popup_dialog_info_loader, 0, 1);
01497 m->insert_menu(help);
01498
01499 m->insert_local_menu();
01500
01501 menu=m;
01502 insert(menu);
01503
01504
01505
01506 ht_status *status = new ht_status();
01507 status->init(&b);
01508 status->setpalette(menu->getpalette());
01509 insert(status);
01510
01511
01512 getbounds(&b);
01513 b.x=0;
01514 b.y=1;
01515 b.h-=2;
01516 desktop=new ht_desktop();
01517 desktop->init(&b);
01518 insert(desktop);
01519
01520
01521 getbounds(&b);
01522 b.x=0;
01523 b.y=b.h-1;
01524 b.h=1;
01525 keyline=new ht_keyline();
01526 keyline->init(&b);
01527 insert(keyline);
01528
01529
01530 getbounds(&b);
01531 b.x=0;
01532 b.y=1;
01533 b.h-=2;
01534
01535 battlefield=new ht_group();
01536 battlefield->init(&b, VO_TRANSPARENT_CHARS, "battlefield");
01537 insert(battlefield);
01538
01539 create_window_log();
01540 }
01541
01542 void ht_app::done()
01543 {
01544 delete_timer(h0);
01545
01546 syntax_lexers->destroy();
01547 delete syntax_lexers;
01548
01549 if (windows) {
01550 windows->destroy();
01551 delete windows;
01552 }
01553
01554 ht_dialog::done();
01555 }
01556
01557 bool ht_app::accept_close_all_windows()
01558 {
01559 UINT wc=windows->count();
01560 ht_app_window_entry *e;
01561 for (UINT i=0; i<wc; i++) {
01562 e=(ht_app_window_entry*)windows->get(i);
01563 htmsg m;
01564 m.msg=msg_accept_close;
01565 m.type=mt_empty;
01566 e->window->sendmsg(&m);
01567 if (m.msg!=msg_accept_close) return false;
01568 }
01569 return true;
01570 }
01571
01572 ht_window *ht_app::create_window_log()
01573 {
01574 ht_window *w=get_window_by_type(AWT_LOG);
01575 if (w) {
01576 focus(w);
01577 } else {
01578 bounds b;
01579
01580
01581
01582 get_stdbounds_file(&b);
01583
01584 ht_window *logwindow=new ht_window();
01585 logwindow->init(&b, "log window", FS_KILLER | FS_TITLE | FS_NUMBER | FS_MOVE | FS_RESIZE, 0);
01586
01587 bounds k=b;
01588 k.x=b.w-2;
01589 k.y=0;
01590 k.w=1;
01591 k.h-=2;
01592 ht_scrollbar *hs=new ht_scrollbar();
01593 hs->init(&k, &logwindow->pal, true);
01594
01595 logwindow->setvscrollbar(hs);
01596
01597 b.x=0;
01598 b.y=0;
01599 b.w-=2;
01600 b.h-=2;
01601 ht_logviewer *logviewer=new ht_logviewer();
01602 logviewer->init(&b, logwindow, loglines, false);
01603 logwindow->insert(logviewer);
01604
01605 insert_window(logwindow, AWT_LOG, 0, false, NULL);
01606 }
01607 return w;
01608 }
01609
01610 ht_window *ht_app::create_window_term(const char *cmd)
01611 {
01612 ht_window *w = get_window_by_type(AWT_TERM);
01613 if (w) {
01614 focus(w);
01615 } else {
01616 bounds b;
01617 get_stdbounds_file(&b);
01618
01619 ht_window *termwindow=new ht_window();
01620 termwindow->init(&b, "terminal", FS_KILLER | FS_TITLE | FS_NUMBER | FS_MOVE | FS_RESIZE, 0);
01621
01622 bounds k=b;
01623 k.x=3;
01624 k.y=k.h-2;
01625 k.w-=7;
01626 k.h=1;
01627 ht_statictext *ind=new ht_statictext();
01628 ind->init(&k, NULL, align_left, false, true);
01629 ind->disable_buffering();
01630 ind->growmode = MK_GM(GMH_FIT, GMV_BOTTOM);
01631
01632 termwindow->setpindicator(ind);
01633
01634 k=b;
01635 k.x=b.w-2;
01636 k.y=0;
01637 k.w=1;
01638 k.h-=2;
01639 ht_scrollbar *hs=new ht_scrollbar();
01640 hs->init(&k, &termwindow->pal, true);
01641
01642 termwindow->setvscrollbar(hs);
01643
01644 ht_streamfile *in, *out, *err;
01645 int handle;
01646 int e;
01647 if ((e = sys_ipc_exec(&in, &out, &err, &handle, cmd, 0)) == 0) {
01648 Terminal *terminal = new Terminal();
01649 terminal->init(in, out, err, handle);
01650
01651 b.x=0;
01652 b.y=0;
01653 b.w-=2;
01654 b.h-=2;
01655 TerminalViewer *termviewer=new TerminalViewer();
01656 termviewer->init(&b, terminal, true);
01657 termwindow->insert(termviewer);
01658
01659 insert_window(termwindow, AWT_LOG, 0, false, NULL);
01660 } else {
01661 errorbox("couldn't create child-process (%d)", e);
01662 return NULL;
01663 }
01664 }
01665 return w;
01666 }
01667
01668 ht_window *ht_app::create_window_clipboard()
01669 {
01670 ht_window *w=get_window_by_type(AWT_CLIPBOARD);
01671 if (w) {
01672 focus(w);
01673 return w;
01674 } else {
01675 bounds b;
01676 get_stdbounds_file(&b);
01677
01678
01679 ht_window *window=new ht_window();
01680 window->init(&b, "clipboard", FS_KILLER | FS_TITLE | FS_NUMBER | FS_MOVE | FS_RESIZE, 0);
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692 bounds k;
01693 k = b;
01694 k.x=3;
01695 k.y=k.h-2;
01696 k.w-=7;
01697 k.h=1;
01698 ht_statictext *ind=new ht_statictext();
01699 ind->init(&k, NULL, align_left, false, true);
01700 ind->disable_buffering();
01701 ind->growmode = MK_GM(GMH_FIT, GMV_BOTTOM);
01702
01703 window->setpindicator(ind);
01704
01705 b.x=0;
01706 b.y=0;
01707 b.w-=2;
01708 b.h-=2;
01709 ht_clipboard_viewer *v=new ht_clipboard_viewer();
01710 v->init(&b, "clipboard", VC_EDIT | VC_GOTO | VC_SEARCH, clipboard, 0);
01711
01712 window->insert(v);
01713
01714
01715 insert_window(window, AWT_CLIPBOARD, 0, false, NULL);
01716 }
01717 return NULL;
01718 }
01719
01720 ht_window *ht_app::create_window_file(char *filename, UINT mode, bool allow_duplicates)
01721 {
01722 if (mode==FOM_AUTO) mode=autodetect_file_open_mode(filename);
01723 switch (mode) {
01724 case FOM_BIN: return create_window_file_bin(filename, allow_duplicates);
01725 case FOM_TEXT: return create_window_file_text(filename, allow_duplicates);
01726 }
01727 return NULL;
01728 }
01729
01730 ht_window *ht_app::create_window_file_bin(char *filename, bool allow_duplicates)
01731 {
01732 bounds b;
01733 get_stdbounds_file(&b);
01734 int e;
01735 char fullfilename[FILENAME_MAX];
01736 if ((e=sys_canonicalize(fullfilename, filename))) {
01737 LOG_EX(LOG_ERROR, "error loading file %s: %s", fullfilename, strerror(e & ~STERR_SYSTEM));
01738 return NULL;
01739 }
01740
01741 ht_window *w;
01742 if (!allow_duplicates && ((w = get_window_by_filename(fullfilename)))) {
01743 focus(w);
01744 return w;
01745 }
01746
01747 ht_file *emfile = new ht_file();
01748 emfile->init(fullfilename, FAM_READ, FOM_EXISTS);
01749
01750 if ((e = emfile->get_error())) {
01751 LOG_EX(LOG_ERROR, "error loading file %s: %s", fullfilename, strerror(e & ~STERR_SYSTEM));
01752 return NULL;
01753 }
01754
01755 if (!doFileChecks(emfile)) return NULL;
01756
01757 ht_streamfile_modifier *mfile = new ht_streamfile_modifier();
01758 mfile->init(emfile, true, 8*1024);
01759
01760 ht_layer_streamfile *file = new ht_layer_streamfile();
01761 file->init(mfile, true);
01762
01763 if ((e=file->get_error())) {
01764 LOG_EX(LOG_ERROR, "error loading file %s: %s", fullfilename, strerror(e & ~STERR_SYSTEM));
01765 return NULL;
01766 }
01767 LOG("loading binary file %s...", fullfilename);
01768 file->set_error_func(app_stream_error_func);
01769
01770 return create_window_file_bin(&b, file, fullfilename, true);
01771 }
01772
01773 ht_window *ht_app::create_window_file_bin(bounds *b, ht_layer_streamfile *file, char *title, bool isfile)
01774 {
01775 ht_file_window *window = new ht_file_window();
01776 window->init(b, title, FS_KILLER | FS_TITLE | FS_NUMBER | FS_MOVE | FS_RESIZE, 0, file);
01777
01778 bounds k=*b;
01779 k.x=b->w-2;
01780 k.y=0;
01781 k.w=1;
01782 k.h-=2;
01783 ht_scrollbar *hs=new ht_scrollbar();
01784 hs->init(&k, &window->pal, true);
01785
01786 window->setvscrollbar(hs);
01787
01788 k=*b;
01789 k.x=3;
01790 k.y=k.h-2;
01791 k.w-=7;
01792 k.h=1;
01793 ht_statictext *ind=new ht_statictext();
01794 ind->init(&k, NULL, align_left, false, true);
01795 ind->disable_buffering();
01796 ind->growmode = MK_GM(GMH_FIT, GMV_BOTTOM);
01797
01798 window->setpindicator(ind);
01799
01800 k=*b;
01801 k.x=0;
01802 k.y=0;
01803 k.w-=2;
01804 k.h-=2;
01805 ht_format_group *format_group=new ht_format_group();
01806 format_group->init(&k, VO_SELECTABLE | VO_RESIZE, VIEWERGROUP_NAME, file, true, true, format_viewer_ifs, NULL);
01807
01808 window->insert(format_group);
01809
01810
01811 if (isfile) {
01812 char cfgfilename[FILENAME_MAX];
01813 strcpy(cfgfilename, title);
01814 strcat(cfgfilename, HT_FILE_CONFIG_SUFFIX);
01815
01816 int einfo;
01817 LOG("%s: loading config file...", cfgfilename);
01818 loadstore_result lsr = load_fileconfig(cfgfilename, ht_fileconfig_magic, ht_fileconfig_fileversion, file_window_load_fcfg_func, window, &einfo);
01819 if (lsr == LS_ERROR_CORRUPTED) {
01820 LOG_EX(LOG_ERROR, "%s: error in line %d", cfgfilename, einfo);
01821 errorbox("%s: error in line %d",cfgfilename, einfo);
01822 } else if (lsr == LS_ERROR_MAGIC || lsr == LS_ERROR_FORMAT) {
01823 LOG_EX(LOG_ERROR, "%s: wrong magic/format", cfgfilename);
01824 errorbox("%s: wrong magic/format", cfgfilename);
01825 } else if (lsr == LS_ERROR_VERSION) {
01826 LOG_EX(LOG_ERROR, "%s: wrong version", cfgfilename);
01827 errorbox("%s: wrong version", cfgfilename);
01828 } else if (lsr == LS_ERROR_NOT_FOUND) {
01829 LOG("%s: not found", cfgfilename);
01830 } else if (lsr != LS_OK) {
01831 LOG_EX(LOG_ERROR, "%s: some error", cfgfilename);
01832 errorbox("%s: some error", cfgfilename);
01833 } else {
01834 LOG("%s: ok", cfgfilename);
01835 }
01836 }
01837
01838
01839 if (isfile) LOG("%s: done.", title);
01840
01841 htmsg m;
01842 m.msg = msg_postinit;
01843 m.type = mt_broadcast;
01844 window->sendmsg(&m);
01845
01846 insert_window(window, AWT_FILE, 0, isfile, file);
01847 return window;
01848 }
01849
01850 ht_window *ht_app::create_window_file_text(char *filename, bool allow_duplicates)
01851 {
01852 bounds b, c;
01853 get_stdbounds_file(&c);
01854 b = c;
01855 int e;
01856 char fullfilename[FILENAME_MAX];
01857 if ((e=sys_canonicalize(fullfilename, filename))) {
01858 LOG_EX(LOG_ERROR, "error loading file %s: %s", fullfilename, strerror(e & ~STERR_SYSTEM));
01859 return NULL;
01860 }
01861
01862 ht_window *w;
01863 if (!allow_duplicates && ((w = get_window_by_filename(fullfilename)))) {
01864 focus(w);
01865 return w;
01866 }
01867
01868 ht_file *emfile = new ht_file();
01869 emfile->init(fullfilename, FAM_READ, FOM_EXISTS);
01870
01871 if ((e=emfile->get_error())) {
01872 LOG_EX(LOG_ERROR, "error loading file %s: %s", fullfilename, strerror(e & ~STERR_SYSTEM));
01873 return NULL;
01874 }
01875
01876 if (!doFileChecks(emfile)) return NULL;
01877
01878 ht_ltextfile *tfile = new ht_ltextfile();
01879 tfile->init(emfile, true, NULL);
01880
01881 ht_layer_textfile *file=new ht_layer_textfile();
01882 file->init(tfile, true);
01883
01884 if ((e=file->get_error())) {
01885 LOG_EX(LOG_ERROR, "error loading file %s: %s", fullfilename, strerror(e & ~STERR_SYSTEM));
01886 return NULL;
01887 }
01888
01889 LOG("loading text file %s...", fullfilename);
01890 file->set_error_func(app_stream_error_func);
01891
01892 return create_window_file_text(&b, file, fullfilename, true);
01893 }
01894
01895 ht_window *ht_app::create_window_file_text(bounds *c, ht_layer_streamfile *f, char *title, bool isfile)
01896 {
01897 bounds b=*c;
01898
01899 ht_layer_textfile *file = (ht_layer_textfile *)f;
01900
01901 ht_file_window *window = new ht_file_window();
01902 window->init(&b, title, FS_KILLER | FS_TITLE | FS_NUMBER | FS_MOVE | FS_RESIZE, 0, file);
01903
01904 b.x=0;
01905 b.y=0;
01906 b.w-=2;
01907 b.h-=2;
01908 ht_text_editor *text_editor=new ht_text_editor();
01909 text_editor->init(&b, true, file, syntax_lexers, TEXTEDITOPT_INPUTTABS|TEXTEDITOPT_UNDO);
01910
01911 char *fn_suf = sys_filename_suffix(file->get_filename());
01912
01913 if (fn_suf) {
01914 if ((ht_stricmp(fn_suf, "c") == 0) || (ht_stricmp(fn_suf, "cc") == 0)
01915 || (ht_stricmp(fn_suf, "cpp") == 0)
01916 || (ht_stricmp(fn_suf, "h") == 0) || (ht_stricmp(fn_suf, "hpp") == 0)) {
01917 text_editor->set_lexer((ht_syntax_lexer*)syntax_lexers->get(0), false);
01918 }
01919 #ifdef HT_HTML_SYNTAX_LEXER
01920 if (ht_stricmp(fn_suf, "htm") == 0 || ht_stricmp(fn_suf, "html") == 0) {
01921 text_editor->set_lexer((ht_syntax_lexer*)syntax_lexers->get(1), false);
01922 }
01923 #endif
01924 }
01925
01926 bounds k=*c;
01927 k.x=k.w-2;
01928 k.y=0;
01929 k.w=1;
01930 k.h-=2;
01931 ht_scrollbar *hs=new ht_scrollbar();
01932 hs->init(&k, &window->pal, true);
01933
01934 window->setvscrollbar(hs);
01935
01936 k=*c;
01937 k.x=3;
01938 k.y=k.h-2;
01939 k.w-=7;
01940 k.h=1;
01941
01942 ht_statictext *ind=new ht_statictext();
01943 ind->init(&k, NULL, align_left, false, true);
01944 ind->disable_buffering();
01945 ind->growmode = MK_GM(GMH_FIT, GMV_BOTTOM);
01946
01947 window->setpindicator(ind);
01948
01949 window->insert(text_editor);
01950 if (isfile) LOG("%s: done.", title);
01951
01952 insert_window(window, AWT_FILE, 0, isfile, file);
01953 return window;
01954 }
01955
01956 ht_window *ht_app::create_window_help(char *file, char *node)
01957 {
01958 ht_window *w = get_window_by_type(AWT_HELP);
01959 if (w) {
01960 focus(w);
01961 return w;
01962 } else {
01963 bounds b, c;
01964 battlefield->getbounds(&c);
01965 b.w=c.w*7/8;
01966 b.h=c.h*7/8;
01967 b.x=(c.w-b.w)/2;
01968 b.y=(c.h-b.h)/2;
01969 bounds k = b;
01970
01971 ht_help_window *window=new ht_help_window();
01972 window->init(&b, "help", FS_KILLER | FS_TITLE | FS_NUMBER | FS_MOVE | FS_RESIZE, 0);
01973
01974 b.x=0;
01975 b.y=0;
01976 b.w-=2;
01977 b.h-=2;
01978 c=b;
01979
01980 b=c;
01981 b.x+=b.w;
01982 b.w=1;
01983 ht_scrollbar *scrollbar=new ht_scrollbar();
01984 scrollbar->init(&b, &window->pal, true);
01985 scrollbar->enable();
01986 window->setvscrollbar(scrollbar);
01987
01988 k.x=3;
01989 k.y=k.h-2;
01990 k.w-=7;
01991 k.h=1;
01992 ht_statictext *ind=new ht_statictext();
01993 ind->init(&k, NULL, align_left, false, true);
01994 ind->disable_buffering();
01995 ind->growmode = MK_GM(GMH_FIT, GMV_BOTTOM);
01996
01997 window->setpindicator(ind);
01998
01999 b=c;
02000 ht_info_viewer *infoviewer=new ht_info_viewer();
02001 infoviewer->init(&b);
02002 window->insert(infoviewer);
02003
02004 char ff[HT_NAME_MAX], cwd[HT_NAME_MAX];
02005
02006 cwd[0] = 0;
02007 getcwd(cwd, sizeof cwd);
02008 if (strcmp(file, "hthelp.info")) {
02009 sys_common_canonicalize(ff, file, cwd, sys_is_path_delim);
02010 } else {
02011 strcpy(ff, file);
02012 }
02013 if (infoviewer->gotonode(ff, node)) {
02014 insert_window(window, AWT_HELP, 0, false, NULL);
02015
02016 window->setpalette(palkey_generic_cyan);
02017 return window;
02018 }
02019 errorbox("help topic '(%s)%s' not found", file, node);
02020 window->done();
02021 delete window;
02022 }
02023 return NULL;
02024 }
02025
02026 ht_window *ht_app::create_window_project()
02027 {
02028 ht_window *w=get_window_by_type(AWT_PROJECT);
02029 if (w) {
02030 focus(w);
02031 return w;
02032 } else {
02033 bounds b;
02034 get_stdbounds_tool(&b);
02035
02036 ht_project_window *project_window=new ht_project_window();
02037 project_window->init(&b, "project window", FS_KILLER | FS_TITLE | FS_NUMBER | FS_MOVE | FS_RESIZE, 0, (ht_project**)&project);
02038
02039 bounds k = b;
02040 k.x = b.w-2;
02041 k.y = 0;
02042 k.w = 1;
02043 k.h -= 2;
02044 ht_scrollbar *hs = new ht_scrollbar();
02045 hs->init(&k, &project_window->pal, true);
02046
02047 project_window->sethscrollbar(hs);
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057 insert_window(project_window, AWT_PROJECT, 0, false, NULL);
02058
02059 project_window->setpalette(palkey_generic_cyan);
02060 return project_window;
02061 }
02062 }
02063
02064 #if 0
02065 ht_view *create_ofm_single(bounds *c, char *url, ht_vfs_viewer **x)
02066 {
02067 bounds b=*c;
02068 b.h-=2;
02069 ht_group *g=new ht_group();
02070 g->init(&b, VO_SELECTABLE, 0);
02071
02072 bounds d=b;
02073
02074 b.x=0;
02075 b.y=0;
02076 b.h=1;
02077 ht_vfs_viewer_status *vst=new ht_vfs_viewer_status();
02078 vst->init(&b);
02079
02080 d.x=0;
02081 d.y=1;
02082 d.h--;
02083 ht_vfs_viewer *v=new ht_vfs_viewer();
02084 v->init(&d, "vfs viewer", 0, 0, 0, vst);
02085
02086 g->insert(v);
02087
02088 g->insert(vst);
02089
02090 ht_vfs_sub *vs=new ht_vfs_sub();
02091 vs->init(url);
02092
02093 v->insertsub(vs);
02094
02095 v->sendmsg(msg_complete_init, 0);
02096
02097 *x=v;
02098 return g;
02099 }
02100 #endif
02101
02102 ht_window *ht_app::create_window_ofm(char *url1, char *url2)
02103 {
02104 bounds b;
02105 get_stdbounds_file(&b);
02106
02107 ht_window *window=new ht_window();
02108 window->init(&b, "file manager", FS_KILLER | FS_TITLE | FS_NUMBER | FS_MOVE | FS_RESIZE, 0);
02109 #if 1
02110 b.w-=2;
02111 b.h-=2;
02112
02113 VfsListbox2 *l = new VfsListbox2();
02114 l->init(&b, virtual_fs_list, window->getframe());
02115
02116
02117 l->changeURL(url1);
02118
02119 window->insert(l);
02120 #else
02121 bounds b1, b2, b3;
02122
02123 ht_vfs_viewer *v1, *v2=NULL;
02124
02125 b.w-=2;
02126
02127 b1=b;
02128 b1.w/=2;
02129 b1.w--;
02130 window->insert(create_ofm_single(&b1, url1, &v1));
02131
02132 if (url2) {
02133 b2=b;
02134 b2.w/=2;
02135 b2.x=b2.w-1;
02136 b2.w=1;
02137 b2.h-=2;
02138 ht_vbar *x=new ht_vbar();
02139 x->init(&b2, 0, 0);
02140 window->insert(x);
02141
02142 b3=b;
02143 b3.w/=2;
02144 b3.x=b3.w;
02145 window->insert(create_ofm_single(&b3, url2, &v2));
02146 }
02147
02148 if (v2) {
02149 v1->set_assoc_vfs_viewer(v2);
02150 v2->set_assoc_vfs_viewer(v1);
02151 }
02152 #endif
02153 insert_window(window, AWT_OFM, 0, false, NULL);
02154 return window;
02155 }
02156
02157 char *ht_app::defaultpalette()
02158 {
02159 return NULL;
02160 }
02161
02162 char *ht_app::defaultpaletteclass()
02163 {
02164 return NULL;
02165 }
02166
02167 int analy_id = 0;
02168 void ht_app::draw()
02169 {
02170
02171 #ifdef DRAW_TIMING
02172 int xyz=get_timer_1024tick(h0);
02173 buf->printf(17, 1, 7, "cur: %d (%d msec)", xyz*1024, get_timer_msec(h0));
02174 #ifndef NO_AVG
02175 if (cur_timing>=AVG_TIMINGS-1) cur_timing=0;
02176 timings[cur_timing++]=xyz;
02177 if (cur_timing>max_timing) max_timing=cur_timing;
02178 int avg=0;
02179 for (int i=0; i<max_timing; i++) avg+=timings[i];
02180 avg=avg/max_timing;
02181 buf->printf(57, 1, 7, "avg%d: %d", max_timing+1, avg*1024);
02182 #endif
02183 #endif
02184 }
02185
02186 void ht_app::delete_window(ht_window *window)
02187 {
02188 UINT i=get_window_listindex(window);
02189 if (i!=LIST_UNDEFINED) {
02190 battlefield->remove(window);
02191
02192 windows->del(i);
02193
02194 window->done();
02195 delete window;
02196 }
02197 }
02198
02199 UINT ht_app::find_free_window_number()
02200 {
02201 UINT c=windows->count();
02202 UINT k=0;
02203 repeat:
02204 k++;
02205 for (UINT i=0; i<c; i++) {
02206 ht_app_window_entry *e=(ht_app_window_entry*)windows->get(i);
02207 if (e->number==k) goto repeat;
02208 }
02209 return k;
02210 }
02211
02212 int ht_app::focus(ht_view *view)
02213 {
02214 return ht_dialog::focus(view);
02215 }
02216
02217 char *ht_app::func(UINT i, bool execute)
02218 {
02219 switch (i) {
02220 case 1:
02221 if (execute) sendmsg(cmd_popup_window_help);
02222 return "help";
02223 case 3:
02224 if (execute) sendmsg(cmd_file_open);
02225 return "open";
02226 case 6:
02227 if (execute) sendmsg(cmd_popup_dialog_view_list);
02228 return "mode";
02229
02230
02231
02232
02233
02234
02235 case 10:
02236 if (execute) sendmsg(cmd_quit);
02237 return "quit";
02238 }
02239 return 0;
02240 }
02241
02242 void ht_app::get_stdbounds_file(bounds *b)
02243 {
02244 if (project) {
02245 bounds c;
02246 get_stdbounds_tool(&c);
02247 battlefield->getbounds(b);
02248 b->x = 0;
02249 b->y = 0;
02250 b->h -= c.h;
02251 } else {
02252 battlefield->getbounds(b);
02253 b->x = 0;
02254 b->y = 0;
02255 }
02256 }
02257
02258 void ht_app::get_stdbounds_tool(bounds *b)
02259 {
02260 UINT h = MAX(size.h/4, 3);
02261 battlefield->getbounds(b);
02262 b->x = 0;
02263 b->y = b->h - h;
02264 b->h = h;
02265 }
02266
02267 ht_window *ht_app::get_window_by_filename(char *filename)
02268 {
02269 UINT c=windows->count();
02270 for (UINT i=0; i<c; i++) {
02271 ht_app_window_entry *e=(ht_app_window_entry*)windows->get(i);
02272
02273 if (strcmp(e->window->desc, filename) == 0) return e->window;
02274 }
02275 return NULL;
02276 }
02277
02278 ht_window *ht_app::get_window_by_number(UINT number)
02279 {
02280 UINT c=windows->count();
02281 for (UINT i=0; i<c; i++) {
02282 ht_app_window_entry *e=(ht_app_window_entry*)windows->get(i);
02283 if (e->number==number) return e->window;
02284 }
02285 return NULL;
02286 }
02287
02288 ht_window *ht_app::get_window_by_type(UINT type)
02289 {
02290 UINT c=windows->count();
02291 for (UINT i=0; i<c; i++) {
02292 ht_app_window_entry *e=(ht_app_window_entry*)windows->get(i);
02293 if (e->type==type) return e->window;
02294 }
02295 return NULL;
02296 }
02297
02298 UINT ht_app::get_window_number(ht_window *window)
02299 {
02300 ht_app_window_entry *e=(ht_app_window_entry*)windows->get(get_window_listindex(window));
02301 if (e) return e->number; else return 0;
02302 }
02303
02304 UINT ht_app::get_window_listindex(ht_window *window)
02305 {
02306 UINT c=windows->count();
02307 for (UINT i=0; i<c; i++) {
02308 ht_app_window_entry *e=(ht_app_window_entry*)windows->get(i);
02309 if (e->window==window) return i;
02310 }
02311 return LIST_UNDEFINED;
02312 }
02313
02314 void ht_app::handlemsg(htmsg *msg)
02315 {
02316 switch (msg->msg) {
02317 #ifdef SYS_SUPPORT_NATIVE_CLIPBOARD
02318 case cmd_edit_copy_native: {
02319 int dz = sys_get_native_clipboard_data_size();
02320 if (dz) {
02321 void *data = smalloc(dz);
02322 if (sys_read_data_from_native_clipboard(data, dz)) {
02323 dz = strlen((char*)data);
02324 clipboard_copy(SYS_NATIVE_CLIPBOARD_NAME, data, dz);
02325 }
02326 free(data);
02327 }
02328 break;
02329 }
02330 case cmd_edit_paste_native: {
02331 int maxsize = clipboard_getsize();
02332 byte *buf = (byte*)smalloc(maxsize);
02333 int r = clipboard_paste(buf, maxsize);
02334 if (r) {
02335 sys_write_data_to_native_clipboard(buf, r);
02336 }
02337 free(buf);
02338 }
02339 #endif
02340 case cmd_file_save: {
02341 UINT i = get_window_listindex((ht_window*)battlefield->current);
02342 ht_app_window_entry *e = (ht_app_window_entry*)windows->get(i);
02343 if ((e) && (e->layer) && (e->isfile)) break;
02344 }
02345 case cmd_file_saveas: {
02346 UINT i=get_window_listindex((ht_window*)battlefield->current);
02347 ht_app_window_entry *e=(ht_app_window_entry*)windows->get(i);
02348 if ((e) && (e->layer)) {
02349 char fn[HT_NAME_MAX];
02350 fn[0] = 0;
02351 if (file_chooser("Save as", fn, sizeof fn)) {
02352 int err;
02353 bool work = true;
02354
02355 if (access(fn, F_OK) == 0) {
02356 work = (confirmbox("File '%s' already exists. Overwrite ?", fn) == button_yes);
02357 }
02358
02359 if (work) {
02360 ht_file *f = new ht_file();
02361 f->init(fn, FAM_WRITE, FOM_CREATE);
02362
02363 if ((err = f->get_error())) {
02364 f->done();
02365 delete f;
02366 LOG_EX(LOG_ERROR, "error saving file %s: %s", fn, strerror(err & ~STERR_SYSTEM));
02367 errorbox("error saving file %s: %s", fn, strerror(err & ~STERR_SYSTEM));
02368 return;
02369 }
02370
02371 e->layer->seek(0);
02372 e->layer->copy_to(f);
02373
02374 ht_streamfile *old = e->layer->get_layered();
02375
02376 if (f->set_access_mode(old->get_access_mode())) {
02377 e->layer->set_layered(f);
02378 e->isfile = true;
02379
02380 old->done();
02381 delete old;
02382
02383 char fullfn[FILENAME_MAX], *ff=fullfn;
02384 if (sys_canonicalize(fullfn, fn)!=0) ff=fn;
02385 e->window->settitle(ff);
02386 clearmsg(msg);
02387 } else errorbox("couldn't inherit access_mode from '%s' to '%s'", old->get_desc(), f->get_desc());
02388 }
02389 }
02390 }
02391 return;
02392 }
02393 case msg_kill: {
02394 htmsg m;
02395 ht_window *w=(ht_window*)msg->data1.ptr;
02396 m.msg=msg_accept_close;
02397 m.type=mt_broadcast;
02398 m.data1.ptr=NULL;
02399 m.data2.ptr=NULL;
02400 w->sendmsg(&m);
02401 if (m.msg==msg_accept_close) delete_window(w);
02402 clearmsg(msg);
02403 return;
02404 }
02405 }
02406 if (msg->msg==msg_draw) {
02407 start_timer(h0);
02408 if (msg->type==mt_broadcast) {
02409 ht_view *v=first;
02410 while (v) {
02411 v->handlemsg(msg);
02412 v=v->next;
02413 }
02414 } else {
02415 current->handlemsg(msg);
02416 }
02417 stop_timer(h0);
02418 draw();
02419 screen->show();
02420 } else {
02421 ht_group::handlemsg(msg);
02422 }
02423 switch (msg->msg) {
02424 case msg_keypressed: {
02425 int i=0;
02426 switch (msg->data1.integer) {
02427 case K_Alt_9: i++;
02428 case K_Alt_8: i++;
02429 case K_Alt_7: i++;
02430 case K_Alt_6: i++;
02431 case K_Alt_5: i++;
02432 case K_Alt_4: i++;
02433 case K_Alt_3: i++;
02434 case K_Alt_2: i++;
02435 case K_Alt_1: i++;
02436 focus(get_window_by_number(i));
02437 clearmsg(msg);
02438 return;
02439 case K_F12: i++;
02440 case K_F11: i++;
02441 case K_F10: i++;
02442 case K_F9: i++;
02443 case K_F8: i++;
02444 case K_F7: i++;
02445 case K_F6: i++;
02446 case K_F5: i++;
02447 case K_F4: i++;
02448 case K_F3: i++;
02449 case K_F2: i++;
02450 case K_F1:
02451 i++;
02452 htmsg m;
02453 m.msg=msg_funcquery;
02454 m.type=mt_empty;
02455 m.data1.integer=i;
02456 sendmsg(&m);
02457 if (m.msg==msg_retval) {
02458 sendmsg(msg_funcexec, i);
02459 clearmsg(msg);
02460 return;
02461 }
02462 break;
02463 #if 0
02464
02465 case K_Control_F9:
02466 ((ht_app*)app)->create_window_term("main.exe");
02467 clearmsg(msg);
02468 return;
02469 case K_Alt_R: {
02470 char *n = "./ht.reg";
02471 ht_file *f = new ht_file();
02472 f->init(n, FAM_WRITE, FOM_CREATE);
02473
02474 ht_object_stream_bin *b = new ht_object_stream_bin();
02475 b->init(f);
02476
02477 b->putObject(registry, NULL);
02478
02479 b->done();
02480 delete b;
02481
02482 f->done();
02483 delete f;
02484
02485 infobox("registry dumped to '%s'", n);
02486
02487 clearmsg(msg);
02488 return;
02489 }
02490 case K_Alt_T:
02491 create_window_ofm("reg:/", "local:/");
02492 clearmsg(msg);
02493 return;*/
02494 case K_Control_A:
02495 create_window_help("/HT/res/info/intidx.info", "Top");
02496
02497 dirtyview();
02498 clearmsg(msg);
02499 return;
02500 #endif
02501 case K_Space:
02502 sendmsg(cmd_popup_dialog_view_list);
02503 clearmsg(msg);
02504 return;
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518 }
02519 break;
02520 }
02521 case cmd_about:
02522 msgbox(btmask_ok, "About "ht_name, 0, align_custom, "\n\ec"ht_name" "ht_version" ("HT_SYS_NAME")\n\n\el"ht_copyright1"\n"ht_copyright2"\n\nThis program is GPL'd. See Help for more information.");
02523 break;
02524 case msg_funcexec:
02525 if (func(msg->data1.integer, 1)) {
02526 clearmsg(msg);
02527 return;
02528 }
02529 break;
02530 case msg_funcquery: {
02531 char *s=func(msg->data1.integer, 0);
02532 if (s) {
02533 msg->msg=msg_retval;
02534 msg->data1.str=s;
02535 } else clearmsg(msg);
02536 return;
02537 }
02538 case cmd_file_exec_cmd: {
02539 char cmd[HT_NAME_MAX];
02540 cmd[0] = 0;
02541 if (inputbox("execute shell command (experimental!)",
02542 (sys_get_caps() & SYSCAP_NONBLOCKING_IPC) ? "command"
02543 : "non-interactive (!) command",
02544 cmd, sizeof cmd, HISTATOM_FILE) == button_ok) {
02545 if (cmd[0]) create_window_term(cmd);
02546 }
02547 clearmsg(msg);
02548 return;
02549 }
02550 case cmd_file_extend: {
02551 ht_streamfile *f = (ht_streamfile *)msg->data1.ptr;
02552 UINT s = (UINT)msg->data2.integer;
02553
02554
02555 int oam = f->get_access_mode();
02556 if (!(oam & FAM_WRITE)) f->set_access_mode(oam | FAM_WRITE);
02557 int e = f->extend(s);
02558 if (!(oam & FAM_WRITE)) f->set_access_mode(oam);
02559 if (e) errorbox("couldn't extend file to offset %08x/%d: %s", s, s, strerror(e));
02560
02561 clearmsg(msg);
02562 return;
02563 }
02564 case cmd_file_truncate: {
02565 ht_streamfile *f = (ht_streamfile *)msg->data1.ptr;
02566 UINT s = (UINT)msg->data2.integer;
02567
02568
02569
02570
02571
02572
02573
02574
02575 if (confirmbox("really truncate %s at offset %08x/%d ?", f->get_filename(), s, s) == button_ok) {
02576 f->truncate(s);
02577 }
02578 clearmsg(msg);
02579 return;
02580 }
02581 case cmd_quit:
02582 if (accept_close_all_windows()) {
02583 LOG("terminating...");
02584 exit_program = true;
02585 sendmsg(cmd_project_close);
02586 clearmsg(msg);
02587 }
02588 return;
02589 case cmd_file_open: {
02590 char *name;
02591 UINT mode;
02592 if (file_open_dialog(&name, &mode)) {
02593 if (name[0]) create_window_file(name, mode, true);
02594 free(name);
02595 }
02596 clearmsg(msg);
02597 return;
02598 }
02599 case cmd_file_new: {
02600 bounds b;
02601 get_stdbounds_file(&b);
02602
02603 UINT mode;
02604
02605 if (file_new_dialog(&mode)) {
02606 ht_mem_file *mfile=new ht_mem_file();
02607 mfile->init();
02608 switch (mode) {
02609 case FOM_TEXT: {
02610 ht_syntax_lexer *lexer = NULL;
02611
02612 ht_ltextfile *tfile = new ht_ltextfile();
02613 tfile->init(mfile, true, lexer);
02614
02615 ht_layer_textfile *file = new ht_layer_textfile();
02616 file->init(tfile, true);
02617
02618 create_window_file_text(&b, file, "Untitled", false);
02619 break;
02620 }
02621 case FOM_BIN: {
02622 ht_streamfile_modifier *modfile = new ht_streamfile_modifier();
02623 modfile->init(mfile, true, 8*1024);
02624
02625 ht_layer_streamfile *file = new ht_layer_streamfile();
02626 file->init(modfile, true);
02627
02628 ht_window *w = create_window_file_bin(&b, file, "Untitled", false);
02629 htmsg m;
02630 m.msg = cmd_file_resize;
02631 m.type = mt_empty;
02632 w->sendmsg(&m);
02633 }
02634 }
02635 }
02636 clearmsg(msg);
02637 return;
02638 }
02639 case cmd_edit_show_clipboard: {
02640 create_window_clipboard();
02641 clearmsg(msg);
02642 return;
02643 }
02644 case cmd_edit_clear_clipboard: {
02645 if (confirmbox("Do you really want to delete the clipboard ?")==button_ok) {
02646 clipboard_clear();
02647 }
02648 clearmsg(msg);
02649 return;
02650 }
02651 case cmd_edit_paste_into_file: {
02652 char filename[HT_NAME_MAX];
02653 filename[0] = 0;
02654 if (file_chooser("clipboard - paste into file", filename, sizeof filename)) {
02655 ht_file *f = new ht_file();
02656 f->init(filename, FAM_WRITE, FOM_CREATE);
02657 if (!f->get_error()) {
02658 clipboard_paste(f, 0);
02659 } else errorbox("can't open file '%s'", filename);
02660 f->done();
02661 delete f;
02662 }
02663 clearmsg(msg);
02664 return;
02665 }
02666 case cmd_edit_copy_from_file: {
02667 char filename[HT_NAME_MAX];
02668 filename[0] = 0;
02669 if (file_chooser("clipboard - copy from file", filename, sizeof filename)) {
02670 char desc[HT_NAME_MAX+5];
02671 ht_file *f = new ht_file();
02672 f->init(filename, FAM_READ, FOM_EXISTS);
02673 if (!f->get_error()) {
02674 ht_snprintf(desc, sizeof desc, "file %s", f->get_filename());
02675 clipboard_copy(desc, f, 0, f->get_size());
02676 } else errorbox("can't open file '%s'", filename);
02677 f->done();
02678 delete f;
02679 }
02680 clearmsg(msg);
02681 return;
02682 }
02683 case cmd_project_open: {
02684 char fn[HT_NAME_MAX];
02685 fn[0] = 0;
02686 if (file_chooser("Open project", fn, sizeof fn)) {
02687 sendmsg(cmd_project_close);
02688 project_opencreate(fn);
02689 }
02690 clearmsg(msg);
02691 return;
02692 }
02693 case cmd_project_close: {
02694 if (project) {
02695 char *fn = ((ht_project*)project)->get_filename();
02696 LOG("%s: saving project", fn);
02697 save_fileconfig(fn, ht_projectconfig_magic, ht_projectconfig_fileversion, file_project_store_fcfg_func, NULL);
02698 LOG("%s: done", fn);
02699 ((ht_project*)project)->destroy();
02700 delete ((ht_project*)project);
02701 project = NULL;
02702 htmsg m;
02703 m.type = mt_broadcast;
02704 m.msg = msg_project_changed;
02705 sendmsg(&m);
02706 }
02707 clearmsg(msg);
02708 return;
02709 }
02710 case cmd_window_close:
02711 if (battlefield->current) sendmsg(msg_kill, battlefield->current);
02712 clearmsg(msg);
02713 return;
02714 case cmd_popup_dialog_eval: {
02715 eval_dialog();
02716 clearmsg(msg);
02717 return;
02718 }
02719 case cmd_popup_dialog_view_list: {
02720 ht_view *v = popup_view_list("select mode");
02721 if (v) focus(v);
02722 clearmsg(msg);
02723 return;
02724 }
02725 case cmd_popup_dialog_window_list: {
02726 ht_window *w = popup_window_list("select window");
02727 if (w) focus(w);
02728 clearmsg(msg);
02729 return;
02730 }
02731 case cmd_popup_dialog_info_loader: {
02732 char file[256];
02733 file[0] = 0;
02734 if (inputbox("open info file", "filename", file, sizeof file, HISTATOM_FILE) == button_ok) {
02735 char node[256];
02736 strcpy(node, "Top");
02737 if (inputbox("open info file", "nodename", node, sizeof node, HISTATOM_GOTO) == button_ok) {
02738 create_window_help(file, node);
02739 dirtyview();
02740 }
02741 }
02742 clearmsg(msg);
02743 return;
02744 }
02745 case cmd_popup_window_log:
02746 create_window_log();
02747 clearmsg(msg);
02748 return;
02749 case cmd_popup_window_project:
02750 create_window_project();
02751 clearmsg(msg);
02752 return;
02753 case cmd_popup_window_options:
02754 create_window_ofm("reg:/", NULL);
02755 clearmsg(msg);
02756 return;
02757 case cmd_popup_window_help:
02758 create_window_help(MAGIC_HT_HELP, "Top");
02759 clearmsg(msg);
02760 return;
02761 case msg_project_changed: {
02762 ht_window *w = ((ht_app*)app)->get_window_by_type(AWT_PROJECT);
02763 if (w) w->sendmsg(msg_dirtyview);
02764 app->sendmsg(msg_draw);
02765 return;
02766 }
02767 }
02768 }
02769
02770 void ht_app::insert_window(ht_window *window, UINT type, bool minimized, bool isfile, ht_layer_streamfile *layer)
02771 {
02772 UINT n=find_free_window_number();
02773 ht_app_window_entry *e=new ht_app_window_entry(window, n, type, minimized, isfile, layer);
02774 windows->insert(e);
02775 window->setnumber(n);
02776 battlefield->insert(window);
02777 focus(window);
02778 }
02779
02780 int ht_app::load(ht_object_stream *f)
02781 {
02782 ht_registry *temp;
02783
02784 if (!(temp=(ht_registry*)f->getObject(NULL))) return 1;
02785
02786 if (registry) {
02787 registry->done();
02788 delete registry;
02789 }
02790 registry=temp;
02791
02792 load_history(f);
02793
02794 htmsg m;
02795 m.msg=msg_config_changed;
02796 m.type=mt_broadcast;
02797 app->sendmsg(&m);
02798 return f->get_error();
02799 }
02800
02801 OBJECT_ID ht_app::object_id() const
02802 {
02803 return ATOM_HT_APP;
02804 }
02805
02806 static int my_compare_func(const char *a, const char *b)
02807 {
02808 return strcmp(a, b);
02809 }
02810
02811 ht_view *ht_app::popup_view_list(char *dialog_title)
02812 {
02813 if (!battlefield->current) return NULL;
02814 bounds b, c;
02815 getbounds(&b);
02816 b.x=b.w/4;
02817 b.y=b.h/4;
02818 b.w/=2;
02819 b.h/=2;
02820 ht_dialog *dialog=new ht_dialog();
02821 dialog->init(&b, dialog_title, FS_KILLER | FS_TITLE | FS_MOVE);
02822
02823
02824 c=b;
02825 c.x=0;
02826 c.y=0;
02827 c.w-=2;
02828 c.h-=2;
02829 ht_text_listbox *listbox=new ht_text_listbox();
02830 listbox->init(&c, 1, 0, LISTBOX_NORMAL);
02831
02832
02833 ht_clist *structure=new ht_clist();
02834 ((ht_clist*)structure)->init();
02835 int index=0;
02836 popup_view_list_dump(battlefield->current, listbox, structure, 0, &index, battlefield->getselected());
02837
02838 listbox->update();
02839 listbox->gotoItemByPosition(index);
02840
02841 ht_text_listbox_sort_order so[1];
02842 so[0].col = 0;
02843 so[0].compare_func = my_compare_func;
02844
02845
02846
02847
02848
02849 dialog->insert(listbox);
02850 dialog->setpalette(palkey_generic_special);
02851
02852 ht_view *result = NULL;
02853 if (dialog->run(false)) {
02854 ht_listbox_data data;
02855 listbox->databuf_get(&data, sizeof data);
02856 ht_data_ptr *p=(ht_data_ptr*)structure->get(listbox->getID(data.cursor_ptr));
02857 if (p) result = (ht_view*)p->value;
02858 }
02859
02860 structure->destroy();
02861 delete structure;
02862
02863 dialog->done();
02864 delete dialog;
02865 return result;
02866 }
02867
02868 int ht_app::popup_view_list_dump(ht_view *view, ht_text_listbox *listbox, ht_list *structure, int depth, int *currenti, ht_view *currentv)
02869 {
02870 if (!view) return 0;
02871 char str[256];
02872 char *s=str;
02873 if (!(view->options & VO_BROWSABLE)) {
02874 depth--;
02875 }
02876
02877 for (int i=0; i<depth; i++) { *(s++)=' ';*(s++)=' '; }
02878 *s=0;
02879
02880 int c=view->childcount();
02881 int count=0;
02882 for (int i=0; i<c; i++) {
02883 ht_view *v=view->getfirstchild();
02884 while (v) {
02885 if (v->browse_idx==i) break;
02886 v=v->next;
02887 }
02888 if (!v) return count;
02889
02890
02891 if ((v->desc) && (strcmp(v->desc, VIEWERGROUP_NAME)) && (v->options & VO_BROWSABLE)) {
02892 ht_snprintf(s, sizeof str-(s-str), "- %s", v->desc);
02893 structure->insert(new ht_data_ptr(v));
02894 if (v==currentv)
02895 *currenti=structure->count()-1;
02896 listbox->insert_str(structure->count()-1, str);
02897 count++;
02898 }
02899 count+=popup_view_list_dump(v, listbox, structure, depth+1, currenti, currentv);
02900 }
02901 return count;
02902 }
02903
02904 ht_window *ht_app::popup_window_list(char *dialog_title)
02905 {
02906 bounds b, c;
02907 getbounds(&b);
02908 c=b;
02909 b.w=b.w*2/3;
02910 b.h=b.h*2/3;
02911 b.x=(c.w-b.w)/2;
02912 b.y=(c.h-b.h)/2;
02913 ht_dialog *dialog=new ht_dialog();
02914 dialog->init(&b, dialog_title, FS_KILLER | FS_TITLE | FS_MOVE);
02915
02916
02917 c=b;
02918 c.x=0;
02919 c.y=0;
02920 c.w-=2;
02921 c.h-=2;
02922 ht_text_listbox *listbox=new ht_itext_listbox();
02923 listbox->init(&c, 2, 1);
02924
02925 UINT vc=windows->count();
02926 for (UINT i=0; i<vc; i++) {
02927 ht_app_window_entry *e=(ht_app_window_entry*)windows->get(i);
02928 char l[16];
02929 ht_snprintf(l, sizeof l, " %2d", e->number);
02930 listbox->insert_str(e->number, l, e->window->desc);
02931 }
02932 listbox->update();
02933 if (battlefield->current) listbox->gotoItemByPosition(battlefield->current->getnumber()-1);
02934
02935 dialog->insert(listbox);
02936 dialog->setpalette(palkey_generic_special);
02937
02938 ht_window *result = NULL;
02939 if (dialog->run(false)) {
02940 ht_listbox_data data;
02941 listbox->databuf_get(&data, sizeof data);
02942 result = get_window_by_number(listbox->getID(data.cursor_ptr));
02943 }
02944 dialog->done();
02945 delete dialog;
02946 return result;
02947 }
02948
02949 void ht_app::project_opencreate(char *filename)
02950 {
02951 char fn[HT_NAME_MAX];
02952 char cwd[HT_NAME_MAX];
02953 getcwd(cwd, sizeof cwd);
02954 if (sys_common_canonicalize(fn, filename, cwd, sys_is_path_delim) != 0) {
02955 LOG("%s: invalid filename", filename);
02956 return;
02957 }
02958 char *suf = sys_filename_suffix(fn);
02959
02960 if (!(suf && (strcmp(suf, HT_PROJECT_CONFIG_SUFFIX+1)==0))) {
02961 strcat(fn, HT_PROJECT_CONFIG_SUFFIX);
02962 }
02963
02964 void *old_project = project;
02965 project = NULL;
02966 int einfo;
02967 LOG("%s: loading project file...", fn);
02968 bool error = true;
02969 loadstore_result lsr = load_fileconfig(fn, ht_projectconfig_magic, ht_projectconfig_fileversion, file_project_load_fcfg_func, NULL, &einfo);
02970 if (lsr == LS_ERROR_CORRUPTED) {
02971 LOG_EX(LOG_ERROR, "%s: error in line %d", fn, einfo);
02972 errorbox("%s: error in line %d", fn, einfo);
02973 } else if (lsr == LS_ERROR_NOT_FOUND) {
02974 if (confirmbox("%s: no such project.\nDo you want to create this project ?", fn) == button_yes) {
02975 project = new ht_project();
02976 ((ht_project*)project)->init(fn);
02977 LOG("%s: new project created", fn);
02978 error = false;
02979 }
02980 } else if (lsr != LS_OK) {
02981 LOG_EX(LOG_ERROR, "%s: some error", fn);
02982 errorbox("%s: some error", fn);
02983 } else {
02984 LOG("%s: done", fn);
02985 error = false;
02986 }
02987 if (error) {
02988
02989 project = old_project;
02990 } else {
02991 htmsg m;
02992 m.type = mt_broadcast;
02993 m.msg = msg_project_changed;
02994 sendmsg(&m);
02995 create_window_project();
02996 }
02997 }
02998
02999 int ht_app::run(bool modal)
03000 {
03001 sendmsg(msg_draw, 0);
03002 while (!exit_program) {
03003 if (ht_keypressed()) {
03004 int k = ht_getkey();
03005 sendmsg(msg_keypressed, k);
03006 sendmsg(msg_draw);
03007 }
03008 ht_queued_msg *q;
03009 while ((q = dequeuemsg())) {
03010 htmsg m = q->msg;
03011 q->target->sendmsg(&m);
03012 sendmsg(msg_draw);
03013 delete q;
03014 }
03015 do_idle();
03016 }
03017 return 0;
03018 }
03019
03020 void ht_app::store(ht_object_stream *f)
03021 {
03022 f->putObject(registry, NULL);
03023
03024 store_history(f);
03025 }
03026
03027
03028
03029
03030
03031 ht_vstate_history_entry::ht_vstate_history_entry(Object *Data, ht_view *View)
03032 {
03033 data = Data;
03034 view = View;
03035 }
03036
03037 ht_vstate_history_entry::~ht_vstate_history_entry()
03038 {
03039 data->done();
03040 delete data;
03041 }
03042
03043
03044
03045
03046
03047 void ht_file_window::init(bounds *b, char *desc, UINT framestyle, UINT number, ht_streamfile *f)
03048 {
03049 ht_window::init(b, desc, framestyle, number);
03050 file = f;
03051 vstate_history = new ht_clist();
03052 ((ht_clist*)vstate_history)->init();
03053 vstate_history_pos = 0;
03054 }
03055
03056 void ht_file_window::done()
03057 {
03058 vstate_history->destroy();
03059 delete vstate_history;
03060 ht_window::done();
03061 }
03062
03063 void ht_file_window::add_vstate_history(ht_vstate_history_entry *e)
03064 {
03065 int c = vstate_history->count();
03066 if (c > vstate_history_pos) {
03067 vstate_history->del_multiple(vstate_history_pos, c-vstate_history_pos);
03068 }
03069 vstate_history->insert(e);
03070 vstate_history_pos++;
03071 }
03072
03073 void ht_file_window::handlemsg(htmsg *msg)
03074 {
03075 switch (msg->msg) {
03076 case cmd_vstate_restore: {
03077 if (vstate_history_pos) {
03078 vstate_history_pos--;
03079 ht_vstate_history_entry *e = (ht_vstate_history_entry*)
03080 vstate_history->get(vstate_history_pos);
03081 htmsg m;
03082 m.msg = msg_vstate_restore;
03083 m.type = mt_empty;
03084 m.data1.ptr = e->data;
03085 e->view->sendmsg(&m);
03086 focus(e->view);
03087 }
03088 clearmsg(msg);
03089 return;
03090 }
03091 case msg_vstate_save: {
03092 Object *data = (Object*)msg->data1.ptr;
03093 ht_view *view = (ht_view*)msg->data2.ptr;
03094 add_vstate_history(new ht_vstate_history_entry(data, view));
03095 break;
03096 }
03097 case msg_accept_close: if (file) {
03098 bool modified=false;
03099 if (file->get_filename() != NULL) {
03100 file->cntl(FCNTL_MODS_IS_DIRTY, 0, file->get_size(), &modified);
03101 } else {
03102 modified = true;
03103 }
03104 if (modified) {
03105 char q[1024];
03106 if (file->get_filename()) {
03107 ht_snprintf(q, sizeof q, "file %s has been modified, save ?", file->get_filename());
03108 } else {
03109 ht_snprintf(q, sizeof q, "untitled file has been modified, save ?");
03110 }
03111 switch (msgbox(btmask_yes+btmask_no+btmask_cancel, "confirmation", 0, align_center, q)) {
03112 case button_yes: {
03113 app->focus(this);
03114 htmsg msg;
03115 msg.msg = cmd_file_save;
03116 msg.type = mt_empty;
03117 app->sendmsg(&msg);
03118 if ((UINT)msg.msg != cmd_file_save) break;
03119 }
03120 case button_cancel:
03121 clearmsg(msg);
03122 return;
03123 }
03124 }
03125
03126
03127 file->cntl(FCNTL_FLUSH_STAT);
03128
03129 Analyser *a;
03130 htmsg m;
03131 m.msg=msg_get_analyser;
03132 m.type=mt_broadcast;
03133 m.data1.ptr=NULL;
03134 sendmsg(&m);
03135 a = (Analyser*)m.data1.ptr;
03136 if ((m.msg==msg_retval) && (a) && (a->isDirty())) {
03137 sendmsg(cmd_analyser_save);
03138 }
03139 }
03140 break;
03141 case cmd_analyser_save: {
03142 char filename[1024];
03143 ht_snprintf(filename, sizeof filename, "%s%s", file->get_filename(), HT_FILE_CONFIG_SUFFIX);
03144 LOG("%s: saving config", filename);
03145 save_fileconfig(filename, ht_fileconfig_magic, ht_fileconfig_fileversion, file_window_store_fcfg_func, this);
03146 LOG("%s: done", filename);
03147 clearmsg(msg);
03148 break;
03149 }
03150 }
03151 ht_window::handlemsg(msg);
03152 switch (msg->msg) {
03153 case msg_keypressed:
03154 switch (msg->data1.integer) {
03155 case K_Alt_Backspace:
03156 case K_Backspace: {
03157 sendmsg(cmd_vstate_restore);
03158 clearmsg(msg);
03159 return;
03160 }
03161 }
03162 break;
03163 }
03164 }
03165
03166
03167
03168 ht_list *build_vfs_list()
03169 {
03170
03171 ht_clist *vfslist=new ht_clist();
03172 vfslist->init();
03173
03174 #if 1
03175
03176 LocalFs *localfs = new LocalFs();
03177 localfs->init();
03178
03179
03180 RegistryFs *registryfs = new RegistryFs();
03181 registryfs->init();
03182
03183 vfslist->insert(localfs);
03184 vfslist->insert(registryfs);
03185 #else
03186
03187 ht_file_vfs *file_vfs = new ht_file_vfs();
03188 file_vfs->init();
03189
03190
03191 ht_reg_vfs *reg_vfs = new ht_reg_vfs();
03192 reg_vfs->init();
03193
03194 vfslist->insert(file_vfs);
03195 vfslist->insert(reg_vfs);
03196 #endif
03197
03198
03199 return vfslist;
03200 }
03201
03202 BUILDER(ATOM_HT_APP, ht_app);
03203 BUILDER(ATOM_HT_PROJECT, ht_project);
03204 BUILDER(ATOM_HT_PROJECT_ITEM, ht_project_item);
03205
03206
03207
03208
03209
03210 bool init_app()
03211 {
03212 bounds b;
03213 screen = new screendrawbuf(ht_name" "ht_version);
03214
03215 loglines = new ht_log();
03216 loglines->init();
03217
03218 virtual_fs_list = build_vfs_list();
03219
03220 project = NULL;
03221
03222 b.x = 0;
03223 b.y = 0;
03224 b.w = screen->size.w;
03225 b.h = screen->size.h;
03226 app = new ht_app();
03227 ((ht_app*)app)->init(&b);
03228 baseview = app;
03229
03230 app_memory_reserve = malloc(16384);
03231 out_of_memory_func = &app_out_of_memory_proc;
03232
03233 REGISTER(ATOM_HT_APP, ht_app);
03234 REGISTER(ATOM_HT_PROJECT, ht_project);
03235 REGISTER(ATOM_HT_PROJECT_ITEM, ht_project_item);
03236 register_atom(ATOM_COMPARE_KEYS_PROJECT_ITEM, (void*)compare_keys_project_item);
03237
03238 return true;
03239 }
03240
03241
03242
03243
03244
03245 void done_app()
03246 {
03247 UNREGISTER(ATOM_HT_APP, ht_app);
03248 UNREGISTER(ATOM_HT_PROJECT, ht_project);
03249 UNREGISTER(ATOM_HT_PROJECT_ITEM, ht_project_item);
03250 unregister_atom(ATOM_COMPARE_KEYS_PROJECT_ITEM);
03251
03252 out_of_memory_func = &out_of_memory;
03253 if (app_memory_reserve) free(app_memory_reserve);
03254
03255 if (project) {
03256 ((ht_project*)project)->destroy();
03257 delete ((ht_project*)project);
03258 }
03259
03260 virtual_fs_list->destroy();
03261 delete virtual_fs_list;
03262
03263 loglines->destroy();
03264 delete loglines;
03265
03266 if (app) {
03267 app->done();
03268 delete app;
03269 }
03270
03271 if (screen) delete screen;
03272 }
03273