Update the changelog
[opencv] / apps / Hawk / Hawk.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/// Hawk.cpp : Defines the class behaviors for the application.
41 //
42
43 #include "stdafx.h"
44 #include "Hawk.h"
45
46 #include "MainFrm.h"
47 #include "ChildFrm.h"
48 #include "HawkDoc.h"
49 #include "HawkView.h"
50 #include "LogView.h"
51
52 #include <io.h>
53 #include <fcntl.h>
54 #include <process.h>
55 #include <signal.h>
56 extern "C"
57 {
58 #include "wrap.h"
59 }
60
61 #include <fstream>
62 //#include "eicdllwrap.h"
63
64 #ifdef _DEBUG
65 #define new DEBUG_NEW
66 #undef THIS_FILE
67 static char THIS_FILE[] = __FILE__;
68 #endif
69
70 char* cline = "-D_EiC";
71 char* std_inc[] = {"assert", "ctype", "errno", /*"float", "limits",*/ "math",
72             "stdarg", "stddef", "stdio", "stdlib", "string", "time"};
73
74 extern "C"
75 {
76 #include "CVEiCL\EiC\src\eic.h"
77 #include "CVEiCL\EiC\src\typemod.h"
78 #include "CVEiCL\EiC\src\global.h"
79 #include "CVEiCL\EiC\src\func.h"
80 #include "CVEiCL\EiC\src\error.h"
81 #include "CVEiCL\EiC\src\symbol.h"
82 #include "eicio.h"
83 }
84 #include "HighGUI.h"
85 extern "C" {
86     void EiC_init_EiC(void);
87     void stdClib(void);
88     void module_ippiwrap(void);
89     void module_ipl();
90     void EiC_switches(char*);
91     void module_highguiwrap();
92     void set_highgui_errlevel(errlevel_t level);
93     void set_highgui_mark(jmp_buf* mark);
94     symentry_t * EiC_lookup(char nspace, char *id);
95     void EiC_xalloc_CleanUp(size_t, size_t);
96
97     extern void (*EiC_messageDisplay)(char*);
98 };
99 void set_hawk_errlevel(errlevel_t level);
100 void set_hawk_mark(jmp_buf* mark);
101 void module_convertwrap();
102 void set_eic_errlevel(errlevel_t level);
103 void set_eic_mark(jmp_buf* mark);
104
105 int FindStringInArray(const CStringArray& array, const CString& string)
106 {
107     for(int i = 0; i < array.GetSize(); i++)
108     {
109         if(strcmp(LPCTSTR(array.GetData()[i]), LPCTSTR(string)) == 0)
110         {
111             return i;
112         }
113     }
114
115     return -1;
116 }
117
118 template<> void AFXAPI DestructElements<CMenu*> (CMenu** pElements, int nCount)
119 {
120     for(int i = 0; i < nCount; i++)
121         delete pElements[i];
122 }
123
124 template<> void AFXAPI DestructElements<plugin_t> (plugin_t* pElements, int nCount)
125 {
126     for(int i = 0; i < nCount; i++)
127         delete pElements[i].m_functions;
128 }
129
130
131 /////////////////////////////////////////////////////////////////////////////
132 // CHawkApp
133
134 BEGIN_MESSAGE_MAP(CHawkApp, CWinApp)
135         //{{AFX_MSG_MAP(CHawkApp)
136         ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
137                 // NOTE - the ClassWizard will add and remove mapping macros here.
138                 //    DO NOT EDIT what you see in these blocks of generated code!
139         //}}AFX_MSG_MAP
140         // Standard file based document commands
141         ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
142         ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
143         // Standard print setup command
144         ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
145 END_MESSAGE_MAP()
146
147 /////////////////////////////////////////////////////////////////////////////
148 // CHawkApp construction
149
150 CHawkApp::CHawkApp()
151 {
152     m_eicOut.write = m_eicOut.read = NULL;
153     m_eicErr.write = m_eicErr.read = NULL;
154     m_mainMenu.m_hMenu = NULL;
155     m_errlevel = unsafe;
156     m_sbRun = TRUE;
157     m_dsMutex = NULL;
158
159     m_pipeDataSize = 0;
160 }
161
162 CHawkApp::~CHawkApp()
163 {
164     for(int i = 0; i < m_funcDialogs.GetSize(); i++)
165     {
166         delete (CFuncDialog*)m_funcDialogs.GetData()[i];
167     }
168 }
169
170 /////////////////////////////////////////////////////////////////////////////
171 // The one and only CHawkApp object
172
173 CHawkApp theApp;
174
175 /////////////////////////////////////////////////////////////////////////////
176 // CHawkApp initialization
177
178 BOOL CHawkApp::InitInstance()
179 {
180         AfxEnableControlContainer();
181
182         // Standard initialization
183         // If you are not using these features and wish to reduce the size
184         //  of your final executable, you should remove from the following
185         //  the specific initialization routines you do not need.
186
187 #ifdef _AFXDLL
188         Enable3dControls();                     // Call this when using MFC in a shared DLL
189 #else
190         Enable3dControlsStatic();       // Call this when linking to MFC statically
191 #endif
192
193         // Change the registry key under which our settings are stored.
194         // TODO: You should modify this string to be something appropriate
195         // such as the name of your company or organization.
196         SetRegistryKey(_T("Intel"));
197
198         LoadStdProfileSettings();  // Load standard INI file options (including MRU)
199
200         // Register the application's document templates.  Document templates
201         //  serve as the connection between documents, frame windows and views.
202
203         CMultiDocTemplate* pDocTemplate;
204         pDocTemplate = new CMultiDocTemplate(
205                 IDR_HAWTYPE,
206                 RUNTIME_CLASS(CHawkDoc),
207                 RUNTIME_CLASS(CChildFrame), // custom MDI child frame
208                 RUNTIME_CLASS(CHawkView));
209         AddDocTemplate(pDocTemplate);
210
211         pDocTemplate = new CMultiDocTemplate(
212                 IDR_LOGTYPE,
213                 RUNTIME_CLASS(CDocument),
214                 RUNTIME_CLASS(CChildFrame), // custom MDI child frame
215                 RUNTIME_CLASS(CLogView));
216         AddDocTemplate(pDocTemplate);
217
218
219         // create main MDI Frame window
220         CMainFrame* pMainFrame = new CMainFrame;
221         if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
222                 return FALSE;
223         m_pMainWnd = pMainFrame;
224
225         // Parse command line for standard shell commands, DDE, file open
226         CCommandLineInfo cmdInfo;
227         ParseCommandLine(cmdInfo);
228
229         // Dispatch commands specified on the command line
230         if (!ProcessShellCommand(cmdInfo))
231                 return FALSE;
232
233         // The main window has been initialized, so show and update it.
234         pMainFrame->ShowWindow(m_nCmdShow);
235         pMainFrame->UpdateWindow();
236
237     // Creating a headband
238     m_headband.Create(IDD_HEADBAND, AfxGetMainWnd());
239
240     // Centering a headband
241     CRect rect, drect, nrect;
242     AfxGetMainWnd()->GetWindowRect(&rect);
243     m_headband.GetWindowRect(&drect);
244     CPoint DUpLeft = CPoint((rect.Width() - drect.Width())/2, (rect.Height() - drect.Height())/2);
245     drect.OffsetRect(DUpLeft);
246     m_headband.MoveWindow(&drect);
247     m_headband.ShowWindow(SW_SHOW);
248     m_headband.UpdateWindow();
249
250     InitCommonControls();
251     
252         BOOL ret = InitEiC();
253     m_headband.DestroyWindow();
254     
255     return ret;
256 }
257
258
259 /////////////////////////////////////////////////////////////////////////////
260 // CAboutDlg dialog used for App About
261
262 class CAboutDlg : public CDialog
263 {
264 public:
265         CAboutDlg();
266
267 // Dialog Data
268         //{{AFX_DATA(CAboutDlg)
269         enum { IDD = IDD_ABOUTBOX };
270         //}}AFX_DATA
271
272         // ClassWizard generated virtual function overrides
273         //{{AFX_VIRTUAL(CAboutDlg)
274         protected:
275         virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
276         //}}AFX_VIRTUAL
277
278 // Implementation
279 protected:
280         //{{AFX_MSG(CAboutDlg)
281                 // No message handlers
282         //}}AFX_MSG
283         DECLARE_MESSAGE_MAP()
284 };
285
286 CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
287 {
288         //{{AFX_DATA_INIT(CAboutDlg)
289         //}}AFX_DATA_INIT
290 }
291
292 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
293 {
294         CDialog::DoDataExchange(pDX);
295         //{{AFX_DATA_MAP(CAboutDlg)
296         //}}AFX_DATA_MAP
297 }
298
299 BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
300         //{{AFX_MSG_MAP(CAboutDlg)
301                 // No message handlers
302         //}}AFX_MSG_MAP
303 END_MESSAGE_MAP()
304
305 // App command to run the dialog
306 void CHawkApp::OnAppAbout()
307 {
308         CAboutDlg aboutDlg;
309         aboutDlg.DoModal();
310 }
311
312 /////////////////////////////////////////////////////////////////////////////
313 // CHawkApp message handlers
314
315 /* My version of printf function... */
316 int eic_hawk_charout(int c, void* buf)
317 {
318     CHawkApp* app = (CHawkApp*)AfxGetApp();
319 //    if(app->m_pipeDataSize > )
320     CString& str = *(CString*)buf;
321     char text = (char)c;
322     str += CString(text);
323
324 /*    if(WaitForSingleObject(app->m_printfMutex, INFINITE) != WAIT_OBJECT_0)
325     {
326         ASSERT(0);
327         v.ival = 0;
328         return v;
329     };*/
330     return 1;
331 }
332
333 extern "C"
334 {
335 int _eicUprintf(int (*output)(int, void*), void *arg, char *fmt, arg_list ap);
336 }
337
338 static val_t eic_hawk_printf()
339 {
340     CHawkApp* app = (CHawkApp*)AfxGetApp();
341     CMainFrame* frame = (CMainFrame*)AfxGetMainWnd();
342
343     val_t v;
344     arg_list ag = getargs();
345     char *fmt = (char*)nextarg(ag,ptr_t).p;
346     CString buf;
347     v.ival = _eicUprintf(eic_hawk_charout, (void*)&buf, fmt, ag);
348
349     frame->m_pRunDoc->GetLogView()->AddString(LPCTSTR(buf));
350 //    ReleaseMutex(app->m_printfMutex);
351     
352     return v;
353 }
354
355 static void _Hawk_MessageDisplay(char* str)
356 {
357     AfxMessageBox(str);
358 }
359
360 /*static val_t eic_Hawk_uni_wrap()
361 {
362     val_t v;
363
364     uni_wrap(stub_f(arg(0, getargs(), ptr_t).p), 
365         (int*)arg(1, getargs(), ptr_t).p,
366         (char*)arg(2, getargs(), ptr_t).p,
367         (char*)&v);
368
369     return v;
370 }*/
371
372 BOOL CHawkApp::InitEiC()
373 {
374     InitEiCHandles();    
375
376     // Initialize the module's path string
377     InitModulePath();
378
379     SetStatusString("Initializing EiC...");
380     EiC_init_EiC();
381     char _argv[] = "";
382     char *_pargv[2] = {_argv, 0};
383     EiC_startEiC(1, _pargv);
384     SetStatusString("Initializing standard C library...");
385     stdClib();
386     EiC_add_builtinfunc("printf", eic_hawk_printf);
387 /*
388     // Setup the signals messaging
389     EiC_messageDisplay = _Hawk_MessageDisplay;*/
390
391     // Initializing EiC plugin functions
392     SetStatusString("Initializing HighGUI library...");
393     module_highguiwrap();
394     SetStatusString("Initializing converters library...");
395     module_convertwrap();
396     LoadPlugins();
397 /*
398     EiC_parseString("typedef struct _a {double v;int w;char t;} a;");
399     EiC_parseString("int f(a b) {return b.w;};");
400     EiC_parseString("struct a b;f(b);\\int e");
401     EiC_parseString("struct a c;");
402
403     EiC_parseString("struct _b {char t;};");
404     EiC_parseString("struct _a b;");
405     symentry_t* sym = EiC_lookup(1, "a");
406     struct_t* s = (struct_t*)sym->type->nxt->u.inf;
407     func_t* funcDesc = (func_t*)sym->type->u.inf;
408     parm_t* parmDesc = funcDesc->parm;
409     s = (struct_t*)parmDesc->type->u.inf;*/
410
411     // Initializing HighGUI
412     cvInitSystem(0,0); // SetInstance(AfxGetApp()->m_hInstance);
413     cvAddSearchPath(LPCTSTR(m_modulePath + CString("bitmaps")));
414     cvAddSearchPath(LPCTSTR(m_modulePath + CString("..\\..\\..\\apps\\Hawk\\bitmaps")));
415     AddVideoPath(m_modulePath + CString("Video"));
416     AddVideoPath(m_modulePath + CString("..\\..\\..\\apps\\Hawk\\Video"));
417
418     // Initializing EiC
419     EiC_switches(cline);
420
421     // Define the universal wrapper function
422     EiC_parseString("void _Hawk_uniwrap(void*,int*,char*,int*, void*);");
423
424     // First lets find the wrappers directory
425     m_wrappersPath = m_modulePath + CString("wrappers");
426     CString inc = CString(":-I ") + m_wrappersPath;
427 //    EiC_parseString(const_cast<char*>(LPCTSTR(inc)));
428     inc += CString("\\std");
429 //    EiC_parseString(const_cast<char*>(LPCTSTR(inc)));
430
431     EiC_parseString("#pragma push_unsafeptr");
432
433     /* Make the source compatible with C standard */
434     EiC_parseString("#define __stdcall");
435     EiC_parseString("#define __cdecl");
436     EiC_parseString("#define __declspec(a)");
437     EiC_parseString("typedef struct{int l,h;} __int64;");
438
439     /* Definitions for IPL */
440     /*EiC_parseString("#define IPL_WINDOWS");*/
441     /*EiC_parseString("#define IPLAPI(type, name, arg) type name arg;");*/
442
443     /* Definitions for OpenCV */
444     EiC_parseString("#define CV_INLINE");
445     /*EiC_parseString("#define HAVE_IPL");*/
446     
447     /* Temporary! Inserted because of EiC bug. */
448     //EiC_parseString("struct CvSubdiv2DPoint;");
449
450     /* Enum all include dirs and headers */
451     char curDir[_MAX_PATH];
452     GetCurrentDirectory(_MAX_PATH, curDir);
453     SetCurrentDirectory(m_wrappersPath);
454     EnumHeaders(m_wrappersPath);
455
456     // Set include directories
457     for(int i = 0; i < m_includeDirs.size(); i++)
458     {
459         EiC_parseString(":-I %s", m_includeDirs[i].c_str());
460     }
461
462     // Include headers
463     for(i = 0; i < m_includeFiles.size(); i++)
464     {
465         string str;
466         str = string("Parsing header ") + m_includeFiles[i] + "...";
467         SetStatusString(str.c_str());
468         Attach(m_includeFiles[i]);
469     }
470     SetCurrentDirectory(curDir);
471
472     char textBuffer[2048];
473     rewind(m_eicErr.read);
474     int err = _read(_fileno(m_eicErr.read), textBuffer, 2047);
475     if(err > 1)
476     {
477         textBuffer[err] = 0;
478         AfxMessageBox(textBuffer);
479     }
480     _chsize(_fileno(m_eicErr.read), 0);
481 #ifdef NDEBUG
482     const char* libName = "cv.dll";
483 #else
484     const char* libName = "cvd.dll";
485 #endif
486     
487     LoadModuleFunctions(libName, "OpenCV");
488
489 #ifdef NDEBUG
490     const char* auxlibName = "cvaux.dll";
491 #else
492     const char* auxlibName = "cvauxd.dll";
493 #endif
494     
495     LoadModuleFunctions(auxlibName, "OpenCVAux");
496
497     
498 #ifdef NDEBUG
499     const char* hglibName = "HighGUI.dll";
500 #else
501     const char* hglibName = "HighGUId.dll";
502 #endif
503     
504     LoadModuleFunctions(hglibName, "OpenCVHighGUI");
505
506
507     LoadModules();
508
509     EiC_parseString("#pragma pop_ptr");
510
511     SetStatusString("Almost done...");
512     // Initialize context menus
513     InitPopupMenu();
514     InitPopupDialogs();
515     // Update error marks
516     UpdateMark();
517     // Loading Hawk configuration
518     m_errlevel = (errlevel_t)GetProfileInt("Configuration", "Error level", (int)unsafe);
519     SetErrLevel(m_errlevel);
520     m_sbRun = GetProfileInt("Configuration", "Autosave before run", TRUE);
521
522     // Remember EiC's state
523     EiC_parseString(":reset here");
524
525     return TRUE;
526 }
527
528 BOOL CHawkApp::InitModulePath()
529 {
530     // Find the full path for this executable
531     HMODULE hnd = GetModuleHandle(LPCTSTR(m_pszExeName));
532     char buff[128];
533     GetModuleFileName(hnd, buff, 128);
534
535     char drive[_MAX_DRIVE], dir[_MAX_DIR], fName[_MAX_FNAME], ext[_MAX_EXT];
536     _splitpath(buff, drive, dir, fName, ext);
537
538     m_modulePath.Format("%s%s",drive,dir);
539
540     return TRUE;
541 }
542
543 BOOL CHawkApp::FindAndAttach(LPCTSTR path, LPCTSTR fileName)
544 {
545     char buffer[2048];
546     char* pFinal;
547
548     int length = SearchPath(path, fileName, ".h", 2048, buffer, &pFinal);
549     if(length > 0)
550     {
551         return Attach(buffer);
552     }
553     else
554     {
555         CString str = CString("Wrapper file ") + CString(fileName) + 
556                 CString(".h has not been found!\n") + 
557                 CString("Functions declared in the file will not be ") + 
558                 CString("available during current session.");
559         AfxMessageBox(str);
560         return FALSE;
561     }
562 }
563
564
565 LPCTSTR CHawkApp::GetModulePath()
566 {
567         return LPCTSTR(m_modulePath);
568 }
569
570 void CHawkApp::LoadPlugins()
571 {
572     long searchHandle;
573     BOOL isAnother = TRUE;
574     _finddata_t data;
575     CString dir, str;
576     dir = m_modulePath + CString("\\plugins\\");
577     str = dir + CString("*.dll");
578
579     searchHandle = _findfirst(LPCTSTR(str), &data);
580     if(searchHandle == -1)
581     {
582         return;
583     }
584
585     while(isAnother)
586     {
587         CString str;
588         str.Format("Loading %s plugin...", data.name);
589         SetStatusString(LPCTSTR(str));
590         HMODULE module;
591         module = LoadLibrary(LPCTSTR(dir + CString(data.name)));
592         if(module && LoadPluginFunctions(module))
593         {
594             CString str(data.name);
595             m_plugins.GetData()[m_plugins.GetSize() - 1].m_path = str.Left(str.GetLength() - 4);
596         }
597         else
598         {
599             CString str;
600             str.Format("Failed to load %s plugin!", data.name);
601             AfxMessageBox(str);
602
603             if(module)
604             {
605                 FreeLibrary(module);
606             }
607         }
608
609         isAnother = !_findnext(searchHandle, &data);
610     }
611 }
612
613 BOOL CHawkApp::LoadPluginFunctions(HMODULE module)
614 {
615     plugin_t plugin;
616
617     // Check if this is Hawk dll
618     plugin.m_GetInfo = (void (*)(plugin_info*))GetProcAddress(module, "PluginGetInfo");
619     plugin.m_SetEiCStack = (void (*)(AR_t**))GetProcAddress(module, "SetEiCStack");
620     plugin.m_SetEiCCallback = (void (*)(void(*)(void*)))GetProcAddress(module, "SetEiCCallback");
621     plugin.m_GetFunctions = (void (*)(char***, val_t (***)(void), int*))
622         GetProcAddress(module, "GetFunctions");
623     plugin.m_SetErrLevel = (void(*)(errlevel_t))GetProcAddress(module, "SetErrLevel");
624     plugin.m_SetErrMark = (void(*)(jmp_buf*))GetProcAddress(module, "SetErrMark");
625     if(!plugin.m_SetEiCStack || !plugin.m_GetFunctions || !plugin.m_SetEiCCallback ||
626         !plugin.m_SetErrLevel || !plugin.m_SetErrMark)
627     {
628         return FALSE;
629     }
630
631     // Get the plugin info
632     plugin.m_GetInfo(&plugin.m_info);
633     
634     // Set eic's stack
635     plugin.m_SetEiCStack(AR);
636     plugin.m_SetEiCCallback(EiC_callBack);
637     plugin.m_SetErrMark(&m_mark);
638
639     // Get all functions wrappers
640     char** func_names;
641     val_t(**funcs)(void);
642     int funcs_count;
643     plugin.m_GetFunctions(&func_names, &funcs, &funcs_count);
644
645     // Register functions in EiC and update names array
646     CStringArray* names = new CStringArray;
647     for(int i = 0; i < funcs_count; i++)
648     {
649         if(funcs[i])
650         {
651             EiC_add_builtinfunc(func_names[i], funcs[i]);
652             for(int j = 0;; j++)
653             {
654                 if(j < names->GetSize())
655                 {
656                     if(strcmp(func_names[i], LPCTSTR(names->GetData()[j])) < 0)
657                     {
658                         names->InsertAt(j, CString(func_names[i]));
659                         break;
660                     }
661                 }
662                 else
663                 {
664                     names->Add(CString(func_names[i]));
665                     break;
666                 }
667             }
668         }
669     }
670     plugin.m_functions = names;
671     plugin.m_handle = module;
672     m_plugins.Add(plugin);
673
674     return TRUE;
675 }
676
677 void CHawkApp::InitPopupMenu()
678 {
679     m_mainMenu.CreatePopupMenu();
680     for(int i = 0; i < m_plugins.GetSize(); i++)
681     {
682         m_mainMenu.AppendMenu(MF_STRING | (i%30 || !i ? 0 : MF_MENUBARBREAK), 
683             (i + 1)<<16, LPCTSTR(m_plugins.GetData()[i].m_info.name));
684     }
685 }
686
687 CMenu* CHawkApp::GetContextMenu()
688 {
689     return &m_mainMenu;
690 }
691
692 CStringArray* CHawkApp::GetFunctions(int i)
693 {
694     return m_plugins.GetData()[i].m_functions;
695 }
696
697 void CHawkApp::ExitEiC()
698 {
699     for(int i = 0; i < m_eicFiles.GetSize(); i++)
700     {
701         char str[8192];
702         sprintf(str, ":clear %s", LPCTSTR(m_eicFiles[i]));
703         EiC_parseString(str);
704     }
705
706     EiC_parseString(":clear ::EiC::");
707
708     EiC_xalloc_CleanUp(0, UINT_MAX);
709 }
710
711 int CHawkApp::ExitInstance() 
712 {
713     OleUninitialize();
714     ExitEiC();  
715
716     // Save Hawk configuration
717     WriteProfileInt("Configuration", "Error level", m_errlevel);
718         return CWinApp::ExitInstance();
719 }
720
721 void CHawkApp::SetErrLevel(errlevel_t level)
722 {
723     m_errlevel = level;
724     set_highgui_errlevel(level);
725     set_hawk_errlevel(level);
726     set_eic_errlevel(level);
727     for(int i = 0; i < m_plugins.GetSize(); i++)
728     {
729         if(m_plugins.GetData()[i].m_SetErrLevel)
730             m_plugins.GetData()[i].m_SetErrLevel(level);
731     }
732 }
733
734 errlevel_t CHawkApp::GetErrLevel()
735 {
736     return m_errlevel;
737 }
738
739 void CHawkApp::UpdateMark(jmp_buf *mark)
740 {
741     jmp_buf* realmark = mark ? mark : &m_mark;
742
743     set_highgui_mark(realmark);
744     set_hawk_mark(realmark);
745     set_eic_mark(realmark);
746     for(int i = 0; i < m_plugins.GetSize(); i++)
747     {
748         if(m_plugins.GetData()[i].m_SetErrMark)
749             m_plugins.GetData()[i].m_SetErrMark(realmark);
750     }
751 }
752
753 BOOL CHawkApp::GetSBRun()
754 {
755     return m_sbRun;
756 }
757
758 void CHawkApp::SetSBRun(BOOL sbRun)
759 {
760     m_sbRun = sbRun;
761 }
762
763 void CHawkApp::SetStatusString(LPCTSTR str)
764 {
765     m_headband.SetDlgItemText(IDC_STATUS, str);
766 }
767
768 void CHawkApp::AddVideoPath(const CString& path)
769 {
770     m_videoPath.Add(path);
771 }
772
773 const CStringArray& CHawkApp::GetVideoPath()
774 {
775     return m_videoPath;
776 }
777
778 BOOL CHawkApp::InitEiCHandles()
779 {/*
780     // Open a pipe to read EiC's stdout
781     int handles[2];
782
783     // Creating a pipe for eicout:
784     int error = _pipe(handles, 9128, _O_TEXT);
785     if(error)
786     {
787         AfxMessageBox("Failed to create an output buffer for EiC...");
788         return FALSE;
789     }
790
791     m_eicOut.read = fdopen(handles[0], "r");
792     m_eicOut.write = fdopen(handles[1], "w");
793
794     // Creating a pipe for eicerr:
795     error = _pipe(handles, 9128, _O_BINARY);
796     if(error)
797     {
798         AfxMessageBox("Failed to create an output buffer for EiC...");
799         return FALSE;
800     }
801
802     m_eicErr.read = fdopen(handles[0], "r");
803     m_eicErr.write = fdopen(handles[1], "w");*/
804
805     m_printfMutex = CreateMutex(NULL, FALSE, "EiC stdout");
806 //    m_eicOut.read = m_eicOut.write = freopen("__stdout.temp", "w+", stdout);
807     _fmode = _O_BINARY;
808     char* tn = tempnam(GetModulePath(), "__eiCErrTemp.");
809     m_EiCErrFile = CString(tn);
810     free(tn);
811     m_eicErr.read = freopen(LPCTSTR(m_EiCErrFile), "w+", stderr);
812     m_eicErr.write = m_eicErr.read;
813     rewind(m_eicErr.read);
814
815     return TRUE;
816 }
817
818 void CHawkApp::CloseEiCHandles()
819 {
820     CloseHandle(m_printfMutex);
821 //    fclose(m_eicOut.write);
822     fclose(m_eicErr.write);
823     remove(LPCTSTR(m_EiCErrFile));
824 }
825
826
827 int get_uweic_type(type_expr* type) 
828 {
829     struct_t* s;
830 #define _TYPE_CASE(x)   case t_##x: return sizeof(x)
831 #define _TYPE_UCASE(x)   case t_##x: case t_u##x: return sizeof(x)
832
833     switch(type->obj)
834     {
835         _TYPE_UCASE(char);
836         _TYPE_UCASE(short);
837         _TYPE_UCASE(int);
838         _TYPE_UCASE(long);
839         _TYPE_CASE(float);
840         _TYPE_CASE(double);
841
842     case t_pointer:
843         return sizeof(void*);
844
845     case t_struct:
846     case t_union:
847         s = (struct_t*)(type->u.inf);
848         return s->tsize;
849
850     case t_void:
851     case t_var:
852         return 0;
853         
854     default:
855         ASSERT(0);
856         return -1;
857     }
858
859 #undef _TYPE_UCASE
860 #undef _TYPE_CASE
861 }
862
863 BOOL CHawkApp::GenAutoWrapper(void* func, LPCTSTR func_name)
864 {
865     // Find EiC description for the function 
866     symentry_t* sym = (symentry_t*)EiC_lookup(1, const_cast<char*>(func_name));
867     if(!sym)
868     {
869 //        ASSERT(0);
870         /* Function not found */
871         return -1;
872     }
873
874     // Get the function return type string
875     CString ret = GetTypeString(sym->type->nxt);
876
877     // Generate the argument list: (type0 x0, type1 x1, etc..., typen xn)
878     CString argstr("(");
879     func_t* funcDesc = (func_t*)sym->type->u.inf;
880     parm_t* parmDesc = funcDesc->parm;
881     CString _argstr;
882     CString _argfstr;
883     for(int p = 0; p < funcDesc->Num - 1; p++)
884     {
885         type_expr* type = parmDesc[p].type;
886         if(type->obj == t_pointer && type->nxt->obj == t_funcdec)
887         {
888             /* Function contains callbacks */
889             return -2;
890         }
891          _argstr.Format("x%d", p);
892         argstr += GetTypeString(parmDesc[p].type, _argstr) /*+ " " + _argstr */ + ",";
893     }
894     if(funcDesc->Num == 1 && parmDesc[p].type->obj == t_var)
895     {
896         argstr += ")";
897     }
898     else
899     {
900         _argstr.Format("x%d", p);
901         argstr += GetTypeString(parmDesc[p].type, _argstr) /*+ " " + _argstr*/ + ")";
902     }
903
904     // Define auxiliary EiC function
905         // First, the return type and function name
906     CString str =  ret + " " + CString(func_name);
907
908         // Then, the function parameters
909     str += argstr;
910
911     // Now, the function body:
912         // First of all, generate the argi array of arguments types
913     CString argistr;
914     argistr.Format("int argi[%d] = ", funcDesc->Num + 3);
915     CString arginitstr;
916             // argi initializer
917     int* argi = new int[funcDesc->Num + 3];
918
919     argi[1] = funcDesc->Num;
920     arginitstr.Format("%d,", funcDesc->Num);
921
922     CString temp;
923     if(sym->type->nxt->obj == t_float)
924     {
925         argi[2] = EICEX_TYPE_FLOAT;
926         temp.Format("%d,", EICEX_TYPE_FLOAT);
927     }
928     else if(sym->type->nxt->obj == t_double)
929     {
930         argi[2] = EICEX_TYPE_DOUBLE;
931         temp.Format("%d,", EICEX_TYPE_DOUBLE);
932     }
933     else
934     {
935         argi[2] = get_uweic_type(sym->type->nxt);
936         temp.Format("%d,", argi[2]);
937     }
938     arginitstr += temp;
939
940     for(p = 0; p < funcDesc->Num - 1; p++)
941     {
942         argi[3 + p] = get_uweic_type(parmDesc[p].type);
943         temp.Format("%d,",argi[3 + p]);
944         arginitstr += temp;
945     }
946     argi[3 + p] = get_uweic_type(parmDesc[p].type);
947     temp.Format("%d", argi[3 + p]);
948     arginitstr += temp;
949
950     argi[0] = stack_size(argi + 1);
951     temp.Format("%d,", argi[0]);
952     arginitstr  = temp + arginitstr;
953     argistr += CString("{") + arginitstr + "};";
954     str += CString("{") + argistr;
955
956     // argi is not needed any more...
957     delete argi;
958     argi = 0;
959             // Generate the nonscalar arguments list
960
961     argistr.Format("int nslist[] = {%d", 0/*funcDesc->Num - 1*/);
962     for(p = 0; p < funcDesc->Num; p++)
963     {
964         if(parmDesc[p].type->obj == t_struct || parmDesc[p].type->obj == t_union)
965             argistr += CString(",1");
966         else
967             argistr += CString(",0");
968     }
969     argistr += CString("};");
970     str += argistr;
971
972             // Generate the function address
973     CString addrstr;
974     addrstr.Format("%d", (int)func);
975     str += "void* xr=" + addrstr + ";";
976             // Now generate the return buffer
977     if(sym->type->nxt->obj != t_void)
978     {
979         argistr.Format("(char*)%d", 1);
980         str += GetTypeString(sym->type->nxt) + " ret;";
981         str += CString("_Hawk_uniwrap(xr, argi, " + argistr + ", nslist, (void*)&ret);return ret;};");
982     }
983     else
984     {
985         argistr.Format("(char*)%d", 0);
986         str += CString("_Hawk_uniwrap(xr, argi, " + argistr + ", nslist, 0);};");
987     }
988     EiC_parseString(const_cast<char*>(LPCTSTR(str)));
989     if(EiC_ParseError)
990     {
991         ASSERT(0);
992         return FALSE;      
993     }
994 #ifndef NDEBUG
995     m_wrapperStrings.Add(str);
996 #endif
997     return TRUE;
998 }
999
1000 CString CHawkApp::GetTypeString(void* _type, const char* name)
1001 {
1002     if(!_type)
1003     {
1004         ASSERT(0);
1005         return CString("");
1006     }
1007         
1008     
1009     type_expr* type = (type_expr*)_type;
1010
1011     // Check typedef
1012     if(type->sym)
1013     {
1014         symentry_t* sym = (symentry_t*)type->sym;
1015         if(sym->sclass == c_typedef)
1016             return CString(sym->id) + " " + name;
1017     }
1018
1019 #define _TYPE_CASE(x) case t_##x: return CString(#x) + " " + name
1020 #define _TYPE_UCASE(x) case t_u##x: return CString("unsigned " #x) + " " + name;
1021     switch(type->obj)
1022     {
1023         _TYPE_CASE(void);
1024         _TYPE_CASE(char);
1025         _TYPE_UCASE(char);
1026         _TYPE_CASE(short);
1027         _TYPE_UCASE(short);
1028         _TYPE_CASE(int);
1029         _TYPE_CASE(enum);
1030         _TYPE_UCASE(int);
1031         _TYPE_CASE(long);
1032         _TYPE_UCASE(long);
1033         _TYPE_CASE(float);
1034         _TYPE_CASE(double);
1035     case t_pointer:
1036         {
1037             CString _name;
1038             int flag = 0;
1039             type_expr* t = type;
1040             while(t && t->obj != t_array) t = t->nxt;
1041             if(t)
1042             {
1043                 CString size;
1044                 size.Format("[%d]", type->u.sz);
1045                 _name = name + size;
1046                 flag = 1;
1047             }
1048             else
1049             {
1050                 _name = CString("*") + name;
1051                 if(type->nxt->obj == t_func || type->nxt->obj == t_funcdec)
1052                     _name = CString("(") + _name + ")";
1053             }
1054             return GetTypeString(type->nxt, _name) /*+ 
1055                 (type->nxt->obj == t_funcdec || flag ? CString() : CString("*"))*/;
1056         }
1057
1058     case t_struct:
1059     case t_union:
1060         {
1061             CString str = type->obj == t_struct ? CString("struct ") : CString("union ");
1062             if(type->sym)
1063             {
1064                 symentry_t* sym = (symentry_t*)type->sym;
1065                 if(sym->sclass & c_typedef)
1066                     str = CString(sym->id);
1067                 else
1068                     str += CString(sym->id);
1069                 return str + " " + name;
1070             }
1071             else
1072             {
1073                 CString ptr;
1074                 ptr.Format("struct_%d", (unsigned int)type);
1075
1076                 if(AddStructType(type))
1077                 {
1078                     str += ptr + "{";
1079                     struct_t* s = (struct_t*)type->u.inf;
1080                     for(int i = 0; i < s->n; i++)
1081                     {
1082                         str += GetTypeString(s->type[i]) + CString(";");
1083                     }
1084                     str += CString("}");
1085                     return str + " " + name;
1086                 }
1087                 else
1088                 {
1089                     str += ptr;
1090                     return str + " " + name;
1091                 }
1092             }
1093         }
1094
1095     case t_func:
1096     case t_funcdec:
1097     case t_builtin:
1098         {
1099             if(!type->nxt && !type->u.inf)
1100                 return CString("");
1101             CString str = GetTypeString(type->nxt);
1102             CString str1;
1103             str1.Format("%s ( ", name);
1104             str += str1;
1105             func_t* funcDesc = (func_t*)type->u.inf;
1106             parm_t* parmDesc = funcDesc->parm;
1107             for(int i = 0; i < funcDesc->Num - 1; i++)
1108             {
1109                 str += GetTypeString(parmDesc[i].type) + " ,";
1110             }
1111             str += GetTypeString(parmDesc[i].type) + " )";
1112             return str;
1113             
1114         }        
1115         break;
1116     case t_array:
1117         {
1118             CString str;
1119             CString ptr;
1120             ptr.Format("_%d", (int)type);
1121             CString _name = CString(name).IsEmpty() ? CString("array") + ptr : CString(name);
1122             ptr.Format("%d", type->u.sz);
1123             str = GetTypeString(type->nxt) + " " + name + "[" + ptr + "]";
1124             return str;
1125         }
1126
1127     case t_var:
1128         {
1129             return "...";
1130         }
1131     default:
1132         ASSERT(0);
1133         return CString("");
1134     }
1135 }
1136
1137 void CHawkApp::LoadModuleFunctions(LPCTSTR filename, LPCTSTR modulename)
1138 {
1139     CString str;
1140     str.Format("Attaching module %s...", filename);
1141     SetStatusString(str);
1142     
1143     CStringArray* names = new CStringArray;
1144     EnumModuleFunctions(filename, *names);
1145
1146     /* Now load all functions... */
1147     HMODULE module = LoadLibrary(filename);
1148     for(int j = 0; j < names->GetSize(); j++)
1149     {
1150         LoadModuleFunction(module, (*names)[j], TRUE);
1151     }
1152
1153     plugin_t plugin;
1154     plugin.m_handle = module;
1155     char buffer[_MAX_PATH];
1156     GetModuleFileName(module, buffer, _MAX_PATH);
1157     plugin.m_path = CString(buffer);
1158     strcpy(plugin.m_info.name, modulename);
1159     plugin.m_functions = names;
1160     plugin.m_GetFunctions = 0;
1161     plugin.m_GetInfo = 0;
1162     plugin.m_SetEiCCallback = 0;
1163     plugin.m_SetEiCStack = 0;
1164     plugin.m_SetErrLevel = 0;
1165     plugin.m_SetErrMark = 0;
1166     m_plugins.Add(plugin);
1167 }
1168
1169 BOOL CHawkApp::AddStructType(const type_expr *type)
1170 {
1171     for(int i = 0; i < m_structTypes.GetSize(); i++)
1172         if(m_structTypes.GetData()[i] == (void*)type)
1173             return FALSE;
1174
1175     m_structTypes.Add((void*)type);
1176     return TRUE;
1177 }
1178
1179 BOOL CHawkApp::Attach(string filename)
1180 {
1181     string str;
1182     str = string("#include \"") + filename + "\"";
1183     EiC_parseString(const_cast<char*>(str.c_str()));
1184     m_eicFiles.Add(CString(filename.c_str()));
1185     return TRUE;
1186 }
1187
1188 BOOL CHawkApp::EnumHeaders(LPCTSTR path)
1189 {
1190     string data = string(path) + "\\wrappers.in";
1191     ifstream headers(data.c_str());
1192     string _path(path);
1193     while(!headers.eof())
1194     {
1195         string str, full;
1196         headers >> str;
1197         full = _path + "\\" + str;
1198
1199         char _filename[_MAX_FNAME], _ext[_MAX_EXT];
1200         _splitpath(str.c_str(), 0, 0, _filename, _ext);
1201         string filename = string(_filename) + _ext;
1202         /* Found a header file or a folder. Remember it! */
1203         CFileFind finder;
1204         if(!finder.FindFile(full.c_str()))
1205         {
1206             CString str;
1207             str.Format("Cannot find %s", full.c_str());
1208             AfxMessageBox(str);
1209             continue;
1210         }
1211         finder.FindNextFile();
1212         if(finder.IsDirectory())
1213         {
1214             m_includeDirs.push_back(str);
1215         }
1216         else
1217         {
1218             m_includeFiles.push_back(filename);
1219             m_includeFilePath.push_back(full);
1220         }
1221     }
1222
1223     return TRUE;
1224 }
1225
1226 BOOL CHawkApp::EnumModuleFunctions(LPCTSTR filename, CStringArray &names)
1227 {
1228         HANDLE hFile;
1229         HANDLE hFileMapping;
1230         LPVOID lpFileBase;
1231
1232     CString errorMessage;
1233     errorMessage.Format("Failed to load the library %s", filename);
1234
1235     char buffer[_MAX_PATH];
1236     LPSTR filePart;
1237     int ret = SearchPath(0, filename, 0, _MAX_PATH, buffer, &filePart);
1238         if(!ret)
1239         {
1240         AfxMessageBox(errorMessage);
1241                 return FALSE;
1242         }
1243
1244     hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ, NULL,
1245                                                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
1246                                         
1247         if ( hFile == INVALID_HANDLE_VALUE )
1248         {
1249         AfxMessageBox(errorMessage);
1250                 return FALSE;
1251         }
1252
1253         hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
1254         if ( hFileMapping == 0 )
1255         {
1256                 CloseHandle(hFile);
1257         AfxMessageBox(errorMessage);
1258                 return FALSE;
1259         }
1260
1261         lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
1262         if ( lpFileBase == 0 )
1263         {
1264                 CloseHandle(hFileMapping);
1265                 CloseHandle(hFile);
1266         AfxMessageBox(errorMessage);
1267                 return FALSE;
1268         }
1269
1270         PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
1271         if(dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
1272     {
1273         CString errorMessage;
1274         errorMessage.Format("The file %s does not appear to be a valid dynamic link library.", buffer);
1275         AfxMessageBox(errorMessage);
1276         return FALSE;
1277     }
1278
1279 #define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (addValue) )
1280     
1281         PIMAGE_NT_HEADERS pNTHeader;
1282         DWORD base = (DWORD)dosHeader;
1283         PIMAGE_EXPORT_DIRECTORY exportDir;
1284
1285
1286         pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader,
1287                                                                 dosHeader->e_lfanew );
1288     PIMAGE_OPTIONAL_HEADER optionalHeader = &pNTHeader->OptionalHeader;
1289         exportDir = MakePtr(PIMAGE_EXPORT_DIRECTORY, base,
1290                                                  optionalHeader->DataDirectory[0].VirtualAddress);
1291     char** name = MakePtr(char**, base, exportDir->AddressOfNames);
1292
1293         for (UINT i = 0; i < exportDir->NumberOfNames; i++)
1294         {
1295         const char* str = *(name + i) + base;
1296         int isCfunc = 1;
1297         for(const char* p = str; *p != 0; p++)
1298         {
1299             char c = *p;
1300             if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9'))
1301                 continue;
1302             else
1303             {
1304                 isCfunc = 0;
1305                 break;
1306             }
1307         }
1308
1309         if(isCfunc)
1310             names.Add(str);
1311         }
1312     
1313         UnmapViewOfFile(lpFileBase);
1314         CloseHandle(hFileMapping);
1315         CloseHandle(hFile);
1316
1317     return TRUE;
1318 }
1319
1320 BOOL CHawkApp::LoadModuleFunction(HMODULE handle, LPCTSTR name, BOOL isOpenCV)
1321 {
1322     if( !strcmp(name, "cvCreateTrackbar" ) ||
1323         !strcmp(name, "cvSetMouseCallback" ) )
1324         return TRUE; //the wrapper should not be created automatically
1325                                           
1326     FARPROC addr = GetProcAddress(handle, name);
1327     if(GenAutoWrapper(addr, name) == -2)
1328     {
1329         if(!isOpenCV)
1330         {
1331             CString str;
1332             str.Format("Function %s takes a function pointer as input.\n\
1333 This function will not be available in the current Hawk session.\nRefer fo the documentation for further details",
1334                 name);
1335             AfxMessageBox(str);
1336         }
1337     }
1338     return TRUE;
1339 }
1340
1341 BOOL CHawkApp::LoadModules()
1342 {
1343     /* First of all, look for plugins that have a PLUG_ALL option */
1344     for(int i = 0; i < m_plugins.GetSize(); i++)
1345     {
1346         plugin_t& plugin = m_plugins[i];
1347         if(plugin.m_info.type == PLUG_ALL)
1348         {
1349             /* Initialize the rest of functions with universal wrappers */
1350             CStringArray all;
1351             EnumModuleFunctions(plugin.m_info.library_path, all);
1352             HMODULE module = LoadLibrary(plugin.m_info.library_path);
1353             for(int i = 0; i < all.GetSize(); i++)
1354             {
1355                 CString buf;
1356                 if(!FindStringInArray(*plugin.m_functions, all[i]))
1357                 {
1358                     LoadModuleFunction(module, all[i], TRUE);
1359                 }
1360             }
1361         }
1362     }
1363
1364     return TRUE;
1365 }
1366
1367 extern "C"
1368 {
1369 extern keyword_t cwords[];
1370 }
1371 CString CHawkApp::GenDecl(const char *name)
1372 {
1373     symentry_t* sym = EiC_lookup(1, const_cast<char*>(name));
1374     if(!sym)
1375         return CString(""); // Name not found
1376
1377     // Make sure this is not a simple keyword or typedef 
1378     if(EiC_iskeyword(cwords, const_cast<char*>(name), 36) || 
1379         (sym->sclass & c_typedef))
1380         return CString("");
1381
1382
1383     return GetTypeString(sym->type, name);
1384 }
1385
1386 CFuncDialog* CHawkApp::GetFuncDialog(int index)
1387 {
1388     return (CFuncDialog*)m_funcDialogs[index];
1389 }
1390
1391 void CHawkApp::InitPopupDialogs()
1392 {
1393     for(int i = 0; i < m_plugins.GetSize(); i++)
1394     {
1395         /* Initialize the context dialog */
1396         CFuncDialog* dlg = new CFuncDialog;
1397         dlg->SetModuleName(m_plugins.GetData()[i].m_info.name);
1398         m_funcDialogs.Add(dlg);
1399     }
1400 }