1 /**
2 * main-client.cpp
3 * This file is part of the YATE Project http://YATE.null.ro
4 *
5 * Yet Another Telephony Engine - a fully featured software PBX and IVR
6 * Copyright (C) 2004-2014 Null Team
7 *
8 * This software is distributed under multiple licenses;
9 * see the COPYING file in the main directory for licensing
10 * information for this specific distribution.
11 *
12 * This use of this software may be subject to additional restrictions.
13 * See the LEGAL file in the main directory for details.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20 #include "yatengine.h"
21
22 #include "resource.h"
23 #include <commctrl.h>
24 #include <stdio.h>
25
26 using namespace TelEngine;
27
28 class DialogWrapper
29 {
30 public:
DialogWrapper()31 inline DialogWrapper()
32 : m_wnd(0)
33 { }
34 virtual ~DialogWrapper();
35 virtual int wndFunc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp);
36 virtual int command(WORD id, LPARAM lp);
hwnd() const37 inline HWND hwnd() const
38 { return m_wnd; }
39 static bool insert(DialogWrapper* dlg, int id);
40 private:
41 HWND m_wnd;
42 };
43
44 static HMODULE s_handle = 0;
45 static HICON s_icon = 0;
46 static HWND s_main = 0;
47
48 // set the status text on bottom of the window
mainStatus(const char * stat)49 static void mainStatus(const char* stat)
50 {
51 if (s_main)
52 ::SetDlgItemText(s_main,IDC_STATUS,stat);
53 }
54
55 // recompute tabs visibility and show/hide child dialogs
tabsVisibility()56 static void tabsVisibility()
57 {
58 if (!s_main)
59 return;
60 HWND tabs = ::GetDlgItem(s_main,IDC_MAINTABS);
61 int current = TabCtrl_GetCurSel(tabs);
62 int numtabs = TabCtrl_GetItemCount(tabs);
63 for (int i=0; i<numtabs; i++) {
64 TCITEM item;
65 item.mask = TCIF_PARAM;
66 if (TabCtrl_GetItem(tabs,i,&item))
67 ::ShowWindow((HWND)item.lParam,(i == current) ? SW_SHOW : SW_HIDE);
68 }
69 }
70
innerDialog(HWND wnd,UINT msg,WPARAM wp,LPARAM lp)71 static int CALLBACK innerDialog(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
72 {
73 DialogWrapper* dlg = reinterpret_cast<DialogWrapper*>(::GetWindowLong(wnd,DWL_USER));
74 if (dlg)
75 return dlg->wndFunc(wnd,msg,wp,lp);
76 switch (msg) {
77 case WM_INITDIALOG:
78 dlg = reinterpret_cast<DialogWrapper*>(lp);
79 ::SetWindowLong(wnd,DWL_USER,(long)dlg);
80 if (dlg)
81 return dlg->wndFunc(wnd,msg,wp,lp);
82 break;
83 case WM_CLOSE:
84 DestroyWindow(wnd);
85 break;
86 default:
87 return 0;
88 }
89 return 1;
90 }
91
~DialogWrapper()92 DialogWrapper::~DialogWrapper()
93 {
94 if (m_wnd) {
95 ::SetWindowLong(m_wnd,DWL_USER,0);
96 DestroyWindow(m_wnd);
97 if (s_main) {
98 HWND tabs = ::GetDlgItem(s_main,IDC_MAINTABS);
99 int numtabs = tabs ? TabCtrl_GetItemCount(tabs) : 0;
100 for (int i=0; i<numtabs; i++) {
101 TCITEM item;
102 item.mask = TCIF_PARAM;
103 if (TabCtrl_GetItem(tabs,i,&item) && ((HWND)item.lParam == m_wnd)) {
104 BOOL current = (TabCtrl_GetCurSel(tabs) == i);
105 TabCtrl_DeleteItem(tabs,i);
106 if (current) {
107 TabCtrl_SetCurSel(tabs,0);
108 tabsVisibility();
109 }
110 }
111 }
112 }
113 }
114 }
115
wndFunc(HWND wnd,UINT msg,WPARAM wp,LPARAM lp)116 int DialogWrapper::wndFunc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
117 {
118 switch (msg) {
119 case WM_INITDIALOG:
120 m_wnd = wnd;
121 break;
122 case WM_CLOSE:
123 DestroyWindow(wnd);
124 break;
125 case WM_NCDESTROY:
126 ::SetWindowLong(wnd,DWL_USER,0);
127 m_wnd = 0;
128 delete this;
129 return 0;
130 case WM_COMMAND:
131 return command(LOWORD(wp),lp);
132 default:
133 return 0;
134 }
135 return 1;
136 }
137
command(WORD id,LPARAM lp)138 int DialogWrapper::command(WORD id, LPARAM lp)
139 {
140 #if 0
141 char buf[128];
142 sprintf(buf,"id=%u lparam=0x%08X",id,lp);
143 ::MessageBox(hwnd(),buf,"WM_COMMAND",MB_OK);
144 #endif
145 return 0;
146 }
147
148
insert(DialogWrapper * dlg,int id)149 bool DialogWrapper::insert(DialogWrapper* dlg, int id)
150 {
151 if (!(s_main && dlg && id))
152 return false;
153 HWND tabs = ::GetDlgItem(s_main,IDC_MAINTABS);
154 if (!tabs)
155 return false;
156 HWND wnd = ::CreateDialogParam(s_handle,MAKEINTRESOURCE(id),tabs,innerDialog,(LPARAM)dlg);
157 if (!wnd)
158 return false;
159
160 char buf[128];
161 ::LoadString(s_handle,id,buf,sizeof(buf));
162
163 TCITEM item;
164 item.mask = TCIF_TEXT | TCIF_PARAM;
165 item.lParam = (LPARAM)wnd;
166 item.pszText = buf;
167 TabCtrl_InsertItem(tabs,TabCtrl_GetItemCount(tabs),&item);
168
169 RECT rect;
170 ::GetClientRect(tabs,&rect);
171 TabCtrl_AdjustRect(tabs,FALSE,&rect);
172 ::MoveWindow(wnd,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,TRUE);
173 ::ShowWindow(wnd,SW_SHOW);
174 return true;
175 }
176
initMainDlg(HWND wnd)177 static void initMainDlg(HWND wnd)
178 {
179 DWORD ver = ::GetVersion();
180 if (((ver & 0xff) >= 4) || ((ver & 0xff00) >= 0x5f00)) {
181 /* set icons in the new shell */
182 ::SendMessage(wnd,WM_SETICON,ICON_BIG,(LPARAM)s_icon);
183 s_icon = (HICON)::LoadImage(s_handle,MAKEINTRESOURCE(IDI_NULLTEAM),IMAGE_ICON,16,16,0);
184 if (s_icon)
185 ::SendMessage(wnd,WM_SETICON,ICON_SMALL,(LPARAM)s_icon);
186 }
187 HMENU smenu = ::GetSystemMenu(wnd,FALSE);
188 ::DeleteMenu(smenu,SC_MAXIMIZE,MF_BYCOMMAND);
189 ::DeleteMenu(smenu,SC_SIZE,MF_BYCOMMAND);
190 s_main = wnd;
191 DialogWrapper::insert(new DialogWrapper,IDD_CALLS);
192 tabsVisibility();
193 }
194
mainDialog(HWND wnd,UINT msg,WPARAM wp,LPARAM lp)195 static int CALLBACK mainDialog(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
196 {
197 switch (msg) {
198 case WM_INITDIALOG:
199 initMainDlg(wnd);
200 break;
201 case WM_CLOSE:
202 ::EndDialog(wnd,1);
203 break;
204 case WM_QUERYDRAGICON:
205 /* in some cases this is used as application icon */
206 return (int)s_icon;
207 case WM_PAINT:
208 if (s_icon && IsIconic(wnd)) {
209 /* handle iconic draw in the old shell */
210 PAINTSTRUCT ps;
211 ::BeginPaint(wnd,&ps);
212 ::DefWindowProc(wnd,WM_ICONERASEBKGND,(WPARAM)ps.hdc,0);
213 ::DrawIcon(ps.hdc,2,2,s_icon);
214 ::EndPaint(wnd,&ps);
215 break;
216 }
217 return 0;
218 case WM_NOTIFY:
219 if ((wp == IDC_MAINTABS) && (((LPNMHDR)lp)->code == TCN_SELCHANGE))
220 tabsVisibility();
221 break;
222 default:
223 return 0;
224 }
225 return 1;
226 }
227
228 class WinClientThread : public Thread
229 {
230 public:
231 void run();
232 };
233
234 class WinClientPlugin : public Plugin
235 {
236 public:
WinClientPlugin()237 WinClientPlugin()
238 : m_thread(0)
239 { }
240 virtual void initialize(void);
isBusy() const241 virtual bool isBusy() const
242 { return true; }
243 private:
244 WinClientThread* m_thread;
245 };
246
run()247 void WinClientThread::run()
248 {
249 s_handle = ::GetModuleHandle(0);
250 s_icon = ::LoadIcon(s_handle,MAKEINTRESOURCE(IDI_NULLTEAM));
251 ::InitCommonControls();
252 int ret = ::DialogBox(s_handle,MAKEINTRESOURCE(IDD_TCLIENT),0,mainDialog);
253 s_main = 0;
254 if (s_icon)
255 ::DestroyIcon(s_icon);
256 if (ret < 0)
257 ret = 127;
258 Engine::halt(ret);
259 }
260
initialize()261 void WinClientPlugin::initialize()
262 {
263 if (!m_thread) {
264 m_thread = new WinClientThread;
265 if (m_thread->error())
266 Engine::halt(1);
267 else
268 m_thread->startup();
269 }
270 }
271
272 INIT_PLUGIN(WinClientPlugin);
273
274 // We force mainCRTStartup as entry point (from linker settings) so we get
275 // the parser called even for a GUI application
main(int argc,const char ** argv,const char ** envp)276 extern "C" int main(int argc, const char** argv, const char** envp)
277 {
278 return Engine::main(argc,argv,envp,TelEngine::Engine::Client);
279 }
280