?? htapp.cc
字號:
/* * HT Editor * htapp.cc * * Copyright (C) 1999-2002 Stefan Weyergraf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "analy.h"#include "cmds.h"#include "log.h"#include "mfile.h"#include "htapp.h"#include "atom.h"#include "display.h"#include "htcfg.h"#include "htclipboard.h"#include "htdialog.h"#include "hteval.h"#include "hthist.h"#include "htidle.h"#include "htinfo.h"#include "htiobox.h"#include "keyb.h"#include "htmenu.h"#include "htpal.h"#include "htsearch.h"#include "strtools.h"#include "sys.h"#include "httree.h"#include "infoview.h"#include "snprintf.h"#include "stream.h"#include "textedit.h"#include "textfile.h"#include "tools.h"#include "vfsview.h"#include "formats.h"#include <errno.h>#include <stdarg.h>#include <stdlib.h>#include <string.h>#include <sys/stat.h>#include <sys/types.h>#include <time.h>#include <unistd.h>#include <exception>extern "C" {#include "regex.h"}#define ATOM_HT_APP MAGIC32("APP\x00")#define ATOM_HT_PROJECT MAGIC32("APP\x01")#define ATOM_HT_PROJECT_ITEM MAGIC32("APP\x02")#define ATOM_COMPARE_KEYS_PROJECT_ITEM MAGIC32("APP\x10")#define HT_PROJECT_CONFIG_SUFFIX ".htprj"#define HT_FILE_CONFIG_SUFFIX ".htcfg"ht_log *loglines;/* * CLASS ht_help_window */class ht_help_window : public ht_window {public:/* overwritten */ virtual void handlemsg(htmsg *msg);};void ht_help_window::handlemsg(htmsg *msg){ ht_window::handlemsg(msg); if (msg->msg == msg_keypressed) { switch (msg->data1.integer) { case K_Escape: { htmsg m; m.type = mt_empty; m.msg = cmd_window_close; ((ht_app*)app)->queuemsg(app, m); clearmsg(msg); return; } } }}bool file_new_dialog(uint *mode){ Bounds b, c; app->getbounds(&b); b.x = (b.w - 40) / 2, b.y = (b.h - 8) / 2; b.w = 40; b.h = 8; ht_dialog *d=new ht_dialog(); d->init(&b, "create new file", FS_KILLER | FS_TITLE | FS_MOVE | FS_RESIZE); b.x=0; b.y=0; /* mode (input) */ c=b; c.x=0; c.y=1; c.w=b.w-2-c.x; c.h=b.h-2-c.y; ht_text_listbox *mode_input = new ht_text_listbox(); mode_input->init(&c); mode_input->insert_str(FOM_TEXT, "text"); mode_input->insert_str(FOM_BIN, "binary"); mode_input->update(); d->insert(mode_input); /* mode (text) */ c=b; c.x=0; c.y=0; c.w=12; c.h=1; ht_label *mode_text=new ht_label(); mode_text->init(&c, "choose ~type", mode_input); d->insert(mode_text); bool retval = false; if (d->run(false)) { ht_listbox_data type; ViewDataBuf vdb(mode_input, &type, sizeof type); *mode = mode_input->getID(type.data->cursor_ptr); retval = true; } d->done(); delete d; return retval;}/* * class FileBrowserVfsListbox */ class FileBrowser;#define FileBrowserVfsListboxData VfsListboxDataclass FileBrowserVfsListbox: public VfsListbox {protected: FileBrowser *file_browser;public: void init(Bounds *b, List *vfs_list, ht_text *show_pos, FileBrowser *file_browser);/* overwritten */ virtual void stateChanged();};/* * class FileBrowser */ struct FileBrowserData { ht_strinputfield_data name; ht_listbox_data listbox;};class FileBrowser: public ht_dialog {protected: ht_strinputfield *name_input; FileBrowserVfsListbox *listbox;public: virtual void init(Bounds *b, Bounds *clientarea, const char *title, const char *starturl); virtual void setstate(int state, int return_val); virtual bool extract_url(char *buf); virtual void listbox_changed();};/**/void FileBrowserVfsListbox::init(Bounds *b, List *vfs_list, ht_text *show_pos, FileBrowser *fb){ file_browser = NULL; VfsListbox::init(b, vfs_list, show_pos); file_browser = fb;}void FileBrowserVfsListbox::stateChanged(){ if (file_browser) file_browser->listbox_changed(); VfsListbox::stateChanged();}/**/void FileBrowser::init(Bounds *n, Bounds *clientarea, const char *title, const char *starturl){ ht_dialog::init(n, title, FS_KILLER | FS_TITLE | FS_MOVE | FS_RESIZE); Bounds b = *clientarea, c; /* name (input) */ c = b; c.x = 1; c.y = 1; c.w -= 2; c.h = 1; List *hist = (List*)getAtomValue(HISTATOM_FILE); name_input = new ht_strinputfield(); name_input->init(&c, 128, hist); insert(name_input); /* name (text) */ c = b; c.x = 1; c.y = 0; c.w = 9; c.h = 1; ht_label *name_text = new ht_label(); name_text->init(&c, "~name", name_input); insert(name_text); /* vfslistbox */ c = b; c.x = 1; c.y = 4; c.w -= 2; c.h -= 4; listbox = new FileBrowserVfsListbox(); listbox->init(&c, virtual_fs_list, NULL, this); listbox->changeURL(starturl); insert(listbox); /* vfslistbox (text) */ c.assign(1, 3, 9, 1); ht_label *name_listbox = new ht_label(); name_listbox->init(&c, "~files", listbox); insert(name_listbox);}bool FileBrowser::extract_url(char *buf){ ht_strinputfield_data i; ViewDataBuf vdb(name_input, &i, sizeof i);/* ht_text_listbox_item *t = (ht_text_listbox_item*)listbox->getbyid(d.listbox.cursor_id); vfs_extra *x = (vfs_extra*)t->extra_data;*/ Vfs *vfs = listbox->getCurVfs(); if (vfs) { int buflen = ht_snprintf(buf, VFS_URL_MAX, "%s:", listbox->getCurProto()); char fname[VFS_URL_MAX]; bin2str(fname, i.text, i.textlen); vfs->canonicalize(buf+buflen, fname, listbox->getCurDir()); return true; } return false;}void FileBrowser::listbox_changed(){ FileBrowserVfsListboxData l; ViewDataBuf vdb(listbox, &l, sizeof l); ht_text_listbox_item *t = (ht_text_listbox_item*)l.data->cursor_ptr; if (t) { vfs_extra *x = (vfs_extra*)t->extra_data; ht_strinputfield_data i; i.textlen = strlen(x->name); i.text = (byte*)x->name; name_input->databuf_set(&i, sizeof i); }}void FileBrowser::setstate(int state, int return_val){ if (state == ds_term_ok) { ht_strinputfield_data i; ViewDataBuf vdb(name_input, &i, sizeof i); pstat_t s; String fn(i.text, i.textlen); int e = sys_pstat(s, fn.contentChar()); if (e == 0 && (s.caps & pstat_mode_type) && (s.mode & HT_S_IFDIR)) { fn.prepend("local:"); listbox->changeURL(fn.contentChar()); return; } } ht_dialog::setstate(state, return_val);}/**/bool file_chooser(const char *title, char *buf, int bufsize){ Bounds b, c; app->getbounds(&b); c = b; b.w = 60; b.h = 20; b.x = (c.w - b.w) / 2, b.y = (c.h - b.h) / 2; c = b; c.x = 0; c.y = 0; c.w -= 2; c.h -= 3; // FIXME: hacked! char cwd[HT_NAME_MAX]; strcpy(cwd, "local:"); if (!getcwd(cwd+6, (sizeof cwd)-6)) { cwd[6] = 0; } FileBrowser *d = new FileBrowser(); d->init(&b, &c, title, cwd); List *hist = (List*)getAtomValue(HISTATOM_FILE); /* go! */ if (d->run(false)) { char b[VFS_URL_MAX]; d->extract_url(b); // FIXME: urls not fully supported... if (ht_strncmp(b, "local:", 6) == 0) { ht_strlcpy(buf, b+6, bufsize); if (hist) insert_history_entry(hist, buf, 0); d->done(); delete d; return true; } } d->done(); delete d; return false;}/**/bool file_open_dialog(char **name, uint *mode){ Bounds b, c; app->getbounds(&b); c = b; b.w = 60; b.h = 20; b.x = (c.w - b.w) / 2, b.y = (c.h - b.h) / 2; c = b; c.x = 0; c.y = 0; c.w -= 2; c.h -= 5; // FIXME: hacked! char cwd[HT_NAME_MAX]; strcpy(cwd, "local:"); if (!getcwd(cwd+6, (sizeof cwd)-6)) { cwd[6] = 0; } FileBrowser *d = new FileBrowser(); d->init(&b, &c, "open file", cwd); List *hist = (List*)getAtomValue(HISTATOM_FILE); /* mode (input) */ c = b; c.x = 6; c.y = b.h-4; c.w = 12; c.h = 1; ht_listpopup *mode_input = new ht_listpopup(); mode_input->init(&c); mode_input->insertstring("autodetect"); mode_input->insertstring("binary"); mode_input->insertstring("text"); mode_input->growmode = MK_GM(GMH_LEFT, GMV_BOTTOM); d->insert(mode_input); /* mode (text) */ c = b; c.x = 1; c.y = b.h-4; c.w = 9; c.h = 1; ht_label *mode_text = new ht_label(); mode_text->init(&c, "~mode", mode_input); mode_text->growmode = MK_GM(GMH_LEFT, GMV_BOTTOM); d->insert(mode_text); /* go! */ if (d->run(false)) { struct { FileBrowserData browser; ht_listpopup_data mode; } data; ViewDataBuf vdb(d, &data, sizeof data); char buf[VFS_URL_MAX]; d->extract_url(buf); // FIXME: urls not fully supported... if (ht_strncmp(buf, "local:", 6) == 0) { *name = ht_strdup(buf+6); if (hist) insert_history_entry(hist, *name, 0); switch (data.mode.cursor_pos) { case 0: *mode=FOM_AUTO; break; case 1: *mode=FOM_BIN; break; case 2: *mode=FOM_TEXT; break; } d->done(); delete d; return true; } } d->done(); delete d; return false;}static uint autodetect_file_open_mode(const char *filename){#define AUTODETECT_SIZE 128 FILE *f=fopen(filename, "rb"); uint r=FOM_BIN; if (f) { byte buf[AUTODETECT_SIZE]; int c=fread(buf, 1, AUTODETECT_SIZE, f); /* empty files are text files */ if (!c) return FOM_TEXT; bool is_bin=false; uint prob_bin_chars=0; for (int i=0; i<c; i++) { if (buf[i]==0) { is_bin=true; break; } else if (buf[i]<32) { prob_bin_chars++; } else if (buf[i]>0xa9) { prob_bin_chars++; } } if (c) { if (prob_bin_chars*100/c>=50) is_bin=true; } else is_bin=true; if (!is_bin) r=FOM_TEXT; fclose(f); return r; } return FOM_BIN;}void file_window_load_fcfg_func(ObjectStream &f, void *context){ ht_file_window *w = (ht_file_window*)context; pstat_t p; FileOfs oldsize = GETX_INT64D(f, "filesize"); uint32 oldtime = GETX_INT32X(f, "filetime"); FileOfs newsize = w->file->getSize(); w->file->pstat(p); uint32 newtime = (p.caps & pstat_mtime) ? p.mtime : 0; if (newsize != oldsize || newtime != oldtime) { char s_oldtime[64], s_newtime[64]; struct tm *t; time_t tt = newtime; t = localtime(&tt); strftime(s_newtime, sizeof s_newtime, "%X %d %b %Y", t); tt = oldtime; t = localtime(&tt); strftime(s_oldtime, sizeof s_oldtime, "%X %d %b %Y", t); String fn; if (confirmbox_c("\ecconfig file applies to different version of file '%y'.\n\n" "\elcurrent: %10qd %s\n\elold: %10qd %s\n\n" "\ecload config file?", &w->file->getDesc(fn), newsize, s_newtime, oldsize, s_oldtime) != button_yes) { return; } } Analyser *a = f.getObject("analyser"); htmsg m; m.msg = msg_set_analyser; m.type = mt_broadcast; m.data1.ptr = a; w->sendmsg(&m);}void file_window_store_fcfg_func(ObjectStream &f, void *context){ ht_file_window *w = (ht_file_window*)context; htmsg m; m.msg = msg_get_analyser; m.type = mt_broadcast; m.data1.ptr = NULL; w->sendmsg(&m); if (m.msg == msg_retval && m.data1.ptr) { pstat_t s; w->file->pstat(s); uint32 t = (s.caps & pstat_mtime) ? s.mtime : 0; PUTX_INT64D(f, w->file->getSize(), "filesize"); PUTX_INT32X(f, t, "filetime"); Analyser *a = (Analyser*)m.data1.ptr; f.putObject(a, "analyser"); }}void file_project_store_fcfg_func(ObjectStream &f, void *context){ PUT_OBJECT(f, (Object*)project);}void file_project_load_fcfg_func(ObjectStream &f, void *context){ Object *p; GET_OBJECT(f, p); project = p;}/* * app_stream_error_func() */#if 0int app_stream_error_func(ht_stream *stream){ int err=stream->get_error(); const char *name = stream->get_desc(); if (err & STERR_SYSTEM) { err=err&0xffff; switch (err) { case 4: { /* EACCES*/#ifdef DJGPP struct stat sbuf; stat(name, &sbuf); if (!(sbuf.st_mode & S_IWUSR)) { 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) { if (chmod(name, S_IRUSR | S_IWUSR)) { errorbox_modal("%s: error (%04x) changing attribute", name, errno & 0xffff); } else { stat(name, &sbuf); if (!(sbuf.st_mode & S_IWUSR)) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -