-rw-r--r-- | T42Dlg.cpp | 1251 |
1 files changed, 1251 insertions, 0 deletions
diff --git a/T42Dlg.cpp b/T42Dlg.cpp new file mode 100644 index 0000000..8990957 --- a/dev/null +++ b/T42Dlg.cpp | |||
@@ -0,0 +1,1251 @@ | |||
1 | // T42Dlg.cpp : implementation file | ||
2 | // | ||
3 | |||
4 | #include "stdafx.h" | ||
5 | #include "T42.h" | ||
6 | #include "T42Dlg.h" | ||
7 | |||
8 | #include "T42Frame.h" | ||
9 | #include "T42AnnounceDlg.h" | ||
10 | #include "T42Document.h" | ||
11 | #include "T42Secretary.h" | ||
12 | |||
13 | #ifdef _DEBUG | ||
14 | #define new DEBUG_NEW | ||
15 | #undef THIS_FILE | ||
16 | static char THIS_FILE[] = __FILE__; | ||
17 | #endif | ||
18 | |||
19 | ///////////////////////////////////////////////////////////////////////////// | ||
20 | // CAboutDlg dialog used for App About | ||
21 | |||
22 | class CAboutDlg : public CDialog | ||
23 | { | ||
24 | public: | ||
25 | CAboutDlg(); | ||
26 | |||
27 | // Dialog Data | ||
28 | //{{AFX_DATA(CAboutDlg) | ||
29 | enum { IDD = IDD_ABOUTBOX }; | ||
30 | //}}AFX_DATA | ||
31 | |||
32 | // ClassWizard generated virtual function overrides | ||
33 | //{{AFX_VIRTUAL(CAboutDlg) | ||
34 | protected: | ||
35 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support | ||
36 | //}}AFX_VIRTUAL | ||
37 | |||
38 | // Implementation | ||
39 | protected: | ||
40 | //{{AFX_MSG(CAboutDlg) | ||
41 | afx_msg void OnKlevernet(); | ||
42 | //}}AFX_MSG | ||
43 | DECLARE_MESSAGE_MAP() | ||
44 | }; | ||
45 | |||
46 | CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) | ||
47 | { | ||
48 | //{{AFX_DATA_INIT(CAboutDlg) | ||
49 | //}}AFX_DATA_INIT | ||
50 | } | ||
51 | |||
52 | void CAboutDlg::DoDataExchange(CDataExchange* pDX) | ||
53 | { | ||
54 | CDialog::DoDataExchange(pDX); | ||
55 | //{{AFX_DATA_MAP(CAboutDlg) | ||
56 | //}}AFX_DATA_MAP | ||
57 | } | ||
58 | |||
59 | BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) | ||
60 | //{{AFX_MSG_MAP(CAboutDlg) | ||
61 | ON_BN_CLICKED(IDC_KLEVERNET, OnKlevernet) | ||
62 | //}}AFX_MSG_MAP | ||
63 | END_MESSAGE_MAP() | ||
64 | |||
65 | |||
66 | void CAboutDlg::OnKlevernet() | ||
67 | { | ||
68 | CString url; | ||
69 | VERIFY(url.LoadString(IDS_KLEVERNET_URL)); | ||
70 | ShellExecute(::GetDesktopWindow(),"open",url,NULL,NULL,SW_SHOWMAXIMIZED); | ||
71 | } | ||
72 | |||
73 | ///////////////////////////////////////////////////////////////////////////// | ||
74 | // CT42Dlg dialog | ||
75 | |||
76 | CT42Dlg::CT42Dlg(CWnd* pParent /*=NULL*/) | ||
77 | : CDialog(CT42Dlg::IDD, pParent), | ||
78 | m_sizeMin(0,0) | ||
79 | { | ||
80 | //{{AFX_DATA_INIT(CT42Dlg) | ||
81 | //}}AFX_DATA_INIT | ||
82 | // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 | ||
83 | m_hIconEmpty = m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); | ||
84 | m_hIconFull = AfxGetApp()->LoadIcon(IDI_FULLCUP); | ||
85 | m_newCalls = 0; | ||
86 | m_daemonSocket = INVALID_SOCKET; | ||
87 | m_talkLifetime = CTimeSpan(0,0,3,0);// 3 mins.. | ||
88 | m_trackTalkID = 1; | ||
89 | m_bmpBack.LoadBitmap(IDB_BACK); | ||
90 | m_bmpBack.GetBitmap(&m_bitmapBack); | ||
91 | m_bExiting = m_bShown = FALSE; | ||
92 | m_hExFW = NULL; | ||
93 | m_marginX = m_marginY = m_gapY = 0; | ||
94 | m_bAway = FALSE; | ||
95 | m_onCall = 0; | ||
96 | m_onCallAway = IDC_SECRETARY; | ||
97 | LoadSettings(); | ||
98 | } | ||
99 | |||
100 | CT42Dlg::~CT42Dlg() | ||
101 | { | ||
102 | SaveSettings(); | ||
103 | } | ||
104 | |||
105 | void CT42Dlg::DoDataExchange(CDataExchange* pDX) | ||
106 | { | ||
107 | CDialog::DoDataExchange(pDX); | ||
108 | //{{AFX_DATA_MAP(CT42Dlg) | ||
109 | DDX_Control(pDX, IDOK, m_ExitCtl); | ||
110 | DDX_Control(pDX, IDC_TALK, m_TeaCtl); | ||
111 | DDX_Control(pDX, IDC_AWAY, m_AwayCtl); | ||
112 | DDX_Control(pDX, ID_HELP, m_HelpCtl); | ||
113 | DDX_Control(pDX, IDC_OPTIONS, m_OptionsCtl); | ||
114 | DDX_Control(pDX, IDC_ONCALLAWAY, m_OnCallAwayCtl); | ||
115 | DDX_Control(pDX, IDC_ONCALL, m_OnCallCtl); | ||
116 | DDX_Control(pDX, IDC_CALLS, m_CallsCtl); | ||
117 | DDX_Control(pDX, IDC_PREVIEW, m_PreviewCtl); | ||
118 | //}}AFX_DATA_MAP | ||
119 | if(pDX->m_bSaveAndValidate){ | ||
120 | m_onCall = GetOnCtl(m_OnCallCtl); | ||
121 | m_onCallAway = GetOnCtl(m_OnCallAwayCtl); | ||
122 | }else{ | ||
123 | SetOnCtl(m_onCall,m_OnCallCtl); | ||
124 | SetOnCtl(m_onCallAway,m_OnCallAwayCtl); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | BEGIN_MESSAGE_MAP(CT42Dlg, CDialog) | ||
129 | //{{AFX_MSG_MAP(CT42Dlg) | ||
130 | ON_WM_SYSCOMMAND() | ||
131 | ON_WM_DESTROY() | ||
132 | ON_WM_PAINT() | ||
133 | ON_WM_QUERYDRAGICON() | ||
134 | ON_BN_CLICKED(IDC_TALK, OnTalk) | ||
135 | ON_MESSAGE(WM_DAEMON, OnDaemon) | ||
136 | ON_WM_CREATE() | ||
137 | ON_MESSAGE(WM_TRAYICON, OnTrayIcon) | ||
138 | ON_WM_WINDOWPOSCHANGING() | ||
139 | ON_COMMAND(ID_TRAY_EXIT, OnTrayExit) | ||
140 | ON_COMMAND(ID_TRAY_OPTIONS, OnTrayOptions) | ||
141 | ON_COMMAND(ID_TRAY_SHOWMAINWINDOW, OnTrayShowmainwindow) | ||
142 | ON_COMMAND(ID_TRAY_T42, OnTrayT42) | ||
143 | ON_BN_CLICKED(IDC_OPTIONS, OnOptions) | ||
144 | ON_NOTIFY(LVN_GETDISPINFO, IDC_CALLS, OnGetdispinfoCalls) | ||
145 | ON_NOTIFY(LVN_ITEMCHANGED, IDC_CALLS, OnItemchangedCalls) | ||
146 | ON_NOTIFY(NM_RCLICK, IDC_CALLS, OnRclickCalls) | ||
147 | ON_COMMAND(ID_CALLLOG_CALLBACK, OnCalllogCallback) | ||
148 | ON_COMMAND(ID_CALLLOG_DELETE, OnCalllogDelete) | ||
149 | ON_COMMAND(ID_CALLLOG_SAVETOFILE, OnCalllogSavetofile) | ||
150 | ON_COMMAND(ID_CALLLOG_EMPTYLOG, OnCalllogEmptylog) | ||
151 | ON_NOTIFY(LVN_DELETEITEM, IDC_CALLS, OnDeleteitemCalls) | ||
152 | ON_MESSAGE(WM_UPDATEPREVIEW, OnUpdatePreview) | ||
153 | ON_NOTIFY(LVN_KEYDOWN, IDC_CALLS, OnKeydownCalls) | ||
154 | ON_WM_SHOWWINDOW() | ||
155 | ON_COMMAND(ID_CALLLOG_MARKASNEW, OnCalllogMarkasnew) | ||
156 | ON_COMMAND(ID_CALLLOG_MARKASPROCESSED, OnCalllogMarkasprocessed) | ||
157 | ON_WM_SIZE() | ||
158 | ON_WM_GETMINMAXINFO() | ||
159 | ON_BN_CLICKED(IDC_AWAY, OnAway) | ||
160 | ON_CBN_SELENDOK(IDC_ONCALL, OnSelendokOncall) | ||
161 | ON_CBN_SELENDOK(IDC_ONCALLAWAY, OnSelendokOncallaway) | ||
162 | ON_COMMAND(ID_TRAY_AWAY, OnTrayAway) | ||
163 | ON_WM_TIMER() | ||
164 | ON_WM_QUERYENDSESSION() | ||
165 | //}}AFX_MSG_MAP | ||
166 | END_MESSAGE_MAP() | ||
167 | |||
168 | ///////////////////////////////////////////////////////////////////////////// | ||
169 | // CT42Dlg message handlers | ||
170 | |||
171 | BOOL CT42Dlg::OnInitDialog() | ||
172 | { | ||
173 | CDialog::OnInitDialog(); | ||
174 | |||
175 | // Add "About..." menu item to system menu. | ||
176 | |||
177 | // IDM_ABOUTBOX must be in the system command range. | ||
178 | ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); | ||
179 | ASSERT(IDM_ABOUTBOX < 0xF000); | ||
180 | |||
181 | CMenu* pSysMenu = GetSystemMenu(FALSE); | ||
182 | CString strAboutMenu; | ||
183 | strAboutMenu.LoadString(IDS_ABOUTBOX); | ||
184 | if (!strAboutMenu.IsEmpty()) | ||
185 | { | ||
186 | pSysMenu->AppendMenu(MF_SEPARATOR); | ||
187 | pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); | ||
188 | } | ||
189 | |||
190 | // Set the icon for this dialog. The framework does this automatically | ||
191 | // when the application's main window is not a dialog | ||
192 | SetIcon(m_hIcon, TRUE); // Set big icon | ||
193 | SetIcon(m_hIcon, FALSE); // Set small icon | ||
194 | |||
195 | CT42App* app = (CT42App*)AfxGetApp(); | ||
196 | { | ||
197 | int x = -1,y = -1,cx = -1,cy = -1; | ||
198 | x = app->GetProfileInt("T42MainWindow","X",x); | ||
199 | y = app->GetProfileInt("T42MainWindow","Y",y); | ||
200 | cx = app->GetProfileInt("T42MainWindow","Width",cx); | ||
201 | cy = app->GetProfileInt("T42MainWindow","Height",cy); | ||
202 | if(cx>0 && cy>0) | ||
203 | SetWindowPos(NULL,x,y,cx,cy,SWP_NOACTIVATE|SWP_NOZORDER); | ||
204 | } | ||
205 | |||
206 | ::SetForegroundWindow(m_hExFW); | ||
207 | |||
208 | m_PreviewCtl.ModifyStyle(0,WS_VSCROLL); | ||
209 | m_PreviewCtl.SetOptions(ECOOP_SET,ECO_AUTOWORDSELECTION| | ||
210 | ECO_AUTOVSCROLL|ECO_AUTOHSCROLL|ECO_READONLY|ECO_SELECTIONBAR); | ||
211 | m_PreviewCtl.SetReadOnly(TRUE); | ||
212 | m_PreviewCtl.SetTargetDevice(NULL,0); | ||
213 | m_PreviewCtl.SetBackgroundColor(FALSE,((CT42App*)AfxGetApp())->m_crT42RemoteBG); | ||
214 | |||
215 | m_CallsCtl.SetBkColor(RGB(0,192,0)); | ||
216 | m_CallsCtl.SetTextColor(RGB(255,255,0)); | ||
217 | m_CallsCtl.SetTextBkColor(RGB(0,192,0)); | ||
218 | m_Images.Create(16,16,TRUE,2,1); | ||
219 | m_iNew = m_Images.Add(AfxGetApp()->LoadIcon(IDI_T42CALLNEW)); | ||
220 | m_iProcessed = m_Images.Add(AfxGetApp()->LoadIcon(IDI_T42CALLPROCESSED)); | ||
221 | ASSERT( m_iNew>=0 && m_iProcessed>=0); | ||
222 | m_CallsCtl.SetImageList(&m_Images,LVSIL_NORMAL); | ||
223 | m_CallsCtl.SetImageList(&m_Images,LVSIL_SMALL); | ||
224 | m_CallsCtl.SetImageList(&m_Images,LVSIL_STATE); | ||
225 | InitCalls(); | ||
226 | |||
227 | CRect wrci, wrco; | ||
228 | GetWindowRect(&wrco); | ||
229 | GetClientRect(&wrci); | ||
230 | // Pull out margins | ||
231 | CRect crc; | ||
232 | m_CallsCtl.GetWindowRect(crc); ScreenToClient(crc); | ||
233 | m_marginX = crc.left; | ||
234 | CRect trc; | ||
235 | m_TeaCtl.GetWindowRect(trc); ScreenToClient(trc); | ||
236 | m_marginY = trc.top; | ||
237 | CRect prc; | ||
238 | m_PreviewCtl.GetWindowRect(prc); ScreenToClient(prc); | ||
239 | m_gapY = prc.top-crc.bottom; | ||
240 | |||
241 | RecalcLayout(); | ||
242 | SetColumnWidths(); | ||
243 | |||
244 | // Calc minimum size | ||
245 | CRect arc; | ||
246 | m_AwayCtl.GetWindowRect(arc); ScreenToClient(arc); | ||
247 | m_sizeMin.cx = arc.right+m_marginX*2+trc.Width()+wrco.Width()-wrci.Width(); | ||
248 | m_sizeMin.cy = crc.top+m_marginY+m_gapY+40*2+wrco.Height()-wrci.Height(); | ||
249 | |||
250 | SetTimer(timerMinutes,60000,NULL); | ||
251 | |||
252 | m_daemonSocket = socket(AF_INET,SOCK_DGRAM,0); | ||
253 | if(m_daemonSocket == INVALID_SOCKET){ | ||
254 | TRACE0("Failed to initialize daemon\n"); | ||
255 | return TRUE; | ||
256 | } | ||
257 | sockaddr_in da; | ||
258 | da.sin_family = AF_INET; | ||
259 | da.sin_port = htons(app->m_T42TalkPort); | ||
260 | da.sin_addr.s_addr = INADDR_ANY; | ||
261 | if(bind(m_daemonSocket,(sockaddr*)&da,sizeof(da))){ | ||
262 | AfxMessageBox(IDS_DAEMON_FAIL,MB_OK|MB_ICONSTOP); | ||
263 | TRACE0("Failed to bind daemon socket\n"); | ||
264 | return TRUE; | ||
265 | } | ||
266 | if(WSAAsyncSelect(m_daemonSocket,m_hWnd,WM_DAEMON,FD_READ)){ | ||
267 | AfxMessageBox(IDS_DAEMON_FAIL,MB_OK|MB_ICONSTOP); | ||
268 | TRACE0("AsyncSelect failed on daemon socket\n"); | ||
269 | return TRUE; | ||
270 | } | ||
271 | |||
272 | return TRUE; // return TRUE unless you set the focus to a control | ||
273 | } | ||
274 | |||
275 | void CT42Dlg::OnSysCommand(UINT nID, LPARAM lParam) | ||
276 | { | ||
277 | if ((nID & 0xFFF0) == IDM_ABOUTBOX){ | ||
278 | CAboutDlg dlgAbout; | ||
279 | dlgAbout.DoModal(); | ||
280 | }else{ | ||
281 | if(nID==SC_SCREENSAVE){ | ||
282 | TRACE0("SCRS\n"); | ||
283 | }else if(nID==SC_MONITORPOWER){ | ||
284 | TRACE0("MP\n"); | ||
285 | }else | ||
286 | TRACE1("SYSCOM: 0x%04X\n",nID); | ||
287 | CDialog::OnSysCommand(nID, lParam); | ||
288 | } | ||
289 | } | ||
290 | |||
291 | void CT42Dlg::OnDestroy() | ||
292 | { | ||
293 | CT42App* app = (CT42App*)AfxGetApp(); | ||
294 | CDocTemplate* pTemplate = app->m_pTemplate; | ||
295 | pTemplate->CloseAllDocuments(FALSE); | ||
296 | CRect rc; | ||
297 | GetWindowRect(rc); | ||
298 | app->WriteProfileInt("T42MainWindow","X",rc.left); | ||
299 | app->WriteProfileInt("T42MainWindow","Y",rc.top); | ||
300 | app->WriteProfileInt("T42MainWindow","Width",rc.Width()); | ||
301 | app->WriteProfileInt("T42MainWindow","Height",rc.Height()); | ||
302 | |||
303 | NOTIFYICONDATA nid; | ||
304 | memset(&nid,0,sizeof(nid)); | ||
305 | nid.cbSize=sizeof(nid); | ||
306 | nid.hWnd=m_hWnd; | ||
307 | nid.uID=IDC_TRAYICON; | ||
308 | nid.uFlags=0; | ||
309 | VERIFY(Shell_NotifyIcon(NIM_DELETE,&nid)); | ||
310 | |||
311 | WinHelp(0L, HELP_QUIT); | ||
312 | CDialog::OnDestroy(); | ||
313 | } | ||
314 | |||
315 | // If you add a minimize button to your dialog, you will need the code below | ||
316 | // to draw the icon. For MFC applications using the document/view model, | ||
317 | // this is automatically done for you by the framework. | ||
318 | |||
319 | void CT42Dlg::OnPaint() | ||
320 | { | ||
321 | if (IsIconic()) | ||
322 | { | ||
323 | CPaintDC dc(this); // device context for painting | ||
324 | |||
325 | SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); | ||
326 | |||
327 | // Center icon in client rectangle | ||
328 | int cxIcon = GetSystemMetrics(SM_CXICON); | ||
329 | int cyIcon = GetSystemMetrics(SM_CYICON); | ||
330 | CRect rect; | ||
331 | GetClientRect(&rect); | ||
332 | int x = (rect.Width() - cxIcon + 1) / 2; | ||
333 | int y = (rect.Height() - cyIcon + 1) / 2; | ||
334 | |||
335 | // Draw the icon | ||
336 | dc.DrawIcon(x, y, m_hIcon); | ||
337 | } | ||
338 | else | ||
339 | { | ||
340 | CPaintDC pDC(this); | ||
341 | CDC bmpDC; | ||
342 | bmpDC.CreateCompatibleDC(&pDC); | ||
343 | bmpDC.SelectObject(&m_bmpBack); | ||
344 | CRect rc; | ||
345 | GetClientRect(&rc); | ||
346 | for(int x=-m_bitmapBack.bmWidth*2/4;x<rc.Width();x+=m_bitmapBack.bmWidth) | ||
347 | for(int y=-m_bitmapBack.bmHeight*2/4;y<rc.Height();y+=m_bitmapBack.bmHeight) | ||
348 | pDC.BitBlt(x,y,m_bitmapBack.bmWidth,m_bitmapBack.bmHeight,&bmpDC,0,0,SRCCOPY); | ||
349 | bmpDC.DeleteDC(); | ||
350 | CDialog::OnPaint(); | ||
351 | } | ||
352 | } | ||
353 | |||
354 | // The system calls this to obtain the cursor to display while the user drags | ||
355 | // the minimized window. | ||
356 | HCURSOR CT42Dlg::OnQueryDragIcon() | ||
357 | { | ||
358 | return (HCURSOR) m_hIcon; | ||
359 | } | ||
360 | |||
361 | void CT42Dlg::OnTalk() | ||
362 | { | ||
363 | CDocTemplate* pTemplate = ((CT42App*)AfxGetApp())->m_pTemplate; | ||
364 | T42Document* pDoc = (T42Document*)pTemplate->OpenDocumentFile(NULL); | ||
365 | ASSERT_KINDOF(T42Document,pDoc); | ||
366 | pDoc->Talk(); | ||
367 | } | ||
368 | |||
369 | LRESULT CT42Dlg::OnDaemon(WPARAM wP,LPARAM lP) | ||
370 | { | ||
371 | if(WSAGETSELECTERROR(lP)){ | ||
372 | TRACE1("Error on daemon socket: %ld\n", WSAGETSELECTERROR(lP)); | ||
373 | return -1; | ||
374 | } | ||
375 | ASSERT(WSAGETSELECTEVENT(lP)&FD_READ); | ||
376 | TalkCtlMessage rq; | ||
377 | if(recv(m_daemonSocket,(char*)&rq,sizeof(rq),0)!=sizeof(rq)){ | ||
378 | TRACE("Bad packet size on daemon socket\n"); | ||
379 | return -1; | ||
380 | } | ||
381 | TalkCtlResponse rp; | ||
382 | TRACE3("*DAEMON-REQUEST*\nV: %d, T: %d, ID: %ld\n", | ||
383 | (int)rq.m_Version, (int)rq.m_Type, ntohl(rq.m_ID) | ||
384 | ); | ||
385 | TRACE2("ADDR: %s:%d\n", | ||
386 | inet_ntoa(((sockaddr_in*)&rq.m_Addr)->sin_addr), | ||
387 | ntohs(((sockaddr_in*)&rq.m_Addr)->sin_port) | ||
388 | ); | ||
389 | TRACE2("CTL ADDR: %s:%d\n", | ||
390 | inet_ntoa(((sockaddr_in*)&rq.m_ctlAddr)->sin_addr), | ||
391 | ntohs(((sockaddr_in*)&rq.m_ctlAddr)->sin_port) | ||
392 | ); | ||
393 | TRACE3("PID: %ld, LU: %s, RU: %s\n", | ||
394 | rq.m_PID,rq.m_LName,rq.m_RName | ||
395 | ); | ||
396 | TRACE1("TTY: %s\n---\n",rq.m_RTTY); | ||
397 | |||
398 | rp.m_Version = talkCtlVersion; | ||
399 | rp.m_Type = rq.m_Type; | ||
400 | rp.m_ID = htonl(0); | ||
401 | rp.m_Answer = talkCtlReserved; | ||
402 | sockaddr_in a; | ||
403 | memmove(&a,&rq.m_ctlAddr,sizeof(a)); | ||
404 | a.sin_family = ntohs(a.sin_family); | ||
405 | do{ | ||
406 | if(rq.m_Version!=talkCtlVersion){ | ||
407 | rp.m_Answer = talkCtlBadVersion; | ||
408 | break; | ||
409 | } | ||
410 | if(rq.m_Addr.sa_family!=htons(AF_INET)){ | ||
411 | rp.m_Answer = talkCtlBadAddr; | ||
412 | break; | ||
413 | } | ||
414 | if(rq.m_ctlAddr.sa_family!=htons(AF_INET)){ | ||
415 | rp.m_Answer = talkCtlBadCtlAddr; | ||
416 | break; | ||
417 | } | ||
418 | switch(rq.m_Type){ | ||
419 | case talkCtlReqAnnounce: | ||
420 | { | ||
421 | CTime ct = CTime::GetCurrentTime(); | ||
422 | POSITION p = m_talks.GetHeadPosition(); | ||
423 | BOOL bFound = FALSE; | ||
424 | while(p){ | ||
425 | POSITION dp = p; | ||
426 | CTTable& t = m_talks.GetNext(p); | ||
427 | if((ct-t.m_Time)>m_talkLifetime){ | ||
428 | TRACE0("Removing Expired request\n"); | ||
429 | m_talks.RemoveAt(dp); | ||
430 | }else if(t==rq){ | ||
431 | t.m_Time = ct; | ||
432 | rp.m_ID = t.m_RQ.m_ID; | ||
433 | bFound = TRUE; | ||
434 | break; | ||
435 | } | ||
436 | } | ||
437 | if(bFound){ | ||
438 | // ** handle re-announces | ||
439 | rp.m_Answer = talkCtlSuccess; | ||
440 | break; | ||
441 | } | ||
442 | UINT nAction = m_bAway?m_onCallAway:m_onCall; | ||
443 | T42AnnounceDlg ad(rq); | ||
444 | CT42App* app = (CT42App*)AfxGetApp(); | ||
445 | if( | ||
446 | nAction==IDC_SECRETARY | ||
447 | && app->m_T42SWinLimit | ||
448 | && app->m_T42LinesBusy>=app->m_T42SWinLimit | ||
449 | ) | ||
450 | nAction = IDC_NOTHERE;// ?? | ||
451 | if(nAction!=IDC_SECRETARY && nAction!=IDC_NOTHERE | ||
452 | && nAction!=IDC_REFUSE && nAction!=IDCANCEL | ||
453 | ){ | ||
454 | CTTable t; | ||
455 | memmove(&t.m_RQ,&rq,sizeof(t.m_RQ)); | ||
456 | t.m_Time = ct; | ||
457 | t.m_RQ.m_ID = rp.m_ID = htonl(m_trackTalkID++); | ||
458 | m_talks.AddHead(t); | ||
459 | rp.m_Answer = talkCtlSuccess; | ||
460 | if(sendto(m_daemonSocket,(char*)&rp,sizeof(rp),0,(sockaddr*)&a,sizeof(a))!=sizeof(rp)){ | ||
461 | TRACE0("Failed to send daemon response\n"); | ||
462 | return -1; | ||
463 | } | ||
464 | HWND hFW = ::GetForegroundWindow(); | ||
465 | nAction = ad.DoModal(); | ||
466 | ::SetForegroundWindow(hFW); | ||
467 | }else{ | ||
468 | if(nAction==IDC_NOTHERE || nAction==IDC_REFUSE){ | ||
469 | rp.m_Answer=(nAction==IDC_NOTHERE)?talkCtlNotHere:talkCtlPermissionDenied; | ||
470 | break; | ||
471 | } | ||
472 | CTTable t; | ||
473 | memmove(&t.m_RQ,&rq,sizeof(t.m_RQ)); | ||
474 | t.m_Time = ct; | ||
475 | t.m_RQ.m_ID = rp.m_ID = htonl(m_trackTalkID++); | ||
476 | m_talks.AddHead(t); | ||
477 | rp.m_Answer = talkCtlSuccess; | ||
478 | if(sendto(m_daemonSocket,(char*)&rp,sizeof(rp),0,(sockaddr*)&a,sizeof(a))!=sizeof(rp)){ | ||
479 | TRACE0("Failed to send daemon response\n"); | ||
480 | return -1; | ||
481 | } | ||
482 | } | ||
483 | rp.m_Answer=talkCtlReserved; | ||
484 | switch(nAction){ | ||
485 | case IDOK: | ||
486 | { | ||
487 | CDocTemplate* pTemplate = ((CT42App*)AfxGetApp())->m_pTemplate; | ||
488 | T42Document* pDoc = (T42Document*)pTemplate->OpenDocumentFile(NULL); | ||
489 | ASSERT_KINDOF(T42Document,pDoc); | ||
490 | pDoc->Talk(ad.m_Callee,ad.m_ipCaller,NULL); | ||
491 | } | ||
492 | break; | ||
493 | case IDC_SECRETARY: | ||
494 | { | ||
495 | HWND hFW = ::GetForegroundWindow(); | ||
496 | CDocTemplate* pTemplate = ((CT42App*)AfxGetApp())->m_pTemplate; | ||
497 | T42Document* pDoc = (T42Document*)pTemplate->OpenDocumentFile("hidden"); | ||
498 | ASSERT_KINDOF(T42Document,pDoc); | ||
499 | pDoc->AttachRobot(new CT42Secretary); | ||
500 | pDoc->Talk(ad.m_Callee,ad.m_ipCaller,NULL); | ||
501 | ::SetForegroundWindow(hFW); | ||
502 | } | ||
503 | break; | ||
504 | case IDCANCEL: | ||
505 | break; | ||
506 | } | ||
507 | } | ||
508 | break; | ||
509 | case talkCtlReqLeaveInvite: | ||
510 | { | ||
511 | CTime ct = CTime::GetCurrentTime(); | ||
512 | POSITION p = m_talks.GetHeadPosition(); | ||
513 | while(p){ | ||
514 | POSITION dp = p; | ||
515 | CTTable& t = m_talks.GetNext(p); | ||
516 | if((ct-t.m_Time)>m_talkLifetime){ | ||
517 | TRACE0("Removing Expired request\n"); | ||
518 | m_talks.RemoveAt(dp); | ||
519 | }else if(t==rq){ | ||
520 | t.m_Time = ct; | ||
521 | rp.m_ID = rq.m_ID; | ||
522 | rp.m_Answer = talkCtlSuccess; | ||
523 | break; | ||
524 | } | ||
525 | } | ||
526 | if(rp.m_Answer!=talkCtlSuccess){ | ||
527 | CTTable t; | ||
528 | memmove(&t.m_RQ,&rq,sizeof(t.m_RQ)); | ||
529 | t.m_Time = ct; | ||
530 | t.m_RQ.m_ID = rp.m_ID = htonl(m_trackTalkID++); | ||
531 | m_talks.AddHead(t); | ||
532 | rp.m_Answer = talkCtlSuccess; | ||
533 | } | ||
534 | } | ||
535 | break; | ||
536 | case talkCtlReqLookUp: | ||
537 | { | ||
538 | CTime ct = CTime::GetCurrentTime(); | ||
539 | POSITION p = m_talks.GetHeadPosition(); | ||
540 | while(p){ | ||
541 | POSITION dp = p; | ||
542 | CTTable& t = m_talks.GetNext(p); | ||
543 | if((ct-t.m_Time)>m_talkLifetime){ | ||
544 | TRACE0("Removing Expired request\n"); | ||
545 | m_talks.RemoveAt(dp); | ||
546 | }else if(t.Match(rq)){ | ||
547 | rp.m_ID = t.m_RQ.m_ID; | ||
548 | memmove(&rp.m_Addr,&t.m_RQ.m_Addr,sizeof(rp.m_Addr)); | ||
549 | rp.m_Answer = talkCtlSuccess; | ||
550 | break; | ||
551 | } | ||
552 | } | ||
553 | if(rp.m_Answer!=talkCtlSuccess) | ||
554 | rp.m_Answer = talkCtlNotHere; | ||
555 | } | ||
556 | break; | ||
557 | case talkCtlReqDelete: | ||
558 | { | ||
559 | CTime ct = CTime::GetCurrentTime(); | ||
560 | POSITION p = m_talks.GetHeadPosition(); | ||
561 | while(p){ | ||
562 | POSITION dp = p; | ||
563 | CTTable& t = m_talks.GetNext(p); | ||
564 | if((ct-t.m_Time)>m_talkLifetime){ | ||
565 | TRACE0("Removing Expired request\n"); | ||
566 | m_talks.RemoveAt(dp); | ||
567 | }else if(t.m_RQ.m_ID == rq.m_ID){ | ||
568 | m_talks.RemoveAt(dp); | ||
569 | rp.m_Answer=talkCtlSuccess; | ||
570 | break; | ||
571 | } | ||
572 | } | ||
573 | if(rp.m_Answer!=talkCtlSuccess) | ||
574 | rp.m_Answer = talkCtlNotHere; | ||
575 | break; | ||
576 | } | ||
577 | break; | ||
578 | default: | ||
579 | TRACE0("Unknown request type\n"); | ||
580 | rp.m_Answer=talkCtlUnknownRequest; | ||
581 | break; | ||
582 | } | ||
583 | }while(FALSE); | ||
584 | if(rp.m_Answer==talkCtlReserved || rp.m_Answer==talkCtlBadCtlAddr) | ||
585 | return -1; | ||
586 | if(sendto(m_daemonSocket,(char*)&rp,sizeof(rp),0,(sockaddr*)&a,sizeof(a))!=sizeof(rp)){ | ||
587 | TRACE0("Failed to send daemon response\n"); | ||
588 | return -1; | ||
589 | } | ||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | int CT42Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct) | ||
594 | { | ||
595 | if (CDialog::OnCreate(lpCreateStruct) == -1) | ||
596 | return -1; | ||
597 | CRichEditCtrl tmp; | ||
598 | tmp.Create(WS_CHILD,CRect(0,0,0,0),this,0); | ||
599 | |||
600 | NOTIFYICONDATA nid; | ||
601 | memset(&nid,0,sizeof(nid)); | ||
602 | nid.cbSize = sizeof(nid); | ||
603 | nid.hWnd = m_hWnd; | ||
604 | nid.uID = IDC_TRAYICON; | ||
605 | nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; | ||
606 | nid.uCallbackMessage=WM_TRAYICON; | ||
607 | nid.hIcon = m_hIcon; | ||
608 | // *** | ||
609 | strcpy(nid.szTip,"Tea For Two"); | ||
610 | VERIFY(Shell_NotifyIcon(NIM_ADD,&nid)); | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | LRESULT CT42Dlg::OnTrayIcon(WPARAM wP,LPARAM lP) | ||
616 | { | ||
617 | ASSERT(wP==IDC_TRAYICON); | ||
618 | switch(lP){ | ||
619 | case WM_LBUTTONDOWN: | ||
620 | ToggleVisibility(); | ||
621 | break; | ||
622 | case WM_RBUTTONDOWN: | ||
623 | { | ||
624 | CMenu popups; | ||
625 | VERIFY(popups.LoadMenu(IDM_POPUPS)); | ||
626 | CMenu* popUp = popups.GetSubMenu(0); | ||
627 | ASSERT(popUp); | ||
628 | CPoint pt; | ||
629 | VERIFY(::GetCursorPos(&pt)); | ||
630 | SetForegroundWindow(); | ||
631 | popUp->CheckMenuItem(ID_TRAY_SHOWMAINWINDOW,MF_BYCOMMAND|(IsWindowVisible()?MF_CHECKED:MF_UNCHECKED)); | ||
632 | popUp->CheckMenuItem(ID_TRAY_AWAY,MF_BYCOMMAND|(m_bAway?MF_CHECKED:MF_UNCHECKED)); | ||
633 | popUp->TrackPopupMenu(TPM_RIGHTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, | ||
634 | pt.x,pt.y,this); | ||
635 | SendMessage(WM_NULL); | ||
636 | } | ||
637 | break; | ||
638 | } | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | void CT42Dlg::ToggleVisibility() | ||
643 | { | ||
644 | if(IsWindowVisible()){ | ||
645 | m_bShown=FALSE; | ||
646 | ShowWindow(SW_HIDE); | ||
647 | CWnd* pWnd = GetNextWindow(); | ||
648 | if(pWnd){ | ||
649 | pWnd->SetForegroundWindow(); | ||
650 | pWnd->SetFocus(); | ||
651 | } | ||
652 | }else{ | ||
653 | m_bShown=TRUE; | ||
654 | ShowWindow(SW_SHOW); | ||
655 | SetForegroundWindow(); | ||
656 | SetFocus(); | ||
657 | } | ||
658 | } | ||
659 | |||
660 | void CT42Dlg::OnCancel() | ||
661 | { | ||
662 | ToggleVisibility(); | ||
663 | } | ||
664 | |||
665 | |||
666 | void CT42Dlg::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) | ||
667 | { | ||
668 | CDialog::OnWindowPosChanging(lpwndpos); | ||
669 | |||
670 | if(m_bExiting) | ||
671 | return; | ||
672 | if(m_bShown){ | ||
673 | lpwndpos->flags&=~SWP_HIDEWINDOW; | ||
674 | lpwndpos->flags|=SWP_SHOWWINDOW; | ||
675 | }else{ | ||
676 | lpwndpos->flags&=~SWP_SHOWWINDOW; | ||
677 | lpwndpos->flags|=SWP_HIDEWINDOW; | ||
678 | } | ||
679 | } | ||
680 | |||
681 | void CT42Dlg::OnOK() | ||
682 | { | ||
683 | m_bExiting = TRUE; | ||
684 | CDialog::OnOK(); | ||
685 | } | ||
686 | |||
687 | void CT42Dlg::OnTrayExit() | ||
688 | { | ||
689 | OnOK(); | ||
690 | } | ||
691 | |||
692 | void CT42Dlg::OnTrayOptions() | ||
693 | { | ||
694 | OnOptions(); | ||
695 | } | ||
696 | |||
697 | void CT42Dlg::OnTrayShowmainwindow() | ||
698 | { | ||
699 | ToggleVisibility(); | ||
700 | } | ||
701 | |||
702 | void CT42Dlg::OnTrayT42() | ||
703 | { | ||
704 | OnTalk(); | ||
705 | } | ||
706 | |||
707 | void CT42Dlg::OnOptions() | ||
708 | { | ||
709 | CT42App* app = (CT42App*)AfxGetApp(); | ||
710 | app->Options(this); | ||
711 | } | ||
712 | |||
713 | void CT42Dlg::InitCalls() | ||
714 | { | ||
715 | CT42App* app = (CT42App*)AfxGetApp(); | ||
716 | m_CallsCtl.InsertColumn(0,"Time",LVCFMT_LEFT,-1,subitemTime); | ||
717 | m_CallsCtl.InsertColumn(1,"Caller",LVCFMT_LEFT,-1,subitemCaller); | ||
718 | m_CallsCtl.InsertColumn(2,"Callee",LVCFMT_LEFT,-1,subitemCallee); | ||
719 | LONG calls = app->GetT42Calls(); | ||
720 | if(calls>0){ | ||
721 | m_CallsCtl.SetItemCount(calls); | ||
722 | for(LONG tmp=0;tmp<calls;tmp++){ | ||
723 | m_CallsCtl.InsertItem( | ||
724 | LVIF_TEXT, | ||
725 | tmp, | ||
726 | LPSTR_TEXTCALLBACK, | ||
727 | 0,0,// state,statemask | ||
728 | I_IMAGECALLBACK, | ||
729 | 0 // lParam | ||
730 | ); | ||
731 | } | ||
732 | } | ||
733 | SetColumnWidths(); | ||
734 | } | ||
735 | |||
736 | void CT42Dlg::OnGetdispinfoCalls(NMHDR* pNMHDR, LRESULT* pResult) | ||
737 | { | ||
738 | CT42App* app = (CT42App*)AfxGetApp(); | ||
739 | LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; | ||
740 | int iItem = pDispInfo->item.iItem; | ||
741 | CT42CallLogEntry entry; | ||
742 | VERIFY(app->GetT42Call(iItem,entry)); | ||
743 | CString tmp; | ||
744 | switch(pDispInfo->item.iSubItem){ | ||
745 | case subitemTime: | ||
746 | tmp = entry.m_Time.Format(IDS_FORMAT_CALLTIME); | ||
747 | if(entry.m_Status==CT42CallLogEntry::statusProcessed) | ||
748 | pDispInfo->item.iImage = m_iProcessed; | ||
749 | else | ||
750 | pDispInfo->item.iImage = m_iNew; | ||
751 | break; | ||
752 | case subitemCaller: | ||
753 | tmp = entry.m_Caller; | ||
754 | break; | ||
755 | case subitemCallee: | ||
756 | tmp = entry.m_Callee; | ||
757 | break; | ||
758 | default: | ||
759 | ASSERT(FALSE); | ||
760 | break; | ||
761 | } | ||
762 | if(tmp.GetLength()>=pDispInfo->item.cchTextMax) | ||
763 | tmp = tmp.Left(pDispInfo->item.cchTextMax-4)+".."; | ||
764 | strcpy(pDispInfo->item.pszText,tmp); | ||
765 | pDispInfo->item.mask|=LVIF_IMAGE; | ||
766 | pDispInfo->item.mask|=LVIF_TEXT; | ||
767 | |||
768 | *pResult = 0; | ||
769 | } | ||
770 | |||
771 | void CT42Dlg::OnAddT42Call() | ||
772 | { | ||
773 | m_CallsCtl.InsertItem( | ||
774 | LVIF_TEXT, | ||
775 | m_CallsCtl.GetItemCount(), | ||
776 | LPSTR_TEXTCALLBACK, | ||
777 | 0,0,// state,statemask | ||
778 | I_IMAGECALLBACK, | ||
779 | 0 // lParam | ||
780 | ); | ||
781 | m_CallsCtl.RedrawItems(0,m_CallsCtl.GetItemCount()); | ||
782 | m_CallsCtl.Invalidate(); | ||
783 | PostMessage(WM_UPDATEPREVIEW,(WPARAM)-1); | ||
784 | if(!IsWindowVisible()){ | ||
785 | m_newCalls++; | ||
786 | SetTheIcon(m_hIconFull); | ||
787 | } | ||
788 | } | ||
789 | |||
790 | void CT42Dlg::OnDelT42Call() | ||
791 | { | ||
792 | m_CallsCtl.DeleteItem( | ||
793 | m_CallsCtl.GetItemCount()-1 | ||
794 | ); | ||
795 | m_CallsCtl.RedrawItems(0,m_CallsCtl.GetItemCount()); | ||
796 | m_CallsCtl.Invalidate(); | ||
797 | PostMessage(WM_UPDATEPREVIEW,(WPARAM)-1); | ||
798 | } | ||
799 | |||
800 | void CT42Dlg::SetColumnWidths() | ||
801 | { | ||
802 | CTime ct = CTime::GetCurrentTime(); | ||
803 | CString t = ct.Format(IDS_FORMAT_CALLTIME); | ||
804 | CRect rc; | ||
805 | m_CallsCtl.GetClientRect(rc); | ||
806 | INT tw = m_CallsCtl.GetStringWidth(t)+40; | ||
807 | INT cew = m_CallsCtl.GetStringWidth("wwwwwwww"); | ||
808 | INT crw = rc.Width()-(tw+cew); | ||
809 | m_CallsCtl.SetColumnWidth(subitemTime,tw); | ||
810 | m_CallsCtl.SetColumnWidth(subitemCaller,crw); | ||
811 | m_CallsCtl.SetColumnWidth(subitemCallee,cew); | ||
812 | } | ||
813 | |||
814 | void CT42Dlg::OnItemchangedCalls(NMHDR* pNMHDR, LRESULT* pResult) | ||
815 | { | ||
816 | NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; | ||
817 | |||
818 | if( | ||
819 | pNMListView->uChanged&LVIF_STATE | ||
820 | && pNMListView->uNewState&LVIS_FOCUSED | ||
821 | && !(pNMListView->uOldState&LVIS_FOCUSED) | ||
822 | ){ | ||
823 | PostMessage(WM_UPDATEPREVIEW,pNMListView->iItem); | ||
824 | } | ||
825 | *pResult = 0; | ||
826 | } | ||
827 | |||
828 | DWORD CALLBACK CT42Dlg::ESOUTProc(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG FAR *pcb) | ||
829 | { | ||
830 | CString* str = (CString*)dwCookie; | ||
831 | if(cb>str->GetLength()) | ||
832 | cb = str->GetLength(); | ||
833 | if(!cb){ | ||
834 | (*pcb)=0; | ||
835 | return 0; | ||
836 | } | ||
837 | memmove(pbBuff,(LPCTSTR)*str,cb); | ||
838 | (*str) = str->Mid(cb); | ||
839 | (*pcb)=cb; | ||
840 | return 0; | ||
841 | } | ||
842 | |||
843 | void CT42Dlg::OnRclickCalls(NMHDR* pNMHDR, LRESULT* pResult) | ||
844 | { | ||
845 | CPoint pt; | ||
846 | VERIFY(GetCursorPos(&pt)); | ||
847 | CMenu popups; | ||
848 | VERIFY(popups.LoadMenu(IDM_POPUPS)); | ||
849 | CMenu* popup = popups.GetSubMenu(1); | ||
850 | ASSERT(popup); | ||
851 | BOOL bYes = ( | ||
852 | m_CallsCtl.GetNextItem(-1,LVNI_ALL|LVNI_FOCUSED)>=0 | ||
853 | || m_CallsCtl.GetNextItem(-1,LVNI_ALL|LVNI_SELECTED)>=0 | ||
854 | ); | ||
855 | popup->EnableMenuItem(ID_CALLLOG_CALLBACK,MF_BYCOMMAND|( | ||
856 | bYes?MF_ENABLED:MF_GRAYED | ||
857 | )); | ||
858 | popup->EnableMenuItem(ID_CALLLOG_DELETE,MF_BYCOMMAND|( | ||
859 | bYes?MF_ENABLED:MF_GRAYED | ||
860 | )); | ||
861 | popup->EnableMenuItem(ID_CALLLOG_SAVETOFILE,MF_BYCOMMAND|( | ||
862 | bYes?MF_ENABLED:MF_GRAYED | ||
863 | )); | ||
864 | popup->EnableMenuItem(ID_CALLLOG_MARKASNEW,MF_BYCOMMAND|( | ||
865 | bYes?MF_ENABLED:MF_GRAYED | ||
866 | )); | ||
867 | popup->EnableMenuItem(ID_CALLLOG_MARKASPROCESSED,MF_BYCOMMAND|( | ||
868 | bYes?MF_ENABLED:MF_GRAYED | ||
869 | )); | ||
870 | popup->EnableMenuItem(ID_CALLLOG_EMPTYLOG,MF_BYCOMMAND|( | ||
871 | (m_CallsCtl.GetItemCount())?MF_ENABLED:MF_GRAYED | ||
872 | )); | ||
873 | popup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_LEFTBUTTON, | ||
874 | pt.x,pt.y,this); | ||
875 | *pResult = 0; | ||
876 | } | ||
877 | |||
878 | void CT42Dlg::OnCalllogCallback() | ||
879 | { | ||
880 | int item = m_CallsCtl.GetNextItem(-1,LVNI_ALL|LVNI_FOCUSED); | ||
881 | if(item<0) | ||
882 | return; | ||
883 | CT42App* app = (CT42App*)AfxGetApp(); | ||
884 | CT42CallLogEntry entry; | ||
885 | VERIFY(app->GetT42Call(item,entry)); | ||
886 | CDocTemplate* pTemplate = app->m_pTemplate; | ||
887 | T42Document* pDoc = (T42Document*)pTemplate->OpenDocumentFile(NULL); | ||
888 | ASSERT_KINDOF(T42Document,pDoc); | ||
889 | pDoc->Talk(entry.m_Callee,entry.m_Caller,NULL); | ||
890 | entry.m_Status=CT42CallLogEntry::statusProcessed; | ||
891 | VERIFY(app->UpdateT42Call(entry)); | ||
892 | m_CallsCtl.Update(item); | ||
893 | } | ||
894 | |||
895 | void CT42Dlg::OnCalllogDelete() | ||
896 | { | ||
897 | CT42App* app = (CT42App*)AfxGetApp(); | ||
898 | int ii = m_CallsCtl.GetItemCount(); | ||
899 | if(ii<=0) | ||
900 | return; | ||
901 | Klever::CBitSet bs(ii); | ||
902 | for(int i=0;i<ii;i++) | ||
903 | if(m_CallsCtl.GetItemState(i,LVIS_FOCUSED|LVIS_SELECTED)) | ||
904 | bs.BitSet(i); | ||
905 | for(i = (ii-1);i>=0;i--){ | ||
906 | if(!bs.IsSet(i)) | ||
907 | continue; | ||
908 | CT42CallLogEntry entry; | ||
909 | VERIFY(app->GetT42Call(i,entry)); | ||
910 | VERIFY(app->DelT42Call(entry.m_Time)); | ||
911 | } | ||
912 | } | ||
913 | |||
914 | void CT42Dlg::OnCalllogSavetofile() | ||
915 | { | ||
916 | CT42App* app = (CT42App*)AfxGetApp(); | ||
917 | CT42CallLogEntry entry; | ||
918 | CString filter; | ||
919 | VERIFY(filter.LoadString(IDS_FILTER_RTF)); | ||
920 | CFileDialog fd(FALSE,".rtf",NULL, | ||
921 | OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_EXPLORER| | ||
922 | OFN_LONGNAMES|OFN_NOREADONLYRETURN|OFN_PATHMUSTEXIST, | ||
923 | filter,this | ||
924 | ); | ||
925 | if(fd.DoModal()==IDOK){ | ||
926 | int ii = m_CallsCtl.GetItemCount(); | ||
927 | if(ii<=0) | ||
928 | return; | ||
929 | Klever::CBitSet bs(ii); | ||
930 | for(int i=0;i<ii;i++) | ||
931 | if(m_CallsCtl.GetItemState(i,LVIS_FOCUSED|LVIS_SELECTED)) | ||
932 | bs.BitSet(i); | ||
933 | try{ | ||
934 | CStdioFile f(fd.GetPathName(), | ||
935 | CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite| | ||
936 | CFile::typeText); | ||
937 | f.WriteString("{\\rtf1\\ansi\n"); | ||
938 | for(i = (ii-1);i>=0;i--){ | ||
939 | if(!bs.IsSet(i)) | ||
940 | continue; | ||
941 | CT42CallLogEntry entry; | ||
942 | VERIFY(app->GetT42Call(i,entry)); | ||
943 | CString tmp; | ||
944 | tmp.Format(IDS_FORMAT_T42CALLHEADER, | ||
945 | entry.m_Time.Format(IDS_FORMAT_CALLTIMELONG), | ||
946 | entry.m_Caller, entry.m_Callee, | ||
947 | entry.m_Duration.Format(IDS_FORMAT_CALLDURATION) | ||
948 | ); | ||
949 | f.WriteString(tmp); | ||
950 | f.WriteString(entry.m_Message); | ||
951 | } | ||
952 | f.WriteString("\n}\n"); | ||
953 | }catch(CException* e){ | ||
954 | TRACE0("Save exc\n"); | ||
955 | e->Delete(); | ||
956 | } | ||
957 | } | ||
958 | } | ||
959 | |||
960 | void CT42Dlg::OnCalllogEmptylog() | ||
961 | { | ||
962 | CT42App* app = (CT42App*)AfxGetApp(); | ||
963 | int ii = m_CallsCtl.GetItemCount(); | ||
964 | if(ii<=0) | ||
965 | return; | ||
966 | for(int i = (ii-1);i>=0;i--){ | ||
967 | CT42CallLogEntry entry; | ||
968 | VERIFY(app->GetT42Call(i,entry)); | ||
969 | VERIFY(app->DelT42Call(entry.m_Time)); | ||
970 | } | ||
971 | } | ||
972 | |||
973 | void CT42Dlg::OnDeleteitemCalls(NMHDR* pNMHDR, LRESULT* pResult) | ||
974 | { | ||
975 | NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; | ||
976 | PostMessage(WM_UPDATEPREVIEW,(WPARAM)-1); | ||
977 | *pResult = 0; | ||
978 | } | ||
979 | |||
980 | LRESULT CT42Dlg::OnUpdatePreview(WPARAM wP,LPARAM) | ||
981 | { | ||
982 | int iItem = (int)wP; | ||
983 | if(iItem<0) | ||
984 | iItem = m_CallsCtl.GetNextItem(-1,LVNI_ALL|LVNI_FOCUSED); | ||
985 | CT42App* app = (CT42App*)AfxGetApp(); | ||
986 | CT42CallLogEntry entry; | ||
987 | if(iItem<0 ||!app->GetT42Call(iItem,entry)){ | ||
988 | m_PreviewCtl.SetWindowText(""); | ||
989 | return 0; | ||
990 | } | ||
991 | EDITSTREAM es; | ||
992 | memset(&es,0,sizeof(es)); | ||
993 | es.dwCookie = (DWORD)&entry.m_Message; | ||
994 | es.pfnCallback = ESOUTProc; | ||
995 | m_PreviewCtl.StreamIn(SF_RTF,es); | ||
996 | return 0; | ||
997 | } | ||
998 | |||
999 | void CT42Dlg::OnKeydownCalls(NMHDR* pNMHDR, LRESULT* pResult) | ||
1000 | { | ||
1001 | LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR; | ||
1002 | |||
1003 | switch(pLVKeyDow->wVKey){ | ||
1004 | case 'R': | ||
1005 | if(GetKeyState(VK_CONTROL)&0x8000) | ||
1006 | OnCalllogCallback(); | ||
1007 | break; | ||
1008 | case VK_DELETE: | ||
1009 | OnCalllogDelete(); | ||
1010 | break; | ||
1011 | case 'D': | ||
1012 | if(GetKeyState(VK_CONTROL)&0x8000) | ||
1013 | OnCalllogDelete(); | ||
1014 | break; | ||
1015 | } | ||
1016 | *pResult = 0; | ||
1017 | } | ||
1018 | |||
1019 | BOOL CT42Dlg::PreCreateWindow(CREATESTRUCT& cs) | ||
1020 | { | ||
1021 | m_hExFW = ::GetForegroundWindow(); | ||
1022 | return CDialog::PreCreateWindow(cs); | ||
1023 | } | ||
1024 | |||
1025 | void CT42Dlg::SetTheIcon(HICON hIcon) | ||
1026 | { | ||
1027 | m_hIcon = hIcon; | ||
1028 | SetIcon(m_hIcon, TRUE); // Set big icon | ||
1029 | SetIcon(m_hIcon, FALSE); // Set small icon | ||
1030 | NOTIFYICONDATA nid; | ||
1031 | memset(&nid,0,sizeof(nid)); | ||
1032 | nid.cbSize = sizeof(nid); | ||
1033 | nid.hWnd = m_hWnd; | ||
1034 | nid.uID = IDC_TRAYICON; | ||
1035 | nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; | ||
1036 | nid.uCallbackMessage=WM_TRAYICON; | ||
1037 | nid.hIcon = hIcon; | ||
1038 | if(m_newCalls) | ||
1039 | _snprintf(nid.szTip,sizeof(nid.szTip)-1,"%d new calls waiting",m_newCalls); | ||
1040 | else | ||
1041 | strcpy(nid.szTip,"Tea For Two"); | ||
1042 | VERIFY(Shell_NotifyIcon(NIM_MODIFY,&nid)); | ||
1043 | } | ||
1044 | |||
1045 | void CT42Dlg::OnShowWindow(BOOL bShow, UINT nStatus) | ||
1046 | { | ||
1047 | CDialog::OnShowWindow(bShow, nStatus); | ||
1048 | if(bShow){ | ||
1049 | m_newCalls=0; | ||
1050 | SetTheIcon(m_hIconEmpty); | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | void CT42Dlg::OnCalllogMarkasnew() | ||
1055 | { | ||
1056 | CT42App* app = (CT42App*)AfxGetApp(); | ||
1057 | int ii = m_CallsCtl.GetItemCount(); | ||
1058 | if(ii<=0) | ||
1059 | return; | ||
1060 | Klever::CBitSet bs(ii); | ||
1061 | for(int i=0;i<ii;i++) | ||
1062 | if(m_CallsCtl.GetItemState(i,LVIS_FOCUSED|LVIS_SELECTED)) | ||
1063 | bs.BitSet(i); | ||
1064 | int f = -1,t = -1; | ||
1065 | for(i = 0;i<ii;i++){ | ||
1066 | if(!bs.IsSet(i)) | ||
1067 | continue; | ||
1068 | CT42CallLogEntry entry; | ||
1069 | VERIFY(app->GetT42Call(i,entry)); | ||
1070 | if(entry.m_Status==CT42CallLogEntry::statusProcessed){ | ||
1071 | entry.m_Status=CT42CallLogEntry::statusOk; | ||
1072 | VERIFY(app->UpdateT42Call(entry)); | ||
1073 | if(f<0) | ||
1074 | f=i; | ||
1075 | if(t<i) | ||
1076 | t=i; | ||
1077 | } | ||
1078 | } | ||
1079 | if(f<0 || t<0) | ||
1080 | return; | ||
1081 | m_CallsCtl.RedrawItems(f,t); | ||
1082 | m_CallsCtl.Invalidate(); | ||
1083 | } | ||
1084 | |||
1085 | void CT42Dlg::OnCalllogMarkasprocessed() | ||
1086 | { | ||
1087 | CT42App* app = (CT42App*)AfxGetApp(); | ||
1088 | int ii = m_CallsCtl.GetItemCount(); | ||
1089 | if(ii<=0) | ||
1090 | return; | ||
1091 | Klever::CBitSet bs(ii); | ||
1092 | for(int i=0;i<ii;i++) | ||
1093 | if(m_CallsCtl.GetItemState(i,LVIS_FOCUSED|LVIS_SELECTED)) | ||
1094 | bs.BitSet(i); | ||
1095 | int f = -1,t = -1; | ||
1096 | for(i = 0;i<ii;i++){ | ||
1097 | if(!bs.IsSet(i)) | ||
1098 | continue; | ||
1099 | CT42CallLogEntry entry; | ||
1100 | VERIFY(app->GetT42Call(i,entry)); | ||
1101 | if(entry.m_Status!=CT42CallLogEntry::statusProcessed){ | ||
1102 | entry.m_Status=CT42CallLogEntry::statusProcessed; | ||
1103 | VERIFY(app->UpdateT42Call(entry)); | ||
1104 | if(f<0) | ||
1105 | f=i; | ||
1106 | if(t<i) | ||
1107 | t=i; | ||
1108 | } | ||
1109 | } | ||
1110 | if(f<0 || t<0) | ||
1111 | return; | ||
1112 | m_CallsCtl.RedrawItems(f,t); | ||
1113 | m_CallsCtl.Invalidate(); | ||
1114 | } | ||
1115 | |||
1116 | void CT42Dlg::RecalcLayout() | ||
1117 | { | ||
1118 | CRect crc; | ||
1119 | GetClientRect(&crc); | ||
1120 | CRect rcCalls; | ||
1121 | m_CallsCtl.GetWindowRect(&rcCalls); | ||
1122 | ScreenToClient(rcCalls); | ||
1123 | // Calculate windows height. | ||
1124 | UINT wHeight = (crc.Height()-rcCalls.top-m_marginY-m_gapY)/2; | ||
1125 | UINT wWidth = crc.Width()-(2*m_marginX); | ||
1126 | // Position windows | ||
1127 | m_CallsCtl.SetWindowPos( | ||
1128 | NULL, | ||
1129 | m_marginX,rcCalls.top-crc.top, wWidth,wHeight, | ||
1130 | SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER | ||
1131 | ); | ||
1132 | m_PreviewCtl.SetWindowPos( | ||
1133 | NULL, | ||
1134 | m_marginX,rcCalls.top-crc.top+wHeight+m_gapY, wWidth,wHeight, | ||
1135 | SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER | ||
1136 | ); | ||
1137 | |||
1138 | CRect brc; | ||
1139 | m_TeaCtl.GetWindowRect(brc); ScreenToClient(brc); | ||
1140 | UINT bX = crc.Width()-m_marginX-brc.Width(); | ||
1141 | m_TeaCtl.SetWindowPos(NULL,bX,brc.top, 0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS); | ||
1142 | m_OptionsCtl.GetWindowRect(brc); ScreenToClient(brc); | ||
1143 | m_OptionsCtl.SetWindowPos(NULL,bX,brc.top,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS); | ||
1144 | m_ExitCtl.GetWindowRect(brc); ScreenToClient(brc); | ||
1145 | m_ExitCtl.SetWindowPos(NULL,bX,brc.top,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS); | ||
1146 | m_HelpCtl.GetWindowRect(brc); ScreenToClient(brc); | ||
1147 | m_HelpCtl.SetWindowPos(NULL,bX,brc.top,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS); | ||
1148 | } | ||
1149 | |||
1150 | void CT42Dlg::OnSize(UINT nType, int cx, int cy) | ||
1151 | { | ||
1152 | CDialog::OnSize(nType, cx, cy); | ||
1153 | |||
1154 | if(m_marginX && m_marginY && m_gapY){ | ||
1155 | RecalcLayout(); | ||
1156 | SetColumnWidths(); | ||
1157 | } | ||
1158 | |||
1159 | } | ||
1160 | |||
1161 | void CT42Dlg::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) | ||
1162 | { | ||
1163 | if(m_sizeMin.cx && m_sizeMin.cy){ | ||
1164 | lpMMI->ptMinTrackSize.x = m_sizeMin.cx; | ||
1165 | lpMMI->ptMinTrackSize.y = m_sizeMin.cy; | ||
1166 | } | ||
1167 | |||
1168 | CDialog::OnGetMinMaxInfo(lpMMI); | ||
1169 | } | ||
1170 | |||
1171 | void CT42Dlg::SetOnCtl(UINT nAction,CComboBox& ctl) | ||
1172 | { | ||
1173 | int n = 0; | ||
1174 | switch(nAction){ | ||
1175 | case IDC_SECRETARY: n = 1; break; | ||
1176 | case IDC_NOTHERE: n = 2; break; | ||
1177 | case IDC_REFUSE: n = 3; break; | ||
1178 | case IDCANCEL: n = 4; break; | ||
1179 | } | ||
1180 | ctl.SetCurSel(n); | ||
1181 | } | ||
1182 | |||
1183 | UINT CT42Dlg::GetOnCtl(CComboBox& ctl) | ||
1184 | { | ||
1185 | switch(ctl.GetCurSel()){ | ||
1186 | case 1: return IDC_SECRETARY; | ||
1187 | case 2: return IDC_NOTHERE; | ||
1188 | case 3: return IDC_REFUSE; | ||
1189 | case 4: return IDCANCEL; | ||
1190 | } | ||
1191 | return 0; | ||
1192 | } | ||
1193 | |||
1194 | void CT42Dlg::OnAway() | ||
1195 | { | ||
1196 | m_bAway = m_AwayCtl.GetCheck(); | ||
1197 | } | ||
1198 | void CT42Dlg::OnSelendokOncall() | ||
1199 | { | ||
1200 | m_onCall = GetOnCtl(m_OnCallCtl); | ||
1201 | } | ||
1202 | void CT42Dlg::OnSelendokOncallaway() | ||
1203 | { | ||
1204 | m_onCallAway = GetOnCtl(m_OnCallAwayCtl); | ||
1205 | } | ||
1206 | |||
1207 | void CT42Dlg::LoadSettings() | ||
1208 | { | ||
1209 | CT42App* app = (CT42App*)AfxGetApp(); | ||
1210 | m_onCall = app->GetProfileInt("Settings","T42OnCall",m_onCall); | ||
1211 | m_onCallAway = app->GetProfileInt("Settings","T42OnCallAway",m_onCallAway); | ||
1212 | } | ||
1213 | |||
1214 | void CT42Dlg::SaveSettings() | ||
1215 | { | ||
1216 | CT42App* app = (CT42App*)AfxGetApp(); | ||
1217 | app->WriteProfileInt("Settings","T42OnCall",m_onCall); | ||
1218 | app->WriteProfileInt("Settings","T42OnCallAway",m_onCallAway); | ||
1219 | } | ||
1220 | |||
1221 | void CT42Dlg::OnTrayAway() | ||
1222 | { | ||
1223 | m_AwayCtl.SetCheck((m_bAway=!m_bAway)?1:0); | ||
1224 | } | ||
1225 | |||
1226 | void CT42Dlg::OnTimer(UINT nIDEvent) | ||
1227 | { | ||
1228 | if(nIDEvent==timerMinutes){ | ||
1229 | KillTimer(timerMinutes); | ||
1230 | CDocTemplate* pTemplate = ((CT42App*)AfxGetApp())->m_pTemplate; | ||
1231 | POSITION p = pTemplate->GetFirstDocPosition(); | ||
1232 | while(p){ | ||
1233 | T42Document* pDoc = (T42Document*)pTemplate->GetNextDoc(p); | ||
1234 | pDoc->OnMinute(); | ||
1235 | } | ||
1236 | SetTimer(timerMinutes,60000,NULL); | ||
1237 | } | ||
1238 | |||
1239 | CDialog::OnTimer(nIDEvent); | ||
1240 | } | ||
1241 | |||
1242 | BOOL CT42Dlg::OnQueryEndSession() | ||
1243 | { | ||
1244 | if (!CDialog::OnQueryEndSession()) | ||
1245 | return FALSE; | ||
1246 | |||
1247 | CT42App* app = (CT42App*)AfxGetApp(); | ||
1248 | app->SaveSettings(); | ||
1249 | |||
1250 | return TRUE; | ||
1251 | } | ||