00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <ctype.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024
00025 #include "htclipboard.h"
00026 #include "htctrl.h"
00027 #include "htdialog.h"
00028 #include "hthist.h"
00029 #include "htidle.h"
00030 #include "htkeyb.h"
00031 #include "htpal.h"
00032 #include "htstring.h"
00033 #include "tools.h"
00034
00035
00036
00037
00038
00039 void ht_dialog::init(bounds *b, const char *desc, UINT framestyle)
00040 {
00041 ht_window::init(b, desc, framestyle);
00042 VIEW_DEBUG_NAME("ht_dialog");
00043 options&=~VO_SELBOUND;
00044 msgqueue=new ht_queue();
00045 msgqueue->init();
00046 }
00047
00048 void ht_dialog::done()
00049 {
00050 msgqueue->done();
00051 delete msgqueue;
00052 ht_window::done();
00053 }
00054
00055 int ht_dialog::alone()
00056 {
00057 return 1;
00058 }
00059
00060 char *ht_dialog::defaultpalette()
00061 {
00062 return palkey_generic_dialog_default;
00063 }
00064
00065 ht_queued_msg *ht_dialog::dequeuemsg()
00066 {
00067 return (ht_queued_msg*)msgqueue->dequeue();
00068 }
00069
00070 void ht_dialog::draw()
00071 {
00072 clear(getcolor(palidx_generic_body));
00073 ht_group::draw();
00074 }
00075
00076 int ht_dialog::getstate(int *_return_val)
00077 {
00078 if (_return_val) *_return_val=return_val;
00079 return state;
00080 }
00081
00082 void ht_dialog::handlemsg(htmsg *msg)
00083 {
00084 if (msg->msg==msg_button_pressed) {
00085 switch (msg->data1.integer) {
00086 case button_cancel:
00087 setstate(ds_term_cancel, msg->data1.integer);
00088 clearmsg(msg);
00089 return;
00090 default:
00091 setstate(ds_term_ok, msg->data1.integer);
00092 clearmsg(msg);
00093 return;
00094 }
00095 }
00096 ht_window::handlemsg(msg);
00097 if (msg->msg==msg_keypressed) {
00098 switch (msg->data1.integer) {
00099 case K_Escape:
00100 setstate(ds_term_cancel, msg->data1.integer);
00101 clearmsg(msg);
00102 return;
00103 case K_Return:
00104 sendmsg(msg_button_pressed, button_ok);
00105 clearmsg(msg);
00106 return;
00107 case K_Control_O: {
00108
00109 }
00110 }
00111 }
00112 }
00113
00114 int ht_dialog::run(bool modal)
00115 {
00116 ht_view *orig_focused=app->getselected(), *orig_baseview=baseview;
00117 int oldx, oldy;
00118 ht_view *drawer=modal ? this : app;
00119 screen->getcursor(&oldx, &oldy);
00120 setstate(ds_normal, 0);
00121 ((ht_group*)app)->insert(this);
00122 ((ht_group*)app)->focus(this);
00123 baseview=this;
00124 drawer->sendmsg(msg_draw, 0);
00125 screen->show();
00126 while (getstate(0)==ds_normal) {
00127 if (ht_keypressed()) {
00128 ht_key k=ht_getkey();
00129 sendmsg(msg_keypressed, k);
00130 drawer->sendmsg(msg_draw, 0);
00131 screen->show();
00132 }
00133 ht_queued_msg *q;
00134 while ((q=dequeuemsg())) {
00135 htmsg m=q->msg;
00136 q->target->sendmsg(&m);
00137 sendmsg(msg_draw);
00138 delete q;
00139 }
00140 if (!modal) do_idle();
00141 }
00142 int return_val;
00143 int state=getstate(&return_val);
00144 screen->setcursor(oldx, oldy);
00145 ((ht_group*)app)->remove(this);
00146 app->focus(orig_focused);
00147 baseview=orig_baseview;
00148 if (state!=ds_term_cancel) {
00149 return return_val;
00150 } else {
00151 return 0;
00152 }
00153 }
00154
00155 void ht_dialog::queuemsg(ht_view *target, htmsg *msg)
00156 {
00157 ht_queued_msg *q=new ht_queued_msg();
00158 q->target=target;
00159 q->msg=*msg;
00160 msgqueue->enqueue(q);
00161 }
00162
00163 void ht_dialog::setstate(int st, int retval)
00164 {
00165 state = st;
00166 return_val = retval;
00167 }
00168
00169
00170
00171
00172
00173 void ht_cluster::init(bounds *b, ht_string_list *_strings)
00174 {
00175 ht_view::init(b, VO_SELECTABLE | VO_OWNBUFFER | VO_POSTPROCESS, 0);
00176 VIEW_DEBUG_NAME("ht_cluster");
00177 strings=_strings;
00178 scount=strings->count();
00179 if (scount>32) scount=32;
00180 sel=0;
00181 for (int i=0; i<scount; i++) {
00182 char *s=strings->get_string(i);
00183 s=strchr(s, '~');
00184 if (s) {
00185 shortcuts[i]=ht_metakey((ht_key)*(s+1));
00186 } else shortcuts[i]=K_INVALID;
00187 }
00188 }
00189
00190 void ht_cluster::done()
00191 {
00192 strings->destroy();
00193 delete strings;
00194 ht_view::done();
00195 }
00196
00197 char *ht_cluster::defaultpalette()
00198 {
00199 return palkey_generic_dialog_default;
00200 }
00201
00202
00203
00204
00205
00206 void ht_checkboxes::init(bounds *b, ht_string_list *strings)
00207 {
00208 ht_cluster::init(b, strings);
00209 VIEW_DEBUG_NAME("ht_checkboxes");
00210 state=0;
00211 }
00212
00213 void ht_checkboxes::done()
00214 {
00215 ht_cluster::done();
00216 }
00217
00218 int ht_checkboxes::datasize()
00219 {
00220 return sizeof (ht_checkboxes_data);
00221 }
00222
00223 void ht_checkboxes::draw()
00224 {
00225 clear(getcolor(focused ? palidx_generic_cluster_focused
00226 : palidx_generic_cluster_unfocused));
00227 int i=0;
00228 int vx=0, vy=0;
00229 int maxcolstrlen=0;
00230 while (i<scount) {
00231 int c=getcolor(palidx_generic_cluster_unfocused);
00232 if ((focused) && (sel==i)) c=getcolor(palidx_generic_cluster_focused);
00233 char *s=strings->get_string(i);
00234 int slen=strlen(s);
00235 if (slen>maxcolstrlen) maxcolstrlen=slen;
00236 if ((1<<i) & state) {
00237 buf_print(vx, vy, c, "[X]");
00238 } else {
00239 buf_print(vx, vy, c, "[ ]");
00240 }
00241 int k=0, oc=c;
00242 for (int q=0; q<size.w-4; q++) {
00243 if (!*(s+q)) break;
00244 if (*(s+q)=='~') {
00245 c=getcolor(palidx_generic_cluster_shortcut);
00246 continue;
00247 } else {
00248 buf_printchar(vx+k+4, vy, c, *(s+q));
00249 k++;
00250 }
00251 c=oc;
00252 }
00253 i++;
00254 vy++;
00255 if (vy>=size.h) {
00256 vx+=maxcolstrlen+5;
00257 vy=0;
00258 maxcolstrlen=0;
00259 }
00260 }
00261 }
00262
00263 void ht_checkboxes::getdata(ht_object_stream *s)
00264 {
00265 s->putIntDec(state, 4, NULL);
00266 }
00267
00268 void ht_checkboxes::handlemsg(htmsg *msg)
00269 {
00270 if (msg->type==mt_postprocess) {
00271 if (msg->msg==msg_keypressed) {
00272 for (int i=0; i<scount; i++) {
00273 if ((shortcuts[i]!=-1) && (msg->data1.integer==shortcuts[i])) {
00274 sel=i;
00275 state=state^(1<<sel);
00276 app->focus(this);
00277 dirtyview();
00278 clearmsg(msg);
00279 return;
00280 }
00281 }
00282 }
00283 } else {
00284 if (msg->msg==msg_keypressed) {
00285 switch (msg->data1.integer) {
00286 case K_Left:
00287 sel-=size.h;
00288 if (sel<0) sel=0;
00289 dirtyview();
00290 clearmsg(msg);
00291 return;
00292 case K_Right:
00293 sel+=size.h;
00294 if (sel>=scount) sel=scount-1;
00295 dirtyview();
00296 clearmsg(msg);
00297 return;
00298 case K_Up:
00299 sel--;
00300 if (sel<0) sel=0;
00301 dirtyview();
00302 clearmsg(msg);
00303 return;
00304 case K_Down:
00305 sel++;
00306 if (sel>=scount) sel=scount-1;
00307 dirtyview();
00308 clearmsg(msg);
00309 return;
00310 case K_Space:
00311 state=state^(1<<sel);
00312 dirtyview();
00313 clearmsg(msg);
00314 return;
00315 }
00316 }
00317 }
00318 ht_cluster::handlemsg(msg);
00319 }
00320
00321 void ht_checkboxes::setdata(ht_object_stream *s)
00322 {
00323 state=s->getIntDec(4, NULL);
00324 dirtyview();
00325 }
00326
00327
00328
00329
00330
00331 void ht_radioboxes::init(bounds *b, ht_string_list *strings)
00332 {
00333 ht_cluster::init(b, strings);
00334 VIEW_DEBUG_NAME("ht_radioboxes");
00335 }
00336
00337 void ht_radioboxes::done()
00338 {
00339 ht_cluster::done();
00340 }
00341
00342 int ht_radioboxes::datasize()
00343 {
00344 return sizeof (ht_radioboxes_data);
00345 }
00346
00347 void ht_radioboxes::draw()
00348 {
00349 clear(getcolor(focused ? palidx_generic_cluster_focused
00350 : palidx_generic_cluster_unfocused));
00351 int i=0;
00352 int vx=0, vy=0;
00353 int maxcolstrlen=0;
00354 while (i<scount) {
00355 int c=getcolor(palidx_generic_cluster_unfocused);
00356 if ((focused) && (sel==i)) c=getcolor(palidx_generic_cluster_focused);
00357 char *s=strings->get_string(i);
00358 int slen=strlen(s);
00359 if (slen>maxcolstrlen) maxcolstrlen=slen;
00360 buf_print(vx, vy, c, "( )");
00361 if (i==sel) {
00362 buf_printchar(vx+1, vy, c, CHAR_RADIO);
00363 }
00364 buf_print(vx+4, vy, c, s);
00365 i++;
00366 vy++;
00367 if (vy>=size.h) {
00368 vx+=maxcolstrlen+5;
00369 vy=0;
00370 maxcolstrlen=0;
00371 }
00372 }
00373 }
00374
00375 void ht_radioboxes::getdata(ht_object_stream *s)
00376 {
00377 s->putIntDec(sel, 4, NULL);
00378 }
00379
00380 void ht_radioboxes::handlemsg(htmsg *msg)
00381 {
00382 if (msg->msg==msg_keypressed) {
00383 switch (msg->data1.integer) {
00384 case K_Left:
00385 sel-=size.h;
00386 if (sel<0) sel=0;
00387 dirtyview();
00388 clearmsg(msg);
00389 return;
00390 case K_Right:
00391 sel+=size.h;
00392 if (sel>=scount) sel=scount-1;
00393 dirtyview();
00394 clearmsg(msg);
00395 return;
00396 case K_Up:
00397 sel--;
00398 if (sel<0) sel=0;
00399 dirtyview();
00400 clearmsg(msg);
00401 return;
00402 case K_Down:
00403 sel++;
00404 if (sel>=scount) sel=scount-1;
00405 dirtyview();
00406 clearmsg(msg);
00407 return;
00408
00409
00410
00411
00412
00413 }
00414 }
00415 ht_cluster::handlemsg(msg);
00416 }
00417
00418 void ht_radioboxes::setdata(ht_object_stream *s)
00419 {
00420 sel=s->getIntDec(4, NULL);
00421 }
00422
00423
00424
00425
00426
00427 void ht_history_listbox::init(bounds *b, ht_list *hist)
00428 {
00429 history = hist;
00430 ht_listbox::init(b);
00431 }
00432
00433 int ht_history_listbox::calcCount()
00434 {
00435 return history->count();
00436 }
00437
00438 void *ht_history_listbox::getFirst()
00439 {
00440 if (history->count()) {
00441 return (void*)1;
00442 } else {
00443 return NULL;
00444 }
00445 }
00446
00447 void *ht_history_listbox::getLast()
00448 {
00449 if (history->count()) {
00450 return (void*)(history->count());
00451 } else {
00452 return NULL;
00453 }
00454 }
00455
00456 void *ht_history_listbox::getNext(void *entry)
00457 {
00458 UINT e=(UINT)entry;
00459 if (!e) return NULL;
00460 if (e < history->count()) {
00461 return (void*)(e+1);
00462 } else {
00463 return NULL;
00464 }
00465 }
00466
00467 void *ht_history_listbox::getPrev(void *entry)
00468 {
00469 UINT e=(UINT)entry;
00470 if (e > 1) {
00471 return (void*)(e-1);
00472 } else {
00473 return NULL;
00474 }
00475 }
00476
00477 char *ht_history_listbox::getStr(int col, void *entry)
00478 {
00479 return ((ht_history_entry*)history->get((int)entry-1))->desc;
00480 }
00481
00482 void ht_history_listbox::handlemsg(htmsg *msg)
00483 {
00484 switch (msg->msg) {
00485 case msg_keypressed:
00486 switch (msg->data1.integer) {
00487 case K_Delete: {
00488 int p = pos;
00489 cursorUp(1);
00490 history->del(p);
00491 update();
00492 if (p) cursorDown(1);
00493 dirtyview();
00494 clearmsg(msg);
00495 break;
00496 }
00497 }
00498 break;
00499 }
00500 ht_listbox::handlemsg(msg);
00501 }
00502
00503 void *ht_history_listbox::quickfind(char *s)
00504 {
00505 void *item = getFirst();
00506 int slen = strlen(s);
00507 while (item && (ht_strncmp(getStr(0, item), s, slen)!=0)) {
00508 item = getNext(item);
00509 }
00510 return item;
00511 }
00512
00513 char *ht_history_listbox::quickfindCompletition(char *s)
00514 {
00515 void *item = getFirst();
00516 char *res = NULL;
00517 int slen = strlen(s);
00518 while (item) {
00519 if (ht_strncmp(getStr(0, item), s, slen)==0) {
00520 if (!res) {
00521 res = ht_strdup(getStr(0, item));
00522 } else {
00523 int a = strccomm(res, getStr(0, item));
00524 res[a] = 0;
00525 }
00526 }
00527 item = getNext(item);
00528 }
00529 return res;
00530 }
00531
00532
00533
00534
00535
00536
00537 void ht_history_popup_dialog::init(bounds *b, ht_list *hist)
00538 {
00539 history = hist;
00540 ht_listpopup_dialog::init(b, "history");
00541 }
00542
00543 void ht_history_popup_dialog::getdata(ht_object_stream *s)
00544 {
00545
00546 s->putIntDec(listbox->pos, 4, NULL);
00547 if (history->count()) {
00548 s->putString(((ht_history_entry*)history->get(listbox->pos))->desc, NULL);
00549 } else {
00550 s->putString(NULL, NULL);
00551 }
00552 }
00553
00554 void ht_history_popup_dialog::init_text_listbox(bounds *b)
00555 {
00556 listbox=new ht_history_listbox();
00557 ((ht_history_listbox *)listbox)->init(b, history);
00558 insert(listbox);
00559 }
00560
00561 void ht_history_popup_dialog::setdata(ht_object_stream *s)
00562 {
00563 }
00564
00565
00566
00567
00568
00569 void ht_inputfield::init(bounds *b, int Maxtextlen, ht_list *hist)
00570 {
00571 ht_view::init(b, VO_SELECTABLE, "some inputfield");
00572 VIEW_DEBUG_NAME("ht_inputfield");
00573
00574 history=hist;
00575 maxtextlenv=Maxtextlen;
00576
00577 textv=(byte*)malloc(maxtextlenv+1);
00578 curcharv=textv;
00579 textlenv=0;
00580 selstartv=0;
00581 selendv=0;
00582
00583 text=&textv;
00584 curchar=&curcharv;
00585 textlen=&textlenv;
00586 maxtextlen=&maxtextlenv;
00587 selstart=&selstartv;
00588 selend=&selendv;
00589
00590 insert=1;
00591 ofs=0;
00592 attachedto=0;
00593 }
00594
00595 void ht_inputfield::done()
00596 {
00597 freebuf();
00598 ht_view::done();
00599 }
00600
00601 void ht_inputfield::attach(ht_inputfield *inputfield)
00602 {
00603 freebuf();
00604 inputfield->query(&curchar, &text, &selstart, &selend, &textlen, &maxtextlen);
00605 attachedto=inputfield;
00606 ofs=0;
00607 insert=1;
00608 }
00609
00610 int ht_inputfield::datasize()
00611 {
00612 return sizeof (ht_inputfield_data);
00613 }
00614
00615 char *ht_inputfield::defaultpalette()
00616 {
00617 return palkey_generic_dialog_default;
00618 }
00619
00620 void ht_inputfield::freebuf()
00621 {
00622 if (!attachedto && (text) && (*text)) free(*text);
00623 }
00624
00625 void ht_inputfield::getdata(ht_object_stream *s)
00626 {
00627 UINT h=s->recordStart(datasize());
00628 if (!attachedto) {
00629 s->putIntDec(*textlen, 4, NULL);
00630 s->putBinary(*text, *textlen, NULL);
00631 }
00632 s->recordEnd(h);
00633 }
00634
00635 int ht_inputfield::insertbyte(byte *pos, byte b)
00636 {
00637 if (*textlen<*maxtextlen) {
00638 if (*selstart) {
00639 if (pos<*selstart) {
00640 (*selstart)++;
00641 (*selend)++;
00642 } else if (pos<*selend) {
00643 (*selend)++;
00644 }
00645 }
00646 memmove(pos+1, pos, *textlen-(pos-*text));
00647 *pos=b;
00648 (*textlen)++;
00649 dirtyview();
00650 return 1;
00651 }
00652 return 0;
00653 }
00654
00655 void ht_inputfield::isetcursor(UINT pos)
00656 {
00657 if (pos<(UINT)*textlen) *curchar=*text+pos;
00658 }
00659
00660 void ht_inputfield::query(byte ***c, byte ***t, byte ***ss, byte ***se, int **tl, int **mtl)
00661 {
00662 *c=curchar;
00663 *t=text;
00664 *ss=selstart;
00665 *se=selend;
00666 *tl=textlen;
00667 *mtl=maxtextlen;
00668 }
00669
00670 void ht_inputfield::select_add(byte *start, byte *end)
00671 {
00672 if (end<start) {
00673 byte *temp=start;
00674 start=end;
00675 end=temp;
00676 }
00677 if (end==*selstart) {
00678 *selstart=start;
00679 } else if (start==*selend) {
00680 *selend=end;
00681 } else if (start==*selstart) {
00682 *selstart=end;
00683 } else if (end==*selend) {
00684 *selend=start;
00685 } else {
00686 *selstart=start;
00687 *selend=end;
00688 }
00689 if (*selstart>*selend) {
00690 byte *temp=*selstart;
00691 *selstart=*selend;
00692 *selend=temp;
00693 }
00694 }
00695
00696 void ht_inputfield::setdata(ht_object_stream *s)
00697 {
00698 UINT h=s->recordStart(datasize());
00699 if (!attachedto) {
00700 textlen=&textlenv;
00701 *textlen=s->getIntDec(4, NULL);
00702
00703 if (*textlen>*maxtextlen) *textlen=*maxtextlen;
00704
00705 s->getBinary(*text, *textlen, NULL);
00706
00707 curchar=&curcharv;
00708 *curchar=*text+*textlen;
00709
00710 if (*textlen) {
00711 *selstart=*text;
00712 *selend=*text+*textlen;
00713 } else {
00714 *selstart=0;
00715 *selend=0;
00716 }
00717
00718 ofs=0;
00719 }
00720
00721 s->recordEnd(h);
00722 dirtyview();
00723 }
00724
00725
00726
00727
00728
00729 void ht_strinputfield::init(bounds *b, int maxstrlen, ht_list *history)
00730 {
00731 ht_inputfield::init(b, maxstrlen, history);
00732 VIEW_DEBUG_NAME("ht_strinputfield");
00733 is_virgin = true;
00734 selectmode = false;
00735 }
00736
00737 void ht_strinputfield::done()
00738 {
00739 ht_inputfield::done();
00740 }
00741
00742 void ht_strinputfield::correct_viewpoint()
00743 {
00744 if (*curchar-*text<ofs) ofs=*curchar-*text; else
00745 if (*curchar-*text-(size.w-2)*size.h+1>ofs) ofs=*curchar-*text-(size.w-2)*size.h+1;
00746 }
00747
00748 void ht_strinputfield::draw()
00749 {
00750 int c=focused ? getcolor(palidx_generic_input_focused) :
00751 getcolor(palidx_generic_input_unfocused);
00752 byte *t=*text+ofs;
00753 int l=*textlen-ofs;
00754 if (l>size.w) l=size.w;
00755 int y=0;
00756 fill(0, 0, size.w, size.h, c, ' ');
00757 if (ofs) buf_printchar(0, y, getcolor(palidx_generic_input_clip), '<');
00758 for (int k=0; k<*textlen-ofs; k++) {
00759 if (1+k-y*(size.w-2)>size.w-2) {
00760 if (y+1<size.h) y++; else break;
00761 }
00762 if ((t<*selstart) || (t>=*selend)) {
00763 buf_printchar(1+k-y*(size.w-2), y, c, *(t++));
00764 } else {
00765 buf_printchar(1+k-y*(size.w-2), y, getcolor(palidx_generic_input_selected), *(t++));
00766 }
00767 }
00768 if (*textlen-ofs > (size.w-2)*size.h) {
00769 buf_printchar(size.w-1, y, getcolor(palidx_generic_input_clip), '>');
00770 }
00771 if (history && history->count()) {
00772 buf_printchar(size.w-1, y+size.h-1, getcolor(palidx_generic_input_clip), CHAR_ARROW_DOWN);
00773 }
00774 if (focused) {
00775 int cx, cy;
00776 if (*curchar-*text-ofs>=(size.w-2)*size.h) {
00777 cx = size.w-1;
00778 cy = size.h-1;
00779 } else {
00780 cx = (*curchar-*text-ofs)%(size.w-2)+1;
00781 cy = (*curchar-*text-ofs)/(size.w-2);
00782 }
00783 setcursor(cx, cy, insert ? cm_normal : cm_overwrite);
00784 }
00785 }
00786
00787 void ht_strinputfield::handlemsg(htmsg *msg)
00788 {
00789 if ((msg->type==mt_empty) && (msg->msg==msg_keypressed)) {
00790 int k = msg->data1.integer;
00791 switch (k) {
00792 case K_Alt_S:
00793 selectmode=!selectmode;
00794 clearmsg(msg);
00795 break;
00796 case K_Up:
00797 is_virgin=0;
00798 if (*curchar-*text-ofs<size.w-2) {
00799 ofs-=size.w-2;
00800 if (ofs<0) ofs=0;
00801 }
00802 *curchar-=size.w-2;
00803 if (*curchar<*text) *curchar=*text;
00804 correct_viewpoint();
00805 dirtyview();
00806 clearmsg(msg);
00807 return;
00808 case K_Down:
00809 is_virgin=0;
00810 if (*curchar+size.w-2-*text>*textlen) {
00811 history_dialog();
00812 clearmsg(msg);
00813 return;
00814 } else {
00815 *curchar+=size.w-2;
00816 if (*curchar-*text>*textlen) *curchar=*text+*textlen;
00817 correct_viewpoint();
00818 dirtyview();
00819 }
00820 clearmsg(msg);
00821 return;
00822 case K_Shift_Left:
00823 case K_Left:
00824 is_virgin=0;
00825 if (*curchar>*text) {
00826 (*curchar)--;
00827 if ((k==K_Shift_Left) != selectmode) {
00828 select_add(*curchar, *curchar+1);
00829 }
00830 }
00831 correct_viewpoint();
00832 dirtyview();
00833 clearmsg(msg);
00834 return;
00835 case K_Shift_Right:
00836 case K_Right:
00837 is_virgin=0;
00838 if (*curchar-*text<*textlen) {
00839 (*curchar)++;
00840 if ((k==K_Shift_Right) != selectmode) {
00841 select_add(*curchar-1, *curchar);
00842 }
00843 }
00844 correct_viewpoint();
00845 dirtyview();
00846 clearmsg(msg);
00847 return;
00848 case K_Backspace:
00849 if (is_virgin) {
00850 is_virgin=0;
00851 *selstart=0;
00852 *selend=0;
00853 *textlen=0;
00854 *curchar=*text;
00855 dirtyview();
00856 clearmsg(msg);
00857 } else if (*curchar>*text) {
00858 *selstart=0;
00859 *selend=0;
00860 memmove(*curchar-1, *curchar, *textlen-(*curchar-*text));
00861 (*textlen)--;
00862 (*curchar)--;
00863 is_virgin=0;
00864 correct_viewpoint();
00865 dirtyview();
00866 clearmsg(msg);
00867 return;
00868 }
00869 break;
00870 case K_Delete:
00871 if (is_virgin) {
00872 is_virgin=0;
00873 *selstart=0;
00874 *selend=0;
00875 *textlen=0;
00876 *curchar=*text;
00877 dirtyview();
00878 clearmsg(msg);
00879 } else if ((*curchar-*text<*textlen) && (*textlen)) {
00880 if (*selstart) {
00881 if (*curchar>=*selstart) {
00882 if (*curchar<*selend) (*selend)--;
00883 if (*selstart==*selend) {
00884 *selstart=0;
00885 *selend=0;
00886 }
00887 } else {
00888 (*selstart)--;
00889 (*selend)--;
00890 }
00891 }
00892 memmove(*curchar, *curchar+1, *textlen-(*curchar-*text)-1);
00893 (*textlen)--;
00894 dirtyview();
00895 clearmsg(msg);
00896 return;
00897 }
00898 break;
00899 case K_Shift_Home:
00900 case K_Home:
00901 is_virgin=0;
00902 if ((k==K_Shift_Home) != selectmode) {
00903 select_add(*curchar, *text);
00904 }
00905 *curchar=*text;
00906 correct_viewpoint();
00907 dirtyview();
00908 clearmsg(msg);
00909 return;
00910 case K_Shift_End:
00911 case K_End:
00912 is_virgin=0;
00913 if ((k==K_Shift_End) != selectmode) {
00914 select_add(*curchar, *text+*textlen);
00915 }
00916 *curchar=*text+*textlen;
00917 correct_viewpoint();
00918 dirtyview();
00919 clearmsg(msg);
00920 return;
00921 case K_Insert:
00922 insert=!insert;
00923 dirtyview();
00924 clearmsg(msg);
00925 return;
00926 case K_Alt_X:
00927 case K_Shift_Delete:
00928 if (*selend>*selstart) clipboard_copy("inputfield", *selstart, *selend-*selstart);
00929 case K_Alt_D:
00930 case K_Control_Delete:
00931 if (*selend>*selstart) {
00932 memmove(*selstart, *selend, *textlen-(*selend-*text));
00933 *textlen-=*selend-*selstart;
00934 *curchar=*selstart;
00935 *selstart=0;
00936 *selend=0;
00937 is_virgin=0;
00938 correct_viewpoint();
00939 }
00940 dirtyview();
00941 clearmsg(msg);
00942 return;
00943 case K_Alt_C:
00944 case K_Control_Insert:
00945 if (*selend>*selstart) clipboard_copy("inputfield", *selstart, *selend-*selstart);
00946 is_virgin=0;
00947 dirtyview();
00948 clearmsg(msg);
00949 return;
00950 case K_Alt_V:
00951 case K_Shift_Insert: {
00952 int maxsize=MIN(*maxtextlen-*textlen, (int)clipboard_getsize());
00953 byte *buf=(byte*)malloc(maxsize);
00954 int r=clipboard_paste(buf, maxsize);
00955 if (r) {
00956 for (int i=0; i<r; i++) {
00957 setbyte(buf[r-i-1]);
00958 }
00959 *selstart=*curchar;
00960 *selend=*curchar+r;
00961 }
00962 delete buf;
00963 is_virgin=0;
00964 dirtyview();
00965 clearmsg(msg);
00966 return;
00967 }
00968 default:
00969 if ((msg->data1.integer>=' ') && (msg->data1.integer<256)) {
00970 if (is_virgin) {
00971 is_virgin=0;
00972 *selstart=0;
00973 *selend=0;
00974 *textlen=0;
00975 *curchar=*text;
00976 ofs=0;
00977 }
00978 inputbyte(msg->data1.integer);
00979 dirtyview();
00980 clearmsg(msg);
00981 return;
00982 }
00983 }
00984 }
00985 ht_inputfield::handlemsg(msg);
00986 }
00987
00988 void ht_strinputfield::history_dialog()
00989 {
00990 if (history && history->count()) {
00991 bounds b;
00992 getbounds(&b);
00993 b.y--;
00994 b.h=8;
00995 ht_history_popup_dialog *l=new ht_history_popup_dialog();
00996 l->init(&b, history);
00997 if (l->run(false)) {
00998 ht_listpopup_dialog_data d;
00999 l->databuf_get(&d, sizeof d);
01000
01001 if (d.cursor_string) {
01002 ht_history_entry *v=(ht_history_entry*)history->get(d.cursor_pos);
01003 if ((v->data) && (group)) {
01004 v->datafile->seek(0);
01005 group->setdata(v->data);
01006 } else {
01007 ht_inputfield_data e;
01008 e.textlen=strlen(d.cursor_string);
01009 e.text=(byte*)d.cursor_string;
01010 databuf_set(&e, sizeof e);
01011 }
01012 }
01013 is_virgin=0;
01014 }
01015 l->done();
01016 delete l;
01017 }
01018 }
01019
01020 void ht_strinputfield::receivefocus()
01021 {
01022 correct_viewpoint();
01023 ht_inputfield::receivefocus();
01024 }
01025
01026 bool ht_strinputfield::inputbyte(byte a)
01027 {
01028 if (setbyte(a)) {
01029 (*curchar)++;
01030 correct_viewpoint();
01031 is_virgin=0;
01032 return true;
01033 }
01034 return false;
01035 }
01036
01037 bool ht_strinputfield::setbyte(byte a)
01038 {
01039 if ((insert) || (*curchar-*text>=*textlen)) {
01040 if ((insertbyte(*curchar, a)) && (*curchar-*text<*textlen)) return true;
01041 } else {
01042 **curchar=a;
01043 return true;
01044 }
01045 return false;
01046 }
01047
01048
01049
01050
01051
01052 void ht_hexinputfield::init(bounds *b, int maxstrlen)
01053 {
01054 ht_inputfield::init(b, maxstrlen);
01055 VIEW_DEBUG_NAME("ht_strinputfield");
01056 nib=0;
01057 insert=1;
01058 }
01059
01060 void ht_hexinputfield::done()
01061 {
01062 ht_inputfield::done();
01063 }
01064
01065 void ht_hexinputfield::correct_viewpoint()
01066 {
01067 if (*curchar-*text<ofs) ofs=*curchar-*text; else
01068 if ((*curchar-*text)*3-(size.w-2)*size.h+5>ofs*3) ofs=((*curchar-*text)*3-(size.w-2)*size.h+5)/3;
01069 }
01070
01071 void ht_hexinputfield::draw()
01072 {
01073 int c=focused ? getcolor(palidx_generic_input_focused) :
01074 getcolor(palidx_generic_input_unfocused);
01075 char hbuf[256], *h=hbuf;
01076 int y=0;
01077 fill(0, 0, size.w, size.h, c, ' ');
01078 if (ofs) buf_print(0, y, getcolor(palidx_generic_input_clip), "<");
01079 int vv=*textlen-ofs;
01080 if (vv<0) vv=0; else if (vv>(size.w-2)*size.h/3) vv=(size.w-2)*size.h/3+1;
01081 for (int k=0; k<vv; k++) {
01082 h+=sprintf(h, "%02x ", *(*text+k+ofs));
01083 }
01084 if (vv) {
01085 h=hbuf;
01086 while ((*h) && (y<size.h)) {
01087 h+=buf_lprint(1, y, c, size.w-2, h);
01088 y++;
01089 }
01090 y--;
01091 }
01092 if ((*textlen-ofs)*3 > (size.w-2)*size.h) {
01093 buf_print(size.w-1, y, getcolor(palidx_generic_input_clip), ">");
01094 }
01095 if (focused) {
01096 int cx, cy;
01097 if ((*curchar-*text-ofs)*3+nib+1>=(size.w-2)*size.h) {
01098 cx = size.w-1;
01099 cy = size.h-1;
01100 } else {
01101 cx = ((*curchar-*text-ofs)*3+nib+1)%(size.w-2);
01102 cy = ((*curchar-*text-ofs)*3+nib+1)/(size.w-2);
01103 }
01104 setcursor(cx, cy, insert ? cm_normal : cm_overwrite);
01105 }
01106 }
01107
01108 void ht_hexinputfield::handlemsg(htmsg *msg)
01109 {
01110 if (msg->msg==msg_keypressed) {
01111 switch (msg->data1.integer) {
01112 case K_Up:
01113 if (*curchar-*text-ofs<(size.w-2)/3) {
01114 ofs-=(size.w-2)/3;
01115 if (ofs<0) ofs=0;
01116 }
01117 *curchar-=(size.w-2)/3;
01118 if (*curchar<*text) *curchar=*text;
01119 correct_viewpoint();
01120 dirtyview();
01121 clearmsg(msg);
01122 return;
01123 case K_Down:
01124
01125
01126
01127 *curchar+=(size.w-2)/3;
01128 if (*curchar-*text>*textlen) *curchar=*text+*textlen;
01129 if (*curchar-*text>=*textlen) nib=0;
01130 correct_viewpoint();
01131 dirtyview();
01132 clearmsg(msg);
01133 return;
01134 case K_Left:
01135 if (nib) {
01136 nib=0;
01137 } else if (*curchar>*text) {
01138 (*curchar)--;
01139 nib=1;
01140 }
01141 correct_viewpoint();
01142 dirtyview();
01143 clearmsg(msg);
01144 return;
01145 case K_Right:
01146 if (!nib) {
01147 if (*curchar-*text<*textlen) nib=1;
01148 } else if (*curchar-*text<*textlen) {
01149 (*curchar)++;
01150 nib=0;
01151 }
01152 correct_viewpoint();
01153 dirtyview();
01154 clearmsg(msg);
01155 return;
01156 case K_Backspace:
01157 if (*textlen) {
01158 if (*curchar+nib>*text) {
01159
01160
01161
01162
01163 memmove(*curchar-1+nib, *curchar+nib, *textlen-(*curchar-*text));
01164 (*textlen)--;
01165 if (*curchar-*text && !nib) (*curchar)--;
01166 nib=0;
01167 correct_viewpoint();
01168 dirtyview();
01169 }
01170 clearmsg(msg);
01171 return;
01172 }
01173 break;
01174 case K_Delete:
01175 if ((*curchar-*text<*textlen) && (*textlen)) {
01176 memmove(*curchar, *curchar+1, *textlen-(*curchar-*text)-1);
01177 (*textlen)--;
01178 nib=0;
01179 dirtyview();
01180 clearmsg(msg);
01181 return;
01182 }
01183 break;
01184 case K_Home:
01185 *curchar=*text;
01186 nib=0;
01187 correct_viewpoint();
01188 dirtyview();
01189 clearmsg(msg);
01190 return;
01191 case K_End:
01192 *curchar=*text+*textlen;
01193 nib=0;
01194 correct_viewpoint();
01195 dirtyview();
01196 clearmsg(msg);
01197 return;
01198 case K_Insert:
01199 insert=!insert;
01200 dirtyview();
01201 clearmsg(msg);
01202 return;
01203 default:
01204 if ((msg->data1.integer>='0') && (msg->data1.integer<='9')) {
01205 setnibble(msg->data1.integer-'0');
01206 dirtyview();
01207 clearmsg(msg);
01208 } else if ((msg->data1.integer>='a') && (msg->data1.integer<='f')) {
01209 setnibble(msg->data1.integer-'a'+10);
01210 dirtyview();
01211 clearmsg(msg);
01212 }
01213 return;
01214 }
01215 }
01216 ht_inputfield::handlemsg(msg);
01217 }
01218
01219 void ht_hexinputfield::receivefocus()
01220 {
01221 correct_viewpoint();
01222 if ((nib) && (*curchar-*text==*textlen)) {
01223 nib=0;
01224 }
01225 ht_inputfield::receivefocus();
01226 }
01227
01228 void ht_hexinputfield::setnibble(byte a)
01229 {
01230 if (((insert) || (*curchar-*text>=*textlen)) && (nib==0)) {
01231 if ((insertbyte(*curchar, a<<4)) && (*curchar-*text<*textlen)) nib=1;
01232 } else {
01233 if (nib) {
01234 **curchar=(**curchar & 0xf0) | a;
01235 (*curchar)++;
01236 nib=0;
01237 } else {
01238 **curchar=(**curchar & 0xf) | (a<<4);
01239 nib=1;
01240 }
01241 }
01242 correct_viewpoint();
01243 }
01244
01245
01246
01247
01248
01249 void ht_button::init(bounds *b, const char *Text, int Value)
01250 {
01251 ht_view::init(b, VO_SELECTABLE | VO_OWNBUFFER | VO_POSTPROCESS, "some button");
01252 VIEW_DEBUG_NAME("ht_button");
01253 value=Value;
01254 text=ht_strdup(Text);
01255 pressed=0;
01256 magicchar=strchr(text, '~');
01257 if (magicchar) {
01258 int l=strlen(text);
01259 memmove(magicchar, magicchar+1, l-(magicchar-text));
01260 shortcut1=ht_metakey((ht_key)tolower(*magicchar));
01261 shortcut2=(ht_key)tolower(*magicchar);
01262 } else {
01263 shortcut1=K_INVALID;
01264 shortcut2=K_INVALID;
01265 }
01266 }
01267
01268 void ht_button::done()
01269 {
01270 if (text) free(text);
01271 ht_view::done();
01272 }
01273
01274 char *ht_button::defaultpalette()
01275 {
01276 return palkey_generic_dialog_default;
01277 }
01278
01279 void ht_button::draw()
01280 {
01281 int c=focused ? getcolor(palidx_generic_button_focused) :
01282 getcolor(palidx_generic_button_unfocused);
01283 fill(0, 0, size.w-1, size.h-1, c, ' ');
01284 int xp=(size.w-strlen(text))/2, yp=(size.h-1)/2;
01285 buf_print(xp, yp, c, text);
01286 if (magicchar) buf_printchar(xp+(magicchar-text), yp, getcolor(palidx_generic_button_shortcut), *magicchar);
01287
01288 buf_printchar(0, 1, getcolor(palidx_generic_button_shadow), ' ');
01289 for (int i=1; i<size.w-1; i++) {
01290 buf_printchar(i, 1, getcolor(palidx_generic_button_shadow), CHAR_FILLED_HU);
01291 }
01292 buf_printchar(size.w-1, 0, getcolor(palidx_generic_button_shadow), CHAR_FILLED_HL);
01293 buf_printchar(size.w-1, 1, getcolor(palidx_generic_button_shadow), CHAR_FILLED_HU);
01294 }
01295
01296 void ht_button::handlemsg(htmsg *msg)
01297 {
01298 if (msg->type==mt_postprocess) {
01299 if (msg->msg==msg_keypressed) {
01300 if (((shortcut1!=K_INVALID) && (msg->data1.integer==shortcut1)) ||
01301 ((shortcut2!=K_INVALID) && (msg->data1.integer==shortcut2))) {
01302 push();
01303 dirtyview();
01304 clearmsg(msg);
01305 return;
01306 }
01307 }
01308 } else if (msg->type==mt_empty) {
01309 if (msg->msg==msg_keypressed) {
01310 switch (msg->data1.integer) {
01311 case K_Return:
01312 case K_Space:
01313 push();
01314 dirtyview();
01315 clearmsg(msg);
01316 return;
01317 }
01318 }
01319 }
01320 ht_view::handlemsg(msg);
01321 }
01322
01323 void ht_button::push()
01324 {
01325
01326
01327 app->sendmsg(msg_button_pressed, value);
01328
01329 pressed=1;
01330 }
01331
01332
01333
01334
01335 void ht_listbox_title::init(bounds *b)
01336 {
01337 ht_view::init(b, VO_RESIZE, "ht_listbox_title");
01338 growmode = MK_GM(GMH_FIT, GMV_FIT);
01339 texts = NULL;
01340 listbox = NULL;
01341 cols = 0;
01342 }
01343
01344 void ht_listbox_title::done()
01345 {
01346 if (texts) {
01347 for (int i=0; i<cols; i++) {
01348 free(texts[i]);
01349 }
01350 free(texts);
01351 }
01352 ht_view::done();
01353 }
01354
01355 char *ht_listbox_title::defaultpalette()
01356 {
01357 return palkey_generic_dialog_default;
01358 }
01359
01360 void ht_listbox_title::draw()
01361 {
01362 vcp color = getTextColor();
01363 clear(color);
01364 if (!texts || !listbox) return;
01365 int x = listbox->x;
01366 x = 0;
01367 for (int i=0; i<cols; i++) {
01368 buf_lprint(x, 0, color, size.w, texts[i]);
01369 x += listbox->widths[i];
01370 if (i+1<cols) {
01371 buf_printchar(x++, 0, color, ' ');
01372 buf_printchar(x++, 0, color, CHAR_LINEV);
01373 buf_printchar(x++, 0, color, ' ');
01374 }
01375 }
01376 }
01377
01378 vcp ht_listbox_title::getTextColor()
01379 {
01380 return getcolor(palidx_generic_body);
01381 }
01382
01383 void ht_listbox_title::setText(int cols, ...)
01384 {
01385 va_list vargs;
01386 va_start(vargs, cols);
01387 setTextv(cols, vargs);
01388 va_end(vargs);
01389 va_end(vargs);
01390 }
01391
01392 void ht_listbox_title::setTextv(int c, va_list vargs)
01393 {
01394 if (texts) {
01395 for (int i=0; i<cols; i++) {
01396 free(texts[i]);
01397 }
01398 free(texts);
01399 }
01400 texts = NULL;
01401 cols = c;
01402 if (!c) return;
01403 texts = (char**)malloc(c * sizeof(char*));
01404 for (int i=0; i<cols; i++) {
01405 texts[i] = ht_strdup(va_arg(vargs, char* ));
01406 }
01407 update();
01408 }
01409
01410 void ht_listbox_title::update()
01411 {
01412 if (texts && listbox && listbox->widths) {
01413 for (int i=0; i<cols; i++) {
01414 int s = strlen(texts[i]);
01415 if (s > listbox->widths[i]) listbox->widths[i] = s;
01416 }
01417 }
01418 }
01419
01420
01421
01422
01423
01424
01425 class ht_listbox_vstate: public Object {
01426 public:
01427 void *e_top;
01428 void *e_cursor;
01429
01430 ht_listbox_vstate(void *top, void *cursor)
01431 {
01432 e_top = top;
01433 e_cursor = cursor;
01434 }
01435 };
01436
01437 void ht_listbox::init(bounds *b, UINT Listboxcaps)
01438 {
01439 ht_view::init(b, VO_SELECTABLE | VO_OWNBUFFER | VO_RESIZE, 0);
01440 cached_count = 0;
01441
01442 growmode = MK_GM(GMH_FIT, GMV_FIT);
01443
01444 bounds c=*b;
01445 c.x=c.w-1;
01446 c.y=0;
01447 c.w=1;
01448 scrollbar=new ht_scrollbar();
01449 scrollbar->init(&c, &pal, true);
01450
01451 pos = 0;
01452 cursor = 0;
01453 e_top = getFirst();
01454 e_cursor = e_top;
01455 title = NULL;
01456 visible_height = 0;
01457 x = 0;
01458 widths = NULL;
01459 clearQuickfind();
01460 update();
01461 listboxcaps = Listboxcaps;
01462 cols = 0;
01463 }
01464
01465 void ht_listbox::done()
01466 {
01467 scrollbar->done();
01468 delete scrollbar;
01469 if (widths) free(widths);
01470 ht_view::done();
01471 }
01472
01473 void ht_listbox::adjustPosHack()
01474 {
01475 if (e_cursor!=e_top) return;
01476 int i=0;
01477 void *tmp = e_cursor;
01478 if (!tmp) return;
01479 while ((tmp) && (i<=visible_height)) {
01480 tmp = getNext(tmp);
01481 i++;
01482 }
01483 if (i<visible_height) {
01484 cursorDown(cursorUp(visible_height-pos-i));
01485 }
01486 }
01487
01488 void ht_listbox::adjustScrollbar()
01489 {
01490 int pstart, psize;
01491 if (scrollbar_pos(pos-cursor, size.h, cached_count, &pstart, &psize)) {
01492 mScrollbarEnabled = true;
01493 scrollbar->enable();
01494 bounds c = size;
01495 c.x = c.w-1;
01496 c.y = 0;
01497 c.w = 1;
01498 scrollbar->setbounds(&c);
01499 scrollbar->setpos(pstart, psize);
01500 } else {
01501 mScrollbarEnabled = false;
01502 scrollbar->disable();
01503 }
01504 }
01505
01506 void ht_listbox::attachTitle(ht_listbox_title *aTitle)
01507 {
01508 if (numColumns() > cols) rearrangeColumns();
01509 title = aTitle;
01510 title->listbox = this;
01511 title->update();
01512 title->dirtyview();
01513 }
01514
01515 void ht_listbox::clearQuickfind()
01516 {
01517 quickfinder[0] = 0;
01518 qpos = quickfinder;
01519 updateCursor();
01520 }
01521
01522 int ht_listbox::cursorAdjust()
01523 {
01524 return 0;
01525 }
01526
01527 int ht_listbox::cursorUp(int n)
01528 {
01529 void *tmp;
01530 int i = 0;
01531
01532 while (n--) {
01533 tmp = getPrev(e_cursor);
01534 if (!tmp) break;
01535 if (e_cursor==e_top) {
01536 e_top = tmp;
01537 } else {
01538 cursor--;
01539 }
01540 e_cursor = tmp;
01541 pos--;
01542 if (pos<0) pos = 0;
01543 i++;
01544 }
01545 return i;
01546 }
01547
01548 int ht_listbox::cursorDown(int n)
01549 {
01550 void *tmp;
01551 int i = 0;
01552
01553 while (n--) {
01554 tmp = getNext(e_cursor);
01555 if (!tmp) break;
01556 if (cursor+1 >= visible_height) {
01557 e_top = getNext(e_top);
01558 } else {
01559 cursor++;
01560 }
01561 pos++;
01562 e_cursor = tmp;
01563 i++;
01564 }
01565 return i;
01566 }
01567
01568 int ht_listbox::datasize()
01569 {
01570 return sizeof(ht_listbox_data);
01571 }
01572
01573 char *ht_listbox::defaultpalette()
01574 {
01575 return palkey_generic_dialog_default;
01576 }
01577
01578 void ht_listbox::draw()
01579 {
01580 int fc = focused ? getcolor(palidx_generic_list_focused_unselected) :
01581 getcolor(palidx_generic_list_unfocused_unselected);
01582
01583 int Cols = numColumns();
01584 if (Cols > cols) rearrangeColumns();
01585
01586 bool resizing_cols = true;
01587 bool title_redraw = false;
01588 while (resizing_cols) {
01589 resizing_cols = false;
01590 clear(fc);
01591 void *entry = e_top;
01592 int i=0;
01593 while ((entry) && (i < visible_height)) {
01594 int c=(i==cursor) ? (focused ? getcolor(palidx_generic_list_focused_selected) :
01595 getcolor(palidx_generic_list_unfocused_selected)) : fc;
01596 if (i==cursor) {
01597 fill(0, i, size.w, 1, c, ' ');
01598 }
01599 int X = -x;
01600 for (int j=0; j<cols; j++) {
01601 char *s = getStr(j, entry);
01602 int slen = strlen(s);
01603 if (slen > widths[j]) {
01604 widths[j] = slen;
01605
01606
01607
01608
01609 resizing_cols = true;
01610 title_redraw = true;
01611 }
01612 if (s) {
01613 if (X >= 0) {
01614 buf_lprint(X, i, c, size.w, s);
01615 } else {
01616 if (slen > -X) buf_lprint(0, i, c, size.w, &s[-X]);
01617 }
01618 }
01619 if (j==cols-1) {
01620 X += slen;
01621 } else {
01622 X += widths[j];
01623 }
01624 if (j+1<cols) {
01625 buf_printchar(X++, i, c, ' ');
01626 buf_printchar(X++, i, c, CHAR_LINEV);
01627 buf_printchar(X++, i, c, ' ');
01628 }
01629 }
01630 if (x > 0) {
01631
01632 buf_printchar(0, i, c, '<');
01633 }
01634
01635 int a = mScrollbarEnabled ? 0 : 1;
01636 if (X >= size.w+a) {
01637
01638 buf_printchar(size.w-2+a, i, c, '>');
01639 }
01640 entry = getNext(entry);
01641 i++;
01642 }
01643 }
01644 updateCursor();
01645 if (title_redraw && title) {
01646 title->update();
01647 title->dirtyview();
01648 }
01649
01650
01651
01652
01653
01654
01655
01656 }
01657
01658 int ht_listbox::estimateEntryPos(void *entry)
01659 {
01660
01661 void *tmp = getFirst();
01662 int res = 0;
01663 while (tmp) {
01664 if (tmp==entry) break;
01665 tmp = getNext(tmp);
01666 res++;
01667 }
01668 return (tmp==entry) ? res : -1;
01669 }
01670
01671 void ht_listbox::getdata(ht_object_stream *s)
01672 {
01673 ht_listbox_data d;
01674 d.top_ptr = e_top;
01675 d.cursor_ptr = e_cursor;
01676 s->write(&d, sizeof d);
01677 }
01678
01679 void ht_listbox::gotoItemByEntry(void *entry, bool clear_quickfind)
01680 {
01681 if (clear_quickfind) clearQuickfind();
01682 if (!entry) return;
01683 void *tmp = e_top;
01684 int i=0;
01685 bool ok=false;
01686 pos -= cursor;
01687 if (pos<0) pos = 0;
01688 cursor = 0;
01689
01690 while ((tmp) && (i < visible_height)) {
01691 if (tmp == entry) {
01692 ok = true;
01693 break;
01694 }
01695 pos++;
01696 cursor++;
01697 i++;
01698 tmp = getNext(tmp);
01699 }
01700 e_cursor = entry;
01701 if (!ok) {
01702 e_top = entry;
01703 cursor = 0;
01704 pos = estimateEntryPos(entry);
01705 assert(pos != -1);
01706 }
01707 adjustPosHack();
01708 stateChanged();
01709 }
01710
01711 void ht_listbox::gotoItemByPosition(UINT pos)
01712 {
01713 void *entry = getFirst();
01714 while (pos--) entry = getNext(entry);
01715 gotoItemByEntry(entry, true);
01716 }
01717
01718 void ht_listbox::handlemsg(htmsg *msg)
01719 {
01720 switch (msg->msg) {
01721 case msg_vstate_restore: {
01722 ht_listbox_vstate *vs = (ht_listbox_vstate*)msg->data1.ptr;
01723 e_top = vs->e_top;
01724 e_cursor = vs->e_cursor;
01725 update();
01726
01727 clearmsg(msg);
01728 return;
01729 }
01730 case msg_keypressed: switch (msg->data1.integer) {
01731 case K_Control_PageUp:
01732 case K_Home:
01733 clearQuickfind();
01734 pos = cursor = 0;
01735 e_top = e_cursor = getFirst();
01736 dirtyview();
01737 clearmsg(msg);
01738 stateChanged();
01739 return;
01740 case K_Control_PageDown:
01741 case K_End: {
01742 clearQuickfind();
01743 cursor = 0;
01744 pos = cached_count ? cached_count-1 : 0;
01745 e_cursor = e_top = getLast();
01746 cursorUp(visible_height-1);
01747 cursorDown(visible_height-1);
01748 dirtyview();
01749 clearmsg(msg);
01750 stateChanged();
01751 return;
01752 }
01753 case K_PageUp:
01754 clearQuickfind();
01755 cursorUp(visible_height-1);
01756 dirtyview();
01757 clearmsg(msg);
01758 stateChanged();
01759 return;
01760 case K_PageDown: {
01761 clearQuickfind();
01762 cursorDown(visible_height-1);
01763 dirtyview();
01764 clearmsg(msg);
01765 stateChanged();
01766 return;
01767 }
01768 case K_Up:
01769 clearQuickfind();
01770 cursorUp(1);
01771 dirtyview();
01772 clearmsg(msg);
01773 stateChanged();
01774 return;
01775 case K_Down:
01776 clearQuickfind();
01777 cursorDown(1);
01778 dirtyview();
01779 clearmsg(msg);
01780 stateChanged();
01781 return;
01782 case K_Left:
01783 case K_Control_Left:
01784 if (x > 0) x--;
01785 updateCursor();
01786 dirtyview();
01787 clearmsg(msg);
01788 stateChanged();
01789 return;
01790 case K_Right:
01791 case K_Control_Right:
01792 x++;
01793 updateCursor();
01794 dirtyview();
01795 clearmsg(msg);
01796 stateChanged();
01797 return;
01798 case K_Tab:
01799 if (listboxcaps & LISTBOX_QUICKFIND) {
01800 if (*quickfinder) {
01801 char *qc = quickfindCompletition(quickfinder);
01802 if (qc) {
01803 strcpy(quickfinder, qc);
01804 qpos = strend(quickfinder);
01805 free(qc);
01806 goto qf;
01807 }
01808 }
01809 }
01810 break;
01811 case K_Backspace: {
01812 if (listboxcaps & LISTBOX_QUICKFIND) {
01813 if (qpos > quickfinder) {
01814 *(--qpos) = 0;
01815 qf:
01816 void *a = quickfind(quickfinder);
01817 if (a) {
01818 gotoItemByEntry(a, false);
01819 updateCursor();
01820 dirtyview();
01821 }
01822 clearmsg(msg);
01823 stateChanged();
01824 }
01825 }
01826 return;
01827 }
01828 default: {
01829 if ((listboxcaps & LISTBOX_QUICKFIND) && (msg->data1.integer > 31) && (msg->data1.integer < 0xff)) {
01830 *(qpos++) = msg->data1.integer;
01831 *qpos = 0;
01832 void *a = quickfind(quickfinder);
01833 if (a) {
01834 gotoItemByEntry(a, false);
01835 updateCursor();
01836 dirtyview();
01837 clearmsg(msg);
01838 stateChanged();
01839 } else {
01840 *(--qpos) = 0;
01841 }
01842 }
01843 }
01844 }
01845 break;
01846 }
01847 ht_view::handlemsg(msg);
01848 }
01849
01850 int ht_listbox::numColumns()
01851 {
01852 return 1;
01853 }
01854
01855 char *ht_listbox::quickfindCompletition(char *s)
01856 {
01857 return ht_strdup(s);
01858 }
01859
01860 void ht_listbox::rearrangeColumns()
01861 {
01862 if (widths) free(widths);
01863 cols = numColumns();
01864 widths = (int*)calloc(cols*sizeof(int), 1);
01865 }
01866
01867 void ht_listbox::redraw()
01868 {
01869 ht_view::redraw();
01870 scrollbar->relocate_to(this);
01871
01872 scrollbar->redraw();
01873 if (title) {
01874 title->redraw();
01875 }
01876 scrollbar->unrelocate_to(this);
01877 }
01878
01879 void ht_listbox::resize(int rw, int rh)
01880 {
01881 ht_view::resize(rw, rh);
01882 update();
01883 }
01884
01885 void ht_listbox::stateChanged()
01886 {
01887 adjustScrollbar();
01888 }
01889
01890 bool ht_listbox::selectEntry(void *entry)
01891 {
01892 return true;
01893 }
01894
01895 void ht_listbox::setdata(ht_object_stream *s)
01896 {
01897 ht_listbox_data d;
01898 s->read(&d, sizeof d);
01899 e_top = d.top_ptr;
01900 e_cursor = d.cursor_ptr;
01901 update();
01902 }
01903
01904 Object *ht_listbox::vstate_create()
01905 {
01906 return new ht_listbox_vstate(e_top, e_cursor);
01907 }
01908
01909 void ht_listbox::vstate_save()
01910 {
01911 Object *vs = vstate_create();
01912 if (vs) {
01913 htmsg m;
01914 m.msg = msg_vstate_save;
01915 m.type = mt_empty;
01916 m.data1.ptr = vs;
01917 m.data2.ptr = this;
01918 app->sendmsg(&m);
01919 }
01920 }
01921
01922
01923
01924
01925 void ht_listbox::update()
01926 {
01927 void *entry = getFirst();
01928 cached_count = calcCount();
01929 visible_height = MIN(size.h, cached_count);
01930 if (cached_count <= size.h) {
01931 if (!e_cursor) e_cursor = getFirst();
01932 cursor = 0;
01933 while (entry && (cursor < visible_height)) {
01934 if (entry == e_cursor) {
01935 e_top = getFirst();
01936 goto ok;
01937 }
01938 entry = getNext(entry);
01939 cursor++;
01940 }
01941 }
01942 if (!e_top) {
01943 e_top = getFirst();
01944 }
01945 if (!e_cursor) e_cursor = e_top;
01946 entry = e_top;
01947 cursor = 0;
01948 while (entry && (cursor < visible_height)) {
01949 if (entry == e_cursor) goto ok;
01950 entry = getNext(entry);
01951 cursor++;
01952 }
01953 cursor = 0;
01954 e_top = e_cursor;
01955 ok:
01956 adjustPosHack();
01957 stateChanged();
01958 if (title) {
01959 title->update();
01960 title->dirtyview();
01961 }
01962 dirtyview();
01963 }
01964
01965 void ht_listbox::updateCursor()
01966 {
01967 if (focused) {
01968 if (*quickfinder) {
01969 setcursor((qpos-quickfinder)+cursorAdjust()-x, cursor);
01970 } else {
01971 hidecursor();
01972 }
01973 }
01974 }
01975
01976
01977
01978
01979
01980 void ht_text_listbox::init(bounds *b, int aCols, int aKeycol, UINT aListboxcaps)
01981 {
01982 first = last = NULL;
01983 count = 0;
01984 ht_listbox::init(b, aListboxcaps);
01985 cols = aCols;
01986 keycol = aKeycol;
01987 Cursor_adjust = 0;
01988 rearrangeColumns();
01989 }
01990
01991 void ht_text_listbox::done()
01992 {
01993 clearAll();
01994 ht_listbox::done();
01995 }
01996
01997 void ht_text_listbox::clearAll()
01998 {
01999 ht_text_listbox_item *temp = first;
02000 while (temp) {
02001 ht_text_listbox_item *temp2 = temp->next;
02002 freeExtraData(temp->extra_data);
02003 for (int i=0; i<cols; i++) {
02004 free(temp->data[i]);
02005 }
02006 free(temp);
02007 temp = temp2;
02008 }
02009 first = last = NULL;
02010
02011 pos = 0;
02012 cursor = 0;
02013 e_top = getFirst();
02014 e_cursor = e_top;
02015 x = 0;
02016 clearQuickfind();
02017
02018 count = 0;
02019 Cursor_adjust = 0;
02020 }
02021
02022 int ht_text_listbox::calcCount()
02023 {
02024 return count;
02025 }
02026
02027 int ht_text_listbox::compare_strn(char *s1, char *s2, int l)
02028 {
02029 return ht_strncmp(s1, s2, l);
02030 }
02031
02032 int ht_text_listbox::compare_ccomm(char *s1, char *s2)
02033 {
02034 return strccomm(s1, s2);
02035 }
02036
02037 int ht_text_listbox::cursorAdjust()
02038 {
02039 return Cursor_adjust;
02040 }
02041
02042 void ht_text_listbox::freeExtraData(void *extra_data)
02043 {
02044 }
02045
02046 void *ht_text_listbox::getFirst()
02047 {
02048 return first;
02049 }
02050
02051 UINT ht_text_listbox::getID(void *entry)
02052 {
02053 if (entry) {
02054 return ((ht_text_listbox_item *)entry)->id;
02055 } else {
02056 return 0;
02057 }
02058 }
02059
02060 void *ht_text_listbox::getLast()
02061 {
02062 return last;
02063 }
02064
02065 void *ht_text_listbox::getNext(void *entry)
02066 {
02067 if (!entry) return NULL;
02068 return ((ht_text_listbox_item *)entry)->next;
02069 }
02070
02071 void *ht_text_listbox::getPrev(void *entry)
02072 {
02073 if (!entry) return NULL;
02074 return ((ht_text_listbox_item *)entry)->prev;
02075 }
02076
02077 char *ht_text_listbox::getStr(int col, void *entry)
02078 {
02079 if (entry && (col < cols)) {
02080 return ((ht_text_listbox_item *)entry)->data[col];
02081 } else {
02082 return "";
02083 }
02084 }
02085
02086 void ht_text_listbox::insert_str_extra(int id, void *extra_data, char **strs)
02087 {
02088
02089 ht_text_listbox_item *item = (ht_text_listbox_item *)malloc(sizeof(ht_text_listbox_item)+sizeof(char *)*cols);
02090 item->next = NULL;
02091 item->prev = last;
02092 item->id = id;
02093 item->extra_data = extra_data;
02094 for (int i=0; i<cols; i++) {
02095 int slen = strlen(strs[i]);
02096 if (slen > widths[i]) {
02097 widths[i] = slen;
02098 }
02099
02100 item->data[i] = ht_strdup(strs[i]);
02101 }
02102 if (first) {
02103 last->next = item;
02104 } else {
02105 first = item;
02106 }
02107 last = item;
02108 count++;
02109 }
02110
02111 void ht_text_listbox::insert_str_extra(int id, void *extra_data, char *str, ...)
02112 {
02113 ht_text_listbox_item *item = (ht_text_listbox_item *)malloc(sizeof(ht_text_listbox_item)+sizeof(char *)*cols);
02114 item->next = NULL;
02115 item->prev = last;
02116 item->id = id;
02117 item->extra_data = extra_data;
02118 va_list str2;
02119 va_start(str2, str);
02120 char *str3 = str;
02121 for (int i=0; i<cols; i++) {
02122 int slen = strlen(str3);
02123 if (slen > widths[i]) {
02124 widths[i] = slen;
02125 }
02126
02127 item->data[i] = ht_strdup(str3);
02128 str3 = va_arg(str2, char *);
02129 }
02130 va_end(str2);
02131 if (first) {
02132 last->next = item;
02133 } else {
02134 first = item;
02135 }
02136 last = item;
02137 count++;
02138 }
02139
02140 void ht_text_listbox::insert_str(int id, char **strs)
02141 {
02142 insert_str_extra(id, NULL, strs);
02143 }
02144
02145 void ht_text_listbox::insert_str(int id, char *str, ...)
02146 {
02147
02148 ht_text_listbox_item *item = (ht_text_listbox_item *)malloc(sizeof(ht_text_listbox_item)+sizeof(char *)*cols);
02149 item->next = NULL;
02150 item->prev = last;
02151 item->id = id;
02152 item->extra_data = NULL;
02153 va_list str2;
02154 va_start(str2, str);
02155 char *str3 = str;
02156 for (int i=0; i<cols; i++) {
02157 int slen = strlen(str3);
02158 if (slen > widths[i]) {
02159 widths[i] = slen;
02160 }
02161
02162 item->data[i] = ht_strdup(str3);
02163 str3 = va_arg(str2, char *);
02164 }
02165 va_end(str2);
02166 if (first) {
02167 last->next = item;
02168 } else {
02169 first = item;
02170 }
02171 last = item;
02172 count++;
02173 }
02174
02175 int ht_text_listbox::numColumns()
02176 {
02177 return cols;
02178 }
02179
02180 void *ht_text_listbox::quickfind(char *s)
02181 {
02182 ht_text_listbox_item *item = first;
02183 int slen = strlen(s);
02184 while (item && (compare_strn(item->data[keycol], s, slen)!=0)) {
02185 item = item->next;
02186 }
02187 return item;
02188 }
02189
02190 char *ht_text_listbox::quickfindCompletition(char *s)
02191 {
02192 ht_text_listbox_item *item = first;
02193 char *res = NULL;
02194 int slen = strlen(s);
02195 while (item) {
02196 if (compare_strn(item->data[keycol], s, slen)==0) {
02197 if (!res) {
02198 res = ht_strdup(item->data[keycol]);
02199 } else {
02200 int a = compare_ccomm(item->data[keycol], res);
02201 res[a] = 0;
02202 }
02203 }
02204 item = item->next;
02205 }
02206 return res;
02207 }
02208
02209 static int ht_text_listboxcomparatio(ht_text_listbox_item *a, ht_text_listbox_item *b, int count, ht_text_listbox_sort_order *so)
02210 {
02211 for (int i=0;i<count;i++) {
02212 int r = so[i].compare_func(a->data[so[i].col], b->data[so[i].col]);
02213 if (r!=0) return r;
02214 }
02215 return 0;
02216 }
02217
02218 static void ht_text_listboxqsort(int l, int r, int count, ht_text_listbox_sort_order *so, ht_text_listbox_item **list)
02219 {
02220 int m=(l+r)/2;
02221 int L=l;
02222 int R=r;
02223 ht_text_listbox_item *c=list[m];
02224 do {
02225 while ((l<=r) && (ht_text_listboxcomparatio(list[l], c, count, so)<0)) l++;
02226 while ((l<=r) && (ht_text_listboxcomparatio(list[r], c, count, so)>0)) r--;
02227 if (l<=r) {
02228 ht_text_listbox_item *t=list[l];
02229 list[l]=list[r];
02230 list[r]=t;
02231 l++;
02232 r--;
02233 }
02234 } while(l<r);
02235 if (L<r) ht_text_listboxqsort(L, r, count, so, list);
02236 if (l<R) ht_text_listboxqsort(l, R, count, so, list);
02237 }
02238
02239 void ht_text_listbox::sort(int count, ht_text_listbox_sort_order *so)
02240 {
02241 ht_text_listbox_item **list;
02242 ht_text_listbox_item *tmp;
02243 int i=0;
02244 int cnt = calcCount();
02245
02246 if (cnt<2) return;
02247
02248 list = (ht_text_listbox_item **)malloc(cnt*sizeof(void *));
02249 tmp = first;
02250 while (tmp) {
02251 list[i++] = tmp;
02252 tmp = (ht_text_listbox_item *)getNext(tmp);
02253 }
02254
02255 int c_id = ((ht_text_listbox_item*)e_cursor)->id;
02256
02257 ht_text_listboxqsort(0, cnt-1, count, so, list);
02258
02259 for (i=0; i<cnt; i++) {
02260 if (list[i]->id == c_id) {
02261 pos = i;
02262 e_cursor = list[i];
02263 }
02264 }
02265
02266 first = list[0];
02267 last = list[cnt-1];
02268 first->prev = NULL;
02269 last->next = NULL;
02270 last->prev = list[cnt-2];
02271 tmp = first->next = list[1];
02272 for (i=1; i<cnt-1; i++) {
02273 tmp->prev = list[i-1];
02274 tmp->next = list[i+1];
02275 tmp = list[i+1];
02276 }
02277 free(list);
02278
02279 update();
02280 stateChanged();
02281 }
02282
02283 void ht_text_listbox::update()
02284 {
02285 ht_listbox::update();
02286 Cursor_adjust = 0;
02287 if (widths) {
02288 for (int i=0; i<keycol; i++) {
02289 Cursor_adjust+=widths[i]+3;
02290 }
02291 }
02292 }
02293
02294
02295
02296
02297
02298 void ht_itext_listbox::init(bounds *b, int Cols, int Keycol)
02299 {
02300 ht_text_listbox::init(b, Cols, Keycol);
02301 }
02302
02303 void ht_itext_listbox::done()
02304 {
02305 ht_text_listbox::done();
02306 }
02307
02308 int ht_itext_listbox::compare_strn(char *s1, char *s2, int l)
02309 {
02310 return ht_strnicmp(s1, s2, l);
02311 }
02312
02313 int ht_itext_listbox::compare_ccomm(char *s1, char *s2)
02314 {
02315 return strcicomm(s1, s2);
02316 }
02317
02318
02319
02320
02321
02322 #define STATICTEXT_MIN_LINE_FILL 70
02323
02324 void ht_statictext_align(ht_statictext_linedesc *d, statictext_align align, int w)
02325 {
02326 switch (align) {
02327 case align_center:
02328 d->ofs=(w-d->len)/2;
02329 break;
02330 case align_right:
02331 d->ofs=w-d->len;
02332 break;
02333 default:
02334 d->ofs=0;
02335 break;
02336 }
02337 }
02338
02339 void ht_statictext::init(bounds *b, const char *t, statictext_align al, bool breakl, bool trans)
02340 {
02341 ht_view::init(b, VO_OWNBUFFER | VO_RESIZE, "some statictext");
02342 VIEW_DEBUG_NAME("ht_statictext");
02343
02344 align=al;
02345 breaklines=breakl;
02346 transparent=trans;
02347 text=ht_strdup(t);
02348 }
02349
02350 void ht_statictext::done()
02351 {
02352 if (text) free(text);
02353 ht_view::done();
02354 }
02355
02356 char *ht_statictext::defaultpalette()
02357 {
02358 return palkey_generic_dialog_default;
02359 }
02360
02361 #define ssst_word 0
02362 #define ssst_separator 1
02363 #define ssst_whitespace 2
02364
02365 int get_ssst(char s)
02366 {
02367 if (strchr(".,:;+-*/=()[]", s)) {
02368 return ssst_separator;
02369 } else if (s==' ') {
02370 return ssst_whitespace;
02371 }
02372 return ssst_word;
02373 }
02374
02375 void ht_statictext::draw()
02376 {
02377 if (!transparent) clear(gettextcolor());
02378 char *t=gettext();
02379 if (!t) return;
02380 if (breaklines) {
02381
02382 ht_statictext_linedesc *orig_d=(ht_statictext_linedesc *)malloc(sizeof (ht_statictext_linedesc)*size.h);
02383 ht_statictext_linedesc *d=orig_d;
02384 statictext_align lalign=align;
02385 int c=0;
02386 while ((*t) && (c<size.h)) {
02387
02388 if ((*t==ALIGN_CHAR_ESCAPE) && (align==align_custom)) {
02389 switch (t[1]) {
02390 case ALIGN_CHAR_LEFT:
02391 lalign=align_left;
02392 break;
02393 case ALIGN_CHAR_CENTER:
02394 lalign=align_center;
02395 break;
02396 case ALIGN_CHAR_RIGHT:
02397 lalign=align_right;
02398 break;
02399 }
02400 t+=2;
02401 }
02402
02403 int i=0, len=1;
02404 char *bp=t+1, *n=t+1;
02405 int ssst=get_ssst(t[i]);
02406 while (t[i]) {
02407 if ((i+1>size.w) || (t[i]=='\n') || !(t[i+1])) {
02408 bool kill_ws=(t[i]!='\n');
02409 if (i+1<=size.w) {
02410
02411 bp=t+i+1;
02412 } else if (t[i]=='\n') {
02413
02414 bp=t+i+1;
02415 } else if (size.w && ((bp-t)*100/size.w < STATICTEXT_MIN_LINE_FILL)) {
02416
02417 bp=t+i;
02418 }
02419 len=bp-t;
02420 if (t[len-1]=='\n') len--;
02421 n=bp;
02422 if (kill_ws) {
02423 while (*n==' ') n++;
02424 while (t[len-1]==' ') len--;
02425 }
02426 break;
02427 }
02428 int s=get_ssst(t[i+1]);
02429 if ((ssst!=s) || (ssst==ssst_separator)) {
02430 bp=t+i+1;
02431 }
02432 ssst=s;
02433 i++;
02434 }
02435 d->text=t;
02436 d->len=len;
02437 ht_statictext_align(d, lalign, size.w);
02438 d++;
02439 c++;
02440 t=n;
02441 }
02442
02443
02444 d=orig_d;
02445 for (int i=0; i<c; i++) {
02446 buf_lprint(d->ofs, i, gettextcolor(), d->len, d->text);
02447 d++;
02448 }
02449 free(orig_d);
02450 } else {
02451 int o=0;
02452 buf_print(o, 0, gettextcolor(), t);
02453 }
02454 }
02455
02456 vcp ht_statictext::gettextcolor()
02457 {
02458 return getcolor(palidx_generic_body);
02459
02460 }
02461
02462 char *ht_statictext::gettext()
02463 {
02464 return text;
02465 }
02466
02467 void ht_statictext::settext(const char *_text)
02468 {
02469 if (text) free(text);
02470 text = ht_strdup(_text);
02471 dirtyview();
02472 }
02473
02474
02475
02476
02477
02478 void ht_listpopup_dialog::init(bounds *b, char *desc)
02479 {
02480 ht_dialog::init(b, desc, FS_TITLE | FS_MOVE);
02481 VIEW_DEBUG_NAME("ht_listpopup_dialog");
02482
02483 bounds c;
02484 getclientarea(&c);
02485 c.x=0;
02486 c.y=0;
02487 init_text_listbox(&c);
02488 }
02489
02490 void ht_listpopup_dialog::done()
02491 {
02492 ht_dialog::done();
02493 }
02494
02495 int ht_listpopup_dialog::datasize()
02496 {
02497 return sizeof (ht_listpopup_dialog_data);
02498 }
02499
02500 char *ht_listpopup_dialog::defaultpalette()
02501 {
02502 return palkey_generic_blue;
02503 }
02504
02505 void ht_listpopup_dialog::getdata(ht_object_stream *s)
02506 {
02507 ht_listbox_data d;
02508 listbox->databuf_get(&d, sizeof d);
02509
02510 s->putIntDec(((ht_text_listbox*)listbox)->getID(d.cursor_ptr), 4, NULL);
02511
02512 ht_text_listbox_item *cursor = (ht_text_listbox_item*)d.cursor_ptr;
02513 if (cursor) {
02514 s->putString(cursor->data[0], NULL);
02515 } else {
02516 s->putString(NULL, NULL);
02517 }
02518 }
02519
02520 void ht_listpopup_dialog::init_text_listbox(bounds *b)
02521 {
02522 listbox=new ht_text_listbox();
02523 ((ht_text_listbox *)listbox)->init(b);
02524 insert(listbox);
02525 }
02526
02527 void ht_listpopup_dialog::insertstring(char *string)
02528 {
02529 ((ht_text_listbox *)listbox)->insert_str(listbox->calcCount(), string);
02530 listbox->update();
02531 }
02532
02533 void ht_listpopup_dialog::select_next()
02534 {
02535 listbox->cursorDown(1);
02536 }
02537
02538 void ht_listpopup_dialog::select_prev()
02539 {
02540 listbox->cursorUp(1);
02541 }
02542
02543 void ht_listpopup_dialog::setdata(ht_object_stream *s)
02544 {
02545 int cursor_id=s->getIntDec(4, NULL);
02546 s->getString(NULL);
02547
02548 listbox->gotoItemByPosition(cursor_id);
02549 }
02550
02551
02552
02553
02554
02555 void ht_listpopup::init(bounds *b)
02556 {
02557 ht_statictext::init(b, 0, align_left, 0);
02558 setoptions(options|VO_SELECTABLE);
02559 VIEW_DEBUG_NAME("ht_listpopup");
02560
02561 bounds c=*b;
02562 c.x=0;
02563 c.y=0;
02564 c.h=8;
02565
02566 listpopup=new ht_listpopup_dialog();
02567 listpopup->init(&c, 0);
02568 }
02569
02570 void ht_listpopup::done()
02571 {
02572 listpopup->done();
02573 delete listpopup;
02574
02575 ht_view::done();
02576 }
02577
02578 int ht_listpopup::datasize()
02579 {
02580 return listpopup->datasize();
02581 }
02582
02583 void ht_listpopup::draw()
02584 {
02585 ht_statictext::draw();
02586 buf_printchar(size.w-1, 0, gettextcolor(), CHAR_ARROW_DOWN);
02587 }
02588
02589 vcp ht_listpopup::gettextcolor()
02590 {
02591 return focused ? getcolor(palidx_generic_input_selected) :
02592 getcolor(palidx_generic_input_focused);
02593 }
02594
02595 void ht_listpopup::getdata(ht_object_stream *s)
02596 {
02597 listpopup->getdata(s);
02598 }
02599
02600 char *ht_listpopup::gettext()
02601 {
02602 ht_listpopup_dialog_data d;
02603 listpopup->databuf_get(&d, sizeof d);
02604 return d.cursor_string;
02605 }
02606
02607 void ht_listpopup::handlemsg(htmsg *msg)
02608 {
02609 if (msg->msg==msg_keypressed) {
02610 switch (msg->data1.integer) {
02611 case K_Up: {
02612 int r;
02613 ht_listpopup_dialog_data d;
02614 listpopup->databuf_get(&d, sizeof d);
02615 listpopup->select_prev();
02616 r=run_listpopup();
02617 clearmsg(msg);
02618 if (!r) listpopup->databuf_set(&d, sizeof d);
02619 return;
02620 }
02621 case K_Down: {
02622 int r;
02623 ht_listpopup_dialog_data d;
02624 listpopup->databuf_get(&d, sizeof d);
02625 listpopup->select_next();
02626 r=run_listpopup();
02627 clearmsg(msg);
02628 if (!r) listpopup->databuf_set(&d, sizeof d);
02629 return;
02630 }
02631 }
02632 }
02633 ht_statictext::handlemsg(msg);
02634 }
02635
02636 int ht_listpopup::run_listpopup()
02637 {
02638 int r;
02639 listpopup->relocate_to(this);
02640 r=listpopup->run(false);
02641 listpopup->unrelocate_to(this);
02642 return r;
02643 }
02644
02645 void ht_listpopup::insertstring(char *string)
02646 {
02647 listpopup->insertstring(string);
02648 }
02649
02650 void ht_listpopup::setdata(ht_object_stream *s)
02651 {
02652 listpopup->setdata(s);
02653 }
02654
02655
02656
02657
02658
02659 ht_listbox_ptr::ht_listbox_ptr(ht_listbox *_listbox)
02660 {
02661 listbox=_listbox;
02662 }
02663
02664 ht_listbox_ptr::~ht_listbox_ptr()
02665 {
02666 }
02667
02668
02669
02670
02671
02672 void ht_label::init(bounds *b, const char *_text, ht_view *_connected)
02673 {
02674 ht_view::init(b, VO_POSTPROCESS, 0);
02675 text = ht_strdup(_text);
02676 magicchar = strchr(text, '~');
02677 if (magicchar) {
02678 int l = strlen(text);
02679 memmove(magicchar, magicchar+1, l-(magicchar-text));
02680 }
02681 connected=_connected;
02682 if (magicchar) {
02683 shortcut = ht_metakey((ht_key)*magicchar);
02684 } else shortcut = K_INVALID;
02685 }
02686
02687 void ht_label::done()
02688 {
02689 if (text) free(text);
02690 ht_view::done();
02691 }
02692
02693 char *ht_label::defaultpalette()
02694 {
02695 return palkey_generic_dialog_default;
02696 }
02697
02698 void ht_label::draw()
02699 {
02700 vcp c;
02701 vcp sc = getcolor(palidx_generic_text_shortcut);
02702 if (connected->focused) {
02703 c = getcolor(palidx_generic_text_focused);
02704 } else {
02705 c = getcolor(palidx_generic_text_unfocused);
02706 }
02707 buf_lprint(0, 0, c, size.w, text);
02708 if (magicchar) buf_printchar(magicchar-text, 0, sc, *magicchar);
02709 }
02710
02711 void ht_label::handlemsg(htmsg *msg)
02712 {
02713 if (msg->type==mt_postprocess) {
02714 if (msg->msg==msg_keypressed) {
02715 if ((shortcut!=-1) && (msg->data1.integer==shortcut)) {
02716 app->focus(connected);
02717 dirtyview();
02718 clearmsg(msg);
02719 return;
02720 }
02721 }
02722 } else ht_view::handlemsg(msg);
02723 }
02724
02725
02726
02727
02728
02729 void ht_progress_indicator::init(bounds *b, char *hint)
02730 {
02731 ht_window::init(b, NULL, 0);
02732
02733 bounds c=*b;
02734
02735 c.x=1;
02736 c.y=1;
02737 c.w-=c.x+2;
02738 c.h-=c.y+3;
02739 text=new ht_statictext();
02740 text->init(&c, NULL, align_center, true);
02741 insert(text);
02742
02743 c.y+=2;
02744 c.h=1;
02745 ht_statictext *t=new ht_statictext();
02746 t->init(&c, hint, align_center);
02747 insert(t);
02748 }
02749
02750 char *ht_progress_indicator::defaultpalette()
02751 {
02752 return palkey_generic_dialog_default;
02753 }
02754
02755 void ht_progress_indicator::settext(const char *t)
02756 {
02757 text->settext(t);
02758 }
02759
02760
02761
02762
02763
02764 int vcs[16]={VC_BLACK, VC_BLUE, VC_GREEN, VC_CYAN, VC_RED, VC_MAGENTA, VC_YELLOW, VC_WHITE, VC_LIGHT(VC_BLACK), VC_LIGHT(VC_BLUE), VC_LIGHT(VC_GREEN), VC_LIGHT(VC_CYAN), VC_LIGHT(VC_RED), VC_LIGHT(VC_MAGENTA), VC_LIGHT(VC_YELLOW), VC_LIGHT(VC_WHITE)};
02765
02766 void ht_color_block::init(bounds *b, int selected, int Flags)
02767 {
02768 ht_view::init(b, VO_OWNBUFFER | VO_SELECTABLE, 0);
02769 VIEW_DEBUG_NAME("ht_color_block");
02770 flags=Flags;
02771
02772 ht_color_block_data d;
02773 d.color = selected;
02774 databuf_set(&d, sizeof d);
02775 if (flags & cf_light) colors=16; else colors=8;
02776 }
02777
02778 void ht_color_block::done()
02779 {
02780 ht_view::done();
02781 }
02782
02783 int ht_color_block::datasize()
02784 {
02785 return sizeof (ht_color_block_data);
02786 }
02787
02788 char *ht_color_block::defaultpalette()
02789 {
02790 return palkey_generic_dialog_default;
02791 }
02792
02793 void ht_color_block::draw()
02794 {
02795 clear(getcolor(palidx_generic_body));
02796 dword cursor=VCP(focused ? VC_LIGHT(VC_WHITE) : VC_BLACK, VC_TRANSPARENT);
02797 for (int i=0; i<colors; i++) {
02798 buf_printchar((i%4)*3+1, i/4, VCP(vcs[i], VC_TRANSPARENT), CHAR_FILLED_F);
02799 buf_printchar((i%4)*3+2, i/4, VCP(vcs[i], VC_BLACK), CHAR_FILLED_M);
02800 if (i==color) {
02801 buf_printchar((i%4)*3, i/4, cursor, '>');
02802 buf_printchar((i%4)*3+3, i/4, cursor, '<');
02803 }
02804 }
02805 if (flags & cf_transparent) {
02806 buf_print(1, (colors==8) ? 2 : 4, VCP(VC_BLACK, VC_TRANSPARENT), "transparent");
02807 if (color==-1) {
02808 buf_printchar(0, (colors==8) ? 2 : 4, cursor, '>');
02809 buf_printchar(12, (colors==8) ? 2 : 4, cursor, '<');
02810 }
02811 }
02812 }
02813
02814 void ht_color_block::getdata(ht_object_stream *s)
02815 {
02816 s->putIntDec((color==-1) ? VC_TRANSPARENT : vcs[color], 4, NULL);
02817 }
02818
02819 void ht_color_block::handlemsg(htmsg *msg)
02820 {
02821 if (msg->msg==msg_keypressed) {
02822 switch (msg->data1.integer) {
02823 case K_Left:
02824 if (color==-1) color=(flags & cf_light) ? 15 : 7; else
02825 if (color%4-1>=0) color--;
02826 dirtyview();
02827 clearmsg(msg);
02828 return;
02829 case K_Right:
02830 if (color==-1) color=(flags & cf_light) ? 15 : 7; else
02831 if (color%4+1<=3) color++;
02832 dirtyview();
02833 clearmsg(msg);
02834 return;
02835 case K_Up:
02836 if (color==-1) color=(flags & cf_light) ? 15 : 7; else
02837 if (color-4>=0) color-=4;
02838 dirtyview();
02839 clearmsg(msg);
02840 return;
02841 case K_Down:
02842 if (color!=-1)
02843 if (color+4<colors) color+=4; else color=-1;
02844 dirtyview();
02845 clearmsg(msg);
02846 return;
02847 }
02848 }
02849 ht_view::handlemsg(msg);
02850 }
02851
02852 void ht_color_block::setdata(ht_object_stream *s)
02853 {
02854 int c=s->getIntDec(4, NULL);
02855 if (c==VC_TRANSPARENT) color=-1; else {
02856 for (int i=0; i<16; i++) if (vcs[i]==c) {
02857 color=i;
02858 break;
02859 }
02860 }
02861 dirtyview();
02862 }
02863
02864 void center_bounds(bounds *b)
02865 {
02866 bounds c;
02867 app->getbounds(&c);
02868 b->x=(c.w-b->w)/2;
02869 b->y=(c.h-b->h)/2;
02870 }
02871