1 /**
2  * @namespace   biew
3  * @file        biew.c
4  * @brief       This file contains entry point of BIEW project.
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      Kostya Nosov <k-nosov@yandex.ru>
17  * @date        27.11.2000
18  * @note        Changing technology recognition of new-exe files
19 **/
20 #include <string.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <signal.h>
24 #include <limits.h>
25 #include <sys/stat.h>
26 #ifdef HAVE_SYS_RESOURCE
27 #include <sys/resource.h>
28 #endif
29 #include <stdlib.h>
30 #include <errno.h>
31 
32 #include "bconsole.h"
33 #include "colorset.h"
34 #include "bmfile.h"
35 #include "bin_util.h"
36 #include "codeguid.h"
37 #include "editor.h"
38 #include "tstrings.h"
39 #include "reg_form.h"
40 #include "biewutil.h"
41 #include "search.h"
42 #include "setup.h"
43 #include "biewlib/file_ini.h"
44 #include "biewlib/kbd_code.h"
45 #include "biewlib/biewlib.h"
46 #include "biewlib/pmalloc.h"
47 
48 
49 unsigned ArgCount;
50 char **  ArgVector;
51 unsigned ListFileCount;
52 static char **ListFile;
53 static char *LastOpenFileName;
54 __filesize_t LastOffset;
55 static tBool UseIniFile=True;
56 char biew_help_name[FILENAME_MAX+1] = "";
57 char biew_skin_name[FILENAME_MAX+1] = "";
58 char biew_syntax_name[FILENAME_MAX+1] = "";
59 char biew_codepage[256] = "CP866";
60 extern char last_skin_error[];
61 char biew_scheme_name[256] = "Built-in";
62 static char biew_ini_ver[32];
63 unsigned long biew_vioIniFlags = 0L;
64 unsigned long biew_twinIniFlags = 0L;
65 unsigned long biew_kbdFlags = 0L;
66 tBool iniSettingsAnywhere = False;
67 tBool fioUseMMF = False;
68 tBool iniPreserveTime = False;
69 tBool iniUseExtProgs = True;
70 __filesize_t headshift = 0L;
71 char *ini_name;
72 
73 TWindow * MainWnd = 0,*HelpWnd = 0,*TitleWnd = 0,*ErrorWnd = 0;
74 
75 #define SHORT_PATH_LEN __TVIO_MAXSCREENWIDTH-54
76 
77 char shortname[SHORT_PATH_LEN + 1];
78 
79 extern REGISTRY_BIN binTable;
80 extern REGISTRY_BIN rmTable;
81 extern REGISTRY_BIN movTable;
82 extern REGISTRY_BIN mp3Table;
83 extern REGISTRY_BIN mpegTable;
84 extern REGISTRY_BIN jpegTable;
85 extern REGISTRY_BIN wavTable;
86 extern REGISTRY_BIN aviTable;
87 extern REGISTRY_BIN asfTable;
88 extern REGISTRY_BIN bmpTable;
89 extern REGISTRY_BIN neTable;
90 extern REGISTRY_BIN peTable;
91 extern REGISTRY_BIN leTable;
92 extern REGISTRY_BIN lxTable;
93 extern REGISTRY_BIN nlm386Table;
94 extern REGISTRY_BIN elf386Table;
95 extern REGISTRY_BIN jvmTable;
96 extern REGISTRY_BIN coff386Table;
97 extern REGISTRY_BIN archTable;
98 extern REGISTRY_BIN aoutTable;
99 extern REGISTRY_BIN OldPharLapTable;
100 extern REGISTRY_BIN PharLapTable;
101 extern REGISTRY_BIN rdoffTable;
102 extern REGISTRY_BIN rdoff2Table;
103 extern REGISTRY_BIN sisTable;
104 extern REGISTRY_BIN sisxTable;
105 extern REGISTRY_BIN lmfTable;
106 extern REGISTRY_BIN mzTable;
107 extern REGISTRY_BIN dossysTable;
108 
109 static REGISTRY_BIN *mainBinTable[] =
110 {
111   &neTable,
112   &peTable,
113   &leTable,
114   &lxTable,
115   &nlm386Table,
116   &elf386Table,
117   &jvmTable,
118   &coff386Table,
119   &archTable,
120   &aoutTable,
121   &OldPharLapTable,
122   &PharLapTable,
123   &rdoffTable,
124   &rdoff2Table,
125   &lmfTable,
126   &mzTable,
127   &dossysTable,
128   &sisTable,
129   &sisxTable,
130   &aviTable,
131   &asfTable,
132   &bmpTable,
133   &mpegTable,
134   &jpegTable,
135   &wavTable,
136   &movTable,
137   &rmTable,
138   &mp3Table,
139   &binTable
140 };
141 
142 REGISTRY_BIN *detectedFormat = 0;
143 
144 
145 extern REGISTRY_MODE binMode;
146 extern REGISTRY_MODE textMode;
147 extern REGISTRY_MODE hexMode;
148 extern REGISTRY_MODE disMode;
149 
150 static REGISTRY_MODE *mainModeTable[] =
151 {
152   &textMode,
153   &binMode,
154   &hexMode,
155   &disMode
156 };
157 
158 REGISTRY_MODE *activeMode;
159 static size_t LastMode = sizeof(mainModeTable)/sizeof(REGISTRY_BIN *)+10;
160 
161 static unsigned defMainModeSel = 0;
162 
SelectMode(void)163 tBool SelectMode( void )
164 {
165   const char *modeName[sizeof(mainModeTable)/sizeof(REGISTRY_MODE *)];
166   size_t i,nModes;
167   int retval;
168 
169   nModes = sizeof(mainModeTable)/sizeof(REGISTRY_MODE *);
170   for(i = 0;i < nModes;i++) modeName[i] = mainModeTable[i]->name;
171   retval = SelBoxA(modeName,nModes," Select translation mode: ",defMainModeSel);
172   if(retval != -1)
173   {
174     if(activeMode->term) activeMode->term();
175     activeMode = mainModeTable[retval];
176     if(activeMode->init) activeMode->init();
177     defMainModeSel = retval;
178     return True;
179   }
180   return False;
181 }
182 
init_modes(hIniProfile * ini)183 static void __NEAR__ __FASTCALL__ init_modes( hIniProfile *ini )
184 {
185   if(activeMode->init) activeMode->init();
186   if(activeMode->read_ini) activeMode->read_ini(ini);
187 }
188 
term_modes(void)189 static void __NEAR__ __FASTCALL__ term_modes( void )
190 {
191   if(activeMode->term) activeMode->term();
192 }
193 
__init_biew(void)194 static void __NEAR__ __FASTCALL__ __init_biew( void )
195 {
196    LastOpenFileName = PMalloc(4096);
197    ListFile = PMalloc((ArgCount-1)*sizeof(char *));
198    if((!LastOpenFileName) || (!ListFile))
199    {
200      printm("BIEW initialization failed! Out of memory!");
201      exit(EXIT_FAILURE);
202    }
203 }
204 
__term_biew(void)205 static void __NEAR__ __FASTCALL__ __term_biew( void )
206 {
207    PFREE(LastOpenFileName);
208    PFREE(ListFile);
209 }
210 
QuickSelectMode(void)211 void QuickSelectMode( void )
212 {
213   unsigned nModes;
214   nModes = sizeof(mainModeTable)/sizeof(REGISTRY_MODE *);
215   if(defMainModeSel < nModes - 1) defMainModeSel++;
216   else                            defMainModeSel = 0;
217   if(activeMode->term) activeMode->term();
218   activeMode = mainModeTable[defMainModeSel];
219   if(activeMode->init) activeMode->init();
220 }
221 
MakeShortName(void)222 static void __NEAR__ __FASTCALL__ MakeShortName( void )
223 {
224   unsigned l;
225   unsigned slen = twGetClientWidth(TitleWnd)-54;
226   l = strlen(ArgVector[1]);
227   if(l <= slen) strcpy(shortname,ArgVector[1]);
228   else
229   {
230     strncpy(shortname,ArgVector[1],slen/2 - 3);
231     shortname[slen/2-4] = 0;
232     strcat(shortname,"...");
233     strcat(shortname,&ArgVector[1][l - slen/2]);
234   }
235   __nls_CmdlineToOem((unsigned char *)shortname,strlen(shortname));
236 }
237 
IsNewExe()238 __filesize_t IsNewExe()
239 {
240   __filesize_t ret;
241   char id[2];
242   bmReadBufferEx(id,sizeof(id),0,BM_SEEK_SET);
243 #if 0
244    /*
245       It is well documented technology, but it correctly working
246       only with normal stubs, i.e. when New EXE header is located at
247       offset > 0x40. However, in PC world exists files with wrong
248       stubs, which are normal for Host OS. Hence biew must recognize
249       them as normal New EXE files, despite the fact that DOS can
250       not execute ones.
251       Fixed by Kostya Nosov <k-nosov@yandex.ru>.
252    */
253    if(!( id[0] == 'M' && id[1] == 'Z' &&
254         bmReadWordEx(0x18,BM_SEEK_SET) >= 0x40 &&
255         (ret=bmReadDWordEx(0x3C,BM_SEEK_SET)) > 0x40L)) ret = 0;
256 #endif
257    if(!( id[0] == 'M' && id[1] == 'Z' &&
258         (ret=bmReadDWordEx(0x3C,BM_SEEK_SET)) > 0x02L)) ret = 0;
259    return (__filesize_t)ret;
260 }
261 
AutoDetectMode(void)262 static void __NEAR__ __FASTCALL__ AutoDetectMode( void )
263 {
264   int i,n;
265   n = sizeof(mainModeTable) / sizeof(REGISTRY_MODE *);
266   for(i = 0;i < n;i++)
267   {
268     if(mainModeTable[i]->detect())
269     {
270       defMainModeSel = i;
271       break;
272     }
273   }
274   activeMode = mainModeTable[i];
275   BMSeek(0,BM_SEEK_SET);
276 }
277 
278 struct tagbiewArg
279 {
280   const char key[4];
281   const char *prompt;
282 }biewArg[] =
283 {
284   { "-a", "autodetect mode (default)" },
285   { "-b", "view file in binary mode" },
286   { "-d", "view file in disassembler mode" },
287   { "-h", "view file in hexadecimal mode" },
288   { "-t", "view file in text mode" },
289   { "-s", "change size of file to NNN bytes (create, if file does not exist)" },
290   { "-i", "ignore .ini file (create new)" },
291   { "-?", "display this screen" }
292 };
293 
queryKey(char * arg)294 static int __NEAR__ __FASTCALL__ queryKey(char *arg)
295 {
296   int ret = -1;
297   size_t i;
298   for(i = 0;i < sizeof(biewArg)/sizeof(struct tagbiewArg);i++)
299   {
300     if(strcmp(arg,biewArg[i].key) == 0) { ret = i; break; }
301   }
302   return ret;
303 }
304 
305 static unsigned int  biew_mode     = UINT_MAX;
306 static __filesize_t  new_file_size = FILESIZE_MAX;
307 
ParseCmdLine(void)308 static void __NEAR__ __FASTCALL__ ParseCmdLine( void )
309 {
310   unsigned i;
311   ListFileCount = 0;
312   for(i = 1;i < ArgCount;i++)
313   {
314      int biew_key;
315      biew_key = queryKey(ArgVector[i]);
316      switch(biew_key)
317      {
318        case 0: biew_mode = UINT_MAX; break;
319        case 1: biew_mode = 1; break;
320        case 2: biew_mode = 3; break;
321        case 3: biew_mode = 2; break;
322        case 4: biew_mode = 0; break;
323        case 5:
324 #if (__WORDSIZE >= 32) && !defined(__QNX4__)
325 		new_file_size = strtoull(ArgVector[++i],NULL,10);
326 #else
327 		new_file_size = strtoul(ArgVector[++i],NULL,10);
328 #endif
329 		break;
330        case 6: UseIniFile = False; break;
331        case 7: ListFileCount = 0; return;
332        default: ListFile[ListFileCount++] = ArgVector[i];
333      }
334   }
335   if(ListFileCount) ArgVector[1] = ListFile[0];
336 }
337 
LoadInfo(void)338 static tBool __NEAR__ __FASTCALL__ LoadInfo( void )
339 {
340    MakeShortName();
341    if(new_file_size != FILESIZE_MAX)
342    {
343        bhandle_t handle;
344        if(__IsFileExists(ArgVector[1]) == False) handle = __OsCreate(ArgVector[1]);
345        else
346        {
347          handle = __OsOpen(ArgVector[1],FO_READWRITE | SO_DENYNONE);
348          if(handle == NULL_HANDLE) handle = __OsOpen(ArgVector[1],FO_READWRITE | SO_COMPAT);
349        }
350        if(handle != NULL_HANDLE)
351        {
352            __OsChSize(handle,new_file_size);
353            __OsClose(handle);
354        }
355        else
356        {
357           errnoMessageBox(OPEN_FAIL,NULL,errno);
358           return False;
359        }
360    }
361    if(BMOpen(ArgVector[1]) != 0) return False;
362    if(biew_mode != UINT_MAX)
363    {
364      defMainModeSel = biew_mode;
365      activeMode = mainModeTable[defMainModeSel];
366    }
367    else
368    {
369      if(LastMode >= sizeof(mainModeTable)/sizeof(REGISTRY_MODE *) || !isValidIniArgs()) AutoDetectMode();
370      else
371      {
372        defMainModeSel = LastMode;
373        activeMode = mainModeTable[defMainModeSel];
374      }
375    }
376  return True;
377 }
378 
__detectBinFmt(void)379 static void __NEAR__ __FASTCALL__ __detectBinFmt( void )
380 {
381  unsigned i;
382  if(!bmGetFLength())
383  {
384    detectedFormat = &binTable;
385    return;
386  }
387  for(i = 0;i < sizeof(mainBinTable)/sizeof(REGISTRY_BIN *);i++)
388  {
389    if(mainBinTable[i]->check_format())
390    {
391      detectedFormat = mainBinTable[i];
392      if(detectedFormat->init) detectedFormat->init();
393      break;
394    }
395  }
396  /* Special case: mz initialization */
397  mzTable.check_format();
398 }
399 
PaintTitle(void)400 void PaintTitle( void )
401 {
402  twUseWin(TitleWnd);
403  twFreezeWin(TitleWnd);
404  twGotoXY(1,1);
405  twClrEOL();
406  twPrintF("File : %s",shortname);
407  twGotoXY(twGetClientWidth(TitleWnd)-43,1);
408  twPrintF("Size : %8llu bytes",BMGetFLength());
409  twRefreshWin(TitleWnd);
410 }
411 
MyAtExit(void)412 static void MyAtExit( void )
413 {
414   if(MainWnd) CloseWnd(MainWnd);
415   if(HelpWnd) CloseWnd(HelpWnd);
416   if(TitleWnd) CloseWnd(TitleWnd);
417   if(ErrorWnd) CloseWnd(ErrorWnd);
418   termBConsole();
419   __term_biew();
420   __term_sys();
421 }
422 
isValidIniArgs(void)423 tBool isValidIniArgs( void )
424 {
425   return iniSettingsAnywhere ? True :
426          ArgVector[1] ?
427 	 strcmp(ArgVector[1],LastOpenFileName) == 0 ?
428 	 biew_mode != UINT_MAX && biew_mode != LastMode ?
429 	 False : True : False : False;
430 }
431 
load_ini_info(void)432 static hIniProfile * __NEAR__ __FASTCALL__ load_ini_info( void )
433 {
434   char tmp[20], buf[20];
435   hIniProfile *ini;
436   ini_name = getenv("BIEW_INI");
437   if(!ini_name) ini_name = __get_ini_name("biew");
438   ini = UseIniFile ? iniOpenFile(ini_name,NULL) : NULL;
439   biewReadProfileString(ini,"Biew","Setup","HelpName","",biew_help_name,sizeof(biew_help_name));
440   biewReadProfileString(ini,"Biew","Setup","SkinName","",biew_skin_name,sizeof(biew_skin_name));
441   biewReadProfileString(ini,"Biew","Setup","SyntaxName","",biew_syntax_name,sizeof(biew_syntax_name));
442   biewReadProfileString(ini,"Biew","Search","String","",(char *)search_buff,sizeof(search_buff));
443   search_len = strlen((char *)search_buff);
444   biewReadProfileString(ini,"Biew","Search","Case","off",tmp,sizeof(tmp));
445   biewSearchFlg = stricmp(tmp,"on") == 0 ? SF_CASESENS : SF_NONE;
446   biewReadProfileString(ini,"Biew","Search","Word","off",tmp,sizeof(tmp));
447   if(stricmp(tmp,"on") == 0) biewSearchFlg |= SF_WORDONLY;
448   biewReadProfileString(ini,"Biew","Search","Backward","off",tmp,sizeof(tmp));
449   if(stricmp(tmp,"on") == 0) biewSearchFlg |= SF_REVERSE;
450   biewReadProfileString(ini,"Biew","Search","Template","off",tmp,sizeof(tmp));
451   if(stricmp(tmp,"on") == 0) biewSearchFlg |= SF_WILDCARDS;
452   biewReadProfileString(ini,"Biew","Search","UsePlugin","off",tmp,sizeof(tmp));
453   if(stricmp(tmp,"on") == 0) biewSearchFlg |= SF_PLUGINS;
454   biewReadProfileString(ini,"Biew","Search","AsHex","off",tmp,sizeof(tmp));
455   if(stricmp(tmp,"on") == 0) biewSearchFlg |= SF_ASHEX;
456   biewReadProfileString(ini,"Biew","Browser","LastOpen","",LastOpenFileName,4096);
457   sprintf(buf,"%u",LastMode); /* [dBorca] so that src and dst won't overlap for strncpy */
458   biewReadProfileString(ini,"Biew","Browser","LastMode",buf,tmp,sizeof(tmp));
459   LastMode = (size_t)strtoul(tmp,NULL,10);
460   biewReadProfileString(ini,"Biew","Browser","Offset","0",tmp,sizeof(tmp));
461 #if (__WORDSIZE >= 32) && !defined(__QNX4__)
462   LastOffset = atoll(tmp);
463 #else
464   LastOffset = atol(tmp); /** by watcom */
465 #endif
466   biewReadProfileString(ini,"Biew","Setup","Version","",biew_ini_ver,sizeof(biew_ini_ver));
467   biewReadProfileString(ini,"Biew","Setup","DirectConsole","yes",tmp,sizeof(tmp));
468   if(stricmp(tmp,"yes") == 0) biew_vioIniFlags = __TVIO_FLG_DIRECT_CONSOLE_ACCESS;
469   biewReadProfileString(ini,"Biew","Setup","ForceMono","no",tmp,sizeof(tmp));
470   if(stricmp(tmp,"yes") == 0) biew_twinIniFlags = TWIF_FORCEMONO;
471   biewReadProfileString(ini,"Biew","Setup","Force7Bit","no",tmp,sizeof(tmp));
472   if(stricmp(tmp,"yes") == 0) biew_vioIniFlags |= __TVIO_FLG_USE_7BIT;
473   biewReadProfileString(ini,"Biew","Setup","MouseSens","yes",tmp,sizeof(tmp));
474   if(stricmp(tmp,"yes") == 0) biew_kbdFlags = KBD_NONSTOP_ON_MOUSE_PRESS;
475   biewReadProfileString(ini,"Biew","Setup","IniSettingsAnywhere","no",tmp,sizeof(tmp));
476   if(stricmp(tmp,"yes") == 0) iniSettingsAnywhere = True;
477   biewReadProfileString(ini,"Biew","Setup","FioUseMMF","no",tmp,sizeof(tmp));
478   if(stricmp(tmp,"yes") == 0) fioUseMMF = True;
479   if(!__mmfIsWorkable()) fioUseMMF = False;
480   biewReadProfileString(ini,"Biew","Setup","PreserveTimeStamp","no",tmp,sizeof(tmp));
481   if(stricmp(tmp,"yes") == 0) iniPreserveTime = True;
482   biewReadProfileString(ini,"Biew","Setup","UseExternalProgs","yes",tmp,sizeof(tmp));
483   if(stricmp(tmp,"yes") == 0) iniUseExtProgs = True;
484   biewReadProfileString(ini,"Biew","Setup","Codepage","CP866",biew_codepage,sizeof(biew_codepage));
485   return ini;
486 }
487 
save_ini_info(void)488 static void __NEAR__ __FASTCALL__ save_ini_info( void )
489 {
490   char tmp[20];
491   hIniProfile *ini;
492   search_buff[search_len] = 0;
493   ini = iniOpenFile(ini_name,NULL);
494   biewWriteProfileString(ini,"Biew","Setup","HelpName",biew_help_name);
495   biewWriteProfileString(ini,"Biew","Setup","SkinName",biew_skin_name);
496   biewWriteProfileString(ini,"Biew","Setup","SyntaxName",biew_syntax_name);
497   biewWriteProfileString(ini,"Biew","Setup","Version",BIEW_VERSION);
498   biewWriteProfileString(ini,"Biew","Search","String",(char *)search_buff);
499   biewWriteProfileString(ini,"Biew","Search","Case",biewSearchFlg & SF_CASESENS ? "on" : "off");
500   biewWriteProfileString(ini,"Biew","Search","Word",biewSearchFlg & SF_WORDONLY ? "on" : "off");
501   biewWriteProfileString(ini,"Biew","Search","Backward",biewSearchFlg & SF_REVERSE ? "on" : "off");
502   biewWriteProfileString(ini,"Biew","Search","Template",biewSearchFlg & SF_WILDCARDS ? "on" : "off");
503   biewWriteProfileString(ini,"Biew","Search","UsePlugin",biewSearchFlg & SF_PLUGINS ? "on" : "off");
504   biewWriteProfileString(ini,"Biew","Search","AsHex",biewSearchFlg & SF_ASHEX ? "on" : "off");
505   biewWriteProfileString(ini,"Biew","Browser","LastOpen",ArgVector[1]);
506   sprintf(tmp,"%u",defMainModeSel);
507   biewWriteProfileString(ini,"Biew","Browser","LastMode",tmp);
508 #if (__WORDSIZE >= 32) && !defined(__QNX4__)
509   sprintf(tmp,"%llu",LastOffset);
510 #else
511   sprintf(tmp,"%lu",LastOffset);
512 #endif
513   biewWriteProfileString(ini,"Biew","Browser","Offset",tmp);
514   strcpy(tmp,biew_vioIniFlags & __TVIO_FLG_DIRECT_CONSOLE_ACCESS ? "yes" : "no");
515   biewWriteProfileString(ini,"Biew","Setup","DirectConsole",tmp);
516   strcpy(tmp,biew_twinIniFlags & TWIF_FORCEMONO ? "yes" : "no");
517   biewWriteProfileString(ini,"Biew","Setup","ForceMono",tmp);
518   strcpy(tmp,(biew_vioIniFlags & __TVIO_FLG_USE_7BIT) == __TVIO_FLG_USE_7BIT ? "yes" : "no");
519   biewWriteProfileString(ini,"Biew","Setup","Force7Bit",tmp);
520   strcpy(tmp,biew_kbdFlags & KBD_NONSTOP_ON_MOUSE_PRESS ? "yes" : "no");
521   biewWriteProfileString(ini,"Biew","Setup","MouseSens",tmp);
522   strcpy(tmp,iniSettingsAnywhere ? "yes" : "no");
523   biewWriteProfileString(ini,"Biew","Setup","IniSettingsAnywhere",tmp);
524   strcpy(tmp,fioUseMMF ? "yes" : "no");
525   biewWriteProfileString(ini,"Biew","Setup","FioUseMMF",tmp);
526   strcpy(tmp,iniPreserveTime ? "yes" : "no");
527   biewWriteProfileString(ini,"Biew","Setup","PreserveTimeStamp",tmp);
528   strcpy(tmp,iniUseExtProgs ? "yes" : "no");
529   biewWriteProfileString(ini,"Biew","Setup","UseExternalProgs",tmp);
530   biewWriteProfileString(ini,"Biew","Setup","Codepage",biew_codepage);
531   if(activeMode->save_ini) activeMode->save_ini(ini);
532   udnTerm(ini);
533   iniCloseFile(ini);
534 }
535 
536 static FTime ftim;
537 static tBool ftim_ok = False;
538 
ShowUsage(void)539 static void __FASTCALL__ ShowUsage(void) {
540     unsigned evt,i,nln,h,y;
541     TWindow *win;
542     nln = sizeof(biewArg)/sizeof(struct tagbiewArg);
543     h = nln+4;
544     y = tvioHeight/2-h/2;
545     win = WindowOpen(2,y,tvioWidth-1,y+h,TWS_NONE | TWS_NLSOEM);
546     if(!win) goto done;
547     twSetTitleAttr(win,BIEW_VER_MSG,TW_TMODE_CENTER,error_cset.border);
548     twCentredWin(win,NULL);
549     twSetColorAttr(error_cset.main);
550     twSetFrameAttr(win,TW_DOUBLE_FRAME,error_cset.border);
551     twSetFooterAttr(win," Press [ ESC ] to quit ",TW_TMODE_RIGHT,error_cset.border);
552     twClearWin();
553     twGotoXY(1,1);
554     twPutS(" Usage: biew [OPTIONS] file...");
555     for(i = 0;i < nln;i++)
556     {
557 	twGotoXY(1,4+i);
558 	twPrintF("  %s     %s\n",biewArg[i].key,biewArg[i].prompt);
559     }
560     twShowWin(win);
561     do {
562 	evt = GetEvent(NULL,NULL,ErrorWnd);
563     }while(!(evt == KE_ESCAPE || evt == KE_F(10) || evt == KE_ENTER));
564     twDestroyWin(win);
565     done:
566     termBConsole();
567 }
568 
main(int argc,char * argv[])569 int main( int argc, char *argv[] )
570 {
571  hIniProfile *ini;
572  tBool skin_err;
573  int retval;
574 #ifndef NDEBUG
575 #ifdef RLIMIT_CORE
576   {
577     /* on many systems default coresize is 0.
578        Enable any coresize here. */
579     struct rlimit rl;
580     getrlimit(RLIMIT_CORE,&rl);
581     rl.rlim_cur = rl.rlim_max;
582     setrlimit(RLIMIT_CORE,&rl);
583   }
584 #endif
585 #endif
586  ArgCount = argc;
587  ArgVector = argv;
588  __init_sys();
589  __init_biew();
590  ini = load_ini_info();
591  skin_err = csetReadIniFile(biew_skin_name);
592  initBConsole(biew_vioIniFlags,biew_twinIniFlags);
593  if(ArgCount < 2) goto show_usage;
594  ParseCmdLine();
595  if(!ListFileCount)
596  {
597    /** print usage message */
598     size_t i;
599     show_usage:
600     ShowUsage();
601     printm("\n"BIEW_VER_MSG"\n");
602     printm(" Usage: biew [OPTIONS] file...\n\n");
603     for(i = 0;i < sizeof(biewArg)/sizeof(struct tagbiewArg);i++)
604     {
605       printm("  %s\t%s\n",biewArg[i].key,biewArg[i].prompt);
606     }
607     printm("\n");
608     return EXIT_FAILURE;
609  }
610  udnInit(ini);
611  ErrorWnd = WindowOpen(1,1,50,16,TWS_NONE | TWS_NLSOEM);
612  if(ErrorWnd) twSetTitleAttr(ErrorWnd," Error ",TW_TMODE_CENTER,error_cset.border);
613  else { printm("fatal error: can't create window"); return EXIT_FAILURE; }
614  twCentredWin(ErrorWnd,NULL);
615  twSetColorAttr(error_cset.main);
616  twSetFrameAttr(ErrorWnd,TW_DOUBLE_FRAME,error_cset.border);
617  HelpWnd = WindowOpen(1,tvioHeight,tvioWidth,tvioHeight,TWS_NLSOEM);
618  twSetColorAttr(prompt_cset.digit);
619  twClearWin();
620  twShowWin(HelpWnd);
621  if(strcmp(biew_ini_ver,BIEW_VERSION) != 0) Setup();
622  TitleWnd = WindowOpen(1,1,tvioWidth,1,TWS_NONE);
623  twSetColorAttr(title_cset.main);
624  twClearWin();
625  twShowWin(TitleWnd);
626  activeMode = mainModeTable[1];
627  atexit(MyAtExit);
628  retval = EXIT_SUCCESS;
629  if(skin_err)
630  {
631    char sout[256];
632    sprintf(sout,"Error in skin file detected: '%s'",last_skin_error);
633    ErrMessageBox(sout,NULL);
634  }
635  /* We must do it before opening a file because of some RTL has bug
636     when are trying to open already open file with no sharing access */
637  ftim_ok = __OsGetFTime(ArgVector[1],&ftim);
638  if(!LoadInfo())
639  {
640    if(ini) iniCloseFile(ini);
641    retval = EXIT_FAILURE;
642    goto Bye;
643  }
644  __detectBinFmt();
645  init_modes(ini);
646  init_addons();
647  init_sysinfo();
648  if(ini) iniCloseFile(ini);
649  MainWnd = WindowOpen(1,2,tvioWidth,tvioHeight-1,TWS_NONE);
650  twSetColorAttr(browser_cset.main);
651  twClearWin();
652  PaintTitle();
653  if(!isValidIniArgs() || LastOffset > BMGetFLength()) LastOffset = 0;
654  twShowWin(MainWnd);
655  MainLoop();
656  LastOffset = BMGetCurrFilePos();
657  save_ini_info();
658  term_sysinfo();
659  term_addons();
660  term_modes();
661  if(detectedFormat->destroy) detectedFormat->destroy();
662  BMClose();
663  if(iniPreserveTime && ftim_ok) __OsSetFTime(ArgVector[1],&ftim);
664  Bye:
665  return retval;
666 }
667 
NewSource(void)668 tBool NewSource( void )
669 {
670   int i;
671   tBool ret;
672   unsigned j,freq;
673   static int prev_file;
674   char ** nlsListFile;
675   nlsListFile = (char **)PMalloc(ListFileCount*sizeof(char *));
676   if(nlsListFile)
677   {
678     for(j = 0;j < ListFileCount;j++)
679     {
680       nlsListFile[j] = PMalloc(strlen(ListFile[j])+1);
681       if(!nlsListFile[j]) break;
682     }
683   }
684   else { MemOutBox("Initializing List of File\n"); return 0; }
685   for(freq = 0;freq < j;freq++)
686   {
687     unsigned ls;
688     ls = strlen(ListFile[freq]);
689     memcpy(nlsListFile[freq],ListFile[freq],ls+1);
690     __nls_CmdlineToOem((unsigned char *)nlsListFile[freq],ls);
691   }
692   i = SelBoxA((const char **)nlsListFile,j," Select new file: ",prev_file);
693   ret = 0;
694   for(freq = 0;freq < j;freq++) PFree(nlsListFile[freq]);
695   PFree(nlsListFile);
696   if(i != -1)
697   {
698     if(iniPreserveTime && ftim_ok) __OsSetFTime(ArgVector[1],&ftim);
699     BMClose();
700     ftim_ok = __OsGetFTime(ListFile[i],&ftim);
701     if(BMOpen(ListFile[i]) == 0)
702     {
703       ArgVector[1] = ListFile[i];
704       if(detectedFormat->destroy) detectedFormat->destroy();
705       if(activeMode->term) activeMode->term();
706       MakeShortName();
707       __detectBinFmt();
708       if(activeMode->init) activeMode->init();
709       ret = True;
710     }
711     else
712     {
713        if(BMOpen(ArgVector[1]) != 0)
714        {
715          exit(EXIT_FAILURE);
716        }
717        if(detectedFormat->destroy) detectedFormat->destroy();
718        if(activeMode->term) activeMode->term();
719        MakeShortName();
720        __detectBinFmt();
721        if(activeMode->init) activeMode->init();
722        ret = False;
723     }
724   }
725   return ret;
726 }
727 
biewReadProfileString(hIniProfile * ini,const char * section,const char * subsection,const char * _item,const char * def_value,char * buffer,unsigned cbBuffer)728 unsigned __FASTCALL__ biewReadProfileString(hIniProfile *ini,
729                                const char *section,
730                                const char *subsection,
731                                const char *_item,
732                                const char *def_value,
733                                char *buffer,
734                                unsigned cbBuffer)
735 {
736   return UseIniFile ? iniReadProfileString(ini,section,subsection,
737                                            _item,def_value,buffer,cbBuffer)
738                     : 1;
739 }
740 
biewWriteProfileString(hIniProfile * ini,const char * section,const char * subsection,const char * item,const char * value)741 tBool __FASTCALL__ biewWriteProfileString(hIniProfile *ini,
742                                           const char *section,
743                                           const char *subsection,
744                                           const char *item,
745                                           const char *value)
746 {
747   return iniWriteProfileString(ini,section,subsection,item,value);
748 }
749