00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <string.h>
00022
00023 #include "htatom.h"
00024 #include "htctrl.h"
00025 #include "htendian.h"
00026 #include "hthist.h"
00027 #include "htiobox.h"
00028 #include "htpal.h"
00029 #include "htstring.h"
00030 #include "snprintf.h"
00031 #include "syntax.h"
00032 #include "textedit.h"
00033 #include "textfile.h"
00034
00035 extern "C" {
00036 #include "evalx.h"
00037 }
00038
00039
00040
00041
00042
00043 #define FH_HEAD 1
00044 #define FH_DESC 2
00045
00046
00047 class ht_help_lexer: public ht_syntax_lexer {
00048 public:
00049
00050 virtual vcp getcolor_syntax(UINT pal_index)
00051 {
00052 return VCP(VC_BLUE, VC_TRANSPARENT);
00053 }
00054
00055 virtual lexer_state getinitstate()
00056 {
00057 return FH_HEAD;
00058 }
00059
00060 virtual lexer_token geterrortoken()
00061 {
00062 return 3;
00063 }
00064
00065 virtual char *getname()
00066 {
00067 return "bla";
00068 }
00069
00070 virtual lexer_token gettoken(void *buf, UINT buflen, text_pos p, bool start_of_line, lexer_state *ret_state, UINT *ret_len)
00071 {
00072 *ret_len = buflen;
00073 int ps = *ret_state;
00074 if (buflen == 0) *ret_state = FH_HEAD; else *ret_state = FH_DESC;
00075 return buflen ? ps : 0;
00076 }
00077
00078 virtual vcp gettoken_color(lexer_token t)
00079 {
00080 switch (t) {
00081 case FH_HEAD:
00082 return VCP(VC_LIGHT(VC_WHITE), VC_TRANSPARENT);
00083 case FH_DESC:
00084 return VCP(VC_BLACK, VC_TRANSPARENT);
00085 }
00086 return VCP(VC_RED, VC_TRANSPARENT);
00087 }
00088 };
00089
00090 static void dialog_fhelp(ht_streamfile *f)
00091 {
00092 ht_help_lexer *l = new ht_help_lexer();
00093 l->init();
00094
00095 ht_ltextfile *t = new ht_ltextfile();
00096 t->init(f, true, NULL);
00097
00098 bounds b, c;
00099 app->getbounds(&c);
00100 b = c;
00101
00102
00103 b.x = (c.w - b.w) / 2,
00104 b.y = (c.h - b.h) / 2;
00105 c = b;
00106
00107 ht_dialog *dialog = new ht_dialog();
00108 dialog->init(&b, "eval() - functions", FS_KILLER | FS_TITLE | FS_MOVE | FS_RESIZE);
00109
00110 b.x = 0;
00111 b.y = 0;
00112 b.w -= 2;
00113 b.h -= 2;
00114
00115 ht_text_viewer *v = new ht_text_viewer();
00116 v->init(&b, true, t, NULL);
00117
00118 v->set_lexer(l, true);
00119
00120 dialog->insert(v);
00121
00122 b = c;
00123 b.x = b.w-2;
00124 b.y = 0;
00125 b.w = 1;
00126 b.h-=2;
00127 ht_scrollbar *hs=new ht_scrollbar();
00128 hs->init(&b, &dialog->pal, true);
00129
00130 dialog->setvscrollbar(hs);
00131
00132 dialog->setpalette(palkey_generic_cyan);
00133
00134 dialog->run(0);
00135
00136 v->done();
00137 delete v;
00138 }
00139
00140 void dialog_eval_help(eval_func_handler func_handler, eval_symbol_handler symbol_handler, void *context)
00141 {
00142 eval_scalar res;
00143 if (eval(&res, "help()", func_handler, symbol_handler, context)) {
00144 eval_str s;
00145 scalar_context_str(&res, &s);
00146 scalar_destroy(&res);
00147
00148 ht_memmap_file *f = new ht_memmap_file();
00149 f->init((byte*)s.value, s.len);
00150
00151 dialog_fhelp(f);
00152
00153 string_destroy(&s);
00154 }
00155 }
00156
00157
00158
00159
00160 static int sprint_base2(char *x, dword value, bool leading_zeros)
00161 {
00162 char *ix = x;
00163 bool draw = leading_zeros;
00164 for (int i=0; i<32; i++) {
00165 bool v = value & (1<<(32-i-1));
00166 if (v) draw = true;
00167 if (draw) *x++ = v ? '1' : '0';
00168 }
00169 *x = 0;
00170 return x-ix;
00171 }
00172
00173 static int sprint_base2_0(char *x, dword value, int zeros)
00174 {
00175 char *ix = x;
00176 char vi = 0;
00177 dword m = 0x80000000;
00178 while (zeros < 32) {m >>= 1; zeros++;}
00179 do {
00180 if (value & m) {
00181 while (vi--) *(x++)='0';
00182 vi = 0;
00183 *x = '1';
00184 x++;
00185 } else {
00186 vi++;
00187 }
00188 m >>= 1;
00189 } while (m);
00190 if (!value) *(x++)='0';
00191 *x = 0;
00192 return x-ix;
00193 }
00194
00195 static void nicify(char *dest, const char *src, int d)
00196 {
00197 *dest = *src;
00198 int l=strlen(src);
00199 if (!l) return;
00200 dest++;
00201 src++;
00202 while (l--) {
00203 if ((l%d==0) && (l>1)) {
00204 *dest='\'';
00205 dest++;
00206 }
00207 *(dest++) = *(src++);
00208 }
00209 *dest=0;
00210 }
00211
00212 #define BUTTON_HELP 100
00213
00214 static void do_eval(ht_strinputfield *s, ht_statictext *t, char *b)
00215 {
00216 eval_scalar r;
00217 if (eval(&r, b, NULL, NULL, NULL)) {
00218 switch (r.type) {
00219 case SCALAR_INT: {
00220 char *x = b;
00221 char buf1[1024];
00222 char buf2[1024];
00223
00224 dword lo = QWORD_GET_LO(r.scalar.integer.value);
00225 dword hi = QWORD_GET_HI(r.scalar.integer.value);
00226 x += sprintf(x, "64bit integer:\n");
00227 ht_snprintf(buf1, sizeof buf1, "%qx", &r.scalar.integer.value);
00228 nicify(buf2, buf1, 4);
00229 x += ht_snprintf(x, 64, "hex %s\n", buf2);
00230 ht_snprintf(buf1, sizeof buf1, "%qu", &r.scalar.integer.value);
00231 nicify(buf2, buf1, 3);
00232 x += ht_snprintf(x, 64, "dec %s\n", buf2);
00233 if (to_sint64(r.scalar.integer.value) < to_sint64(0)) {
00234 ht_snprintf(buf1, sizeof buf1, "%qd", &r.scalar.integer.value);
00235 nicify(buf2, buf1+1, 3);
00236 x += ht_snprintf(x, 64, "sdec -%s\n", buf2);
00237 }
00238 ht_snprintf(buf1, sizeof buf1, "%qo", &r.scalar.integer.value);
00239 nicify(buf2, buf1, 3);
00240 x += ht_snprintf(x, 64, "oct %s\n", buf2);
00241
00242 sprint_base2(buf1, lo, true);
00243 nicify(buf2, buf1, 8);
00244 x += ht_snprintf(x, 64, "binlo %s\n", buf2);
00245 if (hi) {
00246 sprint_base2(buf1, hi, true);
00247 nicify(buf2, buf1, 8);
00248 x += ht_snprintf(x, 64, "binhi %s\n", buf2);
00249 }
00250 char bb[4];
00251 int i = lo;
00252
00253 x += sprintf(x, "%s", "string \"");
00254 create_foreign_int(bb, i, 4, big_endian);
00255 bin2str(x, bb, 4);
00256 x += 4;
00257 x += sprintf(x, "%s", "\" 32bit big-endian (e.g. network)\n");
00258
00259 x += sprintf(x, "string \"");
00260 create_foreign_int(bb, i, 4, little_endian);
00261 bin2str(x, bb, 4);
00262 x += 4;
00263 x += sprintf(x, "%s", "\" 32bit little-endian (e.g. x86)\n");
00264
00265 *x = 0;
00266 break;
00267 }
00268 case SCALAR_STR: {
00269 char *x=b;
00270 x+=sprintf(x, "string:\n");
00271
00272 x+=sprintf(x, "c-escaped \"");
00273 x+=escape_special(x, 0xff, r.scalar.str.value, r.scalar.str.len, NULL, true);
00274 *(x++)='"';
00275 *(x++)='\n';
00276
00277 x+=sprintf(x, "raw '");
00278 int ll = MIN((UINT)r.scalar.str.len, 0xff);
00279 bin2str(x, r.scalar.str.value, ll);
00280 x+=ll;
00281 *(x++)='\'';
00282 *(x++)='\n';
00283 *x=0;
00284 break;
00285 }
00286 case SCALAR_FLOAT: {
00287 char *x=b;
00288 x+=sprintf(b, "val %.20f\nnorm %.20e", r.scalar.floatnum.value, r.scalar.floatnum.value);
00289
00290 float ff = ((float)r.scalar.floatnum.value);
00291 dword f = *(dword*)&ff;
00292 x += sprintf(x, "\n-- IEEE-754, 32 bit --");
00293 x += sprintf(x, "\nhex %08x\nbin ", f);
00294 x += sprint_base2(x, f, true);
00295 x += sprintf(x, "\nsplit %c1.", (f>>31) ? '-' : '+');
00296 x += sprint_base2_0(x, f&((1<<23)-1), 23);
00297 x += sprintf(x, "b * 2^%d", ((f>>23)&255)-127);
00298 break;
00299 }
00300 default:
00301 strcpy(b, "?");
00302 }
00303 scalar_destroy(&r);
00304 } else {
00305 char *str="?";
00306 int pos=0;
00307 get_eval_error(&str, &pos);
00308 s->isetcursor(pos);
00309 sprintf(b, "error at pos %d: %s", pos+1, str);
00310 }
00311
00312 t->settext(b);
00313 }
00314
00315 void eval_dialog()
00316 {
00317 bounds b, c;
00318 app->getbounds(&c);
00319 b.w=70;
00320 b.h=17;
00321 b.x=(c.w-b.w)/2;
00322 b.y=(c.h-b.h)/2;
00323 ht_dialog *d=new ht_dialog();
00324 c=b;
00325 char *hint="type integer, float or string expression to evaluate";
00326
00327 d->init(&b, "evaluate", FS_TITLE | FS_MOVE | FS_RESIZE);
00328
00329 ht_list *ehist=(ht_list*)find_atom(HISTATOM_EVAL_EXPR);
00330
00331
00332 BOUNDS_ASSIGN(b, 1, 1, c.w-14, 1);
00333 ht_strinputfield *s=new ht_strinputfield();
00334 s->init(&b, 255, ehist);
00335 d->insert(s);
00336
00337 ht_button *bhelp = new ht_button();
00338 BOUNDS_ASSIGN(b, c.w-12, 1, 10, 1);
00339 bhelp->init(&b, "~Functions", BUTTON_HELP);
00340 d->insert(bhelp);
00341
00342 BOUNDS_ASSIGN(b, 1, 3, c.w-4, c.h-5);
00343 ht_statictext *t=new ht_statictext();
00344 t->init(&b, hint, align_left);
00345 t->growmode = MK_GM(GMH_LEFT, GMV_FIT);
00346 d->insert(t);
00347
00348 int button;
00349 while ((button = d->run(false)) != button_cancel) {
00350 switch (button) {
00351 case button_ok:
00352 ht_strinputfield_data str;
00353 char b[1024];
00354 s->databuf_get(&str, sizeof str);
00355 if (str.textlen) {
00356 bin2str(b, str.text, str.textlen);
00357 insert_history_entry(ehist, b, 0);
00358 do_eval(s, t, b);
00359 } else {
00360 t->settext(hint);
00361 }
00362 break;
00363 case BUTTON_HELP:
00364 dialog_eval_help(NULL, NULL, NULL);
00365 break;
00366 }
00367 }
00368
00369 d->done();
00370 delete d;
00371 }