1 /**
2 * @namespace biew
3 * @file bconsole.c
4 * @brief This file contains low level BIEW console functions.
5 * @version -
6 * @remark this source file is part of Binary vIEW project (BIEW).
7 * The Binary vIEW (BIEW) is copyright (C) 1995 Nickols_K.
8 * All rights reserved. This software is redistributable under the
9 * licence given in the file "Licence.en" ("Licence.ru" in russian
10 * translation) distributed in the BIEW archive.
11 * @note Requires POSIX compatible development system
12 *
13 * @author Nickols_K
14 * @since 1995
15 * @note Development, fixes and improvements
16 * @author Mauro Giachero
17 * @date 02.11.2007
18 * @note Added "ungotstring" function to enable inline assemblers
19 **/
20 #include <stdarg.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <ctype.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <time.h>
28
29 #include "editor.h"
30 #include "colorset.h"
31 #include "biewutil.h"
32 #include "tstrings.h"
33 #include "search.h"
34 #include "bconsole.h"
35 #include "biewlib/pmalloc.h"
36 #include "biewlib/kbd_code.h"
37
38 extern TWindow * ErrorWnd;
39
40 #define MAXINPUT 79
41
42 #define FORMFEED 12
43
44 static int KB_Buff[64];
45 static unsigned char KB_freq = 0;
46 extern char biew_codepage[];
47
initBConsole(unsigned long vio_flg,unsigned long twin_flg)48 void __FASTCALL__ initBConsole( unsigned long vio_flg,unsigned long twin_flg )
49 {
50 twInit(biew_codepage,vio_flg,twin_flg);
51 if(tvioWidth < 80 || tvioHeight < 3)
52 {
53 if(tvioWidth>16&&tvioHeight>2) {
54 unsigned evt,x,y;
55 TWindow *win;
56 x = (tvioWidth-17)/2;
57 y = (tvioHeight-3)/2;
58 win = WindowOpen(x,y,x+16,y+2,TWS_NONE | TWS_NLSOEM);
59 if(!win) goto done;
60 twSetTitleAttr(win," Error ",TW_TMODE_CENTER,error_cset.border);
61 twCentredWin(win,NULL);
62 twSetColorAttr(error_cset.main);
63 twSetFrameAttr(win,TW_DOUBLE_FRAME,error_cset.border);
64 twGotoXY(1,1);
65 twPutS("Screensize<80x3");
66 twShowWin(win);
67 do {
68 evt = GetEvent(NULL,NULL,ErrorWnd);
69 }while(!(evt == KE_ESCAPE || evt == KE_F(10) || evt == KE_ENTER));
70 twDestroyWin(win);
71 }
72 done:
73 twDestroy();
74 printm("Size of video buffer must be larger than 79x2\n"
75 "Current size of video buffer is: w=%u h=%u\n",tvioWidth,tvioHeight);
76 exit(EXIT_FAILURE);
77 }
78 }
79
termBConsole(void)80 void __FASTCALL__ termBConsole( void )
81 {
82 twDestroy();
83 }
84
85 /**
86 read the next keyboard character
87 */
getkey(int hard,void (* func)(void))88 static int __NEAR__ __FASTCALL__ getkey(int hard, void (*func)(void))
89 {
90 return KB_freq ? KB_Buff[--KB_freq] :
91 GetEvent( func ? func : hard ? hard > 1 ?
92 drawAsmEdPrompt : drawEditPrompt : drawEmptyPrompt,
93 func ? NULL : hard ? hard > 1 ?
94 EditAsmActionFromMenu: NULL: NULL,
95 NULL);
96 }
97
ungotkey(int keycode)98 static tBool __NEAR__ __FASTCALL__ ungotkey(int keycode)
99 {
100 tBool ret = False;
101 if(KB_freq < sizeof(KB_Buff)/sizeof(int))
102 {
103 KB_Buff[KB_freq++] = keycode;
104 ret = True;
105 }
106 return ret;
107 }
108
ungotstring(char * string)109 tBool __FASTCALL__ ungotstring(char *string)
110 {
111 int pos;
112 for (pos = strlen(string)-1; pos>=0; pos--) {
113 if (ungotkey(string[pos]) == False)
114 return False;
115 }
116 return True;
117 }
118
xeditstring(char * s,const char * legal,unsigned maxlength,void (* func)(void))119 int __FASTCALL__ xeditstring(char *s,const char *legal,unsigned maxlength, void (*func)(void))
120 {
121 return eeditstring(s,legal,&maxlength,1,NULL,__ESS_ENABLEINSERT,NULL,func);
122 }
123
124 #define isSpace(val) (((int)val+1)%3 ? 0 : 1)
125 #define isFirstD(pos) (isSpace(pos-1))
126 #define isSecondD(pos) (isSpace(pos+1))
127
128 static tBool insert = True;
129
eeditstring(char * s,const char * legal,unsigned * maxlength,unsigned _y,unsigned * stx,unsigned attr,char * undo,void (* func)(void))130 int __FASTCALL__ eeditstring(char *s,const char *legal, unsigned *maxlength,unsigned _y,unsigned *stx,unsigned attr,char *undo, void (*func)(void))
131 {
132 int c;
133 unsigned len = attr & __ESS_HARDEDIT ? *maxlength : attr & __ESS_NON_C_STR ? _y : strlen(s);
134 unsigned pos = len;
135 unsigned y = attr & __ESS_HARDEDIT ? _y : 1;
136 int lastkey,func_getkeys;
137 char ashex = attr & __ESS_ASHEX;
138 tBool freq = (attr & __ESS_HARDEDIT) == __ESS_HARDEDIT;
139 if(stx) pos = *stx;
140 if(!(attr & __ESS_HARDEDIT))
141 twSetCursorType(attr & __ESS_ENABLEINSERT ? insert ? TW_CUR_NORM : TW_CUR_SOLID : TW_CUR_NORM);
142 do
143 {
144 unsigned i;
145 Loop:
146 twFreezeWin(twUsedWin());
147 if(!(attr & __ESS_NOREDRAW))
148 {
149 if(!undo) twDirectWrite(1,y,s,len);
150 else
151 {
152 for(i = 0;i < len;i++)
153 {
154 twSetColorAttr(s[i] == undo[i] ? browser_cset.edit.main : browser_cset.edit.change);
155 twDirectWrite(i+1,y,&s[i],1);
156 }
157 }
158 if(!(attr & __ESS_HARDEDIT))
159 {
160 twGotoXY(len + 1,y);
161 if(ashex)
162 if(isSecondD(pos) && pos >= len)
163 {
164 twPutChar('.');
165 twGotoXY(len + 2,y);
166 }
167 for(i = len; i < *maxlength;i++)
168 twPutChar((attr & __ESS_FILLER_7BIT) == __ESS_FILLER_7BIT ? TWC_DEF_FILLER : TWC_MED_SHADE);
169 }
170 }
171 twRefreshLine(twUsedWin(),y);
172 twGotoXY(pos + 1, y);
173 func_getkeys = attr & __ESS_HARDEDIT ? attr & 0x0020 ? 2 : 1 : 0;
174 new_keycode:
175 c = getkey(func_getkeys, func);
176 lastkey = c;
177 attr |= __ESS_NOREDRAW;
178 switch(c)
179 {
180 case KE_MOUSE:
181 case KE_SHIFTKEYS:
182 goto new_keycode;
183 case KE_HOME : if(!(ashex && isSecondD(pos))) pos = 0; break;
184 case KE_END : if(!(ashex && isSecondD(pos))) pos = len; break;
185 case KE_LEFTARROW : if(pos)
186 {
187 if(!ashex) pos--;
188 else
189 if(!isSecondD(pos))
190 {
191 if(pos > 3) pos -=3;
192 else pos = 0;
193 }
194 }
195 break;
196 case KE_RIGHTARROW: if(pos < len)
197 {
198 if(!ashex) pos++;
199 else
200 if(!isSecondD(pos))
201 {
202 pos += 3;
203 if(pos >= len) pos = len;
204 }
205 }
206 break;
207 case KE_BKSPACE : if (pos > 0 && !(attr & __ESS_HARDEDIT))
208 {
209 attr &= ~__ESS_NOREDRAW;
210 memmove(&s[pos-1], &s[pos], len - pos + 1);
211 pos--; len--;
212 if(ashex)
213 if(isSpace(pos) && pos > 2)
214 {
215 memmove(&s[pos-2], &s[pos], len - pos + 2);
216 pos-=2; len-=2;
217 }
218 }
219 break;
220 case KE_DEL : if (pos < len && !(attr & __ESS_HARDEDIT))
221 {
222 attr &= ~__ESS_NOREDRAW;
223 memmove(&s[pos], &s[pos+1], len - pos);
224 len--;
225 if(ashex)
226 if(!isSpace(pos) && pos > 2)
227 {
228 memmove(&s[pos], &s[pos+2], len - pos);
229 len-=2;
230 }
231 }
232 break;
233 case KE_CTL_BKSPACE:
234 if(undo)
235 {
236 attr &= ~__ESS_NOREDRAW;
237 if(pos) pos--; if(ashex) if(isSpace(pos) && pos) pos--;
238 s[pos] = undo[pos];
239 }
240 break;
241 case KE_INS : if(attr & __ESS_ENABLEINSERT &&
242 !(attr & __ESS_HARDEDIT) &&
243 !ashex)
244 insert = insert ? False : True;
245 twSetCursorType(attr & __ESS_ENABLEINSERT ? insert ? TW_CUR_NORM : TW_CUR_SOLID : TW_CUR_NORM);
246 break;
247 case KE_ENTER : break;
248 case KE_ESCAPE : len = 0; break;
249 default :
250 /** FunKey trough int 16 returned XX00 exclude Ctrl0-CtrlZ */
251 if(!(c & 0x00FF) || c == KE_TAB || c == KE_SHIFT_TAB || c == KE_BKSPACE) { c = KE_ENTER; break; }
252 if ( legal == 0 || strchr(legal, c) != NULL )
253 {
254 attr &= ~__ESS_NOREDRAW;
255 if(!freq && !(attr & __ESS_WANTRETURN)) { freq = True; s[0] = 0; len = pos = 0; ungotkey(c); break; }
256 if(pos < *maxlength)
257 {
258 if(insert)
259 {
260 if(len < *maxlength)
261 {
262 memmove(&s[pos + 1], &s[pos], len - pos + 1);
263 len++;
264 }
265 }
266 else
267 if (pos >= len) len++;
268 if(len > *maxlength) len = *maxlength;
269 s[pos++] = c;
270 if(ashex)
271 {
272 if(isSpace(pos))
273 {
274 if (pos >= len) len++;
275 if(len > *maxlength) len = *maxlength;
276 s[pos] = attr & __ESS_HARDEDIT && !((pos + 1) % 12) ? '-' : ' ';
277 pos++;
278 }
279 if(isSecondD(pos) && pos < len) s[pos] = '.';
280 }
281 }
282 else s[pos - 1] = c;
283 }
284 break;
285 } /* switch */
286 if(!freq) freq = True;
287 if(!(attr & __ESS_HARDEDIT)) s[len] = 0;
288 if(ashex)
289 if(!isFirstD(pos))
290 if(c != KE_ESCAPE) goto Loop;
291 if(attr & __ESS_WANTRETURN) if(!(ashex && isSecondD(pos))) break;
292 }
293 while ( (c != KE_ENTER) && (c != KE_ESCAPE));
294 if(!(attr & __ESS_HARDEDIT)) twSetCursorType(TW_CUR_OFF);
295 if(!(attr & __ESS_WANTRETURN && attr & __ESS_NOTUPDATELEN)) *maxlength = len;
296 if(stx) *stx = pos;
297 return lastkey;
298 } /* editstring */
299
PleaseWaitWnd(void)300 TWindow *__FASTCALL__ PleaseWaitWnd( void )
301 {
302 TWindow *w,*usd;
303 usd = twUsedWin();
304 w = CrtDlgWndnls(SYSTEM_BUSY,14,1);
305 twGotoXY(1,1); twPutS(PLEASE_WAIT);
306 twUseWin(usd);
307 return w;
308 }
309
MemOutBox(const char * user_msg)310 void __FASTCALL__ MemOutBox(const char *user_msg)
311 {
312 ErrMessageBox(user_msg," Not enough memory! ");
313 }
314
315 struct percent_data
316 {
317 time_t _time;
318 time_t prev_time;
319 unsigned _percents;
320 tBool is_first;
321 };
322
PercentWndCallBack(TWindow * it,unsigned event,unsigned long param,void * data)323 static long __FASTCALL__ PercentWndCallBack(TWindow *it,unsigned event, unsigned long param, void *data)
324 {
325 struct percent_data *my_data;
326 UNUSED(param);
327 UNUSED(data);
328 switch(event)
329 {
330 case WM_CREATE:
331 if((my_data=malloc(sizeof(struct percent_data))) != NULL)
332 {
333 twSetUsrData(it,my_data);
334 }
335 break;
336 case WM_DESTROY:
337 my_data = twGetUsrData(it);
338 if(my_data) free(my_data);
339 break;
340 default: break;
341 }
342 return 0L;
343 }
344
345
PercentWnd(const char * text,const char * title)346 TWindow *__FASTCALL__ PercentWnd(const char *text,const char *title)
347 {
348 TWindow *ret,*usd;
349 static time_t sttime;
350 struct percent_data* my_data;
351 usd = twUsedWin();
352 twcRegisterClass("PERCENT_WND", __CS_ORDINAL, PercentWndCallBack);
353 ret = twCreateWinEx(1,1,53,6,TWS_FRAMEABLE | TWS_NLSOEM,NULL,"PERCENT_WND");
354 twCentredWin(ret,NULL);
355 twSetColorAttr(dialog_cset.main);
356 twSetFrameAttr(ret,TW_UP3D_FRAME,dialog_cset.main);
357 twSetTitleAttr(ret,title,TW_TMODE_CENTER,dialog_cset.title);
358 twSetFooterAttr(ret," [ Ctrl-Break ] - Abort ",TW_TMODE_RIGHT,dialog_cset.footer);
359 twClearWin();
360 twGotoXY(1,1); twPutS(text);
361 twinDrawFrameAttr(1,2,52,4,TW_DN3D_FRAME,dialog_cset.main);
362 twShowWin(ret);
363 twUseWin(usd);
364 time(&sttime);
365 my_data = twGetUsrData(ret);
366 if(my_data)
367 {
368 my_data->_time = my_data->prev_time = sttime;
369 my_data->_percents = 0;
370 my_data->is_first = True;
371 }
372 return ret;
373 }
374
ShowPercentInWnd(TWindow * pw,unsigned percents)375 tBool __FASTCALL__ ShowPercentInWnd(TWindow *pw,unsigned percents)
376 {
377 TWindow *usd;
378 unsigned cells,remaind, prev_prcnt = 0;
379 time_t sttime =0,curtime,deltat, prev_time = 0;
380 struct tm *tm;
381 struct percent_data* my_data;
382 tBool is_first = True;
383 char outb[50];
384 tBool ret;
385 usd = twUsedWin();
386 twUseWin(pw);
387 my_data = twGetUsrData(pw);
388 if(my_data)
389 {
390 prev_prcnt = my_data->_percents;
391 sttime = my_data->_time;
392 prev_time = my_data->prev_time;
393 is_first = my_data->is_first;
394 }
395 if(percents != prev_prcnt || is_first)
396 {
397 if(percents > 100) percents = 100;
398 cells = percents/2;
399 remaind = percents%2;
400 memset(outb,TWC_FL_BLK,cells);
401 if(remaind) outb[cells++] = TWC_LF_HBLK;
402 if(cells < sizeof(outb)) memset(&outb[cells],TWC_DEF_FILLER,sizeof(outb)-cells);
403 twDirectWrite(2,3,outb,sizeof(outb));
404 }
405 time(&curtime);
406 if(prev_time != curtime || is_first)
407 {
408 deltat = curtime - sttime;
409 tm = gmtime(&deltat);
410 strftime(outb,sizeof(outb),"%X",tm);
411 twGotoXY(1,5);
412 twPutS("Elapsed time: ");
413 twPutS(outb);
414 }
415 if(my_data)
416 {
417 my_data->_percents = percents;
418 my_data->is_first = False;
419 my_data->prev_time = curtime;
420 }
421 twUseWin(usd);
422 ret = !IsKbdTerminate();
423 CleanKbdTermSig();
424 return ret;
425 }
426
WindowOpen(tAbsCoord x1,tAbsCoord y1,tAbsCoord x2,tAbsCoord y2,unsigned flags)427 TWindow * __FASTCALL__ WindowOpen(tAbsCoord x1,tAbsCoord y1,tAbsCoord x2,tAbsCoord y2,unsigned flags)
428 {
429 TWindow *ret;
430 ret = twCreateWin(x1,y1,x2-x1+1,y2-y1+1,flags);
431 if(!ret) { MemOutBox(NULL); exit(EXIT_FAILURE); }
432 return ret;
433 }
434
CloseWnd(TWindow * w)435 void __FASTCALL__ CloseWnd(TWindow *w)
436 {
437 twDestroyWin(w);
438 }
439
_CreateWindowDD(const char * title,tAbsCoord x2,tAbsCoord y2,tBool is_nls)440 static TWindow * __NEAR__ __FASTCALL__ _CreateWindowDD(const char * title,tAbsCoord x2,tAbsCoord y2,tBool is_nls)
441 {
442 TWindow *win;
443 unsigned flags;
444 char frame[8];
445 flags = TWS_FRAMEABLE;
446 if(is_nls) flags |= TWS_NLSOEM;
447 win = WindowOpen(0,0,x2,y2,flags);
448 twCentredWin(win,NULL);
449 twSetColorAttr(dialog_cset.main);
450 twClearWin();
451 memcpy(frame,TW_DOUBLE_FRAME,8);
452 if(!is_nls) __nls_OemToOsdep((unsigned char *)frame,8);
453 twSetFrameAttr(win,frame,dialog_cset.border);
454 if(title) twSetTitleAttr(win,title,TW_TMODE_CENTER,dialog_cset.title);
455 twShowWin(win);
456 return win;
457 }
458
459 #define _CreateWindowDDnls(title,x2,y2) (_CreateWindowDD(title,x2,y2,True))
460
CrtDlgWnd(const char * title,tAbsCoord width,tAbsCoord height)461 TWindow * __FASTCALL__ CrtDlgWnd(const char * title,tAbsCoord width,tAbsCoord height )
462 {
463 return _CreateWindowDD(title,width,height,False);
464 }
465
CrtDlgWndnls(const char * title,tAbsCoord width,tAbsCoord height)466 TWindow * __FASTCALL__ CrtDlgWndnls(const char * title,tAbsCoord width,tAbsCoord height )
467 {
468 return _CreateWindowDDnls(title,width,height);
469 }
470
_CrtMnuWindowDD(const char * title,tAbsCoord x1,tAbsCoord y1,tAbsCoord x2,tAbsCoord y2,tBool is_nls)471 static TWindow * __NEAR__ __FASTCALL__ _CrtMnuWindowDD(const char *title,tAbsCoord x1, tAbsCoord y1, tAbsCoord x2,tAbsCoord y2,tBool is_nls)
472 {
473 TWindow *win;
474 unsigned flags;
475 flags = TWS_FRAMEABLE;
476 if(is_nls) flags |= TWS_NLSOEM;
477 win = WindowOpen(x1,y1,x2,y2,flags);
478 if(!x1 && !y1) twCentredWin(win,NULL);
479 twSetColorAttr(menu_cset.main);
480 twClearWin();
481 twSetFrameAttr(win,TW_DOUBLE_FRAME,menu_cset.border);
482 if(title) twSetTitleAttr(win,title,TW_TMODE_CENTER,menu_cset.title);
483 twShowWin(win);
484 return win;
485 }
486
CrtMnuWnd(const char * title,tAbsCoord x1,tAbsCoord y1,tAbsCoord x2,tAbsCoord y2)487 TWindow * __FASTCALL__ CrtMnuWnd(const char * title,tAbsCoord x1, tAbsCoord y1,tAbsCoord x2,tAbsCoord y2)
488 {
489 return _CrtMnuWindowDD(title,x1,y1,x2,y2,False);
490 }
491
CrtMnuWndnls(const char * title,tAbsCoord x1,tAbsCoord y1,tAbsCoord x2,tAbsCoord y2)492 TWindow * __FASTCALL__ CrtMnuWndnls(const char * title,tAbsCoord x1, tAbsCoord y1,tAbsCoord x2,tAbsCoord y2)
493 {
494 return _CrtMnuWindowDD(title,x1,y1,x2,y2,True);
495 }
496
CrtLstWnd(const char * title,tAbsCoord x2,tAbsCoord y2)497 TWindow * __FASTCALL__ CrtLstWnd(const char * title,tAbsCoord x2,tAbsCoord y2)
498 {
499 return _CrtMnuWindowDD(title,0,0,x2,y2,False);
500 }
501
CrtLstWndnls(const char * title,tAbsCoord x2,tAbsCoord y2)502 TWindow * __FASTCALL__ CrtLstWndnls(const char * title,tAbsCoord x2,tAbsCoord y2)
503 {
504 return _CrtMnuWindowDD(title,0,0,x2,y2,True);
505 }
506
_CreateHlpWnd(const char * title,tAbsCoord x2,tAbsCoord y2,tBool is_nls)507 static TWindow * __NEAR__ __FASTCALL__ _CreateHlpWnd(const char * title,tAbsCoord x2,tAbsCoord y2,tBool is_nls)
508 {
509 TWindow *win;
510 unsigned flags;
511 flags = TWS_FRAMEABLE;
512 if(is_nls) flags |= TWS_NLSOEM;
513 win = WindowOpen(0,0,x2,y2,flags);
514 twCentredWin(win,NULL);
515 twSetColorAttr(help_cset.main);
516 twClearWin();
517 twSetFrameAttr(win,TW_DOUBLE_FRAME,help_cset.border);
518 if(title) twSetTitleAttr(win,title,TW_TMODE_CENTER,help_cset.title);
519 twShowWin(win);
520 return win;
521 }
522
CrtHlpWnd(const char * title,tAbsCoord x2,tAbsCoord y2)523 TWindow * __FASTCALL__ CrtHlpWnd(const char * title,tAbsCoord x2,tAbsCoord y2)
524 {
525 return _CreateHlpWnd(title,x2,y2,False);
526 }
527
CrtHlpWndnls(const char * title,tAbsCoord x2,tAbsCoord y2)528 TWindow * __FASTCALL__ CrtHlpWndnls(const char * title,tAbsCoord x2,tAbsCoord y2)
529 {
530 return _CreateHlpWnd(title,x2,y2,True);
531 }
532
CreateEditor(tAbsCoord X1,tAbsCoord Y1,tAbsCoord X2,tAbsCoord Y2,unsigned flags)533 TWindow * __FASTCALL__ CreateEditor(tAbsCoord X1,tAbsCoord Y1,tAbsCoord X2,tAbsCoord Y2,unsigned flags)
534 {
535 TWindow *ret;
536 ret = WindowOpen(X1,Y1,X2,Y2,flags);
537 twSetColorAttr(dialog_cset.editor.active);
538 twClearWin();
539 return ret;
540 }
541
__MB(const char * text,const char * title,ColorAttr base,ColorAttr frame)542 static void __NEAR__ __FASTCALL__ __MB(const char * text,const char * title,
543 ColorAttr base,ColorAttr frame)
544 {
545 unsigned slen,tlen;
546 slen = strlen(text) + 3;
547 tlen = strlen(title) + 2;
548 slen = min(max(slen,tlen)+1,78);
549 twResizeWin(ErrorWnd,slen,3);
550 twCentredWin(ErrorWnd,NULL);
551 twSetFrameAttr(ErrorWnd,TW_DOUBLE_FRAME,frame);
552 twSetTitleAttr(ErrorWnd,title,TW_TMODE_CENTER,frame);
553 twSetColorAttr(base);
554 twClearWin();
555 twShowWinOnTop(ErrorWnd);
556 twGotoXY(2,1);
557 twPutS(text);
558 }
559
__MessageBox(const char * text,const char * title,ColorAttr base,ColorAttr frame)560 static void __NEAR__ __FASTCALL__ __MessageBox(const char * text,const char * title,
561 ColorAttr base,ColorAttr frame)
562 {
563 TWindow *prev;
564 unsigned evt;
565 prev = twUsedWin();
566 twUseWin(ErrorWnd);
567 __MB(text,title,base,frame);
568 do
569 {
570 evt = GetEvent(drawEmptyPrompt,NULL,ErrorWnd);
571 }
572 while(!(evt == KE_ESCAPE || evt == KE_F(10) || evt == KE_SPACE || evt == KE_ENTER));
573 twHideWin(ErrorWnd);
574 twUseWin(prev);
575 twResizeWin(ErrorWnd,tvioWidth,tvioHeight); /* It for reserving memory */
576 }
577
578
TMessageBox(const char * text,const char * title)579 void __FASTCALL__ TMessageBox(const char * text,const char * title)
580 {
581 __MessageBox(text,title ? title : "",dialog_cset.main,dialog_cset.title);
582 }
583
NotifyBox(const char * text,const char * title)584 void __FASTCALL__ NotifyBox(const char * text,const char * title)
585 {
586 __MessageBox(text,title ? title : NOTE_MSG,notify_cset.main,notify_cset.border);
587 }
588
ErrMessageBox(const char * text,const char * title)589 void __FASTCALL__ ErrMessageBox(const char * text,const char * title)
590 {
591 __MessageBox(text,title ? title : ERROR_MSG,error_cset.main,error_cset.border);
592 }
593
WarnMessageBox(const char * text,const char * title)594 void __FASTCALL__ WarnMessageBox(const char * text,const char * title)
595 {
596 __MessageBox(text,title ? title : WARN_MSG,warn_cset.main,warn_cset.border);
597 }
598
errnoMessageBox(const char * text,const char * title,int __errno__)599 void __FASTCALL__ errnoMessageBox(const char *text,const char *title,int __errno__)
600 {
601 char stmp[256];
602 sprintf(stmp,"%s: %i (%s)",text,__errno__,strerror(__errno__));
603 ErrMessageBox(stmp,title);
604 }
605
PaintLine(unsigned i,const char * name,unsigned width,unsigned mord_width,tBool isOrdinal,tBool useAcc,tBool is_hl)606 static void __NEAR__ __FASTCALL__ PaintLine(unsigned i,const char *name,
607 unsigned width,unsigned mord_width,
608 tBool isOrdinal,
609 tBool useAcc,tBool is_hl)
610 {
611 size_t namelen;
612 char buffer[__TVIO_MAXSCREENWIDTH + 1];
613 memset(buffer,TWC_DEF_FILLER,sizeof(buffer));
614 buffer[__TVIO_MAXSCREENWIDTH] = 0; /* [dBorca] play it safe for strchr below */
615 namelen = name?strlen(name):0;
616 if(isOrdinal)
617 {
618 char * endptr;
619 endptr = name?strrchr(name,LB_ORD_DELIMITER):NULL;
620 if(endptr)
621 {
622 unsigned len, rlen;
623 // write name
624 len = endptr - name;
625 rlen = len;
626 if(len > width - mord_width-1)
627 rlen = width - mord_width-3;
628 memcpy(buffer,name,rlen);
629 if(len > rlen) memcpy(buffer+rlen,"..", 2); // using 2 dots now -XF
630 // write ordinal. it's left aligned now -XF
631 buffer[width - mord_width - 1] = '@';
632 len = rlen = namelen - (len+1);
633 if(rlen > mord_width) rlen = mord_width - 2;
634 memcpy(&buffer[width - mord_width], endptr+1, rlen);
635 if(len > rlen) memcpy(buffer+width-mord_width+rlen,"..", 2);
636 }
637 }
638 else if(name) memcpy((char *)buffer,name,min(namelen,width));
639 if(useAcc)
640 {
641 char *st,*ends,*ptr;
642 char ch;
643 twGotoXY(3,i+1);
644 st = buffer;
645 ends = buffer+width;
646 while(1)
647 {
648 ptr = strchr(st,'~');
649 if(ptr)
650 {
651 unsigned outlen;
652 outlen = ptr-st;
653 twDirectWrite(twWhereX(),twWhereY(),st,outlen);
654 twGotoXY(twWhereX()+outlen,twWhereY());
655 st = ptr;
656 ch = *(++st);
657 if(ch != '~')
658 {
659 ColorAttr ca;
660 ca = twGetColorAttr();
661 twSetColorAttr(is_hl ? menu_cset.hotkey.focused : menu_cset.hotkey.active);
662 twPutChar(ch);
663 twSetColorAttr(ca);
664 }
665 st++;
666 }
667 else
668 {
669 twDirectWrite(twWhereX(),twWhereY(),st,(unsigned)(ends-st));
670 break;
671 }
672 }
673 }
674 else twDirectWrite(3,i+1,buffer,width);
675 }
676
Paint(TWindow * win,const char ** names,unsigned nlist,unsigned start,unsigned height,unsigned width,unsigned mord_width,tBool isOrdinal,tBool useAcc,unsigned cursor)677 static void __NEAR__ __FASTCALL__ Paint(TWindow *win,const char ** names,
678 unsigned nlist,unsigned start,
679 unsigned height,unsigned width,
680 unsigned mord_width,
681 tBool isOrdinal,tBool useAcc,
682 unsigned cursor)
683 {
684 unsigned i, pos = 0;
685 twUseWin(win);
686 twFreezeWin(win);
687 width -= 3;
688 if (height>2 && height<nlist)
689 pos = 1 + (start+cursor)*(height-2)/nlist;
690 for(i = 0;i < height;i++)
691 {
692 twSetColorAttr(menu_cset.main);
693 twGotoXY(1,i + 1);
694 if (i == 0)
695 twPutChar(start ? TWC_UP_ARROW : TWC_DEF_FILLER);
696 else if(i == height-1)
697 twPutChar(start + height < nlist ? TWC_DN_ARROW : TWC_DEF_FILLER);
698 else if (i == pos)
699 twPutChar(TWC_THUMB);
700 else twPutChar(TWC_DEF_FILLER);
701 twGotoXY(2,i + 1);
702 twPutChar(TWC_SV);
703 twSetColorAttr(menu_cset.item.active);
704 PaintLine(i,names[i + start],width,mord_width,isOrdinal,useAcc,cursor == i);
705 }
706 twRefreshWin(win);
707 }
708
709 static char byNam;
710
_lb_searchtext(const char * str,const char * tmpl,unsigned searchlen,const int * cache,unsigned flg)711 tBool __FASTCALL__ _lb_searchtext(const char *str,const char *tmpl,unsigned searchlen,const int *cache, unsigned flg)
712 {
713 return strFind(str, strlen(str), tmpl, searchlen, cache, flg) ? True : False;
714 }
715
listcompare(const void __HUGE__ * v1,const void __HUGE__ * v2)716 static tCompare __FASTCALL__ listcompare(const void __HUGE__ *v1,const void __HUGE__ *v2)
717 {
718 tCompare ret;
719 if(byNam) ret = stricmp(*((const char **)v1),*((const char **)v2));
720 else
721 {
722 const char *o1,*o2;
723 const char *s1,*s2;
724
725 s1 = *((const char **)v1);
726 s2 = *((const char **)v2);
727 o1 = strrchr(s1,LB_ORD_DELIMITER);
728 o2 = strrchr(s2,LB_ORD_DELIMITER);
729 if(o1 && o2)
730 {
731 unsigned long ord1,ord2;
732 char buff1[7], buff2[7];
733 strncpy(buff1,o1 + 1,6);
734 strncpy(buff2,o2 + 1,6);
735 ord1 = atol(buff1);
736 ord2 = atol(buff2);
737 ret = __CmpLong__(ord1,ord2);
738 }
739 else ret = stricmp(s1,s2);
740 }
741 return ret;
742 }
743
__ListBox(const char ** names,unsigned nlist,unsigned defsel,const char * title,int assel)744 static int __NEAR__ __FASTCALL__ __ListBox(const char ** names,unsigned nlist,unsigned defsel,const char * title,int assel)
745 {
746 TWindow * wlist;
747 char *acctable = 0;
748 unsigned i,j,width,height,mwidth = strlen(title);
749 unsigned mordstr_width, mord_width;
750 int ret,start,ostart,cursor,ocursor,scursor;
751 tBool isOrdinal,sf;
752 if(!names || !nlist) return -1;
753 isOrdinal = True;
754 scursor = -1;
755 i = 0;
756 if((assel & LB_USEACC) == LB_USEACC)
757 {
758 acctable = PMalloc(nlist*sizeof(char));
759 if(!acctable)
760 {
761 MemOutBox("Displaying list");
762 return -1;
763 }
764 memset(acctable,0,nlist*sizeof(char));
765 for(i = 0;i < nlist;i++)
766 {
767 unsigned len;
768 len = names[i]?strlen(names[i]):0;
769 for(j = 0;j < len;j++)
770 {
771 if(names[i][j] == '~' && names[i][j+1] != '~')
772 {
773 acctable[i] = toupper(names[i][j+1]);
774 break;
775 }
776 }
777 }
778 }
779 if(names[0]) if(!strrchr(names[0],LB_ORD_DELIMITER)) isOrdinal = False;
780 mordstr_width = mord_width = 0;
781 if(!isOrdinal)
782 for(i = 0;i < nlist;i++)
783 {
784 j = names[i]?strlen(names[i]):0;
785 if(j > mwidth) mwidth = j;
786 }
787 else
788 {
789 char *ord_delimiter;
790 for(i = 0;i < nlist;i++)
791 {
792 ord_delimiter = names[i]?strrchr(names[i], LB_ORD_DELIMITER):NULL;
793 if(ord_delimiter)
794 {
795 j = ord_delimiter - names[i];
796 if(j > mordstr_width) mordstr_width = j;
797 j = &names[i][strlen(names[i])] - ord_delimiter;
798 if(j > mord_width) mord_width = j;
799 }
800 }
801 // name now has higher priority than ordinal -XF
802 if(mordstr_width > (unsigned)(tvioWidth-10))
803 mordstr_width = (unsigned)(tvioWidth-10);
804 if(mord_width > (unsigned)(tvioWidth-4)-mordstr_width-1)
805 mord_width = (unsigned)(tvioWidth-4)-mordstr_width-1;
806 mwidth = mordstr_width+mord_width+1;
807 }
808 mwidth += 4;
809 if(mwidth > (unsigned)(tvioWidth-1)) mwidth = tvioWidth-1; // maximal width increased to tvioWidth-1 -XF
810 height = nlist < (unsigned)(tvioHeight - 4) ? nlist : tvioHeight - 4;
811 wlist = CrtLstWndnls(title,mwidth-1,height);
812 if((assel & LB_SELECTIVE) == LB_SELECTIVE) twSetFooterAttr(wlist," [ENTER] - Go ",TW_TMODE_RIGHT,dialog_cset.selfooter);
813 restart:
814 ostart = start = cursor = ocursor = 0;
815 if(defsel != UINT_MAX && defsel < nlist)
816 {
817 cursor = defsel;
818 while((unsigned)cursor > height) { start += height; cursor -= height; }
819 ostart = start;
820 ocursor = cursor;
821 }
822 Paint(wlist,names,nlist,(unsigned)start,height,mwidth,mord_width,isOrdinal,(assel & LB_USEACC) == LB_USEACC,(unsigned)cursor);
823 width = mwidth - 3;
824 if((assel & LB_SELECTIVE) == LB_SELECTIVE)
825 {
826 twSetColorAttr(menu_cset.item.focused);
827 PaintLine((unsigned)cursor,names[cursor + start],width,mord_width,isOrdinal,(assel & LB_USEACC) == LB_USEACC,True);
828 }
829 sf = False;
830 for(;;)
831 {
832 unsigned ch;
833 ch = GetEvent(isOrdinal ? drawOrdListPrompt : (assel & LB_SORTABLE) ? drawListPrompt : drawSearchListPrompt,NULL,wlist);
834 if(ch == KE_ESCAPE || ch == KE_F(10)) { ret = -1; break; }
835 if(ch == KE_ENTER) { ret = start + cursor; break; }
836 if(ch!=KE_F(7) && ch!=KE_SHIFT_F(7)) scursor = -1;
837 switch(ch)
838 {
839 case KE_F(2):
840 case KE_F(3):
841 if(isOrdinal || (assel & LB_SORTABLE))
842 {
843 byNam = ch == KE_F(2);
844 if(!isOrdinal && !byNam) break;
845 HQSort(names,nlist,sizeof(char *),listcompare);
846 goto restart;
847 }
848 break;
849 case KE_F(4): /** save content to disk */
850 {
851 char ofname[256];
852 ofname[0] = 0;
853 if(GetStringDlg(ofname," Save info to file : "," [ENTER] - Proceed ",NAME_MSG))
854 {
855 FILE * out;
856 out = fopen(ofname,"wt");
857 if(out)
858 {
859 strncpy(ofname,title,sizeof(ofname));
860 ofname[sizeof(ofname)-1] = '\0';
861 if(GetStringDlg(ofname," User comments : "," [ENTER] - Proceed "," Description : "))
862 {
863 fprintf(out,"%s\n\n",ofname);
864 }
865 for(i = 0;i < nlist;i++)
866 {
867 char *p;
868 p = names[i]?strchr(names[i],LB_ORD_DELIMITER):NULL;
869 if(p)
870 {
871 *p = 0;
872 fprintf(out,names[i]);
873 for(j = p - names[i];j < 50;j++) fprintf(out," ");
874 fprintf(out," @%s",p+1);
875 if(p) *p = LB_ORD_DELIMITER;
876 }
877 else fprintf(out,names[i]);
878 fprintf(out,"\n");
879 }
880 fclose(out);
881 }
882 else errnoMessageBox(WRITE_FAIL,NULL,errno);
883 }
884 }
885 break;
886 case KE_F(7): /** perform binary search in list */
887 case KE_SHIFT_F(7):
888 {
889 static char searchtxt[21] = "";
890 static unsigned char searchlen = 0;
891 static unsigned sflg = SF_NONE;
892
893 if (!(ch==KE_SHIFT_F(7) && searchlen) &&
894 !SearchDialog(SD_SIMPLE,searchtxt,&searchlen,&sflg))
895 break;
896
897 {
898 int direct, cache[UCHAR_MAX+1];
899 tBool found;
900 int ii,endsearch,startsearch;
901 searchtxt[searchlen] = 0;
902 endsearch = sflg & SF_REVERSE ? -1 : (int)nlist;
903 direct = sflg & SF_REVERSE ? -1 : 1;
904 startsearch = (assel & LB_SELECTIVE) == LB_SELECTIVE ?
905 cursor + start :
906 scursor != -1 ?
907 scursor :
908 start;
909 if(startsearch > (int)(nlist-1)) startsearch = nlist-1;
910 if(startsearch < 0) startsearch = 0;
911 if((assel & LB_SELECTIVE) == LB_SELECTIVE || scursor != -1)
912 {
913 sflg & SF_REVERSE ? startsearch-- : startsearch++;
914 }
915 found = False;
916 fillBoyerMooreCache(cache, searchtxt, searchlen, sflg & SF_CASESENS);
917 for(ii = startsearch;ii != endsearch;ii+=direct)
918 {
919 if(names[ii])
920 {
921 if(_lb_searchtext(names[ii],searchtxt,searchlen,cache,sflg))
922 {
923 start = scursor = ii;
924 if((unsigned)start > nlist - height) start = nlist - height;
925 ostart = start - 1;
926 if((assel & LB_SELECTIVE) == LB_SELECTIVE)
927 cursor = scursor - start;
928 found = True;
929 break;
930 }
931 }
932 }
933 if(!found) scursor = -1;
934 if(scursor == -1) ErrMessageBox(STR_NOT_FOUND,SEARCH_MSG);
935 }
936 }
937 break;
938 case KE_DOWNARROW : if((assel & LB_SELECTIVE) == LB_SELECTIVE) cursor ++; else start ++; break;
939 case KE_UPARROW : if((assel & LB_SELECTIVE) == LB_SELECTIVE) cursor --; else start --; break;
940 case KE_PGDN : start += height; break;
941 case KE_PGUP : start -= height; break;
942 case KE_CTL_PGDN : start = nlist - height; cursor = height; break;
943 case KE_CTL_PGUP : start = cursor = 0; break;
944 default :
945 /** Try accelerate choose */
946 if((assel & LB_USEACC) == LB_USEACC)
947 {
948 if((unsigned char)(ch & 0x00FF) > 31)
949 {
950 ch = toupper(ch & 0x00FF);
951 for(i = 0;i < nlist;i++)
952 {
953 if(ch == (unsigned)acctable[i]) { ret = i; goto Done; }
954 }
955 }
956 }
957 }
958 if((assel & LB_SELECTIVE) == LB_SELECTIVE)
959 {
960 if(cursor < 0) { cursor = 0; start--; }
961 if((unsigned)cursor > height - 1) { cursor = height - 1; start++; }
962 }
963 if(start < 0) start = 0;
964 if((unsigned)start > nlist - height) start = nlist - height;
965 if(start != ostart)
966 {
967 ostart = start;
968 Paint(wlist,names,nlist,(unsigned)start,height,mwidth,mord_width,isOrdinal,(assel & LB_USEACC) == LB_USEACC,(unsigned)cursor);
969 sf = True;
970 }
971 if((cursor != ocursor || sf) && (assel & LB_SELECTIVE) == LB_SELECTIVE)
972 {
973 twSetColorAttr(menu_cset.item.active);
974 PaintLine((unsigned)ocursor,names[ocursor + start],width,mord_width,isOrdinal,(assel & LB_USEACC) == LB_USEACC,False);
975 twSetColorAttr(menu_cset.item.focused);
976 PaintLine((unsigned)cursor,names[cursor + start],width,mord_width,isOrdinal,(assel & LB_USEACC) == LB_USEACC,True);
977 ocursor = cursor;
978 sf = False;
979 }
980 if(scursor != -1)
981 {
982 twSetColorAttr(menu_cset.highlight);
983 if(scursor >= start && (unsigned)scursor < start + height)
984 PaintLine((unsigned)(scursor - start),names[scursor],width,mord_width,isOrdinal,(assel & LB_USEACC) == LB_USEACC,True);
985 }
986 }
987 Done:
988 CloseWnd(wlist);
989 if(acctable) PFREE(acctable);
990 return ret;
991 }
992
CommonListBox(const char ** names,unsigned nlist,const char * title,int acc,unsigned defsel)993 int __FASTCALL__ CommonListBox(const char **names,unsigned nlist,const char *title,int acc,unsigned defsel)
994 {
995 return __ListBox(names,nlist,defsel,title,acc);
996 }
997
DisplayBox(const char ** names,unsigned nlist,const char * title)998 void __FASTCALL__ DisplayBox(const char **names,unsigned nlist,const char *title)
999 {
1000 __ListBox(names,nlist,UINT_MAX,title,0); /** not sortable & not selective */
1001 }
1002
ListBox(const char ** names,unsigned nlist,const char * title)1003 void __FASTCALL__ ListBox(const char ** names,unsigned nlist,const char * title)
1004 {
1005 __ListBox(names,nlist,UINT_MAX,title,LB_SORTABLE);
1006 }
1007
SelListBox(const char ** names,unsigned nlist,const char * title,unsigned defsel)1008 int __FASTCALL__ SelListBox(const char ** names,unsigned nlist,const char * title,unsigned defsel)
1009 {
1010 return __ListBox(names,nlist,defsel,title,LB_SELECTIVE | LB_SORTABLE);
1011 }
1012
SelBox(const char ** names,unsigned nlist,const char * title,unsigned defsel)1013 int __FASTCALL__ SelBox(const char ** names,unsigned nlist,const char * title,unsigned defsel)
1014 {
1015 return __ListBox(names,nlist,defsel,title,LB_SELECTIVE);
1016 }
1017
SelBoxA(const char ** names,unsigned nlist,const char * title,unsigned defsel)1018 int __FASTCALL__ SelBoxA(const char ** names,unsigned nlist,const char * title,unsigned defsel)
1019 {
1020 return __ListBox(names,nlist,defsel,title,LB_SELECTIVE | LB_USEACC);
1021 }
1022
PageBox(unsigned width,unsigned height,const void ** __obj,unsigned nobj,pagefunc func)1023 int __FASTCALL__ PageBox(unsigned width,unsigned height,const void ** __obj,unsigned nobj,pagefunc func)
1024 {
1025 TWindow * wlist;
1026 int start,ostart,ret;
1027 if(height>tvioHeight-2) height=tvioHeight-2;
1028 wlist = _CreateWindowDD(0,width-1,height,True);
1029 ostart = start = 0;
1030 (*func)(wlist,__obj,(unsigned)start,nobj);
1031 for(;;)
1032 {
1033 unsigned ch;
1034 ch = GetEvent(drawEmptyPrompt,NULL,wlist);
1035 if(ch == KE_ESCAPE || ch == KE_F(10)) { ret = -1; break; }
1036 if(ch == KE_ENTER) { ret = start; break; }
1037 switch(ch)
1038 {
1039 case KE_PGDN : start ++; break;
1040 case KE_PGUP : start --; break;
1041 case KE_CTL_PGDN : start = nobj - 1; break;
1042 case KE_CTL_PGUP : start = 0; break;
1043 default : break;
1044 };
1045 if(start < 0) start = 0;
1046 if((unsigned)start > nobj - 1) start = nobj - 1;
1047 if(start != ostart)
1048 {
1049 ostart = start;
1050 twGotoXY(1,1);
1051 (*func)(wlist,__obj,(unsigned)start,nobj);
1052 }
1053 }
1054 CloseWnd(wlist);
1055 return ret;
1056 }
1057